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

  1. /*@z19.c:Galley Attaching:DetachGalley()@*************************************/
  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:         z19.c                                                      */
  26. /*  MODULE:       Galley Attaching                                           */
  27. /*  EXTERNS:      SearchGalley(), AttachGalley(), DetachGalley()             */
  28. /*                                                                           */
  29. /*****************************************************************************/
  30. #include "externs"
  31.  
  32.  
  33. /*****************************************************************************/
  34. /*                                                                           */
  35. /*  DetachGalley(hd)                                                         */
  36. /*                                                                           */
  37. /*  Detach galley hd from its target.                                        */
  38. /*                                                                           */
  39. /*****************************************************************************/
  40.  
  41. DetachGalley(hd)
  42. OBJECT hd;
  43. { OBJECT prnt, index;
  44.   debug1(DGA, D, "DetachGalley( %s )", EchoObject(hd));
  45.   assert( type(hd) == HEAD && Up(hd) != hd, "DetachGalley: precondition!" );
  46.   Parent(prnt, Up(hd));
  47.   assert( Up(prnt) != prnt, "DetachGalley: parent!" );
  48.   index = New(UNATTACHED);
  49.   MoveLink(Up(hd), index, PARENT);
  50.   Link(NextDown(Up(prnt)), index);
  51.   debug0(DGA, D, "DetachGalley returning.");
  52. } /* end DetachGalley */
  53.  
  54.  
  55. /*@::SearchGalley()@**********************************************************/
  56. /*                                                                           */
  57. /*  OBJECT SearchGalley(start, sym, forwards, subgalleys, closures, input)   */
  58. /*                                                                           */
  59. /*  Search a galley and its sub-galleys for a target which uses sym.  The    */
  60. /*  meanings of the flags are as follows:                                    */
  61. /*                                                                           */
  62. /*    forwards     If TRUE, search forwards from just after start, else      */
  63. /*                 search backwards from just before start                   */
  64. /*    subgalleys   If TRUE, search down into sub-galleys of this galley      */
  65. /*    closures     If TRUE, closures in this galley are acceptable results   */
  66. /*    input        If TRUE, InputSym is an acceptable result                 */
  67. /*                                                                           */
  68. /*****************************************************************************/
  69.  
  70. OBJECT SearchGalley(start, sym, forwards, subgalleys, closures, input)
  71. OBJECT start, sym;  BOOLEAN forwards, subgalleys, closures, input;
  72. { OBJECT y, res, z, zlink, link;
  73.   debug5(DGA, D, "[SearchGalley( start, %s, %s, %s, %s, %s )", SymName(sym),
  74.     forwards ? "fwd" : "back", subgalleys ? "subgalleys" : "nosubgalleys",
  75.     closures ? "closures" : "noclosures", input ? "input" : "noinput");
  76.   assert( type(start) == LINK || type(start) == HEAD, "SearchGalley: start!" );
  77.  
  78.   link = forwards ? NextDown(start) : PrevDown(start);
  79.   res = nil;
  80.   while( res == nil && type(link) != HEAD )
  81.   { Child(y, link);
  82.     debug1(DGA, DD, "  examining %s", EchoObject(y));
  83.     switch( type(y) )
  84.     {
  85.       case UNATTACHED:
  86.       case RECEIVING:
  87.     
  88.     if( subgalleys )
  89.     for( zlink = Down(y); zlink!=y && res==nil;  zlink = NextDown(zlink) )
  90.     { Child(z, zlink);
  91.       res = SearchGalley(z, sym, TRUE, TRUE, TRUE, input);
  92.     }
  93.     if( !res && input && type(y)==RECEIVING && actual(actual(y))==InputSym )
  94.       res = y;
  95.     break;
  96.  
  97.  
  98.       case RECEPTIVE:
  99.     
  100.     if( closures && type(actual(y)) == CLOSURE
  101.              && SearchUses(actual(actual(y)), sym) )  res = y;
  102.     else if( input && actual(actual(y)) == InputSym )  res = y;
  103.     break;
  104.  
  105.  
  106.       default:
  107.     
  108.     break;
  109.  
  110.     }
  111.     link = forwards ? NextDown(link) : PrevDown(link);
  112.   }
  113.   debug1(DGA, D, "]SearchGalley returning %s", EchoObject(res));
  114.   return res;
  115. } /* end SearchGalley */
  116.  
  117.  
  118. /*@@**************************************************************************/
  119. /*                                                                           */
  120. /*  AttachGalley(hd, inners)                                                 */
  121. /*                                                                           */
  122. /*  Attach galley hd, which may be unsized, to a destination.  This involves */
  123. /*  searching for a destination forward or back from the attachment point of */
  124. /*  hd and promoting up to and including the first definite component of hd. */
  125. /*                                                                           */
  126. /*  Although AttachGalley never flushes any galleys, it may identify some    */
  127. /*  galleys which should be flushed, even if the attach is itself not        */
  128. /*  successful.  These are returned in *inners, or nil if none.              */
  129. /*                                                                           */
  130. /*****************************************************************************/
  131.  
  132. AttachGalley(hd, inners)
  133. OBJECT hd, *inners;
  134. { OBJECT index;            /* the index of hd in the enclosing galley   */
  135.   OBJECT hd_inners;        /* inner galleys of hd, if unsized           */
  136.   OBJECT dest;            /* the target @Galley hd empties into        */
  137.   OBJECT dest_index;        /* the index of dest                         */
  138.   OBJECT target;        /* the target indefinite containing dest     */
  139.   OBJECT target_index;        /* the index of target                       */
  140.   OBJECT target_galley;        /* the body of target, made into a galley    */
  141.   OBJECT tg_inners;        /* inner galleys of target_galley            */
  142.   BOOLEAN need_precedes;    /* true if destination lies before galley    */
  143.   OBJECT recs;            /* list of recursive definite objects        */
  144.   OBJECT link, y;        /* for scanning through the components of hd */
  145.   CONSTRAINT c;            /* temporary variable holding a constraint   */
  146.   OBJECT env, n1, tmp, zlink, z, sym;    /* placeholders and temporaries         */
  147.   BOOLEAN was_sized;        /* true if sized(hd) initially               */
  148.  
  149.   debug2(DGA, D, "[AttachGalley(Galley %s into %s)",
  150.     SymName(actual(hd)), SymName(whereto(hd)));
  151.   ifdebug(DGA, DD, DebugObject(hd));
  152.   assert( Up(hd) != hd, "AttachGalley: no index!" );
  153.   Parent(index, Up(hd));
  154.   assert( type(index) == UNATTACHED, "AttachGalley: not UNATTACHED!" );
  155.   *inners = hd_inners = tg_inners = nil;
  156.   was_sized = sized(hd);
  157.  
  158.   for(;;)
  159.   {
  160.     /*************************************************************************/
  161.     /*                                                                       */
  162.     /*  Search for a destination for hd.  If hd is unsized, search for       */
  163.     /*  inner galleys preceding it first of all, then for receptive objects  */
  164.     /*  following it, possibly in inner galleys.  If no luck, exit.          */
  165.     /*  If hd is sized, search only for receptive objects in the current     */
  166.     /*  galley below the current spot, and fail if cannot find any.          */
  167.     /*                                                                       */
  168.     /*************************************************************************/
  169.  
  170.     sym = whereto(hd);
  171.     if( sized(hd) )
  172.     {
  173.       /* sized galley case: search on from current spot */
  174.       target_index = SearchGalley(Up(index), sym, TRUE, FALSE, TRUE, TRUE);
  175.       if( target_index == nil )
  176.       {    
  177.     /* search failed to find any new target, so kill the galley */
  178.     for( link = Down(hd); link != hd; link = NextDown(link) )
  179.     { Child(y, link);
  180.       if( type(y) == SPLIT )  Child(y, DownDim(y, ROW));
  181.       if( is_definite(type(y)) )  break;
  182.     }
  183.     if( link != hd )
  184.         Error(WARN, &fpos(y), "galley %s deleted from here: no target",
  185.         SymName(actual(hd)));
  186.     debug0(DGA, D, "calling KillGalley from AttachGalley (a)");
  187.     KillGalley(hd);
  188.     debug0(DGA, D, "]AttachGalley returning: no target for sized galley");
  189.     return;
  190.       }
  191.       else if( actual(actual(target_index)) == InputSym )
  192.       {
  193.     /* search found input object, so suspend on that */
  194.     DeleteNode(index);
  195.     Link(target_index, hd);
  196.     debug0(DGA, D, "]AttachGalley returning: InputSym");
  197.     return;
  198.       }
  199.  
  200.     }
  201.     else /* unsized galley, either backwards or normal */
  202.     {
  203.       if( backward(hd) )
  204.       {    target_index= SearchGalley(Up(index), sym, FALSE, TRUE, TRUE, FALSE);
  205.     need_precedes = FALSE;
  206.       }
  207.       else
  208.       {    target_index = SearchGalley(Up(index), sym, FALSE, TRUE, FALSE, FALSE);
  209.     need_precedes = (target_index != nil);
  210.     if( target_index == nil )
  211.       target_index = SearchGalley(Up(index), sym, TRUE, TRUE, TRUE, FALSE);
  212.       }
  213.  
  214.       /* if no luck, exit without error */
  215.       if( target_index == nil )
  216.       {    debug0(DGA, D, "]AttachGalley returning: no target for unsized galley");
  217.     return;
  218.       }
  219.     }
  220.     assert( type(target_index) == RECEPTIVE, "AttachGalley: target_index!" );
  221.     target = actual(target_index);
  222.     assert( type(target) == CLOSURE, "AttachGalley: target!" );
  223.  
  224.     /* set target_galley to the expanded value of target */
  225.     EnterErrorBlock(FALSE);
  226.     target_galley = New(HEAD);
  227.     FposCopy(fpos(target_galley), fpos(target));
  228.     actual(target_galley) = actual(target);
  229.     whereto(target_galley) = ready_galls(target_galley) = nil;
  230.     backward(target_galley) = must_expand(target_galley) = FALSE;
  231.     sized(target_galley) = FALSE;
  232.     Constrained(target, &c, COL);
  233.     if( !constrained(c) )  Error(FATAL, &fpos(target),
  234.        "receptive symbol %s has unconstrained width", SymName(actual(target)));
  235.     debug2(DSC, D, "Constrained( %s, COL ) = %s",
  236.     EchoObject(target), EchoConstraint(&c));
  237.     debug1(DGA, DD, "  expanding %s", EchoObject(target));
  238.     tmp = CopyObject(target, no_fpos);
  239.     Link(target_galley, tmp);
  240.     if( !FitsConstraint(0, 0, c) )
  241.     { debug0(DGA, D, "  reject: target_galley horizontal constraint is -1");
  242.       goto REJECT;
  243.     }
  244.     env = DetachEnv(tmp);
  245.     SizeGalley(target_galley, env, external(target), threaded(target),
  246.     non_blocking(target_index), trigger_externs(target_index),
  247.     &save_style(target), &c, whereto(hd), &dest_index, &recs, &tg_inners);
  248.     if( recs != nil )  ExpandRecursives(recs);
  249.     dest = actual(dest_index);
  250.  
  251.     /* verify that hd satisfies any horizontal constraint on dest */
  252.     debug1(DGA, DD, "  checking COL fit of hd in %s", SymName(actual(dest)));
  253.     Constrained(dest, &c, COL);
  254.     debug2(DSC, D, "Constrained( %s, COL ) = %s",
  255.     EchoObject(dest), EchoConstraint(&c));
  256.     assert( constrained(c), "AttachGalley: dest unconstrained!" );
  257.     if( !sized(hd) )
  258.     { EnterErrorBlock(TRUE);
  259.       if( !FitsConstraint(0, 0, c) )
  260.       {    debug0(DGA, D, "  reject: hd horizontal constraint is -1");
  261.     goto REJECT;
  262.       }
  263.       n1 = nil;
  264.       Child(y, Down(hd));
  265.       env = DetachEnv(y);
  266.       /*** to set non_blocking() to FALSE seems doubtful!
  267.       SizeGalley(hd, env, TRUE, threaded(dest), FALSE, TRUE,
  268.         &save_style(dest), &c, nil, &n1, &recs, &hd_inners);
  269.       *** */
  270.       SizeGalley(hd, env, TRUE, threaded(dest), non_blocking(target_index),
  271.     TRUE, &save_style(dest), &c, nil, &n1, &recs, &hd_inners);
  272.       if( recs != nil )  ExpandRecursives(recs);
  273.       if( need_precedes )        /* need an ordering constraint */
  274.       {    OBJECT index1 = New(PRECEDES);
  275.     OBJECT index2 = New(FOLLOWS);
  276.     blocked(index2) = FALSE;
  277.     tmp = MakeWord(WORD, STR_EMPTY, no_fpos);
  278.     Link(index1, tmp);  Link(index2, tmp);
  279.     Link(Up(index), index1);
  280.     Link(Down(hd), index2);
  281.     debug0(DGA, D, "  inserting PRECEDES and FOLLOWS");
  282.       }
  283.       LeaveErrorBlock(TRUE);
  284.     }
  285.     if( !FitsConstraint(back(hd, COL), fwd(hd, COL), c) )
  286.     { debug3(DGA, D, "  reject: hd %s,%s does not fit target_galley %s",
  287.     EchoLength(back(hd, COL)), EchoLength(fwd(hd, COL)),
  288.     EchoConstraint(&c));
  289.       Error(WARN, &fpos(hd),"too little horizontal space for galley %s at %s",
  290.     SymName(actual(hd)), SymName(actual(dest)));
  291.       goto REJECT;
  292.     }
  293.  
  294.     /* check status of first component of hd */
  295.     debug0(DGA, DD, "  now ready to attach; hd =");
  296.     ifdebug(DGA, DD, DebugObject(hd));
  297.     for( link = Down(hd);  link != hd;  link = NextDown(link) )
  298.     {
  299.       Child(y, link);
  300.       debug1(DGA, DD, "  examining %s", EchoObject(y));
  301.       if( type(y) == SPLIT )  Child(y, DownDim(y, ROW));
  302.       switch( type(y) )
  303.       {
  304.  
  305.     case EXPAND_IND:
  306.     case GALL_PREC:
  307.     case GALL_FOLL:
  308.     case GALL_TARG:
  309.     case CROSS_PREC:
  310.     case CROSS_FOLL:
  311.     case CROSS_TARG:
  312.         
  313.       break;
  314.  
  315.  
  316.     case PRECEDES:
  317.     case UNATTACHED:
  318.         
  319.       if( was_sized )
  320.       { /* SizeGalley was not called, so hd_inners was not set by it */
  321.         if( hd_inners == nil )  hd_inners = New(ACAT);
  322.         Link(hd_inners, y);
  323.       }
  324.       break;
  325.  
  326.  
  327.     case RECEPTIVE:
  328.  
  329.       if( non_blocking(y) )
  330.       { link = PrevDown(link);
  331.         DeleteNode(y);
  332.       }
  333.       else goto SUSPEND;
  334.       break;
  335.  
  336.  
  337.     case RECEIVING:
  338.         
  339.       if( non_blocking(y) )
  340.       { while( Down(y) != y )
  341.         { Child(z, Down(y));
  342.           DetachGalley(z);
  343.           KillGalley(z);
  344.         }
  345.         link = PrevDown(link);
  346.         DeleteNode(y);
  347.       }
  348.       else goto SUSPEND;
  349.       break;
  350.  
  351.  
  352.     case FOLLOWS:
  353.         
  354.       Child(tmp, Down(y));
  355.       if( Up(tmp) == LastUp(tmp) )
  356.       { link = pred(link, CHILD);
  357.         debug0(DGA, DD, "  disposing FOLLOWS");
  358.         DisposeChild(NextDown(link));
  359.         break;
  360.       }
  361.       Parent(tmp, Up(tmp));
  362.       assert(type(tmp) == PRECEDES, "Attach: PRECEDES!");
  363.       switch( CheckConstraint(tmp, target_index) )
  364.       {
  365.         case CLEAR:        DeleteNode(tmp);
  366.                 link = pred(link, CHILD);
  367.                 DisposeChild(NextDown(link));
  368.                 break;
  369.  
  370.         case PROMOTE:    break;
  371.  
  372.         case BLOCK:        debug0(DGA, DD, "CheckContraint: BLOCK");
  373.                 goto SUSPEND;
  374.  
  375.         case CLOSE:        debug0(DGA, D, "  reject: CheckContraint");
  376.                 goto REJECT;
  377.       }
  378.       break;
  379.  
  380.  
  381.     case GAP_OBJ:
  382.  
  383.       if( !join(gap(y)) )  seen_nojoin(hd) = TRUE;
  384.       break;
  385.  
  386.  
  387.     case CLOSURE:
  388.     case NULL_CLOS:
  389.     case CROSS:
  390.  
  391.       break;
  392.  
  393.  
  394.     case WORD:
  395.     case QWORD:
  396.     case ONE_COL:
  397.     case ONE_ROW:
  398.     case WIDE:
  399.     case HIGH:
  400.     case HSCALE:
  401.     case VSCALE:
  402.     case HCONTRACT:
  403.     case VCONTRACT:
  404.     case HEXPAND:
  405.     case VEXPAND:
  406.     case PADJUST:
  407.     case HADJUST:
  408.     case VADJUST:
  409.     case ROTATE:
  410.     case SCALE:
  411.     case INCGRAPHIC:
  412.     case SINCGRAPHIC:
  413.     case GRAPHIC:
  414.     case ACAT:
  415.     case HCAT:
  416.     case ROW_THR:
  417.         
  418.       /* make sure y is not joined to a target below */
  419.       for( zlink = NextDown(link);  zlink != hd;  zlink = NextDown(zlink) )
  420.       { Child(z, zlink);
  421.         switch( type(z) )
  422.         {
  423.           case RECEPTIVE:    if( non_blocking(z) )
  424.                 { zlink = PrevDown(zlink);
  425.                   DeleteNode(z);
  426.                 }
  427.                 else
  428.                 { y = z;
  429.                   goto SUSPEND;
  430.                 }
  431.                 break;
  432.  
  433.           case RECEIVING:    if( non_blocking(z) )
  434.                 { zlink = PrevDown(zlink);
  435.                   while( Down(z) != z )
  436.                   { Child(tmp, Down(y));
  437.                     DetachGalley(tmp);
  438.                     KillGalley(tmp);
  439.                   }
  440.                   DeleteNode(z);
  441.                 }
  442.                 else
  443.                 { y = z;
  444.                   goto SUSPEND;
  445.                 }
  446.                 break;
  447.  
  448.           case GAP_OBJ:    if( !join(gap(z)) )  zlink = PrevDown(hd);
  449.                 break;
  450.  
  451.           default:        break;
  452.         }
  453.       }
  454.  
  455.       /* check availability of vertical space for the first component */
  456.       if( !external(dest) )
  457.       { Constrained(dest, &c, ROW);
  458.         debug2(DSC, D, "Constrained( %s, ROW ) = %s",
  459.           EchoObject(dest), EchoConstraint(&c));
  460.         if( !FitsConstraint(back(y, ROW), fwd(y, ROW), c) )
  461.         { Error(WARN, &fpos(y),
  462.         "this component of %s did not fit into its nearest target",
  463.         SymName(actual(hd)));
  464.           debug3(DGA, D, "  reject: vsize %s,%s in %s; y=",
  465.         EchoLength(back(y, ROW)), EchoLength(fwd(y, ROW)),
  466.         EchoConstraint(&c));
  467.           ifdebug(DGA, D, DebugObject(y));
  468.           goto REJECT;
  469.         }
  470.         debug0(DSA, D, "calling AdjustSize from AttachGalley (a)");
  471.         AdjustSize(dest, back(y, ROW), fwd(y, ROW), ROW);
  472.       }
  473.       if( !external(target) )
  474.       { Constrained(target, &c, ROW);
  475.         debug2(DSC, D, "Constrained( %s, ROW ) = %s",
  476.             EchoObject(target), EchoConstraint(&c));
  477.         Child(z, LastDown(target_galley));
  478.         assert( !is_index(type(z)), "AttachGalley: is_index(z)!" );
  479.         assert( back(z, ROW) >= 0 && fwd(z, ROW) >= 0,
  480.             "AttachGalley: negative z sizes!" );
  481.         if( !FitsConstraint(back(z, ROW), fwd(z, ROW), c) )
  482.         { Error(WARN, &fpos(y),
  483.         "this component of %s did not fit into its nearest target",
  484.         SymName(actual(hd)));
  485.           debug3(DGA, D, "  reject: size was %s,%s in %s; y =",
  486.         EchoLength(back(z, ROW)), EchoLength(fwd(z, ROW)),
  487.         EchoConstraint(&c));
  488.           ifdebug(DGA, D, DebugObject(y));
  489.           goto REJECT;
  490.         }
  491.         debug0(DSA, D, "calling AdjustSize from AttachGalley (b)");
  492.         AdjustSize(target, back(z, ROW), fwd(z, ROW), ROW);
  493.       }
  494.       goto ACCEPT;
  495.  
  496.  
  497.     default:
  498.         
  499.       Error(INTERN, &fpos(y), "AttachGalley: %s", Image(type(y)));
  500.       break;
  501.  
  502.       } /* end switch */
  503.     } /* end for */
  504.  
  505.     /* empty galley; promote any indexes, kill the galley, and exit */
  506.     /* this bypasses target_galley, which is not expanded in the empty case */
  507.     debug0(DGA, D, "  empty galley");
  508.     if( tg_inners != nil )  DisposeObject(tg_inners), tg_inners = nil;
  509.     DisposeObject(target_galley);
  510.     LeaveErrorBlock(FALSE);
  511.     if( LastDown(hd) != hd )  Promote(hd, hd, target_index);
  512.     debug0(DGA, D, "calling KillGalley from AttachGalley (b)");
  513.     KillGalley(hd);
  514.  
  515.     /* return; only hd_inners needs to be flushed now */
  516.     *inners = hd_inners;
  517.     debug0(DGA, D, "]AttachGalley returning killed: empty galley");
  518.     return;
  519.  
  520.  
  521.     REJECT:
  522.     
  523.       /* reject first component */
  524.       LeaveErrorBlock(TRUE);
  525.       if( tg_inners != nil )  DisposeObject(tg_inners), tg_inners = nil;
  526.       DisposeObject(target_galley);
  527.       if( backward(hd) && !sized(hd) )
  528.       {
  529.     /* move to just before the failed target */
  530.     MoveLink(Up(index), Up(target_index), PARENT);
  531.       }
  532.       else
  533.       {
  534.     /* move to just after the failed target */
  535.     MoveLink(Up(index), NextDown(Up(target_index)), PARENT);
  536.       }
  537.       continue;
  538.  
  539.  
  540.     SUSPEND:
  541.     
  542.       /* suspend at first component */
  543.       debug1(DGA, D, "  suspend %s", EchoObject(y));
  544.       blocked(y) = TRUE;
  545.       LeaveErrorBlock(FALSE);
  546.       if( tg_inners != nil )  DisposeObject(tg_inners), tg_inners = nil;
  547.       DisposeObject(target_galley);
  548.       MoveLink(Up(index), Up(target_index), PARENT);
  549.       if( was_sized )
  550.       { /* nothing new to flush if suspending and already sized */
  551.     if( hd_inners != nil )  DisposeObject(hd_inners), hd_inners = nil;
  552.       }
  553.       else
  554.       { /* flush newly discovered inners if not sized before */
  555.     *inners = hd_inners;
  556.       }
  557.       debug0(DGA, D, "]AttachGalley returning: suspending.");
  558.       return;
  559.  
  560.  
  561.     ACCEPT:
  562.     
  563.       /* accept first component; now committed to the attach */
  564.       debug1(DGA, D, "  accept %s", EchoObject(y));
  565.       LeaveErrorBlock(TRUE);
  566.  
  567.       /* adjust horizontal sizes */
  568.       debug0(DSA, D, "calling AdjustSize from AttachGalley (c)");
  569.       AdjustSize(dest, back(hd, COL), fwd(hd, COL), COL);
  570.       debug0(DSA, D, "calling AdjustSize from AttachGalley (d)");
  571.       AdjustSize(target, back(target_galley, COL),
  572.                 fwd(target_galley, COL), COL);
  573.         
  574.       /* attach hd to dest */
  575.       MoveLink(Up(hd), dest_index, PARENT);
  576.       assert( type(index) == UNATTACHED, "AttachGalley: type(index)!" );
  577.       DeleteNode(index);
  578.  
  579.       /* move first component of hd into dest */
  580.       /* nb Interpose must be done after all AdjustSize calls */
  581.       if( !external(dest) )   Interpose(dest, VCAT, hd, y);
  582.       Promote(hd, NextDown(link), dest_index);
  583.  
  584.       /* move target_galley into target */
  585.       /* nb Interpose must be done after all AdjustSize calls */
  586.       if( !external(target) )
  587.       {    Child(z, LastDown(target_galley));
  588.     Interpose(target, VCAT, z, z);
  589.       }
  590.       Promote(target_galley, target_galley, target_index);
  591.       DeleteNode(target_galley);
  592.       assert(Down(target_index)==target_index, "AttachGalley: target_ind");
  593.       if( blocked(target_index) )  blocked(dest_index) = TRUE;
  594.       DeleteNode(target_index);
  595.  
  596.       /* return; both tg_inners and hd_inners need to be flushed now;        */
  597.       /* if was_sized, hd_inners contains the inners of the first component; */
  598.       /* otherwise it contains the inners of all components, from SizeGalley */
  599.       if( tg_inners == nil ) *inners = hd_inners;
  600.       else if( hd_inners == nil ) *inners = tg_inners;
  601.       else
  602.       {    TransferLinks(Down(hd_inners), hd_inners, tg_inners);
  603.     DeleteNode(hd_inners);
  604.     *inners = tg_inners;
  605.       }
  606.       debug0(DGA, D, "]AttachGalley returning (accept)");
  607.       return;
  608.  
  609.   } /* end for */
  610. } /* end AttachGalley */
  611.