summaryrefslogtreecommitdiff
path: root/indra/llui/lltexteditor.cpp
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/lltexteditor.cpp
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/lltexteditor.cpp')
-rw-r--r--indra/llui/lltexteditor.cpp102
1 files changed, 102 insertions, 0 deletions
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