Tabs to spaces, more consistent formatting.
[AROS.git] / workbench / libs / muimaster / classes / application.c
blob0e609c738a97094d66ca4fc1544c656723b211a5
1 /*
2 Copyright 1999, David Le Corfec.
3 Copyright 2002-2012, 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 <rexx/errors.h>
23 #include <rexx/storage.h>
24 #include <rexx/rxslib.h>
25 #include <proto/alib.h>
26 #include <proto/exec.h>
27 #include <proto/dos.h>
28 #include <proto/intuition.h>
29 #include <proto/utility.h>
30 #include <proto/commodities.h>
31 #include <proto/muimaster.h>
32 #include <proto/iffparse.h>
33 #include <proto/rexxsyslib.h>
34 #include <proto/workbench.h>
35 #include <proto/icon.h>
37 //#define MYDEBUG 1
38 #include "debug.h"
39 #include "prefs.h"
41 #include "muimaster_intern.h"
42 #include "mui.h"
43 #include "support.h"
45 #include <string.h>
47 extern struct Library *MUIMasterBase;
50 struct TrackingNode
52 struct MinNode tn_Node;
53 Object *tn_Application;
56 struct MUI_ApplicationData
58 struct MUI_GlobalInfo app_GlobalInfo;
59 APTR app_WindowFamily; /* delegates window list */
60 struct MinList app_IHList;
61 struct MinList app_MethodQueue;
62 struct SignalSemaphore app_MethodSemaphore;
63 struct MinList app_ReturnIDQueue;
64 struct Hook *app_BrokerHook;
65 struct MsgPort *app_BrokerPort;
66 struct MsgPort *app_TimerPort;
67 struct timerequest *app_TimerReq;
68 struct Task *app_Task;
69 CxObj *app_Broker;
70 Object *app_Menustrip;
71 Object *app_AboutWin;
72 APTR app_RIDMemChunk;
73 STRPTR app_Author;
74 STRPTR app_Base;
75 STRPTR app_Copyright;
76 STRPTR app_Description;
77 STRPTR app_HelpFile;
78 STRPTR app_Title;
79 STRPTR app_Version;
80 BOOL app_VersionAllocated;
81 STRPTR app_Version_Number;
82 STRPTR app_Version_Date;
83 STRPTR app_Version_Extra;
84 WORD app_SleepCount; // attribute nests
85 ULONG app_TimerOutstanding;
86 ULONG app_MenuAction; /* Remember last action */
87 BOOL app_ForceQuit;
88 BOOL app_Iconified;
89 BOOL app_SingleTask;
90 BOOL app_Active;
91 BYTE app_BrokerPri;
92 struct TrackingNode app_TrackingNode;
93 BOOL app_is_TNode_in_list;
94 ULONG searchwinid;
95 LONG winposused; //dont add other vars before windowpos all is save together
96 struct windowpos winpos[MAXWINS];
97 struct MsgPort *app_RexxPort;
98 struct RexxMsg *app_RexxMsg;
99 struct Hook *app_RexxHook;
100 struct MUI_Command *app_Commands;
101 STRPTR app_RexxString;
102 BOOL app_UseRexx;
103 struct MsgPort *app_AppPort; /* Port for handling AppIcon / AppMenu */
104 struct AppIcon *app_AppIcon;
105 struct DiskObject *app_DiskObject; /* This is only pointer to client-managed object */
106 struct DiskObject *app_DefaultDiskObject; /* This is complete object managed by the class */
109 struct timerequest_ext
111 struct timerequest treq;
112 struct MUI_InputHandlerNode *ihn;
116 * Application class is the master class for all
117 * MUI applications. It serves as a kind of anchor
118 * for all input, either coming from the user or
119 * somewhere from the system, e.g. commodities
120 * or ARexx messages. (hemm forget theses last 2 for Zune :)
122 * An application can have any number of sub windows,
123 * these windows are the children of the application.
124 * (FYI, it delegates child handling to a Family object).
128 MUIA_Application_Active [ISG] done
129 MUIA_Application_Author [I.G] done
130 MUIA_Application_Base [I.G] done
131 MUIA_Application_Broker [..G] done
132 MUIA_Application_BrokerHook [ISG] done
133 MUIA_Application_BrokerPort [..G] done
134 MUIA_Application_BrokerPri [I.G] done
135 MUIA_Application_Commands [ISG] needs Arexx
136 MUIA_Application_Copyright [I.G] done
137 MUIA_Application_Description [I.G] done
138 MUIA_Application_DiskObject [ISG] done
139 MUIA_Application_DoubleStart [..G] not triggered yet (todo)
140 MUIA_Application_DropObject [IS.] needs AppMessage
141 MUIA_Application_ForceQuit [..G] not triggered yet
142 MUIA_Application_HelpFile [ISG] unused/dummy
143 MUIA_Application_Iconified [.SG] done
144 MUIA_Application_Menu [I.G] unimplemented (OBSOLETE)
145 MUIA_Application_MenuAction [..G] done
146 MUIA_Application_MenuHelp [..G] todo (ditto)
147 MUIA_Application_Menustrip [I..] done
148 MUIA_Application_RexxHook [ISG] needs Arexx
149 MUIA_Application_RexxMsg [..G] needs Arexx
150 MUIA_Application_RexxString [.S.] needs Arexx
151 MUIA_Application_SingleTask [I..] done
152 MUIA_Application_Sleep [.S.] todo
153 MUIA_Application_Title [I.G] done
154 MUIA_Application_UseCommodities [I..] done
155 MUIA_Application_UseRexx [I..] done
156 MUIA_Application_Version [I.G] done
157 MUIA_Application_Window [I..] done
158 MUIA_Application_WindowList [..G] done
160 OM_ADDMEMBER done
161 OM_REMMEMBER done
162 MUIM_Application_AboutMUI todo
163 MUIM_Application_AddInputHandler done ?
164 MUIM_Application_CheckRefresh todo (implementable ?)
165 MUIM_Application_GetMenuCheck OBSOLETE
166 MUIM_Application_GetMenuState OBSOLETE
167 MUIM_Application_Input OBSOLETE
168 MUIM_Application_InputBuffered todo
169 MUIM_Application_Load
170 MUIM_Application_NewInput done
171 MUIM_Application_OpenConfigWindow
172 MUIM_Application_PushMethod
173 MUIM_Application_RemInputHandler done ?
174 MUIM_Application_ReturnID done
175 MUIM_Application_Save
176 MUIM_Application_SetConfigItem
177 MUIM_Application_SetMenuCheck
178 MUIM_Application_SetMenuState
179 MUIM_Application_ShowHelp
181 Notify.mui/MUIM_FindUData done
182 Notify.mui/MUIM_GetUData done
183 Notify.mui/MUIM_SetUData done
184 Notify.mui/MUIM_SetUDataOnce done
187 static const int __version = 1;
188 static const int __revision = 1;
192 * MethodQueueNode
194 struct MQNode
196 struct MinNode mq_Node;
197 Object *mq_Dest;
198 LONG mq_Count;
199 IPTR *mq_Msg;
203 * FilePrefHeader
205 struct FilePrefHeader
207 UBYTE ph_Version;
208 UBYTE ph_Type;
209 UBYTE ph_Flags[4];
212 #define ID_MUIO MAKE_ID('M','U','I','O')
215 * Allocates an MethodQueue Method
217 static struct MQNode *CreateMQNode(LONG count)
219 struct MQNode *mq;
221 mq = (struct MQNode *)mui_alloc(sizeof(struct MQNode) +
222 (count * sizeof(IPTR)));
223 if (!mq)
224 return NULL;
226 mq->mq_Count = count;
227 mq->mq_Msg = (IPTR *) (((char *)mq) + sizeof(struct MQNode));
228 return mq;
232 * Free an IQ Method got from CreateIQMethod()
234 static void DeleteMQNode(struct MQNode *mq)
236 mui_free(mq);
241 * Queue of Return IDs
243 struct RIDNode
245 struct MinNode rid_Node;
246 ULONG rid_Value;
250 static struct RIDNode *CreateRIDNode(struct MUI_ApplicationData *data,
251 ULONG retid)
253 struct RIDNode *rid;
255 if ((rid = mui_alloc_struct(struct RIDNode)))
257 rid->rid_Value = retid;
259 return rid;
263 static void DeleteRIDNode(struct MUI_ApplicationData *data,
264 struct RIDNode *rid)
266 mui_free(rid);
270 /**************************************************************************
271 Process a pushed method.
272 **************************************************************************/
273 static BOOL application_do_pushed_method(struct MUI_ApplicationData *data)
275 struct MQNode *mq;
277 ObtainSemaphore(&data->app_MethodSemaphore);
279 if ((mq = (struct MQNode *)RemHead((struct List *)&data->app_MethodQueue)))
281 ReleaseSemaphore(&data->app_MethodSemaphore);
283 DoMethodA(mq->mq_Dest, (Msg) mq->mq_Msg);
284 DeleteMQNode(mq);
285 return TRUE;
287 ReleaseSemaphore(&data->app_MethodSemaphore);
288 return FALSE;
291 static Object *find_application_by_base(struct IClass *cl, Object *obj,
292 STRPTR base)
294 struct TrackingNode *tn;
295 Object *retval = NULL;
297 ObtainSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
298 ForeachNode(&MUIMB(MUIMasterBase)->Applications, tn)
300 STRPTR tn_base = "";
302 get(tn->tn_Application, MUIA_Application_Base, &tn_base);
304 if (tn_base && (strcmp(base, tn_base)) == 0)
306 retval = tn->tn_Application;
307 break;
310 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
312 return retval;
315 /**************************************************************************
316 OM_NEW
317 **************************************************************************/
318 static IPTR Application__OM_NEW(struct IClass *cl, Object *obj,
319 struct opSet *msg)
321 struct MUI_ApplicationData *data;
322 struct TagItem *tags, *tag;
323 BOOL bad_childs = FALSE;
325 obj = (Object *) DoSuperMethodA(cl, obj, (Msg) msg);
326 if (!obj)
327 return FALSE;
329 /* Initial local instance data */
330 data = INST_DATA(cl, obj);
332 /* init input handler list */
333 NewList((struct List *)&(data->app_IHList));
335 /* init input queue */
336 NewList((struct List *)&(data->app_MethodQueue));
338 /* init return ids queue */
339 NewList((struct List *)&(data->app_ReturnIDQueue));
341 /* window list */
342 data->app_WindowFamily = MUI_NewObjectA(MUIC_Family, NULL);
343 if (!data->app_WindowFamily)
345 CoerceMethod(cl, obj, OM_DISPOSE);
346 return 0;
349 data->app_GlobalInfo.mgi_ApplicationObject = obj;
350 if (!(data->app_GlobalInfo.mgi_WindowsPort = CreateMsgPort()))
352 CoerceMethod(cl, obj, OM_DISPOSE);
353 return 0;
356 data->app_Task = FindTask(NULL);
358 /* Parse prefs */
359 data->app_SingleTask =
360 (BOOL) GetTagData(MUIA_Application_SingleTask, FALSE,
361 msg->ops_AttrList);
362 data->app_Base =
363 (STRPTR) GetTagData(MUIA_Application_Base, (IPTR) "UNNAMED",
364 msg->ops_AttrList);
365 if (!data->app_Base || strpbrk(data->app_Base, ":/()#?*,"))
367 data->app_Base = NULL; /* don't remove */
368 CoerceMethod(cl, obj, OM_DISPOSE);
370 return 0;
373 if (!data->app_SingleTask)
375 /* must append .1, .2, ... to the base name */
376 LONG i;
377 char portname[255];
379 for (i = 1; i < 1000; i++)
381 snprintf(portname, 255, "%s.%d", data->app_Base, (int)i);
382 if (!find_application_by_base(cl, obj, portname))
383 break;
385 data->app_Base = StrDup(portname);
387 else
389 Object *other_app;
391 ObtainSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
392 if ((other_app = find_application_by_base(cl, obj, data->app_Base)))
394 //FIXME "Is calling MUIM_Application_PushMethod on an alien application object safe?"
395 DoMethod(other_app, MUIM_Application_PushMethod,
396 (IPTR) other_app, 3, MUIM_Set, MUIA_Application_DoubleStart,
397 TRUE);
398 data->app_Base = NULL;
400 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
402 data->app_Base = StrDup(data->app_Base);
405 if (!data->app_Base)
407 CoerceMethod(cl, obj, OM_DISPOSE);
408 return 0;
411 data->app_GlobalInfo.mgi_Configdata =
412 MUI_NewObject(MUIC_Configdata, MUIA_Configdata_Application, obj,
413 TAG_DONE);
414 if (!data->app_GlobalInfo.mgi_Configdata)
416 CoerceMethod(cl, obj, OM_DISPOSE);
417 return 0;
419 get(data->app_GlobalInfo.mgi_Configdata, MUIA_Configdata_ZunePrefs,
420 &data->app_GlobalInfo.mgi_Prefs);
422 // D(bug("muimaster.library/application.c: Message Port created at 0x%lx\n",
423 // data->app_GlobalInfo.mgi_WindowPort));
425 /* Setup timer stuff */
426 if (!(data->app_TimerPort = CreateMsgPort()))
428 CoerceMethod(cl, obj, OM_DISPOSE);
429 return 0;
432 if (!(data->app_TimerReq =
433 (struct timerequest *)CreateIORequest(data->app_TimerPort,
434 sizeof(struct timerequest))))
436 CoerceMethod(cl, obj, OM_DISPOSE);
437 return 0;
440 if (OpenDevice(TIMERNAME, UNIT_VBLANK,
441 (struct IORequest *)data->app_TimerReq, 0))
443 CoerceMethod(cl, obj, OM_DISPOSE);
444 return 0;
447 InitSemaphore(&data->app_MethodSemaphore);
449 muiNotifyData(obj)->mnd_GlobalInfo = &data->app_GlobalInfo;
451 /* parse initial taglist */
453 data->app_Active = 1;
454 data->app_Title = "Unnamed";
455 data->app_Version = "Unnamed 0.0";
456 data->app_Description = "?";
458 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags));)
460 switch (tag->ti_Tag)
462 case MUIA_Application_Author:
463 data->app_Author = (STRPTR) tag->ti_Data;
464 break;
466 case MUIA_Application_Base:
467 /* moved before config parsing */
468 break;
470 case MUIA_Application_Copyright:
471 data->app_Copyright = (STRPTR) tag->ti_Data;
472 break;
474 case MUIA_Application_Description:
475 data->app_Description = (STRPTR) tag->ti_Data;
476 break;
478 case MUIA_Application_HelpFile:
479 data->app_HelpFile = (STRPTR) tag->ti_Data;
480 break;
482 case MUIA_Application_SingleTask:
483 /* moved before config parsing */
484 break;
486 case MUIA_Application_Title:
487 data->app_Title = (STRPTR) tag->ti_Data;
488 break;
490 case MUIA_Application_Version:
491 data->app_Version = (STRPTR) tag->ti_Data;
492 break;
494 case MUIA_Application_Version_Number:
495 data->app_Version_Number = (STRPTR) tag->ti_Data;
496 break;
498 case MUIA_Application_Version_Date:
499 data->app_Version_Date = (STRPTR) tag->ti_Data;
500 break;
502 case MUIA_Application_Version_Extra:
503 data->app_Version_Extra = (STRPTR) tag->ti_Data;
504 break;
506 case MUIA_Application_Window:
507 if (tag->ti_Data)
508 DoMethod(obj, OM_ADDMEMBER, tag->ti_Data);
509 else
510 bad_childs = TRUE;
511 break;
513 case MUIA_Application_Menustrip:
514 data->app_Menustrip = (Object *) tag->ti_Data;
515 break;
517 case MUIA_Application_BrokerPri:
518 data->app_BrokerPri = (BYTE) tag->ti_Data;
519 break;
521 case MUIA_Application_BrokerHook:
522 data->app_BrokerHook = (struct Hook *)tag->ti_Data;
523 break;
525 case MUIA_Application_Active:
526 data->app_Active = tag->ti_Data ? TRUE : FALSE;
527 break;
529 case MUIA_Application_UsedClasses:
531 STRPTR *list = (STRPTR *) tag->ti_Data;
532 if (!list)
533 break;
534 while (*list)
536 struct IClass *icl = MUI_GetClass(*list);
537 if (icl)
538 MUI_FreeClass(icl);
539 ++list;
542 break;
544 case MUIA_Application_UseRexx:
545 data->app_UseRexx = tag->ti_Data ? TRUE : FALSE;
546 break;
548 case MUIA_Application_Commands:
549 data->app_Commands = (struct MUI_Command *)tag->ti_Data;
550 break;
552 case MUIA_Application_RexxHook:
553 data->app_RexxHook = (struct Hook *)tag->ti_Data;
554 break;
556 case MUIA_Application_DiskObject:
557 data->app_DiskObject = (struct DiskObject *)tag->ti_Data;
558 break;
563 /* create MUIA_Application_Version if NULL */
564 if (data->app_Version == NULL
565 && data->app_Title != NULL && data->app_Version_Number != NULL)
567 STRPTR result = NULL;
568 ULONG length = 0;
570 /* Calculate length */
571 length = strlen("$VER: ") + strlen(data->app_Title) + 1 /* space */
572 + strlen(data->app_Version_Number) + 1 /* NULL */ ;
574 if (data->app_Version_Date != NULL)
576 length += 1 /* space */ + 1 /* ( */
577 + strlen(data->app_Version_Date) + 1 /* ) */ ;
580 if (data->app_Version_Extra != NULL)
582 length += 1 /* space */ + 1 /* [ */
583 + strlen(data->app_Version_Extra) + 1 /* ] */ ;
586 /* Allocate memory */
587 result = AllocVec(length, MEMF_ANY);
589 if (result != NULL)
591 result[0] = '\0';
593 /* Format string */
594 strlcat(result, "$VER: ", length);
595 strlcat(result, data->app_Title, length);
596 strlcat(result, " ", length);
597 strlcat(result, data->app_Version_Number, length);
599 if (data->app_Version_Date != NULL)
601 strlcat(result, " (", length);
602 strlcat(result, data->app_Version_Date, length);
603 strlcat(result, ")", length);
606 if (data->app_Version_Extra != NULL)
608 strlcat(result, " [", length);
609 strlcat(result, data->app_Version_Extra, length);
610 strlcat(result, "]", length);
613 data->app_Version = result;
614 data->app_VersionAllocated = TRUE;
619 if (bad_childs)
621 CoerceMethod(cl, obj, OM_DISPOSE);
622 return 0;
625 if (CxBase
626 && GetTagData(MUIA_Application_UseCommodities, TRUE,
627 msg->ops_AttrList))
629 data->app_BrokerPort = CreateMsgPort();
631 if (data->app_BrokerPort)
633 struct NewBroker nb;
635 nb.nb_Version = NB_VERSION;
636 nb.nb_Name =
637 data->app_Title ? data->app_Title : (STRPTR) "Unnamed";
638 nb.nb_Title =
639 data->app_Version ? data->app_Version : (STRPTR) "Unnamed";
640 nb.nb_Descr =
641 data->app_Description ? data->
642 app_Description : (STRPTR) "?";
643 nb.nb_Unique = 0;
644 nb.nb_Flags = COF_SHOW_HIDE;
645 nb.nb_Pri = data->app_BrokerPri;
646 nb.nb_Port = data->app_BrokerPort;
647 nb.nb_ReservedChannel = 0;
649 if (strncmp(nb.nb_Title, "$VER: ", 6) == 0)
650 nb.nb_Title += 6;
652 data->app_Broker = CxBroker(&nb, 0);
654 if (data->app_Broker)
656 if (data->app_Active)
657 ActivateCxObj(data->app_Broker, 1);
662 if (data->app_UseRexx)
664 data->app_RexxPort = CreateMsgPort();
665 if (data->app_RexxPort)
667 data->app_RexxPort->mp_Node.ln_Name = StrDup(data->app_Base);
668 if (data->app_RexxPort->mp_Node.ln_Name != NULL)
670 D(bug("[MUI] %s is using REXX!\n",
671 data->app_RexxPort->mp_Node.ln_Name));
672 char *i;
673 for (i = data->app_RexxPort->mp_Node.ln_Name; *i != '\0';
674 i++)
676 *i = toupper(*i);
678 AddPort(data->app_RexxPort);
680 else
682 DeleteMsgPort(data->app_RexxPort);
683 data->app_RexxPort = NULL;
688 if (data->app_Menustrip)
689 DoMethod(data->app_Menustrip, MUIM_ConnectParent, (IPTR) obj);
691 data->app_AppPort = CreateMsgPort();
693 ObtainSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
694 data->app_TrackingNode.tn_Application = obj;
695 AddTail((struct List *)&MUIMB(MUIMasterBase)->Applications,
696 (struct Node *)&data->app_TrackingNode);
697 data->app_is_TNode_in_list = TRUE;
698 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
700 return (IPTR) obj;
705 /**************************************************************************
706 OM_DISPOSE
707 **************************************************************************/
708 static IPTR Application__OM_DISPOSE(struct IClass *cl, Object *obj,
709 Msg msg)
711 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
712 struct RIDNode *rid;
714 long positionmode;
715 if (data->app_Base)
717 char filename[255];
718 positionmode = data->app_GlobalInfo.mgi_Prefs->window_position;
719 if (positionmode >= 1)
721 snprintf(filename, 255, "ENV:zune/%s.prefs", data->app_Base);
722 DoMethod(data->app_GlobalInfo.mgi_Configdata,
723 MUIM_Configdata_Save, (IPTR) filename);
725 if (positionmode == 2)
727 snprintf(filename, 255, "ENVARC:zune/%s.prefs", data->app_Base);
728 DoMethod(data->app_GlobalInfo.mgi_Configdata,
729 MUIM_Configdata_Save, (IPTR) filename);
733 if (data->app_is_TNode_in_list)
735 ObtainSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
736 Remove((struct Node *)&data->app_TrackingNode);
737 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
740 if (data->app_WindowFamily)
742 struct MinList *children = NULL;
743 Object *cstate;
744 Object *child;
746 /* special loop because the next object may have been removed/freed by
747 * the previous. so restart from listhead each time.
749 while (1)
751 get(data->app_WindowFamily, MUIA_Family_List, &children);
752 if (children == NULL)
753 break;
755 cstate = (Object *) children->mlh_Head;
756 if ((child = NextObject(&cstate)))
758 D(bug("Application_Dispose(%p) : OM_REMMEMBER(%p)\n", obj,
759 child));
760 DoMethod(obj, OM_REMMEMBER, (IPTR) child);
761 D(bug("Application_Dispose(%p) : MUI_DisposeObject(%p)\n",
762 obj, child));
763 MUI_DisposeObject(child);
766 else
768 break;
771 MUI_DisposeObject(data->app_WindowFamily);
774 if (data->app_Menustrip)
775 MUI_DisposeObject(data->app_Menustrip);
777 if (data->app_VersionAllocated && data->app_Version != NULL)
779 FreeVec(data->app_Version);
782 /* free commodities stuff */
784 if (data->app_Broker)
786 DeleteCxObjAll(data->app_Broker);
789 if (data->app_BrokerPort)
791 struct Message *msg;
793 while ((msg = GetMsg(data->app_BrokerPort)))
795 ReplyMsg(msg);
798 DeleteMsgPort(data->app_BrokerPort);
801 /* free timer stuff */
802 if (data->app_TimerReq)
804 if (data->app_TimerReq->tr_node.io_Device)
806 while (data->app_TimerOutstanding)
808 if (Wait(1L << data->app_TimerPort->
809 mp_SigBit | 4096) & 4096)
810 break;
811 data->app_TimerOutstanding--;
813 CloseDevice((struct IORequest *)data->app_TimerReq);
815 DeleteIORequest((struct IORequest *)data->app_TimerReq);
817 if (data->app_TimerPort)
818 DeleteMsgPort(data->app_TimerPort);
820 if (data->app_RexxPort)
822 struct Message *msg;
823 while ((msg = GetMsg(data->app_RexxPort)))
825 ReplyMsg(msg);
827 RemPort(data->app_RexxPort);
829 if (data->app_RexxPort->mp_Node.ln_Name != NULL)
830 FreeVec(data->app_RexxPort->mp_Node.ln_Name);
832 DeleteMsgPort(data->app_RexxPort);
835 if (data->app_AppIcon)
836 RemoveAppIcon(data->app_AppIcon);
838 if (data->app_DefaultDiskObject)
839 FreeDiskObject(data->app_DefaultDiskObject);
841 if (data->app_AppPort)
843 struct Message *msg;
844 while ((msg = GetMsg(data->app_AppPort)))
845 ReplyMsg(msg);
847 DeleteMsgPort(data->app_AppPort);
850 if (data->app_GlobalInfo.mgi_Configdata)
851 MUI_DisposeObject(data->app_GlobalInfo.mgi_Configdata);
853 if (data->app_GlobalInfo.mgi_WindowsPort)
854 DeleteMsgPort(data->app_GlobalInfo.mgi_WindowsPort);
856 FreeVec(data->app_Base);
858 /* free returnid stuff */
860 while ((rid =
861 (struct RIDNode *)RemHead((struct List *)&data->
862 app_ReturnIDQueue)))
864 DeleteRIDNode(data, rid);
867 return DoSuperMethodA(cl, obj, msg);
871 /**************************************************************************
872 OM_SET
873 **************************************************************************/
874 static IPTR Application__OM_SET(struct IClass *cl, Object *obj,
875 struct opSet *msg)
877 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
878 struct TagItem *tags = msg->ops_AttrList;
879 struct TagItem *tag;
881 /* There are many ways to find out what tag items provided by set()
882 ** we do know. The best way should be using NextTagItem() and simply
883 ** browsing through the list.
885 while ((tag = NextTagItem(&tags)) != NULL)
887 IPTR *addr;
888 switch (tag->ti_Tag)
891 case MUIA_Application_SearchWinId:
892 data->searchwinid = tag->ti_Data;
893 break;
895 case MUIA_Application_CopyWinPosToApp:
896 addr = (IPTR *) tag->ti_Data;
897 CopyMem((CONST_APTR) tag->ti_Data, &data->winposused, *(addr));
898 break;
900 case MUIA_Application_SetWinPos:
902 struct windowpos *winp;
903 winp = (struct windowpos *)tag->ti_Data;
904 //kprintf("SetWinPos %d %d %d %d %d\n", winp->id, winp->x1,
905 // winp->y1, winp->w1, winp->h1);
906 int i;
907 for (i = 0; i < MAXWINS - 1; i++)
909 if (data->winpos[i].w1)
911 if (winp->id == data->winpos[i].id)
913 //existing entry is overwritten
914 data->winpos[i].x1 = winp->x1;
915 data->winpos[i].y1 = winp->y1;
916 data->winpos[i].w1 = winp->w1;
917 data->winpos[i].h1 = winp->h1;
918 data->winpos[i].x2 = winp->x2;
919 data->winpos[i].y2 = winp->y2;
920 data->winpos[i].w2 = winp->w2;
921 data->winpos[i].h2 = winp->h2;
922 break;
925 else
927 // a new entry is added
928 data->winpos[i].id = winp->id;
929 data->winpos[i].x1 = winp->x1;
930 data->winpos[i].y1 = winp->y1;
931 data->winpos[i].w1 = winp->w1;
932 data->winpos[i].h1 = winp->h1;
933 data->winpos[i].x2 = winp->x2;
934 data->winpos[i].y2 = winp->y2;
935 data->winpos[i].w2 = winp->w2;
936 data->winpos[i].h2 = winp->h2;
937 break;
941 break;
943 case MUIA_Application_Configdata:
944 DoMethod(obj, MUIM_Application_PushMethod, (IPTR) obj, 2,
945 MUIM_Application_SetConfigdata, tag->ti_Data);
946 break;
948 case MUIA_Application_HelpFile:
949 data->app_HelpFile = (STRPTR) tag->ti_Data;
950 break;
952 case MUIA_Application_Iconified:
954 BOOL do_iconify = tag->ti_Data == 1;
955 if (data->app_Iconified != do_iconify)
957 data->app_Iconified = do_iconify;
959 nnset(obj, MUIA_ShowMe, !data->app_Iconified);
961 /* Inform workbench.library */
962 if (data->app_Iconified)
964 STRPTR appname =
965 data->app_Title ? data->
966 app_Title : (STRPTR) "Unnamed";
967 struct DiskObject *dobj =
968 (struct DiskObject *)XGET(obj,
969 MUIA_Application_DiskObject);
971 if (dobj == NULL)
973 /* Get default AppIcon in ENV:SYS or ENVARC:SYS */
974 dobj = GetDefDiskObject(WBAPPICON);
975 if (dobj)
976 data->app_DefaultDiskObject = dobj;
977 else
979 /* First default: ENV:SYS/def_MUI.info */
980 dobj = GetDiskObject("ENV:SYS/def_MUI");
981 if (dobj)
982 data->app_DefaultDiskObject = dobj;
983 else
985 /* Second default: ENV:SYS/def_Zune.info */
986 dobj =
987 GetDiskObject("ENV:SYS/def_Zune");
988 if (dobj)
989 data->app_DefaultDiskObject = dobj;
990 else
992 /* Third default: default tool icon */
993 dobj = GetDefDiskObject(WBTOOL);
994 if (dobj)
995 data->app_DefaultDiskObject =
996 dobj;
1002 if (dobj == NULL)
1003 break;
1005 dobj->do_CurrentX = NO_ICON_POSITION;
1006 dobj->do_CurrentY = NO_ICON_POSITION;
1008 data->app_AppIcon =
1009 AddAppIconA(0L, 0L, appname, data->app_AppPort,
1010 BNULL, dobj, NULL);
1012 else
1014 if (data->app_AppIcon)
1016 RemoveAppIcon(data->app_AppIcon);
1017 data->app_AppIcon = NULL;
1019 if (data->app_DefaultDiskObject)
1021 FreeDiskObject(data->app_DefaultDiskObject);
1022 data->app_DefaultDiskObject = NULL;
1027 break;
1029 case MUIA_ShowMe:
1031 /* Ok ok, you think this stinks? Well, think of it as
1032 an attribute belonging to an interface which
1033 MUIC_Application, together with MUIC_Area and a few
1034 others implement. It makes sense now, yes? */
1035 struct List *wlist = NULL;
1036 APTR wstate;
1037 Object *curwin = NULL;
1038 Object *lastwin = NULL;
1040 /* MUIA_ShowMe can cause MUIM_Setup/MUIM_Cleanup to be issued.
1041 * On the other hand it is allowed to add/remove other
1042 * application windows in MUIM_Setup/MUIM_Cleanup.
1043 * This means after processing a window from internal list,
1044 * the list needs to be re-read and iteration started again,
1045 * because wstate can become invalid.
1046 * Note: The code below assumes that the window won't remove
1047 * itself from the list.
1050 while (1)
1052 get(data->app_WindowFamily, MUIA_Family_List, &wlist);
1053 wstate = (Object *) wlist->lh_Head;
1054 while ((curwin = NextObject(&wstate)))
1056 if (lastwin == NULL)
1057 break;
1058 if (curwin == lastwin)
1060 curwin = NextObject(&wstate);
1061 break;
1065 /* This is the window to be processed */
1066 if (curwin)
1068 set(curwin, MUIA_ShowMe, tag->ti_Data);
1069 lastwin = curwin;
1071 else
1073 /* No more windows */
1074 break;
1078 break;
1080 case MUIA_Application_Sleep:
1082 struct List *wlist = NULL;
1083 APTR wstate;
1084 Object *curwin;
1086 if (tag->ti_Data)
1088 data->app_SleepCount++;
1089 if (data->app_SleepCount == 1)
1091 get(obj, MUIA_Application_WindowList, &wlist);
1092 if (wlist)
1094 wstate = wlist->lh_Head;
1095 while ((curwin = NextObject(&wstate)))
1097 set(curwin, MUIA_Window_Sleep, TRUE);
1102 else
1104 data->app_SleepCount--;
1105 if (data->app_SleepCount == 0)
1107 get(obj, MUIA_Application_WindowList, &wlist);
1108 if (wlist)
1110 wstate = wlist->lh_Head;
1111 while ((curwin = NextObject(&wstate)))
1113 set(curwin, MUIA_Window_Sleep, FALSE);
1119 break;
1121 case MUIA_Application_MenuAction:
1122 data->app_MenuAction = tag->ti_Data;
1123 break;
1125 case MUIA_Application_BrokerHook:
1126 data->app_BrokerHook = (struct Hook *)tag->ti_Data;
1127 break;
1129 case MUIA_Application_Active:
1130 data->app_Active = tag->ti_Data ? TRUE : FALSE;
1131 if (data->app_Broker)
1133 ActivateCxObj(data->app_Broker, data->app_Active);
1135 break;
1137 case MUIA_Application_Commands:
1138 data->app_Commands = (struct MUI_Command *)tag->ti_Data;
1139 break;
1141 case MUIA_Application_RexxString:
1142 data->app_RexxString = (STRPTR) tag->ti_Data;
1143 break;
1145 case MUIA_Application_RexxHook:
1146 data->app_RexxHook = (struct Hook *)tag->ti_Data;
1147 break;
1149 case MUIA_Application_DiskObject:
1150 data->app_DiskObject = (struct DiskObject *)tag->ti_Data;
1151 break;
1155 return DoSuperMethodA(cl, obj, (Msg) msg);
1160 * OM_GET
1162 static IPTR Application__OM_GET(struct IClass *cl, Object *obj,
1163 struct opGet *msg)
1165 #define STORE *(msg->opg_Storage)
1167 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1169 switch (msg->opg_AttrID)
1171 case MUIA_Application_GetWinPosAddr:
1172 STORE = (IPTR) & data->winposused;
1173 return TRUE;
1175 case MUIA_Application_GetWinPosSize:
1177 int i;
1178 for (i = 0; i < MAXWINS - 1; i++)
1180 if (!data->winpos[i].w1)
1182 i *= sizeof(struct windowpos);
1183 i += sizeof(long);
1184 data->winposused = i;
1185 STORE = i;
1186 return (TRUE);
1189 STORE = 0;
1190 return TRUE;
1193 case MUIA_Application_GetWinPos:
1195 int i;
1196 if (data->searchwinid)
1198 for (i = 0; i < MAXWINS - 1; i++)
1200 if (data->winpos[i].w1)
1202 if (data->searchwinid == data->winpos[i].id)
1204 STORE = (IPTR) & data->winpos[i].id;
1205 return 1;
1208 else
1209 break;
1212 STORE = 0;
1213 return 1;
1215 return TRUE;
1217 case MUIA_Version:
1218 STORE = __version;
1219 return TRUE;
1221 case MUIA_Revision:
1222 STORE = __revision;
1223 return TRUE;
1225 case MUIA_Application_Author:
1226 STORE = (IPTR) data->app_Author;
1227 return TRUE;
1229 case MUIA_Application_Base:
1230 STORE = (IPTR) data->app_Base;
1231 return TRUE;
1233 case MUIA_Application_Copyright:
1234 STORE = (IPTR) data->app_Copyright;
1235 return TRUE;
1237 case MUIA_Application_Description:
1238 STORE = (IPTR) data->app_Description;
1239 return TRUE;
1241 case MUIA_Application_DoubleStart:
1242 return TRUE;
1244 case MUIA_Application_ForceQuit:
1245 STORE = (IPTR) data->app_ForceQuit;
1246 return TRUE;
1248 case MUIA_Application_HelpFile:
1249 STORE = (IPTR) data->app_HelpFile;
1250 return TRUE;
1252 case MUIA_Application_Iconified:
1253 STORE = (IPTR) data->app_Iconified;
1254 return TRUE;
1256 case MUIA_Application_Title:
1257 STORE = (IPTR) data->app_Title;
1258 return TRUE;
1260 case MUIA_Application_Version:
1261 STORE = (IPTR) data->app_Version;
1262 return TRUE;
1264 case MUIA_Application_Version_Number:
1265 STORE = (IPTR) data->app_Version_Number;
1266 return TRUE;
1268 case MUIA_Application_Version_Date:
1269 STORE = (IPTR) data->app_Version_Date;
1270 return TRUE;
1272 case MUIA_Application_Version_Extra:
1273 STORE = (IPTR) data->app_Version_Extra;
1274 return TRUE;
1276 case MUIA_Application_WindowList:
1277 return GetAttr(MUIA_Family_List, data->app_WindowFamily,
1278 msg->opg_Storage);
1280 case MUIA_Application_Menustrip:
1281 STORE = (IPTR) data->app_Menustrip;
1282 return TRUE;
1284 case MUIA_Application_MenuAction:
1285 STORE = (IPTR) data->app_MenuAction;
1286 return TRUE;
1288 case MUIA_Application_BrokerPort:
1289 STORE = (IPTR) data->app_BrokerPort;
1290 return TRUE;
1292 case MUIA_Application_BrokerPri:
1293 STORE = (IPTR) data->app_BrokerPri;
1294 return TRUE;
1296 case MUIA_Application_BrokerHook:
1297 STORE = (IPTR) data->app_BrokerHook;
1298 return TRUE;
1300 case MUIA_Application_Broker:
1301 STORE = (IPTR) data->app_Broker;
1302 return TRUE;
1304 case MUIA_Application_Active:
1305 STORE = data->app_Active;
1306 return TRUE;
1308 case MUIA_Application_Commands:
1309 STORE = (IPTR) data->app_Commands;
1310 return TRUE;
1312 case MUIA_Application_RexxMsg:
1313 STORE = (IPTR) data->app_RexxMsg;
1314 return TRUE;
1316 case MUIA_Application_RexxHook:
1317 STORE = (IPTR) data->app_RexxHook;
1318 return TRUE;
1320 case MUIA_Application_DiskObject:
1321 STORE = (IPTR) data->app_DiskObject;
1322 return TRUE;
1325 /* our handler didn't understand the attribute, we simply pass
1326 ** it to our superclass now
1328 return (DoSuperMethodA(cl, obj, (Msg) msg));
1329 #undef STORE
1333 /**************************************************************************
1334 OM_ADDMEMBER
1335 **************************************************************************/
1336 static IPTR Application__OM_ADDMEMBER(struct IClass *cl, Object *obj,
1337 struct opMember *msg)
1339 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1341 D(bug("Application_AddMember: Adding 0x%lx to window member list\n",
1342 msg->opam_Object));
1344 DoMethodA(data->app_WindowFamily, (Msg) msg);
1345 /* Application knows its GlobalInfo, so we can inform window */
1346 DoMethod(msg->opam_Object, MUIM_ConnectParent, (IPTR) obj);
1347 return TRUE;
1351 /**************************************************************************
1352 OM_REMMEMBER
1353 **************************************************************************/
1354 static IPTR Application__OM_REMMEMBER(struct IClass *cl, Object *obj,
1355 struct opMember *msg)
1357 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1359 D(bug("Application_RemMember: Removing 0x%lx from window member list\n",
1360 msg->opam_Object));
1362 DoMethod(msg->opam_Object, MUIM_DisconnectParent);
1363 DoMethodA(data->app_WindowFamily, (Msg) msg);
1364 return TRUE;
1369 /**************************************************************************
1370 MUIM_Application_AddInputHandler
1371 **************************************************************************/
1372 static IPTR Application__MUIM_AddInputHandler(struct IClass *cl,
1373 Object *obj, struct MUIP_Application_AddInputHandler *msg)
1375 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1377 if (msg->ihnode->ihn_Flags & MUIIHNF_TIMER)
1379 struct timerequest_ext *time_ext =
1380 (struct timerequest_ext *)AllocVec(sizeof(struct
1381 timerequest_ext), MEMF_PUBLIC);
1382 if (time_ext)
1384 /* Store the request inside the input handler, so that we can
1385 ** remove the inputhandler without problems */
1386 msg->ihnode->ihn_Node.mln_Pred = (struct MinNode *)time_ext;
1388 time_ext->treq = *data->app_TimerReq;
1389 time_ext->treq.tr_node.io_Command = TR_ADDREQUEST;
1390 time_ext->treq.tr_time.tv_secs = msg->ihnode->ihn_Millis / 1000;
1391 time_ext->treq.tr_time.tv_micro =
1392 (msg->ihnode->ihn_Millis % 1000) * 1000;
1393 time_ext->ihn = msg->ihnode;
1394 SendIO((struct IORequest *)time_ext);
1397 else
1398 AddTail((struct List *)&data->app_IHList,
1399 (struct Node *)msg->ihnode);
1400 return TRUE;
1404 /**************************************************************************
1405 MUIM_Application_RemInputHandler
1406 **************************************************************************/
1407 static IPTR Application__MUIM_RemInputHandler(struct IClass *cl,
1408 Object *obj, struct MUIP_Application_RemInputHandler *msg)
1410 //struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1411 if (msg->ihnode->ihn_Flags & MUIIHNF_TIMER)
1413 struct timerequest_ext *time_ext =
1414 (struct timerequest_ext *)msg->ihnode->ihn_Node.mln_Pred;
1415 if (!CheckIO((struct IORequest *)time_ext))
1416 AbortIO((struct IORequest *)time_ext);
1417 WaitIO((struct IORequest *)time_ext);
1418 FreeVec(time_ext);
1420 else
1421 Remove((struct Node *)msg->ihnode);
1423 return TRUE;
1427 void _zune_window_message(struct IntuiMessage *imsg); /* from window.c */
1430 * MUIM_Application_InputBuffered : process all pending events
1432 static IPTR Application__MUIM_InputBuffered(struct IClass *cl, Object *obj,
1433 struct MUIP_Application_InputBuffered *msg)
1435 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1436 struct IntuiMessage *imsg;
1438 /* process all pushed methods */
1439 while (application_do_pushed_method(data))
1442 imsg =
1443 (struct IntuiMessage *)GetMsg(data->app_GlobalInfo.mgi_WindowsPort);
1444 if (imsg != NULL)
1446 /* Let window object process message */
1447 _zune_window_message(imsg); /* will reply the message */
1449 return TRUE;
1452 /**************************************************************************
1453 MUIM_Application_NewInput : application main loop
1454 **************************************************************************/
1455 static IPTR Application__MUIM_NewInput(struct IClass *cl, Object *obj,
1456 struct MUIP_Application_NewInput *msg)
1458 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1459 struct RIDNode *rid;
1460 ULONG retval = 0;
1461 ULONG signal, signalmask;
1462 ULONG handler_mask = 0; /* the mask of the signal handlers */
1463 struct MinNode *mn;
1465 //struct MinNode ihn_Node;
1467 signal = *msg->signal;
1469 /* process all pushed methods */
1470 while (application_do_pushed_method(data))
1471 /* nothing */ ;
1473 /* query the signal for the handlers */
1474 for (mn = data->app_IHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
1476 struct MUI_InputHandlerNode *ihn;
1477 ihn = (struct MUI_InputHandlerNode *)mn;
1478 handler_mask |= ihn->ihn_Signals;
1481 signalmask = (1L << data->app_GlobalInfo.mgi_WindowsPort->mp_SigBit)
1482 | (1L << data->app_TimerPort->mp_SigBit) | handler_mask;
1484 if (data->app_Broker)
1485 signalmask |= (1L << data->app_BrokerPort->mp_SigBit);
1487 if (data->app_RexxPort)
1488 signalmask |= (1L << data->app_RexxPort->mp_SigBit);
1490 if (data->app_AppPort)
1491 signalmask |= (1L << data->app_AppPort->mp_SigBit);
1493 if (signal == 0)
1495 /* Stupid app which (always) passes 0 in signals. It's impossible to
1496 know which signals were really set as the app will already have
1497 called Wait() which has cleared the task's tc_SigRecvd. So assume
1498 the window, timer, and broker signals all to be set. Also all of
1499 the inputhandler signals (MUI does that too). */
1501 signal = signalmask;
1504 if (signal & signalmask)
1506 if (signal & (1L << data->app_GlobalInfo.mgi_WindowsPort->
1507 mp_SigBit))
1509 struct IntuiMessage *imsg;
1510 /* process all pushed methods */
1512 while ((imsg =
1513 (struct IntuiMessage *)GetMsg(data->app_GlobalInfo.
1514 mgi_WindowsPort)))
1516 /* Let window object process message */
1517 _zune_window_message(imsg); /* will reply the message */
1521 if (signal & (1L << data->app_TimerPort->mp_SigBit))
1523 struct timerequest_ext *time_ext;
1524 struct Node *n;
1525 struct List list;
1526 NewList(&list);
1528 /* At first we fetch all messages from the message port and store
1529 ** them in a list, we use the node of the Message here */
1530 while ((time_ext =
1531 (struct timerequest_ext *)GetMsg(data->app_TimerPort)))
1532 AddTail(&list, (struct Node *)time_ext);
1534 /* Now we proccess the list and resend the timer io, no loop can
1535 ** happen. We use RemHead() because the handler can remove it
1536 ** itself and so a FreeVec() could happen in
1537 ** MUIM_Application_RemInputHandler which would destroy the
1538 ** ln->Succ of course */
1539 while ((n = RemHead(&list)))
1541 struct timerequest_ext *time_ext =
1542 (struct timerequest_ext *)n;
1543 struct MUI_InputHandlerNode *ihn = time_ext->ihn;
1544 time_ext->treq.tr_time.tv_secs =
1545 time_ext->ihn->ihn_Millis / 1000;
1546 time_ext->treq.tr_time.tv_micro =
1547 (time_ext->ihn->ihn_Millis % 1000) * 1000;
1548 SendIO((struct IORequest *)&time_ext->treq);
1549 DoMethod(ihn->ihn_Object, ihn->ihn_Method);
1553 if (data->app_BrokerPort
1554 && (signal & (1L << data->app_BrokerPort->mp_SigBit)))
1556 CxMsg *msg;
1558 while ((msg = (CxMsg *) GetMsg(data->app_BrokerPort)))
1560 switch (CxMsgType(msg))
1562 case CXM_COMMAND:
1563 switch (CxMsgID(msg))
1565 case CXCMD_DISABLE:
1566 set(obj, MUIA_Application_Active, FALSE);
1567 break;
1569 case CXCMD_ENABLE:
1570 set(obj, MUIA_Application_Active, TRUE);
1571 break;
1573 case CXCMD_APPEAR:
1574 case CXCMD_DISAPPEAR:
1575 /* No default handling - application needs to be in
1576 * control of this */
1577 break;
1579 case CXCMD_KILL:
1580 SetSignal(SIGBREAKF_CTRL_C, SIGBREAKF_CTRL_C);
1581 break;
1583 break;
1586 if (data->app_BrokerHook)
1588 CallHookPkt(data->app_BrokerHook, obj, msg);
1591 ReplyMsg((struct Message *)msg);
1595 if (data->app_RexxPort
1596 && (signal & (1L << data->app_RexxPort->mp_SigBit)))
1599 D(bug("[MUI] Got Rexx message!\n"));
1600 struct Message *msg;
1601 while ((msg = GetMsg(data->app_RexxPort)))
1603 ReplyMsg(msg);
1607 if (data->app_AppPort
1608 && (signal & (1L << data->app_AppPort->mp_SigBit)))
1610 struct AppMessage *appmsg;
1611 while ((appmsg =
1612 (struct AppMessage *)GetMsg(data->app_AppPort)))
1614 if ((appmsg->am_Type == AMTYPE_APPICON)
1615 && (appmsg->am_NumArgs == 0)
1616 && (appmsg->am_ArgList == NULL)
1617 && (XGET(obj, MUIA_Application_Iconified) == TRUE))
1619 /* Reply before removing AppIcon */
1620 ReplyMsg((struct Message *)appmsg);
1621 set(obj, MUIA_Application_Iconified, FALSE);
1622 continue;
1625 ReplyMsg((struct Message *)appmsg);
1629 if (signal & handler_mask)
1631 for (mn = data->app_IHList.mlh_Head; mn->mln_Succ;
1632 mn = mn->mln_Succ)
1634 struct MUI_InputHandlerNode *ihn;
1635 ihn = (struct MUI_InputHandlerNode *)mn;
1636 if (signal & ihn->ihn_Signals)
1637 DoMethod(ihn->ihn_Object, ihn->ihn_Method);
1642 /* process all pushed methods - again */
1643 while (application_do_pushed_method(data))
1644 /* nothing */ ;
1646 *msg->signal = signalmask;
1648 /* set return code */
1649 if ((rid =
1650 (struct RIDNode *)RemHead((struct List *)&data->
1651 app_ReturnIDQueue)))
1653 retval = rid->rid_Value;
1654 DeleteRIDNode(data, rid);
1655 return retval;
1657 return 0;
1660 /**************************************************************************
1661 MUIM_Application_Input : application main loop
1662 This method shouldn't be used in any new program. As it polls all signals.
1663 **************************************************************************/
1664 static IPTR Application__MUIM_Input(struct IClass *cl, Object *obj,
1665 struct MUIP_Application_Input *msg)
1667 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1668 ULONG signal = 0, handler_mask = 0;
1669 struct MinNode *mn;
1671 /* query the signal for the handlers */
1672 for (mn = data->app_IHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
1674 struct MUI_InputHandlerNode *ihn;
1675 ihn = (struct MUI_InputHandlerNode *)mn;
1676 handler_mask |= ihn->ihn_Flags;
1679 signal = (1L << data->app_GlobalInfo.mgi_WindowsPort->mp_SigBit)
1680 | (1L << data->app_TimerPort->mp_SigBit) | handler_mask;
1682 if (data->app_RexxPort)
1683 signal |= (1L << data->app_RexxPort->mp_SigBit);
1685 if (data->app_AppPort)
1686 signal |= (1L << data->app_AppPort->mp_SigBit);
1689 *msg->signal = signal;
1690 return Application__MUIM_NewInput(cl, obj, (APTR) msg);
1693 /**************************************************************************
1694 MUIM_Application_PushMethod: Add a method in the method FIFO. Will
1695 be executed in the next event loop.
1696 **************************************************************************/
1697 static IPTR Application__MUIM_PushMethod(struct IClass *cl, Object *obj,
1698 struct MUIP_Application_PushMethod *msg)
1700 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1701 struct MQNode *mq;
1702 LONG i;
1703 IPTR *m = (IPTR *) & msg->count; /* FIXME: breaks on 64-bit BigEndian systems */
1704 LONG count;
1706 count = msg->count & 0xf; /* MUI4 uses count to pass additional info */
1708 mq = CreateMQNode(count);
1709 if (!mq)
1710 return 0;
1711 mq->mq_Dest = msg->dest;
1713 /* fill msg */
1714 for (i = 0; i < count; i++)
1715 mq->mq_Msg[i] = *(m + 1 + i);
1717 /* enqueue method */
1718 ObtainSemaphore(&data->app_MethodSemaphore);
1719 AddTail((struct List *)&data->app_MethodQueue, (struct Node *)mq);
1720 ReleaseSemaphore(&data->app_MethodSemaphore);
1722 /* CHECKME: to wake task up as soon as possible! */
1723 Signal(data->app_Task,
1724 1L << data->app_GlobalInfo.mgi_WindowsPort->mp_SigBit);
1726 return TRUE;
1731 * MUIM_Application_ReturnID : Tell MUI to return the given id with
1732 * the next call to MUIM_Application_NewInput. kinda obsolete :)
1734 static IPTR Application__MUIM_ReturnID(struct IClass *cl, Object *obj,
1735 struct MUIP_Application_ReturnID *msg)
1737 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1738 struct RIDNode *rid;
1741 if (!data->app_RIDMemChunk)
1743 data->app_RIDMemChunk =
1744 g_mem_chunk_create(struct RIDNode, 10, G_ALLOC_AND_FREE);
1747 rid = CreateRIDNode(data, msg->retid);
1748 if (!rid)
1749 return FALSE;
1750 AddTail((struct List *)&data->app_ReturnIDQueue, (struct Node *)rid);
1751 return TRUE;
1756 * MUIM_FindUData : tests if the MUIA_UserData of the object
1757 * contains the given <udata> and returns the object pointer in this case.
1759 static IPTR Application__MUIM_FindUData(struct IClass *cl, Object *obj,
1760 struct MUIP_FindUData *msg)
1762 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1764 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
1765 return (IPTR) obj;
1767 return DoMethodA(data->app_WindowFamily, (Msg) msg);
1772 * MUIM_GetUData : This method tests if the MUIA_UserData of the object
1773 * contains the given <udata> and gets <attr> to <storage> for itself
1774 * in this case.
1776 static IPTR Application__MUIM_GetUData(struct IClass *cl, Object *obj,
1777 struct MUIP_GetUData *msg)
1779 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1781 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
1783 get(obj, msg->attr, msg->storage);
1784 return TRUE;
1786 return DoMethodA(data->app_WindowFamily, (Msg) msg);
1791 * MUIM_SetUData : This method tests if the MUIA_UserData of the object
1792 * contains the given <udata> and sets <attr> to <val> for itself in this case.
1794 static IPTR Application__MUIM_SetUData(struct IClass *cl, Object *obj,
1795 struct MUIP_SetUData *msg)
1797 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1799 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
1800 set(obj, msg->attr, msg->val);
1802 DoMethodA(data->app_WindowFamily, (Msg) msg);
1803 return TRUE;
1808 * MUIM_SetUDataOnce : This method tests if the MUIA_UserData of the object
1809 * contains the given <udata> and sets <attr> to <val> for itself in this case.
1811 static IPTR Application__MUIM_SetUDataOnce(struct IClass *cl, Object *obj,
1812 struct MUIP_SetUDataOnce *msg)
1814 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1816 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
1818 set(obj, msg->attr, msg->val);
1819 return TRUE;
1821 return DoMethodA(data->app_WindowFamily, (Msg) msg);
1825 /**************************************************************************
1826 MUIM_Application_AboutMUI: brought up the about window, centered on refwindow
1827 **************************************************************************/
1828 static IPTR Application__MUIM_AboutMUI(struct IClass *cl, Object *obj,
1829 struct MUIP_Application_AboutMUI *msg)
1831 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1833 if (!data->app_AboutWin)
1835 data->app_AboutWin = AboutmuiObject,
1836 msg->refwindow ? MUIA_Window_RefWindow : TAG_IGNORE,
1837 msg->refwindow, MUIA_Window_LeftEdge,
1838 MUIV_Window_LeftEdge_Centered, MUIA_Window_TopEdge,
1839 MUIV_Window_TopEdge_Centered, MUIA_Aboutmui_Application, obj,
1840 End;
1841 if (!data->app_AboutWin)
1842 return 0;
1843 DoMethod(data->app_AboutWin, MUIM_Notify, MUIA_Window_CloseRequest,
1844 TRUE, (IPTR) obj, 3, MUIM_WriteLong, 0L,
1845 (IPTR) & data->app_AboutWin);
1846 } /* if (!data->app_AboutWin) */
1848 if (data->app_AboutWin)
1851 set(data->app_AboutWin, MUIA_Window_Open, TRUE);
1853 return 0;
1856 static IPTR Application__MUIM_SetConfigdata(struct IClass *cl, Object *obj,
1857 struct MUIP_Application_SetConfigdata *msg)
1859 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1860 struct MinList *children = NULL;
1861 Object *cstate;
1862 Object *child;
1864 get(data->app_WindowFamily, MUIA_Family_List, &children);
1865 if (children)
1867 cstate = (Object *) children->mlh_Head;
1868 if ((child = NextObject(&cstate)))
1870 D(bug("closing window %p\n", child));
1872 set(child, MUIA_Window_Open, FALSE);
1876 if (data->app_GlobalInfo.mgi_Configdata)
1877 MUI_DisposeObject(data->app_GlobalInfo.mgi_Configdata);
1878 data->app_GlobalInfo.mgi_Configdata = msg->configdata;
1879 get(data->app_GlobalInfo.mgi_Configdata, MUIA_Configdata_ZunePrefs,
1880 &data->app_GlobalInfo.mgi_Prefs);
1882 DoMethod(obj, MUIM_Application_PushMethod, (IPTR) obj, 1,
1883 MUIM_Application_OpenWindows);
1884 return 0;
1888 /* MUIM_Application_OpenWindows
1889 * Opens all windows of an application
1891 static IPTR Application__MUIM_OpenWindows(struct IClass *cl, Object *obj,
1892 struct MUIP_Application_OpenWindows *msg)
1894 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1895 struct MinList *children = NULL;
1896 Object *cstate;
1897 Object *child;
1899 get(data->app_WindowFamily, MUIA_Family_List, &children);
1900 if (!children)
1901 return 0;
1903 cstate = (Object *) children->mlh_Head;
1904 if ((child = NextObject(&cstate)))
1906 set(child, MUIA_Window_Open, TRUE);
1908 return 0;
1912 static IPTR Application__MUIM_OpenConfigWindow(struct IClass *cl,
1913 Object *obj, struct MUIP_Application_OpenConfigWindow *msg)
1915 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1916 struct TagItem tags[] = {
1917 {SYS_Asynch, FALSE},
1918 {SYS_Input, 0},
1919 {SYS_Output, 0},
1920 {NP_StackSize, AROS_STACKSIZE},
1921 {TAG_DONE}
1923 char cmd[255];
1925 snprintf(cmd, 255, "sys:prefs/Zune %s %ld",
1926 data->app_Base ? data->app_Base : (STRPTR) "", (long)obj);
1928 if (SystemTagList(cmd, tags) == -1)
1930 return 0;
1932 Delay(50);
1934 if (data->app_Base)
1936 snprintf(cmd, 255, "ENV:zune/%s.prefs", data->app_Base);
1937 DoMethod(data->app_GlobalInfo.mgi_Configdata, MUIM_Configdata_Load,
1938 (IPTR) cmd);
1941 return 1;
1944 static IPTR Application__MUIM_Execute(Class *CLASS, Object *self,
1945 Msg message)
1947 IPTR signals = 0L;
1949 while
1950 (DoMethod(self, MUIM_Application_NewInput, (IPTR) & signals)
1951 != MUIV_Application_ReturnID_Quit)
1953 if (signals)
1955 signals = Wait(signals | SIGBREAKF_CTRL_C);
1956 if (signals & SIGBREAKF_CTRL_C)
1957 break;
1961 return 0;
1965 static IPTR Application__MUIM_UpdateMenus(struct IClass *cl, Object *obj,
1966 Msg message)
1968 struct List *wlist = NULL;
1969 APTR wstate;
1970 Object *curwin;
1972 get(obj, MUIA_Application_WindowList, &wlist);
1974 if (wlist)
1976 wstate = wlist->lh_Head;
1977 while ((curwin = NextObject(&wstate)))
1979 DoMethod(curwin, MUIM_Window_UpdateMenu);
1983 return 0;
1986 static IPTR Application__MUIM_Load(struct IClass *cl, Object *obj,
1987 struct MUIP_Application_Load *message)
1989 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1990 struct IFFHandle *iff;
1991 char name[1024];
1992 BPTR fh;
1993 Object *dataspace;
1994 struct MinList *children = NULL;
1995 Object *cstate;
1996 Object *child;
1998 if (!data->app_Base)
1999 return 0;
2001 dataspace = MUI_NewObject(MUIC_Dataspace, TAG_DONE);
2002 if (!dataspace)
2003 return 0;
2005 if (message->name == MUIV_Application_Load_ENV)
2006 snprintf(name, sizeof(name), "ENV:Zune/%s.cfg", data->app_Base);
2007 else if (message->name == MUIV_Application_Load_ENVARC)
2008 snprintf(name, sizeof(name), "ENVARC:Zune/%s.cfg", data->app_Base);
2009 else
2010 strncpy(name, message->name, sizeof(name));
2012 fh = Open(name, MODE_OLDFILE);
2013 if (fh)
2015 if ((iff = AllocIFF()))
2017 iff->iff_Stream = (IPTR) fh;
2019 InitIFFasDOS(iff);
2021 if (!OpenIFF(iff, IFFF_READ))
2023 if (!StopChunk(iff, ID_PREF, ID_MUIO))
2025 if (!ParseIFF(iff, IFFPARSE_SCAN))
2027 DoMethod(dataspace, MUIM_Dataspace_ReadIFF, iff,
2028 ID_PREF, ID_MUIO);
2032 CloseIFF(iff);
2034 FreeIFF(iff);
2036 Close(fh);
2039 get(data->app_WindowFamily, MUIA_Family_List, &children);
2040 cstate = (Object *) children->mlh_Head;
2041 while ((child = NextObject(&cstate)))
2043 DoMethod(child, MUIM_Import, dataspace);
2046 MUI_DisposeObject(dataspace);
2048 return 0;
2051 static IPTR Application__MUIM_Save(struct IClass *cl, Object *obj,
2052 struct MUIP_Application_Save *message)
2054 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
2055 struct IFFHandle *iff;
2056 char name[1024];
2057 BPTR fh;
2058 Object *dataspace;
2059 struct MinList *children = NULL;
2060 Object *cstate;
2061 Object *child;
2063 if (!data->app_Base)
2064 return 0;
2066 dataspace = MUI_NewObject(MUIC_Dataspace, TAG_DONE);
2067 if (!dataspace)
2068 return 0;
2070 get(data->app_WindowFamily, MUIA_Family_List, &children);
2071 cstate = (Object *) children->mlh_Head;
2072 while ((child = NextObject(&cstate)))
2074 DoMethod(child, MUIM_Export, dataspace);
2077 if (message->name == MUIV_Application_Save_ENV)
2078 snprintf(name, sizeof(name), "ENV:Zune/%s.cfg", data->app_Base);
2079 else if (message->name == MUIV_Application_Save_ENVARC)
2080 snprintf(name, sizeof(name), "ENVARC:Zune/%s.cfg", data->app_Base);
2081 else
2082 strncpy(name, message->name, sizeof(name));
2084 fh = Open(name, MODE_NEWFILE);
2085 if (fh)
2087 if ((iff = AllocIFF()))
2089 iff->iff_Stream = (IPTR) fh;
2091 InitIFFasDOS(iff);
2093 if (!OpenIFF(iff, IFFF_WRITE))
2095 if (!PushChunk(iff, ID_PREF, ID_FORM, IFFSIZE_UNKNOWN))
2097 if (!PushChunk(iff, ID_PREF, ID_PRHD,
2098 sizeof(struct FilePrefHeader)))
2100 struct FilePrefHeader head;
2102 head.ph_Version = PHV_CURRENT;
2103 head.ph_Type = 0;
2104 head.ph_Flags[0] =
2105 head.ph_Flags[1] =
2106 head.ph_Flags[2] = head.ph_Flags[3] = 0;
2108 if (WriteChunkBytes(iff, &head,
2109 sizeof(head)) == sizeof(head))
2111 PopChunk(iff);
2112 DoMethod(dataspace, MUIM_Dataspace_WriteIFF,
2113 iff, ID_PREF, ID_MUIO);
2115 else
2117 PopChunk(iff);
2120 PopChunk(iff);
2122 CloseIFF(iff);
2124 FreeIFF(iff);
2126 Close(fh);
2129 MUI_DisposeObject(dataspace);
2131 return 0;
2135 * The class dispatcher
2137 BOOPSI_DISPATCHER(IPTR, Application_Dispatcher, cl, obj, msg)
2139 switch (msg->MethodID)
2141 case OM_NEW:
2142 return Application__OM_NEW(cl, obj, (struct opSet *)msg);
2143 case OM_DISPOSE:
2144 return Application__OM_DISPOSE(cl, obj, msg);
2145 case OM_SET:
2146 return Application__OM_SET(cl, obj, (struct opSet *)msg);
2147 case OM_GET:
2148 return Application__OM_GET(cl, obj, (struct opGet *)msg);
2149 case OM_ADDMEMBER:
2150 return Application__OM_ADDMEMBER(cl, obj, (APTR) msg);
2151 case OM_REMMEMBER:
2152 return Application__OM_REMMEMBER(cl, obj, (APTR) msg);
2153 case MUIM_Application_AddInputHandler:
2154 return Application__MUIM_AddInputHandler(cl, obj, (APTR) msg);
2155 case MUIM_Application_RemInputHandler:
2156 return Application__MUIM_RemInputHandler(cl, obj, (APTR) msg);
2157 case MUIM_Application_Input:
2158 return Application__MUIM_Input(cl, obj, (APTR) msg);
2159 case MUIM_Application_InputBuffered:
2160 return Application__MUIM_InputBuffered(cl, obj, (APTR) msg);
2161 case MUIM_Application_NewInput:
2162 return Application__MUIM_NewInput(cl, obj, (APTR) msg);
2163 case MUIM_Application_PushMethod:
2164 return Application__MUIM_PushMethod(cl, obj, (APTR) msg);
2165 case MUIM_Application_ReturnID:
2166 return Application__MUIM_ReturnID(cl, obj, (APTR) msg);
2167 case MUIM_FindUData:
2168 return Application__MUIM_FindUData(cl, obj, (APTR) msg);
2169 case MUIM_GetUData:
2170 return Application__MUIM_GetUData(cl, obj, (APTR) msg);
2171 case MUIM_SetUData:
2172 return Application__MUIM_SetUData(cl, obj, (APTR) msg);
2173 case MUIM_SetUDataOnce:
2174 return Application__MUIM_SetUDataOnce(cl, obj, (APTR) msg);
2175 case MUIM_Application_AboutMUI:
2176 return Application__MUIM_AboutMUI(cl, obj, (APTR) msg);
2177 case MUIM_Application_SetConfigdata:
2178 return Application__MUIM_SetConfigdata(cl, obj, (APTR) msg);
2179 case MUIM_Application_OpenWindows:
2180 return Application__MUIM_OpenWindows(cl, obj, (APTR) msg);
2181 case MUIM_Application_OpenConfigWindow:
2182 return Application__MUIM_OpenConfigWindow(cl, obj, (APTR) msg);
2183 case MUIM_Application_Execute:
2184 return Application__MUIM_Execute(cl, obj, msg);
2185 case MUIM_Application_UpdateMenus:
2186 return Application__MUIM_UpdateMenus(cl, obj, msg);
2187 case MUIM_Application_Load:
2188 return Application__MUIM_Load(cl, obj, (APTR) msg);
2189 case MUIM_Application_Save:
2190 return Application__MUIM_Save(cl, obj, (APTR) msg);
2193 return (DoSuperMethodA(cl, obj, msg));
2195 BOOPSI_DISPATCHER_END
2197 * Class descriptor.
2199 const struct __MUIBuiltinClass _MUI_Application_desc =
2201 MUIC_Application,
2202 MUIC_Notify,
2203 sizeof(struct MUI_ApplicationData),
2204 (void *) Application_Dispatcher