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

  1.  
  2. /*
  3.  * @(#)par.c 2.9 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 "tfm.h"
  15. #include "tokenstack.h"
  16. #include "evalstack.h"
  17. #include "box.h"
  18. #include "pack.h"
  19. #include "hyph.h"
  20. #include "par.h"
  21.  
  22. ptr     cur_p;
  23.  
  24. ptr     passive;
  25.  
  26. scal    background[7];
  27. scal    break_width[7];
  28. scal    active_width[7];
  29. scal    cur_active_width[7];
  30.  
  31. val     threshold;
  32. bool    second_pass;
  33. scal    first_indent;
  34. scal    first_width;
  35. scal    second_indent;
  36. scal    second_width;
  37.  
  38. val     fewest_demerits;
  39. val     minimum_demerits;
  40. val     minimal_demerits[4];
  41.  
  42. ptr     best_bet;
  43. hword   best_line;
  44. hword   best_pl_line[4];
  45. ptr     best_place[4];
  46.  
  47. hword   easy_line;
  48. hword   last_special_line;
  49. int     line_diff;
  50. scal    disc_width;
  51. hword   pass_number;
  52. ptr     printed_node;
  53. val     actual_looseness;
  54. bool    no_shrink_error_yet;
  55.  
  56. ptr     just_box;
  57.  
  58. #define act_width   active_width[1]
  59.  
  60. #define store_background(W) \
  61.     (active_width[W] = background[W])
  62.  
  63. #define store_break_width(W) \
  64.     (active_width[W] = break_width[W])
  65.  
  66. #define update_active(W) \
  67.     (active_width[W] += mem[r + W].sc)
  68.  
  69. #define copy_to_cur_active(W) \
  70.     (cur_active_width[W] = active_width[W])
  71.  
  72. #define downdate_width(W) \
  73.     (cur_active_width[W] -= mem[prev_r + W].sc)
  74.  
  75. #define update_width(W) \
  76.     (cur_active_width[W] += mem[r + W].sc)
  77.  
  78. #define set_break_width_to_background(W) \
  79.     (break_width[W] = background[W])
  80.  
  81. #define combine_two_deltas(W) \
  82.     (mem[prev_r + W].sc += mem[r + W].sc)
  83.  
  84. #define convert_to_break_width(W) \
  85.     (mem[prev_r + W].sc = \
  86.          mem[prev_r + W].sc + break_width[W] - cur_active_width[W])
  87.  
  88. #define new_delta_to_break_width(W) \
  89.     (mem[q + W].sc = break_width[W] - cur_active_width[W])
  90.  
  91. #define new_delta_from_break_width(W) \
  92.     (mem[q + W].sc = cur_active_width[W] - break_width[W])
  93.  
  94. #define width_lig_char(C) \
  95.     char_width(font(lig_char(C)), \
  96.                 char_info(font(lig_char(C)), character(lig_char(C))))
  97.  
  98. #define width_char(C) \
  99.     char_width(font(C), char_info(font(C), character(C)))
  100.         
  101.  
  102. #define kern_break() \
  103.     {if (!is_char_node(link(cur_p)) && auto_breaking && \
  104.         type(link(cur_p)) == GLUE_NODE) \
  105.         try_break(0L, UNHYPHENATED); \
  106.     act_width += width(cur_p);}
  107.  
  108. #define check_shrinkage(G) \
  109.     {if (shrink_order(G) != NORMAL && shrink(G) != 0) \
  110.         G = finite_shrink(G);}
  111.  
  112. line_break (final_widow_penalty)
  113.     val     final_widow_penalty;
  114. {
  115.     ptr     q;
  116.     ptr     r;
  117.     ptr     s;
  118.     ptr     prev_p;
  119.     bool    auto_breaking;
  120.  
  121.     pack_begin_line = mode_line;
  122.     link(temp_head) = link(head);
  123.     if (is_char_node(tail)) {
  124.         tail_append(new_penalty(INF_PENALTY));
  125.     } else if (type(tail) != GLUE_NODE) {
  126.         tail_append(new_penalty(INF_PENALTY));
  127.     } else {
  128.         type(tail) = PENALTY_NODE;
  129.         delete_glue_ref(glue_ptr(tail));
  130.         flush_node_list(leader_ptr(tail));
  131.         penalty(tail) = INF_PENALTY;
  132.     }
  133.     link(tail) = new_param_glue(PAR_FILL_SKIP_CODE);
  134.     pop_nest();
  135.     no_shrink_error_yet = TRUE;
  136.     check_shrinkage(left_skip);
  137.     check_shrinkage(right_skip);
  138.     q = left_skip;
  139.     r = right_skip;
  140.     background[1] = width(q) + width(r);
  141.     background[2] = 0;
  142.     background[3] = 0;
  143.     background[4] = 0;
  144.     background[5] = 0;
  145.     background[2 + stretch_order(q)] = stretch(q);
  146.     background[2 + stretch_order(r)] += stretch(r);
  147.     background[6] = shrink(q) + shrink(r);
  148.     minimum_demerits = AWFUL_BAD;
  149.     minimal_demerits[VERY_LOOSE_FIT] = AWFUL_BAD;
  150.     minimal_demerits[LOOSE_FIT] = AWFUL_BAD;
  151.     minimal_demerits[DECENT_FIT] = AWFUL_BAD;
  152.     minimal_demerits[TIGHT_FIT] = AWFUL_BAD;
  153.     if (par_shape_ptr == NULL) {
  154.         if (hang_indent == 0) {
  155.             last_special_line = 0;
  156.             second_width = hsize;
  157.             second_indent = 0;
  158.         } else {
  159.             last_special_line = abs(hang_after);
  160.             if (hang_after < 0) {
  161.                 first_width = hsize - abs(hang_indent);
  162.                 first_indent = (hang_indent >= 0 ? hang_indent : 0);
  163.                 second_width = hsize;
  164.                 second_indent = 0;
  165.             } else {
  166.                 first_width = hsize;
  167.                 first_indent = 0;
  168.                 second_width = hsize - abs(hang_indent);
  169.                 second_indent = (hang_indent >= 0 ? hang_indent : 0);
  170.             }
  171.         }
  172.     } else {
  173.         last_special_line = info(par_shape_ptr) - 1;
  174.         second_width = mem[par_shape_ptr + 2 * (last_special_line + 1)].sc;
  175.         second_indent = mem[par_shape_ptr + 2 * last_special_line + 1].sc;
  176.     }
  177.     easy_line = (looseness == 0) ? last_special_line : MAX_HALFWORD;
  178.     threshold = pretolerance;
  179.     if (threshold >= 0) {
  180.         if (tracing_paragraphs > 0) {
  181.             begin_diagnostic();
  182.             print_nl("@firstpass");
  183.         } 
  184.         second_pass = FALSE;
  185.     } else {
  186.         threshold = tolerance;
  187.         second_pass = TRUE;
  188.         if (tracing_paragraphs > 0)
  189.             begin_diagnostic();
  190.     }
  191.     loop {
  192.         q = get_node(ACTIVE_NODE_SIZE);
  193.         type(q) = UNHYPHENATED;
  194.         fitness(q) = DECENT_FIT;
  195.         link(q) = last_active;
  196.         break_node(q) = NULL;
  197.         line_number(q) = prev_graf + 1;
  198.         total_demerits(q) = 0;
  199.         link(active) = q;
  200.         do_all_six(store_background);
  201.         passive = NULL;
  202.         printed_node = temp_head;
  203.         pass_number = 0;
  204.         font_in_short_display = null_font;
  205.         cur_p = link(temp_head);
  206.         auto_breaking = TRUE;
  207.         prev_p = cur_p;
  208.         while (cur_p != NULL && link(active) != last_active) {
  209.             if (is_char_node(cur_p)) {
  210.                 prev_p = cur_p;
  211.                 do {
  212.                     act_width += width_char(cur_p);
  213.                     cur_p = link(cur_p);
  214.                 } while (is_char_node(cur_p));
  215.             }
  216.             switch (type(cur_p))
  217.             {
  218.             case HLIST_NODE:
  219.             case VLIST_NODE:
  220.             case RULE_NODE:
  221.                 act_width += width(cur_p);
  222.                 break;
  223.             
  224.             case WHATSIT_NODE:
  225.                 break;
  226.             
  227.             case GLUE_NODE:
  228.                 if (auto_breaking) {
  229.                     if (is_char_node(prev_p))
  230.                         try_break(0L, UNHYPHENATED);
  231.                     else if (precedes_break(prev_p)) 
  232.                         try_break(0L, UNHYPHENATED);
  233.                 }
  234.                 check_shrinkage(glue_ptr(cur_p));
  235.                 q = glue_ptr(cur_p);
  236.                 act_width += width(q);
  237.                 active_width[2 + stretch_order(q)] += stretch(q);
  238.                 active_width[6] += shrink(q);
  239.                 if (second_pass && auto_breaking) 
  240.                     try_hyph();
  241.                 break;
  242.             
  243.             case KERN_NODE:
  244.                 kern_break();
  245.                 break;
  246.             
  247.             case LIGATURE_NODE:
  248.                 act_width += width_lig_char(cur_p);
  249.                 break;
  250.             
  251.             case DISC_NODE:
  252.                 s = pre_break(cur_p);
  253.                 disc_width = 0;
  254.                 if (s == NULL) {
  255.                     try_break(ex_hyphen_penalty, HYPHENATED);
  256.                 } else {
  257.                     do {
  258.                         if (is_char_node(s)) {
  259.                             disc_width += width_char(s);
  260.                         } else {
  261.                             switch (type(s))
  262.                             {
  263.                             case LIGATURE_NODE:
  264.                                 disc_width += width_lig_char(s);
  265.                                 break;
  266.                             
  267.                             case HLIST_NODE:
  268.                             case VLIST_NODE:
  269.                             case RULE_NODE:
  270.                             case KERN_NODE:
  271.                                 disc_width += width(s);
  272.                                 break;
  273.                             
  274.                             default:
  275.                                 confusion("disc3");
  276.                                 break;
  277.                             }
  278.                         }
  279.                         s = link(s);
  280.                     } while (s != NULL);
  281.                     act_width += disc_width;
  282.                     try_break(hyphen_penalty, HYPHENATED);
  283.                     act_width -= disc_width;
  284.                 }
  285.                 break;
  286.             
  287.             case MATH_NODE:
  288.                 auto_breaking = (subtype(cur_p) == AFTER);
  289.                 kern_break();
  290.                 break;
  291.             
  292.             case PENALTY_NODE:
  293.                 try_break(penalty(cur_p), UNHYPHENATED);
  294.                 break;
  295.             
  296.             case MARK_NODE:
  297.             case INS_NODE:
  298.             case ADJUST_NODE:
  299.                 break;
  300.             
  301.             default:
  302.                 confusion("paragraph");
  303.                 break;
  304.             }
  305.             prev_p = cur_p;
  306.             cur_p = link(cur_p);
  307.         }
  308.         if (cur_p == NULL) {
  309.             try_break(EJECT_PENALTY, HYPHENATED);
  310.             if (link(active) != last_active) {
  311.                 r = link(active);
  312.                 fewest_demerits = AWFUL_BAD;
  313.                 do {
  314.                     if (type(r) != DELTA_NODE &&
  315.                         total_demerits(r) < fewest_demerits) {
  316.                         fewest_demerits = total_demerits(r);
  317.                         best_bet = r;
  318.                     }
  319.                     r = link(r);
  320.                 } while (r != last_active);
  321.                 best_line = line_number(best_bet);
  322.                 if (looseness == 0)
  323.                     goto done;
  324.                 r = link(active);
  325.                 actual_looseness = 0;
  326.                 do {
  327.                     if (type(r) != DELTA_NODE) {
  328.                         line_diff = (int) line_number(r) - (int) best_line;
  329.                         if (line_diff < actual_looseness &&
  330.                             looseness <= line_diff ||   
  331.                             line_diff > actual_looseness &&
  332.                             looseness >= line_diff) {
  333.                             best_bet = r;
  334.                             actual_looseness = line_diff;
  335.                             fewest_demerits = total_demerits(r);
  336.                         } else if (line_diff == actual_looseness && 
  337.                             total_demerits(r) < fewest_demerits) {
  338.                             best_bet = r;
  339.                             fewest_demerits = total_demerits(r);
  340.                         }
  341.                     }
  342.                     r = link(r);
  343.                 } while (r != last_active);
  344.                 best_line = line_number(best_bet);
  345.                 if (actual_looseness == looseness || second_pass)
  346.                     goto done;
  347.             }
  348.         }
  349.         for (q = link(active); q != last_active; q = cur_p) {
  350.             cur_p = link(q);
  351.             if (type(q) == DELTA_NODE)
  352.                 free_node(q, DELTA_NODE_SIZE);
  353.             else free_node(q, ACTIVE_NODE_SIZE);
  354.         }
  355.         for (q = passive; q != NULL; q = cur_p) {
  356.             cur_p = link(q);
  357.             free_node(q, PASSIVE_NODE_SIZE);
  358.         }
  359.         if (tracing_paragraphs > 0)
  360.             print_nl("@secondpass"); 
  361.         threshold = tolerance;
  362.         second_pass = TRUE;
  363.     }
  364.  
  365. done:
  366.     if (tracing_paragraphs > 0)
  367.         end_diagnostic(TRUE);
  368.         
  369.     post_line_break(final_widow_penalty);
  370.     for (q = link(active); q != last_active; q = cur_p) {
  371.         cur_p = link(q);
  372.         if (type(q) == DELTA_NODE)
  373.             free_node(q, DELTA_NODE_SIZE);
  374.         else free_node(q, ACTIVE_NODE_SIZE);
  375.     }
  376.     for (q = passive; q != NULL; q = cur_p) {
  377.         cur_p = link(q);
  378.         free_node(q, PASSIVE_NODE_SIZE);
  379.     }
  380.     pack_begin_line = 0;
  381. }
  382.  
  383. try_break (pi, break_type)
  384.     val     pi;
  385.     int     break_type;
  386. {
  387.     val     b;
  388.     val     d;
  389.     hword   l;
  390.     ptr     q;
  391.     ptr     r;
  392.     hword   old_l;
  393.     ptr     prev_r;
  394.     int     fit_class;
  395.     scal    shortfall;
  396.     scal    line_width;
  397.     ptr     prev_prev_r;
  398.     bool    no_break_yet;
  399.     bool    artificial_badness;
  400.     bool    node_r_stays_active;
  401.     
  402.     no_break_yet = TRUE;
  403.     old_l = 0;
  404.     prev_r = active;
  405.     if (abs(pi) >= INF_PENALTY) {
  406.         if (pi > 0) {
  407.             update_printed_node();
  408.             return;
  409.         } else {
  410.             pi = EJECT_PENALTY;
  411.         }
  412.     }
  413.     do_all_six(copy_to_cur_active);
  414.     loop {
  415.         r = link(prev_r);
  416.         if (type(r) == DELTA_NODE) {
  417.             do_all_six(update_width);
  418.             prev_prev_r = prev_r;
  419.             prev_r = r;
  420.             continue;
  421.         }
  422.         l = line_number(r);
  423.         if (l > old_l) {
  424.             if (minimum_demerits < AWFUL_BAD &&
  425.                 (old_l != easy_line || r == last_active)) {
  426.                 if (no_break_yet) {
  427.                     no_break_yet = FALSE;
  428.                     set_break_width(break_type);
  429.                 }
  430.                 if (type(prev_r) == DELTA_NODE) {
  431.                     do_all_six(convert_to_break_width);
  432.                 } else if (prev_r == active) {
  433.                     do_all_six(store_break_width);
  434.                 } else {
  435.                     q = get_node(DELTA_NODE_SIZE);
  436.                     link(q) = r;
  437.                     type(q) = DELTA_NODE;
  438.                     subtype(q) = 0;
  439.                     do_all_six(new_delta_to_break_width);
  440.                     link(prev_r) = q;
  441.                     prev_prev_r = prev_r;
  442.                     prev_r = q;
  443.                 }
  444.                 minimum_demerits += abs(adj_demerits);
  445.                 fit_class = VERY_LOOSE_FIT;
  446.                 while (fit_class <= TIGHT_FIT) {
  447.                     if (minimal_demerits[fit_class] <= minimum_demerits) {
  448.                         q = get_node(PASSIVE_NODE_SIZE);
  449.                         link(q) = passive;
  450.                         passive = q;
  451.                         cur_break(q) = cur_p;
  452.                         incr(pass_number);
  453.                         serial(q) = pass_number;
  454.                         prev_break(q) = best_place[fit_class];
  455.                         q = get_node(ACTIVE_NODE_SIZE);
  456.                         break_node(q) = passive;
  457.                         line_number(q) = best_pl_line[fit_class] + 1;
  458.                         fitness(q) = fit_class;
  459.                         type(q) = break_type;
  460.                         total_demerits(q) = minimal_demerits[fit_class];
  461.                         link(q) = r;
  462.                         link(prev_r) = q;
  463.                         prev_r = q;
  464.                         if (tracing_paragraphs > 0)
  465.                             show_break_node(q, fit_class, break_type);
  466.                     }
  467.                     minimal_demerits[fit_class] = AWFUL_BAD;
  468.                     incr(fit_class);
  469.                 }
  470.                 minimum_demerits = AWFUL_BAD;
  471.                 if (r != last_active) {
  472.                     q = get_node(DELTA_NODE_SIZE);
  473.                     link(q) = r;
  474.                     type(q) = DELTA_NODE;
  475.                     subtype(q) = 0;
  476.                     do_all_six(new_delta_from_break_width);
  477.                     link(prev_r) = q;
  478.                     prev_prev_r = prev_r;
  479.                     prev_r = q;
  480.                 }
  481.             }
  482.             if (r == last_active) {
  483.                 update_printed_node();
  484.                 return;
  485.             }
  486.             if (l > easy_line) {
  487.                 line_width = second_width;
  488.                 old_l = MAX_HALFWORD - 1;
  489.             } else {
  490.                 old_l = l;
  491.                 if (l > last_special_line)
  492.                     line_width = second_width;
  493.                 else if (par_shape_ptr == NULL)
  494.                     line_width = first_width;
  495.                 else line_width = mem[par_shape_ptr + 2 * l].sc;
  496.             }
  497.         }
  498.         artificial_badness = FALSE;
  499.         shortfall = line_width - cur_active_width[1];
  500.         if (shortfall > 0) {
  501.             if (cur_active_width[3] != 0 ||
  502.                 cur_active_width[4] != 0 ||
  503.                 cur_active_width[5] != 0) {
  504.                 b = 0;
  505.                 fit_class = DECENT_FIT;
  506.             } else {
  507.                 if (shortfall > 7230584 && cur_active_width[2] < 1663497) {
  508.                     b = INF_BAD;
  509.                     fit_class = VERY_LOOSE_FIT;
  510.                     goto done;
  511.                 }
  512.                 b = badness(shortfall, cur_active_width[2]);
  513.                 if (b > 12)
  514.                     if (b > 99)
  515.                         fit_class = VERY_LOOSE_FIT;
  516.                     else fit_class = LOOSE_FIT;
  517.                 else fit_class = DECENT_FIT;
  518.             }
  519.         } else {
  520.             if (-shortfall > cur_active_width[6])
  521.                 b = INF_BAD + 1;
  522.             else b = badness(-shortfall, cur_active_width[6]);
  523.             if (b > 12)
  524.                 fit_class = TIGHT_FIT;
  525.             else fit_class = DECENT_FIT;
  526.         }
  527.         
  528.     done:
  529.         if (b > INF_BAD || pi == EJECT_PENALTY) {
  530.             if (second_pass &&
  531.                 minimum_demerits == AWFUL_BAD &&
  532.                 link(r) == last_active &&
  533.                 prev_r == active) {
  534.                 b = 0;
  535.                 artificial_badness = TRUE;
  536.             } else if (b > threshold)
  537.                 goto deactivate;
  538.             node_r_stays_active = FALSE;
  539.         } else {
  540.             prev_r = r;
  541.             if (b > threshold)
  542.                 continue;
  543.             node_r_stays_active = TRUE;
  544.         }
  545.         d = line_penalty + b;
  546.         d = d * d;
  547.         if (pi != 0) {
  548.             if (pi > 0)
  549.                 d += pi * pi;
  550.             else if (pi > EJECT_PENALTY)
  551.                 d -= pi * pi;
  552.         }
  553.         if (break_type == HYPHENATED && type(r) == HYPHENATED) {
  554.             if (cur_p != NULL)
  555.                 d += double_hyphen_demerits;
  556.             else d += final_hyphen_demerits;
  557.         }
  558.         if (abs(fit_class - (int) fitness(r)) > 1)
  559.             d += adj_demerits;
  560.         if (tracing_paragraphs > 0)
  561.             show_break_status(r, artificial_badness, b, pi, d);
  562.         d += total_demerits(r);
  563.         if (d <= minimal_demerits[fit_class]) {
  564.             minimal_demerits[fit_class] = d;
  565.             best_place[fit_class] = break_node(r);
  566.             best_pl_line[fit_class] = l;
  567.             if (d < minimum_demerits)
  568.                 minimum_demerits = d;
  569.         }
  570.         if (node_r_stays_active) continue;
  571.         
  572.     deactivate:
  573.         link(prev_r) = link(r);
  574.         free_node(r, ACTIVE_NODE_SIZE);
  575.         if (prev_r == active) {
  576.             r = link(active);
  577.             if (type(r) == DELTA_NODE) {
  578.                 do_all_six(update_active);
  579.                 do_all_six(copy_to_cur_active);
  580.                 link(active) = link(r);
  581.                 free_node(r, DELTA_NODE_SIZE);
  582.             }
  583.         } else if (type(prev_r) == DELTA_NODE) {
  584.             r = link(prev_r);
  585.             if (r == last_active) {
  586.                 do_all_six(downdate_width);
  587.                 link(prev_prev_r) = last_active;
  588.                 free_node(prev_r, DELTA_NODE_SIZE);
  589.                 prev_r = prev_prev_r;
  590.             } else if (type(r) == DELTA_NODE) {
  591.                 do_all_six(update_width);
  592.                 do_all_six(combine_two_deltas);
  593.                 link(prev_r) = link(r);
  594.                 free_node(r, DELTA_NODE_SIZE);
  595.             }
  596.         }
  597.     }
  598. }
  599.  
  600. post_line_break (final_widow_penalty)
  601.     val     final_widow_penalty;
  602. {
  603.     ptr     q;
  604.     ptr     r;
  605.     ptr     s;
  606.     int     t;
  607.     val     pen;
  608.     hword   cur_line;
  609.     scal    cur_width;
  610.     scal    cur_indent;
  611.     bool    disc_break;
  612.  
  613.     q = break_node(best_bet);
  614.     cur_p = NULL;
  615.     do {
  616.         r = q;
  617.         q = prev_break(q);
  618.         next_break(r) = cur_p;
  619.         cur_p = r;
  620.     } while (q != NULL);
  621.     cur_line = prev_graf + 1;
  622.     do {
  623.         q = cur_break(cur_p);
  624.         disc_break = FALSE;
  625.         if (q != NULL) {
  626.             if (type(q) == GLUE_NODE) {
  627.                 delete_glue_ref(glue_ptr(q));
  628.                 glue_ptr(q) = right_skip;
  629.                 subtype(q) = RIGHT_SKIP_CODE + 1;
  630.                 add_glue_ref(right_skip);
  631.                 goto done;
  632.             } else {
  633.                 if (type(q) == DISC_NODE) {
  634.                     t = replace_count(q);
  635.                     if (t == 0) {
  636.                         r = link(q);
  637.                     } else {
  638.                         r = q;
  639.                         while (t > 1) {
  640.                             r = link(r);
  641.                             decr(t);
  642.                         }
  643.                         s = link(r);
  644.                         if (!is_char_node(s) &&
  645.                             next_break(cur_p) != NULL &&
  646.                             cur_break(next_break(cur_p)) == s)
  647.                             s = r;
  648.                         r = link(s);
  649.                         link(s) = NULL;
  650.                         flush_node_list(link(q));
  651.                         replace_count(q) = 0;
  652.                     }
  653.                     if (post_break(q) != NULL) {
  654.                         s = post_break(q);
  655.                         while (link(s) != NULL)
  656.                             s = link(s);
  657.                         link(s) = r;
  658.                         r = post_break(q);
  659.                         post_break(q) = NULL;
  660.                     }
  661.                     if (pre_break(q) != NULL) {
  662.                         s = pre_break(q);
  663.                         link(q) = s;
  664.                         while (link(s) != NULL)
  665.                             s = link(s);
  666.                         pre_break(q) = NULL;
  667.                         q = s;
  668.                     }
  669.                     link(q) = r;
  670.                     disc_break = TRUE;
  671.                 } else if (type(q) == MATH_NODE || type(q) == KERN_NODE) {
  672.                     width(q) = 0;
  673.                 }
  674.             }
  675.         } else {
  676.             q = temp_head; 
  677.             while (link(q) != NULL)
  678.                 q = link(q);
  679.         }
  680.         r = new_param_glue(RIGHT_SKIP_CODE);
  681.         link(r) = link(q);
  682.         link(q) = r;
  683.         q = r;
  684.  
  685.     done:
  686.         r = link(q);
  687.         link(q) = NULL;
  688.         q = link(temp_head);
  689.         link(temp_head) = r;
  690.         if (left_skip != zero_glue) {
  691.             r = new_param_glue(LEFT_SKIP_CODE);
  692.             link(r) = q;
  693.             q = r;
  694.         }
  695.         if (cur_line > last_special_line) {
  696.             cur_width = second_width;
  697.             cur_indent = second_indent;
  698.         } else if (par_shape_ptr == NULL) {
  699.             cur_width = first_width;
  700.             cur_indent = first_indent;
  701.         } else {
  702.             cur_width = mem[par_shape_ptr + 2 * cur_line].sc;
  703.             cur_indent = mem[par_shape_ptr + 2 * cur_line - 1].sc;
  704.         }
  705.         adjust_tail = adjust_head;
  706.         just_box = hpack(q, cur_width, EXACTLY);
  707.         shift_amount(just_box) = cur_indent;
  708.         append_to_vlist(just_box);
  709.         if (adjust_head != adjust_tail) {
  710.             link(tail) = link(adjust_head);
  711.             tail = adjust_tail;
  712.         }
  713.         adjust_tail = NULL;
  714.         if (cur_line + 1 != best_line) {
  715.             pen = inter_line_penalty;
  716.             if (cur_line == prev_graf + 1)
  717.                 pen += club_penalty;
  718.             if (cur_line + 2 == best_line)
  719.                 pen += final_widow_penalty;
  720.             if (disc_break)
  721.                 pen += broken_penalty;
  722.             if (pen != 0) {
  723.                 r = new_penalty(pen);
  724.                 link(tail) = r;
  725.                 tail = r;
  726.             }
  727.         }
  728.         incr(cur_line);
  729.         cur_p = next_break(cur_p);
  730.         if (cur_p != NULL) {
  731.             r = temp_head;
  732.             loop {
  733.                 q = link(r);
  734.                 if (q == cur_break(cur_p))
  735.                     break;
  736.                 if (is_char_node(q))
  737.                     break;
  738.                 if (non_discardable(q))
  739.                     break;
  740.                 if (subtype(q) == ACC_KERN && type(q) == KERN_NODE)
  741.                     break;
  742.                 r = q;
  743.             }
  744.             if (r != temp_head) {
  745.                 link(r) = NULL;
  746.                 flush_node_list(link(temp_head));
  747.                 link(temp_head) = q;
  748.             }
  749.         }
  750.     } while (cur_p != NULL);
  751.     if (cur_line != best_line || link(temp_head) != NULL)
  752.         confusion("line breaking");
  753.     prev_graf = best_line - 1;
  754. }
  755.  
  756. set_break_width (break_type)
  757.     int     break_type;
  758. {
  759.     ptr     s;
  760.     int     t;
  761.     ptr     v;
  762.  
  763.     do_all_six(set_break_width_to_background);
  764.     if (break_type == UNHYPHENATED || cur_p == NULL) {
  765.         for (s = cur_p; s != NULL; s = link(s)) {
  766.             if (is_char_node(s))
  767.                 return;
  768.             switch (type(s))
  769.             {
  770.             case GLUE_NODE:
  771.                 v = glue_ptr(s);
  772.                 break_width[1] -= width(v);
  773.                 break_width[2 + stretch_order(v)] -= stretch(v);
  774.                 break_width[6] -= shrink(v);
  775.                 break;
  776.             
  777.             case PENALTY_NODE:
  778.                 break;
  779.             
  780.             case MATH_NODE:
  781.             case KERN_NODE:
  782.                 if (subtype(s) == ACC_KERN) 
  783.                     return;
  784.                 else break_width[1] -= width(s);
  785.                 break;
  786.  
  787.             default:
  788.                 return;
  789.                 break;
  790.             }
  791.         }
  792.     } else {
  793.         t = replace_count(cur_p);
  794.         s = cur_p;
  795.         while (t > 0) {
  796.             decr(t);
  797.             s = link(s);
  798.             if (is_char_node(s))
  799.                 break_width[1] -= width_char(s);
  800.             else {
  801.                 switch (type(s))
  802.                 {
  803.                 case LIGATURE_NODE:
  804.                     break_width[1] -= width_lig_char(s);
  805.                     break;
  806.  
  807.                 case HLIST_NODE:
  808.                 case VLIST_NODE:
  809.                 case RULE_NODE:
  810.                 case KERN_NODE:
  811.                     break_width[1] -= width(s);
  812.                     break;
  813.  
  814.                 default:
  815.                     confusion("disc1");
  816.                     break;
  817.                 }
  818.             }
  819.         }
  820.         for (s = post_break(cur_p); s != NULL; s = link(s)) {
  821.             if (is_char_node(s))
  822.                 break_width[1] += width_char(s);
  823.             else {
  824.                 switch (type(s))
  825.                 {
  826.                 case LIGATURE_NODE:
  827.                     break_width[1] += width_lig_char(s);
  828.                     break;
  829.  
  830.                 case HLIST_NODE:
  831.                 case VLIST_NODE:
  832.                 case RULE_NODE:
  833.                 case KERN_NODE:
  834.                     break_width[1] += width(s);
  835.                     break;
  836.  
  837.                 default:
  838.                     confusion("disc2");
  839.                     break;
  840.                 }
  841.             }
  842.         }
  843.         break_width[1] += disc_width;
  844.     }
  845. }
  846.  
  847. #if 0
  848. set_break_width (break_type)
  849.     int     break_type;
  850. {
  851.     ptr     s;
  852.     int     t;
  853.     ptr     v;
  854.  
  855.     do_all_six(set_break_width_to_background);
  856.     s = cur_p;
  857.     if (break_type > UNHYPHENATED && cur_p != NULL) {
  858.         t = replace_count(cur_p);
  859.         v = cur_p;
  860.         while (t > 0) {
  861.             decr(t);
  862.             v = link(v);
  863.             if (is_char_node(v)) {
  864.                 break_width[1] -= width_char(v);
  865.             } else {
  866.                 switch (type(v))
  867.                 {
  868.                 case LIGATURE_NODE:
  869.                     break_width[1] -= width_lig_char(v);
  870.                     break;
  871.  
  872.                 case HLIST_NODE:
  873.                 case VLIST_NODE:
  874.                 case RULE_NODE:
  875.                 case KERN_NODE:
  876.                     break_width[1] -= width(v);
  877.                     break;
  878.  
  879.                 default:
  880.                     confusion("disc1");
  881.                     break;
  882.                 }
  883.             }
  884.         }
  885.         for (s = post_break(cur_p); s != NULL; s = link(s)) {
  886.             if (is_char_node(s)) {
  887.                 break_width[1] += width_char(s);
  888.             } else {
  889.                 switch (type(s))
  890.                 {
  891.                 case LIGATURE_NODE:
  892.                     break_width[1] += width_lig_char(s);
  893.                     break;
  894.  
  895.                 case HLIST_NODE:
  896.                 case VLIST_NODE:
  897.                 case RULE_NODE:
  898.                     break_width[1] += width(s);
  899.                     break;
  900.  
  901.                 case KERN_NODE:
  902.                     if (t == 0 && subtype(s) != ACC_KERN)
  903.                         t = -1;
  904.                     else break_width[1] += width(s);
  905.                     break;
  906.  
  907.                 default:
  908.                     confusion("disc2");
  909.                     break;
  910.                 }
  911.             }
  912.             incr(t);
  913.         }
  914.         break_width[1] += disc_width;
  915.         if (t == 0)
  916.             s = link(v);
  917.     }
  918.     for (s; s != NULL; s = link(s)) {
  919.         if (is_char_node(s))
  920.             return;
  921.         switch (type(s))
  922.         {
  923.         case GLUE_NODE:
  924.             v = glue_ptr(s);
  925.             break_width[1] -= width(v);
  926.             break_width[2 + stretch_order(v)] -= stretch(v);
  927.             break_width[6] -= shrink(v);
  928.             break;
  929.         
  930.         case PENALTY_NODE:
  931.             break;
  932.         
  933.         case MATH_NODE:
  934.         case KERN_NODE:
  935.             if (subtype(s) == ACC_KERN) 
  936.                 return;
  937.             else break_width[1] -= width(s);
  938.             break;
  939.  
  940.         default:
  941.             return;
  942.         }
  943.     }
  944. }
  945. #endif
  946.  
  947. show_break_node (q, f, h)
  948.     ptr     q;
  949.     int     f;
  950.     int     h;
  951. {
  952.     print_nl("@@");
  953.     print_int(serial(passive));
  954.     print(": line ");
  955.     print_int(line_number(q) - 1);
  956.     print_char('.');
  957.     print_int(f);
  958.     if (h == HYPHENATED)
  959.         print_char('-');
  960.     print(" t=");
  961.     print_val(total_demerits(q));
  962.     print(" -> @@");
  963.     if (prev_break(passive) == NULL)
  964.         print("0");
  965.     else print_int(serial(prev_break(passive)));
  966. }
  967.  
  968. show_break_status (r, a, b, p, d)
  969.     ptr     r;
  970.     bool    a;
  971.     val     b;
  972.     val     p;
  973.     val     d;
  974. {
  975.     ptr     save_link;
  976.  
  977.     if (printed_node != cur_p) {
  978.         print_nl("");
  979.         if (cur_p == NULL) {
  980.             short_display(link(printed_node));
  981.         } else {
  982.             save_link = link(cur_p);
  983.             link(cur_p) = NULL;
  984.             print_nl("");
  985.             short_display(link(printed_node));
  986.             link(cur_p) = save_link;
  987.         }
  988.         printed_node = cur_p;
  989.     }
  990.     print_nl("@");
  991.     if (cur_p == NULL) {
  992.         print_esc("par");
  993.     } else if (type(cur_p) != GLUE_NODE) {
  994.         if (type(cur_p) == PENALTY_NODE)
  995.             print_esc("penalty");
  996.         else if (type(cur_p) == DISC_NODE)
  997.             print_esc("discretionary");
  998.         else if (type(cur_p) == KERN_NODE)
  999.             print_esc("kern");
  1000.         else print_esc("math");
  1001.     }
  1002.     print(" via @@");
  1003.     if (break_node(r) == NULL)
  1004.         print_char('0');
  1005.     else print_int(serial(break_node(r)));
  1006.     print(" b=");
  1007.     if (a) print_char('*');
  1008.     else print_val(b);
  1009.     print(" p=");
  1010.     print_val(p);
  1011.     print(" d=");
  1012.     print_val(d);
  1013. }
  1014.  
  1015. update_printed_node ()
  1016. {
  1017.     int     t;
  1018.  
  1019.     if (cur_p == printed_node &&
  1020.         cur_p != NULL &&
  1021.         type(cur_p) == DISC_NODE)
  1022.         for (t = replace_count(cur_p); t > 0; decr(t))
  1023.             printed_node = link(printed_node);
  1024. }
  1025.  
  1026. ptr
  1027. finite_shrink (p)
  1028.     ptr     p;
  1029. {
  1030.     ptr     q;
  1031.  
  1032.     if (no_shrink_error_yet) {
  1033.         no_shrink_error_yet = FALSE;
  1034.         print_err("Infinite glue shrinkage found in a paragraph");
  1035.         help_shrink();
  1036.         error();
  1037.     }
  1038.     q = new_spec(p);
  1039.     shrink_order(q) = NORMAL;
  1040.     delete_glue_ref(p);
  1041.     return q;
  1042. }
  1043.  
  1044. /*
  1045.  *  Help text
  1046.  */
  1047.  
  1048. help_shrink()
  1049. {
  1050.     help5("The paragraph just ended includes some glue that has",
  1051.     "infinite shrinkability, e.g., `\\hskip 0pt minus 1fil'.",
  1052.     "Such glue doesn't belong there---it allows a paragraph",
  1053.     "of any length to fit on one line. But it's safe to proceed,",
  1054.     "since the offensive shrinkability has been made finite.");
  1055. }
  1056.