home *** CD-ROM | disk | FTP | other *** search
/ Mega Top 1 / os2_top1.zip / os2_top1 / APPS / TEKST / CMTEX330 / SOURCE / BOXLIST.C < prev    next >
C/C++ Source or Header  |  1992-02-19  |  21KB  |  1,128 lines

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