Fixed binary search: no more infinite loops when vendor is unknown.
[tangerine.git] / workbench / libs / muimaster / classes / application.c
blob7e396c6ca521f7a98b5148ef59b0cf041f3d34e8
1 /*
2 Copyright 1999, David Le Corfec.
3 Copyright 2002-2006, The AROS Development Team.
4 All rights reserved.
6 $Id$
7 */
9 #include <exec/types.h>
10 #include <devices/timer.h>
11 #include <dos/dostags.h>
12 #include <dos/datetime.h>
13 #include <utility/date.h>
14 #include <prefs/prefhdr.h>
16 #include <ctype.h>
17 #include <stdio.h>
18 #include <stdlib.h>
20 #include <clib/alib_protos.h>
21 #include <libraries/commodities.h>
22 #include <proto/exec.h>
23 #include <proto/dos.h>
24 #include <proto/intuition.h>
25 #include <proto/utility.h>
26 #include <proto/commodities.h>
27 #include <proto/muimaster.h>
28 #include <proto/iffparse.h>
30 //#define MYDEBUG 1 */
31 #include "debug.h"
32 #include "prefs.h"
34 #include "muimaster_intern.h"
35 #include "mui.h"
36 #include "support.h"
38 #include <string.h>
40 extern struct Library *MUIMasterBase;
43 struct TrackingNode
45 struct MinNode tn_Node;
46 Object *tn_Application;
49 struct MUI_ApplicationData
51 struct MUI_GlobalInfo app_GlobalInfo;
52 APTR app_WindowFamily; /* delegates window list */
53 struct MinList app_IHList;
54 struct MinList app_MethodQueue;
55 struct SignalSemaphore app_MethodSemaphore;
56 struct MinList app_ReturnIDQueue;
57 struct Hook *app_BrokerHook;
58 struct MsgPort *app_BrokerPort;
59 struct MsgPort *app_TimerPort;
60 struct timerequest *app_TimerReq;
61 struct Task *app_Task;
62 CxObj *app_Broker;
63 Object *app_Menustrip;
64 Object *app_AboutWin;
65 APTR app_RIDMemChunk;
66 STRPTR app_Author;
67 STRPTR app_Base;
68 STRPTR app_Copyright;
69 STRPTR app_Description;
70 STRPTR app_HelpFile;
71 STRPTR app_Title;
72 STRPTR app_Version;
73 BOOL app_VersionAllocated;
74 STRPTR app_Version_Number;
75 STRPTR app_Version_Date;
76 STRPTR app_Version_Extra;
77 ULONG app_SleepCount;
78 ULONG app_TimerOutstanding;
79 ULONG app_MenuAction; /* Remember last action */
80 BOOL app_ForceQuit;
81 BOOL app_Iconified;
82 BOOL app_SingleTask;
83 BOOL app_Active;
84 BYTE app_BrokerPri;
85 struct TrackingNode app_TrackingNode;
86 BOOL app_is_TNode_in_list;
87 ULONG searchwinid;
88 LONG winposused; //dont add other vars before windowpos all is save together
89 struct windowpos winpos[MAXWINS];
90 struct MsgPort *app_RexxPort;
94 struct timerequest_ext
96 struct timerequest treq;
97 struct MUI_InputHandlerNode *ihn;
101 * Application class is the master class for all
102 * MUI applications. It serves as a kind of anchor
103 * for all input, either coming from the user or
104 * somewhere from the system, e.g. commodities
105 * or ARexx messages. (hemm forget theses last 2 for Zune :)
107 * An application can have any number of sub windows,
108 * these windows are the children of the application.
109 * (FYI, it delegates child handling to a Family object).
113 MUIA_Application_Active [ISG] done
114 MUIA_Application_Author [I.G] done
115 MUIA_Application_Base [I.G] done
116 MUIA_Application_Broker [..G] done
117 MUIA_Application_BrokerHook [ISG] done
118 MUIA_Application_BrokerPort [..G] done
119 MUIA_Application_BrokerPri [I.G] done
120 MUIA_Application_Commands [ISG] needs Arexx
121 MUIA_Application_Copyright [I.G] done
122 MUIA_Application_Description [I.G] done
123 MUIA_Application_DiskObject [ISG] needs struct DiskObject
124 MUIA_Application_DoubleStart [..G] not triggered yet (todo)
125 MUIA_Application_DropObject [IS.] needs AppMessage
126 MUIA_Application_ForceQuit [..G] not triggered yet
127 MUIA_Application_HelpFile [ISG] unused/dummy
128 MUIA_Application_Iconified [.SG] complete (handle appicons)
129 MUIA_Application_Menu [I.G] unimplemented (OBSOLETE)
130 MUIA_Application_MenuAction [..G] done
131 MUIA_Application_MenuHelp [..G] todo (ditto)
132 MUIA_Application_Menustrip [I..] done
133 MUIA_Application_RexxHook [ISG] needs Arexx
134 MUIA_Application_RexxMsg [..G] needs Arexx
135 MUIA_Application_RexxString [.S.] needs Arexx
136 MUIA_Application_SingleTask [I..] done
137 MUIA_Application_Sleep [.S.] todo
138 MUIA_Application_Title [I.G] done
139 MUIA_Application_UseCommodities [I..] done
140 MUIA_Application_UseRexx [I..] done ? needs Arexx
141 MUIA_Application_Version [I.G] done
142 MUIA_Application_Window [I..] done
143 MUIA_Application_WindowList [..G] done
145 OM_ADDMEMBER done
146 OM_REMMEMBER done
147 MUIM_Application_AboutMUI todo
148 MUIM_Application_AddInputHandler done ?
149 MUIM_Application_CheckRefresh todo (implementable ?)
150 MUIM_Application_GetMenuCheck OBSOLETE
151 MUIM_Application_GetMenuState OBSOLETE
152 MUIM_Application_Input OBSOLETE
153 MUIM_Application_InputBuffered todo
154 MUIM_Application_Load
155 MUIM_Application_NewInput todo
156 MUIM_Application_OpenConfigWindow
157 MUIM_Application_PushMethod
158 MUIM_Application_RemInputHandler done ?
159 MUIM_Application_ReturnID done
160 MUIM_Application_Save
161 MUIM_Application_SetConfigItem
162 MUIM_Application_SetMenuCheck
163 MUIM_Application_SetMenuState
164 MUIM_Application_ShowHelp
166 Notify.mui/MUIM_FindUData done
167 Notify.mui/MUIM_GetUData done
168 Notify.mui/MUIM_SetUData done
169 Notify.mui/MUIM_SetUDataOnce done
172 static const int __version = 1;
173 static const int __revision = 1;
177 * MethodQueueNode
179 struct MQNode {
180 struct MinNode mq_Node;
181 Object *mq_Dest;
182 LONG mq_Count;
183 IPTR *mq_Msg;
187 * FilePrefHeader
189 struct FilePrefHeader
191 UBYTE ph_Version;
192 UBYTE ph_Type;
193 UBYTE ph_Flags[4];
196 #define ID_MUIO MAKE_ID('M','U','I','O')
199 * Allocates an MethodQueue Method
201 static struct MQNode *CreateMQNode(LONG count)
203 struct MQNode *mq;
205 mq = (struct MQNode *)mui_alloc(sizeof(struct MQNode) + (count * sizeof(IPTR)));
206 if (!mq)
207 return NULL;
209 mq->mq_Count = count;
210 mq->mq_Msg = (IPTR *)(((char *)mq)+sizeof(struct MQNode));
211 return mq;
215 * Free an IQ Method got from CreateIQMethod()
217 static void DeleteMQNode(struct MQNode *mq)
219 mui_free(mq);
224 * Queue of Return IDs
226 struct RIDNode {
227 struct MinNode rid_Node;
228 ULONG rid_Value;
232 static struct RIDNode *CreateRIDNode(struct MUI_ApplicationData *data, ULONG retid)
234 struct RIDNode *rid;
235 if ((rid = mui_alloc_struct(struct RIDNode)))
237 rid->rid_Value = retid;
239 return rid;
243 static void DeleteRIDNode (struct MUI_ApplicationData *data, struct RIDNode *rid)
245 mui_free(rid);
249 /**************************************************************************
250 Process a pushed method.
251 **************************************************************************/
252 static BOOL application_do_pushed_method (struct MUI_ApplicationData *data)
254 struct MQNode *mq;
256 ObtainSemaphore(&data->app_MethodSemaphore);
258 if ((mq = (struct MQNode *)RemHead((struct List *)&data->app_MethodQueue)))
260 ReleaseSemaphore(&data->app_MethodSemaphore);
262 DoMethodA(mq->mq_Dest, (Msg)mq->mq_Msg);
263 DeleteMQNode(mq);
264 return TRUE;
266 ReleaseSemaphore(&data->app_MethodSemaphore);
267 return FALSE;
270 static Object *find_application_by_base(struct IClass *cl, Object *obj, STRPTR base)
272 struct TrackingNode *tn;
273 Object *retval = NULL;
275 ObtainSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
276 ForeachNode(&MUIMB(MUIMasterBase)->Applications, tn)
278 STRPTR tn_base = "";
280 get(tn->tn_Application, MUIA_Application_Base, &tn_base);
282 if (tn_base && (strcmp(base, tn_base)) == 0)
284 retval = tn->tn_Application;
285 break;
288 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
290 return retval;
293 /**************************************************************************
294 OM_NEW
295 **************************************************************************/
296 static IPTR Application__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
298 struct MUI_ApplicationData *data;
299 struct TagItem *tags,*tag;
300 BOOL bad_childs = FALSE , needrexx = TRUE;
302 obj = (Object *)DoSuperMethodA(cl, obj, (Msg)msg);
303 if (!obj)
304 return FALSE;
306 /* Initial local instance data */
307 data = INST_DATA(cl, obj);
309 /* init input handler list */
310 NewList((struct List*)&(data->app_IHList));
312 /* init input queue */
313 NewList((struct List*)&(data->app_MethodQueue));
315 /* init return ids queue */
316 NewList((struct List*)&(data->app_ReturnIDQueue));
318 /* window list */
319 data->app_WindowFamily = MUI_NewObjectA(MUIC_Family, NULL);
320 if (!data->app_WindowFamily)
322 CoerceMethod(cl,obj,OM_DISPOSE);
323 return 0;
326 data->app_GlobalInfo.mgi_ApplicationObject = obj;
327 if (!(data->app_GlobalInfo.mgi_WindowsPort = CreateMsgPort()))
329 CoerceMethod(cl,obj,OM_DISPOSE);
330 return 0;
333 data->app_Task = FindTask(NULL);
335 /* Parse prefs */
336 data->app_SingleTask = (BOOL)GetTagData(MUIA_Application_SingleTask, FALSE,
337 msg->ops_AttrList);
338 data->app_Base = (STRPTR)GetTagData(MUIA_Application_Base, (IPTR)"UNNAMED", msg->ops_AttrList);
339 if (!data->app_Base || strpbrk(data->app_Base, " :/()#?*.,"))
341 data->app_Base = NULL; /* don't remove */
342 CoerceMethod(cl, obj, OM_DISPOSE);
344 return 0;
347 if (!data->app_SingleTask)
349 /* must append .1, .2, ... to the base name */
350 int i;
351 char portname[255];
353 for (i = 1; i < 1000; i++)
355 snprintf(portname, 255, "%s.%ld", data->app_Base, (LONG)i);
356 if (!find_application_by_base(cl, obj, portname))
357 break;
359 data->app_Base = StrDup(portname);
361 else
363 Object *other_app;
365 ObtainSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
366 if ((other_app = find_application_by_base(cl, obj, data->app_Base)))
368 //FIXME "Is calling MUIM_Application_PushMethod on an alien application object safe?"
369 DoMethod(other_app, MUIM_Application_PushMethod, (IPTR)other_app, 3,
370 MUIM_Set, MUIA_Application_DoubleStart, TRUE);
371 data->app_Base = NULL;
373 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
375 data->app_Base = StrDup(data->app_Base);
378 if (!data->app_Base)
380 CoerceMethod(cl, obj, OM_DISPOSE);
381 return 0;
384 data->app_GlobalInfo.mgi_Configdata =
385 MUI_NewObject(MUIC_Configdata, MUIA_Configdata_Application, obj, TAG_DONE);
386 if (!data->app_GlobalInfo.mgi_Configdata)
388 CoerceMethod(cl,obj,OM_DISPOSE);
389 return 0;
391 get(data->app_GlobalInfo.mgi_Configdata,MUIA_Configdata_ZunePrefs,
392 &data->app_GlobalInfo.mgi_Prefs);
394 // D(bug("muimaster.library/application.c: Message Port created at 0x%lx\n",
395 // data->app_GlobalInfo.mgi_WindowPort));
397 /* Setup timer stuff */
398 if (!(data->app_TimerPort = CreateMsgPort()))
400 CoerceMethod(cl,obj,OM_DISPOSE);
401 return 0;
404 if (!(data->app_TimerReq = (struct timerequest *)CreateIORequest(data->app_TimerPort, sizeof(struct timerequest))))
406 CoerceMethod(cl,obj,OM_DISPOSE);
407 return 0;
410 if (OpenDevice(TIMERNAME, UNIT_VBLANK, (struct IORequest *)data->app_TimerReq, 0))
412 CoerceMethod(cl,obj,OM_DISPOSE);
413 return 0;
416 InitSemaphore(&data->app_MethodSemaphore);
418 muiNotifyData(obj)->mnd_GlobalInfo = &data->app_GlobalInfo;
420 /* parse initial taglist */
422 data->app_Active = 1;
423 data->app_Title = "Unnamed";
424 data->app_Version = "Unnamed 0.0";
425 data->app_Description = "?";
427 for (tags = msg->ops_AttrList; (tag = NextTagItem((const struct TagItem **)&tags)); )
429 switch (tag->ti_Tag)
431 case MUIA_Application_Author:
432 data->app_Author = (STRPTR)tag->ti_Data;
433 break;
435 case MUIA_Application_Base:
436 /* moved before config parsing */
437 break;
439 case MUIA_Application_Copyright:
440 data->app_Copyright = (STRPTR)tag->ti_Data;
441 break;
443 case MUIA_Application_Description:
444 data->app_Description = (STRPTR)tag->ti_Data;
445 break;
447 case MUIA_Application_HelpFile:
448 data->app_HelpFile = (STRPTR)tag->ti_Data;
449 break;
451 case MUIA_Application_SingleTask:
452 /* moved before config parsing */
453 break;
455 case MUIA_Application_Title:
456 data->app_Title = (STRPTR)tag->ti_Data;
457 break;
459 case MUIA_Application_Version:
460 data->app_Version = (STRPTR)tag->ti_Data;
461 break;
463 case MUIA_Application_Version_Number:
464 data->app_Version_Number = (STRPTR)tag->ti_Data;
465 break;
467 case MUIA_Application_Version_Date:
468 data->app_Version_Date = (STRPTR)tag->ti_Data;
469 break;
471 case MUIA_Application_Version_Extra:
472 data->app_Version_Extra = (STRPTR) tag->ti_Data;
473 break;
475 case MUIA_Application_Window:
476 if (tag->ti_Data) DoMethod(obj,OM_ADDMEMBER,tag->ti_Data);
477 else bad_childs = TRUE;
478 break;
480 case MUIA_Application_Menustrip:
481 data->app_Menustrip = (Object*)tag->ti_Data;
482 break;
484 case MUIA_Application_BrokerPri:
485 data->app_BrokerPri = (BYTE)tag->ti_Data;
486 break;
488 case MUIA_Application_BrokerHook:
489 data->app_BrokerHook = (struct Hook *)tag->ti_Data;
490 break;
492 case MUIA_Application_Active:
493 data->app_Active = tag->ti_Data ? TRUE : FALSE;
494 break;
496 case MUIA_Application_UsedClasses:
498 STRPTR *list = (STRPTR *)tag->ti_Data;
499 if (!list) break;
500 while (*list)
502 struct IClass *icl = MUI_GetClass(*list);
503 if (icl)
504 MUI_FreeClass(icl);
505 ++list;
508 break;
509 case MUIA_Application_UseRexx:
510 needrexx = tag->ti_Data ? TRUE : FALSE;
511 break;
515 /* create MUIA_Application_Version if NULL */
518 data->app_Version == NULL
519 && data->app_Title != NULL && data->app_Version_Number != NULL
522 STRPTR result = NULL;
523 ULONG length = 0;
525 /* Calculate length */
526 length = strlen("$VER: ") + strlen(data->app_Title) + 1 /* space */
527 + strlen(data->app_Version_Number) + 1 /* NULL */;
529 if (data->app_Version_Date != NULL)
531 length += 1 /* space */ + 1 /* ( */
532 + strlen(data->app_Version_Date) + 1 /* ) */;
535 if (data->app_Version_Extra != NULL)
537 length += 1 /* space */ + 1 /* [ */
538 + strlen(data->app_Version_Extra) + 1 /* ] */;
541 /* Allocate memory */
542 result = AllocVec(length, MEMF_ANY);
544 if (result != NULL)
546 result[0] = '\0';
548 /* Format string */
549 strlcat(result, "$VER: ", length);
550 strlcat(result, data->app_Title, length);
551 strlcat(result, " ", length);
552 strlcat(result, data->app_Version_Number, length);
554 if (data->app_Version_Date != NULL)
556 strlcat(result, " (", length);
557 strlcat(result, data->app_Version_Date, length);
558 strlcat(result, ")", length);
561 if (data->app_Version_Extra != NULL)
563 strlcat(result, " [", length);
564 strlcat(result, data->app_Version_Extra, length);
565 strlcat(result, "]", length);
568 data->app_Version = result;
569 data->app_VersionAllocated = TRUE;
574 if (bad_childs)
576 CoerceMethod(cl, obj, OM_DISPOSE);
577 return 0;
580 if (CxBase && GetTagData(MUIA_Application_UseCommodities, TRUE, msg->ops_AttrList))
582 data->app_BrokerPort = CreateMsgPort();
584 if (data->app_BrokerPort)
586 struct NewBroker nb;
588 nb.nb_Version = NB_VERSION;
589 nb.nb_Name = data->app_Title ? data->app_Title : (STRPTR)"Unnamed";
590 nb.nb_Title = data->app_Version ? data->app_Version : (STRPTR)"Unnamed";
591 nb.nb_Descr = data->app_Description ? data->app_Description : (STRPTR)"?";
592 nb.nb_Unique = 0;
593 nb.nb_Flags = COF_SHOW_HIDE;
594 nb.nb_Pri = data->app_BrokerPri;
595 nb.nb_Port = data->app_BrokerPort;
596 nb.nb_ReservedChannel = 0;
598 if (strncmp(nb.nb_Title, "$VER: ", 6) == 0) nb.nb_Title += 6;
600 data->app_Broker = CxBroker(&nb, 0);
602 if (data->app_Broker)
604 if (data->app_Active) ActivateCxObj(data->app_Broker, 1);
609 if (needrexx)
611 data->app_RexxPort = CreateMsgPort();
612 if (data->app_RexxPort)
614 data->app_RexxPort->mp_Node.ln_Name = StrDup(data->app_Base);
615 if (data->app_RexxPort->mp_Node.ln_Name != NULL)
617 char *i;
618 for (i = data->app_RexxPort->mp_Node.ln_Name; *i != '\0'; i++)
620 *i = toupper(*i);
622 AddPort(data->app_RexxPort);
624 else
626 DeleteMsgPort(data->app_RexxPort);
627 data->app_RexxPort = NULL;
632 if (data->app_Menustrip) DoMethod(data->app_Menustrip, MUIM_ConnectParent, (IPTR)obj);
634 ObtainSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
635 data->app_TrackingNode.tn_Application = obj;
636 AddTail((struct List *)&MUIMB(MUIMasterBase)->Applications, (struct Node*)&data->app_TrackingNode);
637 data->app_is_TNode_in_list = TRUE;
638 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
640 return (IPTR)obj;
645 /**************************************************************************
646 OM_DISPOSE
647 **************************************************************************/
648 static IPTR Application__OM_DISPOSE(struct IClass *cl, Object *obj, Msg msg)
650 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
651 struct RIDNode *rid;
653 long positionmode;
654 if (data->app_Base)
656 char filename[255];
657 positionmode=data->app_GlobalInfo.mgi_Prefs->window_position;
658 if (positionmode >= 1)
660 snprintf(filename, 255, "ENV:zune/%s.prefs", data->app_Base);
661 DoMethod(data->app_GlobalInfo.mgi_Configdata, MUIM_Configdata_Save, (IPTR)filename);
663 if (positionmode == 2)
665 snprintf(filename, 255, "ENVARC:zune/%s.prefs", data->app_Base);
666 DoMethod(data->app_GlobalInfo.mgi_Configdata, MUIM_Configdata_Save, (IPTR)filename);
670 if (data->app_is_TNode_in_list)
672 ObtainSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
673 Remove((struct Node *)&data->app_TrackingNode);
674 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
677 if (data->app_WindowFamily)
679 struct MinList *children;
680 Object *cstate;
681 Object *child;
683 /* special loop because the next object may have been removed/freed by
684 * the previous. so restart from listhead each time.
686 while (1)
688 get(data->app_WindowFamily, MUIA_Family_List, &children);
689 cstate = (Object *)children->mlh_Head;
690 if ((child = NextObject(&cstate)))
692 D(bug("Application_Dispose(%p) : OM_REMMEMBER(%p)\n", obj, child));
693 DoMethod(obj, OM_REMMEMBER, (IPTR)child);
694 D(bug("Application_Dispose(%p) : MUI_DisposeObject(%p)\n", obj, child));
695 MUI_DisposeObject(child);
698 else
700 break;
703 MUI_DisposeObject(data->app_WindowFamily);
706 if (data->app_Menustrip)
707 MUI_DisposeObject(data->app_Menustrip);
709 if (data->app_VersionAllocated && data->app_Version != NULL)
711 FreeVec(data->app_Version);
714 /* free commodities stuff */
716 if (data->app_Broker)
718 DeleteCxObjAll(data->app_Broker);
721 if (data->app_BrokerPort)
723 struct Message *msg;
725 while((msg = GetMsg(data->app_BrokerPort)))
727 ReplyMsg(msg);
730 DeleteMsgPort(data->app_BrokerPort);
733 /* free timer stuff */
734 if (data->app_TimerReq)
736 if (data->app_TimerReq->tr_node.io_Device)
738 while (data->app_TimerOutstanding)
740 if (Wait(1L << data->app_TimerPort->mp_SigBit | 4096) & 4096)
741 break;
742 data->app_TimerOutstanding--;
744 CloseDevice((struct IORequest *)data->app_TimerReq);
746 DeleteIORequest((struct IORequest *)data->app_TimerReq);
748 if (data->app_TimerPort)
749 DeleteMsgPort(data->app_TimerPort);
751 if (data->app_RexxPort)
753 struct Message *msg;
754 while((msg = GetMsg(data->app_RexxPort)))
756 ReplyMsg(msg);
758 RemPort(data->app_RexxPort);
760 if (data->app_RexxPort->mp_Node.ln_Name != NULL) FreeVec(data->app_RexxPort->mp_Node.ln_Name);
762 DeleteMsgPort(data->app_RexxPort);
765 if (data->app_GlobalInfo.mgi_Configdata)
766 MUI_DisposeObject(data->app_GlobalInfo.mgi_Configdata);
768 if (data->app_GlobalInfo.mgi_WindowsPort)
769 DeleteMsgPort(data->app_GlobalInfo.mgi_WindowsPort);
771 FreeVec(data->app_Base);
773 /* free returnid stuff */
775 while ((rid = (struct RIDNode *)RemHead((struct List *)&data->app_ReturnIDQueue)))
777 DeleteRIDNode(data, rid);
780 return DoSuperMethodA(cl, obj, msg);
784 /**************************************************************************
785 OM_SET
786 **************************************************************************/
787 static IPTR Application__OM_SET(struct IClass *cl, Object *obj, struct opSet *msg)
789 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
790 struct TagItem *tags = msg->ops_AttrList;
791 struct TagItem *tag;
793 /* There are many ways to find out what tag items provided by set()
794 ** we do know. The best way should be using NextTagItem() and simply
795 ** browsing through the list.
797 while ((tag = NextTagItem((const struct TagItem **)&tags)) != NULL)
799 IPTR *addr;
800 switch (tag->ti_Tag)
803 case MUIA_Application_SearchWinId:
804 data->searchwinid = tag->ti_Data;
805 break;
807 case MUIA_Application_CopyWinPosToApp:
808 addr = (IPTR *) tag->ti_Data;
809 CopyMem((CONST_APTR) tag->ti_Data, &data->winposused, *(addr));
810 break;
812 case MUIA_Application_SetWinPos:
814 struct windowpos *winp;
815 winp = (struct windowpos *) tag->ti_Data;
816 //kprintf("SetWinPos %d %d %d %d %d\n",winp->id,winp->x1,winp->y1,winp->w1,winp->h1);
817 int i;
818 for (i = 0 ; i < MAXWINS -1 ; i++)
820 if (data->winpos[i].w1)
822 if (winp->id == data->winpos[i].id) //existing entry is overwritten
824 data->winpos[i].x1 = winp->x1;data->winpos[i].y1 = winp->y1;
825 data->winpos[i].w1 = winp->w1;data->winpos[i].h1 = winp->h1;
826 data->winpos[i].x2 = winp->x2;data->winpos[i].y2 = winp->y2;
827 data->winpos[i].w2 = winp->w2;data->winpos[i].h2 = winp->h2;
828 break;
831 else
832 { // a new entry is add
833 data->winpos[i].id = winp->id;
834 data->winpos[i].x1 = winp->x1;data->winpos[i].y1 = winp->y1;
835 data->winpos[i].w1 = winp->w1;data->winpos[i].h1 = winp->h1;
836 data->winpos[i].x2 = winp->x2;data->winpos[i].y2 = winp->y2;
837 data->winpos[i].w2 = winp->w2;data->winpos[i].h2 = winp->h2;
838 break;
842 break;
844 case MUIA_Application_Configdata:
845 DoMethod(obj, MUIM_Application_PushMethod, (IPTR)obj, 2,
846 MUIM_Application_SetConfigdata, tag->ti_Data);
847 break;
849 case MUIA_Application_HelpFile:
850 data->app_HelpFile = (STRPTR)tag->ti_Data;
851 break;
853 case MUIA_Application_Iconified:
855 BOOL do_iconify = tag->ti_Data == 1;
856 if (data->app_Iconified != do_iconify)
858 data->app_Iconified = do_iconify;
860 nnset(obj, MUIA_ShowMe, !data->app_Iconified);
861 //FIXME "In case the WB is up, an appicon needs to be placed on the desktop"
864 break;
866 case MUIA_ShowMe:
868 /* Ok ok, you think this stinks? Well, think of it as
869 an attribute belonging to an interface which MUIC_Application,
870 together with MUIC_Area and a few others implement. It makes
871 sense now, yes? */
872 struct List *wlist;
873 APTR wstate;
874 Object *curwin;
876 get(obj, MUIA_Application_WindowList, &wlist);
878 if (wlist)
880 wstate = wlist->lh_Head;
881 while ((curwin = NextObject(&wstate)))
883 set(curwin, MUIA_ShowMe, tag->ti_Data);
887 break;
889 case MUIA_Application_Sleep:
890 if (tag->ti_Data) data->app_SleepCount++;
891 else data->app_SleepCount--;
892 if (data->app_SleepCount < 0)
893 data->app_SleepCount = 0;
894 else
897 * todo SC == 0 (wakeup), SC == 1 (sleep)
900 break;
902 case MUIA_Application_MenuAction:
903 data->app_MenuAction = tag->ti_Data;
904 break;
906 case MUIA_Application_BrokerHook:
907 data->app_BrokerHook = (struct Hook *)tag->ti_Data;
908 break;
910 case MUIA_Application_Active:
911 data->app_Active = tag->ti_Data ? TRUE : FALSE;
912 if (data->app_Broker)
914 ActivateCxObj(data->app_Broker, data->app_Active);
916 break;
921 return DoSuperMethodA(cl, obj, (Msg)msg);
926 * OM_GET
928 static IPTR Application__OM_GET(struct IClass *cl, Object *obj, struct opGet *msg)
930 #define STORE *(msg->opg_Storage)
932 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
934 switch(msg->opg_AttrID)
936 case MUIA_Application_GetWinPosAddr:
937 STORE = (IPTR) &data->winposused;
938 return TRUE;
940 case MUIA_Application_GetWinPosSize:
942 int i;
943 for (i=0 ; i < MAXWINS -1 ; i++)
945 if (!data->winpos[i].w1 )
947 i *= sizeof (struct windowpos);
948 i += sizeof (long);
949 data->winposused=i;
950 STORE=i;
951 return(TRUE);
954 STORE=0;
955 return TRUE;
958 case MUIA_Application_GetWinPos:
960 int i;
961 if (data->searchwinid)
963 for (i=0 ; i < MAXWINS -1 ; i++)
965 if (data->winpos[i].w1 )
967 if (data->searchwinid == data->winpos[i].id)
969 STORE = (IPTR) &data->winpos[i].id;
970 return 1;
973 else
974 break;
977 STORE=0;
978 return 1;
980 return TRUE;
982 case MUIA_Version:
983 STORE = __version;
984 return TRUE;
986 case MUIA_Revision:
987 STORE = __revision;
988 return TRUE;
990 case MUIA_Application_Author:
991 STORE = (IPTR)data->app_Author;
992 return TRUE;
994 case MUIA_Application_Base:
995 STORE = (IPTR)data->app_Base;
996 return TRUE;
998 case MUIA_Application_Copyright:
999 STORE = (IPTR)data->app_Copyright;
1000 return TRUE;
1002 case MUIA_Application_Description:
1003 STORE = (IPTR)data->app_Description;
1004 return TRUE;
1006 case MUIA_Application_DoubleStart:
1007 return TRUE;
1009 case MUIA_Application_ForceQuit:
1010 STORE = (IPTR)data->app_ForceQuit;
1011 return TRUE;
1013 case MUIA_Application_HelpFile:
1014 STORE = (IPTR)data->app_HelpFile;
1015 return TRUE;
1017 case MUIA_Application_Iconified:
1018 STORE = (IPTR)data->app_Iconified;
1019 return TRUE;
1021 case MUIA_Application_Title:
1022 STORE = (IPTR)data->app_Title;
1023 return TRUE;
1025 case MUIA_Application_Version:
1026 STORE = (IPTR)data->app_Version;
1027 return TRUE;
1029 case MUIA_Application_Version_Number:
1030 STORE = (IPTR) data->app_Version_Number;
1031 return TRUE;
1033 case MUIA_Application_Version_Date:
1034 STORE = (IPTR) data->app_Version_Date;
1035 return TRUE;
1037 case MUIA_Application_Version_Extra:
1038 STORE = (IPTR) data->app_Version_Extra;
1039 return TRUE;
1041 case MUIA_Application_WindowList:
1042 return GetAttr(MUIA_Family_List, data->app_WindowFamily, msg->opg_Storage);
1044 case MUIA_Application_Menustrip:
1045 STORE = (IPTR)data->app_Menustrip;
1046 return TRUE;
1048 case MUIA_Application_MenuAction:
1049 STORE = (IPTR)data->app_MenuAction;
1050 return TRUE;
1052 case MUIA_Application_BrokerPort:
1053 STORE = (IPTR)data->app_BrokerPort;
1054 return TRUE;
1056 case MUIA_Application_BrokerPri:
1057 STORE = (IPTR)data->app_BrokerPri;
1058 return TRUE;
1060 case MUIA_Application_BrokerHook:
1061 STORE = (IPTR)data->app_BrokerHook;
1062 return TRUE;
1064 case MUIA_Application_Broker:
1065 STORE = (IPTR)data->app_Broker;
1066 return TRUE;
1068 case MUIA_Application_Active:
1069 STORE = data->app_Active;
1070 return TRUE;
1073 /* our handler didn't understand the attribute, we simply pass
1074 ** it to our superclass now
1076 return(DoSuperMethodA(cl, obj, (Msg) msg));
1077 #undef STORE
1081 /**************************************************************************
1082 OM_ADDMEMBER
1083 **************************************************************************/
1084 static IPTR Application__OM_ADDMEMBER(struct IClass *cl, Object *obj, struct opMember *msg)
1086 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1088 D(bug("Application_AddMember: Adding 0x%lx to window member list\n",msg->opam_Object));
1090 DoMethodA(data->app_WindowFamily, (Msg)msg);
1091 /* Application knows its GlobalInfo, so we can inform window */
1092 DoMethod(msg->opam_Object, MUIM_ConnectParent, (IPTR)obj);
1093 return TRUE;
1097 /**************************************************************************
1098 OM_REMMEMBER
1099 **************************************************************************/
1100 static IPTR Application__OM_REMMEMBER(struct IClass *cl, Object *obj, struct opMember *msg)
1102 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1104 D(bug("Application_RemMember: Removing 0x%lx from window member list\n",msg->opam_Object));
1106 DoMethod(msg->opam_Object, MUIM_DisconnectParent);
1107 DoMethodA(data->app_WindowFamily, (Msg)msg);
1108 return TRUE;
1113 /**************************************************************************
1114 MUIM_Application_AddInputHandler
1115 **************************************************************************/
1116 static IPTR Application__MUIM_AddInputHandler(struct IClass *cl, Object *obj,
1117 struct MUIP_Application_AddInputHandler *msg)
1119 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1121 if (msg->ihnode->ihn_Flags & MUIIHNF_TIMER)
1123 struct timerequest_ext *time_ext = (struct timerequest_ext *)AllocVec(sizeof(struct timerequest_ext),MEMF_PUBLIC);
1124 if (time_ext)
1126 /* Store the request inside the input handler, so the we can remove
1127 ** the inputhandler without problems */
1128 msg->ihnode->ihn_Node.mln_Pred = (struct MinNode*)time_ext;
1130 time_ext->treq = *data->app_TimerReq;
1131 time_ext->treq.tr_node.io_Command = TR_ADDREQUEST;
1132 time_ext->treq.tr_time.tv_secs = msg->ihnode->ihn_Millis/1000;
1133 time_ext->treq.tr_time.tv_micro = (msg->ihnode->ihn_Millis%1000)*1000;
1134 time_ext->ihn = msg->ihnode;
1135 SendIO((struct IORequest*)time_ext);
1137 } else AddTail((struct List *)&data->app_IHList, (struct Node *)msg->ihnode);
1138 return TRUE;
1142 /**************************************************************************
1143 MUIM_Application_RemInputHandler
1144 **************************************************************************/
1145 static IPTR Application__MUIM_RemInputHandler(struct IClass *cl, Object *obj, struct MUIP_Application_RemInputHandler *msg)
1147 //struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1148 if (msg->ihnode->ihn_Flags & MUIIHNF_TIMER)
1150 struct timerequest_ext *time_ext = (struct timerequest_ext*)msg->ihnode->ihn_Node.mln_Pred;
1151 if (!CheckIO((struct IORequest*)time_ext)) AbortIO((struct IORequest*)time_ext);
1152 WaitIO((struct IORequest*)time_ext);
1153 FreeVec(time_ext);
1154 } else Remove((struct Node *)msg->ihnode);
1156 return TRUE;
1160 void _zune_window_message(struct IntuiMessage *imsg); /* from window.c */
1163 * MUIM_Application_InputBuffered : process all pending events
1165 static IPTR Application__MUIM_InputBuffered(struct IClass *cl, Object *obj,
1166 struct MUIP_Application_InputBuffered *msg)
1168 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1169 struct IntuiMessage *imsg;
1171 /* process all pushed methods */
1172 while (application_do_pushed_method(data))
1175 imsg = (struct IntuiMessage *)GetMsg(data->app_GlobalInfo.mgi_WindowsPort);
1176 if (imsg != NULL)
1178 /* Let window object process message */
1179 _zune_window_message(imsg); /* will reply the message */
1181 return TRUE;
1184 /**************************************************************************
1185 MUIM_Application_NewInput : application main loop
1186 **************************************************************************/
1187 static IPTR Application__MUIM_NewInput(struct IClass *cl, Object *obj, struct MUIP_Application_NewInput *msg)
1189 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1190 struct RIDNode *rid;
1191 ULONG retval = 0;
1192 ULONG signal, signalmask;
1193 ULONG handler_mask = 0; /* the mask of the signal handlers */
1194 struct MinNode *mn;
1196 //struct MinNode ihn_Node;
1198 signal = *msg->signal;
1200 /* process all pushed methods */
1201 while (application_do_pushed_method(data))
1202 /* nothing */ ;
1204 /* query the signal for the handlers */
1205 for (mn = data->app_IHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
1207 struct MUI_InputHandlerNode *ihn;
1208 ihn = (struct MUI_InputHandlerNode *)mn;
1209 handler_mask |= ihn->ihn_Signals;
1212 signalmask = (1L << data->app_GlobalInfo.mgi_WindowsPort->mp_SigBit)
1213 | (1L << data->app_TimerPort->mp_SigBit) | handler_mask;
1215 if (data->app_Broker)
1216 signalmask |= (1L << data->app_BrokerPort->mp_SigBit);
1218 if (signal == 0)
1220 /* Stupid app which (always) passes 0 in signals. It's impossible to
1221 know which signals were really set as the app will already have
1222 called Wait() which has cleared the task's tc_SigRecvd. So assume
1223 the window, timer, and broker signals all to be set. Also all of
1224 the inputhandler signals (MUI does that too). */
1226 signal = signalmask;
1229 if (signal & signalmask)
1231 if (signal & (1L << data->app_GlobalInfo.mgi_WindowsPort->mp_SigBit))
1233 struct IntuiMessage *imsg;
1234 /* process all pushed methods */
1236 while ((imsg = (struct IntuiMessage *)GetMsg(data->app_GlobalInfo.mgi_WindowsPort)))
1238 /* Let window object process message */
1239 _zune_window_message(imsg); /* will reply the message */
1243 if (signal & (1L << data->app_TimerPort->mp_SigBit))
1245 struct timerequest_ext *time_ext;
1246 struct Node *n;
1247 struct List list;
1248 NewList(&list);
1250 /* At first we fetch all messages from the message port and store them
1251 ** in a list, we use the node of the Message here */
1252 while ((time_ext = (struct timerequest_ext *)GetMsg(data->app_TimerPort)))
1253 AddTail(&list,(struct Node*)time_ext);
1255 /* Now we proccess the list and resend the timer io, no loop can happen
1256 ** we use RemHead() because the handler can remove it itself and so
1257 ** a FreeVec() could happen in MUIM_Application_RemInputHandler which would
1258 ** destroy the the ln->Succ of course */
1259 while ((n = RemHead(&list)))
1261 struct timerequest_ext *time_ext = (struct timerequest_ext *)n;
1262 struct MUI_InputHandlerNode *ihn = time_ext->ihn;
1263 time_ext->treq.tr_time.tv_secs = time_ext->ihn->ihn_Millis/1000;
1264 time_ext->treq.tr_time.tv_micro = (time_ext->ihn->ihn_Millis%1000)*1000;
1265 SendIO((struct IORequest *)&time_ext->treq);
1266 DoMethod(ihn->ihn_Object,ihn->ihn_Method);
1270 if (data->app_BrokerPort && (signal & (1L << data->app_BrokerPort->mp_SigBit)))
1272 CxMsg *msg;
1274 while((msg = (CxMsg *)GetMsg(data->app_BrokerPort)))
1276 switch(CxMsgType(msg))
1278 case CXM_COMMAND:
1279 switch(CxMsgID(msg))
1281 case CXCMD_DISABLE:
1282 set(obj, MUIA_Application_Active, FALSE);
1283 break;
1285 case CXCMD_ENABLE:
1286 set(obj, MUIA_Application_Active, TRUE);
1287 break;
1289 case CXCMD_APPEAR:
1290 set(obj, MUIA_Application_Iconified, FALSE);
1291 break;
1293 case CXCMD_DISAPPEAR:
1294 set(obj, MUIA_Application_Iconified, TRUE);
1295 break;
1297 case CXCMD_KILL:
1298 SetSignal(SIGBREAKF_CTRL_C, SIGBREAKF_CTRL_C);
1299 break;
1301 break;
1304 if (data->app_BrokerHook)
1306 CallHookPkt(data->app_BrokerHook, obj, msg);
1309 ReplyMsg((struct Message *)msg);
1313 if (signal & handler_mask)
1315 for (mn = data->app_IHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
1317 struct MUI_InputHandlerNode *ihn;
1318 ihn = (struct MUI_InputHandlerNode *)mn;
1319 if (signal & ihn->ihn_Signals) DoMethod(ihn->ihn_Object,ihn->ihn_Method);
1324 /* process all pushed methods - again */
1325 while (application_do_pushed_method(data))
1326 /* nothing */ ;
1328 *msg->signal = signalmask;
1330 /* set return code */
1331 if ((rid = (struct RIDNode *)RemHead((struct List *)&data->app_ReturnIDQueue)))
1333 retval = rid->rid_Value;
1334 DeleteRIDNode(data, rid);
1335 return retval;
1337 return 0;
1340 /**************************************************************************
1341 MUIM_Application_Input : application main loop
1342 This method shouldn't be used in new programm. As it polls all signals.
1343 **************************************************************************/
1344 static IPTR Application__MUIM_Input(struct IClass *cl, Object *obj, struct MUIP_Application_Input *msg)
1346 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1347 ULONG signal = 0, handler_mask = 0;
1348 struct MinNode *mn;
1350 /* query the signal for the handlers */
1351 for (mn = data->app_IHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
1353 struct MUI_InputHandlerNode *ihn;
1354 ihn = (struct MUI_InputHandlerNode *)mn;
1355 handler_mask |= ihn->ihn_Flags;
1358 signal = (1L << data->app_GlobalInfo.mgi_WindowsPort->mp_SigBit)
1359 | (1L << data->app_TimerPort->mp_SigBit) | handler_mask;
1360 *msg->signal = signal;
1361 return Application__MUIM_NewInput(cl, obj, (APTR)msg);
1364 /**************************************************************************
1365 MUIM_Application_PushMethod: Add a method in the method FIFO. Will
1366 be executed in the next event loop.
1367 **************************************************************************/
1368 static IPTR Application__MUIM_PushMethod(struct IClass *cl, Object *obj, struct MUIP_Application_PushMethod *msg)
1370 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1371 struct MQNode *mq;
1372 LONG i;
1373 IPTR *m = (IPTR *)&msg->count; /* Warning, it will break on 64-bit BigEndian systems!!! */
1375 mq = CreateMQNode(msg->count);
1376 if (!mq) return 0;
1377 mq->mq_Dest = msg->dest;
1379 /* fill msg */
1380 for (i = 0; i < msg->count; i++)
1381 mq->mq_Msg[i] = *(m + 1 + i);
1383 /* enqueue method */
1384 ObtainSemaphore(&data->app_MethodSemaphore);
1385 AddTail((struct List *)&data->app_MethodQueue, (struct Node *)mq);
1386 ReleaseSemaphore(&data->app_MethodSemaphore);
1388 /* CHECKME: to wake task up as soon as possible! */
1389 Signal(data->app_Task, 1L << data->app_GlobalInfo.mgi_WindowsPort->mp_SigBit);
1391 return TRUE;
1396 * MUIM_Application_ReturnID : Tell MUI to return the given id with
1397 * the next call to MUIM_Application_NewInput. kinda obsolete :)
1399 static IPTR Application__MUIM_ReturnID(struct IClass *cl, Object *obj,
1400 struct MUIP_Application_ReturnID *msg)
1402 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1403 struct RIDNode *rid;
1406 if (!data->app_RIDMemChunk)
1408 data->app_RIDMemChunk =
1409 g_mem_chunk_create(struct RIDNode, 10, G_ALLOC_AND_FREE);
1412 rid = CreateRIDNode(data, msg->retid);
1413 if (!rid)
1414 return FALSE;
1415 AddTail((struct List *)&data->app_ReturnIDQueue, (struct Node *)rid);
1416 return TRUE;
1421 * MUIM_FindUData : tests if the MUIA_UserData of the object
1422 * contains the given <udata> and returns the object pointer in this case.
1424 static IPTR Application__MUIM_FindUData(struct IClass *cl, Object *obj, struct MUIP_FindUData *msg)
1426 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1428 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
1429 return (IPTR)obj;
1431 return DoMethodA(data->app_WindowFamily, (Msg)msg);
1436 * MUIM_GetUData : This method tests if the MUIA_UserData of the object
1437 * contains the given <udata> and gets <attr> to <storage> for itself
1438 * in this case.
1440 static IPTR Application__MUIM_GetUData(struct IClass *cl, Object *obj, struct MUIP_GetUData *msg)
1442 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1444 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
1446 get(obj, msg->attr, msg->storage);
1447 return TRUE;
1449 return DoMethodA(data->app_WindowFamily, (Msg)msg);
1454 * MUIM_SetUData : This method tests if the MUIA_UserData of the object
1455 * contains the given <udata> and sets <attr> to <val> for itself in this case.
1457 static IPTR Application__MUIM_SetUData(struct IClass *cl, Object *obj, struct MUIP_SetUData *msg)
1459 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1461 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
1462 set(obj, msg->attr, msg->val);
1464 DoMethodA(data->app_WindowFamily, (Msg)msg);
1465 return TRUE;
1470 * MUIM_SetUDataOnce : This method tests if the MUIA_UserData of the object
1471 * contains the given <udata> and sets <attr> to <val> for itself in this case.
1473 static IPTR Application__MUIM_SetUDataOnce(struct IClass *cl, Object *obj, struct MUIP_SetUDataOnce *msg)
1475 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1477 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
1479 set(obj, msg->attr, msg->val);
1480 return TRUE;
1482 return DoMethodA(data->app_WindowFamily, (Msg)msg);
1486 /**************************************************************************
1487 MUIM_Application_AboutMUI: brought up the about window, centered on refwindow
1488 **************************************************************************/
1489 static IPTR Application__MUIM_AboutMUI(struct IClass *cl, Object *obj, struct MUIP_Application_AboutMUI *msg)
1491 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1493 if (!data->app_AboutWin)
1495 data->app_AboutWin = AboutmuiObject,
1496 msg->refwindow ? MUIA_Window_RefWindow : TAG_IGNORE, msg->refwindow,
1497 MUIA_Window_LeftEdge, MUIV_Window_LeftEdge_Centered,
1498 MUIA_Window_TopEdge, MUIV_Window_TopEdge_Centered,
1499 MUIA_Aboutmui_Application, obj,
1500 End;
1501 if (!data->app_AboutWin)
1502 return 0;
1503 DoMethod(data->app_AboutWin, MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
1504 (IPTR)obj, 3, MUIM_WriteLong, 0L, (IPTR)&data->app_AboutWin);
1505 } /* if (!data->app_AboutWin) */
1507 if (data->app_AboutWin)
1510 set(data->app_AboutWin, MUIA_Window_Open, TRUE);
1512 return 0;
1515 static IPTR Application__MUIM_SetConfigdata(struct IClass *cl, Object *obj,
1516 struct MUIP_Application_SetConfigdata *msg)
1518 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1519 struct MinList *children;
1520 Object *cstate;
1521 Object *child;
1523 get(data->app_WindowFamily, MUIA_Family_List, &children);
1524 cstate = (Object *)children->mlh_Head;
1525 if ((child = NextObject(&cstate)))
1527 D(bug("closing window %p\n", child));
1529 set(child, MUIA_Window_Open, FALSE);
1532 if (data->app_GlobalInfo.mgi_Configdata)
1533 MUI_DisposeObject(data->app_GlobalInfo.mgi_Configdata);
1534 data->app_GlobalInfo.mgi_Configdata = msg->configdata;
1535 get(data->app_GlobalInfo.mgi_Configdata,MUIA_Configdata_ZunePrefs,
1536 &data->app_GlobalInfo.mgi_Prefs);
1538 DoMethod(obj, MUIM_Application_PushMethod, (IPTR)obj, 1, MUIM_Application_OpenWindows);
1539 return 0;
1543 /* MUIM_Application_OpenWindows
1544 * Opens all windows of an application
1546 static IPTR Application__MUIM_OpenWindows(struct IClass *cl, Object *obj,
1547 struct MUIP_Application_OpenWindows *msg)
1549 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1550 struct MinList *children;
1551 Object *cstate;
1552 Object *child;
1554 get(data->app_WindowFamily, MUIA_Family_List, &children);
1555 cstate = (Object *)children->mlh_Head;
1556 if ((child = NextObject(&cstate)))
1558 set(child, MUIA_Window_Open, TRUE);
1560 return 0;
1564 static IPTR Application__MUIM_OpenConfigWindow(struct IClass *cl, Object *obj,
1565 struct MUIP_Application_OpenConfigWindow *msg)
1567 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1568 struct TagItem tags[] =
1570 { SYS_Asynch , FALSE },
1571 { SYS_Input , 0 },
1572 { SYS_Output , 0 },
1573 { NP_StackSize , AROS_STACKSIZE},
1574 { TAG_DONE }
1576 char cmd[255];
1578 snprintf(cmd, 255, "sys:prefs/Zune %s %d", data->app_Base ? data->app_Base : (STRPTR) "", (int) obj);
1580 if (SystemTagList(cmd, tags) == -1)
1582 return 0;
1584 Delay(50);
1586 if (data->app_Base)
1588 snprintf(cmd, 255, "ENV:zune/%s.prefs", data->app_Base);
1589 DoMethod(data->app_GlobalInfo.mgi_Configdata, MUIM_Configdata_Load, (IPTR)cmd);
1592 return 1;
1595 static IPTR Application__MUIM_Execute(Class *CLASS, Object *self, Msg message)
1597 IPTR signals = 0L;
1599 while
1601 DoMethod(self, MUIM_Application_NewInput, (IPTR) &signals)
1602 != MUIV_Application_ReturnID_Quit
1605 if (signals)
1607 signals = Wait(signals | SIGBREAKF_CTRL_C);
1608 if (signals & SIGBREAKF_CTRL_C) break;
1612 return 0;
1616 static IPTR Application__MUIM_UpdateMenus(struct IClass *cl, Object *obj, Msg message)
1618 struct List *wlist;
1619 APTR wstate;
1620 Object *curwin;
1622 get(obj, MUIA_Application_WindowList, &wlist);
1624 if (wlist)
1626 wstate = wlist->lh_Head;
1627 while ((curwin = NextObject(&wstate)))
1629 DoMethod(curwin, MUIM_Window_UpdateMenu);
1633 return 0;
1636 static IPTR Application__MUIM_Load(struct IClass *cl, Object *obj, struct MUIP_Application_Load *message)
1638 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1639 struct IFFHandle *iff;
1640 char name[1024];
1641 BPTR fh;
1642 Object *dataspace;
1643 struct MinList *children;
1644 Object *cstate;
1645 Object *child;
1647 if(!data->app_Base)
1648 return 0;
1650 dataspace = MUI_NewObject(MUIC_Dataspace, TAG_DONE);
1651 if(!dataspace)
1652 return 0;
1654 if(message->name == MUIV_Application_Load_ENV)
1655 snprintf(name, sizeof(name), "ENV:Zune/%s.cfg", data->app_Base);
1656 else if(message->name == MUIV_Application_Load_ENVARC)
1657 snprintf(name, sizeof(name), "ENVARC:Zune/%s.cfg", data->app_Base);
1658 else
1659 strncpy(name, message->name, sizeof(name));
1661 fh = Open(name, MODE_OLDFILE);
1662 if(fh)
1664 if ((iff = AllocIFF()))
1666 iff->iff_Stream = (IPTR) fh;
1668 InitIFFasDOS(iff);
1670 if (!OpenIFF(iff, IFFF_READ))
1672 if (!StopChunk(iff, ID_PREF, ID_MUIO))
1674 if (!ParseIFF(iff, IFFPARSE_SCAN))
1676 DoMethod(dataspace, MUIM_Dataspace_ReadIFF, iff, ID_PREF, ID_MUIO);
1680 CloseIFF(iff);
1682 FreeIFF(iff);
1684 Close(fh);
1687 get(data->app_WindowFamily, MUIA_Family_List, &children);
1688 cstate = (Object *)children->mlh_Head;
1689 while ((child = NextObject(&cstate)))
1691 DoMethod(child, MUIM_Import, dataspace);
1694 MUI_DisposeObject(dataspace);
1696 return 0;
1699 static IPTR Application__MUIM_Save(struct IClass *cl, Object *obj, struct MUIP_Application_Save *message)
1701 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1702 struct IFFHandle *iff;
1703 char name[1024];
1704 BPTR fh;
1705 Object *dataspace;
1706 struct MinList *children;
1707 Object *cstate;
1708 Object *child;
1710 if(!data->app_Base)
1711 return 0;
1713 dataspace = MUI_NewObject(MUIC_Dataspace, TAG_DONE);
1714 if(!dataspace)
1715 return 0;
1717 get(data->app_WindowFamily, MUIA_Family_List, &children);
1718 cstate = (Object *)children->mlh_Head;
1719 while ((child = NextObject(&cstate)))
1721 DoMethod(child, MUIM_Export, dataspace);
1724 if(message->name == MUIV_Application_Save_ENV)
1725 snprintf(name, sizeof(name), "ENV:Zune/%s.cfg", data->app_Base);
1726 else if(message->name == MUIV_Application_Save_ENVARC)
1727 snprintf(name, sizeof(name), "ENVARC:Zune/%s.cfg", data->app_Base);
1728 else
1729 strncpy(name, message->name, sizeof(name));
1731 fh = Open(name, MODE_NEWFILE);
1732 if(fh)
1734 if ((iff = AllocIFF()))
1736 iff->iff_Stream = (IPTR) fh;
1738 InitIFFasDOS(iff);
1740 if (!OpenIFF(iff, IFFF_WRITE))
1742 if (!PushChunk(iff, ID_PREF, ID_FORM, IFFSIZE_UNKNOWN))
1744 if (!PushChunk(iff, ID_PREF, ID_PRHD, sizeof(struct FilePrefHeader)))
1746 struct FilePrefHeader head;
1748 head.ph_Version = PHV_CURRENT;
1749 head.ph_Type = 0;
1750 head.ph_Flags[0] =
1751 head.ph_Flags[1] =
1752 head.ph_Flags[2] =
1753 head.ph_Flags[3] = 0;
1755 if (WriteChunkBytes(iff, &head, sizeof(head)) == sizeof(head))
1757 PopChunk(iff);
1758 DoMethod(dataspace, MUIM_Dataspace_WriteIFF, iff, ID_PREF, ID_MUIO);
1760 else
1762 PopChunk(iff);
1765 PopChunk(iff);
1767 CloseIFF(iff);
1769 FreeIFF(iff);
1771 Close(fh);
1774 MUI_DisposeObject(dataspace);
1776 return 0;
1780 * The class dispatcher
1782 BOOPSI_DISPATCHER(IPTR, Application_Dispatcher, cl, obj, msg)
1784 switch (msg->MethodID)
1786 case OM_NEW: return Application__OM_NEW(cl, obj, (struct opSet *) msg);
1787 case OM_DISPOSE: return Application__OM_DISPOSE(cl, obj, msg);
1788 case OM_SET: return Application__OM_SET(cl, obj, (struct opSet *)msg);
1789 case OM_GET: return Application__OM_GET(cl, obj, (struct opGet *)msg);
1790 case OM_ADDMEMBER: return Application__OM_ADDMEMBER(cl, obj, (APTR)msg);
1791 case OM_REMMEMBER: return Application__OM_REMMEMBER(cl, obj, (APTR)msg);
1792 case MUIM_Application_AddInputHandler: return Application__MUIM_AddInputHandler(cl, obj, (APTR)msg);
1793 case MUIM_Application_RemInputHandler: return Application__MUIM_RemInputHandler(cl, obj, (APTR)msg);
1794 case MUIM_Application_Input: return Application__MUIM_Input(cl, obj, (APTR)msg);
1795 case MUIM_Application_InputBuffered: return Application__MUIM_InputBuffered(cl, obj, (APTR)msg);
1796 case MUIM_Application_NewInput: return Application__MUIM_NewInput(cl, obj, (APTR)msg);
1797 case MUIM_Application_PushMethod: return Application__MUIM_PushMethod(cl, obj, (APTR)msg);
1798 case MUIM_Application_ReturnID: return Application__MUIM_ReturnID(cl, obj, (APTR)msg);
1799 case MUIM_FindUData: return Application__MUIM_FindUData(cl, obj, (APTR)msg);
1800 case MUIM_GetUData: return Application__MUIM_GetUData(cl, obj, (APTR)msg);
1801 case MUIM_SetUData: return Application__MUIM_SetUData(cl, obj, (APTR)msg);
1802 case MUIM_SetUDataOnce: return Application__MUIM_SetUDataOnce(cl, obj, (APTR)msg);
1803 case MUIM_Application_AboutMUI: return Application__MUIM_AboutMUI(cl, obj, (APTR)msg);
1804 case MUIM_Application_SetConfigdata: return Application__MUIM_SetConfigdata(cl, obj, (APTR)msg);
1805 case MUIM_Application_OpenWindows: return Application__MUIM_OpenWindows(cl, obj, (APTR)msg);
1806 case MUIM_Application_OpenConfigWindow: return Application__MUIM_OpenConfigWindow(cl, obj, (APTR)msg);
1807 case MUIM_Application_Execute: return Application__MUIM_Execute(cl, obj, msg);
1808 case MUIM_Application_UpdateMenus: return Application__MUIM_UpdateMenus(cl, obj, msg);
1809 case MUIM_Application_Load: return Application__MUIM_Load(cl, obj, (APTR) msg);
1810 case MUIM_Application_Save: return Application__MUIM_Save(cl, obj, (APTR) msg);
1813 return(DoSuperMethodA(cl, obj, msg));
1815 BOOPSI_DISPATCHER_END
1818 * Class descriptor.
1820 const struct __MUIBuiltinClass _MUI_Application_desc = {
1821 MUIC_Application,
1822 MUIC_Notify,
1823 sizeof(struct MUI_ApplicationData),
1824 (void*)Application_Dispatcher