home *** CD-ROM | disk | FTP | other *** search
/ The Best of Mecomp Multimedia 2 / MECOMP-CD-II.iso / amiga / datatypes / embed_datatype / dispatch.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-10-13  |  83.5 KB  |  2,498 lines

  1.  
  2. /*
  3. **
  4. **  $VER: dispatch.c 1.3 (12.10.97)
  5. **  embed.datatype 1.3
  6. **
  7. **  Dispatch routine for a DataTypes class
  8. **
  9. **  Written 1996/1997 by Roland 'Gizzy' Mainz
  10. **  Original example source from David N. Junod
  11. **
  12. */
  13.  
  14. /* main includes */
  15. #include "classbase.h"
  16.  
  17. /*****************************************************************************/
  18. /* Source configuration */
  19.  
  20. #define DRAW_BOX_AROUND_OBJECT 1
  21.  
  22. /*****************************************************************************/
  23.  
  24. #define EMBEDA_Dummy            (TAG_USER + 0x002B2000UL)
  25. #define EMBEDA_Sync             (EMBEDA_Dummy + 1UL)
  26. #define EMBEDA_SyncObjectLine   (EMBEDA_Dummy + 2UL)
  27.  
  28. /*****************************************************************************/
  29.  
  30. /* local prototypes */
  31. static struct GadgetInfo       *CreateGadgetInfoClipBuffer( struct ClassBase *, struct GadgetInfo *, struct EmbedLine * );
  32. static void                     FreeGadgetInfoClipBuffer( struct ClassBase *, struct GadgetInfo * );
  33. static void                     SyncGadgetInfoClipBuffer( struct ClassBase *, struct GadgetInfo *, struct GadgetInfo *, struct EmbedLine * );
  34. static BOOL                     IsKindOf( struct ClassBase *, Object *, struct IClass *, ClassID );
  35.  
  36. /*****************************************************************************/
  37.  
  38. /* A single line segment in our object */
  39. struct EmbedLine
  40. {
  41.     struct Line     el_Line;
  42.     struct MinNode  el_VisibleLink;
  43.     struct IBox     el_LineBox;
  44.     struct IBox     el_VisibleBox;
  45.     ULONG           el_TopVert;
  46.     ULONG           el_TopHoriz;
  47.     Object         *el_Object;  /* datatypesclass object */
  48.     struct BitMap  *el_ObjectBitMap;
  49.     BOOL            el_IsDTObject;
  50.     BOOL            el_ObjectCanClip;
  51.     BOOL            el_ObjectIsClipped;
  52.     BOOL            el_Pad0;
  53.     Object         *el_Model;   /* model */
  54. };
  55.  
  56. #define VisibleLink2EmbedLine( vl ) ((struct EmbedLine *)(((UBYTE *)(vl)) - offsetof( struct EmbedLine, el_VisibleLink )))
  57.  
  58. /* embed.datatype instance data */
  59. struct EmbedInstData
  60. {
  61.     APTR              eid_Pool;             /* Object memory pool (misc usage)          */
  62.     LONG              eid_OldTopVert;       /* Last layouted position */
  63.     LONG              eid_OldTopHoriz;      /* Last layouted position */
  64.     struct IBox       eid_OldParentDomain;  /* Old parent (win/req/grp) domain */
  65.     struct MinList   *eid_LineList;
  66.     struct MinList    eid_VisibleMembers;
  67.  
  68.     struct EmbedLine *eid_HitMemberLine;
  69.     struct EmbedLine *eid_HelpMemberLine;
  70.     ULONG             eid_HelpMemberCode;
  71.     ULONG             eid_HelpMemberReturnedCode;
  72.     struct EmbedLine *eid_ActiveMemberLine;
  73. };
  74.  
  75. /*****************************************************************************/
  76.  
  77. /* Embed model, which saves some usefull object data */
  78. struct EmbedModelInstData
  79. {
  80.     struct EmbedLine   *emid_ObjectLine;
  81.     BOOL                emid_Sync;
  82.     BOOL                emid_Busy;
  83. };
  84.  
  85. /*****************************************************************************/
  86.  
  87.  
  88. BOOL initClass( struct ClassBase *cb )
  89. {
  90.     struct IClass *cl;
  91.  
  92.     /* Create our classes... */
  93.     if( cl = MakeClass( NULL, MODELCLASS, NULL, (ULONG)sizeof( struct EmbedModelInstData ), 0UL ) )
  94.     {
  95.       cl -> cl_Dispatcher . h_Entry = (HOOKFUNC)DispatchModel;
  96.       cl -> cl_UserData             = (ULONG)cb;
  97.  
  98.       cb -> cb_EmbedModel = cl; /* store class ptr */
  99.  
  100.       if( cl = MakeClass( EMBEDDTCLASS, TEXTDTCLASS, NULL, (ULONG)sizeof( struct EmbedInstData ), 0UL ) )
  101.       {
  102.         cl -> cl_Dispatcher . h_Entry = (HOOKFUNC)Dispatch;
  103.         cl -> cl_UserData             = (ULONG)cb;
  104.  
  105.         cb -> cb_Lib . cl_Class = cl; /* store class ptr */
  106.  
  107.         AddClass( cl );
  108.  
  109.         return( TRUE );
  110.       }
  111.       else
  112.       {
  113.         FreeClass( (cb -> cb_EmbedModel) );
  114.         cb -> cb_EmbedModel = NULL;
  115.       }
  116.     }
  117.  
  118.     return( FALSE );
  119. }
  120.  
  121. /*****************************************************************************/
  122.  
  123. void mysprintf( struct ClassBase *cb, STRPTR buffer, STRPTR fmt, ... )
  124. {
  125.     APTR args;
  126.  
  127.     args = (APTR)((&fmt) + 1);
  128.  
  129.     RawDoFmt( fmt, args, (void (*))"\x16\xc0\x4e\x75", buffer );
  130. }
  131.  
  132.  
  133. /*****************************************************************************/
  134.  
  135. struct MyStackSwapStruct
  136. {
  137.     struct StackSwapStruct  stk;
  138.     struct IClass          *cl;
  139.     Object                 *o;
  140.     Msg                     msg;
  141. };
  142.  
  143. /*****************************************************************************/
  144.  
  145. DISPATCHERFLAGS
  146. ULONG Dispatch( REGA0 struct IClass *cl, REGA2 Object *o, REGA1 Msg msg )
  147. {
  148.     struct ClassBase         *cb = (struct ClassBase *)(cl -> cl_UserData);
  149.     ULONG                     retval;
  150.     struct MyStackSwapStruct  mystk;
  151.     UBYTE                    *lower,
  152.                              *upper,
  153.                              *sp;
  154.     struct Task              *ThisTask;
  155.     ULONG                     stacksize;
  156.  
  157.     mystk . cl                = cl;
  158.     mystk . o                 = o;
  159.     mystk . msg               = msg;
  160.  
  161.     ThisTask = FindTask( NULL );
  162.     stacksize = (ULONG)(((UBYTE *)(ThisTask -> tc_SPReg)) - ((UBYTE *)(ThisTask -> tc_SPLower)));
  163.  
  164. #define DTSTACKSIZE (16384UL)
  165.  
  166.     /* Enougth stack ? */
  167.     if( stacksize > (DTSTACKSIZE / 2UL) )
  168.     {
  169.       retval = MyDispatch( (&mystk) );
  170.     }
  171.     else
  172.     {
  173.       /* Alloc a new stack frame... */
  174.       while( !(lower = (UBYTE *)AllocMem( DTSTACKSIZE, MEMF_PUBLIC )) );
  175.  
  176.       sp = upper = lower + DTSTACKSIZE;
  177.  
  178.       mystk . stk . stk_Lower   = lower;
  179.       mystk . stk . stk_Upper   = (ULONG)upper;
  180.       mystk . stk . stk_Pointer = sp;
  181.  
  182.       retval = SwapMe( (&mystk) );
  183.  
  184.       FreeMem( lower, DTSTACKSIZE );
  185.     }
  186.  
  187.     return( retval );
  188. }
  189.  
  190.  
  191. DISPATCHERFLAGS
  192. ULONG SwapMe( REGA0 struct MyStackSwapStruct *mystk )
  193. {
  194.     ULONG retval;
  195.  
  196. #define cb ((struct ClassBase *)(mystk -> cl -> cl_UserData))
  197.  
  198.     StackSwap( (&(mystk -> stk)) );
  199.  
  200.       retval = MyDispatch( mystk );
  201.  
  202.     StackSwap( (&(mystk -> stk)) );
  203. #undef cb
  204.  
  205.     return( retval );
  206. }
  207.  
  208.  
  209. DISPATCHERFLAGS
  210. ULONG MyDispatch( REGA0 struct MyStackSwapStruct *mystk )
  211. {
  212.     struct IClass        *cl  = mystk -> cl;
  213.     Object               *o   = mystk -> o;
  214.     Msg                   msg = mystk -> msg;
  215.  
  216.     struct ClassBase     *cb = (struct ClassBase *)(cl -> cl_UserData);
  217.     struct EmbedInstData *eid;
  218.     struct MinList       *linelist;
  219.     ULONG                 retval = 0UL;
  220.  
  221.     switch( msg -> MethodID )
  222.     {
  223.         case OM_NEW:
  224.         {
  225.             if( retval = DoSuperMethodA( cl, o, msg ) )
  226.             {
  227.               ULONG  len,
  228.                      estlines,
  229.                      poolsize;
  230.               BOOL   success = FALSE;
  231.               STRPTR buffer;
  232.  
  233.               /* Get a pointer to the object data */
  234.               eid = (struct EmbedInstData *)INST_DATA( cl, (Object *)retval );
  235.  
  236.               NewList( (struct List *)(&(eid -> eid_VisibleMembers)) );
  237.  
  238.               /* Get the attributes that we need to determine
  239.                * memory pool size
  240.                */
  241.               GetDTAttrs( (Object *)retval,
  242.                           TDTA_Buffer,        (&buffer),
  243.                           TDTA_BufferLen,     (&len),
  244.                           TAG_DONE );
  245.  
  246.               /* Make sure we have a text buffer */
  247.               if( buffer && len )
  248.               {
  249.                 /* Estimate the pool size that we will need */
  250.                 estlines = (len / 80) + 1;
  251.                 estlines = (estlines > 200) ? 200 : estlines;
  252.                 poolsize = sizeof (struct EmbedLine) * estlines;
  253.  
  254.                 /* Create a memory pool for the line list */
  255.                 if( eid -> eid_Pool = CreatePool( (MEMF_CLEAR | MEMF_PUBLIC), poolsize, poolsize ) )
  256.                 {
  257.                   success = TRUE;
  258.                 }
  259.                 else
  260.                 {
  261.                   SetIoErr( ERROR_NO_FREE_STORE );
  262.                 }
  263.               }
  264.               else
  265.               {
  266.                 /* Indicate that something was missing that we needed */
  267.                 SetIoErr( ERROR_REQUIRED_ARG_MISSING );
  268.               }
  269.  
  270.               if( success )
  271.               {
  272.                 parseMethod( cb, cl, (Object *)retval );
  273.               }
  274.               else
  275.               {
  276.                 CoerceMethod( cl, (Object *)retval, OM_DISPOSE );
  277.                 retval = NULL;
  278.               }
  279.             }
  280.         }
  281.             break;
  282.  
  283.         case OM_UPDATE:
  284.         {
  285.             /* Avoid OM_NOTIFY loops */
  286.             if( DoMethod( o, ICM_CHECKLOOP ) )
  287.             {
  288.               break;
  289.             }
  290.         }
  291.         case OM_SET:
  292.         {
  293.             struct GadgetInfo *gi = ((struct opSet *)msg) -> ops_GInfo;
  294.  
  295.             /* Get a pointer to the object data */
  296.             eid = (struct EmbedInstData *)INST_DATA( cl, o );
  297.  
  298.             /* Pass the attributes to the text class and force a refresh if we need it */
  299.             retval = DoSuperMethodA( cl, o, msg );
  300.  
  301.             /* Do layout, if required */
  302.             if( BumpMembers( cl, o, gi ) )
  303.             {
  304.               /* If there was a layout => redraw */
  305.               retval = 1UL;
  306.             }
  307.  
  308.             /* Is this a member sync msg ? */
  309.             if( FindTagItem( EMBEDA_Sync, (((struct opSet *)msg) -> ops_AttrList) ) )
  310.             {
  311.               BOOL              busy = FALSE;
  312.               struct EmbedLine *worknode,
  313.                                *nextnode;
  314.               struct EmbedLine *refreshline;
  315.  
  316.               /* Check if we need only to update a single object... */
  317.               if( refreshline = (struct EmbedLine *)GetTagData( EMBEDA_SyncObjectLine, 0UL, (((struct opSet *)msg) -> ops_AttrList) ) )
  318.               {
  319.                 /* We don't need to update a single member when a global refresh will be triggered... */
  320.                 if( retval == 0UL )
  321.                 {
  322.                   struct RastPort   *rp;
  323.                   struct GadgetInfo *buffer_gi = NULL,
  324.                                     *member_gi = gi;
  325.  
  326.                   if( !((refreshline -> el_ObjectCanClip) || ((refreshline -> el_ObjectIsClipped) == FALSE)) )
  327.                   {
  328.                     member_gi = buffer_gi = CreateGadgetInfoClipBuffer( cb, gi, refreshline );
  329.                   }
  330.  
  331.                   if( member_gi )
  332.                   {
  333.                     /* Get a pointer to the rastport */
  334.                     if( rp = ObtainGIRPort( member_gi ) )
  335.                     {
  336.                       struct gpRender gpr;
  337.  
  338.                       /* Force a redraw */
  339.                       gpr . MethodID   = GM_RENDER;
  340.                       gpr . gpr_GInfo  = member_gi;
  341.                       gpr . gpr_RPort  = rp;
  342.                       gpr . gpr_Redraw = GREDRAW_REDRAW;
  343.  
  344.                       (void)DoMethodA( (refreshline -> el_Object), (Msg)(&gpr) );
  345.  
  346.                       /* Release the temporary rastport */
  347.                       ReleaseGIRPort( rp );
  348.                     }
  349.                   }
  350.  
  351.                   if( buffer_gi );
  352.                   {
  353.                     SyncGadgetInfoClipBuffer( cb, gi, buffer_gi, refreshline );
  354.  
  355.                     FreeGadgetInfoClipBuffer( cb, buffer_gi );
  356.                   }
  357.                 }
  358.               }
  359.               else
  360.               {
  361.                 /* Broadcast refresh: Refresh whole object */
  362.                 retval = 1UL;
  363.               }
  364.  
  365.               /* Any member busy ? */
  366.               worknode = (struct EmbedLine *)(eid -> eid_LineList -> mlh_Head);
  367.  
  368.               while( nextnode = (struct EmbedLine *)(worknode -> el_Line . ln_Link . mln_Succ) )
  369.               {
  370.                 if( worknode -> el_Model )
  371.                 {
  372.                   if( busy = IsModelBusy( cb, (worknode -> el_Model) ) )
  373.                   {
  374.                     break;
  375.                   }
  376.                 }
  377.  
  378.                 worknode = nextnode;
  379.               }
  380.  
  381.               /* Tell everyone that we are busy doing things */
  382.               notifyAttrChanges( o, gi, 0UL,
  383.                                  GA_ID,    G( o ) -> GadgetID,
  384.                                  DTA_Busy, busy,
  385.                                  TAG_DONE );
  386.             }
  387.  
  388.             /* Refresh ? */
  389.             if( retval )
  390.             {
  391.               /* Top instance ? */
  392.               if( OCLASS( o ) == cl )
  393.               {
  394.                 struct RastPort *rp;
  395.  
  396.                 /* Get a pointer to the rastport */
  397.                 if( rp = ObtainGIRPort( gi ) )
  398.                 {
  399.                   struct gpRender gpr;
  400.  
  401.                   /* Force a redraw */
  402.                   gpr . MethodID   = GM_RENDER;
  403.                   gpr . gpr_GInfo  = gi;
  404.                   gpr . gpr_RPort  = rp;
  405.                   gpr . gpr_Redraw = GREDRAW_REDRAW;
  406.  
  407.                   DoMethodA( o, (Msg)(&gpr) );
  408.  
  409.                   /* Release the temporary rastport */
  410.                   ReleaseGIRPort( rp );
  411.                 }
  412.  
  413.                 retval = 0UL;
  414.               }
  415.             }
  416.         }
  417.             break;
  418.  
  419.         case GM_HITTEST:
  420.         {
  421.             struct DTSpecialInfo *si = (struct DTSpecialInfo *)(G( o ) -> SpecialInfo);
  422.  
  423.             eid = (struct EmbedInstData *)INST_DATA( cl, o );
  424.  
  425.             if( AttemptSemaphoreShared( (&(si -> si_Lock)) ) )
  426.             {
  427.               struct MinNode *worknode,
  428.                              *nextnode;
  429.               struct IBox    *domain;
  430.  
  431.               GetDTAttrs( o, DTA_Domain, (&domain), TAG_DONE );
  432.  
  433.               /* Query all members (gadgets) */
  434.               worknode = eid -> eid_VisibleMembers . mlh_Head;
  435.  
  436.               while( nextnode = worknode -> mln_Succ )
  437.               {
  438.                 struct EmbedLine *work = VisibleLink2EmbedLine( worknode );
  439.  
  440.                 if( work -> el_Object )
  441.                 {
  442.                   /* Member disabled ? */
  443.                   if( !((EXTG( (work -> el_Object) ) -> Flags) & GFLG_DISABLED) )
  444.                   {
  445.                     if( retval = DoMemberHitTest( domain, (work -> el_Object), (struct gpHitTest *)msg ) )
  446.                     {
  447.                       eid -> eid_HitMemberLine = work;
  448.  
  449.                       break;
  450.                     }
  451.                   }
  452.                 }
  453.  
  454.                 worknode = nextnode;
  455.               }
  456.  
  457.               ReleaseSemaphore( (&(si -> si_Lock)) );
  458.             }
  459.         }
  460.             break;
  461.  
  462.         case GM_HELPTEST:
  463.         {
  464.             struct DTSpecialInfo *si = (struct DTSpecialInfo *)(G( o ) -> SpecialInfo);
  465.  
  466.             eid = (struct EmbedInstData *)INST_DATA( cl, o );
  467.  
  468.             if( AttemptSemaphoreShared( (&(si -> si_Lock)) ) )
  469.             {
  470.               UWORD member_count = 0U;
  471.  
  472.               struct MinNode   *worknode,
  473.                                *nextnode;
  474.               struct IBox      *domain = NULL;
  475.               struct EmbedLine *memberline = NULL;
  476.               Object           *member     = NULL;
  477.  
  478.               GetDTAttrs( o, DTA_Domain, (&domain), TAG_DONE );
  479.  
  480.               /* Query all members (gadgets) */
  481.               worknode = eid -> eid_VisibleMembers . mlh_Head;
  482.  
  483.               while( nextnode = worknode -> mln_Succ )
  484.               {
  485.                 memberline = VisibleLink2EmbedLine( worknode );
  486.  
  487.                 if( member = memberline -> el_Object )
  488.                 {
  489.                   member_count++;
  490.  
  491.                   /* Does the object request GM_HELPTEST ? */
  492.                   if( (EXTG( member ) -> MoreFlags) & GMORE_GADGETHELP )
  493.                   {
  494.                     ULONG member_retval;
  495.  
  496.                     if( member_retval = DoMemberHitTest( domain, member, (struct gpHitTest *)msg ) )
  497.                     {
  498.                       if( member_retval == GMR_HELPHIT )
  499.                       {
  500.                         retval = (GMR_HELPCODE | member_count);
  501.  
  502.                         eid -> eid_HelpMemberCode = 0x0000FFFFUL;
  503.                       }
  504.                       else
  505.                       {
  506.                         /* Note that member_retval includes GMR_HELPCODE */
  507.                         retval = (member_retval | member_count);
  508.  
  509.                         eid -> eid_HelpMemberCode = member_retval & (~GMR_HELPCODE);
  510.                       }
  511.  
  512.                       break;
  513.                     }
  514.                   }
  515.                 }
  516.  
  517.                 worknode = nextnode;
  518.               }
  519.  
  520.               /* Something hit ? */
  521.               if( nextnode )
  522.               {
  523.                 /* Did another group member return the same helpcode like the last help member ??
  524.                  * Note that intuition won't send IDCMP_GADGETHELP for those msgs.
  525.                  * In this case we're creating a different helpcode,
  526.                  * the orginal one may be obtained through EMBEDA_HelpCode attribute
  527.                  */
  528.                 if( ((eid -> eid_HelpMemberReturnedCode) == retval) && ((eid -> eid_HelpMemberLine -> el_Object) != member) )
  529.                 {
  530.                   retval += 1UL;
  531.                 }
  532.               }
  533.  
  534.               eid -> eid_HelpMemberReturnedCode = retval;
  535.               eid -> eid_HelpMemberLine         = memberline;
  536.  
  537.               ReleaseSemaphore( (&(si -> si_Lock)) );
  538.             }
  539.             else
  540.             {
  541.               /*  retval = GMR_NOHELPHIT;
  542.                *  GMR_NOHELPHIT == 0UL, which will be NOP
  543.                */
  544.             }
  545.         }
  546.             break;
  547.  
  548.         case GM_GOACTIVE:
  549.         {
  550.             struct DTSpecialInfo *si = (struct DTSpecialInfo *)(G( o ) -> SpecialInfo);
  551.  
  552.             eid = (struct EmbedInstData *)INST_DATA( cl, o );
  553.  
  554.             /* During layout we cannot be activated */
  555.             if( !((si -> si_Flags) & DTSIF_LAYOUT) )
  556.             {
  557.               /* Will be released inside GM_HANDLEINPUT method, see below */
  558.               if( AttemptSemaphoreShared( (&(si -> si_Lock)) ) )
  559.               {
  560.                 if( ((eid -> eid_ActiveMemberLine) == NULL) )
  561.                 {
  562.                   struct EmbedLine *memberline;
  563.  
  564.                   memberline = eid -> eid_HitMemberLine;
  565.                   eid -> eid_HitMemberLine = NULL;
  566.  
  567.                   if( !((EXTG( (memberline -> el_Object) ) -> Flags) & GFLG_DISABLED) )
  568.                   {
  569.                     eid -> eid_ActiveMemberLine = memberline;
  570.  
  571.                     (EXTG( (memberline -> el_Object) ) -> Activation) |= GACT_ACTIVEGADGET;
  572.                   }
  573.                 }
  574.               }
  575.               else
  576.               {
  577.                 /* Object locked by another task */
  578.                 retval = GMR_NOREUSE;
  579.                 break;
  580.               }
  581.             }
  582.             else
  583.             {
  584.               /* Currently in layout, can't render yet */
  585.               retval = GMR_NOREUSE;
  586.               break;
  587.             }
  588.         }
  589.         case GM_HANDLEINPUT:
  590.         {
  591.             struct gpInput        gpi = *((struct gpInput *)msg);
  592.             struct GadgetInfo    *gi;
  593.             struct IBox           gbox;
  594.             struct DTSpecialInfo *si = (struct DTSpecialInfo *)(G( o ) -> SpecialInfo);
  595.             struct EmbedLine     *memberline;
  596.             struct IBox          *domain;
  597.  
  598.             eid = (struct EmbedInstData *)INST_DATA( cl, o );
  599.  
  600.             gi  = gpi . gpi_GInfo;
  601.  
  602.             /* Check if instance semaphore wasn't already obtained by GM_GOACTIVE (see upstairs) */
  603.             if( (msg -> MethodID) == GM_HANDLEINPUT )
  604.             {
  605.               /* During layout we cannot be active */
  606.               if( !((si -> si_Flags) & DTSIF_LAYOUT) )
  607.               {
  608.                 /* Obtain instance data, if possible */
  609.                 if( !AttemptSemaphoreShared( (&(si -> si_Lock)) ) )
  610.                 {
  611.                   retval = GMR_NOREUSE;
  612.                   break;
  613.                 }
  614.               }
  615.               else
  616.               {
  617.                 /* Layout in progress */
  618.                 retval = GMR_NOREUSE;
  619.                 break;
  620.               }
  621.             }
  622.  
  623.             GetDTAttrs( o, DTA_Domain, (&domain), TAG_DONE );
  624.  
  625.             if( memberline = eid -> eid_ActiveMemberLine )
  626.             {
  627.               Object *member = memberline -> el_Object;
  628.  
  629.               if( (memberline -> el_ObjectCanClip) || ((memberline -> el_ObjectIsClipped) == FALSE) )
  630.               {
  631.  
  632.                 gbox = GetAbsGadgetBox( (&(gi -> gi_Domain)), EXTG( member ), FALSE );
  633. #if 0
  634.                 if( gpi . gpi_IEvent )
  635.                 {
  636.                   gpi . gpi_IEvent -> ie_X  -= ((gbox . Left) - (domain -> Left));
  637.                   gpi . gpi_IEvent -> ie_Y  -= ((gbox . Top)  - (domain -> Top));
  638.                 }
  639. #endif
  640.  
  641.                   (gpi . gpi_Mouse . X) -= ((gbox . Left) - (domain -> Left));
  642.                   (gpi . gpi_Mouse . Y) -= ((gbox . Top)  - (domain -> Top));
  643.  
  644.                     retval = DoMethodA( member, (Msg)(&gpi) );
  645.  
  646.                   (gpi . gpi_Mouse . X) += ((gbox . Left) - (domain -> Left));
  647.                   (gpi . gpi_Mouse . Y) += ((gbox . Top)  - (domain -> Top));
  648.  
  649. #if 0
  650.                 if( gpi . gpi_IEvent )
  651.                 {
  652.                   gpi . gpi_IEvent -> ie_X  += ((gbox . Left) - (domain -> Left));
  653.                   gpi . gpi_IEvent -> ie_Y  += ((gbox . Top)  - (domain -> Top));
  654.                 }
  655. #endif
  656.               }
  657.               else
  658.               {
  659.                 struct GadgetInfo *buffer_gi;
  660.  
  661. #if 0
  662.                 kprintf( "class %lu sub %lu ie x %ld ie y %ld mx %ld my %ld\n",
  663.                          (LONG)(gpi . gpi_IEvent -> ie_Class), (LONG)(gpi . gpi_IEvent -> ie_SubClass),
  664.                          (LONG)(gpi . gpi_IEvent -> ie_X), (LONG)(gpi . gpi_IEvent -> ie_Y),
  665.                          (LONG)(gpi . gpi_Mouse . X),      (LONG)(gpi . gpi_Mouse . Y) );
  666. #endif
  667.  
  668.                 if( buffer_gi = CreateGadgetInfoClipBuffer( cb, gi, memberline ) )
  669.                 {
  670.                   gpi . gpi_GInfo = buffer_gi;
  671.  
  672.                   (gpi . gpi_Mouse . X) -= (memberline -> el_TopHoriz);
  673.                   (gpi . gpi_Mouse . Y) -= (memberline -> el_TopVert);
  674.  
  675.                     retval = DoMethodA( (memberline -> el_Object), (Msg)(&gpi) );
  676.  
  677.                   (gpi . gpi_Mouse . X) += (memberline -> el_TopHoriz);
  678.                   (gpi . gpi_Mouse . Y) += (memberline -> el_TopVert);
  679.  
  680.                   gpi . gpi_GInfo = gi;
  681.  
  682.                   SyncGadgetInfoClipBuffer( cb, gi, buffer_gi, memberline );
  683.  
  684.                   FreeGadgetInfoClipBuffer( cb, buffer_gi );
  685.                 }
  686.               }
  687.  
  688.               if( retval != GMR_MEACTIVE )
  689.               {
  690. #ifdef COMMENTED_OUT
  691.                 if( retval & (GMR_NEXTACTIVE | GMR_PREVACTIVE) )
  692.                 {
  693.                   Object              *member;
  694.                   BOOL                 match;
  695.                   struct TagItem       ActivateMemberTags[ 2 ];
  696.                   struct gpGoInactive  gpgi;
  697.  
  698.                   match = FALSE;
  699.  
  700.                   if( retval & GMR_NEXTACTIVE )
  701.                   {
  702.                     /* Activate next member... */
  703.  
  704.                     /* Scan through GadgetCollectionList and return the next member after member_object
  705.                      * which has the GFLG_TABCYCLE flag set.
  706.                      * First scan until member_object was found (then set match = TRUE)...
  707.                      * ...then (if( match == TRUE)) get the next GFLG_TABCYCLE member
  708.                      */
  709.                     object_state = (Object *)(eid -> eid_GadgetCollectionList . mlh_Head);
  710.  
  711.                     while( member = (Object *)NextObject( (&object_state) ) )
  712.                     {
  713.                       if( match )
  714.                       {
  715.                         if( ((EXTG( member ) -> Flags) & GFLG_TABCYCLE) && (!((EXTG( member ) -> Flags) & GFLG_DISABLED)) )
  716.                         {
  717.                           break;
  718.                         }
  719.                       }
  720.                       else
  721.                       {
  722.                         if( member == member_object )
  723.                         {
  724.                           match = TRUE;
  725.                         }
  726.                       }
  727.                     }
  728.  
  729.                     /* If there a match but we reach end of GadgetCollectionList, get the first GFLG_TABCYCLE member */
  730.                     if( (member == NULL) && (match == TRUE) )
  731.                     {
  732.                       object_state = (Object *)(eid -> eid_GadgetCollectionList . mlh_Head);
  733.  
  734.                       while( member = (Object *)NextObject( (&object_state) ) )
  735.                       {
  736.                         if( ((EXTG( member ) -> Flags) & GFLG_TABCYCLE) && (!((EXTG( member ) -> Flags) & GFLG_DISABLED)) )
  737.                         {
  738.                           break;
  739.                         }
  740.                       }
  741.                     }
  742.                   }
  743.                   else
  744.                   {
  745.                     /* Activate previous member... */
  746.                     member = member_object;
  747.  
  748.                     /* Scan through GadgetCollectionList until...
  749.                      * ...PrevObjectContinous returns NULL
  750.                      * ...we found a previous member which has the GFLG_TABCYCLE flag set or
  751.                      * ...the object PrevObjectContinous returns is the same as the member_object one
  752.                      */
  753.                     do
  754.                     {
  755.                       member = PrevObjectContinous( member, (&(eid -> eid_GadgetCollectionList)) );
  756.  
  757.                       if( member == NULL )
  758.                       {
  759.                         break;
  760.                       }
  761.                     } while( ((!((EXTG( member ) -> Flags) & GFLG_TABCYCLE)) || ((EXTG( member ) -> Flags) & GFLG_DISABLED)) && (member != member_object) );
  762.                   }
  763.  
  764.                   if( member == NULL )
  765.                   {
  766.                     member = member_object;
  767.                   }
  768.  
  769.                   /* Abort (deactivate) current member */
  770.                   gpgi . MethodID   = GM_GOINACTIVE;
  771.                   gpgi . gpgi_GInfo = gi;
  772.                   gpgi . gpgi_Abort = 0UL; /* Aborted on own request (GMR_NEXTACTIVE or GMR_PREVACTIVE) */
  773.  
  774.                   DoMethodA( o, (Msg)(&gpgi) );
  775.  
  776.  
  777.                   /* Activate the next/previous member */
  778.                   ActivateMemberTags[ 0 ] . ti_Tag  = EMBEDA_ActiveMember;
  779.                   ActivateMemberTags[ 0 ] . ti_Data = (ULONG)member;
  780.                   ActivateMemberTags[ 1 ] . ti_Tag  = TAG_DONE;
  781.                   ActivateMemberTags[ 1 ] . ti_Data = 0UL;
  782.  
  783.                   DoMethod( o, OM_SET, ActivateMemberTags, gi );
  784.  
  785.                   retval = ((eid -> eid_ActiveMember) == member)?(GMR_MEACTIVE):(GMR_NOREUSE);
  786.                 }
  787.                 else
  788. #endif
  789.                 {
  790.                   if( retval & GMR_REUSE )
  791.                   {
  792.                     /* Check if any of my members was hit... */
  793.                     struct gpHitTest gpht;
  794.  
  795.                     gpht . MethodID       = GM_HITTEST;
  796.                     gpht . gpht_GInfo     = gi;
  797.                     gpht . gpht_Mouse . X = gpi . gpi_Mouse . X;
  798.                     gpht . gpht_Mouse . Y = gpi . gpi_Mouse . Y;
  799.  
  800.                     /* Check if a member was hit -- but it shouldn't be the current active member */
  801.                     if( DoMethodA( o, (Msg)(&gpht) ) == GMR_GADGETHIT )
  802.                     {
  803.                       if( (eid -> eid_ActiveMemberLine) != (eid -> eid_HitMemberLine) )
  804.                       {
  805.                         /* If there was a hit, deactivate the old member and activate the new one */
  806.                         struct gpInput member_gpi;
  807.  
  808.                         /* Abort (deactivate) current member */
  809.                         struct gpGoInactive gpgi;
  810.  
  811.                         gpgi . MethodID   = GM_GOINACTIVE;
  812.                         gpgi . gpgi_GInfo = gi;
  813.                         gpgi . gpgi_Abort = 0UL; /* Aborted on own request (retval != GMR_MEACTIVE) */
  814.  
  815.                         DoMethodA( o, (Msg)(&gpgi) );
  816.  
  817.                         /* Change msg to a GM_GOACTIVE one */
  818.                         member_gpi = gpi;
  819.                         member_gpi . MethodID = GM_GOACTIVE;
  820.  
  821.                         /* Activate new member (found in (eid -> eid_HitMemberLine)),
  822.                          * which should return GMR_MEACTIVE
  823.                          */
  824.                         retval = DoMethodA( o, (Msg)(&member_gpi) );
  825.                       }
  826.                     }
  827.                   }
  828.                 }
  829.               }
  830.             }
  831.             else
  832.             {
  833.               /* intuition should reuse this event (no member active etc.) */
  834.               retval = GMR_REUSE;
  835.             }
  836.  
  837.             ReleaseSemaphore( (&(si -> si_Lock)) );
  838.         }
  839.             break;
  840.  
  841.         case GM_GOINACTIVE:
  842.         {
  843.             struct DTSpecialInfo *si        = (struct DTSpecialInfo *)(G( o ) -> SpecialInfo);
  844.             struct EmbedLine     *memberline;
  845.             Object               *member;
  846.             struct gpGoInactive  *gpgi      = (struct gpGoInactive *)msg;
  847.             struct GadgetInfo    *gi;
  848.  
  849.             eid  = (struct EmbedInstData *)INST_DATA( cl, o );
  850.             
  851.             gi = gpgi -> gpgi_GInfo;
  852.  
  853.             ObtainSemaphoreShared( (&(si -> si_Lock)) );
  854.  
  855.             if( memberline = eid -> eid_ActiveMemberLine )
  856.             {
  857.               member = memberline -> el_Object;
  858.  
  859.               /* pass msg to active member... */
  860.               if( (memberline -> el_ObjectCanClip) || ((memberline -> el_ObjectIsClipped) == FALSE) )
  861.               {
  862.                 retval = DoMethodA( member, msg );
  863.               }
  864.               else
  865.               {
  866.                 struct GadgetInfo *buffer_gi;
  867.  
  868.                 if( buffer_gi = CreateGadgetInfoClipBuffer( cb, gi, memberline ) )
  869.                 {
  870.                   gpgi -> gpgi_GInfo = buffer_gi;
  871.  
  872.                     retval = DoMethodA( (memberline -> el_Object), (Msg)gpgi );
  873.  
  874.                   gpgi -> gpgi_GInfo = gi;
  875.  
  876.                   SyncGadgetInfoClipBuffer( cb, gi, buffer_gi, memberline );
  877.  
  878.                   FreeGadgetInfoClipBuffer( cb, buffer_gi );
  879.                 }
  880.               }
  881.  
  882.               /* Clear the GACT_ACTIVEGADGET flag */
  883.               (EXTG( member ) -> Activation) &= (~GACT_ACTIVEGADGET);
  884.  
  885.               /* No active member */
  886.               eid -> eid_ActiveMemberLine = NULL;
  887.             }
  888.  
  889.             ReleaseSemaphore( (&(si -> si_Lock)) );
  890.         }
  891.             break;
  892.  
  893.         case GM_RENDER:
  894.         {
  895.             struct DTSpecialInfo *si  = (struct DTSpecialInfo *)(G( o ) -> SpecialInfo);
  896.  
  897.             /* We must not render during layout */
  898.             if( !((si -> si_Flags) & DTSIF_LAYOUT) )
  899.             {
  900.               struct gpRender       gpr = *((struct gpRender *)msg);
  901.               struct GadgetInfo    *gi  = gpr . gpr_GInfo;
  902.  
  903.               eid = (struct EmbedInstData *)INST_DATA( cl, o );
  904.  
  905.               /* Be sure that all members (gadgets) are on the right place when redrawing ! */
  906.               BumpMembers( cl, o, gi );
  907.  
  908.               /* Clear our gadget box */
  909.               if( gpr . gpr_RPort )
  910.               {
  911.                 /* If this is a major redraw, then erase the old image */
  912.                 if( ((gpr . gpr_Redraw) == GREDRAW_REDRAW) ||
  913.                     ((si -> si_OTopVert) != (si -> si_TopVert)) || ((si -> si_OTopHoriz) != (si -> si_TopHoriz)) )
  914.                 {
  915.                   struct IBox *domain;
  916.  
  917.                   GetDTAttrs( o, DTA_Domain, (&domain), TAG_DONE );
  918.  
  919.                   EraseRect( (gpr . gpr_RPort), (LONG)(domain -> Left),
  920.                                                 (LONG)(domain -> Top),
  921.                                                 (LONG)((domain -> Left) + (domain -> Width)  - 1L),
  922.                                                 (LONG)((domain -> Top)  + (domain -> Height) - 1L) );
  923.                 }
  924.               }
  925.  
  926.               /* Redraw members */
  927.               if( AttemptSemaphoreShared( (&(si -> si_Lock)) ) )
  928.               {
  929.                 struct MinNode  *worknode,
  930.                                 *nextnode;
  931.                 struct TextFont *font;
  932.  
  933.                 GetDTAttrs( o, DTA_TextFont, (&font), TAG_DONE );
  934.  
  935. #if 0
  936.                 /* First let the superclass partake */
  937.                 retval = DoSuperMethodA( cl, o, (Msg)(&gpr) );
  938. #endif
  939.  
  940.                 worknode = eid -> eid_VisibleMembers . mlh_Head;
  941.  
  942.                 while( nextnode = worknode -> mln_Succ )
  943.                 {
  944.                   struct EmbedLine *work = VisibleLink2EmbedLine( worknode );
  945.  
  946.                   if( work -> el_Object )
  947.                   {
  948.                     struct gpRender  member_gpr = gpr; /* copy message, some old datatype classes modify the message
  949.                                                         * and does not restore the previous contents
  950.                                                         */
  951.  
  952.                     member_gpr . gpr_Redraw = GREDRAW_REDRAW;
  953.  
  954.                     if( (work -> el_ObjectCanClip) || ((work -> el_ObjectIsClipped) == FALSE) )
  955.                     {
  956.                       /* Let the member render itself */
  957.                       (void)DoMethodA( (work -> el_Object), (Msg)(&member_gpr) );
  958.                     }
  959.                     else
  960.                     {
  961.                       struct GadgetInfo *buffer_gi;
  962.  
  963.                       if( buffer_gi = CreateGadgetInfoClipBuffer( cb, gi, work ) )
  964.                       {
  965.                         member_gpr . gpr_GInfo = buffer_gi;
  966.  
  967.                           (void)DoMethodA( (work -> el_Object), (Msg)(&member_gpr) );
  968.  
  969.                         member_gpr . gpr_GInfo = gi;
  970.  
  971.                         SyncGadgetInfoClipBuffer( cb, gi, buffer_gi, work );
  972.  
  973.                         FreeGadgetInfoClipBuffer( cb, buffer_gi );
  974.                       }
  975.                     }
  976.  
  977.                     /* test test - sync with blitter (This is not neccesary, but I want to be sure that all is OK after this point) */
  978.                     WaitBlit();
  979.  
  980. #ifdef DRAW_BOX_AROUND_OBJECT
  981.                     {
  982.                       struct IBox gbox;
  983.  
  984.                       /* Draw a little box around the object */
  985.                       gbox = GetAbsGadgetBox( (&(gi -> gi_Domain)), EXTG( (work -> el_Object) ), FALSE );
  986.  
  987.                       /* Restore real box (which was shrinked in CreateVisibleList to make space for this box) */
  988.                       gbox . Left   -= 1;
  989.                       gbox . Top    -= 1;
  990.                       gbox . Width  += 2;
  991.                       gbox . Height += 2;
  992.  
  993.                       /* draw a box with shadowcolor around the object */
  994.                       SetDrMd( (gpr . gpr_RPort), JAM1 );
  995.                       SetAPen( (gpr . gpr_RPort), (ULONG)(gpr . gpr_GInfo -> gi_DrInfo -> dri_Pens[ SHADOWPEN ]) );
  996.                       Move( (gpr . gpr_RPort), (LONG)(gbox . Left),                  (LONG)(gbox . Top)                   );
  997.                       Draw( (gpr . gpr_RPort), (LONG)(gbox . Left),                  (LONG)(gbox . Top) + (gbox . Height) );
  998.                       Draw( (gpr . gpr_RPort), (LONG)(gbox . Left) + (gbox . Width), (LONG)(gbox . Top) + (gbox . Height) );
  999.                       Draw( (gpr . gpr_RPort), (LONG)(gbox . Left) + (gbox . Width), (LONG)(gbox . Top)                   );
  1000.                       Draw( (gpr . gpr_RPort), (LONG)(gbox . Left),                  (LONG)(gbox . Top)                   );
  1001.                     }
  1002. #endif /* DRAW_BOX_AROUND_OBJECT */
  1003.                   }
  1004.                   else
  1005.                   {
  1006.                     struct BitMap *bm;
  1007.  
  1008.                     if( bm = AllocBitMap( ((ULONG)(work -> el_Line . ln_Width)  + 16UL),
  1009.                                           ((ULONG)(work -> el_Line . ln_Height) + 16UL),
  1010.                                           (ULONG)(gpr . gpr_RPort -> BitMap -> Depth),
  1011.                                           (BMF_CLEAR | BMF_MINPLANES),
  1012.                                           (gpr . gpr_RPort -> BitMap) ) )
  1013.                     {
  1014.                       struct RastPort tmprp = { 0 };
  1015.  
  1016.                       InitRastPort( (&tmprp) );
  1017.                       tmprp . BitMap = bm;
  1018.  
  1019.                       SetABPenDrMd( (&tmprp), (ULONG)(work -> el_Line . ln_FgPen), (ULONG)(work -> el_Line . ln_BgPen), JAM2 );
  1020.                       Move( (&tmprp), 0, (LONG)(font -> tf_Baseline) );
  1021.                       Text( (&tmprp), (work -> el_Line . ln_Text), (long)(work -> el_Line . ln_TextLen) );
  1022.  
  1023.                       BltBitMapRastPort( bm, (long)(work -> el_TopHoriz), (long)(work -> el_TopVert),
  1024.                                          (gpr . gpr_RPort),
  1025.                                          (long)(work -> el_VisibleBox . Left),
  1026.                                          (long)(work -> el_VisibleBox . Top),
  1027.                                          (long)(work -> el_VisibleBox . Width),
  1028.                                          (long)(work -> el_VisibleBox . Height),
  1029.                                          0xC0 );
  1030.  
  1031.                       WaitBlit();
  1032.  
  1033.                       FreeBitMap( bm );
  1034.                     }
  1035.                   }
  1036.  
  1037.                   worknode = nextnode;
  1038.                 }
  1039.  
  1040.                 /* Store the drawn horiz/vert position */
  1041.                 si -> si_OTopVert  = si -> si_TopVert;
  1042.                 si -> si_OTopHoriz = si -> si_TopHoriz;
  1043.  
  1044.                 ReleaseSemaphore( (&(si -> si_Lock)) );
  1045.               }
  1046.               else
  1047.               {
  1048.                 D( kprintf( "rendering rejected\n" ) );
  1049.               }
  1050.             }
  1051.         }
  1052.             break;
  1053.  
  1054.         case GM_LAYOUT:
  1055.         case DTM_PROCLAYOUT:
  1056.         {
  1057.             struct DTSpecialInfo *si = (struct DTSpecialInfo *)(G( o ) -> SpecialInfo);
  1058.             struct GadgetInfo    *gi = (((struct gpLayout *)msg) -> gpl_GInfo);
  1059.  
  1060.             eid = (struct EmbedInstData *)INST_DATA( cl, o );
  1061.  
  1062.             /* Set the layout flag.
  1063.              * This avoids rendering and other unwanted actions during the layout process.
  1064.              * (the flag will be cleared in layoutMethod function).
  1065.              */
  1066.             si -> si_Flags |= DTSIF_LAYOUT;
  1067.  
  1068.             ObtainSemaphore( (&(si -> si_Lock)) );
  1069.  
  1070.               /* Avoids that an embedded object like animation.datatype subclass would render during async layout */
  1071.               DestroyVisibleList( cb, o, eid );
  1072.  
  1073.             ReleaseSemaphore( (&(si -> si_Lock)) );
  1074.  
  1075.             /* Tell everyone that we are busy doing things */
  1076.             notifyAttrChanges( o, gi, 0UL,
  1077.                                GA_ID,    G( o ) -> GadgetID,
  1078.                                DTA_Busy, TRUE,
  1079.                                TAG_DONE );
  1080.  
  1081.             /* Let the super-class partake */
  1082.             retval = DoSuperMethodA( cl, o, msg );
  1083.  
  1084.             /* set layout flag again because text.datatype cleared it :-( */
  1085.             si -> si_Flags |= DTSIF_LAYOUT;
  1086.  
  1087.             /* Layout the text */
  1088.             retval += layoutMethod( cb, cl, o, (struct gpLayout *)msg );
  1089.         }
  1090.             break;
  1091.  
  1092.         case DTM_REMOVEDTOBJECT:
  1093.         {
  1094.             /* Get a pointer to our object data */
  1095.             eid = (struct EmbedInstData *)INST_DATA( cl, o );
  1096.  
  1097.             if( linelist = eid -> eid_LineList )
  1098.             {
  1099.               struct EmbedLine *worknode,
  1100.                                *nextnode;
  1101.  
  1102.               /* Send msg to all gadgets */
  1103.               worknode = (struct EmbedLine *)(linelist -> mlh_Head);
  1104.  
  1105.               while( nextnode = (struct EmbedLine *)(worknode -> el_Line . ln_Link . mln_Succ) )
  1106.               {
  1107.                 if( worknode -> el_Object )
  1108.                 {
  1109.                   (void)DoMethodA( (worknode -> el_Object), msg );
  1110.  
  1111.                   (EXTG( (worknode -> el_Object) ) -> GadgetType) &= ~GTYP_REQGADGET;
  1112.  
  1113.                   FreeBitMap( (worknode -> el_ObjectBitMap) );
  1114.                   worknode -> el_ObjectBitMap = NULL;
  1115.                 }
  1116.  
  1117.                 worknode = nextnode;
  1118.               }
  1119.             }
  1120.  
  1121.             /* Let the superclass partake */
  1122.             retval = DoSuperMethodA( cl, o, msg );
  1123.         }
  1124.             break;
  1125.  
  1126.         case DTM_TRIGGER:
  1127.         {
  1128.             /* Get a pointer to our object data */
  1129.             eid = (struct EmbedInstData *)INST_DATA( cl, o );
  1130.  
  1131.             if( linelist = eid -> eid_LineList )
  1132.             {
  1133.               struct EmbedLine *worknode,
  1134.                                *nextnode;
  1135.  
  1136.               /* Send msg to all gadgets */
  1137.               worknode = (struct EmbedLine *)(linelist -> mlh_Head);
  1138.  
  1139.               while( nextnode = (struct EmbedLine *)(worknode -> el_Line . ln_Link . mln_Succ) )
  1140.               {
  1141.                 if( worknode -> el_Object )
  1142.                 {
  1143.                   retval += DoMethodA( (worknode -> el_Object), msg );
  1144.                 }
  1145.  
  1146.                 worknode = nextnode;
  1147.               }
  1148.             }
  1149.         }
  1150.             break;
  1151.  
  1152.         case OM_DISPOSE:
  1153.         {
  1154.             /* Get a pointer to our object data */
  1155.             eid = (struct EmbedInstData *)INST_DATA( cl, o );
  1156.  
  1157.             if( linelist = eid -> eid_LineList )
  1158.             {
  1159.               struct EmbedLine *worknode,
  1160.                                *nextnode;
  1161.  
  1162.               worknode = (struct EmbedLine *)(linelist -> mlh_Head);
  1163.  
  1164.               while( nextnode = (struct EmbedLine *)(worknode -> el_Line . ln_Link . mln_Succ) )
  1165.               {
  1166.                 if( worknode -> el_Object )
  1167.                 {
  1168.                   /* pass dispose msg to member/model */
  1169.                   if( worknode -> el_IsDTObject )
  1170.                   {
  1171.                     DisposeDTObject( (worknode -> el_Object) );
  1172.                   }
  1173.                   else
  1174.                   {
  1175.                     DisposeObject( (worknode -> el_Object) );
  1176.                   }
  1177.  
  1178.                   DisposeObject( (worknode -> el_Model) );
  1179.                 }
  1180.  
  1181.                 worknode = nextnode;
  1182.               }
  1183.  
  1184.               /* Don't let the super class free the line list */
  1185.               NewList( (struct List *)linelist );
  1186.             }
  1187.  
  1188.             /* Delete the line pool */
  1189.             DeletePool( (eid -> eid_Pool) );
  1190.         }
  1191.         /* Let the superclass handle everything else */
  1192.         default:
  1193.         {
  1194.             retval = DoSuperMethodA( cl, o, msg );
  1195.         }
  1196.             break;
  1197.     }
  1198.  
  1199.     return( retval );
  1200. }
  1201.  
  1202. #define ECMD_REMARK     (1UL)
  1203. #define ECMD_DATATYPE   (2UL)
  1204. #define ECMD_CALENDAR   (3UL)
  1205. #define ECMD_PROPGADGET (4UL)
  1206. #define ECMD_TRIGGER    (5UL)
  1207. #define ECMD_LINK       (6UL)
  1208.  
  1209. struct EmbedCommand
  1210. {
  1211.     ULONG  ec_ID;
  1212.     STRPTR ec_Command;
  1213. };
  1214.  
  1215. struct EmbedCommand embedcommands[] =
  1216. {
  1217.     { ECMD_REMARK,     "remark"     },
  1218.     { ECMD_REMARK,     "rem"        },
  1219.     { ECMD_DATATYPE,   "datatype"   },
  1220.     { ECMD_CALENDAR,   "calendar"   },
  1221.     { ECMD_PROPGADGET, "propgadget" },
  1222.     { ECMD_TRIGGER,    "trigger"    },
  1223.     { ECMD_LINK,       "link"       },
  1224.     { 0UL,             NULL         }
  1225. };
  1226.  
  1227.  
  1228. ULONG parseMethod( struct ClassBase *cb, struct IClass *cl, Object *o )
  1229. {
  1230.     struct DTSpecialInfo *si      = (struct DTSpecialInfo *)(G( o ) -> SpecialInfo);
  1231.     struct EmbedInstData *eid     = (struct EmbedInstData *)INST_DATA( cl, o );
  1232.     ULONG                 totalh  = 0UL,
  1233.                           totalw  = 0UL;
  1234.     struct RastPort       trp     = { 0 };
  1235.     ULONG                 hunit   = 1UL;
  1236.  
  1237.     /* Switches */
  1238.     BOOL                  linefeed  = FALSE;
  1239.     BOOL                  newseg    = FALSE;
  1240.  
  1241.     /* Attributes obtained from super-class */
  1242.     struct TextFont      *font;
  1243.     struct MinList       *linelist;
  1244.     ULONG                 bufferlen  = 0UL;
  1245.     STRPTR                buffer     = NULL;
  1246.  
  1247.     /* Line information */
  1248.     ULONG                 num,
  1249.                           offset,
  1250.                           swidth     = 0UL,
  1251.                           lineheight = 0UL;
  1252.     ULONG                 anchor     = 0UL,
  1253.                           newanchor  = 0UL;
  1254.     ULONG                 style      = FS_NORMAL;
  1255.     struct EmbedLine     *line;
  1256.     ULONG                 yoffset  = 0UL;
  1257.     UBYTE                 fgpen    = 1UL; /* should be: (msg -> gpl_GInfo -> gi_DrInfo -> dri_Pens[ TEXTPEN ]);       */
  1258.     UBYTE                 bgpen    = 0UL; /* should be: (msg -> gpl_GInfo -> gi_DrInfo -> dri_Pens[ BACKGROUNDPEN ]); */
  1259.     ULONG                 i;
  1260.  
  1261.     BOOL                  command = FALSE;
  1262.  
  1263.     D( kprintf( "in parsing\n" ) );
  1264.  
  1265.     /* Get all the attributes that we are going to need for a successful layout */
  1266.     if( GetDTAttrs( o,
  1267.                     DTA_TextFont,   (&font),
  1268.                     TDTA_Buffer,    (&buffer),
  1269.                     TDTA_BufferLen, (&bufferlen),
  1270.                     TDTA_LineList,  (&linelist),
  1271.                     TAG_DONE ) == 4UL )
  1272.     {
  1273.       eid -> eid_LineList = linelist;
  1274.  
  1275.       /* Make sure we have a buffer */
  1276.       if( buffer )
  1277.       {
  1278.         /* Initialize the temporary RastPort (for layout calculations) */
  1279.         InitRastPort( (&trp) );
  1280.         SetFont( (&trp), font );
  1281.  
  1282.         /* Step through the text buffer */
  1283.         for( i = offset = num = 0UL ; (i <= bufferlen) ; i++ )
  1284.         {
  1285.           if( buffer[ i ] == '@' )
  1286.           {
  1287.             /* a directive must start at the begin of the line... */
  1288.             if( buffer[ i - 1 ] = '\n' )
  1289.             {
  1290.               command = TRUE;
  1291.             }
  1292.           }
  1293.  
  1294.           /* Check for end of line */
  1295.           if( buffer[ i ] == '\n' || (i == bufferlen) )
  1296.           {
  1297.             newseg = linefeed = TRUE;
  1298.             newanchor = i + 1;
  1299.           }
  1300.           /* Check for end of page */
  1301.           else if( buffer[ i ] == 12 )
  1302.           {
  1303.             newseg = linefeed = TRUE;
  1304.             newanchor = i + 1;
  1305.           }
  1306.           else
  1307.           {
  1308.             /* Compute the width of the line. */
  1309.             swidth = TextLength( &trp, &buffer[ anchor ], num + 1 );
  1310.  
  1311.             num++;
  1312.           }
  1313.  
  1314.           /* Time for a new text segment yet? */
  1315.           if( newseg )
  1316.           {
  1317.             /* Allocate a new line segment from our memory pool */
  1318.             if( line = (struct EmbedLine *)AllocPooled( (eid -> eid_Pool), sizeof( struct EmbedLine ) ) )
  1319.             {
  1320.               Object *image,
  1321.                      *model;
  1322.               ULONG   height;
  1323.  
  1324.               /* Does the line contain a command ? */
  1325.               if( command )
  1326.               {
  1327.                 STRPTR cmd  = &buffer[ anchor + 1 ],
  1328.                        args = NULL;
  1329.                 ULONG  id   = 0UL;
  1330.                 ULONG  ci   = 0UL; /* command interator */
  1331.  
  1332.                 command  = FALSE;
  1333.                 linefeed = FALSE;
  1334.  
  1335.                 /* Which command ? */
  1336.                 while( embedcommands[ ci ] . ec_Command )
  1337.                 {
  1338.                   ULONG len = (ULONG)strlen( (embedcommands[ ci ] . ec_Command) );
  1339.  
  1340.                   if( !Strnicmp( cmd, (embedcommands[ ci ] . ec_Command), len ) )
  1341.                   {
  1342.                     args = cmd + len + 1;
  1343.                     id   = embedcommands[ ci ] . ec_ID;
  1344.  
  1345.                     break;
  1346.                   }
  1347.  
  1348.                   ci++;
  1349.                 }
  1350.  
  1351.                 /* Extract arguments */
  1352.                 if( args )
  1353.                 {
  1354.                   STRPTR s;
  1355.  
  1356.                   if( s = (STRPTR)AllocVec( num, (MEMF_PUBLIC | MEMF_CLEAR) ) )
  1357.                   {
  1358.                     stccpy( s, args, (int)(num - (ULONG)(args - cmd)) );
  1359.                   }
  1360.  
  1361.                   args = s;
  1362.  
  1363.                   D( kprintf( "args '%s'\n", args ) );
  1364.                 }
  1365.  
  1366.                 switch( id )
  1367.                 {
  1368.                   case ECMD_REMARK:
  1369.                   {
  1370.                       D( kprintf( "remark: %s", args ) );
  1371.                   }
  1372.                       break;
  1373.  
  1374.                   case ECMD_DATATYPE:
  1375.                   {
  1376.                       if( image = NewDTObject( args, GA_GadgetHelp, TRUE, TAG_DONE ) )
  1377.                       {
  1378.                         line -> el_Object         = image;
  1379.                         line -> el_IsDTObject     = TRUE;
  1380.                         line -> el_ObjectCanClip  = TRUE;
  1381.  
  1382.                         if( model = NewObject( (cb -> cb_EmbedModel), NULL, EMBEDA_SyncObjectLine, line,
  1383.                                                                             ICA_TARGET,            o,
  1384.                                                                             TAG_DONE ) )
  1385.                         {
  1386.                           line -> el_Model = model;
  1387.  
  1388.                           /* Set model as target */
  1389.                           SetDTAttrs( image, NULL, NULL, ICA_TARGET, model, TAG_DONE );
  1390.  
  1391.                           D( kprintf( "dto %lx\n", image ) );
  1392.                         }
  1393.                         else
  1394.                         {
  1395.                           D( kprintf( "no model\n" ) );
  1396.                           DisposeDTObject( image );
  1397.                         }
  1398.                       }
  1399.                       else
  1400.                       {
  1401.                         D( kprintf( "------- dt error %ld\n", IoErr() ) );
  1402.                       }
  1403.                   }
  1404.                       break;
  1405.  
  1406.                   case ECMD_CALENDAR:
  1407.                   {
  1408.                       if( image = NewObject( NULL, "calendar.gadget", GA_GadgetHelp, TRUE, TAG_DONE ) )
  1409.                       {
  1410.                         line -> el_Object          = image;
  1411.                         line -> el_IsDTObject      = FALSE;
  1412.                         line -> el_ObjectCanClip   = FALSE;
  1413.                         line -> el_ObjectIsClipped = TRUE;
  1414.  
  1415.                         if( model = NewObject( (cb -> cb_EmbedModel), NULL, EMBEDA_SyncObjectLine, line,
  1416.                                                                             ICA_TARGET,            o,
  1417.                                                                             TAG_DONE ) )
  1418.                         {
  1419.                           /* Set model as target */
  1420.                           SetDTAttrs( image, NULL, NULL, ICA_TARGET, model, TAG_DONE );
  1421.  
  1422.                           D( kprintf( "calendar %lx\n", image ) );
  1423.  
  1424.                           line -> el_Model          = model;
  1425.                         }
  1426.                         else
  1427.                         {
  1428.                           D( kprintf( "no model\n" ) );
  1429.                           DisposeDTObject( image );
  1430.                         }
  1431.                       }
  1432.                       else
  1433.                       {
  1434.                         D( kprintf( "------- calendar error %ld\n", IoErr() ) );
  1435.                       }
  1436.                   }
  1437.                       break;
  1438.  
  1439.                   case ECMD_PROPGADGET:
  1440.                   {
  1441.                       if( image = NewObject( NULL, PROPGCLASS,
  1442.                                              PGA_Borderless, FALSE,
  1443.                                              PGA_NewLook,    TRUE,
  1444.                                              PGA_Total,      100UL,
  1445.                                              PGA_Visible,     10UL,
  1446.                                              PGA_Top,         20UL,
  1447.                                              PGA_Freedom,    FREEVERT,
  1448.                                              GA_GadgetHelp,  TRUE,
  1449.                                              TAG_DONE ) )
  1450.                       {
  1451.                         line -> el_Object          = image;
  1452.                         line -> el_IsDTObject      = FALSE;
  1453.                         line -> el_ObjectCanClip   = FALSE;
  1454.                         line -> el_ObjectIsClipped = TRUE;
  1455.  
  1456.                         if( model = NewObject( (cb -> cb_EmbedModel), NULL, EMBEDA_SyncObjectLine, line,
  1457.                                                                             ICA_TARGET,            o,
  1458.                                                                             TAG_DONE ) )
  1459.                         {
  1460.                           /* Set model as target */
  1461.                           SetDTAttrs( image, NULL, NULL, ICA_TARGET, model, TAG_DONE );
  1462.  
  1463.                           D( kprintf( "prop %lx\n", image ) );
  1464.  
  1465.                           line -> el_Model          = model;
  1466.                         }
  1467.                         else
  1468.                         {
  1469.                           D( kprintf( "no model\n" ) );
  1470.                           DisposeDTObject( image );
  1471.                         }
  1472.                       }
  1473.                       else
  1474.                       {
  1475.                         D( kprintf( "------- prop error %ld\n", IoErr() ) );
  1476.                       }
  1477.                   }
  1478.                       break;
  1479.  
  1480.                   default:
  1481.                   {
  1482.                       D( kprintf( "unknown command %lu\n", id ) );
  1483.                   }
  1484.                       break;
  1485.                 }
  1486.  
  1487.                 if( args )
  1488.                 {
  1489.                   FreeVec( args );
  1490.                 }
  1491.               }
  1492.  
  1493.               if( line -> el_Object )
  1494.               {
  1495.                 if( line -> el_IsDTObject )
  1496.                 {
  1497.                   GetDTAttrs( (line -> el_Object), DTA_NominalVert,  (&height),
  1498.                                                    DTA_NominalHoriz, (&swidth),
  1499.                                                    TAG_DONE );
  1500.                 }
  1501.                 else
  1502.                 {
  1503.                   struct gpDomain gpd = { 0 }; /* Clear all fields */
  1504.                   ULONG           success;
  1505.  
  1506.                   /* Get the domain of the object */
  1507.                   gpd . MethodID  = GM_DOMAIN;
  1508.                   gpd . gpd_Which = GDOMAIN_NOMINAL;
  1509.  
  1510.                   if( (success = DoMethodA( o, (Msg)(&gpd) )) == 0UL )
  1511.                   {
  1512.                     kprintf( "can't get nominal box, I try now the minimum box\n" );
  1513.  
  1514.                     gpd . gpd_Which = GDOMAIN_MINIMUM;
  1515.  
  1516.                     success = DoMethodA( o, (Msg)(&gpd) );
  1517.                   }
  1518.  
  1519.                   if( success )
  1520.                   {
  1521.                     swidth = gpd . gpd_Domain . Width;
  1522.                     height = gpd . gpd_Domain . Height;
  1523.                   }
  1524.                   else
  1525.                   {
  1526.                     /* Oh no ! - Use fixed width/height to fix the size problem
  1527.                      * (e.g. fixed to topaz 8, but scale if a larger font is used):
  1528.                      */
  1529.                     swidth = (320UL * (font -> tf_XSize)) / 8UL;
  1530.                     height = (200UL * (font -> tf_YSize)) / 8UL;
  1531.                   }
  1532.                 }
  1533.  
  1534.                 /* Valid width/height ? */
  1535.                 if( (height == 0UL) || (swidth == 0UL) )
  1536.                 {
  1537.                   LONG  totvert   = 0L,
  1538.                         tothoriz  = 0L,
  1539.                         vertunit  = 0L,
  1540.                         horizunit = 0L;
  1541.  
  1542.                   /* Calculate width/height manually... */
  1543.                   GetDTAttrs( (line -> el_Object), DTA_TotalVert,  (&totvert),
  1544.                                                    DTA_TotalHoriz, (&tothoriz),
  1545.                                                    DTA_VertUnit,   (&vertunit),
  1546.                                                    DTA_HorizUnit,  (&horizunit),
  1547.                                                    TAG_DONE );
  1548.  
  1549.                   swidth  = totvert  * MAX( vertunit,  1L );
  1550.                   height  = tothoriz * MAX( horizunit, 1L );
  1551.  
  1552.                   /* Valid width/height (2nd attempt) ? */
  1553.                   if( (height == 0UL) || (swidth == 0UL) )
  1554.                   {
  1555.                     /* Oh no ! - Use fixed width/height to fix the size problem
  1556.                      * (e.g. fixed to topaz 8, but scale if a larger font is used):
  1557.                      */
  1558.                     swidth = (320UL * (font -> tf_XSize)) / 8UL;
  1559.                     height = (200UL * (font -> tf_YSize)) / 8UL;
  1560.                   }
  1561.                 }
  1562.               }
  1563.               else
  1564.               {
  1565.                 swidth = TextLength( &trp, &buffer[ anchor ], num );
  1566.                 height = font -> tf_YSize;
  1567.               }
  1568.  
  1569.               line -> el_Line . ln_Text    = &buffer[ anchor ];
  1570.               line -> el_Line . ln_TextLen = num;
  1571.               line -> el_Line . ln_XOffset = offset;
  1572.               line -> el_Line . ln_YOffset = yoffset + (font -> tf_Baseline);
  1573.               line -> el_Line . ln_Width   = swidth;
  1574.               line -> el_Line . ln_Height  = height;
  1575.               line -> el_Line . ln_Flags   = (linefeed)?(LNF_LF):(0UL);
  1576.               line -> el_Line . ln_FgPen   = fgpen;
  1577.               line -> el_Line . ln_BgPen   = bgpen;
  1578.               line -> el_Line . ln_Style   = style;
  1579.               line -> el_Line . ln_Data    = NULL;
  1580.  
  1581.               /* Fill in line box */
  1582.               line -> el_LineBox . Left   = line -> el_Line . ln_XOffset;
  1583.               line -> el_LineBox . Top    = line -> el_Line . ln_YOffset - (font -> tf_Baseline);
  1584.               line -> el_LineBox . Width  = line -> el_Line . ln_Width;
  1585.               line -> el_LineBox . Height = line -> el_Line . ln_Height;
  1586.  
  1587.               D( kprintf( "new line box %lx %ld %ld %ld %ld\n", line, (line -> el_LineBox . Left),
  1588.                                                                       (line -> el_LineBox . Top),
  1589.                                                                       (line -> el_LineBox . Width),
  1590.                                                                       (line -> el_LineBox . Height) ) );
  1591.  
  1592.               /* Add the line to the list */
  1593.               AddTail( (struct List *)linelist, (struct Node *)(&(line -> el_Line . ln_Link)) );
  1594.  
  1595.               /* Increment the offset */
  1596.               offset += swidth;
  1597.  
  1598.               /* Bump line height */
  1599.               lineheight = MAX( height, lineheight );
  1600.  
  1601.               /* Increment the line count */
  1602.               if( linefeed )
  1603.               {
  1604.                 yoffset += lineheight;
  1605.                 totalw = MAX( totalw, offset );
  1606.                 totalh += (lineheight + (font -> tf_YSize) - 1) / (font -> tf_YSize); /* pix_height / pix_per_unit, rounded */
  1607.  
  1608.                 offset     = 0UL;
  1609.                 lineheight = 0UL;
  1610.               }
  1611.             }
  1612.  
  1613.             /* Clear the variables */
  1614.             newseg = linefeed = FALSE;
  1615.             anchor = newanchor;
  1616.             num = 0UL;
  1617.           }
  1618.         }
  1619.       }
  1620.       else
  1621.       {
  1622.         D( kprintf( "no buffer\n" ) );
  1623.       }
  1624.  
  1625.       SetDTAttrs( o, NULL, NULL, DTA_NominalVert,  (totalh * (font -> tf_YSize)),
  1626.                                  DTA_NominalHoriz, (hunit * totalw),
  1627.                                  TAG_DONE );
  1628.  
  1629.  
  1630.       /* Compute the lines and columns type information */
  1631.       si -> si_VertUnit  = font -> tf_YSize;
  1632.       si -> si_VisVert   = 0L;
  1633.       si -> si_TotVert   = totalh;
  1634.  
  1635.       si -> si_HorizUnit = hunit;
  1636.       si -> si_VisHoriz  = 0L;
  1637.       si -> si_TotHoriz  = totalw;
  1638.     }
  1639.     else
  1640.     {
  1641.       D( kprintf( "no args\n" ) );
  1642.     }
  1643.  
  1644.     return( totalh );
  1645. }
  1646.  
  1647.  
  1648. ULONG layoutMethod( struct ClassBase *cb, struct IClass *cl, Object *o, struct gpLayout *gpl )
  1649. {
  1650.     struct DTSpecialInfo *si  = (struct DTSpecialInfo *)(G( o ) -> SpecialInfo);
  1651.     struct EmbedInstData *eid = (struct EmbedInstData *)INST_DATA( cl, o );
  1652.     ULONG                 visible,
  1653.                           totalh  = 0UL,
  1654.                           totalw;
  1655.     ULONG                 hunit   = si -> si_HorizUnit,
  1656.                           vunit   = si -> si_VertUnit;
  1657.     STRPTR                title;
  1658.     BOOL                  busy    = FALSE;
  1659.  
  1660.     /* Attributes obtained from super-class */
  1661.     struct MinList       *linelist = eid -> eid_LineList;
  1662.     struct IBox          *domain;
  1663.  
  1664.     /* Get all the attributes that we are going to need for a successful layout */
  1665.     if( GetDTAttrs( o,
  1666.                     DTA_Domain,  (&domain),
  1667.                     DTA_ObjName, (&title),
  1668.                     TAG_DONE) == 2UL )
  1669.     {
  1670.       struct gpLayout   member_gpl;
  1671.       struct EmbedLine *worknode,
  1672.                        *nextnode;
  1673.  
  1674.       /* Lock the global object data so that nobody else can manipulate it */
  1675.       ObtainSemaphore( (&(si -> si_Lock)) );
  1676.  
  1677.       DestroyVisibleList( cb, o, eid );
  1678.  
  1679.       /* No layout to perform */
  1680.       totalh = si -> si_TotVert;
  1681.       totalw = si -> si_TotHoriz;
  1682.  
  1683.       /* Compute the lines and columns type information */
  1684.       si -> si_VertUnit  = vunit;
  1685.       si -> si_VisVert   = visible = domain -> Height / vunit;
  1686.       si -> si_TotVert   = totalh;
  1687.  
  1688.       si -> si_HorizUnit = hunit;
  1689.       si -> si_VisHoriz  = (LONG) domain -> Width / hunit;
  1690.       si -> si_TotHoriz  = totalw;
  1691.  
  1692.       /* Bump members */
  1693.       CreateVisibleList( cb, o, eid, domain, (gpl -> gpl_GInfo) );
  1694.  
  1695.       /* Layout members */
  1696.       member_gpl = *gpl;
  1697.       member_gpl . MethodID = GM_LAYOUT;
  1698.  
  1699.       worknode = (struct EmbedLine *)(linelist -> mlh_Head);
  1700.  
  1701.       while( nextnode = (struct EmbedLine *)(worknode -> el_Line . ln_Link . mln_Succ) )
  1702.       {
  1703.         if( worknode -> el_Object )
  1704.         {
  1705.           /* If this is the initial layout, we've to tell te member something abouts it's parent wid/req */
  1706.           if( gpl -> gpl_Initial )
  1707.           {
  1708.             if( (EXTG( o ) -> GadgetType) & GTYP_REQGADGET )
  1709.             {
  1710.               (EXTG( (worknode -> el_Object) ) -> GadgetType) |= GTYP_REQGADGET;
  1711.             }
  1712.           }
  1713.  
  1714.           /* pass msg to active member... */
  1715.           if( (worknode -> el_ObjectCanClip) || ((worknode -> el_ObjectIsClipped) == FALSE) )
  1716.           {
  1717.             (void)DoMethodA( (worknode -> el_Object), (Msg)(&member_gpl) );
  1718.           }
  1719.           else
  1720.           {
  1721.             struct GadgetInfo *buffer_gi;
  1722.  
  1723.             if( buffer_gi = CreateGadgetInfoClipBuffer( cb, (gpl -> gpl_GInfo), worknode ) )
  1724.             {
  1725.               member_gpl . gpl_GInfo = buffer_gi;
  1726.  
  1727.                 (void)DoMethodA( (worknode -> el_Object), (Msg)(&member_gpl) );
  1728.  
  1729.               member_gpl . gpl_GInfo = (gpl -> gpl_GInfo);
  1730.  
  1731. /* no rendering during GM_LAYOUT allowed ! */
  1732. #ifdef COMMENTED_OUT
  1733.               SyncGadgetInfoClipBuffer( cb, (gpl -> gpl_GInfo), buffer_gi, worknode );
  1734. #endif
  1735.  
  1736.               FreeGadgetInfoClipBuffer( cb, buffer_gi );
  1737.             }
  1738.           }
  1739.         }
  1740.  
  1741.         worknode = nextnode;
  1742.       }
  1743.  
  1744.       /* Release the global data lock */
  1745.       ReleaseSemaphore( (&(si -> si_Lock)) );
  1746.  
  1747.       /* Any member busy ? */
  1748.       worknode = (struct EmbedLine *)(linelist -> mlh_Head);
  1749.  
  1750.       while( nextnode = (struct EmbedLine *)(worknode -> el_Line . ln_Link . mln_Succ) )
  1751.       {
  1752.         if( worknode -> el_Model )
  1753.         {
  1754.           if( busy = IsModelBusy( cb, (worknode -> el_Model) ) )
  1755.           {
  1756.             break;
  1757.           }
  1758.         }
  1759.  
  1760.         worknode = nextnode;
  1761.       }
  1762.  
  1763.       /* Store parent's (window/req) domain box */
  1764.       eid -> eid_OldParentDomain = gpl -> gpl_GInfo -> gi_Domain;
  1765.  
  1766.       /* Clear the layout flag */
  1767.       si -> si_Flags &= ~DTSIF_LAYOUT;
  1768.  
  1769.       /* Not aborted, so tell the world of our newest attributes */
  1770.       notifyAttrChanges( o, (gpl -> gpl_GInfo), 0UL,
  1771.                          GA_ID,                   G( o ) -> GadgetID,
  1772.  
  1773.                          DTA_VisibleVert,         visible,
  1774.                          DTA_TotalVert,           totalh,
  1775.                          DTA_VertUnit,            vunit,
  1776.  
  1777.                          DTA_VisibleHoriz,        (ULONG)(domain -> Width / hunit),
  1778.                          DTA_TotalHoriz,          totalw,
  1779.                          DTA_HorizUnit,           hunit,
  1780.  
  1781.                          DTA_Title,               title,
  1782.                          DTA_Busy,                busy,
  1783.                          DTA_Sync,                TRUE,
  1784.                          TAG_DONE );
  1785.     }
  1786.     else
  1787.     {
  1788.       /* Clear the layout flag */
  1789.       si -> si_Flags &= ~DTSIF_LAYOUT;
  1790.  
  1791.       D( kprintf( "no args\n" ) );
  1792.     }
  1793.  
  1794.     return( totalh );
  1795. }
  1796.  
  1797.  
  1798. /* Notify attribute changes (OM_NOTIFY) */
  1799. ULONG notifyAttrChanges( Object *o, struct GadgetInfo *ginfo, ULONG flags, Tag tag1, ... )
  1800. {
  1801.     struct opUpdate opu;
  1802.  
  1803.     opu . MethodID     = OM_NOTIFY;
  1804.     opu . opu_AttrList = (struct TagItem *)(&tag1);
  1805.     opu . opu_GInfo    = ginfo;
  1806.     opu . opu_Flags    = flags;
  1807.  
  1808.     return( DoMethodA( o, (Msg)(&opu) ) );
  1809. }
  1810.  
  1811.  
  1812. /* Destroy list of visible members and their domain boxes */
  1813. void DestroyVisibleList( struct ClassBase *cb, Object *o, struct EmbedInstData *eid )
  1814. {
  1815.     struct MinNode *worknode,
  1816.                    *nextnode;
  1817.  
  1818.     worknode = eid -> eid_VisibleMembers . mlh_Head;
  1819.  
  1820.     while( nextnode = worknode -> mln_Succ )
  1821.     {
  1822.       struct EmbedLine *work = VisibleLink2EmbedLine( worknode );
  1823.  
  1824.       if( work -> el_Object )
  1825.       {
  1826.         struct IBox *domain = NULL;
  1827.  
  1828.         if( GetDTAttrs( (work -> el_Object), DTA_Domain, (&domain), TAG_DONE ) == 1UL )
  1829.         {
  1830.           if( domain )
  1831.           {
  1832.             /* destroy domain box that the member can draw anything during layout */
  1833.             domain -> Left  = domain -> Top    = SHRT_MAX;
  1834.             domain -> Width = domain -> Height = 0;
  1835.           }
  1836.         }
  1837.       }
  1838.  
  1839.       worknode = nextnode;
  1840.     }
  1841.  
  1842.     NewList( (struct List *)(&(eid -> eid_VisibleMembers)) );
  1843. }
  1844.  
  1845.  
  1846. /* Create list of currently visible members (gadgets) */
  1847. void CreateVisibleList( struct ClassBase *cb, Object *o, struct EmbedInstData *eid, struct IBox *domain, struct GadgetInfo *gi )
  1848. {
  1849.     struct DTSpecialInfo    *si  = (struct DTSpecialInfo *)(G( o ) -> SpecialInfo);
  1850.     struct EmbedLine        *worknode,
  1851.                             *nextnode;
  1852.     ULONG                    offset_horiz = (si -> si_TopHoriz) * MAX( (si -> si_HorizUnit), 1L );
  1853.     ULONG                    offset_vert  = (si -> si_TopVert)  * MAX( (si -> si_VertUnit),  1L );
  1854.  
  1855.     /* Bump visiblebox of lines */
  1856.     worknode = (struct EmbedLine *)(eid -> eid_LineList -> mlh_Head);
  1857.  
  1858.     while( nextnode = (struct EmbedLine *)(worknode -> el_Line . ln_Link . mln_Succ) )
  1859.     {
  1860.       BOOL  visible = TRUE;
  1861.       LONG  topvert   = 0L,
  1862.             tophoriz  = 0L,
  1863.             totvert   = 0L,
  1864.             tothoriz  = 0L,
  1865.             vertunit  = 0L,
  1866.             horizunit = 0L,
  1867.             vertpix,
  1868.             horizpix;
  1869.  
  1870.       if( (worknode -> el_Object) && (worknode -> el_IsDTObject) )
  1871.       {
  1872.         GetDTAttrs( (worknode -> el_Object), DTA_TopVert,    (&topvert),
  1873.                                              DTA_TopHoriz,   (&tophoriz),
  1874.                                              DTA_TotalVert,  (&totvert),
  1875.                                              DTA_TotalHoriz, (&tothoriz),
  1876.                                              DTA_VertUnit,   (&vertunit),
  1877.                                              DTA_HorizUnit,  (&horizunit),
  1878.                                              TAG_DONE );
  1879.  
  1880. #if 0
  1881.         vertpix  = topvert  * MAX( vertunit,  1L );
  1882.         horizpix = tophoriz * MAX( horizunit, 1L );
  1883. #endif
  1884.       }
  1885.       else
  1886.       {
  1887.         vertunit  = si -> si_VertUnit;
  1888.         horizunit = si -> si_HorizUnit;
  1889.         totvert   = si -> si_TotVert;
  1890.         tothoriz  = si -> si_TotHoriz;
  1891.       }
  1892.  
  1893.       worknode -> el_VisibleBox . Left    = (worknode -> el_LineBox . Left) - offset_horiz + (domain -> Left);
  1894.       worknode -> el_VisibleBox . Top     = (worknode -> el_LineBox . Top)  - offset_vert  + (domain -> Top);
  1895.       worknode -> el_VisibleBox . Width   = worknode -> el_LineBox . Width;
  1896.       worknode -> el_VisibleBox . Height  = worknode -> el_LineBox . Height;
  1897.  
  1898.       if( (worknode -> el_VisibleBox . Left) < (domain -> Left) )
  1899.       {
  1900.         horizpix                           = ((domain -> Left) - (worknode -> el_VisibleBox . Left)) * horizunit;
  1901.         worknode -> el_VisibleBox . Width -= (domain -> Left) - (worknode -> el_VisibleBox . Left);
  1902.         worknode -> el_VisibleBox . Left   = domain -> Left;
  1903.       }
  1904.       else
  1905.       {
  1906.         horizpix = 0UL;
  1907.       }
  1908.  
  1909.       if( (worknode -> el_VisibleBox . Top) < (domain -> Top) )
  1910.       {
  1911.         vertpix                             = ((domain -> Top) - (worknode -> el_VisibleBox . Top)) * vertunit;
  1912.         worknode -> el_VisibleBox . Height -= (domain -> Top) - (worknode -> el_VisibleBox . Top);
  1913.         worknode -> el_VisibleBox . Top     = domain -> Top;
  1914.       }
  1915.       else
  1916.       {
  1917.         vertpix = 0UL;
  1918.       }
  1919.  
  1920.       if( ((worknode -> el_VisibleBox . Left) >= ((domain -> Left) + (domain -> Width)) )  ||
  1921.           ((worknode -> el_VisibleBox . Top)  >= ((domain -> Top)  + (domain -> Height)) ) ||
  1922.           ((worknode -> el_VisibleBox . Left) <  (domain -> Left) )                        ||
  1923.           ((worknode -> el_VisibleBox . Top)  <  (domain -> Top) ) )
  1924.       {
  1925.         visible = FALSE;
  1926.       }
  1927.  
  1928.       if( ((worknode -> el_VisibleBox . Left) + (worknode -> el_VisibleBox . Width)) > ((domain -> Left) + (domain -> Width)) )
  1929.       {
  1930.         worknode -> el_VisibleBox . Width -= ((worknode -> el_VisibleBox . Left) + (worknode -> el_VisibleBox . Width)) - ((domain -> Left) + (domain -> Width));
  1931.       }
  1932.  
  1933.       if( ((worknode -> el_VisibleBox . Top) + (worknode -> el_VisibleBox . Height)) > ((domain -> Top) + (domain -> Height)) )
  1934.       {
  1935.         worknode -> el_VisibleBox . Height -= ((worknode -> el_VisibleBox . Top) + (worknode -> el_VisibleBox . Height)) - ((domain -> Top) + (domain -> Height));
  1936.       }
  1937.  
  1938.       /* Is visible, 2nd */
  1939.       if( ((worknode -> el_VisibleBox . Left) >= ((domain -> Left) + (domain -> Width)) )  ||
  1940.           ((worknode -> el_VisibleBox . Top)  >= ((domain -> Top)  + (domain -> Height)) ) ||
  1941.           ((worknode -> el_VisibleBox . Left) <  (domain -> Left) )                        ||
  1942.           ((worknode -> el_VisibleBox . Top)  <  (domain -> Top) ) )
  1943.       {
  1944.         visible = FALSE;
  1945.       }
  1946.  
  1947.       /* Is visible, 3rd */
  1948.       if( ((worknode -> el_VisibleBox . Left) < 0)  || ((worknode -> el_VisibleBox . Top)    < 0) ||
  1949.           ((worknode -> el_VisibleBox . Width) < 0) || ((worknode -> el_VisibleBox . Height) < 0) )
  1950.       {
  1951.         visible = FALSE;
  1952.       }
  1953.  
  1954.       if( visible )
  1955.       {
  1956. #ifdef DRAW_BOX_AROUND_OBJECT
  1957.         if( worknode -> el_Object )
  1958.         {
  1959.           /* Reduce gadget box that the 0-color box fits around the object.
  1960.            * BUG: This causes problems because the domain box is now smaller than the wanted
  1961.            *      optimum size.
  1962.            */
  1963.           worknode -> el_VisibleBox . Left   += 1;
  1964.           worknode -> el_VisibleBox . Top    += 1;
  1965.           worknode -> el_VisibleBox . Width  -= 2;
  1966.           worknode -> el_VisibleBox . Height -= 2;
  1967.         }
  1968. #endif /* DRAW_BOX_AROUND_OBJECT */
  1969.  
  1970.         AddTail( (struct List *)(&(eid -> eid_VisibleMembers)), (struct Node *)(&(worknode -> el_VisibleLink)) );
  1971.       }
  1972.       else
  1973.       {
  1974.         /* member has no box, move it out of the visible area... */
  1975.         worknode -> el_VisibleBox . Left  = worknode -> el_VisibleBox . Top    = SHRT_MAX;
  1976.         worknode -> el_VisibleBox . Width = worknode -> el_VisibleBox . Height = 0;
  1977.       }
  1978.  
  1979.       /* Recalculate current topvert/tophoriz */
  1980.       topvert  = vertpix  / MAX( vertunit,  1L );
  1981.       tophoriz = horizpix / MAX( horizunit, 1L );
  1982.  
  1983.       /* Check limits */
  1984.       topvert  = MIN( topvert,  totvert  );
  1985.       tophoriz = MIN( tophoriz, tothoriz );
  1986.  
  1987.       /* Store... */
  1988.       worknode -> el_TopVert  = topvert;
  1989.       worknode -> el_TopHoriz = tophoriz;
  1990.  
  1991.       if( worknode -> el_Object )
  1992.       {
  1993.         ULONG width  = worknode -> el_VisibleBox . Width,
  1994.               height = worknode -> el_VisibleBox . Height;
  1995.  
  1996.         /* Restore flags (V40 bug workaround) */
  1997.         G( (worknode -> el_Object) ) -> Flags |= GFLG_RELSPECIAL;
  1998.  
  1999.         FreeBitMap( (worknode -> el_ObjectBitMap) );
  2000.         worknode -> el_ObjectBitMap = NULL;
  2001.  
  2002.         /* If the object can' clip, we don't reduce it's gadget box size here. Instead, the object
  2003.          * renders into a hidden bitmap which is copied into the visible area on demand
  2004.          */
  2005.         if( (worknode -> el_ObjectCanClip) == FALSE )
  2006.         {
  2007. #ifdef DRAW_BOX_AROUND_OBJECT
  2008.           if( ((width  + 2) < (worknode -> el_LineBox . Width)) ||
  2009.               ((height + 2) < (worknode -> el_LineBox . Height)) )
  2010. #else
  2011.           if( (width  < (worknode -> el_LineBox . Width)) ||
  2012.               (height < (worknode -> el_LineBox . Height)) )
  2013. #endif /* DRAW_BOX_AROUND_OBJECT */
  2014.           {
  2015.             worknode -> el_ObjectIsClipped = TRUE;
  2016.  
  2017.             worknode -> el_ObjectBitMap = AllocBitMap( ((worknode -> el_LineBox . Width)  + 16UL),
  2018.                                                        ((worknode -> el_LineBox . Height) + 16UL),
  2019.                                                        (ULONG)(gi -> gi_RastPort -> BitMap -> Depth),
  2020.                                                        (BMF_CLEAR | BMF_MINPLANES), (gi -> gi_RastPort -> BitMap) );
  2021.  
  2022.             kprintf( "object is clipped tv %lu th %lu\n", (worknode -> el_TopVert), (worknode -> el_TopHoriz) );
  2023.           }
  2024.           else
  2025.           {
  2026.             worknode -> el_ObjectIsClipped = FALSE;
  2027.  
  2028.             kprintf( "object is not clipped\n" );
  2029.           }
  2030.  
  2031.           width  = worknode -> el_LineBox . Width;
  2032.           height = worknode -> el_LineBox . Height;
  2033.         }
  2034.  
  2035.         if( worknode -> el_ObjectIsClipped )
  2036.         {
  2037.           /* Set new box (no gadgetinfo, the refresh/redraw is done later) */
  2038.           SetAttrs( (worknode -> el_Object), GA_Left,      0UL,
  2039.                                              GA_Top,       0UL,
  2040.                                              GA_Width,     width,
  2041.                                              GA_Height,    height,
  2042.                                              DTA_TopVert,  (worknode -> el_TopVert),
  2043.                                              DTA_TopHoriz, (worknode -> el_TopHoriz),
  2044.                                              TAG_DONE );
  2045.         }
  2046.         else
  2047.         {
  2048.           /* Set new box (no gadgetinfo, the refresh/redraw is done later) */
  2049.           SetAttrs( (worknode -> el_Object), GA_Left,      (worknode -> el_VisibleBox . Left),
  2050.                                              GA_Top,       (worknode -> el_VisibleBox . Top),
  2051.                                              GA_Width,     width,
  2052.                                              GA_Height,    height,
  2053.                                              DTA_TopVert,  (worknode -> el_TopVert),
  2054.                                              DTA_TopHoriz, (worknode -> el_TopHoriz),
  2055.                                              TAG_DONE );
  2056.         }
  2057.       }
  2058.  
  2059.       worknode = nextnode;
  2060.     }
  2061. }
  2062.  
  2063.  
  2064. DISPATCHERFLAGS
  2065. ULONG DispatchModel( REGA0 struct IClass *cl, REGA2 Object *o, REGA1 Msg msg )
  2066. {
  2067.     struct ClassBase          *cb = (struct ClassBase *)(cl -> cl_UserData);
  2068.     struct EmbedModelInstData *emid;
  2069.     ULONG                      retval = 0UL;
  2070.  
  2071.     switch( msg -> MethodID )
  2072.     {
  2073.         case OM_NEW:
  2074.         {
  2075.             struct EmbedLine *el;
  2076.             Object           *dt;
  2077.  
  2078.             if( el = (struct EmbedLine *)GetTagData( EMBEDA_SyncObjectLine, 0UL, (((struct opSet *)msg) -> ops_AttrList) ) )
  2079.             {
  2080.               dt = el -> el_Object;
  2081.  
  2082.               if( retval = DoSuperMethodA( cl, o, msg ) )
  2083.               {
  2084.                 /* Get a pointer to the object data */
  2085.                 emid = (struct EmbedModelInstData *)INST_DATA( cl, (Object *)retval );
  2086.  
  2087.                 emid -> emid_ObjectLine = el;
  2088.                 emid -> emid_Busy       = IsKindOf( cb, dt, NULL, DATATYPESCLASS ); /* datatypesclass objects are "busy" at their
  2089.                                                                                  * initial entry in the window and will tell
  2090.                                                                                  * us about any change
  2091.                                                                                  */
  2092.                 emid -> emid_Sync   = FALSE;
  2093.               }
  2094.             }
  2095.         }
  2096.             break;
  2097.  
  2098.         case OM_UPDATE:
  2099.         {
  2100.             /* Avoid OM_NOTIFY loops */
  2101.             if( DoMethod( o, ICM_CHECKLOOP ) )
  2102.             {
  2103.               break;
  2104.             }
  2105.         }
  2106.         case OM_SET:
  2107.         {
  2108.             struct TagItem *tstate,
  2109.                            *ti;
  2110.             BOOL            sync = FALSE;
  2111.  
  2112.             /* Get a pointer to the object data */
  2113.             emid = (struct EmbedModelInstData *)INST_DATA( cl, o );
  2114.  
  2115.             tstate = ((struct opSet *)msg) -> ops_AttrList;
  2116.  
  2117.             while( ti = NextTagItem( (&tstate) ) )
  2118.             {
  2119.               switch( ti -> ti_Tag )
  2120.               {
  2121.                 case DTA_Sync:
  2122.                 {
  2123.                     emid -> emid_Sync = ti -> ti_Data;
  2124.                     sync = TRUE;
  2125.                 }
  2126.                     break;
  2127.  
  2128.                 case DTA_Busy:
  2129.                 {
  2130.                     emid -> emid_Busy = ti -> ti_Data;
  2131.                     sync = TRUE;
  2132.                 }
  2133.                     break;
  2134.               }
  2135.             }
  2136.  
  2137.             if( sync )
  2138.             {
  2139.               notifyAttrChanges( o, (((struct opSet *)msg) -> ops_GInfo), 0UL,
  2140.                                  EMBEDA_Sync,           (emid -> emid_Sync),
  2141.                                  EMBEDA_SyncObjectLine, (emid -> emid_ObjectLine),
  2142.                                  TAG_DONE );
  2143.             }
  2144.         }
  2145.             break;
  2146.  
  2147.         /* Let the superclass handle everything else */
  2148.         default:
  2149.         {
  2150.             retval = DoSuperMethodA( cl, o, msg );
  2151.         }
  2152.             break;
  2153.     }
  2154.  
  2155.     return( retval );
  2156. }
  2157.  
  2158.  
  2159. BOOL IsModelBusy( struct ClassBase *cb, Object *model )
  2160. {
  2161.     if( model )
  2162.     {
  2163.       /* "hack way": Access model instance data like "white box" */
  2164.       struct EmbedModelInstData *emid = (struct EmbedModelInstData *)INST_DATA( (cb -> cb_EmbedModel), model );
  2165.  
  2166.       return( (emid -> emid_Busy) );
  2167.     }
  2168.  
  2169.     return( FALSE );
  2170. }
  2171.  
  2172.  
  2173. struct IBox GetRelGadgetBox( struct IBox *domain, struct ExtGadget *g, struct IBox *absbox )
  2174. {
  2175.     struct IBox retbox = { 0, 0, 0, 0 };
  2176.  
  2177.     if( domain && g && absbox )
  2178.     {
  2179.       retbox = *absbox;
  2180.  
  2181.       if( (g -> Flags) & GFLG_RELBOTTOM )
  2182.       {
  2183.         (retbox . Top) -= ((domain -> Top) + (domain -> Height));
  2184.       }
  2185.  
  2186.       if( (g -> Flags) & GFLG_RELRIGHT )
  2187.       {
  2188.         (retbox . Left) -= ((domain -> Left) + (domain -> Width));
  2189.       }
  2190.  
  2191.       if( (g -> Flags) & GFLG_RELWIDTH )
  2192.       {
  2193.         (retbox . Width) -= (domain -> Width);
  2194.       }
  2195.  
  2196.       if( (g -> Flags) & GFLG_RELHEIGHT )
  2197.       {
  2198.         (retbox . Height) -= (domain -> Height);
  2199.       }
  2200.    }
  2201.  
  2202.    return( retbox );
  2203. }
  2204.  
  2205.  
  2206. struct IBox GetAbsGadgetBox( struct IBox *domain, struct ExtGadget *g, BOOL useBounds )
  2207. {
  2208.     struct IBox retbox = { 0, 0, 0, 0 };
  2209.  
  2210.     if( domain && g )
  2211.     {
  2212.       if( ((g -> MoreFlags) & GMORE_BOUNDS) && useBounds )
  2213.       {
  2214.         retbox = *((struct IBox *)(&(g -> BoundsLeftEdge)));
  2215.       }
  2216.       else
  2217.       {
  2218.         retbox = *(GADGET_BOX( g ));
  2219.       }
  2220.  
  2221.       if( (g -> Flags) & GFLG_RELBOTTOM )
  2222.       {
  2223.         (retbox . Top) += ((domain -> Top) + (domain -> Height));
  2224.       }
  2225.  
  2226.       if( (g -> Flags) & GFLG_RELRIGHT )
  2227.       {
  2228.         (retbox . Left) += ((domain -> Left) + (domain -> Width));
  2229.       }
  2230.  
  2231.       if( (g -> Flags) & GFLG_RELWIDTH )
  2232.       {
  2233.         (retbox . Width) += (domain -> Width);
  2234.       }
  2235.  
  2236.       if( (g -> Flags) & GFLG_RELHEIGHT )
  2237.       {
  2238.         (retbox . Height) += (domain -> Height);
  2239.       }
  2240.     }
  2241.  
  2242.     return( retbox );
  2243. }
  2244.  
  2245.  
  2246. ULONG DoMemberHitTest( struct IBox *domain, Object *member, struct gpHitTest *gpht )
  2247. {
  2248.     ULONG              retval;
  2249.     struct IBox        gbox;
  2250.     struct GadgetInfo *gi;
  2251.  
  2252.     retval = 0UL;
  2253.     gi     = gpht -> gpht_GInfo;
  2254.  
  2255.     gbox = GetAbsGadgetBox( (&(gi -> gi_Domain)), EXTG( member ), (BOOL)((gpht -> MethodID) == GM_HELPTEST) );
  2256.  
  2257.     (gpht -> gpht_Mouse . X) -= ((gbox . Left) - (domain -> Left));
  2258.     (gpht -> gpht_Mouse . Y) -= ((gbox . Top)  - (domain -> Top));
  2259.  
  2260.     /* Mouse coordinates must be inside members's select box */
  2261.     if( ((gpht -> gpht_Mouse . X) >= 0)              &&
  2262.         ((gpht -> gpht_Mouse . Y) >= 0)              &&
  2263.         ((gpht -> gpht_Mouse . X) <= (gbox . Width)) &&
  2264.         ((gpht -> gpht_Mouse . Y) <= (gbox . Height)) )
  2265.     {
  2266.       retval = DoMethodA( member, (Msg)gpht );
  2267.     }
  2268.  
  2269.     (gpht -> gpht_Mouse . X) += ((gbox . Left) - (domain -> Left));
  2270.     (gpht -> gpht_Mouse . Y) += ((gbox . Top)  - (domain -> Top));
  2271.  
  2272.     return( retval );
  2273. }
  2274.  
  2275.  
  2276. BOOL BumpMembers( struct IClass *cl, Object *o, struct GadgetInfo *gi )
  2277. {
  2278.     if( o && gi )
  2279.     {
  2280.       struct EmbedInstData *eid = (struct EmbedInstData *)INST_DATA( cl, o );
  2281.       struct DTSpecialInfo *si  = (struct DTSpecialInfo *)(G( o ) -> SpecialInfo);
  2282.  
  2283.       /* Be sure that all members (gadgets) are on the right place when redrawing ! */
  2284.       if( ((si -> si_TopVert)  != (eid -> eid_OldTopVert))  ||
  2285.           ((si -> si_TopHoriz) != (eid -> eid_OldTopHoriz)) ||
  2286.           ((gi -> gi_Domain)   != (eid -> eid_OldParentDomain)) )
  2287.       {
  2288.         struct gpLayout gpl;
  2289.  
  2290.         if( (gi -> gi_Domain) != (eid -> eid_OldParentDomain) )
  2291.         {
  2292.           D( kprintf( "posted layout !?\n" ) );
  2293.         }
  2294.  
  2295.         eid -> eid_OldTopVert      = si -> si_TopVert;
  2296.         eid -> eid_OldTopHoriz     = si -> si_TopHoriz;
  2297.         eid -> eid_OldParentDomain = gi -> gi_Domain;
  2298.  
  2299.         /* Do "size" layout, which moves the members */
  2300.         gpl . MethodID    = GM_LAYOUT;
  2301.         gpl . gpl_GInfo   = gi;
  2302.         gpl . gpl_Initial = 0L;
  2303.  
  2304.         DoMethodA( o, (Msg)(&gpl) );
  2305.  
  2306.         return( TRUE );
  2307.       }
  2308.     }
  2309.  
  2310.     return( FALSE );
  2311. }
  2312.  
  2313.  
  2314. /* Create a copy from the given GadgetInfo with a HIDDEN bitmap.
  2315.  * "bounds" is the absoute gadget box in win/req. cooridnates
  2316.  */
  2317. static
  2318. struct GadgetInfo *CreateGadgetInfoClipBuffer( struct ClassBase *cb, struct GadgetInfo *gi, struct EmbedLine *el )
  2319. {
  2320.     if( cb && gi && el )
  2321.     {
  2322.       struct GadgetInfo *ggi;
  2323.       ULONG              size1,
  2324.                          size;
  2325.  
  2326.       /* We merge'ed multiple AllocVec's to one below. size#? are the memory block
  2327.        * offsets in the allocated buffer, size the the total buffer length
  2328.        */
  2329.       size1 =         sizeof( struct GadgetInfo ) + 8UL;
  2330.       size  = size1 + sizeof( struct RastPort   ) + 8UL;
  2331.  
  2332.       if( ggi = (struct GadgetInfo *)AllocVec( size, (MEMF_PUBLIC | MEMF_CLEAR) ) )
  2333.       {
  2334. #if 0
  2335.         struct BitMap   *srcbm  = gi -> gi_RastPort -> BitMap,
  2336.                         *bm;
  2337.         struct RastPort *rp;
  2338. #endif
  2339.  
  2340.         struct RastPort *grp    = (struct RastPort *)MEMORY_NAL_FOLLOWING( ggi, size1 );
  2341.  
  2342.         /* Init RastPort */
  2343.         InitRastPort( grp );
  2344.  
  2345.         if( grp -> BitMap = el -> el_ObjectBitMap )
  2346.         {
  2347. #if 0
  2348.           if( rp = ObtainGIRPort( gi ) )
  2349.           {
  2350.             /* Copy front buffer into our tmp. bitmap */
  2351.             ClipBlit( rp,
  2352.                       (long)(el -> el_VisibleBox . Left),
  2353.                       (long)(el -> el_VisibleBox . Top),
  2354.                       grp,
  2355.                       (long)(el -> el_TopHoriz),
  2356.                       (long)(el -> el_TopVert),
  2357.                       (long)(el -> el_VisibleBox . Width),
  2358.                       (long)(el -> el_VisibleBox . Height),
  2359.                       0xC0 );
  2360.  
  2361.             WaitBlit();
  2362.  
  2363.             ReleaseGIRPort( rp );
  2364.           }
  2365.           else
  2366.           {
  2367.             kprintf( "CreateGadgetInfoClipBuffer/ObtainGIRPort failed\n" );
  2368.           }
  2369. #endif
  2370.  
  2371.           /* Init GadgetInfo */
  2372.           *ggi = *gi;
  2373.           ggi -> gi_RastPort = grp;
  2374.  
  2375.           return( ggi );
  2376.         }
  2377.  
  2378.         FreeVec( ggi );
  2379.       }
  2380.       else
  2381.       {
  2382.         kprintf( "CreateGadgetInfoClipBuffer AllocVec\n" );
  2383.       }
  2384.     }
  2385.     else
  2386.     {
  2387.       kprintf( "CreateGadgetInfoClipBuffer wrong args\n" );
  2388.     }
  2389.  
  2390.     return( NULL );
  2391. }
  2392.  
  2393.  
  2394. static
  2395. void FreeGadgetInfoClipBuffer( struct ClassBase *cb, struct GadgetInfo *ggi )
  2396. {
  2397.     if( cb && ggi )
  2398.     {
  2399.       FreeVec( ggi );
  2400.     }
  2401. }
  2402.  
  2403.  
  2404. static
  2405. void SyncGadgetInfoClipBuffer( struct ClassBase *cb, struct GadgetInfo *gi, struct GadgetInfo *ggi, struct EmbedLine *el )
  2406. {
  2407.     if( cb && gi && ggi && el )
  2408.     {
  2409.       struct RastPort *rp;
  2410.  
  2411.       if( rp = ObtainGIRPort( gi ) )
  2412.       {
  2413.         ClipBlit( (ggi -> gi_RastPort),
  2414.                   (long)(el -> el_TopHoriz),
  2415.                   (long)(el -> el_TopVert),
  2416.                   rp,
  2417.                   (long)(el -> el_VisibleBox . Left),
  2418.                   (long)(el -> el_VisibleBox . Top),
  2419.                   (long)(el -> el_VisibleBox . Width),
  2420.                   (long)(el -> el_VisibleBox . Height),
  2421.                   0xC0 );
  2422.  
  2423.         WaitBlit();
  2424.  
  2425.         ReleaseGIRPort( rp );
  2426.       }
  2427.       else
  2428.       {
  2429.         kprintf( "SyncGadgetInfoClipBuffer/ObtainGIRPort failed\n" );
  2430.       }
  2431.     }
  2432.     else
  2433.     {
  2434.       kprintf( "SyncGadgetInfoClipBuffer wrong args\n" );
  2435.     }
  2436. }
  2437.  
  2438.  
  2439. /* offloaded from my objecttools.library */
  2440. static
  2441. BOOL IsKindOf( struct ClassBase *cb, Object *object, struct IClass *searchclass, ClassID searchclassID )
  2442. {
  2443.     if( object && (searchclass || searchclassID) )
  2444.     {
  2445.       struct IClass *workclass,
  2446.                     *superclass;
  2447.  
  2448.       workclass = OCLASS( object );
  2449.  
  2450.       if( searchclass )
  2451.       {
  2452.         /* Check for touch down at the rootclass,
  2453.          * (root of this class tree, ((workclass -> cl_Super) == NULL) ) => QUIT
  2454.          */
  2455.         while( superclass = workclass -> cl_Super )
  2456.         {
  2457.           /* Match this class searchclass ? */
  2458.           if( searchclass == workclass )
  2459.           {
  2460.             return( TRUE );
  2461.           }
  2462.  
  2463.           /* workclass = superclass of old workclass */
  2464.           workclass = superclass;
  2465.         }
  2466.       }
  2467.       else
  2468.       {
  2469.         if( searchclassID )
  2470.         {
  2471.           /* Check for touch down at the rootclass,
  2472.            * (root of this class tree, ((workclass -> cl_Super) == NULL) ) => QUIT
  2473.            */
  2474.           while( superclass = workclass -> cl_Super )
  2475.           {
  2476.             /* Match this classID searchclassID ? */
  2477.             if( !Stricmp( (workclass -> cl_ID), searchclassID ) )
  2478.             {
  2479.               return( TRUE );
  2480.             }
  2481.  
  2482.             /* workclass = superclass of old workclass */
  2483.             workclass = superclass;
  2484.           }
  2485.         }
  2486.       }
  2487.     }
  2488.     else
  2489.     {
  2490.       kprintf( "IsKindOf: wrong args %lx %lx %lx \"%s\"\n", object, searchclass, searchclassID, searchclassID );
  2491.     }
  2492.  
  2493.     return( FALSE );
  2494. }
  2495.  
  2496.  
  2497.  
  2498.