use dmb/dsb from asm/cpu.h file.
[AROS.git] / workbench / libs / muimaster / classes / family.c
blob903d1520ce018cf3218fe10f69343be059897275
1 /*
2 Copyright © 1999, David Le Corfec.
3 Copyright © 2002-2015, The AROS Development Team.
4 All rights reserved.
6 $Id$
7 */
9 #include <exec/types.h>
11 #include <clib/alib_protos.h>
12 #include <proto/exec.h>
13 #include <proto/intuition.h>
14 #include <proto/utility.h>
15 #include <proto/muimaster.h>
17 /* #define MYDEBUG 1 */
18 #include "debug.h"
19 #include "muimaster_intern.h"
20 #include "mui.h"
22 extern struct Library *MUIMasterBase;
24 struct MUI_FamilyData
26 struct List children;
30 * Family class is the base class for objects that are able
31 * to handle a list of children. This is e.g. the case for
32 * MUIs Menustrip, Menu and Menuitem objects.
33 * Group class and application class should also be a
34 * subclass of Family class, but due to BOOPSI system
35 * limitations, this is currently impossible.
39 Family.mui/MUIA_Family_Child [I..] done (note : == MUIA_Group_Child)
40 Family.mui/MUIA_Family_List [..G] done
42 Family.mui/MUIM_Family_AddHead done
43 Family.mui/MUIM_Family_AddTail done
44 Family.mui/MUIM_Family_Insert done
45 Family.mui/MUIM_Family_Remove done
46 Family.mui/MUIM_Family_Sort done
47 Family.mui/MUIM_Family_Transfer done
48 Notify.mui/MUIM_FindUData done
49 Notify.mui/MUIM_GetUData done
50 Notify.mui/MUIM_SetUData done
51 Notify.mui/MUIM_SetUDataOnce done
54 static const int __version = 1;
55 static const int __revision = 1;
57 /* static void */
58 /* debuglist(struct List *list) */
59 /* { */
60 /* g_print("list %p:\nlh_Head@%p = %p\nlh_Tail@%p = %p\nlh_TailPred@%p = %p\n", */
61 /* list, &list->lh_Head, list->lh_Head, */
62 /* &list->lh_Tail, list->lh_Tail, */
63 /* &list->lh_TailPred, list->lh_TailPred); */
64 /* } */
66 /* static void */
67 /* printlist (struct List *list) */
68 /* { */
69 /* struct Node *node; */
71 /* debuglist(list); */
73 /* for (node = list->lh_Head; node->ln_Succ; node = node->ln_Succ) */
74 /* { */
75 /* g_print("%s (ln_Succ@%p = %p | ln_Pred@%p = %p)\n", "node->ln_Name", */
76 /* &node->ln_Succ, node->ln_Succ, &node->ln_Pred, node->ln_Pred); */
77 /* } */
78 /* g_print("\n"); */
79 /* } */
82 * OM_NEW
84 IPTR Family__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
86 struct MUI_FamilyData *data;
87 struct TagItem *tags;
88 struct TagItem *tag;
89 BOOL bad_children = FALSE;
91 obj = (Object *) DoSuperMethodA(cl, obj, (Msg) msg);
92 if (!obj)
93 return FALSE;
95 * Initial local instance data
97 data = INST_DATA(cl, obj);
98 NewList(&(data->children));
101 * parse initial taglist
103 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags));)
105 if (tag->ti_Tag == MUIA_Family_Child
106 || tag->ti_Tag == MUIA_Group_Child)
108 if (tag->ti_Data) /* add child */
109 DoMethod(obj, MUIM_Family_AddTail, tag->ti_Data);
110 else /* fail and dispose children */
112 bad_children = TRUE;
117 if (bad_children)
119 CoerceMethod(cl, obj, OM_DISPOSE);
120 return 0;
123 return (IPTR) obj;
128 * OM_DISPOSE
130 IPTR Family__OM_DISPOSE(struct IClass *cl, Object *obj, Msg msg)
132 struct MUI_FamilyData *data = INST_DATA(cl, obj);
133 Object *cstate = (Object *) data->children.lh_Head;
134 Object *child;
136 while ((child = NextObject(&cstate)))
138 /* g_print("Family_Dispose: dispose child %p\n", child); */
139 MUI_DisposeObject(child);
142 return DoSuperMethodA(cl, obj, msg);
147 * OM_GET
149 IPTR Family__OM_GET(struct IClass *cl, Object *obj, struct opGet *msg)
151 struct MUI_FamilyData *data = INST_DATA(cl, obj);
152 IPTR *store = msg->opg_Storage;
154 switch (msg->opg_AttrID)
156 case MUIA_Family_List:
157 *store = (IPTR) & data->children;
158 return TRUE;
160 case MUIA_Version:
161 *store = __version;
162 return TRUE;
164 case MUIA_Revision:
165 *store = __revision;
166 return TRUE;
168 case MUIA_Family_ChildCount:
170 Object *cstate = (Object *) data->children.lh_Head;
171 *store = 0;
172 while (NextObject(&cstate))
173 (*store)++;
174 return TRUE;
178 return (DoSuperMethodA(cl, obj, (Msg) msg));
183 * MUIM_Family_AddHead : Add an object as first object to the family.
185 IPTR Family__MUIM_AddHead(struct IClass *cl, Object *obj,
186 struct MUIP_Family_AddHead *msg)
188 struct MUI_FamilyData *data = INST_DATA(cl, obj);
190 if (msg->obj)
192 AddHead(&(data->children), (struct Node *)_OBJECT(msg->obj));
194 /* if we are in an application tree, propagate pointers */
195 if (muiNotifyData(obj)->mnd_GlobalInfo)
197 DoMethod(msg->obj, MUIM_ConnectParent, (IPTR)obj);
200 /* Some apps (Odyssey) expect _parent() will work before group tree
201 * is added to application tree */
202 muiNotifyData(msg->obj)->mnd_ParentObject = obj;
204 return TRUE;
206 else
207 return FALSE;
212 * MUIM_Family_AddTail : Add an object as last object to the family.
214 IPTR Family__MUIM_AddTail(struct IClass *cl, Object *obj,
215 struct MUIP_Family_AddTail *msg)
217 struct MUI_FamilyData *data = INST_DATA(cl, obj);
219 if (msg->obj)
221 D(bug("Family_AddTail(%p): obj=%p node=%p\n", obj, msg->obj,
222 _OBJECT(msg->obj)));
223 DoMethod(msg->obj, OM_ADDTAIL, (IPTR) & data->children);
225 /* if we are in an application tree, propagate pointers */
226 if (muiNotifyData(obj)->mnd_GlobalInfo)
228 DoMethod(msg->obj, MUIM_ConnectParent, (IPTR)obj);
231 /* Some apps (Odyssey) expect _parent() will work before group tree
232 * is added to application tree */
233 muiNotifyData(msg->obj)->mnd_ParentObject = obj;
235 return TRUE;
237 else
238 return FALSE;
243 * MUIM_Family_Insert : Add an object after another object to the family.
245 IPTR Family__MUIM_Insert(struct IClass *cl, Object *obj,
246 struct MUIP_Family_Insert *msg)
248 struct MUI_FamilyData *data = INST_DATA(cl, obj);
250 if (msg->obj)
252 Insert(&(data->children), (struct Node *)_OBJECT(msg->obj),
253 (struct Node *)_OBJECT(msg->pred));
255 /* if we are in an application tree, propagate pointers */
256 if (muiNotifyData(obj)->mnd_GlobalInfo)
258 DoMethod(msg->obj, MUIM_ConnectParent, (IPTR)obj);
261 /* Some apps (Odyssey) expect _parent() will work before group tree
262 * is added to application tree */
263 muiNotifyData(msg->obj)->mnd_ParentObject = obj;
265 return TRUE;
267 else
268 return FALSE;
273 * MUIM_Family_Remove : Remove an object from a family.
275 IPTR Family__MUIM_Remove(struct IClass *cl, Object *obj,
276 struct MUIP_Family_Remove *msg)
278 /* struct MUI_FamilyData *data = INST_DATA(cl, obj);
279 struct Node *node; */
281 if (msg->obj)
283 /* D(bug("Family_Remove(%p): obj=%p\n", obj, msg->obj)); */
284 DoMethod(msg->obj, MUIM_DisconnectParent);
285 muiNotifyData(msg->obj)->mnd_ParentObject = NULL;
286 DoMethod(msg->obj, OM_REMOVE);
287 return TRUE;
289 else
290 return FALSE;
295 * MUIM_Family_Sort : Sort the children of a family.
297 IPTR Family__MUIM_Sort(struct IClass *cl, Object *obj,
298 struct MUIP_Family_Sort *msg)
300 struct MUI_FamilyData *data = INST_DATA(cl, obj);
301 int i;
303 NewList(&(data->children));
304 for (i = 0; msg->obj[i]; i++)
306 AddTail(&(data->children), (struct Node *)_OBJECT(msg->obj[i]));
308 return TRUE;
313 * MUIM_Family_Transfer : All the children of the family are removed and
314 * added to another family in the same order.
316 IPTR Family__MUIM_Transfer(struct IClass *cl, Object *obj,
317 struct MUIP_Family_Transfer *msg)
319 struct MUI_FamilyData *data = INST_DATA(cl, obj);
320 Object *cstate = (Object *) data->children.lh_Head;
321 Object *child;
323 while ((child = NextObject(&cstate)))
325 DoMethod(obj, MUIM_Family_Remove, (IPTR) child);
326 DoMethod(msg->family, MUIM_Family_AddTail, (IPTR) child);
328 return TRUE;
332 /**************************************************************************
333 MUIM_FindUData : tests if the MUIA_UserData of the object
334 contains the given <udata> and returns the object pointer in this case.
335 **************************************************************************/
336 IPTR Family__MUIM_FindUData(struct IClass *cl, Object *obj,
337 struct MUIP_FindUData *msg)
339 struct MUI_FamilyData *data = INST_DATA(cl, obj);
340 Object *cstate = (Object *) data->children.lh_Head;
341 Object *child;
343 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
344 return (IPTR) obj;
346 while ((child = NextObject(&cstate)))
348 Object *found = (Object *) DoMethodA(child, (Msg) msg);
349 if (found)
350 return (IPTR) found;
352 return 0;
357 * MUIM_GetUData : This method tests if the MUIA_UserData of the object
358 * contains the given <udata> and gets <attr> to <storage> for itself
359 * in this case.
361 IPTR Family__MUIM_GetUData(struct IClass *cl, Object *obj,
362 struct MUIP_GetUData *msg)
364 struct MUI_FamilyData *data = INST_DATA(cl, obj);
365 Object *cstate = (Object *) data->children.lh_Head;
366 Object *child;
368 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
370 get(obj, msg->attr, msg->storage);
371 return TRUE;
373 while ((child = NextObject(&cstate)))
374 if (DoMethodA(child, (Msg) msg))
375 return TRUE;
377 return FALSE;
382 * MUIM_SetUData : This method tests if the MUIA_UserData of the object
383 * contains the given <udata> and sets <attr> to <val> for itself in this case.
385 IPTR Family__MUIM_SetUData(struct IClass *cl, Object *obj,
386 struct MUIP_SetUData *msg)
388 struct MUI_FamilyData *data = INST_DATA(cl, obj);
389 Object *cstate = (Object *) data->children.lh_Head;
390 Object *child;
392 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
393 set(obj, msg->attr, msg->val);
395 while ((child = NextObject(&cstate)))
396 DoMethodA(child, (Msg) msg);
398 return TRUE;
403 * MUIM_SetUDataOnce : This method tests if the MUIA_UserData of the object
404 * contains the given <udata> and sets <attr> to <val> for itself in this case.
406 IPTR Family__MUIM_SetUDataOnce(struct IClass *cl, Object *obj,
407 struct MUIP_SetUDataOnce *msg)
409 struct MUI_FamilyData *data = INST_DATA(cl, obj);
410 Object *cstate = (Object *) data->children.lh_Head;
411 Object *child;
413 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
415 set(obj, msg->attr, msg->val);
416 return TRUE;
418 while ((child = NextObject(&cstate)))
419 if (DoMethodA(child, (Msg) msg))
420 return TRUE;
422 return FALSE;
425 IPTR Family__MUIM_GetChild(struct IClass *cl, Object *obj,
426 struct MUIP_Family_GetChild *msg)
428 struct MUI_FamilyData *data = INST_DATA(cl, obj);
429 Object *cstate = (Object *) data->children.lh_Head;
430 Object *child, *prev = NULL;
431 LONG counter = 0;
433 while ((child = NextObject(&cstate)))
435 if ((msg->nr >= 0) && (msg->nr == counter))
436 return (IPTR) child;
438 if ((msg->ref != NULL) && (msg->ref == child))
440 if (msg->nr == MUIV_Family_GetChild_Next)
441 return (IPTR) NextObject(&cstate);
442 if (msg->nr == MUIV_Family_GetChild_Previous)
443 return (IPTR) prev;
446 if (msg->nr == MUIV_Family_GetChild_First)
447 return (IPTR) child;
449 prev = child;
450 counter++;
453 if (msg->nr == MUIV_Family_GetChild_Last)
454 return (IPTR) prev;
456 return (IPTR) NULL;
459 BOOPSI_DISPATCHER(IPTR, Family_Dispatcher, cl, obj, msg)
461 switch (msg->MethodID)
463 case OM_NEW:
464 return Family__OM_NEW(cl, obj, (struct opSet *)msg);
466 case OM_DISPOSE:
467 return Family__OM_DISPOSE(cl, obj, msg);
469 case OM_GET:
470 return Family__OM_GET(cl, obj, (struct opGet *)msg);
472 case MUIM_Family_AddHead:
473 return Family__MUIM_AddHead(cl, obj, (APTR) msg);
475 case OM_ADDMEMBER:
476 case MUIM_Family_AddTail:
477 return Family__MUIM_AddTail(cl, obj, (APTR) msg);
479 case MUIM_Family_Insert:
480 return Family__MUIM_Insert(cl, obj, (APTR) msg);
482 case OM_REMMEMBER:
483 case MUIM_Family_Remove:
484 return Family__MUIM_Remove(cl, obj, (APTR) msg);
486 case MUIM_Family_Sort:
487 return Family__MUIM_Sort(cl, obj, (APTR) msg);
489 case MUIM_Family_Transfer:
490 return Family__MUIM_Transfer(cl, obj, (APTR) msg);
492 case MUIM_FindUData:
493 return Family__MUIM_FindUData(cl, obj, (APTR) msg);
495 case MUIM_GetUData:
496 return Family__MUIM_GetUData(cl, obj, (APTR) msg);
498 case MUIM_SetUData:
499 return Family__MUIM_SetUData(cl, obj, (APTR) msg);
501 case MUIM_SetUDataOnce:
502 return Family__MUIM_SetUDataOnce(cl, obj, (APTR) msg);
504 case MUIM_Family_GetChild:
505 return Family__MUIM_GetChild(cl, obj, (APTR) msg);
508 return (DoSuperMethodA(cl, obj, msg));
510 BOOPSI_DISPATCHER_END
513 * Class descriptor.
515 const struct __MUIBuiltinClass _MUI_Family_desc =
517 MUIC_Family,
518 MUIC_Notify,
519 sizeof(struct MUI_FamilyData),
520 (void *) Family_Dispatcher