Full Code of zcodes/IMESupport for AI

master d544494d5f20 cached
18 files
20.5 KB
7.1k tokens
31 symbols
1 requests
Download .txt
Repository: zcodes/IMESupport
Branch: master
Commit: d544494d5f20
Files: 18
Total size: 20.5 KB

Directory structure:
gitextract_0i6bqump/

├── .gitignore
├── .no-sublime-package
├── IMESupport.sublime-settings
├── README.md
├── README_en.org
├── README_jp.org
├── hook/
│   ├── imesupport_hook.c
│   ├── imesupport_hook.h
│   ├── make_mingw32.mak
│   ├── make_mingw64.mak
│   ├── make_msvc32.mak
│   ├── make_msvc32_win7.mak
│   ├── make_msvc64.mak
│   └── make_msvc64_win7.mak
├── imesupport/
│   ├── __init__.py
│   └── globalhook.py
├── imesupportplugin.py
└── packages.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
.ropeproject
font_name.txt
imesupport.log
hook/*.obj
hook/*.dll
hook/*.exp
hook/*.lib


================================================
FILE: .no-sublime-package
================================================


================================================
FILE: IMESupport.sublime-settings
================================================
{
    "imesupport_screen_scaling": 100
}


================================================
FILE: README.md
================================================
## Sublime Text Build 3186

从 BUILD 3186 开始,ST 官方支持 IME 了,此插件或许可以被标注 Deprecated 了。

## IMESupport

Sublime Text 中文输入法支持,解决输入法候选框无法跟随 st 光标 (cursor) 的问题。

## 须知

### 原理

由于 st 默认不支持 IME (Input Method Editor),导致在使用微软拼音、搜狗拼音等输入法输入中文的时候,候选框会固定在屏幕的一个角上,不会跟随光标的移动而移动。这个插件就是利用 st 的 api 接口和 Windows 的 hook (钩子) 机制,用 hackable (一种无奈且并不优雅) 的方式让 st 支持 IME (或者说 IMM/Input Method Manager)。

插件的主要操作分为两步:

1. 在光标位置改变时,通过 st 内置的事件监听接口触发获取光标位置操作(现在 st 内置 api 支持获取光标位置),然后将位置信息传递给加载的钩子处理。

2. hook 中的主要操作使用 Windows Api (ImmSetCompositionWindow) 设置输入法候选框的位置。

### Sublime Text 版本

由于旧版本的 st 没有获取光标相对于 st 窗口 (window) 的 api,最开始插件获取光标位置是通过获取当光标相对于 st 布局 (layout) 的位置,再配合侧边栏的宽度、手动配置调整参数等信息手动计算的,这样导致光标的位置极其不准确(换个主题可能侧边栏的宽度等就不同了),候选框跟随定位准确也就无从说起了。

从 BUILD 3143 起,st 有了可以获取光标(cursor)相对于窗口位置的 api(View.text_to_window()), 并鉴于以前手动计算问题太多、太不可靠,所有对代码做了精简,直接使用新的 api,而不再支持手动计算方式,所以,此插件支持 Sublime Text 3 Build 3143+(注意:跟 3143 比较临近的版本 api 实现并不是很好,如光标在搜索等输入框时位置也无法获取,so,尽量用最新版本吧)。

### Windows 系统版本和高清屏

鉴于 Windows 对于高清屏(缩放率大于 100%)的支持并不是很好,从 Windows 10 起这种状况才有所改观,并且某些针对缩放率等信息的 Windows api 从 Windows 10 起才开始支持,所以插件支持最好的 Windows 版本是 10。 如果 Windows 系统版本低于 Windows 10, 该插件也可以使用,唯一的区别就是无法自动获取显示的缩放率,如果使用缩放率大于 100,且小于 Windows 10 版本的 Windows,可以通过设置 ime_support_screen_scaling 手动配置一下。

缩放率 100% 的默认配置:
```json
{
  "imesupport_screen_scaling": 100
}
```

目前,这是该插件唯一需要手动设置的,以前的配置信息(offset 之类的)已经不再需要。

## 安装

注意:这是 [chikatoike/IMESupport](https://github.com/chikatoike/IMESupport) 的
fork 版本,所以不要使用 package_control 安装。

直接将该项目克隆或是下载到 Sublime_Text_3_Install_Path/Data/Packages 目录下就好,不知道该目录在哪的同学可以使用菜单 Perference > Browse Packages 打开。

## 已知问题

### 第一次输入定位不准

目前测试来看,这个问题主要原因还是插件未加载完成造成的,所以刚打开 st 的时候,稍等等,等插件加载完就好了。

## ChangeLog

### 2018-11-25
* 简化代码,放弃支持 Sublime Text 老版本 (Sublime Text 3.0+ 起)
* 兼容 Windows 7 +
* 兼容 搜狗拼音、QQ 拼音、手心输入法、小狼毫输入法

### 2017-07-31
* 新版本 (dev build 3142) 可以使用 View.text_to_view 获取光标的位置。
* 使用 Visual Studio 2017 Community 重新编译 dll 文件。


================================================
FILE: README_en.org
================================================
* IMESupport for Sublime Text 2/3

* Description
  In current version of Sublime Text 2/3, there is a problem that can not be displayed IME composition window correctly.
  This plugin solves this problem.

* Target platform
  This plugin works only on windows.

* Screenshot

  Before installed this plugin.
  Inptting using IME, but IME composition window is not displayed correct position.

  [[https://raw.github.com/chikatoike/IMESupport/master/img/inline1.png]]

  After installed this plugin, IME comosition window is displayed correctly.

  [[https://raw.github.com/chikatoike/IMESupport/master/img/inline2.png]]

* Reference
  http://sublimetext.userecho.com/topic/98697-handling-ime-message-on-windows-for-koreanjapanese-and-chinese-user/


================================================
FILE: README_jp.org
================================================
* IMESupport for Sublime Text
  English: https://github.com/chikatoike/IMESupport/blob/master/README_en.org

* 概要
  IMESupportは、Windows の Sublime Text で IME を利用した文字入力をサポートするパッケージです。
  IME でインライン変換の入力文字が正しい位置に表示されない問題をある程度解決できます。

* 動作環境
  Windows OS のみ対応しています。 以下のバージョンで動作します。
  - Sublime Text 2 32bit
  - Sublime Text 2 64bit
  - Sublime Text 3 32bit
  - Sublime Text 3 64bit

  以下の環境で動作確認しました。
  - Sublime Text 2 32bit + Windows Vista 32bit + Microsoft Office IME 2007
  - Sublime Text 2 32bit + Windows Vista 32bit + Google日本語入力
  - Sublime Text 2 32bit + Windows Vista 32bit + SKK日本語入力FEP
  - Sublime Text 2 32bit + Windows 7 32bit + Microsoft Office IME 2010
  - Sublime Text 2 32bit + Windows 7 32bit + Google日本語入力
  - Sublime Text 2 32bit + Windows 7 32bit + SKK日本語入力FEP
  - Sublime Text 2 64bit + Windows 8 64bit + Microsoft IME 2012
  - Sublime Text 3 32bit + Windows 8 64bit + Microsoft IME 2012
  - Sublime Text 3 64bit + Windows 8 64bit + Microsoft IME 2012
  ATOK等、上に書かれていないIMEでも動作するはずですが、確認していません。

* インストール方法
  Package Controlを使ってインストールしてください。
  Package Controlをインストールした状態で、以下の手順でインストールできます。

  1. コマンドパレットで「Package Control: Install Package」を絞り込んでEnter
  2. パッケージ一覧から「IMESupport」を絞り込んでEnter
  3. ステータスバーにインストール完了のメッセージが表示されたら Sublime Text 2 を再起動

  手動でインストールする場合:

  コマンドプロンプト等で C:\Users\(ユーザー名)\AppData\Roaming\Sublime Text 2\Packages に移動して、
  git clone してください。

* 機能
  以下の機能が利用できます。
  - インライン変換の表示位置補正

* インライン変換の表示位置補正について
  この機能はインストールするだけで有効になります。ユーザー側での設定は必要ありません。

  現行バージョンの Sublime Text 2 では、IMEをONにして日本語入力しようとすると、以下のようにカーソル位置とは別の場所に入力中のテキストが表示されます。

  [[https://raw.github.com/chikatoike/IMESupport/master/img/inline1.png]]

  これを、カーソル位置に表示されるように補正します。

  [[https://raw.github.com/chikatoike/IMESupport/master/img/inline2.png]]

** 既知の不具合
   - IME ON で連続で入力するときに、変換確定後の次の1文字が、前の入力開始位置と同じ場所に表示されてしまいます。 これは2文字以上入力すれば、正しい位置に移動します。
   - File→New View into File で現在開いているファイルを新しいViewに表示した場合、最初のView以外では正しく動作しない可能性があります。
   これは Sublime Text 自体の不具合が原因です。適当な対策を実装していますが、パッケージ側で完全に対策するのは困難です。もし正しく動作していない場合はご報告下さい。

** 制限事項
   - ファイル編集以外の入力は対応していません。例えば、検索文字列の入力、Goto Anything などです。これらに入力フォーカスがある場合、強制的に画面左上に表示します。
   - 垂直分割時に、左側に1つもタブ(View)が表示されていない場合、右側のViewでは正しい位置に表示されません。これは、Viewがないとウィンドウ左端からの距離が計算出来ないためです。同様に、水平分割時に上側にViewがない場合は下側で正しい位置に表示されません。

* 参考
  - http://d.hatena.ne.jp/chikatoike/20121030/1351552567
  - http://sublimetext.userecho.com/topic/98697-handling-ime-message-on-windows-for-koreanjapanese-and-chinese-user/

* CHANGELOG
  2013-02-26
  - File→New View into File で開いたビューでの不具合対策(ST2/ST3)

  2013-02-09
  - Sublime text 3 でside barが表示されているときに、IMEの表示位置がずれていた問題を修正 (shirosakiさん、ありがとうごさいます)

  2013-01-30
  - Sublime Text 3 に対応
  - ver.0.2 開発開始

  2013-01-29
  - ver.0.1 リリース

  2013-01-22
  - Package Controlを使ったインストール方法を追加

  2013-01-21
  - line_padding_top, line_padding_bottom が設定されているときのフォントの大きさを修正 (shspageさん、ありがとうごさいます)

  2012-11-19
  - x64版に対応
  - メニューからのプロジェクト選択でクラッシュする問題を修正

  2012-11-11
  - 対応するIMEについて追記

  2012-11-07
  - IME起動時のフォントの大きさを修正 (tkmusic1976さん、ありがとうございます)

  2012-10-30
  - 64bit版のWindowsのサポートについて記載

  2012-10-29
  - 分割の比率が 1:1 ではない場合の表示位置がおかしい問題を修正
  - 最初のリリース


================================================
FILE: hook/imesupport_hook.c
================================================
#define _CRT_SECURE_NO_WARNINGS

#include <windows.h>
#include <versionhelpers.h>
#include <stdio.h>
#include <tchar.h>
#include <strsafe.h>
#include "imesupport_hook.h"

static LRESULT CALLBACK MyHookProc(int nCode, WPARAM wp, LPARAM lp);
static LRESULT CALLBACK WindowMessageHookProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
static void Trace(const TCHAR *str, BOOL append);

static HINSTANCE hModule = NULL;
static HHOOK hHook = NULL;

BOOL WINAPI DllMain(HINSTANCE hModuleDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    hModule = hModuleDLL;

    switch (fdwReason) {
        case DLL_PROCESS_ATTACH:
            break;
        case DLL_PROCESS_DETACH:
            if (hHook != NULL) {
                EndHook();
            }
            break;
    }
    return TRUE;
}


EXPORT BOOL StartHook(HWND hwnd)
{
    if (hHook != NULL) {
        return FALSE;
    }

    DWORD tid = GetWindowThreadProcessId(hwnd, NULL);
    hHook = SetWindowsHookEx(WH_GETMESSAGE, MyHookProc, hModule, tid);

    return hHook != NULL;
}

EXPORT BOOL EndHook(void)
{
    if (hHook == NULL) {
        return FALSE;
    }
    BOOL ret = UnhookWindowsHookEx(hHook);
    hHook = NULL;
    return ret;
}

void SetFont(LOGFONT *lf)
{
    FILE *fp;
    TCHAR szFontInfoFile[_MAX_PATH];
    TCHAR szFull[_MAX_PATH];
    TCHAR szDrive[_MAX_PATH];
    TCHAR szDir[_MAX_DIR];
    TCHAR szFontName[128] = {0};

    GetModuleFileName(hModule, szFull, sizeof(szFull) / sizeof(TCHAR));
    _tsplitpath(szFull, szDrive, szDir, NULL, NULL);
    _tmakepath(szFontInfoFile, szDrive, szDir, _T("font_name"), _T("txt"));

    if ((fp = fopen(szFontInfoFile, _T("r"))) != NULL) {
        if (fread(szFontName, sizeof(TCHAR), 128, fp) > 0) {
            _sntprintf((LPSTR) lf->lfFaceName, LF_FACESIZE, _T("%s"), szFontName);
        }

        fclose(fp);
    }
}

EXPORT int GetMessageId(void)
{
    static UINT message = 0;

    if (message == 0) {
        message = RegisterWindowMessage(_T("WM_IMESUPPORT_SET_INLINE_POSITION"));
    }

    return message;
}

static LRESULT CALLBACK MyHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    if (nCode < 0) {
        return CallNextHookEx(hHook, nCode, wParam, lParam);
    }
    else if (nCode == HC_ACTION) {
        const MSG *p = (const MSG *)lParam;
        WindowMessageHookProc(p->hwnd, p->message, p->wParam, p->lParam);
    }

    return CallNextHookEx(hHook, nCode, wParam, lParam);
}

static void im_set_composition(HWND hWnd, int x, int y, LOGFONT *lf)
{
    HIMC hImc;

    if ((hImc = ImmGetContext(hWnd)) != (HIMC) 0) {
        if (ImmGetOpenStatus(hImc)) {
            ImmSetCompositionFont(hImc, lf);

            COMPOSITIONFORM cfs;
            cfs.dwStyle = CFS_POINT;
            cfs.ptCurrentPos.x = x;
            cfs.ptCurrentPos.y = y;

            // MapWindowPoints(HWND_DESKTOP, hWnd, &cfs.ptCurrentPos, 1);
            ImmSetCompositionWindow(hImc, &cfs);
        }

        ImmReleaseContext(hWnd, hImc);
    }
}

static LRESULT CALLBACK WindowMessageHookProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    static int x = INVALID_VALUE;
    static int y = INVALID_VALUE;
    static int font_size = INVALID_VALUE;
    static LOGFONT lf =
    {
        -12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET,
        OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
        PROOF_QUALITY, FIXED_PITCH | FF_DONTCARE,
        "Consolas"
    };
    static UINT uDpi = 96;
    static float scaling = 1.0;
    HIMC hImc;

    SetFont(&lf);
    switch (msg) {
        // about ime messages, see: https://docs.microsoft.com/en-us/windows/desktop/Intl/ime-messages
        // WM_IME_CONTROL: change the position of a composition window
        // WM_IME_COMPOSITION: notifies the application about changes to the composition string
        // WM_IME_NOTIFY: general changes to the status of the IME windows
        //
        // case WM_IME_CONTROL:
        case WM_IME_COMPOSITION:
        case WM_IME_NOTIFY:
            if (x == INVALID_VALUE || y == INVALID_VALUE) {
                break;
            }

            // sogou use WM_IME_COMPOSITION,and send WM_IME_NOTIFY +
            // IMN_SETCOMPOSITIONWINDOW, it will cause a dead loop
            if (msg == WM_IME_NOTIFY && wParam == IMN_SETCOMPOSITIONWINDOW) {
                break;
            }

            if ((hImc = ImmGetContext(hWnd)) != (HIMC) 0) {
                im_set_composition(hWnd, x, y, &lf);
                ImmReleaseContext(hWnd, hImc);
            }
            break;
        default:
            if (msg == GetMessageId()) {
                if (wParam != INVALID_VALUE && lParam != INVALID_VALUE) {
                    x = (wParam >> 16) & 0xffff;
                    y = wParam & 0xffff;

                    font_size = (lParam >> 16) & 0xffff;
                    scaling = (float) ((lParam & 0xffff) / 100.0);

                    HDC hdc;
                    hdc = GetDC(hWnd);
                    lf.lfHeight = - MulDiv(font_size, GetDeviceCaps(hdc, LOGPIXELSY), 72);
                    ReleaseDC(hWnd, hdc);

#if WINVER > 0x6010
                    // only windows 10 support these api
                    DPI_AWARENESS dpiAwareness = GetAwarenessFromDpiAwarenessContext(GetThreadDpiAwarenessContext());
                    switch (dpiAwareness) {
                        case DPI_AWARENESS_SYSTEM_AWARE:
                            uDpi = GetDpiForSystem();
                            break;
                        case DPI_AWARENESS_PER_MONITOR_AWARE:
                            uDpi = GetDpiForWindow(hWnd);
                            break;
                    }
                    scaling = (float) (uDpi / 96.0);
#endif
                    x = (int) (x * scaling);
                    y = (int) (y * scaling);

                    if ((hImc = ImmGetContext(hWnd)) != (HIMC) 0) {
                        im_set_composition(hWnd, x, y, &lf);
                        ImmReleaseContext(hWnd, hImc);
                    }
                }
                else {
                    x = INVALID_VALUE;
                    y = INVALID_VALUE;
                    font_size = INVALID_VALUE;
                }
            }
            break;
    }

    return 0;
}

static void Trace(const TCHAR *str, BOOL append)
{
    FILE *fp;
    TCHAR szLogFile[_MAX_PATH];
    TCHAR szFull[_MAX_PATH];
    TCHAR szDrive[_MAX_DRIVE];
    TCHAR szDir[_MAX_DIR];

    GetModuleFileName(hModule, szFull, sizeof(szFull) / sizeof(TCHAR));
    _tsplitpath(szFull, szDrive, szDir, NULL, NULL);
    _tmakepath(szLogFile, szDrive, szDir, _T("imesupport"), _T("log"));

    fp = _tfopen(szLogFile, append ? _T("a") : _T("w"));

    if (fp == NULL) {
        return;
    }

    _ftprintf(fp, _T("%s"), str);
    _ftprintf(fp, _T("\n"));
    fclose(fp);
}

// vim: st=4 sts=4 ts=4 et


================================================
FILE: hook/imesupport_hook.h
================================================
#ifndef _IMESUPPORT_HOOK_H_
#define _IMESUPPORT_HOOK_H_

#include <windows.h>


#ifdef _MSC_VER
#define EXPORT __declspec(dllexport)
#else
#define EXPORT
#endif

#define INVALID_VALUE 0xffffffff

#ifndef WINVER
#define WINVER 0x6010
#endif


EXPORT BOOL StartHook(HWND hwnd);
EXPORT BOOL EndHook(void);
EXPORT int GetMessageId(void);

#endif

// vim: st=4 sts=4 ts=4 et


================================================
FILE: hook/make_mingw32.mak
================================================
# for MinGW.

TARGET=../imesupport_hook_x86.dll
SRC=imesupport_hook.c
HEADER=imesupport_hook.h
CFLAGS=-O2 -Wall -shared -m32
LDFLAGS+=-limm32
OPT=

all: $(TARGET)

$(TARGET): $(SRC) $(HEADER)
	gcc $(CFLAGS) $(OPT) -o $(TARGET) $(SRC) $(LDFLAGS)

.PHONY: clean
clean:
	rm -f $(TARGET)


================================================
FILE: hook/make_mingw64.mak
================================================
# for MinGW.

TARGET=../imesupport_hook_x64.dll
SRC=imesupport_hook.c
HEADER=imesupport_hook.h
CFLAGS=-O2 -Wall -shared -m64
LDFLAGS+=-limm32
OPT=

all: $(TARGET)

$(TARGET): $(SRC) $(HEADER)
	gcc $(CFLAGS) $(OPT) -o $(TARGET) $(SRC) $(LDFLAGS)

.PHONY: clean
clean:
	rm -f $(TARGET)


================================================
FILE: hook/make_msvc32.mak
================================================
all: ..\imesupport_hook_x86.dll

..\imesupport_hook_x86.dll: imesupport_hook_x86.dll
	copy imesupport_hook_x86.dll ..\imesupport_hook_x86.dll

imesupport_hook_x86.dll: imesupport_hook.c
	cl /DWINVER=0xA000 /wd4996 /LD /Feimesupport_hook_x86.dll imesupport_hook.c imm32.lib user32.lib user32.lib gdi32.lib kernel32.lib ntdll.lib

clean:
	cmd /C "del ..\imesupport_hook_x86.dll imesupport_hook_x86.dll imesupport_hook_x86.exp imesupport_hook_x86.lib imesupport_hook.obj" /F /Q


================================================
FILE: hook/make_msvc32_win7.mak
================================================
all: ..\imesupport_hook_x86_win7.dll

..\imesupport_hook_x86_win7.dll: imesupport_hook_x86_win7.dll
	copy imesupport_hook_x86_win7.dll ..\imesupport_hook_x86_win7.dll

imesupport_hook_x86_win7.dll: imesupport_hook.c imesupport_hook.h
	cl /DWINVER=0xA000 /wd4996 /LD /Feimesupport_hook_x86_win7.dll imesupport_hook.c imm32.lib user32.lib user32.lib gdi32.lib kernel32.lib ntdll.lib

clean:
	cmd /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


================================================
FILE: hook/make_msvc64.mak
================================================
all: ..\imesupport_hook_x64.dll

..\imesupport_hook_x64.dll: imesupport_hook_x64.dll
	copy imesupport_hook_x64.dll ..\imesupport_hook_x64.dll

imesupport_hook_x64.dll: imesupport_hook.c imesupport_hook.h
	cl /DWINVER=0xA000 /wd4996 /LD /Feimesupport_hook_x64.dll imesupport_hook.c imm32.lib user32.lib gdi32.lib kernel32.lib ntdll.lib

clean:
	cmd /C "del ..\imesupport_hook_x64.dll imesupport_hook_x64.dll imesupport_hook_x64.exp imesupport_hook_x64.lib imesupport_hook.obj" /F /Q


================================================
FILE: hook/make_msvc64_win7.mak
================================================
all: ..\imesupport_hook_x64_win7.dll

..\imesupport_hook_x64_win7.dll: imesupport_hook_x64_win7.dll
	copy imesupport_hook_x64_win7.dll ..\imesupport_hook_x64_win7.dll

imesupport_hook_x64_win7.dll: imesupport_hook.c imesupport_hook.h
	cl /wd4996 /LD /Feimesupport_hook_x64_win7.dll imesupport_hook.c imm32.lib user32.lib gdi32.lib kernel32.lib ntdll.lib

clean:
	cmd /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


================================================
FILE: imesupport/__init__.py
================================================


================================================
FILE: imesupport/globalhook.py
================================================
# -*- coding: utf-8 -*-
import ctypes
from os.path import join, dirname, abspath
from os import popen

INVALID_VALUE = 0xffff

WM_IMESUPPORT_SET_INLINE_POSITION = -1
imesupport_dll = None


def setup(hwnd, arch_x64, dll_dir=dirname(dirname(abspath(__file__)))):
    # Default DLL location: ../imesupport_hook_xxx.dll
    global imesupport_dll
    global WM_IMESUPPORT_SET_INLINE_POSITION
    if imesupport_dll is not None:
        return True

    dll_name = 'imesupport_hook'
    if arch_x64:
        dll_name += '_x64'
    else:
        dll_name += '_x86'

    with popen('wmic os get caption') as ret:
        systeminfo = ret.read()
        if systeminfo.find('Windows 10') < 0:
            dll_name += '_win7'

    dll_name += '.dll'
    print(dll_name)
    imesupport_dll = ctypes.cdll.LoadLibrary(join(dll_dir, dll_name))
    WM_IMESUPPORT_SET_INLINE_POSITION = imesupport_dll.GetMessageId()
    return imesupport_dll.StartHook(hwnd)


def cleanup():
    global imesupport_dll

    imesupport_dll.EndHook()
    return ctypes.cdll.FreeLibrary(imesupport_dll)


def set_inline_position(hwnd, x, y, font_size, scaling):
    if imesupport_dll is not None:
        ctypes.windll.user32.PostMessageW(
            hwnd, WM_IMESUPPORT_SET_INLINE_POSITION, x << 16 | y,
            font_size << 16 | scaling)


def clear_inline_position(hwnd):
    if imesupport_dll is not None:
        ctypes.windll.user32.PostMessageW(hwnd,
                                          WM_IMESUPPORT_SET_INLINE_POSITION,
                                          INVALID_VALUE, INVALID_VALUE)


================================================
FILE: imesupportplugin.py
================================================
import os
import time
import sublime
import sublime_plugin

try:
    from imesupport import globalhook
except ImportError:
    from .imesupport import globalhook


class SlackCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        self.view.insert(edit, 0, "Hello, World!")


class WindowLayout(object):
    def __init__(self, window):
        self.window = window
        self.last_extents = None
        self.settings = sublime.load_settings('IMESupport.sublime-settings')

    def calc_cursor_position(self, view, cursor):
        if "text_to_window" in dir(view):
            pos = view.text_to_window(cursor)
            font_size = self.get_font_size(view)
            caret_width = view.settings().get('caret_extra_width')
            scaling = self.settings.get('imesupport_screen_scaling')
            return (int(pos[0]) + caret_width, int(pos[1]), font_size, scaling)

    @staticmethod
    def get_font_face(view):
        return view.settings().get('font_face', '')

    @staticmethod
    def get_font_size(view):
        return int(view.settings().get('font_size', ''))


def setup(hwnd):
    if int(sublime.version()) < 3000:
        pass
    else:

        # load dll
        globalhook.setup(hwnd, sublime.arch() == 'x64')


class ImeSupportEventListener(sublime_plugin.EventListener):
    def __init__(self):
        self.layouts = {}
        self.initialized = False

    def on_new(self, view):
        sublime.set_timeout(lambda: self.update(view), 400)

    def on_activated(self, view):
        sublime.set_timeout(lambda: self.update(view), 200)

    def on_deactivated(self, view):
        sublime.set_timeout(lambda: self.update(view), 200)

    def on_modified(self, view):
        sublime.set_timeout(lambda: self.update(view), 200)

    def on_selection_modified(self, view):
        sublime.set_timeout(lambda: self.update(view), 200)

    def on_post_window_command(self, window, command_name, args):
        sublime.set_timeout(lambda: self.update(window.active_view()), 400)

    def update(self, view):
        if view is None:
            return
        window = view.window()
        if window is None:
            return

        if not self.initialized:
            setup(window.hwnd())
            fontFile = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'font_name.txt')
            with open(fontFile, 'wb') as f:
                f.write(view.settings().get('font_face', '').encode('utf-8'))

            self.initialized = True

        id = window.id()
        if id not in self.layouts:
            self.layouts[id] = WindowLayout(window)

        pos = self.layouts[id].calc_cursor_position(view, view.sel()[0].b)
        globalhook.set_inline_position(window.hwnd(), *pos)


def plugin_unload():
    globalhook.cleanup()


================================================
FILE: packages.json
================================================
{
    "schema_version": "2.0",
    "packages": [
        {
            "name": "IMESupport",
            "details": "https://github.com/chikatoike/IMESupport",
            "releases": [
                {
                    "sublime_text": "*",
                    "platforms": "windows",
                    "details": "https://github.com/chikatoike/IMESupport"
                }
            ]
        }
    ]
}
Download .txt
gitextract_0i6bqump/

├── .gitignore
├── .no-sublime-package
├── IMESupport.sublime-settings
├── README.md
├── README_en.org
├── README_jp.org
├── hook/
│   ├── imesupport_hook.c
│   ├── imesupport_hook.h
│   ├── make_mingw32.mak
│   ├── make_mingw64.mak
│   ├── make_msvc32.mak
│   ├── make_msvc32_win7.mak
│   ├── make_msvc64.mak
│   └── make_msvc64_win7.mak
├── imesupport/
│   ├── __init__.py
│   └── globalhook.py
├── imesupportplugin.py
└── packages.json
Download .txt
SYMBOL INDEX (31 symbols across 3 files)

FILE: hook/imesupport_hook.c
  function BOOL (line 17) | BOOL WINAPI DllMain(HINSTANCE hModuleDLL, DWORD fdwReason, LPVOID lpvRes...
  function EXPORT (line 34) | EXPORT BOOL StartHook(HWND hwnd)
  function EXPORT (line 46) | EXPORT BOOL EndHook(void)
  function SetFont (line 56) | void SetFont(LOGFONT *lf)
  function EXPORT (line 78) | EXPORT int GetMessageId(void)
  function LRESULT (line 89) | static LRESULT CALLBACK MyHookProc(int nCode, WPARAM wParam, LPARAM lParam)
  function im_set_composition (line 102) | static void im_set_composition(HWND hWnd, int x, int y, LOGFONT *lf)
  function LRESULT (line 123) | static LRESULT CALLBACK WindowMessageHookProc(HWND hWnd, UINT msg, WPARA...
  function Trace (line 211) | static void Trace(const TCHAR *str, BOOL append)

FILE: imesupport/globalhook.py
  function setup (line 12) | def setup(hwnd, arch_x64, dll_dir=dirname(dirname(abspath(__file__)))):
  function cleanup (line 37) | def cleanup():
  function set_inline_position (line 44) | def set_inline_position(hwnd, x, y, font_size, scaling):
  function clear_inline_position (line 51) | def clear_inline_position(hwnd):

FILE: imesupportplugin.py
  class SlackCommand (line 12) | class SlackCommand(sublime_plugin.TextCommand):
    method run (line 13) | def run(self, edit):
  class WindowLayout (line 17) | class WindowLayout(object):
    method __init__ (line 18) | def __init__(self, window):
    method calc_cursor_position (line 23) | def calc_cursor_position(self, view, cursor):
    method get_font_face (line 32) | def get_font_face(view):
    method get_font_size (line 36) | def get_font_size(view):
  function setup (line 40) | def setup(hwnd):
  class ImeSupportEventListener (line 49) | class ImeSupportEventListener(sublime_plugin.EventListener):
    method __init__ (line 50) | def __init__(self):
    method on_new (line 54) | def on_new(self, view):
    method on_activated (line 57) | def on_activated(self, view):
    method on_deactivated (line 60) | def on_deactivated(self, view):
    method on_modified (line 63) | def on_modified(self, view):
    method on_selection_modified (line 66) | def on_selection_modified(self, view):
    method on_post_window_command (line 69) | def on_post_window_command(self, window, command_name, args):
    method update (line 72) | def update(self, view):
  function plugin_unload (line 95) | def plugin_unload():
Condensed preview — 18 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (27K chars).
[
  {
    "path": ".gitignore",
    "chars": 86,
    "preview": ".ropeproject\nfont_name.txt\nimesupport.log\nhook/*.obj\nhook/*.dll\nhook/*.exp\nhook/*.lib\n"
  },
  {
    "path": ".no-sublime-package",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "IMESupport.sublime-settings",
    "chars": 41,
    "preview": "{\n    \"imesupport_screen_scaling\": 100\n}\n"
  },
  {
    "path": "README.md",
    "chars": 1916,
    "preview": "## Sublime Text Build 3186\n\n从 BUILD 3186 开始,ST 官方支持 IME 了,此插件或许可以被标注 Deprecated 了。\n\n## IMESupport\n\nSublime Text 中文输入法支持,"
  },
  {
    "path": "README_en.org",
    "chars": 770,
    "preview": "* 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 ca"
  },
  {
    "path": "README_jp.org",
    "chars": 3227,
    "preview": "* IMESupport for Sublime Text\r\n  English: https://github.com/chikatoike/IMESupport/blob/master/README_en.org\r\n\r\n* 概要\r\n  "
  },
  {
    "path": "hook/imesupport_hook.c",
    "chars": 7045,
    "preview": "#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 <tcha"
  },
  {
    "path": "hook/imesupport_hook.h",
    "chars": 396,
    "preview": "#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 __"
  },
  {
    "path": "hook/make_mingw32.mak",
    "chars": 301,
    "preview": "# for MinGW.\r\n\r\nTARGET=../imesupport_hook_x86.dll\r\nSRC=imesupport_hook.c\r\nHEADER=imesupport_hook.h\r\nCFLAGS=-O2 -Wall -sh"
  },
  {
    "path": "hook/make_mingw64.mak",
    "chars": 301,
    "preview": "# for MinGW.\r\n\r\nTARGET=../imesupport_hook_x64.dll\r\nSRC=imesupport_hook.c\r\nHEADER=imesupport_hook.h\r\nCFLAGS=-O2 -Wall -sh"
  },
  {
    "path": "hook/make_msvc32.mak",
    "chars": 475,
    "preview": "all: ..\\imesupport_hook_x86.dll\n\n..\\imesupport_hook_x86.dll: imesupport_hook_x86.dll\n\tcopy imesupport_hook_x86.dll ..\\im"
  },
  {
    "path": "hook/make_msvc32_win7.mak",
    "chars": 558,
    "preview": "all: ..\\imesupport_hook_x86_win7.dll\r\n\r\n..\\imesupport_hook_x86_win7.dll: imesupport_hook_x86_win7.dll\r\n\tcopy imesupport_"
  },
  {
    "path": "hook/make_msvc64.mak",
    "chars": 492,
    "preview": "all: ..\\imesupport_hook_x64.dll\r\n\r\n..\\imesupport_hook_x64.dll: imesupport_hook_x64.dll\r\n\tcopy imesupport_hook_x64.dll .."
  },
  {
    "path": "hook/make_msvc64_win7.mak",
    "chars": 531,
    "preview": "all: ..\\imesupport_hook_x64_win7.dll\r\n\r\n..\\imesupport_hook_x64_win7.dll: imesupport_hook_x64_win7.dll\r\n\tcopy imesupport_"
  },
  {
    "path": "imesupport/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "imesupport/globalhook.py",
    "chars": 1574,
    "preview": "# -*- coding: utf-8 -*-\nimport ctypes\nfrom os.path import join, dirname, abspath\nfrom os import popen\n\nINVALID_VALUE = 0"
  },
  {
    "path": "imesupportplugin.py",
    "chars": 2888,
    "preview": "import os\r\nimport time\r\nimport sublime\r\nimport sublime_plugin\r\n\r\ntry:\r\n    from imesupport import globalhook\r\nexcept Imp"
  },
  {
    "path": "packages.json",
    "chars": 413,
    "preview": "{\n    \"schema_version\": \"2.0\",\n    \"packages\": [\n        {\n            \"name\": \"IMESupport\",\n            \"details\": \"htt"
  }
]

About this extraction

This page contains the full source code of the zcodes/IMESupport GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 18 files (20.5 KB), approximately 7.1k tokens, and a symbol index with 31 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!