Update Japanese On Screen Keyboard

This commit is contained in:
mgaver 2013-04-22 18:02:52 +09:00
parent dda1551488
commit e22f8d516e
2 changed files with 563 additions and 326 deletions

View file

@ -1,325 +1,552 @@
// Copyright (c) 2012- PPSSPP Project. // Copyright (c) 2012- PPSSPP Project.
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0 or later versions. // the Free Software Foundation, version 2.0 or later versions.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at // Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "i18n/i18n.h" #include "i18n/i18n.h"
#include "math/math_util.h" #include "math/math_util.h"
#include "Core/Dialog/PSPOskDialog.h" #include "Core/Dialog/PSPOskDialog.h"
#include "Core/Util/PPGeDraw.h" #include "Core/Util/PPGeDraw.h"
#include "Core/HLE/sceCtrl.h" #include "Core/HLE/sceCtrl.h"
#include "Core/Reporting.h" #include "Core/Reporting.h"
#include "Common/ChunkFile.h" #include "Common/ChunkFile.h"
#include "GPU/GPUState.h" #include "GPU/GPUState.h"
#ifndef _WIN32 #ifndef _WIN32
#include <ctype.h> #include <ctype.h>
#include <math.h> #include <math.h>
#endif #endif
#define NUMKEYROWS 4 #define NUMKEYROWS 4
#define KEYSPERROW 12 #define KEYSPERROW 12
#define NUMBEROFVALIDCHARS (KEYSPERROW * NUMKEYROWS) #define NUMBEROFVALIDCHARS (KEYSPERROW * NUMKEYROWS)
static const char oskKeys[OSK_KEYBOARD_COUNT][NUMKEYROWS][KEYSPERROW + 1] =
{ const int numKeyCols[OSK_KEYBOARD_COUNT] = {12, 12, 13, 13};
{ const int numKeyRows[OSK_KEYBOARD_COUNT] = {4, 4, 5, 5};
{'1','2','3','4','5','6','7','8','9','0','-','+','\0'},
{'q','w','e','r','t','y','u','i','o','p','[',']','\0'}, /* static const char oskKeys[2][numKeyCols][KEYSPERROW + 1] =
{'a','s','d','f','g','h','j','k','l',';','@','~','\0'}, {
{'z','x','c','v','b','n','m',',','.','/','?','\\','\0'}, {
}, {'1','2','3','4','5','6','7','8','9','0','-','+','\0'},
{ {'q','w','e','r','t','y','u','i','o','p','[',']','\0'},
{'!','@','#','$','%','^','&','*','(',')','_','+','\0'}, {'a','s','d','f','g','h','j','k','l',';','@','~','\0'},
{'Q','W','E','R','T','Y','U','I','O','P','{','}','\0'}, {'z','x','c','v','b','n','m',',','.','/','?','\\','\0'},
{'A','S','D','F','G','H','J','K','L',':','"','`','\0'}, },
{'Z','X','C','V','B','N','M','<','>','/','?','|','\0'}, {
}, {'!','@','#','$','%','^','&','*','(',')','_','+','\0'},
}; {'Q','W','E','R','T','Y','U','I','O','P','{','}','\0'},
{'A','S','D','F','G','H','J','K','L',':','"','`','\0'},
{'Z','X','C','V','B','N','M','<','>','/','?','|','\0'},
PSPOskDialog::PSPOskDialog() : PSPDialog() { },
};
} */
PSPOskDialog::~PSPOskDialog() { // Japanese(Kana) diacritics
} static const wchar_t diacritics[2][103] =
{
void PSPOskDialog::ConvertUCS2ToUTF8(std::string& _string, const u32 em_address) {L"かがきぎくぐけげこごさざしじすずせぜそぞただちぢつづてでとどはばぱばひびぴびふぶぷぶへべぺべほぼぽぼウヴカガキギクグケゲコゴサザシジスズセゼソゾタダチヂツヅテデトドハバパバヒビピビフブプブヘベペベホボポボ"},
{ {L"はぱばぱひぴびぴふぷぶぷへぱべぱほぽぼぽハパバパヒピビピフプブプヘパベパホポボポ"}
char stringBuffer[2048]; };
char *string = stringBuffer;
// Korean(Hangul) consonant
if (em_address == 0) static const wchar_t kor_cons[] = L"ㄱㄲㄴㄷㄸㄹㅁㅂㅃㅅㅆㅇㅈㅉㅊㅋㅌㅍㅎ";
{
_string = ""; // Korean(Hangul) bowels, Some bowels are not used, them will be spacing
return; static const wchar_t kor_vowel[] = L"ㅏㅐㅑㅒㅓㅔㅕㅖㅗ ㅛㅜ ㅠㅡ ㅣ";
}
u16 *src = (u16 *) Memory::GetPointer(em_address); static const wchar_t oskKeys[OSK_KEYBOARD_COUNT][5][14] =
int c; {
while (c = *src++) {
{ // Latin Lowercase
if (c < 0x80) {L"1234567890-+\0"},
*string++ = c; {L"qwertyuiop[]\0"},
else if (c < 0x800) {L"asdfghjkl;@~\0"},
{ {L"zxcvbnm,./?\\\0"},
*string++ = 0xC0 | (c >> 6); },
*string++ = 0x80 | (c & 0x3F); {
} // Latin Uppercase
else {L"!@#$%^&*()_+\0"},
{ {L"QWERTYUIOP{}\0"},
*string++ = 0xE0 | (c >> 12); {L"ASDFGHJKL:\"`\0"},
*string++ = 0x80 | ((c >> 6) & 0x3F); {L"ZXCVBNM<>/?|\0"},
*string++ = 0x80 | (c & 0x3F); },
} {
} // Hiragana
*string++ = '\0'; {L"あかさたなはまやらわぁゃっ"},
_string = stringBuffer; {L"いきしちにひみ り ぃ  "},
} {L"うくすつぬふむゆるをぅゅ˝"},
{L"えけせてねへめ れ ぇ ˚"},
{L"おこそとのほもよるんぉょ "},
int PSPOskDialog::Init(u32 oskPtr) },
{ {
// Ignore if already running // Katakana
if (status != SCE_UTILITY_STATUS_NONE && status != SCE_UTILITY_STATUS_SHUTDOWN) {L"アカサタナハマヤラワァャッ"},
return SCE_ERROR_UTILITY_INVALID_STATUS; {L"イキシチニヒミ リ ィ  "},
// Seems like this should crash? {L"ウクスツヌフムユルヲゥュ˝"},
if (!Memory::IsValidAddress(oskPtr)) {L"エケセテネヘメ レ ェ ˚"},
{ {L"オコソトノホモヨルンォョ "},
ERROR_LOG_REPORT(HLE, "sceUtilityOskInitStart: invalid params (%08x)", oskPtr); },
return -1; /*
} {
// Korean(Hangul) Lowercase
oskParams = Memory::GetStruct<SceUtilityOskParams>(oskPtr); {L"1234567890-+"},
if (oskParams->base.size != sizeof(SceUtilityOskParams)) {L"ㅂㅈㄷㄱㅅㅛㅕㅑㅐㅔ[]"},
{ {L"ㅁㄴㅇㄹㅎㅗㅓㅏㅣ;@~"},
ERROR_LOG(HLE, "sceUtilityOskInitStart: invalid size (%d)", oskParams->base.size); {L"ㅋㅌㅊㅍㅠㅜㅡ<>/?|"},
return SCE_ERROR_UTILITY_INVALID_PARAM_SIZE; },
} {
// Also seems to crash. // Korean(Hangul) Uppercase
if (!Memory::IsValidAddress(oskParams->fieldPtr)) {L"!@#$%^&*()_+"},
{ {L"ㅃㅉㄸㄲㅆㅛㅕㅑㅒㅖ{}"},
ERROR_LOG_REPORT(HLE, "sceUtilityOskInitStart: invalid field data (%08x)", oskParams->fieldPtr); {L"ㅁㄴㅇㄹㅎㅗㅓㅏㅣ:\"`"},
return -1; {L"ㅋㅌㅊㅍㅠㅜㅡ<>/?|"},
} },
*/
if (oskParams->unk_60 != 0) };
WARN_LOG_REPORT(HLE, "sceUtilityOskInitStart: unknown param is non-zero (%08x)", oskParams->unk_60);
if (oskParams->fieldCount != 1)
WARN_LOG_REPORT(HLE, "sceUtilityOskInitStart: unsupported field count %d", oskParams->fieldCount); PSPOskDialog::PSPOskDialog() : PSPDialog() {
setlocale(LC_ALL, "");
status = SCE_UTILITY_STATUS_INITIALIZE; }
selectedChar = 0;
currentKeyboard = OSK_KEYBOARD_LATIN_LOWERCASE; PSPOskDialog::~PSPOskDialog() {
}
Memory::ReadStruct(oskParams->fieldPtr, &oskData);
ConvertUCS2ToUTF8(oskDesc, oskData.descPtr); void PSPOskDialog::ConvertUCS2ToUTF8(std::string& _string, const u32 em_address)
ConvertUCS2ToUTF8(oskIntext, oskData.intextPtr); {
ConvertUCS2ToUTF8(oskOuttext, oskData.outtextPtr); char stringBuffer[2048];
char *string = stringBuffer;
inputChars = oskIntext.substr(0, FieldMaxLength());
if (em_address == 0)
// Eat any keys pressed before the dialog inited. {
__CtrlReadLatch(); _string = "";
return;
StartFade(true); }
return 0;
} u16 *src = (u16 *) Memory::GetPointer(em_address);
int c;
u32 PSPOskDialog::FieldMaxLength() while (c = *src++)
{ {
if (oskData.outtextlimit > oskData.outtextlength - 1 || oskData.outtextlimit == 0) if (c < 0x80)
return oskData.outtextlength - 1; *string++ = c;
return oskData.outtextlimit; else if (c < 0x800)
} {
*string++ = 0xC0 | (c >> 6);
void PSPOskDialog::RenderKeyboard() *string++ = 0x80 | (c & 0x3F);
{ }
int selectedRow = selectedChar / KEYSPERROW; else
int selectedCol = selectedChar % KEYSPERROW; {
*string++ = 0xE0 | (c >> 12);
char temp[2]; *string++ = 0x80 | ((c >> 6) & 0x3F);
temp[1] = '\0'; *string++ = 0x80 | (c & 0x3F);
}
u32 limit = FieldMaxLength(); }
*string++ = '\0';
const float keyboardLeftSide = (480.0f - (24.0f * KEYSPERROW)) / 2.0f; _string = stringBuffer;
const float characterWidth = 12.0f; }
float previewLeftSide = (480.0f - (12.0f * limit)) / 2.0f;
float title = (480.0f - (0.5f * limit)) / 2.0f; void PSPOskDialog::ConvertUCS2ToUTF8(std::string& _string, wchar_t* input)
{
PPGeDrawText(oskDesc.c_str(), title , 20, PPGE_ALIGN_CENTER, 0.5f, CalcFadedColor(0xFFFFFFFF)); char stringBuffer[2048];
for (u32 i = 0; i < limit; ++i) char *string = stringBuffer;
{
u32 color = CalcFadedColor(0xFFFFFFFF); int c;
if (i < inputChars.size()) while (c = *input++)
temp[0] = inputChars[i]; {
else if (i == inputChars.size()) if (c < 0x80)
{ *string++ = c;
temp[0] = oskKeys[currentKeyboard][selectedRow][selectedCol]; else if (c < 0x800)
float animStep = (float)(gpuStats.numFrames % 40) / 20.0f; {
// Fade in and out the next character so they know it's not part of the string yet. *string++ = 0xC0 | (c >> 6);
u32 alpha = (0.5f - (cosf(animStep * M_PI) / 2.0f)) * 128 + 127; *string++ = 0x80 | (c & 0x3F);
color = CalcFadedColor((alpha << 24) | 0xFFFFFF); }
else
PPGeDrawText(temp, previewLeftSide + (i * characterWidth), 40.0f, 0, 0.5f, color); {
*string++ = 0xE0 | (c >> 12);
// Also draw the underline for the same reason. *string++ = 0x80 | ((c >> 6) & 0x3F);
color = CalcFadedColor(0xFFFFFFFF); *string++ = 0x80 | (c & 0x3F);
temp[0] = '_'; }
} }
else *string++ = '\0';
temp[0] = '_'; _string = stringBuffer;
}
PPGeDrawText(temp, previewLeftSide + (i * characterWidth), 40.0f, 0, 0.5f, color);
}
for (int row = 0; row < NUMKEYROWS; ++row) int PSPOskDialog::Init(u32 oskPtr)
{ {
for (int col = 0; col < KEYSPERROW; ++col) // Ignore if already running
{ if (status != SCE_UTILITY_STATUS_NONE && status != SCE_UTILITY_STATUS_SHUTDOWN)
u32 color = CalcFadedColor(0xFFFFFFFF); return SCE_ERROR_UTILITY_INVALID_STATUS;
if (selectedRow == row && col == selectedCol) // Seems like this should crash?
color = CalcFadedColor(0xFF3060FF); if (!Memory::IsValidAddress(oskPtr))
{
temp[0] = oskKeys[currentKeyboard][row][col]; ERROR_LOG_REPORT(HLE, "sceUtilityOskInitStart: invalid params (%08x)", oskPtr);
PPGeDrawText(temp, keyboardLeftSide + (25.0f * col) + characterWidth / 2.0, 70.0f + (25.0f * row), PPGE_ALIGN_HCENTER, 0.6f, color); return -1;
}
if (selectedRow == row && col == selectedCol)
PPGeDrawText("_", keyboardLeftSide + (25.0f * col) + characterWidth / 2.0, 70.0f + (25.0f * row), PPGE_ALIGN_HCENTER, 0.6f, CalcFadedColor(0xFFFFFFFF)); oskParams = Memory::GetStruct<SceUtilityOskParams>(oskPtr);
} if (oskParams->base.size != sizeof(SceUtilityOskParams))
} {
} ERROR_LOG(HLE, "sceUtilityOskInitStart: invalid size (%d)", oskParams->base.size);
return SCE_ERROR_UTILITY_INVALID_PARAM_SIZE;
int PSPOskDialog::Update() }
{ // Also seems to crash.
buttons = __CtrlReadLatch(); if (!Memory::IsValidAddress(oskParams->fieldPtr))
int selectedRow = selectedChar / KEYSPERROW; {
int selectedExtra = selectedChar % KEYSPERROW; ERROR_LOG_REPORT(HLE, "sceUtilityOskInitStart: invalid field data (%08x)", oskParams->fieldPtr);
return -1;
u32 limit = FieldMaxLength(); }
if (status == SCE_UTILITY_STATUS_INITIALIZE) if (oskParams->unk_60 != 0)
{ WARN_LOG_REPORT(HLE, "sceUtilityOskInitStart: unknown param is non-zero (%08x)", oskParams->unk_60);
status = SCE_UTILITY_STATUS_RUNNING; if (oskParams->fieldCount != 1)
} WARN_LOG_REPORT(HLE, "sceUtilityOskInitStart: unsupported field count %d", oskParams->fieldCount);
else if (status == SCE_UTILITY_STATUS_RUNNING)
{ status = SCE_UTILITY_STATUS_INITIALIZE;
UpdateFade(); selectedChar = 0;
currentKeyboard = OSK_KEYBOARD_LATIN_LOWERCASE;
StartDraw();
RenderKeyboard(); Memory::ReadStruct(oskParams->fieldPtr, &oskData);
PPGeDrawImage(I_CROSS, 30, 220, 20, 20, 0, CalcFadedColor(0xFFFFFFFF)); ConvertUCS2ToUTF8(oskDesc, oskData.descPtr);
PPGeDrawImage(I_CIRCLE, 150, 220, 20, 20, 0, CalcFadedColor(0xFFFFFFFF)); ConvertUCS2ToUTF8(oskIntext, oskData.intextPtr);
//PPGeDrawImage(I_BUTTON, 230, 220, 50, 20, 0, CalcFadedColor(0xFFFFFFFF)); ConvertUCS2ToUTF8(oskOuttext, oskData.outtextPtr);
//PPGeDrawImage(I_BUTTON, 350, 220, 55, 20, 0, CalcFadedColor(0xFFFFFFFF));
inputChars = L"";
I18NCategory *d = GetI18NCategory("Dialog");
PPGeDrawText(d->T("Select"), 60, 220, PPGE_ALIGN_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF)); u16 *src = (u16 *) Memory::GetPointer(oskData.intextPtr);
PPGeDrawText(d->T("Delete"), 180, 220, PPGE_ALIGN_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF)); int c;
PPGeDrawText("Start", 245, 220, PPGE_ALIGN_LEFT, 0.6f, CalcFadedColor(0xFFFFFFFF)); while (c = *src++)
PPGeDrawText(d->T("Finish"), 290, 222, PPGE_ALIGN_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF)); {
PPGeDrawText("Select", 365, 220, PPGE_ALIGN_LEFT, 0.6f, CalcFadedColor(0xFFFFFFFF)); inputChars += c;
// TODO: Show title of next keyboard? if(c == 0x00)
PPGeDrawText(d->T("Shift"), 415, 222, PPGE_ALIGN_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF)); {
break;
if (IsButtonPressed(CTRL_UP)) }
{ }
selectedChar -= KEYSPERROW;
} // Eat any keys pressed before the dialog inited.
else if (IsButtonPressed(CTRL_DOWN)) __CtrlReadLatch();
{
selectedChar += KEYSPERROW; StartFade(true);
} return 0;
else if (IsButtonPressed(CTRL_LEFT)) }
{
selectedChar--; std::wstring PSPOskDialog::CombinationString()
if (((selectedChar + KEYSPERROW) % KEYSPERROW) == KEYSPERROW - 1) {
selectedChar += KEYSPERROW; std::wstring string;
}
else if (IsButtonPressed(CTRL_RIGHT)) isCombinated = false;
{
selectedChar++; int selectedRow = selectedChar / numKeyCols[currentKeyboard];
if ((selectedChar % KEYSPERROW) == 0) int selectedCol = selectedChar % numKeyCols[currentKeyboard];
selectedChar -= KEYSPERROW;
} if(oskKeys[currentKeyboard][selectedRow][selectedCol] == L'˝')
{
selectedChar = (selectedChar + NUMBEROFVALIDCHARS) % NUMBEROFVALIDCHARS; for(u32 i = 0; i < inputChars.size(); i++)
{
if (IsButtonPressed(CTRL_CROSS)) if(i + 1 == inputChars.size())
{ {
if (inputChars.size() < limit) for(u32 j = 0; j < wcslen(diacritics[0]); j+=2)
inputChars += oskKeys[currentKeyboard][selectedRow][selectedExtra]; {
} if(inputChars[i] == diacritics[0][j])
else if (IsButtonPressed(CTRL_SELECT)) {
{ string += diacritics[0][j + 1];
// TODO: Limit by allowed keyboards... isCombinated = true;
currentKeyboard = (OskKeyboardDisplay)((currentKeyboard + 1) % OSK_KEYBOARD_COUNT); break;
} }
else if (IsButtonPressed(CTRL_CIRCLE)) }
{
if (inputChars.size() > 0) if(isCombinated == false)
inputChars.resize(inputChars.size() - 1); {
} string += inputChars[i];
else if (IsButtonPressed(CTRL_START)) }
{ }
StartFade(false); else
} {
EndDraw(); string += inputChars[i];
} }
else if (status == SCE_UTILITY_STATUS_FINISHED) }
{ }
status = SCE_UTILITY_STATUS_SHUTDOWN; else if(oskKeys[currentKeyboard][selectedRow][selectedCol] == L'˚')
} {
for(u32 i = 0; i < inputChars.size(); i++)
for (u32 i = 0; i < oskData.outtextlength; ++i) {
{ if(i + 1 == inputChars.size())
u16 value = 0; {
if (i < inputChars.size()) for(u32 j = 0; j < wcslen(diacritics[1]); j+=2)
value = inputChars[i]; {
Memory::Write_U16(value, oskData.outtextPtr + (2 * i)); if(inputChars[i] == diacritics[1][j])
} {
string += diacritics[1][j + 1];
oskParams->base.result = 0; isCombinated = true;
oskData.result = PSP_UTILITY_OSK_RESULT_CHANGED; break;
Memory::WriteStruct(oskParams->fieldPtr, &oskData); }
}
return 0;
} if(isCombinated == false)
{
template <typename T> string += inputChars[i];
static void DoBasePointer(PointerWrap &p, T **ptr) }
{ }
u32 addr = *ptr == NULL ? 0 : (u8 *) *ptr - Memory::base; else
p.Do(addr); {
if (addr == 0) string += inputChars[i];
*ptr = NULL; }
else }
*ptr = Memory::GetStruct<T>(addr); }
else
} {
for(u32 i = 0; i < inputChars.size(); i++)
void PSPOskDialog::DoState(PointerWrap &p) {
{ string += inputChars[i];
PSPDialog::DoState(p); }
DoBasePointer(p, &oskParams);
p.Do(oskData); if (string.size() < FieldMaxLength())
p.Do(oskDesc); {
p.Do(oskIntext); string += oskKeys[currentKeyboard][selectedRow][selectedCol];
p.Do(oskOuttext); }
p.Do(selectedChar); isCombinated = true;
p.Do(inputChars); }
p.DoMarker("PSPOskDialog");
} return string;
}
u32 PSPOskDialog::FieldMaxLength()
{
if (oskData.outtextlimit > oskData.outtextlength - 1 || oskData.outtextlimit == 0)
return oskData.outtextlength - 1;
return oskData.outtextlimit;
}
void PSPOskDialog::RenderKeyboard()
{
int selectedRow = selectedChar / numKeyCols[currentKeyboard];
int selectedCol = selectedChar % numKeyCols[currentKeyboard];
wchar_t temp[2];
temp[1] = '\0';
std::string buffer;
u32 limit = FieldMaxLength();
const float keyboardLeftSide = (480.0f - (24.0f * numKeyCols[currentKeyboard])) / 2.0f;
const float characterWidth = 12.0f;
float previewLeftSide = (480.0f - (12.0f * limit)) / 2.0f;
float title = (480.0f - (0.5f * limit)) / 2.0f;
PPGeDrawText(oskDesc.c_str(), title , 20, PPGE_ALIGN_CENTER, 0.5f, CalcFadedColor(0xFFFFFFFF));
std::wstring result;
result = CombinationString();
for (u32 i = 0; i < limit; ++i)
{
u32 color = CalcFadedColor(0xFFFFFFFF);
if (i + 1 < result.size())
{
temp[0] = result[i];
ConvertUCS2ToUTF8(buffer, temp);
PPGeDrawText(buffer.c_str(), previewLeftSide + (i * characterWidth), 40.0f, 0, 0.5f, color);
}
else
{
if (i + 1 == result.size())
{
temp[0] = result[i];
if(isCombinated == true)
{
float animStep = (float)(gpuStats.numFrames % 40) / 20.0f;
// Fade in and out the next character so they know it's not part of the string yet.
u32 alpha = (0.5f - (cosf(animStep * M_PI) / 2.0f)) * 128 + 127;
color = CalcFadedColor((alpha << 24) | 0xFFFFFF);
ConvertUCS2ToUTF8(buffer, temp);
PPGeDrawText(buffer.c_str(), previewLeftSide + (i * characterWidth), 40.0f, 0, 0.5f, color);
// Also draw the underline for the same reason.
color = CalcFadedColor(0xFFFFFFFF);
PPGeDrawText("_", previewLeftSide + (i * characterWidth), 40.0f, 0, 0.5f, color);
}
else
{
ConvertUCS2ToUTF8(buffer, temp);
PPGeDrawText(buffer.c_str(), previewLeftSide + (i * characterWidth), 40.0f, 0, 0.5f, color);
}
}
else
{
PPGeDrawText("_", previewLeftSide + (i * characterWidth), 40.0f, 0, 0.5f, color);
}
}
}
for (int row = 0; row < numKeyRows[currentKeyboard]; ++row)
{
for (int col = 0; col < numKeyCols[currentKeyboard]; ++col)
{
u32 color = CalcFadedColor(0xFFFFFFFF);
if (selectedRow == row && col == selectedCol)
color = CalcFadedColor(0xFF3060FF);
temp[0] = oskKeys[currentKeyboard][row][col];
ConvertUCS2ToUTF8(buffer, temp);
PPGeDrawText(buffer.c_str(), keyboardLeftSide + (25.0f * col) + characterWidth / 2.0, 70.0f + (25.0f * row), PPGE_ALIGN_HCENTER, 0.6f, color);
if (selectedRow == row && col == selectedCol)
PPGeDrawText("_", keyboardLeftSide + (25.0f * col) + characterWidth / 2.0, 70.0f + (25.0f * row), PPGE_ALIGN_HCENTER, 0.6f, CalcFadedColor(0xFFFFFFFF));
}
}
}
int PSPOskDialog::Update()
{
buttons = __CtrlReadLatch();
int selectedRow = selectedChar / numKeyCols[currentKeyboard];
int selectedExtra = selectedChar % numKeyCols[currentKeyboard];
u32 limit = FieldMaxLength();
if (status == SCE_UTILITY_STATUS_INITIALIZE)
{
status = SCE_UTILITY_STATUS_RUNNING;
}
else if (status == SCE_UTILITY_STATUS_RUNNING)
{
UpdateFade();
StartDraw();
RenderKeyboard();
PPGeDrawImage(I_CROSS, 30, 220, 20, 20, 0, CalcFadedColor(0xFFFFFFFF));
PPGeDrawImage(I_CIRCLE, 150, 220, 20, 20, 0, CalcFadedColor(0xFFFFFFFF));
//PPGeDrawImage(I_BUTTON, 230, 220, 50, 20, 0, CalcFadedColor(0xFFFFFFFF));
//PPGeDrawImage(I_BUTTON, 350, 220, 55, 20, 0, CalcFadedColor(0xFFFFFFFF));
I18NCategory *d = GetI18NCategory("Dialog");
PPGeDrawText(d->T("Select"), 60, 220, PPGE_ALIGN_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF));
PPGeDrawText(d->T("Delete"), 180, 220, PPGE_ALIGN_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF));
PPGeDrawText("Start", 245, 220, PPGE_ALIGN_LEFT, 0.6f, CalcFadedColor(0xFFFFFFFF));
PPGeDrawText(d->T("Finish"), 290, 222, PPGE_ALIGN_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF));
PPGeDrawText("Select", 365, 220, PPGE_ALIGN_LEFT, 0.6f, CalcFadedColor(0xFFFFFFFF));
// TODO: Show title of next keyboard?
PPGeDrawText(d->T("Shift"), 415, 222, PPGE_ALIGN_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF));
if (IsButtonPressed(CTRL_UP))
{
selectedChar -= numKeyCols[currentKeyboard];
}
else if (IsButtonPressed(CTRL_DOWN))
{
selectedChar += numKeyCols[currentKeyboard];
}
else if (IsButtonPressed(CTRL_LEFT))
{
selectedChar--;
if (((selectedChar + numKeyCols[currentKeyboard]) % numKeyCols[currentKeyboard]) == numKeyCols[currentKeyboard] - 1)
selectedChar += numKeyCols[currentKeyboard];
}
else if (IsButtonPressed(CTRL_RIGHT))
{
selectedChar++;
if ((selectedChar % numKeyCols[currentKeyboard]) == 0)
selectedChar -= numKeyCols[currentKeyboard];
}
selectedChar = (selectedChar + (numKeyCols[currentKeyboard] * numKeyRows[currentKeyboard])) % (numKeyCols[currentKeyboard] * numKeyRows[currentKeyboard]);
if (IsButtonPressed(CTRL_CROSS))
{
inputChars = CombinationString();
}
else if (IsButtonPressed(CTRL_SELECT))
{
// TODO: Limit by allowed keyboards...
currentKeyboard = (OskKeyboardDisplay)((currentKeyboard + 1) % OSK_KEYBOARD_COUNT);
if(selectedRow >= numKeyRows[currentKeyboard])
{
selectedRow = numKeyRows[currentKeyboard] - 1;
}
if(selectedExtra >= numKeyCols[currentKeyboard])
{
selectedExtra = numKeyCols[currentKeyboard] - 1;
}
selectedChar = selectedRow * numKeyCols[currentKeyboard] + selectedExtra;
}
else if (IsButtonPressed(CTRL_CIRCLE))
{
if (inputChars.size() > 0)
inputChars.resize(inputChars.size() - 1);
}
else if (IsButtonPressed(CTRL_START))
{
StartFade(false);
}
EndDraw();
}
else if (status == SCE_UTILITY_STATUS_FINISHED)
{
status = SCE_UTILITY_STATUS_SHUTDOWN;
}
for (u32 i = 0; i < oskData.outtextlength; ++i)
{
u16 value = 0;
if (i < inputChars.size())
value = inputChars[i];
Memory::Write_U16(value, oskData.outtextPtr + (2 * i));
}
oskParams->base.result = 0;
oskData.result = PSP_UTILITY_OSK_RESULT_CHANGED;
Memory::WriteStruct(oskParams->fieldPtr, &oskData);
return 0;
}
template <typename T>
static void DoBasePointer(PointerWrap &p, T **ptr)
{
u32 addr = *ptr == NULL ? 0 : (u8 *) *ptr - Memory::base;
p.Do(addr);
if (addr == 0)
*ptr = NULL;
else
*ptr = Memory::GetStruct<T>(addr);
}
void PSPOskDialog::DoState(PointerWrap &p)
{
PSPDialog::DoState(p);
DoBasePointer(p, &oskParams);
p.Do(oskData);
p.Do(oskDesc);
p.Do(oskIntext);
p.Do(oskOuttext);
p.Do(selectedChar);
p.Do(inputChars);
p.DoMarker("PSPOskDialog");
}

View file

@ -144,6 +144,11 @@ enum OskKeyboardDisplay
{ {
OSK_KEYBOARD_LATIN_LOWERCASE, OSK_KEYBOARD_LATIN_LOWERCASE,
OSK_KEYBOARD_LATIN_UPPERCASE, OSK_KEYBOARD_LATIN_UPPERCASE,
OSK_KEYBOARD_HIRAGANA,
OSK_KEYBOARD_KATAKANA,
/* OSK_KEYBOARD_KOREAN_LOWERCASE,
OSK_KEYBOARD_KOREAN_UPPERCASE,
*/
// TODO: Something to do native? // TODO: Something to do native?
OSK_KEYBOARD_COUNT OSK_KEYBOARD_COUNT
}; };
@ -159,7 +164,11 @@ public:
virtual void DoState(PointerWrap &p); virtual void DoState(PointerWrap &p);
private: private:
void ConvertUCS2ToUTF8(std::string& _string, const u32 em_address); void ConvertUCS2ToUTF8(std::string& _string, const u32 em_address);
void ConvertUCS2ToUTF8(std::string& _string, wchar_t* input);
void RenderKeyboard(); void RenderKeyboard();
std::wstring CombinationString(); // for Japanese, Korean
u32 FieldMaxLength(); u32 FieldMaxLength();
SceUtilityOskParams *oskParams; SceUtilityOskParams *oskParams;
@ -169,7 +178,8 @@ private:
std::string oskOuttext; std::string oskOuttext;
int selectedChar; int selectedChar;
std::string inputChars; std::wstring inputChars;
OskKeyboardDisplay currentKeyboard; OskKeyboardDisplay currentKeyboard;
bool isCombinated;
}; };