Fixed out-by-one error in previous commit.
[AROS.git] / workbench / c / Decoration / decoration.c
blob707d8d83adb87b1a0d88d6bd8afbf7095118c209
1 /*
2 Copyright 1995-2012, The AROS Development Team.
3 $Id$
4 */
6 /******************************************************************************
8 NAME
10 Decoration
12 SYNOPSIS
14 (N/A)
16 LOCATION
20 FUNCTION
22 Allows user definable skins for the intuition windows, menus and gadgets.
24 NOTES
26 Must be launched before Wanderer - usually in the S:startup-sequence
28 BUGS
30 SEE ALSO
32 IPREFS
34 INTERNALS
36 ******************************************************************************/
38 #define DEBUG 0
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"
52 #include "newimage.h"
53 #include "config.h"
55 const TEXT version_string[] = "$VER: Decoration 1.5 (22.4.2012)";
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;
71 struct SkinMessage {
72 struct MagicMessage msg;
73 UWORD class;
74 STRPTR path;
75 STRPTR id;
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);
83 FreeVec(nd);
86 struct DecorationDecorator *LoadDecoration(STRPTR path)
88 struct DecorationDecorator * dnd = NULL;
89 struct TagItem *screenTags, *menuTags, *windowTags;
91 D(bug("LoadDecoration: Entering\n"));
93 STRPTR newpath;
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));
101 if (dnd)
103 dnd->dc = LoadConfig(newpath);
104 D(bug("LoadDecoration: config @ 0x%p\n", dnd->dc));
105 if (!dnd->dc)
107 DeleteDecorator(&dnd->base);
108 return NULL;
111 dnd->di = LoadImages(dnd->dc);
112 D(bug("LoadDecoration: images @ 0x%p\n", dnd->di));
113 if (!dnd->di)
115 DeleteDecorator(&dnd->base);
116 return NULL;
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);
123 if (basedecor)
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;
161 return dnd;
164 #define ARGUMENT_TEMPLATE "PATH,SCREENID=ID/K"
166 char usage[] =
167 "Decoration:\n"
168 "Arguments:\n";
170 int main(void)
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);
190 if (args == NULL) {
191 FreeDosObject (DOS_RDARGS, (APTR) newargs);
192 return 0;
195 if ((port = CreateMsgPort()) == NULL)
196 return 0;
198 Forbid();
199 if (FindPort(__detached_name)) {
200 struct SkinMessage msg;
201 msg.msg.mn_ReplyPort = port;
202 msg.msg.mn_Magic = MAGIC_PRIVATE_SKIN;
203 msg.class = 0;
204 msg.path = (STRPTR) rd_Args[0];
205 msg.id = (STRPTR) rd_Args[1];
206 PutMsg(FindPort(__detached_name), (struct Message *) &msg);
207 WaitPort(port);
208 GetMsg(port);
209 Permit();
210 DeleteMsgPort(port);
211 FreeArgs(args);
212 return 0;
214 Permit();
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;
231 AddPort(port);
233 D(bug("Decoration: Port created and added\n"));
235 D(bug("Decoration: Got decorator\n"));
237 if (decor != NULL)
239 decor->nd_Pattern = (STRPTR) rd_Args[1];
240 decor->nd_Port = port;
241 ChangeDecoration(DECORATION_SET, decor);
244 D(bug("Before Detach()\n"));
246 Detach();
248 D(bug("After Detach()\n"));
250 BOOL running = TRUE;
252 while (running)
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);
263 while (msg)
265 switch(msg->msg.mn_Magic)
267 case MAGIC_PRIVATE_TITLECHILD:
268 dmsg = (struct DecoratorMessage *) msg;
269 if (decor)
271 SetAttrs((Object *)*((Object **)((IPTR)dmsg->dm_Class + (IPTR)decor->nd_ScreenObjOffset)), SDA_TitleChild, dmsg->dm_Object, TAG_DONE);
273 break;
274 case MAGIC_PRIVATE_SKIN:
275 decor = (struct NewDecorator *)LoadDecoration(msg->path);
276 if (decor != NULL)
278 decor->nd_Pattern = msg->id;
279 decor->nd_Port = port;
280 ChangeDecoration(DECORATION_SET, decor);
282 break;
283 case MAGIC_DECORATOR:
284 dmsg = (struct DecoratorMessage *) msg;
285 DeleteDecorator((struct NewDecorator *) dmsg->dm_Object);
286 break;
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);
301 FreeArgs(args);
302 return 0;