update experimental gcc 6 patch to gcc 6.1.0 release
[AROS.git] / workbench / libs / muimaster / classes / menuitem.c
blobc6641ca894fd0667f4f3928b3114571c1e8c7654
1 /*
2 Copyright © 2002-2015, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <exec/memory.h>
7 #include <intuition/icclass.h>
8 #include <intuition/gadgetclass.h>
9 #include <libraries/gadtools.h>
10 #include <clib/alib_protos.h>
11 #include <proto/exec.h>
12 #include <proto/intuition.h>
13 #include <proto/utility.h>
14 #include <proto/muimaster.h>
16 /* #define MYDEBUG 1 */
17 #include "debug.h"
18 #include "mui.h"
19 #include "muimaster_intern.h"
20 #include "support.h"
22 extern struct Library *MUIMasterBase;
24 #define MENUF_CHECKED (1<<0)
25 #define MENUF_CHECKIT (1<<1)
26 #define MENUF_COMMANDSTRING (1<<2)
27 #define MENUF_ENABLED (1<<3)
28 #define MENUF_TOGGLE (1<<4)
30 #define MENUF_MENUSTRIP (1<<15)
31 #define MENUF_MENU (1<<16)
32 #define MENUF_MENUITEM (1<<17)
34 #define MUIA_Menuitem_Type (MUIB_Menuitem | 0x00000001)
36 #define MUIV_Menuitem_Type_Menustrip (-1)
37 #define MUIV_Menuitem_Type_Menu (-2)
38 #define MUIV_Menuitem_Type_Menuitem (-3)
40 struct MUI_MenuitemData
42 ULONG flags;
43 ULONG exclude;
45 char *shortcut;
46 char *title;
48 struct NewMenu *newmenu;
50 struct MenuItem *trigger;
53 static int Menuitem_GetTotalChildren(Object *obj)
55 Object *cstate;
56 Object *child;
57 struct MinList *ChildList = NULL;
58 int num = 0;
60 get(obj, MUIA_Family_List, &ChildList);
61 cstate = (Object *) ChildList->mlh_Head;
62 while ((child = NextObject(&cstate)))
64 num++;
65 num += Menuitem_GetTotalChildren(child);
67 return num;
70 static int Menuitem_FillNewMenu(Object *obj, struct NewMenu *menu,
71 int depth)
73 Object *cstate;
74 Object *child;
75 struct MinList *ChildList = NULL;
76 int num = 0;
78 if (depth > 2)
79 return 0;
81 get(obj, MUIA_Family_List, &ChildList);
82 cstate = (Object *) ChildList->mlh_Head;
83 while ((child = NextObject(&cstate)))
85 int entries;
86 ULONG checkit = 0, checked = 0, toggle = 0, enabled = 0;
88 get(child, MUIA_Menuitem_Title, &menu->nm_Label);
89 get(child, MUIA_Menuitem_Shortcut, &menu->nm_CommKey);
90 get(child, MUIA_Menuitem_Checkit, &checkit);
91 get(child, MUIA_Menuitem_Checked, &checked);
92 get(child, MUIA_Menuitem_Toggle, &toggle);
93 get(child, MUIA_Menuitem_Enabled, &enabled);
94 if (checkit)
95 menu->nm_Flags |= CHECKIT;
96 if (checked)
97 menu->nm_Flags |= CHECKED;
98 if (toggle)
99 menu->nm_Flags |= MENUTOGGLE;
100 get(child, MUIA_Menuitem_Exclude, &menu->nm_MutualExclude);
102 if (depth == 0)
104 LONG type = 0;
105 get(child, MUIA_Menuitem_Type, &type);
107 if (type == MUIV_Menuitem_Type_Menuitem)
108 /* Depth 0 Menuitems are to become items of current menu,
109 * not menus. MUI behavior */
110 menu->nm_Type = NM_ITEM;
111 else
112 menu->nm_Type = NM_TITLE;
114 else if (depth == 1)
115 menu->nm_Type = NM_ITEM;
116 else if (depth == 2)
117 menu->nm_Type = NM_SUB;
119 if (!enabled)
121 if (menu->nm_Type == NM_TITLE)
122 menu->nm_Flags |= NM_MENUDISABLED;
123 else
124 menu->nm_Flags |= NM_ITEMDISABLED;
127 menu->nm_UserData = child;
129 menu++;
130 num++;
131 entries = Menuitem_FillNewMenu(child, menu, depth + 1);
133 menu += entries;
134 num += entries;
136 return num;
139 /**************************************************************************
141 **************************************************************************/
142 static struct NewMenu *Menuitem_BuildNewMenu(struct MUI_MenuitemData *data,
143 Object *obj)
145 int entries = Menuitem_GetTotalChildren(obj);
146 if (data->newmenu)
147 FreeVec(data->newmenu);
148 data->newmenu = NULL;
149 if (!entries)
150 return NULL;
152 if ((data->newmenu =
153 (struct NewMenu *)AllocVec((entries +
154 1) * sizeof(struct NewMenu), MEMF_CLEAR)))
156 Menuitem_FillNewMenu(obj, data->newmenu, 0);
158 return data->newmenu;
161 /**************************************************************************
162 OM_NEW
163 **************************************************************************/
164 IPTR Common__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
166 struct MUI_MenuitemData *data;
167 struct TagItem *tags, *tag;
169 obj = (Object *) DoSuperMethodA(cl, obj, (Msg) msg);
170 /* We need no tags */
171 if (!obj)
172 return 0;
174 data = INST_DATA(cl, obj);
176 data->flags = MENUF_ENABLED;
178 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags));)
180 switch (tag->ti_Tag)
182 case MUIA_Menuitem_Checked:
183 _handle_bool_tag(data->flags, tag->ti_Data, MENUF_CHECKED);
184 break;
186 case MUIA_Menuitem_Checkit:
187 _handle_bool_tag(data->flags, tag->ti_Data, MENUF_CHECKIT);
188 break;
190 case MUIA_Menuitem_CommandString:
191 _handle_bool_tag(data->flags, tag->ti_Data, MENUF_COMMANDSTRING);
192 break;
194 case MUIA_Menu_Enabled:
195 case MUIA_Menuitem_Enabled:
196 _handle_bool_tag(data->flags, tag->ti_Data, MENUF_ENABLED);
197 break;
199 case MUIA_Menuitem_Toggle:
200 _handle_bool_tag(data->flags, tag->ti_Data, MENUF_TOGGLE);
201 break;
203 case MUIA_Menuitem_Exclude:
204 data->exclude = tag->ti_Data;
205 break;
207 case MUIA_Menuitem_Shortcut:
208 data->shortcut = (char *)tag->ti_Data;
209 break;
211 case MUIA_Menu_Title:
212 case MUIA_Menuitem_Title:
213 data->title = (char *)tag->ti_Data;
214 break;
218 return (IPTR) obj;
221 IPTR Menuitem__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
223 struct MUI_MenuitemData *data;
224 obj = (Object *) Common__OM_NEW(cl, obj, msg);
225 data = INST_DATA(cl, obj);
227 data->flags |= MENUF_MENUITEM;
229 return (IPTR) obj;
232 IPTR Menu__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
234 struct MUI_MenuitemData *data;
235 obj = (Object *) Common__OM_NEW(cl, obj, msg);
236 data = INST_DATA(cl, obj);
238 data->flags |= MENUF_MENU;
240 return (IPTR) obj;
243 IPTR Menustrip__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
245 struct MUI_MenuitemData *data;
246 obj = (Object *) Common__OM_NEW(cl, obj, msg);
247 data = INST_DATA(cl, obj);
249 data->flags |= MENUF_MENUSTRIP;
251 return (IPTR) obj;
254 /**************************************************************************
255 OM_SET
256 **************************************************************************/
257 IPTR Menuitem__OM_SET(struct IClass *cl, Object *obj, struct opSet *msg)
259 struct MUI_MenuitemData *data;
260 struct TagItem *tags, *tag;
262 data = INST_DATA(cl, obj);
264 BOOL rebuild = FALSE;
266 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags));)
268 switch (tag->ti_Tag)
270 case MUIA_Menuitem_Checked:
271 _handle_bool_tag(data->flags, tag->ti_Data, MENUF_CHECKED);
272 if (data->exclude && (data->flags & MENUF_CHECKED))
274 Object *parent = NULL;
275 get(obj, MUIA_Parent, &parent);
277 if (parent)
279 Object *child;
280 Object *cstate;
281 struct MinList *ChildList = NULL;
282 ULONG i = 1;
284 get(parent, MUIA_Family_List, &ChildList);
285 cstate = (Object *) ChildList->mlh_Head;
286 while ((child = NextObject(&cstate)))
288 if ((i & data->exclude) && (child != obj))
290 IPTR checkit = 0, checked = 0;
292 get(child, MUIA_Menuitem_Checkit, &checkit);
293 get(child, MUIA_Menuitem_Checked, &checked);
295 if (checkit && checked)
297 set(child, MUIA_Menuitem_Checked, FALSE);
301 i <<= 1;
306 rebuild = TRUE;
307 break;
309 case MUIA_Menuitem_Checkit:
310 _handle_bool_tag(data->flags, tag->ti_Data, MENUF_CHECKIT);
311 rebuild = TRUE;
312 break;
314 case MUIA_Menuitem_CommandString:
315 _handle_bool_tag(data->flags, tag->ti_Data,
316 MENUF_COMMANDSTRING);
317 rebuild = TRUE;
318 break;
320 case MUIA_Menu_Enabled:
321 case MUIA_Menuitem_Enabled:
322 _handle_bool_tag(data->flags, tag->ti_Data, MENUF_ENABLED);
323 tag->ti_Tag = TAG_IGNORE;
324 rebuild = TRUE;
325 break;
327 case MUIA_Menuitem_Toggle:
328 _handle_bool_tag(data->flags, tag->ti_Data, MENUF_TOGGLE);
329 rebuild = TRUE;
330 break;
332 case MUIA_Menuitem_Exclude:
333 data->exclude = tag->ti_Data;
334 rebuild = TRUE;
335 break;
337 case MUIA_Menuitem_Shortcut:
338 data->shortcut = (char *)tag->ti_Data;
339 rebuild = TRUE;
340 break;
342 case MUIA_Menu_Title:
343 case MUIA_Menuitem_Title:
344 data->title = (char *)tag->ti_Data;
345 tag->ti_Tag = TAG_IGNORE;
346 rebuild = TRUE;
347 break;
349 case MUIA_Menuitem_Trigger:
350 data->trigger = (struct MenuItem *)tag->ti_Data;
351 rebuild = TRUE;
352 break;
356 if (rebuild)
358 if (muiNotifyData(obj) &&
359 muiNotifyData(obj)->mnd_GlobalInfo &&
360 muiNotifyData(obj)->mnd_GlobalInfo->mgi_ApplicationObject)
362 DoMethod(_app(obj), MUIM_Application_UpdateMenus);
366 return DoSuperMethodA(cl, obj, (Msg) msg);
369 /**************************************************************************
370 OM_GET
371 **************************************************************************/
372 #define STORE *(msg->opg_Storage)
373 IPTR Menuitem__OM_GET(struct IClass *cl, Object *obj, struct opGet *msg)
375 struct MUI_MenuitemData *data = INST_DATA(cl, obj);
377 switch (msg->opg_AttrID)
379 case MUIA_Menuitem_Checked:
380 STORE = ((data->flags & MENUF_CHECKED) != 0);
381 return 1;
383 case MUIA_Menuitem_Checkit:
384 STORE = ((data->flags & MENUF_CHECKIT) != 0);
385 return 1;
387 case MUIA_Menuitem_CommandString:
388 STORE = ((data->flags & MENUF_COMMANDSTRING) != 0);
389 return 1;
391 case MUIA_Menu_Enabled:
392 case MUIA_Menuitem_Enabled:
393 STORE = ((data->flags & MENUF_ENABLED) != 0);
394 return 1;
396 case MUIA_Menuitem_Toggle:
397 STORE = ((data->flags & MENUF_TOGGLE) != 0);
398 return 1;
400 case MUIA_Menuitem_Exclude:
401 STORE = data->exclude;
402 return 1;
404 case MUIA_Menuitem_Shortcut:
405 STORE = (IPTR) data->shortcut;
406 return 1;
408 case MUIA_Menu_Title:
409 case MUIA_Menuitem_Title:
410 STORE = (IPTR) data->title;
411 return 1;
413 case MUIA_Menuitem_NewMenu:
414 Menuitem_BuildNewMenu(data, obj);
415 STORE = (IPTR) data->newmenu;
416 return 1;
418 case MUIA_Menuitem_Trigger:
419 STORE = (IPTR) data->trigger;
420 return 1;
422 case MUIA_Menuitem_Type:
423 if (data->flags & MENUF_MENUSTRIP)
424 STORE = (IPTR) MUIV_Menuitem_Type_Menustrip;
425 else if(data->flags & MENUF_MENU)
426 STORE = (IPTR) MUIV_Menuitem_Type_Menu;
427 else
428 STORE = (IPTR) MUIV_Menuitem_Type_Menuitem;
429 return 1;
433 return DoSuperMethodA(cl, obj, (Msg) msg);
435 #undef STORE
438 /**************************************************************************
439 OM_DISPOSE
440 **************************************************************************/
441 IPTR Menuitem__OM_DISPOSE(struct IClass *cl, Object *obj, Msg msg)
443 struct MUI_MenuitemData *data = INST_DATA(cl, obj);
445 FreeVec(data->newmenu);
447 return DoSuperMethodA(cl, obj, msg);
451 /**************************************************************************
452 MUIM_ConnectParent
453 **************************************************************************/
454 IPTR Menuitem__MUIM_ConnectParent(struct IClass *cl, Object *obj,
455 struct MUIP_ConnectParent *msg)
457 Object *cstate;
458 Object *child;
459 struct MinList *ChildList = NULL;
461 D(bug("Menuitem_ConnectParent(%p) %s\n", obj, OCLASS(obj)->cl_ID));
463 DoSuperMethodA(cl, obj, (Msg) msg);
465 muiNotifyData(obj)->mnd_ParentObject = msg->parent;
467 get(obj, MUIA_Family_List, &ChildList);
468 cstate = (Object *) ChildList->mlh_Head;
469 while ((child = NextObject(&cstate)))
471 DoMethod(child, MUIM_ConnectParent, (IPTR) obj);
473 return TRUE;
476 /**************************************************************************
477 MUIM_DisconnectParent
478 **************************************************************************/
479 IPTR Menuitem__MUIM_DisconnectParent(struct IClass *cl, Object *obj,
480 struct MUIP_ConnectParent *msg)
482 Object *cstate;
483 Object *child;
484 struct MinList *ChildList = NULL;
486 D(bug("Menuitem_DisconnectParent(%p) %s\n", obj, OCLASS(obj)->cl_ID));
488 get(obj, MUIA_Family_List, &ChildList);
489 cstate = (Object *) ChildList->mlh_Head;
490 while ((child = NextObject(&cstate)))
492 DoMethodA(child, (Msg) msg);
494 muiNotifyData(obj)->mnd_ParentObject = NULL;
495 DoSuperMethodA(cl, obj, (Msg) msg);
496 return TRUE;
499 /**************************************************************************
500 MUIM_Family_Insert, MUIM_Family_Remove
501 **************************************************************************/
502 IPTR Menuitem__MUIM_Update(struct IClass *cl, Object *obj, Msg msg)
504 // struct MUI_MenuitemData *data = INST_DATA(cl, obj);
506 IPTR retval = DoSuperMethodA(cl, obj, msg);
508 if (muiNotifyData(obj) &&
509 muiNotifyData(obj)->mnd_GlobalInfo &&
510 muiNotifyData(obj)->mnd_GlobalInfo->mgi_ApplicationObject)
512 DoMethod(_app(obj), MUIM_Application_UpdateMenus);
515 return retval;
518 IPTR Common_Dispatcher(Class *cl, Object *obj, Msg msg)
520 switch (msg->MethodID)
522 case OM_DISPOSE:
523 return Menuitem__OM_DISPOSE(cl, obj, msg);
524 case OM_SET:
525 return Menuitem__OM_SET(cl, obj, (struct opSet *)msg);
526 case OM_GET:
527 return Menuitem__OM_GET(cl, obj, (struct opGet *)msg);
528 case MUIM_ConnectParent:
529 return Menuitem__MUIM_ConnectParent(cl, obj, (APTR) msg);
530 case MUIM_DisconnectParent:
531 return Menuitem__MUIM_DisconnectParent(cl, obj, (APTR) msg);
532 case MUIM_Family_Insert:
533 return Menuitem__MUIM_Update(cl, obj, (APTR) msg);
534 case MUIM_Family_Remove:
535 return Menuitem__MUIM_Update(cl, obj, (APTR) msg);
536 case MUIM_Family_AddTail:
537 return Menuitem__MUIM_Update(cl, obj, (APTR) msg);
538 case MUIM_Family_AddHead:
539 return Menuitem__MUIM_Update(cl, obj, (APTR) msg);
540 case OM_ADDMEMBER:
541 return Menuitem__MUIM_Update(cl, obj, (APTR) msg);
542 case OM_REMMEMBER:
543 return Menuitem__MUIM_Update(cl, obj, (APTR) msg);
545 return DoSuperMethodA(cl, obj, msg);
548 BOOPSI_DISPATCHER(IPTR, Menuitem_Dispatcher, cl, obj, msg)
550 switch (msg->MethodID)
552 case OM_NEW:
553 return Menuitem__OM_NEW(cl, obj, (struct opSet *)msg);
556 return Common_Dispatcher(cl, obj, msg);
558 BOOPSI_DISPATCHER_END
560 BOOPSI_DISPATCHER(IPTR, Menu_Dispatcher, cl, obj, msg)
562 switch (msg->MethodID)
564 case OM_NEW:
565 return Menu__OM_NEW(cl, obj, (struct opSet *)msg);
568 return Common_Dispatcher(cl, obj, msg);
570 BOOPSI_DISPATCHER_END
572 BOOPSI_DISPATCHER(IPTR, Menustrip_Dispatcher, cl, obj, msg)
574 switch (msg->MethodID)
576 case OM_NEW:
577 return Menustrip__OM_NEW(cl, obj, (struct opSet *)msg);
580 return Common_Dispatcher(cl, obj, msg);
582 BOOPSI_DISPATCHER_END
584 * Class descriptor.
586 const struct __MUIBuiltinClass _MUI_Menuitem_desc =
588 MUIC_Menuitem,
589 MUIC_Family,
590 sizeof(struct MUI_MenuitemData),
591 (void *) Menuitem_Dispatcher
595 * Class descriptor.- this class is the same like menuitem
597 const struct __MUIBuiltinClass _MUI_Menu_desc =
599 MUIC_Menu,
600 MUIC_Family,
601 sizeof(struct MUI_MenuitemData),
602 (void *) Menu_Dispatcher
606 * Class descriptor.- this class is the same like menuitem
608 const struct __MUIBuiltinClass _MUI_Menustrip_desc =
610 MUIC_Menustrip,
611 MUIC_Family,
612 sizeof(struct MUI_MenuitemData),
613 (void *) Menustrip_Dispatcher