home *** CD-ROM | disk | FTP | other *** search
/ Atari FTP / ATARI_FTP_0693.zip / ATARI_FTP_0693 / Tex / Tex29 / StTeXsrc.zoo / src / boxlists.c < prev    next >
C/C++ Source or Header  |  1988-03-13  |  26KB  |  1,098 lines

  1.  
  2. /*
  3.  * @(#)boxlists.c 2.6 EPA
  4.  *
  5.  * Copyright 1987,1988 Pat J Monardo
  6.  *
  7.  * Redistribution of this file is permitted through
  8.  * the specifications in the file COPYING.
  9.  *
  10.  * 
  11.  */
  12.  
  13. #include "tex.h"
  14. #include "token.h"
  15. #include "tokenstack.h"
  16. #include "tokenlists.h"
  17. #include "eqstack.h"
  18. #include "evalstack.h"
  19. #include "box.h"
  20. #include "scan.h"
  21. #include "def.h"
  22. #include "tfm.h"
  23. #include "pack.h"
  24. #include "page.h"
  25. #include "math.h"
  26. #include "boxlists.h"
  27.  
  28. ptr     cur_box;
  29.  
  30. append_glue ()
  31. {
  32.     hword   s;
  33.     
  34.     s = cur_chr;
  35.     switch (s) 
  36.     {
  37.     case FIL_CODE:
  38.         cur_val = fil_glue;
  39.         break;
  40.  
  41.     case FILL_CODE:
  42.         cur_val = fill_glue;
  43.         break;
  44.  
  45.     case SS_CODE:
  46.         cur_val = ss_glue;
  47.         break;
  48.  
  49.     case FIL_NEG_CODE:
  50.         cur_val = fil_neg_glue;
  51.         break;
  52.  
  53.     case SKIP_CODE:
  54.         scan_glue(GLUE_VAL);
  55.         break;
  56.  
  57.     case MSKIP_CODE:
  58.         scan_glue(MU_VAL);
  59.         break;
  60.  
  61.     default:
  62.         break;
  63.     }
  64.     tail_append(new_glue((ptr) cur_val));
  65.     if (s >= SKIP_CODE) {
  66.         decr(glue_ref_count((ptr) cur_val));
  67.         if (s > SKIP_CODE)
  68.             subtype(tail) = MU_GLUE;
  69.     }
  70. }
  71.  
  72. append_kern ()
  73. {
  74.     qword   s;
  75.     
  76.     s = cur_chr;
  77.     scan_dimen(s == MU_GLUE, FALSE, FALSE);
  78.     tail_append(new_kern(cur_val));
  79.     subtype(tail) = s;
  80. }
  81.  
  82. handle_right_brace ()
  83. {
  84.     scal    d;
  85.     val     f;
  86.     ptr     p;
  87.     ptr     q;
  88.     
  89.     switch (cur_group)
  90.     {
  91.     case SIMPLE_GROUP:
  92.         unsave();
  93.         break;
  94.     
  95.     case BOTTOM_LEVEL:
  96.         print_err("Too many }'s");
  97.         help_close_group();
  98.         error();
  99.         break;
  100.     
  101.     case SEMI_SIMPLE_GROUP:
  102.     case MATH_SHIFT_GROUP:
  103.     case MATH_LEFT_GROUP:
  104.         extra_right_brace();
  105.         break;
  106.  
  107.     case HBOX_GROUP:
  108.         package(0);
  109.         break;
  110.     
  111.     case ADJUSTED_HBOX_GROUP:
  112.         adjust_tail = adjust_head;
  113.         package(0);
  114.         break;
  115.     
  116.     case VBOX_GROUP:
  117.         end_graf();
  118.         package(0);
  119.         break;
  120.     
  121.     case VTOP_GROUP:
  122.         end_graf();
  123.         package(VTOP_CODE);
  124.         break;
  125.  
  126.     case INSERT_GROUP:
  127.         end_graf();
  128.         q = split_top_skip;
  129.         add_glue_ref(q);
  130.         d = split_max_depth;
  131.         f = floating_penalty;
  132.         unsave();
  133.         decr(save_ptr);
  134.         p = vpack(link(head), NATURAL);
  135.         pop_nest();
  136.         if (saved(0) < 255) {
  137.             tail_append(get_node(INS_NODE_SIZE));
  138.             type(tail) = INS_NODE;
  139.             subtype(tail) = qi(saved(0));
  140.             height(tail) = height(p) + depth(p);
  141.             ins_ptr(tail) = list_ptr(p);
  142.             split_top_ptr(tail) = q;
  143.             depth(tail) = d;
  144.             float_cost(tail) = f;
  145.         } else {
  146.             tail_append(get_node(SMALL_NODE_SIZE));
  147.             type(tail) = ADJUST_NODE;
  148.             subtype(tail) = 0;
  149.             adjust_ptr(tail) = list_ptr(p);
  150.             delete_glue_ref(q);
  151.         }
  152.         free_node(p, BOX_NODE_SIZE);
  153.         if (nest_ptr == 0) 
  154.             build_page();
  155.         break;
  156.     
  157.     case OUTPUT_GROUP:
  158.         if (loc != NULL)  {
  159.             print_err("Unbalanced output routine");
  160.             help_output_balance();
  161.             error();
  162.             do get_token();
  163.             while (loc != NULL);
  164.         }
  165.         end_token_list();
  166.         end_graf();
  167.         unsave();
  168.         output_active = FALSE;
  169.         insert_penalties = 0;
  170.         if (box(255) != NULL) {
  171.             print_err("Output routine didn't use all of ");
  172.             print_esc("box255");
  173.             help_output();
  174.             box_error(255);
  175.         }
  176.         if (tail != head) {
  177.             link(page_tail) = link(head);
  178.             page_tail = tail;
  179.         }
  180.         if (link(page_head) != NULL) {
  181.             if (link(contrib_head) == NULL)
  182.                 contrib_tail = page_tail;
  183.             link(page_tail) = link(contrib_head);
  184.             link(contrib_head) = link(page_head);
  185.             link(page_head) = NULL;
  186.             page_tail = page_head;
  187.         }
  188.         pop_nest();
  189.         build_page();
  190.         break;
  191.     
  192.     case DISC_GROUP:
  193.         build_discretionary();
  194.         break;
  195.     
  196.     case ALIGN_GROUP:
  197.         back_input();
  198.         cur_tok = CS_TOKEN_FLAG + FROZEN_CR;
  199.         print_err("Missing ");
  200.         print_esc("cr");
  201.         print(" inserted");
  202.         help_align_cr();
  203.         ins_error(); 
  204.         break;
  205.  
  206.     case NO_ALIGN_GROUP:
  207.         end_graf();
  208.         unsave();
  209.         align_peek();
  210.         break;
  211.     
  212.     case VCENTER_GROUP:
  213.         end_graf();
  214.         unsave();
  215.         save_ptr -= 2;
  216.         p = vpackage(link(head), saved(1), (int) saved(0), MAX_DIMEN);
  217.         pop_nest();
  218.         tail_append(new_noad());
  219.         type(tail) = VCENTER_NOAD;
  220.         math_type(nucleus(tail)) = SUB_BOX;
  221.         info(nucleus(tail)) = p;
  222.         break;
  223.     
  224.     case MATH_CHOICE_GROUP:
  225.         build_choices();
  226.         break;
  227.  
  228.     case MATH_GROUP:
  229.         unsave();
  230.         decr(save_ptr);
  231.         math_type(saved(0)) = SUB_MLIST;
  232.         p = fin_mlist(NULL);
  233.         info(saved(0)) = p;
  234.         if (p != NULL) {
  235.             if (link(p) == NULL) {
  236.                 if (type(p) == ORD_NOAD) {
  237.                     if (math_type(subscr(p)) == EMPTY &&
  238.                         math_type(supscr(p)) == EMPTY) {
  239.                         mem[saved(0)].hh = mem[nucleus(p)].hh;
  240.                         free_node(p, NOAD_SIZE);
  241.                     }
  242.                 } else if (type(p) == ACCENT_NOAD &&
  243.                     saved(0) == nucleus(tail) &&
  244.                     type(tail) == ORD_NOAD) {
  245.                     q = head;
  246.                     while (link(q) != tail)
  247.                         q = link(q);
  248.                     link(q) = p;
  249.                     free_node(tail, NOAD_SIZE);
  250.                     tail = p;
  251.                 }
  252.             }
  253.         }
  254.         break;
  255.     
  256.     default:
  257.         confusion("rightbrace");
  258.         break;
  259.     }
  260. }
  261.  
  262. extra_right_brace ()
  263. {
  264.     print_err("Extra }, or forgotten ");
  265.     switch (cur_group) 
  266.     {
  267.     case SEMI_SIMPLE_GROUP:
  268.         print_esc("endgroup");
  269.         break;
  270.  
  271.     case MATH_SHIFT_GROUP:
  272.         print_char('$');
  273.         break;
  274.  
  275.     case MATH_LEFT_GROUP:
  276.         print_esc("right");
  277.         break;
  278.     }
  279.     help_group_close();
  280.     error();
  281.     incr(align_state);
  282. }
  283.  
  284. scan_spec ()
  285. {
  286.     if (scan_keyword("to")) {
  287.         saved(0) = EXACTLY;
  288.     } else if (scan_keyword("spread")) {
  289.         saved(0) = ADDITIONAL;
  290.     } else {
  291.         saved(0) = ADDITIONAL;
  292.         saved(1) = 0;
  293.         goto found;
  294.     }
  295.     scan_normal_dimen();
  296.     saved(1) = cur_val;
  297.  
  298. found:
  299.     save_ptr += 2;
  300.     scan_left_brace();
  301. }
  302.  
  303. scan_box ()
  304. {
  305.     get_nbrx_token();
  306.     if (cur_cmd == MAKE_BOX) {
  307.         begin_box();
  308.     } else if (saved(0) >= LEADER_FLAG &&
  309.             (cur_cmd == HRULE || cur_cmd == VRULE)) {
  310.             cur_box = scan_rule_spec();
  311.             box_end();
  312.     } else {
  313.         print_err("A <box> was supposed to be here");
  314.         help_box();
  315.         back_error();
  316.     }
  317. }
  318.  
  319. begin_box ()
  320. {
  321.     int     k;
  322.     int     m;
  323.     int     n;
  324.     ptr     p;
  325.     ptr     q;
  326.  
  327.     switch (cur_chr)
  328.     {
  329.     case BOX_CODE:
  330.         scan_eight_bit_int();
  331.         cur_box = box(cur_val);
  332.         box(cur_val) = NULL;
  333.         break;
  334.     
  335.     case COPY_CODE:
  336.         scan_eight_bit_int();
  337.         cur_box = copy_node_list(box(cur_val));
  338.         break;
  339.     
  340.     case LAST_BOX_CODE:
  341.         cur_box = NULL;
  342.         if (abs(mode) == MMODE) {
  343.             you_cant();
  344.             help_lastbox_m();
  345.             error();
  346.         } else if (mode == VMODE && head == tail) {
  347.             you_cant();
  348.             help_lastbox_v();
  349.             error();
  350.         } else if (!is_char_node(tail) &&
  351.             (type(tail) == HLIST_NODE || type(tail) == VLIST_NODE)) {
  352.             q = head;
  353.             do  {
  354.                 p = q;
  355.                 if (!is_char_node(q) && type(q) == DISC_NODE) {
  356.                     for (m = 1; m <= replace_count(q); incr(m)) 
  357.                         p = link(p);
  358.                     if (p == tail)
  359.                         break;
  360.                 }
  361.                 q = link(p);
  362.             } while (q != tail);
  363.             cur_box = tail;
  364.             shift_amount(cur_box) = 0;
  365.             tail = p;
  366.             link(p) = NULL;
  367.         }
  368.         break;
  369.  
  370.     case VSPLIT_CODE:
  371.         scan_eight_bit_int();
  372.         n = cur_val;
  373.         if (!scan_keyword("to")) {
  374.             print_err("Missing `to' inserted");
  375.             help_vsplit();
  376.             error();
  377.         }
  378.         scan_normal_dimen();
  379.         cur_box = vsplit(n, cur_val);
  380.         break;
  381.     
  382.     default:
  383.         k = cur_chr - VTOP_CODE;
  384.         incr(save_ptr);
  385.         scan_spec();
  386.         if (k == HMODE) {
  387.             if (saved(-3) < BOX_FLAG && abs(mode) == VMODE)
  388.                 new_save_level(ADJUSTED_HBOX_GROUP);
  389.             else new_save_level(HBOX_GROUP);
  390.         } else {
  391.             if (k == VMODE) {
  392.                 new_save_level(VBOX_GROUP);
  393.             } else {
  394.                 new_save_level(VTOP_GROUP);
  395.                 k = VMODE;
  396.             }
  397.             normal_paragraph();
  398.         }
  399.         push_nest();
  400.         mode = -k;
  401.         if (k == VMODE) {
  402.             prev_depth = IGNORE_DEPTH;
  403.             if (every_vbox != NULL)
  404.                 begin_token_list(every_vbox, EVERY_VBOX_TEXT);
  405.         } else {
  406.             space_factor = 1000;
  407.             if (every_hbox != NULL) 
  408.                 begin_token_list(every_hbox, EVERY_HBOX_TEXT);
  409.         }
  410.         return;
  411.     }
  412.     box_end();
  413. }
  414.  
  415. box_end ()
  416. {
  417.     ptr     p;
  418.  
  419.     if (saved(0) < BOX_FLAG) {
  420.         if (cur_box != NULL) {
  421.             shift_amount(cur_box) = saved(0);
  422.             if (abs(mode) == VMODE) {
  423.                 append_to_vlist(cur_box);
  424.                 if (adjust_tail != NULL) {
  425.                     if (adjust_head != adjust_tail) {
  426.                         link(tail) = link(adjust_head);
  427.                         tail = adjust_tail;
  428.                     }
  429.                     adjust_tail = NULL;
  430.                 }
  431.                 if (mode > 0) 
  432.                     build_page();
  433.             } else {
  434.                 if (abs(mode) == HMODE) {
  435.                     space_factor = 1000;
  436.                 } else {
  437.                     p = new_noad();
  438.                     math_type(nucleus(p)) = SUB_BOX;
  439.                     info(nucleus(p)) = cur_box;
  440.                     cur_box = p;
  441.                 }
  442.                 link(tail) = cur_box;
  443.                 tail = cur_box;
  444.             }
  445.         }
  446.     } else if (saved(0) < SHIP_OUT_FLAG) {
  447.         if (saved(0) < BOX_FLAG + 256)
  448.             eq_define((ptr)(BOX_BASE-BOX_FLAG+saved(0)), BOX_REF, cur_box);
  449.         else
  450.             geq_define((ptr)(BOX_BASE-BOX_FLAG-256+saved(0)), BOX_REF, cur_box);
  451.     } else if (cur_box != NULL) {
  452.         if (saved(0) > SHIP_OUT_FLAG) {
  453.             get_nbrx_token();
  454.             if (cur_cmd == HSKIP && abs(mode) != VMODE ||
  455.                 cur_cmd == VSKIP && abs(mode) == VMODE ||
  456.                 cur_cmd == MSKIP && abs(mode) == MMODE) {
  457.                 append_glue();
  458.                 leader_ptr(tail) = cur_box;
  459.                 subtype(tail) = saved(0) - (LEADER_FLAG - A_LEADERS);
  460.             } else {
  461.                 print_err("Leaders not followed by proper glue");
  462.                 help_leaders();
  463.                 back_error();
  464.                 flush_node_list(cur_box);
  465.             }
  466.         } else {
  467.             ship_out(cur_box);
  468.         }
  469.     }
  470. }
  471.  
  472. package (c)
  473.     int     c;
  474. {
  475.     scal    d;
  476.     scal    h;
  477.     ptr     p;
  478.  
  479.     d = box_max_depth;
  480.     unsave();
  481.     save_ptr -= 3;
  482.     if (mode == -HMODE) {
  483.         cur_box = hpack(link(head), saved(2), (int) saved(1));
  484.     } else {
  485.         cur_box = vpackage(link(head), saved(2), (int) saved(1), d);
  486.         if (c == VTOP_CODE) {
  487.             h = 0;
  488.             p = list_ptr(cur_box);
  489.             if (p != NULL && type(p) <= RULE_NODE)
  490.                 h = height(p);
  491.             depth(cur_box) += height(cur_box) - h;
  492.             height(cur_box) = h;
  493.         }
  494.     }
  495.     pop_nest();
  496.     box_end();
  497. }
  498.  
  499. normal_paragraph ()
  500. {
  501.     if (looseness != 0)
  502.         eq_word_define((ptr) INT_BASE + LOOSENESS_CODE, 0L);
  503.     if (hang_indent != 0)
  504.         eq_word_define((ptr) DIMEN_BASE + HANG_INDENT_CODE, 0L);
  505.     if (hang_after != 1)
  506.         eq_word_define((ptr) INT_BASE + HANG_AFTER_CODE, 1L);
  507.     if (par_shape_ptr != NULL)
  508.         eq_define(PAR_SHAPE_LOC, SHAPE_REF, NULL);
  509. }
  510.  
  511. new_graf (indented)
  512.     bool    indented;
  513. {
  514.     prev_graf = 0;
  515.     if (mode == VMODE || head != tail)
  516.         tail_append(new_param_glue(PAR_SKIP_CODE));
  517.     push_nest();
  518.     mode = HMODE;
  519.     space_factor = 1000;
  520.     if (indented) {
  521.         tail = new_null_box();
  522.         link(head) = tail;
  523.         width(tail) = par_indent;
  524.     }
  525.     if (every_par != NULL)
  526.         begin_token_list(every_par, EVERY_PAR_TEXT);
  527.     if (nest_ptr == 1) 
  528.         build_page();
  529. }
  530.  
  531. indent_in_hmode ()
  532. {
  533.     ptr     p;
  534.     ptr     q;
  535.  
  536.     if (cur_chr > 0) {
  537.         p = new_null_box();
  538.         width(p) = par_indent;
  539.         if (abs(mode) == HMODE) {
  540.             space_factor = 1000;
  541.         } else {
  542.             q = new_noad();
  543.             math_type(nucleus(q)) = SUB_BOX;
  544.             info(nucleus(q)) = p;
  545.             p = q;
  546.         }
  547.         tail_append(p);
  548.     }
  549. }
  550.  
  551. head_for_vmode ()
  552. {
  553.     if (mode < 0) {
  554.         if (cur_cmd != HRULE) {
  555.             off_save();
  556.         } else {
  557.             print_err("You can't use `");
  558.             print_esc("hrule");
  559.             print("' here except with leaders");
  560.             help_head_for_vmode();
  561.             error();
  562.         }
  563.     } else {
  564.         back_input();
  565.         cur_tok = par_token;
  566.         back_input();
  567.         token_type = INSERTED;
  568.     }
  569. }
  570.     
  571. end_graf ()
  572. {
  573.     if (mode == HMODE) {
  574.         if (head == tail)
  575.             pop_nest();
  576.         else line_break(widow_penalty);
  577.         normal_paragraph();
  578.         error_count = 0;
  579.     }
  580. }
  581.  
  582. append_to_vlist (b)
  583.     ptr     b;
  584. {
  585.     scal    d;
  586.     ptr     p;
  587.  
  588.     if (prev_depth > IGNORE_DEPTH) {
  589.         d = width(baseline_skip) - prev_depth - height(b);
  590.         if (d < line_skip_limit) {
  591.             p = new_param_glue(LINE_SKIP_CODE);
  592.         } else {
  593.             p = new_skip_param(BASELINE_SKIP_CODE);
  594.             width(temp_ptr) = d;
  595.         }
  596.         link(tail) = p;
  597.         tail = p;
  598.     }
  599.     link(tail) = b;
  600.     tail = b;
  601.     prev_depth = depth(b);
  602. }
  603.  
  604. begin_insert_or_adjust ()
  605. {
  606.     if (cur_cmd == VADJUST) {
  607.         cur_val = 255;
  608.     } else {
  609.         scan_eight_bit_int();
  610.         if (cur_val == 255) {
  611.             print_err("You can't ");
  612.             print_esc("insert");
  613.             print_int(255);
  614.             help_insert_255();
  615.             error();
  616.             cur_val = 0;
  617.         }
  618.     }
  619.     saved(0) = cur_val;
  620.     incr(save_ptr);
  621.     new_save_level(INSERT_GROUP);
  622.     scan_left_brace();
  623.     normal_paragraph();
  624.     push_nest();
  625.     mode = -VMODE;
  626.     prev_depth = IGNORE_DEPTH;
  627. }
  628.  
  629. make_mark ()
  630. {
  631.     ptr     p;
  632.  
  633.     scan_toks(FALSE, TRUE);
  634.     p = get_node(SMALL_NODE_SIZE);
  635.     type(p) = MARK_NODE;
  636.     subtype(p) = 0;
  637.     mark_ptr(p) = def_ref;
  638.     link(tail) = p;
  639.     tail = p;
  640. }
  641.  
  642. append_penalty ()
  643. {
  644.     scan_int();
  645.     tail_append(new_penalty(cur_val));
  646.     if (mode == VMODE) 
  647.         build_page();
  648. }
  649.  
  650. delete_last ()
  651. {
  652.     qword   m;
  653.     ptr     p;
  654.     ptr     q;
  655.  
  656.     if (mode == VMODE && tail == head) {
  657.         if (cur_chr != GLUE_NODE || last_glue != MAX_HALFWORD) {
  658.             you_cant();
  659.             help_delete_last();
  660.             if (cur_chr == KERN_NODE)
  661.                 help_line[1] = "Try `I\\kern-\\lastkern' instead.";
  662.             else if (cur_chr != GLUE_NODE)
  663.                 help_line[1] = "Perhaps you can make the output routine do it.";
  664.             error();
  665.         }
  666.     } else if (!is_char_node(tail) && type(tail) == cur_chr) {
  667.         q = head;
  668.         do  {
  669.             p = q;
  670.             if (!is_char_node(q) && type(q) == DISC_NODE) {
  671.                 for (m = 1; m <= replace_count(q); incr(m))
  672.                     p = link(p);
  673.                 if (p == tail)
  674.                     return;
  675.             }
  676.             q = link(p);
  677.         } while (q != tail);
  678.         link(p) = NULL;
  679.         flush_node_list(tail);
  680.         tail = p;
  681.     }
  682. }
  683.  
  684. unpackage ()
  685. {   
  686.     int     c;
  687.     ptr     p;
  688.     
  689.     c = cur_chr;
  690.     scan_eight_bit_int();
  691.     p = box(cur_val);
  692.     if (p == NULL) return;
  693.     if (abs(mode) == MMODE ||
  694.         abs(mode) == VMODE && type(p) != VLIST_NODE ||
  695.         abs(mode) == HMODE && type(p) != HLIST_NODE) {
  696.         print_err("Incompatible list can't be unboxed");
  697.         help_pandora();
  698.         error();
  699.         return;
  700.     }
  701.     if (c == COPY_CODE) {
  702.         link(tail) = copy_node_list(list_ptr(p));
  703.     } else {
  704.         link(tail) = list_ptr(p);
  705.         box(cur_val) = NULL;
  706.         free_node(p, BOX_NODE_SIZE);
  707.     }
  708.     while (link(tail) != NULL)
  709.         tail = link(tail);
  710. }
  711.  
  712. append_italic_correction ()
  713. {
  714.     ptr     p;
  715.     fnt     f;
  716.  
  717.     if (tail != head) {
  718.         if (is_char_node(tail))
  719.             p = tail;
  720.         else if (type(tail) == LIGATURE_NODE)
  721.             p = lig_char(tail);
  722.         else return;
  723.         f = font(p);
  724.         tail_append(new_kern(char_italic(f, char_info(f, character(p)))));
  725.         subtype(tail) = EXPLICIT;
  726.     }
  727. }
  728.  
  729. append_discretionary ()
  730. {
  731.     int     c;
  732.  
  733.     tail_append(new_disc());
  734.     if (cur_chr == 1) {
  735.         c = hyphen_char[cur_font];
  736.         if (c >= 0 && c < 256)
  737.             pre_break(tail) = new_character(cur_font, c);
  738.     } else {
  739.         incr(save_ptr);
  740.         saved(-1) = 0;
  741.         scan_left_brace();
  742.         new_save_level(DISC_GROUP);
  743.         push_nest();
  744.         mode = -HMODE;
  745.         space_factor = 1000;
  746.     }
  747. }
  748.  
  749. build_discretionary ()
  750. {
  751.     int     n;
  752.     ptr     p;
  753.     ptr     q;
  754.  
  755.     unsave();
  756.     q = head;
  757.     p = link(q);
  758.     n = 0;
  759.     while (p != NULL) {
  760.         if (!is_char_node(p) && type(p) > RULE_NODE &&
  761.             type(p) != KERN_NODE && type(p) != LIGATURE_NODE) {
  762.             print_err("Improper discretionary list");
  763.             help_discretionary();
  764.             error();
  765.             begin_diagnostic();
  766.             print_nl("The following discretionary sublist has been deleted:");
  767.             show_box(p);
  768.             end_diagnostic(TRUE);
  769.             flush_node_list(p);
  770.             link(q) = NULL;
  771.             break;
  772.         }
  773.         q = p;
  774.         p = link(q);
  775.         incr(n);
  776.     }
  777.     p = link(head);
  778.     pop_nest();
  779.     switch ((int) saved(-1))
  780.     {
  781.     case 0:
  782.         pre_break(tail) = p;
  783.         break;
  784.  
  785.     case 1:
  786.         post_break(tail) = p;
  787.         break;
  788.  
  789.     case 2:
  790.         if (n > 0 && abs(mode) == MMODE) {
  791.             print_err("Illegal math ");
  792.             print_esc("discretionary");
  793.             help_math_disc();
  794.             flush_node_list(p);
  795.             n = 0;
  796.             error();
  797.         } else
  798.             link(tail) = p;
  799.         if (n <= MAX_QUARTERWORD)
  800.             replace_count(tail) = n;
  801.         else {
  802.             print_err("Discretionary list is too long");
  803.             help_disc();
  804.             error();
  805.         }
  806.         if (n > 0) tail = q;
  807.         decr(save_ptr);
  808.         return;
  809.     }
  810.     incr(saved(-1));
  811.     scan_left_brace();
  812.     new_save_level(DISC_GROUP);
  813.     push_nest();
  814.     mode = -HMODE;
  815.     space_factor = 1000;
  816. }
  817.  
  818. make_accent ()
  819. {
  820.     scal    a;
  821.     fnt     f;
  822.     scal    h;
  823.     qqqq    i;
  824.     ptr     p;
  825.     ptr     q;
  826.     ptr     r;
  827.     float   s;
  828.     float   t;
  829.     scal    w;
  830.     scal    x;
  831.     scal    delta;
  832.  
  833.     scan_char_num();
  834.     f = cur_font;
  835.     p = new_character(f, cur_val);
  836.     if (p != NULL) {
  837.         x = x_height(f);
  838.         s = (float) slant(f) / 65536.0;
  839.         a = char_width(f, char_info(f, character(p)));
  840.         do_assignments();
  841.         q = NULL;
  842.         f = cur_font;
  843.         if (cur_cmd == LETTER ||
  844.             cur_cmd == OTHER_CHAR ||
  845.             cur_cmd ==  CHAR_GIVEN) {
  846.             q = new_character(f, cur_chr);
  847.         } else if (cur_cmd ==  CHAR_NUM) {
  848.             scan_char_num();
  849.             q = new_character(f, cur_val);
  850.         } else back_input();
  851.         if (q != NULL) {
  852.             t = (float) slant(f) / 65536.0;
  853.             i = char_info(f, character(q));
  854.             w = char_width(f, i); 
  855.             h = char_height(f, height_depth(i));
  856.             if (h != x) {
  857.                 p = hpack(p, NATURAL);
  858.                 shift_amount(p) = x - h;
  859.             }
  860.             delta = round((float) (w - a) / 2.0 + h * t - x * s);
  861.             r = new_kern(delta);
  862.             subtype(r) = ACC_KERN;
  863.             link(tail) = r;
  864.             link(r) = p;
  865.             tail = new_kern(-a - delta);
  866.             subtype(tail) = ACC_KERN;
  867.             link(p) = tail; p = q;
  868.         }
  869.         link(tail) = p;
  870.         tail = p;
  871.         space_factor = 1000;
  872.     }
  873. }
  874.  
  875. align_error ()
  876. {
  877.     if (abs(align_state) > 2) {
  878.         print_err("Misplaced ");
  879.         print_cmd_chr(cur_cmd, cur_chr);
  880.         if (cur_tok == TAB_TOKEN + '&') 
  881.             help_tab();
  882.         else help_align_error();
  883.         error();
  884.     } else {
  885.         back_input();
  886.         if (align_state < 0) {
  887.             print_err("Missing { inserted");
  888.             incr(align_state);
  889.             cur_tok = LEFT_BRACE_TOKEN + '{';
  890.         } else {
  891.             print_err("Missing } inserted");
  892.             decr(align_state);
  893.             cur_tok = RIGHT_BRACE_TOKEN + '}';
  894.         }
  895.         help_fix_alignment();
  896.         ins_error();
  897.     }
  898. }
  899.  
  900. no_align_error ()
  901. {
  902.     print_err("Misplaced ");
  903.     print_esc("noalign");
  904.     help_noalign();
  905.     error();
  906. }
  907.  
  908. omit_error ()
  909. {
  910.     print_err("Misplaced ");
  911.     print_esc("omit");
  912.     help_omit();
  913.     error();
  914. }
  915.  
  916. do_endv ()
  917. {
  918.     if (cur_group == ALIGN_GROUP) {
  919.         end_graf();
  920.         if (fin_col())
  921.             fin_row();
  922.     } else {
  923.         off_save();
  924.     }
  925. }
  926.  
  927. cs_error ()
  928. {
  929.     print_err("Extra ");
  930.     print_esc("endcsname");
  931.     help_csname();
  932.     error();
  933. }
  934.  
  935. /*
  936.  *  Help text
  937.  */
  938.  
  939. help_head_for_vmode ()
  940. {
  941.     help2("To put a horizontal rule in an hbox or an alignment,",
  942.     "you should use \\leaders or \\hrulefill (see The TeXbook).");
  943. }
  944.  
  945. help_close_group ()
  946. {
  947.     help2("You've closed more groups than you opened.",
  948.     "Such booboos are generally harmless, so keep going.");
  949. }
  950.  
  951. help_output_balance ()
  952. {
  953.     help2("Your sneaky output routine has fewer real {'s than }'s.",
  954.     "I can't handle that very well; good luck.");
  955. }
  956.  
  957. help_output ()
  958. {
  959.     help3("Your \\output commands should empty \\box255,",
  960.     "e.g., by saying `\\shipout\\box255'.",
  961.     "Proceed; I'll discard its present contents.");
  962. }
  963.  
  964. help_group_close ()
  965. {
  966.     help5("I've deleted a group-closing symbol because it seems to be",
  967.     "spurious, as in `$x}$'. But perhaps the } is legitimate and",
  968.     "you forgot something else, as in `\\hbox{$x}'. In such cases",
  969.     "the way to recover is to insert both the forgotten and the",
  970.     "deleted material, e.g., by typing `I$}'.");
  971. }
  972.  
  973. help_leaders ()
  974. {
  975.     help3("You should say `\\leaders <box or rule><hskip or vskip>'.",
  976.     "I found the <box or rule>, but there's no suitable",
  977.     "<hskip or vskip>, so I'm ignoring these leaders.");
  978. }
  979.  
  980. help_lastbox_m ()
  981. {
  982.     help1("Sorry; this \\lastbox will be void.");
  983. }
  984.  
  985. help_lastbox_v ()
  986. {
  987.     help2("Sorry...I usually can't take things from the current page.",
  988.     "This \\lastbox will therefore be void.");
  989. }
  990.  
  991. help_vsplit ()
  992. {
  993.     help2("I'm working on `\\vsplit<box number> to <dimen>';",
  994.     "will look for the <dimen> next.");
  995. }
  996.  
  997. help_box ()
  998. {
  999.     help3("I was expecting to see \\hbox or \\vbox or \\copy or \\box or",
  1000.     "something like that. So you might find something missing in",
  1001.     "your output. But keep trying; you can fix this later.");
  1002. }
  1003.  
  1004. help_insert_255 ()
  1005. {
  1006.     help1("I'm changing to \\insert0; box 255 is special.");
  1007. }
  1008.  
  1009. help_space_fac ()
  1010. {
  1011.     help1("I allow only values in the range 1..65536 here.");
  1012. }
  1013.  
  1014. help_delete_last ()
  1015. {
  1016.     help2("Sorry...I usually can't take things from the current page.",
  1017.     "Try `I\\vskip-\\lastskip' instead.");
  1018. }
  1019.  
  1020. help_pandora ()
  1021. {
  1022.     help3("Sorry, Pandora. (You sneaky devil.)",
  1023.     "I refuse to unbox an \\hbox in vertical mode or vice versa.",
  1024.     "And I can't open any boxes in math mode.");
  1025. }
  1026.  
  1027. help_math_disc ()
  1028. {
  1029.     help2("Sorry: The third part of a discretionary break must be",
  1030.     "empty, in math formulas. I had to delete your third part.");
  1031. }
  1032.  
  1033. help_discretionary ()
  1034. {
  1035.     help1("Discretionary lists must contain only boxes and kerns.");
  1036. }
  1037.  
  1038. help_disc ()
  1039. {
  1040.     help2("Wow---I never thought anybody would tweak me here.",
  1041.     "You can't seriously need such a huge discretionary list?");
  1042. }
  1043.  
  1044. help_missing_the ()
  1045. {
  1046.     help3("Please dont say \\count or \\dimen or \\skip in the midst of",
  1047.     "a paragraph or formula. I'm going to assume that you",
  1048.     "meant to say `\\the\\count' or `\\the\\dimen' or `\\the\\skip',");
  1049. }
  1050.  
  1051. help_tab ()
  1052. {
  1053.     help6("I can't figure out why you would want to use a tab mark",
  1054.     "here. If you just want an ampersand, the remedy is",
  1055.     "simple: Just type `I\\&' now. But if some right brace",
  1056.     "up above has ended a previous alignment prematurely,",
  1057.     "you're probably due for more error messages, and you",
  1058.     "might try typing `S' now just to see what is salvageable.");
  1059. }
  1060.  
  1061. help_align_error ()
  1062. {
  1063.     help5("I can't figure out why you would want to use a tab mark",
  1064.     "or \\cr or \\span just now. If something like a right brace",
  1065.     "up above has ended a previous alignment prematurely,",
  1066.     "you're probably due for more error messages, and you",
  1067.     "might try typing `S' now just to see what is salvageable.");
  1068. }
  1069.  
  1070. help_align_cr ()
  1071. {
  1072.     help1("I'm guessing that you meant to end an alignment here.");
  1073. }
  1074.     
  1075. help_fix_alignment ()
  1076. {
  1077.     help3("I've put in what seems to be necessary to fix",
  1078.     "the current column of the current alignment.",
  1079.     "Try to go on, since this might almost work.");
  1080. }
  1081.  
  1082. help_noalign ()
  1083. {
  1084.     help2("I expect to see \\noalign only after the \\cr of",
  1085.     "an alignment. Proceed, and I'll ignore this case.");
  1086. }
  1087.  
  1088. help_omit ()
  1089. {
  1090.     help2("I expect to see \\omit only after tab marks or the \\cr of",
  1091.     "an alignment. Proceed, and I'll ignore this case.");
  1092. }
  1093.  
  1094. help_csname ()
  1095. {
  1096.     help1("I'm ignoring this, since I wasn't doing a \\csname.");
  1097. }
  1098.