OSDN Git Service

a45022d3193b613cbf2f0e91757b76b701567d27
[putex/putex.git] / src / texsourc / tex7.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 0994 */
23 void build_page (void)
24 {
25   halfword p;
26   halfword q, r;
27   integer b, c;
28   integer pi;
29 /*  unsigned char n;  */
30   unsigned int n;             /* 95/Jan/7 */
31   scaled delta, h, w;
32
33   if ((link(contrib_head) == 0) || output_active)
34     return;
35
36   do
37     {
38 lab22:
39       p = link(contrib_head);
40
41       if (last_glue != max_halfword)
42         delete_glue_ref(last_glue);
43
44       last_penalty = 0;
45       last_kern = 0;
46
47       if (type(p) == glue_node)
48       {
49         last_glue = glue_ptr(p);
50         add_glue_ref(last_glue);
51       }
52       else
53       {
54         last_glue = max_halfword;
55
56         if (type(p) == penalty_node)
57           last_penalty = penalty(p);
58         else if (type(p) == kern_node)
59           last_kern = width(p);
60       }
61
62       switch (type(p))
63       {
64         case hlist_node:
65         case vlist_node:
66         case dir_node:
67         case rule_node:
68           if (page_contents < box_there)
69           {
70             if (page_contents == 0)
71               freeze_page_specs(box_there);
72             else
73               page_contents = box_there;
74
75             q = new_skip_param(top_skip_code);
76
77             if (width(temp_ptr) > height(p))
78               width(temp_ptr) = width(temp_ptr) - height(p);
79             else
80               width(temp_ptr) = 0;
81
82             link(q) = p;
83             link(contrib_head) = q;
84             goto lab22;
85           }
86           else
87           {
88             page_total = page_total + page_depth + height(p);
89             page_depth = depth(p);
90             goto lab80;
91           }
92           break;
93
94         case whatsit_node:
95           goto lab80;
96           break;
97
98         case glue_node:
99           if (page_contents < box_there)
100             goto lab31;
101           else if (precedes_break(page_tail))
102             pi = 0;
103           else
104             goto lab90;
105           break;
106
107         case kern_node:
108           if (page_contents < box_there)
109             goto lab31;
110           else if (link(p) == 0)
111             return;
112           else if (type(link(p)) == glue_node)
113             pi = 0;
114           else
115             goto lab90;
116           break;
117
118         case penalty_node:
119           if (page_contents < box_there)
120             goto lab31;
121           else
122             pi = penalty(p);
123           break;
124
125         case mark_node:
126           goto lab80;
127           break;
128
129         case ins_node:
130           {
131             if (page_contents == 0)
132               freeze_page_specs(inserts_only);
133
134             n = subtype(p);
135             r = page_ins_head;
136
137             while (n >= subtype(link(r)))
138               r = link(r);
139
140             n = n;
141
142             if (subtype(r) != n)
143             {
144               q = get_node(page_ins_node_size);
145               link(q) = link(r);
146               link(r) = q;
147               r = q;
148               subtype(r) = n;
149               type(r) = inserting;
150               ensure_vbox(n);
151
152               if (box(n) == 0)
153                 height(r) = 0;
154               else
155               {
156                 if (ins_dir(p) != box_dir(box(n)))
157                 {
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.");
162                   box_error(n);
163                 }
164                 else
165                   height(r) = height(box(n)) + depth(box(n));
166               }
167
168               best_ins_ptr(r) = 0;
169               q = skip(n);
170
171               if (count(n) == 1000)
172                 h = height(r);
173               else
174                 h = x_over_n(height(r), 1000) * count(n);
175
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);
179
180               if ((shrink_order(q) != normal) && (shrink(q) != 0))
181               {
182                 print_err("Infinite glue shrinkage inserted from ");
183                 print_esc("skip");
184                 print_int(n);
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.");
188                 error();
189               }
190             }
191
192             if (type(r) == split_up)
193               insert_penalties = insert_penalties + float_cost(p);
194             else
195             {
196               last_ins_ptr(r) = p;
197               delta = page_goal - page_total - page_depth + page_shrink;
198
199               if (count(n) == 1000)
200                 h = height(p);
201               else
202                 h = x_over_n(height(p), 1000) * count(n);
203
204               if (((h <= 0) || (h <= delta)) && (height(p) + height(r) <= dimen(n)))
205               {
206                 page_goal = page_goal - h;
207                 height(r) = height(r) + height(p);
208               }
209               else
210               {
211                 if (count(n) <= 0)
212                   w = max_dimen;  /* 2^30 - 1 */
213                 else
214                 {
215                   w = page_goal - page_total - page_depth;
216
217                   if (count(n) != 1000)
218                     w = x_over_n(w, count(n)) * 1000;
219                 }
220
221                 if (w > dimen(n) - height(r))
222                   w = dimen(n) - height(r);
223
224                 q = vert_break(ins_ptr(p), w, depth(p));
225                 height(r) = height(r) + best_height_plus_depth;
226
227 #ifdef STAT
228                 if (tracing_pages > 0)
229                 {
230                   begin_diagnostic();
231                   print_nl("% split");
232                   print_int(n);
233                   print_string(" to");
234                   print_scaled(w);
235                   print_char(',');
236                   print_scaled(best_height_plus_depth);
237                   print_string(" p=");
238
239                   if (q == 0)
240                     print_int(eject_penalty);
241                   else if (type(q) == penalty_node)
242                     print_int(penalty(q));
243                   else
244                     print_char('0');
245
246                   end_diagnostic(false);
247                 }
248 #endif /* STAT */
249                 if (count(n) != 1000)
250                   best_height_plus_depth = x_over_n(best_height_plus_depth, 1000) * count(n);
251
252                 page_goal = page_goal - best_height_plus_depth;
253                 type(r) = split_up;
254                 broken_ptr(r) = q;
255                 broken_ins(r) = p;
256
257                 if (q == 0)
258                   insert_penalties = insert_penalties + (eject_penalty);
259                 else if (type(q) == penalty_node)
260                   insert_penalties = insert_penalties + penalty(q);
261               }
262             }
263             goto lab80;
264           }
265           break;
266
267         default:
268           {
269             confusion("page");
270             return;       // abort_flag set
271           }
272           break;
273       }
274
275       if (pi < inf_penalty)
276       {
277         if (page_total < page_goal)
278           if ((page_so_far[3] != 0) || (page_so_far[4] != 0) || (page_so_far[5] != 0))
279             b = 0;
280           else
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 */
284         else
285           b = badness(page_total - page_goal, page_shrink);
286   
287         if (b < awful_bad) /* 2^30 - 1 */
288           if (pi <= eject_penalty)
289             c = pi; 
290           else if (b < inf_bad)
291             c = b + pi + insert_penalties;
292           else
293             c = deplorable;
294         else
295           c = b;
296
297         if (insert_penalties >= 10000)
298           c = awful_bad;  /* 2^30 - 1 */
299
300 #ifdef STAT
301         if (tracing_pages > 0)
302         {
303           begin_diagnostic();
304           print_nl("%");
305           print_string(" t=");
306           print_totals();
307           print_string(" g=");
308           print_scaled(page_goal);
309           print_string(" b=");
310
311           if (b == awful_bad) /* 2^30 - 1 */
312             print_char('*');
313           else
314             print_int(b);
315
316           print_string(" p=");
317           print_int(pi);
318           print_string(" c=");
319
320           if (c == awful_bad) /* 2^30 - 1 */
321             print_char('*');
322           else
323             print_int(c);
324
325           if (c <= least_page_cost)
326             print_char('#');
327
328           end_diagnostic(false);
329         }
330 #endif /* STAT */
331
332         if (c <= least_page_cost)
333         {
334           best_page_break = p;
335           best_size = page_goal;
336           least_page_cost = c;
337           r = link(page_ins_head);
338
339           while (r != page_ins_head)
340           {
341             best_ins_ptr(r) = last_ins_ptr(r);
342             r = link(r);
343           }
344         }
345
346         if ((c == awful_bad) || (pi <= eject_penalty))  /* 2^30 - 1 */
347         {
348           fire_up(p);
349
350           if (output_active)
351             return;
352
353           goto lab30;
354         }
355       }
356
357       if ((type(p) < glue_node) || (type(p) > kern_node))
358         goto lab80; 
359 lab90:
360       if (type(p) == kern_node)
361         q = p;
362       else
363       {
364         q = glue_ptr(p);
365         page_so_far[2 + stretch_order(q)] = page_so_far[2 + stretch_order(q)] + stretch(q);
366         page_shrink = page_shrink + shrink(q);
367
368         if ((shrink_order(q) != normal) && (shrink(q) != 0))
369         {
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.");
375           error();
376           r = new_spec(q);
377           shrink_order(r) = normal;
378           delete_glue_ref(q);
379           glue_ptr(p) = r;
380           q = r;
381         }
382       }
383
384       page_total = page_total + page_depth + width(q);
385       page_depth = 0;
386 lab80:
387       if (page_depth > page_max_depth)
388       {
389         page_total = page_total + page_depth - page_max_depth;
390         page_depth = page_max_depth;
391       }
392
393       link(page_tail) = p;
394       page_tail = p;
395       link(contrib_head) = link(p);
396       link(p) = 0;
397       goto lab30;
398 lab31:
399       link(contrib_head) = link(p);
400       link(p) = 0;
401       flush_node_list(p);
402 lab30:;
403     }
404   while (!(link(contrib_head) == 0));
405
406   if (nest_ptr == 0)
407     tail = contrib_head;
408   else
409     nest[0].tail_field = contrib_head;
410
411 /* sec 1043 */
412 void app_space (void)
413 {
414   pointer q;
415
416   if ((space_factor >= 2000) && (xspace_skip != zero_glue))
417     q = new_param_glue(xspace_skip_code);
418   else
419   {
420     if (space_skip != zero_glue)
421       main_p = space_skip;
422     else
423     {
424       main_p = font_glue[cur_font];
425
426       if (main_p == 0)
427       {
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;
434       }
435     }
436
437     main_p = new_spec(main_p);
438
439     if (space_factor >= 2000)
440       width(main_p) = width(main_p) + extra_space(cur_font);
441
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;
446   }
447   
448   if (!is_char_node(tail) && (type(tail) == disp_node))
449   {
450     link(prev_node) = q;
451     link(q) = tail;
452     prev_node = q;
453   }
454   else
455   {
456     link(tail) = q;
457     tail = q;
458   }
459 }
460 /* sec 1047 */
461 void insert_dollar_sign (void)
462 {
463   back_input();
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.");
468   ins_error();
469 }
470 /* sec 1049 */
471 void you_cant (void)
472 {
473   print_err("You can't use `");
474   print_cmd_chr(cur_cmd, cur_chr);
475   print_string("' in ");
476   print_mode(mode);
477 }
478 /* sec 1050 */
479 void report_illegal_case (void)
480 {
481   you_cant();
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'.");
486   error();
487 }
488 /* sec 1051 */
489 boolean privileged (void)
490 {
491   if (mode > 0)
492     return true;
493   else
494   {
495     report_illegal_case();
496     return false;
497   }
498 }
499 /* sec 1054 */
500 boolean its_all_over (void)
501 {
502   if (privileged ())
503   {
504     if ((page_head == page_tail) && (head == cur_list.tail_field) && (dead_cycles == 0))
505     {
506       return true;
507     }
508
509     back_input();
510     tail_append(new_null_box());
511     width(tail) = hsize;
512     tail_append(new_glue(fill_glue));
513     tail_append(new_penalty(-1073741824L));
514     build_page();
515   }
516
517   return false;
518 }
519 /* sec 1060 */
520 void append_glue (void)
521 {
522   small_number s;
523
524   s = cur_chr;
525
526   switch(s)
527   {
528     case fil_code:
529       cur_val = fil_glue;
530       break;
531
532     case fill_code:
533       cur_val = fill_glue;
534       break;
535
536     case ss_code:
537       cur_val = ss_glue;
538       break;
539
540     case fil_neg_code:
541       cur_val = fil_neg_glue;
542       break;
543
544     case skip_code:
545       scan_glue(glue_val);
546       break;
547
548     case mskip_code:
549       scan_glue(mu_val);
550       break;
551   }
552
553   tail_append(new_glue(cur_val));
554   inhibit_glue_flag = false;
555
556   if (s >= skip_code)
557   {
558     decr(glue_ref_count(cur_val));
559
560     if (s > skip_code)
561       subtype(tail) = mu_glue;
562   }
563 }
564 /* sec 1061 */
565 void append_kern (void)
566
567   quarterword s;
568
569   s = cur_chr;
570   scan_dimen(s == mu_glue, false, false);
571   inhibit_glue_flag = false;
572
573   if (!is_char_node(tail) && (type(tail) == disp_node))
574   {
575     prev_append(new_kern(cur_val));
576     subtype(prev_node) = s;
577   }
578   else
579   {
580     tail_append(new_kern(cur_val));
581     subtype(tail) = s;
582   }
583 }
584 /* sec 1064 */
585 void off_save (void)
586 {
587   pointer p;
588
589   if (cur_group == bottom_level)
590   {
591     print_err("Extra ");
592     print_cmd_chr(cur_cmd, cur_chr);
593     help1("Things are pretty mixed up, but I think the worst is over.");
594     error();
595   }
596   else
597   {
598     back_input();
599     p = get_avail();
600     link(temp_head) = p;
601     print_err("Missing ");
602
603     switch (cur_group)
604     {
605       case semi_simple_group:
606         {
607           info(p) = cs_token_flag + frozen_end_group;
608           print_esc("endgroup");
609         }
610         break;
611
612       case math_shift_group:
613         {
614           info(p) = math_shift_token + '$';
615           print_char('$');
616         }
617         break;
618
619       case math_left_group:
620         {
621           info(p) = cs_token_flag + frozen_right;
622           link(p) = get_avail();
623           p = link(p);
624           info(p) = other_token + '.';
625           print_esc("right.");
626         }
627         break;
628
629       default:
630         {
631           info(p) = right_brace_token + '}';
632           print_char('}');
633         }
634         break;
635     }
636
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.");
644     error();
645   }
646 }
647 /* sec 1069 */
648 void extra_right_brace (void)
649 {
650   print_err("Extra }, or forgotten ");
651
652   switch(cur_group)
653   {
654     case semi_simple_group:
655       print_esc("endgroup");
656       break;
657
658     case math_shift_group:
659       print_char('$');
660       break;
661
662     case math_left_group:
663       print_esc("right");
664       break;
665   }
666
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$}'.");
672   error();
673   incr(align_state);
674 }
675 /* sec 1070 */
676 void normal_paragraph (void)
677 {
678   if (looseness != 0)
679     eq_word_define(int_base + looseness_code, 0);
680
681   if (hang_indent != 0)
682     eq_word_define(dimen_base + hang_indent_code, 0);
683
684   if (hang_after != 1)
685     eq_word_define(int_base + hang_after_code, 1);
686
687   if (par_shape_ptr != 0)
688     eq_define(par_shape_loc, shape_ref, 0);
689 }
690 /* sec 1075 */
691 void box_end_(integer box_context)
692 {
693   pointer p;
694   pointer q;
695
696   if (box_context < box_flag)
697   {
698     if (cur_box != 0)
699     {
700       p = link(cur_box);
701       link(cur_box) = 0;
702       
703       while (p != 0)
704       {
705         q = p;
706         p = link(p);
707         
708         if (box_dir(q) == abs(direction))
709         {
710           list_ptr(q) = cur_box;
711           cur_box = q;
712           link(cur_box) = 0;
713         }
714         else
715         {
716           delete_glue_ref(space_ptr(q));
717           delete_glue_ref(xspace_ptr(q));
718           free_node(q, box_node_size);
719         }
720       }
721
722       if (box_dir(cur_box) != abs(direction))
723         cur_box = new_dir_node(cur_box,abs(direction));
724
725       shift_amount(cur_box) = box_context;
726
727       if (abs(mode) == vmode)
728       {
729         append_to_vlist(cur_box);
730
731         if (adjust_tail != 0)
732         {
733           if (adjust_head != adjust_tail)
734           {
735             link(tail) = link(adjust_head);
736             tail = adjust_tail;
737           }
738
739           adjust_tail = 0;
740         }
741
742         if (mode > 0)
743           build_page();
744       }
745       else
746       {
747         if (abs(mode) == hmode)
748           space_factor = 1000;
749         else
750         {
751           p = new_noad();
752           math_type(nucleus(p)) = sub_box;
753           info(nucleus(p)) = cur_box;
754           cur_box = p;
755         }
756
757         link(tail) = cur_box;
758         tail = cur_box;
759       }
760     }
761   }
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);
765     else
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)
769     {
770       do
771         {
772           get_x_token();
773         }
774       while(!((cur_cmd != spacer) && (cur_cmd != relax)));
775
776       if (((cur_cmd == hskip) && (abs(mode) != vmode)) || ((cur_cmd == vskip) && (abs(mode) == vmode)))
777       {
778         append_glue();
779         subtype(tail) = box_context - (leader_flag - a_leaders);
780         
781         if (type(cur_box) <= dir_node)
782         {
783           p = link(cur_box);
784           link(cur_box) = 0;
785           
786           while (p != 0)
787           {
788             q = p;
789             p = link(p);
790             
791             if (box_dir(q) == abs(direction))
792             {
793               list_ptr(q) = cur_box;
794               cur_box = q;
795               link(cur_box) = 0;
796             }
797             else
798             {
799               delete_glue_ref(space_ptr(q));
800               delete_glue_ref(xspace_ptr(q));
801               free_node(q, box_node_size);
802             }
803           }
804
805           if (box_dir(cur_box) != abs(direction))
806             cur_box = new_dir_node(cur_box,abs(direction));
807         }
808
809         leader_ptr(tail) = cur_box;
810       }
811       else
812       {
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.");
817         back_error();
818         flush_node_list(cur_box);
819       }
820     }
821     else
822       ship_out(cur_box);
823 }
824 /* sec 1079 */
825 void begin_box_(integer box_context)
826 {
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}
832   pointer p, q;
833   quarterword m;
834   halfword k;
835   eight_bits n;
836
837   switch(cur_chr)
838   {
839     case box_code:
840       {
841         scan_eight_bit_int();
842         cur_box = box(cur_val);
843         box(cur_val) = 0;
844       }
845       break;
846
847     case copy_code:
848       {
849         scan_eight_bit_int();
850         cur_box = copy_node_list(box(cur_val));
851       }
852       break;
853
854     case last_box_code:
855       {
856         cur_box = 0;
857
858         if (abs(mode) == mmode)
859         {
860           you_cant();
861           help1("Sorry; this \\lastbox will be void.");
862           error();
863         }
864         else if ((mode == vmode) && (head == cur_list.tail_field))
865         {
866           you_cant();
867           help2("Sorry...I usually can't take things from the current page.",
868               "This \\lastbox will therefore be void.");
869           error();
870         }
871         else
872         {
873           check_effective_tail(goto lab30);
874
875           if (!(is_char_node(tx) || (head != tx)))
876             if ((type(tail) == hlist_node) || (type(tail) == vlist_node) ||
877               (type(tail) == dir_node))
878             {
879               fetch_effective_tail(goto lab30);
880               cur_box = tx;
881               shift_amount(cur_box) = 0;
882               
883               if (type(cur_box) == dir_node)
884               {
885                 link(list_ptr(cur_box)) = cur_box;
886                 cur_box = list_ptr(cur_box);
887                 list_ptr(link(cur_box)) = 0;
888               }
889               else if (box_dir(cur_box) == dir_default)
890                 set_box_dir(cur_box, abs(direction));
891             }
892         }
893 lab30:;
894       }
895       break;
896
897     case vsplit_code:
898       {
899         scan_eight_bit_int();
900         n = cur_val;
901
902         if (!scan_keyword("to"))
903         {
904           print_err("Missing `to' inserted");
905           help2("I'm working on `\\vsplit<box number> to <dimen>';",
906               "will look for the <dimen> next.");
907           error();
908         }
909
910         scan_dimen(false, false, false);
911         cur_box = vsplit(n, cur_val);
912       }
913       break;
914
915     default:
916       {
917         k = cur_chr - vtop_code;
918         saved(0) = box_context;
919         a_dir = adjust_dir;
920
921         if (k == hmode)
922           if ((box_context < box_flag) && (abs(mode) == vmode))
923           {
924             a_dir = abs(direction);
925             scan_spec(adjust_hbox_group, true);
926           }
927           else
928             scan_spec(hbox_group, true);
929         else
930         {
931           if (k == vmode)
932             scan_spec(vbox_group, true);
933           else
934           {
935             scan_spec(vtop_group, true);
936             k = vmode;
937           }
938
939           normal_paragraph();
940         }
941
942         push_nest();
943         mode = - (integer) k;
944         adjust_dir = a_dir;
945
946         if (k == vmode)
947         {
948           prev_depth = ignore_depth;
949
950           if (every_vbox != 0)
951             begin_token_list(every_vbox, every_vbox_text);
952         }
953         else
954         {
955           space_factor = 1000;
956
957           if (every_hbox != 0)
958             begin_token_list(every_hbox, every_vbox_text);
959         }
960         return;
961       }
962       break;
963   }
964
965   box_end(box_context);
966 }
967 /* sec 1084 */
968 void scan_box_(integer box_context)
969 {
970   do
971     {
972       get_x_token(); 
973     }
974   while (!((cur_cmd != spacer) && (cur_cmd != relax)));
975
976   if (cur_cmd == make_box)
977   {
978     begin_box(box_context);
979   }
980   else if ((box_context >= leader_flag) && ((cur_cmd == hrule) || (cur_cmd == vrule)))
981   {
982     cur_box = scan_rule_spec();
983     box_end(box_context);
984   }
985   else
986   {
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.");
991     back_error();
992   }
993 }
994 /****************************************************************************/
995 void package_ (small_number);
996 /****************************************************************************/
997 /* sec 1091 */
998 small_number norm_min_ (integer h)
999 {
1000   if (h <= 0)
1001     return 1;
1002   else if (h >= 63)
1003     return 63;
1004   else
1005     return h;
1006 }
1007 /* sec 1091 */
1008 void new_graf_(boolean indented)
1009 {
1010   prev_graf = 0;
1011
1012   if ((mode == vmode) || (head != tail))
1013     tail_append(new_param_glue(par_skip_code));
1014
1015   push_nest();
1016   adjust_dir = abs(direction);
1017   mode = hmode;
1018   space_factor = 1000;
1019   set_cur_lang();
1020   clang = cur_lang;
1021   prev_graf =(norm_min(left_hyphen_min) * 64 + norm_min(right_hyphen_min)) * 65536L + cur_lang;
1022
1023   if (indented)
1024   {
1025     tail = new_null_box();
1026     link(head) = tail;
1027     width(tail) = par_indent;
1028   }
1029
1030   if (every_par != 0)
1031     begin_token_list(every_par, every_par_text);
1032
1033   if (nest_ptr == 1)
1034     build_page();
1035 }
1036 /* sec 1093 */
1037 void indent_in_hmode (void)
1038 {
1039   pointer p, q;
1040
1041   if (cur_chr > 0)
1042   {
1043     p = new_null_box();
1044     width(p) = par_indent;
1045
1046     if (abs(mode) == hmode)
1047       space_factor = 1000;
1048     else
1049     {
1050       q = new_noad();
1051       math_type(nucleus(q)) = sub_box;
1052       info(nucleus(q)) = p;
1053       p = q;
1054     }
1055
1056     tail_append(p);
1057   }
1058 }
1059 /* sec 1095 */
1060 void head_for_vmode (void)
1061 {
1062   if (mode < 0)
1063   {
1064     if (cur_cmd != hrule)
1065       off_save();
1066     else
1067     {
1068       print_err("You can't use `");
1069       print_esc("hrule");
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).");
1073       error();
1074     }
1075   }
1076   else
1077   {
1078     back_input();
1079     cur_tok = par_token;
1080     back_input();
1081     cur_input.index_field = inserted;
1082   }
1083 }
1084 /* sec 1096 */
1085 void end_graf (void)
1086 {
1087   if (mode == hmode)
1088   {
1089     if (head == tail)
1090       pop_nest();
1091     else
1092     {
1093       adjust_hlist(head, true);
1094       line_break(widow_penalty);
1095     }
1096
1097     normal_paragraph();
1098     error_count = 0;
1099   }
1100 }
1101 /* sec 1099 */
1102 void begin_insert_or_adjust (void)
1103 {
1104   if (cur_cmd == vadjust)
1105     cur_val = 255;
1106   else
1107   {
1108     scan_eight_bit_int();
1109
1110     if (cur_val == 255)
1111     {
1112       print_err("You can't ");
1113       print_esc("insert");
1114       print_int(255);
1115       help1("I'm changing to \\insert0; box 255 is special.");
1116       error();
1117       cur_val = 0;
1118     }
1119   }
1120
1121   saved(0) = cur_val;
1122   incr(save_ptr);
1123   new_save_level(insert_group);
1124   scan_left_brace();
1125   normal_paragraph();
1126   push_nest();
1127   mode = -vmode;
1128   direction = adjust_dir;
1129   prev_depth = ignore_depth;
1130 }
1131 /* sec 1101 */
1132 void make_mark (void)
1133 {
1134   pointer p;
1135
1136   p = scan_toks(false, true);
1137   p = get_node(small_node_size);
1138   type(p) = mark_node;
1139   subtype(p) = 0;
1140   mark_ptr(p) = def_ref;
1141   
1142   if (!is_char_node(tail) && (type(tail) == disp_node))
1143     prev_append(p);
1144   else
1145     tail_append(p);
1146 }
1147 /* sec 1103 */
1148 void append_penalty (void)
1149 {
1150   scan_int();
1151
1152   if (!is_char_node(tail) && (type(tail) == disp_node))
1153     prev_append(new_penalty(cur_val));
1154   else
1155     tail_append(new_penalty(cur_val));
1156
1157   if (mode == vmode)
1158     build_page();
1159 }
1160 /* sec 1105 */
1161 void delete_last (void)
1162 {
1163   pointer p, q;
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}
1168   quarterword m;
1169
1170   if ((mode == vmode) && (tail == head))
1171   {
1172     if ((cur_chr != glue_node) || (last_glue != max_halfword))
1173     {
1174       you_cant();
1175       help2("Sorry...I usually can't take things from the current page.",
1176           "Try `I\\vskip-\\lastskip' instead.");
1177
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.";
1182       error();
1183     }
1184   }
1185   else
1186   {
1187     check_effective_tail(return);
1188     
1189     if (!is_char_node(tx))
1190       if (type(tx) == cur_chr)
1191       {
1192         fetch_effective_tail(return);
1193         flush_node_list(tx);
1194       }
1195   }
1196 }
1197 /* sec 1110 */
1198 void unpackage (void)
1199 {
1200   pointer p;
1201   char c;
1202   scaled disp; // {displacement}
1203
1204   c = cur_chr;
1205   scan_eight_bit_int();
1206   p = box(cur_val);
1207
1208   if (p == 0)
1209     return;
1210
1211   if (type(p) == dir_node)
1212     p = list_ptr(p);
1213
1214   if ((abs(mode) == mmode) || ((abs(mode) == vmode) && (type(p) != vlist_node)) ||
1215     ((abs(mode) == hmode) && (type(p) != hlist_node)))
1216   {
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.");
1221     error();
1222     return;
1223   }
1224   
1225   switch (box_dir(p))
1226   {
1227     case dir_yoko:
1228     case dir_tate:
1229     case dir_dtou:
1230       if (abs(direction) != box_dir(p))
1231       {
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.");
1235         error();
1236         return;
1237       }
1238   }
1239   
1240   disp = 0;
1241
1242   if (c == copy_code)
1243     link(tail) = copy_node_list(list_ptr(p));
1244   else
1245   {
1246     if (type(box(cur_val)) == dir_node)
1247     {
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);
1251     }
1252
1253     link(tail) = list_ptr(p);
1254     box(cur_val) = 0;
1255     delete_glue_ref(space_ptr(p));
1256     delete_glue_ref(xspace_ptr(p));
1257     free_node(p, box_node_size);
1258   }
1259
1260   while (link(tail) != 0)
1261   {
1262     p = tail;
1263     tail = link(tail);
1264     
1265     if (!is_char_node(tail))
1266       switch (type(tail))
1267       {
1268         case glue_node:
1269           if ((subtype(tail) == kanji_skip_code + 1) ||
1270             (subtype(tail)=xkanji_skip_code+1))
1271           {
1272             link(p) = link(tail);
1273             delete_glue_ref(glue_ptr(tail));
1274             free_node(tail, small_node_size);
1275             tail = p;
1276           }
1277           break;
1278
1279         case penalty_node:
1280           if (subtype(tail) == widow_pena)
1281           {
1282             link(p) = link(tail);
1283             free_node(tail, small_node_size);
1284             tail = p;
1285           }
1286           break;
1287         
1288         case disp_node:
1289           {
1290             prev_disp = disp;
1291             disp = disp_dimen(tail);
1292             prev_node = p;
1293           }
1294           break;
1295     }
1296   }
1297 }
1298 /* sec 1113 */
1299 void append_italic_correction (void)
1300 {
1301   pointer p;
1302   internal_font_number f;
1303   pointer d; // {|disp_node|}
1304   
1305   if (tail != head)
1306   {
1307     if (!is_char_node(tail) && (type(tail) == disp_node))
1308     {
1309       d = tail;
1310       tail = prev_node;
1311     }
1312     else
1313       d = 0;
1314     
1315     if ((last_jchr != null) && (link(last_jchr) == tail) && (is_char_node(tail)))
1316       p = last_jchr;
1317     else if (is_char_node(tail))
1318       p = tail;
1319     else if (type(tail) == ligature_node)
1320       p = lig_char(tail);
1321     else
1322       return;
1323
1324     f = font(p);
1325     tail_append(new_kern(char_italic(f, char_info(f, character(p)))));
1326     subtype(tail) = ita_kern;
1327     
1328     if (d != 0)
1329     {
1330       prev_node = tail;
1331       tail_append(d);
1332     }
1333   }
1334 }
1335 /* sec 1117 */
1336 void append_discretionary (void)
1337 {
1338   integer c;
1339
1340   tail_append(new_disc());
1341
1342   if (cur_chr == 1)
1343   {
1344     c = hyphen_char[cur_font];
1345
1346     if (c >= 0)
1347       if (c < 256)
1348         pre_break(tail) = new_character(cur_font, c);
1349   }
1350   else
1351   {
1352     incr(save_ptr);
1353     saved(-1) = 0;
1354     new_save_level(disc_group);
1355     scan_left_brace();
1356     push_nest();
1357     mode = -hmode;
1358     space_factor = 1000;
1359   }
1360 }
1361 /* sec 1119 */
1362 void build_discretionary (void)
1363 {
1364   pointer p, q;
1365   integer n;
1366
1367   unsave();
1368   q = head;
1369   p = link(q);
1370   n = 0;
1371
1372   while (p != 0)
1373   {
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))
1379             {
1380               link(q) = link(p);
1381               free_node(p, small_node_size);
1382               p = q;
1383             }
1384             else
1385             {
1386               print_err("Improper discretionary list");
1387               help1("Discretionary lists must contain only boxes and kerns.");
1388               error();
1389               begin_diagnostic();
1390               print_nl("The following discretionary sublist has been deleted:");
1391               show_box(p);
1392               end_diagnostic(true);
1393               flush_node_list(p);
1394               link(q) = 0;
1395               goto lab30;
1396             }
1397
1398     q = p;
1399     p = link(q);
1400     incr(n);
1401   }
1402
1403 lab30:
1404   p = link(head);
1405   pop_nest();
1406
1407   switch (saved(-1))
1408   {
1409     case 0:
1410       pre_break(tail) = p;
1411       break;
1412
1413     case 1:
1414       post_break(tail) = p;
1415       break;
1416
1417     case 2:
1418       {
1419         if ((n > 0) && (abs(mode) == mmode))
1420         {
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.");
1425           flush_node_list(p);
1426           n = 0;
1427           error();
1428         }
1429         else
1430           link(tail) = p;
1431
1432         if (n <= max_quarterword)
1433           replace_count(tail) = n;
1434         else
1435         {
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?");
1439           error();
1440         }
1441
1442         if (n > 0)
1443           tail = q;
1444
1445         decr(save_ptr);
1446         prev_node = tail;
1447         tail_append(get_node(small_node_size));
1448         type(tail) = disp_node;
1449         disp_dimen(tail) = 0;
1450         prev_disp = 0;
1451         return;
1452       }
1453       break;
1454   }
1455
1456   incr(saved(-1));
1457   new_save_level(disc_group);
1458   scan_left_brace();
1459   push_nest();
1460   mode = -hmode;
1461   space_factor = 1000;
1462 }
1463 /* sec 1123 */
1464 void make_accent (void)
1465 {
1466   real s, t;
1467   scaled disp; // {displacement}
1468   KANJI_code cx; // {temporary register for KANJI}
1469   pointer p, q, r;
1470   internal_font_number f;
1471   scaled a, h, x, w, delta;
1472   four_quarters i;
1473
1474   scan_char_num();
1475
1476   if (!is_char_ascii(cur_val))
1477   {
1478     cx = cur_val;
1479     
1480     if (direction == dir_tate)
1481       f = cur_tfont;
1482     else
1483       f = cur_jfont;
1484
1485     p = new_character(f, get_jfm_pos(cx, f));
1486     
1487     if (p != 0)
1488     {
1489       link(p) = get_avail();
1490       info(link(p)) = cx;
1491     }
1492   }
1493   else
1494   {
1495     f = cur_font;
1496     p = new_character(f,cur_val);
1497   }
1498
1499   if (p != 0)
1500   {
1501     x = x_height(f);
1502     s = slant(f) / ((double) 65536.0);
1503     a = char_width(f, char_info(f, character(p)));
1504     do_assignments();
1505     q = 0;
1506     f = cur_font;
1507     cx = empty;
1508     
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))
1512     {
1513       if (direction == dir_tate)
1514         f = cur_tfont;
1515       else
1516         f = cur_jfont;
1517       
1518       cx = cur_chr;
1519     }
1520     else if (cur_cmd == char_given)
1521       if (is_char_ascii(cur_chr))
1522         q = new_character(f, cur_chr);
1523       else
1524       {
1525         if (direction == dir_tate)
1526           f = cur_tfont;
1527         else
1528           f = cur_jfont;
1529         
1530         cx = cur_chr;
1531       }
1532     else if (cur_cmd == char_num)
1533     {
1534       scan_char_num();
1535       
1536       if (is_char_ascii(cur_val))
1537         q = new_character(f, cur_val);
1538       else
1539       {
1540         if (direction == dir_tate)
1541           f = cur_tfont;
1542         else
1543           f = cur_jfont;
1544         
1545         cx = cur_val;
1546       }
1547     }
1548     else
1549       back_input();
1550     
1551     if (direction == dir_tate)
1552     {
1553       if (font_dir[f] == dir_tate)
1554         disp = 0;
1555       else if (font_dir[f] == dir_yoko)
1556         disp = t_baseline_shift - y_baseline_shift;
1557       else
1558         disp = t_baseline_shift;
1559     }
1560     else
1561     {
1562       if (font_dir[f] == dir_yoko)
1563         disp = 0;
1564       else if (font_dir[f] == dir_tate)
1565         disp = y_baseline_shift - t_baseline_shift;
1566       else
1567         disp = y_baseline_shift;
1568     }
1569     
1570     append_disp_node_at_begin();
1571     
1572     if (cx != empty)
1573     {
1574       q = new_character(f, get_jfm_pos(cx, f));
1575       link(q) = get_avail();
1576       info(link(q)) = cx;
1577       last_jchr = q;
1578     }
1579
1580     if (q != 0)
1581     {
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));
1586
1587       if (h != x)
1588       {
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);
1595         p = hpack(p, 0, 1);
1596         shift_amount(p) = x - h;
1597       }
1598
1599       delta = round((w - a) / ((double) 2.0)+ h * t - x * s);
1600       r = new_kern(delta);
1601       subtype(r) = acc_kern;
1602       link(tail) = r;
1603       link(r) = p;
1604       tail = new_kern(- (integer) a - delta);
1605       subtype(tail) = acc_kern;
1606       
1607       if (h == x)
1608       {
1609         if (font_dir[font(p)] != dir_default)
1610           link(link(p)) = tail;
1611         else
1612           link(p) = tail;
1613       }
1614       else
1615         link(p) = tail;
1616
1617       p = q;
1618     }
1619
1620     link(tail) = p;
1621     if (link(p) != 0)
1622       tail = link(p);
1623     else
1624       tail = p;
1625     append_disp_node_at_end();
1626     space_factor = 1000;
1627   }
1628 }
1629 /* sec 1127 */
1630 void align_error (void)
1631 {
1632   if (abs(align_state) > 2)
1633   {
1634     print_err("Misplaced ");
1635     print_cmd_chr(cur_cmd, cur_chr);
1636
1637     if (cur_tok == tab_token + '&')
1638     {
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.");
1645     }
1646     else
1647     {
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.");
1653     }
1654
1655     error();
1656   }
1657   else
1658   {
1659     back_input();
1660
1661     if (align_state < 0)
1662     {
1663       print_err("Missing { inserted");
1664       incr(align_state);
1665       cur_tok = left_brace_token + '{';
1666     }
1667     else
1668     {
1669       print_err("Missing } inserted");
1670       decr(align_state);
1671       cur_tok = right_brace_token + '}';
1672     }
1673
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.");
1677     ins_error();
1678   }
1679 }
1680 /* sec 1129 */
1681 void noalign_error (void)
1682 {
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.");
1687   error();
1688 }
1689 /* sec 1129 */
1690 void omit_error (void)
1691 {
1692   print_err("Misplaced ");
1693   print_esc("omit");
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.");
1696   error();
1697 }
1698 /* sec 1131 */
1699 void do_endv (void)
1700 {
1701   base_ptr = input_ptr;
1702   input_stack[base_ptr] = cur_input;
1703
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))
1707     decr(base_ptr);
1708
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)");
1713
1714   if (cur_group == align_group)
1715   {
1716     end_graf();
1717
1718     if (fin_col ())
1719       fin_row();
1720   }
1721   else
1722     off_save();
1723 }
1724 /* sec 1135 */
1725 void cs_error (void)
1726 {
1727   print_err("Extra ");
1728   print_esc("endcsname");
1729   help1("I'm ignoring this, since I wasn't doing a \\csname."); 
1730   error();
1731 }
1732 /* sec 1136 */
1733 void push_math_(group_code c)
1734 {
1735   push_nest();
1736   mode = -mmode;
1737   incompleat_noad = 0;
1738   new_save_level(c);
1739 }
1740 /* sec 1138 */
1741 void init_math (void)
1742 {
1743   scaled w;
1744   scaled l;
1745   scaled s;
1746   pointer p;
1747   pointer q;
1748   internal_font_number f;
1749   integer n;
1750   scaled v;
1751   scaled d;
1752
1753   get_token();
1754
1755   if ((cur_cmd == math_shift) && (mode > 0))
1756   {
1757     if (head == tail)
1758     {
1759       pop_nest();
1760       w = -max_dimen; /* - (2^30 - 1) */
1761     }
1762     else
1763     {
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);
1769
1770       while (p != 0)
1771       {
1772 lab21:
1773         if ((p >= hi_mem_min))
1774         {
1775           f = font(p);
1776           d = char_width(f, char_info(f, character(p)));
1777           if (font_dir[f] != dir_default)
1778             p = link(p);
1779           goto lab40;
1780         }
1781
1782         switch (type(p))
1783         {
1784           case hlist_node:
1785           case vlist_node:
1786           case dir_node:
1787           case rule_node:
1788             {
1789               d = width(p);
1790               goto lab40;
1791             }
1792             break;
1793
1794           case ligature_node:
1795             {
1796               mem[lig_trick] = mem[lig_char(p)];
1797               link(lig_trick) = link(p);
1798               p = lig_trick;
1799               goto lab21;
1800             }
1801             break;
1802
1803           case kern_node:
1804           case math_node:
1805             d = width(p);
1806             break;
1807
1808           case glue_node:
1809             {
1810               q = glue_ptr(p);
1811               d = width(q);
1812
1813               if (glue_sign(just_box) == stretching)
1814               {
1815                 if ((glue_order(just_box) == stretch_order(q)) && (stretch(q) != 0))
1816                   v = max_dimen;  /* - (2^30 - 1) */
1817               }
1818               else if (glue_sign(just_box) == shrinking)
1819               {
1820                 if ((glue_order(just_box) == shrink_order(q)) && (shrink(q) != 0))
1821                   v = max_dimen;  /* - (2^30 - 1) */
1822               }
1823
1824               if (subtype(p) >= a_leaders)
1825                 goto lab40;
1826             }
1827             break;
1828
1829           case whatsit_node:
1830             d = 0;
1831             break;
1832
1833           default:
1834             d = 0;
1835             break;
1836         }
1837
1838         if (v < max_dimen) /* - (2^30 - 1) */
1839           v = v + d;
1840
1841         goto lab45;
1842 lab40:
1843         if (v < max_dimen) /* - (2^30 - 1) */
1844         {
1845           v = v + d;
1846           w = v;
1847         }
1848         else
1849         {
1850           w = max_dimen;  /* - (2^30 - 1) */
1851           goto lab30;
1852         }
1853 lab45:
1854         p = link(p);
1855       }
1856 lab30:;
1857     }
1858
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)))
1862       {
1863         l = hsize - abs(hang_indent);
1864
1865         if (hang_indent > 0)
1866           s = hang_indent;
1867         else
1868           s = 0;
1869       }
1870       else
1871       {
1872         l = hsize;
1873         s = 0;
1874       }
1875     else
1876     {
1877       n = info(par_shape_ptr);
1878
1879       if (prev_graf + 2 >= n)
1880         p = par_shape_ptr + 2 * n;
1881       else
1882         p = par_shape_ptr + 2 *(prev_graf + 2);
1883
1884       s = mem[p - 1].cint;
1885       l = mem[p].cint;
1886     }
1887
1888     push_math(math_shift_group);
1889     mode = mmode;
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);
1894
1895     if (every_display != 0)
1896       begin_token_list(every_display, every_display_text);
1897
1898     if (nest_ptr == 1)
1899     {
1900       build_page();
1901     }
1902   }
1903   else
1904   {
1905     back_input();
1906
1907     {
1908       push_math(math_shift_group);
1909       eq_word_define(int_base + cur_fam_code, -1);
1910
1911       if (every_math != 0)
1912         begin_token_list(every_math, every_math_text);
1913     }
1914   }
1915
1916   direction = -abs(direction);
1917 }
1918 /* sec 1142 */
1919 void start_eq_no (void)
1920 {
1921   saved(0) = cur_chr;
1922   incr(save_ptr);
1923
1924   {
1925     push_math(math_shift_group);
1926     eq_word_define(int_base + cur_fam_code, -1);
1927
1928     if (every_math != 0)
1929       begin_token_list(every_math, every_math_text);
1930   }
1931 }
1932 /* sec 1151 */
1933 void scan_math_(pointer p, pointer q)
1934 {
1935   integer c;
1936   KANJI_code cx;
1937
1938   cx = 0;
1939 lab20:
1940   do
1941     {
1942       get_x_token();
1943     }
1944   while(!((cur_cmd != spacer) && (cur_cmd != relax)));
1945
1946 lab21:
1947   switch (cur_cmd)
1948   {
1949     case letter:
1950     case other_char:
1951     case char_given:
1952       {
1953         c = math_code(cur_chr);
1954
1955         if (is_char_ascii(cur_chr) || (cur_chr == 256))
1956         {
1957           c = (math_code(cur_chr));
1958           
1959           if (c == 32768L)
1960           {
1961             {
1962               cur_cs = cur_chr + active_base;
1963               cur_cmd = eq_type(cur_cs);
1964               cur_chr = equiv(cur_cs);
1965               x_token();
1966               back_input();
1967             }
1968
1969             goto lab20;
1970           }
1971         }
1972         else
1973           cx = cur_chr;
1974       }
1975       break;
1976
1977     case kanji:
1978     case kana:
1979     case other_kchar:
1980       cx = cur_chr;
1981       break;
1982
1983     case char_num:
1984       {
1985         scan_char_num();
1986         cur_chr = cur_val;
1987         cur_cmd = char_given;
1988         goto lab21;
1989       }
1990       break;
1991
1992     case math_char_num:
1993       {
1994         scan_fifteen_bit_int();
1995         c = cur_val;
1996       }
1997       break;
1998
1999     case math_given:
2000       c = cur_chr;
2001       break;
2002
2003     case delim_num:
2004       {
2005         scan_twenty_seven_bit_int();
2006         c = cur_val / 4096;
2007       }
2008       break;
2009
2010     default:
2011       {
2012         back_input();
2013         scan_left_brace();
2014         saved(0) = p;
2015         incr(save_ptr);
2016         push_math(math_group);
2017         return;
2018       }
2019       break;
2020   }
2021
2022   if (cx == 0)
2023   {
2024     math_type(p) = math_char;
2025     character(p) = (c % 256);
2026     
2027     if ((c >= var_code) && ((cur_fam >= 0) && (cur_fam < 16)))
2028       fam(p) = cur_fam;
2029     else
2030       fam(p) = (c / 256) % 16;
2031     
2032     if (font_dir[fam_fnt(fam(p) + cur_size)] != dir_default)
2033     {
2034       print_err("Not one-byte family");
2035       help1("IGNORE.");
2036       error();
2037     }
2038   }
2039   else
2040   {
2041     if (q == 0)
2042     {
2043       math_type(p) = sub_mlist;
2044       info(p) = new_noad();
2045       p = nucleus(info(p));
2046       q = kcode_noad_nucleus(p);
2047     }
2048
2049     math_type(p) = math_jchar;
2050     fam(p) = cur_jfam;
2051     character(p) = (0);
2052     math_kcode(p - 1) = (cx);
2053     
2054     if (font_dir[fam_fnt(fam(p) + cur_size)] == dir_default)
2055     {
2056       print_err("Not two-byte family");
2057       help1("IGNORE.");
2058       error();
2059     }
2060   }
2061 }
2062 /* sec 1155 */
2063 void set_math_char_(integer c)
2064 {
2065   pointer p;
2066
2067   if (c >= 32768L)
2068   {
2069     cur_cs = cur_chr + active_base;
2070     cur_cmd = eq_type(cur_cs);
2071     cur_chr = equiv(cur_cs);
2072     x_token();
2073     back_input();
2074   }
2075   else
2076   {
2077     p = new_noad();
2078     math_type(nucleus(p)) = math_char;
2079     character(nucleus(p)) = c % 256;
2080     fam(nucleus(p)) = (c / 256) % 16;
2081
2082     if (c >= var_code)
2083     {
2084       if (((cur_fam >= 0) && (cur_fam < 16)))
2085         fam(nucleus(p)) = cur_fam;
2086
2087       type(p) = ord_noad;
2088     }
2089     else
2090       type(p) = ord_noad + (c / 4096);
2091
2092     link(tail) = p;
2093     tail = p;
2094     
2095     if (font_dir[fam_fnt(fam(nucleus(p)) + cur_size)] != dir_default)
2096     {
2097       print_err("Not one-byte family");
2098       help1("IGNORE.");
2099       error();
2100     }
2101
2102     inhibit_glue_flag = false;
2103   }
2104 }
2105 /* sec 1159 */
2106 void math_limit_switch (void)
2107 {
2108   if (head != tail)
2109     if (type(tail) == op_noad)
2110     {
2111       subtype(tail) = cur_chr;
2112       return;
2113     }
2114
2115   print_err("Limit controls must follow a math operator");
2116   help1("I'm ignoring this misplaced \\limits or \\nolimits command.");
2117   error();
2118 }
2119 /* sec 1160 */
2120 void scan_delimiter_(pointer p, boolean r)
2121 {
2122   if (r)
2123   {
2124     scan_twenty_seven_bit_int();
2125   }
2126   else
2127   {
2128     do
2129       {
2130         get_x_token();
2131       }
2132     while (!((cur_cmd != spacer) && (cur_cmd != relax)));
2133
2134     switch (cur_cmd)
2135     {
2136       case letter:
2137       case other_char:
2138         cur_val = del_code(cur_chr);
2139         break;
2140
2141       case delim_num:
2142         scan_twenty_seven_bit_int();
2143         break;
2144
2145       default:
2146         cur_val = -1;
2147         break;
2148     }
2149   }
2150
2151   if (cur_val < 0)
2152   {
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>'.");
2160     back_error();
2161     cur_val = 0;
2162   }
2163
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;
2168 }
2169 /* sec 1163 */
2170 void math_radical (void)
2171 {
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));
2180 }
2181 /* sec 1165 */
2182 void math_ac (void)
2183 {
2184   if (cur_cmd == accent)
2185   {
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.)");
2191     error();
2192   }
2193
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;
2203
2204   if ((cur_val >= var_code) && ((cur_fam >= 0) && (cur_fam < 16)))
2205     fam(accent_chr(tail)) = cur_fam;
2206   else
2207     fam(accent_chr(tail)) = (cur_val / 256) % 16;
2208
2209   scan_math(nucleus(tail), kcode_noad(tail));
2210 }
2211 /* sec 1172 */
2212 void append_choices (void)
2213 {
2214   tail_append(new_choice());
2215   incr(save_ptr);
2216   saved(-1) = 0;
2217   push_math(math_choice_group);
2218   scan_left_brace();
2219 }
2220 /* sec 1184 */
2221 halfword fin_mlist_(halfword p)
2222 {
2223   pointer q;
2224
2225   if (incompleat_noad != 0)
2226   {
2227     math_type(denominator(incompleat_noad)) = sub_mlist;
2228     info(denominator(incompleat_noad)) = link(head);
2229
2230     if (p == 0)
2231       q = incompleat_noad;
2232     else
2233     {
2234       q = info(numerator(incompleat_noad));
2235
2236       if (type(q) != left_noad)
2237       {
2238         confusion("right");
2239         return 0;       // abort_flag set
2240       }
2241
2242       info(numerator(incompleat_noad)) = link(q);
2243       link(q) = incompleat_noad;
2244       link(incompleat_noad) = p;
2245     }
2246   }
2247   else
2248   {
2249     link(tail) = p;
2250     q = link(head);
2251   }
2252   pop_nest();
2253
2254   return q;
2255 }
2256 /* sec 1174 */
2257 void build_choices (void)
2258 {
2259   pointer p;
2260
2261   unsave();
2262   p = fin_mlist(0);
2263
2264   switch (saved(-1))
2265   {
2266     case 0:
2267       display_mlist(tail) = p;
2268       break;
2269
2270     case 1:
2271       text_mlist(tail) = p;
2272       break;
2273
2274     case 2:
2275       script_mlist(tail) = p;
2276       break;
2277
2278     case 3:
2279       {
2280         script_script_mlist(tail) = p;
2281         decr(save_ptr);
2282         return;
2283       }
2284       break;
2285   }
2286
2287   incr(saved(-1));
2288   push_math(math_choice_group);
2289   scan_left_brace();
2290 }
2291 /* sec 1176 */
2292 void sub_sup (void)
2293 {
2294 /*  small_number t; */
2295   int t; /* 95/Jan/7 */
2296   pointer p;
2297
2298   t = 0;
2299   p = 0;
2300   inhibit_glue_flag = false;
2301
2302   if (tail != head)
2303     if (script_allowed(tail))
2304     {
2305       p = supscr(tail) + cur_cmd - sup_mark;
2306       t = math_type(p);
2307     }
2308
2309   if ((p == 0) || (t != 0))
2310   {
2311     tail_append(new_noad());
2312     p = supscr(tail) + cur_cmd - sup_mark;
2313
2314     if (t != 0)
2315     {
2316       if (cur_cmd == sup_mark)
2317       {
2318         print_err("Double superscript");
2319         help1("I treat `x^1^2' essentially like `x^1{}^2'.");
2320       }
2321       else
2322       {
2323         print_err("Double subscript");
2324         help1("I treat `x_1_2' essentially like `x_1{}_2'.");
2325       }
2326       error();
2327     }
2328   }
2329   scan_math(p, 0);
2330 }
2331 /* sec 1086 */
2332 void package_(small_number c)
2333 {
2334   scaled h;
2335   pointer p;
2336   scaled d;
2337
2338   d = box_max_depth;
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;
2343   else
2344     cur_kanji_skip = zero_glue;
2345   if (auto_xspacing > 0)
2346     cur_xkanji_skip = xkanji_skip;
2347   else
2348     cur_xkanji_skip = zero_glue;
2349   add_glue_ref(cur_kanji_skip);
2350   add_glue_ref(cur_xkanji_skip);
2351   unsave();
2352   save_ptr = save_ptr - 3;
2353
2354   if (mode == -hmode)
2355   {
2356     cur_box = hpack(link(head), saved(2), saved(1));
2357     set_box_dir(cur_box, abs(direction));
2358     pop_nest();
2359   }
2360   else
2361   {
2362     cur_box = vpackage(link(head), saved(2), saved(1), d);
2363     set_box_dir(cur_box, abs(direction));
2364     pop_nest();
2365
2366     if (c == vtop_code)
2367     {
2368       h = 0;
2369       p = list_ptr(cur_box);
2370
2371       if (p != 0)
2372         if (type(p) <= rule_node)
2373           h = height(p);
2374
2375       depth(cur_box) = depth(cur_box) - h + height(cur_box);
2376       height(cur_box) = h;
2377     }
2378   }
2379
2380   box_end(saved(0));
2381 }