give the filename to the parser for errors
[dana/openbox.git] / openbox / config.c
1 #include "config.h"
2
3 #ifdef HAVE_STDIO_H
4 #  include <stdio.h>
5 #endif
6
7 static void config_free_entry(ConfigEntry *entry);
8 static void config_set_entry(char *name, ConfigValueType type,
9                              ConfigValue value);
10 static void config_def_free(ConfigDefEntry *entry);
11 static void print_config(GQuark q, gpointer data, gpointer fonk){
12     ConfigDefEntry *e = (ConfigDefEntry *)data;
13     g_message("config: %s %d", e->name, e->hasList);
14 }
15
16 static GData *config = NULL;
17 static GData *config_def = NULL;
18
19 /* provided by cparse.l */
20 void cparse_go(char *filename, FILE *);
21
22
23 void config_startup()
24 {
25     /* test definition */
26     ConfigDefEntry *def;
27
28     def = config_def_new("test", Config_String);
29     config_def_set(def);
30
31     def = config_def_new("test", Config_String);
32     config_def_set(def);
33
34     def = config_def_new("testlist", Config_String);
35     config_def_add_value(def, "one");
36     config_def_add_value(def, "two");
37     config_def_set(def);
38
39     g_datalist_foreach(&config_def, print_config, NULL);
40 }
41
42 void config_shutdown()
43 {
44     g_datalist_clear(&config);
45     g_datalist_clear(&config_def);
46 }
47
48 void config_parse()
49 {
50     FILE *file;
51     char *path;
52
53     /* load the system wide rc file first */
54     path = g_build_filename(RCDIR, "rc3", NULL);
55     if ((file = fopen(path, "r")) != NULL) {
56         cparse_go(path, file);
57         fclose(file);
58     }
59     g_free(path);
60
61     /* then load the user one which can override it */
62     path = g_build_filename(g_get_home_dir(), ".openbox", "rc3", NULL);
63     if ((file = fopen(path, "r")) != NULL) {
64         cparse_go(path, file);
65         fclose(file);
66     }
67     g_free(path);
68 }
69
70 gboolean config_set(char *name, ConfigValueType type, ConfigValue value)
71 {
72     ConfigDefEntry *def;
73     gboolean ret = FALSE;
74
75     name = g_ascii_strdown(name, -1);
76     g_message("Setting %s", name);
77
78     g_datalist_foreach(&config_def, print_config, NULL);
79     def = g_datalist_get_data(&config_def, name);
80
81     if (def == NULL) {
82         g_message("Invalid config option '%s'", name);
83     } else {
84         if (def->hasList) {
85             gboolean found = FALSE;
86             GSList *it;
87
88             it = def->values;
89             g_assert(it != NULL);
90             do {
91                 if (g_ascii_strcasecmp(it->data, value.string) == 0) {
92                     found = TRUE;
93                     break;
94                 }
95             } while ((it = it->next));
96
97             if (!found)
98                 g_message("Invalid value '%s' for config option '%s'",
99                           value.string, name);
100             else
101                 ret = TRUE;
102         } else
103             ret = TRUE;
104
105     }
106
107     if (ret)
108         config_set_entry(name, type, value);
109     else
110         g_free(name);
111
112     return ret;
113 }
114
115 gboolean config_get(char *name, ConfigValueType type, ConfigValue *value)
116 {
117     ConfigEntry *entry;
118     gboolean ret = FALSE;
119
120     name = g_ascii_strdown(name, -1);
121     entry = g_datalist_get_data(&config, name);
122     if (entry != NULL && entry->type == type) {
123         *value = entry->value;
124         ret = TRUE;
125     }
126     g_free(name);
127     return ret;
128 }
129
130 static void config_set_entry(char *name, ConfigValueType type,
131                              ConfigValue value)
132 {
133     ConfigEntry *entry = NULL;
134
135     entry = g_new(ConfigEntry, 1);
136     entry->name = name;
137     entry->type = type;
138     if (type == Config_String)
139         entry->value.string = g_strdup(value.string);
140     else
141         entry->value = value;
142
143     g_datalist_set_data_full(&config, name, entry,
144                              (GDestroyNotify)config_free_entry);
145 }
146
147 static void config_free_entry(ConfigEntry *entry)
148 {
149     g_free(entry->name);
150     entry->name = NULL;
151     if(entry->type == Config_String) {
152         g_free(entry->value.string);
153         entry->value.string = NULL;
154     }
155     g_free(entry);
156 }
157
158 ConfigDefEntry *config_def_new(char *name, ConfigValueType type)
159 {
160     ConfigDefEntry *entry;
161
162     entry = g_new(ConfigDefEntry, 1);
163     entry->name = g_ascii_strdown(name, -1);
164     entry->hasList = FALSE;
165     entry->type = type;
166     entry->values = NULL;
167     return entry;
168 }
169
170 static void config_def_free(ConfigDefEntry *entry)
171 {
172     GSList *it;
173
174     g_free(entry->name);
175     if (entry->hasList) {
176         for (it = entry->values; it != NULL; it = it->next)
177             g_free(it->data);
178         g_slist_free(entry->values);
179     }
180     g_free(entry);
181 }
182
183 gboolean config_def_add_value(ConfigDefEntry *entry, char *value)
184 {
185     if (entry->type != Config_String) {
186         g_warning("Tried adding value to non-string config definition");
187         return FALSE;
188     }
189
190     entry->hasList = TRUE;
191     entry->values = g_slist_append(entry->values, g_ascii_strdown(value, -1));
192     return TRUE;
193 }
194
195 gboolean config_def_set(ConfigDefEntry *entry)
196 {
197     gboolean ret = FALSE;
198     ConfigDefEntry *def;
199
200     if ((def = g_datalist_get_data(&config_def, entry->name))) {
201         g_assert(def != entry); /* adding it twice!? */
202         g_warning("Definition already set for config option '%s'. ",
203                   entry->name);
204         config_def_free(entry);
205     } else {
206         g_datalist_set_data_full(&config_def, entry->name, entry,
207                                  (GDestroyNotify)config_def_free);
208         ret = TRUE;
209     }
210
211     return ret;
212 }