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))
348 if (type(p) == kern_node)
353 page_so_far[2 + stretch_order(q)] = page_so_far[2 + stretch_order(q)] + stretch(q);
354 page_shrink = page_shrink + shrink(q);
356 if ((shrink_order(q) != normal) && (shrink(q) != 0))
358 print_err("Infinite glue shrinkage found on current page");
359 help4("The page about to be output contains some infinitely",
360 "shrinkable glue, e.g., `\\vss' or `\\vskip 0pt minus 1fil'.",
361 "Such glue doesn't belong there; but you can safely proceed,",
362 "since the offensive shrinkability has been made finite.");
365 shrink_order(r) = normal;
372 page_total = page_total + page_depth + width(q);
375 if (page_depth > page_max_depth)
377 page_total = page_total + page_depth - page_max_depth;
378 page_depth = page_max_depth;
383 link(contrib_head) = link(p);
387 link(contrib_head) = link(p);
392 while (!(link(contrib_head) == 0));
397 nest[0].tail_field = contrib_head;
400 void app_space (void)
404 if ((space_factor >= 2000) && (xspace_skip != zero_glue))
405 q = new_param_glue(xspace_skip_code);
408 if (space_skip != zero_glue)
412 main_p = font_glue[cur_font];
416 main_p = new_spec(zero_glue);
417 main_k = param_base[cur_font] + space_code;
418 width(main_p) = font_info[main_k].cint;
419 stretch(main_p) = font_info[main_k + 1].cint;
420 shrink(main_p) = font_info[main_k + 2].cint;
421 font_glue[cur_font] = main_p;
425 main_p = new_spec(main_p);
427 if (space_factor >= 2000)
428 width(main_p) = width(main_p) + extra_space(cur_font);
430 stretch(main_p) = xn_over_d(stretch(main_p), space_factor, 1000);
431 shrink(main_p) = xn_over_d(shrink(main_p), 1000, space_factor);
432 q = new_glue(main_p);
433 glue_ref_count(main_p) = 0;
440 void insert_dollar_sign (void)
443 cur_tok = math_shift_token + '$';
444 print_err("Missing $ inserted");
445 help2("I've inserted a begin-math/end-math symbol since I think",
446 "you left one out. Proceed, with fingers crossed.");
452 print_err("You can't use `");
453 print_cmd_chr(cur_cmd, cur_chr);
454 print_string("' in ");
458 void report_illegal_case (void)
461 help4("Sorry, but I'm not programmed to handle this case;",
462 "I'll just pretend that you didn't ask for it.",
463 "If you're in the wrong mode, you might be able to",
464 "return to the right one by typing `I}' or `I$' or `I\\par'.");
468 boolean privileged (void)
474 report_illegal_case();
479 boolean its_all_over (void)
483 if ((page_head == page_tail) && (head == tail) && (dead_cycles == 0))
489 tail_append(new_null_box());
491 tail_append(new_glue(fill_glue));
492 tail_append(new_penalty(-1073741824L));
499 void append_glue (void)
520 cur_val = fil_neg_glue;
532 tail_append(new_glue(cur_val));
536 decr(glue_ref_count(cur_val));
539 subtype(tail) = mu_glue;
543 void append_kern (void)
549 scan_dimen((s == mu_glue), false, false);
550 tail_append(new_kern(cur_val));
558 if (cur_group == bottom_level)
561 print_cmd_chr(cur_cmd, cur_chr);
562 help1("Things are pretty mixed up, but I think the worst is over.");
570 print_err("Missing ");
574 case semi_simple_group:
576 info(p) = cs_token_flag + frozen_end_group;
577 print_esc("endgroup");
581 case math_shift_group:
583 info(p) = math_shift_token + '$';
588 case math_left_group:
590 info(p) = cs_token_flag + frozen_right;
591 link(p) = get_avail();
593 info(p) = other_token + '.';
600 info(p) = right_brace_token + '}';
606 print_string(" inserted");
607 ins_list(link(temp_head));
608 help5("I've inserted something that you may have forgotten.",
609 "(See the <inserted text> above.)",
610 "With luck, this will get me unwedged. But if you",
611 "really didn't forget anything, try typing `2' now; then",
612 "my insertion and my current dilemma will both disappear.");
617 void extra_right_brace (void)
619 print_err("Extra }, or forgotten ");
623 case semi_simple_group:
624 print_esc("endgroup");
627 case math_shift_group:
631 case math_left_group:
636 help5("I've deleted a group-closing symbol because it seems to be",
637 "spurious, as in `$x}$'. But perhaps the } is legitimate and",
638 "you forgot something else, as in `\\hbox{$x}'. In such cases",
639 "the way to recover is to insert both the forgotten and the",
640 "deleted material, e.g., by typing `I$}'.");
645 void normal_paragraph (void)
648 eq_word_define(int_base + looseness_code, 0);
650 if (hang_indent != 0)
651 eq_word_define(dimen_base + hang_indent_code, 0);
654 eq_word_define(int_base + hang_after_code, 1);
656 if (par_shape_ptr != 0)
657 eq_define(par_shape_loc, shape_ref, 0);
660 void box_end_(integer box_context)
664 if (box_context < box_flag)
668 shift_amount(cur_box) = box_context;
670 if (abs(mode) == vmode)
672 append_to_vlist(cur_box);
674 if (adjust_tail != 0)
676 if (adjust_head != adjust_tail)
678 link(tail) = link(adjust_head);
690 if (abs(mode) == hmode)
695 math_type(nucleus(p)) = sub_box;
696 info(nucleus(p)) = cur_box;
700 link(tail) = cur_box;
705 else if (box_context < ship_out_flag)
706 if (box_context < (box_flag + 256))
707 eq_define((box_base - box_flag) + box_context, box_ref, cur_box);
709 geq_define((box_base - box_flag - 256) + box_context, box_ref, cur_box);
710 else if (cur_box != 0)
711 if (box_context > ship_out_flag)
717 while (!((cur_cmd != spacer) && (cur_cmd != relax)));
719 if (((cur_cmd == hskip) && (abs(mode) != vmode)) || ((cur_cmd == vskip) && (abs(mode) == vmode)))
722 subtype(tail) = box_context - (leader_flag - a_leaders);
723 leader_ptr(tail) = cur_box;
727 print_err("Leaders not followed by proper glue");
728 help3("You should say `\\leaders <box or rule><hskip or vskip>'.",
729 "I found the <box or rule>, but there's no suitable",
730 "<hskip or vskip>, so I'm ignoring these leaders.");
732 flush_node_list(cur_box);
739 void begin_box_(integer box_context)
750 scan_eight_bit_int();
751 cur_box = box(cur_val);
758 scan_eight_bit_int();
759 cur_box = copy_node_list(box(cur_val));
767 if (abs(mode) == mmode)
770 help1("Sorry; this \\lastbox will be void.");
773 else if ((mode == vmode) && (head == cur_list.tail_field))
776 help2("Sorry...I usually can't take things from the current page.",
777 "This \\lastbox will therefore be void.");
782 if (!is_char_node(tail))
783 if ((type(tail) == hlist_node) || (type(tail) == vlist_node))
791 if (!is_char_node(q))
792 if (type(q) == disc_node)
794 for (m = 1; m <= replace_count(q); m++)
803 while (!(q == tail));
806 shift_amount(cur_box) = 0;
818 scan_eight_bit_int();
821 if (!scan_keyword("to"))
823 print_err("Missing `to' inserted");
824 help2("I'm working on `\\vsplit<box number> to <dimen>';",
825 "will look for the <dimen> next.");
829 scan_dimen(false, false, false);
830 cur_box = vsplit(n, cur_val);
836 k = cur_chr - vtop_code;
837 saved(0) = box_context;
840 if ((box_context < box_flag) && (abs(mode) == vmode))
841 scan_spec(adjust_hbox_group, true);
843 scan_spec(hbox_group, true);
847 scan_spec(vbox_group, true);
850 scan_spec(vtop_group, true);
858 mode = - (integer) k;
862 prev_depth = ignore_depth;
865 begin_token_list(every_vbox, every_vbox_text);
872 begin_token_list(every_hbox, every_vbox_text);
879 box_end(box_context);
882 void scan_box_(integer box_context)
888 while (!((cur_cmd != spacer) && (cur_cmd != relax)));
890 if (cur_cmd == make_box)
892 begin_box(box_context);
894 else if ((box_context >= leader_flag) && ((cur_cmd == hrule) || (cur_cmd == vrule)))
896 cur_box = scan_rule_spec();
897 box_end(box_context);
901 print_err("A <box> was supposed to be here");
902 help3("I was expecting to see \\hbox or \\vbox or \\copy or \\box or",
903 "something like that. So you might find something missing in",
904 "your output. But keep trying; you can fix this later.");
908 /****************************************************************************/
909 void package_ (small_number);
910 /****************************************************************************/
912 small_number norm_min_ (integer h)
922 void new_graf_(boolean indented)
926 if ((mode == vmode) || (head != tail))
927 tail_append(new_param_glue(par_skip_code));
934 prev_graf =(norm_min(left_hyphen_min) * 64 + norm_min(right_hyphen_min)) * 65536L + cur_lang;
938 tail = new_null_box();
940 width(tail) = par_indent;
944 begin_token_list(every_par, every_par_text);
950 void indent_in_hmode (void)
957 width(p) = par_indent;
959 if (abs(mode) == hmode)
964 math_type(nucleus(q)) = sub_box;
965 info(nucleus(q)) = p;
973 void head_for_vmode (void)
977 if (cur_cmd != hrule)
981 print_err("You can't use `");
983 print_string("' here except with leaders");
984 help2("To put a horizontal rule in an hbox or an alignment,",
985 "you should use \\leaders or \\hrulefill (see The TeXbook).");
1005 line_break(widow_penalty);
1012 void begin_insert_or_adjust (void)
1014 if (cur_cmd == vadjust)
1018 scan_eight_bit_int();
1022 print_err("You can't ");
1023 print_esc("insert");
1025 help1("I'm changing to \\insert0; box 255 is special.");
1033 new_save_level(insert_group);
1038 prev_depth = ignore_depth;
1041 void make_mark (void)
1045 p = scan_toks(false, true);
1046 p = get_node(small_node_size);
1047 type(p) = mark_node;
1049 mark_ptr(p) = def_ref;
1054 void append_penalty (void)
1057 tail_append(new_penalty(cur_val));
1063 void delete_last (void)
1068 if ((mode == vmode) && (tail == head))
1070 if ((cur_chr != glue_node) || (last_glue != max_halfword))
1073 help2("Sorry...I usually can't take things from the current page.",
1074 "Try `I\\vskip-\\lastskip' instead.");
1076 if (cur_chr == kern_node)
1077 help_line[0] = "Try `I\\kern-\\last_kern' instead.";
1078 else if (cur_chr != glue_node)
1079 help_line[0] = "Perhaps you can make the output routine do it.";
1085 if (!is_char_node(tail))
1086 if (type(tail) == cur_chr)
1094 if (!is_char_node(q))
1095 if (type(q) == disc_node)
1097 for (m = 1; m <= replace_count(q); m++)
1106 while (!(q == tail));
1109 flush_node_list(tail);
1115 void unpackage (void)
1121 scan_eight_bit_int();
1127 if ((abs(mode) == mmode) || ((abs(mode) == vmode) && (type(p) != vlist_node)) ||
1128 ((abs(mode) == hmode) && (type(p) != hlist_node)))
1130 print_err("Incompatible list can't be unboxed");
1131 help3("Sorry, Pandora. (You sneaky devil.)",
1132 "I refuse to unbox an \\hbox in vertical mode or vice versa.",
1133 "And I can't open any boxes in math mode.");
1139 link(tail) = copy_node_list(list_ptr(p));
1142 link(tail) = list_ptr(p);
1144 free_node(p, box_node_size);
1147 while (link(tail) != 0)
1151 void append_italic_correction (void)
1154 internal_font_number f;
1158 if (is_char_node(tail))
1160 else if (type(tail) == ligature_node)
1166 tail_append(new_kern(char_italic(f, char_info(f, character(p)))));
1167 subtype(tail) = explicit;
1171 void append_discretionary (void)
1175 tail_append(new_disc());
1179 c = hyphen_char[cur_font];
1183 pre_break(tail) = new_character(cur_font, c);
1189 new_save_level(disc_group);
1193 space_factor = 1000;
1197 void build_discretionary (void)
1209 if (!is_char_node(p))
1210 if (type(p) > rule_node)
1211 if (type(p) != kern_node)
1212 if (type(p) != ligature_node)
1214 print_err("Improper discretionary list");
1215 help1("Discretionary lists must contain only boxes and kerns.");
1218 print_nl("The following discretionary sublist has been deleted:");
1220 end_diagnostic(true);
1238 pre_break(tail) = p;
1242 post_break(tail) = p;
1247 if ((n > 0) && (abs(mode) == mmode))
1249 print_err("Illegal math ");
1250 print_esc("discretionary");
1251 help2("Sorry: The third part of a discretionary break must be",
1252 "empty, in math formulas. I had to delete your third part.");
1260 if (n <= max_quarterword)
1261 replace_count(tail) = n;
1264 print_err("Discretionary list is too long");
1265 help2("Wow---I never thought anybody would tweak me here.",
1266 "You can't seriously need such a huge discretionary list?");
1280 new_save_level(disc_group);
1284 space_factor = 1000;
1287 void make_accent (void)
1291 internal_font_number f;
1292 scaled a, h, x, w, delta;
1297 p = new_character(f, cur_val);
1302 s = slant(f) / ((double) 65536.0);
1303 a = char_width(f, char_info(f, character(p)));
1308 if ((cur_cmd == letter) || (cur_cmd == other_char) || (cur_cmd == char_given))
1309 q = new_character(f, cur_chr);
1310 else if (cur_cmd == char_num)
1313 q = new_character(f, cur_val);
1320 t = slant(f) / ((double) 65536.0);
1321 i = char_info(f, character(q));
1322 w = char_width(f, i);
1323 h = char_height(f, height_depth(i));
1328 shift_amount(p) = x - h;
1331 delta = round((w - a) / ((double) 2.0)+ h * t - x * s);
1332 r = new_kern(delta);
1333 subtype(r) = acc_kern;
1336 tail = new_kern(- (integer) a - delta);
1337 subtype(tail) = acc_kern;
1344 space_factor = 1000;
1348 void align_error (void)
1350 if (abs(align_state) > 2)
1352 print_err("Misplaced ");
1353 print_cmd_chr(cur_cmd, cur_chr);
1355 if (cur_tok == tab_token + '&')
1357 help6("I can't figure out why you would want to use a tab mark",
1358 "here. If you just want an ampersand, the remedy is",
1359 "simple: Just type `I\\&' now. But if some right brace",
1360 "up above has ended a previous alignment prematurely,",
1361 "you're probably due for more error messages, and you",
1362 "might try typing `S' now just to see what is salvageable.");
1366 help5("I can't figure out why you would want to use a tab mark",
1367 "or \\cr or \\span just now. If something like a right brace",
1368 "up above has ended a previous alignment prematurely,",
1369 "you're probably due for more error messages, and you",
1370 "might try typing `S' now just to see what is salvageable.");
1379 if (align_state < 0)
1381 print_err("Missing { inserted");
1383 cur_tok = left_brace_token + '{';
1387 print_err("Missing } inserted");
1389 cur_tok = right_brace_token + '}';
1392 help3("I've put in what seems to be necessary to fix",
1393 "the current column of the current alignment.",
1394 "Try to go on, since this might almost work.");
1399 void noalign_error (void)
1401 print_err("Misplaced ");
1402 print_esc("noalign");
1403 help2("I expect to see \\noalign only after the \\cr of",
1404 "an alignment. Proceed, and I'll ignore this case.");
1408 void omit_error (void)
1410 print_err("Misplaced ");
1412 help2("I expect to see \\omit only after tab marks or the \\cr of",
1413 "an alignment. Proceed, and I'll ignore this case.");
1419 base_ptr = input_ptr;
1420 input_stack[base_ptr] = cur_input;
1422 while ((input_stack[base_ptr].index_field != v_template) &&
1423 (input_stack[base_ptr].loc_field == 0) &&
1424 (input_stack[base_ptr].state_field == token_list))
1427 if ((input_stack[base_ptr].index_field != v_template) ||
1428 (input_stack[base_ptr].loc_field != 0) ||
1429 (input_stack[base_ptr].state_field != token_list))
1430 fatal_error("(interwoven alignment preambles are not allowed)");
1432 if (cur_group == align_group)
1443 void cs_error (void)
1445 print_err("Extra ");
1446 print_esc("endcsname");
1447 help1("I'm ignoring this, since I wasn't doing a \\csname.");
1451 void push_math_(group_code c)
1455 incompleat_noad = 0;
1459 void init_math (void)
1466 internal_font_number f;
1473 if ((cur_cmd == math_shift) && (mode > 0))
1478 w = -max_dimen; /* - (2^30 - 1) */
1482 line_break(display_widow_penalty);
1483 v = shift_amount(just_box) + 2 * quad(cur_font);
1484 w = -max_dimen; /* - (2^30 - 1) */
1485 p = list_ptr(just_box);
1490 if (is_char_node(p))
1493 d = char_width(f, char_info(f, character(p)));
1510 mem[lig_trick] = mem[lig_char(p)];
1511 link(lig_trick) = link(p);
1527 if (glue_sign(just_box) == stretching)
1529 if ((glue_order(just_box) == stretch_order(q)) && (stretch(q) != 0))
1530 v = max_dimen; /* - (2^30 - 1) */
1532 else if (glue_sign(just_box) == shrinking)
1534 if ((glue_order(just_box) == shrink_order(q)) && (shrink(q) != 0))
1535 v = max_dimen; /* - (2^30 - 1) */
1538 if (subtype(p) >= a_leaders)
1552 if (v < max_dimen) /* - (2^30 - 1) */
1557 if (v < max_dimen) /* - (2^30 - 1) */
1564 w = max_dimen; /* - (2^30 - 1) */
1573 if (par_shape_ptr == 0)
1574 if ((hang_indent != 0) && (((hang_after >= 0) &&
1575 (prev_graf + 2 > hang_after)) || (prev_graf + 1 < - (integer) hang_after)))
1577 l = hsize - abs(hang_indent);
1579 if (hang_indent > 0)
1591 n = info(par_shape_ptr);
1593 if (prev_graf + 2 >= n)
1594 p = par_shape_ptr + 2 * n;
1596 p = par_shape_ptr + 2 *(prev_graf + 2);
1598 s = mem[p - 1].cint;
1602 push_math(math_shift_group);
1604 eq_word_define(int_base + cur_fam_code, -1);
1605 eq_word_define(dimen_base + pre_display_size_code, w);
1606 eq_word_define(dimen_base + display_width_code, l);
1607 eq_word_define(dimen_base + display_indent_code, s);
1609 if (every_display != 0)
1610 begin_token_list(every_display, every_display_text);
1622 push_math(math_shift_group);
1623 eq_word_define(int_base + cur_fam_code, -1);
1625 if (every_math != 0)
1626 begin_token_list(every_math, every_math_text);
1631 void start_eq_no (void)
1637 push_math(math_shift_group);
1638 eq_word_define(int_base + cur_fam_code, -1);
1640 if (every_math != 0)
1641 begin_token_list(every_math, every_math_text);
1645 void scan_math_(pointer p)
1654 while (!((cur_cmd != spacer) && (cur_cmd != relax)));
1663 c = math_code(cur_chr);
1668 cur_cs = cur_chr + active_base;
1669 cur_cmd = eq_type(cur_cs);
1670 cur_chr = equiv(cur_cs);
1684 cur_cmd = char_given;
1691 scan_fifteen_bit_int();
1702 scan_twenty_seven_bit_int();
1713 push_math(math_group);
1719 math_type(p) = math_char;
1720 character(p) = c % 256;
1722 if ((c >= var_code) && ((cur_fam >= 0) && (cur_fam < 16)))
1725 fam(p) = (c / 256) % 16;
1728 void set_math_char_(integer c)
1734 cur_cs = cur_chr + active_base;
1735 cur_cmd = eq_type(cur_cs);
1736 cur_chr = equiv(cur_cs);
1743 math_type(nucleus(p)) = math_char;
1744 character(nucleus(p)) = c % 256;
1745 fam(nucleus(p)) = (c / 256) % 16;
1749 if (((cur_fam >= 0) && (cur_fam < 16)))
1750 fam(nucleus(p)) = cur_fam;
1755 type(p) = ord_noad + (c / 4096);
1762 void math_limit_switch (void)
1765 if (type(tail) == op_noad)
1767 subtype(tail) = cur_chr;
1771 print_err("Limit controls must follow a math operator");
1772 help1("I'm ignoring this misplaced \\limits or \\nolimits command.");
1776 void scan_delimiter_(pointer p, boolean r)
1780 scan_twenty_seven_bit_int();
1788 while (!((cur_cmd != spacer) && (cur_cmd != relax)));
1794 cur_val = del_code(cur_chr);
1798 scan_twenty_seven_bit_int();
1809 print_err("Missing delimiter (. inserted)");
1810 help6("I was expecting to see something like `(' or `\\{' or",
1811 "`\\}' here. If you typed, e.g., `{' instead of `\\{', you",
1812 "should probably delete the `{' by typing `1' now, so that",
1813 "braces don't get unbalanced. Otherwise just proceed.",
1814 "Acceptable delimiters are characters whose \\delcode is",
1815 "nonnegative, or you can use `\\delimiter <delimiter code>'.");
1820 small_fam(p) = (cur_val / 1048576L) % 16;
1821 small_char(p) = (cur_val / 4096) % 256;
1822 large_fam(p) = (cur_val / 256) % 16;
1823 large_char(p) = cur_val % 256;
1826 void math_radical (void)
1828 tail_append(get_node(radical_noad_size));
1829 type(tail) = radical_noad;
1830 subtype(tail) = normal;
1831 mem[nucleus(tail)].hh = empty_field;
1832 mem[subscr(tail)].hh = empty_field;
1833 mem[supscr(tail)].hh = empty_field;
1834 scan_delimiter(left_delimiter(tail), true);
1835 scan_math(nucleus(tail));
1840 if (cur_cmd == accent)
1842 print_err("Please use ");
1843 print_esc("mathaccent");
1844 print_string(" for accents in math mode");
1845 help2("I'm changing \\accent to \\mathaccent here; wish me luck.",
1846 "(Accents are not the same in formulas as they are in text.)");
1850 tail_append(get_node(accent_noad_size));
1851 type(tail) = accent_noad;
1852 subtype(tail) = normal;
1853 mem[nucleus(tail)].hh = empty_field;
1854 mem[subscr(tail)].hh = empty_field;
1855 mem[supscr(tail)].hh = empty_field;
1856 math_type(accent_chr(tail)) = math_char;
1857 scan_fifteen_bit_int();
1858 character(accent_chr(tail)) = cur_val % 256;
1860 if ((cur_val >= var_code) && ((cur_fam >= 0) && (cur_fam < 16)))
1861 fam(accent_chr(tail)) = cur_fam;
1863 fam(accent_chr(tail)) = (cur_val / 256) % 16;
1865 scan_math(nucleus(tail));
1868 void append_choices (void)
1870 tail_append(new_choice());
1873 push_math(math_choice_group);
1877 halfword fin_mlist_(halfword p)
1881 if (incompleat_noad != 0)
1883 math_type(denominator(incompleat_noad)) = sub_mlist;
1884 info(denominator(incompleat_noad)) = link(head);
1887 q = incompleat_noad;
1890 q = info(numerator(incompleat_noad));
1892 if (type(q) != left_noad)
1898 info(numerator(incompleat_noad)) = link(q);
1899 link(q) = incompleat_noad;
1900 link(incompleat_noad) = p;
1914 void build_choices (void)
1924 display_mlist(tail) = p;
1928 text_mlist(tail) = p;
1932 script_mlist(tail) = p;
1937 script_script_mlist(tail) = p;
1945 push_math(math_choice_group);
1951 /* small_number t; */
1952 int t; /* 95/Jan/7 */
1959 if (script_allowed(tail))
1961 p = supscr(tail) + cur_cmd - sup_mark;
1965 if ((p == 0) || (t != 0))
1967 tail_append(new_noad());
1968 p = supscr(tail) + cur_cmd - sup_mark;
1972 if (cur_cmd == sup_mark)
1974 print_err("Double superscript");
1975 help1("I treat `x^1^2' essentially like `x^1{}^2'.");
1979 print_err("Double subscript");
1980 help1("I treat `x_1_2' essentially like `x_1{}_2'.");
1988 void package_(small_number c)
1996 save_ptr = save_ptr - 3;
1999 cur_box = hpack(link(head), saved(2), saved(1));
2002 cur_box = vpackage(link(head), saved(2), saved(1), d);
2007 p = list_ptr(cur_box);
2010 if (type(p) <= rule_node)
2013 depth(cur_box) = depth(cur_box) - h + height(cur_box);
2014 height(cur_box) = h;