2533 lines
75 KiB
C
2533 lines
75 KiB
C
/*
|
|
* IMM32 library
|
|
*
|
|
* Copyright 1998 Patrik Stridvall
|
|
* Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
|
|
#include <stdarg.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 FROM_IME 0xcafe1337
|
|
|
|
static void (*pX11DRV_ForceXIMReset)(HWND);
|
|
|
|
typedef struct tagIMCCInternal
|
|
{
|
|
DWORD dwLock;
|
|
DWORD dwSize;
|
|
} IMCCInternal;
|
|
|
|
#define MAKE_FUNCPTR(f) typeof(f) * p##f
|
|
typedef struct _tagImmHkl{
|
|
struct list entry;
|
|
HKL hkl;
|
|
HMODULE hIME;
|
|
IMEINFO imeInfo;
|
|
WCHAR imeClassName[17]; /* 16 character max */
|
|
ULONG uSelected;
|
|
|
|
/* 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);
|
|
} ImmHkl;
|
|
#undef MAKE_FUNCPTR
|
|
|
|
typedef struct tagInputContextData
|
|
{
|
|
BOOL bInternalState;
|
|
BOOL bRead;
|
|
BOOL bInComposition;
|
|
HFONT textfont;
|
|
|
|
DWORD dwLock;
|
|
INPUTCONTEXT IMC;
|
|
|
|
ImmHkl *immKbd;
|
|
} InputContextData;
|
|
|
|
typedef struct _tagTRANSMSG {
|
|
UINT message;
|
|
WPARAM wParam;
|
|
LPARAM lParam;
|
|
} TRANSMSG, *LPTRANSMSG;
|
|
|
|
static InputContextData *root_context = NULL;
|
|
static HWND hwndDefault = NULL;
|
|
static HANDLE hImeInst;
|
|
static const WCHAR WC_IMECLASSNAME[] = {'I','M','E',0};
|
|
static ATOM atIMEClass = 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 const WCHAR szwWineIMCProperty[] = {'W','i','n','e','I','m','m','H','I','M','C','P','r','o','p','e','r','t','y',0};
|
|
/*
|
|
* prototypes
|
|
*/
|
|
static LRESULT WINAPI IME_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
|
|
LPARAM lParam);
|
|
static void UpdateDataInDefaultIMEWindow(HWND hwnd, BOOL showable);
|
|
static void ImmInternalPostIMEMessage(InputContextData*, UINT, WPARAM, LPARAM);
|
|
static void ImmInternalSetOpenStatus(BOOL fOpen);
|
|
static HIMCC updateResultStr(HIMCC old, LPWSTR resultstr, DWORD len);
|
|
|
|
/* ImmHkl loading and freeing */
|
|
#define LOAD_FUNCPTR(f) if((ptr->p##f = (LPVOID)GetProcAddress(ptr->hIME, #f)) == NULL){WARN("Can't find function %s in ime\n", #f);}
|
|
static ImmHkl *IMM_GetImmHkl(HKL hkl)
|
|
{
|
|
ImmHkl *ptr;
|
|
WCHAR filename[MAX_PATH];
|
|
|
|
TRACE("Seeking ime for keyboard 0x%x\n",(unsigned)hkl);
|
|
|
|
LIST_FOR_EACH_ENTRY(ptr, &ImmHklList, ImmHkl, entry)
|
|
{
|
|
if (ptr->hkl == hkl)
|
|
return ptr;
|
|
}
|
|
/* not found... create it */
|
|
|
|
ptr = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ImmHkl));
|
|
|
|
ptr->hkl = hkl;
|
|
if (ImmGetIMEFileNameW(hkl, filename, MAX_PATH)) ptr->hIME = LoadLibraryW(filename);
|
|
if (ptr->hIME)
|
|
{
|
|
LOAD_FUNCPTR(ImeInquire);
|
|
LOAD_FUNCPTR(ImeDestroy);
|
|
LOAD_FUNCPTR(ImeSelect);
|
|
if (!ptr->pImeInquire || !ptr->pImeDestroy || !ptr->pImeSelect)
|
|
{
|
|
FreeLibrary(ptr->hIME);
|
|
ptr->hIME = NULL;
|
|
}
|
|
else
|
|
{
|
|
ptr->pImeInquire(&ptr->imeInfo, ptr->imeClassName, NULL);
|
|
LOAD_FUNCPTR(ImeConfigure);
|
|
LOAD_FUNCPTR(ImeEscape);
|
|
LOAD_FUNCPTR(ImeSetActiveContext);
|
|
LOAD_FUNCPTR(ImeToAsciiEx);
|
|
LOAD_FUNCPTR(NotifyIME);
|
|
LOAD_FUNCPTR(ImeRegisterWord);
|
|
LOAD_FUNCPTR(ImeUnregisterWord);
|
|
LOAD_FUNCPTR(ImeEnumRegisterWord);
|
|
LOAD_FUNCPTR(ImeSetCompositionString);
|
|
LOAD_FUNCPTR(ImeConversionList);
|
|
LOAD_FUNCPTR(ImeProcessKey);
|
|
LOAD_FUNCPTR(ImeGetRegisterWordStyle);
|
|
LOAD_FUNCPTR(ImeGetImeMenuItems);
|
|
}
|
|
}
|
|
list_add_head(&ImmHklList,&ptr->entry);
|
|
|
|
return ptr;
|
|
}
|
|
#undef LOAD_FUNCPTR
|
|
|
|
static void IMM_FreeAllImmHkl(void)
|
|
{
|
|
ImmHkl *ptr,*cursor2;
|
|
|
|
LIST_FOR_EACH_ENTRY_SAFE(ptr, cursor2, &ImmHklList, ImmHkl, entry)
|
|
{
|
|
list_remove(&ptr->entry);
|
|
if (ptr->hIME)
|
|
{
|
|
ptr->pImeDestroy(1);
|
|
FreeLibrary(ptr->hIME);
|
|
}
|
|
HeapFree(GetProcessHeap(),0,ptr);
|
|
}
|
|
}
|
|
|
|
static VOID IMM_PostResult(InputContextData *data)
|
|
{
|
|
unsigned int i;
|
|
LPCOMPOSITIONSTRING compstr;
|
|
LPBYTE compdata;
|
|
LPWSTR ResultStr;
|
|
HIMCC newCompStr;
|
|
|
|
TRACE("Posting result as IME_CHAR\n");
|
|
compdata = ImmLockIMCC(root_context->IMC.hCompStr);
|
|
compstr = (LPCOMPOSITIONSTRING)compdata;
|
|
ResultStr = (LPWSTR)(compdata + compstr->dwResultStrOffset);
|
|
|
|
for (i = 0; i < compstr->dwResultStrLen; i++)
|
|
ImmInternalPostIMEMessage (root_context, WM_IME_CHAR, ResultStr[i], 1);
|
|
|
|
ImmUnlockIMCC(root_context->IMC.hCompStr);
|
|
|
|
/* clear the buffer */
|
|
newCompStr = updateResultStr(root_context->IMC.hCompStr, NULL, 0);
|
|
ImmDestroyIMCC(root_context->IMC.hCompStr);
|
|
root_context->IMC.hCompStr = newCompStr;
|
|
}
|
|
|
|
static void IMM_Register(void)
|
|
{
|
|
WNDCLASSW wndClass;
|
|
ZeroMemory(&wndClass, sizeof(WNDCLASSW));
|
|
wndClass.style = CS_GLOBALCLASS | CS_IME | CS_HREDRAW | CS_VREDRAW;
|
|
wndClass.lpfnWndProc = (WNDPROC) IME_WindowProc;
|
|
wndClass.cbClsExtra = 0;
|
|
wndClass.cbWndExtra = 0;
|
|
wndClass.hInstance = hImeInst;
|
|
wndClass.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
|
|
wndClass.hIcon = NULL;
|
|
wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW +1);
|
|
wndClass.lpszMenuName = 0;
|
|
wndClass.lpszClassName = WC_IMECLASSNAME;
|
|
atIMEClass = RegisterClassW(&wndClass);
|
|
}
|
|
|
|
static void IMM_Unregister(void)
|
|
{
|
|
if (atIMEClass) {
|
|
UnregisterClassW(WC_IMECLASSNAME, NULL);
|
|
}
|
|
}
|
|
|
|
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");
|
|
}
|
|
|
|
|
|
BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved)
|
|
{
|
|
HMODULE x11drv;
|
|
|
|
TRACE("%p, %x, %p\n",hInstDLL,fdwReason,lpReserved);
|
|
switch (fdwReason)
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
DisableThreadLibraryCalls(hInstDLL);
|
|
hImeInst = hInstDLL;
|
|
IMM_RegisterMessages();
|
|
x11drv = GetModuleHandleA("winex11.drv");
|
|
if (x11drv) pX11DRV_ForceXIMReset = (void *)GetProcAddress( x11drv, "ForceXIMReset");
|
|
break;
|
|
case DLL_PROCESS_DETACH:
|
|
if (hwndDefault)
|
|
{
|
|
DestroyWindow(hwndDefault);
|
|
hwndDefault = 0;
|
|
}
|
|
IMM_Unregister();
|
|
IMM_FreeAllImmHkl();
|
|
break;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/* for posting messages as the IME */
|
|
static void ImmInternalPostIMEMessage(InputContextData *data, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HWND target = GetFocus();
|
|
if (!target)
|
|
PostMessageW(data->IMC.hWnd,msg,wParam,lParam);
|
|
else
|
|
PostMessageW(target, msg, wParam, lParam);
|
|
}
|
|
|
|
static LRESULT ImmInternalSendIMENotify(InputContextData *data, WPARAM notify, LPARAM lParam)
|
|
{
|
|
HWND target;
|
|
|
|
target = data->IMC.hWnd;
|
|
if (!target) target = GetFocus();
|
|
|
|
if (target)
|
|
return SendMessageW(target, WM_IME_NOTIFY, notify, lParam);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static HIMCC ImmCreateBlankCompStr(void)
|
|
{
|
|
HIMCC rc;
|
|
LPCOMPOSITIONSTRING ptr;
|
|
rc = ImmCreateIMCC(sizeof(COMPOSITIONSTRING));
|
|
ptr = (LPCOMPOSITIONSTRING)ImmLockIMCC(rc);
|
|
memset(ptr,0,sizeof(COMPOSITIONSTRING));
|
|
ptr->dwSize = sizeof(COMPOSITIONSTRING);
|
|
ImmUnlockIMCC(rc);
|
|
return rc;
|
|
}
|
|
|
|
static void ImmInternalSetOpenStatus(BOOL fOpen)
|
|
{
|
|
TRACE("Setting internal state to %s\n",(fOpen)?"OPEN":"CLOSED");
|
|
|
|
if (root_context->IMC.fOpen && fOpen == FALSE)
|
|
{
|
|
ShowWindow(hwndDefault,SW_HIDE);
|
|
ImmDestroyIMCC(root_context->IMC.hCompStr);
|
|
root_context->IMC.hCompStr = ImmCreateBlankCompStr();
|
|
}
|
|
|
|
root_context->IMC.fOpen = fOpen;
|
|
root_context->bInternalState = fOpen;
|
|
|
|
ImmInternalSendIMENotify(root_context, IMN_SETOPENSTATUS, 0);
|
|
}
|
|
|
|
static int updateField(DWORD origLen, DWORD origOffset, DWORD currentOffset,
|
|
LPBYTE target, LPBYTE source, DWORD* lenParam,
|
|
DWORD* offsetParam, BOOL wchars )
|
|
{
|
|
if (origLen > 0 && origOffset > 0)
|
|
{
|
|
int truelen = origLen;
|
|
if (wchars)
|
|
truelen *= sizeof(WCHAR);
|
|
|
|
memcpy(&target[currentOffset], &source[origOffset], truelen);
|
|
|
|
*lenParam = origLen;
|
|
*offsetParam = currentOffset;
|
|
currentOffset += truelen;
|
|
}
|
|
return currentOffset;
|
|
}
|
|
|
|
static HIMCC updateCompStr(HIMCC old, LPWSTR compstr, DWORD len)
|
|
{
|
|
/* we need to make sure the CompStr, CompClaus and CompAttr fields are all
|
|
* set and correct */
|
|
int needed_size;
|
|
HIMCC rc;
|
|
LPBYTE newdata = NULL;
|
|
LPBYTE olddata = NULL;
|
|
LPCOMPOSITIONSTRING new_one;
|
|
LPCOMPOSITIONSTRING lpcs = NULL;
|
|
INT current_offset = 0;
|
|
|
|
TRACE("%s, %i\n",debugstr_wn(compstr,len),len);
|
|
|
|
if (old == NULL && compstr == NULL && len == 0)
|
|
return NULL;
|
|
|
|
if (old != NULL)
|
|
{
|
|
olddata = ImmLockIMCC(old);
|
|
lpcs = (LPCOMPOSITIONSTRING)olddata;
|
|
}
|
|
|
|
needed_size = sizeof(COMPOSITIONSTRING) + len * sizeof(WCHAR) +
|
|
len + sizeof(DWORD) * 2;
|
|
|
|
if (lpcs != NULL)
|
|
{
|
|
needed_size += lpcs->dwCompReadAttrLen;
|
|
needed_size += lpcs->dwCompReadClauseLen;
|
|
needed_size += lpcs->dwCompReadStrLen * sizeof(DWORD);
|
|
needed_size += lpcs->dwResultReadClauseLen;
|
|
needed_size += lpcs->dwResultReadStrLen * sizeof(DWORD);
|
|
needed_size += lpcs->dwResultClauseLen;
|
|
needed_size += lpcs->dwResultStrLen * sizeof(DWORD);
|
|
needed_size += lpcs->dwPrivateSize;
|
|
}
|
|
rc = ImmCreateIMCC(needed_size);
|
|
newdata = ImmLockIMCC(rc);
|
|
new_one = (LPCOMPOSITIONSTRING)newdata;
|
|
|
|
new_one->dwSize = needed_size;
|
|
current_offset = sizeof(COMPOSITIONSTRING);
|
|
if (lpcs != NULL)
|
|
{
|
|
current_offset = updateField(lpcs->dwCompReadAttrLen,
|
|
lpcs->dwCompReadAttrOffset,
|
|
current_offset, newdata, olddata,
|
|
&new_one->dwCompReadAttrLen,
|
|
&new_one->dwCompReadAttrOffset, FALSE);
|
|
|
|
current_offset = updateField(lpcs->dwCompReadClauseLen,
|
|
lpcs->dwCompReadClauseOffset,
|
|
current_offset, newdata, olddata,
|
|
&new_one->dwCompReadClauseLen,
|
|
&new_one->dwCompReadClauseOffset, FALSE);
|
|
|
|
current_offset = updateField(lpcs->dwCompReadStrLen,
|
|
lpcs->dwCompReadStrOffset,
|
|
current_offset, newdata, olddata,
|
|
&new_one->dwCompReadStrLen,
|
|
&new_one->dwCompReadStrOffset, TRUE);
|
|
|
|
/* new CompAttr, CompClause, CompStr, dwCursorPos */
|
|
new_one->dwDeltaStart = 0;
|
|
|
|
current_offset = updateField(lpcs->dwResultReadClauseLen,
|
|
lpcs->dwResultReadClauseOffset,
|
|
current_offset, newdata, olddata,
|
|
&new_one->dwResultReadClauseLen,
|
|
&new_one->dwResultReadClauseOffset, FALSE);
|
|
|
|
current_offset = updateField(lpcs->dwResultReadStrLen,
|
|
lpcs->dwResultReadStrOffset,
|
|
current_offset, newdata, olddata,
|
|
&new_one->dwResultReadStrLen,
|
|
&new_one->dwResultReadStrOffset, TRUE);
|
|
|
|
current_offset = updateField(lpcs->dwResultClauseLen,
|
|
lpcs->dwResultClauseOffset,
|
|
current_offset, newdata, olddata,
|
|
&new_one->dwResultClauseLen,
|
|
&new_one->dwResultClauseOffset, FALSE);
|
|
|
|
current_offset = updateField(lpcs->dwResultStrLen,
|
|
lpcs->dwResultStrOffset,
|
|
current_offset, newdata, olddata,
|
|
&new_one->dwResultStrLen,
|
|
&new_one->dwResultStrOffset, TRUE);
|
|
|
|
current_offset = updateField(lpcs->dwPrivateSize,
|
|
lpcs->dwPrivateOffset,
|
|
current_offset, newdata, olddata,
|
|
&new_one->dwPrivateSize,
|
|
&new_one->dwPrivateOffset, FALSE);
|
|
}
|
|
|
|
/* set new data */
|
|
/* CompAttr */
|
|
new_one->dwCompAttrLen = len;
|
|
if (len > 0)
|
|
{
|
|
new_one->dwCompAttrOffset = current_offset;
|
|
memset(&newdata[current_offset],ATTR_INPUT,len);
|
|
current_offset += len;
|
|
}
|
|
|
|
/* CompClause */
|
|
if (len > 0)
|
|
{
|
|
new_one->dwCompClauseLen = sizeof(DWORD) * 2;
|
|
new_one->dwCompClauseOffset = current_offset;
|
|
*(DWORD*)(&newdata[current_offset]) = 0;
|
|
current_offset += sizeof(DWORD);
|
|
*(DWORD*)(&newdata[current_offset]) = len;
|
|
current_offset += sizeof(DWORD);
|
|
}
|
|
|
|
/* CompStr */
|
|
new_one->dwCompStrLen = len;
|
|
if (len > 0)
|
|
{
|
|
new_one->dwCompStrOffset = current_offset;
|
|
memcpy(&newdata[current_offset],compstr,len*sizeof(WCHAR));
|
|
}
|
|
|
|
/* CursorPos */
|
|
new_one->dwCursorPos = len;
|
|
|
|
ImmUnlockIMCC(rc);
|
|
if (lpcs)
|
|
ImmUnlockIMCC(old);
|
|
|
|
return rc;
|
|
}
|
|
|
|
static HIMCC updateResultStr(HIMCC old, LPWSTR resultstr, DWORD len)
|
|
{
|
|
/* we need to make sure the ResultStr and ResultClause fields are all
|
|
* set and correct */
|
|
int needed_size;
|
|
HIMCC rc;
|
|
LPBYTE newdata = NULL;
|
|
LPBYTE olddata = NULL;
|
|
LPCOMPOSITIONSTRING new_one;
|
|
LPCOMPOSITIONSTRING lpcs = NULL;
|
|
INT current_offset = 0;
|
|
|
|
TRACE("%s, %i\n",debugstr_wn(resultstr,len),len);
|
|
|
|
if (old == NULL && resultstr == NULL && len == 0)
|
|
return NULL;
|
|
|
|
if (old != NULL)
|
|
{
|
|
olddata = ImmLockIMCC(old);
|
|
lpcs = (LPCOMPOSITIONSTRING)olddata;
|
|
}
|
|
|
|
needed_size = sizeof(COMPOSITIONSTRING) + len * sizeof(WCHAR) +
|
|
sizeof(DWORD) * 2;
|
|
|
|
if (lpcs != NULL)
|
|
{
|
|
needed_size += lpcs->dwCompReadAttrLen;
|
|
needed_size += lpcs->dwCompReadClauseLen;
|
|
needed_size += lpcs->dwCompReadStrLen * sizeof(DWORD);
|
|
needed_size += lpcs->dwCompAttrLen;
|
|
needed_size += lpcs->dwCompClauseLen;
|
|
needed_size += lpcs->dwCompStrLen * sizeof(DWORD);
|
|
needed_size += lpcs->dwResultReadClauseLen;
|
|
needed_size += lpcs->dwResultReadStrLen * sizeof(DWORD);
|
|
needed_size += lpcs->dwPrivateSize;
|
|
}
|
|
rc = ImmCreateIMCC(needed_size);
|
|
newdata = ImmLockIMCC(rc);
|
|
new_one = (LPCOMPOSITIONSTRING)newdata;
|
|
|
|
new_one->dwSize = needed_size;
|
|
current_offset = sizeof(COMPOSITIONSTRING);
|
|
if (lpcs != NULL)
|
|
{
|
|
current_offset = updateField(lpcs->dwCompReadAttrLen,
|
|
lpcs->dwCompReadAttrOffset,
|
|
current_offset, newdata, olddata,
|
|
&new_one->dwCompReadAttrLen,
|
|
&new_one->dwCompReadAttrOffset, FALSE);
|
|
|
|
current_offset = updateField(lpcs->dwCompReadClauseLen,
|
|
lpcs->dwCompReadClauseOffset,
|
|
current_offset, newdata, olddata,
|
|
&new_one->dwCompReadClauseLen,
|
|
&new_one->dwCompReadClauseOffset, FALSE);
|
|
|
|
current_offset = updateField(lpcs->dwCompReadStrLen,
|
|
lpcs->dwCompReadStrOffset,
|
|
current_offset, newdata, olddata,
|
|
&new_one->dwCompReadStrLen,
|
|
&new_one->dwCompReadStrOffset, TRUE);
|
|
|
|
current_offset = updateField(lpcs->dwCompAttrLen,
|
|
lpcs->dwCompAttrOffset,
|
|
current_offset, newdata, olddata,
|
|
&new_one->dwCompAttrLen,
|
|
&new_one->dwCompAttrOffset, FALSE);
|
|
|
|
current_offset = updateField(lpcs->dwCompClauseLen,
|
|
lpcs->dwCompClauseOffset,
|
|
current_offset, newdata, olddata,
|
|
&new_one->dwCompClauseLen,
|
|
&new_one->dwCompClauseOffset, FALSE);
|
|
|
|
current_offset = updateField(lpcs->dwCompStrLen,
|
|
lpcs->dwCompStrOffset,
|
|
current_offset, newdata, olddata,
|
|
&new_one->dwCompStrLen,
|
|
&new_one->dwCompStrOffset, TRUE);
|
|
|
|
new_one->dwCursorPos = lpcs->dwCursorPos;
|
|
new_one->dwDeltaStart = 0;
|
|
|
|
current_offset = updateField(lpcs->dwResultReadClauseLen,
|
|
lpcs->dwResultReadClauseOffset,
|
|
current_offset, newdata, olddata,
|
|
&new_one->dwResultReadClauseLen,
|
|
&new_one->dwResultReadClauseOffset, FALSE);
|
|
|
|
current_offset = updateField(lpcs->dwResultReadStrLen,
|
|
lpcs->dwResultReadStrOffset,
|
|
current_offset, newdata, olddata,
|
|
&new_one->dwResultReadStrLen,
|
|
&new_one->dwResultReadStrOffset, TRUE);
|
|
|
|
/* new ResultClause , ResultStr */
|
|
|
|
current_offset = updateField(lpcs->dwPrivateSize,
|
|
lpcs->dwPrivateOffset,
|
|
current_offset, newdata, olddata,
|
|
&new_one->dwPrivateSize,
|
|
&new_one->dwPrivateOffset, FALSE);
|
|
}
|
|
|
|
/* set new data */
|
|
/* ResultClause */
|
|
if (len > 0)
|
|
{
|
|
new_one->dwResultClauseLen = sizeof(DWORD) * 2;
|
|
new_one->dwResultClauseOffset = current_offset;
|
|
*(DWORD*)(&newdata[current_offset]) = 0;
|
|
current_offset += sizeof(DWORD);
|
|
*(DWORD*)(&newdata[current_offset]) = len;
|
|
current_offset += sizeof(DWORD);
|
|
}
|
|
|
|
/* ResultStr */
|
|
new_one->dwResultStrLen = len;
|
|
if (len > 0)
|
|
{
|
|
new_one->dwResultStrOffset = current_offset;
|
|
memcpy(&newdata[current_offset],resultstr,len*sizeof(WCHAR));
|
|
}
|
|
ImmUnlockIMCC(rc);
|
|
if (lpcs)
|
|
ImmUnlockIMCC(old);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
* ImmAssociateContext (IMM32.@)
|
|
*/
|
|
HIMC WINAPI ImmAssociateContext(HWND hWnd, HIMC hIMC)
|
|
{
|
|
HIMC old = NULL;
|
|
InputContextData *data = (InputContextData*)hIMC;
|
|
|
|
TRACE("(%p, %p):\n", hWnd, hIMC);
|
|
|
|
/*
|
|
* WINE SPECIFIC! MAY CONFLICT
|
|
* associate the root context we have an XIM created
|
|
*/
|
|
if (hWnd == 0x000)
|
|
{
|
|
root_context = (InputContextData*)hIMC;
|
|
}
|
|
|
|
/*
|
|
* If already associated just return
|
|
*/
|
|
if (hIMC && data->IMC.hWnd == hWnd)
|
|
return hIMC;
|
|
|
|
if (hWnd)
|
|
{
|
|
old = (HIMC)RemovePropW(hWnd,szwWineIMCProperty);
|
|
|
|
if (old == NULL)
|
|
old = (HIMC)root_context;
|
|
else if (old == (HIMC)-1)
|
|
old = NULL;
|
|
|
|
if (hIMC != (HIMC)root_context)
|
|
{
|
|
if (hIMC == NULL) /* Meaning disable imm for that window*/
|
|
SetPropW(hWnd,szwWineIMCProperty,(HANDLE)-1);
|
|
else
|
|
SetPropW(hWnd,szwWineIMCProperty,(HANDLE)hIMC);
|
|
}
|
|
}
|
|
|
|
if (!hIMC)
|
|
return old;
|
|
|
|
if (IsWindow(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
|
|
*/
|
|
SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, TRUE, ISC_SHOWUIALL);
|
|
}
|
|
|
|
return old;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmAssociateContextEx (IMM32.@)
|
|
*/
|
|
BOOL WINAPI ImmAssociateContextEx(HWND hWnd, HIMC hIMC, DWORD dwFlags)
|
|
{
|
|
FIXME("(%p, %p, %d): stub\n", hWnd, hIMC, dwFlags);
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return FALSE;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmConfigureIMEA (IMM32.@)
|
|
*/
|
|
BOOL WINAPI ImmConfigureIMEA(
|
|
HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
|
|
{
|
|
FIXME("(%p, %p, %d, %p): stub\n",
|
|
hKL, hWnd, dwMode, lpData
|
|
);
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return FALSE;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmConfigureIMEW (IMM32.@)
|
|
*/
|
|
BOOL WINAPI ImmConfigureIMEW(
|
|
HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
|
|
{
|
|
FIXME("(%p, %p, %d, %p): stub\n",
|
|
hKL, hWnd, dwMode, lpData
|
|
);
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return FALSE;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmCreateContext (IMM32.@)
|
|
*/
|
|
HIMC WINAPI ImmCreateContext(void)
|
|
{
|
|
InputContextData *new_context;
|
|
|
|
new_context = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(InputContextData));
|
|
|
|
/* Load the IME */
|
|
new_context->immKbd = IMM_GetImmHkl(GetKeyboardLayout(0));
|
|
|
|
/*
|
|
* Once we depend on the IME for all the processing like we should
|
|
* these will become hard errors and result in creation failures
|
|
*/
|
|
if (!new_context->immKbd->hIME)
|
|
TRACE("IME dll could not be loaded\n");
|
|
|
|
/* hCompStr is never NULL */
|
|
new_context->IMC.hCompStr = ImmCreateBlankCompStr();
|
|
new_context->IMC.hMsgBuf = ImmCreateIMCC(1);
|
|
|
|
/* Initialize the IME Private */
|
|
new_context->IMC.hPrivate = ImmCreateIMCC(new_context->immKbd->imeInfo.dwPrivateDataSize);
|
|
|
|
if (new_context->immKbd->hIME &&
|
|
!new_context->immKbd->pImeSelect(new_context, TRUE))
|
|
{
|
|
TRACE("Selection of IME failed\n");
|
|
ImmDestroyContext(new_context);
|
|
return 0;
|
|
}
|
|
|
|
new_context->immKbd->uSelected++;
|
|
TRACE("Created context 0x%x\n",(UINT)new_context);
|
|
|
|
return (HIMC)new_context;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmDestroyContext (IMM32.@)
|
|
*/
|
|
BOOL WINAPI ImmDestroyContext(HIMC hIMC)
|
|
{
|
|
InputContextData *data = (InputContextData*)hIMC;
|
|
|
|
TRACE("Destroying %p\n",hIMC);
|
|
|
|
if (hIMC)
|
|
{
|
|
data->immKbd->uSelected --;
|
|
if (data->immKbd->hIME)
|
|
data->immKbd->pImeSelect(hIMC, FALSE);
|
|
|
|
ImmDestroyIMCC(data->IMC.hCompStr);
|
|
ImmDestroyIMCC(data->IMC.hCandInfo);
|
|
ImmDestroyIMCC(data->IMC.hGuideLine);
|
|
ImmDestroyIMCC(data->IMC.hPrivate);
|
|
ImmDestroyIMCC(data->IMC.hMsgBuf);
|
|
|
|
if (data->textfont)
|
|
{
|
|
DeleteObject(data->textfont);
|
|
data->textfont = NULL;
|
|
}
|
|
|
|
HeapFree(GetProcessHeap(),0,data);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmDisableIME (IMM32.@)
|
|
*/
|
|
BOOL WINAPI ImmDisableIME(DWORD idThread)
|
|
{
|
|
FIXME("(%d): stub\n", idThread);
|
|
return TRUE;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmEnumRegisterWordA (IMM32.@)
|
|
*/
|
|
UINT WINAPI ImmEnumRegisterWordA(
|
|
HKL hKL, REGISTERWORDENUMPROCA lpfnEnumProc,
|
|
LPCSTR lpszReading, DWORD dwStyle,
|
|
LPCSTR lpszRegister, LPVOID lpData)
|
|
{
|
|
FIXME("(%p, %p, %s, %d, %s, %p): stub\n",
|
|
hKL, lpfnEnumProc,
|
|
debugstr_a(lpszReading), dwStyle,
|
|
debugstr_a(lpszRegister), lpData
|
|
);
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmEnumRegisterWordW (IMM32.@)
|
|
*/
|
|
UINT WINAPI ImmEnumRegisterWordW(
|
|
HKL hKL, REGISTERWORDENUMPROCW lpfnEnumProc,
|
|
LPCWSTR lpszReading, DWORD dwStyle,
|
|
LPCWSTR lpszRegister, LPVOID lpData)
|
|
{
|
|
FIXME("(%p, %p, %s, %d, %s, %p): stub\n",
|
|
hKL, lpfnEnumProc,
|
|
debugstr_w(lpszReading), dwStyle,
|
|
debugstr_w(lpszRegister), lpData
|
|
);
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmEscapeA (IMM32.@)
|
|
*/
|
|
LRESULT WINAPI ImmEscapeA(
|
|
HKL hKL, HIMC hIMC,
|
|
UINT uEscape, LPVOID lpData)
|
|
{
|
|
FIXME("(%p, %p, %d, %p): stub\n",
|
|
hKL, hIMC, uEscape, lpData
|
|
);
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmEscapeW (IMM32.@)
|
|
*/
|
|
LRESULT WINAPI ImmEscapeW(
|
|
HKL hKL, HIMC hIMC,
|
|
UINT uEscape, LPVOID lpData)
|
|
{
|
|
FIXME("(%p, %p, %d, %p): stub\n",
|
|
hKL, hIMC, uEscape, lpData
|
|
);
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmGetCandidateListA (IMM32.@)
|
|
*/
|
|
DWORD WINAPI ImmGetCandidateListA(
|
|
HIMC hIMC, DWORD deIndex,
|
|
LPCANDIDATELIST lpCandList, DWORD dwBufLen)
|
|
{
|
|
FIXME("(%p, %d, %p, %d): stub\n",
|
|
hIMC, deIndex,
|
|
lpCandList, dwBufLen
|
|
);
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmGetCandidateListCountA (IMM32.@)
|
|
*/
|
|
DWORD WINAPI ImmGetCandidateListCountA(
|
|
HIMC hIMC, LPDWORD lpdwListCount)
|
|
{
|
|
FIXME("(%p, %p): stub\n", hIMC, lpdwListCount);
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmGetCandidateListCountW (IMM32.@)
|
|
*/
|
|
DWORD WINAPI ImmGetCandidateListCountW(
|
|
HIMC hIMC, LPDWORD lpdwListCount)
|
|
{
|
|
FIXME("(%p, %p): stub\n", hIMC, lpdwListCount);
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmGetCandidateListW (IMM32.@)
|
|
*/
|
|
DWORD WINAPI ImmGetCandidateListW(
|
|
HIMC hIMC, DWORD deIndex,
|
|
LPCANDIDATELIST lpCandList, DWORD dwBufLen)
|
|
{
|
|
FIXME("(%p, %d, %p, %d): stub\n",
|
|
hIMC, deIndex,
|
|
lpCandList, dwBufLen
|
|
);
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmGetCandidateWindow (IMM32.@)
|
|
*/
|
|
BOOL WINAPI ImmGetCandidateWindow(
|
|
HIMC hIMC, DWORD dwBufLen, LPCANDIDATEFORM lpCandidate)
|
|
{
|
|
FIXME("(%p, %d, %p): stub\n", hIMC, dwBufLen, lpCandidate);
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return FALSE;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmGetCompositionFontA (IMM32.@)
|
|
*/
|
|
BOOL WINAPI ImmGetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
|
|
{
|
|
LOGFONTW lfW;
|
|
BOOL rc;
|
|
|
|
TRACE("(%p, %p):\n", hIMC, lplf);
|
|
|
|
rc = ImmGetCompositionFontW(hIMC,&lfW);
|
|
if (rc)
|
|
{
|
|
memcpy(lplf,&lfW,sizeof(LOGFONTA));
|
|
WideCharToMultiByte(CP_ACP, 0, lfW.lfFaceName, -1, lplf->lfFaceName,
|
|
LF_FACESIZE, NULL, NULL);
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmGetCompositionFontW (IMM32.@)
|
|
*/
|
|
BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
|
|
{
|
|
InputContextData *data = (InputContextData*)hIMC;
|
|
|
|
TRACE("(%p, %p):\n", hIMC, lplf);
|
|
|
|
if (!data)
|
|
return FALSE;
|
|
|
|
*lplf = data->IMC.lfFont.W;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmGetCompositionStringA (IMM32.@)
|
|
*/
|
|
LONG WINAPI ImmGetCompositionStringA(
|
|
HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
|
|
{
|
|
CHAR *buf;
|
|
LONG rc = 0;
|
|
InputContextData *data = (InputContextData*)hIMC;
|
|
LPCOMPOSITIONSTRING compstr;
|
|
LPBYTE compdata;
|
|
|
|
TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen);
|
|
|
|
if (!data)
|
|
return FALSE;
|
|
|
|
if (!data->IMC.hCompStr)
|
|
return FALSE;
|
|
|
|
compdata = ImmLockIMCC(data->IMC.hCompStr);
|
|
compstr = (LPCOMPOSITIONSTRING)compdata;
|
|
|
|
if (dwIndex == GCS_RESULTSTR && compstr->dwResultStrLen > 0 &&
|
|
compstr->dwResultStrOffset > 0)
|
|
{
|
|
LPWSTR ResultStr = (LPWSTR)(compdata + compstr->dwResultStrOffset);
|
|
|
|
TRACE("GSC_RESULTSTR %p %i\n",ResultStr,
|
|
compstr->dwResultStrLen);
|
|
|
|
buf = HeapAlloc( GetProcessHeap(), 0, compstr->dwResultStrLen * 3 );
|
|
rc = WideCharToMultiByte(CP_ACP, 0, ResultStr,
|
|
compstr->dwResultStrLen , buf,
|
|
compstr->dwResultStrLen * 3, NULL, NULL);
|
|
if (dwBufLen >= rc)
|
|
memcpy(lpBuf,buf,rc);
|
|
|
|
data->bRead = TRUE;
|
|
HeapFree( GetProcessHeap(), 0, buf );
|
|
}
|
|
else if (dwIndex == GCS_COMPSTR && compstr->dwCompStrLen > 0 &&
|
|
compstr->dwCompStrOffset > 0)
|
|
{
|
|
LPWSTR CompString = (LPWSTR)(compdata + compstr->dwCompStrOffset);
|
|
|
|
TRACE("GSC_COMPSTR %p %i\n", CompString, compstr->dwCompStrLen);
|
|
|
|
buf = HeapAlloc( GetProcessHeap(), 0, compstr->dwCompStrLen * 3 );
|
|
rc = WideCharToMultiByte(CP_ACP, 0, CompString,
|
|
compstr->dwCompStrLen, buf,
|
|
compstr->dwCompStrLen * 3, NULL, NULL);
|
|
if (dwBufLen >= rc)
|
|
memcpy(lpBuf,buf,rc);
|
|
HeapFree( GetProcessHeap(), 0, buf );
|
|
}
|
|
else if (dwIndex == GCS_COMPATTR && compstr->dwCompAttrLen > 0 &&
|
|
compstr->dwCompAttrOffset > 0)
|
|
{
|
|
LPWSTR Compattr = (LPWSTR)(compdata + compstr->dwCompAttrOffset);
|
|
TRACE("GSC_COMPATTR %p %i\n", Compattr , compstr->dwCompAttrLen);
|
|
|
|
rc = compstr->dwCompAttrLen;
|
|
if (dwBufLen >= rc)
|
|
memcpy(lpBuf,Compattr,rc);
|
|
}
|
|
else if (dwIndex == GCS_COMPCLAUSE && compstr->dwCompClauseLen > 0 &&
|
|
compstr->dwCompClauseOffset > 0)
|
|
{
|
|
LPWSTR Compclause = (LPWSTR)(compdata + compstr->dwCompClauseOffset);
|
|
TRACE("GSC_COMPCLAUSE %p %i\n", Compclause, compstr->dwCompClauseLen);
|
|
|
|
rc = compstr->dwCompClauseLen;
|
|
if (dwBufLen >= compstr->dwCompClauseLen)
|
|
memcpy(lpBuf,Compclause,rc);
|
|
}
|
|
else if (dwIndex == GCS_RESULTCLAUSE && compstr->dwResultClauseLen > 0 &&
|
|
compstr->dwResultClauseOffset > 0)
|
|
{
|
|
LPWSTR Resultclause = (LPWSTR)(compdata + compstr->dwResultClauseOffset);
|
|
TRACE("GSC_RESULTCLAUSE %p %i\n", Resultclause, compstr->dwResultClauseLen);
|
|
|
|
rc = compstr->dwResultClauseLen;
|
|
if (dwBufLen >= compstr->dwResultClauseLen)
|
|
memcpy(lpBuf,Resultclause,rc);
|
|
}
|
|
else if (dwIndex == GCS_CURSORPOS)
|
|
{
|
|
TRACE("GSC_CURSORPOS\n");
|
|
rc = compstr->dwCursorPos;
|
|
}
|
|
else if (dwIndex == GCS_DELTASTART)
|
|
{
|
|
TRACE("GCS_DELTASTART\n");
|
|
rc = compstr->dwDeltaStart;
|
|
}
|
|
else
|
|
{
|
|
FIXME("Unhandled index 0x%x\n",dwIndex);
|
|
}
|
|
|
|
ImmUnlockIMCC(data->IMC.hCompStr);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmGetCompositionStringW (IMM32.@)
|
|
*/
|
|
LONG WINAPI ImmGetCompositionStringW(
|
|
HIMC hIMC, DWORD dwIndex,
|
|
LPVOID lpBuf, DWORD dwBufLen)
|
|
{
|
|
LONG rc = 0;
|
|
InputContextData *data = (InputContextData*)hIMC;
|
|
LPCOMPOSITIONSTRING compstr;
|
|
LPBYTE compdata;
|
|
|
|
TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen);
|
|
|
|
if (!data)
|
|
return FALSE;
|
|
|
|
if (!data->IMC.hCompStr)
|
|
return FALSE;
|
|
|
|
compdata = ImmLockIMCC(data->IMC.hCompStr);
|
|
compstr = (LPCOMPOSITIONSTRING)compdata;
|
|
|
|
if (dwIndex == GCS_RESULTSTR && compstr->dwResultStrLen > 0 &&
|
|
compstr->dwResultStrOffset > 0)
|
|
{
|
|
LPWSTR ResultStr = (LPWSTR)(compdata + compstr->dwResultStrOffset);
|
|
data->bRead = TRUE;
|
|
rc = compstr->dwResultStrLen * sizeof(WCHAR);
|
|
|
|
if (dwBufLen >= rc)
|
|
memcpy(lpBuf,ResultStr,rc);
|
|
}
|
|
else if (dwIndex == GCS_RESULTREADSTR && compstr->dwResultReadStrLen > 0 &&
|
|
compstr->dwResultReadStrOffset > 0)
|
|
{
|
|
LPWSTR ResultReadString = (LPWSTR)(compdata + compstr->dwResultReadStrOffset);
|
|
|
|
rc = compstr->dwResultReadStrLen * sizeof(WCHAR);
|
|
if (dwBufLen >= rc)
|
|
memcpy(lpBuf,ResultReadString,rc);
|
|
}
|
|
else if (dwIndex == GCS_COMPSTR && compstr->dwCompStrLen > 0 &&
|
|
compstr->dwCompStrOffset > 0)
|
|
{
|
|
LPWSTR CompString = (LPWSTR)(compdata + compstr->dwCompStrOffset);
|
|
rc = compstr->dwCompStrLen * sizeof(WCHAR);
|
|
if (dwBufLen >= rc)
|
|
memcpy(lpBuf,CompString,rc);
|
|
}
|
|
else if (dwIndex == GCS_COMPATTR && compstr->dwCompAttrLen > 0 &&
|
|
compstr->dwCompAttrOffset > 0)
|
|
{
|
|
|
|
LPWSTR Compattr = (LPWSTR)(compdata + compstr->dwCompAttrOffset);
|
|
|
|
rc = compstr->dwCompAttrLen;
|
|
if (dwBufLen >= rc)
|
|
memcpy(lpBuf,Compattr,rc);
|
|
}
|
|
else if (dwIndex == GCS_COMPCLAUSE && compstr->dwCompClauseLen > 0 &&
|
|
compstr->dwCompClauseOffset > 0)
|
|
{
|
|
LPWSTR Compclause = (LPWSTR)(compdata + compstr->dwCompClauseOffset);
|
|
|
|
rc = compstr->dwCompClauseLen;
|
|
if (dwBufLen >= compstr->dwCompClauseLen)
|
|
memcpy(lpBuf,Compclause,rc);
|
|
}
|
|
else if (dwIndex == GCS_COMPREADSTR && compstr->dwCompReadStrLen > 0 &&
|
|
compstr->dwCompReadStrOffset > 0)
|
|
{
|
|
LPWSTR CompReadString = (LPWSTR)(compdata + compstr->dwCompReadStrOffset);
|
|
|
|
rc = compstr->dwCompReadStrLen * sizeof(WCHAR);
|
|
|
|
if (dwBufLen >= rc)
|
|
memcpy(lpBuf,CompReadString,rc);
|
|
}
|
|
else if (dwIndex == GCS_CURSORPOS)
|
|
{
|
|
TRACE("GSC_CURSORPOS\n");
|
|
rc = compstr->dwCursorPos;
|
|
}
|
|
else if (dwIndex == GCS_DELTASTART)
|
|
{
|
|
TRACE("GCS_DELTASTART\n");
|
|
rc = compstr->dwDeltaStart;
|
|
}
|
|
else
|
|
{
|
|
FIXME("Unhandled index 0x%x\n",dwIndex);
|
|
}
|
|
|
|
ImmUnlockIMCC(data->IMC.hCompStr);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmGetCompositionWindow (IMM32.@)
|
|
*/
|
|
BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
|
|
{
|
|
InputContextData *data = (InputContextData*)hIMC;
|
|
|
|
TRACE("(%p, %p)\n", hIMC, lpCompForm);
|
|
|
|
if (!data)
|
|
return FALSE;
|
|
|
|
*lpCompForm = data->IMC.cfCompForm;
|
|
return 1;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmGetContext (IMM32.@)
|
|
*
|
|
*/
|
|
HIMC WINAPI ImmGetContext(HWND hWnd)
|
|
{
|
|
HIMC rc = NULL;
|
|
|
|
TRACE("%p\n", hWnd);
|
|
|
|
rc = (HIMC)GetPropW(hWnd,szwWineIMCProperty);
|
|
if (rc == (HIMC)-1)
|
|
rc = NULL;
|
|
else if (rc == NULL)
|
|
rc = (HIMC)root_context;
|
|
|
|
if (rc)
|
|
{
|
|
InputContextData *data = (InputContextData*)rc;
|
|
data->IMC.hWnd = hWnd;
|
|
}
|
|
TRACE("returning %p\n", rc);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmGetConversionListA (IMM32.@)
|
|
*/
|
|
DWORD WINAPI ImmGetConversionListA(
|
|
HKL hKL, HIMC hIMC,
|
|
LPCSTR pSrc, LPCANDIDATELIST lpDst,
|
|
DWORD dwBufLen, UINT uFlag)
|
|
{
|
|
FIXME("(%p, %p, %s, %p, %d, %d): stub\n",
|
|
hKL, hIMC, debugstr_a(pSrc), lpDst, dwBufLen, uFlag
|
|
);
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmGetConversionListW (IMM32.@)
|
|
*/
|
|
DWORD WINAPI ImmGetConversionListW(
|
|
HKL hKL, HIMC hIMC,
|
|
LPCWSTR pSrc, LPCANDIDATELIST lpDst,
|
|
DWORD dwBufLen, UINT uFlag)
|
|
{
|
|
FIXME("(%p, %p, %s, %p, %d, %d): stub\n",
|
|
hKL, hIMC, debugstr_w(pSrc), lpDst, dwBufLen, uFlag
|
|
);
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmGetConversionStatus (IMM32.@)
|
|
*/
|
|
BOOL WINAPI ImmGetConversionStatus(
|
|
HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence)
|
|
{
|
|
TRACE("(%p, %p, %p): best guess\n", hIMC, lpfdwConversion, lpfdwSentence);
|
|
if (lpfdwConversion)
|
|
*lpfdwConversion = IME_CMODE_NATIVE;
|
|
if (lpfdwSentence)
|
|
*lpfdwSentence = IME_SMODE_NONE;
|
|
return TRUE;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmGetDefaultIMEWnd (IMM32.@)
|
|
*/
|
|
HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
|
|
{
|
|
static int shown = 0;
|
|
|
|
if (!shown) {
|
|
FIXME("(%p - %p %p ): semi-stub\n", hWnd,hwndDefault, root_context);
|
|
shown = 1;
|
|
}
|
|
|
|
if (hwndDefault == NULL)
|
|
{
|
|
static const WCHAR the_name[] = {'I','M','E','\0'};
|
|
|
|
IMM_Register();
|
|
hwndDefault = CreateWindowExW( WS_EX_TOOLWINDOW, WC_IMECLASSNAME,
|
|
the_name, WS_POPUP, 0, 0, 1, 1, 0, 0,
|
|
hImeInst, 0);
|
|
|
|
TRACE("Default created (%p)\n",hwndDefault);
|
|
}
|
|
|
|
return hwndDefault;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmGetDescriptionA (IMM32.@)
|
|
*/
|
|
UINT WINAPI ImmGetDescriptionA(
|
|
HKL hKL, LPSTR lpszDescription, UINT uBufLen)
|
|
{
|
|
WCHAR *buf;
|
|
DWORD len;
|
|
|
|
TRACE("%p %p %d\n", hKL, lpszDescription, uBufLen);
|
|
|
|
/* find out how many characters in the unicode buffer */
|
|
len = ImmGetDescriptionW( hKL, NULL, 0 );
|
|
|
|
/* allocate a buffer of that size */
|
|
buf = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof (WCHAR) );
|
|
if( !buf )
|
|
return 0;
|
|
|
|
/* fetch the unicode buffer */
|
|
len = ImmGetDescriptionW( hKL, buf, len + 1 );
|
|
|
|
/* convert it back to ASCII */
|
|
len = WideCharToMultiByte( CP_ACP, 0, buf, len + 1,
|
|
lpszDescription, uBufLen, NULL, NULL );
|
|
|
|
HeapFree( GetProcessHeap(), 0, buf );
|
|
|
|
return len;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmGetDescriptionW (IMM32.@)
|
|
*/
|
|
UINT WINAPI ImmGetDescriptionW(HKL hKL, LPWSTR lpszDescription, UINT uBufLen)
|
|
{
|
|
static const WCHAR name[] = { 'W','i','n','e',' ','X','I','M',0 };
|
|
|
|
FIXME("(%p, %p, %d): semi stub\n", hKL, lpszDescription, uBufLen);
|
|
|
|
if (!uBufLen) return lstrlenW( name );
|
|
lstrcpynW( lpszDescription, name, uBufLen );
|
|
return lstrlenW( lpszDescription );
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmGetGuideLineA (IMM32.@)
|
|
*/
|
|
DWORD WINAPI ImmGetGuideLineA(
|
|
HIMC hIMC, DWORD dwIndex, LPSTR lpBuf, DWORD dwBufLen)
|
|
{
|
|
FIXME("(%p, %d, %s, %d): stub\n",
|
|
hIMC, dwIndex, debugstr_a(lpBuf), dwBufLen
|
|
);
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmGetGuideLineW (IMM32.@)
|
|
*/
|
|
DWORD WINAPI ImmGetGuideLineW(HIMC hIMC, DWORD dwIndex, LPWSTR lpBuf, DWORD dwBufLen)
|
|
{
|
|
FIXME("(%p, %d, %s, %d): stub\n",
|
|
hIMC, dwIndex, debugstr_w(lpBuf), dwBufLen
|
|
);
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmGetIMEFileNameA (IMM32.@)
|
|
*/
|
|
UINT WINAPI ImmGetIMEFileNameA( HKL hKL, LPSTR lpszFileName, UINT uBufLen)
|
|
{
|
|
LPWSTR bufW = NULL;
|
|
UINT wBufLen = uBufLen;
|
|
UINT rc;
|
|
|
|
if (uBufLen && lpszFileName)
|
|
bufW = HeapAlloc(GetProcessHeap(),0,uBufLen * sizeof(WCHAR));
|
|
else /* We need this to get the number of byte required */
|
|
{
|
|
bufW = HeapAlloc(GetProcessHeap(),0,MAX_PATH * sizeof(WCHAR));
|
|
wBufLen = MAX_PATH;
|
|
}
|
|
|
|
rc = ImmGetIMEFileNameW(hKL,bufW,wBufLen);
|
|
|
|
if (rc > 0)
|
|
{
|
|
if (uBufLen && lpszFileName)
|
|
rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, lpszFileName,
|
|
uBufLen, NULL, NULL);
|
|
else /* get the length */
|
|
rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL,
|
|
NULL);
|
|
}
|
|
|
|
HeapFree(GetProcessHeap(),0,bufW);
|
|
return rc;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmGetIMEFileNameW (IMM32.@)
|
|
*/
|
|
UINT WINAPI ImmGetIMEFileNameW(HKL hKL, LPWSTR lpszFileName, UINT uBufLen)
|
|
{
|
|
static const WCHAR szImeFileW[] = {'I','m','e',' ','F','i','l','e',0};
|
|
static const WCHAR fmt[] = {'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','x',0};
|
|
|
|
HKEY hkey;
|
|
DWORD length;
|
|
DWORD rc;
|
|
WCHAR regKey[sizeof(fmt)/sizeof(WCHAR)+8];
|
|
|
|
wsprintfW( regKey, fmt, (unsigned)hKL );
|
|
rc = RegOpenKeyW( HKEY_LOCAL_MACHINE, regKey, &hkey);
|
|
if (rc != ERROR_SUCCESS)
|
|
{
|
|
SetLastError(rc);
|
|
return 0;
|
|
}
|
|
|
|
length = 0;
|
|
rc = RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, NULL, &length);
|
|
|
|
if (rc != ERROR_SUCCESS)
|
|
{
|
|
RegCloseKey(hkey);
|
|
SetLastError(rc);
|
|
return 0;
|
|
}
|
|
if (length > uBufLen * sizeof(WCHAR) || !lpszFileName)
|
|
{
|
|
RegCloseKey(hkey);
|
|
if (lpszFileName)
|
|
{
|
|
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
|
return 0;
|
|
}
|
|
else
|
|
return length / sizeof(WCHAR);
|
|
}
|
|
|
|
RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, lpszFileName, &length);
|
|
|
|
RegCloseKey(hkey);
|
|
|
|
return length / sizeof(WCHAR);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmGetOpenStatus (IMM32.@)
|
|
*/
|
|
BOOL WINAPI ImmGetOpenStatus(HIMC hIMC)
|
|
{
|
|
InputContextData *data = (InputContextData*)hIMC;
|
|
|
|
if (!data)
|
|
return FALSE;
|
|
FIXME("(%p): semi-stub\n", hIMC);
|
|
|
|
return data->IMC.fOpen;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmGetProperty (IMM32.@)
|
|
*/
|
|
DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex)
|
|
{
|
|
DWORD rc = 0;
|
|
TRACE("(%p, %d)\n", hKL, fdwIndex);
|
|
|
|
switch (fdwIndex)
|
|
{
|
|
case IGP_PROPERTY:
|
|
TRACE("(%s)\n", "IGP_PROPERTY");
|
|
rc = IME_PROP_UNICODE | IME_PROP_AT_CARET;
|
|
break;
|
|
case IGP_CONVERSION:
|
|
FIXME("(%s)\n", "IGP_CONVERSION");
|
|
rc = IME_CMODE_NATIVE;
|
|
break;
|
|
case IGP_SENTENCE:
|
|
FIXME("%s)\n", "IGP_SENTENCE");
|
|
rc = IME_SMODE_AUTOMATIC;
|
|
break;
|
|
case IGP_SETCOMPSTR:
|
|
TRACE("(%s)\n", "IGP_SETCOMPSTR");
|
|
rc = 0;
|
|
break;
|
|
case IGP_SELECT:
|
|
TRACE("(%s)\n", "IGP_SELECT");
|
|
rc = SELECT_CAP_CONVERSION | SELECT_CAP_SENTENCE;
|
|
break;
|
|
case IGP_GETIMEVERSION:
|
|
TRACE("(%s)\n", "IGP_GETIMEVERSION");
|
|
rc = IMEVER_0400;
|
|
break;
|
|
case IGP_UI:
|
|
TRACE("(%s)\n", "IGP_UI");
|
|
rc = 0;
|
|
break;
|
|
default:
|
|
rc = 0;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmGetRegisterWordStyleA (IMM32.@)
|
|
*/
|
|
UINT WINAPI ImmGetRegisterWordStyleA(
|
|
HKL hKL, UINT nItem, LPSTYLEBUFA lpStyleBuf)
|
|
{
|
|
FIXME("(%p, %d, %p): stub\n", hKL, nItem, lpStyleBuf);
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmGetRegisterWordStyleW (IMM32.@)
|
|
*/
|
|
UINT WINAPI ImmGetRegisterWordStyleW(
|
|
HKL hKL, UINT nItem, LPSTYLEBUFW lpStyleBuf)
|
|
{
|
|
FIXME("(%p, %d, %p): stub\n", hKL, nItem, lpStyleBuf);
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmGetStatusWindowPos (IMM32.@)
|
|
*/
|
|
BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
|
|
{
|
|
FIXME("(%p, %p): stub\n", hIMC, lpptPos);
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return FALSE;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmGetVirtualKey (IMM32.@)
|
|
*/
|
|
UINT WINAPI ImmGetVirtualKey(HWND hWnd)
|
|
{
|
|
OSVERSIONINFOA version;
|
|
FIXME("(%p): stub\n", hWnd);
|
|
GetVersionExA( &version );
|
|
switch(version.dwPlatformId)
|
|
{
|
|
case VER_PLATFORM_WIN32_WINDOWS:
|
|
return VK_PROCESSKEY;
|
|
case VER_PLATFORM_WIN32_NT:
|
|
return 0;
|
|
default:
|
|
FIXME("%d not supported\n",version.dwPlatformId);
|
|
return VK_PROCESSKEY;
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmInstallIMEA (IMM32.@)
|
|
*/
|
|
HKL WINAPI ImmInstallIMEA(
|
|
LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText)
|
|
{
|
|
FIXME("(%s, %s): stub\n",
|
|
debugstr_a(lpszIMEFileName), debugstr_a(lpszLayoutText)
|
|
);
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return NULL;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmInstallIMEW (IMM32.@)
|
|
*/
|
|
HKL WINAPI ImmInstallIMEW(
|
|
LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText)
|
|
{
|
|
FIXME("(%s, %s): stub\n",
|
|
debugstr_w(lpszIMEFileName), debugstr_w(lpszLayoutText)
|
|
);
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return NULL;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmIsIME (IMM32.@)
|
|
*/
|
|
BOOL WINAPI ImmIsIME(HKL hKL)
|
|
{
|
|
TRACE("(%p): semi-stub\n", hKL);
|
|
/*
|
|
* FIXME: Dead key locales will return TRUE here when they should not
|
|
* There is probably a more proper way to check this.
|
|
*/
|
|
return (root_context != NULL);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmIsUIMessageA (IMM32.@)
|
|
*/
|
|
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_KEYUP) ||
|
|
(msg == WM_MSIME_SERVICE) ||
|
|
(msg == WM_MSIME_RECONVERTOPTIONS) ||
|
|
(msg == WM_MSIME_MOUSE) ||
|
|
(msg == WM_MSIME_RECONVERTREQUEST) ||
|
|
(msg == WM_MSIME_RECONVERT) ||
|
|
(msg == WM_MSIME_QUERYPOSITION) ||
|
|
(msg == WM_MSIME_DOCUMENTFEED))
|
|
|
|
{
|
|
if (!hwndDefault)
|
|
ImmGetDefaultIMEWnd(NULL);
|
|
|
|
if (hWndIME == NULL)
|
|
PostMessageA(hwndDefault, msg, wParam, lParam);
|
|
|
|
rc = TRUE;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmIsUIMessageW (IMM32.@)
|
|
*/
|
|
BOOL WINAPI ImmIsUIMessageW(
|
|
HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
BOOL rc = FALSE;
|
|
TRACE("(%p, %d, %ld, %ld): stub\n", hWndIME, msg, wParam, lParam);
|
|
if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
|
|
(msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP) ||
|
|
(msg == WM_MSIME_SERVICE) ||
|
|
(msg == WM_MSIME_RECONVERTOPTIONS) ||
|
|
(msg == WM_MSIME_MOUSE) ||
|
|
(msg == WM_MSIME_RECONVERTREQUEST) ||
|
|
(msg == WM_MSIME_RECONVERT) ||
|
|
(msg == WM_MSIME_QUERYPOSITION) ||
|
|
(msg == WM_MSIME_DOCUMENTFEED))
|
|
rc = TRUE;
|
|
return rc;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmNotifyIME (IMM32.@)
|
|
*/
|
|
BOOL WINAPI ImmNotifyIME(
|
|
HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
|
|
{
|
|
BOOL rc = FALSE;
|
|
|
|
TRACE("(%p, %d, %d, %d)\n",
|
|
hIMC, dwAction, dwIndex, dwValue);
|
|
|
|
if (!root_context)
|
|
return rc;
|
|
|
|
switch(dwAction)
|
|
{
|
|
case NI_CHANGECANDIDATELIST:
|
|
FIXME("%s\n","NI_CHANGECANDIDATELIST");
|
|
break;
|
|
case NI_CLOSECANDIDATE:
|
|
FIXME("%s\n","NI_CLOSECANDIDATE");
|
|
break;
|
|
case NI_COMPOSITIONSTR:
|
|
switch (dwIndex)
|
|
{
|
|
case CPS_CANCEL:
|
|
TRACE("%s - %s\n","NI_COMPOSITIONSTR","CPS_CANCEL");
|
|
{
|
|
BOOL send;
|
|
LPCOMPOSITIONSTRING lpCompStr;
|
|
|
|
if (pX11DRV_ForceXIMReset)
|
|
pX11DRV_ForceXIMReset(root_context->IMC.hWnd);
|
|
|
|
lpCompStr = ImmLockIMCC(root_context->IMC.hCompStr);
|
|
send = (lpCompStr->dwCompStrLen != 0);
|
|
ImmUnlockIMCC(root_context->IMC.hCompStr);
|
|
|
|
ImmDestroyIMCC(root_context->IMC.hCompStr);
|
|
root_context->IMC.hCompStr = ImmCreateBlankCompStr();
|
|
|
|
if (send)
|
|
ImmInternalPostIMEMessage(root_context, WM_IME_COMPOSITION, 0,
|
|
GCS_COMPSTR);
|
|
rc = TRUE;
|
|
}
|
|
break;
|
|
case CPS_COMPLETE:
|
|
TRACE("%s - %s\n","NI_COMPOSITIONSTR","CPS_COMPLETE");
|
|
if (hIMC != (HIMC)FROM_IME && pX11DRV_ForceXIMReset)
|
|
pX11DRV_ForceXIMReset(root_context->IMC.hWnd);
|
|
{
|
|
HIMCC newCompStr;
|
|
DWORD cplen = 0;
|
|
LPWSTR cpstr;
|
|
LPCOMPOSITIONSTRING cs = NULL;
|
|
LPBYTE cdata = NULL;
|
|
|
|
/* clear existing result */
|
|
newCompStr = updateResultStr(root_context->IMC.hCompStr, NULL, 0);
|
|
ImmDestroyIMCC(root_context->IMC.hCompStr);
|
|
root_context->IMC.hCompStr = newCompStr;
|
|
|
|
if (root_context->IMC.hCompStr)
|
|
{
|
|
cdata = ImmLockIMCC(root_context->IMC.hCompStr);
|
|
cs = (LPCOMPOSITIONSTRING)cdata;
|
|
cplen = cs->dwCompStrLen;
|
|
cpstr = (LPWSTR)&(cdata[cs->dwCompStrOffset]);
|
|
ImmUnlockIMCC(root_context->IMC.hCompStr);
|
|
}
|
|
if (cplen > 0)
|
|
{
|
|
WCHAR param = cpstr[0];
|
|
newCompStr = updateResultStr(root_context->IMC.hCompStr, cpstr, cplen);
|
|
ImmDestroyIMCC(root_context->IMC.hCompStr);
|
|
root_context->IMC.hCompStr = newCompStr;
|
|
newCompStr = updateCompStr(root_context->IMC.hCompStr, NULL, 0);
|
|
ImmDestroyIMCC(root_context->IMC.hCompStr);
|
|
root_context->IMC.hCompStr = newCompStr;
|
|
|
|
root_context->bRead = FALSE;
|
|
|
|
ImmInternalPostIMEMessage(root_context, WM_IME_COMPOSITION, 0,
|
|
GCS_COMPSTR);
|
|
|
|
ImmInternalPostIMEMessage(root_context, WM_IME_COMPOSITION,
|
|
param,
|
|
GCS_RESULTSTR|GCS_RESULTCLAUSE);
|
|
}
|
|
|
|
ImmInternalPostIMEMessage(root_context, WM_IME_ENDCOMPOSITION, 0, 0);
|
|
root_context->bInComposition = FALSE;
|
|
}
|
|
break;
|
|
case CPS_CONVERT:
|
|
FIXME("%s - %s\n","NI_COMPOSITIONSTR","CPS_CONVERT");
|
|
break;
|
|
case CPS_REVERT:
|
|
FIXME("%s - %s\n","NI_COMPOSITIONSTR","CPS_REVERT");
|
|
break;
|
|
default:
|
|
ERR("%s - %s (%i)\n","NI_COMPOSITIONSTR","UNKNOWN",dwIndex);
|
|
break;
|
|
}
|
|
break;
|
|
case NI_IMEMENUSELECTED:
|
|
FIXME("%s\n", "NI_IMEMENUSELECTED");
|
|
break;
|
|
case NI_OPENCANDIDATE:
|
|
FIXME("%s\n", "NI_OPENCANDIDATE");
|
|
break;
|
|
case NI_SELECTCANDIDATESTR:
|
|
FIXME("%s\n", "NI_SELECTCANDIDATESTR");
|
|
break;
|
|
case NI_SETCANDIDATE_PAGESIZE:
|
|
FIXME("%s\n", "NI_SETCANDIDATE_PAGESIZE");
|
|
break;
|
|
case NI_SETCANDIDATE_PAGESTART:
|
|
FIXME("%s\n", "NI_SETCANDIDATE_PAGESTART");
|
|
break;
|
|
default:
|
|
ERR("Unknown\n");
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmRegisterWordA (IMM32.@)
|
|
*/
|
|
BOOL WINAPI ImmRegisterWordA(
|
|
HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszRegister)
|
|
{
|
|
FIXME("(%p, %s, %d, %s): stub\n",
|
|
hKL, debugstr_a(lpszReading), dwStyle, debugstr_a(lpszRegister)
|
|
);
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return FALSE;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmRegisterWordW (IMM32.@)
|
|
*/
|
|
BOOL WINAPI ImmRegisterWordW(
|
|
HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszRegister)
|
|
{
|
|
FIXME("(%p, %s, %d, %s): stub\n",
|
|
hKL, debugstr_w(lpszReading), dwStyle, debugstr_w(lpszRegister)
|
|
);
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return FALSE;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmReleaseContext (IMM32.@)
|
|
*/
|
|
BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC)
|
|
{
|
|
static int shown = 0;
|
|
|
|
if (!shown) {
|
|
FIXME("(%p, %p): stub\n", hWnd, hIMC);
|
|
shown = 1;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmSetCandidateWindow (IMM32.@)
|
|
*/
|
|
BOOL WINAPI ImmSetCandidateWindow(
|
|
HIMC hIMC, LPCANDIDATEFORM lpCandidate)
|
|
{
|
|
FIXME("(%p, %p): stub\n", hIMC, lpCandidate);
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return FALSE;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmSetCompositionFontA (IMM32.@)
|
|
*/
|
|
BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
|
|
{
|
|
InputContextData *data = (InputContextData*)hIMC;
|
|
TRACE("(%p, %p)\n", hIMC, lplf);
|
|
|
|
if (!data)
|
|
return FALSE;
|
|
|
|
memcpy(&data->IMC.lfFont.W,lplf,sizeof(LOGFONTA));
|
|
MultiByteToWideChar(CP_ACP, 0, lplf->lfFaceName, -1, data->IMC.lfFont.W.lfFaceName,
|
|
LF_FACESIZE);
|
|
|
|
ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0);
|
|
|
|
if (data->textfont)
|
|
{
|
|
DeleteObject(data->textfont);
|
|
data->textfont = NULL;
|
|
}
|
|
|
|
data->textfont = CreateFontIndirectW(&data->IMC.lfFont.W);
|
|
return TRUE;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmSetCompositionFontW (IMM32.@)
|
|
*/
|
|
BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
|
|
{
|
|
InputContextData *data = (InputContextData*)hIMC;
|
|
TRACE("(%p, %p)\n", hIMC, lplf);
|
|
|
|
if (!data)
|
|
return FALSE;
|
|
|
|
data->IMC.lfFont.W = *lplf;
|
|
ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0);
|
|
|
|
if (data->textfont)
|
|
{
|
|
DeleteObject(data->textfont);
|
|
data->textfont = NULL;
|
|
}
|
|
data->textfont = CreateFontIndirectW(&data->IMC.lfFont.W);
|
|
return TRUE;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmSetCompositionStringA (IMM32.@)
|
|
*/
|
|
BOOL WINAPI ImmSetCompositionStringA(
|
|
HIMC hIMC, DWORD dwIndex,
|
|
LPCVOID lpComp, DWORD dwCompLen,
|
|
LPCVOID lpRead, DWORD dwReadLen)
|
|
{
|
|
DWORD comp_len;
|
|
DWORD read_len;
|
|
WCHAR *CompBuffer = NULL;
|
|
WCHAR *ReadBuffer = NULL;
|
|
BOOL rc;
|
|
|
|
TRACE("(%p, %d, %p, %d, %p, %d): stub\n",
|
|
hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
|
|
|
|
comp_len = MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, NULL, 0);
|
|
if (comp_len)
|
|
{
|
|
CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len * sizeof(WCHAR));
|
|
MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len);
|
|
}
|
|
|
|
read_len = MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, NULL, 0);
|
|
if (read_len)
|
|
{
|
|
ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len * sizeof(WCHAR));
|
|
MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len);
|
|
}
|
|
|
|
rc = ImmSetCompositionStringW(hIMC, dwIndex, CompBuffer, comp_len,
|
|
ReadBuffer, read_len);
|
|
|
|
HeapFree(GetProcessHeap(), 0, CompBuffer);
|
|
HeapFree(GetProcessHeap(), 0, ReadBuffer);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmSetCompositionStringW (IMM32.@)
|
|
*/
|
|
BOOL WINAPI ImmSetCompositionStringW(
|
|
HIMC hIMC, DWORD dwIndex,
|
|
LPCVOID lpComp, DWORD dwCompLen,
|
|
LPCVOID lpRead, DWORD dwReadLen)
|
|
{
|
|
DWORD flags = 0;
|
|
WCHAR wParam = 0;
|
|
|
|
TRACE("(%p, %d, %p, %d, %p, %d): stub\n",
|
|
hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
|
|
|
|
|
|
if (hIMC != (HIMC)FROM_IME)
|
|
FIXME("PROBLEM: This only sets the wine level string\n");
|
|
|
|
/*
|
|
* Explanation:
|
|
* this sets the composition string in the imm32.dll level
|
|
* of the composition buffer. we cannot manipulate the xim level
|
|
* buffer, which means that once the xim level buffer changes again
|
|
* any call to this function from the application will be lost
|
|
*/
|
|
|
|
if (lpRead && dwReadLen)
|
|
FIXME("Reading string unimplemented\n");
|
|
|
|
/*
|
|
* app operating this api to also receive the message from xim
|
|
*/
|
|
|
|
if (dwIndex == SCS_SETSTR)
|
|
{
|
|
HIMCC newCompStr;
|
|
if (!root_context->bInComposition)
|
|
{
|
|
ImmInternalPostIMEMessage(root_context, WM_IME_STARTCOMPOSITION, 0, 0);
|
|
root_context->bInComposition = TRUE;
|
|
}
|
|
|
|
flags = GCS_COMPSTR;
|
|
|
|
if (dwCompLen && lpComp)
|
|
{
|
|
newCompStr = updateCompStr(root_context->IMC.hCompStr, (LPWSTR)lpComp, dwCompLen / sizeof(WCHAR));
|
|
ImmDestroyIMCC(root_context->IMC.hCompStr);
|
|
root_context->IMC.hCompStr = newCompStr;
|
|
|
|
wParam = ((const WCHAR*)lpComp)[0];
|
|
flags |= GCS_COMPCLAUSE | GCS_COMPATTR | GCS_DELTASTART;
|
|
}
|
|
else
|
|
{
|
|
newCompStr = updateCompStr(root_context->IMC.hCompStr, NULL, 0);
|
|
ImmDestroyIMCC(root_context->IMC.hCompStr);
|
|
root_context->IMC.hCompStr = newCompStr;
|
|
}
|
|
}
|
|
|
|
UpdateDataInDefaultIMEWindow(hwndDefault,FALSE);
|
|
|
|
ImmInternalPostIMEMessage(root_context, WM_IME_COMPOSITION, wParam, flags);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmSetCompositionWindow (IMM32.@)
|
|
*/
|
|
BOOL WINAPI ImmSetCompositionWindow(
|
|
HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
|
|
{
|
|
BOOL reshow = FALSE;
|
|
InputContextData *data = (InputContextData*)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 (!data)
|
|
return FALSE;
|
|
|
|
data->IMC.cfCompForm = *lpCompForm;
|
|
|
|
if (IsWindowVisible(hwndDefault))
|
|
{
|
|
reshow = TRUE;
|
|
ShowWindow(hwndDefault,SW_HIDE);
|
|
}
|
|
|
|
/* FIXME: this is a partial stub */
|
|
|
|
if (reshow)
|
|
ShowWindow(hwndDefault,SW_SHOWNOACTIVATE);
|
|
|
|
ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONWINDOW, 0);
|
|
return TRUE;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmSetConversionStatus (IMM32.@)
|
|
*/
|
|
BOOL WINAPI ImmSetConversionStatus(
|
|
HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence)
|
|
{
|
|
static int shown = 0;
|
|
|
|
if (!shown) {
|
|
FIXME("(%p, %d, %d): stub\n",
|
|
hIMC, fdwConversion, fdwSentence
|
|
);
|
|
shown = 1;
|
|
}
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return FALSE;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmSetOpenStatus (IMM32.@)
|
|
*/
|
|
BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen)
|
|
{
|
|
InputContextData *data = (InputContextData*)hIMC;
|
|
|
|
TRACE("%p %d\n", hIMC, fOpen);
|
|
|
|
if (hIMC == (HIMC)FROM_IME)
|
|
{
|
|
ImmInternalSetOpenStatus(fOpen);
|
|
ImmInternalSendIMENotify(root_context, IMN_SETOPENSTATUS, 0);
|
|
return TRUE;
|
|
}
|
|
|
|
if (!data)
|
|
return FALSE;
|
|
|
|
if (fOpen != data->bInternalState)
|
|
{
|
|
if (fOpen == FALSE && pX11DRV_ForceXIMReset)
|
|
pX11DRV_ForceXIMReset(data->IMC.hWnd);
|
|
|
|
if (fOpen == FALSE)
|
|
ImmInternalPostIMEMessage(data, WM_IME_ENDCOMPOSITION,0,0);
|
|
else
|
|
ImmInternalPostIMEMessage(data, WM_IME_STARTCOMPOSITION,0,0);
|
|
|
|
ImmInternalSetOpenStatus(fOpen);
|
|
ImmInternalSetOpenStatus(!fOpen);
|
|
|
|
if (data->IMC.fOpen == FALSE)
|
|
ImmInternalPostIMEMessage(data, WM_IME_ENDCOMPOSITION,0,0);
|
|
else
|
|
ImmInternalPostIMEMessage(data, WM_IME_STARTCOMPOSITION,0,0);
|
|
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmSetStatusWindowPos (IMM32.@)
|
|
*/
|
|
BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
|
|
{
|
|
FIXME("(%p, %p): stub\n", hIMC, lpptPos);
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return FALSE;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmSimulateHotKey (IMM32.@)
|
|
*/
|
|
BOOL WINAPI ImmSimulateHotKey(HWND hWnd, DWORD dwHotKeyID)
|
|
{
|
|
FIXME("(%p, %d): stub\n", hWnd, dwHotKeyID);
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return FALSE;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmUnregisterWordA (IMM32.@)
|
|
*/
|
|
BOOL WINAPI ImmUnregisterWordA(
|
|
HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszUnregister)
|
|
{
|
|
FIXME("(%p, %s, %d, %s): stub\n",
|
|
hKL, debugstr_a(lpszReading), dwStyle, debugstr_a(lpszUnregister)
|
|
);
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return FALSE;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmUnregisterWordW (IMM32.@)
|
|
*/
|
|
BOOL WINAPI ImmUnregisterWordW(
|
|
HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszUnregister)
|
|
{
|
|
FIXME("(%p, %s, %d, %s): stub\n",
|
|
hKL, debugstr_w(lpszReading), dwStyle, debugstr_w(lpszUnregister)
|
|
);
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return FALSE;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmGetImeMenuItemsA (IMM32.@)
|
|
*/
|
|
DWORD WINAPI ImmGetImeMenuItemsA( HIMC hIMC, DWORD dwFlags, DWORD dwType,
|
|
LPIMEMENUITEMINFOA lpImeParentMenu, LPIMEMENUITEMINFOA lpImeMenu,
|
|
DWORD dwSize)
|
|
{
|
|
FIXME("(%p, %i, %i, %p, %p, %i): stub\n", hIMC, dwFlags, dwType,
|
|
lpImeParentMenu, lpImeMenu, dwSize);
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmGetImeMenuItemsW (IMM32.@)
|
|
*/
|
|
DWORD WINAPI ImmGetImeMenuItemsW( HIMC hIMC, DWORD dwFlags, DWORD dwType,
|
|
LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu,
|
|
DWORD dwSize)
|
|
{
|
|
FIXME("(%p, %i, %i, %p, %p, %i): stub\n", hIMC, dwFlags, dwType,
|
|
lpImeParentMenu, lpImeMenu, dwSize);
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmLockIMC(IMM32.@)
|
|
*/
|
|
LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC)
|
|
{
|
|
InputContextData *data = (InputContextData*)hIMC;
|
|
|
|
if (!data)
|
|
return NULL;
|
|
data->dwLock++;
|
|
return &data->IMC;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmUnlockIMC(IMM32.@)
|
|
*/
|
|
BOOL WINAPI ImmUnlockIMC(HIMC hIMC)
|
|
{
|
|
InputContextData *data = (InputContextData*)hIMC;
|
|
data->dwLock--;
|
|
return (data->dwLock!=0);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmGetIMCLockCount(IMM32.@)
|
|
*/
|
|
DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC)
|
|
{
|
|
InputContextData *data = (InputContextData*)hIMC;
|
|
return data->dwLock;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmCreateIMCC(IMM32.@)
|
|
*/
|
|
HIMCC WINAPI ImmCreateIMCC(DWORD size)
|
|
{
|
|
IMCCInternal *internal;
|
|
int real_size = size + sizeof(IMCCInternal);
|
|
|
|
internal = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, real_size);
|
|
if (internal == NULL)
|
|
return NULL;
|
|
|
|
internal->dwSize = size;
|
|
return (HIMCC)internal;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmDestroyIMCC(IMM32.@)
|
|
*/
|
|
HIMCC WINAPI ImmDestroyIMCC(HIMCC block)
|
|
{
|
|
HeapFree(GetProcessHeap(),0,block);
|
|
return NULL;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmLockIMCC(IMM32.@)
|
|
*/
|
|
LPVOID WINAPI ImmLockIMCC(HIMCC imcc)
|
|
{
|
|
IMCCInternal *internal;
|
|
internal = (IMCCInternal*) imcc;
|
|
|
|
internal->dwLock ++;
|
|
return internal + 1;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmUnlockIMCC(IMM32.@)
|
|
*/
|
|
BOOL WINAPI ImmUnlockIMCC(HIMCC imcc)
|
|
{
|
|
IMCCInternal *internal;
|
|
internal = (IMCCInternal*) imcc;
|
|
|
|
internal->dwLock --;
|
|
return (internal->dwLock!=0);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmGetIMCCLockCount(IMM32.@)
|
|
*/
|
|
DWORD WINAPI ImmGetIMCCLockCount(HIMCC imcc)
|
|
{
|
|
IMCCInternal *internal;
|
|
internal = (IMCCInternal*) imcc;
|
|
|
|
return internal->dwLock;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmReSizeIMCC(IMM32.@)
|
|
*/
|
|
HIMCC WINAPI ImmReSizeIMCC(HIMCC imcc, DWORD size)
|
|
{
|
|
IMCCInternal *internal,*newone;
|
|
int real_size = size + sizeof(IMCCInternal);
|
|
|
|
internal = (IMCCInternal*) imcc;
|
|
|
|
newone = HeapReAlloc(GetProcessHeap(), 0, internal, real_size);
|
|
newone->dwSize = size;
|
|
|
|
return newone;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmGetIMCCSize(IMM32.@)
|
|
*/
|
|
DWORD WINAPI ImmGetIMCCSize(HIMCC imcc)
|
|
{
|
|
IMCCInternal *internal;
|
|
internal = (IMCCInternal*) imcc;
|
|
|
|
return internal->dwSize;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ImmGenerateMessage(IMM32.@)
|
|
*/
|
|
BOOL WINAPI ImmGenerateMessage(HIMC hIMC)
|
|
{
|
|
InputContextData *data = (InputContextData*)hIMC;
|
|
|
|
TRACE("%i messages queued\n",data->IMC.dwNumMsgBuf);
|
|
if (data->IMC.dwNumMsgBuf > 0)
|
|
{
|
|
LPTRANSMSG lpTransMsg;
|
|
INT i;
|
|
|
|
lpTransMsg = (LPTRANSMSG)ImmLockIMCC(data->IMC.hMsgBuf);
|
|
for (i = 0; i < data->IMC.dwNumMsgBuf; i++)
|
|
ImmInternalPostIMEMessage(data, lpTransMsg[i].message, lpTransMsg[i].wParam, lpTransMsg[i].lParam);
|
|
|
|
ImmUnlockIMCC(data->IMC.hMsgBuf);
|
|
|
|
data->IMC.dwNumMsgBuf = 0;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*****
|
|
* Internal functions to help with IME window management
|
|
*/
|
|
static void PaintDefaultIMEWnd(HWND hwnd)
|
|
{
|
|
PAINTSTRUCT ps;
|
|
RECT rect;
|
|
HDC hdc = BeginPaint(hwnd,&ps);
|
|
LPCOMPOSITIONSTRING compstr;
|
|
LPBYTE compdata = NULL;
|
|
HMONITOR monitor;
|
|
MONITORINFO mon_info;
|
|
INT offX=0, offY=0;
|
|
|
|
GetClientRect(hwnd,&rect);
|
|
FillRect(hdc, &rect, (HBRUSH)(COLOR_WINDOW + 1));
|
|
|
|
compdata = ImmLockIMCC(root_context->IMC.hCompStr);
|
|
compstr = (LPCOMPOSITIONSTRING)compdata;
|
|
|
|
if (compstr->dwCompStrLen && compstr->dwCompStrOffset)
|
|
{
|
|
SIZE size;
|
|
POINT pt;
|
|
HFONT oldfont = NULL;
|
|
LPWSTR CompString;
|
|
|
|
CompString = (LPWSTR)(compdata + compstr->dwCompStrOffset);
|
|
if (root_context->textfont)
|
|
oldfont = SelectObject(hdc,root_context->textfont);
|
|
|
|
|
|
GetTextExtentPoint32W(hdc, CompString, compstr->dwCompStrLen, &size);
|
|
pt.x = size.cx;
|
|
pt.y = size.cy;
|
|
LPtoDP(hdc,&pt,1);
|
|
|
|
/*
|
|
* How this works based on tests on windows:
|
|
* CFS_POINT: then we start our window at the point and grow it as large
|
|
* as it needs to be for the string.
|
|
* CFS_RECT: we still use the ptCurrentPos as a starting point and our
|
|
* window is only as large as we need for the string, but we do not
|
|
* grow such that our window exceeds the given rect. Wrapping if
|
|
* needed and possible. If our ptCurrentPos is outside of our rect
|
|
* then no window is displayed.
|
|
* CFS_FORCE_POSITION: appears to behave just like CFS_POINT
|
|
* maybe becase the default MSIME does not do any IME adjusting.
|
|
*/
|
|
if (root_context->IMC.cfCompForm.dwStyle != CFS_DEFAULT)
|
|
{
|
|
POINT cpt = root_context->IMC.cfCompForm.ptCurrentPos;
|
|
ClientToScreen(root_context->IMC.hWnd,&cpt);
|
|
rect.left = cpt.x;
|
|
rect.top = cpt.y;
|
|
rect.right = rect.left + pt.x;
|
|
rect.bottom = rect.top + pt.y;
|
|
monitor = MonitorFromPoint(cpt, MONITOR_DEFAULTTOPRIMARY);
|
|
}
|
|
else /* CFS_DEFAULT */
|
|
{
|
|
/* Windows places the default IME window in the bottom left */
|
|
HWND target = root_context->IMC.hWnd;
|
|
if (!target) target = GetFocus();
|
|
|
|
GetWindowRect(target,&rect);
|
|
rect.top = rect.bottom;
|
|
rect.right = rect.left + pt.x + 20;
|
|
rect.bottom = rect.top + pt.y + 20;
|
|
offX=offY=10;
|
|
monitor = MonitorFromWindow(target, MONITOR_DEFAULTTOPRIMARY);
|
|
}
|
|
|
|
if (root_context->IMC.cfCompForm.dwStyle == CFS_RECT)
|
|
{
|
|
RECT client;
|
|
client =root_context->IMC.cfCompForm.rcArea;
|
|
MapWindowPoints( root_context->IMC.hWnd, 0, (POINT *)&client, 2 );
|
|
IntersectRect(&rect,&rect,&client);
|
|
/* TODO: Wrap the input if needed */
|
|
}
|
|
|
|
if (root_context->IMC.cfCompForm.dwStyle == CFS_DEFAULT)
|
|
{
|
|
/* make sure we are on the desktop */
|
|
mon_info.cbSize = sizeof(mon_info);
|
|
GetMonitorInfoW(monitor, &mon_info);
|
|
|
|
if (rect.bottom > mon_info.rcWork.bottom)
|
|
{
|
|
int shift = rect.bottom - mon_info.rcWork.bottom;
|
|
rect.top -= shift;
|
|
rect.bottom -= shift;
|
|
}
|
|
if (rect.left < 0)
|
|
{
|
|
rect.right -= rect.left;
|
|
rect.left = 0;
|
|
}
|
|
if (rect.right > mon_info.rcWork.right)
|
|
{
|
|
int shift = rect.right - mon_info.rcWork.right;
|
|
rect.left -= shift;
|
|
rect.right -= shift;
|
|
}
|
|
}
|
|
|
|
SetWindowPos(hwnd, HWND_TOPMOST, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOACTIVATE);
|
|
|
|
TextOutW(hdc, offX,offY, CompString, compstr->dwCompStrLen);
|
|
|
|
if (oldfont)
|
|
SelectObject(hdc,oldfont);
|
|
}
|
|
|
|
ImmUnlockIMCC(root_context->IMC.hCompStr);
|
|
|
|
EndPaint(hwnd,&ps);
|
|
}
|
|
|
|
static void UpdateDataInDefaultIMEWindow(HWND hwnd, BOOL showable)
|
|
{
|
|
LPCOMPOSITIONSTRING compstr;
|
|
|
|
if (root_context->IMC.hCompStr)
|
|
compstr = ImmLockIMCC(root_context->IMC.hCompStr);
|
|
else
|
|
compstr = NULL;
|
|
|
|
if (compstr == NULL || compstr->dwCompStrLen == 0)
|
|
ShowWindow(hwndDefault,SW_HIDE);
|
|
else if (showable)
|
|
ShowWindow(hwndDefault,SW_SHOWNOACTIVATE);
|
|
|
|
RedrawWindow(hwnd,NULL,NULL,RDW_ERASENOW|RDW_INVALIDATE);
|
|
|
|
if (compstr != NULL)
|
|
ImmUnlockIMCC(root_context->IMC.hCompStr);
|
|
}
|
|
|
|
/*
|
|
* The window proc for the default IME window
|
|
*/
|
|
static LRESULT WINAPI IME_WindowProc(HWND hwnd, UINT msg, WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
LRESULT rc = 0;
|
|
|
|
TRACE("Incoming Message 0x%x (0x%08x, 0x%08x)\n", msg, (UINT)wParam,
|
|
(UINT)lParam);
|
|
|
|
switch(msg)
|
|
{
|
|
case WM_PAINT:
|
|
PaintDefaultIMEWnd(hwnd);
|
|
return FALSE;
|
|
|
|
case WM_NCCREATE:
|
|
return TRUE;
|
|
|
|
case WM_CREATE:
|
|
SetWindowTextA(hwnd,"Wine Ime Active");
|
|
return TRUE;
|
|
|
|
case WM_SETFOCUS:
|
|
if (wParam)
|
|
SetFocus((HWND)wParam);
|
|
else
|
|
FIXME("Received focus, should never have focus\n");
|
|
break;
|
|
case WM_IME_COMPOSITION:
|
|
TRACE("IME message %s, 0x%x, 0x%x (%i)\n",
|
|
"WM_IME_COMPOSITION", (UINT)wParam, (UINT)lParam,
|
|
root_context->bRead);
|
|
if (lParam & GCS_RESULTSTR)
|
|
IMM_PostResult(root_context);
|
|
else
|
|
UpdateDataInDefaultIMEWindow(hwnd,TRUE);
|
|
break;
|
|
case WM_IME_STARTCOMPOSITION:
|
|
TRACE("IME message %s, 0x%x, 0x%x\n",
|
|
"WM_IME_STARTCOMPOSITION", (UINT)wParam, (UINT)lParam);
|
|
root_context->IMC.hWnd = GetFocus();
|
|
ShowWindow(hwndDefault,SW_SHOWNOACTIVATE);
|
|
break;
|
|
case WM_IME_ENDCOMPOSITION:
|
|
TRACE("IME message %s, 0x%x, 0x%x\n",
|
|
"WM_IME_ENDCOMPOSITION", (UINT)wParam, (UINT)lParam);
|
|
ShowWindow(hwndDefault,SW_HIDE);
|
|
break;
|
|
case WM_IME_SELECT:
|
|
TRACE("IME message %s, 0x%x, 0x%x\n","WM_IME_SELECT",
|
|
(UINT)wParam, (UINT)lParam);
|
|
break;
|
|
case WM_IME_CONTROL:
|
|
TRACE("IME message %s, 0x%x, 0x%x\n","WM_IME_CONTROL",
|
|
(UINT)wParam, (UINT)lParam);
|
|
rc = 1;
|
|
break;
|
|
case WM_IME_NOTIFY:
|
|
TRACE("!! IME NOTIFY\n");
|
|
break;
|
|
default:
|
|
TRACE("Non-standard message 0x%x\n",msg);
|
|
}
|
|
/* check the MSIME messages */
|
|
if (msg == WM_MSIME_SERVICE)
|
|
{
|
|
TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_SERVICE",
|
|
(UINT)wParam, (UINT)lParam);
|
|
rc = FALSE;
|
|
}
|
|
else if (msg == WM_MSIME_RECONVERTOPTIONS)
|
|
{
|
|
TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_RECONVERTOPTIONS",
|
|
(UINT)wParam, (UINT)lParam);
|
|
}
|
|
else if (msg == WM_MSIME_MOUSE)
|
|
{
|
|
TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_MOUSE",
|
|
(UINT)wParam, (UINT)lParam);
|
|
}
|
|
else if (msg == WM_MSIME_RECONVERTREQUEST)
|
|
{
|
|
TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_RECONVERTREQUEST",
|
|
(UINT)wParam, (UINT)lParam);
|
|
}
|
|
else if (msg == WM_MSIME_RECONVERT)
|
|
{
|
|
TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_RECONVERT",
|
|
(UINT)wParam, (UINT)lParam);
|
|
}
|
|
else if (msg == WM_MSIME_QUERYPOSITION)
|
|
{
|
|
TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_QUERYPOSITION",
|
|
(UINT)wParam, (UINT)lParam);
|
|
}
|
|
else if (msg == WM_MSIME_DOCUMENTFEED)
|
|
{
|
|
TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_DOCUMENTFEED",
|
|
(UINT)wParam, (UINT)lParam);
|
|
}
|
|
/* DefWndProc if not an IME message */
|
|
else if (!rc && !((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
|
|
(msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP)))
|
|
rc = DefWindowProcW(hwnd,msg,wParam,lParam);
|
|
|
|
return rc;
|
|
}
|