Large commit with initial reading string support, TSF UILess code, etc.
authordewyatt
Tue, 03 Aug 2010 16:57:49 -0400
changeset 4759863ba7d1f029
parent 4758 e2f4e31b41fc
child 4760 c40027ee6d47
Large commit with initial reading string support, TSF UILess code, etc.
src/video/win32/SDL_win32keyboard.c
src/video/win32/SDL_win32video.h
     1.1 --- a/src/video/win32/SDL_win32keyboard.c	Tue Aug 03 16:52:10 2010 -0400
     1.2 +++ b/src/video/win32/SDL_win32keyboard.c	Tue Aug 03 16:57:49 2010 -0400
     1.3 @@ -26,8 +26,13 @@
     1.4  #include "../../events/SDL_keyboard_c.h"
     1.5  #include "../../events/scancodes_win32.h"
     1.6  
     1.7 -#include <msctf.h>
     1.8  #include <imm.h>
     1.9 +#include <oleauto.h>
    1.10 +
    1.11 +static void IME_Init(SDL_VideoData *videodata, HWND hwnd);
    1.12 +static void IME_Enable(SDL_VideoData *videodata, HWND hwnd);
    1.13 +static void IME_Disable(SDL_VideoData *videodata, HWND hwnd);
    1.14 +static void IME_Quit(SDL_VideoData *videodata);
    1.15  
    1.16  #ifndef MAPVK_VK_TO_VSC
    1.17  #define MAPVK_VK_TO_VSC     0
    1.18 @@ -49,11 +54,6 @@
    1.19      82, 79, 80, 81, 75, 76, 77, 71, 72, 73
    1.20  };
    1.21  
    1.22 -void IME_Disable(SDL_VideoData *videodata, HWND hwnd);
    1.23 -void IME_Enable(SDL_VideoData *videodata, HWND hwnd);
    1.24 -void IME_Init(SDL_VideoData *videodata, HWND hwnd);
    1.25 -void IME_Quit(SDL_VideoData *videodata);
    1.26 -
    1.27  void
    1.28  WIN_InitKeyboard(_THIS)
    1.29  {
    1.30 @@ -90,13 +90,32 @@
    1.31      data->key_layout = win32_scancode_table;
    1.32  
    1.33      data->ime_com_initialized = SDL_FALSE;
    1.34 -    data->ime_thread_mgr = 0;
    1.35 +    data->ime_threadmgr = 0;
    1.36      data->ime_initialized = SDL_FALSE;
    1.37      data->ime_enabled = SDL_FALSE;
    1.38      data->ime_available = SDL_FALSE;
    1.39      data->ime_hwnd_main = 0;
    1.40      data->ime_hwnd_current = 0;
    1.41      data->ime_himc = 0;
    1.42 +    data->ime_composition[0] = 0;
    1.43 +    data->ime_readingstring[0] = 0;
    1.44 +    data->ime_cursor = 0;
    1.45 +    data->ime_hkl = 0;
    1.46 +    data->ime_himm32 = 0;
    1.47 +    data->GetReadingString = 0;
    1.48 +    data->ShowReadingWindow = 0;
    1.49 +    data->ImmLockIMC = 0;
    1.50 +    data->ImmUnlockIMC = 0;
    1.51 +    data->ImmLockIMCC = 0;
    1.52 +    data->ImmUnlockIMCC = 0;
    1.53 +    data->ime_uiless = SDL_FALSE;
    1.54 +    data->ime_threadmgrex = 0;
    1.55 +    data->ime_uielemsinkcookie = TF_INVALID_COOKIE;
    1.56 +    data->ime_alpnsinkcookie = TF_INVALID_COOKIE;
    1.57 +    data->ime_openmodesinkcookie = TF_INVALID_COOKIE;
    1.58 +    data->ime_convmodesinkcookie = TF_INVALID_COOKIE;
    1.59 +    data->ime_uielemsink = 0;
    1.60 +    data->ime_ippasink = 0;
    1.61  
    1.62      WIN_UpdateKeymap();
    1.63  
    1.64 @@ -144,8 +163,7 @@
    1.65  WIN_StartTextInput(_THIS)
    1.66  {
    1.67      SDL_Window *window = SDL_GetKeyboardFocus();
    1.68 -    if (window)
    1.69 -    {
    1.70 +    if (window) {
    1.71          HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
    1.72          SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
    1.73          IME_Init(videodata, hwnd);
    1.74 @@ -157,8 +175,7 @@
    1.75  WIN_StopTextInput(_THIS)
    1.76  {
    1.77      SDL_Window *window = SDL_GetKeyboardFocus();
    1.78 -    if (window)
    1.79 -    {
    1.80 +    if (window) {
    1.81          HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
    1.82          SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
    1.83          IME_Init(videodata, hwnd);
    1.84 @@ -172,19 +189,94 @@
    1.85  
    1.86  }
    1.87  
    1.88 -void
    1.89 -IME_Disable(SDL_VideoData *videodata, HWND hwnd)
    1.90 +#define LANG_CHT MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL)
    1.91 +#define LANG_CHS MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)
    1.92 +
    1.93 +#define MAKEIMEVERSION(major,minor) ((DWORD) (((BYTE)(major) << 24) | ((BYTE)(minor) << 16) ))
    1.94 +#define IMEID_VER(id) ((id) & 0xffff0000)
    1.95 +#define IMEID_LANG(id) ((id) & 0x0000ffff)
    1.96 +
    1.97 +#define CHT_HKL_DAYI            ((HKL)0xE0060404)
    1.98 +#define CHT_HKL_NEW_PHONETIC    ((HKL)0xE0080404)
    1.99 +#define CHT_HKL_NEW_CHANG_JIE   ((HKL)0xE0090404)
   1.100 +#define CHT_HKL_NEW_QUICK       ((HKL)0xE00A0404)
   1.101 +#define CHT_HKL_HK_CANTONESE    ((HKL)0xE00B0404)
   1.102 +#define CHT_IMEFILENAME1        "TINTLGNT.IME"
   1.103 +#define CHT_IMEFILENAME2        "CINTLGNT.IME"
   1.104 +#define CHT_IMEFILENAME3        "MSTCIPHA.IME"
   1.105 +#define IMEID_CHT_VER42         (LANG_CHT | MAKEIMEVERSION(4, 2))
   1.106 +#define IMEID_CHT_VER43         (LANG_CHT | MAKEIMEVERSION(4, 3))
   1.107 +#define IMEID_CHT_VER44         (LANG_CHT | MAKEIMEVERSION(4, 4))
   1.108 +#define IMEID_CHT_VER50         (LANG_CHT | MAKEIMEVERSION(5, 0))
   1.109 +#define IMEID_CHT_VER51         (LANG_CHT | MAKEIMEVERSION(5, 1))
   1.110 +#define IMEID_CHT_VER52         (LANG_CHT | MAKEIMEVERSION(5, 2))
   1.111 +#define IMEID_CHT_VER60         (LANG_CHT | MAKEIMEVERSION(6, 0))
   1.112 +#define IMEID_CHT_VER_VISTA     (LANG_CHT | MAKEIMEVERSION(7, 0))
   1.113 +
   1.114 +#define CHS_HKL                 ((HKL)0xE00E0804)
   1.115 +#define CHS_IMEFILENAME1        "PINTLGNT.IME"
   1.116 +#define CHS_IMEFILENAME2        "MSSCIPYA.IME"
   1.117 +#define IMEID_CHS_VER41         (LANG_CHS | MAKEIMEVERSION(4, 1))
   1.118 +#define IMEID_CHS_VER42         (LANG_CHS | MAKEIMEVERSION(4, 2))
   1.119 +#define IMEID_CHS_VER53         (LANG_CHS | MAKEIMEVERSION(5, 3))
   1.120 +
   1.121 +#define LANG() LOWORD((videodata->ime_hkl))
   1.122 +#define PRIMLANG() ((WORD)PRIMARYLANGID(LANG()))
   1.123 +#define SUBLANG() SUBLANGID(LANG())
   1.124 +
   1.125 +static void IME_UpdateInputLocale(SDL_VideoData *videodata);
   1.126 +static void IME_ClearComposition(SDL_VideoData *videodata);
   1.127 +static void IME_SetWindow(SDL_VideoData* videodata, HWND hwnd);
   1.128 +static void IME_SetupAPI(SDL_VideoData *videodata);
   1.129 +static DWORD IME_GetId(SDL_VideoData *videodata, UINT uIndex);
   1.130 +static void IME_SendEditingEvent(SDL_VideoData *videodata);
   1.131 +#define SDL_IsEqualIID(riid1, riid2) SDL_IsEqualGUID(riid1, riid2)
   1.132 +#define SDL_IsEqualGUID(rguid1, rguid2) (!SDL_memcmp(rguid1, rguid2, sizeof(GUID)))
   1.133 +
   1.134 +static SDL_bool UILess_SetupSinks(SDL_VideoData *videodata);
   1.135 +static void UILess_ReleaseSinks(SDL_VideoData *videodata);
   1.136 +static void UILess_EnableUIUpdates(SDL_VideoData *videodata);
   1.137 +static void UILess_DisableUIUpdates(SDL_VideoData *videodata);
   1.138 +
   1.139 +static void
   1.140 +IME_Init(SDL_VideoData *videodata, HWND hwnd)
   1.141  {
   1.142 -    if (!videodata->ime_initialized || !videodata->ime_hwnd_current)
   1.143 +    if (videodata->ime_initialized)
   1.144          return;
   1.145  
   1.146 -    if (videodata->ime_hwnd_current == videodata->ime_hwnd_main)
   1.147 -        ImmAssociateContext(videodata->ime_hwnd_current, NULL);
   1.148 +    videodata->ime_hwnd_main = hwnd;
   1.149 +    if (SUCCEEDED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED))) {
   1.150 +        videodata->ime_com_initialized = SDL_TRUE;
   1.151 +        CoCreateInstance(&CLSID_TF_ThreadMgr, NULL, CLSCTX_INPROC_SERVER, &IID_ITfThreadMgr, &videodata->ime_threadmgr);
   1.152 +    }
   1.153 +    videodata->ime_initialized = SDL_TRUE;
   1.154 +    videodata->ime_himm32 = LoadLibraryA("imm32.dll");
   1.155 +    if (!videodata->ime_himm32) {
   1.156 +        videodata->ime_available = SDL_FALSE;
   1.157 +        return;
   1.158 +    }
   1.159 +    videodata->ImmLockIMC = (LPINPUTCONTEXT2 (WINAPI *)(HIMC))GetProcAddress(videodata->ime_himm32, "ImmLockIMC");
   1.160 +    videodata->ImmUnlockIMC = (BOOL (WINAPI *)(HIMC))GetProcAddress(videodata->ime_himm32, "ImmUnlockIMC");
   1.161 +    videodata->ImmLockIMCC = (LPVOID (WINAPI *)(HIMCC))GetProcAddress(videodata->ime_himm32, "ImmLockIMCC");
   1.162 +    videodata->ImmUnlockIMCC = (BOOL (WINAPI *)(HIMCC))GetProcAddress(videodata->ime_himm32, "ImmUnlockIMCC");
   1.163  
   1.164 -    videodata->ime_enabled = SDL_FALSE;
   1.165 +    IME_SetWindow(videodata, hwnd);
   1.166 +    videodata->ime_himc = ImmGetContext(hwnd);
   1.167 +    ImmReleaseContext(hwnd, videodata->ime_himc);
   1.168 +    if (!videodata->ime_himc) {
   1.169 +        videodata->ime_available = SDL_FALSE;
   1.170 +        IME_Disable(videodata, hwnd);
   1.171 +        return;
   1.172 +    }
   1.173 +    videodata->ime_available = SDL_TRUE;
   1.174 +    IME_UpdateInputLocale(videodata);
   1.175 +    IME_SetupAPI(videodata);
   1.176 +    videodata->ime_uiless = UILess_SetupSinks(videodata);
   1.177 +    IME_UpdateInputLocale(videodata);
   1.178 +    IME_Disable(videodata, hwnd);
   1.179  }
   1.180  
   1.181 -void
   1.182 +static void
   1.183  IME_Enable(SDL_VideoData *videodata, HWND hwnd)
   1.184  {
   1.185      if (!videodata->ime_initialized || !videodata->ime_hwnd_current)
   1.186 @@ -198,54 +290,45 @@
   1.187          ImmAssociateContext(videodata->ime_hwnd_current, videodata->ime_himc);
   1.188  
   1.189      videodata->ime_enabled = SDL_TRUE;
   1.190 +    IME_UpdateInputLocale(videodata);
   1.191 +    UILess_EnableUIUpdates(videodata);
   1.192  }
   1.193  
   1.194 -void
   1.195 -IME_Init(SDL_VideoData *videodata, HWND hwnd)
   1.196 +static void
   1.197 +IME_Disable(SDL_VideoData *videodata, HWND hwnd)
   1.198  {
   1.199 -    if (videodata->ime_initialized)
   1.200 +    if (!videodata->ime_initialized || !videodata->ime_hwnd_current)
   1.201          return;
   1.202  
   1.203 -    videodata->ime_hwnd_main = hwnd;
   1.204 -    if (SUCCEEDED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED))) {
   1.205 -        videodata->ime_com_initialized = SDL_TRUE;
   1.206 -        CoCreateInstance(&CLSID_TF_ThreadMgr, NULL, CLSCTX_INPROC_SERVER, &IID_ITfThreadMgr, &videodata->ime_thread_mgr);
   1.207 -    }
   1.208 -    videodata->ime_initialized = SDL_TRUE;
   1.209 -    videodata->ime_hwnd_current = videodata->ime_hwnd_main;
   1.210 -    if (videodata->ime_thread_mgr) {
   1.211 -        struct ITfDocumentMgr *document_mgr = 0;
   1.212 -        if (SUCCEEDED(videodata->ime_thread_mgr->lpVtbl->AssociateFocus(videodata->ime_thread_mgr, hwnd, NULL, &document_mgr))) {
   1.213 -            if (document_mgr)
   1.214 -                document_mgr->lpVtbl->Release(document_mgr);
   1.215 -        }
   1.216 -    }
   1.217 -    videodata->ime_himc = ImmGetContext(hwnd);
   1.218 -    ImmReleaseContext(hwnd, videodata->ime_himc);
   1.219 -    if (!videodata->ime_himc) {
   1.220 -        videodata->ime_available = SDL_FALSE;
   1.221 -        IME_Disable(videodata, hwnd);
   1.222 -        return;
   1.223 -    }
   1.224 -    videodata->ime_available = SDL_TRUE;
   1.225 -    IME_Disable(videodata, hwnd);
   1.226 +    IME_ClearComposition(videodata);
   1.227 +    if (videodata->ime_hwnd_current == videodata->ime_hwnd_main)
   1.228 +        ImmAssociateContext(videodata->ime_hwnd_current, NULL);
   1.229 +
   1.230 +    videodata->ime_enabled = SDL_FALSE;
   1.231 +    UILess_DisableUIUpdates(videodata);
   1.232  }
   1.233  
   1.234 -void
   1.235 +static void
   1.236  IME_Quit(SDL_VideoData *videodata)
   1.237  {
   1.238      if (!videodata->ime_initialized)
   1.239          return;
   1.240  
   1.241 +    UILess_ReleaseSinks(videodata);
   1.242      if (videodata->ime_hwnd_main)
   1.243          ImmAssociateContext(videodata->ime_hwnd_main, videodata->ime_himc);
   1.244  
   1.245      videodata->ime_hwnd_main = 0;
   1.246      videodata->ime_himc = 0;
   1.247 -    if (videodata->ime_thread_mgr)
   1.248 +    if (videodata->ime_himm32)
   1.249      {
   1.250 -        videodata->ime_thread_mgr->lpVtbl->Release(videodata->ime_thread_mgr);
   1.251 -        videodata->ime_thread_mgr = 0;
   1.252 +        FreeLibrary(videodata->ime_himm32);
   1.253 +        videodata->ime_himm32 = 0;
   1.254 +    }
   1.255 +    if (videodata->ime_threadmgr)
   1.256 +    {
   1.257 +        videodata->ime_threadmgr->lpVtbl->Release(videodata->ime_threadmgr);
   1.258 +        videodata->ime_threadmgr = 0;
   1.259      }
   1.260      if (videodata->ime_com_initialized)
   1.261      {
   1.262 @@ -255,18 +338,384 @@
   1.263      videodata->ime_initialized = SDL_FALSE;
   1.264  }
   1.265  
   1.266 +static void
   1.267 +IME_GetReadingString(SDL_VideoData *videodata, HWND hwnd)
   1.268 +{
   1.269 +    DWORD id = 0;
   1.270 +    HIMC himc = 0;
   1.271 +    WCHAR buffer[16];
   1.272 +    WCHAR *s = buffer;
   1.273 +    DWORD len = 0;
   1.274 +    DWORD err = 0;
   1.275 +    BOOL vertical = FALSE;
   1.276 +    UINT maxuilen = 0;
   1.277 +    static OSVERSIONINFOA osversion = {0};
   1.278 +    if (videodata->ime_uiless)
   1.279 +        return;
   1.280 +
   1.281 +    videodata->ime_readingstring[0] = 0;
   1.282 +    if (!osversion.dwOSVersionInfoSize)
   1.283 +    {
   1.284 +        osversion.dwOSVersionInfoSize = sizeof(osversion);
   1.285 +        GetVersionExA(&osversion);
   1.286 +    }
   1.287 +    id = IME_GetId(videodata, 0);
   1.288 +    if (!id)
   1.289 +        return;
   1.290 +
   1.291 +    himc = ImmGetContext(hwnd);
   1.292 +    if (!himc)
   1.293 +        return;
   1.294 +
   1.295 +    if (videodata->GetReadingString)
   1.296 +    {
   1.297 +        len = videodata->GetReadingString(himc, 0, 0, &err, &vertical, &maxuilen);
   1.298 +        if (len)
   1.299 +        {
   1.300 +            if (len > SDL_arraysize(buffer))
   1.301 +                len = SDL_arraysize(buffer);
   1.302 +
   1.303 +            len = videodata->GetReadingString(himc, len, s, &err, &vertical, &maxuilen);
   1.304 +        }
   1.305 +        SDL_wcslcpy(videodata->ime_readingstring, s, len);
   1.306 +    }
   1.307 +    else
   1.308 +    {
   1.309 +        LPINPUTCONTEXT2 lpimc = videodata->ImmLockIMC(himc);
   1.310 +        LPBYTE p = 0;
   1.311 +        s = 0;
   1.312 +        switch (id)
   1.313 +        {
   1.314 +        case IMEID_CHT_VER42:
   1.315 +        case IMEID_CHT_VER43:
   1.316 +        case IMEID_CHT_VER44:
   1.317 +            p = *(LPBYTE *)((LPBYTE)videodata->ImmLockIMCC(lpimc->hPrivate) + 24);
   1.318 +            if (!p)
   1.319 +                break;
   1.320 +
   1.321 +            len = *(DWORD *)(p + 7*4 + 32*4);
   1.322 +            s = (WCHAR *)(p + 56);
   1.323 +            break;
   1.324 +        case IMEID_CHT_VER51:
   1.325 +        case IMEID_CHT_VER52:
   1.326 +        case IMEID_CHS_VER53:
   1.327 +            p = *(LPBYTE *)((LPBYTE)videodata->ImmLockIMCC(lpimc->hPrivate) + 4);
   1.328 +            if (!p)
   1.329 +                break;
   1.330 +
   1.331 +            p = *(LPBYTE *)((LPBYTE)p + 1*4 + 5*4);
   1.332 +            if (!p)
   1.333 +                break;
   1.334 +
   1.335 +            len = *(DWORD *)(p + 1*4 + (16*2+2*4) + 5*4 + 16*2);
   1.336 +            s = (WCHAR *)(p + 1*4 + (16*2+2*4) + 5*4);
   1.337 +            break;
   1.338 +        case IMEID_CHS_VER41:
   1.339 +            {
   1.340 +                int offset = (IME_GetId(videodata, 1) >= 0x00000002) ? 8 : 7;
   1.341 +                p = *(LPBYTE *)((LPBYTE)videodata->ImmLockIMCC(lpimc->hPrivate) + offset * 4);
   1.342 +                if (!p)
   1.343 +                    break;
   1.344 +
   1.345 +                len = *(DWORD *)(p + 7*4 + 16*2*4);
   1.346 +                s = (WCHAR *)(p + 6*4 + 16*2*1);
   1.347 +            }
   1.348 +            break;
   1.349 +        case IMEID_CHS_VER42:
   1.350 +            if (osversion.dwPlatformId != VER_PLATFORM_WIN32_NT)
   1.351 +                break;
   1.352 +
   1.353 +            p = *(LPBYTE *)((LPBYTE)videodata->ImmLockIMCC(lpimc->hPrivate) + 1*4 + 1*4 + 6*4);
   1.354 +            if (!p)
   1.355 +                break;
   1.356 +
   1.357 +            len = *(DWORD *)(p + 1*4 + (16*2+2*4) + 5*4 + 16*2);
   1.358 +            s = (WCHAR *)(p + 1*4 + (16*2+2*4) + 5*4);
   1.359 +            break;
   1.360 +        }
   1.361 +        if (s)
   1.362 +        {
   1.363 +            SDL_wcslcpy(videodata->ime_readingstring, s, len + 1);
   1.364 +        }
   1.365 +        videodata->ImmUnlockIMCC(lpimc->hPrivate);
   1.366 +        videodata->ImmUnlockIMC(himc);
   1.367 +    }
   1.368 +    ImmReleaseContext(hwnd, himc);
   1.369 +    IME_SendEditingEvent(videodata);
   1.370 +}
   1.371 +
   1.372 +static void
   1.373 +IME_InputLangChanged(SDL_VideoData *videodata)
   1.374 +{
   1.375 +    UINT uLang = PRIMLANG();
   1.376 +    HWND hwndime = 0;
   1.377 +    IME_UpdateInputLocale(videodata);
   1.378 +    IME_SetupAPI(videodata);
   1.379 +    if (uLang != PRIMLANG())
   1.380 +    {
   1.381 +        IME_ClearComposition(videodata);
   1.382 +    }
   1.383 +    hwndime = ImmGetDefaultIMEWnd(videodata->ime_hwnd_current);
   1.384 +    if (hwndime)
   1.385 +    {
   1.386 +        SendMessageA(hwndime, WM_IME_CONTROL, IMC_OPENSTATUSWINDOW, 0);
   1.387 +        SendMessageA(hwndime, WM_IME_CONTROL, IMC_CLOSESTATUSWINDOW, 0);
   1.388 +    }
   1.389 +}
   1.390 +
   1.391 +static DWORD
   1.392 +IME_GetId(SDL_VideoData *videodata, UINT uIndex)
   1.393 +{
   1.394 +    static HKL hklprev = 0;
   1.395 +    static DWORD dwRet[2] = {0};
   1.396 +    DWORD dwVerSize = 0;
   1.397 +    DWORD dwVerHandle = 0;
   1.398 +    LPVOID lpVerBuffer = 0;
   1.399 +    LPVOID lpVerData = 0;
   1.400 +    UINT cbVerData = 0;
   1.401 +    char szTemp[256];
   1.402 +    HKL hkl = 0;
   1.403 +    DWORD dwLang = 0;
   1.404 +    if (uIndex >= sizeof(dwRet) / sizeof(dwRet[0]))
   1.405 +        return 0;
   1.406 +
   1.407 +    hkl = videodata->ime_hkl;
   1.408 +    if (hklprev == hkl)
   1.409 +        return dwRet[uIndex];
   1.410 +
   1.411 +    hklprev = hkl;
   1.412 +    dwLang = ((DWORD)hkl & 0xffff);
   1.413 +    if (videodata->ime_uiless && LANG() == LANG_CHT)
   1.414 +    {
   1.415 +        dwRet[0] = IMEID_CHT_VER_VISTA;
   1.416 +        dwRet[1] = 0;
   1.417 +        return dwRet[0];
   1.418 +    }
   1.419 +    if (hkl != CHT_HKL_NEW_PHONETIC
   1.420 +        && hkl != CHT_HKL_NEW_CHANG_JIE
   1.421 +        && hkl != CHT_HKL_NEW_QUICK
   1.422 +        && hkl != CHT_HKL_HK_CANTONESE
   1.423 +        && hkl != CHS_HKL)
   1.424 +    {
   1.425 +        dwRet[0] = dwRet[1] = 0;
   1.426 +        return dwRet[uIndex];
   1.427 +    }
   1.428 +    if (ImmGetIMEFileNameA(hkl, szTemp, sizeof(szTemp) - 1) <= 0)
   1.429 +    {
   1.430 +        dwRet[0] = dwRet[1] = 0;
   1.431 +        return dwRet[uIndex];
   1.432 +    }
   1.433 +    if (!videodata->GetReadingString)
   1.434 +    {
   1.435 +        #define LCID_INVARIANT MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT)
   1.436 +        if (CompareStringA(LCID_INVARIANT, NORM_IGNORECASE, szTemp, -1, CHT_IMEFILENAME1, -1) != 2
   1.437 +            && CompareStringA(LCID_INVARIANT, NORM_IGNORECASE, szTemp, -1, CHT_IMEFILENAME2, -1) != 2
   1.438 +            && CompareStringA(LCID_INVARIANT, NORM_IGNORECASE, szTemp, -1, CHT_IMEFILENAME3, -1) != 2
   1.439 +            && CompareStringA(LCID_INVARIANT, NORM_IGNORECASE, szTemp, -1, CHS_IMEFILENAME1, -1) != 2
   1.440 +            && CompareStringA(LCID_INVARIANT, NORM_IGNORECASE, szTemp, -1, CHS_IMEFILENAME2, -1) != 2
   1.441 +            )
   1.442 +        {
   1.443 +            dwRet[0] = dwRet[1] = 0;
   1.444 +            return dwRet[uIndex];
   1.445 +        }
   1.446 +        #undef LCID_INVARIANT
   1.447 +        dwVerSize = GetFileVersionInfoSizeA(szTemp, &dwVerHandle);
   1.448 +        if (dwVerSize)
   1.449 +        {
   1.450 +            lpVerBuffer = SDL_malloc(dwVerSize);
   1.451 +            if (lpVerBuffer)
   1.452 +            {
   1.453 +                if (GetFileVersionInfoA(szTemp, dwVerHandle, dwVerSize, lpVerBuffer))
   1.454 +                {
   1.455 +                    if (VerQueryValueA(lpVerBuffer, "\\", &lpVerData, &cbVerData))
   1.456 +                    {
   1.457 +                        #define pVerFixedInfo   ((VS_FIXEDFILEINFO FAR*)lpVerData)
   1.458 +                        DWORD dwVer = pVerFixedInfo->dwFileVersionMS;
   1.459 +                        dwVer = (dwVer & 0x00ff0000) << 8 | (dwVer & 0x000000ff) << 16;
   1.460 +                        if (videodata->GetReadingString ||
   1.461 +                            dwLang == LANG_CHT && (
   1.462 +                            dwVer == MAKEIMEVERSION(4, 2) ||
   1.463 +                            dwVer == MAKEIMEVERSION(4, 3) ||
   1.464 +                            dwVer == MAKEIMEVERSION(4, 4) ||
   1.465 +                            dwVer == MAKEIMEVERSION(5, 0) ||
   1.466 +                            dwVer == MAKEIMEVERSION(5, 1) ||
   1.467 +                            dwVer == MAKEIMEVERSION(5, 2) ||
   1.468 +                            dwVer == MAKEIMEVERSION(6, 0))
   1.469 +                            ||
   1.470 +                            dwLang == LANG_CHS && (
   1.471 +                            dwVer == MAKEIMEVERSION(4, 1) ||
   1.472 +                            dwVer == MAKEIMEVERSION(4, 2) ||
   1.473 +                            dwVer == MAKEIMEVERSION(5, 3))
   1.474 +                            )
   1.475 +                        {
   1.476 +                            dwRet[0] = dwVer | dwLang;
   1.477 +                            dwRet[1] = pVerFixedInfo->dwFileVersionLS;
   1.478 +                            SDL_free(lpVerBuffer);
   1.479 +                            return dwRet[0];
   1.480 +                        }
   1.481 +                        #undef pVerFixedInfo
   1.482 +                    }
   1.483 +                }
   1.484 +            }
   1.485 +            SDL_free(lpVerBuffer);
   1.486 +        }
   1.487 +    }
   1.488 +    dwRet[0] = dwRet[1] = 0;
   1.489 +    return dwRet[uIndex];
   1.490 +}
   1.491 +
   1.492 +static void
   1.493 +IME_SetupAPI(SDL_VideoData *videodata)
   1.494 +{
   1.495 +    char ime_file[MAX_PATH + 1];
   1.496 +    HMODULE hime = 0;
   1.497 +    HKL hkl = 0;
   1.498 +    videodata->GetReadingString = 0;
   1.499 +    videodata->ShowReadingWindow = 0;
   1.500 +    if (videodata->ime_uiless)
   1.501 +        return;
   1.502 +
   1.503 +    hkl = videodata->ime_hkl;
   1.504 +    if (ImmGetIMEFileNameA(hkl, ime_file, sizeof(ime_file) - 1) <= 0)
   1.505 +        return;
   1.506 +
   1.507 +    hime = LoadLibraryA(ime_file);
   1.508 +    if (!hime)
   1.509 +        return;
   1.510 +
   1.511 +    videodata->GetReadingString = (UINT (WINAPI *)(HIMC, UINT, LPWSTR, PINT, BOOL*, PUINT))
   1.512 +        GetProcAddress(hime, "GetReadingString");
   1.513 +    videodata->ShowReadingWindow = (BOOL (WINAPI *)(HIMC, BOOL))
   1.514 +        GetProcAddress(hime, "ShowReadingWindow");
   1.515 +
   1.516 +    if (videodata->ShowReadingWindow)
   1.517 +    {
   1.518 +        HIMC himc = ImmGetContext(videodata->ime_hwnd_current);
   1.519 +        if (himc)
   1.520 +        {
   1.521 +            videodata->ShowReadingWindow(himc, FALSE);
   1.522 +            ImmReleaseContext(videodata->ime_hwnd_current, himc);
   1.523 +        }
   1.524 +    }
   1.525 +}
   1.526 +
   1.527 +static void
   1.528 +IME_SetWindow(SDL_VideoData* videodata, HWND hwnd)
   1.529 +{
   1.530 +    videodata->ime_hwnd_current = hwnd;
   1.531 +    if (videodata->ime_threadmgr) {
   1.532 +        struct ITfDocumentMgr *document_mgr = 0;
   1.533 +        if (SUCCEEDED(videodata->ime_threadmgr->lpVtbl->AssociateFocus(videodata->ime_threadmgr, hwnd, NULL, &document_mgr))) {
   1.534 +            if (document_mgr)
   1.535 +                document_mgr->lpVtbl->Release(document_mgr);
   1.536 +        }
   1.537 +    }
   1.538 +}
   1.539 +
   1.540 +static void
   1.541 +IME_UpdateInputLocale(SDL_VideoData *videodata)
   1.542 +{
   1.543 +    static HKL hklPrevious = 0;
   1.544 +    videodata->ime_hkl = GetKeyboardLayout(0);
   1.545 +    if (hklPrevious == videodata->ime_hkl)
   1.546 +        return;
   1.547 +
   1.548 +    hklPrevious = videodata->ime_hkl;
   1.549 +}
   1.550 +
   1.551 +static void
   1.552 +IME_ClearComposition(SDL_VideoData *videodata)
   1.553 +{
   1.554 +    HIMC himc = 0;
   1.555 +    if (!videodata->ime_initialized)
   1.556 +        return;
   1.557 +
   1.558 +    himc = ImmGetContext(videodata->ime_hwnd_current);
   1.559 +    if (!himc)
   1.560 +        return;
   1.561 +
   1.562 +    ImmNotifyIME(himc, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
   1.563 +    if (videodata->ime_uiless)
   1.564 +        ImmSetCompositionString(himc, SCS_SETSTR, TEXT(""), sizeof(TCHAR), TEXT(""), sizeof(TCHAR));
   1.565 +
   1.566 +    ImmNotifyIME(himc, NI_CLOSECANDIDATE, 0, 0);
   1.567 +    ImmReleaseContext(videodata->ime_hwnd_current, himc);
   1.568 +    SDL_SendEditingText("", 0, 0);
   1.569 +}
   1.570 +
   1.571 +static void
   1.572 +IME_ClearEditing(SDL_VideoData *videodata)
   1.573 +{
   1.574 +
   1.575 +}
   1.576 +
   1.577 +static void
   1.578 +IME_GetCompositionString(SDL_VideoData *videodata, HIMC himc, DWORD string)
   1.579 +{
   1.580 +    LONG Length = ImmGetCompositionStringW(himc, string, videodata->ime_composition, sizeof(videodata->ime_composition));
   1.581 +    if (Length < 0)
   1.582 +        Length = 0;
   1.583 +
   1.584 +    Length /= sizeof(videodata->ime_composition[0]);
   1.585 +    videodata->ime_cursor = LOWORD(ImmGetCompositionStringW(himc, GCS_CURSORPOS, 0, 0));
   1.586 +    if (videodata->ime_composition[videodata->ime_cursor] == 0x3000)
   1.587 +    {
   1.588 +        int i;
   1.589 +        for (i = videodata->ime_cursor + 1; i < Length; ++i)
   1.590 +            videodata->ime_composition[i - 1] = videodata->ime_composition[i];
   1.591 +
   1.592 +        --Length;
   1.593 +    }
   1.594 +    videodata->ime_composition[Length] = 0;
   1.595 +}
   1.596 +
   1.597 +static void
   1.598 +IME_SendInputEvent(SDL_VideoData *videodata)
   1.599 +{
   1.600 +    char *s = 0;
   1.601 +    s = WIN_StringToUTF8(videodata->ime_composition);
   1.602 +    SDL_SendKeyboardText(s);
   1.603 +    SDL_free(s);
   1.604 +
   1.605 +    videodata->ime_composition[0] = 0;
   1.606 +    videodata->ime_readingstring[0] = 0;
   1.607 +    videodata->ime_cursor = 0;
   1.608 +}
   1.609 +
   1.610 +static void
   1.611 +IME_SendEditingEvent(SDL_VideoData *videodata)
   1.612 +{
   1.613 +    char *s = 0;
   1.614 +    WCHAR wBuffer[SDL_TEXTEDITINGEVENT_TEXT_SIZE];
   1.615 +    wBuffer[0] = 0;
   1.616 +    if (videodata->ime_readingstring[0])
   1.617 +    {
   1.618 +        size_t len = SDL_min(SDL_wcslen(videodata->ime_composition), (size_t)videodata->ime_cursor);
   1.619 +        SDL_wcslcpy(wBuffer, videodata->ime_composition, len + 1);
   1.620 +        SDL_wcslcat(wBuffer, videodata->ime_readingstring, sizeof(wBuffer));
   1.621 +        SDL_wcslcat(wBuffer, &videodata->ime_composition[len], sizeof(wBuffer) - len);
   1.622 +    }
   1.623 +    else
   1.624 +    {
   1.625 +        SDL_wcslcpy(wBuffer, videodata->ime_composition, sizeof(videodata->ime_composition));
   1.626 +    }
   1.627 +    s = WIN_StringToUTF8(wBuffer);
   1.628 +    SDL_SendEditingText(s, videodata->ime_cursor + SDL_wcslen(videodata->ime_readingstring), 0);
   1.629 +    SDL_free(s);
   1.630 +}
   1.631 +
   1.632  SDL_bool
   1.633  IME_HandleMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM *lParam, SDL_VideoData *videodata)
   1.634  {
   1.635      SDL_bool trap = SDL_FALSE;
   1.636      HIMC himc = 0;
   1.637 -    WCHAR Buffer[SDL_TEXTINPUTEVENT_TEXT_SIZE / 2];
   1.638      if (!videodata->ime_initialized || !videodata->ime_available || !videodata->ime_enabled)
   1.639          return SDL_FALSE;
   1.640  
   1.641      switch (msg)
   1.642      {
   1.643      case WM_INPUTLANGCHANGE:
   1.644 +        //IME_InputLangChanged(videodata);
   1.645          break;
   1.646      case WM_IME_SETCONTEXT:
   1.647          *lParam = 0;
   1.648 @@ -279,37 +728,31 @@
   1.649          himc = ImmGetContext(hwnd);
   1.650          if (*lParam & GCS_RESULTSTR)
   1.651          {
   1.652 -            LONG Length = 0;
   1.653 -            char *s = 0;
   1.654 -            Length = ImmGetCompositionStringW(himc, GCS_RESULTSTR, Buffer, sizeof(Buffer) * sizeof(Buffer[0]));
   1.655 -            Buffer[Length / sizeof(Buffer[0])] = 0;
   1.656 -            s = WIN_StringToUTF8(Buffer);
   1.657 -            SDL_SendKeyboardText(s);
   1.658 -            SDL_free(s);
   1.659 +            IME_GetCompositionString(videodata, himc, GCS_RESULTSTR);
   1.660 +            IME_SendInputEvent(videodata);
   1.661          }
   1.662          if (*lParam & GCS_COMPSTR)
   1.663          {
   1.664 -            LONG Length = 0;
   1.665 -            DWORD Cursor = 0;
   1.666 -            char *s = 0;
   1.667 -            Length = ImmGetCompositionStringW(himc, GCS_COMPSTR, Buffer, sizeof(Buffer) * sizeof(Buffer[0]));
   1.668 -            Buffer[Length / sizeof(Buffer[0])] = 0;
   1.669 -            s = WIN_StringToUTF8(Buffer);
   1.670 -            Cursor = LOWORD(ImmGetCompositionStringW(himc, GCS_CURSORPOS, 0, 0));
   1.671 -            SDL_SendEditingText(s, Cursor, 0);
   1.672 -            SDL_free(s);
   1.673 +            if (!videodata->ime_uiless)
   1.674 +                videodata->ime_readingstring[0] = 0;
   1.675 +
   1.676 +            IME_GetCompositionString(videodata, himc, GCS_COMPSTR);
   1.677 +            IME_SendEditingEvent(videodata);
   1.678          }
   1.679          ImmReleaseContext(hwnd, himc);
   1.680          break;
   1.681      case WM_IME_ENDCOMPOSITION:
   1.682 -        SDL_SendKeyboardText("");
   1.683 +        videodata->ime_composition[0] = 0;
   1.684 +        videodata->ime_readingstring[0] = 0;
   1.685 +        videodata->ime_cursor = 0;
   1.686 +        SDL_SendEditingText("", 0, 0);
   1.687          break;
   1.688      case WM_IME_NOTIFY:
   1.689          switch (wParam)
   1.690          {
   1.691          case IMN_SETCONVERSIONMODE:
   1.692 -            break;
   1.693          case IMN_SETOPENSTATUS:
   1.694 +            IME_UpdateInputLocale(videodata);
   1.695              break;
   1.696          case IMN_OPENCANDIDATE:
   1.697          case IMN_CHANGECANDIDATE:
   1.698 @@ -319,6 +762,34 @@
   1.699              trap = SDL_TRUE;
   1.700              break;
   1.701          case IMN_PRIVATE:
   1.702 +            {
   1.703 +                DWORD dwId = IME_GetId(videodata, 0);
   1.704 +                IME_GetReadingString(videodata, hwnd);
   1.705 +                switch (dwId)
   1.706 +                {
   1.707 +                case IMEID_CHT_VER42:
   1.708 +                case IMEID_CHT_VER43:
   1.709 +                case IMEID_CHT_VER44:
   1.710 +                case IMEID_CHS_VER41:
   1.711 +                case IMEID_CHS_VER42:
   1.712 +                    if (*lParam == 1 || *lParam == 2)
   1.713 +                        trap = SDL_TRUE;
   1.714 +
   1.715 +                    break;
   1.716 +                case IMEID_CHT_VER50:
   1.717 +                case IMEID_CHT_VER51:
   1.718 +                case IMEID_CHT_VER52:
   1.719 +                case IMEID_CHT_VER60:
   1.720 +                case IMEID_CHS_VER53:
   1.721 +                    if (*lParam == 16
   1.722 +                        || *lParam == 17
   1.723 +                        || *lParam == 26
   1.724 +                        || *lParam == 27
   1.725 +                        || *lParam == 28)
   1.726 +                        trap = SDL_TRUE;
   1.727 +                    break;
   1.728 +                }
   1.729 +            }
   1.730              break;
   1.731          default:
   1.732              trap = SDL_TRUE;
   1.733 @@ -329,4 +800,265 @@
   1.734      return trap;
   1.735  }
   1.736  
   1.737 +STDMETHODIMP_(ULONG) TSFSink_AddRef(TSFSink *sink)
   1.738 +{
   1.739 +    return ++sink->refcount;
   1.740 +}
   1.741 +
   1.742 +STDMETHODIMP_(ULONG)TSFSink_Release(TSFSink *sink)
   1.743 +{
   1.744 +    --sink->refcount;
   1.745 +    if (sink->refcount == 0)
   1.746 +    {
   1.747 +        SDL_free(sink);
   1.748 +        return 0;
   1.749 +    }
   1.750 +    return sink->refcount;
   1.751 +}
   1.752 +
   1.753 +STDMETHODIMP UIElementSink_QueryInterface(TSFSink *sink, REFIID riid, PVOID *ppv)
   1.754 +{
   1.755 +    if (!ppv)
   1.756 +        return E_INVALIDARG;
   1.757 +
   1.758 +    *ppv = 0;
   1.759 +    if (SDL_IsEqualIID(riid, &IID_IUnknown))
   1.760 +        *ppv = (IUnknown *)sink;
   1.761 +    else if (SDL_IsEqualIID(riid, &IID_ITfUIElementSink))
   1.762 +        *ppv = (ITfUIElementSink *)sink;
   1.763 +
   1.764 +    if (*ppv)
   1.765 +    {
   1.766 +        TSFSink_AddRef(sink);
   1.767 +        return S_OK;
   1.768 +    }
   1.769 +    return E_NOINTERFACE;
   1.770 +}
   1.771 +
   1.772 +ITfUIElement *UILess_GetUIElement(SDL_VideoData *videodata, DWORD dwUIElementId)
   1.773 +{
   1.774 +    ITfUIElementMgr *puiem = 0;
   1.775 +    ITfUIElement *pelem = 0;
   1.776 +    ITfThreadMgrEx *threadmgrex = videodata->ime_threadmgrex;
   1.777 +
   1.778 +    if (SUCCEEDED(threadmgrex->lpVtbl->QueryInterface(threadmgrex, &IID_ITfUIElementMgr, (LPVOID *)&puiem)))
   1.779 +    {
   1.780 +        puiem->lpVtbl->GetUIElement(puiem, dwUIElementId, &pelem);
   1.781 +        puiem->lpVtbl->Release(puiem);
   1.782 +    }
   1.783 +    return pelem;
   1.784 +}
   1.785 +
   1.786 +STDMETHODIMP UIElementSink_BeginUIElement(TSFSink *sink, DWORD dwUIElementId, BOOL *pbShow)
   1.787 +{
   1.788 +    ITfUIElement *pElement = UILess_GetUIElement((SDL_VideoData *)sink->data, dwUIElementId);
   1.789 +    ITfReadingInformationUIElement *preading = 0;
   1.790 +    ITfCandidateListUIElement *pcandidates = 0;
   1.791 +    SDL_VideoData *videodata = (SDL_VideoData *)sink->data;
   1.792 +    if (!pElement)
   1.793 +        return E_INVALIDARG;
   1.794 +
   1.795 +    *pbShow = FALSE;
   1.796 +    if (SUCCEEDED(pElement->lpVtbl->QueryInterface(pElement, &IID_ITfReadingInformationUIElement, (LPVOID *)&preading)))
   1.797 +    {
   1.798 +        BSTR bstr;
   1.799 +        if (SUCCEEDED(preading->lpVtbl->GetString(preading, &bstr)) && bstr)
   1.800 +        {
   1.801 +            WCHAR *s = (WCHAR *)bstr;
   1.802 +            SysFreeString(bstr);
   1.803 +        }
   1.804 +        preading->lpVtbl->Release(preading);
   1.805 +    }
   1.806 +    else if (SUCCEEDED(pElement->lpVtbl->QueryInterface(pElement, &IID_ITfCandidateListUIElement, (PVOID *)&pcandidates)))
   1.807 +    {
   1.808 +        pcandidates->lpVtbl->Release(pcandidates);
   1.809 +    }
   1.810 +    return S_OK;
   1.811 +}
   1.812 +
   1.813 +STDMETHODIMP UIElementSink_UpdateUIElement(TSFSink *sink, DWORD dwUIElementId)
   1.814 +{
   1.815 +    ITfUIElement *pElement = UILess_GetUIElement((SDL_VideoData *)sink->data, dwUIElementId);
   1.816 +    ITfReadingInformationUIElement *preading = 0;
   1.817 +    ITfCandidateListUIElement *pcandidates = 0;
   1.818 +    SDL_VideoData *videodata = (SDL_VideoData *)sink->data;
   1.819 +    if (!pElement)
   1.820 +        return E_INVALIDARG;
   1.821 +
   1.822 +    if (SUCCEEDED(pElement->lpVtbl->QueryInterface(pElement, &IID_ITfReadingInformationUIElement, (LPVOID *)&preading)))
   1.823 +    {
   1.824 +        BSTR bstr;
   1.825 +        if (SUCCEEDED(preading->lpVtbl->GetString(preading, &bstr)) && bstr)
   1.826 +        {
   1.827 +            WCHAR *s = (WCHAR *)bstr;
   1.828 +            SDL_wcslcpy(videodata->ime_readingstring, s, sizeof(videodata->ime_readingstring));
   1.829 +            IME_SendEditingEvent(videodata);
   1.830 +            SysFreeString(bstr);
   1.831 +        }
   1.832 +        preading->lpVtbl->Release(preading);
   1.833 +    }
   1.834 +    else if (SUCCEEDED(pElement->lpVtbl->QueryInterface(pElement, &IID_ITfCandidateListUIElement, (PVOID *)&pcandidates)))
   1.835 +    {
   1.836 +        pcandidates->lpVtbl->Release(pcandidates);
   1.837 +    }
   1.838 +    return S_OK;
   1.839 +}
   1.840 +
   1.841 +STDMETHODIMP UIElementSink_EndUIElement(TSFSink *sink, DWORD dwUIElementId)
   1.842 +{
   1.843 +    ITfUIElement *pElement = UILess_GetUIElement((SDL_VideoData *)sink->data, dwUIElementId);
   1.844 +    ITfReadingInformationUIElement *preading = 0;
   1.845 +    ITfCandidateListUIElement *pcandidates = 0;
   1.846 +    SDL_VideoData *videodata = (SDL_VideoData *)sink->data;
   1.847 +    if (!pElement)
   1.848 +        return E_INVALIDARG;
   1.849 +
   1.850 +    if (SUCCEEDED(pElement->lpVtbl->QueryInterface(pElement, &IID_ITfReadingInformationUIElement, (LPVOID *)&preading)))
   1.851 +    {
   1.852 +        videodata->ime_readingstring[0] = 0;
   1.853 +        IME_SendEditingEvent(videodata);
   1.854 +        preading->lpVtbl->Release(preading);
   1.855 +    }
   1.856 +    else if (SUCCEEDED(pElement->lpVtbl->QueryInterface(pElement, &IID_ITfCandidateListUIElement, (PVOID *)&pcandidates)))
   1.857 +    {
   1.858 +        pcandidates->lpVtbl->Release(pcandidates);
   1.859 +    }
   1.860 +    return S_OK;
   1.861 +}
   1.862 +
   1.863 +STDMETHODIMP IPPASink_QueryInterface(TSFSink *sink, REFIID riid, PVOID *ppv)
   1.864 +{
   1.865 +    if (!ppv)
   1.866 +        return E_INVALIDARG;
   1.867 +
   1.868 +    *ppv = 0;
   1.869 +    if (SDL_IsEqualIID(riid, &IID_IUnknown))
   1.870 +        *ppv = (IUnknown *)sink;
   1.871 +    else if (SDL_IsEqualIID(riid, &IID_ITfInputProcessorProfileActivationSink))
   1.872 +        *ppv = (ITfInputProcessorProfileActivationSink *)sink;
   1.873 +
   1.874 +    if (*ppv)
   1.875 +    {
   1.876 +        TSFSink_AddRef(sink);
   1.877 +        return S_OK;
   1.878 +    }
   1.879 +    return E_NOINTERFACE;
   1.880 +}
   1.881 +
   1.882 +STDMETHODIMP IPPASink_OnActivated(TSFSink *sink, DWORD dwProfileType, LANGID langid, REFCLSID clsid, REFGUID catid, REFGUID guidProfile, HKL hkl, DWORD dwFlags)
   1.883 +{
   1.884 +    if (SDL_IsEqualIID(catid, &GUID_TFCAT_TIP_KEYBOARD) && (dwFlags & TF_IPSINK_FLAG_ACTIVE))
   1.885 +        IME_InputLangChanged((SDL_VideoData *)sink->data);
   1.886 +
   1.887 +    return S_OK;
   1.888 +}
   1.889 +
   1.890 +static void *vtUIElementSink[] = {
   1.891 +    (void *)(UIElementSink_QueryInterface),
   1.892 +    (void *)(TSFSink_AddRef),
   1.893 +    (void *)(TSFSink_Release),
   1.894 +    (void *)(UIElementSink_BeginUIElement),
   1.895 +    (void *)(UIElementSink_UpdateUIElement),
   1.896 +    (void *)(UIElementSink_EndUIElement)
   1.897 +};
   1.898 +
   1.899 +static void *vtIPPASink[] = {
   1.900 +    (void *)(IPPASink_QueryInterface),
   1.901 +    (void *)(TSFSink_AddRef),
   1.902 +    (void *)(TSFSink_Release),
   1.903 +    (void *)(IPPASink_OnActivated)
   1.904 +};
   1.905 +
   1.906 +static void
   1.907 +UILess_EnableUIUpdates(SDL_VideoData *videodata)
   1.908 +{
   1.909 +    ITfSource *source = 0;
   1.910 +    if (!videodata->ime_threadmgrex || videodata->ime_uielemsinkcookie != TF_INVALID_COOKIE)
   1.911 +        return;
   1.912 +
   1.913 +    if (SUCCEEDED(videodata->ime_threadmgrex->lpVtbl->QueryInterface(videodata->ime_threadmgrex, &IID_ITfSource, (LPVOID *)&source)))
   1.914 +    {
   1.915 +        source->lpVtbl->AdviseSink(source, &IID_ITfUIElementSink, (IUnknown *)videodata->ime_uielemsink, &videodata->ime_uielemsinkcookie);
   1.916 +        source->lpVtbl->Release(source);
   1.917 +    }
   1.918 +}
   1.919 +
   1.920 +static void
   1.921 +UILess_DisableUIUpdates(SDL_VideoData *videodata)
   1.922 +{
   1.923 +    ITfSource *source = 0;
   1.924 +    if (!videodata->ime_threadmgrex || videodata->ime_uielemsinkcookie == TF_INVALID_COOKIE)
   1.925 +        return;
   1.926 +
   1.927 +    if (SUCCEEDED(videodata->ime_threadmgrex->lpVtbl->QueryInterface(videodata->ime_threadmgrex, &IID_ITfSource, (LPVOID *)&source)))
   1.928 +    {
   1.929 +        source->lpVtbl->UnadviseSink(source, videodata->ime_uielemsinkcookie);
   1.930 +        videodata->ime_uielemsinkcookie = TF_INVALID_COOKIE;
   1.931 +        source->lpVtbl->Release(source);
   1.932 +    }
   1.933 +}
   1.934 +
   1.935 +static SDL_bool
   1.936 +UILess_SetupSinks(SDL_VideoData *videodata)
   1.937 +{
   1.938 +    TfClientId clientid = 0;
   1.939 +    SDL_bool result = SDL_FALSE;
   1.940 +    ITfSource *source = 0;
   1.941 +    if (FAILED(CoCreateInstance(&CLSID_TF_ThreadMgr, NULL, CLSCTX_INPROC_SERVER, &IID_ITfThreadMgrEx, &videodata->ime_threadmgrex)))
   1.942 +        return SDL_FALSE;
   1.943 +
   1.944 +    if (FAILED(videodata->ime_threadmgrex->lpVtbl->ActivateEx(videodata->ime_threadmgrex, &clientid, TF_TMAE_UIELEMENTENABLEDONLY)))
   1.945 +        return SDL_FALSE;
   1.946 +
   1.947 +    videodata->ime_uielemsink = SDL_malloc(sizeof(TSFSink));
   1.948 +    videodata->ime_ippasink = SDL_malloc(sizeof(TSFSink));
   1.949 +
   1.950 +    videodata->ime_uielemsink->lpVtbl = vtUIElementSink;
   1.951 +    videodata->ime_uielemsink->refcount = 1;
   1.952 +    videodata->ime_uielemsink->data = videodata;
   1.953 +
   1.954 +    videodata->ime_ippasink->lpVtbl = vtIPPASink;
   1.955 +    videodata->ime_ippasink->refcount = 1;
   1.956 +    videodata->ime_ippasink->data = videodata;
   1.957 +
   1.958 +    if (SUCCEEDED(videodata->ime_threadmgrex->lpVtbl->QueryInterface(videodata->ime_threadmgrex, &IID_ITfSource, (LPVOID *)&source)))
   1.959 +    {
   1.960 +        if (SUCCEEDED(source->lpVtbl->AdviseSink(source, &IID_ITfUIElementSink, (IUnknown *)videodata->ime_uielemsink, &videodata->ime_uielemsinkcookie)))
   1.961 +        {
   1.962 +            if (SUCCEEDED(source->lpVtbl->AdviseSink(source, &IID_ITfInputProcessorProfileActivationSink, (IUnknown *)videodata->ime_ippasink, &videodata->ime_alpnsinkcookie)))
   1.963 +            {
   1.964 +                result = SDL_TRUE;
   1.965 +            }
   1.966 +        }
   1.967 +        source->lpVtbl->Release(source);
   1.968 +    }
   1.969 +    return result;
   1.970 +}
   1.971 +
   1.972 +#define SAFE_RELEASE(p)                             \
   1.973 +{                                                   \
   1.974 +    if (p) {                                        \
   1.975 +        (p)->lpVtbl->Release((p));                  \
   1.976 +        (p) = 0;                                    \
   1.977 +    }                                               \
   1.978 +}
   1.979 +
   1.980 +static void
   1.981 +UILess_ReleaseSinks(SDL_VideoData *videodata)
   1.982 +{
   1.983 +    ITfSource *Source = 0;
   1.984 +    if (videodata->ime_threadmgrex && SUCCEEDED(videodata->ime_threadmgrex->lpVtbl->QueryInterface(videodata->ime_threadmgrex, &IID_ITfSource, &Source)))
   1.985 +    {
   1.986 +        Source->lpVtbl->UnadviseSink(Source, videodata->ime_uielemsinkcookie);
   1.987 +        Source->lpVtbl->UnadviseSink(Source, videodata->ime_alpnsinkcookie);
   1.988 +        SAFE_RELEASE(Source);
   1.989 +        videodata->ime_threadmgrex->lpVtbl->Deactivate(videodata->ime_threadmgrex);
   1.990 +        SAFE_RELEASE(videodata->ime_threadmgrex);
   1.991 +        TSFSink_Release(videodata->ime_uielemsink);
   1.992 +        videodata->ime_uielemsink = 0;
   1.993 +        TSFSink_Release(videodata->ime_ippasink);
   1.994 +        videodata->ime_ippasink = 0;
   1.995 +    }
   1.996 +}
   1.997 +
   1.998  /* vi: set ts=4 sw=4 expandtab: */
     2.1 --- a/src/video/win32/SDL_win32video.h	Tue Aug 03 16:52:10 2010 -0400
     2.2 +++ b/src/video/win32/SDL_win32video.h	Tue Aug 03 16:57:49 2010 -0400
     2.3 @@ -1,95 +1,150 @@
     2.4 -/*
     2.5 -    SDL - Simple DirectMedia Layer
     2.6 -    Copyright (C) 1997-2010 Sam Lantinga
     2.7 -
     2.8 -    This library is free software; you can redistribute it and/or
     2.9 -    modify it under the terms of the GNU Lesser General Public
    2.10 -    License as published by the Free Software Foundation; either
    2.11 -    version 2.1 of the License, or (at your option) any later version.
    2.12 -
    2.13 -    This library is distributed in the hope that it will be useful,
    2.14 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.15 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    2.16 -    Lesser General Public License for more details.
    2.17 -
    2.18 -    You should have received a copy of the GNU Lesser General Public
    2.19 -    License along with this library; if not, write to the Free Software
    2.20 -    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    2.21 -
    2.22 -    Sam Lantinga
    2.23 -    slouken@libsdl.org
    2.24 -*/
    2.25 -#include "SDL_config.h"
    2.26 -
    2.27 -#ifndef _SDL_win32video_h
    2.28 -#define _SDL_win32video_h
    2.29 -
    2.30 -#include "../SDL_sysvideo.h"
    2.31 -
    2.32 -#define WIN32_LEAN_AND_MEAN
    2.33 -#define STRICT
    2.34 -#define UNICODE
    2.35 -#undef WINVER
    2.36 -#define WINVER  0x500           /* Need 0x410 for AlphaBlend() and 0x500 for EnumDisplayDevices() */
    2.37 -#include <windows.h>
    2.38 -
    2.39 -#if SDL_VIDEO_RENDER_D3D
    2.40 -//#include <d3d9.h>
    2.41 -#define D3D_DEBUG_INFO
    2.42 -#include "d3d9.h"
    2.43 -#endif
    2.44 -
    2.45 -#if SDL_VIDEO_RENDER_DDRAW
    2.46 -/* WIN32_LEAN_AND_MEAN was defined, so we have to include this by hand */
    2.47 -#include <objbase.h>
    2.48 -#include "ddraw.h"
    2.49 -#endif
    2.50 -
    2.51 -#include "SDL_win32clipboard.h"
    2.52 -#include "SDL_win32events.h"
    2.53 -#include "SDL_win32gamma.h"
    2.54 -#include "SDL_win32keyboard.h"
    2.55 -#include "SDL_win32modes.h"
    2.56 -#include "SDL_win32mouse.h"
    2.57 -#include "SDL_win32opengl.h"
    2.58 -#include "SDL_win32window.h"
    2.59 -
    2.60 -#ifdef UNICODE
    2.61 -#define WIN_StringToUTF8(S) SDL_iconv_string("UTF-8", "UCS-2", (char *)S, (SDL_wcslen(S)+1)*sizeof(WCHAR))
    2.62 -#define WIN_UTF8ToString(S) (WCHAR *)SDL_iconv_string("UCS-2", "UTF-8", (char *)S, SDL_strlen(S)+1)
    2.63 -#else
    2.64 -#define WIN_StringToUTF8(S) SDL_iconv_string("UTF-8", "ASCII", (char *)S, (SDL_strlen(S)+1))
    2.65 -#define WIN_UTF8ToString(S) SDL_iconv_string("ASCII", "UTF-8", (char *)S, SDL_strlen(S)+1)
    2.66 -#endif
    2.67 -extern void WIN_SetError(const char *prefix);
    2.68 -
    2.69 -/* Private display data */
    2.70 -
    2.71 -typedef struct SDL_VideoData
    2.72 -{
    2.73 -#if SDL_VIDEO_RENDER_D3D
    2.74 -    HANDLE d3dDLL;
    2.75 -    IDirect3D9 *d3d;
    2.76 -#endif
    2.77 -#if SDL_VIDEO_RENDER_DDRAW
    2.78 -    HANDLE ddrawDLL;
    2.79 -    IDirectDraw *ddraw;
    2.80 -#endif
    2.81 -
    2.82 -    const SDL_scancode *key_layout;
    2.83 -    DWORD clipboard_count;
    2.84 -
    2.85 -    SDL_bool ime_com_initialized;
    2.86 -    struct ITfThreadMgr *ime_thread_mgr;
    2.87 -    SDL_bool ime_initialized;
    2.88 -    SDL_bool ime_enabled;
    2.89 -    SDL_bool ime_available;
    2.90 -    HWND ime_hwnd_main;
    2.91 -    HWND ime_hwnd_current;
    2.92 -    HIMC ime_himc;
    2.93 -
    2.94 -} SDL_VideoData;
    2.95 -
    2.96 -#endif /* _SDL_win32video_h */
    2.97 -
    2.98 -/* vi: set ts=4 sw=4 expandtab: */
    2.99 +/*
   2.100 +    SDL - Simple DirectMedia Layer
   2.101 +    Copyright (C) 1997-2010 Sam Lantinga
   2.102 +
   2.103 +    This library is free software; you can redistribute it and/or
   2.104 +    modify it under the terms of the GNU Lesser General Public
   2.105 +    License as published by the Free Software Foundation; either
   2.106 +    version 2.1 of the License, or (at your option) any later version.
   2.107 +
   2.108 +    This library is distributed in the hope that it will be useful,
   2.109 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   2.110 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   2.111 +    Lesser General Public License for more details.
   2.112 +
   2.113 +    You should have received a copy of the GNU Lesser General Public
   2.114 +    License along with this library; if not, write to the Free Software
   2.115 +    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   2.116 +
   2.117 +    Sam Lantinga
   2.118 +    slouken@libsdl.org
   2.119 +*/
   2.120 +#include "SDL_config.h"
   2.121 +
   2.122 +#ifndef _SDL_win32video_h
   2.123 +#define _SDL_win32video_h
   2.124 +
   2.125 +#include "../SDL_sysvideo.h"
   2.126 +
   2.127 +#define WIN32_LEAN_AND_MEAN
   2.128 +#define STRICT
   2.129 +#define UNICODE
   2.130 +#undef WINVER
   2.131 +#define WINVER  0x500           /* Need 0x410 for AlphaBlend() and 0x500 for EnumDisplayDevices() */
   2.132 +#include <windows.h>
   2.133 +
   2.134 +#include <msctf.h>
   2.135 +
   2.136 +#if SDL_VIDEO_RENDER_D3D
   2.137 +//#include <d3d9.h>
   2.138 +#define D3D_DEBUG_INFO
   2.139 +#include "d3d9.h"
   2.140 +#endif
   2.141 +
   2.142 +#if SDL_VIDEO_RENDER_DDRAW
   2.143 +/* WIN32_LEAN_AND_MEAN was defined, so we have to include this by hand */
   2.144 +#include <objbase.h>
   2.145 +#include "ddraw.h"
   2.146 +#endif
   2.147 +
   2.148 +#include "SDL_win32clipboard.h"
   2.149 +#include "SDL_win32events.h"
   2.150 +#include "SDL_win32gamma.h"
   2.151 +#include "SDL_win32keyboard.h"
   2.152 +#include "SDL_win32modes.h"
   2.153 +#include "SDL_win32mouse.h"
   2.154 +#include "SDL_win32opengl.h"
   2.155 +#include "SDL_win32window.h"
   2.156 +#include "SDL_events.h"
   2.157 +
   2.158 +#ifdef UNICODE
   2.159 +#define WIN_StringToUTF8(S) SDL_iconv_string("UTF-8", "UCS-2", (char *)S, (SDL_wcslen(S)+1)*sizeof(WCHAR))
   2.160 +#define WIN_UTF8ToString(S) (WCHAR *)SDL_iconv_string("UCS-2", "UTF-8", (char *)S, SDL_strlen(S)+1)
   2.161 +#else
   2.162 +#define WIN_StringToUTF8(S) SDL_iconv_string("UTF-8", "ASCII", (char *)S, (SDL_strlen(S)+1))
   2.163 +#define WIN_UTF8ToString(S) SDL_iconv_string("ASCII", "UTF-8", (char *)S, SDL_strlen(S)+1)
   2.164 +#endif
   2.165 +extern void WIN_SetError(const char *prefix);
   2.166 +
   2.167 +typedef struct  
   2.168 +{
   2.169 +    void **lpVtbl;
   2.170 +    int refcount;
   2.171 +    void *data;
   2.172 +} TSFSink;
   2.173 +
   2.174 +// Definition from Win98DDK version of IMM.H
   2.175 +typedef struct tagINPUTCONTEXT2 {
   2.176 +    HWND                hWnd;                           
   2.177 +    BOOL                fOpen;                          
   2.178 +    POINT               ptStatusWndPos;                 
   2.179 +    POINT               ptSoftKbdPos;                   
   2.180 +    DWORD               fdwConversion;                  
   2.181 +    DWORD               fdwSentence;                    
   2.182 +    union   {                                           
   2.183 +        LOGFONTA        A;                              
   2.184 +        LOGFONTW        W;                              
   2.185 +    } lfFont;                                           
   2.186 +    COMPOSITIONFORM     cfCompForm;                     
   2.187 +    CANDIDATEFORM       cfCandForm[4];                  
   2.188 +    HIMCC               hCompStr;                       
   2.189 +    HIMCC               hCandInfo;                      
   2.190 +    HIMCC               hGuideLine;                     
   2.191 +    HIMCC               hPrivate;                       
   2.192 +    DWORD               dwNumMsgBuf;                    
   2.193 +    HIMCC               hMsgBuf;                        
   2.194 +    DWORD               fdwInit;                        
   2.195 +    DWORD               dwReserve[3];                   
   2.196 +} INPUTCONTEXT2, *PINPUTCONTEXT2, NEAR *NPINPUTCONTEXT2, FAR *LPINPUTCONTEXT2;  
   2.197 +
   2.198 +/* Private display data */
   2.199 +
   2.200 +typedef struct SDL_VideoData
   2.201 +{
   2.202 +#if SDL_VIDEO_RENDER_D3D
   2.203 +    HANDLE d3dDLL;
   2.204 +    IDirect3D9 *d3d;
   2.205 +#endif
   2.206 +#if SDL_VIDEO_RENDER_DDRAW
   2.207 +    HANDLE ddrawDLL;
   2.208 +    IDirectDraw *ddraw;
   2.209 +#endif
   2.210 +
   2.211 +    const SDL_scancode *key_layout;
   2.212 +    DWORD clipboard_count;
   2.213 +
   2.214 +    SDL_bool ime_com_initialized;
   2.215 +    struct ITfThreadMgr *ime_threadmgr;
   2.216 +    SDL_bool ime_initialized;
   2.217 +    SDL_bool ime_enabled;
   2.218 +    SDL_bool ime_available;
   2.219 +    HWND ime_hwnd_main;
   2.220 +    HWND ime_hwnd_current;
   2.221 +    HIMC ime_himc;
   2.222 +
   2.223 +    WCHAR ime_composition[SDL_TEXTEDITINGEVENT_TEXT_SIZE];
   2.224 +    WCHAR ime_readingstring[16];
   2.225 +    int ime_cursor;
   2.226 +
   2.227 +    HKL ime_hkl;
   2.228 +    HMODULE ime_himm32;
   2.229 +    UINT (WINAPI *GetReadingString)(HIMC himc, UINT uReadingBufLen, LPWSTR lpwReadingBuf, PINT pnErrorIndex, BOOL *pfIsVertical, PUINT puMaxReadingLen);
   2.230 +    BOOL (WINAPI *ShowReadingWindow)(HIMC himc, BOOL bShow);
   2.231 +    LPINPUTCONTEXT2 (WINAPI *ImmLockIMC)(HIMC himc);
   2.232 +    BOOL (WINAPI *ImmUnlockIMC)(HIMC himc);
   2.233 +    LPVOID (WINAPI *ImmLockIMCC)(HIMCC himcc);
   2.234 +    BOOL (WINAPI *ImmUnlockIMCC)(HIMCC himcc);
   2.235 +
   2.236 +    SDL_bool ime_uiless;
   2.237 +    struct ITfThreadMgrEx *ime_threadmgrex;
   2.238 +    DWORD ime_uielemsinkcookie;
   2.239 +    DWORD ime_alpnsinkcookie;
   2.240 +    DWORD ime_openmodesinkcookie;
   2.241 +    DWORD ime_convmodesinkcookie;
   2.242 +    TSFSink *ime_uielemsink;
   2.243 +    TSFSink *ime_ippasink;
   2.244 +} SDL_VideoData;
   2.245 +
   2.246 +#endif /* _SDL_win32video_h */
   2.247 +
   2.248 +/* vi: set ts=4 sw=4 expandtab: */