2 Copyright 2014 Clerk Ma
\r
4 This program is free software; you can redistribute it and/or modify
\r
5 it under the terms of the GNU General Public License as published by
\r
6 the Free Software Foundation; either version 2 of the License, or
\r
7 (at your option) any later version.
\r
9 This program is distributed in the hope that it will be useful, but
\r
10 WITHOUT ANY WARRANTY; without even the implied warranty of
\r
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
\r
12 General Public License for more details.
\r
14 You should have received a copy of the GNU General Public License
\r
15 along with this program; if not, write to the Free Software
\r
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
\r
20 #define EXTERN extern
\r
21 #include "yandytex.h"
\r
24 pointer rebox (pointer b, scaled w)
\r
27 internal_font_number f;
\r
30 if ((width(b) != w) && (list_ptr(b) != 0))
\r
32 if (type(b) == vlist_node)
\r
37 if ((is_char_node(p)) && (link(p) == 0))
\r
40 v = char_width(f, char_info(f, character(p)));
\r
43 link(p) = new_kern(width(b) - v);
\r
46 free_node(b, box_node_size);
\r
47 b = new_glue(ss_glue);
\r
50 while (link(p) != 0)
\r
53 link(p) = new_glue(ss_glue);
\r
54 return hpack(b, w, exactly);
\r
63 pointer math_glue (pointer g, scaled m)
\r
69 n = x_over_n(m, 65536L);
\r
78 p = get_node(glue_spec_size);
\r
79 width(p) = mu_mult(width(g));
\r
80 stretch_order(p) = stretch_order(g);
\r
82 if (stretch_order(p) == normal)
\r
83 stretch(p) = mu_mult(stretch(g));
\r
85 stretch(p) = stretch(g);
\r
87 shrink_order(p) = shrink_order(g);
\r
89 if (shrink_order(p) == normal)
\r
90 shrink(p) = mu_mult(shrink(g));
\r
92 shrink(p) = shrink(g);
\r
97 void math_kern (pointer p, scaled m)
\r
102 if (subtype(p) == mu_glue)
\r
104 n = x_over_n(m, 65536L);
\r
113 width(p) = mu_mult(width(p));
\r
114 subtype(p) = explicit;
\r
118 void flush_math (void)
\r
120 flush_node_list(link(head));
\r
121 flush_node_list(incompleat_noad);
\r
124 incompleat_noad = 0;
\r
127 pointer clean_box (pointer p, small_number s)
\r
130 small_number save_style;
\r
134 switch (math_type(p))
\r
138 cur_mlist = new_noad();
\r
139 mem[nucleus(cur_mlist)] = mem[p];
\r
151 cur_mlist = info(p);
\r
156 q = new_null_box();
\r
162 save_style = cur_style;
\r
164 mlist_penalties = false;
\r
166 q = link(temp_head);
\r
167 cur_style = save_style;
\r
170 if (cur_style < script_style)
\r
171 cur_size = text_size;
\r
173 cur_size = 16 * ((cur_style - text_style) / 2);
\r
175 cur_mu = x_over_n(math_quad(cur_size), 18);
\r
179 if (is_char_node(q) || (q == 0))
\r
180 x = hpack(q, 0, 1);
\r
181 else if ((link(q) == 0) && (type(q) <= vlist_node) && (shift_amount(q) == 0))
\r
184 x = hpack(q, 0, 1);
\r
188 if (is_char_node(q))
\r
194 if (!is_char_node(r))
\r
195 if (type(r) == kern_node)
\r
197 free_node(r, small_node_size);
\r
205 void fetch (pointer a)
\r
207 cur_c = character(a);
\r
208 cur_f = fam_fnt(fam(a) + cur_size);
\r
210 if (cur_f == null_font)
\r
213 print_size(cur_size);
\r
216 prints(" is undefined (character ");
\r
219 help4("Somewhere in the math formula just ended, you used the",
\r
220 "stated character from an undefined font family. For example,",
\r
221 "plain TeX doesn't allow \\it or \\sl in subscripts. Proceed,",
\r
222 "and I'll try to forget that I needed that character.");
\r
224 cur_i = null_character;
\r
229 if ((cur_c >= font_bc[cur_f]) && (cur_c <= font_ec[cur_f]))
\r
230 cur_i = char_info(cur_f, cur_c);
\r
232 cur_i = null_character;
\r
234 if (!char_exists(cur_i))
\r
236 char_warning(cur_f, cur_c);
\r
242 void make_over (pointer q)
\r
244 info(nucleus(q)) = overbar(clean_box(nucleus(q), 2 * (cur_style / 2) + 1),
\r
245 3 * default_rule_thickness, default_rule_thickness);
\r
246 math_type(nucleus(q)) = sub_box;
\r
249 void make_under (pointer q)
\r
254 x = clean_box(nucleus(q), cur_style);
\r
255 p = new_kern(3 * default_rule_thickness);
\r
257 link(p) = fraction_rule(default_rule_thickness);
\r
258 y = vpackage(x, 0, 1, max_dimen);
\r
259 delta = height(y) + depth(y) + default_rule_thickness;
\r
260 height(y) = height(x);
\r
261 depth(y) = delta - height(y);
\r
262 info(nucleus(q)) = y;
\r
263 math_type(nucleus(q)) = sub_box;
\r
266 void make_vcenter (pointer q)
\r
271 v = info(nucleus(q));
\r
273 if (type(v) != vlist_node)
\r
275 confusion("vcenter");
\r
279 delta = height(v) + depth(v);
\r
280 height(v) = axis_height(cur_size) + half(delta);
\r
281 depth(v) = delta - height(v);
\r
284 void make_radical (pointer q)
\r
289 x = clean_box(nucleus(q), 2 * (cur_style / 2) + 1);
\r
291 if (cur_style < text_style)
\r
292 clr = default_rule_thickness + (abs(math_x_height(cur_size)) / 4);
\r
295 clr = default_rule_thickness;
\r
296 clr = clr + (abs(clr) / 4);
\r
299 y = var_delimiter(left_delimiter(q), cur_size, height(x) + depth(x) + clr + default_rule_thickness);
\r
300 delta = depth(y) - (height(x) + depth(x) + clr);
\r
303 clr = clr + half(delta);
\r
305 shift_amount(y) = - (integer) (height(x) + clr);
\r
306 link(y) = overbar(x, clr, height(y));
\r
307 info(nucleus(q)) = hpack(y, 0, 1);
\r
308 math_type(nucleus(q)) = sub_box;
\r
311 void make_math_accent (pointer q)
\r
316 internal_font_number f;
\r
323 fetch(accent_chr(q));
\r
325 if (char_exists(cur_i))
\r
332 if (math_type(nucleus(q)) == math_char)
\r
336 if (char_tag(cur_i) == lig_tag)
\r
338 a = lig_kern_start(cur_f, cur_i);
\r
339 cur_i = font_info[a].qqqq;
\r
341 if (skip_byte(cur_i) > stop_flag)
\r
343 a = lig_kern_restart(cur_f, cur_i);
\r
344 cur_i = font_info[a].qqqq;
\r
349 if (next_char(cur_i) == skew_char[cur_f])
\r
351 if (op_byte(cur_i) >= kern_flag)
\r
352 if (skip_byte(cur_i) <= stop_flag)
\r
353 s = char_kern(cur_f, cur_i);
\r
358 if (skip_byte(cur_i) >= stop_flag)
\r
361 a = a + skip_byte(cur_i) + 1;
\r
362 cur_i = font_info[a].qqqq;
\r
368 x = clean_box(nucleus(q), cramped_style(cur_style));
\r
374 if (char_tag(i) != list_tag)
\r
378 i = char_info(f, y);
\r
380 if (!char_exists(i))
\r
383 if (char_width(f, i) > w)
\r
390 if (h < x_height(f))
\r
393 delta = x_height(f);
\r
395 if ((math_type(supscr(q)) != 0) || (math_type(subscr(q)) != 0))
\r
396 if (math_type(nucleus(q)) == math_char)
\r
398 flush_node_list(x);
\r
400 mem[nucleus(x)] = mem[nucleus(q)];
\r
401 mem[supscr(x)] = mem[supscr(q)];
\r
402 mem[subscr(x)] = mem[subscr(q)];
\r
403 mem[supscr(q)].hh = empty_field;
\r
404 mem[subscr(q)].hh = empty_field;
\r
405 math_type(nucleus(q)) = sub_mlist;
\r
406 info(nucleus(q)) = x;
\r
407 x = clean_box(nucleus(q), cur_style);
\r
408 delta = delta + height(x) - h;
\r
412 y = char_box(f, c);
\r
413 shift_amount(y) = s + half(w - width(y));
\r
415 p = new_kern(-(integer) delta);
\r
418 y = vpackage(y, 0, 1, max_dimen);
\r
419 width(y) = width(x);
\r
423 p = new_kern(h - height(y));
\r
424 link(p) = list_ptr(y);
\r
429 info(nucleus(q)) = y;
\r
430 math_type(nucleus(q)) = sub_box;
\r
434 void make_fraction (pointer q)
\r
436 pointer p, v, x, y, z;
\r
437 scaled delta, delta1, delta2, shift_up, shift_down, clr;
\r
439 if (thickness(q) == default_code)
\r
440 thickness(q) = default_rule_thickness;
\r
442 x = clean_box(numerator(q), num_style(cur_style));
\r
443 z = clean_box(denominator(q), denom_style(cur_style));
\r
445 if (width(x) < width(z))
\r
446 x = rebox(x, width(z));
\r
448 z = rebox(z, width(x));
\r
450 if (cur_style < text_style)
\r
452 shift_up = num1(cur_size);
\r
453 shift_down = denom1(cur_size);
\r
457 shift_down = denom2(cur_size);
\r
459 if (thickness(q) != 0)
\r
460 shift_up = num2(cur_size);
\r
462 shift_up = num3(cur_size);
\r
465 if (thickness(q) == 0)
\r
467 if (cur_style < text_style)
\r
468 clr = 7 * default_rule_thickness;
\r
470 clr = 3 * default_rule_thickness;
\r
472 delta = half(clr - ((shift_up - depth(x)) - (height(z) - shift_down)));
\r
476 shift_up = shift_up + delta;
\r
477 shift_down = shift_down + delta;
\r
482 if (cur_style < text_style)
\r
483 clr = 3 * thickness(q);
\r
485 clr = thickness(q);
\r
487 delta = half(thickness(q));
\r
488 delta1 = clr - ((shift_up - depth(x)) - (axis_height(cur_size) + delta));
\r
489 delta2 = clr - ((axis_height(cur_size) - delta) - (height(z) - shift_down));
\r
492 shift_up = shift_up + delta1;
\r
495 shift_down = shift_down + delta2;
\r
498 v = new_null_box();
\r
499 type(v) = vlist_node;
\r
500 height(v) = shift_up + height(x);
\r
501 depth(v) = depth(z) + shift_down;
\r
502 width(v) = width(x);
\r
504 if (thickness(q) == 0)
\r
506 p = new_kern((shift_up - depth(x)) - (height(z) - shift_down));
\r
511 y = fraction_rule(thickness(q));
\r
512 p = new_kern((axis_height(cur_size) - delta) - (height(z) - shift_down));
\r
515 p = new_kern((shift_up - depth(x)) - (axis_height(cur_size) + delta));
\r
522 if (cur_style < text_style)
\r
523 delta = delim1(cur_size);
\r
525 delta = delim2(cur_size);
\r
527 x = var_delimiter(left_delimiter(q), cur_size, delta);
\r
529 z = var_delimiter(right_delimiter(q), cur_size, delta);
\r
531 new_hlist(q) = hpack(x, 0, 1);
\r
534 void make_ord (pointer q)
\r
540 if (math_type(subscr(q)) == 0)
\r
541 if (math_type(supscr(q)) == 0)
\r
542 if (math_type(nucleus(q)) == math_char)
\r
547 if ((type(p) >= ord_noad) && (type(p) <= punct_noad))
\r
548 if (math_type(nucleus(p)) == math_char)
\r
549 if (fam(nucleus(p)) == fam(nucleus(q)))
\r
551 math_type(nucleus(q)) = math_text_char;
\r
554 if (char_tag(cur_i) == lig_tag)
\r
556 a = lig_kern_start(cur_f, cur_i);
\r
557 cur_c = character(nucleus(p));
\r
558 cur_i = font_info[a].qqqq;
\r
560 if (skip_byte(cur_i) > stop_flag)
\r
562 a = lig_kern_restart(cur_f, cur_i);
\r
563 cur_i = font_info[a].qqqq;
\r
568 if (next_char(cur_i) == cur_c)
\r
569 if (skip_byte(cur_i) <= stop_flag)
\r
570 if (op_byte(cur_i) >= kern_flag)
\r
572 p = new_kern(char_kern(cur_f, cur_i));
\r
581 switch (op_byte(cur_i))
\r
585 character(nucleus(q)) = rem_byte(cur_i);
\r
589 character(nucleus(p)) = rem_byte(cur_i);
\r
596 character(nucleus(r)) = rem_byte(cur_i);
\r
597 fam(nucleus(r)) = fam(nucleus(q));
\r
601 if (op_byte(cur_i) < 11)
\r
602 math_type(nucleus(r)) = math_char;
\r
604 math_type(nucleus(r)) = math_text_char;
\r
611 character(nucleus(q)) = rem_byte(cur_i);
\r
612 mem[subscr(q)] = mem[subscr(p)];
\r
613 mem[supscr(q)] = mem[supscr(p)];
\r
614 free_node(p, noad_size);
\r
619 if (op_byte(cur_i) > 3)
\r
622 math_type(nucleus(q)) = math_char;
\r
626 if (skip_byte(cur_i) >= stop_flag)
\r
629 a = a + skip_byte(cur_i) + 1;
\r
630 cur_i = font_info[a].qqqq;
\r
637 small_number make_left_right (pointer q, small_number style, scaled max_d, scaled max_h)
\r
639 scaled delta, delta1, delta2;
\r
641 if (style < script_style)
\r
642 cur_size = text_size;
\r
644 cur_size = 16 * ((style - text_style) / 2);
\r
646 delta2 = max_d + axis_height(cur_size);
\r
647 delta1 = max_h + max_d - delta2;
\r
649 if (delta2 > delta1)
\r
652 delta = (delta1 / 500) * delimiter_factor;
\r
653 delta2 = delta1 + delta1 - delimiter_shortfall;
\r
655 if (delta < delta2)
\r
658 new_hlist(q) = var_delimiter(delimiter(q), cur_size, delta);
\r
660 return type(q) - (left_noad - open_noad);
\r
663 void mlist_to_hlist (void)
\r
667 small_number style;
\r
668 small_number save_style;
\r
671 /* small_number r_type; */
\r
673 /* small_number t; */
\r
675 pointer p, x, y, z;
\r
678 scaled max_h, max_d;
\r
682 penalties = mlist_penalties;
\r
691 if (cur_style < script_style)
\r
692 cur_size = text_size;
\r
694 cur_size = 16 * ((cur_style - text_style) / 2);
\r
696 cur_mu = x_over_n(math_quad(cur_size), 18);
\r
716 type(q) = ord_noad;
\r
732 if (r_type == bin_noad)
\r
733 type(r) = ord_noad;
\r
735 if (type(q) == right_noad)
\r
736 goto done_with_noad;
\r
741 goto done_with_noad;
\r
744 case fraction_noad:
\r
747 goto check_dimensions;
\r
753 delta = make_op(q);
\r
755 if (subtype(q) == limits)
\r
756 goto check_dimensions;
\r
782 make_math_accent(q);
\r
791 cur_style = subtype(q);
\r
794 if (cur_style < script_style)
\r
795 cur_size = text_size;
\r
797 cur_size = 16 * ((cur_style - text_style) / 2);
\r
799 cur_mu = x_over_n(math_quad(cur_size), 18);
\r
802 goto done_with_node;
\r
808 switch (cur_style / 2)
\r
811 choose_mlist(display_mlist);
\r
815 choose_mlist(text_mlist);
\r
819 choose_mlist(script_mlist);
\r
823 choose_mlist(script_script_mlist);
\r
827 flush_node_list(display_mlist(q));
\r
828 flush_node_list(text_mlist(q));
\r
829 flush_node_list(script_mlist(q));
\r
830 flush_node_list(script_script_mlist(q));
\r
831 type(q) = style_node;
\r
832 subtype(q) = cur_style;
\r
841 while (link(p) != 0)
\r
847 goto done_with_node;
\r
857 goto done_with_node;
\r
862 if (height(q) > max_h)
\r
865 if (depth(q) > max_d)
\r
868 goto done_with_node;
\r
874 if (subtype(q) == mu_glue)
\r
877 y = math_glue(x, cur_mu);
\r
878 delete_glue_ref(x);
\r
880 subtype(q) = normal;
\r
882 else if ((cur_size != text_size) && (subtype(q) == cond_math_glue))
\r
887 if ((type(q) == glue_node) || (type(p) == kern_node))
\r
891 flush_node_list(p);
\r
895 goto done_with_node;
\r
901 math_kern(q, cur_mu);
\r
902 goto done_with_node;
\r
908 confusion("mlist1");
\r
914 switch (math_type(nucleus(q)))
\r
917 case math_text_char:
\r
921 if (char_exists(cur_i))
\r
923 delta = char_italic(cur_f, cur_i);
\r
924 p = new_character(cur_f, cur_c);
\r
926 if ((math_type(nucleus(q)) == math_text_char) && (space(cur_f) != 0))
\r
929 if ((math_type(subscr(q)) == 0) && (delta != 0))
\r
931 link(p) = new_kern(delta);
\r
945 p = info(nucleus(q));
\r
950 cur_mlist = info(nucleus(q));
\r
951 save_style = cur_style;
\r
952 mlist_penalties = false;
\r
954 cur_style = save_style;
\r
957 if (cur_style < script_style)
\r
958 cur_size = text_size;
\r
960 cur_size = 16 * ((cur_style - text_style) / 2);
\r
962 cur_mu = x_over_n(math_quad(cur_size), 18);
\r
965 p = hpack(link(temp_head), 0, 1);
\r
971 confusion("mlist2");
\r
979 if ((math_type(subscr(q)) == 0) && (math_type(supscr(q)) == 0))
\r
980 goto check_dimensions;
\r
982 make_scripts(q, delta);
\r
985 z = hpack(new_hlist(q), 0, 1);
\r
987 if (height(z) > max_h)
\r
990 if (depth(z) > max_d)
\r
993 free_node(z, box_node_size);
\r
1003 if (r_type == bin_noad)
\r
1004 type(r) = ord_noad;
\r
1010 cur_style = style;
\r
1013 if (cur_style < script_style)
\r
1014 cur_size = text_size;
\r
1016 cur_size = 16 *((cur_style - text_style) / 2);
\r
1018 cur_mu = x_over_n(math_quad(cur_size), 18);
\r
1025 pen = inf_penalty;
\r
1040 pen = bin_op_penalty;
\r
1047 pen = rel_penalty;
\r
1052 case vcenter_noad:
\r
1058 case radical_noad:
\r
1059 s = radical_noad_size;
\r
1063 s = accent_noad_size;
\r
1066 case fraction_noad:
\r
1069 s = fraction_noad_size;
\r
1075 t = make_left_right(q, style, max_d, max_h);
\r
1080 cur_style = subtype(q);
\r
1081 s = style_node_size;
\r
1084 if (cur_style < script_style)
\r
1085 cur_size = text_size;
\r
1087 cur_size = 16 *((cur_style - text_style) / 2);
\r
1089 cur_mu = x_over_n(math_quad(cur_size), 18);
\r
1096 case whatsit_node:
\r
1097 case penalty_node:
\r
1116 confusion("mlist3");
\r
1124 switch (str_pool[r_type * 8 + t + magic_offset])
\r
1131 if (cur_style < script_style)
\r
1132 x = thin_mu_skip_code;
\r
1138 x = thin_mu_skip_code;
\r
1142 if (cur_style < script_style)
\r
1143 x = med_mu_skip_code;
\r
1149 if (cur_style < script_style)
\r
1150 x = thick_mu_skip_code;
\r
1157 confusion("mlist4");
\r
1165 y = math_glue(glue_par(x), cur_mu);
\r
1167 glue_ref_count(y) = 0;
\r
1170 subtype(z) = x + 1;
\r
1174 if (new_hlist(q) != 0)
\r
1176 link(p) = new_hlist(q);
\r
1182 while (!(link(p) == 0));
\r
1187 if (pen < inf_penalty)
\r
1189 r_type = type(link(q));
\r
1191 if (r_type != penalty_node)
\r
1192 if (r_type != rel_noad)
\r
1194 z = new_penalty(pen);
\r
1210 void push_alignment (void)
\r
1214 p = get_node(align_stack_node_size);
\r
1215 link(p) = align_ptr;
\r
1216 info(p) = cur_align;
\r
1217 llink(p) = preamble;
\r
1218 rlink(p) = cur_span;
\r
1219 mem[p + 2].cint = cur_loop;
\r
1220 mem[p + 3].cint = align_state;
\r
1221 info(p + 4) = cur_head;
\r
1222 link(p + 4) = cur_tail;
\r
1224 cur_head = get_avail();
\r
1227 void pop_alignment (void)
\r
1231 free_avail(cur_head);
\r
1233 cur_tail = link(p + 4);
\r
1234 cur_head = info(p + 4);
\r
1235 align_state = mem[p + 3].cint;
\r
1236 cur_loop = mem[p + 2].cint;
\r
1237 cur_span = rlink(p);
\r
1238 preamble = llink(p);
\r
1239 cur_align = info(p);
\r
1240 align_ptr = link(p);
\r
1241 free_node(p, align_stack_node_size);
\r
1244 void get_preamble_token (void)
\r
1249 while ((cur_chr == span_code) && (cur_cmd == tab_mark))
\r
1253 if (cur_cmd > max_command)
\r
1260 if (cur_cmd == endv)
\r
1262 fatal_error("(interwoven alignment preambles are not allowed)");
\r
1266 if ((cur_cmd == assign_glue) && (cur_chr == glue_base + tab_skip_code))
\r
1268 scan_optional_equals();
\r
1269 scan_glue(glue_val);
\r
1271 if (global_defs > 0)
\r
1272 geq_define(glue_base + tab_skip_code, glue_ref, cur_val);
\r
1274 eq_define(glue_base + tab_skip_code, glue_ref, cur_val);
\r
1280 void init_align (void)
\r
1282 pointer save_cs_ptr;
\r
1285 save_cs_ptr = cur_cs;
\r
1287 align_state = -1000000L;
\r
1289 if ((mode == mmode) && ((tail != head) || (incompleat_noad != 0)))
\r
1291 print_err("Improper ");
\r
1292 print_esc("halign");
\r
1293 prints(" inside $$'s");
\r
1294 help3("Displays can use special alignments (like \\eqalignno)",
\r
1295 "only if nothing but the alignment itself is between $$'s.",
\r
1296 "So I've deleted the formulas that preceded this alignment.");
\r
1303 if (mode == mmode)
\r
1306 prev_depth = nest[nest_ptr - 2].aux_field.cint;
\r
1308 else if (mode > 0)
\r
1309 mode = - (integer) mode;
\r
1311 scan_spec(align_group, false);
\r
1313 cur_align = align_head;
\r
1315 scanner_status = aligning;
\r
1316 warning_index = save_cs_ptr;
\r
1317 align_state = -1000000L;
\r
1321 link(cur_align) = new_param_glue(tab_skip_code);
\r
1322 cur_align = link(cur_align);
\r
1324 if (cur_cmd == car_ret)
\r
1332 get_preamble_token();
\r
1334 if (cur_cmd == mac_param)
\r
1337 if ((cur_cmd <= car_ret) && (cur_cmd >= tab_mark) && (align_state == -1000000L))
\r
1338 if ((p == hold_head) && (cur_loop == 0) && (cur_cmd == tab_mark))
\r
1339 cur_loop = cur_align;
\r
1342 print_err("Missing # inserted in alignment preamble");
\r
1343 help3("There should be exactly one # between &'s, when an",
\r
1344 "\\halign or \\valign is being set up. In this case you had",
\r
1345 "none, so I've put one in; maybe that will work.");
\r
1349 else if ((cur_cmd != spacer) || (p != hold_head))
\r
1351 link(p) = get_avail();
\r
1353 info(p) = cur_tok;
\r
1358 link(cur_align) = new_null_box();
\r
1359 cur_align = link(cur_align);
\r
1360 info(cur_align) = end_span;
\r
1361 width(cur_align) = null_flag;
\r
1362 u_part(cur_align) = link(hold_head);
\r
1369 get_preamble_token();
\r
1371 if ((cur_cmd <= car_ret) && (cur_cmd >= tab_mark) && (align_state == -1000000L))
\r
1374 if (cur_cmd == mac_param)
\r
1376 print_err("Only one # is allowed per tab");
\r
1377 help3("There should be exactly one # between &'s, when an",
\r
1378 "\\halign or \\valign is being set up. In this case you had",
\r
1379 "more than one, so I'm ignoring all but the first.");
\r
1384 link(p) = get_avail();
\r
1386 info(p) = cur_tok;
\r
1390 link(p) = get_avail();
\r
1392 info(p) = end_template_token;
\r
1393 v_part(cur_align) = link(hold_head);
\r
1397 scanner_status = 0;
\r
1398 new_save_level(align_group);
\r
1400 if (every_cr != 0)
\r
1401 begin_token_list(every_cr, every_cr_text);
\r
1406 void init_span (pointer p)
\r
1410 if (mode == -hmode)
\r
1411 space_factor = 1000;
\r
1414 prev_depth = ignore_depth;
\r
1415 normal_paragraph();
\r
1421 void init_row (void)
\r
1425 mode = (-hmode - vmode) - mode;
\r
1427 if (mode == -hmode)
\r
1432 tail_append(new_glue(glue_ptr(preamble)));
\r
1433 subtype(tail) = tab_skip_code + 1;
\r
1434 cur_align = link(preamble);
\r
1435 cur_tail = cur_head;
\r
1436 init_span(cur_align);
\r
1439 void init_col (void)
\r
1441 extra_info(cur_align) = cur_cmd;
\r
1443 if (cur_cmd == omit)
\r
1448 begin_token_list(u_part(cur_align), u_template);
\r
1452 void fin_row (void)
\r
1456 if (mode == -hmode)
\r
1458 p = hpack(link(head), 0, 1);
\r
1460 append_to_vlist(p);
\r
1462 if (cur_head != cur_tail)
\r
1464 link(tail) = link(cur_head);
\r
1470 p = vpackage(link(head), 0, 1, max_dimen);
\r
1474 space_factor = 1000;
\r
1477 type(p) = unset_node;
\r
1478 glue_stretch(p) = 0;
\r
1480 if (every_cr != 0)
\r
1481 begin_token_list(every_cr, every_cr_text);
\r
1486 void fin_align (void)
\r
1488 pointer p, q, r, s, u, v;
\r
1493 memory_word aux_save;
\r
1495 if (cur_group != align_group)
\r
1497 confusion("align1");
\r
1503 if (cur_group != align_group)
\r
1505 confusion("align0");
\r
1511 if (nest[nest_ptr - 1].mode_field == mmode)
\r
1512 o = display_indent;
\r
1516 q = link(preamble);
\r
1520 flush_list(u_part(q));
\r
1521 flush_list(v_part(q));
\r
1522 p = link(link(q));
\r
1524 if (width(q) == null_flag)
\r
1530 if (s != zero_glue)
\r
1532 add_glue_ref(zero_glue);
\r
1533 delete_glue_ref(s);
\r
1534 glue_ptr(c) = zero_glue;
\r
1538 if (info(q) != end_span)
\r
1540 t = width(q) + width(glue_ptr(link(q)));
\r
1544 n = min_quarterword + 1;
\r
1548 width(r) = width(r) - t;
\r
1551 while (link(r) > n)
\r
1554 n = link(info(s)) + 1;
\r
1559 info(r) = info(s);
\r
1566 if (width(r) > width(info(s)))
\r
1567 width(info(s)) = width(r);
\r
1569 free_node(r, span_node_size);
\r
1574 while (!(r == end_span));
\r
1577 type(q) = unset_node;
\r
1578 span_count(q) = min_quarterword;
\r
1581 glue_order(q) = normal;
\r
1582 glue_sign(q) = normal;
\r
1583 glue_stretch(q) = 0;
\r
1584 glue_shrink(q) = 0;
\r
1587 while (!(q == 0));
\r
1589 save_ptr = save_ptr - 2;
\r
1590 pack_begin_line = - (integer) mode_line;
\r
1592 if (mode == -vmode)
\r
1594 rule_save = overfull_rule;
\r
1595 overfull_rule = 0;
\r
1596 p = hpack(preamble, saved(1), saved(0));
\r
1597 overfull_rule = rule_save;
\r
1601 q = link(preamble);
\r
1605 height(q) = width(q);
\r
1607 q = link(link(q));
\r
1609 while (!(q == 0));
\r
1611 p = vpackage(preamble, saved(1), saved(0), max_dimen);
\r
1612 q = link(preamble);
\r
1616 width(q) = height(q);
\r
1618 q = link(link(q));
\r
1620 while (!(q == 0));
\r
1623 pack_begin_line = 0;
\r
1629 if (!is_char_node(q))
\r
1630 if (type(q) == unset_node)
\r
1632 if (mode == -vmode)
\r
1634 type(q) = hlist_node;
\r
1635 width(q) = width(p);
\r
1639 type(q) = vlist_node;
\r
1640 height(q) = height(p);
\r
1643 glue_order(q) = glue_order(p);
\r
1644 glue_sign(q) = glue_sign(p);
\r
1645 glue_set(q) = glue_set(p);
\r
1646 shift_amount(q) = o;
\r
1647 r = link(list_ptr(q));
\r
1648 s = link(list_ptr(p));
\r
1652 n = span_count(r);
\r
1657 while (n > min_quarterword)
\r
1662 link(u) = new_glue(v);
\r
1664 subtype(u) = tab_skip_code + 1;
\r
1667 if (glue_sign(p) == stretching)
\r
1669 if (stretch_order(v) == glue_order(p))
\r
1670 t = t + round(glue_set(p) * stretch(v));
\r
1672 else if (glue_sign(p) == shrinking)
\r
1674 if (shrink_order(v) == glue_order(p))
\r
1675 t = t - round(glue_set(p) * shrink(v));
\r
1679 link(u) = new_null_box();
\r
1683 if (mode == -vmode)
\r
1684 width(u) = width(s);
\r
1687 type(u) = vlist_node;
\r
1688 height(u) = width(s);
\r
1693 if (mode == -vmode)
\r
1695 height(r) = height(q);
\r
1696 depth(r) = depth(q);
\r
1698 if (t == width(r))
\r
1700 glue_sign(r) = normal;
\r
1701 glue_order(r) = normal;
\r
1702 glue_set(r) = 0.0;
\r
1704 else if (t > width(r))
\r
1706 glue_sign(r) = stretching;
\r
1708 if (glue_stretch(r) == 0)
\r
1709 glue_set(r) = 0.0;
\r
1711 glue_set(r) = (t - width(r)) / ((double) glue_stretch(r));
\r
1715 glue_order(r) = glue_sign(r);
\r
1716 glue_sign(r) = shrinking;
\r
1718 if (glue_shrink(r) == 0)
\r
1719 glue_set(r) = 0.0;
\r
1720 else if ((glue_order(r) == normal) && (width(r) - t > glue_shrink(r)))
\r
1721 glue_set(r) = 1.0;
\r
1723 glue_set(r) = (width(r) - t)/ ((double) glue_shrink(r));
\r
1727 type(r) = hlist_node;
\r
1731 width(r) = width(q);
\r
1733 if (t == height(r))
\r
1735 glue_sign(r) = normal;
\r
1736 glue_order(r) = normal;
\r
1737 glue_set(r) = 0.0;
\r
1739 else if (t > height(r))
\r
1741 glue_sign(r) = stretching;
\r
1743 if (glue_stretch(r) == 0)
\r
1744 glue_set(r) = 0.0;
\r
1746 glue_set(r) = (t - height(r)) / ((double) glue_stretch(r));
\r
1750 glue_order(r) = glue_sign(r);
\r
1751 glue_sign(r) = shrinking;
\r
1753 if (glue_shrink(r) == 0)
\r
1754 glue_set(r) = 0.0;
\r
1755 else if ((glue_order(r) == normal) && (height(r) - t > glue_shrink(r)))
\r
1756 glue_set(r) = 1.0;
\r
1758 glue_set(r) = (height(r) - t) / ((double) glue_shrink(r));
\r
1762 type(r) = vlist_node;
\r
1765 shift_amount(r) = 0;
\r
1767 if (u != hold_head)
\r
1769 link(u) = link(r);
\r
1770 link(r) = link(hold_head);
\r
1774 r = link(link(r));
\r
1775 s = link(link(s));
\r
1777 while (!(r == 0));
\r
1779 else if (type(q) == rule_node)
\r
1781 if (is_running(width(q)))
\r
1782 width(q) = width(p);
\r
1784 if (is_running(height(q)))
\r
1785 height(q) = height(p);
\r
1787 if (is_running(depth(q)))
\r
1788 depth(q) = depth(p);
\r
1794 q = hpack(q, 0, 1);
\r
1795 shift_amount(q) = o;
\r
1804 flush_node_list(p);
\r
1806 aux_save = cur_list.aux_field;
\r
1811 if (mode == mmode)
\r
1815 if (cur_cmd != math_shift)
\r
1817 print_err("Missing $$ inserted");
\r
1818 help2("Displays can use special alignments (like \\eqalignno)",
\r
1819 "only if nothing but the alignment itself is between $$'s.");
\r
1826 if (cur_cmd != math_shift)
\r
1828 print_err("Display math should end with $$");
\r
1829 help2("The `$' that I just saw supposedly matches a previous `$$'.",
\r
1830 "So I shall assume that you typed `$$' both times.");
\r
1836 tail_append(new_penalty(pre_display_penalty));
\r
1837 tail_append(new_param_glue(above_display_skip_code));
\r
1843 tail_append(new_penalty(post_display_penalty));
\r
1844 tail_append(new_param_glue(below_display_skip_code));
\r
1845 prev_depth = aux_save.cint;
\r
1846 resume_after_display();
\r
1850 cur_list.aux_field = aux_save;
\r
1856 if (mode == vmode)
\r
1861 boolean fin_col (void)
\r
1871 if (cur_align == 0)
\r
1873 confusion("endv");
\r
1877 q = link(cur_align);
\r
1881 confusion("endv");
\r
1885 if (align_state < 500000L)
\r
1887 fatal_error("(interwoven alignment preambles are not allowed)");
\r
1893 if ((p == 0) && (extra_info(cur_align) < cr_code))
\r
1894 if (cur_loop != 0)
\r
1896 link(q) = new_null_box();
\r
1898 info(p) = end_span;
\r
1899 width(p) = null_flag;
\r
1900 cur_loop = link(cur_loop);
\r
1902 r = u_part(cur_loop);
\r
1906 link(q) = get_avail();
\r
1908 info(q) = info(r);
\r
1913 u_part(p) = link(hold_head);
\r
1915 r = v_part(cur_loop);
\r
1919 link(q) = get_avail();
\r
1921 info(q) = info(r);
\r
1926 v_part(p) = link(hold_head);
\r
1927 cur_loop = link(cur_loop);
\r
1928 link(p) = new_glue(glue_ptr(cur_loop));
\r
1932 print_err("Extra alignment tab has been changed to ");
\r
1934 help3("You have given more \\span or & marks than there were",
\r
1935 "in the preamble to the \\halign or \\valign now in progress.",
\r
1936 "So I'll assume that you meant to type \\cr instead.");
\r
1937 extra_info(cur_align) = cr_code;
\r
1941 if (extra_info(cur_align) != span_code)
\r
1944 new_save_level(align_group);
\r
1947 if (mode == -hmode)
\r
1949 adjust_tail = cur_tail;
\r
1950 u = hpack(link(head), 0, 1);
\r
1952 cur_tail = adjust_tail;
\r
1957 u = vpackage(link(head), 0, 1, 0);
\r
1961 n = min_quarterword;
\r
1963 if (cur_span != cur_align)
\r
1970 q = link(link(q));
\r
1972 while (!(q == cur_align));
\r
1974 if (n > max_quarterword)
\r
1976 confusion("256 spans");
\r
1982 while (link(info(q)) < n)
\r
1985 if (link(info(q)) > n)
\r
1987 s = get_node(span_node_size);
\r
1988 info(s) = info(q);
\r
1993 else if (width(info(q)) < w)
\r
1994 width(info(q)) = w;
\r
1996 else if (w > width(cur_align))
\r
1997 width(cur_align) = w;
\r
1999 type(u) = unset_node;
\r
2000 span_count(u) = n;
\r
2002 if (total_stretch[filll] != 0)
\r
2004 else if (total_stretch[fill] != 0)
\r
2006 else if (total_stretch[fil] != 0)
\r
2011 glue_order(u) = o;
\r
2012 glue_stretch(u) = total_stretch[o];
\r
2014 if (total_shrink[filll] != 0)
\r
2016 else if (total_shrink[fill] != 0)
\r
2018 else if (total_shrink[fil] != 0)
\r
2024 glue_shrink(u) = total_shrink[o];
\r
2030 tail_append(new_glue(glue_ptr(link(cur_align))));
\r
2031 subtype(tail) = tab_skip_code + 1;
\r
2033 if (extra_info(cur_align) >= cr_code)
\r
2041 align_state = 1000000L;
\r
2047 while (!(cur_cmd != spacer));
\r
2055 scaled make_op (pointer q)
\r
2058 pointer p, v, x, y, z;
\r
2061 scaled shift_up, shift_down;
\r
2063 if ((subtype(q) == normal) && (cur_style < text_style))
\r
2064 subtype(q) = limits;
\r
2066 if (math_type(nucleus(q)) == math_char)
\r
2068 fetch(nucleus(q));
\r
2070 if ((cur_style < text_style) && (char_tag(cur_i) == list_tag))
\r
2072 c = rem_byte(cur_i);
\r
2073 i = char_info(cur_f, c);
\r
2075 if (char_exists(i))
\r
2079 character(nucleus(q)) = c;
\r
2083 delta = char_italic(cur_f, cur_i);
\r
2084 x = clean_box(nucleus(q), cur_style);
\r
2086 if ((math_type(subscr(q)) != 0) && (subtype(q) != limits))
\r
2087 width(x) = width(x) - delta;
\r
2089 shift_amount(x) = half(height(x) - depth(x)) - axis_height(cur_size);
\r
2090 math_type(nucleus(q)) = sub_box;
\r
2091 info(nucleus(q)) = x;
\r
2096 if (subtype(q) == limits)
\r
2098 x = clean_box(supscr(q), sup_style(cur_style));
\r
2099 y = clean_box(nucleus(q), cur_style);
\r
2100 z = clean_box(subscr(q), sub_style(cur_style));
\r
2101 v = new_null_box();
\r
2102 type(v) = vlist_node;
\r
2103 width(v) = width(y);
\r
2105 if (width(x) > width(v))
\r
2106 width(v) = width(x);
\r
2108 if (width(z) > width(v))
\r
2109 width(v) = width(z);
\r
2111 x = rebox(x, width(v));
\r
2112 y = rebox(y, width(v));
\r
2113 z = rebox(z, width(v));
\r
2114 shift_amount(x) = half(delta);
\r
2115 shift_amount(z) = - (integer) shift_amount(x);
\r
2116 height(v) = height(y);
\r
2117 depth(v) = depth(y);
\r
2119 if (math_type(supscr(q)) == 0)
\r
2121 free_node(x, box_node_size);
\r
2126 shift_up = big_op_spacing3 - depth(x);
\r
2128 if (shift_up < big_op_spacing1)
\r
2129 shift_up = big_op_spacing1;
\r
2131 p = new_kern(shift_up);
\r
2134 p = new_kern(big_op_spacing5);
\r
2137 height(v) = height(v) + big_op_spacing5 + height(x) + depth(x) + shift_up;
\r
2140 if (math_type(subscr(q)) == 0)
\r
2141 free_node(z, box_node_size);
\r
2144 shift_down = big_op_spacing4 - height(z);
\r
2146 if (shift_down < big_op_spacing2)
\r
2147 shift_down = big_op_spacing2;
\r
2149 p = new_kern(shift_down);
\r
2152 p = new_kern(big_op_spacing5);
\r
2154 depth(v) = depth(v) + big_op_spacing5 + height(z) + depth(z) + shift_down;
\r
2163 void make_scripts (pointer q, scaled delta)
\r
2165 pointer p, x, y, z;
\r
2166 scaled shift_up, shift_down, clr;
\r
2171 if (is_char_node(p))
\r
2178 z = hpack(p, 0, 1);
\r
2180 if (cur_style < script_style)
\r
2183 t = script_script_size;
\r
2185 shift_up = height(z) - sup_drop(t);
\r
2186 shift_down = depth(z) + sub_drop(t);
\r
2187 free_node(z, box_node_size);
\r
2190 if (math_type(supscr(q)) == 0)
\r
2192 x = clean_box(subscr(q), sub_style(cur_style));
\r
2193 width(x) = width(x) + script_space;
\r
2195 if (shift_down < sub1(cur_size))
\r
2196 shift_down = sub1(cur_size);
\r
2198 clr = height(x) -(abs(math_x_height(cur_size) * 4) / 5);
\r
2200 if (shift_down < clr)
\r
2203 shift_amount(x) = shift_down;
\r
2208 x = clean_box(supscr(q), sup_style(cur_style));
\r
2209 width(x) = width(x) + script_space;
\r
2211 if (odd(cur_style))
\r
2212 clr = sup3(cur_size);
\r
2213 else if (cur_style < text_style)
\r
2214 clr = sup1(cur_size);
\r
2216 clr = sup2(cur_size);
\r
2218 if (shift_up < clr)
\r
2221 clr = depth(x) +(abs(math_x_height(cur_size)) / 4);
\r
2223 if (shift_up < clr)
\r
2227 if (math_type(subscr(q)) == 0)
\r
2228 shift_amount(x) = - (integer) shift_up;
\r
2231 y = clean_box(subscr(q), sub_style(cur_style));
\r
2232 width(y) = width(y) + script_space;
\r
2234 if (shift_down < sub2(cur_size))
\r
2235 shift_down = sub2(cur_size);
\r
2237 clr = 4 * default_rule_thickness - ((shift_up - depth(x)) - (height(y) - shift_down));
\r
2241 shift_down = shift_down + clr;
\r
2243 clr = (abs(math_x_height(cur_size) * 4) / 5) - (shift_up - depth(x));
\r
2247 shift_up = shift_up + clr;
\r
2248 shift_down = shift_down - clr;
\r
2252 shift_amount(x) = delta;
\r
2253 p = new_kern((shift_up - depth(x)) - (height(y) - shift_down));
\r
2256 x = vpackage(x, 0, 1, max_dimen);
\r
2257 shift_amount(x) = shift_down;
\r
2261 if (new_hlist(q) == 0)
\r
2267 while (link(p) != 0)
\r