diff options
| -rw-r--r-- | indra/llcommon/llstring.cpp | 98 | ||||
| -rw-r--r-- | indra/llcommon/llstring.h | 7 | ||||
| -rw-r--r-- | indra/llui/lllineeditor.cpp | 28 | ||||
| -rw-r--r-- | indra/llui/lllineeditor.h | 3 | ||||
| -rw-r--r-- | indra/llui/llnotifications.cpp | 1 | ||||
| -rw-r--r-- | indra/llui/llnotifications.h | 1 | ||||
| -rw-r--r-- | indra/newview/lltoastalertpanel.cpp | 3 | 
7 files changed, 138 insertions, 3 deletions
| diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index f40e7ad45f..9a2251e0a7 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -600,6 +600,7 @@ std::string mbcsstring_makeASCII(const std::string& wstr)  	}  	return out_str;  } +  std::string utf8str_removeCRLF(const std::string& utf8str)  {  	if (0 == utf8str.length()) @@ -621,6 +622,43 @@ std::string utf8str_removeCRLF(const std::string& utf8str)  	return out;  } +// Search for any emoji symbol, return true if found +bool wstring_has_emoji(const LLWString& wstr) +{ +    for (const llwchar& wch : wstr) +    { +        if (LLStringOps::isEmoji(wch)) +            return true; +    } + +    return false; +} + +// Cut emoji symbols if exist +bool wstring_remove_emojis(LLWString& wstr) +{ +    bool found = false; +    for (size_t i = 0; i < wstr.size(); ++i) +    { +        if (LLStringOps::isEmoji(wstr[i])) +        { +            wstr.erase(i--, 1); +            found = true; +        } +    } +    return found; +} + +// Cut emoji symbols if exist +bool utf8str_remove_emojis(std::string& utf8str) +{ +    LLWString wstr = utf8str_to_wstring(utf8str); +    if (!wstring_remove_emojis(wstr)) +        return false; +    utf8str = wstring_to_utf8str(wstr); +    return true; +} +  #if LL_WINDOWS  unsigned int ll_wstring_default_code_page()  { @@ -833,6 +871,66 @@ std::string LLStringOps::sDayFormat;  std::string LLStringOps::sAM;  std::string LLStringOps::sPM; +// static +bool LLStringOps::isEmoji(llwchar wch) +{ +    // Most of the following symbols are not actually emoticons, but rather small pictures + +    // 0x1F000 .. 0x1F02F - mahjong tiles +    // https://symbl.cc/en/unicode/table/#mahjong-tiles + +    // 0x1F030 .. 0x1F09F - domino tiles +    // https://symbl.cc/en/unicode/table/#domino-tiles + +    // 0x1F0A0 .. 0x1F0FF - playing cards +    // https://symbl.cc/en/unicode/table/#playing-cards + +    // 0x1F100 .. 0x1F1FF - enclosed alphanumeric supplement +    // https://symbl.cc/en/unicode/table/#enclosed-alphanumeric-supplement + +    // 0x1F200 .. 0x1F2FF - enclosed ideographic supplement +    // https://symbl.cc/en/unicode/table/#enclosed-ideographic-supplement + +    // 0x1F300 .. 0x1F5FF - miscellaneous symbols and pictographs +    // https://symbl.cc/en/unicode/table/#miscellaneous-symbols-and-pictographs + +    // 0x1F600 .. 0x1F64F - emoticons +    // https://symbl.cc/en/unicode/table/#emoticons + +    // 0x1F650 .. 0x1F67F - ornamental dingbats +    // https://symbl.cc/en/unicode/table/#ornamental-dingbats + +    // 0x1F680 .. 0x1F6FF - transport and map symbols +    // https://symbl.cc/en/unicode/table/#transport-and-map-symbols + +    // 0x1F700 .. 0x1F77F - alchemical symbols +    // https://symbl.cc/en/unicode/table/#alchemical-symbols + +    // 0x1F780 .. 0x1F7FF - geometric shapes extended +    // https://symbl.cc/en/unicode/table/#geometric-shapes-extended + +    // 0x1F800 .. 0x1F8FF - supplemental arrows c +    // https://symbl.cc/en/unicode/table/#supplemental-arrows-c + +    // 0x1F900 .. 0x1F9FF - supplemental symbols and pictographs +    // https://symbl.cc/en/unicode/table/#supplemental-symbols-and-pictographs + +    // 0x1FA00 .. 0x1FA6F - chess symbols +    // https://symbl.cc/en/unicode/table/#chess-symbols + +    // 0x1FA70 .. 0x1FAFF - symbols and pictographs extended a +    // https://symbl.cc/en/unicode/table/#symbols-and-pictographs-extended-a + +    // 0x1FB00 .. 0x1FBFF - symbols for legacy computing +    // https://symbl.cc/en/unicode/table/#symbols-for-legacy-computing + +    // 0x1FC00 .. 0x1FFFF - undefined block 44 +    // These symbols aren't defined yet +    // https://symbl.cc/en/unicode/table/#undefined-block-44 + +    return wch >= 0x1F000 && wch < 0x1FC00; +} +  S32	LLStringOps::collate(const llwchar* a, const llwchar* b)  {  diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 1fd6cac14a..6e70a6fa5c 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -189,6 +189,8 @@ public:  	static bool isAlnum(char a) { return isalnum((unsigned char)a) != 0; }  	static bool isAlnum(llwchar a) { return iswalnum(a) != 0; } +	static bool isEmoji(llwchar wch); +  	static S32	collate(const char* a, const char* b) { return strcoll(a, b); }  	static S32	collate(const llwchar* a, const llwchar* b); @@ -737,6 +739,11 @@ LL_COMMON_API std::string mbcsstring_makeASCII(const std::string& str);  LL_COMMON_API std::string utf8str_removeCRLF(const std::string& utf8str); +LL_COMMON_API bool wstring_has_emoji(const LLWString& wstr); + +LL_COMMON_API bool wstring_remove_emojis(LLWString& wstr); + +LL_COMMON_API bool utf8str_remove_emojis(std::string& utf8str);  #if LL_WINDOWS  /* @name Windows string helpers diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 940cf398c0..96fa57b5a6 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -95,6 +95,7 @@ LLLineEditor::Params::Params()  	commit_on_focus_lost("commit_on_focus_lost", true),  	ignore_tab("ignore_tab", true),  	is_password("is_password", false), +	allow_emoji("allow_emoji"),  	cursor_color("cursor_color"),  	use_bg_color("use_bg_color", false),  	bg_color("bg_color"), @@ -141,6 +142,7 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)  	mIgnoreArrowKeys( FALSE ),  	mIgnoreTab( p.ignore_tab ),  	mDrawAsterixes( p.is_password ), +	mAllowEmoji( p.allow_emoji ),  	mSpellCheck( p.spellcheck ),  	mSpellCheckStart(-1),  	mSpellCheckEnd(-1), @@ -413,8 +415,13 @@ void LLLineEditor::setText(const LLStringExplicit &new_text, bool use_size_limit  	all_selected = all_selected || (len == 0 && hasFocus() && mSelectAllonFocusReceived);  	std::string truncated_utf8 = new_text; +	if (!mAllowEmoji) +	{ +		// Cut emoji symbols if exist +        utf8str_remove_emojis(truncated_utf8); +	}  	if (use_size_limit && truncated_utf8.size() > (U32)mMaxLengthBytes) -	{	 +	{  		truncated_utf8 = utf8str_truncate(new_text, mMaxLengthBytes);  	}  	mText.assign(truncated_utf8); @@ -586,13 +593,21 @@ void LLLineEditor::replaceWithSuggestion(U32 index)  	{  		if ( (it->first <= (U32)mCursorPos) && (it->second >= (U32)mCursorPos) )  		{ +			LLWString suggestion = utf8str_to_wstring(mSuggestionList[index]); +			if (!mAllowEmoji) +			{ +				// Cut emoji symbols if exist +				wstring_remove_emojis(suggestion); +			} +			if (suggestion.empty()) +				return; +  			deselect();  			// Delete the misspelled word  			mText.erase(it->first, it->second - it->first);  			// Insert the suggestion in its place -			LLWString suggestion = utf8str_to_wstring(mSuggestionList[index]);  			mText.insert(it->first, suggestion);  			setCursor(it->first + (S32)suggestion.length()); @@ -955,9 +970,11 @@ void LLLineEditor::removeChar()  	}  } -  void LLLineEditor::addChar(const llwchar uni_char)  { +	if (!mAllowEmoji && LLStringOps::isEmoji(uni_char)) +		return; +  	llwchar new_c = uni_char;  	if (hasSelection())  	{ @@ -1257,6 +1274,11 @@ void LLLineEditor::pasteHelper(bool is_primary)  		if (!paste.empty())  		{ +			if (!mAllowEmoji) +			{ +				wstring_remove_emojis(paste); +			} +  			if (!prevalidateInput(paste))  				return; diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index ae4e05c065..8e5735acb4 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -92,6 +92,7 @@ public:  										ignore_tab,  										bg_image_always_focused,  										is_password, +										allow_emoji,  										use_bg_color;  		// colors @@ -238,6 +239,7 @@ public:  	void			setIgnoreArrowKeys(BOOL b)		{ mIgnoreArrowKeys = b; }  	void			setIgnoreTab(BOOL b)			{ mIgnoreTab = b; }  	void			setPassDelete(BOOL b)			{ mPassDelete = b; } +	void			setAllowEmoji(BOOL b)			{ mAllowEmoji = b; }  	void			setDrawAsterixes(BOOL b);  	// get the cursor position of the beginning/end of the prev/next word in the text @@ -396,6 +398,7 @@ protected:  	BOOL 		mShowImageFocused; +	bool		mAllowEmoji;  	bool		mUseBgColor;  	LLWString	mPreeditWString; diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index d736aa6634..464ef576a7 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -88,6 +88,7 @@ LLNotificationForm::FormInput::FormInput()  :	type("type"),  	text("text"),  	max_length_chars("max_length_chars"), +	allow_emoji("allow_emoji"),  	width("width", 0),  	value("value")  {} diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 921398a693..0729c00946 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -201,6 +201,7 @@ public:  		Mandatory<std::string>	type;  		Optional<S32>			width;  		Optional<S32>			max_length_chars; +		Optional<bool>			allow_emoji;  		Optional<std::string>	text;  		Optional<std::string>	value; diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp index f37baa1031..c84f00bdf4 100644 --- a/indra/newview/lltoastalertpanel.cpp +++ b/indra/newview/lltoastalertpanel.cpp @@ -90,6 +90,7 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal  	std::string edit_text_contents;  	S32 edit_text_max_chars = 0;  	bool is_password = false; +	bool allow_emoji = false;  	LLToastPanel::setBackgroundVisible(FALSE);  	LLToastPanel::setBackgroundOpaque(TRUE); @@ -134,6 +135,7 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal  			edit_text_contents = (*it)["value"].asString();  			edit_text_name = (*it)["name"].asString();  			edit_text_max_chars = (*it)["max_length_chars"].asInteger(); +			allow_emoji = (*it)["allow_emoji"].asBoolean();  		}  		else if (type == "password")  		{ @@ -292,6 +294,7 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal  			mLineEditor->reshape(leditor_rect.getWidth(), leditor_rect.getHeight());  			mLineEditor->setRect(leditor_rect);  			mLineEditor->setMaxTextChars(edit_text_max_chars); +			mLineEditor->setAllowEmoji(allow_emoji);  			mLineEditor->setText(edit_text_contents);  			std::string notif_name = mNotification->getName(); | 
