home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari FTP
/
ATARI_FTP_0693.zip
/
ATARI_FTP_0693
/
Tex
/
Tex29
/
StTeXsrc.zoo
/
src
/
align.c
next >
Wrap
C/C++ Source or Header
|
1988-03-13
|
20KB
|
684 lines
/*
* @(#)align.c 2.8 EPA
*
* Copyright 1987,1988 Pat J Monardo
*
* Redistribution of this file is permitted through
* the specifications in the file COPYING.
*
*
*/
#include "tex.h"
#include "eqstack.h"
#include "token.h"
#include "tokenstack.h"
#include "scan.h"
#include "evalstack.h"
#include "box.h"
#include "pack.h"
#include "math.h"
#include "mlst-hlst.h"
#include "align.h"
ptr align_ptr;
ptr cur_align;
ptr cur_span;
ptr cur_loop;
ptr cur_head;
ptr cur_tail;
push_alignment ()
{
ptr p;
p = get_node(ALIGN_STACK_NODE_SIZE);
link(p) = align_ptr;
info(p) = cur_align;
llink(p) = preamble;
rlink(p) = cur_span;
mem[p + 2].i = cur_loop;
mem[p + 3].i = align_state;
info(p + 4) = cur_head;
link(p + 4) = cur_tail;
align_ptr = p;
cur_head = get_avail();
}
pop_alignment ()
{
ptr p;
free_avail(cur_head);
p = align_ptr;
cur_tail = link(p + 4);
cur_head = info(p + 4);
align_state = mem[p + 3].i;
cur_loop = mem[p + 2].i;
cur_span = rlink(p);
preamble = llink(p);
cur_align = info(p);
align_ptr = link(p);
free_node(p, ALIGN_STACK_NODE_SIZE);
}
init_align ()
{
ptr p;
ptr save_cs_ptr;
save_cs_ptr = cur_cs;
push_alignment();
align_state = -1000000;
if (mode == MMODE && (tail != head || incompleat_noad != NULL)) {
print_err("Improper ");
print_esc("halign");
print(" inside $$'s");
help_display_align();
error();
flush_math();
}
push_nest();
if (mode == MMODE) {
mode = -VMODE;
prev_depth = nest[nest_ptr - 2].aux_field;
} else if (mode > 0) {
negate(mode);
}
scan_spec();
new_save_level(ALIGN_GROUP);
preamble = NULL;
cur_align = align_head;
cur_loop = NULL;
scanner_status = ALIGNING;
warning_index = save_cs_ptr;
align_state = -1000000;
loop {
link(cur_align) = new_param_glue(TAB_SKIP_CODE);
cur_align = link(cur_align);
if (cur_cmd == CAR_RET)
break;
p = align_tokens;
token_link(p) = NULL;
loop {
get_preamble_token();
if (cur_cmd == MAC_PARAM)
break;
if (cur_cmd <= CAR_RET &&
cur_cmd >= TAB_MARK &&
align_state == -1000000) {
if (p == align_tokens &&
cur_loop == NULL &&
cur_cmd == TAB_MARK) {
cur_loop = cur_align;
} else {
print_err("Missing # inserted in alignment preamble");
help_preamble_missing();
back_error();
break;
}
} else if (cur_cmd != SPACER || p != align_tokens) {
token_link(p) = new_token();
p = token_link(p);
token(p) = cur_tok;
}
}
link(cur_align) = new_null_box();
cur_align = link(cur_align);
info(cur_align) = end_span;
width(cur_align) = NULL_FLAG;
u_part(cur_align) = token_link(align_tokens);
p = align_tokens;
token_link(p) = NULL;
loop {
get_preamble_token();
if (cur_cmd <= CAR_RET &&
cur_cmd >= TAB_MARK &&
align_state == -1000000)
break;
if (cur_cmd == MAC_PARAM) {
print_err("Only one # is allowed per tab");
help_preamble_many();
error();
continue;
}
token_link(p) = new_token();
p = token_link(p);
token(p) = cur_tok;
}
token_link(p) = new_token();
p = token_link(p);
token(p) = END_TEMPLATE_TOKEN;
v_part(cur_align) = token_link(align_tokens);
}
scanner_status = NORMAL;
new_save_level(ALIGN_GROUP);
if (every_cr != NULL)
begin_token_list(every_cr, EVERY_CR_TEXT);
align_peek();
}
get_preamble_token ()
{
restart:
get_token();
while (cur_chr == SPAN_CODE && cur_cmd == TAB_MARK) {
get_token();
if (cur_cmd > MAX_COMMAND) {
expand();
get_token();
}
}
if (cur_cmd == ASSIGN_GLUE && cur_chr == GLUE_BASE + TAB_SKIP_CODE) {
scan_optional_equals();
scan_glue(GLUE_VAL);
if (global_defs > 0)
geq_define(GLUE_BASE + TAB_SKIP_CODE, GLUE_REF, (ptr) cur_val);
else eq_define(GLUE_BASE + TAB_SKIP_CODE, GLUE_REF, (ptr) cur_val);
goto restart;
}
}
align_peek ()
{
restart:
align_state = 1000000;
get_nbx_token();
if (cur_cmd == NO_ALIGN) {
scan_left_brace();
new_save_level(NO_ALIGN_GROUP);
if (mode == -VMODE)
normal_paragraph();
} else if (cur_cmd == RIGHT_BRACE) {
fin_align();
} else if (cur_cmd == CAR_RET && cur_chr == CR_CR_CODE) {
goto restart;
} else {
init_row();
init_col();
}
}
init_row()
{
push_nest();
mode = (-HMODE - VMODE) - mode;
aux = 0;
tail_append(new_glue(glue_ptr(preamble)));
subtype(tail) = TAB_SKIP_CODE + 1;
cur_align = link(preamble);
cur_tail = cur_head;
init_span(cur_align);
}
init_span (p)
ptr p;
{
push_nest();
if (mode == -HMODE) {
space_factor = 1000;
} else {
prev_depth = IGNORE_DEPTH;
normal_paragraph();
}
cur_span = p;
}
init_col ()
{
extra_info(cur_align) = cur_cmd;
if (cur_cmd == OMIT) {
align_state = 0;
} else {
back_input();
begin_token_list((ptr) u_part(cur_align), (qword) U_TEMPLATE);
}
}
bool
fin_col ()
{
hword n;
gord o;
ptr p;
ptr q;
ptr r;
ptr s;
ptr u;
scal w;
q = link(cur_align);
if (cur_align == NULL || q == NULL)
confusion("endv");
p = link(q);
if (p == NULL && extra_info(cur_align) < CR_CODE) {
if (cur_loop != NULL) {
link(q) = new_null_box();
p = link(q);
info(p) = end_span;
width(p) = NULL_FLAG;
cur_loop = link(cur_loop);
q = align_tokens;
r = u_part(cur_loop);
while (r != NULL) {
token_link(q) = new_token();
q = token_link(q);
token(q) = token(r);
r = token_link(r);
}
token_link(q) = NULL;
u_part(p) = token_link(align_tokens);
q = align_tokens;
r = v_part(cur_loop);
while (r != NULL) {
token_link(q) = new_token();
q = token_link(q);
token(q) = token(r);
r = token_link(r);
}
token_link(q) = NULL;
v_part(p) = token_link(align_tokens);
cur_loop = link(cur_loop);
link(p) = new_glue(glue_ptr(cur_loop));
} else {
print_err("Extra alignment tab has been changed to ");
print_esc("cr");
help_align_apply();
extra_info(cur_align) = CR_CODE;
error();
}
}
if (extra_info(cur_align) != SPAN_CODE) {
unsave();
new_save_level(ALIGN_GROUP);
if (mode == -HMODE) {
adjust_tail = cur_tail;
u = hpack(link(head), NATURAL);
w = width(u);
cur_tail = adjust_tail;
adjust_tail = NULL;
} else {
u = vpackage(link(head), NATURAL, 0L);
w = height(u);
}
n = MIN_QUARTERWORD;
if (cur_span != cur_align) {
q = cur_span;
do {
incr(n);
q = link(link(q));
} while (q != cur_align);
if (n > MAX_QUARTERWORD)
confusion("256 spans");
q = cur_span;
while (link(info(q)) < n)
q = info(q);
if (link(info(q)) > n) {
s = get_node(SPAN_NODE_SIZE);
info(s) = info(q);
link(s) = n;
info(q) = s;
width(s) = w;
} else if (width(info(q)) < w) {
width(info(q)) = w;
}
} else if (w > width(cur_align)) {
width(cur_align) = w;
}
type(u) = UNSET_NODE;
span_count(u) = n;
get_stretch_order();
glue_order(u) = o;
glue_stretch(u) = total_stretch[o];
get_shrink_order();
glue_sign(u) = o;
glue_shrink(u) = total_shrink[o];
pop_nest();
link(tail) = u;
tail = u;
tail_append(new_glue(glue_ptr(link(cur_align))));
subtype(tail) = TAB_SKIP_CODE + 1;
if (extra_info(cur_align) >= CR_CODE)
return TRUE;
init_span(p);
}
align_state = 1000000;
get_nbx_token();
cur_align = p;
init_col();
return FALSE;
}
fin_row ()
{
ptr p;
if (mode == -HMODE) {
p = hpack(link(head), NATURAL);
pop_nest();
append_to_vlist(p);
if(cur_head != cur_tail) {
link(tail) = link(cur_head);
tail = cur_tail;
}
} else {
p = vpack(link(head), NATURAL);
pop_nest();
link(tail) = p;
tail = p;
space_factor = 1000;
}
type(p) = UNSET_NODE;
glue_stretch(p) = 0;
if (every_cr != NULL)
begin_token_list(every_cr, EVERY_CR_TEXT);
align_peek();
}
fin_align ()
{
int n;
scal o;
ptr p;
ptr q;
ptr r;
ptr s;
scal t;
ptr u;
ptr v;
scal w;
scal rule_save;
if (cur_group != ALIGN_GROUP)
confusion("align1");
unsave();
if (cur_group != ALIGN_GROUP)
confusion("align0");
unsave();
if (nest[nest_ptr - 1].mode_field == MMODE)
o = display_indent;
else o = 0;
q = link(preamble);
do {
flush_list((ptr) u_part(q));
flush_list((ptr) v_part(q));
p = link(link(q));
if (width(q) == NULL_FLAG) {
width(q) = 0;
r = link(q);
s = glue_ptr(r);
if (s != zero_glue) {
add_glue_ref(zero_glue);
delete_glue_ref(s);
glue_ptr(r) = zero_glue;
}
}
if (info(q) != end_span) {
t = width(q) + width(glue_ptr(link(q)));
r = info(q);
s = end_span;
info(s) = p;
n = MIN_QUARTERWORD + 1;
do {
width(r) -= t;
u = info(r);
while (link(r) > n) {
s = info(s);
n = link(info(s)) + 1;
}
if (link(r) < n) {
info(r) = info(s);
info(s) = r;
decr(link(r));
s = r;
} else {
if (width(r) > width(info(s)))
width(info(s)) = width(r);
free_node(r, SPAN_NODE_SIZE);
}
r = u;
} while (r != end_span);
}
type(q) = UNSET_NODE;
span_count(q) = MIN_QUARTERWORD;
height(q) = 0;
depth(q) = 0;
glue_order(q) = NORMAL;
glue_sign(q) = NORMAL;
glue_stretch(q) = 0;
glue_shrink(q) = 0;
q = p;
} while (q != NULL);
save_ptr -= 2;
pack_begin_line = -mode_line;
if (mode == -VMODE) {
rule_save = overfull_rule;
overfull_rule = 0;
p = hpack(preamble, saved(1), (int) saved(0));
overfull_rule = rule_save;
} else {
q = link(preamble);
do {
height(q) = width(q);
width(q) = 0;
q = link(link(q));
} while (q != NULL);
p = vpackage(preamble, saved(1), (int) saved(0), MAX_DIMEN);
q = link(preamble);
do {
width(q) = height(q);
height(q) = 0;
q = link(link(q));
} while (q != NULL);
}
pack_begin_line = 0;
for (s = head, q = link(s); q != NULL; s = q, q = link(s)) {
if (type(q) == UNSET_NODE) {
if (mode == -VMODE) {
type(q) = HLIST_NODE;
width(q) = width(p);
} else {
type(q) = VLIST_NODE;
height(q) = height(p);
}
glue_order(q) = glue_order(p);
glue_sign(q) = glue_sign(p);
glue_set(q) = glue_set(p);
shift_amount(q) = o;
r = link(list_ptr(q));
s = link(list_ptr(p));
do {
n = span_count(r);
t = width(s);
w = t;
u = hold_head;
while (n > MIN_QUARTERWORD) {
decr(n);
s = link(s);
v = glue_ptr(s);
link(u) = new_glue(v);
u = link(u);
subtype(u) = TAB_SKIP_CODE + 1;
t += width(v);
if (glue_sign(p) == STRETCHING) {
if (stretch_order(v) == glue_order(p))
t += round(glue_set(p) * stretch(v));
} else if (glue_sign(p) == SHRINKING) {
if (shrink_order(v) == glue_order(p))
t -= round(glue_set(p) * shrink(v));
}
s = link(s);
link(u) = new_null_box();
u = link(u);
t += width(s);
if (mode == -VMODE) {
width(u) = width(s);
} else {
type(u) = VLIST_NODE;
height(u) = width(s);
}
}
if (mode == -VMODE) {
height(r) = height(q);
depth(r) = depth(q);
if (t == width(r)) {
glue_sign(r) = NORMAL;
glue_order(r) = NORMAL;
glue_set(r) = 0.0;
} else if (t > width(r)) {
glue_sign(r) = STRETCHING;
if (glue_stretch(r) == 0)
glue_set(r) = 0.0;
else glue_set(r) =
(float) (t - width(r)) / glue_stretch(r);
} else {
glue_order(r) = glue_sign(r);
glue_sign(r) = SHRINKING;
if (glue_shrink(r) == 0)
glue_set(r) = 0.0;
else if (glue_order(r) == NORMAL &&
width(r) - t > glue_shrink(r))
glue_set(r) = 1.0;
else glue_set(r) =
(float)(width(r) - t) / glue_shrink(r);
}
width(r) = w;
type(r) = HLIST_NODE;
} else {
width(r) = width(q);
if (t == height(r)) {
glue_sign(r) = NORMAL;
glue_order(r) = NORMAL;
glue_set(r) = 0.0;
} else if (t > height(r)) {
glue_sign(r) = STRETCHING;
if (glue_stretch(r) == 0)
glue_set(r) = 0.0;
else glue_set(r) =
(float) (t - height(r)) / glue_stretch(r);
} else {
glue_order(r) = glue_sign(r);
glue_sign(r) = SHRINKING;
if (glue_shrink(r) == 0)
glue_set(r) = 0.0;
else if (glue_order(r) == NORMAL &&
height(r) - t > glue_shrink(r))
glue_set(r) = 1.0;
else glue_set(r) =
(float) (height(r) - t) / glue_shrink(r);
}
height(r) = w;
type(r) = VLIST_NODE;
}
shift_amount(r) = 0;
if (u != hold_head) {
link(u) = link(r);
link(r) = link(hold_head);
r = u;
}
r = link(link(r));
s = link(link(s));
} while (r != NULL);
} else if (type(q) == RULE_NODE) {
if (is_running(width(q)))
width(q) = width(p);
if (is_running(height(q)))
height(q) = height(p);
if (is_running(depth(q)))
depth(q) = depth(p);
if (o != 0) {
r = link(q);
link(q) = NULL;
q = hpack(q, NATURAL);
shift_amount(q) = o;
link(q) = r;
link(s) = q;
}
}
}
flush_node_list(p);
pop_alignment();
t = aux;
p = link(head);
q = tail;
pop_nest();
if (mode == MMODE) {
do_assignments();
if (cur_cmd != MATH_SHIFT) {
print_err("Missing $$ inserted");
help_fin_display_align();
back_error();
} else {
get_x_token();
if (cur_cmd != MATH_SHIFT) {
print_err("Display math should end with $$");
help_fin_display();
back_error();
}
}
pop_nest();
tail_append(new_penalty(pre_display_penalty));
tail_append(new_param_glue(ABOVE_DISPLAY_SKIP_CODE));
link(tail) = p;
if (p != NULL)
tail = q;
tail_append(new_penalty(post_display_penalty));
tail_append(new_param_glue(BELOW_DISPLAY_SKIP_CODE));
prev_depth = t;
resume_after_display();
} else {
aux = t;
link(tail) = p;
if (p != NULL)
tail = q;
if (mode == VMODE)
build_page();
}
}
/*
* Help text
*/
help_display_align ()
{
help3("Displays can use special alignments (like \\eqalignno)",
"only if nothing but the alignment itself is between $$'s.",
"So I've deleted the formulas that preceded this alignment.");
}
help_fin_display_align ()
{
help2("Displays can use special alignments (like \\eqalignno)",
"only if nothing but the alignment itself is between $$'s.");
}
help_preamble_missing ()
{
help3("There should be exactly one # between &'s, when an",
"\\halign or \\valign is being set up. In this case you had",
"none, so I've put one in; maybe that will work.");
}
help_preamble_many ()
{
help3("There should be exactly one # between &'s, when an",
"\\halign or \\valign is being set up. In this case you had",
"more than one, so I'm ignoring all but the first.");
}
help_align_apply ()
{
help3("You have given more \\span or & marks than there were",
"in the preamble to the \\halign or \\valign now in progress.",
"So I'll assume that you meant to type \\cr instead.");
}
help_fin_display ()
{
help2("The `$' that I just saw supposedly matches a previous `$$'.",
"So I shall assume that you typed `$$' both times.");
}