diff options
Diffstat (limited to 'indra')
| -rw-r--r-- | indra/llui/lllineeditor.cpp | 26 | ||||
| -rw-r--r-- | indra/llui/llmenugl.cpp | 4 | ||||
| -rw-r--r-- | indra/llui/llspellcheck.cpp | 152 | ||||
| -rw-r--r-- | indra/llui/llspellcheck.h | 14 | ||||
| -rw-r--r-- | indra/llui/lltextbase.cpp | 14 | ||||
| -rw-r--r-- | indra/llui/lltexteditor.cpp | 4 | ||||
| -rw-r--r-- | indra/newview/llfloaterspellchecksettings.cpp | 73 | ||||
| -rw-r--r-- | indra/newview/llfloaterspellchecksettings.h | 4 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/floater_spellcheck.xml | 35 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/strings.xml | 3 | 
10 files changed, 282 insertions, 47 deletions
| diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 8fc0465acf..48d49af588 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -599,7 +599,9 @@ std::string LLLineEditor::getMisspelledWord(U32 pos) const  	for (std::list<std::pair<U32, U32> >::const_iterator it = mMisspellRanges.begin(); it != mMisspellRanges.end(); ++it)  	{  		if ( (it->first <= pos) && (it->second >= pos) ) +		{  			return wstring_to_utf8str(mText.getWString().substr(it->first, it->second - it->first)); +		}  	}  	return LLStringUtil::null;  } @@ -609,7 +611,9 @@ bool LLLineEditor::isMisspelledWord(U32 pos) const  	for (std::list<std::pair<U32, U32> >::const_iterator it = mMisspellRanges.begin(); it != mMisspellRanges.end(); ++it)  	{  		if ( (it->first <= pos) && (it->second >= pos) ) +		{  			return true; +		}  	}  	return false;  } @@ -1896,7 +1900,9 @@ void LLLineEditor::draw()  			// Find the start of the first word  			U32 word_start = 0, word_end = 0;  			while ( (word_start < text.length()) && (!LLStringOps::isAlpha(text[word_start])) ) +			{  				word_start++; +			}  			// Iterate over all words in the text block and check them one by one  			mMisspellRanges.clear(); @@ -1912,17 +1918,23 @@ void LLLineEditor::draw()  					word_end++;  				}  				if (word_end > text.length()) +				{  					break; +				}  				// Don't process words shorter than 3 characters  				std::string word = wstring_to_utf8str(text.substr(word_start, word_end - word_start));  				if ( (word.length() >= 3) && (!LLSpellChecker::instance().checkSpelling(word)) ) +				{  					mMisspellRanges.push_back(std::pair<U32, U32>(start + word_start, start + word_end)); +				}  				// Find the start of the next word  				word_start = word_end + 1;  				while ( (word_start < text.length()) && (!LLWStringUtil::isPartOfWord(text[word_start])) ) +				{  					word_start++; +				}  			}  			mSpellCheckStart = start; @@ -1934,19 +1946,27 @@ void LLLineEditor::draw()  		{  			// Skip over words that aren't (partially) visible  			if ( ((it->first < start) && (it->second < start)) || (it->first > end) ) +			{  				continue; +			}  			// Skip the current word if the user is still busy editing it  			if ( (!mSpellCheckTimer.hasExpired()) && (it->first <= (U32)mCursorPos) && (it->second >= (U32)mCursorPos) ) +			{   				continue; +			}  			S32 pxWidth = getRect().getWidth();  			S32 pxStart = findPixelNearestPos(it->first - getCursor());  			if (pxStart > pxWidth) +			{  				continue; +			}  			S32 pxEnd = findPixelNearestPos(it->second - getCursor());  			if (pxEnd > pxWidth) +			{  				pxEnd = pxWidth; +			}  			S32 pxBottom = (S32)(text_bottom + mGLFont->getDescenderHeight()); @@ -1955,7 +1975,9 @@ void LLLineEditor::draw()  			{  				gl_line_2d(pxStart, pxBottom, pxStart + 2, pxBottom - 2);  				if (pxStart + 3 < pxEnd) +				{  					gl_line_2d(pxStart + 2, pxBottom - 3, pxStart + 4, pxBottom - 1); +				}  				pxStart += 4;  			}  		} @@ -2582,9 +2604,13 @@ void LLLineEditor::showContextMenu(S32 x, S32 y)  		if (hasSelection())  		{  			if ( (mCursorPos < llmin(mSelectionStart, mSelectionEnd)) || (mCursorPos > llmax(mSelectionStart, mSelectionEnd)) ) +			{  				deselect(); +			}  			else +			{  				setCursor(llmax(mSelectionStart, mSelectionEnd)); +			}  		}  		bool use_spellcheck = getSpellCheck(), is_misspelled = false; diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 3c14bf5415..efb9848a90 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -3909,9 +3909,13 @@ void LLContextMenu::show(S32 x, S32 y, LLView* spawning_view)  	arrange();  	if (spawning_view) +	{  		mSpawningViewHandle = spawning_view->getHandle(); +	}  	else +	{  		mSpawningViewHandle.markDead(); +	}  	LLView::setVisible(TRUE);  } diff --git a/indra/llui/llspellcheck.cpp b/indra/llui/llspellcheck.cpp index 04c8a4fed0..887714d720 100644 --- a/indra/llui/llspellcheck.cpp +++ b/indra/llui/llspellcheck.cpp @@ -41,6 +41,9 @@ static const std::string DICT_DIR = "dictionaries";  static const std::string DICT_CUSTOM_SUFFIX = "_custom";  static const std::string DICT_IGNORE_SUFFIX = "_ignore"; +static const std::string DICT_FILE_MAIN = "dictionaries.xml"; +static const std::string DICT_FILE_USER = "user_dictionaries.xml"; +  LLSD LLSpellChecker::sDictMap;  LLSpellChecker::settings_change_signal_t LLSpellChecker::sSettingsChangeSignal; @@ -75,13 +78,17 @@ S32 LLSpellChecker::getSuggestions(const std::string& word, std::vector<std::str  {  	suggestions.clear();  	if ( (!mHunspell) || (word.length() < 3) ) +	{  		return 0; +	}  	char** suggestion_list; int suggestion_cnt = 0;  	if ( (suggestion_cnt = mHunspell->suggest(&suggestion_list, word.c_str())) != 0 )  	{  		for (int suggestion_index = 0; suggestion_index < suggestion_cnt; suggestion_index++) +		{  			suggestions.push_back(suggestion_list[suggestion_index]); +		}  		mHunspell->free_list(&suggestion_list, suggestion_cnt);	  	}  	return suggestions.size(); @@ -94,17 +101,28 @@ const LLSD LLSpellChecker::getDictionaryData(const std::string& dict_language)  	{  		const LLSD& dict_entry = *it;  		if (dict_language == dict_entry["language"].asString()) +		{  			return dict_entry; +		}  	}  	return LLSD();  }  // static +bool LLSpellChecker::hasDictionary(const std::string& dict_language, bool check_installed) +{ +	const LLSD dict_info = getDictionaryData(dict_language); +	return dict_info.has("language") && ( (!check_installed) || (dict_info["installed"].asBoolean()) ); +} + +// static  void LLSpellChecker::setDictionaryData(const LLSD& dict_info)  {  	const std::string dict_language = dict_info["language"].asString();  	if (dict_language.empty()) +	{  		return; +	}  	for (LLSD::array_iterator it = sDictMap.beginArray(); it != sDictMap.endArray(); ++it)  	{ @@ -126,22 +144,28 @@ void LLSpellChecker::refreshDictionaryMap()  	const std::string user_path = getDictionaryUserPath();  	// Load dictionary information (file name, friendly name, ...) -	llifstream user_file(user_path + "dictionaries.xml", std::ios::binary); +	llifstream user_file(user_path + DICT_FILE_MAIN, std::ios::binary);  	if ( (!user_file.is_open()) || (0 == LLSDSerialize::fromXMLDocument(sDictMap, user_file)) || (0 == sDictMap.size()) )  	{ -		llifstream app_file(app_path + "dictionaries.xml", std::ios::binary); +		llifstream app_file(app_path + DICT_FILE_MAIN, std::ios::binary);  		if ( (!app_file.is_open()) || (0 == LLSDSerialize::fromXMLDocument(sDictMap, app_file)) || (0 == sDictMap.size()) ) +		{  			return; +		}  	}  	// Load user installed dictionary information -	llifstream custom_file(user_path + "user_dictionaries.xml", std::ios::binary); +	llifstream custom_file(user_path + DICT_FILE_USER, std::ios::binary);  	if (custom_file.is_open())  	{  		LLSD custom_dict_map;  		LLSDSerialize::fromXMLDocument(custom_dict_map, custom_file); -		for (LLSD::array_const_iterator it = custom_dict_map.beginArray(); it != custom_dict_map.endArray(); ++it) -			setDictionaryData(*it); +		for (LLSD::array_iterator it = custom_dict_map.beginArray(); it != custom_dict_map.endArray(); ++it) +		{ +			LLSD& dict_info = *it; +			dict_info["user_installed"] = true; +			setDictionaryData(dict_info); +		}  		custom_file.close();  	} @@ -197,7 +221,9 @@ void LLSpellChecker::addToDictFile(const std::string& dict_path, const std::stri  			{  				// Skip over the first line since that's just a line count  				if (0 != line_num) +				{  					word_list.push_back(word); +				}  				line_num++;  			}  		} @@ -215,11 +241,20 @@ void LLSpellChecker::addToDictFile(const std::string& dict_path, const std::stri  	{  		file_out << word_list.size() << std::endl;  		for (std::vector<std::string>::const_iterator itWord = word_list.begin(); itWord != word_list.end(); ++itWord) +		{  			file_out << *itWord << std::endl; +		}  		file_out.close();  	}  } +bool LLSpellChecker::isActiveDictionary(const std::string& dict_language) const +{ +	return +		(mDictLanguage == dict_language) ||  +		(mDictSecondary.end() != std::find(mDictSecondary.begin(), mDictSecondary.end(), dict_language)); +} +  void LLSpellChecker::setSecondaryDictionaries(dict_list_t dict_list)  {  	if (!getUseSpellCheck()) @@ -238,8 +273,8 @@ void LLSpellChecker::setSecondaryDictionaries(dict_list_t dict_list)  	{  		mDictSecondary = dict_list; -		std::string dict_name = mDictName; -		initHunspell(dict_name); +		std::string dict_language = mDictLanguage; +		initHunspell(dict_language);  	}  	else if (end_added != dict_add.begin())		// Add the new secondary dictionaries one by one  	{ @@ -249,31 +284,37 @@ void LLSpellChecker::setSecondaryDictionaries(dict_list_t dict_list)  		{  			const LLSD dict_entry = getDictionaryData(*it_added);  			if ( (!dict_entry.isDefined()) || (!dict_entry["installed"].asBoolean()) ) +			{  				continue; +			}  			const std::string strFileDic = dict_entry["name"].asString() + ".dic";  			if (gDirUtilp->fileExists(user_path + strFileDic)) +			{  				mHunspell->add_dic((user_path + strFileDic).c_str()); +			}  			else if (gDirUtilp->fileExists(app_path + strFileDic)) +			{  				mHunspell->add_dic((app_path + strFileDic).c_str()); +			}  		}  		mDictSecondary = dict_list;  		sSettingsChangeSignal();  	}  } -void LLSpellChecker::initHunspell(const std::string& dict_name) +void LLSpellChecker::initHunspell(const std::string& dict_language)  {  	if (mHunspell)  	{  		delete mHunspell;  		mHunspell = NULL; -		mDictName.clear(); +		mDictLanguage.clear();  		mDictFile.clear();  		mIgnoreList.clear();  	} -	const LLSD dict_entry = (!dict_name.empty()) ? getDictionaryData(dict_name) : LLSD(); +	const LLSD dict_entry = (!dict_language.empty()) ? getDictionaryData(dict_language) : LLSD();  	if ( (!dict_entry.isDefined()) || (!dict_entry["installed"].asBoolean()) || (!dict_entry["is_primary"].asBoolean()))  	{  		sSettingsChangeSignal(); @@ -287,13 +328,19 @@ void LLSpellChecker::initHunspell(const std::string& dict_name)  		const std::string filename_aff = dict_entry["name"].asString() + ".aff";  		const std::string filename_dic = dict_entry["name"].asString() + ".dic";  		if ( (gDirUtilp->fileExists(user_path + filename_aff)) && (gDirUtilp->fileExists(user_path + filename_dic)) ) +		{  			mHunspell = new Hunspell((user_path + filename_aff).c_str(), (user_path + filename_dic).c_str()); +		}  		else if ( (gDirUtilp->fileExists(app_path + filename_aff)) && (gDirUtilp->fileExists(app_path + filename_dic)) ) +		{  			mHunspell = new Hunspell((app_path + filename_aff).c_str(), (app_path + filename_dic).c_str()); +		}  		if (!mHunspell) +		{  			return; +		} -		mDictName = dict_name; +		mDictLanguage = dict_language;  		mDictFile = dict_entry["name"].asString();  		if (dict_entry["has_custom"].asBoolean()) @@ -325,13 +372,19 @@ void LLSpellChecker::initHunspell(const std::string& dict_name)  		{  			const LLSD dict_entry = getDictionaryData(*it);  			if ( (!dict_entry.isDefined()) || (!dict_entry["installed"].asBoolean()) ) +			{  				continue; +			}  			const std::string filename_dic = dict_entry["name"].asString() + ".dic";  			if (gDirUtilp->fileExists(user_path + filename_dic)) +			{  				mHunspell->add_dic((user_path + filename_dic).c_str()); +			}  			else if (gDirUtilp->fileExists(app_path + filename_dic)) +			{  				mHunspell->add_dic((app_path + filename_dic).c_str()); +			}  		}  	} @@ -363,18 +416,85 @@ bool LLSpellChecker::getUseSpellCheck()  }  // static +bool LLSpellChecker::canRemoveDictionary(const std::string& dict_language) +{ +	// Only user-installed inactive dictionaries can be removed +	const LLSD dict_info = getDictionaryData(dict_language); +	return  +		(dict_info["user_installed"].asBoolean()) &&  +		( (!getUseSpellCheck()) || (!LLSpellChecker::instance().isActiveDictionary(dict_language)) ); +} + +// static +void LLSpellChecker::removeDictionary(const std::string& dict_language) +{ +	if (!canRemoveDictionary(dict_language)) +	{ +		return; +	} + +	LLSD dict_map = loadUserDictionaryMap(); +	for (LLSD::array_const_iterator it = dict_map.beginArray(); it != dict_map.endArray(); ++it) +	{ +		const LLSD& dict_info = *it; +		if (dict_info["language"].asString() == dict_language) +		{ +			const std::string dict_dic = getDictionaryUserPath() + dict_info["name"].asString() + ".dic"; +			if (gDirUtilp->fileExists(dict_dic)) +			{ +				LLFile::remove(dict_dic); +			} +			const std::string dict_aff = getDictionaryUserPath() + dict_info["name"].asString() + ".aff"; +			if (gDirUtilp->fileExists(dict_aff)) +			{ +				LLFile::remove(dict_aff); +			} +			dict_map.erase(it - dict_map.beginArray()); +			break; +		} +	} +	saveUserDictionaryMap(dict_map); + +	refreshDictionaryMap(); +} + +// static +LLSD LLSpellChecker::loadUserDictionaryMap() +{ +	LLSD dict_map; +	llifstream dict_file(getDictionaryUserPath() + DICT_FILE_USER, std::ios::binary); +	if (dict_file.is_open()) +	{ +		LLSDSerialize::fromXMLDocument(dict_map, dict_file); +		dict_file.close(); +	} +	return dict_map; +} + +// static +void LLSpellChecker::saveUserDictionaryMap(const LLSD& dict_map) +{ +	llofstream dict_file(getDictionaryUserPath() + DICT_FILE_USER, std::ios::trunc); +	if (dict_file.is_open()) +	{ +		LLSDSerialize::toPrettyXML(dict_map, dict_file); +		dict_file.close(); +	} +} + +// static  boost::signals2::connection LLSpellChecker::setSettingsChangeCallback(const settings_change_signal_t::slot_type& cb)  {  	return sSettingsChangeSignal.connect(cb);  }  // static -void LLSpellChecker::setUseSpellCheck(const std::string& dict_name) +void LLSpellChecker::setUseSpellCheck(const std::string& dict_language)  { -	if ( (((dict_name.empty()) && (getUseSpellCheck())) || (!dict_name.empty())) &&  -		 (LLSpellChecker::instance().mDictName != dict_name) ) +	if ( (((dict_language.empty()) && (getUseSpellCheck())) || (!dict_language.empty())) &&  +		 (LLSpellChecker::instance().mDictLanguage != dict_language) )  	{ -		LLSpellChecker::instance().initHunspell(dict_name); +		LLSpellChecker::instance().initHunspell(dict_language);  	}  } @@ -382,5 +502,7 @@ void LLSpellChecker::setUseSpellCheck(const std::string& dict_name)  void LLSpellChecker::initClass()  {  	if (sDictMap.isUndefined()) +	{  		refreshDictionaryMap(); +	}  } diff --git a/indra/llui/llspellcheck.h b/indra/llui/llspellcheck.h index acb121dd19..4ab80195ea 100644 --- a/indra/llui/llspellcheck.h +++ b/indra/llui/llspellcheck.h @@ -48,24 +48,30 @@ public:  	S32  getSuggestions(const std::string& word, std::vector<std::string>& suggestions) const;  protected:  	void addToDictFile(const std::string& dict_path, const std::string& word); -	void initHunspell(const std::string& dict_name); +	void initHunspell(const std::string& dict_language);  public:  	typedef std::list<std::string> dict_list_t; -	const std::string&	getActiveDictionary() const { return mDictName; } +	const std::string&	getPrimaryDictionary() const { return mDictLanguage; }  	const dict_list_t&	getSecondaryDictionaries() const { return mDictSecondary; } +	bool				isActiveDictionary(const std::string& dict_language) const;  	void				setSecondaryDictionaries(dict_list_t dict_list); +	static bool				 canRemoveDictionary(const std::string& dict_language);  	static const std::string getDictionaryAppPath();  	static const std::string getDictionaryUserPath();  	static const LLSD		 getDictionaryData(const std::string& dict_language);  	static const LLSD&		 getDictionaryMap() { return sDictMap; }  	static bool				 getUseSpellCheck(); +	static bool				 hasDictionary(const std::string& dict_language, bool check_installed = false);  	static void				 refreshDictionaryMap(); -	static void				 setUseSpellCheck(const std::string& dict_name); +	static void				 removeDictionary(const std::string& dict_language); +	static void				 setUseSpellCheck(const std::string& dict_language);  protected: +	static LLSD				 loadUserDictionaryMap();  	static void				 setDictionaryData(const LLSD& dict_info); +	static void				 saveUserDictionaryMap(const LLSD& dict_map);  public:  	typedef boost::signals2::signal<void()> settings_change_signal_t; @@ -75,7 +81,7 @@ protected:  protected:  	Hunspell*	mHunspell; -	std::string	mDictName; +	std::string	mDictLanguage;  	std::string	mDictFile;  	dict_list_t	mDictSecondary;  	std::vector<std::string> mIgnoreList; diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 4db1efdd20..5821cc3593 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -582,7 +582,9 @@ void LLTextBase::drawText()  				// Find the start of the first word  				U32 word_start = seg_start, word_end = -1;  				while ( (word_start < wstrText.length()) && (!LLStringOps::isAlpha(wstrText[word_start])) ) +				{  					word_start++; +				}  				// Iterate over all words in the text block and check them one by one  				while (word_start < seg_end) @@ -597,7 +599,9 @@ void LLTextBase::drawText()  						word_end++;  					}  					if (word_end > seg_end) +					{  						break; +					}  					// Don't process words shorter than 3 characters  					std::string word = wstring_to_utf8str(wstrText.substr(word_start, word_end - word_start)); @@ -609,7 +613,9 @@ void LLTextBase::drawText()  					// Find the start of the next word  					word_start = word_end + 1;  					while ( (word_start < seg_end) && (!LLWStringUtil::isPartOfWord(wstrText[word_start])) ) +					{  						word_start++; +					}  				}  			} @@ -695,12 +701,16 @@ void LLTextBase::drawText()  				{  					gl_line_2d(squiggle_start, squiggle_bottom, squiggle_start + 2, squiggle_bottom - 2);  					if (squiggle_start + 3 < squiggle_end) +					{  						gl_line_2d(squiggle_start + 2, squiggle_bottom - 3, squiggle_start + 4, squiggle_bottom - 1); +					}  					squiggle_start += 4;  				}  				if (misspell_it->second > seg_end) +				{  					break; +				}  				++misspell_it;  			} @@ -1297,7 +1307,9 @@ std::string LLTextBase::getMisspelledWord(U32 pos) const  	for (std::list<std::pair<U32, U32> >::const_iterator it = mMisspellRanges.begin(); it != mMisspellRanges.end(); ++it)  	{  		if ( (it->first <= pos) && (it->second >= pos) ) +		{  			return wstring_to_utf8str(getWText().substr(it->first, it->second - it->first)); +		}  	}  	return LLStringUtil::null;  } @@ -1307,7 +1319,9 @@ bool LLTextBase::isMisspelledWord(U32 pos) const  	for (std::list<std::pair<U32, U32> >::const_iterator it = mMisspellRanges.begin(); it != mMisspellRanges.end(); ++it)  	{  		if ( (it->first <= pos) && (it->second >= pos) ) +		{  			return true; +		}  	}  	return false;  } diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index b860f0b44f..144b6960a1 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -1960,9 +1960,13 @@ void LLTextEditor::showContextMenu(S32 x, S32 y)  	if (hasSelection())  	{  		if ( (mCursorPos < llmin(mSelectionStart, mSelectionEnd)) || (mCursorPos > llmax(mSelectionStart, mSelectionEnd)) ) +		{  			deselect(); +		}  		else +		{  			setCursorPos(llmax(mSelectionStart, mSelectionEnd)); +		}  	}  	bool use_spellcheck = getSpellCheck(), is_misspelled = false; diff --git a/indra/newview/llfloaterspellchecksettings.cpp b/indra/newview/llfloaterspellchecksettings.cpp index 8bf480c4df..059a28fbcd 100644 --- a/indra/newview/llfloaterspellchecksettings.cpp +++ b/indra/newview/llfloaterspellchecksettings.cpp @@ -33,6 +33,7 @@  #include "llscrolllistctrl.h"  #include "llsdserialize.h"  #include "llspellcheck.h" +#include "lltrans.h"  #include "llviewercontrol.h"  #include <boost/algorithm/string.hpp> @@ -45,12 +46,26 @@ LLFloaterSpellCheckerSettings::LLFloaterSpellCheckerSettings(const LLSD& key)  {  } +void LLFloaterSpellCheckerSettings::draw() +{ +	LLFloater::draw(); + +	std::vector<LLScrollListItem*> sel_items = getChild<LLScrollListCtrl>("spellcheck_available_list")->getAllSelected(); +	bool enable_remove = !sel_items.empty(); +	for (std::vector<LLScrollListItem*>::const_iterator sel_it = sel_items.begin(); sel_it != sel_items.end(); ++sel_it) +	{ +		enable_remove &= LLSpellChecker::canRemoveDictionary((*sel_it)->getValue().asString()); +	} +	getChild<LLUICtrl>("spellcheck_remove_btn")->setEnabled(enable_remove); +} +  BOOL LLFloaterSpellCheckerSettings::postBuild(void)  { -	gSavedSettings.getControl("SpellCheck")->getSignal()->connect(boost::bind(&LLFloaterSpellCheckerSettings::refreshDictionaryLists, this, false)); +	gSavedSettings.getControl("SpellCheck")->getSignal()->connect(boost::bind(&LLFloaterSpellCheckerSettings::refreshDictionaries, this, false));  	LLSpellChecker::setSettingsChangeCallback(boost::bind(&LLFloaterSpellCheckerSettings::onSpellCheckSettingsChange, this)); +	getChild<LLUICtrl>("spellcheck_remove_btn")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onBtnRemove, this));  	getChild<LLUICtrl>("spellcheck_import_btn")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onBtnImport, this)); -	getChild<LLUICtrl>("spellcheck_main_combo")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::refreshDictionaryLists, this, false)); +	getChild<LLUICtrl>("spellcheck_main_combo")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::refreshDictionaries, this, false));  	getChild<LLUICtrl>("spellcheck_moveleft_btn")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onBtnMove, this, "spellcheck_active_list", "spellcheck_available_list"));  	getChild<LLUICtrl>("spellcheck_moveright_btn")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onBtnMove, this, "spellcheck_available_list", "spellcheck_active_list"));  	getChild<LLUICtrl>("spellcheck_ok")->setCommitCallback(boost::bind(&LLFloaterSpellCheckerSettings::onBtnOK, this)); @@ -82,6 +97,7 @@ void LLFloaterSpellCheckerSettings::onBtnMove(const std::string& from, const std  	std::vector<LLScrollListItem*> sel_items = from_ctrl->getAllSelected();  	for (std::vector<LLScrollListItem*>::const_iterator sel_it = sel_items.begin(); sel_it != sel_items.end(); ++sel_it)  	{ +		row["value"] = (*sel_it)->getValue();  		row["columns"][0]["value"] = (*sel_it)->getColumn(0)->getValue();  		to_ctrl->addElement(row);  	} @@ -101,7 +117,13 @@ void LLFloaterSpellCheckerSettings::onBtnOK()  		LLScrollListCtrl* list_ctrl = findChild<LLScrollListCtrl>("spellcheck_active_list");  		std::vector<LLScrollListItem*> list_items = list_ctrl->getAllData();  		for (std::vector<LLScrollListItem*>::const_iterator item_it = list_items.begin(); item_it != list_items.end(); ++item_it) -			list_dict.push_back((*item_it)->getColumn(0)->getValue().asString()); +		{ +			const std::string language = (*item_it)->getValue().asString(); +			if (LLSpellChecker::hasDictionary(language, true)) +			{ +				list_dict.push_back(language); +			} +		}  	}  	gSavedSettings.setString("SpellCheckDictionary", boost::join(list_dict, ",")); @@ -110,15 +132,24 @@ void LLFloaterSpellCheckerSettings::onBtnOK()  void LLFloaterSpellCheckerSettings::onOpen(const LLSD& key)  { -	refreshDictionaryLists(true); +	refreshDictionaries(true); +} + +void LLFloaterSpellCheckerSettings::onBtnRemove() +{ +	std::vector<LLScrollListItem*> sel_items = getChild<LLScrollListCtrl>("spellcheck_available_list")->getAllSelected(); +	for (std::vector<LLScrollListItem*>::const_iterator sel_it = sel_items.begin(); sel_it != sel_items.end(); ++sel_it) +	{ +		LLSpellChecker::instance().removeDictionary((*sel_it)->getValue().asString()); +	}  }  void LLFloaterSpellCheckerSettings::onSpellCheckSettingsChange()  { -	refreshDictionaryLists(true); +	refreshDictionaries(true);  } -void LLFloaterSpellCheckerSettings::refreshDictionaryLists(bool from_settings) +void LLFloaterSpellCheckerSettings::refreshDictionaries(bool from_settings)  {  	bool enabled = gSavedSettings.getBOOL("SpellCheck");  	getChild<LLUICtrl>("spellcheck_moveleft_btn")->setEnabled(enabled); @@ -128,7 +159,9 @@ void LLFloaterSpellCheckerSettings::refreshDictionaryLists(bool from_settings)  	LLComboBox* dict_combo = findChild<LLComboBox>("spellcheck_main_combo");  	std::string dict_cur = dict_combo->getSelectedItemLabel();  	if ((dict_cur.empty() || from_settings) && (LLSpellChecker::getUseSpellCheck())) -		dict_cur = LLSpellChecker::instance().getActiveDictionary(); +	{ +		dict_cur = LLSpellChecker::instance().getPrimaryDictionary(); +	}  	dict_combo->clearRows();  	dict_combo->setEnabled(enabled); @@ -139,10 +172,14 @@ void LLFloaterSpellCheckerSettings::refreshDictionaryLists(bool from_settings)  		{  			const LLSD& dict = *dict_it;  			if ( (dict["installed"].asBoolean()) && (dict["is_primary"].asBoolean()) && (dict.has("language")) ) +			{  				dict_combo->add(dict["language"].asString()); +			}  		}  		if (!dict_combo->selectByValue(dict_cur)) +		{  			dict_combo->clear(); +		}  	}  	// Populate the available and active dictionary list @@ -153,16 +190,20 @@ void LLFloaterSpellCheckerSettings::refreshDictionaryLists(bool from_settings)  	if ( ((!avail_ctrl->getItemCount()) && (!active_ctrl->getItemCount())) || (from_settings) )  	{  		if (LLSpellChecker::getUseSpellCheck()) +		{  			active_list = LLSpellChecker::instance().getSecondaryDictionaries(); +		}  	}  	else  	{  		std::vector<LLScrollListItem*> active_items = active_ctrl->getAllData();  		for (std::vector<LLScrollListItem*>::const_iterator item_it = active_items.begin(); item_it != active_items.end(); ++item_it)  		{ -			std::string dict = (*item_it)->getColumn(0)->getValue().asString(); +			std::string dict = (*item_it)->getValue().asString();  			if (dict_cur != dict) +			{  				active_list.push_back(dict); +			}  		}  	} @@ -173,27 +214,31 @@ void LLFloaterSpellCheckerSettings::refreshDictionaryLists(bool from_settings)  	active_ctrl->clearRows();  	active_ctrl->setEnabled(enabled); -	active_ctrl->sortByColumnIndex(0, true);  	for (LLSpellChecker::dict_list_t::const_iterator it = active_list.begin(); it != active_list.end(); ++it)  	{ -		row["columns"][0]["value"] = *it; +		const std::string language = *it; +		const LLSD dict = LLSpellChecker::getDictionaryData(language); +		row["value"] = language; +		row["columns"][0]["value"] = (!dict["user_installed"].asBoolean()) ? language : language + " " + LLTrans::getString("UserDictionary");  		active_ctrl->addElement(row);  	} +	active_ctrl->sortByColumnIndex(0, true);  	active_list.push_back(dict_cur);  	avail_ctrl->clearRows();  	avail_ctrl->setEnabled(enabled); -	avail_ctrl->sortByColumnIndex(0, true);  	for (LLSD::array_const_iterator dict_it = dict_map.beginArray(); dict_it != dict_map.endArray(); ++dict_it)  	{  		const LLSD& dict = *dict_it; -		if ( (dict["installed"].asBoolean()) && (dict.has("language")) &&  -			 (active_list.end() == std::find(active_list.begin(), active_list.end(), dict["language"].asString())) ) +		const std::string language = dict["language"].asString(); +		if ( (dict["installed"].asBoolean()) && (active_list.end() == std::find(active_list.begin(), active_list.end(), language)) )  		{ -			row["columns"][0]["value"] = dict["language"].asString(); +			row["value"] = language; +			row["columns"][0]["value"] = (!dict["user_installed"].asBoolean()) ? language : language + " " + LLTrans::getString("UserDictionary");  			avail_ctrl->addElement(row);  		}  	} +	avail_ctrl->sortByColumnIndex(0, true);  }  ///---------------------------------------------------------------------------- diff --git a/indra/newview/llfloaterspellchecksettings.h b/indra/newview/llfloaterspellchecksettings.h index 3a4428d4c3..c1c998915f 100644 --- a/indra/newview/llfloaterspellchecksettings.h +++ b/indra/newview/llfloaterspellchecksettings.h @@ -34,6 +34,7 @@ class LLFloaterSpellCheckerSettings : public LLFloater  public:  	LLFloaterSpellCheckerSettings(const LLSD& key); +	/*virtual*/ void draw();  	/*virtual*/ BOOL postBuild();  	/*virtual*/ void onOpen(const LLSD& key); @@ -42,8 +43,9 @@ protected:  	void onBtnImport();  	void onBtnMove(const std::string& from, const std::string& to);  	void onBtnOK(); +	void onBtnRemove();  	void onSpellCheckSettingsChange(); -	void refreshDictionaryLists(bool from_settings); +	void refreshDictionaries(bool from_settings);  };  class LLFloaterSpellCheckerImport : public LLFloater diff --git a/indra/newview/skins/default/xui/en/floater_spellcheck.xml b/indra/newview/skins/default/xui/en/floater_spellcheck.xml index 91639ed0da..786b830ad9 100644 --- a/indra/newview/skins/default/xui/en/floater_spellcheck.xml +++ b/indra/newview/skins/default/xui/en/floater_spellcheck.xml @@ -3,10 +3,10 @@   border="true"   can_close="true"   can_minimize="true" - bottom="275" + bottom="300"   left="300"   can_resize="false" - height="330" + height="355"   width="490"   name="spellcheck_floater"   title="Spell Checker Settings"> @@ -53,16 +53,6 @@     top_pad="-15"     width="175"    /> -  <button -   follows="left|top" -   height="23" -   label="Import" -   label_selected="Import" -   layout="topleft" -   left_pad="5" -   name="spellcheck_import_btn" -   top_delta="0" -   width="75" />    <text     enabled_control="SpellCheck"     follows="top|left" @@ -148,6 +138,25 @@     top_pad="-105"     width="175"    /> +  <button +   enabled="false" +   follows="left|top" +   height="23" +   label="Remove" +   layout="topleft" +   left="55" +   name="spellcheck_remove_btn" +   top_pad="5" +   width="80" /> +  <button +   follows="left|top" +   height="23" +   label="Import..." +   layout="topleft" +   left_pad="15" +   name="spellcheck_import_btn" +   top_delta="0" +   width="80" />    <view_border     top_pad="10"     left="2" @@ -159,7 +168,7 @@     mouse_opaque="false"     name="divisor4"/>    <button -   top_pad="10" +   top_pad="8"     right="380"     height="22"     width="90" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 4b58df595f..79c9f855e8 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -3758,4 +3758,7 @@ Try enclosing path to the editor with double quotes.    <string name="snapshot_quality_high">High</string>    <string name="snapshot_quality_very_high">Very High</string> +  <!-- Spell check settings floater --> +  <string name="UserDictionary">[User]</string> +      </strings> | 
