rodecomp/Source/Client/Input/VietnameseInput.cpp
ragnarok-clanker 53430132ed Decompile 14 functions in Source/Client/Input/VietnameseInput.cpp, Source/Client/Input/VietnameseInput.h, ...
Batch #4497 by eAthena: 3 byte-identical, 11 confirmed by peer review.

- fn_18304 NotifyImeHelper: logic confirmed by peer review
- fn_18307 TELEXInputMode::TELEXInputMode: logic confirmed by peer review
- fn_18308 TELEXInputMode::Convert: logic confirmed by peer review
- fn_18309 TELEXInputMode::IsModifierKey: logic confirmed by peer review
- fn_18310 CInputMode::Reset: byte-identical
- fn_18311 CVietnameseInput::CVietnameseInput: byte-identical
- fn_18312 CVietnameseInput::Release: byte-identical
- fn_18313 CVietnameseInput::Compose: logic confirmed by peer review
- fn_18314 CVietnameseInput::SetMode: logic confirmed by peer review
- fn_18315 CVietnameseInput::IsComposeKey: logic confirmed by peer review
- fn_18316 CVietnameseInput::Reset: logic confirmed by peer review
- fn_18317 VNIInputMode::VNIInputMode: logic confirmed by peer review
- fn_18318 VNIInputMode::Convert: logic confirmed by peer review
- fn_18319 VNIInputMode::IsModifierKey: logic confirmed by peer review

Peer-reviewed-by: willerthal, youko, KWDev
Reviewed-by: ragnarok-clanker
Adds to the build: Source/Client/Input/VietnameseInput.cpp, Source/Client/Input/ImeHelper.cpp
2026-10-30 03:37:33 +00:00

324 lines
8.1 KiB
C++

#include "Client/Input/VietnameseInput.h"
#include <cstring>
// GLOBAL: gl_24898
unsigned char g_telexToneKeys[6] = "sfrxj";
// GLOBAL: gl_24899
unsigned short g_vietLowerChars[74] = {
0xEC61, 0xCC61, 0xD261, 0xDE61, 0xF261, 0x0061, 0xECE2, 0xCCE2, 0xD2E2, 0xDEE2, 0xF2E2, 0x00E2, 0xECE3, 0xCCE3, 0xD2E3,
0xDEE3, 0xF2E3, 0x00E3, 0xEC65, 0xCC65, 0xD265, 0xDE65, 0xF265, 0x0065, 0xECEA, 0xCCEA, 0xD2EA, 0xDEEA, 0xF2EA, 0x00EA,
0xEC69, 0xCC69, 0xD269, 0xDE69, 0xF269, 0x0069, 0xEC6F, 0xCC6F, 0xD26F, 0xDE6F, 0xF26F, 0x006F, 0xECF4, 0xCCF4, 0xD2F4,
0xDEF4, 0xF2F4, 0x00F4, 0xECF5, 0xCCF5, 0xD2F5, 0xDEF5, 0xF2F5, 0x00F5, 0xEC75, 0xCC75, 0xD275, 0xDE75, 0xF275, 0x0075,
0xECFD, 0xCCFD, 0xD2FD, 0xDEFD, 0xF2FD, 0x00FD, 0xEC79, 0xCC79, 0xD279, 0xDE79, 0xF279, 0x0079, 0x0064, 0x00F0,
};
// GLOBAL: gl_24900
unsigned short g_vietUpperChars[74] = {
0xEC41, 0xCC41, 0xD241, 0xDE41, 0xF241, 0x0041, 0xECC2, 0xCCC2, 0xD2C2, 0xDEC2, 0xF2C2, 0x00C2, 0xECC3, 0xCCC3, 0xD2C3,
0xDEC3, 0xF2C3, 0x00C3, 0xEC45, 0xCC45, 0xD245, 0xDE45, 0xF245, 0x0045, 0xECCA, 0xCCCA, 0xD2CA, 0xDECA, 0xF2CA, 0x00CA,
0xEC49, 0xCC49, 0xD249, 0xDE49, 0xF249, 0x0049, 0xEC4F, 0xCC4F, 0xD24F, 0xDE4F, 0xF24F, 0x004F, 0xECD4, 0xCCD4, 0xD2D4,
0xDED4, 0xF2D4, 0x00D4, 0xECD5, 0xCCD5, 0xD2D5, 0xDED5, 0xF2D5, 0x00D5, 0xEC55, 0xCC55, 0xD255, 0xDE55, 0xF255, 0x0055,
0xECDD, 0xCCDD, 0xD2DD, 0xDEDD, 0xF2DD, 0x00DD, 0xEC59, 0xCC59, 0xD259, 0xDE59, 0xF259, 0x0059, 0x0044, 0x00D0,
};
// OFFSET: 0x00AFBB20
// FUNCTION: fn_18307
TELEXInputMode::TELEXInputMode() {
}
// OFFSET: 0x00AFBB40
// FUNCTION: fn_18308
int TELEXInputMode::Convert(char key, char vowel, int index) {
if (key == this->m_lastKey) {
this->Reset();
return 1000;
}
int tone = 0;
while (key != g_telexToneKeys[tone] && tone < 5) {
++tone;
}
if (tone < 5) {
if (vowel != 'D' && vowel != 'd') {
if (this->m_toneIndex > 0) {
index = index - this->m_toneIndex + 6;
}
this->m_lastKey = key;
this->m_toneIndex = tone + 1;
return index - 5 + tone;
}
} else if (key == vowel) {
if (vowel != 'U' && vowel != 'u' && vowel != 'Y' && vowel != 'y') {
if (key == 'd' || key == 'D') {
this->m_markKey = key;
this->m_lastKey = key;
return 73;
}
if (this->m_markKey > 0 && (this->m_markKey == 'w' || this->m_markKey == 'W')) {
index -= 12;
}
this->m_markKey = key;
this->m_lastKey = key;
return index + 6;
}
} else if ((key == 'w' || key == 'W') && vowel != 'E' && vowel != 'e' && vowel != 'Y' && vowel != 'y' && vowel != 'D' && vowel != 'd') {
if (this->m_markKey > 0 && this->m_markKey == vowel) {
index -= 6;
}
this->m_markKey = key;
this->m_lastKey = key;
return index + 12;
}
this->Reset();
return -1;
}
// OFFSET: 0x00AFBC80
// FUNCTION: fn_18309
int TELEXInputMode::IsModifierKey(char key, int count, char vowel) {
if (key != vowel && key != 'w' && key != 'W') {
int tone = 0;
while (key != g_telexToneKeys[tone] && tone < 5) {
++tone;
}
if (tone >= 5) {
this->Reset();
return 0;
}
}
return 1;
}
// OFFSET: 0x00AFBCE0
// FUNCTION: fn_18310
void CInputMode::Reset() {
this->m_lastKey = 127;
this->m_toneIndex = -1;
this->m_markKey = -1;
}
// OFFSET: 0x00AFBD00
// FUNCTION: fn_18311
CVietnameseInput::CVietnameseInput() {
std::memset(this->m_keys, 0, sizeof(this->m_keys) + sizeof(this->m_chars));
this->m_state = 1001;
this->m_count = 0;
this->m_mode = nullptr;
}
// OFFSET: 0x00AFBE20
// FUNCTION: fn_18312
int CVietnameseInput::Release() {
if (this->m_mode) {
delete this->m_mode;
}
return 1;
}
// OFFSET: 0x00AFBE40
// FUNCTION: fn_18313
int CVietnameseInput::Compose(char key, unsigned short* output, int* replaced) {
int index;
if (this->m_state == 1002) {
this->m_vowel = key;
this->m_state = 1003;
switch (key) {
case 'A':
case 'a':
index = 5;
break;
case 'E':
case 'e':
index = 23;
break;
case 'I':
case 'i':
index = 35;
break;
case 'O':
case 'o':
index = 41;
break;
case 'U':
case 'u':
index = 59;
break;
case 'Y':
case 'y':
index = 71;
break;
case 'D':
case 'd':
index = 72;
break;
default:
this->m_state = 1001;
index = -1;
break;
}
} else if (this->m_state == 1003) {
index = this->m_mode->Convert(key, this->m_vowel, this->m_index);
if (index == 1000) {
*output = this->m_chars[this->m_count - 2];
this->Reset(0);
return 1001;
}
if (index < 0) {
*output = this->m_chars[this->m_count - 1];
this->Reset(0);
return 1001;
}
*replaced = 0;
} else {
index = reinterpret_cast<int>(output);
}
this->m_index = index;
if (this->m_vowel >= 'a') {
*output = g_vietLowerChars[index];
} else {
*output = g_vietUpperChars[index];
}
if (this->m_count > 9) {
this->m_keys[1] = this->m_keys[8];
this->m_keys[2] = this->m_keys[9];
this->m_chars[1] = this->m_chars[8];
this->m_chars[2] = this->m_chars[9];
this->m_count = 3;
}
this->m_keys[this->m_count] = key;
this->m_chars[this->m_count] = *output;
++this->m_count;
return this->m_state;
}
// OFFSET: 0x00AFC010
// FUNCTION: fn_18314
bool CVietnameseInput::SetMode(int type) {
this->m_type = type;
if (this->m_mode) {
delete this->m_mode;
}
if (type == 0) {
this->m_mode = new VNIInputMode;
} else if (type == 1) {
this->m_mode = new TELEXInputMode;
}
return this->m_mode != nullptr;
}
// OFFSET: 0x00AFC0D0
// FUNCTION: fn_18315
int CVietnameseInput::IsComposeKey(char key) {
if (this->m_state == 1003) {
if (this->m_mode->IsModifierKey(key, this->m_count, this->m_vowel)) {
return 1;
}
this->Reset(0);
}
if (key == 'A' || key == 'a' || key == 'E' || key == 'e' || key == 'I' || key == 'i' || key == 'O' || key == 'o' || key == 'U' || key == 'u' ||
key == 'Y' || key == 'y' || key == 'D' || key == 'd') {
if (this->m_state != 1002) {
this->m_state = 1002;
}
return 1;
}
return 0;
}
// OFFSET: 0x00AFC1A0
// FUNCTION: fn_18316
void CVietnameseInput::Reset(int resetMode) {
if (resetMode && this->m_mode) {
this->m_mode->Reset();
}
std::memset(this->m_keys, 0, sizeof(this->m_keys) + sizeof(this->m_chars));
this->m_state = 1001;
this->m_count = 0;
this->m_vowel = 0;
}
// OFFSET: 0x00AFC1F0
// FUNCTION: fn_18317
VNIInputMode::VNIInputMode() {
}
// OFFSET: 0x00AFC210
// FUNCTION: fn_18318
int VNIInputMode::Convert(char key, char vowel, int index) {
if (key == this->m_lastKey) {
this->Reset();
return 1000;
}
switch (key) {
case '1':
case '2':
case '3':
case '4':
case '5':
if (vowel != 'D' && vowel != 'd') {
if (this->m_toneIndex > 0) {
index = index - this->m_toneIndex + 6;
}
this->m_lastKey = key;
this->m_toneIndex = key - '0';
return index - '6' + key;
}
break;
case '6':
if (vowel == 'A' || vowel == 'a' || vowel == 'E' || vowel == 'e' || vowel == 'O' || vowel == 'o') {
this->m_lastKey = key;
if (this->m_markKey > 0) {
index -= this->m_markKey;
}
this->m_markKey = 6;
return index + 6;
}
break;
case '7':
if (vowel == 'O' || vowel == 'o') {
this->m_lastKey = key;
if (this->m_markKey > 6) {
index -= this->m_markKey;
}
this->m_markKey = 12;
return index + 12;
}
if (vowel == 'U' || vowel == 'u') {
this->m_lastKey = key;
this->m_markKey = 6;
return index + 6;
}
break;
case '8':
if (vowel == 'A' || vowel == 'a') {
this->m_lastKey = key;
if (this->m_markKey > 0) {
index -= this->m_markKey;
}
this->m_markKey = 12;
return index + 12;
}
break;
case '9':
if (vowel == 'D' || vowel == 'd') {
index = 73;
this->m_lastKey = key;
}
return index;
default:
return index;
}
this->Reset();
return -1;
}
// OFFSET: 0x00AFC380
// FUNCTION: fn_18319
int VNIInputMode::IsModifierKey(char key, int count, char vowel) {
if (key >= '1' && key <= '9') {
return 1;
}
this->Reset();
return 0;
}