/*****************************************************************************/ // TranslatorSettings // Written by Michael Wilber, Haiku Translation Kit Team // // TranslatorSettings.cpp // // This class manages (saves/loads/locks/unlocks) the settings // for a Translator. // // // Copyright (c) 2004 Haiku Project // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. /*****************************************************************************/ #include #include #include #include // for B_TRANSLATOR_EXT_* #include "TranslatorSettings.h" // --------------------------------------------------------------- // Constructor // // Sets the default settings, location for the settings file // and sets the reference count to 1 // // Preconditions: // // Parameters: // // Postconditions: // // Returns: // --------------------------------------------------------------- TranslatorSettings::TranslatorSettings(const char *settingsFile, const TranSetting *defaults, int32 defCount) : fLock("TranslatorSettings Lock") { if (find_directory(B_USER_SETTINGS_DIRECTORY, &fSettingsPath)) fSettingsPath.SetTo("/tmp"); fSettingsPath.Append(settingsFile); fRefCount = 1; if (defCount > 0) { fDefaults = defaults; fDefCount = defCount; } else { fDefaults = NULL; fDefCount = 0; } // Add Default Settings // (Used when loading from the settings file or from // a BMessage fails) const TranSetting *defs = fDefaults; for (int32 i = 0; i < fDefCount; i++) { switch (defs[i].dataType) { case TRAN_SETTING_BOOL: fSettingsMsg.AddBool(defs[i].name, static_cast(defs[i].defaultVal)); break; case TRAN_SETTING_INT32: fSettingsMsg.AddInt32(defs[i].name, defs[i].defaultVal); break; default: // ASSERT here? Erase the bogus setting entry instead? break; } } } // --------------------------------------------------------------- // Acquire // // Returns a pointer to the TranslatorSettings and increments // the reference count. // // Preconditions: // // Parameters: // // Postconditions: // // Returns: pointer to this TranslatorSettings object // --------------------------------------------------------------- TranslatorSettings * TranslatorSettings::Acquire() { TranslatorSettings *psettings = NULL; fLock.Lock(); fRefCount++; psettings = this; fLock.Unlock(); return psettings; } // --------------------------------------------------------------- // Release // // Decrements the reference count and deletes the // TranslatorSettings if the reference count is zero. // // Preconditions: // // Parameters: // // Postconditions: // // Returns: pointer to this TranslatorSettings object if // the reference count is greater than zero, returns NULL // if the reference count is zero and the TranslatorSettings // object has been deleted // --------------------------------------------------------------- TranslatorSettings * TranslatorSettings::Release() { TranslatorSettings *psettings = NULL; fLock.Lock(); fRefCount--; if (fRefCount > 0) { psettings = this; fLock.Unlock(); } else delete this; // delete this object and // release locks return psettings; } // --------------------------------------------------------------- // Destructor // // Does nothing! // // Preconditions: // // Parameters: // // Postconditions: // // Returns: // --------------------------------------------------------------- TranslatorSettings::~TranslatorSettings() { } // --------------------------------------------------------------- // LoadSettings // // Loads the settings by reading them from the default // settings file. // // Preconditions: // // Parameters: // // Postconditions: // // Returns: B_OK if there were no errors or an error code from // BFile::SetTo() or BMessage::Unflatten() if there were errors // --------------------------------------------------------------- status_t TranslatorSettings::LoadSettings() { status_t result; fLock.Lock(); // Don't try to open the settings file if there are // no settings that need to be loaded if (fDefCount > 0) { BFile settingsFile; result = settingsFile.SetTo(fSettingsPath.Path(), B_READ_ONLY); if (result == B_OK) { BMessage msg; result = msg.Unflatten(&settingsFile); if (result == B_OK) result = LoadSettings(&msg); } } else result = B_OK; fLock.Unlock(); return result; } // --------------------------------------------------------------- // LoadSettings // // Loads the settings from a BMessage passed to the function. // // Preconditions: // // Parameters: pmsg pointer to BMessage that contains the // settings // // Postconditions: // // Returns: B_BAD_VALUE if pmsg is NULL or invalid options // have been found, B_OK if there were no // errors or an error code from BMessage::FindBool() or // BMessage::ReplaceBool() if there were other errors // --------------------------------------------------------------- status_t TranslatorSettings::LoadSettings(BMessage *pmsg) { if (pmsg == NULL) return B_BAD_VALUE; fLock.Lock(); const TranSetting *defaults = fDefaults; for (int32 i = 0; i < fDefCount; i++) { switch (defaults[i].dataType) { case TRAN_SETTING_BOOL: { bool value; if (pmsg->FindBool(defaults[i].name, &value) != B_OK) { if (fSettingsMsg.HasBool(defaults[i].name)) break; else value = static_cast(defaults[i].defaultVal); } fSettingsMsg.ReplaceBool(defaults[i].name, value); break; } case TRAN_SETTING_INT32: { int32 value; if (pmsg->FindInt32(defaults[i].name, &value) != B_OK) { if (fSettingsMsg.HasInt32(defaults[i].name)) break; else value = defaults[i].defaultVal; } fSettingsMsg.ReplaceInt32(defaults[i].name, value); break; } default: // TODO: ASSERT here? Erase the bogus setting entry instead? break; } } fLock.Unlock(); return B_OK; } // --------------------------------------------------------------- // SaveSettings // // Saves the settings as a flattened BMessage to the default // settings file // // Preconditions: // // Parameters: // // Postconditions: // // Returns: B_OK if no errors or an error code from BFile::SetTo() // or BMessage::Flatten() if there were errors // --------------------------------------------------------------- status_t TranslatorSettings::SaveSettings() { status_t result; fLock.Lock(); // Only write out settings file if there are // actual settings stored by this object if (fDefCount > 0) { BFile settingsFile; result = settingsFile.SetTo(fSettingsPath.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE); if (result == B_OK) result = fSettingsMsg.Flatten(&settingsFile); } else result = B_OK; fLock.Unlock(); return result; } // --------------------------------------------------------------- // GetConfigurationMessage // // Saves the current settings to the BMessage passed to the // function // // Preconditions: // // Parameters: pmsg pointer to BMessage where the settings // will be stored // // Postconditions: // // Returns: B_OK if there were no errors or an error code from // BMessage::RemoveName() or BMessage::AddBool() if there were // errors // --------------------------------------------------------------- status_t TranslatorSettings::GetConfigurationMessage(BMessage *pmsg) { status_t result = B_BAD_VALUE; if (pmsg) { int32 i; for (i = 0; i < fDefCount; i++) { result = pmsg->RemoveName(fDefaults[i].name); if (result != B_OK && result != B_NAME_NOT_FOUND) break; } if (i == fDefCount) { fLock.Lock(); result = B_OK; const TranSetting *defs = fDefaults; for (i = 0; i < fDefCount && result >= B_OK; i++) { switch (defs[i].dataType) { case TRAN_SETTING_BOOL: result = pmsg->AddBool(defs[i].name, SetGetBool(defs[i].name)); break; case TRAN_SETTING_INT32: result = pmsg->AddInt32(defs[i].name, SetGetInt32(defs[i].name)); break; default: // ASSERT here? Erase the bogus setting entry instead? break; } } fLock.Unlock(); } } return result; } // --------------------------------------------------------------- // FindTranSetting // // Returns a pointer to the TranSetting with the given name // // // Preconditions: // // Parameters: name name of the TranSetting to find // // // Postconditions: // // Returns: NULL if the TranSetting cannot be found, or a pointer // to the desired TranSetting if it is found // --------------------------------------------------------------- const TranSetting * TranslatorSettings::FindTranSetting(const char *name) { for (int32 i = 0; i < fDefCount; i++) { if (!strcmp(fDefaults[i].name, name)) return fDefaults + i; } return NULL; } // --------------------------------------------------------------- // SetGetBool // // Sets the state of the bool setting identified by the given name // // // Preconditions: // // Parameters: name identifies the setting to set or get // // pbool the new value for the bool, or, if null, // it indicates that the caller wants to Get // rather than Set // // Postconditions: // // Returns: the prior value of the setting // --------------------------------------------------------------- bool TranslatorSettings::SetGetBool(const char *name, bool *pbool) { bool bprevValue; fLock.Lock(); const TranSetting *def = FindTranSetting(name); if (def) { fSettingsMsg.FindBool(def->name, &bprevValue); if (pbool) fSettingsMsg.ReplaceBool(def->name, *pbool); } else bprevValue = false; fLock.Unlock(); return bprevValue; } // --------------------------------------------------------------- // SetGetInt32 // // Sets the state of the int32 setting identified by the given name // // // Preconditions: // // Parameters: name identifies the setting to set or get // // pint32 the new value for the setting, or, if null, // it indicates that the caller wants to Get // rather than Set // // Postconditions: // // Returns: the prior value of the setting // --------------------------------------------------------------- int32 TranslatorSettings::SetGetInt32(const char *name, int32 *pint32) { int32 prevValue; fLock.Lock(); const TranSetting *def = FindTranSetting(name); if (def) { fSettingsMsg.FindInt32(def->name, &prevValue); if (pint32) fSettingsMsg.ReplaceInt32(def->name, *pint32); } else prevValue = 0; fLock.Unlock(); return prevValue; }