966 lines
26 KiB
C++
966 lines
26 KiB
C++
// CInput.cpp - part if Multi-Language input class
|
|
//
|
|
// Copyright (C) 2000-2005, Kwon-il Lee
|
|
//
|
|
// Kwon-il Lee
|
|
// zupet@hitel.net
|
|
|
|
#ifndef NOMINMAX
|
|
#define NOMINMAX
|
|
#endif
|
|
|
|
#include "CInput.h"
|
|
#include "CImm.h"
|
|
#include <malloc.h>
|
|
|
|
#include "GameRule.h"
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
#define CHT_IMEFILENAME1 "TINTLGNT.IME" // New Phonetic
|
|
#define CHT_IMEFILENAME2 "CINTLGNT.IME" // New Chang Jie
|
|
#define CHT_IMEFILENAME3 "MSTCIPHA.IME" // Phonetic 5.1
|
|
#define CHS_IMEFILENAME1 "PINTLGNT.IME" // MSPY1.5/2/3
|
|
#define CHS_IMEFILENAME2 "MSSCIPYA.IME" // MSPY3 for OfficeXP
|
|
|
|
#define LANG_CHT MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL)
|
|
#define LANG_CHS MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)
|
|
#define _CHT_HKL ( (HKL)(INT_PTR)0xE0080404 ) // New Phonetic
|
|
#define _CHT_HKL2 ( (HKL)(INT_PTR)0xE0090404 ) // New Chang Jie
|
|
#define _CHS_HKL ( (HKL)(INT_PTR)0xE00E0804 ) // MSPY
|
|
#define MAKEIMEVERSION( major, minor ) \
|
|
( (DWORD)( ( (BYTE)( major ) << 24 ) | ( (BYTE)( minor ) << 16 ) ) )
|
|
|
|
#define IMEID_CHT_VER42 ( LANG_CHT | MAKEIMEVERSION( 4, 2 ) ) // New(Phonetic/ChanJie)IME98 : 4.2.x.x // Win98
|
|
#define IMEID_CHT_VER43 ( LANG_CHT | MAKEIMEVERSION( 4, 3 ) ) // New(Phonetic/ChanJie)IME98a : 4.3.x.x // Win2k
|
|
#define IMEID_CHT_VER44 ( LANG_CHT | MAKEIMEVERSION( 4, 4 ) ) // New ChanJie IME98b : 4.4.x.x // WinXP
|
|
#define IMEID_CHT_VER50 ( LANG_CHT | MAKEIMEVERSION( 5, 0 ) ) // New(Phonetic/ChanJie)IME5.0 : 5.0.x.x // WinME
|
|
#define IMEID_CHT_VER51 ( LANG_CHT | MAKEIMEVERSION( 5, 1 ) ) // New(Phonetic/ChanJie)IME5.1 : 5.1.x.x // IME2002(w/OfficeXP)
|
|
#define IMEID_CHT_VER52 ( LANG_CHT | MAKEIMEVERSION( 5, 2 ) ) // New(Phonetic/ChanJie)IME5.2 : 5.2.x.x // IME2002a(w/Whistler)
|
|
#define IMEID_CHT_VER60 ( LANG_CHT | MAKEIMEVERSION( 6, 0 ) ) // New(Phonetic/ChanJie)IME6.0 : 6.0.x.x // IME XP(w/WinXP SP1)
|
|
#define IMEID_CHS_VER41 ( LANG_CHS | MAKEIMEVERSION( 4, 1 ) ) // MSPY1.5 // SCIME97 or MSPY1.5 (w/Win98, Office97)
|
|
#define IMEID_CHS_VER42 ( LANG_CHS | MAKEIMEVERSION( 4, 2 ) ) // MSPY2 // Win2k/WinME
|
|
#define IMEID_CHS_VER53 ( LANG_CHS | MAKEIMEVERSION( 5, 3 ) ) // MSPY3 // WinXP
|
|
|
|
enum { INDICATOR_NON_IME, INDICATOR_CHS, INDICATOR_CHT, INDICATOR_KOREAN, INDICATOR_JAPANESE };
|
|
enum { IMEUI_STATE_OFF, IMEUI_STATE_ON, IMEUI_STATE_ENGLISH };
|
|
|
|
#define LCID_INVARIANT MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT)
|
|
|
|
wchar_t g_aszIndicator[5][3] =
|
|
{
|
|
L"En", //INDICATOR_NON_IME
|
|
L"\x7B80", //INDICATOR_CHS
|
|
L"\x7E41", //INDICATOR_CHT
|
|
L"\xAC00", //INDICATOR_KOREAN
|
|
L"\x3042", //INDICATOR_JAPANESE
|
|
};
|
|
|
|
static CIMM g_imm;
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
int ConvertString(UINT codePage, const wchar_t* wText, int wLen, char* text, int len)
|
|
{
|
|
//AziaMafia Fix CODEPAGE CP_UTF8 // codePage
|
|
if(text == 0) {
|
|
return WideCharToMultiByte(codePage, 0, wText, wLen, NULL, 0, NULL, NULL);
|
|
} else {
|
|
int tLen = WideCharToMultiByte(codePage, 0, wText, wLen, NULL, 0, NULL, NULL);
|
|
|
|
if(tLen > len) {
|
|
return 0;
|
|
} else {
|
|
return WideCharToMultiByte(codePage, 0, wText, wLen, text, tLen, NULL, NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/ /* Begin of CInput */
|
|
CInput::CInput()
|
|
: m_ulStart(0)
|
|
, m_ulEnd(0)
|
|
, m_hDllIme(NULL)
|
|
, m_ImeState(IMEUI_STATE_OFF)
|
|
, m_bOnlyNum(false)
|
|
, m_bSpaceLimit(false)
|
|
, m_isEndComposing(false)
|
|
{
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
CInput::~CInput()
|
|
{
|
|
if( m_hDllIme )
|
|
FreeLibrary( m_hDllIme );
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
void CInput::InitInput()
|
|
{
|
|
g_imm.Init();
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
void CInput::OnInputLanguageChange(HWND hWnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
m_hkl = (HKL)lParam;
|
|
m_langId = LOWORD(m_hkl);
|
|
|
|
m_codePage = GetCodePageFromLang(m_langId);
|
|
|
|
m_input.resize(0);
|
|
|
|
/* Check Property */
|
|
DWORD property = ImmGetProperty(GetKeyboardLayout(0), IGP_PROPERTY);
|
|
|
|
m_bUnicodeIME = (property & IME_PROP_UNICODE) ? true : false;
|
|
|
|
//중국 관련, 일부 IME 프로그램이 Unicode 임에도, 위의 값이 false 임;
|
|
if( !m_bUnicodeIME )
|
|
{
|
|
char szTmp[1024] = {0,};
|
|
if ( ImmGetIMEFileNameA( m_hkl, szTmp, _countof(szTmp) - 1 ) )
|
|
{
|
|
if (stricmp( szTmp,"UNISPIM5.IME" ) == 0 ||
|
|
stricmp( szTmp,"winabc.ime" ) == 0 ||
|
|
stricmp( szTmp,"WNWB.IME" ) == 0 )
|
|
m_bUnicodeIME = true;
|
|
}
|
|
}
|
|
|
|
/* Update Indicator */
|
|
CheckToggleState(hWnd);
|
|
|
|
/* Update m_dwId[] */
|
|
GetImeId();
|
|
|
|
/* Bind Proc */
|
|
SetupImeApi(hWnd);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
bool CInput::OnComposition(HWND hWnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HIMC hImc;
|
|
if(lParam&GCS_COMPSTR) {
|
|
hImc = ImmGetContext(hWnd);
|
|
if(hImc) {
|
|
|
|
int tempSize = ImmGetCompositionStringW(hImc, GCS_COMPSTR, NULL, 0);
|
|
|
|
wchar_t* temp = (wchar_t*)alloca(tempSize);
|
|
|
|
ImmGetCompositionStringW(hImc, GCS_COMPSTR, temp, tempSize);
|
|
|
|
m_comp.assign(temp, temp+tempSize/sizeof(wchar_t));
|
|
|
|
ImmReleaseContext(hWnd, hImc);
|
|
|
|
m_isEndComposing = false; /// 2012.02.16 - prodongi
|
|
}
|
|
}
|
|
if(lParam&GCS_RESULTSTR) {
|
|
hImc = ImmGetContext(hWnd);
|
|
if(hImc) {
|
|
|
|
int tempSize = ImmGetCompositionStringW(hImc, GCS_RESULTSTR, NULL, 0);
|
|
|
|
wchar_t* temp = (wchar_t*)alloca(tempSize);
|
|
|
|
ImmGetCompositionStringW(hImc, GCS_RESULTSTR, temp, tempSize);
|
|
if(IsSpaceLimit()) // 2011. 11. 3 - marine ime를 사용하여 입력하는 경우 space키를 막을 때..
|
|
{
|
|
wchar_t* space = (wchar_t*)alloca(tempSize);
|
|
*space = L' ';
|
|
|
|
if(*(temp+1) == *space)
|
|
m_input.append(temp, temp+(tempSize/2)/sizeof(wchar_t));
|
|
else
|
|
m_input.append(temp, temp+tempSize/sizeof(wchar_t));
|
|
}
|
|
else
|
|
m_input.append(temp, temp+tempSize/sizeof(wchar_t));
|
|
|
|
ImmReleaseContext(hWnd, hImc);
|
|
|
|
m_isEndComposing = true; /// 2012.02.16 - prodongi
|
|
}
|
|
}
|
|
if(lParam&GCS_COMPATTR) {
|
|
hImc = ImmGetContext(hWnd);
|
|
if(hImc) {
|
|
|
|
int tempSize = ImmGetCompositionStringW(hImc, GCS_COMPATTR, NULL, 0);
|
|
|
|
BYTE* temp = (BYTE*)alloca(tempSize);
|
|
|
|
ImmGetCompositionStringW(hImc, GCS_COMPATTR, temp, tempSize);
|
|
|
|
int start;
|
|
int end;
|
|
for(start=0; start<tempSize; ++start) if(temp[start]==ATTR_TARGET_CONVERTED || temp[start]==ATTR_TARGET_NOTCONVERTED) break;
|
|
for(end=start; end<tempSize; ++end) if(temp[end]!=temp[start]) break;
|
|
|
|
m_ulStart = start;
|
|
m_ulEnd = end;
|
|
|
|
ImmReleaseContext(hWnd, hImc);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
bool CInput::OnEndComposition(HWND hWnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
m_comp.resize(0);
|
|
m_ulStart = m_ulEnd = 0;
|
|
m_reading.resize(0);
|
|
|
|
return true;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
bool CInput::OnNotify(HWND hWnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HIMC hImc;
|
|
|
|
switch (wParam)
|
|
{
|
|
case IMN_OPENCANDIDATE:
|
|
case IMN_CHANGECANDIDATE:
|
|
hImc = ImmGetContext(hWnd);
|
|
if(hImc) {
|
|
|
|
m_reading.resize(0);
|
|
|
|
int candidateLen = ImmGetCandidateListW(hImc, 0, NULL, 0);
|
|
|
|
if(candidateLen > 0) {
|
|
|
|
m_candidate.resize(candidateLen);
|
|
|
|
ImmGetCandidateListW(hImc, 0, (CANDIDATELIST*)&m_candidate[0], candidateLen);
|
|
|
|
CANDIDATELIST* pList = ( CANDIDATELIST* )&m_candidate[0];
|
|
if( pList )
|
|
{
|
|
static DWORD dwOldSelection = 0;
|
|
if( dwOldSelection != pList->dwSelection )
|
|
{
|
|
pList->dwPageStart = pList->dwSelection;
|
|
dwOldSelection = pList->dwSelection;
|
|
}
|
|
}
|
|
}
|
|
|
|
ImmReleaseContext(hWnd, hImc);
|
|
}
|
|
return true;
|
|
|
|
case IMN_CLOSECANDIDATE:
|
|
m_candidate.resize(0);
|
|
return true;
|
|
|
|
case IMN_SETCONVERSIONMODE:
|
|
case IMN_SETOPENSTATUS:
|
|
CheckToggleState(hWnd);
|
|
return false;
|
|
|
|
case IMN_SETCOMPOSITIONWINDOW:
|
|
return true;
|
|
|
|
case IMN_PRIVATE:
|
|
GetPrivateReadingString(hWnd);
|
|
|
|
// Trap some messages to hide reading window
|
|
switch( m_dwId[0] )
|
|
{
|
|
case IMEID_CHT_VER42:
|
|
case IMEID_CHT_VER43:
|
|
case IMEID_CHT_VER44:
|
|
case IMEID_CHS_VER41:
|
|
case IMEID_CHS_VER42:
|
|
if((lParam==1)||(lParam==2)) return true;
|
|
break;
|
|
|
|
case IMEID_CHT_VER50:
|
|
case IMEID_CHT_VER51:
|
|
case IMEID_CHT_VER52:
|
|
case IMEID_CHT_VER60:
|
|
case IMEID_CHS_VER53:
|
|
if((lParam==16)||(lParam==17)||(lParam==26)||(lParam==27)||(lParam==28)) return true;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
bool CInput::OnChar(HWND hWnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch(wParam)
|
|
{
|
|
case '\r':
|
|
case '\n':
|
|
m_input.resize(0);
|
|
break;
|
|
case '\b':
|
|
if(m_input.size()) m_input.resize(m_input.size() - 1);
|
|
break;
|
|
case '\t':
|
|
case 27:
|
|
break;
|
|
default:
|
|
if(wParam > 31) {
|
|
if( m_bSpaceLimit )
|
|
if(wParam == 32) // space bar
|
|
return false;
|
|
|
|
if( m_bOnlyNum )
|
|
if( 48 > wParam || wParam > 57 )
|
|
return false;
|
|
|
|
wchar_t temp;
|
|
// AziaMafia CP_UTF8
|
|
//MultiByteToWideChar(m_codePage, 0, (char*)&wParam, 1, &temp, 1);
|
|
MultiByteToWideChar(m_codePage, 0, (char*)&wParam, 1, &temp, 1);
|
|
|
|
m_input.push_back(temp);
|
|
}
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/// 2012.02.16 - prodongi
|
|
void CInput::OnKeyDown(WPARAM wParam)
|
|
{
|
|
switch (wParam)
|
|
{
|
|
case VK_RETURN:
|
|
m_isEndComposing = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
int CInput::GetInput(char* text, int len)
|
|
{
|
|
return ConvertString(m_codePage, m_input.c_str(), m_input.size(), text, len);
|
|
}
|
|
|
|
int CInput::GetInput(wchar_t* text, int len)
|
|
{
|
|
if( len < 0 ) return 0;
|
|
|
|
int copy_size = m_input.size();
|
|
if( copy_size > len ) copy_size = len;
|
|
|
|
memcpy( text, m_input.c_str(), (copy_size)*2 );
|
|
if( copy_size == len )
|
|
{
|
|
text[copy_size] = 0;
|
|
--copy_size;
|
|
}
|
|
|
|
return copy_size;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
int CInput::GetComp(char* text, int len)
|
|
{
|
|
return ConvertString(m_codePage, m_comp.c_str(), m_comp.size(), text, len);
|
|
}
|
|
|
|
int CInput::GetComp(wchar_t* text, int len)
|
|
{
|
|
if( len < 0 ) return 0;
|
|
|
|
int copy_size = m_comp.size();
|
|
if( copy_size > len ) copy_size = len;
|
|
|
|
memcpy( text, m_comp.c_str(), (copy_size+1)*2);
|
|
if( copy_size == len )
|
|
{
|
|
text[copy_size] = 0;
|
|
--copy_size;
|
|
}
|
|
|
|
return copy_size;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
int CInput::GetReading(char* text, int len)
|
|
{
|
|
return ConvertString(m_codePage, m_reading.c_str(), m_reading.size(), text, len);
|
|
}
|
|
|
|
int CInput::GetReading(wchar_t* text, int len)
|
|
{
|
|
if( len < 0 ) return 0;
|
|
|
|
int copy_size = m_reading.size();
|
|
if( copy_size > len ) copy_size = len;
|
|
|
|
memcpy( text, m_reading.c_str(), copy_size*2 );
|
|
if( copy_size == len )
|
|
{
|
|
text[copy_size] = 0;
|
|
--copy_size;
|
|
}
|
|
|
|
return copy_size;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
int CInput::GetCandidate(DWORD index, char* text, int len)
|
|
{
|
|
if(m_candidate.empty()) {
|
|
return 0;
|
|
} else {
|
|
CANDIDATELIST* candidateList = (CANDIDATELIST*)&m_candidate[0];
|
|
|
|
if(index >= candidateList->dwCount) {
|
|
return 0;
|
|
} else {
|
|
|
|
if(m_bUnicodeIME) {
|
|
|
|
wchar_t* wText = (wchar_t*)(&m_candidate[0] + candidateList->dwOffset[index]);
|
|
|
|
return ConvertString(m_codePage, wText, wcslen(wText), text, len);
|
|
|
|
} else {
|
|
|
|
char* temp = (char*)(&m_candidate[0] + candidateList->dwOffset[index]);
|
|
|
|
if(text == 0) {
|
|
return strlen(temp);
|
|
} else {
|
|
int tempLen = strlen(temp);
|
|
|
|
if(len < tempLen) {
|
|
return 0;
|
|
} else {
|
|
memcpy(text, temp, tempLen);
|
|
return tempLen;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
int CInput::GetCandidateCount()
|
|
{
|
|
if(m_candidate.empty()) {
|
|
return 0;
|
|
} else {
|
|
return ((CANDIDATELIST*)&m_candidate[0])->dwCount;
|
|
}
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
int CInput::GetCandidateSelection()
|
|
{
|
|
if(m_candidate.empty()) {
|
|
return 0;
|
|
} else {
|
|
if(PRIMARYLANGID(m_langId) == LANG_KOREAN)
|
|
return ((CANDIDATELIST*)&m_candidate[0])->dwCount;
|
|
else
|
|
return ((CANDIDATELIST*)&m_candidate[0])->dwSelection;
|
|
}
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
int CInput::GetCandidatePageSize()
|
|
{
|
|
if(m_candidate.empty()) {
|
|
return 0;
|
|
} else {
|
|
return ((CANDIDATELIST*)&m_candidate[0])->dwPageSize;
|
|
}
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
int CInput::GetCandidatePageStart()
|
|
{
|
|
if(m_candidate.empty()) {
|
|
return 0;
|
|
} else {
|
|
return ((CANDIDATELIST*)&m_candidate[0])->dwPageStart;
|
|
}
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
void CInput::GetUnderLine(int* start, int* end)
|
|
{
|
|
*start = WideCharToMultiByte(m_codePage, 0, m_comp.c_str(), m_ulStart, NULL, 0, NULL, NULL);
|
|
*end = WideCharToMultiByte(m_codePage, 0, m_comp.c_str(), m_ulEnd, NULL, 0, NULL, NULL);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
void CInput::GetImeId()
|
|
{
|
|
char szTmp[1024];
|
|
|
|
m_dwId[0] = m_dwId[1] = 0;
|
|
|
|
if(!((m_hkl==_CHT_HKL) || (m_hkl==_CHT_HKL2) || (m_hkl==_CHS_HKL)))
|
|
return;
|
|
|
|
if ( !ImmGetIMEFileNameA( m_hkl, szTmp, _countof(szTmp) - 1 ) )
|
|
return;
|
|
|
|
if ( !_GetReadingString ) {
|
|
|
|
if( ( CompareStringA( LCID_INVARIANT, NORM_IGNORECASE, szTmp, -1, CHT_IMEFILENAME1, -1 ) != CSTR_EQUAL ) &&
|
|
( CompareStringA( LCID_INVARIANT, NORM_IGNORECASE, szTmp, -1, CHT_IMEFILENAME2, -1 ) != CSTR_EQUAL ) &&
|
|
( CompareStringA( LCID_INVARIANT, NORM_IGNORECASE, szTmp, -1, CHT_IMEFILENAME3, -1 ) != CSTR_EQUAL ) &&
|
|
( CompareStringA( LCID_INVARIANT, NORM_IGNORECASE, szTmp, -1, CHS_IMEFILENAME1, -1 ) != CSTR_EQUAL ) &&
|
|
( CompareStringA( LCID_INVARIANT, NORM_IGNORECASE, szTmp, -1, CHS_IMEFILENAME2, -1 ) != CSTR_EQUAL ) ) {
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
DWORD dwVerHandle;
|
|
DWORD dwVerSize = GetFileVersionInfoSize( szTmp, &dwVerHandle );
|
|
|
|
if( dwVerSize ) {
|
|
|
|
LPVOID lpVerBuffer = alloca( dwVerSize );
|
|
|
|
if( GetFileVersionInfo( szTmp, dwVerHandle, dwVerSize, lpVerBuffer ) ) {
|
|
|
|
LPVOID lpVerData;
|
|
UINT cbVerData;
|
|
|
|
if( VerQueryValue( lpVerBuffer, "\\", &lpVerData, &cbVerData ) ) {
|
|
|
|
DWORD dwVer = ( (VS_FIXEDFILEINFO*)lpVerData )->dwFileVersionMS;
|
|
dwVer = ( dwVer & 0x00ff0000 ) << 8 | ( dwVer & 0x000000ff ) << 16;
|
|
if( _GetReadingString
|
|
||
|
|
( m_langId == LANG_CHT &&
|
|
( dwVer == MAKEIMEVERSION(4, 2) ||
|
|
dwVer == MAKEIMEVERSION(4, 3) ||
|
|
dwVer == MAKEIMEVERSION(4, 4) ||
|
|
dwVer == MAKEIMEVERSION(5, 0) ||
|
|
dwVer == MAKEIMEVERSION(5, 1) ||
|
|
dwVer == MAKEIMEVERSION(5, 2) ||
|
|
dwVer == MAKEIMEVERSION(6, 0) ) )
|
|
||
|
|
( m_langId == LANG_CHS &&
|
|
( dwVer == MAKEIMEVERSION(4, 1) ||
|
|
dwVer == MAKEIMEVERSION(4, 2) ||
|
|
dwVer == MAKEIMEVERSION(5, 3) ) ) ) {
|
|
|
|
m_dwId[0] = dwVer | m_langId;
|
|
m_dwId[1] = ( (VS_FIXEDFILEINFO*)lpVerData )->dwFileVersionLS;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
void CInput::SetupImeApi(HWND hWnd)
|
|
{
|
|
char szImeFile[MAX_PATH + 1];
|
|
|
|
_GetReadingString = NULL;
|
|
_ShowReadingWindow = NULL;
|
|
|
|
if( ImmGetIMEFileNameA( m_hkl, szImeFile, _countof(szImeFile) - 1 ) != 0 ) {
|
|
|
|
if( m_hDllIme ) FreeLibrary( m_hDllIme );
|
|
|
|
m_hDllIme = LoadLibraryA( szImeFile );
|
|
|
|
if ( m_hDllIme ) {
|
|
_GetReadingString = (UINT (WINAPI*)(HIMC, UINT, LPWSTR, PINT, BOOL*, PUINT))
|
|
( GetProcAddress( m_hDllIme, "GetReadingString" ) );
|
|
_ShowReadingWindow =(BOOL (WINAPI*)(HIMC, BOOL))
|
|
( GetProcAddress( m_hDllIme, "ShowReadingWindow" ) );
|
|
|
|
if( _ShowReadingWindow ) {
|
|
HIMC hImc = ImmGetContext(hWnd);
|
|
if(hImc) {
|
|
_ShowReadingWindow( hImc, false );
|
|
ImmReleaseContext(hWnd, hImc);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
bool CInput::GetReadingWindowOrientation()
|
|
{
|
|
bool bHorizontalReading = ( m_hkl == _CHS_HKL ) || ( m_hkl == _CHT_HKL2 ) || ( m_dwId[0] == 0 );
|
|
if( !bHorizontalReading && ( m_dwId[0] & 0x0000FFFF ) == LANG_CHT )
|
|
{
|
|
char szRegPath[MAX_PATH];
|
|
HKEY hKey;
|
|
DWORD dwVer = m_dwId[0] & 0xFFFF0000;
|
|
strcpy( szRegPath, "software\\microsoft\\windows\\currentversion\\" );
|
|
strcat( szRegPath, ( dwVer >= MAKEIMEVERSION( 5, 1 ) ) ? "MSTCIPH" : "TINTLGNT" );
|
|
LONG lRc = RegOpenKeyExA( HKEY_CURRENT_USER, szRegPath, 0, KEY_READ, &hKey );
|
|
if (lRc == ERROR_SUCCESS)
|
|
{
|
|
DWORD dwSize = sizeof(DWORD), dwMapping, dwType;
|
|
lRc = RegQueryValueExA( hKey, "Keyboard Mapping", NULL, &dwType, (PBYTE)&dwMapping, &dwSize );
|
|
if (lRc == ERROR_SUCCESS)
|
|
{
|
|
if ( ( dwVer <= MAKEIMEVERSION( 5, 0 ) &&
|
|
( (BYTE)dwMapping == 0x22 || (BYTE)dwMapping == 0x23 ) )
|
|
||
|
|
( ( dwVer == MAKEIMEVERSION( 5, 1 ) || dwVer == MAKEIMEVERSION( 5, 2 ) ) &&
|
|
(BYTE)dwMapping >= 0x22 && (BYTE)dwMapping <= 0x24 )
|
|
)
|
|
{
|
|
bHorizontalReading = true;
|
|
}
|
|
}
|
|
RegCloseKey( hKey );
|
|
}
|
|
}
|
|
|
|
return bHorizontalReading;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
void CInput::GetPrivateReadingString(HWND hWnd)
|
|
{
|
|
if( !m_dwId[0] ) {
|
|
m_reading.resize(0);
|
|
return;
|
|
}
|
|
|
|
HIMC hImc = ImmGetContext(hWnd);
|
|
if( !hImc ) {
|
|
m_reading.resize(0);
|
|
return;
|
|
}
|
|
|
|
|
|
DWORD dwErr = 0;
|
|
|
|
if( _GetReadingString ) {
|
|
|
|
UINT uMaxUiLen;
|
|
BOOL bVertical;
|
|
// Obtain the reading string size
|
|
int wstrLen = _GetReadingString( hImc, 0, NULL, (PINT)&dwErr, &bVertical, &uMaxUiLen );
|
|
|
|
if( wstrLen == 0 ) {
|
|
m_reading.resize(0);
|
|
} else {
|
|
wchar_t *wstr = (wchar_t*)alloca(sizeof(wchar_t) * wstrLen);
|
|
_GetReadingString( hImc, wstrLen, wstr, (PINT)&dwErr, &bVertical, &uMaxUiLen );
|
|
m_reading.assign(wstr, wstr+wstrLen);
|
|
}
|
|
|
|
m_bVerticalReading = bVertical ? true : false;
|
|
|
|
ImmReleaseContext(hWnd, hImc);
|
|
|
|
} else {
|
|
|
|
// IMEs that doesn't implement Reading String API
|
|
wchar_t* temp;
|
|
DWORD tempLen;
|
|
bool bUnicodeIme = false;
|
|
INPUTCONTEXT *lpIC = g_imm.LockIMC(hImc);
|
|
|
|
if(lpIC == NULL) {
|
|
temp = NULL;
|
|
tempLen = 0;
|
|
} else {
|
|
LPBYTE p = 0;
|
|
switch( m_dwId[0] )
|
|
{
|
|
case IMEID_CHT_VER42: // New(Phonetic/ChanJie)IME98 : 4.2.x.x // Win98
|
|
case IMEID_CHT_VER43: // New(Phonetic/ChanJie)IME98a : 4.3.x.x // WinMe, Win2k
|
|
case IMEID_CHT_VER44: // New ChanJie IME98b : 4.4.x.x // WinXP
|
|
p = *(LPBYTE *)((LPBYTE)g_imm.LockIMCC( lpIC->hPrivate ) + 24 );
|
|
if( !p ) break;
|
|
tempLen = *(DWORD *)( p + 7 * 4 + 32 * 4 );
|
|
dwErr = *(DWORD *)( p + 8 * 4 + 32 * 4 );
|
|
temp = (wchar_t *)( p + 56 );
|
|
bUnicodeIme = true;
|
|
break;
|
|
|
|
case IMEID_CHT_VER50: // 5.0.x.x // WinME
|
|
p = *(LPBYTE *)( (LPBYTE)g_imm.LockIMCC( lpIC->hPrivate ) + 3 * 4 );
|
|
if( !p ) break;
|
|
p = *(LPBYTE *)( (LPBYTE)p + 1*4 + 5*4 + 4*2 );
|
|
if( !p ) break;
|
|
tempLen = *(DWORD *)(p + 1*4 + (16*2+2*4) + 5*4 + 16);
|
|
dwErr = *(DWORD *)(p + 1*4 + (16*2+2*4) + 5*4 + 16 + 1*4);
|
|
temp = (wchar_t *)(p + 1*4 + (16*2+2*4) + 5*4);
|
|
bUnicodeIme = false;
|
|
break;
|
|
|
|
case IMEID_CHT_VER51: // 5.1.x.x // IME2002(w/OfficeXP)
|
|
case IMEID_CHT_VER52: // 5.2.x.x // (w/whistler)
|
|
case IMEID_CHS_VER53: // 5.3.x.x // SCIME2k or MSPY3 (w/OfficeXP and Whistler)
|
|
p = *(LPBYTE *)((LPBYTE)g_imm.LockIMCC( lpIC->hPrivate ) + 4);
|
|
if( !p ) break;
|
|
p = *(LPBYTE *)((LPBYTE)p + 1*4 + 5*4);
|
|
if( !p ) break;
|
|
tempLen = *(DWORD *)(p + 1*4 + (16*2+2*4) + 5*4 + 16 * 2);
|
|
dwErr = *(DWORD *)(p + 1*4 + (16*2+2*4) + 5*4 + 16 * 2 + 1*4);
|
|
temp = (wchar_t *) (p + 1*4 + (16*2+2*4) + 5*4);
|
|
bUnicodeIme = true;
|
|
break;
|
|
|
|
// the code tested only with Win 98 SE (MSPY 1.5/ ver 4.1.0.21)
|
|
case IMEID_CHS_VER41:
|
|
{
|
|
int nOffset;
|
|
nOffset = ( m_dwId[1] >= 0x00000002 ) ? 8 : 7;
|
|
|
|
p = *(LPBYTE *)((LPBYTE)g_imm.LockIMCC( lpIC->hPrivate ) + nOffset * 4);
|
|
if( !p ) break;
|
|
tempLen = *(DWORD *)(p + 7*4 + 16*2*4);
|
|
dwErr = *(DWORD *)(p + 8*4 + 16*2*4);
|
|
dwErr = std::min( dwErr, tempLen );
|
|
temp = (wchar_t *)(p + 6*4 + 16*2*1);
|
|
bUnicodeIme = true;
|
|
}
|
|
break;
|
|
|
|
case IMEID_CHS_VER42: // 4.2.x.x // SCIME98 or MSPY2 (w/Office2k, Win2k, WinME, etc)
|
|
{
|
|
OSVERSIONINFOA osi;
|
|
osi.dwOSVersionInfoSize = sizeof(osi);
|
|
GetVersionExA( &osi );
|
|
|
|
int nTcharSize = ( osi.dwPlatformId == VER_PLATFORM_WIN32_NT ) ? sizeof(wchar_t) : sizeof(char);
|
|
p = *(LPBYTE *)((LPBYTE)g_imm.LockIMCC( lpIC->hPrivate ) + 1*4 + 1*4 + 6*4);
|
|
if( !p ) break;
|
|
tempLen = *(DWORD *)(p + 1*4 + (16*2+2*4) + 5*4 + 16 * nTcharSize);
|
|
dwErr = *(DWORD *)(p + 1*4 + (16*2+2*4) + 5*4 + 16 * nTcharSize + 1*4);
|
|
temp = (wchar_t *) (p + 1*4 + (16*2+2*4) + 5*4);
|
|
bUnicodeIme = ( osi.dwPlatformId == VER_PLATFORM_WIN32_NT ) ? true : false;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
temp = NULL;
|
|
tempLen = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(tempLen == 0) {
|
|
m_reading.resize(0);
|
|
} else {
|
|
if( bUnicodeIme ) {
|
|
m_reading.assign(temp, tempLen);
|
|
} else {
|
|
// AziaMafia CP_UTF8
|
|
int wstrLen = MultiByteToWideChar(m_codePage, 0, (char*)temp, tempLen, NULL, 0);
|
|
wchar_t* wstr = (wchar_t*)alloca(sizeof(wchar_t)*wstrLen);
|
|
MultiByteToWideChar(m_codePage, 0, (char*)temp, tempLen, wstr, wstrLen);
|
|
m_reading.assign(wstr, wstrLen);
|
|
|
|
}
|
|
}
|
|
|
|
g_imm.UnlockIMCC(lpIC->hPrivate);
|
|
g_imm.UnlockIMC(hImc);
|
|
|
|
m_bVerticalReading = !GetReadingWindowOrientation();
|
|
}
|
|
|
|
ImmReleaseContext(hWnd, hImc);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
void CInput::CheckToggleState(HWND hWnd)
|
|
{
|
|
/* Update Indicator */
|
|
switch (PRIMARYLANGID(m_langId))
|
|
{
|
|
case LANG_KOREAN:
|
|
m_bVerticalCandidate = false;
|
|
m_wszCurrIndicator = g_aszIndicator[INDICATOR_KOREAN];
|
|
break;
|
|
|
|
case LANG_JAPANESE:
|
|
m_bVerticalCandidate = true;
|
|
m_wszCurrIndicator = g_aszIndicator[INDICATOR_JAPANESE];
|
|
break;
|
|
|
|
case LANG_CHINESE:
|
|
{
|
|
m_bVerticalCandidate = true;
|
|
WORD lang = SUBLANGID(m_langId);
|
|
switch( lang )
|
|
{
|
|
case SUBLANG_CHINESE_SIMPLIFIED:
|
|
m_bVerticalCandidate = m_dwId[0] == 0;
|
|
m_wszCurrIndicator = g_aszIndicator[INDICATOR_CHS];
|
|
break;
|
|
|
|
case SUBLANG_CHINESE_TRADITIONAL:
|
|
m_wszCurrIndicator = g_aszIndicator[INDICATOR_CHT];
|
|
break;
|
|
|
|
default:
|
|
m_wszCurrIndicator = g_aszIndicator[INDICATOR_NON_IME];
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
m_wszCurrIndicator = g_aszIndicator[INDICATOR_NON_IME];
|
|
break;
|
|
}
|
|
|
|
if( m_wszCurrIndicator == g_aszIndicator[INDICATOR_NON_IME] )
|
|
{
|
|
char szLang[10];
|
|
GetLocaleInfoA( MAKELCID( m_langId, SORT_DEFAULT ), LOCALE_SABBREVLANGNAME, szLang, _countof(szLang) );
|
|
m_wszCurrIndicator[0] = szLang[0];
|
|
m_wszCurrIndicator[1] = towlower( szLang[1] );
|
|
}
|
|
|
|
|
|
|
|
/* Check Toggle State */
|
|
bool bIme = ImmIsIME( m_hkl ) != 0;
|
|
|
|
HIMC hImc = ImmGetContext(hWnd);
|
|
if( hImc ) {
|
|
|
|
if( ( PRIMARYLANGID(m_langId) == LANG_CHINESE ) && bIme ) {
|
|
|
|
DWORD dwConvMode, dwSentMode;
|
|
ImmGetConversionStatus(hImc, &dwConvMode, &dwSentMode);
|
|
m_ImeState = ( dwConvMode & IME_CMODE_NATIVE ) ? IMEUI_STATE_ON : IMEUI_STATE_ENGLISH;
|
|
|
|
} else {
|
|
|
|
m_ImeState = ( bIme && ImmGetOpenStatus(hImc) != 0 ) ? IMEUI_STATE_ON : IMEUI_STATE_OFF;
|
|
}
|
|
ImmReleaseContext(hWnd, hImc);
|
|
|
|
} else {
|
|
|
|
m_ImeState = IMEUI_STATE_OFF;
|
|
}
|
|
}
|
|
|
|
int GetCharsetFromLang( LANGID langid )
|
|
{
|
|
switch( PRIMARYLANGID(langid) )
|
|
{
|
|
case LANG_JAPANESE:
|
|
return SHIFTJIS_CHARSET;
|
|
case LANG_KOREAN:
|
|
return HANGEUL_CHARSET;
|
|
case LANG_CHINESE:
|
|
switch( SUBLANGID(langid) )
|
|
{
|
|
case SUBLANG_CHINESE_SIMPLIFIED:
|
|
return GB2312_CHARSET;
|
|
case SUBLANG_CHINESE_TRADITIONAL:
|
|
return CHINESEBIG5_CHARSET;
|
|
default:
|
|
return ANSI_CHARSET;
|
|
}
|
|
case LANG_GREEK:
|
|
return GREEK_CHARSET;
|
|
case LANG_TURKISH:
|
|
return TURKISH_CHARSET;
|
|
case LANG_HEBREW:
|
|
return HEBREW_CHARSET;
|
|
case LANG_ARABIC:
|
|
return ARABIC_CHARSET;
|
|
case LANG_ESTONIAN:
|
|
case LANG_LATVIAN:
|
|
case LANG_LITHUANIAN:
|
|
return BALTIC_CHARSET;
|
|
case LANG_THAI:
|
|
return THAI_CHARSET;
|
|
case LANG_CZECH:
|
|
case LANG_HUNGARIAN:
|
|
case LANG_POLISH:
|
|
case LANG_CROATIAN:
|
|
case LANG_MACEDONIAN:
|
|
case LANG_ROMANIAN:
|
|
case LANG_SLOVAK:
|
|
case LANG_SLOVENIAN:
|
|
return EASTEUROPE_CHARSET;
|
|
case LANG_RUSSIAN:
|
|
case LANG_BELARUSIAN:
|
|
case LANG_BULGARIAN:
|
|
case LANG_UKRAINIAN:
|
|
return RUSSIAN_CHARSET;
|
|
case LANG_VIETNAMESE:
|
|
return VIETNAMESE_CHARSET;
|
|
default:
|
|
return ANSI_CHARSET;
|
|
}
|
|
}
|
|
|
|
int GetCodePageFromCharset( int charset )
|
|
{
|
|
switch( charset )
|
|
{
|
|
case SHIFTJIS_CHARSET:
|
|
return 932;
|
|
case HANGUL_CHARSET:
|
|
return 949;
|
|
case GB2312_CHARSET:
|
|
if(GameRule::GetCurrentLocalBitSet() == GameRule::LOCAL_BITSET::HK)
|
|
{
|
|
return 950;
|
|
}
|
|
else
|
|
{
|
|
return 936;
|
|
}
|
|
case CHINESEBIG5_CHARSET:
|
|
return 950;
|
|
case GREEK_CHARSET:
|
|
return 1253;
|
|
case TURKISH_CHARSET:
|
|
return 1254;
|
|
case HEBREW_CHARSET:
|
|
return 1255;
|
|
case ARABIC_CHARSET:
|
|
return 1256;
|
|
case BALTIC_CHARSET:
|
|
return 1257;
|
|
case THAI_CHARSET:
|
|
return 874;
|
|
case EASTEUROPE_CHARSET:
|
|
return 1250;
|
|
case VIETNAMESE_CHARSET:
|
|
return 1258;
|
|
case RUSSIAN_CHARSET:
|
|
return 1251;
|
|
|
|
default:
|
|
return 1252;
|
|
}
|
|
}
|
|
|
|
int GetCodePageFromLang( LANGID langid )
|
|
{
|
|
return GetCodePageFromCharset(GetCharsetFromLang(langid));
|
|
}
|