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