1
4
5# include "luametatex.h"
6
7
19
20
114
115math_state_info lmt_math_state = {
116 .size = 0,
117 .level = 0,
118 .par_head = NULL,
119 .fam_head = NULL,
120 .last_left = 0,
121 .last_right = 0,
122 .last_atom = 0,
123 .scale = scaling_factor,
124 .single = 0,
125 .padding = 0,
126};
127
128
129
130typedef enum saved_math_entries {
131 saved_math_direction_entry = 0,
132 saved_math_n_of_records = 1,
133} saved_math_entries;
134
135# define saved_math_direction saved_value_1(saved_math_direction_entry)
136
137inline static void saved_math_initialize(void)
138{
139 saved_type(0) = saved_record_0;
140 saved_record(0) = math_save_type;
141}
142
143int tex_show_math_record(void)
144{
145 tex_print_str("math ");
146 switch (saved_type(0)) {
147 case saved_record_0:
148 tex_print_format("direction %i", saved_value_1(0));
149 break;
150 default:
151 return 0;
152 }
153 return 1;
154}
155
156
157
158typedef enum saved_equation_number_entries {
159 saved_equation_number_location_entry = 0,
160 saved_equation_number_n_of_records = 1,
161} saved_equation_number_entries;
162
163# define saved_equation_number_location saved_value_1(saved_equation_number_location_entry)
164
165inline static void saved_equation_number_initialize(void)
166{
167 saved_type(0) = saved_record_0;
168 saved_record(0) = number_save_type;
169}
170
171void tex_show_math_number_group(void)
172{
173 tex_print_cmd_chr(equation_number_cmd, saved_equation_number_location);
174}
175
176int tex_show_math_number_record(void)
177{
178 tex_print_str("equation number ");
179 switch (saved_type(0)) {
180 case saved_record_0:
181 tex_print_format("location %i", saved_value_1(0));
182 break;
183 default:
184 return 0;
185 }
186 return 1;
187}
188
189
190
191typedef enum saved_choice_entries {
192 saved_choice_count_entry = 0,
193 saved_choice_n_of_records = 1,
194} saved_choice_entries;
195
196# define saved_choice_count saved_value_1(saved_choice_count_entry)
197
198inline static void saved_choice_initialize(void)
199{
200 saved_type(0) = saved_record_0;
201 saved_record(0) = choice_save_type;
202}
203
204inline static int saved_choice_current_component(void)
205{
206 return saved_type(saved_choice_count_entry - saved_choice_n_of_records) == saved_record_0
207 ? saved_value_1(saved_choice_count_entry - saved_choice_n_of_records) : -1 ;
208}
209
210inline static void saved_choice_update_component(void)
211{
212 saved_value_1(saved_choice_count_entry - saved_choice_n_of_records) += 1;
213}
214
215void tex_show_math_choice_group(void)
216{
217 tex_print_str_esc("mathchoice");
218 tex_aux_show_group_count(saved_choice_count);
219}
220
221int tex_show_math_choice_record(void)
222{
223 tex_print_str("choice ");
224 switch (saved_type(0)) {
225 case saved_record_0:
226 tex_print_format("count %i", saved_value_1(0));
227 break;
228 default:
229 return 0;
230 }
231 return 1;
232}
233
234
235
236typedef enum saved_fraction_entries {
237 saved_fraction_variant_entry = 0,
238 saved_fraction_userstyle_entry = 0,
239 saved_fraction_autostyle_entry = 0,
240 saved_fraction_n_of_records = 1,
241} saved_fraction_entries;
242
243# define saved_fraction_variant saved_value_1(saved_fraction_variant_entry)
244# define saved_fraction_userstyle saved_value_2(saved_fraction_userstyle_entry)
245# define saved_fraction_autostyle saved_value_3(saved_fraction_autostyle_entry)
246
247inline static void saved_fraction_initialize(void)
248{
249 saved_type(0) = saved_record_0;
250 saved_record(0) = fraction_save_type;
251}
252
253inline static int saved_fraction_current_component(void)
254{
255 return saved_type(saved_fraction_variant_entry - saved_fraction_n_of_records) == saved_record_0
256 ? saved_value_1(saved_fraction_variant_entry - saved_fraction_n_of_records) : -1 ;
257}
258
259inline static void saved_fraction_update_component(void)
260{
261 saved_value_1(saved_fraction_variant_entry - saved_fraction_n_of_records) += 1;
262}
263
264inline static int saved_fraction_current_userstyle(void)
265{
266 return saved_value_2(saved_fraction_userstyle_entry - saved_fraction_n_of_records);
267}
268
269inline static int saved_fraction_current_autostyle(void)
270{
271 return saved_value_3(saved_fraction_autostyle_entry - saved_fraction_n_of_records);
272}
273
274void tex_show_math_fraction_group(void)
275{
276 tex_print_str_esc("fraction");
277 tex_aux_show_group_count(saved_fraction_variant);
278}
279
280int tex_show_math_fraction_record(void)
281{
282 tex_print_str("fraction ");
283 switch (saved_type(0)) {
284 case saved_record_0:
285 tex_print_format("variant %i, userstyle %i, autostyle %i", saved_value_1(0), saved_value_2(0), saved_value_3(0));
286 break;
287 default:
288 return 0;
289 }
290 return 1;
291}
292
293
294
295typedef enum saved_radical_entries {
296 saved_radical_degree_done_entry = 0,
297 saved_radical_style_entry = 0,
298 saved_radical_n_of_records = 1,
299} saved_radical_entries;
300
301# define saved_radical_degree_done saved_value_1(saved_radical_degree_done_entry)
302# define saved_radical_style saved_value_2(saved_radical_style_entry)
303
304inline static void saved_radical_initialize(void)
305{
306 saved_type(0) = saved_record_0;
307 saved_record(0) = radical_save_type;
308}
309
310inline static int saved_radical_current_component(void)
311{
312 return saved_type(saved_radical_degree_done_entry - saved_radical_n_of_records) == saved_record_0
313 ? saved_value_1(saved_radical_degree_done_entry - saved_radical_n_of_records) : -1 ;
314}
315
316inline static int saved_radical_current_style(void)
317{
318 return saved_value_2(saved_radical_style_entry - saved_radical_n_of_records);
319}
320
321inline static void saved_radical_update_component(void)
322{
323 saved_value_1(saved_radical_degree_done_entry - saved_radical_n_of_records) += 1;
324}
325
326void tex_show_math_radical_group(void)
327{
328 tex_print_str_esc("radical");
329 tex_aux_show_group_count(saved_radical_degree_done);
330}
331
332int tex_show_math_radical_record(void)
333{
334 tex_print_str("radical ");
335 switch (saved_type(0)) {
336 case saved_record_0:
337 tex_print_format("degree %i, style %i", saved_value_1(0), saved_value_2(0));
338 break;
339 default:
340 return 0;
341 }
342 return 1;
343}
344
345
346
347typedef enum saved_operator_entries {
348 saved_operator_variant_entry = 0,
349 saved_operator_n_of_records = 1,
350} saved_operator_entries;
351
352# define saved_operator_variant saved_value_1(saved_operator_variant_entry)
353
354inline static void saved_operator_initialize(void)
355{
356 saved_type(0) = saved_record_0;
357 saved_record(0) = operator_save_type;
358}
359
360inline static int saved_operator_current_component(void)
361{
362 return saved_type(saved_operator_variant_entry - saved_operator_n_of_records) == saved_record_0
363 ? saved_value_1(saved_operator_variant_entry - saved_operator_n_of_records) : -1 ;
364}
365
366inline static void saved_operator_update_component(void)
367{
368 saved_value_1(saved_operator_variant_entry - saved_operator_n_of_records) += 1;
369}
370
371void tex_show_math_operator_group(void)
372{
373 tex_print_str_esc("operator");
374 tex_aux_show_group_count(saved_operator_variant);
375}
376
377int tex_show_math_operator_record(void)
378{
379 tex_print_str("operator ");
380 switch (saved_type(0)) {
381 case saved_record_0:
382 tex_print_format("variant %i", saved_value_1(0));
383 break;
384 default:
385 return 0;
386 }
387 return 1;
388}
389
390
391
392typedef enum saved_math_group_entries {
393 saved_math_group_pointer_entry = 0,
394 saved_math_group_all_class_entry = 0,
395 saved_math_group_n_of_records = 1,
396} saved_math_group_entries;
397
398# define saved_math_group_pointer saved_value_1(saved_math_group_pointer_entry)
399# define saved_math_group_all_class saved_value_2(saved_math_group_all_class_entry)
400
401inline static void saved_math_group_initialize(void)
402{
403 saved_type(0) = saved_record_0;
404 saved_record(0) = math_group_save_type;
405}
406
407int tex_show_math_group_record(void)
408{
409 tex_print_str("math group ");
410 switch (saved_type(0)) {
411 case saved_record_0:
412 tex_print_format("pointer %i, allclass %i", saved_value_1(0), saved_value_2(0));
413 break;
414 default:
415 return 0;
416 }
417 return 1;
418}
419
420
421
422static int tex_aux_scan_math (halfword p, halfword style, int usetextfont, halfword toks, halfword toks_text, int nocomponent, halfword cls, halfword all);
423static halfword tex_aux_finish_math_list (halfword p);
424static void tex_aux_math_math_component (halfword n, int append);
425
426# define cramped 1
427
428# define cramped_style(A) (2 * ((A) / 2) + cramped)
429# define sub_style(A) (2 * ((A) / 4) + script_style + cramped)
430# define sup_style(A) (2 * ((A) / 4) + script_style + ((A) % 2))
431# define num_style(A) ((A) + 2 - 2 * ((A) / 6))
432# define denom_style(A) (2 * ((A) / 2) + cramped + 2 - 2 * ((A) / 6))
433# define sup_sup_style(A) sup_style(sup_style((A)))
434
435inline static mathdictval tex_fake_math_dict(halfword chr)
436{
437 mathdictval d = tex_no_dict_code();
438 if (math_dict_properties_par || math_dict_group_par) {
439 d.properties = (unsigned short) math_dict_properties_par;
440 d.group = (unsigned short) math_dict_group_par;
441 d.index = (unsigned int) chr;
442 }
443 return d;
444}
445
446void tex_math_copy_char_data(halfword target, halfword source, int wipelist)
447{
448 if (node_type(source) == math_char_node) {
449 kernel_math_family(target) = kernel_math_family(source);
450 kernel_math_character(target) = kernel_math_character(source);
451 kernel_math_options(target) = kernel_math_options(source);
452 kernel_math_properties(target) = kernel_math_properties(source);
453 kernel_math_group(target) = kernel_math_group(source);
454 kernel_math_index(target) = kernel_math_index(source);
455 } else {
456 kernel_math_list(target) = kernel_math_list(source);
457 if (wipelist) {
458 kernel_math_list(source) = null;
459 }
460 }
461}
462
463inline static void tex_math_set_scripts_options(halfword n)
464{
465 switch (math_scripts_mode_par) {
466 case 1: noad_options(n) |= noad_option_fixed_super_or_sub_script; break;
467 case 2: noad_options(n) |= noad_option_fixed_super_and_sub_script; break;
468 }
469}
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
540
541halfword tex_size_of_style(halfword style)
542{
543 switch (style) {
544 case script_style:
545 case cramped_script_style:
546 return script_size;
547 case script_script_style:
548 case cramped_script_script_style:
549 return script_script_size;
550 default:
551 return text_size;
552 }
553}
554
555halfword tex_math_style_variant(halfword style, halfword param)
556{
557 switch (tex_get_math_parameter(style, param, NULL)) {
558 case math_normal_style_variant:
559 return style;
560 case math_cramped_style_variant:
561
562 return cramped_style(style);
563 case math_subscript_style_variant:
564
565 return sub_style(style);
566 case math_superscript_style_variant:
567 case math_small_style_variant:
568
569 return sup_style(style);
570 case math_smaller_style_variant:
571 case math_numerator_style_variant:
572
573 return num_style(style);
574 case math_denominator_style_variant:
575
576 return denom_style(style);
577 case math_double_superscript_variant:
578
579 return sup_sup_style(style);
580 default:
581 return style;
582 }
583}
584
585int tex_math_has_class_option(halfword cls, int option)
586{
587 halfword value = count_parameter(first_math_options_code + cls);
588 if (value == no_class_options) {
589 unsigned parent = (unsigned) count_parameter(first_math_parent_code + cls);
590 cls = (parent >> 16) & 0xFF;
591 if (! valid_math_class_code(cls)) {
592 return 0;
593 }
594 value = count_parameter(first_math_options_code + cls);
595 }
596 return (value & option) == option;
597}
598
599int tex_math_has_class_parent(halfword cls)
600{
601 halfword value = count_parameter(first_math_options_code + cls);
602 if (value == no_class_options) {
603 unsigned parent = (unsigned) count_parameter(first_math_parent_code + cls);
604 return (parent >> 16) & 0xFF;
605 }
606 return 0;
607}
608
609static void tex_aux_unsave_math(void)
610{
611 tex_unsave();
612 lmt_save_state.save_stack_data.ptr -= saved_math_n_of_records;
613 tex_flush_node_list(lmt_dir_state.text_dir_ptr);
614 lmt_dir_state.text_dir_ptr = saved_math_direction;
615}
616
617
623
624void tex_flush_math(void)
625{
626 halfword head = cur_list.head;
627 tex_flush_node_list(node_next(head));
628 tex_flush_node_list(cur_list.incomplete_noad);
629 node_next(head) = null;
630 cur_list.tail = head;
631 cur_list.incomplete_noad = null;
632}
633
634
635
636static void tex_aux_print_parameter(const char *what, halfword style, halfword param, halfword indirect, halfword value)
637{
638 tex_begin_diagnostic();
639 tex_print_format("{%s ", what);
640 if (indirect >= 0 && indirect <= last_math_indirect) {
641 tex_print_str(lmt_interface.math_indirect_values[indirect].name);
642 tex_print_char(' ');
643 }
644 if (param < math_parameter_last) {
645 tex_print_cmd_chr(math_parameter_cmd, param);
646 } else {
647 tex_print_format("%x %x ", math_parameter_spacing_left(param), math_parameter_spacing_right(param));
648 }
649 tex_print_cmd_chr(math_style_cmd, style);
650 tex_print_char('=');
651 switch (math_parameter_value_type(param)) {
652 case math_integer_parameter:
653 case math_style_parameter:
654 tex_print_int(value);
655 break;
656 case math_dimension_parameter:
657 tex_print_dimension(value, pt_unit);
658 break;
659 case math_muglue_parameter:
660 tex_print_spec(value, mu_unit);
661 break;
662 default:
663 tex_print_int(value);
664 break;
665 }
666 tex_print_char('}');
667 tex_end_diagnostic();
668}
669
670static void tex_aux_print_fam(const char *what, halfword size, halfword fam)
671{
672 tex_begin_diagnostic();
673 tex_print_format("{%s %C family %i: %F}", what, define_family_cmd, size, fam, tex_fam_fnt(fam, size));
674 tex_end_diagnostic();
675}
676
677
681
682int tex_fam_fnt(int fam, int size)
683{
684 sa_tree_item item;
685 sa_get_item_4(lmt_math_state.fam_head, fam + (256 * size), &item);
686 return (int) item.int_value;
687}
688
689void tex_def_fam_fnt(int fam, int size, int fnt, int level)
690{
691 sa_tree_item item;
692 item.int_value = fnt;
693 sa_set_item_4(lmt_math_state.fam_head, fam + (256 * size), item, level);
694 if (tracing_assigns_par > 1) {
695 tex_aux_print_fam("assigning", size, fam);
696 }
697 tex_fixup_math_parameters(fam, size, fnt, level);
698}
699
700static void tex_aux_unsave_math_fam_data(int gl)
701{
702 if (lmt_math_state.fam_head->stack) {
703 while (lmt_math_state.fam_head->sa_stack_ptr > 0 && abs(lmt_math_state.fam_head->stack[lmt_math_state.fam_head->sa_stack_ptr].level) >= (int) gl) {
704 sa_stack_item item = lmt_math_state.fam_head->stack[lmt_math_state.fam_head->sa_stack_ptr];
705 if (item.level > 0) {
706 sa_rawset_item_4(lmt_math_state.fam_head, item.code, item.value_1);
707
708 if (tracing_restores_par > 1) {
709 int size = item.code / 256;
710 int fam = item.code % 256;
711 tex_aux_print_fam("restoring", size, fam);
712 }
713 }
714 (lmt_math_state.fam_head->sa_stack_ptr)--;
715 }
716 }
717}
718
719
720
721void tex_def_math_parameter(int style, int param, scaled value, int level, int indirect, int fixup)
722{
723 if (fixup && ignore_math_parameter(param) == 2) {
724 return;
725 } else {
726 sa_tree_item item1, item2;
727 int different = 1;
728 if (level <= 1) {
729 if (math_parameter_value_type(param) == math_muglue_parameter) {
730 sa_get_item_8(lmt_math_state.par_head, (param + (math_parameter_max_range * style)), &item1, &item2);
731 if (item2.int_value == indirect_math_regular && item1.int_value > thick_muskip_code) {
732 if (lmt_node_memory_state.nodesizes[item1.int_value]) {
733 tex_free_node(item1.int_value, glue_spec_size);
734 }
735 }
736 }
737 } else {
738
739 sa_get_item_8(lmt_math_state.par_head, (param + (math_parameter_max_range * style)), &item1, &item2);
740 different = item1.int_value != value || item2.int_value != indirect;
741 }
742
743 item1.int_value = value;
744 item2.int_value = indirect;
745 sa_set_item_8(lmt_math_state.par_head, (param + (math_parameter_max_range * style)), item1, item2, level);
746 if (different && tracing_assigns_par > 1) {
747 tex_aux_print_parameter("assigning", style, param, indirect, value);
748 }
749
750 }
751}
752
753
754
755scaled tex_get_math_parameter(int style, int param, halfword *type)
756{
757 halfword indirect, value;
758 sa_tree_item v1, v2;
759 sa_get_item_8(lmt_math_state.par_head, (param + (math_parameter_max_range * style)), &v1, &v2);
760 indirect = v2.int_value == lmt_math_state.par_head->dflt.int_value ? indirect_math_unset : v2.uint_value;
761 value = v1.int_value;
762 switch (indirect) {
763 case indirect_math_unset:
764 if (type) {
765 *type = no_val_level;
766 }
767 return MATHPARAMDEFAULT;
768
769 case indirect_math_regular:
770 switch (math_parameter_value_type(param)) {
771 case math_dimension_parameter:
772 if (type) {
773 *type = dimension_val_level;
774 }
775 return value;
776 case math_muglue_parameter:
777 if (type) {
778 *type = muglue_val_level;
779 }
780 return value <= thick_muskip_code ? muglue_parameter(value) : value;
781
782
783 default:
784 if (type) {
785 *type = integer_val_level;
786 }
787 return value;
788 }
789
790 case indirect_math_integer:
791 if (! value) {
792 if (type) {
793 *type = integer_val_level;
794 }
795 return value;
796 } else if (eq_type(value) == integer_cmd) {
797 if (type) {
798 *type = integer_val_level;
799 }
800 return eq_value(value);
801 } else {
802 goto MISMATCH;
803 }
804 case indirect_math_dimension:
805 if (! value) {
806 if (type) {
807 *type = dimension_val_level;
808 }
809 return value;
810 } else if (eq_type(value) == dimension_cmd) {
811 if (type) {
812 *type = dimension_val_level;
813 }
814 return eq_value(value);
815 } else if (eq_type(value) == posit_cmd) {
816 if (type) {
817 *type = dimension_val_level;
818 }
819 return tex_posit_to_dimension(eq_value(value));
820 } else {
821 goto MISMATCH;
822 }
823 case indirect_math_mugluespec:
824 if (! value) {
825 if (type) {
826 *type = muglue_val_level;
827 }
828 return value;
829 } else {
830 switch (eq_type(value)) {
831 case mugluespec_cmd:
832 if (type) {
833 *type = muglue_val_level;
834 }
835 return eq_value(value);
836 default:
837 goto MISMATCH;
838 }
839
840 }
841 case indirect_math_gluespec:
842 if (! value) {
843 if (type) {
844 *type = glue_val_level;
845 }
846 return value;
847 } else {
848 switch (eq_type(value)) {
849 case gluespec_cmd:
850 if (type) {
851 *type = glue_val_level;
852 }
853 return eq_value(value);
854 default:
855 goto MISMATCH;
856 }
857 }
858
859 case indirect_math_register_integer:
860 if (! value) {
861 if (type) {
862 *type = integer_val_level;
863 }
864 return value;
865 } else if (eq_type(value) == register_integer_reference_cmd) {
866 if (type) {
867 *type = integer_val_level;
868 }
869 return eq_value(value);
870 } else {
871 goto MISMATCH;
872 }
873 case indirect_math_register_dimension:
874 if (! value) {
875 if (type) {
876 *type = dimension_val_level;
877 }
878 return value;
879 } else if (eq_type(value) == register_dimension_reference_cmd) {
880 if (type) {
881 *type = dimension_val_level;
882 }
883 return eq_value(value);
884 } else {
885 goto MISMATCH;
886 }
887 case indirect_math_register_gluespec:
888 if (! value) {
889 if (type) {
890 *type = glue_val_level;
891 }
892 return value;
893 } else if (eq_type(value) == register_glue_reference_cmd) {
894 if (type) {
895 *type = glue_val_level;
896 }
897 return eq_value(value);
898 } else {
899 goto MISMATCH;
900 }
901 case indirect_math_register_mugluespec:
902 if (! value) {
903 if (type) {
904 *type = muglue_val_level;
905 }
906 return value;
907 } else if (eq_type(value) == register_muglue_reference_cmd) {
908 if (type) {
909 *type = muglue_val_level;
910 }
911 return eq_value(value);
912 } else {
913 goto MISMATCH;
914 }
915 case indirect_math_internal_integer:
916 if (! value) {
917 if (type) {
918 *type = integer_val_level;
919 }
920 return value;
921 } else if (eq_type(value) == internal_integer_reference_cmd) {
922 if (type) {
923 *type = integer_val_level;
924 }
925 return eq_value(value);
926 } else {
927 goto MISMATCH;
928 }
929 case indirect_math_internal_dimension:
930 if (! value) {
931 if (type) {
932 *type = dimension_val_level;
933 }
934 return value;
935 } else if (eq_type(value) == internal_dimension_reference_cmd) {
936 if (type) {
937 *type = dimension_val_level;
938 }
939 return eq_value(value);
940 } else {
941 goto MISMATCH;
942 }
943 case indirect_math_internal_gluespec:
944 if (! value) {
945 if (type) {
946 *type = glue_val_level;
947 }
948 return value;
949 } else if (eq_type(value) == internal_glue_reference_cmd) {
950 if (type) {
951 *type = glue_val_level;
952 }
953 return eq_value(value);
954 } else {
955 goto MISMATCH;
956 }
957 case indirect_math_internal_mugluespec:
958 if (! value) {
959 if (type) {
960 *type = muglue_val_level;
961 }
962 return value;
963 } else if (eq_type(value) == internal_muglue_reference_cmd) {
964 if (type) {
965 *type = muglue_val_level;
966 }
967 return eq_value(value);
968 } else {
969 goto MISMATCH;
970 }
971 default:
972 MISMATCH:
973 tex_handle_error(
974 normal_error_type,
975 "Invalid inherited math parameter",
976 "You probably changed the type of the inherited math parameter, so I will "
977 "use zero instead."
978 );
979 return 0;
980 }
981}
982
983int tex_has_math_parameter(int style, int param)
984{
985 sa_tree_item v1, v2;
986 sa_get_item_8(lmt_math_state.par_head, (param + (math_parameter_max_range * style)), &v1, &v2);
987 return v2.int_value == lmt_math_state.par_head->dflt.int_value ? indirect_math_unset : v2.uint_value;
988}
989
990static void tex_aux_unsave_math_parameter_data(int gl)
991{
992 if (lmt_math_state.par_head->stack) {
993 while (lmt_math_state.par_head->sa_stack_ptr > 0 && abs(lmt_math_state.par_head->stack[lmt_math_state.par_head->sa_stack_ptr].level) >= (int) gl) {
994 sa_stack_item item = lmt_math_state.par_head->stack[lmt_math_state.par_head->sa_stack_ptr];
995 if (item.level > 0) {
996 int param = item.code % math_parameter_max_range;
997 int style = item.code / math_parameter_max_range;
998 if (math_parameter_value_type(param) == math_muglue_parameter) {
999 sa_tree_item item1, item2;
1000 sa_get_item_8(lmt_math_state.par_head, item.code, &item1, &item2);
1001 if (item2.int_value == indirect_math_regular && item1.int_value > thick_muskip_code) {
1002
1003 if (lmt_node_memory_state.nodesizes[item1.int_value]) {
1004
1005 tex_free_node(item1.int_value, glue_spec_size);
1006 } else {
1007
1008 }
1009 }
1010 }
1011 sa_rawset_item_8(lmt_math_state.par_head, item.code, item.value_1, item.value_2);
1012
1013 if (tracing_restores_par > 1) {
1014 int indirect = item.value_2.int_value;
1015 tex_aux_print_parameter("restoring", style, param, indirect, tex_get_math_parameter(style, param, NULL));
1016 }
1017 }
1018 lmt_math_state.par_head->sa_stack_ptr--;
1019 }
1020 }
1021}
1022
1023
1024
1025void tex_unsave_math_data(int level)
1026{
1027 tex_aux_unsave_math_fam_data(level);
1028 tex_aux_unsave_math_parameter_data(level);
1029}
1030
1031
1032
1033void tex_dump_math_data(dumpstream f)
1034{
1035 if (! lmt_math_state.fam_head) {
1036 lmt_math_state.fam_head = sa_new_tree(MATHFONTSTACK, 4, (sa_tree_item) { .int_value = MATHFONTDEFAULT });
1037 }
1038 sa_dump_tree(f, lmt_math_state.fam_head);
1039 if (! lmt_math_state.par_head) {
1040 lmt_math_state.par_head = sa_new_tree(MATHPARAMSTACK, 8, (sa_tree_item) { .int_value = MATHPARAMDEFAULT });
1041 }
1042 sa_dump_tree(f, lmt_math_state.par_head);
1043}
1044
1045void tex_undump_math_data(dumpstream f)
1046{
1047 lmt_math_state.fam_head = sa_undump_tree(f);
1048 lmt_math_state.par_head = sa_undump_tree(f);
1049}
1050
1051void tex_initialize_math(void)
1052{
1053 if (! lmt_math_state.fam_head) {
1054 lmt_math_state.fam_head = sa_new_tree(MATHFONTSTACK, 4, (sa_tree_item) { .int_value = MATHFONTDEFAULT });
1055 }
1056 if (! lmt_math_state.par_head) {
1057 lmt_math_state.par_head = sa_new_tree(MATHPARAMSTACK, 8, (sa_tree_item) { .int_value = MATHPARAMDEFAULT });
1058 tex_initialize_math_spacing();
1059 }
1060 return;
1061}
1062
1063
1101
1102halfword tex_new_sub_box(halfword curbox)
1103{
1104 halfword noad = tex_new_node(simple_noad, ordinary_noad_subtype);
1105 halfword sbox = tex_new_node(sub_box_node, 0);
1106 noad_nucleus(noad) = sbox;
1107 kernel_math_list(sbox) = curbox;
1108 return noad;
1109}
1110
1111static quarterword tex_aux_set_math_char(halfword target, mathcodeval *mval, mathdictval *dval)
1112{
1113 halfword hmcode = tex_get_hm_code(mval->character_value);
1114 kernel_math_character(target) = mval->character_value;
1115 if (mval->class_value == math_use_current_family_code) {
1116 kernel_math_family(target) = cur_fam_par_in_range ? cur_fam_par : mval->family_value;
1117 node_subtype(target) = ordinary_noad_subtype;
1118 } else if (mval->family_value == variable_family_par) {
1119
1120 kernel_math_family(target) = cur_fam_par_in_range ? cur_fam_par : mval->family_value;
1121 node_subtype(target) = mval->class_value;
1122 } else {
1123 kernel_math_family(target) = mval->family_value;
1124 node_subtype(target) = mval->class_value;
1125 }
1126 if (dval) {
1127 kernel_math_properties(target) = dval->properties;
1128 kernel_math_group(target) = dval->group;
1129 kernel_math_index(target) = dval->index;
1130 }
1131 if ((hmcode & auto_discretionary_normal) == auto_discretionary_normal) {
1132 math_kernel_node_set_option(target, math_kernel_auto_discretionary);
1133 }
1134 if ((hmcode & auto_discretionary_italic) == auto_discretionary_italic) {
1135 math_kernel_node_set_option(target, math_kernel_full_discretionary);
1136 }
1137 return node_subtype(target);
1138}
1139
1140
1169
1170void tex_run_math_style(void) {
1171 switch (cur_chr) {
1172 case yet_unset_math_style:
1173 {
1174 halfword style = tex_scan_math_style_identifier(1, 0);
1175 if (is_valid_math_style(style)) {
1176 halfword noad = tex_new_node(style_node, (quarterword) style);
1177 cur_list.math_style = style;
1178 tex_tail_append(noad);
1179 }
1180 }
1181 break;
1182 case scaled_math_style:
1183 {
1184 halfword noad = tex_new_node(style_node, scaled_math_style);
1185 style_scale(noad) = tex_scan_integer(0, NULL);
1186
1187 cur_list.math_scale = style_scale(noad);
1188 tex_tail_append(noad);
1189 }
1190 break;
1191 default:
1192 if (is_valid_math_style(cur_chr)) {
1193 halfword noad = tex_new_node(style_node, (quarterword) cur_chr);
1194 cur_list.math_style = cur_chr;
1195 tex_tail_append(noad);
1196 } else {
1197
1198 }
1199 }
1200}
1201
1202
1218
1219static void tex_aux_display_choice_noad (halfword n, int threshold, int max);
1220static void tex_aux_display_parameter_node (halfword n);
1221static void tex_aux_display_simple_noad (halfword n, int threshold, int max);
1222static void tex_aux_display_radical_noad (halfword n, int threshold, int max);
1223static void tex_aux_display_accent_noad (halfword n, int threshold, int max);
1224static void tex_aux_display_fence_noad (halfword n, int threshold, int max);
1225static void tex_aux_display_fraction_noad (halfword n, int threshold, int max);
1226
1227static void tex_aux_print_fam_and_char(halfword n)
1228{
1229 tex_print_format(", family %x, character %x, original %x", kernel_math_family(n), kernel_math_character(n));
1230 tex_aux_show_dictionary(n, kernel_math_properties(n), kernel_math_group(n), kernel_math_index(n), tex_fam_fnt(kernel_math_family(n), 0), kernel_math_character(n));
1231}
1232
1233int tex_show_math_node(halfword n, int threshold, int max)
1234{
1235 switch (node_type(n)) {
1236 case style_node:
1237
1238 break;
1239 case choice_node:
1240 tex_aux_display_choice_noad(n, threshold, max);
1241 break;
1242 case parameter_node:
1243 tex_aux_display_parameter_node(n);
1244 break;
1245 case simple_noad:
1246 tex_aux_display_simple_noad(n, threshold, max);
1247 break;
1248 case radical_noad:
1249 tex_aux_display_radical_noad(n, threshold, max);
1250 break;
1251 case accent_noad:
1252 tex_aux_display_accent_noad(n, threshold, max);
1253 break;
1254 case fence_noad:
1255 tex_aux_display_fence_noad(n, threshold, max);
1256 break;
1257 case fraction_noad:
1258 tex_aux_display_fraction_noad(n, threshold, max);
1259 break;
1260 case math_text_char_node:
1261 case math_char_node:
1262 tex_aux_print_fam_and_char(n);
1263 break;
1264 case sub_box_node:
1265 tex_print_node_list(kernel_math_list(n), NULL, threshold, max);
1266 break;
1267 case sub_mlist_node:
1268 if (kernel_math_list(n)) {
1269 tex_print_node_list(kernel_math_list(n), NULL, threshold, max);
1270 } else {
1271 tex_print_str(", empty");
1272 }
1273 break;
1274 default:
1275 return 0;
1276 }
1277 return 1;
1278}
1279
1280inline static halfword tex_aux_valid_delimiter(halfword d)
1281{
1282 return (d && (delimiter_small_family(d) || delimiter_small_character(d) || delimiter_large_family(d) || delimiter_large_character(d))) ? d : null;
1283}
1284
1285static void tex_aux_print_delimiter(halfword d)
1286{
1287 if (delimiter_small_family(d) < 0) {
1288
1289 tex_print_int(-1);
1290 } else if (delimiter_small_family(d) < 16 && delimiter_large_family(d) < 16 && delimiter_small_character(d) < 256 && delimiter_large_character(d) < 256) {
1291
1292 int a = delimiter_small_family(d) * 256 + delimiter_small_character(d);
1293 a = a * 0x1000 + delimiter_large_family(d) * 256 + delimiter_large_character(d);
1294 tex_print_format(", code %x", a);
1295 } else if ((delimiter_large_family(d) == 0 && delimiter_large_character(d) == 0) || delimiter_small_character(d) > 65535 || delimiter_large_character(d) > 65535) {
1296
1297 tex_print_format(", family %x, character %x", delimiter_small_family(d), delimiter_small_character(d));
1298 }
1299}
1300
1301
1309
1310static void tex_aux_display_common_noad(halfword n, int threshold, int max)
1311{
1312 tex_print_node_list(noad_nucleus(n), "nucleus", threshold, max);
1313 tex_print_node_list(noad_supscr(n), "superscript", threshold, max);
1314 tex_print_node_list(noad_subscr(n), "subscript", threshold, max);
1315 tex_print_node_list(noad_supprescr(n), "superprescript", threshold, max);
1316 tex_print_node_list(noad_subprescr(n), "subprescript", threshold, max);
1317 tex_print_node_list(noad_prime(n), "primescript", threshold, max);
1318 tex_print_node_list(noad_new_hlist(n), "newhlist", threshold, max);
1319}
1320
1321static void tex_aux_display_parameter_node(halfword n)
1322{
1323 tex_print_format(", id %i, style %i", parameter_name(n), parameter_style(n));
1324}
1325
1326static void tex_aux_display_choice_noad(halfword n, int threshold, int max)
1327{
1328 switch (node_subtype(n)) {
1329 case normal_choice_subtype:
1330 tex_print_node_list(choice_display_mlist(n), "display", threshold, max);
1331 tex_print_node_list(choice_text_mlist(n), "text", threshold, max);
1332 tex_print_node_list(choice_script_mlist(n), "script", threshold, max);
1333 tex_print_node_list(choice_script_script_mlist(n), "scriptscript", threshold, max);
1334 break;
1335 case discretionary_choice_subtype:
1336 tex_print_format(", class %i", choice_class(n));
1337 tex_print_node_list(choice_pre_break(n), "pre", threshold, max);
1338 tex_print_node_list(choice_post_break(n), "post", threshold, max);
1339 tex_print_node_list(choice_no_break(n), "replace", threshold, max);
1340 break;
1341 }
1342}
1343
1344static void tex_aux_display_simple_noad(halfword n, int threshold, int max)
1345{
1346 if (noad_source(n)) {
1347 tex_print_format(", source %i", noad_source(n));
1348 }
1349 tex_aux_display_common_noad(n, threshold, max);
1350}
1351
1352static void tex_aux_display_radical_noad(halfword n, int threshold, int max)
1353{
1354 if (noad_width(n)) {
1355 tex_print_format(", width %p", noad_width(n));
1356 }
1357 if (radical_height(n)) {
1358 tex_print_format(", height %p", radical_height(n));
1359 }
1360 if (radical_depth(n)) {
1361 tex_print_format(", depth %p", radical_depth(n));
1362 }
1363 if (radical_size(n)) {
1364 tex_print_format(", size %i", radical_size(n));
1365 }
1366 if (noad_source(n) != 0) {
1367 tex_print_format(", source %i", noad_source(n));
1368 }
1369 if (noad_options(n)) {
1370 tex_print_format(", options %x", noad_options(n));
1371 }
1372 if (radical_left_delimiter(n)) {
1373 tex_print_str(", left");
1374 tex_aux_print_delimiter(radical_left_delimiter(n));
1375 }
1376 if (radical_right_delimiter(n)) {
1377 tex_print_str(", right");
1378 tex_aux_print_delimiter(radical_right_delimiter(n));
1379 }
1380 if (radical_degree(n)) {
1381 tex_print_node_list(radical_degree(n), "degree", threshold, max);
1382 }
1383 tex_aux_display_common_noad(n, threshold, max);
1384}
1385
1386static void tex_aux_display_accent_noad(halfword n, int threshold, int max)
1387{
1388 halfword top_char = accent_top_character(n);
1389 halfword bottom_char = accent_bottom_character(n);
1390 halfword fraction = accent_fraction(n);
1391 if (fraction) {
1392 tex_print_str(", fraction ");
1393 tex_print_int(fraction);
1394 }
1395 switch (node_subtype(n)) {
1396 case bothflexible_accent_subtype:
1397 if (top_char) {
1398 tex_print_str(", top ");
1399 tex_aux_print_fam_and_char(top_char);
1400 }
1401 if (bottom_char) {
1402 tex_print_str(", bottom ");
1403 tex_aux_print_fam_and_char(bottom_char);
1404 }
1405 if (! (top_char || bottom_char)) {
1406 tex_print_str(", overlay ");
1407 tex_aux_print_fam_and_char(accent_middle_character(n));
1408 }
1409 break;
1410 case fixedtop_accent_subtype:
1411 if (top_char) {
1412 tex_print_str(", fixed top ");
1413 tex_aux_print_fam_and_char(top_char);
1414 }
1415 if (bottom_char) {
1416 tex_print_str(", bottom ");
1417 tex_aux_print_fam_and_char(bottom_char);
1418 }
1419 break;
1420 case fixedbottom_accent_subtype:
1421 if (top_char) {
1422 tex_print_str(", top ");
1423 tex_aux_print_fam_and_char(top_char);
1424 }
1425 if (bottom_char) {
1426 tex_print_str(", fixed bottom ");
1427 tex_aux_print_fam_and_char(bottom_char);
1428 }
1429 break;
1430 case fixedboth_accent_subtype:
1431 if (top_char) {
1432 tex_print_str(", fixed top ");
1433 tex_aux_print_fam_and_char(top_char);
1434 }
1435 if (bottom_char) {
1436 tex_print_str(", fixed bottom ");
1437 tex_aux_print_fam_and_char(bottom_char);
1438 }
1439 break;
1440 }
1441 tex_aux_display_common_noad(n, threshold, max);
1442}
1443
1444static void tex_aux_display_fence_noad(halfword n, int threshold, int max)
1445{
1446 if (noad_height(n)) {
1447 tex_print_format(", height %p", noad_height(n));
1448 }
1449 if (noad_depth(n)) {
1450 tex_print_format(", depth %p", noad_depth(n));
1451 }
1452 if (fence_top_overshoot(n)) {
1453 tex_print_format(", top %p", fence_top_overshoot(n));
1454 }
1455 if (fence_bottom_overshoot(n)) {
1456 tex_print_format(", top %p", fence_bottom_overshoot(n));
1457 }
1458 if (get_noad_main_class(n) != unset_noad_class) {
1459 tex_print_format(", class %i", get_noad_main_class(n));
1460 }
1461 if (get_noad_left_class(n) != unset_noad_class) {
1462 tex_print_format(", leftclass %i", get_noad_left_class(n));
1463 }
1464 if (get_noad_right_class(n) != unset_noad_class) {
1465 tex_print_format(", rightclass %i", get_noad_right_class(n));
1466 }
1467 if (noad_source(n) != 0) {
1468 tex_print_format(", source %i", noad_source(n));
1469 }
1470 if (noad_options(n)) {
1471 tex_print_format(", options %x", noad_options(n));
1472 }
1473 tex_aux_print_delimiter(fence_delimiter_list(n));
1474 tex_print_node_list(fence_delimiter_top(n), "top", threshold, max);
1475 tex_print_node_list(fence_delimiter_bottom(n), "bottom", threshold, max);
1476}
1477
1478static void tex_aux_display_fraction_noad(halfword n, int threshold, int max)
1479{
1480 halfword leftdelimiter = tex_aux_valid_delimiter(fraction_left_delimiter(n));
1481 halfword rightdelimiter = tex_aux_valid_delimiter(fraction_right_delimiter(n));
1482 tex_print_str(", thickness ");
1483 if (fraction_rule_thickness(n) == preset_rule_thickness) {
1484 tex_print_str("default");
1485 } else {
1486 tex_print_dimension(fraction_rule_thickness(n), pt_unit);
1487 }
1488 if (leftdelimiter) {
1489 tex_print_str(", leftdelimiter ");
1490 tex_aux_print_delimiter(leftdelimiter);
1491 }
1492 if (rightdelimiter) {
1493 tex_print_str(", rightdelimiter ");
1494 tex_aux_print_delimiter(rightdelimiter);
1495 }
1496 if (noad_source(n) != 0) {
1497 tex_print_str(", source ");
1498 tex_print_int(noad_source(n));
1499 }
1500 if (noad_options(n)) {
1501 tex_print_str(", options ");
1502 tex_print_qhex(noad_options(n));
1503 }
1504 tex_print_node_list(fraction_numerator(n), "numerator", threshold, max);
1505 tex_print_node_list(fraction_denominator(n), "denominator", threshold, max);
1506}
1507
1508
1519
1520static void tex_aux_new_save_level_math(quarterword group)
1521{
1522 halfword direction = math_direction_par;
1523 saved_math_initialize();
1524 saved_math_direction = lmt_dir_state.text_dir_ptr;
1525 lmt_save_state.save_stack_data.ptr += saved_math_n_of_records;
1526 lmt_dir_state.text_dir_ptr = tex_new_dir(normal_dir_subtype, direction);
1527 tex_new_save_level(group);
1528 update_tex_par_direction(direction);
1529 update_tex_text_direction(direction);
1530}
1531
1532static void tex_aux_push_math(quarterword group, int style)
1533{
1534 if (math_direction_par != text_direction_par) {
1535 cur_list.math_dir = 1;
1536 }
1537 cur_list.math_begin = math_begin_class_par;
1538 cur_list.math_end = math_end_class_par;
1539 cur_list.math_main_style = style;
1540 tex_push_nest();
1541 cur_list.mode = inline_mmode;
1542 cur_list.incomplete_noad = null;
1543 cur_list.math_style = style;
1544 cur_list.math_scale = internal_math_scale_par;
1545 tex_aux_new_save_level_math(group);
1546 update_tex_math_left_class(unset_noad_class);
1547 update_tex_math_right_class(unset_noad_class);
1548}
1549
1550static void tex_aux_enter_inline_math(int style)
1551{
1552 tex_aux_push_math(math_inline_group, style);
1553 update_tex_family(0, unused_math_family);
1554 if (every_math_par) {
1555 tex_begin_token_list(every_math_par, every_math_text);
1556 }
1557}
1558
1559static void tex_aux_enter_display_math(halfword cmd);
1560
1561
1568
1569void tex_run_math_initialize(void)
1570{
1571 switch(cur_cmd) {
1572 case math_shift_cmd:
1573
1574 lmt_nest_state.math_mode = 1;
1575 tex_get_token();
1576 lmt_nest_state.math_mode = 0;
1577 if (cur_cmd == math_shift_cmd && cur_list.mode > nomode) {
1578 tex_aux_enter_display_math(math_shift_cmd);
1579 } else {
1580 tex_back_input(cur_tok);
1581 tex_aux_enter_inline_math(text_style);
1582 }
1583 break;
1584 case math_shift_cs_cmd:
1585 if (cur_chr == begin_math_mode_code) {
1586 tex_aux_enter_inline_math(tex_scan_math_style_identifier(0, 0));
1587 } else if (cur_chr == begin_display_math_code && cur_list.mode > nomode) {
1588 tex_aux_enter_display_math(begin_display_math_code);
1589 } else if (cur_chr == begin_inline_math_code) {
1590 tex_aux_enter_inline_math(text_style);
1591 } else {
1592 tex_you_cant_error("math shift 1");
1593 }
1594 break;
1595 default:
1596 tex_you_cant_error("math shift 2");
1597 break;
1598 }
1599}
1600
1601
1609
1610void tex_run_math_equation_number(void) {
1611 if (cur_group == math_display_group) {
1612 saved_equation_number_initialize();
1613 saved_equation_number_location = cur_chr;
1614 lmt_save_state.save_stack_data.ptr += saved_equation_number_n_of_records;
1615 tex_aux_enter_inline_math(text_style);
1616 } else {
1617 tex_off_save();
1618 }
1619}
1620
1621
1636
1637void tex_run_math_left_brace(void)
1638{
1639 if (math_grouping_mode_par) {
1640
1641 tex_new_save_level(math_simple_group);
1642 update_tex_internal_math_style(cur_mode == mmode ? cur_list.math_style : -1);
1643 update_tex_internal_math_scale(cur_mode == mmode ? cur_list.math_scale : -1);
1644 } else {
1645 halfword q = tex_new_node(math_char_node, 0);
1646 halfword n = tex_new_node(simple_noad, ordinary_noad_subtype);
1647 tex_tail_append(n);
1648 noad_nucleus(n) = q;
1649 tex_back_input(cur_tok);
1650 tex_aux_scan_math(q, cur_list.math_style, 0, 0, 0, 0, unset_noad_class, unset_noad_class);
1651 }
1652}
1653
1654
1666
1667static int tex_aux_pre_math_par_direction(void)
1668{
1669 return tex_located_save_value(internal_integer_location(par_direction_code));
1670}
1671
1672
1679
1680static void tex_aux_enter_display_math(halfword cmd)
1681{
1682 if (math_display_mode_par) {
1683 tex_aux_push_math(math_inline_group, display_style);
1684 cur_list.math_mode = cmd;
1685 cur_list.mode = inline_mmode;
1686 update_tex_family(0, unused_math_family);
1687 if (every_display_par) {
1688 tex_begin_token_list(every_display_par, every_display_text);
1689 }
1690 } else {
1691
1692 scaled size;
1693
1694 scaled width;
1695
1696 scaled indent;
1697
1700 if (cur_list.head == cur_list.tail || (node_next(cur_list.head) == cur_list.tail && node_type(cur_list.tail) == par_node && ! node_next(cur_list.tail))) {
1701 if (node_next(cur_list.head) == cur_list.tail) {
1702
1706 tex_flush_node(cur_list.tail);
1707
1708 }
1709 tex_pop_nest();
1710 size = - max_dimension;
1711 } else {
1712 tex_line_break(1, math_display_group);
1713
1714 size = tex_actual_box_width(lmt_linebreak_state.just_box, scaledround((tex_get_font_em_width(cur_font_par) / scaling_factor_double) * math_pre_display_gap_factor_par));
1715 }
1716
1721 if (par_shape_par) {
1722
1723 int n = tex_get_specification_count(par_shape_par);
1724 if (n > 0) {
1725 if (cur_list.prev_graf + 2 < n) {
1726 n = cur_list.prev_graf + 2;
1727 }
1728 indent = tex_get_specification_indent(par_shape_par, n) ;
1729 width = tex_get_specification_width(par_shape_par, n);
1730 indent = swap_parshape_indent(pre_display_direction_par, indent, width);
1731 } else {
1732 width = hsize_par;
1733 indent = 0;
1734 }
1735 } else if ((hang_indent_par != 0) && (((hang_after_par >= 0) && (cur_list.prev_graf + 2 > hang_after_par)) || (cur_list.prev_graf + 1 < -hang_after_par))) {
1736 halfword hangindent = swap_hang_indent(pre_display_direction_par, hang_indent_par);
1737 width = hsize_par - abs(hangindent);
1738 indent = hangindent > 0 ? hangindent : 0;
1739 } else {
1740 width = hsize_par;
1741 indent = 0;
1742 }
1743 tex_aux_push_math(math_display_group, display_style);
1744 cur_list.mode = mmode;
1745 update_tex_family(0, unused_math_family);
1746 update_tex_pre_display_size(size);
1747 update_tex_display_width(width);
1748 update_tex_display_indent(indent);
1749 update_tex_pre_display_direction(tex_aux_pre_math_par_direction());
1750 if (every_display_par) {
1751 tex_begin_token_list(every_display_par, every_display_text);
1752 }
1753 if (lmt_nest_state.nest_data.ptr == 1) {
1754 tex_build_page(before_display_page_context, 0);
1755 }
1756 }
1757}
1758
1759
1766
1767static delcodeval tex_aux_scan_extdef_del_code(int extcode, int doclass)
1768{
1769 delcodeval d = tex_no_del_code();
1770 switch (extcode) {
1771 case tex_mathcode:
1772
1773 {
1774 halfword v = tex_scan_integer(0, NULL);
1775
1776 if (doclass) {
1777 d.small.class_value = (short) (v / 0x1000000);
1778 v = (v & 0xFFFFFF);
1779 }
1780 if (v > 0xFFFFFF) {
1781 tex_handle_error(
1782 normal_error_type,
1783 "Invalid delimiter code",
1784 "I'm going to use 0 instead of that illegal code value."
1785 );
1786 v = 0;
1787 }
1788 d.small.family_value = (short) (v / 0x100000);
1789 d.small.character_value = (v % 0x100000) / 0x1000;
1790 d.large.family_value = (short) ((v & 0xFFF) / 0x100);
1791 d.large.character_value = (v % 0x100);
1792
1793 d.small.character_value = math_character_part(d.small.character_value);
1794 d.large.character_value = math_character_part(d.large.character_value);
1795 }
1796 break;
1797 case umath_mathcode:
1798
1799 {
1800 if (doclass) {
1801 d.small.class_value = (short) tex_scan_math_class_number(0);
1802 }
1803 d.small.family_value = (short) tex_scan_math_family_number();
1804 d.small.character_value = tex_scan_math_char_number();
1805 if (d.small.family_value < 0 || d.small.family_value > max_math_family_index) {
1806 tex_handle_error(
1807 normal_error_type,
1808 "Invalid delimiter family",
1809 "I'm going to use family 0 instead."
1810 );
1811 d.small.family_value = 0;
1812 d.small.character_value = 0;
1813 }
1814 }
1815 break;
1816 default:
1817
1818 tex_confusion("unknown extcode, case 1");
1819 break;
1820 }
1821 d.large.class_value = d.small.class_value;
1822 return d;
1823}
1824
1825void tex_scan_extdef_del_code(int level, int extcode)
1826{
1827 delcodeval d;
1828 int chr = tex_scan_char_number(0);
1829 tex_scan_optional_equals();
1830 d = tex_aux_scan_extdef_del_code(extcode, 0);
1831 tex_set_del_code(chr, d, (quarterword) level);
1832}
1833
1834mathdictval tex_scan_mathdict(void)
1835{
1836 mathdictval d = tex_no_dict_code();
1837 d.properties = (unsigned short) tex_scan_math_properties_number();
1838 d.group = (unsigned short) tex_scan_math_group_number();
1839 d.index = (unsigned int) tex_scan_math_index_number();
1840 return d;
1841}
1842
1843
1851
1852mathcodeval tex_scan_mathchar(int extcode)
1853{
1854 mathcodeval d = tex_no_math_code();
1855 switch (extcode) {
1856 case tex_mathcode:
1857
1858 {
1859 halfword v = tex_scan_integer(0, NULL);
1860 if (v >= 0) {
1861 if (v > 0xFFFF) {
1862 v = 0xFFFF;
1863 }
1864 d.class_value = (short) math_old_class_part(v);
1865 d.family_value = (short) math_old_family_part(v);
1866 d.character_value = math_old_character_part(v);
1867 }
1868 }
1869 break;
1870 case umath_mathcode:
1871
1872 {
1873 d.class_value = (short) tex_scan_math_class_number(0);
1874 d.family_value = (short) tex_scan_math_family_number();
1875 d.character_value = tex_scan_math_char_number();
1876 }
1877 break;
1878 default:
1879 tex_confusion("unknown extcode, case 2");
1880 break;
1881 }
1882 if (d.class_value < 0 || d.character_value > max_math_character_code || d.class_value > max_math_class_code || d.family_value > max_math_family_index) {
1883 tex_handle_error(
1884 normal_error_type,
1885 "Invalid math code",
1886 "I'm going to use 0 instead of that illegal code value."
1887 );
1888 d.class_value = 0;
1889 d.family_value = 0;
1890 d.character_value = 0;
1891 }
1892 return d;
1893}
1894
1895halfword tex_new_math_spec(mathcodeval m, quarterword code)
1896{
1897 halfword s = tex_new_node(math_spec_node, code);
1898 math_spec_class(s) = (singleword) m.class_value;
1899 math_spec_family(s) = (singleword) m.family_value;
1900 math_spec_character(s) = m.character_value;
1901 return s;
1902}
1903
1904halfword tex_new_math_dict_spec(mathdictval d, mathcodeval m, quarterword code)
1905{
1906 halfword s = tex_new_node(math_spec_node, code);
1907 math_spec_class(s) = (singleword) m.class_value;
1908 math_spec_family(s) = (singleword) m.family_value;
1909 math_spec_character(s) = m.character_value;
1910 math_spec_properties(s) = (quarterword) d.properties;
1911 math_spec_group(s) = (quarterword) d.group;
1912 math_spec_index(s) = d.index;
1913 return s;
1914}
1915
1916mathcodeval tex_get_math_spec(halfword s)
1917{
1918 mathcodeval m = tex_no_math_code();
1919 if (s) {
1920 m.class_value = math_spec_class(s);
1921 m.family_value = math_spec_family(s);
1922 m.character_value = math_spec_character(s);
1923 }
1924 return m;
1925}
1926
1927mathdictval tex_get_math_dict(halfword s)
1928{
1929 mathdictval d = tex_no_dict_code();
1930 if (s) {
1931 d.properties = math_spec_properties(s);
1932 d.group = math_spec_group(s);
1933 d.index = math_spec_index(s);
1934 }
1935 return d;
1936}
1937
1938halfword tex_scan_math_spec(int optional_equal)
1939{
1940 mathcodeval m;
1941 if (optional_equal) {
1942 tex_scan_optional_equals();
1943 }
1944 m = tex_scan_mathchar(umath_mathcode);
1945 return tex_new_math_spec(m, mathspec_mathcode);
1946}
1947
1948void tex_scan_extdef_math_code(int level, int extcode)
1949{
1950 mathcodeval d;
1951 int chr = tex_scan_char_number(0);
1952 tex_scan_optional_equals();
1953 d = tex_scan_mathchar(extcode);
1954 tex_set_math_code(chr, d, (quarterword) level);
1955}
1956
1957
1958
1959mathcodeval tex_scan_delimiter_as_mathchar(int extcode)
1960{
1961 delcodeval dval = tex_aux_scan_extdef_del_code(extcode, 1);
1962 return dval.small;
1963}
1964
1965
1979
1980
1983
1984static void tex_aux_report_active(int where, const char *what, int code, int character)
1985{
1986 tex_begin_diagnostic();
1987 tex_print_format("[active: location %i, %s, code %i, char %i]",where, what, code, character);
1988 tex_end_diagnostic();
1989}
1990
1991static void tex_aux_append_math_char(mathcodeval mval, mathdictval dval, int automatic);
1992
1993int tex_check_active_math_char(int character)
1994{
1995 halfword code = tex_get_am_code(character);
1996 if (code) {
1997 switch (code) {
1998 case alignment_tab_cmd:
1999 case superscript_cmd:
2000 case subscript_cmd:
2001 case letter_cmd:
2002 case other_char_cmd:
2003 case active_char_cmd:
2004 cur_cmd = code;
2005 cur_chr = character;
2006 cur_tok = token_val(cur_cmd, cur_chr);
2007 if (tracing_commands_par >= 4) {
2008 switch (code) {
2009 case alignment_tab_cmd:
2010 case superscript_cmd:
2011 case subscript_cmd:
2012 tex_aux_report_active(4, "control", code, character);
2013 break;
2014 case letter_cmd:
2015 case other_char_cmd:
2016 tex_aux_report_active(4, "inject", code, character);
2017 break;
2018 case active_char_cmd:
2019 tex_aux_report_active(4, "active", code, character);
2020 break;
2021 }
2022 }
2023 return 1;
2024 default:
2025 if (tracing_commands_par >= 4) {
2026 tex_aux_report_active(4, "ignore", code, character);
2027 }
2028 return 1;
2029 }
2030 } else {
2031 return 0;
2032 }
2033}
2034
2035int tex_pass_active_math_char(int character)
2036{
2037 halfword code = tex_get_am_code(character);
2038 if (code) {
2039 return 1;
2040 } else {
2041 return 0;
2042 }
2043}
2044
2045static int tex_aux_scan_active_math_char(mathcodeval *mval, int where)
2046{
2047 halfword character = mval->character_value;
2048 halfword code = tex_get_am_code(character);
2049 if (code) {
2050 switch (code) {
2051 case alignment_tab_cmd:
2052 case superscript_cmd:
2053 case subscript_cmd:
2054 cur_cmd = code;
2055 cur_chr = character;
2056 cur_tok = token_val(cur_cmd, cur_chr);
2057 tex_back_input(cur_tok);
2058 if (tracing_commands_par >= 4) {
2059 tex_aux_report_active(where, "control", code, character);
2060 }
2061 return 1;
2062 case letter_cmd:
2063 case other_char_cmd:
2064 cur_cmd = code;
2065 cur_chr = character;
2066 cur_tok = token_val(cur_cmd, cur_chr);
2067 if (tracing_commands_par >= 4) {
2068 tex_aux_report_active(where, "inject", code, character);
2069 }
2070 return 0;
2071 case active_char_cmd:
2072
2076 tex_set_am_code(character, other_char_cmd, cur_level);
2077 cur_cs = tex_active_to_cs(cur_chr, 1);
2078 cur_cmd = eq_type(cur_cs);
2079 cur_chr = eq_value(cur_cs);
2080 tex_x_token();
2081 tex_back_input(cur_tok);
2082 if (tracing_commands_par >= 4) {
2083 tex_aux_report_active(where, "active", code, character);
2084 }
2085 return 1;
2086 default:
2087 if (tracing_commands_par >= 4) {
2088 tex_aux_report_active(where, "ignore", code, character);
2089 }
2090 return 1;
2091 }
2092 } else if (mval->class_value == active_math_class_value) {
2093
2094 cur_cs = tex_active_to_cs(cur_chr, 1);
2095 cur_cmd = eq_type(cur_cs);
2096 cur_chr = eq_value(cur_cs);
2097 tex_x_token();
2098 tex_back_input(cur_tok);
2099 if (tracing_commands_par >= 4) {
2100 tex_aux_report_active(where, "active", code, character);
2101 }
2102 return 1;
2103 } else {
2104
2105
2106
2107 return 0;
2108 }
2109}
2110
2111static int tex_aux_scan_math(halfword target, halfword style, int usetextfont, halfword toks, halfword toks_text, int nocomponent, halfword cls, halfword all)
2112{
2113 mathcodeval mval = tex_no_math_code();
2114 mathdictval dval = tex_no_dict_code();
2115 lmt_math_state.last_atom = cls;
2116 RESTART:
2117 do {
2118 tex_get_x_token();
2119 } while (cur_cmd == spacer_cmd || cur_cmd == relax_cmd);
2120
2121 switch (cur_cmd) {
2122 case char_number_cmd:
2123
2124 cur_chr = tex_scan_char_number(0);
2125
2126 case letter_cmd:
2127 case other_char_cmd:
2128 case char_given_cmd:
2129 mval = tex_get_math_code(cur_chr);
2130 if (tex_aux_scan_active_math_char(&mval, 1)) {
2131 goto RESTART;
2132 } else {
2133 dval = tex_fake_math_dict(mval.character_value);
2134 break;
2135 }
2136
2137
2138
2139
2140
2141 case math_char_number_cmd:
2142 switch (cur_chr) {
2143 case math_char_number_code:
2144 mval = tex_scan_mathchar(tex_mathcode);
2145 break;
2146 case math_xchar_number_code:
2147 mval = tex_scan_mathchar(umath_mathcode);
2148 break;
2149 default:
2150 tex_confusion("scan math char, case 1");
2151 break;
2152 }
2153 dval = tex_fake_math_dict(mval.character_value);
2154 break;
2155 case mathspec_cmd:
2156 mval = tex_get_math_spec(cur_chr);
2157 dval = tex_get_math_dict(cur_chr);
2158 break;
2159 case delimiter_number_cmd:
2160 switch (cur_chr) {
2161 case math_delimiter_code:
2162 mval = tex_scan_delimiter_as_mathchar(tex_mathcode);
2163 break;
2164 case math_udelimiter_code:
2165 mval = tex_scan_delimiter_as_mathchar(umath_mathcode);
2166 break;
2167 default:
2168 tex_confusion("scan math char, case 2");
2169 break;
2170 }
2171 break;
2172 case math_component_cmd:
2173 if (nocomponent) {
2174 goto DEFAULT;
2175 } else {
2176 saved_math_group_initialize();
2177 saved_math_group_all_class = unset_noad_class;
2178 saved_math_group_pointer = target;
2179 lmt_save_state.save_stack_data.ptr += saved_math_group_n_of_records;
2180 tex_aux_push_math(math_component_group, style);
2181 if (usetextfont) {
2182 tex_set_math_text_font(style, usetextfont);
2183 }
2184 tex_aux_math_math_component(cur_list.tail, 0);
2185 tex_finish_math_group();
2186 return 1;
2187 }
2188 case left_brace_cmd:
2189 goto SCAN_SUBFORMULA;
2190 default:
2191
2195 DEFAULT:
2196 tex_back_input(cur_tok);
2197 tex_scan_left_brace();
2198 SCAN_SUBFORMULA:
2199 saved_math_group_initialize();
2200 saved_math_group_all_class = all;
2201 saved_math_group_pointer = target;
2202 lmt_save_state.save_stack_data.ptr += saved_math_group_n_of_records;
2203 tex_aux_push_math(math_group, style);
2204 toks = every_math_atom_par;
2205 toks_text = every_math_atom_text;
2206 if (toks) {
2207 tex_begin_token_list(toks, (quarterword) toks_text);
2208 }
2209 if (usetextfont) {
2210 tex_set_math_text_font(style, usetextfont);
2211 }
2212 return 1;
2213 }
2214 node_type(target) = math_char_node;
2215 if (glyph_options_par & glyph_option_no_italic_correction) {
2216 math_kernel_node_set_option(target, math_kernel_no_italic_correction);
2217 }
2218 if (glyph_options_par & glyph_option_no_left_kern) {
2219 math_kernel_node_set_option(target, math_kernel_no_left_pair_kern);
2220 }
2221 if (glyph_options_par & glyph_option_no_right_kern) {
2222 math_kernel_node_set_option(target, math_kernel_no_right_pair_kern);
2223 }
2224 tex_aux_set_math_char(target, &mval, &dval);
2225 return 0;
2226}
2227
2228
2235
2236static void tex_aux_append_math_accent(mathcodeval mval, mathdictval dval)
2237{
2238 halfword accent = tex_new_node(accent_noad, bothflexible_accent_subtype);
2239 quarterword subtype = ordinary_noad_subtype;
2240 tex_tail_append(accent);
2241 if (! (mval.character_value == 0 && mval.family_value == 0)) {
2242 halfword q = tex_new_node(math_char_node, 0);
2243 subtype = tex_aux_set_math_char(q, &mval, &dval);
2244 accent_top_character(accent) = q;
2245 }
2246 {
2247 halfword q = tex_new_node(math_char_node, subtype);
2248 noad_nucleus(accent) = q;
2249 tex_aux_scan_math(q, tex_math_style_variant(cur_list.math_style, math_parameter_accent_variant), 0, 0, 0, 0, unset_noad_class, unset_noad_class);
2250 }
2251}
2252
2253
2258
2259static void tex_aux_append_math_fence(halfword fence, quarterword mathclass)
2260{
2261 switch (mathclass) {
2262 case open_noad_subtype:
2263 {
2264 tex_aux_push_math(math_fence_group, cur_list.math_style);
2265 node_subtype(fence) = left_fence_side;
2266 node_next(cur_list.head) = fence;
2267 cur_list.tail = fence;
2268 cur_list.delimiter = fence;
2269 }
2270 break;
2271 case close_noad_subtype:
2272 {
2273 halfword q = tex_aux_finish_math_list(fence);
2274 halfword n = tex_new_node(simple_noad, fenced_noad_subtype);
2275 halfword l = tex_new_node(sub_mlist_node, 0);
2276 tex_aux_unsave_math();
2277 tex_tail_append(n);
2278 node_subtype(fence) = right_fence_side;
2279 noad_nucleus(n) = l;
2280 noad_options(n) |= noad_option_unpack_list;
2281 kernel_math_list(noad_nucleus(n)) = q;
2282 }
2283 break;
2284 case middle_noad_subtype:
2285 {
2286 halfword q = tex_aux_finish_math_list(fence);
2287 tex_aux_unsave_math();
2288 tex_aux_push_math(math_fence_group, cur_list.math_style);
2289 node_subtype(fence) = middle_fence_side;
2290 node_next(cur_list.head) = q;
2291 cur_list.tail = fence;
2292 cur_list.delimiter = fence;
2293 }
2294 break;
2295 }
2296}
2297
2298static void tex_aux_append_math_fence_val(mathcodeval mval, mathdictval dval, quarterword mathclass)
2299{
2300 halfword fence = tex_new_node(fence_noad, middle_fence_side);
2301 halfword delimiter = tex_new_node(delimiter_node, mval.class_value);
2302 (void) dval;
2303 fence_delimiter_list(fence) = delimiter;
2304 delimiter_small_family(delimiter) = mval.family_value;
2305 delimiter_small_character(delimiter) = mval.character_value;
2306 delimiter_large_family(delimiter) = mval.family_value;
2307 delimiter_large_character(delimiter) = mval.character_value;
2308 set_noad_classes(fence, mval.class_value);
2309
2310 noad_options(fence) |= noad_option_no_check;
2311 if (mathclass == middle_noad_subtype && cur_group != math_fence_group) {
2312 tex_aux_append_math_fence_val(tex_no_math_code(), tex_no_dict_code(), open_noad_subtype);
2313 }
2314 tex_aux_append_math_fence(fence, mathclass);
2315}
2316
2317static void tex_aux_append_math_char(mathcodeval mval, mathdictval dval, int automatic)
2318{
2319 if (tex_aux_scan_active_math_char(&mval, 2)) {
2320 return;
2321 } else {
2322 if (automatic && tex_math_has_class_option(mval.class_value, auto_inject_class_option)) {
2323 switch (mval.class_value) {
2324 case accent_noad_subtype:
2325 tex_aux_append_math_accent(mval, dval);
2326 return;
2327 case open_noad_subtype:
2328 case close_noad_subtype:
2329 case middle_noad_subtype:
2330 tex_aux_append_math_fence_val(mval, dval, mval.class_value);
2331 return;
2332 }
2333 }
2334 {
2335 halfword p = tex_new_node(simple_noad, ordinary_noad_subtype);
2336 halfword q = tex_new_node(math_char_node, 0);
2337 noad_nucleus(p) = q;
2338 if (glyph_options_par & glyph_option_no_italic_correction) {
2339 math_kernel_node_set_option(q, math_kernel_no_italic_correction);
2340 }
2341 node_subtype(p) = tex_aux_set_math_char(q, &mval, &dval);
2342 tex_math_set_scripts_options(p);
2343 tex_tail_append(p);
2344 }
2345 }
2346}
2347
2348
2355
2356static void tex_aux_append_math_char_in_text(mathcodeval mval, mathdictval dval)
2357{
2358 (void) dval;
2359 if (tex_aux_scan_active_math_char(&mval, 3)) {
2360 return;
2361 } else {
2362 halfword p = tex_new_char_node(glyph_character_subtype, tex_fam_fnt(mval.family_value, text_size), mval.character_value, 1);
2363 tex_tail_append(p);
2364 }
2365}
2366
2367void tex_run_math_letter(void)
2368{
2369 tex_aux_append_math_char(tex_get_math_code(cur_chr), tex_fake_math_dict(cur_chr), 1);
2370}
2371
2372void tex_run_math_char_number(void) {
2373
2377 mathcodeval mval = tex_no_math_code();
2378 mathdictval dval = tex_no_dict_code();
2379 cur_chr = tex_scan_char_number(0);
2380 mval.character_value = cur_chr;
2381 mval.family_value = (short) cur_fam_par;
2382
2383 tex_aux_append_math_char(mval, dval, 1);
2384}
2385
2386void tex_run_math_math_spec(void)
2387{
2388 tex_aux_append_math_char(tex_get_math_spec(cur_chr), tex_get_math_dict(cur_chr), 1);
2389}
2390
2391void tex_run_text_math_spec(void)
2392{
2393 tex_aux_append_math_char_in_text(tex_get_math_spec(cur_chr), tex_get_math_dict(cur_chr));
2394}
2395
2396int tex_scan_math_cmd_val(mathcodeval *mval, mathdictval *dval)
2397{
2398 do {
2399 tex_get_x_token();
2400 } while (cur_cmd == spacer_cmd);
2401 switch (cur_cmd) {
2402 case mathspec_cmd:
2403 *mval = tex_get_math_spec(cur_chr);
2404 break;
2405 case math_char_number_cmd:
2406 switch (cur_chr) {
2407 case math_char_number_code:
2408 *mval = tex_scan_mathchar(tex_mathcode);
2409 break;
2410 case math_xchar_number_code:
2411 *mval = tex_scan_mathchar(umath_mathcode);
2412 break;
2413 case math_dictionary_number_code:
2414 *dval = tex_scan_mathdict();
2415 *mval = tex_scan_mathchar(umath_mathcode);
2416 break;
2417 default:
2418
2419 return 0;
2420 }
2421 break;
2422 case delimiter_number_cmd:
2423 switch (cur_chr) {
2424 case math_delimiter_code:
2425 *mval = tex_scan_delimiter_as_mathchar(tex_mathcode);
2426 break;
2427 case math_udelimiter_code:
2428 *mval = tex_scan_delimiter_as_mathchar(umath_mathcode);
2429 break;
2430 default:
2431
2432 return 0;
2433 }
2434 break;
2435
2441
2442
2443
2444
2445 default:
2446
2450 {
2451 halfword n = 0;
2452 tex_back_input(cur_tok);
2453 n = tex_scan_integer(0, NULL);
2454 *mval = tex_mathchar_from_integer(n, umath_mathcode);
2455 }
2456 break;
2457 }
2458 return 1;
2459}
2460
2461int tex_scan_math_code_val(halfword code, mathcodeval *mval, mathdictval *dval)
2462{
2463 switch (code) {
2464 case math_char_number_code:
2465 *mval = tex_scan_mathchar(tex_mathcode);
2466 break;
2467 case math_xchar_number_code:
2468 *mval = tex_scan_mathchar(umath_mathcode);
2469 break;
2470 case math_dictionary_number_code:
2471 *dval = tex_scan_mathdict();
2472 *mval = tex_scan_mathchar(umath_mathcode);
2473 break;
2474 case math_class_number_code:
2475 {
2476 halfword family = cur_fam_par;
2477 halfword mathclass = tex_scan_math_class_number(0);
2478 tex_scan_math_cmd_val(mval, dval);
2479 mval->class_value = (short) mathclass;
2480 mval->family_value = (short) family;
2481 }
2482 break;
2483 default:
2484
2485 tex_back_input(cur_tok);
2486 return 0;
2487 }
2488 return 1;
2489}
2490
2491void tex_run_text_math_char_number(void) {
2492 mathcodeval mval = tex_no_math_code();
2493 mathdictval dval = tex_no_dict_code();
2494 if (tex_scan_math_code_val(cur_chr, &mval, &dval)) {
2495 tex_aux_append_math_char_in_text(mval, dval);
2496 }
2497}
2498
2499void tex_run_math_math_char_number(void) {
2500 mathcodeval mval = tex_no_math_code();
2501 mathdictval dval = tex_no_dict_code();
2502 if (tex_scan_math_code_val(cur_chr, &mval, &dval)) {
2503 tex_aux_append_math_char(mval, dval, 1);
2504 }
2505}
2506
2507void tex_run_math_delimiter_number(void) {
2508 switch (cur_chr) {
2509 case math_delimiter_code:
2510 tex_aux_append_math_char(tex_scan_delimiter_as_mathchar(tex_mathcode), tex_no_dict_code(), 0);
2511 break;
2512 case math_udelimiter_code:
2513 tex_aux_append_math_char(tex_scan_delimiter_as_mathchar(umath_mathcode), tex_no_dict_code(), 0);
2514 break;
2515 }
2516}
2517
2518
2523
2524static void tex_aux_math_math_component(halfword target, int append)
2525{
2526 quarterword subtype = unset_noad_class;
2527 quarterword allclass = unset_noad_class;
2528 halfword style = cur_list.math_style;
2529 int usetextfont = math_atom_no_font_option;
2530 reset_noad_classes(target);
2531 switch (cur_chr) {
2532 case math_component_ordinary_code:
2533 subtype = ordinary_noad_subtype;
2534 break;
2535 case math_component_operator_code:
2536 subtype = operator_noad_subtype;
2537 break;
2538 case math_component_binary_code:
2539 subtype = binary_noad_subtype;
2540 break;
2541 case math_component_relation_code:
2542 subtype = relation_noad_subtype;
2543 break;
2544 case math_component_open_code:
2545 subtype = open_noad_subtype;
2546 break;
2547 case math_component_close_code:
2548 subtype = close_noad_subtype;
2549 break;
2550 case math_component_punctuation_code:
2551 subtype = punctuation_noad_subtype;
2552 break;
2553 case math_component_variable_code:
2554 subtype = variable_noad_subtype;
2555 break;
2556 case math_component_inner_code:
2557 subtype = inner_noad_subtype;
2558 break;
2559 case math_component_under_code:
2560 subtype = under_noad_subtype;
2561 style = tex_math_style_variant(style, math_parameter_under_line_variant);
2562 break;
2563 case math_component_over_code:
2564 subtype = over_noad_subtype;
2565 style = tex_math_style_variant(style, math_parameter_over_line_variant);
2566 break;
2567 case math_component_fraction_code:
2568 subtype = fraction_noad_subtype;
2569 break;
2570 case math_component_radical_code:
2571 subtype = radical_noad_subtype;
2572 break;
2573 case math_component_middle_code:
2574 subtype = middle_noad_subtype;
2575 break;
2576 case math_component_accent_code:
2577 subtype = accent_noad_subtype;
2578 break;
2579 case math_component_fenced_code:
2580 subtype = fenced_noad_subtype;
2581 break;
2582 case math_component_ghost_code:
2583 subtype = ghost_noad_subtype;
2584 break;
2585 case math_component_atom_code:
2586 {
2587 halfword attrlist = null;
2588 while (1) {
2589 switch (tex_scan_character("custnmaolprvCUSTNMAOLPRV", 0, 1, 0)) {
2590 case 'a': case 'A':
2591 switch (tex_scan_character("ltLT", 0, 0, 0)) {
2592 case 't': case 'T':
2593 if (tex_scan_mandate_keyword("attr", 2)) {
2594 attrlist = tex_scan_attribute(attrlist);
2595 }
2596 break;
2597 case 'l': case 'L':
2598 if (tex_scan_mandate_keyword("all", 2)) {
2599 allclass = (quarterword) tex_scan_math_class_number(0);
2600 if (! valid_math_class_code(allclass)) {
2601 allclass = unset_noad_class;
2602 }
2603 }
2604 break;
2605 default:
2606 tex_aux_show_keyword_error("attr|all");
2607 goto DONE;
2608 }
2609 break;
2610 case 'l': case 'L':
2611 switch (tex_scan_character("ieIE", 0, 0, 0)) {
2612 case 'e': case 'E':
2613 if (tex_scan_mandate_keyword("leftclass", 2)) {
2614 halfword c = tex_scan_math_class_number(0);
2615 if (! valid_math_class_code(c)) {
2616 c = ordinary_noad_subtype;
2617 }
2618 set_noad_left_class(target, c);
2619 }
2620 break;
2621 case 'i': case 'I':
2622 if (tex_scan_mandate_keyword("limits", 2)) {
2623 noad_options(target) |= noad_option_limits;
2624 }
2625 break;
2626 default:
2627 tex_aux_show_keyword_error("leftclass|limits");
2628 goto DONE;
2629 }
2630 break;
2631 case 'r': case 'R':
2632 if (tex_scan_mandate_keyword("rightclass", 1)) {
2633 halfword c = tex_scan_math_class_number(0);
2634 if (! valid_math_class_code(c)) {
2635 c = ordinary_noad_subtype;
2636 }
2637 set_noad_right_class(target, c);
2638 }
2639 break;
2640 case 'c': case 'C':
2641 if (tex_scan_mandate_keyword("class", 1)) {
2642 subtype = (quarterword) tex_scan_math_class_number(0);
2643 if (! valid_math_class_code(subtype)) {
2644 subtype = ordinary_noad_subtype;
2645 }
2646 set_noad_main_class(target, subtype);
2647 }
2648 break;
2649 case 'u': case 'U':
2650
2651 if (tex_scan_character("nN", 0, 0, 0)) {
2652 switch (tex_scan_character("prPR", 0, 0, 0)) {
2653 case 'p': case 'P':
2654 if (tex_scan_mandate_keyword("unpack", 3)) {
2655 noad_options(target) |= noad_option_unpack_list;
2656 }
2657 break;
2658 case 'r': case 'R':
2659 if (tex_scan_mandate_keyword("unroll", 3)) {
2660 noad_options(target) |= noad_option_unroll_list;
2661 }
2662 break;
2663 default:
2664 tex_aux_show_keyword_error("unpack|unroll");
2665 goto DONE;
2666 }
2667 }
2668 break;
2669 case 's': case 'S':
2670 switch (tex_scan_character("ioIO", 0, 0, 0)) {
2671 case 'i': case 'I':
2672 if (tex_scan_mandate_keyword("single", 2)) {
2673 noad_options(target) |= noad_option_single;
2674 }
2675 break;
2676 case 'o': case 'O':
2677 if (tex_scan_mandate_keyword("source", 2)) {
2678 noad_source(target) = tex_scan_integer(0, NULL);
2679 }
2680 break;
2681 default:
2682 tex_aux_show_keyword_error("single|source");
2683 goto DONE;
2684 }
2685 break;
2686 case 't': case 'T':
2687 if (tex_scan_mandate_keyword("textfont", 1)) {
2688 usetextfont = math_atom_text_font_option;
2689 }
2690 break;
2691 case 'm': case 'M':
2692 if (tex_scan_mandate_keyword("mathfont", 1)) {
2693 usetextfont = math_atom_math_font_option;
2694 }
2695 break;
2696 case 'n': case 'N':
2697
2698 if (tex_scan_character("oO", 0, 0, 0)) {
2699 switch (tex_scan_character("loLO", 0, 0, 0)) {
2700 case 'l': case 'L':
2701 if (tex_scan_mandate_keyword("nolimits", 3)) {
2702 noad_options(target) |= noad_option_no_limits;
2703 }
2704 break;
2705 case 'o': case 'O':
2706 if (tex_scan_mandate_keyword("nooverflow", 3)) {
2707 noad_options(target) |= noad_option_no_overflow;
2708 }
2709 break;
2710 default:
2711 tex_aux_show_keyword_error("nolimits|nooverflow");
2712 goto DONE;
2713 }
2714 }
2715 break;
2716 case 'o': case 'O':
2717
2718 if (tex_scan_mandate_keyword("options", 1)) {
2719 noad_options(target) = tex_scan_integer(0, NULL);
2720 }
2721 break;
2722 case 'v': case 'V':
2723 if (tex_scan_mandate_keyword("void", 1)) {
2724 noad_options(target) |= noad_option_void;
2725 }
2726 break;
2727 case 'p': case 'P':
2728 if (tex_scan_mandate_keyword("phantom", 1)) {
2729 noad_options(target) |= noad_option_phantom;
2730 }
2731 break;
2732 default:
2733 goto DONE;
2734 }
2735 }
2736 DONE:
2737 if (attrlist) {
2738 tex_attach_attribute_list_attribute(target, attrlist);
2739 }
2740 if (subtype == unset_noad_class) {
2741 if (get_noad_left_class(target) != unset_noad_class && get_noad_right_class(target) != unset_noad_class) {
2742 subtype = ordinary_noad_subtype;
2743 } else {
2744
2745 subtype = (quarterword) tex_scan_math_class_number(0);
2746 }
2747 }
2748 }
2749 break;
2750 }
2751 if (! valid_math_class_code(subtype)) {
2752 subtype = ordinary_noad_subtype;
2753 }
2754
2757 {
2758 halfword content = tex_new_node(math_char_node, 0);
2759 noad_nucleus(target) = content;
2760 node_subtype(target) = subtype;
2761 if (append) {
2762 tex_tail_append(target);
2763 }
2764 tex_aux_scan_math(content, style, usetextfont, 0, 0, 0, subtype, allclass);
2765 }
2766}
2767
2768void tex_run_math_math_component(void)
2769{
2770 halfword n = tex_new_node(simple_noad, ordinary_noad_subtype);
2771 tex_math_set_scripts_options(n);
2772 tex_aux_math_math_component(n, 1);
2773}
2774
2775int tex_is_math_disc(halfword n)
2776{
2777 return
2778 n && node_type(n) == hlist_node && box_list(n) && node_type(box_list(n)) == disc_node &&
2779 disc_class(box_list(n)) != unset_disc_class && ! node_next(box_list(n));
2780}
2781
2782halfword tex_math_make_disc(halfword d)
2783{
2784 halfword q = tex_new_node(sub_mlist_node, 0);
2785 halfword n = tex_new_node(simple_noad, (quarterword) disc_class(d));
2786 kernel_math_list(q) = d;
2787 noad_nucleus(n) = q;
2788 noad_options(n) = noad_option_unpack_list;
2789 return n;
2790}
2791
2792
2796
2797void tex_run_math_modifier(void)
2798{
2799 halfword tail = cur_list.tail;
2800 if (cur_list.head != tail) {
2801 switch (node_type(tail)) {
2802 case simple_noad:
2803 switch (cur_chr) {
2804 case adapt_to_left_modifier_code:
2805 noad_options(tail) = unset_option(noad_options(tail), noad_option_adapt_to_right_size);
2806 noad_options(tail) |= noad_option_adapt_to_left_size;
2807 break;
2808 case adapt_to_right_modifier_code:
2809 noad_options(tail) = unset_option(noad_options(tail), noad_option_adapt_to_left_size);
2810 noad_options(tail) |= noad_option_adapt_to_right_size;
2811 break;
2812
2813 case axis_modifier_code:
2814 noad_options(tail) |= noad_option_axis;
2815 break;
2816 case no_axis_modifier_code:
2817 noad_options(tail) |= noad_option_no_axis;
2818 break;
2819 case phantom_modifier_code:
2820 noad_options(tail) |= noad_option_phantom;
2821 break;
2822 case void_modifier_code:
2823 noad_options(tail) |= noad_option_void;
2824 break;
2825 case source_modifier_code:
2826 if (tex_scan_keyword("nucleus")) {
2827 noad_options(tail) |= noad_option_source_on_nucleus;
2828 }
2829 noad_source(tail) = tex_scan_integer(0, NULL);
2830 break;
2831 case openup_height_modifier_code:
2832 noad_options(tail) |= noad_option_openup_height;
2833 noad_height(tail) = tex_scan_dimension(0, 0, 0, 0, NULL);
2834 break;
2835 case openup_depth_modifier_code:
2836 noad_options(tail) |= noad_option_openup_depth;
2837 noad_depth(tail) = tex_scan_dimension(0, 0, 0, 0, NULL);
2838 break;
2839 case display_limits_modifier_code:
2840 noad_options(tail) = unset_option(noad_options(tail), noad_option_limits | noad_option_no_limits);
2841 break;
2842 case limits_modifier_code:
2843 noad_options(tail) = unset_option(noad_options(tail), noad_option_no_limits);
2844 noad_options(tail) |= noad_option_limits;
2845 break;
2846 case no_limits_modifier_code:
2847 noad_options(tail) = unset_option(noad_options(tail), noad_option_limits);
2848 noad_options(tail) |= noad_option_no_limits;
2849 break;
2850 }
2851 default:
2852 switch (node_type(tail)) {
2853 case accent_noad:
2854 switch (cur_chr) {
2855 case source_modifier_code:
2856 if (tex_scan_keyword("nucleus")) {
2857 noad_options(tail) |= noad_option_source_on_nucleus;
2858 }
2859 noad_source(tail) = tex_scan_integer(0, NULL);
2860 break;
2861 }
2862
2863 }
2864 break;
2865 }
2866 }
2867}
2868
2869
2876
2877static void tex_aux_scan_delimiter(halfword target, int code, int mathclass)
2878{
2879 delcodeval dval = tex_no_del_code();
2880 mathcodeval mval = tex_no_math_code();
2881 switch (code) {
2882 case no_mathcode:
2883
2884 do {
2885 tex_get_x_token();
2886 } while (cur_cmd == spacer_cmd || cur_cmd == relax_cmd);
2887 switch (cur_cmd) {
2888 case letter_cmd:
2889 case other_char_cmd:
2890 dval = tex_get_del_code(cur_chr);
2891 if (tex_has_del_code(dval)) {
2892 goto REALDELIMITER;
2893 } else {
2894 mval = tex_get_math_code(cur_chr);
2895 goto FAKEDELIMITER;
2896 }
2897 case delimiter_number_cmd:
2898 switch (cur_chr) {
2899 case math_delimiter_code:
2900
2901 dval = tex_aux_scan_extdef_del_code(tex_mathcode, 1);
2902 break;
2903 case math_udelimiter_code:
2904
2905 dval = tex_aux_scan_extdef_del_code(umath_mathcode, 1);
2906 break;
2907 default:
2908 tex_confusion("scan delimiter, case 1");
2909 break;
2910 }
2911 goto REALDELIMITER;
2912 case mathspec_cmd:
2913 mval = tex_get_math_spec(cur_chr);
2914 goto FAKEDELIMITER;
2915 case math_char_number_cmd:
2916 switch (cur_chr) {
2917 case math_char_number_code:
2918 mval = tex_scan_mathchar(tex_mathcode);
2919 break;
2920 case math_xchar_number_code:
2921 mval = tex_scan_mathchar(umath_mathcode);
2922 break;
2923 default:
2924 tex_confusion("scan math char, case 1");
2925 break;
2926 }
2927 goto FAKEDELIMITER;
2928 }
2929 break;
2930 case tex_mathcode:
2931
2932 dval = tex_aux_scan_extdef_del_code(tex_mathcode, 1);
2933 goto REALDELIMITER;
2934 case umath_mathcode:
2935
2936 dval = tex_aux_scan_extdef_del_code(umath_mathcode, 0);
2937 goto REALDELIMITER;
2938 default:
2939 tex_confusion("scan delimiter, case 2");
2940 goto REALDELIMITER;
2941 }
2942 FAKEDELIMITER:
2943 if (mathclass != unset_noad_class) {
2944 mval.class_value = (short) mathclass;
2945 }
2946 dval.small = mval;
2947 dval.large = mval;
2948 REALDELIMITER:
2949 if (! target) {
2950 return;
2951 } else if (tex_has_del_code(dval)) {
2952 node_subtype(target) = dval.small.class_value;
2953 delimiter_small_family(target) = dval.small.family_value;
2954 delimiter_small_character(target) = dval.small.character_value;
2955 delimiter_large_family(target) = dval.large.family_value;
2956 delimiter_large_character(target) = dval.large.character_value;
2957 } else {
2958 tex_back_input(cur_tok);
2959 tex_handle_error(
2960 normal_error_type,
2961 "Missing delimiter (. inserted)",
2962 "I was expecting to see something like '(' or '\\{' or '\\}' here. Acceptable\n"
2963 "delimiters are characters whose \\delcode is nonnegative, or you can use\n"
2964 "'\\delimiter <delimiter code>'."
2965 );
2966 node_subtype(target) = unset_noad_class;
2967 delimiter_small_family(target) = 0;
2968 delimiter_small_character(target) = 0;
2969 delimiter_large_family(target) = 0;
2970 delimiter_large_character(target) = 0;
2971 }
2972 return;
2973}
2974
2975void tex_run_math_radical(void)
2976{
2977 halfword code = cur_chr;
2978 fullword options = 0;
2979 halfword radical = tex_new_node(radical_noad, (quarterword) code);
2980 halfword style = yet_unset_math_style;
2981 halfword variant = 0;
2982 halfword attrlist = null;
2983 halfword top = null;
2984 halfword bottom = null;
2985 tex_tail_append(radical);
2986
2987 while (1) {
2988 switch (tex_scan_character("abeswlmrhndtABESWLMRHDNT", 0, 1, 0)) {
2989 case 0:
2990 goto DONE;
2991 case 'a': case 'A':
2992 if (tex_scan_mandate_keyword("attr", 1)) {
2993 attrlist = tex_scan_attribute(attrlist);
2994 }
2995 break;
2996 case 'b': case 'B':
2997 if (tex_scan_mandate_keyword("bottom", 1)) {
2998 bottom = 1;
2999 }
3000 break;
3001 case 'e': case 'E':
3002 if (tex_scan_mandate_keyword("exact", 1)) {
3003 options = options | noad_option_exact;
3004 }
3005 break;
3006 case 't': case 'T':
3007 if (tex_scan_mandate_keyword("top", 1)) {
3008 top = 1;
3009 }
3010 break;
3011 case 's': case 'S':
3012 switch (tex_scan_character("hitoHITO", 0, 0, 0)) {
3013 case 't': case 'T':
3014 switch (tex_scan_character("ryRY", 0, 0, 0)) {
3015 case 'y': case 'Y':
3016 if (tex_scan_mandate_keyword("style", 3)) {
3017 switch (code) {
3018 case normal_radical_subtype:
3019 case radical_radical_subtype:
3020 case root_radical_subtype:
3021 case rooted_radical_subtype:
3022 case delimited_radical_subtype:
3023 style = tex_scan_math_style_identifier(1, 0);
3024 break;
3025 default:
3026
3027 break;
3028 }
3029 }
3030 break;
3031 case 'r': case 'R':
3032 if (tex_scan_mandate_keyword("stretch", 3)) {
3033 options = options | noad_option_stretch;
3034 }
3035 break;
3036 default:
3037 tex_aux_show_keyword_error("style|stretch");
3038 goto DONE;
3039 }
3040 break;
3041 case 'o': case 'O':
3042 if (tex_scan_mandate_keyword("source", 2)) {
3043 noad_source(radical) = tex_scan_integer(0, NULL);
3044 }
3045 break;
3046 case 'i': case 'I':
3047 if (tex_scan_mandate_keyword("size", 2)) {
3048 radical_size(radical) = tex_scan_integer(0, NULL);
3049 }
3050 break;
3051 case 'h': case 'H':
3052 if (tex_scan_mandate_keyword("shrink", 2)) {
3053 options = options | noad_option_shrink;
3054 }
3055 break;
3056 default:
3057 tex_aux_show_keyword_error("style|source|stretch|shrink");
3058 goto DONE;
3059 }
3060 break;
3061 case 'w': case 'W':
3062 if (tex_scan_mandate_keyword("width", 1)) {
3063 noad_width(radical) = tex_scan_dimension(0, 0, 0, 0, NULL);
3064 }
3065 break;
3066 case 'd': case 'D':
3067 if (tex_scan_mandate_keyword("depth", 1)) {
3068 radical_depth(radical) = tex_scan_dimension(0, 0, 0, 0, NULL);
3069 }
3070 break;
3071 case 'h': case 'H':
3072 if (tex_scan_mandate_keyword("height", 1)) {
3073 radical_height(radical) = tex_scan_dimension(0, 0, 0, 0, NULL);
3074 }
3075 break;
3076 case 'l': case 'L':
3077 if (tex_scan_mandate_keyword("left", 1)) {
3078 options = options | noad_option_left;
3079 }
3080 break;
3081 case 'm': case 'M':
3082 if (tex_scan_mandate_keyword("middle", 1)) {
3083 options = options | noad_option_middle;
3084 }
3085 break;
3086 case 'r': case 'R':
3087 switch (tex_scan_character("ieIE", 0, 0, 0)) {
3088 case 'i': case 'I':
3089 if (tex_scan_mandate_keyword("right", 2)) {
3090 options = options | noad_option_right;
3091 }
3092 break;
3093 case 'e': case 'E':
3094 if (tex_scan_mandate_keyword("reflected", 2)) {
3095 options |= noad_option_reflected;
3096 }
3097 break;
3098 default:
3099 tex_aux_show_keyword_error("right|reflected");
3100 goto DONE;
3101 }
3102 break;
3103 case 'n': case 'N':
3104 switch (tex_scan_character("oO", 0, 0, 0)) {
3105 case 'o': case 'O':
3106 switch (tex_scan_character("orOR", 0, 0, 0)) {
3107 case 'r': case 'R':
3108 if (tex_scan_mandate_keyword("norule", 3)) {
3109 options |= noad_option_no_rule;
3110 }
3111 break;
3112 case 'o': case 'O':
3113 if (tex_scan_mandate_keyword("nooverflow", 3)) {
3114 options |= noad_option_no_overflow;
3115 }
3116 break;
3117 default:
3118 tex_aux_show_keyword_error("norule|nooverflow");
3119 goto DONE;
3120 }
3121 break;
3122 default:
3123 tex_aux_show_keyword_error("norule|nooverflow");
3124 goto DONE;
3125 }
3126 break;
3127 default:
3128 goto DONE;
3129 }
3130 }
3131 DONE:
3132 if (style == yet_unset_math_style) {
3133 switch (code) {
3134 case normal_radical_subtype:
3135 case radical_radical_subtype:
3136 case root_radical_subtype:
3137 variant = math_parameter_radical_variant;
3138 break;
3139 case under_delimiter_radical_subtype:
3140 variant = math_parameter_under_delimiter_variant;
3141 break;
3142 case over_delimiter_radical_subtype:
3143 variant = math_parameter_over_delimiter_variant;
3144 break;
3145 case delimiter_under_radical_subtype:
3146 variant = math_parameter_delimiter_under_variant;
3147 break;
3148 case delimiter_over_radical_subtype:
3149 variant = math_parameter_delimiter_over_variant;
3150 break;
3151 case delimited_radical_subtype:
3152 variant = math_parameter_radical_variant;
3153 break;
3154 case h_extensible_radical_subtype:
3155 variant = math_parameter_h_extensible_variant;
3156 break;
3157 }
3158 style = variant ? tex_math_style_variant(cur_list.math_style, variant) : cur_list.math_style;
3159 }
3160 if (attrlist) {
3161 tex_attach_attribute_list_attribute(radical, attrlist);
3162 }
3163 noad_options(radical) = options;
3164 set_noad_style(radical, style);
3165 {
3166 switch (code) {
3167 case normal_radical_subtype:
3168 {
3169 halfword left = tex_new_node(delimiter_node, 0);
3170 radical_left_delimiter(radical) = left;
3171 tex_aux_scan_delimiter(left, tex_mathcode, unset_noad_class);
3172 }
3173 break;
3174 case radical_radical_subtype:
3175 case root_radical_subtype:
3176 case rooted_radical_subtype:
3177 case delimited_radical_subtype:
3178 {
3179 halfword left = tex_new_node(delimiter_node, 0);
3180 radical_left_delimiter(radical) = left;
3181 tex_aux_scan_delimiter(left, umath_mathcode, unset_noad_class);
3182 }
3183 switch (code) {
3184 case rooted_radical_subtype:
3185 case delimited_radical_subtype:
3186 {
3187 halfword right = tex_new_node(delimiter_node, 0);
3188 radical_right_delimiter(radical) = right;
3189 tex_aux_scan_delimiter(right, umath_mathcode, unset_noad_class);
3190 }
3191 }
3192 break;
3193 case under_delimiter_radical_subtype:
3194 case over_delimiter_radical_subtype:
3195 case delimiter_under_radical_subtype:
3196 case delimiter_over_radical_subtype:
3197 case h_extensible_radical_subtype:
3198 {
3199 halfword left = tex_new_node(delimiter_node, 0);
3200 radical_left_delimiter(radical) = left;
3201 tex_aux_scan_delimiter(left, umath_mathcode, unset_noad_class);
3202 }
3203 break;
3204 default:
3205 tex_confusion("scan math radical");
3206 break;
3207 }
3208 if (top) {
3209 top = tex_new_node(delimiter_node, 0);
3210 radical_top_delimiter(radical) = top;
3211 tex_aux_scan_delimiter(top, umath_mathcode, unset_noad_class);
3212 }
3213 if (bottom) {
3214 bottom = tex_new_node(delimiter_node, 0);
3215 radical_bottom_delimiter(radical) = bottom;
3216 tex_aux_scan_delimiter(bottom, umath_mathcode, unset_noad_class);
3217 }
3218 }
3219 switch (code) {
3220 case h_extensible_radical_subtype:
3221
3222 {
3223 halfword q = tex_new_node(sub_box_node, 0);
3224 noad_nucleus(radical) = q;
3225 break;
3226 }
3227 case root_radical_subtype:
3228 case rooted_radical_subtype:
3229 {
3230
3231 saved_radical_initialize();
3232 saved_radical_degree_done = 0;
3233 saved_radical_style = style;
3234 lmt_save_state.save_stack_data.ptr += saved_radical_n_of_records;
3235 tex_aux_push_math(math_radical_group, tex_math_style_variant(style, math_parameter_degree_variant));
3236 tex_scan_left_brace();
3237 break;
3238 }
3239 default :
3240 {
3241 halfword q = tex_new_node(math_char_node, 0);
3242 noad_nucleus(radical) = q;
3243 tex_aux_scan_math(q, tex_math_style_variant(style, variant ? variant : math_parameter_radical_variant), 0, 0, 0, 0, unset_noad_class, unset_noad_class);
3244 break;
3245 }
3246 }
3247}
3248
3249void tex_finish_math_radical(void)
3250{
3251 tex_aux_unsave_math();
3252 {
3253 halfword whatever = tex_new_node(sub_mlist_node, 0);
3254 halfword content = tex_aux_finish_math_list(null);
3255 halfword radical = cur_list.tail;
3256 kernel_math_list(whatever) = content;
3257 switch (saved_radical_current_component()) {
3258 case 0:
3259 {
3260 halfword style = saved_radical_current_style();
3261 radical_degree(radical) = whatever;
3262 saved_radical_update_component();
3263 tex_aux_push_math(math_radical_group, tex_math_style_variant(style, math_parameter_radical_variant));
3264 tex_scan_left_brace();
3265 }
3266 break;
3267 case 1:
3268 {
3269 noad_nucleus(radical) = whatever;
3270 lmt_save_state.save_stack_data.ptr -= saved_radical_n_of_records;
3271 }
3272 break;
3273 default:
3274 tex_confusion("scan radical");
3275 break;
3276 }
3277 }
3278}
3279
3280void tex_run_math_accent(void)
3281{
3282 mathcodeval t = tex_no_math_code();
3283 mathcodeval b = tex_no_math_code();
3284 mathcodeval o = tex_no_math_code();
3285 halfword code = cur_chr;
3286 halfword accent = tex_new_node(accent_noad, bothflexible_accent_subtype);
3287 quarterword subtype = ordinary_noad_subtype;
3288 halfword mathclass = accent_noad_subtype;
3289 halfword attrlist = null;
3290 if (cur_cmd == accent_cmd) {
3291 tex_handle_error(
3292 normal_error_type,
3293 "Please use \\mathaccent for accents in math mode",
3294 "I'm changing \\accent to \\mathaccent here; wish me luck. (Accents are not the\n"
3295 "same in formulas as they are in text.)" );
3296 }
3297 tex_tail_append(accent);
3298 switch (code) {
3299 case math_accent_code:
3300
3301 t = tex_scan_mathchar(tex_mathcode);
3302 break;
3303 case math_uaccent_code:
3304
3305 while (1) {
3306 switch (tex_scan_character("abcensftokABCENSFTOK", 0, 1, 0)) {
3307 case 'a': case 'A':
3308 switch (tex_scan_character("txTX", 0, 0, 0)) {
3309 case 't': case 'T':
3310 if (tex_scan_mandate_keyword("attr", 2)) {
3311 attrlist = tex_scan_attribute(attrlist);
3312 }
3313 break;
3314
3315
3316
3317
3318
3319 default:
3320
3321 tex_aux_show_keyword_error("attr");
3322 goto DONE;
3323 }
3324 break;
3325 case 'c': case 'C':
3326 switch (tex_scan_character("elEL", 0, 0, 0)) {
3327 case 'e': case 'E':
3328 if (tex_scan_mandate_keyword("center", 2)) {
3329 noad_options(accent) |= noad_option_center;
3330 }
3331 break;
3332 case 'l': case 'L':
3333 if (tex_scan_mandate_keyword("class", 2)) {
3334 halfword c = (quarterword) tex_scan_math_class_number(0);
3335 if (valid_math_class_code(c)) {
3336 mathclass = c;
3337 }
3338 }
3339 break;
3340 default:
3341 tex_aux_show_keyword_error("center|class");
3342 goto DONE;
3343 }
3344 break;
3345 case 'e': case 'E':
3346 if (tex_scan_mandate_keyword("exact", 1)) {
3347 noad_options(accent) |= noad_option_exact;
3348 }
3349 break;
3350 case 's': case 'S':
3351 switch (tex_scan_character("othiOTHI", 0, 0, 0)) {
3352 case 'o': case 'O':
3353 if (tex_scan_mandate_keyword("source", 2)) {
3354 noad_source(accent) = tex_scan_integer(0, NULL);
3355 }
3356 break;
3357 case 't': case 'T':
3358 if (tex_scan_mandate_keyword("stretch", 2)) {
3359 noad_options(accent) |= noad_option_stretch;
3360 }
3361 break;
3362 case 'h': case 'H':
3363 if (tex_scan_mandate_keyword("shrink", 2)) {
3364 noad_options(accent) |= noad_option_shrink;
3365 }
3366 break;
3367 case 'i': case 'I':
3368 if (tex_scan_mandate_keyword("single", 2)) {
3369 noad_options(accent) |= noad_option_single;
3370 }
3371 break;
3372 default:
3373 tex_aux_show_keyword_error("source|stretch|shrink|single");
3374 goto DONE;
3375 }
3376 break;
3377 case 'f': case 'F':
3378 switch (tex_scan_character("frFR", 0, 0, 0)) {
3379 case 'r': case 'R':
3380 if (tex_scan_mandate_keyword("fraction", 2)) {
3381 accent_fraction(accent) = tex_scan_integer(0, NULL);
3382 }
3383 break;
3384 case 'f': case 'F':
3385
3386 if (tex_scan_mandate_keyword("fixed", 2)) {
3387 node_subtype(accent) = fixedtop_accent_subtype;
3388 t = tex_scan_mathchar(umath_mathcode);
3389 }
3390 goto DONE;
3391 default:
3392 tex_aux_show_keyword_error("fraction|fixed");
3393 goto DONE;
3394 }
3395 case 'k': case 'K':
3396 if (tex_scan_mandate_keyword("keepbase", 1)) {
3397 noad_options(accent) |= noad_option_keep_base;
3398 }
3399 break;
3400 case 'n': case 'N':
3401 if (tex_scan_mandate_keyword("nooverflow", 1)) {
3402
3406 noad_options(accent) |= noad_option_no_overflow;
3407 }
3408 break;
3409 case 'b': case 'B':
3410 switch (tex_scan_character("aoAo", 0, 0, 0)) {
3411 case 'a': case 'A':
3412 if (tex_scan_mandate_keyword("base", 2)) {
3413 noad_options(accent) |= noad_option_auto_base;
3414 }
3415 break;
3416 case 'o': case 'O':
3417
3418
3419 if (tex_scan_character("t", 0, 0, 0)) {
3420 switch (tex_scan_character("thTH", 0, 0, 0)) {
3421 case 'h': case 'H':
3422
3423 if (tex_scan_keyword("fixed")) {
3424 node_subtype(accent) = fixedtop_accent_subtype;
3425 }
3426 t = tex_scan_mathchar(umath_mathcode);
3427 if (tex_scan_keyword("fixed")) {
3428 node_subtype(accent) = fixedboth_accent_subtype;
3429 }
3430 b = tex_scan_mathchar(umath_mathcode);
3431 goto DONE;
3432 case 't': case 'T':
3433 if (tex_scan_mandate_keyword("bottom", 4)) {
3434
3435 if (tex_scan_keyword("fixed")) {
3436 node_subtype(accent) = fixedbottom_accent_subtype;
3437 }
3438 b = tex_scan_mathchar(umath_mathcode);
3439 }
3440 goto DONE;
3441 default:
3442 tex_aux_show_keyword_error("both|bottom");
3443 goto DONE;
3444 }
3445 }
3446 goto DONE;
3447 default:
3448 tex_aux_show_keyword_error("base|both|bottom");
3449 goto DONE;
3450 }
3451 break;
3452 case 't': case 'T':
3453
3454 if (tex_scan_mandate_keyword("top", 1)) {
3455 if (tex_scan_keyword("fixed")) {
3456 node_subtype(accent) = fixedtop_accent_subtype;
3457 }
3458 t = tex_scan_mathchar(umath_mathcode);
3459 }
3460 goto DONE;
3461 case 'o': case 'O':
3462
3463 if (tex_scan_mandate_keyword("overlay", 1)) {
3464 if (tex_scan_keyword("fixed")) {
3465 node_subtype(accent) = fixedtop_accent_subtype;
3466 }
3467 o = tex_scan_mathchar(umath_mathcode);
3468 }
3469 goto DONE;
3470 default:
3471
3472 t = tex_scan_mathchar(umath_mathcode);
3473 goto DONE;
3474 }
3475 }
3476 default:
3477 tex_confusion("scan math accent");
3478 }
3479 DONE:
3480 if (attrlist) {
3481 tex_attach_attribute_list_attribute(accent, attrlist);
3482 }
3483 if (! (t.character_value == 0 && t.family_value == 0)) {
3484 halfword n = tex_new_node(math_char_node, 0);
3485 subtype = tex_aux_set_math_char(n, &t, NULL);
3486 accent_top_character(accent) = n;
3487 }
3488 if (! (b.character_value == 0 && b.family_value == 0)) {
3489 halfword n = tex_new_node(math_char_node, 0);
3490 subtype = tex_aux_set_math_char(n, &b, NULL);
3491 accent_bottom_character(accent) = n;
3492 }
3493 if (! (o.character_value == 0 && o.family_value == 0)) {
3494 halfword n = tex_new_node(math_char_node, 0);
3495 subtype = tex_aux_set_math_char(n, &o, NULL);
3496 accent_middle_character(accent) = n;
3497 }
3498 {
3499 halfword n = tex_new_node(math_char_node, subtype);
3500 noad_nucleus(accent) = n;
3501 tex_aux_scan_math(n, tex_math_style_variant(cur_list.math_style, math_parameter_accent_variant), 0, 0, 0, 0, unset_noad_class, unset_noad_class);
3502 }
3503 set_noad_main_class(accent, mathclass);
3504}
3505
3506
3514
3515void tex_run_math_choice(void) {
3516 switch (cur_chr) {
3517 case math_discretionary_code:
3518 {
3519 halfword n = tex_new_node(choice_node, discretionary_choice_subtype);
3520 choice_class(n) = unset_noad_class;
3521 while (1) {
3522 switch (tex_scan_character("cC", 0, 1, 0)) {
3523 case 0:
3524 goto DONE;
3525 case 'c': case 'C':
3526 if (tex_scan_mandate_keyword("class", 1)) {
3527 choice_class(n) = tex_scan_math_class_number(0);
3528 }
3529 break;
3530 default:
3531 goto DONE;
3532 }
3533 }
3534 DONE:
3535 tex_tail_append(n);
3536 saved_choice_initialize();
3537 saved_choice_count = math_pre_break_choice;
3538 lmt_save_state.save_stack_data.ptr += saved_choice_n_of_records;
3539 tex_aux_push_math(math_choice_group, cur_list.math_style);
3540 tex_scan_left_brace();
3541 break;
3542 }
3543 case math_choice_code:
3544
3545 {
3546 halfword n = tex_new_node(choice_node, normal_choice_subtype);
3547 tex_tail_append(n);
3548 saved_choice_initialize();
3549 saved_choice_count = math_display_choice;
3550 lmt_save_state.save_stack_data.ptr += saved_choice_n_of_records;
3551 tex_aux_push_math(math_choice_group, display_style);
3552 tex_scan_left_brace();
3553 break;
3554 }
3555 case math_stack_code:
3556
3557 {
3558
3559 halfword m = tex_new_node(math_char_node, 0);
3560 halfword n = tex_new_node(simple_noad, ordinary_noad_subtype);
3561 halfword s = tex_math_style_variant(cur_list.math_style, math_parameter_stack_variant);
3562 tex_tail_append(n);
3563 noad_nucleus(n) = m;
3564 tex_scan_left_brace();
3565 saved_math_group_initialize();
3566 saved_math_group_pointer = m;
3567 saved_math_group_all_class = unset_noad_class;
3568 lmt_save_state.save_stack_data.ptr += saved_math_group_n_of_records;
3569 tex_aux_push_math(math_stack_group, s);
3570 break;
3571 }
3572 }
3573}
3574
3575int tex_current_math_style(void)
3576{
3577 return is_m_mode(cur_list.mode) ? cur_list.math_style : -1;
3578}
3579
3580int tex_current_math_main_style(void)
3581{
3582 return is_m_mode(cur_list.mode) ? cur_list.math_main_style : -1;
3583}
3584
3585void tex_finish_math_choice(void)
3586{
3587 tex_aux_unsave_math();
3588 {
3589 halfword content = tex_aux_finish_math_list(null);
3590 halfword choice = saved_choice_current_component();
3591 if (choice >= 0) {
3592 int style = cur_list.math_style;
3593 switch (node_subtype(cur_list.tail)) {
3594 case normal_choice_subtype:
3595 switch (choice) {
3596 case math_display_choice:
3597 choice_display_mlist(cur_list.tail) = content;
3598 style = text_style;
3599 break;
3600 case math_text_choice:
3601 choice_text_mlist(cur_list.tail) = content;
3602 style = script_style;
3603 break;
3604 case math_script_choice:
3605 choice_script_mlist(cur_list.tail) = content;
3606 style = script_script_style;
3607 break;
3608 case math_script_script_choice:
3609 choice_script_script_mlist(cur_list.tail) = content;
3610 lmt_save_state.save_stack_data.ptr -= saved_choice_n_of_records;
3611 return;
3612 }
3613 break;
3614 case discretionary_choice_subtype:
3615 switch (choice) {
3616 case math_pre_break_choice:
3617 choice_pre_break(cur_list.tail) = content;
3618 style = display_style;
3619 break;
3620 case math_post_break_choice:
3621 choice_post_break(cur_list.tail) = content;
3622 style = text_style;
3623 break;
3624 case math_no_break_choice:
3625 choice_no_break(cur_list.tail) = content;
3626 style = script_style;
3627 lmt_save_state.save_stack_data.ptr -= saved_choice_n_of_records;
3628 return;
3629 }
3630 break;
3631 }
3632 saved_choice_update_component();
3633 tex_aux_push_math(math_choice_group, style);
3634 tex_scan_left_brace();
3635 } else {
3636 tex_confusion("scan build choices");
3637 }
3638 }
3639}
3640
3641void tex_finish_math_fraction(void)
3642{
3643 tex_aux_unsave_math();
3644 {
3645 halfword content = tex_aux_finish_math_list(null);
3646 halfword over = saved_fraction_current_component();
3647 if (over >= 0) {
3648 halfword autostyle = saved_fraction_current_autostyle();
3649 halfword userstyle = saved_fraction_current_userstyle();
3650 halfword fraction = cur_list.tail;
3651 set_noad_style(fraction, userstyle);
3652 switch (over) {
3653 case math_numerator_above:
3654 kernel_math_list(fraction_numerator(fraction)) = content;
3655 break;
3656 case math_denominator_above:
3657 kernel_math_list(fraction_denominator(fraction)) = content;
3658 lmt_save_state.save_stack_data.ptr -= saved_fraction_n_of_records;
3659 return;
3660 }
3661 saved_fraction_update_component();
3662 tex_aux_push_math(math_fraction_group, autostyle);
3663 tex_scan_left_brace();
3664 } else {
3665 tex_confusion("scan build fraction");
3666 }
3667 }
3668}
3669
3670void tex_finish_math_operator(void)
3671{
3672 tex_aux_unsave_math();
3673 {
3674 halfword content = tex_aux_finish_math_list(null);
3675 halfword over = saved_operator_current_component();
3676 if (over >= 0) {
3677 halfword fenced = cur_list.tail;
3678 switch (over) {
3679 case math_limits_top:
3680 kernel_math_list(fence_delimiter_top(fenced)) = content;
3681 break;
3682 case math_limits_bottom:
3683 kernel_math_list(fence_delimiter_bottom(fenced)) = content;
3684 lmt_save_state.save_stack_data.ptr -= saved_operator_n_of_records;
3685 return;
3686 }
3687 saved_operator_update_component();
3688 tex_aux_push_math(math_operator_group, tex_math_style_variant(cur_list.math_style, math_parameter_subscript_variant));
3689 tex_scan_left_brace();
3690 } else {
3691 tex_confusion("math operator");
3692 }
3693 }
3694}
3695
3696
3702
3703# define scripts_allowed(A) ((node_type((A)) >= simple_noad) && (node_type((A)) < fence_noad))
3704
3705static halfword tex_math_double_atom(void)
3706{
3707 halfword tail = tex_new_node(simple_noad, ordinary_noad_subtype);
3708 halfword list = tex_new_node(sub_mlist_node, 0);
3709 tex_tail_append(tail);
3710 if (math_double_script_mode_par >= 0) {
3711 node_subtype(tail) = (math_double_script_mode_par >> 16) & 0xFF;
3712 noad_class_left(tail) = (math_double_script_mode_par >> 8) & 0xFF;
3713 noad_class_right(tail) = (math_double_script_mode_par >> 0) & 0xFF;
3714 }
3715 noad_nucleus(tail) = list;
3716 return tail;
3717}
3718
3719void tex_run_math_script(void)
3720{
3721 int code = cur_chr;
3722 halfword tail = cur_list.tail;
3723 switch (cur_cmd) {
3724 case subscript_cmd:
3725 code = math_sub_script_code;
3726 break;
3727 case superscript_cmd:
3728 code = math_super_script_code;
3729 break;
3730 }
3731 switch (code) {
3732 case math_no_script_code:
3733 {
3734 halfword glue = tex_new_glue_node(zero_glue, conditional_math_glue);
3735 tex_tail_append(glue);
3736 tex_add_glue_option(glue, glue_option_no_auto_break);
3737 }
3738 return;
3739 case math_no_ruling_code:
3740 {
3741 halfword glue = tex_new_glue_node(zero_glue, rulebased_math_glue);
3742 tex_tail_append(glue);
3743 tex_add_glue_option(glue, glue_option_no_auto_break);
3744 }
3745 return;
3746 case math_sub_script_code:
3747 tex_get_token();
3748 if (cur_tok == underscore_token || cur_cmd == subscript_cmd) {
3749 tex_get_token();
3750 if (cur_tok == underscore_token || cur_cmd == subscript_cmd) {
3751 tex_get_token();
3752 if (cur_tok == underscore_token || cur_cmd == subscript_cmd) {
3753 code = math_shifted_sub_pre_script_code;
3754 } else {
3755 tex_back_input(cur_tok);
3756 code = math_shifted_sub_script_code;
3757 }
3758 } else {
3759 tex_back_input(cur_tok);
3760 code = math_sub_pre_script_code;
3761 }
3762 } else {
3763 tex_back_input(cur_tok);
3764 }
3765 break;
3766 case math_super_script_code:
3767 tex_get_token();
3768 if (cur_tok == circumflex_token || cur_cmd == superscript_cmd) {
3769 tex_get_token();
3770 if (cur_tok == circumflex_token || cur_cmd == superscript_cmd) {
3771 tex_get_token();
3772 if (cur_tok == circumflex_token || cur_cmd == superscript_cmd) {
3773 code = math_shifted_super_pre_script_code;
3774 } else {
3775 tex_back_input(cur_tok);
3776 code = math_shifted_super_script_code;
3777 }
3778 } else {
3779 tex_back_input(cur_tok);
3780 code = math_super_pre_script_code;
3781 }
3782 } else {
3783 tex_back_input(cur_tok);
3784 }
3785 break;
3786 }
3787 if (tail == cur_list.head || (! scripts_allowed(tail))) {
3788 halfword n = tex_new_node(sub_mlist_node, 0);
3789 tail = tex_new_node(simple_noad, ordinary_noad_subtype);
3790 tex_tail_append(tail);
3791 noad_nucleus(tail) = n;
3792 }
3793 switch (code) {
3794 case math_sub_script_code:
3795 case math_no_sub_script_code:
3796 case math_shifted_sub_script_code:
3797 {
3798 if (noad_subscr(tail)) {
3799 tail = tex_math_double_atom();
3800 if (math_double_script_mode_par < 0) {
3801 tex_handle_error(
3802 normal_error_type,
3803 "Double subscript",
3804 "I treat 'x_1_2' essentially like 'x_1{}_2'."
3805 );
3806 }
3807 }
3808 switch (code) {
3809 case math_no_sub_script_code:
3810 noad_options(tail) |= noad_option_no_sub_script;
3811 break;
3812 case math_shifted_sub_script_code:
3813 noad_options(tail) |= noad_option_shifted_sub_script;
3814 break;
3815 }
3816 {
3817 halfword n = tex_new_node(math_char_node, 0);
3818 noad_subscr(tail) = n;
3819 tex_aux_scan_math(n, tex_math_style_variant(cur_list.math_style, math_parameter_subscript_variant), 0, 0, 0, 1, unset_noad_class, unset_noad_class);
3820 if (! noad_script_order(tail)) {
3821 noad_script_order(tail) = script_subscript_first;
3822 }
3823 }
3824 break;
3825 }
3826 case math_sub_pre_script_code:
3827 case math_no_sub_pre_script_code:
3828 case math_shifted_sub_pre_script_code:
3829 {
3830 if (noad_subprescr(tail)) {
3831 int limitation = node_type(tail) == fraction_noad;
3832 tail = tex_math_double_atom();
3833 if (math_double_script_mode_par < 0) {
3834 tex_handle_error(
3835 normal_error_type,
3836 limitation ? "Fractions take no pre subscript directly" : "Double pre subscript",
3837 "I just ignore it; consider wrapping this element."
3838 );
3839 }
3840 }
3841 switch (code) {
3842 case math_no_sub_pre_script_code:
3843 noad_options(tail) |= noad_option_no_sub_pre_script;
3844 break;
3845 case math_shifted_sub_pre_script_code:
3846 noad_options(tail) |= noad_option_shifted_sub_pre_script;
3847 break;
3848 }
3849 {
3850 halfword n = tex_new_node(math_char_node, 0);
3851 noad_subprescr(tail) = n;
3852 tex_aux_scan_math(n, tex_math_style_variant(cur_list.math_style, math_parameter_subscript_variant), 0, 0, 0, 1, unset_noad_class, unset_noad_class);
3853 }
3854 break;
3855 }
3856 case math_super_script_code:
3857 case math_no_super_script_code:
3858 case math_shifted_super_script_code:
3859 {
3860 if (noad_supscr(tail)) {
3861 tail = tex_math_double_atom();
3862 if (math_double_script_mode_par < 0) {
3863 tex_handle_error(
3864 normal_error_type,
3865 "Double superscript",
3866 "I treat 'x^1^2' essentially like 'x^1{}^2'."
3867 );
3868 }
3869 }
3870 switch (code) {
3871 case math_no_super_script_code:
3872 noad_options(tail) |= noad_option_no_super_script;
3873 break;
3874 case math_shifted_super_script_code:
3875 noad_options(tail) |= noad_option_shifted_super_script;
3876 break;
3877 }
3878 {
3879 halfword n = tex_new_node(math_char_node, 0);
3880 noad_supscr(tail) = n;
3881 if (! noad_script_order(tail)) {
3882 noad_script_order(tail) = script_superscript_first;
3883 }
3884 tex_aux_scan_math(n, tex_math_style_variant(cur_list.math_style, math_parameter_superscript_variant), 0, 0, 0, 1, unset_noad_class, unset_noad_class);
3885 }
3886 break;
3887 }
3888 case math_super_pre_script_code:
3889 case math_no_super_pre_script_code:
3890 case math_shifted_super_pre_script_code:
3891 {
3892 if (noad_supprescr(tail)) {
3893 int limitation = node_type(tail) == fraction_noad;
3894 tail = tex_math_double_atom();
3895 if (math_double_script_mode_par < 0) {
3896 tex_handle_error(
3897 normal_error_type,
3898 limitation ? "Fractions take no pre superscript directly" : "Double pre superscript",
3899 "I just ignore it; consider wrapping this element."
3900 );
3901 }
3902 }
3903 switch (code) {
3904 case math_no_super_script_code:
3905 noad_options(tail) |= noad_option_no_super_pre_script;
3906 break;
3907 case math_shifted_super_pre_script_code:
3908 noad_options(tail) |= noad_option_shifted_super_pre_script;
3909 break;
3910 }
3911 {
3912 halfword n = tex_new_node(math_char_node, 0);
3913 noad_supprescr(tail) = n;
3914 tex_aux_scan_math(n, tex_math_style_variant(cur_list.math_style, math_parameter_superscript_variant), 0, 0, 0, 1, unset_noad_class, unset_noad_class);
3915 }
3916 break;
3917 }
3918 case math_prime_script_code:
3919 {
3920 if (noad_prime(tail)) {
3921 tail = tex_math_double_atom();
3922 if (math_double_script_mode_par < 0) {
3923 tex_handle_error(
3924 normal_error_type,
3925 "Double prime script",
3926 "I'll add a dummy nucleus."
3927 );
3928 }
3929 }
3930 {
3931 halfword n = tex_new_node(math_char_node, 0);
3932 noad_prime(tail) = n;
3933 if (! noad_script_order(tail)) {
3934 noad_script_order(tail) = script_primescript_first;
3935 }
3936
3937 tex_aux_scan_math(n, tex_math_style_variant(cur_list.math_style, math_parameter_superscript_variant), 0, 0, 0, 1, unset_noad_class, unset_noad_class);
3938 }
3939 break;
3940 }
3941 }
3942}
3943
3944
3956
3957void tex_run_math_fraction(void)
3958{
3959
3960 halfword code = cur_chr;
3961 if (cur_list.incomplete_noad) {
3962
3963 switch (code) {
3964 case math_above_delimited_code:
3965 case math_over_delimited_code:
3966 case math_atop_delimited_code:
3967 case math_u_above_delimited_code:
3968 case math_u_over_delimited_code:
3969 case math_u_atop_delimited_code:
3970 case math_u_skewed_delimited_code:
3971 case math_u_stretched_delimited_code:
3972 tex_aux_scan_delimiter(null, no_mathcode, unset_noad_class);
3973 tex_aux_scan_delimiter(null, no_mathcode, unset_noad_class);
3974 break;
3975 }
3976 switch (code) {
3977 case math_above_code:
3978 case math_above_delimited_code:
3979 case math_u_above_code:
3980 case math_u_above_delimited_code:
3981 tex_scan_dimension(0, 0, 0, 0, NULL);
3982 break;
3983 }
3984
3985 tex_handle_error(
3986 normal_error_type,
3987 "Ambiguous; you need another { and }",
3988 "I'm ignoring this fraction specification, since I don't know whether a\n"
3989 "construction like 'x \\over y \\over z' means '{x \\over y} \\over z' or\n"
3990 "'x \\over {y \\over z}'."
3991 );
3992 } else {
3993 halfword fraction = tex_new_node(fraction_noad, 0);
3994 halfword numerator = tex_new_node(sub_mlist_node, 0);
3995 halfword denominator = null;
3996 halfword autostyle = tex_math_style_variant(cur_list.math_style, math_parameter_fraction_variant);
3997 halfword userstyle = -1;
3998 halfword attrlist = null;
3999 fullword options = 0;
4000 halfword mathclass = fraction_noad_subtype;
4001 halfword rulethickness = preset_rule_thickness;
4002 int ruledone = 0;
4003 fraction_h_factor(fraction) = scaling_factor;
4004 fraction_v_factor(fraction) = scaling_factor;
4005 switch (code) {
4006 case math_above_code:
4007 case math_above_delimited_code:
4008 node_subtype(fraction) = above_fraction_subtype;
4009 goto NEXTSTEP1;
4010 case math_over_code:
4011 case math_over_delimited_code:
4012 node_subtype(fraction) = over_fraction_subtype;
4013 goto NEXTSTEP1;
4014 case math_atop_code:
4015 case math_atop_delimited_code:
4016 node_subtype(fraction) = atop_fraction_subtype;
4017 NEXTSTEP1:
4018 {
4019 cur_list.incomplete_noad = fraction;
4020 fraction_numerator(fraction) = numerator;
4021 kernel_math_list(numerator) = node_next(cur_list.head);
4022 node_next(cur_list.head) = null;
4023 cur_list.tail = cur_list.head;
4024 cur_list.math_style = autostyle;
4025 break;
4026 }
4027 case math_u_above_code:
4028 case math_u_above_delimited_code:
4029 node_subtype(fraction) = above_fraction_subtype;
4030 goto NEXTSTEP2;
4031 case math_u_over_code:
4032 case math_u_over_delimited_code:
4033 node_subtype(fraction) = over_fraction_subtype;
4034 goto NEXTSTEP2;
4035 case math_u_atop_code:
4036 case math_u_atop_delimited_code:
4037 node_subtype(fraction) = atop_fraction_subtype;
4038 goto NEXTSTEP2;
4039 case math_u_skewed_code:
4040 case math_u_skewed_delimited_code:
4041 node_subtype(fraction) = skewed_fraction_subtype;
4042 goto NEXTSTEP2;
4043 case math_u_stretched_code:
4044 case math_u_stretched_delimited_code:
4045 node_subtype(fraction) = stretched_fraction_subtype;
4046 NEXTSTEP2:
4047 {
4048 cur_list.incomplete_noad = null;
4049 denominator = tex_new_node(sub_mlist_node, 0);
4050 tex_tail_append(fraction);
4051 fraction_numerator(fraction) = numerator;
4052 fraction_denominator(fraction) = denominator;
4053 break;
4054 }
4055 }
4056 switch (code) {
4057 case math_u_skewed_code:
4058 case math_u_skewed_delimited_code:
4059 case math_u_stretched_code:
4060 case math_u_stretched_delimited_code:
4061 {
4062 halfword q = tex_new_node(delimiter_node, 0);
4063 fraction_middle_delimiter(fraction) = q;
4064 tex_aux_scan_delimiter(q, no_mathcode, unset_noad_class);
4065 break;
4066 }
4067 }
4068 switch (code) {
4069 case math_above_delimited_code:
4070 case math_over_delimited_code:
4071 case math_atop_delimited_code:
4072 case math_u_above_delimited_code:
4073 case math_u_over_delimited_code:
4074 case math_u_atop_delimited_code:
4075 case math_u_skewed_delimited_code:
4076 case math_u_stretched_delimited_code:
4077 {
4078 halfword left = tex_new_node(delimiter_node, 0);
4079 halfword right = tex_new_node(delimiter_node, 0);
4080 fraction_left_delimiter(fraction) = left;
4081 fraction_right_delimiter(fraction) = right;
4082 tex_aux_scan_delimiter(left, no_mathcode, open_noad_subtype);
4083 tex_aux_scan_delimiter(right, no_mathcode, close_noad_subtype);
4084 break;
4085 }
4086 }
4087 switch (code) {
4088
4089 case math_above_code:
4090 case math_above_delimited_code:
4091 rulethickness = tex_scan_dimension(0, 0, 0, 0, NULL);
4092 break;
4093 case math_over_code:
4094 case math_over_delimited_code:
4095 rulethickness = preset_rule_thickness;
4096 break;
4097 case math_atop_code:
4098 case math_atop_delimited_code:
4099 break;
4100
4104 case math_u_above_code:
4105 case math_u_above_delimited_code:
4106 goto OPTIONS;
4107 case math_u_atop_code:
4108 case math_u_atop_delimited_code:
4109 case math_u_over_code:
4110 case math_u_over_delimited_code:
4111 ruledone = 1;
4112 goto OPTIONS;
4113 case math_u_stretched_code:
4114 case math_u_stretched_delimited_code:
4115 case math_u_skewed_code:
4116 case math_u_skewed_delimited_code:
4117 ruledone = 1;
4118 OPTIONS:
4119 while (1) {
4120 switch (tex_scan_character("acefhnpstvACEFHNPSTV", 0, 1, 0)) {
4121 case 'a': case 'A':
4122 if (tex_scan_mandate_keyword("attr", 1)) {
4123 attrlist = tex_scan_attribute(attrlist);
4124 }
4125 break;
4126 case 'c': case 'C':
4127 switch (tex_scan_character("leLE", 0, 0, 0)) {
4128 case 'l': case 'L':
4129 if (tex_scan_mandate_keyword("class", 2)) {
4130 halfword c = (quarterword) tex_scan_math_class_number(0);
4131 if (valid_math_class_code(c)) {
4132 mathclass = c;
4133 }
4134 }
4135 break;
4136 case 'e': case 'E':
4137 if (tex_scan_mandate_keyword("center", 2)) {
4138 options |= noad_option_center;
4139 }
4140 break;
4141 default:
4142 tex_aux_show_keyword_error("class|center");
4143 goto DONE;
4144 }
4145 break;
4146 case 'e': case 'E':
4147
4148 if (tex_scan_mandate_keyword("exact", 1)) {
4149 options |= noad_option_exact;
4150 }
4151 break;
4152 case 'p': case 'P':
4153
4154 if (tex_scan_mandate_keyword("proportional", 1)) {
4155 options |= noad_option_proportional;
4156 }
4157 break;
4158 case 'n': case 'N':
4159
4160 if (tex_scan_character("oO", 0, 0, 0)) {
4161 switch (tex_scan_character("aoAO", 0, 0, 0)) {
4162 case 'a': case 'A':
4163 if (tex_scan_mandate_keyword("noaxis", 3)) {
4164 options |= noad_option_no_axis;
4165 }
4166 break;
4167 case 'o': case 'O':
4168 if (tex_scan_mandate_keyword("nooverflow", 3)) {
4169 options |= noad_option_no_overflow;
4170 }
4171 break;
4172 default:
4173 tex_aux_show_keyword_error("noaxis|nooverflow");
4174 goto DONE;
4175 }
4176 }
4177 break;
4178 case 't': case 'T':
4179 if (tex_scan_mandate_keyword("thickness", 1)) {
4180 ruledone = 1;
4181 rulethickness = tex_scan_dimension(0, 0, 0, 0, NULL);
4182 }
4183 break;
4184 case 'f': case 'F':
4185 if (tex_scan_mandate_keyword("font", 1)) {
4186 ruledone = 1;
4187 options |= noad_option_prefer_font_thickness;
4188 }
4189 break;
4190 case 's': case 'S':
4191 switch (tex_scan_character("toTO", 0, 0, 0)) {
4192 case 't': case 'T':
4193 if (tex_scan_mandate_keyword("style", 2)) {
4194 halfword style = tex_scan_math_style_identifier(1, 0);
4195 if (denominator) {
4196 userstyle = style;
4197 } else {
4198
4199 }
4200 }
4201 break;
4202 case 'o': case 'O':
4203 if (tex_scan_mandate_keyword("source", 2)) {
4204 noad_source(fraction) = tex_scan_integer(0, NULL);
4205 }
4206 break;
4207 default:
4208 tex_aux_show_keyword_error("style|source");
4209 goto DONE;
4210 }
4211 break;
4212 case 'h': case 'H':
4213 if (tex_scan_mandate_keyword("hfactor", 1)) {
4214 fraction_h_factor(fraction) = tex_scan_integer(0, NULL);
4215 }
4216 break;
4217 case 'v': case 'V':
4218 if (tex_scan_mandate_keyword("vfactor", 1)) {
4219 fraction_v_factor(fraction) = tex_scan_integer(0, NULL);
4220 }
4221 break;
4222 default:
4223 goto DONE;
4224 }
4225 }
4226 DONE:
4227 if (! ruledone) {
4228 rulethickness = tex_scan_dimension(0, 0, 0, 0, NULL);
4229 }
4230 break;
4231 }
4232 fraction_rule_thickness(fraction) = rulethickness;
4233 noad_options(fraction) = options;
4234 set_noad_main_class(fraction, mathclass);
4235 if (attrlist) {
4236 tex_attach_attribute_list_attribute(fraction, attrlist);
4237 }
4238 if (denominator) {
4239
4243 saved_fraction_initialize();
4244 saved_fraction_variant = math_numerator_above;
4245 saved_fraction_autostyle = autostyle;
4246 saved_fraction_userstyle = userstyle;
4247 lmt_save_state.save_stack_data.ptr += saved_fraction_n_of_records;
4248 cur_list.math_flatten = 0;
4249 tex_aux_push_math(math_fraction_group, autostyle);
4250 tex_scan_left_brace();
4251 } else {
4252
4256 }
4257 }
4258}
4259
4260
4268
4269static halfword tex_aux_finish_math_list(halfword p)
4270{
4271 halfword q;
4272 if (cur_list.incomplete_noad) {
4273 halfword denominator = fraction_denominator(cur_list.incomplete_noad);
4274 if (denominator) {
4275 node_type(denominator) = sub_mlist_node;
4276 } else {
4277 denominator = tex_new_node(sub_mlist_node, 0);
4278 fraction_denominator(cur_list.incomplete_noad) = denominator;
4279 q = denominator;
4280 }
4281 kernel_math_list(denominator) = node_next(cur_list.head);
4282 if (p) {
4283 halfword numerator = fraction_numerator(cur_list.incomplete_noad);
4284 q = kernel_math_list(numerator);
4285 if ((node_type(q) != fence_noad) || (node_subtype(q) != left_fence_side) || (! cur_list.delimiter)) {
4286 tex_confusion("right fence");
4287 }
4288 kernel_math_list(numerator) = node_next(cur_list.delimiter);
4289 node_next(cur_list.delimiter) = cur_list.incomplete_noad;
4290 node_next(cur_list.incomplete_noad) = p;
4291 } else {
4292 q = cur_list.incomplete_noad;
4293 }
4294 } else {
4295 node_next(cur_list.tail) = p;
4296 q = node_next(cur_list.head);
4297 }
4298 tex_pop_nest();
4299 return q;
4300}
4301
4302
4310
4311static void tex_aux_flatten_math_list(halfword parent)
4312{
4313 halfword p = kernel_math_list(parent);
4314 if (p && ! node_next(p)) {
4315 switch (node_type(p)) {
4316 case simple_noad:
4317 {
4318
4319 if (! noad_has_following_scripts(p) && tex_math_has_class_option(node_subtype(p), flatten_class_option) && ! noad_source(p)) {
4320 halfword n = noad_nucleus(p);
4321 halfword s = parent;
4322 node_type(s) = node_type(n);
4323 tex_math_copy_char_data(s, n, 1);
4324 tex_attach_attribute_list_copy(s, n);
4325 tex_flush_node(p);
4326 }
4327 break;
4328 }
4329 case accent_noad:
4330 {
4331 halfword tail = cur_list.tail;
4332 if (saved_math_group_pointer == noad_nucleus(tail) && node_type(tail) == simple_noad) {
4333 switch (node_subtype(tail)) {
4334 case ordinary_noad_subtype:
4335 tex_couple_nodes(node_prev(tail), p);
4336 noad_nucleus(tail) = null;
4337 noad_subscr(tail) = null;
4338 noad_supscr(tail) = null;
4339 noad_prime(tail) = null;
4340 tex_attach_attribute_list_copy(p, tail);
4341 tex_flush_node(tail);
4342 cur_list.tail = p;
4343 break;
4344 }
4345 }
4346 break;
4347 }
4348 }
4349 }
4350}
4351
4352
4360
4361void tex_finish_math_group(void)
4362{
4363 int old_style = cur_list.math_style;
4364 halfword p, parent;
4365 quarterword allclass;
4366 tex_aux_unsave_math();
4367 lmt_save_state.save_stack_data.ptr -= saved_math_group_n_of_records;
4368 parent = saved_math_group_pointer;
4369 allclass = (quarterword) saved_math_group_all_class;
4370 node_type(parent) = sub_mlist_node;
4371 p = tex_aux_finish_math_list(null);
4372 kernel_math_list(parent) = p;
4373 if (cur_list.math_flatten) {
4374 tex_aux_flatten_math_list(parent);
4375 }
4376
4380 if (allclass != unset_noad_class) {
4381 while (p) {
4382 if (node_type(p) == simple_noad) {
4383
4384 if (get_noad_main_class(p) == unset_noad_class) {
4385 set_noad_main_class(p, allclass);
4386 }
4387 if (get_noad_left_class(p) == unset_noad_class) {
4388 set_noad_left_class(p, allclass);
4389 }
4390 if (get_noad_right_class(p) == unset_noad_class) {
4391 set_noad_right_class(p, allclass);
4392 }
4393 }
4394 p = node_next(p);
4395 }
4396
4397 }
4398 if (node_next(saved_math_group_pointer) > 0) {
4399 halfword q = tex_new_node(math_char_node, 0);
4400 noad_nucleus(node_next(saved_math_group_pointer)) = q;
4401 node_next(saved_math_group_pointer) = null;
4402 saved_math_group_pointer = q;
4403 tex_aux_scan_math(q, old_style, 0, 0, 0, 0, unset_noad_class, unset_noad_class);
4404
4405 }
4406}
4407
4408
4415
4416void tex_run_math_fence(void)
4417{
4418 scaled ht = 0;
4419 scaled dp = 0;
4420 scaled top = 0;
4421 scaled bottom = 0;
4422 fullword options = 0;
4423 halfword mainclass = unset_noad_class;
4424 halfword leftclass = unset_noad_class;
4425 halfword rightclass = unset_noad_class;
4426 halfword source = 0;
4427 halfword factor = scaling_factor;
4428 halfword attrlist = null;
4429 quarterword st = (quarterword) cur_chr;
4430 halfword style = cur_list.math_style;
4431 if (math_check_fences_par) {
4432 options |= noad_option_no_check;
4433 }
4434 switch (st) {
4435 case left_operator_side:
4436 case no_fence_side:
4437 break;
4438 case extended_left_fence_side:
4439 st = left_fence_side;
4440 break;
4441 case extended_middle_fence_side:
4442 st = middle_fence_side;
4443 break;
4444 case extended_right_fence_side:
4445 st = right_fence_side;
4446 break;
4447 default :
4448 goto CHECK_PAIRING;
4449 }
4450 while (1) {
4451
4452 switch (tex_scan_character("hdanmlevpcrsutbfHDANMLEVPCRSUTBF", 0, 1, 0)) {
4453 case 0:
4454 goto CHECK_PAIRING;
4455 case 'a': case 'A':
4456 switch (tex_scan_character("uxtUXT", 0, 0, 0)) {
4457 case 'u': case 'U':
4458 if (tex_scan_mandate_keyword("auto", 2)) {
4459 options |= noad_option_auto;
4460 }
4461 break;
4462 case 't': case 'T':
4463 if (tex_scan_mandate_keyword("attr", 2)) {
4464 attrlist = tex_scan_attribute(attrlist);
4465 }
4466 break;
4467 case 'x': case 'X':
4468 if (tex_scan_mandate_keyword("axis", 2)) {
4469 options |= noad_option_axis;
4470 }
4471 break;
4472 default:
4473 tex_aux_show_keyword_error("auto|attr|axis");
4474 goto CHECK_PAIRING;
4475 }
4476 break;
4477 case 'b': case 'B':
4478 if (tex_scan_mandate_keyword("bottom", 1)) {
4479 bottom = tex_scan_dimension(0, 0, 0, 0, NULL);
4480 }
4481 break;
4482 case 'd': case 'D':
4483 if (tex_scan_mandate_keyword("depth", 1)) {
4484 dp = tex_scan_dimension(0, 0, 0, 0, NULL);
4485 }
4486 break;
4487 case 'f': case 'F':
4488 if (tex_scan_mandate_keyword("factor", 1)) {
4489 factor = tex_scan_integer(0, NULL);
4490 }
4491 break;
4492 case 'h': case 'H':
4493 if (tex_scan_mandate_keyword("height", 1)) {
4494 ht = tex_scan_dimension(0, 0, 0, 0, NULL);
4495 }
4496 break;
4497 case 'n': case 'N':
4498 switch (tex_scan_character("oO", 0, 0, 0)) {
4499 case 'o': case 'O':
4500 switch (tex_scan_character("alcoALCO", 0, 0, 0)) {
4501 case 'a': case 'A':
4502 if (tex_scan_mandate_keyword("noaxis", 3)) {
4503 options |= noad_option_no_axis;
4504 }
4505 break;
4506 case 'l': case 'L':
4507 if (tex_scan_mandate_keyword("nolimits", 3)) {
4508 options = unset_option(options, noad_option_limits);
4509 options |= noad_option_no_limits;
4510 }
4511 break;
4512 case 'c': case 'C':
4513 if (tex_scan_mandate_keyword("nocheck", 3)) {
4514 options |= noad_option_no_check;
4515 }
4516 break;
4517 case 'o': case 'O':
4518 if (tex_scan_mandate_keyword("nooverflow", 3)) {
4519 options |= noad_option_no_overflow;
4520 }
4521 break;
4522 default:
4523 tex_aux_show_keyword_error("noaxis|nolimits|nocheck|nooverflow");
4524 goto CHECK_PAIRING;
4525 }
4526 break;
4527 default:
4528 goto CHECK_PAIRING;
4529 }
4530 break;
4531 case 'm': case 'M':
4532 if (tex_scan_mandate_keyword("middle", 1)) {
4533 options |= noad_option_auto_middle;
4534 }
4535 break;
4536 case 'l': case 'L':
4537 switch (tex_scan_character("ieIE", 0, 0, 0)) {
4538 case 'e': case 'E':
4539 if (tex_scan_mandate_keyword("leftclass", 2)) {
4540 halfword c = tex_scan_math_class_number(0);
4541
4542 if (valid_math_class_code(c)) {
4543 leftclass = c;
4544 }
4545 }
4546 break;
4547 case 'i': case 'I':
4548 if (tex_scan_mandate_keyword("limits", 2)) {
4549 options = unset_option(options, noad_option_no_limits);
4550 options |= noad_option_limits;
4551 }
4552 break;
4553 default:
4554 tex_aux_show_keyword_error("leftclass|limits");
4555 goto CHECK_PAIRING;
4556 }
4557 break;
4558 case 'e': case 'E':
4559 if (tex_scan_mandate_keyword("exact", 1)) {
4560 options |= noad_option_exact;
4561 }
4562 break;
4563 case 'v': case 'V':
4564 if (tex_scan_mandate_keyword("void", 1)) {
4565 options |= noad_option_void;
4566 }
4567 break;
4568 case 'p': case 'P':
4569 if (tex_scan_mandate_keyword("phantom", 1)) {
4570 options |= noad_option_phantom;
4571 }
4572 break;
4573 case 'c': case 'C':
4574 if (tex_scan_mandate_keyword("class", 1)) {
4575 mainclass = tex_scan_math_class_number(0);
4576 }
4577 break;
4578 case 'r': case 'R':
4579 if (tex_scan_mandate_keyword("rightclass", 1)) {
4580 halfword c = tex_scan_math_class_number(0);
4581
4582 if (valid_math_class_code(c)) {
4583 rightclass = c;
4584 }
4585 }
4586 break;
4587 case 's': case 'S':
4588 switch (tex_scan_character("coiCOI", 0, 0, 0)) {
4589 case 'c': case 'C':
4590 if (tex_scan_mandate_keyword("scale", 2)) {
4591 options |= noad_option_scale;
4592 }
4593 break;
4594 case 'o': case 'O':
4595 if (tex_scan_mandate_keyword("source", 2)) {
4596 source = tex_scan_integer(0, NULL);
4597 }
4598 break;
4599 case 'i': case 'I':
4600 if (tex_scan_mandate_keyword("single", 2)) {
4601 options |= noad_option_single;
4602 }
4603 break;
4604 default:
4605 tex_aux_show_keyword_error("scale|source|single");
4606 goto CHECK_PAIRING;
4607 }
4608 break;
4609 case 't': case 'T':
4610 if (tex_scan_mandate_keyword("top", 1)) {
4611 top = tex_scan_dimension(0, 0, 0, 0, NULL);
4612 }
4613 break;
4614 default:
4615 goto CHECK_PAIRING;
4616 }
4617 }
4618 CHECK_PAIRING:
4619 switch (st) {
4620 case no_fence_side:
4621 case left_fence_side:
4622 break;
4623 case left_operator_side:
4624 {
4625
4626 int indisplay = style == display_style || style == cramped_display_style;
4627
4628 if (! (has_option(options, noad_option_limits) || has_option(options, noad_option_no_limits))) {
4629
4630 options |= indisplay ? noad_option_limits : noad_option_no_limits;
4631 }
4632 }
4633 break;
4634 default:
4635 if (cur_group != math_fence_group) {
4636 tex_aux_append_math_fence_val(tex_no_math_code(), tex_no_dict_code(), open_noad_subtype);
4637 }
4638 switch (cur_group) {
4639 case math_fence_group:
4640 break;
4641 case math_inline_group:
4642 case math_display_group:
4643 case math_number_group:
4644 tex_aux_scan_delimiter(null, no_mathcode, unset_noad_class);
4645 if (st == middle_fence_side) {
4646 tex_handle_error(
4647 normal_error_type,
4648 "Extra \\middle",
4649 "I'm ignoring a \\middle that had no matching \\left."
4650 );
4651 } else {
4652 tex_handle_error(
4653 normal_error_type,
4654 "Extra \\right",
4655 "I'm ignoring a \\right that had no matching \\left."
4656 );
4657 }
4658 break;
4659 default:
4660 tex_off_save();
4661 }
4662 }
4663
4666 {
4667 halfword fence = tex_new_node(fence_noad, st);
4668 halfword delimiter = tex_new_node(delimiter_node, 0);
4669 halfword autoclass = unset_noad_class;
4670 fence_delimiter_list(fence) = delimiter;
4671 noad_height(fence) = ht;
4672 noad_depth(fence) = dp;
4673 noad_options(fence) = options;
4674 set_noad_classes(fence, mainclass);
4675 if (leftclass != unset_noad_class) {
4676 set_noad_left_class(fence, leftclass);
4677 }
4678 if (rightclass != unset_noad_class) {
4679 set_noad_right_class(fence, rightclass);
4680 }
4681 noad_italic(fence) = 0;
4682 noad_source(fence) = source;
4683
4684 fence_top_overshoot(fence) = top;
4685 fence_bottom_overshoot(fence) = bottom;
4686
4691 if (mainclass == unset_noad_class) {
4692 mainclass = node_subtype(delimiter);
4693 if (mainclass == unset_noad_class || mainclass == ordinary_noad_subtype) {
4694 switch (st) {
4695 case left_fence_side:
4696 mainclass = open_noad_subtype;
4697 break;
4698 case middle_fence_side:
4699 mainclass = middle_noad_subtype;
4700 break;
4701 case right_fence_side:
4702 mainclass = close_noad_subtype;
4703 break;
4704 }
4705 }
4706 set_noad_main_class(fence, mainclass);
4707 }
4708
4709 switch (st) {
4710 case left_fence_side:
4711 autoclass = open_noad_subtype;
4712 break;
4713 case middle_fence_side:
4714 autoclass = middle_noad_subtype;
4715 break;
4716 case right_fence_side:
4717 autoclass = close_noad_subtype;
4718 break;
4719 }
4720
4721 tex_aux_scan_delimiter(delimiter, no_mathcode, autoclass);
4722
4723 if (attrlist) {
4724 tex_attach_attribute_list_attribute(fence, attrlist);
4725 tex_attach_attribute_list_attribute(delimiter, attrlist);
4726 }
4727 switch (st) {
4728 case left_fence_side:
4729 tex_aux_append_math_fence(fence, open_noad_subtype);
4730 fence_nesting_factor(fence) = factor;
4731 break;
4732 case middle_fence_side:
4733 tex_aux_append_math_fence(fence, middle_noad_subtype);
4734 break;
4735 case right_fence_side:
4736 tex_aux_append_math_fence(fence, close_noad_subtype);
4737 fence_nesting_factor(fence) = factor;
4738 break;
4739 case left_operator_side:
4740 {
4741 halfword top = tex_new_node(sub_mlist_node, 0);
4742 halfword bottom = tex_new_node(sub_mlist_node, 0);
4743 fence_delimiter_top(fence) = top;
4744 fence_delimiter_bottom(fence) = bottom;
4745 tex_aux_push_math(math_fence_group, style);
4746 node_next(cur_list.head) = fence;
4747 cur_list.tail = fence;
4748 cur_list.delimiter = fence;
4749 saved_operator_initialize();
4750 saved_operator_variant = math_limits_top;
4751 lmt_save_state.save_stack_data.ptr += saved_operator_n_of_records;
4752 tex_aux_push_math(math_operator_group, tex_math_style_variant(style, math_parameter_superscript_variant));
4753 tex_scan_left_brace();
4754 }
4755 break;
4756 case no_fence_side:
4757 {
4758 halfword n = tex_new_node(simple_noad, fenced_noad_subtype);
4759 halfword l = tex_new_node(sub_mlist_node, 0);
4760 tex_tail_append(n);
4761 set_noad_main_class(n, mainclass);
4762 noad_nucleus(n) = l;
4763 kernel_math_list(noad_nucleus(n)) = fence;
4764 }
4765 break;
4766 default:
4767 tex_confusion("left right fence");
4768 break;
4769 }
4770 }
4771}
4772
4773
4779
4780static void tex_aux_check_second_math_shift(void)
4781{
4782 tex_get_x_token();
4783 if (cur_cmd != math_shift_cmd) {
4784 tex_back_input(cur_tok);
4785 tex_handle_error(
4786 normal_error_type,
4787 "Display math should end with $$",
4788 "The '$' that I just saw supposedly matches a previous '$$'. So I shall assume\n"
4789 "that you typed '$$' both times."
4790 );
4791 }
4792}
4793
4794static void tex_aux_check_display_math_end(void)
4795{
4796 switch (cur_chr) {
4797 case end_display_math_code:
4798 case end_math_mode_code:
4799 return;
4800 }
4801 tex_handle_error(
4802 normal_error_type,
4803 "Display math should end with \\Ustopdisplaymath or \\Ustopmathmode",
4804 "I shall assume that you typed that."
4805 );
4806}
4807
4808static void tex_aux_check_inline_math_end(void)
4809{
4810 switch (cur_chr) {
4811 case end_inline_math_code:
4812 case end_math_mode_code:
4813 return;
4814 }
4815 tex_handle_error(
4816 normal_error_type,
4817 "Inline math should end with \\Ustopmath or \\Ustopmathmode",
4818 "I shall assume that you typed that."
4819 );
4820}
4821
4822static void tex_aux_resume_after_display(void)
4823{
4824 switch (cur_group) {
4825 case math_display_group:
4826 tex_aux_unsave_math();
4827 cur_list.prev_graf += 3;
4828 tex_push_nest();
4829 cur_list.mode = hmode;
4830 cur_list.space_factor = default_space_factor;
4831
4832 tex_tail_append(tex_new_par_node(parameter_par_subtype));
4833 tex_get_x_token();
4834 if (cur_cmd != spacer_cmd) {
4835 tex_back_input(cur_tok);
4836 }
4837 if (lmt_nest_state.nest_data.ptr == 1) {
4838 tex_build_page(after_display_page_context, 0);
4839 }
4840 break;
4841 default:
4842 tex_confusion("finishing display math");
4843 break;
4844 }
4845}
4846
4847
4864
4865static void tex_aux_inject_display_skip(quarterword param, quarterword subtype)
4866{
4867 if (param > 0) {
4868 switch (display_skip_mode_par) {
4869 case display_skip_default :
4870 case display_skip_always :
4871 break;
4872 case display_skip_non_zero:
4873 if (tex_glue_is_zero(glue_parameter(param))) {
4874 return;
4875 } else {
4876 break;
4877 }
4878 case display_skip_ignore:
4879 return;
4880 default:
4881
4882 break;
4883 }
4884 tex_tail_append(tex_new_param_glue_node(param, subtype));
4885 }
4886}
4887
4888static void tex_aux_finish_displayed_math(int atleft, halfword eqnumber, halfword equation)
4889{
4890
4891 halfword equation_box;
4892
4893 scaled equation_width;
4894
4895 scaled line_width;
4896
4897 scaled number_width;
4898
4899 scaled number_plus_gap_width;
4900
4901 scaled indent;
4902
4903 scaled displacement;
4904
4905 quarterword glue_above, glue_below;
4906
4907 quarterword subtype_above, subtype_below;
4908
4909 scaled eqno_width;
4910
4911 int swap_dir = math_direction_par != pre_display_direction_par;
4912 if (eqnumber && swap_dir) {
4913 atleft = ! atleft;
4914 }
4915
4916 lmt_packaging_state.post_adjust_tail = post_adjust_head;
4917 lmt_packaging_state.pre_adjust_tail = pre_adjust_head;
4918 lmt_packaging_state.post_migrate_tail = post_migrate_head;
4919 lmt_packaging_state.pre_migrate_tail = pre_migrate_head;
4920
4921 equation_box = tex_hpack(equation, 0, packing_additional, direction_unknown, holding_none_option, box_limit_none);
4922 node_subtype(equation_box) = equation_list;
4923 attach_current_attribute_list(equation_box);
4924 equation = box_list(equation_box);
4925
4926 equation_width = box_width(equation_box);
4927 line_width = display_width_par;
4928 indent = display_indent_par;
4929 if (eqnumber) {
4930 number_width = box_width(eqnumber);
4931 eqno_width = number_width;
4932 number_plus_gap_width = number_width + tex_round_xn_over_d(math_eqno_gap_step_par, tex_get_math_quad_style(text_style), scaling_factor);
4933 node_subtype(eqnumber) = equation_number_list;
4934
4935 } else {
4936 number_width = 0;
4937 eqno_width = 0;
4938 number_plus_gap_width = 0;
4939 }
4940 if (equation_width + number_plus_gap_width > line_width) {
4941
4947 if ((number_width != 0) && ((equation_width - lmt_packaging_state.total_shrink[normal_glue_order] + number_plus_gap_width <= line_width)
4948 || (lmt_packaging_state.total_shrink[fi_glue_order] != 0)
4949 || (lmt_packaging_state.total_shrink[fil_glue_order] != 0)
4950 || (lmt_packaging_state.total_shrink[fill_glue_order] != 0)
4951 || (lmt_packaging_state.total_shrink[filll_glue_order] != 0))) {
4952 box_list(equation_box) = null;
4953 tex_flush_node(equation_box);
4954 equation_box = tex_hpack(equation, line_width - number_plus_gap_width, packing_exactly, direction_unknown, holding_none_option, box_limit_none);
4955 node_subtype(equation_box) = equation_list;
4956 attach_current_attribute_list(equation_box);
4957 } else {
4958 number_width = 0;
4959 if (equation_width > line_width) {
4960 box_list(equation_box) = null;
4961 tex_flush_node(equation_box);
4962 equation_box = tex_hpack(equation, line_width, packing_exactly, direction_unknown, holding_none_option, box_limit_none);
4963 node_subtype(equation_box) = equation_list;
4964 attach_current_attribute_list(equation_box);
4965 }
4966 }
4967 equation_width = box_width(equation_box);
4968 }
4969
4979 displacement = tex_half_scaled(line_width - equation_width);
4980 if ((number_width > 0) && (displacement < 2 * number_width)) {
4981
4982 displacement = tex_half_scaled(line_width - equation_width - number_width);
4983
4987 if (equation && node_type(equation) == glue_node) {
4988 displacement = 0;
4989 }
4990 }
4991 tex_tail_append(tex_new_penalty_node(pre_display_penalty_par, before_display_penalty_subtype));
4992 if ((displacement + indent <= pre_display_size_par) || ((cur_list.math_dir == dir_lefttoright) && atleft)
4993 || ((cur_list.math_dir == dir_righttoleft) && ! atleft)) {
4994
4995 glue_above = above_display_skip_code;
4996 subtype_above = above_display_skip_glue;
4997 glue_below = below_display_skip_code;
4998 subtype_below = below_display_skip_glue;
4999 } else {
5000 glue_above = above_display_short_skip_code;
5001 subtype_above = above_display_short_skip_glue;
5002 glue_below = below_display_short_skip_code;
5003 subtype_below = below_display_short_skip_glue;
5004 }
5005
5014 if (eqnumber && atleft && (number_width == 0)) {
5015
5016 box_shift_amount(eqnumber) = 0;
5017
5018
5019 tex_append_to_vlist(eqnumber, lua_key_index(equation_number), NULL);
5020 tex_tail_append(tex_new_penalty_node(infinite_penalty, equation_number_penalty_subtype));
5021 } else {
5022 tex_aux_inject_display_skip(glue_above, subtype_above);
5023 }
5024 if (number_width != 0) {
5025 scaled shift = line_width - equation_width - number_width - displacement;
5026 halfword move = tex_new_kern_node(shift, explicit_kern_subtype);
5027 if (atleft) {
5028 if (swap_dir) {
5029 if (math_direction_par == dir_lefttoright) {
5030
5031 halfword kern = tex_new_kern_node(shift + number_width, explicit_kern_subtype);
5032 tex_try_couple_nodes(eqnumber, move);
5033 tex_try_couple_nodes(move, equation_box);
5034 tex_try_couple_nodes(equation_box, kern);
5035 } else {
5036
5037 tex_try_couple_nodes(eqnumber, move);
5038 tex_try_couple_nodes(move, equation_box);
5039 }
5040 } else {
5041 halfword kern;
5042 if (math_direction_par == dir_lefttoright) {
5043
5044 kern = tex_new_kern_node(shift + number_width, explicit_kern_subtype);
5045 } else {
5046
5047 kern = tex_new_kern_node(shift, explicit_kern_subtype);
5048 }
5049 tex_try_couple_nodes(eqnumber, move);
5050 tex_try_couple_nodes(move, equation_box);
5051 tex_try_couple_nodes(equation_box, kern);
5052 }
5053 equation_box = eqnumber;
5054 } else {
5055 if (swap_dir) {
5056 if (math_direction_par == dir_lefttoright) {
5057
5058 } else {
5059
5060 }
5061 tex_try_couple_nodes(equation_box, move);
5062 tex_try_couple_nodes(move, eqnumber);
5063 } else {
5064 halfword kern;
5065 if (math_direction_par == dir_lefttoright) {
5066
5067 kern = tex_new_kern_node(displacement, explicit_kern_subtype);
5068 } else {
5069
5070 kern = tex_new_kern_node(shift + number_width, explicit_kern_subtype);
5071 }
5072 tex_try_couple_nodes(kern, equation_box);
5073 tex_try_couple_nodes(equation_box, move);
5074 tex_try_couple_nodes(move, eqnumber);
5075 equation_box = kern;
5076 }
5077 }
5078 equation_box = tex_hpack(equation_box, 0, packing_additional, direction_unknown, holding_none_option, box_limit_none);
5079 node_subtype(equation_box) = equation_list;
5080 attach_current_attribute_list(equation_box);
5081 box_shift_amount(equation_box) = indent;
5082 } else {
5083 box_shift_amount(equation_box) = indent + displacement;
5084 }
5085
5086 if (pre_adjust_head != lmt_packaging_state.pre_adjust_tail) {
5087 tex_inject_adjust_list(pre_adjust_head, 1, lmt_linebreak_state.just_box, NULL);
5088 }
5089 lmt_packaging_state.pre_adjust_tail = null;
5090
5091 if (pre_migrate_head != lmt_packaging_state.pre_migrate_tail) {
5092 tex_append_list(pre_migrate_head, lmt_packaging_state.pre_migrate_tail);
5093
5094
5095
5096 }
5097
5098 tex_append_to_vlist(equation_box, lua_key_index(equation), NULL);
5099 if (eqnumber && number_width == 0 && ! atleft) {
5100 tex_tail_append(tex_new_penalty_node(infinite_penalty, equation_number_penalty_subtype));
5101
5102 box_shift_amount(eqnumber) = indent + line_width - eqno_width ;
5103
5104
5105 tex_append_to_vlist(eqnumber, lua_key_index(equation_number), NULL);
5106 glue_below = 0;
5107 }
5108
5109 if (post_migrate_head != lmt_packaging_state.post_migrate_tail) {
5110 tex_append_list(post_migrate_head, lmt_packaging_state.post_migrate_tail);
5111
5112
5113
5114 }
5115 lmt_packaging_state.post_migrate_tail = null;
5116 if (lmt_packaging_state.post_adjust_tail) {
5117 if (post_adjust_head != lmt_packaging_state.post_adjust_tail) {
5118 tex_inject_adjust_list(post_adjust_head, 1, null, NULL);
5119 }
5120 lmt_packaging_state.post_adjust_tail = null;
5121 }
5122
5123 tex_tail_append(tex_new_penalty_node(post_display_penalty_par, after_display_penalty_subtype));
5124 tex_aux_inject_display_skip(glue_below, subtype_below);
5125 tex_aux_resume_after_display();
5126}
5127
5128
5139
5140
5141
5142inline static int tex_aux_class_from_glyph(halfword n)
5143{
5144 return node_subtype(n) - (node_subtype(n) > glyph_math_extra_subtype ? glyph_math_extra_subtype : glyph_math_ordinary_subtype);
5145}
5146
5147inline static int tex_aux_class_from_list(halfword n)
5148{
5149 switch (node_subtype(n)) {
5150 case math_fraction_list:
5151 return fraction_noad_subtype;
5152 case math_accent_list:
5153 return accent_noad_subtype;
5154 case math_radical_list:
5155 return radical_noad_subtype;
5156 default:
5157 return 0;
5158 }
5159}
5160
5161static int tex_aux_short_math(halfword m)
5162{
5163
5164 if (m) {
5165
5175 switch (node_type(m)) {
5176 case kern_node:
5177
5178 m = node_next(m);
5179 break;
5180 case hlist_node:
5181 case vlist_node:
5182
5186 if (! node_next(m) && tex_math_has_class_option(tex_aux_class_from_list(m), short_inline_class_option)) {
5187 scaled threshold = short_inline_math_threshold_par;
5188 if (threshold > 0 && box_width(m) <= threshold) {
5189 return 1;
5190 }
5191 }
5192 return 0;
5193 }
5194
5195 if (m) {
5196 switch (node_type(m)) {
5197 case glyph_node:
5198 if (tex_math_has_class_option(tex_aux_class_from_glyph(m), short_inline_class_option)) {
5199 m = node_next(m);
5200 break;
5201 } else {
5202 return 0;
5203 }
5204 default:
5205 return 0;
5206 }
5207 } else {
5208 return 0;
5209 }
5210
5211 if (m) {
5212 switch (node_type(m)) {
5213 case vlist_node:
5214 case hlist_node:
5215 switch (node_subtype(m)) {
5216 case math_sup_list:
5217 case math_sub_list:
5218 case math_pre_post_list:
5219 case math_scripts_list:
5220 m = node_next(m);
5221 break;
5222 }
5223
5224 }
5225 }
5226
5227 if (m && node_type(m) == kern_node) {
5228 m = node_next(m);
5229 }
5230 return ! m;
5231 }
5232 return 0;
5233}
5234
5235void tex_run_math_shift(void)
5236{
5237 switch (cur_group) {
5238 case math_inline_group:
5239 case math_display_group:
5240 case math_number_group:
5241 {
5242
5243 halfword eqnumber = null;
5244
5245 int atleft = 0;
5246
5247 int mode = cur_list.mode;
5248 int mathmode = cur_list.math_mode;
5249
5250 halfword mathlist = tex_aux_finish_math_list(null);
5251 int mathleft = cur_list.math_begin;
5252 int mathright = cur_list.math_end;
5253 if (cur_cmd == math_shift_cs_cmd) {
5254 switch (cur_chr) {
5255 case begin_inline_math_code:
5256 case begin_display_math_code:
5257 case begin_math_mode_code:
5258 tex_you_cant_error(NULL);
5259 break;
5260 }
5261 }
5262 if (cur_list.mode == -mode) {
5263
5264 AGAIN:
5265 switch (cur_cmd) {
5266 case math_shift_cmd:
5267 tex_aux_check_second_math_shift();
5268 break;
5269 case end_paragraph_cmd:
5270 tex_get_x_token();
5271 goto AGAIN;
5272 default:
5273 tex_aux_check_display_math_end();
5274 break;
5275 }
5276 tex_run_mlist_to_hlist(mathlist, 0, text_style, unset_noad_class, unset_noad_class);
5277 eqnumber = tex_hpack(node_next(temp_head), 0, packing_additional, direction_unknown, holding_none_option, box_limit_none);
5278 attach_current_attribute_list(eqnumber);
5279 tex_aux_unsave_math();
5280
5281 lmt_save_state.save_stack_data.ptr -= saved_equation_number_n_of_records;
5282
5283 atleft = saved_equation_number_location == left_location_code;
5284 mode = cur_list.mode;
5285 mathlist = tex_aux_finish_math_list(null);
5286
5287
5288
5289 }
5290 if (mode == inline_mmode) {
5291
5292
5300 halfword beginmath = tex_new_node(math_node, begin_inline_math);
5301 halfword endmath = tex_new_node(math_node, end_inline_math);
5302 halfword shortmath = 0;
5303 if (mathmode) {
5304 switch (cur_cmd) {
5305 case math_shift_cs_cmd:
5306 if (cur_chr != end_display_math_code && cur_chr != end_math_mode_code) {
5307 tex_aux_check_second_math_shift();
5308 }
5309 break;
5310 case math_shift_cmd:
5311 tex_aux_check_second_math_shift();
5312 break;
5313 }
5314 } else if (cur_cmd == math_shift_cs_cmd) {
5315 tex_aux_check_inline_math_end();
5316 }
5317 tex_tail_append(beginmath);
5318 if (pre_inline_penalty_par != max_integer) {
5319 math_penalty(beginmath) = pre_inline_penalty_par;
5320 }
5321
5322 switch (math_skip_mode_par) {
5323 case math_skip_surround_when_zero:
5324 if (! tex_glue_is_zero(math_skip_par)) {
5325 tex_copy_glue_values(beginmath, math_skip_par);
5326 } else {
5327 math_surround(beginmath) = math_surround_par;
5328 }
5329 break ;
5330 case math_skip_always_left:
5331 case math_skip_always_both:
5332 case math_skip_only_when_skip:
5333 tex_copy_glue_values(beginmath, math_skip_par);
5334 break ;
5335 case math_skip_always_right:
5336 case math_skip_ignore:
5337 break ;
5338 case math_skip_always_surround:
5339 default:
5340 math_surround(beginmath) = math_surround_par;
5341 break;
5342 }
5343
5344 if (cur_list.math_dir) {
5345 tex_tail_append(tex_new_dir(normal_dir_subtype, math_direction_par));
5346 }
5347 tex_run_mlist_to_hlist(mathlist, cur_list.mode > nomode, is_valid_math_style(cur_list.math_main_style) ? cur_list.math_main_style : text_style, cur_list.math_begin, cur_list.math_end);
5348 shortmath = tex_aux_short_math(node_next(temp_head));
5349 tex_try_couple_nodes(cur_list.tail, node_next(temp_head));
5350 cur_list.tail = tex_tail_of_node_list(cur_list.tail);
5351 if (cur_list.math_dir) {
5352 tex_tail_append(tex_new_dir(cancel_dir_subtype, math_direction_par));
5353 }
5354 cur_list.math_dir = 0;
5355 tex_tail_append(endmath);
5356
5357 if (post_inline_penalty_par != max_integer) {
5358 math_penalty(endmath) = post_inline_penalty_par;
5359 }
5360
5361 switch (math_skip_mode_par) {
5362 case math_skip_surround_when_zero :
5363 if (! tex_glue_is_zero(math_skip_par)) {
5364 tex_copy_glue_values(endmath, math_skip_par);
5365 math_surround(endmath) = 0;
5366 } else {
5367 math_surround(endmath) = math_surround_par;
5368 }
5369 break;
5370 case math_skip_always_right:
5371 case math_skip_always_both:
5372 case math_skip_only_when_skip:
5373 tex_copy_glue_values(endmath, math_skip_par);
5374 break;
5375 case math_skip_always_left:
5376 case math_skip_ignore:
5377 break;
5378 case math_skip_always_surround:
5379 default:
5380 math_surround(endmath) = math_surround_par;
5381 break;
5382 }
5383
5384 if (shortmath) {
5385 if (pre_short_inline_penalty_par != max_integer) {
5386 math_penalty(beginmath) = pre_short_inline_penalty_par;
5387 }
5388 if (post_short_inline_penalty_par != max_integer) {
5389 math_penalty(endmath) = post_short_inline_penalty_par;
5390 }
5391 tex_add_math_option(beginmath, math_option_short);
5392 tex_add_math_option(endmath, math_option_short);
5393 }
5394 cur_list.space_factor = default_space_factor;
5395 mathleft = cur_list.math_begin;
5396 mathright = cur_list.math_end;
5397 math_tolerance(beginmath) = math_tolerance_par;
5398 math_pre_tolerance(beginmath) = math_pre_tolerance_par;
5399 math_tolerance(endmath) = tolerance_par;
5400 math_pre_tolerance(endmath) = pre_tolerance_par;
5401 tex_aux_unsave_math();
5402 } else {
5403 if (! eqnumber) {
5404 if (cur_cmd == math_shift_cmd) {
5405 tex_aux_check_second_math_shift();
5406 } else {
5407 tex_aux_check_display_math_end();
5408 }
5409 }
5410 tex_run_mlist_to_hlist(mathlist, 0, display_style, cur_list.math_begin, cur_list.math_end);
5411 mathleft = cur_list.math_begin;
5412 mathright = cur_list.math_end;
5413 tex_aux_finish_displayed_math(atleft, eqnumber, node_next(temp_head));
5414 }
5415
5416 update_tex_math_left_class(mathleft);
5417 update_tex_math_right_class(mathright);
5418
5419 lmt_math_state.last_left = mathleft;
5420 lmt_math_state.last_right = mathright;
5421 }
5422 break;
5423 default:
5424 tex_off_save();
5425 break;
5426 }
5427}
5428
5429
5436
5437void tex_finish_display_alignment(halfword head, halfword tail, halfword prevdepth)
5438{
5439 tex_handle_assignments();
5440 AGAIN:
5441 switch (cur_cmd) {
5442 case math_shift_cmd:
5443 tex_aux_check_second_math_shift();
5444 break;
5445 case end_paragraph_cmd:
5446 tex_get_x_token();
5447 goto AGAIN;
5448 default:
5449 tex_aux_check_display_math_end();
5450 break;
5451 }
5452 tex_pop_nest();
5453 tex_tail_append(tex_new_penalty_node(pre_display_penalty_par, before_display_penalty_subtype));
5454 tex_aux_inject_display_skip(above_display_skip_code, above_display_skip_glue);
5455 node_next(cur_list.tail) = head;
5456 if (head && tail) {
5457 cur_list.tail = tail;
5458 }
5459 tex_tail_append(tex_new_penalty_node(post_display_penalty_par, after_display_penalty_subtype));
5460 tex_aux_inject_display_skip(below_display_skip_code, below_display_skip_glue);
5461 cur_list.prev_depth = prevdepth;
5462 tex_aux_resume_after_display();
5463}
5464
5465
5471
5472static void tex_aux_define_inl_math_parameters(int size, int param, scaled value, int level)
5473{
5474 switch (size) {
5475 case script_size:
5476 tex_def_math_parameter(script_style, param, value, level, indirect_math_regular, 1);
5477 tex_def_math_parameter(cramped_script_style, param, value, level, indirect_math_regular, 1);
5478 break;
5479 case script_script_size:
5480 tex_def_math_parameter(script_script_style, param, value, level, indirect_math_regular, 1);
5481 tex_def_math_parameter(cramped_script_script_style, param, value, level, indirect_math_regular, 1);
5482 break;
5483 default:
5484 tex_def_math_parameter(text_style, param, value, level, indirect_math_regular, 1);
5485 tex_def_math_parameter(cramped_text_style, param, value, level, indirect_math_regular, 1);
5486 break;
5487 }
5488}
5489
5490static void tex_aux_define_dis_math_parameters(int size, int param, scaled value, int level)
5491{
5492 if (size == text_size) {
5493 tex_def_math_parameter(display_style, param, value, level, indirect_math_regular, 1);
5494 tex_def_math_parameter(cramped_display_style, param, value, level, indirect_math_regular, 1);
5495 }
5496}
5497
5498
5518
5519static void tex_aux_define_all_math_parameters(int size, int param, scaled value, int level)
5520{
5521 switch (size) {
5522 case script_size:
5523 tex_def_math_parameter(script_style, param, value, level, indirect_math_regular, 1);
5524 tex_def_math_parameter(cramped_script_style, param, value, level, indirect_math_regular, 1);
5525 break;
5526 case script_script_size:
5527 tex_def_math_parameter(script_script_style, param, value, level, indirect_math_regular, 1);
5528 tex_def_math_parameter(cramped_script_script_style, param, value, level, indirect_math_regular, 1);
5529 break;
5530 default:
5531 tex_def_math_parameter(text_style, param, value, level, indirect_math_regular, 1);
5532 tex_def_math_parameter(cramped_text_style, param, value, level, indirect_math_regular, 1);
5533 tex_def_math_parameter(display_style, param, value, level, indirect_math_regular, 1);
5534 tex_def_math_parameter(cramped_display_style, param, value, level, indirect_math_regular, 1);
5535 break;
5536 }
5537}
5538
5539
5552
5553# define total_mathsy_parameters 22
5554# define total_mathex_parameters 13
5555
5556# define mathsy(A,B) font_parameter(tex_fam_fnt(2,A),B)
5557# define mathex(A,B) font_parameter(tex_fam_fnt(3,A),B)
5558
5559# define math_x_height(A) mathsy(A,5)
5560# define math_quad(A) mathsy(A,6)
5561# define num1(A) mathsy(A,8)
5562# define num2(A) mathsy(A,9)
5563# define num3(A) mathsy(A,10)
5564# define denom1(A) mathsy(A,11)
5565# define denom2(A) mathsy(A,12)
5566# define sup1(A) mathsy(A,13)
5567# define sup2(A) mathsy(A,14)
5568# define sup3(A) mathsy(A,15)
5569# define sub1(A) mathsy(A,16)
5570# define sub2(A) mathsy(A,17)
5571# define sup_drop(A) mathsy(A,18)
5572# define sub_drop(A) mathsy(A,19)
5573# define delim1(A) mathsy(A,20)
5574# define delim2(A) mathsy(A,21)
5575# define axis_height(A) mathsy(A,22)
5576
5577# define default_rule_thickness(A) mathex(A,8)
5578# define big_operator_spacing1(A) mathex(A,9)
5579# define big_operator_spacing2(A) mathex(A,10)
5580# define big_operator_spacing3(A) mathex(A,11)
5581# define big_operator_spacing4(A) mathex(A,12)
5582# define big_operator_spacing5(A) mathex(A,13)
5583
5584# define math_parameter(a,b) ((font_math_parameter_count(a) >= b) ? font_math_parameter(a,b) : undefined_math_parameter)
5585
5586inline static scaled tex_aux_get_font_math_parameter(scaled scale, halfword f, int id)
5587{
5588 scaled v = math_parameter(f, id);
5589 if (v == undefined_math_parameter) {
5590 return v;
5591 } else {
5592 return v ? scaledround(0.001 * scale * v) : 0;
5593 }
5594}
5595
5596inline static scaled tex_aux_get_font_math_quantity(scaled scale, halfword v)
5597{
5598 return v ? scaledround(0.001 * scale * v) : 0;
5599}
5600
5601
5605
5606void tex_fixup_math_parameters(int fam, int size, int f, int level)
5607{
5608 scaled scale = tex_get_math_font_scale(f, size);
5609
5610 if (tracing_math_par > 1) {
5611 tex_begin_diagnostic();
5612 tex_print_format("[math: fixing up font, family %i, size %i, font %i, level %i]", fam, size, f, level);
5613 tex_end_diagnostic();
5614 }
5615
5616
5617
5618
5619 tex_aux_define_all_math_parameters(size, math_parameter_quad, tex_aux_get_font_math_quantity (scale, font_size(f)), level);
5620 tex_aux_define_all_math_parameters(size, math_parameter_exheight, tex_aux_get_font_math_quantity (scale, font_parameter(f, ex_height_code)), level);
5621 tex_aux_define_all_math_parameters(size, math_parameter_axis, tex_aux_get_font_math_parameter(scale, f, AxisHeight), level);
5622
5623 tex_aux_define_all_math_parameters(size, math_parameter_accent_base_height, tex_aux_get_font_math_parameter(scale, f, AccentBaseHeight), level);
5624 tex_aux_define_all_math_parameters(size, math_parameter_accent_base_depth, tex_aux_get_font_math_parameter(scale, f, AccentBaseDepth), level);
5625 tex_aux_define_all_math_parameters(size, math_parameter_flattened_accent_base_height, tex_aux_get_font_math_parameter(scale, f, FlattenedAccentBaseHeight), level);
5626 tex_aux_define_all_math_parameters(size, math_parameter_flattened_accent_base_depth, tex_aux_get_font_math_parameter(scale, f, FlattenedAccentBaseDepth), level);
5627 tex_aux_define_all_math_parameters(size, math_parameter_overbar_kern, tex_aux_get_font_math_parameter(scale, f, OverbarExtraAscender), level);
5628 tex_aux_define_all_math_parameters(size, math_parameter_overbar_rule, tex_aux_get_font_math_parameter(scale, f, OverbarRuleThickness), level);
5629 tex_aux_define_all_math_parameters(size, math_parameter_overbar_vgap, tex_aux_get_font_math_parameter(scale, f, OverbarVerticalGap), level);
5630 tex_aux_define_all_math_parameters(size, math_parameter_underbar_kern, tex_aux_get_font_math_parameter(scale, f, UnderbarExtraDescender), level);
5631 tex_aux_define_all_math_parameters(size, math_parameter_underbar_rule, tex_aux_get_font_math_parameter(scale, f, UnderbarRuleThickness ), level);
5632 tex_aux_define_all_math_parameters(size, math_parameter_underbar_vgap, tex_aux_get_font_math_parameter(scale, f, UnderbarVerticalGap), level);
5633 tex_aux_define_all_math_parameters(size, math_parameter_under_delimiter_vgap, tex_aux_get_font_math_parameter(scale, f, StretchStackGapAboveMin), level);
5634 tex_aux_define_all_math_parameters(size, math_parameter_under_delimiter_bgap, tex_aux_get_font_math_parameter(scale, f, StretchStackBottomShiftDown), level);
5635 tex_aux_define_all_math_parameters(size, math_parameter_over_delimiter_vgap, tex_aux_get_font_math_parameter(scale, f, StretchStackGapBelowMin), level);
5636 tex_aux_define_all_math_parameters(size, math_parameter_over_delimiter_bgap, tex_aux_get_font_math_parameter(scale, f, StretchStackTopShiftUp), level);
5637 tex_aux_define_all_math_parameters(size, math_parameter_radical_kern, tex_aux_get_font_math_parameter(scale, f, RadicalExtraAscender), level);
5638 tex_aux_define_all_math_parameters(size, math_parameter_radical_rule, tex_aux_get_font_math_parameter(scale, f, RadicalRuleThickness), level);
5639 tex_aux_define_all_math_parameters(size, math_parameter_radical_degree_before, tex_aux_get_font_math_parameter(scale, f, RadicalKernBeforeDegree), level);
5640 tex_aux_define_all_math_parameters(size, math_parameter_radical_degree_after, tex_aux_get_font_math_parameter(scale, f, RadicalKernAfterDegree), level);
5641 tex_aux_define_all_math_parameters(size, math_parameter_subscript_shift_drop, tex_aux_get_font_math_parameter(scale, f, SubscriptBaselineDropMin), level);
5642 tex_aux_define_all_math_parameters(size, math_parameter_superscript_shift_drop, tex_aux_get_font_math_parameter(scale, f, SuperscriptBaselineDropMax), level);
5643 tex_aux_define_all_math_parameters(size, math_parameter_subscript_shift_down, tex_aux_get_font_math_parameter(scale, f, SubscriptShiftDown), level);
5644 tex_aux_define_all_math_parameters(size, math_parameter_prime_shift_drop, tex_aux_get_font_math_parameter(scale, f, PrimeBaselineDropMax), level);
5645 tex_aux_define_all_math_parameters(size, math_parameter_subscript_top_max, tex_aux_get_font_math_parameter(scale, f, SubscriptTopMax), level);
5646 tex_aux_define_all_math_parameters(size, math_parameter_superscript_bottom_min, tex_aux_get_font_math_parameter(scale, f, SuperscriptBottomMin), level);
5647 tex_aux_define_all_math_parameters(size, math_parameter_superscript_subscript_bottom_max, tex_aux_get_font_math_parameter(scale, f, SuperscriptBottomMaxWithSubscript), level);
5648 tex_aux_define_all_math_parameters(size, math_parameter_subscript_superscript_vgap, tex_aux_get_font_math_parameter(scale, f, SubSuperscriptGapMin), level);
5649 tex_aux_define_all_math_parameters(size, math_parameter_limit_above_vgap, tex_aux_get_font_math_parameter(scale, f, UpperLimitGapMin), level);
5650 tex_aux_define_all_math_parameters(size, math_parameter_limit_above_bgap, tex_aux_get_font_math_parameter(scale, f, UpperLimitBaselineRiseMin), level);
5651 tex_aux_define_all_math_parameters(size, math_parameter_limit_below_vgap, tex_aux_get_font_math_parameter(scale, f, LowerLimitGapMin), level);
5652 tex_aux_define_all_math_parameters(size, math_parameter_limit_below_bgap, tex_aux_get_font_math_parameter(scale, f, LowerLimitBaselineDropMin), level);
5653 tex_aux_define_all_math_parameters(size, math_parameter_nolimit_sub_factor, tex_aux_get_font_math_parameter(scale, f, NoLimitSubFactor), level);
5654 tex_aux_define_all_math_parameters(size, math_parameter_nolimit_sup_factor, tex_aux_get_font_math_parameter(scale, f, NoLimitSupFactor), level);
5655 tex_aux_define_all_math_parameters(size, math_parameter_skewed_fraction_hgap, tex_aux_get_font_math_parameter(scale, f, SkewedFractionHorizontalGap), level);
5656 tex_aux_define_all_math_parameters(size, math_parameter_skewed_fraction_vgap, tex_aux_get_font_math_parameter(scale, f, SkewedFractionVerticalGap), level);
5657 tex_aux_define_all_math_parameters(size, math_parameter_space_before_script, tex_aux_get_font_math_parameter(scale, f, SpaceBeforeScript), level);
5658 tex_aux_define_all_math_parameters(size, math_parameter_space_after_script, tex_aux_get_font_math_parameter(scale, f, SpaceAfterScript), level);
5659 tex_aux_define_all_math_parameters(size, math_parameter_connector_overlap_min, tex_aux_get_font_math_parameter(scale, f, MinConnectorOverlap), level);
5660 tex_aux_define_all_math_parameters(size, math_parameter_superscript_snap, tex_aux_get_font_math_parameter(scale, f, SuperscriptSnap), level);
5661 tex_aux_define_all_math_parameters(size, math_parameter_subscript_snap, tex_aux_get_font_math_parameter(scale, f, SubscriptSnap), level);
5662 tex_aux_define_all_math_parameters(size, math_parameter_fraction_rule, tex_aux_get_font_math_parameter(scale, f, FractionRuleThickness), level);
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680 tex_aux_define_all_math_parameters(size, math_parameter_prime_space_after, tex_aux_get_font_math_parameter(scale, f, PrimeSpaceAfter), level);
5681 tex_aux_define_all_math_parameters(size, math_parameter_skewed_delimiter_tolerance, tex_aux_get_font_math_parameter(scale, f, SkewedDelimiterTolerance), level);
5682 tex_aux_define_all_math_parameters(size, math_parameter_accent_top_shift_up, tex_aux_get_font_math_parameter(scale, f, AccentTopShiftUp), level);
5683 tex_aux_define_all_math_parameters(size, math_parameter_accent_bottom_shift_down, tex_aux_get_font_math_parameter(scale, f, AccentBottomShiftDown), level);
5684 tex_aux_define_all_math_parameters(size, math_parameter_accent_top_overshoot, tex_aux_get_font_math_parameter(scale, f, AccentTopOvershoot), level);
5685 tex_aux_define_all_math_parameters(size, math_parameter_accent_bottom_overshoot, tex_aux_get_font_math_parameter(scale, f, AccentBottomOvershoot), level);
5686 tex_aux_define_all_math_parameters(size, math_parameter_accent_superscript_drop, tex_aux_get_font_math_parameter(scale, f, AccentSuperscriptDrop), level);
5687 tex_aux_define_all_math_parameters(size, math_parameter_accent_superscript_percent, tex_aux_get_font_math_parameter(scale, f, AccentSuperscriptPercent), level);
5688 tex_aux_define_all_math_parameters(size, math_parameter_accent_extend_margin, tex_aux_get_font_math_parameter(scale, f, AccentExtendMargin), level);
5689 tex_aux_define_all_math_parameters(size, math_parameter_flattened_accent_top_shift_up, tex_aux_get_font_math_parameter(scale, f, FlattenedAccentTopShiftUp), level);
5690 tex_aux_define_all_math_parameters(size, math_parameter_flattened_accent_bottom_shift_down, tex_aux_get_font_math_parameter(scale, f, FlattenedAccentBottomShiftDown), level);
5691 tex_aux_define_all_math_parameters(size, math_parameter_delimiter_extend_margin, tex_aux_get_font_math_parameter(scale, f, DelimiterExtendMargin), level);
5692 tex_aux_define_all_math_parameters(size, math_parameter_radical_extensible_after, tex_aux_get_font_math_parameter(scale, f, RadicalKernAfterExtensible), level);
5693 tex_aux_define_all_math_parameters(size, math_parameter_radical_extensible_before, tex_aux_get_font_math_parameter(scale, f, RadicalKernBeforeExtensible), level);
5694
5695
5696
5697 tex_aux_define_all_math_parameters(size, math_parameter_prime_width, math_parameter(f, PrimeWidthPercent), level);
5698 tex_aux_define_all_math_parameters(size, math_parameter_prime_raise, math_parameter(f, PrimeRaisePercent), level);
5699 tex_aux_define_all_math_parameters(size, math_parameter_prime_raise_composed, math_parameter(f, PrimeRaiseComposedPercent), level);
5700 tex_aux_define_all_math_parameters(size, math_parameter_radical_degree_raise, math_parameter(f, RadicalDegreeBottomRaisePercent), level);
5701
5702
5703
5704 tex_aux_define_all_math_parameters(size, math_parameter_x_scale, scaling_factor, level);
5705 tex_aux_define_all_math_parameters(size, math_parameter_y_scale, scaling_factor, level);
5706
5707
5708
5709 tex_aux_define_all_math_parameters(size, math_parameter_limit_above_kern, 0, level);
5710 tex_aux_define_all_math_parameters(size, math_parameter_limit_below_kern, 0, level);
5711 tex_aux_define_all_math_parameters(size, math_parameter_extra_superscript_shift, 0, level);
5712 tex_aux_define_all_math_parameters(size, math_parameter_extra_subscript_shift, 0, level);
5713 tex_aux_define_all_math_parameters(size, math_parameter_extra_superprescript_shift, 0, level);
5714 tex_aux_define_all_math_parameters(size, math_parameter_extra_subprescript_shift, 0, level);
5715 tex_aux_define_all_math_parameters(size, math_parameter_rule_height, 0, level);
5716 tex_aux_define_all_math_parameters(size, math_parameter_rule_depth, 0, level);
5717 tex_aux_define_all_math_parameters(size, math_parameter_superscript_shift_distance, 0, level);
5718 tex_aux_define_all_math_parameters(size, math_parameter_subscript_shift_distance, 0, level);
5719 tex_aux_define_all_math_parameters(size, math_parameter_superprescript_shift_distance, 0, level);
5720 tex_aux_define_all_math_parameters(size, math_parameter_subprescript_shift_distance, 0, level);
5721 tex_aux_define_all_math_parameters(size, math_parameter_extra_superscript_space, 0, level);
5722 tex_aux_define_all_math_parameters(size, math_parameter_extra_subscript_space, 0, level);
5723 tex_aux_define_all_math_parameters(size, math_parameter_extra_superprescript_space, 0, level);
5724 tex_aux_define_all_math_parameters(size, math_parameter_extra_subprescript_space, 0, level);
5725
5726
5727
5728 if (math_parameter(f, SubscriptShiftDownWithSuperscript) != undefined_math_parameter) {
5729 tex_aux_define_all_math_parameters(size, math_parameter_subscript_superscript_shift_down, tex_aux_get_font_math_parameter(scale, f, SubscriptShiftDownWithSuperscript), level);
5730 } else {
5731 tex_aux_define_all_math_parameters(size, math_parameter_subscript_superscript_shift_down, tex_aux_get_font_math_parameter(scale, f, SubscriptShiftDown), level);
5732 }
5733
5734
5735
5736 tex_aux_define_dis_math_parameters(size, math_parameter_delimiter_percent, math_parameter(f, DelimiterDisplayPercent), level);
5737 tex_aux_define_inl_math_parameters(size, math_parameter_delimiter_percent, math_parameter(f, DelimiterPercent), level);
5738
5739 tex_aux_define_dis_math_parameters(size, math_parameter_operator_size, tex_aux_get_font_math_parameter(scale, f, DisplayOperatorMinHeight), level);
5740 tex_aux_define_inl_math_parameters(size, math_parameter_radical_vgap, tex_aux_get_font_math_parameter(scale, f, RadicalVerticalGap), level);
5741 tex_aux_define_dis_math_parameters(size, math_parameter_radical_vgap, tex_aux_get_font_math_parameter(scale, f, RadicalDisplayStyleVerticalGap), level);
5742 tex_aux_define_inl_math_parameters(size, math_parameter_stack_num_up, tex_aux_get_font_math_parameter(scale, f, StackTopShiftUp), level);
5743 tex_aux_define_dis_math_parameters(size, math_parameter_stack_num_up, tex_aux_get_font_math_parameter(scale, f, StackTopDisplayStyleShiftUp), level);
5744 tex_aux_define_inl_math_parameters(size, math_parameter_stack_denom_down, tex_aux_get_font_math_parameter(scale, f, StackBottomShiftDown), level);
5745 tex_aux_define_dis_math_parameters(size, math_parameter_stack_denom_down, tex_aux_get_font_math_parameter(scale, f, StackBottomDisplayStyleShiftDown), level);
5746 tex_aux_define_inl_math_parameters(size, math_parameter_stack_vgap, tex_aux_get_font_math_parameter(scale, f, StackGapMin), level);
5747 tex_aux_define_dis_math_parameters(size, math_parameter_stack_vgap, tex_aux_get_font_math_parameter(scale, f, StackDisplayStyleGapMin), level);
5748 tex_aux_define_inl_math_parameters(size, math_parameter_fraction_num_vgap, tex_aux_get_font_math_parameter(scale, f, FractionNumeratorGapMin), level);
5749 tex_aux_define_dis_math_parameters(size, math_parameter_fraction_num_vgap, tex_aux_get_font_math_parameter(scale, f, FractionNumeratorDisplayStyleGapMin), level);
5750 tex_aux_define_inl_math_parameters(size, math_parameter_fraction_num_up, tex_aux_get_font_math_parameter(scale, f, FractionNumeratorShiftUp), level);
5751 tex_aux_define_dis_math_parameters(size, math_parameter_fraction_num_up, tex_aux_get_font_math_parameter(scale, f, FractionNumeratorDisplayStyleShiftUp), level);
5752 tex_aux_define_inl_math_parameters(size, math_parameter_fraction_denom_vgap, tex_aux_get_font_math_parameter(scale, f, FractionDenominatorGapMin), level);
5753 tex_aux_define_dis_math_parameters(size, math_parameter_fraction_denom_vgap, tex_aux_get_font_math_parameter(scale, f, FractionDenominatorDisplayStyleGapMin), level);
5754 tex_aux_define_inl_math_parameters(size, math_parameter_fraction_denom_down, tex_aux_get_font_math_parameter(scale, f, FractionDenominatorShiftDown), level);
5755 tex_aux_define_dis_math_parameters(size, math_parameter_fraction_denom_down, tex_aux_get_font_math_parameter(scale, f, FractionDenominatorDisplayStyleShiftDown), level);
5756 tex_aux_define_inl_math_parameters(size, math_parameter_fraction_del_size, tex_aux_get_font_math_parameter(scale, f, FractionDelimiterSize), level);
5757 tex_aux_define_dis_math_parameters(size, math_parameter_fraction_del_size, tex_aux_get_font_math_parameter(scale, f, FractionDelimiterDisplayStyleSize), level);
5758
5759 tex_aux_define_dis_math_parameters(size, math_parameter_delimiter_shortfall, tex_aux_get_font_math_parameter(scale, f, DelimiterDisplayShortfall), level);
5760 tex_aux_define_inl_math_parameters(size, math_parameter_delimiter_shortfall, tex_aux_get_font_math_parameter(scale, f, DelimiterShortfall), level);
5761
5762
5763
5764 switch (size) {
5765 case script_size:
5766 tex_def_math_parameter(script_style, math_parameter_superscript_shift_up, tex_aux_get_font_math_parameter(scale, f, SuperscriptShiftUp), level, indirect_math_regular, 1);
5767 tex_def_math_parameter(cramped_script_style, math_parameter_superscript_shift_up, tex_aux_get_font_math_parameter(scale, f, SuperscriptShiftUpCramped), level, indirect_math_regular, 1);
5768 tex_def_math_parameter(script_style, math_parameter_prime_shift_up, tex_aux_get_font_math_parameter(scale, f, PrimeShiftUp), level, indirect_math_regular, 1);
5769 tex_def_math_parameter(cramped_script_style, math_parameter_prime_shift_up, tex_aux_get_font_math_parameter(scale, f, PrimeShiftUpCramped), level, indirect_math_regular, 1);
5770 break;
5771 case script_script_size:
5772 tex_def_math_parameter(script_script_style, math_parameter_superscript_shift_up, tex_aux_get_font_math_parameter(scale, f, SuperscriptShiftUp), level, indirect_math_regular, 1);
5773 tex_def_math_parameter(cramped_script_script_style, math_parameter_superscript_shift_up, tex_aux_get_font_math_parameter(scale, f, SuperscriptShiftUpCramped), level, indirect_math_regular, 1);
5774 tex_def_math_parameter(script_script_style, math_parameter_prime_shift_up, tex_aux_get_font_math_parameter(scale, f, PrimeShiftUp), level, indirect_math_regular, 1);
5775 tex_def_math_parameter(cramped_script_script_style, math_parameter_prime_shift_up, tex_aux_get_font_math_parameter(scale, f, PrimeShiftUpCramped), level, indirect_math_regular, 1);
5776 break;
5777 default:
5778 tex_def_math_parameter(display_style, math_parameter_superscript_shift_up, tex_aux_get_font_math_parameter(scale, f, SuperscriptShiftUp), level, indirect_math_regular, 1);
5779 tex_def_math_parameter(cramped_display_style, math_parameter_superscript_shift_up, tex_aux_get_font_math_parameter(scale, f, SuperscriptShiftUpCramped), level, indirect_math_regular, 1);
5780 tex_def_math_parameter(text_style, math_parameter_superscript_shift_up, tex_aux_get_font_math_parameter(scale, f, SuperscriptShiftUp), level, indirect_math_regular, 1);
5781 tex_def_math_parameter(cramped_text_style, math_parameter_superscript_shift_up, tex_aux_get_font_math_parameter(scale, f, SuperscriptShiftUpCramped), level, indirect_math_regular, 1);
5782 tex_def_math_parameter(display_style, math_parameter_prime_shift_up, tex_aux_get_font_math_parameter(scale, f, PrimeShiftUp), level, indirect_math_regular, 1);
5783 tex_def_math_parameter(cramped_display_style, math_parameter_prime_shift_up, tex_aux_get_font_math_parameter(scale, f, PrimeShiftUpCramped), level, indirect_math_regular, 1);
5784 tex_def_math_parameter(text_style, math_parameter_prime_shift_up, tex_aux_get_font_math_parameter(scale, f, PrimeShiftUp), level, indirect_math_regular, 1);
5785 tex_def_math_parameter(cramped_text_style, math_parameter_prime_shift_up, tex_aux_get_font_math_parameter(scale, f, PrimeShiftUpCramped), level, indirect_math_regular, 1);
5786 break;
5787 }
5788
5789}
5790
5791
5799
5800void tex_set_display_styles(halfword code, halfword value, halfword level, halfword indirect)
5801{
5802 tex_def_math_parameter(display_style, code, value, level, indirect, 0);
5803 tex_def_math_parameter(cramped_display_style, code, value, level, indirect, 0);
5804}
5805
5806void tex_set_text_styles(halfword code, halfword value, halfword level, halfword indirect)
5807{
5808 tex_def_math_parameter(text_style, code, value, level, indirect, 0);
5809 tex_def_math_parameter(cramped_text_style, code, value, level, indirect, 0);
5810}
5811
5812void tex_set_main_styles(halfword code, halfword value, halfword level, halfword indirect)
5813{
5814 for (int style = display_style; style <= cramped_text_style; style++) {
5815 tex_def_math_parameter(style, code, value, level, indirect, 0);
5816 }
5817}
5818
5819void tex_set_script_styles(halfword code, halfword value, halfword level, halfword indirect)
5820{
5821 tex_def_math_parameter(script_style, code, value, level, indirect, 0);
5822 tex_def_math_parameter(cramped_script_style, code, value, level, indirect, 0);
5823}
5824
5825void tex_set_script_script_styles(halfword code, halfword value, halfword level, halfword indirect)
5826{
5827 tex_def_math_parameter(script_script_style, code, value, level, indirect, 0);
5828 tex_def_math_parameter(cramped_script_script_style, code, value, level, indirect, 0);
5829}
5830
5831void tex_set_all_styles(halfword code, halfword value, halfword level, halfword indirect)
5832{
5833 for (int style = display_style; style <= cramped_script_script_style; style++) {
5834 tex_def_math_parameter(style, code, value, level, indirect, 0);
5835 }
5836}
5837
5838void tex_set_uncramped_styles(halfword code, halfword value, halfword level, halfword indirect)
5839{
5840 for (int style = display_style; style <= script_script_style; style += 2) {
5841 tex_def_math_parameter(style, code, value, level, indirect, 0);
5842 }
5843}
5844
5845void tex_set_cramped_styles(halfword code, halfword value, halfword level, halfword indirect)
5846{
5847 for (int style = cramped_display_style; style <= cramped_script_script_style; style += 2) {
5848 tex_def_math_parameter(style, code, value, level, indirect, 0);
5849 }
5850}
5851
5852void tex_set_split_styles(halfword code, halfword value, halfword level, halfword indirect)
5853{
5854 tex_set_display_styles (code, value, level, indirect);
5855 tex_set_text_styles (code, value, level, indirect);
5856 tex_set_script_styles (code, 0, level, indirect);
5857 tex_set_script_script_styles(code, 0, level, indirect);
5858}
5859
5860void tex_set_unsplit_styles(halfword code, halfword value, halfword level, halfword indirect)
5861{
5862 tex_set_script_styles (code, value, level, indirect);
5863 tex_set_script_script_styles(code, value, level, indirect);
5864}
5865
5866void tex_reset_all_styles(halfword level)
5867{
5868 for (int code = math_parameter_atom_pairs_first; code <= math_parameter_atom_pairs_last; code++) {
5869 tex_set_all_styles(code, zero_muskip_code, level, indirect_math_unset);
5870 }
5871}
5872
5873inline static halfword tex_aux_math_class_default(halfword mathclass) {
5874 return (mathclass << 24) + (mathclass << 16) + (mathclass << 8) + mathclass;
5875}
5876
5877inline static void tex_set_math_class_default(halfword mathclass, halfword parent, halfword options)
5878{
5879 tex_word_define(0, internal_integer_location(first_math_class_code + mathclass), tex_aux_math_class_default(parent));
5880 tex_word_define(0, internal_integer_location(first_math_atom_code + mathclass), tex_aux_math_class_default(mathclass));
5881 tex_word_define(0, internal_integer_location(first_math_options_code + mathclass), options);
5882 tex_word_define(0, internal_integer_location(first_math_parent_code + mathclass), tex_aux_math_class_default(mathclass));
5883}
5884
5885static void tex_aux_set_math_atom_rule(halfword left, halfword right, halfword newleft, halfword newright)
5886{
5887 tex_set_all_styles(math_parameter_rules_pair(left, right), (newleft << 16) + newright, level_one, indirect_math_regular);
5888}
5889
5890
5899
5900void tex_initialize_math_spacing(void)
5901{
5902
5903 for (int mathclass = 0; mathclass <= max_math_class_code; mathclass++) {
5904 tex_set_math_class_default(mathclass, mathclass, no_class_options);
5905
5906 tex_word_define(0, internal_integer_location(first_math_pre_penalty_code + mathclass), math_default_penalty);
5907 tex_word_define(0, internal_integer_location(first_math_post_penalty_code + mathclass), math_default_penalty);
5908 tex_word_define(0, internal_integer_location(first_math_display_pre_penalty_code + mathclass), math_default_penalty);
5909 tex_word_define(0, internal_integer_location(first_math_display_post_penalty_code + mathclass), math_default_penalty);
5910 }
5911
5912 tex_reset_all_styles(level_one);
5913
5914 tex_set_math_class_default(ordinary_noad_subtype, ordinary_noad_subtype, no_italic_correction_class_option |
5915 check_ligature_class_option |
5916 check_kern_pair_class_option |
5917 flatten_class_option);
5918 tex_set_math_class_default(operator_noad_subtype, operator_noad_subtype, check_ligature_class_option |
5919 check_kern_pair_class_option);
5920 tex_set_math_class_default(binary_noad_subtype, binary_noad_subtype, no_italic_correction_class_option |
5921 check_ligature_class_option |
5922 check_kern_pair_class_option |
5923 flatten_class_option);
5924 tex_set_math_class_default(relation_noad_subtype, relation_noad_subtype, no_italic_correction_class_option |
5925 check_ligature_class_option |
5926 check_kern_pair_class_option |
5927 flatten_class_option |
5928 omit_penalty_class_option);
5929 tex_set_math_class_default(open_noad_subtype, open_noad_subtype, no_italic_correction_class_option |
5930
5931 check_ligature_class_option |
5932 check_kern_pair_class_option);
5933 tex_set_math_class_default(close_noad_subtype, close_noad_subtype, no_italic_correction_class_option |
5934
5935 check_ligature_class_option |
5936 check_kern_pair_class_option);
5937 tex_set_math_class_default(punctuation_noad_subtype, punctuation_noad_subtype, no_italic_correction_class_option |
5938 check_ligature_class_option |
5939 check_kern_pair_class_option |
5940 flatten_class_option);
5941 tex_set_math_class_default(variable_noad_subtype, ordinary_noad_subtype, no_italic_correction_class_option);
5942 tex_set_math_class_default(active_noad_subtype, ordinary_noad_subtype, no_italic_correction_class_option);
5943 tex_set_math_class_default(inner_noad_subtype, inner_noad_subtype, flatten_class_option);
5944 tex_set_math_class_default(under_noad_subtype, ordinary_noad_subtype, no_class_options);
5945 tex_set_math_class_default(over_noad_subtype, ordinary_noad_subtype, no_class_options);
5946 tex_set_math_class_default(fraction_noad_subtype, ordinary_noad_subtype, no_class_options);
5947 tex_set_math_class_default(radical_noad_subtype, ordinary_noad_subtype, no_class_options);
5948 tex_set_math_class_default(middle_noad_subtype, open_noad_subtype, no_italic_correction_class_option);
5949 tex_set_math_class_default(accent_noad_subtype, ordinary_noad_subtype, no_class_options);
5950 tex_set_math_class_default(fenced_noad_subtype, inner_noad_subtype , no_class_options);
5951 tex_set_math_class_default(ghost_noad_subtype, ordinary_noad_subtype, no_class_options);
5952 tex_set_math_class_default(vcenter_noad_subtype, ordinary_noad_subtype, no_class_options);
5953
5954 tex_aux_set_math_atom_rule(math_begin_class, binary_noad_subtype, ordinary_noad_subtype, ordinary_noad_subtype);
5955 tex_aux_set_math_atom_rule(binary_noad_subtype, math_end_class, ordinary_noad_subtype, ordinary_noad_subtype);
5956
5957 tex_aux_set_math_atom_rule(binary_noad_subtype, binary_noad_subtype, binary_noad_subtype, ordinary_noad_subtype);
5958 tex_aux_set_math_atom_rule(operator_noad_subtype, binary_noad_subtype, operator_noad_subtype, ordinary_noad_subtype);
5959 tex_aux_set_math_atom_rule(open_noad_subtype, binary_noad_subtype, open_noad_subtype, ordinary_noad_subtype);
5960 tex_aux_set_math_atom_rule(punctuation_noad_subtype, binary_noad_subtype, punctuation_noad_subtype, ordinary_noad_subtype);
5961 tex_aux_set_math_atom_rule(relation_noad_subtype, binary_noad_subtype, relation_noad_subtype, ordinary_noad_subtype);
5962
5963 tex_aux_set_math_atom_rule(binary_noad_subtype, close_noad_subtype, ordinary_noad_subtype, close_noad_subtype);
5964 tex_aux_set_math_atom_rule(binary_noad_subtype, punctuation_noad_subtype, ordinary_noad_subtype, punctuation_noad_subtype);
5965 tex_aux_set_math_atom_rule(binary_noad_subtype, relation_noad_subtype, ordinary_noad_subtype, relation_noad_subtype);
5966
5967 tex_aux_set_math_atom_rule(relation_noad_subtype, close_noad_subtype, ordinary_noad_subtype, close_noad_subtype);
5968 tex_aux_set_math_atom_rule(relation_noad_subtype, punctuation_noad_subtype, ordinary_noad_subtype, punctuation_noad_subtype);
5969
5970
5971
5972
5973
5974 tex_set_all_styles (math_parameter_spacing_pair(ordinary_noad_subtype, operator_noad_subtype), thin_muskip_code, level_one, indirect_math_regular);
5975 tex_set_split_styles (math_parameter_spacing_pair(ordinary_noad_subtype, binary_noad_subtype), med_muskip_code, level_one, indirect_math_regular);
5976 tex_set_split_styles (math_parameter_spacing_pair(ordinary_noad_subtype, relation_noad_subtype), thick_muskip_code, level_one, indirect_math_regular);
5977 tex_set_split_styles (math_parameter_spacing_pair(ordinary_noad_subtype, inner_noad_subtype), thin_muskip_code, level_one, indirect_math_regular);
5978
5979 tex_set_all_styles (math_parameter_spacing_pair(operator_noad_subtype, ordinary_noad_subtype), thin_muskip_code, level_one, indirect_math_regular);
5980 tex_set_all_styles (math_parameter_spacing_pair(operator_noad_subtype, operator_noad_subtype), thin_muskip_code, level_one, indirect_math_regular);
5981 tex_set_split_styles (math_parameter_spacing_pair(operator_noad_subtype, relation_noad_subtype), thick_muskip_code, level_one, indirect_math_regular);
5982 tex_set_split_styles (math_parameter_spacing_pair(operator_noad_subtype, inner_noad_subtype), thin_muskip_code, level_one, indirect_math_regular);
5983
5984 tex_set_all_styles (math_parameter_spacing_pair(operator_noad_subtype, fraction_noad_subtype), thin_muskip_code, level_one, indirect_math_regular);
5985 tex_set_all_styles (math_parameter_spacing_pair(operator_noad_subtype, radical_noad_subtype), thin_muskip_code, level_one, indirect_math_regular);
5986 tex_set_all_styles (math_parameter_spacing_pair(fraction_noad_subtype, operator_noad_subtype), thin_muskip_code, level_one, indirect_math_regular);
5987 tex_set_all_styles (math_parameter_spacing_pair(radical_noad_subtype, operator_noad_subtype), thin_muskip_code, level_one, indirect_math_regular);
5988
5989 tex_set_split_styles (math_parameter_spacing_pair(binary_noad_subtype, ordinary_noad_subtype), med_muskip_code, level_one, indirect_math_regular);
5990 tex_set_split_styles (math_parameter_spacing_pair(binary_noad_subtype, operator_noad_subtype), med_muskip_code, level_one, indirect_math_regular);
5991 tex_set_split_styles (math_parameter_spacing_pair(binary_noad_subtype, open_noad_subtype), med_muskip_code, level_one, indirect_math_regular);
5992 tex_set_split_styles (math_parameter_spacing_pair(binary_noad_subtype, inner_noad_subtype), med_muskip_code, level_one, indirect_math_regular);
5993
5994 tex_set_split_styles (math_parameter_spacing_pair(binary_noad_subtype, middle_noad_subtype), med_muskip_code, level_one, indirect_math_regular);
5995 tex_set_split_styles (math_parameter_spacing_pair(binary_noad_subtype, fraction_noad_subtype), med_muskip_code, level_one, indirect_math_regular);
5996 tex_set_split_styles (math_parameter_spacing_pair(binary_noad_subtype, radical_noad_subtype), med_muskip_code, level_one, indirect_math_regular);
5997 tex_set_split_styles (math_parameter_spacing_pair(middle_noad_subtype, binary_noad_subtype), med_muskip_code, level_one, indirect_math_regular);
5998 tex_set_split_styles (math_parameter_spacing_pair(fraction_noad_subtype, binary_noad_subtype), med_muskip_code, level_one, indirect_math_regular);
5999 tex_set_split_styles (math_parameter_spacing_pair(radical_noad_subtype, binary_noad_subtype), med_muskip_code, level_one, indirect_math_regular);
6000
6001 tex_set_split_styles (math_parameter_spacing_pair(relation_noad_subtype, ordinary_noad_subtype), thick_muskip_code, level_one, indirect_math_regular);
6002 tex_set_split_styles (math_parameter_spacing_pair(relation_noad_subtype, operator_noad_subtype), thick_muskip_code, level_one, indirect_math_regular);
6003 tex_set_split_styles (math_parameter_spacing_pair(relation_noad_subtype, open_noad_subtype), thick_muskip_code, level_one, indirect_math_regular);
6004 tex_set_split_styles (math_parameter_spacing_pair(relation_noad_subtype, inner_noad_subtype), thick_muskip_code, level_one, indirect_math_regular);
6005
6006 tex_set_split_styles (math_parameter_spacing_pair(relation_noad_subtype, middle_noad_subtype), thick_muskip_code, level_one, indirect_math_regular);
6007 tex_set_split_styles (math_parameter_spacing_pair(relation_noad_subtype, fraction_noad_subtype), thick_muskip_code, level_one, indirect_math_regular);
6008 tex_set_split_styles (math_parameter_spacing_pair(relation_noad_subtype, radical_noad_subtype), thick_muskip_code, level_one, indirect_math_regular);
6009 tex_set_split_styles (math_parameter_spacing_pair(middle_noad_subtype, relation_noad_subtype), thick_muskip_code, level_one, indirect_math_regular);
6010 tex_set_split_styles (math_parameter_spacing_pair(fraction_noad_subtype, relation_noad_subtype), thick_muskip_code, level_one, indirect_math_regular);
6011 tex_set_split_styles (math_parameter_spacing_pair(radical_noad_subtype, relation_noad_subtype), thick_muskip_code, level_one, indirect_math_regular);
6012
6013 tex_set_all_styles (math_parameter_spacing_pair(close_noad_subtype, operator_noad_subtype), thin_muskip_code, level_one, indirect_math_regular);
6014 tex_set_split_styles (math_parameter_spacing_pair(close_noad_subtype, binary_noad_subtype), med_muskip_code, level_one, indirect_math_regular);
6015 tex_set_split_styles (math_parameter_spacing_pair(close_noad_subtype, relation_noad_subtype), thick_muskip_code, level_one, indirect_math_regular);
6016 tex_set_split_styles (math_parameter_spacing_pair(close_noad_subtype, inner_noad_subtype), thin_muskip_code, level_one, indirect_math_regular);
6017
6018 tex_set_split_styles (math_parameter_spacing_pair(punctuation_noad_subtype, ordinary_noad_subtype), thin_muskip_code, level_one, indirect_math_regular);
6019 tex_set_split_styles (math_parameter_spacing_pair(punctuation_noad_subtype, operator_noad_subtype), thin_muskip_code, level_one, indirect_math_regular);
6020 tex_set_split_styles (math_parameter_spacing_pair(punctuation_noad_subtype, relation_noad_subtype), thin_muskip_code, level_one, indirect_math_regular);
6021 tex_set_split_styles (math_parameter_spacing_pair(punctuation_noad_subtype, open_noad_subtype), thin_muskip_code, level_one, indirect_math_regular);
6022 tex_set_split_styles (math_parameter_spacing_pair(punctuation_noad_subtype, close_noad_subtype), thin_muskip_code, level_one, indirect_math_regular);
6023 tex_set_split_styles (math_parameter_spacing_pair(punctuation_noad_subtype, punctuation_noad_subtype), thin_muskip_code, level_one, indirect_math_regular);
6024 tex_set_split_styles (math_parameter_spacing_pair(punctuation_noad_subtype, inner_noad_subtype), thin_muskip_code, level_one, indirect_math_regular);
6025
6026 tex_set_split_styles (math_parameter_spacing_pair(punctuation_noad_subtype, fraction_noad_subtype), thin_muskip_code, level_one, indirect_math_regular);
6027 tex_set_split_styles (math_parameter_spacing_pair(punctuation_noad_subtype, middle_noad_subtype), thin_muskip_code, level_one, indirect_math_regular);
6028 tex_set_split_styles (math_parameter_spacing_pair(punctuation_noad_subtype, radical_noad_subtype), thin_muskip_code, level_one, indirect_math_regular);
6029 tex_set_split_styles (math_parameter_spacing_pair(fraction_noad_subtype, punctuation_noad_subtype), thin_muskip_code, level_one, indirect_math_regular);
6030 tex_set_split_styles (math_parameter_spacing_pair(middle_noad_subtype, punctuation_noad_subtype), thin_muskip_code, level_one, indirect_math_regular);
6031 tex_set_split_styles (math_parameter_spacing_pair(radical_noad_subtype, punctuation_noad_subtype), thin_muskip_code, level_one, indirect_math_regular);
6032
6033 tex_set_split_styles (math_parameter_spacing_pair(inner_noad_subtype, ordinary_noad_subtype), thin_muskip_code, level_one, indirect_math_regular);
6034 tex_set_all_styles (math_parameter_spacing_pair(inner_noad_subtype, operator_noad_subtype), thin_muskip_code, level_one, indirect_math_regular);
6035 tex_set_split_styles (math_parameter_spacing_pair(inner_noad_subtype, binary_noad_subtype), med_muskip_code, level_one, indirect_math_regular);
6036 tex_set_split_styles (math_parameter_spacing_pair(inner_noad_subtype, relation_noad_subtype), thick_muskip_code, level_one, indirect_math_regular);
6037 tex_set_split_styles (math_parameter_spacing_pair(inner_noad_subtype, open_noad_subtype), thin_muskip_code, level_one, indirect_math_regular);
6038 tex_set_split_styles (math_parameter_spacing_pair(inner_noad_subtype, punctuation_noad_subtype), thin_muskip_code, level_one, indirect_math_regular);
6039 tex_set_split_styles (math_parameter_spacing_pair(inner_noad_subtype, inner_noad_subtype), thin_muskip_code, level_one, indirect_math_regular);
6040
6041 tex_set_split_styles (math_parameter_spacing_pair(inner_noad_subtype, middle_noad_subtype), thin_muskip_code, level_one, indirect_math_regular);
6042 tex_set_split_styles (math_parameter_spacing_pair(fraction_noad_subtype, inner_noad_subtype), thin_muskip_code, level_one, indirect_math_regular);
6043 tex_set_split_styles (math_parameter_spacing_pair(radical_noad_subtype, inner_noad_subtype), thin_muskip_code, level_one, indirect_math_regular);
6044 tex_set_split_styles (math_parameter_spacing_pair(middle_noad_subtype, inner_noad_subtype), thin_muskip_code, level_one, indirect_math_regular);
6045 tex_set_split_styles (math_parameter_spacing_pair(fraction_noad_subtype, inner_noad_subtype), thin_muskip_code, level_one, indirect_math_regular);
6046 tex_set_split_styles (math_parameter_spacing_pair(radical_noad_subtype, inner_noad_subtype), thin_muskip_code, level_one, indirect_math_regular);
6047
6048
6049
6050 tex_set_all_styles (math_parameter_x_scale, scaling_factor, level_one, indirect_math_regular);
6051 tex_set_all_styles (math_parameter_y_scale, scaling_factor, level_one, indirect_math_regular);
6052
6053
6054
6055 tex_set_all_styles (math_parameter_over_line_variant, math_cramped_style_variant, level_one, indirect_math_regular);
6056 tex_set_all_styles (math_parameter_under_line_variant, math_normal_style_variant, level_one, indirect_math_regular);
6057 tex_set_all_styles (math_parameter_over_delimiter_variant, math_small_style_variant, level_one, indirect_math_regular);
6058 tex_set_all_styles (math_parameter_under_delimiter_variant, math_small_style_variant, level_one, indirect_math_regular);
6059 tex_set_all_styles (math_parameter_delimiter_over_variant, math_normal_style_variant, level_one, indirect_math_regular);
6060 tex_set_all_styles (math_parameter_delimiter_under_variant, math_normal_style_variant, level_one, indirect_math_regular);
6061 tex_set_all_styles (math_parameter_h_extensible_variant, math_normal_style_variant, level_one, indirect_math_regular);
6062 tex_set_all_styles (math_parameter_v_extensible_variant, math_normal_style_variant, level_one, indirect_math_regular);
6063 tex_set_all_styles (math_parameter_fraction_variant, math_cramped_style_variant, level_one, indirect_math_regular);
6064 tex_set_all_styles (math_parameter_radical_variant, math_cramped_style_variant, level_one, indirect_math_regular);
6065 tex_set_all_styles (math_parameter_degree_variant, math_double_superscript_variant, level_one, indirect_math_regular);
6066 tex_set_all_styles (math_parameter_accent_variant, math_cramped_style_variant, level_one, indirect_math_regular);
6067 tex_set_all_styles (math_parameter_top_accent_variant, math_cramped_style_variant, level_one, indirect_math_regular);
6068 tex_set_all_styles (math_parameter_bottom_accent_variant, math_cramped_style_variant, level_one, indirect_math_regular);
6069 tex_set_all_styles (math_parameter_overlay_accent_variant, math_cramped_style_variant, level_one, indirect_math_regular);
6070 tex_set_all_styles (math_parameter_numerator_variant, math_numerator_style_variant, level_one, indirect_math_regular);
6071 tex_set_all_styles (math_parameter_denominator_variant, math_denominator_style_variant, level_one, indirect_math_regular);
6072 tex_set_all_styles (math_parameter_superscript_variant, math_superscript_style_variant, level_one, indirect_math_regular);
6073 tex_set_all_styles (math_parameter_subscript_variant, math_subscript_style_variant, level_one, indirect_math_regular);
6074 tex_set_all_styles (math_parameter_prime_variant, math_superscript_style_variant, level_one, indirect_math_regular);
6075 tex_set_all_styles (math_parameter_stack_variant, math_numerator_style_variant, level_one, indirect_math_regular);
6076}
6077
6078
6084
6085void tex_finalize_math_parameters(void)
6086{
6087 int saved_trace = tracing_assigns_par;
6088 tracing_assigns_par = 0;
6089 if (tex_get_math_parameter(display_style, math_parameter_space_after_script, NULL) == undefined_math_parameter) {
6090 tex_def_math_parameter(display_style, math_parameter_space_after_script, script_space_par, level_one, indirect_math_regular, 1);
6091 tex_def_math_parameter(text_style, math_parameter_space_after_script, script_space_par, level_one, indirect_math_regular, 1);
6092 tex_def_math_parameter(script_style, math_parameter_space_after_script, script_space_par, level_one, indirect_math_regular, 1);
6093 tex_def_math_parameter(script_script_style, math_parameter_space_after_script, script_space_par, level_one, indirect_math_regular, 1);
6094 tex_def_math_parameter(cramped_display_style, math_parameter_space_after_script, script_space_par, level_one, indirect_math_regular, 1);
6095 tex_def_math_parameter(cramped_text_style, math_parameter_space_after_script, script_space_par, level_one, indirect_math_regular, 1);
6096 tex_def_math_parameter(cramped_script_style, math_parameter_space_after_script, script_space_par, level_one, indirect_math_regular, 1);
6097 tex_def_math_parameter(cramped_script_script_style, math_parameter_space_after_script, script_space_par, level_one, indirect_math_regular, 1);
6098 }
6099 tracing_assigns_par = saved_trace;
6100}
6101
6102static void tex_aux_math_parameter_error(int style, int param, const char *name)
6103{
6104 if (param >= 0) {
6105 tex_handle_error(
6106 normal_error_type,
6107 "Math error: parameter '%s' with id %i in style %i is not set",
6108 name, param, style,
6109 "Sorry, but I can't typeset math unless various parameters have been set. This is\n"
6110 "normally done by loading special math fonts into the math family slots. Your font\n"
6111 "set is lacking at least the parameter mentioned earlier."
6112 );
6113 } else {
6114 tex_formatted_error("math", "invalid parameter '%s' in style %i", name, style);
6115 }
6116 return;
6117}
6118
6119
6122
6123inline static scaled tex_aux_max_scale(int style, int param)
6124{
6125 scaled scale = tex_get_math_parameter(style, param, NULL);
6126 if (scale > max_math_scaling_factor) {
6127 return max_math_scaling_factor;
6128 } else if (scale < 0) {
6129 return 0;
6130 } else {
6131 return scale;
6132 }
6133}
6134
6135
6141
6142scaled tex_get_math_quad_style(int style)
6143{
6144 scaled scale = tex_aux_max_scale(style, math_parameter_x_scale);
6145 scaled value = tex_get_math_parameter(style, math_parameter_quad, NULL);
6146 if (value == undefined_math_parameter) {
6147 tex_aux_math_parameter_error(style, -1, "quad");
6148 return 0;
6149 } else {
6150 return scaledround(0.001 * value * scale);
6151 }
6152}
6153
6154
6160
6161scaled tex_math_axis_size(int size)
6162{
6163 scaled value;
6164 switch (size) {
6165 case script_size : size = script_style; break;
6166 case script_script_size: size = script_script_style; break;
6167 default : size = text_style; break;
6168 }
6169 value = tex_get_math_parameter(size, math_parameter_axis, NULL);
6170 if (value == undefined_math_parameter) {
6171 tex_aux_math_parameter_error(size, -1, "axis");
6172 return 0;
6173 } else {
6174 return value;
6175 }
6176}
6177
6178scaled tex_get_math_quad_size(int size)
6179{
6180 switch (size) {
6181 case script_size : size = script_style; break;
6182 case script_script_size: size = script_script_style; break;
6183 default : size = text_style; break;
6184 }
6185 return tex_get_math_parameter(size, math_parameter_quad, NULL);
6186}
6187
6188scaled tex_get_math_quad_size_scaled(int size)
6189{
6190 scaled value, scale;
6191 switch (size) {
6192 case script_size : size = script_style; break;
6193 case script_script_size: size = script_script_style; break;
6194 default : size = text_style; break;
6195 }
6196 value = tex_get_math_parameter(size, math_parameter_quad, NULL);
6197 scale = tex_aux_max_scale(size, math_parameter_x_scale);
6198
6199 return scaledround(0.001 * value * scale / 18.0);
6200}
6201
6202scaled tex_get_math_quad_size_unscaled(int size)
6203{
6204 switch (size) {
6205 case script_size : size = script_style; break;
6206 case script_script_size: size = script_script_style; break;
6207 default : size = text_style; break;
6208 }
6209 return scaledround(tex_get_math_parameter(size, math_parameter_quad, NULL) / 18.0);
6210}
6211
6212static int tex_aux_math_parameter_okay(int param)
6213{
6214 if (ignore_math_parameter(param) == 1) {
6215 if (tracing_math_par > 1) {
6216 tex_begin_diagnostic();
6217 tex_print_format("[math: parameter, name %s, ignored]", lmt_name_of_math_parameter(param));
6218 tex_end_diagnostic();
6219 }
6220 return 0;
6221 } else {
6222 return 1;
6223 }
6224}
6225
6226scaled tex_get_math_parameter_checked(int style, int param)
6227{
6228 if (tex_aux_math_parameter_okay(param)) {
6229 scaled value = tex_get_math_parameter(style, param, NULL);
6230 if (value == undefined_math_parameter) {
6231 tex_aux_math_parameter_error(style, param, lmt_name_of_math_parameter(param));
6232 return 0;
6233 } else {
6234 return value;
6235 }
6236 } else {
6237 return 0;
6238 }
6239}
6240
6241scaled tex_get_math_parameter_default(int style, int param, scaled dflt)
6242{
6243 if (tex_aux_math_parameter_okay(param)) {
6244 scaled value = tex_get_math_parameter(style, param, NULL);
6245 if (value == undefined_math_parameter) {
6246 return dflt;
6247 } else {
6248 return value;
6249 }
6250 } else {
6251 return dflt;
6252 }
6253}
6254
6255void tex_run_math_italic_correction(void) {
6256 if (cur_chr == italic_correction_code) {
6257 tex_tail_append(tex_new_kern_node(0, explicit_kern_subtype));
6258 }
6259}
6260
6261
6262
6263scaled tex_get_math_x_parameter(int style, int param)
6264{
6265 if (tex_aux_math_parameter_okay(param)) {
6266 scaled scale = tex_aux_max_scale(style, math_parameter_x_scale);
6267 scaled value = tex_get_math_parameter(style, param, NULL);
6268 if (value == undefined_math_parameter) {
6269 return value;
6270 } else {
6271 return value ? scaledround(0.000000001 * glyph_scale_par * glyph_x_scale_par * value * scale) : 0;
6272 }
6273 } else {
6274 return 0;
6275 }
6276}
6277
6278scaled tex_get_math_x_parameter_checked(int style, int param)
6279{
6280 if (tex_aux_math_parameter_okay(param)) {
6281 scaled scale = tex_aux_max_scale(style, math_parameter_x_scale);
6282 scaled value = tex_get_math_parameter(style, param, NULL);
6283 if (value == undefined_math_parameter) {
6284 tex_aux_math_parameter_error(style, param, lmt_name_of_math_parameter(param));
6285 return 0;
6286 } else {
6287 return value ? scaledround(0.000000001 * glyph_scale_par * glyph_x_scale_par * value * scale) : 0;
6288 }
6289 } else {
6290 return 0;
6291 }
6292}
6293
6294scaled tex_get_math_x_parameter_default(int style, int param, scaled dflt)
6295{
6296 if (tex_aux_math_parameter_okay(param)) {
6297 scaled scale = tex_aux_max_scale(style, math_parameter_x_scale);
6298 scaled value = tex_get_math_parameter(style, param, NULL);
6299 if (value == undefined_math_parameter) {
6300 return dflt;
6301 } else{
6302 return value ? scaledround(0.000000001 * glyph_scale_par * glyph_x_scale_par * value * scale) : 0;
6303 }
6304 } else {
6305 return dflt;
6306 }
6307}
6308
6309scaled tex_get_math_y_parameter(int style, int param)
6310{
6311 if (tex_aux_math_parameter_okay(param)) {
6312 scaled scale = tex_aux_max_scale(style, math_parameter_y_scale);
6313 scaled value = tex_get_math_parameter(style, param, NULL);
6314 if (value == undefined_math_parameter) {
6315 return value;
6316 } else{
6317 return value ? scaledround(0.000000001 * glyph_scale_par * glyph_y_scale_par * value * scale) : 0;
6318 }
6319 } else {
6320 return 0;
6321 }
6322}
6323
6324scaled tex_get_math_y_parameter_checked(int style, int param)
6325{
6326 if (tex_aux_math_parameter_okay(param)) {
6327 scaled scale = tex_aux_max_scale(style, math_parameter_y_scale);
6328 scaled value = tex_get_math_parameter(style, param, NULL);
6329 if (value == undefined_math_parameter) {
6330 tex_aux_math_parameter_error(style, param, lmt_name_of_math_parameter(param));
6331 return 0;
6332 } else {
6333 return value ? scaledround(0.000000001 * glyph_scale_par * glyph_y_scale_par * value * scale) : 0;
6334 }
6335 } else {
6336 return 0;
6337 }
6338}
6339
6340scaled tex_get_math_y_parameter_default(int style, int param, scaled dflt)
6341{
6342 if (tex_aux_math_parameter_okay(param)) {
6343 scaled scale = tex_aux_max_scale(style, math_parameter_y_scale);
6344 scaled value = tex_get_math_parameter(style, param, NULL);
6345 if (value == undefined_math_parameter) {
6346 return dflt;
6347 } else {
6348 return value ? scaledround(0.000000001 * glyph_scale_par * glyph_y_scale_par * value * scale) : 0;
6349 }
6350 } else {
6351 return dflt;
6352 }
6353}
6354
6355scaled tex_get_font_math_parameter(int font, int size, int param)
6356{
6357 scaled scale = tex_get_math_font_scale(font, size);
6358 scaled value = tex_aux_get_font_math_parameter(scale, font, param);
6359 if (value == undefined_math_parameter) {
6360 return undefined_math_parameter;
6361 } else {
6362 return value ? scaledround(0.001 * glyph_scale_par * value) : 0;
6363 }
6364}
6365
6366
6367
6368scaled tex_get_font_math_y_parameter(int font, int size, int param)
6369{
6370 scaled scale = tex_get_math_font_scale(font, size);
6371 scaled value = tex_aux_get_font_math_parameter(scale, font, param);
6372 if (value == undefined_math_parameter) {
6373 return undefined_math_parameter;
6374 } else {
6375 return value ? scaledround(0.000001 * glyph_scale_par * glyph_y_scale_par * value) : 0;
6376 }
6377}
6378
6379scaled tex_get_font_math_x_parameter(int font, int size, int param)
6380{
6381 scaled scale = tex_get_math_font_scale(font, size);
6382 scaled value = tex_aux_get_font_math_parameter(scale, font, param);
6383 if (value == undefined_math_parameter) {
6384 return undefined_math_parameter;
6385 } else {
6386 return value ? scaledround(0.000001 * glyph_scale_par * glyph_x_scale_par * value) : 0;
6387 }
6388}
6389
6390halfword tex_to_math_spacing_parameter(halfword left, halfword right)
6391{
6392 halfword param = math_parameter_spacing_pair(left,right);
6393 return (param >= math_parameter_atom_pairs_first && param <= math_parameter_atom_pairs_last) ? param : -1;
6394}
6395
6396halfword tex_to_math_rules_parameter(halfword left, halfword right)
6397{
6398 halfword param = math_parameter_rules_pair(left,right);
6399 return (param >= math_parameter_atom_rules_first && param <= math_parameter_atom_rules_last) ? param : -1;
6400}
6401
6402void tex_set_default_math_codes(void)
6403{
6404 mathcodeval mval = tex_no_math_code();
6405
6406 mval.class_value = math_use_current_family_code;
6407
6408 for (int d = '0'; d <= '9'; d++) {
6409 mval.character_value = d;
6410 tex_set_math_code(d, mval, level_one);
6411 }
6412
6413 mval.family_value = 1;
6414 for (int u = 'A'; u <= 'Z'; u++) {
6415 mval.character_value = u;
6416 tex_set_math_code(u, mval, level_one);
6417 }
6418 for (int l = 'a'; l <= 'z'; l++) {
6419 mval.character_value = l;
6420 tex_set_math_code(l, mval, level_one);
6421 }
6422
6423 tex_set_del_code('.', (delcodeval) { { 0, 0, 0, }, { 0, 0, 0 } }, level_one);
6424}
6425
6426int tex_in_main_math_style(halfword style)
6427{
6428 switch (style) {
6429 case display_style:
6430 case text_style:
6431 return 1;
6432
6437 default:
6438 return 0;
6439 }
6440}
6441 |