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

  1. /*@z18.c:Galley Transfer:Declarations@****************************************/
  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:         z18.c                                                      */
  26. /*  MODULE:       Galley Transfer                                            */
  27. /*  EXTERNS:      TransferInit(), TransferBegin(), TransferComponent(),      */
  28. /*                TransferEnd(), TransferClose()                             */
  29. /*                                                                           */
  30. /*****************************************************************************/
  31. #include "externs"
  32.  
  33. #define    MAX_DEPTH      30            /* max depth of galleys      */
  34. static OBJECT        root_galley = nil;    /* the root galley           */
  35. static OBJECT        targets[MAX_DEPTH];    /* currently open \Inputs    */
  36. static CONSTRAINT    constraints[MAX_DEPTH];    /* their COL constraints     */
  37. static int        itop;            /* stack top                 */
  38. static CONSTRAINT    initial_constraint;    /* initial COL constraint    */
  39. static STYLE        InitialStyle;        /* initial style             */
  40.  
  41. #if DEBUG_ON
  42. static debug_targets()
  43. { int i;  OBJECT tmp;
  44.   for( i = 0;  i <= itop;  i++ )
  45.   { if( targets[i] == nil || Down(targets[i]) == targets[i] )  tmp = nil;
  46.     else Child(tmp, Down(targets[i]));
  47.     debug3(DGT, D, "  target[%d] %s = %s", i,
  48.       EchoConstraint(&constraints[i]), EchoObject(tmp));
  49.   }
  50. } /* end debug_targets */
  51. #endif
  52.  
  53.  
  54. /*@::TransferInit()@**********************************************************/
  55. /*                                                                           */
  56. /*  TransferInit(InitEnv)                                                    */
  57. /*                                                                           */
  58. /*  Initialise this module.  The initial environment is InitEnv.             */
  59. /*                                                                           */
  60. /*****************************************************************************/
  61.  
  62. TransferInit(InitEnv)
  63. OBJECT InitEnv;
  64. { OBJECT dest, x, y, recs, inners, nothing, dest_index, up_hd;
  65.   debug1(DGT, D, "TransferInit( %s )", EchoObject(InitEnv));
  66.   SetConstraint(initial_constraint, MAX_LEN-1, MAX_LEN-1, MAX_LEN-1);
  67.  
  68.   /* save initial environment and style */
  69.   SetGap( line_gap(InitialStyle), FALSE, FALSE, FIXED_UNIT, MARK_MODE, 18*PT);
  70.   SetGap(space_gap(InitialStyle), FALSE, TRUE,  FIXED_UNIT, EDGE_MODE,  1*EM);
  71.   font(InitialStyle)            = 0;
  72.   hyph_style(InitialStyle)      = HYPH_UNDEF;
  73.   fill_style(InitialStyle)      = FILL_UNDEF;
  74.   display_style(InitialStyle)   = DISPLAY_UNDEF;
  75.  
  76.   /* construct destination for root galley */
  77.   up_hd = New(HEAD);
  78.   dest_index = New(RECEIVING);
  79.   dest = New(CLOSURE);  actual(dest) = PrintSym;
  80.   actual(dest_index) = dest;
  81.   external(dest) = TRUE;
  82.   threaded(dest) = FALSE;
  83.   blocked(dest_index) = FALSE;
  84.   Link(up_hd, dest_index);
  85.  
  86.   /* construct root galley */
  87.   root_galley = New(HEAD);
  88.   FposCopy(fpos(root_galley), *no_fpos);
  89.   actual(root_galley) = whereto(root_galley) = ready_galls(root_galley) = nil;
  90.   backward(root_galley) = must_expand(root_galley) = sized(root_galley) = FALSE;
  91.   x = New(CLOSURE);  actual(x) = InputSym;
  92.   Link(root_galley, x);
  93.   SizeGalley(root_galley, InitEnv, TRUE, FALSE, FALSE, FALSE, &InitialStyle,
  94.         &initial_constraint, nil, ¬hing, &recs, &inners);
  95.   assert( recs   == nil , "TransferInit: recs   != nil!" );
  96.   assert( inners == nil , "TransferInit: inners != nil!" );
  97.   Link(dest_index, root_galley);
  98.  
  99.   /* initialise target and constraint stacks */
  100.   Child(y, Down(root_galley));
  101.   assert( type(y) == RECEPTIVE && type(actual(y)) == CLOSURE &&
  102.     actual(actual(y)) == InputSym, "TransferInit: initial galley!" );
  103.   assert( external(actual(y)), "TransferInit: input sym not external!" );
  104.   blocked(y) = TRUE;
  105.   targets[itop = 0] = New(ACAT);
  106.   Link(targets[itop], y);
  107.   Constrained(actual(y), &constraints[itop], COL);
  108.   debug2(DSC, D, "Constrained( %s, COL ) = %s",
  109.     EchoObject(y), EchoConstraint(&constraints[itop]));
  110.  
  111.   debug0(DGT, D, "TransferInit returning.");
  112.   ifdebug(DGT, DD, debug_targets());
  113. } /* end TransferInit */
  114.  
  115.  
  116. /*@::TransferBegin()@*********************************************************/
  117. /*                                                                           */
  118. /*  OBJECT TransferBegin(x)                                                  */
  119. /*                                                                           */
  120. /*  Commence the transfer of a new galley whose header is invokation x.      */
  121. /*                                                                           */
  122. /*****************************************************************************/
  123.  
  124. OBJECT TransferBegin(x)
  125. OBJECT x;
  126. { OBJECT xsym, index, y, link, env, new_env, hold_env, res, hd, target;
  127.   CONSTRAINT c;
  128.   debug1(DGT, D, "TransferBegin( %s )", EchoObject(x));
  129.   ifdebug(DGT, DD, debug_targets());
  130.   assert( type(x) == CLOSURE, "TransferBegin: non-CLOSURE!" );
  131.  
  132.   /* add an automatically generated @Tag parameter to x if required */
  133.   CrossAddTag(x);
  134.  
  135.   /* construct new (inner) env chain */
  136.   if( Down(targets[itop]) == targets[itop] )
  137.       Error(FATAL, &fpos(x), "cannot attach galley %s", SymName(actual(x)));
  138.   Child(target, Down(targets[itop]));
  139.   xsym = actual(x);
  140.   env = GetEnv(actual(target));
  141.   debug1(DGT, DD, "  current env chain: %s", EchoObject(env));
  142.   if( has_body(xsym) )
  143.   {
  144.     /* prepare a copy of x for inclusion in environment */
  145.     y = CopyObject(x, no_fpos);
  146.  
  147.     /* attach its environment */
  148.     AttachEnv(env, y);
  149.  
  150.     /* now the new environment is y catenated with the old one */
  151.     debug0(DCR, DD, "calling SetEnv from TransferBegin (a)");
  152.     new_env = SetEnv(y, nil);
  153.   }
  154.   else new_env = env;
  155.   hold_env = New(ACAT);  Link(hold_env, new_env);
  156.   debug1(DGT, DD, "  new env chain: %s", EchoObject(new_env));
  157.  
  158.   /* convert x into an unsized galley called hd */
  159.   index = New(UNATTACHED);
  160.   hd = New(HEAD);
  161.   FposCopy(fpos(hd), fpos(x));
  162.   actual(hd) = xsym;
  163.   backward(hd) = TargetSymbol(x, &whereto(hd));
  164.   ready_galls(hd) = nil;
  165.   must_expand(hd) = TRUE;
  166.   sized(hd) = FALSE;
  167.   Link(index, hd);
  168.   Link(hd, x);
  169.   AttachEnv(env, x);
  170.  
  171.   /* search for destination for hd and release it */
  172.   Link(Up(target), index);
  173.   debug0(DGF, D, "  calling FlushGalley from TransferBegin");
  174.   FlushGalley(hd);
  175.  
  176.   /* if failed to flush, undo everything and exit */
  177.   Parent(index, Up(hd));
  178.   if( type(index) == UNATTACHED && !sized(hd) )
  179.   { DeleteNode(index);
  180.     DisposeObject(hold_env);
  181.     if( LastDown(x) != x )
  182.     { Child(env, LastDown(x));
  183.       if( type(env) == ENV )  DisposeChild(LastDown(x));
  184.     }
  185.     debug1(DGT,D, "TransferBegin returning failed, x: %s", EchoObject(x));
  186.     return x;
  187.   }
  188.  
  189.   if( has_rpar(actual(hd)) )
  190.   {
  191.     /* set up new target to be inner \InputSym, or nil if none */
  192.     if( ++itop >= MAX_DEPTH ) Error(FATAL, &fpos(x),
  193.     "galley nested too deeply (max is %d)", MAX_DEPTH);
  194.     targets[itop] = New(ACAT);  target = nil;
  195.     for( link = Down(hd);  link != hd;  link = NextDown(link) )
  196.     { Child(y, link);
  197.       if( type(y) == RECEPTIVE && actual(actual(y)) == InputSym )
  198.       {
  199.     Constrained(actual(y), &constraints[itop], COL);
  200.     if( FitsConstraint(0, 0, constraints[itop]) )
  201.     { Link(targets[itop], y);  target = y;
  202.       debug2(DSC, D, "Constrained( %s, COL ) = %s",
  203.         EchoObject(y), EchoConstraint(&constraints[itop]));
  204.       env = DetachEnv(actual(y));
  205.       AttachEnv(new_env, actual(y));
  206.     }
  207.     else
  208.     { Error(WARN, &fpos(hd), "galley %s deleted (target too narrow)",
  209.         SymName(actual(hd)));
  210.     }
  211.     break;
  212.       }
  213.     }
  214.  
  215.     /* return a token appropriate to the new target */
  216.     if( target == nil || external(actual(target)) )
  217.       res = NewToken(GSTUB_EXT, no_fpos, 0, 0, precedence(xsym), nil);
  218.     else
  219.     { Constrained(actual(target), &c, ROW);
  220.       if( constrained(c) )  Error(FATAL, &fpos(target),
  221.         "right parameter of %s is vertically constrained", SymName(xsym));
  222.       else res = NewToken(GSTUB_INT, no_fpos, 0, 0, precedence(xsym), nil);
  223.     }
  224.   }
  225.   else res = NewToken(GSTUB_NONE, no_fpos, 0, 0, precedence(xsym), nil);
  226.  
  227.   DisposeObject(hold_env);
  228.   debug1(DGT, D, "TransferBegin returning %s", Image(type(res)));
  229.   ifdebug(DGT, DD, debug_targets());
  230.   return res;
  231. } /* end TransferBegin */
  232.  
  233.  
  234. /*@::TransferComponent()@*****************************************************/
  235. /*                                                                           */
  236. /*  TransferComponent(x)                                                     */
  237. /*                                                                           */
  238. /*  Transfer component x of a galley.                                        */
  239. /*                                                                           */
  240. /*****************************************************************************/
  241.  
  242. TransferComponent(x)
  243. OBJECT x;
  244. { OBJECT y, env, start_search, recs, inners, nothing, hd, dest, dest_index;
  245.   debug1(DGT, D, "TransferComponent( %s )", EchoObject(x));
  246.   ifdebug(DGT, DD, debug_targets());
  247.  
  248.   /* if no dest_index, discard x and exit */
  249.   if( Down(targets[itop]) == targets[itop] )
  250.   { DisposeObject(x);
  251.     debug0(DGT, D, "TransferComponent returning (no target).");
  252.     return;
  253.   }
  254.   Child(dest_index, Down(targets[itop]));
  255.   assert( external(actual(dest_index)), "TransferComponent: internal!" );
  256.  
  257.   /* make the component into a galley */
  258.   hd = New(HEAD);
  259.   FposCopy(fpos(hd), fpos(x));
  260.   actual(hd) = whereto(hd) = ready_galls(hd) = nil;
  261.   backward(hd) = must_expand(hd) = sized(hd) = FALSE;
  262.   Link(hd, x);
  263.   dest = actual(dest_index);
  264.   env = GetEnv(dest);
  265.   debug1(DGT, DD, "  current env chain: %s", EchoObject(env));
  266.   SizeGalley(hd, env, TRUE, threaded(dest), FALSE, TRUE, &save_style(dest),
  267.     &constraints[itop], nil, ¬hing, &recs, &inners);
  268.   if( recs != nil )  ExpandRecursives(recs);
  269.  
  270.   /* promote the components, remembering where old spot was */
  271.   start_search = PrevDown(Up(dest_index));
  272.   debug0(DSA, D, "  calling AdjustSize from TransferComponent");
  273.   AdjustSize(dest, back(hd, COL), fwd(hd, COL), COL);
  274.   Promote(hd, hd, dest_index);
  275.   DeleteNode(hd);
  276.  
  277.   /* flush any widowed galleys attached to \Input */
  278.   if( Down(dest_index) != dest_index )
  279.   { OBJECT tinners, index;
  280.     tinners = New(ACAT);
  281.     while( Down(dest_index) != dest_index )
  282.     { Child(y, Down(dest_index));
  283.       assert( type(y) == HEAD, "TransferComponent: input child!" );
  284.       DetachGalley(y);
  285.       Parent(index, Up(y));
  286.       MoveLink(Up(index), NextDown(start_search), PARENT);
  287.       Link(tinners, index);
  288.     }
  289.     FlushInners(tinners, nil);
  290.   }
  291.  
  292.   /* flush any galleys inside hd */
  293.   if( inners != nil )  FlushInners(inners, nil);
  294.  
  295.   /* flush parent galley, if needed */
  296.   if( blocked(dest_index) )
  297.   { blocked(dest_index) = FALSE;
  298.     Parent(y, Up(dest_index));
  299.     debug0(DGF, D, "  calling FlushGalley from TransferComponent");
  300.     FlushGalley(y);
  301.   }
  302.   
  303.   debug0(DGT, D, "TransferComponent returning.");
  304.   ifdebug(DGT, DD, debug_targets());
  305. } /* end TransferComponent */
  306.  
  307.  
  308. /*@::TransferEnd()@***********************************************************/
  309. /*                                                                           */
  310. /*  TransferEnd(x)                                                           */
  311. /*                                                                           */
  312. /*  End the transfer of a galley.                                            */
  313. /*                                                                           */
  314. /*****************************************************************************/
  315.  
  316. TransferEnd(x)
  317. OBJECT x;
  318. { OBJECT recs, inners, nothing, z, env, dest, hd, dest_index, y, start_search;
  319.   debug1(DGT, D, "TransferEnd( %s )", EchoObject(x));
  320.   ifdebug(DGT, DD, debug_targets());
  321.  
  322.   /* if no dest_index, discard x and exit */
  323.   if( Down(targets[itop]) == targets[itop] )
  324.   { DisposeObject(x);  DisposeObject(targets[itop--]);
  325.     debug0(DGT, D, "TransferEnd returning: no dest_index");
  326.     return;
  327.   }
  328.   Child(dest_index, Down(targets[itop]));
  329.  
  330.   /* make the component into a galley */
  331.   hd = New(HEAD);  FposCopy(fpos(hd), fpos(x));
  332.   actual(hd) = whereto(hd) = ready_galls(hd) = nil;
  333.   backward(hd) = must_expand(hd) = sized(hd) = FALSE;
  334.   Link(hd, x);  dest = actual(dest_index);  env = GetEnv(dest);
  335.   debug1(DGT, DD, "  current env chain: %s", EchoObject(env));
  336.   SizeGalley(hd, env, external(dest), threaded(dest), FALSE, TRUE,
  337.     &save_style(dest), &constraints[itop], nil, ¬hing, &recs, &inners);
  338.   if( recs != nil )  ExpandRecursives(recs);
  339.  
  340.   /* promote the components, remembering where old spot was */
  341.   start_search = PrevDown(Up(dest_index));
  342.   debug0(DSA, D, "calling AdjustSize from TransferEnd (a)");
  343.   AdjustSize(dest, back(hd, COL), fwd(hd, COL), COL);
  344.   if( !external(dest) )
  345.   { Child(z, LastDown(hd));
  346.     debug0(DSA, D, "calling AdjustSize from TransferEnd (b)");
  347.     AdjustSize(dest, back(z, ROW), fwd(z, ROW), ROW);
  348.     Interpose(dest, VCAT, hd, z);
  349.   }
  350.   Promote(hd, hd, dest_index);  DeleteNode(hd);
  351.  
  352.   /* flush any widowed galleys attached to \Input */
  353.   if( Down(dest_index) != dest_index )
  354.   { OBJECT tinners, index;
  355.     tinners = New(ACAT);
  356.     while( Down(dest_index) != dest_index )
  357.     { Child(y, Down(dest_index));
  358.       assert( type(y) == HEAD, "TransferComponent: input child!" );
  359.       DetachGalley(y);
  360.       Parent(index, Up(y));
  361.       MoveLink(Up(index), NextDown(start_search), PARENT);
  362.       Link(tinners, index);
  363.     }
  364.     FlushInners(tinners, nil);
  365.   }
  366.  
  367.   /* flush any galleys inside hd */
  368.   if( inners != nil )  FlushInners(inners, nil);
  369.  
  370.   /* close dest_index, and flush parent galley if needed */
  371.   if( blocked(dest_index) )
  372.   { Parent(y, Up(dest_index));
  373.     DeleteNode(dest_index);
  374.     debug0(DGF, D, "  calling FlushGalley from TransferEnd");
  375.     FlushGalley(y);
  376.   }
  377.   else DeleteNode(dest_index);
  378.   
  379.   /* pop target stack and exit */
  380.   DisposeObject(targets[itop--]);
  381.   debug0(DGT, D, "TransferEnd returning.");
  382.   ifdebug(DGT, DD, debug_targets());
  383. } /* end TransferEnd */
  384.  
  385. /*@::TransferClose()@*********************************************************/
  386. /*                                                                           */
  387. /*  TransferClose()                                                          */
  388. /*                                                                           */
  389. /*  Close this module.                                                       */
  390. /*                                                                           */
  391. /*****************************************************************************/
  392.  
  393. TransferClose()
  394. { OBJECT inners;
  395.   debug0(DGT, D, "TransferClose()");
  396.   debug0(DGA, D, "  calling FreeGalley from TransferClose");
  397.   if( LastDown(root_galley) != root_galley )
  398.   { inners = nil;
  399.     FreeGalley(root_galley, root_galley, &inners, nil, nil);
  400.     if( inners != nil )  FlushInners(inners, nil);
  401.     debug0(DGF, D, "  calling FlushGalley from TransferClose");
  402.     FlushGalley(root_galley);
  403.   }
  404.   debug0(DGT, D, "TransferClose returning.");
  405. }
  406.