21#include "../../SDL_internal.h"
23#if SDL_VIDEO_DRIVER_WINDOWS
27#include "../../events/SDL_keyboard_c.h"
28#include "../../events/scancodes_windows.h"
33#ifndef SDL_DISABLE_WINDOWS_IME
40#ifndef MAPVK_VK_TO_VSC
41#define MAPVK_VK_TO_VSC 0
43#ifndef MAPVK_VSC_TO_VK
44#define MAPVK_VSC_TO_VK 1
46#ifndef MAPVK_VK_TO_CHAR
47#define MAPVK_VK_TO_CHAR 2
57 data->ime_threadmgr = 0;
61 data->ime_hwnd_main = 0;
62 data->ime_hwnd_current = 0;
64 data->ime_composition[0] = 0;
65 data->ime_readingstring[0] = 0;
70 data->ime_candcount = 0;
71 data->ime_candref = 0;
72 data->ime_candsel = 0;
73 data->ime_candpgsize = 0;
74 data->ime_candlistindexbase = 0;
80 data->ime_winwidth = 0;
81 data->ime_winheight = 0;
85 data->GetReadingString = 0;
86 data->ShowReadingWindow = 0;
88 data->ImmUnlockIMC = 0;
89 data->ImmLockIMCC = 0;
90 data->ImmUnlockIMCC = 0;
92 data->ime_threadmgrex = 0;
97 data->ime_uielemsink = 0;
98 data->ime_ippasink = 0;
136 vk = MapVirtualKey(
i, MAPVK_VSC_TO_VK);
138 int ch = (MapVirtualKey( vk, MAPVK_VK_TO_CHAR ) & 0x7FFF);
140 if ( ch >=
'A' && ch <=
'Z' ) {
141 keymap[scancode] =
SDLK_a + ( ch -
'A' );
143 keymap[scancode] = ch;
155#ifndef SDL_DISABLE_WINDOWS_IME
168 BYTE keyboardState[256];
170 int keycode, scancode,
result,
i;
172 GetKeyboardState(keyboardState);
175 scancode = MapVirtualKey(keycode, MAPVK_VK_TO_VSC);
181 for (
i = 0;
i < 5;
i++) {
182 result = ToUnicode(keycode, scancode, keyboardState, (LPWSTR)
buffer, 16, 0);
193#ifndef SDL_DISABLE_WINDOWS_IME
199#ifndef SDL_DISABLE_WINDOWS_IME
205 IME_Init(videodata, hwnd);
206 IME_Enable(videodata, hwnd);
214#ifndef SDL_DISABLE_WINDOWS_IME
220#ifndef SDL_DISABLE_WINDOWS_IME
225 IME_Init(videodata, hwnd);
226 IME_Disable(videodata, hwnd);
248 cf.ptCurrentPos.x = videodata->
ime_rect.
x;
249 cf.ptCurrentPos.y = videodata->
ime_rect.
y;
250 cf.dwStyle = CFS_FORCE_POSITION;
251 ImmSetCompositionWindow(himc, &cf);
256#ifdef SDL_DISABLE_WINDOWS_IME
273#elif defined(__GNUC__)
278#define DEFINE_GUID(n,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) static const GUID n = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
279DEFINE_GUID(IID_ITfInputProcessorProfileActivationSink, 0x71C6E74E,0x0F28,0x11D8,0xA8,0x2A,0x00,0x06,0x5B,0x84,0x43,0x5C);
280DEFINE_GUID(IID_ITfUIElementSink, 0xEA1EA136,0x19DF,0x11D7,0xA6,0xD2,0x00,0x06,0x5B,0x84,0x43,0x5C);
281DEFINE_GUID(GUID_TFCAT_TIP_KEYBOARD, 0x34745C63,0xB2F0,0x4784,0x8B,0x67,0x5E,0x12,0xC8,0x70,0x1A,0x31);
282DEFINE_GUID(IID_ITfSource, 0x4EA48A35,0x60AE,0x446F,0x8F,0xD6,0xE6,0xA8,0xD8,0x24,0x59,0xF7);
283DEFINE_GUID(IID_ITfUIElementMgr, 0xEA1EA135,0x19DF,0x11D7,0xA6,0xD2,0x00,0x06,0x5B,0x84,0x43,0x5C);
284DEFINE_GUID(IID_ITfCandidateListUIElement, 0xEA1EA138,0x19DF,0x11D7,0xA6,0xD2,0x00,0x06,0x5B,0x84,0x43,0x5C);
285DEFINE_GUID(IID_ITfReadingInformationUIElement, 0xEA1EA139,0x19DF,0x11D7,0xA6,0xD2,0x00,0x06,0x5B,0x84,0x43,0x5C);
286DEFINE_GUID(IID_ITfThreadMgr, 0xAA80E801,0x2021,0x11D2,0x93,0xE0,0x00,0x60,0xB0,0x67,0xB8,0x6E);
287DEFINE_GUID(CLSID_TF_ThreadMgr, 0x529A9E6B,0x6587,0x4F23,0xAB,0x9E,0x9C,0x7D,0x68,0x3E,0x3C,0x50);
288DEFINE_GUID(IID_ITfThreadMgrEx, 0x3E90ADE3,0x7594,0x4CB0,0xBB,0x58,0x69,0x62,0x8F,0x5F,0x45,0x8C);
291#define LANG_CHT MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL)
292#define LANG_CHS MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)
294#define MAKEIMEVERSION(major,minor) ((DWORD) (((BYTE)(major) << 24) | ((BYTE)(minor) << 16) ))
295#define IMEID_VER(id) ((id) & 0xffff0000)
296#define IMEID_LANG(id) ((id) & 0x0000ffff)
298#define CHT_HKL_DAYI ((HKL)(UINT_PTR)0xE0060404)
299#define CHT_HKL_NEW_PHONETIC ((HKL)(UINT_PTR)0xE0080404)
300#define CHT_HKL_NEW_CHANG_JIE ((HKL)(UINT_PTR)0xE0090404)
301#define CHT_HKL_NEW_QUICK ((HKL)(UINT_PTR)0xE00A0404)
302#define CHT_HKL_HK_CANTONESE ((HKL)(UINT_PTR)0xE00B0404)
303#define CHT_IMEFILENAME1 "TINTLGNT.IME"
304#define CHT_IMEFILENAME2 "CINTLGNT.IME"
305#define CHT_IMEFILENAME3 "MSTCIPHA.IME"
306#define IMEID_CHT_VER42 (LANG_CHT | MAKEIMEVERSION(4, 2))
307#define IMEID_CHT_VER43 (LANG_CHT | MAKEIMEVERSION(4, 3))
308#define IMEID_CHT_VER44 (LANG_CHT | MAKEIMEVERSION(4, 4))
309#define IMEID_CHT_VER50 (LANG_CHT | MAKEIMEVERSION(5, 0))
310#define IMEID_CHT_VER51 (LANG_CHT | MAKEIMEVERSION(5, 1))
311#define IMEID_CHT_VER52 (LANG_CHT | MAKEIMEVERSION(5, 2))
312#define IMEID_CHT_VER60 (LANG_CHT | MAKEIMEVERSION(6, 0))
313#define IMEID_CHT_VER_VISTA (LANG_CHT | MAKEIMEVERSION(7, 0))
315#define CHS_HKL ((HKL)(UINT_PTR)0xE00E0804)
316#define CHS_IMEFILENAME1 "PINTLGNT.IME"
317#define CHS_IMEFILENAME2 "MSSCIPYA.IME"
318#define IMEID_CHS_VER41 (LANG_CHS | MAKEIMEVERSION(4, 1))
319#define IMEID_CHS_VER42 (LANG_CHS | MAKEIMEVERSION(4, 2))
320#define IMEID_CHS_VER53 (LANG_CHS | MAKEIMEVERSION(5, 3))
322#define LANG() LOWORD((videodata->ime_hkl))
323#define PRIMLANG() ((WORD)PRIMARYLANGID(LANG()))
324#define SUBLANG() SUBLANGID(LANG())
328static void IME_SetWindow(
SDL_VideoData* videodata, HWND hwnd);
330static DWORD IME_GetId(
SDL_VideoData *videodata, UINT uIndex);
337static void UILess_DisableUIUpdates(
SDL_VideoData *videodata);
348 CoCreateInstance(&CLSID_TF_ThreadMgr,
NULL, CLSCTX_INPROC_SERVER, &IID_ITfThreadMgr, (LPVOID *)&videodata->
ime_threadmgr);
362 IME_SetWindow(videodata, hwnd);
363 videodata->
ime_himc = ImmGetContext(hwnd);
364 ImmReleaseContext(hwnd, videodata->
ime_himc);
367 IME_Disable(videodata, hwnd);
371 IME_UpdateInputLocale(videodata);
372 IME_SetupAPI(videodata);
373 videodata->
ime_uiless = UILess_SetupSinks(videodata);
374 IME_UpdateInputLocale(videodata);
375 IME_Disable(videodata, hwnd);
385 IME_Disable(videodata, hwnd);
392 IME_UpdateInputLocale(videodata);
393 UILess_EnableUIUpdates(videodata);
402 IME_ClearComposition(videodata);
407 UILess_DisableUIUpdates(videodata);
416 UILess_ReleaseSinks(videodata);
434 IME_DestroyTextures(videodata);
447 BOOL vertical =
FALSE;
455 id = IME_GetId(videodata, 0);
459 himc = ImmGetContext(hwnd);
463 if (videodata->GetReadingString) {
464 len = videodata->GetReadingString(himc, 0, 0, &err, &vertical, &maxuilen);
469 len = videodata->GetReadingString(himc,
len,
s, &err, &vertical, &maxuilen);
474 LPINPUTCONTEXT2 lpimc = videodata->ImmLockIMC(himc);
479 case IMEID_CHT_VER42:
480 case IMEID_CHT_VER43:
481 case IMEID_CHT_VER44:
482 p = *(LPBYTE *)((LPBYTE)videodata->ImmLockIMCC(lpimc->hPrivate) + 24);
486 len = *(DWORD *)(
p + 7*4 + 32*4);
487 s = (WCHAR *)(
p + 56);
489 case IMEID_CHT_VER51:
490 case IMEID_CHT_VER52:
491 case IMEID_CHS_VER53:
492 p = *(LPBYTE *)((LPBYTE)videodata->ImmLockIMCC(lpimc->hPrivate) + 4);
496 p = *(LPBYTE *)((LPBYTE)
p + 1*4 + 5*4);
500 len = *(DWORD *)(
p + 1*4 + (16*2+2*4) + 5*4 + 16*2);
501 s = (WCHAR *)(
p + 1*4 + (16*2+2*4) + 5*4);
503 case IMEID_CHS_VER41:
505 int offset = (IME_GetId(videodata, 1) >= 0x00000002) ? 8 : 7;
506 p = *(LPBYTE *)((LPBYTE)videodata->ImmLockIMCC(lpimc->hPrivate) +
offset * 4);
510 len = *(DWORD *)(
p + 7*4 + 16*2*4);
511 s = (WCHAR *)(
p + 6*4 + 16*2*1);
514 case IMEID_CHS_VER42:
515 p = *(LPBYTE *)((LPBYTE)videodata->ImmLockIMCC(lpimc->hPrivate) + 1*4 + 1*4 + 6*4);
519 len = *(DWORD *)(
p + 1*4 + (16*2+2*4) + 5*4 + 16*2);
520 s = (WCHAR *)(
p + 1*4 + (16*2+2*4) + 5*4);
528 videodata->ImmUnlockIMCC(lpimc->hPrivate);
529 videodata->ImmUnlockIMC(himc);
531 ImmReleaseContext(hwnd, himc);
532 IME_SendEditingEvent(videodata);
538 UINT lang = PRIMLANG();
539 IME_UpdateInputLocale(videodata);
543 IME_SetupAPI(videodata);
544 if (lang != PRIMLANG()) {
545 IME_ClearComposition(videodata);
552 static HKL hklprev = 0;
553 static DWORD dwRet[2] = {0};
555 DWORD dwVerHandle = 0;
556 LPVOID lpVerBuffer = 0;
557 LPVOID lpVerData = 0;
562 if (uIndex >=
sizeof(dwRet) /
sizeof(dwRet[0]))
567 return dwRet[uIndex];
570 dwLang = ((DWORD_PTR)hkl & 0xffff);
571 if (videodata->
ime_uiless && LANG() == LANG_CHT) {
572 dwRet[0] = IMEID_CHT_VER_VISTA;
576 if (hkl != CHT_HKL_NEW_PHONETIC
577 && hkl != CHT_HKL_NEW_CHANG_JIE
578 && hkl != CHT_HKL_NEW_QUICK
579 && hkl != CHT_HKL_HK_CANTONESE
581 dwRet[0] = dwRet[1] = 0;
582 return dwRet[uIndex];
584 if (ImmGetIMEFileNameA(hkl, szTemp,
sizeof(szTemp) - 1) <= 0) {
585 dwRet[0] = dwRet[1] = 0;
586 return dwRet[uIndex];
588 if (!videodata->GetReadingString) {
589 #define LCID_INVARIANT MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT)
590 if (CompareStringA(LCID_INVARIANT, NORM_IGNORECASE, szTemp, -1, CHT_IMEFILENAME1, -1) != 2
591 && CompareStringA(LCID_INVARIANT, NORM_IGNORECASE, szTemp, -1, CHT_IMEFILENAME2, -1) != 2
592 && CompareStringA(LCID_INVARIANT, NORM_IGNORECASE, szTemp, -1, CHT_IMEFILENAME3, -1) != 2
593 && CompareStringA(LCID_INVARIANT, NORM_IGNORECASE, szTemp, -1, CHS_IMEFILENAME1, -1) != 2
594 && CompareStringA(LCID_INVARIANT, NORM_IGNORECASE, szTemp, -1, CHS_IMEFILENAME2, -1) != 2) {
595 dwRet[0] = dwRet[1] = 0;
596 return dwRet[uIndex];
598 #undef LCID_INVARIANT
599 dwVerSize = GetFileVersionInfoSizeA(szTemp, &dwVerHandle);
603 if (GetFileVersionInfoA(szTemp, dwVerHandle, dwVerSize, lpVerBuffer)) {
604 if (VerQueryValueA(lpVerBuffer,
"\\", &lpVerData, &cbVerData)) {
605 #define pVerFixedInfo ((VS_FIXEDFILEINFO FAR*)lpVerData)
606 DWORD dwVer = pVerFixedInfo->dwFileVersionMS;
607 dwVer = (dwVer & 0x00ff0000) << 8 | (dwVer & 0x000000ff) << 16;
608 if ((videodata->GetReadingString) ||
609 ((dwLang == LANG_CHT) && (
610 dwVer == MAKEIMEVERSION(4, 2) ||
611 dwVer == MAKEIMEVERSION(4, 3) ||
612 dwVer == MAKEIMEVERSION(4, 4) ||
613 dwVer == MAKEIMEVERSION(5, 0) ||
614 dwVer == MAKEIMEVERSION(5, 1) ||
615 dwVer == MAKEIMEVERSION(5, 2) ||
616 dwVer == MAKEIMEVERSION(6, 0)))
618 ((dwLang == LANG_CHS) && (
619 dwVer == MAKEIMEVERSION(4, 1) ||
620 dwVer == MAKEIMEVERSION(4, 2) ||
621 dwVer == MAKEIMEVERSION(5, 3)))) {
622 dwRet[0] = dwVer | dwLang;
623 dwRet[1] = pVerFixedInfo->dwFileVersionLS;
634 dwRet[0] = dwRet[1] = 0;
635 return dwRet[uIndex];
641 char ime_file[MAX_PATH + 1];
644 videodata->GetReadingString = 0;
645 videodata->ShowReadingWindow = 0;
650 if (ImmGetIMEFileNameA(hkl, ime_file,
sizeof(ime_file) - 1) <= 0)
657 videodata->GetReadingString = (UINT (WINAPI *)(HIMC, UINT, LPWSTR, PINT, BOOL*, PUINT))
659 videodata->ShowReadingWindow = (BOOL (WINAPI *)(HIMC, BOOL))
662 if (videodata->ShowReadingWindow) {
665 videodata->ShowReadingWindow(himc,
FALSE);
679 document_mgr->
lpVtbl->Release(document_mgr);
687 static HKL hklprev = 0;
688 videodata->
ime_hkl = GetKeyboardLayout(0);
689 if (hklprev == videodata->
ime_hkl)
693 switch (PRIMLANG()) {
696 if (SUBLANG() == SUBLANG_CHINESE_SIMPLIFIED)
720 ImmNotifyIME(himc, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
722 ImmSetCompositionString(himc, SCS_SETSTR, TEXT(
""),
sizeof(TCHAR), TEXT(
""),
sizeof(TCHAR));
724 ImmNotifyIME(himc, NI_CLOSECANDIDATE, 0, 0);
730IME_GetCompositionString(
SDL_VideoData *videodata, HIMC himc, DWORD
string)
737 videodata->
ime_cursor = LOWORD(ImmGetCompositionStringW(himc, GCS_CURSORPOS, 0, 0));
783IME_AddCandidate(
SDL_VideoData *videodata, UINT
i, LPCWSTR candidate)
791 *
dst++ = *candidate++;
799 LPCANDIDATELIST cand_list = 0;
800 DWORD
size = ImmGetCandidateListW(himc, 0, 0, 0);
804 size = ImmGetCandidateListW(himc, 0, cand_list,
size);
811 if (LANG() == LANG_CHS && IME_GetId(videodata, 0)) {
812 const UINT maxcandchar = 18;
816 size_t len =
SDL_wcslen((LPWSTR)((DWORD_PTR)cand_list + cand_list->dwOffset[
i])) + 1;
817 if (
len + cchars > maxcandchar) {
818 if (
i > cand_list->dwSelection)
838 for (
i = page_start,
j = 0; (DWORD)i < cand_list->dwCount &&
j < (
int)videodata->
ime_candpgsize;
i++,
j++) {
839 LPCWSTR candidate = (LPCWSTR)((DWORD_PTR)cand_list + cand_list->dwOffset[
i]);
840 IME_AddCandidate(videodata,
j, candidate);
842 if (PRIMLANG() == LANG_KOREAN || (PRIMLANG() == LANG_CHT && !IME_GetId(videodata, 0)))
856 IME_DestroyTextures(videodata);
857 IME_SendEditingEvent(videodata);
865 IME_DestroyTextures(videodata);
866 IME_SendEditingEvent(videodata);
878 case WM_INPUTLANGCHANGE:
879 IME_InputLangChanged(videodata);
881 case WM_IME_SETCONTEXT:
884 case WM_IME_STARTCOMPOSITION:
887 case WM_IME_COMPOSITION:
889 himc = ImmGetContext(hwnd);
890 if (*lParam & GCS_RESULTSTR) {
891 IME_GetCompositionString(videodata, himc, GCS_RESULTSTR);
892 IME_SendInputEvent(videodata);
894 if (*lParam & GCS_COMPSTR) {
898 IME_GetCompositionString(videodata, himc, GCS_COMPSTR);
899 IME_SendEditingEvent(videodata);
901 ImmReleaseContext(hwnd, himc);
903 case WM_IME_ENDCOMPOSITION:
911 case IMN_SETCONVERSIONMODE:
912 case IMN_SETOPENSTATUS:
913 IME_UpdateInputLocale(videodata);
915 case IMN_OPENCANDIDATE:
916 case IMN_CHANGECANDIDATE:
921 IME_ShowCandidateList(videodata);
922 himc = ImmGetContext(hwnd);
926 IME_GetCandidateList(himc, videodata);
927 ImmReleaseContext(hwnd, himc);
929 case IMN_CLOSECANDIDATE:
931 IME_HideCandidateList(videodata);
935 DWORD dwId = IME_GetId(videodata, 0);
936 IME_GetReadingString(videodata, hwnd);
939 case IMEID_CHT_VER42:
940 case IMEID_CHT_VER43:
941 case IMEID_CHT_VER44:
942 case IMEID_CHS_VER41:
943 case IMEID_CHS_VER42:
944 if (*lParam == 1 || *lParam == 2)
948 case IMEID_CHT_VER50:
949 case IMEID_CHT_VER51:
950 case IMEID_CHT_VER52:
951 case IMEID_CHT_VER60:
952 case IMEID_CHS_VER53:
975 IME_HideCandidateList(videodata);
990 pcandlist->
lpVtbl->GetSelection(pcandlist, &selection);
992 pcandlist->
lpVtbl->GetCurrentPage(pcandlist, &page);
996 IME_ShowCandidateList(videodata);
998 pcandlist->
lpVtbl->GetPageIndex(pcandlist, 0, 0, &pgcount);
1000 UINT *idxlist =
SDL_malloc(
sizeof(UINT) * pgcount);
1002 pcandlist->
lpVtbl->GetPageIndex(pcandlist, idxlist, pgcount, &pgcount);
1003 pgstart = idxlist[page];
1004 if (page < pgcount - 1)
1007 pgsize =
count - pgstart;
1016 for (
i = pgstart,
j = 0; (DWORD)
i <
count && j < videodata->ime_candpgsize;
i++,
j++) {
1020 IME_AddCandidate(videodata,
j, bstr);
1021 SysFreeString(bstr);
1025 if (PRIMLANG() == LANG_KOREAN)
1031 return ++
sink->refcount;
1034STDMETHODIMP_(ULONG) TSFSink_Release(
TSFSink *
sink)
1037 if (
sink->refcount == 0) {
1041 return sink->refcount;
1044STDMETHODIMP UIElementSink_QueryInterface(
TSFSink *
sink, REFIID riid, PVOID *ppv)
1051 *ppv = (IUnknown *)
sink;
1056 TSFSink_AddRef(
sink);
1068 if (
SUCCEEDED(threadmgrex->
lpVtbl->QueryInterface(threadmgrex, &IID_ITfUIElementMgr, (LPVOID *)&puiem))) {
1069 puiem->
lpVtbl->GetUIElement(puiem, dwUIElementId, &pelem);
1070 puiem->lpVtbl->Release(puiem);
1075STDMETHODIMP UIElementSink_BeginUIElement(
TSFSink *
sink, DWORD dwUIElementId, BOOL *pbShow)
1085 if (
SUCCEEDED(element->
lpVtbl->QueryInterface(element, &IID_ITfReadingInformationUIElement, (LPVOID *)&preading))) {
1087 if (
SUCCEEDED(preading->lpVtbl->GetString(preading, &bstr)) && bstr) {
1088 SysFreeString(bstr);
1090 preading->lpVtbl->Release(preading);
1092 else if (
SUCCEEDED(element->
lpVtbl->QueryInterface(element, &IID_ITfCandidateListUIElement, (LPVOID *)&pcandlist))) {
1094 UILess_GetCandidateList(videodata, pcandlist);
1095 pcandlist->lpVtbl->Release(pcandlist);
1100STDMETHODIMP UIElementSink_UpdateUIElement(
TSFSink *
sink, DWORD dwUIElementId)
1109 if (
SUCCEEDED(element->
lpVtbl->QueryInterface(element, &IID_ITfReadingInformationUIElement, (LPVOID *)&preading))) {
1111 if (
SUCCEEDED(preading->lpVtbl->GetString(preading, &bstr)) && bstr) {
1112 WCHAR *
s = (WCHAR *)bstr;
1114 IME_SendEditingEvent(videodata);
1115 SysFreeString(bstr);
1117 preading->lpVtbl->Release(preading);
1119 else if (
SUCCEEDED(element->
lpVtbl->QueryInterface(element, &IID_ITfCandidateListUIElement, (LPVOID *)&pcandlist))) {
1120 UILess_GetCandidateList(videodata, pcandlist);
1121 pcandlist->lpVtbl->Release(pcandlist);
1126STDMETHODIMP UIElementSink_EndUIElement(
TSFSink *
sink, DWORD dwUIElementId)
1135 if (
SUCCEEDED(element->
lpVtbl->QueryInterface(element, &IID_ITfReadingInformationUIElement, (LPVOID *)&preading))) {
1137 IME_SendEditingEvent(videodata);
1138 preading->lpVtbl->Release(preading);
1140 if (
SUCCEEDED(element->
lpVtbl->QueryInterface(element, &IID_ITfCandidateListUIElement, (LPVOID *)&pcandlist))) {
1143 IME_CloseCandidateList(videodata);
1145 pcandlist->lpVtbl->Release(pcandlist);
1150STDMETHODIMP IPPASink_QueryInterface(
TSFSink *
sink, REFIID riid, PVOID *ppv)
1157 *ppv = (IUnknown *)
sink;
1158 else if (
WIN_IsEqualIID(riid, &IID_ITfInputProcessorProfileActivationSink))
1162 TSFSink_AddRef(
sink);
1168STDMETHODIMP IPPASink_OnActivated(
TSFSink *
sink, DWORD dwProfileType, LANGID langid, REFCLSID clsid, REFGUID catid, REFGUID guidProfile, HKL hkl, DWORD dwFlags)
1170 static const GUID TF_PROFILE_DAYI = { 0x037B2C25, 0x480C, 0x4D7F, { 0xB0, 0x27, 0xD6, 0xCA, 0x6B, 0x69, 0x78, 0x8A } };
1176 IME_HideCandidateList(videodata);
1180static void *vtUIElementSink[] = {
1181 (
void *)(UIElementSink_QueryInterface),
1182 (
void *)(TSFSink_AddRef),
1183 (
void *)(TSFSink_Release),
1184 (
void *)(UIElementSink_BeginUIElement),
1185 (
void *)(UIElementSink_UpdateUIElement),
1186 (
void *)(UIElementSink_EndUIElement)
1189static void *vtIPPASink[] = {
1190 (
void *)(IPPASink_QueryInterface),
1191 (
void *)(TSFSink_AddRef),
1192 (
void *)(TSFSink_Release),
1193 (
void *)(IPPASink_OnActivated)
1229 if (
FAILED(CoCreateInstance(&CLSID_TF_ThreadMgr,
NULL, CLSCTX_INPROC_SERVER, &IID_ITfThreadMgrEx, (LPVOID *)&videodata->
ime_threadmgrex)))
1257#define SAFE_RELEASE(p) \
1260 (p)->lpVtbl->Release((p)); \
1283StartDrawToBitmap(HDC hdc, HBITMAP *hhbm,
int width,
int height)
1286 BITMAPINFOHEADER *infoHeader = &info.bmiHeader;
1290 infoHeader->biSize =
sizeof(BITMAPINFOHEADER);
1291 infoHeader->biWidth =
width;
1293 infoHeader->biPlanes = 1;
1294 infoHeader->biBitCount = 32;
1295 infoHeader->biCompression =
BI_RGB;
1296 *hhbm = CreateDIBSection(hdc, &info, DIB_RGB_COLORS, (
void **)&
bits, 0, 0);
1298 SelectObject(hdc, *hhbm);
1304StopDrawToBitmap(HDC hdc, HBITMAP *hhbm)
1306 if (hhbm && *hhbm) {
1307 DeleteObject(*hhbm);
1317 const int penadjust = (int)
SDL_floor(pensize / 2.0f - 0.5f);
1318 left += pensize / 2;
1330#define SDL_swap(a,b) { \
1349 if (
right >= winw) {
1362 if (
right >= winw) {
1410 SIZE maxcandsize = {0};
1415 const int listborder = 1;
1416 const int listpadding = 0;
1417 const int listbordercolor =
RGB(0xB4, 0xC7, 0xAA);
1418 const int listfillcolor =
RGB(255, 255, 255);
1420 const int candborder = 1;
1421 const int candpadding = 0;
1422 const int candmargin = 1;
1423 const COLORREF candbordercolor =
RGB(255, 255, 255);
1424 const COLORREF candfillcolor =
RGB(255, 255, 255);
1425 const COLORREF candtextcolor =
RGB(0, 0, 0);
1426 const COLORREF selbordercolor =
RGB(0x84, 0xAC, 0xDD);
1427 const COLORREF selfillcolor =
RGB(0xD2, 0xE6, 0xFF);
1428 const COLORREF seltextcolor =
RGB(0, 0, 0);
1429 const int horzcandspacing = 5;
1431 HPEN listpen = listborder != 0 ? CreatePen(PS_SOLID, listborder, listbordercolor) : (HPEN)GetStockObject(NULL_PEN);
1432 HBRUSH listbrush = CreateSolidBrush(listfillcolor);
1433 HPEN candpen = candborder != 0 ? CreatePen(PS_SOLID, candborder, candbordercolor) : (HPEN)GetStockObject(NULL_PEN);
1434 HBRUSH candbrush = CreateSolidBrush(candfillcolor);
1435 HPEN selpen = candborder != 0 ? CreatePen(PS_DOT, candborder, selbordercolor) : (HPEN)GetStockObject(NULL_PEN);
1436 HBRUSH selbrush = CreateSolidBrush(selfillcolor);
1437 HFONT font = CreateFont((
int)(1 + videodata->
ime_rect.
h * 0.75f), 0, 0, 0, FW_NORMAL,
FALSE,
FALSE,
FALSE, DEFAULT_CHARSET, OUT_CHARACTER_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, VARIABLE_PITCH | FF_SWISS, TEXT(
"Microsoft Sans Serif"));
1439 SetBkMode(hdc, TRANSPARENT);
1440 SelectObject(hdc, font);
1442 for (
i = 0;
i < candcount; ++
i) {
1447 GetTextExtentPoint32W(hdc,
s, (
int)
SDL_wcslen(
s), &candsizes[
i]);
1448 maxcandsize.cx =
SDL_max(maxcandsize.cx, candsizes[
i].cx);
1449 maxcandsize.cy =
SDL_max(maxcandsize.cy, candsizes[
i].cy);
1464 ((candcount + 1) * candmargin) +
1465 (candcount * candborder * 2) +
1466 (candcount * candpadding * 2) +
1467 (candcount * maxcandsize.cy)
1474 ((candcount + 1) * candmargin) +
1475 (candcount * candborder * 2) +
1476 (candcount * candpadding * 2) +
1477 ((candcount - 1) * horzcandspacing);
1480 for (
i = 0;
i < candcount; ++
i)
1481 size.cx += candsizes[
i].cx;
1493 StartDrawToBitmap(hdc, &hbm,
size.cx,
size.cy);
1495 SelectObject(hdc, listpen);
1496 SelectObject(hdc, listbrush);
1499 SelectObject(hdc, candpen);
1500 SelectObject(hdc, candbrush);
1501 SetTextColor(hdc, candtextcolor);
1502 SetBkMode(hdc, TRANSPARENT);
1504 for (
i = 0;
i < candcount; ++
i) {
1511 left = listborder + listpadding + candmargin;
1512 top = listborder + listpadding + (
i * candborder * 2) + (
i * candpadding * 2) + ((
i + 1) * candmargin) + (
i * maxcandsize.cy);
1513 right =
size.cx - listborder - listpadding - candmargin;
1514 bottom =
top + maxcandsize.cy + (candpadding * 2) + (candborder * 2);
1517 left = listborder + listpadding + (
i * candborder * 2) + (
i * candpadding * 2) + ((
i + 1) * candmargin) + (
i * horzcandspacing);
1519 for (
j = 0;
j <
i; ++
j)
1520 left += candsizes[
j].cx;
1522 top = listborder + listpadding + candmargin;
1523 right =
left + candsizes[
i].cx + (candpadding * 2) + (candborder * 2);
1524 bottom =
size.cy - listborder - listpadding - candmargin;
1528 SelectObject(hdc, selpen);
1529 SelectObject(hdc, selbrush);
1530 SetTextColor(hdc, seltextcolor);
1533 SelectObject(hdc, candpen);
1534 SelectObject(hdc, candbrush);
1535 SetTextColor(hdc, candtextcolor);
1541 StopDrawToBitmap(hdc, &hbm);
1543 DeleteObject(listpen);
1544 DeleteObject(listbrush);
1545 DeleteObject(candpen);
1546 DeleteObject(candbrush);
1547 DeleteObject(selpen);
1548 DeleteObject(selbrush);
1551 IME_PositionCandidateList(videodata,
size);
1557 HDC hdc = CreateCompatibleDC(
NULL);
1560 IME_RenderCandidateList(videodata, hdc);
1570 IME_Render(videodata);
#define SDL_GetWindowSize
#define SDL_GetKeyboardFocus
#define SDL_InvalidParamError(param)
#define SDL_TEXTEDITINGEVENT_TEXT_SIZE
void SDL_SetScancodeName(SDL_Scancode scancode, const char *name)
void SDL_GetDefaultKeymap(SDL_Keycode *keymap)
void SDL_ToggleModState(const SDL_Keymod modstate, const SDL_bool toggle)
void SDL_SetKeymap(int start, SDL_Keycode *keys, int length)
int SDL_SendEditingText(const char *text, int start, int length)
int SDL_SendKeyboardText(const char *text)
#define SDLK_SCANCODE_MASK
Sint32 SDL_Keycode
The SDL virtual key representation.
void * SDL_LoadFunction(void *handle, const char *name)
#define TF_TMAE_UIELEMENTENABLEDONLY
#define TF_INVALID_COOKIE
#define TF_IPSINK_FLAG_ACTIVE
GLuint GLuint GLsizei count
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
GLint GLint GLsizei width
GLint GLint GLsizei GLsizei height
GLdouble GLdouble GLdouble GLdouble top
GLsizei GLsizei GLchar * source
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const void * bits
GLsizei GLenum GLboolean sink
GLuint GLsizei GLsizei * length
SDL_Scancode
The SDL keyboard scancode representation.
@ SDL_SCANCODE_APPLICATION
#define SDL_arraysize(array)
static SDL_VideoDevice * _this
HRESULT WIN_CoInitialize(void)
void WIN_CoUninitialize(void)
BOOL WIN_IsEqualIID(REFIID a, REFIID b)
#define WIN_StringToUTF8(S)
BOOL WIN_IsEqualGUID(const GUID *a, const GUID *b)
void WIN_SetTextInputRect(_THIS, SDL_Rect *rect)
void WIN_ResetDeadKeys(void)
SDL_bool IME_HandleMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM *lParam, struct SDL_VideoData *videodata)
void WIN_InitKeyboard(_THIS)
void WIN_StopTextInput(_THIS)
void WIN_UpdateKeymap(void)
void WIN_StartTextInput(_THIS)
void WIN_QuitKeyboard(_THIS)
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int int in j)
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
EGLSurface EGLNativeWindowType * window
static const SDL_Scancode windows_scancode_table[]
const struct ITfCandidateListUIElementVtbl * lpVtbl
const struct ITfDocumentMgrVtbl * lpVtbl
const struct ITfSourceVtbl * lpVtbl
const struct ITfThreadMgrExVtbl * lpVtbl
const struct ITfThreadMgrVtbl * lpVtbl
const struct ITfUIElementVtbl * lpVtbl
A rectangle, with the origin at the upper left (integer).
struct ITfThreadMgr * ime_threadmgr
int ime_candlistindexbase
SDL_bool ime_candvertical
SDL_bool ime_com_initialized
WCHAR ime_candidates[MAX_CANDLIST][MAX_CANDLENGTH]
SDL_Rect ime_candlistrect
WCHAR ime_readingstring[16]
struct ITfThreadMgrEx * ime_threadmgrex
DWORD ime_uielemsinkcookie
WCHAR ime_composition[SDL_TEXTEDITINGEVENT_TEXT_SIZE]
The type used to identify a window.
static void DrawRect(SDL_Renderer *r, const int x, const int y, const int w, const int h)