You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1762 lines
64 KiB
1762 lines
64 KiB
/****************************************************************************
|
|
APIENTRY.CPP
|
|
|
|
Owner: cslim
|
|
Copyright (c) 1997-1999 Microsoft Corporation
|
|
|
|
API entries between IMM32 and IME
|
|
|
|
History:
|
|
14-JUL-1999 cslim Copied from IME98 source tree
|
|
*****************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#include "apientry.h"
|
|
#include "common.h"
|
|
#include "ui.h"
|
|
#include "hauto.h"
|
|
#include "dllmain.h"
|
|
#include "hanja.h"
|
|
#include "escape.h"
|
|
#include "config.h"
|
|
#include "names.h"
|
|
#include "winex.h"
|
|
#include "hanja.h"
|
|
#include "cpadsvr.h"
|
|
#include "debug.h"
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// ImeMenu Define
|
|
#define NUM_ROOT_MENU_L 4
|
|
#define NUM_ROOT_MENU_R 1
|
|
#define NUM_SUB_MENU_L 0
|
|
#define NUM_SUB_MENU_R 0
|
|
|
|
#define IDIM_ROOT_ML_1 0x10
|
|
#define IDIM_ROOT_ML_2 0x11
|
|
#define IDIM_ROOT_ML_3 0x12
|
|
#define IDIM_ROOT_ML_4 0x13
|
|
#define IDIM_ROOT_MR_1 0x30
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Private function Declarations
|
|
PRIVATE BOOL IsInSystemSetupMode();
|
|
PRIVATE BOOL IsRunningAsLocalSystem();
|
|
PRIVATE BOOL IsRunningInOOBE();
|
|
PRIVATE BOOL PASCAL Select(HIMC hImc, BOOL fSelect);
|
|
PRIVATE VOID PASCAL UpdateOpenCloseState(PCIMECtx pImeCtx);
|
|
PRIVATE VOID PASCAL ToAsciiExHangulMode(PCIMECtx pImeCtx, UINT uVirKey, UINT uScanCode, CONST LPBYTE lpbKeyState);
|
|
PRIVATE BOOL PASCAL ToAsciiExHanja(PCIMECtx pImeCtx, UINT uVirKey, CONST LPBYTE lpbKeyState);
|
|
|
|
PRIVATE WCHAR PASCAL Banja2Junja(WCHAR bChar);
|
|
PRIVATE BOOL PASCAL IsKSC5601(WCHAR wcCur);
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
ImeInquire
|
|
|
|
This function handle initialization of IME. It also returns IMEINFO structure
|
|
and UI class name of IME
|
|
----------------------------------------------------------------------------*/
|
|
BOOL WINAPI ImeInquire(LPIMEINFO lpIMEInfo, LPTSTR lpszWndClass, DWORD dwSystemInfoFlags)
|
|
{
|
|
BOOL fRet = fFalse;
|
|
|
|
Dbg(DBGID_API, TEXT("ImeInquire():lpIMEInfo = 0x%08lX, dwSystemInfoFlags = 0x%08lX"), lpIMEInfo, dwSystemInfoFlags);
|
|
|
|
if (lpIMEInfo)
|
|
{
|
|
lpIMEInfo->dwPrivateDataSize = sizeof(IMCPRIVATE); // The private data in an IME context.
|
|
lpIMEInfo->fdwProperty = IME_PROP_AT_CARET // IME conversion window is at caret position.
|
|
| IME_PROP_NEED_ALTKEY // ALT key pass into ImeProcessKey
|
|
| IME_PROP_CANDLIST_START_FROM_1 // Candidate list start from 1
|
|
| IME_PROP_END_UNLOAD;
|
|
|
|
if (IsMemphis() || IsWinNT5orUpper())
|
|
lpIMEInfo->fdwProperty |= IME_PROP_COMPLETE_ON_UNSELECT; // Complete when IME unselected.
|
|
|
|
lpIMEInfo->fdwConversionCaps = IME_CMODE_NATIVE // IMEs in NATIVE mode else ALPHANUMERIC mode
|
|
| IME_CMODE_FULLSHAPE // else in SBCS mode
|
|
| IME_CMODE_HANJACONVERT;// Hangul hanja conversion
|
|
|
|
lpIMEInfo->fdwSentenceCaps = 0; // IME sentence mode capability
|
|
lpIMEInfo->fdwUICaps = 0;
|
|
lpIMEInfo->fdwSCSCaps = SCS_CAP_COMPSTR; // IME can generate the composition string by SCS_SETSTR
|
|
lpIMEInfo->fdwSelectCaps = SELECT_CAP_CONVERSION; // ImeSetCompositionString capability
|
|
|
|
// Set Unicode flag if system support it
|
|
if (vfUnicode == fTrue)
|
|
lpIMEInfo->fdwProperty |= IME_PROP_UNICODE; // String content of the Input Context will be UNICODE
|
|
|
|
// NT5 Unicode injection through VK_PACKET
|
|
if (IsWinNT5orUpper())
|
|
lpIMEInfo->fdwProperty |= IME_PROP_ACCEPT_WIDE_VKEY;
|
|
|
|
// Return Unicode string for Unicode environment
|
|
#ifndef UNDER_CE // Windows CE always Unicode
|
|
if (vfUnicode == fTrue)
|
|
StrCopyW((LPWSTR)lpszWndClass, wszUIClassName);
|
|
else
|
|
lstrcpyA(lpszWndClass, szUIClassName);
|
|
#else // UNDER_CE
|
|
lstrcpyW(lpszWndClass, wszUIClassName);
|
|
#endif // UNDER_CE
|
|
|
|
fRet = fTrue;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// 16 bit application check
|
|
// If client is 16 bit Apps, only allow KS C-5601 chars.
|
|
|
|
if (IsWinNT())
|
|
{
|
|
// Win98 does not pass dwSystemInfoFlags;
|
|
vpInstData->dwSystemInfoFlags = dwSystemInfoFlags;
|
|
|
|
if (dwSystemInfoFlags & IME_SYSINFO_WOW16)
|
|
vpInstData->f16BitApps = fTrue;
|
|
|
|
// If in MT setup mode(system setup, upgrading and OOBE), display IME status window.
|
|
if (IsInSystemSetupMode())
|
|
vpInstData->dwSystemInfoFlags |= IME_SYSINFO_WINLOGON;
|
|
}
|
|
else
|
|
{
|
|
// user GetProcessVersion
|
|
DWORD dwVersion = GetProcessVersion(GetCurrentProcessId());
|
|
// Windowss 3.x
|
|
if (HIWORD(dwVersion) <= 3)
|
|
{
|
|
vpInstData->f16BitApps = fTrue;
|
|
#ifdef DEBUG
|
|
DebugOutT(TEXT("!!! 16bit Apps running under Win9x !!!\r\n"));
|
|
#endif
|
|
}
|
|
}
|
|
|
|
// If 16bit apps, always disable ISO10646(full range Hangul)
|
|
if (vpInstData->f16BitApps == fTrue)
|
|
vpInstData->fISO10646 = fFalse;
|
|
|
|
return fRet;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
ImeConversionList
|
|
|
|
obtain the list of candidate list from one character
|
|
----------------------------------------------------------------------------*/
|
|
DWORD WINAPI ImeConversionList(HIMC hIMC, LPCTSTR lpSource, LPCANDIDATELIST lpDest, DWORD dwBufLen, UINT uFlag)
|
|
{
|
|
WCHAR wchHanja;
|
|
|
|
Dbg(DBGID_API, TEXT("ImeConversionList():hIMC = 0x%08lX, *lpSource = %04X, dwBufLen =%08lX"), hIMC, *(LPWSTR)lpSource, dwBufLen);
|
|
|
|
if (hIMC == NULL)
|
|
return 0;
|
|
|
|
if (lpSource == NULL || *(LPWSTR)lpSource == 0)
|
|
return 0;
|
|
|
|
// If dwBufLen==0 then should return buffer size
|
|
if (dwBufLen && lpDest == NULL)
|
|
return 0;
|
|
|
|
//
|
|
// Code Conversion
|
|
//
|
|
// CONFIRM: Win98 send Unicode or not?
|
|
if (IsMemphis() || IsWinNT())
|
|
wchHanja = *(LPWSTR)lpSource;
|
|
else
|
|
{
|
|
if (MultiByteToWideChar(CP_KOREA, MB_PRECOMPOSED, lpSource, 2, &wchHanja, 1) == 0)
|
|
return 0;
|
|
}
|
|
|
|
switch (uFlag)
|
|
{
|
|
case GCL_CONVERSION:
|
|
return GetConversionList(wchHanja, lpDest, dwBufLen);
|
|
break;
|
|
case GCL_REVERSECONVERSION:
|
|
case GCL_REVERSE_LENGTH:
|
|
break;
|
|
default:
|
|
DbgAssert(0);
|
|
}
|
|
return (0);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
ImeConfigure
|
|
|
|
Open IME configuration DLG
|
|
----------------------------------------------------------------------------*/
|
|
BOOL WINAPI ImeConfigure(HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
|
|
{
|
|
BOOL fRet = fFalse;
|
|
|
|
Dbg (DBGID_API, TEXT("ImeConfigure():hKL = 0x%08lX, dwMode = 0x%08lX"), hKL, dwMode);
|
|
|
|
switch (dwMode)
|
|
{
|
|
case IME_CONFIG_GENERAL:
|
|
if (ConfigDLG(hWnd))
|
|
fRet = fTrue;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
ImeDestroy
|
|
----------------------------------------------------------------------------*/
|
|
BOOL WINAPI ImeDestroy(UINT uReserved)
|
|
{
|
|
Dbg(DBGID_API, TEXT("ImeDestroy(): Bye *-<\r\nSee Again !"));
|
|
if (uReserved)
|
|
return (fFalse);
|
|
else
|
|
return (fTrue);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
ImeEscape
|
|
|
|
Support Korean IME escape functions
|
|
----------------------------------------------------------------------------*/
|
|
LRESULT WINAPI ImeEscape(HIMC hIMC, UINT uSubFunc, LPVOID lpData)
|
|
{
|
|
PCIMECtx pImeCtx = GetIMECtx(hIMC);
|
|
LRESULT lRet;
|
|
|
|
if (lpData == NULL || pImeCtx == NULL)
|
|
return 0;
|
|
|
|
Dbg(DBGID_API, TEXT("ImeEscape():hIMC = 0x%08lX, uSubFunc = 0x%08lX"), hIMC, uSubFunc);
|
|
switch (uSubFunc)
|
|
{
|
|
case IME_ESC_AUTOMATA:
|
|
lRet = EscAutomata(pImeCtx, (LPIMESTRUCT32)lpData, fTrue);
|
|
break;
|
|
|
|
case IME_AUTOMATA:
|
|
lRet = EscAutomata(pImeCtx, (LPIMESTRUCT32)lpData, fFalse);
|
|
break;
|
|
|
|
case IME_GETOPEN:
|
|
lRet = EscGetOpen(pImeCtx, (LPIMESTRUCT32)lpData);
|
|
break;
|
|
|
|
// Popup Hanja candidate window
|
|
case IME_ESC_HANJA_MODE:
|
|
if (lRet = EscHanjaMode(pImeCtx, (LPSTR)lpData, fTrue))
|
|
{
|
|
pImeCtx->SetCandidateMsg(CIMECtx::MSG_OPENCAND);
|
|
pImeCtx->GenerateMessage();
|
|
}
|
|
break;
|
|
|
|
// 16bit apps(Win 3.1) compatibility
|
|
case IME_HANJAMODE:
|
|
if (lRet = EscHanjaMode(pImeCtx, (LPSTR)lpData, fFalse))
|
|
{
|
|
pImeCtx->SetCandidateMsg(CIMECtx::MSG_OPENCAND);
|
|
pImeCtx->GenerateMessage();
|
|
}
|
|
break;
|
|
|
|
case IME_SETOPEN:
|
|
lRet = EscSetOpen(pImeCtx, (LPIMESTRUCT32)lpData);
|
|
break;
|
|
|
|
case IME_MOVEIMEWINDOW:
|
|
lRet = EscMoveIMEWindow(pImeCtx, (LPIMESTRUCT32)lpData);
|
|
break;
|
|
|
|
case 0x1100:
|
|
lRet = EscGetIMEKeyLayout(pImeCtx, (LPIMESTRUCT32)lpData);
|
|
break;
|
|
|
|
default:
|
|
Dbg(DBGID_Misc, TEXT("Unknown ImeEscape() subfunc(#0x%X) is called."), uSubFunc);
|
|
return (0);
|
|
}
|
|
return (lRet);
|
|
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
ImeSetActiveContext
|
|
----------------------------------------------------------------------------*/
|
|
BOOL WINAPI ImeSetActiveContext(HIMC hIMC, BOOL fActive)
|
|
{
|
|
Dbg(DBGID_API, TEXT("ImeSetActiveContext():hIMC = 0x%08lX, fActive = 0x%d"), hIMC, fActive);
|
|
|
|
// Initialize composition context. For Korean IME, don't need to kee composition str,
|
|
// when context changed.
|
|
//if (pImeCtx)
|
|
//{
|
|
//pImeCtx->ClearCompositionStrBuffer();
|
|
//pImeCtx->GetAutomata()->InitState();
|
|
//pImeCtx->ResetComposition();
|
|
//}
|
|
// CONFIRM: Is this really safe to disable?
|
|
#if 0
|
|
LPINPUTCONTEXT lpIMC;
|
|
LPCOMPOSITIONSTRING lpCompStr;
|
|
|
|
Dbg(DBGID_API, _T("ImeSetActiveContext():hIMC = 0x%08lX, fActive = 0x%d"), hIMC, fActive);
|
|
|
|
if (!hIMC)
|
|
return fFalse;
|
|
|
|
lpIMC = ImmLockIMC(hIMC);
|
|
if (!lpIMC)
|
|
return fFalse;
|
|
|
|
if (fActive)
|
|
{
|
|
if (lpCompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr))
|
|
{
|
|
if (lpCompStr->dwCompStrLen)
|
|
{
|
|
CIMEData ImeData;
|
|
|
|
// if composition character mismatched with Automata object's reset with lpCompStr
|
|
// I'm really suspicious when this situation occurs. I think never occur... -cslim
|
|
if (pInstData->pMachine->GetCompositionChar()
|
|
!= *(LPWSTR)((LPBYTE)lpCompStr + lpCompStr->dwCompStrOffset))
|
|
{
|
|
pInstData->pMachine->InitState();
|
|
pInstData->pMachine->
|
|
SetCompositionChar(*(LPWSTR)((LPBYTE)lpCompStr + lpCompStr->dwCompStrOffset));
|
|
}
|
|
}
|
|
ImmUnlockIMCC(lpIMC->hCompStr);
|
|
}
|
|
}
|
|
|
|
ImmUnlockIMC(hIMC);
|
|
#endif
|
|
|
|
return fTrue;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
ImeProcessKey
|
|
|
|
Return fTrue if IME should process the key
|
|
----------------------------------------------------------------------------*/
|
|
BOOL WINAPI ImeProcessKey(HIMC hIMC, UINT uVirKey, LPARAM lParam, CONST LPBYTE lpbKeyState)
|
|
{
|
|
PCIMECtx pImeCtx;
|
|
WORD uScanCode;
|
|
BOOL fRet = fFalse;
|
|
|
|
Dbg(DBGID_API, TEXT("ImeProcessKey():hIMC=0x%08lX, uVKey=0x%04X, lParam=0x%08lX"), hIMC, uVirKey, lParam);
|
|
|
|
if (lpbKeyState == NULL)
|
|
return fFalse;
|
|
|
|
// NT5 Unicode injection
|
|
uVirKey = (UINT)LOWORD(uVirKey);
|
|
uScanCode = HIWORD(lParam);
|
|
|
|
if (uVirKey == VK_PROCESSKEY) // Mouse button clicked
|
|
{
|
|
Dbg(DBGID_Key, TEXT("ImeProcessKey : return fTrue - Mouse Button Pressed"));
|
|
return fTrue;
|
|
}
|
|
else if (uScanCode & KF_UP)
|
|
{
|
|
Dbg(DBGID_Key, TEXT("ImeProcessKey : return fFalse - KF_UP"));
|
|
return (fFalse);
|
|
}
|
|
else if (uVirKey == VK_SHIFT) // no SHIFT key
|
|
{
|
|
Dbg(DBGID_Key, TEXT("ImeProcessKey : return fFalse - VK_SHIFT"));
|
|
return (fFalse);
|
|
}
|
|
else if (uVirKey == VK_CONTROL) // no CTRL key
|
|
{
|
|
Dbg(DBGID_Key, TEXT("ImeProcessKey : return fFalse - VK_CONTROL"));
|
|
return (fFalse);
|
|
}
|
|
else if (uVirKey == VK_HANGUL || uVirKey == VK_JUNJA || uVirKey == VK_HANJA)
|
|
{
|
|
Dbg(DBGID_Key, TEXT("ImeProcessKey : return fTrue - VK_HANGUL, VK_JUNJA, VK_HANJA"));
|
|
return (fTrue);
|
|
}
|
|
else
|
|
{
|
|
// need more check
|
|
}
|
|
|
|
if ((pImeCtx = GetIMECtx(hIMC)) == NULL)
|
|
return fFalse;
|
|
|
|
// If IME close, return with no action.
|
|
if (pImeCtx->IsOpen() == fFalse)
|
|
{
|
|
Dbg(DBGID_Key, TEXT("ImeProcessKey : return fFalse - IME closed"));
|
|
return fFalse;
|
|
}
|
|
|
|
// If Hanja conv mode return fTrue. ImeToAsciiEx will handle.
|
|
if (pImeCtx->GetConversionMode() & IME_CMODE_HANJACONVERT)
|
|
{
|
|
return fTrue;
|
|
}
|
|
|
|
// If interim state
|
|
if (pImeCtx->GetCompBufLen())
|
|
{
|
|
// If ALT key down and in composition process, finalize it.
|
|
if (uVirKey == VK_MENU)
|
|
{
|
|
Dbg(DBGID_Key, TEXT("ImeProcessKey : Finalize and return fFalse - VK_MENU"));
|
|
pImeCtx->FinalizeCurCompositionChar();
|
|
pImeCtx->GenerateMessage();
|
|
}
|
|
else
|
|
{
|
|
Dbg(DBGID_Key, TEXT("ImeProcessKey : Interim state. Key pressed except ALT"));
|
|
fRet = fTrue;
|
|
}
|
|
}
|
|
else // If composition string does not exist,
|
|
{
|
|
// if Ctrl+xx key, do not process in non-interim mode
|
|
if (IsControlKeyPushed(lpbKeyState) == fFalse)
|
|
{
|
|
// If Hangul mode
|
|
if (pImeCtx->GetConversionMode() & IME_CMODE_HANGUL)
|
|
{ // Start of hangul composition
|
|
WORD wcCur = 0;
|
|
|
|
if (pImeCtx->GetAutomata() != NULL)
|
|
{
|
|
wcCur = pImeCtx->GetAutomata()->GetKeyMap(uVirKey, IsShiftKeyPushed(lpbKeyState) ? 1 : 0 );
|
|
}
|
|
// 2beolsik Alphanumeric keys have same layout as English key
|
|
// So we don't need process when user pressed Alphanumeric key under 2beolsik
|
|
if ( (wcCur && pImeCtx->GetGData() && pImeCtx->GetGData()->GetCurrentBeolsik() != KL_2BEOLSIK) || (wcCur & H_HANGUL) )
|
|
fRet = fTrue;
|
|
}
|
|
|
|
// if IME_CMODE_FULLSHAPE
|
|
if (pImeCtx->GetConversionMode() & IME_CMODE_FULLSHAPE)
|
|
{
|
|
if (CHangulAutomata::GetEnglishKeyMap(uVirKey, IsShiftKeyPushed(lpbKeyState) ? 1 : 0))
|
|
fRet = fTrue;
|
|
}
|
|
}
|
|
}
|
|
|
|
// NT 5 Unicode injection
|
|
if (uVirKey == VK_PACKET)
|
|
{
|
|
Dbg(DBGID_Key, TEXT("ImeProcessKey : VK_PACKET"));
|
|
fRet = fTrue;
|
|
}
|
|
|
|
Dbg(DBGID_Key, TEXT("ImeProcessKey : return value = %d"), fRet);
|
|
return fRet;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
NotifyIME
|
|
|
|
Change the status of IME according to the given parameter
|
|
----------------------------------------------------------------------------*/
|
|
BOOL WINAPI NotifyIME(HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
|
|
{
|
|
PCIMECtx pImeCtx;
|
|
BOOL fRet = fFalse;
|
|
|
|
Dbg(DBGID_API, TEXT("NotifyIME():hIMC = 0x%08lX, dwAction = 0x%08lX, dwIndex = 0x%08lX, dwValue = 0x%08lX"), hIMC, dwAction, dwIndex, dwValue);
|
|
|
|
if ((pImeCtx = GetIMECtx(hIMC)) == NULL)
|
|
return fFalse;
|
|
|
|
switch (dwAction)
|
|
{
|
|
case NI_COMPOSITIONSTR:
|
|
switch (dwIndex)
|
|
{
|
|
//////////////////////////////////////////////////////////
|
|
case CPS_COMPLETE:
|
|
Dbg(DBGID_IMENotify, TEXT("NotifyIME(): NI_COMPOSITIONSTR-CPS_COMPLETE"));
|
|
|
|
// If composition state
|
|
if (pImeCtx->GetCompBufLen())
|
|
{
|
|
// For ESC_HANJAMODE call this, we should reset comp str.
|
|
pImeCtx->ResetComposition();
|
|
pImeCtx->SetResultStr(pImeCtx->GetCompBufStr());
|
|
pImeCtx->SetEndComposition(fTrue);
|
|
pImeCtx->StoreComposition();
|
|
|
|
// Raid #104
|
|
if (pImeCtx->GetConversionMode() & IME_CMODE_HANJACONVERT)
|
|
{
|
|
// Cancel Hanja change mode
|
|
pImeCtx->SetConversionMode(pImeCtx->GetConversionMode() & ~IME_CMODE_HANJACONVERT);
|
|
pImeCtx->SetCandidateMsg(CIMECtx::MSG_CLOSECAND);
|
|
}
|
|
|
|
// Clear all automata states
|
|
pImeCtx->GetAutomata()->InitState();
|
|
pImeCtx->GenerateMessage();
|
|
|
|
fRet = fTrue;
|
|
}
|
|
break;
|
|
|
|
//////////////////////////////////////////////////////////
|
|
case CPS_CANCEL:
|
|
Dbg(DBGID_IMENotify, TEXT("NotifyIME(): NI_COMPOSITIONSTR-CPS_CANCEL"));
|
|
|
|
// if composition string exist, remove it and send WM_IME_ENDCOMPOSITION
|
|
if (pImeCtx->GetCompBufLen())
|
|
{
|
|
pImeCtx->SetEndComposition(fTrue);
|
|
pImeCtx->GenerateMessage();
|
|
pImeCtx->ClearCompositionStrBuffer();
|
|
|
|
fRet = fTrue;
|
|
}
|
|
break;
|
|
|
|
//////////////////////////////////////////////////////////
|
|
case CPS_CONVERT:
|
|
case CPS_REVERT:
|
|
|
|
default:
|
|
Dbg(DBGID_IMENotify, TEXT("NotifyIME(): NI_COMPOSITIONSTR-CPS_CONVERT or CPS_REVERT !!! NOT IMPMLEMENTED !!!"));
|
|
break;
|
|
} // switch (dwIndex)
|
|
break;
|
|
|
|
case NI_OPENCANDIDATE:
|
|
Dbg(DBGID_IMENotify, TEXT("NotifyIME(): NI_OPENCANDIDATE"));
|
|
// if not Hanja mocde
|
|
if (!(pImeCtx->GetConversionMode() & IME_CMODE_HANJACONVERT))
|
|
{
|
|
if (pImeCtx->GetCompBufLen() && GenerateHanjaCandList(pImeCtx))
|
|
{
|
|
pImeCtx->SetCandidateMsg(CIMECtx::MSG_OPENCAND);
|
|
// Set Hanja conv mode
|
|
pImeCtx->SetConversionMode(pImeCtx->GetConversionMode() | IME_CMODE_HANJACONVERT);
|
|
OurSendMessage(pImeCtx->GetAppWnd(), WM_IME_NOTIFY, IMN_SETCONVERSIONMODE, 0L);
|
|
pImeCtx->GenerateMessage();
|
|
fRet = fTrue;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case NI_CLOSECANDIDATE:
|
|
if (pImeCtx->GetConversionMode() & IME_CMODE_HANJACONVERT)
|
|
{
|
|
pImeCtx->SetCandidateMsg(CIMECtx::MSG_CLOSECAND);
|
|
// Set clear Hanja conv mode
|
|
pImeCtx->SetConversionMode(pImeCtx->GetConversionMode() & ~IME_CMODE_HANJACONVERT);
|
|
// To Notify to UI wnd
|
|
OurSendMessage(pImeCtx->GetAppWnd(), WM_IME_NOTIFY, IMN_SETCONVERSIONMODE, 0L);
|
|
pImeCtx->GenerateMessage();
|
|
fRet = fTrue;
|
|
}
|
|
break;
|
|
|
|
case NI_SELECTCANDIDATESTR:
|
|
case NI_SETCANDIDATE_PAGESTART:
|
|
Dbg(DBGID_IMENotify, TEXT("NotifyIME(): NI_SETCANDIDATE_PAGESTART"));
|
|
if (pImeCtx->GetConversionMode() & IME_CMODE_HANJACONVERT)
|
|
{
|
|
pImeCtx->SetCandStrSelection(dwValue);
|
|
pImeCtx->SetCandidateMsg(CIMECtx::MSG_CHANGECAND);
|
|
pImeCtx->GenerateMessage();
|
|
fRet = fTrue;
|
|
}
|
|
break;
|
|
|
|
case NI_CONTEXTUPDATED:
|
|
Dbg(DBGID_IMENotify, TEXT("NotifyIME(): NI_CONTEXTUPDATED"));
|
|
switch (dwValue)
|
|
{
|
|
case IMC_SETOPENSTATUS:
|
|
Dbg(DBGID_IMENotify, TEXT("NotifyIME(): NI_CONTEXTUPDATED - IMC_SETOPENSTATUS"));
|
|
Dbg(DBGID_IMENotify, TEXT("pImeCtx->GetConversionMode() = 0x%08lX"), pImeCtx->GetConversionMode());
|
|
UpdateOpenCloseState(pImeCtx);
|
|
fRet = fTrue;
|
|
break;
|
|
|
|
case IMC_SETCONVERSIONMODE:
|
|
Dbg(DBGID_IMENotify, TEXT("NotifyIME(): NI_CONTEXTUPDATED - IMC_SETCONVERSIONMODE"));
|
|
Dbg(DBGID_IMENotify, TEXT("pImeCtx->GetConversionMode() = 0x%08lX"), pImeCtx->GetConversionMode());
|
|
UpdateOpenCloseState(pImeCtx);
|
|
fRet = fTrue;
|
|
break;
|
|
//case IMC_SETSTATUSWINDOWPOS:
|
|
case IMC_SETCANDIDATEPOS:
|
|
case IMC_SETCOMPOSITIONFONT:
|
|
case IMC_SETCOMPOSITIONWINDOW:
|
|
//DbgAssert(0);
|
|
fRet = fTrue;
|
|
break;
|
|
|
|
default:
|
|
Dbg(DBGID_IMENotify, TEXT("NotifyIME(): NI_CONTEXTUPDATED - Unhandeled IMC value = 0x%08lX"), dwValue);
|
|
break;
|
|
} // switch (dwValue)
|
|
break;
|
|
|
|
case NI_IMEMENUSELECTED:
|
|
Dbg(DBGID_IMENotify, TEXT("NotifyIME(): NI_IMEMENUSELECTED"));
|
|
switch (dwIndex)
|
|
{
|
|
case IDIM_ROOT_MR_1:
|
|
// BUGBUG: NT Bug #379149
|
|
// Because Internat uses SendMessage, If user does not cancel the DLG, Deadlock occurs.
|
|
// ImeConfigure(GetKeyboardLayout(NULL), pImeCtx->GetAppWnd(), IME_CONFIG_GENERAL, NULL);
|
|
OurPostMessage(GetActiveUIWnd(), WM_MSIME_PROPERTY, 0L, IME_CONFIG_GENERAL);
|
|
break;
|
|
case IDIM_ROOT_ML_4:
|
|
fRet = OurImmSetConversionStatus(hIMC,
|
|
(pImeCtx->GetConversionMode() & ~IME_CMODE_HANGUL) | IME_CMODE_FULLSHAPE,
|
|
pImeCtx->GetSentenceMode());
|
|
break;
|
|
case IDIM_ROOT_ML_3:
|
|
fRet = OurImmSetConversionStatus(hIMC,
|
|
pImeCtx->GetConversionMode() & ~(IME_CMODE_HANGUL | IME_CMODE_FULLSHAPE),
|
|
pImeCtx->GetSentenceMode());
|
|
break;
|
|
case IDIM_ROOT_ML_2:
|
|
fRet = OurImmSetConversionStatus(hIMC,
|
|
pImeCtx->GetConversionMode() | IME_CMODE_HANGUL | IME_CMODE_FULLSHAPE,
|
|
pImeCtx->GetSentenceMode());
|
|
break;
|
|
case IDIM_ROOT_ML_1:
|
|
fRet = OurImmSetConversionStatus(hIMC,
|
|
(pImeCtx->GetConversionMode() | IME_CMODE_HANGUL) & ~IME_CMODE_FULLSHAPE,
|
|
pImeCtx->GetSentenceMode());
|
|
break;
|
|
} // switch (dwIndex)
|
|
break;
|
|
|
|
case NI_CHANGECANDIDATELIST:
|
|
case NI_FINALIZECONVERSIONRESULT:
|
|
case NI_SETCANDIDATE_PAGESIZE:
|
|
default:
|
|
Dbg(DBGID_IMENotify, TEXT("NotifyIME(): Unhandeled NI_ value = 0x%08lX"), dwAction);
|
|
break;
|
|
} // switch (dwAction)
|
|
|
|
return fRet;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
ImeSelect
|
|
|
|
Initialize/Uninitialize IME private context
|
|
----------------------------------------------------------------------------*/
|
|
BOOL WINAPI ImeSelect(HIMC hIMC, BOOL fSelect) // fTrue-initialize, fFalse-uninitialize(free resource)
|
|
{
|
|
BOOL fRet = fFalse;
|
|
|
|
Dbg(DBGID_API, TEXT("ImeSelect():hIMC = 0x%08lX, fSelect = 0x%d"), hIMC, fSelect);
|
|
|
|
if (!hIMC) // if invalid input context handle
|
|
{
|
|
DbgAssert(0);
|
|
return fFalse;
|
|
}
|
|
|
|
// If DLL_PROCESS_DETACH already called once.
|
|
if (vfDllDetachCalled)
|
|
{
|
|
return fFalse;
|
|
}
|
|
fRet = Select(hIMC, fSelect);
|
|
|
|
return fRet;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
ImeSetCompositionString
|
|
----------------------------------------------------------------------------*/
|
|
BOOL WINAPI ImeSetCompositionString(HIMC hIMC, DWORD dwIndex, LPVOID lpComp,
|
|
DWORD dwCompLen, LPVOID lpRead, DWORD dwReadLen)
|
|
{
|
|
PCIMECtx pImeCtx;
|
|
WCHAR wcComp;
|
|
BOOL fSendStart,
|
|
fRet = fFalse;
|
|
|
|
Dbg(DBGID_API|DBGID_SetComp, TEXT("ImeSetCompositionString():hIMC = 0x%08lX, dwIndex = 0x%08lX, lpComp = 0x%04X"), hIMC, dwIndex, *(LPWSTR)lpComp);
|
|
|
|
if ((pImeCtx = GetIMECtx(hIMC)) == NULL)
|
|
return fFalse;
|
|
|
|
if (dwIndex == SCS_SETSTR)
|
|
{
|
|
// Conv mode check
|
|
if ((pImeCtx->GetConversionMode() & IME_CMODE_HANGUL)==0)
|
|
{
|
|
Dbg(DBGID_API|DBGID_SetComp, TEXT("!!! WARNING !!!: ImeSetCompositionString(): English mode"));
|
|
return fFalse;
|
|
}
|
|
|
|
// Send WM_IME_STARTCOMPOSITION if not interim state.
|
|
fSendStart = pImeCtx->GetCompBufLen() ? fFalse : fTrue;
|
|
|
|
wcComp = L'\0';
|
|
// Parameter check
|
|
if (lpComp != NULL && *(LPWSTR)lpComp != L'\0' && dwCompLen != 0)
|
|
{
|
|
if (pImeCtx->IsUnicodeEnv())
|
|
wcComp = *(LPWSTR)lpComp;
|
|
else
|
|
if (MultiByteToWideChar(CP_KOREA, MB_PRECOMPOSED, (LPSTR)lpComp, 2, &wcComp, 1) == 0)
|
|
{
|
|
DbgAssert(0);
|
|
wcComp = 0;
|
|
}
|
|
|
|
// Hangul range check
|
|
if ( (wcComp > 0x3130 && wcComp < 0x3164) ||
|
|
(wcComp >= 0xAC00 && wcComp < 0xD7A4) )
|
|
{
|
|
pImeCtx->SetCompositionStr(wcComp);
|
|
pImeCtx->StoreComposition();
|
|
}
|
|
else
|
|
{
|
|
Dbg(DBGID_SetComp, TEXT("!!! WARNING !!!: lpComp is null or Input character is not Hangul"));
|
|
DbgAssert(0);
|
|
wcComp = 0;
|
|
}
|
|
}
|
|
|
|
// Send WM_IME_STARTCOMPOSITION
|
|
if (fSendStart)
|
|
pImeCtx->SetStartComposition(fTrue);
|
|
|
|
// REVIEW: Even if wcComp ==0, Should send WM_IME_COMPOSITION
|
|
// Send composition char
|
|
//SetTransBuffer(lpTransMsg, WM_IME_COMPOSITION,
|
|
// (WPARAM)wcComp, (GCS_COMPSTR|GCS_COMPATTR|CS_INSERTCHAR|CS_NOMOVECARET));
|
|
|
|
// Set Automata state if non-null comp char
|
|
if (wcComp)
|
|
pImeCtx->GetAutomata()->SetCompositionChar(wcComp);
|
|
else
|
|
{
|
|
// REVIEW: Even if wcComp ==0, Should send WM_IME_COMPOSITION
|
|
pImeCtx->ClearCompositionStrBuffer();
|
|
pImeCtx->AddMessage(WM_IME_COMPOSITION, 0, (GCS_COMPSTR|GCS_COMPATTR|CS_INSERTCHAR|CS_NOMOVECARET));
|
|
pImeCtx->SetEndComposition(fTrue);
|
|
pImeCtx->GetAutomata()->InitState();
|
|
}
|
|
|
|
// Generate IME message
|
|
pImeCtx->GenerateMessage();
|
|
|
|
fRet = fTrue;
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
ImeToAsciiEx
|
|
----------------------------------------------------------------------------*/
|
|
UINT WINAPI ImeToAsciiEx(UINT uVirKey, UINT uScanCode, CONST LPBYTE lpbKeyState,
|
|
LPTRANSMSGLIST lpTransBuf, UINT fuState, HIMC hIMC)
|
|
{
|
|
PCIMECtx pImeCtx;
|
|
UINT uNumMsg=0;
|
|
WORD bKeyCode;
|
|
|
|
Dbg(DBGID_API, TEXT("ImeToAsciiEx(): hIMC = 0x%08lX, uVirKey = 0x%04X, uScanCode = 0x%04X"), hIMC, uVirKey, uScanCode);
|
|
Dbg(DBGID_Key, TEXT("lpbKeyState = 0x%08lX, lpdwTransBuf = 0x%08lX, fuState = 0x%04X"), lpbKeyState, lpTransBuf, fuState);
|
|
|
|
if ((pImeCtx = GetIMECtx(hIMC)) == NULL)
|
|
return 0;
|
|
|
|
// Start process key
|
|
pImeCtx->SetProcessKeyStatus(fTrue);
|
|
|
|
// special message buffer for ToAsciiEx()
|
|
pImeCtx->SetTransMessage(lpTransBuf);
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// If Hanja conv mode
|
|
if (pImeCtx->GetConversionMode() & IME_CMODE_HANJACONVERT)
|
|
{
|
|
if (ToAsciiExHanja(pImeCtx, uVirKey, lpbKeyState) == fFalse)
|
|
goto ToAsciiExExit_NoMsg;
|
|
}
|
|
else
|
|
{
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// W2K specific - Unicode injection
|
|
if (LOWORD(uVirKey) == VK_PACKET)
|
|
{
|
|
WCHAR wch = HIWORD(uVirKey);
|
|
Dbg(DBGID_Key, TEXT("ImeToAsciiEx: VK_PACKET arrived(NonHanja conv mode)"));
|
|
|
|
// If composition char exist, first finalize and append injection char, then send all.
|
|
if (pImeCtx->GetCompBufLen())
|
|
{
|
|
pImeCtx->FinalizeCurCompositionChar();
|
|
pImeCtx->AppendResultStr(wch);
|
|
}
|
|
else
|
|
// If no composition char exist, just insert injection char as finalized char.
|
|
pImeCtx->SetResultStr(wch);
|
|
goto ToAsciiExExit;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// If Non-Hanja conv mode
|
|
switch (uVirKey)
|
|
{
|
|
case VK_PROCESSKEY: // if mouse button clicked
|
|
Dbg(DBGID_Key, TEXT("ImeToAsciiEx : VK_PROCESSKEY"));
|
|
if (pImeCtx->GetCompBufLen())
|
|
pImeCtx->FinalizeCurCompositionChar();
|
|
break;
|
|
|
|
case VK_HANGUL :
|
|
Dbg(DBGID_Key, " - VK_HANGUL");
|
|
if (pImeCtx->GetCompBufLen())
|
|
pImeCtx->FinalizeCurCompositionChar();
|
|
|
|
OurImmSetConversionStatus(hIMC,
|
|
pImeCtx->GetConversionMode()^IME_CMODE_HANGUL,
|
|
pImeCtx->GetSentenceMode());
|
|
UpdateOpenCloseState(pImeCtx);
|
|
break;
|
|
|
|
case VK_JUNJA :
|
|
Dbg(DBGID_Key, TEXT(" - VK_JUNJA"));
|
|
if (pImeCtx->GetCompBufLen())
|
|
pImeCtx->FinalizeCurCompositionChar();
|
|
|
|
pImeCtx->AddKeyDownMessage(uVirKey, uScanCode);
|
|
|
|
OurImmSetConversionStatus(hIMC,
|
|
pImeCtx->GetConversionMode()^IME_CMODE_FULLSHAPE,
|
|
pImeCtx->GetSentenceMode());
|
|
UpdateOpenCloseState(pImeCtx);
|
|
break;
|
|
|
|
case VK_HANJA :
|
|
Dbg(DBGID_Key, TEXT(" - VK_HANJA"));
|
|
if (pImeCtx->GetCompBufLen())
|
|
{
|
|
// Keep current composition str
|
|
pImeCtx->SetCompositionStr(pImeCtx->GetCompBufStr());
|
|
if (GenerateHanjaCandList(pImeCtx))
|
|
{
|
|
pImeCtx->SetCandidateMsg(CIMECtx::MSG_OPENCAND);
|
|
OurImmSetConversionStatus(hIMC,
|
|
pImeCtx->GetConversionMode() | IME_CMODE_HANJACONVERT,
|
|
pImeCtx->GetSentenceMode());
|
|
}
|
|
}
|
|
else
|
|
pImeCtx->AddKeyDownMessage(uVirKey, uScanCode);
|
|
break;
|
|
|
|
default :
|
|
// if hangul mode
|
|
if (pImeCtx->GetConversionMode() & IME_CMODE_HANGUL)
|
|
ToAsciiExHangulMode(pImeCtx, uVirKey, uScanCode, lpbKeyState);
|
|
else
|
|
// if junja mode
|
|
if ( (pImeCtx->GetConversionMode() & IME_CMODE_FULLSHAPE)
|
|
&& (bKeyCode = CHangulAutomata::GetEnglishKeyMap(uVirKey,
|
|
(IsShiftKeyPushed(lpbKeyState) ? 1 : 0))) )
|
|
{
|
|
if (uVirKey >= 'A' && uVirKey <= 'Z')
|
|
{
|
|
bKeyCode = CHangulAutomata::GetEnglishKeyMap(uVirKey,
|
|
(IsShiftKeyPushed(lpbKeyState) ? 1 : 0)
|
|
^ ((lpbKeyState[VK_CAPITAL] & 0x01) ? 1: 0));
|
|
}
|
|
|
|
bKeyCode = Banja2Junja(bKeyCode);
|
|
pImeCtx->SetResultStr(bKeyCode);
|
|
}
|
|
// Unknown mode
|
|
else
|
|
{
|
|
DbgAssert(0);
|
|
pImeCtx->AddKeyDownMessage(uVirKey, uScanCode);
|
|
}
|
|
} // switch (uVirKey)
|
|
}
|
|
|
|
ToAsciiExExit:
|
|
pImeCtx->StoreComposition();
|
|
//pImeCtx->StoreCandidate();
|
|
pImeCtx->FinalizeMessage(); // final setup for IME Messages
|
|
|
|
ToAsciiExExit_NoMsg:
|
|
uNumMsg = pImeCtx->GetMessageCount();
|
|
pImeCtx->ResetMessage(); // reset
|
|
pImeCtx->SetTransMessage((LPTRANSMSGLIST)NULL);// start process key
|
|
pImeCtx->SetProcessKeyStatus(fFalse);
|
|
|
|
return (uNumMsg);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
ToAsciiExHangulMode
|
|
|
|
Subroutine used by ImeToAsciiEx.
|
|
----------------------------------------------------------------------------*/
|
|
VOID PASCAL ToAsciiExHangulMode(PCIMECtx pImeCtx, UINT uVirKey, UINT uScanCode, CONST LPBYTE lpbKeyState)
|
|
{
|
|
CHangulAutomata* pAutomata;
|
|
WCHAR wcCur;
|
|
UINT uNumMsg=0;
|
|
|
|
Dbg(DBGID_API, TEXT("ToAsciiExHangulMode()"));
|
|
pAutomata = pImeCtx->GetAutomata();
|
|
DbgAssert(pAutomata != NULL);
|
|
|
|
switch (uVirKey)
|
|
{
|
|
///////////////////////////////////////////////////////////
|
|
// Back space processing
|
|
case VK_BACK :
|
|
Dbg(DBGID_Key, TEXT("ImeToAsciiEx : VK_BACK"));
|
|
if (pAutomata->BackSpace())
|
|
{
|
|
wcCur = pAutomata->GetCompositionChar();
|
|
if (pImeCtx->GetGData() && pImeCtx->GetGData()->GetJasoDel() == fFalse)
|
|
{
|
|
pAutomata->InitState();
|
|
wcCur = 0;
|
|
}
|
|
|
|
if (wcCur)
|
|
{
|
|
pImeCtx->SetCompositionStr(wcCur);
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
Dbg(DBGID_Key, TEXT("ImeToAsciiEx : VK_BACK - Empty char"));
|
|
|
|
// Send Empty Composition stringto clear message
|
|
pImeCtx->AddMessage(WM_IME_COMPOSITION, 0, (GCS_COMPSTR|GCS_COMPATTR|CS_INSERTCHAR|CS_NOMOVECARET));
|
|
|
|
// Send Close composition window message
|
|
pImeCtx->SetEndComposition(fTrue);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// BUG :
|
|
DbgAssert(0);
|
|
// Put the Backspace message into return buffer.
|
|
pImeCtx->AddMessage(WM_CHAR, (WPARAM)VK_BACK, (LPARAM)0x000E0001L); //(uScanCode << 16) | 1UL
|
|
}
|
|
break;
|
|
|
|
default :
|
|
// Ctrl+xx processing bug #60
|
|
if (IsControlKeyPushed(lpbKeyState))
|
|
{
|
|
pImeCtx->FinalizeCurCompositionChar();
|
|
pImeCtx->AddKeyDownMessage(uVirKey, uScanCode);
|
|
}
|
|
else
|
|
switch (pAutomata->Machine(uVirKey, IsShiftKeyPushed(lpbKeyState) ? 1 : 0 ))
|
|
{
|
|
case HAUTO_COMPOSITION:
|
|
// Send start composition msg. if no composition exist.
|
|
if (pImeCtx->GetCompBufLen() == 0)
|
|
pImeCtx->SetStartComposition(fTrue);
|
|
|
|
// Get Current composition char
|
|
wcCur = pAutomata->GetCompositionChar();
|
|
|
|
// if ISO10646 flag disabled, should permit only KSC5601 chars
|
|
if (vpInstData->fISO10646== fFalse)
|
|
{
|
|
Dbg(DBGID_API, TEXT("ToAsciiExHangulMode - ISO10646 Off"));
|
|
if (IsKSC5601(wcCur) == fFalse)
|
|
{
|
|
Dbg(DBGID_API, TEXT("ToAsciiExHangulMode - Non KSC5601 char"));
|
|
// To cancel last Jaso
|
|
pAutomata->BackSpace();
|
|
// Complete
|
|
pAutomata->MakeComplete();
|
|
pImeCtx->SetResultStr(pAutomata->GetCompleteChar());
|
|
// Run Automata again
|
|
pAutomata->Machine(uVirKey, IsShiftKeyPushed(lpbKeyState) ? 1 : 0 );
|
|
wcCur = pAutomata->GetCompositionChar();
|
|
}
|
|
}
|
|
|
|
pImeCtx->SetCompositionStr(wcCur);
|
|
break;
|
|
|
|
case HAUTO_COMPLETE:
|
|
pImeCtx->SetResultStr(pAutomata->GetCompleteChar());
|
|
pImeCtx->SetCompositionStr(pAutomata->GetCompositionChar());
|
|
break;
|
|
|
|
////////////////////////////////////////////////////////
|
|
// User pressed Alphanumeric key.
|
|
// When user type alphanumeric char in interim state.
|
|
// ImeProcessKey should guarantee return fTrue only if
|
|
// hangul key pressed or alphanumeric key(including special keys)
|
|
// pressed in interim state or Fullshape mode.
|
|
case HAUTO_NONHANGULKEY:
|
|
wcCur = pAutomata->GetKeyMap(uVirKey, IsShiftKeyPushed(lpbKeyState) ? 1 : 0);
|
|
|
|
if (wcCur && (pImeCtx->GetConversionMode() & IME_CMODE_FULLSHAPE))
|
|
wcCur = Banja2Junja(wcCur);
|
|
|
|
// if interim state
|
|
if (pImeCtx->GetCompBufLen())
|
|
{
|
|
//DbgAssert(lpImcP->fdwImeMsg & MSG_ALREADY_START);
|
|
pImeCtx->FinalizeCurCompositionChar();
|
|
if (wcCur)
|
|
pImeCtx->AppendResultStr(wcCur);
|
|
else
|
|
pImeCtx->AddKeyDownMessage(uVirKey, uScanCode);
|
|
}
|
|
else // Not interim state
|
|
{
|
|
if (wcCur)
|
|
pImeCtx->SetResultStr(wcCur);
|
|
else
|
|
// if not alphanumeric key(special key), just send it to App
|
|
pImeCtx->AddKeyDownMessage(uVirKey, uScanCode);
|
|
}
|
|
break;
|
|
|
|
default :
|
|
DbgAssert(0);
|
|
} // switch (pAutomata->Machine(uVirKey, (lpbKeyState[VK_SHIFT] & 0x80) ? 1 : 0 ) )
|
|
} // switch (uVirKey)
|
|
|
|
return;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
ToAsciiExHanja
|
|
|
|
Subroutine used by ImeToAsciiEx. Handle key code in Hanja conversion mode on
|
|
|
|
Returns True only if there is message need to generated.
|
|
----------------------------------------------------------------------------*/
|
|
BOOL PASCAL ToAsciiExHanja(PCIMECtx pImeCtx, UINT uVirKey, CONST LPBYTE lpbKeyState)
|
|
{
|
|
UINT uNumMsg = 0;
|
|
DWORD iStart;
|
|
WORD bKeyCode;
|
|
LPCANDIDATELIST lpCandList;
|
|
WCHAR wcHanja, wchInject;
|
|
|
|
Dbg(DBGID_Hanja, TEXT("ToAsciiExHanja(): IME_CMODE_HANJACONVERT"));
|
|
|
|
|
|
// if Left Alt key or Ctrl+xx down or no cand info.
|
|
if (pImeCtx->GetPCandInfo() == NULL || pImeCtx->GetPCandInfo()->dwCount == 0)
|
|
{
|
|
Dbg(DBGID_Hanja, TEXT("ToAsciiExHanja(): WARNING no cand info. send MSG_CLOSE_CANDIDATE"));
|
|
pImeCtx->SetCandidateMsg(CIMECtx::MSG_CLOSECAND);
|
|
// Cancel Hanja conversion mode
|
|
OurImmSetConversionStatus(pImeCtx->GetHIMC(),
|
|
pImeCtx->GetConversionMode() & ~IME_CMODE_HANJACONVERT,
|
|
pImeCtx->GetSentenceMode());
|
|
return fTrue;
|
|
}
|
|
|
|
wchInject = HIWORD(uVirKey);
|
|
uVirKey = LOWORD(uVirKey);
|
|
|
|
lpCandList = (LPCANDIDATELIST)((LPBYTE)pImeCtx->GetPCandInfo() + sizeof(CANDIDATEINFO));
|
|
iStart = (lpCandList->dwSelection / lpCandList->dwPageSize) * lpCandList->dwPageSize;
|
|
|
|
// FIXED : In Hanja conversion mode, for selection candidate, use english keymap
|
|
bKeyCode = CHangulAutomata::GetEnglishKeyMap(uVirKey, IsShiftKeyPushed(lpbKeyState) ? 1 : 0 );
|
|
if (bKeyCode && (uVirKey != VK_PACKET))
|
|
{
|
|
if (bKeyCode >= '1' && bKeyCode <= '9'
|
|
&& iStart + bKeyCode - '1' < lpCandList->dwCount)
|
|
{
|
|
wcHanja = pImeCtx->GetCandidateStr(iStart + bKeyCode - '1');
|
|
Dbg(DBGID_Hanja, TEXT("ImeToAsciiEx-HANJACONVERT : wcHanja = 0x%04X"), wcHanja);
|
|
|
|
pImeCtx->SetEndComposition(fTrue);
|
|
pImeCtx->SetCandidateMsg(CIMECtx::MSG_CLOSECAND);
|
|
pImeCtx->SetResultStr(wcHanja);
|
|
|
|
OurImmSetConversionStatus(pImeCtx->GetHIMC(),
|
|
pImeCtx->GetConversionMode() & ~IME_CMODE_HANJACONVERT,
|
|
pImeCtx->GetSentenceMode());
|
|
// pImeCtx->ClearCompositionStrBuffer();
|
|
}
|
|
else
|
|
goto Exit_NoHandledKey;
|
|
}
|
|
else
|
|
{
|
|
switch (uVirKey)
|
|
{
|
|
case VK_HANJA :
|
|
case VK_ESCAPE :
|
|
case VK_PROCESSKEY :
|
|
case VK_HANGUL :
|
|
// Added for left and right Window buttons
|
|
case VK_LWIN : case VK_RWIN :
|
|
case VK_APPS :
|
|
case VK_MENU :
|
|
case VK_PACKET :
|
|
// FIXED : Bug #27
|
|
// Word notify CPS_COMPLETE when user ALT down in hanja conv mode
|
|
// then send double finalize char
|
|
// check if composition char exist
|
|
DbgAssert(pImeCtx->GetCompBufLen()); // Comp string should be exist in Hanja conv mode.
|
|
if (pImeCtx->GetCompBufLen())
|
|
{
|
|
// FIXED : if ESC_HANJA called, MSG_ALREADY_START is not set
|
|
// This prevent MSG_END_COMPOSITION.
|
|
pImeCtx->SetEndComposition(fTrue);
|
|
pImeCtx->SetResultStr(pImeCtx->GetCompBufStr());
|
|
|
|
// Unicode injection
|
|
if (uVirKey == VK_PACKET)
|
|
{
|
|
Dbg(DBGID_Key|DBGID_Hanja, TEXT("ImeToAsciiEx: VK_PACKET arrived(Hanja conv mode Comp char exist) - Append 0x%x"), wchInject);
|
|
pImeCtx->AppendResultStr(wchInject);
|
|
}
|
|
}
|
|
|
|
pImeCtx->SetCandidateMsg(CIMECtx::MSG_CLOSECAND);
|
|
|
|
// Cancel Hanja conversion mode
|
|
OurImmSetConversionStatus(pImeCtx->GetHIMC(),
|
|
pImeCtx->GetConversionMode() & ~IME_CMODE_HANJACONVERT,
|
|
pImeCtx->GetSentenceMode());
|
|
break;
|
|
|
|
case VK_LEFT :
|
|
if (iStart)
|
|
{
|
|
lpCandList->dwPageStart -= CAND_PAGE_SIZE;
|
|
lpCandList->dwSelection -= CAND_PAGE_SIZE;
|
|
pImeCtx->SetCandidateMsg(CIMECtx::MSG_CHANGECAND);
|
|
}
|
|
else
|
|
goto Exit_NoHandledKey;
|
|
|
|
// Keep current composition str
|
|
pImeCtx->SetCompositionStr(pImeCtx->GetCompBufStr());
|
|
break;
|
|
|
|
case VK_RIGHT :
|
|
if (iStart + CAND_PAGE_SIZE < lpCandList->dwCount)
|
|
{
|
|
lpCandList->dwPageStart += CAND_PAGE_SIZE;
|
|
lpCandList->dwSelection += CAND_PAGE_SIZE;
|
|
pImeCtx->SetCandidateMsg(CIMECtx::MSG_CHANGECAND);
|
|
}
|
|
else
|
|
goto Exit_NoHandledKey;
|
|
|
|
// Keep current composition str
|
|
pImeCtx->SetCompositionStr(pImeCtx->GetCompBufStr());
|
|
break;
|
|
|
|
default :
|
|
// Keep current composition str
|
|
// pImeCtx->SetCompositionStr(pImeCtx->GetCompBufStr());
|
|
goto Exit_NoHandledKey;
|
|
}
|
|
}
|
|
|
|
return fTrue;
|
|
|
|
Exit_NoHandledKey:
|
|
MessageBeep(MB_ICONEXCLAMATION);
|
|
return fFalse;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
ImeRegisterWord
|
|
|
|
NOT USED
|
|
----------------------------------------------------------------------------*/
|
|
BOOL WINAPI ImeRegisterWord(LPCTSTR lpszReading, DWORD dwStyle, LPCTSTR lpszString)
|
|
{
|
|
Dbg(DBGID_API, TEXT("ImeRegisterWord() : NOT IMPLEMENTED"));
|
|
return fFalse;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
ImeUnregisterWord
|
|
|
|
NOT USED
|
|
----------------------------------------------------------------------------*/
|
|
BOOL WINAPI ImeUnregisterWord(LPCTSTR lpszReading, DWORD dwStyle, LPCTSTR lpszString)
|
|
{
|
|
Dbg(DBGID_API, TEXT("ImeUnregisterWord() : NOT IMPLEMENTED"));
|
|
return fFalse;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
ImeGetRegisterWordStyle
|
|
|
|
NOT USED
|
|
----------------------------------------------------------------------------*/
|
|
UINT WINAPI ImeGetRegisterWordStyle(UINT nItem, LPSTYLEBUF lpStyleBuf)
|
|
{
|
|
Dbg(DBGID_API, TEXT("ImeGetRegisterWordStyle() : NOT IMPLEMENTED"));
|
|
return (0);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
ImeEnumRegisterWord
|
|
|
|
NOT USED
|
|
----------------------------------------------------------------------------*/
|
|
UINT WINAPI ImeEnumRegisterWord(REGISTERWORDENUMPROC lpfnRegisterWordEnumProc,
|
|
LPCTSTR lpszReading, DWORD dwStyle, LPCTSTR lpszString, LPVOID lpData)
|
|
{
|
|
Dbg(DBGID_API, TEXT("ImeEnumRegisterWord() : NOT IMPLEMENTED"));
|
|
return (0);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
ImeGetImeMenuItems
|
|
----------------------------------------------------------------------------*/
|
|
DWORD WINAPI ImeGetImeMenuItems(HIMC hIMC, DWORD dwFlags, DWORD dwType,
|
|
LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu,
|
|
DWORD dwSize)
|
|
{
|
|
PCIMECtx pImeCtx;
|
|
DWORD dwNumOfItems=0;
|
|
|
|
Dbg(DBGID_API, TEXT("ImeGetImeMenuItems() : "));
|
|
|
|
if ((pImeCtx = GetIMECtx(hIMC)) == NULL)
|
|
return 0;
|
|
|
|
if (!lpImeMenu)
|
|
{
|
|
if (!lpImeParentMenu)
|
|
{
|
|
if (dwFlags & IGIMIF_RIGHTMENU)
|
|
dwNumOfItems = NUM_ROOT_MENU_R;
|
|
else
|
|
dwNumOfItems = NUM_ROOT_MENU_L;
|
|
goto ImeGetImeMenuItemsExit;
|
|
}
|
|
else
|
|
{
|
|
if (dwFlags & IGIMIF_RIGHTMENU)
|
|
dwNumOfItems = NUM_SUB_MENU_R;
|
|
else
|
|
dwNumOfItems = NUM_SUB_MENU_L;
|
|
goto ImeGetImeMenuItemsExit;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
if (!lpImeParentMenu)
|
|
{
|
|
if (dwFlags & IGIMIF_RIGHTMENU)
|
|
{
|
|
lpImeMenu->cbSize = sizeof(IMEMENUITEMINFOW);
|
|
lpImeMenu->fType = 0;
|
|
lpImeMenu->fState = 0;
|
|
lpImeMenu->wID = IDIM_ROOT_MR_1;
|
|
lpImeMenu->hbmpChecked = 0;
|
|
lpImeMenu->hbmpUnchecked = 0;
|
|
OurLoadStringW(vpInstData->hInst, IDS_CONFIG, lpImeMenu->szString, IMEMENUITEM_STRING_SIZE);
|
|
lpImeMenu->hbmpItem = 0;
|
|
|
|
dwNumOfItems = NUM_ROOT_MENU_R;
|
|
}
|
|
else // Left Menu
|
|
{
|
|
// 1. Hangul Halfshape menu
|
|
lpImeMenu->cbSize = sizeof(IMEMENUITEMINFOW);
|
|
lpImeMenu->fType = IMFT_RADIOCHECK;
|
|
if ((pImeCtx->GetConversionMode() & IME_CMODE_HANGUL) &&
|
|
!(pImeCtx->GetConversionMode() & IME_CMODE_FULLSHAPE))
|
|
lpImeMenu->fState = IMFS_CHECKED;
|
|
else
|
|
lpImeMenu->fState = 0;
|
|
|
|
lpImeMenu->wID = IDIM_ROOT_ML_1;
|
|
lpImeMenu->hbmpChecked = 0;
|
|
lpImeMenu->hbmpUnchecked = 0;
|
|
OurLoadStringW(vpInstData->hInst, IDS_IME_HANGUL_HALF, lpImeMenu->szString, IMEMENUITEM_STRING_SIZE);
|
|
lpImeMenu->hbmpItem = 0;
|
|
|
|
// 2. Hangul Fullshape menu
|
|
lpImeMenu++;
|
|
lpImeMenu->cbSize = sizeof(IMEMENUITEMINFOW);
|
|
lpImeMenu->fType = IMFT_RADIOCHECK;
|
|
if ((pImeCtx->GetConversionMode() & IME_CMODE_HANGUL) &&
|
|
(pImeCtx->GetConversionMode()& IME_CMODE_FULLSHAPE))
|
|
lpImeMenu->fState = IMFS_CHECKED;
|
|
else
|
|
lpImeMenu->fState = 0;
|
|
|
|
lpImeMenu->wID = IDIM_ROOT_ML_2;
|
|
lpImeMenu->hbmpChecked = 0;
|
|
lpImeMenu->hbmpUnchecked = 0;
|
|
OurLoadStringW(vpInstData->hInst, IDS_IME_HANGUL_FULL, lpImeMenu->szString, IMEMENUITEM_STRING_SIZE);
|
|
lpImeMenu->hbmpItem = 0;
|
|
|
|
|
|
// 3. English Halfshape menu
|
|
lpImeMenu++;
|
|
lpImeMenu->cbSize = sizeof(IMEMENUITEMINFOW);
|
|
lpImeMenu->fType = IMFT_RADIOCHECK;
|
|
if (!(pImeCtx->GetConversionMode() & IME_CMODE_HANGUL) &&
|
|
!(pImeCtx->GetConversionMode() & IME_CMODE_FULLSHAPE))
|
|
lpImeMenu->fState = IMFS_CHECKED;
|
|
else
|
|
lpImeMenu->fState = 0;
|
|
|
|
lpImeMenu->wID = IDIM_ROOT_ML_3;
|
|
lpImeMenu->hbmpChecked = 0;
|
|
lpImeMenu->hbmpUnchecked = 0;
|
|
OurLoadStringW(vpInstData->hInst, IDS_IME_ENG_HALF, lpImeMenu->szString, IMEMENUITEM_STRING_SIZE);
|
|
lpImeMenu->hbmpItem = 0;
|
|
|
|
// 4. English Fullshape menu
|
|
lpImeMenu++;
|
|
lpImeMenu->cbSize = sizeof(IMEMENUITEMINFOW);
|
|
lpImeMenu->fType = IMFT_RADIOCHECK;
|
|
if ( !(pImeCtx->GetConversionMode() & IME_CMODE_HANGUL) &&
|
|
(pImeCtx->GetConversionMode() & IME_CMODE_FULLSHAPE))
|
|
lpImeMenu->fState = IMFS_CHECKED;
|
|
else
|
|
lpImeMenu->fState = 0;
|
|
lpImeMenu->wID = IDIM_ROOT_ML_4;
|
|
lpImeMenu->hbmpChecked = 0;
|
|
lpImeMenu->hbmpUnchecked = 0;
|
|
OurLoadStringW(vpInstData->hInst, IDS_IME_ENG_FULL, lpImeMenu->szString, IMEMENUITEM_STRING_SIZE);
|
|
lpImeMenu->hbmpItem = 0;
|
|
|
|
// return total number of menu list
|
|
dwNumOfItems = NUM_ROOT_MENU_L;
|
|
}
|
|
}
|
|
|
|
ImeGetImeMenuItemsExit:
|
|
return dwNumOfItems;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Private Helper Functions
|
|
//
|
|
|
|
//
|
|
// OS setup (Whistler,Win2K) sets this flag
|
|
//
|
|
BOOL IsInSystemSetupMode()
|
|
{
|
|
LPCSTR szKeyName = "SYSTEM\\Setup";
|
|
DWORD dwType, dwSize;
|
|
HKEY hKeySetup;
|
|
DWORD dwSystemSetupInProgress = 0;
|
|
DWORD dwUpgradeInProcess = 0;
|
|
DWORD dwOOBEInProcess = 0;
|
|
LONG lResult;
|
|
|
|
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_READ, &hKeySetup) == ERROR_SUCCESS)
|
|
{
|
|
dwSize = sizeof(DWORD);
|
|
lResult = RegQueryValueEx(hKeySetup, TEXT("SystemSetupInProgress"), NULL, &dwType, (LPBYTE) &dwSystemSetupInProgress, &dwSize);
|
|
dwSize = sizeof(DWORD);
|
|
lResult = RegQueryValueEx(hKeySetup, TEXT("UpgradeInProgress"), NULL, &dwType, (LPBYTE) &dwUpgradeInProcess, &dwSize);
|
|
dwSize = sizeof(DWORD);
|
|
lResult = RegQueryValueEx(hKeySetup, TEXT("OobeInProgress"), NULL, &dwType, (LPBYTE) &dwOOBEInProcess, &dwSize);
|
|
|
|
if (dwSystemSetupInProgress == 1 || dwUpgradeInProcess == 1 || dwOOBEInProcess == 1)
|
|
{
|
|
RegCloseKey (hKeySetup);
|
|
return TRUE;
|
|
}
|
|
RegCloseKey (hKeySetup);
|
|
}
|
|
|
|
if (IsWinNT5orUpper() && (IsRunningAsLocalSystem() || IsRunningInOOBE()))
|
|
return TRUE;
|
|
|
|
return FALSE ;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: RunningAsLocalSystem
|
|
//
|
|
// Synopsis: Detects whether we're running in the System account.
|
|
//
|
|
// Arguments: None
|
|
//
|
|
// Returns: TRUE if the service is running as LocalSystem
|
|
// FALSE if it is not or if any errors were encountered
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
BOOL IsRunningAsLocalSystem()
|
|
{
|
|
SID LocalSystemSid = { SID_REVISION,
|
|
1,
|
|
SECURITY_NT_AUTHORITY,
|
|
SECURITY_LOCAL_SYSTEM_RID };
|
|
|
|
|
|
|
|
BOOL fCheckSucceeded;
|
|
BOOL fIsLocalSystem = FALSE;
|
|
|
|
|
|
|
|
fCheckSucceeded = CheckTokenMembership(NULL,
|
|
&LocalSystemSid,
|
|
&fIsLocalSystem);
|
|
|
|
|
|
|
|
return (fCheckSucceeded && fIsLocalSystem);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
IsRunningInOOBE
|
|
|
|
Bug #401732:IME Status window does not come up on the registration page of WPA in the windows starting mode
|
|
----------------------------------------------------------------------------*/
|
|
BOOL IsRunningInOOBE()
|
|
{
|
|
TCHAR achModule[MAX_PATH];
|
|
TCHAR ch;
|
|
LPTSTR pch;
|
|
LPTSTR pchFileName;
|
|
|
|
if (GetModuleFileName(NULL, achModule, ARRAYSIZE(achModule)) == 0)
|
|
return FALSE;
|
|
|
|
pch = pchFileName = achModule;
|
|
|
|
while ((ch = *pch) != 0)
|
|
{
|
|
pch = CharNext(pch);
|
|
|
|
if (ch == '\\')
|
|
pchFileName = pch;
|
|
}
|
|
|
|
if (lstrcmpi(pchFileName, TEXT("msoobe.exe")) == 0)
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL PASCAL Select(HIMC hIMC, BOOL fSelect)
|
|
{
|
|
PCIMECtx pImeCtx = NULL;
|
|
BOOL fRet = fTrue;
|
|
|
|
// If IME select On
|
|
if (fSelect)
|
|
{
|
|
IMCPRIVATE imcPriv;
|
|
IImeIPoint1* pIP = NULL;
|
|
LPCImeIPoint pCIImeIPoint = NULL;
|
|
DWORD dwInitStatus = 0;
|
|
|
|
// Clear all private buffer
|
|
ZeroMemory(&imcPriv, sizeof(IMCPRIVATE));
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Create IImeIPoint1 instance
|
|
//////////////////////////////////////////////////////////////////////
|
|
if ((pCIImeIPoint = new CIImeIPoint)==NULL)
|
|
return fFalse;
|
|
// This increments the reference count
|
|
if (FAILED(pCIImeIPoint->QueryInterface(IID_IImeIPoint1, (VOID **)&pIP)))
|
|
return fFalse;
|
|
AST(pIP != NULL);
|
|
imcPriv.pIPoint = pIP;
|
|
|
|
// initialize IImeIPoint interface. This will create CImeCtx object
|
|
Dbg(DBGID_API, "ImeSelect - init IP");
|
|
pCIImeIPoint->Initialize(hIMC);
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Get CImeCtx object from IImeIPoint1
|
|
//////////////////////////////////////////////////////////////////////
|
|
pCIImeIPoint->GetImeCtx((VOID**)&pImeCtx);
|
|
AST(pImeCtx != NULL);
|
|
if (pImeCtx == NULL)
|
|
{
|
|
Dbg( DBGID_API, "ImeSelect - pImeCtx == NULL" );
|
|
return fFalse;
|
|
}
|
|
|
|
// Set pImeCtx
|
|
imcPriv.pImeCtx = pImeCtx;
|
|
|
|
// Set hIMC for compare
|
|
imcPriv.hIMC = hIMC;
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Set IMC private buffer
|
|
//////////////////////////////////////////////////////////////////////
|
|
Dbg(DBGID_API, TEXT("ImeSelect - set priv buf"));
|
|
SetPrivateBuffer(hIMC, &imcPriv, sizeof(IMCPRIVATE));
|
|
|
|
// Set Unicode flag
|
|
pImeCtx->SetUnicode(vfUnicode);
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Set initial IMC states if not already set
|
|
//////////////////////////////////////////////////////////////////////
|
|
pImeCtx->GetInitStatus(&dwInitStatus);
|
|
|
|
// if INPUTCONTEXT member are not initialized, initialize it.
|
|
if (!(dwInitStatus & INIT_CONVERSION))
|
|
{
|
|
pImeCtx->SetOpen(fFalse); // Initial IME close status == Alphanumeric mode
|
|
pImeCtx->SetConversionMode(IME_CMODE_ALPHANUMERIC); // Set initial conversion mode.
|
|
dwInitStatus |= INIT_CONVERSION;
|
|
}
|
|
#if 0
|
|
// !!! We don't need this code NT5 IMM does it !!!
|
|
else
|
|
{
|
|
// When IME switched from other IME, for example KKIME,
|
|
// status window sometimes not updated to correct info because KKIME maintains
|
|
// conversion mode independetly from Open/Close status and they uses non-Korean
|
|
// conversion mode like IME_CMODE_KATAKANA or IME_CMODE_ROMAN.
|
|
// So need to adjust conversion mode according to Open/Clos Status and current
|
|
// conversion mode.
|
|
|
|
if (pImeCtx->IsOpen() == fFalse && pImeCtx->GetConversionMode() != IME_CMODE_ALPHANUMERIC)
|
|
pImeCtx->SetConversionMode(IME_CMODE_ALPHANUMERIC);
|
|
else
|
|
if (pImeCtx->IsOpen() && (pImeCtx->GetConversionMode() & (IME_CMODE_HANGUL|IME_CMODE_FULLSHAPE)) == fFalse)
|
|
pImeCtx->SetConversionMode(IME_CMODE_HANGUL);
|
|
}
|
|
#endif
|
|
|
|
if (!(dwInitStatus & INIT_LOGFONT))
|
|
{
|
|
LOGFONT* pLf = pImeCtx->GetLogFont();
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
// Note: Win98 does not support CreateFontW().
|
|
// But, imc->logfont->lfFaceName is UNICODE!
|
|
if (IsMemphis() || IsWinNT())
|
|
StrCopyW((LPWSTR)pLf->lfFaceName, wzIMECompFont);
|
|
else
|
|
lstrcpyA(pLf->lfFaceName, szIMECompFont);
|
|
|
|
// Gulim 9pt
|
|
pLf->lfHeight = 16;
|
|
pLf->lfEscapement = 0;
|
|
pLf->lfOrientation = 0;
|
|
pLf->lfWeight = FW_NORMAL;
|
|
pLf->lfItalic = fFalse;
|
|
pLf->lfUnderline = fFalse;
|
|
pLf->lfStrikeOut = fFalse;
|
|
pLf->lfCharSet = HANGUL_CHARSET;
|
|
pLf->lfOutPrecision = OUT_DEFAULT_PRECIS;
|
|
pLf->lfClipPrecision = CLIP_DEFAULT_PRECIS;
|
|
pLf->lfQuality = DEFAULT_QUALITY;
|
|
pLf->lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;
|
|
dwInitStatus |= INIT_LOGFONT;
|
|
}
|
|
|
|
if (!(dwInitStatus & INIT_STATUSWNDPOS))
|
|
{
|
|
if (pImeCtx->GetGDataRaw())
|
|
{
|
|
pImeCtx->SetStatusWndPos((pImeCtx->GetGDataRaw())->ptStatusPos);
|
|
}
|
|
dwInitStatus |= INIT_STATUSWNDPOS;
|
|
}
|
|
|
|
if (!(dwInitStatus & INIT_COMPFORM))
|
|
{
|
|
pImeCtx->SetCompositionFormStyle(CFS_DEFAULT);
|
|
dwInitStatus |= INIT_COMPFORM;
|
|
}
|
|
|
|
// Set New initialization status
|
|
pImeCtx->SetInitStatus(dwInitStatus);
|
|
}
|
|
else // fSelect
|
|
{
|
|
IImeIPoint1* pIP = GetImeIPoint(hIMC);
|
|
LPCImePadSvr lpCImePadSvr;
|
|
CIMCPriv ImcPriv;
|
|
LPIMCPRIVATE pImcPriv;
|
|
|
|
// Cleanup Private buffer and release IImeIPoint1
|
|
// Always OnImeSelect already cleanup.
|
|
if (pIP)
|
|
pIP->Release();
|
|
|
|
lpCImePadSvr = CImePadSvr::GetCImePadSvr();
|
|
if(lpCImePadSvr)
|
|
lpCImePadSvr->SetIUnkIImeIPoint((IUnknown *)NULL);
|
|
|
|
if (ImcPriv.LockIMC(hIMC))
|
|
{
|
|
ImcPriv->pIPoint = (IImeIPoint1*)NULL;
|
|
ImcPriv->pImeCtx = NULL;
|
|
ImcPriv.ResetPrivateBuffer();
|
|
}
|
|
}
|
|
|
|
Dbg(DBGID_API, "Select() exit hIMC=%x, fSelect=%d", hIMC, fSelect);
|
|
return (fTrue);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// Conversion mode and Open/Close Helper functions
|
|
// In Kor IME, Open status equal to Han mode and Close status equal to Eng mode
|
|
// So, we change pair open status with conversion mode, and vice versa.
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// UpdateOpenCloseState()
|
|
// Purpose :
|
|
// Set Open/Close state according to conversion mode
|
|
// if Eng mode - set Close
|
|
// if Han mode - Set Open
|
|
VOID PASCAL UpdateOpenCloseState(PCIMECtx pImeCtx)
|
|
{
|
|
if ( (pImeCtx->GetConversionMode() & IME_CMODE_HANGUL)
|
|
|| (pImeCtx->GetConversionMode() & IME_CMODE_FULLSHAPE)
|
|
|| (pImeCtx->GetConversionMode() & IME_CMODE_HANJACONVERT) )
|
|
{
|
|
if (pImeCtx->IsOpen() == fFalse)
|
|
OurImmSetOpenStatus(pImeCtx->GetHIMC(), fTrue);
|
|
}
|
|
else
|
|
{
|
|
if (pImeCtx->IsOpen())
|
|
OurImmSetOpenStatus(pImeCtx->GetHIMC(), fFalse);
|
|
}
|
|
}
|
|
|
|
#if NOTUSED
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// UpdateConversionState()
|
|
// Purpose :
|
|
// Set Conversion state according to Open/Close status
|
|
// if Open - Set Han mode
|
|
// if Close - Set Eng mode
|
|
VOID PASCAL UpdateConversionState(HIMC hIMC)
|
|
{
|
|
LPINPUTCONTEXT lpIMC;
|
|
|
|
if (lpIMC = OurImmLockIMC(hIMC))
|
|
{
|
|
if (OurImmGetOpenStatus(hIMC))
|
|
{
|
|
if ( !(lpIMC->fdwConversion & (IME_CMODE_HANGUL|IME_CMODE_FULLSHAPE)) )
|
|
{
|
|
OurImmSetConversionStatus(hIMC, lpIMC->fdwConversion | IME_CMODE_HANGUL,
|
|
lpIMC->fdwSentence);
|
|
}
|
|
DbgAssert(lpIMC->fdwConversion & (IME_CMODE_HANGUL|IME_CMODE_FULLSHAPE));
|
|
}
|
|
else
|
|
{
|
|
// BUG: IME_CMODE_HANJACONVERT ????
|
|
if (lpIMC->fdwConversion & (IME_CMODE_HANGUL|IME_CMODE_FULLSHAPE))
|
|
OurImmSetConversionStatus(hIMC, lpIMC->fdwConversion & ~(IME_CMODE_HANGUL|IME_CMODE_FULLSHAPE),
|
|
lpIMC->fdwSentence);
|
|
DbgAssert(!(lpIMC->fdwConversion & IME_CMODE_HANGUL));
|
|
}
|
|
OurImmUnlockIMC(hIMC);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*----------------------------------------------------------------------------
|
|
Banja2Junja
|
|
|
|
Convert Ascii Half shape to Full shape character
|
|
----------------------------------------------------------------------------*/
|
|
WCHAR PASCAL Banja2Junja(WCHAR bChar) //, LPDWORD lpTransBuf, LPCOMPOSITIONSTRING lpCompStr)
|
|
{
|
|
WCHAR wcJunja;
|
|
|
|
if (bChar == L' ')
|
|
wcJunja = 0x3000; // FullWidth space
|
|
else
|
|
if (bChar == L'~')
|
|
wcJunja = 0xFF5E;
|
|
else
|
|
if (bChar == L'\\')
|
|
wcJunja = 0xFFE6; // FullWidth WON sign
|
|
else
|
|
wcJunja = 0xFF00 + (WORD)(bChar - (BYTE)0x20);
|
|
|
|
Dbg(DBGID_Misc, TEXT("Banja2Junja: wcJunja = 0x%04X"), wcJunja);
|
|
return wcJunja;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
IsKSC5601
|
|
|
|
Test if character within the KSC 5601
|
|
Return True if input Unicode chracter has correspoding KSC 5601 code
|
|
----------------------------------------------------------------------------*/
|
|
BOOL PASCAL IsKSC5601(WCHAR wcCur)
|
|
{
|
|
WCHAR wcUni[2];
|
|
BYTE szWansung[4];
|
|
|
|
wcUni[0] = wcCur;
|
|
wcUni[1] = 0;
|
|
|
|
// check if compatibility Hangul jamo
|
|
if (wcCur >= 0x3131 && wcCur <= 0x3163)
|
|
return fTrue;
|
|
|
|
// Convert to ANSI
|
|
if (WideCharToMultiByte(CP_KOREA, 0, wcUni, 1, (LPSTR)szWansung, sizeof(szWansung), NULL, NULL)==0)
|
|
{
|
|
DbgAssert(0);
|
|
return fFalse;
|
|
}
|
|
else
|
|
{
|
|
// KSC 5601 Area in 949 cp
|
|
if ( (szWansung[0]>=0xB0 && szWansung[0]<=0xC8)
|
|
&& (szWansung[1]>=0xA1 && szWansung[1]<=0xFE) )
|
|
return fTrue;
|
|
else
|
|
return fFalse;
|
|
}
|
|
}
|
|
|