aboutsummaryrefslogtreecommitdiffstats
path: root/z21.c
diff options
context:
space:
mode:
authorJeffrey H. Kingston <jeff@it.usyd.edu.au>2010-09-14 19:21:41 +0000
committerJeffrey H. Kingston <jeff@it.usyd.edu.au>2010-09-14 19:21:41 +0000
commit71bdb35d52747e6d7d9f55df4524d57c2966be94 (patch)
tree480ee5eefccc40d5f3331cc52d66f722fd19bfb9 /z21.c
parentb41263ea7578fa9742486135c762803b52794105 (diff)
downloadlout-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 'z21.c')
-rw-r--r--z21.c508
1 files changed, 508 insertions, 0 deletions
diff --git a/z21.c b/z21.c
new file mode 100644
index 0000000..f0b38b8
--- /dev/null
+++ b/z21.c
@@ -0,0 +1,508 @@
+/*@z21.c:Galley Maker:SizeGalley()@*******************************************/
+/* */
+/* 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: z21.c */
+/* MODULE: Galley Maker */
+/* EXTERNS: SizeGalley() */
+/* */
+/*****************************************************************************/
+#include "externs.h"
+
+/*****************************************************************************/
+/* */
+/* SizeGalley(hd, env, rows, joined, nonblock, trig, style, c, target, */
+/* dest_index, recs, inners, enclose) */
+/* */
+/* Convert unsized galley hd into sized format. The input parameters are: */
+/* */
+/* hd the galley to be converted */
+/* env its environment (needs to be "held" while manifesting) */
+/* rows TRUE if the resulting galley may have more than one row */
+/* joined TRUE if the resulting galley must be simply joined */
+/* nonblock Set the non_blocking() field of RECEPTIVEs to this value */
+/* trig TRUE if indefinites of hd may trigger external galleys */
+/* *style The initial style */
+/* *c the width constraint hd should conform to */
+/* target if non-nilobj, expand indefinite objects to reveal a */
+/* @Galley within this symbol */
+/* enclose If non-nilobj, enclose any @Galley symbol encountered */
+/* during manifesting by this symbol. */
+/* */
+/* The output parameters, in addition to the converted hd, are: */
+/* */
+/* dest_index the index of the @Galley found within target, if any */
+/* recs list of all RECURSIVE indexes found (or nilobj if none) */
+/* inners list of all UNATTACHED indexes found (or nilobj if none), */
+/* not including any that come after the target or InputSym. */
+/* */
+/*****************************************************************************/
+
+void SizeGalley(OBJECT hd, OBJECT env, BOOLEAN rows, BOOLEAN joined,
+BOOLEAN nonblock, BOOLEAN trig, STYLE *style, CONSTRAINT *c, OBJECT target,
+OBJECT *dest_index, OBJECT *recs, OBJECT *inners, OBJECT enclose)
+{ OBJECT y, link, z, crs, t, tlink, zlink, tmp, why;
+ OBJECT extras, tmp1, tmp2, bt[2], ft[2], hold_env;
+ BOOLEAN after_target;
+
+ assert( type(hd) == HEAD && Down(hd) != hd, "SizeGalley: precondition!" );
+ assert( !sized(hd), "SizeGalley: already sized!" );
+ debug6(DGM, D, "SizeGalley(%s, -, %s, %s, %s, %s, -, %s, -, -, -), hd =",
+ SymName(actual(hd)), bool(rows), bool(joined), bool(nonblock),
+ bool(trig), EchoConstraint(c));
+ debug1(DGM, DD, " env = %s", EchoObject(env));
+ ifdebug(DGM, D, DebugObject(hd));
+
+ /* manifest the child of hd, making sure it is simply joined if required */
+ Child(y, Down(hd));
+ tmp1 = target;
+ tmp2 = enclose;
+ crs = nilobj;
+ bt[COLM] = ft[COLM] = bt[ROWM] = ft[ROWM] = nilobj;
+ New(hold_env, ACAT); Link(hold_env, env);
+ if( AllowCrossDb && type(y) == CLOSURE && has_optimize(actual(y))
+ && FindOptimize(y, env) )
+ {
+ SetOptimize(hd, style);
+ }
+ debug0(DOM, D, " [ calling Manifest from SizeGalley");
+ if( joined )
+ { New(bt[COLM], THREAD); New(ft[COLM], THREAD);
+ debug0(DGM, DD, " SizeGalley calling Manifest (joined)");
+ y = Manifest(y, env, style, bt, ft, &tmp1, &crs, TRUE, must_expand(hd),
+ &tmp2, FALSE);
+ assert( Down(bt[COLM]) != bt[COLM] && Down(ft[COLM]) != ft[COLM],
+ "SizeGalley: threads!" );
+ Child(tmp1, Down(bt[COLM])); Child(tmp2, Down(ft[COLM]));
+ if( Down(bt[COLM]) != LastDown(bt[COLM]) ||
+ Down(ft[COLM]) != LastDown(ft[COLM]) || tmp1 != tmp2 )
+ Error(21, 1, "galley %s must have just one column mark",
+ FATAL, &fpos(y), SymName(actual(hd)) );
+ DisposeObject(bt[COLM]); DisposeObject(ft[COLM]);
+ }
+ else
+ { debug0(DGM, DD, " SizeGalley calling Manifest (not joined)");
+ y = Manifest(y, env, style, bt, ft, &tmp1, &crs, TRUE, must_expand(hd),
+ &tmp2, FALSE);
+ }
+ debug0(DOM, D, " ] returning from Manifest in SizeGalley");
+ DisposeObject(hold_env);
+ debug0(DGM, DD, "SizeGalley: after manifesting, hd =");
+ ifdebug(DGM, DD, DebugObject(hd));
+
+ /* horizontally size hd */
+ debug0(DGM, DD, "SizeGalley horizontally sizing hd:");
+ New(extras, ACAT);
+ y = MinSize(y, COLM, &extras);
+
+ /* break hd if vertical galley */
+ if( gall_dir(hd) == ROWM )
+ {
+ CopyConstraint(constraint(hd), *c);
+ debug0(DOB, DD, " calling BreakObject from SizeGalley");
+ debug0(DGM, DD, " SizeGalley calling BreakObject:");
+ y = BreakObject(y, c);
+ if( !FitsConstraint(back(y, COLM), fwd(y, COLM), *c) )
+ Error(21, 13, "%s,%s object too wide for available space",
+ FATAL, &fpos(y), EchoLength(back(y, COLM)), EchoLength(fwd(y, COLM)));
+ back(hd, COLM) = back(y, COLM);
+ fwd(hd, COLM) = fwd(y, COLM);
+ assert( FitsConstraint(back(hd, COLM), fwd(hd, COLM), *c),
+ "SizeGalley: BreakObject failed to fit!" );
+ debug2(DSF, DD, "MinSize(hd, COLM) = %s,%s",
+ EchoLength(back(hd, COLM)), EchoLength(fwd(hd, COLM)) );
+ }
+
+ /* hyphenate hd if horizontal optimal galley says so */
+ else if( opt_components(hd) != nilobj && opt_hyph(hd) && type(y) == ACAT )
+ { debug0(DOG, D, " SizeGalley calling Hyphenate()");
+ y = Hyphenate(y);
+ }
+
+ /* get the rows of hd to the top level, if required */
+ seen_nojoin(hd) = FALSE;
+ if( rows )
+ { /* OBJECT prev_gap = nilobj; */
+ debug0(DGM, DD, "SizeGalley cleaning up rows of hd:");
+ for( link = hd; NextDown(link) != hd; link = NextDown(link) )
+ { Child(y, NextDown(link));
+ debug2(DGM, DD, " cleaning %s: %s", Image(type(y)), EchoObject(y));
+ switch( type(y) )
+ {
+ case GAP_OBJ:
+
+ /* prev_gap = y; */
+ if( !join(gap(y)) ) seen_nojoin(hd) = TRUE;
+ break;
+
+
+ case VCAT:
+
+ if( gall_dir(hd) == ROWM )
+ { TransferLinks(Down(y), y, Up(y));
+ DisposeChild(Up(y));
+ link = PrevDown(link);
+ }
+ break;
+
+
+ case ACAT:
+
+ if( gall_dir(hd) == COLM )
+ { TransferLinks(Down(y), y, Up(y));
+ DisposeChild(Up(y));
+ link = PrevDown(link);
+ }
+ break;
+
+
+ case SPLIT:
+
+ assert(Up(y)==LastUp(y), "SizeGalley COL_THR: Up(y)!=LastUp(y)!");
+ Child(z, DownDim(y, ROWM));
+ if( is_indefinite(type(z)) )
+ {
+ debug1(DGT, D, "SizeGalley setting external_ver(%s) to TRUE (a)",
+ EchoObject(z));
+ external_ver(z) = TRUE;
+ }
+ else if( type(z) == VCAT )
+ { OBJECT hor, thor, clink, dlink;
+ Child(hor, DownDim(y, COLM));
+ assert( type(hor) == COL_THR, "SizeGalley: missing COL_THR!" );
+ Parent(thor, UpDim(z, COLM));
+ assert( hor == thor, "SizeGalley/SPLIT: hor != thor!" );
+ clink = DownDim(y, COLM);
+ dlink = UpDim(z, COLM);
+ for( tlink = LastDown(z); tlink != z; tlink = PrevDown(tlink) )
+ { Child(t, tlink);
+ if( type(t) == GAP_OBJ )
+ { Link(NextDown(link), t);
+ }
+ else
+ { New(tmp, SPLIT);
+ back(tmp, COLM) = back(hor, COLM);
+ fwd(tmp, COLM) = fwd(hor, COLM);
+ Link(NextDown(link), tmp);
+ Link(tmp, NextUp(clink));
+ Link(NextDown(dlink), t);
+ Link(tmp, t);
+ }
+ }
+ DeleteLink(dlink);
+ assert(Up(y)==LastUp(y), "SizeGalley COL_THR: Up(y) != LastUp(y)!");
+ DisposeChild(Up(y));
+ link = PrevDown(link);
+ }
+ break;
+
+
+ case CLOSURE:
+ case HEAD:
+
+ if( gall_dir(hd) == COLM )
+ external_hor(y) = TRUE;
+ else
+ {
+ debug1(DGT, D, "SizeGalley setting external_ver(%s) to TRUE (b)",
+ EchoObject(y));
+ external_ver(y) = TRUE;
+ }
+ break;
+
+
+ default:
+
+ break;
+ }
+ }
+ }
+
+ /* determine a scale factor for {} @Scale objects */
+ /* NB AdjustSize cannot be done correctly until after seen_nojoin is set */
+ for( link = Down(extras); link != extras; link = NextDown(link) )
+ { Child(y, link);
+ if( type(y) == SCALE_IND )
+ {
+ /* check that all is in order */
+ CONSTRAINT zc; OBJECT t; FULL_LENGTH b, f;
+ z = actual(y);
+ assert( type(z) == SCALE, "SizeObject: type(z) != SCALE!" );
+ assert( bc(constraint(z)) == 0, "SizeObject: bc(constraint(z)) != 0" );
+ assert( Down(z) != z, "SizeObject SCALE: Down(z) == z!" );
+ Child(t, Down(z));
+
+ /* use @Scale COLM size constraint to determine a suitable scale factor */
+ /* check that @Scale is not in a horizontal galley */
+ if( gall_dir(hd) == COLM )
+ { Error(21, 2, "%s with unspecified scale factor in horizontal galley",
+ FATAL, &fpos(z), KW_SCALE);
+ }
+
+ Constrained(z, &zc, COLM, &why);
+ debug2(DGM, DD, "Constrained(%s, -, COLM) = %s", EchoObject(z),
+ EchoConstraint(&zc));
+ if( !constrained(zc) )
+ { Error(21, 3, "replacing infinite scale factor (unconstrained width) by 1.0",
+ WARN, &fpos(z));
+ bc(constraint(z)) = fc(constraint(z)) = 1 * SF;
+ }
+ else if( size(t, COLM) == 0 )
+ { Error(21, 4, "replacing infinite scale factor (zero width object) by 1.0",
+ WARN, &fpos(z));
+ bc(constraint(z)) = fc(constraint(z)) = 1 * SF;
+ }
+ else if( (float) bfc(zc) / size(t, COLM) > 100.0 )
+ { Error(21, 5, "replacing very large scale factor (over 100) by 1.0",
+ WARN, &fpos(z));
+ bc(constraint(z)) = fc(constraint(z)) = 1 * SF;
+ }
+ else if( (float) bfc(zc) / size(t, COLM) < 0.01 )
+ { if( bfc(zc) == 0 )
+ Error(21, 6, "object deleted (scale factor is zero)",
+ WARN, &fpos(z));
+ else
+ Error(21, 7, "object deleted (scale factor is smaller than 0.01)",
+ WARN, &fpos(z));
+ bc(constraint(z)) = fc(constraint(z)) = 1 * SF;
+ tmp = MakeWord(WORD, STR_EMPTY, &fpos(t));
+ back(tmp, COLM) = fwd(tmp, COLM) = 0;
+ back(tmp, ROWM) = fwd(tmp, ROWM) = 0;
+ word_font(tmp) = word_colour(tmp) = word_language(tmp) = 0;
+ word_hyph(tmp) = FALSE;
+ ReplaceNode(tmp, t);
+ DisposeObject(t);
+ t = tmp;
+ }
+ else bc(constraint(z)) = fc(constraint(z)) = (bfc(zc) * SF)/size(t, COLM);
+
+ /* calculate scaled size and adjust */
+ b = (back(t, COLM) * fc(constraint(z))) / SF;
+ f = (fwd(t, COLM) * fc(constraint(z))) / SF;
+ debug3(DGM, DD, "AdjustSize(%s, %s, %s, COLM)", EchoObject(z),
+ EchoLength(b), EchoLength(f));
+ AdjustSize(z, b, f, COLM);
+
+ /* if already vertically sized (because inside @Rotate) adjust that */
+ if( vert_sized(z) )
+ { b = (back(t, ROWM) * fc(constraint(z))) / SF;
+ f = (fwd(t, ROWM) * fc(constraint(z))) / SF;
+ debug4(DGM, DD, "AdjustSize(%s, %s, %s, %s)", EchoObject(z),
+ EchoLength(b), EchoLength(f), dimen(ROWM));
+ AdjustSize(z, b, f, ROWM);
+ }
+ }
+ }
+ DisposeObject(extras);
+
+ /* size the rows of hd and attach indices where needed */
+ debug0(DGM, DD, " SizeGalley calling MinSize(ROWM):");
+ debug0(DGM, DD, "SizeGalley sizing rows of hd =");
+ ifdebug(DGM, DD, DebugObject(hd));
+ *recs = *inners = *dest_index = nilobj;
+ after_target = FALSE;
+ for( link = Down(hd); link != hd; link = NextDown(link) )
+ { Child(y, link);
+
+ if( type(y) == GAP_OBJ || is_index(type(y)) ) continue;
+ debug0(DGM, DDD, " ROWM sizing:");
+ ifdebug(DGM, DDD, DebugObject(y));
+ New(extras, ACAT);
+ y = MinSize(y, ROWM, &extras);
+ debug3(DSF, DD, "MinSize( %s , ROWM ) = %s,%s", EchoObject(y),
+ EchoLength(back(y, ROWM)), EchoLength(fwd(y, ROWM)) );
+ debug0(DGM, DDD, " ROWM result:");
+ ifdebug(DGM, DDD, DebugObject(y));
+
+ /* now attach indexes in front of y */
+ for( zlink = Down(extras); zlink != extras; zlink = NextDown(zlink) )
+ { Child(z, zlink);
+ blocked(z) = FALSE;
+ /* debug1(DCR, DD, " extra: %s", EchoObject(z)); */
+ debug2(DGM, DD, " extra%s: %s",
+ after_target ? " after_target" : "", EchoObject(z));
+ switch( type(z) )
+ {
+ case RECEPTIVE:
+
+ /* debug2(DCR, DD, " ... uses_ext = %s, trig = %s",
+ bool(uses_extern_target(actual(actual(z)))), bool(trig)); */
+ trigger_externs(z) = uses_extern_target(actual(actual(z))) && trig;
+ non_blocking(z) = nonblock;
+ if( actual(actual(z)) == GalleySym || actual(actual(z)) == ForceGalleySym )
+ *dest_index = z;
+ if( actual(actual(z)) == GalleySym || actual(actual(z)) == ForceGalleySym
+ || actual(actual(z)) == InputSym )
+ after_target = TRUE;
+ break;
+
+
+ case RECURSIVE:
+
+ if( *recs == nilobj ) New(*recs, ACAT);
+ Link(*recs, z);
+ break;
+
+
+ case UNATTACHED:
+
+ if( !after_target ) /* *** new semantics *** */
+ { if( *inners == nilobj ) New(*inners, ACAT);
+ Link(*inners, z);
+ }
+ break;
+
+
+ case SCALE_IND:
+ case EXPAND_IND:
+ case GALL_PREC:
+ case GALL_FOLL:
+ case GALL_FOLL_OR_PREC:
+ case GALL_TARG:
+ case CROSS_PREC:
+ case CROSS_FOLL:
+ case CROSS_FOLL_OR_PREC:
+ case CROSS_TARG:
+ case PAGE_LABEL_IND:
+
+ debug1(DCR, DD, " SizeGalley: %s", EchoObject(z));
+ break;
+
+
+ case COVER_IND:
+
+ /* adjust size of the COVER object, change it to @Scale etc. */
+ { OBJECT cover, prnt, chld; int dirn, thr_type, ok1, ok2, sf,subst, esubst;
+ float sf1, sf2; CONSTRAINT c; FULL_LENGTH b, f;
+ cover = actual(z);
+ if( type(cover) == HCOVER )
+ { dirn = COLM;
+ thr_type = COL_THR;
+ ok1 = VCAT;
+ ok2 = VCAT;
+ subst = HSCALE;
+ esubst = ONE_COL;
+ }
+ else
+ { dirn = ROWM;
+ thr_type = ROW_THR;
+ ok1 = ACAT;
+ ok2 = HCAT;
+ subst = VSCALE;
+ esubst = ONE_ROW;
+ }
+ Parent(prnt, UpDim(cover, dirn));
+ while( type(prnt) == SPLIT || type(prnt) == thr_type )
+ Parent(prnt, UpDim(prnt, dirn));
+ Child(chld, Down(cover));
+ if( type(prnt) != ok1 && type(prnt) != ok2 )
+ {
+ Error(21, 8, "%s replaced by %s (mark not shared)",
+ WARN, &fpos(cover), Image(type(cover)), Image(subst));
+ debug2(DGM, DDD, " cover = %s %s", Image(type(cover)),
+ EchoObject(cover));
+ debug1(DGM, DDD, " prnt = %s:", Image(type(prnt)));
+ ifdebug(DGM, DDD, DebugObject(prnt));
+ type(cover) = subst;
+ }
+ else if( back(chld, dirn) == 0 && fwd(chld, dirn) == 0 )
+ {
+ /* empty object, this is treated as a no-op */
+ type(cover) = esubst;
+ }
+ else if( back(chld, dirn) == 0 || fwd(chld, dirn) == 0 )
+ { Error(21, 9, "%s replaced by %s (infinite scale factor)",
+ WARN, &fpos(cover), Image(type(cover)), Image(subst));
+ type(cover) = subst;
+ }
+ else if( size(prnt, dirn) == 0 )
+ { Error(21, 10, "%s replaced by %s (zero scale factor)",
+ WARN, &fpos(cover), Image(type(cover)), Image(subst));
+ type(cover) = subst;
+ }
+ else /* sensible scale factor exists */
+ {
+ /* work out proposed scale factor and sizes for cover */
+ sf1 = (float) back(prnt, dirn) / back(chld, dirn);
+ sf2 = (float) fwd(prnt, dirn) / fwd(chld, dirn);
+ sf = find_max(sf1, sf2) * SF;
+ b = (back(chld, dirn) * sf) / SF;
+ f = (fwd(chld, dirn) * sf) / SF;
+
+ /* check whether new object fits */
+ Constrained(cover, &c, dirn, &why);
+ if( FitsConstraint(b, f, c) )
+ {
+ /* it fits, so make cover a SCALE object with this size */
+ type(cover) = SCALE;
+ if( dirn == COLM )
+ { bc(constraint(cover)) = sf;
+ fc(constraint(cover)) = SF;
+ }
+ else
+ { bc(constraint(cover)) = SF;
+ fc(constraint(cover)) = sf;
+ }
+ AdjustSize(cover, b, f, dirn);
+ }
+ else
+ { Error(21, 11, "%s replaced by %s (insufficient space)",
+ WARN, &fpos(cover), Image(type(cover)), Image(subst));
+ type(cover) = subst;
+ }
+ }
+ }
+ break;
+
+
+ default:
+
+ assert1(FALSE, "SizeGalley:", Image(type(z)));
+ break;
+
+ }
+ }
+ TransferLinks(Down(extras), extras, link);
+ assert( Down(extras) == extras && Up(extras) == extras, "SizeG: extras!");
+ Dispose(extras);
+ }
+
+ /* insinuate cross references */
+ if( crs != nilobj )
+ {
+ debug1(DCR, DD, "SizeGalley insinuating %s", EchoObject(crs));
+ TransferLinks(Down(crs), crs, Down(hd));
+ DisposeObject(crs);
+ }
+
+ /* check that *dest_index was found if it was required, and exit */
+ if( target != nilobj && *dest_index == nilobj )
+ Error(21, 12, "unexpected absence of %s from the body of %s",
+ FATAL, &fpos(hd), SymName(target), SymName(actual(hd)));
+ debug3(DGM, D, "SizeGalley returning %s,%s %s; hd =",
+ EchoLength(back(hd, COLM)), EchoLength(fwd(hd, COLM)),
+ EchoConstraint(&constraint(hd)));
+ ifdebug(DGM, D, DebugGalley(hd, nilobj, 4));
+ sized(hd) = TRUE;
+
+} /* end SizeGalley */