update experimental gcc 6 patch to gcc 6.1.0 release
[AROS.git] / workbench / libs / muimaster / classes / application.c
blob3dda3b261d5340cf2f3fade94c34814b4637e079
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 = (IPTR *) tag->ti_Data;
905 CopyMem((CONST_APTR) tag->ti_Data, &data->winposused, *(addr));
906 break;
908 case MUIA_Application_SetWinPos:
910 struct windowpos *winp;
911 winp = (struct windowpos *)tag->ti_Data;
912 //kprintf("SetWinPos %d %d %d %d %d\n", winp->id, winp->x1,
913 // winp->y1, winp->w1, winp->h1);
914 int i;
915 for (i = 0; i < MAXWINS - 1; i++)
917 if (data->winpos[i].w1)
919 if (winp->id == data->winpos[i].id)
921 //existing entry is overwritten
922 data->winpos[i].x1 = winp->x1;
923 data->winpos[i].y1 = winp->y1;
924 data->winpos[i].w1 = winp->w1;
925 data->winpos[i].h1 = winp->h1;
926 data->winpos[i].x2 = winp->x2;
927 data->winpos[i].y2 = winp->y2;
928 data->winpos[i].w2 = winp->w2;
929 data->winpos[i].h2 = winp->h2;
930 break;
933 else
935 // a new entry is added
936 data->winpos[i].id = winp->id;
937 data->winpos[i].x1 = winp->x1;
938 data->winpos[i].y1 = winp->y1;
939 data->winpos[i].w1 = winp->w1;
940 data->winpos[i].h1 = winp->h1;
941 data->winpos[i].x2 = winp->x2;
942 data->winpos[i].y2 = winp->y2;
943 data->winpos[i].w2 = winp->w2;
944 data->winpos[i].h2 = winp->h2;
945 break;
949 break;
951 case MUIA_Application_Configdata:
952 DoMethod(obj, MUIM_Application_PushMethod, (IPTR) obj, 2,
953 MUIM_Application_SetConfigdata, tag->ti_Data);
954 break;
956 case MUIA_Application_HelpFile:
957 data->app_HelpFile = (STRPTR) tag->ti_Data;
958 break;
960 case MUIA_Application_Iconified:
962 BOOL do_iconify = tag->ti_Data == 1;
963 if (data->app_Iconified != do_iconify)
965 data->app_Iconified = do_iconify;
967 nnset(obj, MUIA_ShowMe, !data->app_Iconified);
969 /* Inform workbench.library */
970 if (data->app_Iconified)
972 STRPTR appname =
973 data->app_Title ? data->
974 app_Title : (STRPTR) "Unnamed";
975 struct DiskObject *dobj =
976 (struct DiskObject *)XGET(obj,
977 MUIA_Application_DiskObject);
979 if (dobj == NULL)
981 /* Get default AppIcon in ENV:SYS or ENVARC:SYS */
982 dobj = GetDefDiskObject(WBAPPICON);
983 if (dobj)
984 data->app_DefaultDiskObject = dobj;
985 else
987 /* First default: ENV:SYS/def_MUI.info */
988 dobj = GetDiskObject("ENV:SYS/def_MUI");
989 if (dobj)
990 data->app_DefaultDiskObject = dobj;
991 else
993 /* Second default: ENV:SYS/def_Zune.info */
994 dobj =
995 GetDiskObject("ENV:SYS/def_Zune");
996 if (dobj)
997 data->app_DefaultDiskObject = dobj;
998 else
1000 /* Third default: default tool icon */
1001 dobj = GetDefDiskObject(WBTOOL);
1002 if (dobj)
1003 data->app_DefaultDiskObject =
1004 dobj;
1010 if (dobj == NULL)
1011 break;
1013 dobj->do_CurrentX = NO_ICON_POSITION;
1014 dobj->do_CurrentY = NO_ICON_POSITION;
1016 data->app_AppIcon =
1017 AddAppIconA(0L, 0L, appname, data->app_AppPort,
1018 BNULL, dobj, NULL);
1020 else
1022 if (data->app_AppIcon)
1024 RemoveAppIcon(data->app_AppIcon);
1025 data->app_AppIcon = NULL;
1027 if (data->app_DefaultDiskObject)
1029 FreeDiskObject(data->app_DefaultDiskObject);
1030 data->app_DefaultDiskObject = NULL;
1035 break;
1037 case MUIA_ShowMe:
1039 /* Ok ok, you think this stinks? Well, think of it as
1040 an attribute belonging to an interface which
1041 MUIC_Application, together with MUIC_Area and a few
1042 others implement. It makes sense now, yes? */
1043 struct List *wlist = NULL;
1044 APTR wstate;
1045 Object *curwin = NULL;
1046 Object *lastwin = NULL;
1048 /* MUIA_ShowMe can cause MUIM_Setup/MUIM_Cleanup to be issued.
1049 * On the other hand it is allowed to add/remove other
1050 * application windows in MUIM_Setup/MUIM_Cleanup.
1051 * This means after processing a window from internal list,
1052 * the list needs to be re-read and iteration started again,
1053 * because wstate can become invalid.
1054 * Note: The code below assumes that the window won't remove
1055 * itself from the list.
1058 while (1)
1060 get(data->app_WindowFamily, MUIA_Family_List, &wlist);
1061 wstate = (Object *) wlist->lh_Head;
1062 while ((curwin = NextObject(&wstate)))
1064 if (lastwin == NULL)
1065 break;
1066 if (curwin == lastwin)
1068 curwin = NextObject(&wstate);
1069 break;
1073 /* This is the window to be processed */
1074 if (curwin)
1076 set(curwin, MUIA_ShowMe, tag->ti_Data);
1077 lastwin = curwin;
1079 else
1081 /* No more windows */
1082 break;
1086 break;
1088 case MUIA_Application_Sleep:
1090 struct List *wlist = NULL;
1091 APTR wstate;
1092 Object *curwin;
1094 if (tag->ti_Data)
1096 data->app_SleepCount++;
1097 if (data->app_SleepCount == 1)
1099 get(obj, MUIA_Application_WindowList, &wlist);
1100 if (wlist)
1102 wstate = wlist->lh_Head;
1103 while ((curwin = NextObject(&wstate)))
1105 set(curwin, MUIA_Window_Sleep, TRUE);
1110 else
1112 data->app_SleepCount--;
1113 if (data->app_SleepCount == 0)
1115 get(obj, MUIA_Application_WindowList, &wlist);
1116 if (wlist)
1118 wstate = wlist->lh_Head;
1119 while ((curwin = NextObject(&wstate)))
1121 set(curwin, MUIA_Window_Sleep, FALSE);
1127 break;
1129 case MUIA_Application_MenuAction:
1130 data->app_MenuAction = tag->ti_Data;
1131 break;
1133 case MUIA_Application_BrokerHook:
1134 data->app_BrokerHook = (struct Hook *)tag->ti_Data;
1135 break;
1137 case MUIA_Application_Active:
1138 data->app_Active = tag->ti_Data ? TRUE : FALSE;
1139 if (data->app_Broker)
1141 ActivateCxObj(data->app_Broker, data->app_Active);
1143 break;
1145 case MUIA_Application_Commands:
1146 data->app_Commands = (struct MUI_Command *)tag->ti_Data;
1147 break;
1149 case MUIA_Application_RexxString:
1150 data->app_RexxString = (STRPTR) tag->ti_Data;
1151 break;
1153 case MUIA_Application_RexxHook:
1154 data->app_RexxHook = (struct Hook *)tag->ti_Data;
1155 break;
1157 case MUIA_Application_DiskObject:
1158 data->app_DiskObject = (struct DiskObject *)tag->ti_Data;
1159 break;
1163 return DoSuperMethodA(cl, obj, (Msg) msg);
1168 * OM_GET
1170 static IPTR Application__OM_GET(struct IClass *cl, Object *obj,
1171 struct opGet *msg)
1173 #define STORE *(msg->opg_Storage)
1175 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1177 switch (msg->opg_AttrID)
1179 case MUIA_Application_GetWinPosAddr:
1180 STORE = (IPTR) & data->winposused;
1181 return TRUE;
1183 case MUIA_Application_GetWinPosSize:
1185 int i;
1186 for (i = 0; i < MAXWINS - 1; i++)
1188 if (!data->winpos[i].w1)
1190 i *= sizeof(struct windowpos);
1191 i += sizeof(long);
1192 data->winposused = i;
1193 STORE = i;
1194 return (TRUE);
1197 STORE = 0;
1198 return TRUE;
1201 case MUIA_Application_GetWinPos:
1203 int i;
1204 if (data->searchwinid)
1206 for (i = 0; i < MAXWINS - 1; i++)
1208 if (data->winpos[i].w1)
1210 if (data->searchwinid == data->winpos[i].id)
1212 STORE = (IPTR) & data->winpos[i].id;
1213 return 1;
1216 else
1217 break;
1220 STORE = 0;
1221 return 1;
1223 return TRUE;
1225 case MUIA_Version:
1226 STORE = __version;
1227 return TRUE;
1229 case MUIA_Revision:
1230 STORE = __revision;
1231 return TRUE;
1233 case MUIA_Application_Author:
1234 STORE = (IPTR) data->app_Author;
1235 return TRUE;
1237 case MUIA_Application_Base:
1238 STORE = (IPTR) data->app_Base;
1239 return TRUE;
1241 case MUIA_Application_Copyright:
1242 STORE = (IPTR) data->app_Copyright;
1243 return TRUE;
1245 case MUIA_Application_Description:
1246 STORE = (IPTR) data->app_Description;
1247 return TRUE;
1249 case MUIA_Application_DoubleStart:
1250 return TRUE;
1252 case MUIA_Application_ForceQuit:
1253 STORE = (IPTR) data->app_ForceQuit;
1254 return TRUE;
1256 case MUIA_Application_HelpFile:
1257 STORE = (IPTR) data->app_HelpFile;
1258 return TRUE;
1260 case MUIA_Application_Iconified:
1261 STORE = (IPTR) data->app_Iconified;
1262 return TRUE;
1264 case MUIA_Application_Title:
1265 STORE = (IPTR) data->app_Title;
1266 return TRUE;
1268 case MUIA_Application_Version:
1269 STORE = (IPTR) data->app_Version;
1270 return TRUE;
1272 case MUIA_Application_Version_Number:
1273 STORE = (IPTR) data->app_Version_Number;
1274 return TRUE;
1276 case MUIA_Application_Version_Date:
1277 STORE = (IPTR) data->app_Version_Date;
1278 return TRUE;
1280 case MUIA_Application_Version_Extra:
1281 STORE = (IPTR) data->app_Version_Extra;
1282 return TRUE;
1284 case MUIA_Application_WindowList:
1285 return GetAttr(MUIA_Family_List, data->app_WindowFamily,
1286 msg->opg_Storage);
1288 case MUIA_Application_Menustrip:
1289 STORE = (IPTR) data->app_Menustrip;
1290 return TRUE;
1292 case MUIA_Application_MenuAction:
1293 STORE = (IPTR) data->app_MenuAction;
1294 return TRUE;
1296 case MUIA_Application_BrokerPort:
1297 STORE = (IPTR) data->app_BrokerPort;
1298 return TRUE;
1300 case MUIA_Application_BrokerPri:
1301 STORE = (IPTR) data->app_BrokerPri;
1302 return TRUE;
1304 case MUIA_Application_BrokerHook:
1305 STORE = (IPTR) data->app_BrokerHook;
1306 return TRUE;
1308 case MUIA_Application_Broker:
1309 STORE = (IPTR) data->app_Broker;
1310 return TRUE;
1312 case MUIA_Application_Active:
1313 STORE = data->app_Active;
1314 return TRUE;
1316 case MUIA_Application_Commands:
1317 STORE = (IPTR) data->app_Commands;
1318 return TRUE;
1320 case MUIA_Application_RexxMsg:
1321 STORE = (IPTR) data->app_RexxMsg;
1322 return TRUE;
1324 case MUIA_Application_RexxHook:
1325 STORE = (IPTR) data->app_RexxHook;
1326 return TRUE;
1328 case MUIA_Application_DiskObject:
1329 STORE = (IPTR) data->app_DiskObject;
1330 return TRUE;
1333 /* our handler didn't understand the attribute, we simply pass
1334 ** it to our superclass now
1336 return (DoSuperMethodA(cl, obj, (Msg) msg));
1337 #undef STORE
1341 /**************************************************************************
1342 OM_ADDMEMBER
1343 **************************************************************************/
1344 static IPTR Application__OM_ADDMEMBER(struct IClass *cl, Object *obj,
1345 struct opMember *msg)
1347 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1349 D(bug("Application_AddMember: Adding 0x%lx to window member list\n",
1350 msg->opam_Object));
1352 DoMethodA(data->app_WindowFamily, (Msg) msg);
1353 /* Application knows its GlobalInfo, so we can inform window */
1354 DoMethod(msg->opam_Object, MUIM_ConnectParent, (IPTR) obj);
1355 return TRUE;
1359 /**************************************************************************
1360 OM_REMMEMBER
1361 **************************************************************************/
1362 static IPTR Application__OM_REMMEMBER(struct IClass *cl, Object *obj,
1363 struct opMember *msg)
1365 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1367 D(bug("Application_RemMember: Removing 0x%lx from window member list\n",
1368 msg->opam_Object));
1370 DoMethod(msg->opam_Object, MUIM_DisconnectParent);
1371 DoMethodA(data->app_WindowFamily, (Msg) msg);
1373 return TRUE;
1378 /**************************************************************************
1379 MUIM_Application_AddInputHandler
1380 **************************************************************************/
1381 static IPTR Application__MUIM_AddInputHandler(struct IClass *cl,
1382 Object *obj, struct MUIP_Application_AddInputHandler *msg)
1384 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1386 if (msg->ihnode->ihn_Flags & MUIIHNF_TIMER)
1388 struct timerequest_ext *time_ext =
1389 (struct timerequest_ext *)AllocVec(sizeof(struct
1390 timerequest_ext), MEMF_PUBLIC);
1391 if (time_ext)
1393 /* Store the request inside the input handler, so that we can
1394 ** remove the inputhandler without problems */
1395 msg->ihnode->ihn_Node.mln_Pred = (struct MinNode *)time_ext;
1397 time_ext->treq = *data->app_TimerReq;
1398 time_ext->treq.tr_node.io_Command = TR_ADDREQUEST;
1399 time_ext->treq.tr_time.tv_secs = msg->ihnode->ihn_Millis / 1000;
1400 time_ext->treq.tr_time.tv_micro =
1401 (msg->ihnode->ihn_Millis % 1000) * 1000;
1402 time_ext->ihn = msg->ihnode;
1403 SendIO((struct IORequest *)time_ext);
1406 else
1407 AddTail((struct List *)&data->app_IHList,
1408 (struct Node *)msg->ihnode);
1409 return TRUE;
1413 /**************************************************************************
1414 MUIM_Application_RemInputHandler
1415 **************************************************************************/
1416 static IPTR Application__MUIM_RemInputHandler(struct IClass *cl,
1417 Object *obj, struct MUIP_Application_RemInputHandler *msg)
1419 //struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1420 if (msg->ihnode->ihn_Flags & MUIIHNF_TIMER)
1422 struct timerequest_ext *time_ext =
1423 (struct timerequest_ext *)msg->ihnode->ihn_Node.mln_Pred;
1424 if (!CheckIO((struct IORequest *)time_ext))
1425 AbortIO((struct IORequest *)time_ext);
1426 WaitIO((struct IORequest *)time_ext);
1427 FreeVec(time_ext);
1429 else
1430 Remove((struct Node *)msg->ihnode);
1432 return TRUE;
1436 void _zune_window_message(struct IntuiMessage *imsg); /* from window.c */
1439 * MUIM_Application_InputBuffered : process all pending events
1441 static IPTR Application__MUIM_InputBuffered(struct IClass *cl, Object *obj,
1442 struct MUIP_Application_InputBuffered *msg)
1444 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1445 struct IntuiMessage *imsg;
1447 /* process all pushed methods */
1448 while (application_do_pushed_method(data))
1451 imsg =
1452 (struct IntuiMessage *)GetMsg(data->app_GlobalInfo.mgi_WindowsPort);
1453 if (imsg != NULL)
1455 /* Let window object process message */
1456 _zune_window_message(imsg); /* will reply the message */
1458 return TRUE;
1461 /**************************************************************************
1462 MUIM_Application_NewInput : application main loop
1463 **************************************************************************/
1464 static IPTR Application__MUIM_NewInput(struct IClass *cl, Object *obj,
1465 struct MUIP_Application_NewInput *msg)
1467 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1468 struct RIDNode *rid;
1469 ULONG retval = 0;
1470 ULONG signal, signalmask;
1471 ULONG handler_mask = 0; /* the mask of the signal handlers */
1472 struct MinNode *mn;
1474 //struct MinNode ihn_Node;
1476 signal = *msg->signal;
1478 /* process all pushed methods */
1479 while (application_do_pushed_method(data))
1480 /* nothing */ ;
1482 /* query the signal for the handlers */
1483 for (mn = data->app_IHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
1485 struct MUI_InputHandlerNode *ihn;
1486 ihn = (struct MUI_InputHandlerNode *)mn;
1487 handler_mask |= ihn->ihn_Signals;
1490 signalmask = (1L << data->app_GlobalInfo.mgi_WindowsPort->mp_SigBit)
1491 | (1L << data->app_TimerPort->mp_SigBit) | handler_mask;
1493 if (data->app_Broker)
1494 signalmask |= (1L << data->app_BrokerPort->mp_SigBit);
1496 if (data->app_RexxPort)
1497 signalmask |= (1L << data->app_RexxPort->mp_SigBit);
1499 if (data->app_AppPort)
1500 signalmask |= (1L << data->app_AppPort->mp_SigBit);
1502 if (signal == 0)
1504 /* Stupid app which (always) passes 0 in signals. It's impossible to
1505 know which signals were really set as the app will already have
1506 called Wait() which has cleared the task's tc_SigRecvd. So assume
1507 the window, timer, and broker signals all to be set. Also all of
1508 the inputhandler signals (MUI does that too). */
1510 signal = signalmask;
1513 if (signal & signalmask)
1515 if (signal & (1L << data->app_GlobalInfo.mgi_WindowsPort->
1516 mp_SigBit))
1518 struct IntuiMessage *imsg;
1519 /* process all pushed methods */
1521 while ((imsg =
1522 (struct IntuiMessage *)GetMsg(data->app_GlobalInfo.
1523 mgi_WindowsPort)))
1525 /* Let window object process message */
1526 _zune_window_message(imsg); /* will reply the message */
1530 if (signal & (1L << data->app_TimerPort->mp_SigBit))
1532 struct timerequest_ext *time_ext;
1533 struct Node *n;
1534 struct List list;
1535 NewList(&list);
1537 /* At first we fetch all messages from the message port and store
1538 ** them in a list, we use the node of the Message here */
1539 while ((time_ext =
1540 (struct timerequest_ext *)GetMsg(data->app_TimerPort)))
1541 AddTail(&list, (struct Node *)time_ext);
1543 /* Now we proccess the list and resend the timer io, no loop can
1544 ** happen. We use RemHead() because the handler can remove it
1545 ** itself and so a FreeVec() could happen in
1546 ** MUIM_Application_RemInputHandler which would destroy the
1547 ** ln->Succ of course */
1548 while ((n = RemHead(&list)))
1550 struct timerequest_ext *time_ext =
1551 (struct timerequest_ext *)n;
1552 struct MUI_InputHandlerNode *ihn = time_ext->ihn;
1553 time_ext->treq.tr_time.tv_secs =
1554 time_ext->ihn->ihn_Millis / 1000;
1555 time_ext->treq.tr_time.tv_micro =
1556 (time_ext->ihn->ihn_Millis % 1000) * 1000;
1557 SendIO((struct IORequest *)&time_ext->treq);
1558 DoMethod(ihn->ihn_Object, ihn->ihn_Method);
1562 if (data->app_BrokerPort
1563 && (signal & (1L << data->app_BrokerPort->mp_SigBit)))
1565 CxMsg *msg;
1567 while ((msg = (CxMsg *) GetMsg(data->app_BrokerPort)))
1569 switch (CxMsgType(msg))
1571 case CXM_COMMAND:
1572 switch (CxMsgID(msg))
1574 case CXCMD_DISABLE:
1575 set(obj, MUIA_Application_Active, FALSE);
1576 break;
1578 case CXCMD_ENABLE:
1579 set(obj, MUIA_Application_Active, TRUE);
1580 break;
1582 case CXCMD_APPEAR:
1583 case CXCMD_DISAPPEAR:
1584 /* No default handling - application needs to be in
1585 * control of this */
1586 break;
1588 case CXCMD_KILL:
1589 SetSignal(SIGBREAKF_CTRL_C, SIGBREAKF_CTRL_C);
1590 break;
1592 break;
1595 if (data->app_BrokerHook)
1597 CallHookPkt(data->app_BrokerHook, obj, msg);
1600 ReplyMsg((struct Message *)msg);
1604 if (data->app_RexxPort
1605 && (signal & (1L << data->app_RexxPort->mp_SigBit)))
1608 D(bug("[MUI] Got Rexx message!\n"));
1609 struct Message *msg;
1610 while ((msg = GetMsg(data->app_RexxPort)))
1612 ReplyMsg(msg);
1616 if (data->app_AppPort
1617 && (signal & (1L << data->app_AppPort->mp_SigBit)))
1619 struct AppMessage *appmsg;
1620 while ((appmsg =
1621 (struct AppMessage *)GetMsg(data->app_AppPort)))
1623 if ((appmsg->am_Type == AMTYPE_APPICON)
1624 && (appmsg->am_NumArgs == 0)
1625 && (appmsg->am_ArgList == NULL)
1626 && (XGET(obj, MUIA_Application_Iconified) == TRUE))
1628 /* Reply before removing AppIcon */
1629 ReplyMsg((struct Message *)appmsg);
1630 set(obj, MUIA_Application_Iconified, FALSE);
1631 continue;
1633 else if (appmsg->am_Type == AMTYPE_APPWINDOW)
1635 set((Object *) appmsg->am_UserData, MUIA_AppMessage,
1636 appmsg);
1639 ReplyMsg((struct Message *)appmsg);
1643 if (signal & handler_mask)
1645 for (mn = data->app_IHList.mlh_Head; mn->mln_Succ;
1646 mn = mn->mln_Succ)
1648 struct MUI_InputHandlerNode *ihn;
1649 ihn = (struct MUI_InputHandlerNode *)mn;
1650 if (signal & ihn->ihn_Signals)
1651 DoMethod(ihn->ihn_Object, ihn->ihn_Method);
1656 /* process all pushed methods - again */
1657 while (application_do_pushed_method(data))
1658 /* nothing */ ;
1660 *msg->signal = signalmask;
1662 /* set return code */
1663 if ((rid =
1664 (struct RIDNode *)RemHead((struct List *)&data->
1665 app_ReturnIDQueue)))
1667 retval = rid->rid_Value;
1668 DeleteRIDNode(data, rid);
1669 return retval;
1671 return 0;
1674 /**************************************************************************
1675 MUIM_Application_Input : application main loop
1676 This method shouldn't be used in any new program. As it polls all signals.
1677 **************************************************************************/
1678 static IPTR Application__MUIM_Input(struct IClass *cl, Object *obj,
1679 struct MUIP_Application_Input *msg)
1681 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1682 ULONG signal = 0, handler_mask = 0;
1683 struct MinNode *mn;
1685 /* query the signal for the handlers */
1686 for (mn = data->app_IHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
1688 struct MUI_InputHandlerNode *ihn;
1689 ihn = (struct MUI_InputHandlerNode *)mn;
1690 handler_mask |= ihn->ihn_Flags;
1693 signal = (1L << data->app_GlobalInfo.mgi_WindowsPort->mp_SigBit)
1694 | (1L << data->app_TimerPort->mp_SigBit) | handler_mask;
1696 if (data->app_RexxPort)
1697 signal |= (1L << data->app_RexxPort->mp_SigBit);
1699 if (data->app_AppPort)
1700 signal |= (1L << data->app_AppPort->mp_SigBit);
1703 *msg->signal = signal;
1704 return Application__MUIM_NewInput(cl, obj, (APTR) msg);
1707 /**************************************************************************
1708 MUIM_Application_PushMethod: Add a method in the method FIFO. Will
1709 be executed in the next event loop.
1710 **************************************************************************/
1711 static IPTR Application__MUIM_PushMethod(struct IClass *cl, Object *obj,
1712 struct MUIP_Application_PushMethod *msg)
1714 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1715 struct MQNode *mq;
1716 LONG i;
1717 IPTR *m = (IPTR *) &msg->count; /* FIXME: breaks on 64-bit BigEndian systems */
1718 LONG count;
1720 count = msg->count & 0xf; /* MUI4 uses count to pass additional info */
1722 mq = CreateMQNode(count);
1723 if (!mq)
1724 return 0;
1725 mq->mq_Dest = msg->dest;
1727 /* fill msg */
1728 for (i = 0; i < count; i++)
1729 mq->mq_Msg[i] = *(m + 1 + i);
1731 /* enqueue method */
1732 ObtainSemaphore(&data->app_MethodSemaphore);
1733 AddTail((struct List *)&data->app_MethodQueue, (struct Node *)mq);
1734 ReleaseSemaphore(&data->app_MethodSemaphore);
1736 /* CHECKME: to wake task up as soon as possible! */
1737 Signal(data->app_Task,
1738 1L << data->app_GlobalInfo.mgi_WindowsPort->mp_SigBit);
1740 return (IPTR)mq;
1743 /**************************************************************************
1744 MUIM_Application_UnpushMethod: Removes a method which was added by
1745 MUIM_Application_PushMethod.
1746 **************************************************************************/
1747 static IPTR Application__MUIM_UnpushMethod(struct IClass *cl, Object *obj,
1748 struct MUIP_Application_UnpushMethod *msg)
1750 D(bug("[Application__MUIM_UnpushMethod] dest %p id %p method %u\n",
1751 msg->dest, msg->methodid, msg->method));
1753 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1755 struct MQNode *current, *next;
1756 ULONG removed = 0;
1758 ObtainSemaphore(&data->app_MethodSemaphore);
1759 ForeachNodeSafe(&data->app_MethodQueue, current, next)
1761 D(bug("[Application__MUIM_UnpushMethod] examine dest %p id %p "
1762 "method %u\n",
1763 current->mq_Dest, current, current->mq_Msg[0]));
1764 if (((msg->dest == NULL) || (msg->dest == current->mq_Dest))
1765 && ((msg->methodid == 0) || (msg->methodid == (IPTR)current))
1766 && ((msg->method == 0) || (msg->method == current->mq_Msg[0]))
1769 Remove((struct Node*)current);
1770 DeleteMQNode(current);
1771 removed++;
1772 D(bug("[Application__MUIM_UnpushMethod] current %p removed\n",
1773 current));
1776 ReleaseSemaphore(&data->app_MethodSemaphore);
1778 return removed;
1783 * MUIM_Application_ReturnID : Tell MUI to return the given id with
1784 * the next call to MUIM_Application_NewInput. kinda obsolete :)
1786 static IPTR Application__MUIM_ReturnID(struct IClass *cl, Object *obj,
1787 struct MUIP_Application_ReturnID *msg)
1789 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1790 struct RIDNode *rid;
1793 if (!data->app_RIDMemChunk)
1795 data->app_RIDMemChunk =
1796 g_mem_chunk_create(struct RIDNode, 10, G_ALLOC_AND_FREE);
1799 rid = CreateRIDNode(data, msg->retid);
1800 if (!rid)
1801 return FALSE;
1802 AddTail((struct List *)&data->app_ReturnIDQueue, (struct Node *)rid);
1803 return TRUE;
1808 * MUIM_FindUData : tests if the MUIA_UserData of the object
1809 * contains the given <udata> and returns the object pointer in this case.
1811 static IPTR Application__MUIM_FindUData(struct IClass *cl, Object *obj,
1812 struct MUIP_FindUData *msg)
1814 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1816 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
1817 return (IPTR) obj;
1819 return DoMethodA(data->app_WindowFamily, (Msg) msg);
1824 * MUIM_GetUData : This method tests if the MUIA_UserData of the object
1825 * contains the given <udata> and gets <attr> to <storage> for itself
1826 * in this case.
1828 static IPTR Application__MUIM_GetUData(struct IClass *cl, Object *obj,
1829 struct MUIP_GetUData *msg)
1831 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1833 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
1835 get(obj, msg->attr, msg->storage);
1836 return TRUE;
1838 return DoMethodA(data->app_WindowFamily, (Msg) msg);
1843 * MUIM_SetUData : This method tests if the MUIA_UserData of the object
1844 * contains the given <udata> and sets <attr> to <val> for itself in this case.
1846 static IPTR Application__MUIM_SetUData(struct IClass *cl, Object *obj,
1847 struct MUIP_SetUData *msg)
1849 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1851 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
1852 set(obj, msg->attr, msg->val);
1854 DoMethodA(data->app_WindowFamily, (Msg) msg);
1855 return TRUE;
1860 * MUIM_SetUDataOnce : This method tests if the MUIA_UserData of the object
1861 * contains the given <udata> and sets <attr> to <val> for itself in this case.
1863 static IPTR Application__MUIM_SetUDataOnce(struct IClass *cl, Object *obj,
1864 struct MUIP_SetUDataOnce *msg)
1866 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1868 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
1870 set(obj, msg->attr, msg->val);
1871 return TRUE;
1873 return DoMethodA(data->app_WindowFamily, (Msg) msg);
1877 /****** Application.mui/MUIM_Application_AboutMUI ****************************
1879 * NAME
1880 * MUIM_Application_AboutMUI (V14)
1882 * SYNOPSIS
1883 * DoMethod(obj, MUIM_Application_AboutMUI, Object refwindow);
1885 * FUNCTION
1886 * Show Zune's About window.
1888 * INPUTS
1889 * refwindow - the window object relative to which the About window will
1890 * be placed.
1892 * SEE ALSO
1893 * MUIA_Window_RefWindow.
1895 ******************************************************************************
1899 static IPTR Application__MUIM_AboutMUI(struct IClass *cl, Object *obj,
1900 struct MUIP_Application_AboutMUI *msg)
1902 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1904 if (!data->app_AboutWin)
1906 data->app_AboutWin = AboutmuiObject,
1907 msg->refwindow ? MUIA_Window_RefWindow : TAG_IGNORE,
1908 msg->refwindow, MUIA_Window_LeftEdge,
1909 MUIV_Window_LeftEdge_Centered, MUIA_Window_TopEdge,
1910 MUIV_Window_TopEdge_Centered, MUIA_Aboutmui_Application, obj,
1911 End;
1914 if (data->app_AboutWin)
1915 set(data->app_AboutWin, MUIA_Window_Open, TRUE);
1917 return 0;
1920 static IPTR Application__MUIM_SetConfigdata(struct IClass *cl, Object *obj,
1921 struct MUIP_Application_SetConfigdata *msg)
1923 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1924 struct MinList *children = NULL;
1925 Object *cstate;
1926 Object *child;
1928 get(data->app_WindowFamily, MUIA_Family_List, &children);
1929 if (children)
1931 cstate = (Object *) children->mlh_Head;
1932 if ((child = NextObject(&cstate)))
1934 D(bug("closing window %p\n", child));
1936 set(child, MUIA_Window_Open, FALSE);
1940 if (data->app_GlobalInfo.mgi_Configdata)
1941 MUI_DisposeObject(data->app_GlobalInfo.mgi_Configdata);
1942 data->app_GlobalInfo.mgi_Configdata = msg->configdata;
1943 get(data->app_GlobalInfo.mgi_Configdata, MUIA_Configdata_ZunePrefs,
1944 &data->app_GlobalInfo.mgi_Prefs);
1946 DoMethod(obj, MUIM_Application_PushMethod, (IPTR) obj, 1,
1947 MUIM_Application_OpenWindows);
1948 return 0;
1952 /* MUIM_Application_OpenWindows
1953 * Opens all windows of an application
1955 static IPTR Application__MUIM_OpenWindows(struct IClass *cl, Object *obj,
1956 struct MUIP_Application_OpenWindows *msg)
1958 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1959 struct MinList *children = NULL;
1960 Object *cstate;
1961 Object *child;
1963 get(data->app_WindowFamily, MUIA_Family_List, &children);
1964 if (!children)
1965 return 0;
1967 cstate = (Object *) children->mlh_Head;
1968 if ((child = NextObject(&cstate)))
1970 set(child, MUIA_Window_Open, TRUE);
1972 return 0;
1976 static IPTR Application__MUIM_OpenConfigWindow(struct IClass *cl,
1977 Object *obj, struct MUIP_Application_OpenConfigWindow *msg)
1979 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1980 struct TagItem tags[] = {
1981 {SYS_Asynch, FALSE},
1982 {SYS_Input, 0},
1983 {SYS_Output, 0},
1984 {NP_StackSize, AROS_STACKSIZE},
1985 {TAG_DONE}
1987 char cmd[255];
1989 snprintf(cmd, 255, "sys:prefs/Zune %s %ld",
1990 data->app_Base ? data->app_Base : (STRPTR) "", (long)obj);
1992 if (SystemTagList(cmd, tags) == -1)
1994 return 0;
1996 Delay(50);
1998 if (data->app_Base)
2000 snprintf(cmd, 255, "ENV:zune/%s.prefs", data->app_Base);
2001 DoMethod(data->app_GlobalInfo.mgi_Configdata, MUIM_Configdata_Load,
2002 (IPTR) cmd);
2005 return 1;
2008 static IPTR Application__MUIM_Execute(Class *CLASS, Object *self,
2009 Msg message)
2011 IPTR signals = 0L;
2013 while
2014 (DoMethod(self, MUIM_Application_NewInput, (IPTR) & signals)
2015 != MUIV_Application_ReturnID_Quit)
2017 if (signals)
2019 signals = Wait(signals | SIGBREAKF_CTRL_C);
2020 if (signals & SIGBREAKF_CTRL_C)
2021 break;
2025 return 0;
2029 static IPTR Application__MUIM_UpdateMenus(struct IClass *cl, Object *obj,
2030 Msg message)
2032 struct List *wlist = NULL;
2033 APTR wstate;
2034 Object *curwin;
2036 get(obj, MUIA_Application_WindowList, &wlist);
2038 if (wlist)
2040 wstate = wlist->lh_Head;
2041 while ((curwin = NextObject(&wstate)))
2043 DoMethod(curwin, MUIM_Window_UpdateMenu);
2047 return 0;
2050 static IPTR Application__MUIM_Load(struct IClass *cl, Object *obj,
2051 struct MUIP_Application_Load *message)
2053 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
2054 struct IFFHandle *iff;
2055 char name[1024];
2056 BPTR fh;
2057 Object *dataspace;
2058 struct MinList *children = NULL;
2059 Object *cstate;
2060 Object *child;
2062 if (!data->app_Base)
2063 return 0;
2065 dataspace = MUI_NewObject(MUIC_Dataspace, TAG_DONE);
2066 if (!dataspace)
2067 return 0;
2069 if (message->name == MUIV_Application_Load_ENV)
2070 snprintf(name, sizeof(name), "ENV:Zune/%s.cfg", data->app_Base);
2071 else if (message->name == MUIV_Application_Load_ENVARC)
2072 snprintf(name, sizeof(name), "ENVARC:Zune/%s.cfg", data->app_Base);
2073 else
2074 strncpy(name, message->name, sizeof(name));
2076 fh = Open(name, MODE_OLDFILE);
2077 if (fh)
2079 if ((iff = AllocIFF()))
2081 iff->iff_Stream = (IPTR) fh;
2083 InitIFFasDOS(iff);
2085 if (!OpenIFF(iff, IFFF_READ))
2087 if (!StopChunk(iff, ID_PREF, ID_MUIO))
2089 if (!ParseIFF(iff, IFFPARSE_SCAN))
2091 DoMethod(dataspace, MUIM_Dataspace_ReadIFF, iff,
2092 ID_PREF, ID_MUIO);
2096 CloseIFF(iff);
2098 FreeIFF(iff);
2100 Close(fh);
2103 get(data->app_WindowFamily, MUIA_Family_List, &children);
2104 cstate = (Object *) children->mlh_Head;
2105 while ((child = NextObject(&cstate)))
2107 DoMethod(child, MUIM_Import, dataspace);
2110 MUI_DisposeObject(dataspace);
2112 return 0;
2115 static IPTR Application__MUIM_Save(struct IClass *cl, Object *obj,
2116 struct MUIP_Application_Save *message)
2118 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
2119 struct IFFHandle *iff;
2120 char name[1024];
2121 BPTR fh;
2122 Object *dataspace;
2123 struct MinList *children = NULL;
2124 Object *cstate;
2125 Object *child;
2127 if (!data->app_Base)
2128 return 0;
2130 dataspace = MUI_NewObject(MUIC_Dataspace, TAG_DONE);
2131 if (!dataspace)
2132 return 0;
2134 get(data->app_WindowFamily, MUIA_Family_List, &children);
2135 cstate = (Object *) children->mlh_Head;
2136 while ((child = NextObject(&cstate)))
2138 DoMethod(child, MUIM_Export, dataspace);
2141 if (message->name == MUIV_Application_Save_ENV)
2142 snprintf(name, sizeof(name), "ENV:Zune/%s.cfg", data->app_Base);
2143 else if (message->name == MUIV_Application_Save_ENVARC)
2144 snprintf(name, sizeof(name), "ENVARC:Zune/%s.cfg", data->app_Base);
2145 else
2146 strncpy(name, message->name, sizeof(name));
2148 fh = Open(name, MODE_NEWFILE);
2149 if (fh)
2151 if ((iff = AllocIFF()))
2153 iff->iff_Stream = (IPTR) fh;
2155 InitIFFasDOS(iff);
2157 if (!OpenIFF(iff, IFFF_WRITE))
2159 if (!PushChunk(iff, ID_PREF, ID_FORM, IFFSIZE_UNKNOWN))
2161 if (!PushChunk(iff, ID_PREF, ID_PRHD,
2162 sizeof(struct FilePrefHeader)))
2164 struct FilePrefHeader head;
2166 head.ph_Version = PHV_CURRENT;
2167 head.ph_Type = 0;
2168 head.ph_Flags[0] =
2169 head.ph_Flags[1] =
2170 head.ph_Flags[2] = head.ph_Flags[3] = 0;
2172 if (WriteChunkBytes(iff, &head,
2173 sizeof(head)) == sizeof(head))
2175 PopChunk(iff);
2176 DoMethod(dataspace, MUIM_Dataspace_WriteIFF,
2177 iff, ID_PREF, ID_MUIO);
2179 else
2181 PopChunk(iff);
2184 PopChunk(iff);
2186 CloseIFF(iff);
2188 FreeIFF(iff);
2190 Close(fh);
2193 MUI_DisposeObject(dataspace);
2195 return 0;
2198 /****** Application.mui/MUIM_Application_CheckRefresh ************************
2200 * NAME
2201 * MUIM_Application_CheckRefresh (V11)
2203 * SYNOPSIS
2204 * DoMethod(obj, MUIM_Application_CheckRefresh);
2206 * FUNCTION
2207 * Redraw any damaged portions within all of the application's windows.
2208 * This method is normally only used in hooks that handle Intuition
2209 * messages received while modal requesters are open (e.g. ASL file
2210 * requesters). If such a hook is not used, a modal requester may damage
2211 * the contents of your application windows when the requester is moved.
2213 * NOTES
2214 * The object attributes needed for the ASL tags in the example below may
2215 * not all have valid values unless the parent window is open. Therefore
2216 * the tags should not be passed to MUI_AllocAslRequestTags() in an
2217 * OM_NEW method (for example), but should instead be passed to
2218 * MUI_AslRequestTags() when the requester is shown.
2220 * EXAMPLE
2222 * \* A hook function to refresh windows when called from asl.library *\
2223 * AROS_UFH3(static void, IMsgHook,
2224 * AROS_UFHA(struct Hook *, hook, A0),
2225 * AROS_UFHA(struct FileRequester *, req, A2),
2226 * AROS_UFHA(struct IntuiMessage *, imsg, A1))
2228 * AROS_USERFUNC_INIT
2230 * if (imsg->Class == IDCMP_REFRESHWINDOW)
2231 * DoMethod(req->fr_UserData, MUIM_Application_CheckRefresh);
2233 * AROS_USERFUNC_EXIT
2236 * ...
2238 * \* Show the requester *\
2239 * MUI_AslRequestTags(ASL_FileRequest, req,
2240 * ASLFR_Window, XGET(window, MUIA_Window_Window),
2241 * ASLFR_IntuiMsgFunc, (IPTR)hook,
2242 * ASLFR_UserData, XGET(window, MUIA_ApplicationObject),
2243 * TAG_DONE);
2245 ******************************************************************************
2249 static IPTR Application__MUIM_CheckRefresh(struct IClass *cl, Object *obj,
2250 struct MUIP_Application_CheckRefresh *message)
2252 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
2253 struct MinList *children = NULL;
2254 Object *cstate;
2255 Object *child;
2257 get(data->app_WindowFamily, MUIA_Family_List, &children);
2258 cstate = (Object *) children->mlh_Head;
2259 while ((child = NextObject(&cstate)))
2260 DoMethod(child, MUIM_Window_Refresh);
2262 return 0;
2266 * The class dispatcher
2268 BOOPSI_DISPATCHER(IPTR, Application_Dispatcher, cl, obj, msg)
2270 switch (msg->MethodID)
2272 case OM_NEW:
2273 return Application__OM_NEW(cl, obj, (struct opSet *)msg);
2274 case OM_DISPOSE:
2275 return Application__OM_DISPOSE(cl, obj, msg);
2276 case OM_SET:
2277 return Application__OM_SET(cl, obj, (struct opSet *)msg);
2278 case OM_GET:
2279 return Application__OM_GET(cl, obj, (struct opGet *)msg);
2280 case OM_ADDMEMBER:
2281 return Application__OM_ADDMEMBER(cl, obj, (APTR) msg);
2282 case OM_REMMEMBER:
2283 return Application__OM_REMMEMBER(cl, obj, (APTR) msg);
2284 case MUIM_Application_AddInputHandler:
2285 return Application__MUIM_AddInputHandler(cl, obj, (APTR) msg);
2286 case MUIM_Application_RemInputHandler:
2287 return Application__MUIM_RemInputHandler(cl, obj, (APTR) msg);
2288 case MUIM_Application_Input:
2289 return Application__MUIM_Input(cl, obj, (APTR) msg);
2290 case MUIM_Application_InputBuffered:
2291 return Application__MUIM_InputBuffered(cl, obj, (APTR) msg);
2292 case MUIM_Application_NewInput:
2293 return Application__MUIM_NewInput(cl, obj, (APTR) msg);
2294 case MUIM_Application_PushMethod:
2295 return Application__MUIM_PushMethod(cl, obj, (APTR) msg);
2296 case MUIM_Application_UnpushMethod:
2297 return Application__MUIM_UnpushMethod(cl, obj, (APTR) msg);
2298 case MUIM_Application_ReturnID:
2299 return Application__MUIM_ReturnID(cl, obj, (APTR) msg);
2300 case MUIM_FindUData:
2301 return Application__MUIM_FindUData(cl, obj, (APTR) msg);
2302 case MUIM_GetUData:
2303 return Application__MUIM_GetUData(cl, obj, (APTR) msg);
2304 case MUIM_SetUData:
2305 return Application__MUIM_SetUData(cl, obj, (APTR) msg);
2306 case MUIM_SetUDataOnce:
2307 return Application__MUIM_SetUDataOnce(cl, obj, (APTR) msg);
2308 case MUIM_Application_AboutMUI:
2309 return Application__MUIM_AboutMUI(cl, obj, (APTR) msg);
2310 case MUIM_Application_SetConfigdata:
2311 return Application__MUIM_SetConfigdata(cl, obj, (APTR) msg);
2312 case MUIM_Application_OpenWindows:
2313 return Application__MUIM_OpenWindows(cl, obj, (APTR) msg);
2314 case MUIM_Application_OpenConfigWindow:
2315 return Application__MUIM_OpenConfigWindow(cl, obj, (APTR) msg);
2316 case MUIM_Application_Execute:
2317 return Application__MUIM_Execute(cl, obj, msg);
2318 case MUIM_Application_UpdateMenus:
2319 return Application__MUIM_UpdateMenus(cl, obj, msg);
2320 case MUIM_Application_Load:
2321 return Application__MUIM_Load(cl, obj, (APTR) msg);
2322 case MUIM_Application_Save:
2323 return Application__MUIM_Save(cl, obj, (APTR) msg);
2324 case MUIM_Application_CheckRefresh:
2325 return Application__MUIM_CheckRefresh(cl, obj, (APTR) msg);
2328 return (DoSuperMethodA(cl, obj, msg));
2330 BOOPSI_DISPATCHER_END
2332 * Class descriptor.
2334 const struct __MUIBuiltinClass _MUI_Application_desc =
2336 MUIC_Application,
2337 MUIC_Notify,
2338 sizeof(struct MUI_ApplicationData),
2339 (void *) Application_Dispatcher