Browse Source

Use custom IME handler on Vita (#1442)

pull/1485/head
Epifanov Ivan 5 years ago committed by Anders Jenbo
parent
commit
e108e30338
  1. 5
      CMakeLists.txt
  2. 16
      SourceX/DiabloUI/diabloui.cpp
  3. 120
      SourceX/platform/vita/keyboard.cpp
  4. 3
      SourceX/platform/vita/keyboard.h

5
CMakeLists.txt

@ -354,6 +354,11 @@ if(SWITCH)
SourceX/platform/switch/docking.cpp)
set(BIN_TARGET devilutionx.elf)
endif()
if(VITA)
list(APPEND devilutionx_SRCS
SourceX/platform/vita/keyboard.cpp)
endif()
if(N3DS)
list(APPEND devilutionx_SRCS

16
SourceX/DiabloUI/diabloui.cpp

@ -23,6 +23,10 @@
// for virtual keyboard on Switch
#include "platform/switch/keyboard.h"
#endif
#ifdef __vita__
// for virtual keyboard on Vita
#include "platform/vita/keyboard.h"
#endif
namespace dvl {
@ -102,6 +106,8 @@ void UiInitList(int count, void (*fnFocus)(int value), void (*fnSelect)(int valu
textInputActive = true;
#ifdef __SWITCH__
switch_start_text_input("", pItemUIEdit->m_value, pItemUIEdit->m_max_length, /*multiline=*/0);
#elif defined(__vita__)
vita_start_text_input("", pItemUIEdit->m_value, pItemUIEdit->m_max_length);
#else
SDL_StartTextInput();
#endif
@ -218,6 +224,12 @@ void selhero_CatToName(char *in_buf, char *out_buf, int cnt)
strncat(out_buf, output.c_str(), cnt - strlen(out_buf));
}
void selhero_SetName(char *in_buf, char *out_buf, int cnt)
{
std::string output = utf8_to_latin1(in_buf);
strncpy(out_buf, output.c_str(), cnt);
}
bool HandleMenuAction(MenuAction menu_action)
{
switch (menu_action) {
@ -333,7 +345,11 @@ void UiFocusNavigation(SDL_Event *event)
#ifndef USE_SDL1
case SDL_TEXTINPUT:
if (textInputActive) {
#ifdef __vita__
selhero_SetName(event->text.text, UiTextInput, UiTextInputLen);
#else
selhero_CatToName(event->text.text, UiTextInput, UiTextInputLen);
#endif
}
return;
#endif

120
SourceX/platform/vita/keyboard.cpp

@ -0,0 +1,120 @@
#include <string.h>
#include <stdbool.h>
#include <SDL.h>
#include <psp2/types.h>
#include <psp2/ime_dialog.h>
#include "platform/vita/keyboard.h"
static void utf16_to_utf8(const uint16_t *src, uint8_t *dst)
{
int i;
for (i = 0; src[i]; i++) {
if ((src[i] & 0xFF80) == 0) {
*(dst++) = src[i] & 0xFF;
} else if((src[i] & 0xF800) == 0) {
*(dst++) = ((src[i] >> 6) & 0xFF) | 0xC0;
*(dst++) = (src[i] & 0x3F) | 0x80;
} else if((src[i] & 0xFC00) == 0xD800 && (src[i + 1] & 0xFC00) == 0xDC00) {
*(dst++) = (((src[i] + 64) >> 8) & 0x3) | 0xF0;
*(dst++) = (((src[i] >> 2) + 16) & 0x3F) | 0x80;
*(dst++) = ((src[i] >> 4) & 0x30) | 0x80 | ((src[i + 1] << 2) & 0xF);
*(dst++) = (src[i + 1] & 0x3F) | 0x80;
i += 1;
} else {
*(dst++) = ((src[i] >> 12) & 0xF) | 0xE0;
*(dst++) = ((src[i] >> 6) & 0x3F) | 0x80;
*(dst++) = (src[i] & 0x3F) | 0x80;
}
}
*dst = '\0';
}
static void utf8_to_utf16(const uint8_t *src, uint16_t *dst)
{
int i;
for (i = 0; src[i];) {
if ((src[i] & 0xE0) == 0xE0) {
*(dst++) = ((src[i] & 0x0F) << 12) | ((src[i + 1] & 0x3F) << 6) | (src[i + 2] & 0x3F);
i += 3;
} else if ((src[i] & 0xC0) == 0xC0) {
*(dst++) = ((src[i] & 0x1F) << 6) | (src[i + 1] & 0x3F);
i += 2;
} else {
*(dst++) = src[i];
i += 1;
}
}
*dst = '\0';
}
static int vita_input_thread(void *ime_buffer)
{
while(1) {
// update IME status. Terminate, if finished
SceCommonDialogStatus dialogStatus = sceImeDialogGetStatus();
if (dialogStatus == SCE_COMMON_DIALOG_STATUS_FINISHED) {
uint8_t utf8_buffer[SCE_IME_DIALOG_MAX_TEXT_LENGTH];
SceImeDialogResult result;
SDL_memset(&result, 0, sizeof(SceImeDialogResult));
sceImeDialogGetResult(&result);
// Convert UTF16 to UTF8
utf16_to_utf8((SceWChar16*)ime_buffer, utf8_buffer);
// send sdl event
SDL_Event event;
event.text.type = SDL_TEXTINPUT;
SDL_utf8strlcpy(event.text.text, (const char*)utf8_buffer, SDL_arraysize(event.text.text));
SDL_PushEvent(&event);
sceImeDialogTerm();
break;
}
}
return 0;
}
static int vita_keyboard_get(const char *guide_text, const char *initial_text, int max_len, SceWChar16 *buf)
{
SceWChar16 title[SCE_IME_DIALOG_MAX_TITLE_LENGTH];
SceWChar16 text[SCE_IME_DIALOG_MAX_TEXT_LENGTH];
SceInt32 res;
SDL_memset(&title, 0, sizeof(title));
SDL_memset(&text, 0, sizeof(text));
utf8_to_utf16((const uint8_t*)guide_text, title);
utf8_to_utf16((const uint8_t*)initial_text, text);
SceImeDialogParam param;
sceImeDialogParamInit(&param);
param.supportedLanguages = SCE_IME_LANGUAGE_ENGLISH;
param.languagesForced = SCE_FALSE;
param.type = SCE_IME_TYPE_DEFAULT;
param.option = 0;
param.textBoxMode = SCE_IME_DIALOG_TEXTBOX_MODE_WITH_CLEAR;
param.maxTextLength = max_len;
param.title = title;
param.initialText = text;
param.inputTextBuffer = buf;
res = sceImeDialogInit(&param);
if (res < 0) {
return 0;
}
return 1;
}
void vita_start_text_input(const char *guide_text, const char *initial_text, int max_length)
{
SceWChar16 ime_buffer[SCE_IME_DIALOG_MAX_TEXT_LENGTH];
if (vita_keyboard_get(guide_text, initial_text, max_length, ime_buffer)) {
SDL_CreateThread(vita_input_thread, "vita_input_thread", (void *)ime_buffer);
}
}

3
SourceX/platform/vita/keyboard.h

@ -0,0 +1,3 @@
#pragma once
void vita_start_text_input(const char *guide_text, const char *initial_text, int max_length);
Loading…
Cancel
Save