|
|
/****************************** 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; }
|