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

  1.  
  2. /*
  3.  * @(#)box.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 "texext.h"
  15. #include "tfm.h"
  16. #include "math.h"
  17. #include "box.h"
  18. #include "token.h"
  19. #include "tokenlists.h"
  20.  
  21. val     depth_threshold;
  22. val     breadth_max;
  23. fnt     font_in_short_display;
  24.  
  25. ptr
  26. new_null_box ()
  27. {
  28.     ptr     p;
  29.  
  30.     p = get_node(BOX_NODE_SIZE);
  31.     type(p) = HLIST_NODE;
  32.     subtype(p) = MIN_QUARTERWORD;
  33.     width(p) = 0;
  34.     depth(p) = 0;
  35.     height(p) = 0;
  36.     shift_amount(p) = 0;
  37.     list_ptr(p) = NULL;
  38.     glue_sign(p) = NORMAL;
  39.     glue_order(p) = NORMAL;
  40.     glue_set(p) = 0.0;
  41.  
  42.     return p;
  43. }
  44.  
  45. ptr
  46. new_rule ()
  47. {
  48.     ptr      p;
  49.  
  50.     p = get_node(RULE_NODE_SIZE);
  51.     type(p) = RULE_NODE;
  52.     subtype(p) = 0;
  53.     width(p) = NULL_FLAG;
  54.     depth(p) = NULL_FLAG;
  55.     height(p) = NULL_FLAG;
  56.  
  57.     return p;
  58. }
  59.  
  60. ptr
  61. new_ligature (f, c, q)
  62.     qword   f;
  63.     qword   c;
  64.     ptr     q;
  65. {
  66.     ptr     p;
  67.  
  68.     p = get_node(SMALL_NODE_SIZE);
  69.     type(p) = LIGATURE_NODE;
  70.     subtype(p) = 0;
  71.     font(lig_char(p)) = f;
  72.     character(lig_char(p)) = c;
  73.     lig_ptr(p) = q;
  74.  
  75.     return p;
  76. }
  77.  
  78. ptr
  79. new_disc ()
  80. {
  81.     ptr     p;
  82.  
  83.     p = get_node(SMALL_NODE_SIZE);
  84.     type(p) = DISC_NODE;
  85.     replace_count(p) = 0;
  86.     pre_break(p) = NULL;
  87.     post_break(p) = NULL;
  88.  
  89.     return p;
  90. }
  91.  
  92. ptr
  93. new_math (w, s)
  94.     scal    w;
  95.     int     s;
  96. {
  97.     ptr     p;
  98.  
  99.     p = get_node(SMALL_NODE_SIZE);
  100.     type(p) = MATH_NODE;
  101.     subtype(p) = s;
  102.     width(p) = w;
  103.  
  104.     return p;
  105. }
  106.  
  107. ptr
  108. new_spec (p)
  109.     ptr     p;
  110. {
  111.     ptr     q;
  112.  
  113.     q = get_node(GLUE_SPEC_SIZE);
  114.     mem[q] = mem[p];
  115.     glue_ref_count(q) = NULL;
  116.     width(q) = width(p);
  117.     stretch(q) = stretch(p);
  118.     shrink(q) = shrink(p);
  119.  
  120.     return q;
  121. }
  122.  
  123. ptr
  124. new_param_glue (n)
  125.     int     n;
  126. {
  127.     ptr     p;
  128.     ptr     q;
  129.  
  130.     p = get_node(SMALL_NODE_SIZE);
  131.     type(p) = GLUE_NODE;
  132.     subtype(p) = n + 1;
  133.     leader_ptr(p) = NULL;
  134.     q = glue_par(n);
  135.     glue_ptr(p) = q;
  136.     incr(glue_ref_count(q));
  137.  
  138.     return p;
  139. }
  140.  
  141. ptr
  142. new_glue (q)
  143.     ptr     q;
  144. {
  145.     ptr     p;
  146.  
  147.     p = get_node(SMALL_NODE_SIZE);
  148.     type(p) = GLUE_NODE;
  149.     subtype(p) = NORMAL;
  150.     leader_ptr(p) = NULL;
  151.     glue_ptr(p) = q;
  152.     incr(glue_ref_count(q));
  153.  
  154.     return p;
  155. }
  156.  
  157. ptr
  158. new_skip_param (n)
  159.     int     n;
  160. {
  161.     ptr     p;
  162.  
  163.     temp_ptr = new_spec(glue_par(n));
  164.     p = new_glue(temp_ptr);
  165.     glue_ref_count(temp_ptr) = NULL;
  166.     subtype(p) = n + 1;
  167.  
  168.     return p;
  169. }
  170.  
  171. ptr
  172. new_kern (w)
  173.     scal    w;
  174. {
  175.     ptr     p;
  176.  
  177.     p = get_node(SMALL_NODE_SIZE);
  178.     type(p) = KERN_NODE;
  179.     subtype(p) = NORMAL;
  180.     width(p) = w;
  181.  
  182.     return p;
  183. }
  184.  
  185. ptr
  186. new_penalty (m)
  187.     val     m;
  188. {
  189.     ptr     p;
  190.  
  191.     p = get_node(SMALL_NODE_SIZE);
  192.     type(p) = PENALTY_NODE;
  193.     subtype(p) = 0;
  194.     penalty(p) = m;
  195.  
  196.     return p;
  197. }
  198.  
  199. print_font_and_char (p)
  200.     ptr     p;
  201. {
  202.     if (p > mem_end) {
  203.         print_esc("CLOBBERED.");
  204.     } else {
  205.         if (font(p) < FONT_BASE || font(p) > FONT_MAX) {
  206.             print_char('*');
  207.         } else {
  208.             print_esc("");
  209.             print_str(font_id_text(font(p)));
  210.             print_char(' ');
  211.             print_ASCII(qo(character(p)));
  212.         }
  213.     }
  214. }
  215.  
  216. print_mark (p)
  217.     ptr     p;
  218. {
  219.     print_char('{');
  220.     if (p < 0 || p > tok_end)
  221.         print_esc("CLOBBERED.");
  222.     else show_token_list(token_link(p), NULL, (val) MAX_PRINT_LINE - 10);
  223.     print_char('}');
  224. }
  225.  
  226. print_rule_dimen (d)
  227.     scal    d;
  228. {
  229.     if (is_running(d))
  230.         print_char('*');
  231.     else print_scaled(d);
  232. }
  233.  
  234. print_glue (d, o, s)
  235.     scal    d;
  236.     qword   o;
  237.     char*   s;
  238. {
  239.     print_scaled(d);
  240.     if (o < NORMAL || o > FILLL) {
  241.         print("foul");
  242.     } else if (o > NORMAL) {
  243.         print("fil");
  244.         while  (o >  FIL) {
  245.             print_char('l');
  246.             decr(o);
  247.         }
  248.     } else if (s) {
  249.         print(s);
  250.     }
  251. }
  252.  
  253. print_spec (p, s)
  254.     ptr     p;
  255.     chrs    s;
  256. {
  257.     if (p < MEM_MIN || p >= hi_mem_min) {
  258.         print_char('*');
  259.     } else {
  260.         print_scaled(width(p));
  261.         print(s);
  262.         if (stretch(p) != 0) {
  263.             print(" plus ");
  264.             print_glue(stretch(p), stretch_order(p), s);
  265.         }
  266.         if (shrink(p) != 0) {
  267.             print(" minus ");
  268.             print_glue(shrink(p), shrink_order(p), s);
  269.         }
  270.     }
  271. }
  272.  
  273. short_display (p)
  274.     ptr     p;
  275. {
  276.     int     n;
  277.  
  278.     for (; p > NULL; p = link(p)) {
  279.         if (is_char_node(p) && p <= mem_end) {
  280.             if (font(p) != font_in_short_display) {
  281.                 if (font(p) < FONT_BASE || font(p) > FONT_MAX) {
  282.                     print_char('*');
  283.                 } else {
  284.                     print_esc("");
  285.                     print_str(font_id_text(font(p)));
  286.                 }
  287.                 print_char(' ');
  288.                 font_in_short_display = font(p);
  289.             }
  290.             print_ASCII(qo(character(p)));
  291.         } else {
  292.             switch (type(p))
  293.             {
  294.             case HLIST_NODE:
  295.             case VLIST_NODE: 
  296.             case INS_NODE:
  297.             case WHATSIT_NODE:
  298.             case MARK_NODE:
  299.             case ADJUST_NODE:
  300.             case UNSET_NODE:
  301.                 print("[]");
  302.                 break;
  303.  
  304.             case RULE_NODE:
  305.                 print_char('|');
  306.                 break;
  307.  
  308.             case GLUE_NODE:
  309.                 if (glue_ptr(p) != zero_glue)
  310.                     print_char(' ');
  311.                 break;
  312.  
  313.             case MATH_NODE:
  314.                 print_char('$');
  315.                 break;
  316.  
  317.             case LIGATURE_NODE:
  318.                 short_display(lig_ptr(p));
  319.                 break;
  320.  
  321.             case DISC_NODE:
  322.                 short_display(pre_break(p));
  323.                 short_display(post_break(p));
  324.                 n = replace_count(p);
  325.                 while (n > 0) {
  326.                     if (link(p) != NULL)
  327.                         p = link(p);
  328.                     decr(n);
  329.                 }
  330.                 break;
  331.  
  332.             default:
  333.                 break;
  334.             }
  335.         }
  336.     }
  337. }
  338.  
  339. show_box (p)
  340.     ptr     p;
  341. {
  342.     depth_threshold = show_box_depth;
  343.     breadth_max = show_box_breadth;
  344.     if (breadth_max <= 0)
  345.         breadth_max = 5;
  346.     if (pool_ptr + depth_threshold >= POOL_SIZE)
  347.         depth_threshold = POOL_SIZE - pool_ptr - 1;
  348.     show_node_list(p);
  349. }
  350.  
  351. show_box1 (p)
  352.     ptr     p;
  353. {
  354.     if (type(p) == HLIST_NODE)
  355.         print_esc("h");
  356.     else if (type(p) == VLIST_NODE)
  357.         print_esc("v");
  358.     else print_esc("unset");
  359.     print("box(");
  360.     print_scaled(height(p));
  361.     print_char('+') ;
  362.     print_scaled(depth(p));
  363.     print(")x") ;
  364.     print_scaled(width(p));
  365.     if (type(p) == UNSET_NODE) {
  366.         if (span_count(p) != MIN_QUARTERWORD) {
  367.             print(" (");
  368.             print_int(qo(span_count(p))+1);
  369.             print(" columns)");
  370.         }
  371.         if (glue_stretch(p) != 0) {
  372.             print(", stretch ");
  373.             print_glue(glue_stretch(p), glue_order(p), "");
  374.         }
  375.         if (glue_shrink(p) != 0) {
  376.             print(", shrink ");
  377.             print_glue(glue_shrink(p), glue_sign(p), "");
  378.         }
  379.     } else {
  380.         show_glue_set(p);
  381.         if (shift_amount(p) != 0) {
  382.             print(", shifted ");
  383.             print_scaled(shift_amount(p));
  384.         }
  385.     }
  386.     node_list_display(list_ptr(p));
  387. }
  388.  
  389. show_glue_set (p)
  390.     ptr     p;
  391. {
  392.     if (glue_set(p) != 0 && glue_sign(p) != NORMAL) {
  393.         print(", glue set ");
  394.         if (glue_sign(p) == SHRINKING)
  395.             print("- ");
  396.         if (abs(glue_set(p)) > 20000.0) {
  397.             if (glue_set(p) > 0)
  398.                 print_char('>');
  399.             else print("< -");
  400.             print_glue(20000 * UNITY, glue_order(p), "");
  401.         } else {
  402.             print_glue(round(glue_set(p) * UNITY), glue_order(p), "");
  403.         }
  404.     }
  405. }
  406.  
  407. show_rule (p)
  408.     ptr     p;
  409. {
  410.     print_esc("rule(");
  411.     print_rule_dimen(height(p));
  412.     print_char('+');
  413.     print_rule_dimen(depth(p));
  414.     print(")x");
  415.     print_rule_dimen(width(p));
  416. }
  417.  
  418. show_insertion (p)
  419.     ptr     p;
  420. {
  421.     print_esc("insert");
  422.     print_int(qo(subtype(p)));
  423.     print(", natural size ");
  424.     print_scaled(height(p));
  425.     print("; split(");
  426.     print_spec(split_top_ptr(p), "");
  427.     print_char(',');
  428.     print_scaled(depth(p));
  429.     print("); float cost ");
  430.     print_val(float_cost(p));
  431.     node_list_display(ins_ptr(p));
  432. }
  433.  
  434. show_leaders (p)
  435.     ptr     p;
  436. {
  437.     print_esc("");
  438.     if (subtype(p) == C_LEADERS)
  439.         print_char('c');
  440.     else if (subtype(p) == X_LEADERS)
  441.         print_char('x');
  442.     print("leaders ");
  443.     print_spec(glue_ptr(p), "");
  444.     node_list_display(leader_ptr(p));
  445. }
  446.  
  447. show_glue (p)
  448.     ptr     p;
  449. {
  450.     if (subtype(p) >= A_LEADERS) {
  451.         show_leaders(p);
  452.     } else {
  453.         print_esc("glue");
  454.         if (subtype(p) != NORMAL) {
  455.             print_char('(');
  456.             if (subtype(p) < COND_MATH_GLUE)
  457.                 print_skip_param(subtype(p) - 1);
  458.             else if (subtype(p) == COND_MATH_GLUE)
  459.                 print_esc("nonscript");
  460.             else print_esc("mskip");
  461.             print_char(')');
  462.         }
  463.         if (subtype(p) != COND_MATH_GLUE) {
  464.             print_char(' ');
  465.             if (subtype(p) < COND_MATH_GLUE)
  466.                 print_spec(glue_ptr(p), "");
  467.             else print_spec(glue_ptr(p), "mu");
  468.         }
  469.     }
  470. }
  471.  
  472. show_kern (p)
  473.     ptr     p;
  474. {
  475.     if (subtype(p) != MU_GLUE) {
  476.         print_esc("kern");
  477.         if (subtype(p) != NORMAL)
  478.             print_char(' ');
  479.         print_scaled(width(p));
  480.         if (subtype(p) == ACC_KERN)
  481.             print(" (for accent)");
  482.     } else {
  483.         print_esc("mkern");
  484.         print_scaled(width(p));
  485.         print("mu");
  486.     }
  487. }
  488.  
  489. show_math (p)
  490.     ptr     p;
  491. {
  492.     print_esc("math");
  493.     if (subtype(p) == BEFORE)
  494.         print("on");
  495.     else print("off");
  496.     if (width(p) != 0) {
  497.         print(", surrounded ");
  498.         print_scaled(width(p));
  499.     }
  500. }
  501.     
  502. show_ligature (p)
  503.     ptr     p;
  504. {
  505.     print_font_and_char(lig_char(p));
  506.     print(" (ligature ");
  507.     font_in_short_display = font(lig_char(p));
  508.     short_display(lig_ptr(p));
  509.     print_char(')');
  510. }
  511.  
  512. show_discretionary (p)
  513.     ptr     p;
  514. {
  515.     print_esc("discretionary");
  516.     if (replace_count(p) > 0) {
  517.         print(" replacing ");
  518.         print_int(replace_count(p));
  519.     }
  520.     node_list_display(pre_break(p));
  521.     append_char('|');
  522.     show_node_list(post_break(p));
  523.     flush_char();
  524. }
  525.  
  526. show_penalty (p)
  527.     ptr     p;
  528. {
  529.     print_esc("penalty ");
  530.     print_val(penalty(p));
  531. }
  532.  
  533. show_mark (p)
  534.     ptr     p;
  535. {
  536.     print_esc("mark");
  537.     print_mark(mark_ptr(p));
  538. }
  539.  
  540. show_adjust (p)
  541.     ptr     p;
  542. {
  543.     print_esc("vadjust");
  544.     node_list_display(adjust_ptr(p));
  545. }
  546.  
  547. show_node_list (p)
  548.     ptr     p;
  549. {
  550.     int     n;
  551.  
  552.     if (cur_length() > depth_threshold) {
  553.         if (p > NULL)
  554.             print(" []");
  555.         return;
  556.     }
  557.     n = 0;
  558.     while (p > NULL) {
  559.         print_ln();
  560.         print_cur_str();
  561.         if (p > mem_end) {
  562.             print("Bad link, display aborted.");
  563.             return;
  564.         }
  565.         incr(n);
  566.         if (n > breadth_max) {
  567.             print("etc.");
  568.             return;
  569.         }
  570.         if (is_char_node(p)) {
  571.             print_font_and_char(p);
  572.         } else {
  573.             switch (type(p))
  574.             {
  575.             case HLIST_NODE:
  576.             case VLIST_NODE:
  577.             case UNSET_NODE:
  578.                 show_box1(p);
  579.                 break;
  580.  
  581.             case RULE_NODE:
  582.                 show_rule(p);
  583.                 break;
  584.             
  585.             case INS_NODE:
  586.                 show_insertion(p);
  587.                 break;
  588.             
  589.             case WHATSIT_NODE:
  590.                 show_whatsit(p);
  591.                 break;
  592.             
  593.             case GLUE_NODE:
  594.                 show_glue(p);
  595.                 break;
  596.             
  597.             case KERN_NODE:
  598.                 show_kern(p);
  599.                 break;
  600.             
  601.             case MATH_NODE:
  602.                 show_math(p);
  603.                 break;
  604.             
  605.             case LIGATURE_NODE:
  606.                 show_ligature(p);
  607.                 break;
  608.  
  609.             case PENALTY_NODE:
  610.                 show_penalty(p);
  611.                 break;
  612.         
  613.             case DISC_NODE:
  614.                 show_discretionary(p);
  615.                 break;
  616.             
  617.             case MARK_NODE:
  618.                 show_mark(p);
  619.                 break;
  620.             
  621.             case ADJUST_NODE:
  622.                 show_adjust(p);
  623.                 break;
  624.             
  625.             case STYLE_NODE:
  626.                 print_style(subtype(p));
  627.                 break;
  628.             
  629.             case CHOICE_NODE:
  630.                 show_choice_node(p);
  631.                 break;
  632.  
  633.             case INNER_NOAD:
  634.             case ORD_NOAD:
  635.             case OP_NOAD:
  636.             case BIN_NOAD:
  637.             case REL_NOAD:
  638.             case OPEN_NOAD:
  639.             case CLOSE_NOAD:
  640.             case PUNCT_NOAD:
  641.             case RADICAL_NOAD:
  642.             case OVER_NOAD:
  643.             case UNDER_NOAD:
  644.             case VCENTER_NOAD:
  645.             case ACCENT_NOAD:
  646.             case LEFT_NOAD:
  647.             case RIGHT_NOAD:
  648.                 show_normal_noad(p);
  649.                 break;
  650.             
  651.             case FRACTION_NOAD:
  652.                 show_fraction_noad(p);
  653.                 break;
  654.  
  655.             default:
  656.                 print("Unknown node type!");
  657.                 break;
  658.             }
  659.         }
  660.         p = link(p);
  661.     }
  662. }
  663.  
  664. show_info ()
  665. {
  666.     show_node_list(info(temp_ptr));
  667. }
  668.  
  669. delete_glue_ref (p)
  670.     ptr     p;
  671. {
  672.     if (glue_ref_count(p) == NULL)
  673.         free_node(p, GLUE_SPEC_SIZE);
  674.     else decr(glue_ref_count(p));
  675. }
  676.  
  677. flush_node_list (p)
  678.     ptr     p;
  679. {
  680.     ptr     q;
  681.  
  682.     while (p != NULL) {
  683.         q = link(p);
  684.         if (is_char_node(p)) {
  685.             free_avail(p);
  686.         } else {
  687.             switch (type(p))
  688.             {
  689.             case HLIST_NODE:
  690.             case VLIST_NODE:
  691.             case UNSET_NODE:
  692.                 flush_node_list(list_ptr(p));
  693.                 free_node(p, BOX_NODE_SIZE);
  694.                 goto done;
  695.                     
  696.             case RULE_NODE:
  697.                 free_node(p, RULE_NODE_SIZE);
  698.                 goto done;
  699.  
  700.             case INS_NODE:
  701.                 flush_node_list(ins_ptr(p));
  702.                 delete_glue_ref(split_top_ptr(p));
  703.                 free_node(p, INS_NODE_SIZE);
  704.                 goto done;
  705.  
  706.             case WHATSIT_NODE:
  707.                 free_whatsit(p);
  708.                 goto done;
  709.             
  710.             case GLUE_NODE:
  711.                 fast_delete_glue_ref(glue_ptr(p));
  712.                 if (leader_ptr(p) != NULL)
  713.                     flush_node_list(leader_ptr(p));
  714.                 break;
  715.  
  716.             case KERN_NODE:
  717.             case MATH_NODE:
  718.             case PENALTY_NODE:
  719.                 break;
  720.  
  721.             case LIGATURE_NODE:
  722.                 flush_node_list(lig_ptr(p));
  723.                 break;
  724.  
  725.             case MARK_NODE:
  726.                 delete_token_ref(mark_ptr(p));
  727.                 break;
  728.             
  729.             case DISC_NODE:
  730.                 flush_node_list(pre_break(p));
  731.                 flush_node_list(post_break(p));
  732.                 break;
  733.  
  734.             case ADJUST_NODE:
  735.                 flush_node_list(adjust_ptr(p));
  736.                 break;
  737.  
  738.             case STYLE_NODE:
  739.                 free_node(p, STYLE_NODE_SIZE);
  740.                 goto done;
  741.  
  742.             case CHOICE_NODE:
  743.                 flush_node_list(display_mlist(p));
  744.                 flush_node_list(text_mlist(p));
  745.                 flush_node_list(script_mlist(p));
  746.                 flush_node_list(script_script_mlist(p));
  747.                 free_node(p, STYLE_NODE);
  748.                 goto done;
  749.  
  750.             case ORD_NOAD:
  751.             case OP_NOAD:
  752.             case BIN_NOAD:
  753.             case REL_NOAD:
  754.             case OPEN_NOAD:
  755.             case CLOSE_NOAD:
  756.             case PUNCT_NOAD:
  757.             case INNER_NOAD:
  758.             case RADICAL_NOAD:
  759.             case OVER_NOAD:
  760.             case UNDER_NOAD:
  761.             case VCENTER_NOAD:
  762.             case ACCENT_NOAD:
  763.                 if (math_type(nucleus(p)) >= SUB_BOX)
  764.                     flush_node_list(info(nucleus(p)));
  765.                 if (math_type(supscr(p)) >= SUB_BOX)
  766.                     flush_node_list(info(supscr(p)));
  767.                 if (math_type(subscr(p)) >= SUB_BOX)
  768.                     flush_node_list(info(subscr(p)));
  769.                 if (type(p) == RADICAL_NOAD)
  770.                     free_node(p, RADICAL_NOAD_SIZE);
  771.                 else if (type(p) == ACCENT_NOAD)
  772.                     free_node(p, ACCENT_NOAD_SIZE);
  773.                 else free_node(p, NOAD_SIZE);
  774.                 goto done;
  775.             
  776.             case LEFT_NOAD:
  777.             case RIGHT_NOAD:
  778.                 free_node(p, NOAD_SIZE);
  779.                 goto done;
  780.             
  781.             case FRACTION_NOAD:
  782.                 flush_node_list(info(numerator(p)));
  783.                 flush_node_list(info(denominator(p)));
  784.                 free_node(p, FRACTION_NOAD_SIZE);
  785.                 goto done;
  786.  
  787.             default:
  788.                 confusion("flushing");
  789.                 break;
  790.             }
  791.             free_node(p, SMALL_NODE_SIZE);
  792.             done:;  
  793.         }
  794.         p = q;
  795.     }
  796. }
  797.  
  798. ptr
  799. copy_node_list (p)
  800.     ptr     p;
  801. {
  802.     ptr     h;
  803.     ptr     q;
  804.     ptr     r;
  805.     int     words;
  806.  
  807.     h = get_avail();
  808.     q = h;
  809.     while (p != NULL) {
  810.         words = 1;
  811.         if (is_char_node(p)) {
  812.             r = get_avail();
  813.         } else {
  814.             switch (type(p))
  815.             {
  816.             case HLIST_NODE:
  817.             case VLIST_NODE:
  818.             case UNSET_NODE:
  819.                 r = get_node(BOX_NODE_SIZE);
  820.                 mem[r + 6] = mem[p + 6];
  821.                 mem[r + 5] = mem[p + 5];
  822.                 list_ptr(r) = copy_node_list(list_ptr(p));
  823.                 words = 5;
  824.                 break;
  825.             
  826.             case RULE_NODE:
  827.                 r = get_node(RULE_NODE_SIZE);
  828.                 words = RULE_NODE_SIZE;
  829.                 break;
  830.  
  831.             case INS_NODE:
  832.                 r = get_node(INS_NODE_SIZE);
  833.                 mem[r + 4] = mem[p + 4];
  834.                 add_glue_ref(split_top_ptr(p));
  835.                 ins_ptr(r) = copy_node_list(ins_ptr(p));
  836.                 words = INS_NODE_SIZE - 1;
  837.                 break;
  838.  
  839.             case WHATSIT_NODE:
  840.                 r = copy_whatsit(p);
  841.                 break;
  842.             
  843.             case GLUE_NODE:
  844.                 r = get_node(SMALL_NODE_SIZE);
  845.                 add_glue_ref(glue_ptr(p));
  846.                 glue_ptr(r) = glue_ptr(p);
  847.                 leader_ptr(r) = copy_node_list(leader_ptr(p));
  848.                 break;
  849.             
  850.             case KERN_NODE:
  851.             case MATH_NODE:
  852.             case PENALTY_NODE:
  853.                 r = get_node(SMALL_NODE_SIZE);
  854.                 words = SMALL_NODE_SIZE;
  855.                 break;
  856.             
  857.             case LIGATURE_NODE:
  858.                 r = get_node(SMALL_NODE_SIZE);
  859.                 mem[lig_char(r)] = mem[lig_char(p)];
  860.                 lig_ptr(r) = copy_node_list(lig_ptr(p));
  861.                 break;
  862.                 
  863.             case DISC_NODE:
  864.                 r = get_node(SMALL_NODE_SIZE);
  865.                 pre_break(r) = copy_node_list(pre_break(p));
  866.                 post_break(r) = copy_node_list(post_break(p));
  867.                 break;
  868.  
  869.             case MARK_NODE:
  870.                 r = get_node(SMALL_NODE_SIZE);
  871.                 add_token_ref(mark_ptr(p));
  872.                 words = SMALL_NODE_SIZE;
  873.                 break;
  874.  
  875.             case ADJUST_NODE:
  876.                 r = get_node(SMALL_NODE_SIZE);
  877.                 adjust_ptr(r) = copy_node_list(adjust_ptr(p));
  878.                 break;
  879.             
  880.             default:
  881.                 confusion("copying");
  882.                 break;
  883.             }
  884.         }
  885.         while (words > 0) {
  886.             decr(words);
  887.             mem[r + words] = mem[p + words];
  888.         }
  889.         link(q) = r;
  890.         q = r;
  891.         p = link(p);
  892.     }
  893.     link(q) = NULL;
  894.     q = link(h);
  895.     free_avail(h);
  896.     return q;
  897. }
  898.