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