Leaked source code of windows server 2003
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.
 
 
 
 
 
 

608 lines
16 KiB

/****************************** Module Header ******************************\
* Module Name: clwinnls.c
*
* Copyright (c) 1985 - 1999, Microsoft Corporation
*
* This module contains all the code for the NT 3.x IMM API functions.
*
* History:
* 11-Jan-1995 wkwok Created.
* 07-May-1996 takaok Cleaned up.
\***************************************************************************/
#include "precomp.h"
#pragma hdrstop
BOOL CheckCountry();
BOOL ImmEnableIME( HWND hwnd, BOOL fEnable );
BOOL IMPGetIMEWorker( HKL hkl, LPIMEPROW lpImeProW );
VOID ConvertImeProWtoA( LPIMEPROA lpImeProA, LPIMEPROW lpImeProW );
LRESULT SendIMEMessageAll( HWND hwndApp, HANDLE lParam, BOOL fAnsi );
BOOL ImmWINNLSEnableIME(
HWND hwndApp,
BOOL bFlag)
{
if ( ! CheckCountry() ) {
SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
return FALSE;
}
return ImmEnableIME( hwndApp, bFlag );
}
//
// returns the "enable/disable" state of the
// caller thread's default input context.
//
BOOL ImmWINNLSGetEnableStatus(
HWND hwndApp)
{
if ( ! CheckCountry() ) {
SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
return FALSE;
}
return (ImmGetSaveContext(hwndApp, IGSC_WINNLSCHECK) != NULL_HIMC);
}
UINT WINAPI ImmWINNLSGetIMEHotkey(
HWND hwndIme)
{
UNREFERENCED_PARAMETER(hwndIme);
//
// Win95/NT3.51 behavior, i.e. always return 0.
//
return 0;
}
/***************************************************************************\
*
* IME APIs
*
\***************************************************************************/
LRESULT WINAPI ImmSendIMEMessageExW(
HWND hwndApp,
LPARAM lParam)
{
return SendIMEMessageAll( hwndApp, (HANDLE)lParam, FALSE );
}
LRESULT WINAPI ImmSendIMEMessageExA(
HWND hwndApp,
LPARAM lParam)
{
return SendIMEMessageAll( hwndApp, (HANDLE)lParam, TRUE );
}
LRESULT SendIMEMessageAll(
HWND hwndApp,
HANDLE hMemImeStruct,
BOOL fAnsi )
{
HWND hWnd;
LPIMESTRUCT lpIme;
LRESULT lResult;
#ifdef LATER
// Need for MSTEST30a(32bit)...
// If different process of hWnd in SendIMEMessageEx, then we should be inter-send messag
on this.
if (PtiCurrent() != pti) {
HWND hDefIMEWnd = ImmGetDefaultIMEWnd(hWnd);
if (hDefIMEWnd)
return SendMessage(hDefIMEWnd,WM_CONVERTREQUESTEX,(WPARAM)hWnd,lParam);
}
#endif
//
// the passed handle must be the handle of
// global memory block.
//
lpIme = (LPIMESTRUCT)GlobalLock( hMemImeStruct );
if ( lpIme == NULL ) {
return (FALSE);
}
if ( ! CheckCountry( ) ) {
lpIme->wParam = IME_RS_INVALID;
GlobalUnlock( hMemImeStruct );
return (FALSE);
}
//
// We don't need to handle if it's non-IME layout
//
if ( ! ImmIsIME( GetKeyboardLayout(0) ) ) {
lpIme->wParam = IME_RS_INVALID;
GlobalUnlock( hMemImeStruct );
return (FALSE);
}
//
// check if the initialize of IMM has been done.
//
if ( !IsWindow(ImmGetDefaultIMEWnd(hwndApp)) ) {
//
// for Win3.1/Win95 compatibility
// we need to return TRUE here.
//
// PPT4 calls SendImeMessage at the very
// early stage of initialization. If we
// return FALSE here, it thinks IME is
// not available.
//
if ( lpIme->fnc == 0x07 ) // IME_GETVERSION
//
// Excel5.0J calls this function at the early stage
// and we need to return version number.
//
lResult = IMEVER_31;
else
lResult = TRUE;
GlobalUnlock( hMemImeStruct );
return lResult;
}
//
// caller may give us NULL window handle...
//
if ( !IsWindow(hwndApp) ) {
hWnd = GetFocus();
} else {
hWnd = hwndApp;
}
lResult = TranslateIMESubFunctions( hWnd, lpIme, fAnsi );
GlobalUnlock( hMemImeStruct );
return lResult;
}
/***************************************************************************\
*
* IMP APIs
*
\***************************************************************************/
BOOL WINAPI ImmIMPGetIMEW(
HWND hwndApp,
LPIMEPROW lpImeProW)
{
UNREFERENCED_PARAMETER(hwndApp);
if ( ! CheckCountry() ) {
SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
return FALSE;
}
return IMPGetIMEWorker( GetKeyboardLayout(0), lpImeProW );
}
BOOL WINAPI ImmIMPGetIMEA(
HWND hwndApp,
LPIMEPROA lpImeProA)
{
IMEPROW ImeProW;
UNREFERENCED_PARAMETER(hwndApp);
if ( ! CheckCountry() ) {
SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
return FALSE;
}
if ( IMPGetIMEWorker( GetKeyboardLayout(0), &ImeProW ) ) {
ConvertImeProWtoA( lpImeProA, &ImeProW );
return TRUE;
}
return FALSE;
}
VOID ConvertImeProWtoA( LPIMEPROA lpImeProA, LPIMEPROW lpImeProW )
{
lpImeProA->hWnd = lpImeProW->hWnd;
lpImeProA->InstDate = lpImeProW->InstDate;
lpImeProA->wVersion = lpImeProW->wVersion;
WideCharToMultiByte( CP_ACP, 0,
lpImeProW->szDescription, -1,
lpImeProA->szDescription, sizeof(lpImeProA->szDescription),
NULL, NULL );
WideCharToMultiByte( CP_ACP, 0,
lpImeProW->szName, -1,
lpImeProA->szName, sizeof(lpImeProA->szName),
NULL, NULL );
lpImeProA->szOptions[0] = '\0';
}
DATETIME CleanDate = {0};
BOOL IMPGetIMEWorker( HKL hkl, LPIMEPROW lpImeProW )
{
IMEINFOEX iiex;
if ( ImmGetImeInfoEx( &iiex, ImeInfoExKeyboardLayout, (PVOID)&hkl) ) {
lpImeProW->hWnd = NULL;
lpImeProW->InstDate = CleanDate;
lpImeProW->wVersion = iiex.dwImeWinVersion;
lstrcpynW( lpImeProW->szDescription, iiex.wszImeDescription, 50 );
lstrcpynW( lpImeProW->szName, iiex.wszImeFile, 80 );
lstrcpynW( lpImeProW->szOptions, TEXT(""), 1 );
return TRUE;
}
return FALSE;
}
BOOL WINAPI ImmIMPQueryIMEW(
LPIMEPROW lpImeProW)
{
BOOL fResult = FALSE;
INT numLayouts = 0;
HKL *phklRoot = NULL;
HKL *phkl = NULL;
if ( ! CheckCountry() ) {
SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
return FALSE;
}
//
// get the number of keyboard layouts available
//
numLayouts = GetKeyboardLayoutList( 0, NULL );
if ( numLayouts > 0 ) {
//
// allocate the buffer for the array of layouts.
// +1 for a NULL sentinel
//
phklRoot = ImmLocalAlloc( 0, (numLayouts+1) * sizeof(HKL) );
if ( phklRoot != NULL ) {
//
// get the keyboard layouts
//
if ( GetKeyboardLayoutList( numLayouts, phklRoot ) == numLayouts ) {
//
// put a NULL sentinel at the end of the buffer
//
*(phklRoot+numLayouts) = (HKL)NULL;
if ( lpImeProW->szName[0] == L'\0' ) {
//
// This is the first call of IMPQueryIME
// We will start at the first layout.
//
phkl = phklRoot;
} else {
//
// The caller specifies the name of IME.
// We will start at the next layout.
// Note this assumes that the order of keyboard layouts
// returned by GetKeyboardLayoutList() is not changed
// between calls. ( Though actually there is no such
// guarantee, we ignore the chance of the changing
// the list of keyboard layouts for now. )
//
IMEINFOEX iiex;
//
// Let's retrieve the corresponding hkl
// from the IME filename specified by the caller.
//
if ( ImmGetImeInfoEx( &iiex,
ImeInfoExImeFileName,
(PVOID)lpImeProW->szName ) ) {
//
// let phkl point to the next hkl
//
phkl = phklRoot;
while ( *phkl != NULL ) {
if ( *phkl++ == iiex.hkl ) {
break;
}
}
}
}
if ( phkl != NULL ) {
while ( *phkl != NULL ) {
//
// IMPGetIMEWorker will return FALSE if
// the hkl specified is a non-IME layout.
//
if ( fResult = IMPGetIMEWorker(*phkl++, lpImeProW) ) {
break;
}
}
}
}
ImmLocalFree( phklRoot );
}
}
return fResult;
}
BOOL WINAPI ImmIMPQueryIMEA(
LPIMEPROA lpImeProA)
{
IMEPROW ImeProW;
if ( ! CheckCountry() ) {
SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
return FALSE;
}
if ( lpImeProA->szName[0] != '\0' ) {
//
// Convert MultiByteString(szName) to UnicodeString
//
INT i;
i = MultiByteToWideChar( CP_ACP, (DWORD)MB_PRECOMPOSED,
lpImeProA->szName,
-1,
ImeProW.szName,
(INT)sizeof(ImeProW.szName)/sizeof(WCHAR));
if ( i == 0 ) {
return FALSE;
}
} else {
ImeProW.szName[0] = L'\0';
}
if ( ImmIMPQueryIMEW( &ImeProW ) ) {
ConvertImeProWtoA( lpImeProA, &ImeProW );
return TRUE;
}
return FALSE;
}
BOOL WINAPI ImmIMPSetIMEW(
HWND hwndApp,
LPIMEPROW lpImeProW)
{
IMEINFOEX iiex;
HKL hkl = NULL;
UNREFERENCED_PARAMETER(hwndApp);
if ( ! CheckCountry() ) {
SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
return FALSE;
}
if ( lpImeProW->szName[0] != L'\0' ) {
//
// IME name is specified. Switch to the IME specified.
//
if ( ImmGetImeInfoEx(&iiex,ImeInfoExImeFileName,(PVOID)lpImeProW->szName) ) {
hkl = iiex.hkl;
}
} else {
//
// IME name is not specified. Switch to a non-IME layout
//
INT numLayouts;
HKL *phkl;
HKL *phklRoot;
numLayouts = GetKeyboardLayoutList( 0, NULL );
if ( numLayouts > 0 ) {
phkl = phklRoot = ImmLocalAlloc( 0, (numLayouts + 1) * sizeof(HKL) );
if ( phkl != NULL ) {
if ( GetKeyboardLayoutList( numLayouts, phkl ) == numLayouts ) {
*(phklRoot+numLayouts) = (HKL)NULL;
while ( *phkl != NULL ) {
if ( ! ImmIsIME( *phkl ) ) {
hkl = *phkl;
break;
}
phkl++;
}
}
ImmLocalFree( phklRoot );
}
}
}
if ( hkl != NULL && GetKeyboardLayout(0) != hkl ) {
HWND hwndFocus;
hwndFocus = GetFocus();
if ( hwndFocus != NULL ) {
PostMessage( hwndFocus,
WM_INPUTLANGCHANGEREQUEST,
DEFAULT_CHARSET,
(LPARAM)hkl);
return TRUE;
}
}
return FALSE;
}
BOOL WINAPI ImmIMPSetIMEA(
HWND hwndApp,
LPIMEPROA lpImeProA)
{
IMEPROW ImeProW;
UNREFERENCED_PARAMETER(hwndApp);
if ( ! CheckCountry() ) {
SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
return FALSE;
}
if ( lpImeProA->szName[0] != '\0' ) {
//
// Convert MultiByteString(szName) to UnicodeString
//
INT i;
i = MultiByteToWideChar( CP_ACP, (DWORD)MB_PRECOMPOSED,
lpImeProA->szName,
-1,
ImeProW.szName,
(INT)sizeof(ImeProW.szName)/sizeof(WCHAR));
if ( i == 0 ) {
return FALSE;
}
} else {
ImeProW.szName[0] = L'\0';
}
return ImmIMPSetIMEW(hwndApp, &ImeProW);
}
//
// if the "enable/disable" state of the default input context
// of the caller thread is same as the state specified by
// fEnalble parameter, this function does nothing but returns
// the current "enable/disable" state.
//
// if fEnable is FALSE, this function disables the default
// input context of caller thread.
//
// if fEnable is TRUE, this function enables the default
// input context of caller thread.
//
//
BOOL ImmEnableIME(
HWND hwnd,
BOOL fEnable
)
{
HIMC hImc;
PCLIENTIMC pClientImc;
BOOL fCurrentState;
HWND hwndFocus;
BOOL fImeInitialized;
//
// Get the caller thread's default input context
//
hImc = (HIMC)NtUserGetThreadState(UserThreadStateDefaultInputContext);
if ( hImc == NULL_HIMC ) {
return FALSE;
}
pClientImc = ImmLockClientImc( hImc );
if ( pClientImc == NULL ) {
return FALSE;
}
//
// we will return the curren t"enable/disable" state of the input context
//
fCurrentState = TestICF(pClientImc, IMCF_WINNLSDISABLE) ? FALSE : TRUE;
//
// if the current thread (caller thread) doesn't have the focus window,
// UI windows will not be updated. When we're called later, we will end
// up to just return the fCurrentState without calling ImmSetActiveContext.
// To avoid that, the "same status" check below is disabled...
if ( (fCurrentState && fEnable) || (!fCurrentState && !fEnable) ) {
ImmUnlockClientImc( pClientImc );
//
// nothing has been changed. return the current state
//
return fCurrentState;
}
if ( ! IsWindow(hwnd) ) {
hwndFocus = GetFocus();
} else {
hwndFocus = hwnd;
}
//
// check if the initialize of IMM has been done.
//
if ( IsWindow(ImmGetDefaultIMEWnd(hwndFocus)) ) {
fImeInitialized = TRUE;
} else {
fImeInitialized = FALSE;
}
if ( fImeInitialized ) {
if ( ! fEnable ) {
//
// we're going to disable the target IMC
//
//
// make the target IMC non-active
//
ImmSetActiveContext( hwndFocus, hImc, FALSE );
} else {
//
// we're going to enable the target IMC
//
//
// make NULL context non-active
//
ImmSetActiveContext( hwndFocus, NULL_HIMC, FALSE );
}
}
//
// update the state of the input context
//
if ( fEnable )
ClrICF( pClientImc, IMCF_WINNLSDISABLE );
else
SetICF( pClientImc, IMCF_WINNLSDISABLE );
ImmUnlockClientImc( pClientImc );
if ( fImeInitialized ) {
if ( fEnable ) {
//
// we're going to enable the target IMC
//
//
// make the target IMC active
//
ImmSetActiveContext( hwndFocus, hImc, TRUE );
} else {
//
// we're going to disable the target IMC
//
//
// make NULL context active
//
ImmSetActiveContext( hwndFocus, NULL_HIMC, TRUE );
}
}
//
// the return value is previous state
//
return fCurrentState;
}
BOOL CheckCountry()
{
WORD LangId;
LangId = PRIMARYLANGID(LANGIDFROMLCID(GetSystemDefaultLCID()));
if ( LangId == LANG_JAPANESE || LangId == LANG_KOREAN ) {
return TRUE;
}
return FALSE;
}