1 /* Copyright 2014 Clerk Ma
\r
3 This program is free software; you can redistribute it and/or modify
\r
4 it under the terms of the GNU General Public License as published by
\r
5 the Free Software Foundation; either version 2 of the License, or
\r
6 (at your option) any later version.
\r
8 This program is distributed in the hope that it will be useful, but
\r
9 WITHOUT ANY WARRANTY; without even the implied warranty of
\r
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
\r
11 General Public License for more details.
\r
13 You should have received a copy of the GNU General Public License
\r
14 along with this program; if not, write to the Free Software
\r
15 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
\r
18 #define EXTERN extern
\r
20 #include "yandytex.h"
\r
23 pointer rebox (pointer b, scaled w)
\r
26 internal_font_number f;
\r
29 if ((width(b) != w) && (list_ptr(b) != 0))
\r
31 if (type(b) == vlist_node)
\r
36 if ((is_char_node(p)) && (link(p) == 0))
\r
39 v = char_width(f, char_info(f, character(p)));
\r
42 link(p) = new_kern(width(b) - v);
\r
45 free_node(b, box_node_size);
\r
46 b = new_glue(ss_glue);
\r
49 while (link(p) != 0)
\r
52 link(p) = new_glue(ss_glue);
\r
53 return hpack(b, w, exactly);
\r
62 pointer math_glue (pointer g, scaled m)
\r
68 n = x_over_n(m, 65536L);
\r
77 p = get_node(glue_spec_size);
\r
78 width(p) = mu_mult(width(g));
\r
79 stretch_order(p) = stretch_order(g);
\r
81 if (stretch_order(p) == normal)
\r
82 stretch(p) = mu_mult(stretch(g));
\r
84 stretch(p) = stretch(g);
\r
86 shrink_order(p) = shrink_order(g);
\r
88 if (shrink_order(p) == normal)
\r
89 shrink(p) = mu_mult(shrink(g));
\r
91 shrink(p) = shrink(g);
\r
96 void math_kern (pointer p, scaled m)
\r
101 if (subtype(p) == mu_glue)
\r
103 n = x_over_n(m, 65536L);
\r
112 width(p) = mu_mult(width(p));
\r
113 subtype(p) = explicit;
\r
117 void flush_math (void)
\r
119 flush_node_list(link(head));
\r
120 flush_node_list(incompleat_noad);
\r
123 incompleat_noad = 0;
\r
126 pointer clean_box (pointer p, small_number s)
\r
129 small_number save_style;
\r
133 switch (math_type(p))
\r
137 cur_mlist = new_noad();
\r
138 mem[nucleus(cur_mlist)] = mem[p];
\r
150 cur_mlist = info(p);
\r
155 q = new_null_box();
\r
161 save_style = cur_style;
\r
163 mlist_penalties = false;
\r
165 q = link(temp_head);
\r
166 cur_style = save_style;
\r
169 if (cur_style < script_style)
\r
170 cur_size = text_size;
\r
172 cur_size = 16 * ((cur_style - text_style) / 2);
\r
174 cur_mu = x_over_n(math_quad(cur_size), 18);
\r
178 if (is_char_node(q) || (q == 0))
\r
179 x = hpack(q, 0, 1);
\r
180 else if ((link(q) == 0) && (type(q) <= vlist_node) && (shift_amount(q) == 0))
\r
183 x = hpack(q, 0, 1);
\r
187 if (is_char_node(q))
\r
193 if (!is_char_node(r))
\r
194 if (type(r) == kern_node)
\r
196 free_node(r, small_node_size);
\r
204 void fetch (pointer a)
\r
206 cur_c = character(a);
\r
207 cur_f = fam_fnt(fam(a) + cur_size);
\r
209 if (cur_f == null_font)
\r
212 print_size(cur_size);
\r
215 prints(" is undefined (character ");
\r
218 help4("Somewhere in the math formula just ended, you used the",
\r
219 "stated character from an undefined font family. For example,",
\r
220 "plain TeX doesn't allow \\it or \\sl in subscripts. Proceed,",
\r
221 "and I'll try to forget that I needed that character.");
\r
223 cur_i = null_character;
\r
228 if ((cur_c >= font_bc[cur_f]) && (cur_c <= font_ec[cur_f]))
\r
229 cur_i = char_info(cur_f, cur_c);
\r
231 cur_i = null_character;
\r
233 if (!char_exists(cur_i))
\r
235 char_warning(cur_f, cur_c);
\r
241 void make_over (pointer q)
\r
243 info(nucleus(q)) = overbar(clean_box(nucleus(q), 2 * (cur_style / 2) + 1),
\r
244 3 * default_rule_thickness, default_rule_thickness);
\r
245 math_type(nucleus(q)) = sub_box;
\r
248 void make_under (pointer q)
\r
253 x = clean_box(nucleus(q), cur_style);
\r
254 p = new_kern(3 * default_rule_thickness);
\r
256 link(p) = fraction_rule(default_rule_thickness);
\r
257 y = vpackage(x, 0, 1, max_dimen);
\r
258 delta = height(y) + depth(y) + default_rule_thickness;
\r
259 height(y) = height(x);
\r
260 depth(y) = delta - height(y);
\r
261 info(nucleus(q)) = y;
\r
262 math_type(nucleus(q)) = sub_box;
\r
265 void make_vcenter (pointer q)
\r
270 v = info(nucleus(q));
\r
272 if (type(v) != vlist_node)
\r
274 confusion("vcenter");
\r
278 delta = height(v) + depth(v);
\r
279 height(v) = axis_height(cur_size) + half(delta);
\r
280 depth(v) = delta - height(v);
\r
283 void make_radical (pointer q)
\r
288 x = clean_box(nucleus(q), 2 * (cur_style / 2) + 1);
\r
290 if (cur_style < text_style)
\r
291 clr = default_rule_thickness + (abs(math_x_height(cur_size)) / 4);
\r
294 clr = default_rule_thickness;
\r
295 clr = clr + (abs(clr) / 4);
\r
298 y = var_delimiter(left_delimiter(q), cur_size, height(x) + depth(x) + clr + default_rule_thickness);
\r
299 delta = depth(y) -(height(x) + depth(x) + clr);
\r
302 clr = clr + half(delta);
\r
304 shift_amount(y) = - (integer) (height(x) + clr);
\r
305 link(y) = overbar(x, clr, height(y));
\r
306 info(nucleus(q)) = hpack(y, 0, 1);
\r
307 math_type(nucleus(q)) = sub_box;
\r
310 void make_math_accent (pointer q)
\r
315 internal_font_number f;
\r
322 fetch(accent_chr(q));
\r
324 if (char_exists(cur_i))
\r
331 if (math_type(nucleus(q)) == math_char)
\r
335 if (char_tag(cur_i) == lig_tag)
\r
337 a = lig_kern_start(cur_f, cur_i);
\r
338 cur_i = font_info[a].qqqq;
\r
340 if (skip_byte(cur_i) > stop_flag)
\r
342 a = lig_kern_restart(cur_f, cur_i);
\r
343 cur_i = font_info[a].qqqq;
\r
348 if (next_char(cur_i) == skew_char[cur_f])
\r
350 if (op_byte(cur_i) >= kern_flag)
\r
351 if (skip_byte(cur_i) <= stop_flag)
\r
352 s = char_kern(cur_f, cur_i);
\r
357 if (skip_byte(cur_i) >= stop_flag)
\r
360 a = a + skip_byte(cur_i) + 1;
\r
361 cur_i = font_info[a].qqqq;
\r
367 x = clean_box(nucleus(q), cramped_style(cur_style));
\r
373 if (char_tag(i) != list_tag)
\r
377 i = char_info(f, y);
\r
379 if (!char_exists(i))
\r
382 if (char_width(f, i) > w)
\r
389 if (h < x_height(f))
\r
392 delta = x_height(f);
\r
394 if ((math_type(supscr(q)) != 0) || (math_type(subscr(q)) != 0))
\r
395 if (math_type(nucleus(q)) == math_char)
\r
397 flush_node_list(x);
\r
399 mem[nucleus(x)] = mem[nucleus(q)];
\r
400 mem[supscr(x)] = mem[supscr(q)];
\r
401 mem[subscr(x)] = mem[subscr(q)];
\r
402 mem[supscr(q)].hh = empty_field;
\r
403 mem[subscr(q)].hh = empty_field;
\r
404 math_type(nucleus(q)) = sub_mlist;
\r
405 info(nucleus(q)) = x;
\r
406 x = clean_box(nucleus(q), cur_style);
\r
407 delta = delta + height(x) - h;
\r
411 y = char_box(f, c);
\r
412 shift_amount(y) = s + half(w - width(y));
\r
414 p = new_kern(-(integer) delta);
\r
417 y = vpackage(y, 0, 1, max_dimen);
\r
418 width(y) = width(x);
\r
422 p = new_kern(h - height(y));
\r
423 link(p) = list_ptr(y);
\r
428 info(nucleus(q)) = y;
\r
429 math_type(nucleus(q)) = sub_box;
\r
433 void make_fraction (pointer q)
\r
435 pointer p, v, x, y, z;
\r
436 scaled delta, delta1, delta2, shift_up, shift_down, clr;
\r
438 if (thickness(q) == default_code)
\r
439 thickness(q) = default_rule_thickness;
\r
441 x = clean_box(numerator(q), num_style(cur_style));
\r
442 z = clean_box(denominator(q), denom_style(cur_style));
\r
444 if (width(x) < width(z))
\r
445 x = rebox(x, width(z));
\r
447 z = rebox(z, width(x));
\r
449 if (cur_style < text_style)
\r
451 shift_up = num1(cur_size);
\r
452 shift_down = denom1(cur_size);
\r
456 shift_down = denom2(cur_size);
\r
458 if (thickness(q) != 0)
\r
459 shift_up = num2(cur_size);
\r
461 shift_up = num3(cur_size);
\r
464 if (thickness(q) == 0)
\r
466 if (cur_style < text_style)
\r
467 clr = 7 * default_rule_thickness;
\r
469 clr = 3 * default_rule_thickness;
\r
471 delta = half(clr - ((shift_up - depth(x)) - (height(z) - shift_down)));
\r
475 shift_up = shift_up + delta;
\r
476 shift_down = shift_down + delta;
\r
481 if (cur_style < text_style)
\r
482 clr = 3 * thickness(q);
\r
484 clr = thickness(q);
\r
486 delta = half(thickness(q));
\r
487 delta1 = clr - ((shift_up - depth(x)) - (axis_height(cur_size) + delta));
\r
488 delta2 = clr - ((axis_height(cur_size) - delta) - (height(z) - shift_down));
\r
491 shift_up = shift_up + delta1;
\r
494 shift_down = shift_down + delta2;
\r
497 v = new_null_box();
\r
498 type(v) = vlist_node;
\r
499 height(v) = shift_up + height(x);
\r
500 depth(v) = depth(z) + shift_down;
\r
501 width(v) = width(x);
\r
503 if (thickness(q) == 0)
\r
505 p = new_kern((shift_up - depth(x)) - (height(z) - shift_down));
\r
510 y = fraction_rule(thickness(q));
\r
511 p = new_kern((axis_height(cur_size) - delta) - (height(z) - shift_down));
\r
514 p = new_kern((shift_up - depth(x)) - (axis_height(cur_size) + delta));
\r
521 if (cur_style < text_style)
\r
522 delta = delim1(cur_size);
\r
524 delta = delim2(cur_size);
\r
526 x = var_delimiter(left_delimiter(q), cur_size, delta);
\r
528 z = var_delimiter(right_delimiter(q), cur_size, delta);
\r
530 new_hlist(q) = hpack(x, 0, 1);
\r
533 void make_ord (pointer q)
\r
539 if (math_type(subscr(q)) == 0)
\r
540 if (math_type(supscr(q)) == 0)
\r
541 if (math_type(nucleus(q)) == math_char)
\r
546 if ((type(p) >= ord_noad) && (type(p) <= punct_noad))
\r
547 if (math_type(nucleus(p)) == math_char)
\r
548 if (fam(nucleus(p)) == fam(nucleus(q)))
\r
550 math_type(nucleus(q)) = math_text_char;
\r
553 if (char_tag(cur_i) == lig_tag)
\r
555 a = lig_kern_start(cur_f, cur_i);
\r
556 cur_c = character(nucleus(p));
\r
557 cur_i = font_info[a].qqqq;
\r
559 if (skip_byte(cur_i) > stop_flag)
\r
561 a = lig_kern_restart(cur_f, cur_i);
\r
562 cur_i = font_info[a].qqqq;
\r
567 if (next_char(cur_i) == cur_c)
\r
568 if (skip_byte(cur_i) <= stop_flag)
\r
569 if (op_byte(cur_i) >= kern_flag)
\r
571 p = new_kern(char_kern(cur_f, cur_i));
\r
580 switch (op_byte(cur_i))
\r
584 character(nucleus(q)) = rem_byte(cur_i);
\r
588 character(nucleus(p)) = rem_byte(cur_i);
\r
595 character(nucleus(r)) = rem_byte(cur_i);
\r
596 fam(nucleus(r)) = fam(nucleus(q));
\r
600 if (op_byte(cur_i) < 11)
\r
601 math_type(nucleus(r)) = math_char;
\r
603 math_type(nucleus(r)) = math_text_char;
\r
610 character(nucleus(q)) = rem_byte(cur_i);
\r
611 mem[subscr(q)] = mem[subscr(p)];
\r
612 mem[supscr(q)] = mem[supscr(p)];
\r
613 free_node(p, noad_size);
\r
618 if (op_byte(cur_i) > 3)
\r
621 math_type(nucleus(q)) = math_char;
\r
625 if (skip_byte(cur_i) >= stop_flag)
\r
628 a = a + skip_byte(cur_i) + 1;
\r
629 cur_i = font_info[a].qqqq;
\r
636 small_number make_left_right (pointer q, small_number style, scaled max_d, scaled max_h)
\r
638 scaled delta, delta1, delta2;
\r
640 if (style < script_style)
\r
641 cur_size = text_size;
\r
643 cur_size = 16 * ((style - text_style) / 2);
\r
645 delta2 = max_d + axis_height(cur_size);
\r
646 delta1 = max_h + max_d - delta2;
\r
648 if (delta2 > delta1)
\r
651 delta = (delta1 / 500) * delimiter_factor;
\r
652 delta2 = delta1 + delta1 - delimiter_shortfall;
\r
654 if (delta < delta2)
\r
657 new_hlist(q) = var_delimiter(delimiter(q), cur_size, delta);
\r
659 return type(q) - (left_noad - open_noad);
\r
662 void mlist_to_hlist (void)
\r
666 small_number style;
\r
667 small_number save_style;
\r
670 /* small_number r_type; */
\r
672 /* small_number t; */
\r
674 pointer p, x, y, z;
\r
677 scaled max_h, max_d;
\r
681 penalties = mlist_penalties;
\r
690 if (cur_style < script_style)
\r
691 cur_size = text_size;
\r
693 cur_size = 16 * ((cur_style - text_style) / 2);
\r
695 cur_mu = x_over_n(math_quad(cur_size), 18);
\r
715 type(q) = ord_noad;
\r
731 if (r_type == bin_noad)
\r
732 type(r) = ord_noad;
\r
734 if (type(q) == right_noad)
\r
735 goto done_with_noad;
\r
740 goto done_with_noad;
\r
743 case fraction_noad:
\r
746 goto check_dimensions;
\r
752 delta = make_op(q);
\r
754 if (subtype(q) == limits)
\r
755 goto check_dimensions;
\r
781 make_math_accent(q);
\r
790 cur_style = subtype(q);
\r
793 if (cur_style < script_style)
\r
794 cur_size = text_size;
\r
796 cur_size = 16 * ((cur_style - text_style) / 2);
\r
798 cur_mu = x_over_n(math_quad(cur_size), 18);
\r
801 goto done_with_node;
\r
807 switch (cur_style / 2)
\r
810 choose_mlist(display_mlist);
\r
814 choose_mlist(text_mlist);
\r
818 choose_mlist(script_mlist);
\r
822 choose_mlist(script_script_mlist);
\r
826 flush_node_list(display_mlist(q));
\r
827 flush_node_list(text_mlist(q));
\r
828 flush_node_list(script_mlist(q));
\r
829 flush_node_list(script_script_mlist(q));
\r
830 type(q) = style_node;
\r
831 subtype(q) = cur_style;
\r
840 while (link(p) != 0)
\r
846 goto done_with_node;
\r
856 goto done_with_node;
\r
861 if (height(q) > max_h)
\r
864 if (depth(q) > max_d)
\r
867 goto done_with_node;
\r
873 if (subtype(q) == mu_glue)
\r
876 y = math_glue(x, cur_mu);
\r
877 delete_glue_ref(x);
\r
879 subtype(q) = normal;
\r
881 else if ((cur_size != text_size) && (subtype(q) == cond_math_glue))
\r
886 if ((type(q) == glue_node) || (type(p) == kern_node))
\r
890 flush_node_list(p);
\r
894 goto done_with_node;
\r
900 math_kern(q, cur_mu);
\r
901 goto done_with_node;
\r
907 confusion("mlist1");
\r
913 switch (math_type(nucleus(q)))
\r
916 case math_text_char:
\r
920 if (char_exists(cur_i))
\r
922 delta = char_italic(cur_f, cur_i);
\r
923 p = new_character(cur_f, cur_c);
\r
925 if ((math_type(nucleus(q)) == math_text_char) && (space(cur_f) != 0))
\r
928 if ((math_type(subscr(q)) == 0) && (delta != 0))
\r
930 link(p) = new_kern(delta);
\r
944 p = info(nucleus(q));
\r
949 cur_mlist = info(nucleus(q));
\r
950 save_style = cur_style;
\r
951 mlist_penalties = false;
\r
953 cur_style = save_style;
\r
956 if (cur_style < script_style)
\r
957 cur_size = text_size;
\r
959 cur_size = 16 * ((cur_style - text_style) / 2);
\r
961 cur_mu = x_over_n(math_quad(cur_size), 18);
\r
964 p = hpack(link(temp_head), 0, 1);
\r
970 confusion("mlist2");
\r
978 if ((math_type(subscr(q)) == 0) && (math_type(supscr(q)) == 0))
\r
979 goto check_dimensions;
\r
981 make_scripts(q, delta);
\r
984 z = hpack(new_hlist(q), 0, 1);
\r
986 if (height(z) > max_h)
\r
989 if (depth(z) > max_d)
\r
992 free_node(z, box_node_size);
\r
1002 if (r_type == bin_noad)
\r
1003 type(r) = ord_noad;
\r
1009 cur_style = style;
\r
1012 if (cur_style < script_style)
\r
1013 cur_size = text_size;
\r
1015 cur_size = 16 *((cur_style - text_style) / 2);
\r
1017 cur_mu = x_over_n(math_quad(cur_size), 18);
\r
1024 pen = inf_penalty;
\r
1039 pen = bin_op_penalty;
\r
1046 pen = rel_penalty;
\r
1051 case vcenter_noad:
\r
1057 case radical_noad:
\r
1058 s = radical_noad_size;
\r
1062 s = accent_noad_size;
\r
1065 case fraction_noad:
\r
1068 s = fraction_noad_size;
\r
1074 t = make_left_right(q, style, max_d, max_h);
\r
1079 cur_style = subtype(q);
\r
1080 s = style_node_size;
\r
1083 if (cur_style < script_style)
\r
1084 cur_size = text_size;
\r
1086 cur_size = 16 *((cur_style - text_style) / 2);
\r
1088 cur_mu = x_over_n(math_quad(cur_size), 18);
\r
1095 case whatsit_node:
\r
1096 case penalty_node:
\r
1115 confusion("mlist3");
\r
1123 switch (str_pool[r_type * 8 + t + magic_offset])
\r
1130 if (cur_style < script_style)
\r
1131 x = thin_mu_skip_code;
\r
1137 x = thin_mu_skip_code;
\r
1141 if (cur_style < script_style)
\r
1142 x = med_mu_skip_code;
\r
1148 if (cur_style < script_style)
\r
1149 x = thick_mu_skip_code;
\r
1156 confusion("mlist4");
\r
1164 y = math_glue(glue_par(x), cur_mu);
\r
1166 glue_ref_count(y) = 0;
\r
1169 subtype(z) = x + 1;
\r
1173 if (new_hlist(q) != 0)
\r
1175 link(p) = new_hlist(q);
\r
1181 while (!(link(p) == 0));
\r
1186 if (pen < inf_penalty)
\r
1188 r_type = type(link(q));
\r
1190 if (r_type != penalty_node)
\r
1191 if (r_type != rel_noad)
\r
1193 z = new_penalty(pen);
\r
1209 void push_alignment (void)
\r
1213 p = get_node(align_stack_node_size);
\r
1214 link(p) = align_ptr;
\r
1215 info(p) = cur_align;
\r
1216 llink(p) = preamble;
\r
1217 rlink(p) = cur_span;
\r
1218 mem[p + 2].cint = cur_loop;
\r
1219 mem[p + 3].cint = align_state;
\r
1220 info(p + 4) = cur_head;
\r
1221 link(p + 4) = cur_tail;
\r
1223 cur_head = get_avail();
\r
1226 void pop_alignment (void)
\r
1230 free_avail(cur_head);
\r
1232 cur_tail = link(p + 4);
\r
1233 cur_head = info(p + 4);
\r
1234 align_state = mem[p + 3].cint;
\r
1235 cur_loop = mem[p + 2].cint;
\r
1236 cur_span = rlink(p);
\r
1237 preamble = llink(p);
\r
1238 cur_align = info(p);
\r
1239 align_ptr = link(p);
\r
1240 free_node(p, align_stack_node_size);
\r
1243 void get_preamble_token (void)
\r
1248 while ((cur_chr == span_code) && (cur_cmd == tab_mark))
\r
1252 if (cur_cmd > max_command)
\r
1259 if (cur_cmd == endv)
\r
1261 fatal_error("(interwoven alignment preambles are not allowed)");
\r
1265 if ((cur_cmd == assign_glue) && (cur_chr == glue_base + tab_skip_code))
\r
1267 scan_optional_equals();
\r
1268 scan_glue(glue_val);
\r
1270 if (global_defs > 0)
\r
1271 geq_define(glue_base + tab_skip_code, glue_ref, cur_val);
\r
1273 eq_define(glue_base + tab_skip_code, glue_ref, cur_val);
\r
1279 void init_align (void)
\r
1281 pointer save_cs_ptr;
\r
1284 save_cs_ptr = cur_cs;
\r
1286 align_state = -1000000L;
\r
1288 if ((mode == mmode) && ((tail != head) || (incompleat_noad != 0)))
\r
1290 print_err("Improper ");
\r
1291 print_esc("halign");
\r
1292 prints(" inside $$'s");
\r
1293 help3("Displays can use special alignments (like \\eqalignno)",
\r
1294 "only if nothing but the alignment itself is between $$'s.",
\r
1295 "So I've deleted the formulas that preceded this alignment.");
\r
1302 if (mode == mmode)
\r
1305 prev_depth = nest[nest_ptr - 2].aux_field.cint;
\r
1307 else if (mode > 0)
\r
1308 mode = - (integer) mode;
\r
1310 scan_spec(align_group, false);
\r
1312 cur_align = align_head;
\r
1314 scanner_status = aligning;
\r
1315 warning_index = save_cs_ptr;
\r
1316 align_state = -1000000L;
\r
1320 link(cur_align) = new_param_glue(tab_skip_code);
\r
1321 cur_align = link(cur_align);
\r
1323 if (cur_cmd == car_ret)
\r
1331 get_preamble_token();
\r
1333 if (cur_cmd == mac_param)
\r
1336 if ((cur_cmd <= car_ret) && (cur_cmd >= tab_mark) && (align_state == -1000000L))
\r
1337 if ((p == hold_head) && (cur_loop == 0) && (cur_cmd == tab_mark))
\r
1338 cur_loop = cur_align;
\r
1341 print_err("Missing # inserted in alignment preamble");
\r
1342 help3("There should be exactly one # between &'s, when an",
\r
1343 "\\halign or \\valign is being set up. In this case you had",
\r
1344 "none, so I've put one in; maybe that will work.");
\r
1348 else if ((cur_cmd != spacer) || (p != hold_head))
\r
1350 link(p) = get_avail();
\r
1352 info(p) = cur_tok;
\r
1357 link(cur_align) = new_null_box();
\r
1358 cur_align = link(cur_align);
\r
1359 info(cur_align) = end_span;
\r
1360 width(cur_align) = null_flag;
\r
1361 u_part(cur_align) = link(hold_head);
\r
1368 get_preamble_token();
\r
1370 if ((cur_cmd <= car_ret) && (cur_cmd >= tab_mark) && (align_state == -1000000L))
\r
1373 if (cur_cmd == mac_param)
\r
1375 print_err("Only one # is allowed per tab");
\r
1376 help3("There should be exactly one # between &'s, when an",
\r
1377 "\\halign or \\valign is being set up. In this case you had",
\r
1378 "more than one, so I'm ignoring all but the first.");
\r
1383 link(p) = get_avail();
\r
1385 info(p) = cur_tok;
\r
1389 link(p) = get_avail();
\r
1391 info(p) = end_template_token;
\r
1392 v_part(cur_align) = link(hold_head);
\r
1396 scanner_status = 0;
\r
1397 new_save_level(align_group);
\r
1399 if (every_cr != 0)
\r
1400 begin_token_list(every_cr, every_cr_text);
\r
1405 void init_span (pointer p)
\r
1409 if (mode == -hmode)
\r
1410 space_factor = 1000;
\r
1413 prev_depth = ignore_depth;
\r
1414 normal_paragraph();
\r
1420 void init_row (void)
\r
1424 mode = (-hmode - vmode) - mode;
\r
1426 if (mode == -hmode)
\r
1431 tail_append(new_glue(glue_ptr(preamble)));
\r
1432 subtype(tail) = tab_skip_code + 1;
\r
1433 cur_align = link(preamble);
\r
1434 cur_tail = cur_head;
\r
1435 init_span(cur_align);
\r
1438 void init_col (void)
\r
1440 extra_info(cur_align) = cur_cmd;
\r
1442 if (cur_cmd == omit)
\r
1447 begin_token_list(u_part(cur_align), u_template);
\r
1451 void fin_row (void)
\r
1455 if (mode == -hmode)
\r
1457 p = hpack(link(head), 0, 1);
\r
1459 append_to_vlist(p);
\r
1461 if (cur_head != cur_tail)
\r
1463 link(tail) = link(cur_head);
\r
1469 p = vpackage(link(head), 0, 1, max_dimen);
\r
1473 space_factor = 1000;
\r
1476 type(p) = unset_node;
\r
1477 glue_stretch(p) = 0;
\r
1479 if (every_cr != 0)
\r
1480 begin_token_list(every_cr, every_cr_text);
\r
1485 void fin_align (void)
\r
1487 pointer p, q, r, s, u, v;
\r
1492 memory_word aux_save;
\r
1494 if (cur_group != align_group)
\r
1496 confusion("align1");
\r
1502 if (cur_group != align_group)
\r
1504 confusion("align0");
\r
1510 if (nest[nest_ptr - 1].mode_field == mmode)
\r
1511 o = display_indent;
\r
1515 q = link(preamble);
\r
1519 flush_list(u_part(q));
\r
1520 flush_list(v_part(q));
\r
1521 p = link(link(q));
\r
1523 if (width(q) == null_flag)
\r
1529 if (s != zero_glue)
\r
1531 add_glue_ref(zero_glue);
\r
1532 delete_glue_ref(s);
\r
1533 glue_ptr(c) = zero_glue;
\r
1537 if (info(q) != end_span)
\r
1539 t = width(q) + width(glue_ptr(link(q)));
\r
1543 n = min_quarterword + 1;
\r
1547 width(r) = width(r) - t;
\r
1550 while (link(r) > n)
\r
1553 n = link(info(s)) + 1;
\r
1558 info(r) = info(s);
\r
1565 if (width(r) > width(info(s)))
\r
1566 width(info(s)) = width(r);
\r
1568 free_node(r, span_node_size);
\r
1573 while (!(r == end_span));
\r
1576 type(q) = unset_node;
\r
1577 span_count(q) = min_quarterword;
\r
1580 glue_order(q) = normal;
\r
1581 glue_sign(q) = normal;
\r
1582 glue_stretch(q) = 0;
\r
1583 glue_shrink(q) = 0;
\r
1586 while (!(q == 0));
\r
1588 save_ptr = save_ptr - 2;
\r
1589 pack_begin_line = - (integer) mode_line;
\r
1591 if (mode == -vmode)
\r
1593 rule_save = overfull_rule;
\r
1594 overfull_rule = 0;
\r
1595 p = hpack(preamble, saved(1), saved(0));
\r
1596 overfull_rule = rule_save;
\r
1600 q = link(preamble);
\r
1604 height(q) = width(q);
\r
1606 q = link(link(q));
\r
1608 while (!(q == 0));
\r
1610 p = vpackage(preamble, saved(1), saved(0), max_dimen);
\r
1611 q = link(preamble);
\r
1615 width(q) = height(q);
\r
1617 q = link(link(q));
\r
1619 while (!(q == 0));
\r
1622 pack_begin_line = 0;
\r
1628 if (!is_char_node(q))
\r
1629 if (type(q) == unset_node)
\r
1631 if (mode == -vmode)
\r
1633 type(q) = hlist_node;
\r
1634 width(q) = width(p);
\r
1638 type(q) = vlist_node;
\r
1639 height(q) = height(p);
\r
1642 glue_order(q) = glue_order(p);
\r
1643 glue_sign(q) = glue_sign(p);
\r
1644 glue_set(q) = glue_set(p);
\r
1645 shift_amount(q) = o;
\r
1646 r = link(list_ptr(q));
\r
1647 s = link(list_ptr(p));
\r
1651 n = span_count(r);
\r
1656 while (n > min_quarterword)
\r
1661 link(u) = new_glue(v);
\r
1663 subtype(u) = tab_skip_code + 1;
\r
1666 if (glue_sign(p) == stretching)
\r
1668 if (stretch_order(v) == glue_order(p))
\r
1669 t = t + round(glue_set(p) * stretch(v));
\r
1671 else if (glue_sign(p) == shrinking)
\r
1673 if (shrink_order(v) == glue_order(p))
\r
1674 t = t - round(glue_set(p) * shrink(v));
\r
1678 link(u) = new_null_box();
\r
1682 if (mode == -vmode)
\r
1683 width(u) = width(s);
\r
1686 type(u) = vlist_node;
\r
1687 height(u) = width(s);
\r
1692 if (mode == -vmode)
\r
1694 height(r) = height(q);
\r
1695 depth(r) = depth(q);
\r
1697 if (t == width(r))
\r
1699 glue_sign(r) = normal;
\r
1700 glue_order(r) = normal;
\r
1701 glue_set(r) = 0.0;
\r
1703 else if (t > width(r))
\r
1705 glue_sign(r) = stretching;
\r
1707 if (glue_stretch(r) == 0)
\r
1708 glue_set(r) = 0.0;
\r
1710 glue_set(r) = (t - width(r)) / ((double) glue_stretch(r));
\r
1714 glue_order(r) = glue_sign(r);
\r
1715 glue_sign(r) = shrinking;
\r
1717 if (glue_shrink(r) == 0)
\r
1718 glue_set(r) = 0.0;
\r
1719 else if ((glue_order(r) == normal) && (width(r) - t > glue_shrink(r)))
\r
1720 glue_set(r) = 1.0;
\r
1722 glue_set(r) = (width(r) - t)/ ((double) glue_shrink(r));
\r
1726 type(r) = hlist_node;
\r
1730 width(r) = width(q);
\r
1732 if (t == height(r))
\r
1734 glue_sign(r) = normal;
\r
1735 glue_order(r) = normal;
\r
1736 glue_set(r) = 0.0;
\r
1738 else if (t > height(r))
\r
1740 glue_sign(r) = stretching;
\r
1742 if (glue_stretch(r) == 0)
\r
1743 glue_set(r) = 0.0;
\r
1745 glue_set(r) = (t - height(r)) / ((double) glue_stretch(r));
\r
1749 glue_order(r) = glue_sign(r);
\r
1750 glue_sign(r) = shrinking;
\r
1752 if (glue_shrink(r) == 0)
\r
1753 glue_set(r) = 0.0;
\r
1754 else if ((glue_order(r) == normal) && (height(r) - t > glue_shrink(r)))
\r
1755 glue_set(r) = 1.0;
\r
1757 glue_set(r) = (height(r) - t) / ((double) glue_shrink(r));
\r
1761 type(r) = vlist_node;
\r
1764 shift_amount(r) = 0;
\r
1766 if (u != hold_head)
\r
1768 link(u) = link(r);
\r
1769 link(r) = link(hold_head);
\r
1773 r = link(link(r));
\r
1774 s = link(link(s));
\r
1776 while (!(r == 0));
\r
1778 else if (type(q) == rule_node)
\r
1780 if (is_running(width(q)))
\r
1781 width(q) = width(p);
\r
1783 if (is_running(height(q)))
\r
1784 height(q) = height(p);
\r
1786 if (is_running(depth(q)))
\r
1787 depth(q) = depth(p);
\r
1793 q = hpack(q, 0, 1);
\r
1794 shift_amount(q) = o;
\r
1803 flush_node_list(p);
\r
1805 aux_save = cur_list.aux_field;
\r
1810 if (mode == mmode)
\r
1814 if (cur_cmd != math_shift)
\r
1816 print_err("Missing $$ inserted");
\r
1817 help2("Displays can use special alignments (like \\eqalignno)",
\r
1818 "only if nothing but the alignment itself is between $$'s.");
\r
1825 if (cur_cmd != math_shift)
\r
1827 print_err("Display math should end with $$");
\r
1828 help2("The `$' that I just saw supposedly matches a previous `$$'.",
\r
1829 "So I shall assume that you typed `$$' both times.");
\r
1835 tail_append(new_penalty(pre_display_penalty));
\r
1836 tail_append(new_param_glue(above_display_skip_code));
\r
1842 tail_append(new_penalty(post_display_penalty));
\r
1843 tail_append(new_param_glue(below_display_skip_code));
\r
1844 prev_depth = aux_save.cint;
\r
1845 resume_after_display();
\r
1849 cur_list.aux_field = aux_save;
\r
1855 if (mode == vmode)
\r
1860 boolean fin_col (void)
\r
1870 if (cur_align == 0)
\r
1872 confusion("endv");
\r
1876 q = link(cur_align);
\r
1880 confusion("endv");
\r
1884 if (align_state < 500000L)
\r
1886 fatal_error("(interwoven alignment preambles are not allowed)");
\r
1892 if ((p == 0) && (extra_info(cur_align) < cr_code))
\r
1893 if (cur_loop != 0)
\r
1895 link(q) = new_null_box();
\r
1897 info(p) = end_span;
\r
1898 width(p) = null_flag;
\r
1899 cur_loop = link(cur_loop);
\r
1901 r = u_part(cur_loop);
\r
1905 link(q) = get_avail();
\r
1907 info(q) = info(r);
\r
1912 u_part(p) = link(hold_head);
\r
1914 r = v_part(cur_loop);
\r
1918 link(q) = get_avail();
\r
1920 info(q) = info(r);
\r
1925 v_part(p) = link(hold_head);
\r
1926 cur_loop = link(cur_loop);
\r
1927 link(p) = new_glue(glue_ptr(cur_loop));
\r
1931 print_err("Extra alignment tab has been changed to ");
\r
1933 help3("You have given more \\span or & marks than there were",
\r
1934 "in the preamble to the \\halign or \\valign now in progress.",
\r
1935 "So I'll assume that you meant to type \\cr instead.");
\r
1936 extra_info(cur_align) = cr_code;
\r
1940 if (extra_info(cur_align) != span_code)
\r
1943 new_save_level(align_group);
\r
1946 if (mode == -hmode)
\r
1948 adjust_tail = cur_tail;
\r
1949 u = hpack(link(head), 0, 1);
\r
1951 cur_tail = adjust_tail;
\r
1956 u = vpackage(link(head), 0, 1, 0);
\r
1960 n = min_quarterword;
\r
1962 if (cur_span != cur_align)
\r
1969 q = link(link(q));
\r
1971 while (!(q == cur_align));
\r
1973 if (n > max_quarterword)
\r
1975 confusion("256 spans");
\r
1981 while (link(info(q)) < n)
\r
1984 if (link(info(q)) > n)
\r
1986 s = get_node(span_node_size);
\r
1987 info(s) = info(q);
\r
1992 else if (width(info(q)) < w)
\r
1993 width(info(q)) = w;
\r
1995 else if (w > width(cur_align))
\r
1996 width(cur_align) = w;
\r
1998 type(u) = unset_node;
\r
1999 span_count(u) = n;
\r
2001 if (total_stretch[filll] != 0)
\r
2003 else if (total_stretch[fill] != 0)
\r
2005 else if (total_stretch[fil] != 0)
\r
2010 glue_order(u) = o;
\r
2011 glue_stretch(u) = total_stretch[o];
\r
2013 if (total_shrink[filll] != 0)
\r
2015 else if (total_shrink[fill] != 0)
\r
2017 else if (total_shrink[fil] != 0)
\r
2023 glue_shrink(u) = total_shrink[o];
\r
2029 tail_append(new_glue(glue_ptr(link(cur_align))));
\r
2030 subtype(tail) = tab_skip_code + 1;
\r
2032 if (extra_info(cur_align) >= cr_code)
\r
2040 align_state = 1000000L;
\r
2046 while (!(cur_cmd != spacer));
\r
2054 scaled make_op (pointer q)
\r
2057 pointer p, v, x, y, z;
\r
2060 scaled shift_up, shift_down;
\r
2062 if ((subtype(q) == normal) && (cur_style < text_style))
\r
2063 subtype(q) = limits;
\r
2065 if (math_type(nucleus(q)) == math_char)
\r
2067 fetch(nucleus(q));
\r
2069 if ((cur_style < text_style) && (char_tag(cur_i) == list_tag))
\r
2071 c = rem_byte(cur_i);
\r
2072 i = char_info(cur_f, c);
\r
2074 if (char_exists(i))
\r
2078 character(nucleus(q)) = c;
\r
2082 delta = char_italic(cur_f, cur_i);
\r
2083 x = clean_box(nucleus(q), cur_style);
\r
2085 if ((math_type(subscr(q)) != 0) && (subtype(q) != limits))
\r
2086 width(x) = width(x) - delta;
\r
2088 shift_amount(x) = half(height(x) - depth(x)) - axis_height(cur_size);
\r
2089 math_type(nucleus(q)) = sub_box;
\r
2090 info(nucleus(q)) = x;
\r
2095 if (subtype(q) == limits)
\r
2097 x = clean_box(supscr(q), sup_style(cur_style));
\r
2098 y = clean_box(nucleus(q), cur_style);
\r
2099 z = clean_box(subscr(q), sub_style(cur_style));
\r
2100 v = new_null_box();
\r
2101 type(v) = vlist_node;
\r
2102 width(v) = width(y);
\r
2104 if (width(x) > width(v))
\r
2105 width(v) = width(x);
\r
2107 if (width(z) > width(v))
\r
2108 width(v) = width(z);
\r
2110 x = rebox(x, width(v));
\r
2111 y = rebox(y, width(v));
\r
2112 z = rebox(z, width(v));
\r
2113 shift_amount(x) = half(delta);
\r
2114 shift_amount(z) = - (integer) shift_amount(x);
\r
2115 height(v) = height(y);
\r
2116 depth(v) = depth(y);
\r
2118 if (math_type(supscr(q)) == 0)
\r
2120 free_node(x, box_node_size);
\r
2125 shift_up = big_op_spacing3 - depth(x);
\r
2127 if (shift_up < big_op_spacing1)
\r
2128 shift_up = big_op_spacing1;
\r
2130 p = new_kern(shift_up);
\r
2133 p = new_kern(big_op_spacing5);
\r
2136 height(v) = height(v) + big_op_spacing5 + height(x) + depth(x) + shift_up;
\r
2139 if (math_type(subscr(q)) == 0)
\r
2140 free_node(z, box_node_size);
\r
2143 shift_down = big_op_spacing4 - height(z);
\r
2145 if (shift_down < big_op_spacing2)
\r
2146 shift_down = big_op_spacing2;
\r
2148 p = new_kern(shift_down);
\r
2151 p = new_kern(big_op_spacing5);
\r
2153 depth(v) = depth(v) + big_op_spacing5 + height(z) + depth(z) + shift_down;
\r
2162 void make_scripts (pointer q, scaled delta)
\r
2164 pointer p, x, y, z;
\r
2165 scaled shift_up, shift_down, clr;
\r
2170 if (is_char_node(p))
\r
2177 z = hpack(p, 0, 1);
\r
2179 if (cur_style < script_style)
\r
2182 t = script_script_size;
\r
2184 shift_up = height(z) - sup_drop(t);
\r
2185 shift_down = depth(z) + sub_drop(t);
\r
2186 free_node(z, box_node_size);
\r
2189 if (math_type(supscr(q)) == 0)
\r
2191 x = clean_box(subscr(q), sub_style(cur_style));
\r
2192 width(x) = width(x) + script_space;
\r
2194 if (shift_down < sub1(cur_size))
\r
2195 shift_down = sub1(cur_size);
\r
2197 clr = height(x) -(abs(math_x_height(cur_size) * 4) / 5);
\r
2199 if (shift_down < clr)
\r
2202 shift_amount(x) = shift_down;
\r
2207 x = clean_box(supscr(q), sup_style(cur_style));
\r
2208 width(x) = width(x) + script_space;
\r
2210 if (odd(cur_style))
\r
2211 clr = sup3(cur_size);
\r
2212 else if (cur_style < text_style)
\r
2213 clr = sup1(cur_size);
\r
2215 clr = sup2(cur_size);
\r
2217 if (shift_up < clr)
\r
2220 clr = depth(x) +(abs(math_x_height(cur_size)) / 4);
\r
2222 if (shift_up < clr)
\r
2226 if (math_type(subscr(q)) == 0)
\r
2227 shift_amount(x) = - (integer) shift_up;
\r
2230 y = clean_box(subscr(q), sub_style(cur_style));
\r
2231 width(y) = width(y) + script_space;
\r
2233 if (shift_down < sub2(cur_size))
\r
2234 shift_down = sub2(cur_size);
\r
2236 clr = 4 * default_rule_thickness - ((shift_up - depth(x)) - (height(y) - shift_down));
\r
2240 shift_down = shift_down + clr;
\r
2242 clr = (abs(math_x_height(cur_size) * 4) / 5) - (shift_up - depth(x));
\r
2246 shift_up = shift_up + clr;
\r
2247 shift_down = shift_down - clr;
\r
2251 shift_amount(x) = delta;
\r
2252 p = new_kern((shift_up - depth(x)) - (height(y) - shift_down));
\r
2255 x = vpackage(x, 0, 1, max_dimen);
\r
2256 shift_amount(x) = shift_down;
\r
2260 if (new_hlist(q) == 0)
\r
2266 while (link(p) != 0)
\r