diff options
author | Oz Linden <oz@lindenlab.com> | 2012-05-23 21:30:13 -0400 |
---|---|---|
committer | Oz Linden <oz@lindenlab.com> | 2012-05-23 21:30:13 -0400 |
commit | 04ab2cf43b5341900737f0d480bce0b8205add8e (patch) | |
tree | d413bed4ad998b779a4b631902d967e2678630bb /indra/newview/llautoreplace.cpp | |
parent | 0d11c70e8e68ea2c33cdf01b56b6f2f81ed46f1e (diff) |
storm-1738: restructure code, preferences storage, preferences ui; ui not completely tested
Diffstat (limited to 'indra/newview/llautoreplace.cpp')
-rw-r--r-- | indra/newview/llautoreplace.cpp | 711 |
1 files changed, 512 insertions, 199 deletions
diff --git a/indra/newview/llautoreplace.cpp b/indra/newview/llautoreplace.cpp index 10005aee9f..0432bf735a 100644 --- a/indra/newview/llautoreplace.cpp +++ b/indra/newview/llautoreplace.cpp @@ -1,4 +1,4 @@ -/** +/** * @file llautoreplace.cpp * @brief Auto Replace Manager * @@ -10,12 +10,12 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -32,10 +32,10 @@ LLAutoReplace* LLAutoReplace::sInstance; +const char* LLAutoReplace::SETTINGS_FILE_NAME = "settings_autoreplace.xml"; + LLAutoReplace::LLAutoReplace() { - sInstance = this; - sInstance->loadFromDisk(); } LLAutoReplace::~LLAutoReplace() @@ -55,29 +55,27 @@ void LLAutoReplace::autoreplaceCallback(LLUIString& inputText, S32& cursorPos) { return; } - - LLWString text = inputText.getWString(); + LLWString text = inputText.getWString(); if(text.size()<1) { return; } - + if(LLWStringUtil::isPartOfWord(text[wordEnd])) { return;//we only check on word breaks } - - wordEnd--; - if(LLWStringUtil::isPartOfWord(text[wordEnd])) + wordEnd--; + if ( LLWStringUtil::isPartOfWord(text[wordEnd]) ) { while ((wordEnd > 0) && (' ' != text[wordEnd-1])) { wordEnd--; } - wordStart=wordEnd; + wordStart=wordEnd; while ((wordEnd < (S32)text.length()) && (' ' != text[wordEnd])) { @@ -86,7 +84,7 @@ void LLAutoReplace::autoreplaceCallback(LLUIString& inputText, S32& cursorPos) std::string strLastWord = std::string(text.begin(), text.end()); std::string lastTypedWord = strLastWord.substr(wordStart, wordEnd-wordStart); - std::string replacedWord(replaceWord(lastTypedWord)); + std::string replacedWord( mSettings.replaceWord(lastTypedWord) ); if(replacedWord != lastTypedWord) { @@ -94,7 +92,6 @@ void LLAutoReplace::autoreplaceCallback(LLUIString& inputText, S32& cursorPos) LLWString strOld = utf8str_to_wstring(lastTypedWord); int nDiff = strNew.size() - strOld.size(); - //int wordStart = regText.find(lastTypedWord); text.replace(wordStart,lastTypedWord.length(),strNew); inputText = wstring_to_utf8str(text); cursorPos+=nDiff; @@ -108,307 +105,623 @@ LLAutoReplace* LLAutoReplace::getInstance() if(!sInstance) { sInstance = new LLAutoReplace(); + sInstance->loadFromSettings(); } return sInstance; } -void LLAutoReplace::save() -{ - saveToDisk(mAutoReplaces); -} - -std::string LLAutoReplace::getFileName() +std::string LLAutoReplace::getUserSettingsFileName() { std::string path=gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""); if (!path.empty()) { - path = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "settings_autoreplace.xml"); + path = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, SETTINGS_FILE_NAME); } - return path; + return path; } -std::string LLAutoReplace::getDefaultFileName() +std::string LLAutoReplace::getAppSettingsFileName() { std::string path=gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""); if (!path.empty()) { - path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "settings_autoreplace.xml"); + path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, SETTINGS_FILE_NAME); } - return path; + else + { + LL_ERRS("AutoReplace") << "Failed to get app settings directory name" << LL_ENDL; + } + return path; } -LLSD LLAutoReplace::exportList(std::string listName) +LLAutoReplaceSettings LLAutoReplace::getSettings() { - LLSD toReturn; - if(mAutoReplaces.has(listName)) - { - toReturn["listName"]=listName; - toReturn["data"]=mAutoReplaces[listName]["data"]; - toReturn["priority"]=mAutoReplaces[listName]["priority"]; - } - return toReturn; + return mSettings; +} + +void LLAutoReplace::setSettings(const LLAutoReplaceSettings& newSettings) +{ + mSettings.set(newSettings); } -BOOL LLAutoReplace::addReplacementList(LLSD newList) +void LLAutoReplace::loadFromSettings() { - if(newList.has("listName")) + std::string filename=getUserSettingsFileName(); + if (filename.empty()) + { + LL_INFOS("AutoReplace") << "no valid user settings directory." << LL_ENDL; + } + if(gDirUtilp->fileExists(filename)) { - std::string name = newList["listName"]; - LLSD newPart; - newPart["data"]=newList["data"]; - newPart["enabled"]=TRUE; - newPart["priority"]=newList["priority"].asInteger(); - llinfos << "adding new list with settings priority "<<newPart["priority"].asInteger() <<llendl; - mAutoReplaces[name]=newPart; + LLSD userSettings; + llifstream file; + file.open(filename.c_str()); + if (file.is_open()) + { + LLSDSerialize::fromXML(userSettings, file); + } + file.close(); + if ( mSettings.setFromLLSD(userSettings) ) + { + LL_INFOS("AutoReplace") << "settings loaded from '" << filename << "'" << LL_ENDL; + } + else + { + LL_WARNS("AutoReplace") << "invalid settings found in '" << filename << "'" << LL_ENDL; + } + } + else // no user settings found, try application settings + { + std::string defaultName = getAppSettingsFileName(); + LL_INFOS("AutoReplace") << " user settings file '" << filename << "' not found;\n" + << " trying '" << defaultName.c_str() << "'" + << LL_ENDL; + + if(gDirUtilp->fileExists(defaultName)) + { + LLSD appDefault; + llifstream file; + file.open(defaultName.c_str()); + if (file.is_open()) + { + LLSDSerialize::fromXMLDocument(appDefault, file); + } + file.close(); - return TRUE; + if ( mSettings.setFromLLSD(appDefault) ) + { + LL_INFOS("AutoReplace") << "settings loaded from '" << filename << "'" << LL_ENDL; + saveToUserSettings(appDefault); + } + else + { + LL_WARNS("AutoReplace") << "invalid settings found in '" << filename << "'" << LL_ENDL; + } + } + else + { + if (mSettings.setFromLLSD(mSettings.getExampleLLSD())) + { + LL_WARNS("AutoReplace") << "no settings found; loaded example." << LL_ENDL; + } + else + { + LL_WARNS("AutoReplace") << "no settings found and example invalid!" << LL_ENDL; + } + } } - return FALSE; } -BOOL LLAutoReplace::removeReplacementList(std::string listName) +void LLAutoReplace::saveToUserSettings(const LLSD& newSettings) { - if(mAutoReplaces.has(listName)) - { - mAutoReplaces.erase(listName); - return TRUE; - } - return FALSE; + std::string filename=getUserSettingsFileName(); + llofstream file; + file.open(filename.c_str()); + LLSDSerialize::toPrettyXML(newSettings, file); + file.close(); + LL_INFOS("AutoReplace") << "settings saved to '" << filename << "'" << LL_ENDL; } -BOOL LLAutoReplace::setListEnabled(std::string listName, BOOL enabled) +// ================================================================ +// LLAutoReplaceSettings +// ================================================================ + +const std::string LLAutoReplaceSettings::AUTOREPLACE_LIST_NAME = "name"; ///< key for looking up list names +const std::string LLAutoReplaceSettings::AUTOREPLACE_LIST_REPLACEMENTS = "replacements"; ///< key for looking up replacement map + +LLAutoReplaceSettings::LLAutoReplaceSettings() { - if(mAutoReplaces.has(listName)) +} + +LLAutoReplaceSettings::LLAutoReplaceSettings(const LLAutoReplaceSettings& settings) +{ + // copy all values through fundamental type intermediates for thread safety + mLists = LLSD::emptyArray(); + + for ( LLSD::array_const_iterator list = settings.mLists.beginArray(), listEnd = settings.mLists.endArray(); + list != listEnd; + list++ + ) { - mAutoReplaces[listName]["enabled"]=enabled; - return TRUE; + LLSD listMap = LLSD::emptyMap(); + std::string listName = (*list)[AUTOREPLACE_LIST_NAME]; + listMap[AUTOREPLACE_LIST_NAME] = listName; + listMap[AUTOREPLACE_LIST_REPLACEMENTS] = LLSD::emptyMap(); + + for ( LLSD::map_const_iterator + entry = (*list)[AUTOREPLACE_LIST_REPLACEMENTS].beginMap(), + entriesEnd = (*list)[AUTOREPLACE_LIST_REPLACEMENTS].endMap(); + entry != entriesEnd; + entry++ + ) + { + std::string keyword = entry->first; + std::string replacement = entry->second.asString(); + listMap[AUTOREPLACE_LIST_REPLACEMENTS].insert(keyword, LLSD(replacement)); + } + + mLists.append(listMap); } - - return FALSE; } -BOOL LLAutoReplace::setListPriority(std::string listName, int priority) +void LLAutoReplaceSettings::set(const LLAutoReplaceSettings& newSettings) { - if(mAutoReplaces.has(listName)) + mLists = newSettings.mLists; +} + +bool LLAutoReplaceSettings::setFromLLSD(const LLSD& settingsFromLLSD) +{ + bool settingsValid = true; + + if ( settingsFromLLSD.isArray() ) { - mAutoReplaces[listName]["priority"]=priority; - return TRUE; + for ( LLSD::array_const_iterator + list = settingsFromLLSD.beginArray(), + listEnd = settingsFromLLSD.endArray(); + settingsValid && list != listEnd; + list++ + ) + { + settingsValid = listIsValid(*list); + } } - return FALSE; + else + { + settingsValid = false; + LL_WARNS("AutoReplace") << "settings are not an array" << LL_ENDL; + } + + if ( settingsValid ) + { + mLists = settingsFromLLSD; + } + else + { + LL_WARNS("AutoReplace") << "invalid settings discarded; using hard coded example" << LL_ENDL; + } + + return settingsValid; } -LLSD LLAutoReplace::getAutoReplaces() +bool LLAutoReplaceSettings::listNameMatches( const LLSD& list, const std::string name ) { - return mAutoReplaces; + return list.isMap() + && list.has(AUTOREPLACE_LIST_NAME) + && list[AUTOREPLACE_LIST_NAME].asString() == name; } -void LLAutoReplace::loadFromDisk() +const LLSD* LLAutoReplaceSettings::getListEntries(std::string listName) { - std::string filename=getFileName(); - if (filename.empty()) + const LLSD* returnedEntries = NULL; + for( LLSD::array_const_iterator list = mLists.beginArray(), endList = mLists.endArray(); + returnedEntries == NULL && list != endList; + list++ + ) + { + const LLSD& thisList = *list; + if ( listNameMatches(thisList, listName) ) + { + returnedEntries = &thisList[AUTOREPLACE_LIST_REPLACEMENTS]; + } + } + return returnedEntries; +} + +std::string LLAutoReplaceSettings::replacementFor(std::string keyword, std::string listName) +{ + std::string replacement; + bool foundList = false; + for( LLSD::array_const_iterator list = mLists.beginArray(), endList = mLists.endArray(); + ! foundList && list != endList; + list++ + ) { - llinfos << "no valid user directory." << llendl; + const LLSD& thisList = *list; + if ( listNameMatches(thisList, listName) ) + { + foundList = true; // whether there is a replacement or not, we're done + if ( thisList.isMap() + && thisList.has(AUTOREPLACE_LIST_REPLACEMENTS) + && thisList[AUTOREPLACE_LIST_REPLACEMENTS].has(keyword) + ) + { + replacement = thisList[AUTOREPLACE_LIST_REPLACEMENTS][keyword].asString(); + LL_DEBUGS("AutoReplace")<<"'"<<keyword<<"' -> '"<<replacement<<"'"<<LL_ENDL; + } + } + if (!foundList) + { + LL_WARNS("AutoReplace")<<"failed to find list '"<<listName<<"'"<<LL_ENDL; + } } - if(!gDirUtilp->fileExists(filename)) + if (replacement.empty()) { - std::string defaultName = getDefaultFileName(); - llinfos << " user settings file doesnt exist, going to try and read default one from "<<defaultName.c_str()<< llendl; + LL_WARNS("AutoReplace")<<"failed to find '"<<keyword<<"'"<<LL_ENDL; + } + return replacement; +} - if(gDirUtilp->fileExists(defaultName)) +LLSD LLAutoReplaceSettings::getListNames() +{ + LLSD toReturn = LLSD::emptyArray(); + for( LLSD::array_const_iterator list = mLists.beginArray(), endList = mLists.endArray(); + list != endList && (*list).isDefined(); // deleting entries leaves undefined items in the iterator + list++ + ) + { + const LLSD& thisList = *list; + if ( thisList.isMap() ) { - LLSD blankllsd; - llifstream file; - file.open(defaultName.c_str()); - if (file.is_open()) + if ( thisList.has(AUTOREPLACE_LIST_NAME) ) { - LLSDSerialize::fromXMLDocument(blankllsd, file); + std::string name = thisList[AUTOREPLACE_LIST_NAME].asString(); + toReturn.append(LLSD(name)); + } + else + { + LL_ERRS("AutoReplace") << " ! MISSING "<<AUTOREPLACE_LIST_NAME<< LL_ENDL; } - file.close(); - saveToDisk(blankllsd); } else { - saveToDisk(getExampleLLSD()); + LL_ERRS("AutoReplace") << " ! not a map: "<<LLSD::typeString(thisList.type())<< LL_ENDL; } } + return toReturn; +} + +bool LLAutoReplaceSettings::listIsValid(const LLSD& list) +{ + bool listValid = true; + if ( ! list.isMap() ) + { + listValid = false; + LL_WARNS("AutoReplace") << "list is not a map" << LL_ENDL; + } + else if ( ! list.has(AUTOREPLACE_LIST_NAME) + || ! list[AUTOREPLACE_LIST_NAME].isString() + || list[AUTOREPLACE_LIST_NAME].asString().empty() + ) + { + listValid = false; + LL_WARNS("AutoReplace") + << "list found without " << AUTOREPLACE_LIST_NAME + << " (or it is empty)" + << LL_ENDL; + } + else if ( ! list.has(AUTOREPLACE_LIST_REPLACEMENTS) || ! list[AUTOREPLACE_LIST_REPLACEMENTS].isMap() ) + { + listValid = false; + LL_WARNS("AutoReplace") << "list '" << list[AUTOREPLACE_LIST_NAME].asString() << "' without " << AUTOREPLACE_LIST_REPLACEMENTS << LL_ENDL; + } else { - llifstream file; - file.open(filename.c_str()); - if (file.is_open()) + for ( LLSD::map_const_iterator + entry = list[AUTOREPLACE_LIST_REPLACEMENTS].beginMap(), + entriesEnd = list[AUTOREPLACE_LIST_REPLACEMENTS].endMap(); + listValid && entry != entriesEnd; + entry++ + ) { - LLSDSerialize::fromXML(mAutoReplaces, file); + if ( ! entry->second.isString() ) + { + listValid = false; + LL_WARNS("AutoReplace") + << "non-string replacement value found in list '" + << list[AUTOREPLACE_LIST_NAME].asString() << "'" + << LL_ENDL; + } } - file.close(); - } + } + + return listValid; } -void LLAutoReplace::saveToDisk(LLSD newSettings) +const LLSD* LLAutoReplaceSettings::exportList(std::string listName) { - mAutoReplaces=newSettings; - std::string filename=getFileName(); - llofstream file; - file.open(filename.c_str()); - LLSDSerialize::toPrettyXML(mAutoReplaces, file); - file.close(); + const LLSD* exportedList = NULL; + for ( LLSD::array_const_iterator list = mLists.beginArray(), listEnd = mLists.endArray(); + exportedList == NULL && list != listEnd; + list++ + ) + { + if ( listNameMatches(*list, listName) ) + { + const LLSD& namedList = (*list); + exportedList = &namedList; + } + } + return exportedList; } -void LLAutoReplace::runTest() +bool LLAutoReplaceSettings::listNameIsUnique(const LLSD& newList) { - std::string startS("He just abandonned all his abilties"); - std::string endS = replaceWords(startS); - llinfos << "!!! Test of autoreplace; start with "<<startS.c_str() << " end with " << endS.c_str()<<llendl; + bool nameIsUnique = true; + // this must always be called with a valid list, so it is safe to assume it has a name + std::string newListName = newList[AUTOREPLACE_LIST_NAME].asString(); + for ( LLSD::array_const_iterator list = mLists.beginArray(), listEnd = mLists.endArray(); + nameIsUnique && list != listEnd; + list++ + ) + { + if ( listNameMatches(*list, newListName) ) + { + LL_WARNS("AutoReplace")<<"duplicate list name '"<<newListName<<"'"<<LL_ENDL; + nameIsUnique = false; + } + } + return nameIsUnique; +} +/* static */ +void LLAutoReplaceSettings::createEmptyList(LLSD& emptyList) +{ + emptyList = LLSD::emptyMap(); + emptyList[AUTOREPLACE_LIST_NAME] = "Empty"; + emptyList[AUTOREPLACE_LIST_REPLACEMENTS] = LLSD::emptyMap(); +} +/* static */ +void LLAutoReplaceSettings::setListName(LLSD& list, const std::string& newName) +{ + list[AUTOREPLACE_LIST_NAME] = newName; } -BOOL LLAutoReplace::saveListToDisk(std::string listName, std::string fileName) +/* static */ +std::string LLAutoReplaceSettings::getListName(LLSD& list) { - if(mAutoReplaces.has(listName)) + std::string name; + if ( list.isMap() && list.has(AUTOREPLACE_LIST_NAME) && list[AUTOREPLACE_LIST_NAME].isString() ) { - llofstream file; - file.open(fileName.c_str()); - LLSDSerialize::toPrettyXML(exportList(listName), file); - file.close(); - return TRUE; + name = list[AUTOREPLACE_LIST_NAME].asString(); } - return FALSE; + return name; } -LLSD LLAutoReplace::getAutoReplaceEntries(std::string listName) +LLAutoReplaceSettings::AddListResult LLAutoReplaceSettings::addList(const LLSD& newList) { - LLSD toReturn; - if(mAutoReplaces.has(listName)) + AddListResult result; + if ( listIsValid( newList ) ) { - toReturn=mAutoReplaces[listName]; + if ( listNameIsUnique( newList ) ) + { + mLists.append(newList); + result = AddListOk; + } + else + { + LL_WARNS("AutoReplace") << "attempt to add duplicate name" << LL_ENDL; + result = AddListDuplicateName; + } } - return toReturn; + else + { + LL_WARNS("AutoReplace") << "attempt to add invalid list" << LL_ENDL; + result = AddListInvalidList; + } + return result; } -std::string LLAutoReplace::replaceWord(std::string currentWord) +bool LLAutoReplaceSettings::removeReplacementList(std::string listName) { - static LLCachedControl<bool> perform_autoreplace(gSavedSettings, "AutoReplace"); - if(!(perform_autoreplace))return currentWord; - //loop through priorities - for(int currentPriority = 10;currentPriority>=0;currentPriority--) + bool found = false; + for( S32 index = 0; !found && mLists[index].isDefined(); index++ ) { - LLSD::map_const_iterator loc_it = mAutoReplaces.beginMap(); - LLSD::map_const_iterator loc_end = mAutoReplaces.endMap(); - for (; loc_it != loc_end; ++loc_it) + if( listNameMatches(mLists.get(index), listName) ) { - const std::string& location = (*loc_it).first; - //llinfos << "location is "<<location.c_str() << " word is "<<currentWord.c_str()<<llendl; - const LLSD& loc_map = (*loc_it).second; - if(loc_map["priority"].asInteger()==currentPriority) - { - if((loc_map["data"].has(currentWord))&&(loc_map["enabled"].asBoolean())) - { - std::string replacement = loc_map["data"][currentWord]; - lldebugs << "found a word in list " << location.c_str() << " and it will replace " << currentWord.c_str() << " => " << replacement.c_str() << llendl; - return replacement; - } - } + LL_DEBUGS("AutoReplace")<<"list '"<<listName<<"'"<<LL_ENDL; + mLists.erase(index); + found = true; } } - return currentWord; + return found; } -std::string LLAutoReplace::replaceWords(std::string words) +/// Move the named list up in the priority order +bool LLAutoReplaceSettings::increaseListPriority(std::string listName) { - static LLCachedControl<bool> perform_autoreplace(gSavedSettings, "AutoReplace"); - if(!(perform_autoreplace)) + LL_DEBUGS("AutoReplace")<<listName<<LL_ENDL; + bool found = false; + S32 search_index; + LLSD targetList; + for ( search_index = 0, targetList = mLists[0]; + !found && targetList.isDefined(); + search_index += 1, targetList = mLists[search_index] + ) { - return words; - } - - boost_tokenizer tokens(words, boost::char_separator<char>(" ")); - for (boost_tokenizer::iterator token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter) - { - std::string currentWord(*token_iter); - LLSD::map_const_iterator loc_it = mAutoReplaces.beginMap(); - LLSD::map_const_iterator loc_end = mAutoReplaces.endMap(); - for (; loc_it != loc_end; ++loc_it) + if ( listNameMatches( targetList, listName) ) { - const std::string& location = (*loc_it).first; - const LLSD& loc_map = (*loc_it).second; - if((loc_map["data"].has(currentWord))&&(loc_map["enabled"].asBoolean())) + LL_DEBUGS("AutoReplace")<<"found at index "<<search_index<<LL_ENDL; + found = true; + if (search_index > 0) + { + // copy the target to before the element preceding it + mLists.insert(search_index-1,targetList); + // delete the original, now duplicate, copy + mLists.erase(search_index+1); + } + else { - std::string replacement = loc_map["data"][currentWord]; - lldebugs << "found a word in list " << location.c_str() << " and it will replace " << currentWord.c_str() << " => " << replacement.c_str() << llendl; - int wordStart = words.find(currentWord); - words.replace(wordStart,currentWord.length(),replacement); - return replaceWords(words);//lol recursion! + LL_WARNS("AutoReplace") << "attempted to move top list up" << LL_ENDL; } - } + } } - return words; + return found; } -BOOL LLAutoReplace::addEntryToList(std::string wrong, std::string right, std::string listName) +/// Move the named list down in the priority order +bool LLAutoReplaceSettings::decreaseListPriority(std::string listName) { - // *HACK: Make sure the "Custom" list exists, because the design of this - // system prevents us from updating it by changing the original file... - if(mAutoReplaces.has(listName)) + LL_DEBUGS("AutoReplace")<<listName<<LL_ENDL; + S32 found_index = -1; + S32 search_index; + for ( search_index = 0; + found_index == -1 && mLists[search_index].isDefined(); + search_index++ + ) { - mAutoReplaces[listName]["data"][wrong]=right; - return TRUE; + if ( listNameMatches( mLists[search_index], listName) ) + { + LL_DEBUGS("AutoReplace")<<"found at index "<<search_index<<LL_ENDL; + found_index = search_index; + } } - else if(listName == "Custom") + if (found_index != -1) { - mAutoReplaces[listName]["data"][wrong] = right; - mAutoReplaces[listName]["enabled"] = 1; - mAutoReplaces[listName]["priority"] = 10; - return TRUE; + // move this list after the found_index from after it to before it + if (mLists[found_index+1].isDefined()) + { + // copy item to after the element that follows it + mLists.insert(found_index+2, mLists[found_index]); + // erase the original, now duplicate, copy + mLists.erase(found_index); + } + else + { + LL_WARNS("AutoReplace") << "attempted to move bottom list down" << LL_ENDL; + } } - - return FALSE; + return (found_index != -1); } -BOOL LLAutoReplace::removeEntryFromList(std::string wrong, std::string listName) + +std::string LLAutoReplaceSettings::replaceWord(const std::string currentWord) { - if(mAutoReplaces.has(listName)) + std::string returnedWord = currentWord; // in case no replacement is found + static LLCachedControl<bool> autoreplace_enabled(gSavedSettings, "AutoReplace"); + if ( autoreplace_enabled ) { - if(mAutoReplaces[listName]["data"].has(wrong)) + //loop through lists in order + bool found = false; + for( LLSD::array_const_iterator list = mLists.beginArray(), endLists = mLists.endArray(); + ! found && list != endLists; + list++ + ) { - mAutoReplaces[listName]["data"].erase(wrong); - return TRUE; + const LLSD& checkList = *list; + const LLSD& replacements = checkList[AUTOREPLACE_LIST_REPLACEMENTS]; + + if ( replacements.has(currentWord) ) + { + found = true; + LL_DEBUGS("AutoReplace") + << "found in list '" << checkList[AUTOREPLACE_LIST_NAME].asString() << "' : '" + << currentWord << "' => '" << replacements[currentWord].asString() << "'" + << LL_ENDL; + returnedWord = replacements[currentWord].asString(); + } } } - return FALSE; + return returnedWord; } -LLSD LLAutoReplace::getExampleLLSD() +bool LLAutoReplaceSettings::addEntryToList(std::string keyword, std::string replacement, std::string listName) { - LLSD toReturn; - - LLSD listone; - LLSD listtwo; - - LLSD itemOne; - itemOne["wrong"]="wrong1"; - itemOne["right"]="right1"; - listone[0]=itemOne; - - LLSD itemTwo; - itemTwo["wrong"]="wrong2"; - itemTwo["right"]="right2"; - listone[1]=itemTwo; - - toReturn["listOne"]=listone; + bool added = false; + if ( ! keyword.empty() && ! replacement.empty() ) + { + bool isOneWord = true; + for (S32 character = 0; isOneWord && character < keyword.size(); character++ ) + { + if ( ! LLWStringUtil::isPartOfWord(keyword[character]) ) + { + LL_WARNS("AutoReplace") << "keyword '" << keyword << "' not a single word" << LL_ENDL; + isOneWord = false; + } + } - itemOne["wrong"]="secondwrong1"; - itemOne["right"]="secondright1"; - listone[0]=itemOne; + if ( isOneWord ) + { + bool listFound = false; + for( LLSD::array_iterator list = mLists.beginArray(), endLists = mLists.endArray(); + ! listFound && list != endLists; + list++ + ) + { + if ( listNameMatches(*list, listName) ) + { + listFound = true; + (*list)[AUTOREPLACE_LIST_REPLACEMENTS][keyword]=replacement; + } + } + if (listFound) + { + added = true; + } + else + { + LL_WARNS("AutoReplace") << "list '" << listName << "' not found" << LL_ENDL; + } + } + } - itemTwo["wrong"]="secondwrong2"; - itemTwo["right"]="secondright2"; - listone[1]=itemTwo; + return added; +} - toReturn["listTwo"]=listone; +bool LLAutoReplaceSettings::removeEntryFromList(std::string keyword, std::string listName) +{ + bool found = false; + for( LLSD::array_iterator list = mLists.beginArray(), endLists = mLists.endArray(); + ! found && list != endLists; + list++ + ) + { + if ( listNameMatches(*list, listName) ) + { + found = true; + (*list)[AUTOREPLACE_LIST_REPLACEMENTS].erase(keyword); + } + } + if (!found) + { + LL_WARNS("AutoReplace") << "list '" << listName << "' not found" << LL_ENDL; + } + return found; +} - return toReturn; +LLSD LLAutoReplaceSettings::getExampleLLSD() +{ + LL_DEBUGS("AutoReplace")<<LL_ENDL; + LLSD example = LLSD::emptyArray(); + + example[0] = LLSD::emptyMap(); + example[0][AUTOREPLACE_LIST_NAME] = "Example List 1"; + example[0][AUTOREPLACE_LIST_REPLACEMENTS] = LLSD::emptyMap(); + example[0][AUTOREPLACE_LIST_REPLACEMENTS]["keyword1"] = "replacement string 1"; + example[0][AUTOREPLACE_LIST_REPLACEMENTS]["keyword2"] = "replacement string 2"; + + example[1] = LLSD::emptyMap(); + example[1][AUTOREPLACE_LIST_NAME] = "Example List 2"; + example[1][AUTOREPLACE_LIST_REPLACEMENTS] = LLSD::emptyMap(); + example[1][AUTOREPLACE_LIST_REPLACEMENTS]["mistake1"] = "correction 1"; + example[1][AUTOREPLACE_LIST_REPLACEMENTS]["mistake2"] = "correction 2"; + + return example; } +LLAutoReplaceSettings::~LLAutoReplaceSettings() +{ +} |