imm32: Correct a typo accidently using data instead of root_context.
[wine/multimedia.git] / dlls / imm32 / imm.c
blob950fdc5d6fc860ff09269f1995f6ff00045df508
1 /*
2 * IMM32 library
4 * Copyright 1998 Patrik Stridvall
5 * Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include <stdarg.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "wingdi.h"
27 #include "winuser.h"
28 #include "winerror.h"
29 #include "wine/debug.h"
30 #include "imm.h"
31 #include "ddk/imm.h"
32 #include "winnls.h"
33 #include "winreg.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(imm);
37 #define FROM_IME 0xcafe1337
39 static void (*pX11DRV_ForceXIMReset)(HWND);
41 typedef struct tagIMCCInternal
43 DWORD dwLock;
44 DWORD dwSize;
45 } IMCCInternal;
47 typedef struct tagInputContextData
49 BOOL bInternalState;
50 BOOL bRead;
51 BOOL bInComposition;
52 HFONT textfont;
54 DWORD dwLock;
55 INPUTCONTEXT IMC;
56 } InputContextData;
58 typedef struct _tagTRANSMSG {
59 UINT message;
60 WPARAM wParam;
61 LPARAM lParam;
62 } TRANSMSG, *LPTRANSMSG;
64 static InputContextData *root_context = NULL;
65 static HWND hwndDefault = NULL;
66 static HANDLE hImeInst;
67 static const WCHAR WC_IMECLASSNAME[] = {'I','M','E',0};
68 static ATOM atIMEClass = 0;
70 /* MSIME messages */
71 static UINT WM_MSIME_SERVICE;
72 static UINT WM_MSIME_RECONVERTOPTIONS;
73 static UINT WM_MSIME_MOUSE;
74 static UINT WM_MSIME_RECONVERTREQUEST;
75 static UINT WM_MSIME_RECONVERT;
76 static UINT WM_MSIME_QUERYPOSITION;
77 static UINT WM_MSIME_DOCUMENTFEED;
80 * prototypes
82 static LRESULT WINAPI IME_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
83 LPARAM lParam);
84 static void UpdateDataInDefaultIMEWindow(HWND hwnd, BOOL showable);
85 static void ImmInternalPostIMEMessage(InputContextData*, UINT, WPARAM, LPARAM);
86 static void ImmInternalSetOpenStatus(BOOL fOpen);
87 static HIMCC updateResultStr(HIMCC old, LPWSTR resultstr, DWORD len);
89 static VOID IMM_PostResult(InputContextData *data)
91 unsigned int i;
92 LPCOMPOSITIONSTRING compstr;
93 LPBYTE compdata;
94 LPWSTR ResultStr;
95 HIMCC newCompStr;
97 TRACE("Posting result as IME_CHAR\n");
98 compdata = ImmLockIMCC(root_context->IMC.hCompStr);
99 compstr = (LPCOMPOSITIONSTRING)compdata;
100 ResultStr = (LPWSTR)(compdata + compstr->dwResultStrOffset);
102 for (i = 0; i < compstr->dwResultStrLen; i++)
103 ImmInternalPostIMEMessage (root_context, WM_IME_CHAR, ResultStr[i], 1);
105 ImmUnlockIMCC(root_context->IMC.hCompStr);
107 /* clear the buffer */
108 newCompStr = updateResultStr(root_context->IMC.hCompStr, NULL, 0);
109 ImmDestroyIMCC(root_context->IMC.hCompStr);
110 root_context->IMC.hCompStr = newCompStr;
113 static void IMM_Register(void)
115 WNDCLASSW wndClass;
116 ZeroMemory(&wndClass, sizeof(WNDCLASSW));
117 wndClass.style = CS_GLOBALCLASS | CS_IME | CS_HREDRAW | CS_VREDRAW;
118 wndClass.lpfnWndProc = (WNDPROC) IME_WindowProc;
119 wndClass.cbClsExtra = 0;
120 wndClass.cbWndExtra = 0;
121 wndClass.hInstance = hImeInst;
122 wndClass.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
123 wndClass.hIcon = NULL;
124 wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW +1);
125 wndClass.lpszMenuName = 0;
126 wndClass.lpszClassName = WC_IMECLASSNAME;
127 atIMEClass = RegisterClassW(&wndClass);
130 static void IMM_Unregister(void)
132 if (atIMEClass) {
133 UnregisterClassW(WC_IMECLASSNAME, NULL);
137 static void IMM_RegisterMessages(void)
139 WM_MSIME_SERVICE = RegisterWindowMessageA("MSIMEService");
140 WM_MSIME_RECONVERTOPTIONS = RegisterWindowMessageA("MSIMEReconvertOptions");
141 WM_MSIME_MOUSE = RegisterWindowMessageA("MSIMEMouseOperation");
142 WM_MSIME_RECONVERTREQUEST = RegisterWindowMessageA("MSIMEReconvertRequest");
143 WM_MSIME_RECONVERT = RegisterWindowMessageA("MSIMEReconvert");
144 WM_MSIME_QUERYPOSITION = RegisterWindowMessageA("MSIMEQueryPosition");
145 WM_MSIME_DOCUMENTFEED = RegisterWindowMessageA("MSIMEDocumentFeed");
149 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved)
151 HMODULE x11drv;
153 TRACE("%p, %x, %p\n",hInstDLL,fdwReason,lpReserved);
154 switch (fdwReason)
156 case DLL_PROCESS_ATTACH:
157 DisableThreadLibraryCalls(hInstDLL);
158 hImeInst = hInstDLL;
159 IMM_RegisterMessages();
160 x11drv = GetModuleHandleA("winex11.drv");
161 if (x11drv) pX11DRV_ForceXIMReset = (void *)GetProcAddress( x11drv, "ForceXIMReset");
162 break;
163 case DLL_PROCESS_DETACH:
164 if (hwndDefault)
166 DestroyWindow(hwndDefault);
167 hwndDefault = 0;
169 IMM_Unregister();
170 break;
172 return TRUE;
175 /* for posting messages as the IME */
176 static void ImmInternalPostIMEMessage(InputContextData *data, UINT msg, WPARAM wParam, LPARAM lParam)
178 HWND target = GetFocus();
179 if (!target)
180 PostMessageW(data->IMC.hWnd,msg,wParam,lParam);
181 else
182 PostMessageW(target, msg, wParam, lParam);
185 static LRESULT ImmInternalSendIMENotify(InputContextData *data, WPARAM notify, LPARAM lParam)
187 HWND target;
189 target = data->IMC.hWnd;
190 if (!target) target = GetFocus();
192 if (target)
193 return SendMessageW(target, WM_IME_NOTIFY, notify, lParam);
195 return 0;
198 static HIMCC ImmCreateBlankCompStr(void)
200 HIMCC rc;
201 LPCOMPOSITIONSTRING ptr;
202 rc = ImmCreateIMCC(sizeof(COMPOSITIONSTRING));
203 ptr = (LPCOMPOSITIONSTRING)ImmLockIMCC(rc);
204 memset(ptr,0,sizeof(COMPOSITIONSTRING));
205 ptr->dwSize = sizeof(COMPOSITIONSTRING);
206 ImmUnlockIMCC(rc);
207 return rc;
210 static void ImmInternalSetOpenStatus(BOOL fOpen)
212 TRACE("Setting internal state to %s\n",(fOpen)?"OPEN":"CLOSED");
214 if (root_context->IMC.fOpen && fOpen == FALSE)
216 ShowWindow(hwndDefault,SW_HIDE);
217 ImmDestroyIMCC(root_context->IMC.hCompStr);
218 root_context->IMC.hCompStr = ImmCreateBlankCompStr();
221 root_context->IMC.fOpen = fOpen;
222 root_context->bInternalState = fOpen;
224 ImmInternalSendIMENotify(root_context, IMN_SETOPENSTATUS, 0);
227 static int updateField(DWORD origLen, DWORD origOffset, DWORD currentOffset,
228 LPBYTE target, LPBYTE source, DWORD* lenParam,
229 DWORD* offsetParam, BOOL wchars )
231 if (origLen > 0 && origOffset > 0)
233 int truelen = origLen;
234 if (wchars)
235 truelen *= sizeof(WCHAR);
237 memcpy(&target[currentOffset], &source[origOffset], truelen);
239 *lenParam = origLen;
240 *offsetParam = currentOffset;
241 currentOffset += truelen;
243 return currentOffset;
246 static HIMCC updateCompStr(HIMCC old, LPWSTR compstr, DWORD len)
248 /* we need to make sure the CompStr, CompClaus and CompAttr fields are all
249 * set and correct */
250 int needed_size;
251 HIMCC rc;
252 LPBYTE newdata = NULL;
253 LPBYTE olddata = NULL;
254 LPCOMPOSITIONSTRING new_one;
255 LPCOMPOSITIONSTRING lpcs = NULL;
256 INT current_offset = 0;
258 TRACE("%s, %i\n",debugstr_wn(compstr,len),len);
260 if (old == NULL && compstr == NULL && len == 0)
261 return NULL;
263 if (old != NULL)
265 olddata = ImmLockIMCC(old);
266 lpcs = (LPCOMPOSITIONSTRING)olddata;
269 needed_size = sizeof(COMPOSITIONSTRING) + len * sizeof(WCHAR) +
270 len + sizeof(DWORD) * 2;
272 if (lpcs != NULL)
274 needed_size += lpcs->dwCompReadAttrLen;
275 needed_size += lpcs->dwCompReadClauseLen;
276 needed_size += lpcs->dwCompReadStrLen * sizeof(DWORD);
277 needed_size += lpcs->dwResultReadClauseLen;
278 needed_size += lpcs->dwResultReadStrLen * sizeof(DWORD);
279 needed_size += lpcs->dwResultClauseLen;
280 needed_size += lpcs->dwResultStrLen * sizeof(DWORD);
281 needed_size += lpcs->dwPrivateSize;
283 rc = ImmCreateIMCC(needed_size);
284 newdata = ImmLockIMCC(rc);
285 new_one = (LPCOMPOSITIONSTRING)newdata;
287 new_one->dwSize = needed_size;
288 current_offset = sizeof(COMPOSITIONSTRING);
289 if (lpcs != NULL)
291 current_offset = updateField(lpcs->dwCompReadAttrLen,
292 lpcs->dwCompReadAttrOffset,
293 current_offset, newdata, olddata,
294 &new_one->dwCompReadAttrLen,
295 &new_one->dwCompReadAttrOffset, FALSE);
297 current_offset = updateField(lpcs->dwCompReadClauseLen,
298 lpcs->dwCompReadClauseOffset,
299 current_offset, newdata, olddata,
300 &new_one->dwCompReadClauseLen,
301 &new_one->dwCompReadClauseOffset, FALSE);
303 current_offset = updateField(lpcs->dwCompReadStrLen,
304 lpcs->dwCompReadStrOffset,
305 current_offset, newdata, olddata,
306 &new_one->dwCompReadStrLen,
307 &new_one->dwCompReadStrOffset, TRUE);
309 /* new CompAttr, CompClause, CompStr, dwCursorPos */
310 new_one->dwDeltaStart = 0;
312 current_offset = updateField(lpcs->dwResultReadClauseLen,
313 lpcs->dwResultReadClauseOffset,
314 current_offset, newdata, olddata,
315 &new_one->dwResultReadClauseLen,
316 &new_one->dwResultReadClauseOffset, FALSE);
318 current_offset = updateField(lpcs->dwResultReadStrLen,
319 lpcs->dwResultReadStrOffset,
320 current_offset, newdata, olddata,
321 &new_one->dwResultReadStrLen,
322 &new_one->dwResultReadStrOffset, TRUE);
324 current_offset = updateField(lpcs->dwResultClauseLen,
325 lpcs->dwResultClauseOffset,
326 current_offset, newdata, olddata,
327 &new_one->dwResultClauseLen,
328 &new_one->dwResultClauseOffset, FALSE);
330 current_offset = updateField(lpcs->dwResultStrLen,
331 lpcs->dwResultStrOffset,
332 current_offset, newdata, olddata,
333 &new_one->dwResultStrLen,
334 &new_one->dwResultStrOffset, TRUE);
336 current_offset = updateField(lpcs->dwPrivateSize,
337 lpcs->dwPrivateOffset,
338 current_offset, newdata, olddata,
339 &new_one->dwPrivateSize,
340 &new_one->dwPrivateOffset, FALSE);
343 /* set new data */
344 /* CompAttr */
345 new_one->dwCompAttrLen = len;
346 if (len > 0)
348 new_one->dwCompAttrOffset = current_offset;
349 memset(&newdata[current_offset],ATTR_INPUT,len);
350 current_offset += len;
353 /* CompClause */
354 if (len > 0)
356 new_one->dwCompClauseLen = sizeof(DWORD) * 2;
357 new_one->dwCompClauseOffset = current_offset;
358 *(DWORD*)(&newdata[current_offset]) = 0;
359 current_offset += sizeof(DWORD);
360 *(DWORD*)(&newdata[current_offset]) = len;
361 current_offset += sizeof(DWORD);
364 /* CompStr */
365 new_one->dwCompStrLen = len;
366 if (len > 0)
368 new_one->dwCompStrOffset = current_offset;
369 memcpy(&newdata[current_offset],compstr,len*sizeof(WCHAR));
372 /* CursorPos */
373 new_one->dwCursorPos = len;
375 ImmUnlockIMCC(rc);
376 if (lpcs)
377 ImmUnlockIMCC(old);
379 return rc;
382 static HIMCC updateResultStr(HIMCC old, LPWSTR resultstr, DWORD len)
384 /* we need to make sure the ResultStr and ResultClause fields are all
385 * set and correct */
386 int needed_size;
387 HIMCC rc;
388 LPBYTE newdata = NULL;
389 LPBYTE olddata = NULL;
390 LPCOMPOSITIONSTRING new_one;
391 LPCOMPOSITIONSTRING lpcs = NULL;
392 INT current_offset = 0;
394 TRACE("%s, %i\n",debugstr_wn(resultstr,len),len);
396 if (old == NULL && resultstr == NULL && len == 0)
397 return NULL;
399 if (old != NULL)
401 olddata = ImmLockIMCC(old);
402 lpcs = (LPCOMPOSITIONSTRING)olddata;
405 needed_size = sizeof(COMPOSITIONSTRING) + len * sizeof(WCHAR) +
406 sizeof(DWORD) * 2;
408 if (lpcs != NULL)
410 needed_size += lpcs->dwCompReadAttrLen;
411 needed_size += lpcs->dwCompReadClauseLen;
412 needed_size += lpcs->dwCompReadStrLen * sizeof(DWORD);
413 needed_size += lpcs->dwCompAttrLen;
414 needed_size += lpcs->dwCompClauseLen;
415 needed_size += lpcs->dwCompStrLen * sizeof(DWORD);
416 needed_size += lpcs->dwResultReadClauseLen;
417 needed_size += lpcs->dwResultReadStrLen * sizeof(DWORD);
418 needed_size += lpcs->dwPrivateSize;
420 rc = ImmCreateIMCC(needed_size);
421 newdata = ImmLockIMCC(rc);
422 new_one = (LPCOMPOSITIONSTRING)newdata;
424 new_one->dwSize = needed_size;
425 current_offset = sizeof(COMPOSITIONSTRING);
426 if (lpcs != NULL)
428 current_offset = updateField(lpcs->dwCompReadAttrLen,
429 lpcs->dwCompReadAttrOffset,
430 current_offset, newdata, olddata,
431 &new_one->dwCompReadAttrLen,
432 &new_one->dwCompReadAttrOffset, FALSE);
434 current_offset = updateField(lpcs->dwCompReadClauseLen,
435 lpcs->dwCompReadClauseOffset,
436 current_offset, newdata, olddata,
437 &new_one->dwCompReadClauseLen,
438 &new_one->dwCompReadClauseOffset, FALSE);
440 current_offset = updateField(lpcs->dwCompReadStrLen,
441 lpcs->dwCompReadStrOffset,
442 current_offset, newdata, olddata,
443 &new_one->dwCompReadStrLen,
444 &new_one->dwCompReadStrOffset, TRUE);
446 current_offset = updateField(lpcs->dwCompAttrLen,
447 lpcs->dwCompAttrOffset,
448 current_offset, newdata, olddata,
449 &new_one->dwCompAttrLen,
450 &new_one->dwCompAttrOffset, FALSE);
452 current_offset = updateField(lpcs->dwCompClauseLen,
453 lpcs->dwCompClauseOffset,
454 current_offset, newdata, olddata,
455 &new_one->dwCompClauseLen,
456 &new_one->dwCompClauseOffset, FALSE);
458 current_offset = updateField(lpcs->dwCompStrLen,
459 lpcs->dwCompStrOffset,
460 current_offset, newdata, olddata,
461 &new_one->dwCompStrLen,
462 &new_one->dwCompStrOffset, TRUE);
464 new_one->dwCursorPos = lpcs->dwCursorPos;
465 new_one->dwDeltaStart = 0;
467 current_offset = updateField(lpcs->dwResultReadClauseLen,
468 lpcs->dwResultReadClauseOffset,
469 current_offset, newdata, olddata,
470 &new_one->dwResultReadClauseLen,
471 &new_one->dwResultReadClauseOffset, FALSE);
473 current_offset = updateField(lpcs->dwResultReadStrLen,
474 lpcs->dwResultReadStrOffset,
475 current_offset, newdata, olddata,
476 &new_one->dwResultReadStrLen,
477 &new_one->dwResultReadStrOffset, TRUE);
479 /* new ResultClause , ResultStr */
481 current_offset = updateField(lpcs->dwPrivateSize,
482 lpcs->dwPrivateOffset,
483 current_offset, newdata, olddata,
484 &new_one->dwPrivateSize,
485 &new_one->dwPrivateOffset, FALSE);
488 /* set new data */
489 /* ResultClause */
490 if (len > 0)
492 new_one->dwResultClauseLen = sizeof(DWORD) * 2;
493 new_one->dwResultClauseOffset = current_offset;
494 *(DWORD*)(&newdata[current_offset]) = 0;
495 current_offset += sizeof(DWORD);
496 *(DWORD*)(&newdata[current_offset]) = len;
497 current_offset += sizeof(DWORD);
500 /* ResultStr */
501 new_one->dwResultStrLen = len;
502 if (len > 0)
504 new_one->dwResultStrOffset = current_offset;
505 memcpy(&newdata[current_offset],resultstr,len*sizeof(WCHAR));
507 ImmUnlockIMCC(rc);
508 if (lpcs)
509 ImmUnlockIMCC(old);
511 return rc;
516 /***********************************************************************
517 * ImmAssociateContext (IMM32.@)
519 HIMC WINAPI ImmAssociateContext(HWND hWnd, HIMC hIMC)
521 InputContextData *data = (InputContextData*)hIMC;
523 WARN("(%p, %p): semi-stub\n", hWnd, hIMC);
525 if (!hIMC)
526 return NULL;
529 * WINE SPECIFIC! MAY CONFLICT
530 * associate the root context we have an XIM created
532 if (hWnd == 0x000)
534 root_context = (InputContextData*)hIMC;
538 * If already associated just return
540 if (data->IMC.hWnd == hWnd)
541 return hIMC;
543 if (IsWindow(data->IMC.hWnd))
546 * Post a message that your context is switching
548 SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, FALSE, ISC_SHOWUIALL);
551 data->IMC.hWnd = hWnd;
553 if (IsWindow(data->IMC.hWnd))
556 * Post a message that your context is switching
558 SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, TRUE, ISC_SHOWUIALL);
562 * TODO: We need to keep track of the old context associated
563 * with a window and return it for now we will return NULL;
565 return NULL;
568 /***********************************************************************
569 * ImmAssociateContextEx (IMM32.@)
571 BOOL WINAPI ImmAssociateContextEx(HWND hWnd, HIMC hIMC, DWORD dwFlags)
573 FIXME("(%p, %p, %d): stub\n", hWnd, hIMC, dwFlags);
574 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
575 return FALSE;
578 /***********************************************************************
579 * ImmConfigureIMEA (IMM32.@)
581 BOOL WINAPI ImmConfigureIMEA(
582 HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
584 FIXME("(%p, %p, %d, %p): stub\n",
585 hKL, hWnd, dwMode, lpData
587 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
588 return FALSE;
591 /***********************************************************************
592 * ImmConfigureIMEW (IMM32.@)
594 BOOL WINAPI ImmConfigureIMEW(
595 HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
597 FIXME("(%p, %p, %d, %p): stub\n",
598 hKL, hWnd, dwMode, lpData
600 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
601 return FALSE;
604 /***********************************************************************
605 * ImmCreateContext (IMM32.@)
607 HIMC WINAPI ImmCreateContext(void)
609 InputContextData *new_context;
611 new_context = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(InputContextData));
613 /* hCompStr is never NULL */
614 new_context->IMC.hCompStr = ImmCreateBlankCompStr();
615 new_context->IMC.hMsgBuf = ImmCreateIMCC(1);
617 return (HIMC)new_context;
620 /***********************************************************************
621 * ImmDestroyContext (IMM32.@)
623 BOOL WINAPI ImmDestroyContext(HIMC hIMC)
625 InputContextData *data = (InputContextData*)hIMC;
627 TRACE("Destroying %p\n",hIMC);
629 if (hIMC)
631 ImmDestroyIMCC(data->IMC.hCompStr);
632 ImmDestroyIMCC(data->IMC.hCandInfo);
633 ImmDestroyIMCC(data->IMC.hGuideLine);
634 ImmDestroyIMCC(data->IMC.hPrivate);
635 ImmDestroyIMCC(data->IMC.hMsgBuf);
637 if (data->textfont)
639 DeleteObject(data->textfont);
640 data->textfont = NULL;
643 HeapFree(GetProcessHeap(),0,data);
645 return TRUE;
648 /***********************************************************************
649 * ImmDisableIME (IMM32.@)
651 BOOL WINAPI ImmDisableIME(DWORD idThread)
653 FIXME("(%d): stub\n", idThread);
654 return TRUE;
657 /***********************************************************************
658 * ImmEnumRegisterWordA (IMM32.@)
660 UINT WINAPI ImmEnumRegisterWordA(
661 HKL hKL, REGISTERWORDENUMPROCA lpfnEnumProc,
662 LPCSTR lpszReading, DWORD dwStyle,
663 LPCSTR lpszRegister, LPVOID lpData)
665 FIXME("(%p, %p, %s, %d, %s, %p): stub\n",
666 hKL, lpfnEnumProc,
667 debugstr_a(lpszReading), dwStyle,
668 debugstr_a(lpszRegister), lpData
670 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
671 return 0;
674 /***********************************************************************
675 * ImmEnumRegisterWordW (IMM32.@)
677 UINT WINAPI ImmEnumRegisterWordW(
678 HKL hKL, REGISTERWORDENUMPROCW lpfnEnumProc,
679 LPCWSTR lpszReading, DWORD dwStyle,
680 LPCWSTR lpszRegister, LPVOID lpData)
682 FIXME("(%p, %p, %s, %d, %s, %p): stub\n",
683 hKL, lpfnEnumProc,
684 debugstr_w(lpszReading), dwStyle,
685 debugstr_w(lpszRegister), lpData
687 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
688 return 0;
691 /***********************************************************************
692 * ImmEscapeA (IMM32.@)
694 LRESULT WINAPI ImmEscapeA(
695 HKL hKL, HIMC hIMC,
696 UINT uEscape, LPVOID lpData)
698 FIXME("(%p, %p, %d, %p): stub\n",
699 hKL, hIMC, uEscape, lpData
701 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
702 return 0;
705 /***********************************************************************
706 * ImmEscapeW (IMM32.@)
708 LRESULT WINAPI ImmEscapeW(
709 HKL hKL, HIMC hIMC,
710 UINT uEscape, LPVOID lpData)
712 FIXME("(%p, %p, %d, %p): stub\n",
713 hKL, hIMC, uEscape, lpData
715 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
716 return 0;
719 /***********************************************************************
720 * ImmGetCandidateListA (IMM32.@)
722 DWORD WINAPI ImmGetCandidateListA(
723 HIMC hIMC, DWORD deIndex,
724 LPCANDIDATELIST lpCandList, DWORD dwBufLen)
726 FIXME("(%p, %d, %p, %d): stub\n",
727 hIMC, deIndex,
728 lpCandList, dwBufLen
730 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
731 return 0;
734 /***********************************************************************
735 * ImmGetCandidateListCountA (IMM32.@)
737 DWORD WINAPI ImmGetCandidateListCountA(
738 HIMC hIMC, LPDWORD lpdwListCount)
740 FIXME("(%p, %p): stub\n", hIMC, lpdwListCount);
741 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
742 return 0;
745 /***********************************************************************
746 * ImmGetCandidateListCountW (IMM32.@)
748 DWORD WINAPI ImmGetCandidateListCountW(
749 HIMC hIMC, LPDWORD lpdwListCount)
751 FIXME("(%p, %p): stub\n", hIMC, lpdwListCount);
752 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
753 return 0;
756 /***********************************************************************
757 * ImmGetCandidateListW (IMM32.@)
759 DWORD WINAPI ImmGetCandidateListW(
760 HIMC hIMC, DWORD deIndex,
761 LPCANDIDATELIST lpCandList, DWORD dwBufLen)
763 FIXME("(%p, %d, %p, %d): stub\n",
764 hIMC, deIndex,
765 lpCandList, dwBufLen
767 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
768 return 0;
771 /***********************************************************************
772 * ImmGetCandidateWindow (IMM32.@)
774 BOOL WINAPI ImmGetCandidateWindow(
775 HIMC hIMC, DWORD dwBufLen, LPCANDIDATEFORM lpCandidate)
777 FIXME("(%p, %d, %p): stub\n", hIMC, dwBufLen, lpCandidate);
778 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
779 return FALSE;
782 /***********************************************************************
783 * ImmGetCompositionFontA (IMM32.@)
785 BOOL WINAPI ImmGetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
787 FIXME("(%p, %p): stub\n", hIMC, lplf);
788 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
789 return FALSE;
792 /***********************************************************************
793 * ImmGetCompositionFontW (IMM32.@)
795 BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
797 FIXME("(%p, %p): stub\n", hIMC, lplf);
798 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
799 return FALSE;
802 /***********************************************************************
803 * ImmGetCompositionStringA (IMM32.@)
805 LONG WINAPI ImmGetCompositionStringA(
806 HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
808 CHAR *buf;
809 LONG rc = 0;
810 InputContextData *data = (InputContextData*)hIMC;
811 LPCOMPOSITIONSTRING compstr;
812 LPBYTE compdata;
814 TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen);
816 if (!data)
817 return FALSE;
819 if (!data->IMC.hCompStr)
820 return FALSE;
822 compdata = ImmLockIMCC(data->IMC.hCompStr);
823 compstr = (LPCOMPOSITIONSTRING)compdata;
825 if (dwIndex == GCS_RESULTSTR && compstr->dwResultStrLen > 0 &&
826 compstr->dwResultStrOffset > 0)
828 LPWSTR ResultStr = (LPWSTR)(compdata + compstr->dwResultStrOffset);
830 TRACE("GSC_RESULTSTR %p %i\n",ResultStr,
831 compstr->dwResultStrLen);
833 buf = HeapAlloc( GetProcessHeap(), 0, compstr->dwResultStrLen * 3 );
834 rc = WideCharToMultiByte(CP_ACP, 0, ResultStr,
835 compstr->dwResultStrLen , buf,
836 compstr->dwResultStrLen * 3, NULL, NULL);
837 if (dwBufLen >= rc)
838 memcpy(lpBuf,buf,rc);
840 data->bRead = TRUE;
841 HeapFree( GetProcessHeap(), 0, buf );
843 else if (dwIndex == GCS_COMPSTR && compstr->dwCompStrLen > 0 &&
844 compstr->dwCompStrOffset > 0)
846 LPWSTR CompString = (LPWSTR)(compdata + compstr->dwCompStrOffset);
848 TRACE("GSC_COMPSTR %p %i\n", CompString, compstr->dwCompStrLen);
850 buf = HeapAlloc( GetProcessHeap(), 0, compstr->dwCompStrLen * 3 );
851 rc = WideCharToMultiByte(CP_ACP, 0, CompString,
852 compstr->dwCompStrLen, buf,
853 compstr->dwCompStrLen * 3, NULL, NULL);
854 if (dwBufLen >= rc)
855 memcpy(lpBuf,buf,rc);
856 HeapFree( GetProcessHeap(), 0, buf );
858 else if (dwIndex == GCS_COMPATTR && compstr->dwCompAttrLen > 0 &&
859 compstr->dwCompAttrOffset > 0)
861 LPWSTR Compattr = (LPWSTR)(compdata + compstr->dwCompAttrOffset);
862 TRACE("GSC_COMPATTR %p %i\n", Compattr , compstr->dwCompAttrLen);
864 rc = compstr->dwCompAttrLen;
865 if (dwBufLen >= rc)
866 memcpy(lpBuf,Compattr,rc);
868 else if (dwIndex == GCS_COMPCLAUSE && compstr->dwCompClauseLen > 0 &&
869 compstr->dwCompClauseOffset > 0)
871 LPWSTR Compclause = (LPWSTR)(compdata + compstr->dwCompClauseOffset);
872 TRACE("GSC_COMPCLAUSE %p %i\n", Compclause, compstr->dwCompClauseLen);
874 rc = compstr->dwCompClauseLen;
875 if (dwBufLen >= compstr->dwCompClauseLen)
876 memcpy(lpBuf,Compclause,rc);
878 else if (dwIndex == GCS_RESULTCLAUSE && compstr->dwResultClauseLen > 0 &&
879 compstr->dwResultClauseOffset > 0)
881 LPWSTR Resultclause = (LPWSTR)(compdata + compstr->dwResultClauseOffset);
882 TRACE("GSC_RESULTCLAUSE %p %i\n", Resultclause, compstr->dwResultClauseLen);
884 rc = compstr->dwResultClauseLen;
885 if (dwBufLen >= compstr->dwResultClauseLen)
886 memcpy(lpBuf,Resultclause,rc);
888 else if (dwIndex == GCS_CURSORPOS)
890 TRACE("GSC_CURSORPOS\n");
891 rc = compstr->dwCursorPos;
893 else if (dwIndex == GCS_DELTASTART)
895 TRACE("GCS_DELTASTART\n");
896 rc = compstr->dwDeltaStart;
898 else
900 FIXME("Unhandled index 0x%x\n",dwIndex);
903 ImmUnlockIMCC(data->IMC.hCompStr);
905 return rc;
908 /***********************************************************************
909 * ImmGetCompositionStringW (IMM32.@)
911 LONG WINAPI ImmGetCompositionStringW(
912 HIMC hIMC, DWORD dwIndex,
913 LPVOID lpBuf, DWORD dwBufLen)
915 LONG rc = 0;
916 InputContextData *data = (InputContextData*)hIMC;
917 LPCOMPOSITIONSTRING compstr;
918 LPBYTE compdata;
920 TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen);
922 if (!data)
923 return FALSE;
925 if (!data->IMC.hCompStr)
926 return FALSE;
928 compdata = ImmLockIMCC(data->IMC.hCompStr);
929 compstr = (LPCOMPOSITIONSTRING)compdata;
931 if (dwIndex == GCS_RESULTSTR && compstr->dwResultStrLen > 0 &&
932 compstr->dwResultStrOffset > 0)
934 LPWSTR ResultStr = (LPWSTR)(compdata + compstr->dwResultStrOffset);
935 data->bRead = TRUE;
936 rc = compstr->dwResultStrLen * sizeof(WCHAR);
938 if (dwBufLen >= rc)
939 memcpy(lpBuf,ResultStr,rc);
941 else if (dwIndex == GCS_RESULTREADSTR && compstr->dwResultReadStrLen > 0 &&
942 compstr->dwResultReadStrOffset > 0)
944 LPWSTR ResultReadString = (LPWSTR)(compdata + compstr->dwResultReadStrOffset);
946 rc = compstr->dwResultReadStrLen * sizeof(WCHAR);
947 if (dwBufLen >= rc)
948 memcpy(lpBuf,ResultReadString,rc);
950 else if (dwIndex == GCS_COMPSTR && compstr->dwCompStrLen > 0 &&
951 compstr->dwCompStrOffset > 0)
953 LPWSTR CompString = (LPWSTR)(compdata + compstr->dwCompStrOffset);
954 rc = compstr->dwCompStrLen * sizeof(WCHAR);
955 if (dwBufLen >= rc)
956 memcpy(lpBuf,CompString,rc);
958 else if (dwIndex == GCS_COMPATTR && compstr->dwCompAttrLen > 0 &&
959 compstr->dwCompAttrOffset > 0)
962 LPWSTR Compattr = (LPWSTR)(compdata + compstr->dwCompAttrOffset);
964 rc = compstr->dwCompAttrLen;
965 if (dwBufLen >= rc)
966 memcpy(lpBuf,Compattr,rc);
968 else if (dwIndex == GCS_COMPCLAUSE && compstr->dwCompClauseLen > 0 &&
969 compstr->dwCompClauseOffset > 0)
971 LPWSTR Compclause = (LPWSTR)(compdata + compstr->dwCompClauseOffset);
973 rc = compstr->dwCompClauseLen;
974 if (dwBufLen >= compstr->dwCompClauseLen)
975 memcpy(lpBuf,Compclause,rc);
977 else if (dwIndex == GCS_COMPREADSTR && compstr->dwCompReadStrLen > 0 &&
978 compstr->dwCompReadStrOffset > 0)
980 LPWSTR CompReadString = (LPWSTR)(compdata + compstr->dwCompReadStrOffset);
982 rc = compstr->dwCompReadStrLen * sizeof(WCHAR);
984 if (dwBufLen >= rc)
985 memcpy(lpBuf,CompReadString,rc);
987 else if (dwIndex == GCS_CURSORPOS)
989 TRACE("GSC_CURSORPOS\n");
990 rc = compstr->dwCursorPos;
992 else if (dwIndex == GCS_DELTASTART)
994 TRACE("GCS_DELTASTART\n");
995 rc = compstr->dwDeltaStart;
997 else
999 FIXME("Unhandled index 0x%x\n",dwIndex);
1002 ImmUnlockIMCC(data->IMC.hCompStr);
1004 return rc;
1007 /***********************************************************************
1008 * ImmGetCompositionWindow (IMM32.@)
1010 BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
1012 InputContextData *data = (InputContextData*)hIMC;
1014 TRACE("(%p, %p)\n", hIMC, lpCompForm);
1016 if (!data)
1017 return FALSE;
1019 *lpCompForm = data->IMC.cfCompForm;
1020 return 1;
1023 /***********************************************************************
1024 * ImmGetContext (IMM32.@)
1027 HIMC WINAPI ImmGetContext(HWND hWnd)
1029 TRACE("%p\n", hWnd);
1031 if (!root_context)
1032 return NULL;
1034 root_context->IMC.hWnd = hWnd;
1035 return (HIMC)root_context;
1038 /***********************************************************************
1039 * ImmGetConversionListA (IMM32.@)
1041 DWORD WINAPI ImmGetConversionListA(
1042 HKL hKL, HIMC hIMC,
1043 LPCSTR pSrc, LPCANDIDATELIST lpDst,
1044 DWORD dwBufLen, UINT uFlag)
1046 FIXME("(%p, %p, %s, %p, %d, %d): stub\n",
1047 hKL, hIMC, debugstr_a(pSrc), lpDst, dwBufLen, uFlag
1049 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1050 return 0;
1053 /***********************************************************************
1054 * ImmGetConversionListW (IMM32.@)
1056 DWORD WINAPI ImmGetConversionListW(
1057 HKL hKL, HIMC hIMC,
1058 LPCWSTR pSrc, LPCANDIDATELIST lpDst,
1059 DWORD dwBufLen, UINT uFlag)
1061 FIXME("(%p, %p, %s, %p, %d, %d): stub\n",
1062 hKL, hIMC, debugstr_w(pSrc), lpDst, dwBufLen, uFlag
1064 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1065 return 0;
1068 /***********************************************************************
1069 * ImmGetConversionStatus (IMM32.@)
1071 BOOL WINAPI ImmGetConversionStatus(
1072 HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence)
1074 TRACE("(%p, %p, %p): best guess\n", hIMC, lpfdwConversion, lpfdwSentence);
1075 if (lpfdwConversion)
1076 *lpfdwConversion = IME_CMODE_NATIVE;
1077 if (lpfdwSentence)
1078 *lpfdwSentence = IME_SMODE_NONE;
1079 return TRUE;
1082 /***********************************************************************
1083 * ImmGetDefaultIMEWnd (IMM32.@)
1085 HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
1087 static int shown = 0;
1089 if (!shown) {
1090 FIXME("(%p - %p %p ): semi-stub\n", hWnd,hwndDefault, root_context);
1091 shown = 1;
1094 if (hwndDefault == NULL)
1096 static const WCHAR the_name[] = {'I','M','E','\0'};
1098 IMM_Register();
1099 hwndDefault = CreateWindowExW( WS_EX_TOOLWINDOW, WC_IMECLASSNAME,
1100 the_name, WS_POPUP, 0, 0, 1, 1, 0, 0,
1101 hImeInst, 0);
1103 TRACE("Default created (%p)\n",hwndDefault);
1106 return hwndDefault;
1109 /***********************************************************************
1110 * ImmGetDescriptionA (IMM32.@)
1112 UINT WINAPI ImmGetDescriptionA(
1113 HKL hKL, LPSTR lpszDescription, UINT uBufLen)
1115 WCHAR *buf;
1116 DWORD len;
1118 TRACE("%p %p %d\n", hKL, lpszDescription, uBufLen);
1120 /* find out how many characters in the unicode buffer */
1121 len = ImmGetDescriptionW( hKL, NULL, 0 );
1123 /* allocate a buffer of that size */
1124 buf = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof (WCHAR) );
1125 if( !buf )
1126 return 0;
1128 /* fetch the unicode buffer */
1129 len = ImmGetDescriptionW( hKL, buf, len + 1 );
1131 /* convert it back to ASCII */
1132 len = WideCharToMultiByte( CP_ACP, 0, buf, len + 1,
1133 lpszDescription, uBufLen, NULL, NULL );
1135 HeapFree( GetProcessHeap(), 0, buf );
1137 return len;
1140 /***********************************************************************
1141 * ImmGetDescriptionW (IMM32.@)
1143 UINT WINAPI ImmGetDescriptionW(HKL hKL, LPWSTR lpszDescription, UINT uBufLen)
1145 static const WCHAR name[] = { 'W','i','n','e',' ','X','I','M',0 };
1147 FIXME("(%p, %p, %d): semi stub\n", hKL, lpszDescription, uBufLen);
1149 if (!uBufLen) return lstrlenW( name );
1150 lstrcpynW( lpszDescription, name, uBufLen );
1151 return lstrlenW( lpszDescription );
1154 /***********************************************************************
1155 * ImmGetGuideLineA (IMM32.@)
1157 DWORD WINAPI ImmGetGuideLineA(
1158 HIMC hIMC, DWORD dwIndex, LPSTR lpBuf, DWORD dwBufLen)
1160 FIXME("(%p, %d, %s, %d): stub\n",
1161 hIMC, dwIndex, debugstr_a(lpBuf), dwBufLen
1163 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1164 return 0;
1167 /***********************************************************************
1168 * ImmGetGuideLineW (IMM32.@)
1170 DWORD WINAPI ImmGetGuideLineW(HIMC hIMC, DWORD dwIndex, LPWSTR lpBuf, DWORD dwBufLen)
1172 FIXME("(%p, %d, %s, %d): stub\n",
1173 hIMC, dwIndex, debugstr_w(lpBuf), dwBufLen
1175 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1176 return 0;
1179 /***********************************************************************
1180 * ImmGetIMEFileNameA (IMM32.@)
1182 UINT WINAPI ImmGetIMEFileNameA( HKL hKL, LPSTR lpszFileName, UINT uBufLen)
1184 LPWSTR bufW = NULL;
1185 UINT wBufLen = uBufLen;
1186 UINT rc;
1188 if (uBufLen && lpszFileName)
1189 bufW = HeapAlloc(GetProcessHeap(),0,uBufLen * sizeof(WCHAR));
1190 else /* We need this to get the number of byte required */
1192 bufW = HeapAlloc(GetProcessHeap(),0,MAX_PATH * sizeof(WCHAR));
1193 wBufLen = MAX_PATH;
1196 rc = ImmGetIMEFileNameW(hKL,bufW,wBufLen);
1198 if (rc > 0)
1200 if (uBufLen && lpszFileName)
1201 rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, lpszFileName,
1202 uBufLen, NULL, NULL);
1203 else /* get the length */
1204 rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL,
1205 NULL);
1208 HeapFree(GetProcessHeap(),0,bufW);
1209 return rc;
1212 /***********************************************************************
1213 * ImmGetIMEFileNameW (IMM32.@)
1215 UINT WINAPI ImmGetIMEFileNameW(HKL hKL, LPWSTR lpszFileName, UINT uBufLen)
1217 static const WCHAR szImeFileW[] = {'I','m','e',' ','F','i','l','e',0};
1218 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};
1220 HKEY hkey;
1221 DWORD length;
1222 DWORD rc;
1223 WCHAR regKey[sizeof(fmt)/sizeof(WCHAR)+8];
1225 wsprintfW( regKey, fmt, (unsigned)hKL );
1226 rc = RegOpenKeyW( HKEY_LOCAL_MACHINE, regKey, &hkey);
1227 if (rc != ERROR_SUCCESS)
1229 SetLastError(rc);
1230 return 0;
1233 length = 0;
1234 rc = RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, NULL, &length);
1236 if (rc != ERROR_SUCCESS)
1238 RegCloseKey(hkey);
1239 SetLastError(rc);
1240 return 0;
1242 if (length > uBufLen * sizeof(WCHAR) || !lpszFileName)
1244 RegCloseKey(hkey);
1245 if (lpszFileName)
1247 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1248 return 0;
1250 else
1251 return length / sizeof(WCHAR);
1254 RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, lpszFileName, &length);
1256 RegCloseKey(hkey);
1258 return length / sizeof(WCHAR);
1261 /***********************************************************************
1262 * ImmGetOpenStatus (IMM32.@)
1264 BOOL WINAPI ImmGetOpenStatus(HIMC hIMC)
1266 InputContextData *data = (InputContextData*)hIMC;
1268 if (!data)
1269 return FALSE;
1270 FIXME("(%p): semi-stub\n", hIMC);
1272 return data->IMC.fOpen;
1275 /***********************************************************************
1276 * ImmGetProperty (IMM32.@)
1278 DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex)
1280 DWORD rc = 0;
1281 TRACE("(%p, %d)\n", hKL, fdwIndex);
1283 switch (fdwIndex)
1285 case IGP_PROPERTY:
1286 TRACE("(%s)\n", "IGP_PROPERTY");
1287 rc = IME_PROP_UNICODE | IME_PROP_AT_CARET;
1288 break;
1289 case IGP_CONVERSION:
1290 FIXME("(%s)\n", "IGP_CONVERSION");
1291 rc = IME_CMODE_NATIVE;
1292 break;
1293 case IGP_SENTENCE:
1294 FIXME("%s)\n", "IGP_SENTENCE");
1295 rc = IME_SMODE_AUTOMATIC;
1296 break;
1297 case IGP_SETCOMPSTR:
1298 TRACE("(%s)\n", "IGP_SETCOMPSTR");
1299 rc = 0;
1300 break;
1301 case IGP_SELECT:
1302 TRACE("(%s)\n", "IGP_SELECT");
1303 rc = SELECT_CAP_CONVERSION | SELECT_CAP_SENTENCE;
1304 break;
1305 case IGP_GETIMEVERSION:
1306 TRACE("(%s)\n", "IGP_GETIMEVERSION");
1307 rc = IMEVER_0400;
1308 break;
1309 case IGP_UI:
1310 TRACE("(%s)\n", "IGP_UI");
1311 rc = 0;
1312 break;
1313 default:
1314 rc = 0;
1316 return rc;
1319 /***********************************************************************
1320 * ImmGetRegisterWordStyleA (IMM32.@)
1322 UINT WINAPI ImmGetRegisterWordStyleA(
1323 HKL hKL, UINT nItem, LPSTYLEBUFA lpStyleBuf)
1325 FIXME("(%p, %d, %p): stub\n", hKL, nItem, lpStyleBuf);
1326 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1327 return 0;
1330 /***********************************************************************
1331 * ImmGetRegisterWordStyleW (IMM32.@)
1333 UINT WINAPI ImmGetRegisterWordStyleW(
1334 HKL hKL, UINT nItem, LPSTYLEBUFW lpStyleBuf)
1336 FIXME("(%p, %d, %p): stub\n", hKL, nItem, lpStyleBuf);
1337 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1338 return 0;
1341 /***********************************************************************
1342 * ImmGetStatusWindowPos (IMM32.@)
1344 BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
1346 FIXME("(%p, %p): stub\n", hIMC, lpptPos);
1347 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1348 return FALSE;
1351 /***********************************************************************
1352 * ImmGetVirtualKey (IMM32.@)
1354 UINT WINAPI ImmGetVirtualKey(HWND hWnd)
1356 OSVERSIONINFOA version;
1357 FIXME("(%p): stub\n", hWnd);
1358 GetVersionExA( &version );
1359 switch(version.dwPlatformId)
1361 case VER_PLATFORM_WIN32_WINDOWS:
1362 return VK_PROCESSKEY;
1363 case VER_PLATFORM_WIN32_NT:
1364 return 0;
1365 default:
1366 FIXME("%d not supported\n",version.dwPlatformId);
1367 return VK_PROCESSKEY;
1371 /***********************************************************************
1372 * ImmInstallIMEA (IMM32.@)
1374 HKL WINAPI ImmInstallIMEA(
1375 LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText)
1377 FIXME("(%s, %s): stub\n",
1378 debugstr_a(lpszIMEFileName), debugstr_a(lpszLayoutText)
1380 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1381 return NULL;
1384 /***********************************************************************
1385 * ImmInstallIMEW (IMM32.@)
1387 HKL WINAPI ImmInstallIMEW(
1388 LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText)
1390 FIXME("(%s, %s): stub\n",
1391 debugstr_w(lpszIMEFileName), debugstr_w(lpszLayoutText)
1393 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1394 return NULL;
1397 /***********************************************************************
1398 * ImmIsIME (IMM32.@)
1400 BOOL WINAPI ImmIsIME(HKL hKL)
1402 TRACE("(%p): semi-stub\n", hKL);
1404 * FIXME: Dead key locales will return TRUE here when they should not
1405 * There is probably a more proper way to check this.
1407 return (root_context != NULL);
1410 /***********************************************************************
1411 * ImmIsUIMessageA (IMM32.@)
1413 BOOL WINAPI ImmIsUIMessageA(
1414 HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1416 BOOL rc = FALSE;
1418 TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam);
1419 if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
1420 (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP) ||
1421 (msg == WM_MSIME_SERVICE) ||
1422 (msg == WM_MSIME_RECONVERTOPTIONS) ||
1423 (msg == WM_MSIME_MOUSE) ||
1424 (msg == WM_MSIME_RECONVERTREQUEST) ||
1425 (msg == WM_MSIME_RECONVERT) ||
1426 (msg == WM_MSIME_QUERYPOSITION) ||
1427 (msg == WM_MSIME_DOCUMENTFEED))
1430 if (!hwndDefault)
1431 ImmGetDefaultIMEWnd(NULL);
1433 if (hWndIME == NULL)
1434 PostMessageA(hwndDefault, msg, wParam, lParam);
1436 rc = TRUE;
1438 return rc;
1441 /***********************************************************************
1442 * ImmIsUIMessageW (IMM32.@)
1444 BOOL WINAPI ImmIsUIMessageW(
1445 HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1447 BOOL rc = FALSE;
1448 TRACE("(%p, %d, %ld, %ld): stub\n", hWndIME, msg, wParam, lParam);
1449 if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
1450 (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP) ||
1451 (msg == WM_MSIME_SERVICE) ||
1452 (msg == WM_MSIME_RECONVERTOPTIONS) ||
1453 (msg == WM_MSIME_MOUSE) ||
1454 (msg == WM_MSIME_RECONVERTREQUEST) ||
1455 (msg == WM_MSIME_RECONVERT) ||
1456 (msg == WM_MSIME_QUERYPOSITION) ||
1457 (msg == WM_MSIME_DOCUMENTFEED))
1458 rc = TRUE;
1459 return rc;
1462 /***********************************************************************
1463 * ImmNotifyIME (IMM32.@)
1465 BOOL WINAPI ImmNotifyIME(
1466 HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
1468 BOOL rc = FALSE;
1470 TRACE("(%p, %d, %d, %d)\n",
1471 hIMC, dwAction, dwIndex, dwValue);
1473 if (!root_context)
1474 return rc;
1476 switch(dwAction)
1478 case NI_CHANGECANDIDATELIST:
1479 FIXME("%s\n","NI_CHANGECANDIDATELIST");
1480 break;
1481 case NI_CLOSECANDIDATE:
1482 FIXME("%s\n","NI_CLOSECANDIDATE");
1483 break;
1484 case NI_COMPOSITIONSTR:
1485 switch (dwIndex)
1487 case CPS_CANCEL:
1488 TRACE("%s - %s\n","NI_COMPOSITIONSTR","CPS_CANCEL");
1490 BOOL send;
1491 LPCOMPOSITIONSTRING lpCompStr;
1493 if (pX11DRV_ForceXIMReset)
1494 pX11DRV_ForceXIMReset(root_context->IMC.hWnd);
1496 lpCompStr = ImmLockIMCC(root_context->IMC.hCompStr);
1497 send = (lpCompStr->dwCompStrLen != 0);
1498 ImmUnlockIMCC(root_context->IMC.hCompStr);
1500 ImmDestroyIMCC(root_context->IMC.hCompStr);
1501 root_context->IMC.hCompStr = ImmCreateBlankCompStr();
1503 if (send)
1504 ImmInternalPostIMEMessage(root_context, WM_IME_COMPOSITION, 0,
1505 GCS_COMPSTR);
1506 rc = TRUE;
1508 break;
1509 case CPS_COMPLETE:
1510 TRACE("%s - %s\n","NI_COMPOSITIONSTR","CPS_COMPLETE");
1511 if (hIMC != (HIMC)FROM_IME && pX11DRV_ForceXIMReset)
1512 pX11DRV_ForceXIMReset(root_context->IMC.hWnd);
1514 HIMCC newCompStr;
1515 DWORD cplen = 0;
1516 LPWSTR cpstr;
1517 LPCOMPOSITIONSTRING cs = NULL;
1518 LPBYTE cdata = NULL;
1520 /* clear existing result */
1521 newCompStr = updateResultStr(root_context->IMC.hCompStr, NULL, 0);
1522 ImmDestroyIMCC(root_context->IMC.hCompStr);
1523 root_context->IMC.hCompStr = newCompStr;
1525 if (root_context->IMC.hCompStr)
1527 cdata = ImmLockIMCC(root_context->IMC.hCompStr);
1528 cs = (LPCOMPOSITIONSTRING)cdata;
1529 cplen = cs->dwCompStrLen;
1530 cpstr = (LPWSTR)&(cdata[cs->dwCompStrOffset]);
1531 ImmUnlockIMCC(root_context->IMC.hCompStr);
1533 if (cplen > 0)
1535 WCHAR param = cpstr[0];
1536 newCompStr = updateResultStr(root_context->IMC.hCompStr, cpstr, cplen);
1537 ImmDestroyIMCC(root_context->IMC.hCompStr);
1538 root_context->IMC.hCompStr = newCompStr;
1539 newCompStr = updateCompStr(root_context->IMC.hCompStr, NULL, 0);
1540 ImmDestroyIMCC(root_context->IMC.hCompStr);
1541 root_context->IMC.hCompStr = newCompStr;
1543 root_context->bRead = FALSE;
1545 ImmInternalPostIMEMessage(root_context, WM_IME_COMPOSITION, 0,
1546 GCS_COMPSTR);
1548 ImmInternalPostIMEMessage(root_context, WM_IME_COMPOSITION,
1549 param,
1550 GCS_RESULTSTR|GCS_RESULTCLAUSE);
1553 ImmInternalPostIMEMessage(root_context, WM_IME_ENDCOMPOSITION, 0, 0);
1554 root_context->bInComposition = FALSE;
1556 break;
1557 case CPS_CONVERT:
1558 FIXME("%s - %s\n","NI_COMPOSITIONSTR","CPS_CONVERT");
1559 break;
1560 case CPS_REVERT:
1561 FIXME("%s - %s\n","NI_COMPOSITIONSTR","CPS_REVERT");
1562 break;
1563 default:
1564 ERR("%s - %s (%i)\n","NI_COMPOSITIONSTR","UNKNOWN",dwIndex);
1565 break;
1567 break;
1568 case NI_IMEMENUSELECTED:
1569 FIXME("%s\n", "NI_IMEMENUSELECTED");
1570 break;
1571 case NI_OPENCANDIDATE:
1572 FIXME("%s\n", "NI_OPENCANDIDATE");
1573 break;
1574 case NI_SELECTCANDIDATESTR:
1575 FIXME("%s\n", "NI_SELECTCANDIDATESTR");
1576 break;
1577 case NI_SETCANDIDATE_PAGESIZE:
1578 FIXME("%s\n", "NI_SETCANDIDATE_PAGESIZE");
1579 break;
1580 case NI_SETCANDIDATE_PAGESTART:
1581 FIXME("%s\n", "NI_SETCANDIDATE_PAGESTART");
1582 break;
1583 default:
1584 ERR("Unknown\n");
1587 return rc;
1590 /***********************************************************************
1591 * ImmRegisterWordA (IMM32.@)
1593 BOOL WINAPI ImmRegisterWordA(
1594 HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszRegister)
1596 FIXME("(%p, %s, %d, %s): stub\n",
1597 hKL, debugstr_a(lpszReading), dwStyle, debugstr_a(lpszRegister)
1599 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1600 return FALSE;
1603 /***********************************************************************
1604 * ImmRegisterWordW (IMM32.@)
1606 BOOL WINAPI ImmRegisterWordW(
1607 HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszRegister)
1609 FIXME("(%p, %s, %d, %s): stub\n",
1610 hKL, debugstr_w(lpszReading), dwStyle, debugstr_w(lpszRegister)
1612 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1613 return FALSE;
1616 /***********************************************************************
1617 * ImmReleaseContext (IMM32.@)
1619 BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC)
1621 static int shown = 0;
1623 if (!shown) {
1624 FIXME("(%p, %p): stub\n", hWnd, hIMC);
1625 shown = 1;
1627 return TRUE;
1630 /***********************************************************************
1631 * ImmSetCandidateWindow (IMM32.@)
1633 BOOL WINAPI ImmSetCandidateWindow(
1634 HIMC hIMC, LPCANDIDATEFORM lpCandidate)
1636 FIXME("(%p, %p): stub\n", hIMC, lpCandidate);
1637 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1638 return FALSE;
1641 /***********************************************************************
1642 * ImmSetCompositionFontA (IMM32.@)
1644 BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
1646 InputContextData *data = (InputContextData*)hIMC;
1647 TRACE("(%p, %p)\n", hIMC, lplf);
1649 if (!data)
1650 return FALSE;
1652 memcpy(&data->IMC.lfFont.W,lplf,sizeof(LOGFONTA));
1653 MultiByteToWideChar(CP_ACP, 0, lplf->lfFaceName, -1, data->IMC.lfFont.W.lfFaceName,
1654 LF_FACESIZE);
1656 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0);
1658 if (data->textfont)
1660 DeleteObject(data->textfont);
1661 data->textfont = NULL;
1664 data->textfont = CreateFontIndirectW(&data->IMC.lfFont.W);
1665 return TRUE;
1668 /***********************************************************************
1669 * ImmSetCompositionFontW (IMM32.@)
1671 BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
1673 InputContextData *data = (InputContextData*)hIMC;
1674 TRACE("(%p, %p)\n", hIMC, lplf);
1676 if (!data)
1677 return FALSE;
1679 data->IMC.lfFont.W = *lplf;
1680 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0);
1682 if (data->textfont)
1684 DeleteObject(data->textfont);
1685 data->textfont = NULL;
1687 data->textfont = CreateFontIndirectW(&data->IMC.lfFont.W);
1688 return TRUE;
1691 /***********************************************************************
1692 * ImmSetCompositionStringA (IMM32.@)
1694 BOOL WINAPI ImmSetCompositionStringA(
1695 HIMC hIMC, DWORD dwIndex,
1696 LPCVOID lpComp, DWORD dwCompLen,
1697 LPCVOID lpRead, DWORD dwReadLen)
1699 DWORD comp_len;
1700 DWORD read_len;
1701 WCHAR *CompBuffer = NULL;
1702 WCHAR *ReadBuffer = NULL;
1703 BOOL rc;
1705 TRACE("(%p, %d, %p, %d, %p, %d): stub\n",
1706 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
1708 comp_len = MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, NULL, 0);
1709 if (comp_len)
1711 CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len * sizeof(WCHAR));
1712 MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len);
1715 read_len = MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, NULL, 0);
1716 if (read_len)
1718 ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len * sizeof(WCHAR));
1719 MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len);
1722 rc = ImmSetCompositionStringW(hIMC, dwIndex, CompBuffer, comp_len,
1723 ReadBuffer, read_len);
1725 HeapFree(GetProcessHeap(), 0, CompBuffer);
1726 HeapFree(GetProcessHeap(), 0, ReadBuffer);
1728 return rc;
1731 /***********************************************************************
1732 * ImmSetCompositionStringW (IMM32.@)
1734 BOOL WINAPI ImmSetCompositionStringW(
1735 HIMC hIMC, DWORD dwIndex,
1736 LPCVOID lpComp, DWORD dwCompLen,
1737 LPCVOID lpRead, DWORD dwReadLen)
1739 DWORD flags = 0;
1740 WCHAR wParam = 0;
1742 TRACE("(%p, %d, %p, %d, %p, %d): stub\n",
1743 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
1746 if (hIMC != (HIMC)FROM_IME)
1747 FIXME("PROBLEM: This only sets the wine level string\n");
1750 * Explanation:
1751 * this sets the composition string in the imm32.dll level
1752 * of the composition buffer. we cannot manipulate the xim level
1753 * buffer, which means that once the xim level buffer changes again
1754 * any call to this function from the application will be lost
1757 if (lpRead && dwReadLen)
1758 FIXME("Reading string unimplemented\n");
1761 * app operating this api to also receive the message from xim
1764 if (dwIndex == SCS_SETSTR)
1766 HIMCC newCompStr;
1767 if (!root_context->bInComposition)
1769 ImmInternalPostIMEMessage(root_context, WM_IME_STARTCOMPOSITION, 0, 0);
1770 root_context->bInComposition = TRUE;
1773 flags = GCS_COMPSTR;
1775 if (dwCompLen && lpComp)
1777 newCompStr = updateCompStr(root_context->IMC.hCompStr, (LPWSTR)lpComp, dwCompLen / sizeof(WCHAR));
1778 ImmDestroyIMCC(root_context->IMC.hCompStr);
1779 root_context->IMC.hCompStr = newCompStr;
1781 wParam = ((const WCHAR*)lpComp)[0];
1782 flags |= GCS_COMPCLAUSE | GCS_COMPATTR | GCS_DELTASTART;
1784 else
1786 newCompStr = updateCompStr(root_context->IMC.hCompStr, NULL, 0);
1787 ImmDestroyIMCC(root_context->IMC.hCompStr);
1788 root_context->IMC.hCompStr = newCompStr;
1792 UpdateDataInDefaultIMEWindow(hwndDefault,FALSE);
1794 ImmInternalPostIMEMessage(root_context, WM_IME_COMPOSITION, wParam, flags);
1796 return TRUE;
1799 /***********************************************************************
1800 * ImmSetCompositionWindow (IMM32.@)
1802 BOOL WINAPI ImmSetCompositionWindow(
1803 HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
1805 BOOL reshow = FALSE;
1806 InputContextData *data = (InputContextData*)hIMC;
1808 TRACE("(%p, %p)\n", hIMC, lpCompForm);
1809 TRACE("\t%x, (%i,%i), (%i,%i - %i,%i)\n",lpCompForm->dwStyle,
1810 lpCompForm->ptCurrentPos.x, lpCompForm->ptCurrentPos.y, lpCompForm->rcArea.top,
1811 lpCompForm->rcArea.left, lpCompForm->rcArea.bottom, lpCompForm->rcArea.right);
1813 if (!data)
1814 return FALSE;
1816 data->IMC.cfCompForm = *lpCompForm;
1818 if (IsWindowVisible(hwndDefault))
1820 reshow = TRUE;
1821 ShowWindow(hwndDefault,SW_HIDE);
1824 /* FIXME: this is a partial stub */
1826 if (reshow)
1827 ShowWindow(hwndDefault,SW_SHOWNOACTIVATE);
1829 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONWINDOW, 0);
1830 return TRUE;
1833 /***********************************************************************
1834 * ImmSetConversionStatus (IMM32.@)
1836 BOOL WINAPI ImmSetConversionStatus(
1837 HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence)
1839 static int shown = 0;
1841 if (!shown) {
1842 FIXME("(%p, %d, %d): stub\n",
1843 hIMC, fdwConversion, fdwSentence
1845 shown = 1;
1847 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1848 return FALSE;
1851 /***********************************************************************
1852 * ImmSetOpenStatus (IMM32.@)
1854 BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen)
1856 InputContextData *data = (InputContextData*)hIMC;
1858 TRACE("%p %d\n", hIMC, fOpen);
1860 if (hIMC == (HIMC)FROM_IME)
1862 ImmInternalSetOpenStatus(fOpen);
1863 ImmInternalSendIMENotify(root_context, IMN_SETOPENSTATUS, 0);
1864 return TRUE;
1867 if (!data)
1868 return FALSE;
1870 if (fOpen != data->bInternalState)
1872 if (fOpen == FALSE && pX11DRV_ForceXIMReset)
1873 pX11DRV_ForceXIMReset(data->IMC.hWnd);
1875 if (fOpen == FALSE)
1876 ImmInternalPostIMEMessage(data, WM_IME_ENDCOMPOSITION,0,0);
1877 else
1878 ImmInternalPostIMEMessage(data, WM_IME_STARTCOMPOSITION,0,0);
1880 ImmInternalSetOpenStatus(fOpen);
1881 ImmInternalSetOpenStatus(!fOpen);
1883 if (data->IMC.fOpen == FALSE)
1884 ImmInternalPostIMEMessage(data, WM_IME_ENDCOMPOSITION,0,0);
1885 else
1886 ImmInternalPostIMEMessage(data, WM_IME_STARTCOMPOSITION,0,0);
1888 return FALSE;
1890 return TRUE;
1893 /***********************************************************************
1894 * ImmSetStatusWindowPos (IMM32.@)
1896 BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
1898 FIXME("(%p, %p): stub\n", hIMC, lpptPos);
1899 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1900 return FALSE;
1903 /***********************************************************************
1904 * ImmSimulateHotKey (IMM32.@)
1906 BOOL WINAPI ImmSimulateHotKey(HWND hWnd, DWORD dwHotKeyID)
1908 FIXME("(%p, %d): stub\n", hWnd, dwHotKeyID);
1909 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1910 return FALSE;
1913 /***********************************************************************
1914 * ImmUnregisterWordA (IMM32.@)
1916 BOOL WINAPI ImmUnregisterWordA(
1917 HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszUnregister)
1919 FIXME("(%p, %s, %d, %s): stub\n",
1920 hKL, debugstr_a(lpszReading), dwStyle, debugstr_a(lpszUnregister)
1922 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1923 return FALSE;
1926 /***********************************************************************
1927 * ImmUnregisterWordW (IMM32.@)
1929 BOOL WINAPI ImmUnregisterWordW(
1930 HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszUnregister)
1932 FIXME("(%p, %s, %d, %s): stub\n",
1933 hKL, debugstr_w(lpszReading), dwStyle, debugstr_w(lpszUnregister)
1935 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1936 return FALSE;
1939 /***********************************************************************
1940 * ImmGetImeMenuItemsA (IMM32.@)
1942 DWORD WINAPI ImmGetImeMenuItemsA( HIMC hIMC, DWORD dwFlags, DWORD dwType,
1943 LPIMEMENUITEMINFOA lpImeParentMenu, LPIMEMENUITEMINFOA lpImeMenu,
1944 DWORD dwSize)
1946 FIXME("(%p, %i, %i, %p, %p, %i): stub\n", hIMC, dwFlags, dwType,
1947 lpImeParentMenu, lpImeMenu, dwSize);
1948 return 0;
1951 /***********************************************************************
1952 * ImmGetImeMenuItemsW (IMM32.@)
1954 DWORD WINAPI ImmGetImeMenuItemsW( HIMC hIMC, DWORD dwFlags, DWORD dwType,
1955 LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu,
1956 DWORD dwSize)
1958 FIXME("(%p, %i, %i, %p, %p, %i): stub\n", hIMC, dwFlags, dwType,
1959 lpImeParentMenu, lpImeMenu, dwSize);
1960 return 0;
1963 /***********************************************************************
1964 * ImmLockIMC(IMM32.@)
1966 LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC)
1968 InputContextData *data = (InputContextData*)hIMC;
1970 if (!data)
1971 return NULL;
1972 data->dwLock++;
1973 return &data->IMC;
1976 /***********************************************************************
1977 * ImmUnlockIMC(IMM32.@)
1979 BOOL WINAPI ImmUnlockIMC(HIMC hIMC)
1981 InputContextData *data = (InputContextData*)hIMC;
1982 data->dwLock--;
1983 return (data->dwLock!=0);
1986 /***********************************************************************
1987 * ImmGetIMCLockCount(IMM32.@)
1989 DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC)
1991 InputContextData *data = (InputContextData*)hIMC;
1992 return data->dwLock;
1995 /***********************************************************************
1996 * ImmCreateIMCC(IMM32.@)
1998 HIMCC WINAPI ImmCreateIMCC(DWORD size)
2000 IMCCInternal *internal;
2001 int real_size = size + sizeof(IMCCInternal);
2003 internal = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, real_size);
2004 if (internal == NULL)
2005 return NULL;
2007 internal->dwSize = size;
2008 return (HIMCC)internal;
2011 /***********************************************************************
2012 * ImmDestroyIMCC(IMM32.@)
2014 HIMCC WINAPI ImmDestroyIMCC(HIMCC block)
2016 HeapFree(GetProcessHeap(),0,block);
2017 return NULL;
2020 /***********************************************************************
2021 * ImmLockIMCC(IMM32.@)
2023 LPVOID WINAPI ImmLockIMCC(HIMCC imcc)
2025 IMCCInternal *internal;
2026 internal = (IMCCInternal*) imcc;
2028 internal->dwLock ++;
2029 return internal + 1;
2032 /***********************************************************************
2033 * ImmUnlockIMCC(IMM32.@)
2035 BOOL WINAPI ImmUnlockIMCC(HIMCC imcc)
2037 IMCCInternal *internal;
2038 internal = (IMCCInternal*) imcc;
2040 internal->dwLock --;
2041 return (internal->dwLock!=0);
2044 /***********************************************************************
2045 * ImmGetIMCCLockCount(IMM32.@)
2047 DWORD WINAPI ImmGetIMCCLockCount(HIMCC imcc)
2049 IMCCInternal *internal;
2050 internal = (IMCCInternal*) imcc;
2052 return internal->dwLock;
2055 /***********************************************************************
2056 * ImmReSizeIMCC(IMM32.@)
2058 HIMCC WINAPI ImmReSizeIMCC(HIMCC imcc, DWORD size)
2060 IMCCInternal *internal,*newone;
2061 int real_size = size + sizeof(IMCCInternal);
2063 internal = (IMCCInternal*) imcc;
2065 newone = HeapReAlloc(GetProcessHeap(), 0, internal, real_size);
2066 newone->dwSize = size;
2068 return newone;
2071 /***********************************************************************
2072 * ImmGetIMCCSize(IMM32.@)
2074 DWORD WINAPI ImmGetIMCCSize(HIMCC imcc)
2076 IMCCInternal *internal;
2077 internal = (IMCCInternal*) imcc;
2079 return internal->dwSize;
2082 /***********************************************************************
2083 * ImmGenerateMessage(IMM32.@)
2085 BOOL WINAPI ImmGenerateMessage(HIMC hIMC)
2087 InputContextData *data = (InputContextData*)hIMC;
2089 TRACE("%i messages queued\n",data->IMC.dwNumMsgBuf);
2090 if (data->IMC.dwNumMsgBuf > 0)
2092 LPTRANSMSG lpTransMsg;
2093 INT i;
2095 lpTransMsg = (LPTRANSMSG)ImmLockIMCC(data->IMC.hMsgBuf);
2096 for (i = 0; i < data->IMC.dwNumMsgBuf; i++)
2097 ImmInternalPostIMEMessage(data, lpTransMsg[i].message, lpTransMsg[i].wParam, lpTransMsg[i].lParam);
2099 ImmUnlockIMCC(data->IMC.hMsgBuf);
2101 data->IMC.dwNumMsgBuf = 0;
2104 return TRUE;
2107 /*****
2108 * Internal functions to help with IME window management
2110 static void PaintDefaultIMEWnd(HWND hwnd)
2112 PAINTSTRUCT ps;
2113 RECT rect;
2114 HDC hdc = BeginPaint(hwnd,&ps);
2115 LPCOMPOSITIONSTRING compstr;
2116 LPBYTE compdata = NULL;
2117 HMONITOR monitor;
2118 MONITORINFO mon_info;
2119 INT offX=0, offY=0;
2121 GetClientRect(hwnd,&rect);
2122 FillRect(hdc, &rect, (HBRUSH)(COLOR_WINDOW + 1));
2124 compdata = ImmLockIMCC(root_context->IMC.hCompStr);
2125 compstr = (LPCOMPOSITIONSTRING)compdata;
2127 if (compstr->dwCompStrLen && compstr->dwCompStrOffset)
2129 SIZE size;
2130 POINT pt;
2131 HFONT oldfont = NULL;
2132 LPWSTR CompString;
2134 CompString = (LPWSTR)(compdata + compstr->dwCompStrOffset);
2135 if (root_context->textfont)
2136 oldfont = SelectObject(hdc,root_context->textfont);
2139 GetTextExtentPoint32W(hdc, CompString, compstr->dwCompStrLen, &size);
2140 pt.x = size.cx;
2141 pt.y = size.cy;
2142 LPtoDP(hdc,&pt,1);
2145 * How this works based on tests on windows:
2146 * CFS_POINT: then we start our window at the point and grow it as large
2147 * as it needs to be for the string.
2148 * CFS_RECT: we still use the ptCurrentPos as a starting point and our
2149 * window is only as large as we need for the string, but we do not
2150 * grow such that our window exceeds the given rect. Wrapping if
2151 * needed and possible. If our ptCurrentPos is outside of our rect
2152 * then no window is displayed.
2153 * CFS_FORCE_POSITION: appears to behave just like CFS_POINT
2154 * maybe becase the default MSIME does not do any IME adjusting.
2156 if (root_context->IMC.cfCompForm.dwStyle != CFS_DEFAULT)
2158 POINT cpt = root_context->IMC.cfCompForm.ptCurrentPos;
2159 ClientToScreen(root_context->IMC.hWnd,&cpt);
2160 rect.left = cpt.x;
2161 rect.top = cpt.y;
2162 rect.right = rect.left + pt.x;
2163 rect.bottom = rect.top + pt.y;
2164 monitor = MonitorFromPoint(cpt, MONITOR_DEFAULTTOPRIMARY);
2166 else /* CFS_DEFAULT */
2168 /* Windows places the default IME window in the bottom left */
2169 HWND target = root_context->IMC.hWnd;
2170 if (!target) target = GetFocus();
2172 GetWindowRect(target,&rect);
2173 rect.top = rect.bottom;
2174 rect.right = rect.left + pt.x + 20;
2175 rect.bottom = rect.top + pt.y + 20;
2176 offX=offY=10;
2177 monitor = MonitorFromWindow(target, MONITOR_DEFAULTTOPRIMARY);
2180 if (root_context->IMC.cfCompForm.dwStyle == CFS_RECT)
2182 RECT client;
2183 client =root_context->IMC.cfCompForm.rcArea;
2184 MapWindowPoints( root_context->IMC.hWnd, 0, (POINT *)&client, 2 );
2185 IntersectRect(&rect,&rect,&client);
2186 /* TODO: Wrap the input if needed */
2189 if (root_context->IMC.cfCompForm.dwStyle == CFS_DEFAULT)
2191 /* make sure we are on the desktop */
2192 mon_info.cbSize = sizeof(mon_info);
2193 GetMonitorInfoW(monitor, &mon_info);
2195 if (rect.bottom > mon_info.rcWork.bottom)
2197 int shift = rect.bottom - mon_info.rcWork.bottom;
2198 rect.top -= shift;
2199 rect.bottom -= shift;
2201 if (rect.left < 0)
2203 rect.right -= rect.left;
2204 rect.left = 0;
2206 if (rect.right > mon_info.rcWork.right)
2208 int shift = rect.right - mon_info.rcWork.right;
2209 rect.left -= shift;
2210 rect.right -= shift;
2214 SetWindowPos(hwnd, HWND_TOPMOST, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOACTIVATE);
2216 TextOutW(hdc, offX,offY, CompString, compstr->dwCompStrLen);
2218 if (oldfont)
2219 SelectObject(hdc,oldfont);
2222 ImmUnlockIMCC(root_context->IMC.hCompStr);
2224 EndPaint(hwnd,&ps);
2227 static void UpdateDataInDefaultIMEWindow(HWND hwnd, BOOL showable)
2229 LPCOMPOSITIONSTRING compstr;
2231 if (root_context->IMC.hCompStr)
2232 compstr = ImmLockIMCC(root_context->IMC.hCompStr);
2233 else
2234 compstr = NULL;
2236 if (compstr == NULL || compstr->dwCompStrLen == 0)
2237 ShowWindow(hwndDefault,SW_HIDE);
2238 else if (showable)
2239 ShowWindow(hwndDefault,SW_SHOWNOACTIVATE);
2241 RedrawWindow(hwnd,NULL,NULL,RDW_ERASENOW|RDW_INVALIDATE);
2243 if (compstr != NULL)
2244 ImmUnlockIMCC(root_context->IMC.hCompStr);
2248 * The window proc for the default IME window
2250 static LRESULT WINAPI IME_WindowProc(HWND hwnd, UINT msg, WPARAM wParam,
2251 LPARAM lParam)
2253 LRESULT rc = 0;
2255 TRACE("Incoming Message 0x%x (0x%08x, 0x%08x)\n", msg, (UINT)wParam,
2256 (UINT)lParam);
2258 switch(msg)
2260 case WM_PAINT:
2261 PaintDefaultIMEWnd(hwnd);
2262 return FALSE;
2264 case WM_NCCREATE:
2265 return TRUE;
2267 case WM_CREATE:
2268 SetWindowTextA(hwnd,"Wine Ime Active");
2269 return TRUE;
2271 case WM_SETFOCUS:
2272 if (wParam)
2273 SetFocus((HWND)wParam);
2274 else
2275 FIXME("Received focus, should never have focus\n");
2276 break;
2277 case WM_IME_COMPOSITION:
2278 TRACE("IME message %s, 0x%x, 0x%x (%i)\n",
2279 "WM_IME_COMPOSITION", (UINT)wParam, (UINT)lParam,
2280 root_context->bRead);
2281 if (lParam & GCS_RESULTSTR)
2282 IMM_PostResult(root_context);
2283 else
2284 UpdateDataInDefaultIMEWindow(hwnd,TRUE);
2285 break;
2286 case WM_IME_STARTCOMPOSITION:
2287 TRACE("IME message %s, 0x%x, 0x%x\n",
2288 "WM_IME_STARTCOMPOSITION", (UINT)wParam, (UINT)lParam);
2289 root_context->IMC.hWnd = GetFocus();
2290 ShowWindow(hwndDefault,SW_SHOWNOACTIVATE);
2291 break;
2292 case WM_IME_ENDCOMPOSITION:
2293 TRACE("IME message %s, 0x%x, 0x%x\n",
2294 "WM_IME_ENDCOMPOSITION", (UINT)wParam, (UINT)lParam);
2295 ShowWindow(hwndDefault,SW_HIDE);
2296 break;
2297 case WM_IME_SELECT:
2298 TRACE("IME message %s, 0x%x, 0x%x\n","WM_IME_SELECT",
2299 (UINT)wParam, (UINT)lParam);
2300 break;
2301 case WM_IME_CONTROL:
2302 TRACE("IME message %s, 0x%x, 0x%x\n","WM_IME_CONTROL",
2303 (UINT)wParam, (UINT)lParam);
2304 rc = 1;
2305 break;
2306 case WM_IME_NOTIFY:
2307 TRACE("!! IME NOTIFY\n");
2308 break;
2309 default:
2310 TRACE("Non-standard message 0x%x\n",msg);
2312 /* check the MSIME messages */
2313 if (msg == WM_MSIME_SERVICE)
2315 TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_SERVICE",
2316 (UINT)wParam, (UINT)lParam);
2317 rc = FALSE;
2319 else if (msg == WM_MSIME_RECONVERTOPTIONS)
2321 TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_RECONVERTOPTIONS",
2322 (UINT)wParam, (UINT)lParam);
2324 else if (msg == WM_MSIME_MOUSE)
2326 TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_MOUSE",
2327 (UINT)wParam, (UINT)lParam);
2329 else if (msg == WM_MSIME_RECONVERTREQUEST)
2331 TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_RECONVERTREQUEST",
2332 (UINT)wParam, (UINT)lParam);
2334 else if (msg == WM_MSIME_RECONVERT)
2336 TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_RECONVERT",
2337 (UINT)wParam, (UINT)lParam);
2339 else if (msg == WM_MSIME_QUERYPOSITION)
2341 TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_QUERYPOSITION",
2342 (UINT)wParam, (UINT)lParam);
2344 else if (msg == WM_MSIME_DOCUMENTFEED)
2346 TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_DOCUMENTFEED",
2347 (UINT)wParam, (UINT)lParam);
2349 /* DefWndProc if not an IME message */
2350 else if (!rc && !((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
2351 (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP)))
2352 rc = DefWindowProcW(hwnd,msg,wParam,lParam);
2354 return rc;