home *** CD-ROM | disk | FTP | other *** search
/ Aminet 18 / aminetcdnumber181997.iso / Aminet / misc / emu / AROSdev.lha / AROS / rom / intuition / icclass.c < prev    next >
C/C++ Source or Header  |  1997-01-27  |  7KB  |  311 lines

  1. /* AROS icclass implementation
  2.  * 10/25/96 caldi@usa.nai.net
  3.  */
  4.  
  5. #include <exec/types.h>
  6.  
  7. #include <dos/dos.h>
  8. #include <dos/dosextens.h>
  9.  
  10. #include <intuition/intuition.h>
  11. #include <intuition/intuitionbase.h>
  12. #include <intuition/classes.h>
  13. #include <intuition/classusr.h>
  14. #include <intuition/gadgetclass.h>
  15. #include <intuition/cghooks.h>
  16. #include <intuition/icclass.h>
  17.  
  18. #include <graphics/gfxbase.h>
  19. #include <graphics/gfxmacros.h>
  20.  
  21. #include <utility/tagitem.h>
  22. #include <utility/hooks.h>
  23.  
  24. #include <clib/macros.h>
  25.  
  26. #include <proto/exec.h>
  27. #include <proto/intuition.h>
  28. #include <proto/graphics.h>
  29. #include <proto/utility.h>
  30.  
  31. #ifdef _AROS
  32. #include <aros/asmcall.h>
  33. #include <proto/alib.h>
  34. #include "intuition_intern.h"
  35. #endif
  36.  
  37. /****************************************************************************/
  38.  
  39.  
  40. /****************************************************************************/
  41.  
  42. struct ICData
  43. {
  44.     Object       * ic_Target;
  45.     struct TagItem * ic_Mapping;
  46.     struct TagItem * ic_CloneTags;
  47.     ULONG         ic_LoopCounter;
  48. };
  49.  
  50. /****************************************************************************/
  51.  
  52. #undef IntuitionBase
  53. #define IntuitionBase     ((struct IntuitionBase *)(cl->cl_UserData))
  54.  
  55. #ifdef ICTARGET
  56.  
  57. /* This nifty routine (hopefully) allows us to send a IDCMP message from a boopsi gadget method.
  58.  *
  59.  * It does not seem like we can support ICTARGET_IDCMP until AROS has a real compatible intuition :)
  60.  */
  61. static struct IntuiMessage SendIDCMPUpdate( Class *cl, Object *o, struct opUpdate *msg, ULONG Class, UWORD Code, APTR IAddress )
  62. {
  63.     struct IntuiMessage *imsg;
  64.  
  65.     imsg = msg->opu_GInfo->gi_Window->MessageKey;
  66.  
  67.     while( imsg && !(imsg->Class & IDCMP_LONELYMESSAGE) )
  68.     {
  69.     imsg = imsg->SpecialLink;
  70.     }
  71.  
  72.     if( !imsg )
  73.     {
  74.     if( imsg = AllocMem( sizeof( struct ExtIntuiMessage ), MEMF_CLEAR ) )
  75.     {
  76.         imsg->SpecialLink = msg->opu_GInfo->gi_Window->MessageKey;
  77.         msg->opu_GInfo->gi_Window->MessageKey = imsg->SpecialLink;
  78.         imsg->ExecMessage.mn_ReplyPort = msg->opu_GInfo->gi_Window->WindowPort;
  79.     }
  80.     }
  81.  
  82.     if( imsg )
  83.     {
  84.     imsg->Class = Class;
  85.     imsg->Code = Code;
  86.     imsg->Qualifier = 0;
  87.     imsg->IAddress = IAddress;
  88.     imsg->MouseX = 0;
  89.     imsg->MouseY = 0;
  90.     imsg->Seconds = 0;
  91.     imsg->Micros = 0;
  92.     imsg->IDCMPWindow = msg->opu_GInfo->gi_Window;
  93.  
  94.     PutMsg( msg->opu_GInfo->gi_Window->UserPort, (struct Message *)imsg );
  95.     }
  96.     return( imsg );
  97. }
  98. #endif
  99.  
  100.  
  101. /* Send update notification to target
  102.  */
  103. static ULONG notify_icclass(Class *cl, Object *o, struct opUpdate *msg)
  104. {
  105.     struct ICData * ic = INST_DATA(cl,o);
  106.  
  107.     if ( ic->ic_Target != NULL )
  108.     {
  109.     if ( (msg->opu_AttrList) && (msg->opu_GInfo) )
  110.     {
  111.         ic->ic_LoopCounter += 1UL;
  112.  
  113.         /* don't get caught in a circular notify target loop */
  114.         if ( ic->ic_LoopCounter == 1UL)
  115.         {
  116.         if (ic->ic_Target != (Object *)ICTARGET_IDCMP)
  117.         {
  118.             if ((ic->ic_CloneTags = CloneTagItems(msg->opu_AttrList)))
  119.             {
  120.             if (ic->ic_Mapping != NULL)
  121.             {
  122.                 MapTags(ic->ic_CloneTags, ic->ic_Mapping, TRUE);
  123.             }
  124.  
  125.             DoMethod( ic->ic_Target,
  126.                 OM_UPDATE,
  127.                 ic->ic_CloneTags,
  128.                 msg->opu_GInfo,
  129.                 msg->opu_Flags);
  130.  
  131.             FreeTagItems(ic->ic_CloneTags);
  132.             }
  133.         }
  134. #ifdef ICTARGET
  135.         else
  136.         {
  137.             if ( ic->ic_CloneTags = CloneTagItems(msg->opu_AttrList) )
  138.             {
  139.             if (ic->ic_Mapping != NULL)
  140.             {
  141.                 MapTags(ic->ic_CloneTags, ic->ic_Mapping, TRUE);
  142.             }
  143.  
  144.             SendIDCMPUpdate( cl, o, msg, IDCMP_IDCMPUPDATE, 0, ic->ic_CloneTags);
  145.  
  146.             /* NOTE: ReplyMsg() must cause FreeTagItems(imsg->IAddress)
  147.              * when freeing a  IDCMP_IDCMPUPDATE message!!
  148.              */
  149.             }
  150.         }
  151. #endif
  152.         }
  153.  
  154.         ic->ic_LoopCounter -= 1UL;
  155.     }
  156.     }
  157.     return(1UL);
  158. }
  159.  
  160. /* icclass boopsi dispatcher
  161.  */
  162. AROS_UFH3(static IPTR, dispatch_icclass,
  163.     AROS_UFHA(Class *,  cl,  A0),
  164.     AROS_UFHA(Object *, o,   A2),
  165.     AROS_UFHA(Msg,      msg, A1)
  166. )
  167. {
  168.     IPTR retval = 0UL;
  169.     struct ICData *ic;
  170.  
  171.     if (msg->MethodID != OM_NEW)
  172.     ic = INST_DATA(cl, retval);
  173.  
  174.     switch(msg->MethodID)
  175.     {
  176.     case OM_NEW:
  177.     retval = DoSuperMethodA(cl, o, msg);
  178.  
  179.     if (!retval)
  180.         break;
  181.  
  182.     ic = INST_DATA(cl, retval);
  183.  
  184.     /* set some defaults */
  185.     ic->ic_Target     = NULL;
  186.     ic->ic_Mapping     = NULL;
  187.     ic->ic_CloneTags = NULL;
  188.  
  189.     /* Handle our special tags - overrides defaults */
  190.     /* set_icclass(cl, (Object*)retval, (struct opSet *)msg); */
  191.  
  192.     /* Fall through */
  193.  
  194.     case OM_SET:
  195.     {
  196.         struct TagItem *tstate = ((struct opSet *)msg)->ops_AttrList;
  197.         struct TagItem *tag;
  198.  
  199.         while ((tag = NextTagItem(&tstate)))
  200.         {
  201.         switch(tag->ti_Tag)
  202.         {
  203.         case ICA_MAP:
  204.             ic->ic_Mapping = (struct TagItem *)tag->ti_Data;
  205.             break;
  206.  
  207.         case ICA_TARGET:
  208.             ic->ic_Target = (Object *)tag->ti_Data;
  209.             break;
  210.         }
  211.         }
  212.     }
  213.     break;
  214.  
  215.     case OM_NOTIFY:
  216.     retval = (IPTR)notify_icclass(cl, o, (struct opUpdate *)msg);
  217.     break;
  218.  
  219.     case OM_DISPOSE:
  220.     {
  221.         struct ICData *ic = INST_DATA(cl, o);
  222.  
  223.         ic->ic_LoopCounter = 0UL;
  224.  
  225.         if(ic->ic_CloneTags)
  226.         {
  227.         FreeTagItems(ic->ic_CloneTags);
  228.         ic->ic_CloneTags = NULL;
  229.         }
  230.     }
  231.  
  232.     break;
  233.  
  234.     case OM_GET:
  235.     switch (((struct opGet *)msg)->opg_AttrID)
  236.     {
  237.     case ICA_MAP:
  238.         *((struct opGet *)msg)->opg_Storage = (ULONG)ic->ic_Mapping;
  239.         break;
  240.  
  241.     case ICA_TARGET:
  242.         *((struct opGet *)msg)->opg_Storage = (ULONG)ic->ic_Target;
  243.         break;
  244.     }
  245.  
  246.     break;
  247.  
  248.     /*
  249.     NOTE: I current don't see the purpose of the ICM_* methods
  250.     this implementation could be WAY off base...
  251.     */
  252.  
  253.     case  ICM_SETLOOP:          /* set/increment loop counter    */
  254.     {
  255.         struct ICData *ic = INST_DATA(cl, o);
  256.  
  257.         ic->ic_LoopCounter += 1UL;
  258.     }
  259.  
  260.     break;
  261.  
  262.     case  ICM_CLEARLOOP:    /* clear/decrement loop counter */
  263.     {
  264.         struct ICData *ic = INST_DATA(cl, o);
  265.  
  266.         ic->ic_LoopCounter -= 1UL;
  267.     }
  268.  
  269.     break;
  270.  
  271.     case  ICM_CHECKLOOP:    /* set/increment loop     */
  272.     {
  273.         struct ICData *ic = INST_DATA(cl, o);
  274.  
  275.         retval = (IPTR)ic->ic_LoopCounter;
  276.     }
  277.  
  278.     break;
  279.  
  280.     default:
  281.     retval = DoSuperMethodA(cl, o, msg);
  282.     break;
  283.     } /* switch */
  284.  
  285.     return retval;
  286. }  /* dispatch_icclass */
  287.  
  288. #undef IntuitionBase
  289.  
  290. /****************************************************************************/
  291.  
  292. /* Initialize our image class. */
  293. struct IClass *InitICClass (struct IntuitionBase * IntuitionBase)
  294. {
  295.     struct IClass *cl = NULL;
  296.  
  297.     /* This is the code to make the icclass...
  298.     */
  299.     if ( (cl = MakeClass(ICCLASS, ROOTCLASS, NULL, sizeof(struct ICData), 0)) )
  300.     {
  301.     cl->cl_Dispatcher.h_Entry    = (APTR)AROS_ASMSYMNAME(dispatch_icclass);
  302.     cl->cl_Dispatcher.h_SubEntry = NULL;
  303.     cl->cl_UserData          = (IPTR)IntuitionBase;
  304.  
  305.     AddClass (cl);
  306.     }
  307.  
  308.     return (cl);
  309. }
  310.  
  311.