only load the system rc if the user rc didnt load
[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     /* set up built in variables! and their default values! */
26
27     config_def_set(config_def_new("engine", Config_String));
28     config_def_set(config_def_new("theme", Config_String));
29     config_def_set(config_def_new("font", Config_String));
30     config_def_set(config_def_new("font.shadow.offset", Config_Integer));
31     config_def_set(config_def_new("font.shadow.tint", Config_Integer));
32     config_def_set(config_def_new("titlebar.layout", Config_String));
33
34     /*g_datalist_foreach(&config_def, print_config, NULL);*/
35 }
36
37 void config_shutdown()
38 {
39     g_datalist_clear(&config);
40     g_datalist_clear(&config_def);
41 }
42
43 void config_parse()
44 {
45     FILE *file;
46     char *path;
47     gboolean load = FALSE;
48
49     /* load the user rc */
50     path = g_build_filename(g_get_home_dir(), ".openbox", "rc3", NULL);
51     if ((file = fopen(path, "r")) != NULL) {
52         cparse_go(path, file);
53         fclose(file);
54         load = TRUE;
55     }
56     g_free(path);
57     g_free(path);
58
59     if (!load) {
60         /* load the system wide rc */
61         path = g_build_filename(RCDIR, "rc3", NULL);
62         if ((file = fopen(path, "r")) != NULL) {
63             cparse_go(path, file);
64             fclose(file);
65         }
66     }
67 }
68
69 gboolean config_set(char *name, ConfigValueType type, ConfigValue value)
70 {
71     ConfigDefEntry *def;
72     gboolean ret = FALSE;
73
74     name = g_ascii_strdown(name, -1);
75     g_message("Setting %s", name);
76
77     /*g_datalist_foreach(&config_def, print_config, NULL);*/
78     def = g_datalist_get_data(&config_def, name);
79
80     if (def == NULL) {
81         g_message("Invalid config option '%s'", name);
82     } else {
83         if (def->hasList) {
84             gboolean found = FALSE;
85             GSList *it;
86
87             it = def->values;
88             g_assert(it != NULL);
89             do {
90                 if (g_ascii_strcasecmp(it->data, value.string) == 0) {
91                     found = TRUE;
92                     break;
93                 }
94             } while ((it = it->next));
95
96             if (!found)
97                 g_message("Invalid value '%s' for config option '%s'",
98                           value.string, name);
99             else
100                 ret = TRUE;
101         } else
102             ret = TRUE;
103
104     }
105
106     if (ret)
107         config_set_entry(name, type, value);
108     else
109         g_free(name);
110
111     return ret;
112 }
113
114 gboolean config_get(char *name, ConfigValueType type, ConfigValue *value)
115 {
116     ConfigEntry *entry;
117     gboolean ret = FALSE;
118
119     name = g_ascii_strdown(name, -1);
120     entry = g_datalist_get_data(&config, name);
121     if (entry != NULL && entry->type == type) {
122         *value = entry->value;
123         ret = TRUE;
124     }
125     g_free(name);
126     return ret;
127 }
128
129 static void config_set_entry(char *name, ConfigValueType type,
130                              ConfigValue value)
131 {
132     ConfigEntry *entry = NULL;
133
134     entry = g_new(ConfigEntry, 1);
135     entry->name = name;
136     entry->type = type;
137     if (type == Config_String)
138         entry->value.string = g_strdup(value.string);
139     else
140         entry->value = value;
141
142     g_datalist_set_data_full(&config, name, entry,
143                              (GDestroyNotify)config_free_entry);
144 }
145
146 static void config_free_entry(ConfigEntry *entry)
147 {
148     g_free(entry->name);
149     entry->name = NULL;
150     if(entry->type == Config_String) {
151         g_free(entry->value.string);
152         entry->value.string = NULL;
153     }
154     g_free(entry);
155 }
156
157 ConfigDefEntry *config_def_new(char *name, ConfigValueType type)
158 {
159     ConfigDefEntry *entry;
160
161     entry = g_new(ConfigDefEntry, 1);
162     entry->name = g_ascii_strdown(name, -1);
163     entry->hasList = FALSE;
164     entry->type = type;
165     entry->values = NULL;
166     return entry;
167 }
168
169 static void config_def_free(ConfigDefEntry *entry)
170 {
171     GSList *it;
172
173     g_free(entry->name);
174     if (entry->hasList) {
175         for (it = entry->values; it != NULL; it = it->next)
176             g_free(it->data);
177         g_slist_free(entry->values);
178     }
179     g_free(entry);
180 }
181
182 gboolean config_def_add_value(ConfigDefEntry *entry, char *value)
183 {
184     if (entry->type != Config_String) {
185         g_warning("Tried adding value to non-string config definition");
186         return FALSE;
187     }
188
189     entry->hasList = TRUE;
190     entry->values = g_slist_append(entry->values, g_ascii_strdown(value, -1));
191     return TRUE;
192 }
193
194 gboolean config_def_set(ConfigDefEntry *entry)
195 {
196     gboolean ret = FALSE;
197     ConfigDefEntry *def;
198
199     if ((def = g_datalist_get_data(&config_def, entry->name))) {
200         g_assert(def != entry); /* adding it twice!? */
201         g_warning("Definition already set for config option '%s'. ",
202                   entry->name);
203         config_def_free(entry);
204     } else {
205         g_datalist_set_data_full(&config_def, entry->name, entry,
206                                  (GDestroyNotify)config_def_free);
207         ret = TRUE;
208     }
209
210     return ret;
211 }