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 85 data->GetReadingString = 0;
86 data->ShowReadingWindow = 0;
88 data->ImmUnlockIMC = 0;
89 data->ImmLockIMCC = 0;
90 data->ImmUnlockIMCC = 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 272 #define USE_INIT_GUID 273 #elif defined(__GNUC__) 274 #define USE_INIT_GUID 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}} 279 DEFINE_GUID(IID_ITfInputProcessorProfileActivationSink, 0x71C6E74E,0x0F28,0x11D8,0xA8,0x2A,0x00,0x06,0x5B,0x84,0x43,0x5C);
280 DEFINE_GUID(IID_ITfUIElementSink, 0xEA1EA136,0x19DF,0x11D7,0xA6,0xD2,0x00,0x06,0x5B,0x84,0x43,0x5C);
281 DEFINE_GUID(GUID_TFCAT_TIP_KEYBOARD, 0x34745C63,0xB2F0,0x4784,0x8B,0x67,0x5E,0x12,0xC8,0x70,0x1A,0x31);
282 DEFINE_GUID(IID_ITfSource, 0x4EA48A35,0x60AE,0x446F,0x8F,0xD6,0xE6,0xA8,0xD8,0x24,0x59,0xF7);
283 DEFINE_GUID(IID_ITfUIElementMgr, 0xEA1EA135,0x19DF,0x11D7,0xA6,0xD2,0x00,0x06,0x5B,0x84,0x43,0x5C);
284 DEFINE_GUID(IID_ITfCandidateListUIElement, 0xEA1EA138,0x19DF,0x11D7,0xA6,0xD2,0x00,0x06,0x5B,0x84,0x43,0x5C);
285 DEFINE_GUID(IID_ITfReadingInformationUIElement, 0xEA1EA139,0x19DF,0x11D7,0xA6,0xD2,0x00,0x06,0x5B,0x84,0x43,0x5C);
286 DEFINE_GUID(IID_ITfThreadMgr, 0xAA80E801,0x2021,0x11D2,0x93,0xE0,0x00,0x60,0xB0,0x67,0xB8,0x6E);
287 DEFINE_GUID(CLSID_TF_ThreadMgr, 0x529A9E6B,0x6587,0x4F23,0xAB,0x9E,0x9C,0x7D,0x68,0x3E,0x3C,0x50);
288 DEFINE_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)0xE0060404) 299 #define CHT_HKL_NEW_PHONETIC ((HKL)0xE0080404) 300 #define CHT_HKL_NEW_CHANG_JIE ((HKL)0xE0090404) 301 #define CHT_HKL_NEW_QUICK ((HKL)0xE00A0404) 302 #define CHT_HKL_HK_CANTONESE ((HKL)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)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()) 328 static void IME_SetWindow(
SDL_VideoData* videodata, HWND hwnd);
334 #define SDL_IsEqualIID(riid1, riid2) SDL_IsEqualGUID(riid1, riid2) 335 #define SDL_IsEqualGUID(rguid1, rguid2) (!SDL_memcmp(rguid1, rguid2, sizeof(GUID))) 339 static void UILess_EnableUIUpdates(
SDL_VideoData *videodata);
340 static void UILess_DisableUIUpdates(
SDL_VideoData *videodata);
351 CoCreateInstance(&CLSID_TF_ThreadMgr,
NULL, CLSCTX_INPROC_SERVER, &IID_ITfThreadMgr, (
LPVOID *)&videodata->
ime_threadmgr);
364 IME_SetWindow(videodata, hwnd);
365 videodata->
ime_himc = ImmGetContext(hwnd);
366 ImmReleaseContext(hwnd, videodata->
ime_himc);
369 IME_Disable(videodata, hwnd);
373 IME_UpdateInputLocale(videodata);
374 IME_SetupAPI(videodata);
375 videodata->
ime_uiless = UILess_SetupSinks(videodata);
376 IME_UpdateInputLocale(videodata);
377 IME_Disable(videodata, hwnd);
387 IME_Disable(videodata, hwnd);
394 IME_UpdateInputLocale(videodata);
395 UILess_EnableUIUpdates(videodata);
404 IME_ClearComposition(videodata);
409 UILess_DisableUIUpdates(videodata);
418 UILess_ReleaseSinks(videodata);
436 IME_DestroyTextures(videodata);
451 static OSVERSIONINFOA osversion;
457 if (!osversion.dwOSVersionInfoSize) {
458 osversion.dwOSVersionInfoSize =
sizeof(osversion);
459 GetVersionExA(&osversion);
461 id = IME_GetId(videodata, 0);
465 himc = ImmGetContext(hwnd);
469 if (videodata->GetReadingString) {
470 len = videodata->GetReadingString(himc, 0, 0, &err, &vertical, &maxuilen);
475 len = videodata->GetReadingString(himc, len, s, &err, &vertical, &maxuilen);
485 case IMEID_CHT_VER42:
486 case IMEID_CHT_VER43:
487 case IMEID_CHT_VER44:
488 p = *(LPBYTE *)((LPBYTE)videodata->ImmLockIMCC(lpimc->hPrivate) + 24);
492 len = *(DWORD *)(p + 7*4 + 32*4);
493 s = (WCHAR *)(p + 56);
495 case IMEID_CHT_VER51:
496 case IMEID_CHT_VER52:
497 case IMEID_CHS_VER53:
498 p = *(LPBYTE *)((LPBYTE)videodata->ImmLockIMCC(lpimc->hPrivate) + 4);
502 p = *(LPBYTE *)((LPBYTE)p + 1*4 + 5*4);
506 len = *(DWORD *)(p + 1*4 + (16*2+2*4) + 5*4 + 16*2);
507 s = (WCHAR *)(p + 1*4 + (16*2+2*4) + 5*4);
509 case IMEID_CHS_VER41:
511 int offset = (IME_GetId(videodata, 1) >= 0x00000002) ? 8 : 7;
512 p = *(LPBYTE *)((LPBYTE)videodata->ImmLockIMCC(lpimc->hPrivate) + offset * 4);
516 len = *(DWORD *)(p + 7*4 + 16*2*4);
517 s = (WCHAR *)(p + 6*4 + 16*2*1);
520 case IMEID_CHS_VER42:
521 if (osversion.dwPlatformId != VER_PLATFORM_WIN32_NT)
524 p = *(LPBYTE *)((LPBYTE)videodata->ImmLockIMCC(lpimc->hPrivate) + 1*4 + 1*4 + 6*4);
528 len = *(DWORD *)(p + 1*4 + (16*2+2*4) + 5*4 + 16*2);
529 s = (WCHAR *)(p + 1*4 + (16*2+2*4) + 5*4);
537 videodata->ImmUnlockIMCC(lpimc->hPrivate);
538 videodata->ImmUnlockIMC(himc);
540 ImmReleaseContext(hwnd, himc);
541 IME_SendEditingEvent(videodata);
547 UINT lang = PRIMLANG();
548 IME_UpdateInputLocale(videodata);
552 IME_SetupAPI(videodata);
553 if (lang != PRIMLANG()) {
554 IME_ClearComposition(videodata);
561 static HKL hklprev = 0;
562 static DWORD dwRet[2] = {0};
564 DWORD dwVerHandle = 0;
571 if (uIndex >=
sizeof(dwRet) /
sizeof(dwRet[0]))
576 return dwRet[uIndex];
579 dwLang = ((DWORD_PTR)hkl & 0xffff);
580 if (videodata->
ime_uiless && LANG() == LANG_CHT) {
581 dwRet[0] = IMEID_CHT_VER_VISTA;
585 if (hkl != CHT_HKL_NEW_PHONETIC
586 && hkl != CHT_HKL_NEW_CHANG_JIE
587 && hkl != CHT_HKL_NEW_QUICK
588 && hkl != CHT_HKL_HK_CANTONESE
590 dwRet[0] = dwRet[1] = 0;
591 return dwRet[uIndex];
593 if (ImmGetIMEFileNameA(hkl, szTemp,
sizeof(szTemp) - 1) <= 0) {
594 dwRet[0] = dwRet[1] = 0;
595 return dwRet[uIndex];
597 if (!videodata->GetReadingString) {
598 #define LCID_INVARIANT MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT) 599 if (CompareStringA(LCID_INVARIANT, NORM_IGNORECASE, szTemp, -1, CHT_IMEFILENAME1, -1) != 2
600 && CompareStringA(LCID_INVARIANT, NORM_IGNORECASE, szTemp, -1, CHT_IMEFILENAME2, -1) != 2
601 && CompareStringA(LCID_INVARIANT, NORM_IGNORECASE, szTemp, -1, CHT_IMEFILENAME3, -1) != 2
602 && CompareStringA(LCID_INVARIANT, NORM_IGNORECASE, szTemp, -1, CHS_IMEFILENAME1, -1) != 2
603 && CompareStringA(LCID_INVARIANT, NORM_IGNORECASE, szTemp, -1, CHS_IMEFILENAME2, -1) != 2) {
604 dwRet[0] = dwRet[1] = 0;
605 return dwRet[uIndex];
607 #undef LCID_INVARIANT 608 dwVerSize = GetFileVersionInfoSizeA(szTemp, &dwVerHandle);
612 if (GetFileVersionInfoA(szTemp, dwVerHandle, dwVerSize, lpVerBuffer)) {
613 if (VerQueryValueA(lpVerBuffer,
"\\", &lpVerData, &cbVerData)) {
614 #define pVerFixedInfo ((VS_FIXEDFILEINFO FAR*)lpVerData) 615 DWORD dwVer = pVerFixedInfo->dwFileVersionMS;
616 dwVer = (dwVer & 0x00ff0000) << 8 | (dwVer & 0x000000ff) << 16;
617 if ((videodata->GetReadingString) ||
618 ((dwLang == LANG_CHT) && (
619 dwVer == MAKEIMEVERSION(4, 2) ||
620 dwVer == MAKEIMEVERSION(4, 3) ||
621 dwVer == MAKEIMEVERSION(4, 4) ||
622 dwVer == MAKEIMEVERSION(5, 0) ||
623 dwVer == MAKEIMEVERSION(5, 1) ||
624 dwVer == MAKEIMEVERSION(5, 2) ||
625 dwVer == MAKEIMEVERSION(6, 0)))
627 ((dwLang == LANG_CHS) && (
628 dwVer == MAKEIMEVERSION(4, 1) ||
629 dwVer == MAKEIMEVERSION(4, 2) ||
630 dwVer == MAKEIMEVERSION(5, 3)))) {
631 dwRet[0] = dwVer | dwLang;
632 dwRet[1] = pVerFixedInfo->dwFileVersionLS;
643 dwRet[0] = dwRet[1] = 0;
644 return dwRet[uIndex];
650 char ime_file[MAX_PATH + 1];
653 videodata->GetReadingString = 0;
654 videodata->ShowReadingWindow = 0;
659 if (ImmGetIMEFileNameA(hkl, ime_file,
sizeof(ime_file) - 1) <= 0)
666 videodata->GetReadingString = (
UINT (WINAPI *)(HIMC,
UINT, LPWSTR, PINT,
BOOL*, PUINT))
668 videodata->ShowReadingWindow = (
BOOL (WINAPI *)(HIMC,
BOOL))
671 if (videodata->ShowReadingWindow) {
674 videodata->ShowReadingWindow(himc,
FALSE);
688 document_mgr->
lpVtbl->Release(document_mgr);
696 static HKL hklprev = 0;
697 videodata->
ime_hkl = GetKeyboardLayout(0);
698 if (hklprev == videodata->
ime_hkl)
702 switch (PRIMLANG()) {
705 if (SUBLANG() == SUBLANG_CHINESE_SIMPLIFIED)
729 ImmNotifyIME(himc, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
731 ImmSetCompositionString(himc, SCS_SETSTR, TEXT(
""),
sizeof(TCHAR), TEXT(
""),
sizeof(TCHAR));
733 ImmNotifyIME(himc, NI_CLOSECANDIDATE, 0, 0);
739 IME_GetCompositionString(
SDL_VideoData *videodata, HIMC himc, DWORD
string)
746 videodata->
ime_cursor = LOWORD(ImmGetCompositionStringW(himc, GCS_CURSORPOS, 0, 0));
749 for (i = videodata->
ime_cursor + 1; i < length; ++i)
792 IME_AddCandidate(
SDL_VideoData *videodata, UINT i, LPCWSTR candidate)
800 *dst++ = *candidate++;
808 LPCANDIDATELIST cand_list = 0;
809 DWORD size = ImmGetCandidateListW(himc, 0, 0, 0);
811 cand_list = (LPCANDIDATELIST)
SDL_malloc(size);
813 size = ImmGetCandidateListW(himc, 0, cand_list, size);
820 if (LANG() == LANG_CHS && IME_GetId(videodata, 0)) {
821 const UINT maxcandchar = 18;
825 size_t len =
SDL_wcslen((LPWSTR)((DWORD_PTR)cand_list + cand_list->dwOffset[i])) + 1;
826 if (len + cchars > maxcandchar) {
827 if (i > cand_list->dwSelection)
843 for (i = page_start, j = 0; (DWORD)i < cand_list->dwCount && j < (
int)videodata->
ime_candpgsize; i++, j++) {
844 LPCWSTR candidate = (LPCWSTR)((DWORD_PTR)cand_list + cand_list->dwOffset[
i]);
845 IME_AddCandidate(videodata, j, candidate);
847 if (PRIMLANG() == LANG_KOREAN || (PRIMLANG() == LANG_CHT && !IME_GetId(videodata, 0)))
861 IME_DestroyTextures(videodata);
862 IME_SendEditingEvent(videodata);
870 IME_DestroyTextures(videodata);
871 IME_SendEditingEvent(videodata);
883 case WM_INPUTLANGCHANGE:
884 IME_InputLangChanged(videodata);
886 case WM_IME_SETCONTEXT:
889 case WM_IME_STARTCOMPOSITION:
892 case WM_IME_COMPOSITION:
894 himc = ImmGetContext(hwnd);
895 if (*lParam & GCS_RESULTSTR) {
896 IME_GetCompositionString(videodata, himc, GCS_RESULTSTR);
897 IME_SendInputEvent(videodata);
899 if (*lParam & GCS_COMPSTR) {
903 IME_GetCompositionString(videodata, himc, GCS_COMPSTR);
904 IME_SendEditingEvent(videodata);
906 ImmReleaseContext(hwnd, himc);
908 case WM_IME_ENDCOMPOSITION:
916 case IMN_SETCONVERSIONMODE:
917 case IMN_SETOPENSTATUS:
918 IME_UpdateInputLocale(videodata);
920 case IMN_OPENCANDIDATE:
921 case IMN_CHANGECANDIDATE:
926 IME_ShowCandidateList(videodata);
927 himc = ImmGetContext(hwnd);
931 IME_GetCandidateList(himc, videodata);
932 ImmReleaseContext(hwnd, himc);
934 case IMN_CLOSECANDIDATE:
936 IME_HideCandidateList(videodata);
940 DWORD dwId = IME_GetId(videodata, 0);
941 IME_GetReadingString(videodata, hwnd);
944 case IMEID_CHT_VER42:
945 case IMEID_CHT_VER43:
946 case IMEID_CHT_VER44:
947 case IMEID_CHS_VER41:
948 case IMEID_CHS_VER42:
949 if (*lParam == 1 || *lParam == 2)
953 case IMEID_CHT_VER50:
954 case IMEID_CHT_VER51:
955 case IMEID_CHT_VER52:
956 case IMEID_CHT_VER60:
957 case IMEID_CHS_VER53:
980 IME_HideCandidateList(videodata);
995 pcandlist->
lpVtbl->GetSelection(pcandlist, &selection);
996 pcandlist->
lpVtbl->GetCount(pcandlist, &count);
997 pcandlist->
lpVtbl->GetCurrentPage(pcandlist, &page);
1001 IME_ShowCandidateList(videodata);
1003 pcandlist->
lpVtbl->GetPageIndex(pcandlist, 0, 0, &pgcount);
1005 UINT *idxlist =
SDL_malloc(
sizeof(UINT) * pgcount);
1007 pcandlist->
lpVtbl->GetPageIndex(pcandlist, idxlist, pgcount, &pgcount);
1008 pgstart = idxlist[page];
1009 if (page < pgcount - 1)
1010 pgsize =
SDL_min(count, idxlist[page + 1]) - pgstart;
1012 pgsize = count - pgstart;
1021 for (i = pgstart, j = 0; (DWORD)i < count && j < videodata->ime_candpgsize; i++, j++) {
1025 IME_AddCandidate(videodata, j, bstr);
1026 SysFreeString(bstr);
1030 if (PRIMLANG() == LANG_KOREAN)
1034 STDMETHODIMP_(ULONG) TSFSink_AddRef(
TSFSink *
sink)
1039 STDMETHODIMP_(ULONG)TSFSink_Release(
TSFSink *
sink)
1049 STDMETHODIMP UIElementSink_QueryInterface(
TSFSink *sink, REFIID riid, PVOID *ppv)
1055 if (SDL_IsEqualIID(riid, &IID_IUnknown))
1056 *ppv = (IUnknown *)sink;
1057 else if (SDL_IsEqualIID(riid, &IID_ITfUIElementSink))
1061 TSFSink_AddRef(sink);
1073 if (
SUCCEEDED(threadmgrex->
lpVtbl->QueryInterface(threadmgrex, &IID_ITfUIElementMgr, (LPVOID *)&puiem))) {
1074 puiem->
lpVtbl->GetUIElement(puiem, dwUIElementId, &pelem);
1075 puiem->lpVtbl->Release(puiem);
1080 STDMETHODIMP UIElementSink_BeginUIElement(
TSFSink *sink, DWORD dwUIElementId, BOOL *pbShow)
1090 if (
SUCCEEDED(element->
lpVtbl->QueryInterface(element, &IID_ITfReadingInformationUIElement, (LPVOID *)&preading))) {
1092 if (
SUCCEEDED(preading->lpVtbl->GetString(preading, &bstr)) && bstr) {
1093 SysFreeString(bstr);
1095 preading->lpVtbl->Release(preading);
1097 else if (
SUCCEEDED(element->
lpVtbl->QueryInterface(element, &IID_ITfCandidateListUIElement, (LPVOID *)&pcandlist))) {
1099 UILess_GetCandidateList(videodata, pcandlist);
1100 pcandlist->lpVtbl->Release(pcandlist);
1105 STDMETHODIMP UIElementSink_UpdateUIElement(
TSFSink *sink, DWORD dwUIElementId)
1114 if (
SUCCEEDED(element->
lpVtbl->QueryInterface(element, &IID_ITfReadingInformationUIElement, (LPVOID *)&preading))) {
1116 if (
SUCCEEDED(preading->lpVtbl->GetString(preading, &bstr)) && bstr) {
1117 WCHAR *s = (WCHAR *)bstr;
1119 IME_SendEditingEvent(videodata);
1120 SysFreeString(bstr);
1122 preading->lpVtbl->Release(preading);
1124 else if (
SUCCEEDED(element->
lpVtbl->QueryInterface(element, &IID_ITfCandidateListUIElement, (LPVOID *)&pcandlist))) {
1125 UILess_GetCandidateList(videodata, pcandlist);
1126 pcandlist->lpVtbl->Release(pcandlist);
1131 STDMETHODIMP UIElementSink_EndUIElement(
TSFSink *sink, DWORD dwUIElementId)
1140 if (
SUCCEEDED(element->
lpVtbl->QueryInterface(element, &IID_ITfReadingInformationUIElement, (LPVOID *)&preading))) {
1142 IME_SendEditingEvent(videodata);
1143 preading->lpVtbl->Release(preading);
1145 if (
SUCCEEDED(element->
lpVtbl->QueryInterface(element, &IID_ITfCandidateListUIElement, (LPVOID *)&pcandlist))) {
1148 IME_CloseCandidateList(videodata);
1150 pcandlist->lpVtbl->Release(pcandlist);
1155 STDMETHODIMP IPPASink_QueryInterface(
TSFSink *sink, REFIID riid, PVOID *ppv)
1161 if (SDL_IsEqualIID(riid, &IID_IUnknown))
1162 *ppv = (IUnknown *)sink;
1163 else if (SDL_IsEqualIID(riid, &IID_ITfInputProcessorProfileActivationSink))
1167 TSFSink_AddRef(sink);
1173 STDMETHODIMP IPPASink_OnActivated(
TSFSink *sink, DWORD dwProfileType, LANGID langid, REFCLSID clsid, REFGUID catid, REFGUID guidProfile, HKL hkl, DWORD dwFlags)
1175 static const GUID TF_PROFILE_DAYI = { 0x037B2C25, 0x480C, 0x4D7F, { 0xB0, 0x27, 0xD6, 0xCA, 0x6B, 0x69, 0x78, 0x8A } };
1181 IME_HideCandidateList(videodata);
1185 static void *vtUIElementSink[] = {
1186 (
void *)(UIElementSink_QueryInterface),
1187 (
void *)(TSFSink_AddRef),
1188 (
void *)(TSFSink_Release),
1189 (
void *)(UIElementSink_BeginUIElement),
1190 (
void *)(UIElementSink_UpdateUIElement),
1191 (
void *)(UIElementSink_EndUIElement)
1194 static void *vtIPPASink[] = {
1195 (
void *)(IPPASink_QueryInterface),
1196 (
void *)(TSFSink_AddRef),
1197 (
void *)(TSFSink_Release),
1198 (
void *)(IPPASink_OnActivated)
1210 source->lpVtbl->Release(source);
1224 source->lpVtbl->Release(source);
1234 if (
FAILED(CoCreateInstance(&CLSID_TF_ThreadMgr,
NULL, CLSCTX_INPROC_SERVER, &IID_ITfThreadMgrEx, (LPVOID *)&videodata->
ime_threadmgrex)))
1257 source->lpVtbl->Release(source);
1262 #define SAFE_RELEASE(p) \ 1265 (p)->lpVtbl->Release((p)); \ 1277 SAFE_RELEASE(source);
1288 StartDrawToBitmap(HDC hdc, HBITMAP *hhbm,
int width,
int height)
1291 BITMAPINFOHEADER *infoHeader = &info.bmiHeader;
1295 infoHeader->biSize =
sizeof(BITMAPINFOHEADER);
1296 infoHeader->biWidth =
width;
1297 infoHeader->biHeight = -1 *
SDL_abs(height);
1298 infoHeader->biPlanes = 1;
1299 infoHeader->biBitCount = 32;
1300 infoHeader->biCompression =
BI_RGB;
1301 *hhbm = CreateDIBSection(hdc, &info, DIB_RGB_COLORS, (
void **)&bits, 0, 0);
1303 SelectObject(hdc, *hhbm);
1309 StopDrawToBitmap(HDC hdc, HBITMAP *hhbm)
1311 if (hhbm && *hhbm) {
1312 DeleteObject(*hhbm);
1322 const int penadjust = (int)
SDL_floor(pensize / 2.0
f - 0.5
f);
1323 left += pensize / 2;
1326 bottom -= penadjust;
1327 Rectangle(hdc, left, top, right, bottom);
1335 #define SDL_swap(a,b) { \ 1342 IME_PositionCandidateList(
SDL_VideoData *videodata, SIZE size)
1352 right = left + size.cx;
1353 bottom = top + size.cy;
1354 if (right >= winw) {
1355 left -= right - winw;
1365 right = left + size.cx;
1367 if (right >= winw) {
1368 left -= right - winw;
1379 right = left + size.cx;
1415 SIZE maxcandsize = {0};
1420 const int listborder = 1;
1421 const int listpadding = 0;
1422 const int listbordercolor =
RGB(0xB4, 0xC7, 0xAA);
1423 const int listfillcolor =
RGB(255, 255, 255);
1425 const int candborder = 1;
1426 const int candpadding = 0;
1427 const int candmargin = 1;
1428 const COLORREF candbordercolor =
RGB(255, 255, 255);
1429 const COLORREF candfillcolor =
RGB(255, 255, 255);
1430 const COLORREF candtextcolor =
RGB(0, 0, 0);
1431 const COLORREF selbordercolor =
RGB(0x84, 0xAC, 0xDD);
1432 const COLORREF selfillcolor =
RGB(0xD2, 0xE6, 0xFF);
1433 const COLORREF seltextcolor =
RGB(0, 0, 0);
1434 const int horzcandspacing = 5;
1436 HPEN listpen = listborder != 0 ? CreatePen(PS_SOLID, listborder, listbordercolor) : (HPEN)GetStockObject(NULL_PEN);
1437 HBRUSH listbrush = CreateSolidBrush(listfillcolor);
1438 HPEN candpen = candborder != 0 ? CreatePen(PS_SOLID, candborder, candbordercolor) : (HPEN)GetStockObject(NULL_PEN);
1439 HBRUSH candbrush = CreateSolidBrush(candfillcolor);
1440 HPEN selpen = candborder != 0 ? CreatePen(PS_DOT, candborder, selbordercolor) : (HPEN)GetStockObject(NULL_PEN);
1441 HBRUSH selbrush = CreateSolidBrush(selfillcolor);
1442 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"));
1444 SetBkMode(hdc, TRANSPARENT);
1445 SelectObject(hdc, font);
1447 for (i = 0; i < candcount; ++
i) {
1452 GetTextExtentPoint32W(hdc, s, (
int)
SDL_wcslen(s), &candsizes[i]);
1453 maxcandsize.cx =
SDL_max(maxcandsize.cx, candsizes[i].cx);
1454 maxcandsize.cy =
SDL_max(maxcandsize.cy, candsizes[i].cy);
1469 ((candcount + 1) * candmargin) +
1470 (candcount * candborder * 2) +
1471 (candcount * candpadding * 2) +
1472 (candcount * maxcandsize.cy)
1479 ((candcount + 1) * candmargin) +
1480 (candcount * candborder * 2) +
1481 (candcount * candpadding * 2) +
1482 ((candcount - 1) * horzcandspacing);
1485 for (i = 0; i < candcount; ++
i)
1486 size.cx += candsizes[i].cx;
1498 StartDrawToBitmap(hdc, &hbm, size.cx, size.cy);
1500 SelectObject(hdc, listpen);
1501 SelectObject(hdc, listbrush);
1502 DrawRect(hdc, 0, 0, size.cx, size.cy, listborder);
1504 SelectObject(hdc, candpen);
1505 SelectObject(hdc, candbrush);
1506 SetTextColor(hdc, candtextcolor);
1507 SetBkMode(hdc, TRANSPARENT);
1509 for (i = 0; i < candcount; ++
i) {
1516 left = listborder + listpadding + candmargin;
1517 top = listborder + listpadding + (i * candborder * 2) + (i * candpadding * 2) + ((i + 1) * candmargin) + (i * maxcandsize.cy);
1518 right = size.cx - listborder - listpadding - candmargin;
1519 bottom = top + maxcandsize.cy + (candpadding * 2) + (candborder * 2);
1522 left = listborder + listpadding + (i * candborder * 2) + (i * candpadding * 2) + ((i + 1) * candmargin) + (i * horzcandspacing);
1524 for (j = 0; j <
i; ++
j)
1525 left += candsizes[j].cx;
1527 top = listborder + listpadding + candmargin;
1528 right = left + candsizes[
i].cx + (candpadding * 2) + (candborder * 2);
1529 bottom = size.cy - listborder - listpadding - candmargin;
1533 SelectObject(hdc, selpen);
1534 SelectObject(hdc, selbrush);
1535 SetTextColor(hdc, seltextcolor);
1538 SelectObject(hdc, candpen);
1539 SelectObject(hdc, candbrush);
1540 SetTextColor(hdc, candtextcolor);
1543 DrawRect(hdc, left, top, right, bottom, candborder);
1544 ExtTextOutW(hdc, left + candborder + candpadding, top + candborder + candpadding, 0,
NULL, s, (
int)
SDL_wcslen(s),
NULL);
1546 StopDrawToBitmap(hdc, &hbm);
1548 DeleteObject(listpen);
1549 DeleteObject(listbrush);
1550 DeleteObject(candpen);
1551 DeleteObject(candbrush);
1552 DeleteObject(selpen);
1553 DeleteObject(selbrush);
1556 IME_PositionCandidateList(videodata, size);
1562 HDC hdc = CreateCompatibleDC(
NULL);
1565 IME_RenderCandidateList(videodata, hdc);
1575 IME_Render(videodata);
void SDL_GetDefaultKeymap(SDL_Keycode *keymap)
GLsizei GLenum GLboolean sink
LPINPUTCONTEXT2(WINAPI *ImmLockIMC)(HIMC himc)
GLint GLint GLsizei width
GLuint GLuint GLsizei count
static SDL_Window * window
const struct ITfThreadMgrExVtbl * lpVtbl
const struct ITfSourceVtbl * lpVtbl
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
void WIN_ResetDeadKeys(void)
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d ®2 endm macro vzip8 reg2 vzip d d ®2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld [DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp local skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
static void DrawRect(SDL_Renderer *r, const int x, const int y, const int w, const int h)
#define SDLK_SCANCODE_MASK
const struct ITfThreadMgrVtbl * lpVtbl
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const void * bits
#define TF_INVALID_COOKIE
#define SDL_GetKeyboardFocus
#define SDL_InvalidParamError(param)
GLint GLint GLsizei GLsizei height
DWORD ime_openmodesinkcookie
GLdouble GLdouble GLdouble GLdouble top
Sint32 SDL_Keycode
The SDL virtual key representation.
const struct ITfDocumentMgrVtbl * lpVtbl
LPVOID(WINAPI *ImmLockIMCC)(HIMCC himcc)
static SDL_VideoDevice * _this
DWORD ime_uielemsinkcookie
void SDL_SetKeymap(int start, SDL_Keycode *keys, int length)
#define SDL_GetWindowSize
void WIN_StartTextInput(_THIS)
HRESULT WIN_CoInitialize(void)
int SDL_SendKeyboardText(const char *text)
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)
#define TF_IPSINK_FLAG_ACTIVE
void WIN_StopTextInput(_THIS)
const struct ITfCandidateListUIElementVtbl * lpVtbl
#define WIN_StringToUTF8(S)
GLsizei GLsizei GLchar * source
void WIN_InitKeyboard(_THIS)
void WIN_QuitKeyboard(_THIS)
void SDL_SetScancodeName(SDL_Scancode scancode, const char *name)
const struct ITfUIElementVtbl * lpVtbl
BOOL(WINAPI *CloseTouchInputHandle)(HTOUCHINPUT)
DWORD ime_convmodesinkcookie
SDL_bool ime_com_initialized
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)
void SDL_ToggleModState(const SDL_Keymod modstate, const SDL_bool toggle)
WCHAR ime_readingstring[16]
void WIN_CoUninitialize(void)
void WIN_UpdateKeymap(void)
void WIN_SetTextInputRect(_THIS, SDL_Rect *rect)
static const SDL_Scancode windows_scancode_table[]
The type used to identify a window.
SDL_bool ime_candvertical
WCHAR ime_composition[SDL_TEXTEDITINGEVENT_TEXT_SIZE]
int ime_candlistindexbase
#define SDL_arraysize(array)
SDL_Rect ime_candlistrect
void * SDL_LoadFunction(void *handle, const char *name)
#define TF_TMAE_UIELEMENTENABLEDONLY
GLuint GLsizei GLsizei * length
SDL_Scancode
The SDL keyboard scancode representation.
int SDL_SendEditingText(const char *text, int start, int length)
WCHAR ime_candidates[MAX_CANDLIST][MAX_CANDLENGTH]
A rectangle, with the origin at the upper left.
SDL_bool IME_HandleMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM *lParam, struct SDL_VideoData *videodata)
#define SDL_TEXTEDITINGEVENT_TEXT_SIZE
struct ITfThreadMgrEx * ime_threadmgrex
struct ITfThreadMgr * ime_threadmgr