7 * (C) Copyright 1998 Manuel Lemos.
8 * (C) Copyright 1996-1997 Ian J. Einman.
9 * (C) Copyright 1993-1996 Jaba Development.
10 * (C) Copyright 1993-1996 Jan van den Baard.
11 * All Rights Reserved.
14 * Revision 42.5 2004/06/16 20:16:48 verhaegs
15 * Use METHODPROTO, METHOD_END and REGFUNCPROTOn where needed.
17 * Revision 42.4 2003/01/18 19:10:00 chodorowski
18 * Instead of using the _AROS or __AROS preprocessor symbols, use __AROS__.
20 * Revision 42.3 2000/08/17 15:09:18 chodorowski
21 * Fixed compiler warnings.
23 * Revision 42.2 2000/05/29 00:40:24 bergers
24 * Update to compile with AROS now. Should also still compile with SASC etc since I only made changes that test the define __AROS__. The compilation is still very noisy but it does the trick for the main directory. Maybe members of the BGUI team should also have a look at the compiler warnings because some could also cause problems on other systems... (Comparison always TRUE due to datatype (or something like that)). And please compile it on an Amiga to see whether it still works... Thanks.
26 * Revision 42.1 2000/05/15 19:27:02 stegerg
27 * another hundreds of REG() macro replacements in func headers/protos.
29 * Revision 42.0 2000/05/09 22:10:06 mlemos
30 * Bumped to revision 42.0 before handing BGUI to AROS team
32 * Revision 41.11 2000/05/09 19:55:01 mlemos
33 * Merged with the branch Manuel_Lemos_fixes.
35 * Revision 41.10.2.7 1999/07/31 01:56:37 mlemos
36 * Added calls to the code that keeps track of the created objects.
38 * Revision 41.10.2.6 1999/07/03 15:17:45 mlemos
39 * Replaced the calls to CallHookPkt to BGUI_CallHookPkt.
41 * Revision 41.10.2.5 1998/11/21 00:27:15 mlemos
42 * Fixed erroneous code in OM_UPDATE.
44 * Revision 41.10.2.4 1998/11/19 01:23:33 mlemos
45 * Fixed the return value type of BASE_ADDMAP value.
47 * Revision 41.10.2.3 1998/09/19 01:54:21 mlemos
48 * Made BASE_ADDHOOK method return TRUE on success rather than the hook linet
51 * Revision 41.10.2.2 1998/03/02 23:49:04 mlemos
52 * Switched vector allocation functions calls to BGUI allocation functions.
54 * Revision 41.10.2.1 1998/03/01 15:39:19 mlemos
55 * Added support to track BaseInfo memory leaks.
57 * Revision 41.10 1998/02/25 21:13:01 mlemos
60 * Revision 1.1 1998/02/25 17:09:41 mlemos
66 #include "include/classdefs.h"
70 #define NOTIFY_METHOD 3
73 typedef struct Notif
{
79 struct TagItem n_Condition
;
84 * Structures to track notification
88 struct TagItem
*m_MapList
;
93 struct TagItem a_Attr
;
108 * Object instance data.
111 struct MinNode rd_Node
; /* Node for adding to objects. */
112 WORD rd_NodeOffset
; /* Offset of node from object. */
113 struct MinList rd_NotifyList
; /* Notification list. */
114 UWORD rd_LoopCount
; /* To prevent infinite notification. */
119 * Create a shiny new object.
121 METHOD(RootClassNew
, struct opSet
*, ops
)
127 * We let the superclass setup an object
130 if (rc
= AsmDoSuperMethodA(cl
, obj
, (Msg
)ops
))
133 * Get the instance data.
135 rd
= INST_DATA(cl
, rc
);
137 rd
->rd_NodeOffset
= (BYTE
*)rc
- (BYTE
*)rd
;
140 * Initialize the notification lists.
142 NewList((struct List
*)&rd
->rd_NotifyList
);
144 TrackNewObject((Object
*)rc
,ops
->ops_AttrList
);
153 * We need to update our targets.
155 METHOD(RootClassNotify
, struct opUpdate
*, opu
)
157 RD
*rd
= INST_DATA(cl
, obj
);
158 NOTIF
*n
= (NOTIF
*)rd
->rd_NotifyList
.mlh_Head
;
159 struct TagItem
*clones
;
168 * Make sure that the ICA_xxx
169 * attributes will function.
171 rc
= AsmDoSuperMethodA(cl
, obj
, (Msg
)opu
);
174 * Broadcast the message to all
175 * targets mapping the attributes
181 target
= n
->n_Object
;
184 * Object counter not 0? Do not update.
191 if (AsmDoMethod(target
, RM_SETLOOP
))
193 * Break the loop...we are done.
199 * Check condition, if we have one.
201 if (n
->n_Flags
& (RAF_FALSE
|RAF_TRUE
))
205 * Conditional tag present in
206 * the notification tags?
208 if (tag
= FindTagItem(n
->n_Condition
.ti_Tag
, opu
->opu_AttrList
))
210 cond
= (n
->n_Condition
.ti_Data
== tag
->ti_Data
);
211 if (n
->n_Flags
& RAF_FALSE
) cond
= !cond
;
217 * Skip interim messages?
219 if (n
->n_Flags
& RAF_NO_INTERIM
)
221 if (opu
->opu_Flags
& OPUF_INTERIM
) type
= 0;
228 * When the object has a maplist
231 if (((MAP
*)n
)->m_MapList
)
234 * Clone the original attribute list.
236 if (clones
= CloneTagItems(opu
->opu_AttrList
))
238 MapTags(clones
, ((MAP
*)n
)->m_MapList
, MAP_KEEP_NOT_FOUND
);
240 AsmDoMethod(target
, OM_UPDATE
, clones
, (n
->n_Flags
& RAF_NO_GINFO
) ? NULL
: opu
->opu_GInfo
, opu
->opu_Flags
);
245 FreeTagItems(clones
);
250 AsmDoMethodA(n
->n_Object
, (Msg
)opu
);
258 DoSetMethod(target
, (n
->n_Flags
& RAF_NO_GINFO
) ? NULL
: opu
->opu_GInfo
,
259 ((ATTR
*)n
)->a_Attr
.ti_Tag
, ((ATTR
*)n
)->a_Attr
.ti_Data
, TAG_DONE
);
263 msg
= ((METHOD
*)n
)->m_Method
;
268 if (!(n
->n_Flags
& RAF_NO_GINFO
))
277 * These methods get the GadgetInfo in the third long-word.
279 msg
[2] = (ULONG
)opu
->opu_GInfo
;
284 * All others in the second long-word.
286 msg
[1] = (ULONG
)opu
->opu_GInfo
;
290 AsmDoMethodA(target
, (Msg
)msg
);
294 if (!BGUI_CallHookPkt(((HOOK
*)n
)->h_Hook
, (void *)obj
, (void *)opu
))
299 if (target
) AsmDoMethod(target
, RM_CLEARLOOP
);
309 STATIC VOID
FreeNotif(NOTIF
*n
)
314 FreeTagItems(((MAP
*)n
)->m_MapList
);
321 * They do not need us anymore.
323 METHOD(RootClassDispose
, Msg
, msg
)
325 RD
*rd
= INST_DATA(cl
, obj
);
329 * Remove all targets and deallocate all resources.
331 while (n
= (NOTIF
*)RemHead((struct List
*)&rd
->rd_NotifyList
))
335 * Remove us from any list we may be in.
337 AsmDoMethod(obj
, RM_REMOVE
);
340 * Let the superclass dispose of us.
343 TrackDisposedObject(obj
);
345 return AsmDoSuperMethodA(cl
, obj
, msg
);
351 * Emulate OM_UPDATE with new methods.
353 METHOD(RootClassUpdateX
, struct opUpdate
*, opu
)
355 ULONG rc
= AsmCoerceMethod(cl
,obj
, RM_SETM
, opu
->opu_AttrList
, (opu
->opu_Flags
& OPUF_INTERIM
) ? RAF_INTERIM
|RAF_UPDATE
: RAF_UPDATE
);
358 && !(opu
->opu_Flags
& OPUF_INTERIM
))
359 AsmDoMethod(obj
, RM_REFRESH
, opu
->opu_GInfo
, rc
);
367 * Emulate OM_SET with new methods.
369 METHOD(RootClassSetX
, struct opSet
*, ops
)
371 ULONG rc
= AsmDoMethod(obj
, RM_SETM
, ops
->ops_AttrList
, 0);
373 if (ops
->ops_GInfo
) AsmDoMethod(obj
, RM_REFRESH
, ops
->ops_GInfo
, rc
);
381 * Emulate OM_GET with new methods.
383 METHOD(RootClassGetX
, struct opGet
*, opg
)
385 return AsmDoMethod(obj
, RM_GET
, &opg
->opg_AttrID
, 0);
391 * Emulate RM_SET for any superclass.
393 METHOD(RootClassSet
, struct rmAttr
*, ra
)
395 struct TagItem tags
[2];
398 tags
[0].ti_Tag
= ra
->ra_Attr
->ti_Tag
;
399 tags
[0].ti_Data
= ra
->ra_Attr
->ti_Data
;
400 tags
[1].ti_Tag
= TAG_DONE
;
402 rc
= AsmDoSuperMethod(cl
, obj
, (ra
->ra_Flags
& RAF_UPDATE
) ? OM_UPDATE
: OM_SET
, tags
, NULL
,
403 (ra
->ra_Flags
& RAF_INTERIM
) ? OPUF_INTERIM
: 0);
405 return (ULONG
)0;//((rc > 0) ? (RAF_UNDERSTOOD|RAF_REDRAW) : 0);
411 * Emulate RM_GET for any superclass.
413 METHOD(RootClassGet
, struct rmAttr
*, ra
)
415 AsmDoSuperMethod(cl
, obj
, OM_GET
, ra
->ra_Attr
->ti_Tag
, ra
->ra_Attr
->ti_Data
);
423 METHOD(RootClassSetM
, struct rmAttr
*, ra1
)
426 struct TagItem
*tstate
= ra1
->ra_Attr
;
429 ra
.MethodID
= RM_SET
;
430 ra
.ra_Flags
= ra1
->ra_Flags
;
432 while (ra
.ra_Attr
= BGUI_NextTagItem(&tstate
))
433 rc
|= AsmDoMethodA(obj
, (Msg
)&ra
);
441 METHOD(RootClassGetM
, struct rmAttr
*, ra1
)
444 struct TagItem
*tstate
= ra1
->ra_Attr
;
447 ra
.MethodID
= RM_GET
;
448 ra
.ra_Flags
= ra1
->ra_Flags
;
450 while (ra
.ra_Attr
= BGUI_NextTagItem(&tstate
))
451 rc
|= AsmDoMethodA(obj
, (Msg
)&ra
);
460 void AddNotify(RD
*rd
, NOTIF
*n
, Msg msg
, int type
)
466 n
->n_Pri
= ((struct rmAddAttr
*)msg
)->raa_Priority
;
467 n
->n_Flags
= ((struct rmAddAttr
*)msg
)->raa_Flags
;
468 n
->n_Condition
= ((struct rmAddAttr
*)msg
)->raa_Condition
;
469 n
->n_Object
= ((struct rmAddAttr
*)msg
)->raa_Object
;
472 * Add the target to the list.
474 Enqueue((struct List
*)&rd
->rd_NotifyList
, (struct Node
*)n
);
479 * Add a map object to the list.
481 METHOD(RootClassAddMap
, struct rmAddMap
*, ram
)
483 RD
*rd
= INST_DATA(cl
, obj
);
487 * Check if the object is valid.
489 if (ram
->ram_Object
&& (ram
->ram_Object
!= obj
))
492 * Allocate and initialize a MAP structure.
494 if (am
= (MAP
*)BGUI_AllocPoolMem(sizeof(MAP
)))
497 * Check if we need to make a map list.
499 if (ram
->ram_MapList
)
504 if (!(am
->m_MapList
= CloneTagItems(ram
->ram_MapList
)))
506 BGUI_FreePoolMem(am
);
514 AddNotify(rd
, (NOTIF
*)am
, (Msg
)ram
, NOTIFY_MAP
);
523 * Add an attribute conditional object to the list.
525 METHOD(RootClassAddAttr
, struct rmAddAttr
*, raa
)
527 RD
*rd
= INST_DATA(cl
, obj
);
531 * Check if the object is valid.
533 if (raa
->raa_Object
&& (raa
->raa_Object
!= obj
))
536 * Allocate and initialize an ATTR structure.
538 if (aa
= (ATTR
*)BGUI_AllocPoolMem(sizeof(ATTR
)))
541 * Copy the attribute.
543 aa
->a_Attr
= raa
->raa_Attr
;
548 AddNotify(rd
, (NOTIF
*)aa
, (Msg
)raa
, NOTIFY_ATTR
);
557 * Add a method object to the list.
559 METHOD(RootClassAddMethod
, struct rmAddMethod
*, ram
)
561 RD
*rd
= INST_DATA(cl
, obj
);
565 * Check if the object is valid.
567 if (ram
->ram_Size
&& ram
->ram_Object
&& (ram
->ram_Object
!= obj
))
570 * Allocate and initialize a METHOD structure.
572 if (am
= (METHOD
*)BGUI_AllocPoolMem(sizeof(METHOD
) + ram
->ram_Size
- sizeof(ULONG
)))
577 CopyMem((void *)&ram
->ram_MethodID
, (void *)am
->m_Method
, ram
->ram_Size
);
582 AddNotify(rd
, (NOTIF
*)am
, (Msg
)ram
, NOTIFY_METHOD
);
591 * Add a hook to the list.
593 METHOD(RootClassAddHook
, struct rmAddHook
*, rah
)
595 RD
*rd
= INST_DATA(cl
, obj
);
599 * Check if the hook is valid.
604 * Allocate and initialize a HOOK structure.
606 if (ah
= (HOOK
*)BGUI_AllocPoolMem(sizeof(HOOK
)))
611 ah
->h_Hook
= rah
->rah_Hook
;
616 AddNotify(rd
, (NOTIF
*)ah
, (Msg
)rah
, NOTIFY_HOOK
);
618 ah
->h_Node
.n_Object
= NULL
;
627 * Remove an object from a list.
629 METHOD(NotifyClassRemove
, struct bmRemove
*, brt
)
631 RD
*rd
= INST_DATA(cl
, obj
);
632 NOTIF
*n
= (NOTIF
*)rd
->rd_NotifyList
.mlh_Head
;
636 #warning A comment within a comment makes gcc puke...
639 switch (brt->MethodID)
642 type = NOTIFY_TARGET;
644 case BASE_REMCONDITIONAL:
645 type = NOTIFY_CONDITIONAL;
648 type = NOTIFY_METHOD;
656 * Find an object in the target list.
660 if ((n
->n_Type
== type
) && ((n
->n_Object
== brt
->bar_Object
) || (!n
->n_Object
)))
663 * Remove it from the list.
665 Remove((struct Node
*)n
);
668 * Deallocate the structure.
685 * Set infinite loop counter.
687 METHOD(RootClassSetLoop
, Msg
, msg
)
689 RD
*rd
= INST_DATA(cl
, obj
);
691 if (rd
->rd_LoopCount
)
702 * Clear infinite loop counter.
704 METHOD(RootClassClearLoop
, Msg
, msg
)
706 RD
*rd
= INST_DATA(cl
, obj
);
717 METHOD(RootClassRemove
, Msg
, msg
)
719 RD
*rd
= INST_DATA(cl
, obj
);
720 struct MinNode
*mln
= &rd
->rd_Node
;
722 if (mln
->mln_Succ
&& mln
->mln_Pred
)
724 Remove((struct Node
*)mln
);
725 mln
->mln_Succ
= mln
->mln_Pred
= NULL
;
734 METHOD(RootClassAddHead
, struct rmAdd
*, ra
)
736 RD
*rd
= INST_DATA(cl
, obj
);
738 AddHead(ra
->ra_List
, (struct Node
*)&rd
->rd_Node
);
746 METHOD(RootClassAddTail
, struct rmAdd
*, ra
)
748 RD
*rd
= INST_DATA(cl
, obj
);
750 AddTail(ra
->ra_List
, (struct Node
*)&rd
->rd_Node
);
758 METHOD(RootClassInsert
, struct rmInsert
*, ri
)
760 RD
*rd
= INST_DATA(cl
, obj
), *rd2
;
764 rd2
= INST_DATA(cl
, ri
->ri_Previous
);
765 Insert(ri
->ri_List
, (struct Node
*)&rd
->rd_Node
, (struct Node
*)&rd2
->rd_Node
);
769 AddHead(ri
->ri_List
, (struct Node
*)&rd
->rd_Node
);
777 METHOD(RootClassPrev
, Msg
, msg
)
779 RD
*rd
= INST_DATA(cl
, obj
);
780 struct MinNode
*mn
= rd
->rd_Node
.mln_Pred
;
782 if (mn
&& mn
->mln_Pred
)
783 return (ULONG
)((UBYTE
*)mn
+ rd
->rd_NodeOffset
);
791 METHOD(RootClassNext
, Msg
, msg
)
793 RD
*rd
= INST_DATA(cl
, obj
);
794 struct MinNode
*mn
= rd
->rd_Node
.mln_Succ
;
796 if (mn
&& mn
->mln_Succ
)
797 return (ULONG
)((UBYTE
*)mn
+ rd
->rd_NodeOffset
);
804 makeproto Object
*ListHeadObject(struct List
*lh
)
806 RD
*rd
= (RD
*)(lh
->lh_Head
);
808 if (rd
->rd_Node
.mln_Succ
) return (Object
*)(((UBYTE
*)rd
) + rd
->rd_NodeOffset
);
811 makeproto Object
*ListTailObject(struct List
*lh
)
813 RD
*rd
= (RD
*)(lh
->lh_TailPred
);
815 if (rd
->rd_Node
.mln_Pred
) return (Object
*)(((UBYTE
*)rd
) + rd
->rd_NodeOffset
);
821 METHOD(BaseClassAddMap
, struct bmAddMap
*, bam
)
823 return((ULONG
)(AsmDoMethod(obj
, RM_ADDMAP
, 0, 0, 0, 0, bam
->bam_Object
, bam
->bam_MapList
)!=NULL
));
829 METHOD(BaseClassAddMethod
, struct bmAddMethod
*, bam
)
831 struct rmAddMethod
*ram
;
833 int size
= bam
->bam_Size
* sizeof(ULONG
);
836 if (ram
= BGUI_AllocPoolMem(sizeof(struct bmAddMethod
) + size
))
838 ram
->MethodID
= RM_ADDMETHOD
;
839 ram
->ram_Object
= bam
->bam_Object
;
840 ram
->ram_Flags
= bam
->bam_Flags
;
841 ram
->ram_Size
= size
;
843 CopyMem((void *)&bam
->bam_MethodID
, (void *)&ram
->ram_MethodID
, size
);
845 nh
= AsmDoMethodA(obj
, (Msg
)ram
);
847 BGUI_FreePoolMem(ram
);
853 /// BASE_ADDCONDITIONAL
855 METHOD(BaseClassAddConditional
, struct bmAddConditional
*, bac
)
859 if (nh
= AsmDoMethod(obj
, RM_ADDATTR
, 0, RAF_FALSE
, bac
->bac_Condition
.ti_Tag
, bac
->bac_Condition
.ti_Data
,
860 bac
->bac_Object
, bac
->bac_FALSE
.ti_Tag
, bac
->bac_FALSE
.ti_Data
))
862 if (AsmDoMethod(obj
, RM_ADDATTR
, 0, RAF_TRUE
, bac
->bac_Condition
.ti_Tag
, bac
->bac_Condition
.ti_Data
,
863 bac
->bac_Object
, bac
->bac_TRUE
.ti_Tag
, bac
->bac_TRUE
.ti_Data
))
866 AsmDoMethod(obj
, RM_REMNOTIFY
, 0, nh
);
874 METHOD(BaseClassAddHook
, struct bmAddHook
*, bah
)
876 return((ULONG
)(AsmDoMethod(obj
, RM_ADDHOOK
, 0, 0, 0, 0, bah
->bah_Hook
)!=NULL
));
883 METHOD(ImageClassDraw
, struct impDraw
*, imp
)
885 int x
= imp
->imp_Offset
.X
;
886 int y
= imp
->imp_Offset
.Y
;
891 if (bi
= AllocBaseInfoDebug(__FILE__
,__LINE__
,BI_RastPort
, imp
->imp_RPort
, BI_DrawInfo
, imp
->imp_DrInfo
, TAG_DONE
))
893 if (bi
= AllocBaseInfo(BI_RastPort
, imp
->imp_RPort
, BI_DrawInfo
, imp
->imp_DrInfo
, TAG_DONE
))
896 if (x
) IMAGE(obj
)->LeftEdge
+= x
;
897 if (y
) IMAGE(obj
)->TopEdge
+= y
;
899 rc
= AsmDoMethod(obj
, BASE_RENDER
, bi
, imp
->imp_State
);
901 if (x
) IMAGE(obj
)->LeftEdge
-= x
;
902 if (y
) IMAGE(obj
)->TopEdge
-= y
;
911 /// Class initialization.
913 * Class function array.
915 STATIC DPFUNC ClassFunc
[] =
917 RM_SET
, (FUNCPTR
)RootClassSet
,
918 RM_GET
, (FUNCPTR
)RootClassGet
,
919 RM_SETM
, (FUNCPTR
)RootClassSetM
,
920 RM_GETM
, (FUNCPTR
)RootClassGetM
,
921 OM_SET
, (FUNCPTR
)RootClassSetX
,
922 OM_GET
, (FUNCPTR
)RootClassGetX
,
923 OM_UPDATE
, (FUNCPTR
)RootClassUpdateX
,
924 OM_NEW
, (FUNCPTR
)RootClassNew
,
925 OM_DISPOSE
, (FUNCPTR
)RootClassDispose
,
926 OM_NOTIFY
, (FUNCPTR
)RootClassNotify
,
927 RM_SETLOOP
, (FUNCPTR
)RootClassSetLoop
,
928 RM_CLEARLOOP
, (FUNCPTR
)RootClassClearLoop
,
930 RM_REMOVE
, (FUNCPTR
)RootClassRemove
,
931 RM_ADDHEAD
, (FUNCPTR
)RootClassAddHead
,
932 RM_ADDTAIL
, (FUNCPTR
)RootClassAddTail
,
933 RM_INSERT
, (FUNCPTR
)RootClassInsert
,
934 RM_NEXT
, (FUNCPTR
)RootClassNext
,
935 RM_PREV
, (FUNCPTR
)RootClassPrev
,
937 RM_ADDMAP
, (FUNCPTR
)RootClassAddMap
,
938 RM_ADDATTR
, (FUNCPTR
)RootClassAddAttr
,
939 RM_ADDMETHOD
, (FUNCPTR
)RootClassAddMethod
,
940 RM_ADDHOOK
, (FUNCPTR
)RootClassAddHook
,
942 BASE_ADDMAP
, (FUNCPTR
)BaseClassAddMap
,
943 BASE_ADDCONDITIONAL
, (FUNCPTR
)BaseClassAddConditional
,
944 BASE_ADDMETHOD
, (FUNCPTR
)BaseClassAddMethod
,
945 BASE_ADDHOOK
, (FUNCPTR
)BaseClassAddHook
,
946 BASE_REMMAP
, (FUNCPTR
)NotifyClassRemove
,
947 BASE_REMCONDITIONAL
, (FUNCPTR
)NotifyClassRemove
,
948 BASE_REMMETHOD
, (FUNCPTR
)NotifyClassRemove
,
949 BASE_REMHOOK
, (FUNCPTR
)NotifyClassRemove
,
951 IM_DRAW
, (FUNCPTR
)ImageClassDraw
,
956 Class
*InitRootSubClass(char *superclass
)
958 return BGUI_MakeClass(CLASS_SuperClassID
, superclass
,
959 CLASS_ObjectSize
, sizeof(RD
),
960 CLASS_DFTable
, ClassFunc
,
965 * Simple class initialization.
967 makeproto Class
*InitRootClass(void)
969 return InitRootSubClass("rootclass");
972 makeproto Class
*InitGadgetClass(void)
974 return InitRootSubClass("gadgetclass");
977 makeproto Class
*InitImageClass(void)
979 return InitRootSubClass("imageclass");