aboutsummaryrefslogtreecommitdiffstats
path: root/z23.c
diff options
context:
space:
mode:
Diffstat (limited to 'z23.c')
-rw-r--r--z23.c1237
1 files changed, 1237 insertions, 0 deletions
diff --git a/z23.c b/z23.c
new file mode 100644
index 0000000..9b2a4d2
--- /dev/null
+++ b/z23.c
@@ -0,0 +1,1237 @@
+/*@z23.c:Galley Printer:ScaleFactor()@****************************************/
+/* */
+/* 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: z23.c */
+/* MODULE: Galley Printer */
+/* EXTERNS: FixAndPrintObject() */
+/* */
+/*****************************************************************************/
+#include "externs.h"
+#define NO_SUPPRESS FALSE
+#define SUPPRESS TRUE
+#define word_equal(x, str) (is_word(type(x)) && StringEqual(string(x), str))
+
+
+/*****************************************************************************/
+/* */
+/* static float ScaleFactor(avail_size, inner_size) */
+/* */
+/* Return the scale factor for this scaling, or 0 if impossible. */
+/* */
+/*****************************************************************************/
+
+static float ScaleFactor(FULL_LENGTH avail_size, FULL_LENGTH inner_size)
+{ float scale_factor;
+ scale_factor = avail_size <= 0 ? 0 :
+ inner_size <= 0 ? 0 : (float) avail_size / inner_size;
+ return scale_factor;
+}
+
+
+/*@::FindAdjustIncrement()@***************************************************/
+/* */
+/* static FULL_LENGTH FindAdjustIncrement(x, frame_size, dim) */
+/* */
+/* Find the amount by which to increase the width of the subobjects of */
+/* concatenation object x so that it is adjusted to fill size frame_size. */
+/* */
+/*****************************************************************************/
+
+static FULL_LENGTH FindAdjustIncrement(OBJECT x, FULL_LENGTH frame_size,int dim)
+{ OBJECT y, link, prev, g;
+ int adjustable_gaps; BOOLEAN jn;
+ FULL_LENGTH inc, mk, actual_size;
+
+ debug2(DGP, DD, "FindAdjustIncrement(x, %s, %s)",
+ EchoLength(frame_size), dimen(dim));
+ FirstDefinite(x, link, prev, jn);
+ if( link != x )
+ { adjustable_gaps = 0;
+ mk = back(prev, dim);
+ NextDefiniteWithGap(x, link, y, g, jn);
+ while( link != x )
+ { if ( mode(gap(g)) == TAB_MODE || units(gap(g)) == AVAIL_UNIT
+ || units(gap(g)) == FRAME_UNIT )
+ { debug0(DGP, DD, "FindAdjustIncrement returning 0 (tab gap)");
+ return 0;
+ }
+ mk += ActualGap(fwd(prev, dim), back(y, dim), fwd(y, dim), &gap(g),
+ frame_size, mk);
+ prev = y;
+ adjustable_gaps++;
+ NextDefiniteWithGap(x, link, y, g, jn);
+ }
+ actual_size = mk + fwd(prev, dim);
+ debug2(DGP, DD, " actual_size = %s, adjustable_gaps = %d",
+ EchoLength(actual_size), adjustable_gaps);
+ inc = adjustable_gaps==0 ? 0 : (frame_size - actual_size) / adjustable_gaps;
+ }
+ else inc = 0;
+ debug1(DGP, DD, "FindAdjustIncrement returning %s", EchoLength(inc));
+ return inc;
+} /* end FindAdjustIncrement */
+
+
+/*@::FixAndPrintObject()@*****************************************************/
+/* */
+/* FixAndPrintObject(x, xmk, xb, xf, dim, suppress, pg, count) */
+/* */
+/* Fix the absolute position of object x in dimension dim, in such a way */
+/* that the principal mark of x has coordinate xmk, and x has actual size */
+/* (xb, xf), where xb >= back(x, dim) and xf >= fwd(x, dim). */
+/* */
+/* Actually, in the case where x includes an object lying on a thread */
+/* leading outside x, the final size of x may be different. Because */
+/* of this, the procedure sets back(x, dim) and fwd(x, dim) to the actual */
+/* size of x upon return. The caller assumes that x will exactly occupy */
+/* this space back(x, dim), fwd(x, dim). */
+/* */
+/* The suppress parameter is true if a temporary suppression of adjustment */
+/* in this direction is in effect (because a neighbouring adjustment has */
+/* already been done). This is for @HAdjust and @VAdjust, not @PAdjust. */
+/* */
+/* If dim == COLM, the coordinate information is merely stored; but if */
+/* dim == ROWM, it is used to generate PostScript for printing x. */
+/* */
+/* Parameter pg records the height of the current page. This is used */
+/* to correct for the fact that Lout places its origin at the top left, */
+/* while PostScript places its origin at the bottom left. This correction */
+/* cannot be made by transforming user space. */
+/* */
+/* x is child number count of its parent (used by COL_THR and ROW_THR only) */
+/* */
+/*****************************************************************************/
+
+void FixAndPrintObject(OBJECT x, FULL_LENGTH xmk, FULL_LENGTH xb,
+ FULL_LENGTH xf, int dim, BOOLEAN suppress, FULL_LENGTH pg, int count)
+{ OBJECT y, link, prev, g, uplink, z, face, thr;
+ FULL_LENGTH mk, ymk, frame_size, back_edge, yb, yf, inc, f;
+ int i; float scale_factor; BOOLEAN jn;
+ debug7(DGP, DD, "[ FixAndPrintObject(%s %s, %s, %s,%s, %s, %s, pg )",
+ Image(type(x)),
+ ((type(x) == WORD || type(x) == QWORD) ? string(x) : STR_EMPTY),
+ EchoLength(xmk), EchoLength(xb), EchoLength(xf),dimen(dim),
+ (suppress == SUPPRESS ? "suppress" : "no_suppress"));
+ debug2(DGP, DD, " size(x) = %s,%s; x =",
+ EchoLength(back(x, dim)), EchoLength(fwd(x, dim)));
+ ifdebug(DGP, DD, DebugObject(x));
+
+ /*** start and stop debugging
+ if( dim == COLM && is_word(type(x)) &&
+ StringEqual(string(x), AsciiToFull("STARTBUG")) )
+ dbg[DGP].on[DD] = dbg[DGP].on[D] = TRUE;
+ if( dim == COLM && is_word(type(x)) &&
+ StringEqual(string(x), AsciiToFull("STOPBUG")) )
+ dbg[DGP].on[DD] = dbg[DGP].on[D] = FALSE;
+ *** */
+
+
+ switch( type(x) )
+ {
+
+ case CLOSURE:
+ case NULL_CLOS:
+ case PAGE_LABEL:
+ case CROSS:
+ case FORCE_CROSS:
+
+ back(x, dim) = xb; fwd(x, dim) = xf;
+ break;
+
+
+ case START_HVSPAN:
+ case START_HSPAN:
+ case START_VSPAN:
+
+ CountChild(y, DownDim(x, dim), count);
+ if( type(y) == HSPANNER || type(y) == VSPANNER )
+ {
+ Child(z, Down(y));
+ Parent(thr, UpDim(x, dim));
+ debug7(DGP, DD, " calling SPAN %s(xmk %s, x %s,%s, cons %s, z %s,%s)",
+ dimen(dim), EchoLength(xmk),
+ EchoLength(back(x, dim)), EchoLength(fwd(x, dim)),
+ EchoConstraint(&constraint(y)),
+ EchoLength(back(z, dim)), EchoLength(fwd(z, dim)));
+ /* ***
+ f = find_max(xf, fwd(z,dim));
+ FixAndPrintObject(z, xmk - back(thr, dim) + back(z, dim), back(z, dim),
+ find_max(f, bfc(constraint(y)) - back(z, dim)),
+ dim, FALSE, pg, 1);
+ *** */
+ debug5(DGP, DD, " calling FAPO from %s (y = %s, bfc = %s, z = %s,%s",
+ Image(type(x)), Image(type(y)), EchoLength(bfc(constraint(y))),
+ EchoLength(back(z, dim)), EchoLength(fwd(z, dim)));
+ /* ***
+ FixAndPrintObject(z, xmk - back(thr, dim) + back(z, dim), back(z, dim),
+ bfc(constraint(y)) - back(z, dim), dim, FALSE, pg, 1);
+ *** */
+ FixAndPrintObject(z, xmk - back(thr, dim) + back(z, dim), back(z, dim),
+ find_max(fwd(z, dim), bfc(constraint(y)) - back(z, dim)),
+ dim, FALSE, pg, 1);
+ }
+ else
+ {
+ FixAndPrintObject(y, xmk, xb, xf, dim, suppress, pg, count);
+ back(x, dim) = back(y, dim); fwd(x, dim) = fwd(y, dim);
+ }
+ break;
+
+
+ case HSPAN:
+ case VSPAN:
+
+ /* nothing to print, spanner beneath is already done */
+ break;
+
+
+ case WORD:
+ case QWORD:
+
+ if( dim == COLM )
+ {
+ /* save horizontal position for PrintWord below */
+ word_save_mark(x) = xmk;
+
+ /* if first occurrence of this font on this page, notify font */
+ if( string(x)[0] != '\0' )
+ { face = finfo[word_font(x)].original_font;
+ if( font_page(face) < font_curr_page )
+ { debug3(DFT, DD, "FAPO: x = %s, word_font = %d, face = %s",
+ string(x), word_font(x), EchoObject(face));
+ FontPageUsed(face);
+ }
+ }
+ }
+ else
+ {
+ debug4(DGP, D, /* underline(x) == UNDER_UNDEF, */
+ " FAPO %s %s %s (underline = %s)", EchoFilePos(&fpos(x)),
+ Image(type(x)),
+ string(x), underline(x) == UNDER_OFF ? "UNDER_OFF" :
+ underline(x) == UNDER_ON ? "UNDER_ON" : "UNDER_UNDEF");
+ assert( underline(x) == UNDER_OFF || underline(x) == UNDER_ON,
+ "FixAndPrintObject: underline(x)!" );
+ if( string(x)[0] != '\0' )
+ { PrintWord(x, word_save_mark(x), pg - xmk);
+ if( underline(x) == UNDER_ON )
+ {
+ FontWordSize(x); /* to restore fwd(x, COLM) */
+ PrintUnderline(word_font(x), word_save_mark(x),
+ word_save_mark(x) + fwd(x, COLM), pg - xmk);
+ }
+ }
+ }
+ back(x, dim) = xb; fwd(x, dim) = xf;
+ break;
+
+
+ case WIDE:
+ case HIGH:
+
+ CountChild(y, Down(x), count);
+ if( (dim == COLM) == (type(x) == WIDE) )
+ { yf = bfc(constraint(x)) - back(y, dim);
+ FixAndPrintObject(y, xmk, back(y,dim), yf, dim, NO_SUPPRESS, pg,count);
+ back(x, dim) = xb; fwd(x, dim) = xf;
+ }
+ else
+ { FixAndPrintObject(y, xmk, xb, xf, dim, suppress, pg, count);
+ back(x, dim) = back(y, dim); fwd(x, dim) = fwd(y, dim);
+ }
+ break;
+
+
+ case HSHIFT:
+ case VSHIFT:
+
+ CountChild(y, Down(x), count);
+ if( (dim == COLM) == (type(x) == HSHIFT) )
+ {
+ /* work out the size of the shift depending on the units */
+ f = FindShift(x, y, dim);
+ ymk = xmk - f;
+ yb = find_max(0, xb - f);
+ yf = find_max(0, xf + f);
+ FixAndPrintObject(y, ymk, yb, yf, dim, suppress, pg, count);
+
+ /* recalculate the size of x as in MinSize */
+ f = FindShift(x, y, dim);
+ back(x, dim) = find_min(MAX_FULL_LENGTH, find_max(0, back(y, dim) + f));
+ fwd(x, dim) = find_min(MAX_FULL_LENGTH, find_max(0, fwd(y, dim) - f));
+ }
+ else
+ { FixAndPrintObject(y, xmk, xb, xf, dim, suppress, pg, count);
+ back(x, dim) = back(y, dim); fwd(x, dim) = fwd(y, dim);
+ }
+ break;
+
+
+ case HCONTRACT:
+ case VCONTRACT:
+
+ CountChild(y, Down(x), count);
+ if( (dim == COLM) == (type(x) == HCONTRACT) )
+ { FixAndPrintObject(y, xmk, back(y,dim), fwd(y,dim), dim,
+ NO_SUPPRESS, pg, count);
+ back(x, dim) = xb; fwd(x, dim) = xf;
+ }
+ else
+ { FixAndPrintObject(y, xmk, xb, xf, dim, suppress, pg, count);
+ back(x, dim) = back(y, dim); fwd(x, dim) = fwd(y, dim);
+ }
+ break;
+
+
+ case ONE_COL:
+ case ONE_ROW:
+ case HLIMITED:
+ case VLIMITED:
+ case HEXPAND:
+ case VEXPAND:
+
+ CountChild(y, Down(x), count);
+ if( (dim == COLM) == (type(x) == ONE_COL || type(x) == HEXPAND) )
+ { FixAndPrintObject(y, xmk, xb, xf, dim, NO_SUPPRESS, pg, count);
+ back(x, dim) = xb; fwd(x, dim) = xf;
+ }
+ else
+ { FixAndPrintObject(y, xmk, xb, xf, dim, suppress, pg, count);
+ back(x, dim) = back(y, dim); fwd(x, dim) = fwd(y, dim);
+ }
+ break;
+
+
+ case VSCALE:
+
+ debug0(DRS, DD, "FixAndPrintObject at VSCALE");
+ CountChild(y, Down(x), count);
+ switch( BackEnd )
+ {
+ case PLAINTEXT:
+
+ break;
+
+
+ case POSTSCRIPT:
+ case PDF:
+
+ if( dim == COLM )
+ FixAndPrintObject(y, xmk, xb, xf, dim, NO_SUPPRESS, pg, count);
+ else if( (scale_factor = ScaleFactor(xb+xf, size(y, ROWM))) > 0 )
+ { SaveGraphicState(y);
+ CoordTranslate(0, pg-(xmk-xb+(FULL_LENGTH) (back(y,ROWM)*scale_factor)));
+ CoordScale(1.0, scale_factor);
+ FixAndPrintObject(y, 0, back(y,ROWM), fwd(y,ROWM), dim,
+ NO_SUPPRESS, 0, count);
+ RestoreGraphicState();
+ }
+ else if( !is_word(type(y)) || string(y)[0] != '\0' )
+ Error(23, 1, "object deleted (it cannot be scaled vertically)",
+ WARN, &fpos(x));
+ break;
+ }
+ back(x, dim) = xb; fwd(x, dim) = xf;
+ break;
+
+
+ case HSCALE:
+
+ debug0(DRS, DD, "FixAndPrintObject at HSCALE");
+ CountChild(y, Down(x), count);
+ switch( BackEnd )
+ {
+ case PLAINTEXT:
+
+ break;
+
+
+ case POSTSCRIPT:
+ case PDF:
+
+ if( dim == COLM )
+ { save_mark(x) = xmk;
+ bc(constraint(x)) = xb;
+ fc(constraint(x)) = xf;
+ if( (scale_factor = ScaleFactor(xb+xf, size(y, COLM))) > 0 )
+ FixAndPrintObject(y, 0, back(y, COLM), fwd(y, COLM), dim,
+ NO_SUPPRESS, pg, count);
+ else if( !is_word(type(y)) || string(y)[0] != '\0' )
+ Error(23, 2, "object deleted (it cannot be scaled horizontally)",
+ WARN, &fpos(y));
+ }
+ else if( (scale_factor =
+ ScaleFactor(bc(constraint(x))+fc(constraint(x)),size(y,COLM))) > 0 )
+ { SaveGraphicState(y);
+ CoordTranslate(save_mark(x) - bc(constraint(x))
+ + (FULL_LENGTH) (back(y, COLM)*scale_factor), 0);
+ CoordScale(scale_factor, 1.0);
+ FixAndPrintObject(y, xmk, xb, xf, dim, NO_SUPPRESS, pg, count);
+ RestoreGraphicState();
+ }
+ break;
+ }
+ back(x, dim) = xb; fwd(x, dim) = xf;
+ break;
+
+
+ case SCALE:
+
+ CountChild(y, Down(x), count);
+ switch( BackEnd )
+ {
+ case PLAINTEXT:
+
+ /* printable only if scale factor is one */
+ if( bc(constraint(x)) == SF && fc(constraint(x)) == SF )
+ {
+ FixAndPrintObject(y, xmk, xb, xf, dim, suppress, pg, count);
+ }
+ break;
+
+
+ case POSTSCRIPT:
+ case PDF:
+
+ if( dim == COLM )
+ { assert( bc(constraint(x)) > 0, "FAPO: horizontal scale factor!" );
+ save_mark(x) = xmk;
+ yb = xb * SF / bc(constraint(x));
+ yf = xf * SF / bc(constraint(x));
+ FixAndPrintObject(y, 0, yb, yf, dim, NO_SUPPRESS, pg, count);
+ }
+ else
+ { assert( fc(constraint(x)) > 0, "FAPO: vertical scale factor!" );
+ yb = xb * SF / fc(constraint(x));
+ yf = xf * SF / fc(constraint(x));
+ SaveGraphicState(y);
+ CoordTranslate(save_mark(x), pg - xmk);
+ CoordScale( (float) bc(constraint(x))/SF,
+ (float) fc(constraint(x))/SF);
+ FixAndPrintObject(y, 0, yb, yf, dim, NO_SUPPRESS,
+ 0, count);
+ RestoreGraphicState();
+ }
+ break;
+ }
+ back(x, dim) = xb; fwd(x, dim) = xf;
+ break;
+
+
+ case KERN_SHRINK:
+
+ CountChild(y, LastDown(x), count);
+ if( dim == COLM )
+ { FixAndPrintObject(y, xmk, back(y,dim), fwd(y,dim), dim,
+ NO_SUPPRESS, pg, count);
+ }
+ else
+ { FixAndPrintObject(y, xmk, xb, xf, dim, suppress, pg, count);
+ back(x, dim) = back(y, dim); fwd(x, dim) = fwd(y, dim);
+ }
+ break;
+
+
+ case BACKGROUND:
+
+ /* this object has the size of its second child; but its first */
+ /* child gets printed too, in the same space */
+ CountChild(y, Down(x), count);
+ FixAndPrintObject(y, xmk, xb, xf, dim, suppress, pg, count);
+ CountChild(y, LastDown(x), count);
+ FixAndPrintObject(y, xmk, xb, xf, dim, suppress, pg, count);
+ break;
+
+
+ case ROTATE:
+
+ CountChild(y, Down(x), count);
+ switch( BackEnd )
+ {
+ case PLAINTEXT:
+
+ /* printable only if angle is zero */
+ if( sparec(constraint(x)) == 0 )
+ {
+ FixAndPrintObject(y, xmk, xb, xf, dim, suppress, pg, count);
+ }
+ break;
+
+
+ case POSTSCRIPT:
+ case PDF:
+
+ if( dim == COLM )
+ { CONSTRAINT colc, rowc, yc;
+ save_mark(x) = xmk;
+ SetConstraint(colc, back(x,COLM), MAX_FULL_LENGTH, fwd(x,COLM));
+ SetConstraint(rowc, back(x,ROWM), MAX_FULL_LENGTH, fwd(x,ROWM));
+ RotateConstraint(&yc, y, sparec(constraint(x)), &colc, &rowc,COLM);
+ FixAndPrintObject(y, 0, bc(yc), fc(yc), COLM,NO_SUPPRESS,pg,count);
+ }
+ else
+ { CONSTRAINT colc, rowc, yc;
+ SaveGraphicState(y);
+ CoordTranslate(save_mark(x), pg - xmk);
+ CoordRotate(sparec(constraint(x)));
+ SetConstraint(colc, back(x,COLM), MAX_FULL_LENGTH, fwd(x,COLM));
+ SetConstraint(rowc, back(x,ROWM), MAX_FULL_LENGTH, fwd(x,ROWM));
+ RotateConstraint(&yc, y, sparec(constraint(x)), &colc, &rowc, ROWM);
+ FixAndPrintObject(y, 0, bc(yc), fc(yc), ROWM, NO_SUPPRESS,0,count);
+ RestoreGraphicState();
+ }
+ break;
+ }
+ back(x, dim) = xb; fwd(x, dim) = xf;
+ break;
+
+
+ case PLAIN_GRAPHIC:
+
+ CountChild(y, LastDown(x), count);
+ switch( BackEnd )
+ {
+
+ case POSTSCRIPT:
+ case PDF:
+
+ FixAndPrintObject(y, xmk, xb, xf, dim, suppress, pg, count);
+ break;
+
+
+ case PLAINTEXT:
+
+ if( dim == COLM )
+ {
+ back(x, dim) = xb;
+ fwd(x, dim) = xf;
+ save_mark(x) = xmk - back(x, dim);
+ debug2(DGP, DD, "PLAIN_GRAPHIC COLM storing size %s, %s",
+ EchoLength(back(x, dim)), EchoLength(fwd(x, dim)));
+ FixAndPrintObject(y, xmk, xb, xf, dim, suppress, pg, count);
+ }
+ else
+ { OBJECT tmp, pre, post;
+ Child(tmp, Down(x));
+ if( type(tmp) == VCAT )
+ { Child(pre, Down(tmp));
+ Child(post, LastDown(tmp));
+ }
+ else pre = tmp, post = nilobj;
+ back(x, dim) = xb;
+ fwd(x, dim) = xf;
+ PrintPlainGraphicObject(pre, save_mark(x),
+ pg - (xmk - back(x, dim)), x);
+ FixAndPrintObject(y, xmk, xb, xf, dim, suppress, pg, count);
+ if( post != nilobj )
+ PrintPlainGraphicObject(post, save_mark(x),
+ pg - (xmk - back(x, dim)), x);
+ }
+ break;
+
+ } /* end switch */
+ back(x, dim) = xb; fwd(x, dim) = xf;
+ break;
+
+
+ case GRAPHIC:
+
+ CountChild(y, LastDown(x), count);
+ switch( BackEnd )
+ {
+ case PLAINTEXT:
+
+ FixAndPrintObject(y, xmk, xb, xf, dim, suppress, pg, count);
+ break;
+
+
+ case POSTSCRIPT:
+ case PDF:
+
+ if( dim == COLM )
+ {
+ /* if first occurrence of this font on this page, notify font */
+ if( font(save_style(x)) > 0 )
+ { face = finfo[font(save_style(x))].original_font;
+ if( font_page(face) < font_curr_page ) FontPageUsed(face);
+ }
+
+ back(x, dim) = xb;
+ fwd(x, dim) = xf;
+ debug2(DGP, DD, "GRAPHIC COLM storing size %s, %s",
+ EchoLength(back(x, dim)), EchoLength(fwd(x, dim)));
+ save_mark(x) = xmk - back(x, COLM);
+ FixAndPrintObject(y, xb, xb, xf, dim, NO_SUPPRESS, pg, count);
+ }
+ else
+ { OBJECT tmp, pre, post;
+ Child(tmp, Down(x));
+ if( type(tmp) == VCAT )
+ { Child(pre, Down(tmp));
+ Child(post, LastDown(tmp));
+ }
+ else pre = tmp, post = nilobj;
+ back(x, dim) = xb;
+ fwd(x, dim) = xf;
+
+ SaveTranslateDefineSave(x, save_mark(x), pg - (xmk + fwd(x, ROWM)));
+ /* ***
+ SaveGraphicState(x);
+ CoordTranslate(save_mark(x), pg - (xmk + fwd(x, ROWM)));
+ debug4(DGP, DD, "GRAPHIC ROWM calling %s,%s %s,%s",
+ EchoLength(back(x, COLM)), EchoLength(fwd(x, COLM)),
+ EchoLength(back(x, ROWM)), EchoLength(fwd(x, ROWM)));
+ DefineGraphicNames(x);
+ SaveGraphicState(x);
+ *** */
+
+ PrintGraphicObject(pre);
+ RestoreGraphicState();
+ FixAndPrintObject(y, xb, xb, xf, dim, NO_SUPPRESS, xb + xf, count);
+ if( post != nilobj ) PrintGraphicObject(post);
+ RestoreGraphicState();
+ }
+ break;
+
+ } /* end switch */
+ back(x, dim) = xb; fwd(x, dim) = xf;
+ break;
+
+
+ case INCGRAPHIC:
+ case SINCGRAPHIC:
+
+ CountChild(y, Down(x), count);
+ switch( BackEnd )
+ {
+ case PLAINTEXT:
+
+ break;
+
+
+ case POSTSCRIPT:
+ case PDF:
+
+ if( dim == COLM )
+ { save_mark(x) = xmk;
+ if( incgraphic_ok(x) )
+ { debug2(DGP, DD, " %s (style %s)",
+ EchoObject(x), EchoStyle(&save_style(x)));
+ face = finfo[font(save_style(x))].original_font;
+ if( font_page(face) < font_curr_page )
+ { debug3(DFT, DD, "FAPO-IG: x = %s, font = %d, face = %s",
+ string(x), font(save_style(x)), EchoObject(face));
+ FontPageUsed(face);
+ }
+ }
+ }
+ else if( incgraphic_ok(x) )
+ PrintGraphicInclude(x, save_mark(x), pg - xmk);
+ break;
+
+ }
+ back(x, dim) = xb; fwd(x, dim) = xf;
+ break;
+
+
+ case SPLIT:
+
+ link = DownDim(x, dim); CountChild(y, link, count);
+ FixAndPrintObject(y, xmk, xb, xf, dim, suppress, pg, count);
+ back(x, dim) = back(y, dim); fwd(x, dim) = fwd(y, dim);
+ break;
+
+
+ case VCAT:
+ case HCAT:
+
+ if( (type(x) == VCAT) == (dim == ROWM) )
+ {
+ FirstDefinite(x, link, prev, jn);
+ if( link != x )
+ {
+
+ /* handle the special case of a 0rt gap at the beginning (left */
+ /* justify) by converting it to 0ie but increasing fwd(prev) */
+ /* to the max. possible */
+ NextDefiniteWithGap(x, link, y, g, jn);
+ if( link != x && mode(gap(g)) == TAB_MODE &&
+ units(gap(g)) == AVAIL_UNIT && width(gap(g)) == 0 )
+ {
+ debug2(DGP, DD, " FAPO-CAT converting 0rt (back(x, dim) %s, xb %s)",
+ EchoLength(back(x, dim)), EchoLength(xb));
+ fwd(prev, dim) += xb - back(x, dim);
+ back(x, dim) = xb;
+ mode(gap(g)) = EDGE_MODE;
+ units(gap(g)) = FIXED_UNIT;
+ }
+ FirstDefinite(x, link, prev, jn);
+
+ /* the frame size is the total width actually available */
+ frame_size = back(x, dim) + xf;
+
+ /* back_edge is where the first element begins */
+ back_edge = xmk - back(x, dim);
+
+ /* inc is the adjust increment, used when adjusting gaps */
+ if( adjust_cat(x) && !suppress )
+ inc = FindAdjustIncrement(x, frame_size, dim);
+ else inc = 0;
+
+ debug6(DGP, DD, "[ FAPO-CAT %s (%s,%s): xmk %s, xb %s, xf %s",
+ Image(type(x)), EchoLength(back(x, dim)), EchoLength(fwd(x, dim)),
+ EchoLength(xmk), EchoLength(xb), EchoLength(xf));
+
+ mk = back_edge + back(prev, dim);
+ debug4(DGP, DD, " FAPO-CAT back_edge %s, mk %s, framesize %s, inc %s",
+ EchoLength(back_edge), EchoLength(mk), EchoLength(frame_size),
+ EchoLength(inc));
+
+ NextDefiniteWithGap(x, link, y, g, jn);
+
+ while( link != x )
+ {
+ if( mode(gap(g)) == TAB_MODE && units(gap(g)) == AVAIL_UNIT &&
+ width(gap(g))==FR )
+ {
+ /* object is followed by 1rt gap, give it full space to print */
+ debug5(DGP,D," FAPO (a) calling FAPO(%s, %s, %s, max(%s, %s))",
+ Image(type(prev)), EchoLength(mk), EchoLength(back(prev, dim)),
+ EchoLength(fwd(prev, dim)), EchoLength(xmk+xf-mk-size(y,dim)));
+ FixAndPrintObject(prev, mk, back(prev, dim),
+ find_max(fwd(prev, dim), xmk+xf-mk - size(y, dim)),
+ dim, NO_SUPPRESS, pg, count);
+ }
+ else
+ {
+ debug5(DGP, DD, " FAPO-CAT (b) calling FAPO(%s, %s, %s, %s+%s)",
+ Image(type(prev)), EchoLength(mk), EchoLength(back(prev, dim)),
+ EchoLength(fwd(prev, dim)), EchoLength(inc));
+ FixAndPrintObject(prev, mk, back(prev, dim), fwd(prev, dim) + inc,
+ dim, NO_SUPPRESS, pg, count);
+ }
+ /* NB fwd(prev, dim) may be changed by the call to FAPO */
+ mk += ActualGap(fwd(prev, dim), back(y, dim), fwd(y, dim), &gap(g),
+ frame_size, mk - back_edge);
+ prev = y;
+ NextDefiniteWithGap(x, link, y, g, jn);
+ }
+ if( suppress )
+ {
+ debug4(DGP, DD, " FAPO-CAT (c) calling FAPO(%s, %s, %s, %s)",
+ Image(type(prev)), EchoLength(mk), EchoLength(back(prev, dim)),
+ EchoLength(fwd(prev, dim)));
+ FixAndPrintObject(prev, mk, back(prev, dim), fwd(prev, dim),
+ dim, NO_SUPPRESS, pg, count);
+ }
+ else
+ {
+ debug5(DGP, DD," FAPO-CAT (d) calling FAPO(%s, %s, %s, max(%s, %s))",
+ Image(type(prev)), EchoLength(mk), EchoLength(back(prev, dim)),
+ EchoLength(fwd(prev, dim)), EchoLength(xmk + xf - mk));
+ FixAndPrintObject(prev, mk, back(prev,dim),
+ find_max(fwd(prev, dim), xmk + xf - mk),
+ dim, NO_SUPPRESS, pg, count);
+ }
+ back(x, dim) = find_max(back(x, dim), xb);
+ fwd(x, dim) = mk + fwd(prev, dim) - back_edge - back(x, dim);
+ }
+ else back(x, dim) = xb, fwd(x, dim) = xf;
+ debug0(DGP, DD, "] FAPO-CAT returning.");
+ }
+ else
+ { OBJECT start_group, zlink, m; BOOLEAN dble_found;
+ FULL_LENGTH b, f, dlen;
+ start_group = nilobj; dble_found = FALSE; dlen = 0;
+ debug0(DGP, DD, " groups beginning.");
+ FirstDefinite(x, link, y, jn);
+ if( link != x )
+ {
+ /* start first group, with or without join */
+ b = back(y, dim);
+ f = fwd(y, dim);
+ m = y;
+ start_group = link;
+ dble_found = !jn;
+ debug4(DGP, DD, " starting first group %s (%sdbl_found): b = %s, f = %s",
+ Image(type(y)), dble_found ? "" : "not ",
+ EchoLength(b), EchoLength(f));
+
+ NextDefiniteWithGap(x, link, y, g, jn);
+ while( link != x )
+ {
+ if( !jn )
+ {
+ /* finish off and fix the group ending just before g */
+ debug2(DGP, DD, " finishing group: b = %s, f = %s",
+ EchoLength(b), EchoLength(f));
+ FixAndPrintObject(m, xmk+b, b, xf-b, dim,
+ NO_SUPPRESS, pg, count);
+ b = back(m, dim); f = fwd(m, dim);
+ for( zlink = start_group; zlink != link; zlink=NextDown(zlink) )
+ { CountChild(z, zlink, count);
+ if( !is_definite(type(z)) || z == m ) continue;
+ FixAndPrintObject(z, xmk + b, b, xf - b, dim,
+ SUPPRESS, pg, count);
+ b = find_max(b, back(z, dim)); f = find_max(f, fwd(z, dim));
+ }
+ dlen = find_max(dlen, b + f);
+ dble_found = TRUE;
+ start_group = nilobj;
+
+ /* start new group */
+ b = back(y, dim);
+ f = fwd(y, dim);
+ m = y;
+ start_group = link;
+ debug2(DGP, DD, " starting group: b = %s, f = %s",
+ EchoLength(b), EchoLength(f));
+ }
+ else
+ {
+ /* continue with current group */
+ b = find_max(b, back(y, dim));
+ f = find_max(f, fwd(y, dim));
+ if( fwd(y, dim) > fwd(m, dim) ) m = y;
+ debug2(DGP, DD, " continuing group: b = %s, f = %s",
+ EchoLength(b), EchoLength(f));
+ }
+
+ NextDefiniteWithGap(x, link, y, g, jn);
+ }
+ assert( start_group != nilobj, "FAPO: final start_group!" );
+
+ if( dble_found || !jn )
+ {
+ /* finish off and fix this last group */
+ debug2(DGP, DD, " finishing last group: b = %s, f = %s",
+ EchoLength(b), EchoLength(f));
+ FixAndPrintObject(m, xmk+b, b, xf - b, dim, NO_SUPPRESS, pg,count);
+ b = back(m, dim); f = fwd(m, dim);
+ for( zlink = start_group; zlink != x; zlink = NextDown(zlink) )
+ { CountChild(z, zlink, count);
+ if( !is_definite(type(z)) || z == m ) continue;
+ FixAndPrintObject(z, xmk+b, b, xf - b, dim, SUPPRESS, pg, count);
+ b = find_max(b, back(z, dim)); f = find_max(f, fwd(z, dim));
+ }
+ dlen = find_max(dlen, b + f);
+ back(x, dim) = 0; fwd(x, dim) = dlen;
+ }
+ else
+ {
+ /* finish off and fix this last and only group */
+ debug2(DGP, DD, " finishing last and only group: b = %s, f = %s",
+ EchoLength(b), EchoLength(f));
+ FixAndPrintObject(m, xmk, xb, xf, dim, NO_SUPPRESS, pg, count);
+ b = back(m, dim); f = fwd(m, dim);
+ for( zlink = start_group; zlink != x; zlink = NextDown(zlink) )
+ { CountChild(z, zlink, count);
+ if( !is_definite(type(z)) || z == m ) continue;
+ FixAndPrintObject(z, xmk, xb, xf, dim, SUPPRESS, pg, count);
+ b = find_max(b, back(z, dim)); f = find_max(f, fwd(z, dim));
+ }
+ back(x, dim) = b; fwd(x, dim) = f;
+ }
+ }
+ }
+ break;
+
+
+ case ACAT:
+
+ if( dim == COLM )
+ { BOOLEAN will_adjust, adjusting;
+ FULL_LENGTH actual_size,
+ adjust_indent, frame_size, back_edge, adjust_inc, inc, adjust_sofar;
+ int adjustable_gaps, gaps_sofar;
+ BOOLEAN underlining; int underline_xstart; FONT_NUM underline_font;
+ OBJECT urec, last_bad_gap;
+
+
+ /*********************************************************************/
+ /* */
+ /* The first step is to calculate the following values: */
+ /* */
+ /* last_bad_gap The rightmost tab gap, or nilobj if none; */
+ /* */
+ /* adjustable_gaps the number of gaps suitable for adjustment; */
+ /* i.e. to the right of the right-most tab gap, */
+ /* and of non-zero width; */
+ /* */
+ /* actual_size the actual size of x without adjustment. */
+ /* */
+ /* These are needed when adjusting the line. */
+ /* */
+ /*********************************************************************/
+
+ FirstDefinite(x, link, y, jn);
+ if( link == x ) break; /* no definite children, nothing to print */
+
+ /*** nasty bug finder
+ { OBJECT ff = y;
+ debugcond1(DGP, DD, word_equal(ff, "@ReportLayout"),
+ "FAPO(%s, COLM)", EchoObject(x));
+ debugcond1(DGP, DD, word_equal(ff, "@ReportLayout"),
+ " adjust_cat(x) = %s", bool(adjust_cat(x)));
+ }
+ ***/
+
+ last_bad_gap = nilobj;
+ adjustable_gaps = 0;
+ back_edge = xmk - xb;
+ mk = back_edge + back(y, dim);
+ frame_size = xb + xf;
+ prev = y;
+ NextDefiniteWithGap(x, link, y, g, jn);
+ while( link != x )
+ {
+ save_actual_gap(g) = ActualGap(fwd(prev, dim), back(y, dim),
+ fwd(y, dim), &gap(g), frame_size, mk - back_edge);
+ mk += save_actual_gap(g);
+ if( mode(gap(g)) == TAB_MODE || units(gap(g)) == AVAIL_UNIT
+ || units(gap(g)) == FRAME_UNIT )
+ { last_bad_gap = g;
+ adjustable_gaps = 0;
+ }
+ else if( width(gap(g)) > 0 ) adjustable_gaps++;
+ prev = y;
+ NextDefiniteWithGap(x, link, y, g, jn);
+ }
+ actual_size = mk + fwd(prev, dim) - back_edge;
+
+ /*********************************************************************/
+ /* */
+ /* It is possible that the line cannot be displayed in any */
+ /* reasonable way, because the paragraph breaker was forced to */
+ /* produce an overfull line. In this case, actual_size will */
+ /* exceed frame_size and there will be no adjustable gaps. The */
+ /* solution is to horizontally scale the line if possible, or */
+ /* else to not print it at all. */
+ /* */
+ /*********************************************************************/
+
+ if( actual_size > frame_size && adjustable_gaps == 0 )
+ {
+ /* can't be fixed by adjustment, so scale the line or delete it */
+ CONSTRAINT c;
+ SetConstraint(c, 0, frame_size, frame_size);
+ fwd(x, dim) = actual_size;
+ debug2(DGP, DD, " oversize, actual_size = %s, frame_size = %s",
+ EchoLength(actual_size), EchoLength(frame_size));
+ if( BackEnd != PLAINTEXT && InsertScale(x, &c) )
+ {
+ /* the problem has just been fixed, by inserting a @Scale above x */
+ OBJECT prnt;
+ Parent(prnt, Up(x));
+ Child(y, Down(x));
+ if( actual_size - frame_size < 1 * PT )
+ {
+ /* the correction is probably due to roundoff error, and */
+ /* anyway is too small to print an error message about */
+ }
+ else if( Down(x) == LastDown(x) && is_word(type(y)) )
+ {
+ Error(23, 3, "word %s horizontally scaled by factor %.2f (too wide for %s paragraph)",
+ WARN, &fpos(y), string(y), (float) bc(constraint(prnt)) / SF,
+ EchoLength(frame_size));
+ }
+ else
+ {
+ Error(23, 4, "%s object horizontally scaled by factor %.2f (too wide for %s paragraph)",
+ WARN, &fpos(x), EchoLength(size(x, COLM)),
+ (float) bc(constraint(prnt)) / SF, EchoLength(frame_size));
+ }
+ FixAndPrintObject(prnt, xmk, back(prnt, dim), fwd(prnt, dim), dim,
+ NO_SUPPRESS, pg, count);
+ }
+ else
+ {
+ /* fix the problem by refraining from printing the line */
+ if( size(x, COLM) <= 0 )
+ Error(23, 5, "oversize object has size 0 or less", INTERN, &fpos(x));
+ Child(y, Down(x));
+ if( Down(x) == LastDown(x) && is_word(type(y)) )
+ { Error(23, 6, "word %s deleted (too wide for %s paragraph)",
+ WARN, &fpos(y), string(y), EchoLength(frame_size));
+ }
+ else
+ { Error(23, 7, "%s object deleted (too wide for %s paragraph)",
+ WARN, &fpos(x), EchoLength(size(x, COLM)), EchoLength(frame_size));
+ }
+
+ /* delete and dispose every child of x */
+ while( Down(x) != x )
+ DisposeChild(Down(x));
+ y = MakeWord(WORD, STR_EMPTY, &fpos(x));
+ Link(x, y);
+ back(y, COLM) = fwd(y, COLM) = 0;
+ back(y, ROWM) = fwd(y, ROWM) = 0;
+ }
+ }
+ else
+ {
+
+ /*********************************************************************/
+ /* */
+ /* The line may be displayed in one of four ways: centred, right- */
+ /* justified, adjusted, or none of the above (i.e. left justified). */
+ /* An overfull line is always adjusted; otherwise, the line will */
+ /* be centred or right justified if the display style asks for it; */
+ /* otherwise, the line will be adjusted if adjust_cat(x) == TRUE */
+ /* (i.e. there is an enclosing @PAdjust) or if the display style is */
+ /* DO_ADJUST (meaning that this line is one of a paragraph set in */
+ /* the adjust or outdent break style, other than the last line); */
+ /* otherwise, the line is left justified. */
+ /* */
+ /* The second step is to decide which of these four cases holds */
+ /* for this line, and to record the decision in these variables: */
+ /* */
+ /* will_adjust TRUE if the adjusted style applies; in this */
+ /* case, variables adjust_inc and inc will be */
+ /* set to the appropriate adjustment value; */
+ /* */
+ /* adjust_indent If centring or right justification applies, */
+ /* the indent to produce this, else zero. */
+ /* */
+ /* NB adjust_inc may be negative, if the optimal paragraph breaker */
+ /* has chosen to shrink some gaps. */
+ /* */
+ /*********************************************************************/
+
+ if( actual_size > frame_size )
+ {
+ assert( adjustable_gaps > 0, "FAPO: adjustable_gaps!" );
+ adjust_cat(x) = TRUE;
+ adjust_indent = 0;
+ }
+ else switch( display_style(save_style(x)) )
+ {
+ case DO_ADJUST: adjust_cat(x) = TRUE;
+ adjust_indent = 0;
+ break;
+
+ case DISPLAY_CENTRE: adjust_cat(x) = FALSE;
+ adjust_indent = (frame_size - actual_size)/2;
+ debug1(DGP, DD, "cdisp %s", EchoObject(x));
+ break;
+
+ case DISPLAY_RIGHT: adjust_cat(x) = FALSE;
+ adjust_indent = frame_size - actual_size;
+ debug1(DGP, DD, "rdisp %s", EchoObject(x));
+ break;
+
+ default: /* leave adjust_cat(x) as is */
+ adjust_indent = 0;
+ break;
+ }
+
+ debug2(DGP, DD, "ACAT %s %s",
+ EchoStyle(&save_style(x)), EchoObject(x));
+ debug2(DGP, DD, "frame_size = %s, actual_size = %s",
+ EchoLength(frame_size), EchoLength(actual_size));
+
+ if( adjust_cat(x) && adjustable_gaps > 0 )
+ { will_adjust = TRUE;
+ adjust_inc = (frame_size - actual_size) / adjustable_gaps;
+ inc = find_max(adjust_inc, 0);
+ gaps_sofar = 0; /* number of gaps adjusted so far */
+ adjust_sofar = 0; /* total width of adjustments so far */
+ debug2(DGP, DD, "will_adjust: adjustable_gaps = %d, adjust_inc = %s",
+ adjustable_gaps, EchoLength(adjust_inc));
+ }
+ else will_adjust = FALSE;
+
+
+ /*********************************************************************/
+ /* */
+ /* The third and final step is to traverse x, fixing subobjects. */
+ /* Variable adjusting is true while adjusting is occurring. */
+ /* */
+ /*********************************************************************/
+
+ underlining = FALSE;
+ adjusting = will_adjust && last_bad_gap == nilobj;
+ FirstDefinite(x, link, y, jn);
+ prev = y;
+ mk = xmk - back(x, dim) + back(y, dim) + adjust_indent;
+ NextDefiniteWithGap(x, link, y, g, jn);
+ while( link != x )
+ {
+ /* check for underlining */
+ if( underline(prev) == UNDER_ON )
+ {
+ debug3(DGP, DD, " FAPO/ACAT1 underline() := %s for %s %s",
+ bool(FALSE), Image(type(prev)), EchoObject(prev));
+ underline(prev) = UNDER_OFF;
+ if( !underlining )
+ {
+ /* underlining begins here */
+ underlining = TRUE;
+ debug2(DGP, DD, "underlining begins at %s %s",
+ Image(type(prev)), EchoObject(prev));
+ underline_font = is_word(type(prev)) ? word_font(prev) :
+ font(save_style(x));
+ underline_xstart = mk - back(prev, dim);
+ }
+ if( underline(g) == UNDER_OFF )
+ {
+ /* underlining ends here */
+ debug2(DGP, DD, "underlining ends at %s %s",
+ Image(type(prev)), EchoObject(prev));
+ New(urec, UNDER_REC);
+ back(urec, COLM) = underline_xstart;
+ fwd(urec, COLM) = mk + fwd(prev, dim);
+ back(urec, ROWM) = underline_font;
+ underlining = FALSE;
+ Link(Up(prev), urec);
+ }
+ }
+
+ /* fix previous definite now we know it is not the last one */
+ if( adjusting && width(gap(g)) > 0 )
+ { int tmp;
+
+ FixAndPrintObject(prev, mk, back(prev, dim), fwd(prev, dim) + inc,
+ dim, NO_SUPPRESS, pg, count);
+
+ gaps_sofar++;
+ tmp = ((frame_size - actual_size) * gaps_sofar) / adjustable_gaps;
+ mk += save_actual_gap(g) + (tmp - adjust_sofar);
+ adjust_sofar = tmp;
+ }
+ else
+ {
+ FixAndPrintObject(prev, mk, back(prev, dim), fwd(prev, dim),
+ dim, NO_SUPPRESS, pg, count);
+
+ mk += save_actual_gap(g);
+ }
+ prev = y;
+
+ /* commence adjustment if required */
+ if( !adjusting && will_adjust && g == last_bad_gap )
+ adjusting = TRUE;
+
+ NextDefiniteWithGap(x, link, y, g, jn);
+ }
+
+ /* check for underlining */
+ debugcond3(DGP, D, underline(prev) == UNDER_UNDEF,
+ " underlining is UNDER_UNDEF in %s: %s %s in para:",
+ EchoFilePos(&fpos(prev)), Image(type(prev)), EchoObject(prev));
+ debugcond1(DGP, D, underline(prev)==UNDER_UNDEF, "%s", EchoObject(x));
+ assert( underline(prev) == UNDER_OFF || underline(prev) == UNDER_ON,
+ "FixAndPrint: underline(prev)!" );
+ if( underline(prev) == UNDER_ON )
+ {
+ debug3(DGP, DD, " FAPO/ACAT1 underline() := %s for %s %s",
+ bool(FALSE), Image(type(prev)), EchoObject(prev));
+ underline(prev) = UNDER_OFF;
+ if( !underlining )
+ {
+ /* underlining begins here */
+ debug2(DGP, DD, "underlining begins at %s %s",
+ Image(type(prev)), EchoObject(prev));
+ underlining = TRUE;
+ underline_font = is_word(type(prev)) ? word_font(prev) :
+ font(save_style(x));
+ underline_xstart = mk - back(prev, dim);
+ }
+
+ /* underlining must end here */
+ debug2(DGP, DD, "underlining ends at %s %s",
+ Image(type(prev)), EchoObject(prev));
+ New(urec, UNDER_REC);
+ back(urec, COLM) = underline_xstart;
+ fwd(urec, COLM) = mk + fwd(prev, dim);
+ back(urec, ROWM) = underline_font;
+ underlining = FALSE;
+ Link(Up(prev), urec);
+ }
+
+ /* fix the last definite subobject, prev, which must exist */
+ FixAndPrintObject(prev, mk, back(prev, dim),
+ frame_size - (mk - xmk) - back(x, dim),
+ dim, NO_SUPPRESS, pg, count);
+
+ }
+ }
+ else for( link = Down(x); link != x; link = NextDown(link) )
+ { Child(y, link);
+ if( !is_definite(type(y)) )
+ {
+ if( type(y) == UNDER_REC ) /* generate an underline now */
+ PrintUnderline(back(y, ROWM), back(y, COLM), fwd(y, COLM), pg - xmk);
+ continue;
+ }
+ FixAndPrintObject(y, xmk, xb, xf, dim, NO_SUPPRESS, pg, count);
+ }
+ back(x, dim) = xb; fwd(x, dim) = xf;
+ break;
+
+
+ case COL_THR:
+ case ROW_THR:
+
+ /* find and delete the child number count of y */
+ assert( (type(x) == COL_THR) == (dim == COLM), "FixAndPrintObject: thr!" );
+ for( link = Down(x), uplink = Up(x), i = 1;
+ link != x && uplink != x && i < count;
+ link = NextDown(link), uplink = NextUp(uplink), i++ );
+ assert( link != x && uplink != x, "FixAndPrintObject: link or uplink!" );
+ CountChild(y, link, count);
+ debug7(DGP, DD, " fapo of %s (%s,%s) child %d %s (%s,%s)",
+ Image(type(x)),
+ EchoLength(back(x, dim)), EchoLength(fwd(x, dim)),
+ i, Image(type(y)), EchoLength(back(y, dim)), EchoLength(fwd(y, dim)));
+ MoveLink(uplink, link, CHILD); DeleteLink(link); /* IMPORTANT!!! */
+ assert( type(y) != GAP_OBJ, "FAPO: THR!");
+
+ /* assign size if not done previously */
+ /* ***
+ if( thr_state(x) != FINALSIZE && type(y) != START_HVSPAN &&
+ type(y) != START_HSPAN && type(y) != START_VSPAN &&
+ type(y) != HSPAN && type(y) != VSPAN )
+ *** */
+ if( thr_state(x) != FINALSIZE )
+ { back(x, dim) = xb; fwd(x, dim) = xf;
+ thr_state(x) = FINALSIZE;
+ }
+
+ /* fix y */
+ FixAndPrintObject(y, xmk, back(x, dim), fwd(x, dim), dim,
+ NO_SUPPRESS, pg, count);
+ if( Up(x) == x ) Dispose(x);
+ break;
+
+
+ default:
+
+ assert1(FALSE, "FixAndPrintObject:", Image(type(x)));
+ break;
+
+ } /* end switch */
+ debug2(DGP, DD, "] FixAndPrintObject returning (size now %s,%s).",
+ EchoLength(back(x, dim)), EchoLength(fwd(x, dim)));
+} /* end FixAndPrintObject */