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

  1.  
  2. /*
  3.  * @(#)align.c 2.8 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 "eqstack.h"
  15. #include "token.h"
  16. #include "tokenstack.h"
  17. #include "scan.h"
  18. #include "evalstack.h"
  19. #include "box.h"
  20. #include "pack.h"
  21. #include "math.h"
  22. #include "mlst-hlst.h"
  23. #include "align.h"
  24.  
  25. ptr     align_ptr;
  26.  
  27. ptr     cur_align;
  28. ptr     cur_span;
  29. ptr     cur_loop;
  30. ptr     cur_head;
  31. ptr     cur_tail;
  32.  
  33. push_alignment ()
  34. {
  35.     ptr     p;
  36.  
  37.     p = get_node(ALIGN_STACK_NODE_SIZE);
  38.     link(p) = align_ptr;
  39.     info(p) = cur_align;
  40.     llink(p) = preamble;
  41.     rlink(p) = cur_span;
  42.     mem[p + 2].i = cur_loop;
  43.     mem[p + 3].i = align_state;
  44.     info(p + 4) = cur_head;
  45.     link(p + 4) = cur_tail;
  46.     align_ptr = p;
  47.     cur_head = get_avail();
  48. }
  49.  
  50. pop_alignment ()
  51. {
  52.     ptr     p;
  53.  
  54.     free_avail(cur_head);
  55.     p = align_ptr;
  56.     cur_tail = link(p + 4);
  57.     cur_head = info(p + 4);
  58.     align_state = mem[p + 3].i;
  59.     cur_loop = mem[p + 2].i;
  60.     cur_span = rlink(p);
  61.     preamble = llink(p);
  62.     cur_align = info(p);
  63.     align_ptr = link(p);
  64.     free_node(p, ALIGN_STACK_NODE_SIZE);
  65. }
  66.  
  67. init_align ()
  68. {
  69.     ptr     p;
  70.     ptr     save_cs_ptr;
  71.     
  72.     save_cs_ptr = cur_cs;
  73.     push_alignment();
  74.     align_state = -1000000;
  75.     if (mode == MMODE && (tail != head || incompleat_noad != NULL)) {
  76.         print_err("Improper ");
  77.         print_esc("halign");
  78.         print(" inside $$'s");
  79.         help_display_align();
  80.         error();
  81.         flush_math();
  82.     }
  83.     push_nest();
  84.     if (mode == MMODE) {
  85.         mode = -VMODE;
  86.         prev_depth = nest[nest_ptr - 2].aux_field;
  87.     } else if (mode > 0) {
  88.         negate(mode);
  89.     }
  90.     scan_spec();
  91.     new_save_level(ALIGN_GROUP);
  92.     preamble = NULL;
  93.     cur_align = align_head;
  94.     cur_loop = NULL;
  95.     scanner_status = ALIGNING;
  96.     warning_index = save_cs_ptr;
  97.     align_state = -1000000;
  98.     loop {
  99.         link(cur_align) = new_param_glue(TAB_SKIP_CODE);
  100.         cur_align = link(cur_align);
  101.         if (cur_cmd == CAR_RET)
  102.             break;
  103.         p = align_tokens;
  104.         token_link(p) = NULL;
  105.         loop {
  106.             get_preamble_token();
  107.             if (cur_cmd == MAC_PARAM)
  108.                 break;
  109.             if (cur_cmd <= CAR_RET &&
  110.                 cur_cmd >= TAB_MARK &&
  111.                 align_state == -1000000) {
  112.                 if (p == align_tokens &&
  113.                     cur_loop == NULL &&
  114.                     cur_cmd == TAB_MARK) {
  115.                     cur_loop = cur_align;
  116.                 } else {
  117.                     print_err("Missing # inserted in alignment preamble");
  118.                     help_preamble_missing();
  119.                     back_error();
  120.                     break;
  121.                 }
  122.             } else if (cur_cmd != SPACER || p != align_tokens) {
  123.                 token_link(p) = new_token();
  124.                 p = token_link(p);
  125.                 token(p) = cur_tok;
  126.             }
  127.         }
  128.         link(cur_align) = new_null_box();
  129.         cur_align = link(cur_align);
  130.         info(cur_align) = end_span;
  131.         width(cur_align) = NULL_FLAG;
  132.         u_part(cur_align) = token_link(align_tokens);
  133.         p = align_tokens;
  134.         token_link(p) = NULL;
  135.         loop {
  136.             get_preamble_token();
  137.             if (cur_cmd <= CAR_RET &&
  138.                 cur_cmd >= TAB_MARK &&
  139.                 align_state == -1000000)
  140.                 break;
  141.             if (cur_cmd == MAC_PARAM) {
  142.                 print_err("Only one # is allowed per tab");
  143.                 help_preamble_many();
  144.                 error();
  145.                 continue;
  146.             }
  147.             token_link(p) = new_token();
  148.             p = token_link(p);
  149.             token(p) = cur_tok;
  150.         }
  151.         token_link(p) = new_token();
  152.         p = token_link(p);
  153.         token(p) = END_TEMPLATE_TOKEN;
  154.         v_part(cur_align) = token_link(align_tokens);
  155.     }
  156.     scanner_status = NORMAL;
  157.     new_save_level(ALIGN_GROUP);
  158.     if (every_cr != NULL)
  159.         begin_token_list(every_cr, EVERY_CR_TEXT);
  160.     align_peek();
  161. }
  162.  
  163. get_preamble_token ()
  164. {
  165. restart:
  166.     get_token();
  167.     while (cur_chr == SPAN_CODE && cur_cmd == TAB_MARK) {
  168.         get_token();
  169.         if (cur_cmd > MAX_COMMAND) {
  170.             expand();
  171.             get_token();
  172.         }
  173.     }
  174.     if (cur_cmd == ASSIGN_GLUE && cur_chr == GLUE_BASE + TAB_SKIP_CODE) {
  175.         scan_optional_equals();
  176.         scan_glue(GLUE_VAL);
  177.         if (global_defs > 0)
  178.             geq_define(GLUE_BASE + TAB_SKIP_CODE, GLUE_REF, (ptr) cur_val);
  179.         else eq_define(GLUE_BASE + TAB_SKIP_CODE, GLUE_REF, (ptr) cur_val);
  180.         goto restart;
  181.     }
  182. }
  183.  
  184. align_peek ()
  185. {
  186. restart:
  187.     align_state = 1000000;
  188.     get_nbx_token();
  189.     if (cur_cmd == NO_ALIGN) {
  190.         scan_left_brace();
  191.         new_save_level(NO_ALIGN_GROUP);
  192.         if (mode == -VMODE)
  193.             normal_paragraph();
  194.     } else if (cur_cmd == RIGHT_BRACE) {
  195.         fin_align();
  196.     } else if (cur_cmd == CAR_RET && cur_chr == CR_CR_CODE) {
  197.         goto restart;
  198.     } else {
  199.         init_row();
  200.         init_col();
  201.     }
  202. }
  203.  
  204. init_row()
  205. {
  206.     push_nest();
  207.     mode = (-HMODE - VMODE) - mode;
  208.     aux = 0;
  209.     tail_append(new_glue(glue_ptr(preamble)));
  210.     subtype(tail) = TAB_SKIP_CODE + 1;
  211.     cur_align = link(preamble);
  212.     cur_tail = cur_head;
  213.     init_span(cur_align);
  214. }
  215.  
  216. init_span (p)
  217.     ptr     p;
  218. {
  219.     push_nest();
  220.     if (mode == -HMODE) {
  221.         space_factor = 1000;
  222.     } else {
  223.         prev_depth = IGNORE_DEPTH;
  224.         normal_paragraph();
  225.     }
  226.     cur_span = p;
  227. }
  228.  
  229. init_col ()
  230. {
  231.     extra_info(cur_align) = cur_cmd;
  232.     if (cur_cmd == OMIT) {
  233.         align_state = 0;
  234.     } else {
  235.         back_input();
  236.         begin_token_list((ptr) u_part(cur_align), (qword) U_TEMPLATE);
  237.     }
  238. }
  239.  
  240. bool
  241. fin_col ()
  242. {
  243.     hword   n;
  244.     gord    o;
  245.     ptr     p;
  246.     ptr     q;
  247.     ptr     r;
  248.     ptr     s;
  249.     ptr     u;
  250.     scal    w;
  251.  
  252.     q = link(cur_align);
  253.     if (cur_align == NULL || q == NULL)
  254.         confusion("endv");
  255.     p = link(q);
  256.     if (p == NULL && extra_info(cur_align) < CR_CODE) {
  257.         if (cur_loop != NULL) {
  258.             link(q) = new_null_box();
  259.             p = link(q);
  260.             info(p) = end_span;
  261.             width(p) = NULL_FLAG;
  262.             cur_loop = link(cur_loop);
  263.             q = align_tokens;
  264.             r = u_part(cur_loop);
  265.             while (r != NULL) {
  266.                 token_link(q) = new_token();
  267.                 q = token_link(q);
  268.                 token(q) = token(r);
  269.                 r = token_link(r);
  270.             }
  271.             token_link(q) = NULL;
  272.             u_part(p) = token_link(align_tokens);
  273.             q = align_tokens;
  274.             r = v_part(cur_loop);
  275.             while (r != NULL) {
  276.                 token_link(q) = new_token();
  277.                 q = token_link(q);
  278.                 token(q) = token(r);
  279.                 r = token_link(r);
  280.             }
  281.             token_link(q) = NULL;
  282.             v_part(p) = token_link(align_tokens);
  283.             cur_loop = link(cur_loop);
  284.             link(p) = new_glue(glue_ptr(cur_loop));
  285.         } else {
  286.             print_err("Extra alignment tab has been changed to ");
  287.             print_esc("cr");
  288.             help_align_apply();
  289.             extra_info(cur_align) = CR_CODE;
  290.             error();
  291.         }
  292.     }
  293.     if (extra_info(cur_align) != SPAN_CODE) {
  294.         unsave();
  295.         new_save_level(ALIGN_GROUP);
  296.         if (mode == -HMODE) {
  297.             adjust_tail = cur_tail;
  298.             u = hpack(link(head), NATURAL);
  299.             w = width(u);
  300.             cur_tail = adjust_tail;
  301.             adjust_tail = NULL;
  302.         } else {
  303.             u = vpackage(link(head), NATURAL, 0L);
  304.             w = height(u);
  305.         }
  306.         n = MIN_QUARTERWORD;
  307.         if (cur_span != cur_align) {
  308.             q = cur_span;
  309.             do  {
  310.                 incr(n);
  311.                 q = link(link(q));
  312.             } while (q != cur_align);
  313.             if (n > MAX_QUARTERWORD)
  314.                 confusion("256 spans");
  315.             q = cur_span;
  316.             while (link(info(q)) < n)
  317.                 q = info(q);
  318.             if (link(info(q)) > n) {
  319.                 s = get_node(SPAN_NODE_SIZE);
  320.                 info(s) = info(q);
  321.                 link(s) = n;
  322.                 info(q) = s;
  323.                 width(s) = w;
  324.             } else if (width(info(q)) < w) {
  325.                 width(info(q)) = w;
  326.             }
  327.         } else if (w > width(cur_align)) {
  328.             width(cur_align) = w;
  329.         }
  330.         type(u) = UNSET_NODE;
  331.         span_count(u) = n;
  332.         get_stretch_order();
  333.         glue_order(u) = o;
  334.         glue_stretch(u) = total_stretch[o];
  335.         get_shrink_order();
  336.         glue_sign(u) = o;
  337.         glue_shrink(u) = total_shrink[o];
  338.         pop_nest();
  339.         link(tail) = u;
  340.         tail = u;
  341.         tail_append(new_glue(glue_ptr(link(cur_align))));
  342.         subtype(tail) = TAB_SKIP_CODE + 1;
  343.         if (extra_info(cur_align) >= CR_CODE)
  344.             return TRUE;
  345.         init_span(p);
  346.     }
  347.     align_state = 1000000;
  348.     get_nbx_token();
  349.     cur_align = p;
  350.     init_col();
  351.     return FALSE;
  352. }
  353.  
  354. fin_row ()
  355. {
  356.     ptr     p;
  357.  
  358.     if (mode == -HMODE) {
  359.         p = hpack(link(head), NATURAL);
  360.         pop_nest();
  361.         append_to_vlist(p);
  362.         if(cur_head != cur_tail) {
  363.             link(tail) = link(cur_head);
  364.             tail = cur_tail;
  365.         }
  366.     } else {
  367.         p = vpack(link(head), NATURAL);
  368.         pop_nest();
  369.         link(tail) = p;
  370.         tail = p;
  371.         space_factor = 1000;
  372.     }
  373.     type(p) = UNSET_NODE;
  374.     glue_stretch(p) = 0;
  375.     if (every_cr != NULL)
  376.         begin_token_list(every_cr, EVERY_CR_TEXT);
  377.     align_peek();
  378. }
  379.  
  380. fin_align ()
  381. {
  382.     int     n;
  383.     scal    o;
  384.     ptr     p;
  385.     ptr     q;
  386.     ptr     r;
  387.     ptr     s;
  388.     scal    t;
  389.     ptr     u;
  390.     ptr     v;
  391.     scal    w;
  392.     scal    rule_save;
  393.  
  394.     if (cur_group != ALIGN_GROUP)
  395.         confusion("align1");
  396.     unsave();
  397.     if (cur_group != ALIGN_GROUP)
  398.         confusion("align0");
  399.     unsave();
  400.     if (nest[nest_ptr - 1].mode_field == MMODE)
  401.         o = display_indent;
  402.     else o = 0;
  403.     q = link(preamble);
  404.     do {
  405.         flush_list((ptr) u_part(q));
  406.         flush_list((ptr) v_part(q));
  407.         p = link(link(q));
  408.         if (width(q) == NULL_FLAG) {
  409.             width(q) = 0;
  410.             r = link(q);
  411.             s = glue_ptr(r);
  412.             if (s != zero_glue) {
  413.                 add_glue_ref(zero_glue);
  414.                 delete_glue_ref(s);
  415.                 glue_ptr(r) = zero_glue;
  416.             }
  417.         }
  418.         if (info(q) != end_span) {
  419.             t = width(q) + width(glue_ptr(link(q)));
  420.             r = info(q);
  421.             s = end_span;
  422.             info(s) = p;
  423.             n = MIN_QUARTERWORD + 1;
  424.             do {    
  425.                 width(r) -= t;
  426.                 u = info(r);
  427.                 while (link(r) > n) {
  428.                     s = info(s);
  429.                     n = link(info(s)) + 1;
  430.                 }
  431.                 if (link(r) < n) {
  432.                     info(r) = info(s);
  433.                     info(s) = r;
  434.                     decr(link(r));
  435.                     s = r;
  436.                 } else {
  437.                     if (width(r) > width(info(s)))
  438.                         width(info(s)) = width(r);
  439.                     free_node(r, SPAN_NODE_SIZE);
  440.                 }
  441.                 r = u;
  442.             } while (r != end_span);
  443.         }
  444.         type(q) = UNSET_NODE;
  445.         span_count(q) = MIN_QUARTERWORD;
  446.         height(q) = 0;
  447.         depth(q) = 0;
  448.         glue_order(q) = NORMAL;
  449.         glue_sign(q) = NORMAL;
  450.         glue_stretch(q) = 0;
  451.         glue_shrink(q) = 0;
  452.         q = p;
  453.     } while (q != NULL);
  454.     save_ptr -= 2;
  455.     pack_begin_line = -mode_line;
  456.     if (mode == -VMODE) {
  457.         rule_save = overfull_rule;
  458.         overfull_rule = 0;
  459.         p = hpack(preamble, saved(1), (int) saved(0));
  460.         overfull_rule = rule_save;
  461.     } else {
  462.         q = link(preamble);
  463.         do  {
  464.             height(q) = width(q);
  465.             width(q) = 0;
  466.             q = link(link(q));
  467.         } while (q != NULL);
  468.         p = vpackage(preamble, saved(1), (int) saved(0), MAX_DIMEN);
  469.         q = link(preamble);
  470.         do  {
  471.             width(q) = height(q);
  472.             height(q) = 0;
  473.             q = link(link(q));
  474.         } while (q != NULL);
  475.     }
  476.     pack_begin_line = 0;
  477.     for (s = head, q = link(s); q != NULL; s = q, q = link(s)) {
  478.         if (type(q) == UNSET_NODE) {
  479.             if (mode == -VMODE) {
  480.                 type(q) = HLIST_NODE;
  481.                 width(q) = width(p);
  482.             } else {
  483.                 type(q) = VLIST_NODE;
  484.                 height(q) = height(p);
  485.             }
  486.             glue_order(q) = glue_order(p);
  487.             glue_sign(q) = glue_sign(p);
  488.             glue_set(q) = glue_set(p);
  489.             shift_amount(q) = o;
  490.             r = link(list_ptr(q));
  491.             s = link(list_ptr(p)); 
  492.             do  {
  493.                 n = span_count(r); 
  494.                 t = width(s);
  495.                 w = t;
  496.                 u = hold_head;
  497.                 while (n > MIN_QUARTERWORD) {
  498.                     decr(n);
  499.                     s = link(s);
  500.                     v = glue_ptr(s);
  501.                     link(u) = new_glue(v);
  502.                     u = link(u);
  503.                     subtype(u) = TAB_SKIP_CODE + 1;
  504.                     t += width(v);
  505.                     if (glue_sign(p) == STRETCHING) {
  506.                         if (stretch_order(v) == glue_order(p))
  507.                             t += round(glue_set(p) * stretch(v));
  508.                     } else if (glue_sign(p) == SHRINKING) {
  509.                         if (shrink_order(v) == glue_order(p))
  510.                             t -= round(glue_set(p) * shrink(v));
  511.                     }
  512.                     s = link(s);
  513.                     link(u) = new_null_box();
  514.                     u = link(u);
  515.                     t += width(s);
  516.                     if (mode == -VMODE) {
  517.                         width(u) = width(s);
  518.                     } else {
  519.                         type(u) = VLIST_NODE;
  520.                         height(u) = width(s);
  521.                     }
  522.                 }
  523.                 if (mode == -VMODE) {
  524.                     height(r) = height(q);
  525.                     depth(r) = depth(q);
  526.                     if (t == width(r)) {
  527.                         glue_sign(r) = NORMAL;
  528.                         glue_order(r) = NORMAL;
  529.                         glue_set(r) = 0.0;
  530.                     } else if (t > width(r)) {
  531.                         glue_sign(r) = STRETCHING;
  532.                         if (glue_stretch(r) == 0)
  533.                             glue_set(r) = 0.0;
  534.                         else glue_set(r) =
  535.                                 (float) (t - width(r)) / glue_stretch(r);
  536.                     } else {
  537.                         glue_order(r) = glue_sign(r);
  538.                         glue_sign(r) = SHRINKING;
  539.                         if (glue_shrink(r) == 0)
  540.                             glue_set(r) = 0.0;
  541.                         else if (glue_order(r) == NORMAL &&
  542.                                 width(r) - t > glue_shrink(r))
  543.                             glue_set(r) = 1.0;
  544.                         else glue_set(r) =
  545.                             (float)(width(r) - t) / glue_shrink(r);
  546.                     }
  547.                     width(r) = w;
  548.                     type(r) = HLIST_NODE;
  549.                 } else {
  550.                     width(r) = width(q);
  551.                     if (t == height(r)) {
  552.                         glue_sign(r) = NORMAL;
  553.                         glue_order(r) = NORMAL;
  554.                         glue_set(r) = 0.0;
  555.                     } else if (t > height(r)) {
  556.                         glue_sign(r) = STRETCHING;
  557.                         if (glue_stretch(r) == 0)
  558.                             glue_set(r) = 0.0;
  559.                         else glue_set(r) =  
  560.                                 (float) (t - height(r)) / glue_stretch(r);
  561.                     } else {
  562.                         glue_order(r) = glue_sign(r);
  563.                         glue_sign(r) = SHRINKING;
  564.                         if (glue_shrink(r) == 0)
  565.                             glue_set(r) = 0.0;
  566.                         else if (glue_order(r) == NORMAL &&
  567.                                 height(r) - t > glue_shrink(r))
  568.                             glue_set(r) = 1.0;
  569.                         else glue_set(r) = 
  570.                                 (float) (height(r) - t) / glue_shrink(r);
  571.                     }
  572.                     height(r) = w;
  573.                     type(r) = VLIST_NODE;
  574.                 } 
  575.                 shift_amount(r) = 0; 
  576.                 if (u != hold_head) {
  577.                     link(u) = link(r);
  578.                     link(r) = link(hold_head);
  579.                     r = u;
  580.                 }
  581.                 r = link(link(r));
  582.                 s = link(link(s));
  583.             } while (r != NULL);
  584.         } else if (type(q) == RULE_NODE) {
  585.             if (is_running(width(q)))
  586.                 width(q) = width(p);
  587.             if (is_running(height(q)))
  588.                 height(q) = height(p);
  589.             if (is_running(depth(q)))
  590.                 depth(q) = depth(p);
  591.             if (o != 0) {
  592.                 r = link(q);
  593.                 link(q) = NULL;
  594.                 q = hpack(q, NATURAL);
  595.                 shift_amount(q) = o;
  596.                 link(q) = r;
  597.                 link(s) = q;
  598.             }
  599.         }
  600.     }
  601.     flush_node_list(p);
  602.     pop_alignment();
  603.     t = aux;
  604.     p = link(head);
  605.     q = tail;
  606.     pop_nest();
  607.     if (mode == MMODE) {
  608.         do_assignments();
  609.         if (cur_cmd != MATH_SHIFT) {
  610.             print_err("Missing $$ inserted");
  611.             help_fin_display_align();
  612.             back_error();
  613.         } else {    
  614.             get_x_token();
  615.             if (cur_cmd != MATH_SHIFT) {
  616.                 print_err("Display math should end with $$");
  617.                 help_fin_display();
  618.                 back_error();
  619.             }
  620.         }
  621.         pop_nest();
  622.         tail_append(new_penalty(pre_display_penalty));
  623.         tail_append(new_param_glue(ABOVE_DISPLAY_SKIP_CODE));
  624.         link(tail) = p;
  625.         if (p != NULL)
  626.             tail = q;
  627.         tail_append(new_penalty(post_display_penalty));
  628.         tail_append(new_param_glue(BELOW_DISPLAY_SKIP_CODE));
  629.         prev_depth = t;
  630.         resume_after_display();
  631.     } else {    
  632.         aux = t;
  633.         link(tail) = p;
  634.         if (p != NULL)
  635.             tail = q;
  636.         if (mode == VMODE)
  637.             build_page();
  638.     }
  639. }
  640.  
  641. /*
  642.  *  Help text
  643.  */
  644.  
  645. help_display_align ()
  646. {
  647.     help3("Displays can use special alignments (like \\eqalignno)",
  648.     "only if nothing but the alignment itself is between $$'s.",
  649.     "So I've deleted the formulas that preceded this alignment.");
  650. }
  651.  
  652. help_fin_display_align ()
  653. {
  654.     help2("Displays can use special alignments (like \\eqalignno)",
  655.     "only if nothing but the alignment itself is between $$'s.");
  656. }
  657.  
  658. help_preamble_missing ()
  659. {
  660.     help3("There should be exactly one # between &'s, when an",
  661.     "\\halign or \\valign is being set up. In this case you had",
  662.     "none, so I've put one in; maybe that will work.");
  663. }
  664.  
  665. help_preamble_many ()
  666. {
  667.     help3("There should be exactly one # between &'s, when an",
  668.     "\\halign or \\valign is being set up. In this case you had",
  669.     "more than one, so I'm ignoring all but the first.");
  670. }
  671.  
  672. help_align_apply ()
  673. {
  674.     help3("You have given more \\span or & marks than there were",
  675.     "in the preamble to the \\halign or \\valign now in progress.",
  676.     "So I'll assume that you meant to type \\cr instead.");
  677. }
  678.  
  679. help_fin_display ()
  680. {
  681.     help2("The `$' that I just saw supposedly matches a previous `$$'.",
  682.     "So I shall assume that you typed `$$' both times.");
  683. }
  684.