Skip to content

Instantly share code, notes, and snippets.

@rzl24ozi
Last active February 23, 2018 22:10
Show Gist options
  • Save rzl24ozi/8c20b904c9f5e588ba99 to your computer and use it in GitHub Desktop.
Save rzl24ozi/8c20b904c9f5e588ba99 to your computer and use it in GitHub Desktop.
add w32-ime support to emacs with Windows GUI
--- ./configure.ac.orig 2017-09-12 01:55:00.000000000 +0900
+++ ./configure.ac 2017-09-13 21:00:32.623281500 +0900
@@ -346,6 +346,10 @@
On by default on macOS.])],[],[with_ns=maybe])
OPTION_DEFAULT_OFF([w32], [use native MS Windows GUI in a Cygwin build])
+OPTION_DEFAULT_ON([w32-ime], [don't compile with W32-IME support])
+OPTION_DEFAULT_ON([reconversion], [don't compile with RECONVERSION support])
+OPTION_DEFAULT_ON([documentfeed], [don't compile with DOCUMENTFEED support])
+
OPTION_DEFAULT_ON([gpm],[don't use -lgpm for mouse support on a GNU/Linux console])
OPTION_DEFAULT_ON([dbus],[don't compile with D-Bus support])
OPTION_DEFAULT_ON([gconf],[don't compile with GConf support])
@@ -5251,6 +5255,42 @@
ACL_SUMMARY=no
fi
+USE_W32_IME=no
+if test "${HAVE_W32}" = "yes"; then
+ if test "${with_w32_ime}" != "no"; then
+ USE_W32_IME=yes
+ AC_DEFINE(USE_W32_IME, 1, [Define to support W32-IME.])
+
+ RECONVERSION=no
+ if test "${with_reconversion}" != "no"; then
+ AC_CACHE_CHECK([whether RECONVERTSTRING is declared],
+ emacs_cv_have_reconvertstring,
+ [AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+#include <windows.h>
+#include <imm.h>]], [[RECONVERTSTRING]])],
+ emacs_cv_have_reconvertstring=yes, emacs_cv_have_reconvertstring=no)])
+ if test "$emacs_cv_have_reconvertstring" = "yes"; then
+ RECONVERSION=yes
+ AC_DEFINE(RECONVERSION, 1, [Define to support RECONVERSION.])
+ AC_DEFINE(HAVE_RECONVERTSTRING, 1, [Define to 1 if you have RECONVERTSTRING.])
+
+ DOCUMENTFEED=no
+ if test "${with_documentfeed}" != "no"; then
+ AC_CHECK_DECL(IMR_DOCUMENTFEED, HAVE_IMR_DOCUMENTFEED=yes,
+ HAVE_IMR_DOCUMENTFEED=no,[[
+#include <windows.h>
+#include <imm.h>]])
+ if test "$ac_cv_have_decl_IMR_DOCUMENTFEED" = "yes"; then
+ DOCUMENTFEED=yes
+ AC_DEFINE(DOCUMENTFEED, 1, [Define to support DOCUMENTFEED.])
+ AC_DEFINE(HAVE_IMR_DOCUMENTFEED, 1, [Define to 1 if you have IMR_DOCUMENTFEED.])
+ fi
+ fi
+ fi
+ fi
+ fi
+fi
+
emacs_standard_dirs='Standard dirs'
AS_ECHO(["
Configured for '${canonical}'.
@@ -5291,6 +5331,10 @@
AS_VAR_APPEND([emacs_config_features], ["$optsep$opt"])
optsep=' '
done
+if test "${USE_W32_IME}" = "yes"; then
+ opt=W32_IME
+ AS_VAR_APPEND([emacs_config_features], ["$optsep$opt"])
+fi
AC_DEFINE_UNQUOTED(EMACS_CONFIG_FEATURES, "${emacs_config_features}",
[Summary of some of the main features enabled by configure.])
@@ -5323,6 +5367,16 @@
Does Emacs support Xwidgets (requires gtk3)? ${HAVE_XWIDGETS}
"])
+if test "${HAVE_W32}" = "yes"; then
+ AS_ECHO([" Does Emacs support W32-IME? ${USE_W32_IME}"])
+ if test "${USE_W32_IME}" = "yes"; then
+ AS_ECHO([" Does Emacs support RECONVERSION? ${RECONVERSION}"])
+ if test "${RECONVERSION}" = "yes"; then
+ AS_ECHO([" Does Emacs support DOCUMENTFEED? ${DOCUMENTFEED}"])
+ fi
+ fi
+fi
+
if test -n "${EMACSDATA}"; then
AS_ECHO([" Environment variable EMACSDATA set to: $EMACSDATA"])
fi
--- /dev/null 2017-09-13 21:00:35.000000000 +0900
+++ ./lisp/international/w32-ime.el 2017-09-13 21:00:32.634304500 +0900
@@ -0,0 +1,201 @@
+;;;;; w32-ime.el ---- Meadow features for NTEmacs.
+;;
+;; Author H.Miyashita
+;;
+;;;;;
+
+(defgroup W32-IME nil
+ "w32-ime"
+ :group 'emacs)
+
+(defvar w32-last-selection nil
+ "It is stored the last data from Emacs.")
+
+;----------
+
+(defvar w32-ime-on-hook nil
+ "Functions to eval when IME is turned on at least.
+Even if IME state is not changed, these functiona are maybe called.")
+(defvar w32-ime-off-hook nil
+ "Functions to eval when IME is turned off at least.
+Even if IME state is not changed, these functiona are maybe called.")
+(defvar w32-ime-buffer-switch-p t
+ "If this variable is nil, IME control when buffer is switched is disabled.")
+(defvar w32-ime-show-mode-line t
+ "When t, mode line indicates IME state.")
+(defvar w32-ime-mode-line-state-indicator "[O]"
+ "This is shown at the mode line. It is regarded as state of ime.")
+(make-variable-buffer-local 'w32-ime-mode-line-state-indicator)
+(put 'w32-ime-mode-line-state-indicator 'permanent-local t)
+(defvar w32-ime-mode-line-state-indicator-list '("-" "[|]" "[O]")
+ "List of IME state indicator string.")
+(defvar w32-ime-mode-line-format-original nil
+ "Original mode line format.")
+
+;;
+;; Section: IME
+;;
+
+;; ;; This is temporal solution. In the future, we will prepare
+;; ;; dynamic configuration.
+;; (defvar w32-ime-coding-system-language-environment-alist
+;; '(("Japanese" . japanese-shift-jis)
+;; ("Chinese-GB" . chinese-iso-8bit)
+;; ("Chinese-BIG5" . chinese-big5)
+;; ("Korean" . korean-iso-8bit)))
+
+;;
+;; IME state indicator
+;;
+(global-set-key [kanji] 'ignore)
+(global-set-key [compend] 'ignore)
+
+(defun wrap-function-to-control-ime
+ (function interactive-p interactive-arg &optional suffix)
+ "Wrap FUNCTION, and IME control is enabled when FUNCTION is called.
+An original function is saved to FUNCTION-SUFFIX when suffix is string.
+If SUFFIX is nil, \"-original\" is added. "
+ (let ((original-function
+ (intern (concat (symbol-name function)
+ (if suffix suffix "-original")))))
+ (cond
+ ((not (fboundp original-function))
+ (fset original-function
+ (symbol-function function))
+ (fset function
+ (list
+ 'lambda '(&rest arguments)
+ (when interactive-p
+ (list 'interactive interactive-arg))
+ `(cond
+ ((and (ime-get-mode)
+ (equal current-input-method "W32-IME"))
+ (ime-force-off)
+ (unwind-protect
+ (apply ',original-function arguments)
+ (when (and (not (ime-get-mode))
+ (equal current-input-method "W32-IME"))
+ (ime-force-on))))
+ (t
+ (apply ',original-function arguments)))))))))
+
+(defvar w32-ime-toroku-region-yomigana nil
+ "* if this variable is string, toroku-region regard this value as yomigana.")
+
+(defun w32-ime-toroku-region (begin end)
+ (interactive "r")
+ (let ((string (buffer-substring begin end))
+ (w32-ime-buffer-switch-p nil)
+ (reading w32-ime-toroku-region-yomigana))
+ (unless (stringp reading)
+ (w32-set-ime-mode 'hiragana)
+ (setq reading
+ (read-multilingual-string
+ (format "Input reading of \"%s\": " string) nil "W32-IME")))
+ (w32-ime-register-word-dialog reading string)))
+
+;; for IME management system.
+
+(defun w32-ime-sync-state (window)
+ (when w32-ime-buffer-switch-p
+ (with-current-buffer (window-buffer window)
+ (let* ((frame (window-frame window))
+ (ime-state (ime-get-mode)))
+ (cond
+ ((and (not ime-state)
+ (equal current-input-method "W32-IME"))
+ (ime-force-on nil)
+ (run-hooks 'w32-ime-on-hook))
+ ((and ime-state
+ (not (equal current-input-method "W32-IME")))
+;;; (when (= (w32-ime-undetermined-string-length) 0)
+ (ime-force-off nil)
+ (run-hooks 'w32-ime-off-hook)))))))
+
+(defun w32-ime-set-selected-window-buffer-hook (oldbuf newwin newbuf)
+ (w32-ime-sync-state newwin))
+
+(defun w32-ime-select-window-hook (old new)
+ (w32-ime-sync-state new))
+
+(defun w32-ime-mode-line-update ()
+ (cond
+ (w32-ime-show-mode-line
+ (unless (window-minibuffer-p (selected-window))
+ (setq w32-ime-mode-line-state-indicator
+ (nth (if (ime-get-mode) 1 2)
+ w32-ime-mode-line-state-indicator-list))))
+ (t
+ (setq w32-ime-mode-line-state-indicator
+ (nth 0 w32-ime-mode-line-state-indicator-list))))
+ (force-mode-line-update))
+
+(defun w32-ime-init-mode-line-display ()
+ (unless (member 'w32-ime-mode-line-state-indicator mode-line-format)
+ (setq w32-ime-mode-line-format-original
+ (default-value 'mode-line-format))
+ (if (and (stringp (car mode-line-format))
+ (string= (car mode-line-format) "-"))
+ (setq-default mode-line-format
+ (cons ""
+ (cons 'w32-ime-mode-line-state-indicator
+ (cdr mode-line-format))))
+ (setq-default mode-line-format
+ (cons ""
+ (cons 'w32-ime-mode-line-state-indicator
+ mode-line-format))))
+ (force-mode-line-update t)))
+
+(defun w32-ime-initialize ()
+ (when (and (or (eq system-type 'windows-nt) (eq system-type 'cygwin))
+ (eq window-system 'w32)
+ (featurep 'w32-ime))
+ (w32-ime-init-mode-line-display)
+ (w32-ime-mode-line-update)
+ (add-hook 'select-window-functions
+ 'w32-ime-select-window-hook)
+ (add-hook 'set-selected-window-buffer-functions
+ 'w32-ime-set-selected-window-buffer-hook)
+ (define-key global-map [kanji] 'toggle-input-method)))
+;; (set-keyboard-coding-system 'utf-8)))
+
+(defun w32-ime-uninitialize ()
+ (when (and (or (eq system-type 'windows-nt) (eq system-type 'cygwin))
+ (eq window-system 'w32)
+ (featurep 'w32-ime))
+ (setq-default mode-line-format
+ w32-ime-mode-line-format-original)
+ (force-mode-line-update t)
+ (remove-hook 'select-window-functions
+ 'w32-ime-select-window-hook)
+ (remove-hook 'set-selected-window-buffer-functions
+ 'w32-ime-set-selected-window-buffer-hook)
+ (define-key global-map [kanji] 'ignore)))
+
+(defun w32-ime-exit-from-minibuffer ()
+ (deactivate-input-method)
+ (when (<= (minibuffer-depth) 1)
+ (remove-hook 'minibuffer-exit-hook 'w32-ime-exit-from-minibuffer)))
+
+(defun w32-ime-state-switch (&optional arg)
+ (if arg
+ (progn
+ (setq deactivate-current-input-method-function
+ 'w32-ime-state-switch)
+ (run-hooks 'input-method-activate-hook)
+ (run-hooks 'w32-ime-on-hook)
+ (setq describe-current-input-method-function nil)
+ (when (eq (selected-window) (minibuffer-window))
+ (add-hook 'minibuffer-exit-hook 'w32-ime-exit-from-minibuffer))
+ (ime-force-on))
+ (setq current-input-method nil)
+ (run-hooks 'input-method-deactivate-hook)
+ (run-hooks 'w32-ime-off-hook)
+ (setq describe-current-input-method-function nil)
+ (ime-force-off))
+ (w32-ime-mode-line-update))
+
+(register-input-method "W32-IME" "Japanese" 'w32-ime-state-switch ""
+ "W32 System IME")
+
+(provide 'w32-ime)
--- ./lisp/language/japan-util.el.orig 2017-04-15 00:02:47.000000000 +0900
+++ ./lisp/language/japan-util.el 2017-09-13 21:00:32.639315100 +0900
@@ -31,9 +31,11 @@
(defun setup-japanese-environment-internal ()
;; By default, we use 'japanese-iso-8bit for file names. But, the
;; following prefer-coding-system will override it.
- (if (memq system-type '(windows-nt ms-dos cygwin))
+ (if (memq system-type '(windows-nt ms-dos))
(prefer-coding-system 'japanese-shift-jis)
- (prefer-coding-system 'japanese-iso-8bit))
+ (if (eq system-type 'cygwin)
+ (prefer-coding-system 'utf-8)
+ (prefer-coding-system 'japanese-iso-8bit)))
(use-cjk-char-width-table 'ja_JP))
(defconst japanese-kana-table
--- ./lisp/loadup.el.orig 2017-04-15 00:02:47.000000000 +0900
+++ ./lisp/loadup.el 2017-09-13 21:00:32.649336000 +0900
@@ -270,6 +270,7 @@
(load "w32-vars")
(load "term/w32-win")
(load "disp-table")
+ (load "international/w32-ime")
(when (eq system-type 'windows-nt)
(load "w32-fns")
(load "ls-lisp")
--- ./lisp/startup.el.orig 2017-04-15 00:02:47.000000000 +0900
+++ ./lisp/startup.el 2017-09-13 21:00:32.662363300 +0900
@@ -600,6 +600,8 @@
;; `user-full-name' is now known; reset its standard-value here.
(put 'user-full-name 'standard-value
(list (default-value 'user-full-name)))
+ ;; Set language environment for using "Japanese".
+ (set-language-environment "Japanese")
;; If the PWD environment variable isn't accurate, delete it.
(let ((pwd (getenv "PWD")))
(and (stringp pwd)
--- ./src/frame.c.orig 2017-04-15 00:02:47.000000000 +0900
+++ ./src/frame.c 2017-09-13 21:00:32.677394600 +0900
@@ -3073,6 +3073,9 @@
{"alpha", SYMBOL_INDEX (Qalpha)},
{"sticky", SYMBOL_INDEX (Qsticky)},
{"tool-bar-position", SYMBOL_INDEX (Qtool_bar_position)},
+#ifdef USE_W32_IME
+ {"ime-font", SYMBOL_INDEX (Qime_font)},
+#endif /* USE_W32_IME */
};
#ifdef HAVE_WINDOW_SYSTEM
@@ -5024,6 +5027,9 @@
DEFSYM (Qvertical_scroll_bars, "vertical-scroll-bars");
DEFSYM (Qvisibility, "visibility");
DEFSYM (Qwait_for_wm, "wait-for-wm");
+#ifdef USE_W32_IME
+ DEFSYM (Qime_font, "ime-font");
+#endif /* USE_W32_IME */
{
int i;
--- ./src/keyboard.c.orig 2017-04-15 00:02:47.000000000 +0900
+++ ./src/keyboard.c 2017-09-13 21:00:32.692426400 +0900
@@ -4690,7 +4690,11 @@
"junja", /* VK_JUNJA 0x17 */
"final", /* VK_FINAL 0x18 */
"kanji", /* VK_KANJI/VK_HANJA 0x19 */
+#ifdef USE_W32_IME
+ "compend", /* VK_COMPEND 0x1A */
+#else
0, /* 0x1A */
+#endif /* USE_W32_IME */
"escape", /* VK_ESCAPE 0x1B */
"convert", /* VK_CONVERT 0x1C */
"non-convert", /* VK_NONCONVERT 0x1D */
@@ -8828,6 +8832,13 @@
{
ptrdiff_t count = SPECPDL_INDEX ();
+ /* To control IME */
+#ifdef USE_W32_IME
+ extern Lisp_Object Fime_force_on (), Fime_force_off (), Fime_get_mode ();
+ Lisp_Object VIME_command_off_flag = Qnil;
+ Lisp_Object IME_command_loop_flag = Qnil;
+#endif /* USE_W32_IME */
+
/* How many keys there are in the current key sequence. */
int t;
@@ -8945,6 +8956,12 @@
keybuf[0..mock_input] holds the sequence we should reread. */
replay_sequence:
+#ifdef USE_W32_IME
+/* If key sequences are to replay, IME_loop_flag should not be set.
+ Because event has never been occured. */
+ IME_command_loop_flag = Qnil;
+#endif /* USE_W32_IME */
+
starting_buffer = current_buffer;
first_unbound = bufsize + 1;
@@ -9024,6 +9041,16 @@
goto replay_sequence;
}
+#ifdef USE_W32_IME
+ if (!NILP (IME_command_loop_flag) && NILP (VIME_command_off_flag))
+ {
+ VIME_command_off_flag = Fime_get_mode ();
+ if (!NILP (VIME_command_off_flag))
+ Fime_force_off (Qnil);
+ }
+ IME_command_loop_flag = Qt;
+#endif /* USE_W32_IME */
+
if (t >= bufsize)
error ("Key sequence too long");
@@ -9691,6 +9718,12 @@
? Fcommand_remapping (read_key_sequence_cmd, Qnil, Qnil)
: Qnil;
+ /* to control IME */
+#ifdef USE_W32_IME
+ if (!NILP (VIME_command_off_flag))
+ Fime_force_on (Qnil);
+#endif /* USE_W32_IME */
+
unread_switch_frame = delayed_switch_frame;
unbind_to (count, Qnil);
--- ./src/w32fns.c.orig 2017-04-15 00:02:47.000000000 +0900
+++ ./src/w32fns.c 2017-09-13 21:00:32.706455700 +0900
@@ -52,6 +52,11 @@
#include "w32.h"
#endif
+#ifdef USE_W32_IME
+#include "fontset.h"
+#include "w32font.h"
+#endif
+
#include <commctrl.h>
#include <commdlg.h>
#include <shellapi.h>
@@ -82,6 +87,45 @@
#define IDC_HAND MAKEINTRESOURCE(32649)
#endif
+#ifdef USE_W32_IME
+#ifdef RECONVERSION
+#define CHRSZ sizeof(short)
+#define RECONV_LENG 100
+#define DOCFEED_LENG 100
+static LRESULT w32_get_ime_reconversion_string (HWND, RECONVERTSTRING*);
+static BOOL w32_perform_reconversion (HWND, RECONVERTSTRING*);
+#ifdef DOCUMENTFEED
+#define DOCFEED_CSTR_LENG 64
+static LRESULT w32_get_ime_documentfeed_string (HWND, RECONVERTSTRING*);
+#endif
+#endif
+static int set_ime_font = 0;
+static LOGFONT ime_logfont = {0};
+static int IME_event_off_count;
+Lisp_Object Fime_get_mode();
+const char * const ImmGetOpenStatus_Name = "ImmGetOpenStatus";
+const char * const ImmSetOpenStatus_Name = "ImmSetOpenStatus";
+const char * const ImmSetCompositionWindow_Name = "ImmSetCompositionWindow";
+const char * const ImmGetContext_Name = "ImmGetContext";
+const char * const ImmGetConversionStatus_Name = "ImmGetConversionStatus";
+const char * const ImmSetConversionStatus_Name = "ImmSetConversionStatus";
+const char * const ImmNotifyIME_Name = "ImmNotifyIME";
+
+const char * const ImmReleaseContext_Name = "ImmReleaseContext";
+const char * const ImmCreateContext_Name = "ImmCreateContext";
+const char * const ImmDestroyContext_Name = "ImmDestroyContext";
+const char * const ImmAssociateContext_Name = "ImmAssociateContext";
+const char * const ImmGetHotKey_Name = "ImmGetHotKey";
+const char * const ImmGetProperty_Name = "ImmGetProperty";
+const char * const ImmGetCompositionString_Name = "ImmGetCompositionStringW";
+const char * const ImmSetCompositionString_Name = "ImmSetCompositionStringW";
+const char * const ImmSetCompositionFont_Name = "ImmSetCompositionFontA"; /* LOGFONTA */
+const char * const ImmGetConversionList_Name = "ImmGetConversionListW";
+const char * const ImmConfigureIME_Name = "ImmConfigureIMEW";
+const char * const ImmGetCandidateList_Name = "ImmGetCandidateListW";
+const char * const ImmGetCandidateListCount_Name = "ImmGetCandidateListCountW";
+#endif
+
/* Prefix for system colors. */
#define SYSTEM_COLOR_PREFIX "System"
#define SYSTEM_COLOR_PREFIX_LEN (sizeof (SYSTEM_COLOR_PREFIX) - 1)
@@ -156,12 +200,14 @@
typedef BOOL (WINAPI * TrackMouseEvent_Proc)
(IN OUT LPTRACKMOUSEEVENT lpEventTrack);
+#ifndef USE_W32_IME
typedef LONG (WINAPI * ImmGetCompositionString_Proc)
(IN HIMC context, IN DWORD index, OUT LPVOID buffer, IN DWORD bufLen);
typedef HIMC (WINAPI * ImmGetContext_Proc) (IN HWND window);
typedef BOOL (WINAPI * ImmReleaseContext_Proc) (IN HWND wnd, IN HIMC context);
typedef BOOL (WINAPI * ImmSetCompositionWindow_Proc) (IN HIMC context,
IN COMPOSITIONFORM *form);
+#endif /* !USE_W32_IME */
typedef HMONITOR (WINAPI * MonitorFromPoint_Proc) (IN POINT pt, IN DWORD flags);
typedef BOOL (WINAPI * GetMonitorInfo_Proc)
(IN HMONITOR monitor, OUT struct MONITOR_INFO* info);
@@ -175,10 +221,12 @@
(IN HWND hwnd, OUT TITLEBAR_INFO* info);
TrackMouseEvent_Proc track_mouse_event_fn = NULL;
+#ifndef USE_W32_IME
ImmGetCompositionString_Proc get_composition_string_fn = NULL;
ImmGetContext_Proc get_ime_context_fn = NULL;
ImmReleaseContext_Proc release_ime_context_fn = NULL;
ImmSetCompositionWindow_Proc set_ime_composition_window_fn = NULL;
+#endif /* !USE_W32_IME */
MonitorFromPoint_Proc monitor_from_point_fn = NULL;
GetMonitorInfo_Proc get_monitor_info_fn = NULL;
MonitorFromWindow_Proc monitor_from_window_fn = NULL;
@@ -191,8 +239,13 @@
extern AppendMenuW_Proc unicode_append_menu;
#endif /* NTGUI_UNICODE */
+#ifdef USE_W32_IME
+/* Flag for indicating in conversion. */
+int ime_in_conversion = 0;
+#else
/* Flag to selectively ignore WM_IME_CHAR messages. */
static int ignore_ime_char = 0;
+#endif
/* W95 mousewheel handler */
unsigned int msh_mousewheel = 0;
@@ -759,6 +812,17 @@
return ret;
}
+#ifdef USE_W32_IME
+static void w32_set_ime_conv_window (HWND, struct frame *);
+static void w32_set_ime_status (HWND, int);
+static int w32_get_ime_status (HWND);
+static int w32_set_ime_mode (HWND, int, int);
+void w32_set_ime_logfont (HWND, struct frame *);
+static void w32_set_ime_font (HWND);
+static BOOL w32_get_ime_composition_string (HWND);
+static LRESULT CALLBACK conversion_agent_wndproc (HWND, UINT, WPARAM, LPARAM);
+static int initialize_conversion_agent (void);
+#endif /* USE_W32_IME */
static void
add_system_logical_colors_to_map (Lisp_Object *system_colors)
@@ -2042,6 +2106,8 @@
if (hwnd)
{
+ static int initialized = 0;
+
SetWindowLong (hwnd, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f));
SetWindowLong (hwnd, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f));
SetWindowLong (hwnd, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f));
@@ -2049,6 +2115,12 @@
SetWindowLong (hwnd, WND_HSCROLLBAR_INDEX, FRAME_SCROLL_BAR_AREA_HEIGHT (f));
SetWindowLong (hwnd, WND_BACKGROUND_INDEX, FRAME_BACKGROUND_PIXEL (f));
+ if (!initialized && (w32_major_version > 6 || w32_major_version == 6 && w32_minor_version >= 2))
+ {
+ ShowWindow (hwnd, SW_MINIMIZE); ShowWindow (hwnd, SW_RESTORE);
+ initialized = 1;
+ }
+
/* Enable drag-n-drop. */
DragAcceptFiles (hwnd, TRUE);
@@ -3702,6 +3774,24 @@
TranslateMessage (&windows_msg);
goto dflt;
}
+#ifdef USE_W32_IME
+ else
+ {
+ MSG ime_undo_test_msg;
+
+ if (wParam == VK_BACK
+ && ctrl_modifier == w32_get_key_modifiers (wParam, lParam)
+ && w32_get_ime_status (hwnd) != 0
+ && PeekMessage (&ime_undo_test_msg, hwnd, WM_KEYDOWN, WM_KEYDOWN, PM_NOYIELD | PM_NOREMOVE) != 0
+ && ime_undo_test_msg.wParam == VK_BACK
+ && ime_undo_test_msg.lParam == 0x40000001
+ )
+ {
+ post_character_message (hwnd, msg, wParam, lParam, 0);
+ break;
+ }
+ }
+#endif
/* Fall through */
@@ -3721,6 +3811,7 @@
w32_get_key_modifiers (wParam, lParam));
break;
+#ifndef USE_W32_IME
case WM_UNICHAR:
/* WM_UNICHAR looks promising from the docs, but the exact
circumstances in which TranslateMessage sends it is one of those
@@ -3845,6 +3936,7 @@
case WM_IME_ENDCOMPOSITION:
ignore_ime_char = 0;
goto dflt;
+#endif /* USE_W32_IME */
/* Simulate middle mouse button events when left and right buttons
are used together, but only if user has two button mouse. */
@@ -4593,8 +4685,87 @@
case WM_EMACS_FILENOTIFY:
my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
return 1;
+#ifdef USE_W32_IME
+ case WM_IME_NOTIFY:
+ if (wParam == IMN_SETOPENSTATUS)
+ {
+ if (w32_get_ime_status(hwnd)){
+ struct frame *f = x_window_to_frame (dpyinfo, hwnd);
+ if (f) {
+ set_ime_font = 0;
+ w32_set_ime_conv_window (hwnd, f);
+ }
+ }
+ if (!IME_event_off_count)
+ my_post_msg (&wmsg, hwnd, WM_MULE_IME_STATUS, 0, 0);
+ else
+ IME_event_off_count--;
+ }
+ goto dflt;
+
+ case WM_IME_STARTCOMPOSITION:
+ {
+ struct frame *f = x_window_to_frame (dpyinfo, hwnd);
+ if (f && !set_ime_font)
+ {
+ my_post_msg (&wmsg, hwnd, WM_MULE_IME_SET_FONT, (WPARAM) f, 0);
+ set_ime_font = 1;
+ }
+ }
+ ime_in_conversion = 1;
+ goto dflt;
+
+ case WM_IME_ENDCOMPOSITION:
+ ime_in_conversion = 0;
+ goto dflt;
+
+ case WM_IME_SETCONTEXT:
+ set_ime_font = 0;
+ goto dflt;
+
+ case WM_IME_COMPOSITION:
+ if (lParam & GCS_RESULTSTR)
+ if (w32_get_ime_composition_string (hwnd))
+ return 0;
+ else
+ break;
+ goto dflt;
+
+#ifdef RECONVERSION
+ case WM_IME_REQUEST:
+ if (wParam == IMR_RECONVERTSTRING)
+ {
+ if (!ime_enable_reconversion || !w32_get_ime_status (hwnd))
+ return 0;
+ if (lParam)
+ return w32_get_ime_reconversion_string (hwnd,
+ (RECONVERTSTRING*) lParam);
+ else
+ return sizeof (RECONVERTSTRING) + (RECONV_LENG * 2 + 1) * CHRSZ;
+ }
+#ifdef DOCUMENTFEED
+ else if (wParam == IMR_DOCUMENTFEED)
+ {
+ if (!ime_enable_document_feed)
+ return 0;
+ if (lParam)
+ return w32_get_ime_documentfeed_string (hwnd,
+ (RECONVERTSTRING*) lParam);
+ else
+ return sizeof (RECONVERTSTRING) + (DOCFEED_LENG * 2 + DOCFEED_CSTR_LENG + 1) * CHRSZ;
+ }
+#endif
+ goto dflt;
+#endif
+#endif /* USE_W32_IME */
default:
+
+#ifdef USE_W32_IME
+ if (MESSAGE_IMM_COM_P(msg))
+ return conversion_agent_wndproc (hwnd, msg, wParam, lParam);
+#endif /* USE_W32_IME */
+
/* Check for messages registered at runtime. */
if (msg == msh_mousewheel)
{
@@ -4883,6 +5054,10 @@
x_set_frame_parameters (f, Fcons (Fcons (Qfont_param, font_param), Qnil));
}
x_default_parameter (f, parms, Qfont, font, "font", "Font", RES_TYPE_STRING);
+#ifdef USE_W32_IME
+ x_default_parameter (f, parms, Qime_font, Qnil,
+ "ime-font", "IME-Font", RES_TYPE_STRING);
+#endif
}
DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
@@ -7297,6 +7472,1017 @@
/***********************************************************************
+ Input Method Editor
+ ***********************************************************************/
+#ifdef USE_W32_IME
+BOOL fIME = FALSE;
+
+typedef BOOL (WINAPI *IMMGETOPENSTATUSPROC)(HIMC);
+IMMGETOPENSTATUSPROC ImmGetOpenStatusProc;
+
+typedef BOOL (WINAPI *IMMSETOPENSTATUSPROC)(HIMC, BOOL);
+IMMSETOPENSTATUSPROC ImmSetOpenStatusProc;
+
+typedef BOOL (WINAPI *IMMSETCOMPOSITIONWINDOWPROC)(HIMC, LPCOMPOSITIONFORM);
+IMMSETCOMPOSITIONWINDOWPROC ImmSetCompositionWindowProc;
+
+typedef LONG (WINAPI *IMMGETCOMPOSITIONSTRINGPROC)
+ (HIMC, DWORD, LPVOID, DWORD);
+IMMGETCOMPOSITIONSTRINGPROC ImmGetCompositionStringProc;
+
+typedef LONG (WINAPI *IMMSETCOMPOSITIONSTRINGPROC)
+ (HIMC, DWORD, LPCVOID, DWORD, LPCVOID, DWORD);
+IMMSETCOMPOSITIONSTRINGPROC ImmSetCompositionStringProc;
+
+typedef BOOL (WINAPI *IMMSETCOMPOSITIONFONTPROC) (HIMC, LPLOGFONTA);
+IMMSETCOMPOSITIONFONTPROC ImmSetCompositionFontProc;
+
+typedef HIMC (WINAPI *IMMGETCONTEXTPROC)(HWND);
+IMMGETCONTEXTPROC ImmGetContextProc;
+
+typedef BOOL (WINAPI *IMMGETCONVERSIONSTATUSPROC)(HIMC, LPDWORD, LPDWORD);
+IMMGETCONVERSIONSTATUSPROC ImmGetConversionStatusProc;
+
+typedef BOOL (WINAPI *IMMSETCONVERSIONSTATUSPROC)(HIMC, DWORD, DWORD);
+IMMSETCONVERSIONSTATUSPROC ImmSetConversionStatusProc;
+
+typedef BOOL (WINAPI *IMMGETCONVERSIONLISTPROC)
+ (HKL, HIMC, LPCTSTR, LPCANDIDATELIST, DWORD, UINT);
+IMMGETCONVERSIONLISTPROC ImmGetConversionListProc;
+
+typedef BOOL (WINAPI *IMMCONFIGUREIMEPROC)(HKL, HWND, DWORD, LPVOID);
+IMMCONFIGUREIMEPROC ImmConfigureIMEProc;
+
+typedef BOOL (WINAPI *IMMNOTIFYIMEPROC)(HIMC, DWORD, DWORD, DWORD);
+IMMNOTIFYIMEPROC ImmNotifyIMEProc;
+
+typedef BOOL (WINAPI *IMMRELEASECONTEXTPROC)(HWND, HIMC);
+IMMRELEASECONTEXTPROC ImmReleaseContextProc;
+
+typedef HIMC (WINAPI *IMMCREATECONTEXTPROC)(void);
+IMMCREATECONTEXTPROC ImmCreateContextProc;
+
+typedef BOOL (WINAPI *IMMDESTROYCONTEXTPROC)(HIMC);
+IMMDESTROYCONTEXTPROC ImmDestroyContextProc;
+
+typedef HIMC (WINAPI *IMMASSOCIATECONTEXTPROC) (HWND, HIMC);
+IMMASSOCIATECONTEXTPROC ImmAssociateContextProc;
+
+typedef BOOL (WINAPI *IMMGETCANDIDATELISTPROC)
+ (HIMC, DWORD, LPCANDIDATELIST, DWORD);
+IMMGETCANDIDATELISTPROC ImmGetCandidateListProc;
+
+typedef BOOL (WINAPI *IMMGETCANDIDATELISTCOUNTPROC) (HIMC, LPDWORD);
+IMMGETCANDIDATELISTCOUNTPROC ImmGetCandidateListCountProc;
+
+typedef BOOL (WINAPI *IMMGETHOTKEYPROC)(DWORD, LPUINT, LPUINT, LPHKL);
+IMMGETHOTKEYPROC ImmGetHotKeyProc;
+
+typedef BOOL (WINAPI *IMMGETPROPERTYPROC)(HKL, DWORD);
+IMMGETPROPERTYPROC ImmGetPropertyProc;
+
+// Lisp_Object Vime_control;
+
+static void
+w32_set_ime_conv_window (hwnd, f)
+ HWND hwnd;
+ struct frame *f;
+{
+ if (fIME && !NILP (Vime_control))
+ {
+ HIMC himc;
+ COMPOSITIONFORM compform;
+ struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
+
+ /* If Vw32_ime_composition_window is set, try it. */
+ if (!NILP (Vw32_ime_composition_window)
+ && WINDOWP (Vw32_ime_composition_window)
+ && WINDOW_FRAME (XWINDOW (Vw32_ime_composition_window))
+ == WINDOW_FRAME (w))
+ w = XWINDOW (Vw32_ime_composition_window);
+
+ himc = (ImmGetContextProc) (hwnd);
+ compform.dwStyle = CFS_RECT;
+
+ compform.ptCurrentPos.x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
+
+ compform.ptCurrentPos.y = WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y);
+#if 0
+ if (FRAME_FONT (f)->vertical_centering == 1)
+ compform.ptCurrentPos.y += FRAME_FONT (f)->baseline_offset;
+#endif
+
+ compform.rcArea.left = (WINDOW_BOX_LEFT_EDGE_X (w)
+ + WINDOW_LEFT_MARGIN_WIDTH (w)
+ + WINDOW_LEFT_FRINGE_WIDTH (w));
+
+ compform.rcArea.top = (WINDOW_TOP_EDGE_Y (w)
+ + WINDOW_HEADER_LINE_HEIGHT (w));
+
+ compform.rcArea.right = (WINDOW_BOX_RIGHT_EDGE_X (w)
+ - WINDOW_RIGHT_MARGIN_WIDTH (w)
+ - WINDOW_RIGHT_FRINGE_WIDTH (w)) + 1;
+
+ compform.rcArea.bottom = (WINDOW_BOTTOM_EDGE_Y (w)
+ - WINDOW_MODE_LINE_HEIGHT (w));
+
+ (ImmSetCompositionWindowProc) (himc, &compform);
+ (ImmReleaseContextProc) (hwnd, himc);
+ }
+}
+
+static void
+w32_set_ime_status (hwnd, openp)
+ HWND hwnd;
+ int openp;
+{
+ HIMC himc;
+
+ himc = (ImmGetContextProc) (hwnd);
+ (ImmSetOpenStatusProc) (himc, openp);
+ (ImmReleaseContextProc) (hwnd, himc);
+}
+
+static int
+w32_get_ime_status (hwnd)
+ HWND hwnd;
+{
+ HIMC himc;
+ int ret;
+
+ himc = (ImmGetContextProc) (hwnd);
+ ret = (ImmGetOpenStatusProc) (himc);
+ (ImmReleaseContextProc) (hwnd, himc);
+
+ return ret;
+}
+
+static int
+w32_set_ime_mode (hwnd, mode, mask)
+ HWND hwnd;
+ int mode;
+ int mask;
+{
+ HIMC himc;
+ DWORD cmode, smode;
+
+ himc = (ImmGetContextProc) (hwnd);
+ if (!(ImmGetConversionStatusProc) (himc, &cmode, &smode))
+ return 0;
+
+ cmode = (cmode & (~mask)) | (mode & mask);
+
+ (ImmSetConversionStatusProc) (himc, cmode, smode);
+ (ImmReleaseContextProc) (hwnd, himc);
+
+ return 1;
+}
+
+static BOOL
+w32_get_ime_composition_string (hwnd)
+ HWND hwnd;
+{
+ HIMC hIMC;
+ int size;
+ HANDLE himestr;
+ LPWSTR lpstr;
+
+ struct frame *f;
+
+ hIMC = (ImmGetContextProc) (hwnd);
+ if (!hIMC)
+ return FALSE;
+
+ size = (ImmGetCompositionStringProc) (hIMC, GCS_RESULTSTR, NULL, 0);
+ size += sizeof (WCHAR);
+ himestr = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, size);
+ if (!himestr)
+ abort ();
+
+ (ImmGetCompositionStringProc) (hIMC, GCS_RESULTSTR, himestr, size);
+ (ImmReleaseContextProc) (hwnd, hIMC);
+ {
+ W32Msg wmsg;
+ f = SELECTED_FRAME ();
+ my_post_msg (&wmsg, hwnd, WM_MULE_IME_REPORT,
+ (WPARAM) himestr, (LPARAM) f);
+ }
+ return TRUE;
+}
+
+#ifdef RECONVERSION
+
+static EMACS_INT compstr_beginning_pos(int max_char)
+{
+ EMACS_INT bol, point = PT, pt;
+ for (bol = XFASTINT(Fline_beginning_position(Qnil)), pt = PT;
+ PT >= bol && PT > point - max_char; ) {
+ pt = PT;
+ if (NILP(Fforward_word (make_number (-1))))
+ break;
+ }
+ Fgoto_char (make_number(point));
+ return pt;
+}
+
+static EMACS_INT compstr_end_pos(int max_char)
+{
+ EMACS_INT eol, point = PT, pt;
+
+ for (eol = XFASTINT(Fline_end_position(Qnil)), pt = PT;
+ PT <= eol && PT < point + max_char;) {
+ pt = PT;
+ if (NILP(Fforward_word (make_number (1))))
+ break;
+ }
+ Fgoto_char (make_number(point));
+ return pt;
+}
+
+static LRESULT
+get_reconversion_string (HWND hwnd,
+ RECONVERTSTRING *reconv,
+ unsigned short *compstr)
+{
+ EMACS_INT pt, pt_byte, start, end, len, t_start, t_end, compstr_len;
+ W32Msg wmsg;
+
+ if (!NILP (BVAR (current_buffer, read_only)))
+ return 0;
+
+ pt = PT;
+ pt_byte = PT_BYTE;
+
+ if (compstr)
+ {
+ t_start = PT;
+ start = compstr_beginning_pos (DOCFEED_LENG);
+ end = compstr_end_pos (DOCFEED_LENG);
+ }
+ else if (!NILP (BVAR (current_buffer, mark_active))
+ && !NILP (Vtransient_mark_mode))
+ {
+ if (marker_position (BVAR (current_buffer, mark)) < PT)
+ {
+ t_start = marker_position (BVAR (current_buffer, mark));
+ t_end = PT;
+ }
+ else
+ {
+ t_start = PT;
+ t_end = marker_position (BVAR (current_buffer, mark));
+ }
+ Fgoto_char (make_number (t_end));
+ while (!NILP (Fbolp ()) && t_start < PT)
+ Fforward_char (make_number (-1));
+ if (t_start >= PT)
+ return 0;
+ t_end = PT;
+ }
+ else
+ {
+ if (NILP (Feobp ()))
+ Fforward_char (make_number (1));
+ if (!NILP (Fforward_word (make_number (-1))))
+ t_start = PT;
+ else
+ {
+ SET_PT_BOTH (pt, pt_byte);
+ return 0;
+ }
+ Fforward_word (make_number (1));
+ t_end = PT;
+ SET_PT_BOTH (pt, pt_byte);
+ if (t_end < PT)
+ return 0;
+ }
+
+ if (!compstr)
+ {
+ if (t_start == t_end)
+ return 0;
+
+ Fgoto_char (make_number (t_start));
+ start = compstr_beginning_pos (RECONV_LENG);
+ Fgoto_char (make_number (t_end));
+ end = compstr_end_pos (RECONV_LENG);
+ }
+
+ len = end - start;
+ if (reconv)
+ {
+ int pos;
+ WCHAR *s;
+
+ s = (WCHAR *) (reconv + 1);
+
+ for (pos = start; pos < t_start; pos++)
+ *s++ = (WCHAR) FETCH_CHAR (CHAR_TO_BYTE (pos));
+
+ if (compstr)
+ {
+ for (compstr_len = 0; compstr[compstr_len]; compstr_len++)
+ *s++ = compstr[compstr_len];
+
+ len += compstr_len;
+ }
+ else
+ compstr_len = t_end - t_start;
+
+ for (; pos < end; pos++)
+ *s++ = (WCHAR) FETCH_CHAR (CHAR_TO_BYTE (pos));
+
+ *s = 0;
+ }
+ else
+ {
+ SET_PT_BOTH (pt, pt_byte);
+ if (compstr)
+ {
+ for (compstr_len = 0; compstr[compstr_len]; compstr_len++)
+ ;
+
+ len += compstr_len;
+ }
+ return (sizeof (RECONVERTSTRING) + (len + 1) * CHRSZ);
+ }
+
+ reconv->dwStrOffset = sizeof (RECONVERTSTRING);
+ reconv->dwStrLen = len;
+ reconv->dwCompStrOffset =
+ reconv->dwTargetStrOffset = (t_start - start) * CHRSZ;
+ reconv->dwCompStrLen =
+ reconv->dwTargetStrLen = compstr_len;
+
+ if (!compstr)
+ my_post_msg (&wmsg, hwnd, WM_MULE_IME_DEL_RANGE, (WPARAM) t_start, (LPARAM) t_end);
+
+ return (reconv->dwSize = sizeof (RECONVERTSTRING) + (len + 1) * CHRSZ);
+}
+
+static LRESULT
+w32_get_ime_reconversion_string (HWND hwnd,
+ RECONVERTSTRING *reconv)
+{
+ return get_reconversion_string (hwnd, reconv, NULL);
+}
+#endif /* RECONVERSION */
+
+#if defined(DOCUMENTFEED)
+static LRESULT
+w32_get_ime_documentfeed_string (HWND hwnd,
+ RECONVERTSTRING *reconv)
+{
+ unsigned short ime_compstr[DOCFEED_CSTR_LENG];
+ HIMC hIMC;
+ LONG l;
+
+ if (hIMC = (ImmGetContextProc) (hwnd))
+ {
+ if ((ImmGetCompositionStringProc) (hIMC, GCS_COMPSTR, NULL, 0)
+ >= DOCFEED_CSTR_LENG * CHRSZ)
+ {
+ (ImmReleaseContextProc) (hwnd, hIMC);
+ return 0;
+ }
+
+ switch (l = (ImmGetCompositionStringProc)
+ (hIMC, GCS_COMPSTR, ime_compstr,
+ (DOCFEED_CSTR_LENG - 1) * CHRSZ))
+ {
+ case IMM_ERROR_NODATA:
+ case IMM_ERROR_GENERAL:
+ ime_compstr[0] = 0;
+ break;
+ default:
+ ime_compstr[l / CHRSZ] = 0;
+ break;
+ }
+ (ImmReleaseContextProc) (hwnd, hIMC);
+
+ return get_reconversion_string (hwnd, reconv, ime_compstr);
+ }
+
+ return 0;
+}
+#endif /* DOCUMENTFEED */
+
+void
+w32_ime_control_init (void)
+{
+ HMODULE hImm32;
+ HMODULE hUser32;
+
+ hImm32 = GetModuleHandle ("IMM32.DLL");
+ if (!hImm32)
+ hImm32 = LoadLibrary ("IMM32.DLL");
+
+ fIME = FALSE;
+ Vime_control = Qnil;
+ IME_event_off_count = 0;
+
+ if (hImm32)
+ {
+ ImmGetOpenStatusProc =
+ (IMMGETOPENSTATUSPROC)
+ GetProcAddress (hImm32,
+ ImmGetOpenStatus_Name);
+ ImmSetOpenStatusProc =
+ (IMMSETOPENSTATUSPROC)
+ GetProcAddress (hImm32,
+ ImmSetOpenStatus_Name);
+ ImmSetCompositionWindowProc =
+ (IMMSETCOMPOSITIONWINDOWPROC)
+ GetProcAddress (hImm32,
+ ImmSetCompositionWindow_Name);
+ ImmGetContextProc =
+ (IMMGETCONTEXTPROC)
+ GetProcAddress (hImm32,
+ ImmGetContext_Name);
+ ImmGetConversionStatusProc =
+ (IMMGETCONVERSIONSTATUSPROC)
+ GetProcAddress (hImm32,
+ ImmGetConversionStatus_Name);
+ ImmSetConversionStatusProc =
+ (IMMSETCONVERSIONSTATUSPROC)
+ GetProcAddress (hImm32,
+ ImmSetConversionStatus_Name);
+ ImmNotifyIMEProc =
+ (IMMNOTIFYIMEPROC)
+ GetProcAddress (hImm32,
+ ImmNotifyIME_Name);
+ ImmReleaseContextProc =
+ (IMMRELEASECONTEXTPROC)
+ GetProcAddress (hImm32,
+ ImmReleaseContext_Name);
+ ImmCreateContextProc =
+ (IMMCREATECONTEXTPROC)
+ GetProcAddress (hImm32,
+ ImmCreateContext_Name);
+ ImmDestroyContextProc =
+ (IMMDESTROYCONTEXTPROC)
+ GetProcAddress (hImm32,
+ ImmDestroyContext_Name);
+ ImmAssociateContextProc =
+ (IMMASSOCIATECONTEXTPROC)
+ GetProcAddress (hImm32,
+ ImmAssociateContext_Name);
+ ImmGetHotKeyProc =
+ (IMMGETHOTKEYPROC)
+ GetProcAddress (hImm32,
+ ImmGetHotKey_Name);
+ ImmGetPropertyProc =
+ (IMMGETPROPERTYPROC)
+ GetProcAddress (hImm32, ImmGetProperty_Name);
+ ImmGetCompositionStringProc =
+ (IMMGETCOMPOSITIONSTRINGPROC)
+ GetProcAddress (hImm32, ImmGetCompositionString_Name);
+ ImmSetCompositionStringProc =
+ (IMMSETCOMPOSITIONSTRINGPROC)
+ GetProcAddress (hImm32, ImmSetCompositionString_Name);
+ ImmSetCompositionFontProc =
+ (IMMSETCOMPOSITIONFONTPROC)
+ GetProcAddress (hImm32, ImmSetCompositionFont_Name);
+ ImmGetConversionListProc =
+ (IMMGETCONVERSIONLISTPROC)
+ GetProcAddress (hImm32,
+ ImmGetConversionList_Name);
+ ImmConfigureIMEProc =
+ (IMMCONFIGUREIMEPROC)
+ GetProcAddress (hImm32,
+ ImmConfigureIME_Name);
+ ImmGetCandidateListProc =
+ (IMMGETCANDIDATELISTPROC)
+ GetProcAddress (hImm32,
+ ImmGetCandidateList_Name);
+ ImmGetCandidateListCountProc =
+ (IMMGETCANDIDATELISTCOUNTPROC)
+ GetProcAddress (hImm32,
+ ImmGetCandidateListCount_Name);
+
+ if (ImmGetOpenStatusProc &&
+ ImmSetOpenStatusProc &&
+ ImmSetCompositionWindowProc &&
+ ImmGetCompositionStringProc &&
+ ImmSetCompositionStringProc &&
+ ImmSetCompositionFontProc &&
+ ImmGetPropertyProc &&
+ ImmGetContextProc &&
+ ImmGetConversionStatusProc &&
+ ImmSetConversionStatusProc &&
+ ImmGetConversionListProc &&
+ ImmConfigureIMEProc &&
+ ImmNotifyIMEProc &&
+ ImmReleaseContextProc &&
+ ImmCreateContextProc &&
+ ImmDestroyContextProc &&
+ ImmAssociateContextProc &&
+ ImmGetCandidateListProc &&
+ ImmGetCandidateListCountProc &&
+ ImmGetHotKeyProc)
+ {
+ fIME = TRUE;
+ Vime_control = Qt;
+ }
+ }
+}
+
+#ifdef HAVE_NTGUI
+static int
+need_set_ime_font (PLOGFONT p)
+{
+ if (!p ||
+ (p->lfHeight == ime_logfont.lfHeight
+ && p->lfWidth == ime_logfont.lfWidth
+ && p->lfEscapement == ime_logfont.lfEscapement
+ && p->lfOrientation == ime_logfont.lfOrientation
+ && p->lfWeight == ime_logfont.lfWeight
+ && p->lfItalic == ime_logfont.lfItalic
+ && p->lfUnderline == ime_logfont.lfUnderline
+ && p->lfStrikeOut == ime_logfont.lfStrikeOut
+ && p->lfCharSet == ime_logfont.lfCharSet
+ && p->lfOutPrecision == ime_logfont.lfOutPrecision
+ && p->lfClipPrecision == ime_logfont.lfClipPrecision
+ && p->lfQuality == ime_logfont.lfQuality
+ && p->lfPitchAndFamily == ime_logfont.lfPitchAndFamily
+ && strncmp (p->lfFaceName, ime_logfont.lfFaceName, LF_FACESIZE) == 0))
+ return 0;
+ else
+ return 1;
+}
+void
+w32_set_ime_logfont (hwnd, f)
+ HWND hwnd;
+ struct frame *f;
+{
+ Lisp_Object ime_font = Qnil, temp = Qnil, font = Qnil, family;
+ int fsid = -1;
+ LOGFONT logfont = {0};
+
+ if (!IsWindow (hwnd))
+ return;
+
+ if (!fIME || NILP(Vime_control))
+ return;
+
+ if (STRINGP(ime_font = get_frame_param (f, Qime_font))
+ /* fontset */
+ && ((fsid = fs_query_fontset(ime_font, 0)) >= 0
+ && !NILP(font = fontset_ascii(fsid))
+ && !NILP(font = font_spec_from_name(font))
+ && !NILP(temp = Ffontset_font(temp, make_number(0x3042), Qnil))
+ && !NILP(family = XCAR(temp))
+ /* font */
+ || !NILP(font = font_spec_from_name(ime_font))
+ && SYMBOLP(family = AREF (font, FONT_FAMILY_INDEX))
+ && STRINGP(family = SYMBOL_NAME(family)))
+
+ /* use font object */
+ /* frame-parameter */
+ || (FONTP(font = ime_font)
+ /* frame fontset */
+ || ((fsid = FRAME_FONTSET(f)) >= 0
+ && !NILP(font =
+ Ffont_at(make_number(0), Qnil,
+ temp = Fchar_to_string(make_number(0x3042))))))
+ && SYMBOLP(family = Ffont_get(font, QCfamily))
+ && STRINGP(family = SYMBOL_NAME(family))
+ && !NILP(font = copy_font_spec(font))) {
+ Lisp_Object tail;
+
+ fill_in_logfont (f, &logfont, font);
+
+ logfont.lfWidth = 0;
+
+ family = ENCODE_SYSTEM(family);
+
+ strcpy(logfont.lfFaceName, SDATA(family));
+
+ /* rescale */
+ for (tail = Vface_font_rescale_alist; CONSP (tail); tail = XCDR (tail)) {
+ temp = XCAR (tail);
+ if (!FLOATP (XCDR (temp)))
+ continue;
+
+ if (STRINGP (XCAR (temp))) {
+ if (fast_string_match_ignore_case (XCAR (temp), family) >= 0) {
+ logfont.lfHeight *= XFLOAT_DATA (XCDR (temp));
+ break;
+ }
+ } else if (FONT_SPEC_P (XCAR (temp))) {
+ Lisp_Object name;
+ if (!NILP(name = Ffont_get(XCAR (temp), QCfamily)) &&
+ STRINGP(name) &&
+ xstrcasecmp(SDATA(name), SDATA(family)) == 0) {
+ logfont.lfHeight *= XFLOAT_DATA (XCDR (temp));
+ break;
+ }
+ }
+ }
+ } else {
+ HFONT hfont = FONT_HANDLE (FRAME_FONT (f));
+ GetObject (hfont, sizeof (logfont), &logfont);
+ }
+
+ if (need_set_ime_font (&logfont))
+ {
+ ime_logfont = logfont;
+ PostMessage (hwnd, WM_MULE_IMM_SET_IMEFONT, (WPARAM) f, 0);
+ }
+}
+static void
+w32_set_ime_font (hwnd)
+ HWND hwnd;
+{
+ HIMC himc;
+
+ if (!fIME || NILP (Vime_control))
+ return;
+
+ himc = (ImmGetContextProc) (hwnd);
+ if (!himc)
+ return;
+ (ImmSetCompositionFontProc) (himc, &ime_logfont);
+ (ImmReleaseContextProc) (hwnd, himc);
+}
+#endif /* HAVE_NTGUI */
+
+static LRESULT CALLBACK
+conversion_agent_wndproc (HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
+/* HWND hwnd;
+ UINT message;
+ WPARAM wparam;
+ LPARAM lparam; */
+{
+ HIMC himc, holdimc;
+
+ switch (message)
+ {
+ case WM_MULE_IMM_SET_STATUS:
+ if (InSendMessage())
+ ReplyMessage(1);
+ w32_set_ime_status (hwnd, (int) wparam);
+ break;
+
+ case WM_MULE_IMM_GET_STATUS:
+ return w32_get_ime_status (hwnd);
+
+ case WM_MULE_IMM_SET_MODE:
+ return w32_set_ime_mode (hwnd, (int) wparam, (int) lparam);
+
+ case WM_MULE_IMM_SET_IMEFONT:
+ w32_set_ime_font (hwnd);
+
+ case WM_MULE_IMM_SET_CONVERSION_WINDOW:
+ if (w32_get_ime_status (hwnd))
+ w32_set_ime_conv_window (hwnd, (struct frame *) wparam);
+ break;
+
+#ifdef RECONVERSION
+ case WM_MULE_IMM_PERFORM_RECONVERSION:
+ if (ime_enable_reconversion)
+ w32_perform_reconversion(hwnd, (RECONVERTSTRING*)lparam);
+ break;
+#endif
+
+#if 0
+ case WM_MULE_IMM_GET_COMPOSITION_STRING:
+ return w32_get_ime_composition_string (hwnd);
+#endif
+
+ default:
+ return DefWindowProc (hwnd, message, wparam, lparam);
+ }
+ return 0;
+}
+
+
+/*
+ Emacs Lisp function entries
+*/
+
+DEFUN ("ime-force-on", Fime_force_on, Sime_force_on, 0, 1, 0,
+ doc: /* Force status of IME open. */)
+ (Lisp_Object eventp)
+{
+ if (fIME && !NILP (Vime_control))
+ {
+ HIMC himc;
+ HWND hwnd;
+
+ if (!NILP (Fime_get_mode ()))
+ return Qnil;
+#ifdef HAVE_NTGUI
+ if (NILP (eventp))
+ IME_event_off_count++;
+ hwnd = FRAME_W32_WINDOW (SELECTED_FRAME ());
+#else
+ hwnd = hwndConsole;
+#endif
+ SendMessage (hwnd, WM_MULE_IMM_SET_STATUS, 1, 0);
+ }
+ return Qnil;
+}
+
+DEFUN ("ime-force-off", Fime_force_off, Sime_force_off, 0, 1, 0,
+ doc: /* Force status of IME close. */)
+ (Lisp_Object eventp)
+{
+ if (fIME && !NILP (Vime_control))
+ {
+ HIMC himc;
+ HWND hwnd;
+
+ if (NILP (Fime_get_mode ()))
+ return Qnil;
+#ifdef HAVE_NTGUI
+ if (NILP (eventp))
+ IME_event_off_count++;
+ hwnd = FRAME_W32_WINDOW (SELECTED_FRAME ());
+#else
+ hwnd = hwndConsole;
+#endif
+ SendMessage (hwnd, WM_MULE_IMM_SET_STATUS, 0, 0);
+ }
+ return Qnil;
+}
+
+DEFUN ("ime-get-mode", Fime_get_mode, Sime_get_mode, 0, 0, "",
+ doc: /* Get IME status.
+t means status of IME is open. nil means it is close. */)
+ (void)
+{
+ if (fIME && !NILP (Vime_control))
+ {
+ HWND hwnd;
+ int result;
+
+#ifdef HAVE_NTGUI
+ hwnd = FRAME_W32_WINDOW (SELECTED_FRAME ());
+#else
+ hwnd = hwndConsole;
+#endif
+ result = SendMessage (hwnd, WM_MULE_IMM_GET_STATUS, 0, 0);
+
+ return result ? Qt : Qnil;
+ }
+ else
+ return Qnil;
+}
+
+DEFUN ("w32-set-ime-mode",
+ Fw32_set_ime_mode,
+ Sw32_set_ime_mode, 1, 2, 0,
+ doc: /* Set IME mode to MODE. If FRAME is omitted, the selected frame is used. */)
+ (Lisp_Object mode, Lisp_Object frame)
+{
+ struct frame *f;
+
+ if (NILP (frame))
+ {
+ f = SELECTED_FRAME ();
+ }
+ else
+ {
+ CHECK_FRAME (frame);
+ f = XFRAME (frame);
+ }
+ if (fIME && !NILP (Vime_control))
+ {
+ HWND hwnd;
+ int ret;
+ int newmode, mask;
+
+ newmode = 0;
+ mask = 0;
+
+ hwnd = FRAME_W32_WINDOW (f);
+
+ if (EQ (mode, intern ("katakana")))
+ {
+ newmode |= IME_CMODE_KATAKANA;
+ mask |= IME_CMODE_KATAKANA;
+ }
+ else if (EQ (mode, intern ("hiragana")))
+ {
+ newmode &= ~IME_CMODE_KATAKANA;
+ mask |= IME_CMODE_KATAKANA;
+ }
+ else if (EQ (mode, intern ("kanji")))
+ {
+ newmode |= IME_CMODE_HANJACONVERT;
+ mask |= IME_CMODE_HANJACONVERT;
+ }
+ else if (EQ (mode, intern ("nokanji")))
+ {
+ newmode &= ~IME_CMODE_HANJACONVERT;
+ mask |= IME_CMODE_HANJACONVERT;
+ }
+ else if (EQ (mode, intern ("code")))
+ {
+ newmode |= IME_CMODE_CHARCODE;
+ mask |= IME_CMODE_CHARCODE;
+ }
+ else if (EQ (mode, intern ("nocode")))
+ {
+ newmode &= ~IME_CMODE_CHARCODE;
+ mask |= IME_CMODE_CHARCODE;
+ }
+ else if (EQ (mode, intern ("non-convert")))
+ {
+ newmode |= IME_CMODE_NOCONVERSION;
+ mask |= IME_CMODE_NOCONVERSION;
+ }
+ else if (EQ (mode, intern ("convert")))
+ {
+ newmode &= ~IME_CMODE_NOCONVERSION;
+ mask |= IME_CMODE_NOCONVERSION;
+ }
+ else
+ error ("unknown mode!!");
+
+ ret = SendMessage (hwnd, WM_MULE_IMM_SET_MODE,
+ (WPARAM) newmode, (LPARAM) mask);
+
+ if (!ret)
+ return Qnil;
+
+ return Qt;
+ }
+ return Qnil;
+}
+
+DEFUN ("w32-ime-register-word-dialog",
+ Fw32_ime_register_word_dialog,
+ Sw32_ime_register_word_dialog, 2, 2, 0,
+ doc: /* Open IME regist word dialog. */)
+ (Lisp_Object reading, Lisp_Object word)
+{
+ HKL hkl;
+ int reading_len, word_len;
+ REGISTERWORD regword;
+ Lisp_Object encoded_reading, encoded_word;
+
+ CHECK_STRING (reading);
+ CHECK_STRING (word);
+
+ if (fIME && !NILP (Vime_control) && ImmConfigureIMEProc)
+ {
+ hkl = GetKeyboardLayout (0);
+ encoded_reading = Fencode_coding_string (reading,
+ Vlocale_coding_system,
+ Qnil, Qnil);
+ reading_len = SBYTES (encoded_reading);
+ regword.lpReading = SDATA (encoded_reading);
+
+ encoded_word = Fencode_coding_string (word,
+ Vlocale_coding_system,
+ Qnil, Qnil);
+ word_len = SBYTES (encoded_word);
+ regword.lpWord = SDATA (encoded_word);
+ (ImmConfigureIMEProc) (hkl, FRAME_W32_WINDOW (SELECTED_FRAME ()),
+ IME_CONFIG_REGISTERWORD, &regword);
+ }
+ return Qnil;
+}
+
+DEFUN ("ime-get-property", Fime_get_property, Sime_get_property, 1, 1, 0,
+ doc: /* Retrieves the property and capabilities of the IME associated with the specified input locale.
+INDEX is one of igp-property, igp-conversion, igp-sentence, igp-ui, igp-setcompstr, igp-select of igp-getimeversion*/)
+ (Lisp_Object index)
+{
+ int i;
+ Lisp_Object val;
+ DWORD v;
+
+ static const struct {
+ const char *name;
+ DWORD index;
+ } index_map[] = {
+ {"property", IGP_PROPERTY},
+ {"conversion", IGP_CONVERSION},
+ {"sentence", IGP_SENTENCE},
+ {"ui", IGP_UI},
+ {"setcompstr", IGP_SETCOMPSTR},
+ {"select", IGP_SELECT},
+ {"getimeversion", IGP_GETIMEVERSION},
+ }, prop_map[] = {
+ {"at-caret", IME_PROP_AT_CARET},
+ {"special-ui", IME_PROP_SPECIAL_UI},
+ {"candlist-start-from-1", IME_PROP_CANDLIST_START_FROM_1},
+ {"unicode", IME_PROP_UNICODE},
+ {"complete-on-unselect", IME_PROP_COMPLETE_ON_UNSELECT},
+ }, ui_map[] = {
+ {"rot2700", UI_CAP_2700},
+ {"rot90", UI_CAP_ROT90},
+ {"rotany", UI_CAP_ROTANY},
+ }, setcompstr_map[] = {
+ {"compstr", SCS_CAP_COMPSTR},
+ {"makeread", SCS_CAP_MAKEREAD},
+ {"setreconvertstring", SCS_CAP_SETRECONVERTSTRING},
+ }, select_map[] = {
+ {"conversion", SELECT_CAP_CONVERSION},
+ {"sentence", SELECT_CAP_SENTENCE},
+ }, imeversion_map[] = {
+ {"ver-0310", IMEVER_0310},
+ {"ver-0400", IMEVER_0400},
+ };
+
+ CHECK_SYMBOL(index);
+ for (i = 0; i < sizeof(index_map) / sizeof(index_map[0]); i++)
+ if (EQ(index, intern(index_map[i].name)))
+ break;
+ if (i >= sizeof(index_map) / sizeof(index_map[0]))
+ return Qnil;
+
+ v = (*ImmGetPropertyProc)(GetKeyboardLayout(0), index_map[i].index);
+ val = Qnil;
+#define MAKE_CAP_LIST(map) do { \
+ int j; \
+ for (j = sizeof(map) / sizeof(map[0]) - 1; j >= 0 ; j--) \
+ if (v & map[j].index) \
+ val = Fcons(intern(map[j].name), val); \
+} while(0)
+
+ switch (index_map[i].index) {
+ case IGP_PROPERTY:
+ MAKE_CAP_LIST(prop_map);
+ break;
+ case IGP_UI:
+ MAKE_CAP_LIST(ui_map);
+ break;
+ case IGP_SETCOMPSTR:
+ MAKE_CAP_LIST(setcompstr_map);
+ break;
+ case IGP_SELECT:
+ MAKE_CAP_LIST(select_map);
+ break;
+ case IGP_GETIMEVERSION:
+ MAKE_CAP_LIST(imeversion_map);
+ break;
+ }
+ return val;
+}
+
+#ifdef RECONVERSION
+BOOL w32_perform_reconversion(HWND hwnd, RECONVERTSTRING *reconv)
+{
+ struct frame *f = SELECTED_FRAME ();
+ HIMC himc;
+ BOOL result = FALSE;
+
+ himc = (ImmGetContextProc) (hwnd);
+ if (!himc) {
+ xfree(reconv);
+ return FALSE;
+ }
+
+ if ((*ImmSetCompositionStringProc) (himc,
+ SCS_QUERYRECONVERTSTRING,
+ reconv, reconv->dwSize,
+ NULL, 0 )
+ && (*ImmSetCompositionStringProc) (himc,
+ SCS_SETRECONVERTSTRING,
+ reconv, reconv->dwSize,
+ NULL, 0)) {
+ /* Set the position of candidate list dialog. */
+ (ImmReleaseContextProc) (hwnd, himc);
+ w32_set_ime_conv_window (hwnd, f);
+ result = TRUE;
+ } else
+ (ImmReleaseContextProc) (hwnd, himc);
+ xfree(reconv);
+ return result;
+}
+
+DEFUN ("w32-ime-perform-reconversion",
+ Fw32_ime_perform_reconversion,
+ Sw32_ime_perform_reconversion, 0, 0, "",
+ doc: /* perfom ime reconversion. */)
+ (void)
+{
+ HWND hwnd = FRAME_W32_WINDOW(SELECTED_FRAME());
+ DWORD size;
+ RECONVERTSTRING *reconv;
+
+ if (!ime_enable_reconversion ||
+ NILP(Fime_get_mode()))
+ return Qnil;
+
+ if ((size = get_reconversion_string (hwnd, NULL, NULL))
+ && (reconv = xmalloc (size)) != NULL
+ && (memset (reconv, 0, size), (reconv->dwSize = size))
+ && get_reconversion_string (hwnd, reconv, NULL))
+ PostMessage(hwnd, WM_MULE_IMM_PERFORM_RECONVERSION, 0, (LPARAM) reconv);
+
+ return Qt;
+}
+#endif
+
+#endif /* USE_W32_IME */
+
+
+/***********************************************************************
w32 specialized functions
***********************************************************************/
@@ -9294,6 +10480,9 @@
x_set_fullscreen,
x_set_font_backend,
x_set_alpha,
+#ifdef USE_W32_IME
+ 0, /* ime-font */
+#endif /* USE_W32_IME */
0, /* x_set_sticky */
0, /* x_set_tool_bar_position */
};
@@ -9307,6 +10496,10 @@
w32_visible_system_caret_hwnd = NULL;
DEFSYM (Qundefined_color, "undefined-color");
+#ifdef USE_W32_IME
+ DEFSYM (Qw32_ime_buffer_switch_p, "w32-ime-buffer-switch-p");
+ DEFSYM (Qime_font, "ime-font");
+#endif /* USE_W32_IME */
DEFSYM (Qcancel_timer, "cancel-timer");
DEFSYM (Qhyper, "hyper");
DEFSYM (Qsuper, "super");
@@ -9618,6 +10811,27 @@
This variable has effect only on Windows Vista and later. */);
w32_disable_new_uniscribe_apis = 0;
+#ifdef USE_W32_IME
+#ifdef RECONVERSION
+ DEFVAR_BOOL ("ime-enable-reconversion", ime_enable_reconversion,
+ doc: /* Non-nil enables IME reconversion capability. */);
+ ime_enable_reconversion = 1;
+#endif
+#ifdef DOCUMENTFEED
+ DEFVAR_BOOL ("ime-enable-document-feed", ime_enable_document_feed,
+ doc: /* Non-nil enables IME document feed capability. */);
+ ime_enable_document_feed = 1;
+#endif
+ DEFVAR_LISP ("ime-control", Vime_control, doc: /* IME control flag. */);
+ Vime_control = Qnil;
+
+ DEFVAR_LISP ("w32-ime-composition-window",
+ Vw32_ime_composition_window,
+ doc: /* If this is a window of current frame, IME composition window appears on the
+window instead of current window. */);
+ Vw32_ime_composition_window = Qnil;
+#endif /* USE_W32_IME */
+
#if 0 /* TODO: Port to W32 */
defsubr (&Sx_change_window_property);
defsubr (&Sx_delete_window_property);
@@ -9670,6 +10884,18 @@
defsubr (&Sw32_notification_close);
#endif
+#ifdef USE_W32_IME
+ defsubr (&Sw32_set_ime_mode);
+ defsubr (&Sw32_ime_register_word_dialog);
+ defsubr (&Sime_force_on);
+ defsubr (&Sime_force_off);
+ defsubr (&Sime_get_mode);
+ defsubr (&Sime_get_property);
+#ifdef RECONVERSION
+ defsubr (&Sw32_ime_perform_reconversion);
+#endif
+#endif /* USE_W32_IME */
+
#ifdef WINDOWSNT
defsubr (&Sfile_system_info);
defsubr (&Sdefault_printer_name);
@@ -9942,6 +11168,7 @@
get_title_bar_info_fn = (GetTitleBarInfo_Proc)
GetProcAddress (user32_lib, "GetTitleBarInfo");
+#ifndef USE_W32_IME
{
HMODULE imm32_lib = GetModuleHandle ("imm32.dll");
get_composition_string_fn = (ImmGetCompositionString_Proc)
@@ -9953,6 +11180,7 @@
set_ime_composition_window_fn = (ImmSetCompositionWindow_Proc)
GetProcAddress (imm32_lib, "ImmSetCompositionWindow");
}
+#endif /* !USE_W32_IME */
except_code = 0;
except_addr = 0;
--- ./src/w32font.c.orig 2017-04-15 00:02:47.000000000 +0900
+++ ./src/w32font.c 2017-09-13 21:00:32.717479200 +0900
@@ -52,7 +52,10 @@
#define JOHAB_CHARSET 130
#endif
-static void fill_in_logfont (struct frame *, LOGFONT *, Lisp_Object);
+#ifndef USE_W32_IME
+static
+#endif
+void fill_in_logfont (struct frame *, LOGFONT *, Lisp_Object);
static BYTE w32_antialias_type (Lisp_Object);
static Lisp_Object lispy_antialias_type (BYTE);
@@ -1911,7 +1914,10 @@
}
/* Fill in all the available details of LOGFONT from FONT_SPEC. */
-static void
+#ifndef USE_W32_IME
+static
+#endif
+void
fill_in_logfont (struct frame *f, LOGFONT *logfont, Lisp_Object font_spec)
{
Lisp_Object tmp, extra;
--- ./src/w32font.h.orig 2017-04-15 00:02:47.000000000 +0900
+++ ./src/w32font.h 2017-09-13 21:00:32.731508500 +0900
@@ -83,6 +83,9 @@
int uniscribe_check_otf (LOGFONT *font, Lisp_Object otf_spec);
Lisp_Object intern_font_name (char *);
+#ifdef USE_W32_IME
+void fill_in_logfont (struct frame *, LOGFONT *, Lisp_Object);
+#endif
extern void syms_of_w32font (void);
extern void globals_of_w32font (void);
--- ./src/w32term.c.orig 2017-04-15 00:02:47.000000000 +0900
+++ ./src/w32term.c 2017-09-13 21:00:32.746540600 +0900
@@ -5302,6 +5302,81 @@
break;
#endif
+#ifdef USE_W32_IME
+ case WM_MULE_IME_STATUS:
+ f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
+
+ if (f && !f->iconified && f->visible)
+ {
+ inev.kind = NON_ASCII_KEYSTROKE_EVENT;
+ inev.code = VK_KANJI;
+ inev.modifiers = 0;
+ XSETFRAME (inev.frame_or_window, f);
+ inev.timestamp = msg.msg.time;
+ }
+ break;
+
+ case WM_MULE_IME_REPORT:
+ {
+ LPWSTR lpStr;
+ struct input_event buf;
+ HANDLE hw32_ime_string = (HANDLE) msg.msg.wParam;
+
+ f = (struct frame *) msg.msg.lParam;
+ if (f && !f->iconified && f->visible)
+ {
+ lpStr = (LPWSTR) hw32_ime_string;
+ while(lpStr)
+ {
+ wchar_t code;
+
+ EVENT_INIT (buf);
+ XSETFRAME (buf.frame_or_window, f);
+ buf.timestamp = msg.msg.time;
+ buf.modifiers = 0;
+ if (*lpStr)
+ {
+ if (*lpStr < 0x80)
+ buf.kind = ASCII_KEYSTROKE_EVENT;
+ else
+ buf.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
+ if ((*lpStr & 0xFC00) == 0xD800
+ && (*(lpStr + 1) & 0xFC00) == 0xDC00)
+ {
+ buf.code = 0x10000
+ + (((*lpStr & 0x3FF) << 10)
+ | *(lpStr + 1) & 0x3FF);
+ lpStr++;
+ }
+ else
+ buf.code = *(lpStr++);
+ kbd_buffer_store_event (&buf);
+ }
+ else
+ {
+ buf.kind = NON_ASCII_KEYSTROKE_EVENT;
+ buf.code = VK_COMPEND;
+ kbd_buffer_store_event (&buf);
+ break;
+ }
+ }
+ HeapFree (GetProcessHeap (), 0, (LPVOID) hw32_ime_string);
+ }
+ }
+ break;
+
+ case WM_MULE_IME_DEL_RANGE:
+ del_range ((ptrdiff_t) msg.msg.wParam, (ptrdiff_t) msg.msg.lParam);
+ Fgoto_char (make_number (msg.msg.wParam));
+ redisplay ();
+ break;
+
+ case WM_MULE_IME_SET_FONT:
+ w32_set_ime_logfont (msg.msg.hwnd, (struct frame *) msg.msg.wParam);
+ break;
+
+#endif /* USE_W32_IME */
+
default:
/* Check for messages registered at runtime. */
if (msg.msg.message == msh_mousewheel)
@@ -5667,7 +5742,12 @@
w32_system_caret_hdr_height = WINDOW_HEADER_LINE_HEIGHT (w);
w32_system_caret_mode_height = WINDOW_MODE_LINE_HEIGHT (w);
+#ifdef USE_W32_IME
+ if (f && f == FRAME_DISPLAY_INFO (f)->x_highlight_frame)
+ PostMessage (hwnd, WM_MULE_IMM_SET_CONVERSION_WINDOW, (WPARAM) f, 0);
+#else
PostMessage (hwnd, WM_IME_STARTCOMPOSITION, 0, 0);
+#endif
/* If the size of the active cursor changed, destroy the old
system caret. */
@@ -7059,6 +7139,9 @@
horizontal_scroll_bar_left_border = horizontal_scroll_bar_right_border
= GetSystemMetrics (SM_CYHSCROLL);
}
+#ifdef USE_W32_IME
+ w32_ime_control_init();
+#endif /* USE_W32_IME */
}
void
--- ./src/w32term.h.orig 2017-04-15 00:02:47.000000000 +0900
+++ ./src/w32term.h 2017-09-13 21:00:32.754556700 +0900
@@ -627,6 +627,8 @@
#endif /* WM_MOUSEHWHEEL */
#ifndef WM_APPCOMMAND
#define WM_APPCOMMAND 0x319
+#endif
+#ifndef GET_APPCOMMAND_LPARAM
#define GET_APPCOMMAND_LPARAM(lParam) (HIWORD(lParam) & 0x7fff)
#endif
#ifndef WM_UNICHAR
@@ -665,6 +667,96 @@
#define WM_EMACS_FILENOTIFY (WM_EMACS_START + 25)
#define WM_EMACS_END (WM_EMACS_START + 26)
+#ifdef USE_W32_IME
+#ifndef VK_KANJI
+#define VK_KANJI 0x19
+#endif
+#ifndef VK_KANA
+#define VK_KANA 0x15
+#endif
+#define VK_COMPEND 0x1A
+
+#ifdef RECONVERSION
+#ifndef WM_IME_REQUEST
+#define WM_IME_REQUEST 0x288
+#endif
+#ifndef IMR_COMPOSITIONWINDOW
+#define IMR_COMPOSITIONWINDOW 0x0001
+#endif
+#ifndef IMR_CANDIDATEWINDOW
+#define IMR_CANDIDATEWINDOW 0x0002
+#endif
+#ifdef IMR_COMPOSITIONFONT
+#define IMR_COMPOSITIONFONT 0x0003
+#endif
+#ifndef IMR_RECONVERTSTRING
+#define IMR_RECONVERTSTRING 0x0004
+#endif
+#ifndef IMR_CONFIRMRECONVERTSTRING
+#define IMR_CONFIRMRECONVERTSTRING 0x0005
+#endif
+#endif
+#ifndef IME_PROP_COMPLETE_ON_UNSELECT
+#define IME_PROP_COMPLETE_ON_UNSELECT 0x00100000
+#endif
+#ifndef SCS_CAP_SETRECONVERTSTRING
+#define SCS_CAP_SETRECONVERTSTRING 0x00000004
+#endif
+
+/* For internal communications
+ from window procedure to event loop. */
+#define WM_MULE_IME_REPORT (WM_USER+2200)
+#define WM_MULE_IME_STATUS (WM_USER+2201)
+#define WM_MULE_IME_DEL_RANGE (WM_USER+2202)
+#define WM_MULE_IME_SET_FONT (WM_USER+2203)
+
+/* For internal communications
+ from main thread to window procedure. */
+#define WM_MULE_IMM_MESSAGE_START (WM_USER+2300)
+#define WM_MULE_IMM_SET_STATUS (WM_USER+2300)
+#define WM_MULE_IMM_GET_STATUS (WM_USER+2301)
+#if 0
+#define WM_MULE_IMM_DEAL_WITH_CONTEXT (WM_USER+2302)
+#define WM_MULE_IMM_SET_COMPOSITION_STRING (WM_USER+2303)
+#endif
+#define WM_MULE_IMM_GET_COMPOSITION_STRING (WM_USER+2304)
+#define WM_MULE_IMM_SET_MODE (WM_USER+2305)
+#if 0
+#define WM_MULE_IMM_NOTIFY (WM_USER+2310)
+#define WM_MULE_IMM_GET_UNDETERMINED_STRING_LENGTH (WM_USER+2320)
+#endif
+#define WM_MULE_IMM_SET_IMEFONT (WM_USER+2311)
+#define WM_MULE_IMM_SET_CONVERSION_WINDOW (WM_USER+2312)
+
+#define WM_MULE_IMM_PERFORM_RECONVERSION (WM_USER+2320)
+
+#define WM_MULE_IMM_MESSAGE_END (WM_USER+2399)
+#define MESSAGE_IMM_COM_P(message) \
+ (((message) >= WM_MULE_IMM_MESSAGE_START) && \
+ ((message) <= WM_MULE_IMM_MESSAGE_END))
+
+#ifdef RECONVERSION
+#ifndef HAVE_RECONVERTSTRING
+typedef struct tagRECONVERTSTRING {
+ DWORD dwSize;
+ DWORD dwVersion;
+ DWORD dwStrLen;
+ DWORD dwStrOffset;
+ DWORD dwCompStrLen;
+ DWORD dwCompStrOffset;
+ DWORD dwTargetStrLen;
+ DWORD dwTargetStrOffset;
+} RECONVERTSTRING, *PRECONVERTSTRING;
+#endif
+#ifndef SCS_SETRECONVERTSTRING
+#define SCS_SETRECONVERTSTRING 0x00010000
+#endif
+#ifndef SCS_QUERYRECONVERTSTRING
+#define SCS_QUERYRECONVERTSTRING 0x00020000
+#endif
+#endif /* RECONVERSION */
+#endif /* USE_W32_IME */
+
#define WND_FONTWIDTH_INDEX (0)
#define WND_LINEHEIGHT_INDEX (4)
#define WND_BORDER_INDEX (8)
@@ -860,3 +952,8 @@
#ifdef CYGWIN
extern int w32_message_fd;
#endif /* CYGWIN */
+
+#ifdef USE_W32_IME
+extern void w32_set_ime_logfont (HWND, struct frame *);
+extern void w32_ime_control_init (void);
+#endif /* USE_W32_IME */
--- ./src/window.c.orig 2017-04-15 00:02:47.000000000 +0900
+++ ./src/window.c 2017-09-13 21:00:32.764577300 +0900
@@ -466,6 +466,10 @@
EMACS_INT window_select_count;
+#ifdef USE_W32_IME
+extern int ime_in_conversion;
+#endif
+
/* If select_window is called with inhibit_point_swap true it will
not store point of the old selected window's buffer back into that
window's pointm slot. This is needed by Fset_window_configuration to
@@ -477,6 +481,9 @@
{
struct window *w;
struct frame *sf;
+#ifdef USE_W32_IME
+ Lisp_Object oldwin = selected_window;
+#endif /* USE_W32_IME */
CHECK_LIVE_WINDOW (window);
@@ -529,6 +536,11 @@
record_buffer (w->contents);
}
+#ifdef USE_W32_IME
+ if (!ime_in_conversion && !NILP (Vselect_window_functions))
+ run_hook_with_args_2 (Qselect_window_functions, oldwin, window);
+#endif /* USE_W32_IME */
+
return window;
}
@@ -3375,6 +3387,12 @@
set_window_buffer (window, buffer, true, !NILP (keep_margins));
+#ifdef USE_W32_IME
+ if (!ime_in_conversion && !NILP (Vset_selected_window_buffer_functions))
+ CALLN (Frun_hook_with_args, Qset_selected_window_buffer_functions,
+ tem, window, buffer);
+#endif /* USE_W32_IME */
+
return Qnil;
}
@@ -7160,6 +7178,10 @@
Fput (Qscroll_down, Qscroll_command, Qt);
DEFSYM (Qwindow_configuration_change_hook, "window-configuration-change-hook");
+#ifdef USE_W32_IME
+ DEFSYM (Qset_selected_window_buffer_functions, "set-selected-window-buffer-functions");
+ DEFSYM (Qselect_window_functions, "select-window-functions");
+#endif
DEFSYM (Qwindowp, "windowp");
DEFSYM (Qwindow_configuration_p, "window-configuration-p");
DEFSYM (Qwindow_live_p, "window-live-p");
@@ -7248,6 +7270,17 @@
with the relevant frame selected. */);
Vwindow_configuration_change_hook = Qnil;
+#ifdef USE_W32_IME
+ DEFVAR_LISP ("set-selected-window-buffer-functions",
+ Vset_selected_window_buffer_functions,
+ doc: /* Functions to call when set-window-buffer is called. */);
+ Vset_selected_window_buffer_functions = Qnil;
+
+ DEFVAR_LISP ("select-window-functions", Vselect_window_functions,
+ doc: /* Functions to call when select-window is called. */);
+ Vselect_window_functions = Qnil;
+#endif
+
DEFVAR_LISP ("recenter-redisplay", Vrecenter_redisplay,
doc: /* Non-nil means `recenter' redraws entire frame.
If this option is non-nil, then the `recenter' command with a nil
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment