diff options
Diffstat (limited to 'src/glbl_ime.cpp')
-rw-r--r-- | src/glbl_ime.cpp | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/src/glbl_ime.cpp b/src/glbl_ime.cpp new file mode 100644 index 000000000..f42a218fc --- /dev/null +++ b/src/glbl_ime.cpp @@ -0,0 +1,261 @@ +/* vi:set ts=8 sts=4 sw=4: + * + * VIM - Vi IMproved by Bram Moolenaar + * + * Do ":help uganda" in Vim to read copying and usage conditions. + * Do ":help credits" in Vim to see a list of people who contributed. + */ + +/* + * DESCRIPTION: + * This module produces Global IME for Vim, on Windows with Internet + * Explorer 5.01 or higher. You need three files "dimm.idl", "dimm.h", and + * "dimm_i.c" when compile this module at your self. "dimm.h", and + * "dimm_i.c" are generated from "dimm.idl" by using MIDL.EXE as like + * "if_ole.h". You can get "dimm.idl" in MSDN web site. I got it below + * URL. + * + * WHAT IS THE GLOBAL IME?: + * Global IME makes capability input Chinese, Japanese, and Korean text into + * Vim buffer on any language version of Windows 98, Windows 95, and Windows + * NT 4.0. See below URL for detail of Global IME. You can also find + * various laguage version of Global IME at same place. + * + * RUNTIME REQUIREMENTS: + * - Internet Exproler 5.01 or higher. + * - Global IME (with language pack?). + * - Of course Vim for Windows. + * + * URLS: + * - Where you can probably get "dimm.idl". + * http://msdn.microsoft.com/downloads/samples/internet/libraries/ie5_lib/sample.asp + * - Global IME detailed information. + * http://www.microsoft.com/windows/ie/features/ime.asp + */ + +#ifdef GLOBAL_IME + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <objbase.h> +extern "C" { +#include "vim.h" +} +#include "dimm.h" +#include "glbl_ime.h" + +static IActiveIMMApp *pIApp = NULL; +static IActiveIMMMessagePumpOwner *pIMsg = NULL; +static HWND s_hWnd = NULL; +static BOOL s_bStatus = FALSE; /* for evacuate */ + +/* + * Initialize Global IME. + * "atom" must be return value of RegisterClass(Ex). + */ + void +global_ime_init(ATOM atom, HWND hWnd) +{ + IUnknown *pI; + HRESULT hr; + + if (pIApp != NULL || pIMsg != NULL) + return; + OleInitialize(NULL); + + /* + * Get interface IUnknown + */ + hr = CoCreateInstance(CLSID_CActiveIMM, NULL, CLSCTX_SERVER, + IID_IUnknown, (void**)&pI); + if (FAILED(hr) || !pI) + return; + + /* + * Get interface IActiveIMMApp + */ + hr = pI->QueryInterface(IID_IActiveIMMApp, (void**)&pIApp); + if (FAILED(hr)) + pIApp = NULL; + + /* + * Get interface IActiveIMMMessagePumpOwner + */ + hr = pI->QueryInterface(IID_IActiveIMMMessagePumpOwner, (void**)&pIMsg); + if (FAILED(hr)) + pIMsg = NULL; + + if (pIApp != NULL) + { + pIApp->Activate(TRUE); + pIApp->FilterClientWindows(&atom, 1); + } + if (pIMsg != NULL) + pIMsg->Start(); + + pI->Release(); + s_hWnd = hWnd; +} + +/* + * Reset and clear Global IME. + */ + void +global_ime_end() +{ + if (pIApp != NULL) + { + IActiveIMMApp *p = pIApp; + + pIApp = NULL; + p->FilterClientWindows(NULL, 0); + p->Deactivate(); + p->Release(); + } + if (pIMsg != NULL) + { + IActiveIMMMessagePumpOwner *p = pIMsg; + + pIMsg = NULL; + p->End(); + p->Release(); + } + OleUninitialize(); +} + +/* + * Replacement for DefWindowProc(). + */ + LRESULT WINAPI +global_ime_DefWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + LRESULT lResult; + + if (pIApp == NULL || pIApp->OnDefWindowProc(hWnd, Msg, + wParam, lParam, &lResult) != S_OK) + { +#if defined(WIN3264) && defined(FEAT_MBYTE) + if (wide_WindowProc) + lResult = DefWindowProcW(hwnd, Msg, wParam, lParam); + else +#endif + lResult = DefWindowProc(hWnd, Msg, wParam, lParam); + } + return lResult; +} + +/* + * Replace with TranslateMessage() + */ + BOOL WINAPI +global_ime_TranslateMessage(CONST MSG *lpMsg) +{ + if (pIMsg == NULL || pIMsg->OnTranslateMessage(lpMsg) == S_FALSE) + return TranslateMessage(lpMsg); + return TRUE; +} + +/* + * Set position of IME compotision window. + * + * You have to call this before starting composition. If once composition + * started, this can take no effect until that composition have finised. So + * you should handle WM_IME_STARTCOMPOSITION and call this function. + */ + void WINAPI +global_ime_set_position(POINT *pPoint) +{ + HIMC hImc = NULL; + + if (pIApp == NULL || pPoint == NULL) + return; + + if (SUCCEEDED(pIApp->GetContext(s_hWnd, &hImc))) + { + COMPOSITIONFORM CompForm; + + CompForm.dwStyle = CFS_POINT; + CompForm.ptCurrentPos = *pPoint; + pIApp->SetCompositionWindow(hImc, &CompForm); + pIApp->ReleaseContext(s_hWnd, hImc); + } +} + +/* + * Set font to Global IME + */ +/* GIME_TEST */ + void WINAPI +global_ime_set_font(LOGFONT *pFont) +{ + HIMC hImc = NULL; + + if (pIApp == NULL || pFont == NULL) + return; + + if (SUCCEEDED(pIApp->GetContext(s_hWnd, &hImc))) + { + pIApp->SetCompositionFontA(hImc, pFont); + pIApp->ReleaseContext(s_hWnd, hImc); + } +} + +/* + * for IME control. Save current status of IME, and set force new-status to + * Engllish (turn off). + */ + void WINAPI +global_ime_status_evacuate() +{ + HIMC hImc; + + if (pIApp != NULL && SUCCEEDED(pIApp->GetContext(s_hWnd, &hImc))) + { + s_bStatus = (pIApp->GetOpenStatus(hImc) == 0) ? TRUE : FALSE; + pIApp->SetOpenStatus(hImc, FALSE); + pIApp->ReleaseContext(s_hWnd, hImc); + } +} + +/* + * for IME control. Change IME status to last saved one. + */ + void WINAPI +global_ime_status_restore() +{ + HIMC hImc; + + if (pIApp != NULL && SUCCEEDED(pIApp->GetContext(s_hWnd, &hImc))) + { + pIApp->SetOpenStatus(hImc, s_bStatus); + pIApp->ReleaseContext(s_hWnd, hImc); + } +} + + void WINAPI +global_ime_set_status(int status) +{ + HIMC hImc; + + if (pIApp != NULL && SUCCEEDED(pIApp->GetContext(s_hWnd, &hImc))) + { + pIApp->SetOpenStatus(hImc, status ? TRUE : FALSE); + pIApp->ReleaseContext(s_hWnd, hImc); + } +} + + int WINAPI +global_ime_get_status() +{ + int status = 0; + HIMC hImc; + + if (pIApp != NULL && SUCCEEDED(pIApp->GetContext(s_hWnd, &hImc))) + { + status = pIApp->GetOpenStatus(hImc) ? 1 : 0; + pIApp->ReleaseContext(s_hWnd, hImc); + } + return status; +} + +#endif /* GLOBAL_IME */ |