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 align_peek (void)
26 align_state = 1000000L;
32 while (!(cur_cmd != spacer));
34 if (cur_cmd == no_align)
38 new_save_level(no_align_group);
43 else if (cur_cmd == right_brace)
47 else if ((cur_cmd == car_ret) && (cur_chr == cr_cr_code))
56 halfword finite_shrink_(halfword p)
60 if (no_shrink_error_yet)
62 no_shrink_error_yet = false;
63 print_err("Infinite glue shrinkage found in a paragraph");
64 help5("The paragraph just ended includes some glue that has",
65 "infinite shrinkability, e.g., `\\hskip 0pt minus 1fil'.",
66 "Such glue doesn't belong there---it allows a paragraph",
67 "of any length to fit on one line. But it's safe to proceed,",
68 "since the offensive shrinkability has been made finite.");
73 shrink_order(q) = normal;
79 void try_break_ (integer pi, small_number break_type)
90 internal_font_number f;
92 bool node_r_stays_active;
95 halfword b; /* current badness */
97 bool artificial_demerits;
101 if (abs(pi)>= inf_penalty)
110 do_all_six(copy_to_cur_active);
112 cur_active_width[1] = active_width[1];
113 cur_active_width[2] = active_width[2];
114 cur_active_width[3] = active_width[3];
115 cur_active_width[4] = active_width[4];
116 cur_active_width[5] = active_width[5];
117 cur_active_width[6] = active_width[6];
124 if (type(r) == delta_node)
126 do_all_six(update_width);
128 cur_active_width[1] = cur_active_width[1] + mem[r + 1].cint;
129 cur_active_width[2] = cur_active_width[2] + mem[r + 2].cint;
130 cur_active_width[3] = cur_active_width[3] + mem[r + 3].cint;
131 cur_active_width[4] = cur_active_width[4] + mem[r + 4].cint;
132 cur_active_width[5] = cur_active_width[5] + mem[r + 5].cint;
133 cur_active_width[6] = cur_active_width[6] + mem[r + 6].cint;
135 prev_prev_r = prev_r;
145 if ((minimum_demerits < awful_bad) && ((old_l != easyline) || (r == active)))
149 no_break_yet = false;
150 do_all_six(set_break_width_to_background);
152 break_width[1] = background[1];
153 break_width[2] = background[2];
154 break_width[3] = background[3];
155 break_width[4] = background[4];
156 break_width[5] = background[5];
157 break_width[6] = background[6];
161 if (break_type > unhyphenated)
164 t = replace_count(cur_p);
166 s = post_break(cur_p);
173 if ((v >= hi_mem_min))
176 break_width[1] = break_width[1] - char_width(f, char_info(f, character(v)));
178 else switch (type(v))
182 f = font(lig_char(v));
183 break_width[1] = break_width[1] - char_width(f, char_info(f, character(lig_char(v))));
191 break_width[1] = break_width[1] - width(v);
197 return; // abort_flag set
205 if ((s >= hi_mem_min))
208 break_width[1] = break_width[1] + char_width(f, char_info(f, character(s)));
214 f = font(lig_char(s));
215 break_width[1] = break_width[1] + char_width(f, char_info(f, character(lig_char(s))));
223 break_width[1] = break_width[1] + width(s);
229 return; // abort_flag set
237 break_width[1] = break_width[1] + disc_width;
239 if (post_break(cur_p) == 0)
245 if ((s >= hi_mem_min))
253 break_width[1] = break_width[1] - width(v);
254 break_width[2 + stretch_order(v)] = break_width[2 + stretch_order(v)] - stretch(v);
255 break_width[6] = break_width[6] - shrink(v);
264 break_width[1] = break_width[1] - width(s);
268 if (subtype(s) != explicit)
271 break_width[1] = break_width[1] - width(s);
284 if (type(prev_r) == delta_node)
286 do_all_six(convert_to_break_width);
288 mem[prev_r + 1].cint = mem[prev_r + 1].cint - cur_active_width[1] + break_width[1];
289 mem[prev_r + 2].cint = mem[prev_r + 2].cint - cur_active_width[2] + break_width[2];
290 mem[prev_r + 3].cint = mem[prev_r + 3].cint - cur_active_width[3] + break_width[3];
291 mem[prev_r + 4].cint = mem[prev_r + 4].cint - cur_active_width[4] + break_width[4];
292 mem[prev_r + 5].cint = mem[prev_r + 5].cint - cur_active_width[5] + break_width[5];
293 mem[prev_r + 6].cint = mem[prev_r + 6].cint - cur_active_width[6] + break_width[6];
296 else if (prev_r == active)
298 do_all_six(store_break_width);
300 active_width[1] = break_width[1];
301 active_width[2] = break_width[2];
302 active_width[3] = break_width[3];
303 active_width[4] = break_width[4];
304 active_width[5] = break_width[5];
305 active_width[6] = break_width[6];
310 q = get_node(delta_node_size);
312 type(q) = delta_node;
314 do_all_six(new_delta_to_break_width);
316 mem[q + 1].cint = break_width[1]- cur_active_width[1];
317 mem[q + 2].cint = break_width[2]- cur_active_width[2];
318 mem[q + 3].cint = break_width[3]- cur_active_width[3];
319 mem[q + 4].cint = break_width[4]- cur_active_width[4];
320 mem[q + 5].cint = break_width[5]- cur_active_width[5];
321 mem[q + 6].cint = break_width[6]- cur_active_width[6];
324 prev_prev_r = prev_r;
328 if (abs(adj_demerits) >= awful_bad - minimum_demerits)
329 minimum_demerits = awful_bad - 1;
331 minimum_demerits = minimum_demerits + abs(adj_demerits);
333 for (fit_class = very_loose_fit; fit_class <= tight_fit; fit_class++)
335 if (minimal_demerits[fit_class] <= minimum_demerits)
337 q = get_node(passive_node_size);
340 cur_break(q) = cur_p;
343 serial(q) = pass_number;
345 prev_break(q) = best_place[fit_class];
346 q = get_node(active_node_size);
347 break_node(q) = passive;
348 line_number(q) = best_pl_line[fit_class] + 1;
349 fitness(q) = fit_class;
350 type(q) = break_type;
351 total_demerits(q) = minimal_demerits[fit_class];
356 if (tracing_paragraphs > 0)
359 print_int(serial(passive));
360 print_string(": line ");
361 print_int(line_number(q) - 1);
363 print_int(fit_class);
365 if (break_type == hyphenated)
369 print_int(total_demerits(q));
370 print_string(" -> @@");
372 if (prev_break(passive) == 0)
375 print_int(serial(prev_break(passive)));
380 minimal_demerits[fit_class] = awful_bad;
383 minimum_demerits = 1073741823L; /* 2^30 - 1 */
387 q = get_node(delta_node_size);
389 type(q) = delta_node;
391 do_all_six(new_delta_from_break_width);
393 mem[q + 1].cint = cur_active_width[1] - break_width[1];
394 mem[q + 2].cint = cur_active_width[2] - break_width[2];
395 mem[q + 3].cint = cur_active_width[3] - break_width[3];
396 mem[q + 4].cint = cur_active_width[4] - break_width[4];
397 mem[q + 5].cint = cur_active_width[5] - break_width[5];
398 mem[q + 6].cint = cur_active_width[6] - break_width[6];
401 prev_prev_r = prev_r;
411 line_width = second_width;
412 old_l = max_halfword - 1; /*262142L*/ /* 2^18 - 2 ? */
418 if (l > last_special_line)
419 line_width = second_width;
420 else if (par_shape_ptr == 0)
421 line_width = first_width;
423 line_width = mem[par_shape_ptr + 2 * l].cint;
429 artificial_demerits = false;
430 shortfall = line_width - cur_active_width[1];
433 if ((cur_active_width[3] != 0) || (cur_active_width[4] != 0) || (cur_active_width[5] != 0))
436 fit_class = decent_fit;
440 if (shortfall > 7230584L)
441 if (cur_active_width[2] < 1663497L)
444 fit_class = very_loose_fit;
448 b = badness(shortfall, cur_active_width[2]);
452 fit_class = very_loose_fit;
454 fit_class = loose_fit;
456 fit_class = decent_fit;
461 if (- (integer) shortfall > cur_active_width[6])
464 b = badness(- (integer) shortfall, cur_active_width[6]);
467 fit_class = tight_fit;
469 fit_class = decent_fit;
472 if ((b > inf_bad) || (pi == eject_penalty))
474 if (final_pass && (minimum_demerits == awful_bad) && (link(r) == active) && (prev_r == active))
475 artificial_demerits = true;
476 else if (b > threshold)
479 node_r_stays_active = false;
488 node_r_stays_active = true;
491 if (artificial_demerits)
495 d = line_penalty + b;
505 else if (pi > -10000)
508 if ((break_type == hyphenated) && (type(r) == hyphenated))
510 d = d + double_hyphen_demerits;
512 d = d + final_hyphen_demerits;
514 if (abs(toint(fit_class)- toint(fitness(r))) > 1)
515 d = d + adj_demerits;
519 if (tracing_paragraphs > 0)
521 if (printed_node != cur_p)
526 short_display(link(printed_node));
529 save_link = link(cur_p);
532 short_display(link(printed_node));
533 link(cur_p) = save_link;
536 printed_node = cur_p;
543 else if (type(cur_p) != glue_node)
545 if (type(cur_p) == penalty_node)
546 print_esc("penalty");
547 else if (type(cur_p) == disc_node)
548 print_esc("discretionary");
549 else if (type(cur_p) == kern_node)
555 print_string(" via @@");
557 if (break_node(r) == 0)
560 print_int(serial(break_node(r)));
573 if (artificial_demerits)
580 d = d + total_demerits(r);
582 if (d <= minimal_demerits[fit_class])
584 minimal_demerits[fit_class] = d;
585 best_place[fit_class] = break_node(r);
586 best_pl_line[fit_class] = l;
588 if (d < minimum_demerits)
589 minimum_demerits = d;
592 if (node_r_stays_active)
595 link(prev_r) = link(r);
596 free_node(r, active_node_size);
598 if (prev_r == active)
602 if (type(r) == delta_node)
604 do_all_six(update_active);
605 do_all_six(copy_to_cur_active);
607 active_width[1] = active_width[1] + mem[r + 1].cint;
608 active_width[2] = active_width[2] + mem[r + 2].cint;
609 active_width[3] = active_width[3] + mem[r + 3].cint;
610 active_width[4] = active_width[4] + mem[r + 4].cint;
611 active_width[5] = active_width[5] + mem[r + 5].cint;
612 active_width[6] = active_width[6] + mem[r + 6].cint;
613 cur_active_width[1] = active_width[1];
614 cur_active_width[2] = active_width[2];
615 cur_active_width[3] = active_width[3];
616 cur_active_width[4] = active_width[4];
617 cur_active_width[5] = active_width[5];
618 cur_active_width[6] = active_width[6];
620 link(active) = link(r);
621 free_node(r, delta_node_size);
624 else if (type(prev_r) == delta_node)
630 do_all_six(downdate_width);
632 cur_active_width[1] = cur_active_width[1] - mem[prev_r + 1].cint;
633 cur_active_width[2] = cur_active_width[2] - mem[prev_r + 2].cint;
634 cur_active_width[3] = cur_active_width[3] - mem[prev_r + 3].cint;
635 cur_active_width[4] = cur_active_width[4] - mem[prev_r + 4].cint;
636 cur_active_width[5] = cur_active_width[5] - mem[prev_r + 5].cint;
637 cur_active_width[6] = cur_active_width[6] - mem[prev_r + 6].cint;
639 link(prev_prev_r) = active;
640 free_node(prev_r, delta_node_size);
641 prev_r = prev_prev_r;
643 else if (type(r) == delta_node)
645 do_all_six(update_width);
646 do_all_six(combine_two_deltas);
648 cur_active_width[1] = cur_active_width[1] + mem[r + 1].cint;
649 cur_active_width[2] = cur_active_width[2] + mem[r + 2].cint;
650 cur_active_width[3] = cur_active_width[3] + mem[r + 3].cint;
651 cur_active_width[4] = cur_active_width[4] + mem[r + 4].cint;
652 cur_active_width[5] = cur_active_width[5] + mem[r + 5].cint;
653 cur_active_width[6] = cur_active_width[6] + mem[r + 6].cint;
654 mem[prev_r + 1].cint = mem[prev_r + 1].cint + mem[r + 1].cint;
655 mem[prev_r + 2].cint = mem[prev_r + 2].cint + mem[r + 2].cint;
656 mem[prev_r + 3].cint = mem[prev_r + 3].cint + mem[r + 3].cint;
657 mem[prev_r + 4].cint = mem[prev_r + 4].cint + mem[r + 4].cint;
658 mem[prev_r + 5].cint = mem[prev_r + 5].cint + mem[r + 5].cint;
659 mem[prev_r + 6].cint = mem[prev_r + 6].cint + mem[r + 6].cint;
661 link(prev_r) = link(r);
662 free_node(r, delta_node_size);
670 if (cur_p == printed_node)
672 if (type(cur_p) == disc_node)
674 t = replace_count(cur_p);
679 printed_node = link(printed_node);
683 /* must exit here, there are no internal return - except for confusion */
684 /* savedbadness = b; */ /* 96/Feb/9 - for test in itex.c */
686 /* end of the old tex5.c here */
688 void post_line_break_(integer final_widow_penalty)
692 bool post_disc_break;
699 q = break_node(best_bet);
706 next_break(r) = cur_p;
711 cur_line = prev_graf + 1;
715 q = cur_break(cur_p);
717 post_disc_break = false;
720 if (type(q) == glue_node)
722 delete_glue_ref(glue_ptr(q));
723 glue_ptr(q) = right_skip;
724 subtype(q) = right_skip_code + 1;
725 add_glue_ref(right_skip);
730 if (type(q) == disc_node)
732 t = replace_count(q);
749 flush_node_list(link(q));
750 replace_count(q) = 0;
753 if (post_break(q) != 0)
763 post_disc_break = true;
766 if (pre_break(q) != 0)
781 else if ((type(q) == math_node) || (type(q) == kern_node))
792 r = new_param_glue(right_skip_code);
804 r = new_param_glue(left_skip_code);
809 if (cur_line > last_special_line)
811 cur_width = second_width;
812 cur_indent = second_indent;
814 else if (par_shape_ptr == 0)
816 cur_width = first_width;
817 cur_indent = first_indent;
821 cur_width = mem[par_shape_ptr + 2 * cur_line].cint;
822 cur_indent = mem[par_shape_ptr + 2 * cur_line - 1].cint;
825 adjust_tail = adjust_head;
826 just_box = hpack(q, cur_width, 0);
827 shift_amount(just_box) = cur_indent;
828 append_to_vlist(just_box);
830 if (adjust_head != adjust_tail)
832 link(tail) = link(adjust_head);
838 if (cur_line + 1 != best_line)
840 pen = inter_line_penalty;
842 if (cur_line == prev_graf + 1)
843 pen = pen + club_penalty;
845 if (cur_line + 2 == best_line)
846 pen = pen + final_widow_penalty;
849 pen = pen + broken_penalty;
853 r = new_penalty(pen);
860 cur_p = next_break(cur_p);
863 if (!post_disc_break)
871 if (q == cur_break(cur_p))
874 if ((q >= hi_mem_min))
877 if (non_discardable(q))
880 if (type(q) == kern_node)
890 flush_node_list(link(temp_head));
895 while (!(cur_p == 0));
897 if ((cur_line != best_line) || (link(temp_head) != 0))
899 confusion("line breaking");
900 return; // abort_flag set
903 prev_graf = best_line - 1;
906 small_number reconstitute_(small_number j, small_number n, halfword bchar, halfword hchar)
925 ligature_present = init_lig;
928 if (ligature_present)
931 while(p != 0) /* 94/Mar/22 BUG FIX */
933 append_charnode_to_t(character(p));
937 else if (cur_l < 256)
939 append_charnode_to_t(cur_l);
946 if (cur_l == non_char)
950 if (k == non_address) /* i.e. 0 --- 96/Jan/15 */
953 q = font_info[k].qqqq;
957 q = char_info(hf, cur_l);
959 if (char_tag(q) != lig_tag)
962 k = lig_kern_start(hf, q);
963 q = font_info[k].qqqq;
965 if (skip_byte(q) > stop_flag)
967 k = lig_kern_restart(hf, q);
968 q = font_info[k].qqqq;
971 if (cur_rh < non_char)
978 if (next_char(q) == test_char)
979 if (skip_byte(q) <= 128)
980 if (cur_rh < non_char)
985 goto lab22; /* goto continue; */
989 if (hchar < non_char)
996 if (op_byte(q) < kern_flag)
998 if (cur_l == non_char)
1008 pause_for_instructions();
1017 cur_l = rem_byte(q);
1018 ligature_present = true;
1025 cur_r = rem_byte(q);
1028 character(lig_stack) = cur_r;
1031 lig_stack = new_lig_item(cur_r);
1038 list_ptr(lig_stack) = p;
1039 character(p) = hu[j + 1];
1048 cur_r = rem_byte(q);
1050 lig_stack = new_lig_item(cur_r);
1051 link(lig_stack) = p;
1058 if (ligature_present)
1060 p = new_ligature(hf, cur_l, mem[cur_q].hh.v.RH);
1068 if (lig_stack == 0){
1071 } */ /* removed 99/Jan/6 */
1072 mem[cur_q].hh.v.RH = p;
1074 ligature_present = false;
1077 cur_l = rem_byte(q);
1078 ligature_present = true;
1084 cur_l = rem_byte(q);
1085 ligature_present = true;
1087 if (lig_stack != 0) /* BUG FIX */
1089 if (mem[lig_stack + 1].hh.v.RH != 0) /* l.17828 ? */
1091 mem[t].hh.v.RH = mem[lig_stack + 1].hh.v.RH;
1096 lig_stack = mem[p].hh.v.RH;
1098 if (lig_stack == 0) /* if lig_stack=null ? */
1110 cur_r = mem[lig_stack].hh.b1;
1116 append_charnode_to_t(cur_r);
1125 if (op_byte(q) != 7)
1131 w = char_kern(hf, q);
1135 if (q.b0 >= stop_flag)
1136 if (cur_rh == non_char)
1144 k = k + skip_byte(q) + 1;
1145 q = font_info[k].qqqq;
1152 link(t) = new_kern(w);
1157 if (lig_stack != 0) /* l.17841 */
1160 cur_l = character(lig_stack);
1161 ligature_present = true;
1169 void hyphenate (void)
1173 int l; /* 95/Jan/7 */
1176 halfword major_tail, minor_tail;
1178 int c; /* 95/Jan/7 */
1180 /* integer r_count; */
1181 int r_count; /* 95/Jan/7 */
1189 for (j = 0; j <= hn; j++)
1196 for (j = 2; j <= hn; j++)
1197 h = (h + h + hc[j]) % hyphen_prime;
1209 if (length(k) == hn)
1216 if (str_pool[u] < hc[j])
1219 if (str_pool[u] > hc[j])
1231 hyf[mem[s].hh.v.LH] = 1;
1247 if (trie_trc[cur_lang + 1] != cur_lang)
1254 for (j = 0; j <= hn - rhyf + 1; j++)
1256 z = trie_trl[cur_lang + 1] + hc[j];
1259 while (hc[l] == trie_trc[z])
1261 if (trie_tro[z] != min_trie_op)
1267 v = v + op_start[cur_lang];
1268 i = l - hyf_distance[v];
1270 if (hyf_num[v] > hyf[i])
1275 while(!(v == min_trie_op));
1279 z = trie_trl[z] + hc[l];
1283 for (j = 0; j <= lhyf - 1; j++)
1286 for (j = 0; j <= rhyf - 1; j++)
1289 for (j = lhyf; j <= hn - rhyf; j++)
1301 if ((ha >= hi_mem_min))
1308 hu[0] = character(ha);
1310 else if (type(ha) == ligature_node)
1311 if (font(lig_char(ha)) != hf)
1315 init_list = lig_ptr(ha);
1317 init_lft = (subtype(ha) > 1);
1318 hu[0] = character(lig_char(ha));
1327 free_node(ha, small_node_size);
1331 if (!(r >= hi_mem_min))
1332 if (type(r) == ligature_node)
1344 while (link(s) != ha)
1361 j = reconstitute(j, hn, bchar, hyf_char) + 1;
1363 if (hyphen_passed == 0)
1365 link(s) = link(hold_head);
1367 while (link(s) != 0) /* l.17903 */
1370 if (odd(hyf[j - 1]))
1373 hyphen_passed = j - 1;
1374 link(hold_head) = 0;
1378 if (hyphen_passed > 0)
1381 r = get_node(small_node_size);
1382 link(r) = link(hold_head);
1383 type(r) = disc_node;
1387 while (mem[major_tail].hh.v.RH != 0)
1389 major_tail = link(major_tail);
1397 hyf_node = new_character(hf, hyf_char);
1404 free_avail(hyf_node);
1409 l = reconstitute(l, i, font_bchar[hf], non_char) + 1;
1411 if (link(hold_head) != 0) /* BUG FIX ??? */
1413 if (minor_tail == 0)
1414 pre_break(r) = link(hold_head);
1416 link(minor_tail) = link(hold_head);
1418 minor_tail = link(hold_head);
1420 while (link(minor_tail) != 0) /* BUG FIX */
1421 minor_tail = link(minor_tail);
1425 if (hyf_node != 0) /* if hyf_node<>null then l.17956 */
1436 if (bchar_label[hf] != non_address) /* i.e. 0 --- 96/Jan/15 */
1448 l = reconstitute(l, hn, bchar, 256) + 1;
1452 hu[c_loc] = c; /* c may be used ... */
1456 if (link(hold_head) != 0) /* BUG FIX */
1458 if (minor_tail == 0) /* begin if minor_tail=null then */
1459 post_break(r) = link(hold_head);
1461 link(minor_tail) = link(hold_head);
1463 minor_tail = link(hold_head);
1465 while (link(minor_tail) != 0) /* ??? */
1466 minor_tail = link(minor_tail);
1473 j = reconstitute(j, hn, bchar, non_char) + 1;
1474 link(major_tail) = link(hold_head);
1476 while (mem[major_tail].hh.v.RH != 0)
1478 major_tail = link(major_tail);
1493 replace_count(r) = r_count;
1497 hyphen_passed = j - 1;
1498 link(hold_head) = 0;
1500 while(!(! odd(hyf[j - 1])));
1505 flush_list(init_list);
1508 void new_hyph_exceptions (void)
1510 /* small_number n; */ /* in 3.141 */
1512 /* small_number j; */ /* in 3.141 */
1547 if (lc_code(cur_chr) == 0)
1549 print_err("Not a letter");
1550 help2("Letters in \\hyphenation words must have \\lccode>0.",
1551 "Proceed; I'll ignore the character I just read.");
1557 hc[n] = lc_code(cur_chr);
1566 cur_cmd = char_given;
1581 for (j = 1; j <= n; j++)
1583 h = (h + h + hc[j]) % hyphen_prime;
1589 if (hyph_count == hyphen_prime)
1591 overflow("exception dictionary", hyphen_prime); /* exception dictionary - NOT DYNAMIC */
1592 /* not dynamic ---- but can be set -e=... from command line in ini-TeX */
1593 return; // abort_flag set
1598 while (hyph_word[h] != 0)
1602 if (length(k) < length(s))
1605 if (length(k) > length(s))
1613 if (str_pool[u] < str_pool[v])
1616 if (str_pool[u] > str_pool[v])
1622 while(!(u == str_start[k + 1]));
1641 if (cur_cmd == right_brace)
1651 print_err("Improper ");
1652 print_esc("hyphenation");
1653 print_string(" will be flushed");
1654 help2("Hyphenation exceptions must contain only letters",
1655 "and hyphens. But continue; I'll forgive and forget.");
1659 } /* end of switch */
1663 halfword prune_page_top_(halfword p)
1669 link(temp_head) = p;
1678 q = new_skip_param(split_top_skip_code);
1682 if (width(temp_ptr) > height(p))
1683 width(temp_ptr) = width(temp_ptr) - height(p);
1685 width(temp_ptr) = 0;
1714 confusion("pruning");
1715 return 0; // abort_flag set
1720 return link(temp_head);
1723 halfword vert_break_(halfword p, scaled h, scaled d)
1730 halfword best_place;
1732 /* small_number t; */
1733 int t; /* 95/Jan/7 */
1736 least_cost = awful_bad;
1737 do_all_six(set_height_zero);
1739 active_width[1] = 0;
1740 active_width[2] = 0;
1741 active_width[3] = 0;
1742 active_width[4] = 0;
1743 active_width[5] = 0;
1744 active_width[6] = 0;
1752 else switch(type(p))
1758 cur_height = cur_height + prev_dp + height(p);
1769 if (precedes_break(prev_p))
1800 confusion("vertbreak");
1801 return 0; // abort_flag set
1806 if (pi < inf_penalty)
1809 if ((active_width[3] != 0) || (active_width[4] != 0) || (active_width[5]!= 0))
1812 b = badness(h - cur_height, active_width[2]);
1813 else if (active_width[1] - h > active_width[6])
1816 b = badness(cur_height - h, active_width[6]);
1819 if (pi <= eject_penalty)
1821 else if (b < inf_bad)
1826 if (b <= least_cost)
1830 best_height_plus_depth = cur_height + prev_dp;
1833 if ((b == awful_bad) || (pi <= eject_penalty))
1837 if ((type(p) < glue_node) || (type(p) > kern_node))
1840 if (type(p) == kern_node)
1845 active_width[2 + stretch_order(q)] = active_width[2 + stretch_order(q)] + stretch(q);
1846 active_width[6] = active_width[6] + shrink(q);
1848 if ((shrink_order(q) != normal) && (shrink(q) != 0))
1850 print_err("Infinite glue shrinkage found in box being split");
1851 help4("The box you are \\vsplitting contains some infinitely",
1852 "shrinkable glue, e.g., `\\vss' or `\\vskip 0pt minus 1fil'.",
1853 "Such glue doesn't belong there; but you can safely proceed,",
1854 "since the offensive shrinkability has been made finite.");
1857 shrink_order(r) = normal;
1864 cur_height = cur_height + prev_dp + width(q);
1869 cur_height = cur_height + prev_dp - d;
1880 halfword vsplit_(eight_bits n, scaled h)
1888 if (split_first_mark != 0)
1890 delete_token_ref(split_first_mark);
1891 split_first_mark = 0;
1892 delete_token_ref(split_bot_mark);
1901 if (type(v) != vlist_node)
1904 print_esc("vsplit");
1905 print_string(" needs a ");
1907 help2("The box you are trying to split is an \\hbox.",
1908 "I can't split such a box, so I'll leave it alone.");
1913 q = vert_break(list_ptr(v), h, split_max_depth);
1920 if (type(p) == mark_node)
1921 if (split_first_mark == 0)
1923 split_first_mark = mark_ptr(p);
1924 split_bot_mark = split_first_mark;
1925 token_ref_count(split_first_mark) = token_ref_count(split_first_mark) + 2;
1929 delete_token_ref(split_bot_mark);
1930 split_bot_mark = mark_ptr(p);
1931 add_token_ref(split_bot_mark);
1942 q = prune_page_top(q);
1944 free_node(v, box_node_size);
1949 box(n) = vpackage(q, 0, 1, 1073741823L); /* 2^30 - 1 */
1951 return vpackage(p, h, exactly, split_max_depth);
1954 void print_totals (void)
1956 print_scaled(page_so_far[1]);
1958 if (page_so_far[2] != 0)
1960 print_string(" plus ");
1961 print_scaled(page_so_far[2]);
1965 if (page_so_far[3] != 0)
1967 print_string(" plus ");
1968 print_scaled(page_so_far[3]);
1969 print_string("fil");
1972 if (page_so_far[4] != 0)
1974 print_string(" plus ");
1975 print_scaled(page_so_far[4]);
1976 print_string("fill");
1979 if (page_so_far[5] != 0)
1981 print_string(" plus ");
1982 print_scaled(page_so_far[5]);
1983 print_string("filll");
1986 if (page_so_far[6] != 0)
1988 print_string(" minus ");
1989 print_scaled(page_so_far[6]);
1993 void freeze_page_specs_(small_number s)
1997 page_max_depth = max_depth;
1999 do_all_six(set_page_so_far_zero);
2008 least_page_cost = awful_bad;
2010 if (tracing_pages > 0)
2013 print_nl("%% goal height=");
2014 print_scaled(page_goal);
2015 print_string(", max depth=");
2016 print_scaled(page_max_depth);
2017 end_diagnostic(false);
2022 void box_error_(eight_bits n)
2026 print_nl("The following box has been deleted:");
2028 end_diagnostic(true);
2029 flush_node_list(box(n));
2033 void ensure_vbox_(eight_bits n)
2040 if (type(p) == hlist_node)
2042 print_err("Insertions can only be added to a vbox");
2043 help3("Tut tut: You're trying to \\insert into a",
2044 "\\box register that now contains an \\hbox.",
2045 "Proceed, and I'll discard its present contents.");
2050 void fire_up_(halfword c)
2052 halfword p, q, r, s;
2054 /* unsigned char n; */
2055 unsigned int n; /* 95/Jan/7 */
2057 integer save_vbadness;
2059 halfword save_split_top_skip;
2061 if (type(best_page_break) == penalty_node)
2063 geq_word_define(int_base + output_penalty_code, penalty(best_page_break));
2064 penalty(best_page_break) = inf_penalty;
2067 geq_word_define(int_base + output_penalty_code, inf_penalty);
2072 delete_token_ref(top_mark);
2074 top_mark = bot_mark;
2075 add_token_ref(top_mark);
2076 delete_token_ref(first_mark);
2080 if (c == best_page_break)
2081 best_page_break = 0;
2087 print_string("255 is not void");
2088 help2("You shouldn't use \\box255 except in \\output routines.",
2089 "Proceed, and I'll discard its present contents.");
2093 insert_penalties = 0;
2094 save_split_top_skip = split_top_skip;
2096 if (holding_inserts <= 0)
2098 r = link(page_ins_head);
2100 while (r != page_ins_head)
2102 if (best_ins_ptr(r) != 0)
2108 box(n) = new_null_box();
2110 p = box(n) + list_offset;
2112 while (link(p) != 0)
2115 last_ins_ptr(r) = p;
2127 while (p != best_page_break)
2129 if (type(p) == ins_node)
2131 if (holding_inserts <= 0)
2133 r = link(page_ins_head);
2135 while (subtype(r) != subtype(p))
2138 if (best_ins_ptr(r) == 0)
2143 s = last_ins_ptr(r);
2144 link(s) = ins_ptr(p);
2146 if (best_ins_ptr(r) == p)
2148 if (type(r) == split_up)
2149 if ((broken_ins(r) == p) && (broken_ins(r) != 0))
2151 while (link(s) != broken_ptr(r))
2155 split_top_skip = split_top_ptr(p);
2156 ins_ptr(p) = prune_page_top(broken_ptr(r));
2158 if (ins_ptr(p) != 0)
2160 temp_ptr = vpackage(ins_ptr(p), 0, 1, 1073741823L); /* 2^30 - 1 */
2161 height(p) = height(temp_ptr) + depth(temp_ptr);
2162 free_node(temp_ptr, box_node_size);
2167 best_ins_ptr(r) = 0;
2169 temp_ptr = list_ptr(box(n));
2170 free_node(box(n), box_node_size);
2171 box(n) = vpackage(temp_ptr, 0, 1, 1073741823L); /* 2^30 - 1 */
2175 while (link(s) != 0)
2178 last_ins_ptr(r) = s;
2182 link(prev_p) = link(p);
2189 incr(insert_penalties);
2193 delete_glue_ref(split_top_ptr(p));
2194 free_node(p, ins_node_size);
2200 else if (type(p) == mark_node)
2202 if (first_mark == 0)
2204 first_mark = mark_ptr(p);
2205 add_token_ref(first_mark);
2209 delete_token_ref(bot_mark);
2211 bot_mark = mark_ptr(p);
2212 add_token_ref(bot_mark);
2218 split_top_skip = save_split_top_skip;
2220 if (p != 0) /* if p<>null then l.19730 */
2222 if (link(contrib_head) == 0)
2226 nest[0].tail_field = page_tail;
2228 link(page_tail) = link(contrib_head);
2229 link(contrib_head) = p;
2233 save_vbadness = vbadness;
2237 box(255) = vpackage(link(page_head), best_size, 0, page_max_depth);
2238 vbadness = save_vbadness;
2241 if (last_glue != empty_flag)
2242 delete_glue_ref(last_glue);
2245 page_tail = page_head;
2246 link(page_head) = 0;
2247 last_glue = empty_flag;
2255 link(page_head) = link(hold_head);
2259 r = link(page_ins_head);
2261 while (r != page_ins_head)
2264 free_node(r, page_ins_node_size);
2268 link(page_ins_head) = page_ins_head;
2270 if ((top_mark != 0) && (first_mark == 0))
2272 first_mark = top_mark;
2273 add_token_ref(top_mark);
2276 if (output_routine != 0)
2277 if (dead_cycles >= max_dead_cycles)
2279 print_err("Output loop---");
2280 print_int(dead_cycles);
2281 print_string(" consecutive dead cycles");
2282 help3("I've concluded that your \\output is awry; it never does",
2283 "\\ship_out, so I'm shipping \box255 out myself. Next ",
2284 "increase \\maxdeadcycles if you want me to be more patient!");
2289 output_active = true;
2293 cur_list.aux_field.cint = ignore_depth;
2294 mode_line = - (integer) line;
2295 begin_token_list(output_routine, output_text);
2296 new_save_level(output_group);
2303 if (link(page_head) != 0)
2305 if (link(contrib_head) == 0)
2309 nest[0].tail_field = page_tail;
2311 link(page_tail) = link(contrib_head);
2313 link(contrib_head) = link(page_head);
2314 link(page_head) = 0;
2315 page_tail = page_head;