add focus options
[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
12 static GData *config = NULL;
13 static GData *config_def = NULL;
14
15 /* provided by cparse.l */
16 void cparse_go(char *filename, FILE *);
17
18
19 void config_startup()
20 {
21     ConfigValue val;
22
23     /* set up options exported by the kernel */
24     config_def_set(config_def_new("engine", Config_String,
25                                   "Engine",
26                                   "The name of the theming engine to be used "
27                                   "to decorate windows."));
28     config_def_set(config_def_new("theme", Config_String,
29                                   "Theme",
30                                   "The name of the theme to load with the "
31                                   "chosen engine."));
32     config_def_set(config_def_new("font", Config_String,
33                                   "Titlebar Font",
34                                   "The fontstring specifying the font to "
35                                   "be used in window titlebars."));
36     config_def_set(config_def_new("font.shadow", Config_Bool,
37                                   "Titlebar Font Shadow",
38                                   "Whether or not the text in the window "
39                                   "titlebars gets a drop shadow."));
40     config_def_set(config_def_new("font.shadow.offset", Config_Integer,
41                                   "Titlebar Font Shadow Offset",
42                                   "The offset of the drop shadow for text "
43                                   "in the window titlebars."));
44     config_def_set(config_def_new("titlebar.layout", Config_String,
45                                   "Titlebar Layout",
46                                   "The ordering of the elements in the "
47                                   "window titlebars."));
48
49     config_def_set(config_def_new("focusNew", Config_Bool,
50                                   "Focus New Windows",
51                                   "Focus windows when they first appear."));
52     val.bool = TRUE;
53     config_set("focusNew", Config_Bool, val);
54
55     config_def_set(config_def_new("focusFollowsMouse", Config_Bool,
56                                   "Focus Follows Mouse",
57                                   "Focus windows when the mouse pointer "
58                                   "enters them."));
59     val.bool = TRUE;
60     config_set("focusFollowsMouse", Config_Bool, val);
61 }
62
63 void config_shutdown()
64 {
65     g_datalist_clear(&config);
66     g_datalist_clear(&config_def);
67 }
68
69 void config_parse()
70 {
71     FILE *file;
72     char *path;
73     gboolean load = FALSE;
74
75     /* load the user rc */
76     path = g_build_filename(g_get_home_dir(), ".openbox", "rc3", NULL);
77     if ((file = fopen(path, "r")) != NULL) {
78         cparse_go(path, file);
79         fclose(file);
80         load = TRUE;
81     }
82     g_free(path);
83
84     if (!load) {
85         /* load the system wide rc */
86         path = g_build_filename(RCDIR, "rc3", NULL);
87         if ((file = fopen(path, "r")) != NULL) {
88             /*cparse_go(path, file);*/
89             fclose(file);
90         }
91         g_free(path);
92     }
93 }
94
95 gboolean config_set(char *name, ConfigValueType type, ConfigValue value)
96 {
97     ConfigDefEntry *def;
98     gboolean ret = FALSE;
99
100     name = g_ascii_strdown(name, -1);
101
102     def = g_datalist_get_data(&config_def, name);
103
104     if (def == NULL) {
105         g_warning("Invalid config option '%s'", name);
106     } else {
107         if (def->hasList) {
108             gboolean found = FALSE;
109             GSList *it;
110
111             it = def->values;
112             g_assert(it != NULL);
113             do {
114                 if (g_ascii_strcasecmp(it->data, value.string) == 0) {
115                     found = TRUE;
116                     break;
117                 }
118             } while ((it = it->next));
119
120             if (!found)
121                 g_warning("Invalid value '%s' for config option '%s'",
122                           value.string, name);
123             else
124                 ret = TRUE;
125         } else if (type != def->type) {
126             g_warning("Incorrect type of value for config option '%s'", name);
127         } else
128             ret = TRUE;
129
130     }
131
132     if (ret)
133         config_set_entry(name, type, value);
134     else
135         g_free(name);
136
137     return ret;
138 }
139
140 gboolean config_get(char *name, ConfigValueType type, ConfigValue *value)
141 {
142     ConfigEntry *entry;
143     gboolean ret = FALSE;
144
145     name = g_ascii_strdown(name, -1);
146     entry = g_datalist_get_data(&config, name);
147     if (entry != NULL && entry->type == type) {
148         *value = entry->value;
149         ret = TRUE;
150     }
151     g_free(name);
152     return ret;
153 }
154
155 static void config_set_entry(char *name, ConfigValueType type,
156                              ConfigValue value)
157 {
158     ConfigEntry *entry = NULL;
159
160     entry = g_new(ConfigEntry, 1);
161     entry->name = name;
162     entry->type = type;
163     if (type == Config_String)
164         entry->value.string = g_strdup(value.string);
165     else
166         entry->value = value;
167
168     g_datalist_set_data_full(&config, name, entry,
169                              (GDestroyNotify)config_free_entry);
170 }
171
172 static void config_free_entry(ConfigEntry *entry)
173 {
174     g_free(entry->name);
175     entry->name = NULL;
176     if(entry->type == Config_String) {
177         g_free(entry->value.string);
178         entry->value.string = NULL;
179     }
180     g_free(entry);
181 }
182
183 ConfigDefEntry *config_def_new(char *name, ConfigValueType type,
184                                 char *descriptive_name, char *long_description)
185 {
186     ConfigDefEntry *entry;
187
188     entry = g_new(ConfigDefEntry, 1);
189     entry->name = g_ascii_strdown(name, -1);
190     entry->descriptive_name = g_strdup(descriptive_name);
191     entry->long_description = g_strdup(long_description);
192     entry->hasList = FALSE;
193     entry->type = type;
194     entry->values = NULL;
195     return entry;
196 }
197
198 static void config_def_free(ConfigDefEntry *entry)
199 {
200     GSList *it;
201
202     g_free(entry->name);
203     g_free(entry->descriptive_name);
204     g_free(entry->long_description);
205     if (entry->hasList) {
206         for (it = entry->values; it != NULL; it = it->next)
207             g_free(it->data);
208         g_slist_free(entry->values);
209     }
210     g_free(entry);
211 }
212
213 gboolean config_def_add_value(ConfigDefEntry *entry, char *value)
214 {
215     if (entry->type != Config_String) {
216         g_warning("Tried adding value to non-string config definition");
217         return FALSE;
218     }
219
220     entry->hasList = TRUE;
221     entry->values = g_slist_append(entry->values, g_ascii_strdown(value, -1));
222     return TRUE;
223 }
224
225 gboolean config_def_set(ConfigDefEntry *entry)
226 {
227     gboolean ret = FALSE;
228     ConfigDefEntry *def;
229
230     if ((def = g_datalist_get_data(&config_def, entry->name))) {
231         g_assert(def != entry); /* adding it twice!? */
232         g_warning("Definition already set for config option '%s'. ",
233                   entry->name);
234         config_def_free(entry);
235     } else {
236         g_datalist_set_data_full(&config_def, entry->name, entry,
237                                  (GDestroyNotify)config_def_free);
238         ret = TRUE;
239     }
240
241     return ret;
242 }