* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#define WIN32_NO_STATUS
-
-//#include <stdarg.h>
+#include <stdarg.h>
#include <stdio.h>
-#include <windef.h>
-#include <winbase.h>
-//#include "wingdi.h"
-#include <winuser.h>
-//#include "winerror.h"
-#include <wine/debug.h>
-//#include "imm.h"
-#include <ddk/imm.h>
-#include <winnls.h>
-#include <winreg.h>
-#include <wine/list.h>
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "winerror.h"
+#include "wine/debug.h"
+#include "imm.h"
+#include "ddk/imm.h"
+#include "winnls.h"
+#include "winreg.h"
+#include "wine/list.h"
WINE_DEFAULT_DEBUG_CHANNEL(imm);
-#define MAKE_FUNCPTR(f) typeof(f) * p##f
+#define IMM_INIT_MAGIC 0x19650412
+BOOL WINAPI User32InitializeImmEntryTable(DWORD);
+
typedef struct _tagImmHkl{
struct list entry;
HKL hkl;
HWND UIWnd;
/* Function Pointers */
- MAKE_FUNCPTR(ImeInquire);
- MAKE_FUNCPTR(ImeConfigure);
- MAKE_FUNCPTR(ImeDestroy);
- MAKE_FUNCPTR(ImeEscape);
- MAKE_FUNCPTR(ImeSelect);
- MAKE_FUNCPTR(ImeSetActiveContext);
- MAKE_FUNCPTR(ImeToAsciiEx);
- MAKE_FUNCPTR(NotifyIME);
- MAKE_FUNCPTR(ImeRegisterWord);
- MAKE_FUNCPTR(ImeUnregisterWord);
- MAKE_FUNCPTR(ImeEnumRegisterWord);
- MAKE_FUNCPTR(ImeSetCompositionString);
- MAKE_FUNCPTR(ImeConversionList);
- MAKE_FUNCPTR(ImeProcessKey);
- MAKE_FUNCPTR(ImeGetRegisterWordStyle);
- MAKE_FUNCPTR(ImeGetImeMenuItems);
+ BOOL (WINAPI *pImeInquire)(IMEINFO *, WCHAR *, const WCHAR *);
+ BOOL (WINAPI *pImeConfigure)(HKL, HWND, DWORD, void *);
+ BOOL (WINAPI *pImeDestroy)(UINT);
+ LRESULT (WINAPI *pImeEscape)(HIMC, UINT, void *);
+ BOOL (WINAPI *pImeSelect)(HIMC, BOOL);
+ BOOL (WINAPI *pImeSetActiveContext)(HIMC, BOOL);
+ UINT (WINAPI *pImeToAsciiEx)(UINT, UINT, const BYTE *, DWORD *, UINT, HIMC);
+ BOOL (WINAPI *pNotifyIME)(HIMC, DWORD, DWORD, DWORD);
+ BOOL (WINAPI *pImeRegisterWord)(const WCHAR *, DWORD, const WCHAR *);
+ BOOL (WINAPI *pImeUnregisterWord)(const WCHAR *, DWORD, const WCHAR *);
+ UINT (WINAPI *pImeEnumRegisterWord)(REGISTERWORDENUMPROCW, const WCHAR *, DWORD, const WCHAR *, void *);
+ BOOL (WINAPI *pImeSetCompositionString)(HIMC, DWORD, const void *, DWORD, const void *, DWORD);
+ DWORD (WINAPI *pImeConversionList)(HIMC, const WCHAR *, CANDIDATELIST *, DWORD, UINT);
+ BOOL (WINAPI *pImeProcessKey)(HIMC, UINT, LPARAM, const BYTE *);
+ UINT (WINAPI *pImeGetRegisterWordStyle)(UINT, STYLEBUFW *);
+ DWORD (WINAPI *pImeGetImeMenuItems)(HIMC, DWORD, DWORD, IMEMENUITEMINFOW *, IMEMENUITEMINFOW *, DWORD);
} ImmHkl;
-#undef MAKE_FUNCPTR
typedef struct tagInputContextData
{
DWORD dwLock;
INPUTCONTEXT IMC;
+ DWORD threadID;
ImmHkl *immKbd;
UINT lastVK;
+ BOOL threadDefault;
+ DWORD magic;
} InputContextData;
+#define WINE_IMC_VALID_MAGIC 0x56434D49
+
typedef struct _tagTRANSMSG {
UINT message;
WPARAM wParam;
} TRANSMSG, *LPTRANSMSG;
typedef struct _tagIMMThreadData {
+ struct list entry;
+ DWORD threadID;
HIMC defaultContext;
HWND hwndDefault;
+ BOOL disableIME;
+ DWORD windowRefs;
} IMMThreadData;
-static DWORD tlsIndex = 0;
static struct list ImmHklList = LIST_INIT(ImmHklList);
-
-/* MSIME messages */
-static UINT WM_MSIME_SERVICE;
-static UINT WM_MSIME_RECONVERTOPTIONS;
-static UINT WM_MSIME_MOUSE;
-static UINT WM_MSIME_RECONVERTREQUEST;
-static UINT WM_MSIME_RECONVERT;
-static UINT WM_MSIME_QUERYPOSITION;
-static UINT WM_MSIME_DOCUMENTFEED;
+static struct list ImmThreadDataList = LIST_INIT(ImmThreadDataList);
static const WCHAR szwWineIMCProperty[] = {'W','i','n','e','I','m','m','H','I','M','C','P','r','o','p','e','r','t','y',0};
static const WCHAR szImeRegFmt[] = {'S','y','s','t','e','m','\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\','C','o','n','t','r','o','l','\\','K','e','y','b','o','a','r','d',' ','L','a','y','o','u','t','s','\\','%','0','8','l','x',0};
static const WCHAR szwIME[] = {'I','M','E',0};
+static const WCHAR szwDefaultIME[] = {'D','e','f','a','u','l','t',' ','I','M','E',0};
-static LRESULT WINAPI DefIME_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
- LPARAM lParam);
+static CRITICAL_SECTION threaddata_cs;
+static CRITICAL_SECTION_DEBUG critsect_debug =
+{
+ 0, 0, &threaddata_cs,
+ { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
+ 0, 0, { (DWORD_PTR)(__FILE__ ": threaddata_cs") }
+};
+static CRITICAL_SECTION threaddata_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
+static BOOL disable_ime;
-#define is_himc_ime_unicode(p) (p->immKbd->imeInfo.fdwProperty & IME_PROP_UNICODE)
-#define is_kbd_ime_unicode(p) (p->imeInfo.fdwProperty & IME_PROP_UNICODE)
+static inline BOOL is_himc_ime_unicode(const InputContextData *data)
+{
+ return !!(data->immKbd->imeInfo.fdwProperty & IME_PROP_UNICODE);
+}
+
+static inline BOOL is_kbd_ime_unicode(const ImmHkl *hkl)
+{
+ return !!(hkl->imeInfo.fdwProperty & IME_PROP_UNICODE);
+}
static BOOL IMM_DestroyContext(HIMC hIMC);
+static InputContextData* get_imc_data(HIMC hIMC);
static inline WCHAR *strdupAtoW( const char *str )
{
return ret;
}
-static IMMThreadData* IMM_GetThreadData(void)
+static IMMThreadData *IMM_GetThreadData(HWND hwnd, DWORD thread)
{
- IMMThreadData* data = TlsGetValue(tlsIndex);
- if (!data)
+ IMMThreadData *data;
+ DWORD process;
+
+ if (hwnd)
+ {
+ if (!(thread = GetWindowThreadProcessId(hwnd, &process))) return NULL;
+ if (process != GetCurrentProcessId()) return NULL;
+ }
+ else if (thread)
{
- data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
- sizeof(IMMThreadData));
- TlsSetValue(tlsIndex,data);
- TRACE("Thread Data Created\n");
+ HANDLE h = OpenThread(THREAD_QUERY_INFORMATION, FALSE, thread);
+ if (!h) return NULL;
+ process = GetProcessIdOfThread(h);
+ CloseHandle(h);
+ if (process != GetCurrentProcessId()) return NULL;
}
+ else
+ thread = GetCurrentThreadId();
+
+ EnterCriticalSection(&threaddata_cs);
+ LIST_FOR_EACH_ENTRY(data, &ImmThreadDataList, IMMThreadData, entry)
+ if (data->threadID == thread) return data;
+
+ data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data));
+ data->threadID = thread;
+ list_add_head(&ImmThreadDataList,&data->entry);
+ TRACE("Thread Data Created (%x)\n",thread);
return data;
}
-static void IMM_FreeThreadData(void)
+static BOOL IMM_IsDefaultContext(HIMC imc)
{
- IMMThreadData* data = TlsGetValue(tlsIndex);
- if (data)
- {
- IMM_DestroyContext(data->defaultContext);
- DestroyWindow(data->hwndDefault);
- HeapFree(GetProcessHeap(),0,data);
- TRACE("Thread Data Destroyed\n");
- }
+ InputContextData *data = get_imc_data(imc);
+
+ if (!data)
+ return FALSE;
+
+ return data->threadDefault;
}
-static HMODULE LoadDefaultWineIME(void)
+static void IMM_FreeThreadData(void)
{
- char buffer[MAX_PATH], libname[32], *name, *next;
- HMODULE module = 0;
- HKEY hkey;
+ IMMThreadData *data;
- TRACE("Attempting to fall back to wine default IME\n");
-
- strcpy( buffer, "x11" ); /* default value */
- /* @@ Wine registry key: HKCU\Software\Wine\Drivers */
- if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Drivers", &hkey ))
+ EnterCriticalSection(&threaddata_cs);
+ LIST_FOR_EACH_ENTRY(data, &ImmThreadDataList, IMMThreadData, entry)
{
- DWORD type, count = sizeof(buffer);
- RegQueryValueExA( hkey, "Ime", 0, &type, (LPBYTE) buffer, &count );
- RegCloseKey( hkey );
+ if (data->threadID == GetCurrentThreadId())
+ {
+ list_remove(&data->entry);
+ LeaveCriticalSection(&threaddata_cs);
+ IMM_DestroyContext(data->defaultContext);
+ HeapFree(GetProcessHeap(),0,data);
+ TRACE("Thread Data Destroyed\n");
+ return;
+ }
}
+ LeaveCriticalSection(&threaddata_cs);
+}
- name = buffer;
- while (name)
- {
- next = strchr( name, ',' );
- if (next) *next++ = 0;
-
- snprintf( libname, sizeof(libname), "wine%s.drv", name );
- if ((module = LoadLibraryA( libname )) != 0) break;
- name = next;
- }
+static HMODULE load_graphics_driver(void)
+{
+ static const WCHAR display_device_guid_propW[] = {
+ '_','_','w','i','n','e','_','d','i','s','p','l','a','y','_',
+ 'd','e','v','i','c','e','_','g','u','i','d',0 };
+ static const WCHAR key_pathW[] = {
+ 'S','y','s','t','e','m','\\',
+ 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
+ 'C','o','n','t','r','o','l','\\',
+ 'V','i','d','e','o','\\','{',0};
+ static const WCHAR displayW[] = {'}','\\','0','0','0','0',0};
+ static const WCHAR driverW[] = {'G','r','a','p','h','i','c','s','D','r','i','v','e','r',0};
- return module;
+ HMODULE ret = 0;
+ HKEY hkey;
+ DWORD size;
+ WCHAR path[MAX_PATH];
+ WCHAR key[ARRAY_SIZE( key_pathW ) + ARRAY_SIZE( displayW ) + 40];
+ UINT guid_atom = HandleToULong( GetPropW( GetDesktopWindow(), display_device_guid_propW ));
+
+ if (!guid_atom) return 0;
+ memcpy( key, key_pathW, sizeof(key_pathW) );
+ if (!GlobalGetAtomNameW( guid_atom, key + lstrlenW(key), 40 )) return 0;
+ lstrcatW( key, displayW );
+ if (RegOpenKeyW( HKEY_LOCAL_MACHINE, key, &hkey )) return 0;
+ size = sizeof(path);
+ if (!RegQueryValueExW( hkey, driverW, NULL, NULL, (BYTE *)path, &size )) ret = LoadLibraryW( path );
+ RegCloseKey( hkey );
+ TRACE( "%s %p\n", debugstr_w(path), ret );
+ return ret;
}
/* ImmHkl loading and freeing */
ptr->hkl = hkl;
if (ImmGetIMEFileNameW(hkl, filename, MAX_PATH)) ptr->hIME = LoadLibraryW(filename);
- if (!ptr->hIME)
- ptr->hIME = LoadDefaultWineIME();
+ if (!ptr->hIME) ptr->hIME = load_graphics_driver();
if (ptr->hIME)
{
LOAD_FUNCPTR(ImeInquire);
}
#undef LOAD_FUNCPTR
+HWND WINAPI __wine_get_ui_window(HKL hkl)
+{
+ ImmHkl *immHkl = IMM_GetImmHkl(hkl);
+ return immHkl->UIWnd;
+}
+
static void IMM_FreeAllImmHkl(void)
{
ImmHkl *ptr,*cursor2;
}
}
-static void IMM_RegisterMessages(void)
-{
- WM_MSIME_SERVICE = RegisterWindowMessageA("MSIMEService");
- WM_MSIME_RECONVERTOPTIONS = RegisterWindowMessageA("MSIMEReconvertOptions");
- WM_MSIME_MOUSE = RegisterWindowMessageA("MSIMEMouseOperation");
- WM_MSIME_RECONVERTREQUEST = RegisterWindowMessageA("MSIMEReconvertRequest");
- WM_MSIME_RECONVERT = RegisterWindowMessageA("MSIMEReconvert");
- WM_MSIME_QUERYPOSITION = RegisterWindowMessageA("MSIMEQueryPosition");
- WM_MSIME_DOCUMENTFEED = RegisterWindowMessageA("MSIMEDocumentFeed");
-}
-
-static void IMM_RegisterIMEClass(void)
-{
- WNDCLASSW wndClass;
-
- ZeroMemory(&wndClass, sizeof(WNDCLASSW));
-
- wndClass.style = CS_GLOBALCLASS;
- wndClass.lpfnWndProc = (WNDPROC) DefIME_WindowProc;
- wndClass.cbWndExtra = 2 * sizeof(LONG_PTR);
- wndClass.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
- wndClass.lpszClassName = szwIME;
-
- RegisterClassW(&wndClass);
-}
-
BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved)
{
TRACE("%p, %x, %p\n",hInstDLL,fdwReason,lpReserved);
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
- IMM_RegisterMessages();
- tlsIndex = TlsAlloc();
- if (tlsIndex == TLS_OUT_OF_INDEXES)
+ if (!User32InitializeImmEntryTable(IMM_INIT_MAGIC))
+ {
return FALSE;
- IMM_RegisterIMEClass();
+ }
break;
case DLL_THREAD_ATTACH:
break;
if (lpReserved) break;
IMM_FreeThreadData();
IMM_FreeAllImmHkl();
- TlsFree(tlsIndex);
- UnregisterClassW(szwIME, NULL);
break;
}
return TRUE;
PostMessageW(target, msg, wParam, lParam);
}
+/* for sending messages as the IME */
+static void ImmInternalSendIMEMessage(InputContextData *data, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ HWND target = GetFocus();
+ if (!target)
+ SendMessageW(data->IMC.hWnd,msg,wParam,lParam);
+ else
+ SendMessageW(target, msg, wParam, lParam);
+}
+
static LRESULT ImmInternalSendIMENotify(InputContextData *data, WPARAM notify, LPARAM lParam)
{
HWND target;
return rc;
}
+static InputContextData* get_imc_data(HIMC hIMC)
+{
+ InputContextData *data = hIMC;
+
+ if (hIMC == NULL)
+ return NULL;
+
+ if(IsBadReadPtr(data, sizeof(InputContextData)) || data->magic != WINE_IMC_VALID_MAGIC)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return NULL;
+ }
+ return data;
+}
+
+static HIMC get_default_context( HWND hwnd )
+{
+ HIMC ret;
+ IMMThreadData* thread_data = IMM_GetThreadData( hwnd, 0 );
+
+ if (!thread_data) return 0;
+
+ if (thread_data->defaultContext)
+ {
+ ret = thread_data->defaultContext;
+ LeaveCriticalSection(&threaddata_cs);
+ return ret;
+ }
+
+ /* can't create a default context in another thread */
+ if (thread_data->threadID != GetCurrentThreadId())
+ {
+ LeaveCriticalSection(&threaddata_cs);
+ return 0;
+ }
+
+ LeaveCriticalSection(&threaddata_cs);
+
+ ret = ImmCreateContext();
+ if (!ret) return 0;
+ ((InputContextData*)ret)->threadDefault = TRUE;
+
+ /* thread_data is in the current thread so we can assume it's still valid */
+ EnterCriticalSection(&threaddata_cs);
+
+ if (thread_data->defaultContext) /* someone beat us */
+ {
+ IMM_DestroyContext( ret );
+ ret = thread_data->defaultContext;
+ }
+ else thread_data->defaultContext = ret;
+
+ LeaveCriticalSection(&threaddata_cs);
+ return ret;
+}
+
+static BOOL IMM_IsCrossThreadAccess(HWND hWnd, HIMC hIMC)
+{
+ InputContextData *data;
+
+ if (hWnd)
+ {
+ DWORD thread = GetWindowThreadProcessId(hWnd, NULL);
+ if (thread != GetCurrentThreadId()) return TRUE;
+ }
+ data = get_imc_data(hIMC);
+ if (data && data->threadID != GetCurrentThreadId())
+ return TRUE;
+
+ return FALSE;
+}
+
/***********************************************************************
* ImmAssociateContext (IMM32.@)
*/
HIMC WINAPI ImmAssociateContext(HWND hWnd, HIMC hIMC)
{
HIMC old = NULL;
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("(%p, %p):\n", hWnd, hIMC);
- if (!IMM_GetThreadData()->defaultContext)
- IMM_GetThreadData()->defaultContext = ImmCreateContext();
+ if(hIMC && !data)
+ return NULL;
/*
* If already associated just return
if (hIMC && data->IMC.hWnd == hWnd)
return hIMC;
+ if (hIMC && IMM_IsCrossThreadAccess(hWnd, hIMC))
+ return NULL;
+
if (hWnd)
{
+ HIMC defaultContext = get_default_context( hWnd );
old = RemovePropW(hWnd,szwWineIMCProperty);
if (old == NULL)
- old = IMM_GetThreadData()->defaultContext;
+ old = defaultContext;
else if (old == (HIMC)-1)
old = NULL;
- if (hIMC != IMM_GetThreadData()->defaultContext)
+ if (hIMC != defaultContext)
{
if (hIMC == NULL) /* Meaning disable imm for that window*/
SetPropW(hWnd,szwWineIMCProperty,(HANDLE)-1);
if (!hIMC)
return old;
- if (IsWindow(data->IMC.hWnd))
+ if(GetActiveWindow() == data->IMC.hWnd)
{
- /*
- * Post a message that your context is switching
- */
SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, FALSE, ISC_SHOWUIALL);
- }
-
- data->IMC.hWnd = hWnd;
-
- if (IsWindow(data->IMC.hWnd))
- {
- /*
- * Post a message that your context is switching
- */
+ data->IMC.hWnd = hWnd;
SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, TRUE, ISC_SHOWUIALL);
}
{
TRACE("(%p, %p, 0x%x):\n", hWnd, hIMC, dwFlags);
- if (!IMM_GetThreadData()->defaultContext)
- IMM_GetThreadData()->defaultContext = ImmCreateContext();
-
- if (!hWnd) return FALSE;
+ if (!hWnd)
+ return FALSE;
switch (dwFlags)
{
ImmAssociateContext(hWnd,hIMC);
return TRUE;
case IACE_DEFAULT:
- ImmAssociateContext(hWnd,IMM_GetThreadData()->defaultContext);
+ {
+ HIMC defaultContext = get_default_context( hWnd );
+ if (!defaultContext) return FALSE;
+ ImmAssociateContext(hWnd,defaultContext);
return TRUE;
+ }
case IACE_IGNORENOCONTEXT:
if (GetPropW(hWnd,szwWineIMCProperty))
ImmAssociateContext(hWnd,hIMC);
InputContextData *new_context;
LPGUIDELINE gl;
LPCANDIDATEINFO ci;
+ int i;
new_context = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(InputContextData));
gl->dwSize = sizeof(GUIDELINE);
ImmUnlockIMCC(new_context->IMC.hGuideLine);
+ for (i = 0; i < ARRAY_SIZE(new_context->IMC.cfCandForm); i++)
+ new_context->IMC.cfCandForm[i].dwIndex = ~0u;
+
/* Initialize the IME Private */
new_context->IMC.hPrivate = ImmCreateIMCC(new_context->immKbd->imeInfo.dwPrivateDataSize);
+ new_context->IMC.fdwConversion = new_context->immKbd->imeInfo.fdwConversionCaps;
+ new_context->IMC.fdwSentence = new_context->immKbd->imeInfo.fdwSentenceCaps;
+
if (!new_context->immKbd->pImeSelect(new_context, TRUE))
{
TRACE("Selection of IME failed\n");
IMM_DestroyContext(new_context);
return 0;
}
- SendMessageW(GetFocus(), WM_IME_SELECT, TRUE, (LPARAM)GetKeyboardLayout(0));
+ new_context->threadID = GetCurrentThreadId();
+ SendMessageW(GetFocus(), WM_IME_SELECT, TRUE, (LPARAM)new_context->immKbd);
new_context->immKbd->uSelected++;
TRACE("Created context %p\n",new_context);
+ new_context->magic = WINE_IMC_VALID_MAGIC;
return new_context;
}
static BOOL IMM_DestroyContext(HIMC hIMC)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("Destroying %p\n",hIMC);
- if (hIMC)
- {
- data->immKbd->uSelected --;
- data->immKbd->pImeSelect(hIMC, FALSE);
- SendMessageW(data->IMC.hWnd, WM_IME_SELECT, FALSE, (LPARAM)GetKeyboardLayout(0));
+ if (!data)
+ return FALSE;
- ImmDestroyIMCC(data->IMC.hCompStr);
- ImmDestroyIMCC(data->IMC.hCandInfo);
- ImmDestroyIMCC(data->IMC.hGuideLine);
- ImmDestroyIMCC(data->IMC.hPrivate);
- ImmDestroyIMCC(data->IMC.hMsgBuf);
+ data->immKbd->uSelected --;
+ data->immKbd->pImeSelect(hIMC, FALSE);
+ SendMessageW(data->IMC.hWnd, WM_IME_SELECT, FALSE, (LPARAM)data->immKbd);
+
+ ImmDestroyIMCC(data->IMC.hCompStr);
+ ImmDestroyIMCC(data->IMC.hCandInfo);
+ ImmDestroyIMCC(data->IMC.hGuideLine);
+ ImmDestroyIMCC(data->IMC.hPrivate);
+ ImmDestroyIMCC(data->IMC.hMsgBuf);
+
+ data->magic = 0;
+ HeapFree(GetProcessHeap(),0,data);
- HeapFree(GetProcessHeap(),0,data);
- }
return TRUE;
}
*/
BOOL WINAPI ImmDestroyContext(HIMC hIMC)
{
- if (hIMC != IMM_GetThreadData()->defaultContext)
+ if (!IMM_IsDefaultContext(hIMC) && !IMM_IsCrossThreadAccess(NULL, hIMC))
return IMM_DestroyContext(hIMC);
else
return FALSE;
*/
BOOL WINAPI ImmDisableIME(DWORD idThread)
{
- FIXME("(%d): stub\n", idThread);
+ if (idThread == (DWORD)-1)
+ disable_ime = TRUE;
+ else {
+ IMMThreadData *thread_data = IMM_GetThreadData(NULL, idThread);
+ if (!thread_data) return FALSE;
+ thread_data->disableIME = TRUE;
+ LeaveCriticalSection(&threaddata_cs);
+ }
return TRUE;
}
HIMC hIMC, DWORD dwIndex,
LPCANDIDATELIST lpCandList, DWORD dwBufLen)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
LPCANDIDATEINFO candinfo;
LPCANDIDATELIST candlist;
DWORD ret = 0;
return 0;
candinfo = ImmLockIMCC(data->IMC.hCandInfo);
- if ( dwIndex >= candinfo->dwCount ||
- dwIndex >= (sizeof(candinfo->dwOffset) / sizeof(DWORD)) )
+ if (dwIndex >= candinfo->dwCount || dwIndex >= ARRAY_SIZE(candinfo->dwOffset))
goto done;
candlist = (LPCANDIDATELIST)((LPBYTE)candinfo + candinfo->dwOffset[dwIndex]);
DWORD WINAPI ImmGetCandidateListCountA(
HIMC hIMC, LPDWORD lpdwListCount)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
LPCANDIDATEINFO candinfo;
DWORD ret, count;
DWORD WINAPI ImmGetCandidateListCountW(
HIMC hIMC, LPDWORD lpdwListCount)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
LPCANDIDATEINFO candinfo;
DWORD ret, count;
HIMC hIMC, DWORD dwIndex,
LPCANDIDATELIST lpCandList, DWORD dwBufLen)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
LPCANDIDATEINFO candinfo;
LPCANDIDATELIST candlist;
DWORD ret = 0;
return 0;
candinfo = ImmLockIMCC(data->IMC.hCandInfo);
- if ( dwIndex >= candinfo->dwCount ||
- dwIndex >= (sizeof(candinfo->dwOffset) / sizeof(DWORD)) )
+ if (dwIndex >= candinfo->dwCount || dwIndex >= ARRAY_SIZE(candinfo->dwOffset))
goto done;
candlist = (LPCANDIDATELIST)((LPBYTE)candinfo + candinfo->dwOffset[dwIndex]);
BOOL WINAPI ImmGetCandidateWindow(
HIMC hIMC, DWORD dwIndex, LPCANDIDATEFORM lpCandidate)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("%p, %d, %p\n", hIMC, dwIndex, lpCandidate);
if (!data || !lpCandidate)
return FALSE;
- if ( dwIndex >= (sizeof(data->IMC.cfCandForm) / sizeof(CANDIDATEFORM)) )
+ if (dwIndex >= ARRAY_SIZE(data->IMC.cfCandForm))
+ return FALSE;
+
+ if (data->IMC.cfCandForm[dwIndex].dwIndex != dwIndex)
return FALSE;
*lpCandidate = data->IMC.cfCandForm[dwIndex];
*/
BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("(%p, %p):\n", hIMC, lplf);
/* Helpers for the GetCompositionString functions */
-static INT CopyCompStringIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE target, INT tlen,
- BOOL unicode )
+/* Source encoding is defined by context, source length is always given in respective characters. Destination buffer
+ length is always in bytes. */
+static INT CopyCompStringIMEtoClient(const InputContextData *data, const void *src, INT src_len, void *dst,
+ INT dst_len, BOOL unicode)
{
- INT rc;
+ int char_size = unicode ? sizeof(WCHAR) : sizeof(char);
+ INT ret;
- if (is_himc_ime_unicode(data) && !unicode)
- rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)source, slen, (LPSTR)target, tlen, NULL, NULL);
- else if (!is_himc_ime_unicode(data) && unicode)
- rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)source, slen, (LPWSTR)target, tlen) * sizeof(WCHAR);
+ if (is_himc_ime_unicode(data) ^ unicode)
+ {
+ if (unicode)
+ ret = MultiByteToWideChar(CP_ACP, 0, src, src_len, dst, dst_len / sizeof(WCHAR));
+ else
+ ret = WideCharToMultiByte(CP_ACP, 0, src, src_len, dst, dst_len, NULL, NULL);
+ ret *= char_size;
+ }
else
{
- int dlen = (unicode)?sizeof(WCHAR):sizeof(CHAR);
- memcpy( target, source, min(slen,tlen)*dlen);
- rc = slen*dlen;
+ if (dst_len)
+ {
+ ret = min(src_len * char_size, dst_len);
+ memcpy(dst, src, ret);
+ }
+ else
+ ret = src_len * char_size;
}
- return rc;
+ return ret;
}
-static INT CopyCompAttrIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE ssource, INT sslen,
- LPBYTE target, INT tlen, BOOL unicode )
+/* Composition string encoding is defined by context, returned attributes correspond to string, converted according to
+ passed mode. String length is in characters, attributes are in byte arrays. */
+static INT CopyCompAttrIMEtoClient(const InputContextData *data, const BYTE *src, INT src_len, const void *comp_string,
+ INT str_len, BYTE *dst, INT dst_len, BOOL unicode)
{
+ union
+ {
+ const void *str;
+ const WCHAR *strW;
+ const char *strA;
+ } string;
INT rc;
+ string.str = comp_string;
+
if (is_himc_ime_unicode(data) && !unicode)
{
- rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource, sslen, NULL, 0, NULL, NULL);
- if (tlen)
+ rc = WideCharToMultiByte(CP_ACP, 0, string.strW, str_len, NULL, 0, NULL, NULL);
+ if (dst_len)
{
- const BYTE *src = source;
- LPBYTE dst = target;
int i, j = 0, k = 0;
- if (rc < tlen)
- tlen = rc;
- for (i = 0; i < sslen; ++i)
+ if (rc < dst_len)
+ dst_len = rc;
+ for (i = 0; i < str_len; ++i)
{
int len;
- len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)ssource + i, 1,
- NULL, 0, NULL, NULL);
+ len = WideCharToMultiByte(CP_ACP, 0, string.strW + i, 1, NULL, 0, NULL, NULL);
for (; len > 0; --len)
{
dst[j++] = src[k];
- if (j >= tlen)
+ if (j >= dst_len)
goto end;
}
++k;
}
else if (!is_himc_ime_unicode(data) && unicode)
{
- rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource, sslen, NULL, 0);
- if (tlen)
+ rc = MultiByteToWideChar(CP_ACP, 0, string.strA, str_len, NULL, 0);
+ if (dst_len)
{
- const BYTE *src = source;
- LPBYTE dst = target;
int i, j = 0;
- if (rc < tlen)
- tlen = rc;
- for (i = 0; i < sslen; ++i)
+ if (rc < dst_len)
+ dst_len = rc;
+ for (i = 0; i < str_len; ++i)
{
- if (IsDBCSLeadByte(((LPSTR)ssource)[i]))
+ if (IsDBCSLeadByte(string.strA[i]))
continue;
dst[j++] = src[i];
- if (j >= tlen)
+ if (j >= dst_len)
break;
}
rc = j;
}
else
{
- memcpy( target, source, min(slen,tlen));
- rc = slen;
+ memcpy(dst, src, min(src_len, dst_len));
+ rc = src_len;
}
return rc;
DWORD dwBufLen, BOOL unicode)
{
LONG rc = 0;
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
LPCOMPOSITIONSTRING compstr;
LPBYTE compdata;
*/
BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("(%p, %p)\n", hIMC, lpCompForm);
return FALSE;
*lpCompForm = data->IMC.cfCompForm;
- return 1;
+ return TRUE;
}
/***********************************************************************
SetLastError(ERROR_INVALID_WINDOW_HANDLE);
return NULL;
}
- if (!IMM_GetThreadData()->defaultContext)
- IMM_GetThreadData()->defaultContext = ImmCreateContext();
rc = GetPropW(hWnd,szwWineIMCProperty);
if (rc == (HIMC)-1)
rc = NULL;
else if (rc == NULL)
- rc = IMM_GetThreadData()->defaultContext;
+ rc = get_default_context( hWnd );
if (rc)
{
InputContextData *data = rc;
data->IMC.hWnd = hWnd;
}
+
TRACE("returning %p\n", rc);
return rc;
BOOL WINAPI ImmGetConversionStatus(
HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("%p %p %p\n", hIMC, lpfdwConversion, lpfdwSentence);
return TRUE;
}
+static BOOL needs_ime_window(HWND hwnd)
+{
+ WCHAR classW[8];
+
+ if (GetClassNameW(hwnd, classW, ARRAY_SIZE(classW)) && !lstrcmpW(classW, szwIME))
+ return FALSE;
+ if (GetClassLongPtrW(hwnd, GCL_STYLE) & CS_IME) return FALSE;
+
+ return TRUE;
+}
+
+/***********************************************************************
+ * __wine_register_window (IMM32.@)
+ */
+BOOL WINAPI __wine_register_window(HWND hwnd)
+{
+ HWND new = NULL;
+ IMMThreadData *thread_data;
+ TRACE("(%p)\n", hwnd);
+
+ if (!needs_ime_window(hwnd))
+ return FALSE;
+
+ thread_data = IMM_GetThreadData(hwnd, 0);
+ if (!thread_data)
+ return FALSE;
+
+ if (thread_data->disableIME || disable_ime)
+ {
+ TRACE("IME for this thread is disabled\n");
+ LeaveCriticalSection(&threaddata_cs);
+ return FALSE;
+ }
+ thread_data->windowRefs++;
+ TRACE("windowRefs=%u, hwndDefault=%p\n",
+ thread_data->windowRefs, thread_data->hwndDefault);
+
+ /* Create default IME window */
+ if (thread_data->windowRefs == 1)
+ {
+ /* Do not create the window inside of a critical section */
+ LeaveCriticalSection(&threaddata_cs);
+ new = CreateWindowExW( 0, szwIME, szwDefaultIME,
+ WS_POPUP | WS_DISABLED | WS_CLIPSIBLINGS,
+ 0, 0, 1, 1, 0, 0, 0, 0);
+ /* thread_data is in the current thread so we can assume it's still valid */
+ EnterCriticalSection(&threaddata_cs);
+ /* See if anyone beat us */
+ if (thread_data->hwndDefault == NULL)
+ {
+ thread_data->hwndDefault = new;
+ new = NULL;
+ TRACE("Default is %p\n", thread_data->hwndDefault);
+ }
+ }
+
+ LeaveCriticalSection(&threaddata_cs);
+
+ /* Clean up an unused new window outside of the critical section */
+ if (new != NULL)
+ DestroyWindow(new);
+ return TRUE;
+}
+
+/***********************************************************************
+ * __wine_unregister_window (IMM32.@)
+ */
+void WINAPI __wine_unregister_window(HWND hwnd)
+{
+ HWND to_destroy = 0;
+ IMMThreadData *thread_data;
+ TRACE("(%p)\n", hwnd);
+
+ thread_data = IMM_GetThreadData(hwnd, 0);
+ if (!thread_data) return;
+
+ thread_data->windowRefs--;
+ TRACE("windowRefs=%u, hwndDefault=%p\n",
+ thread_data->windowRefs, thread_data->hwndDefault);
+
+ /* Destroy default IME window */
+ if (thread_data->windowRefs == 0 && thread_data->hwndDefault)
+ {
+ to_destroy = thread_data->hwndDefault;
+ thread_data->hwndDefault = NULL;
+ }
+ LeaveCriticalSection(&threaddata_cs);
+
+ if (to_destroy) DestroyWindow( to_destroy );
+}
+
/***********************************************************************
* ImmGetDefaultIMEWnd (IMM32.@)
*/
HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
{
- if (IMM_GetThreadData()->hwndDefault == NULL)
- IMM_GetThreadData()->hwndDefault = CreateWindowExW( WS_EX_TOOLWINDOW,
- szwIME, NULL, WS_POPUP, 0, 0, 1, 1, 0, 0, 0, 0);
- TRACE("Default is %p\n",IMM_GetThreadData()->hwndDefault);
- return IMM_GetThreadData()->hwndDefault;
+ HWND ret;
+ IMMThreadData* thread_data = IMM_GetThreadData(hWnd, 0);
+ if (!thread_data)
+ return NULL;
+ ret = thread_data->hwndDefault;
+ LeaveCriticalSection(&threaddata_cs);
+ TRACE("Default is %p\n",ret);
+ return ret;
}
/***********************************************************************
/* find out how many characters in the unicode buffer */
len = ImmGetDescriptionW( hKL, NULL, 0 );
+ if (!len)
+ return 0;
/* allocate a buffer of that size */
buf = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof (WCHAR) );
HeapFree( GetProcessHeap(), 0, buf );
- return len;
+ if (len == 0)
+ return 0;
+
+ return len - 1;
}
/***********************************************************************
FIXME("(%p, %p, %d): semi stub\n", hKL, lpszDescription, uBufLen);
+ if (!hKL) return 0;
if (!uBufLen) return lstrlenW( name );
lstrcpynW( lpszDescription, name, uBufLen );
return lstrlenW( lpszDescription );
HKEY hkey;
DWORD length;
DWORD rc;
- WCHAR regKey[sizeof(szImeRegFmt)/sizeof(WCHAR)+8];
+ WCHAR regKey[ARRAY_SIZE(szImeRegFmt)+8];
wsprintfW( regKey, szImeRegFmt, (ULONG_PTR)hKL );
rc = RegOpenKeyW( HKEY_LOCAL_MACHINE, regKey, &hkey);
*/
BOOL WINAPI ImmGetOpenStatus(HIMC hIMC)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
static int i;
if (!data)
*/
BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("(%p, %p)\n", hIMC, lpptPos);
HKL hkl;
DWORD rc;
HKEY hkey;
- WCHAR regKey[sizeof(szImeRegFmt)/sizeof(WCHAR)+8];
+ WCHAR regKey[ARRAY_SIZE(szImeRegFmt)+8];
TRACE ("(%s, %s):\n", debugstr_w(lpszIMEFileName),
debugstr_w(lpszLayoutText));
BOOL WINAPI ImmIsUIMessageA(
HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
{
- BOOL rc = FALSE;
-
TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam);
if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
(msg == WM_IME_SETCONTEXT) ||
(msg == WM_IME_NOTIFY) ||
(msg == WM_IME_COMPOSITIONFULL) ||
(msg == WM_IME_SELECT) ||
- (msg == 0x287 /* FIXME: WM_IME_SYSTEM */) ||
- (msg == WM_MSIME_RECONVERTOPTIONS) ||
- (msg == WM_MSIME_MOUSE) ||
- (msg == WM_MSIME_RECONVERTREQUEST) ||
- (msg == WM_MSIME_RECONVERT) ||
- (msg == WM_MSIME_QUERYPOSITION) ||
- (msg == WM_MSIME_DOCUMENTFEED))
+ (msg == 0x287 /* FIXME: WM_IME_SYSTEM */))
{
if (hWndIME)
SendMessageA(hWndIME, msg, wParam, lParam);
- rc = TRUE;
+ return TRUE;
}
- return rc;
+ return FALSE;
}
/***********************************************************************
BOOL WINAPI ImmIsUIMessageW(
HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
{
- BOOL rc = FALSE;
-
TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam);
if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
(msg == WM_IME_SETCONTEXT) ||
(msg == WM_IME_NOTIFY) ||
(msg == WM_IME_COMPOSITIONFULL) ||
(msg == WM_IME_SELECT) ||
- (msg == 0x287 /* FIXME: WM_IME_SYSTEM */) ||
- (msg == WM_MSIME_RECONVERTOPTIONS) ||
- (msg == WM_MSIME_MOUSE) ||
- (msg == WM_MSIME_RECONVERTREQUEST) ||
- (msg == WM_MSIME_RECONVERT) ||
- (msg == WM_MSIME_QUERYPOSITION) ||
- (msg == WM_MSIME_DOCUMENTFEED))
+ (msg == 0x287 /* FIXME: WM_IME_SYSTEM */))
{
if (hWndIME)
SendMessageW(hWndIME, msg, wParam, lParam);
- rc = TRUE;
+ return TRUE;
}
- return rc;
+ return FALSE;
}
/***********************************************************************
BOOL WINAPI ImmNotifyIME(
HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("(%p, %d, %d, %d)\n",
hIMC, dwAction, dwIndex, dwValue);
+ if (hIMC == NULL)
+ {
+ SetLastError(ERROR_SUCCESS);
+ return FALSE;
+ }
+
if (!data || ! data->immKbd->pNotifyIME)
+ {
return FALSE;
+ }
return data->immKbd->pNotifyIME(hIMC,dwAction,dwIndex,dwValue);
}
*/
BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC)
{
- static int shown = 0;
+ static BOOL shown = FALSE;
if (!shown) {
FIXME("(%p, %p): stub\n", hWnd, hIMC);
- shown = 1;
+ shown = TRUE;
}
return TRUE;
}
*/
LRESULT WINAPI ImmRequestMessageA(HIMC hIMC, WPARAM wParam, LPARAM lParam)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("%p %ld %ld\n", hIMC, wParam, wParam);
- if (data && IsWindow(data->IMC.hWnd))
- return SendMessageA(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
+ if (data) return SendMessageA(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
- return 0;
+ SetLastError(ERROR_INVALID_HANDLE);
+ return 0;
}
/***********************************************************************
*/
LRESULT WINAPI ImmRequestMessageW(HIMC hIMC, WPARAM wParam, LPARAM lParam)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("%p %ld %ld\n", hIMC, wParam, wParam);
- if (data && IsWindow(data->IMC.hWnd))
- return SendMessageW(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
+ if (data) return SendMessageW(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
- return 0;
+ SetLastError(ERROR_INVALID_HANDLE);
+ return 0;
}
/***********************************************************************
BOOL WINAPI ImmSetCandidateWindow(
HIMC hIMC, LPCANDIDATEFORM lpCandidate)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("(%p, %p)\n", hIMC, lpCandidate);
if (!data || !lpCandidate)
return FALSE;
- TRACE("\t%x, %x, (%i,%i), (%i,%i - %i,%i)\n",
- lpCandidate->dwIndex, lpCandidate->dwStyle,
- lpCandidate->ptCurrentPos.x, lpCandidate->ptCurrentPos.y,
- lpCandidate->rcArea.top, lpCandidate->rcArea.left,
- lpCandidate->rcArea.bottom, lpCandidate->rcArea.right);
+ if (IMM_IsCrossThreadAccess(NULL, hIMC))
+ return FALSE;
+
+ TRACE("\t%x, %x, %s, %s\n",
+ lpCandidate->dwIndex, lpCandidate->dwStyle,
+ wine_dbgstr_point(&lpCandidate->ptCurrentPos),
+ wine_dbgstr_rect(&lpCandidate->rcArea));
- if ( lpCandidate->dwIndex >= (sizeof(data->IMC.cfCandForm) / sizeof(CANDIDATEFORM)) )
+ if (lpCandidate->dwIndex >= ARRAY_SIZE(data->IMC.cfCandForm))
return FALSE;
data->IMC.cfCandForm[lpCandidate->dwIndex] = *lpCandidate;
*/
BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("(%p, %p)\n", hIMC, lplf);
if (!data || !lplf)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
+ if (IMM_IsCrossThreadAccess(NULL, hIMC))
return FALSE;
memcpy(&data->IMC.lfFont.W,lplf,sizeof(LOGFONTA));
*/
BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("(%p, %p)\n", hIMC, lplf);
if (!data || !lplf)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
+ if (IMM_IsCrossThreadAccess(NULL, hIMC))
return FALSE;
data->IMC.lfFont.W = *lplf;
WCHAR *CompBuffer = NULL;
WCHAR *ReadBuffer = NULL;
BOOL rc;
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("(%p, %d, %p, %d, %p, %d):\n",
hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
CHAR *CompBuffer = NULL;
CHAR *ReadBuffer = NULL;
BOOL rc;
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("(%p, %d, %p, %d, %p, %d):\n",
hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
{
BOOL reshow = FALSE;
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("(%p, %p)\n", hIMC, lpCompForm);
- TRACE("\t%x, (%i,%i), (%i,%i - %i,%i)\n",lpCompForm->dwStyle,
- lpCompForm->ptCurrentPos.x, lpCompForm->ptCurrentPos.y, lpCompForm->rcArea.top,
- lpCompForm->rcArea.left, lpCompForm->rcArea.bottom, lpCompForm->rcArea.right);
+ if (lpCompForm)
+ TRACE("\t%x, %s, %s\n", lpCompForm->dwStyle,
+ wine_dbgstr_point(&lpCompForm->ptCurrentPos),
+ wine_dbgstr_rect(&lpCompForm->rcArea));
if (!data)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
+ if (IMM_IsCrossThreadAccess(NULL, hIMC))
return FALSE;
data->IMC.cfCompForm = *lpCompForm;
HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence)
{
DWORD oldConversion, oldSentence;
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("%p %d %d\n", hIMC, fdwConversion, fdwSentence);
if (!data)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
+ if (IMM_IsCrossThreadAccess(NULL, hIMC))
return FALSE;
if ( fdwConversion != data->IMC.fdwConversion )
*/
BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("%p %d\n", hIMC, fOpen);
if (!data)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
+ if (IMM_IsCrossThreadAccess(NULL, hIMC))
return FALSE;
if (data->immKbd->UIWnd == NULL)
*/
BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("(%p, %p)\n", hIMC, lpptPos);
if (!data || !lpptPos)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
+ }
- TRACE("\t(%i,%i)\n", lpptPos->x, lpptPos->y);
+ if (IMM_IsCrossThreadAccess(NULL, hIMC))
+ return FALSE;
+
+ TRACE("\t%s\n", wine_dbgstr_point(lpptPos));
data->IMC.ptStatusWndPos = *lpptPos;
ImmNotifyIME( hIMC, NI_CONTEXTUPDATED, 0, IMC_SETSTATUSWINDOWPOS);
LPIMEMENUITEMINFOA lpImeParentMenu, LPIMEMENUITEMINFOA lpImeMenu,
DWORD dwSize)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
lpImeParentMenu, lpImeMenu, dwSize);
+
+ if (!data)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return 0;
+ }
+
if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems)
{
if (!is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu))
LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu,
DWORD dwSize)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
lpImeParentMenu, lpImeMenu, dwSize);
+
+ if (!data)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return 0;
+ }
+
if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems)
{
if (is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu))
*/
LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
if (!data)
return NULL;
*/
BOOL WINAPI ImmUnlockIMC(HIMC hIMC)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
+
+ if (!data)
+ return FALSE;
if (data->dwLock)
data->dwLock--;
return TRUE;
*/
DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
+ if (!data)
+ return 0;
return data->dwLock;
}
*/
BOOL WINAPI ImmGenerateMessage(HIMC hIMC)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
+
+ if (!data)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
TRACE("%i messages queued\n",data->IMC.dwNumMsgBuf);
if (data->IMC.dwNumMsgBuf > 0)
{
LPTRANSMSG lpTransMsg;
- DWORD i;
-
- lpTransMsg = ImmLockIMCC(data->IMC.hMsgBuf);
- for (i = 0; i < data->IMC.dwNumMsgBuf; i++)
- ImmInternalPostIMEMessage(data, lpTransMsg[i].message, lpTransMsg[i].wParam, lpTransMsg[i].lParam);
+ HIMCC hMsgBuf;
+ DWORD i, dwNumMsgBuf;
- ImmUnlockIMCC(data->IMC.hMsgBuf);
+ /* We are going to detach our hMsgBuff so that if processing messages
+ generates new messages they go into a new buffer */
+ hMsgBuf = data->IMC.hMsgBuf;
+ dwNumMsgBuf = data->IMC.dwNumMsgBuf;
+ data->IMC.hMsgBuf = ImmCreateIMCC(0);
data->IMC.dwNumMsgBuf = 0;
+
+ lpTransMsg = ImmLockIMCC(hMsgBuf);
+ for (i = 0; i < dwNumMsgBuf; i++)
+ ImmInternalSendIMEMessage(data, lpTransMsg[i].message, lpTransMsg[i].wParam, lpTransMsg[i].lParam);
+
+ ImmUnlockIMCC(hMsgBuf);
+ ImmDestroyIMCC(hMsgBuf);
}
return TRUE;
else
return FALSE;
+ /* Make sure we are inputting to the correct keyboard */
+ if (data->immKbd->hkl != hKL)
+ {
+ ImmHkl *new_hkl = IMM_GetImmHkl(hKL);
+ if (new_hkl)
+ {
+ data->immKbd->pImeSelect(imc, FALSE);
+ data->immKbd->uSelected--;
+ data->immKbd = new_hkl;
+ data->immKbd->pImeSelect(imc, TRUE);
+ data->immKbd->uSelected++;
+ }
+ else
+ return FALSE;
+ }
+
if (!data->immKbd->hIME || !data->immKbd->pImeProcessKey)
return FALSE;
return FALSE;
}
-
-/*
- * Window Proc for the Default IME window class
- */
-static LRESULT WINAPI DefIME_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
- LPARAM lParam)
-{
- switch (uMsg)
- {
- case WM_CREATE:
- case WM_NCCREATE:
- return TRUE;
- case WM_IME_STARTCOMPOSITION:
- case WM_IME_ENDCOMPOSITION:
- case WM_IME_COMPOSITION:
- case WM_IME_SETCONTEXT:
- case WM_IME_NOTIFY:
- case WM_IME_CONTROL:
- case WM_IME_COMPOSITIONFULL:
- case WM_IME_SELECT:
- case WM_IME_CHAR:
- case WM_IME_REQUEST:
- case WM_IME_KEYDOWN:
- case WM_IME_KEYUP:
- {
- ImmHkl *immHkl = IMM_GetImmHkl(GetKeyboardLayout(0));
- if (immHkl->UIWnd)
- return SendMessageW(immHkl->UIWnd,uMsg,wParam,lParam);
- else
- return FALSE;
- }
- default:
- if ((uMsg == WM_MSIME_RECONVERTOPTIONS) ||
- (uMsg == WM_MSIME_SERVICE) ||
- (uMsg == WM_MSIME_MOUSE) ||
- (uMsg == WM_MSIME_RECONVERTREQUEST) ||
- (uMsg == WM_MSIME_RECONVERT) ||
- (uMsg == WM_MSIME_QUERYPOSITION) ||
- (uMsg == WM_MSIME_DOCUMENTFEED))
- {
- ImmHkl *immHkl = IMM_GetImmHkl(GetKeyboardLayout(0));
- if (immHkl->UIWnd)
- return SendMessageW(immHkl->UIWnd,uMsg,wParam,lParam);
- else
- return FALSE;
- }
- return DefWindowProcW(hwnd, uMsg, wParam, lParam);
- }
+/***********************************************************************
+ * ImmDisableLegacyIME(IMM32.@)
+ */
+BOOL WINAPI ImmDisableLegacyIME(void)
+{
+ FIXME("stub\n");
+ return TRUE;
}