revert between 56095 -> 55830 in arch
[AROS.git] / workbench / libs / muimaster / classes / application.c
blob4c5b267bb89e7f8330993fb9e8f95a5f74f640e6
1 /*
2 Copyright © 1999, David Le Corfec.
3 Copyright © 2002-2015, The AROS Development Team.
4 All rights reserved.
6 $Id$
7 */
9 #include <exec/types.h>
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
96 //together
97 struct windowpos winpos[MAXWINS];
98 struct MsgPort *app_RexxPort;
99 struct RexxMsg *app_RexxMsg;
100 struct Hook *app_RexxHook;
101 struct MUI_Command *app_Commands;
102 STRPTR app_RexxString;
103 BOOL app_UseRexx;
104 struct MsgPort *app_AppPort; /* Port for AppIcon/AppMenu/AppWindow */
105 struct AppIcon *app_AppIcon;
106 struct DiskObject *app_DiskObject; /* This is only pointer to
107 * client-managed object */
108 struct DiskObject *app_DefaultDiskObject; /* This is complete
109 * object managed by
110 * the class */
113 struct timerequest_ext
115 struct timerequest treq;
116 struct MUI_InputHandlerNode *ihn;
120 * Application class is the master class for all
121 * MUI applications. It serves as a kind of anchor
122 * for all input, either coming from the user or
123 * somewhere from the system, e.g. commodities
124 * or ARexx messages. (hemm forget theses last 2 for Zune :)
126 * An application can have any number of sub windows,
127 * these windows are the children of the application.
128 * (FYI, it delegates child handling to a Family object).
132 MUIA_Application_Active [ISG] done
133 MUIA_Application_Author [I.G] done
134 MUIA_Application_Base [I.G] done
135 MUIA_Application_Broker [..G] done
136 MUIA_Application_BrokerHook [ISG] done
137 MUIA_Application_BrokerPort [..G] done
138 MUIA_Application_BrokerPri [I.G] done
139 MUIA_Application_Commands [ISG] needs Arexx
140 MUIA_Application_Copyright [I.G] done
141 MUIA_Application_Description [I.G] done
142 MUIA_Application_DiskObject [ISG] done
143 MUIA_Application_DoubleStart [..G] not triggered yet (todo)
144 MUIA_Application_DropObject [IS.] todo
145 MUIA_Application_ForceQuit [..G] not triggered yet
146 MUIA_Application_HelpFile [ISG] unused/dummy
147 MUIA_Application_Iconified [.SG] done
148 MUIA_Application_Menu [I.G] unimplemented (OBSOLETE)
149 MUIA_Application_MenuAction [..G] done
150 MUIA_Application_MenuHelp [..G] todo (ditto)
151 MUIA_Application_Menustrip [I..] done
152 MUIA_Application_RexxHook [ISG] needs Arexx
153 MUIA_Application_RexxMsg [..G] needs Arexx
154 MUIA_Application_RexxString [.S.] needs Arexx
155 MUIA_Application_SingleTask [I..] done
156 MUIA_Application_Sleep [.S.] todo
157 MUIA_Application_Title [I.G] done
158 MUIA_Application_UseCommodities [I..] done
159 MUIA_Application_UseRexx [I..] done
160 MUIA_Application_Version [I.G] done
161 MUIA_Application_Window [I..] done
162 MUIA_Application_WindowList [..G] done
164 OM_ADDMEMBER done
165 OM_REMMEMBER done
166 MUIM_Application_AboutMUI todo
167 MUIM_Application_AddInputHandler done ?
168 MUIM_Application_CheckRefresh done
169 MUIM_Application_GetMenuCheck OBSOLETE
170 MUIM_Application_GetMenuState OBSOLETE
171 MUIM_Application_Input OBSOLETE
172 MUIM_Application_InputBuffered todo
173 MUIM_Application_Load
174 MUIM_Application_NewInput done
175 MUIM_Application_OpenConfigWindow
176 MUIM_Application_PushMethod
177 MUIM_Application_RemInputHandler done ?
178 MUIM_Application_ReturnID done
179 MUIM_Application_Save
180 MUIM_Application_SetConfigItem
181 MUIM_Application_SetMenuCheck
182 MUIM_Application_SetMenuState
183 MUIM_Application_ShowHelp
185 Notify.mui/MUIM_FindUData done
186 Notify.mui/MUIM_GetUData done
187 Notify.mui/MUIM_SetUData done
188 Notify.mui/MUIM_SetUDataOnce done
191 static const int __version = 1;
192 static const int __revision = 1;
196 * MethodQueueNode
198 struct MQNode
200 struct MinNode mq_Node;
201 Object *mq_Dest;
202 LONG mq_Count;
203 IPTR *mq_Msg;
207 * FilePrefHeader
209 struct FilePrefHeader
211 UBYTE ph_Version;
212 UBYTE ph_Type;
213 UBYTE ph_Flags[4];
216 #define ID_MUIO MAKE_ID('M','U','I','O')
219 * Allocates an MethodQueue Method
221 static struct MQNode *CreateMQNode(LONG count)
223 struct MQNode *mq;
225 mq = (struct MQNode *)mui_alloc(sizeof(struct MQNode) +
226 (count * sizeof(IPTR)));
227 if (!mq)
228 return NULL;
230 mq->mq_Count = count;
231 mq->mq_Msg = (IPTR *) (((char *)mq) + sizeof(struct MQNode));
232 return mq;
236 * Free an IQ Method got from CreateIQMethod()
238 static void DeleteMQNode(struct MQNode *mq)
240 mui_free(mq);
245 * Queue of Return IDs
247 struct RIDNode
249 struct MinNode rid_Node;
250 ULONG rid_Value;
254 static struct RIDNode *CreateRIDNode(struct MUI_ApplicationData *data,
255 ULONG retid)
257 struct RIDNode *rid;
259 if ((rid = mui_alloc_struct(struct RIDNode)))
261 rid->rid_Value = retid;
263 return rid;
267 static void DeleteRIDNode(struct MUI_ApplicationData *data,
268 struct RIDNode *rid)
270 mui_free(rid);
274 /**************************************************************************
275 Process a pushed method.
276 **************************************************************************/
277 static BOOL application_do_pushed_method(struct MUI_ApplicationData *data)
279 struct MQNode *mq;
281 ObtainSemaphore(&data->app_MethodSemaphore);
283 if ((mq = (struct MQNode *)RemHead((struct List *)&data->app_MethodQueue)))
285 ReleaseSemaphore(&data->app_MethodSemaphore);
287 DoMethodA(mq->mq_Dest, (Msg) mq->mq_Msg);
288 DeleteMQNode(mq);
289 return TRUE;
291 ReleaseSemaphore(&data->app_MethodSemaphore);
292 return FALSE;
295 static Object *find_application_by_base(struct IClass *cl, Object *obj,
296 STRPTR base)
298 struct MUIMasterBase_intern *intZuneBase = (struct MUIMasterBase_intern *)MUIMasterBase;
299 struct TrackingNode *tn;
300 Object *retval = NULL;
302 ObtainSemaphore(&intZuneBase->ZuneSemaphore);
303 ForeachNode(&intZuneBase->Applications, tn)
305 STRPTR tn_base = "";
307 get(tn->tn_Application, MUIA_Application_Base, &tn_base);
309 if (tn_base && (strcmp(base, tn_base)) == 0)
311 retval = tn->tn_Application;
312 break;
315 ReleaseSemaphore(&intZuneBase->ZuneSemaphore);
317 return retval;
320 /**************************************************************************
321 OM_NEW
322 **************************************************************************/
323 static IPTR Application__OM_NEW(struct IClass *cl, Object *obj,
324 struct opSet *msg)
326 struct MUI_ApplicationData *data;
327 struct TagItem *tags, *tag;
328 BOOL bad_childs = FALSE;
330 obj = (Object *) DoSuperMethodA(cl, obj, (Msg) msg);
331 if (!obj)
332 return FALSE;
334 /* Initial local instance data */
335 data = INST_DATA(cl, obj);
337 /* init input handler list */
338 NewList((struct List *)&(data->app_IHList));
340 /* init input queue */
341 NewList((struct List *)&(data->app_MethodQueue));
343 /* init return ids queue */
344 NewList((struct List *)&(data->app_ReturnIDQueue));
346 /* window list */
347 data->app_WindowFamily = MUI_NewObjectA(MUIC_Family, NULL);
348 if (!data->app_WindowFamily)
350 CoerceMethod(cl, obj, OM_DISPOSE);
351 return 0;
354 data->app_GlobalInfo.mgi_ApplicationObject = obj;
355 if (!(data->app_GlobalInfo.mgi_WindowsPort = CreateMsgPort()))
357 CoerceMethod(cl, obj, OM_DISPOSE);
358 return 0;
361 data->app_Task = FindTask(NULL);
363 /* Parse prefs */
364 data->app_SingleTask =
365 (BOOL) GetTagData(MUIA_Application_SingleTask, FALSE,
366 msg->ops_AttrList);
367 data->app_Base =
368 (STRPTR) GetTagData(MUIA_Application_Base, (IPTR) "UNNAMED",
369 msg->ops_AttrList);
370 if (!data->app_Base || strpbrk(data->app_Base, ":/()#?*,"))
372 data->app_Base = NULL; /* don't remove */
373 CoerceMethod(cl, obj, OM_DISPOSE);
375 return 0;
378 if (!data->app_SingleTask)
380 /* must append .1, .2, ... to the base name */
381 LONG i;
382 char portname[255];
384 for (i = 1; i < 1000; i++)
386 snprintf(portname, 255, "%s.%d", data->app_Base, (int)i);
387 if (!find_application_by_base(cl, obj, portname))
388 break;
390 data->app_Base = StrDup(portname);
392 else
394 Object *other_app;
396 ObtainSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
397 if ((other_app = find_application_by_base(cl, obj, data->app_Base)))
399 //FIXME "Is calling MUIM_Application_PushMethod on an alien
400 //application object safe?"
401 DoMethod(other_app, MUIM_Application_PushMethod,
402 (IPTR) other_app, 3, MUIM_Set, MUIA_Application_DoubleStart,
403 TRUE);
404 data->app_Base = NULL;
406 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
408 data->app_Base = StrDup(data->app_Base);
411 if (!data->app_Base)
413 CoerceMethod(cl, obj, OM_DISPOSE);
414 return 0;
417 data->app_GlobalInfo.mgi_Configdata =
418 MUI_NewObject(MUIC_Configdata, MUIA_Configdata_Application, obj,
419 TAG_DONE);
420 if (!data->app_GlobalInfo.mgi_Configdata)
422 CoerceMethod(cl, obj, OM_DISPOSE);
423 return 0;
425 get(data->app_GlobalInfo.mgi_Configdata, MUIA_Configdata_ZunePrefs,
426 &data->app_GlobalInfo.mgi_Prefs);
428 // D(bug("muimaster.library/application.c: Message Port created at 0x%lx\n",
429 // data->app_GlobalInfo.mgi_WindowPort));
431 /* Setup timer stuff */
432 if (!(data->app_TimerPort = CreateMsgPort()))
434 CoerceMethod(cl, obj, OM_DISPOSE);
435 return 0;
438 if (!(data->app_TimerReq =
439 (struct timerequest *)CreateIORequest(data->app_TimerPort,
440 sizeof(struct timerequest))))
442 CoerceMethod(cl, obj, OM_DISPOSE);
443 return 0;
446 if (OpenDevice(TIMERNAME, UNIT_VBLANK,
447 (struct IORequest *)data->app_TimerReq, 0))
449 CoerceMethod(cl, obj, OM_DISPOSE);
450 return 0;
453 InitSemaphore(&data->app_MethodSemaphore);
455 muiNotifyData(obj)->mnd_GlobalInfo = &data->app_GlobalInfo;
457 /* parse initial taglist */
459 data->app_Active = 1;
460 data->app_Title = "Unnamed";
461 data->app_Version = "Unnamed 0.0";
462 data->app_Description = "?";
464 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags));)
466 switch (tag->ti_Tag)
468 case MUIA_Application_Author:
469 data->app_Author = (STRPTR) tag->ti_Data;
470 break;
472 case MUIA_Application_Base:
473 /* moved before config parsing */
474 break;
476 case MUIA_Application_Copyright:
477 data->app_Copyright = (STRPTR) tag->ti_Data;
478 break;
480 case MUIA_Application_Description:
481 data->app_Description = (STRPTR) tag->ti_Data;
482 break;
484 case MUIA_Application_HelpFile:
485 data->app_HelpFile = (STRPTR) tag->ti_Data;
486 break;
488 case MUIA_Application_SingleTask:
489 /* moved before config parsing */
490 break;
492 case MUIA_Application_Title:
493 data->app_Title = (STRPTR) tag->ti_Data;
494 break;
496 case MUIA_Application_Version:
497 data->app_Version = (STRPTR) tag->ti_Data;
498 break;
500 case MUIA_Application_Version_Number:
501 data->app_Version_Number = (STRPTR) tag->ti_Data;
502 break;
504 case MUIA_Application_Version_Date:
505 data->app_Version_Date = (STRPTR) tag->ti_Data;
506 break;
508 case MUIA_Application_Version_Extra:
509 data->app_Version_Extra = (STRPTR) tag->ti_Data;
510 break;
512 case MUIA_Application_Window:
513 if (tag->ti_Data)
514 DoMethod(obj, OM_ADDMEMBER, tag->ti_Data);
515 else
516 bad_childs = TRUE;
517 break;
519 case MUIA_Application_Menustrip:
520 data->app_Menustrip = (Object *) tag->ti_Data;
521 break;
523 case MUIA_Application_BrokerPri:
524 data->app_BrokerPri = (BYTE) tag->ti_Data;
525 break;
527 case MUIA_Application_BrokerHook:
528 data->app_BrokerHook = (struct Hook *)tag->ti_Data;
529 break;
531 case MUIA_Application_Active:
532 data->app_Active = tag->ti_Data ? TRUE : FALSE;
533 break;
535 case MUIA_Application_UsedClasses:
537 STRPTR *list = (STRPTR *) tag->ti_Data;
538 if (!list)
539 break;
540 while (*list)
542 struct IClass *icl = MUI_GetClass(*list);
543 if (icl)
544 MUI_FreeClass(icl);
545 ++list;
548 break;
550 case MUIA_Application_UseRexx:
551 data->app_UseRexx = tag->ti_Data ? TRUE : FALSE;
552 break;
554 case MUIA_Application_Commands:
555 data->app_Commands = (struct MUI_Command *)tag->ti_Data;
556 break;
558 case MUIA_Application_RexxHook:
559 data->app_RexxHook = (struct Hook *)tag->ti_Data;
560 break;
562 case MUIA_Application_DiskObject:
563 data->app_DiskObject = (struct DiskObject *)tag->ti_Data;
564 break;
569 /* create MUIA_Application_Version if NULL */
570 if (data->app_Version == NULL
571 && data->app_Title != NULL && data->app_Version_Number != NULL)
573 STRPTR result = NULL;
574 ULONG length = 0;
576 /* Calculate length */
577 length = strlen("$VER: ") + strlen(data->app_Title) + 1 /* space */
578 + strlen(data->app_Version_Number) + 1 /* NULL */ ;
580 if (data->app_Version_Date != NULL)
582 length += 1 /* space */ + 1 /* ( */
583 + strlen(data->app_Version_Date) + 1 /* ) */ ;
586 if (data->app_Version_Extra != NULL)
588 length += 1 /* space */ + 1 /* [ */
589 + strlen(data->app_Version_Extra) + 1 /* ] */ ;
592 /* Allocate memory */
593 result = AllocVec(length, MEMF_ANY);
595 if (result != NULL)
597 result[0] = '\0';
599 /* Format string */
600 strlcat(result, "$VER: ", length);
601 strlcat(result, data->app_Title, length);
602 strlcat(result, " ", length);
603 strlcat(result, data->app_Version_Number, length);
605 if (data->app_Version_Date != NULL)
607 strlcat(result, " (", length);
608 strlcat(result, data->app_Version_Date, length);
609 strlcat(result, ")", length);
612 if (data->app_Version_Extra != NULL)
614 strlcat(result, " [", length);
615 strlcat(result, data->app_Version_Extra, length);
616 strlcat(result, "]", length);
619 data->app_Version = result;
620 data->app_VersionAllocated = TRUE;
625 if (bad_childs)
627 CoerceMethod(cl, obj, OM_DISPOSE);
628 return 0;
631 if (CxBase
632 && GetTagData(MUIA_Application_UseCommodities, TRUE,
633 msg->ops_AttrList))
635 data->app_BrokerPort = CreateMsgPort();
637 if (data->app_BrokerPort)
639 struct NewBroker nb;
641 nb.nb_Version = NB_VERSION;
642 nb.nb_Name =
643 data->app_Title ? data->app_Title : (STRPTR) "Unnamed";
644 nb.nb_Title =
645 data->app_Version ? data->app_Version : (STRPTR) "Unnamed";
646 nb.nb_Descr =
647 data->app_Description ? data->
648 app_Description : (STRPTR) "?";
649 nb.nb_Unique = 0;
650 nb.nb_Flags = COF_SHOW_HIDE;
651 nb.nb_Pri = data->app_BrokerPri;
652 nb.nb_Port = data->app_BrokerPort;
653 nb.nb_ReservedChannel = 0;
655 if (strncmp(nb.nb_Title, "$VER: ", 6) == 0)
656 nb.nb_Title += 6;
658 data->app_Broker = CxBroker(&nb, 0);
660 if (data->app_Broker)
662 if (data->app_Active)
663 ActivateCxObj(data->app_Broker, 1);
668 if (data->app_UseRexx)
670 data->app_RexxPort = CreateMsgPort();
671 if (data->app_RexxPort)
673 data->app_RexxPort->mp_Node.ln_Name = StrDup(data->app_Base);
674 if (data->app_RexxPort->mp_Node.ln_Name != NULL)
676 D(bug("[MUI] %s is using REXX!\n",
677 data->app_RexxPort->mp_Node.ln_Name));
678 char *i;
679 for (i = data->app_RexxPort->mp_Node.ln_Name; *i != '\0';
680 i++)
682 *i = toupper(*i);
684 AddPort(data->app_RexxPort);
686 else
688 DeleteMsgPort(data->app_RexxPort);
689 data->app_RexxPort = NULL;
694 if (data->app_Menustrip)
695 DoMethod(data->app_Menustrip, MUIM_ConnectParent, (IPTR) obj);
697 data->app_AppPort = CreateMsgPort();
698 data->app_GlobalInfo.mgi_AppPort = data->app_AppPort;
699 if (data->app_AppPort == NULL)
701 CoerceMethod(cl, obj, OM_DISPOSE);
702 return 0;
705 ObtainSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
706 data->app_TrackingNode.tn_Application = obj;
707 AddTail((struct List *)&MUIMB(MUIMasterBase)->Applications,
708 (struct Node *)&data->app_TrackingNode);
709 data->app_is_TNode_in_list = TRUE;
710 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
712 return (IPTR) obj;
717 /**************************************************************************
718 OM_DISPOSE
719 **************************************************************************/
720 static IPTR Application__OM_DISPOSE(struct IClass *cl, Object *obj,
721 Msg msg)
723 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
724 struct RIDNode *rid;
726 long positionmode;
727 if (data->app_Base)
729 char filename[255];
730 positionmode = data->app_GlobalInfo.mgi_Prefs->window_position;
731 if (positionmode >= 1)
733 snprintf(filename, 255, "ENV:zune/%s.prefs", data->app_Base);
734 DoMethod(data->app_GlobalInfo.mgi_Configdata,
735 MUIM_Configdata_Save, (IPTR) filename);
737 if (positionmode == 2)
739 snprintf(filename, 255, "ENVARC:zune/%s.prefs", data->app_Base);
740 DoMethod(data->app_GlobalInfo.mgi_Configdata,
741 MUIM_Configdata_Save, (IPTR) filename);
745 if (data->app_is_TNode_in_list)
747 ObtainSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
748 Remove((struct Node *)&data->app_TrackingNode);
749 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
752 if (data->app_WindowFamily)
754 struct MinList *children = NULL;
755 Object *cstate;
756 Object *child;
758 /* special loop because the next object may have been removed/freed by
759 * the previous. so restart from listhead each time.
761 while (1)
763 get(data->app_WindowFamily, MUIA_Family_List, &children);
764 if (children == NULL)
765 break;
767 cstate = (Object *) children->mlh_Head;
768 if ((child = NextObject(&cstate)))
770 D(bug("Application_Dispose(%p) : OM_REMMEMBER(%p)\n", obj,
771 child));
772 DoMethod(obj, OM_REMMEMBER, (IPTR) child);
773 D(bug("Application_Dispose(%p) : MUI_DisposeObject(%p)\n",
774 obj, child));
775 MUI_DisposeObject(child);
778 else
780 break;
783 MUI_DisposeObject(data->app_WindowFamily);
786 if (data->app_Menustrip)
787 MUI_DisposeObject(data->app_Menustrip);
789 if (data->app_VersionAllocated && data->app_Version != NULL)
791 FreeVec(data->app_Version);
794 /* free commodities stuff */
796 if (data->app_Broker)
798 DeleteCxObjAll(data->app_Broker);
801 if (data->app_BrokerPort)
803 struct Message *msg;
805 while ((msg = GetMsg(data->app_BrokerPort)))
807 ReplyMsg(msg);
810 DeleteMsgPort(data->app_BrokerPort);
813 /* free timer stuff */
814 if (data->app_TimerReq)
816 if (data->app_TimerReq->tr_node.io_Device)
818 while (data->app_TimerOutstanding)
820 if (Wait(1L << data->app_TimerPort->
821 mp_SigBit | 4096) & 4096)
822 break;
823 data->app_TimerOutstanding--;
825 CloseDevice((struct IORequest *)data->app_TimerReq);
827 DeleteIORequest((struct IORequest *)data->app_TimerReq);
829 DeleteMsgPort(data->app_TimerPort);
831 if (data->app_RexxPort)
833 struct Message *msg;
834 while ((msg = GetMsg(data->app_RexxPort)))
836 ReplyMsg(msg);
838 RemPort(data->app_RexxPort);
840 FreeVec(data->app_RexxPort->mp_Node.ln_Name);
841 DeleteMsgPort(data->app_RexxPort);
844 if (data->app_AppIcon)
845 RemoveAppIcon(data->app_AppIcon);
847 if (data->app_DefaultDiskObject)
848 FreeDiskObject(data->app_DefaultDiskObject);
850 if (data->app_AppPort)
852 struct Message *msg;
853 while ((msg = GetMsg(data->app_AppPort)))
854 ReplyMsg(msg);
856 DeleteMsgPort(data->app_AppPort);
859 if (data->app_GlobalInfo.mgi_Configdata)
860 MUI_DisposeObject(data->app_GlobalInfo.mgi_Configdata);
862 DeleteMsgPort(data->app_GlobalInfo.mgi_WindowsPort);
864 FreeVec(data->app_Base);
866 /* free returnid stuff */
868 while ((rid =
869 (struct RIDNode *)RemHead((struct List *)&data->
870 app_ReturnIDQueue)))
872 DeleteRIDNode(data, rid);
875 return DoSuperMethodA(cl, obj, msg);
879 /**************************************************************************
880 OM_SET
881 **************************************************************************/
882 static IPTR Application__OM_SET(struct IClass *cl, Object *obj,
883 struct opSet *msg)
885 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
886 struct TagItem *tags = msg->ops_AttrList;
887 struct TagItem *tag;
889 /* There are many ways to find out what tag items provided by set()
890 ** we do know. The best way should be using NextTagItem() and simply
891 ** browsing through the list.
893 while ((tag = NextTagItem(&tags)) != NULL)
895 IPTR addr;
896 switch (tag->ti_Tag)
899 case MUIA_Application_SearchWinId:
900 data->searchwinid = tag->ti_Data;
901 break;
903 case MUIA_Application_CopyWinPosToApp:
904 addr = tag->ti_Data;
905 /* First element is storing size and is a 32-bit integer, even on 64-bit systems */
906 CopyMem((CONST_APTR) tag->ti_Data, &data->winposused, *(LONG *)(addr));
907 break;
909 case MUIA_Application_SetWinPos:
911 struct windowpos *winp;
912 winp = (struct windowpos *)tag->ti_Data;
913 //kprintf("SetWinPos %d %d %d %d %d\n", winp->id, winp->x1,
914 // winp->y1, winp->w1, winp->h1);
915 int i;
916 for (i = 0; i < MAXWINS - 1; i++)
918 if (data->winpos[i].w1)
920 if (winp->id == data->winpos[i].id)
922 //existing entry is overwritten
923 data->winpos[i].x1 = winp->x1;
924 data->winpos[i].y1 = winp->y1;
925 data->winpos[i].w1 = winp->w1;
926 data->winpos[i].h1 = winp->h1;
927 data->winpos[i].x2 = winp->x2;
928 data->winpos[i].y2 = winp->y2;
929 data->winpos[i].w2 = winp->w2;
930 data->winpos[i].h2 = winp->h2;
931 break;
934 else
936 // a new entry is added
937 data->winpos[i].id = winp->id;
938 data->winpos[i].x1 = winp->x1;
939 data->winpos[i].y1 = winp->y1;
940 data->winpos[i].w1 = winp->w1;
941 data->winpos[i].h1 = winp->h1;
942 data->winpos[i].x2 = winp->x2;
943 data->winpos[i].y2 = winp->y2;
944 data->winpos[i].w2 = winp->w2;
945 data->winpos[i].h2 = winp->h2;
946 break;
950 break;
952 case MUIA_Application_Configdata:
953 DoMethod(obj, MUIM_Application_PushMethod, (IPTR) obj, 2,
954 MUIM_Application_SetConfigdata, tag->ti_Data);
955 break;
957 case MUIA_Application_HelpFile:
958 data->app_HelpFile = (STRPTR) tag->ti_Data;
959 break;
961 case MUIA_Application_Iconified:
963 BOOL do_iconify = tag->ti_Data == 1;
964 if (data->app_Iconified != do_iconify)
966 data->app_Iconified = do_iconify;
968 nnset(obj, MUIA_ShowMe, !data->app_Iconified);
970 /* Inform workbench.library */
971 if (data->app_Iconified)
973 STRPTR appname =
974 data->app_Title ? data->
975 app_Title : (STRPTR) "Unnamed";
976 struct DiskObject *dobj =
977 (struct DiskObject *)XGET(obj,
978 MUIA_Application_DiskObject);
980 if (dobj == NULL)
982 /* Get default AppIcon in ENV:SYS or ENVARC:SYS */
983 dobj = GetDefDiskObject(WBAPPICON);
984 if (dobj)
985 data->app_DefaultDiskObject = dobj;
986 else
988 /* First default: ENV:SYS/def_MUI.info */
989 dobj = GetDiskObject("ENV:SYS/def_MUI");
990 if (dobj)
991 data->app_DefaultDiskObject = dobj;
992 else
994 /* Second default: ENV:SYS/def_Zune.info */
995 dobj =
996 GetDiskObject("ENV:SYS/def_Zune");
997 if (dobj)
998 data->app_DefaultDiskObject = dobj;
999 else
1001 /* Third default: default tool icon */
1002 dobj = GetDefDiskObject(WBTOOL);
1003 if (dobj)
1004 data->app_DefaultDiskObject =
1005 dobj;
1011 if (dobj == NULL)
1012 break;
1014 dobj->do_CurrentX = NO_ICON_POSITION;
1015 dobj->do_CurrentY = NO_ICON_POSITION;
1017 data->app_AppIcon =
1018 AddAppIconA(0L, 0L, appname, data->app_AppPort,
1019 BNULL, dobj, NULL);
1021 else
1023 if (data->app_AppIcon)
1025 RemoveAppIcon(data->app_AppIcon);
1026 data->app_AppIcon = NULL;
1028 if (data->app_DefaultDiskObject)
1030 FreeDiskObject(data->app_DefaultDiskObject);
1031 data->app_DefaultDiskObject = NULL;
1036 break;
1038 case MUIA_ShowMe:
1040 /* Ok ok, you think this stinks? Well, think of it as
1041 an attribute belonging to an interface which
1042 MUIC_Application, together with MUIC_Area and a few
1043 others implement. It makes sense now, yes? */
1044 struct List *wlist = NULL;
1045 APTR wstate;
1046 Object *curwin = NULL;
1047 Object *lastwin = NULL;
1049 /* MUIA_ShowMe can cause MUIM_Setup/MUIM_Cleanup to be issued.
1050 * On the other hand it is allowed to add/remove other
1051 * application windows in MUIM_Setup/MUIM_Cleanup.
1052 * This means after processing a window from internal list,
1053 * the list needs to be re-read and iteration started again,
1054 * because wstate can become invalid.
1055 * Note: The code below assumes that the window won't remove
1056 * itself from the list.
1059 while (1)
1061 get(data->app_WindowFamily, MUIA_Family_List, &wlist);
1062 wstate = (Object *) wlist->lh_Head;
1063 while ((curwin = NextObject(&wstate)))
1065 if (lastwin == NULL)
1066 break;
1067 if (curwin == lastwin)
1069 curwin = NextObject(&wstate);
1070 break;
1074 /* This is the window to be processed */
1075 if (curwin)
1077 set(curwin, MUIA_ShowMe, tag->ti_Data);
1078 lastwin = curwin;
1080 else
1082 /* No more windows */
1083 break;
1087 break;
1089 case MUIA_Application_Sleep:
1091 struct List *wlist = NULL;
1092 APTR wstate;
1093 Object *curwin;
1095 if (tag->ti_Data)
1097 data->app_SleepCount++;
1098 if (data->app_SleepCount == 1)
1100 get(obj, MUIA_Application_WindowList, &wlist);
1101 if (wlist)
1103 wstate = wlist->lh_Head;
1104 while ((curwin = NextObject(&wstate)))
1106 set(curwin, MUIA_Window_Sleep, TRUE);
1111 else
1113 data->app_SleepCount--;
1114 if (data->app_SleepCount == 0)
1116 get(obj, MUIA_Application_WindowList, &wlist);
1117 if (wlist)
1119 wstate = wlist->lh_Head;
1120 while ((curwin = NextObject(&wstate)))
1122 set(curwin, MUIA_Window_Sleep, FALSE);
1128 break;
1130 case MUIA_Application_MenuAction:
1131 data->app_MenuAction = tag->ti_Data;
1132 break;
1134 case MUIA_Application_BrokerHook:
1135 data->app_BrokerHook = (struct Hook *)tag->ti_Data;
1136 break;
1138 case MUIA_Application_Active:
1139 data->app_Active = tag->ti_Data ? TRUE : FALSE;
1140 if (data->app_Broker)
1142 ActivateCxObj(data->app_Broker, data->app_Active);
1144 break;
1146 case MUIA_Application_Commands:
1147 data->app_Commands = (struct MUI_Command *)tag->ti_Data;
1148 break;
1150 case MUIA_Application_RexxString:
1151 data->app_RexxString = (STRPTR) tag->ti_Data;
1152 break;
1154 case MUIA_Application_RexxHook:
1155 data->app_RexxHook = (struct Hook *)tag->ti_Data;
1156 break;
1158 case MUIA_Application_DiskObject:
1159 data->app_DiskObject = (struct DiskObject *)tag->ti_Data;
1160 break;
1164 return DoSuperMethodA(cl, obj, (Msg) msg);
1169 * OM_GET
1171 static IPTR Application__OM_GET(struct IClass *cl, Object *obj,
1172 struct opGet *msg)
1174 #define STORE *(msg->opg_Storage)
1176 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1178 switch (msg->opg_AttrID)
1180 case MUIA_Application_GetWinPosAddr:
1181 STORE = (IPTR) & data->winposused;
1182 return TRUE;
1184 case MUIA_Application_GetWinPosSize:
1186 int i;
1187 for (i = 0; i < MAXWINS - 1; i++)
1189 if (!data->winpos[i].w1)
1191 i *= sizeof(struct windowpos);
1192 i += sizeof(long);
1193 data->winposused = i;
1194 STORE = i;
1195 return (TRUE);
1198 STORE = 0;
1199 return TRUE;
1202 case MUIA_Application_GetWinPos:
1204 int i;
1205 if (data->searchwinid)
1207 for (i = 0; i < MAXWINS - 1; i++)
1209 if (data->winpos[i].w1)
1211 if (data->searchwinid == data->winpos[i].id)
1213 STORE = (IPTR) & data->winpos[i].id;
1214 return 1;
1217 else
1218 break;
1221 STORE = 0;
1222 return 1;
1224 return TRUE;
1226 case MUIA_Version:
1227 STORE = __version;
1228 return TRUE;
1230 case MUIA_Revision:
1231 STORE = __revision;
1232 return TRUE;
1234 case MUIA_Application_Author:
1235 STORE = (IPTR) data->app_Author;
1236 return TRUE;
1238 case MUIA_Application_Base:
1239 STORE = (IPTR) data->app_Base;
1240 return TRUE;
1242 case MUIA_Application_Copyright:
1243 STORE = (IPTR) data->app_Copyright;
1244 return TRUE;
1246 case MUIA_Application_Description:
1247 STORE = (IPTR) data->app_Description;
1248 return TRUE;
1250 case MUIA_Application_DoubleStart:
1251 return TRUE;
1253 case MUIA_Application_ForceQuit:
1254 STORE = (IPTR) data->app_ForceQuit;
1255 return TRUE;
1257 case MUIA_Application_HelpFile:
1258 STORE = (IPTR) data->app_HelpFile;
1259 return TRUE;
1261 case MUIA_Application_Iconified:
1262 STORE = (IPTR) data->app_Iconified;
1263 return TRUE;
1265 case MUIA_Application_Title:
1266 STORE = (IPTR) data->app_Title;
1267 return TRUE;
1269 case MUIA_Application_Version:
1270 STORE = (IPTR) data->app_Version;
1271 return TRUE;
1273 case MUIA_Application_Version_Number:
1274 STORE = (IPTR) data->app_Version_Number;
1275 return TRUE;
1277 case MUIA_Application_Version_Date:
1278 STORE = (IPTR) data->app_Version_Date;
1279 return TRUE;
1281 case MUIA_Application_Version_Extra:
1282 STORE = (IPTR) data->app_Version_Extra;
1283 return TRUE;
1285 case MUIA_Application_WindowList:
1286 return GetAttr(MUIA_Family_List, data->app_WindowFamily,
1287 msg->opg_Storage);
1289 case MUIA_Application_Menustrip:
1290 STORE = (IPTR) data->app_Menustrip;
1291 return TRUE;
1293 case MUIA_Application_MenuAction:
1294 STORE = (IPTR) data->app_MenuAction;
1295 return TRUE;
1297 case MUIA_Application_BrokerPort:
1298 STORE = (IPTR) data->app_BrokerPort;
1299 return TRUE;
1301 case MUIA_Application_BrokerPri:
1302 STORE = (IPTR) data->app_BrokerPri;
1303 return TRUE;
1305 case MUIA_Application_BrokerHook:
1306 STORE = (IPTR) data->app_BrokerHook;
1307 return TRUE;
1309 case MUIA_Application_Broker:
1310 STORE = (IPTR) data->app_Broker;
1311 return TRUE;
1313 case MUIA_Application_Active:
1314 STORE = data->app_Active;
1315 return TRUE;
1317 case MUIA_Application_Commands:
1318 STORE = (IPTR) data->app_Commands;
1319 return TRUE;
1321 case MUIA_Application_RexxMsg:
1322 STORE = (IPTR) data->app_RexxMsg;
1323 return TRUE;
1325 case MUIA_Application_RexxHook:
1326 STORE = (IPTR) data->app_RexxHook;
1327 return TRUE;
1329 case MUIA_Application_DiskObject:
1330 STORE = (IPTR) data->app_DiskObject;
1331 return TRUE;
1334 /* our handler didn't understand the attribute, we simply pass
1335 ** it to our superclass now
1337 return (DoSuperMethodA(cl, obj, (Msg) msg));
1338 #undef STORE
1342 /**************************************************************************
1343 OM_ADDMEMBER
1344 **************************************************************************/
1345 static IPTR Application__OM_ADDMEMBER(struct IClass *cl, Object *obj,
1346 struct opMember *msg)
1348 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1350 D(bug("Application_AddMember: Adding 0x%lx to window member list\n",
1351 msg->opam_Object));
1353 DoMethodA(data->app_WindowFamily, (Msg) msg);
1354 /* Application knows its GlobalInfo, so we can inform window */
1355 DoMethod(msg->opam_Object, MUIM_ConnectParent, (IPTR) obj);
1356 return TRUE;
1360 /**************************************************************************
1361 OM_REMMEMBER
1362 **************************************************************************/
1363 static IPTR Application__OM_REMMEMBER(struct IClass *cl, Object *obj,
1364 struct opMember *msg)
1366 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1368 D(bug("Application_RemMember: Removing 0x%lx from window member list\n",
1369 msg->opam_Object));
1371 DoMethod(msg->opam_Object, MUIM_DisconnectParent);
1372 DoMethodA(data->app_WindowFamily, (Msg) msg);
1374 return TRUE;
1379 /**************************************************************************
1380 MUIM_Application_AddInputHandler
1381 **************************************************************************/
1382 static IPTR Application__MUIM_AddInputHandler(struct IClass *cl,
1383 Object *obj, struct MUIP_Application_AddInputHandler *msg)
1385 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1387 if (msg->ihnode->ihn_Flags & MUIIHNF_TIMER)
1389 struct timerequest_ext *time_ext =
1390 (struct timerequest_ext *)AllocVec(sizeof(struct
1391 timerequest_ext), MEMF_PUBLIC);
1392 if (time_ext)
1394 /* Store the request inside the input handler, so that we can
1395 ** remove the inputhandler without problems */
1396 msg->ihnode->ihn_Node.mln_Pred = (struct MinNode *)time_ext;
1398 time_ext->treq = *data->app_TimerReq;
1399 time_ext->treq.tr_node.io_Command = TR_ADDREQUEST;
1400 time_ext->treq.tr_time.tv_secs = msg->ihnode->ihn_Millis / 1000;
1401 time_ext->treq.tr_time.tv_micro =
1402 (msg->ihnode->ihn_Millis % 1000) * 1000;
1403 time_ext->ihn = msg->ihnode;
1404 SendIO((struct IORequest *)time_ext);
1407 else
1408 AddTail((struct List *)&data->app_IHList,
1409 (struct Node *)msg->ihnode);
1410 return TRUE;
1414 /**************************************************************************
1415 MUIM_Application_RemInputHandler
1416 **************************************************************************/
1417 static IPTR Application__MUIM_RemInputHandler(struct IClass *cl,
1418 Object *obj, struct MUIP_Application_RemInputHandler *msg)
1420 //struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1421 if (msg->ihnode->ihn_Flags & MUIIHNF_TIMER)
1423 struct timerequest_ext *time_ext =
1424 (struct timerequest_ext *)msg->ihnode->ihn_Node.mln_Pred;
1425 if (!CheckIO((struct IORequest *)time_ext))
1426 AbortIO((struct IORequest *)time_ext);
1427 WaitIO((struct IORequest *)time_ext);
1428 FreeVec(time_ext);
1430 else
1431 Remove((struct Node *)msg->ihnode);
1433 return TRUE;
1437 void _zune_window_message(struct IntuiMessage *imsg); /* from window.c */
1440 * MUIM_Application_InputBuffered : process all pending events
1442 static IPTR Application__MUIM_InputBuffered(struct IClass *cl, Object *obj,
1443 struct MUIP_Application_InputBuffered *msg)
1445 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1446 struct IntuiMessage *imsg;
1448 /* process all pushed methods */
1449 while (application_do_pushed_method(data))
1452 imsg =
1453 (struct IntuiMessage *)GetMsg(data->app_GlobalInfo.mgi_WindowsPort);
1454 if (imsg != NULL)
1456 /* Let window object process message */
1457 _zune_window_message(imsg); /* will reply the message */
1459 return TRUE;
1462 /**************************************************************************
1463 MUIM_Application_NewInput : application main loop
1464 **************************************************************************/
1465 static IPTR Application__MUIM_NewInput(struct IClass *cl, Object *obj,
1466 struct MUIP_Application_NewInput *msg)
1468 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1469 struct RIDNode *rid;
1470 ULONG retval = 0;
1471 ULONG signal, signalmask;
1472 ULONG handler_mask = 0; /* the mask of the signal handlers */
1473 struct MinNode *mn;
1475 //struct MinNode ihn_Node;
1477 signal = *msg->signal;
1479 /* process all pushed methods */
1480 while (application_do_pushed_method(data))
1481 /* nothing */ ;
1483 /* query the signal for the handlers */
1484 for (mn = data->app_IHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
1486 struct MUI_InputHandlerNode *ihn;
1487 ihn = (struct MUI_InputHandlerNode *)mn;
1488 handler_mask |= ihn->ihn_Signals;
1491 signalmask = (1L << data->app_GlobalInfo.mgi_WindowsPort->mp_SigBit)
1492 | (1L << data->app_TimerPort->mp_SigBit) | handler_mask;
1494 if (data->app_Broker)
1495 signalmask |= (1L << data->app_BrokerPort->mp_SigBit);
1497 if (data->app_RexxPort)
1498 signalmask |= (1L << data->app_RexxPort->mp_SigBit);
1500 if (data->app_AppPort)
1501 signalmask |= (1L << data->app_AppPort->mp_SigBit);
1503 if (signal == 0)
1505 /* Stupid app which (always) passes 0 in signals. It's impossible to
1506 know which signals were really set as the app will already have
1507 called Wait() which has cleared the task's tc_SigRecvd. So assume
1508 the window, timer, and broker signals all to be set. Also all of
1509 the inputhandler signals (MUI does that too). */
1511 signal = signalmask;
1514 if (signal & signalmask)
1516 if (signal & (1L << data->app_GlobalInfo.mgi_WindowsPort->
1517 mp_SigBit))
1519 struct IntuiMessage *imsg;
1520 /* process all pushed methods */
1522 while ((imsg =
1523 (struct IntuiMessage *)GetMsg(data->app_GlobalInfo.
1524 mgi_WindowsPort)))
1526 /* Let window object process message */
1527 _zune_window_message(imsg); /* will reply the message */
1531 if (signal & (1L << data->app_TimerPort->mp_SigBit))
1533 struct timerequest_ext *time_ext;
1534 struct Node *n;
1535 struct List list;
1536 NewList(&list);
1538 /* At first we fetch all messages from the message port and store
1539 ** them in a list, we use the node of the Message here */
1540 while ((time_ext =
1541 (struct timerequest_ext *)GetMsg(data->app_TimerPort)))
1542 AddTail(&list, (struct Node *)time_ext);
1544 /* Now we proccess the list and resend the timer io, no loop can
1545 ** happen. We use RemHead() because the handler can remove it
1546 ** itself and so a FreeVec() could happen in
1547 ** MUIM_Application_RemInputHandler which would destroy the
1548 ** ln->Succ of course */
1549 while ((n = RemHead(&list)))
1551 struct timerequest_ext *time_ext =
1552 (struct timerequest_ext *)n;
1553 struct MUI_InputHandlerNode *ihn = time_ext->ihn;
1554 time_ext->treq.tr_time.tv_secs =
1555 time_ext->ihn->ihn_Millis / 1000;
1556 time_ext->treq.tr_time.tv_micro =
1557 (time_ext->ihn->ihn_Millis % 1000) * 1000;
1558 SendIO((struct IORequest *)&time_ext->treq);
1559 DoMethod(ihn->ihn_Object, ihn->ihn_Method);
1563 if (data->app_BrokerPort
1564 && (signal & (1L << data->app_BrokerPort->mp_SigBit)))
1566 CxMsg *msg;
1568 while ((msg = (CxMsg *) GetMsg(data->app_BrokerPort)))
1570 switch (CxMsgType(msg))
1572 case CXM_COMMAND:
1573 switch (CxMsgID(msg))
1575 case CXCMD_DISABLE:
1576 set(obj, MUIA_Application_Active, FALSE);
1577 break;
1579 case CXCMD_ENABLE:
1580 set(obj, MUIA_Application_Active, TRUE);
1581 break;
1583 case CXCMD_APPEAR:
1584 case CXCMD_DISAPPEAR:
1585 /* No default handling - application needs to be in
1586 * control of this */
1587 break;
1589 case CXCMD_KILL:
1590 SetSignal(SIGBREAKF_CTRL_C, SIGBREAKF_CTRL_C);
1591 break;
1593 break;
1596 if (data->app_BrokerHook)
1598 CallHookPkt(data->app_BrokerHook, obj, msg);
1601 ReplyMsg((struct Message *)msg);
1605 if (data->app_RexxPort
1606 && (signal & (1L << data->app_RexxPort->mp_SigBit)))
1609 D(bug("[MUI] Got Rexx message!\n"));
1610 struct Message *msg;
1611 while ((msg = GetMsg(data->app_RexxPort)))
1613 ReplyMsg(msg);
1617 if (data->app_AppPort
1618 && (signal & (1L << data->app_AppPort->mp_SigBit)))
1620 struct AppMessage *appmsg;
1621 while ((appmsg =
1622 (struct AppMessage *)GetMsg(data->app_AppPort)))
1624 if ((appmsg->am_Type == AMTYPE_APPICON)
1625 && (appmsg->am_NumArgs == 0)
1626 && (appmsg->am_ArgList == NULL)
1627 && (XGET(obj, MUIA_Application_Iconified) == TRUE))
1629 /* Reply before removing AppIcon */
1630 ReplyMsg((struct Message *)appmsg);
1631 set(obj, MUIA_Application_Iconified, FALSE);
1632 continue;
1634 else if (appmsg->am_Type == AMTYPE_APPWINDOW)
1636 set((Object *) appmsg->am_UserData, MUIA_AppMessage,
1637 appmsg);
1640 ReplyMsg((struct Message *)appmsg);
1644 if (signal & handler_mask)
1646 for (mn = data->app_IHList.mlh_Head; mn->mln_Succ;
1647 mn = mn->mln_Succ)
1649 struct MUI_InputHandlerNode *ihn;
1650 ihn = (struct MUI_InputHandlerNode *)mn;
1651 if (signal & ihn->ihn_Signals)
1652 DoMethod(ihn->ihn_Object, ihn->ihn_Method);
1657 /* process all pushed methods - again */
1658 while (application_do_pushed_method(data))
1659 /* nothing */ ;
1661 *msg->signal = signalmask;
1663 /* set return code */
1664 if ((rid =
1665 (struct RIDNode *)RemHead((struct List *)&data->
1666 app_ReturnIDQueue)))
1668 retval = rid->rid_Value;
1669 DeleteRIDNode(data, rid);
1670 return retval;
1672 return 0;
1675 /**************************************************************************
1676 MUIM_Application_Input : application main loop
1677 This method shouldn't be used in any new program. As it polls all signals.
1678 **************************************************************************/
1679 static IPTR Application__MUIM_Input(struct IClass *cl, Object *obj,
1680 struct MUIP_Application_Input *msg)
1682 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1683 ULONG signal = 0, handler_mask = 0;
1684 struct MinNode *mn;
1686 /* query the signal for the handlers */
1687 for (mn = data->app_IHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
1689 struct MUI_InputHandlerNode *ihn;
1690 ihn = (struct MUI_InputHandlerNode *)mn;
1691 handler_mask |= ihn->ihn_Flags;
1694 signal = (1L << data->app_GlobalInfo.mgi_WindowsPort->mp_SigBit)
1695 | (1L << data->app_TimerPort->mp_SigBit) | handler_mask;
1697 if (data->app_RexxPort)
1698 signal |= (1L << data->app_RexxPort->mp_SigBit);
1700 if (data->app_AppPort)
1701 signal |= (1L << data->app_AppPort->mp_SigBit);
1704 *msg->signal = signal;
1705 return Application__MUIM_NewInput(cl, obj, (APTR) msg);
1708 /**************************************************************************
1709 MUIM_Application_PushMethod: Add a method in the method FIFO. Will
1710 be executed in the next event loop.
1711 **************************************************************************/
1712 static IPTR Application__MUIM_PushMethod(struct IClass *cl, Object *obj,
1713 struct MUIP_Application_PushMethod *msg)
1715 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1716 struct MQNode *mq;
1717 LONG i;
1718 IPTR *m = (IPTR *) &msg->count; /* FIXME: breaks on 64-bit BigEndian systems */
1719 LONG count;
1721 count = msg->count & 0xf; /* MUI4 uses count to pass additional info */
1723 mq = CreateMQNode(count);
1724 if (!mq)
1725 return 0;
1726 mq->mq_Dest = msg->dest;
1728 /* fill msg */
1729 for (i = 0; i < count; i++)
1730 mq->mq_Msg[i] = *(m + 1 + i);
1732 /* enqueue method */
1733 ObtainSemaphore(&data->app_MethodSemaphore);
1734 AddTail((struct List *)&data->app_MethodQueue, (struct Node *)mq);
1735 ReleaseSemaphore(&data->app_MethodSemaphore);
1737 /* CHECKME: to wake task up as soon as possible! */
1738 Signal(data->app_Task,
1739 1L << data->app_GlobalInfo.mgi_WindowsPort->mp_SigBit);
1741 return (IPTR)mq;
1744 /**************************************************************************
1745 MUIM_Application_UnpushMethod: Removes a method which was added by
1746 MUIM_Application_PushMethod.
1747 **************************************************************************/
1748 static IPTR Application__MUIM_UnpushMethod(struct IClass *cl, Object *obj,
1749 struct MUIP_Application_UnpushMethod *msg)
1751 D(bug("[Application__MUIM_UnpushMethod] dest %p id %p method %u\n",
1752 msg->dest, msg->methodid, msg->method));
1754 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1756 struct MQNode *current, *next;
1757 ULONG removed = 0;
1759 ObtainSemaphore(&data->app_MethodSemaphore);
1760 ForeachNodeSafe(&data->app_MethodQueue, current, next)
1762 D(bug("[Application__MUIM_UnpushMethod] examine dest %p id %p "
1763 "method %u\n",
1764 current->mq_Dest, current, current->mq_Msg[0]));
1765 if (((msg->dest == NULL) || (msg->dest == current->mq_Dest))
1766 && ((msg->methodid == 0) || (msg->methodid == (IPTR)current))
1767 && ((msg->method == 0) || (msg->method == current->mq_Msg[0]))
1770 Remove((struct Node*)current);
1771 DeleteMQNode(current);
1772 removed++;
1773 D(bug("[Application__MUIM_UnpushMethod] current %p removed\n",
1774 current));
1777 ReleaseSemaphore(&data->app_MethodSemaphore);
1779 return removed;
1784 * MUIM_Application_ReturnID : Tell MUI to return the given id with
1785 * the next call to MUIM_Application_NewInput. kinda obsolete :)
1787 static IPTR Application__MUIM_ReturnID(struct IClass *cl, Object *obj,
1788 struct MUIP_Application_ReturnID *msg)
1790 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1791 struct RIDNode *rid;
1794 if (!data->app_RIDMemChunk)
1796 data->app_RIDMemChunk =
1797 g_mem_chunk_create(struct RIDNode, 10, G_ALLOC_AND_FREE);
1800 rid = CreateRIDNode(data, msg->retid);
1801 if (!rid)
1802 return FALSE;
1803 AddTail((struct List *)&data->app_ReturnIDQueue, (struct Node *)rid);
1804 return TRUE;
1809 * MUIM_FindUData : tests if the MUIA_UserData of the object
1810 * contains the given <udata> and returns the object pointer in this case.
1812 static IPTR Application__MUIM_FindUData(struct IClass *cl, Object *obj,
1813 struct MUIP_FindUData *msg)
1815 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1817 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
1818 return (IPTR) obj;
1820 return DoMethodA(data->app_WindowFamily, (Msg) msg);
1825 * MUIM_GetUData : This method tests if the MUIA_UserData of the object
1826 * contains the given <udata> and gets <attr> to <storage> for itself
1827 * in this case.
1829 static IPTR Application__MUIM_GetUData(struct IClass *cl, Object *obj,
1830 struct MUIP_GetUData *msg)
1832 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1834 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
1836 get(obj, msg->attr, msg->storage);
1837 return TRUE;
1839 return DoMethodA(data->app_WindowFamily, (Msg) msg);
1844 * MUIM_SetUData : This method tests if the MUIA_UserData of the object
1845 * contains the given <udata> and sets <attr> to <val> for itself in this case.
1847 static IPTR Application__MUIM_SetUData(struct IClass *cl, Object *obj,
1848 struct MUIP_SetUData *msg)
1850 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1852 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
1853 set(obj, msg->attr, msg->val);
1855 DoMethodA(data->app_WindowFamily, (Msg) msg);
1856 return TRUE;
1861 * MUIM_SetUDataOnce : This method tests if the MUIA_UserData of the object
1862 * contains the given <udata> and sets <attr> to <val> for itself in this case.
1864 static IPTR Application__MUIM_SetUDataOnce(struct IClass *cl, Object *obj,
1865 struct MUIP_SetUDataOnce *msg)
1867 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1869 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
1871 set(obj, msg->attr, msg->val);
1872 return TRUE;
1874 return DoMethodA(data->app_WindowFamily, (Msg) msg);
1878 /****** Application.mui/MUIM_Application_AboutMUI ****************************
1880 * NAME
1881 * MUIM_Application_AboutMUI (V14)
1883 * SYNOPSIS
1884 * DoMethod(obj, MUIM_Application_AboutMUI, Object refwindow);
1886 * FUNCTION
1887 * Show Zune's About window.
1889 * INPUTS
1890 * refwindow - the window object relative to which the About window will
1891 * be placed.
1893 * SEE ALSO
1894 * MUIA_Window_RefWindow.
1896 ******************************************************************************
1900 static IPTR Application__MUIM_AboutMUI(struct IClass *cl, Object *obj,
1901 struct MUIP_Application_AboutMUI *msg)
1903 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1905 if (!data->app_AboutWin)
1907 data->app_AboutWin = AboutmuiObject,
1908 msg->refwindow ? MUIA_Window_RefWindow : TAG_IGNORE,
1909 msg->refwindow, MUIA_Window_LeftEdge,
1910 MUIV_Window_LeftEdge_Centered, MUIA_Window_TopEdge,
1911 MUIV_Window_TopEdge_Centered, MUIA_Aboutmui_Application, obj,
1912 End;
1915 if (data->app_AboutWin)
1916 set(data->app_AboutWin, MUIA_Window_Open, TRUE);
1918 return 0;
1921 static IPTR Application__MUIM_SetConfigdata(struct IClass *cl, Object *obj,
1922 struct MUIP_Application_SetConfigdata *msg)
1924 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1925 struct MinList *children = NULL;
1926 Object *cstate;
1927 Object *child;
1929 get(data->app_WindowFamily, MUIA_Family_List, &children);
1930 if (children)
1932 cstate = (Object *) children->mlh_Head;
1933 if ((child = NextObject(&cstate)))
1935 D(bug("closing window %p\n", child));
1937 set(child, MUIA_Window_Open, FALSE);
1941 if (data->app_GlobalInfo.mgi_Configdata)
1942 MUI_DisposeObject(data->app_GlobalInfo.mgi_Configdata);
1943 data->app_GlobalInfo.mgi_Configdata = msg->configdata;
1944 get(data->app_GlobalInfo.mgi_Configdata, MUIA_Configdata_ZunePrefs,
1945 &data->app_GlobalInfo.mgi_Prefs);
1947 DoMethod(obj, MUIM_Application_PushMethod, (IPTR) obj, 1,
1948 MUIM_Application_OpenWindows);
1949 return 0;
1953 /* MUIM_Application_OpenWindows
1954 * Opens all windows of an application
1956 static IPTR Application__MUIM_OpenWindows(struct IClass *cl, Object *obj,
1957 struct MUIP_Application_OpenWindows *msg)
1959 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1960 struct MinList *children = NULL;
1961 Object *cstate;
1962 Object *child;
1964 get(data->app_WindowFamily, MUIA_Family_List, &children);
1965 if (!children)
1966 return 0;
1968 cstate = (Object *) children->mlh_Head;
1969 if ((child = NextObject(&cstate)))
1971 set(child, MUIA_Window_Open, TRUE);
1973 return 0;
1977 static IPTR Application__MUIM_OpenConfigWindow(struct IClass *cl,
1978 Object *obj, struct MUIP_Application_OpenConfigWindow *msg)
1980 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1981 struct TagItem tags[] = {
1982 {SYS_Asynch, FALSE},
1983 {SYS_Input, 0},
1984 {SYS_Output, 0},
1985 {NP_StackSize, AROS_STACKSIZE},
1986 {TAG_DONE}
1988 char cmd[255];
1990 snprintf(cmd, 255, "sys:prefs/Zune %s %ld",
1991 data->app_Base ? data->app_Base : (STRPTR) "", (long)obj);
1993 if (SystemTagList(cmd, tags) == -1)
1995 return 0;
1997 Delay(50);
1999 if (data->app_Base)
2001 snprintf(cmd, 255, "ENV:zune/%s.prefs", data->app_Base);
2002 DoMethod(data->app_GlobalInfo.mgi_Configdata, MUIM_Configdata_Load,
2003 (IPTR) cmd);
2006 return 1;
2009 static IPTR Application__MUIM_Execute(Class *CLASS, Object *self,
2010 Msg message)
2012 IPTR signals = 0L;
2014 while
2015 (DoMethod(self, MUIM_Application_NewInput, (IPTR) & signals)
2016 != MUIV_Application_ReturnID_Quit)
2018 if (signals)
2020 signals = Wait(signals | SIGBREAKF_CTRL_C);
2021 if (signals & SIGBREAKF_CTRL_C)
2022 break;
2026 return 0;
2030 static IPTR Application__MUIM_UpdateMenus(struct IClass *cl, Object *obj,
2031 Msg message)
2033 struct List *wlist = NULL;
2034 APTR wstate;
2035 Object *curwin;
2037 get(obj, MUIA_Application_WindowList, &wlist);
2039 if (wlist)
2041 wstate = wlist->lh_Head;
2042 while ((curwin = NextObject(&wstate)))
2044 DoMethod(curwin, MUIM_Window_UpdateMenu);
2048 return 0;
2051 static IPTR Application__MUIM_Load(struct IClass *cl, Object *obj,
2052 struct MUIP_Application_Load *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 if (message->name == MUIV_Application_Load_ENV)
2071 snprintf(name, sizeof(name), "ENV:Zune/%s.cfg", data->app_Base);
2072 else if (message->name == MUIV_Application_Load_ENVARC)
2073 snprintf(name, sizeof(name), "ENVARC:Zune/%s.cfg", data->app_Base);
2074 else
2075 strncpy(name, message->name, sizeof(name) - 1);
2077 fh = Open(name, MODE_OLDFILE);
2078 if (fh)
2080 if ((iff = AllocIFF()))
2082 iff->iff_Stream = (IPTR) fh;
2084 InitIFFasDOS(iff);
2086 if (!OpenIFF(iff, IFFF_READ))
2088 if (!StopChunk(iff, ID_PREF, ID_MUIO))
2090 if (!ParseIFF(iff, IFFPARSE_SCAN))
2092 DoMethod(dataspace, MUIM_Dataspace_ReadIFF, iff,
2093 ID_PREF, ID_MUIO);
2097 CloseIFF(iff);
2099 FreeIFF(iff);
2101 Close(fh);
2104 get(data->app_WindowFamily, MUIA_Family_List, &children);
2105 cstate = (Object *) children->mlh_Head;
2106 while ((child = NextObject(&cstate)))
2108 DoMethod(child, MUIM_Import, dataspace);
2111 MUI_DisposeObject(dataspace);
2113 return 0;
2116 static IPTR Application__MUIM_Save(struct IClass *cl, Object *obj,
2117 struct MUIP_Application_Save *message)
2119 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
2120 struct IFFHandle *iff;
2121 char name[1024];
2122 BPTR fh;
2123 Object *dataspace;
2124 struct MinList *children = NULL;
2125 Object *cstate;
2126 Object *child;
2128 if (!data->app_Base)
2129 return 0;
2131 dataspace = MUI_NewObject(MUIC_Dataspace, TAG_DONE);
2132 if (!dataspace)
2133 return 0;
2135 get(data->app_WindowFamily, MUIA_Family_List, &children);
2136 cstate = (Object *) children->mlh_Head;
2137 while ((child = NextObject(&cstate)))
2139 DoMethod(child, MUIM_Export, dataspace);
2142 if (message->name == MUIV_Application_Save_ENV)
2143 snprintf(name, sizeof(name), "ENV:Zune/%s.cfg", data->app_Base);
2144 else if (message->name == MUIV_Application_Save_ENVARC)
2145 snprintf(name, sizeof(name), "ENVARC:Zune/%s.cfg", data->app_Base);
2146 else
2147 strncpy(name, message->name, sizeof(name) - 1);
2149 fh = Open(name, MODE_NEWFILE);
2150 if (fh)
2152 if ((iff = AllocIFF()))
2154 iff->iff_Stream = (IPTR) fh;
2156 InitIFFasDOS(iff);
2158 if (!OpenIFF(iff, IFFF_WRITE))
2160 if (!PushChunk(iff, ID_PREF, ID_FORM, IFFSIZE_UNKNOWN))
2162 if (!PushChunk(iff, ID_PREF, ID_PRHD,
2163 sizeof(struct FilePrefHeader)))
2165 struct FilePrefHeader head;
2167 head.ph_Version = PHV_CURRENT;
2168 head.ph_Type = 0;
2169 head.ph_Flags[0] =
2170 head.ph_Flags[1] =
2171 head.ph_Flags[2] = head.ph_Flags[3] = 0;
2173 if (WriteChunkBytes(iff, &head,
2174 sizeof(head)) == sizeof(head))
2176 PopChunk(iff);
2177 DoMethod(dataspace, MUIM_Dataspace_WriteIFF,
2178 iff, ID_PREF, ID_MUIO);
2180 else
2182 PopChunk(iff);
2185 PopChunk(iff);
2187 CloseIFF(iff);
2189 FreeIFF(iff);
2191 Close(fh);
2194 MUI_DisposeObject(dataspace);
2196 return 0;
2199 /****** Application.mui/MUIM_Application_CheckRefresh ************************
2201 * NAME
2202 * MUIM_Application_CheckRefresh (V11)
2204 * SYNOPSIS
2205 * DoMethod(obj, MUIM_Application_CheckRefresh);
2207 * FUNCTION
2208 * Redraw any damaged portions within all of the application's windows.
2209 * This method is normally only used in hooks that handle Intuition
2210 * messages received while modal requesters are open (e.g. ASL file
2211 * requesters). If such a hook is not used, a modal requester may damage
2212 * the contents of your application windows when the requester is moved.
2214 * NOTES
2215 * The object attributes needed for the ASL tags in the example below may
2216 * not all have valid values unless the parent window is open. Therefore
2217 * the tags should not be passed to MUI_AllocAslRequestTags() in an
2218 * OM_NEW method (for example), but should instead be passed to
2219 * MUI_AslRequestTags() when the requester is shown.
2221 * EXAMPLE
2223 * \* A hook function to refresh windows when called from asl.library *\
2224 * AROS_UFH3(static void, IMsgHook,
2225 * AROS_UFHA(struct Hook *, hook, A0),
2226 * AROS_UFHA(struct FileRequester *, req, A2),
2227 * AROS_UFHA(struct IntuiMessage *, imsg, A1))
2229 * AROS_USERFUNC_INIT
2231 * if (imsg->Class == IDCMP_REFRESHWINDOW)
2232 * DoMethod(req->fr_UserData, MUIM_Application_CheckRefresh);
2234 * AROS_USERFUNC_EXIT
2237 * ...
2239 * \* Show the requester *\
2240 * MUI_AslRequestTags(ASL_FileRequest, req,
2241 * ASLFR_Window, XGET(window, MUIA_Window_Window),
2242 * ASLFR_IntuiMsgFunc, (IPTR)hook,
2243 * ASLFR_UserData, XGET(window, MUIA_ApplicationObject),
2244 * TAG_DONE);
2246 ******************************************************************************
2250 static IPTR Application__MUIM_CheckRefresh(struct IClass *cl, Object *obj,
2251 struct MUIP_Application_CheckRefresh *message)
2253 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
2254 struct MinList *children = NULL;
2255 Object *cstate;
2256 Object *child;
2258 get(data->app_WindowFamily, MUIA_Family_List, &children);
2259 cstate = (Object *) children->mlh_Head;
2260 while ((child = NextObject(&cstate)))
2261 DoMethod(child, MUIM_Window_Refresh);
2263 return 0;
2267 * The class dispatcher
2269 BOOPSI_DISPATCHER(IPTR, Application_Dispatcher, cl, obj, msg)
2271 switch (msg->MethodID)
2273 case OM_NEW:
2274 return Application__OM_NEW(cl, obj, (struct opSet *)msg);
2275 case OM_DISPOSE:
2276 return Application__OM_DISPOSE(cl, obj, msg);
2277 case OM_SET:
2278 return Application__OM_SET(cl, obj, (struct opSet *)msg);
2279 case OM_GET:
2280 return Application__OM_GET(cl, obj, (struct opGet *)msg);
2281 case OM_ADDMEMBER:
2282 return Application__OM_ADDMEMBER(cl, obj, (APTR) msg);
2283 case OM_REMMEMBER:
2284 return Application__OM_REMMEMBER(cl, obj, (APTR) msg);
2285 case MUIM_Application_AddInputHandler:
2286 return Application__MUIM_AddInputHandler(cl, obj, (APTR) msg);
2287 case MUIM_Application_RemInputHandler:
2288 return Application__MUIM_RemInputHandler(cl, obj, (APTR) msg);
2289 case MUIM_Application_Input:
2290 return Application__MUIM_Input(cl, obj, (APTR) msg);
2291 case MUIM_Application_InputBuffered:
2292 return Application__MUIM_InputBuffered(cl, obj, (APTR) msg);
2293 case MUIM_Application_NewInput:
2294 return Application__MUIM_NewInput(cl, obj, (APTR) msg);
2295 case MUIM_Application_PushMethod:
2296 return Application__MUIM_PushMethod(cl, obj, (APTR) msg);
2297 case MUIM_Application_UnpushMethod:
2298 return Application__MUIM_UnpushMethod(cl, obj, (APTR) msg);
2299 case MUIM_Application_ReturnID:
2300 return Application__MUIM_ReturnID(cl, obj, (APTR) msg);
2301 case MUIM_FindUData:
2302 return Application__MUIM_FindUData(cl, obj, (APTR) msg);
2303 case MUIM_GetUData:
2304 return Application__MUIM_GetUData(cl, obj, (APTR) msg);
2305 case MUIM_SetUData:
2306 return Application__MUIM_SetUData(cl, obj, (APTR) msg);
2307 case MUIM_SetUDataOnce:
2308 return Application__MUIM_SetUDataOnce(cl, obj, (APTR) msg);
2309 case MUIM_Application_AboutMUI:
2310 return Application__MUIM_AboutMUI(cl, obj, (APTR) msg);
2311 case MUIM_Application_SetConfigdata:
2312 return Application__MUIM_SetConfigdata(cl, obj, (APTR) msg);
2313 case MUIM_Application_OpenWindows:
2314 return Application__MUIM_OpenWindows(cl, obj, (APTR) msg);
2315 case MUIM_Application_OpenConfigWindow:
2316 return Application__MUIM_OpenConfigWindow(cl, obj, (APTR) msg);
2317 case MUIM_Application_Execute:
2318 return Application__MUIM_Execute(cl, obj, msg);
2319 case MUIM_Application_UpdateMenus:
2320 return Application__MUIM_UpdateMenus(cl, obj, msg);
2321 case MUIM_Application_Load:
2322 return Application__MUIM_Load(cl, obj, (APTR) msg);
2323 case MUIM_Application_Save:
2324 return Application__MUIM_Save(cl, obj, (APTR) msg);
2325 case MUIM_Application_CheckRefresh:
2326 return Application__MUIM_CheckRefresh(cl, obj, (APTR) msg);
2329 return (DoSuperMethodA(cl, obj, msg));
2331 BOOPSI_DISPATCHER_END
2333 * Class descriptor.
2335 const struct __MUIBuiltinClass _MUI_Application_desc =
2337 MUIC_Application,
2338 MUIC_Notify,
2339 sizeof(struct MUI_ApplicationData),
2340 (void *) Application_Dispatcher