1 /*
2  * Copyright (c) 1998 Sasha Vasko <sasha at aftercode.net>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.   See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  *
18  */
19 #define LOCAL_DEBUG
20 #include "../configure.h"
21 #include "../libAfterStep/asapp.h"
22 #include "../libAfterStep/afterstep.h"
23 #include "../libAfterStep/parser.h"
24 #include "../libAfterStep/background.h"
25 #include "../libAfterStep/screen.h"
26 #include "../libAfterImage/afterimage.h"
27 
28 #include "afterconf.h"
29 
30 /*****************************************************************************
31  *
32  * This routine is responsible for reading and parsing the asetroot config
33  * file
34  *
35  ****************************************************************************/
36 
37 TermDef MyBackgroundTerms[] = {
38 	{TF_NO_MYNAME_PREPENDING | TF_SYNTAX_START, "MyBackground", 12,
39 	 TT_QUOTED_TEXT, BGR_MYBACKGROUND, NULL}
40 	,
41 	{TF_NO_MYNAME_PREPENDING | TF_DONT_SPLIT | TF_DONT_REMOVE_COMMENTS |
42 	 TF_INDEXED, "Use", 3, TT_OPTIONAL_PATHNAME,
43 	 BGR_USE, NULL}
44 	,
45 	{TF_NO_MYNAME_PREPENDING, "Cut", 3, TT_GEOMETRY, BGR_CUT, NULL}
46 	,
47 	{TF_NO_MYNAME_PREPENDING | TF_DONT_REMOVE_COMMENTS, "Tint", 4, TT_COLOR,
48 	 BGR_TINT, NULL}
49 	,
50 	{TF_NO_MYNAME_PREPENDING, "Scale", 5, TT_GEOMETRY, BGR_SCALE, NULL}
51 	,
52 	{TF_NO_MYNAME_PREPENDING, "Align", 5, TT_INTEGER, BGR_ALIGN, NULL}
53 	,
54 	{TF_NO_MYNAME_PREPENDING | TF_INDEXED, "Pad", 3, TT_COLOR, BGR_PAD, NULL}
55 	,
56 	{TF_NO_MYNAME_PREPENDING | TF_SYNTAX_TERMINATOR, "~MyBackground", 13,
57 	 TT_FLAG, BGR_MYBACKGROUND_END, NULL}
58 	,
59 	{0, NULL, 0, 0, 0}
60 };
61 
62 SyntaxDef MyBackgroundSyntax = {
63 	'\n',
64 	'\0',
65 	MyBackgroundTerms,
66 	0,														/* use default hash size */
67 	' ',
68 	"",
69 	"\t",
70 	"Look MyBackground definition",
71 	"MyBackground",
72 	"details how background is to be rendered",
73 	NULL,
74 	0
75 };
76 
77 
78 TermDef ASetRootTerms[] = {
79 	{TF_INDEXED | TF_DONT_SPLIT | TF_NO_MYNAME_PREPENDING, "DeskBack", 8,
80 	 TT_QUOTED_TEXT, BGR_DESK_BACK, NULL}
81 	,
82 /* including MyStyles definitions processing */
83 	INCLUDE_MYSTYLE,
84 	{TF_NO_MYNAME_PREPENDING, "MyBackground", 12, TT_QUOTED_TEXT,
85 	 BGR_MYBACKGROUND, &MyBackgroundSyntax}
86 	,
87 	{0, NULL, 0, 0, 0}
88 };
89 
90 SyntaxDef ASetRootSyntax = {
91 	'\n',
92 	'\0',
93 	ASetRootTerms,
94 	0,														/* use default hash size */
95 	' ',
96 	"",
97 	"\t",
98 	"asetroot configuration",
99 	"Look/DeskBack",
100 	"AfterStep module for rendering root backgrounds",
101 	NULL,
102 	0
103 };
104 
105 /*****************  Create/Destroy MyBackgroundConfig *****************/
CreateMyBackgroundConfig()106 MyBackgroundConfig *CreateMyBackgroundConfig ()
107 {
108 	MyBackgroundConfig *config =
109 			(MyBackgroundConfig *) safemalloc (sizeof (MyBackgroundConfig));
110 
111 	config->name = NULL;
112 	config->flags = 0;
113 	config->data = NULL;
114 	init_asgeometry (&(config->cut));
115 	config->tint = NULL;
116 	init_asgeometry (&(config->scale));
117 	config->pad = NULL;
118 	config->next = NULL;
119 
120 	return config;
121 }
122 
DestroyMyBackgroundConfig(MyBackgroundConfig ** head)123 void DestroyMyBackgroundConfig (MyBackgroundConfig ** head)
124 {
125 	if (head) {
126 		MyBackgroundConfig *cur = *head, *next;
127 
128 		while (cur) {
129 			if (cur->name)
130 				free (cur->name);
131 			if (cur->data)
132 				free (cur->data);
133 			if (cur->tint)
134 				free (cur->tint);
135 			if (cur->pad)
136 				free (cur->pad);
137 			next = cur->next;
138 			free (cur);
139 			cur = next;
140 		}
141 		*head = NULL;
142 	}
143 }
144 
145 /*****************  Create/Destroy DeskBackConfig     *****************/
CreateDeskBackConfig()146 DeskBackConfig *CreateDeskBackConfig ()
147 {
148 	DeskBackConfig *config =
149 			(DeskBackConfig *) safemalloc (sizeof (DeskBackConfig));
150 
151 	config->desk = -1;
152 	config->back_name = NULL;
153 	config->back = NULL;
154 	config->next = NULL;
155 
156 	return config;
157 }
158 
DestroyDeskBackConfig(DeskBackConfig ** head)159 void DestroyDeskBackConfig (DeskBackConfig ** head)
160 {
161 	if (head) {
162 		DeskBackConfig *cur = *head, *next;
163 
164 		while (cur) {
165 			if (cur->back_name)
166 				free (cur->back_name);
167 
168 			next = cur->next;
169 			free (cur);
170 			cur = next;
171 		}
172 		*head = NULL;
173 	}
174 }
175 
176 /*****************  Create/Destroy ASetRootConfig     *****************/
177 
CreateASetRootConfig()178 ASetRootConfig *CreateASetRootConfig ()
179 {
180 	ASetRootConfig *config =
181 			(ASetRootConfig *) safemalloc (sizeof (ASetRootConfig));
182 
183 	/* let's initialize ASetRoot config with some nice values: */
184 	config->my_backs = NULL;
185 	config->my_desks = NULL;
186 	config->style_defs = NULL;
187 
188 	config->more_stuff = NULL;
189 
190 	return config;
191 }
192 
DestroyASetRootConfig(ASetRootConfig * config)193 void DestroyASetRootConfig (ASetRootConfig * config)
194 {
195 	if (config->my_desks)
196 		DestroyDeskBackConfig (&(config->my_desks));
197 	if (config->my_backs)
198 		DestroyMyBackgroundConfig (&(config->my_backs));
199 	DestroyMyStyleDefinitions (&(config->style_defs));
200 	DestroyFreeStorage (&(config->more_stuff));
201 	free (config);
202 }
203 
204 /***********************************************************************/
205 /*      Actual Parsing                                                 */
206 /***********************************************************************/
207 
ParseMyBackgroundOptions(FreeStorageElem * Storage,char * myname)208 MyBackgroundConfig *ParseMyBackgroundOptions (FreeStorageElem * Storage,
209 																							char *myname)
210 {
211 	MyBackgroundConfig *config = CreateMyBackgroundConfig ();
212 	FreeStorageElem *pCurr;
213 	ConfigItem item;
214 
215 	item.memory = NULL;
216 	for (pCurr = Storage; pCurr; pCurr = pCurr->next) {
217 		if (pCurr->term == NULL)
218 			continue;
219 
220 		LOCAL_DEBUG_OUT ("options(%p)->keyword(\"%s\")", pCurr,
221 										 pCurr->term->keyword);
222 
223 		if (pCurr->term->id == BGR_MYBACKGROUND_END) {
224 			config->flags |= BGFLAG_COMPLETE;
225 			continue;
226 		}
227 		if (!ReadConfigItem (&item, pCurr)) {
228 			if (pCurr->term->id == BGR_SCALE)
229 				config->flags |= BGFLAG_SCALE;
230 			continue;
231 		}
232 
233 		switch (pCurr->term->id) {
234 		case BGR_MYBACKGROUND:
235 			config->name = item.data.string;
236 			break;
237 		case BGR_USE:
238 			config->data = item.data.string;
239 			config->flags &= ~(BGFLAG_FILE | BGFLAG_MYSTYLE);
240 			if (item.index == 0)
241 				config->flags |= BGFLAG_FILE;
242 			else if (item.index == 1)
243 				config->flags |= BGFLAG_MYSTYLE;
244 			break;
245 		case BGR_CUT:
246 			config->cut = item.data.geometry;
247 			config->flags |= BGFLAG_CUT;
248 			break;
249 		case BGR_TINT:
250 			config->tint = item.data.string;
251 			config->flags |= BGFLAG_TINT;
252 			break;
253 		case BGR_SCALE:
254 			config->scale = item.data.geometry;
255 			config->flags |= BGFLAG_SCALE;
256 			break;
257 		case BGR_ALIGN:
258 			config->flags &=
259 					~(BGFLAG_ALIGN_CENTER | BGFLAG_ALIGN_RIGHT |
260 						BGFLAG_ALIGN_BOTTOM);
261 			config->flags |= BGFLAG_ALIGN;
262 			if (item.data.integer & 0x1)
263 				config->flags |= BGFLAG_ALIGN_RIGHT;
264 			if (item.data.integer & 0x2)
265 				config->flags |= BGFLAG_ALIGN_BOTTOM;
266 			item.ok_to_free = 1;
267 			break;
268 		case BGR_PAD:
269 			config->pad = item.data.string;
270 			config->flags &= ~(BGFLAG_PAD_VERT | BGFLAG_PAD_HOR);
271 			config->flags |= BGFLAG_PAD;
272 			if (item.index & 0x1)
273 				config->flags |= BGFLAG_PAD_HOR;
274 			if (item.index & 0x2)
275 				config->flags |= BGFLAG_PAD_VERT;
276 			break;
277 		default:
278 			item.ok_to_free = 1;
279 		}
280 	}
281 	ReadConfigItem (&item, NULL);
282 
283 	set_flags (config->flags, BGFLAG_BAD);
284 	if (config->name == NULL)
285 		show_error ("Background Definition error: name is empty !");
286 	else if (!(config->flags & BGFLAG_COMPLETE))
287 		show_error
288 				("Background Definition error: [%s] not terminated properly !",
289 				 config->name);
290 	else
291 		clear_flags (config->flags, BGFLAG_BAD);
292 
293 	if (config->flags & BGFLAG_BAD)
294 		DestroyMyBackgroundConfig (&config);
295 	return config;
296 }
297 
ParseDeskBackOptions(ConfigItem * item,char * myname)298 DeskBackConfig *ParseDeskBackOptions (ConfigItem * item, char *myname)
299 {
300 	DeskBackConfig *config = CreateDeskBackConfig ();
301 	Bool failed = True;
302 
303 	config->desk = item->index;
304 	config->back_name = item->data.string;
305 	item->ok_to_free = 0;
306 
307 	if (config->desk < 0)
308 		show_error ("Desk Background Definition error: bad desk number !");
309 	else if (config->back_name == NULL)
310 		show_error
311 				("Desk Background Definition error:  #%d has empty background name!",
312 				 config->desk);
313 	else
314 		failed = False;
315 
316 	if (failed)
317 		DestroyDeskBackConfig (&config);
318 	return config;
319 }
320 
FixDeskBacks(ASetRootConfig * config)321 void FixDeskBacks (ASetRootConfig * config)
322 {
323 	DeskBackConfig *curr_desk;
324 
325 	if (!config)
326 		return;
327 	for (curr_desk = config->my_desks; curr_desk;
328 			 curr_desk = curr_desk->next) {
329 		MyBackgroundConfig *curr_back;
330 
331 		for (curr_back = config->my_backs; curr_back;
332 				 curr_back = curr_back->next)
333 			if (mystrcasecmp (curr_desk->back_name, curr_back->name) == 0) {
334 				curr_desk->back = curr_back;
335 				break;
336 			}
337 		if (curr_desk->back == NULL) {	/* need to create new back as plain image file,
338 																		   using name from desk definition */
339 			curr_desk->back = CreateMyBackgroundConfig ();
340 			curr_desk->back->next = config->my_backs;
341 			config->my_backs = curr_desk->back;
342 			curr_desk->back->name =
343 					(char *)safemalloc (strlen (curr_desk->back_name) + 1);
344 			strcpy (curr_desk->back->name, curr_desk->back_name);
345 			curr_desk->back->data =
346 					(char *)safemalloc (strlen (curr_desk->back_name) + 1);
347 			strcpy (curr_desk->back->data, curr_desk->back_name);
348 			curr_desk->back->flags |= BGFLAG_FILE | BGFLAG_COMPLETE;
349 		}
350 	}
351 }
352 
ParseASetRootOptions(const char * filename,char * myname)353 ASetRootConfig *ParseASetRootOptions (const char *filename, char *myname)
354 {
355 	ConfigData cd;
356 	ConfigDef *ConfigReader;
357 	ASetRootConfig *config = CreateASetRootConfig ();
358 	MyBackgroundConfig **backs_tail = &(config->my_backs);
359 	DeskBackConfig **desks_tail = &(config->my_desks);
360 	FreeStorageElem *Storage = NULL, *pCurr;
361 	ConfigItem item;
362 
363 	cd.filename = filename;
364 	ConfigReader =
365 			InitConfigReader (myname, &ASetRootSyntax, CDT_Filename, cd, NULL);
366 
367 	if (!ConfigReader)
368 		return config;
369 
370 	item.memory = NULL;
371 	PrintConfigReader (ConfigReader);
372 	ParseConfig (ConfigReader, &Storage);
373 
374 	/* getting rid of all the crap first */
375 	StorageCleanUp (&Storage, &(config->more_stuff), CF_DISABLED_OPTION);
376 
377 	config->style_defs = free_storage2MyStyleDefinitionsList (Storage);
378 
379 	for (pCurr = Storage; pCurr; pCurr = pCurr->next) {
380 		if (pCurr->term == NULL)
381 			continue;
382 
383 		if (pCurr->term->id == BGR_MYBACKGROUND) {
384 			if ((*backs_tail =
385 					 ParseMyBackgroundOptions (pCurr->sub, myname)) != NULL)
386 				backs_tail = &((*backs_tail)->next);
387 			continue;
388 		}
389 
390 		if (!ReadConfigItem (&item, pCurr))
391 			continue;
392 		switch (pCurr->term->id) {
393 		case BGR_DESK_BACK:
394 			if ((*desks_tail = ParseDeskBackOptions (&item, myname)) != NULL)
395 				desks_tail = &((*desks_tail)->next);
396 			break;
397 		default:
398 			item.ok_to_free = 1;
399 		}
400 	}
401 	ReadConfigItem (&item, NULL);
402 	FixDeskBacks (config);
403 
404 	DestroyConfig (ConfigReader);
405 	DestroyFreeStorage (&Storage);
406 	return config;
407 }
408 
myback_parse(char * tline,FILE * fd,char ** myname,int * mylook)409 void myback_parse (char *tline, FILE * fd, char **myname, int *mylook)
410 {
411 	FilePtrAndData fpd;
412 	ConfigDef *ConfigReader;
413 	MyBackgroundConfig *back_config = NULL;
414 	FreeStorageElem *Storage = NULL, *more_stuff = NULL;
415 	MyLook *look = (MyLook *) mylook;
416 	MyBackground *myback = NULL;
417 	ConfigData cd;
418 
419 	if (look == NULL)
420 		look = get_screen_look (NULL);
421 
422 	fpd.fp = fd;
423 	fpd.data = safemalloc (12 + 1 + strlen (tline) + 1 + 1);
424 	sprintf (fpd.data, "MyBackground %s\n", tline);
425 	LOCAL_DEBUG_OUT ("fd(%p)->tline(\"%s\")->fpd.data(\"%s\")", fd, tline,
426 									 fpd.data);
427 	cd.fileptranddata = &fpd;
428 	ConfigReader =
429 			InitConfigReader ((char *)myname, &MyBackgroundSyntax,
430 												CDT_FilePtrAndData, cd, NULL);
431 	free (fpd.data);
432 
433 	if (!ConfigReader)
434 		return;
435 
436 	PrintConfigReader (ConfigReader);
437 	ParseConfig (ConfigReader, &Storage);
438 
439 	/* getting rid of all the crap first */
440 	StorageCleanUp (&Storage, &more_stuff, CF_DISABLED_OPTION);
441 	DestroyFreeStorage (&more_stuff);
442 
443 	back_config = ParseMyBackgroundOptions (Storage, (char *)myname);
444 
445 	DestroyConfig (ConfigReader);
446 	DestroyFreeStorage (&Storage);
447 
448 	if (back_config == NULL)
449 		return;
450 
451 	/* now we have to turn MyBackgroundConfig into MyBackground structure : */
452 	myback = create_myback (back_config->name);
453 
454 	if (get_flags (back_config->flags, BGFLAG_FILE))
455 		myback->type = MB_BackImage;
456 	else if (get_flags (back_config->flags, BGFLAG_MYSTYLE))
457 		myback->type = MB_BackMyStyle;
458 	else
459 		myback->type = MB_BackCmd;
460 
461 	myback->data = back_config->data;
462 	back_config->data = NULL;
463 	if (get_flags (back_config->flags, BGFLAG_CUT))
464 		myback->cut = back_config->cut;
465 	if (get_flags (back_config->flags, BGFLAG_SCALE)) {
466 		myback->scale = back_config->scale;
467 		if (!get_flags (back_config->scale.flags, WidthValue))
468 			myback->scale.width = get_screen_width (NULL);
469 		if (!get_flags (back_config->scale.flags, HeightValue))
470 			myback->scale.height = get_screen_height (NULL);
471 		set_flags (myback->scale.flags, WidthValue | HeightValue);
472 	}
473 
474 	myback->tint = TINT_LEAVE_SAME;
475 	if (get_flags (back_config->flags, BGFLAG_TINT) && back_config->tint)
476 		parse_argb_color (back_config->tint, &(myback->tint));
477 	myback->pad_color = ARGB32_Black;
478 	if (get_flags (back_config->flags, BGFLAG_PAD) && back_config->pad)
479 		parse_argb_color (back_config->pad, &(myback->pad_color));
480 
481 	myback->align_flags = NO_ALIGN;
482 	if (get_flags (back_config->flags, BGFLAG_PAD_HOR)) {
483 		if (get_flags (back_config->flags, BGFLAG_ALIGN_RIGHT))
484 			myback->align_flags = ALIGN_RIGHT;
485 		else if (get_flags (back_config->flags, BGFLAG_ALIGN_CENTER))
486 			myback->align_flags = ALIGN_HCENTER;
487 		else
488 			myback->align_flags = ALIGN_LEFT;
489 	}
490 	if (get_flags (back_config->flags, BGFLAG_PAD_VERT)) {
491 		if (get_flags (back_config->flags, BGFLAG_ALIGN_BOTTOM))
492 			myback->align_flags |= ALIGN_BOTTOM;
493 		else if (get_flags (back_config->flags, BGFLAG_ALIGN_CENTER))
494 			myback->align_flags |= ALIGN_VCENTER;
495 		else
496 			myback->align_flags = ALIGN_TOP;
497 	}
498 	LOCAL_DEBUG_OUT ("myback added: name(\"%s\")->type(%d)->data(\"%s\")",
499 									 myback->name, myback->type, myback->data);
500 	add_myback (look, myback);
501 
502 	/* final cleanup : */
503 	DestroyMyBackgroundConfig (&back_config);
504 }
505