OSDN Git Service

version 2.3.0-final.
[putex/putex.git] / src / texsourc / tex7.c
1 /*\r
2    Copyright 2014 Clerk Ma\r
3 \r
4    This program is free software; you can redistribute it and/or modify\r
5    it under the terms of the GNU General Public License as published by\r
6    the Free Software Foundation; either version 2 of the License, or\r
7    (at your option) any later version.\r
8 \r
9    This program is distributed in the hope that it will be useful, but\r
10    WITHOUT ANY WARRANTY; without even the implied warranty of\r
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
12    General Public License for more details.\r
13 \r
14    You should have received a copy of the GNU General Public License\r
15    along with this program; if not, write to the Free Software\r
16    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\r
17    02110-1301 USA.\r
18 */\r
19 \r
20 #define EXTERN extern\r
21 #include "yandytex.h"\r
22 \r
23 /* sec 0994 */\r
24 void build_page (void)\r
25 {\r
26   pointer p;\r
27   pointer q, r;\r
28   integer b, c;\r
29   integer pi;\r
30   /* unsigned char n; */\r
31   unsigned int n;\r
32   scaled delta, h, w;\r
33 \r
34   if ((link(contrib_head) == 0) || output_active)\r
35     return;\r
36 \r
37   do\r
38     {\r
39 continu:\r
40       p = link(contrib_head);\r
41 \r
42       if (last_glue != max_halfword)\r
43         delete_glue_ref(last_glue);\r
44 \r
45       last_penalty = 0;\r
46       last_kern = 0;\r
47 \r
48       if (type(p) == glue_node)\r
49       {\r
50         last_glue = glue_ptr(p);\r
51         add_glue_ref(last_glue);\r
52       }\r
53       else\r
54       {\r
55         last_glue = max_halfword;\r
56 \r
57         if (type(p) == penalty_node)\r
58           last_penalty = penalty(p);\r
59         else if (type(p) == kern_node)\r
60           last_kern = width(p);\r
61       }\r
62 \r
63       switch (type(p))\r
64       {\r
65         case hlist_node:\r
66         case vlist_node:\r
67         case rule_node:\r
68           if (page_contents < box_there)\r
69           {\r
70             if (page_contents == 0)\r
71               freeze_page_specs(box_there);\r
72             else\r
73               page_contents = box_there;\r
74 \r
75             q = new_skip_param(top_skip_code);\r
76 \r
77             if (width(temp_ptr) > height(p))\r
78               width(temp_ptr) = width(temp_ptr) - height(p);\r
79             else\r
80               width(temp_ptr) = 0;\r
81 \r
82             link(q) = p;\r
83             link(contrib_head) = q;\r
84             goto continu;\r
85           }\r
86           else\r
87           {\r
88             page_total = page_total + page_depth + height(p);\r
89             page_depth = depth(p);\r
90             goto contribute;\r
91           }\r
92           break;\r
93 \r
94         case whatsit_node:\r
95           goto contribute;\r
96           break;\r
97 \r
98         case glue_node:\r
99           if (page_contents < box_there)\r
100             goto done1;\r
101           else if (precedes_break(page_tail))\r
102             pi = 0;\r
103           else\r
104             goto update_heights;\r
105           break;\r
106 \r
107         case kern_node:\r
108           if (page_contents < box_there)\r
109             goto done1;\r
110           else if (link(p) == 0)\r
111             return;\r
112           else if (type(link(p)) == glue_node)\r
113             pi = 0;\r
114           else\r
115             goto update_heights;\r
116           break;\r
117 \r
118         case penalty_node:\r
119           if (page_contents < box_there)\r
120             goto done1;\r
121           else\r
122             pi = penalty(p);\r
123           break;\r
124 \r
125         case mark_node:\r
126           goto contribute;\r
127           break;\r
128 \r
129         case ins_node:\r
130           {\r
131             if (page_contents == 0)\r
132               freeze_page_specs(inserts_only);\r
133 \r
134             n = subtype(p);\r
135             r = page_ins_head;\r
136 \r
137             while (n >= subtype(link(r)))\r
138               r = link(r);\r
139 \r
140             n = n;\r
141 \r
142             if (subtype(r) != n)\r
143             {\r
144               q = get_node(page_ins_node_size);\r
145               link(q) = link(r);\r
146               link(r) = q;\r
147               r = q;\r
148               subtype(r) = n;\r
149               type(r) = inserting;\r
150               ensure_vbox(n);\r
151 \r
152               if (box(n) == 0)\r
153                 height(r) = 0;\r
154               else\r
155                 height(r) = height(box(n)) + depth(box(n));\r
156 \r
157               best_ins_ptr(r) = 0;\r
158               q = skip(n);\r
159 \r
160               if (count(n) == 1000)\r
161                 h = height(r);\r
162               else\r
163                 h = x_over_n(height(r), 1000) * count(n);\r
164 \r
165               page_goal = page_goal - h - width(q);\r
166               page_so_far[2 + stretch_order(q)] = page_so_far[2 + stretch_order(q)] + stretch(q);\r
167               page_shrink = page_shrink + shrink(q);\r
168 \r
169               if ((shrink_order(q) != normal) && (shrink(q) != 0))\r
170               {\r
171                 print_err("Infinite glue shrinkage inserted from ");\r
172                 print_esc("skip");\r
173                 print_int(n);\r
174                 help3("The correction glue for page breaking with insertions",\r
175                     "must have finite shrinkability. But you may proceed,",\r
176                     "since the offensive shrinkability has been made finite.");\r
177                 error();\r
178               }\r
179             }\r
180 \r
181             if (type(r) == split_up)\r
182               insert_penalties = insert_penalties + float_cost(p);\r
183             else\r
184             {\r
185               last_ins_ptr(r) = p;\r
186               delta = page_goal - page_total - page_depth + page_shrink;\r
187 \r
188               if (count(n) == 1000)\r
189                 h = height(p);\r
190               else\r
191                 h = x_over_n(height(p), 1000) * count(n);\r
192 \r
193               if (((h <= 0) || (h <= delta)) && (height(p) + height(r) <= dimen(n)))\r
194               {\r
195                 page_goal = page_goal - h;\r
196                 height(r) = height(r) + height(p);\r
197               }\r
198               else\r
199               {\r
200                 if (count(n) <= 0)\r
201                   w = max_dimen;\r
202                 else\r
203                 {\r
204                   w = page_goal - page_total - page_depth;\r
205 \r
206                   if (count(n) != 1000)\r
207                     w = x_over_n(w, count(n)) * 1000;\r
208                 }\r
209 \r
210                 if (w > dimen(n) - height(r))\r
211                   w = dimen(n) - height(r);\r
212 \r
213                 q = vert_break(ins_ptr(p), w, depth(p));\r
214                 height(r) = height(r) + best_height_plus_depth;\r
215 #ifdef STAT\r
216                 if (tracing_pages > 0)\r
217                 {\r
218                   begin_diagnostic();\r
219                   print_nl("% split");\r
220                   print_int(n);\r
221                   prints(" to");\r
222                   print_scaled(w);\r
223                   print_char(',');\r
224                   print_scaled(best_height_plus_depth);\r
225                   prints(" p=");\r
226 \r
227                   if (q == 0)\r
228                     print_int(eject_penalty);\r
229                   else if (type(q) == penalty_node)\r
230                     print_int(penalty(q));\r
231                   else\r
232                     print_char('0');\r
233 \r
234                   end_diagnostic(false);\r
235                 }\r
236 #endif\r
237                 if (count(n) != 1000)\r
238                   best_height_plus_depth = x_over_n(best_height_plus_depth, 1000) * count(n);\r
239 \r
240                 page_goal = page_goal - best_height_plus_depth;\r
241                 type(r) = split_up;\r
242                 broken_ptr(r) = q;\r
243                 broken_ins(r) = p;\r
244 \r
245                 if (q == 0)\r
246                   insert_penalties = insert_penalties + (eject_penalty);\r
247                 else if (type(q) == penalty_node)\r
248                   insert_penalties = insert_penalties + penalty(q);\r
249               }\r
250             }\r
251             goto contribute;\r
252           }\r
253           break;\r
254 \r
255         default:\r
256           {\r
257             confusion("page");\r
258             return;\r
259           }\r
260           break;\r
261       }\r
262 \r
263       if (pi < inf_penalty)\r
264       {\r
265         if (page_total < page_goal)\r
266           if ((page_so_far[3] != 0) || (page_so_far[4] != 0) || (page_so_far[5] != 0))\r
267             b = 0;\r
268           else\r
269             b = badness(page_goal - page_total, page_so_far[2]);\r
270         else if (page_total - page_goal > page_shrink)\r
271           b = awful_bad;\r
272         else\r
273           b = badness(page_total - page_goal, page_shrink);\r
274   \r
275         if (b < awful_bad)\r
276           if (pi <= eject_penalty)\r
277             c = pi; \r
278           else if (b < inf_bad)\r
279             c = b + pi + insert_penalties;\r
280           else\r
281             c = deplorable;\r
282         else\r
283           c = b;\r
284 \r
285         if (insert_penalties >= 10000)\r
286           c = awful_bad;\r
287 \r
288 #ifdef STAT\r
289         if (tracing_pages > 0)\r
290         {\r
291           begin_diagnostic();\r
292           print_nl("%");\r
293           prints(" t=");\r
294           print_totals();\r
295           prints(" g=");\r
296           print_scaled(page_goal);\r
297           prints(" b=");\r
298 \r
299           if (b == awful_bad)\r
300             print_char('*');\r
301           else\r
302             print_int(b);\r
303 \r
304           prints(" p=");\r
305           print_int(pi);\r
306           prints(" c=");\r
307 \r
308           if (c == awful_bad)\r
309             print_char('*');\r
310           else\r
311             print_int(c);\r
312 \r
313           if (c <= least_page_cost)\r
314             print_char('#');\r
315 \r
316           end_diagnostic(false);\r
317         }\r
318 #endif\r
319 \r
320         if (c <= least_page_cost)\r
321         {\r
322           best_page_break = p;\r
323           best_size = page_goal;\r
324           least_page_cost = c;\r
325           r = link(page_ins_head);\r
326 \r
327           while (r != page_ins_head)\r
328           {\r
329             best_ins_ptr(r) = last_ins_ptr(r);\r
330             r = link(r);\r
331           }\r
332         }\r
333 \r
334         if ((c == awful_bad) || (pi <= eject_penalty))\r
335         {\r
336           fire_up(p);\r
337 \r
338           if (output_active)\r
339             return;\r
340 \r
341           goto done;\r
342         }\r
343       }\r
344 \r
345       if ((type(p) < glue_node) || (type(p) > kern_node))\r
346         goto contribute;\r
347 \r
348 update_heights:\r
349       if (type(p) == kern_node)\r
350         q = p;\r
351       else\r
352       {\r
353         q = glue_ptr(p);\r
354         page_so_far[2 + stretch_order(q)] = page_so_far[2 + stretch_order(q)] + stretch(q);\r
355         page_shrink = page_shrink + shrink(q);\r
356 \r
357         if ((shrink_order(q) != normal) && (shrink(q) != 0))\r
358         {\r
359           print_err("Infinite glue shrinkage found on current page");\r
360           help4("The page about to be output contains some infinitely",\r
361             "shrinkable glue, e.g., `\\vss' or `\\vskip 0pt minus 1fil'.",\r
362             "Such glue doesn't belong there; but you can safely proceed,",\r
363             "since the offensive shrinkability has been made finite.");\r
364           error();\r
365           r = new_spec(q);\r
366           shrink_order(r) = normal;\r
367           delete_glue_ref(q);\r
368           glue_ptr(p) = r;\r
369           q = r;\r
370         }\r
371       }\r
372 \r
373       page_total = page_total + page_depth + width(q);\r
374       page_depth = 0;\r
375 \r
376 contribute:\r
377       if (page_depth > page_max_depth)\r
378       {\r
379         page_total = page_total + page_depth - page_max_depth;\r
380         page_depth = page_max_depth;\r
381       }\r
382 \r
383       link(page_tail) = p;\r
384       page_tail = p;\r
385       link(contrib_head) = link(p);\r
386       link(p) = 0;\r
387       goto done;\r
388 \r
389 done1:\r
390       link(contrib_head) = link(p);\r
391       link(p) = 0;\r
392       flush_node_list(p);\r
393 done:;\r
394     }\r
395   while (!(link(contrib_head) == 0));\r
396 \r
397   if (nest_ptr == 0)\r
398     tail = contrib_head;\r
399   else\r
400     nest[0].tail_field = contrib_head;\r
401\r
402 /* sec 1043 */\r
403 void app_space (void)\r
404 {\r
405   pointer q;\r
406 \r
407   if ((space_factor >= 2000) && (xspace_skip != zero_glue))\r
408     q = new_param_glue(xspace_skip_code);\r
409   else\r
410   {\r
411     if (space_skip != zero_glue)\r
412       main_p = space_skip;\r
413     else\r
414     {\r
415       main_p = font_glue[cur_font];\r
416 \r
417       if (main_p == 0)\r
418       {\r
419         main_p = new_spec(zero_glue);\r
420         main_k = param_base[cur_font] + space_code;\r
421         width(main_p) = font_info[main_k].cint;\r
422         stretch(main_p) = font_info[main_k + 1].cint;\r
423         shrink(main_p) = font_info[main_k + 2].cint;\r
424         font_glue[cur_font] = main_p;\r
425       }\r
426     }\r
427 \r
428     main_p = new_spec(main_p);\r
429 \r
430     if (space_factor >= 2000)\r
431       width(main_p) = width(main_p) + extra_space(cur_font);\r
432 \r
433     stretch(main_p) = xn_over_d(stretch(main_p), space_factor, 1000);\r
434     shrink(main_p) = xn_over_d(shrink(main_p), 1000, space_factor);\r
435     q = new_glue(main_p);\r
436     glue_ref_count(main_p) = 0;\r
437   }\r
438 \r
439   link(tail) = q;\r
440   tail = q;\r
441 }\r
442 /* sec 1047 */\r
443 void insert_dollar_sign (void)\r
444 {\r
445   back_input();\r
446   cur_tok = math_shift_token + '$';\r
447   print_err("Missing $ inserted");\r
448   help2("I've inserted a begin-math/end-math symbol since I think",\r
449       "you left one out. Proceed, with fingers crossed.");\r
450   ins_error();\r
451 }\r
452 /* sec 1049 */\r
453 void you_cant (void)\r
454 {\r
455   print_err("You can't use `");\r
456   print_cmd_chr(cur_cmd, cur_chr);\r
457   prints("' in ");\r
458   print_mode(mode);\r
459 }\r
460 /* sec 1050 */\r
461 void report_illegal_case (void)\r
462 {\r
463   you_cant();\r
464   help4("Sorry, but I'm not programmed to handle this case;",\r
465       "I'll just pretend that you didn't ask for it.",\r
466       "If you're in the wrong mode, you might be able to",\r
467       "return to the right one by typing `I}' or `I$' or `I\\par'.");\r
468   error();\r
469 }\r
470 /* sec 1051 */\r
471 boolean privileged (void)\r
472 {\r
473   if (mode > 0)\r
474     return true;\r
475   else\r
476   {\r
477     report_illegal_case();\r
478     return false;\r
479   }\r
480 }\r
481 /* sec 1054 */\r
482 boolean its_all_over (void)\r
483 {\r
484   if (privileged())\r
485   {\r
486     if ((page_head == page_tail) && (head == tail) && (dead_cycles == 0))\r
487     {\r
488       return true;\r
489     }\r
490 \r
491     back_input();\r
492     tail_append(new_null_box());\r
493     width(tail) = hsize;\r
494     tail_append(new_glue(fill_glue));\r
495     tail_append(new_penalty(-1073741824L));\r
496     build_page();\r
497   }\r
498 \r
499   return false;\r
500 }\r
501 /* sec 1060 */\r
502 void append_glue (void)\r
503 {\r
504   small_number s;\r
505 \r
506   s = cur_chr;\r
507 \r
508   switch (s)\r
509   {\r
510     case fil_code:\r
511       cur_val = fil_glue;\r
512       break;\r
513 \r
514     case fill_code:\r
515       cur_val = fill_glue;\r
516       break;\r
517 \r
518     case ss_code:\r
519       cur_val = ss_glue;\r
520       break;\r
521 \r
522     case fil_neg_code:\r
523       cur_val = fil_neg_glue;\r
524       break;\r
525 \r
526     case skip_code:\r
527       scan_glue(glue_val);\r
528       break;\r
529 \r
530     case mskip_code:\r
531       scan_glue(mu_val);\r
532       break;\r
533   }\r
534 \r
535   tail_append(new_glue(cur_val));\r
536 \r
537   if (s >= skip_code)\r
538   {\r
539     decr(glue_ref_count(cur_val));\r
540 \r
541     if (s > skip_code)\r
542       subtype(tail) = mu_glue;\r
543   }\r
544 }\r
545 /* sec 1061 */\r
546 void append_kern (void)\r
547\r
548   quarterword s;\r
549 \r
550   s = cur_chr;\r
551 \r
552   scan_dimen((s == mu_glue), false, false);\r
553   tail_append(new_kern(cur_val));\r
554   subtype(tail) = s;\r
555 }\r
556 /* sec 1064 */\r
557 void off_save (void)\r
558 {\r
559   pointer p;\r
560 \r
561   if (cur_group == bottom_level)\r
562   {\r
563     print_err("Extra ");\r
564     print_cmd_chr(cur_cmd, cur_chr);\r
565     help1("Things are pretty mixed up, but I think the worst is over.");\r
566     error();\r
567   }\r
568   else\r
569   {\r
570     back_input();\r
571     p = get_avail();\r
572     link(temp_head) = p;\r
573     print_err("Missing ");\r
574 \r
575     switch (cur_group)\r
576     {\r
577       case semi_simple_group:\r
578         {\r
579           info(p) = cs_token_flag + frozen_end_group;\r
580           print_esc("endgroup");\r
581         }\r
582         break;\r
583 \r
584       case math_shift_group:\r
585         {\r
586           info(p) = math_shift_token + '$';\r
587           print_char('$');\r
588         }\r
589         break;\r
590 \r
591       case math_left_group:\r
592         {\r
593           info(p) = cs_token_flag + frozen_right;\r
594           link(p) = get_avail();\r
595           p = link(p);\r
596           info(p) = other_token + '.';\r
597           print_esc("right.");\r
598         }\r
599         break;\r
600 \r
601       default:\r
602         {\r
603           info(p) = right_brace_token + '}';\r
604           print_char('}');\r
605         }\r
606         break;\r
607     }\r
608 \r
609     prints(" inserted");\r
610     ins_list(link(temp_head));\r
611     help5("I've inserted something that you may have forgotten.",\r
612         "(See the <inserted text> above.)",\r
613         "With luck, this will get me unwedged. But if you",\r
614         "really didn't forget anything, try typing `2' now; then",\r
615         "my insertion and my current dilemma will both disappear.");\r
616     error();\r
617   }\r
618 }\r
619 /* sec 1069 */\r
620 void extra_right_brace (void)\r
621 {\r
622   print_err("Extra }, or forgotten ");\r
623 \r
624   switch (cur_group)\r
625   {\r
626     case semi_simple_group:\r
627       print_esc("endgroup");\r
628       break;\r
629 \r
630     case math_shift_group:\r
631       print_char('$');\r
632       break;\r
633 \r
634     case math_left_group:\r
635       print_esc("right");\r
636       break;\r
637   }\r
638 \r
639   help5("I've deleted a group-closing symbol because it seems to be",\r
640       "spurious, as in `$x}$'. But perhaps the } is legitimate and",\r
641       "you forgot something else, as in `\\hbox{$x}'. In such cases",\r
642       "the way to recover is to insert both the forgotten and the",\r
643       "deleted material, e.g., by typing `I$}'.");\r
644   error();\r
645   incr(align_state);\r
646 }\r
647 /* sec 1070 */\r
648 void normal_paragraph (void)\r
649 {\r
650   if (looseness != 0)\r
651     eq_word_define(int_base + looseness_code, 0);\r
652 \r
653   if (hang_indent != 0)\r
654     eq_word_define(dimen_base + hang_indent_code, 0);\r
655 \r
656   if (hang_after != 1)\r
657     eq_word_define(int_base + hang_after_code, 1);\r
658 \r
659   if (par_shape_ptr != 0)\r
660     eq_define(par_shape_loc, shape_ref, 0);\r
661 }\r
662 /* sec 1075 */\r
663 void box_end (integer box_context)\r
664 {\r
665   pointer p;\r
666 \r
667   if (box_context < box_flag)\r
668   {\r
669     if (cur_box != 0)\r
670     {\r
671       shift_amount(cur_box) = box_context;\r
672 \r
673       if (abs(mode) == vmode)\r
674       {\r
675         append_to_vlist(cur_box);\r
676 \r
677         if (adjust_tail != 0)\r
678         {\r
679           if (adjust_head != adjust_tail)\r
680           {\r
681             link(tail) = link(adjust_head);\r
682             tail = adjust_tail;\r
683           }\r
684 \r
685           adjust_tail = 0;\r
686         }\r
687 \r
688         if (mode > 0)\r
689           build_page();\r
690       }\r
691       else\r
692       {\r
693         if (abs(mode) == hmode)\r
694           space_factor = 1000;\r
695         else\r
696         {\r
697           p = new_noad();\r
698           math_type(nucleus(p)) = sub_box;\r
699           info(nucleus(p)) = cur_box;\r
700           cur_box = p;\r
701         }\r
702 \r
703         link(tail) = cur_box;\r
704         tail = cur_box;\r
705       }\r
706     }\r
707   }\r
708   else if (box_context < ship_out_flag)\r
709     if (box_context < (box_flag + 256))\r
710       eq_define((box_base - box_flag) + box_context, box_ref, cur_box);\r
711     else\r
712       geq_define((box_base - box_flag - 256) + box_context, box_ref, cur_box);\r
713   else if (cur_box != 0)\r
714     if (box_context > ship_out_flag)\r
715     {\r
716       do\r
717         {\r
718           get_x_token();\r
719         }\r
720       while (!((cur_cmd != spacer) && (cur_cmd != relax)));\r
721 \r
722       if (((cur_cmd == hskip) && (abs(mode) != vmode)) || ((cur_cmd == vskip) && (abs(mode) == vmode)))\r
723       {\r
724         append_glue();\r
725         subtype(tail) = box_context - (leader_flag - a_leaders);\r
726         leader_ptr(tail) = cur_box;\r
727       }\r
728       else\r
729       {\r
730         print_err("Leaders not followed by proper glue");\r
731         help3("You should say `\\leaders <box or rule><hskip or vskip>'.",\r
732             "I found the <box or rule>, but there's no suitable",\r
733             "<hskip or vskip>, so I'm ignoring these leaders.");\r
734         back_error();\r
735         flush_node_list(cur_box);\r
736       }\r
737     }\r
738     else\r
739       ship_out(cur_box);\r
740 }\r
741 /* sec 1079 */\r
742 void begin_box (integer box_context)\r
743 {\r
744   pointer p, q;\r
745   quarterword m;\r
746   halfword k;\r
747   eight_bits n;\r
748 \r
749   switch (cur_chr)\r
750   {\r
751     case box_code:\r
752       {\r
753         scan_eight_bit_int();\r
754         cur_box = box(cur_val);\r
755         box(cur_val) = 0;\r
756       }\r
757       break;\r
758 \r
759     case copy_code:\r
760       {\r
761         scan_eight_bit_int();\r
762         cur_box = copy_node_list(box(cur_val));\r
763       }\r
764       break;\r
765 \r
766     case last_box_code:\r
767       {\r
768         cur_box = 0;\r
769 \r
770         if (abs(mode) == mmode)\r
771         {\r
772           you_cant();\r
773           help1("Sorry; this \\lastbox will be void.");\r
774           error();\r
775         }\r
776         else if ((mode == vmode) && (head == cur_list.tail_field))\r
777         {\r
778           you_cant();\r
779           help2("Sorry...I usually can't take things from the current page.",\r
780               "This \\lastbox will therefore be void.");\r
781           error();\r
782         }\r
783         else\r
784         {\r
785           if (!is_char_node(tail))\r
786             if ((type(tail) == hlist_node) || (type(tail) == vlist_node))\r
787             {\r
788               q = head;\r
789 \r
790               do\r
791                 {\r
792                   p = q;\r
793 \r
794                   if (!is_char_node(q))\r
795                     if (type(q) == disc_node)\r
796                     {\r
797                       for (m = 1; m <= replace_count(q); m++)\r
798                         p = link(p);\r
799 \r
800                       if (p == tail)\r
801                         goto done;\r
802                     }\r
803 \r
804                   q = link(p);\r
805                 }\r
806               while (!(q == tail));\r
807 \r
808               cur_box = tail;\r
809               shift_amount(cur_box) = 0;\r
810               tail = p;\r
811               link(p) = 0;\r
812 done:;\r
813             }\r
814         }\r
815       }\r
816       break;\r
817 \r
818     case vsplit_code:\r
819       {\r
820         scan_eight_bit_int();\r
821         n = cur_val;\r
822 \r
823         if (!scan_keyword("to"))\r
824         {\r
825           print_err("Missing `to' inserted");\r
826           help2("I'm working on `\\vsplit<box number> to <dimen>';",\r
827               "will look for the <dimen> next.");\r
828           error();\r
829         }\r
830 \r
831         scan_dimen(false, false, false);\r
832         cur_box = vsplit(n, cur_val);\r
833       }\r
834       break;\r
835 \r
836     default:\r
837       {\r
838         k = cur_chr - vtop_code;\r
839         saved(0) = box_context;\r
840 \r
841         if (k == hmode)\r
842           if ((box_context < box_flag) && (abs(mode) == vmode))\r
843             scan_spec(adjust_hbox_group, true);\r
844           else\r
845             scan_spec(hbox_group, true);\r
846         else\r
847         {\r
848           if (k == vmode)\r
849             scan_spec(vbox_group, true);\r
850           else\r
851           {\r
852             scan_spec(vtop_group, true);\r
853             k = vmode;\r
854           }\r
855 \r
856           normal_paragraph();\r
857         }\r
858 \r
859         push_nest();\r
860         mode = - (integer) k;\r
861 \r
862         if (k == vmode)\r
863         {\r
864           prev_depth = ignore_depth;\r
865 \r
866           if (every_vbox != 0)\r
867             begin_token_list(every_vbox, every_vbox_text);\r
868         }\r
869         else\r
870         {\r
871           space_factor = 1000;\r
872 \r
873           if (every_hbox != 0)\r
874             begin_token_list(every_hbox, every_vbox_text);\r
875         }\r
876 \r
877         return;\r
878       }\r
879       break;\r
880   }\r
881 \r
882   box_end(box_context);\r
883 }\r
884 /* sec 1084 */\r
885 void scan_box_(integer box_context)\r
886 {\r
887   do\r
888     {\r
889       get_x_token(); \r
890     }\r
891   while (!((cur_cmd != spacer) && (cur_cmd != relax)));\r
892 \r
893   if (cur_cmd == make_box)\r
894   {\r
895     begin_box(box_context);\r
896   }\r
897   else if ((box_context >= leader_flag) && ((cur_cmd == hrule) || (cur_cmd == vrule)))\r
898   {\r
899     cur_box = scan_rule_spec();\r
900     box_end(box_context);\r
901   }\r
902   else\r
903   {\r
904     print_err("A <box> was supposed to be here");\r
905     help3("I was expecting to see \\hbox or \\vbox or \\copy or \\box or",\r
906         "something like that. So you might find something missing in",\r
907         "your output. But keep trying; you can fix this later.");\r
908     back_error();\r
909   }\r
910 }\r
911 /* sec 1091 */\r
912 small_number norm_min (integer h)\r
913 {\r
914   if (h <= 0)\r
915     return 1;\r
916   else if (h >= 63)\r
917     return 63;\r
918   else\r
919     return h;\r
920 }\r
921 /* sec 1091 */\r
922 void new_graf (boolean indented)\r
923 {\r
924   prev_graf = 0;\r
925 \r
926   if ((mode == vmode) || (head != tail))\r
927     tail_append(new_param_glue(par_skip_code));\r
928 \r
929   push_nest();\r
930   mode = hmode;\r
931   space_factor = 1000;\r
932   set_cur_lang();\r
933   clang = cur_lang;\r
934   prev_graf = (norm_min(left_hyphen_min) * 64 + norm_min(right_hyphen_min)) * 65536L + cur_lang;\r
935 \r
936   if (indented)\r
937   {\r
938     tail = new_null_box();\r
939     link(head) = tail;\r
940     width(tail) = par_indent;\r
941   }\r
942 \r
943   if (every_par != 0)\r
944     begin_token_list(every_par, every_par_text);\r
945 \r
946   if (nest_ptr == 1)\r
947     build_page();\r
948 }\r
949 /* sec 1093 */\r
950 void indent_in_hmode (void)\r
951 {\r
952   pointer p, q;\r
953 \r
954   if (cur_chr > 0)\r
955   {\r
956     p = new_null_box();\r
957     width(p) = par_indent;\r
958 \r
959     if (abs(mode) == hmode)\r
960       space_factor = 1000;\r
961     else\r
962     {\r
963       q = new_noad();\r
964       math_type(nucleus(q)) = sub_box;\r
965       info(nucleus(q)) = p;\r
966       p = q;\r
967     }\r
968 \r
969     tail_append(p);\r
970   }\r
971 }\r
972 /* sec 1095 */\r
973 void head_for_vmode (void)\r
974 {\r
975   if (mode < 0)\r
976   {\r
977     if (cur_cmd != hrule)\r
978       off_save();\r
979     else\r
980     {\r
981       print_err("You can't use `");\r
982       print_esc("hrule");\r
983       prints("' here except with leaders");\r
984       help2("To put a horizontal rule in an hbox or an alignment,",\r
985           "you should use \\leaders or \\hrulefill (see The TeXbook).");\r
986       error();\r
987     }\r
988   }\r
989   else\r
990   {\r
991     back_input();\r
992     cur_tok = par_token;\r
993     back_input();\r
994     index = inserted;\r
995   }\r
996 }\r
997 /* sec 1096 */\r
998 void end_graf (void)\r
999 {\r
1000   if (mode == hmode)\r
1001   {\r
1002     if (head == tail)\r
1003       pop_nest();\r
1004     else\r
1005       line_break(widow_penalty);\r
1006 \r
1007     normal_paragraph();\r
1008     error_count = 0;\r
1009   }\r
1010 }\r
1011 /* sec 1099 */\r
1012 void begin_insert_or_adjust (void)\r
1013 {\r
1014   if (cur_cmd == vadjust)\r
1015     cur_val = 255;\r
1016   else\r
1017   {\r
1018     scan_eight_bit_int();\r
1019 \r
1020     if (cur_val == 255)\r
1021     {\r
1022       print_err("You can't ");\r
1023       print_esc("insert");\r
1024       print_int(255);\r
1025       help1("I'm changing to \\insert0; box 255 is special.");\r
1026       error();\r
1027       cur_val = 0;\r
1028     }\r
1029   }\r
1030 \r
1031   saved(0) = cur_val;\r
1032   incr(save_ptr);\r
1033   new_save_level(insert_group);\r
1034   scan_left_brace();\r
1035   normal_paragraph();\r
1036   push_nest();\r
1037   mode = -vmode;\r
1038   prev_depth = ignore_depth;\r
1039 }\r
1040 /* sec 1101 */\r
1041 void make_mark (void)\r
1042 {\r
1043   pointer p;\r
1044 \r
1045   p = scan_toks(false, true);\r
1046   p = get_node(small_node_size);\r
1047   type(p) = mark_node;\r
1048   subtype(p) = 0;\r
1049   mark_ptr(p) = def_ref;\r
1050   link(tail) = p;\r
1051   tail = p;\r
1052 }\r
1053 /* sec 1103 */\r
1054 void append_penalty (void)\r
1055 {\r
1056   scan_int();\r
1057   tail_append(new_penalty(cur_val));\r
1058 \r
1059   if (mode == vmode)\r
1060     build_page();\r
1061 }\r
1062 /* sec 1105 */\r
1063 void delete_last (void)\r
1064 {\r
1065   pointer p, q;\r
1066   quarterword m;\r
1067 \r
1068   if ((mode == vmode) && (tail == head))\r
1069   {\r
1070     if ((cur_chr != glue_node) || (last_glue != max_halfword))\r
1071     {\r
1072       you_cant();\r
1073       help2("Sorry...I usually can't take things from the current page.",\r
1074           "Try `I\\vskip-\\lastskip' instead.");\r
1075 \r
1076       if (cur_chr == kern_node)\r
1077         help_line[0] = "Try `I\\kern-\\last_kern' instead.";\r
1078       else if (cur_chr != glue_node)\r
1079         help_line[0] = "Perhaps you can make the output routine do it.";\r
1080       error();\r
1081     }\r
1082   }\r
1083   else\r
1084   {\r
1085     if (!is_char_node(tail))\r
1086       if (type(tail) == cur_chr)\r
1087       {\r
1088         q = head;\r
1089 \r
1090         do\r
1091           {\r
1092             p = q;\r
1093 \r
1094             if (!is_char_node(q))\r
1095               if (type(q) == disc_node)\r
1096               {\r
1097                 for (m = 1; m <= replace_count(q); m++)\r
1098                   p = link(p);\r
1099 \r
1100                 if (p == tail)\r
1101                   return;\r
1102               }\r
1103 \r
1104             q = link(p);\r
1105           }\r
1106         while (!(q == tail));\r
1107 \r
1108         link(p) = 0;\r
1109         flush_node_list(tail);\r
1110         tail = p;\r
1111       }\r
1112   }\r
1113 }\r
1114 /* sec 1110 */\r
1115 void unpackage (void)\r
1116 {\r
1117   pointer p;\r
1118   char c;\r
1119 \r
1120   c = cur_chr;\r
1121   scan_eight_bit_int();\r
1122   p = box(cur_val);\r
1123 \r
1124   if (p == 0)\r
1125     return;\r
1126 \r
1127   if ((abs(mode) == mmode) || ((abs(mode) == vmode) && (type(p) != vlist_node)) ||\r
1128     ((abs(mode) == hmode) && (type(p) != hlist_node)))\r
1129   {\r
1130     print_err("Incompatible list can't be unboxed");\r
1131     help3("Sorry, Pandora. (You sneaky devil.)",\r
1132         "I refuse to unbox an \\hbox in vertical mode or vice versa.",\r
1133         "And I can't open any boxes in math mode.");\r
1134     error();\r
1135     return;\r
1136   }\r
1137 \r
1138   if (c == copy_code)\r
1139     link(tail) = copy_node_list(list_ptr(p));\r
1140   else\r
1141   {\r
1142     link(tail) = list_ptr(p);\r
1143     box(cur_val) = 0;\r
1144     free_node(p, box_node_size);\r
1145   }\r
1146 \r
1147   while (link(tail) != 0)\r
1148     tail = link(tail);\r
1149 }\r
1150 /* sec 1113 */\r
1151 void append_italic_correction (void)\r
1152 {\r
1153   pointer p;\r
1154   internal_font_number f;\r
1155 \r
1156   if (tail != head)\r
1157   {\r
1158     if (is_char_node(tail))\r
1159       p = tail;\r
1160     else if (type(tail) == ligature_node)\r
1161       p = tail + 1;\r
1162     else\r
1163       return;\r
1164 \r
1165     f = font(p);\r
1166     tail_append(new_kern(char_italic(f, char_info(f, character(p)))));\r
1167     subtype(tail) = explicit;\r
1168   }\r
1169 }\r
1170 /* sec 1117 */\r
1171 void append_discretionary (void)\r
1172 {\r
1173   integer c;\r
1174 \r
1175   tail_append(new_disc());\r
1176 \r
1177   if (cur_chr == 1)\r
1178   {\r
1179     c = hyphen_char[cur_font];\r
1180 \r
1181     if (c >= 0)\r
1182       if (c < 256)\r
1183         pre_break(tail) = new_character(cur_font, c);\r
1184   }\r
1185   else\r
1186   {\r
1187     incr(save_ptr);\r
1188     saved(-1) = 0;\r
1189     new_save_level(disc_group);\r
1190     scan_left_brace();\r
1191     push_nest();\r
1192     mode = -hmode;\r
1193     space_factor = 1000;\r
1194   }\r
1195 }\r
1196 /* sec 1119 */\r
1197 void build_discretionary (void)\r
1198 {\r
1199   pointer p, q;\r
1200   integer n;\r
1201 \r
1202   unsave();\r
1203   q = head;\r
1204   p = link(q);\r
1205   n = 0;\r
1206 \r
1207   while (p != 0)\r
1208   {\r
1209     if (!is_char_node(p))\r
1210       if (type(p) > rule_node)\r
1211         if (type(p) != kern_node)\r
1212           if (type(p) != ligature_node)\r
1213           {\r
1214             print_err("Improper discretionary list");\r
1215             help1("Discretionary lists must contain only boxes and kerns.");\r
1216             error();\r
1217             begin_diagnostic();\r
1218             print_nl("The following discretionary sublist has been deleted:");\r
1219             show_box(p);\r
1220             end_diagnostic(true);\r
1221             flush_node_list(p);\r
1222             link(q) = 0;\r
1223             goto done;\r
1224           }\r
1225 \r
1226     q = p;\r
1227     p = link(q);\r
1228     incr(n);\r
1229   }\r
1230 \r
1231 done:\r
1232   p = link(head);\r
1233   pop_nest();\r
1234 \r
1235   switch (saved(-1))\r
1236   {\r
1237     case 0:\r
1238       pre_break(tail) = p;\r
1239       break;\r
1240 \r
1241     case 1:\r
1242       post_break(tail) = p;\r
1243       break;\r
1244 \r
1245     case 2:\r
1246       {\r
1247         if ((n > 0) && (abs(mode) == mmode))\r
1248         {\r
1249           print_err("Illegal math ");\r
1250           print_esc("discretionary");\r
1251           help2("Sorry: The third part of a discretionary break must be",\r
1252               "empty, in math formulas. I had to delete your third part.");\r
1253           flush_node_list(p);\r
1254           n = 0;\r
1255           error();\r
1256         }\r
1257         else\r
1258           link(tail) = p;\r
1259 \r
1260         if (n <= max_quarterword)\r
1261           replace_count(tail) = n;\r
1262         else\r
1263         {\r
1264           print_err("Discretionary list is too long");\r
1265           help2("Wow---I never thought anybody would tweak me here.",\r
1266               "You can't seriously need such a huge discretionary list?");\r
1267           error();\r
1268         }\r
1269 \r
1270         if (n > 0)\r
1271           tail = q;\r
1272 \r
1273         decr(save_ptr);\r
1274         return;\r
1275       }\r
1276       break;\r
1277   }\r
1278 \r
1279   incr(saved(-1));\r
1280   new_save_level(disc_group);\r
1281   scan_left_brace();\r
1282   push_nest();\r
1283   mode = -hmode;\r
1284   space_factor = 1000;\r
1285 }\r
1286 /* sec 1123 */\r
1287 void make_accent (void)\r
1288 {\r
1289   real s, t;\r
1290   pointer p, q, r;\r
1291   internal_font_number f;\r
1292   scaled a, h, x, w, delta;\r
1293   four_quarters i;\r
1294 \r
1295   scan_char_num();\r
1296   f = cur_font;\r
1297   p = new_character(f, cur_val);\r
1298 \r
1299   if (p != 0)\r
1300   {\r
1301     x = x_height(f);\r
1302     s = slant(f) / ((double) 65536.0);\r
1303     a = char_width(f, char_info(f, character(p)));\r
1304     do_assignments();\r
1305     q = 0;\r
1306     f = cur_font;\r
1307 \r
1308     if ((cur_cmd == letter) || (cur_cmd == other_char) || (cur_cmd == char_given))\r
1309       q = new_character(f, cur_chr);\r
1310     else if (cur_cmd == char_num)\r
1311     {\r
1312       scan_char_num();\r
1313       q = new_character(f, cur_val);\r
1314     }\r
1315     else\r
1316       back_input();\r
1317 \r
1318     if (q != 0)\r
1319     {\r
1320       t = slant(f) / ((double) 65536.0);\r
1321       i = char_info(f, character(q));\r
1322       w = char_width(f, i);\r
1323       h = char_height(f, height_depth(i));\r
1324 \r
1325       if (h != x)\r
1326       {\r
1327         p = hpack(p, 0, 1);\r
1328         shift_amount(p) = x - h;\r
1329       }\r
1330 \r
1331       delta = round((w - a) / ((double) 2.0) + h * t - x * s);\r
1332       r = new_kern(delta);\r
1333       subtype(r) = acc_kern;\r
1334       link(tail) = r;\r
1335       link(r) = p;\r
1336       tail = new_kern(- (integer) a - delta);\r
1337       subtype(tail) = acc_kern;\r
1338       link(p) = tail;\r
1339       p = q;\r
1340     }\r
1341 \r
1342     link(tail) = p;\r
1343     tail = p;\r
1344     space_factor = 1000;\r
1345   }\r
1346 }\r
1347 /* sec 1127 */\r
1348 void align_error (void)\r
1349 {\r
1350   if (abs(align_state) > 2)\r
1351   {\r
1352     print_err("Misplaced ");\r
1353     print_cmd_chr(cur_cmd, cur_chr);\r
1354 \r
1355     if (cur_tok == tab_token + '&')\r
1356     {\r
1357       help6("I can't figure out why you would want to use a tab mark",\r
1358           "here. If you just want an ampersand, the remedy is",\r
1359           "simple: Just type `I\\&' now. But if some right brace",\r
1360           "up above has ended a previous alignment prematurely,",\r
1361           "you're probably due for more error messages, and you",\r
1362           "might try typing `S' now just to see what is salvageable.");\r
1363     }\r
1364     else\r
1365     {\r
1366       help5("I can't figure out why you would want to use a tab mark",\r
1367           "or \\cr or \\span just now. If something like a right brace",\r
1368           "up above has ended a previous alignment prematurely,",\r
1369           "you're probably due for more error messages, and you",\r
1370           "might try typing `S' now just to see what is salvageable.");\r
1371     }\r
1372 \r
1373     error();\r
1374   }\r
1375   else\r
1376   {\r
1377     back_input();\r
1378 \r
1379     if (align_state < 0)\r
1380     {\r
1381       print_err("Missing { inserted");\r
1382       incr(align_state);\r
1383       cur_tok = left_brace_token + '{';\r
1384     }\r
1385     else\r
1386     {\r
1387       print_err("Missing } inserted");\r
1388       decr(align_state);\r
1389       cur_tok = right_brace_token + '}';\r
1390     }\r
1391 \r
1392     help3("I've put in what seems to be necessary to fix",\r
1393         "the current column of the current alignment.",\r
1394         "Try to go on, since this might almost work.");\r
1395     ins_error();\r
1396   }\r
1397 }\r
1398 /* sec 1129 */\r
1399 void noalign_error (void)\r
1400 {\r
1401   print_err("Misplaced ");\r
1402   print_esc("noalign");\r
1403   help2("I expect to see \\noalign only after the \\cr of",\r
1404       "an alignment. Proceed, and I'll ignore this case.");\r
1405   error();\r
1406 }\r
1407 /* sec 1129 */\r
1408 void omit_error (void)\r
1409 {\r
1410   print_err("Misplaced ");\r
1411   print_esc("omit");\r
1412   help2("I expect to see \\omit only after tab marks or the \\cr of",\r
1413       "an alignment. Proceed, and I'll ignore this case.");\r
1414   error();\r
1415 }\r
1416 /* sec 1131 */\r
1417 void do_endv (void)\r
1418 {\r
1419   base_ptr = input_ptr;\r
1420   input_stack[base_ptr] = cur_input;\r
1421 \r
1422   while ((input_stack[base_ptr].index_field != v_template) &&\r
1423     (input_stack[base_ptr].loc_field == 0) &&\r
1424     (input_stack[base_ptr].state_field == token_list))\r
1425     decr(base_ptr);\r
1426 \r
1427   if ((input_stack[base_ptr].index_field != v_template) ||\r
1428     (input_stack[base_ptr].loc_field != 0) ||\r
1429     (input_stack[base_ptr].state_field != token_list))\r
1430     fatal_error("(interwoven alignment preambles are not allowed)");\r
1431 \r
1432   if (cur_group == align_group)\r
1433   {\r
1434     end_graf();\r
1435 \r
1436     if (fin_col())\r
1437       fin_row();\r
1438   }\r
1439   else\r
1440     off_save();\r
1441 }\r
1442 /* sec 1135 */\r
1443 void cs_error (void)\r
1444 {\r
1445   print_err("Extra ");\r
1446   print_esc("endcsname");\r
1447   help1("I'm ignoring this, since I wasn't doing a \\csname."); \r
1448   error();\r
1449 }\r
1450 /* sec 1136 */\r
1451 void push_math (group_code c)\r
1452 {\r
1453   push_nest();\r
1454   mode = -mmode;\r
1455   incompleat_noad = 0;\r
1456   new_save_level(c);\r
1457 }\r
1458 /* sec 1138 */\r
1459 void init_math (void)\r
1460 {\r
1461   scaled w;\r
1462   scaled l;\r
1463   scaled s;\r
1464   pointer p;\r
1465   pointer q;\r
1466   internal_font_number f;\r
1467   integer n;\r
1468   scaled v;\r
1469   scaled d;\r
1470 \r
1471   get_token();\r
1472 \r
1473   if ((cur_cmd == math_shift) && (mode > 0))\r
1474   {\r
1475     if (head == tail)\r
1476     {\r
1477       pop_nest();\r
1478       w = -max_dimen;\r
1479     }\r
1480     else\r
1481     {\r
1482       line_break(display_widow_penalty);\r
1483       v = shift_amount(just_box) + 2 * quad(cur_font);\r
1484       w = -max_dimen;\r
1485       p = list_ptr(just_box);\r
1486 \r
1487       while (p != 0)\r
1488       {\r
1489 reswitch:\r
1490         if (is_char_node(p))\r
1491         {\r
1492           f = font(p);\r
1493           d = char_width(f, char_info(f, character(p)));\r
1494           goto found;\r
1495         }\r
1496 \r
1497         switch (type(p))\r
1498         {\r
1499           case hlist_node:\r
1500           case vlist_node:\r
1501           case rule_node:\r
1502             {\r
1503               d = width(p);\r
1504               goto found;\r
1505             }\r
1506             break;\r
1507 \r
1508           case ligature_node:\r
1509             {\r
1510               mem[lig_trick] = mem[lig_char(p)];\r
1511               link(lig_trick) = link(p);\r
1512               p = lig_trick;\r
1513               goto reswitch;\r
1514             }\r
1515             break;\r
1516 \r
1517           case kern_node:\r
1518           case math_node:\r
1519             d = width(p);\r
1520             break;\r
1521 \r
1522           case glue_node:\r
1523             {\r
1524               q = glue_ptr(p);\r
1525               d = width(q);\r
1526 \r
1527               if (glue_sign(just_box) == stretching)\r
1528               {\r
1529                 if ((glue_order(just_box) == stretch_order(q)) && (stretch(q) != 0))\r
1530                   v = max_dimen;\r
1531               }\r
1532               else if (glue_sign(just_box) == shrinking)\r
1533               {\r
1534                 if ((glue_order(just_box) == shrink_order(q)) && (shrink(q) != 0))\r
1535                   v = max_dimen;\r
1536               }\r
1537 \r
1538               if (subtype(p) >= a_leaders)\r
1539                 goto found;\r
1540             }\r
1541             break;\r
1542 \r
1543           case whatsit_node:\r
1544             d = 0;\r
1545             break;\r
1546 \r
1547           default:\r
1548             d = 0;\r
1549             break;\r
1550         }\r
1551 \r
1552         if (v < max_dimen)\r
1553           v = v + d;\r
1554 \r
1555         goto not_found;\r
1556 \r
1557 found:\r
1558         if (v < max_dimen)\r
1559         {\r
1560           v = v + d;\r
1561           w = v;\r
1562         }\r
1563         else\r
1564         {\r
1565           w = max_dimen;\r
1566           goto done;\r
1567         }\r
1568 \r
1569 not_found:\r
1570         p = link(p);\r
1571       }\r
1572 done:;\r
1573     }\r
1574 \r
1575     if (par_shape_ptr == 0)\r
1576       if ((hang_indent != 0) && (((hang_after >= 0) &&\r
1577         (prev_graf + 2 > hang_after)) || (prev_graf + 1 < - (integer) hang_after)))\r
1578       {\r
1579         l = hsize - abs(hang_indent);\r
1580 \r
1581         if (hang_indent > 0)\r
1582           s = hang_indent;\r
1583         else\r
1584           s = 0;\r
1585       }\r
1586       else\r
1587       {\r
1588         l = hsize;\r
1589         s = 0;\r
1590       }\r
1591     else\r
1592     {\r
1593       n = info(par_shape_ptr);\r
1594 \r
1595       if (prev_graf + 2 >= n)\r
1596         p = par_shape_ptr + 2 * n;\r
1597       else\r
1598         p = par_shape_ptr + 2 * (prev_graf + 2);\r
1599 \r
1600       s = mem[p - 1].cint;\r
1601       l = mem[p].cint;\r
1602     }\r
1603 \r
1604     push_math(math_shift_group);\r
1605     mode = mmode;\r
1606     eq_word_define(int_base + cur_fam_code, -1);\r
1607     eq_word_define(dimen_base + pre_display_size_code, w);\r
1608     eq_word_define(dimen_base + display_width_code, l);\r
1609     eq_word_define(dimen_base + display_indent_code, s);\r
1610 \r
1611     if (every_display != 0)\r
1612       begin_token_list(every_display, every_display_text);\r
1613 \r
1614     if (nest_ptr == 1)\r
1615     {\r
1616       build_page();\r
1617     }\r
1618   }\r
1619   else\r
1620   {\r
1621     back_input();\r
1622 \r
1623     {\r
1624       push_math(math_shift_group);\r
1625       eq_word_define(int_base + cur_fam_code, -1);\r
1626 \r
1627       if (every_math != 0)\r
1628         begin_token_list(every_math, every_math_text);\r
1629     }\r
1630   }\r
1631 }\r
1632 /* sec 1142 */\r
1633 void start_eq_no (void)\r
1634 {\r
1635   saved(0) = cur_chr;\r
1636   incr(save_ptr);\r
1637 \r
1638   {\r
1639     push_math(math_shift_group);\r
1640     eq_word_define(int_base + cur_fam_code, -1);\r
1641 \r
1642     if (every_math != 0)\r
1643       begin_token_list(every_math, every_math_text);\r
1644   }\r
1645 }\r
1646 /* sec 1151 */\r
1647 void scan_math (pointer p)\r
1648 {\r
1649   integer c;\r
1650 \r
1651 restart:\r
1652   do\r
1653     {\r
1654       get_x_token();\r
1655     }\r
1656   while (!((cur_cmd != spacer) && (cur_cmd != relax)));\r
1657 \r
1658 reswitch:\r
1659   switch (cur_cmd)\r
1660   {\r
1661     case letter:\r
1662     case other_char:\r
1663     case char_given:\r
1664       {\r
1665         c = math_code(cur_chr);\r
1666 \r
1667         if (c == 32768L)\r
1668         {\r
1669           {\r
1670             cur_cs = cur_chr + active_base;\r
1671             cur_cmd = eq_type(cur_cs);\r
1672             cur_chr = equiv(cur_cs);\r
1673             x_token();\r
1674             back_input();\r
1675           }\r
1676 \r
1677           goto restart;\r
1678         }\r
1679       }\r
1680       break;\r
1681 \r
1682     case char_num:\r
1683       {\r
1684         scan_char_num();\r
1685         cur_chr = cur_val;\r
1686         cur_cmd = char_given;\r
1687         goto reswitch;\r
1688       }\r
1689       break;\r
1690 \r
1691     case math_char_num:\r
1692       {\r
1693         scan_fifteen_bit_int();\r
1694         c = cur_val;\r
1695       }\r
1696       break;\r
1697 \r
1698     case math_given:\r
1699       c = cur_chr;\r
1700       break;\r
1701 \r
1702     case delim_num:\r
1703       {\r
1704         scan_twenty_seven_bit_int();\r
1705         c = cur_val / 4096;\r
1706       }\r
1707       break;\r
1708 \r
1709     default:\r
1710       {\r
1711         back_input();\r
1712         scan_left_brace();\r
1713         saved(0) = p;\r
1714         incr(save_ptr);\r
1715         push_math(math_group);\r
1716         return;\r
1717       }\r
1718       break;\r
1719   }\r
1720 \r
1721   math_type(p) = math_char;\r
1722   character(p) = c % 256;\r
1723 \r
1724   if ((c >= var_code) && ((cur_fam >= 0) && (cur_fam < 16)))\r
1725     fam(p) = cur_fam;\r
1726   else\r
1727     fam(p) = (c / 256) % 16;\r
1728 }\r
1729 /* sec 1155 */\r
1730 void set_math_char_(integer c)\r
1731 {\r
1732   pointer p;\r
1733 \r
1734   if (c >= 32768L)\r
1735   {\r
1736     cur_cs = cur_chr + active_base;\r
1737     cur_cmd = eq_type(cur_cs);\r
1738     cur_chr = equiv(cur_cs);\r
1739     x_token();\r
1740     back_input();\r
1741   }\r
1742   else\r
1743   {\r
1744     p = new_noad();\r
1745     math_type(nucleus(p)) = math_char;\r
1746     character(nucleus(p)) = c % 256;\r
1747     fam(nucleus(p)) = (c / 256) % 16;\r
1748 \r
1749     if (c >= var_code)\r
1750     {\r
1751       if (((cur_fam >= 0) && (cur_fam < 16)))\r
1752         fam(nucleus(p)) = cur_fam;\r
1753 \r
1754       type(p) = ord_noad;\r
1755     }\r
1756     else\r
1757       type(p) = ord_noad + (c / 4096);\r
1758 \r
1759     link(tail) = p;\r
1760     tail = p;\r
1761   }\r
1762 }\r
1763 /* sec 1159 */\r
1764 void math_limit_switch (void)\r
1765 {\r
1766   if (head != tail)\r
1767     if (type(tail) == op_noad)\r
1768     {\r
1769       subtype(tail) = cur_chr;\r
1770       return;\r
1771     }\r
1772 \r
1773   print_err("Limit controls must follow a math operator");\r
1774   help1("I'm ignoring this misplaced \\limits or \\nolimits command.");\r
1775   error();\r
1776 }\r
1777 /* sec 1160 */\r
1778 void scan_delimiter_(pointer p, boolean r)\r
1779 {\r
1780    if (r)\r
1781      scan_twenty_seven_bit_int();\r
1782    else\r
1783    {\r
1784      do\r
1785       {\r
1786         get_x_token();\r
1787       }\r
1788      while (!((cur_cmd != spacer) && (cur_cmd != relax)));\r
1789 \r
1790      switch (cur_cmd)\r
1791      {\r
1792        case letter:\r
1793        case other_char:\r
1794          cur_val = del_code(cur_chr);\r
1795          break;\r
1796 \r
1797        case delim_num:\r
1798          scan_twenty_seven_bit_int();\r
1799          break;\r
1800 \r
1801        default:\r
1802          cur_val = -1;\r
1803          break;\r
1804      }\r
1805    }\r
1806 \r
1807    if (cur_val < 0)\r
1808    {\r
1809      print_err("Missing delimiter (. inserted)");\r
1810      help6("I was expecting to see something like `(' or `\\{' or",\r
1811          "`\\}' here. If you typed, e.g., `{' instead of `\\{', you",\r
1812          "should probably delete the `{' by typing `1' now, so that",\r
1813          "braces don't get unbalanced. Otherwise just proceed.",\r
1814          "Acceptable delimiters are characters whose \\delcode is",\r
1815          "nonnegative, or you can use `\\delimiter <delimiter code>'.");\r
1816      back_error();\r
1817      cur_val = 0;\r
1818    }\r
1819 \r
1820    small_fam(p) = (cur_val / 1048576L) % 16;\r
1821    small_char(p) = (cur_val / 4096) % 256;\r
1822    large_fam(p) = (cur_val / 256) % 16;\r
1823    large_char(p) = cur_val % 256;\r
1824 }\r
1825 /* sec 1163 */\r
1826 void math_radical (void)\r
1827 {\r
1828   tail_append(get_node(radical_noad_size));\r
1829   type(tail) = radical_noad;\r
1830   subtype(tail) = normal;\r
1831   mem[nucleus(tail)].hh = empty_field;\r
1832   mem[subscr(tail)].hh = empty_field;\r
1833   mem[supscr(tail)].hh = empty_field;\r
1834   scan_delimiter(left_delimiter(tail), true);\r
1835   scan_math(nucleus(tail));\r
1836 }\r
1837 /* sec 1165 */\r
1838 void math_ac (void)\r
1839 {\r
1840   if (cur_cmd == accent)\r
1841   {\r
1842     print_err("Please use ");\r
1843     print_esc("mathaccent");\r
1844     prints(" for accents in math mode");\r
1845     help2("I'm changing \\accent to \\mathaccent here; wish me luck.",\r
1846       "(Accents are not the same in formulas as they are in text.)");\r
1847     error();\r
1848   }\r
1849 \r
1850   tail_append(get_node(accent_noad_size));\r
1851   type(tail) = accent_noad;\r
1852   subtype(tail) = normal;\r
1853   mem[nucleus(tail)].hh = empty_field;\r
1854   mem[subscr(tail)].hh = empty_field;\r
1855   mem[supscr(tail)].hh = empty_field;\r
1856   math_type(accent_chr(tail)) = math_char;\r
1857   scan_fifteen_bit_int();\r
1858   character(accent_chr(tail)) = cur_val % 256;\r
1859 \r
1860   if ((cur_val >= var_code) && ((cur_fam >= 0) && (cur_fam < 16)))\r
1861     fam(accent_chr(tail)) = cur_fam;\r
1862   else\r
1863     fam(accent_chr(tail)) = (cur_val / 256) % 16;\r
1864 \r
1865   scan_math(nucleus(tail));\r
1866 }\r
1867 /* sec 1172 */\r
1868 void append_choices (void)\r
1869 {\r
1870   tail_append(new_choice());\r
1871   incr(save_ptr);\r
1872   saved(-1) = 0;\r
1873   push_math(math_choice_group);\r
1874   scan_left_brace();\r
1875 }\r
1876 /* sec 1184 */\r
1877 pointer fin_mlist (pointer p)\r
1878 {\r
1879   pointer q;\r
1880 \r
1881   if (incompleat_noad != 0)\r
1882   {\r
1883     math_type(denominator(incompleat_noad)) = sub_mlist;\r
1884     info(denominator(incompleat_noad)) = link(head);\r
1885 \r
1886     if (p == 0)\r
1887       q = incompleat_noad;\r
1888     else\r
1889     {\r
1890       q = info(numerator(incompleat_noad));\r
1891 \r
1892       if (type(q) != left_noad)\r
1893       {\r
1894         confusion("right");\r
1895         return 0;\r
1896       }\r
1897 \r
1898       info(numerator(incompleat_noad)) = link(q);\r
1899       link(q) = incompleat_noad;\r
1900       link(incompleat_noad) = p;\r
1901     }\r
1902   }\r
1903   else\r
1904   {\r
1905     link(tail) = p;\r
1906     q = link(head);\r
1907   }\r
1908 \r
1909   pop_nest();\r
1910 \r
1911   return q;\r
1912 }\r
1913 /* sec 1174 */\r
1914 void build_choices (void)\r
1915 {\r
1916   pointer p;\r
1917 \r
1918   unsave();\r
1919   p = fin_mlist(0);\r
1920 \r
1921   switch (saved(-1))\r
1922   {\r
1923     case 0:\r
1924       display_mlist(tail) = p;\r
1925       break;\r
1926 \r
1927     case 1:\r
1928       text_mlist(tail) = p;\r
1929       break;\r
1930 \r
1931     case 2:\r
1932       script_mlist(tail) = p;\r
1933       break;\r
1934 \r
1935     case 3:\r
1936       {\r
1937         script_script_mlist(tail) = p;\r
1938         decr(save_ptr);\r
1939         return;\r
1940       }\r
1941       break;\r
1942   }\r
1943 \r
1944   incr(saved(-1));\r
1945   push_math(math_choice_group);\r
1946   scan_left_brace();\r
1947 }\r
1948 /* sec 1176 */\r
1949 void sub_sup (void)\r
1950 {\r
1951   /* small_number t; */\r
1952   int t;\r
1953   pointer p;\r
1954 \r
1955   t = 0;\r
1956   p = 0;\r
1957 \r
1958   if (tail != head)\r
1959     if (script_allowed(tail))\r
1960     {\r
1961       p = supscr(tail) + cur_cmd - sup_mark;\r
1962       t = math_type(p);\r
1963     }\r
1964 \r
1965   if ((p == 0) || (t != 0))\r
1966   {\r
1967     tail_append(new_noad());\r
1968     p = supscr(tail) + cur_cmd - sup_mark;\r
1969 \r
1970     if (t != 0)\r
1971     {\r
1972       if (cur_cmd == sup_mark)\r
1973       {\r
1974         print_err("Double superscript");\r
1975         help1("I treat `x^1^2' essentially like `x^1{}^2'.");\r
1976       }\r
1977       else\r
1978       {\r
1979         print_err("Double subscript");\r
1980         help1("I treat `x_1_2' essentially like `x_1{}_2'.");\r
1981       }\r
1982 \r
1983       error();\r
1984     }\r
1985   }\r
1986 \r
1987   scan_math(p);\r
1988 }\r
1989 /* sec 1086 */\r
1990 void package (small_number c)\r
1991 {\r
1992   scaled h;\r
1993   pointer p;\r
1994   scaled d;\r
1995 \r
1996   d = box_max_depth;\r
1997   unsave();\r
1998   save_ptr = save_ptr - 3;\r
1999 \r
2000   if (mode == -hmode)\r
2001     cur_box = hpack(link(head), saved(2), saved(1));\r
2002   else\r
2003   {\r
2004     cur_box = vpackage(link(head), saved(2), saved(1), d);\r
2005 \r
2006     if (c == vtop_code)\r
2007     {\r
2008       h = 0;\r
2009       p = list_ptr(cur_box);\r
2010 \r
2011       if (p != 0)\r
2012         if (type(p) <= rule_node)\r
2013           h = height(p);\r
2014 \r
2015       depth(cur_box) = depth(cur_box) - h + height(cur_box);\r
2016       height(cur_box) = h;\r
2017     }\r
2018   }\r
2019 \r
2020   pop_nest();\r
2021   box_end(saved(0));\r
2022 }