home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / APPS / lout2.lzh / LOUT2 / z15.c < prev    next >
Text File  |  1994-01-23  |  24KB  |  622 lines

  1. /*@z15.c:Size Constraints:MinConstraint(), EnlargeToConstraint()@*************/
  2. /*                                                                           */
  3. /*  LOUT: A HIGH-LEVEL LANGUAGE FOR DOCUMENT FORMATTING (VERSION 2.05)       */
  4. /*  COPYRIGHT (C) 1993 Jeffrey H. Kingston                                   */
  5. /*                                                                           */
  6. /*  Jeffrey H. Kingston (jeff@cs.su.oz.au)                                   */
  7. /*  Basser Department of Computer Science                                    */
  8. /*  The University of Sydney 2006                                            */
  9. /*  AUSTRALIA                                                                */
  10. /*                                                                           */
  11. /*  This program is free software; you can redistribute it and/or modify     */
  12. /*  it under the terms of the GNU General Public License as published by     */
  13. /*  the Free Software Foundation; either version 1, or (at your option)      */
  14. /*  any later version.                                                       */
  15. /*                                                                           */
  16. /*  This program is distributed in the hope that it will be useful,          */
  17. /*  but WITHOUT ANY WARRANTY; without even the implied warranty of           */
  18. /*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
  19. /*  GNU General Public License for more details.                             */
  20. /*                                                                           */
  21. /*  You should have received a copy of the GNU General Public License        */
  22. /*  along with this program; if not, write to the Free Software              */
  23. /*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                */
  24. /*                                                                           */
  25. /*  FILE:         z15.c                                                      */
  26. /*  MODULE:       Size Constraints                                           */
  27. /*  EXTERNS:      MinConstraint(), EnlargeToConstraint(),                    */
  28. /*                ReflectConstraint(), SemiRotateConstraint(),               */
  29. /*                RotateConstraint(), InvScaleConstraint(), Constrained(),   */
  30. /*                EchoConstraint(), DebugConstrained()                       */
  31. /*                                                                           */
  32. /*****************************************************************************/
  33. #include <math.h>
  34. #ifndef M_PI
  35. #define M_PI       3.1415926535897931160E0
  36. #endif
  37.  
  38. #include "externs"
  39.  
  40.  
  41. /*****************************************************************************/
  42. /*                                                                           */
  43. /*  MinConstraint(xc, yc)                                                    */
  44. /*                                                                           */
  45. /*  Replace *xc by the minimum of the two constraints *xc and *yc.           */
  46. /*                                                                           */
  47. /*****************************************************************************/
  48.  
  49. MinConstraint(xc, yc)
  50. CONSTRAINT *xc, *yc;
  51. { bc(*xc)  = min(bc(*xc),  bc(*yc));
  52.   bfc(*xc) = min(bfc(*xc), bfc(*yc));
  53.   fc(*xc)  = min(fc(*xc),  fc(*yc));
  54. } /* end MinConstraint */
  55.  
  56.  
  57. /*****************************************************************************/
  58. /*                                                                           */
  59. /*  EnlargeToConstraint(b, f, c)                                             */
  60. /*                                                                           */
  61. /*  Enlarge *b,*f to its largest possible value within constraint *c.        */
  62. /*                                                                           */
  63. /*****************************************************************************/
  64.  
  65. EnlargeToConstraint(b, f, c)
  66. LENGTH *b, *f;  CONSTRAINT *c;
  67. {
  68.   *f = min(bfc(*c) - *b, fc(*c));
  69. } /* end EnlargeToConstraint */
  70.  
  71.  
  72. /*@::InvScaleConstraint(), ReflectConstraint(), etc.@*************************/
  73. /*                                                                           */
  74. /*  InvScaleConstraint(yc, sf, xc)                                           */
  75. /*                                                                           */
  76. /*  Scale constraint xc to the inverse of the scale factor sf.               */
  77. /*                                                                           */
  78. /*****************************************************************************/
  79.  
  80. InvScaleConstraint(yc, sf, xc)
  81. CONSTRAINT *yc;  LENGTH sf;  CONSTRAINT *xc;
  82. { char buff[10];
  83.   ifdebug(DSC, D, sprintf(buff, "%.3f", (float) sf / SF));
  84.   debug2(DSC, D, "InvScaleConstraint(yc, %s, %s)", buff, EchoConstraint(xc));
  85.   assert( sf > 0, "InvScaleConstraint: sf <= 0!" );
  86.   bc(*yc)  = bc(*xc)  == MAX_LEN ? MAX_LEN : min(MAX_LEN, bc(*xc)  * SF / sf);
  87.   bfc(*yc) = bfc(*xc) == MAX_LEN ? MAX_LEN : min(MAX_LEN, bfc(*xc) * SF / sf);
  88.   fc(*yc)  = fc(*xc)  == MAX_LEN ? MAX_LEN : min(MAX_LEN, fc(*xc)  * SF / sf);
  89.   debug1(DSC, D, "InvScaleConstraint returning %s", EchoConstraint(yc));
  90. } /* end InvScaleConstraint */
  91.  
  92.  
  93. /*****************************************************************************/
  94. /*                                                                           */
  95. /*  ReflectConstraint(xc, yc)                                                */
  96. /*                                                                           */
  97. /*  Set xc to the constraint which is yc with its back and forward reversed. */
  98. /*                                                                           */
  99. /*****************************************************************************/
  100.  
  101. #define ReflectConstraint(xc, yc)  SetConstraint(xc, fc(yc), bfc(yc), bc(yc))
  102.  
  103.  
  104. /*****************************************************************************/
  105. /*                                                                           */
  106. /*  static SemiRotateConstraint(xc, u, v, angle, yc)                         */
  107. /*                                                                           */
  108. /*  Used by RotateConstraint to calculate one rotated constraint.            */
  109. /*                                                                           */
  110. /*****************************************************************************/
  111.  
  112. static SemiRotateConstraint(xc, u, v, angle, yc)
  113. CONSTRAINT *xc;  LENGTH u, v;  float angle; CONSTRAINT *yc;
  114. { float cs, sn;  char buff[20];
  115.   ifdebug(DSC, D, sprintf(buff, "%.1f", angle * 360.0 / (2 * M_PI)));
  116.   debug4(DSC, D, "SemiRotateConstraint(xc, %s, %s, %sd, %s",
  117.     EchoLength(u), EchoLength(v), buff, EchoConstraint(yc));
  118.   cs = cos(angle);  sn = sin(angle);
  119.   if( fabs(cs) < 1e-6 )
  120.     SetConstraint(*xc, MAX_LEN, MAX_LEN, MAX_LEN);
  121.   else
  122.     SetConstraint(*xc,
  123.       min(MAX_LEN, (bc(*yc) - u * sn) / cs),
  124.       min(MAX_LEN, (bfc(*yc) - u * sn - v * sn) / cs),
  125.       min(MAX_LEN, (fc(*yc) - v * sn) / cs) );
  126.   debug1(DSC, D, "SemiRotateConstraint returning %s", EchoConstraint(xc));
  127. } /* end SemiRotateConstraint */
  128.  
  129.  
  130. /*@::RotateConstraint()@******************************************************/
  131. /*                                                                           */
  132. /*  RotateConstraint(c, y, angle, hc, vc, dim)                               */
  133. /*                                                                           */
  134. /*  Take the object angle @Rotate y, which is supposed to be constrained     */
  135. /*  horizontally by hc and vertically by vc, and determine a constraint      */
  136. /*  (either horizontal or vertical, depending on dim) for y.                 */
  137. /*                                                                           */
  138. /*  The constraint returned is a trigonometric function of all these         */
  139. /*  parameters, including the present size of y in dimension 1-dim.          */
  140. /*                                                                           */
  141. /*****************************************************************************/
  142.  
  143. RotateConstraint(c, y, angle, hc, vc, dim)
  144. CONSTRAINT *c;  OBJECT y;  LENGTH angle;  CONSTRAINT *hc, *vc;  int dim;
  145. { CONSTRAINT c1, c2, c3, dc;  float theta, psi;
  146.   char buff[20];
  147.   ifdebug(DSC, D, sprintf(buff, "%.1f", (float) angle / DG ));
  148.   debug4(DSC, D, "RotateConstraint(c, y, %sd, %s, %s, %s)",
  149.     buff, EchoConstraint(hc), EchoConstraint(vc), dimen(dim));
  150.  
  151.   /* work out angle in radians between 0 and 2*PI */
  152.   theta = (float) angle * 2 * M_PI / (float) (DG * 360);
  153.   while( theta < 0 ) theta += 2 * M_PI;
  154.   while( theta >= 2 * M_PI ) theta -= 2 * M_PI;
  155.   assert( 0 <= theta && theta <= 2 * M_PI, "RotateConstraint: theta!" );
  156.  
  157.   /* determine theta, c1, and c2 depending on which quadrant we are in */
  158.   if( theta <= M_PI / 2.0 )   /* first quadrant */
  159.   { theta = theta;
  160.     CopyConstraint(c1, *hc);
  161.     CopyConstraint(c2, *vc);
  162.   }
  163.   else if ( theta <= M_PI )   /* second quadrant */
  164.   { theta -= M_PI / 2.0;
  165.     ReflectConstraint(c1, *vc);
  166.     CopyConstraint(c2, *hc);
  167.   }
  168.   else if ( theta <= 3.0 * M_PI / 2.0 )   /* third quadrant */
  169.   { theta -= M_PI;
  170.     ReflectConstraint(c1, *hc);
  171.     ReflectConstraint(c2, *vc);
  172.   }
  173.   else /* fourth quadrant */
  174.   { theta -= 3.0 * M_PI / 2.0;
  175.     CopyConstraint(c1, *vc);
  176.     ReflectConstraint(c2, *hc);
  177.   }
  178.   psi = M_PI / 2.0 - theta;
  179.   debug2(DSC, D, "  c1: %s;  c2: %s", EchoConstraint(&c1), EchoConstraint(&c2));
  180.  
  181.   /* return the minimum of the two constraints, rotated */
  182.   if( dim == COL )
  183.   { SemiRotateConstraint(c, back(y, ROW), fwd(y, ROW), theta, &c1);
  184.     ReflectConstraint(c3, c2);
  185.     SemiRotateConstraint(&dc, fwd(y, ROW), back(y, ROW), psi, &c3);
  186.     MinConstraint(c, &dc);
  187.   }
  188.   else
  189.   { SemiRotateConstraint(c, back(y, COL), fwd(y, COL), psi, &c1);
  190.     SemiRotateConstraint(&dc, fwd(y, COL), back(y, COL), theta, &c2);
  191.     MinConstraint(c, &dc);
  192.   }
  193.  
  194.   debug1(DSC, D, "RotateConstraint returning %s", EchoConstraint(c));
  195. } /* end RotateConstraint */
  196.  
  197.  
  198. /*@::CatConstrained()@********************************************************/
  199. /*                                                                           */
  200. /*  static CatConstrained(x, xc, ratm, y, dim)                               */
  201. /*                                                                           */
  202. /*  Calculate the size constraint of object x, as for Constrained below.     */
  203. /*  y is the enclosing VCAT etc. object;  ratm is TRUE if a ^ lies after     */
  204. /*  x anywhere.  dim is COL or ROW.                                          */
  205. /*                                                                           */
  206. /*  The meaning of the key variables is as follows:                          */
  207. /*                                                                           */
  208. /*  be       The amount by which back(x, dim) can increase from zero         */
  209. /*           without having any impact on size(y, dim).  Thereafter,         */
  210. /*           any increase causes an equal increase in size(y, dim).          */
  211. /*                                                                           */
  212. /*  fe       The amount by which fwd(x, dim) can increase from zero          */
  213. /*           without having any impact on size(y, dim).  Thereafter,         */
  214. /*           any increase causes an equal increase in size(y, dim).          */
  215. /*                                                                           */
  216. /*  backy,   The value that back(y, dim) and fwd(y, dim) would have if x     */
  217. /*  fwdy     was definite with size 0,0.  They will in general be larger     */
  218. /*           than the present values if x is indefinite, and smaller         */
  219. /*           if x is definite, although it depends on marks and gaps.        */
  220. /*                                                                           */
  221. /*****************************************************************************/
  222.  
  223. static CatConstrained(x, xc, ratm, y, dim)
  224. OBJECT x;  CONSTRAINT *xc; BOOLEAN ratm;  OBJECT y;  int dim;
  225. { int side;            /* the size of y that x is on: BACK, ON, FWD */
  226.   CONSTRAINT yc;        /* constraints on y                          */
  227.   LENGTH backy, fwdy;        /* back(y), fwd(y) would be if x was (0, 0)  */
  228.   LENGTH be, fe;        /* amount back(x), fwd(x) can be for free    */
  229.   LENGTH beffect, feffect;    /* scratch variables for calculations        */
  230.   LENGTH seffect;        /* scratch variables for calculations        */
  231.   OBJECT link, sg, pg;    /* link to x, its successor and predecessor  */
  232.   OBJECT prec_def, sd;    /* definite object preceding (succeeding) x  */
  233.   int tb, tbf, tf, tbc, tbfc, tfc, mxy, myz;
  234.  
  235.   Constrained(y, &yc, dim);
  236.   if( constrained(yc) )
  237.   {
  238.     /* find the link of x, and its neighbours and their links */
  239.     link = UpDim(x, dim);
  240.     SetNeighbours(link, ratm, &pg, &prec_def, &sg, &sd, &side);
  241.  
  242.     /* amount of space available at x without changing the size of y */
  243.     be = pg == nil ? 0 : ExtraGap(fwd(prec_def, dim), 0, &gap(pg), BACK);
  244.     fe = sg == nil ? 0 : ExtraGap(0, back(sd, dim),      &gap(sg), FWD);
  245.  
  246.     if( is_indefinite(type(x)) )
  247.     {
  248.       /* insert two lengths and delete one */
  249.       beffect = pg == nil ? 0 : MinGap(fwd(prec_def, dim), 0, 0, &gap(pg));
  250.       feffect = sg == nil ? 0 : MinGap(0, back(sd,dim), fwd(sd,dim), &gap(sg));
  251.       seffect = pg == nil ?
  252.       sg == nil ? 0 : back(sd, dim) :
  253.       sg == nil ? fwd(prec_def, dim) :
  254.         MinGap(fwd(prec_def, dim), back(sd, dim), fwd(sd, dim), &gap(sg));
  255.  
  256.       switch( side )
  257.       {
  258.     case BACK:    backy = back(y, dim) + beffect + feffect - seffect;
  259.             fwdy  = fwd(y, dim);
  260.             break;
  261.  
  262.     case ON:    /* must be first, other cases prohibited */
  263.             backy = 0;
  264.             fwdy = fwd(y, dim) + feffect;
  265.             break;
  266.  
  267.     case FWD:    backy = back(y, dim);
  268.             fwdy  = fwd(y, dim) + beffect + feffect - seffect;
  269.             break;
  270.       }
  271.     }
  272.  
  273.     else /* x is definite */
  274.  
  275.     { beffect = pg == nil ? back(x, dim) :
  276.     MinGap(fwd(prec_def, dim), back(x,dim), fwd(x,dim), &gap(pg)) -
  277.     MinGap(fwd(prec_def, dim), 0,           0,          &gap(pg));
  278.  
  279.       feffect = sg == nil ? fwd(x, dim) :
  280.     MinGap(fwd(x, dim), back(sd, dim), fwd(sd, dim), &gap(sg)) -
  281.     MinGap(0,           back(sd, dim), fwd(sd, dim), &gap(sg));
  282.  
  283.       switch( side )
  284.       {
  285.     case BACK:    backy = back(y, dim) - beffect - feffect;
  286.             fwdy  = fwd(y, dim);
  287.             break;
  288.  
  289.     case ON:    backy = back(y, dim) - beffect;
  290.             fwdy  = fwd(y, dim)  - feffect;
  291.             break;
  292.  
  293.     case FWD:    backy = back(y, dim);
  294.             fwdy  = fwd(y, dim) - beffect - feffect;
  295.             break;
  296.       }
  297.     }
  298.  
  299.     debug5(DSC, DDD, "side: %s, backy: %s, fwdy: %s, be: %s, fe: %s",
  300.         Image(side), EchoLength(backy), EchoLength(fwdy),
  301.         EchoLength(be), EchoLength(fe) );
  302.  
  303.     if( !FitsConstraint(backy, fwdy, yc) )
  304.       SetConstraint(*xc, -1, -1, -1);
  305.     else switch( side )
  306.     {
  307.  
  308.       case BACK:
  309.     
  310.     tbc = bc(yc) == MAX_LEN ? MAX_LEN : bc(yc) - backy;
  311.     tbfc = bfc(yc) == MAX_LEN ? MAX_LEN : bfc(yc) - backy - fwdy;
  312.     mxy = min(tbc, tbfc);
  313.     tb  = min(MAX_LEN, be + mxy);
  314.     tbf = min(MAX_LEN, be + fe + mxy);
  315.     tf  = min(MAX_LEN, fe + mxy);
  316.     SetConstraint(*xc, tb, tbf, tf);
  317.     break;
  318.  
  319.  
  320.       case ON:
  321.     
  322.     tbc = bc(yc) == MAX_LEN ? MAX_LEN : bc(yc) - backy;
  323.     tbfc = bfc(yc) == MAX_LEN ? MAX_LEN : bfc(yc) - backy - fwdy;
  324.     tfc = fc(yc) == MAX_LEN ? MAX_LEN : fc(yc) - fwdy;
  325.     mxy = min(tbc, tbfc);
  326.     myz = min(tfc, tbfc);
  327.     tb  = min(MAX_LEN, be + mxy);
  328.     tbf = min(MAX_LEN, be + fe + tbfc);
  329.     tf  = min(MAX_LEN, fe + myz);
  330.     SetConstraint(*xc, tb, tbf, tf);
  331.     break;
  332.     
  333.  
  334.       case FWD:
  335.  
  336.     tfc = fc(yc) == MAX_LEN ? MAX_LEN : fc(yc) - fwdy;
  337.     tbfc = bfc(yc) == MAX_LEN ? MAX_LEN : bfc(yc) - backy - fwdy;
  338.     mxy = min(tfc, tbfc);
  339.     tb  = min(MAX_LEN, be + mxy);
  340.     tbf = min(MAX_LEN, be + fe + mxy);
  341.     tf  = min(MAX_LEN, fe + mxy);
  342.     SetConstraint(*xc, tb, tbf, tf);
  343.     break;
  344.     
  345.     }
  346.   } /* end if( constrained ) */
  347.   else SetConstraint(*xc, MAX_LEN, MAX_LEN, MAX_LEN);
  348. } /* end CatConstrained */
  349.  
  350.  
  351. /*@::Constrained()@***********************************************************/
  352. /*                                                                           */
  353. /*  Constrained(x, xc, dim)                                                  */
  354. /*                                                                           */
  355. /*  Calculate the size constraint of object x, and return it in *xc.         */
  356. /*                                                                           */
  357. /*****************************************************************************/
  358.  
  359. Constrained(x, xc, dim)
  360. OBJECT x;  CONSTRAINT *xc;  int dim;
  361. { OBJECT y, link, lp, rp, z, tlink, g;  CONSTRAINT yc, hc, vc;
  362.   BOOLEAN ratm;  LENGTH xback, xfwd;  int tb, tf, tbf, tbc, tfc;
  363.   debug2(DSC, DD, "[ Constrained( %s, xc, %s )", EchoObject(x), dimen(dim));
  364.   assert( Up(x) != x, "Constrained: x has no parent!" );
  365.  
  366.   /* find y, the parent of x */
  367.   link = UpDim(x, dim);  ratm = FALSE;
  368.   for( tlink = NextDown(link);  type(tlink) == LINK;  tlink = NextDown(tlink) )
  369.   { Child(g, tlink);
  370.     if( type(g) == GAP_OBJ && mark(gap(g)) )  ratm = TRUE;
  371.   }
  372.   y = tlink;
  373.   debug1(DSC, DDD, "parent y = %s", Image(type(y)));
  374.   ifdebug(DSC, DDD, DebugObject(y));
  375.  
  376.   switch( type(y) )
  377.   {
  378.     case GRAPHIC:
  379.     case ONE_COL:
  380.     case ONE_ROW:
  381.     case HCONTRACT:
  382.     case VCONTRACT:
  383.     case HEXPAND:
  384.     case VEXPAND:
  385.     case PADJUST:
  386.     case HADJUST:
  387.     case VADJUST:
  388.     case SPLIT:
  389.     
  390.       Constrained(y, xc, dim);
  391.       break;
  392.  
  393.  
  394.     case VSCALE:
  395.     case HSCALE:
  396.     
  397.       if( (dim == COL) != (type(y) == HSCALE) )  Constrained(y, xc, dim);
  398.       else SetConstraint(*xc, MAX_LEN, MAX_LEN, MAX_LEN);
  399.       break;
  400.  
  401.  
  402.     case SCALE:
  403.  
  404.       Constrained(y, &yc, dim);
  405.       InvScaleConstraint(xc,
  406.     dim == COL ? bc(constraint(y)) : fc(constraint(y)), &yc);
  407.       break;
  408.  
  409.  
  410.     case ROTATE:
  411.     
  412.       Constrained(y, &hc, COL);  Constrained(y, &vc, ROW);
  413.       RotateConstraint(xc, x, sparec(constraint(y)), &hc, &vc, dim);
  414.       break;
  415.  
  416.  
  417.     case WIDE:
  418.     case HIGH:
  419.     
  420.       Constrained(y, xc, dim);
  421.       if( (type(y)==WIDE) == (dim==COL) )  MinConstraint(xc, &constraint(y));
  422.       break;
  423.  
  424.  
  425.     case HEAD:
  426.     
  427.       if( dim == ROW ) SetConstraint(*xc, MAX_LEN, MAX_LEN, MAX_LEN);
  428.       else
  429.       {    CopyConstraint(yc, constraint(y));
  430.     debug1(DSC, DD, "  head: %s; val is:", EchoConstraint(&yc));
  431.     ifdebug(DSC, DD, DebugObject(y));
  432.     goto REST_OF_HEAD;   /* a few lines down */
  433.       }
  434.       break;
  435.  
  436.  
  437.     case COL_THR:
  438.     case ROW_THR:
  439.  
  440.       assert( (type(y)==COL_THR) == (dim==COL), "Constrained: COL_THR!" );
  441.       Constrained(y, &yc, dim);
  442.       tb = bfc(yc) == MAX_LEN ? MAX_LEN : bfc(yc) - fwd(y, dim);
  443.       tb = min(bc(yc), tb);
  444.       tf = bfc(yc) == MAX_LEN ? MAX_LEN : bfc(yc) - back(y, dim);
  445.       tf = min(fc(yc), tf);
  446.       SetConstraint(*xc, tb, bfc(yc), tf);
  447.       break;
  448.  
  449.  
  450.     case VCAT:
  451.     case HCAT:
  452.     case ACAT:
  453.     
  454.       if( (type(y)==VCAT) == (dim==ROW) )
  455.       {    CatConstrained(x, xc, ratm, y, dim);
  456.     break;
  457.       }
  458.       Constrained(y, &yc, dim);
  459.       if( !constrained(yc) )  SetConstraint(*xc, MAX_LEN, MAX_LEN, MAX_LEN);
  460.       else
  461.       {
  462.     REST_OF_HEAD:
  463.     /* let lp and rp be the links of the gaps delimiting */
  464.     /* the components joined to x (or parent if no such) */
  465.     for( lp = PrevDown(link);  lp != y;  lp = PrevDown(lp) )
  466.     { Child(z, lp);
  467.       if( type(z) == GAP_OBJ && !join(gap(z)) )  break;
  468.     }
  469.     for( rp = NextDown(link);  rp != y;  rp = NextDown(rp) )
  470.     { Child(z, rp);
  471.       if( type(z) == GAP_OBJ && !join(gap(z)) )  break;
  472.     }
  473.     if( lp == y && rp == y && !(type(y) == HEAD && seen_nojoin(y)) )
  474.     {
  475.       /* if whole object is joined, do this */
  476.           tb = bfc(yc) == MAX_LEN ? MAX_LEN : bfc(yc) - fwd(y, dim);
  477.           tb = min(bc(yc), tb);
  478.           tf = bfc(yc) == MAX_LEN ? MAX_LEN : bfc(yc) - back(y, dim);
  479.           tf = min(fc(yc), tf);
  480.           SetConstraint(*xc, tb, bfc(yc), tf);
  481.     }
  482.     else
  483.     {
  484.       /* if // or || is present, do this */
  485.       xback = xfwd = 0;
  486.       for(link = NextDown(lp); link != rp;  link = NextDown(link) )
  487.       { Child(z, link);
  488.         if( type(z) == GAP_OBJ || is_index(type(z)) )  continue;
  489.         xback = max(xback, back(z, dim));  xfwd = max(xfwd, fwd(z, dim));
  490.       }
  491.       debug2(DSC, DD, "  lp != rp; xback,xfwd = %s,%s",
  492.             EchoLength(xback), EchoLength(xfwd));
  493.       tbf = min(bfc(yc), fc(yc));
  494.       tbc = tbf == MAX_LEN ? MAX_LEN : tbf - xfwd;
  495.       tfc = tbf == MAX_LEN ? MAX_LEN : tbf - xback;
  496.       SetConstraint(*xc, tbc, tbf, tfc);
  497.     }
  498.       }
  499.       break;
  500.  
  501.  
  502.     default:  Error(INTERN, &fpos(y), "Constrained: %s", Image(type(y)) );
  503.           break;
  504.   }
  505.   debug1(DSC, DD, "] Constrained returning %s", EchoConstraint(xc));
  506. } /* end Constrained */
  507.  
  508.  
  509. /*@::EchoConstraint(), DebugConstrained()@************************************/
  510. /*                                                                           */
  511. /*  FULL_CHAR *EchoConstraint(c)                                             */
  512. /*                                                                           */
  513. /*  Returns a string showing constraint *c, in centimetres.                  */
  514. /*                                                                           */
  515. /*****************************************************************************/
  516. #if DEBUG_ON
  517.  
  518. FULL_CHAR *EchoConstraint(c)
  519. CONSTRAINT *c;
  520. { static char str[2][40];
  521.   static int i = 0;
  522.   i = (i+1) % 2;
  523.   sprintf(str[i], "<");
  524.   if( bc(*c)==MAX_LEN )  sprintf(&str[i][strlen(str[i])], "INF, ");
  525.   else sprintf(&str[i][strlen(str[i])], "%.3fc, ", (float) bc(*c)/CM);
  526.   if( bfc(*c)==MAX_LEN )  sprintf(&str[i][strlen(str[i])], "INF, ");
  527.   else sprintf(&str[i][strlen(str[i])], "%.3fc, ", (float) bfc(*c)/CM);
  528.   if( fc(*c)==MAX_LEN )  sprintf(&str[i][strlen(str[i])], "INF>");
  529.   else sprintf(&str[i][strlen(str[i])], "%.3fc>", (float) fc(*c)/CM);
  530.   return AsciiToFull(str[i]);
  531. } /* end EchoConstraint */
  532.  
  533.  
  534. /*****************************************************************************/
  535. /*                                                                           */
  536. /*  DebugConstrained(x)                                                      */
  537. /*                                                                           */
  538. /*  Calculate and print the constraints of all closures lying within         */
  539. /*  sized object x.                                                          */
  540. /*                                                                           */
  541. /*****************************************************************************/
  542.  
  543. DebugConstrained(x)
  544. OBJECT x;
  545. { OBJECT y, link;
  546.   CONSTRAINT c;
  547.   debug1(DSC, DDD, "DebugConstrained( %s )", EchoObject(x) );
  548.   switch( type(x) )
  549.   {
  550.  
  551.     case CROSS:
  552.     case ROTATE:
  553.     case INCGRAPHIC:
  554.     case SINCGRAPHIC:
  555.     case GRAPHIC:
  556.     case WORD:
  557.     case QWORD:
  558.     
  559.       break;
  560.  
  561.  
  562.     case CLOSURE:
  563.     
  564.       Constrained(x, &c, COL);
  565.       debug2(DSC, D, "Constrained( %s, &c, COL ) = %s",
  566.     EchoObject(x), EchoConstraint(&c));
  567.       Constrained(x, &c, ROW);
  568.       debug2(DSC, D, "Constrained( %s, &c, ROW ) = %s",
  569.     EchoObject(x), EchoConstraint(&c));
  570.       break;
  571.  
  572.  
  573.     case SPLIT:
  574.     
  575.       link = DownDim(x, COL);  Child(y, link);
  576.       DebugConstrained(y);
  577.       break;
  578.  
  579.  
  580.     case HEAD:
  581.     case ONE_COL:
  582.     case ONE_ROW:
  583.     case HCONTRACT:
  584.     case VCONTRACT:
  585.     case HEXPAND:
  586.     case VEXPAND:
  587.     case PADJUST:
  588.     case HADJUST:
  589.     case VADJUST:
  590.     case HSCALE:
  591.     case VSCALE:
  592.     case SCALE:
  593.     case WIDE:
  594.     case HIGH:
  595.     
  596.       link = Down(x);  Child(y, link);
  597.       DebugConstrained(y);
  598.       break;
  599.  
  600.  
  601.     case COL_THR:
  602.     case VCAT:
  603.     case HCAT:
  604.     case ACAT:
  605.     
  606.       for( link = Down(x);  link != x;  link =NextDown(link) )
  607.       {    Child(y, link);
  608.     if( type(y) != GAP_OBJ && !is_index(type(y)) )  DebugConstrained(y);
  609.       }
  610.       break;
  611.  
  612.  
  613.     default:
  614.     
  615.       Error(INTERN, &fpos(x), "DebugConstrained: type(x)= %s", Image(type(x)) );
  616.       break;
  617.  
  618.   }
  619.   debug0(DSC, DDD, "DebugConstrained returning.");
  620. } /* end DebugConstrained */
  621. #endif
  622.