Replaced System by SYS because on "native" the volume name of the system partition...
[AROS-Contrib.git] / bgui / classes.c
blob95992f83ef150fc7d46b740bc040de35b42e5ec9
1 /*
2 * @(#) $Header$
4 * BGUI library
5 * classes.c
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.
13 * $Log$
14 * Revision 42.9 2004/06/16 20:16:48 verhaegs
15 * Use METHODPROTO, METHOD_END and REGFUNCPROTOn where needed.
17 * Revision 42.8 2003/01/18 19:09:55 chodorowski
18 * Instead of using the _AROS or __AROS preprocessor symbols, use __AROS__.
20 * Revision 42.7 2000/08/09 11:45:57 chodorowski
21 * Removed a lot of #ifdefs that disabled the AROS_LIB* macros when not building on AROS. This is now handled in contrib/bgui/include/bgui_compilerspecific.h.
23 * Revision 42.6 2000/07/06 16:42:03 stegerg
24 * the function ForwardMsg relied on gpInput->gpht_Mouse.X/Y and
25 * gpHitTest.gpht_Mouse.X/Y being of type WORD. For example
26 * it used LONG reads to backup this values and a WORD * pointer
27 * to change them. Does not work with AROS where these are of
28 * type STACKWORD and not WORD.
30 * This caused the problems with the gadgets which could not be
31 * activated, or only activated by clicking somewhere outside.
33 * Revision 42.5 2000/06/01 01:41:37 bergers
34 * Only 2 linker problems left: stch_l & stcu_d. Somebody might want to replace them (embraced by #ifdef __AROS__), please.
36 * Revision 42.4 2000/05/31 01:23:10 bergers
37 * Changes to make BGUI compilable and linkable.
39 * Revision 42.3 2000/05/29 00:40:23 bergers
40 * 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.
42 * Revision 42.2 2000/05/15 19:27:00 stegerg
43 * another hundreds of REG() macro replacements in func headers/protos.
45 * Revision 42.1 2000/05/14 23:32:46 stegerg
46 * changed over 200 function headers which all use register
47 * parameters (oh boy ...), because the simple REG() macro
48 * doesn't work with AROS. And there are still hundreds
49 * of headers left to be fixed :(
51 * Many of these functions would also work with stack
52 * params, but since i have fixed every single one
53 * I encountered up to now, I guess will have to do
54 * the same for the rest.
56 * Revision 42.0 2000/05/09 22:08:37 mlemos
57 * Bumped to revision 42.0 before handing BGUI to AROS team
59 * Revision 41.11 2000/05/09 19:54:03 mlemos
60 * Merged with the branch Manuel_Lemos_fixes.
62 * Revision 41.10.2.12 1999/08/09 23:01:25 mlemos
63 * Optimized method lookup by using a 256 positions hash table and a simple
64 * UBYTE conversion as hash function.
66 * Revision 41.10.2.11 1999/07/29 00:42:12 mlemos
67 * Added a call MarkFreedClass at the end of a successful call to
68 * BGUI_FreeClass.
70 * Revision 41.10.2.10 1999/01/06 19:18:18 mlemos
71 * Prevented division by 0 in the class statistics when no methods were
72 * called.
74 * Revision 41.10.2.9 1998/12/14 19:56:13 mlemos
75 * Replaced the binary search method lookup by hash table method lookup.
76 * Added debug code to produce statistics about method lookup on dispatching.
78 * Revision 41.10.2.8 1998/12/14 18:36:25 mlemos
79 * Added support for method inheritance to speed up method dispatching.
81 * Revision 41.10.2.7 1998/12/14 04:59:47 mlemos
82 * Replaced the assembly method dispatcher by a C dispatcher that uses binary
83 * search as method lookup.
85 * Revision 41.10.2.6 1998/11/13 18:08:10 mlemos
86 * Fixed mistaken default value for BaseInfo screen pointer in AllocBaseInfo.
88 * Revision 41.10.2.5 1998/10/18 18:22:59 mlemos
89 * Ensured that the allocated Baseinfo structure is cleared when it is not
90 * being copied from another BaseInfo structure.
92 * Revision 41.10.2.4 1998/10/12 01:21:54 mlemos
93 * Added the support for class constructor and destructor methods.
95 * Revision 41.10.2.3 1998/10/01 04:24:40 mlemos
96 * Made the class data store also BGUI global data pointer.
98 * Revision 41.10.2.2 1998/03/02 23:48:09 mlemos
99 * Switched vector allocation functions calls to BGUI allocation functions.
101 * Revision 41.10.2.1 1998/03/01 15:32:02 mlemos
102 * Added support to track BaseInfo memory leaks.
104 * Revision 41.10 1998/02/25 21:11:47 mlemos
105 * Bumping to 41.10
107 * Revision 1.1 1998/02/25 17:07:51 mlemos
108 * Ian sources
113 #include "include/classdefs.h"
115 #ifdef __AROS__
116 #else
117 #include <dos.h>
118 #endif
120 #ifdef __AROS__
121 #warning If something is wrong with the dispatcherfunction then look here!
122 //#if 0
123 typedef AROS_UFP4(ULONG,* ClassMethodDispatcher,
124 AROS_UFPA(Class *, cl, A0),
125 AROS_UFPA(Object *, obj, A2),
126 AROS_UFPA(Msg, msg, A1),
127 AROS_UFPA(APTR, global_data, A4));
128 //#endif
130 //typedef ClassMethodDispatcher (void *);
132 #else
133 typedef ASM ULONG (*ClassMethodDispatcher)(REG(a0) Class *cl, REG(a2) Object *obj, REG(a1) Msg msg, REG(a4) APTR global_data);
134 #endif
136 typedef struct SortedMethod
138 ULONG MethodID;
139 #ifdef __AROS__
140 ULONG (*DispatcherFunction)(Class *, Object *, Msg, APTR);
141 #else
142 ClassMethodDispatcher DispatcherFunction;
143 #endif
144 Class *Class;
145 APTR GlobalData;
146 struct SortedMethod *NextHashedMethod;
147 APTR Padding[3];
149 SortedMethod;
151 typedef struct
153 DPFUNC *ClassMethodFunctions;
154 #ifdef __AROS__
155 ULONG (*ClassDispatcher)(Class *, Object *, Msg, APTR);
156 #else
157 ClassMethodDispatcher ClassDispatcher;
158 #endif
159 APTR BGUIGlobalData;
160 APTR ClassGlobalData;
161 SortedMethod *MethodFunctions;
162 ULONG MethodCount;
163 SortedMethod **MethodHashTable;
164 #ifdef DEBUG_BGUI
165 ULONG MethodLookups;
166 ULONG MethodComparisions;
167 ULONG MethodColisions;
168 APTR Padding[6];
169 #else
170 APTR Padding;
171 #endif
173 BGUIClassData;
175 #define METHOD_HASH_TABLE_SIZE 256
176 #define MethodHashValue(method) ((UBYTE)(method))
178 makeproto UBYTE *RootClass = "rootclass";
179 makeproto UBYTE *ImageClass = "imageclass";
180 makeproto UBYTE *GadgetClass = "gadgetclass";
181 makeproto UBYTE *PropGClass = "propgclass";
182 makeproto UBYTE *StrGClass = "strgclass";
184 makeproto Class *BGUI_MakeClass(ULONG tag, ...)
186 return BGUI_MakeClassA((struct TagItem *)&tag);
189 //static ASM ULONG ClassCallDispatcher(REG(a0) Class *cl, REG(a2) Object *obj, REG(a1) Msg msg, REG(a4) APTR global_data)
190 static ASM REGFUNC4(ULONG, ClassCallDispatcher,
191 REGPARAM(A0, Class *, cl),
192 REGPARAM(A2, Object *, obj),
193 REGPARAM(A1, Msg, msg),
194 REGPARAM(A4, APTR, global_data))
196 BGUIClassData *class_data;
197 DPFUNC *class_methods;
199 if(cl
200 && (class_data=(BGUIClassData *)cl->cl_UserData)
201 && (class_methods=class_data[-1].ClassMethodFunctions))
203 for(;class_methods->df_MethodID!=DF_END;class_methods++)
204 if(class_methods->df_MethodID==msg->MethodID)
205 #ifdef __AROS__
206 return AROS_UFC4(ULONG, class_methods->df_Func,
207 AROS_UFCA(Class *, cl, A0),
208 AROS_UFCA(Object *, obj, A1),
209 AROS_UFCA(Msg, msg, A2),
210 AROS_UFCA(APTR, global_data, A4));
211 #else
212 return(((ClassMethodDispatcher)class_methods->df_Func)(cl,obj,msg,global_data));
213 #endif
215 switch(msg->MethodID)
217 case OM_NEW:
218 case OM_DISPOSE:
219 return(1);
221 return(0);
223 REGFUNC_END
225 struct CallData
227 #ifdef __AROS__
228 ULONG (*dispatcher)(Class *, Object *, Msg, APTR);
229 #else
230 ClassMethodDispatcher dispatcher;
231 #endif
232 Class *cl;
233 Object *obj;
234 Msg msg;
235 APTR global_data;
238 //static ULONG ASM CallMethod(REG(a3) struct CallData *call_data)
239 static ASM REGFUNC1(ULONG, CallMethod,
240 REGPARAM(A3, struct CallData *, call_data))
242 register APTR stack;
243 register ULONG result;
245 #ifdef __AROS__
246 #warning Commented EnsureStack
247 #else
248 stack=EnsureStack();
249 #endif
250 result=(*call_data->dispatcher)(call_data->cl,call_data->obj,call_data->msg,call_data->global_data);
251 #ifdef __AROS__
252 #else
253 RevertStack(stack);
254 #endif
255 return(result);
257 REGFUNC_END
259 static int CompareMethods(const void *method_1, const void *method_2)
261 return(((SortedMethod *)method_1)->MethodID==((SortedMethod *)method_2)->MethodID ? 0 : (((SortedMethod *)method_1)->MethodID>((SortedMethod *)method_2)->MethodID ? 1 : -1));
264 static SortedMethod *LookupMethod(BGUIClassData *class_data,ULONG method)
266 SortedMethod *method_found;
267 size_t lower,upper,index;
269 #ifdef DEBUG_BGUI
270 class_data->MethodLookups++;
271 #endif
272 for(lower=0,upper=class_data->MethodCount;lower<upper;)
274 #ifdef DEBUG_BGUI
275 class_data->MethodComparisions++;
276 #endif
277 index=(lower+upper)/2;
278 method_found=class_data->MethodFunctions+index;
279 if(method==method_found->MethodID)
280 return(method_found);
281 if(method>method_found->MethodID)
282 lower=index+1;
283 else
284 upper=index;
286 #ifdef DEBUG_BGUI
287 class_data->MethodComparisions++;
288 #endif
289 return(NULL);
292 //makeproto SAVEDS ASM ULONG __GCD( REG(a0) Class *cl, REG(a2) Object *obj, REG(a1) Msg msg)
293 makeproto SAVEDS ASM REGFUNC3(ULONG, __GCD,
294 REGPARAM(A0, Class *, cl),
295 REGPARAM(A2, Object *, obj),
296 REGPARAM(A1, Msg, msg))
298 struct CallData call_data;
299 BGUIClassData *class_data;
300 SortedMethod *method_found;
302 if(cl==NULL
303 || (class_data=((BGUIClassData *)cl->cl_UserData))==NULL
304 || ((--class_data)->MethodFunctions)==NULL)
306 D(bug("BGUI method dispatcher was called to handle an invalid class!!\n"));
307 return(0);
309 #ifdef DEBUG_BGUI
310 class_data->MethodLookups++;
311 #endif
312 for(method_found=class_data->MethodHashTable[MethodHashValue(msg->MethodID)];method_found && method_found->MethodID!=msg->MethodID;method_found=method_found->NextHashedMethod)
314 #ifdef DEBUG_BGUI
315 class_data->MethodComparisions++;
316 #endif
318 #ifdef DEBUG_BGUI
319 class_data->MethodComparisions++;
320 #endif
321 if(method_found)
323 call_data.cl=method_found->Class;
324 #ifdef __AROS__
325 call_data.dispatcher=method_found->DispatcherFunction;
326 #else
327 call_data.dispatcher=(ClassMethodDispatcher)method_found->DispatcherFunction;
328 #endif
329 call_data.global_data=method_found->GlobalData;
331 else
333 #ifdef __AROS__
334 call_data.dispatcher=(call_data.cl=cl->cl_Super)->cl_Dispatcher.h_Entry;
335 #else
336 call_data.dispatcher=(ClassMethodDispatcher)(call_data.cl=cl->cl_Super)->cl_Dispatcher.h_Entry;
337 #endif
338 call_data.global_data=class_data->BGUIGlobalData;
340 call_data.obj=obj;
341 call_data.msg=msg;
342 return(CallMethod(&call_data));
344 REGFUNC_END
347 * Setup a class.
349 #ifdef __AROS__
350 makearosproto
351 AROS_LH1(Class *, BGUI_MakeClassA,
352 AROS_LHA(struct TagItem *, tags, A0),
353 struct Library *, BGUIBase, 24, BGUI)
354 #else
355 makeproto ASM Class *BGUI_MakeClassA(REG(a0) struct TagItem *tags)
356 #endif
358 AROS_LIBFUNC_INIT
360 #ifdef __AROS__
361 #else
362 ULONG old_a4 = (ULONG)getreg(REG_A4);
363 #endif
364 ULONG SuperClass, SuperClass_ID, Class_ID, Flags, ClassSize, ObjectSize;
365 BGUIClassData *ClassData;
366 Class *cl=NULL;
368 #ifdef __AROS__
369 #else
370 geta4();
371 #endif
373 if ((SuperClass = GetTagData(CLASS_SuperClassBGUI, (ULONG)~0, tags)) == (ULONG)~0)
374 SuperClass = GetTagData(CLASS_SuperClass, NULL, tags);
375 else
376 SuperClass = (ULONG)BGUI_GetClassPtr(SuperClass);
378 if (SuperClass)
379 SuperClass_ID = NULL;
380 else
381 SuperClass_ID = GetTagData(CLASS_SuperClassID, (ULONG)"rootclass", tags);
383 Class_ID = GetTagData(CLASS_ClassID, NULL, tags);
384 Flags = GetTagData(CLASS_Flags, 0, tags);
385 ClassSize = GetTagData(CLASS_ClassSize, 0, tags);
386 ObjectSize = GetTagData(CLASS_ObjectSize, 0, tags);
388 if (ClassData = BGUI_AllocPoolMem(ClassSize + sizeof(BGUIClassData)))
390 if (cl = MakeClass((UBYTE *)Class_ID, (UBYTE *)SuperClass_ID, (Class *)SuperClass, ObjectSize, Flags))
392 DPFUNC *method_functions;
394 cl->cl_UserData = (LONG)(ClassData+1);
395 cl->cl_Dispatcher.h_Entry = (HOOKFUNC)GetTagData(CLASS_Dispatcher, (ULONG)__GCD, tags);
396 ClassData->ClassMethodFunctions = (DPFUNC *)GetTagData(CLASS_ClassDFTable, NULL, tags);
397 #ifdef __AROS__
398 ClassData->ClassDispatcher = GetTagData(CLASS_ClassDispatcher, (ULONG)ClassCallDispatcher, tags);
399 #else
400 ClassData->ClassDispatcher = (ClassMethodDispatcher)GetTagData(CLASS_ClassDispatcher, (ULONG)ClassCallDispatcher, tags);
401 #endif
403 #ifdef __AROS__
404 #warning Missing code here!
405 #else
406 ClassData->BGUIGlobalData = (APTR)getreg(REG_A4);
407 ClassData->ClassGlobalData = (APTR)old_a4;
408 #endif
410 if((method_functions=(DPFUNC *)GetTagData(CLASS_DFTable, NULL, tags)))
413 DPFUNC *methods;
415 for(ClassData->MethodCount=0,methods=method_functions;methods->df_MethodID!=DF_END;ClassData->MethodCount++,methods++);
417 if((ClassData->MethodFunctions=BGUI_AllocPoolMem(sizeof(*ClassData->MethodFunctions)*ClassData->MethodCount)))
419 ULONG method;
421 for(method=0;method<ClassData->MethodCount;method++)
423 ClassData->MethodFunctions[method].MethodID=method_functions[method].df_MethodID;
424 #ifdef __AROS__
425 ClassData->MethodFunctions[method].DispatcherFunction=method_functions[method].df_Func;
426 #else
427 ClassData->MethodFunctions[method].DispatcherFunction=(ClassMethodDispatcher)method_functions[method].df_Func;
428 #endif
429 ClassData->MethodFunctions[method].Class=cl;
430 ClassData->MethodFunctions[method].GlobalData=ClassData->ClassGlobalData;
432 qsort(ClassData->MethodFunctions,ClassData->MethodCount,sizeof(*ClassData->MethodFunctions),CompareMethods);
433 if(cl->cl_Super->cl_Dispatcher.h_Entry==__GCD)
435 BGUIClassData *super_class_data;
436 ULONG new_methods;
438 super_class_data=(((BGUIClassData *)cl->cl_Super->cl_UserData)-1);
439 for(new_methods=ClassData->MethodCount,method=0;method<super_class_data->MethodCount;method++)
441 if(LookupMethod(ClassData,super_class_data->MethodFunctions[method].MethodID)==NULL)
443 SortedMethod *new_sorted_methods;
445 if((new_sorted_methods=BGUI_AllocPoolMem(sizeof(*new_sorted_methods)*(new_methods+1)))==NULL)
447 cl->cl_UserData=NULL;
448 FreeClass(cl);
449 cl=NULL;
450 break;
452 memcpy(new_sorted_methods,ClassData->MethodFunctions,sizeof(*new_sorted_methods)*new_methods);
453 BGUI_FreePoolMem(ClassData->MethodFunctions);
454 ClassData->MethodFunctions=new_sorted_methods;
455 ClassData->MethodFunctions[new_methods]=super_class_data->MethodFunctions[method];
456 new_methods++;
459 ClassData->MethodCount=new_methods;
460 qsort(ClassData->MethodFunctions,ClassData->MethodCount,sizeof(*ClassData->MethodFunctions),CompareMethods);
462 if(cl)
464 if((ClassData->MethodHashTable=BGUI_AllocPoolMem(sizeof(*ClassData->MethodHashTable)*METHOD_HASH_TABLE_SIZE)))
466 ULONG method;
468 memset(ClassData->MethodHashTable,'\0',sizeof(*ClassData->MethodHashTable)*METHOD_HASH_TABLE_SIZE);
469 #ifdef DEBUG_BGUI
470 ClassData->MethodColisions=0;
471 #endif
472 for(method=0;method<ClassData->MethodCount;method++)
474 SortedMethod **method_hash;
476 method_hash= ClassData->MethodHashTable+MethodHashValue(ClassData->MethodFunctions[method].MethodID);
477 #ifdef DEBUG_BGUI
478 if(*method_hash)
479 ClassData->MethodColisions++;
480 #endif
481 ClassData->MethodFunctions[method].NextHashedMethod= *method_hash;
482 *method_hash= &ClassData->MethodFunctions[method];
484 #ifdef DEBUG_BGUI
485 ClassData->MethodLookups=ClassData->MethodComparisions=0;
486 #endif
488 else
490 cl->cl_UserData=NULL;
491 FreeClass(cl);
492 cl=NULL;
496 else
498 cl->cl_UserData=NULL;
499 FreeClass(cl);
500 cl=NULL;
503 else
505 ClassData->MethodFunctions=NULL;
506 ClassData->MethodHashTable=NULL;
508 if(cl
509 && ClassData->ClassDispatcher)
511 struct opSet msg;
513 msg.MethodID=OM_NEW;
514 msg.ops_AttrList=NULL;
515 msg.ops_GInfo=NULL;
516 if(!ClassData->ClassDispatcher(cl,NULL,(Msg)&msg,ClassData->ClassGlobalData))
518 cl->cl_UserData=NULL;
519 FreeClass(cl);
520 cl=NULL;
524 if(cl==NULL)
526 if(ClassData->MethodFunctions)
527 BGUI_FreePoolMem(ClassData->MethodFunctions);
528 BGUI_FreePoolMem(ClassData);
531 #ifdef __AROS__
532 #else
533 putreg(REG_A4, (LONG)old_a4);
534 #endif
535 return cl;
537 AROS_LIBFUNC_EXIT
540 #ifdef __AROS__
541 makearosproto
542 AROS_LH1(BOOL, BGUI_FreeClass,
543 AROS_LHA(Class *, cl, A0),
544 struct Library *, BGUIBase, 25, BGUI)
545 #else
546 makeproto SAVEDS ASM BOOL BGUI_FreeClass(REG(a0) Class *cl)
547 #endif
549 AROS_LIBFUNC_INIT
551 if (cl)
553 if(cl->cl_UserData)
555 BGUIClassData *ClassData;
557 ClassData=((BGUIClassData *)cl->cl_UserData) - 1;
558 if(ClassData->ClassDispatcher)
560 ULONG msg=OM_DISPOSE;
562 if(!ClassData->ClassDispatcher(cl,NULL,(Msg)&msg,ClassData->ClassGlobalData))
563 return FALSE;
565 if(ClassData->MethodFunctions)
567 D(bug("Methods %lu, Lookups %lu, Comparisions %lu, Misses %lu (%lu%%), Colisions %lu (%lu%%)\n",ClassData->MethodCount,ClassData->MethodLookups,ClassData->MethodComparisions,ClassData->MethodComparisions-ClassData->MethodLookups,ClassData->MethodComparisions ? (ClassData->MethodComparisions-ClassData->MethodLookups)*100/ClassData->MethodComparisions : 0,ClassData->MethodColisions,ClassData->MethodCount ? ClassData->MethodColisions*100/ClassData->MethodCount : 0));
568 BGUI_FreePoolMem(ClassData->MethodFunctions);
569 BGUI_FreePoolMem(ClassData->MethodHashTable);
571 BGUI_FreePoolMem(ClassData);
572 cl->cl_UserData=NULL;
574 if(FreeClass(cl))
576 MarkFreedClass(cl);
577 return(TRUE);
580 return FALSE;
582 AROS_LIBFUNC_EXIT
585 //makeproto ULONG ASM BGUI_GetAttrChart(REG(a0) Class *cl, REG(a2) Object *obj, REG(a1) struct rmAttr *ra)
586 makeproto ASM REGFUNC3(ULONG, BGUI_GetAttrChart,
587 REGPARAM(A0, Class *, cl),
588 REGPARAM(A2, Object *, obj),
589 REGPARAM(A1, struct rmAttr *, ra))
591 ULONG flags = ra->ra_Flags;
592 struct TagItem *attr = ra->ra_Attr;
593 ULONG data;
594 UBYTE *dataspace;
595 ULONG rc;
597 if (rc = AsmCoerceMethod(cl, obj, RM_GETATTRFLAGS, attr, flags))
599 if (!(rc & RAF_NOGET))
601 dataspace = (UBYTE *)INST_DATA(cl, obj) + ((rc >> 16) & 0x07FF);
603 if (rc & RAF_BOOL)
605 data = (*dataspace >> ((rc >> 27) & 0x07)) & 1;
606 if (rc & RAF_SIGNED) data = !data;
608 else
610 switch (rc & (RAF_SIGNED|RAF_BYTE|RAF_WORD|RAF_LONG|RAF_ADDR))
612 case RAF_BYTE:
613 data = (ULONG)(*(UBYTE *)dataspace);
614 break;
615 case RAF_BYTE|RAF_SIGNED:
616 data = (LONG)(*(BYTE *)dataspace);
617 break;
618 case RAF_WORD:
619 data = (ULONG)(*(UWORD *)dataspace);
620 break;
621 case RAF_WORD|RAF_SIGNED:
622 data = (LONG)(*(WORD *)dataspace);
623 break;
624 case RAF_LONG:
625 data = (ULONG)(*(ULONG *)dataspace);
626 break;
627 case RAF_LONG|RAF_SIGNED:
628 data = (LONG)(*(LONG *)dataspace);
629 break;
630 case RAF_ADDR:
631 data = (ULONG)dataspace;
632 break;
633 case RAF_NOP:
634 goto no_get;
637 *((ULONG *)(attr->ti_Data)) = data;
639 no_get:
640 if (rc & RAF_CUSTOM)
642 AsmCoerceMethod(cl, obj, RM_GETCUSTOM, attr, flags);
644 if (rc & RAF_SUPER)
646 rc |= AsmDoSuperMethod(cl, obj, RM_GET, attr, flags);
648 rc = (rc & 0xFFFF) | RAF_UNDERSTOOD;
650 else
653 * Let the superclass have a go at it.
655 rc = AsmDoSuperMethodA(cl, obj, (Msg)ra);
657 return rc;
659 REGFUNC_END
661 //makeproto ULONG ASM BGUI_SetAttrChart(REG(a0) Class *cl, REG(a2) Object *obj, REG(a1) struct rmAttr *ra)
662 makeproto ASM REGFUNC3(ULONG, BGUI_SetAttrChart,
663 REGPARAM(A0, Class *, cl),
664 REGPARAM(A2, Object *, obj),
665 REGPARAM(A1, struct rmAttr *, ra))
667 ULONG flags = ra->ra_Flags;
668 struct TagItem *attr = ra->ra_Attr;
669 ULONG data;
670 UBYTE *dataspace, flag;
671 ULONG rc;
673 if (rc = AsmCoerceMethod(cl, obj, RM_GETATTRFLAGS, attr, flags))
675 if ((rc & RAF_NOSET) || ((rc & RAF_NOUPDATE) && (flags & RAF_UPDATE))
676 || ((rc & RAF_NOINTERIM) && (flags & RAF_INTERIM))
677 || ((rc & RAF_INITIAL) && !(flags & RAF_INITIAL)))
679 rc &= ~RAF_SUPER;
681 else
683 if (flags & RAF_INITIAL) rc &= ~RAF_SUPER;
685 dataspace = (UBYTE *)INST_DATA(cl, obj) + ((rc >> 16) & 0x07FF);
686 data = attr->ti_Data;
688 if (rc & RAF_BOOL)
690 flag = 1 << ((rc >> 27) & 0x07);
691 if (rc & RAF_SIGNED) data = !data;
693 if (data) *dataspace |= flag;
694 else *dataspace &= ~flag;
696 else
698 switch (rc & (RAF_SIGNED|RAF_BYTE|RAF_WORD|RAF_LONG|RAF_ADDR))
700 case RAF_BYTE:
701 case RAF_BYTE|RAF_SIGNED:
702 *((UBYTE *)dataspace) = (UBYTE)data;
703 break;
704 case RAF_WORD:
705 case RAF_WORD|RAF_SIGNED:
706 *((UWORD *)dataspace) = (UWORD)data;
707 break;
708 case RAF_LONG:
709 case RAF_LONG|RAF_SIGNED:
710 *((ULONG *)dataspace) = (ULONG)data;
711 break;
712 case RAF_NOP:
713 break;
717 if (rc & RAF_CUSTOM)
719 AsmCoerceMethod(cl, obj, RM_SETCUSTOM, attr, flags);
721 if (rc & RAF_SUPER)
723 rc |= AsmDoSuperMethod(cl, obj, RM_SET, attr, flags);
725 rc = (rc & 0xFFFF) | RAF_UNDERSTOOD;
727 else
730 * Let the superclass have a go at it.
732 rc = AsmDoSuperMethod(cl, obj, RM_SET, attr, flags);
734 return rc;
736 REGFUNC_END
738 makeproto ULONG BGUI_PackStructureTag(UBYTE *dataspace, ULONG *pt, ULONG tag, ULONG data)
740 #ifdef ENHANCED
742 struct TagItem tags[2];
744 tags[0].ti_Tag = tag;
745 tags[0].ti_Data = data;
746 tags[1].ti_Tag = TAG_DONE;
748 return (ULONG)PackStructureTags((APTR)dataspace, pt, tags);
750 #else
752 ULONG type;
753 UBYTE flag;
754 ULONG base = *pt++;
756 while (type = *pt++)
758 if (type == 0xFFFFFFFF)
760 base = *pt++;
761 continue;
763 if (tag == (base + ((type >> 16) & 0x03FF) ))
765 if (type & PKCTRL_UNPACKONLY) return 0;
767 dataspace += (type & 0x1FFF);
769 switch (type & 0x18000000)
771 case PKCTRL_BIT:
772 flag = 1 << ((type >> 13) & 0x0007);
773 if (type & PSTF_SIGNED) data = !data;
774 if (data) *dataspace |= flag;
775 else *dataspace &= ~flag;
776 break;
777 case PKCTRL_UBYTE:
778 *((UBYTE *)dataspace) = (UBYTE)data;
779 break;
780 case PKCTRL_UWORD:
781 *((UWORD *)dataspace) = (UWORD)data;
782 break;
783 case PKCTRL_ULONG:
784 *((ULONG *)dataspace) = (ULONG)data;
785 break;
787 return 1;
790 return 0;
792 #endif
795 makeproto ULONG BGUI_UnpackStructureTag(UBYTE *dataspace, ULONG *pt, ULONG tag, ULONG *storage)
797 #ifdef ENHANCED
799 struct TagItem tags[2];
801 tags[0].ti_Tag = tag;
802 tags[0].ti_Data = (ULONG)storage;
803 tags[1].ti_Tag = TAG_DONE;
805 return (ULONG)UnpackStructureTags((APTR)dataspace, pt, tags);
807 #else
809 ULONG type, data;
810 ULONG base = *pt++;
812 while (type = *pt++)
814 if (type == 0xFFFFFFFF)
816 base = *pt++;
817 continue;
819 if (tag == (base + ((type >> 16) & 0x03FF) ))
821 if (type & PKCTRL_PACKONLY) return 0;
823 dataspace += (type & 0x1FFF);
825 switch (type & 0x98000000)
827 case PKCTRL_UBYTE:
828 data = (ULONG)(*((UBYTE *)dataspace));
829 break;
830 case PKCTRL_UWORD:
831 data = (ULONG)(*((UWORD *)dataspace));
832 break;
833 case PKCTRL_ULONG:
834 data = (ULONG)(*((ULONG *)dataspace));
835 break;
836 case PKCTRL_BYTE:
837 data = (LONG)(*((BYTE *)dataspace));
838 break;
839 case PKCTRL_WORD:
840 data = (LONG)(*((WORD *)dataspace));
841 break;
842 case PKCTRL_LONG:
843 data = (LONG)(*((LONG *)dataspace));
844 break;
845 case PKCTRL_BIT:
846 case PKCTRL_FLIPBIT:
847 data = (*dataspace & (1 << ((type >> 13) & 0x0007))) ? ~0 : 0;
848 if (type & PSTF_SIGNED) data = ~data;
849 break;
851 *storage = data;
852 return 1;
855 return 0;
857 #endif
860 #ifdef __AROS__
861 makearosproto
862 AROS_LH3(ULONG, BGUI_PackStructureTags,
863 AROS_LHA(APTR, pack, A0),
864 AROS_LHA(ULONG *, packTable, A1),
865 AROS_LHA(struct TagItem *, tagList, A2),
866 struct Library *, BGUIBase, 26, BGUI)
867 #else
868 makeproto SAVEDS ULONG ASM BGUI_PackStructureTags(REG(a0) APTR pack, REG(a1) ULONG *packTable, REG(a2) struct TagItem *tagList)
869 #endif
871 AROS_LIBFUNC_INIT
873 #ifdef ENHANCED
875 return PackStructureTags(pack, packTable, tagList);
877 #else
879 struct TagItem *tstate = tagList, *tag;
880 ULONG rc = 0;
882 while (tag = NextTagItem(&tstate))
884 rc += BGUI_PackStructureTag((UBYTE *)pack, packTable, tag->ti_Tag, tag->ti_Data);
886 return rc;
888 #endif
890 AROS_LIBFUNC_EXIT
893 #ifdef __AROS__
894 makearosproto
895 AROS_LH3(ULONG, BGUI_UnpackStructureTags,
896 AROS_LHA(APTR, pack, A0),
897 AROS_LHA(ULONG *, packTable, A1),
898 AROS_LHA(struct TagItem *, tagList, A2),
899 struct Library *, BGUIBase, 27, BGUI)
900 #else
901 makeproto SAVEDS ULONG ASM BGUI_UnpackStructureTags(REG(a0) APTR pack, REG(a1) ULONG *packTable, REG(a2) struct TagItem *tagList)
902 #endif
904 AROS_LIBFUNC_INIT
906 #ifdef ENHANCED
908 return UnpackStructureTags(pack, packTable, tagList);
910 #else
912 struct TagItem *tstate = tagList, *tag;
913 ULONG rc = 0;
915 while (tag = NextTagItem(&tstate))
917 rc += BGUI_UnpackStructureTag((UBYTE *)pack, packTable, tag->ti_Tag, (ULONG *)tag->ti_Data);
919 return rc;
921 #endif
923 AROS_LIBFUNC_EXIT
927 * Quick GetAttr();
929 //makeproto ASM ULONG Get_Attr(REG(a0) Object *obj, REG(d0) ULONG attr, REG(a1) void *storage)
930 makeproto ASM REGFUNC3(ULONG, Get_Attr,
931 REGPARAM(A0, Object *, obj),
932 REGPARAM(D0, ULONG, attr),
933 REGPARAM(A1, void *, storage))
935 return AsmDoMethod(obj, OM_GET, attr, storage);
937 REGFUNC_END
939 //makeproto ASM ULONG Get_SuperAttr(REG(a2) Class *cl, REG(a0) Object *obj, REG(d0) ULONG attr, REG(a1) void *storage)
940 makeproto ASM REGFUNC4(ULONG, Get_SuperAttr,
941 REGPARAM(A2, Class *, cl),
942 REGPARAM(A0, Object *, obj),
943 REGPARAM(D0, ULONG, attr),
944 REGPARAM(A1, void *, storage))
946 return AsmDoSuperMethod(cl, obj, OM_GET, attr, storage);
948 REGFUNC_END
950 makeproto ULONG NewSuperObject(Class *cl, Object *obj, struct TagItem *tags)
952 return AsmDoSuperMethod(cl, obj, OM_NEW, (ULONG)tags, NULL);
956 * Like SetAttrs();
958 makeproto ULONG DoSetMethodNG(Object *obj, Tag tag1, ...)
960 if (obj) return AsmDoMethod(obj, OM_SET, (struct TagItem *)&tag1, NULL);
961 else return 0;
965 * Like SetAttrs();
967 makeproto ULONG DoSuperSetMethodNG(Class *cl, Object *obj, Tag tag1, ...)
969 if (obj) return AsmDoSuperMethod(cl, obj, OM_SET, (struct TagItem *)&tag1, NULL);
970 else return 0;
974 * Call the OM_SET method.
976 makeproto ULONG DoSetMethod(Object *obj, struct GadgetInfo *ginfo, Tag tag1, ...)
978 if (obj) return AsmDoMethod(obj, OM_SET, (struct TagItem *)&tag1, ginfo);
979 else return 0;
983 * Call the OM_SET method of the superclass.
985 makeproto ULONG DoSuperSetMethod(Class *cl, Object *obj, struct GadgetInfo *ginfo, Tag tag1, ...)
987 if (obj) return AsmDoSuperMethod(cl, obj, OM_SET, (struct TagItem *)&tag1, ginfo);
988 else return 0;
992 * Call the OM_UPDATE method.
994 makeproto ULONG DoUpdateMethod(Object *obj, struct GadgetInfo *ginfo, ULONG flags, Tag tag1, ...)
996 if (obj) return AsmDoMethod(obj, OM_UPDATE, (struct TagItem *)&tag1, ginfo, flags);
997 else return 0;
1001 * Call the OM_NOTIFY method.
1003 makeproto ULONG DoNotifyMethod(Object *obj, struct GadgetInfo *ginfo, ULONG flags, Tag tag1, ...)
1005 if (obj) return AsmDoMethod(obj, OM_NOTIFY, (struct TagItem *)&tag1, ginfo, flags);
1006 else return 0;
1010 * Call the GM_RENDER method.
1013 //makeproto ASM ULONG DoRenderMethod(REG(a0) Object *obj, REG(a1) struct GadgetInfo *ginfo, REG(d0) ULONG redraw)
1014 makeproto ASM REGFUNC3(ULONG, DoRenderMethod,
1015 REGPARAM(A0, Object *, obj),
1016 REGPARAM(A1, struct GadgetInfo *, ginfo),
1017 REGPARAM(D0, ULONG, redraw))
1019 struct RastPort *rp;
1020 ULONG rc = 0;
1022 if (obj && (rp = BGUI_ObtainGIRPort(ginfo)))
1024 rc = AsmDoMethod(obj, GM_RENDER, ginfo, rp, redraw);
1025 ReleaseGIRPort(rp);
1027 return rc;
1029 REGFUNC_END
1032 * Forward certain types of messages with modifications.
1034 //makeproto ASM ULONG ForwardMsg(REG(a0) Object *s, REG(a1) Object *d, REG(a2) Msg msg)
1035 makeproto ASM REGFUNC3(ULONG, ForwardMsg,
1036 REGPARAM(A0, Object *, s),
1037 REGPARAM(A1, Object *, d),
1038 REGPARAM(A2, Msg, msg))
1040 #ifdef __AROS__
1041 #define MOUSEWORD STACKWORD
1042 #else
1043 #define MOUSEWORD WORD
1044 #endif
1045 MOUSEWORD *mousex = NULL, *mousey = NULL, old_mousex, old_mousey;
1046 ULONG rc;
1047 struct IBox *b1 = GADGETBOX(s);
1048 struct IBox *b2 = GADGETBOX(d);
1051 * Get address of mouse coordinates in message.
1053 switch (msg->MethodID)
1055 case GM_HITTEST:
1056 case GM_HELPTEST:
1057 mousex = &((struct gpHitTest *)msg)->gpht_Mouse.X;
1058 mousey = &((struct gpHitTest *)msg)->gpht_Mouse.Y;
1059 break;
1060 case GM_GOACTIVE:
1061 case GM_HANDLEINPUT:
1062 mousex = &((struct gpInput *)msg)->gpi_Mouse.X;
1063 mousey = &((struct gpInput *)msg)->gpi_Mouse.Y;
1064 break;
1066 if (!mousex) return 0;
1069 * Store the coordinates.
1071 old_mousex = *mousex;
1072 old_mousey = *mousey;
1074 Get_Attr(s, BT_OuterBox, (ULONG *)&b1);
1075 Get_Attr(d, BT_OuterBox, (ULONG *)&b2);
1078 * Adjust the coordinates to be relative to the destination object.
1080 *mousex += b1->Left - b2->Left;
1081 *mousey += b1->Top - b2->Top;
1084 * Send the message to the destination object.
1086 rc = AsmDoMethodA(d, msg);
1089 * Put the coordinates back to what they were originally.
1091 *mousex = old_mousex;
1092 *mousey = old_mousey;
1094 return rc;
1096 REGFUNC_END
1098 #define BI_FREE_RP 1
1099 #define BI_FREE_DRI 2
1101 #ifdef DEBUG_BGUI
1102 makeproto struct BaseInfo *AllocBaseInfoDebug(STRPTR file, ULONG line,ULONG tag1, ...)
1104 return BGUI_AllocBaseInfoDebugA((struct TagItem *)&tag1,file,line);
1106 #else
1107 makeproto struct BaseInfo *AllocBaseInfo(ULONG tag1, ...)
1109 return BGUI_AllocBaseInfoA((struct TagItem *)&tag1);
1111 #endif
1113 #ifdef DEBUG_BGUI
1114 //makeproto SAVEDS ASM struct BaseInfo *BGUI_AllocBaseInfoDebugA(REG(a0) struct TagItem *tags,REG(a1) STRPTR file, REG(d0) ULONG line)
1115 makeproto SAVEDS ASM REGFUNC3(struct BaseInfo *, BGUI_AllocBaseInfoDebugA,
1116 REGPARAM(A0, struct TagItem *, tags),
1117 REGPARAM(A1, STRPTR, file),
1118 REGPARAM(D0, ULONG, line))
1119 #else
1120 //makeproto SAVEDS ASM struct BaseInfo *BGUI_AllocBaseInfoA(REG(a0) struct TagItem *tags)
1121 makeproto SAVEDS ASM REGFUNC1(struct BaseInfo *, BGUI_AllocBaseInfoA,
1122 REGPARAM(A0, struct TagItem *, tags))
1123 #endif
1125 struct BaseInfo *bi, *bi2;
1126 struct GadgetInfo *gi = NULL;
1127 ULONG *flags;
1129 #ifdef DEBUG_BGUI
1130 if (bi = BGUI_AllocPoolMemDebug(sizeof(struct BaseInfo) + sizeof(ULONG),file,line))
1131 #else
1132 if (bi = BGUI_AllocPoolMem(sizeof(struct BaseInfo) + sizeof(ULONG)))
1133 #endif
1135 flags = (ULONG *)(bi + 1);
1137 if (bi2 = (struct BaseInfo *)GetTagData(BI_BaseInfo, NULL, tags))
1139 *bi = *bi2;
1141 else
1142 memset(bi,'\0',sizeof(*bi));
1144 if (gi = (struct GadgetInfo *)GetTagData(BI_GadgetInfo, (ULONG)gi, tags))
1146 *((struct GadgetInfo *)bi) = *gi;
1149 bi->bi_DrInfo = (struct DrawInfo *)GetTagData(BI_DrawInfo, (ULONG)bi->bi_DrInfo, tags);
1150 bi->bi_RPort = (struct RastPort *)GetTagData(BI_RastPort, (ULONG)bi->bi_RPort, tags);
1151 bi->bi_IScreen = (struct Screen *) GetTagData(BI_Screen, (ULONG)bi->bi_IScreen, tags);
1152 bi->bi_Pens = (UWORD *) GetTagData(BI_Pens, (ULONG)bi->bi_Pens, tags);
1154 if (gi && !bi->bi_RPort)
1156 if (bi->bi_RPort = ObtainGIRPort(gi))
1158 *flags |= BI_FREE_RP;
1162 if (bi->bi_IScreen && !bi->bi_DrInfo)
1164 if (bi->bi_DrInfo = GetScreenDrawInfo(bi->bi_IScreen))
1166 *flags |= BI_FREE_DRI;
1170 if (!bi->bi_Pens)
1172 if (bi->bi_DrInfo) bi->bi_Pens = bi->bi_DrInfo->dri_Pens;
1173 else bi->bi_Pens = DefDriPens;
1176 return bi;
1178 REGFUNC_END
1180 #ifdef DEBUG_BGUI
1181 makeproto void FreeBaseInfoDebug(struct BaseInfo *bi, STRPTR file, ULONG line)
1183 #else
1184 makeproto void FreeBaseInfo(struct BaseInfo *bi)
1186 #endif
1187 ULONG *flags = (ULONG *)(bi + 1);
1189 if (*flags & BI_FREE_RP) ReleaseGIRPort(bi->bi_RPort);
1190 if (*flags & BI_FREE_DRI) FreeScreenDrawInfo(bi->bi_IScreen, bi->bi_DrInfo);
1192 #ifdef DEBUG_BGUI
1193 BGUI_FreePoolMemDebug(bi,file,line);
1194 #else
1195 BGUI_FreePoolMem(bi);
1196 #endif