1
4
5
6
7
74
75
79
80# include "luametatex.h"
81
82
83
84
85
86
87# define hlist_usage ((lua_Integer) 1 << (hlist_node + 1))
88# define vlist_usage ((lua_Integer) 1 << (vlist_node + 1))
89# define rule_usage ((lua_Integer) 1 << (rule_node + 1))
90# define insert_usage ((lua_Integer) 1 << (insert_node + 1))
91# define mark_usage ((lua_Integer) 1 << (mark_node + 1))
92# define adjust_usage ((lua_Integer) 1 << (adjust_node + 1))
93# define boundary_usage ((lua_Integer) 1 << (boundary_node + 1))
94# define disc_usage ((lua_Integer) 1 << (disc_node + 1))
95# define whatsit_usage ((lua_Integer) 1 << (whatsit_node + 1))
96# define par_usage ((lua_Integer) 1 << (par_node + 1))
97# define dir_usage ((lua_Integer) 1 << (dir_node + 1))
98# define math_usage ((lua_Integer) 1 << (math_node + 1))
99# define glue_usage ((lua_Integer) 1 << (glue_node + 1))
100# define kern_usage ((lua_Integer) 1 << (kern_node + 1))
101# define penalty_usage ((lua_Integer) 1 << (penalty_node + 1))
102# define style_usage ((lua_Integer) 1 << (style_node + 1))
103# define choice_usage ((lua_Integer) 1 << (choice_node + 1))
104# define parameter_usage ((lua_Integer) 1 << (parameter_node + 1))
105# define simple_usage ((lua_Integer) 1 << (simple_noad + 1))
106# define radical_usage ((lua_Integer) 1 << (radical_noad + 1))
107# define fraction_usage ((lua_Integer) 1 << (fraction_noad + 1))
108# define accent_usage ((lua_Integer) 1 << (accent_noad + 1))
109# define fence_usage ((lua_Integer) 1 << (fence_noad + 1))
110# define math_char_usage ((lua_Integer) 1 << (math_char_node + 1))
111# define math_text_char_usage ((lua_Integer) 1 << (math_text_char_node + 1))
112# define sub_box_usage ((lua_Integer) 1 << (sub_box_node + 1))
113# define sub_mlist_usage ((lua_Integer) 1 << (sub_mlist_node + 1))
114# define delimiter_usage ((lua_Integer) 1 << (delimiter_node + 1))
115# define glyph_usage ((lua_Integer) 1 << (glyph_node + 1))
116# define unset_usage ((lua_Integer) 1 << (unset_node + 1))
117# define align_record_usage ((lua_Integer) 1 << (align_record_node + 1))
118# define attribute_usage ((lua_Integer) 1 << (attribute_node + 1))
119# define glue_spec_usage ((lua_Integer) 1 << (glue_spec_node + 1))
120
121# define common_usage ((lua_Integer) 1 << (last_nodetype + 2))
122# define generic_usage ((lua_Integer) 1 << (last_nodetype + 3))
123
124# define no_usage ((lua_Integer) 0)
125
126
136
137halfword lmt_check_isdirect(lua_State *L, int i)
138{
139 halfword n = lmt_tohalfword(L, i);
140 return n && _valid_node_(n) ? n : null;
141}
142
143static inline halfword nodelib_valid_direct_from_index(lua_State *L, int i)
144{
145 halfword n = lmt_tohalfword(L, i);
146 return n && _valid_node_(n) ? n : null;
147}
148
149static inline void nodelib_push_direct_or_nil(lua_State *L, halfword n)
150{
151 if (n) {
152 lua_pushinteger(L, n);
153 } else {
154 lua_pushnil(L);
155 }
156}
157
158static inline void nodelib_push_direct_or_nil_node_prev(lua_State *L, halfword n)
159{
160 if (n) {
161 node_prev(n) = null;
162 lua_pushinteger(L, n);
163 } else {
164 lua_pushnil(L);
165 }
166}
167
168static inline void nodelib_push_node_on_top(lua_State *L, halfword n)
169{
170 *(halfword *) lua_newuserdatauv(L, sizeof(halfword), 0) = n;
171 lua_getmetatable(L, -2);
172 lua_setmetatable(L, -2);
173}
174
175
181
182static halfword lmt_maybe_isnode(lua_State *L, int i)
183{
184 halfword *p = lua_touserdata(L, i);
185 halfword n = null;
186 if (p && lua_getmetatable(L, i)) {
187 lua_get_metatablelua(node_instance);
188 if (lua_rawequal(L, -1, -2)) {
189 n = *p;
190 }
191 lua_pop(L, 2);
192 }
193 return n;
194}
195
196halfword lmt_check_isnode(lua_State *L, int i)
197{
198 halfword n = lmt_maybe_isnode(L, i);
199 if (! n) {
200
201 luaL_error(L, "invalid node");
202 }
203 return n;
204}
205
206halfword lmt_optional_isnode(lua_State *L, int i)
207{
208 return lmt_maybe_isnode(L, i);
209}
210
211
212
213
214static void nodelib_push_direct_or_node(lua_State *L, int direct, halfword n)
215{
216 if (n) {
217 if (direct) {
218 lua_pushinteger(L, n);
219 } else {
220 *(halfword *) lua_newuserdatauv(L, sizeof(halfword), 0) = n;
221 lua_getmetatable(L, 1);
222 lua_setmetatable(L, -2);
223 }
224 } else {
225 lua_pushnil(L);
226 }
227}
228
229static void nodelib_push_direct_or_node_node_prev(lua_State *L, int direct, halfword n)
230{
231 if (n) {
232 node_prev(n) = null;
233 if (direct) {
234 lua_pushinteger(L, n);
235 } else {
236 *(halfword *) lua_newuserdatauv(L, sizeof(halfword), 0) = n;
237 lua_getmetatable(L, 1);
238 lua_setmetatable(L, -2);
239 }
240 } else {
241 lua_pushnil(L);
242 }
243}
244
245static halfword nodelib_direct_or_node_from_index(lua_State *L, int direct, int i)
246{
247 if (direct) {
248 return nodelib_valid_direct_from_index(L, i);
249 } else if (lua_isuserdata(L, i)) {
250 return lmt_check_isnode(L, i);
251 } else {
252 return null;
253 }
254}
255
256halfword lmt_check_isdirectornode(lua_State *L, int i, int *isdirect)
257{
258 *isdirect = ! lua_isuserdata(L, i);
259 return *isdirect ? nodelib_valid_direct_from_index(L, i) : lmt_check_isnode(L, i);
260}
261
262static void nodelib_push_attribute_data(lua_State *L, halfword n)
263{
264 if (node_subtype(n) == attribute_list_subtype) {
265 lua_newtable(L);
266 n = node_next(n);
267 while (n) {
268 lua_pushinteger(L, attribute_value(n));
269 lua_rawseti(L, -2, attribute_index(n));
270 n = node_next(n);
271 }
272 } else {
273 lua_pushnil(L);
274 }
275}
276
277
278
279# define isloop_usage common_usage
280
281static int nodelib_direct_isloop(lua_State *L)
282{
283 halfword head = nodelib_valid_direct_from_index(L, 1);
284 if (head) {
285 halfword slow = head;
286 halfword fast = head;
287 while (slow && fast && node_next(fast)) {
288 slow = node_next(slow);
289 fast = node_next(node_next(fast));
290 if (slow == fast) {
291 lua_pushboolean(L, 1);
292 return 1;
293 }
294 }
295 }
296 lua_pushboolean(L, 0);
297 return 0;
298}
299
300
301
302static inline singleword nodelib_getdirection(lua_State *L, int i)
303{
304 return ((lua_type(L, i) == LUA_TNUMBER) ? (singleword) checked_direction_value(lmt_tohalfword(L, i)) : direction_def_value);
305}
306
307
313
314static quarterword nodelib_aux_get_node_type_id_from_name(lua_State *L, int n, node_info *data, int all)
315{
316 if (data) {
317 const char *s = lua_tostring(L, n);
318 for (int j = 0; data[j].id != -1; j++) {
319 if (s == data[j].name) {
320 if (all || data[j].visible) {
321 return (quarterword) j;
322 } else {
323 break;
324 }
325 }
326 }
327 }
328 return unknown_node;
329}
330
331static quarterword nodelib_aux_get_node_subtype_id_from_name(lua_State *L, int n, value_info *data)
332{
333 if (data) {
334 const char *s = lua_tostring(L, n);
335 for (quarterword j = 0; data[j].id != -1; j++) {
336 if (s == data[j].name) {
337 return j;
338 }
339 }
340 }
341 return unknown_subtype;
342}
343
344static quarterword nodelib_aux_get_field_index_from_name(lua_State *L, int n, value_info *data)
345{
346 if (data) {
347 const char *s = lua_tostring(L, n);
348 for (quarterword j = 0; data[j].name; j++) {
349 if (s == data[j].name) {
350 return j;
351 }
352 }
353 }
354 return unknown_field;
355}
356
357static quarterword nodelib_aux_get_valid_node_type_id(lua_State *L, int n)
358{
359 quarterword i = unknown_node;
360 switch (lua_type(L, n)) {
361 case LUA_TSTRING:
362 i = nodelib_aux_get_node_type_id_from_name(L, n, lmt_interface.node_data, 0);
363 if (i == unknown_node) {
364 luaL_error(L, "invalid node type id: %s", lua_tostring(L, n));
365 }
366 break;
367 case LUA_TNUMBER:
368 i = lmt_toquarterword(L, n);
369 if (! tex_nodetype_is_visible(i)) {
370 luaL_error(L, "invalid node type id: %d", i);
371 }
372 break;
373 default:
374 luaL_error(L, "invalid node type id");
375 }
376 return i;
377}
378
379int lmt_get_math_style(lua_State *L, int n, int dflt)
380{
381 int i = -1;
382 switch (lua_type(L, n)) {
383 case LUA_TNUMBER:
384 i = lmt_tointeger(L, n);
385 break;
386 case LUA_TSTRING:
387 i = nodelib_aux_get_field_index_from_name(L, n, lmt_interface.math_style_values);
388 break;
389 }
390 if (i >= 0 && i <= cramped_script_script_style) {
391 return i;
392 } else {
393 return dflt;
394 }
395}
396
397int lmt_get_math_parameter(lua_State *L, int n, int dflt)
398{
399 int i;
400 switch (lua_type(L, n)) {
401 case LUA_TNUMBER:
402 i = lmt_tointeger(L, n);
403 break;
404 case LUA_TSTRING:
405 i = nodelib_aux_get_field_index_from_name(L, n, lmt_interface.math_parameter_values);
406 break;
407 default:
408 i = -1;
409 break;
410 }
411 if (i >= 0 && i < math_parameter_last) {
412 return i;
413 } else {
414 return dflt;
415 }
416}
417
418
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444void lmt_push_node(lua_State *L)
445{
446 halfword n = null;
447 if (lua_type(L, -1) == LUA_TNUMBER) {
448 n = lmt_tohalfword(L, -1);
449 }
450 lua_pop(L, 1);
451 if (n && n <= lmt_node_memory_state.nodes_data.allocated) {
452 halfword *a = lua_newuserdatauv(L, sizeof(halfword), 0);
453 *a = n;
454 lua_get_metatablelua(node_instance);
455 lua_setmetatable(L, -2);
456 } else {
457 lua_pushnil(L);
458 }
459}
460
461void lmt_push_node_fast(lua_State *L, halfword n)
462{
463 if (n) {
464 halfword *a = lua_newuserdatauv(L, sizeof(halfword), 0);
465 *a = n;
466 lua_get_metatablelua(node_instance);
467 lua_setmetatable(L, -2);
468 } else {
469 lua_pushnil(L);
470 }
471}
472
473void lmt_push_directornode(lua_State *L, halfword n, int isdirect)
474{
475 if (! n) {
476 lua_pushnil(L);
477 } else if (isdirect) {
478 lua_push_integer(L, n);
479 } else {
480 lmt_push_node_fast(L, n);
481 }
482}
483
484
485
486static int nodelib_getlist(lua_State *L, int n)
487{
488 if (lua_isuserdata(L, n)) {
489 return lmt_check_isnode(L, n);
490 } else {
491 return null;
492 }
493}
494
495
496
497# define id_usage common_usage
498
499static int nodelib_shared_id(lua_State *L)
500{
501 if (lua_type(L, 1) == LUA_TSTRING) {
502 int i = nodelib_aux_get_node_type_id_from_name(L, 1, lmt_interface.node_data, 0);
503 if (i >= 0) {
504 lua_pushinteger(L, i);
505 } else {
506 lua_pushnil(L);
507 }
508 } else {
509 lua_pushnil(L);
510 }
511 return 1;
512}
513
514
515
516# define getid_usage common_usage
517
518static int nodelib_direct_getid(lua_State *L)
519{
520 halfword n = nodelib_valid_direct_from_index(L, 1);
521 if (n) {
522 lua_pushinteger(L, node_type(n));
523 } else {
524 lua_pushnil(L);
525 }
526 return 1;
527}
528
529
530
531# define getidsubtype_usage common_usage
532
533static int nodelib_direct_getidsubtype(lua_State *L)
534{
535 halfword n = nodelib_valid_direct_from_index(L, 1);
536 if (n) {
537 lua_pushinteger(L, node_type(n));
538 lua_pushinteger(L, node_subtype(n));
539 } else {
540 lua_pushnil(L);
541 lua_pushnil(L);
542 }
543 return 2;
544}
545
546
547
548
549# define getsubtype_usage common_usage
550# define setsubtype_usage common_usage
551
552static int nodelib_direct_getsubtype(lua_State *L)
553{
554 halfword n = nodelib_valid_direct_from_index(L, 1);
555 if (n) {
556 lua_pushinteger(L, node_subtype(n));
557 } else {
558 lua_pushnil(L);
559 }
560 return 1;
561}
562
563static int nodelib_direct_setsubtype(lua_State *L)
564{
565 halfword n = nodelib_valid_direct_from_index(L, 1);
566 if (n && lua_type(L, 2) == LUA_TNUMBER) {
567 node_subtype(n) = lmt_toquarterword(L, 2);
568 }
569 return 0;
570}
571
572
573
574
575# define getexpansion_usage (glyph_usage | kern_usage)
576# define setexpansion_usage getexpansion_usage
577
578static int nodelib_direct_getexpansion(lua_State *L)
579{
580 halfword n = nodelib_valid_direct_from_index(L, 1);
581 if (n) {
582 switch (node_type(n)) {
583 case glyph_node:
584 lua_pushinteger(L, glyph_expansion(n));
585 break;
586 case kern_node:
587 lua_pushinteger(L, kern_expansion(n));
588 break;
589 default:
590 lua_pushnil(L);
591 break;
592 }
593 } else {
594 lua_pushnil(L);
595 }
596 return 1;
597}
598
599static int nodelib_direct_setexpansion(lua_State *L)
600{
601 halfword n = nodelib_valid_direct_from_index(L, 1);
602 if (n) {
603 halfword e = 0;
604 if (lua_type(L, 2) == LUA_TNUMBER) {
605 e = (halfword) lmt_roundnumber(L, 2);
606 }
607 switch (node_type(n)) {
608 case glyph_node:
609 glyph_expansion(n) = e;
610 break;
611 case kern_node:
612 kern_expansion(n) = e;
613 break;
614 }
615 }
616 return 0;
617}
618
619
620
621
622# define getfont_usage (glyph_usage | glue_usage | math_char_usage | math_text_char_usage | delimiter_usage)
623# define setfont_usage (glyph_usage | rule_usage | glue_usage)
624
625static int nodelib_direct_getfont(lua_State *L)
626{
627 halfword n = nodelib_valid_direct_from_index(L, 1);
628 if (n) {
629 switch (node_type(n)) {
630 case glyph_node:
631 lua_pushinteger(L, glyph_font(n));
632 break;
633 case glue_node:
634 lua_pushinteger(L, glue_font(n));
635 break;
636 case math_char_node:
637 case math_text_char_node:
638 lua_pushinteger(L, tex_fam_fnt(kernel_math_family(n), 0));
639 break;
640 case delimiter_node:
641 lua_pushinteger(L, tex_fam_fnt(delimiter_small_family(n), 0));
642 break;
643 default:
644 lua_pushnil(L);
645 break;
646 }
647 } else {
648 lua_pushnil(L);
649 }
650 return 1;
651}
652
653static int nodelib_direct_setfont(lua_State *L)
654{
655 halfword n = nodelib_valid_direct_from_index(L, 1);
656 if (n) {
657 switch (node_type(n)) {
658 case glyph_node:
659 glyph_font(n) = tex_checked_font(lmt_tohalfword(L, 2));
660 if (lua_type(L, 3) == LUA_TNUMBER) {
661 glyph_character(n) = lmt_tohalfword(L, 3);
662 }
663 break;
664 case rule_node:
665 tex_set_rule_font(n, lmt_tohalfword(L, 2));
666 if (lua_type(L, 3) == LUA_TNUMBER) {
667 rule_strut_character(n) = lmt_tohalfword(L, 3);
668 }
669 break;
670 case glue_node:
671 glue_font(n) = tex_checked_font(lmt_tohalfword(L, 2));
672 break;
673 }
674 }
675 return 0;
676}
677
678# define getchardict_usage (glyph_usage | math_char_usage | math_text_char_usage | delimiter_usage)
679# define setchardict_usage getchardict_usage
680
681static int nodelib_direct_getchardict(lua_State *L)
682{
683 halfword n = nodelib_valid_direct_from_index(L, 1);
684 if (n) {
685 switch (node_type(n)) {
686 case glyph_node:
687 lua_pushinteger(L, glyph_properties(n));
688 lua_pushinteger(L, glyph_group(n));
689 lua_pushinteger(L, glyph_index(n));
690 lua_pushinteger(L, glyph_font(n));
691 lua_pushinteger(L, glyph_character(n));
692 return 5;
693 case math_char_node:
694 case math_text_char_node:
695 lua_pushinteger(L, kernel_math_properties(n));
696 lua_pushinteger(L, kernel_math_group(n));
697 lua_pushinteger(L, kernel_math_index(n));
698 lua_pushinteger(L, tex_fam_fnt(kernel_math_family(n),0));
699 lua_pushinteger(L, kernel_math_character(n));
700 return 5;
701 case delimiter_node:
702 lua_pushinteger(L, delimiter_math_properties(n));
703 lua_pushinteger(L, delimiter_math_group(n));
704 lua_pushinteger(L, delimiter_math_index(n));
705 lua_pushinteger(L, tex_fam_fnt(delimiter_small_family(n),0));
706 lua_pushinteger(L, delimiter_small_character(n));
707 return 5;
708 }
709 }
710 return 0;
711}
712
713static int nodelib_direct_setchardict(lua_State *L)
714{
715 halfword n = nodelib_valid_direct_from_index(L, 1);
716 if (n) {
717 switch (node_type(n)) {
718 case glyph_node:
719 glyph_properties(n) = lmt_optquarterword(L, 2, 0);
720 glyph_group(n) = lmt_optquarterword(L, 3, 0);
721 glyph_index(n) = lmt_opthalfword(L, 4, 0);
722 break;
723 case math_char_node:
724 case math_text_char_node:
725 kernel_math_properties(n) = lmt_optquarterword(L, 2, 0);
726 kernel_math_group(n) = lmt_optquarterword(L, 3, 0);
727 kernel_math_index(n) = lmt_opthalfword(L, 4, 0);
728 break;
729 case delimiter_node:
730 delimiter_math_properties(n) = lmt_optquarterword(L, 2, 0);
731 delimiter_math_group(n) = lmt_optquarterword(L, 3, 0);
732 delimiter_math_index(n) = lmt_opthalfword(L, 4, 0);
733 break;
734 }
735 }
736 return 0;
737}
738
739
740
741
742# define getchar_usage (glyph_usage | rule_usage | math_char_usage | math_text_char_usage | delimiter_usage)
743# define setchar_usage getchar_usage
744
745static int nodelib_direct_getchar(lua_State *L)
746{
747 halfword n = nodelib_valid_direct_from_index(L, 1);
748 if (n) {
749 switch(node_type(n)) {
750 case glyph_node:
751 lua_pushinteger(L, glyph_character(n));
752 break;
753 case rule_node:
754 lua_pushinteger(L, rule_strut_character(n));
755 break;
756 case math_char_node:
757 case math_text_char_node:
758 lua_pushinteger(L, kernel_math_character(n));
759 break;
760 case delimiter_node:
761
762 lua_pushinteger(L, delimiter_small_character(n));
763 break;
764 default:
765 lua_pushnil(L);
766 break;
767 }
768 } else {
769 lua_pushnil(L);
770 }
771 return 1;
772}
773
774static int nodelib_direct_setchar(lua_State *L)
775{
776 halfword n = nodelib_valid_direct_from_index(L, 1);
777 if (n && lua_type(L, 2) == LUA_TNUMBER) {
778 switch (node_type(n)) {
779 case glyph_node:
780 glyph_character(n) = lmt_tohalfword(L, 2);
781 break;
782 case rule_node:
783 rule_strut_character(n) = lmt_tohalfword(L, 2);
784 break;
785 case math_char_node:
786 case math_text_char_node:
787 kernel_math_character(n) = lmt_tohalfword(L, 2);
788 break;
789 case delimiter_node:
790
791 delimiter_small_character(n) = lmt_tohalfword(L, 2);
792 break;
793 }
794 }
795 return 0;
796}
797
798
799
800# define getcharspec_usage (glyph_usage | rule_usage | simple_usage | math_char_usage | math_text_char_usage | delimiter_usage)
801# define setcharspec_usage getcharspec_usage
802
803static int nodelib_direct_getcharspec(lua_State *L)
804{
805 halfword n = nodelib_valid_direct_from_index(L, 1);
806 if (n) {
807 AGAIN:
808 switch (node_type(n)) {
809 case glyph_node:
810 lua_pushinteger(L, glyph_character(n));
811 lua_pushinteger(L, glyph_font(n));
812 return 2;
813 case rule_node:
814 lua_pushinteger(L, rule_strut_character(n));
815 lua_pushinteger(L, tex_get_rule_font(n, text_style));
816 break;
817 case simple_noad:
818 n = noad_nucleus(n);
819 if (n) {
820 goto AGAIN;
821 } else {
822 break;
823 }
824 case math_char_node:
825 case math_text_char_node:
826 lua_pushinteger(L, kernel_math_character(n));
827 lua_pushinteger(L, tex_fam_fnt(kernel_math_family(n), 0));
828 lua_pushinteger(L, kernel_math_family(n));
829 return 3;
830 case delimiter_node:
831 lua_pushinteger(L, delimiter_small_character(n));
832 lua_pushinteger(L, tex_fam_fnt(delimiter_small_family(n), 0));
833 lua_pushinteger(L, delimiter_small_family(n));
834 return 3;
835 }
836 }
837 return 0;
838}
839
840
841
842
843# define getfam_usage (math_char_usage | math_text_char_usage | simple_usage | radical_usage | fraction_usage | accent_usage | fence_usage | rule_usage)
844# define setfam_usage getfam_usage
845
846static int nodelib_direct_getfam(lua_State *L)
847{
848 halfword n = nodelib_valid_direct_from_index(L, 1);
849 if (n) {
850 switch(node_type(n)) {
851 case math_char_node:
852 case math_text_char_node:
853 lua_pushinteger(L, kernel_math_family(n));
854 break;
855 case delimiter_node:
856 lua_pushinteger(L, delimiter_small_family(n));
857 break;
858 case simple_noad:
859 case radical_noad:
860 case fraction_noad:
861 case accent_noad:
862 case fence_noad:
863
864 lua_pushinteger(L, noad_family(n));
865 break;
866 case rule_node:
867 lua_pushinteger(L, tex_get_rule_family(n));
868 break;
869 default:
870 lua_pushnil(L);
871 break;
872 }
873 } else {
874 lua_pushnil(L);
875 }
876 return 1;
877}
878
879static int nodelib_direct_setfam(lua_State *L)
880{
881 halfword n = nodelib_valid_direct_from_index(L, 1);
882 if (n && lua_type(L, 2) == LUA_TNUMBER) {
883 switch (node_type(n)) {
884 case math_char_node:
885 case math_text_char_node:
886 kernel_math_family(n) = lmt_tohalfword(L, 2);
887 break;
888 case delimiter_node:
889 delimiter_small_family(n) = lmt_tohalfword(L, 2);
890 delimiter_large_family(n) = delimiter_small_family(n);
891 break;
892 case simple_noad:
893 case radical_noad:
894 case fraction_noad:
895 case accent_noad:
896 case fence_noad:
897
898 set_noad_family(n, lmt_tohalfword(L, 2));
899 break;
900 case rule_node:
901 tex_set_rule_family(n, lmt_tohalfword(L, 2));
902 break;
903 }
904 }
905 return 0;
906}
907
908
909
910
911
917
918# define getstate_usage (glyph_usage | hlist_usage | vlist_usage)
919# define setstate_usage getstate_usage
920
921static int nodelib_direct_getstate(lua_State *L)
922{
923 halfword n = nodelib_valid_direct_from_index(L, 1);
924 if (n) {
925 int state = 0;
926 switch (node_type(n)) {
927 case glyph_node:
928 state = get_glyph_state(n);
929 break;
930 case hlist_node:
931 case vlist_node:
932 state = box_package_state(n);
933 break;
934 default:
935 goto NOPPES;
936 }
937 if (lua_type(L, 2) == LUA_TNUMBER) {
938 lua_pushboolean(L, lua_tointeger(L, 2) == state);
939 return 1;
940 } else if (state) {
941 lua_pushinteger(L, state);
942 return 1;
943 } else {
944
945 }
946 }
947 NOPPES:
948 lua_pushnil(L);
949 return 1;
950}
951
952static int nodelib_direct_setstate(lua_State *L)
953{
954 halfword n = nodelib_valid_direct_from_index(L, 1);
955 if (n) {
956 switch (node_type(n)) {
957 case glyph_node:
958 set_glyph_state(n, lmt_opthalfword(L, 2, 0));
959 break;
960 case hlist_node:
961 case vlist_node:
962 box_package_state(n) = (singleword) lmt_opthalfword(L, 2, 0);
963 break;
964 }
965 }
966 return 0;
967}
968
969
970
971
972# define getclass_usage (simple_usage | radical_usage | fraction_usage | accent_usage | fence_usage | glyph_usage | disc_usage | hlist_usage | vlist_usage | delimiter_usage)
973# define setclass_usage getclass_usage
974
975static int nodelib_direct_getclass(lua_State *L)
976{
977 halfword n = nodelib_valid_direct_from_index(L, 1);
978 if (n) {
979 switch (node_type(n)) {
980 case simple_noad:
981 case radical_noad:
982 case fraction_noad:
983 case accent_noad:
984 case fence_noad:
985 lua_push_integer(L, get_noad_main_class(n));
986 lua_push_integer(L, get_noad_left_class(n));
987 lua_push_integer(L, get_noad_right_class(n));
988 return 3;
989 case glyph_node:
990 {
991 halfword mathclass = node_subtype(n) - glyph_math_ordinary_subtype;
992 if (mathclass >= 0) {
993 lua_push_integer(L, mathclass);
994 return 1;
995 } else {
996 break;
997 }
998 }
999 case disc_node:
1000 lua_push_integer(L, disc_class(n));
1001 return 1;
1002 case hlist_node:
1003 case vlist_node:
1004 {
1005 halfword mathclass = node_subtype(n) - noad_class_list_base;
1006 if (mathclass >= 0) {
1007 lua_push_integer(L, mathclass);
1008 return 1;
1009 } else {
1010 break;
1011 }
1012 }
1013 case delimiter_node:
1014 lua_push_integer(L, node_subtype(n));
1015 return 1;
1016 }
1017 }
1018 lua_pushnil(L);
1019 return 1;
1020}
1021
1022static int nodelib_direct_setclass(lua_State *L)
1023{
1024 halfword n = nodelib_valid_direct_from_index(L, 1);
1025 if (n) {
1026 switch (node_type(n)) {
1027 case simple_noad:
1028 case radical_noad:
1029 case fraction_noad:
1030 case accent_noad:
1031 case fence_noad:
1032 if (lua_type(L, 2) == LUA_TNUMBER) {
1033 set_noad_main_class(n, lmt_tosingleword(L, 2));
1034 }
1035 if (lua_type(L, 3) == LUA_TNUMBER) {
1036 set_noad_left_class(n, lmt_tosingleword(L, 3));
1037 }
1038 if (lua_type(L, 4) == LUA_TNUMBER) {
1039 set_noad_right_class(n, lmt_tosingleword(L, 4));
1040 }
1041 break;
1042 case glyph_node:
1043 node_subtype(n) = glyph_math_ordinary_subtype + lmt_tosingleword(L, 2);
1044 break;
1045 case disc_node:
1046 disc_class(n) = lmt_tosingleword(L, 2);
1047 break;
1048 case hlist_node:
1049 case vlist_node:
1050 node_subtype(n) = noad_class_list_base + lmt_tosingleword(L, 2);
1051 break;
1052 case delimiter_node:
1053 node_subtype(n) = lmt_tosingleword(L, 2);
1054 return 1;
1055 }
1056 }
1057 return 0;
1058}
1059
1060
1061
1062
1063# define getscript_usage (glyph_usage)
1064# define setscript_usage getscript_usage
1065
1066static int nodelib_direct_getscript(lua_State *L)
1067{
1068 halfword n = nodelib_valid_direct_from_index(L, 1);
1069 if (n && node_type(n) == glyph_node && get_glyph_script(n)) {
1070 if (lua_type(L, 2) == LUA_TNUMBER) {
1071 lua_pushboolean(L, lua_tointeger(L, 2) == get_glyph_script(n));
1072 } else {
1073 lua_pushinteger(L, get_glyph_script(n));
1074 }
1075 } else {
1076 lua_pushnil(L);
1077 }
1078 return 1;
1079}
1080
1081static int nodelib_direct_setscript(lua_State *L)
1082{
1083 halfword n = nodelib_valid_direct_from_index(L, 1);
1084 if (n && node_type(n) == glyph_node) {
1085 set_glyph_script(n, lmt_opthalfword(L, 2, 0));
1086 }
1087 return 0;
1088}
1089
1090
1091
1092
1093# define getlanguage_usage (glyph_usage)
1094# define setlanguage_usage getlanguage_usage
1095
1096static int nodelib_direct_getlanguage(lua_State *L)
1097{
1098 halfword n = nodelib_valid_direct_from_index(L, 1);
1099 if (n && node_type(n) == glyph_node) {
1100 lua_pushinteger(L, get_glyph_language(n));
1101 } else {
1102 lua_pushnil(L);
1103 }
1104 return 1;
1105}
1106
1107static int nodelib_direct_setlanguage(lua_State *L)
1108{
1109 halfword n = nodelib_valid_direct_from_index(L, 1);
1110 if (n && node_type(n) == glyph_node) {
1111 set_glyph_language(n, lmt_opthalfword(L, 2, 0));
1112 }
1113 return 0;
1114}
1115
1116
1117
1118
1119# define getcontrol_usage (glyph_usage)
1120# define setcontrol_usage getcontrol_usage
1121
1122static int nodelib_direct_getcontrol(lua_State *L)
1123{
1124 halfword n = nodelib_valid_direct_from_index(L, 1);
1125 if (n && node_type(n) == glyph_node) {
1126 lua_pushinteger(L, get_glyph_control(n));
1127 } else {
1128 lua_pushnil(L);
1129 }
1130 return 1;
1131}
1132
1133static int nodelib_direct_setcontrol(lua_State *L)
1134{
1135 halfword n = nodelib_valid_direct_from_index(L, 1);
1136 if (n && node_type(n) == glyph_node) {
1137 set_glyph_control(n, lmt_opthalfword(L, 2, 0));
1138 }
1139 return 0;
1140}
1141
1142
1143
1144
1145# define getattributelist_usage common_usage
1146# define setattributelist_usage getattributelist_usage
1147
1148static int nodelib_direct_getattributelist(lua_State *L)
1149{
1150 halfword n = nodelib_valid_direct_from_index(L, 1);
1151 if (n && tex_nodetype_has_attributes(node_type(n)) && node_attr(n)) {
1152 if (lua_toboolean(L, 2)) {
1153 nodelib_push_attribute_data(L, node_attr(n));
1154 } else {
1155 lua_pushinteger(L, node_attr(n));
1156 }
1157 } else {
1158 lua_pushnil(L);
1159 }
1160 return 1;
1161}
1162
1163static void nodelib_aux_setattributelist(lua_State *L, halfword n, int index)
1164{
1165 if (n && tex_nodetype_has_attributes(node_type(n))) {
1166 halfword a = null;
1167 switch (lua_type(L, index)) {
1168 case LUA_TNUMBER:
1169 {
1170 halfword m = nodelib_valid_direct_from_index(L, index);
1171 if (m) {
1172 quarterword t = node_type(m);
1173 if (t == attribute_node) {
1174 if (node_subtype(m) == attribute_list_subtype) {
1175 a = m;
1176 } else {
1177
1178 }
1179 } else if (tex_nodetype_has_attributes(t)) {
1180 a = node_attr(m);
1181 }
1182 }
1183 }
1184 break;
1185 case LUA_TBOOLEAN:
1186 if (lua_toboolean(L, index)) {
1187 a = tex_current_attribute_list();
1188 }
1189 break;
1190 case LUA_TTABLE:
1191 {
1192
1193 lua_pushnil(L);
1194 while (lua_next(L, index)) {
1195 halfword key = lmt_tohalfword(L, -2);
1196 halfword val = lmt_tohalfword(L, -1);
1197 a = tex_patch_attribute_list(a, key, val);
1198 lua_pop(L, 1);
1199 }
1200 lua_pop(L, 1);
1201 }
1202 break;
1203 }
1204 tex_attach_attribute_list_attribute(n, a);
1205 }
1206}
1207
1208static int nodelib_direct_setattributelist(lua_State *L)
1209{
1210 nodelib_aux_setattributelist(L, nodelib_valid_direct_from_index(L, 1), 2);
1211 return 0;
1212}
1213
1214
1215
1216
1217# define getpenalty_usage (penalty_usage | disc_usage | math_node)
1218# define setpenalty_usage getpenalty_usage
1219
1220static int nodelib_direct_getpenalty(lua_State *L)
1221{
1222 halfword n = nodelib_valid_direct_from_index(L, 1);
1223 if (n) {
1224 switch (node_type(n)) {
1225 case penalty_node:
1226 lua_pushinteger(L, lua_toboolean(L, 2) ? penalty_tnuoma(n) : penalty_amount(n));
1227 break;
1228 case disc_node:
1229 lua_pushinteger(L, disc_penalty(n));
1230 break;
1231 case math_node:
1232 lua_pushinteger(L, math_penalty(n));
1233 break;
1234 default:
1235 lua_pushnil(L);
1236 break;
1237 }
1238 } else {
1239 lua_pushnil(L);
1240 }
1241 return 1;
1242}
1243
1244static int nodelib_direct_setpenalty(lua_State *L)
1245{
1246 halfword n = nodelib_valid_direct_from_index(L, 1);
1247 if (n) {
1248 switch (node_type(n)) {
1249 case penalty_node:
1250 penalty_amount(n) = (halfword) luaL_optinteger(L, 2, 0);
1251 break;
1252 case disc_node:
1253 disc_penalty(n) = (halfword) luaL_optinteger(L, 2, 0);
1254 break;
1255 case math_node:
1256 math_penalty(n) = (halfword) luaL_optinteger(L, 2, 0);
1257 break;
1258 }
1259 }
1260 return 0;
1261}
1262
1263
1264
1265
1266# define atomlike_usage (simple_usage | accent_usage | radical_usage)
1267
1268# define getnucleus_usage atomlike_usage
1269# define setnucleus_usage atomlike_usage
1270
1271static int nodelib_direct_getnucleus(lua_State *L)
1272{
1273 halfword n = nodelib_valid_direct_from_index(L, 1);
1274 if (n) {
1275 switch (node_type(n)) {
1276 case simple_noad:
1277 case accent_noad:
1278 case radical_noad:
1279 nodelib_push_direct_or_nil(L, noad_nucleus(n));
1280 if (lua_toboolean(L, 2)) {
1281 nodelib_push_direct_or_nil(L, noad_prime(n));
1282 nodelib_push_direct_or_nil(L, noad_supscr(n));
1283 nodelib_push_direct_or_nil(L, noad_subscr(n));
1284 nodelib_push_direct_or_nil(L, noad_supprescr(n));
1285 nodelib_push_direct_or_nil(L, noad_subprescr(n));
1286 return 6;
1287 } else {
1288 return 1;
1289 }
1290 }
1291 }
1292 lua_pushnil(L);
1293 return 1;
1294}
1295
1296static int nodelib_direct_setnucleus(lua_State *L)
1297{
1298 halfword n = nodelib_valid_direct_from_index(L, 1);
1299 if (n) {
1300 switch (node_type(n)) {
1301 case simple_noad:
1302 case accent_noad:
1303 case radical_noad:
1304 noad_nucleus(n) = nodelib_valid_direct_from_index(L, 2);
1305 break;
1306 }
1307 }
1308 return 0;
1309}
1310
1311
1312
1313
1314# define getscripts_usage atomlike_usage
1315# define setscripts_usage atomlike_usage
1316
1317static int nodelib_direct_getscripts(lua_State *L)
1318{
1319 halfword n = nodelib_valid_direct_from_index(L, 1);
1320 if (n) {
1321 switch (node_type(n)) {
1322 case simple_noad:
1323 case accent_noad:
1324 case radical_noad:
1325 nodelib_push_direct_or_nil(L, noad_prime(n));
1326 nodelib_push_direct_or_nil(L, noad_supscr(n));
1327 nodelib_push_direct_or_nil(L, noad_subscr(n));
1328 nodelib_push_direct_or_nil(L, noad_supprescr(n));
1329 nodelib_push_direct_or_nil(L, noad_subprescr(n));
1330 return 5;
1331 }
1332 }
1333 return 0;
1334}
1335
1336static int nodelib_direct_setscripts(lua_State *L)
1337{
1338 halfword n = nodelib_valid_direct_from_index(L, 1);
1339 if (n) {
1340 switch (node_type(n)) {
1341 case simple_noad:
1342 case accent_noad:
1343 case radical_noad:
1344 noad_prime(n) = nodelib_valid_direct_from_index(L, 2);
1345 noad_supscr(n) = nodelib_valid_direct_from_index(L, 3);
1346 noad_subscr(n) = nodelib_valid_direct_from_index(L, 4);
1347 noad_supprescr(n) = nodelib_valid_direct_from_index(L, 5);
1348 noad_subprescr(n) = nodelib_valid_direct_from_index(L, 6);
1349 break;
1350 }
1351 }
1352 return 0;
1353}
1354
1355
1356
1357
1358# define getsub_usage atomlike_usage
1359# define setsub_usage atomlike_usage
1360
1361static int nodelib_direct_getsub(lua_State *L)
1362{
1363 halfword n = nodelib_valid_direct_from_index(L, 1);
1364 if (n) {
1365 switch (node_type(n)) {
1366 case simple_noad:
1367 case accent_noad:
1368 case radical_noad:
1369 nodelib_push_direct_or_nil(L, noad_subscr(n));
1370 return 1;
1371 }
1372 }
1373 lua_pushnil(L);
1374 return 1;
1375}
1376
1377static int nodelib_direct_setsub(lua_State *L)
1378{
1379 halfword n = nodelib_valid_direct_from_index(L, 1);
1380 if (n) {
1381 switch (node_type(n)) {
1382 case simple_noad:
1383 case accent_noad:
1384 case radical_noad:
1385 noad_subscr(n) = nodelib_valid_direct_from_index(L, 2);
1386
1387
1388
1389 break;
1390 }
1391 }
1392 return 0;
1393}
1394
1395
1396
1397
1398# define getsubpre_usage atomlike_usage
1399# define setsubpre_usage atomlike_usage
1400
1401static int nodelib_direct_getsubpre(lua_State *L)
1402{
1403 halfword n = nodelib_valid_direct_from_index(L, 1);
1404 if (n) {
1405 switch (node_type(n)) {
1406 case simple_noad:
1407 case accent_noad:
1408 case radical_noad:
1409 nodelib_push_direct_or_nil(L, noad_subprescr(n));
1410 return 1;
1411 }
1412 }
1413 lua_pushnil(L);
1414 return 1;
1415}
1416
1417static int nodelib_direct_setsubpre(lua_State *L)
1418{
1419 halfword n = nodelib_valid_direct_from_index(L, 1);
1420 if (n) {
1421 switch (node_type(n)) {
1422 case simple_noad:
1423 case accent_noad:
1424 case radical_noad:
1425 noad_subprescr(n) = nodelib_valid_direct_from_index(L, 2);
1426 break;
1427 }
1428 }
1429 return 0;
1430}
1431
1432
1433
1434
1435# define getsup_usage atomlike_usage
1436# define setsup_usage atomlike_usage
1437
1438static int nodelib_direct_getsup(lua_State *L)
1439{
1440 halfword n = nodelib_valid_direct_from_index(L, 1);
1441 if (n) {
1442 switch (node_type(n)) {
1443 case simple_noad:
1444 case accent_noad:
1445 case radical_noad:
1446 nodelib_push_direct_or_nil(L, noad_supscr(n));
1447 return 1;
1448 }
1449 }
1450 lua_pushnil(L);
1451 return 1;
1452}
1453
1454static int nodelib_direct_setsup(lua_State *L)
1455{
1456 halfword n = nodelib_valid_direct_from_index(L, 1);
1457 if (n) {
1458 switch (node_type(n)) {
1459 case simple_noad:
1460 case accent_noad:
1461 case radical_noad:
1462 noad_supscr(n) = nodelib_valid_direct_from_index(L, 2);
1463
1464
1465
1466 break;
1467 }
1468 }
1469 return 0;
1470}
1471
1472
1473
1474
1475# define getsuppre_usage atomlike_usage
1476# define setsuppre_usage atomlike_usage
1477
1478static int nodelib_direct_getsuppre(lua_State *L)
1479{
1480 halfword n = nodelib_valid_direct_from_index(L, 1);
1481 if (n) {
1482 switch (node_type(n)) {
1483 case simple_noad:
1484 case accent_noad:
1485 case radical_noad:
1486 nodelib_push_direct_or_nil(L, noad_supprescr(n));
1487 return 1;
1488 }
1489 }
1490 lua_pushnil(L);
1491 return 1;
1492}
1493
1494static int nodelib_direct_setsuppre(lua_State *L)
1495{
1496 halfword n = nodelib_valid_direct_from_index(L, 1);
1497 if (n) {
1498 switch (node_type(n)) {
1499 case simple_noad:
1500 case accent_noad:
1501 case radical_noad:
1502 noad_supprescr(n) = nodelib_valid_direct_from_index(L, 2);
1503 break;
1504 }
1505 }
1506 return 0;
1507}
1508
1509
1510
1511
1512# define getprime_usage atomlike_usage
1513# define setprime_usage atomlike_usage
1514
1515static int nodelib_direct_getprime(lua_State *L)
1516{
1517 halfword n = nodelib_valid_direct_from_index(L, 1);
1518 if (n) {
1519 switch (node_type(n)) {
1520 case simple_noad:
1521 case accent_noad:
1522 case radical_noad:
1523 nodelib_push_direct_or_nil(L, noad_prime(n));
1524 return 1;
1525 }
1526 }
1527 lua_pushnil(L);
1528 return 1;
1529}
1530
1531static int nodelib_direct_setprime(lua_State *L)
1532{
1533 halfword n = nodelib_valid_direct_from_index(L, 1);
1534 if (n) {
1535 switch (node_type(n)) {
1536 case simple_noad:
1537 case accent_noad:
1538 case radical_noad:
1539 noad_prime(n) = nodelib_valid_direct_from_index(L, 2);
1540 break;
1541 }
1542 }
1543 return 0;
1544}
1545
1546
1547
1548
1549# define getkern_usage (kern_usage | math_usage)
1550# define setkern_usage getkern_usage
1551
1552static int nodelib_direct_getkern(lua_State *L)
1553{
1554 halfword n = nodelib_valid_direct_from_index(L, 1);
1555 if (n) {
1556 switch (node_type(n)) {
1557 case kern_node:
1558 lua_pushnumber(L, kern_amount(n));
1559 if (lua_toboolean(L, 2)) {
1560 lua_pushinteger(L, kern_expansion(n));
1561 return 2;
1562 } else {
1563 break;
1564 }
1565 case math_node:
1566 lua_pushinteger(L, math_surround(n));
1567 break;
1568 default:
1569 lua_pushnil(L);
1570 break;
1571 }
1572 } else {
1573 lua_pushnil(L);
1574 }
1575 return 1;
1576}
1577
1578static int nodelib_direct_setkern(lua_State *L)
1579{
1580 halfword n = nodelib_valid_direct_from_index(L, 1);
1581 if (n) {
1582 switch (node_type(n)) {
1583 case kern_node:
1584 kern_amount(n) = lua_type(L, 2) == LUA_TNUMBER ? (halfword) lmt_roundnumber(L, 2) : 0;
1585 if (lua_type(L, 3) == LUA_TNUMBER) {
1586 node_subtype(n) = lmt_toquarterword(L, 3);
1587 }
1588 break;
1589 case math_node:
1590 math_surround(n) = lua_type(L, 2) == LUA_TNUMBER ? (halfword) lmt_roundnumber(L, 2) : 0;
1591 break;
1592 }
1593 }
1594 return 0;
1595}
1596
1597
1598
1599
1600# define getdirection_usage (dir_usage | hlist_usage | vlist_usage | par_usage)
1601# define setdirection_usage getdirection_usage
1602
1603static int nodelib_direct_getdirection(lua_State *L)
1604{
1605 halfword n = nodelib_valid_direct_from_index(L, 1);
1606 if (n) {
1607 switch (node_type(n)) {
1608 case dir_node:
1609 lua_pushinteger(L, dir_direction(n));
1610 lua_pushboolean(L, node_subtype(n));
1611 return 2;
1612 case hlist_node:
1613 case vlist_node:
1614 lua_pushinteger(L, checked_direction_value(box_dir(n)));
1615 break;
1616 case par_node:
1617 lua_pushinteger(L, par_dir(n));
1618 break;
1619 default:
1620 lua_pushnil(L);
1621 break;
1622 }
1623 } else {
1624 lua_pushnil(L);
1625 }
1626 return 1;
1627}
1628
1629static int nodelib_direct_setdirection(lua_State *L)
1630{
1631 halfword n = nodelib_valid_direct_from_index(L, 1);
1632 if (n) {
1633 switch (node_type(n)) {
1634 case dir_node:
1635 dir_direction(n) = nodelib_getdirection(L, 2);
1636 if (lua_type(L, 3) == LUA_TBOOLEAN) {
1637 if (lua_toboolean(L, 3)) {
1638 node_subtype(n) = (quarterword) (lua_toboolean(L, 3) ? cancel_dir_subtype : normal_dir_subtype);
1639 }
1640 }
1641 break;
1642 case hlist_node:
1643 case vlist_node:
1644 box_dir(n) = (singleword) nodelib_getdirection(L, 2);
1645 break;
1646 case par_node:
1647 par_dir(n) = nodelib_getdirection(L, 2);
1648 break;
1649 }
1650 }
1651 return 0;
1652}
1653
1654
1655
1656
1657# define getanchors_usage (hlist_usage | vlist_usage | simple_usage | radical_usage | fraction_usage | accent_usage | fence_usage)
1658# define setanchors_usage getanchors_usage
1659
1660static int nodelib_direct_getanchors(lua_State *L)
1661{
1662 halfword n = nodelib_valid_direct_from_index(L, 1);
1663 if (n) {
1664 switch (node_type(n)) {
1665 case hlist_node:
1666 case vlist_node:
1667 if (box_anchor(n)) {
1668 lua_pushinteger(L, box_anchor(n));
1669 } else {
1670 lua_pushnil(L);
1671 }
1672 if (box_source_anchor(n)) {
1673 lua_pushinteger(L, box_source_anchor(n));
1674 } else {
1675 lua_pushnil(L);
1676 }
1677 if (box_target_anchor(n)) {
1678 lua_pushinteger(L, box_target_anchor(n));
1679 } else {
1680 lua_pushnil(L);
1681 }
1682
1683 if (box_anchor(n)) {
1684 lua_pushinteger(L, box_anchor(n) & 0x0FFF);
1685 } else {
1686 lua_pushnil(L);
1687 }
1688 if (box_anchor(n)) {
1689 lua_pushinteger(L, (box_anchor(n) >> 16) & 0x0FFF);
1690 } else {
1691 lua_pushnil(L);
1692 }
1693 return 5;
1694 case simple_noad:
1695 case radical_noad:
1696 case fraction_noad:
1697 case accent_noad:
1698 case fence_noad:
1699 if (noad_source(n)) {
1700 lua_pushinteger(L, noad_source(n));
1701 } else {
1702 lua_pushnil(L);
1703 }
1704 return 1;
1705 }
1706 }
1707 return 0;
1708}
1709
1710static int nodelib_direct_setanchors(lua_State *L)
1711{
1712 halfword n = nodelib_valid_direct_from_index(L, 1);
1713 if (n) {
1714 switch (node_type(n)) {
1715 case hlist_node:
1716 case vlist_node:
1717 switch (lua_type(L, 2)) {
1718 case LUA_TNUMBER:
1719 box_anchor(n) = lmt_tohalfword(L, 2);
1720 break;
1721 case LUA_TBOOLEAN:
1722 if (lua_toboolean(L, 2)) {
1723 break;
1724 }
1725 default:
1726 box_anchor(n) = 0;
1727 break;
1728 }
1729 switch (lua_type(L, 3)) {
1730 case LUA_TNUMBER :
1731 box_source_anchor(n) = lmt_tohalfword(L, 3);
1732 break;
1733 case LUA_TBOOLEAN:
1734 if (lua_toboolean(L, 3)) {
1735 break;
1736 }
1737 default:
1738 box_source_anchor(n) = 0;
1739 break;
1740 }
1741 switch (lua_type(L, 4)) {
1742 case LUA_TNUMBER:
1743 box_target_anchor(n) = lmt_tohalfword(L, 4);
1744 break;
1745 case LUA_TBOOLEAN:
1746 if (lua_toboolean(L, 4)) {
1747 break;
1748 }
1749 default:
1750 box_target_anchor(n) = 0;
1751 break;
1752 }
1753 tex_check_box_geometry(n);
1754 case simple_noad:
1755 case radical_noad:
1756 case fraction_noad:
1757 case accent_noad:
1758 case fence_noad:
1759 switch (lua_type(L, 2)) {
1760 case LUA_TNUMBER :
1761 noad_source(n) = lmt_tohalfword(L, 2);
1762 break;
1763 case LUA_TBOOLEAN:
1764 if (lua_toboolean(L, 2)) {
1765 break;
1766 }
1767 default:
1768 noad_source(n) = 0;
1769 break;
1770 }
1771 tex_check_box_geometry(n);
1772 }
1773 }
1774 return 0;
1775}
1776
1777
1778
1779
1780# define getoffsets_usage (glyph_usage | hlist_usage | vlist_usage | rule_usage)
1781# define setoffsets_usage getoffsets_usage
1782
1783static int nodelib_direct_getoffsets(lua_State *L)
1784{
1785 halfword n = nodelib_valid_direct_from_index(L, 1);
1786 if (n) {
1787 switch (node_type(n)) {
1788 case glyph_node:
1789 lua_pushinteger(L, glyph_x_offset(n));
1790 lua_pushinteger(L, glyph_y_offset(n));
1791 lua_pushinteger(L, glyph_left(n));
1792 lua_pushinteger(L, glyph_right(n));
1793 lua_pushinteger(L, glyph_raise(n));
1794 return 5;
1795 case hlist_node:
1796 case vlist_node:
1797 lua_pushinteger(L, box_x_offset(n));
1798 lua_pushinteger(L, box_y_offset(n));
1799 return 2;
1800 case rule_node:
1801 lua_pushinteger(L, rule_x_offset(n));
1802 lua_pushinteger(L, rule_y_offset(n));
1803 lua_pushinteger(L, tex_get_rule_left(n));
1804 lua_pushinteger(L, tex_get_rule_right(n));
1805 lua_pushinteger(L, tex_get_rule_on(n));
1806 lua_pushinteger(L, tex_get_rule_off(n));
1807 return 6;
1808 }
1809 }
1810 return 0;
1811}
1812
1813static int nodelib_direct_setoffsets(lua_State *L)
1814{
1815 halfword n = nodelib_valid_direct_from_index(L, 1);
1816 if (n) {
1817 switch (node_type(n)) {
1818 case glyph_node:
1819 if (lua_type(L, 2) == LUA_TNUMBER) {
1820 glyph_x_offset(n) = (halfword) lmt_roundnumber(L, 2);
1821 }
1822 if (lua_type(L, 3) == LUA_TNUMBER) {
1823 glyph_y_offset(n) = (halfword) lmt_roundnumber(L, 3);
1824 }
1825 if (lua_type(L, 4) == LUA_TNUMBER) {
1826 glyph_left(n) = (halfword) lmt_roundnumber(L, 4);
1827 }
1828 if (lua_type(L, 5) == LUA_TNUMBER) {
1829 glyph_right(n) = (halfword) lmt_roundnumber(L, 5);
1830 }
1831 if (lua_type(L, 6) == LUA_TNUMBER) {
1832 glyph_raise(n) = (halfword) lmt_roundnumber(L, 6);
1833 }
1834 break;
1835 case hlist_node:
1836 case vlist_node:
1837 if (lua_type(L, 2) == LUA_TNUMBER) {
1838 box_x_offset(n) = (halfword) lmt_roundnumber(L, 2);
1839 }
1840 if (lua_type(L, 3) == LUA_TNUMBER) {
1841 box_y_offset(n) = (halfword) lmt_roundnumber(L, 3);
1842 }
1843 tex_check_box_geometry(n);
1844 break;
1845 case rule_node:
1846 if (lua_type(L, 2) == LUA_TNUMBER) {
1847 rule_x_offset(n) = (halfword) lmt_roundnumber(L, 2);
1848 }
1849 if (lua_type(L, 3) == LUA_TNUMBER) {
1850 rule_y_offset(n) = (halfword) lmt_roundnumber(L, 3);
1851 }
1852 if (lua_type(L, 4) == LUA_TNUMBER) {
1853 tex_set_rule_left(n, (halfword) lmt_roundnumber(L, 4));
1854 }
1855 if (lua_type(L, 5) == LUA_TNUMBER) {
1856 tex_set_rule_right(n, (halfword) lmt_roundnumber(L, 5));
1857 }
1858 if (lua_type(L, 6) == LUA_TNUMBER) {
1859 tex_set_rule_on(n, (halfword) lmt_roundnumber(L, 6));
1860 }
1861 if (lua_type(L, 7) == LUA_TNUMBER) {
1862 tex_set_rule_off(n, (halfword) lmt_roundnumber(L, 7));
1863 }
1864 break;
1865 }
1866 }
1867 return 0;
1868}
1869
1870
1871
1872
1873# define addxoffset_usage (glyph_usage | hlist_usage | vlist_usage | rule_usage)
1874# define addyoffset_usage addxoffset_usage
1875
1876static int nodelib_direct_addxoffset(lua_State *L)
1877{
1878 halfword n = nodelib_valid_direct_from_index(L, 1);
1879 if (n) {
1880 switch (node_type(n)) {
1881 case glyph_node:
1882 glyph_x_offset(n) += (halfword) lmt_roundnumber(L, 2);
1883 break;
1884 case hlist_node:
1885 case vlist_node:
1886 box_x_offset(n) += (halfword) lmt_roundnumber(L, 2);
1887 tex_check_box_geometry(n);
1888 break;
1889 case rule_node:
1890 rule_x_offset(n) += (halfword) lmt_roundnumber(L, 2);
1891 break;
1892 }
1893 }
1894 return 0;
1895}
1896
1897static int nodelib_direct_addyoffset(lua_State *L)
1898{
1899 halfword n = nodelib_valid_direct_from_index(L, 1);
1900 if (n) {
1901 switch (node_type(n)) {
1902 case glyph_node:
1903 glyph_y_offset(n) += (halfword) lmt_roundnumber(L, 2);
1904 break;
1905 case hlist_node:
1906 case vlist_node:
1907 box_y_offset(n) += (halfword) lmt_roundnumber(L, 2);
1908 tex_check_box_geometry(n);
1909 break;
1910 case rule_node:
1911 rule_y_offset(n) += (halfword) lmt_roundnumber(L, 2);
1912 break;
1913 }
1914 }
1915 return 0;
1916}
1917
1918
1919
1920
1921# define addmargins_usage (glyph_usage | rule_usage)
1922# define addxymargins_usage glyph_usage
1923
1924static int nodelib_direct_addmargins(lua_State *L)
1925{
1926 halfword n = nodelib_valid_direct_from_index(L, 1);
1927 if (n) {
1928 switch (node_type(n)) {
1929 case glyph_node:
1930 if (lua_type(L, 2) == LUA_TNUMBER) {
1931 glyph_left(n) += (halfword) lmt_roundnumber(L, 2);
1932 }
1933 if (lua_type(L, 3) == LUA_TNUMBER) {
1934 glyph_right(n) += (halfword) lmt_roundnumber(L, 3);
1935 }
1936 if (lua_type(L, 4) == LUA_TNUMBER) {
1937 glyph_raise(n) += (halfword) lmt_roundnumber(L, 3);
1938 }
1939 break;
1940 case rule_node:
1941 if (lua_type(L, 2) == LUA_TNUMBER) {
1942 tex_set_rule_left(n, tex_get_rule_left(n) + (halfword) lmt_roundnumber(L, 2));
1943 }
1944 if (lua_type(L, 3) == LUA_TNUMBER) {
1945 tex_set_rule_right(n, tex_get_rule_right(n) + (halfword) lmt_roundnumber(L, 3));
1946 }
1947 break;
1948 }
1949 }
1950 return 0;
1951}
1952
1953static int nodelib_direct_addxymargins(lua_State *L)
1954{
1955 halfword n = nodelib_valid_direct_from_index(L, 1);
1956 if (n && node_type(n) == glyph_node) {
1957 scaled s = glyph_scale(n);
1958 scaled x = glyph_x_scale(n);
1959 scaled y = glyph_y_scale(n);
1960 double sx, sy;
1961 if (s == 0 || s == 1000) {
1962 if (x == 0 || x == 1000) {
1963 sx = 1;
1964 } else {
1965 sx = 0.001 * x;
1966 }
1967 if (y == 0 || y == 1000) {
1968 sy = 1;
1969 } else {
1970 sy = 0.001 * y;
1971 }
1972 } else {
1973 if (x == 0 || x == 1000) {
1974 sx = 0.001 * s;
1975 } else {
1976 sx = 0.000001 * s * x;
1977 }
1978 if (y == 0 || y == 1000) {
1979 sy = 0.001 * s;
1980 } else {
1981 sy = 0.000001 * s * y;
1982 }
1983 }
1984 if (lua_type(L, 2) == LUA_TNUMBER) {
1985 glyph_left(n) += scaledround(sx * lua_tonumber(L, 2));
1986 }
1987 if (lua_type(L, 3) == LUA_TNUMBER) {
1988 glyph_right(n) += scaledround(sx * lua_tonumber(L, 3));
1989 }
1990 if (lua_type(L, 4) == LUA_TNUMBER) {
1991 glyph_raise(n) += scaledround(sy * lua_tonumber(L, 4));
1992 }
1993 }
1994 return 0;
1995}
1996
1997
1998
1999# define getscale_usage glyph_usage
2000# define setscale_usage getscale_usage
2001
2002static int nodelib_direct_getscale(lua_State *L)
2003{
2004 halfword n = nodelib_valid_direct_from_index(L, 1);
2005 if (n && node_type(n) == glyph_node) {
2006 lua_pushinteger(L, glyph_scale(n));
2007 return 1;
2008 }
2009 return 0;
2010}
2011
2012static int nodelib_direct_setscale(lua_State *L)
2013{
2014 halfword n = nodelib_valid_direct_from_index(L, 1);
2015 if (n && node_type(n) == glyph_node) {
2016 if (lua_type(L, 2) == LUA_TNUMBER) {
2017 glyph_scale(n) = (halfword) lmt_roundnumber(L, 2);
2018 if (! glyph_scale(n)) {
2019 glyph_scale(n) = scaling_factor;
2020 }
2021 }
2022 }
2023 return 0;
2024}
2025
2026
2027
2028
2029# define getscales_usage glyph_usage
2030# define setscales_usage getscales_usage
2031
2032static int nodelib_direct_getscales(lua_State *L)
2033{
2034 halfword n = nodelib_valid_direct_from_index(L, 1);
2035 if (n && node_type(n) == glyph_node) {
2036 lua_pushinteger(L, glyph_scale(n));
2037 lua_pushinteger(L, glyph_x_scale(n));
2038 lua_pushinteger(L, glyph_y_scale(n));
2039 return 3;
2040 } else {
2041 return 0;
2042 }
2043}
2044
2045static int nodelib_direct_setscales(lua_State *L)
2046{
2047 halfword n = nodelib_valid_direct_from_index(L, 1);
2048 if (n && node_type(n) == glyph_node) {
2049 if (lua_type(L, 2) == LUA_TNUMBER) {
2050 glyph_scale(n) = (halfword) lmt_roundnumber(L, 2);
2051 if (! glyph_scale(n)) {
2052 glyph_scale(n) = scaling_factor;
2053 }
2054 }
2055 if (lua_type(L, 3) == LUA_TNUMBER) {
2056 glyph_x_scale(n) = (halfword) lmt_roundnumber(L, 3);
2057 if (! glyph_x_scale(n)) {
2058 glyph_x_scale(n) = scaling_factor;
2059 }
2060 }
2061 if (lua_type(L, 4) == LUA_TNUMBER) {
2062 glyph_y_scale(n) = (halfword) lmt_roundnumber(L, 4);
2063 if (! glyph_y_scale(n)) {
2064 glyph_y_scale(n) = scaling_factor;
2065 }
2066 }
2067 }
2068 return 0;
2069}
2070
2071
2072
2073
2074# define getxscale_usage (glue_usage | glyph_usage)
2075# define getyscale_usage getxscale_usage
2076
2077static int nodelib_direct_getxscale(lua_State *L)
2078{
2079 halfword n = nodelib_valid_direct_from_index(L, 1);
2080 if (n) {
2081 switch (node_type(n)) {
2082 case glue_node:
2083 {
2084 switch (node_subtype(n)) {
2085 case space_skip_glue:
2086 case xspace_skip_glue:
2087 if (tex_char_exists(glue_font(n), 0x20)) {
2088 halfword prv = node_prev(n);
2089 halfword nxt = node_next(n);
2090 if (prv) {
2091 if (node_type(prv) == kern_node && font_related_kern(node_subtype(prv))) {
2092 prv = node_prev(prv);
2093 }
2094 if (prv && node_type(prv) == glyph_node && glyph_font(prv) == glue_font(n)) {
2095 n = prv;
2096 goto COMMON;
2097 }
2098 }
2099 if (nxt) {
2100 if (node_type(nxt) == kern_node && font_related_kern(node_subtype(nxt))) {
2101 prv = node_prev(nxt);
2102 }
2103 if (nxt && node_type(nxt) == glyph_node && glyph_font(nxt) == glue_font(n)) {
2104 n = nxt;
2105 goto COMMON;
2106 }
2107 }
2108 }
2109 break;
2110 }
2111 break;
2112 }
2113 case glyph_node:
2114 COMMON:
2115 {
2116 scaled s = glyph_scale(n);
2117 scaled x = glyph_x_scale(n);
2118 double d;
2119 if (s == 0 || s == 1000) {
2120 if (x == 0 || x == 1000) {
2121 goto DONE;
2122 } else {
2123 d = 0.001 * x;
2124 }
2125 } else if (x == 0 || x == 1000) {
2126 d = 0.001 * s;
2127 } else {
2128 d = 0.000001 * s * x;
2129 }
2130 lua_pushnumber(L, d);
2131 return 1;
2132 }
2133 }
2134 }
2135 DONE:
2136 lua_pushinteger(L, 1);
2137 return 1;
2138}
2139
2140static int nodelib_direct_getyscale(lua_State *L)
2141{
2142 halfword n = nodelib_valid_direct_from_index(L, 1);
2143 if (n && node_type(n) == glyph_node) {
2144 scaled s = glyph_scale(n);
2145 scaled y = glyph_y_scale(n);
2146 double d;
2147 if (s == 0 || s == 1000) {
2148 if (y == 0 || y == 1000) {
2149 goto DONE;
2150 } else {
2151 d = 0.001 * y;
2152 }
2153 } else if (y == 0 || y == 1000) {
2154 d = 0.001 * s;
2155 } else {
2156 d = 0.000001 * s * y;
2157 }
2158 lua_pushnumber(L, d);
2159 return 1;
2160 }
2161 DONE:
2162 lua_pushinteger(L, 1);
2163 return 1;
2164}
2165
2166
2167
2168
2169# define xscaled_usage glyph_usage
2170# define yscaled_usage xscaled_usage
2171
2172static int nodelib_direct_xscaled(lua_State *L)
2173{
2174 halfword n = nodelib_valid_direct_from_index(L, 1);
2175 lua_Number v = lua_tonumber(L, 2);
2176 if (n && node_type(n) == glyph_node) {
2177 scaled s = glyph_scale(n);
2178 scaled x = glyph_x_scale(n);
2179 if (s == 0 || s == 1000) {
2180 if (x == 0 || x == 1000) {
2181
2182 } else {
2183 v = 0.001 * x * v;
2184 }
2185 } else if (x == 0 || x == 1000) {
2186 v = 0.001 * s * v;
2187 } else {
2188 v = 0.000001 * s * x * v;
2189 }
2190 }
2191 lua_pushnumber(L, v);
2192 return 1;
2193}
2194
2195static int nodelib_direct_yscaled(lua_State *L)
2196{
2197 halfword n = nodelib_valid_direct_from_index(L, 1);
2198 lua_Number v = lua_tonumber(L, 2);
2199 if (n && node_type(n) == glyph_node) {
2200 scaled s = glyph_scale(n);
2201 scaled y = glyph_y_scale(n);
2202 if (s == 0 || s == 1000) {
2203 if (y == 0 || y == 1000) {
2204
2205 } else {
2206 v = 0.001 * y * v;
2207 }
2208 } else if (y == 0 || y == 1000) {
2209 v = 0.001 * s * v;
2210 } else {
2211 v = 0.000001 * s * y * v;
2212 }
2213 }
2214 lua_pushnumber(L, v);
2215 return 1;
2216}
2217
2218static void nodelib_aux_pushxyscales(lua_State *L, halfword n)
2219{
2220 scaled s = glyph_scale(n);
2221 scaled x = glyph_x_scale(n);
2222 scaled y = glyph_y_scale(n);
2223 double dx;
2224 double dy;
2225 if (s && s != 1000) {
2226 dx = (x && x != 1000) ? 0.000001 * s * x : 0.001 * s;
2227 } else if (x && x != 1000) {
2228 dx = 0.001 * x;
2229 } else {
2230 lua_pushinteger(L, 1);
2231 goto DONEX;
2232 }
2233 lua_pushnumber(L, dx);
2234 DONEX:
2235 if (s && s != 1000) {
2236 dy = (y && y != 1000) ? 0.000001 * s * y : 0.001 * s;
2237 } else if (y && y != 1000) {
2238 dy = 0.001 * y;
2239 } else {
2240 lua_pushinteger(L, 1);
2241 goto DONEY;
2242 }
2243 lua_pushnumber(L, dy);
2244 DONEY: ;
2245}
2246
2247
2248
2249# define getxyscales_usage glyph_usage
2250# define setxyscales_usage getxyscales_usage
2251
2252static int nodelib_direct_getxyscales(lua_State *L)
2253{
2254 halfword n = nodelib_valid_direct_from_index(L, 1);
2255 if (n && node_type(n) == glyph_node) {
2256 nodelib_aux_pushxyscales(L, n);
2257 } else {
2258 lua_pushinteger(L, 1);
2259 lua_pushinteger(L, 1);
2260 }
2261 return 2;
2262}
2263
2264
2265
2266
2267# define getslant_usage glyph_usage
2268# define setslant_usage getslant_usage
2269
2270static int nodelib_direct_getslant(lua_State *L)
2271{
2272 halfword n = nodelib_valid_direct_from_index(L, 1);
2273 lua_pushinteger(L, n && node_type(n) == glyph_node ? glyph_slant(n) : 0);
2274 return 1;
2275}
2276
2277static int nodelib_direct_setslant(lua_State *L)
2278{
2279 halfword n = nodelib_valid_direct_from_index(L, 1);
2280 if (n && node_type(n) == glyph_node) {
2281 glyph_slant(n) = lmt_opthalfword(L, 2, 0);
2282 }
2283 return 0;
2284}
2285
2286
2287
2288
2289# define getweight_usage glyph_usage
2290# define setweight_usage getweight_usage
2291
2292static int nodelib_direct_getweight(lua_State *L)
2293{
2294 halfword n = nodelib_valid_direct_from_index(L, 1);
2295 halfword b = n && node_type(n) == glyph_node;
2296 lua_pushinteger(L, b ? glyph_weight(n) : 0);
2297 lua_pushboolean(L, b ? tex_has_glyph_option(n, glyph_option_weight_less) : 0);
2298 return 2;
2299}
2300
2301static int nodelib_direct_setweight(lua_State *L)
2302{
2303 halfword n = nodelib_valid_direct_from_index(L, 1);
2304 if (n && node_type(n) == glyph_node) {
2305 glyph_weight(n) = lmt_opthalfword(L, 2, 0);
2306 if (lua_type(L, 3) == LUA_TBOOLEAN && lua_toboolean(L, 3)) {
2307 tex_add_glyph_option(n, glyph_option_weight_less);
2308 }
2309 }
2310 return 0;
2311}
2312
2313
2318
2319
2320
2321
2322# define getdisc_usage (disc_usage | choice_usage)
2323# define setdisc_usage getdisc_usage
2324
2325static int nodelib_direct_getdisc(lua_State *L)
2326{
2327 halfword n = nodelib_valid_direct_from_index(L, 1);
2328 if (n) {
2329 switch (node_type(n)) {
2330 case disc_node:
2331 nodelib_push_direct_or_nil(L, disc_pre_break_head(n));
2332 nodelib_push_direct_or_nil(L, disc_post_break_head(n));
2333 nodelib_push_direct_or_nil(L, disc_no_break_head(n));
2334 if (lua_isboolean(L, 2) && lua_toboolean(L, 2)) {
2335 nodelib_push_direct_or_nil(L, disc_pre_break_tail(n));
2336 nodelib_push_direct_or_nil(L, disc_post_break_tail(n));
2337 nodelib_push_direct_or_nil(L, disc_no_break_tail(n));
2338 return 6;
2339 } else {
2340 return 3;
2341 }
2342 case choice_node:
2343 if (node_subtype(n) == discretionary_choice_subtype) {
2344 nodelib_push_direct_or_nil(L, choice_pre_break(n));
2345 nodelib_push_direct_or_nil(L, choice_post_break(n));
2346 nodelib_push_direct_or_nil(L, choice_no_break(n));
2347 if (lua_isboolean(L, 2) && lua_toboolean(L, 2)) {
2348 nodelib_push_direct_or_nil(L, tex_tail_of_node_list(choice_pre_break(n)));
2349 nodelib_push_direct_or_nil(L, tex_tail_of_node_list(choice_post_break(n)));
2350 nodelib_push_direct_or_nil(L, tex_tail_of_node_list(choice_no_break(n)));
2351 return 6;
2352 } else {
2353 return 3;
2354 }
2355 } else {
2356 break;
2357 }
2358 }
2359 }
2360 return 0;
2361}
2362
2363static int nodelib_direct_setdisc(lua_State *L)
2364{
2365 halfword n = nodelib_valid_direct_from_index(L, 1);
2366 if (n && node_type(n) == disc_node) {
2367 int t = lua_gettop(L) ;
2368 if (t > 1) {
2369 tex_set_disc_field(n, pre_break_code, nodelib_valid_direct_from_index(L, 2));
2370 if (t > 2) {
2371 tex_set_disc_field(n, post_break_code, nodelib_valid_direct_from_index(L, 3));
2372 if (t > 3) {
2373 tex_set_disc_field(n, no_break_code, nodelib_valid_direct_from_index(L, 4));
2374 if (t > 4) {
2375 node_subtype(n) = lmt_toquarterword(L, 5);
2376 if (t > 5) {
2377 disc_penalty(n) = lmt_tohalfword(L, 6);
2378 }
2379 }
2380 } else {
2381 tex_set_disc_field(n, no_break_code, null);
2382 }
2383 } else {
2384 tex_set_disc_field(n, post_break_code, null);
2385 tex_set_disc_field(n, no_break_code, null);
2386 }
2387 } else {
2388 tex_set_disc_field(n, pre_break_code, null);
2389 tex_set_disc_field(n, post_break_code, null);
2390 tex_set_disc_field(n, no_break_code, null);
2391 }
2392 }
2393 return 0;
2394}
2395
2396
2397
2398
2399# define getdiscpart_usage glyph_node
2400# define setdiscpart_usage getdiscpart_usage
2401
2402static int nodelib_direct_getdiscpart(lua_State *L)
2403{
2404 halfword n = nodelib_valid_direct_from_index(L, 1);
2405 if (n && node_type(n) == glyph_node) {
2406 lua_pushinteger(L, get_glyph_discpart(n));
2407 lua_pushinteger(L, get_glyph_discafter(n));
2408 lua_pushinteger(L, get_glyph_disccode(n));
2409 return 3;
2410 } else {
2411 return 0;
2412 }
2413}
2414
2415static int nodelib_direct_setdiscpart(lua_State *L)
2416{
2417 halfword n = nodelib_valid_direct_from_index(L, 1);
2418 if (n && node_type(n) == glyph_node) {
2419 if (lua_type(L, 2) == LUA_TNUMBER) { set_glyph_discpart (n, lua_tointeger(L, 2)); }
2420 if (lua_type(L, 3) == LUA_TNUMBER) { set_glyph_discafter(n, lua_tointeger(L, 3)); }
2421 if (lua_type(L, 4) == LUA_TNUMBER) { set_glyph_disccode (n, lua_tointeger(L, 4)); }
2422 return 1;
2423 } else {
2424 return 0;
2425 }
2426}
2427
2428
2429
2430
2431
2432# define getpre_usage (disc_usage | hlist_usage | vlist_usage | choice_usage)
2433# define getpost_usage getpre_usage
2434# define getreplace_usage (disc_usage | choice_usage)
2435
2436static int nodelib_direct_getpre(lua_State *L)
2437{
2438 halfword n = nodelib_valid_direct_from_index(L, 1);
2439 if (n) {
2440 switch (node_type(n)) {
2441 case disc_node:
2442 nodelib_push_direct_or_nil(L, disc_pre_break_head(n));
2443 nodelib_push_direct_or_nil(L, disc_pre_break_tail(n));
2444 return 2;
2445 case hlist_node:
2446 case vlist_node:
2447 {
2448 halfword h = box_pre_migrated(n);
2449 halfword t = tex_tail_of_node_list(h);
2450 nodelib_push_direct_or_nil(L, h);
2451 nodelib_push_direct_or_nil(L, t);
2452 return 2;
2453 }
2454 case choice_node:
2455 if (node_subtype(n) == discretionary_choice_subtype) {
2456 nodelib_push_direct_or_nil(L, choice_pre_break(n));
2457 return 1;
2458 } else {
2459 break;
2460 }
2461 }
2462 }
2463 return 0;
2464}
2465
2466static int nodelib_direct_getpost(lua_State *L)
2467{
2468 halfword n = nodelib_valid_direct_from_index(L, 1);
2469 if (n) {
2470 switch (node_type(n)) {
2471 case disc_node:
2472 nodelib_push_direct_or_nil(L, disc_post_break_head(n));
2473 nodelib_push_direct_or_nil(L, disc_post_break_tail(n));
2474 return 2;
2475 case hlist_node:
2476 case vlist_node:
2477 {
2478 halfword h = box_post_migrated(n);
2479 halfword t = tex_tail_of_node_list(h);
2480 nodelib_push_direct_or_nil(L, h);
2481 nodelib_push_direct_or_nil(L, t);
2482 return 2;
2483 }
2484 case choice_node:
2485 if (node_subtype(n) == discretionary_choice_subtype) {
2486 nodelib_push_direct_or_nil(L, choice_post_break(n));
2487 return 1;
2488 } else {
2489 break;
2490 }
2491 }
2492 }
2493 return 0;
2494}
2495
2496static int nodelib_direct_getreplace(lua_State *L)
2497{
2498 halfword n = nodelib_valid_direct_from_index(L, 1);
2499 if (n) {
2500 switch (node_type(n)) {
2501 case disc_node:
2502 nodelib_push_direct_or_nil(L, disc_no_break_head(n));
2503 nodelib_push_direct_or_nil(L, disc_no_break_tail(n));
2504 return 2;
2505 case choice_node:
2506 if (node_subtype(n) == discretionary_choice_subtype) {
2507 nodelib_push_direct_or_nil(L, choice_no_break(n));
2508 return 1;
2509 } else {
2510 break;
2511 }
2512 }
2513 }
2514 return 0;
2515}
2516
2517
2518
2519
2520
2521# define setpre_usage (disc_usage | hlist_usage | vlist_usage)
2522# define setpost_usage setpre_usage
2523# define setreplace_usage (disc_usage)
2524
2525static int nodelib_direct_setpre(lua_State *L)
2526{
2527 halfword n = nodelib_valid_direct_from_index(L, 1);
2528 if (n) {
2529 halfword m = (lua_gettop(L) > 1) ? nodelib_valid_direct_from_index(L, 2) : null;
2530 switch (node_type(n)) {
2531 case disc_node:
2532 tex_set_disc_field(n, pre_break_code, m);
2533 break;
2534 case hlist_node:
2535 case vlist_node:
2536 box_pre_migrated(n) = m;
2537 break;
2538 }
2539 }
2540 return 0;
2541}
2542
2543static int nodelib_direct_setpost(lua_State *L)
2544{
2545 halfword n = nodelib_valid_direct_from_index(L, 1);
2546 if (n) {
2547 halfword m = (lua_gettop(L) > 1) ? nodelib_valid_direct_from_index(L, 2) : null;
2548 switch (node_type(n)) {
2549 case disc_node:
2550 tex_set_disc_field(n, post_break_code, m);
2551 break;
2552 case hlist_node:
2553 case vlist_node:
2554 box_post_migrated(n) = m;
2555 break;
2556 }
2557 }
2558 return 0;
2559}
2560
2561static int nodelib_direct_setreplace(lua_State *L)
2562{
2563 halfword n = nodelib_valid_direct_from_index(L, 1);
2564 if (n && node_type(n) == disc_node) {
2565 halfword m = (lua_gettop(L) > 1) ? nodelib_valid_direct_from_index(L, 2) : null;
2566 tex_set_disc_field(n, no_break_code, m);
2567 }
2568 return 0;
2569}
2570
2571
2572
2573
2574
2575
2576# define getwidth_usage (hlist_usage | vlist_usage | unset_usage | align_record_usage | rule_usage | glue_usage | glue_spec_usage | glyph_usage | kern_usage | math_usage)
2577
2578static int nodelib_direct_getwidth(lua_State *L)
2579{
2580 halfword n = nodelib_valid_direct_from_index(L, 1);
2581 if (n) {
2582 switch (node_type(n)) {
2583 case hlist_node:
2584 case vlist_node:
2585 case unset_node:
2586 lua_pushinteger(L, box_width(n));
2587 break;
2588 case align_record_node:
2589 lua_pushinteger(L, box_width(n));
2590 if (lua_toboolean(L, 2)) {
2591 lua_pushinteger(L, box_size(n));
2592 return 2;
2593 }
2594 break;
2595 case rule_node:
2596 lua_pushinteger(L, rule_width(n));
2597 break;
2598 case glue_node:
2599 case glue_spec_node:
2600 lua_pushinteger(L, glue_amount(n));
2601 break;
2602 case glyph_node:
2603 lua_pushnumber(L, tex_glyph_width(n));
2604 if (lua_toboolean(L, 2)) {
2605 lua_pushinteger(L, glyph_expansion(n));
2606 return 2;
2607 }
2608 break;
2609 case kern_node:
2610 lua_pushinteger(L, kern_amount(n));
2611 if (lua_toboolean(L, 2)) {
2612 lua_pushinteger(L, kern_expansion(n));
2613 return 2;
2614 }
2615 break;
2616 case math_node:
2617 lua_pushinteger(L, math_amount(n));
2618 break;
2619 default:
2620 lua_pushnil(L);
2621 break;
2622 }
2623 } else {
2624 lua_pushnil(L);
2625 }
2626 return 1;
2627}
2628
2629# define setwidth_usage (hlist_usage | vlist_usage | unset_usage | align_record_usage | rule_usage | glue_usage | glue_spec_usage | kern_usage | math_usage)
2630
2631static int nodelib_direct_setwidth(lua_State *L)
2632{
2633 halfword n = nodelib_valid_direct_from_index(L, 1);
2634 if (n) {
2635 switch (node_type(n)) {
2636 case hlist_node:
2637 case vlist_node:
2638 case unset_node:
2639 case align_record_node:
2640 box_width(n) = lua_type(L, 2) == LUA_TNUMBER ? lmt_roundnumber(L, 2) : 0;
2641 if (lua_type(L, 3) == LUA_TNUMBER) {
2642 box_size(n) = lmt_roundnumber(L, 3);
2643 box_package_state(n) = package_dimension_size_set;
2644 }
2645 break;
2646 case rule_node:
2647 rule_width(n) = lua_type(L, 2) == LUA_TNUMBER ? lmt_roundnumber(L, 2) : 0;
2648 break;
2649 case glue_node:
2650 case glue_spec_node:
2651 glue_amount(n) = lua_type(L, 2) == LUA_TNUMBER ? lmt_roundnumber(L, 2) : 0;
2652 break;
2653 case kern_node:
2654 kern_amount(n) = lua_type(L, 2) == LUA_TNUMBER ? lmt_roundnumber(L, 2) : 0;
2655 break;
2656 case math_node:
2657 math_amount(n) = lua_type(L, 2) == LUA_TNUMBER ? lmt_roundnumber(L, 2) : 0;
2658 break;
2659 }
2660 }
2661 return 0;
2662}
2663
2664
2665
2666
2667# define getheight_usage (hlist_usage | vlist_usage | unset_usage | rule_usage | insert_usage | glyph_usage | fence_usage)
2668
2669static int nodelib_direct_getheight(lua_State *L)
2670{
2671 halfword n = nodelib_valid_direct_from_index(L, 1);
2672 if (n) {
2673 switch (node_type(n)) {
2674 case hlist_node:
2675 case vlist_node:
2676 case unset_node:
2677 lua_pushinteger(L, box_height(n));
2678 break;
2679 case rule_node:
2680 lua_pushinteger(L, rule_height(n));
2681 break;
2682 case insert_node:
2683 lua_pushinteger(L, insert_total_height(n));
2684 break;
2685 case glyph_node:
2686 lua_pushinteger(L, tex_glyph_height(n));
2687 break;
2688 case fence_noad:
2689 lua_pushinteger(L, noad_height(n));
2690 break;
2691 default:
2692 lua_pushnil(L);
2693 break;
2694 }
2695 } else {
2696 lua_pushnil(L);
2697 }
2698 return 1;
2699}
2700
2701# define setheight_usage (hlist_usage | vlist_usage | unset_usage | rule_usage | insert_usage | fence_usage)
2702
2703static int nodelib_direct_setheight(lua_State *L)
2704{
2705 halfword n = nodelib_valid_direct_from_index(L, 1);
2706 if (n) {
2707 halfword h = 0;
2708 if (lua_type(L, 2) == LUA_TNUMBER) {
2709 h = lmt_roundnumber(L, 2);
2710 }
2711 switch (node_type(n)) {
2712 case hlist_node:
2713 case vlist_node:
2714 case unset_node:
2715 box_height(n) = h;
2716 break;
2717 case rule_node:
2718 rule_height(n) = h;
2719 break;
2720 case insert_node:
2721 insert_total_height(n) = h;
2722 break;
2723 case fence_noad:
2724 noad_height(n) = h;
2725 break;
2726 }
2727 }
2728 return 0;
2729}
2730
2731
2732
2733
2734# define getdepth_usage getheight_usage
2735
2736static int nodelib_direct_getdepth(lua_State *L)
2737{
2738 halfword n = nodelib_valid_direct_from_index(L, 1);
2739 if (n) {
2740 switch (node_type(n)) {
2741 case hlist_node:
2742 case vlist_node:
2743 case unset_node:
2744 lua_pushinteger(L, box_depth(n));
2745 break;
2746 case rule_node:
2747 lua_pushinteger(L, rule_depth(n));
2748 break;
2749 case insert_node:
2750 lua_pushinteger(L, insert_max_depth(n));
2751 break;
2752 case glyph_node:
2753 lua_pushinteger(L, tex_glyph_depth(n));
2754 break;
2755 case fence_noad:
2756 lua_pushinteger(L, noad_depth(n));
2757 break;
2758 default:
2759 lua_pushnil(L);
2760 break;
2761 }
2762 } else {
2763 lua_pushnil(L);
2764 }
2765 return 1;
2766}
2767
2768# define setdepth_usage setheight_usage
2769
2770static int nodelib_direct_setdepth(lua_State *L)
2771{
2772 halfword n = nodelib_valid_direct_from_index(L, 1);
2773 if (n) {
2774 halfword d = 0;
2775 if (lua_type(L, 2) == LUA_TNUMBER) {
2776 d = lmt_roundnumber(L, 2);
2777 }
2778 switch (node_type(n)) {
2779 case hlist_node:
2780 case vlist_node:
2781 case unset_node:
2782 box_depth(n) = d;
2783 break;
2784 case rule_node:
2785 rule_depth(n) = d;
2786 break;
2787 case insert_node:
2788 insert_max_depth(n) = d;
2789 break;
2790 case fence_noad:
2791 noad_depth(n) = d;
2792 break;
2793 }
2794 }
2795 return 0;
2796}
2797
2798
2799
2800
2801# define gettotal_usage (hlist_usage | vlist_usage | unset_usage | rule_usage | insert_usage | glyph_usage | fence_usage)
2802# define settotal_usage insert_usage
2803
2804static int nodelib_direct_gettotal(lua_State *L)
2805{
2806 halfword n = nodelib_valid_direct_from_index(L, 1);
2807 if (n) {
2808 switch (node_type(n)) {
2809 case hlist_node:
2810 case vlist_node:
2811 case unset_node:
2812 lua_pushinteger(L, (lua_Integer) box_total(n));
2813 break;
2814 case rule_node:
2815 lua_pushinteger(L, (lua_Integer) rule_total(n));
2816 break;
2817 case insert_node:
2818 lua_pushinteger(L, (lua_Integer) insert_total_height(n));
2819 break;
2820 case glyph_node:
2821 lua_pushinteger(L, (lua_Integer) tex_glyph_total(n));
2822 break;
2823 case fence_noad:
2824 lua_pushinteger(L, (lua_Integer) noad_total(n));
2825 break;
2826 default:
2827 lua_pushnil(L);
2828 break;
2829 }
2830 } else {
2831 lua_pushnil(L);
2832 }
2833 return 1;
2834}
2835
2836static int nodelib_direct_settotal(lua_State *L)
2837{
2838 halfword n = nodelib_valid_direct_from_index(L, 1);
2839 if (n) {
2840 switch (node_type(n)) {
2841 case insert_node:
2842 insert_total_height(n) = lua_type(L, 2) == LUA_TNUMBER ? (halfword) lmt_roundnumber(L,2) : 0;
2843 break;
2844 }
2845 }
2846 return 0;
2847}
2848
2849
2850
2851
2852# define getshift_usage (hlist_usage | vlist_usage)
2853# define setshift_usage getshift_usage
2854
2855static int nodelib_direct_getshift(lua_State *L)
2856{
2857 halfword n = nodelib_valid_direct_from_index(L, 1);
2858 if (n) {
2859 switch (node_type(n)) {
2860 case hlist_node:
2861 case vlist_node:
2862 lua_pushinteger(L, box_shift_amount(n));
2863 return 1;
2864 }
2865 }
2866 return 0;
2867}
2868
2869static int nodelib_direct_setshift(lua_State *L)
2870{
2871 halfword n = nodelib_valid_direct_from_index(L, 1);
2872 if (n) {
2873 switch (node_type(n)) {
2874 case hlist_node:
2875 case vlist_node:
2876 if (lua_type(L, 2) == LUA_TNUMBER) {
2877 box_shift_amount(n) = (halfword) lmt_roundnumber(L,2);
2878 } else {
2879 box_shift_amount(n) = 0;
2880 }
2881 break;
2882 }
2883 }
2884 return 0;
2885}
2886
2887
2888
2889
2890# define getindex_usage (hlist_usage | vlist_usage | insert_usage | mark_usage | adjust_usage)
2891# define setindex_usage getindex_usage
2892
2893static int nodelib_direct_getindex(lua_State* L)
2894{
2895 halfword n = nodelib_valid_direct_from_index(L, 1);
2896 if (n) {
2897 switch (node_type(n)) {
2898 case hlist_node:
2899 case vlist_node:
2900 lua_pushinteger(L, box_index(n));
2901 break;
2902 case insert_node:
2903 lua_pushinteger(L, insert_index(n));
2904 break;
2905 case mark_node:
2906 lua_pushinteger(L, mark_index(n));
2907 break;
2908 case adjust_node:
2909 lua_pushinteger(L, adjust_index(n));
2910 break;
2911 }
2912 } else {
2913 lua_pushnil(L);
2914 }
2915 return 1;
2916}
2917
2918static int nodelib_direct_setindex(lua_State* L)
2919{
2920 halfword n = nodelib_valid_direct_from_index(L, 1);
2921 if (n) {
2922 switch (node_type(n)) {
2923 case hlist_node:
2924 case vlist_node:
2925 {
2926 halfword index = lmt_tohalfword(L, 2);
2927 if (tex_valid_box_index(index)) {
2928 box_index(n) = index;
2929 } else {
2930
2931 }
2932 break;
2933 }
2934 case insert_node:
2935 {
2936 halfword index = lmt_tohalfword(L, 2);
2937 if (tex_valid_insert_id(index)) {
2938 insert_index(n) = index;
2939 } else {
2940
2941 }
2942 break;
2943 }
2944 case mark_node:
2945 {
2946 halfword index = lmt_tohalfword(L, 2);
2947 if (tex_valid_mark(index)) {
2948 mark_index(n) = index;
2949 }
2950 }
2951 break;
2952 case adjust_node:
2953 {
2954 halfword index = lmt_tohalfword(L, 2);
2955 if (tex_valid_adjust_index(index)) {
2956 adjust_index(n) = index;
2957 }
2958 }
2959 break;
2960 }
2961 } else {
2962 lua_pushnil(L);
2963 }
2964 return 1;
2965}
2966
2967
2968
2969
2970
2971# define hasgeometry_usage (hlist_usage | vlist_usage)
2972# define getgeometry_usage hasgeometry_usage
2973# define setgeometry_usage hasgeometry_usage
2974
2975static int nodelib_direct_hasgeometry(lua_State* L)
2976{
2977 halfword n = nodelib_valid_direct_from_index(L, 1);
2978 if (n) {
2979 switch (node_type(n)) {
2980 case hlist_node:
2981 case vlist_node:
2982 if (box_geometry(n)) {
2983 lua_pushinteger(L, box_geometry(n));
2984 return 1;
2985 }
2986 }
2987 }
2988 lua_pushboolean(L, 0);
2989 return 1;
2990}
2991
2992static int nodelib_direct_getgeometry(lua_State* L)
2993{
2994 halfword n = nodelib_valid_direct_from_index(L, 1);
2995 if (n) {
2996 switch (node_type(n)) {
2997 case hlist_node:
2998 case vlist_node:
2999 if (box_geometry(n)) {
3000 lua_pushinteger(L, box_geometry(n));
3001 if (lua_toboolean(L, 2)) {
3002 lua_pushboolean(L, tex_has_box_geometry(n, offset_geometry));
3003 lua_pushboolean(L, tex_has_box_geometry(n, orientation_geometry));
3004 lua_pushboolean(L, tex_has_box_geometry(n, anchor_geometry));
3005 lua_pushinteger(L, checked_direction_value(box_dir(n)));
3006 return 5;
3007 } else {
3008 return 1;
3009 }
3010 } else if (lua_toboolean(L, 2)) {
3011 lua_pushboolean(L, 0);
3012 lua_pushboolean(L, 0);
3013 lua_pushboolean(L, 0);
3014 lua_pushboolean(L, 0);
3015 lua_pushinteger(L, checked_direction_value(box_dir(n)));
3016 return 5;
3017 }
3018 break;
3019 }
3020 }
3021 lua_pushboolean(L, 0);
3022 return 1;
3023}
3024
3025static int nodelib_direct_setgeometry(lua_State* L)
3026{
3027 halfword n = nodelib_valid_direct_from_index(L, 1);
3028 if (n) {
3029 switch (node_type(n)) {
3030 case hlist_node:
3031 case vlist_node:
3032 box_geometry(n) = (singleword) lmt_tohalfword(L, 2);
3033 break;
3034 }
3035 }
3036 return 0;
3037}
3038
3039
3040
3041
3042# define getorientation_usage (hlist_usage |vlist_usage)
3043# define setorientation_usage getorientation_usage
3044
3045static int nodelib_direct_getorientation(lua_State *L)
3046{
3047 halfword n = nodelib_valid_direct_from_index(L, 1);
3048 if (n) {
3049 switch (node_type(n)) {
3050 case hlist_node:
3051 case vlist_node:
3052 lua_pushinteger(L, box_orientation(n));
3053 lua_pushinteger(L, box_x_offset(n));
3054 lua_pushinteger(L, box_y_offset(n));
3055 lua_pushinteger(L, box_w_offset(n));
3056 lua_pushinteger(L, box_h_offset(n));
3057 lua_pushinteger(L, box_d_offset(n));
3058 return 6;
3059 }
3060 }
3061 return 0;
3062}
3063
3064static int nodelib_direct_setorientation(lua_State *L)
3065{
3066 halfword n = nodelib_valid_direct_from_index(L, 1);
3067 if (n) {
3068 switch (node_type(n)) {
3069 case hlist_node:
3070 case vlist_node:
3071 switch (lua_type(L, 2)) {
3072 case LUA_TNUMBER:
3073 box_orientation(n) = lmt_tohalfword(L, 2);
3074 break;
3075 case LUA_TBOOLEAN:
3076 if (lua_toboolean(L, 2)) {
3077 break;
3078 }
3079 default:
3080 box_orientation(n) = 0;
3081 break;
3082 }
3083 switch (lua_type(L, 3)) {
3084 case LUA_TNUMBER:
3085 box_x_offset(n) = lmt_tohalfword(L, 3);
3086 break;
3087 case LUA_TBOOLEAN:
3088 if (lua_toboolean(L, 3)) {
3089 break;
3090 }
3091 default:
3092 box_x_offset(n) = 0;
3093 break;
3094 }
3095 switch (lua_type(L, 4)) {
3096 case LUA_TNUMBER:
3097 box_y_offset(n) = lmt_tohalfword(L, 4);
3098 break;
3099 case LUA_TBOOLEAN:
3100 if (lua_toboolean(L, 4)) {
3101 break;
3102 }
3103 default:
3104 box_y_offset(n) = 0;
3105 break;
3106 }
3107 switch (lua_type(L, 5)) {
3108 case LUA_TNUMBER:
3109 box_w_offset(n) = lmt_tohalfword(L, 5);
3110 break;
3111 case LUA_TBOOLEAN:
3112 if (lua_toboolean(L, 5)) {
3113 break;
3114 }
3115 default:
3116 box_w_offset(n) = 0;
3117 break;
3118 }
3119 switch (lua_type(L, 6)) {
3120 case LUA_TNUMBER:
3121 box_h_offset(n) = lmt_tohalfword(L, 6);
3122 break;
3123 case LUA_TBOOLEAN:
3124 if (lua_toboolean(L, 6)) {
3125 break;
3126 }
3127 default:
3128 box_h_offset(n) = 0;
3129 break;
3130 }
3131 switch (lua_type(L, 7)) {
3132 case LUA_TNUMBER:
3133 box_d_offset(n) = lmt_tohalfword(L, 7);
3134 break;
3135 case LUA_TBOOLEAN:
3136 if (lua_toboolean(L, 7)) {
3137 break;
3138 }
3139 default:
3140 box_d_offset(n) = 0;
3141 break;
3142 }
3143 tex_check_box_geometry(n);
3144 break;
3145 }
3146 }
3147 return 0;
3148}
3149
3150
3151
3152
3153# define setoptions_usage (glyph_usage | disc_usage | glue_usage | rule_usage | math_usage | penalty_usage | simple_usage | radical_usage | fraction_usage | accent_usage | math_char_usage | math_text_char_usage)
3154# define getoptions_usage setoptions_usage
3155
3156static int nodelib_direct_getoptions(lua_State *L)
3157{
3158 halfword n = nodelib_valid_direct_from_index(L, 1);
3159 if (n) {
3160 switch (node_type(n)) {
3161 case glyph_node:
3162 lua_pushinteger(L, glyph_options(n));
3163 return 1;
3164 case disc_node:
3165 lua_pushinteger(L, disc_options(n));
3166 return 1;
3167 case glue_node:
3168 lua_pushinteger(L, glue_options(n));
3169 return 1;
3170 case rule_node:
3171 lua_pushinteger(L, rule_options(n));
3172 return 1;
3173 case math_node:
3174 lua_pushinteger(L, math_options(n));
3175 return 1;
3176 case penalty_node:
3177 lua_pushinteger(L, penalty_options(n));
3178 return 1;
3179 case simple_noad:
3180 case radical_noad:
3181 case fraction_noad:
3182 case accent_noad:
3183 case fence_noad:
3184 lua_pushinteger(L, noad_options(n));
3185 return 1;
3186 case math_char_node:
3187 case math_text_char_node:
3188 lua_pushinteger(L, kernel_math_options(n));
3189 return 1;
3190 }
3191 }
3192 return 0;
3193}
3194
3195static int nodelib_direct_setoptions(lua_State *L)
3196{
3197 halfword n = nodelib_valid_direct_from_index(L, 1);
3198 if (n) {
3199 switch (node_type(n)) {
3200 case glyph_node:
3201 set_glyph_options(n, lmt_tohalfword(L, 2) & glyph_option_valid);
3202 break;
3203 case disc_node:
3204 set_disc_options(n, lmt_tohalfword(L, 2) & disc_option_valid);
3205 break;
3206 case glue_node:
3207 tex_add_glue_option(n, lmt_tohalfword(L, 2));
3208 return 1;
3209 case rule_node:
3210 set_rule_options(n, lmt_tohalfword(L, 2) & rule_option_valid);
3211 break;
3212 case math_node:
3213 tex_add_math_option(n, lmt_tohalfword(L, 2));
3214 return 1;
3215 case penalty_node:
3216 tex_add_penalty_option(n, lmt_tohalfword(L, 2));
3217 return 1;
3218 case simple_noad:
3219 case radical_noad:
3220 case fraction_noad:
3221 case accent_noad:
3222 case fence_noad:
3223 noad_options(n) = lmt_tofullword(L, 2);
3224 break;
3225 case math_char_node:
3226 case math_text_char_node:
3227 kernel_math_options(n) = lmt_tohalfword(L, 2);
3228 break;
3229 }
3230 }
3231 return 0;
3232}
3233
3234
3235
3236
3237# define getwhd_usage (hlist_usage | vlist_usage | unset_usage | rule_usage | glyph_usage | glue_usage )
3238# define setwhd_usage getwhd_usage
3239
3240static int nodelib_direct_getwhd(lua_State *L)
3241{
3242 halfword n = nodelib_valid_direct_from_index(L, 1);
3243 if (n) {
3244 AGAIN:
3245 switch (node_type(n)) {
3246 case hlist_node:
3247 case vlist_node:
3248 case unset_node:
3249 lua_pushinteger(L, box_width(n));
3250 lua_pushinteger(L, box_height(n));
3251 lua_pushinteger(L, box_depth(n));
3252 return 3;
3253 case rule_node:
3254 lua_pushinteger(L, rule_width(n));
3255 lua_pushinteger(L, rule_height(n));
3256 lua_pushinteger(L, rule_depth(n));
3257 return 3;
3258 case glyph_node:
3259
3260 lua_pushinteger(L, tex_glyph_width(n));
3261 lua_pushinteger(L, tex_glyph_height(n));
3262 lua_pushinteger(L, tex_glyph_depth(n));
3263 if (lua_toboolean(L,2)) {
3264 lua_pushinteger(L, glyph_expansion(n));
3265 return 4;
3266 } else {
3267 return 3;
3268 }
3269 case glue_node:
3270 n = glue_leader_ptr(n);
3271 if (n) {
3272 goto AGAIN;
3273 } else {
3274 break;
3275 }
3276 }
3277 }
3278 return 0;
3279}
3280
3281static int nodelib_direct_setwhd(lua_State *L)
3282{
3283 halfword n = nodelib_valid_direct_from_index(L, 1);
3284 if (n) {
3285 AGAIN:
3286 switch (node_type(n)) {
3287 case hlist_node:
3288 case vlist_node:
3289 case unset_node:
3290 {
3291 int top = lua_gettop(L) ;
3292 if (top > 1) {
3293 if ((lua_type(L, 2) == LUA_TNUMBER)) {
3294 box_width(n) = (halfword) lmt_roundnumber(L, 2);
3295 } else {
3296
3297 }
3298 if (top > 2) {
3299 if ((lua_type(L, 3) == LUA_TNUMBER)) {
3300 box_height(n) = (halfword) lmt_roundnumber(L, 3);
3301 } else {
3302
3303 }
3304 if (top > 3) {
3305 if ((lua_type(L, 4) == LUA_TNUMBER)) {
3306 box_depth(n) = (halfword) lmt_roundnumber(L, 4);
3307 } else {
3308
3309 }
3310 }
3311 }
3312 }
3313 }
3314 break;
3315 case rule_node:
3316 {
3317 int top = lua_gettop(L) ;
3318 if (top > 1) {
3319 if ((lua_type(L, 2) == LUA_TNUMBER)) {
3320 rule_width(n) = (halfword) lmt_roundnumber(L, 2);
3321 } else {
3322
3323 }
3324 if (top > 2) {
3325 if ((lua_type(L, 3) == LUA_TNUMBER)) {
3326 rule_height(n) = (halfword) lmt_roundnumber(L, 3);
3327 } else {
3328
3329 }
3330 if (top > 3) {
3331 if ((lua_type(L, 4) == LUA_TNUMBER)) {
3332 rule_depth(n) = (halfword) lmt_roundnumber(L, 4);
3333 } else {
3334
3335 }
3336 }
3337 }
3338 }
3339 }
3340 break;
3341 case glue_node:
3342 n = glue_leader_ptr(n);
3343 if (n) {
3344 goto AGAIN;
3345 } else {
3346 break;
3347 }
3348 }
3349 }
3350 return 0;
3351}
3352
3353
3354
3355# define getcornerkerns_usage glyph_usage
3356
3357static int nodelib_direct_getcornerkerns(lua_State *L)
3358{
3359 halfword n = nodelib_valid_direct_from_index(L, 1);
3360 if (n && node_type(n) == glyph_node) {
3361 scaledkrn krn = tex_char_corner_kerns_from_glyph(n);
3362 lua_pushinteger(L, krn.bl);
3363 lua_pushinteger(L, krn.br);
3364 lua_pushinteger(L, krn.tl);
3365 lua_pushinteger(L, krn.tr);
3366 return 4;
3367 }
3368 return 0;
3369}
3370
3371
3372
3373# define hasdimensions_usage (hlist_usage | vlist_usage | unset_usage | rule_usage | glyph_usage | glue_usage)
3374
3375static int nodelib_direct_hasdimensions(lua_State *L)
3376{
3377 int b = 0;
3378 halfword n = nodelib_valid_direct_from_index(L, 1);
3379 if (n) {
3380 switch (node_type(n)) {
3381 case hlist_node:
3382 case vlist_node:
3383 case unset_node:
3384 b = (box_width(n) > 0) || (box_total(n) > 0);
3385 break;
3386 case rule_node:
3387 b = (rule_width(n) > 0) || (rule_total(n) > 0);
3388 break;
3389 case glyph_node:
3390 b = tex_glyph_has_dimensions(n);
3391 break;
3392 case glue_node:
3393 {
3394 halfword l = glue_leader_ptr(n);
3395 if (l) {
3396 switch (node_type(l)) {
3397 case hlist_node:
3398 case vlist_node:
3399 b = (box_width(l) > 0) || (box_total(l) > 0);
3400 break;
3401 case rule_node:
3402 b = (rule_width(l) > 0) || (rule_total(l) > 0);
3403 break;
3404 }
3405 }
3406 }
3407 break;
3408 }
3409 }
3410 lua_pushboolean(L, b);
3411 return 1;
3412}
3413
3414
3422
3423
3424
3425# define getglyphdimensions_usage glyph_usage
3426
3427static int nodelib_direct_getglyphdimensions(lua_State *L)
3428{
3429 halfword n = nodelib_valid_direct_from_index(L, 1);
3430 if (n && node_type(n) == glyph_node) {
3431 scaledwhd whd = tex_glyph_dimensions_ex(n);
3432 lua_pushinteger(L, whd.wd);
3433 lua_pushinteger(L, whd.ht);
3434 lua_pushinteger(L, whd.dp);
3435 lua_pushinteger(L, glyph_expansion(n));
3436 nodelib_aux_pushxyscales(L, n);
3437 lua_pushnumber(L, (double) glyph_slant(n) / 1000);
3438 lua_pushnumber(L, (double) glyph_weight(n) / 1000);
3439
3440 return 8;
3441 } else {
3442 return 0;
3443 }
3444}
3445
3446
3447
3448# define getkerndimension_usage kern_usage
3449
3450static int nodelib_direct_getkerndimension(lua_State *L)
3451{
3452 halfword n = nodelib_valid_direct_from_index(L, 1);
3453 if (n && node_type(n) == kern_node) {
3454 lua_pushinteger(L, tex_kern_dimension_ex(n));
3455 return 1;
3456 } else {
3457 return 0;
3458 }
3459}
3460
3461
3462
3463# define getlistdimensions_usage (hlist_usage | vlist_usage)
3464
3465static int nodelib_direct_getlistdimensions(lua_State *L)
3466{
3467 halfword n = nodelib_valid_direct_from_index(L, 1);
3468 if (n) {
3469 switch (node_type(n)) {
3470
3471 case hlist_node:
3472 case vlist_node:
3473 lua_pushinteger(L, box_width(n));
3474 lua_pushinteger(L, box_height(n));
3475 lua_pushinteger(L, box_depth(n));
3476 lua_pushinteger(L, box_shift_amount(n));
3477 nodelib_push_direct_or_nil_node_prev(L, box_list(n));
3478 nodelib_push_direct_or_nil(L, box_except(n));
3479 return 6;
3480 }
3481 }
3482 return 0;
3483}
3484
3485
3486
3487
3488# define getruledimensions_usage rule_usage
3489# define setruledimensions_usage rule_usage
3490
3491static int nodelib_direct_getruledimensions(lua_State *L)
3492{
3493 halfword n = nodelib_valid_direct_from_index(L, 1);
3494 if (n && node_type(n) == rule_node) {
3495 if (node_subtype(n) == virtual_rule_subtype) {
3496 lua_pushinteger(L, rule_virtual_width(n));
3497 lua_pushinteger(L, rule_virtual_height(n));
3498 lua_pushinteger(L, rule_virtual_depth(n));
3499 lua_pushboolean(L, 1);
3500 } else {
3501 lua_pushinteger(L, rule_width(n));
3502 lua_pushinteger(L, rule_height(n));
3503 lua_pushinteger(L, rule_depth(n));
3504 lua_pushboolean(L, 0);
3505 }
3506 return 4;
3507 } else {
3508 return 0;
3509 }
3510}
3511
3512static int nodelib_direct_setruledimensions(lua_State *L)
3513{
3514 halfword n = nodelib_valid_direct_from_index(L, 1);
3515 if (n && node_type(n) == rule_node) {
3516 scaled wd = (scaled) lmt_roundnumber(L, 2);
3517 scaled ht = (scaled) lmt_roundnumber(L, 3);
3518 scaled dp = (scaled) lmt_roundnumber(L, 4);
3519 if (node_subtype(n) == virtual_rule_subtype) {
3520 rule_virtual_width(n) = wd;
3521 rule_virtual_height(n) = ht;
3522 rule_virtual_depth(n) = dp;
3523 rule_width(n) = 0;
3524 rule_height(n) = 0;
3525 rule_depth(n) = 0;
3526 } else {
3527 rule_width(n) = wd;
3528 rule_height(n) = ht;
3529 rule_depth(n) = dp;
3530 }
3531 if (lua_type(L, 5) == LUA_TNUMBER) {
3532 rule_data(n) = (halfword) lmt_roundnumber(L, 5);
3533 }
3534 }
3535 return 0;
3536}
3537
3538
3539
3540
3541# define getlist_usage (hlist_usage | vlist_usage | unset_usage | sub_box_usage | sub_mlist_usage | insert_usage | adjust_usage)
3542# define setlist_usage getlist_usage
3543
3544static int nodelib_direct_getlist(lua_State *L)
3545{
3546 halfword n = nodelib_valid_direct_from_index(L, 1);
3547 if (n) {
3548 switch (node_type(n)) {
3549 case hlist_node:
3550 case vlist_node:
3551 case unset_node:
3552 case align_record_node:
3553 nodelib_push_direct_or_nil_node_prev(L, box_list(n));
3554 break;
3555 case sub_box_node:
3556 case sub_mlist_node:
3557 nodelib_push_direct_or_nil_node_prev(L, kernel_math_list(n));
3558 break;
3559 case insert_node:
3560
3561 nodelib_push_direct_or_nil_node_prev(L, insert_list(n));
3562 break;
3563 case adjust_node:
3564 nodelib_push_direct_or_nil_node_prev(L, adjust_list(n));
3565 break;
3566 default:
3567 lua_pushnil(L);
3568 break;
3569 }
3570 } else {
3571 lua_pushnil(L);
3572 }
3573 return 1;
3574}
3575
3576static int nodelib_direct_setlist(lua_State *L)
3577{
3578 halfword n = nodelib_valid_direct_from_index(L, 1);
3579 if (n) {
3580 switch (node_type(n)) {
3581 case hlist_node:
3582 case vlist_node:
3583 case unset_node:
3584 box_list(n) = nodelib_valid_direct_from_index(L, 2);
3585 break;
3586 case sub_box_node:
3587 case sub_mlist_node:
3588 kernel_math_list(n) = nodelib_valid_direct_from_index(L, 2);
3589 break;
3590 case insert_node:
3591
3592 insert_list(n) = nodelib_valid_direct_from_index(L, 2);
3593 break;
3594 case adjust_node:
3595 adjust_list(n) = nodelib_valid_direct_from_index(L, 2);
3596 break;
3597 }
3598 }
3599 return 0;
3600}
3601
3602
3603
3604
3605# define getexcept_usage (hlist_usage | vlist_usage | unset_usage)
3606# define setexcept_usage getexcept_usage
3607
3608static int nodelib_direct_getexcept(lua_State *L)
3609{
3610 halfword n = nodelib_valid_direct_from_index(L, 1);
3611 if (n) {
3612 switch (node_type(n)) {
3613 case hlist_node:
3614 case vlist_node:
3615 case unset_node:
3616 default:
3617 nodelib_push_direct_or_nil(L, box_except(n));
3618 lua_pushinteger(L, box_exdepth(n));
3619 return 2;
3620 }
3621 }
3622 lua_pushnil(L);
3623 lua_pushnil(L);
3624 return 2;
3625}
3626
3627static int nodelib_direct_setexcept(lua_State *L)
3628{
3629 halfword n = nodelib_valid_direct_from_index(L, 1);
3630 if (n) {
3631 switch (node_type(n)) {
3632 case hlist_node:
3633 case vlist_node:
3634 case unset_node:
3635 box_except(n) = nodelib_valid_direct_from_index(L, 2);
3636 box_exdepth(n) = lmt_optinteger(L, 3, 0);
3637 break;
3638 }
3639 }
3640 return 0;
3641}
3642
3643
3644
3645
3646# define getleader_usage glue_usage
3647# define setleader_usage getleader_usage
3648
3649static int nodelib_direct_getleader(lua_State *L)
3650{
3651 halfword n = nodelib_valid_direct_from_index(L, 1);
3652 if (n && node_type(n) == glue_node) {
3653 nodelib_push_direct_or_nil(L, glue_leader_ptr(n));
3654 } else {
3655 lua_pushnil(L);
3656 }
3657 return 1;
3658}
3659
3660static int nodelib_direct_setleader(lua_State *L)
3661{
3662 halfword n = nodelib_valid_direct_from_index(L, 1);
3663 if (n && node_type(n) == glue_node) {
3664 glue_leader_ptr(n) = nodelib_valid_direct_from_index(L, 2);
3665 }
3666 return 0;
3667}
3668
3669
3670
3671
3672
3678
3679# define getdata_usage (glyph_usage | rule_usage | glue_usage | boundary_usage | attribute_usage | mark_usage)
3680# define setdata_usage getdata_usage
3681
3682static int nodelib_direct_getdata(lua_State *L)
3683{
3684 halfword n = nodelib_valid_direct_from_index(L, 1);
3685 if (n) {
3686 switch (node_type(n)) {
3687 case glyph_node:
3688 lua_pushinteger(L, glyph_data(n));
3689 return 1;
3690 case rule_node:
3691 lua_pushinteger(L, rule_data(n));
3692 return 1;
3693 case glue_node:
3694 lua_pushinteger(L, glue_data(n));
3695 return 1;
3696 case boundary_node:
3697 lua_pushinteger(L, boundary_data(n));
3698 lua_pushinteger(L, boundary_reserved(n));
3699 return 2;
3700 case insert_node:
3701 lua_pushinteger(L, insert_identifier(n));
3702
3703 return 1;
3704 case attribute_node:
3705 switch (node_subtype(n)) {
3706 case attribute_list_subtype:
3707 nodelib_push_attribute_data(L, n);
3708 return 1;
3709 case attribute_value_subtype:
3710
3711 lua_pushinteger(L, attribute_index(n));
3712 lua_pushinteger(L, attribute_value(n));
3713 return 2;
3714 default:
3715
3716 break;
3717 }
3718 break;
3719 case mark_node:
3720 if (lua_toboolean(L, 2)) {
3721 lmt_token_list_to_luastring(L, mark_ptr(n), 0, 0, 0);
3722 } else {
3723 lmt_token_list_to_lua(L, mark_ptr(n));
3724 }
3725 return 1;
3726 }
3727 }
3728 lua_pushnil(L);
3729 return 1;
3730}
3731
3732static int nodelib_direct_setdata(lua_State *L)
3733{
3734 halfword n = nodelib_valid_direct_from_index(L, 1);
3735 if (n) {
3736 switch (node_type(n)) {
3737 case glyph_node:
3738 glyph_data(n) = lmt_tohalfword(L, 2);
3739 break;
3740 case rule_node:
3741 rule_data(n) = lmt_tohalfword(L, 2);
3742 break;
3743 case glue_node:
3744 glue_data(n) = lmt_tohalfword(L, 2);
3745 break;
3746 case boundary_node:
3747 boundary_data(n) = lmt_tohalfword(L, 2);
3748 boundary_reserved(n) = lmt_opthalfword(L, 3, 0);
3749 break;
3750 case insert_node:
3751 insert_identifier(n) = lmt_tohalfword(L, 2);
3752
3753 break;
3754 case attribute_node:
3755
3756 break;
3757 case mark_node:
3758 tex_delete_token_reference(mark_ptr(n));
3759 mark_ptr(n) = lmt_token_list_from_lua(L, 2);
3760 break;
3761 }
3762 }
3763 return 0;
3764}
3765
3766
3767
3768
3769# define getdelimiter_usage (fraction_usage | fence_usage | radical_usage | accent_usage)
3770# define setdelimiter_usage getdelimiter_usage
3771
3772# define getleftdelimiter_usage (fraction_usage | radical_usage)
3773# define setleftdelimiter_usage getleftdelimiter_usage
3774
3775# define getrightdelimiter_usage getleftdelimiter_usage
3776# define setrightdelimiter_usage setleftdelimiter_usage
3777
3778# define gettopdelimiter_usage (fence_usage | radical_usage)
3779# define settopdelimiter_usage gettopdelimiter_usage
3780
3781# define getbottomdelimiter_usage gettopdelimiter_usage
3782# define setbottomdelimiter_usage settopdelimiter_usage
3783
3784static int nodelib_direct_getleftdelimiter(lua_State *L)
3785{
3786 halfword n = nodelib_valid_direct_from_index(L, 1);
3787 if (n) {
3788 switch (node_type(n)) {
3789 case fraction_noad:
3790 nodelib_push_direct_or_nil(L, fraction_left_delimiter(n));
3791 return 1;
3792 case radical_noad:
3793 nodelib_push_direct_or_nil(L, radical_left_delimiter(n));
3794 return 1;
3795 }
3796 }
3797 lua_pushnil(L);
3798 return 1;
3799}
3800
3801static int nodelib_direct_getrightdelimiter(lua_State *L)
3802{
3803 halfword n = nodelib_valid_direct_from_index(L, 1);
3804 if (n) {
3805 switch (node_type(n)) {
3806 case fraction_noad:
3807 nodelib_push_direct_or_nil(L, fraction_right_delimiter(n));
3808 return 1;
3809 case radical_noad:
3810 nodelib_push_direct_or_nil(L, radical_right_delimiter(n));
3811 return 1;
3812 }
3813 }
3814 lua_pushnil(L);
3815 return 1;
3816}
3817
3818static int nodelib_direct_gettopdelimiter(lua_State *L)
3819{
3820 halfword n = nodelib_valid_direct_from_index(L, 1);
3821 if (n) {
3822 switch (node_type(n)) {
3823 case radical_noad:
3824 nodelib_push_direct_or_nil(L, radical_top_delimiter(n));
3825 return 1;
3826 case fence_noad:
3827 nodelib_push_direct_or_nil(L, fence_delimiter_top(n));
3828 return 1;
3829 }
3830 }
3831 lua_pushnil(L);
3832 return 1;
3833}
3834
3835static int nodelib_direct_getbottomdelimiter(lua_State *L)
3836{
3837 halfword n = nodelib_valid_direct_from_index(L, 1);
3838 if (n) {
3839 switch (node_type(n)) {
3840 case radical_noad:
3841 nodelib_push_direct_or_nil(L, radical_bottom_delimiter(n));
3842 return 1;
3843 case fence_noad:
3844 nodelib_push_direct_or_nil(L, fence_delimiter_bottom(n));
3845 return 1;
3846 }
3847 }
3848 lua_pushnil(L);
3849 return 1;
3850}
3851
3852static int nodelib_direct_getdelimiter(lua_State *L)
3853{
3854 halfword n = nodelib_valid_direct_from_index(L, 1);
3855 if (n) {
3856 switch (node_type(n)) {
3857 case fraction_noad:
3858 nodelib_push_direct_or_nil(L, fraction_middle_delimiter(n));
3859 return 1;
3860 case fence_noad:
3861 nodelib_push_direct_or_node(L, n, fence_delimiter(n));
3862 return 1;
3863 case radical_noad:
3864 nodelib_push_direct_or_node(L, n, radical_left_delimiter(n));
3865 return 1;
3866 case accent_noad:
3867 nodelib_push_direct_or_node(L, n, accent_middle_character(n));
3868 return 1;
3869 }
3870 }
3871 lua_pushnil(L);
3872 return 1;
3873}
3874
3875static int nodelib_direct_setleftdelimiter(lua_State *L)
3876{
3877 halfword n = nodelib_valid_direct_from_index(L, 1);
3878 if (n) {
3879 switch (node_type(n)) {
3880 case fraction_noad:
3881 fraction_left_delimiter(n) = nodelib_valid_direct_from_index(L, 2);
3882 break;
3883 case radical_noad:
3884 radical_left_delimiter(n) = nodelib_valid_direct_from_index(L, 2);
3885 break;
3886 }
3887 }
3888 return 0;
3889}
3890
3891static int nodelib_direct_setrightdelimiter(lua_State *L)
3892{
3893 halfword n = nodelib_valid_direct_from_index(L, 1);
3894 if (n) {
3895 switch (node_type(n)) {
3896 case fraction_noad:
3897 fraction_right_delimiter(n) = nodelib_valid_direct_from_index(L, 2);
3898 break;
3899 case radical_noad:
3900 radical_right_delimiter(n) = nodelib_valid_direct_from_index(L, 2);
3901 break;
3902 }
3903 }
3904 return 0;
3905}
3906
3907static int nodelib_direct_settopdelimiter(lua_State *L)
3908{
3909 halfword n = nodelib_valid_direct_from_index(L, 1);
3910 if (n) {
3911 switch (node_type(n)) {
3912 case radical_noad:
3913 radical_top_delimiter(n) = nodelib_valid_direct_from_index(L, 2);
3914 return 1;
3915 case fence_noad:
3916 fence_delimiter_top(n) = nodelib_valid_direct_from_index(L, 2);
3917 return 1;
3918 }
3919 }
3920 return 0;
3921}
3922
3923static int nodelib_direct_setbottomdelimiter(lua_State *L)
3924{
3925 halfword n = nodelib_valid_direct_from_index(L, 1);
3926 if (n) {
3927 switch (node_type(n)) {
3928 case radical_noad:
3929 radical_bottom_delimiter(n) = nodelib_valid_direct_from_index(L, 2);
3930 return 1;
3931 case fence_noad:
3932 fence_delimiter_bottom(n) = nodelib_valid_direct_from_index(L, 2);
3933 return 1;
3934 }
3935 }
3936 return 0;
3937}
3938
3939static int nodelib_direct_setdelimiter(lua_State *L)
3940{
3941 halfword n = nodelib_valid_direct_from_index(L, 1);
3942 if (n) {
3943 switch (node_type(n)) {
3944 case fraction_noad:
3945 fraction_middle_delimiter(n) = nodelib_valid_direct_from_index(L, 2);
3946 break;
3947 case fence_noad:
3948 fence_delimiter(n) = nodelib_valid_direct_from_index(L, 2);
3949 break;
3950 case radical_noad:
3951 radical_left_delimiter(n) = nodelib_valid_direct_from_index(L, 2);
3952 break;
3953 case accent_noad:
3954 accent_middle_character(n) = nodelib_valid_direct_from_index(L, 2);
3955 break;
3956 }
3957 }
3958 return 0;
3959}
3960
3961
3962
3963
3964# define gettop_usage (accent_usage | fence_usage)
3965# define settop_usage gettop_usage
3966# define getbottom_usage gettop_usage
3967# define setbottom_usage getbottom_usage
3968
3969static int nodelib_direct_gettop(lua_State *L)
3970{
3971 halfword n = nodelib_valid_direct_from_index(L, 1);
3972 if (n) {
3973 switch (node_type(n)) {
3974 case accent_noad:
3975 nodelib_push_direct_or_nil(L, accent_top_character(n));
3976 return 1;
3977 case fence_noad:
3978 nodelib_push_direct_or_nil(L, fence_delimiter_top(n));
3979 return 1;
3980 }
3981 }
3982 lua_pushnil(L);
3983 return 1;
3984}
3985
3986static int nodelib_direct_getbottom(lua_State *L)
3987{
3988 halfword n = nodelib_valid_direct_from_index(L, 1);
3989 if (n) {
3990 switch (node_type(n)) {
3991 case accent_noad:
3992 nodelib_push_direct_or_nil(L, accent_bottom_character(n));
3993 return 1;
3994 case fence_noad:
3995 nodelib_push_direct_or_nil(L, fence_delimiter_bottom(n));
3996 return 1;
3997 }
3998 }
3999 lua_pushnil(L);
4000 return 1;
4001}
4002
4003static int nodelib_direct_settop(lua_State *L)
4004{
4005 halfword n = nodelib_valid_direct_from_index(L, 1);
4006 if (n) {
4007 switch (node_type(n)) {
4008 case accent_noad:
4009 accent_top_character(n) = nodelib_valid_direct_from_index(L, 2);
4010 return 0;
4011 case fence_noad:
4012 fence_delimiter_top(n) = nodelib_valid_direct_from_index(L, 2);
4013 return 0;
4014 }
4015 }
4016 lua_pushnil(L);
4017 return 1;
4018}
4019
4020static int nodelib_direct_setbottom(lua_State *L)
4021{
4022 halfword n = nodelib_valid_direct_from_index(L, 1);
4023 if (n) {
4024 switch (node_type(n)) {
4025 case accent_noad:
4026 accent_bottom_character(n) = nodelib_valid_direct_from_index(L, 2);
4027 return 0;
4028 case fence_noad:
4029 fence_delimiter_bottom(n) = nodelib_valid_direct_from_index(L, 2);
4030 return 0;
4031 }
4032 }
4033 lua_pushnil(L);
4034 return 1;
4035}
4036
4037
4038
4039
4040# define getdenominator_usage fraction_usage
4041# define setdenominator_usage fraction_usage
4042# define getnumerator_usage fraction_usage
4043# define setnumerator_usage fraction_usage
4044
4045static int nodelib_direct_getnumerator(lua_State *L)
4046{
4047 halfword n = nodelib_valid_direct_from_index(L, 1);
4048 if (n) {
4049 switch (node_type(n)) {
4050 case fraction_noad:
4051 nodelib_push_direct_or_nil(L, fraction_numerator(n));
4052 return 1;
4053 }
4054 }
4055 lua_pushnil(L);
4056 return 1;
4057}
4058
4059static int nodelib_direct_getdenominator(lua_State *L)
4060{
4061 halfword n = nodelib_valid_direct_from_index(L, 1);
4062 if (n) {
4063 switch (node_type(n)) {
4064 case fraction_noad:
4065 nodelib_push_direct_or_nil(L, fraction_denominator(n));
4066 return 1;
4067 }
4068 }
4069 lua_pushnil(L);
4070 return 1;
4071}
4072
4073static int nodelib_direct_setnumerator(lua_State *L)
4074{
4075 halfword n = nodelib_valid_direct_from_index(L, 1);
4076 if (n) {
4077 switch (node_type(n)) {
4078 case fraction_noad:
4079 fraction_numerator(n) = nodelib_valid_direct_from_index(L, 2);
4080 break;
4081 }
4082 }
4083 return 0;
4084}
4085
4086static int nodelib_direct_setdenominator(lua_State *L)
4087{
4088 halfword n = nodelib_valid_direct_from_index(L, 1);
4089 if (n) {
4090 switch (node_type(n)) {
4091 case fraction_noad:
4092 fraction_denominator(n) = nodelib_valid_direct_from_index(L, 2);
4093 break;
4094 }
4095 }
4096 return 0;
4097}
4098
4099
4100
4101
4102# define getdegree_usage radical_usage
4103# define setdegree_usage getdegree_usage
4104
4105static int nodelib_direct_getdegree(lua_State *L)
4106{
4107 halfword n = nodelib_valid_direct_from_index(L, 1);
4108 if (n) {
4109 switch (node_type(n)) {
4110 case radical_noad:
4111 nodelib_push_direct_or_nil(L, radical_degree(n));
4112 return 1;
4113 }
4114 }
4115 lua_pushnil(L);
4116 return 1;
4117}
4118
4119static int nodelib_direct_setdegree(lua_State *L)
4120{
4121 halfword n = nodelib_valid_direct_from_index(L, 1);
4122 if (n) {
4123 switch (node_type(n)) {
4124 case radical_noad:
4125 radical_degree(n) = nodelib_valid_direct_from_index(L, 2);
4126 break;
4127 }
4128 }
4129 return 0;
4130}
4131
4132
4133
4134
4135# define getchoice_usage choice_usage
4136# define setchoice_usage getchoice_usage
4137
4138static int nodelib_direct_getchoice(lua_State *L)
4139{
4140 halfword n = nodelib_valid_direct_from_index(L, 1);
4141 halfword c = null;
4142 if (n && node_type(n) == choice_node) {
4143 switch (lmt_tointeger(L, 2)) {
4144 case 1: c =
4145 choice_display_mlist(n);
4146 break;
4147 case 2: c =
4148 choice_text_mlist(n);
4149 break;
4150 case 3:
4151 c = choice_script_mlist(n);
4152 break;
4153 case 4:
4154 c = choice_script_script_mlist(n);
4155 break;
4156 }
4157 }
4158 nodelib_push_direct_or_nil(L, c);
4159 return 1;
4160}
4161
4162static int nodelib_direct_setchoice(lua_State *L)
4163{
4164 halfword n = nodelib_valid_direct_from_index(L, 1);
4165 if (n && node_type(n) == choice_node) {
4166 halfword c = nodelib_valid_direct_from_index(L, 2);
4167 switch (lmt_tointeger(L, 2)) {
4168 case 1:
4169 choice_display_mlist(n) = c;
4170 break;
4171 case 2:
4172 choice_text_mlist(n) = c;
4173 break;
4174 case 3:
4175 choice_script_mlist(n) = c;
4176 break;
4177 case 4:
4178 choice_script_script_mlist(n) = c;
4179 break;
4180 }
4181 }
4182 return 0;
4183}
4184
4185
4186
4187
4188# define getglyphdata_usage glyph_usage
4189# define setglyphdata_usage getglyphdata_usage
4190
4191static int nodelib_direct_getglyphdata(lua_State *L)
4192{
4193 halfword n = nodelib_valid_direct_from_index(L, 1);
4194 if (n && (node_type(n) == glyph_node) && (glyph_data(n) != unused_attribute_value)) {
4195 lua_pushinteger(L, glyph_data(n));
4196 } else {
4197 lua_pushnil(L);
4198 }
4199 return 1;
4200}
4201
4202static int nodelib_direct_setglyphdata(lua_State *L)
4203{
4204 halfword n = nodelib_valid_direct_from_index(L, 1);
4205 if (n && node_type(n) == glyph_node) {
4206 glyph_data(n) = (halfword) luaL_optinteger(L, 2, unused_attribute_value);
4207 }
4208 return 0;
4209}
4210
4211
4212
4213
4214# define getnext_usage common_usage
4215# define setnext_usage common_usage
4216
4217static int nodelib_direct_getnext(lua_State *L)
4218{
4219 halfword n = nodelib_valid_direct_from_index(L, 1);
4220 if (n) {
4221 nodelib_push_direct_or_nil(L, node_next(n));
4222 } else {
4223 lua_pushnil(L);
4224 }
4225 return 1;
4226}
4227
4228static int nodelib_direct_setnext(lua_State *L)
4229{
4230 halfword n = nodelib_valid_direct_from_index(L, 1);
4231 if (n) {
4232 node_next(n) = nodelib_valid_direct_from_index(L, 2);
4233 }
4234 return 0;
4235}
4236
4237
4238
4239
4240# define getprev_usage common_usage
4241# define setprev_usage common_usage
4242
4243static int nodelib_direct_getprev(lua_State *L)
4244{
4245 halfword n = nodelib_valid_direct_from_index(L, 1);
4246 if (n) {
4247 nodelib_push_direct_or_nil(L, node_prev(n));
4248 } else {
4249 lua_pushnil(L);
4250 }
4251 return 1;
4252}
4253
4254static int nodelib_direct_setprev(lua_State *L)
4255{
4256 halfword n = nodelib_valid_direct_from_index(L, 1);
4257 if (n) {
4258 node_prev(n) = nodelib_valid_direct_from_index(L, 2);
4259 }
4260 return 0;
4261}
4262
4263
4264
4265
4266# define getboth_usage common_usage
4267# define setboth_usage common_usage
4268
4269static int nodelib_direct_getboth(lua_State *L)
4270{
4271 halfword n = nodelib_valid_direct_from_index(L, 1);
4272 if (n) {
4273 nodelib_push_direct_or_nil(L, node_prev(n));
4274 nodelib_push_direct_or_nil(L, node_next(n));
4275 } else {
4276 lua_pushnil(L);
4277 lua_pushnil(L);
4278 }
4279 return 2;
4280}
4281
4282static int nodelib_direct_setboth(lua_State *L)
4283{
4284 halfword n = nodelib_valid_direct_from_index(L, 1);
4285 if (n) {
4286 node_prev(n) = nodelib_valid_direct_from_index(L, 2);
4287 node_next(n) = nodelib_valid_direct_from_index(L, 3);
4288 }
4289 return 0;
4290}
4291
4292
4293
4294
4295
4296# define isnext_usage common_usage
4297# define isprev_usage common_usage
4298# define isboth_usage common_usage
4299
4300static int nodelib_direct_isnext(lua_State *L)
4301{
4302 halfword n = nodelib_valid_direct_from_index(L, 1);
4303 if (n && node_type(n) == lmt_tohalfword(L, 2)) {
4304 nodelib_push_direct_or_nil(L, node_next(n));
4305 } else {
4306 lua_pushnil(L);
4307 }
4308 return 1;
4309}
4310
4311static int nodelib_direct_isprev(lua_State *L)
4312{
4313 halfword n = nodelib_valid_direct_from_index(L, 1);
4314 if (n && node_type(n) == lmt_tohalfword(L, 2)) {
4315 nodelib_push_direct_or_nil(L, node_prev(n));
4316 } else {
4317 lua_pushnil(L);
4318 }
4319 return 1;
4320}
4321
4322static int nodelib_direct_isboth(lua_State *L)
4323{
4324 halfword n = nodelib_valid_direct_from_index(L, 1);
4325 if (n) {
4326 halfword typ = lmt_tohalfword(L, 2);
4327 halfword prv = node_prev(n);
4328 halfword nxt = node_next(n);
4329 nodelib_push_direct_or_nil(L, prv && node_type(prv) == typ ? prv : null);
4330 nodelib_push_direct_or_nil(L, nxt && node_type(nxt) == typ ? nxt : null);
4331 } else {
4332 lua_pushnil(L);
4333 lua_pushnil(L);
4334 }
4335 return 2;
4336}
4337
4338
4339
4340
4344
4345# define setlink_usage common_usage
4346
4347static int nodelib_direct_setlink(lua_State *L)
4348{
4349 int n = lua_gettop(L);
4350 halfword h = null;
4351 halfword t = null;
4352 for (int i = 1; i <= n; i++) {
4353
4358 switch (lua_type(L, i)) {
4359 case LUA_TNUMBER:
4360 {
4361 halfword c = nodelib_valid_direct_from_index(L, i);
4362 if (c) {
4363 if (c != t) {
4364 if (t) {
4365 node_next(t) = c;
4366 node_prev(c) = t;
4367 } else if (i > 1) {
4368
4369 node_prev(c) = null;
4370 }
4371 t = c;
4372 if (! h) {
4373 h = t;
4374 }
4375 } else {
4376
4377 }
4378 } else {
4379
4380 }
4381 }
4382 break;
4383 case LUA_TBOOLEAN:
4384 if (lua_toboolean(L, i)) {
4385
4386 break;
4387 } else {
4388
4389 }
4390 default:
4391 if (t) {
4392
4393 node_next(t) = null;
4394 } else {
4395
4396 }
4397 }
4398 }
4399 nodelib_push_direct_or_nil(L, h);
4400 return 1;
4401}
4402
4403
4404
4405# define setsplit_usage common_usage
4406
4407static int nodelib_direct_setsplit(lua_State *L)
4408{
4409 halfword l = nodelib_valid_direct_from_index(L, 1);
4410 halfword r = nodelib_valid_direct_from_index(L, 2);
4411 if (l && r) {
4412 if (l != r) {
4413 node_prev(node_next(l)) = null;
4414 node_next(node_prev(r)) = null;
4415 }
4416 node_next(l) = null;
4417 node_prev(r) = null;
4418 }
4419 return 0;
4420}
4421
4422
4423
4424
4425
4426
4427
4428# define validpar_usage par_usage
4429# define patchparshape_usage par_usage
4430# define getparstate_usage par_usage
4431
4432static halfword nodelib_direct_aux_validpar(lua_State *L, int index)
4433{
4434 halfword p = nodelib_valid_direct_from_index(L, index);
4435 if (! p) {
4436 p = tex_find_par_par(cur_list.head);
4437 } else if (node_type(p) != par_node) {
4438 while (node_prev(p)) {
4439 p = node_prev(p);
4440 }
4441 }
4442 return (p && node_type(p) == par_node) ? p : null;
4443}
4444
4445static int nodelib_direct_patchparshape(lua_State *L)
4446{
4447 halfword par = nodelib_direct_aux_validpar(L, 1);
4448 if (par) {
4449 halfword shape = par_par_shape(par);
4450 halfword options = shape ? specification_options(shape) : 0;
4451 if (shape) {
4452 tex_flush_node(shape);
4453 par_par_shape(par) = null;
4454 }
4455 if (lua_type(L, 2) == LUA_TTABLE) {
4456 halfword size = (halfword) lua_rawlen(L, 2);
4457 shape = tex_new_specification_node(size, par_shape_code, options);
4458 par_par_shape(par) = shape;
4459 for (int i = 1; i <= size; i++) {
4460 if (lua_rawgeti(L, 2, i) == LUA_TTABLE) {
4461 if (lua_rawgeti(L, -1, 1) == LUA_TNUMBER) {
4462 scaled indent = lmt_roundnumber(L, -1);
4463 if (lua_rawgeti(L, -2, 2) == LUA_TNUMBER) {
4464 scaled width = lmt_roundnumber(L, -1);
4465 tex_set_specification_indent(shape, i, indent);
4466 tex_set_specification_width(shape, i, width);
4467 }
4468 lua_pop(L, 1);
4469 }
4470 lua_pop(L, 1);
4471 }
4472 lua_pop(L, 1);
4473 }
4474 }
4475 }
4476 return 0;
4477}
4478
4479static int nodelib_direct_getparstate(lua_State *L)
4480{
4481 halfword p = nodelib_direct_aux_validpar(L, 1);
4482 if (p) {
4483 int limited = lua_toboolean(L, 2);
4484 lua_createtable(L, 0, 24);
4485 switch (node_subtype(p)) {
4486 case vmode_par_par_subtype:
4487 case hmode_par_par_subtype:
4488 {
4489
4490 lua_push_integer_at_key(L, hsize, tex_get_par_par(p, par_hsize_code));
4491 lua_push_integer_at_key(L, leftskip, glue_amount(tex_get_par_par(p, par_left_skip_code)));
4492 lua_push_integer_at_key(L, rightskip, glue_amount(tex_get_par_par(p, par_right_skip_code)));
4493 lua_push_integer_at_key(L, hangindent, tex_get_par_par(p, par_hang_indent_code));
4494 lua_push_integer_at_key(L, hangafter, tex_get_par_par(p, par_hang_after_code));
4495 lua_push_integer_at_key(L, parindent, tex_get_par_par(p, par_par_indent_code));
4496 lua_push_integer_at_key(L, prevgraf, par_prev_graf(p));
4497 if (! limited) {
4498 lua_push_integer_at_key(L, parfillleftskip, glue_amount(tex_get_par_par(p, par_par_fill_left_skip_code)));
4499 lua_push_integer_at_key(L, parfillskip, glue_amount(tex_get_par_par(p, par_par_fill_right_skip_code)));
4500 lua_push_integer_at_key(L, parinitleftskip, glue_amount(tex_get_par_par(p, par_par_init_left_skip_code)));
4501 lua_push_integer_at_key(L, parinitrightskip, glue_amount(tex_get_par_par(p, par_par_init_right_skip_code)));
4502 lua_push_integer_at_key(L, emergencyleftskip, glue_amount(tex_get_par_par(p, emergency_left_skip_code)));
4503 lua_push_integer_at_key(L, emergencyrightskip, glue_amount(tex_get_par_par(p, emergency_right_skip_code)));
4504 lua_push_integer_at_key(L, adjustspacing, tex_get_par_par(p, par_adjust_spacing_code));
4505 lua_push_integer_at_key(L, protrudechars, tex_get_par_par(p, par_protrude_chars_code));
4506 lua_push_integer_at_key(L, pretolerance, tex_get_par_par(p, par_pre_tolerance_code));
4507 lua_push_integer_at_key(L, tolerance, tex_get_par_par(p, par_tolerance_code));
4508 lua_push_integer_at_key(L, emergencystretch, tex_get_par_par(p, par_emergency_stretch_code));
4509 lua_push_integer_at_key(L, looseness, tex_get_par_par(p, par_looseness_code));
4510 lua_push_integer_at_key(L, lastlinefit, tex_get_par_par(p, par_last_line_fit_code));
4511 lua_push_integer_at_key(L, linepenalty, tex_get_par_par(p, par_line_penalty_code));
4512 lua_push_integer_at_key(L, interlinepenalty, tex_get_par_par(p, par_inter_line_penalty_code));
4513 lua_push_integer_at_key(L, clubpenalty, tex_get_par_par(p, par_club_penalty_code));
4514 lua_push_integer_at_key(L, widowpenalty, tex_get_par_par(p, par_widow_penalty_code));
4515 lua_push_integer_at_key(L, displaywidowpenalty, tex_get_par_par(p, par_display_widow_penalty_code));
4516 lua_push_integer_at_key(L, lefttwindemerits, tex_get_par_par(p, par_left_twin_demerits_code));
4517 lua_push_integer_at_key(L, righttwindemerits, tex_get_par_par(p, par_right_twin_demerits_code));
4518 lua_push_integer_at_key(L, singlelinepenalty, tex_get_par_par(p, par_single_line_penalty_code));
4519 lua_push_integer_at_key(L, hyphenpenalty, tex_get_par_par(p, par_hyphen_penalty_code));
4520 lua_push_integer_at_key(L, exhyphenpenalty, tex_get_par_par(p, par_ex_hyphen_penalty_code));
4521 lua_push_integer_at_key(L, brokenpenalty, tex_get_par_par(p, par_broken_penalty_code));
4522 lua_push_integer_at_key(L, adjdemerits, tex_get_par_par(p, par_adj_demerits_code));
4523 lua_push_integer_at_key(L, doublehyphendemerits, tex_get_par_par(p, par_double_hyphen_demerits_code));
4524 lua_push_integer_at_key(L, finalhyphendemerits, tex_get_par_par(p, par_final_hyphen_demerits_code));
4525 lua_push_integer_at_key(L, baselineskip, glue_amount(tex_get_par_par(p, par_baseline_skip_code)));
4526 lua_push_integer_at_key(L, lineskip, glue_amount(tex_get_par_par(p, par_line_skip_code)));
4527 lua_push_integer_at_key(L, lineskiplimit, tex_get_par_par(p, par_line_skip_limit_code));
4528 lua_push_integer_at_key(L, shapingpenaltiesmode, tex_get_par_par(p, par_shaping_penalties_mode_code));
4529 lua_push_integer_at_key(L, shapingpenalty, tex_get_par_par(p, par_shaping_penalty_code));
4530 lua_push_integer_at_key(L, emergencyextrastretch, tex_get_par_par(p, par_emergency_extra_stretch_code));
4531 }
4532 lua_push_specification_at_key(L, parshape, tex_get_par_par(p, par_par_shape_code));
4533 if (! limited) {
4534 lua_push_specification_at_key(L, interlinepenalties, tex_get_par_par(p, par_inter_line_penalties_code));
4535 lua_push_specification_at_key(L, clubpenalties, tex_get_par_par(p, par_club_penalties_code));
4536 lua_push_specification_at_key(L, widowpenalties, tex_get_par_par(p, par_widow_penalties_code));
4537 lua_push_specification_at_key(L, displaywidowpenalties, tex_get_par_par(p, par_display_widow_penalties_code));
4538 lua_push_specification_at_key(L, orphanpenalties, tex_get_par_par(p, par_orphan_penalties_code));
4539 lua_push_specification_at_key(L, toddlerpenalties, tex_get_par_par(p, par_toddler_penalties_code));
4540 lua_push_specification_at_key(L, parpasses, tex_get_par_par(p, par_par_passes_code));
4541 lua_push_specification_at_key(L, linebreakchecks, tex_get_par_par(p, par_line_break_checks_code));
4542 lua_push_specification_at_key(L, adjacentdemerits, tex_get_par_par(p, par_adjacent_demerits_code));
4543 lua_push_specification_at_key(L, fitnessclasses, tex_get_par_par(p, par_fitness_classes_code));
4544 }
4545 break;
4546 }
4547
4548
4549
4550 }
4551 return 1;
4552 } else {
4553 return 0;
4554 }
4555}
4556
4557
4558
4559# define type_usage common_usage
4560
4561static int nodelib_hybrid_type(lua_State *L)
4562{
4563 if (lua_type(L, 1) == LUA_TNUMBER) {
4564 halfword i = lmt_tohalfword(L, 1);
4565 if (tex_nodetype_is_visible(i)) {
4566 lua_push_key_by_index(lmt_interface.node_data[i].lua);
4567 return 1;
4568 }
4569 } else if (lmt_maybe_isnode(L, 1)) {
4570 lua_push_key(node);
4571 return 1;
4572 }
4573 lua_pushnil(L);
4574 return 1;
4575}
4576
4577
4578
4579static halfword nodelib_new_node(lua_State *L)
4580{
4581 quarterword i = unknown_node;
4582 switch (lua_type(L, 1)) {
4583 case LUA_TNUMBER:
4584 i = lmt_toquarterword(L, 1);
4585
4586
4587
4588 break;
4589 case LUA_TSTRING:
4590 i = nodelib_aux_get_node_type_id_from_name(L, 1, lmt_interface.node_data, 0);
4591 break;
4592 }
4593 if (tex_nodetype_is_visible(i)) {
4594 quarterword j = unknown_subtype;
4595 switch (lua_type(L, 2)) {
4596 case LUA_TNUMBER:
4597 j = lmt_toquarterword(L, 2);
4598 break;
4599 case LUA_TSTRING:
4600 j = nodelib_aux_get_node_subtype_id_from_name(L, 2, lmt_interface.node_data[i].subtypes);
4601 break;
4602 }
4603 return tex_new_node(i, (j == unknown_subtype) ? 0 : j);
4604 } else {
4605 return luaL_error(L, "invalid node id for creating new node");
4606 }
4607}
4608
4609static int nodelib_userdata_new(lua_State *L)
4610{
4611 lmt_push_node_fast(L, nodelib_new_node(L));
4612 return 1;
4613}
4614
4615
4616
4617# define new_usage common_usage
4618
4619static int nodelib_direct_new(lua_State *L)
4620{
4621 lua_pushinteger(L, nodelib_new_node(L));
4622 return 1;
4623}
4624
4625
4626
4627# define size_usage common_usage
4628
4629static halfword nodelib_shared_size(lua_State *L)
4630{
4631 quarterword i = unknown_node;
4632 switch (lua_type(L, 1)) {
4633 case LUA_TNUMBER:
4634 i = lmt_toquarterword(L, 1);
4635 break;
4636 case LUA_TSTRING:
4637 i = nodelib_aux_get_node_type_id_from_name(L, 1, lmt_interface.node_data, 1);
4638 break;
4639 }
4640 if (tex_nodetype_is_valid(i)) {
4641 lua_pushinteger(L, lmt_interface.node_data[i].size * 8);
4642 } else {
4643 lua_pushnil(L);
4644 }
4645 return 1;
4646}
4647
4648static int nodelib_direct_newtextglyph(lua_State* L)
4649{
4650 halfword glyph = tex_new_text_glyph(lmt_tohalfword(L, 1), lmt_tohalfword(L, 2));
4651 nodelib_aux_setattributelist(L, glyph, 3);
4652 lua_pushinteger(L, glyph);
4653 return 1;
4654}
4655
4656# define newmathglyph_usage common_usage
4657# define newtextglyph_usage common_usage
4658# define newcontinuationatom_usage common_usage
4659
4660static int nodelib_direct_newmathglyph(lua_State* L)
4661{
4662
4663 halfword glyph = tex_new_math_glyph(lmt_tohalfword(L, 1), lmt_tohalfword(L, 2));
4664 nodelib_aux_setattributelist(L, glyph, 3);
4665 lua_pushinteger(L, glyph);
4666 return 1;
4667}
4668
4669static int nodelib_direct_newcontinuationatom(lua_State* L)
4670{
4671 if (lua_type(L, 1) == LUA_TBOOLEAN) {
4672 halfword n = tex_new_math_continuation_atom(null, null);
4673 nodelib_aux_setattributelist(L, n, 2);
4674 lua_pushinteger(L, n);
4675 return 1;
4676 } else {
4677 halfword n = nodelib_valid_direct_from_index(L, 1);
4678 if (n) {
4679 n = tex_new_math_continuation_atom(n, null);
4680 }
4681 return 0;
4682 }
4683}
4684
4685
4686
4687static int nodelib_userdata_free(lua_State *L)
4688{
4689 if (lua_gettop(L) < 1) {
4690 lua_pushnil(L);
4691 } else if (! lua_isnil(L, 1)) {
4692 halfword n = lmt_check_isnode(L, 1);
4693 halfword p = node_next(n);
4694 tex_flush_node(n);
4695 lmt_push_node_fast(L, p);
4696 }
4697 return 1;
4698}
4699
4700
4701
4702# define free_usage common_usage
4703
4704static int nodelib_direct_free(lua_State *L)
4705{
4706 halfword n = nodelib_valid_direct_from_index(L, 1);
4707 if (n) {
4708 halfword p = node_next(n);
4709 tex_flush_node(n);
4710 n = p;
4711 } else {
4712 n = null;
4713 }
4714 nodelib_push_direct_or_nil(L, n);
4715 return 1;
4716}
4717
4718
4719
4720static int nodelib_userdata_flushnode(lua_State *L)
4721{
4722 if (! lua_isnil(L, 1)) {
4723 halfword n = lmt_check_isnode(L, 1);
4724 tex_flush_node(n);
4725 }
4726 return 0;
4727}
4728
4729
4730
4731# define flushnode_usage common_usage
4732
4733static int nodelib_direct_flushnode(lua_State *L)
4734{
4735 halfword n = nodelib_valid_direct_from_index(L, 1);
4736 if (n) {
4737 tex_flush_node(n);
4738 }
4739 return 0;
4740}
4741
4742
4743
4744static int nodelib_userdata_flushlist(lua_State *L)
4745{
4746 if (! lua_isnil(L, 1)) {
4747 halfword n_ptr = lmt_check_isnode(L, 1);
4748 tex_flush_node_list(n_ptr);
4749 }
4750 return 0;
4751}
4752
4753
4754
4755# define flushlist_usage common_usage
4756
4757static int nodelib_direct_flushlist(lua_State *L)
4758{
4759 halfword n = nodelib_valid_direct_from_index(L, 1);
4760 if (n) {
4761 tex_flush_node_list(n);
4762 }
4763 return 0;
4764}
4765
4766
4767
4768static int nodelib_userdata_remove(lua_State *L)
4769{
4770 if (lua_gettop(L) < 2) {
4771 return luaL_error(L, "Not enough arguments for node.remove()");
4772 } else {
4773 halfword head = lmt_check_isnode(L, 1);
4774 if (lua_isnil(L, 2)) {
4775 return 2;
4776 } else {
4777 halfword current = lmt_check_isnode(L, 2);
4778 halfword removed = current;
4779 int remove = lua_toboolean(L, 3);
4780 if (head == current) {
4781 if (node_prev(current)){
4782 node_next(node_prev(current)) = node_next(current);
4783 }
4784 if (node_next(current)){
4785 node_prev(node_next(current)) = node_prev(current);
4786 }
4787 head = node_next(current);
4788 current = node_next(current);
4789 } else {
4790 halfword t = node_prev(current);
4791 if (t) {
4792 node_next(t) = node_next(current);
4793 if (node_next(current)) {
4794 node_prev(node_next(current)) = t;
4795 }
4796 current = node_next(current);
4797 } else {
4798 return luaL_error(L, "Bad arguments to node.remove()");
4799 }
4800 }
4801 lmt_push_node_fast(L, head);
4802 lmt_push_node_fast(L, current);
4803 if (remove) {
4804 tex_flush_node(removed);
4805 return 2;
4806 } else {
4807 lmt_push_node_fast(L, removed);
4808 node_next(removed) = null;
4809 node_prev(removed) = null;
4810 return 3;
4811 }
4812 }
4813 }
4814}
4815
4816
4817
4818# define remove_usage common_usage
4819
4820static int nodelib_direct_remove(lua_State *L)
4821{
4822 halfword head = nodelib_valid_direct_from_index(L, 1);
4823 if (head) {
4824 halfword current = nodelib_valid_direct_from_index(L, 2);
4825 if (current) {
4826 halfword removed = current;
4827 int remove = lua_toboolean(L, 3);
4828 halfword prev = node_prev(current);
4829 if (head == current) {
4830 halfword next = node_next(current);
4831 if (prev){
4832 node_next(prev) = next;
4833 }
4834 if (next){
4835 node_prev(next) = prev;
4836 }
4837 head = node_next(current);
4838 current = head;
4839 } else {
4840 if (prev) {
4841 halfword next = node_next(current);
4842 node_next(prev) = next;
4843 if (next) {
4844 node_prev(next) = prev;
4845 }
4846 current = next;
4847 } else {
4848
4849 return 2;
4850 }
4851 }
4852 nodelib_push_direct_or_nil(L, head);
4853 nodelib_push_direct_or_nil(L, current);
4854 if (remove) {
4855 tex_flush_node(removed);
4856 return 2;
4857 } else {
4858 nodelib_push_direct_or_nil(L, removed);
4859 node_next(removed) = null;
4860 node_prev(removed) = null;
4861 return 3;
4862 }
4863 } else {
4864 nodelib_push_direct_or_nil(L, head);
4865 lua_pushnil(L);
4866 }
4867 } else {
4868 lua_pushnil(L);
4869 lua_pushnil(L);
4870 }
4871 return 2;
4872}
4873
4874# define removefromlist_usage common_usage
4875
4876static int nodelib_direct_removefromlist(lua_State *L)
4877{
4878 halfword head = nodelib_valid_direct_from_index(L, 1);
4879 int count = 0;
4880 if (head) {
4881 halfword id = lmt_tohalfword(L, 2);
4882 halfword subtype = lmt_opthalfword(L, 3, -1);
4883 halfword current = head;
4884 while (current) {
4885 halfword next = node_next(current);
4886 if (node_type(current) == id && (subtype < 0 || node_subtype(current) == subtype)) {
4887 if (current == head) {
4888 head = next;
4889 node_prev(next) = null;
4890 } else {
4891 tex_try_couple_nodes(node_prev(current), next);
4892 }
4893 tex_flush_node(current);
4894 ++count;
4895 }
4896 current = next;
4897 }
4898 }
4899 nodelib_push_direct_or_nil(L, head);
4900 lua_push_integer(L, count);
4901 return 2;
4902}
4903
4904
4905
4906static int nodelib_userdata_insertbefore(lua_State *L)
4907{
4908 if (lua_gettop(L) < 3) {
4909 return luaL_error(L, "Not enough arguments for node.insertbefore()");
4910 } else if (lua_isnil(L, 3)) {
4911 lua_settop(L, 2);
4912 } else {
4913 halfword n = lmt_check_isnode(L, 3);
4914 if (lua_isnil(L, 1)) {
4915 node_next(n) = null;
4916 node_prev(n) = null;
4917 lmt_push_node_fast(L, n);
4918 lua_pushvalue(L, -1);
4919 } else {
4920 halfword current;
4921 halfword head = lmt_check_isnode(L, 1);
4922 if (lua_isnil(L, 2)) {
4923 current = tex_tail_of_node_list(head);
4924 } else {
4925 current = lmt_check_isnode(L, 2);
4926 }
4927 if (head != current) {
4928 halfword t = node_prev(current);
4929 if (t) {
4930 tex_couple_nodes(t, n);
4931 } else {
4932 return luaL_error(L, "Bad arguments to node.insertbefore()");
4933 }
4934 }
4935 tex_couple_nodes(n, current);
4936 lmt_push_node_fast(L, (head == current) ? n : head);
4937 lmt_push_node_fast(L, n);
4938 }
4939 }
4940 return 2;
4941}
4942
4943
4944
4945# define insertbefore_usage common_usage
4946
4947static int nodelib_direct_insertbefore(lua_State *L)
4948{
4949 halfword n = nodelib_valid_direct_from_index(L, 3);
4950 if (n) {
4951 halfword head = nodelib_valid_direct_from_index(L, 1);
4952 halfword current = nodelib_valid_direct_from_index(L, 2);
4953
4954 if (head) {
4955 if (! current) {
4956 current = tex_tail_of_node_list(head);
4957 }
4958 if (head != current) {
4959 halfword prev = node_prev(current);
4960 if (prev) {
4961 tex_couple_nodes(prev, n);
4962 } else {
4963
4964 return 2;
4965 }
4966 }
4967 tex_couple_nodes(n, current);
4968 lua_pushinteger(L, (head == current) ? n : head);
4969 lua_pushinteger(L, n);
4970 } else {
4971 node_next(n) = null;
4972 node_prev(n) = null;
4973 lua_pushinteger(L, n);
4974 lua_pushinteger(L, n);
4975
4976 }
4977 } else {
4978 lua_settop(L, 2);
4979 }
4980 return 2;
4981}
4982
4983
4984
4985static int nodelib_userdata_insertafter(lua_State *L)
4986{
4987 if (lua_gettop(L) < 3) {
4988 return luaL_error(L, "Not enough arguments for node.insertafter()");
4989 } else if (lua_isnil(L, 3)) {
4990 lua_settop(L, 2);
4991 } else {
4992 halfword n = lmt_check_isnode(L, 3);
4993 if (lua_isnil(L, 1)) {
4994 node_next(n) = null;
4995 node_prev(n) = null;
4996 lmt_push_node_fast(L, n);
4997 lua_pushvalue(L, -1);
4998 } else {
4999 halfword current;
5000 halfword head = lmt_check_isnode(L, 1);
5001 if (lua_isnil(L, 2)) {
5002 current = head;
5003 while (node_next(current)) {
5004 current = node_next(current);
5005 }
5006 } else {
5007 current = lmt_check_isnode(L, 2);
5008 }
5009 tex_try_couple_nodes(n, node_next(current));
5010 tex_couple_nodes(current, n);
5011 lua_pop(L, 2);
5012 lmt_push_node_fast(L, n);
5013 }
5014 }
5015 return 2;
5016}
5017
5018
5019
5020# define insertafter_usage common_usage
5021
5022static int nodelib_direct_insertafter(lua_State *L)
5023{
5024
5025 halfword n = nodelib_valid_direct_from_index(L, 3);
5026 if (n) {
5027 halfword head = nodelib_valid_direct_from_index(L, 1);
5028 halfword current = nodelib_valid_direct_from_index(L, 2);
5029 if (head) {
5030 if (! current) {
5031 current = head;
5032 while (node_next(current)) {
5033 current = node_next(current);
5034 }
5035 }
5036 tex_try_couple_nodes(n, node_next(current));
5037 tex_couple_nodes(current, n);
5038 lua_pop(L, 2);
5039 lua_pushinteger(L, n);
5040 } else {
5041
5042 node_next(n) = null;
5043 node_prev(n) = null;
5044 lua_pushinteger(L, n);
5045 lua_pushvalue(L, -1);
5046
5047 }
5048 } else {
5049 lua_settop(L, 2);
5050 }
5051 return 2;
5052}
5053
5054
5055
5056# define appendaftertail_usage common_usage
5057# define prependbeforehead_usage common_usage
5058
5059static int nodelib_direct_appendaftertail(lua_State *L)
5060{
5061
5062 halfword h = nodelib_valid_direct_from_index(L, 1);
5063 halfword n = nodelib_valid_direct_from_index(L, 2);
5064 if (h && n) {
5065 tex_couple_nodes(tex_tail_of_node_list(h), n);
5066 }
5067 return 0;
5068}
5069
5070static int nodelib_direct_prependbeforehead(lua_State *L)
5071{
5072
5073 halfword h = nodelib_valid_direct_from_index(L, 1);
5074 halfword n = nodelib_valid_direct_from_index(L, 2);
5075 if (h && n) {
5076 tex_couple_nodes(n, tex_head_of_node_list(h));
5077 }
5078 return 0;
5079}
5080
5081
5082
5083
5089
5090static int nodelib_userdata_copylist(lua_State *L)
5091{
5092 if (lua_isnil(L, 1)) {
5093 return 1;
5094 } else {
5095 halfword m;
5096 halfword s = null;
5097 halfword n = lmt_check_isnode(L, 1);
5098 if ((lua_gettop(L) > 1) && (! lua_isnil(L, 2))) {
5099 s = lmt_check_isnode(L, 2);
5100 }
5101 m = tex_copy_node_list(n, s);
5102 lmt_push_node_fast(L, m);
5103 return 1;
5104 }
5105}
5106
5107
5108
5109# define copylist_usage common_usage
5110
5111static int nodelib_direct_copylist(lua_State *L)
5112{
5113 halfword n = nodelib_valid_direct_from_index(L, 1);
5114 halfword s = nodelib_valid_direct_from_index(L, 2);
5115 if (n) {
5116 halfword m = tex_copy_node_list(n, s);
5117 lua_pushinteger(L, m);
5118 } else {
5119 lua_pushnil(L);
5120 }
5121 return 1;
5122}
5123
5124
5125
5126
5127static int nodelib_userdata_show(lua_State *L)
5128{
5129 halfword n = lmt_check_isnode(L, 1);
5130 if (n) {
5131 tex_show_node_list(n, lmt_optinteger(L, 2, show_box_depth_par), lmt_optinteger(L, 3, show_box_breadth_par));
5132 }
5133 return 0;
5134}
5135
5136# define show_usage common_usage
5137
5138static int nodelib_direct_show(lua_State *L)
5139{
5140 halfword n = nodelib_valid_direct_from_index(L, 1);
5141 if (n) {
5142 tex_show_node_list(n, lmt_optinteger(L, 2, show_box_depth_par), lmt_optinteger(L, 3, show_box_breadth_par));
5143 }
5144 return 0;
5145}
5146
5147
5148
5149
5150# define showlist_usage common_usage
5151
5152static int nodelib_aux_showlist(lua_State* L, halfword box)
5153{
5154 if (box) {
5155 luaL_Buffer buffer;
5156 int saved_selector = lmt_print_state.selector;
5157 halfword levels = tracing_levels_par;
5158 halfword online = tracing_online_par;
5159 halfword details = show_node_details_par;
5160 halfword depth = lmt_opthalfword(L, 3, show_box_depth_par);
5161 halfword breadth = lmt_opthalfword(L, 4, show_box_breadth_par);
5162 tracing_levels_par = 0;
5163 tracing_online_par = 0;
5164 show_node_details_par = lmt_opthalfword(L, 2, details);
5165 lmt_print_state.selector = luabuffer_selector_code;
5166 lmt_lua_state.used_buffer = &buffer;
5167 luaL_buffinit(L, &buffer);
5168 tex_show_node_list(box, depth, breadth);
5169 tex_print_ln();
5170 luaL_pushresult(&buffer);
5171 lmt_lua_state.used_buffer = NULL;
5172 lmt_print_state.selector = saved_selector;
5173 show_node_details_par = details;
5174 tracing_levels_par = levels;
5175 tracing_online_par = online;
5176 } else {
5177 lua_pushliteral(L, "");
5178 }
5179 return 1;
5180}
5181
5182static int nodelib_common_serialized(lua_State *L, halfword n)
5183{
5184 if (n) {
5185 switch (node_type(n)) {
5186 case hlist_node:
5187 case vlist_node:
5188 return nodelib_aux_showlist(L, n);
5189 default:
5190 {
5191 halfword prv = null;
5192 halfword nxt = null;
5193 if (tex_nodetype_has_prev(n)) {
5194 prv = node_prev(n);
5195 node_prev(n) = null;
5196 }
5197 if (tex_nodetype_has_next(n)) {
5198 nxt = node_next(n);
5199 node_next(n) = null;
5200 }
5201 nodelib_aux_showlist(L, n);
5202 if (prv) {
5203 node_prev(n) = prv;
5204 }
5205 if (nxt) {
5206 node_next(n) = nxt;
5207 }
5208 return 1;
5209 }
5210 }
5211 }
5212 lua_pushliteral(L, "");
5213 return 1;
5214}
5215
5216static int nodelib_userdata_serialized(lua_State *L)
5217{
5218 return nodelib_common_serialized(L, lmt_check_isnode(L, 1));
5219}
5220
5221# define serialized_usage common_usage
5222
5223static int nodelib_direct_serialized(lua_State *L)
5224{
5225 return nodelib_common_serialized(L, nodelib_valid_direct_from_index(L, 1));
5226}
5227
5228
5229
5230static int nodelib_userdata_copy(lua_State *L)
5231{
5232 if (! lua_isnil(L, 1)) {
5233 halfword n = lmt_check_isnode(L, 1);
5234 n = tex_copy_node(n);
5235 lmt_push_node_fast(L, n);
5236 }
5237 return 1;
5238}
5239
5240
5241
5242# define copy_usage common_usage
5243
5244static int nodelib_direct_copy(lua_State *L)
5245{
5246 if (! lua_isnil(L, 1)) {
5247
5248 halfword n = nodelib_valid_direct_from_index(L, 1);
5249 if (n) {
5250 n = tex_copy_node(n);
5251 lua_pushinteger(L, n);
5252 } else {
5253 lua_pushnil(L);
5254 }
5255 }
5256 return 1;
5257}
5258
5259
5260
5261# define copyonly_usage common_usage
5262
5263static int nodelib_direct_copyonly(lua_State *L)
5264{
5265 if (! lua_isnil(L, 1)) {
5266 halfword n = nodelib_valid_direct_from_index(L, 1);
5267 if (n) {
5268 n = tex_copy_node_only(n);
5269 lua_pushinteger(L, n);
5270 } else {
5271 lua_pushnil(L);
5272 }
5273 }
5274 return 1;
5275}
5276
5277
5278
5279
5280static int nodelib_userdata_write(lua_State *L)
5281{
5282 int j = lua_gettop(L);
5283 for (int i = 1; i <= j; i++) {
5284 halfword n = lmt_check_isnode(L, i);
5285 if (n) {
5286 halfword m = node_next(n);
5287 tex_tail_append(n);
5288 if (tex_nodetype_has_attributes(node_type(n)) && ! node_attr(n)) {
5289 attach_current_attribute_list(n);
5290 }
5291 while (m) {
5292 tex_tail_append(m);
5293 if (tex_nodetype_has_attributes(node_type(m)) && ! node_attr(m)) {
5294 attach_current_attribute_list(m);
5295 }
5296 m = node_next(m);
5297 }
5298 }
5299 }
5300 return 0;
5301}
5302
5303
5321
5322
5323
5324
5325# define write_usage common_usage
5326
5327static int nodelib_direct_write(lua_State *L)
5328{
5329 int j = lua_gettop(L);
5330 for (int i = 1; i <= j; i++) {
5331 halfword n = nodelib_valid_direct_from_index(L, i);
5332 if (n) {
5333 halfword m = node_next(n);
5334 tex_tail_append(n);
5335 if (tex_nodetype_has_attributes(node_type(n)) && ! node_attr(n)) {
5336 attach_current_attribute_list(n);
5337 }
5338 while (m) {
5339 tex_tail_append(m);
5340 if (tex_nodetype_has_attributes(node_type(m)) && ! node_attr(m)) {
5341 attach_current_attribute_list(m);
5342 }
5343 m = node_next(m);
5344 }
5345 }
5346 }
5347 return 0;
5348}
5349
5350
5368
5369
5370
5371# define lastnode_usage common_usage
5372
5373static int nodelib_direct_lastnode(lua_State *L)
5374{
5375 halfword m = tex_pop_tail();
5376 lua_pushinteger(L, m);
5377 return 1;
5378}
5379
5380
5381
5382static int nodelib_aux_packing(lua_State *L, int slot)
5383{
5384 switch (lua_type(L, slot)) {
5385 case LUA_TSTRING:
5386 {
5387 const char *s = lua_tostring(L, slot);
5388 if (lua_key_eq(s, exactly)) {
5389 return packing_exactly;
5390 } else if (lua_key_eq(s, additional)) {
5391 return packing_additional;
5392 } else if (lua_key_eq(s, expanded)) {
5393 return packing_expanded;
5394 } else if (lua_key_eq(s, substitute)) {
5395 return packing_substitute;
5396 } else if (lua_key_eq(s, adapted)) {
5397 return packing_adapted;
5398 }
5399 break;
5400 }
5401 case LUA_TNUMBER:
5402 {
5403 int m = (int) lua_tointeger(L, slot);
5404 if (m >= packing_exactly && m <= packing_adapted) {
5405 return m;
5406 }
5407 break;
5408 }
5409 }
5410 return packing_additional;
5411}
5412
5413# define hpack_usage common_usage
5414
5415static int nodelib_direct_hpack(lua_State *L)
5416{
5417 halfword p;
5418 int w = 0;
5419 int m = packing_additional;
5420 singleword d = direction_def_value;
5421 halfword n = nodelib_valid_direct_from_index(L, 1);
5422 if (n) {
5423 int top = lua_gettop(L);
5424 if (top > 1) {
5425 w = lmt_roundnumber(L, 2);
5426 if (top > 2) {
5427 m = nodelib_aux_packing(L, 3);
5428 if (top > 3) {
5429 d = nodelib_getdirection(L, 4);
5430 }
5431 }
5432 }
5433 } else {
5434 n = null;
5435 }
5436 p = tex_hpack(n, w, m, d, holding_none_option, box_limit_none);
5437 lua_pushinteger(L, p);
5438 lua_pushinteger(L, lmt_packaging_state.last_badness);
5439 lua_pushinteger(L, lmt_packaging_state.last_overshoot);
5440 return 3;
5441}
5442
5443# define repack_usage common_usage
5444
5445static int nodelib_direct_repack(lua_State *L)
5446{
5447 halfword n = nodelib_valid_direct_from_index(L, 1);
5448 if (n) {
5449 switch (node_type(n)) {
5450 case hlist_node:
5451 case vlist_node:
5452 {
5453 int top = lua_gettop(L);
5454 int w = top > 1 ? lmt_roundnumber(L, 2) : 0;
5455 int m = top > 2 ? nodelib_aux_packing(L, 3) : packing_additional;
5456 tex_repack(n, w, m);
5457 break;
5458 }
5459 }
5460 }
5461 return 0;
5462}
5463
5464# define freeze_usage common_usage
5465
5466static int nodelib_direct_freeze(lua_State *L)
5467{
5468 halfword n = nodelib_valid_direct_from_index(L, 1);
5469 if (n) {
5470 switch (node_type(n)) {
5471 case hlist_node:
5472 case vlist_node:
5473 tex_freeze(n, lua_toboolean(L, 2), lua_toboolean(L, 3) ? node_type(n) : -1, lmt_opthalfword(L, 4, 0));
5474 break;
5475 }
5476 }
5477 return 0;
5478}
5479
5480
5481
5482
5483# define verticalbreak_usage common_usage
5484# define vpack_usage common_usage
5485
5486static int nodelib_direct_verticalbreak(lua_State *L)
5487{
5488 halfword n = nodelib_valid_direct_from_index(L, 1);
5489 if (n) {
5490 scaled ht = lmt_roundnumber(L, 2);
5491 scaled dp = lmt_roundnumber(L, 3);
5492 n = tex_vert_break(n, ht, dp, 1, 0);
5493 }
5494 lua_pushinteger(L, n);
5495 return 1;
5496}
5497
5498static int nodelib_direct_vpack(lua_State *L)
5499{
5500 halfword p;
5501 int w = 0;
5502 int m = packing_additional;
5503 singleword d = direction_def_value;
5504 halfword n = nodelib_valid_direct_from_index(L, 1);
5505 if (n) {
5506 int top = lua_gettop(L);
5507 if (top > 1) {
5508 w = lmt_roundnumber(L, 2);
5509 if (top > 2) {
5510 switch (lua_type(L, 3)) {
5511 case LUA_TSTRING:
5512 {
5513 const char *s = lua_tostring(L, 3);
5514 if (lua_key_eq(s, additional)) {
5515 m = packing_additional;
5516 } else if (lua_key_eq(s, exactly)) {
5517 m = packing_exactly;
5518 }
5519 break;
5520 }
5521 case LUA_TNUMBER:
5522 {
5523 m = (int) lua_tointeger(L, 3);
5524 if (m != packing_exactly && m != packing_additional) {
5525 m = packing_additional;
5526 }
5527 break;
5528 }
5529 }
5530 if (top > 3) {
5531 d = nodelib_getdirection(L, 4);
5532 }
5533 }
5534 }
5535 } else {
5536 n = null;
5537 }
5538 p = tex_vpack(n, w, m, max_dimension, d, holding_none_option, NULL);
5539 lua_pushinteger(L, p);
5540 lua_pushinteger(L, lmt_packaging_state.last_badness);
5541 return 2;
5542}
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553# define dimensions_usage common_usage
5554
5555static int nodelib_direct_dimensions(lua_State *L)
5556{
5557 int top = lua_gettop(L);
5558 if (top > 0) {
5559 scaledwhd siz = { .wd = 0, .ht = 0, .dp = 0, .ns = 0 };
5560 glueratio g_mult = normal_glue_multiplier;
5561 int vertical = 0;
5562 int g_sign = normal_glue_sign;
5563 int g_order = normal_glue_order;
5564 int i = 1;
5565 halfword n = null;
5566 halfword p = null;
5567 if (top > 3) {
5568 g_mult = (glueratio) lua_tonumber(L, i++);
5569 g_sign = tex_checked_glue_sign(lmt_tohalfword(L, i++));
5570 g_order = tex_checked_glue_order(lmt_tohalfword(L, i++));
5571 }
5572 n = nodelib_valid_direct_from_index(L, i++);
5573 if (lua_type(L, i) == LUA_TBOOLEAN) {
5574 vertical = lua_toboolean(L, i++);
5575 } else {
5576 p = nodelib_valid_direct_from_index(L, i++);
5577 vertical = lua_toboolean(L, i);
5578 }
5579 if (n) {
5580 if (vertical) {
5581 siz = tex_natural_vsizes(n, p, g_mult, g_sign, g_order, 0);
5582 } else {
5583 siz = tex_natural_hsizes(n, p, g_mult, g_sign, g_order);
5584 }
5585 }
5586 lua_pushinteger(L, siz.wd);
5587 lua_pushinteger(L, siz.ht);
5588 lua_pushinteger(L, siz.dp);
5589 return 3;
5590 } else {
5591 return luaL_error(L, "missing argument to 'dimensions' (direct node expected)");
5592 }
5593}
5594
5595
5596
5597
5598
5599
5600# define rangedimensions_usage common_usage
5601
5602static int nodelib_direct_rangedimensions(lua_State *L)
5603{
5604 int top = lua_gettop(L);
5605 if (top > 1) {
5606 scaledwhd siz = { .wd = 0, .ht = 0, .dp = 0, .ns = 0 };
5607 int vertical = 0;
5608 int nsizetoo = 0;
5609 int index = 1;
5610 halfword parent = nodelib_valid_direct_from_index(L, index++);
5611 halfword first = nodelib_valid_direct_from_index(L, index++);
5612 halfword last = first;
5613 if (lua_type(L, index) == LUA_TBOOLEAN) {
5614 vertical = lua_toboolean(L, index++);
5615 } else {
5616 last = nodelib_valid_direct_from_index(L, index++);
5617 vertical = lua_toboolean(L, index++);
5618 }
5619 nsizetoo = lua_toboolean(L, index);
5620 if (parent && first) {
5621 if (vertical) {
5622 siz = tex_natural_vsizes(first, last, (glueratio) box_glue_set(parent), box_glue_sign(parent), box_glue_order(parent), 0);
5623 } else {
5624 siz = tex_natural_hsizes(first, last, (glueratio) box_glue_set(parent), box_glue_sign(parent), box_glue_order(parent));
5625 }
5626 }
5627 lua_pushinteger(L, siz.wd);
5628 lua_pushinteger(L, siz.ht);
5629 lua_pushinteger(L, siz.dp);
5630 if (nsizetoo) {
5631 lua_pushinteger(L, siz.ns);
5632 return 4;
5633 } else {
5634 return 3;
5635 }
5636 } else {
5637 return luaL_error(L, "missing argument to 'rangedimensions' (2 or more direct nodes expected)");
5638 }
5639}
5640
5641
5642
5643# define naturalwidth_usage common_usage
5644
5645static int nodelib_direct_naturalwidth(lua_State *L)
5646{
5647 int top = lua_gettop(L);
5648 if (top > 1) {
5649 scaled wd = 0;
5650 halfword parent = nodelib_valid_direct_from_index(L, 1);
5651 halfword first = nodelib_valid_direct_from_index(L, 2);
5652 halfword last = nodelib_valid_direct_from_index(L, 3);
5653 if (parent && first) {
5654 wd = tex_natural_width(first, last, (glueratio) box_glue_set(parent), box_glue_sign(parent), box_glue_order(parent));
5655 }
5656 lua_pushinteger(L, wd);
5657 return 1;
5658 } else {
5659 return luaL_error(L, "missing argument to 'naturalwidth' (2 or more direct nodes expected)");
5660 }
5661}
5662
5663# define naturalhsize_usage common_usage
5664
5665static int nodelib_direct_naturalhsize(lua_State *L)
5666{
5667 scaled wd = 0;
5668 halfword c = null;
5669 halfword n = nodelib_valid_direct_from_index(L, 1);
5670 if (n) {
5671 wd = tex_natural_hsize(n, &c);
5672 }
5673 lua_pushinteger(L, wd);
5674 lua_pushinteger(L, c ? glue_amount(c) : 0);
5675 nodelib_push_direct_or_nil(L, c);
5676 return 3;
5677}
5678
5679# define mlisttohlist_usage common_usage
5680
5681static int nodelib_direct_mlisttohlist(lua_State *L)
5682{
5683 halfword n = nodelib_valid_direct_from_index(L, 1);
5684 if (n) {
5685 int style = lmt_get_math_style(L, 2, text_style);
5686 int penalties = lua_toboolean(L, 3);
5687 int beginclass = lmt_optinteger(L, 4, unset_noad_class);
5688 int endclass = lmt_optinteger(L, 5, unset_noad_class);
5689 if (! valid_math_class_code(beginclass)) {
5690 beginclass = unset_noad_class;
5691 }
5692 if (! valid_math_class_code(endclass)) {
5693 endclass = unset_noad_class;
5694 }
5695 n = tex_mlist_to_hlist(n, penalties, style, beginclass, endclass, NULL, m_to_h_callback);
5696 }
5697 nodelib_push_direct_or_nil(L, n);
5698 return 1;
5699}
5700
5701
5708
5709static int nodelib_aux_get_node_field_id(lua_State *L, int n, int node)
5710{
5711 int t = node_type(node);
5712 const char *s = lua_tostring(L, n);
5713 if (! s) {
5714 return -2;
5715 } else if (lua_key_eq(s, next)) {
5716 return 0;
5717 } else if (lua_key_eq(s, id)) {
5718 return 1;
5719 } else if (lua_key_eq(s, subtype)) {
5720 if (tex_nodetype_has_subtype(t)) {
5721 return 2;
5722 }
5723 } else if (lua_key_eq(s, attr)) {
5724 if (tex_nodetype_has_attributes(t)) {
5725 return 3;
5726 }
5727 } else if (lua_key_eq(s, prev)) {
5728 if (tex_nodetype_has_prev(t)) {
5729 return -1;
5730 }
5731 } else {
5732 value_info *fields = lmt_interface.node_data[t].fields;
5733 if (fields) {
5734 if (lua_key_eq(s, list)) {
5735 const char *sh = lua_key(head);
5736 for (int j = 0; fields[j].lua; j++) {
5737 if (fields[j].name == s || fields[j].name == sh) {
5738 return j + 3;
5739 }
5740 }
5741 } else {
5742 for (int j = 0; fields[j].lua; j++) {
5743 if (fields[j].name == s) {
5744 return j + 3;
5745 }
5746 }
5747 }
5748 }
5749 }
5750 return -2;
5751}
5752
5753
5754
5755static int nodelib_userdata_hasfield(lua_State *L)
5756{
5757 int i = -2;
5758 if (! lua_isnil(L, 1)) {
5759 i = nodelib_aux_get_node_field_id(L, 2, lmt_check_isnode(L, 1));
5760 }
5761 lua_pushboolean(L, (i != -2));
5762 return 1;
5763}
5764
5765
5766
5767# define hasfield_usage common_usage
5768
5769static int nodelib_direct_hasfield(lua_State *L)
5770{
5771 int i = -2;
5772 halfword n = nodelib_valid_direct_from_index(L, 1);
5773 if (n) {
5774 i = nodelib_aux_get_node_field_id(L, 2, n);
5775 }
5776 lua_pushboolean(L, (i != -2));
5777 return 1;
5778}
5779
5780
5781
5782static int nodelib_shared_types(lua_State *L)
5783{
5784 lua_newtable(L);
5785 for (int i = 0; lmt_interface.node_data[i].id != -1; i++) {
5786 if (lmt_interface.node_data[i].visible) {
5787 lua_pushstring(L, lmt_interface.node_data[i].name);
5788 lua_rawseti(L, -2, lmt_interface.node_data[i].id);
5789 }
5790 }
5791 return 1;
5792}
5793
5794
5795
5796# define fields_usage common_usage
5797
5798static int nodelib_shared_fields(lua_State *L)
5799{
5800 int t = nodelib_aux_get_valid_node_type_id(L, 1);
5801 int f = lua_toboolean(L, 2);
5802 value_info *fields = lmt_interface.node_data[t].fields;
5803 lua_newtable(L);
5804 if (f) {
5805 lua_push_key(next);
5806 lua_push_key(node);
5807 lua_rawset(L, -3);
5808 lua_push_key(id)
5809 lua_push_key(integer);
5810 lua_rawset(L, -3);
5811 if (tex_nodetype_has_subtype(t)) {
5812 lua_push_key(subtype);
5813 lua_push_key(integer);
5814 lua_rawset(L, -3);
5815 }
5816 if (tex_nodetype_has_prev(t)) {
5817 lua_push_key(prev);
5818 lua_push_key(node);
5819 lua_rawset(L, -3);
5820 }
5821 if (fields) {
5822 for (lua_Integer i = 0; fields[i].lua != 0; i++) {
5823
5824 lua_push_key_by_index(fields[i].lua);
5825 lua_push_key_by_index(lmt_interface.field_type_values[fields[i].type].lua);
5826
5827 lua_rawset(L, -3);
5828 }
5829 }
5830 } else {
5831 int offset = 0;
5832 lua_push_key(id);
5833 lua_rawseti(L, -2, offset++);
5834 if (tex_nodetype_has_subtype(t)) {
5835 lua_push_key(subtype);
5836 lua_rawseti(L, -2, offset++);
5837 }
5838 lua_push_key(next);
5839 lua_rawseti(L, -2, offset++);
5840 if (tex_nodetype_has_prev(t)) {
5841 lua_push_key(prev);
5842 lua_rawseti(L, -2, offset++);
5843 }
5844 if (fields) {
5845 for (lua_Integer i = 0; fields[i].lua != 0; i++) {
5846
5847 lua_rawgeti(L, LUA_REGISTRYINDEX, fields[i].lua);
5848 lua_rawseti(L, -2, offset++);
5849 }
5850 }
5851 }
5852 return 1;
5853}
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885static int nodelib_shared_subtypes(lua_State *L)
5886{
5887 value_info *subtypes = NULL;
5888 switch (lua_type(L, 1)) {
5889 case LUA_TSTRING:
5890 {
5891 const char *s = lua_tostring(L,1);
5892
5893 if (lua_key_eq(s, list)) {
5894 subtypes = lmt_interface.node_data[hlist_node].subtypes;
5895 } else {
5896 for (int id = first_nodetype; id <= last_nodetype; id++) {
5897 if (lmt_interface.node_data[id].name && ! strcmp(lmt_interface.node_data[id].name, s)) {
5898 subtypes = lmt_interface.node_data[id].subtypes;
5899 break;
5900 }
5901 }
5902 }
5903
5904
5928 }
5929 break;
5930 case LUA_TNUMBER:
5931 {
5932 int id = (int) lua_tointeger(L, 1);
5933 if (id >= first_nodetype && id <= last_nodetype) {
5934 subtypes = lmt_interface.node_data[id].subtypes;
5935 }
5936 }
5937 break;
5938 }
5939 if (subtypes) {
5940 lua_newtable(L);
5941 for (int i = 0; subtypes[i].name; i++) {
5942 lua_rawgeti(L, LUA_REGISTRYINDEX, subtypes[i].lua);
5943 lua_rawseti(L, -2, subtypes[i].id);
5944 }
5945 } else {
5946 lua_pushnil(L);
5947 }
5948 return 1;
5949}
5950
5951
5952
5953# define slide_usage common_usage
5954
5955static int nodelib_direct_slide(lua_State *L)
5956{
5957 halfword n = nodelib_valid_direct_from_index(L, 1);
5958 if (n) {
5959 while (node_next(n)) {
5960 node_prev(node_next(n)) = n;
5961 n = node_next(n);
5962 }
5963 lua_pushinteger(L, n);
5964 } else {
5965 lua_pushnil(L);
5966 }
5967 return 1;
5968}
5969
5970
5971
5972static int nodelib_userdata_tail(lua_State *L)
5973{
5974 if (! lua_isnil(L, 1)) {
5975 halfword n = lmt_check_isnode(L, 1);
5976 if (n) {
5977 while (node_next(n)) {
5978 n = node_next(n);
5979 }
5980 lmt_push_node_fast(L, n);
5981 } else {
5982
5983 }
5984 }
5985 return 1;
5986}
5987
5988
5989
5990# define tail_usage common_usage
5991
5992static int nodelib_direct_tail(lua_State *L)
5993{
5994 halfword n = nodelib_valid_direct_from_index(L, 1);
5995 if (n) {
5996 while (node_next(n)) {
5997 n = node_next(n);
5998 }
5999 lua_pushinteger(L, n);
6000 } else {
6001 lua_pushnil(L);
6002 }
6003 return 1;
6004}
6005
6006
6007
6008
6009# define beginofmath_usage common_usage
6010# define endofmath_usage common_usage
6011
6012static int nodelib_direct_beginofmath(lua_State *L)
6013{
6014 halfword n = nodelib_valid_direct_from_index(L, 1);
6015 if (n) {
6016 if (node_type(n) == math_node && (node_subtype(n) == begin_inline_math || node_subtype(n) == begin_broken_math)) {
6017 lua_pushinteger(L, n);
6018 return 1;
6019 } else {
6020 int level = 1;
6021 while (node_next(n)) {
6022 n = node_next(n);
6023 if (n && node_type(n) == math_node) {
6024
6025 switch (node_subtype(n)) {
6026 case begin_inline_math:
6027 case begin_broken_math:
6028 ++level;
6029 if (level > 0) {
6030 lua_pushinteger(L, n);
6031 return 1;
6032 } else {
6033 break;
6034 }
6035 case end_inline_math:
6036 case end_broken_math:
6037 --level;
6038 break;
6039 }
6040 }
6041 }
6042 }
6043 }
6044 return 0;
6045}
6046
6047static int nodelib_direct_endofmath(lua_State *L)
6048{
6049 halfword n = nodelib_valid_direct_from_index(L, 1);
6050 if (n) {
6051 if (node_type(n) == math_node && (node_subtype(n) == end_inline_math || node_subtype(n) == end_broken_math)) {
6052 lua_pushinteger(L, n);
6053 return 1;
6054 } else {
6055 int level = 1;
6056 while (node_next(n)) {
6057 n = node_next(n);
6058 if (n && node_type(n) == math_node) {
6059
6060 switch (node_subtype(n)) {
6061 case begin_inline_math:
6062 case begin_broken_math:
6063 ++level;
6064 break;
6065 case end_inline_math:
6066 case end_broken_math:
6067 --level;
6068 if (level > 0) {
6069 break;
6070 } else {
6071 lua_pushinteger(L, n);
6072 return 1;
6073 }
6074 }
6075 }
6076 }
6077 }
6078 }
6079 return 0;
6080}
6081
6082
6083
6084static int nodelib_userdata_hasattribute(lua_State *L)
6085{
6086 halfword n = lmt_check_isnode(L, 1);
6087 if (n) {
6088 int key = lmt_tointeger(L, 2);
6089 int val = tex_has_attribute(n, key, lmt_optinteger(L, 3, unused_attribute_value));
6090 if (val > unused_attribute_value) {
6091 lua_pushinteger(L, val);
6092 return 1;
6093 }
6094 }
6095 lua_pushnil(L);
6096 return 1;
6097}
6098
6099
6100
6101# define hasattribute_usage common_usage
6102
6103static int nodelib_direct_hasattribute(lua_State *L)
6104{
6105 halfword n = nodelib_valid_direct_from_index(L, 1);
6106 if (n) {
6107 int key = nodelib_valid_direct_from_index(L, 2);
6108 int val = tex_has_attribute(n, key, lmt_optinteger(L, 3, unused_attribute_value));
6109 if (val > unused_attribute_value) {
6110 lua_pushinteger(L, val);
6111 return 1;
6112 }
6113 }
6114 lua_pushnil(L);
6115 return 1;
6116}
6117
6118
6119
6120static int nodelib_userdata_getattribute(lua_State *L)
6121{
6122 halfword p = lmt_check_isnode(L, 1);
6123 if (tex_nodetype_has_attributes(node_type(p))) {
6124 p = node_attr(p);
6125 if (p) {
6126 p = node_next(p);
6127 if (p) {
6128 int i = lmt_optinteger(L, 2, 0);
6129 while (p) {
6130 if (attribute_index(p) == i) {
6131 int v = attribute_value(p);
6132 if (v == unused_attribute_value) {
6133 break;
6134 } else {
6135 lua_pushinteger(L, v);
6136 return 1;
6137 }
6138 } else if (attribute_index(p) > i) {
6139 break;
6140 }
6141 p = node_next(p);
6142 }
6143 }
6144 }
6145 }
6146 lua_pushnil(L);
6147 return 1;
6148}
6149
6150# define findattributerange_usage common_usage
6151
6152static int nodelib_direct_findattributerange(lua_State *L)
6153{
6154 halfword h = nodelib_valid_direct_from_index(L, 1);
6155 if (h) {
6156 halfword i = lmt_tohalfword(L, 2);
6157 while (h) {
6158 if (tex_nodetype_has_attributes(node_type(h))) {
6159 halfword p = node_attr(h);
6160 if (p) {
6161 p = node_next(p);
6162 while (p) {
6163 if (attribute_index(p) == i) {
6164 if (attribute_value(p) == unused_attribute_value) {
6165 break;
6166 } else {
6167 halfword t = h;
6168 while (node_next(t)) {
6169 t = node_next(t);
6170 }
6171 while (t != h) {
6172 if (tex_nodetype_has_attributes(node_type(t))) {
6173 halfword a = node_attr(t);
6174 if (a) {
6175 a = node_next(a);
6176 while (a) {
6177 if (attribute_index(a) == i) {
6178 if (attribute_value(a) == unused_attribute_value) {
6179 break;
6180 } else {
6181 goto FOUND;
6182 }
6183 } else if (attribute_index(a) > i) {
6184 break;
6185 }
6186 a = node_next(a);
6187 }
6188 }
6189 }
6190 t = node_prev(t);
6191 }
6192 FOUND:
6193 lua_pushinteger(L, h);
6194 lua_pushinteger(L, t);
6195 return 2;
6196 }
6197 } else if (attribute_index(p) > i) {
6198 break;
6199 }
6200 p = node_next(p);
6201 }
6202 }
6203 }
6204 h = node_next(h);
6205 }
6206 }
6207 return 0;
6208}
6209
6210
6211
6212
6213
6214
6215
6216
6217# define getattribute_usage common_usage
6218# define getattributes_usage common_usage
6219
6220static int nodelib_direct_getattribute(lua_State *L)
6221{
6222 halfword p = nodelib_valid_direct_from_index(L, 1);
6223 if (p) {
6224 if (node_type(p) != attribute_node) {
6225 p = tex_nodetype_has_attributes(node_type(p)) ? node_attr(p) : null;
6226 }
6227 if (p) {
6228 if (node_subtype(p) == attribute_list_subtype) {
6229 p = node_next(p);
6230 }
6231 if (p) {
6232 halfword index = lmt_opthalfword(L, 2, 0);
6233 while (p) {
6234 halfword i = attribute_index(p);
6235 if (i == index) {
6236 int v = attribute_value(p);
6237 if (v == unused_attribute_value) {
6238 break;
6239 } else {
6240 lua_pushinteger(L, v);
6241 return 1;
6242 }
6243 } else if (i > index) {
6244 break;
6245 }
6246 p = node_next(p);
6247 }
6248 }
6249 }
6250 }
6251 lua_pushnil(L);
6252 return 1;
6253}
6254
6255static int nodelib_direct_getattributes(lua_State *L)
6256{
6257 halfword p = nodelib_valid_direct_from_index(L, 1);
6258 if (p) {
6259 if (node_type(p) != attribute_node) {
6260 p = tex_nodetype_has_attributes(node_type(p)) ? node_attr(p) : null;
6261 }
6262 if (p) {
6263 if (node_subtype(p) == attribute_list_subtype) {
6264 p = node_next(p);
6265 }
6266 if (p) {
6267 int top = lua_gettop(L);
6268 for (int i = 2; i <= top; i++) {
6269 halfword a = lmt_tohalfword(L, i);
6270 halfword n = p;
6271 halfword v = unused_attribute_value;
6272 while (n) {
6273 halfword id = attribute_index(n);
6274 if (id == a) {
6275 v = attribute_value(n);
6276 break;
6277 } else if (id > a) {
6278 break;
6279 } else {
6280 n = node_next(n);
6281 }
6282 }
6283 if (v == unused_attribute_value) {
6284 lua_pushnil(L);
6285 } else {
6286 lua_pushinteger(L, v);
6287 }
6288 }
6289 return top - 1;
6290 }
6291 }
6292 }
6293 return 0;
6294}
6295
6296# define setattribute_usage common_usage
6297# define setattributes_usage common_usage
6298
6299static int nodelib_direct_setattribute(lua_State *L)
6300{
6301 halfword n = nodelib_valid_direct_from_index(L, 1);
6302 if (n && tex_nodetype_has_attributes(node_type(n))) {
6303 halfword index = lmt_tohalfword(L, 2);
6304 halfword value = lmt_optinteger(L, 3, unused_attribute_value);
6305
6306
6307
6308 tex_set_attribute(n, index, value);
6309
6310 }
6311 return 0;
6312}
6313
6314
6315
6316static int nodelib_direct_setattributes(lua_State *L)
6317{
6318 halfword n = nodelib_valid_direct_from_index(L, 1);
6319 if (n && tex_nodetype_has_attributes(node_type(n))) {
6320 int top = lua_gettop(L);
6321 int ini = 2;
6322 if (lua_type(L, 2) == LUA_TBOOLEAN) {
6323 ++ini;
6324 if (lua_toboolean(L, 2) && ! node_attr(n)) {
6325 attach_current_attribute_list(n);
6326 }
6327 }
6328 for (int i = ini; i <= top; i += 2) {
6329 halfword key = lmt_tohalfword(L, i);
6330 halfword val = lmt_optinteger(L, i + 1, unused_attribute_value);
6331
6332
6333
6334 tex_set_attribute(n, key, val);
6335
6336 }
6337 }
6338 return 0;
6339}
6340
6341# define patchattributes_usage common_usage
6342
6343static int nodelib_direct_patchattributes(lua_State *L)
6344{
6345 halfword p = nodelib_valid_direct_from_index(L, 1);
6346 if (p) {
6347 halfword att = null;
6348 int top = lua_gettop(L);
6349 for (int i = 2; i <= top; i += 2) {
6350 halfword index = lmt_tohalfword(L, i);
6351 halfword value = lua_type(L, i + 1) == LUA_TNUMBER ? lmt_tohalfword(L, i + 1) : unused_attribute_value;
6352 if (att) {
6353 att = tex_patch_attribute_list(att, index, value);
6354 } else {
6355 att = tex_copy_attribute_list_set(node_attr(p), index, value);
6356 }
6357 }
6358 tex_attach_attribute_list_attribute(p, att);
6359 }
6360 return 0;
6361}
6362
6363
6364
6365# define findattribute_usage common_usage
6366
6367static int nodelib_direct_findattribute(lua_State *L)
6368{
6369 halfword c = nodelib_valid_direct_from_index(L, 1);
6370 if (c) {
6371 halfword i = lmt_tohalfword(L, 2);
6372 if (lua_type(L, 3) == LUA_TBOOLEAN && lua_toboolean(L, 3)) {
6373
6374 halfword a = null;
6375 while (c) {
6376 switch (node_type(c)) {
6377 case hlist_node:
6378 case vlist_node:
6379
6380 case rule_node:
6381 case disc_node:
6382 case glyph_node:
6383 goto CHECK;
6384 case glue_node:
6385 if (glue_leader_ptr(c)) {
6386 goto CHECK;
6387 } else {
6388 goto NEXT;
6389 }
6390 default:
6391 goto NEXT;
6392 }
6393 CHECK:
6394 {
6395
6396 halfword p = node_attr(c);
6397 if (p && a != p) {
6398 a = p;
6399 p = node_next(p);
6400 while (p) {
6401 if (attribute_index(p) == i) {
6402 halfword ret = attribute_value(p);
6403 if (ret == unused_attribute_value) {
6404 break;
6405 } else {
6406 lua_pushinteger(L, ret);
6407 lua_pushinteger(L, c);
6408 return 2;
6409 }
6410 } else if (attribute_index(p) > i) {
6411 break;
6412 }
6413 p = node_next(p);
6414 }
6415 }
6416 }
6417 NEXT:
6418 c = node_next(c);
6419 }
6420 } else {
6421 halfword t = lmt_optinteger(L, 3, -1);
6422 halfword a = null;
6423 while (c) {
6424 if ((t < 0 || node_type(c) == t) && tex_nodetype_has_attributes(node_type(c))) {
6425
6426 halfword p = node_attr(c);
6427 if (p && a != p) {
6428 a = p;
6429 p = node_next(p);
6430 while (p) {
6431 if (attribute_index(p) == i) {
6432 halfword ret = attribute_value(p);
6433 if (ret == unused_attribute_value) {
6434 break;
6435 } else {
6436 lua_pushinteger(L, ret);
6437 lua_pushinteger(L, c);
6438 return 2;
6439 }
6440 } else if (attribute_index(p) > i) {
6441 break;
6442 }
6443 p = node_next(p);
6444 }
6445 }
6446 }
6447 c = node_next(c);
6448 }
6449 }
6450 }
6451 return 0;
6452}
6453
6454# define unsetattribute_usage common_usage
6455# define unsetattributes_usage common_usage
6456
6457static int nodelib_direct_unsetattribute(lua_State *L)
6458{
6459 halfword n = nodelib_valid_direct_from_index(L, 1);
6460 if (n) {
6461 halfword key = lmt_checkhalfword(L, 2);
6462 halfword val = lmt_opthalfword(L, 3, unused_attribute_value);
6463 halfword ret = tex_unset_attribute(n, key, val);
6464 if (ret > unused_attribute_value) {
6465 lua_pushinteger(L, ret);
6466 } else {
6467 lua_pushnil(L);
6468 }
6469 } else {
6470 lua_pushnil(L);
6471 }
6472 return 1;
6473}
6474static int nodelib_direct_unsetattributes(lua_State *L)
6475{
6476 halfword key = lmt_checkhalfword(L, 1);
6477 halfword first = nodelib_valid_direct_from_index(L, 2);
6478 halfword last = nodelib_valid_direct_from_index(L, 3);
6479 if (first) {
6480 tex_unset_attributes(first, last, key);
6481 }
6482 return 0;
6483}
6484
6485
6486
6487
6488static int nodelib_userdata_setattribute(lua_State *L)
6489{
6490 halfword n = lmt_check_isnode(L, 1);
6491 if (n) {
6492 halfword key = lmt_tohalfword(L, 2);
6493 halfword val = lmt_opthalfword(L, 3, unused_attribute_value);
6494 if (val == unused_attribute_value) {
6495 tex_unset_attribute(n, key, val);
6496 } else {
6497 tex_set_attribute(n, key, val);
6498 }
6499 }
6500 return 0;
6501}
6502
6503static int nodelib_userdata_unsetattribute(lua_State *L)
6504{
6505 halfword n = lmt_check_isnode(L, 1);
6506 if (n) {
6507 halfword key = lmt_checkhalfword(L, 2);
6508 halfword val = lmt_opthalfword(L, 3, unused_attribute_value);
6509 halfword ret = tex_unset_attribute(n, key, val);
6510 if (ret > unused_attribute_value) {
6511 lua_pushinteger(L, ret);
6512 } else {
6513 lua_pushnil(L);
6514 }
6515 } else {
6516 lua_pushnil(L);
6517 }
6518 return 1;
6519}
6520
6521
6522
6523
6524
6525# define getglue_usage (glue_usage | glue_spec_usage | hlist_usage | vlist_usage | unset_usage | math_usage)
6526# define setglue_usage getglue_usage
6527# define iszeroglue_usage getglue_usage
6528
6529static int nodelib_direct_getglue(lua_State *L)
6530{
6531 halfword n = nodelib_valid_direct_from_index(L, 1);
6532 if (n) {
6533 switch (node_type(n)) {
6534 case glue_node:
6535 case glue_spec_node:
6536 lua_pushinteger(L, glue_amount(n));
6537 lua_pushinteger(L, glue_stretch(n));
6538 lua_pushinteger(L, glue_shrink(n));
6539 lua_pushinteger(L, glue_stretch_order(n));
6540 lua_pushinteger(L, glue_shrink_order(n));
6541 return 5;
6542 case hlist_node:
6543 case vlist_node:
6544 case unset_node:
6545 lua_pushnumber(L, (double) box_glue_set(n));
6546 lua_pushinteger(L, box_glue_order(n));
6547 lua_pushinteger(L, box_glue_sign(n));
6548 return 3;
6549 case math_node:
6550 lua_pushinteger(L, math_amount(n));
6551 lua_pushinteger(L, math_stretch(n));
6552 lua_pushinteger(L, math_shrink(n));
6553 lua_pushinteger(L, math_stretch_order(n));
6554 lua_pushinteger(L, math_shrink_order(n));
6555 return 5;
6556 }
6557 }
6558 return 0;
6559}
6560
6561static int nodelib_direct_setglue(lua_State *L)
6562{
6563 halfword n = nodelib_valid_direct_from_index(L, 1);
6564 if (n) {
6565 int top = lua_gettop(L);
6566 switch (node_type(n)) {
6567 case glue_node:
6568 case glue_spec_node:
6569 glue_amount(n) = ((top > 1 && lua_type(L, 2) == LUA_TNUMBER)) ? (halfword) lmt_roundnumber(L, 2) : 0;
6570 glue_stretch(n) = ((top > 2 && lua_type(L, 3) == LUA_TNUMBER)) ? (halfword) lmt_roundnumber(L, 3) : 0;
6571 glue_shrink(n) = ((top > 3 && lua_type(L, 4) == LUA_TNUMBER)) ? (halfword) lmt_roundnumber(L, 4) : 0;
6572 glue_stretch_order(n) = tex_checked_glue_order((top > 4 && lua_type(L, 5) == LUA_TNUMBER) ? lmt_tohalfword(L, 5) : 0);
6573 glue_shrink_order(n) = tex_checked_glue_order((top > 5 && lua_type(L, 6) == LUA_TNUMBER) ? lmt_tohalfword(L, 6) : 0);
6574 break;
6575 case hlist_node:
6576 case vlist_node:
6577 case unset_node:
6578 box_glue_set(n) = ((top > 1 && lua_type(L, 2) == LUA_TNUMBER)) ? (glueratio) lua_tonumber(L, 2) : 0;
6579 box_glue_order(n) = tex_checked_glue_order((top > 2 && lua_type(L, 3) == LUA_TNUMBER) ? (halfword) lua_tointeger(L, 3) : 0);
6580 box_glue_sign(n) = tex_checked_glue_sign((top > 3 && lua_type(L, 4) == LUA_TNUMBER) ? (halfword) lua_tointeger(L, 4) : 0);
6581 break;
6582 case math_node:
6583 math_amount(n) = ((top > 1 && lua_type(L, 2) == LUA_TNUMBER)) ? (halfword) lmt_roundnumber(L, 2) : 0;
6584 math_stretch(n) = ((top > 2 && lua_type(L, 3) == LUA_TNUMBER)) ? (halfword) lmt_roundnumber(L, 3) : 0;
6585 math_shrink(n) = ((top > 3 && lua_type(L, 4) == LUA_TNUMBER)) ? (halfword) lmt_roundnumber(L, 4) : 0;
6586 math_stretch_order(n) = tex_checked_glue_order((top > 4 && lua_type(L, 5) == LUA_TNUMBER) ? lmt_tohalfword(L, 5) : 0);
6587 math_shrink_order(n) = tex_checked_glue_order((top > 5 && lua_type(L, 6) == LUA_TNUMBER) ? lmt_tohalfword(L, 6) : 0);
6588 break;
6589 }
6590 }
6591 return 0;
6592}
6593
6594static int nodelib_direct_iszeroglue(lua_State *L)
6595{
6596 halfword n = nodelib_valid_direct_from_index(L, 1);
6597 if (n) {
6598 switch (node_type(n)) {
6599 case glue_node:
6600 case glue_spec_node:
6601 lua_pushboolean(L, glue_amount(n) == 0 && glue_stretch(n) == 0 && glue_shrink(n) == 0);
6602 return 1;
6603 case hlist_node:
6604 case vlist_node:
6605 lua_pushboolean(L, box_glue_set(n) == 0.0 && box_glue_order(n) == 0 && box_glue_sign(n) == 0);
6606 return 1;
6607 case math_node:
6608 lua_pushboolean(L, math_amount(n) == 0 && math_stretch(n) == 0 && math_shrink(n) == 0);
6609 return 1;
6610 }
6611 }
6612 return 0;
6613}
6614
6615
6616
6617# define startofpar_usage common_usage
6618
6619static int nodelib_direct_startofpar(lua_State *L)
6620{
6621 halfword n = nodelib_valid_direct_from_index(L, 1);
6622 lua_pushboolean(L, n && tex_is_start_of_par_node(n));
6623 return 1;
6624}
6625
6626
6627
6628static int nodelib_aux_nil(lua_State *L)
6629{
6630 lua_pushnil(L);
6631 return 1;
6632}
6633
6634
6635
6636
6637
6638
6639
6640
6641
6642
6643# define traverse_usage common_usage
6644# define traverseid_usage common_usage
6645# define traversechar_usage common_usage
6646# define traverseglyph_usage common_usage
6647# define traverselist_usage common_usage
6648# define traverseleader_usage common_usage
6649# define traverseitalic_usage common_usage
6650# define traversecontent_usage common_usage
6651
6652static int nodelib_direct_aux_next(lua_State *L)
6653{
6654 halfword t;
6655 if (lua_isnil(L, 2)) {
6656 t = lmt_tohalfword(L, 1) ;
6657 lua_settop(L, 1);
6658 } else {
6659 t = lmt_tohalfword(L, 2) ;
6660 t = node_next(t);
6661 lua_settop(L, 2);
6662 }
6663 if (t) {
6664 lua_pushinteger(L, t);
6665 lua_pushinteger(L, node_type(t));
6666 lua_pushinteger(L, node_subtype(t));
6667 return 3;
6668 } else {
6669 lua_pushnil(L);
6670 return 1;
6671 }
6672}
6673
6674static int nodelib_direct_aux_prev(lua_State *L)
6675{
6676 halfword t;
6677 if (lua_isnil(L, 2)) {
6678 t = lmt_tohalfword(L, 1) ;
6679 lua_settop(L, 1);
6680 } else {
6681 t = lmt_tohalfword(L, 2) ;
6682 t = node_prev(t);
6683 lua_settop(L, 2);
6684 }
6685 if (t) {
6686 lua_pushinteger(L, t);
6687 lua_pushinteger(L, node_type(t));
6688 lua_pushinteger(L, node_subtype(t));
6689 return 3;
6690 } else {
6691 lua_pushnil(L);
6692 return 1;
6693 }
6694}
6695
6696static int nodelib_direct_traverse(lua_State *L)
6697{
6698 if (lua_isnil(L, 1)) {
6699 lua_pushcclosure(L, nodelib_aux_nil, 0);
6700 return 1;
6701 } else {
6702 halfword n = nodelib_valid_direct_from_index(L, 1);
6703 if (n) {
6704 if (lua_toboolean(L, 2)) {
6705 if (lua_toboolean(L, 3)) {
6706 n = tex_tail_of_node_list(n);
6707 }
6708 lua_pushcclosure(L, nodelib_direct_aux_prev, 0);
6709 } else {
6710 lua_pushcclosure(L, nodelib_direct_aux_next, 0);
6711 }
6712 lua_pushinteger(L, n);
6713 lua_pushnil(L);
6714 return 3;
6715 } else {
6716 lua_pushcclosure(L, nodelib_aux_nil, 0);
6717 return 1;
6718 }
6719 }
6720}
6721
6722static int nodelib_direct_aux_next_filtered(lua_State *L)
6723{
6724 halfword t;
6725 int i = (int) lua_tointeger(L, lua_upvalueindex(1));
6726 if (lua_isnil(L, 2)) {
6727 t = lmt_tohalfword(L, 1) ;
6728 lua_settop(L, 1);
6729 } else {
6730 t = lmt_tohalfword(L, 2) ;
6731 t = node_next(t);
6732 lua_settop(L, 2);
6733 }
6734 while (t && node_type(t) != i) {
6735 t = node_next(t);
6736 }
6737 if (t) {
6738 lua_pushinteger(L, t);
6739 lua_pushinteger(L, node_subtype(t));
6740 return 2;
6741 } else {
6742 lua_pushnil(L);
6743 return 1;
6744 }
6745}
6746
6747static int nodelib_direct_aux_prev_filtered(lua_State *L)
6748{
6749 halfword t;
6750 int i = (int) lua_tointeger(L, lua_upvalueindex(1));
6751 if (lua_isnil(L, 2)) {
6752 t = lmt_tohalfword(L, 1) ;
6753 lua_settop(L, 1);
6754 } else {
6755 t = lmt_tohalfword(L, 2) ;
6756 t = node_prev(t);
6757 lua_settop(L, 2);
6758 }
6759 while (t && node_type(t) != i) {
6760 t = node_prev(t);
6761 }
6762 if (t) {
6763 lua_pushinteger(L, t);
6764 lua_pushinteger(L, node_subtype(t));
6765 return 2;
6766 } else {
6767 lua_pushnil(L);
6768 return 1;
6769 }
6770}
6771
6772static int nodelib_direct_traverseid(lua_State *L)
6773{
6774 if (lua_isnil(L, 2)) {
6775 lua_pushcclosure(L, nodelib_aux_nil, 0);
6776 return 1;
6777 } else {
6778 halfword n = nodelib_valid_direct_from_index(L, 2);
6779 if (n) {
6780 if (lua_toboolean(L, 3)) {
6781 if (lua_toboolean(L, 4)) {
6782 n = tex_tail_of_node_list(n);
6783 }
6784 lua_settop(L, 1);
6785 lua_pushcclosure(L, nodelib_direct_aux_prev_filtered, 1);
6786 } else {
6787 lua_settop(L, 1);
6788 lua_pushcclosure(L, nodelib_direct_aux_next_filtered, 1);
6789 }
6790 lua_pushinteger(L, n);
6791 lua_pushnil(L);
6792 return 3;
6793 } else {
6794 return 0;
6795 }
6796 }
6797}
6798
6799static int nodelib_direct_aux_next_char(lua_State *L)
6800{
6801 halfword t;
6802 if (lua_isnil(L, 2)) {
6803 t = lmt_tohalfword(L, 1) ;
6804 lua_settop(L, 1);
6805 } else {
6806 t = lmt_tohalfword(L, 2) ;
6807 t = node_next(t);
6808 lua_settop(L, 2);
6809 }
6810 while (t && (node_type(t) != glyph_node || glyph_protected(t))) {
6811 t = node_next(t);
6812 }
6813 if (t) {
6814 lua_pushinteger(L, t);
6815 lua_pushinteger(L, glyph_character(t));
6816 lua_pushinteger(L, glyph_font(t));
6817 lua_pushinteger(L, glyph_data(t));
6818 return 4;
6819 } else {
6820 lua_pushnil(L);
6821 return 1;
6822 }
6823}
6824
6825static int nodelib_direct_aux_prev_char(lua_State *L)
6826{
6827 halfword t;
6828 if (lua_isnil(L, 2)) {
6829 t = lmt_tohalfword(L, 1) ;
6830 lua_settop(L, 1);
6831 } else {
6832 t = lmt_tohalfword(L, 2) ;
6833 t = node_prev(t);
6834 lua_settop(L, 2);
6835 }
6836 while (t && (node_type(t) != glyph_node || glyph_protected(t))) {
6837 t = node_prev(t);
6838 }
6839 if (t) {
6840 lua_pushinteger(L, t);
6841 lua_pushinteger(L, glyph_character(t));
6842 lua_pushinteger(L, glyph_font(t));
6843 lua_pushinteger(L, glyph_data(t));
6844 return 4;
6845 } else {
6846 lua_pushnil(L);
6847 return 1;
6848 }
6849}
6850
6851static int nodelib_direct_traversechar(lua_State *L)
6852{
6853 if (lua_isnil(L, 1)) {
6854 lua_pushcclosure(L, nodelib_aux_nil, 0);
6855 return 1;
6856 } else {
6857 halfword n = nodelib_valid_direct_from_index(L, 1);
6858 if (n) {
6859 if (lua_toboolean(L, 2)) {
6860 if (lua_toboolean(L, 3)) {
6861 n = tex_tail_of_node_list(n);
6862 }
6863 lua_pushcclosure(L, nodelib_direct_aux_prev_char, 0);
6864 } else {
6865 lua_pushcclosure(L, nodelib_direct_aux_next_char, 0);
6866 }
6867 lua_pushinteger(L, n);
6868 lua_pushnil(L);
6869 return 3;
6870 } else {
6871 lua_pushcclosure(L, nodelib_aux_nil, 0);
6872 return 1;
6873 }
6874 }
6875}
6876
6877
6878
6879static int nodelib_direct_aux_next_glyph(lua_State *L)
6880{
6881 halfword t;
6882 if (lua_isnil(L, 2)) {
6883 t = lmt_tohalfword(L, 1) ;
6884 lua_settop(L, 1);
6885 } else {
6886 t = lmt_tohalfword(L, 2) ;
6887 t = node_next(t);
6888 lua_settop(L, 2);
6889 }
6890 while (t && node_type(t) != glyph_node) {
6891 t = node_next(t);
6892 }
6893 if (t) {
6894 lua_pushinteger(L, t);
6895 lua_pushinteger(L, glyph_character(t));
6896 lua_pushinteger(L, glyph_font(t));
6897 return 3;
6898 } else {
6899 lua_pushnil(L);
6900 return 1;
6901 }
6902}
6903
6904static int nodelib_direct_aux_prev_glyph(lua_State *L)
6905{
6906 halfword t;
6907 if (lua_isnil(L, 2)) {
6908 t = lmt_tohalfword(L, 1) ;
6909 lua_settop(L, 1);
6910 } else {
6911 t = lmt_tohalfword(L, 2) ;
6912 t = node_prev(t);
6913 lua_settop(L, 2);
6914 }
6915 while (t && node_type(t) != glyph_node) {
6916 t = node_prev(t);
6917 }
6918 if (t) {
6919 lua_pushinteger(L, t);
6920 lua_pushinteger(L, glyph_character(t));
6921 lua_pushinteger(L, glyph_font(t));
6922 return 3;
6923 } else {
6924 lua_pushnil(L);
6925 return 1;
6926 }
6927}
6928
6929static int nodelib_direct_traverseglyph(lua_State *L)
6930{
6931 if (lua_isnil(L, 1)) {
6932 lua_pushcclosure(L, nodelib_aux_nil, 0);
6933 return 1;
6934 } else {
6935 halfword n = nodelib_valid_direct_from_index(L, 1);
6936 if (n) {
6937 if (lua_toboolean(L, 2)) {
6938 if (lua_toboolean(L, 3)) {
6939 n = tex_tail_of_node_list(n);
6940 }
6941 lua_pushcclosure(L, nodelib_direct_aux_prev_glyph, 0);
6942 } else {
6943 lua_pushcclosure(L, nodelib_direct_aux_next_glyph, 0);
6944 }
6945 lua_pushinteger(L, n);
6946 lua_pushnil(L);
6947 return 3;
6948 } else {
6949 lua_pushcclosure(L, nodelib_aux_nil, 0);
6950 return 1;
6951 }
6952 }
6953}
6954
6955static int nodelib_direct_aux_next_list(lua_State *L)
6956{
6957 halfword t;
6958 if (lua_isnil(L, 2)) {
6959 t = lmt_tohalfword(L, 1) ;
6960 lua_settop(L, 1);
6961 } else {
6962 t = lmt_tohalfword(L, 2) ;
6963 t = node_next(t);
6964 lua_settop(L, 2);
6965 }
6966 while (t && node_type(t) != hlist_node && node_type(t) != vlist_node) {
6967 t = node_next(t);
6968 }
6969 if (t) {
6970 lua_pushinteger(L, t);
6971 lua_pushinteger(L, node_type(t));
6972 lua_pushinteger(L, node_subtype(t));
6973 nodelib_push_direct_or_nil(L, box_list(t));
6974 return 4;
6975 } else {
6976 lua_pushnil(L);
6977 return 1;
6978 }
6979}
6980
6981static int nodelib_direct_aux_prev_list(lua_State *L)
6982{
6983 halfword t;
6984 if (lua_isnil(L, 2)) {
6985 t = lmt_tohalfword(L, 1) ;
6986 lua_settop(L, 1);
6987 } else {
6988 t = lmt_tohalfword(L, 2) ;
6989 t = node_prev(t);
6990 lua_settop(L, 2);
6991 }
6992 while (t && node_type(t) != hlist_node && node_type(t) != vlist_node) {
6993 t = node_prev(t);
6994 }
6995 if (t) {
6996 lua_pushinteger(L, t);
6997 lua_pushinteger(L, node_type(t));
6998 lua_pushinteger(L, node_subtype(t));
6999 nodelib_push_direct_or_nil(L, box_list(t));
7000 return 4;
7001 } else {
7002 lua_pushnil(L);
7003 return 1;
7004 }
7005}
7006
7007static int nodelib_direct_traverselist(lua_State *L)
7008{
7009 if (lua_isnil(L, 1)) {
7010 lua_pushcclosure(L, nodelib_aux_nil, 0);
7011 return 1;
7012 } else {
7013 halfword n = nodelib_valid_direct_from_index(L, 1);
7014 if (n) {
7015 if (lua_toboolean(L, 2)) {
7016 if (lua_toboolean(L, 3)) {
7017 n = tex_tail_of_node_list(n);
7018 }
7019 lua_pushcclosure(L, nodelib_direct_aux_prev_list, 0);
7020 } else {
7021 lua_pushcclosure(L, nodelib_direct_aux_next_list, 0);
7022 }
7023 lua_pushinteger(L, n);
7024 lua_pushnil(L);
7025 return 3;
7026 } else {
7027 lua_pushcclosure(L, nodelib_aux_nil, 0);
7028 return 1;
7029 }
7030 }
7031}
7032
7033
7034
7035static int nodelib_direct_aux_next_leader(lua_State *L)
7036{
7037 halfword t;
7038 if (lua_isnil(L, 2)) {
7039 t = lmt_tohalfword(L, 1) ;
7040 lua_settop(L, 1);
7041 } else {
7042 t = lmt_tohalfword(L, 2) ;
7043 t = node_next(t);
7044 lua_settop(L, 2);
7045 }
7046 while (t && ! ((node_type(t) == hlist_node || node_type(t) == vlist_node) && has_box_package_state(t, package_u_leader_set))) {
7047 t = node_next(t);
7048 }
7049 if (t) {
7050 lua_pushinteger(L, t);
7051 lua_pushinteger(L, node_type(t));
7052 lua_pushinteger(L, node_subtype(t));
7053 nodelib_push_direct_or_nil(L, box_list(t));
7054 return 4;
7055 } else {
7056 lua_pushnil(L);
7057 return 1;
7058 }
7059}
7060
7061static int nodelib_direct_aux_prev_leader(lua_State *L)
7062{
7063 halfword t;
7064 if (lua_isnil(L, 2)) {
7065 t = lmt_tohalfword(L, 1) ;
7066 lua_settop(L, 1);
7067 } else {
7068 t = lmt_tohalfword(L, 2) ;
7069 t = node_prev(t);
7070 lua_settop(L, 2);
7071 }
7072 while (t && ! ((node_type(t) == hlist_node || node_type(t) == vlist_node) && has_box_package_state(t, package_u_leader_set))) {
7073 t = node_prev(t);
7074 }
7075 if (t) {
7076 lua_pushinteger(L, t);
7077 lua_pushinteger(L, node_type(t));
7078 lua_pushinteger(L, node_subtype(t));
7079 nodelib_push_direct_or_nil(L, box_list(t));
7080 return 4;
7081 } else {
7082 lua_pushnil(L);
7083 return 1;
7084 }
7085}
7086
7087static int nodelib_direct_traverseleader(lua_State *L)
7088{
7089 if (lua_isnil(L, 1)) {
7090 lua_pushcclosure(L, nodelib_aux_nil, 0);
7091 return 1;
7092 } else {
7093 halfword n = nodelib_valid_direct_from_index(L, 1);
7094 if (n) {
7095 if (lua_toboolean(L, 2)) {
7096 if (lua_toboolean(L, 3)) {
7097 n = tex_tail_of_node_list(n);
7098 }
7099 lua_pushcclosure(L, nodelib_direct_aux_prev_leader, 0);
7100 } else {
7101 lua_pushcclosure(L, nodelib_direct_aux_next_leader, 0);
7102 }
7103 lua_pushinteger(L, n);
7104 lua_pushnil(L);
7105 return 3;
7106 } else {
7107 lua_pushcclosure(L, nodelib_aux_nil, 0);
7108 return 1;
7109 }
7110 }
7111}
7112
7113
7114
7115static int nodelib_direct_aux_next_italic(lua_State *L)
7116{
7117 halfword t;
7118 if (lua_isnil(L, 2)) {
7119 t = lmt_tohalfword(L, 1) ;
7120 lua_settop(L, 1);
7121 } else {
7122 t = lmt_tohalfword(L, 2) ;
7123 t = node_next(t);
7124 lua_settop(L, 2);
7125 }
7126 while (t && ! (node_type(t) == kern_node && (node_subtype(t) == italic_kern_subtype || node_subtype(t) == left_correction_kern_subtype || node_subtype(t) == right_correction_kern_subtype))) {
7127 t = node_next(t);
7128 }
7129 if (t) {
7130 lua_pushinteger(L, t);
7131 lua_pushinteger(L, node_subtype(t));
7132 return 2;
7133 } else {
7134 lua_pushnil(L);
7135 return 1;
7136 }
7137}
7138
7139static int nodelib_direct_traverseitalic(lua_State *L)
7140{
7141 if (lua_isnil(L, 1)) {
7142 lua_pushcclosure(L, nodelib_aux_nil, 0);
7143 return 1;
7144 } else {
7145 halfword n = nodelib_valid_direct_from_index(L, 1);
7146 if (n) {
7147 lua_pushcclosure(L, nodelib_direct_aux_next_italic, 0);
7148 lua_pushinteger(L, n);
7149 lua_pushnil(L);
7150 return 3;
7151 } else {
7152 lua_pushcclosure(L, nodelib_aux_nil, 0);
7153 return 1;
7154 }
7155 }
7156}
7157
7158static int nodelib_direct_aux_next_content(lua_State *L)
7159{
7160 halfword t;
7161 halfword l = null;
7162 if (lua_isnil(L, 2)) {
7163 t = lmt_tohalfword(L, 1) ;
7164 lua_settop(L, 1);
7165 } else {
7166 t = lmt_tohalfword(L, 2) ;
7167 t = node_next(t);
7168 lua_settop(L, 2);
7169 }
7170 while (t) {
7171 switch (node_type(t)) {
7172 case glyph_node:
7173 case disc_node:
7174 case rule_node:
7175 goto FOUND;
7176 case glue_node:
7177 l = glue_leader_ptr(t);
7178 if (l) {
7179 goto FOUND;
7180 } else {
7181 break;
7182 }
7183 case hlist_node:
7184 case vlist_node:
7185 l = box_list(t);
7186 goto FOUND;
7187 }
7188 t = node_next(t);
7189 }
7190 lua_pushnil(L);
7191 return 1;
7192 FOUND:
7193 lua_pushinteger(L, t);
7194 lua_pushinteger(L, node_type(t));
7195 lua_pushinteger(L, node_subtype(t));
7196 if (l) {
7197 nodelib_push_direct_or_nil(L, l);
7198 return 4;
7199 } else {
7200 return 3;
7201 }
7202}
7203
7204static int nodelib_direct_aux_prev_content(lua_State *L)
7205{
7206 halfword t;
7207 halfword l = null;
7208 if (lua_isnil(L, 2)) {
7209 t = lmt_tohalfword(L, 1) ;
7210 lua_settop(L, 1);
7211 } else {
7212 t = lmt_tohalfword(L, 2) ;
7213 t = node_prev(t);
7214 lua_settop(L, 2);
7215 }
7216 while (t) {
7217 switch (node_type(t)) {
7218 case glyph_node:
7219 case disc_node:
7220 case rule_node:
7221 goto FOUND;
7222 case glue_node:
7223 l = glue_leader_ptr(t);
7224 if (l) {
7225 goto FOUND;
7226 } else {
7227 break;
7228 }
7229 case hlist_node:
7230 case vlist_node:
7231 l = box_list(t);
7232 goto FOUND;
7233 }
7234 t = node_prev(t);
7235 }
7236 lua_pushnil(L);
7237 return 1;
7238 FOUND:
7239 lua_pushinteger(L, t);
7240 lua_pushinteger(L, node_type(t));
7241 lua_pushinteger(L, node_subtype(t));
7242 if (l) {
7243 nodelib_push_direct_or_nil(L, l);
7244 return 4;
7245 } else {
7246 return 3;
7247 }
7248}
7249
7250static int nodelib_direct_traversecontent(lua_State *L)
7251{
7252 if (lua_isnil(L, 1)) {
7253 lua_pushcclosure(L, nodelib_aux_nil, 0);
7254 return 1;
7255 } else {
7256 halfword n = nodelib_valid_direct_from_index(L, 1);
7257 if (n) {
7258 if (lua_toboolean(L, 2)) {
7259 if (lua_toboolean(L, 3)) {
7260 n = tex_tail_of_node_list(n);
7261 }
7262 lua_pushcclosure(L, nodelib_direct_aux_prev_content, 0);
7263 } else {
7264 lua_pushcclosure(L, nodelib_direct_aux_next_content, 0);
7265 }
7266 lua_pushinteger(L, n);
7267 lua_pushnil(L);
7268 return 3;
7269 } else {
7270 lua_pushcclosure(L, nodelib_aux_nil, 0);
7271 return 1;
7272 }
7273 }
7274}
7275
7276
7277
7278
7279
7280
7281
7282static int nodelib_aux_next(lua_State *L)
7283{
7284 halfword t;
7285 if (lua_isnil(L, 2)) {
7286 t = lmt_check_isnode(L, 1);
7287 lua_settop(L, 1);
7288 } else {
7289 t = lmt_check_isnode(L, 2);
7290 t = node_next(t);
7291 lua_settop(L, 2);
7292 }
7293 if (t) {
7294 nodelib_push_node_on_top(L, t);
7295 lua_pushinteger(L, node_type(t));
7296 lua_pushinteger(L, node_subtype(t));
7297 return 3;
7298 } else {
7299 lua_pushnil(L);
7300 return 1;
7301 }
7302}
7303
7304static int nodelib_aux_prev(lua_State *L)
7305{
7306 halfword t;
7307 if (lua_isnil(L, 2)) {
7308 t = lmt_check_isnode(L, 1);
7309 lua_settop(L, 1);
7310 } else {
7311 t = lmt_check_isnode(L, 2);
7312 t = node_prev(t);
7313 lua_settop(L, 2);
7314 }
7315 if (t) {
7316 nodelib_push_node_on_top(L, t);
7317 lua_pushinteger(L, node_type(t));
7318 lua_pushinteger(L, node_subtype(t));
7319 return 3;
7320 } else {
7321 lua_pushnil(L);
7322 return 1;
7323 }
7324}
7325
7326static int nodelib_userdata_traverse(lua_State *L)
7327{
7328 if (lua_isnil(L, 1)) {
7329 lua_pushcclosure(L, nodelib_aux_nil, 0);
7330 return 1;
7331 } else {
7332 halfword n = lmt_check_isnode(L, 1);
7333 if (lua_toboolean(L, 2)) {
7334 if (lua_toboolean(L, 3)) {
7335 n = tex_tail_of_node_list(n);
7336 }
7337 lua_pushcclosure(L, nodelib_aux_prev, 0);
7338 } else {
7339 lua_pushcclosure(L, nodelib_aux_next, 0);
7340 }
7341 lmt_push_node_fast(L, n);
7342 lua_pushnil(L);
7343 return 3;
7344 }
7345}
7346
7347static int nodelib_aux_next_filtered(lua_State *L)
7348{
7349 halfword t;
7350 int i = (int) lua_tointeger(L, lua_upvalueindex(1));
7351 if (lua_isnil(L, 2)) {
7352
7353 t = lmt_check_isnode(L, 1);
7354 lua_settop(L,1);
7355 } else {
7356 t = lmt_check_isnode(L, 2);
7357 t = node_next(t);
7358 lua_settop(L,2);
7359 }
7360 while (t && node_type(t) != i) {
7361 t = node_next(t);
7362 }
7363 if (t) {
7364 nodelib_push_node_on_top(L, t);
7365 lua_pushinteger(L, node_subtype(t));
7366 return 2;
7367 } else {
7368 lua_pushnil(L);
7369 return 1;
7370 }
7371}
7372
7373static int nodelib_aux_prev_filtered(lua_State *L)
7374{
7375 halfword t;
7376 int i = (int) lua_tointeger(L, lua_upvalueindex(1));
7377 if (lua_isnil(L, 2)) {
7378
7379 t = lmt_check_isnode(L, 1);
7380 lua_settop(L,1);
7381 } else {
7382 t = lmt_check_isnode(L, 2);
7383 t = node_prev(t);
7384 lua_settop(L,2);
7385 }
7386 while (t && node_type(t) != i) {
7387 t = node_prev(t);
7388 }
7389 if (t) {
7390 nodelib_push_node_on_top(L, t);
7391 lua_pushinteger(L, node_subtype(t));
7392 return 2;
7393 } else {
7394 lua_pushnil(L);
7395 return 1;
7396 }
7397}
7398
7399static int nodelib_userdata_traverse_id(lua_State *L)
7400{
7401 if (lua_isnil(L, 2)) {
7402 lua_pushcclosure(L, nodelib_aux_nil, 0);
7403 return 1;
7404 } else {
7405 halfword n = lmt_check_isnode(L, 2);
7406 if (lua_toboolean(L, 3)) {
7407 if (lua_toboolean(L, 4)) {
7408 n = tex_tail_of_node_list(n);
7409 }
7410 lua_settop(L, 1);
7411 lua_pushcclosure(L, nodelib_aux_prev_filtered, 1);
7412 } else {
7413 lua_settop(L, 1);
7414 lua_pushcclosure(L, nodelib_aux_next_filtered, 1);
7415 }
7416 lmt_push_node_fast(L, n);
7417 lua_pushnil(L);
7418 return 3;
7419 }
7420}
7421
7422
7423
7424
7425
7426
7427# define length_usage common_usage
7428# define count_usage common_usage
7429
7430static int nodelib_direct_length(lua_State *L)
7431{
7432 halfword first = nodelib_valid_direct_from_index(L, 1);
7433 halfword last = nodelib_valid_direct_from_index(L, 2);
7434 int count = 0;
7435 if (first) {
7436 while (first != last) {
7437 count++;
7438 first = node_next(first);
7439 }
7440 }
7441 lua_pushinteger(L, count);
7442 return 1;
7443}
7444
7445static int nodelib_direct_count(lua_State *L)
7446{
7447 quarterword id = lmt_toquarterword(L, 1);
7448 halfword first = nodelib_valid_direct_from_index(L, 2);
7449 halfword last = nodelib_valid_direct_from_index(L, 3);
7450 int count = 0;
7451 if (first) {
7452 while (first != last) {
7453 if (node_type(first) == id) {
7454 count++;
7455 }
7456 first = node_next(first);
7457 }
7458 }
7459 lua_pushinteger(L, count);
7460 return 1;
7461}
7462
7463
7464
7465static inline int nodelib_getattribute_value(lua_State *L, halfword n, int index)
7466{
7467 halfword key = (halfword) lua_tointeger(L, index);
7468 halfword val = tex_has_attribute(n, key, unused_attribute_value);
7469 if (val == unused_attribute_value) {
7470 lua_pushnil(L);
7471 } else {
7472 lua_pushinteger(L, val);
7473 }
7474 return 1;
7475}
7476
7477static inline void nodelib_setattribute_value(lua_State *L, halfword n, int kindex, int vindex)
7478{
7479 if (lua_gettop(L) >= kindex) {
7480 halfword key = lmt_tohalfword(L, kindex);
7481 halfword val = lmt_opthalfword(L, vindex, unused_attribute_value);
7482 if (val == unused_attribute_value) {
7483 tex_unset_attribute(n, key, val);
7484 } else {
7485 tex_set_attribute(n, key, val);
7486 }
7487 } else {
7488 luaL_error(L, "incorrect number of arguments");
7489 }
7490}
7491
7492
7493
7494
7495
7510
7511typedef enum lua_field_errors {
7512 lua_no_field_error,
7513 lua_set_field_error,
7514 lua_get_field_error,
7515} lua_field_errors ;
7516
7517static int last_field_error = lua_no_field_error;
7518static int ignore_field_error = 0;
7519
7520static int nodelib_common_getfield(lua_State *L, int direct, halfword n)
7521{
7522 last_field_error = lua_no_field_error;
7523 switch (lua_type(L, 2)) {
7524 case LUA_TNUMBER:
7525 {
7526 return nodelib_getattribute_value(L, n, 2);
7527 }
7528 case LUA_TSTRING:
7529 {
7530 const char *s = lua_tostring(L, 2);
7531 int t = node_type(n);
7532 if (lua_key_eq(s, id)) {
7533 lua_pushinteger(L, t);
7534 } else if (lua_key_eq(s, next)) {
7535 if (tex_nodetype_has_next(t)) {
7536 nodelib_push_direct_or_node(L, direct, node_next(n));
7537 } else {
7538 goto CANTGET;
7539 }
7540 } else if (lua_key_eq(s, prev)) {
7541 if (tex_nodetype_has_prev(t)) {
7542 nodelib_push_direct_or_node(L, direct, node_prev(n));
7543 } else {
7544 goto CANTGET;
7545 }
7546 } else if (lua_key_eq(s, attr)) {
7547 if (tex_nodetype_has_attributes(t)) {
7548 nodelib_push_direct_or_node(L, direct, node_attr(n));
7549 } else {
7550 goto CANTGET;
7551 }
7552 } else if (lua_key_eq(s, subtype)) {
7553 if (tex_nodetype_has_subtype(t)) {
7554 lua_pushinteger(L, node_subtype(n));
7555 } else {
7556 goto CANTGET;
7557 }
7558 } else {
7559 switch(t) {
7560 case glyph_node:
7561 if (lua_key_eq(s, font)) {
7562 lua_pushinteger(L, glyph_font(n));
7563 } else if (lua_key_eq(s, char)) {
7564 lua_pushinteger(L, glyph_character(n));
7565 } else if (lua_key_eq(s, xoffset)) {
7566 lua_pushinteger(L, glyph_x_offset(n));
7567 } else if (lua_key_eq(s, yoffset)) {
7568 lua_pushinteger(L, glyph_y_offset(n));
7569 } else if (lua_key_eq(s, data)) {
7570 lua_pushinteger(L, glyph_data(n));
7571 } else if (lua_key_eq(s, width)) {
7572 lua_pushinteger(L, tex_glyph_width(n));
7573 } else if (lua_key_eq(s, height)) {
7574 lua_pushinteger(L, tex_glyph_height(n));
7575 } else if (lua_key_eq(s, depth)) {
7576
7577 lua_pushinteger(L, tex_glyph_depth(n));
7578 } else if (lua_key_eq(s, total)) {
7579
7580 lua_pushinteger(L, tex_glyph_total(n));
7581 } else if (lua_key_eq(s, scale)) {
7582 lua_pushinteger(L, glyph_scale(n));
7583 } else if (lua_key_eq(s, xscale)) {
7584 lua_pushinteger(L, glyph_x_scale(n));
7585 } else if (lua_key_eq(s, yscale)) {
7586 lua_pushinteger(L, glyph_y_scale(n));
7587 } else if (lua_key_eq(s, expansion)) {
7588 lua_pushinteger(L, glyph_expansion(n));
7589 } else if (lua_key_eq(s, state)) {
7590 lua_pushinteger(L, get_glyph_state(n));
7591 } else if (lua_key_eq(s, script)) {
7592 lua_pushinteger(L, get_glyph_script(n));
7593 } else if (lua_key_eq(s, language)) {
7594 lua_pushinteger(L, get_glyph_language(n));
7595 } else if (lua_key_eq(s, lhmin)) {
7596 lua_pushinteger(L, get_glyph_lhmin(n));
7597 } else if (lua_key_eq(s, rhmin)) {
7598 lua_pushinteger(L, get_glyph_rhmin(n));
7599 } else if (lua_key_eq(s, left)) {
7600 lua_pushinteger(L, get_glyph_left(n));
7601 } else if (lua_key_eq(s, right)) {
7602 lua_pushinteger(L, get_glyph_right(n));
7603 } else if (lua_key_eq(s, slant)) {
7604 lua_pushinteger(L, glyph_slant(n));
7605 } else if (lua_key_eq(s, weight)) {
7606 lua_pushinteger(L, glyph_weight(n));
7607 } else if (lua_key_eq(s, uchyph)) {
7608 lua_pushinteger(L, get_glyph_uchyph(n));
7609 } else if (lua_key_eq(s, hyphenate)) {
7610 lua_pushinteger(L, get_glyph_hyphenate(n));
7611 } else if (lua_key_eq(s, options)) {
7612 lua_pushinteger(L, get_glyph_options(n));
7613 } else if (lua_key_eq(s, discpart)) {
7614 lua_pushinteger(L, get_glyph_discpart(n));
7615 } else if (lua_key_eq(s, protected)) {
7616 lua_pushinteger(L, glyph_protected(n));
7617 } else if (lua_key_eq(s, properties)) {
7618 lua_pushinteger(L, glyph_properties(n));
7619 } else if (lua_key_eq(s, group)) {
7620 lua_pushinteger(L, glyph_group(n));
7621 } else if (lua_key_eq(s, index)) {
7622 lua_pushinteger(L, glyph_index(n));
7623 } else if (lua_key_eq(s, control)) {
7624 lua_pushinteger(L, get_glyph_control(n));
7625 } else {
7626 goto CANTGET;
7627 }
7628 break;
7629 case hlist_node:
7630 case vlist_node:
7631
7632 if (lua_key_eq(s, list) || lua_key_eq(s, head)) {
7633 nodelib_push_direct_or_node_node_prev(L, direct, box_list(n));
7634 } else if (lua_key_eq(s, width)) {
7635 lua_pushinteger(L, box_width(n));
7636 } else if (lua_key_eq(s, height)) {
7637 lua_pushinteger(L, box_height(n));
7638 } else if (lua_key_eq(s, depth)) {
7639 lua_pushinteger(L, box_depth(n));
7640 } else if (lua_key_eq(s, total)) {
7641 lua_pushinteger(L, box_total(n));
7642 } else if (lua_key_eq(s, direction)) {
7643 lua_pushinteger(L, checked_direction_value(box_dir(n)));
7644 } else if (lua_key_eq(s, shift)) {
7645 lua_pushinteger(L, box_shift_amount(n));
7646 } else if (lua_key_eq(s, glueorder)) {
7647 lua_pushinteger(L, box_glue_order(n));
7648 } else if (lua_key_eq(s, gluesign)) {
7649 lua_pushinteger(L, box_glue_sign(n));
7650 } else if (lua_key_eq(s, glueset)) {
7651 lua_pushnumber(L, (double) box_glue_set(n));
7652 } else if (lua_key_eq(s, geometry)) {
7653 lua_pushinteger(L, box_geometry(n));
7654 } else if (lua_key_eq(s, orientation)) {
7655 lua_pushinteger(L, box_orientation(n));
7656 } else if (lua_key_eq(s, anchor)) {
7657 lua_pushinteger(L, box_anchor(n));
7658 } else if (lua_key_eq(s, source)) {
7659 lua_pushinteger(L, box_source_anchor(n));
7660 } else if (lua_key_eq(s, target)) {
7661 lua_pushinteger(L, box_target_anchor(n));
7662 } else if (lua_key_eq(s, xoffset)) {
7663 lua_pushinteger(L, box_x_offset(n));
7664 } else if (lua_key_eq(s, yoffset)) {
7665 lua_pushinteger(L, box_y_offset(n));
7666 } else if (lua_key_eq(s, woffset)) {
7667 lua_pushinteger(L, box_w_offset(n));
7668 } else if (lua_key_eq(s, hoffset)) {
7669 lua_pushinteger(L, box_h_offset(n));
7670 } else if (lua_key_eq(s, doffset)) {
7671 lua_pushinteger(L, box_d_offset(n));
7672 } else if (lua_key_eq(s, pre)) {
7673 nodelib_push_direct_or_node(L, direct, box_pre_migrated(n));
7674 } else if (lua_key_eq(s, post)) {
7675 nodelib_push_direct_or_node(L, direct, box_post_migrated(n));
7676 } else if (lua_key_eq(s, state)) {
7677 lua_pushinteger(L, box_package_state(n));
7678 } else if (lua_key_eq(s, index)) {
7679 lua_pushinteger(L, box_index(n));
7680 } else if (lua_key_eq(s, except)) {
7681 nodelib_push_direct_or_node(L, direct, box_except(n));
7682 } else {
7683 goto CANTGET;
7684 }
7685 break;
7686 case disc_node:
7687 if (lua_key_eq(s, pre)) {
7688 nodelib_push_direct_or_node(L, direct, disc_pre_break_head(n));
7689 } else if (lua_key_eq(s, post)) {
7690 nodelib_push_direct_or_node(L, direct, disc_post_break_head(n));
7691 } else if (lua_key_eq(s, replace)) {
7692 nodelib_push_direct_or_node(L, direct, disc_no_break_head(n));
7693 } else if (lua_key_eq(s, penalty)) {
7694 lua_pushinteger(L, disc_penalty(n));
7695 } else if (lua_key_eq(s, options)) {
7696 lua_pushinteger(L, disc_options(n));
7697 } else if (lua_key_eq(s, class)) {
7698 lua_pushinteger(L, disc_class(n));
7699 } else {
7700 goto CANTGET;
7701 }
7702 break;
7703 case glue_node:
7704 if (lua_key_eq(s, width)) {
7705 lua_pushinteger(L, glue_amount(n));
7706 } else if (lua_key_eq(s, stretch)) {
7707 lua_pushinteger(L, glue_stretch(n));
7708 } else if (lua_key_eq(s, shrink)) {
7709 lua_pushinteger(L, glue_shrink(n));
7710 } else if (lua_key_eq(s, stretchorder)) {
7711 lua_pushinteger(L, glue_stretch_order(n));
7712 } else if (lua_key_eq(s, shrinkorder)) {
7713 lua_pushinteger(L, glue_shrink_order(n));
7714 } else if (lua_key_eq(s, leader)) {
7715 nodelib_push_direct_or_node(L, direct, glue_leader_ptr(n));
7716 } else if (lua_key_eq(s, font)) {
7717 lua_pushinteger(L, glue_font(n));
7718 } else if (lua_key_eq(s, data)) {
7719 lua_pushinteger(L, glue_data(n));
7720 } else if (lua_key_eq(s, options)) {
7721 lua_pushinteger(L, glue_options(n));
7722 } else {
7723 goto CANTGET;
7724 }
7725 break;
7726 case kern_node:
7727 if (lua_key_eq(s, kern)) {
7728 lua_pushinteger(L, kern_amount(n));
7729 } else if (lua_key_eq(s, expansion)) {
7730 lua_pushinteger(L, kern_expansion(n));
7731 } else {
7732 goto CANTGET;
7733 }
7734 break;
7735 case penalty_node:
7736 if (lua_key_eq(s, penalty)) {
7737 lua_pushinteger(L, penalty_amount(n));
7738 } else if (lua_key_eq(s, options)) {
7739 lua_pushinteger(L, penalty_options(n));
7740 } else {
7741 goto CANTGET;
7742 }
7743 break;
7744 case rule_node:
7745
7746 if (lua_key_eq(s, width)) {
7747 lua_pushinteger(L, rule_width(n));
7748 } else if (lua_key_eq(s, height)) {
7749 lua_pushinteger(L, rule_height(n));
7750 } else if (lua_key_eq(s, depth)) {
7751 lua_pushinteger(L, rule_depth(n));
7752 } else if (lua_key_eq(s, total)) {
7753 lua_pushinteger(L, rule_total(n));
7754 } else if (lua_key_eq(s, xoffset)) {
7755 lua_pushinteger(L, rule_x_offset(n));
7756 } else if (lua_key_eq(s, yoffset)) {
7757 lua_pushinteger(L, rule_y_offset(n));
7758 } else if (lua_key_eq(s, left)) {
7759 lua_pushinteger(L, tex_get_rule_left(n));
7760 } else if (lua_key_eq(s, right)) {
7761 lua_pushinteger(L, tex_get_rule_right(n));
7762 } else if (lua_key_eq(s, on)) {
7763 lua_pushinteger(L, tex_get_rule_on(n));
7764 } else if (lua_key_eq(s, off)) {
7765 lua_pushinteger(L, tex_get_rule_off(n));
7766 } else if (lua_key_eq(s, data)) {
7767 lua_pushinteger(L, rule_data(n));
7768 } else if (lua_key_eq(s, options)) {
7769 lua_pushinteger(L, rule_options(n));
7770 } else if (lua_key_eq(s, font)) {
7771 lua_pushinteger(L, tex_get_rule_font(n, text_style));
7772 } else if (lua_key_eq(s, fam)) {
7773 lua_pushinteger(L, tex_get_rule_font(n, text_style));
7774 } else if (lua_key_eq(s, char)) {
7775 lua_pushinteger(L, rule_strut_character(n));
7776 } else {
7777 goto CANTGET;
7778 }
7779 break;
7780 case dir_node:
7781 if (lua_key_eq(s, direction)) {
7782 lua_pushinteger(L, dir_direction(n));
7783 } else if (lua_key_eq(s, level)) {
7784 lua_pushinteger(L, dir_level(n));
7785 } else {
7786 goto CANTGET;
7787 }
7788 break;
7789 case whatsit_node:
7790 goto CANTGET;
7791 case par_node:
7792
7793 if (lua_key_eq(s, interlinepenalty)) {
7794 lua_pushinteger(L, tex_get_local_interline_penalty(n));
7795 } else if (lua_key_eq(s, brokenpenalty)) {
7796 lua_pushinteger(L, tex_get_local_broken_penalty(n));
7797 } else if (lua_key_eq(s, tolerance)) {
7798 lua_pushinteger(L, tex_get_local_tolerance(n));
7799 } else if (lua_key_eq(s, pretolerance)) {
7800 lua_pushinteger(L, tex_get_local_pre_tolerance(n));
7801 } else if (lua_key_eq(s, direction)) {
7802 lua_pushinteger(L, par_dir(n));
7803 } else if (lua_key_eq(s, leftbox)) {
7804 nodelib_push_direct_or_node(L, direct, par_box_left(n));
7805 } else if (lua_key_eq(s, leftboxwidth)) {
7806 lua_pushinteger(L, tex_get_local_left_width(n));
7807 } else if (lua_key_eq(s, rightbox)) {
7808 nodelib_push_direct_or_node(L, direct, par_box_right(n));
7809 } else if (lua_key_eq(s, rightboxwidth)) {
7810 lua_pushinteger(L, tex_get_local_right_width(n));
7811 } else if (lua_key_eq(s, middlebox)) {
7812 nodelib_push_direct_or_node(L, direct, par_box_middle(n));
7813 } else {
7814 goto CANTGET;
7815 }
7816 break;
7817 case math_char_node:
7818 case math_text_char_node:
7819 if (lua_key_eq(s, fam)) {
7820 lua_pushinteger(L, kernel_math_family(n));
7821 } else if (lua_key_eq(s, char)) {
7822 lua_pushinteger(L, kernel_math_character(n));
7823 } else if (lua_key_eq(s, font)) {
7824 lua_pushinteger(L, tex_fam_fnt(kernel_math_family(n), 0));
7825 } else if (lua_key_eq(s, options)) {
7826 lua_pushinteger(L, kernel_math_options(n));
7827 } else if (lua_key_eq(s, properties)) {
7828 lua_pushinteger(L, kernel_math_properties(n));
7829 } else if (lua_key_eq(s, group)) {
7830 lua_pushinteger(L, kernel_math_group(n));
7831 } else if (lua_key_eq(s, index)) {
7832 lua_pushinteger(L, kernel_math_index(n));
7833 } else {
7834 goto CANTGET;
7835 }
7836 break;
7837 case mark_node:
7838 if (lua_key_eq(s, index) || lua_key_eq(s, class)) {
7839 lua_pushinteger(L, mark_index(n));
7840 } else if (lua_key_eq(s, data) || lua_key_eq(s, mark)) {
7841 if (lua_toboolean(L, 3)) {
7842 lmt_token_list_to_luastring(L, mark_ptr(n), 0, 0, 0);
7843 } else {
7844 lmt_token_list_to_lua(L, mark_ptr(n));
7845 }
7846 } else {
7847 goto CANTGET;
7848 }
7849 break;
7850 case insert_node:
7851 if (lua_key_eq(s, index)) {
7852 lua_pushinteger(L, insert_index(n));
7853 } else if (lua_key_eq(s, cost)) {
7854 lua_pushinteger(L, insert_float_cost(n));
7855 } else if (lua_key_eq(s, depth)) {
7856 lua_pushinteger(L, insert_max_depth(n));
7857 } else if (lua_key_eq(s, height) || lua_key_eq(s, total)) {
7858 lua_pushinteger(L, insert_total_height(n));
7859 } else if (lua_key_eq(s, list) || lua_key_eq(s, head)) {
7860 nodelib_push_direct_or_node_node_prev(L, direct, insert_list(n));
7861 } else if (lua_key_eq(s, data)) {
7862 lua_pushinteger(L, insert_identifier(n));
7863 } else if (lua_key_eq(s, lineheight)) {
7864 lua_pushinteger(L, insert_line_height(n));
7865 } else if (lua_key_eq(s, linedepth)) {
7866 lua_pushinteger(L, insert_line_depth(n));
7867 } else if (lua_key_eq(s, stretch)) {
7868 lua_pushinteger(L, insert_stretch(n));
7869 } else if (lua_key_eq(s, shrink)) {
7870 lua_pushinteger(L, insert_shrink(n));
7871 } else {
7872 goto CANTGET;
7873 }
7874 break;
7875 case math_node:
7876 if (lua_key_eq(s, surround)) {
7877 lua_pushinteger(L, math_surround(n));
7878 } else if (lua_key_eq(s, width)) {
7879 lua_pushinteger(L, math_amount(n));
7880 } else if (lua_key_eq(s, stretch)) {
7881 lua_pushinteger(L, math_stretch(n));
7882 } else if (lua_key_eq(s, shrink)) {
7883 lua_pushinteger(L, math_shrink(n));
7884 } else if (lua_key_eq(s, stretchorder)) {
7885 lua_pushinteger(L, math_stretch_order(n));
7886 } else if (lua_key_eq(s, shrinkorder)) {
7887 lua_pushinteger(L, math_shrink_order(n));
7888 } else if (lua_key_eq(s, penalty)) {
7889 lua_pushinteger(L, math_penalty(n));
7890 } else if (lua_key_eq(s, options)) {
7891 lua_pushinteger(L, math_options(n));
7892 } else {
7893 goto CANTGET;
7894 }
7895 break;
7896 case style_node:
7897 if (lua_key_eq(s, style)) {
7898 lmt_push_math_style_name(L, style_style(n));
7899 } else {
7900 goto CANTGET;
7901 }
7902 break;
7903 case parameter_node:
7904 if (lua_key_eq(s, style)) {
7905 lmt_push_math_style_name(L, parameter_style(n));
7906 } else if (lua_key_eq(s, name)) {
7907 lmt_push_math_parameter(L, parameter_name(n));
7908 } else if (lua_key_eq(s, value)) {
7909 halfword code = parameter_name(n);
7910 if (code < 0 || code >= math_parameter_last) {
7911
7912 lua_pushnil(L);
7913 } else if (math_parameter_value_type(code)) {
7914
7915 lua_pushnil(L);
7916 } else {
7917 lua_pushinteger(L, parameter_value(n));
7918 }
7919 } else {
7920 goto CANTGET;
7921 }
7922 break;
7923 case simple_noad:
7924 case radical_noad:
7925 case fraction_noad:
7926 case accent_noad:
7927 case fence_noad:
7928 if (lua_key_eq(s, nucleus)) {
7929 nodelib_push_direct_or_nil(L, noad_nucleus(n));
7930 } else if (lua_key_eq(s, sub)) {
7931 nodelib_push_direct_or_nil(L, noad_subscr(n));
7932 } else if (lua_key_eq(s, sup)) {
7933 nodelib_push_direct_or_nil(L, noad_supscr(n));
7934 } else if (lua_key_eq(s, prime)) {
7935 nodelib_push_direct_or_nil(L, noad_prime(n));
7936 } else if (lua_key_eq(s, subpre)) {
7937 nodelib_push_direct_or_nil(L, noad_subprescr(n));
7938 } else if (lua_key_eq(s, suppre)) {
7939 nodelib_push_direct_or_nil(L, noad_supprescr(n));
7940 } else if (lua_key_eq(s, options)) {
7941 lua_pushinteger(L, noad_options(n));
7942 } else if (lua_key_eq(s, source)) {
7943 lua_pushinteger(L, noad_source(n));
7944 } else if (lua_key_eq(s, scriptorder)) {
7945 lua_pushinteger(L, noad_script_order(n));
7946 } else if (lua_key_eq(s, class)) {
7947 lua_pushinteger(L, get_noad_main_class(n));
7948 lua_pushinteger(L, get_noad_left_class(n));
7949 lua_pushinteger(L, get_noad_right_class(n));
7950 return 3;
7951 } else if (lua_key_eq(s, fam)) {
7952 lua_pushinteger(L, noad_family(n));
7953 } else {
7954 switch(t) {
7955 case simple_noad:
7956 goto CANTGET;
7957 case radical_noad:
7958 if (lua_key_eq(s, left) || lua_key_eq(s, delimiter)) {
7959 nodelib_push_direct_or_node(L, direct, radical_left_delimiter(n));
7960 } else if (lua_key_eq(s, right)) {
7961 nodelib_push_direct_or_node(L, direct, radical_right_delimiter(n));
7962 } else if (lua_key_eq(s, top)) {
7963 nodelib_push_direct_or_node(L, direct, radical_top_delimiter(n));
7964 } else if (lua_key_eq(s, bottom)) {
7965 nodelib_push_direct_or_node(L, direct, radical_bottom_delimiter(n));
7966 } else if (lua_key_eq(s, degree)) {
7967 nodelib_push_direct_or_node(L, direct, radical_degree(n));
7968 } else if (lua_key_eq(s, width)) {
7969 lua_pushinteger(L, noad_width(n));
7970 } else {
7971 goto CANTGET;
7972 }
7973 break;
7974 case fraction_noad:
7975 if (lua_key_eq(s, width)) {
7976 lua_pushinteger(L, fraction_rule_thickness(n));
7977 } else if (lua_key_eq(s, numerator)) {
7978 nodelib_push_direct_or_nil(L, fraction_numerator(n));
7979 } else if (lua_key_eq(s, denominator)) {
7980 nodelib_push_direct_or_nil(L, fraction_denominator(n));
7981 } else if (lua_key_eq(s, left)) {
7982 nodelib_push_direct_or_nil(L, fraction_left_delimiter(n));
7983 } else if (lua_key_eq(s, right)) {
7984 nodelib_push_direct_or_nil(L, fraction_right_delimiter(n));
7985 } else if (lua_key_eq(s, middle)) {
7986 nodelib_push_direct_or_nil(L, fraction_middle_delimiter(n));
7987 } else {
7988 goto CANTGET;
7989 }
7990 break;
7991 case accent_noad:
7992 if (lua_key_eq(s, top) || lua_key_eq(s, topaccent)) {
7993 nodelib_push_direct_or_node(L, direct, accent_top_character(n));
7994 } else if (lua_key_eq(s, bottom) || lua_key_eq(s, bottomaccent)) {
7995 nodelib_push_direct_or_node(L, direct, accent_bottom_character(n));
7996 } else if (lua_key_eq(s, middle) || lua_key_eq(s, overlayaccent)) {
7997 nodelib_push_direct_or_node(L, direct, accent_middle_character(n));
7998 } else if (lua_key_eq(s, fraction)) {
7999 lua_pushinteger(L, accent_fraction(n));
8000 } else {
8001 goto CANTGET;
8002 }
8003 break;
8004 case fence_noad:
8005 if (lua_key_eq(s, delimiter)) {
8006 nodelib_push_direct_or_node(L, direct, fence_delimiter(n));
8007 } else if (lua_key_eq(s, top)) {
8008 nodelib_push_direct_or_node(L, direct, fence_delimiter_top(n));
8009 } else if (lua_key_eq(s, bottom)) {
8010 nodelib_push_direct_or_node(L, direct, fence_delimiter_bottom(n));
8011 } else if (lua_key_eq(s, italic)) {
8012 lua_pushinteger(L, noad_italic(n));
8013 } else if (lua_key_eq(s, height)) {
8014 lua_pushinteger(L, noad_height(n));
8015 } else if (lua_key_eq(s, depth)) {
8016 lua_pushinteger(L, noad_depth(n));
8017 } else if (lua_key_eq(s, total)) {
8018 lua_pushinteger(L, noad_total(n));
8019 } else if (lua_key_eq(s, variant)) {
8020 lua_pushinteger(L, fence_delimiter_variant(n));
8021 } else {
8022 goto CANTGET;
8023 }
8024 break;
8025 }
8026 }
8027 break;
8028 case delimiter_node:
8029 if (lua_key_eq(s, smallfamily)) {
8030 lua_pushinteger(L, delimiter_small_family(n));
8031 } else if (lua_key_eq(s, smallchar)) {
8032 lua_pushinteger(L, delimiter_small_character(n));
8033 } else if (lua_key_eq(s, largefamily)) {
8034 lua_pushinteger(L, delimiter_large_family(n));
8035 } else if (lua_key_eq(s, largechar)) {
8036 lua_pushinteger(L, delimiter_large_character(n));
8037 } else {
8038 goto CANTGET;
8039 }
8040 break;
8041 case sub_box_node:
8042 case sub_mlist_node:
8043 if (lua_key_eq(s, list) || lua_key_eq(s, head)) {
8044 nodelib_push_direct_or_node_node_prev(L, direct, kernel_math_list(n));
8045 } else {
8046 goto CANTGET;
8047 }
8048 break;
8049 case split_node:
8050 if (lua_key_eq(s, index)) {
8051 lua_push_integer(L, split_insert_index(n));
8052 } else if (lua_key_eq(s, lastinsert)) {
8053 nodelib_push_direct_or_node(L, direct, split_last_insert(n));
8054 } else if (lua_key_eq(s, bestinsert)) {
8055 nodelib_push_direct_or_node(L, direct, split_best_insert(n));
8056 } else if (lua_key_eq(s, broken)) {
8057 nodelib_push_direct_or_node(L, direct, split_broken(n));
8058 } else if (lua_key_eq(s, brokeninsert)) {
8059 nodelib_push_direct_or_node(L, direct, split_broken_insert(n));
8060 } else {
8061 goto CANTGET;
8062 }
8063 break;
8064 case choice_node:
8065
8066 if (lua_key_eq(s, display)) {
8067 nodelib_push_direct_or_node(L, direct, choice_display_mlist(n));
8068 } else if (lua_key_eq(s, text)) {
8069 nodelib_push_direct_or_node(L, direct, choice_text_mlist(n));
8070 } else if (lua_key_eq(s, script)) {
8071 nodelib_push_direct_or_node(L, direct, choice_script_mlist(n));
8072 } else if (lua_key_eq(s, scriptscript)) {
8073 nodelib_push_direct_or_node(L, direct, choice_script_script_mlist(n));
8074 } else if (lua_key_eq(s, pre)) {
8075 nodelib_push_direct_or_node(L, direct, choice_pre_break(n));
8076 } else if (lua_key_eq(s, post)) {
8077 nodelib_push_direct_or_node(L, direct, choice_post_break(n));
8078 } else if (lua_key_eq(s, replace)) {
8079 nodelib_push_direct_or_node(L, direct, choice_no_break(n));
8080 } else {
8081 goto CANTGET;
8082 }
8083 break;
8084 case attribute_node:
8085 switch (node_subtype(n)) {
8086 case attribute_list_subtype:
8087 if (lua_key_eq(s, count)) {
8088 lua_pushinteger(L, attribute_count(n));
8089 } else if (lua_key_eq(s, data)) {
8090 nodelib_push_attribute_data(L, node_attr(n));
8091 } else {
8092 goto CANTGET;
8093 }
8094 break;
8095 case attribute_value_subtype:
8096 if (lua_key_eq(s, index) || lua_key_eq(s, number)) {
8097 lua_pushinteger(L, attribute_index(n));
8098 } else if (lua_key_eq(s, value)) {
8099 lua_pushinteger(L, attribute_value(n));
8100 } else {
8101 goto CANTGET;
8102 }
8103 break;
8104 default:
8105 goto CANTGET;
8106 }
8107 break;
8108 case adjust_node:
8109 if (lua_key_eq(s, list) || lua_key_eq(s, head)) {
8110 nodelib_push_direct_or_node_node_prev(L, direct, adjust_list(n));
8111 } else if (lua_key_eq(s, index) || lua_key_eq(s, class)) {
8112 lua_pushinteger(L, adjust_index(n));
8113 } else {
8114 goto CANTGET;
8115 }
8116 break;
8117 case unset_node:
8118 if (lua_key_eq(s, width)) {
8119 lua_pushinteger(L, box_width(n));
8120 } else if (lua_key_eq(s, height)) {
8121 lua_pushinteger(L, box_height(n));
8122 } else if (lua_key_eq(s, depth)) {
8123 lua_pushinteger(L, box_depth(n));
8124 } else if (lua_key_eq(s, total)) {
8125 lua_pushinteger(L, box_total(n));
8126 } else if (lua_key_eq(s, direction)) {
8127 lua_pushinteger(L, checked_direction_value(box_dir(n)));
8128 } else if (lua_key_eq(s, shrink)) {
8129 lua_pushinteger(L, box_glue_shrink(n));
8130 } else if (lua_key_eq(s, glueorder)) {
8131 lua_pushinteger(L, box_glue_order(n));
8132 } else if (lua_key_eq(s, gluesign)) {
8133 lua_pushinteger(L, box_glue_sign(n));
8134 } else if (lua_key_eq(s, stretch)) {
8135 lua_pushinteger(L, box_glue_stretch(n));
8136 } else if (lua_key_eq(s, count)) {
8137 lua_pushinteger(L, box_span_count(n));
8138 } else if (lua_key_eq(s, list) || lua_key_eq(s, head)) {
8139 nodelib_push_direct_or_node_node_prev(L, direct, box_list(n));
8140 } else {
8141 goto CANTGET;
8142 }
8143 break;
8144
8149 case boundary_node:
8150 if (lua_key_eq(s, data) || lua_key_eq(s, value)) {
8151 lua_pushinteger(L, boundary_data(n));
8152 } else if (lua_key_eq(s, reserved)) {
8153 lua_pushinteger(L, boundary_reserved(n));
8154 } else {
8155 goto CANTGET;
8156 }
8157 break;
8158 case glue_spec_node:
8159 if (lua_key_eq(s, width)) {
8160 lua_pushinteger(L, glue_amount(n));
8161 } else if (lua_key_eq(s, stretch)) {
8162 lua_pushinteger(L, glue_stretch(n));
8163 } else if (lua_key_eq(s, shrink)) {
8164 lua_pushinteger(L, glue_shrink(n));
8165 } else if (lua_key_eq(s, stretchorder)) {
8166 lua_pushinteger(L, glue_stretch_order(n));
8167 } else if (lua_key_eq(s, shrinkorder)) {
8168 lua_pushinteger(L, glue_shrink_order(n));
8169 } else {
8170 last_field_error = lua_get_field_error;
8171 lua_pushnil(L);
8172 }
8173 break;
8174 default:
8175 goto CANTGET;
8176 }
8177 }
8178 break;
8179 }
8180 default:
8181 {
8182 CANTGET:
8183 last_field_error = lua_get_field_error;
8184 lua_pushnil(L);
8185 break;
8186 }
8187 }
8188 return 1;
8189}
8190
8191# define getfield_usage common_usage
8192
8193static int nodelib_direct_getfield(lua_State *L)
8194{
8195 halfword n = nodelib_valid_direct_from_index(L, 1);
8196 if (n) {
8197 return nodelib_common_getfield(L, 1, n);
8198 } else {
8199 lua_pushnil(L);
8200 return 1;
8201 }
8202}
8203
8204static int nodelib_userdata_index(lua_State *L)
8205{
8206 halfword n = *((halfword *) lua_touserdata(L, 1));
8207 if (n) {
8208 return nodelib_common_getfield(L, 0, n);
8209 } else {
8210 lua_pushnil(L);
8211 return 1;
8212 }
8213}
8214
8215static int nodelib_userdata_getfield(lua_State *L)
8216{
8217 halfword n = lmt_maybe_isnode(L, 1);
8218 if (n) {
8219 return nodelib_common_getfield(L, 0, n);
8220 } else {
8221 lua_pushnil(L);
8222 return 1;
8223 }
8224}
8225
8226
8227
8228
8229
8233
8234static int nodelib_common_setfield(lua_State *L, int direct, halfword n)
8235{
8236 last_field_error = lua_no_field_error;
8237 switch (lua_type(L, 2)) {
8238 case LUA_TNUMBER:
8239 {
8240 nodelib_setattribute_value(L, n, 2, 3);
8241 break;
8242 }
8243 case LUA_TSTRING:
8244 {
8245 const char *s = lua_tostring(L, 2);
8246 int t = node_type(n);
8247 if (lua_key_eq(s, next)) {
8248 if (tex_nodetype_has_next(t)) {
8249 node_next(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8250 } else {
8251 goto CANTSET;
8252 }
8253 } else if (lua_key_eq(s, prev)) {
8254 if (tex_nodetype_has_prev(t)) {
8255 node_prev(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8256 } else {
8257 goto CANTSET;
8258 }
8259 } else if (lua_key_eq(s, attr)) {
8260 if (tex_nodetype_has_attributes(t)) {
8261 tex_attach_attribute_list_attribute(n, nodelib_direct_or_node_from_index(L, direct, 3));
8262 } else {
8263 goto CANTSET;
8264 }
8265 } else if (lua_key_eq(s, subtype)) {
8266 if (tex_nodetype_has_subtype(t)) {
8267 node_subtype(n) = lmt_toquarterword(L, 3);
8268 } else {
8269 goto CANTSET;
8270 }
8271 } else {
8272 switch(t) {
8273 case glyph_node:
8274 if (lua_key_eq(s, font)) {
8275 glyph_font(n) = tex_checked_font(lmt_tohalfword(L, 3));
8276 } else if (lua_key_eq(s, char)) {
8277 glyph_character(n) = lmt_tohalfword(L, 3);
8278 } else if (lua_key_eq(s, xoffset)) {
8279 glyph_x_offset(n) = (halfword) lmt_roundnumber(L, 3);
8280 } else if (lua_key_eq(s, yoffset)) {
8281 glyph_y_offset(n) = (halfword) lmt_roundnumber(L, 3);
8282 } else if (lua_key_eq(s, scale)) {
8283 glyph_scale(n) = (halfword) lmt_roundnumber(L, 3);
8284 if (! glyph_scale(n)) {
8285 glyph_scale(n) = scaling_factor;
8286 }
8287 } else if (lua_key_eq(s, xscale)) {
8288 glyph_x_scale(n) = (halfword) lmt_roundnumber(L, 3);
8289 if (! glyph_x_scale(n)) {
8290 glyph_x_scale(n) = scaling_factor;
8291 }
8292 } else if (lua_key_eq(s, yscale)) {
8293 glyph_y_scale(n) = (halfword) lmt_roundnumber(L, 3);
8294 if (! glyph_y_scale(n)) {
8295 glyph_y_scale(n) = scaling_factor;
8296 }
8297 } else if (lua_key_eq(s, data)) {
8298 glyph_data(n) = lmt_opthalfword(L, 3, unused_attribute_value);
8299 } else if (lua_key_eq(s, expansion)) {
8300 glyph_expansion(n) = (halfword) lmt_roundnumber(L, 3);
8301 } else if (lua_key_eq(s, state)) {
8302 set_glyph_state(n, lmt_tohalfword(L, 3));
8303 } else if (lua_key_eq(s, script)) {
8304 set_glyph_script(n, lmt_tohalfword(L, 3));
8305 } else if (lua_key_eq(s, language)) {
8306 set_glyph_language(n, lmt_tohalfword(L, 3));
8307 } else if (lua_key_eq(s, left)) {
8308 set_glyph_left(n, lmt_tohalfword(L, 3));
8309 } else if (lua_key_eq(s, right)) {
8310 set_glyph_right(n, lmt_tohalfword(L, 3));
8311 } else if (lua_key_eq(s, slant)) {
8312 set_glyph_slant(n, lmt_tohalfword(L, 3));
8313 } else if (lua_key_eq(s, weight)) {
8314 set_glyph_weight(n, lmt_tohalfword(L, 3));
8315 } else if (lua_key_eq(s, lhmin)) {
8316 set_glyph_lhmin(n, lmt_tohalfword(L, 3));
8317 } else if (lua_key_eq(s, rhmin)) {
8318 set_glyph_rhmin(n, lmt_tohalfword(L, 3));
8319 } else if (lua_key_eq(s, uchyph)) {
8320 set_glyph_uchyph(n, lmt_tohalfword(L, 3));
8321 } else if (lua_key_eq(s, hyphenate)) {
8322 set_glyph_hyphenate(n, lmt_tohalfword(L, 3));
8323 } else if (lua_key_eq(s, options)) {
8324 set_glyph_options(n, lmt_tohalfword(L, 3) & glyph_option_valid);
8325 } else if (lua_key_eq(s, discpart)) {
8326 set_glyph_discpart(n, lmt_tohalfword(L, 3));
8327 } else if (lua_key_eq(s, protected)) {
8328 glyph_protected(n) = lmt_tosingleword(L, 3);
8329 } else if (lua_key_eq(s, width)) {
8330
8331 } else if (lua_key_eq(s, height)) {
8332
8333 } else if (lua_key_eq(s, depth)) {
8334
8335 } else if (lua_key_eq(s, properties)) {
8336 glyph_properties(n) = lmt_toquarterword(L, 3);
8337 } else if (lua_key_eq(s, group)) {
8338 glyph_group(n) = lmt_toquarterword(L, 3);
8339 } else if (lua_key_eq(s, index)) {
8340 glyph_index(n) = lmt_tohalfword(L, 3);
8341 } else if (lua_key_eq(s, control)) {
8342 set_glyph_control(n, lmt_tohalfword(L, 3));
8343 } else {
8344 goto CANTSET;
8345 }
8346 return 0;
8347 case hlist_node:
8348 case vlist_node:
8349 if (lua_key_eq(s, list) || lua_key_eq(s, head)) {
8350 box_list(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8351 } else if (lua_key_eq(s, width)) {
8352 box_width(n) = (halfword) lmt_roundnumber(L, 3);
8353 } else if (lua_key_eq(s, height)) {
8354 box_height(n) = (halfword) lmt_roundnumber(L, 3);
8355 } else if (lua_key_eq(s, depth)) {
8356 box_depth(n) = (halfword) lmt_roundnumber(L, 3);
8357 } else if (lua_key_eq(s, direction)) {
8358 box_dir(n) = (singleword) nodelib_getdirection(L, 3);
8359 } else if (lua_key_eq(s, shift)) {
8360 box_shift_amount(n) = (halfword) lmt_roundnumber(L, 3);
8361 } else if (lua_key_eq(s, glueorder)) {
8362 box_glue_order(n) = tex_checked_glue_order(lmt_tohalfword(L, 3));
8363 } else if (lua_key_eq(s, gluesign)) {
8364 box_glue_sign(n) = tex_checked_glue_sign(lmt_tohalfword(L, 3));
8365 } else if (lua_key_eq(s, glueset)) {
8366 box_glue_set(n) = (glueratio) lua_tonumber(L, 3);
8367 } else if (lua_key_eq(s, geometry)) {
8368 box_geometry(n) = (singleword) lmt_tohalfword(L, 3);
8369 } else if (lua_key_eq(s, orientation)) {
8370 box_orientation(n) = lmt_tohalfword(L, 3);
8371 tex_check_box_geometry(n);
8372 } else if (lua_key_eq(s, anchor)) {
8373 box_anchor(n) = lmt_tohalfword(L, 3);
8374 tex_check_box_geometry(n);
8375 } else if (lua_key_eq(s, source)) {
8376 box_source_anchor(n) = lmt_tohalfword(L, 3);
8377 tex_check_box_geometry(n);
8378 } else if (lua_key_eq(s, target)) {
8379 box_target_anchor(n) = lmt_tohalfword(L, 3);
8380 tex_check_box_geometry(n);
8381 } else if (lua_key_eq(s, xoffset)) {
8382 box_x_offset(n) = (halfword) lmt_roundnumber(L, 3);
8383 tex_check_box_geometry(n);
8384 } else if (lua_key_eq(s, yoffset)) {
8385 box_y_offset(n) = (halfword) lmt_roundnumber(L, 3);
8386 tex_check_box_geometry(n);
8387 } else if (lua_key_eq(s, woffset)) {
8388 box_w_offset(n) = (halfword) lmt_roundnumber(L, 3);
8389 tex_check_box_geometry(n);
8390 } else if (lua_key_eq(s, hoffset)) {
8391 box_h_offset(n) = (halfword) lmt_roundnumber(L, 3);
8392 tex_check_box_geometry(n);
8393 } else if (lua_key_eq(s, doffset)) {
8394 box_d_offset(n) = (halfword) lmt_roundnumber(L, 3);
8395 tex_check_box_geometry(n);
8396 } else if (lua_key_eq(s, pre)) {
8397 box_pre_migrated(n) = nodelib_direct_or_node_from_index(L, direct, 3);;
8398 } else if (lua_key_eq(s, post)) {
8399 box_post_migrated(n) = nodelib_direct_or_node_from_index(L, direct, 3);;
8400 } else if (lua_key_eq(s, state)) {
8401 box_package_state(n) = (singleword) lmt_tohalfword(L, 3);
8402 } else if (lua_key_eq(s, index)) {
8403 box_index(n) = lmt_tohalfword(L, 3);
8404 } else if (lua_key_eq(s, except)) {
8405 box_except(n) = nodelib_direct_or_node_from_index(L, direct, 3);;
8406 } else {
8407 goto CANTSET;
8408 }
8409 return 0;
8410 case disc_node:
8411 if (lua_key_eq(s, pre)) {
8412 tex_set_disc_field(n, pre_break_code, nodelib_direct_or_node_from_index(L, direct, 3));
8413 } else if (lua_key_eq(s, post)) {
8414 tex_set_disc_field(n, post_break_code, nodelib_direct_or_node_from_index(L, direct, 3));
8415 } else if (lua_key_eq(s, replace)) {
8416 tex_set_disc_field(n, no_break_code, nodelib_direct_or_node_from_index(L, direct, 3));
8417 } else if (lua_key_eq(s, penalty)) {
8418 disc_penalty(n) = lmt_tohalfword(L, 3);
8419 } else if (lua_key_eq(s, options)) {
8420 disc_options(n) = lmt_tohalfword(L, 3) & disc_option_valid;
8421 } else if (lua_key_eq(s, class)) {
8422 disc_class(n) = lmt_tohalfword(L, 3);
8423 } else {
8424 goto CANTSET;
8425 }
8426 return 0;
8427 case glue_node:
8428 if (lua_key_eq(s, width)) {
8429 glue_amount(n) = (halfword) lmt_roundnumber(L, 3);
8430 } else if (lua_key_eq(s, stretch)) {
8431 glue_stretch(n) = (halfword) lmt_roundnumber(L, 3);
8432 } else if (lua_key_eq(s, shrink)) {
8433 glue_shrink(n) = (halfword) lmt_roundnumber(L, 3);
8434 } else if (lua_key_eq(s, stretchorder)) {
8435 glue_stretch_order(n) = tex_checked_glue_order(lmt_tohalfword(L, 3));
8436 } else if (lua_key_eq(s, shrinkorder)) {
8437 glue_shrink_order(n) = tex_checked_glue_order(lmt_tohalfword(L, 3));
8438 } else if (lua_key_eq(s, leader)) {
8439 glue_leader_ptr(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8440 } else if (lua_key_eq(s, font)) {
8441 glue_font(n) = tex_checked_font(lmt_tohalfword(L, 3));
8442 } else if (lua_key_eq(s, data)) {
8443 glue_data(n) = (halfword) lmt_roundnumber(L, 3);
8444 } else if (lua_key_eq(s, options)) {
8445 glue_options(n) |= lmt_tohalfword(L, 3);
8446 } else {
8447 goto CANTSET;
8448 }
8449 return 0;
8450 case kern_node:
8451 if (lua_key_eq(s, kern)) {
8452 kern_amount(n) = (halfword) lmt_roundnumber(L, 3);
8453 } else if (lua_key_eq(s, expansion)) {
8454 kern_expansion(n) = (halfword) lmt_roundnumber(L, 3);
8455 } else {
8456 goto CANTSET;
8457 }
8458 return 0;
8459 case penalty_node:
8460 if (lua_key_eq(s, penalty)) {
8461 penalty_amount(n) = lmt_tohalfword(L, 3);
8462 } else if (lua_key_eq(s, options)) {
8463 penalty_options(n) |= lmt_tohalfword(L, 3);
8464 } else {
8465 goto CANTSET;
8466 }
8467 return 0;
8468 case rule_node:
8469 if (lua_key_eq(s, width)) {
8470 rule_width(n) = (halfword) lmt_roundnumber(L, 3);
8471 } else if (lua_key_eq(s, height)) {
8472 rule_height(n) = (halfword) lmt_roundnumber(L, 3);
8473 } else if (lua_key_eq(s, depth)) {
8474 rule_depth(n) = (halfword) lmt_roundnumber(L, 3);
8475 } else if (lua_key_eq(s, xoffset)) {
8476 rule_x_offset(n) = (halfword) lmt_roundnumber(L, 3);
8477 } else if (lua_key_eq(s, yoffset)) {
8478 rule_y_offset(n) = (halfword) lmt_roundnumber(L, 3);
8479 } else if (lua_key_eq(s, left)) {
8480 tex_set_rule_left(n, (halfword) lmt_roundnumber(L, 3));
8481 } else if (lua_key_eq(s, right)) {
8482 tex_set_rule_right(n, (halfword) lmt_roundnumber(L, 3));
8483 } else if (lua_key_eq(s, on)) {
8484 tex_set_rule_on(n, (halfword) lmt_roundnumber(L, 3));
8485 } else if (lua_key_eq(s, off)) {
8486 tex_set_rule_off(n, (halfword) lmt_roundnumber(L, 3));
8487 } else if (lua_key_eq(s, data)) {
8488 rule_data(n) = lmt_tohalfword(L, 3);
8489 } else if (lua_key_eq(s, options)) {
8490 rule_options(n) = lmt_tohalfword(L, 3) & rule_option_valid;
8491 } else if (lua_key_eq(s, font)) {
8492 tex_set_rule_font(n, lmt_tohalfword(L, 3));
8493 } else if (lua_key_eq(s, fam)) {
8494 tex_set_rule_family(n, lmt_tohalfword(L, 3));
8495 } else if (lua_key_eq(s, char)) {
8496 rule_strut_character(n) = lmt_tohalfword(L, 3);
8497 } else {
8498 goto CANTSET;
8499 }
8500 return 0;
8501 case dir_node:
8502 if (lua_key_eq(s, direction)) {
8503 dir_direction(n) = nodelib_getdirection(L, 3);
8504 } else if (lua_key_eq(s, level)) {
8505 dir_level(n) = lmt_tohalfword(L, 3);
8506 } else {
8507 goto CANTSET;
8508 }
8509 return 0;
8510 case whatsit_node:
8511 return 0;
8512 case par_node:
8513
8514 if (lua_key_eq(s, interlinepenalty)) {
8515 tex_set_local_interline_penalty(n, lmt_tohalfword(L, 3));
8516 } else if (lua_key_eq(s, brokenpenalty)) {
8517 tex_set_local_broken_penalty(n, lmt_tohalfword(L, 3));
8518 } else if (lua_key_eq(s, tolerance)) {
8519 tex_set_local_tolerance(n, lmt_tohalfword(L, 3));
8520 } else if (lua_key_eq(s, pretolerance)) {
8521 tex_set_local_pre_tolerance(n, lmt_tohalfword(L, 3));
8522 } else if (lua_key_eq(s, direction)) {
8523 par_dir(n) = nodelib_getdirection(L, 3);
8524 } else if (lua_key_eq(s, leftbox)) {
8525 par_box_left(n) = nodelib_getlist(L, 3);
8526 } else if (lua_key_eq(s, leftboxwidth)) {
8527 tex_set_local_left_width(n, lmt_roundnumber(L, 3));
8528 } else if (lua_key_eq(s, rightbox)) {
8529 par_box_right(n) = nodelib_getlist(L, 3);
8530 } else if (lua_key_eq(s, rightboxwidth)) {
8531 tex_set_local_right_width(n, lmt_roundnumber(L, 3));
8532 } else if (lua_key_eq(s, middlebox)) {
8533 par_box_middle(n) = nodelib_getlist(L, 3);
8534 } else {
8535 goto CANTSET;
8536 }
8537 return 0;
8538 case math_char_node:
8539 case math_text_char_node:
8540 if (lua_key_eq(s, fam)) {
8541 kernel_math_family(n) = lmt_tohalfword(L, 3);
8542 } else if (lua_key_eq(s, char)) {
8543 kernel_math_character(n) = lmt_tohalfword(L, 3);
8544 } else if (lua_key_eq(s, options)) {
8545 kernel_math_options(n) = lmt_tohalfword(L, 3);
8546 } else if (lua_key_eq(s, properties)) {
8547 kernel_math_properties(n) = lmt_toquarterword(L, 3);
8548 } else if (lua_key_eq(s, group)) {
8549 kernel_math_group(n) = lmt_toquarterword(L, 3);
8550 } else if (lua_key_eq(s, index)) {
8551 kernel_math_index(n) = lmt_tohalfword(L, 3);
8552 } else {
8553 goto CANTSET;
8554 }
8555 return 0;
8556 case mark_node:
8557 if (lua_key_eq(s, index) || lua_key_eq(s, class)) {
8558 halfword m = ignore_field_error ? lmt_opthalfword(L, 3, 1) : lmt_tohalfword(L, 3);
8559 if (tex_valid_mark(m)) {
8560 mark_index(n) = m;
8561 }
8562 } else if (lua_key_eq(s, data) || lua_key_eq(s, mark)) {
8563 tex_delete_token_reference(mark_ptr(n));
8564 mark_ptr(n) = lmt_token_list_from_lua(L, 3);
8565 } else {
8566 goto CANTSET;
8567 }
8568 return 0;
8569 case insert_node:
8570 if (lua_key_eq(s, index)) {
8571 halfword index = ignore_field_error ? lmt_opthalfword(L, 3, 1) : lmt_tohalfword(L, 3);
8572 if (tex_valid_insert_id(index)) {
8573 insert_index(n) = index;
8574 }
8575 } else if (lua_key_eq(s, cost)) {
8576 insert_float_cost(n) = lmt_tohalfword(L, 3);
8577 } else if (lua_key_eq(s, depth)) {
8578 insert_max_depth(n) = (halfword) lmt_roundnumber(L, 3);
8579 } else if (lua_key_eq(s, height) || lua_key_eq(s, total)) {
8580 insert_total_height(n) = (halfword) lmt_roundnumber(L, 3);
8581 } else if (lua_key_eq(s, list) || lua_key_eq(s, head)) {
8582 insert_list(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8583 } else if (lua_key_eq(s, data)) {
8584 insert_identifier(n) = (halfword) lmt_roundnumber(L, 3);
8585 } else if (lua_key_eq(s, lineheight)) {
8586 insert_line_height(n) = (halfword) lmt_roundnumber(L, 3);
8587 } else if (lua_key_eq(s, linedepth)) {
8588 insert_line_depth(n) = (halfword) lmt_roundnumber(L, 3);
8589 } else if (lua_key_eq(s, stretch)) {
8590 insert_stretch(n) = (halfword) lmt_roundnumber(L, 3);
8591 } else if (lua_key_eq(s, shrink)) {
8592 insert_shrink(n) = (halfword) lmt_roundnumber(L, 3);
8593 } else {
8594 goto CANTSET;
8595 }
8596 return 0;
8597 case math_node:
8598 if (lua_key_eq(s, surround)) {
8599 math_surround(n) = (halfword) lmt_roundnumber(L, 3);
8600 } else if (lua_key_eq(s, width)) {
8601 math_amount(n) = (halfword) lmt_roundnumber(L, 3);
8602 } else if (lua_key_eq(s, stretch)) {
8603 math_stretch(n) = (halfword) lmt_roundnumber(L, 3);
8604 } else if (lua_key_eq(s, shrink)) {
8605 math_shrink(n) = (halfword) lmt_roundnumber(L, 3);
8606 } else if (lua_key_eq(s, stretchorder)) {
8607 math_stretch_order(n) = tex_checked_glue_order(lmt_tohalfword(L, 3));
8608 } else if (lua_key_eq(s, shrinkorder)) {
8609 math_shrink_order(n) = tex_checked_glue_order(lmt_tohalfword(L, 3));
8610 } else if (lua_key_eq(s, penalty)) {
8611 math_penalty(n) = lmt_tohalfword(L, 3);
8612 } else if (lua_key_eq(s, options)) {
8613 math_options(n) |= lmt_tohalfword(L, 3);
8614 } else {
8615 goto CANTSET;
8616 }
8617 return 0;
8618 case style_node:
8619 if (lua_key_eq(s, style)) {
8620 style_style(n) = (quarterword) lmt_get_math_style(L, 2, text_style);
8621 } else {
8622
8623 }
8624 return 0;
8625 case parameter_node:
8626 if (lua_key_eq(s, style)) {
8627 parameter_style(n) = (quarterword) lmt_get_math_style(L, 2, text_style);
8628 } else if (lua_key_eq(s, name)) {
8629 parameter_name(n) = lmt_get_math_parameter(L, 2, parameter_name(n));
8630 } else if (lua_key_eq(s, value)) {
8631 halfword code = parameter_name(n);
8632 if (code < 0 || code >= math_parameter_last) {
8633
8634 } else if (math_parameter_value_type(code)) {
8635
8636 } else {
8637 parameter_value(n) = lmt_tohalfword(L, 3);
8638 }
8639 }
8640 return 0;
8641 case simple_noad:
8642 case radical_noad:
8643 case fraction_noad:
8644 case accent_noad:
8645 case fence_noad:
8646
8647 if (lua_key_eq(s, nucleus)) {
8648 noad_nucleus(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8649 } else if (lua_key_eq(s, sub)) {
8650 noad_subscr(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8651 } else if (lua_key_eq(s, sup)) {
8652 noad_supscr(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8653 } else if (lua_key_eq(s, subpre)) {
8654 noad_subprescr(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8655 } else if (lua_key_eq(s, suppre)) {
8656 noad_supprescr(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8657 } else if (lua_key_eq(s, prime)) {
8658 noad_prime(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8659 } else if (lua_key_eq(s, source)) {
8660 noad_source(n) = lmt_tohalfword(L, 3);
8661 } else if (lua_key_eq(s, options)) {
8662 noad_options(n) = lmt_tofullword(L, 3);
8663 } else if (lua_key_eq(s, scriptorder)) {
8664 noad_script_order(n) = lmt_tosingleword(L, 3);
8665 } else if (lua_key_eq(s, class)) {
8666 halfword c = lmt_tohalfword(L, 3);
8667 set_noad_main_class(n, c);
8668 set_noad_left_class(n, lmt_opthalfword(L, 4, c));
8669 set_noad_right_class(n, lmt_opthalfword(L, 5, c));
8670 } else if (lua_key_eq(s, fam)) {
8671 set_noad_family(n, lmt_tohalfword(L, 3));
8672 } else {
8673 switch (t) {
8674 case simple_noad:
8675 break;
8676 case radical_noad:
8677 if (lua_key_eq(s, left) || lua_key_eq(s, delimiter)) {
8678 radical_left_delimiter(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8679 } else if (lua_key_eq(s, right)) {
8680 radical_right_delimiter(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8681 } else if (lua_key_eq(s, top)) {
8682 radical_top_delimiter(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8683 } else if (lua_key_eq(s, bottom)) {
8684 radical_bottom_delimiter(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8685 } else if (lua_key_eq(s, degree)) {
8686 radical_degree(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8687 } else if (lua_key_eq(s, width)) {
8688 noad_width(n) = lmt_roundnumber(L, 3);
8689 } else {
8690 goto CANTSET;
8691 }
8692 return 0;
8693 case fraction_noad:
8694 if (lua_key_eq(s, width)) {
8695 fraction_rule_thickness(n) = (halfword) lmt_roundnumber(L, 3);
8696 } else if (lua_key_eq(s, numerator)) {
8697 fraction_numerator(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8698 } else if (lua_key_eq(s, denominator)) {
8699 fraction_denominator(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8700 } else if (lua_key_eq(s, left)) {
8701 fraction_left_delimiter(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8702 } else if (lua_key_eq(s, right)) {
8703 fraction_right_delimiter(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8704 } else if (lua_key_eq(s, middle)) {
8705 fraction_middle_delimiter(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8706 } else {
8707 goto CANTSET;
8708 }
8709 return 0;
8710 case accent_noad:
8711 if (lua_key_eq(s, top) || lua_key_eq(s, topaccent)) {
8712 accent_top_character(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8713 } else if (lua_key_eq(s, bottom) || lua_key_eq(s, bottomaccent)) {
8714 accent_bottom_character(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8715 } else if (lua_key_eq(s, middle) || lua_key_eq(s, overlayaccent)) {
8716 accent_middle_character(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8717 } else if (lua_key_eq(s, fraction)) {
8718 accent_fraction(n) = (halfword) lmt_roundnumber(L, 3);
8719 } else {
8720 goto CANTSET;
8721 }
8722 return 0;
8723 case fence_noad:
8724 if (lua_key_eq(s, delimiter)) {
8725 fence_delimiter(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8726 } else if (lua_key_eq(s, top)) {
8727 fence_delimiter_top(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8728 } else if (lua_key_eq(s, bottom)) {
8729 fence_delimiter_bottom(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8730 } else if (lua_key_eq(s, italic)) {
8731 noad_italic(n) = (halfword) lmt_roundnumber(L, 3);
8732 } else if (lua_key_eq(s, height)) {
8733 noad_height(n) = (halfword) lmt_roundnumber(L, 3);
8734 } else if (lua_key_eq(s, depth)) {
8735 noad_depth(n) = (halfword) lmt_roundnumber(L, 3);
8736 } else if (lua_key_eq(s, variant)) {
8737 fence_delimiter_variant(n) = (halfword) lmt_roundnumber(L, 3);
8738 } else {
8739 goto CANTSET;
8740 }
8741 return 0;
8742 }
8743 }
8744 return 0;
8745 case delimiter_node:
8746 if (lua_key_eq(s, smallfamily)) {
8747 delimiter_small_family(n) = lmt_tohalfword(L, 3);
8748 } else if (lua_key_eq(s, smallchar)) {
8749 delimiter_small_character(n) = lmt_tohalfword(L, 3);
8750 } else if (lua_key_eq(s, largefamily)) {
8751 delimiter_large_family(n) = lmt_tohalfword(L, 3);
8752 } else if (lua_key_eq(s, largechar)) {
8753 delimiter_large_character(n) = lmt_tohalfword(L, 3);
8754 } else {
8755 goto CANTSET;
8756 }
8757 return 0;
8758 case sub_box_node:
8759 case sub_mlist_node:
8760 if (lua_key_eq(s, list) || lua_key_eq(s, head)) {
8761 kernel_math_list(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8762 } else {
8763 goto CANTSET;
8764 }
8765 return 0;
8766 case split_node:
8767 if (lua_key_eq(s, index)) {
8768 halfword index = lmt_tohalfword(L, 3);
8769 if (tex_valid_insert_id(index)) {
8770 split_insert_index(n) = index;
8771 }
8772 } else if (lua_key_eq(s, lastinsert)) {
8773 split_last_insert(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8774 } else if (lua_key_eq(s, bestinsert)) {
8775 split_best_insert(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8776 } else if (lua_key_eq(s, broken)) {
8777 split_broken(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8778 } else if (lua_key_eq(s, brokeninsert)) {
8779 split_broken_insert(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8780 } else {
8781 goto CANTSET;
8782 }
8783 return 0;
8784 case choice_node:
8785 if (lua_key_eq(s, display)) {
8786 choice_display_mlist(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8787 } else if (lua_key_eq(s, text)) {
8788 choice_text_mlist(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8789 } else if (lua_key_eq(s, script)) {
8790 choice_script_mlist(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8791 } else if (lua_key_eq(s, scriptscript)) {
8792 choice_script_script_mlist(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8793 } else {
8794 goto CANTSET;
8795 }
8796 return 0;
8797 case attribute_node:
8798 switch (node_subtype(n)) {
8799 case attribute_list_subtype:
8800 if (lua_key_eq(s, count)) {
8801 attribute_count(n) = lmt_tohalfword(L, 3);
8802 } else {
8803 goto CANTSET;
8804 }
8805 return 0;
8806 case attribute_value_subtype:
8807 if (lua_key_eq(s, index) || lua_key_eq(s, number)) {
8808 attribute_index(n) = (quarterword) lmt_tohalfword(L, 3);
8809 } else if (lua_key_eq(s, value)) {
8810 attribute_value(n) = lmt_tohalfword(L, 3);
8811 } else {
8812 goto CANTSET;
8813 }
8814 return 0;
8815 default:
8816
8817 return 0;
8818 }
8819
8820 case adjust_node:
8821 if (lua_key_eq(s, list) || lua_key_eq(s, head)) {
8822 adjust_list(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8823 } else if (lua_key_eq(s, index)) {
8824 halfword index = lmt_tohalfword(L, 3);
8825 if (tex_valid_adjust_index(index)) {
8826 adjust_index(n) = index;
8827 }
8828 } else {
8829 goto CANTSET;
8830 }
8831 return 0;
8832 case unset_node:
8833 if (lua_key_eq(s, width)) {
8834 box_width(n) = (halfword) lmt_roundnumber(L, 3);
8835 } else if (lua_key_eq(s, height)) {
8836 box_height(n) = (halfword) lmt_roundnumber(L, 3);
8837 } else if (lua_key_eq(s, depth)) {
8838 box_depth(n) = (halfword) lmt_roundnumber(L, 3);
8839 } else if (lua_key_eq(s, direction)) {
8840 box_dir(n) = (singleword) nodelib_getdirection(L, 3);
8841 } else if (lua_key_eq(s, shrink)) {
8842 box_glue_shrink(n) = (halfword) lmt_roundnumber(L, 3);
8843 } else if (lua_key_eq(s, glueorder)) {
8844 box_glue_order(n) = tex_checked_glue_order(lmt_tohalfword(L, 3));
8845 } else if (lua_key_eq(s, gluesign)) {
8846 box_glue_sign(n) = tex_checked_glue_sign(lmt_tohalfword(L, 3));
8847 } else if (lua_key_eq(s, stretch)) {
8848 box_glue_stretch(n) = (halfword) lmt_roundnumber(L, 3);
8849 } else if (lua_key_eq(s, count)) {
8850 box_span_count(n) = lmt_tohalfword(L, 3);
8851 } else if (lua_key_eq(s, list) || lua_key_eq(s, head)) {
8852 box_list(n) = nodelib_direct_or_node_from_index(L, direct, 3);
8853 } else {
8854 goto CANTSET;
8855 }
8856 return 0;
8857 case boundary_node:
8858 if (lua_key_eq(s, value) || lua_key_eq(s, data)) {
8859 boundary_data(n) = lmt_tohalfword(L, 3);
8860 } else if (lua_key_eq(s, reserved)) {
8861 boundary_reserved(n) = lmt_tohalfword(L, 3);
8862 } else {
8863 goto CANTSET;
8864 }
8865 return 0;
8866 case glue_spec_node:
8867 if (lua_key_eq(s, width)) {
8868 glue_amount(n) = (halfword) lmt_roundnumber(L, 3);
8869 } else if (lua_key_eq(s, stretch)) {
8870 glue_stretch(n) = (halfword) lmt_roundnumber(L, 3);
8871 } else if (lua_key_eq(s, shrink)) {
8872 glue_shrink(n) = (halfword) lmt_roundnumber(L, 3);
8873 } else if (lua_key_eq(s, stretchorder)) {
8874 glue_stretch_order(n) = tex_checked_glue_order(lmt_tohalfword(L, 3));
8875 } else if (lua_key_eq(s, shrinkorder)) {
8876 glue_shrink_order(n) = tex_checked_glue_order(lmt_tohalfword(L, 3));
8877 } else {
8878 goto CANTSET;
8879 }
8880 return 0;
8881 default:
8882 last_field_error = lua_set_field_error;
8883 return ignore_field_error ? 0 : luaL_error(L, "you can't assign to a %s node (%d)\n", lmt_interface.node_data[t].name, n);
8884 }
8885 CANTSET:
8886 last_field_error = lua_set_field_error;
8887 return ignore_field_error ? 0 : luaL_error(L,"you can't set field %s in a %s node (%d)", s, lmt_interface.node_data[t].name, n);
8888 }
8889 return 0;
8890 }
8891 }
8892 return 0;
8893}
8894
8895static int nodelib_shared_setfielderror(lua_State *L)
8896{
8897 ignore_field_error = lua_toboolean(L, 1);
8898 last_field_error = lua_no_field_error;
8899 return 1;
8900}
8901
8902static int nodelib_shared_getfielderror(lua_State *L)
8903{
8904 lua_pushinteger(L, last_field_error);
8905 return 1;
8906}
8907
8908
8909# define setfield_usage common_usage
8910
8911static int nodelib_direct_setfield(lua_State *L)
8912{
8913 halfword n = nodelib_valid_direct_from_index(L, 1);
8914 if (n) {
8915 nodelib_common_setfield(L, 1, n);
8916 }
8917 return 0;
8918}
8919
8920static int nodelib_userdata_newindex(lua_State *L)
8921{
8922 halfword n = *((halfword *) lua_touserdata(L, 1));
8923 if (n) {
8924 nodelib_common_setfield(L, 0, n);
8925 }
8926 return 0;
8927}
8928
8929static int nodelib_userdata_setfield(lua_State *L)
8930{
8931 halfword n = lmt_maybe_isnode(L, 1);
8932 if (n) {
8933 nodelib_common_setfield(L, 0, n);
8934 }
8935 return 0;
8936}
8937
8938
8939
8940static int verbose = 1;
8941
8942static void nodelib_tostring(lua_State *L, halfword n, const char *tag)
8943{
8944 char msg[256];
8945 char a[7] = { ' ', ' ', ' ', 'n', 'i', 'l', 0 };
8946 char v[7] = { ' ', ' ', ' ', 'n', 'i', 'l', 0 };
8947 halfword t = node_type(n);
8948 halfword s = node_subtype(n);
8949 node_info nd = lmt_interface.node_data[t];
8950 if (tex_nodetype_has_prev(t) && node_prev(n)) {
8951 snprintf(a, 7, "%6d", (int) node_prev(n));
8952 }
8953 if (node_next(n)) {
8954 snprintf(v, 7, "%6d", (int) node_next(n));
8955 }
8956 if (t == whatsit_node) {
8957 snprintf(msg, 255, "<%s : %s < %6d > %s : %s %d>", tag, a, (int) n, v, nd.name, s);
8958 } else if (! tex_nodetype_has_subtype(n)) {
8959 snprintf(msg, 255, "<%s : %s < %6d > %s : %s>", tag, a, (int) n, v, nd.name);
8960 } else if (verbose) {
8961
8962 value_info *sd = nd.subtypes;
8963 int j = -1;
8964 if (sd) {
8965
8966
8967
8968 if (s >= nd.first && s <= nd.last) {
8969 for (int i = 0; ; i++) {
8970 if (sd[i].id == s) {
8971 j = i;
8972 break ;
8973 } else if (sd[i].id < 0) {
8974 break;
8975 }
8976 }
8977 }
8978 }
8979 if (j < 0) {
8980 snprintf(msg, 255, "<%s : %s <= %6d => %s : %s %d>", tag, a, (int) n, v, nd.name, s);
8981 } else {
8982 snprintf(msg, 255, "<%s : %s <= %6d => %s : %s %s>", tag, a, (int) n, v, nd.name, sd[j].name);
8983 }
8984 } else {
8985 snprintf(msg, 255, "<%s : %s < %6d > %s : %s %d>", tag, a, (int) n, v, nd.name, s);
8986 }
8987 lua_pushstring(L, (const char *) msg);
8988}
8989
8990
8991
8992static int nodelib_userdata_tostring(lua_State *L)
8993{
8994 halfword n = lmt_check_isnode(L, 1);
8995 if (n) {
8996 nodelib_tostring(L, n, lua_key(node));
8997 } else {
8998 lua_pushnil(L);
8999 }
9000 return 1;
9001}
9002
9003
9004
9005static int nodelib_direct_tostring(lua_State *L)
9006{
9007 halfword n = nodelib_valid_direct_from_index(L, 1);
9008 if (n) {
9009 nodelib_tostring(L, n, lua_key(direct));
9010 } else {
9011 lua_pushnil(L);
9012 }
9013 return 1;
9014}
9015
9016
9017
9018static int nodelib_userdata_equal(lua_State *L)
9019{
9020 halfword n = *((halfword *) lua_touserdata(L, 1));
9021 halfword m = *((halfword *) lua_touserdata(L, 2));
9022 lua_pushboolean(L, (n == m));
9023 return 1;
9024}
9025
9026
9027
9028# define ligaturing_usage common_usage
9029
9030static int nodelib_direct_ligaturing(lua_State *L)
9031{
9032 if (lua_gettop(L) >= 1) {
9033 halfword h = nodelib_valid_direct_from_index(L, 1);
9034 halfword t = nodelib_valid_direct_from_index(L, 2);
9035 if (h) {
9036 halfword tmp_head = tex_new_node(nesting_node, unset_nesting_code);
9037 halfword p = node_prev(h);
9038 tex_couple_nodes(tmp_head, h);
9039 node_tail(tmp_head) = t;
9040 t = tex_handle_ligaturing(tmp_head, t);
9041 if (p) {
9042 node_next(p) = node_next(tmp_head) ;
9043 }
9044 node_prev(node_next(tmp_head)) = p ;
9045 lua_pushinteger(L, node_next(tmp_head));
9046 lua_pushinteger(L, t);
9047 lua_pushboolean(L, 1);
9048 tex_flush_node(tmp_head);
9049 return 3;
9050 }
9051 }
9052 lua_pushnil(L);
9053 lua_pushboolean(L, 0);
9054 return 2;
9055}
9056
9057
9058
9059# define kerning_usage common_usage
9060
9061static int nodelib_direct_kerning(lua_State *L)
9062{
9063 if (lua_gettop(L) >= 1) {
9064 halfword h = nodelib_valid_direct_from_index(L, 1);
9065 halfword t = nodelib_valid_direct_from_index(L, 2);
9066 if (h) {
9067 halfword tmp_head = tex_new_node(nesting_node, unset_nesting_code);
9068 halfword p = node_prev(h);
9069 tex_couple_nodes(tmp_head, h);
9070 node_tail(tmp_head) = t;
9071 t = tex_handle_kerning(tmp_head, t);
9072 if (p) {
9073 node_next(p) = node_next(tmp_head) ;
9074 }
9075 node_prev(node_next(tmp_head)) = p ;
9076 lua_pushinteger(L, node_next(tmp_head));
9077 if (t) {
9078 lua_pushinteger(L, t);
9079 } else {
9080 lua_pushnil(L);
9081 }
9082 lua_pushboolean(L, 1);
9083 tex_flush_node(tmp_head);
9084 return 3;
9085 }
9086 }
9087 lua_pushnil(L);
9088 lua_pushboolean(L, 0);
9089 return 2;
9090}
9091
9092
9096
9097# define hyphenating_usage common_usage
9098# define collapsing_usage common_usage
9099
9100static int nodelib_direct_hyphenating(lua_State *L)
9101{
9102 halfword h = nodelib_valid_direct_from_index(L, 1);
9103 halfword t = nodelib_valid_direct_from_index(L, 2);
9104 if (h) {
9105 if (! t) {
9106 t = h;
9107 while (node_next(t)) {
9108 t = node_next(t);
9109 }
9110 }
9111 tex_hyphenate_list(h, t);
9112 } else {
9113
9114 }
9115 lua_pushinteger(L, h);
9116 lua_pushinteger(L, t);
9117 lua_pushboolean(L, 1);
9118 return 3;
9119}
9120
9121static int nodelib_direct_collapsing(lua_State *L)
9122{
9123 halfword h = nodelib_valid_direct_from_index(L, 1);
9124 if (h) {
9125 halfword c1 = lmt_optinteger(L, 2, ex_hyphen_char_par);
9126 halfword c2 = lmt_optinteger(L, 3, 0x2013);
9127 halfword c3 = lmt_optinteger(L, 4, 0x2014);
9128 halfword c4 = lmt_optinteger(L, 5, 0x2019);
9129 tex_collapse_list(h, c1, c2, c3, c4);
9130 }
9131 lua_pushinteger(L, h);
9132 return 1;
9133}
9134
9135
9136
9137
9138static inline void nodelib_aux_protect_all(halfword h)
9139{
9140 while (h) {
9141 if (node_type(h) == glyph_node) {
9142 glyph_protected(h) = glyph_protected_text_code;
9143 }
9144 h = node_next(h);
9145 }
9146}
9147static inline void nodelib_aux_unprotect_all(halfword h)
9148{
9149 while (h) {
9150 if (node_type(h) == glyph_node) {
9151 glyph_protected(h) = glyph_unprotected_code;
9152 }
9153 h = node_next(h);
9154 }
9155}
9156
9157static inline void nodelib_aux_protect_node(halfword n)
9158{
9159 switch (node_type(n)) {
9160 case glyph_node:
9161 glyph_protected(n) = glyph_protected_text_code;
9162 break;
9163 case disc_node:
9164 nodelib_aux_protect_all(disc_no_break_head(n));
9165 nodelib_aux_protect_all(disc_pre_break_head(n));
9166 nodelib_aux_protect_all(disc_post_break_head(n));
9167 break;
9168 }
9169}
9170
9171static inline void nodelib_aux_unprotect_node(halfword n)
9172{
9173 switch (node_type(n)) {
9174 case glyph_node:
9175 glyph_protected(n) = glyph_unprotected_code;
9176 break;
9177 case disc_node:
9178 nodelib_aux_unprotect_all(disc_no_break_head(n));
9179 nodelib_aux_unprotect_all(disc_pre_break_head(n));
9180 nodelib_aux_unprotect_all(disc_post_break_head(n));
9181 break;
9182 }
9183}
9184
9185
9186
9187
9188# define protectglyph_usage (glyph_usage | disc_usage)
9189# define unprotectglyph_usage (glyph_usage | disc_usage)
9190
9191# define protectglyphs_usage common_usage
9192# define unprotectglyphs_usage common_usage
9193
9194# define protectglyphsnone_usage common_usage
9195# define unprotectglyphsnone_usage common_usage
9196
9197static int nodelib_direct_protectglyph(lua_State *L)
9198{
9199 halfword n = nodelib_valid_direct_from_index(L, 1);
9200 if (n) {
9201 nodelib_aux_protect_node(n);
9202 }
9203 return 0;
9204}
9205
9206static int nodelib_direct_unprotectglyph(lua_State *L)
9207{
9208 halfword n = nodelib_valid_direct_from_index(L, 1);
9209 if (n) {
9210 nodelib_aux_unprotect_node(n);
9211 }
9212 return 0;
9213}
9214
9215static int nodelib_direct_protectglyphs(lua_State *L)
9216{
9217 halfword head = nodelib_valid_direct_from_index(L, 1);
9218 halfword tail = nodelib_valid_direct_from_index(L, 2);
9219 if (head) {
9220 while (head) {
9221 nodelib_aux_protect_node(head);
9222 if (head == tail) {
9223 break;
9224 } else {
9225 head = node_next(head);
9226 }
9227 }
9228 }
9229 return 0;
9230}
9231
9232static int nodelib_direct_unprotectglyphs(lua_State *L)
9233{
9234 halfword head = nodelib_valid_direct_from_index(L, 1);
9235 halfword tail = nodelib_valid_direct_from_index(L, 2);
9236 if (head) {
9237 while (head) {
9238 nodelib_aux_unprotect_node(head);
9239 if (head == tail) {
9240 break;
9241 } else {
9242 head = node_next(head);
9243 }
9244 }
9245 }
9246 return 0;
9247}
9248
9249
9250
9251static inline void nodelib_aux_protect_all_none(halfword h)
9252{
9253 while (h) {
9254 if (node_type(h) == glyph_node) {
9255 halfword f = glyph_font(h);
9256 if (f >= 0 && f <= lmt_font_state.font_data.ptr && lmt_font_state.fonts[f] && has_font_text_control(f, text_control_none_protected)) {
9257 glyph_protected(h) = glyph_protected_text_code;
9258 }
9259 }
9260 h = node_next(h);
9261 }
9262}
9263
9264static inline void nodelib_aux_protect_node_none(halfword n)
9265{
9266 switch (node_type(n)) {
9267 case glyph_node:
9268 {
9269 halfword f = glyph_font(n);
9270 if (f >= 0 && f <= lmt_font_state.font_data.ptr && lmt_font_state.fonts[f] && has_font_text_control(f, text_control_none_protected)) {
9271 glyph_protected(n) = glyph_protected_text_code;
9272 }
9273 }
9274 break;
9275 case disc_node:
9276 nodelib_aux_protect_all_none(disc_no_break_head(n));
9277 nodelib_aux_protect_all_none(disc_pre_break_head(n));
9278 nodelib_aux_protect_all_none(disc_post_break_head(n));
9279 break;
9280 }
9281}
9282
9283static int nodelib_direct_protectglyphsnone(lua_State *L)
9284{
9285 halfword head = nodelib_valid_direct_from_index(L, 1);
9286 halfword tail = nodelib_valid_direct_from_index(L, 2);
9287 if (head) {
9288 while (head) {
9289 nodelib_aux_protect_node_none(head);
9290 if (head == tail) {
9291 break;
9292 } else {
9293 head = node_next(head);
9294 }
9295 }
9296 }
9297 return 0;
9298}
9299
9300
9301
9302
9303
9304# define firstglyphnode_usage common_usage
9305# define firstglyph_usage common_usage
9306# define firstchar_usage common_usage
9307
9308static int nodelib_direct_firstglyphnode(lua_State *L)
9309{
9310 halfword h = nodelib_valid_direct_from_index(L, 1);
9311 halfword t = nodelib_valid_direct_from_index(L, 2);
9312 if (h) {
9313 halfword savetail = null;
9314 if (t) {
9315 savetail = node_next(t);
9316 node_next(t) = null;
9317 }
9318 while (h && node_type(h) != glyph_node) {
9319 h = node_next(h);
9320 }
9321 if (savetail) {
9322 node_next(t) = savetail;
9323 }
9324 }
9325 if (h) {
9326 lua_pushinteger(L, h);
9327 } else {
9328 lua_pushnil(L);
9329 }
9330 return 1;
9331}
9332
9333
9334static int nodelib_direct_firstglyph(lua_State *L)
9335{
9336 halfword h = nodelib_valid_direct_from_index(L, 1);
9337 halfword t = nodelib_valid_direct_from_index(L, 2);
9338 if (h) {
9339 halfword savetail = null;
9340 if (t) {
9341 savetail = node_next(t);
9342 node_next(t) = null;
9343 }
9344
9348 while (h && ! (node_type(h) == glyph_node && glyph_protected(h))) {
9349 h = node_next(h);
9350 }
9351 if (savetail) {
9352 node_next(t) = savetail;
9353 }
9354 }
9355 if (h) {
9356 lua_pushinteger(L, h);
9357 } else {
9358 lua_pushnil(L);
9359 }
9360 return 1;
9361}
9362
9363static int nodelib_direct_firstchar(lua_State *L)
9364{
9365 halfword h = nodelib_valid_direct_from_index(L, 1);
9366 halfword t = nodelib_valid_direct_from_index(L, 2);
9367 if (h) {
9368 halfword savetail = null;
9369 if (t) {
9370 savetail = node_next(t);
9371 node_next(t) = null;
9372 }
9373
9377 while (h && ! (node_type(h) == glyph_node && ! glyph_protected(h))) {
9378 h = node_next(h);
9379 }
9380 if (savetail) {
9381 node_next(t) = savetail;
9382 }
9383 }
9384 if (h) {
9385 lua_pushinteger(L, h);
9386 } else {
9387 lua_pushnil(L);
9388 }
9389 return 1;
9390}
9391
9392
9393
9394
9395# define findnode_usage common_usage
9396
9397static int nodelib_direct_findnode(lua_State *L)
9398{
9399 halfword h = nodelib_valid_direct_from_index(L, 1);
9400 if (h) {
9401 halfword type = lmt_tohalfword(L, 2);
9402 if (lua_gettop(L) > 2) {
9403 halfword subtype = lmt_tohalfword(L, 3);
9404 while (h) {
9405 if (node_type(h) == type && node_subtype(h) == subtype) {
9406 lua_pushinteger(L, h);
9407 return 1;
9408 } else {
9409 h = node_next(h);
9410 }
9411 }
9412 } else {
9413 while (h) {
9414 if (node_type(h) == type) {
9415 lua_pushinteger(L, h);
9416 lua_pushinteger(L, node_subtype(h));
9417 return 2;
9418 } else {
9419 h = node_next(h);
9420 }
9421 }
9422 }
9423 }
9424 lua_pushnil(L);
9425 return 1;
9426}
9427
9428
9429
9430# define hasglyph_usage common_usage
9431
9432static int nodelib_direct_hasglyph(lua_State *L)
9433{
9434 halfword h = nodelib_valid_direct_from_index(L, 1);
9435 while (h) {
9436 switch (node_type(h)) {
9437 case glyph_node:
9438 case disc_node:
9439 nodelib_push_direct_or_nil(L, h);
9440 return 1;
9441 default:
9442 h = node_next(h);
9443 break;
9444 }
9445 }
9446 lua_pushnil(L);
9447 return 1;
9448}
9449
9450
9451
9452static inline int nodelib_aux_in_word(halfword n)
9453{
9454 switch (node_type(n)) {
9455 case glyph_node:
9456 case disc_node:
9457 return 1;
9458 case kern_node:
9459 return node_subtype(n) == font_kern_subtype;
9460 default:
9461 return 0;
9462 }
9463}
9464
9465# define getwordrange_usage common_usage
9466
9467static int nodelib_direct_getwordrange(lua_State *L)
9468{
9469 halfword m = nodelib_valid_direct_from_index(L, 1);
9470 if (m) {
9471
9472 halfword l = m;
9473 halfword r = m;
9474 while (node_prev(l) && nodelib_aux_in_word(node_prev(l))) {
9475 l = node_prev(l);
9476 }
9477 while (node_next(r) && nodelib_aux_in_word(node_next(r))) {
9478 r = node_next(r);
9479 }
9480 nodelib_push_direct_or_nil(L, l);
9481 nodelib_push_direct_or_nil(L, r);
9482 } else {
9483 lua_pushnil(L);
9484 lua_pushnil(L);
9485 }
9486 return 2;
9487}
9488
9489
9490
9491static int nodelib_userdata_inuse(lua_State *L)
9492{
9493 int counts[max_node_type + 1] = { 0 };
9494 int n = tex_n_of_used_nodes(&counts[0]);
9495 lua_createtable(L, 0, max_node_type);
9496 for (int i = 0; i < max_node_type; i++) {
9497 if (counts[i]) {
9498 lua_pushstring(L, lmt_interface.node_data[i].name);
9499 lua_pushinteger(L, counts[i]);
9500 lua_rawset(L, -3);
9501 }
9502 }
9503 lua_pushinteger(L, n);
9504 return 2;
9505}
9506
9507
9508
9509static int nodelib_userdata_instock(lua_State *L)
9510{
9511 int counts[max_node_type + 1] = { 0 };
9512 int n = 0;
9513 lua_createtable(L, 0, max_node_type);
9514 for (int i = 1; i < max_chain_size; i++) {
9515 halfword p = lmt_node_memory_state.free_chain[i];
9516 while (p) {
9517 if (node_type(p) <= max_node_type) {
9518 ++counts[node_type(p)];
9519 }
9520 p = node_next(p);
9521 }
9522 }
9523 for (int i = 0; i < max_node_type; i++) {
9524 if (counts[i]) {
9525 lua_pushstring(L, lmt_interface.node_data[i].name);
9526 lua_pushinteger(L, counts[i]);
9527 lua_rawset(L, -3);
9528 n += counts[i];
9529 }
9530 }
9531 lua_pushinteger(L, n);
9532 return 2;
9533}
9534
9535
9536
9537static int nodelib_userdata_usedlist(lua_State *L)
9538{
9539 lmt_push_node_fast(L, tex_list_node_mem_usage());
9540 return 1;
9541}
9542
9543
9544
9545# define usedlist_usage common_usage
9546
9547static int nodelib_direct_usedlist(lua_State *L)
9548{
9549 lua_pushinteger(L, tex_list_node_mem_usage());
9550 return 1;
9551}
9552
9553
9554
9555# define protrusionskippable_usage common_usage
9556
9557static int nodelib_direct_protrusionskipable(lua_State *L)
9558{
9559 halfword n = lmt_tohalfword(L, 1);
9560 if (n) {
9561 lua_pushboolean(L, tex_protrusion_skipable(n));
9562 } else {
9563 lua_pushnil(L);
9564 }
9565 return 1;
9566}
9567
9568
9569
9570static int nodelib_userdata_currentattributes(lua_State* L)
9571{
9572 halfword n = tex_current_attribute_list();
9573 if (n) {
9574 lmt_push_node_fast(L, n);
9575 } else {
9576 lua_pushnil(L);
9577 }
9578 return 1;
9579}
9580
9581
9582
9583# define currentattributes_usage common_usage
9584
9585static int nodelib_direct_currentattributes(lua_State* L)
9586{
9587 halfword n = tex_current_attribute_list();
9588 if (n) {
9589 lua_pushinteger(L, n);
9590 } else {
9591 lua_pushnil(L);
9592 }
9593 return 1;
9594}
9595
9596
9597
9598# define todirect_usage common_usage
9599# define tovaliddirect_usage common_usage
9600
9601static int nodelib_shared_todirect(lua_State* L)
9602{
9603 if (lua_type(L, 1) != LUA_TNUMBER) {
9604
9605 void* n = lua_touserdata(L, 1);
9606 if (n) {
9607 lua_pushinteger(L, *((halfword*)n));
9608 }
9609 else {
9610 lua_pushnil(L);
9611 }
9612 }
9613 return 1;
9614}
9615
9616static int nodelib_direct_tovaliddirect(lua_State* L)
9617{
9618 halfword n = lmt_check_isnode(L, 1);
9619 if (n) {
9620 lua_pushinteger(L, n);
9621 } else {
9622 lua_pushnil(L);
9623 }
9624 return 1;
9625}
9626
9627
9628
9629# define tonode_usage common_usage
9630
9631static int nodelib_shared_tonode(lua_State* L)
9632{
9633 halfword n = nodelib_valid_direct_from_index(L, 1);
9634 if (n) {
9635 halfword* a = (halfword*) lua_newuserdatauv(L, sizeof(halfword), 0);
9636 *a = n;
9637 lua_get_metatablelua(node_instance);
9638 lua_setmetatable(L, -2);
9639 }
9640 return 1;
9641}
9642
9643
9644
9645
9646
9671
9672static int nodelib_direct_check_char(lua_State* L, halfword n)
9673{
9674 if (! glyph_protected(n)) {
9675 halfword b = 0;
9676 halfword f = (halfword) lua_tointegerx(L, 2, &b);
9677 if (! b) {
9678 goto OKAY;
9679 } else if (f == glyph_font(n)) {
9680 switch (lua_gettop(L)) {
9681 case 2:
9682
9683 goto OKAY;
9684 case 3:
9685
9686 if ((halfword) lua_tointegerx(L, 3, NULL) == glyph_data(n)) {
9687 goto OKAY;
9688 } else {
9689 break;
9690 }
9691 case 4:
9692
9693 if ((halfword) lua_tointegerx(L, 3, NULL) == glyph_data(n)) {
9694 halfword state = (halfword) lua_tointegerx(L, 4, NULL);
9695 if (! state || state == glyph_state(n)) {
9696 goto OKAY;
9697 } else {
9698 break;
9699 }
9700 } else {
9701 break;
9702 }
9703 case 5:
9704
9705 if (lua_tointeger(L, 3) == glyph_scale(n) && lua_tointeger(L, 4) == glyph_x_scale(n) && lua_tointeger(L, 5) == glyph_y_scale(n)) {
9706 goto OKAY;
9707 } else {
9708 break;
9709 }
9710 case 6:
9711
9712 if (lua_tointegerx(L, 3, NULL) == glyph_data(n) && lua_tointeger(L, 4) == glyph_scale(n) && lua_tointeger(L, 5) == glyph_x_scale(n) && lua_tointeger(L, 6) == glyph_y_scale(n)) {
9713 goto OKAY;
9714 } else {
9715 break;
9716 }
9717
9718
9719 }
9720 }
9721 }
9722 return -1;
9723 OKAY:
9724 return glyph_character(n);
9725}
9726
9727# define ischar_usage common_usage
9728# define isnextchar_usage common_usage
9729# define isprevchar_usage common_usage
9730
9731static int nodelib_direct_ischar(lua_State *L)
9732{
9733 halfword n = nodelib_valid_direct_from_index(L, 1);
9734 if (n) {
9735 if (node_type(n) != glyph_node) {
9736 lua_pushnil(L);
9737 lua_pushinteger(L, node_type(n));
9738 return 2;
9739 } else {
9740 halfword chr = nodelib_direct_check_char(L, n);
9741 if (chr >= 0) {
9742 lua_pushinteger(L, chr);
9743 } else {
9744 lua_pushboolean(L, 0);
9745 }
9746 return 1;
9747 }
9748 } else {
9749 lua_pushnil(L);
9750 return 1;
9751 }
9752}
9753
9754
9776
9777static inline int nodelib_aux_similar_glyph(halfword first, halfword second)
9778{
9779 return
9780 node_type(second) == glyph_node
9781 && glyph_font(second) == glyph_font(first)
9782 && glyph_data(second) == glyph_data(first)
9783
9784 && glyph_scale(second) == glyph_scale(first)
9785 && glyph_x_scale(second) == glyph_x_scale(first)
9786 && glyph_y_scale(second) == glyph_y_scale(first)
9787 && glyph_slant(second) == glyph_slant(first)
9788 && glyph_weight(second) == glyph_weight(first)
9789 ;
9790}
9791
9792# define issimilarglyph_usage common_usage
9793
9794static int nodelib_direct_issimilarglyph(lua_State *L)
9795{
9796 halfword first = nodelib_valid_direct_from_index(L, 1);
9797 halfword second = nodelib_valid_direct_from_index(L, 2);
9798 lua_pushboolean(L, nodelib_aux_similar_glyph(first, second));
9799 return 1;
9800}
9801
9802static int nodelib_direct_isnextchar(lua_State *L)
9803{
9804 halfword n = nodelib_valid_direct_from_index(L, 1);
9805 if (n) {
9806
9807 halfword nxt = node_next(n);
9808 if (node_type(n) != glyph_node) {
9809 nodelib_push_direct_or_nil(L, nxt);
9810 lua_pushnil(L);
9811 lua_pushinteger(L, node_type(n));
9812 return 3;
9813 } else {
9814 halfword chr = nodelib_direct_check_char(L, n);
9815 nodelib_push_direct_or_nil(L, nxt);
9816 if (chr >= 0) {
9817 lua_pushinteger(L, chr);
9818 if (nxt && nodelib_aux_similar_glyph(n, nxt)) {
9819 lua_pushinteger(L, glyph_character(nxt));
9820 return 3;
9821 }
9822 } else {
9823 lua_pushboolean(L, 0);
9824 }
9825 return 2;
9826 }
9827 } else {
9828 return 0;
9829 }
9830}
9831
9832static int nodelib_direct_isprevchar(lua_State *L)
9833{
9834 halfword n = nodelib_valid_direct_from_index(L, 1);
9835 if (n) {
9836
9837 halfword prv = node_prev(n);
9838 if (node_type(n) != glyph_node) {
9839 nodelib_push_direct_or_nil(L, prv);
9840 lua_pushnil(L);
9841 lua_pushinteger(L, node_type(n));
9842 return 3;
9843 } else {
9844 halfword chr = nodelib_direct_check_char(L, n);
9845 nodelib_push_direct_or_nil(L, prv);
9846 if (chr >= 0) {
9847 lua_pushinteger(L, chr);
9848 if (prv && nodelib_aux_similar_glyph(n, prv)) {
9849 lua_pushinteger(L, glyph_character(prv));
9850 return 3;
9851 }
9852 } else {
9853 lua_pushboolean(L, 0);
9854 }
9855 return 2;
9856 }
9857 } else {
9858 return 0;
9859 }
9860}
9861
9862# define isglyph_usage common_usage
9863# define isnextglyph_usage common_usage
9864# define isprevglyph_usage common_usage
9865
9866static int nodelib_direct_isglyph(lua_State *L)
9867{
9868 halfword n = nodelib_valid_direct_from_index(L, 1);
9869 if (n) {
9870 if (node_type(n) != glyph_node) {
9871 lua_pushboolean(L, 0);
9872 lua_pushinteger(L, node_type(n));
9873 } else {
9874
9875 lua_pushinteger(L, glyph_character(n));
9876 lua_pushinteger(L, glyph_font(n));
9877 }
9878 } else {
9879 lua_pushnil(L);
9880 lua_pushnil(L);
9881 }
9882 return 2;
9883}
9884
9885static int nodelib_direct_isnextglyph(lua_State *L)
9886{
9887 halfword n = nodelib_valid_direct_from_index(L, 1);
9888 if (n) {
9889 nodelib_push_direct_or_nil(L, node_next(n));
9890 if (node_type(n) != glyph_node) {
9891 lua_pushboolean(L, 0);
9892 lua_pushinteger(L, node_type(n));
9893 } else {
9894
9895 lua_pushinteger(L, glyph_character(n));
9896 lua_pushinteger(L, glyph_font(n));
9897 }
9898 return 3;
9899 } else {
9900 return 0;
9901 }
9902}
9903
9904static int nodelib_direct_isprevglyph(lua_State *L)
9905{
9906 halfword n = nodelib_valid_direct_from_index(L, 1);
9907 if (n) {
9908 nodelib_push_direct_or_nil(L, node_prev(n));
9909 if (node_type(n) != glyph_node) {
9910 lua_pushboolean(L, 0);
9911 lua_pushinteger(L, node_type(n));
9912 } else {
9913
9914 lua_pushinteger(L, glyph_character(n));
9915 lua_pushinteger(L, glyph_font(n));
9916 }
9917 return 3;
9918 } else {
9919 return 0;
9920 }
9921}
9922
9923
9924
9925static inline int nodelib_aux_uses_font_disc(lua_State *L, halfword n, halfword font)
9926{
9927 if (font) {
9928 while (n) {
9929 if ((node_type(n) == glyph_node) && (glyph_font(n) == font)) {
9930 lua_pushboolean(L, 1);
9931 return 1;
9932 }
9933 n = node_next(n);
9934 }
9935 } else {
9936 while (n) {
9937 if (node_type(n) == glyph_node) {
9938 lua_pushinteger(L, glyph_font(n));
9939 return 1;
9940 }
9941 n = node_next(n);
9942 }
9943 }
9944 return 0;
9945}
9946
9947# define usesfont_usage common_usage
9948
9949static int nodelib_direct_usesfont(lua_State *L)
9950{
9951 halfword n = nodelib_valid_direct_from_index(L, 1);
9952 if (n) {
9953 halfword f = lmt_opthalfword(L, 2, 0);
9954 switch (node_type(n)) {
9955 case glyph_node:
9956 if (f) {
9957 lua_pushboolean(L, glyph_font(n) == f);
9958 } else {
9959 lua_pushinteger(L, glyph_font(n));
9960 }
9961 return 1;
9962 case disc_node:
9963 if (nodelib_aux_uses_font_disc(L, disc_pre_break_head(n), f)) {
9964 return 1;
9965 } else if (nodelib_aux_uses_font_disc(L, disc_post_break_head(n), f)) {
9966 return 1;
9967 } else if (nodelib_aux_uses_font_disc(L, disc_no_break_head(n), f)) {
9968 return 1;
9969 }
9970
9998 break;
9999
10000 }
10001 }
10002 lua_pushboolean(L, 0);
10003 return 1;
10004}
10005
10006
10007
10008
10009
10010
10011
10012
10013
10014# define getbox_usage common_usage
10015# define setbox_usage common_usage
10016
10017static int nodelib_direct_getbox(lua_State *L)
10018{
10019 int id = lmt_get_box_id(L, 1, 1);
10020 if (id >= 0) {
10021 int t = tex_get_tex_box_register(id, 0);
10022 if (t) {
10023 lua_pushinteger(L, t);
10024 return 1;
10025 }
10026 }
10027 lua_pushnil(L);
10028 return 1;
10029}
10030
10031static int nodelib_direct_setbox(lua_State *L)
10032{
10033 int flags = 0;
10034 int slot = lmt_check_for_flags(L, 1, &flags, 1, 0);
10035 int id = lmt_get_box_id(L, slot++, 1);
10036 if (id >= 0) {
10037 int n;
10038 switch (lua_type(L, slot)) {
10039 case LUA_TBOOLEAN:
10040 {
10041 n = lua_toboolean(L, slot);
10042 if (n == 0) {
10043 n = null;
10044 } else {
10045 return 0;
10046 }
10047 }
10048 break;
10049 case LUA_TNIL:
10050 n = null;
10051 break;
10052 default:
10053 {
10054 n = nodelib_valid_direct_from_index(L, slot);
10055 if (n) {
10056 switch (node_type(n)) {
10057 case hlist_node:
10058 case vlist_node:
10059 break;
10060 default:
10061
10062 return luaL_error(L, "setbox: incompatible node type (%s)\n",get_node_name(node_type(n)));
10063 }
10064 }
10065 }
10066 break;
10067 }
10068 tex_set_tex_box_register(id, n, flags, 0);
10069 }
10070 return 0;
10071}
10072
10073
10074
10075static int nodelib_userdata_isnode(lua_State *L)
10076{
10077 halfword n = lmt_maybe_isnode(L, 1);
10078 if (n) {
10079 lua_pushinteger (L, n);
10080 } else {
10081 lua_pushboolean (L, 0);
10082 }
10083 return 1;
10084}
10085
10086
10087
10088# define isdirect_usage common_usage
10089# define isnode_usage common_usage
10090
10091static int nodelib_direct_isdirect(lua_State *L)
10092{
10093 if (lua_type(L, 1) != LUA_TNUMBER) {
10094 lua_pushboolean(L, 0);
10095 }
10096
10097 return 1;
10098}
10099
10100
10101
10102static int nodelib_direct_isnode(lua_State *L)
10103{
10104 if (! lmt_maybe_isnode(L, 1)) {
10105 lua_pushboolean(L, 0);
10106 } else {
10107
10108 }
10109 return 1;
10110}
10111
10112
10113
10114static int nodelib_userdata_getproperty(lua_State *L)
10115{
10116 halfword n = lmt_check_isnode(L, 1);
10117 if (n) {
10118 lua_rawgeti(L, LUA_REGISTRYINDEX, lmt_node_memory_state.node_properties_id);
10119 lua_rawgeti(L, -1, n);
10120 } else {
10121 lua_pushnil(L);
10122 }
10123 return 1;
10124}
10125
10126# define getproperty_usage common_usage
10127# define setproperty_usage common_usage
10128
10129static int nodelib_direct_getproperty(lua_State *L)
10130{
10131 halfword n = nodelib_valid_direct_from_index(L, 1);
10132 if (n) {
10133 lua_rawgeti(L, LUA_REGISTRYINDEX, lmt_node_memory_state.node_properties_id);
10134 lua_rawgeti(L, -1, n);
10135 } else {
10136 lua_pushnil(L);
10137 }
10138 return 1;
10139}
10140
10141static int nodelib_userdata_setproperty(lua_State *L)
10142{
10143
10144 halfword n = lmt_check_isnode(L, 1);
10145 if (n) {
10146 lua_settop(L, 2);
10147 lua_rawgeti(L, LUA_REGISTRYINDEX, lmt_node_memory_state.node_properties_id);
10148
10149 lua_replace(L, -3);
10150
10151 lua_rawseti(L, -2, n);
10152 }
10153 return 0;
10154}
10155
10156static int nodelib_direct_setproperty(lua_State *L)
10157{
10158
10159 halfword n = nodelib_valid_direct_from_index(L, 1);
10160 if (n) {
10161 lua_settop(L, 2);
10162 lua_rawgeti(L, LUA_REGISTRYINDEX, lmt_node_memory_state.node_properties_id);
10163
10164 lua_replace(L, 1);
10165
10166 lua_rawseti(L, 1, n);
10167 }
10168 return 0;
10169}
10170
10171
10177
10178static int nodelib_direct_getpropertiestable(lua_State *L)
10179{
10180 if (lua_toboolean(L, lua_gettop(L))) {
10181
10182 lmt_initialize_properties(1);
10183 }
10184 lua_rawgeti(L, LUA_REGISTRYINDEX, lmt_node_memory_state.node_properties_id);
10185 return 1;
10186}
10187
10188static int nodelib_userdata_getpropertiestable(lua_State *L)
10189{
10190 lua_get_metatablelua(node_properties_indirect);
10191 return 1;
10192}
10193
10194
10195
10196static void nodelib_direct_effect_done(lua_State *L, halfword amount, halfword stretch, halfword shrink, halfword stretch_order, halfword shrink_order)
10197{
10198 halfword parent = nodelib_valid_direct_from_index(L, 2);
10199 if (parent) {
10200 singleword sign = box_glue_sign(parent);
10201 if (sign != normal_glue_sign) {
10202 switch (node_type(parent)) {
10203 case hlist_node:
10204 case vlist_node:
10205 {
10206 double w = (double) amount;
10207 switch (sign) {
10208 case stretching_glue_sign:
10209 if (stretch_order == box_glue_order(parent)) {
10210 w += stretch * (double) box_glue_set(parent);
10211 }
10212 break;
10213 case shrinking_glue_sign:
10214 if (shrink_order == box_glue_order(parent)) {
10215 w -= shrink * (double) box_glue_set(parent);
10216 }
10217 break;
10218 }
10219 if (lua_toboolean(L, 3)) {
10220 lua_pushinteger(L, lmt_roundedfloat(w));
10221 } else {
10222 lua_pushnumber(L, w);
10223 }
10224 return;
10225 }
10226 }
10227 }
10228 }
10229 lua_pushinteger(L, amount);
10230}
10231
10232# define effectiveglue_usage (glue_usage | math_usage)
10233
10234static int nodelib_direct_effectiveglue(lua_State *L)
10235{
10236 halfword n = nodelib_valid_direct_from_index(L, 1);
10237 if (n) {
10238 switch (node_type(n)) {
10239 case glue_node:
10240 nodelib_direct_effect_done(L, glue_amount(n), glue_stretch(n), glue_shrink(n), glue_stretch_order(n), glue_shrink_order(n));
10241 break;
10242 case math_node:
10243 if (math_surround(n)) {
10244 lua_pushinteger(L, math_surround(n));
10245 } else {
10246 nodelib_direct_effect_done(L, math_amount(n), math_stretch(n), math_shrink(n), math_stretch_order(n), math_shrink_order(n));
10247 }
10248 break;
10249 default:
10250 lua_pushinteger(L, 0);
10251 break;
10252 }
10253 } else {
10254 lua_pushinteger(L, 0);
10255 }
10256 return 1;
10257}
10258
10259
10269
10270# define checkdiscretionaries_usage common_usage
10271# define checkdiscretionary_usage disc_usage
10272
10273static int nodelib_direct_checkdiscretionaries(lua_State *L) {
10274 halfword n = nodelib_valid_direct_from_index(L, 1);
10275 if (n) {
10276 while (n) {
10277 if (node_type(n) == disc_node) {
10278 tex_check_disc_field(n);
10279 }
10280 n = node_next(n) ;
10281 }
10282 }
10283 return 0;
10284}
10285
10286static int nodelib_direct_checkdiscretionary(lua_State *L) {
10287 halfword n = nodelib_valid_direct_from_index(L, 1);
10288 if (n && node_type(n) == disc_node) {
10289 halfword p = disc_pre_break_head(n);
10290 disc_pre_break_tail(n) = p ? tex_tail_of_node_list(p) : null;
10291 p = disc_post_break_head(n);
10292 disc_post_break_tail(n) = p ? tex_tail_of_node_list(p) : null;
10293 p = disc_no_break_head(n);
10294 disc_no_break_tail(n) = p ? tex_tail_of_node_list(p) : null;
10295 }
10296 return 0;
10297}
10298
10299# define flattendiscretionaries_usage common_usage
10300
10301static int nodelib_direct_flattendiscretionaries(lua_State *L)
10302{
10303 int count = 0;
10304 halfword head = nodelib_valid_direct_from_index(L, 1);
10305 if (head) {
10306 head = tex_flatten_discretionaries(head, &count, lua_toboolean(L, 2));
10307 } else {
10308 head = null;
10309 }
10310 nodelib_push_direct_or_nil(L, head);
10311 lua_pushinteger(L, count);
10312 return 2;
10313}
10314
10315# define softenhyphens_usage common_usage
10316
10317static int nodelib_direct_softenhyphens(lua_State *L)
10318{
10319 int found = 0;
10320 int replaced = 0;
10321 halfword head = nodelib_valid_direct_from_index(L, 1);
10322 if (head) {
10323 tex_soften_hyphens(head, &found, &replaced);
10324 }
10325 nodelib_push_direct_or_nil(L, head);
10326 lua_pushinteger(L, found);
10327 lua_pushinteger(L, replaced);
10328 return 3;
10329}
10330
10331
10332
10333# define getinputfields_usage (glyph_usage | hlist_usage | vlist_usage | unset_usage)
10334# define setinputfields_usage getinputfields_usage
10335
10336static int nodelib_direct_getinputfields(lua_State *L)
10337{
10338 halfword n = nodelib_valid_direct_from_index(L, 1);
10339 if (n) {
10340 switch (node_type(n)) {
10341 case glyph_node:
10342 lua_pushinteger(L, glyph_input_file(n));
10343 lua_pushinteger(L, glyph_input_line(n));
10344 break;
10345 case hlist_node:
10346 case vlist_node:
10347 case unset_node:
10348 lua_pushinteger(L, box_input_file(n));
10349 lua_pushinteger(L, box_input_line(n));
10350 break;
10351 default:
10352 return 0;
10353 }
10354 return 2;
10355 }
10356 return 0;
10357}
10358
10359static int nodelib_direct_setinputfields(lua_State *L)
10360{
10361 halfword n = nodelib_valid_direct_from_index(L, 1);
10362 if (n) {
10363
10364 halfword tag = lmt_tohalfword(L, 2);
10365 halfword line = lmt_tohalfword(L, 3);
10366 switch (node_type(n)) {
10367 case glyph_node:
10368 glyph_input_file(n) = tag;
10369 glyph_input_line(n) = line;
10370 break;
10371 case hlist_node:
10372 case vlist_node:
10373 case unset_node:
10374 box_input_file(n) = tag;
10375 box_input_line(n) = line;
10376 break;
10377 }
10378 }
10379 return 0;
10380}
10381
10382
10386
10387static int nodelib_direct_makeextensible(lua_State *L)
10388{
10389 int top = lua_gettop(L);
10390 if (top >= 3) {
10391 halfword fnt = lmt_tohalfword(L, 1);
10392 halfword chr = lmt_tohalfword(L, 2);
10393 halfword target = lmt_tohalfword(L, 3);
10394 halfword size = lmt_opthalfword(L, 4, 0);
10395 halfword overlap = lmt_opthalfword(L, 5, 65536);
10396 halfword attlist = null;
10397 halfword b = null;
10398 int horizontal = 0;
10399 if (top >= 4) {
10400 overlap = lmt_tohalfword(L, 4);
10401 if (top >= 5) {
10402 horizontal = lua_toboolean(L, 5);
10403 if (top >= 6) {
10404 attlist = nodelib_valid_direct_from_index(L, 6);
10405 }
10406 }
10407 }
10408 b = tex_make_extensible(fnt, chr, target, overlap, horizontal, attlist, size);
10409 lua_pushinteger(L, b);
10410 } else {
10411 lua_pushnil(L);
10412 }
10413 return 1;
10414}
10415
10416# define flattenleaders_usage common_usage
10417
10418static int nodelib_direct_flattenleaders(lua_State *L)
10419{
10420 halfword n = nodelib_valid_direct_from_index(L, 1);
10421 int count = 0;
10422 if (n) {
10423 switch (node_type(n)) {
10424 case hlist_node:
10425 count = tex_flatten_leaders(n, hbox_group, 0, uleader_lua, 0);
10426 break;
10427 case vlist_node:
10428 count = tex_flatten_leaders(n, vbox_group, 0, uleader_lua, 0);
10429 break;
10430 }
10431 }
10432 lua_pushinteger(L, count);
10433 return 1;
10434}
10435
10436
10437
10438# define isvalid_usage common_usage
10439
10440static int nodelib_direct_isvalid(lua_State *L)
10441{
10442 lua_pushboolean(L, nodelib_valid_direct_from_index(L, 1));
10443 return 1;
10444}
10445
10446
10447
10448static inline scaled set_effective_width(halfword source, halfword sign, halfword order, double glue)
10449{
10450 scaled amount = glue_amount(source);
10451 switch (sign) {
10452 case stretching_glue_sign:
10453 if (glue_stretch_order(source) == order) {
10454 return amount + scaledround((double) glue_stretch(source) * glue);
10455 } else {
10456 break;
10457 }
10458 case shrinking_glue_sign:
10459 if (glue_shrink_order(source) == order) {
10460 return amount + scaledround((double) glue_shrink(source) * glue);
10461 } else {
10462 break;
10463 }
10464 }
10465 return amount;
10466}
10467
10468# define getnormalizedline_usage hlist_usage
10469
10470static int nodelib_direct_getnormalizedline(lua_State *L)
10471{
10472 halfword n = nodelib_valid_direct_from_index(L, 1);
10473 if (n && node_type(n) == hlist_node && node_subtype(n) == line_list) {
10474 halfword head = box_list(n);
10475 halfword tail = head;
10476 halfword first = head;
10477 halfword last = tail;
10478 halfword current = head;
10479 scaled ls = 0;
10480 scaled rs = 0;
10481 scaled is = 0;
10482 scaled pr = 0;
10483 scaled pl = 0;
10484 scaled ir = 0;
10485 scaled il = 0;
10486 scaled lh = 0;
10487 scaled rh = 0;
10488 scaled cs = 0;
10489 singleword sign = box_glue_sign(n);
10490 halfword order = box_glue_order(n);
10491 double glue = box_glue_set(n);
10492 int details = lua_toboolean(L, 2);
10493 while (current) {
10494 tail = current ;
10495 if (node_type(current) == glue_node) {
10496 switch (node_subtype(current)) {
10497 case left_skip_glue : ls = set_effective_width(current, sign, order, glue); break;
10498 case right_skip_glue : rs = set_effective_width(current, sign, order, glue); break;
10499 case par_fill_left_skip_glue : pl = set_effective_width(current, sign, order, glue); break;
10500 case par_fill_right_skip_glue : pr = set_effective_width(current, sign, order, glue); break;
10501 case par_init_left_skip_glue : il = set_effective_width(current, sign, order, glue); break;
10502 case par_init_right_skip_glue : ir = set_effective_width(current, sign, order, glue); break;
10503 case indent_skip_glue : is = set_effective_width(current, sign, order, glue); break;
10504 case left_hang_skip_glue : lh = set_effective_width(current, sign, order, glue); break;
10505 case right_hang_skip_glue : rh = set_effective_width(current, sign, order, glue); break;
10506 case correction_skip_glue : cs = set_effective_width(current, sign, order, glue); break;
10507 }
10508 }
10509 current = node_next(current);
10510 }
10511 tex_get_line_content_range(head, tail, &first, &last);
10512 lua_createtable(L, 0, 14);
10513 lua_push_integer_at_key(L, leftskip, ls);
10514 lua_push_integer_at_key(L, rightskip, rs);
10515 lua_push_integer_at_key(L, lefthangskip, lh);
10516 lua_push_integer_at_key(L, righthangskip, rh);
10517 lua_push_integer_at_key(L, indent, is);
10518 lua_push_integer_at_key(L, parfillleftskip, pl);
10519 lua_push_integer_at_key(L, parfillrightskip, pr);
10520 lua_push_integer_at_key(L, parinitleftskip, il);
10521 lua_push_integer_at_key(L, parinitrightskip, ir);
10522 lua_push_integer_at_key(L, correctionskip, cs);
10523 lua_push_integer_at_key(L, first, first);
10524 lua_push_integer_at_key(L, last, last);
10525 lua_push_integer_at_key(L, head, head);
10526 lua_push_integer_at_key(L, tail, tail);
10527 if (details) {
10528 scaled ns = tex_natural_hsize(box_list(n), &cs);
10529 lua_push_integer_at_key(L, width, box_width(n));
10530 lua_push_integer_at_key(L, height, box_height(n));
10531 lua_push_integer_at_key(L, depth, box_depth(n));
10532 lua_push_integer_at_key(L, left, ls + lh + pl + il);
10533 lua_push_integer_at_key(L, right, rs + rh + pr + ir);
10534 lua_push_integer_at_key(L, size, ns);
10535 }
10536 return 1;
10537 }
10538 return 0;
10539}
10540
10541
10542
10543# define ignoremathskip_usage math_usage
10544
10545static int nodelib_direct_ignoremathskip(lua_State *L)
10546{
10547 halfword n = nodelib_valid_direct_from_index(L, 1);
10548 if (n && node_type(n) == math_node) {
10549 lua_pushboolean(L, tex_ignore_math_skip(n));
10550 } else {
10551 lua_pushboolean(L, 0);
10552 }
10553 return 1;
10554}
10555
10556# define reverse_usage common_usage
10557
10558static int nodelib_direct_reverse(lua_State *L)
10559{
10560 halfword n = nodelib_valid_direct_from_index(L, 1);
10561 if (n) {
10562 n = tex_reversed_node_list(n);
10563 }
10564 nodelib_push_direct_or_nil(L, n);
10565 return 1;
10566}
10567
10568# define exchange_usage common_usage
10569
10570static int nodelib_direct_exchange(lua_State *L)
10571{
10572 halfword head = nodelib_valid_direct_from_index(L, 1);
10573 if (head) {
10574 halfword first = nodelib_valid_direct_from_index(L, 2);
10575 if (first) {
10576 halfword second = nodelib_valid_direct_from_index(L, 3);
10577 if (! second) {
10578 second = node_next(first);
10579 }
10580 if (second) {
10581 halfword pf = node_prev(first);
10582 halfword ns = node_next(second);
10583 if (first == head) {
10584 head = second;
10585 } else if (second == head) {
10586 head = first;
10587 }
10588 if (second == node_next(first)) {
10589 node_prev(first) = second;
10590 node_next(second) = first;
10591 } else {
10592 halfword nf = node_next(first);
10593 halfword ps = node_prev(second);
10594 node_prev(first) = ps;
10595 if (ps) {
10596 node_next(ps) = first;
10597 }
10598 node_next(second) = nf;
10599 if (nf) {
10600 node_prev(nf) = second;
10601 }
10602 }
10603 node_next(first) = ns;
10604 node_prev(second) = pf;
10605 if (pf) {
10606 node_next(pf) = second;
10607 }
10608 if (ns) {
10609 node_prev(ns) = first;
10610 }
10611 }
10612 }
10613 }
10614 nodelib_push_direct_or_nil(L, head);
10615 return 1;
10616}
10617
10618
10619
10620# define migrate_usage (hlist_usage | vlist_usage | insert_usage)
10621
10622static int nodelib_direct_migrate(lua_State *L)
10623{
10624 halfword head = nodelib_valid_direct_from_index(L, 1);
10625 if (head) {
10626 int inserts = lua_type(L, 3) == LUA_TBOOLEAN ? lua_toboolean(L, 2) : 1;
10627 int marks = lua_type(L, 2) == LUA_TBOOLEAN ? lua_toboolean(L, 3) : 1;
10628 halfword first = null;
10629 halfword last = null;
10630 tex_migrate(head, &first, &last, inserts, marks);
10631 nodelib_push_direct_or_nil(L, head);
10632 nodelib_push_direct_or_nil(L, first);
10633 nodelib_push_direct_or_nil(L, last);
10634 return 3;
10635 }
10636 return 0;
10637}
10638
10639
10640
10641static int nodelib_aux_no_left(halfword n, halfword l, halfword r)
10642{
10643 if (tex_has_glyph_option(n, (singleword) l)) {
10644 return 1;
10645 } else {
10646 n = node_prev(n);
10647 if (n) {
10648 if (node_type(n) == disc_node) {
10649 n = disc_no_break_tail(n);
10650 }
10651 if (n && node_type(n) == glyph_node && tex_has_glyph_option(n, (singleword) r)) {
10652 return 1;
10653 }
10654 }
10655 }
10656 return 0;
10657}
10658
10659static int nodelib_aux_no_right(halfword n, halfword r, halfword l)
10660{
10661 if (tex_has_glyph_option(n, (singleword) r)) {
10662 return 1;
10663 } else {
10664 n = node_next(n);
10665 if (node_type(n) == disc_node) {
10666 n = disc_no_break_head(n);
10667 }
10668 if (n && node_type(n) == glyph_node && tex_has_glyph_option(n, (singleword) l)) {
10669 return 1;
10670 }
10671 }
10672 return 0;
10673}
10674
10675
10676
10677# define hasglyphoption_usage glyph_usage
10678
10679static int nodelib_direct_hasglyphoption(lua_State *L)
10680{
10681 halfword current = nodelib_valid_direct_from_index(L, 1);
10682 int result = 0;
10683 if (current && node_type(current) == glyph_node) {
10684 int option = lmt_tointeger(L, 2);
10685 switch (option) {
10686 case glyph_option_normal_glyph:
10687 break;
10688 case glyph_option_no_left_ligature:
10689 result = nodelib_aux_no_left(current, glyph_option_no_left_ligature, glyph_option_no_right_ligature);
10690 break;
10691 case glyph_option_no_right_ligature:
10692 result = nodelib_aux_no_right(current, glyph_option_no_right_ligature, glyph_option_no_left_ligature);
10693 break;
10694 case glyph_option_no_left_kern:
10695 result = nodelib_aux_no_left(current, glyph_option_no_left_kern, glyph_option_no_right_kern);
10696 break;
10697 case glyph_option_no_right_kern:
10698 result = nodelib_aux_no_right(current, glyph_option_no_right_kern, glyph_option_no_left_kern);
10699 break;
10700 case glyph_option_no_expansion:
10701 case glyph_option_no_protrusion:
10702 case glyph_option_apply_x_offset:
10703 case glyph_option_apply_y_offset:
10704
10705 break;
10706 case glyph_option_no_italic_correction:
10707 case glyph_option_no_zero_italic_correction:
10708 case glyph_option_math_discretionary:
10709 case glyph_option_math_italics_too:
10710 result = tex_has_glyph_option(current, option);
10711 break;
10712 default:
10713
10714 result = tex_has_glyph_option(current, option);
10715 }
10716 }
10717 lua_pushboolean(L, result);
10718 return 1;
10719}
10720
10721# define hasdiscoption_usage disc_usage
10722
10723static int nodelib_direct_hasdiscoption(lua_State *L)
10724{
10725 halfword current = nodelib_valid_direct_from_index(L, 1);
10726 int result = 0;
10727 if (current && node_type(current) == disc_node) {
10728
10729 result = tex_has_disc_option(current, lmt_tointeger(L, 2));
10730 }
10731 lua_pushboolean(L, result);
10732 return 1;
10733}
10734
10735# define isitalicglyph_usage glyph_usage
10736
10737static int nodelib_direct_isitalicglyph(lua_State *L)
10738{
10739 halfword n = nodelib_valid_direct_from_index(L, 1);
10740 lua_pushboolean(L,
10741 n && node_type(n) == glyph_node && ! tex_has_glyph_option(n, glyph_option_no_italic_correction) && (
10742 glyph_slant(n)
10743 || has_font_text_control(glyph_font(n), text_control_has_italics)
10744 || has_font_text_control(glyph_font(n), text_control_auto_italics)
10745 )
10746 );
10747 return 1;
10748}
10749
10750# define firstitalicglyph_usage common_usage
10751
10752static int nodelib_direct_firstitalicglyph(lua_State *L)
10753{
10754 halfword n = nodelib_valid_direct_from_index(L, 1);
10755 int kerntoo = lua_toboolean(L, 2);
10756 while (n) {
10757 switch (node_type(n)) {
10758 case glyph_node:
10759 if (! tex_has_glyph_option(n, glyph_option_no_italic_correction) && (glyph_slant(n)
10760 || has_font_text_control(glyph_font(n), text_control_has_italics)
10761 || has_font_text_control(glyph_font(n), text_control_auto_italics)
10762 )) {
10763 goto DONE;
10764 }
10765 break;
10766 case kern_node:
10767 if (kerntoo) {
10768 switch (node_subtype(n)) {
10769 case italic_kern_subtype:
10770 case left_correction_kern_subtype:
10771 case right_correction_kern_subtype:
10772 goto DONE;
10773 }
10774 }
10775 break;
10776 }
10777 n = node_next(n);
10778 }
10779 DONE:
10780 nodelib_push_direct_or_nil(L, n);
10781 return 1;
10782}
10783
10784
10785
10786# define isspeciallist_usage common_usage
10787# define getspeciallist_usage common_usage
10788# define setspeciallist_usage common_usage
10789
10790static int nodelib_direct_getspeciallist(lua_State *L)
10791{
10792 const char *s = lua_tostring(L, 1);
10793 halfword head = null;
10794 halfword tail = null;
10795 if (! s) {
10796
10797 } else if (lua_key_eq(s, pageinserthead)) {
10798 head = tex_get_special_node_list(page_insert_list_type, &tail);
10799 } else if (lua_key_eq(s, contributehead)) {
10800 head = tex_get_special_node_list(contribute_list_type, &tail);
10801 } else if (lua_key_eq(s, pagehead)) {
10802 head = tex_get_special_node_list(page_list_type, &tail);
10803 } else if (lua_key_eq(s, temphead)) {
10804 head = tex_get_special_node_list(temp_list_type, &tail);
10805 } else if (lua_key_eq(s, holdhead)) {
10806 head = tex_get_special_node_list(hold_list_type, &tail);
10807 } else if (lua_key_eq(s, postadjusthead)) {
10808 head = tex_get_special_node_list(post_adjust_list_type, &tail);
10809 } else if (lua_key_eq(s, preadjusthead)) {
10810 head = tex_get_special_node_list(pre_adjust_list_type, &tail);
10811 } else if (lua_key_eq(s, postmigratehead)) {
10812 head = tex_get_special_node_list(post_migrate_list_type, &tail);
10813 } else if (lua_key_eq(s, premigratehead)) {
10814 head = tex_get_special_node_list(pre_migrate_list_type, &tail);
10815 } else if (lua_key_eq(s, alignhead)) {
10816 head = tex_get_special_node_list(align_list_type, &tail);
10817 } else if (lua_key_eq(s, pagediscardshead)) {
10818 head = tex_get_special_node_list(page_discards_list_type, &tail);
10819 } else if (lua_key_eq(s, splitdiscardshead)) {
10820 head = tex_get_special_node_list(split_discards_list_type, &tail);
10821 }
10822 nodelib_push_direct_or_nil(L, head);
10823 nodelib_push_direct_or_nil(L, tail);
10824 return 2;
10825}
10826
10827static int nodelib_direct_isspeciallist(lua_State *L)
10828{
10829 halfword head = nodelib_valid_direct_from_index(L, 1);
10830 int istail = 0;
10831 int checked = tex_is_special_node_list(head, &istail);
10832 if (checked >= 0) {
10833 lua_pushinteger(L, checked);
10834 if (istail) {
10835 lua_pushboolean(L, 1);
10836 return 2;
10837 }
10838 } else {
10839 lua_pushboolean(L, 0);
10840 }
10841 return 1;
10842}
10843
10844static int nodelib_direct_setspeciallist(lua_State *L)
10845{
10846 halfword head = nodelib_valid_direct_from_index(L, 2);
10847 const char *s = lua_tostring(L, 1);
10848 if (! s) {
10849
10850 } else if (lua_key_eq(s, pageinserthead)) {
10851 tex_set_special_node_list(page_insert_list_type, head);
10852 } else if (lua_key_eq(s, contributehead)) {
10853 tex_set_special_node_list(contribute_list_type, head);
10854 } else if (lua_key_eq(s, pagehead)) {
10855 tex_set_special_node_list(page_list_type, head);
10856 } else if (lua_key_eq(s, temphead)) {
10857 tex_set_special_node_list(temp_list_type, head);
10858 } else if (lua_key_eq(s, holdhead)) {
10859 tex_set_special_node_list(hold_list_type, head);
10860 } else if (lua_key_eq(s, postadjusthead)) {
10861 tex_set_special_node_list(post_adjust_list_type, head);
10862 } else if (lua_key_eq(s, preadjusthead)) {
10863 tex_set_special_node_list(pre_adjust_list_type, head);
10864 } else if (lua_key_eq(s, postmigratehead)) {
10865 tex_set_special_node_list(post_migrate_list_type, head);
10866 } else if (lua_key_eq(s, premigratehead)) {
10867 tex_set_special_node_list(pre_migrate_list_type, head);
10868 } else if (lua_key_eq(s, alignhead)) {
10869 tex_set_special_node_list(align_list_type, head);
10870 } else if (lua_key_eq(s, pagediscardshead)) {
10871 tex_set_special_node_list(page_discards_list_type, head);
10872 } else if (lua_key_eq(s, splitdiscardshead)) {
10873 tex_set_special_node_list(split_discards_list_type, head);
10874 }
10875 return 0;
10876}
10877
10878
10879
10880# define getmvllist_usage common_usage
10881# define setmvllist_usage common_usage
10882
10883static int nodelib_direct_getmvllist(lua_State *L)
10884{
10885
10886 halfword head = null;
10887 halfword tail = null;
10888 halfword mvl = tex_current_mvl(&head, &tail);
10889 lua_pushinteger(L, head);
10890 lua_pushinteger(L, tail);
10891 lua_pushinteger(L, mvl);
10892 return 3;
10893}
10894
10895# define vbalance_usage common_usage
10896
10897static int nodelib_direct_vbalance(lua_State *L)
10898{
10899 halfword index = lmt_get_box_id(L, 1, 1);
10900 halfword mode = nodelib_aux_packing(L, 2);
10901 halfword trial = lua_toboolean(L, 3);
10902 nodelib_push_direct_or_nil(L, tex_vbalance(index, mode, trial));
10903 return 1;
10904}
10905
10906# define updatetopmarks_usage common_usage
10907# define updatefirstmarks_usage common_usage
10908# define updatefirstandbotmark_usage no_usage
10909# define updatemarks_usage no_usage
10910
10911
10912
10913static int nodelib_direct_updatetopmarks(lua_State *L)
10914{
10915 lua_pushboolean(L, tex_update_top_marks());
10916 return 1;
10917}
10918
10919
10920
10921static int nodelib_direct_updatefirstmarks(lua_State *L)
10922{
10923 lua_pushboolean(L, tex_update_first_marks());
10924 return 1;
10925}
10926
10927
10928
10929static int nodelib_direct_updatefirstandbotmark(lua_State *L)
10930{
10931 halfword n = nodelib_valid_direct_from_index(L, 1);
10932 if (n) {
10933 tex_update_first_and_bot_mark(n);
10934 }
10935 return 0;
10936}
10937
10938static int nodelib_direct_updatemarks(lua_State *L)
10939{
10940 halfword n = nodelib_valid_direct_from_index(L, 1);
10941 lua_pushboolean(L, n ? tex_update_marks(n) : 0);
10942 return 1;
10943}
10944
10945
10946
10947
10948
10949
10950
10951
10952
10953
10954
10955
10956
10957
10958
10959
10960
10966
10967# define getnodes_usage common_usage
10968
10969static int nodelib_direct_getnodes(lua_State *L)
10970{
10971 halfword n = nodelib_valid_direct_from_index(L, 1);
10972 if (n) {
10973 int i = 0;
10974
10975 lua_newtable(L);
10976 if (lua_type(L, 2) == LUA_TNUMBER) {
10977 int t = lmt_tointeger(L, 2);
10978 if (lua_type(L, 3) == LUA_TNUMBER) {
10979 int s = lmt_tointeger(L, 3);
10980 while (n) {
10981 if (node_type(n) == t && node_subtype(n) == s) {
10982 lua_pushinteger(L, n);
10983 lua_rawseti(L, -2, ++i);
10984 }
10985 n = node_next(n);
10986 }
10987 } else {
10988 while (n) {
10989 if (node_type(n) == t) {
10990 lua_pushinteger(L, n);
10991 lua_rawseti(L, -2, ++i);
10992 }
10993 n = node_next(n);
10994 }
10995 }
10996 } else {
10997 while (n) {
10998 lua_pushinteger(L, n);
10999 lua_rawseti(L, -2, ++i);
11000 n = node_next(n);
11001 }
11002 }
11003 if (i) {
11004 return 1;
11005 } else {
11006 lua_pop(L, 1);
11007 }
11008 }
11009 lua_pushnil(L);
11010 return 1;
11011}
11012
11013
11014
11015static int nodelib_direct_getusedattributes(lua_State* L)
11016{
11017 lua_newtable(L);
11018 for (int current = lmt_node_memory_state.nodes_data.top; current > lmt_node_memory_state.reserved; current--) {
11019 if (lmt_node_memory_state.nodesizes[current] > 0 && (node_type(current) == attribute_node && node_subtype(current) != attribute_list_subtype)) {
11020 if (lua_rawgeti(L, -1, attribute_index(current)) == LUA_TTABLE) {
11021 lua_pushboolean(L, 1);
11022 lua_rawseti(L, -2, attribute_value(current));
11023 lua_pop(L, 1);
11024
11025
11026
11027
11028
11029
11030 } else {
11031 lua_pop(L, 1);
11032 lua_newtable(L);
11033 lua_pushboolean(L, 1);
11034 lua_rawseti(L, -2, attribute_value(current));
11035 lua_rawseti(L, -2, attribute_index(current));
11036 }
11037 }
11038 }
11039 return 1;
11040}
11041
11042static int nodelib_shared_getcachestate(lua_State *L)
11043{
11044 lua_pushboolean(L, attribute_cache_disabled);
11045 return 1;
11046}
11047
11048
11049
11050static int nodelib_get_property_t(lua_State *L)
11051{
11052 halfword n = lmt_check_isnode(L, 2);
11053 if (n) {
11054 lua_rawgeti(L, LUA_REGISTRYINDEX, lmt_node_memory_state.node_properties_id);
11055
11056 lua_rawgeti(L, -1, n);
11057 } else {
11058 lua_pushnil(L);
11059 }
11060 return 1;
11061}
11062
11063static int nodelib_set_property_t(lua_State *L)
11064{
11065
11066 halfword n = lmt_check_isnode(L, 2);
11067 if (n) {
11068 lua_rawgeti(L, LUA_REGISTRYINDEX, lmt_node_memory_state.node_properties_id);
11069
11070 lua_insert(L, -2);
11071
11072 lua_rawseti(L, -2, n);
11073 }
11074 return 0;
11075}
11076
11077
11078
11079# define gluetostring_usage (glue_usage | glue_spec_usage)
11080
11081static int nodelib_hybrid_gluetostring(lua_State *L)
11082{
11083 halfword glue = lua_type(L, 1) == LUA_TNUMBER ? nodelib_valid_direct_from_index(L, 1): lmt_maybe_isnode(L, 1);
11084 if (glue) {
11085 switch (node_type(glue)) {
11086 case glue_node:
11087 case glue_spec_node:
11088 {
11089 int saved_selector = lmt_print_state.selector;
11090 char *str = NULL;
11091 lmt_print_state.selector = new_string_selector_code;
11092 tex_print_spec(glue, pt_unit);
11093 str = tex_take_string(NULL);
11094 lmt_print_state.selector = saved_selector;
11095 lua_pushstring(L, str);
11096 return 1;
11097 }
11098 }
11099 }
11100 return 0;
11101}
11102
11103static const struct luaL_Reg nodelib_p[] = {
11104 { "__index", nodelib_get_property_t },
11105 { "__newindex", nodelib_set_property_t },
11106 { NULL, NULL },
11107};
11108
11109void lmt_initialize_properties(int set_size)
11110{
11111 lua_State *L = lmt_lua_state.lua_instance;
11112 if (lmt_node_memory_state.node_properties_id) {
11113
11118 luaL_unref(L, LUA_REGISTRYINDEX, lmt_node_memory_state.node_properties_id);
11119 lmt_node_memory_state.node_properties_id = 0;
11120 }
11121 if (set_size) {
11122 tex_engine_get_config_number("propertiessize", &lmt_node_memory_state.node_properties_table_size);
11123 if (lmt_node_memory_state.node_properties_table_size < 0) {
11124 lmt_node_memory_state.node_properties_table_size = 0;
11125 }
11126
11127 lua_createtable(L, 0, lmt_node_memory_state.node_properties_table_size);
11128 } else {
11129 lua_newtable(L);
11130 }
11131
11132 lmt_node_memory_state.node_properties_id = luaL_ref(L, LUA_REGISTRYINDEX);
11133
11134 lua_pushstring(L, NODE_PROPERTIES_DIRECT);
11135
11136 lua_rawgeti(L, LUA_REGISTRYINDEX, lmt_node_memory_state.node_properties_id);
11137
11138 lua_settable(L, LUA_REGISTRYINDEX);
11139
11140 lua_pushstring(L, NODE_PROPERTIES_INDIRECT);
11141
11142 lua_newtable(L);
11143
11144 luaL_newmetatable(L, NODE_PROPERTIES_INSTANCE);
11145
11146 luaL_setfuncs(L, nodelib_p, 0);
11147
11148 lua_setmetatable(L, -2);
11149
11150 lua_settable(L, LUA_REGISTRYINDEX);
11151
11152}
11153
11154
11155
11156typedef enum usage_targets {
11157 no_usage_target = 0,
11158 direct_usage_target = 1,
11159 userdata_usage_target = 2,
11160 separate_usage_target = 3,
11161 hybrid_usage_target = 4,
11162 general_usage_target = 5,
11163} usage_targets;
11164
11165typedef struct usage_record {
11166 const char *name;
11167 lua_Integer usage;
11168 int target;
11169} usage_record;
11170
11171static const usage_record usage_data[] = {
11172 { .name = "addmargins", .target = direct_usage_target, .usage = addmargins_usage },
11173 { .name = "addxoffset", .target = direct_usage_target, .usage = addxoffset_usage },
11174 { .name = "addxymargins", .target = direct_usage_target, .usage = addxymargins_usage },
11175 { .name = "addyoffset", .target = direct_usage_target, .usage = addyoffset_usage },
11176 { .name = "appendaftertail", .target = direct_usage_target, .usage = appendaftertail_usage },
11177 { .name = "beginofmath", .target = direct_usage_target, .usage = beginofmath_usage },
11178 { .name = "checkdiscretionaries", .target = direct_usage_target, .usage = checkdiscretionaries_usage },
11179 { .name = "checkdiscretionary", .target = direct_usage_target, .usage = checkdiscretionary_usage },
11180 { .name = "collapsing", .target = direct_usage_target, .usage = collapsing_usage },
11181 { .name = "copy", .target = separate_usage_target, .usage = copy_usage },
11182 { .name = "copylist", .target = separate_usage_target, .usage = copylist_usage },
11183 { .name = "copyonly", .target = direct_usage_target, .usage = copyonly_usage },
11184 { .name = "count", .target = direct_usage_target, .usage = count_usage },
11185 { .name = "currentattributes", .target = separate_usage_target, .usage = currentattributes_usage },
11186 { .name = "dimensions", .target = direct_usage_target, .usage = dimensions_usage },
11187 { .name = "effectiveglue", .target = direct_usage_target, .usage = effectiveglue_usage },
11188 { .name = "endofmath", .target = direct_usage_target, .usage = endofmath_usage },
11189 { .name = "exchange", .target = direct_usage_target, .usage = exchange_usage },
11190 { .name = "fields", .target = general_usage_target, .usage = fields_usage },
11191 { .name = "findattribute", .target = direct_usage_target, .usage = findattribute_usage },
11192 { .name = "findattributerange", .target = direct_usage_target, .usage = findattributerange_usage },
11193 { .name = "findnode", .target = direct_usage_target, .usage = findnode_usage },
11194 { .name = "firstchar", .target = direct_usage_target, .usage = firstchar_usage },
11195 { .name = "firstglyph", .target = direct_usage_target, .usage = firstglyph_usage },
11196 { .name = "firstglyphnode", .target = direct_usage_target, .usage = firstglyphnode_usage },
11197 { .name = "firstitalicglyph", .target = direct_usage_target, .usage = firstitalicglyph_usage },
11198 { .name = "flattendiscretionaries", .target = direct_usage_target, .usage = flattendiscretionaries_usage },
11199 { .name = "flattenleaders", .target = direct_usage_target, .usage = flattenleaders_usage },
11200 { .name = "flushlist", .target = separate_usage_target, .usage = flushlist_usage },
11201 { .name = "flushnode", .target = separate_usage_target, .usage = flushnode_usage },
11202 { .name = "free", .target = separate_usage_target, .usage = free_usage },
11203 { .name = "freeze", .target = direct_usage_target, .usage = freeze_usage },
11204 { .name = "getanchors", .target = direct_usage_target, .usage = getanchors_usage },
11205 { .name = "getattribute", .target = separate_usage_target, .usage = getattribute_usage },
11206 { .name = "getattributelist", .target = direct_usage_target, .usage = getattributelist_usage },
11207 { .name = "getattributes", .target = direct_usage_target, .usage = getattributes_usage },
11208 { .name = "getboth", .target = direct_usage_target, .usage = getboth_usage },
11209 { .name = "getbottom", .target = direct_usage_target, .usage = getbottom_usage },
11210 { .name = "getbottomdelimiter", .target = direct_usage_target, .usage = getbottomdelimiter_usage },
11211 { .name = "getbox", .target = direct_usage_target, .usage = getbox_usage },
11212 { .name = "getcachestate", .target = general_usage_target, .usage = common_usage },
11213 { .name = "getchar", .target = direct_usage_target, .usage = getchar_usage },
11214 { .name = "getchardict", .target = direct_usage_target, .usage = getchardict_usage },
11215 { .name = "getcharspec", .target = direct_usage_target, .usage = getcharspec_usage },
11216 { .name = "getchoice", .target = direct_usage_target, .usage = getchoice_usage },
11217 { .name = "getclass", .target = direct_usage_target, .usage = getclass_usage },
11218 { .name = "getcontrol", .target = direct_usage_target, .usage = getcontrol_usage },
11219 { .name = "getcornerkerns", .target = direct_usage_target, .usage = getcornerkerns_usage },
11220 { .name = "getdata", .target = direct_usage_target, .usage = getdata_usage },
11221 { .name = "getdegree", .target = direct_usage_target, .usage = getdegree_usage },
11222 { .name = "getdelimiter", .target = direct_usage_target, .usage = getdelimiter_usage },
11223 { .name = "getdenominator", .target = direct_usage_target, .usage = getdenominator_usage },
11224 { .name = "getdepth", .target = direct_usage_target, .usage = getdepth_usage },
11225 { .name = "getdirection", .target = direct_usage_target, .usage = getdirection_usage },
11226 { .name = "getdisc", .target = direct_usage_target, .usage = getdisc_usage },
11227 { .name = "getdiscpart", .target = direct_usage_target, .usage = getdiscpart_usage },
11228 { .name = "getexcept", .target = direct_usage_target, .usage = getexcept_usage },
11229 { .name = "getexpansion", .target = direct_usage_target, .usage = getexpansion_usage },
11230 { .name = "getfam", .target = direct_usage_target, .usage = getfam_usage },
11231 { .name = "getfield", .target = separate_usage_target, .usage = getfield_usage },
11232 { .name = "getfont", .target = direct_usage_target, .usage = getfont_usage },
11233 { .name = "getgeometry", .target = direct_usage_target, .usage = getgeometry_usage },
11234 { .name = "getglue", .target = direct_usage_target, .usage = getglue_usage },
11235 { .name = "getglyphdata", .target = direct_usage_target, .usage = getglyphdata_usage },
11236 { .name = "getglyphdimensions", .target = direct_usage_target, .usage = getglyphdimensions_usage },
11237 { .name = "getheight", .target = direct_usage_target, .usage = getheight_usage },
11238 { .name = "getid", .target = direct_usage_target, .usage = getid_usage },
11239 { .name = "getidsubtype", .target = direct_usage_target, .usage = getidsubtype_usage },
11240 { .name = "getindex", .target = direct_usage_target, .usage = getindex_usage },
11241 { .name = "getinputfields", .target = direct_usage_target, .usage = getinputfields_usage },
11242 { .name = "getkern", .target = direct_usage_target, .usage = getkern_usage },
11243 { .name = "getkerndimension", .target = direct_usage_target, .usage = getkerndimension_usage },
11244 { .name = "getlanguage", .target = direct_usage_target, .usage = getlanguage_usage },
11245 { .name = "getleader", .target = direct_usage_target, .usage = getleader_usage },
11246 { .name = "getleftdelimiter", .target = direct_usage_target, .usage = getleftdelimiter_usage },
11247 { .name = "getlist", .target = direct_usage_target, .usage = getlist_usage },
11248 { .name = "getlistdimensions", .target = direct_usage_target, .usage = getlistdimensions_usage },
11249 { .name = "getmvllist", .target = direct_usage_target, .usage = getmvllist_usage },
11250 { .name = "getnext", .target = direct_usage_target, .usage = getnext_usage },
11251 { .name = "getnodes", .target = direct_usage_target, .usage = getnodes_usage },
11252 { .name = "getnormalizedline", .target = direct_usage_target, .usage = getnormalizedline_usage },
11253 { .name = "getnucleus", .target = direct_usage_target, .usage = getnucleus_usage },
11254 { .name = "getnumerator", .target = direct_usage_target, .usage = getnumerator_usage },
11255 { .name = "getoffsets", .target = direct_usage_target, .usage = getoffsets_usage },
11256 { .name = "getoptions", .target = direct_usage_target, .usage = getoptions_usage },
11257 { .name = "getorientation", .target = direct_usage_target, .usage = getorientation_usage },
11258 { .name = "getparstate", .target = direct_usage_target, .usage = getparstate_usage },
11259 { .name = "getpenalty", .target = direct_usage_target, .usage = getpenalty_usage },
11260 { .name = "getpost", .target = direct_usage_target, .usage = getpost_usage },
11261 { .name = "getpre", .target = direct_usage_target, .usage = getpre_usage },
11262 { .name = "getprev", .target = direct_usage_target, .usage = getprev_usage },
11263 { .name = "getprime", .target = direct_usage_target, .usage = getprime_usage },
11264 { .name = "getpropertiestable", .target = separate_usage_target, .usage = common_usage },
11265 { .name = "getproperty", .target = separate_usage_target, .usage = getproperty_usage },
11266 { .name = "getreplace", .target = direct_usage_target, .usage = getreplace_usage },
11267 { .name = "getrightdelimiter", .target = direct_usage_target, .usage = getrightdelimiter_usage },
11268 { .name = "getruledimensions", .target = direct_usage_target, .usage = getruledimensions_usage },
11269 { .name = "getscale", .target = direct_usage_target, .usage = getscale_usage },
11270 { .name = "getscales", .target = direct_usage_target, .usage = getscales_usage },
11271 { .name = "getscript", .target = direct_usage_target, .usage = getscript_usage },
11272 { .name = "getscripts", .target = direct_usage_target, .usage = getscripts_usage },
11273 { .name = "getshift", .target = direct_usage_target, .usage = getshift_usage },
11274 { .name = "getslant", .target = direct_usage_target, .usage = getslant_usage },
11275 { .name = "getspeciallist", .target = direct_usage_target, .usage = getspeciallist_usage },
11276 { .name = "getstate", .target = direct_usage_target, .usage = getstate_usage },
11277 { .name = "getsub", .target = direct_usage_target, .usage = getsub_usage },
11278 { .name = "getsubpre", .target = direct_usage_target, .usage = getsubpre_usage },
11279 { .name = "getsubtype", .target = direct_usage_target, .usage = getsubtype_usage },
11280 { .name = "getsup", .target = direct_usage_target, .usage = getsup_usage },
11281 { .name = "getsuppre", .target = direct_usage_target, .usage = getsuppre_usage },
11282 { .name = "gettop", .target = direct_usage_target, .usage = gettop_usage },
11283 { .name = "gettopdelimiter", .target = direct_usage_target, .usage = gettopdelimiter_usage },
11284 { .name = "gettotal", .target = direct_usage_target, .usage = gettotal_usage },
11285 { .name = "getweight", .target = direct_usage_target, .usage = getweight_usage },
11286 { .name = "getwhd", .target = direct_usage_target, .usage = getwhd_usage },
11287 { .name = "getwidth", .target = direct_usage_target, .usage = getwidth_usage },
11288 { .name = "getwordrange", .target = direct_usage_target, .usage = getwordrange_usage },
11289 { .name = "getxscale", .target = direct_usage_target, .usage = getxscale_usage },
11290 { .name = "getxyscales", .target = direct_usage_target, .usage = getxyscales_usage },
11291 { .name = "getyscale", .target = direct_usage_target, .usage = getyscale_usage },
11292 { .name = "gluetostring" , .target = hybrid_usage_target, .usage = gluetostring_usage },
11293 { .name = "hasattribute", .target = separate_usage_target, .usage = hasattribute_usage },
11294 { .name = "hasdimensions", .target = direct_usage_target, .usage = hasdimensions_usage },
11295 { .name = "hasdiscoption", .target = direct_usage_target, .usage = hasdiscoption_usage },
11296 { .name = "hasfield", .target = separate_usage_target, .usage = hasfield_usage },
11297 { .name = "hasgeometry", .target = direct_usage_target, .usage = hasgeometry_usage },
11298 { .name = "hasglyph", .target = direct_usage_target, .usage = hasglyph_usage },
11299 { .name = "hasglyphoption", .target = direct_usage_target, .usage = hasglyphoption_usage },
11300 { .name = "hpack", .target = direct_usage_target, .usage = hpack_usage },
11301 { .name = "hyphenating", .target = direct_usage_target, .usage = hyphenating_usage },
11302 { .name = "id", .target = general_usage_target, .usage = id_usage },
11303 { .name = "ignoremathskip", .target = direct_usage_target, .usage = ignoremathskip_usage },
11304 { .name = "insertafter", .target = separate_usage_target, .usage = insertafter_usage },
11305 { .name = "insertbefore", .target = separate_usage_target, .usage = insertbefore_usage },
11306 { .name = "instock", .target = userdata_usage_target, .usage = common_usage },
11307 { .name = "inuse", .target = userdata_usage_target, .usage = common_usage },
11308 { .name = "isboth", .target = direct_usage_target, .usage = isboth_usage },
11309 { .name = "ischar", .target = direct_usage_target, .usage = ischar_usage },
11310 { .name = "isdirect", .target = direct_usage_target, .usage = isdirect_usage },
11311 { .name = "isglyph", .target = direct_usage_target, .usage = isglyph_usage },
11312 { .name = "isitalicglyph", .target = direct_usage_target, .usage = isitalicglyph_usage },
11313 { .name = "isloop", .target = direct_usage_target, .usage = isloop_usage },
11314 { .name = "isnext", .target = direct_usage_target, .usage = isnext_usage },
11315 { .name = "isnextchar", .target = direct_usage_target, .usage = isnextchar_usage },
11316 { .name = "isnextglyph", .target = direct_usage_target, .usage = isnextglyph_usage },
11317 { .name = "isnode", .target = separate_usage_target, .usage = isnode_usage },
11318 { .name = "isprev", .target = direct_usage_target, .usage = isprev_usage },
11319 { .name = "isprevchar", .target = direct_usage_target, .usage = isnextchar_usage },
11320 { .name = "isprevglyph", .target = direct_usage_target, .usage = isprevglyph_usage },
11321 { .name = "issimilarglyph", .target = direct_usage_target, .usage = issimilarglyph_usage },
11322 { .name = "isspeciallist", .target = direct_usage_target, .usage = isspeciallist_usage },
11323 { .name = "isvalid", .target = direct_usage_target, .usage = isvalid_usage },
11324 { .name = "iszeroglue", .target = direct_usage_target, .usage = iszeroglue_usage },
11325 { .name = "kerning", .target = direct_usage_target, .usage = kerning_usage },
11326 { .name = "lastnode", .target = direct_usage_target, .usage = lastnode_usage },
11327 { .name = "length", .target = direct_usage_target, .usage = length_usage },
11328 { .name = "ligaturing", .target = direct_usage_target, .usage = ligaturing_usage },
11329 { .name = "migrate", .target = direct_usage_target, .usage = migrate_usage },
11330 { .name = "mlisttohlist", .target = direct_usage_target, .usage = mlisttohlist_usage },
11331 { .name = "naturalhsize", .target = direct_usage_target, .usage = naturalhsize_usage },
11332 { .name = "naturalwidth", .target = direct_usage_target, .usage = naturalwidth_usage },
11333 { .name = "new", .target = separate_usage_target, .usage = new_usage },
11334 { .name = "newcontinuationatom", .target = direct_usage_target, .usage = newcontinuationatom_usage },
11335 { .name = "newmathglyph", .target = direct_usage_target, .usage = newmathglyph_usage },
11336 { .name = "newtextglyph", .target = direct_usage_target, .usage = newtextglyph_usage },
11337 { .name = "patchattributes", .target = direct_usage_target, .usage = patchattributes_usage },
11338 { .name = "patchparshape", .target = direct_usage_target, .usage = patchparshape_usage },
11339 { .name = "prependbeforehead", .target = direct_usage_target, .usage = prependbeforehead_usage },
11340 { .name = "protectglyph", .target = direct_usage_target, .usage = protectglyph_usage },
11341 { .name = "protectglyphs", .target = direct_usage_target, .usage = protectglyphs_usage },
11342 { .name = "protectglyphsnone", .target = direct_usage_target, .usage = protectglyphsnone_usage },
11343 { .name = "protrusionskippable", .target = direct_usage_target, .usage = protrusionskippable_usage },
11344 { .name = "rangedimensions", .target = direct_usage_target, .usage = rangedimensions_usage },
11345 { .name = "remove", .target = separate_usage_target, .usage = remove_usage },
11346 { .name = "removefromlist", .target = direct_usage_target, .usage = removefromlist_usage },
11347 { .name = "repack", .target = direct_usage_target, .usage = repack_usage },
11348 { .name = "reverse", .target = direct_usage_target, .usage = reverse_usage },
11349 { .name = "serialized", .target = separate_usage_target, .usage = serialized_usage },
11350 { .name = "setanchors", .target = direct_usage_target, .usage = setanchors_usage },
11351 { .name = "setattribute", .target = separate_usage_target, .usage = setattribute_usage },
11352 { .name = "setattributelist", .target = direct_usage_target, .usage = setattributelist_usage },
11353 { .name = "setattributes", .target = direct_usage_target, .usage = setattributes_usage },
11354 { .name = "setboth", .target = direct_usage_target, .usage = setboth_usage },
11355 { .name = "setbottom", .target = direct_usage_target, .usage = setbottom_usage },
11356 { .name = "setbottomdelimiter", .target = direct_usage_target, .usage = setbottomdelimiter_usage },
11357 { .name = "setbox", .target = direct_usage_target, .usage = setbox_usage },
11358 { .name = "setchar", .target = direct_usage_target, .usage = setchar_usage },
11359 { .name = "setchardict", .target = direct_usage_target, .usage = setchardict_usage },
11360 { .name = "setcharspec", .target = direct_usage_target, .usage = setcharspec_usage },
11361 { .name = "setchoice", .target = direct_usage_target, .usage = setchoice_usage },
11362 { .name = "setclass", .target = direct_usage_target, .usage = setclass_usage },
11363 { .name = "setcontrol", .target = direct_usage_target, .usage = setcontrol_usage },
11364 { .name = "setdata", .target = direct_usage_target, .usage = setdata_usage },
11365 { .name = "setdegree", .target = direct_usage_target, .usage = setdegree_usage },
11366 { .name = "setdelimiter", .target = direct_usage_target, .usage = setdelimiter_usage },
11367 { .name = "setdenominator", .target = direct_usage_target, .usage = setdenominator_usage },
11368 { .name = "setdepth", .target = direct_usage_target, .usage = setdepth_usage },
11369 { .name = "setdirection", .target = direct_usage_target, .usage = setdirection_usage },
11370 { .name = "setdisc", .target = direct_usage_target, .usage = setdisc_usage },
11371 { .name = "setdiscpart", .target = direct_usage_target, .usage = setdiscpart_usage },
11372 { .name = "setexcept", .target = direct_usage_target, .usage = setexcept_usage },
11373 { .name = "setexpansion", .target = direct_usage_target, .usage = setexpansion_usage },
11374 { .name = "setfam", .target = direct_usage_target, .usage = setfam_usage },
11375 { .name = "setfield", .target = separate_usage_target, .usage = setfield_usage },
11376 { .name = "setfont", .target = direct_usage_target, .usage = setfont_usage },
11377 { .name = "setgeometry", .target = direct_usage_target, .usage = setgeometry_usage },
11378 { .name = "setglue", .target = direct_usage_target, .usage = setglue_usage },
11379 { .name = "setglyphdata", .target = direct_usage_target, .usage = setglyphdata_usage },
11380 { .name = "setheight", .target = direct_usage_target, .usage = setheight_usage },
11381 { .name = "setindex", .target = direct_usage_target, .usage = setindex_usage },
11382 { .name = "setinputfields", .target = direct_usage_target, .usage = setinputfields_usage },
11383 { .name = "setkern", .target = direct_usage_target, .usage = setkern_usage },
11384 { .name = "setlanguage", .target = direct_usage_target, .usage = setlanguage_usage },
11385 { .name = "setleader", .target = direct_usage_target, .usage = setleader_usage },
11386 { .name = "setleftdelimiter", .target = direct_usage_target, .usage = setleftdelimiter_usage },
11387 { .name = "setlink", .target = direct_usage_target, .usage = setlink_usage },
11388 { .name = "setlist", .target = direct_usage_target, .usage = setlist_usage },
11389 { .name = "setnext", .target = direct_usage_target, .usage = setnext_usage },
11390 { .name = "setnucleus", .target = direct_usage_target, .usage = setnucleus_usage },
11391 { .name = "setnumerator", .target = direct_usage_target, .usage = setnumerator_usage },
11392 { .name = "setoffsets", .target = direct_usage_target, .usage = setoffsets_usage },
11393 { .name = "setoptions", .target = direct_usage_target, .usage = setoptions_usage },
11394 { .name = "setorientation", .target = direct_usage_target, .usage = setorientation_usage },
11395 { .name = "setpenalty", .target = direct_usage_target, .usage = setpenalty_usage },
11396 { .name = "setpost", .target = direct_usage_target, .usage = setpost_usage },
11397 { .name = "setpre", .target = direct_usage_target, .usage = setpre_usage },
11398 { .name = "setprev", .target = direct_usage_target, .usage = setprev_usage },
11399 { .name = "setprime", .target = direct_usage_target, .usage = setprime_usage },
11400 { .name = "setproperty", .target = separate_usage_target, .usage = setproperty_usage },
11401 { .name = "setreplace", .target = direct_usage_target, .usage = setreplace_usage },
11402 { .name = "setrightdelimiter", .target = direct_usage_target, .usage = setrightdelimiter_usage },
11403 { .name = "setruledimensions", .target = direct_usage_target, .usage = setruledimensions_usage },
11404 { .name = "setruledimensions", .target = direct_usage_target, .usage = setruledimensions_usage },
11405 { .name = "setscale", .target = direct_usage_target, .usage = setscale_usage },
11406 { .name = "setscales", .target = direct_usage_target, .usage = setscales_usage },
11407 { .name = "setscript", .target = direct_usage_target, .usage = setscript_usage },
11408 { .name = "setscripts", .target = direct_usage_target, .usage = setscripts_usage },
11409 { .name = "setshift", .target = direct_usage_target, .usage = setshift_usage },
11410 { .name = "setslant", .target = direct_usage_target, .usage = setslant_usage },
11411 { .name = "setspeciallist", .target = direct_usage_target, .usage = setspeciallist_usage },
11412 { .name = "setsplit", .target = direct_usage_target, .usage = setsplit_usage },
11413 { .name = "setstate", .target = direct_usage_target, .usage = setstate_usage },
11414 { .name = "setsub", .target = direct_usage_target, .usage = setsub_usage },
11415 { .name = "setsubpre", .target = direct_usage_target, .usage = setsubpre_usage },
11416 { .name = "setsubtype", .target = direct_usage_target, .usage = setsubtype_usage },
11417 { .name = "setsup", .target = direct_usage_target, .usage = setsup_usage },
11418 { .name = "setsuppre", .target = direct_usage_target, .usage = setsuppre_usage },
11419 { .name = "settop", .target = direct_usage_target, .usage = settop_usage },
11420 { .name = "settopdelimiter", .target = direct_usage_target, .usage = settopdelimiter_usage },
11421 { .name = "settotal", .target = direct_usage_target, .usage = settotal_usage },
11422 { .name = "setweight", .target = direct_usage_target, .usage = setweight_usage },
11423 { .name = "setwhd", .target = direct_usage_target, .usage = setwhd_usage },
11424 { .name = "setwidth", .target = direct_usage_target, .usage = setwidth_usage },
11425 { .name = "setxyscales", .target = direct_usage_target, .usage = setxyscales_usage },
11426 { .name = "show", .target = separate_usage_target, .usage = show_usage },
11427 { .name = "showlist", .target = direct_usage_target, .usage = showlist_usage },
11428 { .name = "size", .target = direct_usage_target, .usage = size_usage },
11429 { .name = "size", .target = general_usage_target, .usage = common_usage },
11430 { .name = "slide", .target = direct_usage_target, .usage = slide_usage },
11431 { .name = "softenhyphens", .target = direct_usage_target, .usage = softenhyphens_usage },
11432 { .name = "startofpar", .target = direct_usage_target, .usage = startofpar_usage },
11433 { .name = "subtypes", .target = general_usage_target, .usage = common_usage },
11434 { .name = "tail", .target = separate_usage_target, .usage = tail_usage },
11435 { .name = "todirect", .target = userdata_usage_target, .usage = todirect_usage },
11436 { .name = "tonode", .target = direct_usage_target, .usage = tonode_usage },
11437 { .name = "tostring", .target = separate_usage_target, .usage = common_usage },
11438 { .name = "tovaliddirect", .target = direct_usage_target, .usage = tovaliddirect_usage },
11439 { .name = "traverse", .target = separate_usage_target, .usage = traverse_usage },
11440 { .name = "traversechar", .target = direct_usage_target, .usage = traversechar_usage },
11441 { .name = "traversecontent", .target = direct_usage_target, .usage = traversecontent_usage },
11442 { .name = "traverseglyph", .target = direct_usage_target, .usage = traverseglyph_usage },
11443 { .name = "traverseid", .target = separate_usage_target, .usage = traverseid_usage },
11444 { .name = "traverseitalic", .target = direct_usage_target, .usage = traverseitalic_usage },
11445 { .name = "traverseleader", .target = direct_usage_target, .usage = traverseleader_usage },
11446 { .name = "traverselist", .target = direct_usage_target, .usage = traverselist_usage },
11447 { .name = "type", .target = hybrid_usage_target, .usage = type_usage },
11448 { .name = "types", .target = general_usage_target, .usage = common_usage },
11449 { .name = "unprotectglyph", .target = direct_usage_target, .usage = unprotectglyph_usage },
11450 { .name = "unprotectglyphs", .target = direct_usage_target, .usage = unprotectglyphs_usage },
11451 { .name = "unprotectglyphsnone", .target = direct_usage_target, .usage = unprotectglyphsnone_usage },
11452 { .name = "unsetattribute", .target = separate_usage_target, .usage = unsetattribute_usage },
11453 { .name = "unsetattributes", .target = direct_usage_target, .usage = unsetattributes_usage },
11454 { .name = "usedlist", .target = separate_usage_target, .usage = usedlist_usage },
11455 { .name = "usesfont", .target = direct_usage_target, .usage = usesfont_usage },
11456 { .name = "validpar", .target = direct_usage_target, .usage = validpar_usage },
11457 { .name = "verticalbreak", .target = direct_usage_target, .usage = verticalbreak_usage },
11458 { .name = "vpack", .target = direct_usage_target, .usage = vpack_usage },
11459 { .name = "write", .target = separate_usage_target, .usage = write_usage },
11460 { .name = "xscaled", .target = direct_usage_target, .usage = xscaled_usage },
11461 { .name = "yscaled", .target = direct_usage_target, .usage = yscaled_usage },
11462
11463 { .name = "vbalance", .target = direct_usage_target, .usage = vbalance_usage },
11464
11465 { .name = "updatetopmarks", .target = no_usage_target, .usage = updatetopmarks_usage },
11466 { .name = "updatemarks", .target = direct_usage_target, .usage = updatemarks_usage },
11467 { .name = "updatefirstmarks", .target = no_usage_target, .usage = updatefirstmarks_usage },
11468 { .name = "updatefirstandbotmark", .target = direct_usage_target, .usage = updatefirstandbotmark_usage },
11469
11470 { .name = NULL, .target = no_usage_target, .usage = 0 },
11471} ;
11472
11473static int nodelib_direct_hasusage(lua_State *L)
11474{
11475 const char *str = lua_tostring(L, 1);
11476 if (str) {
11477 int target = lmt_optinteger(L, 2, 0);
11478 for (int i = 0; usage_data[i].name != NULL; i++) {
11479 if ((! target || usage_data[i].target == target) && ! strcmp(usage_data[i].name, str)) {
11480 lua_pushboolean(L, 1);
11481 return 1;
11482 }
11483 }
11484 }
11485 lua_pushboolean(L, 0);
11486 return 1;
11487}
11488
11489static int nodelib_direct_getusage(lua_State *L)
11490{
11491 switch (lua_type(L, 1)) {
11492 case LUA_TSTRING:
11493 {
11494 const char *str = lua_tostring(L, 1);
11495 if (str) {
11496 int target = lmt_optinteger(L, 2, 0);
11497 for (int i = 0; usage_data[i].name != NULL; i++) {
11498 if ((! target || usage_data[i].target == target) && ! strcmp(usage_data[i].name, str)) {
11499 if (usage_data[i].usage & common_usage) {
11500 lua_pushboolean(L, 1);
11501 } else {
11502 int n = 0;
11503 lua_newtable(L);
11504 for (int id = 0; id <= passive_node; id++) {
11505 lua_Integer bit = (lua_Integer) 1 << (id + 1);
11506 if (usage_data[i].usage & bit) {
11507 lua_pushinteger(L, id);
11508 lua_rawseti(L, -2, ++n);
11509 }
11510 }
11511 }
11512 return 1;
11513 }
11514 }
11515 }
11516 }
11517 break;
11518 case LUA_TNUMBER:
11519 {
11520 int id = (int) lua_tointeger(L, 1);
11521 if (id >= 0 && id <= passive_node) {
11522 int target = lmt_optinteger(L, 2, 0);
11523 lua_Integer bit = (lua_Integer) 1 << (id + 1);
11524 int n = 0;
11525 lua_newtable(L);
11526 for (int i = 0; usage_data[i].name != NULL; i++) {
11527 if ((! target || usage_data[i].target == target) && ((usage_data[i].usage & bit) || (usage_data[i].usage & common_usage))) {
11528 lua_pushstring(L, usage_data[i].name);
11529 lua_rawseti(L, -2, ++n);
11530 }
11531 }
11532 return 1;
11533 }
11534 }
11535 break;
11536 }
11537 return 0;
11538}
11539
11540
11541
11542static const struct luaL_Reg nodelib_direct_function_list[] = {
11543
11544 { "addmargins", nodelib_direct_addmargins },
11545 { "addxoffset", nodelib_direct_addxoffset },
11546 { "addxymargins", nodelib_direct_addxymargins },
11547 { "addyoffset", nodelib_direct_addyoffset },
11548 { "appendaftertail", nodelib_direct_appendaftertail },
11549 { "beginofmath", nodelib_direct_beginofmath },
11550 { "checkdiscretionaries", nodelib_direct_checkdiscretionaries },
11551 { "checkdiscretionary", nodelib_direct_checkdiscretionary },
11552 { "collapsing", nodelib_direct_collapsing },
11553 { "copy", nodelib_direct_copy },
11554 { "copylist", nodelib_direct_copylist },
11555 { "copyonly", nodelib_direct_copyonly },
11556 { "count", nodelib_direct_count },
11557 { "currentattributes", nodelib_direct_currentattributes },
11558 { "dimensions", nodelib_direct_dimensions },
11559 { "effectiveglue", nodelib_direct_effectiveglue },
11560 { "endofmath", nodelib_direct_endofmath },
11561 { "exchange", nodelib_direct_exchange },
11562 { "findattribute", nodelib_direct_findattribute },
11563 { "findattributerange", nodelib_direct_findattributerange },
11564 { "findnode", nodelib_direct_findnode },
11565 { "firstchar", nodelib_direct_firstchar },
11566 { "firstglyph", nodelib_direct_firstglyph },
11567 { "firstglyphnode", nodelib_direct_firstglyphnode },
11568 { "firstitalicglyph", nodelib_direct_firstitalicglyph },
11569 { "flattendiscretionaries", nodelib_direct_flattendiscretionaries },
11570 { "flattenleaders", nodelib_direct_flattenleaders },
11571 { "flushlist", nodelib_direct_flushlist },
11572 { "flushnode", nodelib_direct_flushnode },
11573 { "free", nodelib_direct_free },
11574 { "freeze", nodelib_direct_freeze },
11575 { "getanchors", nodelib_direct_getanchors },
11576 { "getattribute", nodelib_direct_getattribute },
11577 { "getattributelist", nodelib_direct_getattributelist },
11578 { "getattributes", nodelib_direct_getattributes },
11579 { "getboth", nodelib_direct_getboth },
11580 { "getbottom", nodelib_direct_getbottom },
11581 { "getbottomdelimiter", nodelib_direct_getbottomdelimiter },
11582 { "getbox", nodelib_direct_getbox },
11583 { "getchar", nodelib_direct_getchar },
11584 { "getchardict", nodelib_direct_getchardict },
11585 { "getcharspec", nodelib_direct_getcharspec },
11586 { "getchoice", nodelib_direct_getchoice },
11587 { "getclass", nodelib_direct_getclass },
11588 { "getcontrol", nodelib_direct_getcontrol },
11589 { "getcornerkerns", nodelib_direct_getcornerkerns },
11590 { "getdata", nodelib_direct_getdata },
11591 { "getdegree", nodelib_direct_getdegree },
11592 { "getdelimiter", nodelib_direct_getdelimiter },
11593 { "getdenominator", nodelib_direct_getdenominator },
11594 { "getdepth", nodelib_direct_getdepth },
11595 { "getdirection", nodelib_direct_getdirection },
11596 { "getdisc", nodelib_direct_getdisc },
11597 { "getdiscpart", nodelib_direct_getdiscpart },
11598 { "getexcept", nodelib_direct_getexcept },
11599 { "getexpansion", nodelib_direct_getexpansion },
11600 { "getfam", nodelib_direct_getfam },
11601 { "getfield", nodelib_direct_getfield },
11602 { "getfont", nodelib_direct_getfont },
11603 { "getgeometry", nodelib_direct_getgeometry },
11604 { "getglue", nodelib_direct_getglue },
11605 { "getglyphdata", nodelib_direct_getglyphdata },
11606 { "getglyphdimensions", nodelib_direct_getglyphdimensions },
11607 { "getheight", nodelib_direct_getheight },
11608 { "getid", nodelib_direct_getid },
11609 { "getidsubtype", nodelib_direct_getidsubtype },
11610 { "getindex", nodelib_direct_getindex },
11611 { "getinputfields", nodelib_direct_getinputfields },
11612 { "getkern", nodelib_direct_getkern },
11613 { "getkerndimension", nodelib_direct_getkerndimension },
11614 { "getlanguage", nodelib_direct_getlanguage },
11615 { "getleader", nodelib_direct_getleader },
11616 { "getleftdelimiter", nodelib_direct_getleftdelimiter },
11617 { "getlist", nodelib_direct_getlist },
11618 { "getlistdimensions", nodelib_direct_getlistdimensions },
11619 { "getnext", nodelib_direct_getnext },
11620 { "getmvllist", nodelib_direct_getmvllist },
11621 { "getnodes", nodelib_direct_getnodes },
11622 { "getnormalizedline", nodelib_direct_getnormalizedline },
11623 { "getnucleus", nodelib_direct_getnucleus },
11624 { "getnumerator", nodelib_direct_getnumerator },
11625 { "getoffsets", nodelib_direct_getoffsets },
11626 { "getoptions", nodelib_direct_getoptions },
11627 { "getorientation", nodelib_direct_getorientation },
11628 { "getparstate", nodelib_direct_getparstate },
11629 { "getpenalty", nodelib_direct_getpenalty },
11630 { "getpost", nodelib_direct_getpost },
11631 { "getpre", nodelib_direct_getpre },
11632 { "getprev", nodelib_direct_getprev },
11633 { "getprime", nodelib_direct_getprime },
11634 { "getpropertiestable", nodelib_direct_getpropertiestable },
11635 { "getproperty", nodelib_direct_getproperty },
11636 { "getreplace", nodelib_direct_getreplace },
11637 { "getrightdelimiter", nodelib_direct_getrightdelimiter },
11638 { "getruledimensions", nodelib_direct_getruledimensions },
11639 { "getscale", nodelib_direct_getscale },
11640 { "getscales", nodelib_direct_getscales },
11641 { "getscript", nodelib_direct_getscript },
11642 { "getscripts", nodelib_direct_getscripts },
11643 { "getshift", nodelib_direct_getshift },
11644 { "getslant", nodelib_direct_getslant },
11645 { "getspeciallist", nodelib_direct_getspeciallist },
11646 { "getstate", nodelib_direct_getstate },
11647 { "getsub", nodelib_direct_getsub },
11648 { "getsubpre", nodelib_direct_getsubpre },
11649 { "getsubtype", nodelib_direct_getsubtype },
11650 { "getsup", nodelib_direct_getsup },
11651 { "getsuppre", nodelib_direct_getsuppre },
11652 { "gettop", nodelib_direct_gettop },
11653 { "gettopdelimiter", nodelib_direct_gettopdelimiter },
11654 { "gettotal" , nodelib_direct_gettotal },
11655 { "getusage", nodelib_direct_getusage },
11656 { "getusedattributes", nodelib_direct_getusedattributes },
11657 { "getweight", nodelib_direct_getweight },
11658 { "getwhd", nodelib_direct_getwhd },
11659 { "getwidth", nodelib_direct_getwidth },
11660 { "getwordrange", nodelib_direct_getwordrange },
11661 { "getxscale", nodelib_direct_getxscale },
11662 { "getxyscales", nodelib_direct_getxyscales },
11663 { "getyscale", nodelib_direct_getyscale },
11664 { "hasattribute", nodelib_direct_hasattribute },
11665 { "hasdimensions", nodelib_direct_hasdimensions },
11666 { "hasdiscoption", nodelib_direct_hasdiscoption },
11667 { "hasfield", nodelib_direct_hasfield },
11668 { "hasgeometry", nodelib_direct_hasgeometry },
11669 { "hasglyph", nodelib_direct_hasglyph },
11670 { "hasglyphoption", nodelib_direct_hasglyphoption },
11671 { "hasusage", nodelib_direct_hasusage },
11672 { "hpack", nodelib_direct_hpack },
11673 { "hyphenating", nodelib_direct_hyphenating },
11674 { "ignoremathskip", nodelib_direct_ignoremathskip },
11675 { "insertafter", nodelib_direct_insertafter },
11676 { "insertbefore", nodelib_direct_insertbefore },
11677 { "isboth", nodelib_direct_isboth },
11678 { "ischar", nodelib_direct_ischar },
11679 { "isdirect", nodelib_direct_isdirect },
11680 { "isglyph", nodelib_direct_isglyph },
11681 { "isitalicglyph", nodelib_direct_isitalicglyph },
11682 { "isloop", nodelib_direct_isloop },
11683 { "isnext", nodelib_direct_isnext },
11684 { "isnextchar", nodelib_direct_isnextchar },
11685 { "isnextglyph", nodelib_direct_isnextglyph },
11686 { "isnode", nodelib_direct_isnode },
11687 { "isprev", nodelib_direct_isprev },
11688 { "isprevchar", nodelib_direct_isprevchar },
11689 { "isprevglyph", nodelib_direct_isprevglyph },
11690 { "issimilarglyph", nodelib_direct_issimilarglyph },
11691 { "isspeciallist", nodelib_direct_isspeciallist },
11692 { "isvalid", nodelib_direct_isvalid },
11693 { "iszeroglue", nodelib_direct_iszeroglue },
11694 { "kerning", nodelib_direct_kerning },
11695 { "lastnode", nodelib_direct_lastnode },
11696 { "length", nodelib_direct_length },
11697 { "ligaturing", nodelib_direct_ligaturing },
11698 { "makeextensible", nodelib_direct_makeextensible },
11699 { "migrate", nodelib_direct_migrate },
11700 { "mlisttohlist", nodelib_direct_mlisttohlist },
11701 { "naturalhsize", nodelib_direct_naturalhsize },
11702 { "naturalwidth", nodelib_direct_naturalwidth },
11703 { "new", nodelib_direct_new },
11704 { "newcontinuationatom", nodelib_direct_newcontinuationatom },
11705 { "newmathglyph", nodelib_direct_newmathglyph },
11706 { "newtextglyph", nodelib_direct_newtextglyph },
11707 { "patchattributes", nodelib_direct_patchattributes },
11708 { "patchparshape", nodelib_direct_patchparshape },
11709 { "prependbeforehead", nodelib_direct_prependbeforehead },
11710 { "protectglyph", nodelib_direct_protectglyph },
11711 { "protectglyphs", nodelib_direct_protectglyphs },
11712 { "protectglyphsnone", nodelib_direct_protectglyphsnone },
11713 { "protrusionskippable", nodelib_direct_protrusionskipable },
11714 { "rangedimensions", nodelib_direct_rangedimensions },
11715 { "remove", nodelib_direct_remove },
11716 { "removefromlist", nodelib_direct_removefromlist },
11717 { "repack", nodelib_direct_repack },
11718 { "reverse", nodelib_direct_reverse },
11719 { "serialized", nodelib_direct_serialized },
11720 { "setanchors", nodelib_direct_setanchors },
11721 { "setattribute", nodelib_direct_setattribute },
11722 { "setattributelist", nodelib_direct_setattributelist },
11723 { "setattributes", nodelib_direct_setattributes },
11724 { "setboth", nodelib_direct_setboth },
11725 { "setbottom", nodelib_direct_setbottom },
11726 { "setbottomdelimiter", nodelib_direct_setbottomdelimiter },
11727 { "setbox", nodelib_direct_setbox },
11728 { "setchar", nodelib_direct_setchar },
11729 { "setchardict", nodelib_direct_setchardict },
11730 { "setchoice", nodelib_direct_setchoice },
11731 { "setclass", nodelib_direct_setclass },
11732 { "setcontrol", nodelib_direct_setcontrol },
11733 { "setdata", nodelib_direct_setdata },
11734 { "setdegree", nodelib_direct_setdegree },
11735 { "setdelimiter", nodelib_direct_setdelimiter },
11736 { "setdenominator", nodelib_direct_setdenominator },
11737 { "setdepth", nodelib_direct_setdepth },
11738 { "setdirection", nodelib_direct_setdirection },
11739 { "setdisc", nodelib_direct_setdisc },
11740 { "setdiscpart", nodelib_direct_setdiscpart },
11741 { "setexcept", nodelib_direct_setexcept },
11742 { "setexpansion", nodelib_direct_setexpansion },
11743 { "setfam", nodelib_direct_setfam },
11744 { "setfield", nodelib_direct_setfield },
11745 { "setfont", nodelib_direct_setfont },
11746 { "setgeometry", nodelib_direct_setgeometry },
11747 { "setglue", nodelib_direct_setglue },
11748 { "setglyphdata", nodelib_direct_setglyphdata },
11749 { "setheight", nodelib_direct_setheight },
11750 { "setindex", nodelib_direct_setindex },
11751 { "setinputfields", nodelib_direct_setinputfields },
11752 { "setkern", nodelib_direct_setkern },
11753 { "setlanguage", nodelib_direct_setlanguage },
11754 { "setleader", nodelib_direct_setleader },
11755 { "setleftdelimiter", nodelib_direct_setleftdelimiter },
11756 { "setlink", nodelib_direct_setlink },
11757 { "setlist", nodelib_direct_setlist },
11758 { "setnext", nodelib_direct_setnext },
11759 { "setnucleus", nodelib_direct_setnucleus },
11760 { "setnumerator", nodelib_direct_setnumerator },
11761 { "setoffsets", nodelib_direct_setoffsets },
11762 { "setoptions", nodelib_direct_setoptions },
11763 { "setorientation", nodelib_direct_setorientation },
11764 { "setpenalty", nodelib_direct_setpenalty },
11765 { "setpost", nodelib_direct_setpost },
11766 { "setpre", nodelib_direct_setpre },
11767 { "setprev", nodelib_direct_setprev },
11768 { "setprime" , nodelib_direct_setprime },
11769 { "setproperty", nodelib_direct_setproperty },
11770 { "setreplace", nodelib_direct_setreplace },
11771 { "setrightdelimiter", nodelib_direct_setrightdelimiter },
11772 { "setruledimensions", nodelib_direct_setruledimensions },
11773 { "setscale", nodelib_direct_setscale },
11774 { "setscales", nodelib_direct_setscales },
11775 { "setscript", nodelib_direct_setscript },
11776 { "setscripts", nodelib_direct_setscripts },
11777 { "setshift", nodelib_direct_setshift },
11778 { "setslant", nodelib_direct_setslant },
11779 { "setspeciallist", nodelib_direct_setspeciallist },
11780 { "setsplit", nodelib_direct_setsplit },
11781 { "setstate", nodelib_direct_setstate },
11782 { "setsub", nodelib_direct_setsub },
11783 { "setsubpre", nodelib_direct_setsubpre },
11784 { "setsubtype", nodelib_direct_setsubtype },
11785 { "setsup", nodelib_direct_setsup },
11786 { "setsuppre", nodelib_direct_setsuppre },
11787 { "settop" , nodelib_direct_settop },
11788 { "settopdelimiter", nodelib_direct_settopdelimiter },
11789 { "settotal" , nodelib_direct_settotal },
11790 { "setweight", nodelib_direct_setweight },
11791 { "setwhd", nodelib_direct_setwhd },
11792 { "setwidth", nodelib_direct_setwidth },
11793 { "show", nodelib_direct_show },
11794 { "slide", nodelib_direct_slide },
11795 { "softenhyphens", nodelib_direct_softenhyphens },
11796 { "startofpar", nodelib_direct_startofpar },
11797 { "tail", nodelib_direct_tail },
11798 { "tostring", nodelib_direct_tostring },
11799 { "tovaliddirect", nodelib_direct_tovaliddirect },
11800 { "traverse", nodelib_direct_traverse },
11801 { "traversechar", nodelib_direct_traversechar },
11802 { "traversecontent", nodelib_direct_traversecontent },
11803 { "traverseglyph", nodelib_direct_traverseglyph },
11804 { "traverseid", nodelib_direct_traverseid },
11805 { "traverseitalic", nodelib_direct_traverseitalic },
11806 { "traverseleader", nodelib_direct_traverseleader },
11807 { "traverselist", nodelib_direct_traverselist },
11808 { "unprotectglyph", nodelib_direct_unprotectglyph },
11809 { "unprotectglyphs", nodelib_direct_unprotectglyphs },
11810 { "unsetattribute", nodelib_direct_unsetattribute },
11811 { "unsetattributes", nodelib_direct_unsetattributes },
11812 { "usedlist", nodelib_direct_usedlist },
11813 { "usesfont", nodelib_direct_usesfont },
11814 { "verticalbreak", nodelib_direct_verticalbreak },
11815 { "vpack", nodelib_direct_vpack },
11816 { "write", nodelib_direct_write },
11817 { "xscaled", nodelib_direct_xscaled },
11818 { "yscaled", nodelib_direct_yscaled },
11819
11820 { "vbalance", nodelib_direct_vbalance },
11821
11822 { "updatetopmarks", nodelib_direct_updatetopmarks },
11823 { "updatefirstmarks", nodelib_direct_updatefirstmarks },
11824 { "updatefirstandbotmark", nodelib_direct_updatefirstandbotmark },
11825 { "updatemarks", nodelib_direct_updatemarks },
11826
11827
11828
11829 { "gluetostring", nodelib_hybrid_gluetostring },
11830 { "type", nodelib_hybrid_type },
11831
11832 { "fields", nodelib_shared_fields },
11833 { "getcachestate", nodelib_shared_getcachestate },
11834 { "id", nodelib_shared_id },
11835 { "size", nodelib_shared_size },
11836 { "subtypes", nodelib_shared_subtypes },
11837 { "todirect", nodelib_shared_todirect },
11838 { "tonode", nodelib_shared_tonode },
11839 { "types", nodelib_shared_types },
11840
11841
11842 { "setfielderror", nodelib_shared_setfielderror },
11843 { "getfielderror", nodelib_shared_getfielderror },
11844
11845 { NULL, NULL },
11846
11847};
11848
11849
11850
11851static const struct luaL_Reg nodelib_function_list[] = {
11852
11853 { "copy", nodelib_userdata_copy },
11854 { "copylist", nodelib_userdata_copylist },
11855 { "currentattributes", nodelib_userdata_currentattributes },
11856 { "flushlist", nodelib_userdata_flushlist },
11857 { "flushnode", nodelib_userdata_flushnode },
11858 { "free", nodelib_userdata_free },
11859 { "getattribute", nodelib_userdata_getattribute },
11860 { "getfield", nodelib_userdata_getfield },
11861 { "getpropertiestable", nodelib_userdata_getpropertiestable },
11862 { "getproperty", nodelib_userdata_getproperty },
11863 { "hasattribute", nodelib_userdata_hasattribute },
11864 { "hasfield", nodelib_userdata_hasfield },
11865 { "insertafter", nodelib_userdata_insertafter },
11866 { "insertbefore", nodelib_userdata_insertbefore },
11867 { "instock", nodelib_userdata_instock },
11868 { "inuse", nodelib_userdata_inuse },
11869 { "isnode", nodelib_userdata_isnode },
11870 { "new", nodelib_userdata_new },
11871 { "remove", nodelib_userdata_remove },
11872 { "serialized", nodelib_userdata_serialized },
11873 { "setattribute", nodelib_userdata_setattribute },
11874 { "setfield", nodelib_userdata_setfield },
11875 { "setproperty", nodelib_userdata_setproperty },
11876 { "show", nodelib_userdata_show },
11877 { "tail", nodelib_userdata_tail },
11878 { "tostring", nodelib_userdata_tostring },
11879 { "traverse", nodelib_userdata_traverse },
11880 { "traverseid", nodelib_userdata_traverse_id },
11881 { "unsetattribute", nodelib_userdata_unsetattribute },
11882 { "usedlist", nodelib_userdata_usedlist },
11883 { "write", nodelib_userdata_write },
11884
11885
11886 { "gluetostring", nodelib_hybrid_gluetostring },
11887 { "type", nodelib_hybrid_type },
11888
11889 { "fields", nodelib_shared_fields },
11890 { "getcachestate", nodelib_shared_getcachestate },
11891 { "id", nodelib_shared_id },
11892 { "size", nodelib_shared_size },
11893 { "subtypes", nodelib_shared_subtypes },
11894 { "todirect", nodelib_shared_todirect },
11895 { "tonode", nodelib_shared_tonode },
11896 { "types", nodelib_shared_types },
11897
11898
11899 { "setfielderror", nodelib_shared_setfielderror },
11900 { "getfielderror", nodelib_shared_getfielderror },
11901
11902 { NULL, NULL },
11903
11904};
11905
11906static const struct luaL_Reg nodelib_metatable[] = {
11907 { "__index", nodelib_userdata_index },
11908 { "__newindex", nodelib_userdata_newindex },
11909 { "__tostring", nodelib_userdata_tostring },
11910 { "__eq", nodelib_userdata_equal },
11911 { NULL, NULL },
11912};
11913
11914int luaopen_node(lua_State *L)
11915{
11916
11917 luaL_newmetatable(L, NODE_METATABLE_INSTANCE);
11918
11919 luaL_setfuncs(L, nodelib_metatable, 0);
11920 lua_newtable(L);
11921 luaL_setfuncs(L, nodelib_function_list, 0);
11922
11923 lua_pushstring(L, lua_key(direct));
11924 lua_newtable(L);
11925 luaL_setfuncs(L, nodelib_direct_function_list, 0);
11926 lua_rawset(L, -3);
11927 return 1;
11928}
11929
11930void lmt_node_list_to_lua(lua_State *L, halfword n)
11931{
11932 lmt_push_node_fast(L, n);
11933}
11934
11935halfword lmt_node_list_from_lua(lua_State *L, int n)
11936{
11937 if (lua_isnil(L, n)) {
11938 return null;
11939 } else {
11940 halfword list = lmt_check_isnode(L, n);
11941 return list ? list : null;
11942 }
11943}
11944
11945
11952
11953void lmt_begin_paragraph_callback(
11954 int invmode,
11955 int *indented,
11956 int context
11957)
11958{
11959 int callback_id = lmt_callback_defined(begin_paragraph_callback);
11960 if (callback_id > 0) {
11961 lua_State *L = lmt_lua_state.lua_instance;
11962 int top = 0;
11963 if (lmt_callback_okay(L, callback_id, &top)) {
11964 int i;
11965 lua_pushboolean(L, invmode);
11966 lua_pushboolean(L, *indented);
11967 lmt_push_par_trigger(L, context);
11968 i = lmt_callback_call(L, 3, 1, top);
11969
11970 if (i) {
11971 lmt_callback_error(L, top, i);
11972 }
11973 else {
11974 *indented = lua_toboolean(L, -1);
11975 lmt_callback_wrapup(L, top);
11976 }
11977 }
11978 }
11979}
11980
11981void lmt_paragraph_context_callback(
11982 int context,
11983 int *ignore
11984)
11985{
11986 int callback_id = lmt_callback_defined(paragraph_context_callback);
11987 if (callback_id > 0) {
11988 lua_State *L = lmt_lua_state.lua_instance;
11989 int top = 0;
11990 if (lmt_callback_okay(L, callback_id, &top)) {
11991 int i;
11992 lmt_push_par_context(L, context);
11993 i = lmt_callback_call(L, 1, 1, top);
11994 if (i) {
11995 lmt_callback_error(L, top, i);
11996 }
11997 else {
11998 *ignore = lua_toboolean(L, -1);
11999 lmt_callback_wrapup(L, top);
12000 }
12001 }
12002 }
12003}
12004
12005void lmt_page_filter_callback(
12006 int context,
12007 halfword boundary
12008)
12009{
12010 int callback_id = lmt_callback_defined(buildpage_filter_callback);
12011 if (callback_id > 0) {
12012 lua_State *L = lmt_lua_state.lua_instance;
12013 int top = 0;
12014 if (lmt_callback_okay(L, callback_id, &top)) {
12015 int i;
12016 lmt_push_page_context(L, context);
12017 lua_push_halfword(L, boundary);
12018 i = lmt_callback_call(L, 2, 0, top);
12019 if (i) {
12020 lmt_callback_error(L, top, i);
12021 } else {
12022 lmt_callback_wrapup(L, top);
12023 }
12024 }
12025 }
12026}
12027
12028
12029
12030void lmt_append_line_filter_callback(
12031 halfword context,
12032 halfword index
12033)
12034{
12035 if (cur_list.tail) {
12036 int callback_id = lmt_callback_defined(append_line_filter_callback);
12037 if (callback_id > 0) {
12038 lua_State *L = lmt_lua_state.lua_instance;
12039 int top = 0;
12040 if (lmt_callback_okay(L, callback_id, &top)) {
12041 int i;
12042 lmt_node_list_to_lua(L, node_next(cur_list.head));
12043 lmt_node_list_to_lua(L, cur_list.tail);
12044 lmt_push_append_line_context(L, context);
12045 lua_push_halfword(L, index);
12046 i = lmt_callback_call(L, 4, 1, top);
12047 if (i) {
12048 lmt_callback_error(L, top, i);
12049 } else {
12050 if (lua_type(L, -1) == LUA_TUSERDATA) {
12051 int a = lmt_node_list_from_lua(L, -1);
12052 node_next(cur_list.head) = a;
12053 cur_list.tail = tex_tail_of_node_list(a);
12054 }
12055 lmt_callback_wrapup(L, top);
12056 }
12057 }
12058 }
12059 }
12060}
12061
12062
12069
12070void lmt_node_filter_callback(
12071 int filterid,
12072 int extrainfo,
12073 halfword head,
12074 halfword *tail
12075)
12076{
12077 if (head) {
12078
12079 halfword start = node_next(head);
12080 if (start) {
12081 int callback_id = lmt_callback_defined(filterid);
12082 if (callback_id > 0) {
12083 lua_State *L = lmt_lua_state.lua_instance;
12084 int top = 0;
12085 if (lmt_callback_okay(L, callback_id, &top)) {
12086 int i;
12087
12088 node_prev(start) = null;
12089
12090 lmt_node_list_to_lua(L, start);
12091 lmt_push_group_code(L, extrainfo);
12092 i = lmt_callback_call(L, 2, 1, top);
12093 if (i) {
12094 lmt_callback_error(L, top, i);
12095 } else {
12096
12097 halfword list = lmt_node_list_from_lua(L, -1);
12098 tex_try_couple_nodes(head, list);
12099
12100 lua_pop(L, 2);
12101
12102 *tail = tex_tail_of_node_list(head);
12103 lmt_callback_wrapup(L, top);
12104 }
12105 }
12106 }
12107 }
12108 }
12109 return;
12110}
12111
12112
12115
12116int lmt_linebreak_callback(
12117 halfword head,
12118 int isbroken,
12119 halfword *newhead
12120)
12121{
12122 if (head) {
12123 halfword start = node_next(head);
12124 if (start) {
12125 int callback_id = lmt_callback_defined(linebreak_filter_callback);
12126 if (callback_id > 0) {
12127 lua_State *L = lmt_lua_state.lua_instance;
12128 int top = 0;
12129 if (callback_id > 0 && lmt_callback_okay(L, callback_id, &top)) {
12130 int i;
12131 int ret = 0;
12132 node_prev(start) = null;
12133 lmt_node_list_to_lua(L, start);
12134 lua_pushboolean(L, isbroken);
12135 i = lmt_callback_call(L, 2, 1, top);
12136 if (i) {
12137 lmt_callback_error(L, top, i);
12138 } else {
12139 halfword *result = lua_touserdata(L, -1);
12140 if (result) {
12141 halfword list = lmt_node_list_from_lua(L, -1);
12142 tex_try_couple_nodes(*newhead, list);
12143 ret = 1;
12144 }
12145 lmt_callback_wrapup(L, top);
12146 }
12147 return ret;
12148 }
12149 }
12150 }
12151 }
12152 return 0;
12153}
12154
12155void lmt_alignment_callback(
12156 halfword head,
12157 halfword context,
12158 halfword callback,
12159 halfword attrlist,
12160 halfword preamble
12161)
12162{
12163 if (head || preamble) {
12164 int callback_id = lmt_callback_defined(alignment_filter_callback);
12165 if (callback_id > 0) {
12166 lua_State *L = lmt_lua_state.lua_instance;
12167 int top = 0;
12168 if (lmt_callback_okay(L, callback_id, &top)) {
12169 int i;
12170 lmt_node_list_to_lua(L, head);
12171 lmt_push_alignment_context(L, context);
12172 lua_pushinteger(L, callback);
12173 lmt_node_list_to_lua(L, attrlist);
12174 lmt_node_list_to_lua(L, preamble);
12175 i = lmt_callback_call(L, 5, 0, top);
12176 if (i) {
12177 lmt_callback_error(L, top, i);
12178 } else {
12179 lmt_callback_wrapup(L, top);
12180 }
12181 }
12182 }
12183 }
12184 return;
12185}
12186
12187void lmt_local_box_callback(
12188 halfword linebox,
12189 halfword leftbox,
12190 halfword rightbox,
12191 halfword middlebox,
12192 halfword linenumber,
12193 scaled leftskip,
12194 scaled rightskip,
12195 scaled lefthang,
12196 scaled righthang,
12197 scaled indentation,
12198 scaled parinitleftskip,
12199 scaled parinitrightskip,
12200 scaled parfillleftskip,
12201 scaled parfillrightskip,
12202 scaled overshoot
12203)
12204{
12205 if (linebox) {
12206 int callback_id = lmt_callback_defined(local_box_filter_callback);
12207 if (callback_id > 0) {
12208 lua_State *L = lmt_lua_state.lua_instance;
12209 int top = 0;
12210 if (lmt_callback_okay(L, callback_id, &top)) {
12211 int i;
12212 lmt_node_list_to_lua(L, linebox);
12213 lmt_node_list_to_lua(L, leftbox);
12214 lmt_node_list_to_lua(L, rightbox);
12215 lmt_node_list_to_lua(L, middlebox);
12216 lua_pushinteger(L, linenumber);
12217 lua_pushinteger(L, leftskip);
12218 lua_pushinteger(L, rightskip);
12219 lua_pushinteger(L, lefthang);
12220 lua_pushinteger(L, righthang);
12221 lua_pushinteger(L, indentation);
12222 lua_pushinteger(L, parinitleftskip);
12223 lua_pushinteger(L, parinitrightskip);
12224 lua_pushinteger(L, parfillleftskip);
12225 lua_pushinteger(L, parfillrightskip);
12226 lua_pushinteger(L, overshoot);
12227 i = lmt_callback_call(L, 15, 0, top);
12228 if (i) {
12229 lmt_callback_error(L, top, i);
12230 } else {
12231
12232 lmt_callback_wrapup(L, top);
12233 }
12234 }
12235 }
12236 }
12237}
12238
12239
12243
12244int lmt_append_to_vlist_callback(
12245 halfword box,
12246 int location,
12247 halfword prevdepth,
12248 halfword *result,
12249 int *nextdepth,
12250 int *prevset,
12251 int *checkdepth
12252)
12253{
12254 if (box) {
12255 int callback_id = lmt_callback_defined(append_to_vlist_filter_callback);
12256 if (callback_id > 0) {
12257 lua_State *L = lmt_lua_state.lua_instance;
12258 int top = 0;
12259 if (lmt_callback_okay(L, callback_id, &top)) {
12260 int i;
12261 lmt_node_list_to_lua(L, box);
12262 lua_push_key_by_index(location);
12263 lua_pushinteger(L, (int) prevdepth);
12264 i = lmt_callback_call(L, 3, 3, top);
12265 if (i) {
12266 lmt_callback_error(L, top, i);
12267 } else {
12268 switch (lua_type(L, -3)) {
12269 case LUA_TUSERDATA:
12270 *result = lmt_check_isnode(L, -3);
12271 break;
12272 case LUA_TNIL:
12273 *result = null;
12274 break;
12275 default:
12276 tex_normal_warning("append to vlist callback", "node or nil expected");
12277 break;
12278 }
12279 if (lua_type(L, -2) == LUA_TNUMBER) {
12280 *nextdepth = lmt_roundnumber(L, -2);
12281 *prevset = 1;
12282 }
12283 if (*result && lua_type(L, -1) == LUA_TBOOLEAN) {
12284 *checkdepth = lua_toboolean(L, -1);
12285 }
12286 lmt_callback_wrapup(L, top);
12287 return 1;
12288 }
12289 }
12290 }
12291 }
12292 return 0;
12293}
12294
12295
12299
12300halfword lmt_hpack_filter_callback(
12301 halfword head,
12302 scaled size,
12303 int packtype,
12304 int extrainfo,
12305 int direction,
12306 halfword attr
12307)
12308{
12309 if (head) {
12310 int callback_id = lmt_callback_defined(hpack_filter_callback);
12311 if (callback_id > 0) {
12312 lua_State *L = lmt_lua_state.lua_instance;
12313 int top = 0;
12314 if (lmt_callback_okay(L, callback_id, &top)) {
12315 int i;
12316 node_prev(head) = null;
12317 lmt_node_list_to_lua(L, head);
12318 lmt_push_group_code(L, extrainfo);
12319 lua_pushinteger(L, size);
12320 lmt_push_pack_type(L, packtype);
12321 if (direction >= 0) {
12322 lua_pushinteger(L, direction);
12323 } else {
12324 lua_pushnil(L);
12325 }
12326
12327 lmt_node_list_to_lua(L, attr);
12328 i = lmt_callback_call(L, 6, 1, top);
12329 if (i) {
12330 lmt_callback_error(L, top, i);
12331 } else {
12332 head = lmt_node_list_from_lua(L, -1);
12333 lmt_callback_wrapup(L, top);
12334 }
12335 }
12336 }
12337 }
12338 return head;
12339}
12340
12341extern halfword lmt_packed_vbox_filter_callback(
12342 halfword box,
12343 int extrainfo
12344)
12345{
12346 if (box) {
12347 int callback_id = lmt_callback_defined(packed_vbox_filter_callback);
12348 if (callback_id > 0) {
12349 lua_State *L = lmt_lua_state.lua_instance;
12350 int top = 0;
12351 if (lmt_callback_okay(L, callback_id, &top)) {
12352 int i;
12353 lmt_node_list_to_lua(L, box);
12354 lmt_push_group_code(L, extrainfo);
12355 i = lmt_callback_call(L, 2, 1, top);
12356 if (i) {
12357 lmt_callback_error(L, top, i);
12358 } else {
12359 box = lmt_node_list_from_lua(L, -1);
12360 lmt_callback_wrapup(L, top);
12361 }
12362 }
12363 }
12364 }
12365 return box;
12366}
12367
12368halfword lmt_vpack_filter_callback(
12369 halfword head,
12370 scaled size,
12371 int packtype,
12372 scaled maxdepth,
12373 int extrainfo,
12374 int direction,
12375 halfword attr
12376)
12377{
12378 if (head) {
12379 int callback_id = lmt_callback_defined(extrainfo == output_group ? pre_output_filter_callback : vpack_filter_callback);
12380 if (callback_id > 0) {
12381 lua_State *L = lmt_lua_state.lua_instance;
12382 int top = 0;
12383 if (lmt_callback_okay(L, callback_id, &top)) {
12384 int i;
12385 node_prev(head) = null;
12386 lmt_node_list_to_lua(L, head);
12387 lmt_push_group_code(L, extrainfo);
12388 lua_pushinteger(L, size);
12389 lmt_push_pack_type(L, packtype);
12390 lua_pushinteger(L, maxdepth);
12391 if (direction >= 0) {
12392 lua_pushinteger(L, direction);
12393 } else {
12394 lua_pushnil(L);
12395 }
12396 lmt_node_list_to_lua(L, attr);
12397 i = lmt_callback_call(L, 7, 1, top);
12398 if (i) {
12399 lmt_callback_error(L, top, i);
12400 } else {
12401 head = lmt_node_list_from_lua(L, -1);
12402 lmt_callback_wrapup(L, top);
12403 }
12404 }
12405 }
12406 }
12407 return head;
12408}
12409
12410
12411
12412# define get_dimension_par(P,A,B) \
12413 lua_push_key(A); \
12414 P = (lua_rawget(L, -3) == LUA_TNUMBER) ? lmt_roundnumber(L, -1) : B; \
12415 lua_pop(L, 1);
12416
12417# define get_integer_par(P,A,B) \
12418 lua_push_key(A); \
12419 P = (lua_rawget(L, -3) == LUA_TNUMBER) ? lmt_tohalfword(L, -1) : B; \
12420 lua_pop(L, 1);
12421
12422int lmt_par_pass_callback(
12423 halfword head,
12424 line_break_properties *properties,
12425 halfword identifier,
12426 halfword subpass,
12427 halfword callback,
12428 halfword features,
12429 scaled overfull,
12430 scaled underfull,
12431 halfword verdict,
12432 halfword classified,
12433 scaled threshold,
12434 halfword demerits,
12435 halfword classes,
12436 int *repeat
12437)
12438{
12439
12440 int callback_id = lmt_callback_defined(paragraph_pass_callback);
12441 (void) features;
12442 if (callback_id > 0) {
12443 lua_State *L = lmt_lua_state.lua_instance;
12444 int top = 0;
12445 int result = 0;
12446 if (lmt_callback_okay(L, callback_id, &top)) {
12447 int i;
12448 lmt_node_list_to_lua(L, head);
12449 lua_push_integer(L, identifier);
12450 lua_push_integer(L, subpass);
12451 lua_push_integer(L, callback);
12452 lua_push_integer(L, overfull);
12453 lua_push_integer(L, underfull);
12454 lua_push_integer(L, verdict);
12455 lua_push_integer(L, classified);
12456 lua_push_integer(L, threshold);
12457 lua_push_integer(L, demerits);
12458 lua_push_integer(L, classes);
12459 i = lmt_callback_call(L, 10, 2, top);
12460 if (i) {
12461 lmt_callback_error(L, top, i);
12462 } else {
12463 switch (lua_type(L, -2)) {
12464 case LUA_TBOOLEAN:
12465 {
12466 result = lua_toboolean(L, -2);
12467 break;
12468 }
12469 case LUA_TTABLE:
12470 {
12471
12474 get_integer_par(properties->tolerance, tolerance, properties->tolerance);
12475 lmt_linebreak_state.threshold = properties->tolerance;
12476 lmt_linebreak_state.global_threshold = lmt_linebreak_state.threshold;
12477 get_integer_par(properties->line_penalty, linepenalty, properties->line_penalty);
12478 get_integer_par(properties->left_twin_demerits, lefttwindemerits, properties->left_twin_demerits);
12479 get_integer_par(properties->right_twin_demerits, righttwindemerits, properties->right_twin_demerits);
12480 get_integer_par(properties->extra_hyphen_penalty, extrahyphenpenalty, properties->extra_hyphen_penalty);
12481 get_integer_par(properties->double_hyphen_demerits, doublehyphendemerits, properties->double_hyphen_demerits);
12482 get_integer_par(properties->final_hyphen_demerits, finalhyphendemerits, properties->final_hyphen_demerits);
12483 get_integer_par(properties->adj_demerits, adjdemerits, properties->adj_demerits);
12484 get_dimension_par(properties->emergency_stretch, emergencystretch, properties->emergency_stretch);
12485 get_integer_par(properties->adjust_spacing_step, adjustspacingstep, properties->adjust_spacing_step);
12486 get_integer_par(properties->adjust_spacing_shrink, adjustspacingshrink, properties->adjust_spacing_shrink);
12487 get_integer_par(properties->adjust_spacing_stretch, adjustspacingstretch, properties->adjust_spacing_stretch);
12488 get_integer_par(properties->adjust_spacing, adjustspacing, properties->adjust_spacing);
12489 get_integer_par(properties->line_break_optional, optional, properties->line_break_optional);
12490 get_integer_par(properties->line_break_checks, linebreakchecks, properties->line_break_checks);
12491 get_integer_par(properties->math_penalty_factor, mathpenaltyfactor, properties->math_penalty_factor);
12492 get_integer_par(properties->sf_factor, sffactor, properties->sf_factor);
12493 get_integer_par(properties->sf_stretch_factor, sfstretchfactor, properties->sf_stretch_factor);
12494
12509 result = 1;
12510 break;
12511 }
12512 default:
12513 {
12514
12515 break;
12516 }
12517 }
12518 if (lua_type(L, -1) == LUA_TBOOLEAN) {
12519 *repeat = lua_toboolean(L, -1);
12520 }
12521 }
12522 }
12523 lmt_callback_wrapup(L, top);
12524 return result;
12525 }
12526
12527 return 0;
12528}
12529
12530halfword lmt_uleader_callback(
12531 halfword head,
12532 halfword index,
12533 int context,
12534 halfword box,
12535 int location
12536)
12537{
12538 if (head) {
12539 int callback_id = lmt_callback_defined(handle_uleader_callback);
12540 if (callback_id > 0) {
12541 lua_State *L = lmt_lua_state.lua_instance;
12542 int top = 0;
12543 if (lmt_callback_okay(L, callback_id, &top)) {
12544 int i;
12545 lmt_node_list_to_lua(L, head);
12546
12547 lmt_push_group_code(L, context);
12548 lua_pushinteger(L, index);
12549 lmt_node_list_to_lua(L, box);
12550 lua_pushinteger(L, location);
12551 i = lmt_callback_call(L, 5, 1, top);
12552 if (i) {
12553 lmt_callback_error(L, top, i);
12554 } else {
12555 head = lmt_node_list_from_lua(L, -1);
12556 lmt_callback_wrapup(L, top);
12557 }
12558 }
12559 }
12560 }
12561 return head;
12562}
12563
12564halfword lmt_uinsert_callback(
12565 halfword callback,
12566 halfword index,
12567 halfword order,
12568 halfword packed,
12569 scaled height,
12570 scaled amount
12571)
12572{
12573 if (packed) {
12574 int callback_id = lmt_callback_defined(handle_uinsert_callback);
12575 if (callback_id > 0) {
12576 lua_State *L = lmt_lua_state.lua_instance;
12577 int top = 0;
12578 if (lmt_callback_okay(L, callback_id, &top)) {
12579 int i;
12580 lua_pushinteger(L, callback);
12581 lua_pushinteger(L, index);
12582 lua_pushinteger(L, order);
12583 lmt_node_list_to_lua(L, packed);
12584 lua_pushinteger(L, height);
12585 lua_pushinteger(L, amount);
12586 i = lmt_callback_call(L, 6, 1, top);
12587 if (i) {
12588 lmt_callback_error(L, top, i);
12589 } else {
12590 halfword result = lmt_node_list_from_lua(L, -1);
12591 if (result) {
12592 packed = result;
12593 }
12594 lmt_callback_wrapup(L, top);
12595 }
12596 }
12597 }
12598 }
12599 return packed;
12600}
12601
12602void lmt_insert_par_callback(
12603 halfword node,
12604 halfword mode
12605)
12606{
12607 int callback_id = lmt_callback_defined(insert_par_callback);
12608 if (callback_id > 0) {
12609 lua_State *L = lmt_lua_state.lua_instance;
12610 int top = 0;
12611 if (lmt_callback_okay(L, callback_id, &top)) {
12612 int i;
12613 lmt_node_list_to_lua(L, node);
12614 lmt_push_par_mode(L, mode);
12615 i = lmt_callback_call(L, 2, 0, top);
12616 if (i) {
12617 lmt_callback_error(L, top, i);
12618 } else {
12619 lmt_callback_wrapup(L, top);
12620 }
12621 }
12622 }
12623}
12624
12625scaled lmt_italic_correction_callback(
12626 halfword glyph,
12627 scaled kern,
12628 halfword subtype
12629)
12630{
12631 int callback_id = lmt_callback_defined(italic_correction_callback);
12632 if (callback_id > 0) {
12633 lua_State *L = lmt_lua_state.lua_instance;
12634 int top = 0;
12635 if (lmt_callback_okay(L, callback_id, &top)) {
12636 int i;
12637 lmt_node_list_to_lua(L, glyph);
12638 lua_pushinteger(L, kern);
12639 lua_pushinteger(L, subtype);
12640 i = lmt_callback_call(L, 3, 1, top);
12641 if (i) {
12642 lmt_callback_error(L, top, i);
12643 } else {
12644 kern = lmt_tohalfword(L, -1);
12645 lmt_callback_wrapup(L, top);
12646 }
12647 }
12648 }
12649 return kern;
12650}
12651 |