Fixed binary search: no more infinite loops when vendor is unknown.
[tangerine.git] / workbench / libs / muimaster / classes / boopsi.c
blob1f31b7e4ade2f25b806c49f0ed61d83865cfa774
1 /*
2 Copyright © 2002-2003, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #define MUIMASTER_YES_INLINE_STDARG
8 #include <exec/memory.h>
9 #include <intuition/icclass.h>
10 #include <intuition/gadgetclass.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 #include "debug.h"
18 #include "mui.h"
19 #include "support_classes.h"
20 #include "muimaster_intern.h"
21 #include "boopsi_private.h"
23 extern struct Library *MUIMasterBase;
25 IPTR Boopsi__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
27 struct Boopsi_DATA *data;
28 struct TagItem *tags,*tag;
30 obj = (Object *)DoSuperNewTags(cl, obj, NULL,
31 MUIA_FillArea, FALSE,
32 TAG_MORE, (IPTR) msg->ops_AttrList);
33 if (!obj)
34 return FALSE;
36 data = INST_DATA(cl, obj);
38 data->boopsi_taglist = CloneTagItems(msg->ops_AttrList);
39 data->boopsi_maxwidth = data->boopsi_maxheight = MUI_MAXMAX;
41 /* parse initial taglist */
42 for (tags = msg->ops_AttrList; (tag = NextTagItem((const struct TagItem**)&tags)); )
44 switch (tag->ti_Tag)
46 case MUIA_Boopsi_Class:
47 data->boopsi_class = (struct IClass*)tag->ti_Data;
48 break;
50 case MUIA_Boopsi_ClassID:
51 data->boopsi_classid = (char*)tag->ti_Data;
52 break;
54 case MUIA_Boopsi_MaxHeight:
55 data->boopsi_minwidth = tag->ti_Data;
56 break;
58 case MUIA_Boopsi_MaxWidth:
59 data->boopsi_maxwidth = tag->ti_Data;
60 break;
62 case MUIA_Boopsi_MinHeight:
63 data->boopsi_minheight = tag->ti_Data;
64 break;
66 case MUIA_Boopsi_MinWidth:
67 data->boopsi_minwidth = tag->ti_Data;
68 break;
70 case MUIA_Boopsi_Remember:
72 struct TagItem *new_remember;
73 if ((new_remember = AllocVec(sizeof(struct TagItem)*(data->remember_len + 2),MEMF_CLEAR))) /* +2 because of the TAG_DONE */
75 if (data->remember) CopyMem(data->remember, new_remember, sizeof(struct TagItem)*data->remember_len);
76 new_remember[data->remember_len].ti_Tag = tag->ti_Data;
77 if (data->remember) FreeVec(data->remember);
78 data->remember = new_remember;
79 data->remember_len++;
82 break;
84 case MUIA_Boopsi_Smart:
85 data->boopsi_smart = tag->ti_Data;
86 break;
88 case MUIA_Boopsi_TagDrawInfo:
89 data->boopsi_tagdrawinfo = tag->ti_Data;
90 break;
92 case MUIA_Boopsi_TagScreen:
93 data->boopsi_tagscreen = tag->ti_Data;
94 break;
96 case MUIA_Boopsi_TagWindow:
97 data->boopsi_tagwindow = tag->ti_Data;
98 break;
103 /* Now fill in the initial remember tag datas in our remember tag list */
104 for (tags = data->remember; (tag = NextTagItem((const struct TagItem**)&tags)); )
106 struct TagItem *set_tag = FindTagItem(tag->ti_Tag,msg->ops_AttrList);
107 if (set_tag) tag->ti_Data = set_tag->ti_Data;
110 data->ehn.ehn_Events = IDCMP_IDCMPUPDATE;
111 data->ehn.ehn_Priority = 0;
112 data->ehn.ehn_Flags = 0;
113 data->ehn.ehn_Object = obj;
114 data->ehn.ehn_Class = cl;
116 return (IPTR)obj;
119 IPTR Boopsi__OM_DISPOSE(struct IClass *cl, Object *obj, Msg msg)
121 struct Boopsi_DATA *data = INST_DATA(cl, obj);
123 if (data->boopsi_taglist) FreeTagItems(data->boopsi_taglist);
124 if (data->remember) FreeVec(data->remember);
125 return DoSuperMethodA(cl,obj,msg);
128 IPTR Boopsi__OM_SET(struct IClass *cl, Object *obj, struct opSet *msg)
130 struct TagItem *tags,*tag;
131 struct Boopsi_DATA *data = INST_DATA(cl, obj);
132 int only_trigger = 0;
133 int no_notify = 0;
135 for (tags = msg->ops_AttrList; (tag = NextTagItem((const struct TagItem**)&tags)); )
137 switch (tag->ti_Tag)
139 case MUIA_Boopsi_Class:
140 data->boopsi_class = (struct IClass*)tag->ti_Data;
141 break;
143 case MUIA_Boopsi_ClassID:
144 data->boopsi_classid = (char*)tag->ti_Data;
145 break;
147 case MUIA_Boopsi_MaxHeight:
148 data->boopsi_minwidth = tag->ti_Data;
149 break;
151 case MUIA_Boopsi_MaxWidth:
152 data->boopsi_maxwidth = tag->ti_Data;
153 break;
155 case MUIA_Boopsi_MinHeight:
156 data->boopsi_minheight = tag->ti_Data;
157 break;
159 case MUIA_Boopsi_MinWidth:
160 data->boopsi_minwidth = tag->ti_Data;
161 break;
163 case MUIA_Boopsi_TagDrawInfo:
164 data->boopsi_tagdrawinfo = tag->ti_Data;
165 break;
167 case MUIA_Boopsi_TagScreen:
168 data->boopsi_tagscreen = tag->ti_Data;
169 break;
171 case MUIA_Boopsi_TagWindow:
172 data->boopsi_tagwindow = tag->ti_Data;
173 break;
175 case MUIA_Boopsi_OnlyTrigger:
176 only_trigger = 1;
177 break;
179 case MUIA_NoNotify:
180 no_notify = tag->ti_Data;
181 break;
185 /* Now fill in remember list tag datas in our remember tag list */
186 for (tags = data->remember; (tag = NextTagItem((const struct TagItem**)&tags)); )
188 struct TagItem *set_tag = FindTagItem(tag->ti_Tag,msg->ops_AttrList);
189 if (set_tag) tag->ti_Data = set_tag->ti_Data;
192 if (!only_trigger)
194 if (data->boopsi_object)
196 /* Rendering will happen here!! This could make problems with virtual groups, forward this to MUIM_Draw??? */
197 if (no_notify) SetAttrs(data->boopsi_object, ICA_TARGET, NULL, TAG_DONE);
198 if (SetGadgetAttrsA((struct Gadget*)data->boopsi_object,_window(obj),NULL,msg->ops_AttrList))
199 RefreshGList((struct Gadget*)data->boopsi_object, _window(obj), NULL, 1);
200 if (no_notify) SetAttrs(data->boopsi_object, ICA_TARGET, ICTARGET_IDCMP, TAG_DONE);
204 return DoSuperMethodA(cl,obj,(Msg)msg);
208 #define STORE *(msg->opg_Storage)
209 IPTR Boopsi__OM_GET(struct IClass *cl, Object *obj, struct opGet *msg)
211 struct Boopsi_DATA *data = INST_DATA(cl, obj);
213 switch (msg->opg_AttrID)
215 case MUIA_Boopsi_Object: STORE = (LONG)data->boopsi_object;
217 default:
219 struct TagItem *tags,*tag;
221 /* look in the rember list first */
222 for (tags = data->remember; (tag = NextTagItem((const struct TagItem**)&tags)); )
224 if (tag->ti_Tag == msg->opg_AttrID)
226 if (data->boopsi_object)
227 { /* Call the get method of the boopsi object and update the remember list */
228 IPTR val;
230 if (GetAttr(msg->opg_AttrID,data->boopsi_object,&val))
231 tag->ti_Data = val;
234 STORE = tag->ti_Data;
235 return 1;
239 /* The id is not in the attr list, so we try the boopsi object first (fills in the msg then) */
240 if (data->boopsi_object)
242 IPTR val;
244 if (GetAttr(msg->opg_AttrID,data->boopsi_object,&val))
246 STORE=val;
247 return 1;
251 /* No success so we try the superclass */
252 return DoSuperMethodA(cl,obj,(Msg)msg);
256 return 1;
258 #undef STORE
260 IPTR Boopsi__MUIM_AskMinMax(struct IClass *cl, Object *obj, struct MUIP_AskMinMax *msg)
262 struct Boopsi_DATA *data = INST_DATA(cl, obj);
265 ** let our superclass first fill in what it thinks about sizes.
266 ** this will e.g. add the size of frame and inner spacing.
268 DoSuperMethodA(cl, obj, (Msg)msg);
270 msg->MinMaxInfo->MinWidth += data->boopsi_minwidth;
271 msg->MinMaxInfo->MinHeight += data->boopsi_minheight;
272 msg->MinMaxInfo->DefWidth += data->boopsi_minwidth;
273 msg->MinMaxInfo->DefHeight += data->boopsi_minheight;
274 msg->MinMaxInfo->MaxWidth += data->boopsi_maxwidth;
275 msg->MinMaxInfo->MaxHeight += data->boopsi_maxheight;
276 return TRUE;
279 IPTR Boopsi__MUIM_Setup(struct IClass *cl, Object *obj, struct MUIP_Setup *msg)
281 struct Boopsi_DATA *data = INST_DATA(cl, obj);
282 IPTR rc = DoSuperMethodA(cl, obj, (Msg)msg);
283 if (!rc) return 0;
285 DoMethod(_win(obj),MUIM_Window_AddEventHandler,(IPTR)&data->ehn);
287 return 1;
290 IPTR Boopsi__MUIM_Cleanup(struct IClass *cl, Object *obj, struct MUIP_Cleanup *msg)
292 struct Boopsi_DATA *data = INST_DATA(cl, obj);
293 DoMethod(_win(obj),MUIM_Window_RemEventHandler,(IPTR)&data->ehn);
294 return DoSuperMethodA(cl, obj, (Msg)msg);
297 IPTR Boopsi__MUIM_Show(struct IClass *cl, Object *obj, struct MUIP_Show *msg)
299 struct Boopsi_DATA *data = INST_DATA(cl, obj);
300 IPTR rc = DoSuperMethodA(cl, obj, (Msg)msg);
301 struct TagItem *tag;
302 BOOL completely_visible = TRUE;
304 D(bug("boopsi_show: obj coord %d,%d - %d,%d\n",
305 _mleft(obj), _mtop(obj), _mright(obj), _mbottom(obj)));
307 if (_flags(obj) & MADF_INVIRTUALGROUP)
309 Object *wnd, *parent;
311 get(obj, MUIA_WindowObject,&wnd);
312 parent = obj;
313 while (get(parent,MUIA_Parent,&parent))
315 if (!parent) break;
316 if (parent == wnd) break;
318 if (_flags(parent) & MADF_ISVIRTUALGROUP)
320 if ((_mleft(obj) < _mleft(parent)) ||
321 (_mright(obj) > _mright(parent)) ||
322 (_mtop(obj) < _mtop(parent)) ||
323 (_mbottom(obj) > _mbottom(parent)))
325 completely_visible = FALSE;
326 D(bug("=== boopsi object: completely visible FALSE for obj %x at %d,%d - %d,%d\n",
327 obj, _mleft(obj), _mtop(obj), _mright(obj), _mbottom(obj)));
328 break;
334 if (completely_visible)
336 if ((tag = FindTagItem(GA_Left,data->boopsi_taglist))) tag->ti_Data = _mleft(obj);
337 if ((tag = FindTagItem(GA_Top,data->boopsi_taglist))) tag->ti_Data = _mtop(obj);
338 if ((tag = FindTagItem(GA_Width,data->boopsi_taglist))) tag->ti_Data = _mwidth(obj);
339 if ((tag = FindTagItem(GA_Height,data->boopsi_taglist))) tag->ti_Data = _mheight(obj);
340 if (data->boopsi_tagscreen && (tag = FindTagItem(data->boopsi_tagscreen,data->boopsi_taglist))) tag->ti_Data = (IPTR)_screen(obj);
341 if (data->boopsi_tagwindow && (tag = FindTagItem(data->boopsi_tagwindow,data->boopsi_taglist))) tag->ti_Data = (IPTR)_window(obj);
342 if (data->boopsi_tagdrawinfo && (tag = FindTagItem(data->boopsi_tagdrawinfo,data->boopsi_taglist))) tag->ti_Data = (IPTR)_dri(obj);
344 if ((data->boopsi_object = NewObjectA(data->boopsi_class, data->boopsi_classid, data->boopsi_taglist)))
346 SetAttrsA(data->boopsi_object,data->remember);
347 AddGadget(_window(obj),(struct Gadget*)data->boopsi_object,~0);
351 return rc;
354 IPTR Boopsi__MUIM_Draw(struct IClass *cl, Object *obj, struct MUIP_Draw *msg)
356 struct Boopsi_DATA *data = INST_DATA(cl, obj);
357 DoSuperMethodA(cl, obj, (Msg)msg);
359 if (!(msg->flags & (MADF_DRAWOBJECT | MADF_DRAWUPDATE))) return 1;
360 if (data->boopsi_object) RefreshGList((struct Gadget*)data->boopsi_object, _window(obj), NULL, 1);
361 return 1;
364 IPTR Boopsi__MUIM_Hide(struct IClass *cl, Object *obj, struct MUIP_Hide *msg)
366 struct Boopsi_DATA *data = INST_DATA(cl, obj);
367 if (data->boopsi_object)
369 struct TagItem *tags,*tag;
371 /* Now fill in the initial remember tag datas in our remember tag list */
372 for (tags = data->remember; (tag = NextTagItem((const struct TagItem**)&tags)); )
374 GetAttr(tag->ti_Tag, data->boopsi_object, &tag->ti_Data);
377 RemoveGadget(_window(obj),(struct Gadget*)data->boopsi_object);
378 DisposeObject(data->boopsi_object);
379 data->boopsi_object = NULL;
382 return DoSuperMethodA(cl, obj, (Msg)msg);
385 IPTR Boopsi__MUIM_HandleEvent(struct IClass *cl, Object *obj, struct MUIP_HandleEvent *msg)
387 //struct Boopsi_DATA *data = INST_DATA(cl, obj);
389 if (msg->imsg)
391 if (msg->imsg->Class == IDCMP_IDCMPUPDATE)
393 // struct TagItem *tags,*tag;
395 /* Go through the tag list (iaddress) and set all the tags, this is somewhat stupid,
396 ** because all objects which hear on the same notifies will receive the notify
397 ** although their value has not changed really, but this how MUI seems to mange it
398 ** (this could real make big problems if using MUIV_TriggerValue)
399 ** a better idea, is to distinguish this via a allocatable gadgetid, and the
400 ** object checks wheather the gadget id equals to its allocated
403 SetAttrs(obj,MUIA_Boopsi_OnlyTrigger,TRUE,TAG_MORE,(IPTR)msg->imsg->IAddress);
405 // for (tags = (struct TagItem*)msg->imsg->IAddress; (tag = NextTagItem(&tags)); )
406 // {
407 // }
411 return 0;
414 #if ZUNE_BUILTIN_BOOPSI
415 BOOPSI_DISPATCHER(IPTR, Boopsi_Dispatcher, cl, obj, msg)
417 switch (msg->MethodID)
419 case OM_NEW: return Boopsi__OM_NEW(cl, obj, (struct opSet *) msg);
420 case OM_DISPOSE: return Boopsi__OM_DISPOSE(cl, obj, msg);
421 case OM_GET: return Boopsi__OM_GET(cl, obj, (struct opGet *)msg);
422 case OM_SET: return Boopsi__OM_SET(cl, obj, (struct opSet *)msg);
423 case MUIM_Setup: return Boopsi__MUIM_Setup(cl, obj, (APTR)msg);
424 case MUIM_Cleanup: return Boopsi__MUIM_Cleanup(cl, obj, (APTR)msg);
425 case MUIM_Show: return Boopsi__MUIM_Show(cl, obj, (APTR)msg);
426 case MUIM_Hide: return Boopsi__MUIM_Hide(cl, obj, (APTR)msg);
427 case MUIM_AskMinMax: return Boopsi__MUIM_AskMinMax(cl, obj, (APTR)msg);
428 case MUIM_Draw: return Boopsi__MUIM_Draw(cl, obj, (APTR)msg);
429 case MUIM_HandleEvent: return Boopsi__MUIM_HandleEvent(cl, obj, (APTR)msg);
432 struct Boopsi_DATA *data = INST_DATA(cl, obj);
433 if (((msg->MethodID >> 16) != ((TAG_USER >> 16) | 0x0042)) && data->boopsi_object)
435 return DoMethodA(data->boopsi_object, msg);
437 return DoSuperMethodA(cl, obj, msg);
440 BOOPSI_DISPATCHER_END
442 const struct __MUIBuiltinClass _MUI_Boopsi_desc = {
443 MUIC_Boopsi,
444 MUIC_Area,
445 sizeof(struct Boopsi_DATA),
446 (void*)Boopsi_Dispatcher
448 #endif /* ZUNE_BUILTIN_BOOPSI */