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.
 
 
 
 
 
 

1496 lines
44 KiB

/****************************** Module Header ******************************\
* Module Name: transsub.c
*
* Copyright (c) 1985 - 1999, Microsoft Corporation
*
* This module contains the translation layer functions
* of the sub functions of SendImeMessageEx.
*
* History:
* 21-May-1996 takaok Created.
\***************************************************************************/
#include "precomp.h"
#pragma hdrstop
LRESULT TransSetOpenK( HWND hWndApp, HIMC hImc, LPIMESTRUCT lpIme );
LRESULT TransSetOpenJ( HWND hWndApp, HIMC hImc, LPIMESTRUCT lpIme );
LRESULT TransGetOpenK( HWND hWndApp, HIMC hImc, LPIMESTRUCT lpIme, BOOL fAnsi );
LRESULT TransGetOpenJ( HWND hWndApp, HIMC hImc, LPIMESTRUCT lpIme, BOOL fAnsi );
LRESULT TransMoveImeWindow( HWND hWndApp, HIMC hImc, LPIMESTRUCT lpIme);
LRESULT TransSetConversionWindow( HWND hWndApp, HIMC hImc, LPIMESTRUCT lpIme );
LRESULT TransSetConversionMode( HIMC hImc, LPIMESTRUCT lpIme );
LRESULT TransGetMode( HIMC hImc );
LRESULT TransGetConversionMode( HIMC hImc );
LRESULT TransSetMode( HIMC hImc, LPIMESTRUCT lpIme );
LRESULT TransSendVKey( HWND hWndApp, HIMC hImc, LPIMESTRUCT lpIme, BOOL fAnsi );
LRESULT TransEnterWordRegisterMode( HWND hWndApp, LPIMESTRUCT lpIme, BOOL fAnsi);
LRESULT TransSetConversionFontEx( HWND hWndApp, HIMC hImc, LPIMESTRUCT lpIme, BOOL fAnsi);
LRESULT TransHanjaMode( HWND hWndApp, HIMC hImc, LPIMESTRUCT lpIme);
UINT Get31ModeFrom40ModeJ( DWORD fdwConversion );
UINT Get31ModeFrom40ModeK( DWORD fdwConversion );
LRESULT TransVKDBEMode( HIMC hImc, WPARAM wVKDBE );
BOOL SetFontForMCWVERTICAL( HWND hWndApp, HIMC hImc, LPINPUTCONTEXT pInputContext, BOOL fVert );
BOOL IsForegroundThread( HWND );
BOOL FixLogfont( LPLOGFONTW lplfW, BOOL fVert );
BOOL MySetCompFont( HWND, HIMC, LPLOGFONTW );
BOOL MySetCompWindow( HWND, HIMC, LPCOMPOSITIONFORM );
BOOL MySetCandidateWindow( HWND, HIMC, LPCANDIDATEFORM );
BOOL MyPostImsMessage( HWND hWndApp, WPARAM wParam, LPARAM lParam);
//===================================================================
// TranslateIMESubFunctions
//==========================
//
// KOREAN and JAPANESE common translate routine for the
// sub functions of SendImeMessageEx.
//
// History:
// 21-May-1996 takaok Created.
//
//===================================================================
LRESULT TranslateIMESubFunctions(
HWND hWndApp,
LPIMESTRUCT lpIme,
BOOL fAnsi)
{
HIMC hImc;
LRESULT lRet;
DWORD dwLangID;
hImc = ImmGetSaveContext( hWndApp, IGSC_DEFIMCFALLBACK );
if ( hImc == NULL_HIMC ) {
return FALSE;
}
dwLangID = PRIMARYLANGID(LANGIDFROMLCID(GetSystemDefaultLCID()));
switch (lpIme->fnc) {
case 0x03: // IME_QUERY, IME_GETIMECAPS: KOREAN & JAPANESE
lRet = TRUE;
break;
case 0x04: // IME_SETOPEN: KOREAN & JAPANESE
if ( dwLangID == LANG_KOREAN )
lRet = TransSetOpenK( hWndApp, hImc, lpIme );
else
lRet = TransSetOpenJ( hWndApp, hImc, lpIme );
break;
case 0x05: // IME_GETOPEN: KOREAN & JAPANESE
if ( dwLangID == LANG_KOREAN )
lRet = TransGetOpenK( hWndApp, hImc, lpIme, fAnsi );
else
lRet = TransGetOpenJ( hWndApp, hImc, lpIme, fAnsi );
break;
case 0x06: // IME_ENABLEDOSIME, IME_ENABLE
// internal functions are not supported
lRet = FALSE;
break;
case 0x07: // IME_GETVERSION: KOREAN & JAPANESE
lRet = IMEVER_31;
break;
case 0x08: // IME_MOVEIMEWINDOW, IME_SETCONVERSIONWINDOW: KOREAN & JAPANESE
if ( dwLangID == LANG_KOREAN ) {
//
// IME_MOVEIMEWINDOW for KOREAN
//
lRet = TransMoveImeWindow(hWndApp, hImc, lpIme);
} else {
//
// IME_MOVECONVERTWINDOW or IME_SETCONVERSIONWINDOW for JAPANESE
//
lRet = TransSetConversionWindow( hWndApp, hImc, lpIme );
}
break;
// case 0x09: // undefined
case 0x10: // IME_SETCONVERSIONMODE: JAPANESE
if ( dwLangID == LANG_JAPANESE ) {
lRet = TransSetConversionMode( hImc, lpIme );
} else {
lRet = FALSE;
}
break;
case 0x11: // IME_GETCONVERSIONMODE, IME_GETMODE: // KOREAN & JAPANESE
// Use hSaveIMC, If WINNSEnableIME(FALSE).
if ( dwLangID == LANG_KOREAN ) {
//
// IME_GETMODE for KOREAN
//
lRet = TransGetMode( hImc );
} else {
//
// IME_GETCONVERSIONMODE for JAPANESE
//
lRet = TransGetConversionMode( hImc );
}
break;
case 0x12: // IME_SET_MODE, IME_SETFONT, IME_SETCONVERSIONFONT: KOREAN & JAPANESE
if ( dwLangID == LANG_KOREAN ) {
//
// IME_SET_MODE for KOREAN
//
lRet = TransSetMode( hImc, lpIme );
} else {
//
// IME_SETCONVERSIONFONT for JAPANESE
//
lRet = FALSE; // should not be called. use SETCONVERSIONFONTEX instead
}
break;
case 0x13: // IME_SENDVKEY, IME_SENDKEY: JAPANESE only
if ( dwLangID == LANG_JAPANESE ) {
lRet = TransSendVKey( hWndApp, hImc, lpIme, fAnsi );
} else {
lRet = FALSE;
}
break;
//
// internal sub functions are not supported
//
// case 0x14: // IME_DESTROY, IME_DESTROYIME
// case 0x15: // IME_PRIVATE
// case 0x16: // IME_WINDOWUPDATE
// case 0x17: // IME_SELECT
case 0x18: // IME_ENTERWORDREGISTERMODE: JAPANESE only
if ( dwLangID == LANG_JAPANESE ) {
lRet = TransEnterWordRegisterMode( hWndApp, lpIme, fAnsi);
} else {
lRet = FALSE;
}
break;
case 0x19: // IME_SETCONVERSIONFONTEX: JAPANESE only
if ( dwLangID == LANG_JAPANESE ) {
lRet = TransSetConversionFontEx( hWndApp, hImc, lpIme, fAnsi);
} else {
lRet = FALSE;
}
break;
//
// internal sub functions are not supported
//
// case 0x1A: // IME_DBCSNAME
// case 0x1B: // IME_MAXKEY
// case 0x1C: // IME_WINNLS_SK
case 0x20: // IME_CODECONVERT: KOREAN only
if ( dwLangID == LANG_KOREAN ) {
if (TransCodeConvert( hImc, lpIme))
lRet = lpIme->wParam;
else
lRet = 0;
} else {
lRet = 0;
}
break;
case 0x21: // IME_CONVERTLIST: KOREAN only
if ( dwLangID == LANG_KOREAN ) {
lRet = TransConvertList( hImc, lpIme);
} else {
lRet = FALSE;
}
break;
//
// internal sub functions and undefined sub functions are not supported
//
// case 0x22: // IME_INPUTKEYTOSEQUENCE
// case 0x23: // IME_SEQUENCETOINTERNAL
// case 0x24: // IME_QUERYIMEINFO
// case 0x25: // IME_DIALOG
// case 0x26 - 0x2f: // undefined
case 0x30: // IME_AUTOMATA: KOREAN only
if ( dwLangID == LANG_KOREAN ) {
lRet = ImmEscape(GetKeyboardLayout(0), hImc, IME_AUTOMATA, lpIme);
} else {
lRet = FALSE;
}
break;
case 0x31: // IME_HANJAMODE: KOREAN only
if ( dwLangID == LANG_KOREAN ) {
lRet = TransHanjaMode( hWndApp, hImc, lpIme);
} else {
lRet = FALSE;
}
break;
//
// case 0x32 - 0x3f: // undefined
//
case 0x40: // IME_GETLEVEL: KOREAN only
if ( dwLangID == LANG_KOREAN ) {
lRet = TransGetLevel( hWndApp );
} else {
lRet = FALSE;
}
break;
case 0x41: // IME_SETLEVEL: KOREAN only
if ( dwLangID == LANG_KOREAN ) {
lRet = TransSetLevel( hWndApp, lpIme);
} else {
lRet = FALSE;
}
break;
case 0x42: // IME_GETMNTABLE: KOREAN only
if ( dwLangID == LANG_KOREAN ) {
lRet = TransGetMNTable( hImc, lpIme);
} else {
lRet = FALSE;
}
break;
#if defined(PENAPI)
case IME_SETUNDETERMINESTRING:
lRet = FSetUndetermine( hImc, (HGLOBAL)lpIME->lParam1);
break;
case IME_SETCAPTURE:
lRet = FEnablePenUi((HWND)lpIME->wParam, (lpIME->wParam != NULL));
break;
#endif
#ifdef LATER // IME_NOTIFYWOWTASKEXIT
case IME_NOTIFYWOWTASKEXIT:
//
// Destroy the default IME window of WOW 16bit
// applications now. We should not wait for the
// server wow thread clean up that will destroy the
// IME window because usrsrv won't send WM_DESTROY
// to non-server side window procedures. Some IMEs
// must receive WM_DESTROY to free up 32 bit objects.
//
// kksuzuka #7982:IME memory leak on WOW16 applications.
//
PIMMTHREADINFO piti = PitiCurrent();
if ( piti != NULL && IsWindow( piti->hwndDefaultIme ) ) {
DestroyWindow( piti->hwndDefaultIme );
}
return TRUE;
#endif
default:
//
// private/internal/undefined functions are not supported
//
lRet = FALSE;
break;
}
return (lRet);
}
//===================================================================
// TransSetOpenK
//===============
//
// KOREAN only
//
// History:
// xx-xx-1995 xxx Created
//
//===================================================================
LRESULT TransSetOpenK( HWND hWndApp, HIMC hImc, LPIMESTRUCT lpIme )
{
// NOTE: We will use this function instead of ImmEscape().
LRESULT lRet;
lRet = ImmEscape(GetKeyboardLayout(0), hImc, IME_SETOPEN, lpIme);
return (lRet);
UNREFERENCED_PARAMETER(hWndApp);
}
//===================================================================
// TransSetOpenJ
//===============
//
// Japanese only
//
// History:
// 20-May-1996 takaok Created
//
//===================================================================
LRESULT TransSetOpenJ( HWND hWndApp, HIMC hImc, LPIMESTRUCT lpIme )
{
LRESULT lRet;
lRet = ImmGetOpenStatus( hImc );
//
// if the owner thread of hIMC doesn't have the input focus,
// we won't call UI.
//
if ( !IsForegroundThread( NULL ) && !GetFocus() ) {
//
// this thread doesn't have focus.
// let's update the input context and return without calling UI
//
PINPUTCONTEXT pInputContext;
if ( (pInputContext = ImmLockIMC(hImc)) != NULL ) {
if ( (pInputContext->fOpen && ! lpIme->wParam ) ||
(!pInputContext->fOpen && lpIme->wParam ) )
{
pInputContext->fOpen = (BOOL)lpIme->wParam;
ImmNotifyIME( hImc, NI_CONTEXTUPDATED, 0, IMC_SETOPENSTATUS);
}
ImmUnlockIMC( hImc );
}
} else {
ImmSetOpenStatus( hImc, (BOOL)lpIme->wParam );
}
return lRet;
UNREFERENCED_PARAMETER(hWndApp);
}
//===================================================================
// TransGetOpenK
//===============
//
// KOREAN only
//
// History:
// xx-xx-1995 xxx Created
//
//===================================================================
LRESULT TransGetOpenK( HWND hWndApp, HIMC hImc, LPIMESTRUCT lpIme, BOOL fAnsi )
{
// NOTE: We will use this function instead of ImmEscape().
RECT rc;
LPARAM lTemp;
LRESULT lRet;
lTemp = lpIme->lParam2;
GetWindowRect(hWndApp, &rc);
lpIme->lParam2 = MAKELONG(rc.top, rc.left);
lRet = ImmEscape(GetKeyboardLayout(0), hImc, IME_GETOPEN, lpIme);
lpIme->lParam2 = lTemp;
return (lRet);
UNREFERENCED_PARAMETER(fAnsi);
}
//===================================================================
// TransGetOpenJ
//===============
//
// Japanese only
//
// History:
// 20-May-1996 takaok Created
//
//===================================================================
LRESULT TransGetOpenJ( HWND hWndApp, HIMC hImc, LPIMESTRUCT lpIme, BOOL fAnsi )
{
INT Count;
LRESULT lRet;
lRet = ImmGetOpenStatus( hImc );
// lpIME->wCount is the length of the composition string.
if ( fAnsi ) {
Count= ImmGetCompositionStringA( hImc, GCS_COMPSTR, NULL, 0L );
} else {
Count= ImmGetCompositionStringW( hImc, GCS_COMPSTR, NULL, 0L );
}
lpIme->wCount = ( Count > 0 ) ? Count : 0;
return lRet;
UNREFERENCED_PARAMETER(hWndApp);
}
//===================================================================
// TransMoveImeWindow
//====================
//
// Korean only
//
//===================================================================
LRESULT TransMoveImeWindow( HWND hWndApp, HIMC hImc, LPIMESTRUCT lpIme)
{
// NOTE: We will use this function instead of ImmEscape().
POINT pt;
LRESULT lRet;
if (lpIme->wParam == MCW_WINDOW)
{
pt.x = GET_X_LPARAM(lpIme->lParam1);
pt.y = GET_Y_LPARAM(lpIme->lParam1);
ClientToScreen(hWndApp, &pt);
lpIme->lParam1 = MAKELONG(pt.x, pt.y);
}
lRet = ImmEscape(GetKeyboardLayout(0), hImc, IME_MOVEIMEWINDOW, lpIme);
return (lRet);
}
//===================================================================
// TransSetConversionWindow
//=========================
//
// Japanese only
//
//===================================================================
LRESULT TransSetConversionWindow( HWND hWndApp, HIMC hImc, LPIMESTRUCT lpIme )
{
LPINPUTCONTEXT pInputContext;
COMPOSITIONFORM cof;
CANDIDATEFORM caf;
POINT pt;
RECT rt;
INT i;
if ( ! IsForegroundThread(NULL) && !GetFocus() ) {
//
// For win95 compatibility, we need to return TRUE though we
// didn't really succeed. PP4 calls us when it doesn't have
// the input focus to check if IME is capable to do the specfied
// MCW_xxx. Returning TRUE here will make such application happy.
//
return ( TRUE );
}
pInputContext = ImmLockIMC( hImc );
if ( pInputContext == NULL ) {
return ( FALSE );
}
pt.x = GET_X_LPARAM(lpIme->lParam1);
pt.y = GET_Y_LPARAM(lpIme->lParam1);
rt.left = GET_X_LPARAM(lpIme->lParam2);
rt.top = GET_Y_LPARAM(lpIme->lParam2);
rt.right = GET_X_LPARAM(lpIme->lParam3);
rt.bottom = GET_Y_LPARAM(lpIme->lParam3);
cof.dwStyle = CFS_DEFAULT;
if ( lpIme->wParam & MCW_HIDDEN ) {
pInputContext->fdw31Compat |= F31COMPAT_MCWHIDDEN;
ScreenToClient( pInputContext->hWnd, &pt );
MapWindowPoints( HWND_DESKTOP, pInputContext->hWnd, (LPPOINT)&rt, 2);
} else {
pInputContext->fdw31Compat &= ~F31COMPAT_MCWHIDDEN;
}
if ( lpIme->wParam & MCW_WINDOW) {
if ( !IsWndEqual(hWndApp, pInputContext->hWnd)) {
ClientToScreen(hWndApp, &pt);
ScreenToClient(pInputContext->hWnd, &pt);
if (lpIme->wParam & MCW_RECT) {
cof.dwStyle = CFS_RECT;
MapWindowPoints(hWndApp, HWND_DESKTOP, (LPPOINT)&rt, 2);
MapWindowPoints(HWND_DESKTOP, pInputContext->hWnd, (LPPOINT)&rt, 2);
} else {
cof.dwStyle = CFS_POINT;
}
} else {
if ( lpIme->wParam & MCW_RECT) {
cof.dwStyle = CFS_RECT;
} else {
cof.dwStyle = CFS_POINT;
}
}
}
// Because Chicago IME can not handle CFS_SCREEN. The points should be
// converted to client point.
// If these points are out of Client, HOW SHOULD WE DO????
if ( lpIme->wParam & MCW_SCREEN ) {
ScreenToClient( pInputContext->hWnd, &pt );
if ( lpIme->wParam & CFS_RECT ) {
cof.dwStyle = CFS_RECT;
MapWindowPoints( HWND_DESKTOP, pInputContext->hWnd, (LPPOINT)&rt, 2 );
}
else {
cof.dwStyle = CFS_POINT;
}
}
if ( lpIme->wParam & MCW_VERTICAL) {
if ( !(pInputContext->fdw31Compat & F31COMPAT_MCWVERTICAL) ) {
pInputContext->fdw31Compat |= F31COMPAT_MCWVERTICAL;
SetFontForMCWVERTICAL( hWndApp, hImc, pInputContext, TRUE);
}
} else {
if (pInputContext->fdw31Compat & F31COMPAT_MCWVERTICAL) {
pInputContext->fdw31Compat &= ~F31COMPAT_MCWVERTICAL;
SetFontForMCWVERTICAL( hWndApp, hImc, pInputContext, FALSE);
}
}
cof.ptCurrentPos = pt;
cof.rcArea = rt;
#if defined(PENAPI)
if ( !FSetPosPenUi(&cof) )
#endif
if ( !(pInputContext->fdw31Compat & F31COMPAT_MCWHIDDEN) ) {
MySetCompWindow( hWndApp, hImc, (LPCOMPOSITIONFORM)&cof );
} else {
// Hack for 3.1 Apps. We save the exlude area into IMC.
pInputContext->cfCompForm.ptCurrentPos = cof.ptCurrentPos;
pInputContext->cfCompForm.rcArea = cof.rcArea;
for ( i=0; i < 4; i++ ) {
if ( pInputContext->cfCandForm[i].dwIndex != -1)
{
caf.dwIndex = i;
caf.dwStyle = CFS_EXCLUDE;
caf.ptCurrentPos = pt;
caf.rcArea = rt;
MySetCandidateWindow( hWndApp, hImc, (LPCANDIDATEFORM)&caf );
}
}
}
ImmUnlockIMC( hImc );
return ( TRUE );
}
//===================================================================
// TransSetConversionMode
//=======================
//
// Japanese only
//
// History:
// 31-May-1996 takaok Created.
//
//===================================================================
LRESULT TransSetConversionMode( HIMC hImc, LPIMESTRUCT lpIme )
{
DWORD fdwConversion = 0, fdwSentence, fdwNewConversion, fdwMask;
UINT uPrevMode;
UINT u31Mode;
//
// Get current conversion mode and translate it to
// the 3.1 style conversion mode.
//
ImmGetConversionStatus( hImc, &fdwConversion, &fdwSentence);
uPrevMode = Get31ModeFrom40ModeJ( fdwConversion );
//
// translate requested 3.1 conversion mode to 4.0 conversion mode
//
fdwNewConversion = 0;
u31Mode = (UINT)lpIme->wParam;
switch ( u31Mode & 0x07 ) {
case IME_MODE_ALPHANUMERIC:
fdwNewConversion &= ~IME_CMODE_LANGUAGE;
break;
case IME_MODE_KATAKANA:
fdwNewConversion |= IME_CMODE_NATIVE|IME_CMODE_KATAKANA;
break;
case IME_MODE_HIRAGANA:
fdwNewConversion |= IME_CMODE_NATIVE;
break;
}
if ( !(u31Mode & JAPAN_IME_MODE_SBCSCHAR) )
fdwNewConversion |= IME_CMODE_FULLSHAPE;
if ( u31Mode & IME_MODE_ROMAN )
fdwNewConversion |= IME_CMODE_ROMAN;
if ( u31Mode & IME_MODE_CODEINPUT )
fdwNewConversion |= IME_CMODE_CHARCODE;
//
// compute the mask bit. we need to compute this because
// application may set only bit needed to be changed.
//
fdwMask = 0;
if ( u31Mode & (IME_MODE_ROMAN | IME_MODE_NOROMAN) )
fdwMask |= IME_CMODE_ROMAN;
if ( u31Mode & (IME_MODE_CODEINPUT|IME_MODE_NOCODEINPUT) )
fdwMask |= IME_CMODE_CHARCODE;
if ( u31Mode & 0x07 )
fdwMask |= IME_CMODE_LANGUAGE;
if ( u31Mode & (IME_MODE_DBCSCHAR|JAPAN_IME_MODE_SBCSCHAR) )
fdwMask |= IME_CMODE_FULLSHAPE;
//
// set the new mode
//
fdwNewConversion = (fdwNewConversion & fdwMask) | (fdwConversion & ~fdwMask);
if ( ImmSetConversionStatus( hImc, fdwNewConversion, fdwSentence) ) {
return (LRESULT)uPrevMode;
} else {
return (LRESULT)0;
}
}
//===================================================================
// TransGetMode
//==============
//
// Korean only
//
// translate 4.0 conversion mode into 3.1 conversion mode
//
// History:
// 31-May-1996 takaok Created.
//
//===================================================================
LRESULT TransGetMode( HIMC hImc )
{
DWORD fdwConversion = 0, fdwSentence;
UINT u31Mode = 0;
ImmGetConversionStatus( hImc, &fdwConversion, &fdwSentence);
u31Mode= Get31ModeFrom40ModeK( fdwConversion );
// HACK: To prevent 0 result from treating FALSE, we always set MSB
return ( u31Mode | 0x80000000 );
}
//===================================================================
// Get31ModeFrom40ModeK
//=====================
//
// Korean only
//
// translate 4.0 conversion mode into 3.1 conversion mode
//
// History:
// 31-May-1996 takaok Created.
//
//===================================================================
UINT Get31ModeFrom40ModeK( DWORD fdwConversion )
{
UINT u31Mode = 0;
if ( !(fdwConversion & IME_CMODE_NATIVE) ) {
u31Mode |= IME_MODE_ALPHANUMERIC;
}
if ( !(fdwConversion & IME_CMODE_FULLSHAPE) ) {
u31Mode |= KOREA_IME_MODE_SBCSCHAR;
}
if ( fdwConversion & IME_CMODE_HANJACONVERT ) {
u31Mode |= IME_MODE_HANJACONVERT;
}
return u31Mode;
}
//===================================================================
// TransGetConversionMode
//========================
//
// Japanese only
//
// 4.0 conversion mode => 3.1 conversion mode
//
// History:
// 31-May-1996 takaok Created.
//
//===================================================================
LRESULT TransGetConversionMode( HIMC hImc )
{
DWORD fdwConversion = 0, fdwSentence;
UINT u31Mode = 0;
//
// get the 4.0 style conversion mode
//
ImmGetConversionStatus( hImc, &fdwConversion, &fdwSentence);
return Get31ModeFrom40ModeJ( fdwConversion );
}
//===================================================================
// Get31ModeFrom40ModeJ
//======================
//
// Japanese only
//
// 4.0 conversion mode => 3.1 conversion mode
//
// History:
// 31-May-1996 takaok Created.
//
//===================================================================
UINT Get31ModeFrom40ModeJ( DWORD fdwConversion )
{
UINT u31Mode = 0;
//
// translate the 4.0 style mode to the 3.x style conversion mode
//
if (fdwConversion & IME_CMODE_NATIVE) {
if (fdwConversion & IME_CMODE_KATAKANA) {
u31Mode |= IME_MODE_KATAKANA;
} else {
u31Mode |= IME_MODE_HIRAGANA;
}
} else {
u31Mode |= IME_MODE_ALPHANUMERIC;
}
if (fdwConversion & IME_CMODE_FULLSHAPE) {
u31Mode |= IME_MODE_DBCSCHAR;
} else {
u31Mode |= JAPAN_IME_MODE_SBCSCHAR;
}
if (fdwConversion & IME_CMODE_ROMAN) {
u31Mode |= IME_MODE_ROMAN;
} else {
u31Mode |= IME_MODE_NOROMAN;
}
if (fdwConversion & IME_CMODE_CHARCODE) {
u31Mode |= IME_MODE_CODEINPUT;
} else {
u31Mode |= IME_MODE_NOCODEINPUT;
}
return (u31Mode);
}
//===================================================================
// TransSetMode
//==============
//
// KOREAN only
//
//===================================================================
LRESULT TransSetMode( HIMC hImc, LPIMESTRUCT lpIme )
{
DWORD fdwConversion = 0, fdwSentence, fdwNewConversion, fdwMask;
UINT uPrevMode;
UINT u31Mode;
//
// Get current conversion mode and translate it to
// the 3.1 style conversion mode.
//
ImmGetConversionStatus( hImc, &fdwConversion, &fdwSentence);
uPrevMode = Get31ModeFrom40ModeK( fdwConversion );
//
// translate requested 3.1 conversion mode to 4.0 conversion mode
//
fdwNewConversion = 0;
u31Mode = (UINT)lpIme->wParam;
if ( !(u31Mode & IME_MODE_ALPHANUMERIC) )
fdwNewConversion |= IME_CMODE_HANGEUL;
if ( !(u31Mode & KOREA_IME_MODE_SBCSCHAR) )
fdwConversion |= IME_CMODE_FULLSHAPE;
//
// In HWin3.1 there is no "not modification mode"
//
fdwMask = IME_CMODE_LANGUAGE|IME_CMODE_FULLSHAPE|IME_CMODE_HANJACONVERT;
//
// set the new mode
//
fdwNewConversion = (fdwNewConversion & fdwMask) | (fdwConversion & ~fdwMask);
if ( ImmSetConversionStatus( hImc, fdwNewConversion, fdwSentence) ) {
return (LRESULT)uPrevMode;
} else {
return (LRESULT)0;
}
return FALSE;
}
//===================================================================
// TransSendVKey
//===============
//
// Japanese only
//
//===================================================================
LRESULT TransSendVKey( HWND hWndApp, HIMC hImc, LPIMESTRUCT lpIme, BOOL fAnsi )
{
LRESULT lRet;
switch (lpIme->wParam)
{
// VK_DBE_xxx Support Check.
case (DWORD)(-1):
case (DWORD)(0x0000ffff): // from WOW16
switch (lpIme->wCount)
{
case VK_DBE_ALPHANUMERIC:
case VK_DBE_KATAKANA:
case VK_DBE_HIRAGANA:
case VK_DBE_SBCSCHAR:
case VK_DBE_DBCSCHAR:
case VK_DBE_ROMAN:
case VK_DBE_NOROMAN:
case VK_DBE_CODEINPUT:
case VK_DBE_NOCODEINPUT:
case VK_DBE_ENTERWORDREGISTERMODE:
case VK_DBE_ENTERIMECONFIGMODE:
case VK_DBE_ENTERDLGCONVERSIONMODE:
case VK_DBE_DETERMINESTRING:
case VK_DBE_FLUSHSTRING:
case VK_CONVERT:
lRet = TRUE;
break;
default:
lRet = FALSE;
break;
}
break;
case VK_DBE_ALPHANUMERIC:
case VK_DBE_KATAKANA:
case VK_DBE_HIRAGANA:
case VK_DBE_SBCSCHAR:
case VK_DBE_DBCSCHAR:
case VK_DBE_ROMAN:
case VK_DBE_NOROMAN:
case VK_DBE_CODEINPUT:
case VK_DBE_NOCODEINPUT:
lRet = TransVKDBEMode(hImc, lpIme->wParam);
break;
case VK_DBE_ENTERWORDREGISTERMODE:
{
HKL hkl = GetKeyboardLayout(0L);
if ( fAnsi )
lRet = ImmConfigureIMEA(hkl, hWndApp, IME_CONFIG_REGISTERWORD, NULL);
else
lRet = ImmConfigureIMEW(hkl, hWndApp, IME_CONFIG_REGISTERWORD, NULL);
}
break;
case VK_DBE_ENTERIMECONFIGMODE:
{
HKL hkl = GetKeyboardLayout(0L);
if (fAnsi)
lRet = ImmConfigureIMEA(hkl, hWndApp, IME_CONFIG_GENERAL, NULL);
else
lRet = ImmConfigureIMEW(hkl, hWndApp, IME_CONFIG_GENERAL, NULL);
}
break;
case VK_DBE_ENTERDLGCONVERSIONMODE:
#if defined(PENAPI)
FInitPenUi(hIMC);
#endif
lRet = FALSE;
break;
case VK_DBE_DETERMINESTRING:
// Check there is the composition string or not.
lRet = ImmNotifyIME( ImmGetContext(hWndApp),
NI_COMPOSITIONSTR,
CPS_COMPLETE,
0L);
break;
case VK_DBE_FLUSHSTRING:
lRet = ImmNotifyIME( hImc, NI_COMPOSITIONSTR,CPS_CANCEL,0L);
break;
case VK_CONVERT:
lRet = ImmNotifyIME( hImc, NI_COMPOSITIONSTR, CPS_CONVERT, 0L);
break;
default:
lRet = FALSE;
break;
}
return lRet;
}
//===================================================================
// TransEnterWordRegisterMode
//===========================
//
// Japanese only
//
//===================================================================
LRESULT TransEnterWordRegisterMode( HWND hWndApp, LPIMESTRUCT lpIme, BOOL fAnsi)
{
LRESULT lRet;
HKL hkl = GetKeyboardLayout(0L);
if ( ! ImmIsIME(hkl) ) {
return FALSE;
}
if ( fAnsi ) {
//
// ANSI
//
REGISTERWORDA stReg = {NULL, NULL};
LPSTR lpsz1, lpsz2;
if (lpIme->lParam1&&(lpsz1=GlobalLock((HGLOBAL)lpIme->lParam1))) {
stReg.lpWord = lpsz1;
}
if (lpIme->lParam2&&(lpsz2=GlobalLock((HGLOBAL)lpIme->lParam2))) {
stReg.lpReading = lpsz2;
}
lRet = ImmConfigureIMEA(hkl,hWndApp,IME_CONFIG_REGISTERWORD, (LPVOID)&stReg);
if (lpIme->lParam1 && lpsz1)
GlobalUnlock((HGLOBAL)lpIme->lParam1);
if (lpIme->lParam2 && lpsz2)
GlobalUnlock((HGLOBAL)lpIme->lParam2);
} else {
//
// UNICODE
//
REGISTERWORDW stReg = {NULL, NULL};
LPWSTR lpsz1, lpsz2;
if (lpIme->lParam1&&(lpsz1=GlobalLock((HGLOBAL)lpIme->lParam1))) {
stReg.lpWord = lpsz1;
}
if (lpIme->lParam2&&(lpsz2=GlobalLock((HGLOBAL)lpIme->lParam2))) {
stReg.lpReading = lpsz2;
}
lRet = ImmConfigureIMEW(hkl,hWndApp,IME_CONFIG_REGISTERWORD, (LPVOID)&stReg);
if (lpIme->lParam1 && lpsz1)
GlobalUnlock((HGLOBAL)lpIme->lParam1);
if (lpIme->lParam2 && lpsz2)
GlobalUnlock((HGLOBAL)lpIme->lParam2);
}
return lRet;
}
//===================================================================
// TransSetConversionFontEx
//==========================
//
// Japanese only
//
//===================================================================
LRESULT TransSetConversionFontEx( HWND hWndApp, HIMC hImc, LPIMESTRUCT lpIme, BOOL fAnsi)
{
LPINPUTCONTEXT pInputContext;
LRESULT lRet;
LPLOGFONTW lplf;
LOGFONTW lfw;
pInputContext = ImmLockIMC( hImc );
if ( pInputContext == NULL ) {
return 0L;
}
lplf = (LPLOGFONTW)GlobalLock((HGLOBAL)lpIme->lParam1);
if ( lplf == NULL )
{
ImmUnlockIMC( hImc );
return 0L;
}
if ( fAnsi ) {
memcpy( &lfw, lplf, sizeof(LOGFONTA) );
MultiByteToWideChar( CP_ACP,
0,
(LPCSTR)lplf->lfFaceName, // src
LF_FACESIZE, // size of src
lfw.lfFaceName, // destination buffer
LF_FACESIZE ); // size of destination buffer
} else {
memcpy( &lfw, lplf, sizeof(LOGFONTW));
}
GlobalUnlock((HGLOBAL)lpIme->lParam1);
if (( pInputContext->fdw31Compat & F31COMPAT_MCWVERTICAL)) {
lRet = FixLogfont( &lfw, TRUE);
} else {
lRet = FixLogfont( &lfw, FALSE);
}
ImmUnlockIMC( hImc );
if (lRet == FALSE ) {
return FALSE;
}
return MySetCompFont( hWndApp, hImc, &lfw );
}
//===================================================================
// TransHanjaMode
//================
//
// Korean only
//
//===================================================================
LRESULT TransHanjaMode( HWND hWndApp, HIMC hImc, LPIMESTRUCT lpIme)
{
// NOTE We will use this function instead of ImmEscape().
LRESULT lRet;
PIMEDPI pImeDpi;
DWORD dwThreadId = GetInputContextThread(hImc);
if (dwThreadId == 0) {
RIPMSG1(RIP_WARNING,
"TransHanjaMode: GetInputContextThread(%lx) failed.", hImc);
return FALSE;
}
pImeDpi = ImmLockImeDpi(GetKeyboardLayout(dwThreadId));
if (pImeDpi == NULL)
return FALSE;
/*
* Check if we need ANSI/Unicode conversion
*/
if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE) {
WCHAR wUni;
CHAR chAnsi[2];
UINT i, dchSource;
//The 4th word of imestruct32 contains dchSource
dchSource = *((LPSTR)lpIme + 3 * sizeof(WORD));
chAnsi[0] = *((LPSTR)lpIme + dchSource);
chAnsi[1] = *((LPSTR)lpIme + dchSource + 1);
i = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, chAnsi, 2, &wUni, 1);
if (i) {
*((LPSTR)lpIme + dchSource) = (CHAR)LOWORD(LOBYTE(wUni));
*((LPSTR)lpIme + dchSource+1) = (CHAR)LOWORD(HIBYTE(wUni));
}
else {
ImmUnlockImeDpi(pImeDpi);
return FALSE;
}
}
ImmUnlockImeDpi(pImeDpi);
if (lRet = ImmEscape(GetKeyboardLayout(0), hImc, IME_HANJAMODE, lpIme))
SendMessage(hWndApp, WM_IME_NOTIFY, IMN_OPENCANDIDATE, 1L);
return (lRet);
}
//===================================================================
// TransGetLevel
//===============
//
// Korean only
//
//===================================================================
LRESULT TransGetLevel( HWND hWndApp )
{
UINT lRet;
if ( (lRet = NtUserGetAppImeLevel( hWndApp )) == 0 )
lRet = 1; // default level
return lRet;
}
//===================================================================
// TransSetLevel
//===============
//
// Korean only
//
//===================================================================
LRESULT TransSetLevel( HWND hWndApp, LPIMESTRUCT lpIme)
{
DWORD dwLevel;
dwLevel = (DWORD)lpIme->wParam;
if ( dwLevel >= 1 && dwLevel <= 5 ) {
if ( NtUserSetAppImeLevel(hWndApp, dwLevel) ) {
return TRUE;
}
}
return FALSE;
}
//===================================================================
// TransVKDBEMode
//================
//
// Japanese only
//
//===================================================================
LRESULT TransVKDBEMode( HIMC hImc, WPARAM wVKDBE )
{
DWORD fdwConversion,fdwSentence;
if (!ImmGetConversionStatus(hImc, &fdwConversion, &fdwSentence)) {
return FALSE;
}
switch (wVKDBE)
{
case VK_DBE_ALPHANUMERIC:
fdwConversion &= ~IME_CMODE_LANGUAGE;
break;
case VK_DBE_KATAKANA:
fdwConversion |= (IME_CMODE_JAPANESE | IME_CMODE_KATAKANA);
break;
case VK_DBE_HIRAGANA:
fdwConversion &= ~IME_CMODE_KATAKANA;
fdwConversion |= IME_CMODE_JAPANESE;
break;
case VK_DBE_SBCSCHAR:
fdwConversion &= ~IME_CMODE_FULLSHAPE;
break;
case VK_DBE_DBCSCHAR:
fdwConversion |= IME_CMODE_FULLSHAPE;
break;
case VK_DBE_ROMAN:
fdwConversion |= IME_CMODE_ROMAN;
break;
case VK_DBE_NOROMAN:
fdwConversion &= ~IME_CMODE_ROMAN;
break;
case VK_DBE_CODEINPUT:
fdwConversion |= IME_CMODE_CHARCODE;
break;
case VK_DBE_NOCODEINPUT:
fdwConversion &= ~IME_CMODE_CHARCODE;
break;
default:
break;
}
return ImmSetConversionStatus(hImc, fdwConversion, fdwSentence);
}
//===================================================================
// IsForegroundThread
//===================
//
// Check if the caller thread has the foreground window.
// If hwnd is specified, the function checks if the creator
// thread of the specified window has the foreground window.
//
//===================================================================
BOOL IsForegroundThread(HWND hwnd)
{
HWND hwndFG;
DWORD dwThreadId;
hwndFG = GetForegroundWindow();
if ( IsWindow( hwnd ) ) {
dwThreadId = GetWindowThreadProcessId( hwnd, NULL );
} else {
dwThreadId = GetCurrentThreadId();
}
return ( GetWindowThreadProcessId(hwndFG,NULL) == dwThreadId );
}
//===================================================================
// SetFontForMCWVERTICAL
//======================
//
// Japanese only
//
// set/reset vertical writing font
//
//===================================================================
BOOL SetFontForMCWVERTICAL( HWND hWndApp, HIMC hImc, LPINPUTCONTEXT pInputContext, BOOL fVert )
{
LOGFONTW lf;
PCLIENTIMC pClientImc;
if ( pInputContext->fdwInit & INIT_LOGFONT) {
//
// If a font has ever been set, use it
//
BOOL fAnsi;
memcpy(&lf,&pInputContext->lfFont.W,sizeof(LOGFONTW));
//
// check if the input context is unicode
//
pClientImc = ImmLockClientImc( hImc );
if (pClientImc == NULL) {
return FALSE;
}
fAnsi = ! TestICF( pClientImc, IMCF_UNICODE );
ImmUnlockClientImc( pClientImc );
if ( fAnsi ) {
CHAR FaceNameA[ LF_FACESIZE ];
//
// we need a temporary buffer because MultiByteToWideChar
// doesn't allow us to specify src==dest.
//
memcpy( FaceNameA, &lf.lfFaceName, LF_FACESIZE );
MultiByteToWideChar( CP_ACP,
0,
FaceNameA, // src
LF_FACESIZE, // size of src
lf.lfFaceName, // destination buffer
LF_FACESIZE ); // size of destination buffer
}
} else {
//
// system font should be used as the default font
//
GetObjectW( GetStockObject(SYSTEM_FONT), sizeof(lf), (LPVOID)&lf );
}
//
// put/remove '@' from the font facename.
// "@facename" means vertical writing font
//
if ( FixLogfont( &lf, fVert ) == FALSE ) {
return FALSE;
}
return MySetCompFont( hWndApp, hImc, &lf );
}
//===================================================================
// FixLogfont
//============
//
// Japanese only
//
// put/remove '@' from the font facename.
// "@facename" means vertical writing font
//
//===================================================================
BOOL FixLogfont( LPLOGFONTW lplfW, BOOL fVert )
{
int i;
if ( fVert ) {
//
// convert the specified font to vertical writing font
//
lplfW->lfEscapement = 2700;
lplfW->lfOrientation = 2700;
if ((lplfW->lfCharSet == SHIFTJIS_CHARSET) && (lplfW->lfFaceName[0] != L'@')) {
for(i=0;lplfW->lfFaceName[i];++i) // Search NULL
if (i > (LF_FACESIZE-2)) // if not remain 2 char
return FALSE; // then error
// Because insert @ char
for( ; i>=0 ; --i ) // Copy facename from tail
lplfW->lfFaceName[i+1] = lplfW->lfFaceName[i];
lplfW->lfFaceName[0] = L'@'; // insert @ character
}
} else {
//
// convert the specified font to normal font
//
lplfW->lfEscapement = 0;
lplfW->lfOrientation = 0;
if ((lplfW->lfCharSet == SHIFTJIS_CHARSET) && (lplfW->lfFaceName[0] == L'@'))
lstrcpynW(lplfW->lfFaceName,&(lplfW->lfFaceName[1]),LF_FACESIZE-1);
}
return TRUE;
}
//===================================================================
// MySetCompFont
//==============
//
// Japanese only
//
//===================================================================
BOOL MySetCompFont( HWND hWndApp, HIMC hImc, LPLOGFONTW lplf )
{
BOOL lRet = FALSE;
DWORD dwCompat;
PINPUTCONTEXT pInputContext;
PCLIENTIMC pClientImc;
LOGFONTW lfw;
LPLOGFONTW lplfw = &lfw;
BOOL fUnicode;
// BOGUS!!
// Some application call SendIMEMessage(IME_SETCONVERSIONFONT)
// when the apps is handling WM_PAINT.
// New Win95 IME try to draw the UI during calling ImmSetCompositionFont,
// and WM_PAINT will be sent in the API....
// To avoid this thing, WINNLS makes the notification to IME and APPS later.
// ........
if ( (pInputContext = ImmLockIMC(hImc)) != NULL ) {
dwCompat = ImmGetAppCompatFlags( hImc );
pClientImc = ImmLockClientImc(hImc);
if (pClientImc != NULL) {
fUnicode = TestICF(pClientImc, IMCF_UNICODE);
ImmUnlockClientImc(pClientImc);
if ( fUnicode )
lplfw = &(pInputContext->lfFont.W);
else
LFontAtoLFontW( &(pInputContext->lfFont.A), lplfw );
if ( RtlEqualMemory(lplfw, lplf, sizeof(LOGFONTA)-LF_FACESIZE)
&& !lstrcmp(lplfw->lfFaceName, lplf->lfFaceName) ) {
/*
* Don't inform IME ahd UI when logfont is not changed.
*/
lRet = TRUE;
} else if ( dwCompat & IMECOMPAT_UNSYNC31IMEMSG ) {
memcpy( &(pInputContext->lfFont.W), lplf, sizeof(LOGFONT));
if ( dwCompat & IMECOMPAT_UNSYNC31IMEMSG2 )
/*
* BOGUS!! for PageMaker5J
*/
lRet = PostMessage( hWndApp, WM_IME_SYSTEM, IMS_SETCOMPOSITIONFONT, 0 );
else
lRet = MyPostImsMessage( hWndApp, IMS_SETCOMPOSITIONFONT, 0);
} else {
lRet = ImmSetCompositionFont( hImc, lplf );
}
}
ImmUnlockIMC( hImc );
}
return lRet;
}
//===================================================================
// MySetCompWindow
//================
//
// Japanese only
//
//===================================================================
BOOL MySetCompWindow(
HWND hWndApp,
HIMC hImc,
LPCOMPOSITIONFORM lpcof
)
{
BOOL fRet = FALSE;
DWORD dwCompat;
PINPUTCONTEXT pInputContext;
// BOGUS!!
// Some application call SendIMEMessage(IME_SETCONVERSIONWINDOW)
// when the apps is handling WM_PAINT.
// New Win95 IME try to draw the UI during calling ImmSetCompositionWindow,
// and WM_PAINT will be sent in the API....
// To avoid this thing, WINNLS makes the notification to IME and APPS later.
// ........
if ( (pInputContext = ImmLockIMC(hImc)) != NULL ) {
dwCompat = ImmGetAppCompatFlags( hImc );
if ( dwCompat & IMECOMPAT_UNSYNC31IMEMSG ) {
memcpy( &(pInputContext->cfCompForm), lpcof, sizeof(COMPOSITIONFORM));
if ( dwCompat & IMECOMPAT_UNSYNC31IMEMSG2 ) {
/*
* BOGUS!! for PageMaker5J
*/
fRet = PostMessage( hWndApp, WM_IME_SYSTEM, IMS_SETCOMPOSITIONWINDOW, 0 );
} else {
fRet = MyPostImsMessage( hWndApp, IMS_SETCOMPOSITIONWINDOW, 0 );
}
} else {
pInputContext->fdw31Compat |= F31COMPAT_CALLFROMWINNLS;
fRet = ImmSetCompositionWindow( hImc, lpcof );
}
ImmUnlockIMC( hImc );
}
return fRet;
}
//===================================================================
// MySetCandidateWindow
//=====================
//
// Japanese only
//
//===================================================================
BOOL MySetCandidateWindow( HWND hWndApp, HIMC hImc, LPCANDIDATEFORM lpcaf)
{
BOOL fRet = FALSE;
DWORD dwCompat;
PINPUTCONTEXT pInputContext;
// BOGUS!!
// Some application call SendIMEMessage(IME_SETCONVERSIONWINDOW)
// when the apps is handling WM_PAINT.
// New Win95 IME try to draw the UI during calling ImmSetCandidateWindow,
// and WM_PAINT will be sent in the API....
// To avoid this thing, WINNLS makes the notification to IME and APPS later.
// ........
if ( (pInputContext = ImmLockIMC(hImc)) != NULL ) {
dwCompat = ImmGetAppCompatFlags( hImc );
if ( dwCompat & IMECOMPAT_UNSYNC31IMEMSG ) {
memcpy( &(pInputContext->cfCandForm[lpcaf->dwIndex]), lpcaf, sizeof(CANDIDATEFORM));
fRet = MyPostImsMessage( hWndApp, IMS_SETCANDIDATEPOS, lpcaf->dwIndex );
} else {
fRet = ImmSetCandidateWindow( hImc, lpcaf );
}
ImmUnlockIMC( hImc );
}
return fRet;
}
//===================================================================
// MyPostImsMessage
//==================
//
// Japanese only
//
// BOGUS!!
// Some application call SendIMEMessage(IME_SETCONVERSIONWINDOW)
// when the apps is handling WM_PAINT.
// New Win95 IME try to draw the UI during calling ImmSetCompositionWindow,
// and WM_PAINT will be sent in the API....
// To avoid this thing, WINNLS makes the notification to IME and APPS later.
// ........
//===================================================================
BOOL MyPostImsMessage( HWND hWndApp, WPARAM wParam, LPARAM lParam )
{
HWND hDefIMEWnd;
BOOL fRet = FALSE;
hDefIMEWnd = ImmGetDefaultIMEWnd(hWndApp);
if ( hDefIMEWnd != NULL ) {
if ( PostMessage( hDefIMEWnd, WM_IME_SYSTEM, wParam, lParam) ) {
fRet = TRUE;
}
}
return fRet;
}