/* 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 language version of Global IME at same place. * * RUNTIME REQUIREMENTS: * - Internet Explorer 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 #include 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 finished. 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); } } #if 0 /* * for IME control. Save current status of IME, and set force new-status to * English (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); } } #endif 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 */