blob: 6fd84ecc42827fae5465ba00ba768f9eabbb352b [file] [log] [blame]
Bram Moolenaaredf3f972016-08-29 22:49:24 +02001/* vi:set ts=8 sts=4 sw=4 noet:
Bram Moolenaar071d4272004-06-13 20:20:40 +00002 *
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 Moolenaar143c38c2007-05-10 16:41:10 +000022 * various language version of Global IME at same place.
Bram Moolenaar071d4272004-06-13 20:20:40 +000023 *
24 * RUNTIME REQUIREMENTS:
Bram Moolenaar143c38c2007-05-10 16:41:10 +000025 * - Internet Explorer 5.01 or higher.
Bram Moolenaar071d4272004-06-13 20:20:40 +000026 * - 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)
Bram Moolenaar0eb035c2019-04-02 22:15:55 +0200136 lResult = DefWindowProcW(hWnd, Msg, wParam, lParam);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000137 return lResult;
138}
139
140/*
141 * Replace with TranslateMessage()
142 */
143 BOOL WINAPI
144global_ime_TranslateMessage(CONST MSG *lpMsg)
145{
146 if (pIMsg == NULL || pIMsg->OnTranslateMessage(lpMsg) == S_FALSE)
147 return TranslateMessage(lpMsg);
148 return TRUE;
149}
150
151/*
Bram Moolenaar84a05ac2013-05-06 04:24:17 +0200152 * Set position of IME composition window.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000153 *
154 * You have to call this before starting composition. If once composition
Bram Moolenaar143c38c2007-05-10 16:41:10 +0000155 * started, this can take no effect until that composition have finished. So
Bram Moolenaar071d4272004-06-13 20:20:40 +0000156 * you should handle WM_IME_STARTCOMPOSITION and call this function.
157 */
158 void WINAPI
159global_ime_set_position(POINT *pPoint)
160{
161 HIMC hImc = NULL;
162
163 if (pIApp == NULL || pPoint == NULL)
164 return;
165
166 if (SUCCEEDED(pIApp->GetContext(s_hWnd, &hImc)))
167 {
168 COMPOSITIONFORM CompForm;
169
170 CompForm.dwStyle = CFS_POINT;
171 CompForm.ptCurrentPos = *pPoint;
172 pIApp->SetCompositionWindow(hImc, &CompForm);
173 pIApp->ReleaseContext(s_hWnd, hImc);
174 }
175}
176
177/*
178 * Set font to Global IME
179 */
180/* GIME_TEST */
181 void WINAPI
182global_ime_set_font(LOGFONT *pFont)
183{
184 HIMC hImc = NULL;
185
186 if (pIApp == NULL || pFont == NULL)
187 return;
188
189 if (SUCCEEDED(pIApp->GetContext(s_hWnd, &hImc)))
190 {
191 pIApp->SetCompositionFontA(hImc, pFont);
192 pIApp->ReleaseContext(s_hWnd, hImc);
193 }
194}
195
Bram Moolenaar9c96f592005-06-30 21:52:39 +0000196#if 0
Bram Moolenaar071d4272004-06-13 20:20:40 +0000197/*
198 * for IME control. Save current status of IME, and set force new-status to
Bram Moolenaar9c96f592005-06-30 21:52:39 +0000199 * English (turn off).
Bram Moolenaar071d4272004-06-13 20:20:40 +0000200 */
201 void WINAPI
202global_ime_status_evacuate()
203{
204 HIMC hImc;
205
206 if (pIApp != NULL && SUCCEEDED(pIApp->GetContext(s_hWnd, &hImc)))
207 {
208 s_bStatus = (pIApp->GetOpenStatus(hImc) == 0) ? TRUE : FALSE;
209 pIApp->SetOpenStatus(hImc, FALSE);
210 pIApp->ReleaseContext(s_hWnd, hImc);
211 }
212}
213
214/*
215 * for IME control. Change IME status to last saved one.
216 */
217 void WINAPI
218global_ime_status_restore()
219{
220 HIMC hImc;
221
222 if (pIApp != NULL && SUCCEEDED(pIApp->GetContext(s_hWnd, &hImc)))
223 {
224 pIApp->SetOpenStatus(hImc, s_bStatus);
225 pIApp->ReleaseContext(s_hWnd, hImc);
226 }
227}
Bram Moolenaar9c96f592005-06-30 21:52:39 +0000228#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000229
230 void WINAPI
231global_ime_set_status(int status)
232{
233 HIMC hImc;
234
235 if (pIApp != NULL && SUCCEEDED(pIApp->GetContext(s_hWnd, &hImc)))
236 {
237 pIApp->SetOpenStatus(hImc, status ? TRUE : FALSE);
238 pIApp->ReleaseContext(s_hWnd, hImc);
239 }
240}
241
242 int WINAPI
243global_ime_get_status()
244{
245 int status = 0;
246 HIMC hImc;
247
248 if (pIApp != NULL && SUCCEEDED(pIApp->GetContext(s_hWnd, &hImc)))
249 {
250 status = pIApp->GetOpenStatus(hImc) ? 1 : 0;
251 pIApp->ReleaseContext(s_hWnd, hImc);
252 }
253 return status;
254}
255
256#endif /* GLOBAL_IME */