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
22 #include "yandytex.h"
\r
25 void build_page (void)
\r
31 /* unsigned char n; */
\r
35 if ((link(contrib_head) == 0) || output_active)
\r
41 p = link(contrib_head);
\r
43 if (last_glue != max_halfword)
\r
44 delete_glue_ref(last_glue);
\r
49 if (type(p) == glue_node)
\r
51 last_glue = glue_ptr(p);
\r
52 add_glue_ref(last_glue);
\r
56 last_glue = max_halfword;
\r
58 if (type(p) == penalty_node)
\r
59 last_penalty = penalty(p);
\r
60 else if (type(p) == kern_node)
\r
61 last_kern = width(p);
\r
69 if (page_contents < box_there)
\r
71 if (page_contents == 0)
\r
72 freeze_page_specs(box_there);
\r
74 page_contents = box_there;
\r
76 q = new_skip_param(top_skip_code);
\r
78 if (width(temp_ptr) > height(p))
\r
79 width(temp_ptr) = width(temp_ptr) - height(p);
\r
81 width(temp_ptr) = 0;
\r
84 link(contrib_head) = q;
\r
89 page_total = page_total + page_depth + height(p);
\r
90 page_depth = depth(p);
\r
100 if (page_contents < box_there)
\r
102 else if (precedes_break(page_tail))
\r
105 goto update_heights;
\r
109 if (page_contents < box_there)
\r
111 else if (link(p) == 0)
\r
113 else if (type(link(p)) == glue_node)
\r
116 goto update_heights;
\r
120 if (page_contents < box_there)
\r
132 if (page_contents == 0)
\r
133 freeze_page_specs(inserts_only);
\r
138 while (n >= subtype(link(r)))
\r
143 if (subtype(r) != n)
\r
145 q = get_node(page_ins_node_size);
\r
150 type(r) = inserting;
\r
156 height(r) = height(box(n)) + depth(box(n));
\r
158 best_ins_ptr(r) = 0;
\r
161 if (count(n) == 1000)
\r
164 h = x_over_n(height(r), 1000) * count(n);
\r
166 page_goal = page_goal - h - width(q);
\r
167 page_so_far[2 + stretch_order(q)] = page_so_far[2 + stretch_order(q)] + stretch(q);
\r
168 page_shrink = page_shrink + shrink(q);
\r
170 if ((shrink_order(q) != normal) && (shrink(q) != 0))
\r
172 print_err("Infinite glue shrinkage inserted from ");
\r
175 help3("The correction glue for page breaking with insertions",
\r
176 "must have finite shrinkability. But you may proceed,",
\r
177 "since the offensive shrinkability has been made finite.");
\r
182 if (type(r) == split_up)
\r
183 insert_penalties = insert_penalties + float_cost(p);
\r
186 last_ins_ptr(r) = p;
\r
187 delta = page_goal - page_total - page_depth + page_shrink;
\r
189 if (count(n) == 1000)
\r
192 h = x_over_n(height(p), 1000) * count(n);
\r
194 if (((h <= 0) || (h <= delta)) && (height(p) + height(r) <= dimen(n)))
\r
196 page_goal = page_goal - h;
\r
197 height(r) = height(r) + height(p);
\r
205 w = page_goal - page_total - page_depth;
\r
207 if (count(n) != 1000)
\r
208 w = x_over_n(w, count(n)) * 1000;
\r
211 if (w > dimen(n) - height(r))
\r
212 w = dimen(n) - height(r);
\r
214 q = vert_break(ins_ptr(p), w, depth(p));
\r
215 height(r) = height(r) + best_height_plus_depth;
\r
218 if (tracing_pages > 0)
\r
220 begin_diagnostic();
\r
221 print_nl("% split");
\r
226 print_scaled(best_height_plus_depth);
\r
230 print_int(eject_penalty);
\r
231 else if (type(q) == penalty_node)
\r
232 print_int(penalty(q));
\r
236 end_diagnostic(false);
\r
239 if (count(n) != 1000)
\r
240 best_height_plus_depth = x_over_n(best_height_plus_depth, 1000) * count(n);
\r
242 page_goal = page_goal - best_height_plus_depth;
\r
243 type(r) = split_up;
\r
248 insert_penalties = insert_penalties + (eject_penalty);
\r
249 else if (type(q) == penalty_node)
\r
250 insert_penalties = insert_penalties + penalty(q);
\r
265 if (pi < inf_penalty)
\r
267 if (page_total < page_goal)
\r
268 if ((page_so_far[3] != 0) || (page_so_far[4] != 0) || (page_so_far[5] != 0))
\r
271 b = badness(page_goal - page_total, page_so_far[2]);
\r
272 else if (page_total - page_goal > page_shrink)
\r
275 b = badness(page_total - page_goal, page_shrink);
\r
278 if (pi <= eject_penalty)
\r
280 else if (b < inf_bad)
\r
281 c = b + pi + insert_penalties;
\r
287 if (insert_penalties >= 10000)
\r
291 if (tracing_pages > 0)
\r
293 begin_diagnostic();
\r
298 print_scaled(page_goal);
\r
301 if (b == awful_bad)
\r
310 if (c == awful_bad)
\r
315 if (c <= least_page_cost)
\r
318 end_diagnostic(false);
\r
322 if (c <= least_page_cost)
\r
324 best_page_break = p;
\r
325 best_size = page_goal;
\r
326 least_page_cost = c;
\r
327 r = link(page_ins_head);
\r
329 while (r != page_ins_head)
\r
331 best_ins_ptr(r) = last_ins_ptr(r);
\r
336 if ((c == awful_bad) || (pi <= eject_penalty))
\r
347 if ((type(p) < glue_node) || (type(p) > kern_node))
\r
351 if (type(p) == kern_node)
\r
356 page_so_far[2 + stretch_order(q)] = page_so_far[2 + stretch_order(q)] + stretch(q);
\r
357 page_shrink = page_shrink + shrink(q);
\r
359 if ((shrink_order(q) != normal) && (shrink(q) != 0))
\r
361 print_err("Infinite glue shrinkage found on current page");
\r
362 help4("The page about to be output contains some infinitely",
\r
363 "shrinkable glue, e.g., `\\vss' or `\\vskip 0pt minus 1fil'.",
\r
364 "Such glue doesn't belong there; but you can safely proceed,",
\r
365 "since the offensive shrinkability has been made finite.");
\r
368 shrink_order(r) = normal;
\r
369 delete_glue_ref(q);
\r
375 page_total = page_total + page_depth + width(q);
\r
379 if (page_depth > page_max_depth)
\r
381 page_total = page_total + page_depth - page_max_depth;
\r
382 page_depth = page_max_depth;
\r
385 link(page_tail) = p;
\r
387 link(contrib_head) = link(p);
\r
392 link(contrib_head) = link(p);
\r
394 flush_node_list(p);
\r
397 while (!(link(contrib_head) == 0));
\r
400 tail = contrib_head;
\r
402 nest[0].tail_field = contrib_head;
\r
405 void app_space (void)
\r
409 if ((space_factor >= 2000) && (xspace_skip != zero_glue))
\r
410 q = new_param_glue(xspace_skip_code);
\r
413 if (space_skip != zero_glue)
\r
414 main_p = space_skip;
\r
417 main_p = font_glue[cur_font];
\r
421 main_p = new_spec(zero_glue);
\r
422 main_k = param_base[cur_font] + space_code;
\r
423 width(main_p) = font_info[main_k].cint;
\r
424 stretch(main_p) = font_info[main_k + 1].cint;
\r
425 shrink(main_p) = font_info[main_k + 2].cint;
\r
426 font_glue[cur_font] = main_p;
\r
430 main_p = new_spec(main_p);
\r
432 if (space_factor >= 2000)
\r
433 width(main_p) = width(main_p) + extra_space(cur_font);
\r
435 stretch(main_p) = xn_over_d(stretch(main_p), space_factor, 1000);
\r
436 shrink(main_p) = xn_over_d(shrink(main_p), 1000, space_factor);
\r
437 q = new_glue(main_p);
\r
438 glue_ref_count(main_p) = 0;
\r
445 void insert_dollar_sign (void)
\r
448 cur_tok = math_shift_token + '$';
\r
449 print_err("Missing $ inserted");
\r
450 help2("I've inserted a begin-math/end-math symbol since I think",
\r
451 "you left one out. Proceed, with fingers crossed.");
\r
455 void you_cant (void)
\r
457 print_err("You can't use `");
\r
458 print_cmd_chr(cur_cmd, cur_chr);
\r
463 void report_illegal_case (void)
\r
466 help4("Sorry, but I'm not programmed to handle this case;",
\r
467 "I'll just pretend that you didn't ask for it.",
\r
468 "If you're in the wrong mode, you might be able to",
\r
469 "return to the right one by typing `I}' or `I$' or `I\\par'.");
\r
473 boolean privileged (void)
\r
479 report_illegal_case();
\r
484 boolean its_all_over (void)
\r
488 if ((page_head == page_tail) && (head == tail) && (dead_cycles == 0))
\r
494 tail_append(new_null_box());
\r
495 width(tail) = hsize;
\r
496 tail_append(new_glue(fill_glue));
\r
497 tail_append(new_penalty(-1073741824L));
\r
504 void append_glue (void)
\r
513 cur_val = fil_glue;
\r
517 cur_val = fill_glue;
\r
525 cur_val = fil_neg_glue;
\r
529 scan_glue(glue_val);
\r
537 tail_append(new_glue(cur_val));
\r
539 if (s >= skip_code)
\r
541 decr(glue_ref_count(cur_val));
\r
544 subtype(tail) = mu_glue;
\r
548 void append_kern (void)
\r
554 scan_dimen((s == mu_glue), false, false);
\r
555 tail_append(new_kern(cur_val));
\r
559 void off_save (void)
\r
563 if (cur_group == bottom_level)
\r
565 print_err("Extra ");
\r
566 print_cmd_chr(cur_cmd, cur_chr);
\r
567 help1("Things are pretty mixed up, but I think the worst is over.");
\r
574 link(temp_head) = p;
\r
575 print_err("Missing ");
\r
579 case semi_simple_group:
\r
581 info(p) = cs_token_flag + frozen_end_group;
\r
582 print_esc("endgroup");
\r
586 case math_shift_group:
\r
588 info(p) = math_shift_token + '$';
\r
593 case math_left_group:
\r
595 info(p) = cs_token_flag + frozen_right;
\r
596 link(p) = get_avail();
\r
598 info(p) = other_token + '.';
\r
599 print_esc("right.");
\r
605 info(p) = right_brace_token + '}';
\r
611 prints(" inserted");
\r
612 ins_list(link(temp_head));
\r
613 help5("I've inserted something that you may have forgotten.",
\r
614 "(See the <inserted text> above.)",
\r
615 "With luck, this will get me unwedged. But if you",
\r
616 "really didn't forget anything, try typing `2' now; then",
\r
617 "my insertion and my current dilemma will both disappear.");
\r
622 void extra_right_brace (void)
\r
624 print_err("Extra }, or forgotten ");
\r
628 case semi_simple_group:
\r
629 print_esc("endgroup");
\r
632 case math_shift_group:
\r
636 case math_left_group:
\r
637 print_esc("right");
\r
641 help5("I've deleted a group-closing symbol because it seems to be",
\r
642 "spurious, as in `$x}$'. But perhaps the } is legitimate and",
\r
643 "you forgot something else, as in `\\hbox{$x}'. In such cases",
\r
644 "the way to recover is to insert both the forgotten and the",
\r
645 "deleted material, e.g., by typing `I$}'.");
\r
650 void normal_paragraph (void)
\r
652 if (looseness != 0)
\r
653 eq_word_define(int_base + looseness_code, 0);
\r
655 if (hang_indent != 0)
\r
656 eq_word_define(dimen_base + hang_indent_code, 0);
\r
658 if (hang_after != 1)
\r
659 eq_word_define(int_base + hang_after_code, 1);
\r
661 if (par_shape_ptr != 0)
\r
662 eq_define(par_shape_loc, shape_ref, 0);
\r
665 void box_end (integer box_context)
\r
669 if (box_context < box_flag)
\r
673 shift_amount(cur_box) = box_context;
\r
675 if (abs(mode) == vmode)
\r
677 append_to_vlist(cur_box);
\r
679 if (adjust_tail != 0)
\r
681 if (adjust_head != adjust_tail)
\r
683 link(tail) = link(adjust_head);
\r
684 tail = adjust_tail;
\r
695 if (abs(mode) == hmode)
\r
696 space_factor = 1000;
\r
700 math_type(nucleus(p)) = sub_box;
\r
701 info(nucleus(p)) = cur_box;
\r
705 link(tail) = cur_box;
\r
710 else if (box_context < ship_out_flag)
\r
711 if (box_context < (box_flag + 256))
\r
712 eq_define((box_base - box_flag) + box_context, box_ref, cur_box);
\r
714 geq_define((box_base - box_flag - 256) + box_context, box_ref, cur_box);
\r
715 else if (cur_box != 0)
\r
716 if (box_context > ship_out_flag)
\r
722 while (!((cur_cmd != spacer) && (cur_cmd != relax)));
\r
724 if (((cur_cmd == hskip) && (abs(mode) != vmode)) || ((cur_cmd == vskip) && (abs(mode) == vmode)))
\r
727 subtype(tail) = box_context - (leader_flag - a_leaders);
\r
728 leader_ptr(tail) = cur_box;
\r
732 print_err("Leaders not followed by proper glue");
\r
733 help3("You should say `\\leaders <box or rule><hskip or vskip>'.",
\r
734 "I found the <box or rule>, but there's no suitable",
\r
735 "<hskip or vskip>, so I'm ignoring these leaders.");
\r
737 flush_node_list(cur_box);
\r
744 void begin_box (integer box_context)
\r
755 scan_eight_bit_int();
\r
756 cur_box = box(cur_val);
\r
763 scan_eight_bit_int();
\r
764 cur_box = copy_node_list(box(cur_val));
\r
768 case last_box_code:
\r
772 if (abs(mode) == mmode)
\r
775 help1("Sorry; this \\lastbox will be void.");
\r
778 else if ((mode == vmode) && (head == cur_list.tail_field))
\r
781 help2("Sorry...I usually can't take things from the current page.",
\r
782 "This \\lastbox will therefore be void.");
\r
787 if (!is_char_node(tail))
\r
788 if ((type(tail) == hlist_node) || (type(tail) == vlist_node))
\r
796 if (!is_char_node(q))
\r
797 if (type(q) == disc_node)
\r
799 for (m = 1; m <= replace_count(q); m++)
\r
808 while (!(q == tail));
\r
811 shift_amount(cur_box) = 0;
\r
822 scan_eight_bit_int();
\r
825 if (!scan_keyword("to"))
\r
827 print_err("Missing `to' inserted");
\r
828 help2("I'm working on `\\vsplit<box number> to <dimen>';",
\r
829 "will look for the <dimen> next.");
\r
833 scan_dimen(false, false, false);
\r
834 cur_box = vsplit(n, cur_val);
\r
840 k = cur_chr - vtop_code;
\r
841 saved(0) = box_context;
\r
844 if ((box_context < box_flag) && (abs(mode) == vmode))
\r
845 scan_spec(adjust_hbox_group, true);
\r
847 scan_spec(hbox_group, true);
\r
851 scan_spec(vbox_group, true);
\r
854 scan_spec(vtop_group, true);
\r
858 normal_paragraph();
\r
862 mode = - (integer) k;
\r
866 prev_depth = ignore_depth;
\r
868 if (every_vbox != 0)
\r
869 begin_token_list(every_vbox, every_vbox_text);
\r
873 space_factor = 1000;
\r
875 if (every_hbox != 0)
\r
876 begin_token_list(every_hbox, every_vbox_text);
\r
884 box_end(box_context);
\r
887 void scan_box_(integer box_context)
\r
893 while (!((cur_cmd != spacer) && (cur_cmd != relax)));
\r
895 if (cur_cmd == make_box)
\r
897 begin_box(box_context);
\r
899 else if ((box_context >= leader_flag) && ((cur_cmd == hrule) || (cur_cmd == vrule)))
\r
901 cur_box = scan_rule_spec();
\r
902 box_end(box_context);
\r
906 print_err("A <box> was supposed to be here");
\r
907 help3("I was expecting to see \\hbox or \\vbox or \\copy or \\box or",
\r
908 "something like that. So you might find something missing in",
\r
909 "your output. But keep trying; you can fix this later.");
\r
914 small_number norm_min (integer h)
\r
924 void new_graf (boolean indented)
\r
928 if ((mode == vmode) || (head != tail))
\r
929 tail_append(new_param_glue(par_skip_code));
\r
933 space_factor = 1000;
\r
936 prev_graf = (norm_min(left_hyphen_min) * 64 + norm_min(right_hyphen_min)) * 65536L + cur_lang;
\r
940 tail = new_null_box();
\r
942 width(tail) = par_indent;
\r
945 if (every_par != 0)
\r
946 begin_token_list(every_par, every_par_text);
\r
952 void indent_in_hmode (void)
\r
958 p = new_null_box();
\r
959 width(p) = par_indent;
\r
961 if (abs(mode) == hmode)
\r
962 space_factor = 1000;
\r
966 math_type(nucleus(q)) = sub_box;
\r
967 info(nucleus(q)) = p;
\r
975 void head_for_vmode (void)
\r
979 if (cur_cmd != hrule)
\r
983 print_err("You can't use `");
\r
984 print_esc("hrule");
\r
985 prints("' here except with leaders");
\r
986 help2("To put a horizontal rule in an hbox or an alignment,",
\r
987 "you should use \\leaders or \\hrulefill (see The TeXbook).");
\r
994 cur_tok = par_token;
\r
1000 void end_graf (void)
\r
1002 if (mode == hmode)
\r
1007 line_break(widow_penalty);
\r
1009 normal_paragraph();
\r
1014 void begin_insert_or_adjust (void)
\r
1016 if (cur_cmd == vadjust)
\r
1020 scan_eight_bit_int();
\r
1022 if (cur_val == 255)
\r
1024 print_err("You can't ");
\r
1025 print_esc("insert");
\r
1027 help1("I'm changing to \\insert0; box 255 is special.");
\r
1033 saved(0) = cur_val;
\r
1035 new_save_level(insert_group);
\r
1036 scan_left_brace();
\r
1037 normal_paragraph();
\r
1040 prev_depth = ignore_depth;
\r
1043 void make_mark (void)
\r
1047 p = scan_toks(false, true);
\r
1048 p = get_node(small_node_size);
\r
1049 type(p) = mark_node;
\r
1051 mark_ptr(p) = def_ref;
\r
1056 void append_penalty (void)
\r
1059 tail_append(new_penalty(cur_val));
\r
1061 if (mode == vmode)
\r
1065 void delete_last (void)
\r
1070 if ((mode == vmode) && (tail == head))
\r
1072 if ((cur_chr != glue_node) || (last_glue != max_halfword))
\r
1075 help2("Sorry...I usually can't take things from the current page.",
\r
1076 "Try `I\\vskip-\\lastskip' instead.");
\r
1078 if (cur_chr == kern_node)
\r
1079 help_line[0] = "Try `I\\kern-\\last_kern' instead.";
\r
1080 else if (cur_chr != glue_node)
\r
1081 help_line[0] = "Perhaps you can make the output routine do it.";
\r
1087 if (!is_char_node(tail))
\r
1088 if (type(tail) == cur_chr)
\r
1096 if (!is_char_node(q))
\r
1097 if (type(q) == disc_node)
\r
1099 for (m = 1; m <= replace_count(q); m++)
\r
1108 while (!(q == tail));
\r
1111 flush_node_list(tail);
\r
1117 void unpackage (void)
\r
1123 scan_eight_bit_int();
\r
1129 if ((abs(mode) == mmode) || ((abs(mode) == vmode) && (type(p) != vlist_node)) ||
\r
1130 ((abs(mode) == hmode) && (type(p) != hlist_node)))
\r
1132 print_err("Incompatible list can't be unboxed");
\r
1133 help3("Sorry, Pandora. (You sneaky devil.)",
\r
1134 "I refuse to unbox an \\hbox in vertical mode or vice versa.",
\r
1135 "And I can't open any boxes in math mode.");
\r
1140 if (c == copy_code)
\r
1141 link(tail) = copy_node_list(list_ptr(p));
\r
1144 link(tail) = list_ptr(p);
\r
1146 free_node(p, box_node_size);
\r
1149 while (link(tail) != 0)
\r
1150 tail = link(tail);
\r
1153 void append_italic_correction (void)
\r
1156 internal_font_number f;
\r
1160 if (is_char_node(tail))
\r
1162 else if (type(tail) == ligature_node)
\r
1168 tail_append(new_kern(char_italic(f, char_info(f, character(p)))));
\r
1169 subtype(tail) = explicit;
\r
1173 void append_discretionary (void)
\r
1177 tail_append(new_disc());
\r
1181 c = hyphen_char[cur_font];
\r
1185 pre_break(tail) = new_character(cur_font, c);
\r
1191 new_save_level(disc_group);
\r
1192 scan_left_brace();
\r
1195 space_factor = 1000;
\r
1199 void build_discretionary (void)
\r
1211 if (!is_char_node(p))
\r
1212 if (type(p) > rule_node)
\r
1213 if (type(p) != kern_node)
\r
1214 if (type(p) != ligature_node)
\r
1216 print_err("Improper discretionary list");
\r
1217 help1("Discretionary lists must contain only boxes and kerns.");
\r
1219 begin_diagnostic();
\r
1220 print_nl("The following discretionary sublist has been deleted:");
\r
1222 end_diagnostic(true);
\r
1223 flush_node_list(p);
\r
1237 switch (saved(-1))
\r
1240 pre_break(tail) = p;
\r
1244 post_break(tail) = p;
\r
1249 if ((n > 0) && (abs(mode) == mmode))
\r
1251 print_err("Illegal math ");
\r
1252 print_esc("discretionary");
\r
1253 help2("Sorry: The third part of a discretionary break must be",
\r
1254 "empty, in math formulas. I had to delete your third part.");
\r
1255 flush_node_list(p);
\r
1262 if (n <= max_quarterword)
\r
1263 replace_count(tail) = n;
\r
1266 print_err("Discretionary list is too long");
\r
1267 help2("Wow---I never thought anybody would tweak me here.",
\r
1268 "You can't seriously need such a huge discretionary list?");
\r
1282 new_save_level(disc_group);
\r
1283 scan_left_brace();
\r
1286 space_factor = 1000;
\r
1289 void make_accent (void)
\r
1293 internal_font_number f;
\r
1294 scaled a, h, x, w, delta;
\r
1299 p = new_character(f, cur_val);
\r
1304 s = slant(f) / ((double) 65536.0);
\r
1305 a = char_width(f, char_info(f, character(p)));
\r
1310 if ((cur_cmd == letter) || (cur_cmd == other_char) || (cur_cmd == char_given))
\r
1311 q = new_character(f, cur_chr);
\r
1312 else if (cur_cmd == char_num)
\r
1315 q = new_character(f, cur_val);
\r
1322 t = slant(f) / ((double) 65536.0);
\r
1323 i = char_info(f, character(q));
\r
1324 w = char_width(f, i);
\r
1325 h = char_height(f, height_depth(i));
\r
1329 p = hpack(p, 0, 1);
\r
1330 shift_amount(p) = x - h;
\r
1333 delta = round((w - a) / ((double) 2.0) + h * t - x * s);
\r
1334 r = new_kern(delta);
\r
1335 subtype(r) = acc_kern;
\r
1338 tail = new_kern(- (integer) a - delta);
\r
1339 subtype(tail) = acc_kern;
\r
1346 space_factor = 1000;
\r
1350 void align_error (void)
\r
1352 if (abs(align_state) > 2)
\r
1354 print_err("Misplaced ");
\r
1355 print_cmd_chr(cur_cmd, cur_chr);
\r
1357 if (cur_tok == tab_token + '&')
\r
1359 help6("I can't figure out why you would want to use a tab mark",
\r
1360 "here. If you just want an ampersand, the remedy is",
\r
1361 "simple: Just type `I\\&' now. But if some right brace",
\r
1362 "up above has ended a previous alignment prematurely,",
\r
1363 "you're probably due for more error messages, and you",
\r
1364 "might try typing `S' now just to see what is salvageable.");
\r
1368 help5("I can't figure out why you would want to use a tab mark",
\r
1369 "or \\cr or \\span just now. If something like a right brace",
\r
1370 "up above has ended a previous alignment prematurely,",
\r
1371 "you're probably due for more error messages, and you",
\r
1372 "might try typing `S' now just to see what is salvageable.");
\r
1381 if (align_state < 0)
\r
1383 print_err("Missing { inserted");
\r
1384 incr(align_state);
\r
1385 cur_tok = left_brace_token + '{';
\r
1389 print_err("Missing } inserted");
\r
1390 decr(align_state);
\r
1391 cur_tok = right_brace_token + '}';
\r
1394 help3("I've put in what seems to be necessary to fix",
\r
1395 "the current column of the current alignment.",
\r
1396 "Try to go on, since this might almost work.");
\r
1401 void noalign_error (void)
\r
1403 print_err("Misplaced ");
\r
1404 print_esc("noalign");
\r
1405 help2("I expect to see \\noalign only after the \\cr of",
\r
1406 "an alignment. Proceed, and I'll ignore this case.");
\r
1410 void omit_error (void)
\r
1412 print_err("Misplaced ");
\r
1413 print_esc("omit");
\r
1414 help2("I expect to see \\omit only after tab marks or the \\cr of",
\r
1415 "an alignment. Proceed, and I'll ignore this case.");
\r
1419 void do_endv (void)
\r
1421 base_ptr = input_ptr;
\r
1422 input_stack[base_ptr] = cur_input;
\r
1424 while ((input_stack[base_ptr].index_field != v_template) &&
\r
1425 (input_stack[base_ptr].loc_field == 0) &&
\r
1426 (input_stack[base_ptr].state_field == token_list))
\r
1429 if ((input_stack[base_ptr].index_field != v_template) ||
\r
1430 (input_stack[base_ptr].loc_field != 0) ||
\r
1431 (input_stack[base_ptr].state_field != token_list))
\r
1432 fatal_error("(interwoven alignment preambles are not allowed)");
\r
1434 if (cur_group == align_group)
\r
1445 void cs_error (void)
\r
1447 print_err("Extra ");
\r
1448 print_esc("endcsname");
\r
1449 help1("I'm ignoring this, since I wasn't doing a \\csname.");
\r
1453 void push_math (group_code c)
\r
1457 incompleat_noad = 0;
\r
1458 new_save_level(c);
\r
1461 void init_math (void)
\r
1468 internal_font_number f;
\r
1475 if ((cur_cmd == math_shift) && (mode > 0))
\r
1484 line_break(display_widow_penalty);
\r
1485 v = shift_amount(just_box) + 2 * quad(cur_font);
\r
1487 p = list_ptr(just_box);
\r
1492 if (is_char_node(p))
\r
1495 d = char_width(f, char_info(f, character(p)));
\r
1510 case ligature_node:
\r
1512 mem[lig_trick] = mem[lig_char(p)];
\r
1513 link(lig_trick) = link(p);
\r
1529 if (glue_sign(just_box) == stretching)
\r
1531 if ((glue_order(just_box) == stretch_order(q)) && (stretch(q) != 0))
\r
1534 else if (glue_sign(just_box) == shrinking)
\r
1536 if ((glue_order(just_box) == shrink_order(q)) && (shrink(q) != 0))
\r
1540 if (subtype(p) >= a_leaders)
\r
1545 case whatsit_node:
\r
1554 if (v < max_dimen)
\r
1560 if (v < max_dimen)
\r
1577 if (par_shape_ptr == 0)
\r
1578 if ((hang_indent != 0) && (((hang_after >= 0) &&
\r
1579 (prev_graf + 2 > hang_after)) || (prev_graf + 1 < - (integer) hang_after)))
\r
1581 l = hsize - abs(hang_indent);
\r
1583 if (hang_indent > 0)
\r
1595 n = info(par_shape_ptr);
\r
1597 if (prev_graf + 2 >= n)
\r
1598 p = par_shape_ptr + 2 * n;
\r
1600 p = par_shape_ptr + 2 * (prev_graf + 2);
\r
1602 s = mem[p - 1].cint;
\r
1606 push_math(math_shift_group);
\r
1608 eq_word_define(int_base + cur_fam_code, -1);
\r
1609 eq_word_define(dimen_base + pre_display_size_code, w);
\r
1610 eq_word_define(dimen_base + display_width_code, l);
\r
1611 eq_word_define(dimen_base + display_indent_code, s);
\r
1613 if (every_display != 0)
\r
1614 begin_token_list(every_display, every_display_text);
\r
1616 if (nest_ptr == 1)
\r
1626 push_math(math_shift_group);
\r
1627 eq_word_define(int_base + cur_fam_code, -1);
\r
1629 if (every_math != 0)
\r
1630 begin_token_list(every_math, every_math_text);
\r
1635 void start_eq_no (void)
\r
1637 saved(0) = cur_chr;
\r
1641 push_math(math_shift_group);
\r
1642 eq_word_define(int_base + cur_fam_code, -1);
\r
1644 if (every_math != 0)
\r
1645 begin_token_list(every_math, every_math_text);
\r
1649 void scan_math (pointer p)
\r
1658 while (!((cur_cmd != spacer) && (cur_cmd != relax)));
\r
1667 c = math_code(cur_chr);
\r
1672 cur_cs = cur_chr + active_base;
\r
1673 cur_cmd = eq_type(cur_cs);
\r
1674 cur_chr = equiv(cur_cs);
\r
1687 cur_chr = cur_val;
\r
1688 cur_cmd = char_given;
\r
1693 case math_char_num:
\r
1695 scan_fifteen_bit_int();
\r
1706 scan_twenty_seven_bit_int();
\r
1707 c = cur_val / 4096;
\r
1714 scan_left_brace();
\r
1717 push_math(math_group);
\r
1723 math_type(p) = math_char;
\r
1724 character(p) = c % 256;
\r
1726 if ((c >= var_code) && ((cur_fam >= 0) && (cur_fam < 16)))
\r
1729 fam(p) = (c / 256) % 16;
\r
1732 void set_math_char_(integer c)
\r
1738 cur_cs = cur_chr + active_base;
\r
1739 cur_cmd = eq_type(cur_cs);
\r
1740 cur_chr = equiv(cur_cs);
\r
1747 math_type(nucleus(p)) = math_char;
\r
1748 character(nucleus(p)) = c % 256;
\r
1749 fam(nucleus(p)) = (c / 256) % 16;
\r
1751 if (c >= var_code)
\r
1753 if (((cur_fam >= 0) && (cur_fam < 16)))
\r
1754 fam(nucleus(p)) = cur_fam;
\r
1756 type(p) = ord_noad;
\r
1759 type(p) = ord_noad + (c / 4096);
\r
1766 void math_limit_switch (void)
\r
1769 if (type(tail) == op_noad)
\r
1771 subtype(tail) = cur_chr;
\r
1775 print_err("Limit controls must follow a math operator");
\r
1776 help1("I'm ignoring this misplaced \\limits or \\nolimits command.");
\r
1780 void scan_delimiter_(pointer p, boolean r)
\r
1783 scan_twenty_seven_bit_int();
\r
1790 while (!((cur_cmd != spacer) && (cur_cmd != relax)));
\r
1796 cur_val = del_code(cur_chr);
\r
1800 scan_twenty_seven_bit_int();
\r
1811 print_err("Missing delimiter (. inserted)");
\r
1812 help6("I was expecting to see something like `(' or `\\{' or",
\r
1813 "`\\}' here. If you typed, e.g., `{' instead of `\\{', you",
\r
1814 "should probably delete the `{' by typing `1' now, so that",
\r
1815 "braces don't get unbalanced. Otherwise just proceed.",
\r
1816 "Acceptable delimiters are characters whose \\delcode is",
\r
1817 "nonnegative, or you can use `\\delimiter <delimiter code>'.");
\r
1822 small_fam(p) = (cur_val / 1048576L) % 16;
\r
1823 small_char(p) = (cur_val / 4096) % 256;
\r
1824 large_fam(p) = (cur_val / 256) % 16;
\r
1825 large_char(p) = cur_val % 256;
\r
1828 void math_radical (void)
\r
1830 tail_append(get_node(radical_noad_size));
\r
1831 type(tail) = radical_noad;
\r
1832 subtype(tail) = normal;
\r
1833 mem[nucleus(tail)].hh = empty_field;
\r
1834 mem[subscr(tail)].hh = empty_field;
\r
1835 mem[supscr(tail)].hh = empty_field;
\r
1836 scan_delimiter(left_delimiter(tail), true);
\r
1837 scan_math(nucleus(tail));
\r
1840 void math_ac (void)
\r
1842 if (cur_cmd == accent)
\r
1844 print_err("Please use ");
\r
1845 print_esc("mathaccent");
\r
1846 prints(" for accents in math mode");
\r
1847 help2("I'm changing \\accent to \\mathaccent here; wish me luck.",
\r
1848 "(Accents are not the same in formulas as they are in text.)");
\r
1852 tail_append(get_node(accent_noad_size));
\r
1853 type(tail) = accent_noad;
\r
1854 subtype(tail) = normal;
\r
1855 mem[nucleus(tail)].hh = empty_field;
\r
1856 mem[subscr(tail)].hh = empty_field;
\r
1857 mem[supscr(tail)].hh = empty_field;
\r
1858 math_type(accent_chr(tail)) = math_char;
\r
1859 scan_fifteen_bit_int();
\r
1860 character(accent_chr(tail)) = cur_val % 256;
\r
1862 if ((cur_val >= var_code) && ((cur_fam >= 0) && (cur_fam < 16)))
\r
1863 fam(accent_chr(tail)) = cur_fam;
\r
1865 fam(accent_chr(tail)) = (cur_val / 256) % 16;
\r
1867 scan_math(nucleus(tail));
\r
1870 void append_choices (void)
\r
1872 tail_append(new_choice());
\r
1875 push_math(math_choice_group);
\r
1876 scan_left_brace();
\r
1879 pointer fin_mlist (pointer p)
\r
1883 if (incompleat_noad != 0)
\r
1885 math_type(denominator(incompleat_noad)) = sub_mlist;
\r
1886 info(denominator(incompleat_noad)) = link(head);
\r
1889 q = incompleat_noad;
\r
1892 q = info(numerator(incompleat_noad));
\r
1894 if (type(q) != left_noad)
\r
1896 confusion("right");
\r
1900 info(numerator(incompleat_noad)) = link(q);
\r
1901 link(q) = incompleat_noad;
\r
1902 link(incompleat_noad) = p;
\r
1916 void build_choices (void)
\r
1923 switch (saved(-1))
\r
1926 display_mlist(tail) = p;
\r
1930 text_mlist(tail) = p;
\r
1934 script_mlist(tail) = p;
\r
1939 script_script_mlist(tail) = p;
\r
1947 push_math(math_choice_group);
\r
1948 scan_left_brace();
\r
1951 void sub_sup (void)
\r
1953 /* small_number t; */
\r
1961 if (script_allowed(tail))
\r
1963 p = supscr(tail) + cur_cmd - sup_mark;
\r
1967 if ((p == 0) || (t != 0))
\r
1969 tail_append(new_noad());
\r
1970 p = supscr(tail) + cur_cmd - sup_mark;
\r
1974 if (cur_cmd == sup_mark)
\r
1976 print_err("Double superscript");
\r
1977 help1("I treat `x^1^2' essentially like `x^1{}^2'.");
\r
1981 print_err("Double subscript");
\r
1982 help1("I treat `x_1_2' essentially like `x_1{}_2'.");
\r
1992 void package (small_number c)
\r
1998 d = box_max_depth;
\r
2000 save_ptr = save_ptr - 3;
\r
2002 if (mode == -hmode)
\r
2003 cur_box = hpack(link(head), saved(2), saved(1));
\r
2006 cur_box = vpackage(link(head), saved(2), saved(1), d);
\r
2008 if (c == vtop_code)
\r
2011 p = list_ptr(cur_box);
\r
2014 if (type(p) <= rule_node)
\r
2017 depth(cur_box) = depth(cur_box) - h + height(cur_box);
\r
2018 height(cur_box) = h;
\r
2023 box_end(saved(0));
\r