Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 1 | /* vi:set ts=8 sts=4 sw=4: |
| 2 | * |
| 3 | * VIM - Vi IMproved by Bram Moolenaar |
| 4 | * |
| 5 | * Do ":help uganda" in Vim to read copying and usage conditions. |
| 6 | * Do ":help credits" in Vim to see a list of people who contributed. |
| 7 | */ |
| 8 | |
| 9 | /* |
| 10 | * DESCRIPTION: |
| 11 | * This module produces Global IME for Vim, on Windows with Internet |
| 12 | * Explorer 5.01 or higher. You need three files "dimm.idl", "dimm.h", and |
| 13 | * "dimm_i.c" when compile this module at your self. "dimm.h", and |
| 14 | * "dimm_i.c" are generated from "dimm.idl" by using MIDL.EXE as like |
| 15 | * "if_ole.h". You can get "dimm.idl" in MSDN web site. I got it below |
| 16 | * URL. |
| 17 | * |
| 18 | * WHAT IS THE GLOBAL IME?: |
| 19 | * Global IME makes capability input Chinese, Japanese, and Korean text into |
| 20 | * Vim buffer on any language version of Windows 98, Windows 95, and Windows |
| 21 | * NT 4.0. See below URL for detail of Global IME. You can also find |
Bram Moolenaar | 143c38c | 2007-05-10 16:41:10 +0000 | [diff] [blame] | 22 | * various language version of Global IME at same place. |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 23 | * |
| 24 | * RUNTIME REQUIREMENTS: |
Bram Moolenaar | 143c38c | 2007-05-10 16:41:10 +0000 | [diff] [blame] | 25 | * - Internet Explorer 5.01 or higher. |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 26 | * - Global IME (with language pack?). |
| 27 | * - Of course Vim for Windows. |
| 28 | * |
| 29 | * URLS: |
| 30 | * - Where you can probably get "dimm.idl". |
| 31 | * http://msdn.microsoft.com/downloads/samples/internet/libraries/ie5_lib/sample.asp |
| 32 | * - Global IME detailed information. |
| 33 | * http://www.microsoft.com/windows/ie/features/ime.asp |
| 34 | */ |
| 35 | |
| 36 | #ifdef GLOBAL_IME |
| 37 | |
| 38 | #define WIN32_LEAN_AND_MEAN |
| 39 | #include <windows.h> |
| 40 | #include <objbase.h> |
| 41 | extern "C" { |
| 42 | #include "vim.h" |
| 43 | } |
| 44 | #include "dimm.h" |
| 45 | #include "glbl_ime.h" |
| 46 | |
| 47 | static IActiveIMMApp *pIApp = NULL; |
| 48 | static IActiveIMMMessagePumpOwner *pIMsg = NULL; |
| 49 | static HWND s_hWnd = NULL; |
| 50 | static BOOL s_bStatus = FALSE; /* for evacuate */ |
| 51 | |
| 52 | /* |
| 53 | * Initialize Global IME. |
| 54 | * "atom" must be return value of RegisterClass(Ex). |
| 55 | */ |
| 56 | void |
| 57 | global_ime_init(ATOM atom, HWND hWnd) |
| 58 | { |
| 59 | IUnknown *pI; |
| 60 | HRESULT hr; |
| 61 | |
| 62 | if (pIApp != NULL || pIMsg != NULL) |
| 63 | return; |
| 64 | OleInitialize(NULL); |
| 65 | |
| 66 | /* |
| 67 | * Get interface IUnknown |
| 68 | */ |
| 69 | hr = CoCreateInstance(CLSID_CActiveIMM, NULL, CLSCTX_SERVER, |
| 70 | IID_IUnknown, (void**)&pI); |
| 71 | if (FAILED(hr) || !pI) |
| 72 | return; |
| 73 | |
| 74 | /* |
| 75 | * Get interface IActiveIMMApp |
| 76 | */ |
| 77 | hr = pI->QueryInterface(IID_IActiveIMMApp, (void**)&pIApp); |
| 78 | if (FAILED(hr)) |
| 79 | pIApp = NULL; |
| 80 | |
| 81 | /* |
| 82 | * Get interface IActiveIMMMessagePumpOwner |
| 83 | */ |
| 84 | hr = pI->QueryInterface(IID_IActiveIMMMessagePumpOwner, (void**)&pIMsg); |
| 85 | if (FAILED(hr)) |
| 86 | pIMsg = NULL; |
| 87 | |
| 88 | if (pIApp != NULL) |
| 89 | { |
| 90 | pIApp->Activate(TRUE); |
| 91 | pIApp->FilterClientWindows(&atom, 1); |
| 92 | } |
| 93 | if (pIMsg != NULL) |
| 94 | pIMsg->Start(); |
| 95 | |
| 96 | pI->Release(); |
| 97 | s_hWnd = hWnd; |
| 98 | } |
| 99 | |
| 100 | /* |
| 101 | * Reset and clear Global IME. |
| 102 | */ |
| 103 | void |
| 104 | global_ime_end() |
| 105 | { |
| 106 | if (pIApp != NULL) |
| 107 | { |
| 108 | IActiveIMMApp *p = pIApp; |
| 109 | |
| 110 | pIApp = NULL; |
| 111 | p->FilterClientWindows(NULL, 0); |
| 112 | p->Deactivate(); |
| 113 | p->Release(); |
| 114 | } |
| 115 | if (pIMsg != NULL) |
| 116 | { |
| 117 | IActiveIMMMessagePumpOwner *p = pIMsg; |
| 118 | |
| 119 | pIMsg = NULL; |
| 120 | p->End(); |
| 121 | p->Release(); |
| 122 | } |
| 123 | OleUninitialize(); |
| 124 | } |
| 125 | |
| 126 | /* |
| 127 | * Replacement for DefWindowProc(). |
| 128 | */ |
| 129 | LRESULT WINAPI |
| 130 | global_ime_DefWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) |
| 131 | { |
| 132 | LRESULT lResult; |
| 133 | |
| 134 | if (pIApp == NULL || pIApp->OnDefWindowProc(hWnd, Msg, |
| 135 | wParam, lParam, &lResult) != S_OK) |
| 136 | { |
| 137 | #if defined(WIN3264) && defined(FEAT_MBYTE) |
| 138 | if (wide_WindowProc) |
Bram Moolenaar | ee0446c | 2005-05-27 20:13:12 +0000 | [diff] [blame] | 139 | lResult = DefWindowProcW(hWnd, Msg, wParam, lParam); |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 140 | else |
| 141 | #endif |
| 142 | lResult = DefWindowProc(hWnd, Msg, wParam, lParam); |
| 143 | } |
| 144 | return lResult; |
| 145 | } |
| 146 | |
| 147 | /* |
| 148 | * Replace with TranslateMessage() |
| 149 | */ |
| 150 | BOOL WINAPI |
| 151 | global_ime_TranslateMessage(CONST MSG *lpMsg) |
| 152 | { |
| 153 | if (pIMsg == NULL || pIMsg->OnTranslateMessage(lpMsg) == S_FALSE) |
| 154 | return TranslateMessage(lpMsg); |
| 155 | return TRUE; |
| 156 | } |
| 157 | |
| 158 | /* |
Bram Moolenaar | 84a05ac | 2013-05-06 04:24:17 +0200 | [diff] [blame^] | 159 | * Set position of IME composition window. |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 160 | * |
| 161 | * You have to call this before starting composition. If once composition |
Bram Moolenaar | 143c38c | 2007-05-10 16:41:10 +0000 | [diff] [blame] | 162 | * started, this can take no effect until that composition have finished. So |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 163 | * you should handle WM_IME_STARTCOMPOSITION and call this function. |
| 164 | */ |
| 165 | void WINAPI |
| 166 | global_ime_set_position(POINT *pPoint) |
| 167 | { |
| 168 | HIMC hImc = NULL; |
| 169 | |
| 170 | if (pIApp == NULL || pPoint == NULL) |
| 171 | return; |
| 172 | |
| 173 | if (SUCCEEDED(pIApp->GetContext(s_hWnd, &hImc))) |
| 174 | { |
| 175 | COMPOSITIONFORM CompForm; |
| 176 | |
| 177 | CompForm.dwStyle = CFS_POINT; |
| 178 | CompForm.ptCurrentPos = *pPoint; |
| 179 | pIApp->SetCompositionWindow(hImc, &CompForm); |
| 180 | pIApp->ReleaseContext(s_hWnd, hImc); |
| 181 | } |
| 182 | } |
| 183 | |
| 184 | /* |
| 185 | * Set font to Global IME |
| 186 | */ |
| 187 | /* GIME_TEST */ |
| 188 | void WINAPI |
| 189 | global_ime_set_font(LOGFONT *pFont) |
| 190 | { |
| 191 | HIMC hImc = NULL; |
| 192 | |
| 193 | if (pIApp == NULL || pFont == NULL) |
| 194 | return; |
| 195 | |
| 196 | if (SUCCEEDED(pIApp->GetContext(s_hWnd, &hImc))) |
| 197 | { |
| 198 | pIApp->SetCompositionFontA(hImc, pFont); |
| 199 | pIApp->ReleaseContext(s_hWnd, hImc); |
| 200 | } |
| 201 | } |
| 202 | |
Bram Moolenaar | 9c96f59 | 2005-06-30 21:52:39 +0000 | [diff] [blame] | 203 | #if 0 |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 204 | /* |
| 205 | * for IME control. Save current status of IME, and set force new-status to |
Bram Moolenaar | 9c96f59 | 2005-06-30 21:52:39 +0000 | [diff] [blame] | 206 | * English (turn off). |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 207 | */ |
| 208 | void WINAPI |
| 209 | global_ime_status_evacuate() |
| 210 | { |
| 211 | HIMC hImc; |
| 212 | |
| 213 | if (pIApp != NULL && SUCCEEDED(pIApp->GetContext(s_hWnd, &hImc))) |
| 214 | { |
| 215 | s_bStatus = (pIApp->GetOpenStatus(hImc) == 0) ? TRUE : FALSE; |
| 216 | pIApp->SetOpenStatus(hImc, FALSE); |
| 217 | pIApp->ReleaseContext(s_hWnd, hImc); |
| 218 | } |
| 219 | } |
| 220 | |
| 221 | /* |
| 222 | * for IME control. Change IME status to last saved one. |
| 223 | */ |
| 224 | void WINAPI |
| 225 | global_ime_status_restore() |
| 226 | { |
| 227 | HIMC hImc; |
| 228 | |
| 229 | if (pIApp != NULL && SUCCEEDED(pIApp->GetContext(s_hWnd, &hImc))) |
| 230 | { |
| 231 | pIApp->SetOpenStatus(hImc, s_bStatus); |
| 232 | pIApp->ReleaseContext(s_hWnd, hImc); |
| 233 | } |
| 234 | } |
Bram Moolenaar | 9c96f59 | 2005-06-30 21:52:39 +0000 | [diff] [blame] | 235 | #endif |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 236 | |
| 237 | void WINAPI |
| 238 | global_ime_set_status(int status) |
| 239 | { |
| 240 | HIMC hImc; |
| 241 | |
| 242 | if (pIApp != NULL && SUCCEEDED(pIApp->GetContext(s_hWnd, &hImc))) |
| 243 | { |
| 244 | pIApp->SetOpenStatus(hImc, status ? TRUE : FALSE); |
| 245 | pIApp->ReleaseContext(s_hWnd, hImc); |
| 246 | } |
| 247 | } |
| 248 | |
| 249 | int WINAPI |
| 250 | global_ime_get_status() |
| 251 | { |
| 252 | int status = 0; |
| 253 | HIMC hImc; |
| 254 | |
| 255 | if (pIApp != NULL && SUCCEEDED(pIApp->GetContext(s_hWnd, &hImc))) |
| 256 | { |
| 257 | status = pIApp->GetOpenStatus(hImc) ? 1 : 0; |
| 258 | pIApp->ReleaseContext(s_hWnd, hImc); |
| 259 | } |
| 260 | return status; |
| 261 | } |
| 262 | |
| 263 | #endif /* GLOBAL_IME */ |