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

  1.  
  2. /*
  3.  * %Y%:%M%:%I%:%Q%
  4.  *
  5.  * Copyright 1987,1988,1991,1992 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. fnt    cur_f;
  20. int    cur_c;
  21. qcell    cur_i;
  22.  
  23. int    cur_style;
  24. int    cur_size;
  25. scal    cur_mu;
  26.  
  27. #define change_size_and_mu() \
  28. {    if (cur_style < SCRIPT_STYLE) { \
  29.         cur_size = TEXT_SIZE; \
  30.     } else { \
  31.         cur_size = 16 * ((cur_style - TEXT_STYLE) / 2); \
  32.     } \
  33.     cur_mu = x_over_n(math_quad(cur_size), 18); \
  34. }
  35.  
  36. int    magic_offset = - 9 * ORD_NOAD;
  37.  
  38. char    math_spacing[] = 
  39.     "0234000122*4000133**3**344*0400400*000000234000111*1111112341011";
  40.  
  41. #define new_hlist(N)        link(nucleus(N))
  42.  
  43. ptr
  44. mlist_to_hlist (mlist, style, penalties)
  45.     ptr    mlist;
  46.     int    style;
  47.     bool    penalties;
  48. {
  49.     ptr    h;
  50.     ptr    p;
  51.     ptr    q;
  52.     ptr    r;
  53.     int    s;
  54.     int    t;
  55.     ptr    x;
  56.     ptr    y;
  57.     ptr    z;
  58.     int    pen;
  59.     scal    delta;
  60.     scal    max_d;
  61.     scal    max_h;
  62.     int    r_type;
  63.     int    save_style;
  64.  
  65.     q = mlist;
  66.     r = null;
  67.     r_type = OP_NOAD;
  68.     max_h = 0;
  69.     max_d = 0;
  70.     cur_style = style;
  71.     change_size_and_mu();
  72.  
  73.     while (q != null)
  74.     {
  75. reswitch:
  76.         delta = 0;
  77.         switch (type(q))
  78.         {
  79.         case BIN_NOAD:    
  80.             switch (r_type)
  81.             {
  82.             case BIN_NOAD:
  83.             case OP_NOAD:
  84.             case REL_NOAD:
  85.             case OPEN_NOAD:
  86.             case PUNCT_NOAD:
  87.             case LEFT_NOAD:
  88.                 type(q) = ORD_NOAD;
  89.                 goto reswitch;
  90.  
  91.             default:
  92.                 break;
  93.             }
  94.             break;
  95.  
  96.         case REL_NOAD:
  97.         case CLOSE_NOAD:
  98.         case PUNCT_NOAD:
  99.         case RIGHT_NOAD:
  100.             if (r_type == BIN_NOAD) {
  101.                 type(r) = ORD_NOAD;
  102.             }
  103.             if (type(q) == RIGHT_NOAD) {
  104.                 goto done_with_noad;
  105.             }
  106.             break;
  107.  
  108.         case LEFT_NOAD:
  109.             goto done_with_noad;
  110.  
  111.         case FRACTION_NOAD:
  112.             make_fraction(q);
  113.             goto check_dimensions;
  114.         
  115.         case OP_NOAD:
  116.             delta = make_op(q);
  117.             if (subtype(q) == LIMITS) {
  118.                 goto check_dimensions;
  119.             }
  120.             break;
  121.  
  122.         case ORD_NOAD:
  123.             make_ord(q);
  124.             break;
  125.  
  126.         case OPEN_NOAD:
  127.         case INNER_NOAD:
  128.             break;
  129.         
  130.         case RADICAL_NOAD:
  131.             make_radical(q);
  132.             break;
  133.         
  134.         case OVER_NOAD:
  135.             make_over(q);
  136.             break;
  137.  
  138.         case UNDER_NOAD:
  139.             make_under(q);
  140.             break;
  141.     
  142.         case ACCENT_NOAD:
  143.             make_math_accent(q);
  144.             break;
  145.         
  146.         case VCENTER_NOAD:
  147.             make_vcenter(q);
  148.             break;
  149.         
  150.         case STYLE_NODE:
  151.             cur_style = subtype(q);
  152.             change_size_and_mu();
  153.             goto done_with_node;
  154.         
  155.         case CHOICE_NODE:
  156.             switch (cur_style / 2) {
  157. #            define choose_mlist(L)    {p = L(q); L(q) = null;}
  158.             case 0: choose_mlist(display_mlist); break;
  159.             case 1: choose_mlist(text_mlist); break;
  160.             case 2: choose_mlist(script_mlist); break;
  161.             case 3: choose_mlist(script_script_mlist); break;
  162.             }
  163.             flush_node_list(display_mlist(q));
  164.             flush_node_list(text_mlist(q));
  165.             flush_node_list(script_mlist(q));
  166.             flush_node_list(script_script_mlist(q));
  167.             type(q) = STYLE_NODE;
  168.             subtype(q) = cur_style;
  169.             display_mlist(q) = null;
  170.             text_mlist(q) = null;
  171.             script_mlist(q) = null;
  172.             script_script_mlist(q) = null;
  173.             if (p != null) {
  174.                 z = link(q);
  175.                 link(q) = p;
  176.                 while (link(p) != null) {
  177.                     p = link(p);
  178.                 }
  179.                 link(p) = z;
  180.             }
  181.             goto done_with_node;
  182.  
  183.         case INS_NODE:
  184.         case MARK_NODE:
  185.         case ADJUST_NODE:
  186.         case WHATSIT_NODE:
  187.         case PENALTY_NODE:
  188.         case DISC_NODE:
  189.             goto done_with_node;
  190.         
  191.         case RULE_NODE:
  192.             if (rule_height(q) > max_h) {
  193.                 max_h = rule_height(q);
  194.             }
  195.             if (rule_depth(q) > max_d) {
  196.                 max_d = rule_depth(q);
  197.             }
  198.             goto done_with_node;
  199.  
  200.         case GLUE_NODE:
  201.             if (subtype(q) == MU_GLUE) {
  202.                 x = glue_ptr(q);
  203.                 y = math_glue(x, cur_mu);
  204.                 delete_glue_ref(x);
  205.                 glue_ptr(q) = y;
  206.                 subtype(q) = NORMAL;
  207.             } else if (cur_size != TEXT_SIZE
  208.                 && subtype(q) == COND_MATH_GLUE) {
  209.                 p = link(q);
  210.                 if (p != null
  211.                 && (type(p) == GLUE_NODE
  212.                 || type(p) == KERN_NODE)) {
  213.                     link(q) = link(p);
  214.                     link(p) = null;
  215.                     flush_node_list(p);
  216.                 }
  217.             }
  218.             goto done_with_node;
  219.         
  220.         case KERN_NODE:
  221.             math_kern(q, cur_mu);
  222.             goto done_with_node;
  223.         
  224.         default:
  225.             confusion("mlist1");
  226.         }
  227.  
  228.         switch (math_type(nucleus(q)))
  229.         {
  230.         case MATH_CHAR:
  231.         case MATH_TEXT_CHAR:
  232.             fetch(nucleus(q));
  233.             if (char_exists(cur_i)) {
  234.                 delta = char_italic(cur_f, cur_i);
  235.                 p = new_character(cur_f, cur_c);
  236.                 if (math_type(nucleus(q)) == MATH_TEXT_CHAR
  237.                 && space(cur_f) != 0) {
  238.                     delta = 0;
  239.                 }
  240.                 if (math_type(subscr(q)) == EMPTY
  241.                 && delta != 0) {
  242.                     link(p) = new_kern(delta);
  243.                     delta = 0;
  244.                 }
  245.             } else {
  246.                 p = null;
  247.             }
  248.             break;
  249.         
  250.         case EMPTY:
  251.             p = null;
  252.             break;
  253.  
  254.         case SUB_BOX:
  255.             p = math_link(nucleus(q));
  256.             break;
  257.  
  258.         case SUB_MLIST:
  259.             save_style = cur_style;
  260.             p = mlist_to_hlist(math_link(nucleus(q)),
  261.                 cur_style, FALSE);
  262.             cur_style = save_style;
  263.             change_size_and_mu();
  264.             p = hpack(p, NATURAL); 
  265.             break;
  266.  
  267.         default:
  268.             confusion("mlist2");
  269.         }
  270.         new_hlist(q) = p;
  271.         if (math_type(subscr(q)) == EMPTY
  272.         && math_type(supscr(q)) == EMPTY) {
  273.             goto check_dimensions;
  274.         }
  275.         make_scripts(q, delta);
  276.         
  277. check_dimensions:
  278.         z = hpack(new_hlist(q), NATURAL);
  279.         if (box_height(z) > max_h) {
  280.             max_h = box_height(z);
  281.         }
  282.         if (box_depth(z) > max_d) {
  283.             max_d = box_depth(z);
  284.         }
  285.         free_node(z, BOX_NODE_SIZE);
  286.  
  287. done_with_noad:
  288.         r = q;
  289.         r_type = type(r);
  290.  
  291. done_with_node:
  292.         q = link(q);
  293.     } 
  294.  
  295.     if (r_type == BIN_NOAD) {
  296.         type(r) = ORD_NOAD;
  297.     }
  298.     h = p = new_avail();
  299.     link(p) = null;
  300.     q = mlist;
  301.     r_type = 0;
  302.     cur_style = style;
  303.     change_size_and_mu();
  304.  
  305.     while (q != null) {
  306.         t = ORD_NOAD;
  307.         s = NOAD_SIZE;
  308.         pen = INF_PENALTY;
  309.         switch (type(q))
  310.         {
  311.         case OP_NOAD:
  312.         case OPEN_NOAD:
  313.         case CLOSE_NOAD:
  314.         case PUNCT_NOAD:
  315.         case INNER_NOAD:
  316.             t = type(q);
  317.             break;
  318.         
  319.         case BIN_NOAD:
  320.             t = BIN_NOAD;
  321.             pen = bin_op_penalty;
  322.             break;
  323.         
  324.         case REL_NOAD:
  325.             t = REL_NOAD;
  326.             pen = rel_penalty;
  327.             break; 
  328.         
  329.         case ORD_NOAD:
  330.         case VCENTER_NOAD:
  331.         case OVER_NOAD:
  332.         case UNDER_NOAD:
  333.             break;
  334.  
  335.         case RADICAL_NOAD:
  336.             s = RADICAL_NOAD_SIZE;
  337.             break;
  338.  
  339.         case ACCENT_NOAD:
  340.             s = ACCENT_NOAD_SIZE;
  341.             break;
  342.  
  343.         case FRACTION_NOAD:
  344.             t = INNER_NOAD;
  345.             s = FRACTION_NOAD_SIZE;
  346.             break;
  347.  
  348.         case LEFT_NOAD:
  349.         case RIGHT_NOAD:
  350.             t = make_left_right(q, style, max_d, max_h);
  351.             break;
  352.         
  353.         case STYLE_NODE:
  354.             s = STYLE_NODE_SIZE;
  355.             cur_style = subtype(q);
  356.             change_size_and_mu();
  357.             goto delete_q;
  358.  
  359.         case WHATSIT_NODE:
  360.         case PENALTY_NODE:
  361.         case RULE_NODE:
  362.         case DISC_NODE:
  363.         case ADJUST_NODE:
  364.         case INS_NODE:
  365.         case MARK_NODE:
  366.         case GLUE_NODE:
  367.         case KERN_NODE:
  368.             p = link(p) = q;
  369.             q = link(q);
  370.             link(p) = null;
  371.             continue;
  372.         
  373.         default:
  374.             confusion("mlist3");
  375.         }
  376.  
  377.         if (r_type > 0) {
  378.             int    x;
  379.  
  380.             switch (math_spacing[r_type * 8 + t + magic_offset]) 
  381.             {
  382.             case '0':
  383.                 x = -1;
  384.                 break;
  385.  
  386.             case '1':
  387.                 if (cur_style < SCRIPT_STYLE) {
  388.                     x = THIN_MU_SKIP_CODE;
  389.                 } else {
  390.                     x = -1;
  391.                 }
  392.                 break;
  393.  
  394.             case '2':
  395.                 x = THIN_MU_SKIP_CODE;
  396.                 break;
  397.  
  398.             case '3':
  399.                 if (cur_style < SCRIPT_STYLE) {
  400.                     x = MED_MU_SKIP_CODE;
  401.                 } else {
  402.                     x = -1;
  403.                 }
  404.                 break;
  405.  
  406.             case '4':
  407.                 if (cur_style < SCRIPT_STYLE) {
  408.                     x = THICK_MU_SKIP_CODE;
  409.                 } else {
  410.                     x = -1;
  411.                 }
  412.                 break;
  413.  
  414.             default:
  415.                 confusion("mlist4");
  416.                 break;
  417.             }
  418.             if (x >= 0) {
  419.                 y = math_glue(mu_glue_par(x), cur_mu);
  420.                 z = new_glue(y);
  421.                 glue_ref_count(y) = null;
  422.                 p = link(p) = z;
  423.                 subtype(z) = GLUE_PARS + x + 1;
  424.             }
  425.         }
  426.         if (new_hlist(q) != null) {
  427.             link(p) = new_hlist(q);
  428.             do p = link(p);
  429.             while (link(p) != null);
  430.         }
  431.         if (penalties && link(q) != null && pen < INF_PENALTY) {
  432.             r_type = type(link(q));
  433.             if (r_type != PENALTY_NODE && r_type != REL_NOAD) {
  434.                 z = new_penalty(pen);
  435.                 p = link(p) = z;
  436.             }
  437.         }
  438.         r_type = t;
  439.  
  440. delete_q:
  441.         r = q;
  442.         q = link(q);
  443.         free_node(r, s);
  444.     }
  445.     return (link(h));
  446. }
  447.  
  448. void
  449. make_over (q)
  450.     ptr    q;
  451. {
  452.     math_link(nucleus(q)) =
  453.         overbar(clean_box(nucleus(q), cramped_style(cur_style)),
  454.             3 * default_rule_thickness, default_rule_thickness);
  455.     math_type(nucleus(q)) = SUB_BOX;
  456. }
  457.  
  458. void
  459. make_under (q)
  460.     ptr     q;
  461. {
  462.     ptr    p;
  463.     ptr    x;
  464.     ptr    y;
  465.     scal    delta;
  466.  
  467.     x = clean_box(nucleus(q), cur_style);
  468.     link(x) = p = new_kern(3 * default_rule_thickness);
  469.     link(p) = fraction_rule(default_rule_thickness);
  470.     y = vpack(x, NATURAL);
  471.     delta = box_height(y) + box_depth(y) + default_rule_thickness;
  472.     box_height(y) = box_height(x);
  473.     box_depth(y) = delta - box_height(y);
  474.     math_link(nucleus(q)) = y;
  475.     math_type(nucleus(q)) = SUB_BOX;
  476. }
  477.  
  478. void
  479. make_vcenter (q)
  480.     ptr    q;
  481. {
  482.     ptr    v;
  483.     scal    delta;
  484.  
  485.     v = math_link(nucleus(q));
  486.     if (type(v) != VLIST_NODE) {
  487.         confusion("vcenter");
  488.     }
  489.     delta = box_height(v) + box_depth(v);
  490.     box_height(v) = axis_height(cur_size) + half(delta);
  491.     box_depth(v) = delta - box_height(v);
  492. }
  493.  
  494. void
  495. make_radical (q)
  496.     ptr    q;
  497. {
  498.     ptr    x;
  499.     ptr    y;
  500.     scal    clr;
  501.     scal    delta;
  502.  
  503.     x = clean_box(nucleus(q), cramped_style(cur_style));
  504.     clr = default_rule_thickness;
  505.     if (cur_style < TEXT_STYLE) {
  506.         clr += abs(math_x_height(cur_size)) / 4;
  507.     } else {
  508.         clr += (abs(clr) / 4);
  509.     }
  510.     y = var_delimiter(left_delimiter(q), cur_size,
  511.         box_height(x) + box_depth(x) + clr + default_rule_thickness);
  512.     delta = box_depth(y) - (box_height(x) + box_depth(x) + clr);
  513.     if (delta > 0) {
  514.         clr += half(delta);
  515.     }
  516.     shift_amount(y) = -(box_height(x) + clr);
  517.     link(y) = overbar(x, clr, box_height(y));
  518.     math_link(nucleus(q)) = hpack(y, NATURAL);
  519.     math_type(nucleus(q)) = SUB_BOX;
  520. }
  521.  
  522. void
  523. make_math_accent (q)
  524.     ptr    q;
  525. {
  526.     qcell    *a;
  527.     int    c;
  528.     fnt    f;
  529.     scal    h;
  530.     qcell    i;
  531.     ptr    p;
  532.     scal    s;
  533.     scal    w;
  534.     ptr    x;
  535.     ptr    y;
  536.     scal    delta;
  537.  
  538.     fetch(accent_chr(q)); 
  539.     if (!char_exists(cur_i))
  540.         return;
  541.     i = cur_i;
  542.     c = cur_c;
  543.     f = cur_f;
  544.     s = 0;
  545.     if (math_type(nucleus(q)) == MATH_CHAR) {
  546.         fetch(nucleus(q));
  547.         if (char_tag(cur_i) == LIG_TAG) {
  548.             a = lig_kern_start(cur_f, cur_i);
  549.             cur_i = *a;
  550.             if (skip_byte(cur_i) > STOP_FLAG) {
  551.                 a = lig_kern_restart(cur_f, cur_i);
  552.                 cur_i = *a;
  553.             }
  554.             loop {
  555.                 if (next_char(cur_i) == skew_char(cur_f)) {
  556.                     if (op_byte(cur_i) >= KERN_FLAG
  557.                     && skip_byte(cur_i) <= STOP_FLAG) {
  558.                         s = char_kern(cur_f, cur_i);
  559.                     }
  560.                     break;
  561.                 }
  562.                 if (skip_byte(cur_i) >= STOP_FLAG) {
  563.                     break;
  564.                 }
  565.                 a += skip_byte(cur_i) + 1;
  566.                 cur_i = *a;
  567.             }
  568.         }
  569.     }
  570.     x = clean_box(nucleus(q), cramped_style(cur_style));
  571.     w = box_width(x);
  572.     h = box_height(x);
  573.     loop {
  574.         if (char_tag(i) != LIST_TAG) {
  575.             break;
  576.         }
  577.         y = rem_byte(i);
  578.         i = char_info(f, y);
  579.         if (char_width(f, i) > w) {
  580.             break;
  581.         }
  582.         c = y;
  583.     }
  584.     delta = (h < x_height(f) ? h : x_height(f));
  585.     if ((math_type(supscr(q)) != EMPTY
  586.     || math_type(subscr(q)) != EMPTY)
  587.     && math_type(nucleus(q)) == MATH_CHAR) {
  588.             flush_node_list(x);
  589.             x = new_noad(); 
  590.             mcopy(nucleus(x), nucleus(q));
  591.             mcopy(supscr(x), supscr(q));
  592.             mcopy(subscr(x), subscr(q));
  593.             mzero(supscr(q));
  594.             mzero(subscr(q));
  595.             math_type(nucleus(q)) = SUB_MLIST;
  596.             math_link(nucleus(q)) = x;
  597.             x = clean_box(nucleus(q), cur_style);
  598.             delta += box_height(x) - h;
  599.             h = box_height(x);
  600.     }
  601.     y = char_box(f, c);
  602.     shift_amount(y) = s + half(w - box_width(y));
  603.     box_width(y) = 0;
  604.     link(y) = p = new_kern(-delta);
  605.     link(p) = x;
  606.     y = vpack(y, NATURAL);
  607.     box_width(y) = box_width(x);
  608.     if (box_height(y) < h) {
  609.         p = new_kern(h - box_height(y));
  610.         link(p) = list_ptr(y);
  611.         list_ptr(y) = p;
  612.         box_height(y) = h;
  613.     }
  614.     math_link(nucleus(q)) = y;
  615.     math_type(nucleus(q)) = SUB_BOX;
  616. }
  617.  
  618. void
  619. make_fraction (q)
  620.     ptr    q;
  621. {
  622.     ptr    p;
  623.     ptr    v;
  624.     ptr    x;
  625.     ptr    y;
  626.     ptr    z;
  627.     scal    clr;
  628.     scal    delta;
  629.     scal    delta1;
  630.     scal    delta2;
  631.     scal    shift_up;
  632.     scal    shift_down;
  633.  
  634.     if (thickness(q) == DEFAULT_CODE) {
  635.         thickness(q) = default_rule_thickness;
  636.     }
  637.     x = clean_box(numerator(q), num_style(cur_style));
  638.     z = clean_box(denominator(q), denom_style(cur_style));
  639.     if (box_width(x) < box_width(z)) {
  640.         x = rebox(x, box_width(z));
  641.     } else {
  642.         z = rebox(z, box_width(x));
  643.     }
  644.     if (cur_style < TEXT_STYLE) {
  645.         shift_up = num1(cur_size);
  646.         shift_down = denom1(cur_size);
  647.     } else {
  648.         shift_down = denom2(cur_size);
  649.         if (thickness(q) != 0) {
  650.             shift_up = num2(cur_size);
  651.         } else {
  652.             shift_up = num3(cur_size);
  653.         }
  654.     }
  655.     if (thickness(q) == 0) {
  656.         if (cur_style < TEXT_STYLE) {
  657.             clr = 7 * default_rule_thickness;
  658.         } else {
  659.             clr = 3 * default_rule_thickness;
  660.         }
  661.         delta = half(clr - 
  662.             ((shift_up - box_depth(x)) -
  663.             (box_height(z) - shift_down)));
  664.         if (delta > 0) {
  665.             shift_up += delta;
  666.             shift_down += delta;
  667.         }
  668.     } else {
  669.         if (cur_style < TEXT_STYLE) {
  670.             clr = 3 * thickness(q);
  671.         } else {
  672.             clr = thickness(q);
  673.         }
  674.         delta1 = delta2 = clr;
  675.         delta = half(thickness(q));
  676.         delta1 -= (shift_up - box_depth(x)) -
  677.             (axis_height(cur_size)+delta);
  678.         delta2 -= (axis_height(cur_size) - delta) -
  679.             (box_height(z) - shift_down);
  680.         if (delta1 > 0) {
  681.             shift_up += delta1;
  682.         }
  683.         if (delta2 > 0) {
  684.             shift_down += delta2;
  685.         }
  686.     }
  687.     v = new_null_box();
  688.     type(v) = VLIST_NODE;
  689.     box_height(v) = shift_up + box_height(x);
  690.     box_depth(v) = box_depth(z) + shift_down;
  691.     box_width(v) = box_width(x);
  692.     if (thickness(q) == 0) {
  693.         p = new_kern((shift_up - box_depth(x)) -
  694.             (box_height(z) - shift_down));
  695.         link(p) = z;
  696.     } else {
  697.         y = fraction_rule(thickness(q));
  698.         p = new_kern((axis_height(cur_size) - delta) -
  699.             (box_height(z) - shift_down));
  700.         link(y) = p;
  701.         link(p) = z;
  702.         p = new_kern((shift_up - box_depth(x)) -
  703.             (axis_height(cur_size)+delta));
  704.         link(p) = y;
  705.     }
  706.     link(x) = p;
  707.     list_ptr(v) = x;
  708.     if (cur_style < TEXT_STYLE) {
  709.         delta = delim1(cur_size);
  710.     } else {
  711.         delta = delim2(cur_size);
  712.     }
  713.     x = var_delimiter(left_delimiter(q), cur_size, delta);
  714.     link(x) = v;
  715.     z = var_delimiter(right_delimiter(q), cur_size, delta);
  716.     link(v) = z;
  717.     new_hlist(q) = hpack(x, NATURAL);
  718. }
  719.  
  720. scal
  721. make_op (q)
  722.     ptr    q;
  723. {
  724.     ptr    p;
  725.     ptr    v;
  726.     ptr    x;
  727.     ptr    y;
  728.     ptr    z;
  729.     scal    delta;
  730.     scal    shift_up;
  731.     scal    shift_down;
  732.  
  733.     if (subtype(q) == NORMAL && cur_style < TEXT_STYLE)
  734.         subtype(q) = LIMITS;
  735.     if (math_type(nucleus(q)) == MATH_CHAR) {
  736.         fetch(nucleus(q));
  737.         if (cur_style < TEXT_STYLE && char_tag(cur_i) == LIST_TAG) {
  738.             cur_c = rem_byte(cur_i);
  739.             character(nucleus(q)) = cur_c;
  740.             cur_i = char_info(cur_f, cur_c);
  741.         }
  742.         delta = char_italic(cur_f, cur_i);
  743.         x = clean_box(nucleus(q), cur_style);
  744.         if (math_type(subscr(q)) != EMPTY && subtype(q) != LIMITS) {
  745.             box_width(x) -= delta;
  746.         }
  747.         shift_amount(x) = half(box_height(x) - box_depth(x)) -
  748.             axis_height(cur_size);
  749.         math_type(nucleus(q)) = SUB_BOX;
  750.         math_link(nucleus(q)) = x;
  751.     } else {
  752.         delta = 0;
  753.     }
  754.     if (subtype(q) == LIMITS) {
  755.         x = clean_box(supscr(q), sup_style(cur_style));
  756.         y = clean_box(nucleus(q), cur_style);
  757.         z = clean_box(subscr(q), sub_style(cur_style));
  758.         v = new_null_box();
  759.         type(v) = VLIST_NODE;
  760.         box_width(v) = box_width(y);
  761.         if (box_width(x) > box_width(v)) {
  762.             box_width(v) = box_width(x);
  763.         }
  764.         if (box_width(z) > box_width(v)) {
  765.             box_width(v) = box_width(z);
  766.         }
  767.         x = rebox(x, box_width(v));
  768.         y = rebox(y, box_width(v));
  769.         z = rebox(z, box_width(v));
  770.         shift_amount(x) = half(delta);
  771.         shift_amount(z) = -shift_amount(x);
  772.         box_height(v) = box_height(y);
  773.         box_depth(v) = box_depth(y);
  774.         if (math_type(supscr(q)) == EMPTY) {
  775.             free_node(x, BOX_NODE_SIZE);
  776.             list_ptr(v) = y;
  777.         } else {
  778.             shift_up = big_op_spacing3 - box_depth(x);
  779.             if (shift_up < big_op_spacing1) {
  780.                 shift_up = big_op_spacing1;
  781.             }
  782.             p = new_kern(shift_up);
  783.             link(x) = p; link(p) = y; 
  784.             p = new_kern(big_op_spacing5);
  785.             list_ptr(v) = p;
  786.             link(p) = x;
  787.             box_height(v) += big_op_spacing5 +
  788.                 box_height(x) + box_depth(x) + shift_up;
  789.         }
  790.         if (math_type(subscr(q)) == EMPTY) {
  791.             free_node(z, BOX_NODE_SIZE);
  792.         } else {
  793.             shift_down = big_op_spacing4 - box_height(z);
  794.             if (shift_down < big_op_spacing2) {
  795.                 shift_down = big_op_spacing2;
  796.             }
  797.             p = new_kern(shift_down);
  798.             link(y) = p;
  799.             link(p) = z;
  800.             p = new_kern(big_op_spacing5);
  801.             link(z) = p;
  802.             box_depth(v) += big_op_spacing5 +
  803.                 box_height(z) + box_depth(z) + shift_down;
  804.         }
  805.         new_hlist(q) = v;
  806.     }
  807.     return delta;
  808. }
  809.  
  810. #define ord_lig()                            \
  811. {    switch (op_byte(cur_i))                        \
  812.     {                                \
  813.     case 1: case 5:                            \
  814.         character(nucleus(q)) = rem_byte(cur_i);        \
  815.         break;                            \
  816.     case 2: case 6:                            \
  817.         character(nucleus(p)) = rem_byte(cur_i);        \
  818.         break;                            \
  819.     case 3: case 7: case 11:                    \
  820.         r = new_noad();                        \
  821.         character(nucleus(r)) = rem_byte(cur_i);        \
  822.         fam(nucleus(r)) = fam(nucleus(q));            \
  823.         link(q) = r;                        \
  824.         link(r) = p;                        \
  825.         if (op_byte(cur_i) < 11) {                \
  826.             math_type(nucleus(r)) = MATH_CHAR;        \
  827.         } else {                        \
  828.             math_type(nucleus(r)) = MATH_TEXT_CHAR;        \
  829.         }                            \
  830.         break;                            \
  831.     default:                            \
  832.         link(q) = link(p);                    \
  833.         character(nucleus(q)) = rem_byte(cur_i);        \
  834.         mcopy(subscr(q), subscr(p));                \
  835.         mcopy(supscr(q), supscr(p));                \
  836.         free_node(p, NOAD_SIZE);                \
  837.         break;                            \
  838.     }                                \
  839.     if (op_byte(cur_i) > 3)                        \
  840.         return;                            \
  841.     math_type(nucleus(q)) = MATH_CHAR;                \
  842.     goto restart;                            \
  843. }
  844.  
  845. void
  846. make_ord (q)
  847.     ptr    q;
  848. {
  849.     ptr    p, r;
  850.     qcell    *a;
  851.  
  852. restart:
  853.     if (math_type(subscr(q)) != EMPTY
  854.     || math_type(supscr(q)) != EMPTY
  855.     || math_type(nucleus(q)) != MATH_CHAR) {
  856.         return;
  857.     }
  858.     p = link(q);
  859.     if (p == null
  860.     || type(p) < ORD_NOAD
  861.     || type(p) > PUNCT_NOAD
  862.     || math_type(nucleus(p)) != MATH_CHAR
  863.     || fam(nucleus(p)) != fam(nucleus(q))) {
  864.         return;
  865.     }
  866.     math_type(nucleus(q)) = MATH_TEXT_CHAR;
  867.     fetch(nucleus(q));
  868.     if (char_tag(cur_i) == LIG_TAG) {
  869.         a = lig_kern_start(cur_f, cur_i);
  870.         cur_c = character(nucleus(p));
  871.         cur_i = *a;
  872.         if (skip_byte(cur_i) > STOP_FLAG) {
  873.             a = lig_kern_restart(cur_f, cur_i);
  874.             cur_i = *a;
  875.         }
  876.         loop {
  877.             if (next_char(cur_i) == cur_c
  878.             && skip_byte(cur_i) <= STOP_FLAG) {
  879.                 if (op_byte(cur_i) >= KERN_FLAG) {
  880.                     p = new_kern(char_kern(cur_f, cur_i));
  881.                     link(p) = link(q);
  882.                     link(q) = p;
  883.                     return;
  884.                 } else {
  885.                     check_interrupt();
  886.                     ord_lig();
  887.                 }
  888.             }
  889.             if (skip_byte(cur_i) >= STOP_FLAG) {
  890.                 return;
  891.             }
  892.             a += skip_byte(cur_i) + 1;
  893.             cur_i = *a;
  894.         }
  895.     }
  896. }
  897.  
  898. void
  899. make_scripts (q, delta)
  900.     ptr    q;
  901.     scal    delta;
  902. {
  903.     ptr    p;
  904.     int    t;
  905.     ptr    x;
  906.     ptr    y;
  907.     ptr    z;
  908.     scal    clr;
  909.     scal    shift_up;
  910.     scal    shift_down;
  911.  
  912.     p = new_hlist(q);
  913.     if (is_char_node(p)) {
  914.         shift_up = 0;
  915.         shift_down = 0;
  916.     } else {
  917.         z = hpack(p, NATURAL);
  918.         if (cur_style < SCRIPT_STYLE) {
  919.             t = SCRIPT_SIZE;
  920.         } else {
  921.             t = SCRIPT_SCRIPT_SIZE;
  922.         }
  923.         shift_up = box_height(z) - sup_drop(t);
  924.         shift_down = box_depth(z) + sub_drop(t);
  925.         free_node(z, BOX_NODE_SIZE);
  926.     }
  927.     if (math_type(supscr(q)) == EMPTY) {
  928.         x = clean_box(subscr(q), sub_style(cur_style));
  929.         box_width(x) += script_space;
  930.         if (shift_down < sub1(cur_size)) {
  931.             shift_down = sub1(cur_size);
  932.         }
  933.         clr = box_height(x) - (abs(math_x_height(cur_size) * 4) / 5);
  934.         if (shift_down < clr) {
  935.             shift_down = clr;
  936.         }
  937.         shift_amount(x) = shift_down;
  938.     } else {
  939.         x = clean_box(supscr(q), sup_style(cur_style));
  940.         box_width(x) += script_space;
  941.         if (odd(cur_style)) {
  942.             clr = sup3(cur_size);
  943.         } else if (cur_style < TEXT_STYLE) {
  944.             clr = sup1(cur_size);
  945.         } else {
  946.             clr = sup2(cur_size);
  947.         }
  948.         if (shift_up < clr) {
  949.             shift_up = clr;
  950.         }
  951.         clr = box_depth(x) + (abs(math_x_height(cur_size)) / 4);
  952.         if (shift_up < clr) {
  953.             shift_up = clr;
  954.         }
  955.         if (math_type(subscr(q)) == EMPTY) {
  956.             shift_amount(x) = -shift_up;
  957.         } else {
  958.             y = clean_box(subscr(q), sub_style(cur_style));
  959.             box_width(y) += script_space;
  960.             if (shift_down < sub2(cur_size)) {
  961.                 shift_down = sub2(cur_size);
  962.             }
  963.             clr = 4 * default_rule_thickness -
  964.                 ((shift_up - box_depth(x)) - 
  965.                     (box_height(y) - shift_down));
  966.             if (clr > 0) {
  967.                 shift_down += clr;
  968.                 clr = (abs(math_x_height(cur_size) * 4) / 5) -
  969.                     (shift_up - box_depth(x));
  970.                 if (clr > 0) {
  971.                     shift_up += clr;
  972.                     shift_down -= clr;
  973.                 }
  974.             }
  975.             shift_amount(x) = delta;
  976.             p = new_kern((shift_up - box_depth(x)) -
  977.                 (box_height(y) - shift_down));
  978.             link(x) = p; link(p) = y;
  979.             x = vpack(x, NATURAL);
  980.             shift_amount(x) = shift_down;
  981.         }
  982.     }
  983.     if (new_hlist(q) == null) {
  984.         new_hlist(q) = x;
  985.     } else {
  986.         p = new_hlist(q);
  987.         while (link(p) != null) {
  988.             p = link(p);
  989.         }
  990.         link(p) = x;
  991.     }
  992. }
  993.  
  994. int
  995. make_left_right (q, style, max_d, max_h)
  996.     ptr    q;
  997.     int    style;
  998.     scal    max_d;
  999.     scal    max_h;
  1000. {
  1001.     scal    delta;
  1002.     scal    delta1;
  1003.     scal    delta2;
  1004.  
  1005.     if (style < SCRIPT_STYLE) {
  1006.         cur_size = TEXT_SIZE;
  1007.     } else {
  1008.         cur_size = 16 * ((style - TEXT_STYLE) / 2);
  1009.     }
  1010.     delta2 = max_d + axis_height(cur_size);
  1011.     delta1 = max_h + max_d - delta2;
  1012.     if (delta2 > delta1) {
  1013.         delta1 = delta2;
  1014.     }
  1015.     delta = (delta1 / 500) * delimiter_factor;
  1016.     delta2 = delta1 + delta1 - delimiter_shortfall;
  1017.     if (delta < delta2) {
  1018.         delta = delta2;
  1019.     }
  1020.     new_hlist(q) = var_delimiter(delimiter(q), cur_size, delta);
  1021.     return (type(q) - (LEFT_NOAD - OPEN_NOAD));
  1022. }
  1023.  
  1024. void
  1025. fetch (a)
  1026.     ptr    a;
  1027. {
  1028.     cur_c = character(a);
  1029.     cur_f = fam_fnt(fam(a) + cur_size);
  1030.     if (cur_f == null_font) {
  1031.         print_err(null_str);
  1032.         print_size(cur_size);
  1033.         print(" ");
  1034.         print_int(fam(a));
  1035.         print(" is undefined (character ");
  1036.         print_ASCII(cur_c);
  1037.         print(")");
  1038.         help_undefd_mathchar();
  1039.         error();
  1040.         cur_i = null_character;
  1041.         math_type(a) = EMPTY;
  1042.     } else {
  1043.         if (cur_c >= font_bc(cur_f)
  1044.         && cur_c <= font_ec(cur_f)) {
  1045.             cur_i = char_info(cur_f, cur_c);
  1046.         } else {
  1047.             cur_i = null_character;
  1048.         }
  1049.         if (!char_exists(cur_i)) {
  1050.             char_warning(cur_f, cur_c);
  1051.             math_type(a) = EMPTY;
  1052.         }
  1053.     }
  1054. }
  1055.  
  1056. ptr
  1057. clean_box (p, style)
  1058.     ptr    p;
  1059.     int    style;
  1060. {
  1061.     ptr    m;
  1062.     ptr    q;
  1063.     ptr    r;
  1064.     ptr    x;
  1065.     int    save_style;
  1066.  
  1067.     switch (math_type(p))
  1068.     {
  1069.     case MATH_CHAR:
  1070.         m = new_noad();
  1071.         mcopy(nucleus(m), p);
  1072.         break;
  1073.  
  1074.     case SUB_BOX:
  1075.         q = math_link(p);
  1076.         goto found; 
  1077.     
  1078.     case SUB_MLIST:
  1079.         m = math_link(p);
  1080.         break;
  1081.     
  1082.     default:
  1083.         q = new_null_box();
  1084.         goto found;
  1085.     }
  1086.  
  1087.     save_style = cur_style;
  1088.     q = mlist_to_hlist(m, style, FALSE);
  1089.     cur_style = save_style;
  1090.     change_size_and_mu();
  1091.  
  1092. found:
  1093.     if (is_char_node(q) || q == null) {
  1094.         x = hpack(q, NATURAL);    
  1095.     } else if (link(q) == null
  1096.         && type(q) <= VLIST_NODE
  1097.         && shift_amount(q) == 0) {
  1098.         x = q;
  1099.     } else {
  1100.         x = hpack(q, NATURAL);
  1101.     }
  1102.     q = list_ptr(x);
  1103.     if (is_char_node(q)) {
  1104.         r = link(q);
  1105.         if (r != null
  1106.         && link(r) == null
  1107.         && type(r) == KERN_NODE) {
  1108.             free_node(r, SMALL_NODE_SIZE);
  1109.             link(q) = null;
  1110.         }
  1111.     }
  1112.     return x;
  1113. }
  1114.  
  1115. void
  1116. _mlst_hlst_init ()
  1117. {
  1118. }
  1119.  
  1120. void
  1121. _mlst_hlst_init_once ()
  1122. {
  1123. }
  1124.  
  1125. /*
  1126. **    Help text
  1127. */
  1128.  
  1129. help_undefd_mathchar ()
  1130. {
  1131.     help4("Somewhere in the math formula just ended, you used the",
  1132.     "stated character from an undefined font family. For example,",
  1133.     "plain TeX doesn't allow \\it or \\sl in subscripts. Proceed,",
  1134.     "and I'll try to forget that I needed that character.");
  1135. }
  1136.