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] = (IPTR
)opu
->opu_GInfo
;
284 * All others in the second long-word.
286 msg
[1] = (IPTR
)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
= (ULONG
)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
= (ULONG
)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
= (ULONG
)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 ((rc
> 0) ? /* (RAF_UNDERSTOOD|RAF_REDRAW) */ 0 : 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
|= (ULONG
)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
|= (ULONG
)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
)
632 RD
*rd
= INST_DATA(cl
, obj
);
633 NOTIF
*n
= (NOTIF
*)rd
->rd_NotifyList
.mlh_Head
;
636 switch (brt
->MethodID
)
639 type
= NOTIFY_TARGET
;
641 case BASE_REMCONDITIONAL
:
642 type
= NOTIFY_CONDITIONAL
;
645 type
= NOTIFY_METHOD
;
653 * Find an object in the target list.
657 if ((n
->n_Type
== type
) && ((n
->n_Object
== brt
->bar_Object
) || (!n
->n_Object
)))
660 * Remove it from the list.
662 Remove((struct Node
*)n
);
665 * Deallocate the structure.
681 * Set infinite loop counter.
683 METHOD(RootClassSetLoop
, Msg
, msg
)
685 RD
*rd
= INST_DATA(cl
, obj
);
687 if (rd
->rd_LoopCount
)
698 * Clear infinite loop counter.
700 METHOD(RootClassClearLoop
, Msg
, msg
)
702 RD
*rd
= INST_DATA(cl
, obj
);
713 METHOD(RootClassRemove
, Msg
, msg
)
715 RD
*rd
= INST_DATA(cl
, obj
);
716 struct MinNode
*mln
= &rd
->rd_Node
;
718 if (mln
->mln_Succ
&& mln
->mln_Pred
)
720 Remove((struct Node
*)mln
);
721 mln
->mln_Succ
= mln
->mln_Pred
= NULL
;
730 METHOD(RootClassAddHead
, struct rmAdd
*, ra
)
732 RD
*rd
= INST_DATA(cl
, obj
);
734 AddHead(ra
->ra_List
, (struct Node
*)&rd
->rd_Node
);
742 METHOD(RootClassAddTail
, struct rmAdd
*, ra
)
744 RD
*rd
= INST_DATA(cl
, obj
);
746 AddTail(ra
->ra_List
, (struct Node
*)&rd
->rd_Node
);
754 METHOD(RootClassInsert
, struct rmInsert
*, ri
)
756 RD
*rd
= INST_DATA(cl
, obj
), *rd2
;
760 rd2
= INST_DATA(cl
, ri
->ri_Previous
);
761 Insert(ri
->ri_List
, (struct Node
*)&rd
->rd_Node
, (struct Node
*)&rd2
->rd_Node
);
765 AddHead(ri
->ri_List
, (struct Node
*)&rd
->rd_Node
);
773 METHOD(RootClassPrev
, Msg
, msg
)
775 RD
*rd
= INST_DATA(cl
, obj
);
776 struct MinNode
*mn
= rd
->rd_Node
.mln_Pred
;
778 if (mn
&& mn
->mln_Pred
)
779 return (IPTR
)((UBYTE
*)mn
+ rd
->rd_NodeOffset
);
787 METHOD(RootClassNext
, Msg
, msg
)
789 RD
*rd
= INST_DATA(cl
, obj
);
790 struct MinNode
*mn
= rd
->rd_Node
.mln_Succ
;
792 if (mn
&& mn
->mln_Succ
)
793 return (IPTR
)((UBYTE
*)mn
+ rd
->rd_NodeOffset
);
800 makeproto Object
*ListHeadObject(struct List
*lh
)
802 RD
*rd
= (RD
*)(lh
->lh_Head
);
804 if (rd
->rd_Node
.mln_Succ
) return (Object
*)(((UBYTE
*)rd
) + rd
->rd_NodeOffset
);
807 makeproto Object
*ListTailObject(struct List
*lh
)
809 RD
*rd
= (RD
*)(lh
->lh_TailPred
);
811 if (rd
->rd_Node
.mln_Pred
) return (Object
*)(((UBYTE
*)rd
) + rd
->rd_NodeOffset
);
817 METHOD(BaseClassAddMap
, struct bmAddMap
*, bam
)
819 return (IPTR
)(AsmDoMethod(obj
, RM_ADDMAP
, 0, 0, 0, 0, bam
->bam_Object
, bam
->bam_MapList
)!=0);
825 METHOD(BaseClassAddMethod
, struct bmAddMethod
*, bam
)
827 struct rmAddMethod
*ram
;
829 int size
= bam
->bam_Size
* sizeof(ULONG
);
832 if ((ram
= BGUI_AllocPoolMem(sizeof(struct bmAddMethod
) + size
)))
834 ram
->MethodID
= RM_ADDMETHOD
;
835 ram
->ram_Object
= bam
->bam_Object
;
836 ram
->ram_Flags
= bam
->bam_Flags
;
837 ram
->ram_Size
= size
;
839 CopyMem((void *)&bam
->bam_MethodID
, (void *)&ram
->ram_MethodID
, size
);
841 nh
= AsmDoMethodA(obj
, (Msg
)ram
);
843 BGUI_FreePoolMem(ram
);
849 /// BASE_ADDCONDITIONAL
851 METHOD(BaseClassAddConditional
, struct bmAddConditional
*, bac
)
855 if ((nh
= AsmDoMethod(obj
, RM_ADDATTR
, 0, RAF_FALSE
, bac
->bac_Condition
.ti_Tag
, bac
->bac_Condition
.ti_Data
,
856 bac
->bac_Object
, bac
->bac_FALSE
.ti_Tag
, bac
->bac_FALSE
.ti_Data
)))
858 if (AsmDoMethod(obj
, RM_ADDATTR
, 0, RAF_TRUE
, bac
->bac_Condition
.ti_Tag
, bac
->bac_Condition
.ti_Data
,
859 bac
->bac_Object
, bac
->bac_TRUE
.ti_Tag
, bac
->bac_TRUE
.ti_Data
))
862 AsmDoMethod(obj
, RM_REMNOTIFY
, 0, nh
);
870 METHOD(BaseClassAddHook
, struct bmAddHook
*, bah
)
872 return (IPTR
)(AsmDoMethod(obj
, RM_ADDHOOK
, 0, 0, 0, 0, bah
->bah_Hook
)!=0);
879 METHOD(ImageClassDraw
, struct impDraw
*, imp
)
881 int x
= imp
->imp_Offset
.X
;
882 int y
= imp
->imp_Offset
.Y
;
887 if ((bi
= AllocBaseInfoDebug(__FILE__
,__LINE__
,BI_RastPort
, imp
->imp_RPort
, BI_DrawInfo
, imp
->imp_DrInfo
, TAG_DONE
)))
889 if ((bi
= AllocBaseInfo(BI_RastPort
, imp
->imp_RPort
, BI_DrawInfo
, imp
->imp_DrInfo
, TAG_DONE
)))
892 if (x
) IMAGE(obj
)->LeftEdge
+= x
;
893 if (y
) IMAGE(obj
)->TopEdge
+= y
;
895 rc
= AsmDoMethod(obj
, BASE_RENDER
, bi
, imp
->imp_State
);
897 if (x
) IMAGE(obj
)->LeftEdge
-= x
;
898 if (y
) IMAGE(obj
)->TopEdge
-= y
;
907 /// Class initialization.
909 * Class function array.
911 STATIC DPFUNC ClassFunc
[] =
913 { RM_SET
, RootClassSet
},
914 { RM_GET
, RootClassGet
},
915 { RM_SETM
, RootClassSetM
},
916 { RM_GETM
, RootClassGetM
},
917 { OM_SET
, RootClassSetX
},
918 { OM_GET
, RootClassGetX
},
919 { OM_UPDATE
, RootClassUpdateX
},
920 { OM_NEW
, RootClassNew
},
921 { OM_DISPOSE
, RootClassDispose
},
922 { OM_NOTIFY
, RootClassNotify
},
923 { RM_SETLOOP
, RootClassSetLoop
},
924 { RM_CLEARLOOP
, RootClassClearLoop
},
926 { RM_REMOVE
, RootClassRemove
},
927 { RM_ADDHEAD
, RootClassAddHead
},
928 { RM_ADDTAIL
, RootClassAddTail
},
929 { RM_INSERT
, RootClassInsert
},
930 { RM_NEXT
, RootClassNext
},
931 { RM_PREV
, RootClassPrev
},
933 { RM_ADDMAP
, RootClassAddMap
},
934 { RM_ADDATTR
, RootClassAddAttr
},
935 { RM_ADDMETHOD
, RootClassAddMethod
},
936 { RM_ADDHOOK
, RootClassAddHook
},
938 { BASE_ADDMAP
, BaseClassAddMap
},
939 { BASE_ADDCONDITIONAL
, BaseClassAddConditional
},
940 { BASE_ADDMETHOD
, BaseClassAddMethod
},
941 { BASE_ADDHOOK
, BaseClassAddHook
},
942 { BASE_REMMAP
, NotifyClassRemove
},
943 { BASE_REMCONDITIONAL
, NotifyClassRemove
},
944 { BASE_REMMETHOD
, NotifyClassRemove
},
945 { BASE_REMHOOK
, NotifyClassRemove
},
947 { IM_DRAW
, ImageClassDraw
},
952 Class
*InitRootSubClass(char *superclass
)
954 return BGUI_MakeClass(CLASS_SuperClassID
, superclass
,
955 CLASS_ObjectSize
, sizeof(RD
),
956 CLASS_DFTable
, ClassFunc
,
961 * Simple class initialization.
963 makeproto Class
*InitRootClass(void)
965 return InitRootSubClass("rootclass");
968 makeproto Class
*InitGadgetClass(void)
970 return InitRootSubClass("gadgetclass");
973 makeproto Class
*InitImageClass(void)
975 return InitRootSubClass("imageclass");