#include "prx/libSceImeDialog/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libSceIme/include/ImeInput.hpp" #include "prx/libSceVideoOut/include/ImeTextInput.hpp" #include #include #include #include namespace { constexpr int StatusNone = 0; constexpr int StatusRunning = 1; constexpr int StatusFinished = 2; constexpr std::uint32_t EndStatusOk = 0; constexpr std::uint32_t EndStatusUserCanceled = 1; constexpr std::uint32_t EndStatusAborted = 2; constexpr int ErrorBusy = static_cast(0x80bc0001u); constexpr int ErrorSuspending = static_cast(0x80bc0009u); constexpr int ErrorNotOpened = static_cast(0x80bc0002u); constexpr int ErrorNotInUse = static_cast(0x80bc0107u); constexpr int ErrorInvalidMaxTextLength = static_cast(0x80bc0016u); constexpr int ErrorInvalidInputTextBuffer = static_cast(0x80bc0017u); constexpr int ErrorInvalidAddress = static_cast(0x80bc0031u); void Require(bool value) { if (!value) std::abort(); } constexpr unsigned WindowId = 7; ImeTextInput g_window; void Type(const char* utf8) { SDL_Event event{}; event.type = SDL_TEXTINPUT; event.text.windowID = WindowId; std::strncpy(event.text.text, utf8, sizeof(event.text.text) - 1); g_window.HandleEvent(event, WindowId); } void Press(SDL_Scancode scancode) { SDL_Event event{}; event.type = SDL_KEYDOWN; event.key.windowID = WindowId; event.key.keysym.scancode = scancode; g_window.HandleEvent(event, WindowId); } Param DialogParam(char16_t* buffer, std::uint32_t maxLength) { Param param{}; param.max_text_length = maxLength; param.input_text_buffer = buffer; return param; } std::uint32_t EndStatus() { Result result{}; Require(sceImeDialogGetResult(&result) == 0); return result.endstatus; } void Open(const Param& param) { Require(sceImeDialogInit(¶m, nullptr) == 0); Require(sceImeDialogGetStatus() == StatusRunning); Require(ImeCapturesKeyboard_nid_postfix()); } void Close() { Require(sceImeDialogTerm() == 0); Require(sceImeDialogGetStatus() == StatusNone); } } int main() { char16_t buffer[16] = u"Hi"; const Param param = DialogParam(buffer, 8); Require(!ImeCapturesKeyboard_nid_postfix()); Require(sceImeDialogGetStatus() == StatusNone); Require(sceImeDialogTerm() == ErrorNotOpened); Open(param); for (int poll = 0; poll < 8; ++poll) Require(sceImeDialogGetStatus() == StatusRunning); Require(sceImeDialogInit(¶m, nullptr) == ErrorBusy); Result early{}; Require(sceImeDialogGetResult(&early) == ErrorNotOpened); Type("\xc3\xa9"); Type("\xf0\x9f\x98\x80"); Require(std::u16string(buffer) == u"Hi"); Press(SDL_SCANCODE_RETURN); Require(sceImeDialogGetStatus() == StatusFinished); Require(!ImeCapturesKeyboard_nid_postfix()); Require(EndStatus() == EndStatusOk); Require(std::u16string(buffer) == u"Hi\u00e9\U0001F600"); Require(sceImeDialogAbort() == ErrorNotOpened); Close(); Require(sceImeDialogTerm() == ErrorNotOpened); buffer[0] = u'\0'; Open(param); Type("abc"); Press(SDL_SCANCODE_HOME); Press(SDL_SCANCODE_DELETE); Press(SDL_SCANCODE_END); Type("\xf0\x9f\x98\x80"); Press(SDL_SCANCODE_BACKSPACE); Press(SDL_SCANCODE_LEFT); Type("X"); Type("1234"); Press(SDL_SCANCODE_END); Type("\xf0\x9f\x98\x80"); Type("98"); Type("Z"); Press(SDL_SCANCODE_RETURN); Require(EndStatus() == EndStatusOk); Require(std::u16string(buffer) == u"bX1234c9"); Close(); buffer[0] = u'\0'; Open(param); Press(SDL_SCANCODE_RETURN); Require(EndStatus() == EndStatusOk); Require(buffer[0] == u'\0'); Close(); std::memcpy(buffer, u"keep", sizeof(u"keep")); Open(param); Type("zz"); Press(SDL_SCANCODE_ESCAPE); Require(sceImeDialogGetStatus() == StatusFinished); Require(EndStatus() == EndStatusUserCanceled); Require(std::u16string(buffer) == u"keep"); Close(); Open(param); Require(sceImeDialogAbort() == 0); Require(sceImeDialogGetStatus() == StatusFinished); Require(!ImeCapturesKeyboard_nid_postfix()); Require(EndStatus() == EndStatusAborted); Type("ignored"); Press(SDL_SCANCODE_RETURN); Require(std::u16string(buffer) == u"keep"); Close(); Require(sceImeDialogForceClose() == ErrorNotInUse); Open(param); Type("zz"); Require(sceImeDialogForceClose() == 0); Require(sceImeDialogGetStatus() == StatusNone); Require(!ImeCapturesKeyboard_nid_postfix()); Type("ignored"); Press(SDL_SCANCODE_RETURN); Require(std::u16string(buffer) == u"keep"); Result closed{}; Require(sceImeDialogGetResult(&closed) == ErrorNotOpened); Require(sceImeDialogTerm() == ErrorNotOpened); Require(sceImeDialogForceClose() == ErrorNotInUse); Open(param); Type("!"); Press(SDL_SCANCODE_RETURN); Require(sceImeDialogGetStatus() == StatusFinished); Require(sceImeDialogForceClose() == 0); Require(sceImeDialogGetStatus() == StatusNone); Require(std::u16string(buffer) == u"keep!"); Open(param); Require(sceImeDialogAbort() == 0); Require(sceImeDialogForceClose() == 0); Require(sceImeDialogGetStatus() == StatusNone); Open(param); Close(); Require(sceImeDialogGetPanelPositionAndForm(nullptr) == ErrorNotOpened); std::uint32_t panelWidth = 0; std::uint32_t panelHeight = 0; Require(sceImeDialogGetPanelSize(nullptr, &panelWidth, &panelHeight) == 0 && panelWidth == 1920 && panelHeight == 1080); panelWidth = 0; panelHeight = 0; Require(sceImeDialogGetPanelSizeExtended(nullptr, nullptr, &panelWidth, &panelHeight) == 0 && panelWidth == 1920 && panelHeight == 1080); Require(sceImeDialogInit(nullptr, nullptr) == ErrorInvalidAddress); const Param empty = DialogParam(buffer, 0); Require(sceImeDialogInit(&empty, nullptr) == ErrorInvalidMaxTextLength); const Param tooLong = DialogParam(buffer, 2049); Require(sceImeDialogInit(&tooLong, nullptr) == ErrorInvalidMaxTextLength); const Param noBuffer = DialogParam(nullptr, 8); Require(sceImeDialogInit(&noBuffer, nullptr) == ErrorInvalidInputTextBuffer); Require(sceImeDialogGetStatus() == StatusNone); Require(!ImeCapturesKeyboard_nid_postfix()); std::uint32_t star = 0xa5a5a5a5u; const auto starAddress = static_cast(reinterpret_cast(&star)); Require(sceImeDialogGetCurrentStarState(starAddress) == ErrorNotInUse && star == 0xa5a5a5a5u); Require(sceImeDialogSetPanelPosition(640, 360) == ErrorNotInUse); Require(sceImeDialogInitInternal(nullptr, nullptr) == ErrorInvalidAddress); Require(sceImeDialogInitInternal(&empty, nullptr) == ErrorInvalidMaxTextLength); Require(sceImeDialogGetStatus() == StatusNone); Require(sceImeDialogInitInternal(¶m, nullptr) == 0); Require(sceImeDialogGetStatus() == StatusRunning && ImeCapturesKeyboard_nid_postfix()); Require(sceImeDialogInitInternal(¶m, nullptr) == ErrorBusy); Require(sceImeDialogGetCurrentStarState(0) == ErrorInvalidAddress); Require(sceImeDialogGetCurrentStarState(starAddress) == 0 && star == 0); Require(sceImeDialogSetPanelPosition(640, 360) == ErrorSuspending); Require(sceImeDialogAbort() == 0); Require(sceImeDialogSetPanelPosition(0, 0) == ErrorSuspending); Close(); }