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)
68 if (page_contents < box_there)
70 if (page_contents == 0)
71 freeze_page_specs(box_there);
73 page_contents = box_there;
75 q = new_skip_param(top_skip_code);
77 if (width(temp_ptr) > height(p))
78 width(temp_ptr) = width(temp_ptr) - height(p);
83 link(contrib_head) = q;
88 page_total = page_total + page_depth + height(p);
89 page_depth = depth(p);
99 if (page_contents < box_there)
101 else if (precedes_break(page_tail))
108 if (page_contents < box_there)
110 else if (link(p) == 0)
112 else if (type(link(p)) == glue_node)
119 if (page_contents < box_there)
131 if (page_contents == 0)
132 freeze_page_specs(inserts_only);
137 while (n >= subtype(link(r)))
144 q = get_node(page_ins_node_size);
156 if (ins_dir(p) != box_dir(box(n)))
158 print_err("Insertions can only be added to a same direction vbox");
159 help3("Tut tut: You're trying to \\insert into a",
160 "\\box register that now have a different direction.",
161 "Proceed, and I'll discard its present contents.");
165 height(r) = height(box(n)) + depth(box(n));
171 if (count(n) == 1000)
174 h = x_over_n(height(r), 1000) * count(n);
176 page_goal = page_goal - h - width(q);
177 page_so_far[2 + stretch_order(q)] = page_so_far[2 + stretch_order(q)] + stretch(q);
178 page_shrink = page_shrink + shrink(q);
180 if ((shrink_order(q) != normal) && (shrink(q) != 0))
182 print_err("Infinite glue shrinkage inserted from ");
185 help3("The correction glue for page breaking with insertions",
186 "must have finite shrinkability. But you may proceed,",
187 "since the offensive shrinkability has been made finite.");
192 if (type(r) == split_up)
193 insert_penalties = insert_penalties + float_cost(p);
197 delta = page_goal - page_total - page_depth + page_shrink;
199 if (count(n) == 1000)
202 h = x_over_n(height(p), 1000) * count(n);
204 if (((h <= 0) || (h <= delta)) && (height(p) + height(r) <= dimen(n)))
206 page_goal = page_goal - h;
207 height(r) = height(r) + height(p);
212 w = max_dimen; /* 2^30 - 1 */
215 w = page_goal - page_total - page_depth;
217 if (count(n) != 1000)
218 w = x_over_n(w, count(n)) * 1000;
221 if (w > dimen(n) - height(r))
222 w = dimen(n) - height(r);
224 q = vert_break(ins_ptr(p), w, depth(p));
225 height(r) = height(r) + best_height_plus_depth;
228 if (tracing_pages > 0)
236 print_scaled(best_height_plus_depth);
240 print_int(eject_penalty);
241 else if (type(q) == penalty_node)
242 print_int(penalty(q));
246 end_diagnostic(false);
249 if (count(n) != 1000)
250 best_height_plus_depth = x_over_n(best_height_plus_depth, 1000) * count(n);
252 page_goal = page_goal - best_height_plus_depth;
258 insert_penalties = insert_penalties + (eject_penalty);
259 else if (type(q) == penalty_node)
260 insert_penalties = insert_penalties + penalty(q);
270 return; // abort_flag set
275 if (pi < inf_penalty)
277 if (page_total < page_goal)
278 if ((page_so_far[3] != 0) || (page_so_far[4] != 0) || (page_so_far[5] != 0))
281 b = badness(page_goal - page_total, page_so_far[2]);
282 else if (page_total - page_goal > page_shrink)
283 b = awful_bad; /* 2^30 - 1 */
285 b = badness(page_total - page_goal, page_shrink);
287 if (b < awful_bad) /* 2^30 - 1 */
288 if (pi <= eject_penalty)
290 else if (b < inf_bad)
291 c = b + pi + insert_penalties;
297 if (insert_penalties >= 10000)
298 c = awful_bad; /* 2^30 - 1 */
301 if (tracing_pages > 0)
308 print_scaled(page_goal);
311 if (b == awful_bad) /* 2^30 - 1 */
320 if (c == awful_bad) /* 2^30 - 1 */
325 if (c <= least_page_cost)
328 end_diagnostic(false);
332 if (c <= least_page_cost)
335 best_size = page_goal;
337 r = link(page_ins_head);
339 while (r != page_ins_head)
341 best_ins_ptr(r) = last_ins_ptr(r);
346 if ((c == awful_bad) || (pi <= eject_penalty)) /* 2^30 - 1 */
357 if ((type(p) < glue_node) || (type(p) > kern_node))
360 if (type(p) == kern_node)
365 page_so_far[2 + stretch_order(q)] = page_so_far[2 + stretch_order(q)] + stretch(q);
366 page_shrink = page_shrink + shrink(q);
368 if ((shrink_order(q) != normal) && (shrink(q) != 0))
370 print_err("Infinite glue shrinkage found on current page");
371 help4("The page about to be output contains some infinitely",
372 "shrinkable glue, e.g., `\\vss' or `\\vskip 0pt minus 1fil'.",
373 "Such glue doesn't belong there; but you can safely proceed,",
374 "since the offensive shrinkability has been made finite.");
377 shrink_order(r) = normal;
384 page_total = page_total + page_depth + width(q);
387 if (page_depth > page_max_depth)
389 page_total = page_total + page_depth - page_max_depth;
390 page_depth = page_max_depth;
395 link(contrib_head) = link(p);
399 link(contrib_head) = link(p);
404 while (!(link(contrib_head) == 0));
409 nest[0].tail_field = contrib_head;
412 void app_space (void)
416 if ((space_factor >= 2000) && (xspace_skip != zero_glue))
417 q = new_param_glue(xspace_skip_code);
420 if (space_skip != zero_glue)
424 main_p = font_glue[cur_font];
428 main_p = new_spec(zero_glue);
429 main_k = param_base[cur_font] + space_code;
430 width(main_p) = font_info[main_k].cint;
431 stretch(main_p) = font_info[main_k + 1].cint;
432 shrink(main_p) = font_info[main_k + 2].cint;
433 font_glue[cur_font] = main_p;
437 main_p = new_spec(main_p);
439 if (space_factor >= 2000)
440 width(main_p) = width(main_p) + extra_space(cur_font);
442 stretch(main_p) = xn_over_d(stretch(main_p), space_factor, 1000);
443 shrink(main_p) = xn_over_d(shrink(main_p), 1000, space_factor);
444 q = new_glue(main_p);
445 glue_ref_count(main_p) = 0;
448 if (!is_char_node(tail) && (type(tail) == disp_node))
461 void insert_dollar_sign (void)
464 cur_tok = math_shift_token + '$';
465 print_err("Missing $ inserted");
466 help2("I've inserted a begin-math/end-math symbol since I think",
467 "you left one out. Proceed, with fingers crossed.");
473 print_err("You can't use `");
474 print_cmd_chr(cur_cmd, cur_chr);
475 print_string("' in ");
479 void report_illegal_case (void)
482 help4("Sorry, but I'm not programmed to handle this case;",
483 "I'll just pretend that you didn't ask for it.",
484 "If you're in the wrong mode, you might be able to",
485 "return to the right one by typing `I}' or `I$' or `I\\par'.");
489 boolean privileged (void)
495 report_illegal_case();
500 boolean its_all_over (void)
504 if ((page_head == page_tail) && (head == cur_list.tail_field) && (dead_cycles == 0))
510 tail_append(new_null_box());
512 tail_append(new_glue(fill_glue));
513 tail_append(new_penalty(-1073741824L));
520 void append_glue (void)
541 cur_val = fil_neg_glue;
553 tail_append(new_glue(cur_val));
554 inhibit_glue_flag = false;
558 decr(glue_ref_count(cur_val));
561 subtype(tail) = mu_glue;
565 void append_kern (void)
570 scan_dimen(s == mu_glue, false, false);
571 inhibit_glue_flag = false;
573 if (!is_char_node(tail) && (type(tail) == disp_node))
575 prev_append(new_kern(cur_val));
576 subtype(prev_node) = s;
580 tail_append(new_kern(cur_val));
589 if (cur_group == bottom_level)
592 print_cmd_chr(cur_cmd, cur_chr);
593 help1("Things are pretty mixed up, but I think the worst is over.");
601 print_err("Missing ");
605 case semi_simple_group:
607 info(p) = cs_token_flag + frozen_end_group;
608 print_esc("endgroup");
612 case math_shift_group:
614 info(p) = math_shift_token + '$';
619 case math_left_group:
621 info(p) = cs_token_flag + frozen_right;
622 link(p) = get_avail();
624 info(p) = other_token + '.';
631 info(p) = right_brace_token + '}';
637 print_string(" inserted");
638 ins_list(link(temp_head));
639 help5("I've inserted something that you may have forgotten.",
640 "(See the <inserted text> above.)",
641 "With luck, this will get me unwedged. But if you",
642 "really didn't forget anything, try typing `2' now; then",
643 "my insertion and my current dilemma will both disappear.");
648 void extra_right_brace (void)
650 print_err("Extra }, or forgotten ");
654 case semi_simple_group:
655 print_esc("endgroup");
658 case math_shift_group:
662 case math_left_group:
667 help5("I've deleted a group-closing symbol because it seems to be",
668 "spurious, as in `$x}$'. But perhaps the } is legitimate and",
669 "you forgot something else, as in `\\hbox{$x}'. In such cases",
670 "the way to recover is to insert both the forgotten and the",
671 "deleted material, e.g., by typing `I$}'.");
676 void normal_paragraph (void)
679 eq_word_define(int_base + looseness_code, 0);
681 if (hang_indent != 0)
682 eq_word_define(dimen_base + hang_indent_code, 0);
685 eq_word_define(int_base + hang_after_code, 1);
687 if (par_shape_ptr != 0)
688 eq_define(par_shape_loc, shape_ref, 0);
691 void box_end_(integer box_context)
696 if (box_context < box_flag)
708 if (box_dir(q) == abs(direction))
710 list_ptr(q) = cur_box;
716 delete_glue_ref(space_ptr(q));
717 delete_glue_ref(xspace_ptr(q));
718 free_node(q, box_node_size);
722 if (box_dir(cur_box) != abs(direction))
723 cur_box = new_dir_node(cur_box,abs(direction));
725 shift_amount(cur_box) = box_context;
727 if (abs(mode) == vmode)
729 append_to_vlist(cur_box);
731 if (adjust_tail != 0)
733 if (adjust_head != adjust_tail)
735 link(tail) = link(adjust_head);
747 if (abs(mode) == hmode)
752 math_type(nucleus(p)) = sub_box;
753 info(nucleus(p)) = cur_box;
757 link(tail) = cur_box;
762 else if (box_context < ship_out_flag)
763 if (box_context < (box_flag + 256))
764 eq_define((box_base - box_flag) + box_context, box_ref, cur_box);
766 geq_define((box_base - box_flag - 256) + box_context, box_ref, cur_box);
767 else if (cur_box != 0)
768 if (box_context > ship_out_flag)
774 while(!((cur_cmd != spacer) && (cur_cmd != relax)));
776 if (((cur_cmd == hskip) && (abs(mode) != vmode)) || ((cur_cmd == vskip) && (abs(mode) == vmode)))
779 subtype(tail) = box_context - (leader_flag - a_leaders);
781 if (type(cur_box) <= dir_node)
791 if (box_dir(q) == abs(direction))
793 list_ptr(q) = cur_box;
799 delete_glue_ref(space_ptr(q));
800 delete_glue_ref(xspace_ptr(q));
801 free_node(q, box_node_size);
805 if (box_dir(cur_box) != abs(direction))
806 cur_box = new_dir_node(cur_box,abs(direction));
809 leader_ptr(tail) = cur_box;
813 print_err("Leaders not followed by proper glue");
814 help3("You should say `\\leaders <box or rule><hskip or vskip>'.",
815 "I found the <box or rule>, but there's no suitable",
816 "<hskip or vskip>, so I'm ignoring these leaders.");
818 flush_node_list(cur_box);
825 void begin_box_(integer box_context)
827 pointer r; // {running behind |p|}
828 boolean fd; // {a final |disp_node| pair?}
829 scaled disp, pdisp; // {displacement}
830 eight_bits a_dir; // {adjust direction}
831 pointer tx; // {effective tail node}
841 scan_eight_bit_int();
842 cur_box = box(cur_val);
849 scan_eight_bit_int();
850 cur_box = copy_node_list(box(cur_val));
858 if (abs(mode) == mmode)
861 help1("Sorry; this \\lastbox will be void.");
864 else if ((mode == vmode) && (head == cur_list.tail_field))
867 help2("Sorry...I usually can't take things from the current page.",
868 "This \\lastbox will therefore be void.");
873 check_effective_tail(goto lab30);
875 if (!(is_char_node(tx) || (head != tx)))
876 if ((type(tail) == hlist_node) || (type(tail) == vlist_node) ||
877 (type(tail) == dir_node))
879 fetch_effective_tail(goto lab30);
881 shift_amount(cur_box) = 0;
883 if (type(cur_box) == dir_node)
885 link(list_ptr(cur_box)) = cur_box;
886 cur_box = list_ptr(cur_box);
887 list_ptr(link(cur_box)) = 0;
889 else if (box_dir(cur_box) == dir_default)
890 set_box_dir(cur_box, abs(direction));
899 scan_eight_bit_int();
902 if (!scan_keyword("to"))
904 print_err("Missing `to' inserted");
905 help2("I'm working on `\\vsplit<box number> to <dimen>';",
906 "will look for the <dimen> next.");
910 scan_dimen(false, false, false);
911 cur_box = vsplit(n, cur_val);
917 k = cur_chr - vtop_code;
918 saved(0) = box_context;
922 if ((box_context < box_flag) && (abs(mode) == vmode))
924 a_dir = abs(direction);
925 scan_spec(adjust_hbox_group, true);
928 scan_spec(hbox_group, true);
932 scan_spec(vbox_group, true);
935 scan_spec(vtop_group, true);
943 mode = - (integer) k;
948 prev_depth = ignore_depth;
951 begin_token_list(every_vbox, every_vbox_text);
958 begin_token_list(every_hbox, every_vbox_text);
965 box_end(box_context);
968 void scan_box_(integer box_context)
974 while (!((cur_cmd != spacer) && (cur_cmd != relax)));
976 if (cur_cmd == make_box)
978 begin_box(box_context);
980 else if ((box_context >= leader_flag) && ((cur_cmd == hrule) || (cur_cmd == vrule)))
982 cur_box = scan_rule_spec();
983 box_end(box_context);
987 print_err("A <box> was supposed to be here");
988 help3("I was expecting to see \\hbox or \\vbox or \\copy or \\box or",
989 "something like that. So you might find something missing in",
990 "your output. But keep trying; you can fix this later.");
994 /****************************************************************************/
995 void package_ (small_number);
996 /****************************************************************************/
998 small_number norm_min_ (integer h)
1008 void new_graf_(boolean indented)
1012 if ((mode == vmode) || (head != tail))
1013 tail_append(new_param_glue(par_skip_code));
1016 adjust_dir = abs(direction);
1018 space_factor = 1000;
1021 prev_graf =(norm_min(left_hyphen_min) * 64 + norm_min(right_hyphen_min)) * 65536L + cur_lang;
1025 tail = new_null_box();
1027 width(tail) = par_indent;
1031 begin_token_list(every_par, every_par_text);
1037 void indent_in_hmode (void)
1044 width(p) = par_indent;
1046 if (abs(mode) == hmode)
1047 space_factor = 1000;
1051 math_type(nucleus(q)) = sub_box;
1052 info(nucleus(q)) = p;
1060 void head_for_vmode (void)
1064 if (cur_cmd != hrule)
1068 print_err("You can't use `");
1070 print_string("' here except with leaders");
1071 help2("To put a horizontal rule in an hbox or an alignment,",
1072 "you should use \\leaders or \\hrulefill (see The TeXbook).");
1079 cur_tok = par_token;
1081 cur_input.index_field = inserted;
1085 void end_graf (void)
1093 adjust_hlist(head, true);
1094 line_break(widow_penalty);
1102 void begin_insert_or_adjust (void)
1104 if (cur_cmd == vadjust)
1108 scan_eight_bit_int();
1112 print_err("You can't ");
1113 print_esc("insert");
1115 help1("I'm changing to \\insert0; box 255 is special.");
1123 new_save_level(insert_group);
1128 direction = adjust_dir;
1129 prev_depth = ignore_depth;
1132 void make_mark (void)
1136 p = scan_toks(false, true);
1137 p = get_node(small_node_size);
1138 type(p) = mark_node;
1140 mark_ptr(p) = def_ref;
1142 if (!is_char_node(tail) && (type(tail) == disp_node))
1148 void append_penalty (void)
1152 if (!is_char_node(tail) && (type(tail) == disp_node))
1153 prev_append(new_penalty(cur_val));
1155 tail_append(new_penalty(cur_val));
1161 void delete_last (void)
1164 pointer r; // {running behind |p|}
1165 boolean fd; // {a final |disp_node| pair?}
1166 scaled disp, pdisp; // {displacement}
1167 pointer tx; // {effective tail node}
1170 if ((mode == vmode) && (tail == head))
1172 if ((cur_chr != glue_node) || (last_glue != max_halfword))
1175 help2("Sorry...I usually can't take things from the current page.",
1176 "Try `I\\vskip-\\lastskip' instead.");
1178 if (cur_chr == kern_node)
1179 help_line[0] = "Try `I\\kern-\\last_kern' instead.";
1180 else if (cur_chr != glue_node)
1181 help_line[0] = "Perhaps you can make the output routine do it.";
1187 check_effective_tail(return);
1189 if (!is_char_node(tx))
1190 if (type(tx) == cur_chr)
1192 fetch_effective_tail(return);
1193 flush_node_list(tx);
1198 void unpackage (void)
1202 scaled disp; // {displacement}
1205 scan_eight_bit_int();
1211 if (type(p) == dir_node)
1214 if ((abs(mode) == mmode) || ((abs(mode) == vmode) && (type(p) != vlist_node)) ||
1215 ((abs(mode) == hmode) && (type(p) != hlist_node)))
1217 print_err("Incompatible list can't be unboxed");
1218 help3("Sorry, Pandora. (You sneaky devil.)",
1219 "I refuse to unbox an \\hbox in vertical mode or vice versa.",
1220 "And I can't open any boxes in math mode.");
1230 if (abs(direction) != box_dir(p))
1232 print_err("Incompatible direction list can't be unboxed");
1233 help2("Sorry, Pandora. (You sneaky devil.)",
1234 "I refuse to unbox a box in differrent direction.");
1243 link(tail) = copy_node_list(list_ptr(p));
1246 if (type(box(cur_val)) == dir_node)
1248 delete_glue_ref(space_ptr(box(cur_val)));
1249 delete_glue_ref(xspace_ptr(box(cur_val)));
1250 free_node(box(cur_val), box_node_size);
1253 link(tail) = list_ptr(p);
1255 delete_glue_ref(space_ptr(p));
1256 delete_glue_ref(xspace_ptr(p));
1257 free_node(p, box_node_size);
1260 while (link(tail) != 0)
1265 if (!is_char_node(tail))
1269 if ((subtype(tail) == kanji_skip_code + 1) ||
1270 (subtype(tail)=xkanji_skip_code+1))
1272 link(p) = link(tail);
1273 delete_glue_ref(glue_ptr(tail));
1274 free_node(tail, small_node_size);
1280 if (subtype(tail) == widow_pena)
1282 link(p) = link(tail);
1283 free_node(tail, small_node_size);
1291 disp = disp_dimen(tail);
1299 void append_italic_correction (void)
1302 internal_font_number f;
1303 pointer d; // {|disp_node|}
1307 if (!is_char_node(tail) && (type(tail) == disp_node))
1315 if ((last_jchr != null) && (link(last_jchr) == tail) && (is_char_node(tail)))
1317 else if (is_char_node(tail))
1319 else if (type(tail) == ligature_node)
1325 tail_append(new_kern(char_italic(f, char_info(f, character(p)))));
1326 subtype(tail) = ita_kern;
1336 void append_discretionary (void)
1340 tail_append(new_disc());
1344 c = hyphen_char[cur_font];
1348 pre_break(tail) = new_character(cur_font, c);
1354 new_save_level(disc_group);
1358 space_factor = 1000;
1362 void build_discretionary (void)
1374 if (!(p >= hi_mem_min))
1375 if (type(p) > rule_node)
1376 if (type(p) != kern_node)
1377 if (type(p) != ligature_node)
1378 if ((type(p) == penalty_node) && (subtype(p) != normal))
1381 free_node(p, small_node_size);
1386 print_err("Improper discretionary list");
1387 help1("Discretionary lists must contain only boxes and kerns.");
1390 print_nl("The following discretionary sublist has been deleted:");
1392 end_diagnostic(true);
1410 pre_break(tail) = p;
1414 post_break(tail) = p;
1419 if ((n > 0) && (abs(mode) == mmode))
1421 print_err("Illegal math ");
1422 print_esc("discretionary");
1423 help2("Sorry: The third part of a discretionary break must be",
1424 "empty, in math formulas. I had to delete your third part.");
1432 if (n <= max_quarterword)
1433 replace_count(tail) = n;
1436 print_err("Discretionary list is too long");
1437 help2("Wow---I never thought anybody would tweak me here.",
1438 "You can't seriously need such a huge discretionary list?");
1447 tail_append(get_node(small_node_size));
1448 type(tail) = disp_node;
1449 disp_dimen(tail) = 0;
1457 new_save_level(disc_group);
1461 space_factor = 1000;
1464 void make_accent (void)
1467 scaled disp; // {displacement}
1468 KANJI_code cx; // {temporary register for KANJI}
1470 internal_font_number f;
1471 scaled a, h, x, w, delta;
1476 if (!is_char_ascii(cur_val))
1480 if (direction == dir_tate)
1485 p = new_character(f, get_jfm_pos(cx, f));
1489 link(p) = get_avail();
1496 p = new_character(f,cur_val);
1502 s = slant(f) / ((double) 65536.0);
1503 a = char_width(f, char_info(f, character(p)));
1509 if ((cur_cmd == letter) || (cur_cmd == other_char))
1510 q = new_character(f, cur_chr);
1511 else if ((cur_cmd=kanji) || (cur_cmd == kana) || (cur_cmd == other_kchar))
1513 if (direction == dir_tate)
1520 else if (cur_cmd == char_given)
1521 if (is_char_ascii(cur_chr))
1522 q = new_character(f, cur_chr);
1525 if (direction == dir_tate)
1532 else if (cur_cmd == char_num)
1536 if (is_char_ascii(cur_val))
1537 q = new_character(f, cur_val);
1540 if (direction == dir_tate)
1551 if (direction == dir_tate)
1553 if (font_dir[f] == dir_tate)
1555 else if (font_dir[f] == dir_yoko)
1556 disp = t_baseline_shift - y_baseline_shift;
1558 disp = t_baseline_shift;
1562 if (font_dir[f] == dir_yoko)
1564 else if (font_dir[f] == dir_tate)
1565 disp = y_baseline_shift - t_baseline_shift;
1567 disp = y_baseline_shift;
1570 append_disp_node_at_begin();
1574 q = new_character(f, get_jfm_pos(cx, f));
1575 link(q) = get_avail();
1582 t = slant(f) / ((double) 65536.0);
1583 i = char_info(f, character(q));
1584 w = char_width(f, i);
1585 h = char_height(f, height_depth(i));
1589 delete_glue_ref(cur_kanji_skip);
1590 delete_glue_ref(cur_xkanji_skip);
1591 cur_kanji_skip = zero_glue;
1592 cur_xkanji_skip = zero_glue;
1593 add_glue_ref(cur_kanji_skip);
1594 add_glue_ref(cur_xkanji_skip);
1596 shift_amount(p) = x - h;
1599 delta = round((w - a) / ((double) 2.0)+ h * t - x * s);
1600 r = new_kern(delta);
1601 subtype(r) = acc_kern;
1604 tail = new_kern(- (integer) a - delta);
1605 subtype(tail) = acc_kern;
1609 if (font_dir[font(p)] != dir_default)
1610 link(link(p)) = tail;
1625 append_disp_node_at_end();
1626 space_factor = 1000;
1630 void align_error (void)
1632 if (abs(align_state) > 2)
1634 print_err("Misplaced ");
1635 print_cmd_chr(cur_cmd, cur_chr);
1637 if (cur_tok == tab_token + '&')
1639 help6("I can't figure out why you would want to use a tab mark",
1640 "here. If you just want an ampersand, the remedy is",
1641 "simple: Just type `I\\&' now. But if some right brace",
1642 "up above has ended a previous alignment prematurely,",
1643 "you're probably due for more error messages, and you",
1644 "might try typing `S' now just to see what is salvageable.");
1648 help5("I can't figure out why you would want to use a tab mark",
1649 "or \\cr or \\span just now. If something like a right brace",
1650 "up above has ended a previous alignment prematurely,",
1651 "you're probably due for more error messages, and you",
1652 "might try typing `S' now just to see what is salvageable.");
1661 if (align_state < 0)
1663 print_err("Missing { inserted");
1665 cur_tok = left_brace_token + '{';
1669 print_err("Missing } inserted");
1671 cur_tok = right_brace_token + '}';
1674 help3("I've put in what seems to be necessary to fix",
1675 "the current column of the current alignment.",
1676 "Try to go on, since this might almost work.");
1681 void noalign_error (void)
1683 print_err("Misplaced ");
1684 print_esc("noalign");
1685 help2("I expect to see \\noalign only after the \\cr of",
1686 "an alignment. Proceed, and I'll ignore this case.");
1690 void omit_error (void)
1692 print_err("Misplaced ");
1694 help2("I expect to see \\omit only after tab marks or the \\cr of",
1695 "an alignment. Proceed, and I'll ignore this case.");
1701 base_ptr = input_ptr;
1702 input_stack[base_ptr] = cur_input;
1704 while ((input_stack[base_ptr].index_field != v_template) &&
1705 (input_stack[base_ptr].loc_field == 0) &&
1706 (input_stack[base_ptr].state_field == token_list))
1709 if ((input_stack[base_ptr].index_field != v_template) ||
1710 (input_stack[base_ptr].loc_field != 0) ||
1711 (input_stack[base_ptr].state_field != token_list))
1712 fatal_error("(interwoven alignment preambles are not allowed)");
1714 if (cur_group == align_group)
1725 void cs_error (void)
1727 print_err("Extra ");
1728 print_esc("endcsname");
1729 help1("I'm ignoring this, since I wasn't doing a \\csname.");
1733 void push_math_(group_code c)
1737 incompleat_noad = 0;
1741 void init_math (void)
1748 internal_font_number f;
1755 if ((cur_cmd == math_shift) && (mode > 0))
1760 w = -max_dimen; /* - (2^30 - 1) */
1764 adjust_hlist(head, true);
1765 line_break(display_widow_penalty);
1766 v = shift_amount(just_box) + 2 * quad(cur_font);
1767 w = -max_dimen; /* - (2^30 - 1) */
1768 p = list_ptr(just_box);
1773 if ((p >= hi_mem_min))
1776 d = char_width(f, char_info(f, character(p)));
1777 if (font_dir[f] != dir_default)
1796 mem[lig_trick] = mem[lig_char(p)];
1797 link(lig_trick) = link(p);
1813 if (glue_sign(just_box) == stretching)
1815 if ((glue_order(just_box) == stretch_order(q)) && (stretch(q) != 0))
1816 v = max_dimen; /* - (2^30 - 1) */
1818 else if (glue_sign(just_box) == shrinking)
1820 if ((glue_order(just_box) == shrink_order(q)) && (shrink(q) != 0))
1821 v = max_dimen; /* - (2^30 - 1) */
1824 if (subtype(p) >= a_leaders)
1838 if (v < max_dimen) /* - (2^30 - 1) */
1843 if (v < max_dimen) /* - (2^30 - 1) */
1850 w = max_dimen; /* - (2^30 - 1) */
1859 if (par_shape_ptr == 0)
1860 if ((hang_indent != 0) && (((hang_after >= 0) &&
1861 (prev_graf + 2 > hang_after)) || (prev_graf + 1 < - (integer) hang_after)))
1863 l = hsize - abs(hang_indent);
1865 if (hang_indent > 0)
1877 n = info(par_shape_ptr);
1879 if (prev_graf + 2 >= n)
1880 p = par_shape_ptr + 2 * n;
1882 p = par_shape_ptr + 2 *(prev_graf + 2);
1884 s = mem[p - 1].cint;
1888 push_math(math_shift_group);
1890 eq_word_define(int_base + cur_fam_code, -1);
1891 eq_word_define(dimen_base + pre_display_size_code, w);
1892 eq_word_define(dimen_base + display_width_code, l);
1893 eq_word_define(dimen_base + display_indent_code, s);
1895 if (every_display != 0)
1896 begin_token_list(every_display, every_display_text);
1908 push_math(math_shift_group);
1909 eq_word_define(int_base + cur_fam_code, -1);
1911 if (every_math != 0)
1912 begin_token_list(every_math, every_math_text);
1916 direction = -abs(direction);
1919 void start_eq_no (void)
1925 push_math(math_shift_group);
1926 eq_word_define(int_base + cur_fam_code, -1);
1928 if (every_math != 0)
1929 begin_token_list(every_math, every_math_text);
1933 void scan_math_(pointer p, pointer q)
1944 while(!((cur_cmd != spacer) && (cur_cmd != relax)));
1953 c = math_code(cur_chr);
1955 if (is_char_ascii(cur_chr) || (cur_chr == 256))
1957 c = (math_code(cur_chr));
1962 cur_cs = cur_chr + active_base;
1963 cur_cmd = eq_type(cur_cs);
1964 cur_chr = equiv(cur_cs);
1987 cur_cmd = char_given;
1994 scan_fifteen_bit_int();
2005 scan_twenty_seven_bit_int();
2016 push_math(math_group);
2024 math_type(p) = math_char;
2025 character(p) = (c % 256);
2027 if ((c >= var_code) && ((cur_fam >= 0) && (cur_fam < 16)))
2030 fam(p) = (c / 256) % 16;
2032 if (font_dir[fam_fnt(fam(p) + cur_size)] != dir_default)
2034 print_err("Not one-byte family");
2043 math_type(p) = sub_mlist;
2044 info(p) = new_noad();
2045 p = nucleus(info(p));
2046 q = kcode_noad_nucleus(p);
2049 math_type(p) = math_jchar;
2052 math_kcode(p - 1) = (cx);
2054 if (font_dir[fam_fnt(fam(p) + cur_size)] == dir_default)
2056 print_err("Not two-byte family");
2063 void set_math_char_(integer c)
2069 cur_cs = cur_chr + active_base;
2070 cur_cmd = eq_type(cur_cs);
2071 cur_chr = equiv(cur_cs);
2078 math_type(nucleus(p)) = math_char;
2079 character(nucleus(p)) = c % 256;
2080 fam(nucleus(p)) = (c / 256) % 16;
2084 if (((cur_fam >= 0) && (cur_fam < 16)))
2085 fam(nucleus(p)) = cur_fam;
2090 type(p) = ord_noad + (c / 4096);
2095 if (font_dir[fam_fnt(fam(nucleus(p)) + cur_size)] != dir_default)
2097 print_err("Not one-byte family");
2102 inhibit_glue_flag = false;
2106 void math_limit_switch (void)
2109 if (type(tail) == op_noad)
2111 subtype(tail) = cur_chr;
2115 print_err("Limit controls must follow a math operator");
2116 help1("I'm ignoring this misplaced \\limits or \\nolimits command.");
2120 void scan_delimiter_(pointer p, boolean r)
2124 scan_twenty_seven_bit_int();
2132 while (!((cur_cmd != spacer) && (cur_cmd != relax)));
2138 cur_val = del_code(cur_chr);
2142 scan_twenty_seven_bit_int();
2153 print_err("Missing delimiter (. inserted)");
2154 help6("I was expecting to see something like `(' or `\\{' or",
2155 "`\\}' here. If you typed, e.g., `{' instead of `\\{', you",
2156 "should probably delete the `{' by typing `1' now, so that",
2157 "braces don't get unbalanced. Otherwise just proceed.",
2158 "Acceptable delimiters are characters whose \\delcode is",
2159 "nonnegative, or you can use `\\delimiter <delimiter code>'.");
2164 small_fam(p) = (cur_val / 1048576L) % 16;
2165 small_char(p) = (cur_val / 4096) % 256;
2166 large_fam(p) = (cur_val / 256) % 16;
2167 large_char(p) = cur_val % 256;
2170 void math_radical (void)
2172 tail_append(get_node(radical_noad_size));
2173 type(tail) = radical_noad;
2174 subtype(tail) = normal;
2175 mem[nucleus(tail)].hh = empty_field;
2176 mem[subscr(tail)].hh = empty_field;
2177 mem[supscr(tail)].hh = empty_field;
2178 scan_delimiter(left_delimiter(tail), true);
2179 scan_math(nucleus(tail), kcode_noad(tail));
2184 if (cur_cmd == accent)
2186 print_err("Please use ");
2187 print_esc("mathaccent");
2188 print_string(" for accents in math mode");
2189 help2("I'm changing \\accent to \\mathaccent here; wish me luck.",
2190 "(Accents are not the same in formulas as they are in text.)");
2194 tail_append(get_node(accent_noad_size));
2195 type(tail) = accent_noad;
2196 subtype(tail) = normal;
2197 mem[nucleus(tail)].hh = empty_field;
2198 mem[subscr(tail)].hh = empty_field;
2199 mem[supscr(tail)].hh = empty_field;
2200 math_type(accent_chr(tail)) = math_char;
2201 scan_fifteen_bit_int();
2202 character(accent_chr(tail)) = cur_val % 256;
2204 if ((cur_val >= var_code) && ((cur_fam >= 0) && (cur_fam < 16)))
2205 fam(accent_chr(tail)) = cur_fam;
2207 fam(accent_chr(tail)) = (cur_val / 256) % 16;
2209 scan_math(nucleus(tail), kcode_noad(tail));
2212 void append_choices (void)
2214 tail_append(new_choice());
2217 push_math(math_choice_group);
2221 halfword fin_mlist_(halfword p)
2225 if (incompleat_noad != 0)
2227 math_type(denominator(incompleat_noad)) = sub_mlist;
2228 info(denominator(incompleat_noad)) = link(head);
2231 q = incompleat_noad;
2234 q = info(numerator(incompleat_noad));
2236 if (type(q) != left_noad)
2239 return 0; // abort_flag set
2242 info(numerator(incompleat_noad)) = link(q);
2243 link(q) = incompleat_noad;
2244 link(incompleat_noad) = p;
2257 void build_choices (void)
2267 display_mlist(tail) = p;
2271 text_mlist(tail) = p;
2275 script_mlist(tail) = p;
2280 script_script_mlist(tail) = p;
2288 push_math(math_choice_group);
2294 /* small_number t; */
2295 int t; /* 95/Jan/7 */
2300 inhibit_glue_flag = false;
2303 if (script_allowed(tail))
2305 p = supscr(tail) + cur_cmd - sup_mark;
2309 if ((p == 0) || (t != 0))
2311 tail_append(new_noad());
2312 p = supscr(tail) + cur_cmd - sup_mark;
2316 if (cur_cmd == sup_mark)
2318 print_err("Double superscript");
2319 help1("I treat `x^1^2' essentially like `x^1{}^2'.");
2323 print_err("Double subscript");
2324 help1("I treat `x_1_2' essentially like `x_1{}_2'.");
2332 void package_(small_number c)
2339 delete_glue_ref(cur_kanji_skip);
2340 delete_glue_ref(cur_xkanji_skip);
2341 if (auto_spacing > 0)
2342 cur_kanji_skip = kanji_skip;
2344 cur_kanji_skip = zero_glue;
2345 if (auto_xspacing > 0)
2346 cur_xkanji_skip = xkanji_skip;
2348 cur_xkanji_skip = zero_glue;
2349 add_glue_ref(cur_kanji_skip);
2350 add_glue_ref(cur_xkanji_skip);
2352 save_ptr = save_ptr - 3;
2356 cur_box = hpack(link(head), saved(2), saved(1));
2357 set_box_dir(cur_box, abs(direction));
2362 cur_box = vpackage(link(head), saved(2), saved(1), d);
2363 set_box_dir(cur_box, abs(direction));
2369 p = list_ptr(cur_box);
2372 if (type(p) <= rule_node)
2375 depth(cur_box) = depth(cur_box) - h + height(cur_box);
2376 height(cur_box) = h;