2 * Copyright 2023 RĂ©mi Bernon for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "imm_private.h"
24 WINE_DEFAULT_DEBUG_CHANNEL(imm
);
26 static const char *debugstr_imn( WPARAM wparam
)
30 case IMN_OPENSTATUSWINDOW
: return "IMN_OPENSTATUSWINDOW";
31 case IMN_CLOSESTATUSWINDOW
: return "IMN_CLOSESTATUSWINDOW";
32 case IMN_OPENCANDIDATE
: return "IMN_OPENCANDIDATE";
33 case IMN_CHANGECANDIDATE
: return "IMN_CHANGECANDIDATE";
34 case IMN_CLOSECANDIDATE
: return "IMN_CLOSECANDIDATE";
35 case IMN_SETCONVERSIONMODE
: return "IMN_SETCONVERSIONMODE";
36 case IMN_SETSENTENCEMODE
: return "IMN_SETSENTENCEMODE";
37 case IMN_SETOPENSTATUS
: return "IMN_SETOPENSTATUS";
38 case IMN_SETCANDIDATEPOS
: return "IMN_SETCANDIDATEPOS";
39 case IMN_SETCOMPOSITIONFONT
: return "IMN_SETCOMPOSITIONFONT";
40 case IMN_SETCOMPOSITIONWINDOW
: return "IMN_SETCOMPOSITIONWINDOW";
41 case IMN_GUIDELINE
: return "IMN_GUIDELINE";
42 case IMN_SETSTATUSWINDOWPOS
: return "IMN_SETSTATUSWINDOWPOS";
43 default: return wine_dbg_sprintf( "%#Ix", wparam
);
47 static const char *debugstr_imc( WPARAM wparam
)
51 case IMC_GETCANDIDATEPOS
: return "IMC_GETCANDIDATEPOS";
52 case IMC_SETCANDIDATEPOS
: return "IMC_SETCANDIDATEPOS";
53 case IMC_GETCOMPOSITIONFONT
: return "IMC_GETCOMPOSITIONFONT";
54 case IMC_SETCOMPOSITIONFONT
: return "IMC_SETCOMPOSITIONFONT";
55 case IMC_GETCOMPOSITIONWINDOW
: return "IMC_GETCOMPOSITIONWINDOW";
56 case IMC_SETCOMPOSITIONWINDOW
: return "IMC_SETCOMPOSITIONWINDOW";
57 case IMC_GETSTATUSWINDOWPOS
: return "IMC_GETSTATUSWINDOWPOS";
58 case IMC_SETSTATUSWINDOWPOS
: return "IMC_SETSTATUSWINDOWPOS";
59 case IMC_CLOSESTATUSWINDOW
: return "IMC_CLOSESTATUSWINDOW";
60 case IMC_OPENSTATUSWINDOW
: return "IMC_OPENSTATUSWINDOW";
61 default: return wine_dbg_sprintf( "%#Ix", wparam
);
65 static WCHAR
*input_context_get_comp_str( INPUTCONTEXT
*ctx
, BOOL result
, UINT
*length
)
67 COMPOSITIONSTRING
*string
;
71 if (!(string
= ImmLockIMCC( ctx
->hCompStr
))) return NULL
;
72 len
= result
? string
->dwResultStrLen
: string
->dwCompStrLen
;
73 off
= result
? string
->dwResultStrOffset
: string
->dwCompStrOffset
;
75 if (len
&& off
&& (text
= malloc( (len
+ 1) * sizeof(WCHAR
) )))
77 memcpy( text
, (BYTE
*)string
+ off
, len
* sizeof(WCHAR
) );
82 ImmUnlockIMCC( ctx
->hCompStr
);
86 static void input_context_set_comp_str( INPUTCONTEXT
*ctx
, const WCHAR
*str
, UINT len
)
88 COMPOSITIONSTRING
*compstr
;
93 size
= sizeof(*compstr
);
94 size
+= len
* sizeof(WCHAR
); /* GCS_COMPSTR */
95 size
+= len
; /* GCS_COMPSTRATTR */
96 size
+= 2 * sizeof(DWORD
); /* GCS_COMPSTRCLAUSE */
98 if (!(himcc
= ImmReSizeIMCC( ctx
->hCompStr
, size
)))
99 WARN( "Failed to resize input context composition string\n" );
100 else if (!(compstr
= ImmLockIMCC( (ctx
->hCompStr
= himcc
) )))
101 WARN( "Failed to lock input context composition string\n" );
104 memset( compstr
, 0, sizeof(*compstr
) );
105 compstr
->dwSize
= sizeof(*compstr
);
109 compstr
->dwCursorPos
= len
;
111 compstr
->dwCompStrLen
= len
;
112 compstr
->dwCompStrOffset
= compstr
->dwSize
;
113 dst
= (BYTE
*)compstr
+ compstr
->dwCompStrOffset
;
114 memcpy( dst
, str
, compstr
->dwCompStrLen
* sizeof(WCHAR
) );
115 compstr
->dwSize
+= compstr
->dwCompStrLen
* sizeof(WCHAR
);
117 compstr
->dwCompClauseLen
= 2 * sizeof(DWORD
);
118 compstr
->dwCompClauseOffset
= compstr
->dwSize
;
119 dst
= (BYTE
*)compstr
+ compstr
->dwCompClauseOffset
;
120 *((DWORD
*)dst
+ 0) = 0;
121 *((DWORD
*)dst
+ 1) = compstr
->dwCompStrLen
;
122 compstr
->dwSize
+= compstr
->dwCompClauseLen
;
124 compstr
->dwCompAttrLen
= compstr
->dwCompStrLen
;
125 compstr
->dwCompAttrOffset
= compstr
->dwSize
;
126 dst
= (BYTE
*)compstr
+ compstr
->dwCompAttrOffset
;
127 memset( dst
, ATTR_INPUT
, compstr
->dwCompAttrLen
);
128 compstr
->dwSize
+= compstr
->dwCompAttrLen
;
131 ImmUnlockIMCC( ctx
->hCompStr
);
135 static HFONT
input_context_select_ui_font( INPUTCONTEXT
*ctx
, HDC hdc
)
137 struct ime_private
*priv
;
139 if (!(priv
= ImmLockIMCC( ctx
->hPrivate
))) return NULL
;
140 if (priv
->textfont
) font
= SelectObject( hdc
, priv
->textfont
);
141 ImmUnlockIMCC( ctx
->hPrivate
);
145 static void ime_send_message( HIMC himc
, UINT message
, WPARAM wparam
, LPARAM lparam
)
151 if (!(ctx
= ImmLockIMC( himc
))) return;
152 if (!(himcc
= ImmReSizeIMCC( ctx
->hMsgBuf
, (ctx
->dwNumMsgBuf
+ 1) * sizeof(*msgs
) )))
153 WARN( "Failed to resize input context message buffer\n" );
154 else if (!(msgs
= ImmLockIMCC( (ctx
->hMsgBuf
= himcc
) )))
155 WARN( "Failed to lock input context message buffer\n" );
158 TRANSMSG msg
= {.message
= message
, .wParam
= wparam
, .lParam
= lparam
};
159 msgs
[ctx
->dwNumMsgBuf
++] = msg
;
160 ImmUnlockIMCC( ctx
->hMsgBuf
);
163 ImmUnlockIMC( himc
);
164 ImmGenerateMessage( himc
);
167 static UINT
ime_set_composition_status( HIMC himc
, BOOL composition
)
169 struct ime_private
*priv
;
173 if (!(ctx
= ImmLockIMC( himc
))) return 0;
174 if ((priv
= ImmLockIMCC( ctx
->hPrivate
)))
176 if (!priv
->bInComposition
&& composition
) msg
= WM_IME_STARTCOMPOSITION
;
177 else if (priv
->bInComposition
&& !composition
) msg
= WM_IME_ENDCOMPOSITION
;
178 priv
->bInComposition
= composition
;
179 ImmUnlockIMCC( ctx
->hPrivate
);
181 ImmUnlockIMC( himc
);
186 static void ime_ui_paint( HIMC himc
, HWND hwnd
)
192 MONITORINFO mon_info
;
198 if (!(ctx
= ImmLockIMC( himc
))) return;
200 hdc
= BeginPaint( hwnd
, &ps
);
202 GetClientRect( hwnd
, &rect
);
203 FillRect( hdc
, &rect
, (HBRUSH
)(COLOR_WINDOW
+ 1) );
206 if ((str
= input_context_get_comp_str( ctx
, FALSE
, &len
)))
208 HFONT font
= input_context_select_ui_font( ctx
, hdc
);
212 GetTextExtentPoint32W( hdc
, str
, len
, &size
);
215 LPtoDP( hdc
, &pt
, 1 );
218 * How this works based on tests on windows:
219 * CFS_POINT: then we start our window at the point and grow it as large
220 * as it needs to be for the string.
221 * CFS_RECT: we still use the ptCurrentPos as a starting point and our
222 * window is only as large as we need for the string, but we do not
223 * grow such that our window exceeds the given rect. Wrapping if
224 * needed and possible. If our ptCurrentPos is outside of our rect
225 * then no window is displayed.
226 * CFS_FORCE_POSITION: appears to behave just like CFS_POINT
227 * maybe because the default MSIME does not do any IME adjusting.
229 if (ctx
->cfCompForm
.dwStyle
!= CFS_DEFAULT
)
231 POINT cpt
= ctx
->cfCompForm
.ptCurrentPos
;
232 ClientToScreen( ctx
->hWnd
, &cpt
);
235 rect
.right
= rect
.left
+ pt
.x
;
236 rect
.bottom
= rect
.top
+ pt
.y
;
237 offset
.x
= offset
.y
= 0;
238 monitor
= MonitorFromPoint( cpt
, MONITOR_DEFAULTTOPRIMARY
);
240 else /* CFS_DEFAULT */
242 /* Windows places the default IME window in the bottom left */
243 HWND target
= ctx
->hWnd
;
244 if (!target
) target
= GetFocus();
246 GetWindowRect( target
, &rect
);
247 rect
.top
= rect
.bottom
;
248 rect
.right
= rect
.left
+ pt
.x
+ 20;
249 rect
.bottom
= rect
.top
+ pt
.y
+ 20;
250 offset
.x
= offset
.y
= 10;
251 monitor
= MonitorFromWindow( target
, MONITOR_DEFAULTTOPRIMARY
);
254 if (ctx
->cfCompForm
.dwStyle
== CFS_RECT
)
256 RECT client
= ctx
->cfCompForm
.rcArea
;
257 MapWindowPoints( ctx
->hWnd
, 0, (POINT
*)&client
, 2 );
258 IntersectRect( &rect
, &rect
, &client
);
259 DrawTextW( hdc
, str
, len
, &rect
, DT_WORDBREAK
| DT_CALCRECT
);
262 if (ctx
->cfCompForm
.dwStyle
== CFS_DEFAULT
)
264 /* make sure we are on the desktop */
265 mon_info
.cbSize
= sizeof(mon_info
);
266 GetMonitorInfoW( monitor
, &mon_info
);
268 if (rect
.bottom
> mon_info
.rcWork
.bottom
)
270 int shift
= rect
.bottom
- mon_info
.rcWork
.bottom
;
272 rect
.bottom
-= shift
;
276 rect
.right
-= rect
.left
;
279 if (rect
.right
> mon_info
.rcWork
.right
)
281 int shift
= rect
.right
- mon_info
.rcWork
.right
;
288 OffsetRect( &rect
, offset
.x
- rect
.left
, offset
.y
- rect
.top
);
289 DrawTextW( hdc
, str
, len
, &rect
, DT_WORDBREAK
);
291 if (font
) SelectObject( hdc
, font
);
295 EndPaint( hwnd
, &ps
);
296 ImmUnlockIMC( himc
);
298 if (!EqualRect( &rect
, &new_rect
))
299 SetWindowPos( hwnd
, HWND_TOPMOST
, new_rect
.left
, new_rect
.top
, new_rect
.right
- new_rect
.left
,
300 new_rect
.bottom
- new_rect
.top
, SWP_NOACTIVATE
);
303 static void ime_ui_update_window( INPUTCONTEXT
*ctx
, HWND hwnd
)
305 COMPOSITIONSTRING
*string
;
307 if (ctx
->hCompStr
) string
= ImmLockIMCC( ctx
->hCompStr
);
310 if (!string
|| string
->dwCompStrLen
== 0)
311 ShowWindow( hwnd
, SW_HIDE
);
314 ShowWindow( hwnd
, SW_SHOWNOACTIVATE
);
315 RedrawWindow( hwnd
, NULL
, NULL
, RDW_ERASENOW
| RDW_INVALIDATE
);
318 if (string
) ImmUnlockIMCC( ctx
->hCompStr
);
320 ctx
->hWnd
= GetFocus();
323 static void ime_ui_composition( HIMC himc
, HWND hwnd
, LPARAM lparam
)
326 if (lparam
& GCS_RESULTSTR
) return;
327 if (!(ctx
= ImmLockIMC( himc
))) return;
328 ime_ui_update_window( ctx
, hwnd
);
329 ImmUnlockIMC( himc
);
332 static void ime_ui_start_composition( HIMC himc
, HWND hwnd
)
335 if (!(ctx
= ImmLockIMC( himc
))) return;
336 ime_ui_update_window( ctx
, hwnd
);
337 ImmUnlockIMC( himc
);
340 static LRESULT WINAPI
ime_ui_window_proc( HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
342 HIMC himc
= (HIMC
)GetWindowLongPtrW( hwnd
, IMMGWL_IMC
);
345 TRACE( "hwnd %p, himc %p, msg %s, wparam %#Ix, lparam %#Ix\n",
346 hwnd
, himc
, debugstr_wm_ime(msg
), wparam
, lparam
);
352 struct ime_private
*priv
;
354 SetWindowTextA( hwnd
, "Wine Ime Active" );
356 if (!(ctx
= ImmLockIMC( himc
))) return TRUE
;
357 if ((priv
= ImmLockIMCC( ctx
->hPrivate
)))
359 priv
->hwndDefault
= hwnd
;
360 ImmUnlockIMCC( ctx
->hPrivate
);
362 ImmUnlockIMC( himc
);
366 ime_ui_paint( himc
, hwnd
);
369 if (wparam
) SetFocus( (HWND
)wparam
);
370 else FIXME( "Received focus, should never have focus\n" );
372 case WM_IME_COMPOSITION
:
373 ime_ui_composition( himc
, hwnd
, lparam
);
375 case WM_IME_STARTCOMPOSITION
:
376 ime_ui_start_composition( himc
, hwnd
);
378 case WM_IME_ENDCOMPOSITION
:
379 ShowWindow( hwnd
, SW_HIDE
);
382 FIXME( "hwnd %p, himc %p, msg %s, wparam %s, lparam %#Ix stub!\n", hwnd
, himc
,
383 debugstr_wm_ime(msg
), debugstr_imn(wparam
), lparam
);
386 FIXME( "hwnd %p, himc %p, msg %s, wparam %s, lparam %#Ix stub!\n", hwnd
, himc
,
387 debugstr_wm_ime(msg
), debugstr_imc(wparam
), lparam
);
391 return DefWindowProcW( hwnd
, msg
, wparam
, lparam
);
394 static WNDCLASSEXW ime_ui_class
=
396 .cbSize
= sizeof(WNDCLASSEXW
),
397 .style
= CS_GLOBALCLASS
| CS_IME
| CS_HREDRAW
| CS_VREDRAW
,
398 .lpfnWndProc
= ime_ui_window_proc
,
399 .cbWndExtra
= 2 * sizeof(LONG_PTR
),
400 .lpszClassName
= L
"Wine IME",
401 .hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1),
404 BOOL WINAPI
ImeInquire( IMEINFO
*info
, WCHAR
*ui_class
, DWORD flags
)
406 TRACE( "info %p, ui_class %p, flags %#lx\n", info
, ui_class
, flags
);
408 ime_ui_class
.hInstance
= imm32_module
;
409 ime_ui_class
.hCursor
= LoadCursorW( NULL
, (LPWSTR
)IDC_ARROW
);
410 ime_ui_class
.hIcon
= LoadIconW( NULL
, (LPWSTR
)IDI_APPLICATION
);
411 RegisterClassExW( &ime_ui_class
);
413 wcscpy( ui_class
, ime_ui_class
.lpszClassName
);
414 memset( info
, 0, sizeof(*info
) );
415 info
->dwPrivateDataSize
= sizeof(IMEPRIVATE
);
416 info
->fdwProperty
= IME_PROP_UNICODE
| IME_PROP_AT_CARET
;
417 info
->fdwConversionCaps
= IME_CMODE_NATIVE
| IME_CMODE_FULLSHAPE
;
418 info
->fdwSentenceCaps
= IME_SMODE_AUTOMATIC
;
419 info
->fdwUICaps
= UI_CAP_2700
;
420 /* Tell App we cannot accept ImeSetCompositionString calls */
421 info
->fdwSCSCaps
= 0;
422 info
->fdwSelectCaps
= SELECT_CAP_CONVERSION
;
427 BOOL WINAPI
ImeDestroy( UINT force
)
429 TRACE( "force %u\n", force
);
430 UnregisterClassW( ime_ui_class
.lpszClassName
, imm32_module
);
434 BOOL WINAPI
ImeSelect( HIMC himc
, BOOL select
)
436 FIXME( "himc %p, select %d semi-stub!\n", himc
, select
);
440 BOOL WINAPI
ImeSetActiveContext( HIMC himc
, BOOL flag
)
443 if (!once
++) FIXME( "himc %p, flag %#x stub!\n", himc
, flag
);
447 BOOL WINAPI
ImeProcessKey( HIMC himc
, UINT vkey
, LPARAM lparam
, BYTE
*state
)
449 struct ime_driver_call_params params
= {.himc
= himc
, .state
= state
};
453 TRACE( "himc %p, vkey %#x, lparam %#Ix, state %p\n", himc
, vkey
, lparam
, state
);
455 if (!(ctx
= ImmLockIMC( himc
))) return FALSE
;
456 ret
= NtUserMessageCall( ctx
->hWnd
, WINE_IME_PROCESS_KEY
, vkey
, lparam
, ¶ms
,
457 NtUserImeDriverCall
, FALSE
);
458 ImmUnlockIMC( himc
);
463 UINT WINAPI
ImeToAsciiEx( UINT vkey
, UINT vsc
, BYTE
*state
, TRANSMSGLIST
*msgs
, UINT flags
, HIMC himc
)
465 COMPOSITIONSTRING
*compstr
;
466 UINT size
, count
= 0;
470 TRACE( "vkey %#x, vsc %#x, state %p, msgs %p, flags %#x, himc %p\n",
471 vkey
, vsc
, state
, msgs
, flags
, himc
);
473 if (!(ctx
= ImmLockIMC( himc
))) return 0;
474 if (!(compstr
= ImmLockIMCC( ctx
->hCompStr
))) goto done
;
475 size
= compstr
->dwSize
;
479 struct ime_driver_call_params params
= {.himc
= himc
, .state
= state
};
482 ImmUnlockIMCC( ctx
->hCompStr
);
483 if (!(himcc
= ImmReSizeIMCC( ctx
->hCompStr
, size
))) goto done
;
484 if (!(compstr
= ImmLockIMCC( (ctx
->hCompStr
= himcc
) ))) goto done
;
486 params
.compstr
= compstr
;
487 status
= NtUserMessageCall( ctx
->hWnd
, WINE_IME_TO_ASCII_EX
, vkey
, vsc
, ¶ms
,
488 NtUserImeDriverCall
, FALSE
);
489 size
= compstr
->dwSize
;
490 } while (status
== STATUS_BUFFER_TOO_SMALL
);
492 if (status
) WARN( "WINE_IME_TO_ASCII_EX returned status %#lx\n", status
);
495 TRANSMSG status_msg
= {.message
= ime_set_composition_status( himc
, !!compstr
->dwCompStrOffset
)};
496 if (status_msg
.message
) msgs
->TransMsg
[count
++] = status_msg
;
498 if (compstr
->dwResultStrLen
)
500 const WCHAR
*result
= (WCHAR
*)((BYTE
*)compstr
+ compstr
->dwResultStrOffset
);
501 TRANSMSG msg
= {.message
= WM_IME_COMPOSITION
, .wParam
= result
[0], .lParam
= GCS_RESULTSTR
};
502 if (compstr
->dwResultClauseOffset
) msg
.lParam
|= GCS_RESULTCLAUSE
;
503 msgs
->TransMsg
[count
++] = msg
;
506 if (compstr
->dwCompStrLen
)
508 const WCHAR
*comp
= (WCHAR
*)((BYTE
*)compstr
+ compstr
->dwCompStrOffset
);
509 TRANSMSG msg
= {.message
= WM_IME_COMPOSITION
, .wParam
= comp
[0], .lParam
= GCS_COMPSTR
| GCS_CURSORPOS
| GCS_DELTASTART
};
510 if (compstr
->dwCompAttrOffset
) msg
.lParam
|= GCS_COMPATTR
;
511 if (compstr
->dwCompClauseOffset
) msg
.lParam
|= GCS_COMPCLAUSE
;
512 else msg
.lParam
|= CS_INSERTCHAR
|CS_NOMOVECARET
;
513 msgs
->TransMsg
[count
++] = msg
;
517 ImmUnlockIMCC( ctx
->hCompStr
);
520 if (count
>= msgs
->uMsgCount
) FIXME( "More than %u messages queued, messages possibly lost\n", msgs
->uMsgCount
);
521 else TRACE( "Returning %u messages queued\n", count
);
522 ImmUnlockIMC( himc
);
526 BOOL WINAPI
ImeConfigure( HKL hkl
, HWND hwnd
, DWORD mode
, void *data
)
528 FIXME( "hkl %p, hwnd %p, mode %lu, data %p stub!\n", hkl
, hwnd
, mode
, data
);
529 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
533 DWORD WINAPI
ImeConversionList( HIMC himc
, const WCHAR
*source
, CANDIDATELIST
*dest
, DWORD dest_len
, UINT flag
)
535 FIXME( "himc %p, source %s, dest %p, dest_len %lu, flag %#x stub!\n",
536 himc
, debugstr_w(source
), dest
, dest_len
, flag
);
537 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
541 BOOL WINAPI
ImeSetCompositionString( HIMC himc
, DWORD index
, const void *comp
, DWORD comp_len
,
542 const void *read
, DWORD read_len
)
546 FIXME( "himc %p, index %lu, comp %p, comp_len %lu, read %p, read_len %lu semi-stub!\n",
547 himc
, index
, comp
, comp_len
, read
, read_len
);
548 if (read
&& read_len
) FIXME( "Read string unimplemented\n" );
549 if (index
!= SCS_SETSTR
&& index
!= SCS_CHANGECLAUSE
&& index
!= SCS_CHANGEATTR
) return FALSE
;
551 if (!(ctx
= ImmLockIMC( himc
))) return FALSE
;
553 if (index
!= SCS_SETSTR
)
554 FIXME( "index %#lx not implemented\n", index
);
557 UINT msg
, flags
= GCS_COMPSTR
| GCS_COMPCLAUSE
| GCS_COMPATTR
| GCS_DELTASTART
| GCS_CURSORPOS
;
558 WCHAR wparam
= comp
&& comp_len
>= sizeof(WCHAR
) ? *(WCHAR
*)comp
: 0;
559 input_context_set_comp_str( ctx
, comp
, comp_len
/ sizeof(WCHAR
) );
560 if ((msg
= ime_set_composition_status( himc
, TRUE
))) ime_send_message( himc
, msg
, 0, 0 );
561 ime_send_message( himc
, WM_IME_COMPOSITION
, wparam
, flags
);
564 ImmUnlockIMC( himc
);
569 BOOL WINAPI
NotifyIME( HIMC himc
, DWORD action
, DWORD index
, DWORD value
)
571 struct ime_private
*priv
;
575 TRACE( "himc %p, action %#lx, index %#lx, value %#lx stub!\n", himc
, action
, index
, value
);
577 if (!(ctx
= ImmLockIMC( himc
))) return FALSE
;
581 case NI_CONTEXTUPDATED
:
584 case IMC_SETCOMPOSITIONFONT
:
585 if ((priv
= ImmLockIMCC( ctx
->hPrivate
)))
587 if (priv
->textfont
) DeleteObject( priv
->textfont
);
588 priv
->textfont
= CreateFontIndirectW( &ctx
->lfFont
.W
);
589 ImmUnlockIMCC( ctx
->hPrivate
);
592 case IMC_SETOPENSTATUS
:
595 input_context_set_comp_str( ctx
, NULL
, 0 );
596 if ((msg
= ime_set_composition_status( himc
, TRUE
))) ime_send_message( himc
, msg
, 0, 0 );
598 NtUserNotifyIMEStatus( ctx
->hWnd
, ctx
->fOpen
);
601 FIXME( "himc %p, action %#lx, index %#lx, value %#lx stub!\n", himc
, action
, index
, value
);
606 case NI_COMPOSITIONSTR
:
611 COMPOSITIONSTRING
*compstr
;
613 if (!(compstr
= ImmLockIMCC( ctx
->hCompStr
)))
614 WARN( "Failed to lock input context composition string\n" );
617 WCHAR wchr
= *(WCHAR
*)((BYTE
*)compstr
+ compstr
->dwCompStrOffset
);
618 COMPOSITIONSTRING tmp
= *compstr
;
621 memset( compstr
, 0, sizeof(*compstr
) );
622 compstr
->dwSize
= tmp
.dwSize
;
623 compstr
->dwResultStrLen
= tmp
.dwCompStrLen
;
624 compstr
->dwResultStrOffset
= tmp
.dwCompStrOffset
;
625 compstr
->dwResultClauseLen
= tmp
.dwCompClauseLen
;
626 compstr
->dwResultClauseOffset
= tmp
.dwCompClauseOffset
;
627 ImmUnlockIMCC( ctx
->hCompStr
);
629 if (tmp
.dwCompStrLen
) flags
|= GCS_RESULTSTR
;
630 if (tmp
.dwCompClauseLen
) flags
|= GCS_RESULTCLAUSE
;
631 if (flags
) ime_send_message( himc
, WM_IME_COMPOSITION
, wchr
, flags
);
634 ImmSetOpenStatus( himc
, FALSE
);
638 input_context_set_comp_str( ctx
, NULL
, 0 );
639 ImmSetOpenStatus( himc
, FALSE
);
642 FIXME( "himc %p, action %#lx, index %#lx, value %#lx stub!\n", himc
, action
, index
, value
);
648 FIXME( "himc %p, action %#lx, index %#lx, value %#lx stub!\n", himc
, action
, index
, value
);
652 ImmUnlockIMC( himc
);
656 LRESULT WINAPI
ImeEscape( HIMC himc
, UINT escape
, void *data
)
658 FIXME( "himc %p, escape %#x, data %p stub!\n", himc
, escape
, data
);
659 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
663 DWORD WINAPI
ImeGetImeMenuItems( HIMC himc
, DWORD flags
, DWORD type
, IMEMENUITEMINFOW
*parent
,
664 IMEMENUITEMINFOW
*menu
, DWORD size
)
666 FIXME( "himc %p, flags %#lx, type %lu, parent %p, menu %p, size %#lx stub!\n",
667 himc
, flags
, type
, parent
, menu
, size
);
668 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
672 BOOL WINAPI
ImeRegisterWord( const WCHAR
*reading
, DWORD style
, const WCHAR
*string
)
674 FIXME( "reading %s, style %lu, string %s stub!\n", debugstr_w(reading
), style
, debugstr_w(string
) );
675 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
679 UINT WINAPI
ImeGetRegisterWordStyle( UINT item
, STYLEBUFW
*style
)
681 FIXME( "item %u, style %p stub!\n", item
, style
);
682 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
686 BOOL WINAPI
ImeUnregisterWord( const WCHAR
*reading
, DWORD style
, const WCHAR
*string
)
688 FIXME( "reading %s, style %lu, string %s stub!\n", debugstr_w(reading
), style
, debugstr_w(string
) );
689 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
693 UINT WINAPI
ImeEnumRegisterWord( REGISTERWORDENUMPROCW proc
, const WCHAR
*reading
, DWORD style
,
694 const WCHAR
*string
, void *data
)
696 FIXME( "proc %p, reading %s, style %lu, string %s, data %p stub!\n",
697 proc
, debugstr_w(reading
), style
, debugstr_w(string
), data
);
698 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);