xref: /haiku/src/add-ons/translators/shared/TranslatorSettings.cpp (revision 1d9d47fc72028bb71b5f232a877231e59cfe2438)
1 /*****************************************************************************/
2 // TranslatorSettings
3 // Written by Michael Wilber, OBOS Translation Kit Team
4 //
5 // TranslatorSettings.cpp
6 //
7 // This class manages (saves/loads/locks/unlocks) the settings
8 // for a Translator.
9 //
10 //
11 // Copyright (c) 2004 OpenBeOS Project
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining a
14 // copy of this software and associated documentation files (the "Software"),
15 // to deal in the Software without restriction, including without limitation
16 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 // and/or sell copies of the Software, and to permit persons to whom the
18 // Software is furnished to do so, subject to the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be included
21 // in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 // DEALINGS IN THE SOFTWARE.
30 /*****************************************************************************/
31 
32 #include <string.h>
33 #include <File.h>
34 #include <FindDirectory.h>
35 #include <TranslatorFormats.h>
36 	// for B_TRANSLATOR_EXT_*
37 #include "TranslatorSettings.h"
38 
39 // ---------------------------------------------------------------
40 // Constructor
41 //
42 // Sets the default settings, location for the settings file
43 // and sets the reference count to 1
44 //
45 // Preconditions:
46 //
47 // Parameters:
48 //
49 // Postconditions:
50 //
51 // Returns:
52 // ---------------------------------------------------------------
53 TranslatorSettings::TranslatorSettings(const char *settingsFile,
54 	TranSetting *defaults, int32 defCount)
55 	: fLock("TranslatorSettings Lock")
56 {
57 	if (find_directory(B_USER_SETTINGS_DIRECTORY, &fSettingsPath))
58 		fSettingsPath.SetTo("/tmp");
59 	fSettingsPath.Append(settingsFile);
60 
61 	fRefCount = 1;
62 
63 	if (defCount > 0) {
64 		fDefaults = defaults;
65 		fDefCount = defCount;
66 	} else {
67 		fDefaults = NULL;
68 		fDefCount = 0;
69 	}
70 
71 	// Add Default Settings
72 	// (Used when loading from the settings file or from
73 	// a BMessage fails)
74 	const TranSetting *defs = fDefaults;
75 	for (int32 i = 0; i < fDefCount; i++) {
76 		switch (defs[i].dataType) {
77 			case TRAN_SETTING_BOOL:
78 				fSettingsMsg.AddBool(defs[i].name,
79 					static_cast<bool>(defs[i].defaultVal));
80 				break;
81 
82 			case TRAN_SETTING_INT32:
83 				fSettingsMsg.AddInt32(defs[i].name, defs[i].defaultVal);
84 				break;
85 
86 			default:
87 				// ASSERT here? Erase the bogus setting entry instead?
88 				break;
89 		}
90 	}
91 }
92 
93 // ---------------------------------------------------------------
94 // Acquire
95 //
96 // Returns a pointer to the TranslatorSettings and increments
97 // the reference count.
98 //
99 // Preconditions:
100 //
101 // Parameters:
102 //
103 // Postconditions:
104 //
105 // Returns: pointer to this TranslatorSettings object
106 // ---------------------------------------------------------------
107 TranslatorSettings *
108 TranslatorSettings::Acquire()
109 {
110 	TranslatorSettings *psettings = NULL;
111 
112 	fLock.Lock();
113 	fRefCount++;
114 	psettings = this;
115 	fLock.Unlock();
116 
117 	return psettings;
118 }
119 
120 // ---------------------------------------------------------------
121 // Release
122 //
123 // Decrements the reference count and deletes the
124 // TranslatorSettings if the reference count is zero.
125 //
126 // Preconditions:
127 //
128 // Parameters:
129 //
130 // Postconditions:
131 //
132 // Returns: pointer to this TranslatorSettings object if
133 // the reference count is greater than zero, returns NULL
134 // if the reference count is zero and the TranslatorSettings
135 // object has been deleted
136 // ---------------------------------------------------------------
137 TranslatorSettings *
138 TranslatorSettings::Release()
139 {
140 	TranslatorSettings *psettings = NULL;
141 
142 	fLock.Lock();
143 	fRefCount--;
144 	if (fRefCount > 0) {
145 		psettings = this;
146 		fLock.Unlock();
147 	} else
148 		delete this;
149 			// delete this object and
150 			// release locks
151 
152 	return psettings;
153 }
154 
155 // ---------------------------------------------------------------
156 // Destructor
157 //
158 // Does nothing!
159 //
160 // Preconditions:
161 //
162 // Parameters:
163 //
164 // Postconditions:
165 //
166 // Returns:
167 // ---------------------------------------------------------------
168 TranslatorSettings::~TranslatorSettings()
169 {
170 }
171 
172 // ---------------------------------------------------------------
173 // LoadSettings
174 //
175 // Loads the settings by reading them from the default
176 // settings file.
177 //
178 // Preconditions:
179 //
180 // Parameters:
181 //
182 // Postconditions:
183 //
184 // Returns: B_OK if there were no errors or an error code from
185 // BFile::SetTo() or BMessage::Unflatten() if there were errors
186 // ---------------------------------------------------------------
187 status_t
188 TranslatorSettings::LoadSettings()
189 {
190 	status_t result;
191 
192 	fLock.Lock();
193 
194 	// Don't try to open the settings file if there are
195 	// no settings that need to be loaded
196 	if (fDefCount > 0) {
197 		BFile settingsFile;
198 		result = settingsFile.SetTo(fSettingsPath.Path(), B_READ_ONLY);
199 		if (result == B_OK) {
200 			BMessage msg;
201 			result = msg.Unflatten(&settingsFile);
202 			if (result == B_OK)
203 				result = LoadSettings(&msg);
204 		}
205 	} else
206 		result = B_OK;
207 
208 	fLock.Unlock();
209 
210 	return result;
211 }
212 
213 // ---------------------------------------------------------------
214 // LoadSettings
215 //
216 // Loads the settings from a BMessage passed to the function.
217 //
218 // Preconditions:
219 //
220 // Parameters:	pmsg	pointer to BMessage that contains the
221 //						settings
222 //
223 // Postconditions:
224 //
225 // Returns: B_BAD_VALUE if pmsg is NULL or invalid options
226 // have been found, B_OK if there were no
227 // errors or an error code from BMessage::FindBool() or
228 // BMessage::ReplaceBool() if there were other errors
229 // ---------------------------------------------------------------
230 status_t
231 TranslatorSettings::LoadSettings(BMessage *pmsg)
232 {
233 	status_t result = B_OK;
234 
235 	if (pmsg) {
236 
237 		fLock.Lock();
238 
239 		const TranSetting *defs = fDefaults;
240 		for (int32 i = 0; i < fDefCount; i++) {
241 			bool tempBool;
242 			int32 tempInt32;
243 			status_t ret;
244 			switch (defs[i].dataType) {
245 				case TRAN_SETTING_BOOL:
246 					ret = pmsg->FindBool(defs[i].name, &tempBool);
247 					if (ret < B_OK)
248 						tempBool = static_cast<bool>(defs[i].defaultVal);
249 					fSettingsMsg.ReplaceBool(defs[i].name, tempBool);
250 					break;
251 
252 				case TRAN_SETTING_INT32:
253 					ret = pmsg->FindInt32(defs[i].name, &tempInt32);
254 					if (ret < B_OK)
255 						tempInt32 = defs[i].defaultVal;
256 					fSettingsMsg.ReplaceInt32(defs[i].name, tempInt32);
257 					break;
258 
259 				default:
260 					// ASSERT here? Erase the bogus setting entry instead?
261 					break;
262 			}
263 		}
264 
265 		fLock.Unlock();
266 	}
267 
268 	return result;
269 }
270 
271 // ---------------------------------------------------------------
272 // SaveSettings
273 //
274 // Saves the settings as a flattened BMessage to the default
275 // settings file
276 //
277 // Preconditions:
278 //
279 // Parameters:
280 //
281 // Postconditions:
282 //
283 // Returns: B_OK if no errors or an error code from BFile::SetTo()
284 // or BMessage::Flatten() if there were errors
285 // ---------------------------------------------------------------
286 status_t
287 TranslatorSettings::SaveSettings()
288 {
289 	status_t result;
290 
291 	fLock.Lock();
292 
293 	// Only write out settings file if there are
294 	// actual settings stored by this object
295 	if (fDefCount > 0) {
296 		BFile settingsFile;
297 		result = settingsFile.SetTo(fSettingsPath.Path(),
298 			B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
299 		if (result == B_OK)
300 			result = fSettingsMsg.Flatten(&settingsFile);
301 	} else
302 		result = B_OK;
303 
304 	fLock.Unlock();
305 
306 	return result;
307 }
308 
309 // ---------------------------------------------------------------
310 // GetConfigurationMessage
311 //
312 // Saves the current settings to the BMessage passed to the
313 // function
314 //
315 // Preconditions:
316 //
317 // Parameters:	pmsg	pointer to BMessage where the settings
318 //						will be stored
319 //
320 // Postconditions:
321 //
322 // Returns: B_OK if there were no errors or an error code from
323 // BMessage::RemoveName() or BMessage::AddBool() if there were
324 // errors
325 // ---------------------------------------------------------------
326 status_t
327 TranslatorSettings::GetConfigurationMessage(BMessage *pmsg)
328 {
329 	status_t result = B_BAD_VALUE;
330 
331 	if (pmsg) {
332 		int32 i;
333 		for (i = 0; i < fDefCount; i++) {
334 			result = pmsg->RemoveName(fDefaults[i].name);
335 			if (result != B_OK && result != B_NAME_NOT_FOUND)
336 				break;
337 		}
338 		if (i == fDefCount) {
339 			fLock.Lock();
340 			result = B_OK;
341 
342 			const TranSetting *defs = fDefaults;
343 			for (i = 0; i < fDefCount && result >= B_OK; i++) {
344 				switch (defs[i].dataType) {
345 					case TRAN_SETTING_BOOL:
346 						result = pmsg->AddBool(defs[i].name,
347 							SetGetBool(defs[i].name));
348 						break;
349 
350 					case TRAN_SETTING_INT32:
351 						result = pmsg->AddInt32(defs[i].name,
352 							SetGetInt32(defs[i].name));
353 						break;
354 
355 					default:
356 						// ASSERT here? Erase the bogus setting entry instead?
357 						break;
358 				}
359 			}
360 
361 			fLock.Unlock();
362 		}
363 	}
364 
365 	return result;
366 }
367 
368 // ---------------------------------------------------------------
369 // FindTranSetting
370 //
371 // Returns a pointer to the TranSetting with the given name
372 //
373 //
374 // Preconditions:
375 //
376 // Parameters:	name	name of the TranSetting to find
377 //
378 //
379 // Postconditions:
380 //
381 // Returns: NULL if the TranSetting cannot be found, or a pointer
382 //          to the desired TranSetting if it is found
383 // ---------------------------------------------------------------
384 const TranSetting *
385 TranslatorSettings::FindTranSetting(const char *name)
386 {
387 	for (int32 i = 0; i < fDefCount; i++) {
388 		if (!strcmp(fDefaults[i].name, name))
389 			return fDefaults + i;
390 	}
391 	return NULL;
392 }
393 
394 // ---------------------------------------------------------------
395 // SetGetBool
396 //
397 // Sets the state of the bool setting identified by the given name
398 //
399 //
400 // Preconditions:
401 //
402 // Parameters:	name	identifies the setting to set or get
403 //
404 //				pbool	the new value for the bool, or, if null,
405 //						it indicates that the caller wants to Get
406 //						rather than Set
407 //
408 // Postconditions:
409 //
410 // Returns: the prior value of the setting
411 // ---------------------------------------------------------------
412 bool
413 TranslatorSettings::SetGetBool(const char *name, bool *pbool)
414 {
415 	bool bprevValue;
416 
417 	fLock.Lock();
418 
419 	const TranSetting *def = FindTranSetting(name);
420 	if (def) {
421 		fSettingsMsg.FindBool(def->name, &bprevValue);
422 		if (pbool)
423 			fSettingsMsg.ReplaceBool(def->name, *pbool);
424 	} else
425 		bprevValue = false;
426 
427 	fLock.Unlock();
428 
429 	return bprevValue;
430 }
431 
432 // ---------------------------------------------------------------
433 // SetGetInt32
434 //
435 // Sets the state of the int32 setting identified by the given name
436 //
437 //
438 // Preconditions:
439 //
440 // Parameters:	name	identifies the setting to set or get
441 //
442 //				pint32	the new value for the setting, or, if null,
443 //						it indicates that the caller wants to Get
444 //						rather than Set
445 //
446 // Postconditions:
447 //
448 // Returns: the prior value of the setting
449 // ---------------------------------------------------------------
450 int32
451 TranslatorSettings::SetGetInt32(const char *name, int32 *pint32)
452 {
453 	int32 prevValue;
454 
455 	fLock.Lock();
456 
457 	const TranSetting *def = FindTranSetting(name);
458 	if (def) {
459 		fSettingsMsg.FindInt32(def->name, &prevValue);
460 		if (pint32)
461 			fSettingsMsg.ReplaceInt32(def->name, *pint32);
462 	} else
463 		prevValue = 0;
464 
465 	fLock.Unlock();
466 
467 	return prevValue;
468 }
469 
470