]> icculus.org git repositories - dana/openbox.git/blob - openbox/config_value.c
wip: Add config_parser.c which will provide a nice means to specify config variables...
[dana/openbox.git] / openbox / config_value.c
1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
2
3    config_value.c for the Openbox window manager
4    Copyright (c) 2011        Dana Jansens
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    See the COPYING file for a copy of the GNU General Public License.
17 */
18
19 #include "config_value.h"
20 #include "action_list.h"
21 #include "geom.h"
22 #include "keyboard.h"
23 #include "mouse.h"
24 #include "translate.h"
25
26 #include "stdlib.h"
27
28 struct _ObConfigValue {
29     gint ref;
30     enum {
31         OB_CV_STRING,
32         OB_CV_LIST,
33         OB_CV_ACTION_LIST
34     } type;
35     union {
36         gchar *string;
37         gchar **list;
38         ObActionList *actions;
39     } v;
40 };
41
42 void config_value_ref(ObConfigValue *v)
43 {
44     ++v->ref;
45 }
46
47 void config_value_unref(ObConfigValue *v)
48 {
49     if (v && --v->ref < 1) {
50         switch (v->type) {
51         case OB_CV_STRING:
52             g_free(v->v.string);
53             break;
54         case OB_CV_LIST:
55             g_strfreev(v->v.list);
56             break;
57         case OB_CV_ACTION_LIST:
58             action_list_unref(v->v.actions);
59             break;
60         }
61         g_slice_free(ObConfigValue, v);
62     }
63 }
64
65 /*************************** describer functions ***************************/
66
67 gboolean config_value_is_string(const ObConfigValue *v)
68 {
69     g_return_val_if_fail(v != NULL, FALSE);
70     return v->type == OB_CV_STRING;
71 }
72
73 gboolean config_value_is_string_list(const ObConfigValue *v)
74 {
75     g_return_val_if_fail(v != NULL, FALSE);
76     return v->type == OB_CV_LIST;
77 }
78
79 gboolean config_value_is_action_list(const ObConfigValue *v)
80 {
81     g_return_val_if_fail(v != NULL, FALSE);
82     return v->type == OB_CV_ACTION_LIST;
83 }
84
85 /**************************** pointer functions ****************************/
86
87 gboolean config_value_copy_ptr(ObConfigValue *v,
88                                ObConfigValueDataType type,
89                                ObConfigValueDataPtr p,
90                                const ObConfigValueEnum e[])
91 {
92     gboolean ok = TRUE;
93
94     switch (type) {
95     case OB_CONFIG_VALUE_STRING:
96         *p.string = config_value_string(v);
97         break;
98     case OB_CONFIG_VALUE_BOOLEAN:
99         *p.boolean = config_value_bool(v);
100         break;
101     case OB_CONFIG_VALUE_INTEGER:
102         *p.integer = config_value_int(v);
103         break;
104     case OB_CONFIG_VALUE_ENUM:
105         ok = config_value_enum(v, e, p.enumeration);
106         break;
107     case OB_CONFIG_VALUE_FRACTION: {
108         gint n, d;
109         config_value_fraction(v, &n, &d);
110         p.fraction->numer = n;
111         p.fraction->denom = d;
112         break;
113     }
114     case OB_CONFIG_VALUE_GRAVITY_COORD: {
115         config_value_gravity_coord(v, p.coord);
116         break;
117     }
118     case OB_CONFIG_VALUE_KEY:
119         ok = config_value_key(v, p.key);
120         break;
121     case OB_CONFIG_VALUE_BUTTON:
122         ok = config_value_button(v, p.button);
123         break;
124     case OB_CONFIG_VALUE_STRING_LIST: {
125         *p.list = config_value_string_list(v);
126         break;
127     }
128     case OB_CONFIG_VALUE_ACTIONLIST:
129         *p.actions = config_value_action_list(v);
130         break;
131     case NUM_OB_CONFIG_VALUE_TYPES:
132         g_assert_not_reached();
133     }
134     return ok;
135 }
136
137
138 /***************************** getter functions ****************************/
139
140 const gchar* config_value_string(ObConfigValue *v)
141 {
142     g_return_val_if_fail(v != NULL, NULL);
143     g_return_val_if_fail(config_value_is_string(v), NULL);
144     return v->v.string;
145 }
146 gboolean config_value_bool(ObConfigValue *v)
147 {
148     g_return_val_if_fail(v != NULL, FALSE);
149     g_return_val_if_fail(config_value_is_string(v), FALSE);
150     return (g_strcasecmp(v->v.string, "true") == 0 ||
151             g_strcasecmp(v->v.string, "yes") == 0);
152 }
153 guint config_value_int(ObConfigValue *v)
154 {
155     gchar *s;
156     g_return_val_if_fail(v != NULL, FALSE);
157     g_return_val_if_fail(config_value_is_string(v), FALSE);
158     s = v->v.string;
159     return strtol(s, &s, 10);
160 }
161 gboolean config_value_enum(ObConfigValue *v, const ObConfigValueEnum choices[],
162                            guint *out)
163 {
164     const ObConfigValueEnum *e;
165
166     g_return_val_if_fail(v != NULL, FALSE);
167     g_return_val_if_fail(config_value_is_string(v), FALSE);
168     g_return_val_if_fail(choices != NULL, FALSE);
169
170     for (e = choices; e->name; ++e)
171         if (g_strcasecmp(v->v.string, e->name) == 0) {
172             *out = e->value;
173             return TRUE;
174         }
175     return FALSE;
176 }
177 void config_value_fraction(ObConfigValue *v, gint *numer, gint *denom)
178 {
179     gchar *s;
180
181     *numer = *denom = 0;
182
183     g_return_if_fail(v != NULL);
184     g_return_if_fail(config_value_is_string(v));
185
186     s = v->v.string;
187     *numer = strtol(s, &s, 10);
188     if (*s == '%')
189         *denom = 100;
190     else if (*s == '/')
191         *denom = atoi(s+1);
192     else
193         *denom = 0;
194 }
195 void config_value_gravity_coord(ObConfigValue *v, GravityCoord *c)
196 {
197     gchar *s;
198
199     c->center = FALSE;
200     c->pos = 0;
201     c->denom = 0;
202
203     g_return_if_fail(v != NULL);
204     g_return_if_fail(config_value_is_string(v));
205
206     s = v->v.string;
207     if (!g_ascii_strcasecmp(s, "center"))
208         c->center = TRUE;
209     else {
210         if (s[0] == '-')
211             c->opposite = TRUE;
212         if (s[0] == '-' || s[0] == '+')
213             ++s;
214
215         c->pos = strtol(s, &s, 10);
216
217         if (*s == '%')
218             c->denom = 100;
219         else if (*s == '/')
220             c->denom = atoi(s+1);
221     }
222 }
223 gboolean config_value_key(ObConfigValue *v, struct _ObKeyboardKey *k)
224 {
225     k->modifiers = 0;
226     k->keycode = 0;
227
228     g_return_val_if_fail(v != NULL, FALSE);
229     g_return_val_if_fail(config_value_is_string(v), FALSE);
230     return translate_key(v->v.string, &k->modifiers, &k->keycode);
231 }
232 gboolean config_value_button(ObConfigValue *v, struct _ObMouseButton *b)
233 {
234     b->modifiers = 0;
235     b->button = 0;
236
237     g_return_val_if_fail(v != NULL, FALSE);
238     g_return_val_if_fail(config_value_is_string(v), FALSE);
239     return translate_button(v->v.string, &b->modifiers, &b->button);
240 }
241 const gchar *const* config_value_string_list(ObConfigValue *v)
242 {
243     g_return_val_if_fail(v != NULL, NULL);
244     g_return_val_if_fail(config_value_is_string_list(v), NULL);
245     return (const gchar**)v->v.list;
246 }
247 ObActionList* config_value_action_list(ObConfigValue *v)
248 {
249     g_return_val_if_fail(v != NULL, NULL);
250     g_return_val_if_fail(config_value_is_action_list(v), NULL);
251     return v->v.actions;
252 }
253
254 /****************************** constructors ******************************/
255
256 ObConfigValue* config_value_new_string(const gchar *s)
257 {
258     g_return_val_if_fail(s != NULL, NULL);
259     return config_value_new_string_steal(g_strdup(s));
260 }
261
262 ObConfigValue* config_value_new_string_steal(gchar *s)
263 {
264     ObConfigValue *v;
265     g_return_val_if_fail(s != NULL, NULL);
266     v = g_slice_new(ObConfigValue);
267     v->ref = 1;
268     v->type = OB_CV_STRING;
269     v->v.string = s;
270     return v;
271 }
272
273 ObConfigValue* config_value_new_string_list(gchar **list)
274 {
275     return config_value_new_string_list_steal(g_strdupv(list));
276 }
277
278 ObConfigValue* config_value_new_string_list_steal(gchar **list)
279 {
280     ObConfigValue *v = g_slice_new(ObConfigValue);
281     v->ref = 1;
282     v->type = OB_CV_LIST;
283     v->v.list = list;
284     return v;
285 }
286
287 ObConfigValue* config_value_new_action_list(ObActionList *al)
288 {
289     ObConfigValue *v = g_slice_new(ObConfigValue);
290     v->ref = 1;
291     v->type = OB_CV_ACTION_LIST;
292     v->v.actions = al;
293     action_list_ref(al);
294     return v;
295 }