1 /*
2  * Compiz configuration system library
3  *
4  * Copyright (C) 2007  Dennis Kasprzyk <onestone@opencompositing.org>
5  * Copyright (C) 2007  Danny Baumann <maniac@opencompositing.org>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11 
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16 
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21 
22 #define _GNU_SOURCE
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdlib.h>
26 
27 #include <ccs.h>
28 
29 #include "ccs-private.h"
30 
31 typedef void (*freeFunc) (void *ptr);
32 
33 #define CCSLIST(type,dtype,ocomp,compfunc) \
34     \
35     CCS##type##List ccs##type##ListAppend (CCS##type##List list, dtype *data) \
36     { \
37 	CCS##type##List l = list; \
38 	CCS##type##List ne = malloc(sizeof(struct _CCS##type##List)); \
39 	if (!ne) \
40 	    return list; \
41 	ne->data = data; \
42 	ne->next = NULL; \
43 	if (!list) \
44 	    return ne; \
45 	while (l->next) l = l->next; \
46 	l->next = ne; \
47 	return list; \
48     } \
49     \
50     CCS##type##List ccs##type##ListPrepend (CCS##type##List list, dtype *data) \
51     { \
52 	CCS##type##List ne = malloc(sizeof(struct _CCS##type##List)); \
53 	if (!ne) \
54 	    return list; \
55 	ne->data = data; \
56 	ne->next = list; \
57 	return ne; \
58     } \
59     \
60     CCS##type##List ccs##type##ListInsert (CCS##type##List list, dtype *data, int position) \
61     { \
62 	CCS##type##List l = list; \
63 	CCS##type##List ne = malloc(sizeof(struct _CCS##type##List)); \
64 	if (!ne) \
65 	    return list; \
66 	ne->data = data; \
67 	ne->next = list; \
68 	if (!list || !position) \
69 	    return ne; \
70 	position--; \
71 	while (l->next && position) \
72 	{ \
73 	    l = l->next; \
74 	    position--; \
75 	} \
76 	ne->next = l->next; \
77 	l->next = ne; \
78 	return list; \
79     } \
80     \
81     CCS##type##List ccs##type##ListInsertBefore (CCS##type##List list, CCS##type##List sibling, dtype *data) \
82     { \
83 	CCS##type##List l = list; \
84 	CCS##type##List ne = malloc(sizeof(struct _CCS##type##List)); \
85 	if (!ne) \
86 	    return list; \
87 	while (l && (l != sibling)) l = l->next; \
88 	ne->data = data; \
89 	ne->next = l; \
90 	return ne; \
91     } \
92     \
93     unsigned int ccs##type##ListLength (CCS##type##List list) \
94     { \
95 	unsigned int count = 0; \
96 	CCS##type##List l = list; \
97 	while (l) \
98 	{ \
99 	    l = l->next; \
100 	    count++; \
101 	} \
102 	return count; \
103     } \
104     \
105     CCS##type##List ccs##type##ListFind (CCS##type##List list, dtype *data) \
106     { \
107 	CCS##type##List l = list; \
108 	while (l) \
109 	{ \
110 	    if (!data && !l->data) break; \
111 	    if ((ocomp)?(compfunc):(memcmp(l->data, data, sizeof(dtype)) == 0)) break; \
112 	    l = l->next; \
113 	} \
114 	return l; \
115     } \
116     \
117     CCS##type##List ccs##type##ListGetItem (CCS##type##List list, unsigned int index) \
118     { \
119 	CCS##type##List l = list; \
120 	while (l && index) \
121 	{ \
122 	    l = l->next; \
123 	    index--; \
124 	} \
125 	return l; \
126     } \
127     \
128     CCS##type##List ccs##type##ListRemove (CCS##type##List list, dtype *data, Bool freeObj) \
129     { \
130 	CCS##type##List l = list; \
131 	CCS##type##List prev = NULL; \
132 	Bool           found = FALSE; \
133 	if (!data) \
134 	    return list; \
135 	while (l) \
136 	{ \
137 	    if (!l->data) continue; \
138 	    if ((ocomp)?(compfunc):(memcmp(l->data, data, sizeof(dtype)) == 0)) \
139 	    { \
140 		found = TRUE; \
141 		break; \
142 	    } \
143 	    prev = l; \
144 	    l = l->next; \
145 	} \
146 	if (!found) \
147 	    return list; \
148 	if (l) \
149 	{ \
150 	    if (prev) prev->next = l->next; \
151 	    else list = l->next; \
152 	    if (freeObj) \
153 		ccsFree##type (l->data); \
154 	    free (l); \
155 	} \
156 	return list; \
157     } \
158     \
159     CCS##type##List ccs##type##ListFree (CCS##type##List list, Bool freeObj) \
160     { \
161 	CCS##type##List l = list; \
162 	CCS##type##List le = NULL; \
163 	while (l) \
164 	{ \
165 	    le = l; \
166 	    l = l->next; \
167 	    if (freeObj) \
168 		ccsFree##type (le->data); \
169 	    free(le); \
170 	} \
171 	return NULL; \
172     }
173 
174 CCSLIST (Plugin, CCSPlugin, FALSE, 0)
175 CCSLIST (Setting, CCSSetting, FALSE, 0)
176 CCSLIST (String, char, TRUE, strcmp (data, l->data) == 0)
177 CCSLIST (Group, CCSGroup, FALSE, 0)
178 CCSLIST (SubGroup, CCSSubGroup, FALSE, 0)
179 CCSLIST (SettingValue, CCSSettingValue, FALSE, 0)
180 CCSLIST (PluginConflict, CCSPluginConflict, FALSE, 0)
181 CCSLIST (BackendInfo, CCSBackendInfo, FALSE, 0)
182 CCSLIST (IntDesc, CCSIntDesc, FALSE, 0)
183 CCSLIST (StrRestriction, CCSStrRestriction, FALSE, 0)
184 CCSLIST (StrExtension, CCSStrExtension, FALSE, 0)
185 
ccsGetValueListFromStringList(CCSStringList list,CCSSetting * parent)186 CCSSettingValueList ccsGetValueListFromStringList (CCSStringList list,
187 						   CCSSetting *parent)
188 {
189     CCSSettingValueList rv = NULL;
190 
191     while (list)
192     {
193 	CCSSettingValue *value = calloc (1, sizeof (CCSSettingValue));
194 	if (!value)
195 	    return rv;
196 
197 	value->isListChild = TRUE;
198 	value->parent = parent;
199 	value->value.asString = strdup (list->data);
200 	rv = ccsSettingValueListAppend (rv, value);
201 	list = list->next;
202     }
203 
204     return rv;
205 }
206 
ccsGetStringListFromValueList(CCSSettingValueList list)207 CCSStringList ccsGetStringListFromValueList (CCSSettingValueList list)
208 {
209     CCSStringList rv = NULL;
210 
211     while (list)
212     {
213 	rv = ccsStringListAppend (rv, strdup (list->data->value.asString) );
214 	list = list->next;
215     }
216 
217     return rv;
218 }
219 
ccsGetStringArrayFromList(CCSStringList list,int * num)220 char ** ccsGetStringArrayFromList (CCSStringList list, int *num)
221 {
222     char ** rv = NULL;
223     int length = ccsStringListLength (list);
224     int i;
225 
226     if (length)
227     {
228 	rv = calloc (length, sizeof (char *));
229 	if (!rv)
230 	    return NULL;
231     }
232 
233     for (i = 0; i < length; i++, list = list->next)
234 	rv[i] = strdup (list->data);
235 
236     *num = length;
237 
238     return rv;
239 }
240 
ccsGetListFromStringArray(char ** array,int num)241 CCSStringList ccsGetListFromStringArray (char ** array, int num)
242 {
243     CCSStringList rv = NULL;
244     int i;
245 
246     for (i = 0; i < num; i++)
247 	rv = ccsStringListAppend (rv, strdup (array[i]) );
248 
249     return rv;
250 }
251 
ccsGetStringArrayFromValueList(CCSSettingValueList list,int * num)252 char ** ccsGetStringArrayFromValueList (CCSSettingValueList list, int *num)
253 {
254     char ** rv = NULL;
255     int length = ccsSettingValueListLength (list);
256     int i;
257 
258     if (length)
259     {
260 	rv = calloc (length, sizeof (char *));
261 	if (!rv)
262 	    return NULL;
263     }
264 
265     for (i = 0; i < length; i++, list = list->next)
266 	rv[i] = strdup (list->data->value.asString);
267 
268     *num = length;
269 
270     return rv;
271 }
272 
ccsGetMatchArrayFromValueList(CCSSettingValueList list,int * num)273 char ** ccsGetMatchArrayFromValueList (CCSSettingValueList list, int *num)
274 {
275     char ** rv = NULL;
276     int length = ccsSettingValueListLength (list);
277     int i;
278 
279     if (length)
280     {
281 	rv = calloc (length, sizeof (char *));
282 	if (!rv)
283 	    return NULL;
284     }
285 
286     for (i = 0; i < length; i++, list = list->next)
287 	rv[i] = strdup (list->data->value.asMatch);
288 
289     *num = length;
290 
291     return rv;
292 }
293 
ccsGetIntArrayFromValueList(CCSSettingValueList list,int * num)294 int * ccsGetIntArrayFromValueList (CCSSettingValueList list, int *num)
295 {
296     int * rv = NULL;
297     int length = ccsSettingValueListLength (list);
298     int i;
299 
300     if (length)
301     {
302 	rv = calloc (length, sizeof (int));
303 	if (!rv)
304 	    return NULL;
305     }
306 
307     for (i = 0; i < length; i++, list = list->next)
308 	rv[i] = list->data->value.asInt;
309 
310     *num = length;
311 
312     return rv;
313 }
314 
ccsGetFloatArrayFromValueList(CCSSettingValueList list,int * num)315 float * ccsGetFloatArrayFromValueList (CCSSettingValueList list, int *num)
316 {
317     float * rv = NULL;
318     int length = ccsSettingValueListLength (list);
319     int i;
320 
321     if (length)
322     {
323 	rv = calloc (length, sizeof (float));
324 	if (!rv)
325 	    return NULL;
326     }
327 
328     for (i = 0; i < length; i++, list = list->next)
329 	rv[i] = list->data->value.asFloat;
330 
331     *num = length;
332 
333     return rv;
334 }
335 
ccsGetBoolArrayFromValueList(CCSSettingValueList list,int * num)336 Bool * ccsGetBoolArrayFromValueList (CCSSettingValueList list, int *num)
337 {
338     Bool * rv = NULL;
339     int length = ccsSettingValueListLength (list);
340     int i;
341 
342     if (length)
343     {
344 	rv = calloc (length, sizeof (Bool));
345 	if (!rv)
346 	    return NULL;
347     }
348 
349     for (i = 0; i < length; i++, list = list->next)
350 	rv[i] = list->data->value.asBool;
351 
352     *num = length;
353 
354     return rv;
355 }
356 
ccsGetColorArrayFromValueList(CCSSettingValueList list,int * num)357 CCSSettingColorValue * ccsGetColorArrayFromValueList (CCSSettingValueList list,
358 						      int *num)
359 {
360     CCSSettingColorValue * rv = NULL;
361     int length = ccsSettingValueListLength (list);
362     int i;
363 
364     if (length)
365     {
366 	rv = calloc (length, sizeof (CCSSettingColorValue));
367 	if (!rv)
368 	    return NULL;
369     }
370 
371     for (i = 0; i < length; i++, list = list->next)
372 	memcpy (&rv[i], &list->data->value.asColor,
373 		sizeof (CCSSettingColorValue));
374 
375     *num = length;
376 
377     return rv;
378 }
379 
ccsGetValueListFromStringArray(char ** array,int num,CCSSetting * parent)380 CCSSettingValueList ccsGetValueListFromStringArray (char ** array, int num,
381 						    CCSSetting *parent)
382 {
383     CCSSettingValueList l = NULL;
384     int i;
385 
386     for (i = 0; i < num; i++)
387     {
388 	CCSSettingValue *value = calloc (1, sizeof (CCSSettingValue));
389 	if (!value)
390 	    return l;
391 
392 	value->isListChild = TRUE;
393 	value->parent = parent;
394 	value->value.asString = strdup (array[i]);
395 	l = ccsSettingValueListAppend (l, value);
396     }
397 
398     return l;
399 }
400 
ccsGetValueListFromMatchArray(char ** array,int num,CCSSetting * parent)401 CCSSettingValueList ccsGetValueListFromMatchArray (char ** array, int num,
402 						   CCSSetting *parent)
403 {
404     CCSSettingValueList l = NULL;
405     int i;
406 
407     for (i = 0; i < num; i++)
408     {
409 	CCSSettingValue *value = calloc (1, sizeof (CCSSettingValue));
410 	if (!value)
411 	    return l;
412 
413 	value->isListChild = TRUE;
414 	value->parent = parent;
415 	value->value.asMatch = strdup (array[i]);
416 	l = ccsSettingValueListAppend (l, value);
417     }
418 
419     return l;
420 }
421 
ccsGetValueListFromIntArray(int * array,int num,CCSSetting * parent)422 CCSSettingValueList ccsGetValueListFromIntArray (int * array, int num,
423 						 CCSSetting *parent)
424 {
425     CCSSettingValueList l = NULL;
426     int i;
427 
428     for (i = 0; i < num; i++)
429     {
430 	CCSSettingValue *value = calloc (1, sizeof (CCSSettingValue));
431 	if (!value)
432 	    return l;
433 
434 	value->isListChild = TRUE;
435 	value->parent = parent;
436 	value->value.asInt = array[i];
437 	l = ccsSettingValueListAppend (l, value);
438     }
439 
440     return l;
441 }
442 
ccsGetValueListFromFloatArray(float * array,int num,CCSSetting * parent)443 CCSSettingValueList ccsGetValueListFromFloatArray (float * array, int num,
444 						   CCSSetting *parent)
445 {
446     CCSSettingValueList l = NULL;
447     int i;
448 
449     for (i = 0; i < num; i++)
450     {
451 	CCSSettingValue *value = calloc (1, sizeof (CCSSettingValue));
452 	if (!value)
453 	    return l;
454 
455 	value->isListChild = TRUE;
456 	value->parent = parent;
457 	value->value.asFloat = array[i];
458 	l = ccsSettingValueListAppend (l, value);
459     }
460 
461     return l;
462 }
463 
ccsGetValueListFromBoolArray(Bool * array,int num,CCSSetting * parent)464 CCSSettingValueList ccsGetValueListFromBoolArray (Bool * array, int num,
465 						  CCSSetting *parent)
466 {
467     CCSSettingValueList l = NULL;
468     int i;
469 
470     for (i = 0; i < num; i++)
471     {
472 	CCSSettingValue *value = calloc (1, sizeof (CCSSettingValue));
473 	if (!value)
474 	    return l;
475 
476 	value->isListChild = TRUE;
477 	value->parent = parent;
478 	value->value.asBool = array[i];
479 	l = ccsSettingValueListAppend (l, value);
480     }
481 
482     return l;
483 }
484 
ccsGetValueListFromColorArray(CCSSettingColorValue * array,int num,CCSSetting * parent)485 CCSSettingValueList ccsGetValueListFromColorArray (CCSSettingColorValue * array,
486 						   int num, CCSSetting *parent)
487 {
488     CCSSettingValueList l = NULL;
489     int i;
490 
491     for (i = 0; i < num; i++)
492     {
493 	CCSSettingValue *value = calloc (1, sizeof (CCSSettingValue));
494 	if (!value)
495 	    return l;
496 
497 	value->isListChild = TRUE;
498 	value->parent = parent;
499 	value->value.asColor = array[i];
500 	l = ccsSettingValueListAppend (l, value);
501     }
502 
503     return l;
504 }
505 
506