OSDN Git Service

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