wine/dlls/imm32/imm.c
Aric Stewart 5db70db76e imm32: Use the COMPOSITIONSTRING in hCompStr.
Stop using our custom structure for the Composition string and instead
use the COMPOSITIONSTRING whose handle is in the IMC structure.
2007-07-11 12:42:25 +02:00

2150 lines
64 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"
WINE_DEFAULT_DEBUG_CHANNEL(imm);
#define FROM_IME 0xcafe1337
static void (*pX11DRV_ForceXIMReset)(HWND);
typedef struct tagIMCCInternal
{
DWORD dwLock;
DWORD dwSize;
} IMCCInternal;
typedef struct tagInputContextData
{
BOOL bInternalState;
BOOL bRead;
BOOL bInComposition;
HFONT textfont;
DWORD dwLock;
INPUTCONTEXT IMC;
} InputContextData;
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;
/* 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;
/*
* prototypes
*/
static LRESULT WINAPI IME_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
LPARAM lParam);
static void UpdateDataInDefaultIMEWindow(HWND hwnd);
static void ImmInternalPostIMEMessage(UINT, WPARAM, LPARAM);
static void ImmInternalSetOpenStatus(BOOL fOpen);
static HIMCC updateResultStr(HIMCC old, LPWSTR resultstr, DWORD len);
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 (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();
break;
}
return TRUE;
}
/* for posting messages as the IME */
static void ImmInternalPostIMEMessage(UINT msg, WPARAM wParam, LPARAM lParam)
{
HWND target = GetFocus();
if (!target)
PostMessageW(root_context->IMC.hWnd,msg,wParam,lParam);
else
PostMessageW(target, msg, wParam, lParam);
}
static LRESULT ImmInternalSendIMENotify(WPARAM notify, LPARAM lParam)
{
HWND target;
target = root_context->IMC.hWnd;
if (!target) target = GetFocus();
if (target)
return SendMessageW(target, WM_IME_NOTIFY, notify, lParam);
return 0;
}
static void ImmInternalSetOpenStatus(BOOL fOpen)
{
TRACE("Setting internal state to %s\n",(fOpen)?"OPEN":"CLOSED");
root_context->IMC.fOpen = fOpen;
root_context->bInternalState = fOpen;
if (fOpen == FALSE)
{
ShowWindow(hwndDefault,SW_HIDE);
ImmDestroyIMCC(root_context->IMC.hCompStr);
root_context->IMC.hCompStr = NULL;
}
else
ShowWindow(hwndDefault, SW_SHOWNOACTIVATE);
ImmInternalSendIMENotify(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)
{
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 */
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)
{
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;
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)
{
InputContextData *data = (InputContextData*)hIMC;
WARN("(%p, %p): semi-stub\n", hWnd, hIMC);
if (!hIMC)
return NULL;
/*
* 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 (data->IMC.hWnd == hWnd)
return hIMC;
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);
}
/*
* TODO: We need to keep track of the old context associated
* with a window and return it for now we will return NULL;
*/
return NULL;
}
/***********************************************************************
* 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));
return (HIMC)new_context;
}
/***********************************************************************
* ImmDestroyContext (IMM32.@)
*/
BOOL WINAPI ImmDestroyContext(HIMC hIMC)
{
InputContextData *data = (InputContextData*)hIMC;
TRACE("Destroying %p\n",hIMC);
if (hIMC)
{
ImmDestroyIMCC(root_context->IMC.hCompStr);
ImmDestroyIMCC(root_context->IMC.hCandInfo);
ImmDestroyIMCC(root_context->IMC.hGuideLine);
ImmDestroyIMCC(root_context->IMC.hPrivate);
ImmDestroyIMCC(root_context->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)
{
FIXME("(%p, %p): stub\n", hIMC, lplf);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
/***********************************************************************
* ImmGetCompositionFontW (IMM32.@)
*/
BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
{
FIXME("(%p, %p): stub\n", hIMC, lplf);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
/***********************************************************************
* 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
{
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
{
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;
memcpy(lpCompForm,&(data->IMC.cfCompForm),sizeof(COMPOSITIONFORM));
return 1;
}
/***********************************************************************
* ImmGetContext (IMM32.@)
*
*/
HIMC WINAPI ImmGetContext(HWND hWnd)
{
TRACE("%p\n", hWnd);
if (!root_context)
return NULL;
root_context->IMC.hWnd = hWnd;
return (HIMC)root_context;
}
/***********************************************************************
* 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)
{
FIXME("(%p - %p %p ): semi-stub\n", hWnd,hwndDefault, root_context);
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 (HWND)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)
{
FIXME("(%p, %p, %d): stub\n", hKL, lpszFileName, uBufLen);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
}
/***********************************************************************
* ImmGetIMEFileNameW (IMM32.@)
*/
UINT WINAPI ImmGetIMEFileNameW(
HKL hKL, LPWSTR lpszFileName, UINT uBufLen)
{
FIXME("(%p, %p, %d): stub\n", hKL, lpszFileName, uBufLen);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
}
/***********************************************************************
* 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");
{
HIMCC newCompStr;
if (pX11DRV_ForceXIMReset)
pX11DRV_ForceXIMReset(root_context->IMC.hWnd);
newCompStr = updateCompStr(root_context->IMC.hCompStr, NULL, 0);
ImmDestroyIMCC(root_context->IMC.hCompStr);
root_context->IMC.hCompStr = newCompStr;
ImmInternalPostIMEMessage(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;
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;
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(WM_IME_COMPOSITION, 0,
GCS_COMPSTR);
ImmInternalPostIMEMessage(WM_IME_COMPOSITION,
param,
GCS_RESULTSTR|GCS_RESULTCLAUSE);
}
ImmInternalPostIMEMessage(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)
{
FIXME("(%p, %p): stub\n", hWnd, hIMC);
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(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;
memcpy(&data->IMC.lfFont.W,lplf,sizeof(LOGFONTW));
ImmInternalSendIMENotify(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(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;
}
else
{
newCompStr = updateCompStr(root_context->IMC.hCompStr, NULL, 0);
ImmDestroyIMCC(root_context->IMC.hCompStr);
root_context->IMC.hCompStr = newCompStr;
}
}
UpdateDataInDefaultIMEWindow(hwndDefault);
ImmInternalPostIMEMessage(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;
memcpy(&data->IMC.cfCompForm,lpCompForm,sizeof(COMPOSITIONFORM));
if (IsWindowVisible(hwndDefault))
{
reshow = TRUE;
ShowWindow(hwndDefault,SW_HIDE);
}
/* FIXME: this is a partial stub */
if (reshow)
ShowWindow(hwndDefault,SW_SHOWNOACTIVATE);
ImmInternalSendIMENotify(IMN_SETCOMPOSITIONWINDOW, 0);
return TRUE;
}
/***********************************************************************
* ImmSetConversionStatus (IMM32.@)
*/
BOOL WINAPI ImmSetConversionStatus(
HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence)
{
FIXME("(%p, %d, %d): stub\n",
hIMC, fdwConversion, fdwSentence
);
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(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(WM_IME_ENDCOMPOSITION,0,0);
else
ImmInternalPostIMEMessage(WM_IME_STARTCOMPOSITION,0,0);
ImmInternalSetOpenStatus(fOpen);
ImmInternalSetOpenStatus(!fOpen);
if (data->IMC.fOpen == FALSE)
ImmInternalPostIMEMessage(WM_IME_ENDCOMPOSITION,0,0);
else
ImmInternalPostIMEMessage(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;
}
/*****
* 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;
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);
if (root_context->IMC.cfCompForm.dwStyle == CFS_POINT ||
root_context->IMC.cfCompForm.dwStyle == CFS_FORCE_POSITION)
{
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 + 20;
rect.bottom = rect.top + pt.y + 20;
}
else if (root_context->IMC.cfCompForm.dwStyle == CFS_RECT)
{
POINT cpt;
cpt.x = root_context->IMC.cfCompForm.rcArea.left;
cpt.y = root_context->IMC.cfCompForm.rcArea.top;
ClientToScreen(root_context->IMC.hWnd,&cpt);
rect.left = cpt.x;
rect.top = cpt.y;
cpt.x = root_context->IMC.cfCompForm.rcArea.right;
cpt.y = root_context->IMC.cfCompForm.rcArea.bottom;
ClientToScreen(root_context->IMC.hWnd,&cpt);
rect.right = cpt.x;
rect.bottom = cpt.y;
}
else
{
rect.right = rect.left + pt.x + 20;
rect.bottom = rect.top + pt.y + 20;
}
MoveWindow(hwnd, rect.left, rect.top, rect.right - rect.left ,
rect.bottom - rect.top, FALSE);
TextOutW(hdc, 10,10, CompString, compstr->dwCompStrLen);
if (oldfont)
SelectObject(hdc,oldfont);
}
ImmUnlockIMCC(root_context->IMC.hCompStr);
EndPaint(hwnd,&ps);
}
static void UpdateDataInDefaultIMEWindow(HWND hwnd)
{
RedrawWindow(hwnd,NULL,NULL,RDW_ERASENOW|RDW_INVALIDATE);
}
/*
* 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);
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;
}