├── .dir-locals.el
├── .gitignore
├── COPYING
├── Makefile.am
├── NEWS.md
├── README.en.md
├── README.md
├── autogen.sh
├── configure.ac
├── lisp
├── Makefile.am
├── tr-ime-debug.el
├── tr-ime-documentfeed.el
├── tr-ime-download.el
├── tr-ime-font.el
├── tr-ime-hook.el
├── tr-ime-isearch.el
├── tr-ime-openstatus.el
├── tr-ime-prefix-key.el
├── tr-ime-reconversion.el
├── tr-ime-recv-notify.el
├── tr-ime-subclassify.el
├── tr-ime-sync.el
├── tr-ime-thread-message.el
├── tr-ime-workaround-inconsistent.el
├── tr-ime-workaround-isearch.el
├── tr-ime-workaround-prefix-key.el
└── tr-ime.el
├── m4
├── .gitignore
└── ax_cxx_compile_stdcxx.m4
└── src
├── Makefile.am
├── debug-message.cc
├── debug-message.hh
├── emacs-27.1
└── emacs-module.h
├── get_msg_hook.cc
├── get_msg_hook.hh
├── get_msg_proc.cc
├── get_msg_proc.hh
├── lisp-in-cc.cc
├── lisp-in-cc.hh
├── message.cc
├── message.hh
├── queue.cc
├── queue.hh
├── subclass_proc.cc
├── subclass_proc.hh
├── tr-ime-mod-resource.rc
├── tr-ime-mod.c
├── tr-ime-modadv-resource.rc
└── tr-ime-modadv.cc
/.dir-locals.el:
--------------------------------------------------------------------------------
1 | ;;; Directory Local Variables
2 | ;;; See Info node `(emacs) Directory Variables' for more information.
3 |
4 | ((c-mode
5 | (c-file-style . "gnu")
6 | (indent-tabs-mode . nil))
7 | (c++-mode
8 | (c-file-style . "gnu")
9 | (indent-tabs-mode . nil))
10 | (emacs-lisp-mode
11 | (indent-tabs-mode . nil))
12 | (autoconf-mode
13 | (indent-tabs-mode . nil))
14 | (shell-script-mode
15 | (indent-tabs-mode . nil))
16 | (markdown-mode
17 | (indent-tabs-mode . nil)))
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .*~
2 | *~
3 | autom4te.cache/
4 | aclocal.m4
5 | ar-lib
6 | build
7 | config.h.in
8 | compile
9 | config.guess
10 | config.sub
11 | configure
12 | depcomp
13 | install-sh
14 | ltmain.sh
15 | Makefile.in
16 | missing
17 |
--------------------------------------------------------------------------------
/Makefile.am:
--------------------------------------------------------------------------------
1 | SUBDIRS = lisp src
2 | dist_doc_DATA = README.md README.en.md COPYING NEWS.md
3 | EXTRA_DIST = autogen.sh
4 |
5 | ACLOCAL_AMFLAGS = -I m4
6 |
--------------------------------------------------------------------------------
/NEWS.md:
--------------------------------------------------------------------------------
1 | * Release 0.5.0 (2022-06-04):
2 | * Add dispatch thread WM_TIMER messages
3 | * WM_TIMER スレッドメッセージ(hwnd が NULL のメッセージ)
4 | をディスパッチして WM_NULL にすり替えて握りつぶす機構を追加しました
5 | * Emacs 27, 28 のメッセージポンプ(メッセージループ)は
6 | スレッドメッセージをディスパッチしないため IME の動作が
7 | おかしくなることがあります
8 | * tr-ime 0.4.x までは、メッセージフックで
9 | すべてのスレッドメッセージをディスパッチする機構を用意して
10 | おかしくならないようにしていました
11 | * しかし、将来の Emacs でメッセージポンプが修正され、
12 | スレッドメッセージをディスパッチするようになったら
13 | 二重にディスパッチすることになり
14 | Emacs の動作がおかしくなる危険性がありました
15 | * そこで、スレッドメッセージでも WM_TIMER のみをディスパッチし、
16 | さらにそれを WM_NULL にすり替えて握りつぶすことで将来の Emacs
17 | での二重ディスパッチを防ぐ方法を新設しました
18 | * デフォルト設定も新方式が有効になるよう変更しています
19 | * Advanced 用モジュール DLL 機能の追加に伴い ABI バージョンを 1 から
20 | 2 へ変更し、ファイル名が変わっています
21 | * 新しいモジュール DLL が必要になります
22 | * Standard 用モジュール DLL は従来のものがそのまま使えますが、
23 | バイナリリリースは再ビルドしたものを入れてあります
24 |
25 | * Release 0.4.1 (2020-11-28):
26 | * Included into MELPA
27 | * MELPA に掲載されました
28 | * MELPA 掲載に伴い、インストール方法や、
29 | 関連する関数名、変数名、設定方法などを整理して変更しました
30 | * 必要なモジュール DLL が load-path 上で見つからない場合、
31 | 自動ダウンロードする機能を追加しました
32 | * コンソールで byte-compile 時にロードされてエラーになる
33 | ことに対する対策を追加しました
34 | * unload-feature されるとき正常にアンロードできるよう対策を追加しました
35 | * 未確定文字列フォント設定で、
36 | コマンド実行後に反映する場合の動作を修正しました
37 | * Emacs 28 で standard で使用する際の IME 状態変更関数について、
38 | スレッドの切り替えを考慮する処理を追加しました
39 | * Emacs 28 で standard で使用する際の IME 状態変更関数の
40 | 状態確認回数上限のデフォルトを 3 から 10 に増やしました
41 | * モジュール DLL は Release 0.4.0 と同じで変更ありません
42 | * バイナリリリースの DLL ファイルは 0.4.0 と同じです
43 | * ソースからビルドすると 0.4.1 の DLL ができますが、
44 | 機能は 0.4.0 とまったく同じです
45 |
46 | * Release 0.4.0 (2020-10-31):
47 | * Changed package name, file names, function names, varible names,
48 | setting methods, etc.
49 | * パッケージ名、ファイル名、関数名、変数名、
50 | 設定方法などを整理して変更しました
51 |
52 | * Release 0.3.0 (2020-09-25):
53 | * Improve Module2
54 | * 再変換 (RECONVERSION) および
55 | 前後の確定済文字列を参照した変換 (DOCUMENTFEED)に対応しました
56 | * 今のところデフォルト無効にしていますので、
57 | 使用したい場合は設定してください
58 | * デバッグ出力レベルを変更できるようにしました
59 | * Module1, 2 双方で、emacsclient でのバッファが変更が検知できず、
60 | IME/IM 同期できなくなることがありましたので対応する設定を追加しました
61 | * Module1 で IME 状態食い違い検出ワークアラウンドを使っていると
62 | 気が付きにくいものですが、Module2 だと簡単に再現しました
63 | * Module2 のプレフィックスキー検出、Module1 のプレフィックスキー検出
64 | ワークアラウンド双方で IME 状態復帰を post-command-hook から
65 | pre-command-hook に変更しました
66 | * emacsclient でファイルを開いて編集してから、IME ON のまま
67 | C-x C-s C-x # のような操作を素早く実行すると、
68 | C-x C-s の保存動作完了前に次の C-x を押してしまうことがあり、
69 | そうすると保存動作の完了後の post-command-hook で
70 | IME ON に復帰していると # が IME に吸われて未確定文字に
71 | なってしまうことがありました
72 |
73 | * Release 0.2.0 (2020-09-20):
74 | * Improve Module2
75 | * Module2 で UI スレッドから Lisp への通知をできるようにし、
76 | これによりこれまで実現できなかった機能を実装しました
77 | * 通知機能により実現した Module2 の新機能は以下の通りです
78 | * すべての IME ON/OFF 方法に対応
79 | (IME 状態変更通知による IME/IM 状態同期)
80 | * その他に Module2 で実装した新機能は以下の通りです
81 | * 未確定文字列フォント設定でファミリとサイズ以外の属性にも対応
82 | * isearch-mode 中の未確定文字列表示がチラつくのを改善
83 | * IME 状態取得・設定方法を Microsoft のドキュメントに
84 | 記載されている方法で実施するよう変更
85 |
86 | * Release 0.1.0 (2020-09-17):
87 | * Add Module2
88 | * メッセージフックやサブクラス化といった多少複雑な機構で、
89 | より高度な機能を実装した実験的な Module2 を追加しました。
90 | これまでの最低限の単純で基本的な機能のみを実装したモジュールを
91 | Module1 と呼ぶことにします。
92 | * Module2 で実現できる機能は以下の通りです。
93 | * C-s など isearch-mode の検索中に未確定文字列を
94 | ミニバッファの 文字入力位置に表示できる
95 | * 未確定文字列のフォントが設定できる
96 | * IME ON/OFF に連動してタスクバーの
97 | IME 状態表示アイコンが切り替わる
98 | * IME ON の状態で C-x, C-c, C-h など、
99 | コマンドのキーシーケンスになる最初の文字
100 | (以下、プレフィックスキー)
101 | を押すと自動的に IME OFF になる
102 |
103 | * Release 0.0.0 (2020-09-04):
104 | * Initial release
105 | * フックやサブクラス化を使わないで実現できる機能は、
106 | ひと段落したのでリリースします。
107 |
--------------------------------------------------------------------------------
/README.en.md:
--------------------------------------------------------------------------------
1 | [](https://melpa.org/#/tr-ime)
2 |
3 | [ [Japanese](./README.md) / English ]
4 |
5 | # Emulator of GNU Emacs IME patch for Windows (tr-ime)
6 |
7 | Emulator of GNU Emacs IME patch for Windows (tr-ime) emulates the C
8 | implementation part of an IME patch for GNU Emacs that allows to input
9 | Japanese using the Windows IME (Input Method Editor). On Emacs 26.2 or
10 | later, Japanese input using the IME is now possible even without the IME
11 | patch. However, some of the features of the IME patch are not implemented
12 | in current Emacs, so it is possible to type Japanese on Emacs without the
13 | IME patch, but it is not convenient.
14 |
15 | w32-ime.el in the
16 | [w32-ime package](https://github.com/trueroad/w32-ime.el)
17 | manages the upper layer of the IME
18 | patch and provides the convenient features but it could not be used on
19 | emacs.exe without the IME patch applied. tr-ime emulates the lower
20 | layers of the IME patches and can interact with w32-ime.el. So, using
21 | tr-ime, w32-ime.el can be used on emacs.exe without the IME patch applied.
22 |
23 | By using tr-ime and w32-ime.el together, emacs.exe without the IME patch
24 | can use the same convenient features as the IME patched emacs.exe. They
25 | can display the on/off state of the IME in the mode line as UI/UX features.
26 | They also have hooks to call when the IME state is changed. With these
27 | hooks, you can change the color and shape of the cursor depending on the
28 | IME on/off status to be visually known to the IME state.
29 |
30 | To use standard features (stable but less functionality) of the tr-ime
31 | package, add the following code to your init.el or .emacs
32 | It loads the tr-ime-mod DLL module if you use Emacs 27.
33 |
34 | ```el
35 | (tr-ime-standard-install)
36 | (setq default-input-method "W32-IME")
37 | (w32-ime-initialize)
38 | ```
39 |
40 | To use advanced features (experimental but more functionality) of the
41 | tr-ime package, add the following code to your init.el or .emacs
42 | It loads the tr-ime-modadv DLL module.
43 |
44 | ```el
45 | (tr-ime-advanced-install)
46 | (setq default-input-method "W32-IME")
47 | (w32-ime-initialize)
48 | ```
49 |
50 | ## News
51 |
52 | [NEWS.md](./NEWS.md)
53 |
54 | ## License
55 |
56 | Copyright (C) 2020-2022 Masamichi Hosoda
57 |
58 | Emulator of GNU Emacs IME patch for Windows (tr-ime)
59 | is free software: you can redistribute it and/or modify
60 | it under the terms of the GNU General Public License as published by
61 | the Free Software Foundation, either version 3 of the License, or
62 | (at your option) any later version.
63 |
64 | Emulator of GNU Emacs IME patch for Windows (tr-ime)
65 | is distributed in the hope that it will be useful,
66 | but WITHOUT ANY WARRANTY; without even the implied warranty of
67 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
68 | GNU General Public License for more details.
69 |
70 | You should have received a copy of the GNU General Public License
71 | along with tr-ime.
72 | If not, see .
73 |
74 | [COPYING](./COPYING)
75 |
--------------------------------------------------------------------------------
/autogen.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | autoreconf -v -i
4 |
--------------------------------------------------------------------------------
/configure.ac:
--------------------------------------------------------------------------------
1 | # -*- Autoconf -*-
2 | # Process this file with autoconf to produce a configure script.
3 |
4 | AC_PREREQ([2.71])
5 | AC_INIT([Emulator of GNU Emacs IME patch for Windows], [0.5.0],, [tr-ime],
6 | [https://github.com/trueroad/tr-emacs-ime-module])
7 | AC_CANONICAL_TARGET
8 | AM_INIT_AUTOMAKE([-Wall -Werror foreign])
9 |
10 | AC_CONFIG_SRCDIR([src/tr-ime-mod.c])
11 | AC_CONFIG_HEADERS([src/config.h])
12 | AC_CONFIG_MACRO_DIRS([m4])
13 |
14 | PACKAGE_FILEVERSION='0,5,0,0'
15 | PACKAGE_PRODUCTVERSION='0,5,0,0'
16 | PACKAGE_COPYRIGHT='Copyright (C) 2020-2022 Masamichi Hosoda.'
17 | PACKAGE_LICENSE='License: GPL3+'
18 |
19 | AC_DEFINE_UNQUOTED([PACKAGE_FILEVERSION], [$PACKAGE_FILEVERSION],
20 | [Define to the FILEVERSION of this package.])
21 | AC_DEFINE_UNQUOTED([PACKAGE_PRODUCTVERSION], [$PACKAGE_PRODUCTVERSION],
22 | [Define to the PRODUCTVERSION of this package.])
23 | AC_DEFINE_UNQUOTED([PACKAGE_COPYRIGHT], ["$PACKAGE_COPYRIGHT"],
24 | [Define to the copyright of this package.])
25 | AC_DEFINE_UNQUOTED([PACKAGE_LICENSE], ["$PACKAGE_LICENSE"],
26 | [Define to the license of this package.])
27 |
28 | MOD_ABI_VERSION='1'
29 | MODADV_ABI_VERSION='2'
30 |
31 | AC_DEFINE_UNQUOTED([MOD_ABI_VERSION], ["$MOD_ABI_VERSION"],
32 | [Define to the module ABI version of this package.])
33 | AC_DEFINE_UNQUOTED([MODADV_ABI_VERSION], ["$MODADV_ABI_VERSION"],
34 | [Define to the advanced module ABI version of this package.])
35 | AC_SUBST([MOD_ABI_VERSION])
36 | AC_SUBST([MODADV_ABI_VERSION])
37 |
38 | AC_DEFINE_UNQUOTED([HOST_PLATFORM], ["$host"],
39 | [Define to the host platform name.])
40 |
41 | # Checks for programs.
42 | AC_PROG_CC
43 | AS_IF([test "x$ac_cv_prog_cc_c99" = xno],
44 | AC_MSG_ERROR([C99 compiler is not found.]))
45 |
46 | AC_PROG_CXX
47 | AX_CXX_COMPILE_STDCXX([14], [ext], [mandatory])
48 |
49 | AM_PROG_AR
50 |
51 | AS_IF([test "x$target_alias" = x],
52 | [target_alias=$target])
53 | AC_CHECK_TARGET_TOOL([WINDRES], [windres], [no])
54 | AS_IF([test "x$WINDRES" = xno],
55 | AC_MSG_ERROR([windres is not found.]))
56 |
57 | AM_PATH_LISPDIR
58 | AC_ARG_WITH([pkglispdir],
59 | AS_HELP_STRING([--with-pkglispdir=DIR],
60 | [where to install emacs lisp files (default lispdir/PACKAGE)]),
61 | [pkglispdir=${withval}], [pkglispdir='${lispdir}/${PACKAGE}'])
62 | AC_SUBST([pkglispdir])
63 | AC_MSG_NOTICE([where to install emacs lisp files is ${pkglispdir}])
64 |
65 | AC_ARG_WITH([pkgmoduledir],
66 | AS_HELP_STRING([--with-pkgmoduledir=DIR],
67 | [where to install emacs dynamic modules (default lispdir/PACKAGE)]),
68 | [pkgmoduleexecdir=${withval}], [pkgmoduleexecdir='${lispdir}/${PACKAGE}'])
69 | AC_SUBST([pkgmoduleexecdir])
70 | AC_MSG_NOTICE([where to install emacs dynamic modules is ${pkgmoduleexecdir}])
71 |
72 | # Checks for libraries.
73 | LT_INIT([disable-static shared win32-dll])
74 | LT_LANG([Windows Resource])
75 | SHREXT=${shrext_cmds}
76 | AC_SUBST([SHREXT])
77 |
78 | AC_SUBST([objdir])
79 |
80 | # Checks for header files.
81 | AC_ARG_WITH([emacs-module-hdir],
82 | AS_HELP_STRING([--with-emacs-module-hdir=DIR],
83 | [directory of emacs-module.h (default: ${srcdir}/src/emacs-27.1)]),
84 | [CPPFLAGS="${CPPFLAGS} -I ${withval}"],
85 | [CPPFLAGS="${CPPFLAGS} -I ${PWD}/${srcdir}/src/emacs-27.1"])
86 | AC_CHECK_HEADERS([emacs-module.h],,
87 | AC_MSG_ERROR([emacs-module.h is not found.]))
88 |
89 | AC_CHECK_HEADERS([windows.h],,
90 | AC_MSG_ERROR([windows.h is not found.]))
91 |
92 | AC_CHECK_HEADERS([imm.h],,
93 | AC_MSG_ERROR([imm.h is not found.]),
94 | [#include ])
95 |
96 | # Checks for typedefs, structures, and compiler characteristics.
97 | AC_CHECK_TYPES([ptrdiff_t])
98 |
99 | AC_LANG_PUSH([C++])
100 | AC_MSG_CHECKING([whether the C++ compiler has __PRETTY_FUNCTION__])
101 | AC_COMPILE_IFELSE(
102 | [AC_LANG_PROGRAM([[]],[[ const char* foo = __PRETTY_FUNCTION__; ]])],
103 | [AC_MSG_RESULT([yes])
104 | AC_DEFINE([HAVE_CXX_PRETTY_FUNCTION], [1],
105 | [Define if C++ compiler has __PRETTY_FUNCTION__])],
106 | [AC_MSG_RESULT([no])])
107 | AC_LANG_POP([C++])
108 |
109 | # Checks for library functions.
110 |
111 | AC_CONFIG_FILES([Makefile
112 | lisp/Makefile
113 | src/Makefile])
114 | AC_OUTPUT
115 |
--------------------------------------------------------------------------------
/lisp/Makefile.am:
--------------------------------------------------------------------------------
1 | #
2 | # Targets
3 | #
4 |
5 | pkglisp_LISP = tr-ime.el \
6 | tr-ime-openstatus.el \
7 | tr-ime-hook.el \
8 | tr-ime-workaround-prefix-key.el \
9 | tr-ime-workaround-inconsistent.el \
10 | tr-ime-subclassify.el \
11 | tr-ime-thread-message.el \
12 | tr-ime-recv-notify.el \
13 | tr-ime-font.el \
14 | tr-ime-isearch.el \
15 | tr-ime-workaround-isearch.el \
16 | tr-ime-prefix-key.el \
17 | tr-ime-sync.el \
18 | tr-ime-reconversion.el \
19 | tr-ime-documentfeed.el \
20 | tr-ime-debug.el \
21 | tr-ime-download.el
22 | EXTRA_DIST = tr-ime.el \
23 | tr-ime-openstatus.el \
24 | tr-ime-hook.el \
25 | tr-ime-workaround-prefix-key.el \
26 | tr-ime-workaround-inconsistent.el \
27 | tr-ime-subclassify.el \
28 | tr-ime-thread-message.el \
29 | tr-ime-recv-notify.el \
30 | tr-ime-font.el \
31 | tr-ime-isearch.el \
32 | tr-ime-workaround-isearch.el \
33 | tr-ime-prefix-key.el \
34 | tr-ime-sync.el \
35 | tr-ime-reconversion.el \
36 | tr-ime-documentfeed.el \
37 | tr-ime-debug.el \
38 | tr-ime-download.el
39 |
--------------------------------------------------------------------------------
/lisp/tr-ime-debug.el:
--------------------------------------------------------------------------------
1 | ;;; tr-ime-debug.el --- Debug settings -*- lexical-binding: t -*-
2 |
3 | ;; Copyright (C) 2020, 2022 Masamichi Hosoda
4 |
5 | ;; Author: Masamichi Hosoda
6 | ;; URL: https://github.com/trueroad/tr-emacs-ime-module
7 |
8 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime)
9 | ;; is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 | ;;
14 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime)
15 | ;; is distributed in the hope that it will be useful,
16 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | ;; GNU General Public License for more details.
19 | ;;
20 | ;; You should have received a copy of the GNU General Public License
21 | ;; along with tr-ime.
22 | ;; If not, see .
23 |
24 | ;;; Commentary:
25 |
26 | ;; This file is part of
27 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime).
28 | ;; See tr-ime.el
29 |
30 | ;;; Code:
31 |
32 | ;;
33 | ;; ユーザ設定用
34 | ;;
35 |
36 | (defgroup tr-ime-debug nil
37 | "デバッグ設定 (advanced)."
38 | :group 'tr-ime)
39 |
40 | ;;
41 | ;; デバッグ出力レベル
42 | ;;
43 |
44 | (declare-function tr-ime-modadv--set-verbose-level "tr-ime-modadv"
45 | (arg1))
46 |
47 | (defun tr-ime-debug--verbose-level-set (symb level)
48 | "デバッグ出力レベルを設定する.
49 |
50 | SYMB には tr-ime-debug-verbose-level をしている。
51 | LEVEL はデバッグ出力レベルを 0 (none) から 6 (trace) の整数で指定するか、
52 | nil を指定した場合は設定(変更)しない。"
53 | (when level
54 | (tr-ime-modadv--set-verbose-level level))
55 | (set-default symb level))
56 |
57 | (defcustom tr-ime-debug-verbose-level nil
58 | "デバッグ出力レベル.
59 |
60 | この設定を変更する場合には \"custom-set-variables\" を使うこと。
61 |
62 | Win32 API の OutputDebugString を使った、
63 | デバッグメッセージの出力レベルを 0 (none) から 6 (trace) の整数で指定するか、
64 | nil を指定した場合は設定(変更)しない。"
65 | :type '(choice (const :tag "none" 0)
66 | (const :tag "fatal" 1)
67 | (const :tag "error" 2)
68 | (const :tag "warn" 3)
69 | (const :tag "info" 4)
70 | (const :tag "debug" 5)
71 | (const :tag "trace" 6)
72 | (const :tag "no set" nil))
73 | :set #'tr-ime-debug--verbose-level-set
74 | :group 'tr-ime-debug)
75 |
76 | ;;
77 | ;; provide
78 | ;;
79 |
80 | (provide 'tr-ime-debug)
81 |
82 | ;; Local Variables:
83 | ;; coding: utf-8
84 | ;; End:
85 |
86 | ;;; tr-ime-debug.el ends here
87 |
--------------------------------------------------------------------------------
/lisp/tr-ime-documentfeed.el:
--------------------------------------------------------------------------------
1 | ;;; tr-ime-documentfeed.el --- Documentfeed -*- lexical-binding: t -*-
2 |
3 | ;; Copyright (C) 2020, 2022 Masamichi Hosoda
4 |
5 | ;; Author: Masamichi Hosoda
6 | ;; URL: https://github.com/trueroad/tr-emacs-ime-module
7 |
8 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime)
9 | ;; is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 | ;;
14 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime)
15 | ;; is distributed in the hope that it will be useful,
16 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | ;; GNU General Public License for more details.
19 | ;;
20 | ;; You should have received a copy of the GNU General Public License
21 | ;; along with tr-ime.
22 | ;; If not, see .
23 |
24 | ;;; Commentary:
25 |
26 | ;; This file is part of
27 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime).
28 | ;; See tr-ime.el
29 |
30 | ;;; Code:
31 |
32 | ;;
33 | ;; require
34 | ;;
35 |
36 | (require 'tr-ime-reconversion)
37 |
38 | ;;
39 | ;; ユーザ設定用
40 | ;;
41 |
42 | (defgroup tr-ime-documentfeed nil
43 | "前後の確定済文字列を参照した変換 (advanced)."
44 | :group 'tr-ime)
45 |
46 | ;;
47 | ;; 前後の確定済文字列を参照した変換 (DOCUMENTFEED)
48 | ;;
49 |
50 | (declare-function tr-ime-modadv--set-documentfeed "tr-ime-modadv"
51 | (arg1 arg2))
52 |
53 | (defun tr-ime-documentfeed--set (symb bool)
54 | "前後の確定済文字列を参照した変換 (DOCUMENTFEED) 動作を行うか否か設定する.
55 |
56 | SYMB には tr-ime-documentfeed-p を指定する。
57 | BOOL が non-nil なら DOCUMENTFEED 動作を行う。
58 | それ以外なら行わない。"
59 | (if bool
60 | (when (and (boundp 'tr-ime-enabled-features)
61 | (eq tr-ime-enabled-features 'advanced))
62 | (add-hook 'tr-ime-modadv--documentfeed-hook
63 | #'tr-ime-reconversion--notify-reconvert-string)
64 | (tr-ime-modadv--set-documentfeed
65 | (string-to-number (frame-parameter nil 'window-id)) t))
66 | (when (fboundp 'tr-ime-modadv--set-documentfeed)
67 | (tr-ime-modadv--set-documentfeed
68 | (string-to-number (frame-parameter nil 'window-id)) nil))
69 | (remove-hook 'tr-ime-modadv--documentfeed-hook
70 | #'tr-ime-reconversion--notify-reconvert-string))
71 | (set-default symb bool))
72 |
73 | (defcustom tr-ime-documentfeed-p t
74 | "前後の確定済文字列を参照した変換 (DOCUMENTFEED) 動作を行うか否か.
75 |
76 | この設定を変更する場合には \"custom-set-variables\" を使うこと。
77 |
78 | 確定済文字列のあるところにカーソルを置いて文字を入力・変換すると、
79 | カーソルのあった場所の確定済文字列によって変換候補が変わる機能。"
80 | :type '(choice (const :tag "Enable" t)
81 | (const :tag "Disable" nil))
82 | :set #'tr-ime-documentfeed--set
83 | :group 'tr-ime-documentfeed)
84 |
85 | (defun tr-ime-documentfeed-unload-function ()
86 | "アンロードするため DOCUMENTFEED を無効にする."
87 | (let (_dummy)
88 | (tr-ime-documentfeed--set '_dummy nil)))
89 |
90 | ;;
91 | ;; provide
92 | ;;
93 |
94 | (provide 'tr-ime-documentfeed)
95 |
96 | ;; Local Variables:
97 | ;; coding: utf-8
98 | ;; End:
99 |
100 | ;;; tr-ime-documentfeed.el ends here
101 |
--------------------------------------------------------------------------------
/lisp/tr-ime-download.el:
--------------------------------------------------------------------------------
1 | ;;; tr-ime-download.el --- Download files -*- lexical-binding: t -*-
2 |
3 | ;; Copyright (C) 2020, 2022 Masamichi Hosoda
4 |
5 | ;; Author: Masamichi Hosoda
6 | ;; URL: https://github.com/trueroad/tr-emacs-ime-module
7 |
8 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime)
9 | ;; is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 | ;;
14 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime)
15 | ;; is distributed in the hope that it will be useful,
16 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | ;; GNU General Public License for more details.
19 | ;;
20 | ;; You should have received a copy of the GNU General Public License
21 | ;; along with tr-ime.
22 | ;; If not, see .
23 |
24 | ;;; Commentary:
25 |
26 | ;; This file is part of
27 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime).
28 | ;; See tr-ime.el
29 |
30 | ;;; Code:
31 |
32 | ;;
33 | ;; モジュール DLL のダウンロード
34 | ;;
35 |
36 | (defconst tr-ime-download--url-prefix
37 | "https://github.com/trueroad/tr-ime-dist/raw/v0.5.0/"
38 | "ダウンロード先 URL のプレフィックス.")
39 |
40 | (defconst tr-ime-download--url-suffix ".gz"
41 | "ダウンロード先 URL のサフィックス.")
42 |
43 | (defconst tr-ime-download--file-sum-alist
44 | '(("tr-ime-mod-1-i686-pc-cygwin.dll" .
45 | "68c734d8b1c56abb089b05f0ece0fe1b2c47ed818ea118be1cadd678d7a2ceb1")
46 | ("tr-ime-mod-1-i686-w64-mingw32.dll" .
47 | "ba162d3f927d779fa42f6906b3c8ac1252dd3f7332938b28c41b0b1cfee646dd")
48 | ("tr-ime-mod-1-x86_64-pc-cygwin.dll" .
49 | "f8362c23faa9835c6071de62967125a3683304718703f39296baec70bbdb0981")
50 | ("tr-ime-mod-1-x86_64-w64-mingw32.dll" .
51 | "92159ebcf946ec6d5a498d9bc473ec3788aaee0caea51f34435da3535f70f2bf")
52 | ("tr-ime-modadv-2-i686-pc-cygwin.dll" .
53 | "3a1dd0e3b114ee3ae1d9bc24f0723a11f4ac57dceaf0de6967262c611e80fe9f")
54 | ("tr-ime-modadv-2-i686-w64-mingw32.dll" .
55 | "9fc539e63601763f7e94fd82523c8b98ac5f2e49fb5ecc7040454488a1e77152")
56 | ("tr-ime-modadv-2-x86_64-pc-cygwin.dll" .
57 | "c3f6ec346293800268af2004053bf6ebde1fe513554e9755d1fa3b6662bd619b")
58 | ("tr-ime-modadv-2-x86_64-w64-mingw32.dll" .
59 | "d3492a55d6342351f38c3cb7c1c3afdc6cba36c58934786e7d2bc7ac999bc0c5"))
60 | "ダウンロードする DLL の sha256sum.")
61 |
62 | (defconst tr-ime-download--dir (file-name-directory load-file-name)
63 | "モジュール DLL のダウンロード先ディレクトリ.")
64 |
65 | (defun tr-ime-download--download-and-unzip (url filename)
66 | "モジュール DLL をダウンロードして解凍する.
67 |
68 | URL からダウンロードして解凍したファイルを、
69 | ディレクトリ DIR のファイル名 FILENAME に置く。"
70 | (let ((tmpfilename (make-temp-file (concat tr-ime-download--dir "tmp"))))
71 | (url-copy-file url tmpfilename t)
72 | (with-temp-file (concat tr-ime-download--dir filename)
73 | (set-buffer-multibyte nil)
74 | (insert-file-contents-literally tmpfilename)
75 | (delete-file tmpfilename)
76 | (zlib-decompress-region (point-min) (point-max)))))
77 |
78 | (defun tr-ime-download--good-file-p (filename)
79 | "ファイルのハッシュを確認する.
80 |
81 | ディレクトリ DIR のファイル名 FILENAME について sha256sum を確認する。
82 | 一致すれば non-nil を返す。そうでなければ nil を返す。"
83 | (let ((sum (cdr (assoc filename tr-ime-download--file-sum-alist)))
84 | (path (concat tr-ime-download--dir filename)))
85 | (if (file-exists-p path)
86 | (with-temp-buffer
87 | (set-buffer-multibyte nil)
88 | (insert-file-contents-literally path)
89 | (string= (secure-hash 'sha256 (current-buffer)) sum))
90 | nil)))
91 |
92 | (defun tr-ime-download--request-file (filename)
93 | "モジュール DLL をダウンロードしてロードする.
94 |
95 | FILENAME のモジュール DLL をダウンロードしてロードする。"
96 | (tr-ime-download--download-and-unzip
97 | (concat tr-ime-download--url-prefix
98 | filename
99 | tr-ime-download--url-suffix)
100 | filename)
101 | (if (tr-ime-download--good-file-p filename)
102 | (progn
103 | (set-file-modes (concat tr-ime-download--dir filename) #o755)
104 | (load filename))
105 | (delete-file (concat tr-ime-download--dir filename))
106 | (error "Download failed: %s" filename)))
107 |
108 | (defun tr-ime-download-mod-file (name &optional no-confirm)
109 | "モジュール DLL をダウンロードするか否か確認してダウンロードする.
110 |
111 | NAME にモジュール DLL のファイル名拡張子なしを指定する。
112 | NO-CONFIRM が non-nil なら確認せずにダウンロードする。"
113 | (if (or no-confirm
114 | (y-or-n-p (format "Download %s.dll? " name)))
115 | (tr-ime-download--request-file (concat name ".dll"))
116 | (error "%s.dll is not found.
117 |
118 | Download or build it and put it in the directory specified in \"load-path.\"
119 | See https://github.com/trueroad/tr-emacs-ime-module" name)))
120 |
121 | ;;
122 | ;; provide
123 | ;;
124 |
125 | (provide 'tr-ime-download)
126 |
127 | ;; Local Variables:
128 | ;; coding: utf-8
129 | ;; End:
130 |
131 | ;;; tr-ime-download.el ends here
132 |
--------------------------------------------------------------------------------
/lisp/tr-ime-font.el:
--------------------------------------------------------------------------------
1 | ;;; tr-ime-font.el --- Font handling -*- lexical-binding: t -*-
2 |
3 | ;; Copyright (C) 2020, 2022 Masamichi Hosoda
4 |
5 | ;; Author: Masamichi Hosoda
6 | ;; URL: https://github.com/trueroad/tr-emacs-ime-module
7 |
8 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime)
9 | ;; is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 | ;;
14 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime)
15 | ;; is distributed in the hope that it will be useful,
16 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | ;; GNU General Public License for more details.
19 | ;;
20 | ;; You should have received a copy of the GNU General Public License
21 | ;; along with tr-ime.
22 | ;; If not, see .
23 |
24 | ;;; Commentary:
25 |
26 | ;; This file is part of
27 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime).
28 | ;; See tr-ime.el
29 |
30 | ;;; Code:
31 |
32 | ;;
33 | ;; require
34 | ;;
35 |
36 | (require 'seq)
37 |
38 | ;;
39 | ;; ユーザ設定用
40 | ;;
41 |
42 | (defgroup tr-ime-font nil
43 | "IME フォント(未確定文字列フォント)設定 (advanced)."
44 | :group 'tr-ime)
45 |
46 | ;;
47 | ;; 属性変換
48 | ;;
49 |
50 | (defun tr-ime-font--encode-weight (symb)
51 | "フェイス属性の weight から LOGFONT 構造体の lfWeight へ変換する.
52 |
53 | SYMB に weight を指定する。返り値は lfWeight。"
54 | (let* ((result
55 | (seq-drop-while
56 | (lambda (x)
57 | (eq (seq-drop-while (lambda (y) (not (eq y symb))) x) []))
58 | font-weight-table))
59 | (weight
60 | (if (eq result []) 100 (aref (aref result 0) 0))))
61 | (cond ((>= weight 210) 900) ; FW_HEAVY
62 | ((>= weight 205) 800) ; FW_EXTRABOLD
63 | ((>= weight 200) 700) ; FW_BOLD
64 | ((>= weight 180) 600) ; FW_SEMIBOLD
65 | ((>= weight 100) 400) ; FW_NORMAL
66 | ((>= weight 50) 300) ; FW_LIGHT
67 | ((>= weight 40) 200) ; FW_EXTRALIGHT
68 | ((>= weight 20) 100) ; FW_THIN
69 | (t 0))))
70 |
71 | (defun tr-ime-font--encode-slant (symb)
72 | "フェイス属性の slant から LOGFONT 構造体の lfItalic へ変換する.
73 |
74 | SYMB に slant を指定する。返り値は lfItalic。"
75 | (let* ((result
76 | (seq-drop-while
77 | (lambda (x)
78 | (eq (seq-drop-while (lambda (y) (not (eq y symb))) x) []))
79 | font-slant-table))
80 | (slant
81 | (if (eq result []) 100 (aref (aref result 0) 0))))
82 | (> slant 150)))
83 |
84 | ;;
85 | ;; フレームの ime-font 設定を反映
86 | ;;
87 |
88 | (declare-function tr-ime-modadv--set-font "tr-ime-modadv"
89 | (arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8
90 | arg9 arg10 arg11 arg12 arg13 arg14 arg15))
91 | (declare-function tr-ime-modadv--get-dpi "tr-ime-modadv")
92 |
93 | (defun tr-ime-font-reflect-frame-parameter (&optional frame)
94 | "フレームの ime-font 設定を反映する.
95 |
96 | FRAME の フレームパラーメータから ime-font 設定を読み取り、
97 | モジュールで C++ 実装されている低レベルフォント設定関数
98 | tr-ime-modadv--set-font を使って未確定文字列のフォントを設定する。
99 | FRAME が nil または省略された場合は選択されているフレームが対象となる。
100 | family に generic family を指定することはできない。
101 |
102 | IME パッチではフレームの ime-font 設定を変更すると即座に反映されるが、
103 | tr-ime 環境では、フレームの ime-font 設定と、
104 | モジュール内部の未確定文字列フォント設定は独立であり、
105 | フレームの ime-font 設定を変更しても、本関数を呼ぶまで反映されない。
106 | よって、設定後に必ず本関数を呼ぶようにするか、何らかのフックなどで
107 | フレームの ime-font 設定変更を検出して本関数を呼ぶようなどすれば、
108 | IME パッチと同様の設定で使うことができる。
109 |
110 | なお、低レベルフォント設定関数 tr-ime-modadv--set-font で設定される、
111 | モジュール内部の設定はスレッド毎の設定となっており、
112 | 一度設定すると他のフレームでも同じ設定が使われる。
113 | そのため、全フレームで同一の設定にしたい場合は、
114 |
115 | (modify-all-frames-parameters '((ime-font . \"原ノ味明朝-24\")))
116 | (w32-tr-ime-reflect-frame-parameter-ime-font)
117 |
118 | のようにすることによって、全フレームおよび \"default-frame-alist\" の
119 | ime-font 設定が変更された上で、モジュール内部の設定にも反映される。
120 |
121 | 逆にフレーム毎の設定をしたい場合は、
122 | 各フレームの ime-font 設定を別々に設定しておき、
123 | \"focus-in-hook\" などで ime-font 設定が変わったことを検出して
124 | 本関数を呼び出すなどすれば、フレームが切り替わった際に、
125 | そのフレームの ime-font 設定を反映させることもできる。"
126 | (interactive)
127 | (let ((ime-font (frame-parameter frame 'ime-font)))
128 | (when ime-font
129 | (let* ((attributes (font-face-attributes ime-font))
130 | (family (plist-get attributes :family))
131 | (height (plist-get attributes :height)))
132 | (when (and family height)
133 | (let ((h (round (/ (* height
134 | (cdr (tr-ime-modadv--get-dpi)))
135 | -720.0))))
136 | (tr-ime-modadv--set-font
137 | (string-to-number
138 | (frame-parameter frame 'window-id))
139 | h 0 0 0
140 | (tr-ime-font--encode-weight (plist-get attributes :weight))
141 | (tr-ime-font--encode-slant (plist-get attributes :slant))
142 | nil nil 1 0 0 0 0 family)))))))
143 |
144 | ;;
145 | ;; 未確定文字列フォント変更検出
146 | ;;
147 |
148 | (defvar tr-ime-font--last-ime-font nil
149 | "未確定文字列フォント変更検出用.")
150 |
151 | (defun tr-ime-font-check ()
152 | "フレームパラメータ ime-font が変更されていたら反映する.
153 |
154 | Emacs の標準的なフックである \"post-command-hook\" に登録するか、
155 | \"after-focus-change-function\" 経由で呼び出す。
156 |
157 | IME パッチは、フレームパラメータの ime-font を設定すると、
158 | 即座に未確定文字列フォントに反映されるが、モジュール環境では反映できない。
159 | 本関数は ime-font が変更されているか確認し、変更されていたら
160 | 変更を反映する tr-ime-font-reflect-frame-parameter
161 | 関数を呼び出すことによって未確定文字列フォントを設定する。
162 |
163 | \"after-focus-change-function\" 経由で呼び出した場合は、
164 | フレームを変更した際に呼ばれ、
165 | フレームへ設定されたパラメータに応じて未確定文字列フォントが
166 | 設定されるようになる。
167 |
168 | \"post-command-hook\" に登録した場合は、ほとんどのコマンドの動作後に呼ばれ、
169 | フレームパラメータの変更後すぐに未確定文字列フォントが
170 | 設定されるようになる。"
171 | (let ((parameter (frame-parameter nil 'ime-font)))
172 | (unless (string= parameter tr-ime-font--last-ime-font)
173 | (tr-ime-font-reflect-frame-parameter)
174 | (setq tr-ime-font--last-ime-font parameter))))
175 |
176 | ;;
177 | ;; フォーカス変更(フレーム変更)時
178 | ;;
179 |
180 | (defun tr-ime-font--after-focus-change-function ()
181 | "フォーカス変更を確認して ime-font 設定を反映する.
182 |
183 | \"after-focus-change-function\" は呼び出された時点では
184 | まだ \"selected-frame\" が変わっていないことがあるので、
185 | 全フレームに対して \"frame-focus-state\" でフォーカスを得ているか否か判定し、
186 | フォーカスを得ていたフレームで w32-tr-ime-font-check
187 | を呼び出して未確定文字列フォントを設定する。
188 |
189 | \"after-focus-change-function\" に登録して使う。"
190 | (dolist (f (frame-list))
191 | (when (frame-focus-state f)
192 | (with-selected-frame f (tr-ime-font-check)))))
193 |
194 | (defun tr-ime-font--focus-set (symb bool)
195 | "フォーカス変更時に ime-font 設定を反映するか否か設定する.
196 |
197 | SYMB は tr-ime-font-focus-p を指定する。
198 | BOOL が non-nil ならフォーカス変更時に ime-font 設定を反映する。
199 | そうでなければフォーカス変更時に ime-font 設定を反映しない。"
200 | (if bool
201 | (add-function :before
202 | after-focus-change-function
203 | #'tr-ime-font--after-focus-change-function)
204 | (remove-function
205 | after-focus-change-function
206 | #'tr-ime-font--after-focus-change-function))
207 | (set-default symb bool))
208 |
209 | (defcustom tr-ime-font-focus-p t
210 | "フォーカス変更時に ime-font 設定を反映するか否か.
211 |
212 | この設定を変更する場合には \"custom-set-variables\" を使うこと。
213 |
214 | 本設定を non-nil (Enable) にすると、フォーカス変更(フレーム変更)時に
215 | フレームパラメータの ime-font 設定が、
216 | モジュールの未確定文字列フォントに反映される。"
217 | :type '(choice (const :tag "Enable" t)
218 | (const :tag "Disable" nil))
219 | :set #'tr-ime-font--focus-set
220 | :group 'tr-ime-font)
221 |
222 | ;;
223 | ;; コマンド実行後
224 | ;;
225 |
226 | (defun tr-ime-font--post-command-set (symb bool)
227 | "コマンド実行後に ime-font 設定を反映するか否か設定する.
228 |
229 | SYMB は tr-ime-font-post-command-p を指定する。
230 | BOOL が non-nil ならコマンド実行後に設定を反映する。
231 | そうでなければコマンド実行後に設定を反映しない。"
232 | (if bool
233 | (add-hook 'post-command-hook
234 | #'tr-ime-font-check)
235 | (remove-hook 'post-command-hook
236 | #'tr-ime-font-check))
237 | (set-default symb bool))
238 |
239 | (defcustom tr-ime-font-post-command-p nil
240 | "コマンド実行後に ime-font 設定を反映するか否か.
241 |
242 | この設定を変更する場合には \"custom-set-variables\" を使うこと。
243 |
244 | 本設定を non-nil (Enable) にすると、ほとんどのコマンド実行後に
245 | フレームパラメータの ime-font 設定が、
246 | モジュールの未確定文字列フォントに反映される。
247 | つまり、ime-font 設定を変更することで IME パッチ環境と同様、
248 | ほぼ即座に未確定文字列フォントが設定できる。"
249 | :type '(choice (const :tag "Enable" t)
250 | (const :tag "Disable" nil))
251 | :set #'tr-ime-font--post-command-set
252 | :group 'tr-ime-font)
253 |
254 | ;;
255 | ;; アンロード
256 | ;;
257 |
258 | (defun tr-ime-font-unload-function ()
259 | "アンロードするため IME フォント(未確定文字列フォント)設定を無効にする."
260 | (let (_dummy)
261 | (tr-ime-font--focus-set '_dummy nil)
262 | (tr-ime-font--post-command-set '_dummy nil)))
263 |
264 | ;;
265 | ;; provide
266 | ;;
267 |
268 | (provide 'tr-ime-font)
269 |
270 | ;; Local Variables:
271 | ;; coding: utf-8
272 | ;; End:
273 |
274 | ;;; tr-ime-font.el ends here
275 |
--------------------------------------------------------------------------------
/lisp/tr-ime-hook.el:
--------------------------------------------------------------------------------
1 | ;;; tr-ime-hook.el --- Hook emulation of IME patch -*- lexical-binding: t -*-
2 |
3 | ;; Copyright (C) 2020-2022 Masamichi Hosoda
4 |
5 | ;; Author: Masamichi Hosoda
6 | ;; URL: https://github.com/trueroad/tr-emacs-ime-module
7 |
8 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime)
9 | ;; is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 | ;;
14 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime)
15 | ;; is distributed in the hope that it will be useful,
16 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | ;; GNU General Public License for more details.
19 | ;;
20 | ;; You should have received a copy of the GNU General Public License
21 | ;; along with tr-ime.
22 | ;; If not, see .
23 |
24 | ;;; Commentary:
25 |
26 | ;; This file is part of
27 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime).
28 | ;; See tr-ime.el
29 |
30 | ;;; Code:
31 |
32 | ;;
33 | ;; ユーザ設定用
34 | ;;
35 |
36 | (defgroup tr-ime-core nil
37 | "コア機能設定.
38 |
39 | コア機能の設定です。通常は設定変更しないでください。"
40 | :group 'tr-ime)
41 |
42 | (defgroup tr-ime-hook nil
43 | "IME パッチ特有のアブノーマルフック."
44 | :group 'tr-ime-core)
45 |
46 | ;;
47 | ;; Hook
48 | ;;
49 |
50 | ;; IME パッチ適用 Emacs ではコンフリクトを未然に防ぐため
51 | ;; 明示的にエラーを出して動作を停止させる
52 | (require 'tr-ime)
53 | (when (tr-ime-detect-ime-patch-p)
54 | (error "%s" (concat "Emacs seems to have an IME patch applied. "
55 | "tr-ime cannot work on it.")))
56 |
57 | ;; IME パッチ適用 Emacs だと変数 select-window-functions が
58 | ;; C 実装なのでエイリアスにしようとするとエラーが発生する
59 | (define-obsolete-variable-alias 'select-window-functions
60 | 'tr-ime-hook-select-window-functions "2020")
61 | (defvar tr-ime-hook-select-window-functions nil
62 | "選択されたウィンドウが変更されると呼ばれるアブノーマルフック.
63 |
64 | IME パッチ特有のフックで、 IME パッチでは C 実装されているが、
65 | Lisp でエミュレーションする。")
66 |
67 | ;; IME パッチ適用 Emacs だと変数 set-selected-window-buffer-functions が
68 | ;; C 実装なのでエイリアスにしようとするとエラーが発生する
69 | (define-obsolete-variable-alias 'set-selected-window-buffer-functions
70 | 'tr-ime-hook-set-selected-window-buffer-functions "2020")
71 | (defvar tr-ime-hook-set-selected-window-buffer-functions nil
72 | "選択ウィンドウに紐づいたバッファが変更されると呼ばれるアブノーマルフック.
73 |
74 | IME パッチ特有のフックで、 IME パッチでは C 実装されているが、
75 | Lisp でエミュレーションする。")
76 |
77 | ;;
78 | ;; 選択ウィンドウに紐づいたバッファの変更を検出する
79 | ;;
80 |
81 | (defvar tr-ime-hook--last-selected-window-buffer nil
82 | "選択ウィンドウに紐づいたバッファの変更検出用変数.")
83 |
84 | (defun tr-ime-hook-check-selected-window-buffer (_frame)
85 | "選択ウィンドウに紐づいたバッファが変更されていたらフックを呼ぶ."
86 | (let* ((window (selected-window))
87 | (buffer (window-buffer window)))
88 | (unless (eq buffer tr-ime-hook--last-selected-window-buffer)
89 | (run-hook-with-args 'tr-ime-hook-set-selected-window-buffer-functions
90 | tr-ime-hook--last-selected-window-buffer
91 | window
92 | buffer)
93 | (setq tr-ime-hook--last-selected-window-buffer buffer))))
94 |
95 | ;;
96 | ;; 選択ウィンドウの変更を検出する
97 | ;;
98 |
99 | (defvar tr-ime-hook--last-selected-window nil
100 | "選択ウィンドウの変更検出用変数.")
101 |
102 | (defun tr-ime-hook-check-selected-window (_frame)
103 | "選択ウィンドウが変更されていたらフックを呼ぶ."
104 | (let* ((window (selected-window))
105 | (buffer (window-buffer window)))
106 | (unless (eq window tr-ime-hook--last-selected-window)
107 | (run-hook-with-args 'tr-ime-hook-select-window-functions
108 | tr-ime-hook--last-selected-window
109 | window)
110 | (setq tr-ime-hook--last-selected-window window)
111 | (setq tr-ime-hook--last-selected-window-buffer buffer))))
112 |
113 | ;;
114 | ;; 選択ウィンドウとバッファの両方の変更を検出する
115 | ;;
116 |
117 | (defun tr-ime-hook-check ()
118 | "選択ウィンドウとバッファの両方を確認してフックを呼ぶ."
119 | (let ((frame (selected-frame)))
120 | (tr-ime-hook-check-selected-window frame)
121 | (tr-ime-hook-check-selected-window-buffer frame)))
122 |
123 | ;;
124 | ;; 設定用
125 | ;;
126 |
127 | (defun tr-ime-hook--set (symb bool)
128 | "IME パッチ特有のアブノーマルフックをエミュレーションするか否か設定する.
129 |
130 | SYMB は tr-ime-hook-p を指定すること。
131 | BOOL が non-nil ならエミュレーション有効でフックが呼ばれる。
132 | そうでなければエミュレーション無効でフックは呼ばれない。"
133 | (if bool
134 | (progn
135 | (add-hook 'window-selection-change-functions
136 | #'tr-ime-hook-check-selected-window)
137 | (add-hook 'window-buffer-change-functions
138 | #'tr-ime-hook-check-selected-window-buffer))
139 | (remove-hook 'window-selection-change-functions
140 | #'tr-ime-hook-check-selected-window)
141 | (remove-hook 'window-buffer-change-functions
142 | #'tr-ime-hook-check-selected-window-buffer))
143 | (set-default symb bool))
144 |
145 | (defcustom tr-ime-hook-p t
146 | "IME パッチ特有のアブノーマルフックをエミュレーションするか否か.
147 |
148 | この設定を変更する場合には \"custom-set-variables\" を使うこと。
149 |
150 | 注意:w32-ime.el はこれらのアブノーマルフックを使って
151 | ウィンドウやバッファの切り替えを認識して
152 | IME/IM の同期や切り替えなどを行っている。
153 | 本設定を無効にすると、ウィンドウやバッファ切り替え時に
154 | IME/IM が同期しなくなるなどの問題が発生する。
155 | 特別な目的が無い限りは non-nil (Enable) にしておくこと。"
156 | :type '(choice (const :tag "Enable" t)
157 | (const :tag "Disable" nil))
158 | :set #'tr-ime-hook--set
159 | :group 'tr-ime-hook)
160 |
161 | (defun tr-ime-hook-unload-function ()
162 | "アンロードするため IME パッチ特有のアブノーマルフックを無効にする."
163 | (let (_dummy)
164 | (tr-ime-hook--set '_dummy nil)))
165 |
166 | ;;
167 | ;; provide
168 | ;;
169 |
170 | (provide 'tr-ime-hook)
171 |
172 | ;; Local Variables:
173 | ;; coding: utf-8
174 | ;; End:
175 |
176 | ;;; tr-ime-hook.el ends here
177 |
--------------------------------------------------------------------------------
/lisp/tr-ime-isearch.el:
--------------------------------------------------------------------------------
1 | ;;; tr-ime-isearch.el --- Handle isearch-mode -*- lexical-binding: t -*-
2 |
3 | ;; Copyright (C) 2020-2022 Masamichi Hosoda
4 |
5 | ;; Author: Masamichi Hosoda
6 | ;; URL: https://github.com/trueroad/tr-emacs-ime-module
7 |
8 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime)
9 | ;; is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 | ;;
14 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime)
15 | ;; is distributed in the hope that it will be useful,
16 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | ;; GNU General Public License for more details.
19 | ;;
20 | ;; You should have received a copy of the GNU General Public License
21 | ;; along with tr-ime.
22 | ;; If not, see .
23 |
24 | ;;; Commentary:
25 |
26 | ;; This file is part of
27 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime).
28 | ;; See tr-ime.el
29 |
30 | ;;; Code:
31 |
32 | ;;
33 | ;; ユーザ設定用
34 | ;;
35 |
36 | (defgroup tr-ime-isearch nil
37 | "\"isearch-mode\" 設定 (advanced)."
38 | :group 'tr-ime)
39 |
40 | ;;
41 | ;; エコーエリア検出
42 | ;;
43 |
44 | (defvar tr-ime-isearch--last-echo-area-0-point nil
45 | "エコーエリア 0 の point 移動検出用.")
46 |
47 | (defvar tr-ime-isearch--last-echo-area-1-point nil
48 | "エコーエリア 1 の point 移動検出用.")
49 |
50 | (defvar tr-ime-isearch--last-echo-area-buffer nil
51 | "最後に使用されたエコーエリアバッファ.")
52 |
53 | (defun tr-ime-isearch--start ()
54 | "エコーエリアのバッファのうちどちらが使われているか検出を開始する.
55 |
56 | \"isearch-mode-hook\" に登録することにより、\"isearch-mode\" 中に
57 | どのエコーエリアが使われているか検出できるようにする。"
58 | (setq tr-ime-isearch--last-echo-area-0-point
59 | (with-current-buffer " *Echo Area 0*"
60 | (point)))
61 | (setq tr-ime-isearch--last-echo-area-1-point
62 | (with-current-buffer " *Echo Area 1*"
63 | (point))))
64 |
65 | (defun tr-ime-isearch--detect-echo-area-buffer ()
66 | "使用中のエコーエリアバッファを検出して返す.
67 |
68 | \"isearch-mode\" 中に使用しているエコーエリアバッファを返す。"
69 | (let* ((point0 (with-current-buffer " *Echo Area 0*"
70 | (point)))
71 | (point1 (with-current-buffer " *Echo Area 1*"
72 | (point)))
73 | (buff (cond ((and tr-ime-isearch--last-echo-area-0-point
74 | (/= point0
75 | tr-ime-isearch--last-echo-area-0-point))
76 | (get-buffer " *Echo Area 0*"))
77 | ((and tr-ime-isearch--last-echo-area-1-point
78 | (/= point1
79 | tr-ime-isearch--last-echo-area-1-point))
80 | (get-buffer " *Echo Area 1*"))
81 | (tr-ime-isearch--last-echo-area-buffer
82 | tr-ime-isearch--last-echo-area-buffer)
83 | (t
84 | (get-buffer " *Echo Area 0*")))))
85 | ;; (tr-ime-modadv--debug-output
86 | ;; (format-message "last point0 %s, point1 %s, buff %s"
87 | ;; tr-ime-isearch--last-echo-area-0-point
88 | ;; tr-ime-isearch--last-echo-area-1-point
89 | ;; tr-ime-isearch--last-echo-area-buffer))
90 | ;; (tr-ime-modadv--debug-output
91 | ;; (format-message " now point0 %s, point1 %s, buff %s"
92 | ;; point0 point1 buff))
93 | (setq tr-ime-isearch--last-echo-area-0-point point0)
94 | (setq tr-ime-isearch--last-echo-area-1-point point1)
95 | (setq tr-ime-isearch--last-echo-area-buffer buff)))
96 |
97 | ;;
98 | ;; 未確定文字列の表示位置
99 | ;;
100 |
101 | (declare-function tr-ime-modadv--set-composition-window "tr-ime-modadv"
102 | (arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8))
103 |
104 | (defun tr-ime-isearch--update ()
105 | "未確定文字列の表示位置を更新・設定する.
106 |
107 | \"isearch-update-post-hook\" に登録することにより、
108 | \"isearch-mode\" 中の未確定文字列の表示位置を
109 | ミニバッファ上の文字入力位置を更新・設定する。"
110 | (with-current-buffer (tr-ime-isearch--detect-echo-area-buffer)
111 | (let* ((sw
112 | (string-width
113 | (buffer-substring-no-properties (point-min) (point))))
114 | (wc (window-width (minibuffer-window)))
115 | (x (* (% sw wc) (frame-char-width)))
116 | (y (* (/ sw wc) (with-selected-window (minibuffer-window)
117 | (line-pixel-height))))
118 | (edges (window-inside-pixel-edges (minibuffer-window)))
119 | (left (nth 0 edges))
120 | (top (nth 1 edges))
121 | (right (nth 2 edges))
122 | (bottom (nth 3 edges))
123 | (px (+ x left))
124 | (py (+ y top)))
125 | ;; (tr-ime-modadv--debug-output
126 | ;; (format-message
127 | ;; "sw %s, wc %s, x %s, y %s, edges %s"
128 | ;; sw wc x y edges))
129 | ;; (tr-ime-modadv--debug-output
130 | ;; (format-message
131 | ;; "left %s, top %s, right %s, bottom %s, px %s, py %s"
132 | ;; left top right bottom px py))
133 | (tr-ime-modadv--set-composition-window
134 | (string-to-number (frame-parameter nil 'window-id))
135 | 1 px py left top right bottom))))
136 |
137 | (defun tr-ime-isearch--end ()
138 | "未確定文字列の表示位置を元に戻す.
139 |
140 | \"isearch-mode-end-hook\" に登録することにより、\"isearch-mode\" 終了後に
141 | 未確定文字列の表示位置を通常のバッファ内のカーソル位置に戻す。"
142 | (tr-ime-modadv--set-composition-window
143 | (string-to-number (frame-parameter nil 'window-id))
144 | 0 0 0 0 0 0 0))
145 |
146 | ;;
147 | ;; 未確定文字列表示位置を文字入力位置にするか否か設定
148 | ;;
149 |
150 | (defun tr-ime-isearch--set (symb bool)
151 | "未確定文字列表示位置を文字入力位置にするか否か設定する.
152 |
153 | SYMB には tr-ime-isearch-p を指定する。
154 | BOOL が non-nil なら \"isearch-mode\" 中の
155 | 未確定文字列表示位置を文字入力位置に設定する。
156 | そうでなければ設定しない。"
157 | (if bool
158 | (progn
159 | (add-hook 'isearch-mode-hook #'tr-ime-isearch--start)
160 | (add-hook 'isearch-update-post-hook #'tr-ime-isearch--update)
161 | (add-hook 'isearch-mode-end-hook #'tr-ime-isearch--end))
162 | (remove-hook 'isearch-mode-hook #'tr-ime-isearch--start)
163 | (remove-hook 'isearch-update-post-hook #'tr-ime-isearch--update)
164 | (remove-hook 'isearch-mode-end-hook #'tr-ime-isearch--end))
165 | (set-default symb bool))
166 |
167 | (defcustom tr-ime-isearch-p t
168 | "未確定文字列表示位置を文字入力位置にするか否か.
169 |
170 | この設定を変更する場合には \"custom-set-variables\" を使うこと。
171 |
172 | \"isearch-mode\" 中に未確定文字列をエコーエリア(ミニバッファ)
173 | に表示する機能。本機能が無効の場合、
174 | 未確定文字列は \"isearch-mode\" に入る前の入力位置に表示される。"
175 | :type '(choice (const :tag "Enable" t)
176 | (const :tag "Disable" nil))
177 | :set #'tr-ime-isearch--set
178 | :group 'tr-ime-isearch)
179 |
180 | ;;
181 | ;; WM_IME_STARTCOMPOSITION で常に DefSubclassProc を呼ぶか
182 | ;;
183 |
184 | (declare-function tr-ime-modadv--set-startcomposition-defsubclassproc
185 | "tr-ime-modadv"
186 | (arg1 arg2))
187 |
188 | (defun tr-ime-isearch--defsubclassproc-set (symb bool)
189 | "WM_IME_STARTCOMPOSITION で常に DefSubclassProc を呼ぶか否か設定する.
190 |
191 | SYMB には tr-ime-isearch-defsubclassproc-p を指定する。
192 | BOOL が non-nil なら常に呼ぶようになる。
193 | そうでなければ未確定文字列ウィンドウの位置設定中は呼ばなくなる。"
194 | (tr-ime-modadv--set-startcomposition-defsubclassproc
195 | (string-to-number (frame-parameter nil 'window-id)) bool)
196 | (set-default symb bool))
197 |
198 | (defcustom tr-ime-isearch-defsubclassproc-p nil
199 | "WM_IME_STARTCOMPOSITION で常に DefSubclassProc を呼ぶか否か.
200 |
201 | この設定を変更する場合には \"custom-set-variables\" を使うこと。
202 |
203 | WM_IME_STARTCOMPOSITION ハンドラにおいて、
204 | \"isearch-mode\" 中(未確定文字列ウィンドウの位置設定中)は
205 | DefSubcalssProc を呼ばず Emacs のメッセージ処理をスキップしている。
206 | これは Emacs で未確定文字列ウィンドウの位置を \"isearch-mode\"
207 | に入る前の文字入力位置に設定してしまうからで、
208 | この設定後に位置を上書きしても未確定文字列ウィンドウがチラつくからである。
209 | しかし、何らかの理由で元の Emacs の処理に戻さなければならない時は、
210 | 本設定を non-nil (Enable) にすることで \"isearch-mode\" 中であっても、
211 | DefSubcalssProc により Emacs のメッセージ処理が必ず呼ばれるようになる。"
212 | :type '(choice (const :tag "Enable" t)
213 | (const :tag "Disable" nil))
214 | :set #'tr-ime-isearch--defsubclassproc-set
215 | :group 'tr-ime-isearch-mode)
216 |
217 | ;;
218 | ;; アンロード
219 | ;;
220 |
221 | (defun tr-ime-isearch-unload-function ()
222 | "アンロードするため \"isearch-mode\" 設定を無効にする."
223 | (let (_dummy)
224 | (tr-ime-isearch--set '_dummy nil)
225 | (tr-ime-isearch--defsubclassproc-set '_dummy nil)))
226 |
227 | ;;
228 | ;; provide
229 | ;;
230 |
231 | (provide 'tr-ime-isearch)
232 |
233 | ;; Local Variables:
234 | ;; coding: utf-8
235 | ;; End:
236 |
237 | ;;; tr-ime-isearch.el ends here
238 |
--------------------------------------------------------------------------------
/lisp/tr-ime-openstatus.el:
--------------------------------------------------------------------------------
1 | ;;; tr-ime-openstatus.el --- IME openstatus functions -*- lexical-binding: t -*-
2 |
3 | ;; Copyright (C) 2020-2022 Masamichi Hosoda
4 |
5 | ;; Author: Masamichi Hosoda
6 | ;; URL: https://github.com/trueroad/tr-emacs-ime-module
7 |
8 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime)
9 | ;; is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 | ;;
14 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime)
15 | ;; is distributed in the hope that it will be useful,
16 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | ;; GNU General Public License for more details.
19 | ;;
20 | ;; You should have received a copy of the GNU General Public License
21 | ;; along with tr-ime.
22 | ;; If not, see .
23 |
24 | ;;; Commentary:
25 |
26 | ;; This file is part of
27 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime).
28 | ;; See tr-ime.el
29 |
30 | ;;; Code:
31 |
32 | ;;
33 | ;; ユーザ設定用
34 | ;;
35 |
36 | (defgroup tr-ime-core nil
37 | "コア機能設定.
38 |
39 | コア機能の設定です。通常は設定変更しないでください。"
40 | :group 'tr-ime)
41 |
42 | (defgroup tr-ime-openstatus nil
43 | "IME 状態変更・状態取得."
44 | :group 'tr-ime-core)
45 |
46 | ;;
47 | ;; Emacs 28 standard
48 | ;;
49 |
50 | (defcustom tr-ime-openstatus-emacs28-open-check-counter 10
51 | "GNU Emacs 28 の IME 状態変更関数使用後の状態確認回数上限 (standard).
52 |
53 | GNU Emacs 28 で standard の場合は
54 | IME 状態変更関数 \"w32-set-ime-open-status\" を使うが、
55 | これを呼んだ直後に IME 状態確認関数 \"w32-get-ime-open-status\" を呼んでも、
56 | 状態変更前を示す返り値が得られることがある。
57 | そこで、ここで設定した回数を上限として状態変更が完了するまで確認する。
58 | 例えば 3 に設定すると最大で 3 回確認するが、
59 | 1 回目や 2 回目で完了していたらそこで打ち切る。
60 | 0 を設定した場合は一切完了確認しない。"
61 | :type 'integer
62 | :group 'tr-ime-openstatus)
63 |
64 | (declare-function w32-set-ime-open-status "w32fns.c" (status)) ; Emacs 28
65 | (declare-function w32-get-ime-open-status "w32fns.c") ; Emacs 28
66 |
67 | (defun tr-ime-openstatus--get-mode-emacs28 ()
68 | "GNU Emacs 28 standard 向け ime-get-mode 実装.
69 |
70 | GNU Emacs 28 の \"w32-get-ime-open-status\" で
71 | IME パッチの ime-force-on をエミュレーションする。
72 | 選択されたフレームが w32 のときは、
73 | IME が OFF なら nil を、ON ならそれ以外を返す。
74 | 非 w32 のときは常に nil を返す。"
75 | (if (eq (framep (selected-frame)) 'w32)
76 | (w32-get-ime-open-status)
77 | nil))
78 |
79 | (defun tr-ime-openstatus--force-on-emacs28 (&optional _dummy)
80 | "GNU Emacs 28 standard 向け ime-force-on 実装.
81 |
82 | GNU Emacs 28 の \"w32-set-ime-open-status\" で
83 | IME パッチの ime-force-on をエミュレーションする。
84 | 選択されたフレームが w32 のときは IME が on になる。
85 | 非 w32 のときは何もしない。"
86 | (when (eq (framep (selected-frame)) 'w32)
87 | (w32-set-ime-open-status t)
88 | (let ((counter 0))
89 | (while (and (< counter tr-ime-openstatus-emacs28-open-check-counter)
90 | (not (w32-get-ime-open-status)))
91 | (thread-yield)
92 | (setq counter (1+ counter))))))
93 |
94 | (defun tr-ime-openstatus--force-off-emacs28 (&optional _dummy)
95 | "GNU Emacs 28 standard 向け ime-force-off 実装.
96 |
97 | GNU Emacs 28 の \"w32-set-ime-open-status\" で
98 | IME パッチの ime-force-off をエミュレーションする。
99 | 選択されたフレームが w32 のときは IME が off になる。
100 | 非 w32 のときは何もしない。"
101 | (when (eq (framep (selected-frame)) 'w32)
102 | (w32-set-ime-open-status nil)
103 | (let ((counter 0))
104 | (while (and (< counter tr-ime-openstatus-emacs28-open-check-counter)
105 | (w32-get-ime-open-status))
106 | (thread-yield)
107 | (setq counter (1+ counter))))))
108 |
109 | ;;
110 | ;; Emacs 27 standard
111 | ;;
112 |
113 | (declare-function tr-ime-mod--setopenstatus "tr-ime-mod"
114 | (arg1 arg2))
115 | (declare-function tr-ime-mod--getopenstatus "tr-ime-mod"
116 | (arg1))
117 |
118 | (defun tr-ime-openstatus--get-mode-emacs27 ()
119 | "GNU Emacs 27 standard 向け ime-get-mode 実装.
120 |
121 | C 実装モジュールで IME パッチの ime-get-mode をエミュレーションする。
122 | 選択されたフレームに window-id パラメータがある(w32 フレーム)ときは、
123 | IME が OFF なら nil を、ON ならそれ以外を返す。
124 | 無いときは常に nil を返す。"
125 | (let ((win-id (frame-parameter nil 'window-id)))
126 | (if win-id
127 | (tr-ime-mod--getopenstatus (string-to-number win-id))
128 | nil)))
129 |
130 | (defun tr-ime-openstatus--force-on-emacs27 (&optional _dummy)
131 | "GNU Emacs 27 standard 向け ime-force-on 実装.
132 |
133 | C 実装モジュールで IME パッチの ime-force-on をエミュレーションする。
134 | 選択されたフレームに window-id パラメータがある(w32 フレーム)ときは、
135 | IME が on になる。無いときは何もしない。"
136 | (let ((win-id (frame-parameter nil 'window-id)))
137 | (when win-id
138 | (tr-ime-mod--setopenstatus (string-to-number win-id) t))))
139 |
140 | (defun tr-ime-openstatus--force-off-emacs27 (&optional _dummy)
141 | "GNU Emacs 27 standard 向け ime-force-off 実装.
142 |
143 | C 実装モジュールで IME パッチの ime-force-off をエミュレーションする。
144 | 選択されたフレームに window-id パラメータがある(w32 フレーム)ときは、
145 | IME が off になる。無いときは何もしない。"
146 | (let ((win-id (frame-parameter nil 'window-id)))
147 | (when win-id
148 | (tr-ime-mod--setopenstatus (string-to-number win-id) nil))))
149 |
150 | ;;
151 | ;; advanced
152 | ;;
153 |
154 | (declare-function tr-ime-modadv--setopenstatus "tr-ime-modadv"
155 | (arg1 arg2))
156 | (declare-function tr-ime-modadv--getopenstatus "tr-ime-modadv"
157 | (arg1))
158 |
159 | (defun tr-ime-openstatus--get-mode-advanced ()
160 | "Advanced 向け ime-get-mode 実装.
161 |
162 | C++ 実装モジュールで IME パッチの ime-get-mode をエミュレーションする。
163 | 選択されたフレームに window-id パラメータがある(w32 フレーム)ときは、
164 | IME が OFF なら nil を、ON ならそれ以外を返す。
165 | 無いときは常に nil を返す。
166 | メッセージフックおよびサブクラス化が有効である必要がある。"
167 | (let ((win-id (frame-parameter nil 'window-id)))
168 | (if win-id
169 | (tr-ime-modadv--getopenstatus (string-to-number win-id))
170 | nil)))
171 |
172 | (defun tr-ime-openstatus--force-on-advanced (&optional _dummy)
173 | "Advanced 向け ime-force-on 実装.
174 |
175 | C++ 実装モジュールで IME パッチの ime-force-on をエミュレーションする。
176 | 選択されたフレームに window-id パラメータがある(w32 フレーム)ときは、
177 | IME が on になる。無いときは何もしない。
178 | メッセージフックおよびサブクラス化が有効である必要がある。"
179 | (let ((win-id (frame-parameter nil 'window-id)))
180 | (when win-id
181 | (tr-ime-modadv--setopenstatus (string-to-number win-id) t))))
182 |
183 | (defun tr-ime-openstatus--force-off-advanced (&optional _dummy)
184 | "Advanced 向け ime-force-off 実装.
185 |
186 | C++ 実装モジュールで IME パッチの ime-force-off をエミュレーションする。
187 | 選択されたフレームに window-id パラメータがある(w32 フレーム)ときは、
188 | IME が off になる。無いときは何もしない。
189 | メッセージフックおよびサブクラス化が有効である必要がある。"
190 | (let ((win-id (frame-parameter nil 'window-id)))
191 | (when win-id
192 | (tr-ime-modadv--setopenstatus (string-to-number win-id) nil))))
193 |
194 | ;;
195 | ;; define aliases
196 | ;;
197 |
198 | (defalias 'tr-ime-openstatus-get-mode
199 | (cond
200 | ((and (boundp 'tr-ime-enabled-features)
201 | (eq tr-ime-enabled-features 'advanced))
202 | #'tr-ime-openstatus--get-mode-advanced)
203 | ((fboundp #'w32-get-ime-open-status)
204 | #'tr-ime-openstatus--get-mode-emacs28)
205 | (t
206 | #'tr-ime-openstatus--get-mode-emacs27))
207 | "IME 状態を返す関数
208 |
209 | IME パッチの ime-get-mode 互換。
210 | IME が OFF なら nil を、ON ならそれ以外を返す。")
211 |
212 | (defalias 'tr-ime-openstatus-force-on
213 | (cond
214 | ((and (boundp 'tr-ime-enabled-features)
215 | (eq tr-ime-enabled-features 'advanced))
216 | #'tr-ime-openstatus--force-on-advanced)
217 | ((fboundp #'w32-set-ime-open-status)
218 | #'tr-ime-openstatus--force-on-emacs28)
219 | (t
220 | #'tr-ime-openstatus--force-on-emacs27))
221 | "IME を on にする関数
222 |
223 | IME パッチの ime-force-on 互換。")
224 |
225 | (defalias 'tr-ime-openstatus-force-off
226 | (cond
227 | ((and (boundp 'tr-ime-enabled-features)
228 | (eq tr-ime-enabled-features 'advanced))
229 | #'tr-ime-openstatus--force-off-advanced)
230 | ((fboundp #'w32-set-ime-open-status)
231 | #'tr-ime-openstatus--force-off-emacs28)
232 | (t
233 | #'tr-ime-openstatus--force-off-emacs27))
234 | "IME を off にする関数
235 |
236 | IME パッチの ime-force-on 互換。")
237 |
238 | ;;
239 | ;; define obsolete functions
240 | ;;
241 |
242 | (define-obsolete-function-alias 'ime-get-mode
243 | #'tr-ime-openstatus-get-mode "2020")
244 |
245 | (define-obsolete-function-alias 'ime-force-on
246 | #'tr-ime-openstatus-force-on "2020")
247 |
248 | (define-obsolete-function-alias 'ime-force-off
249 | #'tr-ime-openstatus-force-off "2020")
250 |
251 | ;;
252 | ;; provide
253 | ;;
254 |
255 | (provide 'tr-ime-openstatus)
256 |
257 | ;; Local Variables:
258 | ;; coding: utf-8
259 | ;; End:
260 |
261 | ;;; tr-ime-openstatus.el ends here
262 |
--------------------------------------------------------------------------------
/lisp/tr-ime-prefix-key.el:
--------------------------------------------------------------------------------
1 | ;;; tr-ime-prefix-key.el --- Handle prefix key -*- lexical-binding: t -*-
2 |
3 | ;; Copyright (C) 2020, 2022 Masamichi Hosoda
4 |
5 | ;; Author: Masamichi Hosoda
6 | ;; URL: https://github.com/trueroad/tr-emacs-ime-module
7 |
8 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime)
9 | ;; is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 | ;;
14 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime)
15 | ;; is distributed in the hope that it will be useful,
16 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | ;; GNU General Public License for more details.
19 | ;;
20 | ;; You should have received a copy of the GNU General Public License
21 | ;; along with tr-ime.
22 | ;; If not, see .
23 |
24 | ;;; Commentary:
25 |
26 | ;; This file is part of
27 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime).
28 | ;; See tr-ime.el
29 |
30 | ;;; Code:
31 |
32 | ;;
33 | ;; ユーザ設定用
34 | ;;
35 |
36 | (defgroup tr-ime-prefix-key nil
37 | "プレフィックスキー検出 (advanced)."
38 | :group 'tr-ime)
39 |
40 | ;;
41 | ;; 検出対象リスト
42 | ;;
43 |
44 | (declare-function tr-ime-modadv--set-prefix-keys "tr-ime-modadv"
45 | (arg1 arg2))
46 |
47 | (defvar tr-ime-prefix-key-p t)
48 |
49 | (defun tr-ime-prefix-key--list-set (symb settings)
50 | "プレフィックスキー検出対象リストを設定する.
51 |
52 | SYMB は tr-ime-prefix-key-list を指定する。
53 | SETTINGS はプレフィックスキーとして検出したいコードのリスト。"
54 | (set-default symb settings)
55 | (when tr-ime-prefix-key-p
56 | (tr-ime-modadv--set-prefix-keys
57 | (string-to-number (frame-parameter nil 'window-id))
58 | settings)))
59 |
60 | (defcustom tr-ime-prefix-key-list '(#x20058 #x20048 #x20043 #x1b)
61 | "プレフィックスキー検出対象リスト.
62 |
63 | この設定を変更する場合には \"custom-set-variables\" を使うこと。
64 |
65 | プレフィックスキーとして検出したいコードのリスト。
66 | コードは上位 16 bit が修飾キー、下位 16 bit が修飾されるキーの
67 | バーチャルキーコードを指定する。
68 | 修飾キーは Shift (#x10000), Ctrl (#x20000), Alt (#x40000) の
69 | ビット論理和で指定する。バーチャルキーコードは Windows のものを指定する。
70 |
71 | 例えば Ctrl-x は Ctrl の修飾キー #x20000 と、
72 | X キーのバーチャルキーコード #x58 のビット論理和なので #x20058 を指定する。
73 | Ctrl-Alt-x であれば、さらに Alt の修飾キーを含めて #x60058 を指定する。"
74 | :type '(repeat integer)
75 | :set #'tr-ime-prefix-key--list-set
76 | :group 'tr-ime-prefix-key)
77 |
78 | ;;
79 | ;; プレフィックスキー(C-x など)を検出して自動的に IME off する
80 | ;;
81 |
82 | (declare-function tr-ime-modadv--resume-prefix-key "tr-ime-modadv")
83 |
84 | (defun tr-ime-prefix-key--set (symb bool)
85 | "プレフィックスキーを検出して自動的に IME off するか否か設定する.
86 |
87 | SYMB には tr-ime-prefix-key-p を指定する。
88 | BOOL が non-nil ならプレフィックスキーを検出して IME off する。
89 | あわせて standard で同様な機能を持つワークアラウンドを無効にする。
90 | BOOL が nil なら停止する。"
91 | (if bool
92 | (when (and (boundp 'tr-ime-enabled-features)
93 | (eq tr-ime-enabled-features 'advanced))
94 | ;; ここで custom-set-variables を使うと init.el に
95 | ;; 設定が書き込まれてしまうので直接 setter を使って無効に設定する
96 | (when (fboundp 'tr-ime-workaround-prefix-key--set)
97 | (let (_dummy)
98 | (tr-ime-workaround-prefix-key--set '_dummy nil)))
99 | (tr-ime-modadv--set-prefix-keys
100 | (string-to-number (frame-parameter nil 'window-id))
101 | tr-ime-prefix-key-list)
102 | (add-hook 'pre-command-hook #'tr-ime-modadv--resume-prefix-key))
103 | (when (fboundp 'tr-ime-modadv--set-prefix-keys)
104 | (tr-ime-modadv--set-prefix-keys
105 | (string-to-number (frame-parameter nil 'window-id)) nil))
106 | (remove-hook 'pre-command-hook #'tr-ime-modadv--resume-prefix-key))
107 | (set-default symb bool))
108 |
109 | (defcustom tr-ime-prefix-key-p t
110 | "プレフィックスキーを検出して自動的に IME off するか否か.
111 |
112 | この設定を変更する場合には \"custom-set-variables\" を使うこと。
113 |
114 | コマンドのキーシーケンスになる最初のキーである
115 | プレフィックスキーを検出すると、
116 | 自動的に IME off にして、コマンド終了後に IME 状態を戻す機能。
117 |
118 | 本機能を有効にすると standard 用の
119 | プレフィックスキー検出ワークアラウンドが無効になる。"
120 | :type '(choice (const :tag "Enable" t)
121 | (const :tag "Disable" nil))
122 | :set #'tr-ime-prefix-key--set
123 | :group 'tr-ime-prefix-key)
124 |
125 | (defun tr-ime-prefix-key-unload-function ()
126 | "アンロードするためプレフィックスキー検出を無効にする."
127 | (let (_dummy)
128 | (tr-ime-prefix-key--set '_dummy nil)))
129 |
130 | ;;
131 | ;; provide
132 | ;;
133 |
134 | (provide 'tr-ime-prefix-key)
135 |
136 | ;; Local Variables:
137 | ;; coding: utf-8
138 | ;; End:
139 |
140 | ;;; tr-ime-prefix-key.el ends here
141 |
--------------------------------------------------------------------------------
/lisp/tr-ime-reconversion.el:
--------------------------------------------------------------------------------
1 | ;;; tr-ime-reconversion.el --- Reconversion -*- lexical-binding: t -*-
2 |
3 | ;; Copyright (C) 2020, 2022 Masamichi Hosoda
4 |
5 | ;; Author: Masamichi Hosoda
6 | ;; URL: https://github.com/trueroad/tr-emacs-ime-module
7 |
8 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime)
9 | ;; is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 | ;;
14 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime)
15 | ;; is distributed in the hope that it will be useful,
16 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | ;; GNU General Public License for more details.
19 | ;;
20 | ;; You should have received a copy of the GNU General Public License
21 | ;; along with tr-ime.
22 | ;; If not, see .
23 |
24 | ;;; Commentary:
25 |
26 | ;; This file is part of
27 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime).
28 | ;; See tr-ime.el
29 |
30 | ;;; Code:
31 |
32 | ;;
33 | ;; ユーザ設定用
34 | ;;
35 |
36 | (defgroup tr-ime-reconversion nil
37 | "再変換 (advanced)."
38 | :group 'tr-ime)
39 |
40 | ;;
41 | ;; 再変換 (RECONVERSION)
42 | ;;
43 |
44 | (declare-function tr-ime-modadv--notify-reconvert-string "tr-ime-modadv"
45 | (arg1 arg2 arg3))
46 |
47 | (defun tr-ime-reconversion--notify-reconvert-string ()
48 | "RECONVERTSTRING 構造体用の材料を収集して UI スレッドへ通知する.
49 |
50 | point のある行全体の文字列と、文字列中の point 位置を収集し、
51 | advanced の C++ 実装である tr-ime-modadv--notify-reconvert-string 関数を呼び、
52 | UI スレッドへ通知する。
53 | ノーマルフック tr-ime-modadv--reconvertstring-hook および
54 | tr-ime-modadv--documentfeed-hook に登録して使う。"
55 | (tr-ime-modadv--notify-reconvert-string
56 | (string-to-number (frame-parameter nil 'window-id))
57 | (buffer-substring-no-properties
58 | (line-beginning-position) (line-end-position))
59 | (- (point) (line-beginning-position))))
60 |
61 | ;;
62 | ;; 設定用
63 | ;;
64 |
65 | (declare-function tr-ime-modadv--set-reconversion "tr-ime-modadv"
66 | (arg1 arg2))
67 |
68 | (defun tr-ime-reconversion--set (symb bool)
69 | "再変換 (RECONVERSION) 動作を行うか否か設定する.
70 |
71 | SYMB には tr-ime-reconversion-p を指定する。
72 | BOOL が non-nil なら再変換動作を行う。
73 | そうでなければ行わない。"
74 | (if bool
75 | (when (and (boundp 'tr-ime-enabled-features)
76 | (eq tr-ime-enabled-features 'advanced))
77 | (add-hook 'tr-ime-modadv--reconvertstring-hook
78 | #'tr-ime-reconversion--notify-reconvert-string)
79 | (tr-ime-modadv--set-reconversion
80 | (string-to-number (frame-parameter nil 'window-id)) t))
81 | (when (fboundp 'tr-ime-modadv--set-reconversion)
82 | (tr-ime-modadv--set-reconversion
83 | (string-to-number (frame-parameter nil 'window-id)) nil))
84 | (remove-hook 'tr-ime-modadv--reconvertstring-hook
85 | #'tr-ime-reconversion--notify-reconvert-string))
86 | (set-default symb bool))
87 |
88 | (defcustom tr-ime-reconversion-p t
89 | "再変換 (RECONVERSION) 動作を行うか否か.
90 |
91 | この設定を変更する場合には \"custom-set-variables\" を使うこと。
92 |
93 | 確定済文字列にカーソルを置いて変換キーを押すと、
94 | カーソルのあった場所の確定済文字列が未確定文字列になって、
95 | 再変換できるようになる機能。"
96 | :type '(choice (const :tag "Enable" t)
97 | (const :tag "Disable" nil))
98 | :set #'tr-ime-reconversion--set
99 | :group 'tr-ime-reconversion)
100 |
101 | (defun tr-ime-reconversion-unload-function ()
102 | "アンロードするため再変換 (RECONVERSION) を無効にする."
103 | (let (_dummy)
104 | (tr-ime-reconversion--set '_dummy nil)))
105 |
106 | ;;
107 | ;; provide
108 | ;;
109 |
110 | (provide 'tr-ime-reconversion)
111 |
112 | ;; Local Variables:
113 | ;; coding: utf-8
114 | ;; End:
115 |
116 | ;;; tr-ime-reconversion.el ends here
117 |
--------------------------------------------------------------------------------
/lisp/tr-ime-recv-notify.el:
--------------------------------------------------------------------------------
1 | ;;; tr-ime-recv-notify.el --- Receive notify -*- lexical-binding: t -*-
2 |
3 | ;; Copyright (C) 2020, 2022 Masamichi Hosoda
4 |
5 | ;; Author: Masamichi Hosoda
6 | ;; URL: https://github.com/trueroad/tr-emacs-ime-module
7 |
8 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime)
9 | ;; is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 | ;;
14 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime)
15 | ;; is distributed in the hope that it will be useful,
16 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | ;; GNU General Public License for more details.
19 | ;;
20 | ;; You should have received a copy of the GNU General Public License
21 | ;; along with tr-ime.
22 | ;; If not, see .
23 |
24 | ;;; Commentary:
25 |
26 | ;; This file is part of
27 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime).
28 | ;; See tr-ime.el
29 |
30 | ;;; Code:
31 |
32 | ;;
33 | ;; ユーザ設定用
34 | ;;
35 |
36 | (defgroup tr-ime-core nil
37 | "コア機能設定.
38 |
39 | コア機能の設定です。通常は設定変更しないでください。"
40 | :group 'tr-ime)
41 |
42 | (defgroup tr-ime-recv-notify nil
43 | "UI スレッドからの通知 (advanced)."
44 | :group 'tr-ime-core)
45 |
46 | ;;
47 | ;; UI スレッドからの通知を Lisp で受け取る
48 | ;;
49 |
50 | (declare-function tr-ime-modadv--language-change-handler "tr-ime-modadv")
51 |
52 | (defun tr-ime-recv-notify--set (symb bool)
53 | "UI スレッドからの通知を Lisp で受け取るか否か設定する.
54 |
55 | SYMB は tr-ime-recv-notify-p を指定する。
56 | BOOL が non-nil なら UI スレッドからの通知を Lisp で受け取る。
57 | そうでなければ受け取らない。"
58 | (if bool
59 | (define-key special-event-map [language-change]
60 | (lambda ()
61 | (interactive)
62 | (tr-ime-modadv--language-change-handler)))
63 | (define-key special-event-map [language-change] 'ignore))
64 | (set-default symb bool))
65 |
66 | (defcustom tr-ime-recv-notify-p t
67 | "UI スレッドからの通知を Lisp で受け取るか否か.
68 |
69 | この設定を変更する場合には \"custom-set-variables\" を使うこと。
70 |
71 | 注意:advanced の一部の機能は
72 | UI スレッドからの通知を Lisp で受け取り、
73 | Lisp での処理結果が UI スレッドへ通知されるまで待つものがある。
74 | これらの機能が有効なまま本設定を無効にしてしまうと
75 | Lisp が通知を受け取れなくなり処理もされず、
76 | UI スレッドは返ってこない通知を待つため(一時的に)
77 | ロックしてしまうことがある。
78 | 特別な目的が無い限りは non-nil (Enable) にしておくこと。"
79 | :type '(choice (const :tag "Enable" t)
80 | (const :tag "Disable" nil))
81 | :set #'tr-ime-recv-notify--set
82 | :group 'tr-ime-recv-notify)
83 |
84 | (defun tr-ime-recv-notify-unload-function ()
85 | "アンロードするため UI スレッドからの通知を無効にする."
86 | (let (_dummy)
87 | (tr-ime-recv-notify--set '_dummy nil)))
88 |
89 | ;;
90 | ;; provide
91 | ;;
92 |
93 | (provide 'tr-ime-recv-notify)
94 |
95 | ;; Local Variables:
96 | ;; coding: utf-8
97 | ;; End:
98 |
99 | ;;; tr-ime-recv-notify.el ends here
100 |
--------------------------------------------------------------------------------
/lisp/tr-ime-subclassify.el:
--------------------------------------------------------------------------------
1 | ;;; tr-ime-subclassify.el --- Subclassify frame -*- lexical-binding: t -*-
2 |
3 | ;; Copyright (C) 2020, 2022 Masamichi Hosoda
4 |
5 | ;; Author: Masamichi Hosoda
6 | ;; URL: https://github.com/trueroad/tr-emacs-ime-module
7 |
8 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime)
9 | ;; is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 | ;;
14 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime)
15 | ;; is distributed in the hope that it will be useful,
16 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | ;; GNU General Public License for more details.
19 | ;;
20 | ;; You should have received a copy of the GNU General Public License
21 | ;; along with tr-ime.
22 | ;; If not, see .
23 |
24 | ;;; Commentary:
25 |
26 | ;; This file is part of
27 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime).
28 | ;; See tr-ime.el
29 |
30 | ;;; Code:
31 |
32 | ;;
33 | ;; ユーザ設定用
34 | ;;
35 |
36 | (defgroup tr-ime-core nil
37 | "コア機能設定.
38 |
39 | コア機能の設定です。通常は設定変更しないでください。"
40 | :group 'tr-ime)
41 |
42 | (defgroup tr-ime-subclassify nil
43 | "メッセージフックとサブクラス化 (advanced)."
44 | :group 'tr-ime-core)
45 |
46 | ;;
47 | ;; メッセージフックとサブクラス化
48 | ;;
49 |
50 | (declare-function tr-ime-modadv--install-message-hook-hwnd "tr-ime-modadv"
51 | (arg1))
52 | (declare-function tr-ime-modadv--uninstall-message-hook-hwnd "tr-ime-modadv"
53 | (arg1))
54 | (declare-function tr-ime-modadv--subclassify-hwnd "tr-ime-modadv"
55 | (arg1 &optional arg2))
56 | (declare-function tr-ime-modadv--unsubclassify-hwnd "tr-ime-modadv"
57 | (&optional arg1 arg2))
58 | (declare-function tr-ime-modadv--exists-subclassified "tr-ime-modadv")
59 |
60 | (defun tr-ime-subclassify--set (symb bool)
61 | "IME 制御のためメッセージフックしてサブクラス化するか否か設定する.
62 |
63 | SYMB は tr-ime-subclassify-p を指定する。
64 | BOOL が non-nil ならメッセージフックしてサブクラス化する。
65 | そうでなければサブクラス解除してメッセージフックを停止する。
66 |
67 | 注意:advanced のほとんどの機能は
68 | メッセージフックとサブクラス化を前提としており、
69 | これらが有効でなければ機能しないだけではなく、
70 | 設定変更すらできないものも存在する。"
71 | (if bool
72 | (progn
73 | (tr-ime-modadv--install-message-hook-hwnd
74 | (string-to-number (frame-parameter nil 'window-id)))
75 | (tr-ime-modadv--subclassify-hwnd
76 | (string-to-number (frame-parameter nil 'window-id)) nil))
77 | (tr-ime-modadv--unsubclassify-hwnd
78 | (string-to-number (frame-parameter nil 'window-id)) nil)
79 | ;; サブクラス解除は非同期に実施されるが、
80 | ;; 解除前にメッセージフック停止すると解除できなくなるので
81 | ;; 存在確認し待機する。
82 | (let ((counter 0))
83 | (while (and (< counter 10)
84 | (tr-ime-modadv--exists-subclassified))
85 | (thread-yield)
86 | (setq counter (1+ counter))))
87 | (tr-ime-modadv--uninstall-message-hook-hwnd
88 | (string-to-number (frame-parameter nil 'window-id))))
89 | (set-default symb bool))
90 |
91 | (defcustom tr-ime-subclassify-p t
92 | "IME 制御のためメッセージフックしてサブクラス化するか否か.
93 |
94 | この設定を変更する場合には \"custom-set-variables\" を使うこと。
95 |
96 | 注意:advanced のほとんどの機能は
97 | メッセージフックとサブクラス化を前提としており、
98 | これらが有効でなければ機能しないだけではなく、
99 | 設定変更すらできないものが存在する。
100 | 特別な目的が無い限りは non-nil (Enable) にしておくこと。"
101 | :type '(choice (const :tag "Enable" t)
102 | (const :tag "Disable" nil))
103 | :set #'tr-ime-subclassify--set
104 | :group 'tr-ime-subclassify)
105 |
106 | (defun tr-ime-subclassify-unload-function ()
107 | "アンロードするためメッセージフックとサブクラス化を無効にする."
108 | (let (_dummy)
109 | (tr-ime-subclassify--set '_dummy nil)))
110 |
111 | ;;
112 | ;; provide
113 | ;;
114 |
115 | (provide 'tr-ime-subclassify)
116 |
117 | ;; Local Variables:
118 | ;; coding: utf-8
119 | ;; End:
120 |
121 | ;;; tr-ime-subclassify.el ends here
122 |
--------------------------------------------------------------------------------
/lisp/tr-ime-sync.el:
--------------------------------------------------------------------------------
1 | ;;; tr-ime-sync.el --- Sync IME openstatus -*- lexical-binding: t -*-
2 |
3 | ;; Copyright (C) 2020, 2022 Masamichi Hosoda
4 |
5 | ;; Author: Masamichi Hosoda
6 | ;; URL: https://github.com/trueroad/tr-emacs-ime-module
7 |
8 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime)
9 | ;; is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 | ;;
14 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime)
15 | ;; is distributed in the hope that it will be useful,
16 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | ;; GNU General Public License for more details.
19 | ;;
20 | ;; You should have received a copy of the GNU General Public License
21 | ;; along with tr-ime.
22 | ;; If not, see .
23 |
24 | ;;; Commentary:
25 |
26 | ;; This file is part of
27 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime).
28 | ;; See tr-ime.el
29 |
30 | ;;; Code:
31 |
32 | ;;
33 | ;; requires
34 | ;;
35 |
36 | (require 'tr-ime-hook)
37 | (require 'tr-ime-openstatus)
38 |
39 | ;;
40 | ;; ユーザ設定用
41 | ;;
42 |
43 | (defgroup tr-ime-sync nil
44 | "IME 状態変更通知による IME/IM 状態同期 (advanced)."
45 | :group 'tr-ime)
46 |
47 | ;;
48 | ;; 状態同期
49 | ;;
50 |
51 | (defun tr-ime-sync--setopenstatus ()
52 | "IME 状態変更通知時に呼ばれる関数.
53 |
54 | まずフックエミュレーション関数を呼び、
55 | これによってウィンドウやバッファの切り替え未検出があったら、
56 | アブノーマルフックが呼ばれて、IME/IM 状態が整える。
57 |
58 | その上で IME 状態と IM 状態が食い違ったら IM 状態を反転して一致させる。
59 | これにより、IME 側トリガの状態変更を IM に反映させる。"
60 | (tr-ime-hook-check)
61 | (let ((ime-status (tr-ime-openstatus-get-mode)))
62 | (cond ((and ime-status
63 | (not current-input-method))
64 | (activate-input-method "W32-IME"))
65 | ((and (not ime-status)
66 | current-input-method)
67 | (deactivate-input-method)))))
68 |
69 | ;;
70 | ;; 設定用
71 | ;;
72 |
73 | (defun tr-ime-sync--set (symb bool)
74 | "IME 状態変更通知による IM 状態同期をするか否か設定する.
75 |
76 | SYMB には tr-ime-sync-p を指定する。
77 | BOOL が non-nil なら IME 状態変更通知による IM 状態同期をする。
78 | そうでなければ同期しない。"
79 | (if bool
80 | (progn
81 | ;; ここで custom-set-variables を使うと init.el に
82 | ;; 設定が書き込まれてしまうので直接 setter を使って無効に設定する
83 | (when (fboundp 'tr-ime-workaround-inconsistent--set)
84 | (let (_dummy)
85 | (tr-ime-workaround-inconsistent--set '_dummy nil)))
86 | (add-hook 'tr-ime-modadv--setopenstatus-hook
87 | #'tr-ime-sync--setopenstatus))
88 | (remove-hook 'tr-ime-modadv--setopenstatus-hook
89 | #'tr-ime-sync--setopenstatus))
90 | (set-default symb bool))
91 |
92 | (defcustom tr-ime-sync-p t
93 | "IME 状態変更通知による IM 状態同期をするか否か.
94 |
95 | この設定を変更する場合には \"custom-set-variables\" を使うこと。
96 |
97 | Emacs 側トリガ(C-\\ やウィンドウ・バッファの切り替えなど)だけでなく、
98 | IME 側トリガ(半角/全角キーやマウスでの切り替えなど)も含め、
99 | IME 状態変更通知がきた時に、IME/IM 状態同期をする機能。
100 |
101 | 本機能を有効にすると standard 用の
102 | IME 状態食い違い検出ワークアラウンドが無効になる。"
103 | :type '(choice (const :tag "Enable" t)
104 | (const :tag "Disable" nil))
105 | :set #'tr-ime-sync--set
106 | :group 'tr-ime-sync)
107 |
108 | (defun tr-ime-sync-unload-function ()
109 | "アンロードするため IME 状態変更通知による IM 状態同期を無効にする."
110 | (let (_dummy)
111 | (tr-ime-sync--set '_dummy nil)))
112 |
113 | ;;
114 | ;; provide
115 | ;;
116 |
117 | (provide 'tr-ime-sync)
118 |
119 | ;; Local Variables:
120 | ;; coding: utf-8
121 | ;; End:
122 |
123 | ;;; tr-ime-sync.el ends here
124 |
--------------------------------------------------------------------------------
/lisp/tr-ime-thread-message.el:
--------------------------------------------------------------------------------
1 | ;;; tr-ime-thread-message.el --- Thread message -*- lexical-binding: t -*-
2 |
3 | ;; Copyright (C) 2020, 2022 Masamichi Hosoda
4 |
5 | ;; Author: Masamichi Hosoda
6 | ;; URL: https://github.com/trueroad/tr-emacs-ime-module
7 |
8 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime)
9 | ;; is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 | ;;
14 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime)
15 | ;; is distributed in the hope that it will be useful,
16 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | ;; GNU General Public License for more details.
19 | ;;
20 | ;; You should have received a copy of the GNU General Public License
21 | ;; along with tr-ime.
22 | ;; If not, see .
23 |
24 | ;;; Commentary:
25 |
26 | ;; This file is part of
27 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime).
28 | ;; See tr-ime.el
29 |
30 | ;;; Code:
31 |
32 | ;;
33 | ;; ユーザ設定用
34 | ;;
35 |
36 | (defgroup tr-ime-core nil
37 | "コア機能設定.
38 |
39 | コア機能の設定です。通常は設定変更しないでください。"
40 | :group 'tr-ime)
41 |
42 | (defgroup tr-ime-thread-message nil
43 | "スレッドメッセージ (advanced)."
44 | :group 'tr-ime-core)
45 |
46 | ;;
47 | ;; スレッドメッセージのディスパッチ
48 | ;;
49 |
50 | (declare-function tr-ime-modadv--set-dispatch-thread-message "tr-ime-modadv"
51 | (arg1))
52 | (declare-function tr-ime-modadv--set-dispatch-thread-wm-timer "tr-ime-modadv"
53 | (arg1))
54 | (defvar tr-ime-thread-message-dispatch-p)
55 | (defvar tr-ime-thread-message-dispatch-wm-timer-p)
56 |
57 | (defun tr-ime-thread-message--dispatch-set (symb bool)
58 | "すべてのスレッドメッセージをディスパッチするか否か設定する.
59 |
60 | SYMB は tr-ime-thread-message-dispatch-p を設定する。
61 | BOOL が non-nil ならすべてのスレッドメッセージをディスパッチする。
62 | そうでなければディスパッチしない。
63 |
64 | 本関数の設定より
65 | tr-ime-thread-message--dispatch-wm-timer-set 関数の設定が優先される。
66 | 本関数による設定を有効にしたい場合は
67 | tr-ime-thread-message--dispatch-wm-timer-set の BOOL を
68 | nil にする必要がある。
69 |
70 | GNU Emacs 27 や 28 の UI スレッドは、
71 | スレッドメッセージをディスパッチしないため IME の動作に不具合が発生する
72 | (タスクトレイの IME 状態表示アイコンが変わらない等)。
73 | そこで、本設定によって Emacs の代わりにメッセージフックが
74 | スレッドメッセージをディスパッチするようにできる。
75 |
76 | 大抵の場合はすべてのスレッドメッセージではなく
77 | WM_TIMER だけをディスパッチすればよいので、本関数ではなく
78 | tr-ime-thread-message--dispatch-wm-timer-set を使った方が良い。
79 | WM_TIMER だけではうまくいかないときに本関数を使う。
80 |
81 | ただし、将来の Emacs でスレッドメッセージをディスパッチするように修正されたら
82 | 本設定を nil にすること。
83 | さもなければひとつのスレッドメッセージを
84 | 二重にディスパッチしてしまうことになり、
85 | Emacs の動作がおかしくなってしまう。"
86 | (if (and (boundp 'tr-ime-thread-message-dispatch-wm-timer-p)
87 | (not tr-ime-thread-message-dispatch-wm-timer-p))
88 | (tr-ime-modadv--set-dispatch-thread-message bool)
89 | (tr-ime-modadv--set-dispatch-thread-message nil))
90 | (set-default symb bool))
91 |
92 | (defun tr-ime-thread-message--dispatch-wm-timer-set (symb bool)
93 | "スレッドメッセージ WM_TIMER をディスパッチするか否か設定する.
94 |
95 | SYMB は tr-ime-thread-message-dispatch-wm-timer-p を設定する。
96 | BOOL が non-nil ならスレッドメッセージ WM_TIMER をディスパッチして
97 | WM_NULL にすり替えて握りつぶす。そうでなければしない。
98 |
99 | 本関数の設定は tr-ime-thread-message--dispatch-set よりも優先する。
100 | tr-ime-thread-message--dispatch-set 関数による設定を有効にしたい場合は
101 | 本関数の BOOL を nil にする必要がある。
102 |
103 | GNU Emacs 27 や 28 の UI スレッドは、
104 | スレッドメッセージをディスパッチしないため IME の動作に不具合が発生する
105 | (タスクトレイの IME 状態表示アイコンが変わらない等)。
106 | そこで、本設定によって Emacs の代わりにメッセージフックが
107 | スレッドメッセージ WM_TIMER をディスパッチするようにできる。
108 |
109 | 大抵の場合はすべてのスレッドメッセージではなく
110 | WM_TIMER だけをディスパッチすればよい。
111 | また、WM_NULL にすり替えて握りつぶすことにより
112 | 将来の Emacs でスレッドメッセージをディスパッチするように
113 | 修正されても二重ディスパッチにならないようにしている。
114 |
115 | WM_TIMER だけではうまくいかない時には本関数の BOOL を nil にして
116 | tr-ime-thread-message--dispatch-set を使って
117 | すべてのスレッドメッセージをディスパッチするとよいかもしれない。"
118 | (let (_dummy)
119 | (if bool
120 | (tr-ime-thread-message--dispatch-set '_dummy nil)
121 | (if (boundp 'tr-ime-thread-message-dispatch-p)
122 | (tr-ime-thread-message--dispatch-set
123 | '_dummy tr-ime-thread-message-dispatch-p))))
124 | (tr-ime-modadv--set-dispatch-thread-wm-timer bool)
125 | (set-default symb bool))
126 |
127 | (defcustom tr-ime-thread-message-dispatch-p nil
128 | "すべてのスレッドメッセージをディスパッチするか否か.
129 |
130 | この設定を変更する場合には \"custom-set-variables\" を使うこと。
131 |
132 | 本設定より
133 | tr-ime-thread-message--dispatch-wm-timer-p 設定が優先される。
134 | 本設定を有効にしたい場合は
135 | tr-ime-thread-message--dispatch-wm-timer-p を nil にする必要がある。
136 |
137 | GNU Emacs 27 や 28 の UI スレッドは、
138 | スレッドメッセージがディスパッチされない。
139 | これによって IME の動作に不具合が発生する
140 | (タスクトレイの IME 状態表示アイコンが変わらない等)。
141 | そこで、本設定によってメッセージフックが
142 | スレッドメッセージをディスパッチするようにできる。
143 |
144 | 大抵の場合はすべてのスレッドメッセージではなく
145 | WM_TIMER だけをディスパッチすればよいので、本設定ではなく
146 | tr-ime-thread-message-dispatch-wm-timer-p を使った方が良い。
147 | WM_TIMER だけではうまくいかないときに本設定を使う。
148 |
149 | ただし、将来の Emacs で
150 | スレッドメッセージをディスパッチするようになったら
151 | 本設定を nil (Disable) にすること。
152 | さもなければひとつのスレッドメッセージを
153 | 二重にディスパッチしてしまうことになり、
154 | Emacs の動作がおかしくなってしまう。"
155 | :type '(choice (const :tag "Enable" t)
156 | (const :tag "Disable" nil))
157 | :set #'tr-ime-thread-message--dispatch-set
158 | :group 'tr-ime-thread-message)
159 |
160 | (defcustom tr-ime-thread-message-dispatch-wm-timer-p t
161 | "スレッドメッセージ WM_TIMER をディスパッチするか否か.
162 |
163 | この設定を変更する場合には \"custom-set-variables\" を使うこと。
164 |
165 | 本設定は tr-ime-thread-message--dispatch-p よりも優先する。
166 | tr-ime-thread-message--dispatch-p の設定を有効にしたい場合は
167 | 本設定 を nil にする必要がある。
168 |
169 | GNU Emacs 27 や 28 の UI スレッドは、
170 | スレッドメッセージがディスパッチされない。
171 | これによって IME の動作に不具合が発生する
172 | (タスクトレイの IME 状態表示アイコンが変わらない等)。
173 | そこで、本設定によってメッセージフックが
174 | スレッドメッセージ WM_TIMER をディスパッチするようにできる。
175 |
176 | 大抵の場合はすべてのスレッドメッセージではなく
177 | WM_TIMER だけをディスパッチすればよい。
178 | また、WM_NULL にすり替えて握りつぶすことにより
179 | 将来の Emacs でスレッドメッセージをディスパッチするように
180 | 修正されても二重ディスパッチにならないようにしている。
181 |
182 | WM_TIMER だけではうまくいかない時には本設定を nil にして
183 | tr-ime-thread-message-dispatch-p を使って
184 | すべてのスレッドメッセージをディスパッチするとよいかもしれない。"
185 | :type '(choice (const :tag "Enable" t)
186 | (const :tag "Disable" nil))
187 | :set #'tr-ime-thread-message--dispatch-wm-timer-set
188 | :group 'tr-ime-thread-message)
189 |
190 | (defun tr-ime-thread-message-unload-function ()
191 | "アンロードするためスレッドメッセージのディスパッチを無効にする."
192 | (let (_dummy)
193 | (tr-ime-thread-message--dispatch-set '_dummy nil)
194 | (tr-ime-thread-message--dispatch-wm-timer-set '_dummy nil)))
195 |
196 | ;;
197 | ;; provide
198 | ;;
199 |
200 | (provide 'tr-ime-thread-message)
201 |
202 | ;; Local Variables:
203 | ;; coding: utf-8
204 | ;; End:
205 |
206 | ;;; tr-ime-thread-message.el ends here
207 |
--------------------------------------------------------------------------------
/lisp/tr-ime-workaround-inconsistent.el:
--------------------------------------------------------------------------------
1 | ;;; tr-ime-workaround-inconsistent.el --- Fix inconsistent workaround -*- lexical-binding: t -*-
2 |
3 | ;; Copyright (C) 2020, 2022 Masamichi Hosoda
4 |
5 | ;; Author: Masamichi Hosoda
6 | ;; URL: https://github.com/trueroad/tr-emacs-ime-module
7 |
8 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime)
9 | ;; is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 | ;;
14 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime)
15 | ;; is distributed in the hope that it will be useful,
16 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | ;; GNU General Public License for more details.
19 | ;;
20 | ;; You should have received a copy of the GNU General Public License
21 | ;; along with tr-ime.
22 | ;; If not, see .
23 |
24 | ;;; Commentary:
25 |
26 | ;; This file is part of
27 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime).
28 | ;; See tr-ime.el
29 |
30 | ;;; Code:
31 |
32 | ;;
33 | ;; requires
34 | ;;
35 |
36 | (require 'tr-ime-openstatus)
37 | (require 'tr-ime-hook)
38 |
39 | ;;
40 | ;; ユーザ設定用
41 | ;;
42 |
43 | (defgroup tr-ime-workaround nil
44 | "ワークアラウンド設定."
45 | :group 'tr-ime)
46 |
47 | (defgroup tr-ime-workaround-inconsistent nil
48 | "IME 状態食い違い検出 (standard)
49 |
50 | advanced では、このワークアラウンドではなく、
51 | advanced の IME 状態変更通知による IM 状態同期を使うこと。"
52 | :group 'tr-ime-workaround)
53 |
54 | ;;
55 | ;; IME 状態の食い違いを検出して修正するワークアラウンド
56 | ;;
57 |
58 | (defcustom tr-ime-workaround-inconsistentent-polling-time 1.0
59 | "IME 状態食い違い検出修正ワークアラウンド用ポーリング時間(秒)."
60 | :type 'float
61 | :group 'tr-ime-workaround-inconsistent)
62 |
63 | (defvar tr-ime-workaround-inconsistent--timer nil
64 | "IME 状態食い違い検出修正ワークアラウンド用タイマ.")
65 |
66 | (defun tr-ime-workaround-inconsistent--polling-handler ()
67 | "IME 状態食い違い検出修正ワークアラウンドのためのポーリングで呼ばれる関数.
68 |
69 | まずフックエミュレーション関数を呼ぶ。
70 | これによってウィンドウやバッファの切り替え未検出があったら、
71 | アブノーマルフックが呼ばれて、IME/IM 状態が整えられる。
72 |
73 | その上で IME 状態と IM 状態が食い違ったら IM 状態を反転して一致させる。
74 | これにより、IME 側トリガの状態変更を IM に反映させる。"
75 | (tr-ime-hook-check)
76 | (let ((ime-status (tr-ime-openstatus-get-mode)))
77 | (cond ((and ime-status
78 | (not current-input-method))
79 | (activate-input-method "W32-IME"))
80 | ((and (not ime-status)
81 | current-input-method)
82 | (deactivate-input-method)))))
83 |
84 | ;;
85 | ;; 設定用
86 | ;;
87 |
88 | (defun tr-ime-workaround-inconsistent--set (symb bool)
89 | "IME 状態食い違い検出修正ワークアラウンドを動作させるか否か設定する.
90 |
91 | SYMB は tr-ime-workaround-inconsistent-p を指定すること。
92 | BOOL が non-nil ならワークアラウンド有効で動作する。
93 | そうでなければワークアラウンド無効で動作しない。"
94 | (when tr-ime-workaround-inconsistent--timer
95 | (cancel-timer tr-ime-workaround-inconsistent--timer)
96 | (setq tr-ime-workaround-inconsistent--timer nil))
97 | (when (and bool
98 | (boundp 'tr-ime-enabled-features)
99 | (eq tr-ime-enabled-features 'standard))
100 | (setq tr-ime-workaround-inconsistent--timer
101 | (run-at-time
102 | t tr-ime-workaround-inconsistentent-polling-time
103 | #'tr-ime-workaround-inconsistent--polling-handler)))
104 | (set-default symb bool))
105 |
106 | (defcustom tr-ime-workaround-inconsistent-p t
107 | "IME 状態食い違い検出修正ワークアラウンドを動作させるか否か.
108 |
109 | この設定を変更する場合には \"custom-set-variables\" を使うこと。
110 |
111 | IME 側トリガの状態変更(半角/全角キーやマウスでの切り替え)を
112 | 定期的なタイマによるポーリングで検出して IM 側を同期させるための機構。"
113 | :type '(choice (const :tag "Enable" t)
114 | (const :tag "Disable" nil))
115 | :set #'tr-ime-workaround-inconsistent--set
116 | :group 'tr-ime-workaround-inconsistent)
117 |
118 | (defun tr-ime-workaround-inconsistent-unload-function ()
119 | "アンロードするため IME 状態食い違い検出修正ワークアラウンドを無効にする."
120 | (let (_dummy)
121 | (tr-ime-workaround-inconsistent--set '_dummy nil)))
122 |
123 | ;;
124 | ;; provide
125 | ;;
126 |
127 | (provide 'tr-ime-workaround-inconsistent)
128 |
129 | ;; Local Variables:
130 | ;; coding: utf-8
131 | ;; End:
132 |
133 | ;;; tr-ime-workaround-inconsistent.el ends here
134 |
--------------------------------------------------------------------------------
/lisp/tr-ime-workaround-isearch.el:
--------------------------------------------------------------------------------
1 | ;;; tr-ime-workaround-isearch.el --- Workaround isearch-mode -*- lexical-binding: t -*-
2 |
3 | ;; Copyright (C) 2020, 2022 Masamichi Hosoda
4 |
5 | ;; Author: Masamichi Hosoda
6 | ;; URL: https://github.com/trueroad/tr-emacs-ime-module
7 |
8 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime)
9 | ;; is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 | ;;
14 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime)
15 | ;; is distributed in the hope that it will be useful,
16 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | ;; GNU General Public License for more details.
19 | ;;
20 | ;; You should have received a copy of the GNU General Public License
21 | ;; along with tr-ime.
22 | ;; If not, see .
23 |
24 | ;;; Commentary:
25 |
26 | ;; This file is part of
27 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime).
28 | ;; See tr-ime.el
29 |
30 | ;;; Code:
31 |
32 | ;;
33 | ;; ユーザ設定用
34 | ;;
35 |
36 | (defgroup tr-ime-workaround nil
37 | "ワークアラウンド設定."
38 | :group 'tr-ime)
39 |
40 | (defgroup tr-ime-workaround-isearch nil
41 | "\"isearch-mode\" (advanced)."
42 | :group 'tr-ime-workaround)
43 |
44 | ;;
45 | ;; isearch-mode 時の Alt + 半角/全角ワークアラウンド
46 | ;;
47 |
48 | (defcustom tr-ime-workaround-isearch-delayed-update-time 0.0001
49 | "Alt + 半角/全角ワークアラウンドで使うタイマの待ち時間(秒)."
50 | :type 'float
51 | :group 'tr-ime-workaround-isearch)
52 |
53 | (defun tr-ime-workaround-isearch--delayed-update ()
54 | "アイドル状態になったら \"isearch-mode\" のエコーエリアを再表示する.
55 |
56 | advanced で \"isearch-mode\" 時に Alt + 半角/全角キー操作をすると、
57 | なぜかエコーエリアが消えてしまう。
58 | キー操作時に再表示させても効果が無い
59 | (恐らくキー操作後にくるイベントか何かで消されている)ので、
60 | Emacs がアイドル状態になったら動作するタイマで再表示させる。"
61 | (interactive)
62 | (run-with-idle-timer tr-ime-workaround-isearch-delayed-update-time
63 | nil #'isearch-update))
64 |
65 | (defun tr-ime-workaround-isearch--delayed-update-set (symb bool)
66 | "Alt + 半角/全角ワークアラウンドを動作させるか否か設定.
67 |
68 | advanced で \"isearch-mode\" 時に Alt + 半角/全角キー操作をすると、
69 | なぜかエコーエリアが消えてしまう対策のワークアラウンドを動作させるか否か
70 | 設定する。
71 |
72 | SYMB には tr-ime-workaround-isearch-delayed-update-p を指定する。
73 | BOOL が non-nil なら動作させる。それ以外なら停止させる。"
74 | (if bool
75 | (define-key isearch-mode-map [M-kanji]
76 | 'tr-ime-workaround-isearch--delayed-update)
77 | (define-key isearch-mode-map [M-kanji] 'ignore))
78 | (set-default symb bool))
79 |
80 | (defcustom tr-ime-workaround-isearch-delayed-update-p t
81 | "Alt + 半角/全角ワークアラウンドを動作させるか否か.
82 |
83 | この設定を変更する場合には \"custom-set-variables\" を使うこと。
84 |
85 | advanced で \"isearch-mode\" 時に Alt + 半角/全角キー操作をすると、
86 | なぜかエコーエリアが消えてしまう。
87 | キー操作時に再表示させても効果が無い
88 | (恐らくキー操作後にくるイベントか何かで消されている)ので、
89 | Emacs がアイドル状態になったら動作するタイマで再表示させるワークアラウンド。"
90 | :type '(choice (const :tag "Enable" t)
91 | (const :tag "Disable" nil))
92 | :set #'tr-ime-workaround-isearch--delayed-update-set
93 | :group 'tr-ime-workaround-isearch)
94 |
95 | (defun tr-ime-workaround-isearch-unload-function ()
96 | "アンロードするため \"isearch-mode\" ワークアラウンドを無効にする."
97 | (let (_dummy)
98 | (tr-ime-workaround-isearch--delayed-update-set '_dummy nil)))
99 |
100 | ;;
101 | ;; provide
102 | ;;
103 |
104 | (provide 'tr-ime-workaround-isearch)
105 |
106 | ;; Local Variables:
107 | ;; coding: utf-8
108 | ;; End:
109 |
110 | ;;; tr-ime-workaround-isearch.el ends here
111 |
--------------------------------------------------------------------------------
/lisp/tr-ime-workaround-prefix-key.el:
--------------------------------------------------------------------------------
1 | ;;; tr-ime-workaround-prefix-key.el --- Prefix key workaround -*- lexical-binding: t -*-
2 |
3 | ;; Copyright (C) 2020, 2022 Masamichi Hosoda
4 |
5 | ;; Author: Masamichi Hosoda
6 | ;; URL: https://github.com/trueroad/tr-emacs-ime-module
7 |
8 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime)
9 | ;; is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 | ;;
14 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime)
15 | ;; is distributed in the hope that it will be useful,
16 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | ;; GNU General Public License for more details.
19 | ;;
20 | ;; You should have received a copy of the GNU General Public License
21 | ;; along with tr-ime.
22 | ;; If not, see .
23 |
24 | ;;; Commentary:
25 |
26 | ;; This file is part of
27 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime).
28 | ;; See tr-ime.el
29 |
30 | ;;; Code:
31 |
32 | ;;
33 | ;; require
34 | ;;
35 |
36 | (require 'tr-ime-openstatus)
37 |
38 | ;;
39 | ;; ユーザ設定用
40 | ;;
41 |
42 | (defgroup tr-ime-workaround nil
43 | "ワークアラウンド設定."
44 | :group 'tr-ime)
45 |
46 | (defgroup tr-ime-workaround-prefix-key nil
47 | "プレフィックスキー検出 (standard)
48 |
49 | advanced では、このワークアラウンドではなく、
50 | advanced のプレフィックスキー検出を使うこと。"
51 | :group 'tr-ime-workaround)
52 |
53 | ;;
54 | ;; プレフィックスキー(C-x など)を検出して IME OFF するワークアラウンド
55 | ;;
56 |
57 | (defcustom tr-ime-workaround-prefix-key-polling-time 0.1
58 | "ポーリング時間(秒)."
59 | :type 'float
60 | :group 'tr-ime-workaround-prefix-key)
61 |
62 | (defcustom tr-ime-workaround-prefix-key-list '(?\C-x ?\C-h ?\C-c ?\e)
63 | "検出対象リスト.
64 |
65 | プレフィックスキーとして検出したいキーのリスト。"
66 | :type '(repeat integer)
67 | :group 'tr-ime-workaround-prefix-key)
68 |
69 | (defvar tr-ime-workaround-prefix-key--detected-p nil
70 | "プレフィックスキー検出フラグ.")
71 | (defvar tr-ime-workaround-prefix-key--before-ime-mode-p nil
72 | "プレフィックスキー検出時の IME 状態保存用.")
73 | (defvar tr-ime-workaround-prefix-key--timer nil
74 | "プレフィックスキー検出用タイマ.")
75 |
76 | (defun tr-ime-workaround-prefix-key--polling-handler ()
77 | "プレフィックスキー検出のためのポーリングで呼ばれる関数.
78 |
79 | 未検出かつ最後に押されたキーが検出対象リストのいずれかだったら、
80 | IME 状態を保存してから IME off にし、フラグを検出済にする。"
81 | (unless tr-ime-workaround-prefix-key--detected-p
82 | (let ((keys (this-single-command-keys)))
83 | (when (and (not (equal [] keys))
84 | (member (aref keys 0) tr-ime-workaround-prefix-key-list))
85 | (setq tr-ime-workaround-prefix-key--before-ime-mode-p
86 | (tr-ime-openstatus-get-mode))
87 | (tr-ime-openstatus-force-off)
88 | (setq tr-ime-workaround-prefix-key--detected-p t)))))
89 |
90 | (defun tr-ime-workaround-prefix-key--restore-ime-mode ()
91 | "自動 IME off から IME 状態を復帰させる関数.
92 |
93 | Emacs の標準的なフックの一つ \"pre-command-hook\" に登録する。
94 | \"pre-command-hook\" によって、ほとんどのコマンドの動作後に呼ばれる。
95 |
96 | この関数の動作は、
97 | プレフィックスキー検出済であったら未検出に変え、
98 | 検出時の IME 状態が on であれば IME on に復帰する。
99 | 未検出であったら何もしない。"
100 | (when tr-ime-workaround-prefix-key--detected-p
101 | (setq tr-ime-workaround-prefix-key--detected-p nil)
102 | (when tr-ime-workaround-prefix-key--before-ime-mode-p
103 | (tr-ime-openstatus-force-on))))
104 |
105 | ;;
106 | ;; 設定用
107 | ;;
108 |
109 | (defun tr-ime-workaround-prefix-key--set (symb bool)
110 | "プレフィックスキー検出ワークアラウンドを動作させるか否か設定する.
111 |
112 | SYMB は tr-ime-workaround-prefix-key-p を指定すること。
113 | BOOL が non-nil ならワークアラウンド有効で動作する。
114 | そうでなければワークアラウンド無効で動作しない。"
115 | (if bool
116 | (when (and (boundp 'tr-ime-enabled-features)
117 | (eq tr-ime-enabled-features 'standard))
118 | (setq tr-ime-workaround-prefix-key--detected-p nil)
119 | (add-hook 'pre-command-hook
120 | #'tr-ime-workaround-prefix-key--restore-ime-mode)
121 | (when tr-ime-workaround-prefix-key--timer
122 | (cancel-timer tr-ime-workaround-prefix-key--timer))
123 | (setq tr-ime-workaround-prefix-key--timer
124 | (run-with-idle-timer
125 | tr-ime-workaround-prefix-key-polling-time t
126 | #'tr-ime-workaround-prefix-key--polling-handler)))
127 | (remove-hook 'pre-command-hook
128 | #'tr-ime-workaround-prefix-key--restore-ime-mode)
129 | (when tr-ime-workaround-prefix-key--timer
130 | (cancel-timer tr-ime-workaround-prefix-key--timer))
131 | (setq tr-ime-workaround-prefix-key--timer nil))
132 | (set-default symb bool))
133 |
134 | (defcustom tr-ime-workaround-prefix-key-p t
135 | "プレフィックスキー検出ワークアラウンドを動作させるか否か.
136 |
137 | この設定を変更する場合には \"custom-set-variables\" を使うこと。
138 |
139 | コマンドのキーシーケンスになる最初のキーである
140 | プレフィックスキーをタイマによるポーリングで検出すると、
141 | 自動的に IME off にして、コマンド開始前に IME 状態を戻す機能。"
142 | :type '(choice (const :tag "Enable" t)
143 | (const :tag "Disable" nil))
144 | :set #'tr-ime-workaround-prefix-key--set
145 | :group 'tr-ime-workaround-prefix-key)
146 |
147 | (defun tr-ime-workaround-prefix-key-unload-function ()
148 | "アンロードするためプレフィックスキー検出ワークアラウンドを無効にする."
149 | (let (_dummy)
150 | (tr-ime-workaround-prefix-key--set '_dummy nil)))
151 |
152 | ;;
153 | ;; provide
154 | ;;
155 |
156 | (provide 'tr-ime-workaround-prefix-key)
157 |
158 | ;; Local Variables:
159 | ;; coding: utf-8
160 | ;; End:
161 |
162 | ;;; tr-ime-workaround-prefix-key.el ends here
163 |
--------------------------------------------------------------------------------
/lisp/tr-ime.el:
--------------------------------------------------------------------------------
1 | ;;; tr-ime.el --- Emulator of IME patch for Windows -*- lexical-binding: t -*-
2 |
3 | ;; Copyright (C) 2020-2022 Masamichi Hosoda
4 |
5 | ;; Author: Masamichi Hosoda
6 | ;; URL: https://github.com/trueroad/tr-emacs-ime-module
7 | ;; Version: 0.5.0
8 | ;; Package-Requires: ((emacs "27.1") (w32-ime "0.0.1"))
9 |
10 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime)
11 | ;; is free software: you can redistribute it and/or modify
12 | ;; it under the terms of the GNU General Public License as published by
13 | ;; the Free Software Foundation, either version 3 of the License, or
14 | ;; (at your option) any later version.
15 | ;;
16 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime)
17 | ;; is distributed in the hope that it will be useful,
18 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 | ;; GNU General Public License for more details.
21 | ;;
22 | ;; You should have received a copy of the GNU General Public License
23 | ;; along with tr-ime.
24 | ;; If not, see .
25 |
26 | ;;; Commentary:
27 |
28 | ;; Emulator of GNU Emacs IME patch for Windows (tr-ime) emulates the C
29 | ;; implementation part of an IME patch for GNU Emacs that allows to input
30 | ;; Japanese using the Windows IME (Input Method Editor). On Emacs 26.2 or
31 | ;; later, Japanese input using the IME is now possible even without the IME
32 | ;; patch. However, some of the features of the IME patch are not implemented
33 | ;; in current Emacs, so it is possible to type Japanese on Emacs without the
34 | ;; IME patch, but it is not convenient.
35 | ;;
36 | ;; w32-ime.el in the w32-ime package manages the upper layer of the IME
37 | ;; patch and provides the convenient features but it could not be used on
38 | ;; emacs.exe without the IME patch applied. tr-ime emulates the lower
39 | ;; layers of the IME patches and can interact with w32-ime.el. So, using
40 | ;; tr-ime, w32-ime.el can be used on emacs.exe without the IME patch applied.
41 | ;;
42 | ;; By using tr-ime and w32-ime.el together, emacs.exe without the IME patch
43 | ;; can use the same convenient features as the IME patched emacs.exe. They
44 | ;; can display the on/off state of the IME in the mode line as UI/UX features.
45 | ;; They also have hooks to call when the IME state is changed. With these
46 | ;; hooks, you can change the color and shape of the cursor depending on the
47 | ;; IME on/off status to be visually known to the IME state.
48 |
49 | ;; To use standard features (stable but less functionality) of the tr-ime
50 | ;; package, add the following code to your init.el or .emacs
51 | ;; It loads the tr-ime-mod DLL module if you use Emacs 27.
52 | ;;
53 | ;; (tr-ime-standard-install)
54 | ;; (setq default-input-method "W32-IME")
55 | ;; (w32-ime-initialize)
56 | ;;
57 | ;; To use advanced features (experimental but more functionality) of the
58 | ;; tr-ime package, add the following code to your init.el or .emacs
59 | ;; It loads the tr-ime-modadv DLL module.
60 | ;;
61 | ;; (tr-ime-advanced-install)
62 | ;; (setq default-input-method "W32-IME")
63 | ;; (w32-ime-initialize)
64 |
65 | ;;; Code:
66 |
67 | (defgroup tr-ime nil
68 | "Emulator of GNU Emacs IME patch for Windows (tr-ime)."
69 | :group 'emacs)
70 |
71 | (defconst tr-ime--mod-abi-version 1
72 | "ABI version number of tr-ime-mod DLL.")
73 | (defconst tr-ime--mod-name (concat "tr-ime-mod-"
74 | (int-to-string tr-ime--mod-abi-version)
75 | "-"
76 | system-configuration)
77 | "Module name of tr-ime-mod (standard).")
78 |
79 | (defconst tr-ime--modadv-abi-version 2
80 | "ABI version number of tr-ime-modadv DLL.")
81 | (defconst tr-ime--modadv-name (concat
82 | "tr-ime-modadv-"
83 | (int-to-string tr-ime--modadv-abi-version)
84 | "-"
85 | system-configuration)
86 | "Module name of tr-imeadv-mod (advanced).")
87 |
88 | (defvar tr-ime-enabled-features nil
89 | "Enabled features in tr-ime (standard/advanced).
90 |
91 | If the standard features are enabled, it is set to 'standard.
92 | If the advanced features are enabled, it is set to 'advanced.
93 | If any features are not enabled, it is set to nil.")
94 |
95 | (declare-function tr-ime-download-mod-file "tr-ime-download"
96 | (name &optional no-confirm))
97 |
98 | (defun tr-ime--c-function-p (symb)
99 | "Return non-nil if SYMB is a function that is defined in a C source."
100 | (and (fboundp symb)
101 | (subrp (symbol-function symb))))
102 |
103 | (defun tr-ime--c-variable-p (symb)
104 | "Return non-nil if SYMB is a variable that is defined in a C source."
105 | (and (boundp symb)
106 | (not (symbol-file symb 'defvar))))
107 |
108 | ;;;###autoload
109 | (defun tr-ime-detect-ime-patch-p ()
110 | "Return non-nil if an IME patch seems to be applied to Emacs."
111 | (or (tr-ime--c-function-p 'ime-get-mode)
112 | (tr-ime--c-function-p 'ime-force-on)
113 | (tr-ime--c-function-p 'ime-force-off)
114 | (tr-ime--c-variable-p 'set-selected-window-buffer-functions)
115 | (tr-ime--c-variable-p 'select-window-functions)))
116 |
117 | ;;;###autoload
118 | (defun tr-ime-standard-install (&optional no-confirm)
119 | "Install tr-ime standard (stable but less functionality) DLL.
120 |
121 | If NO-CONFIRM is non-nil, download the necessary module DLL without
122 | confirming the user."
123 | (tr-ime-uninitialize)
124 | (cond
125 | ((not (eq window-system 'w32))
126 | (display-warning 'tr-ime
127 | (concat
128 | "window-system is not w32. "
129 | "tr-ime cannot install standard DLL on it.")
130 | :warning))
131 | ((tr-ime-detect-ime-patch-p)
132 | (display-warning 'tr-ime
133 | (concat
134 | "Emacs seems to have an IME patch applied. "
135 | "tr-ime cannot work on it.")
136 | :warning))
137 | ((fboundp 'w32-get-ime-open-status)
138 | (display-warning 'tr-ime
139 | (concat
140 | "Function w32-get-ime-open-status exists. "
141 | "tr-ime standard DLL is not necessary.")
142 | :debug))
143 | ((not (string= module-file-suffix ".dll"))
144 | (display-warning 'tr-ime
145 | (concat
146 | "module-file-suffix is not \".dll\". "
147 | "Emacs cannot load tr-ime module DLLs.")
148 | :warning))
149 | ((locate-library tr-ime--mod-name)
150 | (display-warning 'tr-ime
151 | "tr-ime standard DLL already exists."
152 | :debug))
153 | (t
154 | (require 'tr-ime-download)
155 | (tr-ime-download-mod-file tr-ime--mod-name no-confirm)))
156 | (tr-ime-standard-initialize))
157 |
158 | ;;;###autoload
159 | (defun tr-ime-standard-initialize ()
160 | "Initialize tr-ime standard (stable but less functionality) features."
161 | (cond
162 | ((not (eq window-system 'w32))
163 | (display-warning 'tr-ime
164 | (concat
165 | "window-system is not w32. "
166 | "tr-ime cannot initialize on it.")
167 | :warning))
168 | ((tr-ime-detect-ime-patch-p)
169 | (display-warning 'tr-ime
170 | (concat
171 | "Emacs seems to have an IME patch applied. "
172 | "tr-ime cannot work on it.")
173 | :warning))
174 | ((and (not (fboundp 'w32-get-ime-open-status))
175 | (not (string= module-file-suffix ".dll")))
176 | (display-warning 'tr-ime
177 | (concat
178 | "module-file-suffix is not \".dll\". "
179 | "Emacs cannot load tr-ime module DLLs.")
180 | :warning))
181 | (t
182 | (setq tr-ime-enabled-features 'standard)
183 | (unless (fboundp 'w32-get-ime-open-status)
184 | (require 'tr-ime-mod tr-ime--mod-name))
185 | (require 'tr-ime-openstatus)
186 | (require 'tr-ime-hook)
187 | (require 'tr-ime-workaround-prefix-key)
188 | (require 'tr-ime-workaround-inconsistent)
189 | (define-key global-map [M-kanji] 'toggle-input-method)
190 | (define-key isearch-mode-map [M-kanji] 'isearch-toggle-input-method)
191 | (require 'w32-ime))))
192 |
193 | ;;;###autoload
194 | (defun tr-ime-advanced-install (&optional no-confirm)
195 | "Install tr-ime advanced (experimental but more functionality) DLL.
196 |
197 | If NO-CONFIRM is non-nil, download the necessary module DLL without
198 | confirming the user."
199 | (tr-ime-uninitialize)
200 | (cond
201 | ((not (eq window-system 'w32))
202 | (display-warning 'tr-ime
203 | (concat
204 | "window-system is not w32. "
205 | "tr-ime cannot install advanced DLL on it.")
206 | :warning))
207 | ((tr-ime-detect-ime-patch-p)
208 | (display-warning 'tr-ime
209 | (concat
210 | "Emacs seems to have an IME patch applied. "
211 | "tr-ime cannot work on it.")
212 | :warning))
213 | ((not (string= module-file-suffix ".dll"))
214 | (display-warning 'tr-ime
215 | (concat
216 | "module-file-suffix is not \".dll\". "
217 | "Emacs cannot load tr-ime module DLLs.")
218 | :warning))
219 | ((locate-library tr-ime--modadv-name)
220 | (display-warning 'tr-ime
221 | "tr-ime advanced DLL already exists."
222 | :debug))
223 | (t
224 | (require 'tr-ime-download)
225 | (tr-ime-download-mod-file tr-ime--modadv-name no-confirm)))
226 | (tr-ime-advanced-initialize))
227 |
228 | ;;;###autoload
229 | (defun tr-ime-advanced-initialize ()
230 | "Initialize tr-ime advanced (experimental but more functionality) features."
231 | (cond
232 | ((not (eq window-system 'w32))
233 | (display-warning 'tr-ime
234 | (concat
235 | "window-system is not w32. "
236 | "tr-ime cannot initialize on it.")
237 | :warning))
238 | ((tr-ime-detect-ime-patch-p)
239 | (display-warning 'tr-ime
240 | (concat
241 | "Emacs seems to have an IME patch applied. "
242 | "tr-ime cannot work on it.")
243 | :warning))
244 | ((not (string= module-file-suffix ".dll"))
245 | (display-warning 'tr-ime
246 | (concat
247 | "module-file-suffix is not \".dll\". "
248 | "Emacs cannot load tr-ime module DLLs.")
249 | :warning))
250 | (t
251 | (setq tr-ime-enabled-features 'advanced)
252 | (require 'tr-ime-modadv tr-ime--modadv-name)
253 | (require 'tr-ime-openstatus)
254 | (require 'tr-ime-hook)
255 | (require 'tr-ime-subclassify)
256 | (require 'tr-ime-thread-message)
257 | (require 'tr-ime-recv-notify)
258 | (require 'tr-ime-font)
259 | (require 'tr-ime-isearch)
260 | (require 'tr-ime-workaround-isearch)
261 | (require 'tr-ime-prefix-key)
262 | (require 'tr-ime-sync)
263 | (require 'tr-ime-reconversion)
264 | (require 'tr-ime-documentfeed)
265 | (require 'tr-ime-debug)
266 | (define-key global-map [M-kanji] 'ignore)
267 | (require 'w32-ime))))
268 |
269 | ;;;###autoload
270 | (defun tr-ime-uninitialize ()
271 | "Uninitialize tr-ime features."
272 | (when (eq tr-ime-enabled-features 'standard)
273 | (define-key global-map [M-kanji] 'ignore)
274 | (define-key isearch-mode-map [M-kanji] 'ignore))
275 | (when (featurep 'tr-ime-debug)
276 | (unload-feature 'tr-ime-debug t))
277 | (when (featurep 'tr-ime-documentfeed)
278 | (unload-feature 'tr-ime-documentfeed t))
279 | (when (featurep 'tr-ime-reconversion)
280 | (unload-feature 'tr-ime-reconversion t))
281 | (when (featurep 'tr-ime-sync)
282 | (unload-feature 'tr-ime-sync t))
283 | (when (featurep 'tr-ime-prefix-key)
284 | (unload-feature 'tr-ime-prefix-key t))
285 | (when (featurep 'tr-ime-workaround-isearch)
286 | (unload-feature 'tr-ime-workaround-isearch t))
287 | (when (featurep 'tr-ime-isearch)
288 | (unload-feature 'tr-ime-isearch t))
289 | (when (featurep 'tr-ime-font)
290 | (unload-feature 'tr-ime-font t))
291 | (when (featurep 'tr-ime-recv-notify)
292 | (unload-feature 'tr-ime-recv-notify t))
293 | (when (featurep 'tr-ime-thread-message)
294 | (unload-feature 'tr-ime-thread-message t))
295 | (when (featurep 'tr-ime-subclassify)
296 | (unload-feature 'tr-ime-subclassify t))
297 | (when (featurep 'tr-ime-workaround-inconsistent)
298 | (unload-feature 'tr-ime-workaround-inconsistent t))
299 | (when (featurep 'tr-ime-workaround-prefix-key)
300 | (unload-feature 'tr-ime-workaround-prefix-key t))
301 | (when (featurep 'tr-ime-hook)
302 | (unload-feature 'tr-ime-hook t))
303 | (when (featurep 'tr-ime-openstatus)
304 | (unload-feature 'tr-ime-openstatus t))
305 | (when (featurep 'tr-ime-modadv)
306 | (unload-feature 'tr-ime-modadv t))
307 | (when (featurep 'tr-ime-mod)
308 | (unload-feature 'tr-ime-mod t))
309 | (setq tr-ime-enabled-features nil))
310 |
311 | (defun tr-ime-unload-feature ()
312 | "Prepare unloading tr-ime features."
313 | (tr-ime-uninitialize))
314 |
315 | (provide 'tr-ime)
316 |
317 | ;; Local Variables:
318 | ;; coding: utf-8
319 | ;; End:
320 |
321 | ;;; tr-ime.el ends here
322 |
--------------------------------------------------------------------------------
/m4/.gitignore:
--------------------------------------------------------------------------------
1 | libtool.m4
2 | lt~obsolete.m4
3 | ltoptions.m4
4 | ltsugar.m4
5 | ltversion.m4
6 |
--------------------------------------------------------------------------------
/src/Makefile.am:
--------------------------------------------------------------------------------
1 | #
2 | # Targets
3 | #
4 |
5 | noinst_LTLIBRARIES = tr-ime-mod.la
6 | pkgmoduleexec_SCRIPTS = tr-ime-mod-$(MOD_ABI_VERSION)-$(host)$(SHREXT)
7 | CLEANFILES = tr-ime-mod-$(MOD_ABI_VERSION)-$(host)$(SHREXT)
8 |
9 | noinst_LTLIBRARIES += tr-ime-modadv.la
10 | pkgmoduleexec_SCRIPTS += tr-ime-modadv-$(MODADV_ABI_VERSION)-$(host)$(SHREXT)
11 | CLEANFILES += tr-ime-modadv-$(MODADV_ABI_VERSION)-$(host)$(SHREXT)
12 |
13 | #
14 | # Workaround for install-strip modules
15 | #
16 |
17 | INSTALL_SCRIPT = $(INSTALL_PROGRAM)
18 |
19 | #
20 | # For tr-ime-mod
21 | #
22 |
23 | tr_ime_mod_la_SOURCES = tr-ime-mod.c tr-ime-mod-resource.rc
24 |
25 | tr_ime_mod_la_LIBADD = -limm32
26 |
27 | tr_ime_mod_la_LDFLAGS = -no-undefined
28 | tr_ime_mod_la_LDFLAGS += -module
29 | tr_ime_mod_la_LDFLAGS += -avoid-version
30 | tr_ime_mod_la_LDFLAGS += -rpath $(pkgmoduleexecdir)
31 |
32 | $(objdir)/tr-ime-mod$(SHREXT): tr-ime-mod.la
33 |
34 | tr-ime-mod-$(MOD_ABI_VERSION)-$(host)$(SHREXT): \
35 | $(objdir)/tr-ime-mod$(SHREXT)
36 | cp -p $< $@
37 |
38 | #
39 | # For tr-ime-modadv
40 | #
41 |
42 | tr_ime_modadv_la_SOURCES = tr-ime-modadv.cc tr-ime-modadv-resource.rc \
43 | debug-message.cc debug-message.hh lisp-in-cc.cc lisp-in-cc.hh \
44 | get_msg_hook.cc get_msg_hook.hh get_msg_proc.cc get_msg_proc.hh \
45 | message.cc message.hh subclass_proc.cc subclass_proc.hh \
46 | queue.cc queue.hh
47 |
48 | tr_ime_modadv_la_LIBADD = -lgdi32 -lcomctl32 -limm32
49 |
50 | tr_ime_modadv_la_LDFLAGS = -no-undefined
51 | tr_ime_modadv_la_LDFLAGS += -module
52 | tr_ime_modadv_la_LDFLAGS += -avoid-version
53 | tr_ime_modadv_la_LDFLAGS += -rpath $(pkgmoduleexecdir)
54 |
55 | $(objdir)/tr-ime-modadv$(SHREXT): tr-ime-modadv.la
56 |
57 | tr-ime-modadv-$(MODADV_ABI_VERSION)-$(host)$(SHREXT): \
58 | $(objdir)/tr-ime-modadv$(SHREXT)
59 | cp -p $< $@
60 |
61 | #
62 | # For Windows Resource Script (.rc)
63 | #
64 |
65 | WINDRESFLAGS = $(DEFAULT_INCLUDES)
66 |
67 | .rc.lo:
68 | $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
69 | --tag=RC --mode=compile \
70 | $(WINDRES) $(WINDRESFLAGS) -i $< -o $@
71 |
72 | #
73 | # emacs-module.h
74 | #
75 |
76 | EXTRA_DIST = emacs-27.1/emacs-module.h
77 |
--------------------------------------------------------------------------------
/src/debug-message.cc:
--------------------------------------------------------------------------------
1 | // -*- mode: c++; coding: utf-8 -*-
2 |
3 | // This file is part of
4 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
5 | // https://github.com/trueroad/tr-emacs-ime-module
6 | //
7 | // Copyright (C) 2020 Masamichi Hosoda
8 | //
9 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
10 | // is free software: you can redistribute it and/or modify
11 | // it under the terms of the GNU General Public License as published by
12 | // the Free Software Foundation, either version 3 of the License, or
13 | // (at your option) any later version.
14 | //
15 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
16 | // is distributed in the hope that it will be useful,
17 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | // GNU General Public License for more details.
20 | //
21 | // You should have received a copy of the GNU General Public License
22 | // along with tr-ime.
23 | // If not, see .
24 |
25 | #include "debug-message.hh"
26 |
27 | #ifdef HAVE_CONFIG_H
28 | #include "config.h"
29 | #endif
30 |
31 | #include
32 | #include
33 |
34 | #include
35 |
36 | // verbose level
37 | // 0: none
38 | // 1: fatal
39 | // 2: error
40 | // 3: warn
41 | // 4: info
42 | // 5: debug
43 | // 6: trace
44 |
45 | #ifndef NDEBUG
46 | int verbose_level = 5;
47 | #else
48 | int verbose_level = 3;
49 | #endif
50 |
51 | std::string
52 | get_format_message (DWORD dwMessageId)
53 | {
54 | LPSTR lpbuff;
55 |
56 | if (!FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER |
57 | FORMAT_MESSAGE_FROM_SYSTEM |
58 | FORMAT_MESSAGE_IGNORE_INSERTS,
59 | nullptr,
60 | dwMessageId,
61 | MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
62 | reinterpret_cast (&lpbuff),
63 | 0,
64 | nullptr))
65 | return "error";
66 |
67 | std::string ret {lpbuff};
68 | LocalFree (lpbuff);
69 |
70 | return ret;
71 | }
72 |
73 | void
74 | debug_output_reconvert_string (RECONVERTSTRING *rs)
75 | {
76 | std::stringstream ss;
77 |
78 | ss << "---RECONVERTSTRING---" << std::endl
79 | << " dwSize : " << rs->dwSize << std::endl
80 | << " dwVersion : " << rs->dwVersion << std::endl
81 | << " dwStrLen : " << rs->dwStrLen << std::endl
82 | << " dwStrOffset : " << rs->dwStrOffset << std::endl
83 | << " dwCompStrLen : " << rs->dwCompStrLen << std::endl
84 | << " dwCompStrOffset : " << rs->dwCompStrOffset << std::endl
85 | << " dwTargetStrLen : " << rs->dwTargetStrLen << std::endl
86 | << " dwTargetStrOffset: " << rs->dwTargetStrOffset << std::endl;
87 | DEBUG_MESSAGE_STATIC (ss.str ().c_str ());
88 |
89 | auto *buff = reinterpret_cast
90 | (reinterpret_cast (rs) + sizeof (RECONVERTSTRING));
91 | std::basic_string str (buff, rs->dwStrLen);
92 | TRACE_MESSAGE_W (L" buff = \"" << str << L"\"\n");
93 | }
94 |
--------------------------------------------------------------------------------
/src/debug-message.hh:
--------------------------------------------------------------------------------
1 | // -*- mode: c++; coding: utf-8 -*-
2 |
3 | // This file is part of
4 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
5 | // https://github.com/trueroad/tr-emacs-ime-module
6 | //
7 | // Copyright (C) 2020 Masamichi Hosoda
8 | //
9 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
10 | // is free software: you can redistribute it and/or modify
11 | // it under the terms of the GNU General Public License as published by
12 | // the Free Software Foundation, either version 3 of the License, or
13 | // (at your option) any later version.
14 | //
15 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
16 | // is distributed in the hope that it will be useful,
17 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | // GNU General Public License for more details.
20 | //
21 | // You should have received a copy of the GNU General Public License
22 | // along with tr-ime.
23 | // If not, see .
24 |
25 | #ifndef INCLUDE_GUARD_DEBUG_MESSAGE_HH
26 | #define INCLUDE_GUARD_DEBUG_MESSAGE_HH
27 |
28 | #ifdef HAVE_CONFIG_H
29 | #include "config.h"
30 | #endif
31 |
32 | #include
33 | #include
34 |
35 | #include
36 |
37 | #ifdef HAVE_CXX_PRETTY_FUNCTION
38 |
39 | #ifdef NDEBUG
40 | #define DEBUG_MESSAGE(x)
41 | #else
42 | #define DEBUG_MESSAGE(x) \
43 | do \
44 | { \
45 | if (verbose_level >= 5) \
46 | { \
47 | std::stringstream ss; \
48 | ss << "debug: " << __PRETTY_FUNCTION__ << ": " << x; \
49 | OutputDebugStringA (ss.str ().c_str ()); \
50 | } \
51 | } \
52 | while (false)
53 | #endif
54 |
55 | #define WARNING_MESSAGE(x) \
56 | do \
57 | { \
58 | if (verbose_level >= 3) \
59 | { \
60 | std::stringstream ss; \
61 | ss << "warning: " << __PRETTY_FUNCTION__ << ": " << x; \
62 | OutputDebugStringA (ss.str ().c_str ()); \
63 | } \
64 | } \
65 | while (false)
66 |
67 | #else // HAVE_PRETTY_FUNCTION
68 |
69 | #ifdef NDEBUG
70 | #define DEBUG_MESSAGE(x)
71 | #else
72 | #define DEBUG_MESSAGE(x) \
73 | do \
74 | { \
75 | if (verbose_level >= 5) \
76 | { \
77 | std::stringstream ss; \
78 | ss << "debug: " << __func__ << ": " << x; \
79 | OutputDebugStringA (ss.str ().c_str ()); \
80 | } \
81 | } \
82 | while (false)
83 | #endif
84 |
85 | #define WARNING_MESSAGE(x) \
86 | do \
87 | { \
88 | if (verbose_level >= 3) \
89 | { \
90 | std::stringstream ss; \
91 | ss << "warning: " << __func__ << ": " << x; \
92 | OutputDebugStringA (ss.str ().c_str ()); \
93 | } \
94 | } \
95 | while (false)
96 |
97 | #endif // HAVE_PRETTY_FUNCTION
98 |
99 | #ifdef NDEBUG
100 | #define DEBUG_MESSAGE_A(x)
101 | #define DEBUG_MESSAGE_W(x)
102 | #define DEBUG_MESSAGE_STATIC(x)
103 | #define DEBUG_MESSAGE_RECONVERTSTRING(x)
104 | #define TRACE_MESSAGE_A(x)
105 | #define TRACE_MESSAGE_W(x)
106 | #define TRACE_MESSAGE_STATIC(x)
107 | #else
108 | #define DEBUG_MESSAGE_A(x) \
109 | do \
110 | { \
111 | if (verbose_level >= 5) \
112 | { \
113 | std::stringstream ss; \
114 | ss << x; \
115 | OutputDebugStringA (ss.str ().c_str ()); \
116 | } \
117 | } \
118 | while (false)
119 | #define DEBUG_MESSAGE_W(x) \
120 | do \
121 | { \
122 | if (verbose_level >= 5) \
123 | { \
124 | std::basic_stringstream ss; \
125 | ss << x; \
126 | OutputDebugStringW (ss.str ().c_str ()); \
127 | } \
128 | } \
129 | while (false)
130 | #define DEBUG_MESSAGE_STATIC(x) \
131 | do \
132 | { \
133 | if (verbose_level >= 5) \
134 | OutputDebugStringA ((x)); \
135 | } \
136 | while (false)
137 | #define DEBUG_MESSAGE_RECONVERTSTRING(x) \
138 | do \
139 | { \
140 | if (verbose_level >= 5) \
141 | debug_output_reconvert_string ((x)); \
142 | } \
143 | while (false)
144 | #define TRACE_MESSAGE_A(x) \
145 | do \
146 | { \
147 | if (verbose_level >= 6) \
148 | { \
149 | std::stringstream ss; \
150 | ss << x; \
151 | OutputDebugStringA (ss.str ().c_str ()); \
152 | } \
153 | } \
154 | while (false)
155 | #define TRACE_MESSAGE_W(x) \
156 | do \
157 | { \
158 | if (verbose_level >= 6) \
159 | { \
160 | std::basic_stringstream ss; \
161 | ss << x; \
162 | OutputDebugStringW (ss.str ().c_str ()); \
163 | } \
164 | } \
165 | while (false)
166 | #define TRACE_MESSAGE_STATIC(x) \
167 | do \
168 | { \
169 | if (verbose_level >= 6) \
170 | OutputDebugStringA ((x)); \
171 | } \
172 | while (false)
173 | #endif
174 |
175 | #define WARNING_MESSAGE_A(x) \
176 | do \
177 | { \
178 | if (verbose_level >= 3) \
179 | { \
180 | std::stringstream ss; \
181 | ss << x; \
182 | OutputDebugStringA (ss.str ().c_str ()); \
183 | } \
184 | } \
185 | while (false)
186 | #define WARNING_MESSAGE_W(x) \
187 | do \
188 | { \
189 | if (verbose_level >= 3) \
190 | { \
191 | std::basic_stringstream ss; \
192 | ss << x; \
193 | OutputDebugStringW (ss.str ().c_str ()); \
194 | } \
195 | } \
196 | while (false)
197 | #define WARNING_MESSAGE_STATIC(x) \
198 | do \
199 | { \
200 | if (verbose_level >= 3) \
201 | OutputDebugStringA ((x)); \
202 | } \
203 | while (false)
204 |
205 | std::string get_format_message (DWORD dwMessageId);
206 | void debug_output_reconvert_string (RECONVERTSTRING *rs);
207 |
208 | extern int verbose_level;
209 |
210 | #endif // INCLUDE_GUARD_DEBUG_MESSAGE_HH
211 |
--------------------------------------------------------------------------------
/src/emacs-27.1/emacs-module.h:
--------------------------------------------------------------------------------
1 | /* emacs-module.h - GNU Emacs module API.
2 |
3 | Copyright (C) 2015-2020 Free Software Foundation, Inc.
4 |
5 | This file is part of GNU Emacs.
6 |
7 | GNU Emacs is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 3 of the License, or (at
10 | your option) any later version.
11 |
12 | GNU Emacs is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with GNU Emacs. If not, see . */
19 |
20 | /*
21 | This file defines the Emacs module API. Please see the chapter
22 | `Dynamic Modules' in the GNU Emacs Lisp Reference Manual for
23 | information how to write modules and use this header file.
24 | */
25 |
26 | #ifndef EMACS_MODULE_H
27 | #define EMACS_MODULE_H
28 |
29 | #include
30 | #include
31 | #include
32 |
33 | #ifndef __cplusplus
34 | #include
35 | #endif
36 |
37 | #define EMACS_MAJOR_VERSION 27
38 |
39 | #if defined __cplusplus && __cplusplus >= 201103L
40 | # define EMACS_NOEXCEPT noexcept
41 | #else
42 | # define EMACS_NOEXCEPT
43 | #endif
44 |
45 | #ifdef __has_attribute
46 | #if __has_attribute(__nonnull__)
47 | # define EMACS_ATTRIBUTE_NONNULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
48 | #endif
49 | #endif
50 | #ifndef EMACS_ATTRIBUTE_NONNULL
51 | # define EMACS_ATTRIBUTE_NONNULL(...)
52 | #endif
53 |
54 | #ifdef __cplusplus
55 | extern "C" {
56 | #endif
57 |
58 | /* Current environment. */
59 | typedef struct emacs_env_27 emacs_env;
60 |
61 | /* Opaque pointer representing an Emacs Lisp value.
62 | BEWARE: Do not assume NULL is a valid value! */
63 | typedef struct emacs_value_tag *emacs_value;
64 |
65 | enum { emacs_variadic_function = -2 };
66 |
67 | /* Struct passed to a module init function (emacs_module_init). */
68 | struct emacs_runtime
69 | {
70 | /* Structure size (for version checking). */
71 | ptrdiff_t size;
72 |
73 | /* Private data; users should not touch this. */
74 | struct emacs_runtime_private *private_members;
75 |
76 | /* Return an environment pointer. */
77 | emacs_env *(*get_environment) (struct emacs_runtime *ert)
78 | EMACS_ATTRIBUTE_NONNULL(1);
79 | };
80 |
81 |
82 | /* Possible Emacs function call outcomes. */
83 | enum emacs_funcall_exit
84 | {
85 | /* Function has returned normally. */
86 | emacs_funcall_exit_return = 0,
87 |
88 | /* Function has signaled an error using `signal'. */
89 | emacs_funcall_exit_signal = 1,
90 |
91 | /* Function has exit using `throw'. */
92 | emacs_funcall_exit_throw = 2
93 | };
94 |
95 | /* Possible return values for emacs_env.process_input. */
96 | enum emacs_process_input_result
97 | {
98 | /* Module code may continue */
99 | emacs_process_input_continue = 0,
100 |
101 | /* Module code should return control to Emacs as soon as possible. */
102 | emacs_process_input_quit = 1
103 | };
104 |
105 | /* Define emacs_limb_t so that it is likely to match GMP's mp_limb_t.
106 | This micro-optimization can help modules that use mpz_export and
107 | mpz_import, which operate more efficiently on mp_limb_t. It's OK
108 | (if perhaps a bit slower) if the two types do not match, and
109 | modules shouldn't rely on the two types matching. */
110 | typedef size_t emacs_limb_t;
111 | #define EMACS_LIMB_MAX SIZE_MAX
112 |
113 | struct emacs_env_25
114 | {
115 | /* Structure size (for version checking). */
116 | ptrdiff_t size;
117 |
118 | /* Private data; users should not touch this. */
119 | struct emacs_env_private *private_members;
120 |
121 | /* Memory management. */
122 |
123 | emacs_value (*make_global_ref) (emacs_env *env,
124 | emacs_value any_reference)
125 | EMACS_ATTRIBUTE_NONNULL(1);
126 |
127 | void (*free_global_ref) (emacs_env *env,
128 | emacs_value global_reference)
129 | EMACS_ATTRIBUTE_NONNULL(1);
130 |
131 | /* Non-local exit handling. */
132 |
133 | enum emacs_funcall_exit (*non_local_exit_check) (emacs_env *env)
134 | EMACS_ATTRIBUTE_NONNULL(1);
135 |
136 | void (*non_local_exit_clear) (emacs_env *env)
137 | EMACS_ATTRIBUTE_NONNULL(1);
138 |
139 | enum emacs_funcall_exit (*non_local_exit_get)
140 | (emacs_env *env,
141 | emacs_value *non_local_exit_symbol_out,
142 | emacs_value *non_local_exit_data_out)
143 | EMACS_ATTRIBUTE_NONNULL(1, 2, 3);
144 |
145 | void (*non_local_exit_signal) (emacs_env *env,
146 | emacs_value non_local_exit_symbol,
147 | emacs_value non_local_exit_data)
148 | EMACS_ATTRIBUTE_NONNULL(1);
149 |
150 | void (*non_local_exit_throw) (emacs_env *env,
151 | emacs_value tag,
152 | emacs_value value)
153 | EMACS_ATTRIBUTE_NONNULL(1);
154 |
155 | /* Function registration. */
156 |
157 | emacs_value (*make_function) (emacs_env *env,
158 | ptrdiff_t min_arity,
159 | ptrdiff_t max_arity,
160 | emacs_value (*function) (emacs_env *env,
161 | ptrdiff_t nargs,
162 | emacs_value args[],
163 | void *)
164 | EMACS_NOEXCEPT
165 | EMACS_ATTRIBUTE_NONNULL(1),
166 | const char *documentation,
167 | void *data)
168 | EMACS_ATTRIBUTE_NONNULL(1, 4);
169 |
170 | emacs_value (*funcall) (emacs_env *env,
171 | emacs_value function,
172 | ptrdiff_t nargs,
173 | emacs_value args[])
174 | EMACS_ATTRIBUTE_NONNULL(1);
175 |
176 | emacs_value (*intern) (emacs_env *env,
177 | const char *symbol_name)
178 | EMACS_ATTRIBUTE_NONNULL(1, 2);
179 |
180 | /* Type conversion. */
181 |
182 | emacs_value (*type_of) (emacs_env *env,
183 | emacs_value value)
184 | EMACS_ATTRIBUTE_NONNULL(1);
185 |
186 | bool (*is_not_nil) (emacs_env *env, emacs_value value)
187 | EMACS_ATTRIBUTE_NONNULL(1);
188 |
189 | bool (*eq) (emacs_env *env, emacs_value a, emacs_value b)
190 | EMACS_ATTRIBUTE_NONNULL(1);
191 |
192 | intmax_t (*extract_integer) (emacs_env *env, emacs_value value)
193 | EMACS_ATTRIBUTE_NONNULL(1);
194 |
195 | emacs_value (*make_integer) (emacs_env *env, intmax_t value)
196 | EMACS_ATTRIBUTE_NONNULL(1);
197 |
198 | double (*extract_float) (emacs_env *env, emacs_value value)
199 | EMACS_ATTRIBUTE_NONNULL(1);
200 |
201 | emacs_value (*make_float) (emacs_env *env, double value)
202 | EMACS_ATTRIBUTE_NONNULL(1);
203 |
204 | /* Copy the content of the Lisp string VALUE to BUFFER as an utf8
205 | NUL-terminated string.
206 |
207 | SIZE must point to the total size of the buffer. If BUFFER is
208 | NULL or if SIZE is not big enough, write the required buffer size
209 | to SIZE and return true.
210 |
211 | Note that SIZE must include the last NUL byte (e.g. "abc" needs
212 | a buffer of size 4).
213 |
214 | Return true if the string was successfully copied. */
215 |
216 | bool (*copy_string_contents) (emacs_env *env,
217 | emacs_value value,
218 | char *buffer,
219 | ptrdiff_t *size_inout)
220 | EMACS_ATTRIBUTE_NONNULL(1, 4);
221 |
222 | /* Create a Lisp string from a utf8 encoded string. */
223 | emacs_value (*make_string) (emacs_env *env,
224 | const char *contents, ptrdiff_t length)
225 | EMACS_ATTRIBUTE_NONNULL(1, 2);
226 |
227 | /* Embedded pointer type. */
228 | emacs_value (*make_user_ptr) (emacs_env *env,
229 | void (*fin) (void *) EMACS_NOEXCEPT,
230 | void *ptr)
231 | EMACS_ATTRIBUTE_NONNULL(1);
232 |
233 | void *(*get_user_ptr) (emacs_env *env, emacs_value uptr)
234 | EMACS_ATTRIBUTE_NONNULL(1);
235 | void (*set_user_ptr) (emacs_env *env, emacs_value uptr, void *ptr)
236 | EMACS_ATTRIBUTE_NONNULL(1);
237 |
238 | void (*(*get_user_finalizer) (emacs_env *env, emacs_value uptr))
239 | (void *) EMACS_NOEXCEPT EMACS_ATTRIBUTE_NONNULL(1);
240 | void (*set_user_finalizer) (emacs_env *env,
241 | emacs_value uptr,
242 | void (*fin) (void *) EMACS_NOEXCEPT)
243 | EMACS_ATTRIBUTE_NONNULL(1);
244 |
245 | /* Vector functions. */
246 | emacs_value (*vec_get) (emacs_env *env, emacs_value vec, ptrdiff_t i)
247 | EMACS_ATTRIBUTE_NONNULL(1);
248 |
249 | void (*vec_set) (emacs_env *env, emacs_value vec, ptrdiff_t i,
250 | emacs_value val)
251 | EMACS_ATTRIBUTE_NONNULL(1);
252 |
253 | ptrdiff_t (*vec_size) (emacs_env *env, emacs_value vec)
254 | EMACS_ATTRIBUTE_NONNULL(1);
255 | };
256 |
257 | struct emacs_env_26
258 | {
259 | /* Structure size (for version checking). */
260 | ptrdiff_t size;
261 |
262 | /* Private data; users should not touch this. */
263 | struct emacs_env_private *private_members;
264 |
265 | /* Memory management. */
266 |
267 | emacs_value (*make_global_ref) (emacs_env *env,
268 | emacs_value any_reference)
269 | EMACS_ATTRIBUTE_NONNULL(1);
270 |
271 | void (*free_global_ref) (emacs_env *env,
272 | emacs_value global_reference)
273 | EMACS_ATTRIBUTE_NONNULL(1);
274 |
275 | /* Non-local exit handling. */
276 |
277 | enum emacs_funcall_exit (*non_local_exit_check) (emacs_env *env)
278 | EMACS_ATTRIBUTE_NONNULL(1);
279 |
280 | void (*non_local_exit_clear) (emacs_env *env)
281 | EMACS_ATTRIBUTE_NONNULL(1);
282 |
283 | enum emacs_funcall_exit (*non_local_exit_get)
284 | (emacs_env *env,
285 | emacs_value *non_local_exit_symbol_out,
286 | emacs_value *non_local_exit_data_out)
287 | EMACS_ATTRIBUTE_NONNULL(1, 2, 3);
288 |
289 | void (*non_local_exit_signal) (emacs_env *env,
290 | emacs_value non_local_exit_symbol,
291 | emacs_value non_local_exit_data)
292 | EMACS_ATTRIBUTE_NONNULL(1);
293 |
294 | void (*non_local_exit_throw) (emacs_env *env,
295 | emacs_value tag,
296 | emacs_value value)
297 | EMACS_ATTRIBUTE_NONNULL(1);
298 |
299 | /* Function registration. */
300 |
301 | emacs_value (*make_function) (emacs_env *env,
302 | ptrdiff_t min_arity,
303 | ptrdiff_t max_arity,
304 | emacs_value (*function) (emacs_env *env,
305 | ptrdiff_t nargs,
306 | emacs_value args[],
307 | void *)
308 | EMACS_NOEXCEPT
309 | EMACS_ATTRIBUTE_NONNULL(1),
310 | const char *documentation,
311 | void *data)
312 | EMACS_ATTRIBUTE_NONNULL(1, 4);
313 |
314 | emacs_value (*funcall) (emacs_env *env,
315 | emacs_value function,
316 | ptrdiff_t nargs,
317 | emacs_value args[])
318 | EMACS_ATTRIBUTE_NONNULL(1);
319 |
320 | emacs_value (*intern) (emacs_env *env,
321 | const char *symbol_name)
322 | EMACS_ATTRIBUTE_NONNULL(1, 2);
323 |
324 | /* Type conversion. */
325 |
326 | emacs_value (*type_of) (emacs_env *env,
327 | emacs_value value)
328 | EMACS_ATTRIBUTE_NONNULL(1);
329 |
330 | bool (*is_not_nil) (emacs_env *env, emacs_value value)
331 | EMACS_ATTRIBUTE_NONNULL(1);
332 |
333 | bool (*eq) (emacs_env *env, emacs_value a, emacs_value b)
334 | EMACS_ATTRIBUTE_NONNULL(1);
335 |
336 | intmax_t (*extract_integer) (emacs_env *env, emacs_value value)
337 | EMACS_ATTRIBUTE_NONNULL(1);
338 |
339 | emacs_value (*make_integer) (emacs_env *env, intmax_t value)
340 | EMACS_ATTRIBUTE_NONNULL(1);
341 |
342 | double (*extract_float) (emacs_env *env, emacs_value value)
343 | EMACS_ATTRIBUTE_NONNULL(1);
344 |
345 | emacs_value (*make_float) (emacs_env *env, double value)
346 | EMACS_ATTRIBUTE_NONNULL(1);
347 |
348 | /* Copy the content of the Lisp string VALUE to BUFFER as an utf8
349 | NUL-terminated string.
350 |
351 | SIZE must point to the total size of the buffer. If BUFFER is
352 | NULL or if SIZE is not big enough, write the required buffer size
353 | to SIZE and return true.
354 |
355 | Note that SIZE must include the last NUL byte (e.g. "abc" needs
356 | a buffer of size 4).
357 |
358 | Return true if the string was successfully copied. */
359 |
360 | bool (*copy_string_contents) (emacs_env *env,
361 | emacs_value value,
362 | char *buffer,
363 | ptrdiff_t *size_inout)
364 | EMACS_ATTRIBUTE_NONNULL(1, 4);
365 |
366 | /* Create a Lisp string from a utf8 encoded string. */
367 | emacs_value (*make_string) (emacs_env *env,
368 | const char *contents, ptrdiff_t length)
369 | EMACS_ATTRIBUTE_NONNULL(1, 2);
370 |
371 | /* Embedded pointer type. */
372 | emacs_value (*make_user_ptr) (emacs_env *env,
373 | void (*fin) (void *) EMACS_NOEXCEPT,
374 | void *ptr)
375 | EMACS_ATTRIBUTE_NONNULL(1);
376 |
377 | void *(*get_user_ptr) (emacs_env *env, emacs_value uptr)
378 | EMACS_ATTRIBUTE_NONNULL(1);
379 | void (*set_user_ptr) (emacs_env *env, emacs_value uptr, void *ptr)
380 | EMACS_ATTRIBUTE_NONNULL(1);
381 |
382 | void (*(*get_user_finalizer) (emacs_env *env, emacs_value uptr))
383 | (void *) EMACS_NOEXCEPT EMACS_ATTRIBUTE_NONNULL(1);
384 | void (*set_user_finalizer) (emacs_env *env,
385 | emacs_value uptr,
386 | void (*fin) (void *) EMACS_NOEXCEPT)
387 | EMACS_ATTRIBUTE_NONNULL(1);
388 |
389 | /* Vector functions. */
390 | emacs_value (*vec_get) (emacs_env *env, emacs_value vec, ptrdiff_t i)
391 | EMACS_ATTRIBUTE_NONNULL(1);
392 |
393 | void (*vec_set) (emacs_env *env, emacs_value vec, ptrdiff_t i,
394 | emacs_value val)
395 | EMACS_ATTRIBUTE_NONNULL(1);
396 |
397 | ptrdiff_t (*vec_size) (emacs_env *env, emacs_value vec)
398 | EMACS_ATTRIBUTE_NONNULL(1);
399 |
400 | /* Returns whether a quit is pending. */
401 | bool (*should_quit) (emacs_env *env)
402 | EMACS_ATTRIBUTE_NONNULL(1);
403 | };
404 |
405 | struct emacs_env_27
406 | {
407 | /* Structure size (for version checking). */
408 | ptrdiff_t size;
409 |
410 | /* Private data; users should not touch this. */
411 | struct emacs_env_private *private_members;
412 |
413 | /* Memory management. */
414 |
415 | emacs_value (*make_global_ref) (emacs_env *env,
416 | emacs_value any_reference)
417 | EMACS_ATTRIBUTE_NONNULL(1);
418 |
419 | void (*free_global_ref) (emacs_env *env,
420 | emacs_value global_reference)
421 | EMACS_ATTRIBUTE_NONNULL(1);
422 |
423 | /* Non-local exit handling. */
424 |
425 | enum emacs_funcall_exit (*non_local_exit_check) (emacs_env *env)
426 | EMACS_ATTRIBUTE_NONNULL(1);
427 |
428 | void (*non_local_exit_clear) (emacs_env *env)
429 | EMACS_ATTRIBUTE_NONNULL(1);
430 |
431 | enum emacs_funcall_exit (*non_local_exit_get)
432 | (emacs_env *env,
433 | emacs_value *non_local_exit_symbol_out,
434 | emacs_value *non_local_exit_data_out)
435 | EMACS_ATTRIBUTE_NONNULL(1, 2, 3);
436 |
437 | void (*non_local_exit_signal) (emacs_env *env,
438 | emacs_value non_local_exit_symbol,
439 | emacs_value non_local_exit_data)
440 | EMACS_ATTRIBUTE_NONNULL(1);
441 |
442 | void (*non_local_exit_throw) (emacs_env *env,
443 | emacs_value tag,
444 | emacs_value value)
445 | EMACS_ATTRIBUTE_NONNULL(1);
446 |
447 | /* Function registration. */
448 |
449 | emacs_value (*make_function) (emacs_env *env,
450 | ptrdiff_t min_arity,
451 | ptrdiff_t max_arity,
452 | emacs_value (*function) (emacs_env *env,
453 | ptrdiff_t nargs,
454 | emacs_value args[],
455 | void *)
456 | EMACS_NOEXCEPT
457 | EMACS_ATTRIBUTE_NONNULL(1),
458 | const char *documentation,
459 | void *data)
460 | EMACS_ATTRIBUTE_NONNULL(1, 4);
461 |
462 | emacs_value (*funcall) (emacs_env *env,
463 | emacs_value function,
464 | ptrdiff_t nargs,
465 | emacs_value args[])
466 | EMACS_ATTRIBUTE_NONNULL(1);
467 |
468 | emacs_value (*intern) (emacs_env *env,
469 | const char *symbol_name)
470 | EMACS_ATTRIBUTE_NONNULL(1, 2);
471 |
472 | /* Type conversion. */
473 |
474 | emacs_value (*type_of) (emacs_env *env,
475 | emacs_value value)
476 | EMACS_ATTRIBUTE_NONNULL(1);
477 |
478 | bool (*is_not_nil) (emacs_env *env, emacs_value value)
479 | EMACS_ATTRIBUTE_NONNULL(1);
480 |
481 | bool (*eq) (emacs_env *env, emacs_value a, emacs_value b)
482 | EMACS_ATTRIBUTE_NONNULL(1);
483 |
484 | intmax_t (*extract_integer) (emacs_env *env, emacs_value value)
485 | EMACS_ATTRIBUTE_NONNULL(1);
486 |
487 | emacs_value (*make_integer) (emacs_env *env, intmax_t value)
488 | EMACS_ATTRIBUTE_NONNULL(1);
489 |
490 | double (*extract_float) (emacs_env *env, emacs_value value)
491 | EMACS_ATTRIBUTE_NONNULL(1);
492 |
493 | emacs_value (*make_float) (emacs_env *env, double value)
494 | EMACS_ATTRIBUTE_NONNULL(1);
495 |
496 | /* Copy the content of the Lisp string VALUE to BUFFER as an utf8
497 | NUL-terminated string.
498 |
499 | SIZE must point to the total size of the buffer. If BUFFER is
500 | NULL or if SIZE is not big enough, write the required buffer size
501 | to SIZE and return true.
502 |
503 | Note that SIZE must include the last NUL byte (e.g. "abc" needs
504 | a buffer of size 4).
505 |
506 | Return true if the string was successfully copied. */
507 |
508 | bool (*copy_string_contents) (emacs_env *env,
509 | emacs_value value,
510 | char *buffer,
511 | ptrdiff_t *size_inout)
512 | EMACS_ATTRIBUTE_NONNULL(1, 4);
513 |
514 | /* Create a Lisp string from a utf8 encoded string. */
515 | emacs_value (*make_string) (emacs_env *env,
516 | const char *contents, ptrdiff_t length)
517 | EMACS_ATTRIBUTE_NONNULL(1, 2);
518 |
519 | /* Embedded pointer type. */
520 | emacs_value (*make_user_ptr) (emacs_env *env,
521 | void (*fin) (void *) EMACS_NOEXCEPT,
522 | void *ptr)
523 | EMACS_ATTRIBUTE_NONNULL(1);
524 |
525 | void *(*get_user_ptr) (emacs_env *env, emacs_value uptr)
526 | EMACS_ATTRIBUTE_NONNULL(1);
527 | void (*set_user_ptr) (emacs_env *env, emacs_value uptr, void *ptr)
528 | EMACS_ATTRIBUTE_NONNULL(1);
529 |
530 | void (*(*get_user_finalizer) (emacs_env *env, emacs_value uptr))
531 | (void *) EMACS_NOEXCEPT EMACS_ATTRIBUTE_NONNULL(1);
532 | void (*set_user_finalizer) (emacs_env *env,
533 | emacs_value uptr,
534 | void (*fin) (void *) EMACS_NOEXCEPT)
535 | EMACS_ATTRIBUTE_NONNULL(1);
536 |
537 | /* Vector functions. */
538 | emacs_value (*vec_get) (emacs_env *env, emacs_value vec, ptrdiff_t i)
539 | EMACS_ATTRIBUTE_NONNULL(1);
540 |
541 | void (*vec_set) (emacs_env *env, emacs_value vec, ptrdiff_t i,
542 | emacs_value val)
543 | EMACS_ATTRIBUTE_NONNULL(1);
544 |
545 | ptrdiff_t (*vec_size) (emacs_env *env, emacs_value vec)
546 | EMACS_ATTRIBUTE_NONNULL(1);
547 |
548 | /* Returns whether a quit is pending. */
549 | bool (*should_quit) (emacs_env *env)
550 | EMACS_ATTRIBUTE_NONNULL(1);
551 |
552 | /* Processes pending input events and returns whether the module
553 | function should quit. */
554 | enum emacs_process_input_result (*process_input) (emacs_env *env)
555 | EMACS_ATTRIBUTE_NONNULL (1);
556 |
557 | struct timespec (*extract_time) (emacs_env *env, emacs_value value)
558 | EMACS_ATTRIBUTE_NONNULL (1);
559 |
560 | emacs_value (*make_time) (emacs_env *env, struct timespec time)
561 | EMACS_ATTRIBUTE_NONNULL (1);
562 |
563 | bool (*extract_big_integer) (emacs_env *env, emacs_value arg, int *sign,
564 | ptrdiff_t *count, emacs_limb_t *magnitude)
565 | EMACS_ATTRIBUTE_NONNULL (1);
566 |
567 | emacs_value (*make_big_integer) (emacs_env *env, int sign, ptrdiff_t count,
568 | const emacs_limb_t *magnitude)
569 | EMACS_ATTRIBUTE_NONNULL (1);
570 | };
571 |
572 | /* Every module should define a function as follows. */
573 | extern int emacs_module_init (struct emacs_runtime *ert)
574 | EMACS_NOEXCEPT
575 | EMACS_ATTRIBUTE_NONNULL(1);
576 |
577 | #ifdef __cplusplus
578 | }
579 | #endif
580 |
581 | #endif /* EMACS_MODULE_H */
582 |
--------------------------------------------------------------------------------
/src/get_msg_hook.cc:
--------------------------------------------------------------------------------
1 | // -*- mode: c++; coding: utf-8 -*-
2 |
3 | // This file is part of
4 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
5 | // https://github.com/trueroad/tr-emacs-ime-module
6 | //
7 | // Copyright (C) 2020 Masamichi Hosoda
8 | //
9 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
10 | // is free software: you can redistribute it and/or modify
11 | // it under the terms of the GNU General Public License as published by
12 | // the Free Software Foundation, either version 3 of the License, or
13 | // (at your option) any later version.
14 | //
15 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
16 | // is distributed in the hope that it will be useful,
17 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | // GNU General Public License for more details.
20 | //
21 | // You should have received a copy of the GNU General Public License
22 | // along with tr-ime.
23 | // If not, see .
24 |
25 | #include "get_msg_hook.hh"
26 |
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 |
33 | #include
34 |
35 | #include "debug-message.hh"
36 | #include "message.hh"
37 |
38 | bool
39 | get_msg_hook::install (DWORD thread_id)
40 | {
41 | std::lock_guard lock (mtx_);
42 |
43 | if (threads_.find (thread_id) != threads_.end ())
44 | {
45 | DEBUG_MESSAGE ("already installed\n");
46 | return true;
47 | }
48 |
49 | auto hhook =
50 | SetWindowsHookExW (WH_GETMESSAGE, get_msg_proc_, hmodule_, thread_id);
51 | if (!hhook)
52 | {
53 | auto e = GetLastError ();
54 | WARNING_MESSAGE ("SetWindowsHookExW failed: " +
55 | get_format_message (e) + "\n");
56 | return false;
57 | }
58 |
59 | threads_[thread_id] = hhook;
60 |
61 | return true;
62 | }
63 |
64 | void
65 | get_msg_hook::uninstall (DWORD thread_id)
66 | {
67 | std::lock_guard lock (mtx_);
68 |
69 | if (threads_.find (thread_id) == threads_.end ())
70 | {
71 | WARNING_MESSAGE ("not installed\n");
72 | return;
73 | }
74 |
75 | if (!UnhookWindowsHookEx (threads_[thread_id]))
76 | {
77 | auto e = GetLastError ();
78 | WARNING_MESSAGE ("UnhookWindowsHookExW failed" +
79 | get_format_message (e) + "\n");
80 | }
81 |
82 | threads_.erase (thread_id);
83 | }
84 |
85 | void
86 | get_msg_hook::uninstall_all (void)
87 | {
88 | while (true)
89 | {
90 | DWORD thread_id;
91 | {
92 | std::lock_guard lock (mtx_);
93 |
94 | if (!threads_.size ())
95 | break;
96 |
97 | thread_id = threads_.begin ()->first;
98 | }
99 | uninstall (thread_id);
100 | }
101 | }
102 |
103 | void
104 | get_msg_hook::subclassify (HWND hwnd, bool b_all)
105 | {
106 | // SendMessage does not work
107 | PostMessageW (hwnd, u_WM_TR_IME_SUBCLASSIFY_,
108 | static_cast (b_all), 0);
109 | }
110 |
111 | void
112 | get_msg_hook::unsubclassify (HWND hwnd, bool b_all)
113 | {
114 | // SendMessage does not work
115 | PostMessageW (hwnd, u_WM_TR_IME_UNSUBCLASSIFY_,
116 | static_cast (b_all), 0);
117 | }
118 |
119 | void
120 | get_msg_hook::unsubclassify (DWORD thread_id)
121 | {
122 | PostThreadMessageW (thread_id, u_WM_TR_IME_UNSUBCLASSIFY_,
123 | static_cast (true), 0);
124 | }
125 |
126 | void
127 | get_msg_hook::unsubclassify_all (void)
128 | {
129 | std::lock_guard lock (mtx_);
130 |
131 | for (const auto &t: threads_)
132 | unsubclassify (t.first);
133 | }
134 |
135 | bool
136 | get_msg_hook::exists_subclassified (DWORD thread_id)
137 | {
138 | std::promise p;
139 |
140 | PostThreadMessageW (thread_id, u_WM_TR_IME_EXISTS_SUBCLASSIFIED_,
141 | reinterpret_cast (&p), 0);
142 |
143 | auto future = p.get_future ();
144 | auto results = future.wait_for (std::chrono::seconds (1));
145 | if (results == std::future_status::ready)
146 | {
147 | DEBUG_MESSAGE ("ready\n");
148 | return future.get ();
149 | }
150 |
151 | DEBUG_MESSAGE ("timeout\n");
152 |
153 | return false;
154 | }
155 |
156 | bool
157 | get_msg_hook::exists_subclassified_all (void)
158 | {
159 | std::vector v;
160 |
161 | {
162 | std::lock_guard lock (mtx_);
163 |
164 | for (const auto &t: threads_)
165 | v.push_back (t.first);
166 | }
167 |
168 | for (auto id: v)
169 | {
170 | if (exists_subclassified (id))
171 | return true;
172 | }
173 |
174 | return false;
175 | }
176 |
--------------------------------------------------------------------------------
/src/get_msg_hook.hh:
--------------------------------------------------------------------------------
1 | // -*- mode: c++; coding: utf-8 -*-
2 |
3 | // This file is part of
4 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
5 | // https://github.com/trueroad/tr-emacs-ime-module
6 | //
7 | // Copyright (C) 2020, 2022 Masamichi Hosoda
8 | //
9 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
10 | // is free software: you can redistribute it and/or modify
11 | // it under the terms of the GNU General Public License as published by
12 | // the Free Software Foundation, either version 3 of the License, or
13 | // (at your option) any later version.
14 | //
15 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
16 | // is distributed in the hope that it will be useful,
17 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | // GNU General Public License for more details.
20 | //
21 | // You should have received a copy of the GNU General Public License
22 | // along with tr-ime.
23 | // If not, see .
24 |
25 | #ifndef INCLUDE_GUARD_GET_MSG_HOOK_HH
26 | #define INCLUDE_GUARD_GET_MSG_HOOK_HH
27 |
28 | #include
29 | #include
30 |
31 | #include
32 |
33 | class get_msg_hook final
34 | {
35 | public:
36 | explicit
37 | get_msg_hook (HOOKPROC get_msg_proc, HMODULE hmodule)
38 | : get_msg_proc_ (get_msg_proc), hmodule_ (hmodule)
39 | {
40 | }
41 | ~get_msg_hook ()
42 | {
43 | uninstall_all ();
44 | }
45 | get_msg_hook (const get_msg_hook &) = delete;
46 | get_msg_hook (get_msg_hook &&) = delete;
47 | get_msg_hook& operator = (const get_msg_hook &) = delete;
48 | get_msg_hook& operator = (get_msg_hook &&) = delete;
49 |
50 | bool install (DWORD thread_id);
51 | void uninstall (DWORD thread_id);
52 | void uninstall_all (void);
53 |
54 | void subclassify (HWND hwnd, bool b_all);
55 | void unsubclassify (HWND hwnd, bool b_all);
56 | void unsubclassify (DWORD thread_id);
57 | void unsubclassify_all (void);
58 |
59 | bool exists_subclassified (DWORD thread_id);
60 | bool exists_subclassified_all (void);
61 |
62 | private:
63 | const HOOKPROC get_msg_proc_;
64 | const HMODULE hmodule_;
65 |
66 | std::mutex mtx_;
67 | std::unordered_map threads_;
68 | };
69 |
70 | #endif // INCLUDE_GUARD_GET_MSG_HOOK_HH
71 |
--------------------------------------------------------------------------------
/src/get_msg_proc.cc:
--------------------------------------------------------------------------------
1 | // -*- mode: c++; coding: utf-8 -*-
2 |
3 | // This file is part of
4 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
5 | // https://github.com/trueroad/tr-emacs-ime-module
6 | //
7 | // Copyright (C) 2020, 2022 Masamichi Hosoda
8 | //
9 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
10 | // is free software: you can redistribute it and/or modify
11 | // it under the terms of the GNU General Public License as published by
12 | // the Free Software Foundation, either version 3 of the License, or
13 | // (at your option) any later version.
14 | //
15 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
16 | // is distributed in the hope that it will be useful,
17 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | // GNU General Public License for more details.
20 | //
21 | // You should have received a copy of the GNU General Public License
22 | // along with tr-ime.
23 | // If not, see .
24 |
25 | #include "get_msg_proc.hh"
26 |
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 |
33 | #include
34 | #include
35 |
36 | #include "debug-message.hh"
37 | #include "message.hh"
38 | #include "subclass_proc.hh"
39 |
40 | constexpr WCHAR get_msg_proc::target_class_name_[];
41 | thread_local bool get_msg_proc::bsubclassify_all_ {false};
42 | thread_local std::unordered_set get_msg_proc::hwnds_;
43 | thread_local std::unordered_set get_msg_proc::exclude_hwnds_;
44 | std::atomic get_msg_proc::ab_dispatch_thread_messages_ {false};
45 | std::atomic get_msg_proc::ab_dispatch_thread_wm_timer_ {false};
46 |
47 | LRESULT
48 | get_msg_proc::wm_tr_ime_subclassify (int code, WPARAM wparam, LPARAM lparam)
49 | {
50 | // WM_TR_IME_SUBCLASSIFY does not work with SendMessage ()
51 | // because only the "post" ed message is passed to GetMsgProc ().
52 |
53 | DEBUG_MESSAGE ("enter\n");
54 |
55 | // This can be called multiple times.
56 | // So doesn't check whether PM_REMOVE or PM_NOREMOVE.
57 |
58 | auto msg = reinterpret_cast (lparam);
59 | bsubclassify_all_ = static_cast (msg->wParam);
60 |
61 | if (!msg->hwnd)
62 | {
63 | DEBUG_MESSAGE_STATIC (" thread message\n");
64 | }
65 | else if (!find_hwnd (msg->hwnd))
66 | {
67 | if (SetWindowSubclass (msg->hwnd, &subclass_proc::proc,
68 | subclass_proc::get_subclass_id (), 0))
69 | {
70 | DEBUG_MESSAGE_STATIC (" SetWindowSubclass succeeded\n");
71 | add_hwnd (msg->hwnd);
72 | }
73 | else
74 | {
75 | auto e = GetLastError ();
76 | WARNING_MESSAGE ("SetWindowSubclass failed: " +
77 | get_format_message (e) + "\n");
78 | }
79 | }
80 | else
81 | {
82 | DEBUG_MESSAGE_STATIC (" already subclassified\n");
83 | }
84 |
85 | return CallNextHookEx (nullptr, code, wparam, lparam);
86 | }
87 |
88 | LRESULT
89 | get_msg_proc::wm_tr_ime_unsubclassify (int code, WPARAM wparam, LPARAM lparam)
90 | {
91 | // WM_TR_IME_UNSUBCLASSIFY does not work with SendMessage ()
92 | // because only the "post" ed message is passed to GetMsgProc ().
93 |
94 | DEBUG_MESSAGE ("enter\n");
95 |
96 | // This can be called multiple times.
97 | // So doesn't check whether PM_REMOVE or PM_NOREMOVE.
98 |
99 | auto msg = reinterpret_cast (lparam);
100 | auto bunsubclassify_all = static_cast (msg->wParam);
101 | bsubclassify_all_ = false;
102 |
103 | if (!msg->hwnd)
104 | {
105 | DEBUG_MESSAGE_STATIC (" thread message\n");
106 | }
107 | else if (find_hwnd (msg->hwnd))
108 | {
109 | if (RemoveWindowSubclass (msg->hwnd, &subclass_proc::proc,
110 | subclass_proc::get_subclass_id ()))
111 | {
112 | DEBUG_MESSAGE_STATIC (" RemoveWindowSubclass succeeded\n");
113 | remove_hwnd (msg->hwnd);
114 | }
115 | else
116 | {
117 | auto e = GetLastError ();
118 | WARNING_MESSAGE ("RemoveWindowSubclass failed: " +
119 | get_format_message (e) + "\n");
120 | }
121 | }
122 | else
123 | {
124 | DEBUG_MESSAGE_STATIC (" already unsubclassified\n");
125 | }
126 |
127 | if (bunsubclassify_all)
128 | {
129 | for (auto h: hwnds_)
130 | // SendMessage does not work
131 | PostMessageW (h, u_WM_TR_IME_UNSUBCLASSIFY_,
132 | static_cast (false), 0);
133 | }
134 |
135 | return CallNextHookEx (nullptr, code, wparam, lparam);
136 | }
137 |
138 | LRESULT
139 | get_msg_proc::wm_tr_ime_exists_subclassified
140 | (int code, WPARAM wparam, LPARAM lparam)
141 | {
142 | // WM_TR_IME_EXISTS_SUBCLASSIFIED does not work with SendMessage ()
143 | // because only the "post" ed message is passed to GetMsgProc ().
144 |
145 | DEBUG_MESSAGE ("enter\n");
146 |
147 | if (wparam != PM_REMOVE)
148 | {
149 | // Not processed because this may be called again.
150 | DEBUG_MESSAGE_STATIC (" wparam != PM_REMOVE\n");
151 | return CallNextHookEx (nullptr, code, wparam, lparam);
152 | }
153 |
154 | auto msg = reinterpret_cast (lparam);
155 | auto p = reinterpret_cast*> (msg->wParam);
156 |
157 | p->set_value (!hwnds_.empty ());
158 |
159 | return CallNextHookEx (nullptr, code, wparam, lparam);
160 | }
161 |
162 | bool
163 | get_msg_proc::is_target_class (HWND hwnd)
164 | {
165 | DEBUG_MESSAGE ("enter\n");
166 |
167 | if (GetParent (hwnd))
168 | {
169 | DEBUG_MESSAGE_STATIC (" false (hwnd has parent)\n");
170 | add_exclude_hwnd (hwnd);
171 |
172 | return false;
173 | }
174 |
175 | constexpr auto class_size =
176 | sizeof (target_class_name_) / sizeof (target_class_name_[0]);
177 | std::array buff;
178 | auto n = GetClassNameW (hwnd, buff.data (), buff.size ());
179 |
180 | if (!std::equal (std::begin (target_class_name_),
181 | std::begin (target_class_name_) + class_size,
182 | buff.begin (),
183 | buff.begin () + n + 1))
184 | {
185 | DEBUG_MESSAGE_STATIC (" false (class is different)\n");
186 | add_exclude_hwnd (hwnd);
187 |
188 | return false;
189 | }
190 |
191 | DEBUG_MESSAGE_STATIC (" true\n");
192 |
193 | return true;
194 | }
195 |
196 | LRESULT
197 | get_msg_proc::proc (int code, WPARAM wparam, LPARAM lparam)
198 | {
199 | if (code < 0)
200 | {
201 | DEBUG_MESSAGE ("code < 0\n");
202 | return CallNextHookEx (nullptr, code, wparam, lparam);
203 | }
204 | if (code != HC_ACTION)
205 | {
206 | DEBUG_MESSAGE ("code != HC_ACTION\n");
207 | return CallNextHookEx (nullptr, code, wparam, lparam);
208 | }
209 |
210 | auto msg = reinterpret_cast (lparam);
211 | if (!msg)
212 | {
213 | WARNING_MESSAGE ("msg broken\n");
214 | return CallNextHookEx (nullptr, code, wparam, lparam);
215 | }
216 |
217 | if (msg->message == u_WM_TR_IME_SUBCLASSIFY_)
218 | return wm_tr_ime_subclassify (code, wparam, lparam);
219 | else if (msg->message == u_WM_TR_IME_UNSUBCLASSIFY_)
220 | return wm_tr_ime_unsubclassify (code, wparam, lparam);
221 | else if (msg->message == u_WM_TR_IME_EXISTS_SUBCLASSIFIED_)
222 | return wm_tr_ime_exists_subclassified (code, wparam, lparam);
223 |
224 | if (!msg->hwnd)
225 | {
226 | if (wparam != PM_REMOVE)
227 | return CallNextHookEx (nullptr, code, wparam, lparam);
228 |
229 | if (msg->message == WM_TIMER && get_b_dispatch_thread_wm_timer ())
230 | {
231 | DispatchMessageW (msg);
232 | msg->message = WM_NULL;
233 |
234 | return CallNextHookEx (nullptr, code, wparam, lparam);
235 | }
236 | else
237 | {
238 | auto r = CallNextHookEx (nullptr, code, wparam, lparam);
239 | if (get_b_dispatch_thread_messages () && msg->message != WM_QUIT)
240 | DispatchMessageW (msg);
241 |
242 | return r;
243 | }
244 | }
245 |
246 | if (bsubclassify_all_ &&
247 | !find_exclude_hwnd (msg->hwnd) && !find_hwnd (msg->hwnd) &&
248 | is_target_class (msg->hwnd))
249 | {
250 | // SendMessage does not work
251 | PostMessageW (msg->hwnd, u_WM_TR_IME_SUBCLASSIFY_,
252 | static_cast (true), 0);
253 | }
254 |
255 | return CallNextHookEx (nullptr, code, wparam, lparam);
256 | }
257 |
--------------------------------------------------------------------------------
/src/get_msg_proc.hh:
--------------------------------------------------------------------------------
1 | // -*- mode: c++; coding: utf-8 -*-
2 |
3 | // This file is part of
4 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
5 | // https://github.com/trueroad/tr-emacs-ime-module
6 | //
7 | // Copyright (C) 2020, 2022 Masamichi Hosoda
8 | //
9 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
10 | // is free software: you can redistribute it and/or modify
11 | // it under the terms of the GNU General Public License as published by
12 | // the Free Software Foundation, either version 3 of the License, or
13 | // (at your option) any later version.
14 | //
15 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
16 | // is distributed in the hope that it will be useful,
17 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | // GNU General Public License for more details.
20 | //
21 | // You should have received a copy of the GNU General Public License
22 | // along with tr-ime.
23 | // If not, see .
24 |
25 | #ifndef INCLUDE_GUARD_GET_MSG_PROC_HH
26 | #define INCLUDE_GUARD_GET_MSG_PROC_HH
27 |
28 | #include
29 | #include
30 |
31 | #include
32 |
33 | class get_msg_proc final
34 | {
35 | public:
36 | static LRESULT CALLBACK proc (int, WPARAM, LPARAM);
37 | static void destroy (HWND hwnd)
38 | {
39 | remove_hwnd (hwnd);
40 | remove_exclude_hwnd (hwnd);
41 | }
42 | static void set_b_dispatch_thread_messages (bool bset)
43 | {
44 | ab_dispatch_thread_messages_.store (bset);
45 | }
46 | static void set_b_dispatch_thread_wm_timer (bool bset)
47 | {
48 | ab_dispatch_thread_wm_timer_.store (bset);
49 | }
50 |
51 | explicit get_msg_proc () = delete;
52 | ~get_msg_proc () = delete;
53 | get_msg_proc (const get_msg_proc &) = delete;
54 | get_msg_proc (get_msg_proc &&) = delete;
55 | get_msg_proc& operator = (const get_msg_proc &) = delete;
56 | get_msg_proc& operator = (get_msg_proc &&) = delete;
57 |
58 | private:
59 | static bool find_hwnd (HWND hwnd)
60 | {
61 | return (hwnds_.find (hwnd) != hwnds_.end ());
62 | }
63 | static void add_hwnd (HWND hwnd)
64 | {
65 | hwnds_.insert (hwnd);
66 | }
67 | static void remove_hwnd (HWND hwnd)
68 | {
69 | hwnds_.erase (hwnd);
70 | }
71 | static bool find_exclude_hwnd (HWND hwnd)
72 | {
73 | return (exclude_hwnds_.find (hwnd) != exclude_hwnds_.end ());
74 | }
75 | static void add_exclude_hwnd (HWND hwnd)
76 | {
77 | exclude_hwnds_.insert (hwnd);
78 | }
79 | static void remove_exclude_hwnd (HWND hwnd)
80 | {
81 | exclude_hwnds_.erase (hwnd);
82 | }
83 | static bool get_b_dispatch_thread_messages (void)
84 | {
85 | return ab_dispatch_thread_messages_.load ();
86 | }
87 | static bool get_b_dispatch_thread_wm_timer (void)
88 | {
89 | return ab_dispatch_thread_wm_timer_.load ();
90 | }
91 |
92 | static LRESULT wm_tr_ime_subclassify (int, WPARAM, LPARAM);
93 | static LRESULT wm_tr_ime_unsubclassify (int, WPARAM, LPARAM);
94 | static LRESULT wm_tr_ime_exists_subclassified (int, WPARAM, LPARAM);
95 | static bool is_target_class (HWND);
96 |
97 | static constexpr WCHAR target_class_name_[] {L"Emacs"};
98 |
99 | static thread_local bool bsubclassify_all_;
100 | static thread_local std::unordered_set hwnds_;
101 | static thread_local std::unordered_set exclude_hwnds_;
102 |
103 | static std::atomic ab_dispatch_thread_messages_;
104 | static std::atomic ab_dispatch_thread_wm_timer_;
105 | };
106 |
107 | #endif // INCLUDE_GUARD_GET_MSG_PROC_HH
108 |
--------------------------------------------------------------------------------
/src/lisp-in-cc.hh:
--------------------------------------------------------------------------------
1 | // -*- mode: c++; coding: utf-8 -*-
2 |
3 | // This file is part of
4 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
5 | // https://github.com/trueroad/tr-emacs-ime-module
6 | //
7 | // Copyright (C) 2020, 2022 Masamichi Hosoda
8 | //
9 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
10 | // is free software: you can redistribute it and/or modify
11 | // it under the terms of the GNU General Public License as published by
12 | // the Free Software Foundation, either version 3 of the License, or
13 | // (at your option) any later version.
14 | //
15 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
16 | // is distributed in the hope that it will be useful,
17 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | // GNU General Public License for more details.
20 | //
21 | // You should have received a copy of the GNU General Public License
22 | // along with tr-ime.
23 | // If not, see .
24 |
25 | #ifndef INCLUDE_GUARD_LISP_IN_CC_HH
26 | #define INCLUDE_GUARD_LISP_IN_CC_HH
27 |
28 | #include
29 |
30 | emacs_value
31 | Ftr_ime_modadv__install_message_hook_hwnd (emacs_env*, ptrdiff_t,
32 | emacs_value[], void*) noexcept;
33 | extern const char *doc_tr_ime_modadv__install_message_hook_hwnd;
34 |
35 | emacs_value
36 | Ftr_ime_modadv__uninstall_message_hook_hwnd (emacs_env*, ptrdiff_t,
37 | emacs_value[], void*) noexcept;
38 | extern const char *doc_tr_ime_modadv__uninstall_message_hook_hwnd;
39 |
40 | emacs_value
41 | Ftr_ime_modadv__subclassify_hwnd (emacs_env*, ptrdiff_t, emacs_value[], void*)
42 | noexcept;
43 | extern const char *doc_tr_ime_modadv__subclassify_hwnd;
44 |
45 | emacs_value
46 | Ftr_ime_modadv__unsubclassify_hwnd (emacs_env*, ptrdiff_t,
47 | emacs_value[], void*) noexcept;
48 | extern const char *doc_tr_ime_modadv__unsubclassify_hwnd;
49 |
50 | emacs_value
51 | Ftr_ime_modadv__exists_subclassified (emacs_env*, ptrdiff_t,
52 | emacs_value[], void*) noexcept;
53 | extern const char *doc_tr_ime_modadv__exists_subclassified;
54 |
55 | emacs_value
56 | Ftr_ime_modadv__set_dispatch_thread_message (emacs_env*, ptrdiff_t,
57 | emacs_value[], void*) noexcept;
58 | extern const char *doc_tr_ime_modadv__set_dispatch_thread_message;
59 |
60 | emacs_value
61 | Ftr_ime_modadv__set_dispatch_thread_wm_timer (emacs_env*, ptrdiff_t,
62 | emacs_value[], void*) noexcept;
63 | extern const char *doc_tr_ime_modadv__set_dispatch_thread_wm_timer;
64 |
65 | emacs_value
66 | Ftr_ime_modadv__setopenstatus (emacs_env*, ptrdiff_t,
67 | emacs_value[], void*) noexcept;
68 | extern const char *doc_tr_ime_modadv__setopenstatus;
69 |
70 | emacs_value
71 | Ftr_ime_modadv__getopenstatus (emacs_env*, ptrdiff_t,
72 | emacs_value[], void*) noexcept;
73 | extern const char *doc_tr_ime_modadv__getopenstatus;
74 |
75 | emacs_value
76 | Ftr_ime_modadv__set_font (emacs_env*, ptrdiff_t,
77 | emacs_value[], void*) noexcept;
78 | extern const char *doc_tr_ime_modadv__set_font;
79 |
80 | emacs_value
81 | Ftr_ime_modadv__set_composition_window (emacs_env*, ptrdiff_t,
82 | emacs_value[], void*) noexcept;
83 | extern const char *doc_tr_ime_modadv__set_composition_window;
84 |
85 | emacs_value
86 | Ftr_ime_modadv__set_startcomposition_defsubclassproc (emacs_env*, ptrdiff_t,
87 | emacs_value[], void*)
88 | noexcept;
89 | extern const char *doc_tr_ime_modadv__set_startcomposition_defsubclassproc;
90 |
91 | emacs_value
92 | Ftr_ime_modadv__set_prefix_keys (emacs_env*, ptrdiff_t,
93 | emacs_value[], void*) noexcept;
94 | extern const char *doc_tr_ime_modadv__set_prefix_keys;
95 |
96 | emacs_value
97 | Ftr_ime_modadv__resume_prefix_key (emacs_env*, ptrdiff_t,
98 | emacs_value[], void*) noexcept;
99 | extern const char *doc_tr_ime_modadv__resume_prefix_key;
100 |
101 | extern const char *doc_tr_ime_modadv__setopenstatus_hook;
102 | extern const char *doc_tr_ime_modadv__reconvertstring_hook;
103 | extern const char *doc_tr_ime_modadv__documentfeed_hook;
104 |
105 | emacs_value
106 | Ftr_ime_modadv__language_change_handler (emacs_env*, ptrdiff_t,
107 | emacs_value[], void*) noexcept;
108 | extern const char *doc_tr_ime_modadv__language_change_handler;
109 |
110 | emacs_value
111 | Ftr_ime_modadv__notify_reconvert_string (emacs_env*, ptrdiff_t,
112 | emacs_value[], void*) noexcept;
113 | extern const char *doc_tr_ime_modadv__notify_reconvert_string;
114 |
115 | emacs_value
116 | Ftr_ime_modadv__set_reconversion (emacs_env*, ptrdiff_t,
117 | emacs_value[], void*) noexcept;
118 | extern const char *doc_tr_ime_modadv__set_reconversion;
119 |
120 | emacs_value
121 | Ftr_ime_modadv__set_documentfeed (emacs_env*, ptrdiff_t,
122 | emacs_value[], void*) noexcept;
123 | extern const char *doc_tr_ime_modadv__set_documentfeed;
124 |
125 | emacs_value
126 | Ftr_ime_modadv__get_dpi (emacs_env*, ptrdiff_t,
127 | emacs_value[], void*) noexcept;
128 | extern const char *doc_tr_ime_modadv__get_dpi;
129 |
130 | emacs_value
131 | Ftr_ime_modadv__set_verbose_level (emacs_env*, ptrdiff_t,
132 | emacs_value[], void*) noexcept;
133 | extern const char *doc_tr_ime_modadv__set_verbose_level;
134 |
135 | emacs_value
136 | Ftr_ime_modadv_unload_function (emacs_env*, ptrdiff_t,
137 | emacs_value[], void*) noexcept;
138 | extern const char *doc_tr_ime_modadv_unload_function;
139 |
140 | #ifndef NDEBUG
141 |
142 | emacs_value
143 | Ftr_ime_modadv__debug_output (emacs_env*, ptrdiff_t,
144 | emacs_value[], void*) noexcept;
145 | extern const char *doc_tr_ime_modadv__debug_output;
146 |
147 | emacs_value
148 | Ftr_ime_modadv__debug_rectangle (emacs_env*, ptrdiff_t,
149 | emacs_value[], void*) noexcept;
150 | extern const char *doc_tr_ime_modadv__debug_rectangle;
151 |
152 | #endif // NDEBUG
153 |
154 | #endif // INCLUDE_GUARD_LISP_IN_CC_HH
155 |
--------------------------------------------------------------------------------
/src/message.cc:
--------------------------------------------------------------------------------
1 | // -*- mode: c++; coding: utf-8 -*-
2 |
3 | // This file is part of
4 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
5 | // https://github.com/trueroad/tr-emacs-ime-module
6 | //
7 | // Copyright (C) 2020 Masamichi Hosoda
8 | //
9 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
10 | // is free software: you can redistribute it and/or modify
11 | // it under the terms of the GNU General Public License as published by
12 | // the Free Software Foundation, either version 3 of the License, or
13 | // (at your option) any later version.
14 | //
15 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
16 | // is distributed in the hope that it will be useful,
17 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | // GNU General Public License for more details.
20 | //
21 | // You should have received a copy of the GNU General Public License
22 | // along with tr-ime.
23 | // If not, see .
24 |
25 | #include "message.hh"
26 |
27 | #include
28 |
29 | constexpr WCHAR s_WM_TR_IME_SUBCLASSIFY_[] = L"WM_TR_IME_SUBCLASSIFY";
30 | const UINT u_WM_TR_IME_SUBCLASSIFY_ =
31 | RegisterWindowMessageW (s_WM_TR_IME_SUBCLASSIFY_);
32 |
33 | constexpr WCHAR s_WM_TR_IME_UNSUBCLASSIFY_[] = L"WM_TR_IME_UNSUBCLASSIFY";
34 | const UINT u_WM_TR_IME_UNSUBCLASSIFY_ =
35 | RegisterWindowMessageW (s_WM_TR_IME_UNSUBCLASSIFY_);
36 |
37 | constexpr WCHAR s_WM_TR_IME_EXISTS_SUBCLASSIFIED_[] =
38 | L"WM_TR_IME_EXISTS_SUBCLASSIFIED";
39 | const UINT u_WM_TR_IME_EXISTS_SUBCLASSIFIED_ =
40 | RegisterWindowMessageW (s_WM_TR_IME_EXISTS_SUBCLASSIFIED_);
41 |
42 | constexpr WCHAR s_WM_TR_IME_SET_OPEN_STATUS_[] = L"WM_TR_IME_SET_OPEN_STATUS";
43 | const UINT u_WM_TR_IME_SET_OPEN_STATUS_ =
44 | RegisterWindowMessageW (s_WM_TR_IME_SET_OPEN_STATUS_);
45 |
46 | constexpr WCHAR s_WM_TR_IME_GET_OPEN_STATUS_[] = L"WM_TR_IME_GET_OPEN_STATUS";
47 | const UINT u_WM_TR_IME_GET_OPEN_STATUS_ =
48 | RegisterWindowMessageW (s_WM_TR_IME_GET_OPEN_STATUS_);
49 |
50 | constexpr WCHAR s_WM_TR_IME_SET_FONT_[] = L"WM_TR_IME_SET_FONT";
51 | const UINT u_WM_TR_IME_SET_FONT_ =
52 | RegisterWindowMessageW (s_WM_TR_IME_SET_FONT_);
53 |
54 | constexpr WCHAR s_WM_TR_IME_SET_COMPOSITIONWINDOW_[] =
55 | L"WM_TR_IME_SET_COMPOSITIONWINDOW";
56 | const UINT u_WM_TR_IME_SET_COMPOSITIONWINDOW_ =
57 | RegisterWindowMessageW (s_WM_TR_IME_SET_COMPOSITIONWINDOW_);
58 |
59 | constexpr WCHAR s_WM_TR_IME_SET_PREFIX_KEYS_[] =
60 | L"WM_TR_IME_SET_PREFIX_KEYS";
61 | const UINT u_WM_TR_IME_SET_PREFIX_KEYS_ =
62 | RegisterWindowMessageW (s_WM_TR_IME_SET_PREFIX_KEYS_);
63 |
64 | constexpr WCHAR s_WM_TR_IME_NOTIFY_RECONVERT_STRING_[] =
65 | L"WM_TR_IME_NOTIFY_RECONVERT_STRING";
66 | const UINT u_WM_TR_IME_NOTIFY_RECONVERT_STRING_ =
67 | RegisterWindowMessageW (s_WM_TR_IME_NOTIFY_RECONVERT_STRING_);
68 |
69 | constexpr WCHAR s_WM_TR_IME_NOTIFY_BACKWARD_COMPLETE_[] =
70 | L"WM_TR_IME_NOTIFY_BACKWARD_COMPLETE";
71 | const UINT u_WM_TR_IME_NOTIFY_BACKWARD_COMPLETE_ =
72 | RegisterWindowMessageW (s_WM_TR_IME_NOTIFY_BACKWARD_COMPLETE_);
73 |
--------------------------------------------------------------------------------
/src/message.hh:
--------------------------------------------------------------------------------
1 | // -*- mode: c++; coding: utf-8 -*-
2 |
3 | // This file is part of
4 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
5 | // https://github.com/trueroad/tr-emacs-ime-module
6 | //
7 | // Copyright (C) 2020 Masamichi Hosoda
8 | //
9 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
10 | // is free software: you can redistribute it and/or modify
11 | // it under the terms of the GNU General Public License as published by
12 | // the Free Software Foundation, either version 3 of the License, or
13 | // (at your option) any later version.
14 | //
15 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
16 | // is distributed in the hope that it will be useful,
17 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | // GNU General Public License for more details.
20 | //
21 | // You should have received a copy of the GNU General Public License
22 | // along with tr-ime.
23 | // If not, see .
24 |
25 | #ifndef INCLUDE_GUARD_MESSAGE_HH
26 | #define INCLUDE_GUARD_MESSAGE_HH
27 |
28 | #include
29 |
30 | extern const UINT u_WM_TR_IME_SUBCLASSIFY_;
31 | extern const UINT u_WM_TR_IME_UNSUBCLASSIFY_;
32 | extern const UINT u_WM_TR_IME_EXISTS_SUBCLASSIFIED_;
33 | extern const UINT u_WM_TR_IME_SET_OPEN_STATUS_;
34 | extern const UINT u_WM_TR_IME_GET_OPEN_STATUS_;
35 | extern const UINT u_WM_TR_IME_SET_FONT_;
36 | extern const UINT u_WM_TR_IME_SET_COMPOSITIONWINDOW_;
37 | extern const UINT u_WM_TR_IME_SET_PREFIX_KEYS_;
38 | extern const UINT u_WM_TR_IME_NOTIFY_RECONVERT_STRING_;
39 | extern const UINT u_WM_TR_IME_NOTIFY_BACKWARD_COMPLETE_;
40 |
41 | #endif // INCLUDE_GUARD_MESSAGE_HH
42 |
--------------------------------------------------------------------------------
/src/queue.cc:
--------------------------------------------------------------------------------
1 | // -*- mode: c++; coding: utf-8 -*-
2 |
3 | // This file is part of
4 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
5 | // https://github.com/trueroad/tr-emacs-ime-module
6 | //
7 | // Copyright (C) 2020 Masamichi Hosoda
8 | //
9 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
10 | // is free software: you can redistribute it and/or modify
11 | // it under the terms of the GNU General Public License as published by
12 | // the Free Software Foundation, either version 3 of the License, or
13 | // (at your option) any later version.
14 | //
15 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
16 | // is distributed in the hope that it will be useful,
17 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | // GNU General Public License for more details.
20 | //
21 | // You should have received a copy of the GNU General Public License
22 | // along with tr-ime.
23 | // If not, see .
24 |
25 | #include "queue.hh"
26 |
27 | #include
28 | #include
29 | #include
30 | #include
31 |
32 | std::mutex ui_to_lisp_queue::mtx_;
33 | std::deque> ui_to_lisp_queue::queue_;
34 |
35 | bool
36 | ui_to_lisp_queue::empty (void)
37 | {
38 | std::lock_guard lock (mtx_);
39 |
40 | return queue_.empty ();
41 | }
42 |
43 | void
44 | ui_to_lisp_queue::enqueue (std::unique_ptr &&m)
45 | {
46 | std::lock_guard lock (mtx_);
47 |
48 | queue_.push_back (std::move (m));
49 | }
50 |
51 | void
52 | ui_to_lisp_queue::enqueue_fast (std::unique_ptr &&m)
53 | {
54 | std::lock_guard lock (mtx_);
55 |
56 | queue_.push_front (std::move (m));
57 | }
58 |
59 | void
60 | ui_to_lisp_queue::enqueue_one (std::unique_ptr &&m)
61 | {
62 | std::lock_guard lock (mtx_);
63 |
64 | if (std::find_if (queue_.begin (), queue_.end (),
65 | [&m] (const std::unique_ptr &p)
66 | {
67 | return p->get_message () == m->get_message ();
68 | }
69 | ) == queue_.end ())
70 | queue_.push_back (std::move (m));
71 | }
72 |
73 | void
74 | ui_to_lisp_queue::enqueue_fast_one (std::unique_ptr &&m)
75 | {
76 | std::lock_guard lock (mtx_);
77 |
78 | while (!queue_.empty ())
79 | {
80 | auto it = std::find_if (queue_.begin (), queue_.end (),
81 | [&m] (const std::unique_ptr &p)
82 | {
83 | return p->get_message () == m->get_message ();
84 | }
85 | );
86 | if (it == queue_.end ())
87 | break;
88 | queue_.erase (it);
89 | }
90 |
91 | queue_.push_front (std::move (m));
92 | }
93 |
94 | std::unique_ptr
95 | ui_to_lisp_queue::dequeue (void)
96 | {
97 | std::lock_guard lock (mtx_);
98 |
99 | if (queue_.empty ())
100 | return nullptr;
101 |
102 | std::unique_ptr m = std::move (queue_.front ());
103 | if (m)
104 | {
105 | queue_.pop_front ();
106 | return m;
107 | }
108 |
109 | return nullptr;
110 | }
111 |
--------------------------------------------------------------------------------
/src/queue.hh:
--------------------------------------------------------------------------------
1 | // -*- mode: c++; coding: utf-8 -*-
2 |
3 | // This file is part of
4 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
5 | // https://github.com/trueroad/tr-emacs-ime-module
6 | //
7 | // Copyright (C) 2020 Masamichi Hosoda
8 | //
9 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
10 | // is free software: you can redistribute it and/or modify
11 | // it under the terms of the GNU General Public License as published by
12 | // the Free Software Foundation, either version 3 of the License, or
13 | // (at your option) any later version.
14 | //
15 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
16 | // is distributed in the hope that it will be useful,
17 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | // GNU General Public License for more details.
20 | //
21 | // You should have received a copy of the GNU General Public License
22 | // along with tr-ime.
23 | // If not, see .
24 |
25 | #ifndef INCLUDE_GUARD_QUEUE_HH
26 | #define INCLUDE_GUARD_QUEUE_HH
27 |
28 | #include
29 | #include
30 | #include
31 |
32 | #include
33 |
34 | class queue_message
35 | {
36 | public:
37 | enum class message
38 | { setopenstatus, reconvertstring, documentfeed,
39 | backward_char, delete_char
40 | };
41 |
42 | explicit queue_message (message msg, HWND hwnd):
43 | message_ (msg), hwnd_ (hwnd), parameter_ (0)
44 | {
45 | }
46 | explicit queue_message (message msg, HWND hwnd, int param):
47 | message_ (msg), hwnd_ (hwnd), parameter_ (param)
48 | {
49 | }
50 | virtual ~queue_message ()
51 | {
52 | }
53 |
54 | message get_message (void) const
55 | {
56 | return message_;
57 | }
58 | HWND get_hwnd (void) const
59 | {
60 | return hwnd_;
61 | }
62 | int get_parameter (void) const
63 | {
64 | return parameter_;
65 | }
66 |
67 | private:
68 | const message message_;
69 | const HWND hwnd_;
70 | const int parameter_;
71 | };
72 |
73 | class ui_to_lisp_queue
74 | {
75 | public:
76 | explicit ui_to_lisp_queue () = delete;
77 | ~ui_to_lisp_queue () = delete;
78 | ui_to_lisp_queue (const ui_to_lisp_queue &) = delete;
79 | ui_to_lisp_queue (ui_to_lisp_queue &&) = delete;
80 | ui_to_lisp_queue& operator = (const ui_to_lisp_queue &) = delete;
81 | ui_to_lisp_queue& operator = (ui_to_lisp_queue &&) = delete;
82 |
83 | static bool empty(void);
84 | static void enqueue (std::unique_ptr &&);
85 | static void enqueue_fast (std::unique_ptr &&);
86 | static void enqueue_one (std::unique_ptr &&);
87 | static void enqueue_fast_one (std::unique_ptr &&);
88 | static std::unique_ptr dequeue (void);
89 |
90 | private:
91 | static std::mutex mtx_;
92 | static std::deque> queue_;
93 | };
94 |
95 | #endif // INCLUDE_GUARD_QUEUE_HH
96 |
--------------------------------------------------------------------------------
/src/subclass_proc.hh:
--------------------------------------------------------------------------------
1 | // -*- mode: c++; coding: utf-8 -*-
2 |
3 | // This file is part of
4 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
5 | // https://github.com/trueroad/tr-emacs-ime-module
6 | //
7 | // Copyright (C) 2020 Masamichi Hosoda
8 | //
9 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
10 | // is free software: you can redistribute it and/or modify
11 | // it under the terms of the GNU General Public License as published by
12 | // the Free Software Foundation, either version 3 of the License, or
13 | // (at your option) any later version.
14 | //
15 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
16 | // is distributed in the hope that it will be useful,
17 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | // GNU General Public License for more details.
20 | //
21 | // You should have received a copy of the GNU General Public License
22 | // along with tr-ime.
23 | // If not, see .
24 |
25 | #ifndef INCLUDE_GUARD_SUBCLASS_PROC_HH
26 | #define INCLUDE_GUARD_SUBCLASS_PROC_HH
27 |
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 |
35 | #include
36 |
37 | class subclass_proc final
38 | {
39 | public:
40 | static LRESULT CALLBACK
41 | proc (HWND, UINT, WPARAM, LPARAM, UINT_PTR, DWORD_PTR);
42 |
43 | explicit subclass_proc () = delete;
44 | ~subclass_proc () = delete;
45 | subclass_proc (const subclass_proc &) = delete;
46 | subclass_proc (subclass_proc &&) = delete;
47 | subclass_proc& operator = (const subclass_proc &) = delete;
48 | subclass_proc& operator = (subclass_proc &&) = delete;
49 |
50 | static constexpr UINT_PTR get_subclass_id (void)
51 | {
52 | return subclass_id_;
53 | }
54 |
55 | static void lisp_resume_prefix_key (void)
56 | {
57 | prefix_key::lisp_resume ();
58 | }
59 | static void lisp_set_startcomposition_defsubclassproc (bool flag)
60 | {
61 | ab_startcomposition_defsubclassproc_.store (flag);
62 | }
63 | static void lisp_set_reconversion (bool flag)
64 | {
65 | ab_reconversion_.store (flag);
66 | }
67 | static void lisp_set_documentfeed (bool flag)
68 | {
69 | ab_documentfeed_.store (flag);
70 | }
71 |
72 | static void set_last_ime_state (bool flag)
73 | {
74 | ab_last_ime_state_set_.store (flag);
75 | }
76 |
77 | private:
78 | class prefix_key
79 | {
80 | public:
81 | static void set (HWND);
82 | static void lisp_resume (void);
83 | private:
84 | static std::mutex mtx_;
85 | static HWND hwnd_;
86 | static bool b_before_ime_mode_;
87 | };
88 |
89 | class reconvert_string
90 | {
91 | public:
92 | // offset is a byte count from the beginning of the string
93 | // to indicate the cursor position, similar to
94 | // RECONVERTSTRING dwCompStrOffset.
95 | static void set (std::basic_string &&str, DWORD offset)
96 | {
97 | str_ = std::move (str);
98 | offset_ = offset;
99 | len_ = 0;
100 | ab_set_.store (true);
101 | }
102 | static void add_comp (const std::basic_string &compstr)
103 | {
104 | str_.insert (offset_ / sizeof (WCHAR), compstr);
105 | len_ = compstr.size ();
106 | }
107 | static void clear (void)
108 | {
109 | ab_set_.store (false);
110 | }
111 | static std::basic_string &get_str (void)
112 | {
113 | return str_;
114 | }
115 | // For RECONVERTSTRING dwSize
116 | // byte count for the struct
117 | static DWORD get_dwSize (void)
118 | {
119 | return sizeof (RECONVERTSTRING) +
120 | (get_dwStrLen () + 1) * sizeof (WCHAR);
121 | }
122 | // For RECONVERTSTRING dwStrLen
123 | // WCHAR count for the length of the full string
124 | static DWORD get_dwStrLen (void)
125 | {
126 | return str_.size ();
127 | }
128 | // For RECONVERTSTRING dwStrOffset
129 | // byte count from the beginning of the struct to indicate the offset
130 | // of the full string
131 | static constexpr DWORD get_dwStrOffset (void)
132 | {
133 | return sizeof (RECONVERTSTRING);
134 | }
135 | // For RECONVERTSTRING dwComStrOffset
136 | // byte count from the beginning of the string to indicate the offset
137 | // of the composition string
138 | static DWORD get_dwCompStrOffset (void)
139 | {
140 | return offset_;
141 | }
142 | // For RECONVERTSTRING dwCompStrLen
143 | // WCHAR count for the length of the composition string
144 | static DWORD get_dwCompStrLen (void)
145 | {
146 | return len_;
147 | }
148 | static bool isset (void)
149 | {
150 | return ab_set_.load ();
151 | }
152 | private:
153 | static thread_local std::basic_string str_;
154 | static thread_local DWORD offset_;
155 | static thread_local DWORD len_;
156 | static thread_local std::atomic ab_set_;
157 | };
158 |
159 | class backward_complete
160 | {
161 | public:
162 | static void set(void)
163 | {
164 | ab_set_.store (true);
165 | }
166 | static void clear (void)
167 | {
168 | ab_set_.store (false);
169 | }
170 | static bool isset (void)
171 | {
172 | return ab_set_.load ();
173 | }
174 | private:
175 | static thread_local std::atomic ab_set_;
176 | };
177 |
178 | static bool wait_message (HWND, std::function);
179 | static bool set_reconvert_string (RECONVERTSTRING*);
180 |
181 | static LRESULT wm_tr_ime_set_open_status (HWND, UINT, WPARAM, LPARAM);
182 | static LRESULT wm_tr_ime_get_open_status (HWND, UINT, WPARAM, LPARAM);
183 | static LRESULT wm_tr_ime_set_font (HWND, UINT, WPARAM, LPARAM);
184 | static LRESULT wm_tr_ime_set_compositionwindow (HWND, UINT, WPARAM, LPARAM);
185 | static LRESULT wm_tr_ime_set_prefix_keys (HWND, UINT, WPARAM, LPARAM);
186 | static LRESULT
187 | wm_tr_ime_notify_reconvert_string (HWND, UINT, WPARAM, LPARAM);
188 | static LRESULT
189 | wm_tr_ime_notify_backward_complete (HWND, UINT, WPARAM, LPARAM);
190 |
191 | static bool get_reconvert_string (HWND, bool);
192 | static bool add_composition_string (HWND);
193 | static void process_backward_characters (HWND, RECONVERTSTRING*, DWORD);
194 | static void process_delete_characters (HWND, RECONVERTSTRING*);
195 | static LRESULT imr_reconvertstring (HWND, UINT, WPARAM, LPARAM);
196 | static LRESULT imr_documentfeed (HWND, UINT, WPARAM, LPARAM);
197 |
198 | static LRESULT wm_keydown (HWND, UINT, WPARAM, LPARAM);
199 | static LRESULT wm_ime_notify (HWND, UINT, WPARAM, LPARAM);
200 | static LRESULT wm_ime_request (HWND, UINT, WPARAM, LPARAM);
201 | static LRESULT wm_ime_composition (HWND, UINT, WPARAM, LPARAM);
202 | static LRESULT wm_ime_startcomposition (HWND, UINT, WPARAM, LPARAM);
203 | static LRESULT wm_ime_endcomposition (HWND, UINT, WPARAM, LPARAM);
204 |
205 | static constexpr UINT_PTR subclass_id_ {0};
206 | static thread_local LOGFONTW lf_imefont_;
207 | static thread_local COMPOSITIONFORM compform_;
208 | static thread_local std::unordered_set prefix_keys_;
209 | static std::atomic ab_startcomposition_defsubclassproc_;
210 | static std::atomic ab_last_ime_state_set_;
211 | static std::atomic ab_reconversion_;
212 | static std::atomic ab_documentfeed_;
213 | static std::atomic ai_delete_chars_reconversion_complete_;
214 | static thread_local std::unordered_set compositioning_hwnds_;
215 |
216 | static constexpr int i_wait_message_times_ = 100;
217 | static constexpr DWORD dw_wait_message_single_ = 1000;
218 | static constexpr DWORD dw_wait_message_total_ = 3000;
219 | };
220 |
221 | #endif // INCLUDE_GUARD_SUBCLASS_PROC_HH
222 |
--------------------------------------------------------------------------------
/src/tr-ime-mod-resource.rc:
--------------------------------------------------------------------------------
1 | // -*- coding: utf-8 -*-
2 |
3 | // This file is part of
4 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
5 | // https://github.com/trueroad/tr-emacs-ime-module
6 | //
7 | // Copyright (C) 2020 Masamichi Hosoda
8 | //
9 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
10 | // is free software: you can redistribute it and/or modify
11 | // it under the terms of the GNU General Public License as published by
12 | // the Free Software Foundation, either version 3 of the License, or
13 | // (at your option) any later version.
14 | //
15 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
16 | // is distributed in the hope that it will be useful,
17 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | // GNU General Public License for more details.
20 | //
21 | // You should have received a copy of the GNU General Public License
22 | // along with tr-ime.
23 | // If not, see .
24 |
25 | #include "config.h"
26 |
27 | #include
28 |
29 | // UTF-8
30 | #pragma code_page(65001)
31 |
32 | VS_VERSION_INFO VERSIONINFO
33 | FILEVERSION PACKAGE_FILEVERSION
34 | PRODUCTVERSION PACKAGE_PRODUCTVERSION
35 | FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
36 | FILEFLAGS VS_FF_PRERELEASE
37 | FILETYPE VFT_DLL
38 | FILESUBTYPE VFT2_UNKNOWN
39 | BEGIN
40 | BLOCK "StringFileInfo"
41 | BEGIN
42 | BLOCK "040904b0"
43 | BEGIN
44 | VALUE "FileDescription", PACKAGE_NAME " (" PACKAGE ")\0"
45 | VALUE "FileVersion", PACKAGE_VERSION "\0"
46 | VALUE "InternalName", PACKAGE "\0"
47 | VALUE "LegalCopyright", \
48 | PACKAGE_COPYRIGHT " " PACKAGE_LICENSE "\0"
49 | VALUE "LegalTrademarks", PACKAGE_URL "\0"
50 | VALUE "OriginalFilename", "tr-ime-mod-" \
51 | MOD_ABI_VERSION "-" HOST_PLATFORM ".dll\0"
52 | VALUE "ProductName", PACKAGE_NAME "\0"
53 | VALUE "ProductVersion", PACKAGE_VERSION "\0"
54 | END
55 | END
56 | BLOCK "VarFileInfo"
57 | BEGIN
58 | VALUE "Translation", 0x409, 0x04B0
59 | END
60 | END
61 |
--------------------------------------------------------------------------------
/src/tr-ime-mod.c:
--------------------------------------------------------------------------------
1 | // -*- mode: c; coding: utf-8 -*-
2 |
3 | // This file is part of
4 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
5 | // https://github.com/trueroad/tr-emacs-ime-module
6 | //
7 | // Copyright (C) 2020 Masamichi Hosoda
8 | //
9 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
10 | // is free software: you can redistribute it and/or modify
11 | // it under the terms of the GNU General Public License as published by
12 | // the Free Software Foundation, either version 3 of the License, or
13 | // (at your option) any later version.
14 | //
15 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
16 | // is distributed in the hope that it will be useful,
17 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | // GNU General Public License for more details.
20 | //
21 | // You should have received a copy of the GNU General Public License
22 | // along with tr-ime.
23 | // If not, see .
24 |
25 | #define TR_IME_MOD_DLL __declspec(dllexport)
26 |
27 | #include "config.h"
28 |
29 | #include
30 | #include
31 | #include
32 |
33 | // Microsoft undocumented
34 | #ifndef IMC_GETOPENSTATUS
35 | #define IMC_GETOPENSTATUS 0x0005
36 | #endif
37 | #ifndef IMC_SETOPENSTATUS
38 | #define IMC_SETOPENSTATUS 0x0006
39 | #endif
40 |
41 | int TR_IME_MOD_DLL plugin_is_GPL_compatible;
42 |
43 | static emacs_value
44 | tr_ime_mod__setopenstatus
45 | (emacs_env *env, ptrdiff_t nargs, emacs_value *args, void *data)
46 | {
47 | if (nargs != 2)
48 | {
49 | OutputDebugString ("tr_ime_mod__setopenstatus: nargs != 2\n");
50 | return env->intern (env, "nil");
51 | }
52 |
53 | HWND hwnd = (HWND)(env->extract_integer (env, args[0]));
54 | BOOL bopen = env->is_not_nil (env, args[1]);
55 |
56 | if (!IsWindow (hwnd))
57 | {
58 | OutputDebugString ("tr_ime_mod__setopenstatus: hwnd is not window\n");
59 | return env->intern (env, "nil");
60 | }
61 |
62 | HWND hwnd_ime = ImmGetDefaultIMEWnd (hwnd);
63 | if (!hwnd_ime)
64 | {
65 | OutputDebugString
66 | ("tr_ime_mod__setopenstatus: ImmGetDefaultIMEWnd failed\n");
67 | return env->intern (env, "nil");
68 | }
69 |
70 | // PostMessage does not work.
71 | LRESULT r = SendMessageW (hwnd_ime, WM_IME_CONTROL,
72 | IMC_SETOPENSTATUS, (LPARAM)bopen);
73 |
74 | if (r)
75 | {
76 | OutputDebugString
77 | ("tr_ime_mod__setopenstatus: IMC_SETOPENSTATUS failed\n");
78 | return env->intern (env, "nil");
79 | }
80 |
81 | return env->intern (env, "t");
82 | }
83 |
84 | static emacs_value
85 | tr_ime_mod__getopenstatus
86 | (emacs_env *env, ptrdiff_t nargs, emacs_value *args, void *data)
87 | {
88 | if (nargs != 1)
89 | {
90 | OutputDebugString ("tr_ime_mod__getopenstatus: nargs != 1\n");
91 | return env->intern (env, "nil");
92 | }
93 |
94 | HWND hwnd = (HWND)(env->extract_integer (env, args[0]));
95 |
96 | if (!IsWindow (hwnd))
97 | {
98 | OutputDebugString ("tr_ime_mod__getopenstatus: hwnd is not window\n");
99 | return env->intern (env, "nil");
100 | }
101 |
102 | HWND hwnd_ime = ImmGetDefaultIMEWnd (hwnd);
103 | if (!hwnd_ime)
104 | {
105 | OutputDebugString
106 | ("tr_ime_mod__getopenstatus: ImmGetDefaultIMEWnd failed\n");
107 | return env->intern (env, "nil");
108 | }
109 |
110 | LRESULT r = SendMessageW (hwnd_ime, WM_IME_CONTROL,
111 | IMC_GETOPENSTATUS, 0);
112 |
113 | if (r)
114 | return env->intern (env, "t"); // IME on
115 |
116 | return env->intern (env, "nil"); // IME off
117 | }
118 |
119 | static void
120 | regist_function (emacs_env *env,
121 | const char *name,
122 | ptrdiff_t min_arity,
123 | ptrdiff_t max_arity,
124 | emacs_value (*function) (emacs_env *env,
125 | ptrdiff_t nargs,
126 | emacs_value args[],
127 | void *),
128 | const char *documentation,
129 | void *data)
130 | {
131 | emacs_value defalias = env->intern (env, "defalias");
132 | emacs_value symbol = env->intern (env, name);
133 | emacs_value func =
134 | env->make_function (env, min_arity, max_arity, function,
135 | documentation, data);
136 | emacs_value args[] = {symbol, func};
137 |
138 | env->funcall (env, defalias, sizeof (args) / sizeof (args[0]), args);
139 | }
140 |
141 | static void
142 | provide_feature (emacs_env *env, const char *name)
143 | {
144 | emacs_value provide = env->intern (env, "provide");
145 | emacs_value feature = env->intern (env, name);
146 | emacs_value args[] = {feature};
147 |
148 | env->funcall (env, provide, sizeof (args) / sizeof (args[0]), args);
149 | }
150 |
151 | int TR_IME_MOD_DLL
152 | emacs_module_init (struct emacs_runtime *ert)
153 | {
154 | if (ert->size < sizeof (*ert))
155 | {
156 | OutputDebugString ("tr-ime-mod: ert->size < sizeof (*ert)\n");
157 | return 1;
158 | }
159 |
160 | emacs_env *env = ert->get_environment (ert);
161 | if (env->size < sizeof (*env))
162 | {
163 | OutputDebugString ("tr-ime-mod: env->size < sizeof (*env)\n");
164 | return 2;
165 | }
166 |
167 | regist_function (env, "tr-ime-mod--setopenstatus",
168 | 2, 2, tr_ime_mod__setopenstatus,
169 | "Send WM_IME_CONTROL message with IMC_SETOPENSTATUS (undocumented).\n\n"
170 | "ARG1 is interpreted as HWND and ARG2 is interpreted as BOOL.\n"
171 | "The message is then sent to the default IME window of the HWND.\n"
172 | "If the BOOL is FALSE, IME is turned off, otherwise, IME is turned on.\n\n"
173 | "Sample usage:\n"
174 | "(tr-ime-mod--setopenstatus\n"
175 | " (string-to-number (frame-parameter nil 'window-id)) t)",
176 | NULL);
177 | regist_function (env, "tr-ime-mod--getopenstatus",
178 | 1, 1, tr_ime_mod__getopenstatus,
179 | "Send WM_IME_CONTROL message with IMC_GETOPENSTATUS (undocumented).\n\n"
180 | "ARG1 is interpreted as HWND.\n"
181 | "The message is then sent to the default IME window of the HWND.\n"
182 | "If IME is off, nil is returned, otherwise non-nil is returned.\n\n"
183 | "Sample usage:\n"
184 | "(tr-ime-mod--getopenstatus\n"
185 | " (string-to-number (frame-parameter nil 'window-id)))",
186 | NULL);
187 | provide_feature (env, "tr-ime-mod");
188 |
189 | return 0;
190 | }
191 |
--------------------------------------------------------------------------------
/src/tr-ime-modadv-resource.rc:
--------------------------------------------------------------------------------
1 | // -*- coding: utf-8 -*-
2 |
3 | // This file is part of
4 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
5 | // https://github.com/trueroad/tr-emacs-ime-module
6 | //
7 | // Copyright (C) 2020 Masamichi Hosoda
8 | //
9 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
10 | // is free software: you can redistribute it and/or modify
11 | // it under the terms of the GNU General Public License as published by
12 | // the Free Software Foundation, either version 3 of the License, or
13 | // (at your option) any later version.
14 | //
15 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
16 | // is distributed in the hope that it will be useful,
17 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | // GNU General Public License for more details.
20 | //
21 | // You should have received a copy of the GNU General Public License
22 | // along with tr-ime.
23 | // If not, see .
24 |
25 | #include "config.h"
26 |
27 | #include
28 |
29 | // UTF-8
30 | #pragma code_page(65001)
31 |
32 | VS_VERSION_INFO VERSIONINFO
33 | FILEVERSION PACKAGE_FILEVERSION
34 | PRODUCTVERSION PACKAGE_PRODUCTVERSION
35 | FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
36 | FILEFLAGS VS_FF_PRERELEASE
37 | FILETYPE VFT_DLL
38 | FILESUBTYPE VFT2_UNKNOWN
39 | BEGIN
40 | BLOCK "StringFileInfo"
41 | BEGIN
42 | BLOCK "040904b0"
43 | BEGIN
44 | VALUE "FileDescription", PACKAGE_NAME " (" PACKAGE ")\0"
45 | VALUE "FileVersion", PACKAGE_VERSION "\0"
46 | VALUE "InternalName", PACKAGE "\0"
47 | VALUE "LegalCopyright", \
48 | PACKAGE_COPYRIGHT " " PACKAGE_LICENSE "\0"
49 | VALUE "LegalTrademarks", PACKAGE_URL "\0"
50 | VALUE "OriginalFilename", "tr-ime-modadv-" \
51 | MODADV_ABI_VERSION "-" HOST_PLATFORM ".dll\0"
52 | VALUE "ProductName", PACKAGE_NAME "\0"
53 | VALUE "ProductVersion", PACKAGE_VERSION "\0"
54 | END
55 | END
56 | BLOCK "VarFileInfo"
57 | BEGIN
58 | VALUE "Translation", 0x409, 0x04B0
59 | END
60 | END
61 |
--------------------------------------------------------------------------------
/src/tr-ime-modadv.cc:
--------------------------------------------------------------------------------
1 | // -*- mode: c++; coding: utf-8 -*-
2 |
3 | // This file is part of
4 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
5 | // https://github.com/trueroad/tr-emacs-ime-module
6 | //
7 | // Copyright (C) 2020, 2022 Masamichi Hosoda
8 | //
9 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
10 | // is free software: you can redistribute it and/or modify
11 | // it under the terms of the GNU General Public License as published by
12 | // the Free Software Foundation, either version 3 of the License, or
13 | // (at your option) any later version.
14 | //
15 | // Emulator of GNU Emacs IME patch for Windows (tr-ime)
16 | // is distributed in the hope that it will be useful,
17 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | // GNU General Public License for more details.
20 | //
21 | // You should have received a copy of the GNU General Public License
22 | // along with tr-ime.
23 | // If not, see .
24 |
25 | #define TR_IME_MODADV_DLL __declspec(dllexport)
26 |
27 | #ifdef HAVE_CONFIG_H
28 | #include "config.h"
29 | #endif
30 |
31 | #include
32 | #include
33 |
34 | #include
35 |
36 | #include
37 |
38 | #include "debug-message.hh"
39 | #include "lisp-in-cc.hh"
40 |
41 | int TR_IME_MODADV_DLL plugin_is_GPL_compatible;
42 |
43 | namespace
44 | {
45 | void
46 | regist_function (emacs_env *env,
47 | const char *name,
48 | ptrdiff_t min_arity,
49 | ptrdiff_t max_arity,
50 | emacs_value (*function) (emacs_env *env,
51 | ptrdiff_t nargs,
52 | emacs_value args[],
53 | void *) noexcept,
54 | const char *documentation,
55 | void *data)
56 | {
57 | emacs_value defalias = env->intern (env, "defalias");
58 | emacs_value symbol = env->intern (env, name);
59 | emacs_value func =
60 | env->make_function (env, min_arity, max_arity, function,
61 | documentation, data);
62 | std::array args {symbol, func};
63 |
64 | env->funcall (env, defalias, args.size (), args.data ());
65 | }
66 |
67 | void
68 | regist_variable (emacs_env *env,
69 | const char *name,
70 | emacs_value value,
71 | const std::string &documentation)
72 | {
73 | std::array args_form
74 | {
75 | env->intern (env, "defvar"),
76 | env->intern (env, name),
77 | value,
78 | env->make_string (env, documentation.data (), documentation.size ())
79 | };
80 | emacs_value form = env->funcall (env, env->intern (env, "list"),
81 | args_form.size (), args_form.data ());
82 |
83 | std::array args_eval {form, env->intern (env, "t")};
84 | env->funcall (env, env->intern (env, "eval"),
85 | args_eval.size (), args_eval.data ());
86 | }
87 |
88 | void
89 | provide_feature (emacs_env *env, const char *name)
90 | {
91 | emacs_value provide = env->intern (env, "provide");
92 | emacs_value feature = env->intern (env, name);
93 | std::array args {feature};
94 |
95 | env->funcall (env, provide, args.size (), args.data ());
96 | }
97 | };
98 |
99 | int TR_IME_MODADV_DLL
100 | emacs_module_init (struct emacs_runtime *ert) EMACS_NOEXCEPT
101 | {
102 | DEBUG_MESSAGE ("enter\n");
103 |
104 | if (ert->size < sizeof (*ert))
105 | {
106 | WARNING_MESSAGE ("ert->size < sizeof (*ert)\n");
107 | return 1;
108 | }
109 |
110 | emacs_env *env = ert->get_environment (ert);
111 | if (env->size < sizeof (*env))
112 | {
113 | WARNING_MESSAGE ("env->size < sizeof (*env)\n");
114 | return 2;
115 | }
116 |
117 | regist_function (env, "tr-ime-modadv--install-message-hook-hwnd",
118 | 1, 1, Ftr_ime_modadv__install_message_hook_hwnd,
119 | doc_tr_ime_modadv__install_message_hook_hwnd,
120 | nullptr);
121 | regist_function (env, "tr-ime-modadv--uninstall-message-hook-hwnd",
122 | 1, 1, Ftr_ime_modadv__uninstall_message_hook_hwnd,
123 | doc_tr_ime_modadv__uninstall_message_hook_hwnd,
124 | nullptr);
125 | regist_function (env, "tr-ime-modadv--subclassify-hwnd",
126 | 1, 2, Ftr_ime_modadv__subclassify_hwnd,
127 | doc_tr_ime_modadv__subclassify_hwnd,
128 | nullptr);
129 | regist_function (env, "tr-ime-modadv--unsubclassify-hwnd",
130 | 0, 2, Ftr_ime_modadv__unsubclassify_hwnd,
131 | doc_tr_ime_modadv__unsubclassify_hwnd,
132 | nullptr);
133 | regist_function (env, "tr-ime-modadv--exists-subclassified",
134 | 0, 0, Ftr_ime_modadv__exists_subclassified,
135 | doc_tr_ime_modadv__exists_subclassified,
136 | nullptr);
137 | regist_function (env, "tr-ime-modadv--set-dispatch-thread-message",
138 | 1, 1, Ftr_ime_modadv__set_dispatch_thread_message,
139 | doc_tr_ime_modadv__set_dispatch_thread_message,
140 | nullptr);
141 | regist_function (env, "tr-ime-modadv--set-dispatch-thread-wm-timer",
142 | 1, 1, Ftr_ime_modadv__set_dispatch_thread_wm_timer,
143 | doc_tr_ime_modadv__set_dispatch_thread_wm_timer,
144 | nullptr);
145 | regist_function (env, "tr-ime-modadv--setopenstatus",
146 | 2, 2, Ftr_ime_modadv__setopenstatus,
147 | doc_tr_ime_modadv__setopenstatus,
148 | nullptr);
149 | regist_function (env, "tr-ime-modadv--getopenstatus",
150 | 1, 1, Ftr_ime_modadv__getopenstatus,
151 | doc_tr_ime_modadv__getopenstatus,
152 | nullptr);
153 | regist_function (env, "tr-ime-modadv--set-font",
154 | 15, 15, Ftr_ime_modadv__set_font,
155 | doc_tr_ime_modadv__set_font,
156 | nullptr);
157 | regist_function (env, "tr-ime-modadv--set-composition-window",
158 | 8, 8, Ftr_ime_modadv__set_composition_window,
159 | doc_tr_ime_modadv__set_composition_window,
160 | nullptr);
161 | regist_function (env, "tr-ime-modadv--set-startcomposition-defsubclassproc",
162 | 2, 2, Ftr_ime_modadv__set_startcomposition_defsubclassproc,
163 | doc_tr_ime_modadv__set_startcomposition_defsubclassproc,
164 | nullptr);
165 | regist_function (env, "tr-ime-modadv--set-prefix-keys",
166 | 2, 2, Ftr_ime_modadv__set_prefix_keys,
167 | doc_tr_ime_modadv__set_prefix_keys,
168 | nullptr);
169 | regist_function (env, "tr-ime-modadv--resume-prefix-key",
170 | 0, 0, Ftr_ime_modadv__resume_prefix_key,
171 | doc_tr_ime_modadv__resume_prefix_key,
172 | nullptr);
173 | regist_variable (env, "tr-ime-modadv--setopenstatus-hook",
174 | env->intern (env, "nil"),
175 | doc_tr_ime_modadv__setopenstatus_hook);
176 | regist_variable (env, "tr-ime-modadv--reconvertstring-hook",
177 | env->intern (env, "nil"),
178 | doc_tr_ime_modadv__reconvertstring_hook);
179 | regist_variable (env, "tr-ime-modadv--documentfeed-hook",
180 | env->intern (env, "nil"),
181 | doc_tr_ime_modadv__documentfeed_hook);
182 | regist_function (env, "tr-ime-modadv--language-change-handler",
183 | 0, 0, Ftr_ime_modadv__language_change_handler,
184 | doc_tr_ime_modadv__language_change_handler,
185 | nullptr);
186 | regist_function (env, "tr-ime-modadv--notify-reconvert-string",
187 | 3, 3, Ftr_ime_modadv__notify_reconvert_string,
188 | doc_tr_ime_modadv__notify_reconvert_string,
189 | nullptr);
190 | regist_function (env, "tr-ime-modadv--set-reconversion",
191 | 2, 2, Ftr_ime_modadv__set_reconversion,
192 | doc_tr_ime_modadv__set_reconversion,
193 | nullptr);
194 | regist_function (env, "tr-ime-modadv--set-documentfeed",
195 | 2, 2, Ftr_ime_modadv__set_documentfeed,
196 | doc_tr_ime_modadv__set_documentfeed,
197 | nullptr);
198 | regist_function (env, "tr-ime-modadv--get-dpi",
199 | 0, 0, Ftr_ime_modadv__get_dpi,
200 | doc_tr_ime_modadv__get_dpi,
201 | nullptr);
202 | regist_function (env, "tr-ime-modadv--set-verbose-level",
203 | 1, 1, Ftr_ime_modadv__set_verbose_level,
204 | doc_tr_ime_modadv__set_verbose_level,
205 | nullptr);
206 | regist_function (env, "tr-ime-modadv-unload-function",
207 | 0, 0, Ftr_ime_modadv_unload_function,
208 | doc_tr_ime_modadv_unload_function,
209 | nullptr);
210 |
211 | #ifndef NDEBUG
212 |
213 | regist_function (env, "tr-ime-modadv--debug-output",
214 | 1, 1, Ftr_ime_modadv__debug_output,
215 | doc_tr_ime_modadv__debug_output,
216 | nullptr);
217 | regist_function (env, "tr-ime-modadv--debug-rectangle",
218 | 5, 5, Ftr_ime_modadv__debug_rectangle,
219 | doc_tr_ime_modadv__debug_rectangle,
220 | nullptr);
221 |
222 | #endif // NDEBUG
223 |
224 | provide_feature (env, "tr-ime-modadv");
225 |
226 | return 0;
227 | }
228 |
229 | #ifndef NDEBUG
230 | extern "C"
231 | BOOL WINAPI DllMain (HINSTANCE, DWORD dwReason, LPVOID)
232 | {
233 | switch (dwReason)
234 | {
235 | case DLL_PROCESS_ATTACH:
236 | DEBUG_MESSAGE_STATIC ("debug: DllMain: DLL_PROCESS_ATTACH\n");
237 | break;
238 |
239 | case DLL_THREAD_ATTACH:
240 | DEBUG_MESSAGE_STATIC ("debug: DllMain: DLL_THREAD_ATTACH\n");
241 | break;
242 |
243 | case DLL_PROCESS_DETACH:
244 | DEBUG_MESSAGE_STATIC ("debug: DllMain: DLL_PROCESS_DETACH\n");
245 | break;
246 |
247 | case DLL_THREAD_DETACH:
248 | DEBUG_MESSAGE_STATIC ("debug: DllMain: DLL_THREAD_DETACH\n");
249 | break;
250 |
251 | default:
252 | DEBUG_MESSAGE_STATIC ("debug: DllMain: dwReason is unknown\n");
253 | break;
254 | }
255 |
256 | return TRUE;
257 | }
258 | #endif // NDEBUG
259 |
--------------------------------------------------------------------------------