home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OSK
/
APPS
/
lout2.lzh
/
LOUT2
/
z18.c
< prev
next >
Wrap
Text File
|
1994-01-23
|
17KB
|
406 lines
/*@z18.c:Galley Transfer:Declarations@****************************************/
/* */
/* LOUT: A HIGH-LEVEL LANGUAGE FOR DOCUMENT FORMATTING (VERSION 2.05) */
/* COPYRIGHT (C) 1993 Jeffrey H. Kingston */
/* */
/* Jeffrey H. Kingston (jeff@cs.su.oz.au) */
/* Basser Department of Computer Science */
/* The University of Sydney 2006 */
/* AUSTRALIA */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 1, or (at your option) */
/* any later version. */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program; if not, write to the Free Software */
/* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* */
/* FILE: z18.c */
/* MODULE: Galley Transfer */
/* EXTERNS: TransferInit(), TransferBegin(), TransferComponent(), */
/* TransferEnd(), TransferClose() */
/* */
/*****************************************************************************/
#include "externs"
#define MAX_DEPTH 30 /* max depth of galleys */
static OBJECT root_galley = nil; /* the root galley */
static OBJECT targets[MAX_DEPTH]; /* currently open \Inputs */
static CONSTRAINT constraints[MAX_DEPTH]; /* their COL constraints */
static int itop; /* stack top */
static CONSTRAINT initial_constraint; /* initial COL constraint */
static STYLE InitialStyle; /* initial style */
#if DEBUG_ON
static debug_targets()
{ int i; OBJECT tmp;
for( i = 0; i <= itop; i++ )
{ if( targets[i] == nil || Down(targets[i]) == targets[i] ) tmp = nil;
else Child(tmp, Down(targets[i]));
debug3(DGT, D, " target[%d] %s = %s", i,
EchoConstraint(&constraints[i]), EchoObject(tmp));
}
} /* end debug_targets */
#endif
/*@::TransferInit()@**********************************************************/
/* */
/* TransferInit(InitEnv) */
/* */
/* Initialise this module. The initial environment is InitEnv. */
/* */
/*****************************************************************************/
TransferInit(InitEnv)
OBJECT InitEnv;
{ OBJECT dest, x, y, recs, inners, nothing, dest_index, up_hd;
debug1(DGT, D, "TransferInit( %s )", EchoObject(InitEnv));
SetConstraint(initial_constraint, MAX_LEN-1, MAX_LEN-1, MAX_LEN-1);
/* save initial environment and style */
SetGap( line_gap(InitialStyle), FALSE, FALSE, FIXED_UNIT, MARK_MODE, 18*PT);
SetGap(space_gap(InitialStyle), FALSE, TRUE, FIXED_UNIT, EDGE_MODE, 1*EM);
font(InitialStyle) = 0;
hyph_style(InitialStyle) = HYPH_UNDEF;
fill_style(InitialStyle) = FILL_UNDEF;
display_style(InitialStyle) = DISPLAY_UNDEF;
/* construct destination for root galley */
up_hd = New(HEAD);
dest_index = New(RECEIVING);
dest = New(CLOSURE); actual(dest) = PrintSym;
actual(dest_index) = dest;
external(dest) = TRUE;
threaded(dest) = FALSE;
blocked(dest_index) = FALSE;
Link(up_hd, dest_index);
/* construct root galley */
root_galley = New(HEAD);
FposCopy(fpos(root_galley), *no_fpos);
actual(root_galley) = whereto(root_galley) = ready_galls(root_galley) = nil;
backward(root_galley) = must_expand(root_galley) = sized(root_galley) = FALSE;
x = New(CLOSURE); actual(x) = InputSym;
Link(root_galley, x);
SizeGalley(root_galley, InitEnv, TRUE, FALSE, FALSE, FALSE, &InitialStyle,
&initial_constraint, nil, ¬hing, &recs, &inners);
assert( recs == nil , "TransferInit: recs != nil!" );
assert( inners == nil , "TransferInit: inners != nil!" );
Link(dest_index, root_galley);
/* initialise target and constraint stacks */
Child(y, Down(root_galley));
assert( type(y) == RECEPTIVE && type(actual(y)) == CLOSURE &&
actual(actual(y)) == InputSym, "TransferInit: initial galley!" );
assert( external(actual(y)), "TransferInit: input sym not external!" );
blocked(y) = TRUE;
targets[itop = 0] = New(ACAT);
Link(targets[itop], y);
Constrained(actual(y), &constraints[itop], COL);
debug2(DSC, D, "Constrained( %s, COL ) = %s",
EchoObject(y), EchoConstraint(&constraints[itop]));
debug0(DGT, D, "TransferInit returning.");
ifdebug(DGT, DD, debug_targets());
} /* end TransferInit */
/*@::TransferBegin()@*********************************************************/
/* */
/* OBJECT TransferBegin(x) */
/* */
/* Commence the transfer of a new galley whose header is invokation x. */
/* */
/*****************************************************************************/
OBJECT TransferBegin(x)
OBJECT x;
{ OBJECT xsym, index, y, link, env, new_env, hold_env, res, hd, target;
CONSTRAINT c;
debug1(DGT, D, "TransferBegin( %s )", EchoObject(x));
ifdebug(DGT, DD, debug_targets());
assert( type(x) == CLOSURE, "TransferBegin: non-CLOSURE!" );
/* add an automatically generated @Tag parameter to x if required */
CrossAddTag(x);
/* construct new (inner) env chain */
if( Down(targets[itop]) == targets[itop] )
Error(FATAL, &fpos(x), "cannot attach galley %s", SymName(actual(x)));
Child(target, Down(targets[itop]));
xsym = actual(x);
env = GetEnv(actual(target));
debug1(DGT, DD, " current env chain: %s", EchoObject(env));
if( has_body(xsym) )
{
/* prepare a copy of x for inclusion in environment */
y = CopyObject(x, no_fpos);
/* attach its environment */
AttachEnv(env, y);
/* now the new environment is y catenated with the old one */
debug0(DCR, DD, "calling SetEnv from TransferBegin (a)");
new_env = SetEnv(y, nil);
}
else new_env = env;
hold_env = New(ACAT); Link(hold_env, new_env);
debug1(DGT, DD, " new env chain: %s", EchoObject(new_env));
/* convert x into an unsized galley called hd */
index = New(UNATTACHED);
hd = New(HEAD);
FposCopy(fpos(hd), fpos(x));
actual(hd) = xsym;
backward(hd) = TargetSymbol(x, &whereto(hd));
ready_galls(hd) = nil;
must_expand(hd) = TRUE;
sized(hd) = FALSE;
Link(index, hd);
Link(hd, x);
AttachEnv(env, x);
/* search for destination for hd and release it */
Link(Up(target), index);
debug0(DGF, D, " calling FlushGalley from TransferBegin");
FlushGalley(hd);
/* if failed to flush, undo everything and exit */
Parent(index, Up(hd));
if( type(index) == UNATTACHED && !sized(hd) )
{ DeleteNode(index);
DisposeObject(hold_env);
if( LastDown(x) != x )
{ Child(env, LastDown(x));
if( type(env) == ENV ) DisposeChild(LastDown(x));
}
debug1(DGT,D, "TransferBegin returning failed, x: %s", EchoObject(x));
return x;
}
if( has_rpar(actual(hd)) )
{
/* set up new target to be inner \InputSym, or nil if none */
if( ++itop >= MAX_DEPTH ) Error(FATAL, &fpos(x),
"galley nested too deeply (max is %d)", MAX_DEPTH);
targets[itop] = New(ACAT); target = nil;
for( link = Down(hd); link != hd; link = NextDown(link) )
{ Child(y, link);
if( type(y) == RECEPTIVE && actual(actual(y)) == InputSym )
{
Constrained(actual(y), &constraints[itop], COL);
if( FitsConstraint(0, 0, constraints[itop]) )
{ Link(targets[itop], y); target = y;
debug2(DSC, D, "Constrained( %s, COL ) = %s",
EchoObject(y), EchoConstraint(&constraints[itop]));
env = DetachEnv(actual(y));
AttachEnv(new_env, actual(y));
}
else
{ Error(WARN, &fpos(hd), "galley %s deleted (target too narrow)",
SymName(actual(hd)));
}
break;
}
}
/* return a token appropriate to the new target */
if( target == nil || external(actual(target)) )
res = NewToken(GSTUB_EXT, no_fpos, 0, 0, precedence(xsym), nil);
else
{ Constrained(actual(target), &c, ROW);
if( constrained(c) ) Error(FATAL, &fpos(target),
"right parameter of %s is vertically constrained", SymName(xsym));
else res = NewToken(GSTUB_INT, no_fpos, 0, 0, precedence(xsym), nil);
}
}
else res = NewToken(GSTUB_NONE, no_fpos, 0, 0, precedence(xsym), nil);
DisposeObject(hold_env);
debug1(DGT, D, "TransferBegin returning %s", Image(type(res)));
ifdebug(DGT, DD, debug_targets());
return res;
} /* end TransferBegin */
/*@::TransferComponent()@*****************************************************/
/* */
/* TransferComponent(x) */
/* */
/* Transfer component x of a galley. */
/* */
/*****************************************************************************/
TransferComponent(x)
OBJECT x;
{ OBJECT y, env, start_search, recs, inners, nothing, hd, dest, dest_index;
debug1(DGT, D, "TransferComponent( %s )", EchoObject(x));
ifdebug(DGT, DD, debug_targets());
/* if no dest_index, discard x and exit */
if( Down(targets[itop]) == targets[itop] )
{ DisposeObject(x);
debug0(DGT, D, "TransferComponent returning (no target).");
return;
}
Child(dest_index, Down(targets[itop]));
assert( external(actual(dest_index)), "TransferComponent: internal!" );
/* make the component into a galley */
hd = New(HEAD);
FposCopy(fpos(hd), fpos(x));
actual(hd) = whereto(hd) = ready_galls(hd) = nil;
backward(hd) = must_expand(hd) = sized(hd) = FALSE;
Link(hd, x);
dest = actual(dest_index);
env = GetEnv(dest);
debug1(DGT, DD, " current env chain: %s", EchoObject(env));
SizeGalley(hd, env, TRUE, threaded(dest), FALSE, TRUE, &save_style(dest),
&constraints[itop], nil, ¬hing, &recs, &inners);
if( recs != nil ) ExpandRecursives(recs);
/* promote the components, remembering where old spot was */
start_search = PrevDown(Up(dest_index));
debug0(DSA, D, " calling AdjustSize from TransferComponent");
AdjustSize(dest, back(hd, COL), fwd(hd, COL), COL);
Promote(hd, hd, dest_index);
DeleteNode(hd);
/* flush any widowed galleys attached to \Input */
if( Down(dest_index) != dest_index )
{ OBJECT tinners, index;
tinners = New(ACAT);
while( Down(dest_index) != dest_index )
{ Child(y, Down(dest_index));
assert( type(y) == HEAD, "TransferComponent: input child!" );
DetachGalley(y);
Parent(index, Up(y));
MoveLink(Up(index), NextDown(start_search), PARENT);
Link(tinners, index);
}
FlushInners(tinners, nil);
}
/* flush any galleys inside hd */
if( inners != nil ) FlushInners(inners, nil);
/* flush parent galley, if needed */
if( blocked(dest_index) )
{ blocked(dest_index) = FALSE;
Parent(y, Up(dest_index));
debug0(DGF, D, " calling FlushGalley from TransferComponent");
FlushGalley(y);
}
debug0(DGT, D, "TransferComponent returning.");
ifdebug(DGT, DD, debug_targets());
} /* end TransferComponent */
/*@::TransferEnd()@***********************************************************/
/* */
/* TransferEnd(x) */
/* */
/* End the transfer of a galley. */
/* */
/*****************************************************************************/
TransferEnd(x)
OBJECT x;
{ OBJECT recs, inners, nothing, z, env, dest, hd, dest_index, y, start_search;
debug1(DGT, D, "TransferEnd( %s )", EchoObject(x));
ifdebug(DGT, DD, debug_targets());
/* if no dest_index, discard x and exit */
if( Down(targets[itop]) == targets[itop] )
{ DisposeObject(x); DisposeObject(targets[itop--]);
debug0(DGT, D, "TransferEnd returning: no dest_index");
return;
}
Child(dest_index, Down(targets[itop]));
/* make the component into a galley */
hd = New(HEAD); FposCopy(fpos(hd), fpos(x));
actual(hd) = whereto(hd) = ready_galls(hd) = nil;
backward(hd) = must_expand(hd) = sized(hd) = FALSE;
Link(hd, x); dest = actual(dest_index); env = GetEnv(dest);
debug1(DGT, DD, " current env chain: %s", EchoObject(env));
SizeGalley(hd, env, external(dest), threaded(dest), FALSE, TRUE,
&save_style(dest), &constraints[itop], nil, ¬hing, &recs, &inners);
if( recs != nil ) ExpandRecursives(recs);
/* promote the components, remembering where old spot was */
start_search = PrevDown(Up(dest_index));
debug0(DSA, D, "calling AdjustSize from TransferEnd (a)");
AdjustSize(dest, back(hd, COL), fwd(hd, COL), COL);
if( !external(dest) )
{ Child(z, LastDown(hd));
debug0(DSA, D, "calling AdjustSize from TransferEnd (b)");
AdjustSize(dest, back(z, ROW), fwd(z, ROW), ROW);
Interpose(dest, VCAT, hd, z);
}
Promote(hd, hd, dest_index); DeleteNode(hd);
/* flush any widowed galleys attached to \Input */
if( Down(dest_index) != dest_index )
{ OBJECT tinners, index;
tinners = New(ACAT);
while( Down(dest_index) != dest_index )
{ Child(y, Down(dest_index));
assert( type(y) == HEAD, "TransferComponent: input child!" );
DetachGalley(y);
Parent(index, Up(y));
MoveLink(Up(index), NextDown(start_search), PARENT);
Link(tinners, index);
}
FlushInners(tinners, nil);
}
/* flush any galleys inside hd */
if( inners != nil ) FlushInners(inners, nil);
/* close dest_index, and flush parent galley if needed */
if( blocked(dest_index) )
{ Parent(y, Up(dest_index));
DeleteNode(dest_index);
debug0(DGF, D, " calling FlushGalley from TransferEnd");
FlushGalley(y);
}
else DeleteNode(dest_index);
/* pop target stack and exit */
DisposeObject(targets[itop--]);
debug0(DGT, D, "TransferEnd returning.");
ifdebug(DGT, DD, debug_targets());
} /* end TransferEnd */
/*@::TransferClose()@*********************************************************/
/* */
/* TransferClose() */
/* */
/* Close this module. */
/* */
/*****************************************************************************/
TransferClose()
{ OBJECT inners;
debug0(DGT, D, "TransferClose()");
debug0(DGA, D, " calling FreeGalley from TransferClose");
if( LastDown(root_galley) != root_galley )
{ inners = nil;
FreeGalley(root_galley, root_galley, &inners, nil, nil);
if( inners != nil ) FlushInners(inners, nil);
debug0(DGF, D, " calling FlushGalley from TransferClose");
FlushGalley(root_galley);
}
debug0(DGT, D, "TransferClose returning.");
}