1 /* Copyright 2014 Clerk Ma
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2 of the License, or
6 (at your option) any later version.
8 This program is distributed in the hope that it will be useful, but
9 WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 void build_page (void)
29 /* unsigned char n; */
30 unsigned int n; /* 95/Jan/7 */
33 if ((link(contrib_head) == 0) || output_active)
39 p = link(contrib_head);
41 if (last_glue != max_halfword)
42 delete_glue_ref(last_glue);
47 if (type(p) == glue_node)
49 last_glue = glue_ptr(p);
50 add_glue_ref(last_glue);
54 last_glue = max_halfword;
56 if (type(p) == penalty_node)
57 last_penalty = penalty(p);
58 else if (type(p) == kern_node)
67 if (page_contents < box_there)
69 if (page_contents == 0)
70 freeze_page_specs(box_there);
72 page_contents = box_there;
74 q = new_skip_param(top_skip_code);
76 if (width(temp_ptr) > height(p))
77 width(temp_ptr) = width(temp_ptr) - height(p);
82 link(contrib_head) = q;
87 page_total = page_total + page_depth + height(p);
88 page_depth = depth(p);
98 if (page_contents < box_there)
100 else if (precedes_break(page_tail))
107 if (page_contents < box_there)
109 else if (link(p) == 0)
111 else if (type(link(p)) == glue_node)
118 if (page_contents < box_there)
130 if (page_contents == 0)
131 freeze_page_specs(inserts_only);
136 while (n >= subtype(link(r)))
143 q = get_node(page_ins_node_size);
154 height(r) = height(box(n)) + depth(box(n));
159 if (count(n) == 1000)
162 h = x_over_n(height(r), 1000) * count(n);
164 page_goal = page_goal - h - width(q);
165 page_so_far[2 + stretch_order(q)] = page_so_far[2 + stretch_order(q)] + stretch(q);
166 page_shrink = page_shrink + shrink(q);
168 if ((shrink_order(q) != normal) && (shrink(q) != 0))
170 print_err("Infinite glue shrinkage inserted from ");
173 help3("The correction glue for page breaking with insertions",
174 "must have finite shrinkability. But you may proceed,",
175 "since the offensive shrinkability has been made finite.");
180 if (type(r) == split_up)
181 insert_penalties = insert_penalties + float_cost(p);
185 delta = page_goal - page_total - page_depth + page_shrink;
187 if (count(n) == 1000)
190 h = x_over_n(height(p), 1000) * count(n);
192 if (((h <= 0) || (h <= delta)) && (height(p) + height(r) <= dimen(n)))
194 page_goal = page_goal - h;
195 height(r) = height(r) + height(p);
200 w = max_dimen; /* 2^30 - 1 */
203 w = page_goal - page_total - page_depth;
205 if (count(n) != 1000)
206 w = x_over_n(w, count(n)) * 1000;
209 if (w > dimen(n) - height(r))
210 w = dimen(n) - height(r);
212 q = vert_break(ins_ptr(p), w, depth(p));
213 height(r) = height(r) + best_height_plus_depth;
216 if (tracing_pages > 0)
224 print_scaled(best_height_plus_depth);
228 print_int(eject_penalty);
229 else if (type(q) == penalty_node)
230 print_int(penalty(q));
234 end_diagnostic(false);
237 if (count(n) != 1000)
238 best_height_plus_depth = x_over_n(best_height_plus_depth, 1000) * count(n);
240 page_goal = page_goal - best_height_plus_depth;
246 insert_penalties = insert_penalties + (eject_penalty);
247 else if (type(q) == penalty_node)
248 insert_penalties = insert_penalties + penalty(q);
263 if (pi < inf_penalty)
265 if (page_total < page_goal)
266 if ((page_so_far[3] != 0) || (page_so_far[4] != 0) || (page_so_far[5] != 0))
269 b = badness(page_goal - page_total, page_so_far[2]);
270 else if (page_total - page_goal > page_shrink)
273 b = badness(page_total - page_goal, page_shrink);
276 if (pi <= eject_penalty)
278 else if (b < inf_bad)
279 c = b + pi + insert_penalties;
285 if (insert_penalties >= 10000)
286 c = awful_bad; /* 2^30 - 1 */
289 if (tracing_pages > 0)
296 print_scaled(page_goal);
299 if (b == awful_bad) /* 2^30 - 1 */
308 if (c == awful_bad) /* 2^30 - 1 */
313 if (c <= least_page_cost)
316 end_diagnostic(false);
320 if (c <= least_page_cost)
323 best_size = page_goal;
325 r = link(page_ins_head);
327 while (r != page_ins_head)
329 best_ins_ptr(r) = last_ins_ptr(r);
334 if ((c == awful_bad) || (pi <= eject_penalty)) /* 2^30 - 1 */
345 if ((type(p) < glue_node) || (type(p) > kern_node))
349 if (type(p) == kern_node)
354 page_so_far[2 + stretch_order(q)] = page_so_far[2 + stretch_order(q)] + stretch(q);
355 page_shrink = page_shrink + shrink(q);
357 if ((shrink_order(q) != normal) && (shrink(q) != 0))
359 print_err("Infinite glue shrinkage found on current page");
360 help4("The page about to be output contains some infinitely",
361 "shrinkable glue, e.g., `\\vss' or `\\vskip 0pt minus 1fil'.",
362 "Such glue doesn't belong there; but you can safely proceed,",
363 "since the offensive shrinkability has been made finite.");
366 shrink_order(r) = normal;
373 page_total = page_total + page_depth + width(q);
376 if (page_depth > page_max_depth)
378 page_total = page_total + page_depth - page_max_depth;
379 page_depth = page_max_depth;
384 link(contrib_head) = link(p);
388 link(contrib_head) = link(p);
393 while (!(link(contrib_head) == 0));
398 nest[0].tail_field = contrib_head;
401 void app_space (void)
405 if ((space_factor >= 2000) && (xspace_skip != zero_glue))
406 q = new_param_glue(xspace_skip_code);
409 if (space_skip != zero_glue)
413 main_p = font_glue[cur_font];
417 main_p = new_spec(zero_glue);
418 main_k = param_base[cur_font] + space_code;
419 width(main_p) = font_info[main_k].cint;
420 stretch(main_p) = font_info[main_k + 1].cint;
421 shrink(main_p) = font_info[main_k + 2].cint;
422 font_glue[cur_font] = main_p;
426 main_p = new_spec(main_p);
428 if (space_factor >= 2000)
429 width(main_p) = width(main_p) + extra_space(cur_font);
431 stretch(main_p) = xn_over_d(stretch(main_p), space_factor, 1000);
432 shrink(main_p) = xn_over_d(shrink(main_p), 1000, space_factor);
433 q = new_glue(main_p);
434 glue_ref_count(main_p) = 0;
441 void insert_dollar_sign (void)
444 cur_tok = math_shift_token + '$';
445 print_err("Missing $ inserted");
446 help2("I've inserted a begin-math/end-math symbol since I think",
447 "you left one out. Proceed, with fingers crossed.");
453 print_err("You can't use `");
454 print_cmd_chr(cur_cmd, cur_chr);
459 void report_illegal_case (void)
462 help4("Sorry, but I'm not programmed to handle this case;",
463 "I'll just pretend that you didn't ask for it.",
464 "If you're in the wrong mode, you might be able to",
465 "return to the right one by typing `I}' or `I$' or `I\\par'.");
469 boolean privileged (void)
475 report_illegal_case();
480 boolean its_all_over (void)
484 if ((page_head == page_tail) && (head == tail) && (dead_cycles == 0))
490 tail_append(new_null_box());
492 tail_append(new_glue(fill_glue));
493 tail_append(new_penalty(-1073741824L));
500 void append_glue (void)
521 cur_val = fil_neg_glue;
533 tail_append(new_glue(cur_val));
537 decr(glue_ref_count(cur_val));
540 subtype(tail) = mu_glue;
544 void append_kern (void)
550 scan_dimen((s == mu_glue), false, false);
551 tail_append(new_kern(cur_val));
559 if (cur_group == bottom_level)
562 print_cmd_chr(cur_cmd, cur_chr);
563 help1("Things are pretty mixed up, but I think the worst is over.");
571 print_err("Missing ");
575 case semi_simple_group:
577 info(p) = cs_token_flag + frozen_end_group;
578 print_esc("endgroup");
582 case math_shift_group:
584 info(p) = math_shift_token + '$';
589 case math_left_group:
591 info(p) = cs_token_flag + frozen_right;
592 link(p) = get_avail();
594 info(p) = other_token + '.';
601 info(p) = right_brace_token + '}';
608 ins_list(link(temp_head));
609 help5("I've inserted something that you may have forgotten.",
610 "(See the <inserted text> above.)",
611 "With luck, this will get me unwedged. But if you",
612 "really didn't forget anything, try typing `2' now; then",
613 "my insertion and my current dilemma will both disappear.");
618 void extra_right_brace (void)
620 print_err("Extra }, or forgotten ");
624 case semi_simple_group:
625 print_esc("endgroup");
628 case math_shift_group:
632 case math_left_group:
637 help5("I've deleted a group-closing symbol because it seems to be",
638 "spurious, as in `$x}$'. But perhaps the } is legitimate and",
639 "you forgot something else, as in `\\hbox{$x}'. In such cases",
640 "the way to recover is to insert both the forgotten and the",
641 "deleted material, e.g., by typing `I$}'.");
646 void normal_paragraph (void)
649 eq_word_define(int_base + looseness_code, 0);
651 if (hang_indent != 0)
652 eq_word_define(dimen_base + hang_indent_code, 0);
655 eq_word_define(int_base + hang_after_code, 1);
657 if (par_shape_ptr != 0)
658 eq_define(par_shape_loc, shape_ref, 0);
661 void box_end_(integer box_context)
665 if (box_context < box_flag)
669 shift_amount(cur_box) = box_context;
671 if (abs(mode) == vmode)
673 append_to_vlist(cur_box);
675 if (adjust_tail != 0)
677 if (adjust_head != adjust_tail)
679 link(tail) = link(adjust_head);
691 if (abs(mode) == hmode)
696 math_type(nucleus(p)) = sub_box;
697 info(nucleus(p)) = cur_box;
701 link(tail) = cur_box;
706 else if (box_context < ship_out_flag)
707 if (box_context < (box_flag + 256))
708 eq_define((box_base - box_flag) + box_context, box_ref, cur_box);
710 geq_define((box_base - box_flag - 256) + box_context, box_ref, cur_box);
711 else if (cur_box != 0)
712 if (box_context > ship_out_flag)
718 while (!((cur_cmd != spacer) && (cur_cmd != relax)));
720 if (((cur_cmd == hskip) && (abs(mode) != vmode)) || ((cur_cmd == vskip) && (abs(mode) == vmode)))
723 subtype(tail) = box_context - (leader_flag - a_leaders);
724 leader_ptr(tail) = cur_box;
728 print_err("Leaders not followed by proper glue");
729 help3("You should say `\\leaders <box or rule><hskip or vskip>'.",
730 "I found the <box or rule>, but there's no suitable",
731 "<hskip or vskip>, so I'm ignoring these leaders.");
733 flush_node_list(cur_box);
740 void begin_box_(integer box_context)
751 scan_eight_bit_int();
752 cur_box = box(cur_val);
759 scan_eight_bit_int();
760 cur_box = copy_node_list(box(cur_val));
768 if (abs(mode) == mmode)
771 help1("Sorry; this \\lastbox will be void.");
774 else if ((mode == vmode) && (head == cur_list.tail_field))
777 help2("Sorry...I usually can't take things from the current page.",
778 "This \\lastbox will therefore be void.");
783 if (!is_char_node(tail))
784 if ((type(tail) == hlist_node) || (type(tail) == vlist_node))
792 if (!is_char_node(q))
793 if (type(q) == disc_node)
795 for (m = 1; m <= replace_count(q); m++)
804 while (!(q == tail));
807 shift_amount(cur_box) = 0;
819 scan_eight_bit_int();
822 if (!scan_keyword("to"))
824 print_err("Missing `to' inserted");
825 help2("I'm working on `\\vsplit<box number> to <dimen>';",
826 "will look for the <dimen> next.");
830 scan_dimen(false, false, false);
831 cur_box = vsplit(n, cur_val);
837 k = cur_chr - vtop_code;
838 saved(0) = box_context;
841 if ((box_context < box_flag) && (abs(mode) == vmode))
842 scan_spec(adjust_hbox_group, true);
844 scan_spec(hbox_group, true);
848 scan_spec(vbox_group, true);
851 scan_spec(vtop_group, true);
859 mode = - (integer) k;
863 prev_depth = ignore_depth;
866 begin_token_list(every_vbox, every_vbox_text);
873 begin_token_list(every_hbox, every_vbox_text);
880 box_end(box_context);
883 void scan_box_(integer box_context)
889 while (!((cur_cmd != spacer) && (cur_cmd != relax)));
891 if (cur_cmd == make_box)
893 begin_box(box_context);
895 else if ((box_context >= leader_flag) && ((cur_cmd == hrule) || (cur_cmd == vrule)))
897 cur_box = scan_rule_spec();
898 box_end(box_context);
902 print_err("A <box> was supposed to be here");
903 help3("I was expecting to see \\hbox or \\vbox or \\copy or \\box or",
904 "something like that. So you might find something missing in",
905 "your output. But keep trying; you can fix this later.");
909 /****************************************************************************/
910 void package_ (small_number);
911 /****************************************************************************/
913 small_number norm_min_ (integer h)
923 void new_graf_(boolean indented)
927 if ((mode == vmode) || (head != tail))
928 tail_append(new_param_glue(par_skip_code));
935 prev_graf =(norm_min(left_hyphen_min) * 64 + norm_min(right_hyphen_min)) * 65536L + cur_lang;
939 tail = new_null_box();
941 width(tail) = par_indent;
945 begin_token_list(every_par, every_par_text);
951 void indent_in_hmode (void)
958 width(p) = par_indent;
960 if (abs(mode) == hmode)
965 math_type(nucleus(q)) = sub_box;
966 info(nucleus(q)) = p;
974 void head_for_vmode (void)
978 if (cur_cmd != hrule)
982 print_err("You can't use `");
984 prints("' here except with leaders");
985 help2("To put a horizontal rule in an hbox or an alignment,",
986 "you should use \\leaders or \\hrulefill (see The TeXbook).");
1006 line_break(widow_penalty);
1013 void begin_insert_or_adjust (void)
1015 if (cur_cmd == vadjust)
1019 scan_eight_bit_int();
1023 print_err("You can't ");
1024 print_esc("insert");
1026 help1("I'm changing to \\insert0; box 255 is special.");
1034 new_save_level(insert_group);
1039 prev_depth = ignore_depth;
1042 void make_mark (void)
1046 p = scan_toks(false, true);
1047 p = get_node(small_node_size);
1048 type(p) = mark_node;
1050 mark_ptr(p) = def_ref;
1055 void append_penalty (void)
1058 tail_append(new_penalty(cur_val));
1064 void delete_last (void)
1069 if ((mode == vmode) && (tail == head))
1071 if ((cur_chr != glue_node) || (last_glue != max_halfword))
1074 help2("Sorry...I usually can't take things from the current page.",
1075 "Try `I\\vskip-\\lastskip' instead.");
1077 if (cur_chr == kern_node)
1078 help_line[0] = "Try `I\\kern-\\last_kern' instead.";
1079 else if (cur_chr != glue_node)
1080 help_line[0] = "Perhaps you can make the output routine do it.";
1086 if (!is_char_node(tail))
1087 if (type(tail) == cur_chr)
1095 if (!is_char_node(q))
1096 if (type(q) == disc_node)
1098 for (m = 1; m <= replace_count(q); m++)
1107 while (!(q == tail));
1110 flush_node_list(tail);
1116 void unpackage (void)
1122 scan_eight_bit_int();
1128 if ((abs(mode) == mmode) || ((abs(mode) == vmode) && (type(p) != vlist_node)) ||
1129 ((abs(mode) == hmode) && (type(p) != hlist_node)))
1131 print_err("Incompatible list can't be unboxed");
1132 help3("Sorry, Pandora. (You sneaky devil.)",
1133 "I refuse to unbox an \\hbox in vertical mode or vice versa.",
1134 "And I can't open any boxes in math mode.");
1140 link(tail) = copy_node_list(list_ptr(p));
1143 link(tail) = list_ptr(p);
1145 free_node(p, box_node_size);
1148 while (link(tail) != 0)
1152 void append_italic_correction (void)
1155 internal_font_number f;
1159 if (is_char_node(tail))
1161 else if (type(tail) == ligature_node)
1167 tail_append(new_kern(char_italic(f, char_info(f, character(p)))));
1168 subtype(tail) = explicit;
1172 void append_discretionary (void)
1176 tail_append(new_disc());
1180 c = hyphen_char[cur_font];
1184 pre_break(tail) = new_character(cur_font, c);
1190 new_save_level(disc_group);
1194 space_factor = 1000;
1198 void build_discretionary (void)
1210 if (!is_char_node(p))
1211 if (type(p) > rule_node)
1212 if (type(p) != kern_node)
1213 if (type(p) != ligature_node)
1215 print_err("Improper discretionary list");
1216 help1("Discretionary lists must contain only boxes and kerns.");
1219 print_nl("The following discretionary sublist has been deleted:");
1221 end_diagnostic(true);
1239 pre_break(tail) = p;
1243 post_break(tail) = p;
1248 if ((n > 0) && (abs(mode) == mmode))
1250 print_err("Illegal math ");
1251 print_esc("discretionary");
1252 help2("Sorry: The third part of a discretionary break must be",
1253 "empty, in math formulas. I had to delete your third part.");
1261 if (n <= max_quarterword)
1262 replace_count(tail) = n;
1265 print_err("Discretionary list is too long");
1266 help2("Wow---I never thought anybody would tweak me here.",
1267 "You can't seriously need such a huge discretionary list?");
1281 new_save_level(disc_group);
1285 space_factor = 1000;
1288 void make_accent (void)
1292 internal_font_number f;
1293 scaled a, h, x, w, delta;
1298 p = new_character(f, cur_val);
1303 s = slant(f) / ((double) 65536.0);
1304 a = char_width(f, char_info(f, character(p)));
1309 if ((cur_cmd == letter) || (cur_cmd == other_char) || (cur_cmd == char_given))
1310 q = new_character(f, cur_chr);
1311 else if (cur_cmd == char_num)
1314 q = new_character(f, cur_val);
1321 t = slant(f) / ((double) 65536.0);
1322 i = char_info(f, character(q));
1323 w = char_width(f, i);
1324 h = char_height(f, height_depth(i));
1329 shift_amount(p) = x - h;
1332 delta = round((w - a) / ((double) 2.0) + h * t - x * s);
1333 r = new_kern(delta);
1334 subtype(r) = acc_kern;
1337 tail = new_kern(- (integer) a - delta);
1338 subtype(tail) = acc_kern;
1345 space_factor = 1000;
1349 void align_error (void)
1351 if (abs(align_state) > 2)
1353 print_err("Misplaced ");
1354 print_cmd_chr(cur_cmd, cur_chr);
1356 if (cur_tok == tab_token + '&')
1358 help6("I can't figure out why you would want to use a tab mark",
1359 "here. If you just want an ampersand, the remedy is",
1360 "simple: Just type `I\\&' now. But if some right brace",
1361 "up above has ended a previous alignment prematurely,",
1362 "you're probably due for more error messages, and you",
1363 "might try typing `S' now just to see what is salvageable.");
1367 help5("I can't figure out why you would want to use a tab mark",
1368 "or \\cr or \\span just now. If something like a right brace",
1369 "up above has ended a previous alignment prematurely,",
1370 "you're probably due for more error messages, and you",
1371 "might try typing `S' now just to see what is salvageable.");
1380 if (align_state < 0)
1382 print_err("Missing { inserted");
1384 cur_tok = left_brace_token + '{';
1388 print_err("Missing } inserted");
1390 cur_tok = right_brace_token + '}';
1393 help3("I've put in what seems to be necessary to fix",
1394 "the current column of the current alignment.",
1395 "Try to go on, since this might almost work.");
1400 void noalign_error (void)
1402 print_err("Misplaced ");
1403 print_esc("noalign");
1404 help2("I expect to see \\noalign only after the \\cr of",
1405 "an alignment. Proceed, and I'll ignore this case.");
1409 void omit_error (void)
1411 print_err("Misplaced ");
1413 help2("I expect to see \\omit only after tab marks or the \\cr of",
1414 "an alignment. Proceed, and I'll ignore this case.");
1420 base_ptr = input_ptr;
1421 input_stack[base_ptr] = cur_input;
1423 while ((input_stack[base_ptr].index_field != v_template) &&
1424 (input_stack[base_ptr].loc_field == 0) &&
1425 (input_stack[base_ptr].state_field == token_list))
1428 if ((input_stack[base_ptr].index_field != v_template) ||
1429 (input_stack[base_ptr].loc_field != 0) ||
1430 (input_stack[base_ptr].state_field != token_list))
1431 fatal_error("(interwoven alignment preambles are not allowed)");
1433 if (cur_group == align_group)
1444 void cs_error (void)
1446 print_err("Extra ");
1447 print_esc("endcsname");
1448 help1("I'm ignoring this, since I wasn't doing a \\csname.");
1452 void push_math_(group_code c)
1456 incompleat_noad = 0;
1460 void init_math (void)
1467 internal_font_number f;
1474 if ((cur_cmd == math_shift) && (mode > 0))
1479 w = -max_dimen; /* - (2^30 - 1) */
1483 line_break(display_widow_penalty);
1484 v = shift_amount(just_box) + 2 * quad(cur_font);
1485 w = -max_dimen; /* - (2^30 - 1) */
1486 p = list_ptr(just_box);
1491 if (is_char_node(p))
1494 d = char_width(f, char_info(f, character(p)));
1511 mem[lig_trick] = mem[lig_char(p)];
1512 link(lig_trick) = link(p);
1528 if (glue_sign(just_box) == stretching)
1530 if ((glue_order(just_box) == stretch_order(q)) && (stretch(q) != 0))
1531 v = max_dimen; /* - (2^30 - 1) */
1533 else if (glue_sign(just_box) == shrinking)
1535 if ((glue_order(just_box) == shrink_order(q)) && (shrink(q) != 0))
1536 v = max_dimen; /* - (2^30 - 1) */
1539 if (subtype(p) >= a_leaders)
1553 if (v < max_dimen) /* - (2^30 - 1) */
1558 if (v < max_dimen) /* - (2^30 - 1) */
1565 w = max_dimen; /* - (2^30 - 1) */
1574 if (par_shape_ptr == 0)
1575 if ((hang_indent != 0) && (((hang_after >= 0) &&
1576 (prev_graf + 2 > hang_after)) || (prev_graf + 1 < - (integer) hang_after)))
1578 l = hsize - abs(hang_indent);
1580 if (hang_indent > 0)
1592 n = info(par_shape_ptr);
1594 if (prev_graf + 2 >= n)
1595 p = par_shape_ptr + 2 * n;
1597 p = par_shape_ptr + 2 *(prev_graf + 2);
1599 s = mem[p - 1].cint;
1603 push_math(math_shift_group);
1605 eq_word_define(int_base + cur_fam_code, -1);
1606 eq_word_define(dimen_base + pre_display_size_code, w);
1607 eq_word_define(dimen_base + display_width_code, l);
1608 eq_word_define(dimen_base + display_indent_code, s);
1610 if (every_display != 0)
1611 begin_token_list(every_display, every_display_text);
1623 push_math(math_shift_group);
1624 eq_word_define(int_base + cur_fam_code, -1);
1626 if (every_math != 0)
1627 begin_token_list(every_math, every_math_text);
1632 void start_eq_no (void)
1638 push_math(math_shift_group);
1639 eq_word_define(int_base + cur_fam_code, -1);
1641 if (every_math != 0)
1642 begin_token_list(every_math, every_math_text);
1646 void scan_math_(pointer p)
1655 while (!((cur_cmd != spacer) && (cur_cmd != relax)));
1664 c = math_code(cur_chr);
1669 cur_cs = cur_chr + active_base;
1670 cur_cmd = eq_type(cur_cs);
1671 cur_chr = equiv(cur_cs);
1685 cur_cmd = char_given;
1692 scan_fifteen_bit_int();
1703 scan_twenty_seven_bit_int();
1714 push_math(math_group);
1720 math_type(p) = math_char;
1721 character(p) = c % 256;
1723 if ((c >= var_code) && ((cur_fam >= 0) && (cur_fam < 16)))
1726 fam(p) = (c / 256) % 16;
1729 void set_math_char_(integer c)
1735 cur_cs = cur_chr + active_base;
1736 cur_cmd = eq_type(cur_cs);
1737 cur_chr = equiv(cur_cs);
1744 math_type(nucleus(p)) = math_char;
1745 character(nucleus(p)) = c % 256;
1746 fam(nucleus(p)) = (c / 256) % 16;
1750 if (((cur_fam >= 0) && (cur_fam < 16)))
1751 fam(nucleus(p)) = cur_fam;
1756 type(p) = ord_noad + (c / 4096);
1763 void math_limit_switch (void)
1766 if (type(tail) == op_noad)
1768 subtype(tail) = cur_chr;
1772 print_err("Limit controls must follow a math operator");
1773 help1("I'm ignoring this misplaced \\limits or \\nolimits command.");
1777 void scan_delimiter_(pointer p, boolean r)
1781 scan_twenty_seven_bit_int();
1789 while (!((cur_cmd != spacer) && (cur_cmd != relax)));
1795 cur_val = del_code(cur_chr);
1799 scan_twenty_seven_bit_int();
1810 print_err("Missing delimiter (. inserted)");
1811 help6("I was expecting to see something like `(' or `\\{' or",
1812 "`\\}' here. If you typed, e.g., `{' instead of `\\{', you",
1813 "should probably delete the `{' by typing `1' now, so that",
1814 "braces don't get unbalanced. Otherwise just proceed.",
1815 "Acceptable delimiters are characters whose \\delcode is",
1816 "nonnegative, or you can use `\\delimiter <delimiter code>'.");
1821 small_fam(p) = (cur_val / 1048576L) % 16;
1822 small_char(p) = (cur_val / 4096) % 256;
1823 large_fam(p) = (cur_val / 256) % 16;
1824 large_char(p) = cur_val % 256;
1827 void math_radical (void)
1829 tail_append(get_node(radical_noad_size));
1830 type(tail) = radical_noad;
1831 subtype(tail) = normal;
1832 mem[nucleus(tail)].hh = empty_field;
1833 mem[subscr(tail)].hh = empty_field;
1834 mem[supscr(tail)].hh = empty_field;
1835 scan_delimiter(left_delimiter(tail), true);
1836 scan_math(nucleus(tail));
1841 if (cur_cmd == accent)
1843 print_err("Please use ");
1844 print_esc("mathaccent");
1845 prints(" for accents in math mode");
1846 help2("I'm changing \\accent to \\mathaccent here; wish me luck.",
1847 "(Accents are not the same in formulas as they are in text.)");
1851 tail_append(get_node(accent_noad_size));
1852 type(tail) = accent_noad;
1853 subtype(tail) = normal;
1854 mem[nucleus(tail)].hh = empty_field;
1855 mem[subscr(tail)].hh = empty_field;
1856 mem[supscr(tail)].hh = empty_field;
1857 math_type(accent_chr(tail)) = math_char;
1858 scan_fifteen_bit_int();
1859 character(accent_chr(tail)) = cur_val % 256;
1861 if ((cur_val >= var_code) && ((cur_fam >= 0) && (cur_fam < 16)))
1862 fam(accent_chr(tail)) = cur_fam;
1864 fam(accent_chr(tail)) = (cur_val / 256) % 16;
1866 scan_math(nucleus(tail));
1869 void append_choices (void)
1871 tail_append(new_choice());
1874 push_math(math_choice_group);
1878 halfword fin_mlist_(halfword p)
1882 if (incompleat_noad != 0)
1884 math_type(denominator(incompleat_noad)) = sub_mlist;
1885 info(denominator(incompleat_noad)) = link(head);
1888 q = incompleat_noad;
1891 q = info(numerator(incompleat_noad));
1893 if (type(q) != left_noad)
1899 info(numerator(incompleat_noad)) = link(q);
1900 link(q) = incompleat_noad;
1901 link(incompleat_noad) = p;
1915 void build_choices (void)
1925 display_mlist(tail) = p;
1929 text_mlist(tail) = p;
1933 script_mlist(tail) = p;
1938 script_script_mlist(tail) = p;
1946 push_math(math_choice_group);
1952 /* small_number t; */
1953 int t; /* 95/Jan/7 */
1960 if (script_allowed(tail))
1962 p = supscr(tail) + cur_cmd - sup_mark;
1966 if ((p == 0) || (t != 0))
1968 tail_append(new_noad());
1969 p = supscr(tail) + cur_cmd - sup_mark;
1973 if (cur_cmd == sup_mark)
1975 print_err("Double superscript");
1976 help1("I treat `x^1^2' essentially like `x^1{}^2'.");
1980 print_err("Double subscript");
1981 help1("I treat `x_1_2' essentially like `x_1{}_2'.");
1989 void package_(small_number c)
1997 save_ptr = save_ptr - 3;
2000 cur_box = hpack(link(head), saved(2), saved(1));
2003 cur_box = vpackage(link(head), saved(2), saved(1), d);
2008 p = list_ptr(cur_box);
2011 if (type(p) <= rule_node)
2014 depth(cur_box) = depth(cur_box) - h + height(cur_box);
2015 height(cur_box) = h;