Text.mui cleanup:
[AROS.git] / workbench / libs / muimaster / classes / application.c
blobf5ff0db1bdbbe0bae421be87c387bb483c75786f
1 /*
2 Copyright © 1999, David Le Corfec.
3 Copyright © 2002-2013, 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 todo (implementable ?)
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 TrackingNode *tn;
299 Object *retval = NULL;
301 ObtainSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
302 ForeachNode(&MUIMB(MUIMasterBase)->Applications, tn)
304 STRPTR tn_base = "";
306 get(tn->tn_Application, MUIA_Application_Base, &tn_base);
308 if (tn_base && (strcmp(base, tn_base)) == 0)
310 retval = tn->tn_Application;
311 break;
314 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
316 return retval;
319 /**************************************************************************
320 OM_NEW
321 **************************************************************************/
322 static IPTR Application__OM_NEW(struct IClass *cl, Object *obj,
323 struct opSet *msg)
325 struct MUI_ApplicationData *data;
326 struct TagItem *tags, *tag;
327 BOOL bad_childs = FALSE;
329 obj = (Object *) DoSuperMethodA(cl, obj, (Msg) msg);
330 if (!obj)
331 return FALSE;
333 /* Initial local instance data */
334 data = INST_DATA(cl, obj);
336 /* init input handler list */
337 NewList((struct List *)&(data->app_IHList));
339 /* init input queue */
340 NewList((struct List *)&(data->app_MethodQueue));
342 /* init return ids queue */
343 NewList((struct List *)&(data->app_ReturnIDQueue));
345 /* window list */
346 data->app_WindowFamily = MUI_NewObjectA(MUIC_Family, NULL);
347 if (!data->app_WindowFamily)
349 CoerceMethod(cl, obj, OM_DISPOSE);
350 return 0;
353 data->app_GlobalInfo.mgi_ApplicationObject = obj;
354 if (!(data->app_GlobalInfo.mgi_WindowsPort = CreateMsgPort()))
356 CoerceMethod(cl, obj, OM_DISPOSE);
357 return 0;
360 data->app_Task = FindTask(NULL);
362 /* Parse prefs */
363 data->app_SingleTask =
364 (BOOL) GetTagData(MUIA_Application_SingleTask, FALSE,
365 msg->ops_AttrList);
366 data->app_Base =
367 (STRPTR) GetTagData(MUIA_Application_Base, (IPTR) "UNNAMED",
368 msg->ops_AttrList);
369 if (!data->app_Base || strpbrk(data->app_Base, ":/()#?*,"))
371 data->app_Base = NULL; /* don't remove */
372 CoerceMethod(cl, obj, OM_DISPOSE);
374 return 0;
377 if (!data->app_SingleTask)
379 /* must append .1, .2, ... to the base name */
380 LONG i;
381 char portname[255];
383 for (i = 1; i < 1000; i++)
385 snprintf(portname, 255, "%s.%d", data->app_Base, (int)i);
386 if (!find_application_by_base(cl, obj, portname))
387 break;
389 data->app_Base = StrDup(portname);
391 else
393 Object *other_app;
395 ObtainSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
396 if ((other_app = find_application_by_base(cl, obj, data->app_Base)))
398 //FIXME "Is calling MUIM_Application_PushMethod on an alien
399 //application object safe?"
400 DoMethod(other_app, MUIM_Application_PushMethod,
401 (IPTR) other_app, 3, MUIM_Set, MUIA_Application_DoubleStart,
402 TRUE);
403 data->app_Base = NULL;
405 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
407 data->app_Base = StrDup(data->app_Base);
410 if (!data->app_Base)
412 CoerceMethod(cl, obj, OM_DISPOSE);
413 return 0;
416 data->app_GlobalInfo.mgi_Configdata =
417 MUI_NewObject(MUIC_Configdata, MUIA_Configdata_Application, obj,
418 TAG_DONE);
419 if (!data->app_GlobalInfo.mgi_Configdata)
421 CoerceMethod(cl, obj, OM_DISPOSE);
422 return 0;
424 get(data->app_GlobalInfo.mgi_Configdata, MUIA_Configdata_ZunePrefs,
425 &data->app_GlobalInfo.mgi_Prefs);
427 // D(bug("muimaster.library/application.c: Message Port created at 0x%lx\n",
428 // data->app_GlobalInfo.mgi_WindowPort));
430 /* Setup timer stuff */
431 if (!(data->app_TimerPort = CreateMsgPort()))
433 CoerceMethod(cl, obj, OM_DISPOSE);
434 return 0;
437 if (!(data->app_TimerReq =
438 (struct timerequest *)CreateIORequest(data->app_TimerPort,
439 sizeof(struct timerequest))))
441 CoerceMethod(cl, obj, OM_DISPOSE);
442 return 0;
445 if (OpenDevice(TIMERNAME, UNIT_VBLANK,
446 (struct IORequest *)data->app_TimerReq, 0))
448 CoerceMethod(cl, obj, OM_DISPOSE);
449 return 0;
452 InitSemaphore(&data->app_MethodSemaphore);
454 muiNotifyData(obj)->mnd_GlobalInfo = &data->app_GlobalInfo;
456 /* parse initial taglist */
458 data->app_Active = 1;
459 data->app_Title = "Unnamed";
460 data->app_Version = "Unnamed 0.0";
461 data->app_Description = "?";
463 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags));)
465 switch (tag->ti_Tag)
467 case MUIA_Application_Author:
468 data->app_Author = (STRPTR) tag->ti_Data;
469 break;
471 case MUIA_Application_Base:
472 /* moved before config parsing */
473 break;
475 case MUIA_Application_Copyright:
476 data->app_Copyright = (STRPTR) tag->ti_Data;
477 break;
479 case MUIA_Application_Description:
480 data->app_Description = (STRPTR) tag->ti_Data;
481 break;
483 case MUIA_Application_HelpFile:
484 data->app_HelpFile = (STRPTR) tag->ti_Data;
485 break;
487 case MUIA_Application_SingleTask:
488 /* moved before config parsing */
489 break;
491 case MUIA_Application_Title:
492 data->app_Title = (STRPTR) tag->ti_Data;
493 break;
495 case MUIA_Application_Version:
496 data->app_Version = (STRPTR) tag->ti_Data;
497 break;
499 case MUIA_Application_Version_Number:
500 data->app_Version_Number = (STRPTR) tag->ti_Data;
501 break;
503 case MUIA_Application_Version_Date:
504 data->app_Version_Date = (STRPTR) tag->ti_Data;
505 break;
507 case MUIA_Application_Version_Extra:
508 data->app_Version_Extra = (STRPTR) tag->ti_Data;
509 break;
511 case MUIA_Application_Window:
512 if (tag->ti_Data)
513 DoMethod(obj, OM_ADDMEMBER, tag->ti_Data);
514 else
515 bad_childs = TRUE;
516 break;
518 case MUIA_Application_Menustrip:
519 data->app_Menustrip = (Object *) tag->ti_Data;
520 break;
522 case MUIA_Application_BrokerPri:
523 data->app_BrokerPri = (BYTE) tag->ti_Data;
524 break;
526 case MUIA_Application_BrokerHook:
527 data->app_BrokerHook = (struct Hook *)tag->ti_Data;
528 break;
530 case MUIA_Application_Active:
531 data->app_Active = tag->ti_Data ? TRUE : FALSE;
532 break;
534 case MUIA_Application_UsedClasses:
536 STRPTR *list = (STRPTR *) tag->ti_Data;
537 if (!list)
538 break;
539 while (*list)
541 struct IClass *icl = MUI_GetClass(*list);
542 if (icl)
543 MUI_FreeClass(icl);
544 ++list;
547 break;
549 case MUIA_Application_UseRexx:
550 data->app_UseRexx = tag->ti_Data ? TRUE : FALSE;
551 break;
553 case MUIA_Application_Commands:
554 data->app_Commands = (struct MUI_Command *)tag->ti_Data;
555 break;
557 case MUIA_Application_RexxHook:
558 data->app_RexxHook = (struct Hook *)tag->ti_Data;
559 break;
561 case MUIA_Application_DiskObject:
562 data->app_DiskObject = (struct DiskObject *)tag->ti_Data;
563 break;
568 /* create MUIA_Application_Version if NULL */
569 if (data->app_Version == NULL
570 && data->app_Title != NULL && data->app_Version_Number != NULL)
572 STRPTR result = NULL;
573 ULONG length = 0;
575 /* Calculate length */
576 length = strlen("$VER: ") + strlen(data->app_Title) + 1 /* space */
577 + strlen(data->app_Version_Number) + 1 /* NULL */ ;
579 if (data->app_Version_Date != NULL)
581 length += 1 /* space */ + 1 /* ( */
582 + strlen(data->app_Version_Date) + 1 /* ) */ ;
585 if (data->app_Version_Extra != NULL)
587 length += 1 /* space */ + 1 /* [ */
588 + strlen(data->app_Version_Extra) + 1 /* ] */ ;
591 /* Allocate memory */
592 result = AllocVec(length, MEMF_ANY);
594 if (result != NULL)
596 result[0] = '\0';
598 /* Format string */
599 strlcat(result, "$VER: ", length);
600 strlcat(result, data->app_Title, length);
601 strlcat(result, " ", length);
602 strlcat(result, data->app_Version_Number, length);
604 if (data->app_Version_Date != NULL)
606 strlcat(result, " (", length);
607 strlcat(result, data->app_Version_Date, length);
608 strlcat(result, ")", length);
611 if (data->app_Version_Extra != NULL)
613 strlcat(result, " [", length);
614 strlcat(result, data->app_Version_Extra, length);
615 strlcat(result, "]", length);
618 data->app_Version = result;
619 data->app_VersionAllocated = TRUE;
624 if (bad_childs)
626 CoerceMethod(cl, obj, OM_DISPOSE);
627 return 0;
630 if (CxBase
631 && GetTagData(MUIA_Application_UseCommodities, TRUE,
632 msg->ops_AttrList))
634 data->app_BrokerPort = CreateMsgPort();
636 if (data->app_BrokerPort)
638 struct NewBroker nb;
640 nb.nb_Version = NB_VERSION;
641 nb.nb_Name =
642 data->app_Title ? data->app_Title : (STRPTR) "Unnamed";
643 nb.nb_Title =
644 data->app_Version ? data->app_Version : (STRPTR) "Unnamed";
645 nb.nb_Descr =
646 data->app_Description ? data->
647 app_Description : (STRPTR) "?";
648 nb.nb_Unique = 0;
649 nb.nb_Flags = COF_SHOW_HIDE;
650 nb.nb_Pri = data->app_BrokerPri;
651 nb.nb_Port = data->app_BrokerPort;
652 nb.nb_ReservedChannel = 0;
654 if (strncmp(nb.nb_Title, "$VER: ", 6) == 0)
655 nb.nb_Title += 6;
657 data->app_Broker = CxBroker(&nb, 0);
659 if (data->app_Broker)
661 if (data->app_Active)
662 ActivateCxObj(data->app_Broker, 1);
667 if (data->app_UseRexx)
669 data->app_RexxPort = CreateMsgPort();
670 if (data->app_RexxPort)
672 data->app_RexxPort->mp_Node.ln_Name = StrDup(data->app_Base);
673 if (data->app_RexxPort->mp_Node.ln_Name != NULL)
675 D(bug("[MUI] %s is using REXX!\n",
676 data->app_RexxPort->mp_Node.ln_Name));
677 char *i;
678 for (i = data->app_RexxPort->mp_Node.ln_Name; *i != '\0';
679 i++)
681 *i = toupper(*i);
683 AddPort(data->app_RexxPort);
685 else
687 DeleteMsgPort(data->app_RexxPort);
688 data->app_RexxPort = NULL;
693 if (data->app_Menustrip)
694 DoMethod(data->app_Menustrip, MUIM_ConnectParent, (IPTR) obj);
696 data->app_AppPort = CreateMsgPort();
697 data->app_GlobalInfo.mgi_AppPort = data->app_AppPort;
698 if (data->app_AppPort == NULL)
700 CoerceMethod(cl, obj, OM_DISPOSE);
701 return 0;
704 ObtainSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
705 data->app_TrackingNode.tn_Application = obj;
706 AddTail((struct List *)&MUIMB(MUIMasterBase)->Applications,
707 (struct Node *)&data->app_TrackingNode);
708 data->app_is_TNode_in_list = TRUE;
709 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
711 return (IPTR) obj;
716 /**************************************************************************
717 OM_DISPOSE
718 **************************************************************************/
719 static IPTR Application__OM_DISPOSE(struct IClass *cl, Object *obj,
720 Msg msg)
722 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
723 struct RIDNode *rid;
725 long positionmode;
726 if (data->app_Base)
728 char filename[255];
729 positionmode = data->app_GlobalInfo.mgi_Prefs->window_position;
730 if (positionmode >= 1)
732 snprintf(filename, 255, "ENV:zune/%s.prefs", data->app_Base);
733 DoMethod(data->app_GlobalInfo.mgi_Configdata,
734 MUIM_Configdata_Save, (IPTR) filename);
736 if (positionmode == 2)
738 snprintf(filename, 255, "ENVARC:zune/%s.prefs", data->app_Base);
739 DoMethod(data->app_GlobalInfo.mgi_Configdata,
740 MUIM_Configdata_Save, (IPTR) filename);
744 if (data->app_is_TNode_in_list)
746 ObtainSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
747 Remove((struct Node *)&data->app_TrackingNode);
748 ReleaseSemaphore(&MUIMB(MUIMasterBase)->ZuneSemaphore);
751 if (data->app_WindowFamily)
753 struct MinList *children = NULL;
754 Object *cstate;
755 Object *child;
757 /* special loop because the next object may have been removed/freed by
758 * the previous. so restart from listhead each time.
760 while (1)
762 get(data->app_WindowFamily, MUIA_Family_List, &children);
763 if (children == NULL)
764 break;
766 cstate = (Object *) children->mlh_Head;
767 if ((child = NextObject(&cstate)))
769 D(bug("Application_Dispose(%p) : OM_REMMEMBER(%p)\n", obj,
770 child));
771 DoMethod(obj, OM_REMMEMBER, (IPTR) child);
772 D(bug("Application_Dispose(%p) : MUI_DisposeObject(%p)\n",
773 obj, child));
774 MUI_DisposeObject(child);
777 else
779 break;
782 MUI_DisposeObject(data->app_WindowFamily);
785 if (data->app_Menustrip)
786 MUI_DisposeObject(data->app_Menustrip);
788 if (data->app_VersionAllocated && data->app_Version != NULL)
790 FreeVec(data->app_Version);
793 /* free commodities stuff */
795 if (data->app_Broker)
797 DeleteCxObjAll(data->app_Broker);
800 if (data->app_BrokerPort)
802 struct Message *msg;
804 while ((msg = GetMsg(data->app_BrokerPort)))
806 ReplyMsg(msg);
809 DeleteMsgPort(data->app_BrokerPort);
812 /* free timer stuff */
813 if (data->app_TimerReq)
815 if (data->app_TimerReq->tr_node.io_Device)
817 while (data->app_TimerOutstanding)
819 if (Wait(1L << data->app_TimerPort->
820 mp_SigBit | 4096) & 4096)
821 break;
822 data->app_TimerOutstanding--;
824 CloseDevice((struct IORequest *)data->app_TimerReq);
826 DeleteIORequest((struct IORequest *)data->app_TimerReq);
828 DeleteMsgPort(data->app_TimerPort);
830 if (data->app_RexxPort)
832 struct Message *msg;
833 while ((msg = GetMsg(data->app_RexxPort)))
835 ReplyMsg(msg);
837 RemPort(data->app_RexxPort);
839 FreeVec(data->app_RexxPort->mp_Node.ln_Name);
840 DeleteMsgPort(data->app_RexxPort);
843 if (data->app_AppIcon)
844 RemoveAppIcon(data->app_AppIcon);
846 if (data->app_DefaultDiskObject)
847 FreeDiskObject(data->app_DefaultDiskObject);
849 if (data->app_AppPort)
851 struct Message *msg;
852 while ((msg = GetMsg(data->app_AppPort)))
853 ReplyMsg(msg);
855 DeleteMsgPort(data->app_AppPort);
858 if (data->app_GlobalInfo.mgi_Configdata)
859 MUI_DisposeObject(data->app_GlobalInfo.mgi_Configdata);
861 DeleteMsgPort(data->app_GlobalInfo.mgi_WindowsPort);
863 FreeVec(data->app_Base);
865 /* free returnid stuff */
867 while ((rid =
868 (struct RIDNode *)RemHead((struct List *)&data->
869 app_ReturnIDQueue)))
871 DeleteRIDNode(data, rid);
874 return DoSuperMethodA(cl, obj, msg);
878 /**************************************************************************
879 OM_SET
880 **************************************************************************/
881 static IPTR Application__OM_SET(struct IClass *cl, Object *obj,
882 struct opSet *msg)
884 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
885 struct TagItem *tags = msg->ops_AttrList;
886 struct TagItem *tag;
888 /* There are many ways to find out what tag items provided by set()
889 ** we do know. The best way should be using NextTagItem() and simply
890 ** browsing through the list.
892 while ((tag = NextTagItem(&tags)) != NULL)
894 IPTR *addr;
895 switch (tag->ti_Tag)
898 case MUIA_Application_SearchWinId:
899 data->searchwinid = tag->ti_Data;
900 break;
902 case MUIA_Application_CopyWinPosToApp:
903 addr = (IPTR *) tag->ti_Data;
904 CopyMem((CONST_APTR) tag->ti_Data, &data->winposused, *(addr));
905 break;
907 case MUIA_Application_SetWinPos:
909 struct windowpos *winp;
910 winp = (struct windowpos *)tag->ti_Data;
911 //kprintf("SetWinPos %d %d %d %d %d\n", winp->id, winp->x1,
912 // winp->y1, winp->w1, winp->h1);
913 int i;
914 for (i = 0; i < MAXWINS - 1; i++)
916 if (data->winpos[i].w1)
918 if (winp->id == data->winpos[i].id)
920 //existing entry is overwritten
921 data->winpos[i].x1 = winp->x1;
922 data->winpos[i].y1 = winp->y1;
923 data->winpos[i].w1 = winp->w1;
924 data->winpos[i].h1 = winp->h1;
925 data->winpos[i].x2 = winp->x2;
926 data->winpos[i].y2 = winp->y2;
927 data->winpos[i].w2 = winp->w2;
928 data->winpos[i].h2 = winp->h2;
929 break;
932 else
934 // a new entry is added
935 data->winpos[i].id = winp->id;
936 data->winpos[i].x1 = winp->x1;
937 data->winpos[i].y1 = winp->y1;
938 data->winpos[i].w1 = winp->w1;
939 data->winpos[i].h1 = winp->h1;
940 data->winpos[i].x2 = winp->x2;
941 data->winpos[i].y2 = winp->y2;
942 data->winpos[i].w2 = winp->w2;
943 data->winpos[i].h2 = winp->h2;
944 break;
948 break;
950 case MUIA_Application_Configdata:
951 DoMethod(obj, MUIM_Application_PushMethod, (IPTR) obj, 2,
952 MUIM_Application_SetConfigdata, tag->ti_Data);
953 break;
955 case MUIA_Application_HelpFile:
956 data->app_HelpFile = (STRPTR) tag->ti_Data;
957 break;
959 case MUIA_Application_Iconified:
961 BOOL do_iconify = tag->ti_Data == 1;
962 if (data->app_Iconified != do_iconify)
964 data->app_Iconified = do_iconify;
966 nnset(obj, MUIA_ShowMe, !data->app_Iconified);
968 /* Inform workbench.library */
969 if (data->app_Iconified)
971 STRPTR appname =
972 data->app_Title ? data->
973 app_Title : (STRPTR) "Unnamed";
974 struct DiskObject *dobj =
975 (struct DiskObject *)XGET(obj,
976 MUIA_Application_DiskObject);
978 if (dobj == NULL)
980 /* Get default AppIcon in ENV:SYS or ENVARC:SYS */
981 dobj = GetDefDiskObject(WBAPPICON);
982 if (dobj)
983 data->app_DefaultDiskObject = dobj;
984 else
986 /* First default: ENV:SYS/def_MUI.info */
987 dobj = GetDiskObject("ENV:SYS/def_MUI");
988 if (dobj)
989 data->app_DefaultDiskObject = dobj;
990 else
992 /* Second default: ENV:SYS/def_Zune.info */
993 dobj =
994 GetDiskObject("ENV:SYS/def_Zune");
995 if (dobj)
996 data->app_DefaultDiskObject = dobj;
997 else
999 /* Third default: default tool icon */
1000 dobj = GetDefDiskObject(WBTOOL);
1001 if (dobj)
1002 data->app_DefaultDiskObject =
1003 dobj;
1009 if (dobj == NULL)
1010 break;
1012 dobj->do_CurrentX = NO_ICON_POSITION;
1013 dobj->do_CurrentY = NO_ICON_POSITION;
1015 data->app_AppIcon =
1016 AddAppIconA(0L, 0L, appname, data->app_AppPort,
1017 BNULL, dobj, NULL);
1019 else
1021 if (data->app_AppIcon)
1023 RemoveAppIcon(data->app_AppIcon);
1024 data->app_AppIcon = NULL;
1026 if (data->app_DefaultDiskObject)
1028 FreeDiskObject(data->app_DefaultDiskObject);
1029 data->app_DefaultDiskObject = NULL;
1034 break;
1036 case MUIA_ShowMe:
1038 /* Ok ok, you think this stinks? Well, think of it as
1039 an attribute belonging to an interface which
1040 MUIC_Application, together with MUIC_Area and a few
1041 others implement. It makes sense now, yes? */
1042 struct List *wlist = NULL;
1043 APTR wstate;
1044 Object *curwin = NULL;
1045 Object *lastwin = NULL;
1047 /* MUIA_ShowMe can cause MUIM_Setup/MUIM_Cleanup to be issued.
1048 * On the other hand it is allowed to add/remove other
1049 * application windows in MUIM_Setup/MUIM_Cleanup.
1050 * This means after processing a window from internal list,
1051 * the list needs to be re-read and iteration started again,
1052 * because wstate can become invalid.
1053 * Note: The code below assumes that the window won't remove
1054 * itself from the list.
1057 while (1)
1059 get(data->app_WindowFamily, MUIA_Family_List, &wlist);
1060 wstate = (Object *) wlist->lh_Head;
1061 while ((curwin = NextObject(&wstate)))
1063 if (lastwin == NULL)
1064 break;
1065 if (curwin == lastwin)
1067 curwin = NextObject(&wstate);
1068 break;
1072 /* This is the window to be processed */
1073 if (curwin)
1075 set(curwin, MUIA_ShowMe, tag->ti_Data);
1076 lastwin = curwin;
1078 else
1080 /* No more windows */
1081 break;
1085 break;
1087 case MUIA_Application_Sleep:
1089 struct List *wlist = NULL;
1090 APTR wstate;
1091 Object *curwin;
1093 if (tag->ti_Data)
1095 data->app_SleepCount++;
1096 if (data->app_SleepCount == 1)
1098 get(obj, MUIA_Application_WindowList, &wlist);
1099 if (wlist)
1101 wstate = wlist->lh_Head;
1102 while ((curwin = NextObject(&wstate)))
1104 set(curwin, MUIA_Window_Sleep, TRUE);
1109 else
1111 data->app_SleepCount--;
1112 if (data->app_SleepCount == 0)
1114 get(obj, MUIA_Application_WindowList, &wlist);
1115 if (wlist)
1117 wstate = wlist->lh_Head;
1118 while ((curwin = NextObject(&wstate)))
1120 set(curwin, MUIA_Window_Sleep, FALSE);
1126 break;
1128 case MUIA_Application_MenuAction:
1129 data->app_MenuAction = tag->ti_Data;
1130 break;
1132 case MUIA_Application_BrokerHook:
1133 data->app_BrokerHook = (struct Hook *)tag->ti_Data;
1134 break;
1136 case MUIA_Application_Active:
1137 data->app_Active = tag->ti_Data ? TRUE : FALSE;
1138 if (data->app_Broker)
1140 ActivateCxObj(data->app_Broker, data->app_Active);
1142 break;
1144 case MUIA_Application_Commands:
1145 data->app_Commands = (struct MUI_Command *)tag->ti_Data;
1146 break;
1148 case MUIA_Application_RexxString:
1149 data->app_RexxString = (STRPTR) tag->ti_Data;
1150 break;
1152 case MUIA_Application_RexxHook:
1153 data->app_RexxHook = (struct Hook *)tag->ti_Data;
1154 break;
1156 case MUIA_Application_DiskObject:
1157 data->app_DiskObject = (struct DiskObject *)tag->ti_Data;
1158 break;
1162 return DoSuperMethodA(cl, obj, (Msg) msg);
1167 * OM_GET
1169 static IPTR Application__OM_GET(struct IClass *cl, Object *obj,
1170 struct opGet *msg)
1172 #define STORE *(msg->opg_Storage)
1174 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1176 switch (msg->opg_AttrID)
1178 case MUIA_Application_GetWinPosAddr:
1179 STORE = (IPTR) & data->winposused;
1180 return TRUE;
1182 case MUIA_Application_GetWinPosSize:
1184 int i;
1185 for (i = 0; i < MAXWINS - 1; i++)
1187 if (!data->winpos[i].w1)
1189 i *= sizeof(struct windowpos);
1190 i += sizeof(long);
1191 data->winposused = i;
1192 STORE = i;
1193 return (TRUE);
1196 STORE = 0;
1197 return TRUE;
1200 case MUIA_Application_GetWinPos:
1202 int i;
1203 if (data->searchwinid)
1205 for (i = 0; i < MAXWINS - 1; i++)
1207 if (data->winpos[i].w1)
1209 if (data->searchwinid == data->winpos[i].id)
1211 STORE = (IPTR) & data->winpos[i].id;
1212 return 1;
1215 else
1216 break;
1219 STORE = 0;
1220 return 1;
1222 return TRUE;
1224 case MUIA_Version:
1225 STORE = __version;
1226 return TRUE;
1228 case MUIA_Revision:
1229 STORE = __revision;
1230 return TRUE;
1232 case MUIA_Application_Author:
1233 STORE = (IPTR) data->app_Author;
1234 return TRUE;
1236 case MUIA_Application_Base:
1237 STORE = (IPTR) data->app_Base;
1238 return TRUE;
1240 case MUIA_Application_Copyright:
1241 STORE = (IPTR) data->app_Copyright;
1242 return TRUE;
1244 case MUIA_Application_Description:
1245 STORE = (IPTR) data->app_Description;
1246 return TRUE;
1248 case MUIA_Application_DoubleStart:
1249 return TRUE;
1251 case MUIA_Application_ForceQuit:
1252 STORE = (IPTR) data->app_ForceQuit;
1253 return TRUE;
1255 case MUIA_Application_HelpFile:
1256 STORE = (IPTR) data->app_HelpFile;
1257 return TRUE;
1259 case MUIA_Application_Iconified:
1260 STORE = (IPTR) data->app_Iconified;
1261 return TRUE;
1263 case MUIA_Application_Title:
1264 STORE = (IPTR) data->app_Title;
1265 return TRUE;
1267 case MUIA_Application_Version:
1268 STORE = (IPTR) data->app_Version;
1269 return TRUE;
1271 case MUIA_Application_Version_Number:
1272 STORE = (IPTR) data->app_Version_Number;
1273 return TRUE;
1275 case MUIA_Application_Version_Date:
1276 STORE = (IPTR) data->app_Version_Date;
1277 return TRUE;
1279 case MUIA_Application_Version_Extra:
1280 STORE = (IPTR) data->app_Version_Extra;
1281 return TRUE;
1283 case MUIA_Application_WindowList:
1284 return GetAttr(MUIA_Family_List, data->app_WindowFamily,
1285 msg->opg_Storage);
1287 case MUIA_Application_Menustrip:
1288 STORE = (IPTR) data->app_Menustrip;
1289 return TRUE;
1291 case MUIA_Application_MenuAction:
1292 STORE = (IPTR) data->app_MenuAction;
1293 return TRUE;
1295 case MUIA_Application_BrokerPort:
1296 STORE = (IPTR) data->app_BrokerPort;
1297 return TRUE;
1299 case MUIA_Application_BrokerPri:
1300 STORE = (IPTR) data->app_BrokerPri;
1301 return TRUE;
1303 case MUIA_Application_BrokerHook:
1304 STORE = (IPTR) data->app_BrokerHook;
1305 return TRUE;
1307 case MUIA_Application_Broker:
1308 STORE = (IPTR) data->app_Broker;
1309 return TRUE;
1311 case MUIA_Application_Active:
1312 STORE = data->app_Active;
1313 return TRUE;
1315 case MUIA_Application_Commands:
1316 STORE = (IPTR) data->app_Commands;
1317 return TRUE;
1319 case MUIA_Application_RexxMsg:
1320 STORE = (IPTR) data->app_RexxMsg;
1321 return TRUE;
1323 case MUIA_Application_RexxHook:
1324 STORE = (IPTR) data->app_RexxHook;
1325 return TRUE;
1327 case MUIA_Application_DiskObject:
1328 STORE = (IPTR) data->app_DiskObject;
1329 return TRUE;
1332 /* our handler didn't understand the attribute, we simply pass
1333 ** it to our superclass now
1335 return (DoSuperMethodA(cl, obj, (Msg) msg));
1336 #undef STORE
1340 /**************************************************************************
1341 OM_ADDMEMBER
1342 **************************************************************************/
1343 static IPTR Application__OM_ADDMEMBER(struct IClass *cl, Object *obj,
1344 struct opMember *msg)
1346 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1348 D(bug("Application_AddMember: Adding 0x%lx to window member list\n",
1349 msg->opam_Object));
1351 DoMethodA(data->app_WindowFamily, (Msg) msg);
1352 /* Application knows its GlobalInfo, so we can inform window */
1353 DoMethod(msg->opam_Object, MUIM_ConnectParent, (IPTR) obj);
1354 return TRUE;
1358 /**************************************************************************
1359 OM_REMMEMBER
1360 **************************************************************************/
1361 static IPTR Application__OM_REMMEMBER(struct IClass *cl, Object *obj,
1362 struct opMember *msg)
1364 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1366 D(bug("Application_RemMember: Removing 0x%lx from window member list\n",
1367 msg->opam_Object));
1369 DoMethod(msg->opam_Object, MUIM_DisconnectParent);
1370 DoMethodA(data->app_WindowFamily, (Msg) msg);
1372 return TRUE;
1377 /**************************************************************************
1378 MUIM_Application_AddInputHandler
1379 **************************************************************************/
1380 static IPTR Application__MUIM_AddInputHandler(struct IClass *cl,
1381 Object *obj, struct MUIP_Application_AddInputHandler *msg)
1383 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1385 if (msg->ihnode->ihn_Flags & MUIIHNF_TIMER)
1387 struct timerequest_ext *time_ext =
1388 (struct timerequest_ext *)AllocVec(sizeof(struct
1389 timerequest_ext), MEMF_PUBLIC);
1390 if (time_ext)
1392 /* Store the request inside the input handler, so that we can
1393 ** remove the inputhandler without problems */
1394 msg->ihnode->ihn_Node.mln_Pred = (struct MinNode *)time_ext;
1396 time_ext->treq = *data->app_TimerReq;
1397 time_ext->treq.tr_node.io_Command = TR_ADDREQUEST;
1398 time_ext->treq.tr_time.tv_secs = msg->ihnode->ihn_Millis / 1000;
1399 time_ext->treq.tr_time.tv_micro =
1400 (msg->ihnode->ihn_Millis % 1000) * 1000;
1401 time_ext->ihn = msg->ihnode;
1402 SendIO((struct IORequest *)time_ext);
1405 else
1406 AddTail((struct List *)&data->app_IHList,
1407 (struct Node *)msg->ihnode);
1408 return TRUE;
1412 /**************************************************************************
1413 MUIM_Application_RemInputHandler
1414 **************************************************************************/
1415 static IPTR Application__MUIM_RemInputHandler(struct IClass *cl,
1416 Object *obj, struct MUIP_Application_RemInputHandler *msg)
1418 //struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1419 if (msg->ihnode->ihn_Flags & MUIIHNF_TIMER)
1421 struct timerequest_ext *time_ext =
1422 (struct timerequest_ext *)msg->ihnode->ihn_Node.mln_Pred;
1423 if (!CheckIO((struct IORequest *)time_ext))
1424 AbortIO((struct IORequest *)time_ext);
1425 WaitIO((struct IORequest *)time_ext);
1426 FreeVec(time_ext);
1428 else
1429 Remove((struct Node *)msg->ihnode);
1431 return TRUE;
1435 void _zune_window_message(struct IntuiMessage *imsg); /* from window.c */
1438 * MUIM_Application_InputBuffered : process all pending events
1440 static IPTR Application__MUIM_InputBuffered(struct IClass *cl, Object *obj,
1441 struct MUIP_Application_InputBuffered *msg)
1443 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1444 struct IntuiMessage *imsg;
1446 /* process all pushed methods */
1447 while (application_do_pushed_method(data))
1450 imsg =
1451 (struct IntuiMessage *)GetMsg(data->app_GlobalInfo.mgi_WindowsPort);
1452 if (imsg != NULL)
1454 /* Let window object process message */
1455 _zune_window_message(imsg); /* will reply the message */
1457 return TRUE;
1460 /**************************************************************************
1461 MUIM_Application_NewInput : application main loop
1462 **************************************************************************/
1463 static IPTR Application__MUIM_NewInput(struct IClass *cl, Object *obj,
1464 struct MUIP_Application_NewInput *msg)
1466 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1467 struct RIDNode *rid;
1468 ULONG retval = 0;
1469 ULONG signal, signalmask;
1470 ULONG handler_mask = 0; /* the mask of the signal handlers */
1471 struct MinNode *mn;
1473 //struct MinNode ihn_Node;
1475 signal = *msg->signal;
1477 /* process all pushed methods */
1478 while (application_do_pushed_method(data))
1479 /* nothing */ ;
1481 /* query the signal for the handlers */
1482 for (mn = data->app_IHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
1484 struct MUI_InputHandlerNode *ihn;
1485 ihn = (struct MUI_InputHandlerNode *)mn;
1486 handler_mask |= ihn->ihn_Signals;
1489 signalmask = (1L << data->app_GlobalInfo.mgi_WindowsPort->mp_SigBit)
1490 | (1L << data->app_TimerPort->mp_SigBit) | handler_mask;
1492 if (data->app_Broker)
1493 signalmask |= (1L << data->app_BrokerPort->mp_SigBit);
1495 if (data->app_RexxPort)
1496 signalmask |= (1L << data->app_RexxPort->mp_SigBit);
1498 if (data->app_AppPort)
1499 signalmask |= (1L << data->app_AppPort->mp_SigBit);
1501 if (signal == 0)
1503 /* Stupid app which (always) passes 0 in signals. It's impossible to
1504 know which signals were really set as the app will already have
1505 called Wait() which has cleared the task's tc_SigRecvd. So assume
1506 the window, timer, and broker signals all to be set. Also all of
1507 the inputhandler signals (MUI does that too). */
1509 signal = signalmask;
1512 if (signal & signalmask)
1514 if (signal & (1L << data->app_GlobalInfo.mgi_WindowsPort->
1515 mp_SigBit))
1517 struct IntuiMessage *imsg;
1518 /* process all pushed methods */
1520 while ((imsg =
1521 (struct IntuiMessage *)GetMsg(data->app_GlobalInfo.
1522 mgi_WindowsPort)))
1524 /* Let window object process message */
1525 _zune_window_message(imsg); /* will reply the message */
1529 if (signal & (1L << data->app_TimerPort->mp_SigBit))
1531 struct timerequest_ext *time_ext;
1532 struct Node *n;
1533 struct List list;
1534 NewList(&list);
1536 /* At first we fetch all messages from the message port and store
1537 ** them in a list, we use the node of the Message here */
1538 while ((time_ext =
1539 (struct timerequest_ext *)GetMsg(data->app_TimerPort)))
1540 AddTail(&list, (struct Node *)time_ext);
1542 /* Now we proccess the list and resend the timer io, no loop can
1543 ** happen. We use RemHead() because the handler can remove it
1544 ** itself and so a FreeVec() could happen in
1545 ** MUIM_Application_RemInputHandler which would destroy the
1546 ** ln->Succ of course */
1547 while ((n = RemHead(&list)))
1549 struct timerequest_ext *time_ext =
1550 (struct timerequest_ext *)n;
1551 struct MUI_InputHandlerNode *ihn = time_ext->ihn;
1552 time_ext->treq.tr_time.tv_secs =
1553 time_ext->ihn->ihn_Millis / 1000;
1554 time_ext->treq.tr_time.tv_micro =
1555 (time_ext->ihn->ihn_Millis % 1000) * 1000;
1556 SendIO((struct IORequest *)&time_ext->treq);
1557 DoMethod(ihn->ihn_Object, ihn->ihn_Method);
1561 if (data->app_BrokerPort
1562 && (signal & (1L << data->app_BrokerPort->mp_SigBit)))
1564 CxMsg *msg;
1566 while ((msg = (CxMsg *) GetMsg(data->app_BrokerPort)))
1568 switch (CxMsgType(msg))
1570 case CXM_COMMAND:
1571 switch (CxMsgID(msg))
1573 case CXCMD_DISABLE:
1574 set(obj, MUIA_Application_Active, FALSE);
1575 break;
1577 case CXCMD_ENABLE:
1578 set(obj, MUIA_Application_Active, TRUE);
1579 break;
1581 case CXCMD_APPEAR:
1582 case CXCMD_DISAPPEAR:
1583 /* No default handling - application needs to be in
1584 * control of this */
1585 break;
1587 case CXCMD_KILL:
1588 SetSignal(SIGBREAKF_CTRL_C, SIGBREAKF_CTRL_C);
1589 break;
1591 break;
1594 if (data->app_BrokerHook)
1596 CallHookPkt(data->app_BrokerHook, obj, msg);
1599 ReplyMsg((struct Message *)msg);
1603 if (data->app_RexxPort
1604 && (signal & (1L << data->app_RexxPort->mp_SigBit)))
1607 D(bug("[MUI] Got Rexx message!\n"));
1608 struct Message *msg;
1609 while ((msg = GetMsg(data->app_RexxPort)))
1611 ReplyMsg(msg);
1615 if (data->app_AppPort
1616 && (signal & (1L << data->app_AppPort->mp_SigBit)))
1618 struct AppMessage *appmsg;
1619 while ((appmsg =
1620 (struct AppMessage *)GetMsg(data->app_AppPort)))
1622 if ((appmsg->am_Type == AMTYPE_APPICON)
1623 && (appmsg->am_NumArgs == 0)
1624 && (appmsg->am_ArgList == NULL)
1625 && (XGET(obj, MUIA_Application_Iconified) == TRUE))
1627 /* Reply before removing AppIcon */
1628 ReplyMsg((struct Message *)appmsg);
1629 set(obj, MUIA_Application_Iconified, FALSE);
1630 continue;
1632 else if (appmsg->am_Type == AMTYPE_APPWINDOW)
1634 set((Object *) appmsg->am_UserData, MUIA_AppMessage,
1635 appmsg);
1638 ReplyMsg((struct Message *)appmsg);
1642 if (signal & handler_mask)
1644 for (mn = data->app_IHList.mlh_Head; mn->mln_Succ;
1645 mn = mn->mln_Succ)
1647 struct MUI_InputHandlerNode *ihn;
1648 ihn = (struct MUI_InputHandlerNode *)mn;
1649 if (signal & ihn->ihn_Signals)
1650 DoMethod(ihn->ihn_Object, ihn->ihn_Method);
1655 /* process all pushed methods - again */
1656 while (application_do_pushed_method(data))
1657 /* nothing */ ;
1659 *msg->signal = signalmask;
1661 /* set return code */
1662 if ((rid =
1663 (struct RIDNode *)RemHead((struct List *)&data->
1664 app_ReturnIDQueue)))
1666 retval = rid->rid_Value;
1667 DeleteRIDNode(data, rid);
1668 return retval;
1670 return 0;
1673 /**************************************************************************
1674 MUIM_Application_Input : application main loop
1675 This method shouldn't be used in any new program. As it polls all signals.
1676 **************************************************************************/
1677 static IPTR Application__MUIM_Input(struct IClass *cl, Object *obj,
1678 struct MUIP_Application_Input *msg)
1680 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1681 ULONG signal = 0, handler_mask = 0;
1682 struct MinNode *mn;
1684 /* query the signal for the handlers */
1685 for (mn = data->app_IHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
1687 struct MUI_InputHandlerNode *ihn;
1688 ihn = (struct MUI_InputHandlerNode *)mn;
1689 handler_mask |= ihn->ihn_Flags;
1692 signal = (1L << data->app_GlobalInfo.mgi_WindowsPort->mp_SigBit)
1693 | (1L << data->app_TimerPort->mp_SigBit) | handler_mask;
1695 if (data->app_RexxPort)
1696 signal |= (1L << data->app_RexxPort->mp_SigBit);
1698 if (data->app_AppPort)
1699 signal |= (1L << data->app_AppPort->mp_SigBit);
1702 *msg->signal = signal;
1703 return Application__MUIM_NewInput(cl, obj, (APTR) msg);
1706 /**************************************************************************
1707 MUIM_Application_PushMethod: Add a method in the method FIFO. Will
1708 be executed in the next event loop.
1709 **************************************************************************/
1710 static IPTR Application__MUIM_PushMethod(struct IClass *cl, Object *obj,
1711 struct MUIP_Application_PushMethod *msg)
1713 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1714 struct MQNode *mq;
1715 LONG i;
1716 IPTR *m = (IPTR *) & msg->count; /* FIXME: breaks on 64-bit BigEndian systems */
1717 LONG count;
1719 count = msg->count & 0xf; /* MUI4 uses count to pass additional info */
1721 mq = CreateMQNode(count);
1722 if (!mq)
1723 return 0;
1724 mq->mq_Dest = msg->dest;
1726 /* fill msg */
1727 for (i = 0; i < count; i++)
1728 mq->mq_Msg[i] = *(m + 1 + i);
1730 /* enqueue method */
1731 ObtainSemaphore(&data->app_MethodSemaphore);
1732 AddTail((struct List *)&data->app_MethodQueue, (struct Node *)mq);
1733 ReleaseSemaphore(&data->app_MethodSemaphore);
1735 /* CHECKME: to wake task up as soon as possible! */
1736 Signal(data->app_Task,
1737 1L << data->app_GlobalInfo.mgi_WindowsPort->mp_SigBit);
1739 return TRUE;
1744 * MUIM_Application_ReturnID : Tell MUI to return the given id with
1745 * the next call to MUIM_Application_NewInput. kinda obsolete :)
1747 static IPTR Application__MUIM_ReturnID(struct IClass *cl, Object *obj,
1748 struct MUIP_Application_ReturnID *msg)
1750 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1751 struct RIDNode *rid;
1754 if (!data->app_RIDMemChunk)
1756 data->app_RIDMemChunk =
1757 g_mem_chunk_create(struct RIDNode, 10, G_ALLOC_AND_FREE);
1760 rid = CreateRIDNode(data, msg->retid);
1761 if (!rid)
1762 return FALSE;
1763 AddTail((struct List *)&data->app_ReturnIDQueue, (struct Node *)rid);
1764 return TRUE;
1769 * MUIM_FindUData : tests if the MUIA_UserData of the object
1770 * contains the given <udata> and returns the object pointer in this case.
1772 static IPTR Application__MUIM_FindUData(struct IClass *cl, Object *obj,
1773 struct MUIP_FindUData *msg)
1775 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1777 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
1778 return (IPTR) obj;
1780 return DoMethodA(data->app_WindowFamily, (Msg) msg);
1785 * MUIM_GetUData : This method tests if the MUIA_UserData of the object
1786 * contains the given <udata> and gets <attr> to <storage> for itself
1787 * in this case.
1789 static IPTR Application__MUIM_GetUData(struct IClass *cl, Object *obj,
1790 struct MUIP_GetUData *msg)
1792 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1794 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
1796 get(obj, msg->attr, msg->storage);
1797 return TRUE;
1799 return DoMethodA(data->app_WindowFamily, (Msg) msg);
1804 * MUIM_SetUData : This method tests if the MUIA_UserData of the object
1805 * contains the given <udata> and sets <attr> to <val> for itself in this case.
1807 static IPTR Application__MUIM_SetUData(struct IClass *cl, Object *obj,
1808 struct MUIP_SetUData *msg)
1810 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1812 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
1813 set(obj, msg->attr, msg->val);
1815 DoMethodA(data->app_WindowFamily, (Msg) msg);
1816 return TRUE;
1821 * MUIM_SetUDataOnce : This method tests if the MUIA_UserData of the object
1822 * contains the given <udata> and sets <attr> to <val> for itself in this case.
1824 static IPTR Application__MUIM_SetUDataOnce(struct IClass *cl, Object *obj,
1825 struct MUIP_SetUDataOnce *msg)
1827 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1829 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
1831 set(obj, msg->attr, msg->val);
1832 return TRUE;
1834 return DoMethodA(data->app_WindowFamily, (Msg) msg);
1838 /****** Application.mui/MUIM_Application_AboutMUI ****************************
1840 * NAME
1841 * MUIM_Application_AboutMUI (V14)
1843 * SYNOPSIS
1844 * DoMethod(obj, MUIM_Application_AboutMUI, Object refwindow);
1846 * FUNCTION
1847 * Show Zune's About window.
1849 * INPUTS
1850 * refwindow - the window object relative to which the About window will
1851 * be placed.
1853 * SEE ALSO
1854 * MUIA_Window_RefWindow.
1856 ******************************************************************************
1860 static IPTR Application__MUIM_AboutMUI(struct IClass *cl, Object *obj,
1861 struct MUIP_Application_AboutMUI *msg)
1863 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1865 if (!data->app_AboutWin)
1867 data->app_AboutWin = AboutmuiObject,
1868 msg->refwindow ? MUIA_Window_RefWindow : TAG_IGNORE,
1869 msg->refwindow, MUIA_Window_LeftEdge,
1870 MUIV_Window_LeftEdge_Centered, MUIA_Window_TopEdge,
1871 MUIV_Window_TopEdge_Centered, MUIA_Aboutmui_Application, obj,
1872 End;
1875 if (data->app_AboutWin)
1876 set(data->app_AboutWin, MUIA_Window_Open, TRUE);
1878 return 0;
1881 static IPTR Application__MUIM_SetConfigdata(struct IClass *cl, Object *obj,
1882 struct MUIP_Application_SetConfigdata *msg)
1884 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1885 struct MinList *children = NULL;
1886 Object *cstate;
1887 Object *child;
1889 get(data->app_WindowFamily, MUIA_Family_List, &children);
1890 if (children)
1892 cstate = (Object *) children->mlh_Head;
1893 if ((child = NextObject(&cstate)))
1895 D(bug("closing window %p\n", child));
1897 set(child, MUIA_Window_Open, FALSE);
1901 if (data->app_GlobalInfo.mgi_Configdata)
1902 MUI_DisposeObject(data->app_GlobalInfo.mgi_Configdata);
1903 data->app_GlobalInfo.mgi_Configdata = msg->configdata;
1904 get(data->app_GlobalInfo.mgi_Configdata, MUIA_Configdata_ZunePrefs,
1905 &data->app_GlobalInfo.mgi_Prefs);
1907 DoMethod(obj, MUIM_Application_PushMethod, (IPTR) obj, 1,
1908 MUIM_Application_OpenWindows);
1909 return 0;
1913 /* MUIM_Application_OpenWindows
1914 * Opens all windows of an application
1916 static IPTR Application__MUIM_OpenWindows(struct IClass *cl, Object *obj,
1917 struct MUIP_Application_OpenWindows *msg)
1919 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1920 struct MinList *children = NULL;
1921 Object *cstate;
1922 Object *child;
1924 get(data->app_WindowFamily, MUIA_Family_List, &children);
1925 if (!children)
1926 return 0;
1928 cstate = (Object *) children->mlh_Head;
1929 if ((child = NextObject(&cstate)))
1931 set(child, MUIA_Window_Open, TRUE);
1933 return 0;
1937 static IPTR Application__MUIM_OpenConfigWindow(struct IClass *cl,
1938 Object *obj, struct MUIP_Application_OpenConfigWindow *msg)
1940 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
1941 struct TagItem tags[] = {
1942 {SYS_Asynch, FALSE},
1943 {SYS_Input, 0},
1944 {SYS_Output, 0},
1945 {NP_StackSize, AROS_STACKSIZE},
1946 {TAG_DONE}
1948 char cmd[255];
1950 snprintf(cmd, 255, "sys:prefs/Zune %s %ld",
1951 data->app_Base ? data->app_Base : (STRPTR) "", (long)obj);
1953 if (SystemTagList(cmd, tags) == -1)
1955 return 0;
1957 Delay(50);
1959 if (data->app_Base)
1961 snprintf(cmd, 255, "ENV:zune/%s.prefs", data->app_Base);
1962 DoMethod(data->app_GlobalInfo.mgi_Configdata, MUIM_Configdata_Load,
1963 (IPTR) cmd);
1966 return 1;
1969 static IPTR Application__MUIM_Execute(Class *CLASS, Object *self,
1970 Msg message)
1972 IPTR signals = 0L;
1974 while
1975 (DoMethod(self, MUIM_Application_NewInput, (IPTR) & signals)
1976 != MUIV_Application_ReturnID_Quit)
1978 if (signals)
1980 signals = Wait(signals | SIGBREAKF_CTRL_C);
1981 if (signals & SIGBREAKF_CTRL_C)
1982 break;
1986 return 0;
1990 static IPTR Application__MUIM_UpdateMenus(struct IClass *cl, Object *obj,
1991 Msg message)
1993 struct List *wlist = NULL;
1994 APTR wstate;
1995 Object *curwin;
1997 get(obj, MUIA_Application_WindowList, &wlist);
1999 if (wlist)
2001 wstate = wlist->lh_Head;
2002 while ((curwin = NextObject(&wstate)))
2004 DoMethod(curwin, MUIM_Window_UpdateMenu);
2008 return 0;
2011 static IPTR Application__MUIM_Load(struct IClass *cl, Object *obj,
2012 struct MUIP_Application_Load *message)
2014 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
2015 struct IFFHandle *iff;
2016 char name[1024];
2017 BPTR fh;
2018 Object *dataspace;
2019 struct MinList *children = NULL;
2020 Object *cstate;
2021 Object *child;
2023 if (!data->app_Base)
2024 return 0;
2026 dataspace = MUI_NewObject(MUIC_Dataspace, TAG_DONE);
2027 if (!dataspace)
2028 return 0;
2030 if (message->name == MUIV_Application_Load_ENV)
2031 snprintf(name, sizeof(name), "ENV:Zune/%s.cfg", data->app_Base);
2032 else if (message->name == MUIV_Application_Load_ENVARC)
2033 snprintf(name, sizeof(name), "ENVARC:Zune/%s.cfg", data->app_Base);
2034 else
2035 strncpy(name, message->name, sizeof(name));
2037 fh = Open(name, MODE_OLDFILE);
2038 if (fh)
2040 if ((iff = AllocIFF()))
2042 iff->iff_Stream = (IPTR) fh;
2044 InitIFFasDOS(iff);
2046 if (!OpenIFF(iff, IFFF_READ))
2048 if (!StopChunk(iff, ID_PREF, ID_MUIO))
2050 if (!ParseIFF(iff, IFFPARSE_SCAN))
2052 DoMethod(dataspace, MUIM_Dataspace_ReadIFF, iff,
2053 ID_PREF, ID_MUIO);
2057 CloseIFF(iff);
2059 FreeIFF(iff);
2061 Close(fh);
2064 get(data->app_WindowFamily, MUIA_Family_List, &children);
2065 cstate = (Object *) children->mlh_Head;
2066 while ((child = NextObject(&cstate)))
2068 DoMethod(child, MUIM_Import, dataspace);
2071 MUI_DisposeObject(dataspace);
2073 return 0;
2076 static IPTR Application__MUIM_Save(struct IClass *cl, Object *obj,
2077 struct MUIP_Application_Save *message)
2079 struct MUI_ApplicationData *data = INST_DATA(cl, obj);
2080 struct IFFHandle *iff;
2081 char name[1024];
2082 BPTR fh;
2083 Object *dataspace;
2084 struct MinList *children = NULL;
2085 Object *cstate;
2086 Object *child;
2088 if (!data->app_Base)
2089 return 0;
2091 dataspace = MUI_NewObject(MUIC_Dataspace, TAG_DONE);
2092 if (!dataspace)
2093 return 0;
2095 get(data->app_WindowFamily, MUIA_Family_List, &children);
2096 cstate = (Object *) children->mlh_Head;
2097 while ((child = NextObject(&cstate)))
2099 DoMethod(child, MUIM_Export, dataspace);
2102 if (message->name == MUIV_Application_Save_ENV)
2103 snprintf(name, sizeof(name), "ENV:Zune/%s.cfg", data->app_Base);
2104 else if (message->name == MUIV_Application_Save_ENVARC)
2105 snprintf(name, sizeof(name), "ENVARC:Zune/%s.cfg", data->app_Base);
2106 else
2107 strncpy(name, message->name, sizeof(name));
2109 fh = Open(name, MODE_NEWFILE);
2110 if (fh)
2112 if ((iff = AllocIFF()))
2114 iff->iff_Stream = (IPTR) fh;
2116 InitIFFasDOS(iff);
2118 if (!OpenIFF(iff, IFFF_WRITE))
2120 if (!PushChunk(iff, ID_PREF, ID_FORM, IFFSIZE_UNKNOWN))
2122 if (!PushChunk(iff, ID_PREF, ID_PRHD,
2123 sizeof(struct FilePrefHeader)))
2125 struct FilePrefHeader head;
2127 head.ph_Version = PHV_CURRENT;
2128 head.ph_Type = 0;
2129 head.ph_Flags[0] =
2130 head.ph_Flags[1] =
2131 head.ph_Flags[2] = head.ph_Flags[3] = 0;
2133 if (WriteChunkBytes(iff, &head,
2134 sizeof(head)) == sizeof(head))
2136 PopChunk(iff);
2137 DoMethod(dataspace, MUIM_Dataspace_WriteIFF,
2138 iff, ID_PREF, ID_MUIO);
2140 else
2142 PopChunk(iff);
2145 PopChunk(iff);
2147 CloseIFF(iff);
2149 FreeIFF(iff);
2151 Close(fh);
2154 MUI_DisposeObject(dataspace);
2156 return 0;
2160 * The class dispatcher
2162 BOOPSI_DISPATCHER(IPTR, Application_Dispatcher, cl, obj, msg)
2164 switch (msg->MethodID)
2166 case OM_NEW:
2167 return Application__OM_NEW(cl, obj, (struct opSet *)msg);
2168 case OM_DISPOSE:
2169 return Application__OM_DISPOSE(cl, obj, msg);
2170 case OM_SET:
2171 return Application__OM_SET(cl, obj, (struct opSet *)msg);
2172 case OM_GET:
2173 return Application__OM_GET(cl, obj, (struct opGet *)msg);
2174 case OM_ADDMEMBER:
2175 return Application__OM_ADDMEMBER(cl, obj, (APTR) msg);
2176 case OM_REMMEMBER:
2177 return Application__OM_REMMEMBER(cl, obj, (APTR) msg);
2178 case MUIM_Application_AddInputHandler:
2179 return Application__MUIM_AddInputHandler(cl, obj, (APTR) msg);
2180 case MUIM_Application_RemInputHandler:
2181 return Application__MUIM_RemInputHandler(cl, obj, (APTR) msg);
2182 case MUIM_Application_Input:
2183 return Application__MUIM_Input(cl, obj, (APTR) msg);
2184 case MUIM_Application_InputBuffered:
2185 return Application__MUIM_InputBuffered(cl, obj, (APTR) msg);
2186 case MUIM_Application_NewInput:
2187 return Application__MUIM_NewInput(cl, obj, (APTR) msg);
2188 case MUIM_Application_PushMethod:
2189 return Application__MUIM_PushMethod(cl, obj, (APTR) msg);
2190 case MUIM_Application_ReturnID:
2191 return Application__MUIM_ReturnID(cl, obj, (APTR) msg);
2192 case MUIM_FindUData:
2193 return Application__MUIM_FindUData(cl, obj, (APTR) msg);
2194 case MUIM_GetUData:
2195 return Application__MUIM_GetUData(cl, obj, (APTR) msg);
2196 case MUIM_SetUData:
2197 return Application__MUIM_SetUData(cl, obj, (APTR) msg);
2198 case MUIM_SetUDataOnce:
2199 return Application__MUIM_SetUDataOnce(cl, obj, (APTR) msg);
2200 case MUIM_Application_AboutMUI:
2201 return Application__MUIM_AboutMUI(cl, obj, (APTR) msg);
2202 case MUIM_Application_SetConfigdata:
2203 return Application__MUIM_SetConfigdata(cl, obj, (APTR) msg);
2204 case MUIM_Application_OpenWindows:
2205 return Application__MUIM_OpenWindows(cl, obj, (APTR) msg);
2206 case MUIM_Application_OpenConfigWindow:
2207 return Application__MUIM_OpenConfigWindow(cl, obj, (APTR) msg);
2208 case MUIM_Application_Execute:
2209 return Application__MUIM_Execute(cl, obj, msg);
2210 case MUIM_Application_UpdateMenus:
2211 return Application__MUIM_UpdateMenus(cl, obj, msg);
2212 case MUIM_Application_Load:
2213 return Application__MUIM_Load(cl, obj, (APTR) msg);
2214 case MUIM_Application_Save:
2215 return Application__MUIM_Save(cl, obj, (APTR) msg);
2218 return (DoSuperMethodA(cl, obj, msg));
2220 BOOPSI_DISPATCHER_END
2222 * Class descriptor.
2224 const struct __MUIBuiltinClass _MUI_Application_desc =
2226 MUIC_Application,
2227 MUIC_Notify,
2228 sizeof(struct MUI_ApplicationData),
2229 (void *) Application_Dispatcher