diff options
| author | Erik Kundiman <erik@megapahit.org> | 2024-01-29 17:42:38 +0800 | 
|---|---|---|
| committer | Erik Kundiman <erik@megapahit.org> | 2024-01-30 12:06:48 +0800 | 
| commit | aaa8cb5a37a720ff67792d0a31fec793b03b3742 (patch) | |
| tree | 734ce89b2f133f1fd55cd04e5e79eb5c1ed06d50 | |
| parent | 4c97df0ab1b450d5680975e18e894b6676a589ee (diff) | |
First attempt to fix unicode input
It should work well enough with most, but on Japanese (I assume all CJK),
for now the composition part is still left printed out along with the result
(as opposed to just replaced by the result). It's to be fixed next.
| -rw-r--r-- | indra/llui/llfocusmgr.cpp | 6 | ||||
| -rw-r--r-- | indra/llui/llfocusmgr.h | 1 | ||||
| -rw-r--r-- | indra/llui/lllineeditor.cpp | 45 | ||||
| -rw-r--r-- | indra/llui/lllineeditor.h | 2 | ||||
| -rw-r--r-- | indra/llui/lltexteditor.cpp | 102 | ||||
| -rw-r--r-- | indra/llui/lltexteditor.h | 4 | ||||
| -rw-r--r-- | indra/llui/llview.cpp | 19 | ||||
| -rw-r--r-- | indra/llui/llview.h | 2 | ||||
| -rw-r--r-- | indra/llwindow/llwindowcallbacks.cpp | 4 | ||||
| -rw-r--r-- | indra/llwindow/llwindowcallbacks.h | 1 | ||||
| -rw-r--r-- | indra/llwindow/llwindowsdl.cpp | 8 | ||||
| -rw-r--r-- | indra/newview/llviewerwindow.cpp | 8 | ||||
| -rw-r--r-- | indra/newview/llviewerwindow.h | 1 | 
13 files changed, 200 insertions, 3 deletions
| diff --git a/indra/llui/llfocusmgr.cpp b/indra/llui/llfocusmgr.cpp index 7b0a6cbdae..856e03b3ab 100644 --- a/indra/llui/llfocusmgr.cpp +++ b/indra/llui/llfocusmgr.cpp @@ -58,6 +58,12 @@ BOOL LLFocusableElement::handleUnicodeChar(llwchar uni_char, BOOL called_from_pa  	return FALSE;  } +// virtual +BOOL LLFocusableElement::handleUnicodeString(char *uni_str, BOOL called_from_parent) +{ +	return FALSE; +} +  // virtual   bool LLFocusableElement::wantsKeyUpKeyDown() const  { diff --git a/indra/llui/llfocusmgr.h b/indra/llui/llfocusmgr.h index 0e3d7d8e59..f26690f4cb 100644 --- a/indra/llui/llfocusmgr.h +++ b/indra/llui/llfocusmgr.h @@ -59,6 +59,7 @@ public:  	virtual BOOL	handleKey(KEY key, MASK mask, BOOL called_from_parent);  	virtual BOOL	handleKeyUp(KEY key, MASK mask, BOOL called_from_parent);  	virtual BOOL	handleUnicodeChar(llwchar uni_char, BOOL called_from_parent); +	virtual BOOL	handleUnicodeString(char *uni_str, BOOL called_from_parent);      /**       * If true this LLFocusableElement wants to receive KEYUP and KEYDOWN messages  diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 60dbfd68c6..34d08b99de 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -1009,6 +1009,21 @@ void LLLineEditor::addChar(const llwchar uni_char)  	getWindow()->hideCursorUntilMouseMove();  } +void LLLineEditor::addString(char *s) +{ +	if (hasSelection()) +		deleteSelection(); +	else if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode()) { +		if (!prevalidateInput(mText.getWString() +					.substr(getCursor(), 1))) +			return; +		mText.erase(getCursor(), 1); +	} +	mText.insert(getCursor(), utf8str_to_wstring(s)); +	setCursor(getCursor() + 1); +	getWindow()->hideCursorUntilMouseMove(); +} +  // Extends the selection box to the new cursor position  void LLLineEditor::extendSelection( S32 new_cursor_pos )  { @@ -1650,6 +1665,36 @@ BOOL LLLineEditor::handleUnicodeCharHere(llwchar uni_char)  	return handled;  } +BOOL LLLineEditor::handleUnicodeStringHere(char *uni_str) +{ +	auto handled = FALSE; + +	if ((gFocusMgr.getKeyboardFocus() == this) +			&& getVisible() && !mReadOnly) { +		handled = TRUE; +		LLLineEditorRollback rollback(this); + +		addString(uni_str); + +		mKeystrokeTimer.reset(); +		deselect(); +		auto need_to_rollback = FALSE; +		need_to_rollback |= (mPrevalidateFunc +				&& !mPrevalidateFunc(mText.getWString())); + +		if (need_to_rollback) { +			rollback.doRollback(this); +			LLUI::getInstance()->reportBadKeystroke(); +		} + +		if (!need_to_rollback && handled) { +			onKeystroke(); +			mSpellCheckTimer.setTimerExpirySec(SPELLCHECK_DELAY); +		} +	} + +	return handled; +}  BOOL LLLineEditor::canDoDelete() const  { diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index f983828d2b..a8c6ee4536 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -130,6 +130,7 @@ public:  	/*virtual*/ BOOL	handleRightMouseDown(S32 x, S32 y, MASK mask);  	/*virtual*/ BOOL	handleKeyHere(KEY key, MASK mask );  	/*virtual*/ BOOL	handleUnicodeCharHere(llwchar uni_char); +	/*virtual*/ BOOL	handleUnicodeStringHere(char *uni_str);  	/*virtual*/ void	onMouseCaptureLost();  	// LLEditMenuHandler overrides @@ -296,6 +297,7 @@ public:  	void			removeChar();  	void			addChar(const llwchar c); +	void			addString(char *s);  	void			setCursorAtLocalPos(S32 local_mouse_x);  	S32				findPixelNearestPos(S32 cursor_offset = 0) const;  	S32				calcCursorPos(S32 mouse_x); diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 3d2a426913..299af0dec8 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -166,6 +166,50 @@ private:  };  /////////////////////////////////////////////////////////////////// +class LLTextEditor::TextCmdAddString : public LLTextBase::TextCmd +{ +public: +	TextCmdAddString(S32 pos, BOOL group_with_next, char *str, +			LLTextSegmentPtr segment) : +		TextCmd(pos, group_with_next, segment), +		mWString(utf8str_to_wstring(str)), +		mBlockExtensions(FALSE) +	{ +	} +	virtual void blockExtensions() +	{ +		mBlockExtensions = TRUE; +	} +	virtual BOOL canExtend(S32 pos) const +	{ +		if (!mSegments.empty()) return FALSE; + +		return !mBlockExtensions +			&& (pos == getPosition() + (S32)mWString.length()); +	} +	virtual BOOL execute(LLTextBase* editor, S32* delta) +	{ +		*delta = insert(editor, getPosition(), mWString); +		LLWStringUtil::truncate(mWString, *delta); +		return (*delta != 0); +	} +	virtual S32 undo(LLTextBase* editor) +	{ +		remove(editor, getPosition(), mWString.length()); +		return getPosition(); +	} +	virtual S32 redo(LLTextBase* editor) +	{ +		insert(editor, getPosition(), mWString); +		return getPosition() + mWString.length(); +	} + +private: +	LLWString	mWString; +	BOOL		mBlockExtensions; +}; + +///////////////////////////////////////////////////////////////////  class LLTextEditor::TextCmdOverwriteChar : public LLTextBase::TextCmd  { @@ -1111,6 +1155,18 @@ S32 LLTextEditor::addChar(S32 pos, llwchar wc)  	}  } +S32 LLTextEditor::addString(S32 pos, char *str) +{ +	if ((wstring_utf8_length(getWText()) + strlen(str)) +			> mMaxTextByteLength) { +		make_ui_sound("UISndBadKeystroke"); +		return 0; +	} + +	return execute(new TextCmdAddString(pos, FALSE, str, +				LLTextSegmentPtr())); +} +  void LLTextEditor::addChar(llwchar wc)  {  	if( !getEnabled() ) @@ -1146,6 +1202,34 @@ void LLTextEditor::addChar(llwchar wc)  	}  } +void LLTextEditor::addString(char *str) +{ +	if (!getEnabled()) +		return; +	if (hasSelection()) +		deleteSelection(TRUE); +	else if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode()) +		removeChar(mCursorPos); + +	setCursorPos(mCursorPos + addString(mCursorPos, str)); + +	if (!mReadOnly && mAutoreplaceCallback != NULL) { +		S32 replacement_start; +		S32 replacement_length; +		LLWString replacement_string; +		S32 new_cursor_pos = mCursorPos; +		mAutoreplaceCallback(replacement_start, replacement_length, +				replacement_string, new_cursor_pos, getWText()); + +		if (replacement_length > 0 || !replacement_string.empty()) { +			remove(replacement_start, replacement_length, true); +			insert(replacement_start, replacement_string, false, +					LLTextSegmentPtr()); +			setCursorPos(new_cursor_pos); +		} +	} +} +  void LLTextEditor::addLineBreakChar(BOOL group_together)  {  	if( !getEnabled() ) @@ -1864,6 +1948,24 @@ BOOL LLTextEditor::handleUnicodeCharHere(llwchar uni_char)  	return handled;  } +BOOL LLTextEditor::handleUnicodeStringHere(char *uni_str) +{ +	auto handled = FALSE; + +	if (!mReadOnly) { +		addString(uni_str); +		getWindow()->hideCursorUntilMouseMove(); +		handled = TRUE; +	} + +	if (handled) { +		resetCursorBlink(); +		deselect(); +		onKeyStroke(); +	} + +	return handled; +}  // virtual  BOOL LLTextEditor::canDoDelete() const diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index f3939248c2..513781e365 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -101,6 +101,7 @@ public:  	virtual BOOL	handleKeyHere(KEY key, MASK mask );  	virtual BOOL	handleUnicodeCharHere(llwchar uni_char); +	virtual BOOL	handleUnicodeStringHere(char *uni_str);  	virtual void	onMouseCaptureLost(); @@ -241,6 +242,8 @@ protected:  	// Undoable operations  	void			addChar(llwchar c); // at mCursorPos  	S32				addChar(S32 pos, llwchar wc); +	void			addString(char *s); +	S32				addString(S32 pos, char *str);  	void			addLineBreakChar(BOOL group_together = FALSE);  	S32				overwriteChar(S32 pos, llwchar wc);  	void			removeChar(); @@ -301,6 +304,7 @@ private:  	// Concrete TextCmd sub-classes used by the LLTextEditor base class  	class TextCmdInsert;  	class TextCmdAddChar; +	class TextCmdAddString;  	class TextCmdOverwriteChar;  	class TextCmdRemove; diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index da7868d804..6547a99a32 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -1043,12 +1043,31 @@ BOOL LLView::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent)  	return handled;  } +BOOL LLView::handleUnicodeString(char *uni_str, BOOL called_from_parent) +{ +	auto handled = FALSE; + +	if (getVisible() && getEnabled() && !handled) { +		handled = handleUnicodeStringHere(uni_str); +		if (handled && LLView::sDebugKeys) +			LL_INFOS() << "Unicode key handled by " << getName() << LL_ENDL; +	} + +	if (!handled && !called_from_parent && mParentView) +		handled = mParentView->handleUnicodeString(uni_str, FALSE); + +	return handled; +}  BOOL LLView::handleUnicodeCharHere(llwchar uni_char )  {  	return FALSE;  } +BOOL LLView::handleUnicodeStringHere(char *uni_str) +{ +	return FALSE; +}  BOOL LLView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,  							   EDragAndDropType cargo_type, void* cargo_data, diff --git a/indra/llui/llview.h b/indra/llui/llview.h index 7360fd0fb9..4e101adecb 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -382,6 +382,7 @@ public:  	/* virtual */ BOOL	handleKey(KEY key, MASK mask, BOOL called_from_parent);  	/* virtual */ BOOL	handleKeyUp(KEY key, MASK mask, BOOL called_from_parent);  	/* virtual */ BOOL	handleUnicodeChar(llwchar uni_char, BOOL called_from_parent); +	/* virtual */ BOOL	handleUnicodeString(char *uni_str, BOOL called_from_parent);  	virtual BOOL	handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,  									  EDragAndDropType cargo_type, @@ -515,6 +516,7 @@ public:  	virtual BOOL	handleKeyHere(KEY key, MASK mask);  	virtual BOOL	handleKeyUpHere(KEY key, MASK mask);  	virtual BOOL	handleUnicodeCharHere(llwchar uni_char); +	virtual BOOL	handleUnicodeStringHere(char *uni_str);  	virtual void	handleReshape(const LLRect& rect, bool by_user);  	virtual void	dirtyRect(); diff --git a/indra/llwindow/llwindowcallbacks.cpp b/indra/llwindow/llwindowcallbacks.cpp index be61e1e16c..343ec5f9f7 100644 --- a/indra/llwindow/llwindowcallbacks.cpp +++ b/indra/llwindow/llwindowcallbacks.cpp @@ -52,6 +52,10 @@ BOOL LLWindowCallbacks::handleUnicodeChar(llwchar uni_char, MASK mask)  	return FALSE;  } +BOOL LLWindowCallbacks::handleUnicodeString(char *uni_str) +{ +	return FALSE; +}  BOOL LLWindowCallbacks::handleMouseDown(LLWindow *window, const LLCoordGL pos, MASK mask)  { diff --git a/indra/llwindow/llwindowcallbacks.h b/indra/llwindow/llwindowcallbacks.h index 3b18648138..2a9fcf402a 100644 --- a/indra/llwindow/llwindowcallbacks.h +++ b/indra/llwindow/llwindowcallbacks.h @@ -37,6 +37,7 @@ public:  	virtual BOOL handleTranslatedKeyUp(KEY key,  MASK mask);  	virtual void handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level);  	virtual BOOL handleUnicodeChar(llwchar uni_char, MASK mask); +	virtual BOOL handleUnicodeString(char *uni_str);  	virtual BOOL handleMouseDown(LLWindow *window,  LLCoordGL pos, MASK mask);  	virtual BOOL handleMouseUp(LLWindow *window,  LLCoordGL pos, MASK mask); diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp index 106109ceff..bbc966fb25 100644 --- a/indra/llwindow/llwindowsdl.cpp +++ b/indra/llwindow/llwindowsdl.cpp @@ -1893,9 +1893,11 @@ void LLWindowSDL::gatherInput()                  break;              case SDL_TEXTINPUT: -		    mKeyVirtualKey = *event.text.text; -		    handleUnicodeUTF16(mKeyVirtualKey, -				    gKeyboard->currentMask(FALSE)); +		    mCallbacks->handleUnicodeString(event.text.text); +                break; + +            case SDL_TEXTEDITING: +		    mCallbacks->handleUnicodeString(event.edit.text);                  break;              case SDL_KEYUP: diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index ed671fe849..405da33bdf 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -3129,6 +3129,14 @@ BOOL LLViewerWindow::handleUnicodeChar(llwchar uni_char, MASK mask)  	return FALSE;  } +BOOL LLViewerWindow::handleUnicodeString(char *uni_str) +{ +	auto keyboard_focus = gFocusMgr.getKeyboardFocus(); +	if (keyboard_focus) +		keyboard_focus->handleUnicodeString(uni_str, FALSE); + +	return TRUE; +}  void LLViewerWindow::handleScrollWheel(S32 clicks)  { diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index ccef006a07..fe20b5fa23 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -192,6 +192,7 @@ public:  	/*virtual*/ BOOL handleTranslatedKeyUp(KEY key,  MASK mask);  	/*virtual*/ void handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level);  	/*virtual*/ BOOL handleUnicodeChar(llwchar uni_char, MASK mask);	// NOT going to handle extended  +	/*virtual*/ BOOL handleUnicodeString(char *uni_str);  	/*virtual*/ BOOL handleMouseDown(LLWindow *window,  LLCoordGL pos, MASK mask);  	/*virtual*/ BOOL handleMouseUp(LLWindow *window,  LLCoordGL pos, MASK mask);  	/*virtual*/ BOOL handleCloseRequest(LLWindow *window); | 
