diff --git a/lib/irrlicht/source/Irrlicht/CIrrDeviceAndroid.cpp b/lib/irrlicht/source/Irrlicht/CIrrDeviceAndroid.cpp index 05c51659d..ceac173ef 100644 --- a/lib/irrlicht/source/Irrlicht/CIrrDeviceAndroid.cpp +++ b/lib/irrlicht/source/Irrlicht/CIrrDeviceAndroid.cpp @@ -1300,13 +1300,16 @@ void CIrrDeviceAndroid::fromSTKEditBox(int widget_id, const core::stringw& text, return; } - std::vector utf8; + // Android use 32bit wchar_t and java use utf16 string + // We should not use the modified utf8 from java as it fails for emoji + // because it's larger than 16bit + + std::vector utf16; // Use utf32 for emoji later static_assert(sizeof(wchar_t) == sizeof(uint32_t), "wchar_t is not 32bit"); - uint32_t* chars = (uint32_t*)text.c_str(); - utf8::unchecked::utf32to8(chars, chars + text.size(), back_inserter(utf8)); - utf8.push_back(0); - jstring jstring_text = env->NewStringUTF(utf8.data()); + const uint32_t* chars = (const uint32_t*)text.c_str(); + utf8::unchecked::utf32to16(chars, chars + text.size(), back_inserter(utf16)); + jstring jstring_text = env->NewString((const jchar*)utf16.data(), utf16.size()); env->CallVoidMethod(native_activity, method_id, (jint)widget_id, jstring_text, (jint)selection_start, (jint)selection_end, (jint)type); if (was_detached) diff --git a/src/guiengine/widgets/text_box_widget.cpp b/src/guiengine/widgets/text_box_widget.cpp index 66ee17a84..b098fa984 100644 --- a/src/guiengine/widgets/text_box_widget.cpp +++ b/src/guiengine/widgets/text_box_widget.cpp @@ -22,6 +22,7 @@ #include "guiengine/widgets/CGUIEditBox.hpp" #include "utils/ptr_vector.hpp" #include "utils/translation.hpp" +#include "utils/utf8.h" #include #include @@ -264,13 +265,24 @@ ANDROID_EDITTEXT_CALLBACK(ANDROID_PACKAGE_CALLBACK_NAME) if (text == NULL) return; - const char* utf8_text = env->GetStringUTFChars(text, NULL); - if (utf8_text == NULL) + const uint16_t* utf16_text = (const uint16_t*)env->GetStringChars(text, NULL); + if (utf16_text == NULL) return; - - // Android use 32bit wchar_t - std::u32string to_editbox = StringUtils::utf8ToUtf32(utf8_text); - env->ReleaseStringUTFChars(text, utf8_text); + const size_t len = env->GetStringLength(text); + // Android use 32bit wchar_t and java use utf16 string + // We should not use the modified utf8 from java as it fails for emoji + // because it's larger than 16bit + std::u32string to_editbox; + try + { + utf8::utf16to32(utf16_text, utf16_text + len, + back_inserter(to_editbox)); + } + catch (std::exception& e) + { + (void)e; + } + env->ReleaseStringChars(text, utf16_text); GUIEngine::addGUIFunctionBeforeRendering([widget_id, to_editbox, start, end, composing_start, composing_end]()