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