2 Copyright 1995-2014, The AROS Development Team.
6 /******************************************************************************
22 Allows user definable skins for the intuition windows, menus and gadgets.
26 Must be launched before Wanderer - usually in the S:startup-sequence
36 ******************************************************************************/
39 #include <aros/debug.h>
41 #include <clib/alib_protos.h>
43 #include <proto/exec.h>
44 #include <proto/dos.h>
45 #include <proto/intuition.h>
47 #include <aros/detach.h>
49 #include "windowdecorclass.h"
50 #include "screendecorclass.h"
51 #include "menudecorclass.h"
55 const TEXT version_string
[] = "$VER: Decoration 1.8 (8.12.2014)";
57 STRPTR __detached_name
= "Decorator";
59 #define MAGIC_PRIVATE_SKIN 0x0001
60 #define MAGIC_PRIVATE_TITLECHILD 0x0F0F
62 struct DecorationDecorator
64 struct NewDecorator base
; /* MUST BE FIRST */
65 struct DecorConfig
* dc
;
66 struct DecorImages
* di
;
69 struct DecorationDecorator
*basedecor
= NULL
;
72 struct MagicMessage msg
;
78 void DeleteDecorator(struct NewDecorator
*nd
)
80 if (nd
== NULL
) return;
81 if (((struct DecorationDecorator
*)nd
)->dc
!= NULL
) FreeConfig(((struct DecorationDecorator
*)nd
)->dc
);
82 if (((struct DecorationDecorator
*)nd
)->di
!= NULL
) FreeImages(((struct DecorationDecorator
*)nd
)->di
);
86 struct DecorationDecorator
*LoadDecoration(STRPTR path
)
88 struct DecorationDecorator
* dnd
= NULL
;
89 struct TagItem
*screenTags
, *menuTags
, *windowTags
;
91 D(bug("LoadDecoration: Entering\n"));
95 if (path
!= NULL
) newpath
= path
; else newpath
= "Theme:";
97 dnd
= AllocVec(sizeof(struct DecorationDecorator
), MEMF_CLEAR
| MEMF_ANY
);
99 D(bug("LoadDecoration: decorator @ 0x%p\n", dnd
));
103 dnd
->dc
= LoadConfig(newpath
);
104 D(bug("LoadDecoration: config @ 0x%p\n", dnd
->dc
));
107 DeleteDecorator(&dnd
->base
);
111 dnd
->di
= LoadImages(dnd
->dc
);
112 D(bug("LoadDecoration: images @ 0x%p\n", dnd
->di
));
115 DeleteDecorator(&dnd
->base
);
119 dnd
->base
.nd_ScreenTags
= AllocVec(sizeof(struct TagItem
) * 4, MEMF_CLEAR
| MEMF_ANY
);
120 dnd
->base
.nd_MenuTags
= AllocVec(sizeof(struct TagItem
) * 4, MEMF_CLEAR
| MEMF_ANY
);
121 dnd
->base
.nd_WindowTags
= AllocVec(sizeof(struct TagItem
) * 4, MEMF_CLEAR
| MEMF_ANY
);
125 D(bug("LoadDecoration: copying base classes\n"));
126 dnd
->base
.nd_ScreenClass
= basedecor
->base
.nd_ScreenClass
;
127 dnd
->base
.nd_MenuClass
= basedecor
->base
.nd_MenuClass
;
128 dnd
->base
.nd_WindowClass
= basedecor
->base
.nd_WindowClass
;
131 screenTags
= dnd
->base
.nd_ScreenTags
;
132 menuTags
= dnd
->base
.nd_MenuTags
;
133 windowTags
= dnd
->base
.nd_WindowTags
;
135 screenTags
[0].ti_Tag
= SDA_UserBuffer
;
136 menuTags
[0].ti_Tag
= MDA_UserBuffer
;
137 windowTags
[0].ti_Tag
= WDA_UserBuffer
;
138 screenTags
[0].ti_Data
= sizeof(struct ScreenData
);
139 menuTags
[0].ti_Data
= sizeof(struct MenuData
);
140 windowTags
[0].ti_Data
= sizeof(struct WindowData
);
142 screenTags
[1].ti_Tag
= SDA_DecorImages
;
143 menuTags
[1].ti_Tag
= MDA_DecorImages
;
144 windowTags
[1].ti_Tag
= WDA_DecorImages
;
145 screenTags
[1].ti_Data
= (IPTR
)dnd
->di
;
146 menuTags
[1].ti_Data
= (IPTR
)dnd
->di
;
147 windowTags
[1].ti_Data
= (IPTR
)dnd
->di
;
149 screenTags
[2].ti_Tag
= SDA_DecorConfig
;
150 menuTags
[2].ti_Tag
= MDA_DecorConfig
;
151 windowTags
[2].ti_Tag
= WDA_DecorConfig
;
152 screenTags
[2].ti_Data
= (IPTR
)dnd
->dc
;
153 menuTags
[2].ti_Data
= (IPTR
)dnd
->dc
;
154 windowTags
[2].ti_Data
= (IPTR
)dnd
->dc
;
156 screenTags
[3].ti_Tag
= TAG_DONE
;
157 menuTags
[3].ti_Tag
= TAG_DONE
;
158 windowTags
[3].ti_Tag
= TAG_DONE
;
164 #define ARGUMENT_TEMPLATE "PATH,SCREENID=ID/K"
172 struct NewDecorator
*decor
;
173 struct MsgPort
*port
;
175 IPTR rd_Args
[] = {0, 0, };
177 struct RDArgs
*args
, *newargs
;
179 /* the 1M $$ Question why "Decoration ?" does not work in the shell? */
181 newargs
= (struct RDArgs
*) AllocDosObject(DOS_RDARGS
, NULL
);
183 if (newargs
== NULL
) return 0;
185 newargs
->RDA_ExtHelp
= usage
;
186 newargs
->RDA_Flags
= 0;
188 args
= ReadArgs(ARGUMENT_TEMPLATE
, rd_Args
, newargs
);
191 FreeDosObject (DOS_RDARGS
, (APTR
) newargs
);
195 if ((port
= CreateMsgPort()) == NULL
)
199 if (FindPort(__detached_name
)) {
200 struct SkinMessage msg
;
201 msg
.msg
.mn_ReplyPort
= port
;
202 msg
.msg
.mn_Magic
= MAGIC_PRIVATE_SKIN
;
204 msg
.path
= (STRPTR
) rd_Args
[0];
205 msg
.id
= (STRPTR
) rd_Args
[1];
206 PutMsg(FindPort(__detached_name
), (struct Message
*) &msg
);
216 D(bug("Decoration: making classes...\n"));
218 if ((basedecor
= LoadDecoration((STRPTR
) rd_Args
[0])) != NULL
)
220 decor
= &basedecor
->base
;
221 if ((basedecor
->base
.nd_ScreenClass
= MakeScreenDecorClass()) != NULL
)
223 if ((basedecor
->base
.nd_MenuClass
= MakeMenuDecorClass()) != NULL
)
225 if ((basedecor
->base
.nd_WindowClass
= MakeWindowDecorClass()) != NULL
)
227 D(bug("Decoration: Classes made (screen @ 0x%p, menu @ 0x%p, win @ 0x%p)\n", basedecor
->base
.nd_ScreenClass
, basedecor
->base
.nd_MenuClass
, basedecor
->base
.nd_WindowClass
));
229 ULONG skinSignal
= 1 << port
->mp_SigBit
;
230 port
->mp_Node
.ln_Name
=__detached_name
;
233 D(bug("Decoration: Port created and added\n"));
235 D(bug("Decoration: Got decorator\n"));
239 decor
->nd_Pattern
= (STRPTR
) rd_Args
[1];
240 decor
->nd_Port
= port
;
241 ChangeDecoration(DECORATION_SET
, decor
);
244 D(bug("Before Detach()\n"));
248 D(bug("After Detach()\n"));
254 ULONG sigs
= Wait(SIGBREAKF_CTRL_C
| skinSignal
);
255 if ((sigs
& SIGBREAKF_CTRL_C
) != 0)
257 // running = FALSE; /* at the moment no exit */
259 else if ((sigs
& skinSignal
) != 0)
261 struct DecoratorMessage
*dmsg
;
262 struct SkinMessage
* msg
= (struct SkinMessage
*) GetMsg(port
);
265 switch(msg
->msg
.mn_Magic
)
267 case MAGIC_PRIVATE_TITLECHILD
:
268 dmsg
= (struct DecoratorMessage
*) msg
;
271 SetAttrs((Object
*)*((Object
**)((IPTR
)dmsg
->dm_Class
+ (IPTR
)decor
->nd_ScreenObjOffset
)), SDA_TitleChild
, dmsg
->dm_Object
, TAG_DONE
);
274 case MAGIC_PRIVATE_SKIN
:
275 decor
= (struct NewDecorator
*)LoadDecoration(msg
->path
);
278 decor
->nd_Pattern
= msg
->id
;
279 decor
->nd_Port
= port
;
280 ChangeDecoration(DECORATION_SET
, decor
);
283 case MAGIC_DECORATOR
:
284 dmsg
= (struct DecoratorMessage
*) msg
;
285 DeleteDecorator((struct NewDecorator
*) dmsg
->dm_Object
);
288 ReplyMsg((struct Message
*) msg
);
289 msg
= (struct SkinMessage
*) GetMsg(port
);
293 FreeClass(decor
->nd_WindowClass
);
295 FreeClass(decor
->nd_MenuClass
);
297 FreeClass(decor
->nd_ScreenClass
);
300 FreeDosObject (DOS_RDARGS
, (APTR
) newargs
);