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

  1. /*@z16.c:Size Adjustment:SetNeighbours(), CatAdjustSize()@********************/
  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:         z16.c                                                      */
  26. /*  MODULE:       Size Adjustment                                            */
  27. /*  EXTERNS:      SetNeighbours(), AdjustSize()                              */
  28. /*                                                                           */
  29. /*****************************************************************************/
  30. #include "externs"
  31.  
  32.  
  33. /*****************************************************************************/
  34. /*                                                                           */
  35. /*  SetNeighbours(link, ratm, pg, pdef, sg, sdef, side)                      */
  36. /*                                                                           */
  37. /*  This is a utility routine used by CatConstrained(), AdjustSize(),        */
  38. /*  BreakTable() and FlushGalley() for calculating size updates in objects.  */
  39. /*  Assuming that link is the link of a component of a VCAT etc., and that   */
  40. /*  ratm is TRUE if there is a marked component to the right of link, set    */
  41. /*                                                                           */
  42. /*     pg    to the gap separating link from the first definite object       */
  43. /*           to the left, or nil if none.  If pg != nil, set pdef to         */
  44. /*           the preceding definite object;  else pdef is undefined.         */
  45. /*                                                                           */
  46. /*     sg    to the gap separating link from the first definite object       */
  47. /*           to the right, or nil if none.  if sg != nil, set sdef to        */
  48. /*           the succeeding definite object;  else sdef is undefined.        */
  49. /*                                                                           */
  50. /*     side  to the side of the mark link is on; either BACK, ON or FWD.     */
  51. /*                                                                           */
  52. /*****************************************************************************/
  53.  
  54. SetNeighbours(link, ratm, pg, pdef, sg, sdef, side)
  55. OBJECT link;  BOOLEAN ratm;
  56. OBJECT *pg, *pdef, *sg, *sdef;  int *side;
  57. { OBJECT plink, slink;
  58.  
  59.   /* find preceding definite; if it exists, set *pg */
  60.   *pg = nil;
  61.   for( plink = PrevDown(link);  type(plink) == LINK;  plink = PrevDown(plink) )
  62.   { Child(*pdef, plink);
  63.     if( type(*pdef) == SPLIT ? SplitIsDefinite(*pdef) : is_definite(type(*pdef)) )
  64.     { Child(*pg, PrevDown(link));
  65.       while( is_index(type(*pg)) )
  66.       {    link = PrevDown(link);
  67.     Child(*pg, PrevDown(link));
  68.       }
  69.       assert( type(*pg) == GAP_OBJ, "SetNeighbours: type(*pg)!" );
  70.       break;
  71.     }
  72.   }
  73.  
  74.   /* find succeeding definite; if it exists, set *sg */
  75.   *sg = nil;
  76.   for( slink = NextDown(link);  type(slink) == LINK;  slink = NextDown(slink) )
  77.   { Child(*sdef, slink);
  78.     if( type(*sdef) == SPLIT ? SplitIsDefinite(*sdef) : is_definite(type(*sdef)) )
  79.     { Child(*sg, PrevDown(slink));
  80.       while( is_index(type(*sg)) )
  81.       {    slink = PrevDown(slink);
  82.     Child(*sg, PrevDown(slink));
  83.       }
  84.       assert( type(*sg) == GAP_OBJ, "SetNeighbours: type(*sg)!" );
  85.       break;
  86.     }
  87.   }
  88.  
  89.   *side = ratm ? BACK : *pg == nil || mark(gap(*pg)) ? ON : FWD;
  90.   debug4(DSA,DD, "SetNeighbours: ratm == %s, pg %s nil, sg %s nil, side == %s",
  91.     bool(ratm), *pg == nil ? "==" : "!=", *sg == nil ? "==" : "!=", 
  92.     *side == BACK ? "BACK" : *side == ON ? "ON" : "FWD");
  93. } /* end SetNeighbours */
  94.  
  95.  
  96. /*****************************************************************************/
  97. /*                                                                           */
  98. /*  static CatAdjustSize(x, b, f, ratm, y, dim)                              */
  99. /*                                                                           */
  100. /*  Adjust the size of x to be *b, *f.  Object x is known to lie in add-set  */
  101. /*  y;  ratm is TRUE iff there is a mark to the right of x.  Return the      */
  102. /*  new size of y in *b, *f.                                                 */
  103. /*                                                                           */
  104. /*****************************************************************************/
  105.  
  106. static CatAdjustSize(x, b, f, ratm, y, dim)
  107. OBJECT x;  LENGTH *b, *f;  BOOLEAN ratm;  OBJECT y;  int dim;
  108. { OBJECT link;
  109.   OBJECT pg, prec_def, sg, sd;
  110.   LENGTH beffect, feffect, seffect;  int side;
  111.   int bb, ff;
  112.  
  113.   debug6(DSA, D, "CatAdjustSize(%s x, %s, %s, %s, %s y, %s)", Image(type(x)),
  114.     EchoLength(*b), EchoLength(*f), bool(ratm), Image(type(y)), dimen(dim));
  115.   debug2(DSA,DD, "x(%s,%s) =", EchoLength(back(x,dim)), EchoLength(fwd(x,dim)));
  116.   ifdebug(DSA, DD, DebugObject(x));
  117.   debug2(DSA,DD, "y(%s,%s) =", EchoLength(back(y,dim)), EchoLength(fwd(y,dim)));
  118.   ifdebug(DSA, DD, DebugObject(y));
  119.  
  120.   /* DO_ADJUST ACAT is a special case because adjustment affects its size */
  121.   if( dim==COL && type(y)==ACAT && display_style(save_style(y)) == DO_ADJUST )
  122.   { back(x, dim) = *b;  fwd(x, dim) = *f;
  123.     *b = back(y, dim);  *f = fwd(y, dim);
  124.     debug2(DSA, D, "CatAdjustSize ACAT %s,%s", EchoLength(*b), EchoLength(*f));
  125.     return;
  126.   }
  127.  
  128.   link = UpDim(x, dim);
  129.   SetNeighbours(link, ratm, &pg, &prec_def, &sg, &sd, &side);
  130.   { ifdebug(DSA, D,
  131.     if( pg != nil && mode(gap(pg)) == NO_MODE )
  132.     { debug1(DSA, D, "NO_MODE gap pg, is_indefinite(x) == %s, y =",
  133.     bool(is_indefinite(type(x))) );
  134.       ifdebug(DSA, D, DebugObject(y));
  135.     }
  136.     if( sg != nil && mode(gap(sg)) == NO_MODE )
  137.     { debug1(DSA, D, "NO_MODE gap sg, is_indefinite(x) == %s, y =",
  138.     bool(is_indefinite(type(x))) );
  139.       ifdebug(DSA, D, DebugObject(y));
  140.     }
  141.   ); }
  142.   if( is_indefinite(type(x)) )
  143.   {
  144.     beffect = pg == nil ? *b :
  145.       MinGap(fwd(prec_def, dim), *b, *f, &gap(pg));
  146.  
  147.     feffect = sg == nil ? *f :
  148.       MinGap(*f, back(sd, dim), fwd(sd, dim), &gap(sg));
  149.  
  150.     seffect = pg == nil ? sg == nil ? 0 : back(sd, dim) :
  151.       sg == nil ? fwd(prec_def, dim) :
  152.       MinGap(fwd(prec_def, dim), back(sd,dim), fwd(sd,dim), &gap(sg));
  153.   }
  154.   else /* !is_indefinite(type(x)) */
  155.   {
  156.     beffect = pg == nil ?  *b - back(x, dim) :
  157.       MinGap(fwd(prec_def, dim), *b,           *f,          &gap(pg)) -
  158.       MinGap(fwd(prec_def, dim), back(x, dim), fwd(x, dim), &gap(pg));
  159.  
  160.     feffect = sg == nil ? *f - fwd(x, dim) :
  161.       MinGap(*f,          back(sd, dim), fwd(sd, dim), &gap(sg)) -
  162.       MinGap(fwd(x, dim), back(sd, dim), fwd(sd, dim), &gap(sg));
  163.     
  164.     seffect = 0;
  165.   }
  166.  
  167.   back(x, dim) = *b;  fwd(x, dim) = *f;
  168.   switch( side )
  169.   {
  170.     case BACK:    bb = back(y, dim) + beffect + feffect - seffect;
  171.         ff = fwd(y, dim);
  172.         break;
  173.  
  174.     case ON:    bb = back(y, dim) + beffect - seffect;
  175.         ff = fwd(y, dim) + feffect;
  176.         break;
  177.  
  178.     case FWD:    bb = back(y, dim);
  179.         ff = fwd(y, dim) + beffect + feffect - seffect;
  180.         break;
  181.   }
  182.   if( bb > MAX_LEN || ff > MAX_LEN )
  183.   { debug2(DSA, D, "bb = %s, ff = %s, y =", EchoLength(bb), EchoLength(ff));
  184.     ifdebug(DSA, D, DebugObject(y));
  185.     debug0(DSA, D, "x was");
  186.     ifdebug(DSA, D, DebugObject(x));
  187.     Error(FATAL,&fpos(y),"maximum size (%s) exceeded", EchoLength(MAX_LEN));
  188.   }
  189.   *b = bb;  *f = ff;
  190.   debug2(DSA, D, "CatAdjustSize returning %s,%s", EchoLength(*b), EchoLength(*f));
  191. } /* end CatAdjustSize */
  192.  
  193.  
  194. /*@::AdjustSize()@************************************************************/
  195. /*                                                                           */
  196. /*  AdjustSize(x, b, f, dim)                                                 */
  197. /*                                                                           */
  198. /*  Adjust the size of object x, in dimension dim, to be b, f.  If x is a    */
  199. /*  CLOSURE, the adjustment is from a CLOSURE to a definite object of size   */
  200. /*  b, f.                                                                    */
  201. /*                                                                           */
  202. /*****************************************************************************/
  203.  
  204. AdjustSize(x, b, f, dim)
  205. OBJECT x;  LENGTH b, f;  int dim;
  206. { OBJECT y, link, tlink, lp, rp, z, index;
  207.   BOOLEAN ratm;  LENGTH tb, tf, cby, cfy, rby, rfy;
  208.  
  209.   debug6(DSA, D, "[ AdjustSize( %s(%s,%s), %s, %s, %s ), x =",
  210.     Image(type(x)), EchoLength(back(x, dim)), EchoLength(fwd(x, dim)),
  211.     EchoLength(b), EchoLength(f), dimen(dim));
  212.   ifdebug(DSA, DD, DebugObject(x) );
  213.  
  214.   while( b != back(x, dim) || f != fwd(x, dim) || is_indefinite(type(x)) )
  215.   { assert( Up(x) != x, "AdjustSize: Up(x) == x!" );
  216.     assert( b >= 0, "AdjustSize: b < 0!" );
  217.     assert( f >= 0, "AdjustSize: f < 0!" );
  218.  
  219.     /* these cases are unique because they have multiple parents */
  220.     if( type(x) == COL_THR || type(x) == ROW_THR )
  221.     { assert( (type(x)==COL_THR) == (dim==COL), "AdjustSize: COL_THR!" );
  222.       back(x, dim) = b;  fwd(x, dim) = f;
  223.       for( link = Up(x);  link != x;  link = NextUp(link) )
  224.       { Parent(y, link);
  225.     assert( type(y) == SPLIT, "AdjustSize: type(y) != SPLIT!") ;
  226.     AdjustSize(y, b, f, dim);
  227.       }
  228.       debug0(DSA, D, "[ AdjustSize (thread case) returning.");
  229.       return;
  230.     }
  231.  
  232.     link = UpDim(x, dim);  ratm = FALSE;
  233.     for( tlink=NextDown(link);  type(tlink) == LINK;  tlink=NextDown(tlink) )
  234.     { Child(y, tlink);
  235.       if( type(y) == GAP_OBJ && mark(gap(y)) )  ratm = TRUE;
  236.     }
  237.     y = tlink;
  238.  
  239.     debug5(DSA, DD, "  b = %s, f = %s, y = %s(%s,%s), x =",
  240.     EchoLength(b), EchoLength(f), Image(type(y)),
  241.     EchoLength(back(y, dim)), EchoLength(fwd(y, dim)));
  242.     ifdebug(DSA, DD, DebugObject(x) );
  243.  
  244.     switch( type(y) )
  245.     {
  246.  
  247.       case HEAD:
  248.       
  249.     if( dim == ROW )
  250.     { back(x, dim) = b, fwd(x, dim) = f;
  251.       debug0(DSA, D, "] AdjustSize ROW returning at HEAD");
  252.       return;
  253.     }
  254.     else
  255.     {
  256.       /* let lp and rp be the gaps delimiting the          */
  257.       /* components joined to x                            */
  258.       for( lp = PrevDown(link);  lp != y;  lp = PrevDown(lp) )
  259.       { Child(z, lp);
  260.         if( type(z) == GAP_OBJ && !join(gap(z)) )  break;
  261.       }
  262.       for( rp = NextDown(link);  rp != y;  rp = NextDown(rp) )
  263.       { Child(z, rp);
  264.         if( type(z) == GAP_OBJ && !join(gap(z)) )  break;
  265.       }
  266.  
  267.       back(x, dim) = b;  fwd(x, dim) = f;
  268.       if( lp == y && rp == y && !seen_nojoin(y) )
  269.       {    
  270.         /* if whole object is joined, do this */
  271.         b = max(b, back(y, dim));
  272.         f = max(f, fwd(y, dim));
  273.       }
  274.       else
  275.       {
  276.         /* if // or || is present, do this */
  277.         tb = tf = 0;
  278.         for( link = NextDown(lp);  link != rp;  link = NextDown(link) )
  279.         { Child(z, link);
  280.           if( type(z) == GAP_OBJ || is_index(type(z)) )  continue;
  281.           tb = max(tb, back(z, dim));
  282.           tf = max(tf, fwd(z, dim));
  283.         }
  284.         b = 0;  f = max(tb + tf, fwd(y, dim));
  285.       }
  286.       if( back(y, dim) == b && fwd(y, dim) == f )
  287.       {
  288.         debug0(DSA, D, "] AdjustSize (COL) returning at HEAD (no wider)");
  289.         return;
  290.       }
  291.       debug3(DGF, D, "AdjustSize widening %s to %s,%s",
  292.            SymName(actual(y)), EchoLength(b), EchoLength(f));
  293.       back(y, dim) = b;  fwd(y, dim) = f;
  294.       if( Up(y) == y )
  295.       {
  296.         debug0(DSA, D, "] AdjustSize ret. at HEAD (no parent)" );
  297.         return;
  298.       }
  299.       Parent(index, Up(y));
  300.       if( type(index) != RECEIVING )
  301.       {
  302.         debug1(DSA,D, "] AdjustSize ret. at HEAD (%s)", Image(type(index)));
  303.         return;
  304.       }
  305.       assert( actual(index) != nil, "AdjustSize: actual(index) == nil!" );
  306.       assert( type(actual(index)) == CLOSURE, "AdjustSize: index non-C!" );
  307.       if( actual(actual(index)) != GalleySym )
  308.       {
  309.         debug0(DSA, D, "] AdjustSize ret. at HEAD (not @Galley, so root)" );
  310.         return;
  311.       }
  312.       y = actual(index);
  313.     }
  314.     break;
  315.  
  316.  
  317.       case SPLIT:
  318.       case HCONTRACT:
  319.       case VCONTRACT:
  320.       case HEXPAND:
  321.       case VEXPAND:
  322.       case PADJUST:
  323.       case HADJUST:
  324.       case VADJUST:
  325.       case ONE_COL:
  326.       case ONE_ROW:
  327.       case GRAPHIC:
  328.  
  329.     back(x, dim) = b;  fwd(x, dim) = f;
  330.     break;
  331.  
  332.  
  333.       case HSCALE:
  334.       case VSCALE:
  335.  
  336.     back(x, dim) = b;  fwd(x, dim) = f;
  337.     if( (dim==COL) == (type(y)==HSCALE) )
  338.     { debug0(DSA, D, "] AdjustSize returning at HSCALE or VSCALE");
  339.       return;
  340.     }
  341.     break;
  342.  
  343.  
  344.       case SCALE:
  345.  
  346.     back(x, dim) = b;  fwd(x, dim) = f;
  347.     if( dim == COL )
  348.     { b *= bc(constraint(y)) / SF;
  349.       f *= bc(constraint(y)) / SF;
  350.     }
  351.     else
  352.     { b *= fc(constraint(y)) / SF;
  353.       f *= fc(constraint(y)) / SF;
  354.     }
  355.     break;
  356.  
  357.  
  358.       case ROTATE:
  359.       
  360.     back(x, dim) = b;  fwd(x, dim) = f;
  361.     RotateSize(&cby, &cfy, &rby, &rfy, x, sparec(constraint(y)));
  362.     if( cby != back(y, COL) || cfy != fwd(y, COL) )
  363.       AdjustSize(y, cby, cfy, COL);
  364.     if( rby != back(y, ROW) || rfy != fwd(y, ROW) )
  365.       AdjustSize(y, rby, rfy, ROW);
  366.     debug1(DSA, D, "] AdjustSize returning at %s.", Image(type(y)));
  367.     return;
  368.  
  369.  
  370.       case WIDE:
  371.       case HIGH:
  372.       
  373.     if( (type(y) == WIDE) == (dim == COL) )
  374.     { if( !FitsConstraint(b, f, constraint(y)) )
  375.       { Error(WARN, &fpos(y), "size constraint %s,%s,%s broken by %s,%s",
  376.           EchoLength(bc(constraint(y))), EchoLength(bfc(constraint(y))),
  377.           EchoLength(fc(constraint(y))), EchoLength(b), EchoLength(f));
  378.         SetConstraint(constraint(y), MAX_LEN, b+f, MAX_LEN);
  379.       }
  380.       back(x, dim) = b;  fwd(x, dim) = f;
  381.       EnlargeToConstraint(&b, &f, &constraint(y));
  382.     }
  383.     else
  384.     { back(x, dim) = b;
  385.       fwd(x, dim) = f;
  386.     }
  387.     break;
  388.  
  389.  
  390.       case COL_THR:
  391.       case ROW_THR:
  392.  
  393.     assert( (type(y)==COL_THR) == (dim==COL), "AdjustSize: COL_THR!" );
  394.     back(x, dim) = b;  fwd(x, dim) = f;
  395.     b = max(b, back(y, dim));
  396.     f = max(f, fwd(y, dim));
  397.     break;
  398.  
  399.  
  400.       case VCAT:
  401.       case HCAT:
  402.       case ACAT:
  403.  
  404.     if( (type(y) == VCAT) == (dim == ROW) )
  405.       CatAdjustSize(x, &b, &f, ratm, y, dim);
  406.     else
  407.     {
  408.       /* let lp and rp be the gaps bracketing the components joined to x */
  409.       for( lp = PrevDown(link);  lp != y;  lp = PrevDown(lp) )
  410.       { Child(z, lp);
  411.         if( type(z) == GAP_OBJ && !join(gap(z)) )  break;
  412.       }
  413.       for( rp = NextDown(link);  rp != y;  rp = NextDown(rp) )
  414.       { Child(z, rp);
  415.         if( type(z) == GAP_OBJ && !join(gap(z)) )  break;
  416.       }
  417.  
  418.       back(x, dim) = b;  fwd(x, dim) = f;
  419.       if( lp == y && rp == y )
  420.       {
  421.         /* if whole object is joined, do this */
  422.         b = max(b, back(y, dim));
  423.         f = max(f, fwd(y, dim));
  424.       }
  425.       else
  426.       { /* if // or || is present, do this */
  427.         tb = tf = 0;
  428.         for( link = NextDown(lp); link != rp;  link = NextDown(link) )
  429.         { Child(z, link);
  430.           if( type(z) == GAP_OBJ || is_index(type(z)) )  continue;
  431.           tb = max(tb, back(z, dim));
  432.           tf = max(tf, fwd(z, dim));
  433.         }
  434.         b = 0;  f = max(tb + tf, fwd(y, dim));
  435.       }
  436.     }
  437.     break;
  438.  
  439.  
  440.       case WORD:
  441.       case QWORD:
  442.       case CLOSURE:
  443.       case NULL_CLOS:
  444.       case CROSS:
  445.       default:
  446.       
  447.     Error(INTERN, &fpos(y), "AdjustSize: %s", Image(type(y)));
  448.     break;
  449.  
  450.     } /* end switch */
  451.     x = y;
  452.   } /* end while */
  453.   debug0(DSA, D, "] AdjustSize returning.");
  454. } /* end AdjustSize */
  455.