summaryrefslogtreecommitdiff
path: root/indra/llui
diff options
context:
space:
mode:
authorErik Kundiman <erik@megapahit.org>2024-01-29 17:42:38 +0800
committerErik Kundiman <erik@megapahit.org>2024-01-30 12:06:48 +0800
commitaaa8cb5a37a720ff67792d0a31fec793b03b3742 (patch)
tree734ce89b2f133f1fd55cd04e5e79eb5c1ed06d50 /indra/llui
parent4c97df0ab1b450d5680975e18e894b6676a589ee (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.
Diffstat (limited to 'indra/llui')
-rw-r--r--indra/llui/llfocusmgr.cpp6
-rw-r--r--indra/llui/llfocusmgr.h1
-rw-r--r--indra/llui/lllineeditor.cpp45
-rw-r--r--indra/llui/lllineeditor.h2
-rw-r--r--indra/llui/lltexteditor.cpp102
-rw-r--r--indra/llui/lltexteditor.h4
-rw-r--r--indra/llui/llview.cpp19
-rw-r--r--indra/llui/llview.h2
8 files changed, 181 insertions, 0 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();