OSDN Git Service

50c4ef997bf3b4c58b630e2fb9b5675e29389993
[putex/putex.git] / src / texsourc / tex6.c
1 /* Copyright 2014 Clerk Ma
2
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.
7
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.
12
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
16    02110-1301 USA.  */
17
18 #define EXTERN extern
19
20 #include "texd.h"
21
22 /* sec 0785 */
23 void align_peek (void)
24 {
25 restart:
26   align_state = 1000000L;
27
28   do
29     {
30       get_x_token();
31     }
32   while (!(cur_cmd != spacer));
33
34   if (cur_cmd == no_align)
35   {
36     scan_left_brace();
37
38     new_save_level(no_align_group);
39
40     if (mode == -1)
41       normal_paragraph();
42   }
43   else if (cur_cmd == right_brace)
44   {
45     fin_align();
46   }
47   else if ((cur_cmd == car_ret) && (cur_chr == cr_cr_code))
48     goto restart;
49   else
50   {
51     init_row();
52     init_col();
53   }
54 }
55 /* sec 0826 */
56 pointer finite_shrink_(pointer p)
57 {
58   pointer q;
59
60   if (no_shrink_error_yet)
61   {
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.");
69     error();
70   }
71
72   q = new_spec(p);
73   shrink_order(q) = normal;
74   delete_glue_ref(p);
75
76   return q;
77 }
78 /* sec 0829 */
79 void try_break_ (integer pi, small_number break_type)
80 {
81   pointer r;
82   pointer prev_r;
83   halfword old_l;
84   boolean no_break_yet;
85   pointer prev_prev_r;
86   pointer s;
87   pointer q;
88   pointer v;
89   integer t;
90   internal_font_number f;
91   halfword l;
92   boolean node_r_stays_active;
93   scaled line_width;
94   char fit_class;
95   halfword b;
96   integer d;
97   boolean artificial_demerits;
98   pointer save_link;
99   scaled shortfall;
100
101   if (abs(pi) >= inf_penalty)
102     if (pi > 0)
103       goto exit;
104     else
105       pi = eject_penalty;
106
107   no_break_yet = true;
108   prev_r = active;
109   old_l = 0;
110   do_all_six(copy_to_cur_active);
111
112   while (true)
113   {
114 continu:
115     r = link(prev_r);
116
117     if (type(r) == delta_node)
118     {
119       do_all_six(update_width);
120       prev_prev_r = prev_r;
121       prev_r = r;
122       goto continu;
123     }
124
125     {
126       l = line_number(r);
127
128       if (l > old_l)
129       {
130         if ((minimum_demerits < awful_bad) && ((old_l != easy_line) || (r == active)))
131         {
132           if (no_break_yet)
133           {
134             no_break_yet = false;
135             do_all_six(set_break_width_to_background);
136             s = cur_p;
137
138             if (break_type > unhyphenated)
139               if (cur_p != 0)
140               {
141                 t = replace_count(cur_p);
142                 v = cur_p;
143                 s = post_break(cur_p);
144
145                 while (t > 0)
146                 {
147                   decr(t);
148                   v = link(v);
149
150                   if (is_char_node(v))
151                   {
152                     f = font(v);
153                     break_width[1] = break_width[1] - char_width(f, char_info(f, character(v)));
154                   }
155                   else switch (type(v))
156                   {
157                     case ligature_node:
158                       {
159                         f = font(lig_char(v));
160                         break_width[1] = break_width[1] - char_width(f, char_info(f, character(lig_char(v))));
161                       }
162                       break;
163
164                     case hlist_node:
165                     case vlist_node:
166                     case rule_node:
167                     case kern_node:
168                       break_width[1] = break_width[1] - width(v);
169                       break;
170
171                     default:
172                       {
173                         confusion("disc1");
174                         return;
175                       }
176                       break;
177                   }
178                 }
179
180                 while (s != 0)
181                 {
182                   if (is_char_node(s))
183                   {
184                     f = font(s);
185                     break_width[1] = break_width[1] + char_width(f, char_info(f, character(s)));
186                   }
187                   else switch (type(s))
188                   {
189                     case ligature_node:
190                       {
191                         f = font(lig_char(s));
192                         break_width[1] = break_width[1] + char_width(f, char_info(f, character(lig_char(s))));
193                       }
194                       break;
195
196                     case hlist_node:
197                     case vlist_node:
198                     case rule_node:
199                     case kern_node:
200                       break_width[1] = break_width[1] + width(s);
201                       break;
202
203                     default:
204                       {
205                         confusion("disc2");
206                         return;
207                       }
208                       break;
209                   }
210
211                   s = link(s);
212                 }
213
214                 break_width[1] = break_width[1] + disc_width;
215
216                 if (post_break(cur_p) == 0)
217                   s = link(v);
218               }
219
220               while (s != 0)
221               {
222                 if (is_char_node(s))
223                   goto done;
224
225                 switch (type(s))
226                 {
227                   case glue_node:
228                     {
229                       v = glue_ptr(s);
230                       break_width[1] = break_width[1] - width(v);
231                       break_width[2 + stretch_order(v)] = break_width[2 + stretch_order(v)] - stretch(v);
232                       break_width[6] = break_width[6] - shrink(v);
233                     }
234                     break;
235
236                   case penalty_node:
237                     ;
238                     break;
239
240                   case math_node:
241                     break_width[1] = break_width[1] - width(s);
242                     break;
243
244                   case kern_node:
245                     if (subtype(s) != explicit)
246                       goto done;
247                     else
248                       break_width[1] = break_width[1] - width(s);
249                     break;
250
251                   default:
252                     goto done;
253                     break;
254                 }
255
256                 s = link(s);
257               }
258 done:;
259           }
260
261           if (type(prev_r) == delta_node)
262             do_all_six(convert_to_break_width);
263           else if (prev_r == active)
264             do_all_six(store_break_width);
265           else
266           {
267             q = get_node(delta_node_size);
268             link(q) = r;
269             type(q) = delta_node;
270             subtype(q) = 0;
271             do_all_six(new_delta_to_break_width);
272             link(prev_r) = q;
273             prev_prev_r = prev_r;
274             prev_r = q;
275           }
276
277           if (abs(adj_demerits) >= awful_bad - minimum_demerits)
278             minimum_demerits = awful_bad - 1;
279           else
280             minimum_demerits = minimum_demerits + abs(adj_demerits);
281
282           for (fit_class = very_loose_fit; fit_class <= tight_fit; fit_class++)
283           {
284             if (minimal_demerits[fit_class] <= minimum_demerits)
285             {
286               q = get_node(passive_node_size);
287               link(q) = passive;
288               passive = q;
289               cur_break(q) = cur_p;
290 #ifdef STAT
291               incr(pass_number);
292               serial(q) = pass_number;
293 #endif
294               prev_break(q) = best_place[fit_class];
295               q = get_node(active_node_size);
296               break_node(q) = passive;
297               line_number(q) = best_pl_line[fit_class] + 1;
298               fitness(q) = fit_class;
299               type(q) = break_type;
300               total_demerits(q) = minimal_demerits[fit_class];
301               link(q) = r;
302               link(prev_r) = q;
303               prev_r = q;
304 #ifdef STAT
305               if (tracing_paragraphs > 0)
306               {
307                 print_nl("@@");
308                 print_int(serial(passive));
309                 prints(": line ");
310                 print_int(line_number(q) - 1);
311                 print_char('.');
312                 print_int(fit_class);
313
314                 if (break_type == hyphenated)
315                   print_char('-');
316
317                 prints(" t=");
318                 print_int(total_demerits(q));
319                 prints(" -> @@");
320
321                 if (prev_break(passive) == 0)
322                   print_char('0');
323                 else
324                   print_int(serial(prev_break(passive)));
325               }
326 #endif /* STAT */
327             }
328
329             minimal_demerits[fit_class] = awful_bad;
330           }
331
332           minimum_demerits = awful_bad;
333
334           if (r != active)
335           {
336             q = get_node(delta_node_size);
337             link(q) = r;
338             type(q) = delta_node;
339             subtype(q) = 0;
340             do_all_six(new_delta_from_break_width);
341             link(prev_r) = q;
342             prev_prev_r = prev_r;
343             prev_r = q;
344           }
345         }
346
347         if (r == active)
348           goto exit;
349
350         if (l > easy_line)
351         {
352           line_width = second_width;
353           old_l = max_halfword - 1; /*262142L*/ /* 2^18 - 2 ? */
354         }
355         else
356         {
357           old_l = l;
358
359           if (l > last_special_line)
360             line_width = second_width;
361           else if (par_shape_ptr == 0)
362             line_width = first_width;
363           else
364             line_width = mem[par_shape_ptr + 2 * l].cint;
365         }
366       }
367     }
368
369     {
370       artificial_demerits = false;
371       shortfall = line_width - cur_active_width[1];
372
373       if (shortfall > 0)
374         if ((cur_active_width[3] != 0) || (cur_active_width[4] != 0) || (cur_active_width[5] != 0))
375         {
376           b = 0;
377           fit_class = decent_fit;
378         }
379         else
380         {
381           if (shortfall > 7230584L)
382             if (cur_active_width[2] < 1663497L)
383             {
384               b = 10000;
385               fit_class = very_loose_fit;
386               goto done1;
387             }
388
389           b = badness(shortfall, cur_active_width[2]);
390
391           if (b > 12)
392             if (b > 99)
393               fit_class = very_loose_fit;
394             else
395               fit_class = loose_fit;
396           else
397             fit_class = decent_fit;
398 done1:;
399         }
400       else
401       {
402         if (- (integer) shortfall > cur_active_width[6])
403           b = inf_bad + 1;
404         else
405           b = badness(- (integer) shortfall, cur_active_width[6]);
406
407         if (b > 12)
408           fit_class = tight_fit;
409         else
410           fit_class = decent_fit;
411       }
412
413       if ((b > inf_bad) || (pi == eject_penalty))
414       {
415         if (final_pass && (minimum_demerits == awful_bad) && (link(r) == active) && (prev_r == active))
416           artificial_demerits = true;
417         else if (b > threshold)
418           goto deactivate;
419
420         node_r_stays_active = false;
421       }
422       else
423       {
424         prev_r = r;
425
426         if (b > threshold)
427           goto continu;
428
429         node_r_stays_active = true;
430       }
431
432       if (artificial_demerits)
433         d = 0;
434       else
435       {
436         d = line_penalty + b;
437
438         if (abs(d) >= 10000)
439           d = 100000000L;
440         else
441           d = d * d;
442
443         if (pi != 0)
444           if (pi > 0)
445             d = d + pi * pi;
446           else if (pi > -10000)
447             d = d - pi * pi;
448
449         if ((break_type == hyphenated) && (type(r) == hyphenated))
450           if (cur_p != 0)
451             d = d + double_hyphen_demerits;
452           else
453             d = d + final_hyphen_demerits;
454
455         if (abs(toint(fit_class)- toint(fitness(r))) > 1)
456           d = d + adj_demerits;
457       }
458
459 #ifdef STAT
460       if (tracing_paragraphs > 0)
461       {
462         if (printed_node != cur_p)
463         {
464           print_nl("");
465
466           if (cur_p == 0)
467             short_display(link(printed_node));
468           else
469           {
470             save_link = link(cur_p);
471             link(cur_p) = 0;
472             print_nl("");
473             short_display(link(printed_node));
474             link(cur_p) = save_link;
475           }
476
477           printed_node = cur_p;
478         }
479
480         print_nl("@");
481
482         if (cur_p == 0)
483           print_esc("par");
484         else if (type(cur_p) != glue_node)
485         {
486           if (type(cur_p) == penalty_node)
487             print_esc("penalty");
488           else if (type(cur_p) == disc_node)
489             print_esc("discretionary");
490           else if (type(cur_p) == kern_node)
491             print_esc("kern");
492           else
493             print_esc("math");
494         }
495
496         prints(" via @@");
497
498         if (break_node(r) == 0)
499           print_char('0');
500         else
501           print_int(serial(break_node(r)));
502
503         prints(" b=");
504
505         if (b > inf_bad)
506           print_char('*');
507         else
508           print_int(b);
509
510         prints(" p=");
511         print_int(pi);
512         prints(" d=");
513
514         if (artificial_demerits)
515           print_char('*');
516         else
517           print_int(d);
518       }
519 #endif /* STAT */
520
521       d = d + total_demerits(r);
522
523       if (d <= minimal_demerits[fit_class])
524       {
525         minimal_demerits[fit_class] = d;
526         best_place[fit_class] = break_node(r);
527         best_pl_line[fit_class] = l;
528
529         if (d < minimum_demerits)
530           minimum_demerits = d;
531       }
532
533       if (node_r_stays_active)
534         goto continu;
535 deactivate:
536       link(prev_r) = link(r);
537       free_node(r, active_node_size);
538
539       if (prev_r == active)
540       {
541         r = link(active);
542
543         if (type(r) == delta_node)
544         {
545           do_all_six(update_active);
546           do_all_six(copy_to_cur_active);
547           link(active) = link(r);
548           free_node(r, delta_node_size);
549         }
550       }
551       else if (type(prev_r) == delta_node)
552       {
553         r = link(prev_r);
554
555         if (r == active)
556         {
557           do_all_six(downdate_width);
558           link(prev_prev_r) = active;
559           free_node(prev_r, delta_node_size);
560           prev_r = prev_prev_r;
561         }
562         else if (type(r) == delta_node)
563         {
564           do_all_six(update_width);
565           do_all_six(combine_two_deltas);
566           link(prev_r) = link(r);
567           free_node(r, delta_node_size);
568         }
569       }
570     }
571   }
572
573 exit:;
574 #ifdef STAT
575   if (cur_p == printed_node)
576     if (cur_p != 0)
577       if (type(cur_p) == disc_node)
578       {
579         t = replace_count(cur_p);
580
581         while (t > 0)
582         {
583           decr(t);
584           printed_node = link(printed_node);
585         }
586       }
587 #endif /* STAT */
588 }
589 /* end of the old tex5.c here */
590 /* sec 0877 */
591 void post_line_break_(integer final_widow_penalty)
592 {
593   pointer q, r, s;
594   boolean disc_break;
595   boolean post_disc_break;
596   scaled cur_width;
597   scaled cur_indent;
598   quarterword t;
599   integer pen;
600   halfword cur_line;
601
602   q = break_node(best_bet);
603   cur_p = 0;
604
605   do
606     {
607       r = q;
608       q = prev_break(q);
609       next_break(r) = cur_p;
610       cur_p = r;
611     }
612   while (!(q == 0));
613
614   cur_line = prev_graf + 1;
615
616   do
617     {
618       q = cur_break(cur_p);
619       disc_break = false;
620       post_disc_break = false;
621
622       if (q != 0)
623         if (type(q) == glue_node)
624         {
625           delete_glue_ref(glue_ptr(q));
626           glue_ptr(q) = right_skip;
627           subtype(q) = right_skip_code + 1;
628           add_glue_ref(right_skip);
629           goto done;
630         }
631         else
632         {
633           if (type(q) == disc_node)
634           {
635             t = replace_count(q);
636
637             if (t == 0)
638               r = link(q);
639             else
640             {
641               r = q;
642
643               while (t > 1)
644               {
645                 r = link(r);
646                 decr(t);
647               }
648
649               s = link(r);
650               r = link(s);
651               link(s) = 0;
652               flush_node_list(link(q));
653               replace_count(q) = 0;
654             }
655
656             if (post_break(q) != 0)
657             {
658               s = post_break(q);
659
660               while (link(s) != 0)
661                 s = link(s);
662
663               link(s) = r;
664               r = post_break(q);
665               post_break(q) = 0;
666               post_disc_break = true;
667             }
668
669             if (pre_break(q) != 0)
670             {
671               s = prev_break(q);
672               link(q) = s;
673
674               while (link(s) != 0)
675                 s = link(s);
676
677               prev_break(q) = 0;
678               q = s;
679             }
680
681             link(q) = r;
682             disc_break = true;
683           }
684           else if ((type(q) == math_node) || (type(q) == kern_node))
685             width(q) = 0;
686         }
687       else
688       {
689         q = temp_head;
690
691         while (link(q) != 0)
692           q = link(q);
693       }
694
695       r = new_param_glue(right_skip_code);
696       link(r) = link(q);
697       link(q) = r;
698       q = r;
699
700 done:
701
702       r = link(q);
703       link(q) = 0;
704       q = link(temp_head);
705       link(temp_head) = r;
706
707       if (left_skip != 0)
708       {
709         r = new_param_glue(left_skip_code);
710         link(r) = q;
711         q = r;
712       }
713
714       if (cur_line > last_special_line)
715       {
716         cur_width = second_width;
717         cur_indent = second_indent;
718       }
719       else if (par_shape_ptr == 0)
720       {
721         cur_width = first_width;
722         cur_indent = first_indent;
723       }
724       else
725       {
726         cur_width = mem[par_shape_ptr + 2 * cur_line].cint;
727         cur_indent = mem[par_shape_ptr + 2 * cur_line - 1].cint;
728       }
729
730       adjust_tail = adjust_head;
731       just_box = hpack(q, cur_width, 0);
732       shift_amount(just_box) = cur_indent;
733       append_to_vlist(just_box);
734
735       if (adjust_head != adjust_tail)
736       {
737         link(tail) = link(adjust_head);
738         tail = adjust_tail;
739       }
740
741       adjust_tail = 0;
742
743       if (cur_line + 1 != best_line)
744       {
745         pen = inter_line_penalty;
746
747         if (cur_line == prev_graf + 1)
748           pen = pen + club_penalty;
749
750         if (cur_line + 2 == best_line)
751           pen = pen + final_widow_penalty;
752
753         if (disc_break)
754           pen = pen + broken_penalty;
755
756         if (pen != 0)
757         {
758           r = new_penalty(pen);
759           link(tail) = r;
760           tail = r;
761         }
762       }
763
764       incr(cur_line);
765       cur_p = next_break(cur_p);
766
767       if (cur_p != 0)
768         if (!post_disc_break)
769         {
770           r = temp_head;
771
772           while (true)
773           {
774             q = link(r);
775
776             if (q == cur_break(cur_p))
777               goto done1;
778
779             if (is_char_node(q))
780               goto done1;
781
782             if (non_discardable(q))
783               goto done1;
784
785             if (type(q) == kern_node)
786               if (subtype(q) != 1)
787                 goto done1;
788
789             r = q;
790           }
791 done1:
792           if (r != temp_head)
793           {
794             link(r) = 0;
795             flush_node_list(link(temp_head));
796             link(temp_head) = q;
797           }
798         }
799     }
800   while (!(cur_p == 0));
801
802   if ((cur_line != best_line) || (link(temp_head) != 0))
803   {
804     confusion("line breaking");
805     return;
806   }
807
808   prev_graf = best_line - 1;
809 }
810 /* sec 0906 */
811 small_number reconstitute_(small_number j, small_number n, halfword bchar, halfword hchar)
812 {
813   pointer p;
814   pointer t;
815   four_quarters q;
816   halfword cur_rh;
817   halfword test_char;
818   scaled w;
819   font_index k;
820
821   hyphen_passed = 0;
822   t = hold_head;
823   w = 0;
824   link(hold_head) = 0;
825   cur_l = hu[j];
826   cur_q = t;
827
828   if (j == 0)
829   {
830     ligature_present = init_lig;
831     p = init_list; 
832
833     if (ligature_present)
834       lft_hit = init_lft; 
835
836     while (p != 0)
837     {
838       append_charnode_to_t(character(p));
839       p = link(p);
840     }
841   }
842   else if (cur_l < 256)
843   {
844     append_charnode_to_t(cur_l);
845   }
846
847   lig_stack = 0;
848   set_cur_r();
849
850 continu:
851   if (cur_l == non_char)
852   {
853     k = bchar_label[hf];
854
855     if (k == non_address)
856       goto done;
857     else
858       q = font_info[k].qqqq;
859   }
860   else
861   {
862     q = char_info(hf, cur_l);
863
864     if (char_tag(q) != lig_tag)
865       goto done;
866
867     k = lig_kern_start(hf, q);
868     q = font_info[k].qqqq;
869
870     if (skip_byte(q) > stop_flag)
871     {
872       k = lig_kern_restart(hf, q);
873       q = font_info[k].qqqq;
874     }
875   }
876
877   if (cur_rh < non_char)
878     test_char = cur_rh;
879   else
880     test_char = cur_r;
881
882   while (true)
883   {
884     if (next_char(q) == test_char)
885       if (skip_byte(q) <= 128)
886         if (cur_rh < non_char)
887         {
888           hyphen_passed = j;
889           hchar = non_char;
890           cur_rh = non_char;
891           goto continu;
892         }
893         else
894         {
895           if (hchar < non_char)
896             if (odd(hyf[j]))
897             {
898               hyphen_passed = j;
899               hchar = non_char;
900             }
901
902           if (op_byte(q) < kern_flag)
903           {
904             if (cur_l == non_char)
905               lft_hit = true;
906
907             if (j == n)
908               if (lig_stack == 0)
909                 rt_hit = true;
910
911             check_interrupt();
912
913             switch (op_byte(q))
914             {
915               case 1:
916               case 5:
917                 {
918                   cur_l = rem_byte(q);
919                   ligature_present = true;
920                 }
921                 break;
922
923               case 2:
924               case 6:
925                 {
926                   cur_r = rem_byte(q);
927
928                   if (lig_stack != 0)
929                     character(lig_stack) = cur_r;
930                   else
931                   {
932                     lig_stack = new_lig_item(cur_r);
933
934                     if (j == n)
935                       bchar = non_char;
936                     else
937                     {
938                       p = get_avail();
939                       list_ptr(lig_stack) = p;
940                       character(p) = hu[j + 1];
941                       font(p) = hf;
942                     }
943                   }
944                 }
945                 break;
946
947               case 3:
948                 {
949                   cur_r = rem_byte(q);
950                   p = lig_stack;
951                   lig_stack = new_lig_item(cur_r);
952                   link(lig_stack) = p;
953                 }
954                 break;
955
956               case 7:
957               case 11:
958                 {
959                   if (ligature_present)
960                   {
961                     p = new_ligature(hf, cur_l, mem[cur_q].hh.rh);
962
963                     if (lft_hit)
964                     {
965                       mem[p].hh.b1 = 2;
966                       lft_hit = false;
967                     }
968
969                     mem[cur_q].hh.rh = p;
970                     t = p;
971                     ligature_present = false;
972                   }
973
974                   cur_q = t;
975                   cur_l = rem_byte(q);
976                   ligature_present = true;
977                 }
978                 break;
979
980               default:
981                 {
982                   cur_l = rem_byte(q);
983                   ligature_present = true;
984
985                   if (lig_stack != 0)
986                   {
987                     if (lig_ptr(lig_stack) != 0)
988                     {
989                       link(t) = lig_ptr(lig_stack);
990                       t = link(t);
991                       incr(j);
992                     }
993
994                     p = lig_stack;
995                     lig_stack = link(p);
996                     free_node(p, small_node_size);
997
998                     if (lig_stack == 0)
999                     {
1000                       if (j < n)
1001                         cur_r = hu[j + 1];
1002                       else
1003                         cur_r = bchar;
1004
1005                       if (odd(hyf[j]))
1006                         cur_rh = hchar;
1007                       else
1008                         cur_rh = 256;
1009                     }
1010                     else
1011                       cur_r = character(lig_stack);
1012                   }
1013                   else if (j == n)
1014                     goto done;
1015                   else
1016                   {
1017                     append_charnode_to_t(cur_r);
1018                     incr(j);
1019                     set_cur_r();
1020                   }
1021                 }
1022                 break;
1023             }
1024
1025             if (op_byte(q) > 4)
1026               if (op_byte(q) != 7)
1027                 goto done;
1028
1029             goto continu;
1030           }
1031
1032           w = char_kern(hf, q);
1033           goto done;
1034         }
1035
1036     if (q.b0 >= stop_flag)
1037       if (cur_rh == non_char)
1038         goto done;
1039       else
1040       {
1041         cur_rh = non_char;
1042         goto continu;
1043       }
1044       
1045     k = k + skip_byte(q) + 1;
1046     q = font_info[k].qqqq;
1047   }
1048
1049 done:
1050   wrap_lig(rt_hit);
1051
1052   if (w != 0)
1053   {
1054     link(t) = new_kern(w);
1055     t = link(t);
1056     w = 0;
1057   }
1058
1059   if (lig_stack != 0)
1060   {
1061     cur_q = t;
1062     cur_l = character(lig_stack);
1063     ligature_present = true;
1064     pop_lig_stack();
1065     goto continu;
1066   }
1067
1068   return j;
1069 }
1070 /* sec 0895 */
1071 void hyphenate (void)
1072 {
1073 /*  char i, j, l;  */
1074   char i, j;
1075   int l;              /* 95/Jan/7 */
1076   pointer q, r, s;
1077   halfword bchar;
1078   pointer major_tail, minor_tail;
1079 /*  ASCII_code c;  */
1080   int c;
1081   char c_loc;
1082 /*  integer r_count; */
1083   int r_count;
1084   pointer hyf_node;
1085   trie_pointer z;
1086   integer v;
1087   hyph_pointer h;
1088   str_number k;
1089   pool_pointer u;
1090
1091   for (j = 0; j <= hn; j++)
1092     hyf[j] = 0;
1093
1094   h = hc[1];
1095   incr(hn);
1096   hc[hn] = cur_lang;
1097
1098   for (j = 2; j <= hn; j++)
1099     h = (h + h + hc[j]) % hyphen_prime;
1100
1101   while (true)
1102   {
1103     k = hyph_word[h];
1104
1105     if (k == 0)
1106       goto not_found;
1107
1108     if (length(k) < hn)
1109       goto not_found;
1110
1111     if (length(k) == hn)
1112     {
1113       j = 1;
1114       u = str_start[k];
1115
1116       do
1117         {
1118           if (str_pool[u] < hc[j])
1119             goto not_found;
1120
1121           if (str_pool[u] > hc[j])
1122             goto done;
1123
1124           incr(j);
1125           incr(u);
1126         }
1127       while (!(j > hn));
1128
1129       s = hyph_list[h];
1130
1131       while (s != 0)
1132       {
1133         hyf[info(s)] = 1;
1134         s = link(s);
1135       }
1136
1137       decr(hn);
1138       goto found;
1139     }
1140
1141 done:
1142     if (h > 0)
1143       decr(h);
1144     else
1145       h = hyphen_prime;
1146   }
1147
1148 not_found:
1149   decr(hn);
1150
1151   if (trie_trc[cur_lang + 1] != cur_lang)
1152     return;
1153
1154   hc[0] = 0;
1155   hc[hn + 1] = 0;
1156   hc[hn + 2] = 256;
1157
1158   for (j = 0; j <= hn - r_hyf + 1; j++)
1159   {
1160     z = trie_trl[cur_lang + 1] + hc[j];
1161     l = j;
1162
1163     while (hc[l] == trie_trc[z])
1164     {
1165       if (trie_tro[z] != min_trie_op)
1166       {
1167         v = trie_tro[z];
1168
1169         do
1170           {
1171             v = v + op_start[cur_lang];
1172             i = l - hyf_distance[v];
1173
1174             if (hyf_num[v] > hyf[i])
1175               hyf[i]= hyf_num[v];
1176
1177             v = hyf_next[v];
1178           }
1179         while (!(v == min_trie_op));
1180       }
1181
1182       incr(l);
1183       z = trie_trl[z] + hc[l];
1184     }
1185   }
1186
1187 found:
1188   for (j = 0; j <= l_hyf - 1; j++)
1189     hyf[j] = 0;
1190
1191   for (j = 0; j <= r_hyf - 1; j++)
1192     hyf[hn - j]= 0;
1193
1194   for (j = l_hyf; j <= hn - r_hyf; j++)
1195     if (odd(hyf[j]))
1196       goto found1;
1197
1198   return;
1199
1200 found1:
1201   q = link(hb);
1202   link(hb) = 0;
1203   r = link(ha);
1204   link(ha) = 0;
1205   bchar = hyf_bchar;
1206
1207   if (is_char_node(ha))
1208     if (font(ha) != hf)
1209       goto found2;
1210     else
1211     {
1212       init_list = ha;
1213       init_lig = false;
1214       hu[0] = character(ha);
1215     }
1216   else if (type(ha) == ligature_node)
1217     if (font(lig_char(ha)) != hf)
1218       goto found2;
1219     else
1220     {
1221       init_list = lig_ptr(ha);
1222       init_lig = true;
1223       init_lft = (subtype(ha) > 1);
1224       hu[0] = character(lig_char(ha));
1225
1226       if (init_list == 0)
1227         if (init_lft)
1228         {
1229           hu[0] = 256;
1230           init_lig = false;
1231         }
1232
1233       free_node(ha, small_node_size);
1234     }
1235   else
1236   {
1237     if (!is_char_node(r))
1238       if (type(r) == ligature_node)
1239         if (subtype(r) > 1)
1240           goto found2;
1241
1242     j = 1;
1243     s = ha;
1244     init_list = 0;
1245     goto common_ending;
1246   }
1247
1248   s = cur_p;
1249
1250   while (link(s) != ha)
1251     s = link(s);
1252
1253   j = 0;
1254   goto common_ending;
1255
1256 found2:
1257   s = ha;
1258   j = 0;
1259   hu[0] = 256;
1260   init_lig = false;
1261   init_list = 0;
1262
1263 common_ending:
1264   flush_node_list(r);
1265
1266   do
1267     {
1268       l = j;
1269       j = reconstitute(j, hn, bchar, hyf_char) + 1;
1270
1271       if (hyphen_passed == 0)
1272       {
1273         link(s) = link(hold_head);
1274
1275         while (link(s) != 0) /* l.17903 */
1276           s = link(s);
1277
1278         if (odd(hyf[j - 1]))
1279         {
1280           l = j;
1281           hyphen_passed = j - 1;
1282           link(hold_head) = 0;
1283         }
1284       }
1285
1286       if (hyphen_passed > 0)
1287         do
1288           {
1289             r = get_node(small_node_size);
1290             link(r) = link(hold_head);
1291             type(r) = disc_node;
1292             major_tail = r;
1293             r_count = 0;
1294
1295             while (mem[major_tail].hh.rh != 0)
1296             {
1297               major_tail = link(major_tail);
1298               incr(r_count);
1299             }
1300
1301             i = hyphen_passed;
1302             hyf[i] = 0;
1303             minor_tail = 0;
1304             pre_break(r) = 0;
1305             hyf_node = new_character(hf, hyf_char);
1306
1307             if (hyf_node != 0)
1308             {
1309               incr(i);
1310               c = hu[i];
1311               hu[i] = hyf_char;
1312               free_avail(hyf_node);
1313             }
1314
1315             while (l <= i)
1316             {
1317               l = reconstitute(l, i, font_bchar[hf], non_char) + 1;
1318
1319               if (link(hold_head) != 0) /* BUG FIX ??? */
1320               {
1321                 if (minor_tail == 0)
1322                   pre_break(r) = link(hold_head);
1323                 else
1324                   link(minor_tail) = link(hold_head);
1325
1326                 minor_tail = link(hold_head);
1327
1328                 while (link(minor_tail) != 0)  /* BUG FIX */
1329                   minor_tail = link(minor_tail);
1330               }
1331             }
1332
1333             if (hyf_node != 0) /* if hyf_node<>null then l.17956 */
1334             {
1335               hu[i] = c;
1336               l = i;
1337               decr(i);
1338             }
1339
1340             minor_tail = 0;
1341             post_break(r) = 0;
1342             c_loc = 0;
1343
1344             if (bchar_label[hf] != non_address) /* i.e. 0 --- 96/Jan/15 */
1345             {
1346               decr(l);
1347               c = hu[l];
1348               c_loc = l;
1349               hu[l]= 256;
1350             }
1351
1352             while (l < j)
1353             {
1354               do
1355                 {
1356                   l = reconstitute(l, hn, bchar, 256) + 1;
1357
1358                   if (c_loc > 0)
1359                   {
1360                     hu[c_loc] = c;
1361                     c_loc = 0;
1362                   }
1363
1364                   if (link(hold_head) != 0)     /* BUG FIX */
1365                   {
1366                     if (minor_tail == 0) /* begin if minor_tail=null then */
1367                       post_break(r) = link(hold_head);
1368                     else
1369                       link(minor_tail) = link(hold_head);
1370
1371                     minor_tail = link(hold_head);
1372
1373                     while (link(minor_tail) != 0)    /* ??? */
1374                       minor_tail = link(minor_tail);
1375                   }
1376                 }
1377               while (!(l >= j));
1378
1379               while (l > j)
1380               {
1381                 j = reconstitute(j, hn, bchar, non_char) + 1;
1382                 link(major_tail) = link(hold_head);
1383
1384                 while (mem[major_tail].hh.rh != 0)
1385                 {
1386                   major_tail = link(major_tail);
1387                   incr(r_count);
1388                 }
1389               }
1390             }
1391
1392             if (r_count > 127)
1393             {
1394               link(s) = link(r);
1395               link(r) = 0;
1396               flush_node_list(r);
1397             }
1398             else
1399             {
1400               link(s) = r;
1401               replace_count(r) = r_count;
1402             }
1403
1404             s = major_tail;
1405             hyphen_passed = j - 1;
1406             link(hold_head) = 0;
1407           }
1408         while (!(! odd(hyf[j - 1])));
1409     }
1410   while (!(j > hn));
1411
1412   link(s) = q;
1413   flush_list(init_list);
1414 }
1415 /* sec 0934 */
1416 void new_hyph_exceptions (void)
1417 {
1418   char n;
1419   char j;
1420   hyph_pointer h;
1421   str_number k;
1422   pointer p;
1423   pointer q;
1424   str_number s, t;
1425   pool_pointer u, v;
1426
1427   scan_left_brace();
1428   set_cur_lang();
1429   n = 0;
1430   p = 0;
1431
1432   while (true)
1433   {
1434     get_x_token();
1435
1436 reswitch:
1437     switch (cur_cmd)
1438     {
1439       case letter:
1440       case other_char:
1441       case char_given:
1442         if (cur_chr == '-')
1443         {
1444           if (n < 63)
1445           {
1446             q = get_avail();
1447             link(q) = p;
1448             info(q) = n;
1449             p = q;
1450           }
1451         }
1452         else
1453         {
1454           if (lc_code(cur_chr) == 0)
1455           {
1456             print_err("Not a letter");
1457             help2("Letters in \\hyphenation words must have \\lccode>0.",
1458                 "Proceed; I'll ignore the character I just read.");
1459             error();
1460           }
1461           else if (n < 63)
1462           {
1463             incr(n);
1464             hc[n] = lc_code(cur_chr);
1465           }
1466         }
1467         break;
1468
1469       case char_num:
1470         {
1471           scan_char_num();
1472           cur_chr = cur_val;
1473           cur_cmd = char_given;
1474           goto reswitch;
1475         }
1476         break;
1477
1478       case spacer:
1479       case right_brace:
1480         {
1481           if (n > 1)
1482           {
1483             incr(n);
1484             hc[n] = cur_lang;
1485             str_room(n);
1486             h = 0;
1487
1488             for (j = 1; j <= n; j++)
1489             {
1490               h = (h + h + hc[j]) % hyphen_prime;
1491               append_char(hc[j]);
1492             }
1493
1494             s = make_string();
1495
1496             if (hyph_count == hyphen_prime)
1497             {
1498               overflow("exception dictionary", hyphen_prime);
1499               return;
1500             }
1501
1502             incr(hyph_count);
1503
1504             while (hyph_word[h] != 0)
1505             {
1506               k = hyph_word[h];
1507
1508               if (length(k) < length(s))
1509                 goto found;
1510
1511               if (length(k) > length(s))
1512                 goto not_found;
1513
1514               u = str_start[k];
1515               v = str_start[s];
1516
1517               do
1518                 {
1519                   if (str_pool[u] < str_pool[v])
1520                     goto found;
1521
1522                   if (str_pool[u] > str_pool[v])
1523                     goto not_found;
1524
1525                   incr(u);
1526                   incr(v);
1527                 }
1528               while (!(u == str_start[k + 1]));
1529 found:
1530               q = hyph_list[h];
1531               hyph_list[h] = p;
1532               p = q;
1533               t = hyph_word[h];
1534               hyph_word[h] = s;
1535               s = t;
1536
1537 not_found:
1538               if (h > 0)
1539                 decr(h);
1540               else
1541                 h = hyphen_prime;
1542             }
1543
1544             hyph_word[h] = s;
1545             hyph_list[h] = p;
1546           }
1547
1548           if (cur_cmd == right_brace)
1549             return;
1550
1551           n = 0;
1552           p = 0;
1553         }
1554         break;
1555
1556       default:
1557         {
1558           print_err("Improper ");
1559           print_esc("hyphenation");
1560           prints(" will be flushed");
1561           help2("Hyphenation exceptions must contain only letters",
1562               "and hyphens. But continue; I'll forgive and forget.");
1563           error();
1564         }
1565         break;
1566     }
1567   }
1568 }
1569 /* sec 0968 */
1570 pointer prune_page_top_(pointer p)
1571 {
1572   pointer prev_p;
1573   pointer q;
1574
1575   prev_p = temp_head;
1576   link(temp_head) = p;
1577
1578   while (p != 0)
1579     switch (type(p))
1580     {
1581       case hlist_node:
1582       case vlist_node:
1583       case rule_node:
1584         {
1585           q = new_skip_param(split_top_skip_code);
1586           link(prev_p) = q;
1587           link(q) = p;
1588
1589           if (width(temp_ptr) > height(p))
1590             width(temp_ptr) = width(temp_ptr) - height(p);
1591           else
1592             width(temp_ptr) = 0;
1593
1594           p = 0;
1595         }
1596         break;
1597
1598       case whatsit_node:
1599       case mark_node:
1600       case ins_node:
1601         {
1602           prev_p = p;
1603           p = link(prev_p);
1604         }
1605         break;
1606
1607       case glue_node:
1608       case kern_node:
1609       case penalty_node:
1610         {
1611           q = p;
1612           p = link(q);
1613           link(q) = 0;
1614           link(prev_p) = p;
1615           flush_node_list(q);
1616         }
1617         break;
1618
1619       default:
1620         {
1621           confusion("pruning");
1622           return 0;
1623         }
1624         break;
1625     }
1626
1627   return link(temp_head);
1628 }
1629 /* sec 0970 */
1630 pointer vert_break_(pointer p, scaled h, scaled d)
1631 {
1632   pointer prev_p;
1633   pointer q, r;
1634   integer pi;
1635   integer b;
1636   integer least_cost;
1637   pointer best_place;
1638   scaled prev_dp; 
1639 /*  small_number t; */
1640   int t;
1641
1642   prev_p = p;
1643   least_cost = awful_bad;
1644   do_all_six(set_height_zero);
1645   prev_dp = 0;
1646
1647   while (true)
1648   {
1649     if (p == 0)
1650       pi = eject_penalty;
1651     else switch (type(p))
1652     {
1653       case hlist_node:
1654       case vlist_node:
1655       case rule_node:
1656         {
1657           cur_height = cur_height + prev_dp + height(p);
1658           prev_dp = depth(p);
1659           goto not_found;
1660         }
1661         break;
1662
1663       case whatsit_node:
1664         goto not_found;
1665         break;
1666
1667       case glue_node:
1668         if (precedes_break(prev_p))
1669           pi = 0;
1670         else
1671           goto update_heights;
1672         break;
1673
1674       case kern_node:
1675         {
1676           if (link(p) == 0)
1677             t = penalty_node;
1678           else
1679             t = type(link(p));
1680
1681           if (t == glue_node)
1682             pi = 0;
1683           else
1684             goto update_heights;
1685         }
1686         break;
1687
1688       case penalty_node:
1689         pi = penalty(p);
1690         break;
1691
1692       case mark_node:
1693       case ins_node:
1694         goto not_found;
1695         break;
1696
1697       default:
1698         {
1699           confusion("vertbreak");
1700           return 0;
1701         }
1702         break;
1703     }
1704
1705     if (pi < inf_penalty)
1706     {
1707       if (cur_height < h)
1708         if ((active_width[3] != 0) || (active_width[4] != 0) || (active_width[5]!= 0))
1709           b = 0;
1710         else
1711           b = badness(h - cur_height, active_width[2]);
1712       else if (act_width - h > active_width[6])
1713         b = awful_bad;
1714       else
1715         b = badness(cur_height - h, active_width[6]);
1716
1717       if (b < awful_bad)
1718         if (pi <= eject_penalty)
1719           b = pi;
1720         else if (b < inf_bad)
1721           b = b + pi;
1722         else
1723           b = deplorable;
1724
1725       if (b <= least_cost)
1726       {
1727         best_place = p;
1728         least_cost = b;
1729         best_height_plus_depth = cur_height + prev_dp;
1730       }
1731
1732       if ((b == awful_bad) || (pi <= eject_penalty))
1733         goto done;
1734     }
1735
1736     if ((type(p) < glue_node) || (type(p) > kern_node))
1737       goto not_found;
1738
1739 update_heights:
1740
1741     if (type(p) == kern_node)
1742       q = p;
1743     else
1744     {
1745       q = glue_ptr(p);
1746       active_width[2 + stretch_order(q)] = active_width[2 + stretch_order(q)] + stretch(q);
1747       active_width[6] = active_width[6] + shrink(q);
1748
1749       if ((shrink_order(q) != normal) && (shrink(q) != 0))
1750       {
1751         print_err("Infinite glue shrinkage found in box being split");
1752         help4("The box you are \\vsplitting contains some infinitely",
1753             "shrinkable glue, e.g., `\\vss' or `\\vskip 0pt minus 1fil'.",
1754             "Such glue doesn't belong there; but you can safely proceed,",
1755             "since the offensive shrinkability has been made finite.");
1756         error();
1757         r = new_spec(q);
1758         shrink_order(r) = normal;
1759         delete_glue_ref(q);
1760         glue_ptr(p) = r;
1761         q = r;
1762       }
1763     }
1764
1765     cur_height = cur_height + prev_dp + width(q);
1766     prev_dp = 0;
1767
1768 not_found:
1769
1770     if (prev_dp > d)
1771     {
1772       cur_height = cur_height + prev_dp - d;
1773       prev_dp = d;
1774     }
1775
1776     prev_p = p;
1777     p = link(prev_p);
1778   }
1779
1780 done:
1781   return best_place;
1782 }
1783 /* sec 0977 */
1784 pointer vsplit_(eight_bits n, scaled h)
1785 {
1786   pointer v;
1787   pointer p;
1788   pointer q;
1789
1790   v = box(n);
1791
1792   if (split_first_mark != 0)
1793   {
1794     delete_token_ref(split_first_mark);
1795     split_first_mark = 0;
1796     delete_token_ref(split_bot_mark);
1797     split_bot_mark = 0;
1798   }
1799
1800   if (v == 0)
1801   {
1802     return 0;
1803   }
1804
1805   if (type(v) != vlist_node)
1806   {
1807     print_err("");
1808     print_esc("vsplit");
1809     prints(" needs a ");
1810     print_esc("vbox");
1811     help2("The box you are trying to split is an \\hbox.",
1812         "I can't split such a box, so I'll leave it alone.");
1813     error();
1814     return 0;
1815   }
1816
1817   q = vert_break(list_ptr(v), h, split_max_depth);
1818   p = list_ptr(v);
1819
1820   if (p == q)
1821     list_ptr(v) = 0;
1822   else while (true)
1823   {
1824     if (type(p) == mark_node)
1825       if (split_first_mark == 0)
1826       {
1827         split_first_mark = mark_ptr(p);
1828         split_bot_mark = split_first_mark;
1829         token_ref_count(split_first_mark) = token_ref_count(split_first_mark) + 2;
1830       }
1831       else
1832       {
1833         delete_token_ref(split_bot_mark);
1834         split_bot_mark = mark_ptr(p);
1835         add_token_ref(split_bot_mark);
1836       }
1837
1838     if (link(p) == q)
1839     {
1840       link(p) = 0;
1841       goto done;
1842     }
1843
1844     p = link(p);
1845   }
1846
1847 done:
1848   q = prune_page_top(q);
1849   p = list_ptr(v);
1850   free_node(v, box_node_size);
1851  
1852   if (q == 0)
1853     box(n) = 0;
1854   else
1855     box(n) = vpackage(q, 0, 1, 1073741823L);  /* 2^30 - 1 */
1856
1857   return vpackage(p, h, exactly, split_max_depth);
1858 }
1859 /* sec 0985 */
1860 void print_totals (void)
1861 {
1862   print_scaled(page_so_far[1]);
1863
1864   if (page_so_far[2] != 0)
1865   {
1866     prints(" plus ");
1867     print_scaled(page_so_far[2]);
1868     prints("");
1869   }
1870
1871   if (page_so_far[3] != 0)
1872   {
1873     prints(" plus ");
1874     print_scaled(page_so_far[3]);
1875     prints("fil");
1876   }
1877
1878   if (page_so_far[4] != 0)
1879   {
1880     prints(" plus ");
1881     print_scaled(page_so_far[4]);
1882     prints("fill");
1883   }
1884
1885   if (page_so_far[5] != 0)
1886   {
1887     prints(" plus ");
1888     print_scaled(page_so_far[5]);
1889     prints("filll");
1890   }
1891
1892   if (page_so_far[6] != 0)
1893   {
1894     prints(" minus ");
1895     print_scaled(page_so_far[6]);
1896   }
1897 }
1898 /* sec 0987 */
1899 void freeze_page_specs_(small_number s)
1900 {
1901   page_contents = s;
1902   page_goal = vsize;
1903   page_max_depth = max_depth;
1904   page_depth = 0;
1905   do_all_six(set_page_so_far_zero);
1906   least_page_cost = awful_bad;
1907
1908 #ifdef STAT
1909   if (tracing_pages > 0)
1910   {
1911     begin_diagnostic();
1912     print_nl("%% goal height=");
1913     print_scaled(page_goal);
1914     prints(", max depth=");
1915     print_scaled(page_max_depth);
1916     end_diagnostic(false);
1917   }
1918 #endif
1919 }
1920 /* sec 0992 */
1921 void box_error_(eight_bits n)
1922 {
1923   error();
1924   begin_diagnostic();
1925   print_nl("The following box has been deleted:");
1926   show_box(box(n));
1927   end_diagnostic(true);
1928   flush_node_list(box(n));
1929   box(n) = 0;
1930 }
1931 /* sec 0993 */
1932 void ensure_vbox_(eight_bits n)
1933 {
1934   pointer p;
1935
1936   p = box(n);
1937
1938   if (p != 0)
1939     if (type(p) == hlist_node)
1940     {
1941       print_err("Insertions can only be added to a vbox");
1942       help3("Tut tut: You're trying to \\insert into a",
1943           "\\box register that now contains an \\hbox.",
1944           "Proceed, and I'll discard its present contents.");
1945       box_error(n);
1946     }
1947 }
1948 /* sec 1012 */
1949 void fire_up_(pointer c)
1950 {
1951   pointer p, q, r, s;
1952   pointer prev_p;
1953 /*  unsigned char n; */
1954   unsigned int n;
1955   boolean wait;
1956   integer save_vbadness;
1957   scaled save_vfuzz;
1958   pointer save_split_top_skip;
1959
1960   if (type(best_page_break) == penalty_node)
1961   {
1962     geq_word_define(int_base + output_penalty_code, penalty(best_page_break));
1963     penalty(best_page_break) = inf_penalty;
1964   }
1965   else
1966     geq_word_define(int_base + output_penalty_code, inf_penalty);
1967
1968   if (bot_mark != 0)
1969   {
1970     if (top_mark != 0)
1971       delete_token_ref(top_mark);
1972
1973     top_mark = bot_mark;
1974     add_token_ref(top_mark);
1975     delete_token_ref(first_mark);
1976     first_mark = 0;
1977   }
1978
1979   if (c == best_page_break)
1980     best_page_break = 0;
1981
1982   if (box(255) != 0)
1983   {
1984     print_err("");
1985     print_esc("box");
1986     prints("255 is not void");
1987     help2("You shouldn't use \\box255 except in \\output routines.",
1988         "Proceed, and I'll discard its present contents.");
1989     box_error(255);
1990   }
1991
1992   insert_penalties = 0;
1993   save_split_top_skip = split_top_skip;
1994
1995   if (holding_inserts <= 0)
1996   {
1997     r = link(page_ins_head);
1998
1999     while (r != page_ins_head)
2000     {
2001       if (best_ins_ptr(r) != 0)
2002       {
2003         n = subtype(r);
2004         ensure_vbox(n);
2005
2006         if (box(n) == 0)
2007           box(n) = new_null_box();
2008
2009         p = box(n) + list_offset;
2010
2011         while (link(p) != 0)
2012           p = link(p);
2013
2014         last_ins_ptr(r) = p;
2015       }
2016
2017       r = link(r);
2018     }
2019   }
2020
2021   q = hold_head;
2022   link(q) = 0;
2023   prev_p = page_head;
2024   p = link(prev_p);
2025
2026   while (p != best_page_break)
2027   {
2028     if (type(p) == ins_node)
2029     {
2030       if (holding_inserts <= 0)
2031       {
2032         r = link(page_ins_head);
2033
2034         while (subtype(r) != subtype(p))
2035           r = link(r);
2036
2037         if (best_ins_ptr(r) == 0)
2038           wait = true;
2039         else
2040         {
2041           wait = false;
2042           s = last_ins_ptr(r);
2043           link(s) = ins_ptr(p);
2044
2045           if (best_ins_ptr(r) == p)
2046           {
2047             if (type(r) == split_up)
2048               if ((broken_ins(r) == p) && (broken_ins(r) != 0))
2049               {
2050                 while (link(s) != broken_ptr(r))
2051                   s = link(s);
2052
2053                 link(s) = 0;
2054                 split_top_skip = split_top_ptr(p);
2055                 ins_ptr(p) = prune_page_top(broken_ptr(r));
2056
2057                 if (ins_ptr(p) != 0)
2058                 {
2059                   temp_ptr = vpackage(ins_ptr(p), 0, 1, 1073741823L);  /* 2^30 - 1 */
2060                   height(p) = height(temp_ptr) + depth(temp_ptr);
2061                   free_node(temp_ptr, box_node_size);
2062                   wait = true;
2063                 }
2064               }
2065
2066             best_ins_ptr(r) = 0;
2067             n = subtype(r);
2068             temp_ptr = list_ptr(box(n));
2069             free_node(box(n), box_node_size);
2070             box(n) = vpackage(temp_ptr, 0, 1, 1073741823L);  /* 2^30 - 1 */
2071           }
2072           else
2073           {
2074             while (link(s) != 0)
2075               s = link(s);
2076
2077             last_ins_ptr(r) = s;
2078           }
2079         }
2080
2081         link(prev_p) = link(p);
2082         link(p) = 0;
2083
2084         if (wait)
2085         {
2086           link(q) = p;
2087           q = p;
2088           incr(insert_penalties);
2089         }
2090         else
2091         {
2092           delete_glue_ref(split_top_ptr(p));
2093           free_node(p, ins_node_size);
2094         }
2095
2096         p = prev_p;
2097       }
2098     }
2099     else if (type(p) == mark_node)
2100     {
2101       if (first_mark == 0)
2102       {
2103         first_mark = mark_ptr(p);
2104         add_token_ref(first_mark);
2105       }
2106
2107       if (bot_mark != 0)
2108         delete_token_ref(bot_mark);
2109
2110       bot_mark = mark_ptr(p);
2111       add_token_ref(bot_mark);
2112     }
2113     prev_p = p;
2114     p = link(prev_p);
2115   }
2116
2117   split_top_skip = save_split_top_skip;
2118
2119   if (p != 0)
2120   {
2121     if (link(contrib_head) == 0)
2122       if (nest_ptr == 0)
2123         tail = page_tail;
2124       else
2125         nest[0].tail_field = page_tail;
2126
2127     link(page_tail) = link(contrib_head);
2128     link(contrib_head) = p;
2129     link(prev_p) = 0;
2130   }
2131
2132   save_vbadness = vbadness;
2133   vbadness = inf_bad;
2134   save_vfuzz = vfuzz;
2135   vfuzz = max_dimen;
2136   box(255) = vpackage(link(page_head), best_size, 0, page_max_depth);
2137   vbadness = save_vbadness;
2138   vfuzz = save_vfuzz;
2139
2140   if (last_glue != empty_flag)
2141     delete_glue_ref(last_glue);
2142
2143   page_contents = 0;
2144   page_tail = page_head;
2145   link(page_head) = 0;
2146   last_glue = empty_flag;
2147   last_penalty = 0;
2148   last_kern = 0;
2149   page_depth = 0;
2150   page_max_depth = 0;
2151
2152   if (q != hold_head)
2153   {
2154     link(page_head) = link(hold_head);
2155     page_tail = q;
2156   }
2157
2158   r = link(page_ins_head);
2159
2160   while (r != page_ins_head)
2161   {
2162     q = link(r);
2163     free_node(r, page_ins_node_size);
2164     r = q;
2165   }
2166  
2167   link(page_ins_head) = page_ins_head;
2168
2169   if ((top_mark != 0) && (first_mark == 0))
2170   {
2171     first_mark = top_mark;
2172     add_token_ref(top_mark);
2173   }
2174
2175   if (output_routine != 0)
2176     if (dead_cycles >= max_dead_cycles)
2177     {
2178       print_err("Output loop---");
2179       print_int(dead_cycles);
2180       prints(" consecutive dead cycles");
2181       help3("I've concluded that your \\output is awry; it never does",
2182           "\\ship_out, so I'm shipping \box255 out myself. Next ",
2183           "increase \\maxdeadcycles if you want me to be more patient!");
2184       error();
2185     }
2186     else
2187     {
2188       output_active = true;
2189       incr(dead_cycles);
2190       push_nest();
2191       mode = -vmode;
2192       prev_depth = ignore_depth;
2193       mode_line = - (integer) line;
2194       begin_token_list(output_routine, output_text);
2195       new_save_level(output_group);
2196       normal_paragraph();
2197       scan_left_brace();
2198       return;
2199     }
2200
2201   {
2202     if (link(page_head) != 0)
2203     {
2204       if (link(contrib_head) == 0)
2205         if (nest_ptr == 0)
2206           tail = page_tail;
2207         else
2208           nest[0].tail_field = page_tail;
2209       else
2210         link(page_tail) = link(contrib_head);
2211
2212       link(contrib_head) = link(page_head);
2213       link(page_head) = 0;
2214       page_tail = page_head;
2215     }
2216
2217     ship_out(box(255));
2218     box(255) = 0;
2219   }
2220 }