home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari FTP
/
ATARI_FTP_0693.zip
/
ATARI_FTP_0693
/
Tex
/
Tex29
/
StTeXsrc.zoo
/
src
/
boxlists.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-03-13
|
26KB
|
1,098 lines
/*
* @(#)boxlists.c 2.6 EPA
*
* Copyright 1987,1988 Pat J Monardo
*
* Redistribution of this file is permitted through
* the specifications in the file COPYING.
*
*
*/
#include "tex.h"
#include "token.h"
#include "tokenstack.h"
#include "tokenlists.h"
#include "eqstack.h"
#include "evalstack.h"
#include "box.h"
#include "scan.h"
#include "def.h"
#include "tfm.h"
#include "pack.h"
#include "page.h"
#include "math.h"
#include "boxlists.h"
ptr cur_box;
append_glue ()
{
hword s;
s = cur_chr;
switch (s)
{
case FIL_CODE:
cur_val = fil_glue;
break;
case FILL_CODE:
cur_val = fill_glue;
break;
case SS_CODE:
cur_val = ss_glue;
break;
case FIL_NEG_CODE:
cur_val = fil_neg_glue;
break;
case SKIP_CODE:
scan_glue(GLUE_VAL);
break;
case MSKIP_CODE:
scan_glue(MU_VAL);
break;
default:
break;
}
tail_append(new_glue((ptr) cur_val));
if (s >= SKIP_CODE) {
decr(glue_ref_count((ptr) cur_val));
if (s > SKIP_CODE)
subtype(tail) = MU_GLUE;
}
}
append_kern ()
{
qword s;
s = cur_chr;
scan_dimen(s == MU_GLUE, FALSE, FALSE);
tail_append(new_kern(cur_val));
subtype(tail) = s;
}
handle_right_brace ()
{
scal d;
val f;
ptr p;
ptr q;
switch (cur_group)
{
case SIMPLE_GROUP:
unsave();
break;
case BOTTOM_LEVEL:
print_err("Too many }'s");
help_close_group();
error();
break;
case SEMI_SIMPLE_GROUP:
case MATH_SHIFT_GROUP:
case MATH_LEFT_GROUP:
extra_right_brace();
break;
case HBOX_GROUP:
package(0);
break;
case ADJUSTED_HBOX_GROUP:
adjust_tail = adjust_head;
package(0);
break;
case VBOX_GROUP:
end_graf();
package(0);
break;
case VTOP_GROUP:
end_graf();
package(VTOP_CODE);
break;
case INSERT_GROUP:
end_graf();
q = split_top_skip;
add_glue_ref(q);
d = split_max_depth;
f = floating_penalty;
unsave();
decr(save_ptr);
p = vpack(link(head), NATURAL);
pop_nest();
if (saved(0) < 255) {
tail_append(get_node(INS_NODE_SIZE));
type(tail) = INS_NODE;
subtype(tail) = qi(saved(0));
height(tail) = height(p) + depth(p);
ins_ptr(tail) = list_ptr(p);
split_top_ptr(tail) = q;
depth(tail) = d;
float_cost(tail) = f;
} else {
tail_append(get_node(SMALL_NODE_SIZE));
type(tail) = ADJUST_NODE;
subtype(tail) = 0;
adjust_ptr(tail) = list_ptr(p);
delete_glue_ref(q);
}
free_node(p, BOX_NODE_SIZE);
if (nest_ptr == 0)
build_page();
break;
case OUTPUT_GROUP:
if (loc != NULL) {
print_err("Unbalanced output routine");
help_output_balance();
error();
do get_token();
while (loc != NULL);
}
end_token_list();
end_graf();
unsave();
output_active = FALSE;
insert_penalties = 0;
if (box(255) != NULL) {
print_err("Output routine didn't use all of ");
print_esc("box255");
help_output();
box_error(255);
}
if (tail != head) {
link(page_tail) = link(head);
page_tail = tail;
}
if (link(page_head) != NULL) {
if (link(contrib_head) == NULL)
contrib_tail = page_tail;
link(page_tail) = link(contrib_head);
link(contrib_head) = link(page_head);
link(page_head) = NULL;
page_tail = page_head;
}
pop_nest();
build_page();
break;
case DISC_GROUP:
build_discretionary();
break;
case ALIGN_GROUP:
back_input();
cur_tok = CS_TOKEN_FLAG + FROZEN_CR;
print_err("Missing ");
print_esc("cr");
print(" inserted");
help_align_cr();
ins_error();
break;
case NO_ALIGN_GROUP:
end_graf();
unsave();
align_peek();
break;
case VCENTER_GROUP:
end_graf();
unsave();
save_ptr -= 2;
p = vpackage(link(head), saved(1), (int) saved(0), MAX_DIMEN);
pop_nest();
tail_append(new_noad());
type(tail) = VCENTER_NOAD;
math_type(nucleus(tail)) = SUB_BOX;
info(nucleus(tail)) = p;
break;
case MATH_CHOICE_GROUP:
build_choices();
break;
case MATH_GROUP:
unsave();
decr(save_ptr);
math_type(saved(0)) = SUB_MLIST;
p = fin_mlist(NULL);
info(saved(0)) = p;
if (p != NULL) {
if (link(p) == NULL) {
if (type(p) == ORD_NOAD) {
if (math_type(subscr(p)) == EMPTY &&
math_type(supscr(p)) == EMPTY) {
mem[saved(0)].hh = mem[nucleus(p)].hh;
free_node(p, NOAD_SIZE);
}
} else if (type(p) == ACCENT_NOAD &&
saved(0) == nucleus(tail) &&
type(tail) == ORD_NOAD) {
q = head;
while (link(q) != tail)
q = link(q);
link(q) = p;
free_node(tail, NOAD_SIZE);
tail = p;
}
}
}
break;
default:
confusion("rightbrace");
break;
}
}
extra_right_brace ()
{
print_err("Extra }, or forgotten ");
switch (cur_group)
{
case SEMI_SIMPLE_GROUP:
print_esc("endgroup");
break;
case MATH_SHIFT_GROUP:
print_char('$');
break;
case MATH_LEFT_GROUP:
print_esc("right");
break;
}
help_group_close();
error();
incr(align_state);
}
scan_spec ()
{
if (scan_keyword("to")) {
saved(0) = EXACTLY;
} else if (scan_keyword("spread")) {
saved(0) = ADDITIONAL;
} else {
saved(0) = ADDITIONAL;
saved(1) = 0;
goto found;
}
scan_normal_dimen();
saved(1) = cur_val;
found:
save_ptr += 2;
scan_left_brace();
}
scan_box ()
{
get_nbrx_token();
if (cur_cmd == MAKE_BOX) {
begin_box();
} else if (saved(0) >= LEADER_FLAG &&
(cur_cmd == HRULE || cur_cmd == VRULE)) {
cur_box = scan_rule_spec();
box_end();
} else {
print_err("A <box> was supposed to be here");
help_box();
back_error();
}
}
begin_box ()
{
int k;
int m;
int n;
ptr p;
ptr q;
switch (cur_chr)
{
case BOX_CODE:
scan_eight_bit_int();
cur_box = box(cur_val);
box(cur_val) = NULL;
break;
case COPY_CODE:
scan_eight_bit_int();
cur_box = copy_node_list(box(cur_val));
break;
case LAST_BOX_CODE:
cur_box = NULL;
if (abs(mode) == MMODE) {
you_cant();
help_lastbox_m();
error();
} else if (mode == VMODE && head == tail) {
you_cant();
help_lastbox_v();
error();
} else if (!is_char_node(tail) &&
(type(tail) == HLIST_NODE || type(tail) == VLIST_NODE)) {
q = head;
do {
p = q;
if (!is_char_node(q) && type(q) == DISC_NODE) {
for (m = 1; m <= replace_count(q); incr(m))
p = link(p);
if (p == tail)
break;
}
q = link(p);
} while (q != tail);
cur_box = tail;
shift_amount(cur_box) = 0;
tail = p;
link(p) = NULL;
}
break;
case VSPLIT_CODE:
scan_eight_bit_int();
n = cur_val;
if (!scan_keyword("to")) {
print_err("Missing `to' inserted");
help_vsplit();
error();
}
scan_normal_dimen();
cur_box = vsplit(n, cur_val);
break;
default:
k = cur_chr - VTOP_CODE;
incr(save_ptr);
scan_spec();
if (k == HMODE) {
if (saved(-3) < BOX_FLAG && abs(mode) == VMODE)
new_save_level(ADJUSTED_HBOX_GROUP);
else new_save_level(HBOX_GROUP);
} else {
if (k == VMODE) {
new_save_level(VBOX_GROUP);
} else {
new_save_level(VTOP_GROUP);
k = VMODE;
}
normal_paragraph();
}
push_nest();
mode = -k;
if (k == VMODE) {
prev_depth = IGNORE_DEPTH;
if (every_vbox != NULL)
begin_token_list(every_vbox, EVERY_VBOX_TEXT);
} else {
space_factor = 1000;
if (every_hbox != NULL)
begin_token_list(every_hbox, EVERY_HBOX_TEXT);
}
return;
}
box_end();
}
box_end ()
{
ptr p;
if (saved(0) < BOX_FLAG) {
if (cur_box != NULL) {
shift_amount(cur_box) = saved(0);
if (abs(mode) == VMODE) {
append_to_vlist(cur_box);
if (adjust_tail != NULL) {
if (adjust_head != adjust_tail) {
link(tail) = link(adjust_head);
tail = adjust_tail;
}
adjust_tail = NULL;
}
if (mode > 0)
build_page();
} else {
if (abs(mode) == HMODE) {
space_factor = 1000;
} else {
p = new_noad();
math_type(nucleus(p)) = SUB_BOX;
info(nucleus(p)) = cur_box;
cur_box = p;
}
link(tail) = cur_box;
tail = cur_box;
}
}
} else if (saved(0) < SHIP_OUT_FLAG) {
if (saved(0) < BOX_FLAG + 256)
eq_define((ptr)(BOX_BASE-BOX_FLAG+saved(0)), BOX_REF, cur_box);
else
geq_define((ptr)(BOX_BASE-BOX_FLAG-256+saved(0)), BOX_REF, cur_box);
} else if (cur_box != NULL) {
if (saved(0) > SHIP_OUT_FLAG) {
get_nbrx_token();
if (cur_cmd == HSKIP && abs(mode) != VMODE ||
cur_cmd == VSKIP && abs(mode) == VMODE ||
cur_cmd == MSKIP && abs(mode) == MMODE) {
append_glue();
leader_ptr(tail) = cur_box;
subtype(tail) = saved(0) - (LEADER_FLAG - A_LEADERS);
} else {
print_err("Leaders not followed by proper glue");
help_leaders();
back_error();
flush_node_list(cur_box);
}
} else {
ship_out(cur_box);
}
}
}
package (c)
int c;
{
scal d;
scal h;
ptr p;
d = box_max_depth;
unsave();
save_ptr -= 3;
if (mode == -HMODE) {
cur_box = hpack(link(head), saved(2), (int) saved(1));
} else {
cur_box = vpackage(link(head), saved(2), (int) saved(1), d);
if (c == VTOP_CODE) {
h = 0;
p = list_ptr(cur_box);
if (p != NULL && type(p) <= RULE_NODE)
h = height(p);
depth(cur_box) += height(cur_box) - h;
height(cur_box) = h;
}
}
pop_nest();
box_end();
}
normal_paragraph ()
{
if (looseness != 0)
eq_word_define((ptr) INT_BASE + LOOSENESS_CODE, 0L);
if (hang_indent != 0)
eq_word_define((ptr) DIMEN_BASE + HANG_INDENT_CODE, 0L);
if (hang_after != 1)
eq_word_define((ptr) INT_BASE + HANG_AFTER_CODE, 1L);
if (par_shape_ptr != NULL)
eq_define(PAR_SHAPE_LOC, SHAPE_REF, NULL);
}
new_graf (indented)
bool indented;
{
prev_graf = 0;
if (mode == VMODE || head != tail)
tail_append(new_param_glue(PAR_SKIP_CODE));
push_nest();
mode = HMODE;
space_factor = 1000;
if (indented) {
tail = new_null_box();
link(head) = tail;
width(tail) = par_indent;
}
if (every_par != NULL)
begin_token_list(every_par, EVERY_PAR_TEXT);
if (nest_ptr == 1)
build_page();
}
indent_in_hmode ()
{
ptr p;
ptr q;
if (cur_chr > 0) {
p = new_null_box();
width(p) = par_indent;
if (abs(mode) == HMODE) {
space_factor = 1000;
} else {
q = new_noad();
math_type(nucleus(q)) = SUB_BOX;
info(nucleus(q)) = p;
p = q;
}
tail_append(p);
}
}
head_for_vmode ()
{
if (mode < 0) {
if (cur_cmd != HRULE) {
off_save();
} else {
print_err("You can't use `");
print_esc("hrule");
print("' here except with leaders");
help_head_for_vmode();
error();
}
} else {
back_input();
cur_tok = par_token;
back_input();
token_type = INSERTED;
}
}
end_graf ()
{
if (mode == HMODE) {
if (head == tail)
pop_nest();
else line_break(widow_penalty);
normal_paragraph();
error_count = 0;
}
}
append_to_vlist (b)
ptr b;
{
scal d;
ptr p;
if (prev_depth > IGNORE_DEPTH) {
d = width(baseline_skip) - prev_depth - height(b);
if (d < line_skip_limit) {
p = new_param_glue(LINE_SKIP_CODE);
} else {
p = new_skip_param(BASELINE_SKIP_CODE);
width(temp_ptr) = d;
}
link(tail) = p;
tail = p;
}
link(tail) = b;
tail = b;
prev_depth = depth(b);
}
begin_insert_or_adjust ()
{
if (cur_cmd == VADJUST) {
cur_val = 255;
} else {
scan_eight_bit_int();
if (cur_val == 255) {
print_err("You can't ");
print_esc("insert");
print_int(255);
help_insert_255();
error();
cur_val = 0;
}
}
saved(0) = cur_val;
incr(save_ptr);
new_save_level(INSERT_GROUP);
scan_left_brace();
normal_paragraph();
push_nest();
mode = -VMODE;
prev_depth = IGNORE_DEPTH;
}
make_mark ()
{
ptr p;
scan_toks(FALSE, TRUE);
p = get_node(SMALL_NODE_SIZE);
type(p) = MARK_NODE;
subtype(p) = 0;
mark_ptr(p) = def_ref;
link(tail) = p;
tail = p;
}
append_penalty ()
{
scan_int();
tail_append(new_penalty(cur_val));
if (mode == VMODE)
build_page();
}
delete_last ()
{
qword m;
ptr p;
ptr q;
if (mode == VMODE && tail == head) {
if (cur_chr != GLUE_NODE || last_glue != MAX_HALFWORD) {
you_cant();
help_delete_last();
if (cur_chr == KERN_NODE)
help_line[1] = "Try `I\\kern-\\lastkern' instead.";
else if (cur_chr != GLUE_NODE)
help_line[1] = "Perhaps you can make the output routine do it.";
error();
}
} else if (!is_char_node(tail) && type(tail) == cur_chr) {
q = head;
do {
p = q;
if (!is_char_node(q) && type(q) == DISC_NODE) {
for (m = 1; m <= replace_count(q); incr(m))
p = link(p);
if (p == tail)
return;
}
q = link(p);
} while (q != tail);
link(p) = NULL;
flush_node_list(tail);
tail = p;
}
}
unpackage ()
{
int c;
ptr p;
c = cur_chr;
scan_eight_bit_int();
p = box(cur_val);
if (p == NULL) return;
if (abs(mode) == MMODE ||
abs(mode) == VMODE && type(p) != VLIST_NODE ||
abs(mode) == HMODE && type(p) != HLIST_NODE) {
print_err("Incompatible list can't be unboxed");
help_pandora();
error();
return;
}
if (c == COPY_CODE) {
link(tail) = copy_node_list(list_ptr(p));
} else {
link(tail) = list_ptr(p);
box(cur_val) = NULL;
free_node(p, BOX_NODE_SIZE);
}
while (link(tail) != NULL)
tail = link(tail);
}
append_italic_correction ()
{
ptr p;
fnt f;
if (tail != head) {
if (is_char_node(tail))
p = tail;
else if (type(tail) == LIGATURE_NODE)
p = lig_char(tail);
else return;
f = font(p);
tail_append(new_kern(char_italic(f, char_info(f, character(p)))));
subtype(tail) = EXPLICIT;
}
}
append_discretionary ()
{
int c;
tail_append(new_disc());
if (cur_chr == 1) {
c = hyphen_char[cur_font];
if (c >= 0 && c < 256)
pre_break(tail) = new_character(cur_font, c);
} else {
incr(save_ptr);
saved(-1) = 0;
scan_left_brace();
new_save_level(DISC_GROUP);
push_nest();
mode = -HMODE;
space_factor = 1000;
}
}
build_discretionary ()
{
int n;
ptr p;
ptr q;
unsave();
q = head;
p = link(q);
n = 0;
while (p != NULL) {
if (!is_char_node(p) && type(p) > RULE_NODE &&
type(p) != KERN_NODE && type(p) != LIGATURE_NODE) {
print_err("Improper discretionary list");
help_discretionary();
error();
begin_diagnostic();
print_nl("The following discretionary sublist has been deleted:");
show_box(p);
end_diagnostic(TRUE);
flush_node_list(p);
link(q) = NULL;
break;
}
q = p;
p = link(q);
incr(n);
}
p = link(head);
pop_nest();
switch ((int) saved(-1))
{
case 0:
pre_break(tail) = p;
break;
case 1:
post_break(tail) = p;
break;
case 2:
if (n > 0 && abs(mode) == MMODE) {
print_err("Illegal math ");
print_esc("discretionary");
help_math_disc();
flush_node_list(p);
n = 0;
error();
} else
link(tail) = p;
if (n <= MAX_QUARTERWORD)
replace_count(tail) = n;
else {
print_err("Discretionary list is too long");
help_disc();
error();
}
if (n > 0) tail = q;
decr(save_ptr);
return;
}
incr(saved(-1));
scan_left_brace();
new_save_level(DISC_GROUP);
push_nest();
mode = -HMODE;
space_factor = 1000;
}
make_accent ()
{
scal a;
fnt f;
scal h;
qqqq i;
ptr p;
ptr q;
ptr r;
float s;
float t;
scal w;
scal x;
scal delta;
scan_char_num();
f = cur_font;
p = new_character(f, cur_val);
if (p != NULL) {
x = x_height(f);
s = (float) slant(f) / 65536.0;
a = char_width(f, char_info(f, character(p)));
do_assignments();
q = NULL;
f = cur_font;
if (cur_cmd == LETTER ||
cur_cmd == OTHER_CHAR ||
cur_cmd == CHAR_GIVEN) {
q = new_character(f, cur_chr);
} else if (cur_cmd == CHAR_NUM) {
scan_char_num();
q = new_character(f, cur_val);
} else back_input();
if (q != NULL) {
t = (float) slant(f) / 65536.0;
i = char_info(f, character(q));
w = char_width(f, i);
h = char_height(f, height_depth(i));
if (h != x) {
p = hpack(p, NATURAL);
shift_amount(p) = x - h;
}
delta = round((float) (w - a) / 2.0 + h * t - x * s);
r = new_kern(delta);
subtype(r) = ACC_KERN;
link(tail) = r;
link(r) = p;
tail = new_kern(-a - delta);
subtype(tail) = ACC_KERN;
link(p) = tail; p = q;
}
link(tail) = p;
tail = p;
space_factor = 1000;
}
}
align_error ()
{
if (abs(align_state) > 2) {
print_err("Misplaced ");
print_cmd_chr(cur_cmd, cur_chr);
if (cur_tok == TAB_TOKEN + '&')
help_tab();
else help_align_error();
error();
} else {
back_input();
if (align_state < 0) {
print_err("Missing { inserted");
incr(align_state);
cur_tok = LEFT_BRACE_TOKEN + '{';
} else {
print_err("Missing } inserted");
decr(align_state);
cur_tok = RIGHT_BRACE_TOKEN + '}';
}
help_fix_alignment();
ins_error();
}
}
no_align_error ()
{
print_err("Misplaced ");
print_esc("noalign");
help_noalign();
error();
}
omit_error ()
{
print_err("Misplaced ");
print_esc("omit");
help_omit();
error();
}
do_endv ()
{
if (cur_group == ALIGN_GROUP) {
end_graf();
if (fin_col())
fin_row();
} else {
off_save();
}
}
cs_error ()
{
print_err("Extra ");
print_esc("endcsname");
help_csname();
error();
}
/*
* Help text
*/
help_head_for_vmode ()
{
help2("To put a horizontal rule in an hbox or an alignment,",
"you should use \\leaders or \\hrulefill (see The TeXbook).");
}
help_close_group ()
{
help2("You've closed more groups than you opened.",
"Such booboos are generally harmless, so keep going.");
}
help_output_balance ()
{
help2("Your sneaky output routine has fewer real {'s than }'s.",
"I can't handle that very well; good luck.");
}
help_output ()
{
help3("Your \\output commands should empty \\box255,",
"e.g., by saying `\\shipout\\box255'.",
"Proceed; I'll discard its present contents.");
}
help_group_close ()
{
help5("I've deleted a group-closing symbol because it seems to be",
"spurious, as in `$x}$'. But perhaps the } is legitimate and",
"you forgot something else, as in `\\hbox{$x}'. In such cases",
"the way to recover is to insert both the forgotten and the",
"deleted material, e.g., by typing `I$}'.");
}
help_leaders ()
{
help3("You should say `\\leaders <box or rule><hskip or vskip>'.",
"I found the <box or rule>, but there's no suitable",
"<hskip or vskip>, so I'm ignoring these leaders.");
}
help_lastbox_m ()
{
help1("Sorry; this \\lastbox will be void.");
}
help_lastbox_v ()
{
help2("Sorry...I usually can't take things from the current page.",
"This \\lastbox will therefore be void.");
}
help_vsplit ()
{
help2("I'm working on `\\vsplit<box number> to <dimen>';",
"will look for the <dimen> next.");
}
help_box ()
{
help3("I was expecting to see \\hbox or \\vbox or \\copy or \\box or",
"something like that. So you might find something missing in",
"your output. But keep trying; you can fix this later.");
}
help_insert_255 ()
{
help1("I'm changing to \\insert0; box 255 is special.");
}
help_space_fac ()
{
help1("I allow only values in the range 1..65536 here.");
}
help_delete_last ()
{
help2("Sorry...I usually can't take things from the current page.",
"Try `I\\vskip-\\lastskip' instead.");
}
help_pandora ()
{
help3("Sorry, Pandora. (You sneaky devil.)",
"I refuse to unbox an \\hbox in vertical mode or vice versa.",
"And I can't open any boxes in math mode.");
}
help_math_disc ()
{
help2("Sorry: The third part of a discretionary break must be",
"empty, in math formulas. I had to delete your third part.");
}
help_discretionary ()
{
help1("Discretionary lists must contain only boxes and kerns.");
}
help_disc ()
{
help2("Wow---I never thought anybody would tweak me here.",
"You can't seriously need such a huge discretionary list?");
}
help_missing_the ()
{
help3("Please dont say \\count or \\dimen or \\skip in the midst of",
"a paragraph or formula. I'm going to assume that you",
"meant to say `\\the\\count' or `\\the\\dimen' or `\\the\\skip',");
}
help_tab ()
{
help6("I can't figure out why you would want to use a tab mark",
"here. If you just want an ampersand, the remedy is",
"simple: Just type `I\\&' now. But if some right brace",
"up above has ended a previous alignment prematurely,",
"you're probably due for more error messages, and you",
"might try typing `S' now just to see what is salvageable.");
}
help_align_error ()
{
help5("I can't figure out why you would want to use a tab mark",
"or \\cr or \\span just now. If something like a right brace",
"up above has ended a previous alignment prematurely,",
"you're probably due for more error messages, and you",
"might try typing `S' now just to see what is salvageable.");
}
help_align_cr ()
{
help1("I'm guessing that you meant to end an alignment here.");
}
help_fix_alignment ()
{
help3("I've put in what seems to be necessary to fix",
"the current column of the current alignment.",
"Try to go on, since this might almost work.");
}
help_noalign ()
{
help2("I expect to see \\noalign only after the \\cr of",
"an alignment. Proceed, and I'll ignore this case.");
}
help_omit ()
{
help2("I expect to see \\omit only after tab marks or the \\cr of",
"an alignment. Proceed, and I'll ignore this case.");
}
help_csname ()
{
help1("I'm ignoring this, since I wasn't doing a \\csname.");
}