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 22 * various language version of Global IME at same place. 23 * 24 * RUNTIME REQUIREMENTS: 25 * - Internet Explorer 5.01 or higher. 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> 41extern "C" { 42#include "vim.h" 43} 44#include "dimm.h" 45#include "glbl_ime.h" 46 47static IActiveIMMApp *pIApp = NULL; 48static IActiveIMMMessagePumpOwner *pIMsg = NULL; 49static HWND s_hWnd = NULL; 50static BOOL s_bStatus = FALSE; /* for evacuate */ 51 52/* 53 * Initialize Global IME. 54 * "atom" must be return value of RegisterClass(Ex). 55 */ 56 void 57global_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 104global_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 130global_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) 139 lResult = DefWindowProcW(hWnd, Msg, wParam, lParam); 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 151global_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/* 159 * Set position of IME compotision window. 160 * 161 * You have to call this before starting composition. If once composition 162 * started, this can take no effect until that composition have finished. So 163 * you should handle WM_IME_STARTCOMPOSITION and call this function. 164 */ 165 void WINAPI 166global_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 189global_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 203#if 0 204/* 205 * for IME control. Save current status of IME, and set force new-status to 206 * English (turn off). 207 */ 208 void WINAPI 209global_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 225global_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} 235#endif 236 237 void WINAPI 238global_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 250global_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 */ 264