Mercurial > sdl-ios-xcode
comparison src/video/win32/SDL_win32keyboard.c @ 4759:863ba7d1f029
Large commit with initial reading string support, TSF UILess code, etc.
author | dewyatt |
---|---|
date | Tue, 03 Aug 2010 16:57:49 -0400 |
parents | 11b0a6a3eb4d |
children | c40027ee6d47 |
comparison
equal
deleted
inserted
replaced
4758:e2f4e31b41fc | 4759:863ba7d1f029 |
---|---|
24 #include "SDL_win32video.h" | 24 #include "SDL_win32video.h" |
25 | 25 |
26 #include "../../events/SDL_keyboard_c.h" | 26 #include "../../events/SDL_keyboard_c.h" |
27 #include "../../events/scancodes_win32.h" | 27 #include "../../events/scancodes_win32.h" |
28 | 28 |
29 #include <msctf.h> | |
30 #include <imm.h> | 29 #include <imm.h> |
30 #include <oleauto.h> | |
31 | |
32 static void IME_Init(SDL_VideoData *videodata, HWND hwnd); | |
33 static void IME_Enable(SDL_VideoData *videodata, HWND hwnd); | |
34 static void IME_Disable(SDL_VideoData *videodata, HWND hwnd); | |
35 static void IME_Quit(SDL_VideoData *videodata); | |
31 | 36 |
32 #ifndef MAPVK_VK_TO_VSC | 37 #ifndef MAPVK_VK_TO_VSC |
33 #define MAPVK_VK_TO_VSC 0 | 38 #define MAPVK_VK_TO_VSC 0 |
34 #endif | 39 #endif |
35 #ifndef MAPVK_VSC_TO_VK | 40 #ifndef MAPVK_VSC_TO_VK |
46 }; | 51 }; |
47 | 52 |
48 BYTE keypad_scancodes[10] = { | 53 BYTE keypad_scancodes[10] = { |
49 82, 79, 80, 81, 75, 76, 77, 71, 72, 73 | 54 82, 79, 80, 81, 75, 76, 77, 71, 72, 73 |
50 }; | 55 }; |
51 | |
52 void IME_Disable(SDL_VideoData *videodata, HWND hwnd); | |
53 void IME_Enable(SDL_VideoData *videodata, HWND hwnd); | |
54 void IME_Init(SDL_VideoData *videodata, HWND hwnd); | |
55 void IME_Quit(SDL_VideoData *videodata); | |
56 | 56 |
57 void | 57 void |
58 WIN_InitKeyboard(_THIS) | 58 WIN_InitKeyboard(_THIS) |
59 { | 59 { |
60 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; | 60 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; |
88 } | 88 } |
89 | 89 |
90 data->key_layout = win32_scancode_table; | 90 data->key_layout = win32_scancode_table; |
91 | 91 |
92 data->ime_com_initialized = SDL_FALSE; | 92 data->ime_com_initialized = SDL_FALSE; |
93 data->ime_thread_mgr = 0; | 93 data->ime_threadmgr = 0; |
94 data->ime_initialized = SDL_FALSE; | 94 data->ime_initialized = SDL_FALSE; |
95 data->ime_enabled = SDL_FALSE; | 95 data->ime_enabled = SDL_FALSE; |
96 data->ime_available = SDL_FALSE; | 96 data->ime_available = SDL_FALSE; |
97 data->ime_hwnd_main = 0; | 97 data->ime_hwnd_main = 0; |
98 data->ime_hwnd_current = 0; | 98 data->ime_hwnd_current = 0; |
99 data->ime_himc = 0; | 99 data->ime_himc = 0; |
100 data->ime_composition[0] = 0; | |
101 data->ime_readingstring[0] = 0; | |
102 data->ime_cursor = 0; | |
103 data->ime_hkl = 0; | |
104 data->ime_himm32 = 0; | |
105 data->GetReadingString = 0; | |
106 data->ShowReadingWindow = 0; | |
107 data->ImmLockIMC = 0; | |
108 data->ImmUnlockIMC = 0; | |
109 data->ImmLockIMCC = 0; | |
110 data->ImmUnlockIMCC = 0; | |
111 data->ime_uiless = SDL_FALSE; | |
112 data->ime_threadmgrex = 0; | |
113 data->ime_uielemsinkcookie = TF_INVALID_COOKIE; | |
114 data->ime_alpnsinkcookie = TF_INVALID_COOKIE; | |
115 data->ime_openmodesinkcookie = TF_INVALID_COOKIE; | |
116 data->ime_convmodesinkcookie = TF_INVALID_COOKIE; | |
117 data->ime_uielemsink = 0; | |
118 data->ime_ippasink = 0; | |
100 | 119 |
101 WIN_UpdateKeymap(); | 120 WIN_UpdateKeymap(); |
102 | 121 |
103 SDL_SetScancodeName(SDL_SCANCODE_APPLICATION, "Menu"); | 122 SDL_SetScancodeName(SDL_SCANCODE_APPLICATION, "Menu"); |
104 SDL_SetScancodeName(SDL_SCANCODE_LGUI, "Left Windows"); | 123 SDL_SetScancodeName(SDL_SCANCODE_LGUI, "Left Windows"); |
142 | 161 |
143 void | 162 void |
144 WIN_StartTextInput(_THIS) | 163 WIN_StartTextInput(_THIS) |
145 { | 164 { |
146 SDL_Window *window = SDL_GetKeyboardFocus(); | 165 SDL_Window *window = SDL_GetKeyboardFocus(); |
147 if (window) | 166 if (window) { |
148 { | |
149 HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd; | 167 HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd; |
150 SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata; | 168 SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata; |
151 IME_Init(videodata, hwnd); | 169 IME_Init(videodata, hwnd); |
152 IME_Enable(videodata, hwnd); | 170 IME_Enable(videodata, hwnd); |
153 } | 171 } |
155 | 173 |
156 void | 174 void |
157 WIN_StopTextInput(_THIS) | 175 WIN_StopTextInput(_THIS) |
158 { | 176 { |
159 SDL_Window *window = SDL_GetKeyboardFocus(); | 177 SDL_Window *window = SDL_GetKeyboardFocus(); |
160 if (window) | 178 if (window) { |
161 { | |
162 HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd; | 179 HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd; |
163 SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata; | 180 SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata; |
164 IME_Init(videodata, hwnd); | 181 IME_Init(videodata, hwnd); |
165 IME_Disable(videodata, hwnd); | 182 IME_Disable(videodata, hwnd); |
166 } | 183 } |
170 WIN_SetTextInputRect(_THIS, SDL_Rect *rect) | 187 WIN_SetTextInputRect(_THIS, SDL_Rect *rect) |
171 { | 188 { |
172 | 189 |
173 } | 190 } |
174 | 191 |
175 void | 192 #define LANG_CHT MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL) |
176 IME_Disable(SDL_VideoData *videodata, HWND hwnd) | 193 #define LANG_CHS MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED) |
177 { | 194 |
178 if (!videodata->ime_initialized || !videodata->ime_hwnd_current) | 195 #define MAKEIMEVERSION(major,minor) ((DWORD) (((BYTE)(major) << 24) | ((BYTE)(minor) << 16) )) |
179 return; | 196 #define IMEID_VER(id) ((id) & 0xffff0000) |
180 | 197 #define IMEID_LANG(id) ((id) & 0x0000ffff) |
181 if (videodata->ime_hwnd_current == videodata->ime_hwnd_main) | 198 |
182 ImmAssociateContext(videodata->ime_hwnd_current, NULL); | 199 #define CHT_HKL_DAYI ((HKL)0xE0060404) |
183 | 200 #define CHT_HKL_NEW_PHONETIC ((HKL)0xE0080404) |
184 videodata->ime_enabled = SDL_FALSE; | 201 #define CHT_HKL_NEW_CHANG_JIE ((HKL)0xE0090404) |
185 } | 202 #define CHT_HKL_NEW_QUICK ((HKL)0xE00A0404) |
186 | 203 #define CHT_HKL_HK_CANTONESE ((HKL)0xE00B0404) |
187 void | 204 #define CHT_IMEFILENAME1 "TINTLGNT.IME" |
188 IME_Enable(SDL_VideoData *videodata, HWND hwnd) | 205 #define CHT_IMEFILENAME2 "CINTLGNT.IME" |
189 { | 206 #define CHT_IMEFILENAME3 "MSTCIPHA.IME" |
190 if (!videodata->ime_initialized || !videodata->ime_hwnd_current) | 207 #define IMEID_CHT_VER42 (LANG_CHT | MAKEIMEVERSION(4, 2)) |
191 return; | 208 #define IMEID_CHT_VER43 (LANG_CHT | MAKEIMEVERSION(4, 3)) |
192 | 209 #define IMEID_CHT_VER44 (LANG_CHT | MAKEIMEVERSION(4, 4)) |
193 if (!videodata->ime_available) { | 210 #define IMEID_CHT_VER50 (LANG_CHT | MAKEIMEVERSION(5, 0)) |
194 IME_Disable(videodata, hwnd); | 211 #define IMEID_CHT_VER51 (LANG_CHT | MAKEIMEVERSION(5, 1)) |
195 return; | 212 #define IMEID_CHT_VER52 (LANG_CHT | MAKEIMEVERSION(5, 2)) |
196 } | 213 #define IMEID_CHT_VER60 (LANG_CHT | MAKEIMEVERSION(6, 0)) |
197 if (videodata->ime_hwnd_current == videodata->ime_hwnd_main) | 214 #define IMEID_CHT_VER_VISTA (LANG_CHT | MAKEIMEVERSION(7, 0)) |
198 ImmAssociateContext(videodata->ime_hwnd_current, videodata->ime_himc); | 215 |
199 | 216 #define CHS_HKL ((HKL)0xE00E0804) |
200 videodata->ime_enabled = SDL_TRUE; | 217 #define CHS_IMEFILENAME1 "PINTLGNT.IME" |
201 } | 218 #define CHS_IMEFILENAME2 "MSSCIPYA.IME" |
202 | 219 #define IMEID_CHS_VER41 (LANG_CHS | MAKEIMEVERSION(4, 1)) |
203 void | 220 #define IMEID_CHS_VER42 (LANG_CHS | MAKEIMEVERSION(4, 2)) |
221 #define IMEID_CHS_VER53 (LANG_CHS | MAKEIMEVERSION(5, 3)) | |
222 | |
223 #define LANG() LOWORD((videodata->ime_hkl)) | |
224 #define PRIMLANG() ((WORD)PRIMARYLANGID(LANG())) | |
225 #define SUBLANG() SUBLANGID(LANG()) | |
226 | |
227 static void IME_UpdateInputLocale(SDL_VideoData *videodata); | |
228 static void IME_ClearComposition(SDL_VideoData *videodata); | |
229 static void IME_SetWindow(SDL_VideoData* videodata, HWND hwnd); | |
230 static void IME_SetupAPI(SDL_VideoData *videodata); | |
231 static DWORD IME_GetId(SDL_VideoData *videodata, UINT uIndex); | |
232 static void IME_SendEditingEvent(SDL_VideoData *videodata); | |
233 #define SDL_IsEqualIID(riid1, riid2) SDL_IsEqualGUID(riid1, riid2) | |
234 #define SDL_IsEqualGUID(rguid1, rguid2) (!SDL_memcmp(rguid1, rguid2, sizeof(GUID))) | |
235 | |
236 static SDL_bool UILess_SetupSinks(SDL_VideoData *videodata); | |
237 static void UILess_ReleaseSinks(SDL_VideoData *videodata); | |
238 static void UILess_EnableUIUpdates(SDL_VideoData *videodata); | |
239 static void UILess_DisableUIUpdates(SDL_VideoData *videodata); | |
240 | |
241 static void | |
204 IME_Init(SDL_VideoData *videodata, HWND hwnd) | 242 IME_Init(SDL_VideoData *videodata, HWND hwnd) |
205 { | 243 { |
206 if (videodata->ime_initialized) | 244 if (videodata->ime_initialized) |
207 return; | 245 return; |
208 | 246 |
209 videodata->ime_hwnd_main = hwnd; | 247 videodata->ime_hwnd_main = hwnd; |
210 if (SUCCEEDED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED))) { | 248 if (SUCCEEDED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED))) { |
211 videodata->ime_com_initialized = SDL_TRUE; | 249 videodata->ime_com_initialized = SDL_TRUE; |
212 CoCreateInstance(&CLSID_TF_ThreadMgr, NULL, CLSCTX_INPROC_SERVER, &IID_ITfThreadMgr, &videodata->ime_thread_mgr); | 250 CoCreateInstance(&CLSID_TF_ThreadMgr, NULL, CLSCTX_INPROC_SERVER, &IID_ITfThreadMgr, &videodata->ime_threadmgr); |
213 } | 251 } |
214 videodata->ime_initialized = SDL_TRUE; | 252 videodata->ime_initialized = SDL_TRUE; |
215 videodata->ime_hwnd_current = videodata->ime_hwnd_main; | 253 videodata->ime_himm32 = LoadLibraryA("imm32.dll"); |
216 if (videodata->ime_thread_mgr) { | 254 if (!videodata->ime_himm32) { |
217 struct ITfDocumentMgr *document_mgr = 0; | 255 videodata->ime_available = SDL_FALSE; |
218 if (SUCCEEDED(videodata->ime_thread_mgr->lpVtbl->AssociateFocus(videodata->ime_thread_mgr, hwnd, NULL, &document_mgr))) { | 256 return; |
219 if (document_mgr) | 257 } |
220 document_mgr->lpVtbl->Release(document_mgr); | 258 videodata->ImmLockIMC = (LPINPUTCONTEXT2 (WINAPI *)(HIMC))GetProcAddress(videodata->ime_himm32, "ImmLockIMC"); |
221 } | 259 videodata->ImmUnlockIMC = (BOOL (WINAPI *)(HIMC))GetProcAddress(videodata->ime_himm32, "ImmUnlockIMC"); |
222 } | 260 videodata->ImmLockIMCC = (LPVOID (WINAPI *)(HIMCC))GetProcAddress(videodata->ime_himm32, "ImmLockIMCC"); |
261 videodata->ImmUnlockIMCC = (BOOL (WINAPI *)(HIMCC))GetProcAddress(videodata->ime_himm32, "ImmUnlockIMCC"); | |
262 | |
263 IME_SetWindow(videodata, hwnd); | |
223 videodata->ime_himc = ImmGetContext(hwnd); | 264 videodata->ime_himc = ImmGetContext(hwnd); |
224 ImmReleaseContext(hwnd, videodata->ime_himc); | 265 ImmReleaseContext(hwnd, videodata->ime_himc); |
225 if (!videodata->ime_himc) { | 266 if (!videodata->ime_himc) { |
226 videodata->ime_available = SDL_FALSE; | 267 videodata->ime_available = SDL_FALSE; |
227 IME_Disable(videodata, hwnd); | 268 IME_Disable(videodata, hwnd); |
228 return; | 269 return; |
229 } | 270 } |
230 videodata->ime_available = SDL_TRUE; | 271 videodata->ime_available = SDL_TRUE; |
272 IME_UpdateInputLocale(videodata); | |
273 IME_SetupAPI(videodata); | |
274 videodata->ime_uiless = UILess_SetupSinks(videodata); | |
275 IME_UpdateInputLocale(videodata); | |
231 IME_Disable(videodata, hwnd); | 276 IME_Disable(videodata, hwnd); |
232 } | 277 } |
233 | 278 |
234 void | 279 static void |
280 IME_Enable(SDL_VideoData *videodata, HWND hwnd) | |
281 { | |
282 if (!videodata->ime_initialized || !videodata->ime_hwnd_current) | |
283 return; | |
284 | |
285 if (!videodata->ime_available) { | |
286 IME_Disable(videodata, hwnd); | |
287 return; | |
288 } | |
289 if (videodata->ime_hwnd_current == videodata->ime_hwnd_main) | |
290 ImmAssociateContext(videodata->ime_hwnd_current, videodata->ime_himc); | |
291 | |
292 videodata->ime_enabled = SDL_TRUE; | |
293 IME_UpdateInputLocale(videodata); | |
294 UILess_EnableUIUpdates(videodata); | |
295 } | |
296 | |
297 static void | |
298 IME_Disable(SDL_VideoData *videodata, HWND hwnd) | |
299 { | |
300 if (!videodata->ime_initialized || !videodata->ime_hwnd_current) | |
301 return; | |
302 | |
303 IME_ClearComposition(videodata); | |
304 if (videodata->ime_hwnd_current == videodata->ime_hwnd_main) | |
305 ImmAssociateContext(videodata->ime_hwnd_current, NULL); | |
306 | |
307 videodata->ime_enabled = SDL_FALSE; | |
308 UILess_DisableUIUpdates(videodata); | |
309 } | |
310 | |
311 static void | |
235 IME_Quit(SDL_VideoData *videodata) | 312 IME_Quit(SDL_VideoData *videodata) |
236 { | 313 { |
237 if (!videodata->ime_initialized) | 314 if (!videodata->ime_initialized) |
238 return; | 315 return; |
239 | 316 |
317 UILess_ReleaseSinks(videodata); | |
240 if (videodata->ime_hwnd_main) | 318 if (videodata->ime_hwnd_main) |
241 ImmAssociateContext(videodata->ime_hwnd_main, videodata->ime_himc); | 319 ImmAssociateContext(videodata->ime_hwnd_main, videodata->ime_himc); |
242 | 320 |
243 videodata->ime_hwnd_main = 0; | 321 videodata->ime_hwnd_main = 0; |
244 videodata->ime_himc = 0; | 322 videodata->ime_himc = 0; |
245 if (videodata->ime_thread_mgr) | 323 if (videodata->ime_himm32) |
246 { | 324 { |
247 videodata->ime_thread_mgr->lpVtbl->Release(videodata->ime_thread_mgr); | 325 FreeLibrary(videodata->ime_himm32); |
248 videodata->ime_thread_mgr = 0; | 326 videodata->ime_himm32 = 0; |
327 } | |
328 if (videodata->ime_threadmgr) | |
329 { | |
330 videodata->ime_threadmgr->lpVtbl->Release(videodata->ime_threadmgr); | |
331 videodata->ime_threadmgr = 0; | |
249 } | 332 } |
250 if (videodata->ime_com_initialized) | 333 if (videodata->ime_com_initialized) |
251 { | 334 { |
252 CoUninitialize(); | 335 CoUninitialize(); |
253 videodata->ime_com_initialized = SDL_FALSE; | 336 videodata->ime_com_initialized = SDL_FALSE; |
254 } | 337 } |
255 videodata->ime_initialized = SDL_FALSE; | 338 videodata->ime_initialized = SDL_FALSE; |
256 } | 339 } |
257 | 340 |
341 static void | |
342 IME_GetReadingString(SDL_VideoData *videodata, HWND hwnd) | |
343 { | |
344 DWORD id = 0; | |
345 HIMC himc = 0; | |
346 WCHAR buffer[16]; | |
347 WCHAR *s = buffer; | |
348 DWORD len = 0; | |
349 DWORD err = 0; | |
350 BOOL vertical = FALSE; | |
351 UINT maxuilen = 0; | |
352 static OSVERSIONINFOA osversion = {0}; | |
353 if (videodata->ime_uiless) | |
354 return; | |
355 | |
356 videodata->ime_readingstring[0] = 0; | |
357 if (!osversion.dwOSVersionInfoSize) | |
358 { | |
359 osversion.dwOSVersionInfoSize = sizeof(osversion); | |
360 GetVersionExA(&osversion); | |
361 } | |
362 id = IME_GetId(videodata, 0); | |
363 if (!id) | |
364 return; | |
365 | |
366 himc = ImmGetContext(hwnd); | |
367 if (!himc) | |
368 return; | |
369 | |
370 if (videodata->GetReadingString) | |
371 { | |
372 len = videodata->GetReadingString(himc, 0, 0, &err, &vertical, &maxuilen); | |
373 if (len) | |
374 { | |
375 if (len > SDL_arraysize(buffer)) | |
376 len = SDL_arraysize(buffer); | |
377 | |
378 len = videodata->GetReadingString(himc, len, s, &err, &vertical, &maxuilen); | |
379 } | |
380 SDL_wcslcpy(videodata->ime_readingstring, s, len); | |
381 } | |
382 else | |
383 { | |
384 LPINPUTCONTEXT2 lpimc = videodata->ImmLockIMC(himc); | |
385 LPBYTE p = 0; | |
386 s = 0; | |
387 switch (id) | |
388 { | |
389 case IMEID_CHT_VER42: | |
390 case IMEID_CHT_VER43: | |
391 case IMEID_CHT_VER44: | |
392 p = *(LPBYTE *)((LPBYTE)videodata->ImmLockIMCC(lpimc->hPrivate) + 24); | |
393 if (!p) | |
394 break; | |
395 | |
396 len = *(DWORD *)(p + 7*4 + 32*4); | |
397 s = (WCHAR *)(p + 56); | |
398 break; | |
399 case IMEID_CHT_VER51: | |
400 case IMEID_CHT_VER52: | |
401 case IMEID_CHS_VER53: | |
402 p = *(LPBYTE *)((LPBYTE)videodata->ImmLockIMCC(lpimc->hPrivate) + 4); | |
403 if (!p) | |
404 break; | |
405 | |
406 p = *(LPBYTE *)((LPBYTE)p + 1*4 + 5*4); | |
407 if (!p) | |
408 break; | |
409 | |
410 len = *(DWORD *)(p + 1*4 + (16*2+2*4) + 5*4 + 16*2); | |
411 s = (WCHAR *)(p + 1*4 + (16*2+2*4) + 5*4); | |
412 break; | |
413 case IMEID_CHS_VER41: | |
414 { | |
415 int offset = (IME_GetId(videodata, 1) >= 0x00000002) ? 8 : 7; | |
416 p = *(LPBYTE *)((LPBYTE)videodata->ImmLockIMCC(lpimc->hPrivate) + offset * 4); | |
417 if (!p) | |
418 break; | |
419 | |
420 len = *(DWORD *)(p + 7*4 + 16*2*4); | |
421 s = (WCHAR *)(p + 6*4 + 16*2*1); | |
422 } | |
423 break; | |
424 case IMEID_CHS_VER42: | |
425 if (osversion.dwPlatformId != VER_PLATFORM_WIN32_NT) | |
426 break; | |
427 | |
428 p = *(LPBYTE *)((LPBYTE)videodata->ImmLockIMCC(lpimc->hPrivate) + 1*4 + 1*4 + 6*4); | |
429 if (!p) | |
430 break; | |
431 | |
432 len = *(DWORD *)(p + 1*4 + (16*2+2*4) + 5*4 + 16*2); | |
433 s = (WCHAR *)(p + 1*4 + (16*2+2*4) + 5*4); | |
434 break; | |
435 } | |
436 if (s) | |
437 { | |
438 SDL_wcslcpy(videodata->ime_readingstring, s, len + 1); | |
439 } | |
440 videodata->ImmUnlockIMCC(lpimc->hPrivate); | |
441 videodata->ImmUnlockIMC(himc); | |
442 } | |
443 ImmReleaseContext(hwnd, himc); | |
444 IME_SendEditingEvent(videodata); | |
445 } | |
446 | |
447 static void | |
448 IME_InputLangChanged(SDL_VideoData *videodata) | |
449 { | |
450 UINT uLang = PRIMLANG(); | |
451 HWND hwndime = 0; | |
452 IME_UpdateInputLocale(videodata); | |
453 IME_SetupAPI(videodata); | |
454 if (uLang != PRIMLANG()) | |
455 { | |
456 IME_ClearComposition(videodata); | |
457 } | |
458 hwndime = ImmGetDefaultIMEWnd(videodata->ime_hwnd_current); | |
459 if (hwndime) | |
460 { | |
461 SendMessageA(hwndime, WM_IME_CONTROL, IMC_OPENSTATUSWINDOW, 0); | |
462 SendMessageA(hwndime, WM_IME_CONTROL, IMC_CLOSESTATUSWINDOW, 0); | |
463 } | |
464 } | |
465 | |
466 static DWORD | |
467 IME_GetId(SDL_VideoData *videodata, UINT uIndex) | |
468 { | |
469 static HKL hklprev = 0; | |
470 static DWORD dwRet[2] = {0}; | |
471 DWORD dwVerSize = 0; | |
472 DWORD dwVerHandle = 0; | |
473 LPVOID lpVerBuffer = 0; | |
474 LPVOID lpVerData = 0; | |
475 UINT cbVerData = 0; | |
476 char szTemp[256]; | |
477 HKL hkl = 0; | |
478 DWORD dwLang = 0; | |
479 if (uIndex >= sizeof(dwRet) / sizeof(dwRet[0])) | |
480 return 0; | |
481 | |
482 hkl = videodata->ime_hkl; | |
483 if (hklprev == hkl) | |
484 return dwRet[uIndex]; | |
485 | |
486 hklprev = hkl; | |
487 dwLang = ((DWORD)hkl & 0xffff); | |
488 if (videodata->ime_uiless && LANG() == LANG_CHT) | |
489 { | |
490 dwRet[0] = IMEID_CHT_VER_VISTA; | |
491 dwRet[1] = 0; | |
492 return dwRet[0]; | |
493 } | |
494 if (hkl != CHT_HKL_NEW_PHONETIC | |
495 && hkl != CHT_HKL_NEW_CHANG_JIE | |
496 && hkl != CHT_HKL_NEW_QUICK | |
497 && hkl != CHT_HKL_HK_CANTONESE | |
498 && hkl != CHS_HKL) | |
499 { | |
500 dwRet[0] = dwRet[1] = 0; | |
501 return dwRet[uIndex]; | |
502 } | |
503 if (ImmGetIMEFileNameA(hkl, szTemp, sizeof(szTemp) - 1) <= 0) | |
504 { | |
505 dwRet[0] = dwRet[1] = 0; | |
506 return dwRet[uIndex]; | |
507 } | |
508 if (!videodata->GetReadingString) | |
509 { | |
510 #define LCID_INVARIANT MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT) | |
511 if (CompareStringA(LCID_INVARIANT, NORM_IGNORECASE, szTemp, -1, CHT_IMEFILENAME1, -1) != 2 | |
512 && CompareStringA(LCID_INVARIANT, NORM_IGNORECASE, szTemp, -1, CHT_IMEFILENAME2, -1) != 2 | |
513 && CompareStringA(LCID_INVARIANT, NORM_IGNORECASE, szTemp, -1, CHT_IMEFILENAME3, -1) != 2 | |
514 && CompareStringA(LCID_INVARIANT, NORM_IGNORECASE, szTemp, -1, CHS_IMEFILENAME1, -1) != 2 | |
515 && CompareStringA(LCID_INVARIANT, NORM_IGNORECASE, szTemp, -1, CHS_IMEFILENAME2, -1) != 2 | |
516 ) | |
517 { | |
518 dwRet[0] = dwRet[1] = 0; | |
519 return dwRet[uIndex]; | |
520 } | |
521 #undef LCID_INVARIANT | |
522 dwVerSize = GetFileVersionInfoSizeA(szTemp, &dwVerHandle); | |
523 if (dwVerSize) | |
524 { | |
525 lpVerBuffer = SDL_malloc(dwVerSize); | |
526 if (lpVerBuffer) | |
527 { | |
528 if (GetFileVersionInfoA(szTemp, dwVerHandle, dwVerSize, lpVerBuffer)) | |
529 { | |
530 if (VerQueryValueA(lpVerBuffer, "\\", &lpVerData, &cbVerData)) | |
531 { | |
532 #define pVerFixedInfo ((VS_FIXEDFILEINFO FAR*)lpVerData) | |
533 DWORD dwVer = pVerFixedInfo->dwFileVersionMS; | |
534 dwVer = (dwVer & 0x00ff0000) << 8 | (dwVer & 0x000000ff) << 16; | |
535 if (videodata->GetReadingString || | |
536 dwLang == LANG_CHT && ( | |
537 dwVer == MAKEIMEVERSION(4, 2) || | |
538 dwVer == MAKEIMEVERSION(4, 3) || | |
539 dwVer == MAKEIMEVERSION(4, 4) || | |
540 dwVer == MAKEIMEVERSION(5, 0) || | |
541 dwVer == MAKEIMEVERSION(5, 1) || | |
542 dwVer == MAKEIMEVERSION(5, 2) || | |
543 dwVer == MAKEIMEVERSION(6, 0)) | |
544 || | |
545 dwLang == LANG_CHS && ( | |
546 dwVer == MAKEIMEVERSION(4, 1) || | |
547 dwVer == MAKEIMEVERSION(4, 2) || | |
548 dwVer == MAKEIMEVERSION(5, 3)) | |
549 ) | |
550 { | |
551 dwRet[0] = dwVer | dwLang; | |
552 dwRet[1] = pVerFixedInfo->dwFileVersionLS; | |
553 SDL_free(lpVerBuffer); | |
554 return dwRet[0]; | |
555 } | |
556 #undef pVerFixedInfo | |
557 } | |
558 } | |
559 } | |
560 SDL_free(lpVerBuffer); | |
561 } | |
562 } | |
563 dwRet[0] = dwRet[1] = 0; | |
564 return dwRet[uIndex]; | |
565 } | |
566 | |
567 static void | |
568 IME_SetupAPI(SDL_VideoData *videodata) | |
569 { | |
570 char ime_file[MAX_PATH + 1]; | |
571 HMODULE hime = 0; | |
572 HKL hkl = 0; | |
573 videodata->GetReadingString = 0; | |
574 videodata->ShowReadingWindow = 0; | |
575 if (videodata->ime_uiless) | |
576 return; | |
577 | |
578 hkl = videodata->ime_hkl; | |
579 if (ImmGetIMEFileNameA(hkl, ime_file, sizeof(ime_file) - 1) <= 0) | |
580 return; | |
581 | |
582 hime = LoadLibraryA(ime_file); | |
583 if (!hime) | |
584 return; | |
585 | |
586 videodata->GetReadingString = (UINT (WINAPI *)(HIMC, UINT, LPWSTR, PINT, BOOL*, PUINT)) | |
587 GetProcAddress(hime, "GetReadingString"); | |
588 videodata->ShowReadingWindow = (BOOL (WINAPI *)(HIMC, BOOL)) | |
589 GetProcAddress(hime, "ShowReadingWindow"); | |
590 | |
591 if (videodata->ShowReadingWindow) | |
592 { | |
593 HIMC himc = ImmGetContext(videodata->ime_hwnd_current); | |
594 if (himc) | |
595 { | |
596 videodata->ShowReadingWindow(himc, FALSE); | |
597 ImmReleaseContext(videodata->ime_hwnd_current, himc); | |
598 } | |
599 } | |
600 } | |
601 | |
602 static void | |
603 IME_SetWindow(SDL_VideoData* videodata, HWND hwnd) | |
604 { | |
605 videodata->ime_hwnd_current = hwnd; | |
606 if (videodata->ime_threadmgr) { | |
607 struct ITfDocumentMgr *document_mgr = 0; | |
608 if (SUCCEEDED(videodata->ime_threadmgr->lpVtbl->AssociateFocus(videodata->ime_threadmgr, hwnd, NULL, &document_mgr))) { | |
609 if (document_mgr) | |
610 document_mgr->lpVtbl->Release(document_mgr); | |
611 } | |
612 } | |
613 } | |
614 | |
615 static void | |
616 IME_UpdateInputLocale(SDL_VideoData *videodata) | |
617 { | |
618 static HKL hklPrevious = 0; | |
619 videodata->ime_hkl = GetKeyboardLayout(0); | |
620 if (hklPrevious == videodata->ime_hkl) | |
621 return; | |
622 | |
623 hklPrevious = videodata->ime_hkl; | |
624 } | |
625 | |
626 static void | |
627 IME_ClearComposition(SDL_VideoData *videodata) | |
628 { | |
629 HIMC himc = 0; | |
630 if (!videodata->ime_initialized) | |
631 return; | |
632 | |
633 himc = ImmGetContext(videodata->ime_hwnd_current); | |
634 if (!himc) | |
635 return; | |
636 | |
637 ImmNotifyIME(himc, NI_COMPOSITIONSTR, CPS_CANCEL, 0); | |
638 if (videodata->ime_uiless) | |
639 ImmSetCompositionString(himc, SCS_SETSTR, TEXT(""), sizeof(TCHAR), TEXT(""), sizeof(TCHAR)); | |
640 | |
641 ImmNotifyIME(himc, NI_CLOSECANDIDATE, 0, 0); | |
642 ImmReleaseContext(videodata->ime_hwnd_current, himc); | |
643 SDL_SendEditingText("", 0, 0); | |
644 } | |
645 | |
646 static void | |
647 IME_ClearEditing(SDL_VideoData *videodata) | |
648 { | |
649 | |
650 } | |
651 | |
652 static void | |
653 IME_GetCompositionString(SDL_VideoData *videodata, HIMC himc, DWORD string) | |
654 { | |
655 LONG Length = ImmGetCompositionStringW(himc, string, videodata->ime_composition, sizeof(videodata->ime_composition)); | |
656 if (Length < 0) | |
657 Length = 0; | |
658 | |
659 Length /= sizeof(videodata->ime_composition[0]); | |
660 videodata->ime_cursor = LOWORD(ImmGetCompositionStringW(himc, GCS_CURSORPOS, 0, 0)); | |
661 if (videodata->ime_composition[videodata->ime_cursor] == 0x3000) | |
662 { | |
663 int i; | |
664 for (i = videodata->ime_cursor + 1; i < Length; ++i) | |
665 videodata->ime_composition[i - 1] = videodata->ime_composition[i]; | |
666 | |
667 --Length; | |
668 } | |
669 videodata->ime_composition[Length] = 0; | |
670 } | |
671 | |
672 static void | |
673 IME_SendInputEvent(SDL_VideoData *videodata) | |
674 { | |
675 char *s = 0; | |
676 s = WIN_StringToUTF8(videodata->ime_composition); | |
677 SDL_SendKeyboardText(s); | |
678 SDL_free(s); | |
679 | |
680 videodata->ime_composition[0] = 0; | |
681 videodata->ime_readingstring[0] = 0; | |
682 videodata->ime_cursor = 0; | |
683 } | |
684 | |
685 static void | |
686 IME_SendEditingEvent(SDL_VideoData *videodata) | |
687 { | |
688 char *s = 0; | |
689 WCHAR wBuffer[SDL_TEXTEDITINGEVENT_TEXT_SIZE]; | |
690 wBuffer[0] = 0; | |
691 if (videodata->ime_readingstring[0]) | |
692 { | |
693 size_t len = SDL_min(SDL_wcslen(videodata->ime_composition), (size_t)videodata->ime_cursor); | |
694 SDL_wcslcpy(wBuffer, videodata->ime_composition, len + 1); | |
695 SDL_wcslcat(wBuffer, videodata->ime_readingstring, sizeof(wBuffer)); | |
696 SDL_wcslcat(wBuffer, &videodata->ime_composition[len], sizeof(wBuffer) - len); | |
697 } | |
698 else | |
699 { | |
700 SDL_wcslcpy(wBuffer, videodata->ime_composition, sizeof(videodata->ime_composition)); | |
701 } | |
702 s = WIN_StringToUTF8(wBuffer); | |
703 SDL_SendEditingText(s, videodata->ime_cursor + SDL_wcslen(videodata->ime_readingstring), 0); | |
704 SDL_free(s); | |
705 } | |
706 | |
258 SDL_bool | 707 SDL_bool |
259 IME_HandleMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM *lParam, SDL_VideoData *videodata) | 708 IME_HandleMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM *lParam, SDL_VideoData *videodata) |
260 { | 709 { |
261 SDL_bool trap = SDL_FALSE; | 710 SDL_bool trap = SDL_FALSE; |
262 HIMC himc = 0; | 711 HIMC himc = 0; |
263 WCHAR Buffer[SDL_TEXTINPUTEVENT_TEXT_SIZE / 2]; | |
264 if (!videodata->ime_initialized || !videodata->ime_available || !videodata->ime_enabled) | 712 if (!videodata->ime_initialized || !videodata->ime_available || !videodata->ime_enabled) |
265 return SDL_FALSE; | 713 return SDL_FALSE; |
266 | 714 |
267 switch (msg) | 715 switch (msg) |
268 { | 716 { |
269 case WM_INPUTLANGCHANGE: | 717 case WM_INPUTLANGCHANGE: |
718 //IME_InputLangChanged(videodata); | |
270 break; | 719 break; |
271 case WM_IME_SETCONTEXT: | 720 case WM_IME_SETCONTEXT: |
272 *lParam = 0; | 721 *lParam = 0; |
273 break; | 722 break; |
274 case WM_IME_STARTCOMPOSITION: | 723 case WM_IME_STARTCOMPOSITION: |
277 case WM_IME_COMPOSITION: | 726 case WM_IME_COMPOSITION: |
278 trap = SDL_TRUE; | 727 trap = SDL_TRUE; |
279 himc = ImmGetContext(hwnd); | 728 himc = ImmGetContext(hwnd); |
280 if (*lParam & GCS_RESULTSTR) | 729 if (*lParam & GCS_RESULTSTR) |
281 { | 730 { |
282 LONG Length = 0; | 731 IME_GetCompositionString(videodata, himc, GCS_RESULTSTR); |
283 char *s = 0; | 732 IME_SendInputEvent(videodata); |
284 Length = ImmGetCompositionStringW(himc, GCS_RESULTSTR, Buffer, sizeof(Buffer) * sizeof(Buffer[0])); | |
285 Buffer[Length / sizeof(Buffer[0])] = 0; | |
286 s = WIN_StringToUTF8(Buffer); | |
287 SDL_SendKeyboardText(s); | |
288 SDL_free(s); | |
289 } | 733 } |
290 if (*lParam & GCS_COMPSTR) | 734 if (*lParam & GCS_COMPSTR) |
291 { | 735 { |
292 LONG Length = 0; | 736 if (!videodata->ime_uiless) |
293 DWORD Cursor = 0; | 737 videodata->ime_readingstring[0] = 0; |
294 char *s = 0; | 738 |
295 Length = ImmGetCompositionStringW(himc, GCS_COMPSTR, Buffer, sizeof(Buffer) * sizeof(Buffer[0])); | 739 IME_GetCompositionString(videodata, himc, GCS_COMPSTR); |
296 Buffer[Length / sizeof(Buffer[0])] = 0; | 740 IME_SendEditingEvent(videodata); |
297 s = WIN_StringToUTF8(Buffer); | |
298 Cursor = LOWORD(ImmGetCompositionStringW(himc, GCS_CURSORPOS, 0, 0)); | |
299 SDL_SendEditingText(s, Cursor, 0); | |
300 SDL_free(s); | |
301 } | 741 } |
302 ImmReleaseContext(hwnd, himc); | 742 ImmReleaseContext(hwnd, himc); |
303 break; | 743 break; |
304 case WM_IME_ENDCOMPOSITION: | 744 case WM_IME_ENDCOMPOSITION: |
305 SDL_SendKeyboardText(""); | 745 videodata->ime_composition[0] = 0; |
746 videodata->ime_readingstring[0] = 0; | |
747 videodata->ime_cursor = 0; | |
748 SDL_SendEditingText("", 0, 0); | |
306 break; | 749 break; |
307 case WM_IME_NOTIFY: | 750 case WM_IME_NOTIFY: |
308 switch (wParam) | 751 switch (wParam) |
309 { | 752 { |
310 case IMN_SETCONVERSIONMODE: | 753 case IMN_SETCONVERSIONMODE: |
311 break; | |
312 case IMN_SETOPENSTATUS: | 754 case IMN_SETOPENSTATUS: |
755 IME_UpdateInputLocale(videodata); | |
313 break; | 756 break; |
314 case IMN_OPENCANDIDATE: | 757 case IMN_OPENCANDIDATE: |
315 case IMN_CHANGECANDIDATE: | 758 case IMN_CHANGECANDIDATE: |
316 trap = SDL_TRUE; | 759 trap = SDL_TRUE; |
317 break; | 760 break; |
318 case IMN_CLOSECANDIDATE: | 761 case IMN_CLOSECANDIDATE: |
319 trap = SDL_TRUE; | 762 trap = SDL_TRUE; |
320 break; | 763 break; |
321 case IMN_PRIVATE: | 764 case IMN_PRIVATE: |
765 { | |
766 DWORD dwId = IME_GetId(videodata, 0); | |
767 IME_GetReadingString(videodata, hwnd); | |
768 switch (dwId) | |
769 { | |
770 case IMEID_CHT_VER42: | |
771 case IMEID_CHT_VER43: | |
772 case IMEID_CHT_VER44: | |
773 case IMEID_CHS_VER41: | |
774 case IMEID_CHS_VER42: | |
775 if (*lParam == 1 || *lParam == 2) | |
776 trap = SDL_TRUE; | |
777 | |
778 break; | |
779 case IMEID_CHT_VER50: | |
780 case IMEID_CHT_VER51: | |
781 case IMEID_CHT_VER52: | |
782 case IMEID_CHT_VER60: | |
783 case IMEID_CHS_VER53: | |
784 if (*lParam == 16 | |
785 || *lParam == 17 | |
786 || *lParam == 26 | |
787 || *lParam == 27 | |
788 || *lParam == 28) | |
789 trap = SDL_TRUE; | |
790 break; | |
791 } | |
792 } | |
322 break; | 793 break; |
323 default: | 794 default: |
324 trap = SDL_TRUE; | 795 trap = SDL_TRUE; |
325 break; | 796 break; |
326 } | 797 } |
327 break; | 798 break; |
328 } | 799 } |
329 return trap; | 800 return trap; |
330 } | 801 } |
331 | 802 |
803 STDMETHODIMP_(ULONG) TSFSink_AddRef(TSFSink *sink) | |
804 { | |
805 return ++sink->refcount; | |
806 } | |
807 | |
808 STDMETHODIMP_(ULONG)TSFSink_Release(TSFSink *sink) | |
809 { | |
810 --sink->refcount; | |
811 if (sink->refcount == 0) | |
812 { | |
813 SDL_free(sink); | |
814 return 0; | |
815 } | |
816 return sink->refcount; | |
817 } | |
818 | |
819 STDMETHODIMP UIElementSink_QueryInterface(TSFSink *sink, REFIID riid, PVOID *ppv) | |
820 { | |
821 if (!ppv) | |
822 return E_INVALIDARG; | |
823 | |
824 *ppv = 0; | |
825 if (SDL_IsEqualIID(riid, &IID_IUnknown)) | |
826 *ppv = (IUnknown *)sink; | |
827 else if (SDL_IsEqualIID(riid, &IID_ITfUIElementSink)) | |
828 *ppv = (ITfUIElementSink *)sink; | |
829 | |
830 if (*ppv) | |
831 { | |
832 TSFSink_AddRef(sink); | |
833 return S_OK; | |
834 } | |
835 return E_NOINTERFACE; | |
836 } | |
837 | |
838 ITfUIElement *UILess_GetUIElement(SDL_VideoData *videodata, DWORD dwUIElementId) | |
839 { | |
840 ITfUIElementMgr *puiem = 0; | |
841 ITfUIElement *pelem = 0; | |
842 ITfThreadMgrEx *threadmgrex = videodata->ime_threadmgrex; | |
843 | |
844 if (SUCCEEDED(threadmgrex->lpVtbl->QueryInterface(threadmgrex, &IID_ITfUIElementMgr, (LPVOID *)&puiem))) | |
845 { | |
846 puiem->lpVtbl->GetUIElement(puiem, dwUIElementId, &pelem); | |
847 puiem->lpVtbl->Release(puiem); | |
848 } | |
849 return pelem; | |
850 } | |
851 | |
852 STDMETHODIMP UIElementSink_BeginUIElement(TSFSink *sink, DWORD dwUIElementId, BOOL *pbShow) | |
853 { | |
854 ITfUIElement *pElement = UILess_GetUIElement((SDL_VideoData *)sink->data, dwUIElementId); | |
855 ITfReadingInformationUIElement *preading = 0; | |
856 ITfCandidateListUIElement *pcandidates = 0; | |
857 SDL_VideoData *videodata = (SDL_VideoData *)sink->data; | |
858 if (!pElement) | |
859 return E_INVALIDARG; | |
860 | |
861 *pbShow = FALSE; | |
862 if (SUCCEEDED(pElement->lpVtbl->QueryInterface(pElement, &IID_ITfReadingInformationUIElement, (LPVOID *)&preading))) | |
863 { | |
864 BSTR bstr; | |
865 if (SUCCEEDED(preading->lpVtbl->GetString(preading, &bstr)) && bstr) | |
866 { | |
867 WCHAR *s = (WCHAR *)bstr; | |
868 SysFreeString(bstr); | |
869 } | |
870 preading->lpVtbl->Release(preading); | |
871 } | |
872 else if (SUCCEEDED(pElement->lpVtbl->QueryInterface(pElement, &IID_ITfCandidateListUIElement, (PVOID *)&pcandidates))) | |
873 { | |
874 pcandidates->lpVtbl->Release(pcandidates); | |
875 } | |
876 return S_OK; | |
877 } | |
878 | |
879 STDMETHODIMP UIElementSink_UpdateUIElement(TSFSink *sink, DWORD dwUIElementId) | |
880 { | |
881 ITfUIElement *pElement = UILess_GetUIElement((SDL_VideoData *)sink->data, dwUIElementId); | |
882 ITfReadingInformationUIElement *preading = 0; | |
883 ITfCandidateListUIElement *pcandidates = 0; | |
884 SDL_VideoData *videodata = (SDL_VideoData *)sink->data; | |
885 if (!pElement) | |
886 return E_INVALIDARG; | |
887 | |
888 if (SUCCEEDED(pElement->lpVtbl->QueryInterface(pElement, &IID_ITfReadingInformationUIElement, (LPVOID *)&preading))) | |
889 { | |
890 BSTR bstr; | |
891 if (SUCCEEDED(preading->lpVtbl->GetString(preading, &bstr)) && bstr) | |
892 { | |
893 WCHAR *s = (WCHAR *)bstr; | |
894 SDL_wcslcpy(videodata->ime_readingstring, s, sizeof(videodata->ime_readingstring)); | |
895 IME_SendEditingEvent(videodata); | |
896 SysFreeString(bstr); | |
897 } | |
898 preading->lpVtbl->Release(preading); | |
899 } | |
900 else if (SUCCEEDED(pElement->lpVtbl->QueryInterface(pElement, &IID_ITfCandidateListUIElement, (PVOID *)&pcandidates))) | |
901 { | |
902 pcandidates->lpVtbl->Release(pcandidates); | |
903 } | |
904 return S_OK; | |
905 } | |
906 | |
907 STDMETHODIMP UIElementSink_EndUIElement(TSFSink *sink, DWORD dwUIElementId) | |
908 { | |
909 ITfUIElement *pElement = UILess_GetUIElement((SDL_VideoData *)sink->data, dwUIElementId); | |
910 ITfReadingInformationUIElement *preading = 0; | |
911 ITfCandidateListUIElement *pcandidates = 0; | |
912 SDL_VideoData *videodata = (SDL_VideoData *)sink->data; | |
913 if (!pElement) | |
914 return E_INVALIDARG; | |
915 | |
916 if (SUCCEEDED(pElement->lpVtbl->QueryInterface(pElement, &IID_ITfReadingInformationUIElement, (LPVOID *)&preading))) | |
917 { | |
918 videodata->ime_readingstring[0] = 0; | |
919 IME_SendEditingEvent(videodata); | |
920 preading->lpVtbl->Release(preading); | |
921 } | |
922 else if (SUCCEEDED(pElement->lpVtbl->QueryInterface(pElement, &IID_ITfCandidateListUIElement, (PVOID *)&pcandidates))) | |
923 { | |
924 pcandidates->lpVtbl->Release(pcandidates); | |
925 } | |
926 return S_OK; | |
927 } | |
928 | |
929 STDMETHODIMP IPPASink_QueryInterface(TSFSink *sink, REFIID riid, PVOID *ppv) | |
930 { | |
931 if (!ppv) | |
932 return E_INVALIDARG; | |
933 | |
934 *ppv = 0; | |
935 if (SDL_IsEqualIID(riid, &IID_IUnknown)) | |
936 *ppv = (IUnknown *)sink; | |
937 else if (SDL_IsEqualIID(riid, &IID_ITfInputProcessorProfileActivationSink)) | |
938 *ppv = (ITfInputProcessorProfileActivationSink *)sink; | |
939 | |
940 if (*ppv) | |
941 { | |
942 TSFSink_AddRef(sink); | |
943 return S_OK; | |
944 } | |
945 return E_NOINTERFACE; | |
946 } | |
947 | |
948 STDMETHODIMP IPPASink_OnActivated(TSFSink *sink, DWORD dwProfileType, LANGID langid, REFCLSID clsid, REFGUID catid, REFGUID guidProfile, HKL hkl, DWORD dwFlags) | |
949 { | |
950 if (SDL_IsEqualIID(catid, &GUID_TFCAT_TIP_KEYBOARD) && (dwFlags & TF_IPSINK_FLAG_ACTIVE)) | |
951 IME_InputLangChanged((SDL_VideoData *)sink->data); | |
952 | |
953 return S_OK; | |
954 } | |
955 | |
956 static void *vtUIElementSink[] = { | |
957 (void *)(UIElementSink_QueryInterface), | |
958 (void *)(TSFSink_AddRef), | |
959 (void *)(TSFSink_Release), | |
960 (void *)(UIElementSink_BeginUIElement), | |
961 (void *)(UIElementSink_UpdateUIElement), | |
962 (void *)(UIElementSink_EndUIElement) | |
963 }; | |
964 | |
965 static void *vtIPPASink[] = { | |
966 (void *)(IPPASink_QueryInterface), | |
967 (void *)(TSFSink_AddRef), | |
968 (void *)(TSFSink_Release), | |
969 (void *)(IPPASink_OnActivated) | |
970 }; | |
971 | |
972 static void | |
973 UILess_EnableUIUpdates(SDL_VideoData *videodata) | |
974 { | |
975 ITfSource *source = 0; | |
976 if (!videodata->ime_threadmgrex || videodata->ime_uielemsinkcookie != TF_INVALID_COOKIE) | |
977 return; | |
978 | |
979 if (SUCCEEDED(videodata->ime_threadmgrex->lpVtbl->QueryInterface(videodata->ime_threadmgrex, &IID_ITfSource, (LPVOID *)&source))) | |
980 { | |
981 source->lpVtbl->AdviseSink(source, &IID_ITfUIElementSink, (IUnknown *)videodata->ime_uielemsink, &videodata->ime_uielemsinkcookie); | |
982 source->lpVtbl->Release(source); | |
983 } | |
984 } | |
985 | |
986 static void | |
987 UILess_DisableUIUpdates(SDL_VideoData *videodata) | |
988 { | |
989 ITfSource *source = 0; | |
990 if (!videodata->ime_threadmgrex || videodata->ime_uielemsinkcookie == TF_INVALID_COOKIE) | |
991 return; | |
992 | |
993 if (SUCCEEDED(videodata->ime_threadmgrex->lpVtbl->QueryInterface(videodata->ime_threadmgrex, &IID_ITfSource, (LPVOID *)&source))) | |
994 { | |
995 source->lpVtbl->UnadviseSink(source, videodata->ime_uielemsinkcookie); | |
996 videodata->ime_uielemsinkcookie = TF_INVALID_COOKIE; | |
997 source->lpVtbl->Release(source); | |
998 } | |
999 } | |
1000 | |
1001 static SDL_bool | |
1002 UILess_SetupSinks(SDL_VideoData *videodata) | |
1003 { | |
1004 TfClientId clientid = 0; | |
1005 SDL_bool result = SDL_FALSE; | |
1006 ITfSource *source = 0; | |
1007 if (FAILED(CoCreateInstance(&CLSID_TF_ThreadMgr, NULL, CLSCTX_INPROC_SERVER, &IID_ITfThreadMgrEx, &videodata->ime_threadmgrex))) | |
1008 return SDL_FALSE; | |
1009 | |
1010 if (FAILED(videodata->ime_threadmgrex->lpVtbl->ActivateEx(videodata->ime_threadmgrex, &clientid, TF_TMAE_UIELEMENTENABLEDONLY))) | |
1011 return SDL_FALSE; | |
1012 | |
1013 videodata->ime_uielemsink = SDL_malloc(sizeof(TSFSink)); | |
1014 videodata->ime_ippasink = SDL_malloc(sizeof(TSFSink)); | |
1015 | |
1016 videodata->ime_uielemsink->lpVtbl = vtUIElementSink; | |
1017 videodata->ime_uielemsink->refcount = 1; | |
1018 videodata->ime_uielemsink->data = videodata; | |
1019 | |
1020 videodata->ime_ippasink->lpVtbl = vtIPPASink; | |
1021 videodata->ime_ippasink->refcount = 1; | |
1022 videodata->ime_ippasink->data = videodata; | |
1023 | |
1024 if (SUCCEEDED(videodata->ime_threadmgrex->lpVtbl->QueryInterface(videodata->ime_threadmgrex, &IID_ITfSource, (LPVOID *)&source))) | |
1025 { | |
1026 if (SUCCEEDED(source->lpVtbl->AdviseSink(source, &IID_ITfUIElementSink, (IUnknown *)videodata->ime_uielemsink, &videodata->ime_uielemsinkcookie))) | |
1027 { | |
1028 if (SUCCEEDED(source->lpVtbl->AdviseSink(source, &IID_ITfInputProcessorProfileActivationSink, (IUnknown *)videodata->ime_ippasink, &videodata->ime_alpnsinkcookie))) | |
1029 { | |
1030 result = SDL_TRUE; | |
1031 } | |
1032 } | |
1033 source->lpVtbl->Release(source); | |
1034 } | |
1035 return result; | |
1036 } | |
1037 | |
1038 #define SAFE_RELEASE(p) \ | |
1039 { \ | |
1040 if (p) { \ | |
1041 (p)->lpVtbl->Release((p)); \ | |
1042 (p) = 0; \ | |
1043 } \ | |
1044 } | |
1045 | |
1046 static void | |
1047 UILess_ReleaseSinks(SDL_VideoData *videodata) | |
1048 { | |
1049 ITfSource *Source = 0; | |
1050 if (videodata->ime_threadmgrex && SUCCEEDED(videodata->ime_threadmgrex->lpVtbl->QueryInterface(videodata->ime_threadmgrex, &IID_ITfSource, &Source))) | |
1051 { | |
1052 Source->lpVtbl->UnadviseSink(Source, videodata->ime_uielemsinkcookie); | |
1053 Source->lpVtbl->UnadviseSink(Source, videodata->ime_alpnsinkcookie); | |
1054 SAFE_RELEASE(Source); | |
1055 videodata->ime_threadmgrex->lpVtbl->Deactivate(videodata->ime_threadmgrex); | |
1056 SAFE_RELEASE(videodata->ime_threadmgrex); | |
1057 TSFSink_Release(videodata->ime_uielemsink); | |
1058 videodata->ime_uielemsink = 0; | |
1059 TSFSink_Release(videodata->ime_ippasink); | |
1060 videodata->ime_ippasink = 0; | |
1061 } | |
1062 } | |
1063 | |
332 /* vi: set ts=4 sw=4 expandtab: */ | 1064 /* vi: set ts=4 sw=4 expandtab: */ |