home *** CD-ROM | disk | FTP | other *** search
- ;/* RKMModel.c - A simple custom modelclass subclass.
- LC -cfist -b1 -y -v -j73 rkmmodel.c
- quit ;*/
-
- #include <exec/types.h>
- #include <intuition/intuition.h>
- #include <intuition/classes.h>
- #include <intuition/classusr.h>
- #include <intuition/imageclass.h>
- #include <intuition/gadgetclass.h>
- #include <intuition/cghooks.h>
- #include <intuition/icclass.h>
- #include <utility/tagitem.h>
- #include <utility/hooks.h>
- #include <clib/intuition_protos.h>
- #include <clib/utility_protos.h>
- #include <clib/alib_protos.h>
- #include <clib/alib_stdio_protos.h>
-
- extern struct Library *IntuitionBase, *UtilityBase;
-
- /*************************************************************************************************/
- /**************** The attributes defined by this class *****************************************/
- /*************************************************************************************************/
- #define RKMMOD_CurrVal (TAG_USER + 1) /* This attribute is the current value of the model.*******/
- /**********************************************************/
- #define RKMMOD_Up (TAG_USER + 2) /* These two are fake attributes that rkmmodelclass *******/
- #define RKMMOD_Down (TAG_USER + 3) /* uses as pulse values to increment/decrement the *******/
- /* rkmmodel's RKMMOD_CurrVal attribute. *******/
- /**********************************************************/
- #define RKMMOD_Limit (TAG_USER + 4) /* This attribute contains the upper bound of the *******/
- /* rkmmodel's RKMMOD_CurrVal. The rkmmodel has a *******/
- /* static lower bound of zero. *******/
- /*************************************************************************************************/
-
- #define DEFAULTVALLIMIT 100L /* If the programmer doesn't set */
- /* RKMMOD_Limit, it defaults to this. */
- struct RKMModData {
- ULONG currval; /* The instance data for this class. */
- ULONG vallimit;
- };
-
- /*************************************************************************************************/
- /************************** The functions in this module ********************************/
- /*************************************************************************************************/
- void geta4(void); /***************/
- Class *initRKMModClass(void); /***************/
- BOOL freeRKMModClass(Class *); /***************/
- ULONG dispatchRKMModel(Class *, Object *, Msg); /***************/
- void NotifyCurrVal(Class *, Object *, struct opUpdate *, struct RKMModData *); /***************/
- /*************************************************************************************************/
-
- /*************************************************************************************************/
- /******************************** Initialize the class **************************************/
- /*************************************************************************************************/
- Class *initRKMModClass(void) /* Make the class and set */
- { /* up the dispatcher's hook. */
- Class *cl;
- extern ULONG HookEntry(); /* <------- defined in amiga.lib. */
-
- if ( cl = MakeClass( NULL,
- "modelclass", NULL,
- sizeof ( struct RKMModData ),
- 0 ))
- {
- cl->cl_Dispatcher.h_Entry = HookEntry; /* initialize the */
- cl->cl_Dispatcher.h_SubEntry = dispatchRKMModel; /* cl_Dispatcher */
- /* Hook. */
- }
- return ( cl );
- }
-
- /*************************************************************************************************/
- /********************************* Free the class ***************************************/
- /*************************************************************************************************/
- BOOL freeRKMModClass( Class *cl )
- {
- return (FreeClass(cl));
- }
-
- /*************************************************************************************************/
- /******************************** The class Dispatcher ***********************************/
- /*************************************************************************************************/
- ULONG dispatchRKMModel(Class *cl, Object *o, Msg msg)
- {
- struct RKMModData *mmd;
- APTR retval = NULL; /* A generic return value used by this class's methods. The */
- /* meaning of this field depends on the method. For example, */
- /* OM_GET uses this a a boolean return value, while OM_NEW */
- /* uses it as a pointer to the new object. */
- geta4(); /* SAS/C and Manx function - makes sure A4 contains global data pointer. */
-
- switch (msg->MethodID)
- {
- case OM_NEW: /* Pass message onto superclass first so it can set aside the memory */
- /* for the object and take care of superclass instance data. */
- if (retval = (APTR)DoSuperMethodA(cl, o, msg))
- { /************************************************************************/
- /* For the OM_NEW method, the object pointer passed to the dispatcher */
- /* does not point to an object (how could it? The object doesn't exist */
- /* yet.) DoSuperMethodA() returns a pointer to a newly created */
- /* object. INST_DATA() is a macro defined in <intuition/classes.h> */
- /* that returns a pointer to the object's instance data that is local */
- /* to this class. For example, the instance data local to this class */
- /* is the RKMModData structure defined above. */
- /************************************************************************/
- mmd = INST_DATA(cl, retval);
- mmd->currval = GetTagData(RKMMOD_CurrVal, 0L, /* initialize object's attributes. */
- ((struct opSet *)msg)->ops_AttrList);
- mmd->vallimit = GetTagData(RKMMOD_Limit, DEFAULTVALLIMIT,
- ((struct opSet *)msg)->ops_AttrList);
- }
- break;
- case OM_SET:
- case OM_UPDATE:
- mmd = INST_DATA(cl, o);
- DoSuperMethodA(cl, o, msg); /* Let the superclasses set their attributes first. */
- {
- struct TagItem *tstate, *ti; /* grab some temp variables off of the stack. */
-
- ti = ((struct opSet *)msg)->ops_AttrList;
- tstate = ti;
-
- /* Step through all of the attribute/value pairs in the list. Use the */
- /* utility.library tag functions to do this so they can properly process */
- /* special tag IDs like TAG_SKIP, TAG_IGNORE, etc. */
-
- while (ti = NextTagItem(&tstate)) /* Step through all of the attribute/value */
- { /* pairs in the list. Use the utility.library tag functions */
- /* to do this so they can properly process special tag IDs */
- /* like TAG_SKIP, TAG_IGNORE, etc. */
- switch (ti->ti_Tag)
- {
- case RKMMOD_CurrVal:
- if ((ti->ti_Data) > mmd->vallimit) ti->ti_Data =
- mmd->vallimit;
- mmd->currval = ti->ti_Data;
- NotifyCurrVal(cl, o, msg, mmd);
- retval = (APTR)1L; /* Changing RKMMOD_CurrVal can cause a visual */
- break; /* change to gadgets in the rkmmodel's broadcast */
- /* list. The rkmmodel has to tell the applica- */
- /* tion by returning a value besides zero. */
- case RKMMOD_Up:
- mmd->currval++;
-
- /* Make sure the current value is not greater than value limit. */
- if ((mmd->currval) > mmd->vallimit) mmd->currval = mmd->vallimit;
- NotifyCurrVal(cl, o, msg, mmd);
- retval = (APTR)1L; /* Changing RKMMOD_Up can cause a visual */
- break; /* change to gadgets in the rkmmodel's broadcast */
- /* list. The rkmmodel has to tell the applica- */
- /* tion by returning a value besides zero. */
- case RKMMOD_Down:
- mmd->currval--;
- /* Make sure currval didn't go negative. */
- if ((LONG)(mmd->currval) == -1L)
- mmd->currval = 0L;
- NotifyCurrVal(cl, o, msg, mmd);
- retval = (APTR)1L; /* Changing RKMMOD_Down can cause a visual */
- break; /* change to gadgets in the rkmmodel's broadcast */
- /* list. The rkmmodel has to tell the applica- */
- /* tion by returning a value besides zero. */
- case RKMMOD_Limit:
- mmd->vallimit = ti->ti_Data; /* Set the limit. Note that this does */
- break; /* not do bounds checking on the */
- /* current RKMModData.currval value. */
- }
- }
- }
- break;
- case OM_GET: /* The only attribute that is "gettable" in this */
- mmd = INST_DATA(cl, o); /* class or its superclasses is RKMMOD_CurrVal. */
- if ((((struct opGet *)msg)->opg_AttrID) == RKMMOD_CurrVal)
- {
- *(((struct opGet *)msg)->opg_Storage) = mmd->currval;
- retval = (Object *)TRUE;
- }
- else retval = (APTR)DoSuperMethodA(cl, o, msg);
- break;
- default: /* rkmmodelclass does not recognize the methodID, so let the superclass's */
- /* dispatcher take a look at it. */
- retval = (APTR)DoSuperMethodA(cl, o, msg);
- break;
- }
- return((ULONG)retval);
- }
-
- void NotifyCurrVal(Class *cl, Object *o, struct opUpdate *msg, struct RKMModData *mmd)
- {
- struct TagItem tt[2];
-
- tt[0].ti_Tag = RKMMOD_CurrVal; /* make a tag list. */
- tt[0].ti_Data = mmd->currval;
- tt[1].ti_Tag = TAG_DONE;
- /* If the RKMMOD_CurrVal changes, we want everyone to know about */
- DoSuperMethod(cl, o, /* it. Theoretically, the class is supposed to send itself a */
- OM_NOTIFY, /* OM_NOTIFY message. Because this class lets its superclass */
- tt, /* handle the OM_NOTIFY message, it skips the middleman and */
- msg->opu_GInfo, /* sends the OM_NOTIFY directly to its superclass. */
-
- ((msg->MethodID == OM_UPDATE) ? (msg->opu_Flags) : 0L)); /* If this is an OM_UPDATE */
- /* method, make sure the part the OM_UPDATE message adds to the */
- /* OM_SET message gets added. That lets the dispatcher handle */
- } /* OM_UPDATE and OM_SET in the same case. */
-