big fat commit..
[mikachu/openbox.git] / src / configuration.cc
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2
3 #ifdef    HAVE_CONFIG_H
4 #include "../config.h"
5 #endif // HAVE_CONFIG_H
6
7 extern "C" {
8 #ifdef    HAVE_STDLIB_H
9 #  include <stdlib.h>
10 #endif // HAVE_STDLIB_H
11 }
12
13 #include "configuration.hh"
14 #include "util.hh"
15
16 #include <algorithm>
17
18 using std::string;
19
20 bool Configuration::_initialized = False;
21
22 Configuration::Configuration(const string &file, bool autosave) {
23   setFile(file);
24   _modified = False;
25   _database = NULL;
26   _autosave = autosave;
27   if (! _initialized) {
28     XrmInitialize();
29     _initialized = True;
30   }
31 }
32
33 Configuration::Configuration(bool autosave) {
34   _modified = False;
35   _database = NULL;
36   _autosave = autosave;
37   if (! _initialized) {
38     XrmInitialize();
39     _initialized = True;
40   }
41 }
42
43 Configuration::~Configuration() {
44   if (_database != NULL)
45     XrmDestroyDatabase(_database);
46 }
47
48 void Configuration::setFile(const string &file) {
49   _file = file;
50 }
51
52 void Configuration::setAutoSave(bool autosave) {
53   _autosave = autosave;
54 }
55
56 void Configuration::save() {
57   assert(_database != NULL);
58   XrmPutFileDatabase(_database, _file.c_str());
59   _modified = False;
60 }
61
62 bool Configuration::load() {
63   if (_database != NULL)
64     XrmDestroyDatabase(_database);
65   _modified = False;
66   if (NULL == (_database = XrmGetFileDatabase(_file.c_str())))
67     return False;
68   return True;
69 }
70
71 bool Configuration::merge(const string &file, bool overwrite) {
72   if (XrmCombineFileDatabase(file.c_str(), &_database, overwrite) == 0)
73     return False;
74   _modified = True;
75   if (_autosave)
76     save();
77   return True;
78 }
79
80 void Configuration::create() {
81   if (_database != NULL)
82     XrmDestroyDatabase(_database);
83   _modified = False;
84   assert(NULL != (_database = XrmGetStringDatabase("")));
85 }
86
87 void Configuration::setValue(const string &rname, bool value) {
88   assert(_database != NULL);
89
90   const char *val = (value ? "True" : "False");
91   string rc_string = rname + ": " + val;
92   XrmPutLineResource(&_database, rc_string.c_str());
93
94   _modified = True;
95   if (_autosave)
96     save();
97 }
98
99 void Configuration::setValue(const string &rname, unsigned long value) {
100   assert(_database != NULL);
101   
102   string rc_string = rname + ": " + itostring(value);
103   XrmPutLineResource(&_database, rc_string.c_str());
104
105   _modified = True;
106   if (_autosave)
107     save();
108 }
109
110 void Configuration::setValue(const string &rname, long value) {
111   assert(_database != NULL);
112   
113   string rc_string = rname + ": " + itostring(value);
114   XrmPutLineResource(&_database, rc_string.c_str());
115
116   _modified = True;
117   if (_autosave)
118     save();
119 }
120
121 void Configuration::setValue(const string &rname, const char *value) {
122   assert(_database != NULL);
123   assert(value != NULL);
124   
125   string rc_string = rname + ": " + value;
126   XrmPutLineResource(&_database, rc_string.c_str());
127
128   _modified = True;
129   if (_autosave)
130     save();
131 }
132
133 void Configuration::setValue(const string &rname, const string &value) {
134   assert(_database != NULL);
135   
136   string rc_string = rname + ": " + value;
137   XrmPutLineResource(&_database, rc_string.c_str());
138
139   _modified = True;
140   if (_autosave)
141     save();
142 }
143
144 bool Configuration::getValue(const string &rname, bool &value) const {
145   assert(_database != NULL);
146   
147   string rclass = createClassName(rname);
148   
149   char *rettype;
150   XrmValue retvalue;
151   if (0 == XrmGetResource(_database, rname.c_str(), rclass.c_str(), 
152                           &rettype, &retvalue) || retvalue.addr == NULL)
153     return False;
154   string val = retvalue.addr;
155   if (val == "True" || val == "True")
156     value = True;
157   else
158     value = False;
159   return True;
160 }
161
162 bool Configuration::getValue(const string &rname, long &value) const {
163   assert(_database != NULL);
164   
165   string rclass = createClassName(rname);
166   
167   char *rettype;
168   XrmValue retvalue;
169   if (0 == XrmGetResource(_database, rname.c_str(), rclass.c_str(), 
170                           &rettype, &retvalue) || retvalue.addr == NULL)
171     return False;
172   char *end;
173   value = strtol(retvalue.addr, &end, 10);
174   if (end == retvalue.addr)
175     return False;
176   return True;
177 }
178
179 bool Configuration::getValue(const string &rname, unsigned long &value) const {
180   assert(_database != NULL);
181   
182   string rclass = createClassName(rname);
183   
184   char *rettype;
185   XrmValue retvalue;
186   if (0 == XrmGetResource(_database, rname.c_str(), rclass.c_str(), 
187                           &rettype, &retvalue) || retvalue.addr == NULL)
188     return False;
189   char *end;
190   value = strtoul(retvalue.addr, &end, 10);
191   if (end == retvalue.addr)
192     return False;
193   return True;
194 }
195
196 bool Configuration::getValue(const string &rname,
197                              string &value) const {
198   assert(_database != NULL);
199   
200   string rclass = createClassName(rname);
201   
202   char *rettype;
203   XrmValue retvalue;
204   if (0 == XrmGetResource(_database, rname.c_str(), rclass.c_str(), 
205                           &rettype, &retvalue) || retvalue.addr == NULL)
206     return False;
207   value = retvalue.addr;
208   return True;
209 }
210   
211
212 string Configuration::createClassName(const string &rname) const {
213   string rclass(rname);
214
215   string::iterator it = rclass.begin(), end = rclass.end();
216   while (True) {
217     *it = toUpper(*it);
218     ++it;
219     if (it == end) break;
220     it = std::find(it, rclass.end(), '.');
221     if (it == end) break;
222     ++it;
223     if (it == end) break;
224   }
225   return rclass;
226 }
227   
228
229 char Configuration::toUpper(char c) const {
230   if (c >= 'a' && c <= 'z')
231     return c - 'a' + 'A';
232   return c;
233 }