[
  {
    "path": ".gitignore",
    "content": ".ropeproject\nfont_name.txt\nimesupport.log\nhook/*.obj\nhook/*.dll\nhook/*.exp\nhook/*.lib\n"
  },
  {
    "path": ".no-sublime-package",
    "content": ""
  },
  {
    "path": "IMESupport.sublime-settings",
    "content": "{\n    \"imesupport_screen_scaling\": 100\n}\n"
  },
  {
    "path": "README.md",
    "content": "## Sublime Text Build 3186\n\n从 BUILD 3186 开始，ST 官方支持 IME 了，此插件或许可以被标注 Deprecated 了。\n\n## IMESupport\n\nSublime Text 中文输入法支持，解决输入法候选框无法跟随 st 光标 (cursor) 的问题。\n\n## 须知\n\n### 原理\n\n由于 st 默认不支持 IME (Input Method Editor)，导致在使用微软拼音、搜狗拼音等输入法输入中文的时候，候选框会固定在屏幕的一个角上，不会跟随光标的移动而移动。这个插件就是利用 st 的 api 接口和 Windows 的 hook (钩子) 机制，用 hackable (一种无奈且并不优雅) 的方式让 st 支持 IME (或者说 IMM/Input Method Manager)。\n\n插件的主要操作分为两步:\n\n1. 在光标位置改变时，通过 st 内置的事件监听接口触发获取光标位置操作（现在 st 内置 api 支持获取光标位置），然后将位置信息传递给加载的钩子处理。\n\n2. hook 中的主要操作使用 Windows Api (ImmSetCompositionWindow) 设置输入法候选框的位置。\n\n### Sublime Text 版本\n\n由于旧版本的 st 没有获取光标相对于 st 窗口 (window) 的 api，最开始插件获取光标位置是通过获取当光标相对于 st 布局 (layout) 的位置，再配合侧边栏的宽度、手动配置调整参数等信息手动计算的，这样导致光标的位置极其不准确（换个主题可能侧边栏的宽度等就不同了），候选框跟随定位准确也就无从说起了。\n\n从 BUILD 3143 起，st 有了可以获取光标（cursor）相对于窗口位置的 api（View.text_to_window()), 并鉴于以前手动计算问题太多、太不可靠，所有对代码做了精简，直接使用新的 api，而不再支持手动计算方式，所以，此插件支持 Sublime Text 3 Build 3143+（注意：跟 3143 比较临近的版本 api 实现并不是很好，如光标在搜索等输入框时位置也无法获取，so，尽量用最新版本吧）。\n\n### Windows 系统版本和高清屏\n\n鉴于 Windows 对于高清屏（缩放率大于 100%）的支持并不是很好，从 Windows 10 起这种状况才有所改观，并且某些针对缩放率等信息的 Windows api 从 Windows 10 起才开始支持，所以插件支持最好的 Windows 版本是 10。 如果 Windows 系统版本低于 Windows 10， 该插件也可以使用，唯一的区别就是无法自动获取显示的缩放率，如果使用缩放率大于 100，且小于 Windows 10 版本的 Windows，可以通过设置 ime_support_screen_scaling 手动配置一下。\n\n缩放率 100% 的默认配置:\n```json\n{\n  \"imesupport_screen_scaling\": 100\n}\n```\n\n目前，这是该插件唯一需要手动设置的，以前的配置信息（offset 之类的）已经不再需要。\n\n## 安装\n\n注意：这是 [chikatoike/IMESupport](https://github.com/chikatoike/IMESupport) 的\nfork 版本，所以不要使用 package_control 安装。\n\n直接将该项目克隆或是下载到 Sublime_Text_3_Install_Path/Data/Packages 目录下就好，不知道该目录在哪的同学可以使用菜单 Perference > Browse Packages 打开。\n\n## 已知问题\n\n### 第一次输入定位不准\n\n目前测试来看，这个问题主要原因还是插件未加载完成造成的，所以刚打开 st 的时候，稍等等，等插件加载完就好了。\n\n## ChangeLog\n\n### 2018-11-25\n* 简化代码，放弃支持 Sublime Text 老版本 (Sublime Text 3.0+ 起)\n* 兼容 Windows 7 +\n* 兼容 搜狗拼音、QQ 拼音、手心输入法、小狼毫输入法\n\n### 2017-07-31\n* 新版本 (dev build 3142) 可以使用 View.text_to_view 获取光标的位置。\n* 使用 Visual Studio 2017 Community 重新编译 dll 文件。\n"
  },
  {
    "path": "README_en.org",
    "content": "* IMESupport for Sublime Text 2/3\r\n\r\n* Description\r\n  In current version of Sublime Text 2/3, there is a problem that can not be displayed IME composition window correctly.\r\n  This plugin solves this problem.\r\n\r\n* Target platform\r\n  This plugin works only on windows.\r\n\r\n* Screenshot\r\n\r\n  Before installed this plugin.\r\n  Inptting using IME, but IME composition window is not displayed correct position.\r\n\r\n  [[https://raw.github.com/chikatoike/IMESupport/master/img/inline1.png]]\r\n\r\n  After installed this plugin, IME comosition window is displayed correctly.\r\n\r\n  [[https://raw.github.com/chikatoike/IMESupport/master/img/inline2.png]]\r\n\r\n* Reference\r\n  http://sublimetext.userecho.com/topic/98697-handling-ime-message-on-windows-for-koreanjapanese-and-chinese-user/\r\n"
  },
  {
    "path": "README_jp.org",
    "content": "* IMESupport for Sublime Text\r\n  English: https://github.com/chikatoike/IMESupport/blob/master/README_en.org\r\n\r\n* 概要\r\n  IMESupportは、Windows の Sublime Text で IME を利用した文字入力をサポートするパッケージです。\r\n  IME でインライン変換の入力文字が正しい位置に表示されない問題をある程度解決できます。\r\n\r\n* 動作環境\r\n  Windows OS のみ対応しています。 以下のバージョンで動作します。\r\n  - Sublime Text 2 32bit\r\n  - Sublime Text 2 64bit\r\n  - Sublime Text 3 32bit\r\n  - Sublime Text 3 64bit\r\n\r\n  以下の環境で動作確認しました。\r\n  - Sublime Text 2 32bit + Windows Vista 32bit + Microsoft Office IME 2007\r\n  - Sublime Text 2 32bit + Windows Vista 32bit + Google日本語入力\r\n  - Sublime Text 2 32bit + Windows Vista 32bit + SKK日本語入力FEP\r\n  - Sublime Text 2 32bit + Windows 7 32bit + Microsoft Office IME 2010\r\n  - Sublime Text 2 32bit + Windows 7 32bit + Google日本語入力\r\n  - Sublime Text 2 32bit + Windows 7 32bit + SKK日本語入力FEP\r\n  - Sublime Text 2 64bit + Windows 8 64bit + Microsoft IME 2012\r\n  - Sublime Text 3 32bit + Windows 8 64bit + Microsoft IME 2012\r\n  - Sublime Text 3 64bit + Windows 8 64bit + Microsoft IME 2012\r\n  ATOK等、上に書かれていないIMEでも動作するはずですが、確認していません。\r\n\r\n* インストール方法\r\n  Package Controlを使ってインストールしてください。\r\n  Package Controlをインストールした状態で、以下の手順でインストールできます。\r\n\r\n  1. コマンドパレットで「Package Control: Install Package」を絞り込んでEnter\r\n  2. パッケージ一覧から「IMESupport」を絞り込んでEnter\r\n  3. ステータスバーにインストール完了のメッセージが表示されたら Sublime Text 2 を再起動\r\n\r\n  手動でインストールする場合:\r\n\r\n  コマンドプロンプト等で C:\\Users\\(ユーザー名)\\AppData\\Roaming\\Sublime Text 2\\Packages に移動して、\r\n  git clone してください。\r\n\r\n* 機能\r\n  以下の機能が利用できます。\r\n  - インライン変換の表示位置補正\r\n\r\n* インライン変換の表示位置補正について\r\n  この機能はインストールするだけで有効になります。ユーザー側での設定は必要ありません。\r\n\r\n  現行バージョンの Sublime Text 2 では、IMEをONにして日本語入力しようとすると、以下のようにカーソル位置とは別の場所に入力中のテキストが表示されます。\r\n\r\n  [[https://raw.github.com/chikatoike/IMESupport/master/img/inline1.png]]\r\n\r\n  これを、カーソル位置に表示されるように補正します。\r\n\r\n  [[https://raw.github.com/chikatoike/IMESupport/master/img/inline2.png]]\r\n\r\n** 既知の不具合\r\n   - IME ON で連続で入力するときに、変換確定後の次の1文字が、前の入力開始位置と同じ場所に表示されてしまいます。 これは2文字以上入力すれば、正しい位置に移動します。\r\n   - File→New View into File で現在開いているファイルを新しいViewに表示した場合、最初のView以外では正しく動作しない可能性があります。\r\n   これは Sublime Text 自体の不具合が原因です。適当な対策を実装していますが、パッケージ側で完全に対策するのは困難です。もし正しく動作していない場合はご報告下さい。\r\n\r\n** 制限事項\r\n   - ファイル編集以外の入力は対応していません。例えば、検索文字列の入力、Goto Anything などです。これらに入力フォーカスがある場合、強制的に画面左上に表示します。\r\n   - 垂直分割時に、左側に1つもタブ(View)が表示されていない場合、右側のViewでは正しい位置に表示されません。これは、Viewがないとウィンドウ左端からの距離が計算出来ないためです。同様に、水平分割時に上側にViewがない場合は下側で正しい位置に表示されません。\r\n\r\n* 参考\r\n  - http://d.hatena.ne.jp/chikatoike/20121030/1351552567\r\n  - http://sublimetext.userecho.com/topic/98697-handling-ime-message-on-windows-for-koreanjapanese-and-chinese-user/\r\n\r\n* CHANGELOG\r\n  2013-02-26\r\n  - File→New View into File で開いたビューでの不具合対策(ST2/ST3)\r\n\r\n  2013-02-09\r\n  - Sublime text 3 でside barが表示されているときに、IMEの表示位置がずれていた問題を修正 (shirosakiさん、ありがとうごさいます)\r\n\r\n  2013-01-30\r\n  - Sublime Text 3 に対応\r\n  - ver.0.2 開発開始\r\n\r\n  2013-01-29\r\n  - ver.0.1 リリース\r\n\r\n  2013-01-22\r\n  - Package Controlを使ったインストール方法を追加\r\n\r\n  2013-01-21\r\n  - line_padding_top, line_padding_bottom が設定されているときのフォントの大きさを修正 (shspageさん、ありがとうごさいます)\r\n\r\n  2012-11-19\r\n  - x64版に対応\r\n  - メニューからのプロジェクト選択でクラッシュする問題を修正\r\n\r\n  2012-11-11\r\n  - 対応するIMEについて追記\r\n\r\n  2012-11-07\r\n  - IME起動時のフォントの大きさを修正 (tkmusic1976さん、ありがとうございます)\r\n\r\n  2012-10-30\r\n  - 64bit版のWindowsのサポートについて記載\r\n\r\n  2012-10-29\r\n  - 分割の比率が 1:1 ではない場合の表示位置がおかしい問題を修正\r\n  - 最初のリリース\r\n"
  },
  {
    "path": "hook/imesupport_hook.c",
    "content": "#define _CRT_SECURE_NO_WARNINGS\r\n\r\n#include <windows.h>\r\n#include <versionhelpers.h>\r\n#include <stdio.h>\r\n#include <tchar.h>\r\n#include <strsafe.h>\r\n#include \"imesupport_hook.h\"\r\n\r\nstatic LRESULT CALLBACK MyHookProc(int nCode, WPARAM wp, LPARAM lp);\r\nstatic LRESULT CALLBACK WindowMessageHookProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);\r\nstatic void Trace(const TCHAR *str, BOOL append);\r\n\r\nstatic HINSTANCE hModule = NULL;\r\nstatic HHOOK hHook = NULL;\r\n\r\nBOOL WINAPI DllMain(HINSTANCE hModuleDLL, DWORD fdwReason, LPVOID lpvReserved)\r\n{\r\n    hModule = hModuleDLL;\r\n\r\n    switch (fdwReason) {\r\n        case DLL_PROCESS_ATTACH:\r\n            break;\r\n        case DLL_PROCESS_DETACH:\r\n            if (hHook != NULL) {\r\n                EndHook();\r\n            }\r\n            break;\r\n    }\r\n    return TRUE;\r\n}\r\n\r\n\r\nEXPORT BOOL StartHook(HWND hwnd)\r\n{\r\n    if (hHook != NULL) {\r\n        return FALSE;\r\n    }\r\n\r\n    DWORD tid = GetWindowThreadProcessId(hwnd, NULL);\r\n    hHook = SetWindowsHookEx(WH_GETMESSAGE, MyHookProc, hModule, tid);\r\n\r\n    return hHook != NULL;\r\n}\r\n\r\nEXPORT BOOL EndHook(void)\r\n{\r\n    if (hHook == NULL) {\r\n        return FALSE;\r\n    }\r\n    BOOL ret = UnhookWindowsHookEx(hHook);\r\n    hHook = NULL;\r\n    return ret;\r\n}\r\n\r\nvoid SetFont(LOGFONT *lf)\r\n{\r\n    FILE *fp;\r\n    TCHAR szFontInfoFile[_MAX_PATH];\r\n    TCHAR szFull[_MAX_PATH];\r\n    TCHAR szDrive[_MAX_PATH];\r\n    TCHAR szDir[_MAX_DIR];\r\n    TCHAR szFontName[128] = {0};\r\n\r\n    GetModuleFileName(hModule, szFull, sizeof(szFull) / sizeof(TCHAR));\r\n    _tsplitpath(szFull, szDrive, szDir, NULL, NULL);\r\n    _tmakepath(szFontInfoFile, szDrive, szDir, _T(\"font_name\"), _T(\"txt\"));\r\n\r\n    if ((fp = fopen(szFontInfoFile, _T(\"r\"))) != NULL) {\r\n        if (fread(szFontName, sizeof(TCHAR), 128, fp) > 0) {\r\n            _sntprintf((LPSTR) lf->lfFaceName, LF_FACESIZE, _T(\"%s\"), szFontName);\r\n        }\r\n\r\n        fclose(fp);\r\n    }\r\n}\r\n\r\nEXPORT int GetMessageId(void)\r\n{\r\n    static UINT message = 0;\r\n\r\n    if (message == 0) {\r\n        message = RegisterWindowMessage(_T(\"WM_IMESUPPORT_SET_INLINE_POSITION\"));\r\n    }\r\n\r\n    return message;\r\n}\r\n\r\nstatic LRESULT CALLBACK MyHookProc(int nCode, WPARAM wParam, LPARAM lParam)\r\n{\r\n    if (nCode < 0) {\r\n        return CallNextHookEx(hHook, nCode, wParam, lParam);\r\n    }\r\n    else if (nCode == HC_ACTION) {\r\n        const MSG *p = (const MSG *)lParam;\r\n        WindowMessageHookProc(p->hwnd, p->message, p->wParam, p->lParam);\r\n    }\r\n\r\n    return CallNextHookEx(hHook, nCode, wParam, lParam);\r\n}\r\n\r\nstatic void im_set_composition(HWND hWnd, int x, int y, LOGFONT *lf)\r\n{\r\n    HIMC hImc;\r\n\r\n    if ((hImc = ImmGetContext(hWnd)) != (HIMC) 0) {\r\n        if (ImmGetOpenStatus(hImc)) {\r\n            ImmSetCompositionFont(hImc, lf);\r\n\r\n            COMPOSITIONFORM cfs;\r\n            cfs.dwStyle = CFS_POINT;\r\n            cfs.ptCurrentPos.x = x;\r\n            cfs.ptCurrentPos.y = y;\r\n\r\n            // MapWindowPoints(HWND_DESKTOP, hWnd, &cfs.ptCurrentPos, 1);\r\n            ImmSetCompositionWindow(hImc, &cfs);\r\n        }\r\n\r\n        ImmReleaseContext(hWnd, hImc);\r\n    }\r\n}\r\n\r\nstatic LRESULT CALLBACK WindowMessageHookProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)\r\n{\r\n    static int x = INVALID_VALUE;\r\n    static int y = INVALID_VALUE;\r\n    static int font_size = INVALID_VALUE;\r\n    static LOGFONT lf =\r\n    {\r\n        -12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET,\r\n        OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,\r\n        PROOF_QUALITY, FIXED_PITCH | FF_DONTCARE,\r\n        \"Consolas\"\r\n    };\r\n    static UINT uDpi = 96;\r\n    static float scaling = 1.0;\r\n    HIMC hImc;\r\n\r\n    SetFont(&lf);\r\n    switch (msg) {\r\n        // about ime messages, see: https://docs.microsoft.com/en-us/windows/desktop/Intl/ime-messages\r\n        // WM_IME_CONTROL: change the position of a composition window\r\n        // WM_IME_COMPOSITION: notifies the application about changes to the composition string\r\n        // WM_IME_NOTIFY: general changes to the status of the IME windows\r\n        //\r\n        // case WM_IME_CONTROL:\r\n        case WM_IME_COMPOSITION:\r\n        case WM_IME_NOTIFY:\r\n            if (x == INVALID_VALUE || y == INVALID_VALUE) {\r\n                break;\r\n            }\r\n\r\n            // sogou use WM_IME_COMPOSITION，and send WM_IME_NOTIFY +\r\n            // IMN_SETCOMPOSITIONWINDOW, it will cause a dead loop\r\n            if (msg == WM_IME_NOTIFY && wParam == IMN_SETCOMPOSITIONWINDOW) {\r\n                break;\r\n            }\r\n\r\n            if ((hImc = ImmGetContext(hWnd)) != (HIMC) 0) {\r\n                im_set_composition(hWnd, x, y, &lf);\r\n                ImmReleaseContext(hWnd, hImc);\r\n            }\r\n            break;\r\n        default:\r\n            if (msg == GetMessageId()) {\r\n                if (wParam != INVALID_VALUE && lParam != INVALID_VALUE) {\r\n                    x = (wParam >> 16) & 0xffff;\r\n                    y = wParam & 0xffff;\r\n\r\n                    font_size = (lParam >> 16) & 0xffff;\r\n                    scaling = (float) ((lParam & 0xffff) / 100.0);\r\n\r\n                    HDC hdc;\r\n                    hdc = GetDC(hWnd);\r\n                    lf.lfHeight = - MulDiv(font_size, GetDeviceCaps(hdc, LOGPIXELSY), 72);\r\n                    ReleaseDC(hWnd, hdc);\r\n\r\n#if WINVER > 0x6010\r\n                    // only windows 10 support these api\r\n                    DPI_AWARENESS dpiAwareness = GetAwarenessFromDpiAwarenessContext(GetThreadDpiAwarenessContext());\r\n                    switch (dpiAwareness) {\r\n                        case DPI_AWARENESS_SYSTEM_AWARE:\r\n                            uDpi = GetDpiForSystem();\r\n                            break;\r\n                        case DPI_AWARENESS_PER_MONITOR_AWARE:\r\n                            uDpi = GetDpiForWindow(hWnd);\r\n                            break;\r\n                    }\r\n                    scaling = (float) (uDpi / 96.0);\r\n#endif\r\n                    x = (int) (x * scaling);\r\n                    y = (int) (y * scaling);\r\n\r\n                    if ((hImc = ImmGetContext(hWnd)) != (HIMC) 0) {\r\n                        im_set_composition(hWnd, x, y, &lf);\r\n                        ImmReleaseContext(hWnd, hImc);\r\n                    }\r\n                }\r\n                else {\r\n                    x = INVALID_VALUE;\r\n                    y = INVALID_VALUE;\r\n                    font_size = INVALID_VALUE;\r\n                }\r\n            }\r\n            break;\r\n    }\r\n\r\n    return 0;\r\n}\r\n\r\nstatic void Trace(const TCHAR *str, BOOL append)\r\n{\r\n    FILE *fp;\r\n    TCHAR szLogFile[_MAX_PATH];\r\n    TCHAR szFull[_MAX_PATH];\r\n    TCHAR szDrive[_MAX_DRIVE];\r\n    TCHAR szDir[_MAX_DIR];\r\n\r\n    GetModuleFileName(hModule, szFull, sizeof(szFull) / sizeof(TCHAR));\r\n    _tsplitpath(szFull, szDrive, szDir, NULL, NULL);\r\n    _tmakepath(szLogFile, szDrive, szDir, _T(\"imesupport\"), _T(\"log\"));\r\n\r\n    fp = _tfopen(szLogFile, append ? _T(\"a\") : _T(\"w\"));\r\n\r\n    if (fp == NULL) {\r\n        return;\r\n    }\r\n\r\n    _ftprintf(fp, _T(\"%s\"), str);\r\n    _ftprintf(fp, _T(\"\\n\"));\r\n    fclose(fp);\r\n}\r\n\r\n// vim: st=4 sts=4 ts=4 et\r\n"
  },
  {
    "path": "hook/imesupport_hook.h",
    "content": "#ifndef _IMESUPPORT_HOOK_H_\r\n#define _IMESUPPORT_HOOK_H_\r\n\r\n#include <windows.h>\r\n\r\n\r\n#ifdef _MSC_VER\r\n#define EXPORT __declspec(dllexport)\r\n#else\r\n#define EXPORT\r\n#endif\r\n\r\n#define INVALID_VALUE 0xffffffff\r\n\r\n#ifndef WINVER\r\n#define WINVER 0x6010\r\n#endif\r\n\r\n\r\nEXPORT BOOL StartHook(HWND hwnd);\r\nEXPORT BOOL EndHook(void);\r\nEXPORT int GetMessageId(void);\r\n\r\n#endif\r\n\r\n// vim: st=4 sts=4 ts=4 et\r\n"
  },
  {
    "path": "hook/make_mingw32.mak",
    "content": "# for MinGW.\r\n\r\nTARGET=../imesupport_hook_x86.dll\r\nSRC=imesupport_hook.c\r\nHEADER=imesupport_hook.h\r\nCFLAGS=-O2 -Wall -shared -m32\r\nLDFLAGS+=-limm32\r\nOPT=\r\n\r\nall: $(TARGET)\r\n\r\n$(TARGET): $(SRC) $(HEADER)\r\n\tgcc $(CFLAGS) $(OPT) -o $(TARGET) $(SRC) $(LDFLAGS)\r\n\r\n.PHONY: clean\r\nclean:\r\n\trm -f $(TARGET)\r\n"
  },
  {
    "path": "hook/make_mingw64.mak",
    "content": "# for MinGW.\r\n\r\nTARGET=../imesupport_hook_x64.dll\r\nSRC=imesupport_hook.c\r\nHEADER=imesupport_hook.h\r\nCFLAGS=-O2 -Wall -shared -m64\r\nLDFLAGS+=-limm32\r\nOPT=\r\n\r\nall: $(TARGET)\r\n\r\n$(TARGET): $(SRC) $(HEADER)\r\n\tgcc $(CFLAGS) $(OPT) -o $(TARGET) $(SRC) $(LDFLAGS)\r\n\r\n.PHONY: clean\r\nclean:\r\n\trm -f $(TARGET)\r\n"
  },
  {
    "path": "hook/make_msvc32.mak",
    "content": "all: ..\\imesupport_hook_x86.dll\n\n..\\imesupport_hook_x86.dll: imesupport_hook_x86.dll\n\tcopy imesupport_hook_x86.dll ..\\imesupport_hook_x86.dll\n\nimesupport_hook_x86.dll: imesupport_hook.c\n\tcl /DWINVER=0xA000 /wd4996 /LD /Feimesupport_hook_x86.dll imesupport_hook.c imm32.lib user32.lib user32.lib gdi32.lib kernel32.lib ntdll.lib\n\nclean:\n\tcmd /C \"del ..\\imesupport_hook_x86.dll imesupport_hook_x86.dll imesupport_hook_x86.exp imesupport_hook_x86.lib imesupport_hook.obj\" /F /Q\n"
  },
  {
    "path": "hook/make_msvc32_win7.mak",
    "content": "all: ..\\imesupport_hook_x86_win7.dll\r\n\r\n..\\imesupport_hook_x86_win7.dll: imesupport_hook_x86_win7.dll\r\n\tcopy imesupport_hook_x86_win7.dll ..\\imesupport_hook_x86_win7.dll\r\n\r\nimesupport_hook_x86_win7.dll: imesupport_hook.c imesupport_hook.h\r\n\tcl /DWINVER=0xA000 /wd4996 /LD /Feimesupport_hook_x86_win7.dll imesupport_hook.c imm32.lib user32.lib user32.lib gdi32.lib kernel32.lib ntdll.lib\r\n\r\nclean:\r\n\tcmd /C \"del ..\\imesupport_hook_x86_win7.dll imesupport_hook_x86_win7.dll imesupport_hook_x86_win7.exp imesupport_hook_x86_win7.lib imesupport_hook.obj\" /F /Q\r\n"
  },
  {
    "path": "hook/make_msvc64.mak",
    "content": "all: ..\\imesupport_hook_x64.dll\r\n\r\n..\\imesupport_hook_x64.dll: imesupport_hook_x64.dll\r\n\tcopy imesupport_hook_x64.dll ..\\imesupport_hook_x64.dll\r\n\r\nimesupport_hook_x64.dll: imesupport_hook.c imesupport_hook.h\r\n\tcl /DWINVER=0xA000 /wd4996 /LD /Feimesupport_hook_x64.dll imesupport_hook.c imm32.lib user32.lib gdi32.lib kernel32.lib ntdll.lib\r\n\r\nclean:\r\n\tcmd /C \"del ..\\imesupport_hook_x64.dll imesupport_hook_x64.dll imesupport_hook_x64.exp imesupport_hook_x64.lib imesupport_hook.obj\" /F /Q\r\n"
  },
  {
    "path": "hook/make_msvc64_win7.mak",
    "content": "all: ..\\imesupport_hook_x64_win7.dll\r\n\r\n..\\imesupport_hook_x64_win7.dll: imesupport_hook_x64_win7.dll\r\n\tcopy imesupport_hook_x64_win7.dll ..\\imesupport_hook_x64_win7.dll\r\n\r\nimesupport_hook_x64_win7.dll: imesupport_hook.c imesupport_hook.h\r\n\tcl /wd4996 /LD /Feimesupport_hook_x64_win7.dll imesupport_hook.c imm32.lib user32.lib gdi32.lib kernel32.lib ntdll.lib\r\n\r\nclean:\r\n\tcmd /C \"del ..\\imesupport_hook_x64_win7.dll imesupport_hook_x64_win7.dll imesupport_hook_x64_win7.exp imesupport_hook_x64_win7.lib imesupport_hook.obj\" /F /Q\r\n"
  },
  {
    "path": "imesupport/__init__.py",
    "content": ""
  },
  {
    "path": "imesupport/globalhook.py",
    "content": "# -*- coding: utf-8 -*-\nimport ctypes\nfrom os.path import join, dirname, abspath\nfrom os import popen\n\nINVALID_VALUE = 0xffff\n\nWM_IMESUPPORT_SET_INLINE_POSITION = -1\nimesupport_dll = None\n\n\ndef setup(hwnd, arch_x64, dll_dir=dirname(dirname(abspath(__file__)))):\n    # Default DLL location: ../imesupport_hook_xxx.dll\n    global imesupport_dll\n    global WM_IMESUPPORT_SET_INLINE_POSITION\n    if imesupport_dll is not None:\n        return True\n\n    dll_name = 'imesupport_hook'\n    if arch_x64:\n        dll_name += '_x64'\n    else:\n        dll_name += '_x86'\n\n    with popen('wmic os get caption') as ret:\n        systeminfo = ret.read()\n        if systeminfo.find('Windows 10') < 0:\n            dll_name += '_win7'\n\n    dll_name += '.dll'\n    print(dll_name)\n    imesupport_dll = ctypes.cdll.LoadLibrary(join(dll_dir, dll_name))\n    WM_IMESUPPORT_SET_INLINE_POSITION = imesupport_dll.GetMessageId()\n    return imesupport_dll.StartHook(hwnd)\n\n\ndef cleanup():\n    global imesupport_dll\n\n    imesupport_dll.EndHook()\n    return ctypes.cdll.FreeLibrary(imesupport_dll)\n\n\ndef set_inline_position(hwnd, x, y, font_size, scaling):\n    if imesupport_dll is not None:\n        ctypes.windll.user32.PostMessageW(\n            hwnd, WM_IMESUPPORT_SET_INLINE_POSITION, x << 16 | y,\n            font_size << 16 | scaling)\n\n\ndef clear_inline_position(hwnd):\n    if imesupport_dll is not None:\n        ctypes.windll.user32.PostMessageW(hwnd,\n                                          WM_IMESUPPORT_SET_INLINE_POSITION,\n                                          INVALID_VALUE, INVALID_VALUE)\n"
  },
  {
    "path": "imesupportplugin.py",
    "content": "import os\r\nimport time\r\nimport sublime\r\nimport sublime_plugin\r\n\r\ntry:\r\n    from imesupport import globalhook\r\nexcept ImportError:\r\n    from .imesupport import globalhook\r\n\r\n\r\nclass SlackCommand(sublime_plugin.TextCommand):\r\n    def run(self, edit):\r\n        self.view.insert(edit, 0, \"Hello, World!\")\r\n\r\n\r\nclass WindowLayout(object):\r\n    def __init__(self, window):\r\n        self.window = window\r\n        self.last_extents = None\r\n        self.settings = sublime.load_settings('IMESupport.sublime-settings')\r\n\r\n    def calc_cursor_position(self, view, cursor):\r\n        if \"text_to_window\" in dir(view):\r\n            pos = view.text_to_window(cursor)\r\n            font_size = self.get_font_size(view)\r\n            caret_width = view.settings().get('caret_extra_width')\r\n            scaling = self.settings.get('imesupport_screen_scaling')\r\n            return (int(pos[0]) + caret_width, int(pos[1]), font_size, scaling)\r\n\r\n    @staticmethod\r\n    def get_font_face(view):\r\n        return view.settings().get('font_face', '')\r\n\r\n    @staticmethod\r\n    def get_font_size(view):\r\n        return int(view.settings().get('font_size', ''))\r\n\r\n\r\ndef setup(hwnd):\r\n    if int(sublime.version()) < 3000:\r\n        pass\r\n    else:\r\n\r\n        # load dll\r\n        globalhook.setup(hwnd, sublime.arch() == 'x64')\r\n\r\n\r\nclass ImeSupportEventListener(sublime_plugin.EventListener):\r\n    def __init__(self):\r\n        self.layouts = {}\r\n        self.initialized = False\r\n\r\n    def on_new(self, view):\r\n        sublime.set_timeout(lambda: self.update(view), 400)\r\n\r\n    def on_activated(self, view):\r\n        sublime.set_timeout(lambda: self.update(view), 200)\r\n\r\n    def on_deactivated(self, view):\r\n        sublime.set_timeout(lambda: self.update(view), 200)\r\n\r\n    def on_modified(self, view):\r\n        sublime.set_timeout(lambda: self.update(view), 200)\r\n\r\n    def on_selection_modified(self, view):\r\n        sublime.set_timeout(lambda: self.update(view), 200)\r\n\r\n    def on_post_window_command(self, window, command_name, args):\r\n        sublime.set_timeout(lambda: self.update(window.active_view()), 400)\r\n\r\n    def update(self, view):\r\n        if view is None:\r\n            return\r\n        window = view.window()\r\n        if window is None:\r\n            return\r\n\r\n        if not self.initialized:\r\n            setup(window.hwnd())\r\n            fontFile = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'font_name.txt')\r\n            with open(fontFile, 'wb') as f:\r\n                f.write(view.settings().get('font_face', '').encode('utf-8'))\r\n\r\n            self.initialized = True\r\n\r\n        id = window.id()\r\n        if id not in self.layouts:\r\n            self.layouts[id] = WindowLayout(window)\r\n\r\n        pos = self.layouts[id].calc_cursor_position(view, view.sel()[0].b)\r\n        globalhook.set_inline_position(window.hwnd(), *pos)\r\n\r\n\r\ndef plugin_unload():\r\n    globalhook.cleanup()\r\n"
  },
  {
    "path": "packages.json",
    "content": "{\n    \"schema_version\": \"2.0\",\n    \"packages\": [\n        {\n            \"name\": \"IMESupport\",\n            \"details\": \"https://github.com/chikatoike/IMESupport\",\n            \"releases\": [\n                {\n                    \"sublime_text\": \"*\",\n                    \"platforms\": \"windows\",\n                    \"details\": \"https://github.com/chikatoike/IMESupport\"\n                }\n            ]\n        }\n    ]\n}\n"
  }
]