diff options
author | Jeffrey H. Kingston <jeff@it.usyd.edu.au> | 2010-09-14 19:21:41 +0000 |
---|---|---|
committer | Jeffrey H. Kingston <jeff@it.usyd.edu.au> | 2010-09-14 19:21:41 +0000 |
commit | 71bdb35d52747e6d7d9f55df4524d57c2966be94 (patch) | |
tree | 480ee5eefccc40d5f3331cc52d66f722fd19bfb9 /z18.c | |
parent | b41263ea7578fa9742486135c762803b52794105 (diff) | |
download | lout-71bdb35d52747e6d7d9f55df4524d57c2966be94.tar.gz |
Lout 3.17.
git-svn-id: http://svn.savannah.nongnu.org/svn/lout/trunk@2 9365b830-b601-4143-9ba8-b4a8e2c3339c
Diffstat (limited to 'z18.c')
-rw-r--r-- | z18.c | 498 |
1 files changed, 498 insertions, 0 deletions
@@ -0,0 +1,498 @@ +/*@z18.c:Galley Transfer:Declarations@****************************************/ +/* */ +/* THE LOUT DOCUMENT FORMATTING SYSTEM (VERSION 3.17) */ +/* COPYRIGHT (C) 1991, 1999 Jeffrey H. Kingston */ +/* */ +/* Jeffrey H. Kingston (jeff@cs.usyd.edu.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 2, 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., 59 Temple Place, Suite 330, Boston MA 02111-1307 USA */ +/* */ +/* FILE: z18.c */ +/* MODULE: Galley Transfer */ +/* EXTERNS: TransferInit(), TransferBegin(), TransferComponent(), */ +/* TransferEnd(), TransferClose() */ +/* */ +/*****************************************************************************/ +#include "externs.h" + +#define MAX_DEPTH 30 /* max depth of galleys */ +static OBJECT root_galley = nilobj; /* the root galley */ +static OBJECT targets[MAX_DEPTH]; /* currently open \Inputs */ +static CONSTRAINT constraints[MAX_DEPTH]; /* their COLM constraints */ +static int itop; /* stack top */ +static CONSTRAINT initial_constraint; /* initial COLM constraint */ + STYLE InitialStyle; /* initial style */ + OBJECT InitialEnvironment; /* initial environment */ + +#if DEBUG_ON +static void debug_targets(void) +{ int i; OBJECT tmp; + for( i = 0; i <= itop; i++ ) + { if( targets[i] == nilobj || Down(targets[i]) == targets[i] ) tmp = nilobj; + 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. */ +/* */ +/*****************************************************************************/ + +void TransferInit(OBJECT InitEnv) +{ OBJECT dest, x, y, recs, inners, nothing, dest_index, up_hd, why; + debug1(DGT, D, "[ TransferInit( %s )", EchoObject(InitEnv)); + SetConstraint(initial_constraint, + MAX_FULL_LENGTH-1, MAX_FULL_LENGTH-1, MAX_FULL_LENGTH-1); + + /* set initial environment and style */ + InitialEnvironment = InitEnv; + SetGap(line_gap(InitialStyle), FALSE,FALSE,FALSE,FIXED_UNIT,MARK_MODE,18*PT); + vadjust(InitialStyle) = FALSE; + hadjust(InitialStyle) = FALSE; + padjust(InitialStyle) = FALSE; + space_style(InitialStyle) = SPACE_LOUT; + SetGap(space_gap(InitialStyle), FALSE,FALSE,TRUE,FIXED_UNIT,EDGE_MODE,1*EM); + hyph_style(InitialStyle) = HYPH_UNDEF; + fill_style(InitialStyle) = FILL_UNDEF; + display_style(InitialStyle) = DISPLAY_UNDEF; + small_caps(InitialStyle) = SMALL_CAPS_OFF; + font(InitialStyle) = 0; /* i.e. undefined */ + colour(InitialStyle) = 0; /* i.e. undefined */ + language(InitialStyle) = 0; /* i.e. undefined */ + yunit(InitialStyle) = 0; /* i.e. zero */ + zunit(InitialStyle) = 0; /* i.e. zero */ + nobreakfirst(InitialStyle) = FALSE; + nobreaklast(InitialStyle) = FALSE; + + /* construct destination for root galley */ + New(up_hd, HEAD); + force_gall(up_hd) = FALSE; + actual(up_hd) = enclose_obj(up_hd) = limiter(up_hd) = nilobj; + opt_components(up_hd) = opt_constraints(up_hd) = nilobj; + gall_dir(up_hd) = ROWM; + New(dest_index, RECEIVING); + New(dest, CLOSURE); actual(dest) = PrintSym; + actual(dest_index) = dest; + debug2(DGT, D, "TransferInit setting external_ver(%s %s) = TRUE", + Image(type(dest)), SymName(actual(dest))); + external_ver(dest) = TRUE; + external_hor(dest) = FALSE; + threaded(dest) = FALSE; + blocked(dest_index) = FALSE; + Link(up_hd, dest_index); + + /* construct root galley */ + New(root_galley, HEAD); + force_gall(root_galley) = FALSE; + enclose_obj(root_galley) = limiter(root_galley) = nilobj; + opt_components(root_galley) = opt_constraints(root_galley) = nilobj; + gall_dir(root_galley) = ROWM; + FposCopy(fpos(root_galley), *no_fpos); + actual(root_galley) = whereto(root_galley) = nilobj; + ready_galls(root_galley) = nilobj; + must_expand(root_galley) = sized(root_galley) =FALSE; + foll_or_prec(root_galley) = GALL_FOLL; + New(x, CLOSURE); actual(x) = InputSym; + Link(root_galley, x); + SizeGalley(root_galley, InitEnv, TRUE, FALSE, FALSE, FALSE, &InitialStyle, + &initial_constraint, nilobj, ¬hing, &recs, &inners, nilobj); + assert( recs == nilobj , "TransferInit: recs != nilobj!" ); + assert( inners == nilobj , "TransferInit: inners != nilobj!" ); + 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_ver(actual(y)), "TransferInit: input sym not external!" ); + blocked(y) = TRUE; + itop = 0; + New(targets[itop], ACAT); + Link(targets[itop], y); + Constrained(actual(y), &constraints[itop], COLM, &why); + debug2(DSC, DD, "Constrained( %s, COLM ) = %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 invocation x. */ +/* */ +/*****************************************************************************/ + +OBJECT TransferBegin(OBJECT x) +{ OBJECT xsym, index, y, link, env, new_env, hold_env, res, hd, target, why; + 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 */ + if( has_tag(actual(x)) ) CrossAddTag(x); + + /* construct new (inner) env chain */ + if( Down(targets[itop]) == targets[itop] ) + Error(18, 1, "cannot attach galley %s", FATAL,&fpos(x),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, DDD, "calling SetEnv from TransferBegin (a)"); + new_env = SetEnv(y, nilobj); + } + else new_env = env; + New(hold_env, ACAT); Link(hold_env, new_env); + debug1(DGT, DD, " new env chain: %s", EchoObject(new_env)); + + /* convert x into an unsized galley called hd */ + New(index, UNATTACHED); + pinpoint(index) = nilobj; + New(hd, HEAD); + FposCopy(fpos(hd), fpos(x)); + actual(hd) = xsym; + limiter(hd) = opt_components(hd) = opt_constraints(hd) = nilobj; + gall_dir(hd) = ROWM; + ready_galls(hd) = nilobj; + must_expand(hd) = TRUE; + sized(hd) = FALSE; + Link(index, hd); + Link(hd, x); + AttachEnv(env, x); + SetTarget(hd); + enclose_obj(hd) = (has_enclose(actual(hd)) ? BuildEnclose(hd) : nilobj); + + /* search for destination for hd and release it */ + Link(Up(target), index); + debug0(DGF,D, ""); + debug1(DGF,D, " calling FlushGalley(%s) from TransferBegin, root_galley =", + SymName(actual(hd))); + ifdebug(DGF, D, DebugGalley(root_galley, nilobj, 4)); + if( whereto(hd) == nilobj || !uses_extern_target(whereto(hd)) ) /* &&& */ + 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 nilobj if none */ + if( ++itop >= MAX_DEPTH ) + Error(18, 2, "galley nested too deeply (max is %d)", + FATAL, &fpos(x), MAX_DEPTH); + New(targets[itop], ACAT); target = nilobj; + 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], COLM, &why); + if( FitsConstraint(0, 0, constraints[itop]) ) + { Link(targets[itop], y); target = y; + debug2(DSC, DD, "Constrained( %s, COLM ) = %s", + EchoObject(y), EchoConstraint(&constraints[itop])); + env = DetachEnv(actual(y)); + AttachEnv(new_env, actual(y)); + } + else + { Error(18, 3, "galley %s deleted (insufficient width at target)", + WARN, &fpos(hd), SymName(actual(hd))); + } + break; + } + } + + /* return a token appropriate to the new target */ + if( target == nilobj || external_ver(actual(target)) ) + res = NewToken(GSTUB_EXT, no_fpos, 0, 0, precedence(xsym), nilobj); + else + { Constrained(actual(target), &c, ROWM, &why); + if( constrained(c) ) + Error(18, 4, "right parameter of %s is vertically constrained", + FATAL, &fpos(target), SymName(xsym)); + else res = NewToken(GSTUB_INT, no_fpos, 0, 0, precedence(xsym), nilobj); + } + debug1(DGT, D, "] TransferBegin returning %s", Image(type(res))); + } + else + { + res = NewToken(GSTUB_NONE, no_fpos, 0, 0, precedence(xsym), nilobj); + debug1(DGT, D, "] TransferBegin returning %s", Image(type(res))); + } + + DisposeObject(hold_env); + ifdebug(DGT, DD, debug_targets()); + return res; +} /* end TransferBegin */ + +/*@::TransferComponent()@*****************************************************/ +/* */ +/* TransferComponent(x) */ +/* */ +/* Transfer component x of a galley. */ +/* */ +/*****************************************************************************/ + +void TransferComponent(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_ver(actual(dest_index)), "TransferComponent: internal!" ); + + /* make the component into a galley */ + New(hd, HEAD); + force_gall(hd) = FALSE; + enclose_obj(hd) = limiter(hd) = nilobj; + opt_components(hd) = opt_constraints(hd) = nilobj; + gall_dir(hd) = ROWM; + FposCopy(fpos(hd), fpos(x)); + actual(hd) = whereto(hd) = ready_galls(hd) = nilobj; + foll_or_prec(hd) = GALL_FOLL; + 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], nilobj, ¬hing, &recs, &inners, nilobj); + if( recs != nilobj ) ExpandRecursives(recs); + debug3(DSA, D, "after SizeGalley, hd width is (%s,%s), constraint was %s", + EchoLength(back(hd, COLM)), EchoLength(fwd(hd, COLM)), + EchoConstraint(&constraints[itop])); + + /* promote the components, remembering where old spot was */ + start_search = PrevDown(Up(dest_index)); + debug1(DSA, D, " calling AdjustSize from TransferComponent %s", + EchoFilePos(&fpos(hd))); + ifdebug(DSA, D, + Child(y, Down(hd)); + while( type(y) == VCAT ) Child(y, Down(y)); + debug2(DSA, D, " first component is %s at %s", + Image(type(y)), EchoFilePos(&fpos(y))); + if( NextDown(Down(hd)) != hd && NextDown(NextDown(Down(hd))) != hd ) + { Child(y, NextDown(NextDown(Down(hd)))); + debug2(DSA, D, " second component is %s at %s", + Image(type(y)), EchoFilePos(&fpos(y))); + } + ); + AdjustSize(dest, back(hd, COLM), fwd(hd, COLM), COLM); + Promote(hd, hd, dest_index, FALSE); + DeleteNode(hd); + + /* flush any widowed galleys attached to \Input */ + if( Down(dest_index) != dest_index ) + { OBJECT tinners, index; + New(tinners, ACAT); + while( Down(dest_index) != dest_index ) + { Child(y, Down(dest_index)); + assert( type(y) == HEAD, "TransferComponent: input child!" ); + if( opt_components(y) != nilobj ) + { DisposeObject(opt_components(y)); + opt_components(y) = nilobj; + debug1(DOG, D, "TransferComponent de-optimizing %s (@Input case)", + SymName(actual(y))); + } + DetachGalley(y); + Parent(index, Up(y)); + MoveLink(Up(index), NextDown(start_search), PARENT); + Link(tinners, index); + } + debug0(DGF, D, " calling FlushInners() from TransferComponent (a)"); + FlushInners(tinners, nilobj); + } + + /* flush any galleys inside hd */ + if( inners != nilobj ) + { + debug0(DGF, D, " calling FlushInners() from TransferComponent (b)"); + FlushInners(inners, nilobj); + } + + /* 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. */ +/* */ +/*****************************************************************************/ + +void TransferEnd(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 */ + New(hd, HEAD); FposCopy(fpos(hd), fpos(x)); + force_gall(hd) = FALSE; + enclose_obj(hd) = limiter(hd) = nilobj; + opt_components(hd) = opt_constraints(hd) = nilobj; + gall_dir(hd) = ROWM; + actual(hd) = whereto(hd) = ready_galls(hd) = nilobj; + foll_or_prec(hd) = GALL_FOLL; + 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_ver(dest), threaded(dest), FALSE, TRUE, + &save_style(dest), &constraints[itop], nilobj, ¬hing, &recs, &inners, + nilobj); + if( recs != nilobj ) ExpandRecursives(recs); + debug3(DSA, D, "after SizeGalley, hd width is (%s,%s), constraint was %s", + EchoLength(back(hd, COLM)), EchoLength(fwd(hd, COLM)), + EchoConstraint(&constraints[itop])); + + /* 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, COLM), fwd(hd, COLM), COLM); + if( !external_ver(dest) ) + { Child(z, LastDown(hd)); + debug0(DSA, D, "calling AdjustSize from TransferEnd (b)"); + AdjustSize(dest, back(z, ROWM), fwd(z, ROWM), ROWM); + Interpose(dest, VCAT, hd, z); + } + Promote(hd, hd, dest_index, TRUE); DeleteNode(hd); + + /* flush any widowed galleys attached to \Input */ + if( Down(dest_index) != dest_index ) + { OBJECT tinners, index; + New(tinners, ACAT); + while( Down(dest_index) != dest_index ) + { Child(y, Down(dest_index)); + assert( type(y) == HEAD, "TransferEnd: input child!" ); + if( opt_components(y) != nilobj ) + { DisposeObject(opt_components(y)); + opt_components(y) = nilobj; + debug1(DOG, D, "TransferEnd de-optimizing %s (@Input case)", + SymName(actual(y))); + } + DetachGalley(y); + Parent(index, Up(y)); + MoveLink(Up(index), NextDown(start_search), PARENT); + Link(tinners, index); + } + debug0(DGF, D, " calling FlushInners() from TransferEnd (a)"); + FlushInners(tinners, nilobj); + } + + /* flush any galleys inside hd */ + if( inners != nilobj ) + { + debug0(DGF, D, " calling FlushInners() from TransferEnd (b)"); + FlushInners(inners, nilobj); + } + + /* 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. */ +/* */ +/*****************************************************************************/ + +void TransferClose(void) +{ OBJECT inners; + debug0(DGT, D, "[ TransferClose()"); + ifdebug(DGT, DD, debug_targets()); + debug0(DGA, D, " calling FreeGalley from TransferClose"); + if( LastDown(root_galley) != root_galley ) + { inners = nilobj; + FreeGalley(root_galley, root_galley, &inners, nilobj, nilobj); + if( inners != nilobj ) + { + debug0(DGF, D, " calling FlushInners() from TransferClose"); + FlushInners(inners, nilobj); + } + debug0(DGF, D, " calling FlushGalley from TransferClose"); + FlushGalley(root_galley); + } + debug0(DGT, D, "] TransferClose returning."); +} |