Last active
August 13, 2020 12:07
-
-
Save ponkore/cff76d28023b648ef728070d1c721c71 to your computer and use it in GitHub Desktop.
Windows IME Patch for Emacs27.1 on Windows (derived from https://gist.github.com/rzl24ozi/b4f4b4d729035d3c439b )
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/lisp/loadup.el b/lisp/loadup.el | |
index 97525b2..634e6a0 100644 | |
--- a/lisp/loadup.el | |
+++ b/lisp/loadup.el | |
@@ -311,7 +311,9 @@ | |
(load "w32-vars") | |
(load "term/w32-win") | |
(load "disp-table") | |
+ (load "international/w32-ime") | |
(when (eq system-type 'windows-nt) | |
+ (load "image") | |
(load "w32-fns") | |
(load "ls-lisp") | |
(load "dos-w32")))) | |
diff --git a/lisp/startup.el b/lisp/startup.el | |
index bff1000..91bde4e 100644 | |
--- a/lisp/startup.el | |
+++ b/lisp/startup.el | |
@@ -643,6 +643,8 @@ normal-top-level | |
;; `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) | |
diff --git a/lisp/term/w32-win.el b/lisp/term/w32-win.el | |
index 3e932c7..86fb993 100644 | |
--- a/lisp/term/w32-win.el | |
+++ b/lisp/term/w32-win.el | |
@@ -281,6 +281,10 @@ libgnutls-version | |
'(glib "libglib-2.0-0.dll") | |
'(gio "libgio-2.0-0.dll") | |
'(gobject "libgobject-2.0-0.dll") | |
+ '(magickwand "libMagickWand-6.Q16HDRI-5.dll" "libMagickWand-6.Q16-5.dll" | |
+ "libMagickWand-6.Q16HDRI-2.dll" "libMagickWand-6.Q16-2.dll") | |
+ '(magickcore "libMagickCore-6.Q16HDRI-5.dll" "libMagickCore-6.Q16-5.dll" | |
+ "libMagickCore-6.Q16HDRI-2.dll" "libMagickCore-6.Q16-2.dll") | |
(if (>= libgnutls-version 30400) | |
'(gnutls "libgnutls-30.dll") | |
'(gnutls "libgnutls-28.dll" "libgnutls-26.dll")) | |
diff --git a/src/frame.c b/src/frame.c | |
index 4dd8bb1..7001109 100644 | |
--- a/src/frame.c | |
+++ b/src/frame.c | |
@@ -3776,6 +3776,9 @@ DEFUN ("set-frame-window-state-change", Fset_frame_window_state_change, | |
{"ns-appearance", SYMBOL_INDEX (Qns_appearance)}, | |
{"ns-transparent-titlebar", SYMBOL_INDEX (Qns_transparent_titlebar)}, | |
#endif | |
+#ifdef USE_W32_IME | |
+ {"ime-font", SYMBOL_INDEX (Qime_font)}, | |
+#endif /* USE_W32_IME */ | |
}; | |
#ifdef HAVE_WINDOW_SYSTEM | |
@@ -6024,6 +6027,9 @@ syms_of_frame (void) | |
DEFSYM (Qtop_only, "top-only"); | |
DEFSYM (Qiconify_top_level, "iconify-top-level"); | |
DEFSYM (Qmake_invisible, "make-invisible"); | |
+#ifdef USE_W32_IME | |
+ DEFSYM (Qime_font, "ime-font"); | |
+#endif /* USE_W32_IME */ | |
{ | |
int i; | |
diff --git a/src/image.c b/src/image.c | |
index 56878bc..63420e0 100644 | |
--- a/src/image.c | |
+++ b/src/image.c | |
@@ -8618,6 +8618,231 @@ imagemagick_initialize (void) | |
} | |
} | |
+#ifdef WINDOWSNT | |
+DEF_DLL_FN (MagickWand *, CloneMagickWand, (const MagickWand *)); | |
+DEF_DLL_FN (MagickWand *, DestroyMagickWand, (MagickWand *)); | |
+DEF_DLL_FN (MagickWand *, DestroyPixelIterator, (PixelIterator *)); | |
+DEF_DLL_FN (PixelWand *, DestroyPixelWand, (PixelWand *)); | |
+#ifdef HAVE_MAGICKAUTOORIENTIMAGE | |
+DEF_DLL_FN (MagickBooleanType, MagickAutoOrientImage, (MagickWand *)); | |
+#endif | |
+DEF_DLL_FN (MagickBooleanType, MagickCropImage, (MagickWand *, const size_t, const size_t, const ssize_t, const ssize_t)); | |
+#ifdef HAVE_MAGICKEXPORTIMAGEPIXELS | |
+DEF_DLL_FN (MagickBooleanType, MagickExportImagePixels, (MagickWand *, const ssize_t, const ssize_t, const size_t, const size_t, const char *, const StorageType, void *)); | |
+#endif | |
+DEF_DLL_FN (char *, MagickGetException, (const MagickWand *, ExceptionType *)); | |
+DEF_DLL_FN (MagickWand *, MagickGetImage, (MagickWand *)); | |
+DEF_DLL_FN (DisposeType, MagickGetImageDelay, (MagickWand *)); | |
+DEF_DLL_FN (DisposeType, MagickGetImageDispose, (MagickWand *)); | |
+DEF_DLL_FN (size_t, MagickGetImageHeight, (MagickWand *)); | |
+DEF_DLL_FN (MagickBooleanType, MagickGetImagePage, (MagickWand *, size_t *, size_t *, ssize_t *, ssize_t *)); | |
+DEF_DLL_FN (char *, MagickGetImageSignature, (MagickWand *)); | |
+DEF_DLL_FN (size_t, MagickGetImageWidth, (MagickWand *)); | |
+DEF_DLL_FN (size_t, MagickGetNumberImages, (MagickWand *)); | |
+#ifdef HAVE_MAGICKMERGEIMAGELAYERS | |
+DEF_DLL_FN (MagickWand *, MagickMergeImageLayers, (MagickWand *, const ImageLayerMethod)); | |
+#else | |
+DEF_DLL_FN (MagickWand *, MagickFlattenImages, (MagickWand *)); | |
+#endif | |
+DEF_DLL_FN (MagickBooleanType, MagickReadImage, (MagickWand *, const char *)); | |
+DEF_DLL_FN (MagickBooleanType, MagickReadImageBlob, (MagickWand *, const void *, const size_t)); | |
+DEF_DLL_FN (void *, MagickRelinquishMemory, (void *)); | |
+DEF_DLL_FN (MagickBooleanType, MagickRotateImage, (MagickWand *, const PixelWand *, const double)); | |
+DEF_DLL_FN (MagickBooleanType, MagickScaleImage, (MagickWand *, const size_t, const size_t)); | |
+DEF_DLL_FN (MagickBooleanType, MagickSetDepth, (MagickWand *, const size_t)); | |
+DEF_DLL_FN (MagickBooleanType, MagickSetFilename, (MagickWand *, const char *)); | |
+DEF_DLL_FN (MagickBooleanType, MagickSetImageBackgroundColor, (MagickWand *, const PixelWand *)); | |
+DEF_DLL_FN (MagickBooleanType, MagickSetIteratorIndex, (MagickWand *, const ssize_t)); | |
+DEF_DLL_FN (MagickBooleanType, MagickSetSize, (MagickWand *, const size_t, const size_t)); | |
+DEF_DLL_FN (void, MagickWandGenesis, (void)); | |
+DEF_DLL_FN (void, MagickWandTerminus, (void)); | |
+DEF_DLL_FN (MagickWand *, NewMagickWand, (void)); | |
+DEF_DLL_FN (PixelIterator *, NewPixelIterator, (MagickWand *)); | |
+DEF_DLL_FN (PixelWand *, NewPixelWand, (void)); | |
+DEF_DLL_FN (double, PixelGetAlpha, (const PixelWand *)); | |
+DEF_DLL_FN (void, PixelGetMagickColor, (const PixelWand *, MagickPixelPacket *)); | |
+DEF_DLL_FN (PixelWand **, PixelGetNextIteratorRow, (PixelIterator *, size_t *)); | |
+DEF_DLL_FN (MagickBooleanType, PixelSetIteratorRow, (PixelIterator *, const ssize_t)); | |
+DEF_DLL_FN (void, PixelSetMagickColor, (PixelWand *, const MagickPixelPacket *)); | |
+DEF_DLL_FN (void, PixelSetRed, (PixelWand *, const double)); | |
+DEF_DLL_FN (void, PixelSetGreen, (PixelWand *, const double)); | |
+DEF_DLL_FN (void, PixelSetBlue, (PixelWand *, const double)); | |
+DEF_DLL_FN (MagickBooleanType, PixelSyncIterator, (PixelIterator *)); | |
+ | |
+DEF_DLL_FN (ExceptionInfo *, AcquireExceptionInfo, (void)); | |
+DEF_DLL_FN (ExceptionInfo *, DestroyExceptionInfo, (ExceptionInfo *)); | |
+DEF_DLL_FN (char *, DestroyString, (char *)); | |
+DEF_DLL_FN (char **, GetMagickList, (const char *, size_t *, ExceptionInfo *)); | |
+ | |
+static bool | |
+init_imagemagick_functions (void) | |
+{ | |
+ HMODULE magickwand, magickcore; | |
+ | |
+ if (!(magickcore = w32_delayed_load (Qmagickcore)) | |
+ || !(magickwand = w32_delayed_load (Qmagickwand))) | |
+ return 0; | |
+ | |
+ LOAD_DLL_FN (magickwand, CloneMagickWand); | |
+ LOAD_DLL_FN (magickwand, DestroyMagickWand); | |
+ LOAD_DLL_FN (magickwand, DestroyPixelIterator); | |
+ LOAD_DLL_FN (magickwand, DestroyPixelWand); | |
+#ifdef HAVE_MAGICKAUTOORIENTIMAGE | |
+ LOAD_DLL_FN (magickwand, MagickAutoOrientImage); | |
+#endif | |
+ LOAD_DLL_FN (magickwand, MagickCropImage); | |
+#ifdef HAVE_MAGICKEXPORTIMAGEPIXELS | |
+ LOAD_DLL_FN (magickwand, MagickExportImagePixels); | |
+#endif | |
+ LOAD_DLL_FN (magickwand, MagickGetException); | |
+ LOAD_DLL_FN (magickwand, MagickGetImage); | |
+ LOAD_DLL_FN (magickwand, MagickGetImageDelay); | |
+ LOAD_DLL_FN (magickwand, MagickGetImageDispose); | |
+ LOAD_DLL_FN (magickwand, MagickGetImageHeight); | |
+ LOAD_DLL_FN (magickwand, MagickGetImagePage); | |
+ LOAD_DLL_FN (magickwand, MagickGetImageSignature); | |
+ LOAD_DLL_FN (magickwand, MagickGetImageWidth); | |
+ LOAD_DLL_FN (magickwand, MagickGetNumberImages); | |
+#ifdef HAVE_MAGICKMERGEIMAGELAYERS | |
+ LOAD_DLL_FN (magickwand, MagickMergeImageLayers); | |
+#else | |
+ LOAD_DLL_FN (magickwand, MagickFlattenImages); | |
+#endif | |
+ LOAD_DLL_FN (magickwand, MagickReadImage); | |
+ LOAD_DLL_FN (magickwand, MagickReadImageBlob); | |
+ LOAD_DLL_FN (magickwand, MagickRelinquishMemory); | |
+ LOAD_DLL_FN (magickwand, MagickRotateImage); | |
+ LOAD_DLL_FN (magickwand, MagickScaleImage); | |
+ LOAD_DLL_FN (magickwand, MagickSetDepth); | |
+ LOAD_DLL_FN (magickwand, MagickSetFilename); | |
+ LOAD_DLL_FN (magickwand, MagickSetImageBackgroundColor); | |
+ LOAD_DLL_FN (magickwand, MagickSetIteratorIndex); | |
+ LOAD_DLL_FN (magickwand, MagickSetSize); | |
+ LOAD_DLL_FN (magickwand, MagickWandGenesis); | |
+ LOAD_DLL_FN (magickwand, MagickWandTerminus); | |
+ LOAD_DLL_FN (magickwand, NewMagickWand); | |
+ LOAD_DLL_FN (magickwand, NewPixelIterator); | |
+ LOAD_DLL_FN (magickwand, NewPixelWand); | |
+ LOAD_DLL_FN (magickwand, PixelGetAlpha); | |
+ LOAD_DLL_FN (magickwand, PixelGetMagickColor); | |
+ LOAD_DLL_FN (magickwand, PixelGetNextIteratorRow); | |
+ LOAD_DLL_FN (magickwand, PixelSetIteratorRow); | |
+ LOAD_DLL_FN (magickwand, PixelSetMagickColor); | |
+ LOAD_DLL_FN (magickwand, PixelSetRed); | |
+ LOAD_DLL_FN (magickwand, PixelSetGreen); | |
+ LOAD_DLL_FN (magickwand, PixelSetBlue); | |
+ LOAD_DLL_FN (magickwand, PixelSyncIterator); | |
+ | |
+ LOAD_DLL_FN (magickcore, AcquireExceptionInfo); | |
+ LOAD_DLL_FN (magickcore, DestroyExceptionInfo); | |
+ LOAD_DLL_FN (magickcore, DestroyString); | |
+ LOAD_DLL_FN (magickcore, GetMagickList); | |
+ | |
+ return 1; | |
+} | |
+ | |
+#undef CloneMagickWand | |
+#undef DestroyMagickWand | |
+#undef DestroyPixelIterator | |
+#undef DestroyPixelWand | |
+#undef MagickAutoOrientImage | |
+#undef MagickCropImage | |
+#undef MagickExportImagePixels | |
+#undef MagickGetException | |
+#undef MagickGetImage | |
+#undef MagickGetImageDelay | |
+#undef MagickGetImageDispose | |
+#undef MagickGetImageHeight | |
+#undef MagickGetImagePage | |
+#undef MagickGetImageSignature | |
+#undef MagickGetImageWidth | |
+#undef MagickGetNumberImages | |
+#ifdef HAVE_MAGICKMERGEIMAGELAYERS | |
+#undef MagickMergeImageLayers | |
+#else | |
+#undef MagickFlattenImages | |
+#endif | |
+#undef MagickReadImage | |
+#undef MagickReadImageBlob | |
+#undef MagickRelinquishMemory | |
+#undef MagickRotateImage | |
+#undef MagickScaleImage | |
+#undef MagickSetDepth | |
+#undef MagickSetFilename | |
+#undef MagickSetImageBackgroundColor | |
+#undef MagickSetIteratorIndex | |
+#undef MagickSetSize | |
+#undef MagickWandGenesis | |
+#undef MagickWandTerminus | |
+#undef NewMagickWand | |
+#undef NewPixelIterator | |
+#undef NewPixelWand | |
+#undef PixelGetAlpha | |
+#undef PixelGetMagickColor | |
+#undef PixelGetNextIteratorRow | |
+#undef PixelSetIteratorRow | |
+#undef PixelSetMagickColor | |
+#undef PixelSetRed | |
+#undef PixelSetGreen | |
+#undef PixelSetBlue | |
+#undef PixelSyncIterator | |
+#undef AcquireExceptionInfo | |
+#undef DestroyExceptionInfo | |
+#undef DestroyString | |
+#undef GetMagickList | |
+ | |
+#define CloneMagickWand fn_CloneMagickWand | |
+#define DestroyMagickWand fn_DestroyMagickWand | |
+#define DestroyPixelIterator fn_DestroyPixelIterator | |
+#define DestroyPixelWand fn_DestroyPixelWand | |
+#define MagickAutoOrientImage fn_MagickAutoOrientImage | |
+#define MagickCropImage fn_MagickCropImage | |
+#define MagickExportImagePixels fn_MagickExportImagePixels | |
+#define MagickGetException fn_MagickGetException | |
+#define MagickGetImage fn_MagickGetImage | |
+#define MagickGetImageDelay fn_MagickGetImageDelay | |
+#define MagickGetImageDispose fn_MagickGetImageDispose | |
+#define MagickGetImageHeight fn_MagickGetImageHeight | |
+#define MagickGetImagePage fn_MagickGetImagePage | |
+#define MagickGetImageSignature fn_MagickGetImageSignature | |
+#define MagickGetImageWidth fn_MagickGetImageWidth | |
+#define MagickGetNumberImages fn_MagickGetNumberImages | |
+#ifdef HAVE_MAGICKMERGEIMAGELAYERS | |
+#define MagickMergeImageLayers fn_MagickMergeImageLayers | |
+#else | |
+#define MagickFlattenImages fn_MagickFlattenImages | |
+#endif | |
+#define MagickReadImage fn_MagickReadImage | |
+#define MagickReadImageBlob fn_MagickReadImageBlob | |
+#define MagickRelinquishMemory fn_MagickRelinquishMemory | |
+#define MagickRotateImage fn_MagickRotateImage | |
+#define MagickScaleImage fn_MagickScaleImage | |
+#define MagickSetDepth fn_MagickSetDepth | |
+#define MagickSetFilename fn_MagickSetFilename | |
+#define MagickSetImageBackgroundColor fn_MagickSetImageBackgroundColor | |
+#define MagickSetIteratorIndex fn_MagickSetIteratorIndex | |
+#define MagickSetSize fn_MagickSetSize | |
+#define MagickWandGenesis fn_MagickWandGenesis | |
+#define MagickWandTerminus fn_MagickWandTerminus | |
+#define NewMagickWand fn_NewMagickWand | |
+#define NewPixelIterator fn_NewPixelIterator | |
+#define NewPixelWand fn_NewPixelWand | |
+#define PixelGetAlpha fn_PixelGetAlpha | |
+#define PixelGetMagickColor fn_PixelGetMagickColor | |
+#define PixelGetNextIteratorRow fn_PixelGetNextIteratorRow | |
+#define PixelSetIteratorRow fn_PixelSetIteratorRow | |
+#define PixelSetMagickColor fn_PixelSetMagickColor | |
+#define PixelSetRed fn_PixelSetRed | |
+#define PixelSetGreen fn_PixelSetGreen | |
+#define PixelSetBlue fn_PixelSetBlue | |
+#define PixelSyncIterator fn_PixelSyncIterator | |
+#define AcquireExceptionInfo fn_AcquireExceptionInfo | |
+#define DestroyExceptionInfo fn_DestroyExceptionInfo | |
+#define DestroyString fn_DestroyString | |
+#define GetMagickList fn_GetMagickList | |
+ | |
+#endif /* !WINDOWSNT */ | |
+ | |
/* Log ImageMagick error message. | |
Useful when an ImageMagick function returns the status `MagickFalse'. */ | |
@@ -9299,6 +9524,11 @@ DEFUN ("imagemagick-types", Fimagemagick_types, Simagemagick_types, 0, 0, 0, | |
size_t i; | |
imagemagick_initialize (); | |
+#if WINDOWSNT | |
+ if (!init_imagemagick_functions ()) | |
+ return Qnil; | |
+#endif | |
+ | |
ex = AcquireExceptionInfo (); | |
imtypes = GetMagickList ("*", &numf, ex); | |
DestroyExceptionInfo (ex); | |
@@ -10338,6 +10568,10 @@ syms_of_image (void) | |
#if defined (HAVE_IMAGEMAGICK) | |
DEFSYM (Qimagemagick, "imagemagick"); | |
add_image_type (Qimagemagick); | |
+#if defined HAVE_NTGUI && !defined CYGWIN | |
+ DEFSYM (Qmagickwand, "magickwand"); | |
+ DEFSYM (Qmagickcore, "magickcore"); | |
+#endif /* HAVE_NTGUI */ | |
#endif | |
#if defined (HAVE_RSVG) | |
diff --git a/src/keyboard.c b/src/keyboard.c | |
index 5f136f0..576d699 100644 | |
--- a/src/keyboard.c | |
+++ b/src/keyboard.c | |
@@ -4594,7 +4594,11 @@ #define FUNCTION_KEY_OFFSET 0x0 | |
"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 */ | |
@@ -9305,6 +9309,12 @@ read_key_sequence (Lisp_Object *keybuf, Lisp_Object prompt, | |
{ | |
ptrdiff_t count = SPECPDL_INDEX (); | |
+ /* To control IME */ | |
+#ifdef USE_W32_IME | |
+ 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; | |
@@ -9426,6 +9436,12 @@ read_key_sequence (Lisp_Object *keybuf, Lisp_Object prompt, | |
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 = READ_KEY_ELTS + 1; | |
Lisp_Object first_event = mock_input > 0 ? keybuf[0] : Qnil; | |
@@ -9508,6 +9524,16 @@ read_key_sequence (Lisp_Object *keybuf, Lisp_Object prompt, | |
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 >= READ_KEY_ELTS) | |
error ("Key sequence too long"); | |
@@ -10192,6 +10218,12 @@ read_key_sequence (Lisp_Object *keybuf, Lisp_Object prompt, | |
? 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); | |
diff --git a/src/w32fns.c b/src/w32fns.c | |
index 2f01fb5..8256e27 100644 | |
--- a/src/w32fns.c | |
+++ b/src/w32fns.c | |
@@ -59,6 +59,11 @@ #define _WIN32_WINNT 0x0600 | |
#include "pdumper.h" | |
+#ifdef USE_W32_IME | |
+#include "fontset.h" | |
+#include "w32font.h" | |
+#endif | |
+ | |
#include <basetyps.h> | |
#include <unknwn.h> | |
#include <commctrl.h> | |
@@ -86,6 +91,44 @@ #define FOF_NO_CONNECTED_ELEMENTS 0x2000 | |
#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; | |
+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) | |
@@ -160,12 +203,14 @@ DECLARE_HANDLE(HMONITOR); | |
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); | |
@@ -183,10 +228,12 @@ DECLARE_HANDLE(HMONITOR); | |
(HANDLE hThread, PCWSTR lpThreadDescription); | |
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; | |
@@ -197,8 +244,13 @@ DECLARE_HANDLE(HMONITOR); | |
extern AppendMenuW_Proc unicode_append_menu; | |
+#ifdef USE_W32_IME | |
+/* Flag for indicating in conversion in IME. */ | |
+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; | |
@@ -803,6 +855,15 @@ w32_color_map_lookup (const char *colorname) | |
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); | |
+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); | |
+#endif /* USE_W32_IME */ | |
static void | |
add_system_logical_colors_to_map (Lisp_Object *system_colors) | |
@@ -2492,6 +2553,8 @@ w32_createwindow (struct frame *f, int *coords) | |
if (hwnd) | |
{ | |
+ static int initialized = 0; | |
+ | |
if (FRAME_SKIP_TASKBAR (f)) | |
SetWindowLong (hwnd, GWL_EXSTYLE, | |
GetWindowLong (hwnd, GWL_EXSTYLE) | WS_EX_NOACTIVATE); | |
@@ -2503,6 +2566,12 @@ w32_createwindow (struct frame *f, int *coords) | |
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); | |
@@ -4521,6 +4590,24 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | |
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 */ | |
FALLTHROUGH; | |
@@ -4540,6 +4627,7 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | |
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 | |
@@ -4664,6 +4752,7 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | |
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. */ | |
@@ -5487,8 +5576,89 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | |
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 = w32_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 = w32_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) | |
{ | |
@@ -8145,6 +8315,992 @@ DEFUN ("system-move-file-to-trash", Fsystem_move_file_to_trash, | |
#endif /* WINDOWSNT */ | |
+ | |
+/*********************************************************************** | |
+ 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 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) | |
+ && EQ (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 hwnd, int openp) | |
+{ | |
+ HIMC himc; | |
+ | |
+ himc = (ImmGetContextProc) (hwnd); | |
+ (ImmSetOpenStatusProc) (himc, openp); | |
+ (ImmReleaseContextProc) (hwnd, himc); | |
+} | |
+ | |
+static int | |
+w32_get_ime_status (HWND hwnd) | |
+{ | |
+ HIMC himc; | |
+ int ret; | |
+ | |
+ himc = (ImmGetContextProc) (hwnd); | |
+ ret = (ImmGetOpenStatusProc) (himc); | |
+ (ImmReleaseContextProc) (hwnd, himc); | |
+ | |
+ return ret; | |
+} | |
+ | |
+static int | |
+w32_set_ime_mode (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) | |
+{ | |
+ HIMC hIMC; | |
+ int size; | |
+ HANDLE himestr; | |
+ | |
+ 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 = XFIXNAT(Fline_beginning_position(Qnil)), pt = PT; | |
+ PT >= bol && PT > point - max_char; ) { | |
+ pt = PT; | |
+ if (NILP(Fforward_word (make_fixnum (-1)))) | |
+ break; | |
+ } | |
+ Fgoto_char (make_fixnum(point)); | |
+ return pt; | |
+} | |
+ | |
+static EMACS_INT compstr_end_pos(int max_char) | |
+{ | |
+ EMACS_INT eol, point = PT, pt; | |
+ | |
+ for (eol = XFIXNAT(Fline_end_position(Qnil)), pt = PT; | |
+ PT <= eol && PT < point + max_char;) { | |
+ pt = PT; | |
+ if (NILP(Fforward_word (make_fixnum (1)))) | |
+ break; | |
+ } | |
+ Fgoto_char (make_fixnum(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 = t_end = 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_fixnum (t_end)); | |
+ while (!NILP (Fbolp ()) && t_start < PT) | |
+ Fforward_char (make_fixnum (-1)); | |
+ if (t_start >= PT) | |
+ return 0; | |
+ t_end = PT; | |
+ } | |
+ else | |
+ { | |
+ if (NILP (Feobp ())) | |
+ Fforward_char (make_fixnum (1)); | |
+ if (!NILP (Fforward_word (make_fixnum (-1)))) | |
+ t_start = PT; | |
+ else | |
+ { | |
+ SET_PT_BOTH (pt, pt_byte); | |
+ return 0; | |
+ } | |
+ Fforward_word (make_fixnum (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_fixnum (t_start)); | |
+ start = compstr_beginning_pos (RECONV_LENG); | |
+ Fgoto_char (make_fixnum (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; | |
+ | |
+ 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 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_fixnum(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_fixnum(0), Qnil, | |
+ temp = Fchar_to_string(make_fixnum(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, SSDATA(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(SSDATA(name), SSDATA(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) | |
+{ | |
+ 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) | |
+{ | |
+ 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); | |
+ FALLTHROUGH; | |
+ 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)) | |
+ { | |
+ 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)) | |
+ { | |
+ 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; | |
+ 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); | |
+ regword.lpReading = SSDATA (encoded_reading); | |
+ | |
+ encoded_word = Fencode_coding_string (word, | |
+ Vlocale_coding_system, | |
+ Qnil, Qnil); | |
+ regword.lpWord = SSDATA (encoded_word); | |
+ (ImmConfigureIMEProc) (hkl, FRAME_W32_WINDOW (SELECTED_FRAME ()), | |
+ IME_CONFIG_REGISTERWORD, ®word); | |
+ } | |
+ 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 | |
@@ -10357,6 +11513,10 @@ syms_of_w32fns (void) | |
PDUMPER_IGNORE (w32_visible_system_caret_hwnd); | |
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"); | |
@@ -10694,6 +11854,27 @@ syms_of_w32fns (void) | |
doc: /* Non-nil means don't display the abort dialog when aborting. */); | |
w32_disable_abort_dialog = 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); | |
@@ -10747,6 +11928,18 @@ syms_of_w32fns (void) | |
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 (&Sw32_read_registry); | |
defsubr (&Sfile_system_info); | |
@@ -11024,6 +12217,7 @@ globals_of_w32fns (void) | |
get_title_bar_info_fn = (GetTitleBarInfo_Proc) | |
get_proc_addr (user32_lib, "GetTitleBarInfo"); | |
+#ifndef USE_W32_IME | |
{ | |
HMODULE imm32_lib = GetModuleHandle ("imm32.dll"); | |
get_composition_string_fn = (ImmGetCompositionString_Proc) | |
@@ -11035,6 +12229,7 @@ globals_of_w32fns (void) | |
set_ime_composition_window_fn = (ImmSetCompositionWindow_Proc) | |
get_proc_addr (imm32_lib, "ImmSetCompositionWindow"); | |
} | |
+#endif /* !USE_W32_IME */ | |
HMODULE hm_kernel32 = GetModuleHandle ("kernel32.dll"); | |
is_debugger_present = (IsDebuggerPresent_Proc) | |
diff --git a/src/w32font.c b/src/w32font.c | |
index c1d5f25..2853a46 100644 | |
--- a/src/w32font.c | |
+++ b/src/w32font.c | |
@@ -55,7 +55,9 @@ #define VIETNAMESE_CHARSET 163 | |
#define JOHAB_CHARSET 130 | |
#endif | |
+#ifndef USE_W32_IME | |
static void fill_in_logfont (struct frame *, LOGFONT *, Lisp_Object); | |
+#endif | |
static BYTE w32_antialias_type (Lisp_Object); | |
static Lisp_Object lispy_antialias_type (BYTE); | |
@@ -2011,7 +2013,10 @@ w32_to_fc_weight (int n) | |
} | |
/* 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; | |
diff --git a/src/w32font.h b/src/w32font.h | |
index a76f8c3..ec91c65 100644 | |
--- a/src/w32font.h | |
+++ b/src/w32font.h | |
@@ -83,6 +83,9 @@ #define CACHE_BLOCKSIZE 128 | |
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 globals_of_w32font (void); | |
diff --git a/src/w32term.c b/src/w32term.c | |
index 76cf6bd..9a2be97 100644 | |
--- a/src/w32term.c | |
+++ b/src/w32term.c | |
@@ -5676,6 +5676,79 @@ w32_read_socket (struct terminal *terminal, | |
break; | |
#endif | |
+#ifdef USE_W32_IME | |
+ case WM_MULE_IME_STATUS: | |
+ f = w32_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) | |
+ { | |
+ 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_fixnum (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) | |
@@ -6042,7 +6115,12 @@ w32_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, | |
+ 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)->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. */ | |
@@ -7559,6 +7637,9 @@ #define LOAD_PROC(lib, fn) pfn##fn = (void *) GetProcAddress (lib, #fn) | |
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 | |
diff --git a/src/w32term.h b/src/w32term.h | |
index f8a8a72..1faeadf 100644 | |
--- a/src/w32term.h | |
+++ b/src/w32term.h | |
@@ -634,6 +634,8 @@ #define WM_MOUSEHWHEEL (WM_MOUSEWHEEL + 4) | |
#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 | |
@@ -672,6 +674,96 @@ #define WM_EMACS_INPUT_READY (WM_EMACS_START + 24) | |
#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) | |
@@ -888,3 +980,8 @@ #define GUI_SDATA(x) ((guichar_t*) SDATA (x)) | |
#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 */ | |
diff --git a/src/window.c b/src/window.c | |
index ff17cd8..58239e3 100644 | |
--- a/src/window.c | |
+++ b/src/window.c | |
@@ -507,6 +507,10 @@ DEFUN ("old-selected-window", Fold_selected_window, | |
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 | |
@@ -518,6 +522,9 @@ select_window (Lisp_Object window, Lisp_Object norecord, | |
{ | |
struct window *w; | |
struct frame *sf; | |
+#ifdef USE_W32_IME | |
+ Lisp_Object oldwin = selected_window; | |
+#endif /* USE_W32_IME */ | |
CHECK_LIVE_WINDOW (window); | |
@@ -571,6 +578,11 @@ select_window (Lisp_Object window, Lisp_Object norecord, | |
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; | |
} | |
@@ -4115,6 +4127,12 @@ buffer (that is `window-dedicated-p' returns t for WINDOW) and does not | |
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; | |
} | |
@@ -8157,6 +8175,10 @@ syms_of_window (void) | |
DEFSYM (Qwindow_size_change_functions, "window-size-change-functions"); | |
DEFSYM (Qwindow_buffer_change_functions, "window-buffer-change-functions"); | |
DEFSYM (Qwindow_selection_change_functions, "window-selection-change-functions"); | |
+#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"); | |
@@ -8248,6 +8270,17 @@ syms_of_window (void) | |
as argument. */); | |
Vwindow_buffer_change_functions = 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 ("window-size-change-functions", Vwindow_size_change_functions, | |
doc: /* Functions called during redisplay when window sizes have changed. | |
The value should be a list of functions that take one argument. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment