Merged from the latest developing branch.
[MacVim.git] / src / glbl_ime.cpp
blob1abfeaf57ed00dde4a08e756e37725c04f050bd7
1 /* vi:set ts=8 sts=4 sw=4:
3 * VIM - Vi IMproved by Bram Moolenaar
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 */
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.
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.
24 * RUNTIME REQUIREMENTS:
25 * - Internet Explorer 5.01 or higher.
26 * - Global IME (with language pack?).
27 * - Of course Vim for Windows.
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
36 #ifdef GLOBAL_IME
38 #define WIN32_LEAN_AND_MEAN
39 #include <windows.h>
40 #include <objbase.h>
41 extern "C" {
42 #include "vim.h"
44 #include "dimm.h"
45 #include "glbl_ime.h"
47 static IActiveIMMApp *pIApp = NULL;
48 static IActiveIMMMessagePumpOwner *pIMsg = NULL;
49 static HWND s_hWnd = NULL;
50 static BOOL s_bStatus = FALSE; /* for evacuate */
53 * Initialize Global IME.
54 * "atom" must be return value of RegisterClass(Ex).
56 void
57 global_ime_init(ATOM atom, HWND hWnd)
59 IUnknown *pI;
60 HRESULT hr;
62 if (pIApp != NULL || pIMsg != NULL)
63 return;
64 OleInitialize(NULL);
67 * Get interface IUnknown
69 hr = CoCreateInstance(CLSID_CActiveIMM, NULL, CLSCTX_SERVER,
70 IID_IUnknown, (void**)&pI);
71 if (FAILED(hr) || !pI)
72 return;
75 * Get interface IActiveIMMApp
77 hr = pI->QueryInterface(IID_IActiveIMMApp, (void**)&pIApp);
78 if (FAILED(hr))
79 pIApp = NULL;
82 * Get interface IActiveIMMMessagePumpOwner
84 hr = pI->QueryInterface(IID_IActiveIMMMessagePumpOwner, (void**)&pIMsg);
85 if (FAILED(hr))
86 pIMsg = NULL;
88 if (pIApp != NULL)
90 pIApp->Activate(TRUE);
91 pIApp->FilterClientWindows(&atom, 1);
93 if (pIMsg != NULL)
94 pIMsg->Start();
96 pI->Release();
97 s_hWnd = hWnd;
101 * Reset and clear Global IME.
103 void
104 global_ime_end()
106 if (pIApp != NULL)
108 IActiveIMMApp *p = pIApp;
110 pIApp = NULL;
111 p->FilterClientWindows(NULL, 0);
112 p->Deactivate();
113 p->Release();
115 if (pIMsg != NULL)
117 IActiveIMMMessagePumpOwner *p = pIMsg;
119 pIMsg = NULL;
120 p->End();
121 p->Release();
123 OleUninitialize();
127 * Replacement for DefWindowProc().
129 LRESULT WINAPI
130 global_ime_DefWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
132 LRESULT lResult;
134 if (pIApp == NULL || pIApp->OnDefWindowProc(hWnd, Msg,
135 wParam, lParam, &lResult) != S_OK)
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);
144 return lResult;
148 * Replace with TranslateMessage()
150 BOOL WINAPI
151 global_ime_TranslateMessage(CONST MSG *lpMsg)
153 if (pIMsg == NULL || pIMsg->OnTranslateMessage(lpMsg) == S_FALSE)
154 return TranslateMessage(lpMsg);
155 return TRUE;
159 * Set position of IME compotision window.
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.
165 void WINAPI
166 global_ime_set_position(POINT *pPoint)
168 HIMC hImc = NULL;
170 if (pIApp == NULL || pPoint == NULL)
171 return;
173 if (SUCCEEDED(pIApp->GetContext(s_hWnd, &hImc)))
175 COMPOSITIONFORM CompForm;
177 CompForm.dwStyle = CFS_POINT;
178 CompForm.ptCurrentPos = *pPoint;
179 pIApp->SetCompositionWindow(hImc, &CompForm);
180 pIApp->ReleaseContext(s_hWnd, hImc);
185 * Set font to Global IME
187 /* GIME_TEST */
188 void WINAPI
189 global_ime_set_font(LOGFONT *pFont)
191 HIMC hImc = NULL;
193 if (pIApp == NULL || pFont == NULL)
194 return;
196 if (SUCCEEDED(pIApp->GetContext(s_hWnd, &hImc)))
198 pIApp->SetCompositionFontA(hImc, pFont);
199 pIApp->ReleaseContext(s_hWnd, hImc);
203 #if 0
205 * for IME control. Save current status of IME, and set force new-status to
206 * English (turn off).
208 void WINAPI
209 global_ime_status_evacuate()
211 HIMC hImc;
213 if (pIApp != NULL && SUCCEEDED(pIApp->GetContext(s_hWnd, &hImc)))
215 s_bStatus = (pIApp->GetOpenStatus(hImc) == 0) ? TRUE : FALSE;
216 pIApp->SetOpenStatus(hImc, FALSE);
217 pIApp->ReleaseContext(s_hWnd, hImc);
222 * for IME control. Change IME status to last saved one.
224 void WINAPI
225 global_ime_status_restore()
227 HIMC hImc;
229 if (pIApp != NULL && SUCCEEDED(pIApp->GetContext(s_hWnd, &hImc)))
231 pIApp->SetOpenStatus(hImc, s_bStatus);
232 pIApp->ReleaseContext(s_hWnd, hImc);
235 #endif
237 void WINAPI
238 global_ime_set_status(int status)
240 HIMC hImc;
242 if (pIApp != NULL && SUCCEEDED(pIApp->GetContext(s_hWnd, &hImc)))
244 pIApp->SetOpenStatus(hImc, status ? TRUE : FALSE);
245 pIApp->ReleaseContext(s_hWnd, hImc);
249 int WINAPI
250 global_ime_get_status()
252 int status = 0;
253 HIMC hImc;
255 if (pIApp != NULL && SUCCEEDED(pIApp->GetContext(s_hWnd, &hImc)))
257 status = pIApp->GetOpenStatus(hImc) ? 1 : 0;
258 pIApp->ReleaseContext(s_hWnd, hImc);
260 return status;
263 #endif /* GLOBAL_IME */