NTEmacs IMEパッチ作成(24.4)
IMEパッチ
これまで gnupack のものを使用してきたが、最新がリリースされていないので、24.3ベースでパッチを作成してみる。 まずは gnupack の 概要 又は ダウンロードファイル一覧 から24.3のものを入手する。 現時点での最新は emacs-24.3-ime-2013-05-03.patch.tar.gz であった。
まずは24.4のソースにパッチをあててみる
rockers:‾/svn/emacs-24.4$ patch -b -p1 < emacs-24.3-ime-2013-05-03.patch
NGのところをそれぞれ対応する。 24.3のパッチ適用済ツリーと比較して作業。
★具体的には
- TotoiseSVNで、24.3のパッチ適用済ツリーの「変更をチェック」と24.4の(24.3用)パッチ適用済ツリーの「変更をチェック」を両方出す
- rejファイルから、失敗した部分の内容を確認し、24.3のdiffを元に対象箇所を特定
- 24.4の対象箇所を探し、ケースバイケースで手動マージを行う
作業内容
OK
patching file lib-src/hexl.c Hunk #1 succeeded at 158 (offset -4 lines). Hunk #2 succeeded at 216 (offset -4 lines).
OK
patching file lib-src/make-docfile.c
OK
patching file lib-src/makefile.w32-in Hunk #1 succeeded at 144 (offset 4 lines). Hunk #2 succeeded at 161 (offset 4 lines).
Hunk#1 は元ソースで対応と同じ(#ifndef _TIMEZONE_DEFINED) Hunk#2 は手動マージ
patching file lib-src/ntlib.c Reversed (or previously applied) patch detected! Assume -R? [n] Apply anyway? [n] Skipping patch. 2 out of 2 hunks ignored -- saving rejects to file lib-src/ntlib.c.rej
OK
patching file lib-src/ntlib.h Hunk #1 succeeded at 25 with fuzz 1.
OK
patching file lisp/cedet/cedet-cscope.el
OK
patching file lisp/image.el Hunk #1 succeeded at 126 (offset 15 lines).
OK(ファイル追加)
patching file lisp/international/w32-ime.el
OK
patching file lisp/loadup.el Hunk #1 succeeded at 253 (offset 4 lines).
OK(ファイル追加)
patching file lisp/site/site-init.el
OK(ファイル追加)
patching file lisp/site/site-start.el
Hunk#1はOK Hunk#2は手動マージ
patching file lisp/startup.el Hunk #1 succeeded at 594 with fuzz 2 (offset 77 lines). Hunk #2 FAILED at 1519. 1 out of 2 hunks FAILED -- saving rejects to file lisp/startup.el.rej
Hunk#1はよーく見ると元ソースで対応済みなのでマージ不要
patching file nt/addpm.c Reversed (or previously applied) patch detected! Assume -R? [n] Apply anyway? [n] Skipping patch. 1 out of 1 hunk ignored -- saving rejects to file nt/addpm.c.rej
Hunk#1は元ソースで対応済みなのでマージ不要
patching file nt/addsection.c Reversed (or previously applied) patch detected! Assume -R? [n] Apply anyway? [n] Skipping patch. 1 out of 1 hunk ignored -- saving rejects to file nt/addsection.c.rej
OK (#undef HAVE_STRUCT_UTIMBUF を #define HAVE_STRUCT_UTIMBUF 1 としており、実際にはコンフィギュレーション変更である)
patching file nt/config.nt Hunk #1 succeeded at 1023 (offset 120 lines).
24.3のパッチ適用済ファイルの方は、改行コードがUnixになっていたため、Winに戻してdiffをとる
24.3->24.4で追加されたIMPORTANTの記載が若干気になるが、、
patching file nt/configure.bat Hunk #1 FAILED at 1. 1 out of 1 hunk FAILED -- saving rejects to file nt/configure.bat.rej
OK
patching file nt/gmake.defs Hunk #1 succeeded at 169 (offset 8 lines). Hunk #2 succeeded at 219 (offset 8 lines). Hunk #3 succeeded at 328 (offset 8 lines).
順次比較して作業。多分、合っていると思う。。
patching file nt/inc/ms-w32.h Hunk #1 FAILED at 115. Hunk #2 succeeded at 180 with fuzz 2 (offset 47 lines). Hunk #3 FAILED at 274. Hunk #4 succeeded at 392 with fuzz 1 (offset 75 lines). Hunk #5 FAILED at 366. Hunk #6 succeeded at 507 (offset 91 lines). 3 out of 6 hunks FAILED -- saving rejects to file nt/inc/ms-w32.h.rej
OK
patching file nt/inc/sys/socket.h Hunk #1 succeeded at 99 (offset 4 lines).
元々のパッチは、プロトタイプ宣言先頭の _CRTIMP を削除するという内容。 24.4では元々無くなっているので対応不要。
patching file nt/inc/sys/stat.h Hunk #1 FAILED at 101. 1 out of 1 hunk FAILED -- saving rejects to file nt/inc/sys/stat.h.rej
元々のパッチは _W64 と _TIMEZONE_DEFINED による切り分けを追加。 24.4では _TIMEVAL_DEFINED と _TIMEZONE_DEFINED により切り分けられているので対応不要。
patching file nt/inc/sys/time.h Hunk #1 FAILED at 6. 1 out of 1 hunk FAILED -- saving rejects to file nt/inc/sys/time.h.rej
元々のパッチは #ifdef GNUC の切り分けを #if defined(GNUC) && !defined(_W64) に変更していたもの 24.4では元々対応済みなので不要。
patching file nt/preprep.c Reversed (or previously applied) patch detected! Assume -R? [n] Apply anyway? [n] Skipping patch. 1 out of 1 hunk ignored -- saving rejects to file nt/preprep.c.rej
OK(ファイル追加)
patching file site-lisp/cmigemo.el
OK(ファイル追加)
patching file site-lisp/cp5022x.el
OK(ファイル追加)
patching file site-lisp/ezsetup.el
OK(ファイル追加)
patching file site-lisp/ja-coding.el
OK(ファイル追加)
patching file site-lisp/smart-ime.el
Hunk #5の #ifdef USE_W32_CALL_LISP_THREAD のところを手動マージ
patching file src/alloc.c Hunk #1 succeeded at 22 with fuzz 1 (offset -2 lines). Hunk #2 succeeded at 35 (offset -2 lines). Hunk #3 succeeded at 346 (offset 16 lines). Hunk #4 succeeded at 3770 with fuzz 1 (offset 3318 lines). Hunk #5 FAILED at 663. Hunk #6 succeeded at 3774 (offset 278 lines). Hunk #7 succeeded at 5341 (offset 304 lines). Hunk #8 succeeded at 5631 (offset 411 lines). Hunk #9 succeeded at 5652 with fuzz 1 (offset 408 lines). Hunk #10 succeeded at 5663 (offset 408 lines). Hunk #11 succeeded at 5722 with fuzz 2 (offset 376 lines). 1 out of 11 hunks FAILED -- saving rejects to file src/alloc.c.rej
OK
patching file src/atimer.c
Hunk #2の FAILは周囲のdiffが異なっていたため。手動マージ
patching file src/callproc.c Hunk #1 succeeded at 30 with fuzz 1 (offset 1 line). Hunk #2 FAILED at 1167. Hunk #3 succeeded at 1241 (offset 67 lines). 1 out of 3 hunks FAILED -- saving rejects to file src/callproc.c.rej
OK
patching file src/cm.h
OK(ファイル追加)
patching file src/cmigemo.c
Hunk #2 file_name_completion_stat() のところは、元ソースが大きく変わっており、処理する対象が無さそう
patching file src/dired.c Hunk #1 succeeded at 51 with fuzz 2 (offset -29 lines). Hunk #2 FAILED at 831. 1 out of 2 hunks FAILED -- saving rejects to file src/dired.c.rej
OK
patching file src/dispnew.c Hunk #1 succeeded at 6119 (offset -122 lines).
OK
patching file src/doprnt.c
OK
patching file src/emacs.c Hunk #1 succeeded at 770 with fuzz 2 (offset 58 lines). Hunk #2 succeeded at 1534 (offset 106 lines).
frame.c HUNK #1
24.3
#if !HAVE_NS
24.4
#if !HAVE_NS && !HAVE_NTGUI
変更後
#if !HAVE_NS && !HAVE_NTGUI && !defined USE_W32_IME
patching file src/frame.c Hunk #1 FAILED at 1959. Hunk #2 succeeded at 2744 (offset 49 lines). 1 out of 2 hunks FAILED -- saving rejects to file src/frame.c.rej
OK
patching file src/frame.h Hunk #1 succeeded at 1217 (offset 58 lines).
OK
patching file src/gmalloc.c
image.c
Hunk #5
_setjmp だか __setjmp だかの定義の問題らしい。 解決されているっぽく見えるのでとりあえず置いておく
Hunk #6 も #5同様
Hunk #10 は解決されてそう。DEF_IMGLIB_FN の引数の型かな
patching file src/image.c Hunk #1 succeeded at 536 (offset -5 lines). Hunk #2 succeeded at 548 (offset -5 lines). Hunk #3 succeeded at 622 (offset -6 lines). Hunk #4 succeeded at 3197 (offset 135 lines). Hunk #5 FAILED at 5563. Hunk #6 FAILED at 5760. Hunk #7 succeeded at 6587 (offset 147 lines). Hunk #8 succeeded at 6668 (offset 142 lines). Hunk #9 succeeded at 8657 (offset 550 lines). Hunk #10 FAILED at 8275. Hunk #11 succeeded at 8871 (offset 559 lines). Hunk #12 succeeded at 8899 (offset 561 lines). Hunk #13 succeeded at 8970 (offset 563 lines). Hunk #14 succeeded at 9038 with fuzz 2 (offset 563 lines). Hunk #15 succeeded at 9052 (offset 566 lines). Hunk #16 succeeded at 9638 (offset 564 lines). Hunk #17 succeeded at 9685 (offset 584 lines). 3 out of 17 hunks FAILED -- saving rejects to file src/image.c.rej
Hunk #1 なんでFAILかわからないが行追加だけなので同様に行う
patching file src/keyboard.c Hunk #1 FAILED at 72. Hunk #2 succeeded at 4778 (offset 127 lines). Hunk #3 succeeded at 8854 with fuzz 1 (offset -46 lines). Hunk #4 succeeded at 8976 (offset -95 lines). Hunk #5 succeeded at 9061 (offset -147 lines). Hunk #6 succeeded at 9734 (offset -258 lines). 1 out of 6 hunks FAILED -- saving rejects to file src/keyboard.c.rej
Hunk #3 かなりソースが変わっているので適用部分無し。そのまま
patching file src/lisp.h Hunk #1 succeeded at 286 with fuzz 1 (offset 84 lines). Hunk #2 succeeded at 628 with fuzz 2 (offset 223 lines). Hunk #3 FAILED at 1752. Hunk #4 succeeded at 3670 (offset 737 lines). 1 out of 4 hunks FAILED -- saving rejects to file src/lisp.h.rej
Hunk #1 また、cmigemo だが、、入れておく
patching file src/makefile.w32-in Hunk #1 FAILED at 134. Hunk #2 succeeded at 153 (offset 1 line). Hunk #3 succeeded at 225 (offset 1 line). Hunk #4 succeeded at 1720 with fuzz 1 (offset 29 lines). 1 out of 4 hunks FAILED -- saving rejects to file src/makefile.w32-in.rej
OK
patching file src/print.c Hunk #1 succeeded at 1950 (offset 12 lines).
SIZE_T の定義等。 解決されてそうな感じなので一旦そのまま
patching file src/ralloc.c Hunk #1 FAILED at 52. Hunk #2 FAILED at 170. Hunk #3 FAILED at 224. Hunk #4 FAILED at 254. Hunk #5 FAILED at 392. Hunk #6 FAILED at 472. Hunk #7 FAILED at 568. Hunk #8 FAILED at 774. Hunk #9 FAILED at 855. Hunk #10 FAILED at 906. Hunk #11 FAILED at 963. Hunk #12 FAILED at 1088. 12 out of 12 hunks FAILED -- saving rejects to file src/ralloc.c.rej
OK
patching file src/regex.c Hunk #1 succeeded at 364 (offset -4 lines).
OK
patching file src/sound.c Hunk #1 succeeded at 1243 (offset -45 lines). Hunk #2 succeeded at 1283 (offset -45 lines).
OK
patching file src/term.c Hunk #1 succeeded at 62 with fuzz 2 (offset -1 lines).
OK
patching file src/unexw32.c Hunk #1 succeeded at 216 (offset 1 line). Hunk #2 succeeded at 482 (offset 1 line). Hunk #3 succeeded at 498 (offset 1 line). Hunk #4 succeeded at 513 (offset 1 line).
OK
patching file src/vm-limit.c Hunk #1 succeeded at 51 with fuzz 2 (offset 30 lines).
w32.c Hunk #1 FAILED at 29. time.hのinclude順。解決されてそうなので一旦そのまま
Hunk #2 FAILED at 65. epaths.h のinclude。解決済
Hunk #3 FAILED at 96. __GNUC__ と _W64の絡み。解決済
Hunk #4 FAILED at 114. if _WIN32_WINNT < 0x500 及び endif の追加。元ソースで解決済
Hunk #5 FAILED at 162. ifndef FSCTL_GET_REPARSE_POINT、元ソースで解決済
Hunk #10 FAILED at 2014. get_emacs_configuration 関数が無くなっているので関係無し
Hunk #13 FAILED at 2499. nameをポインタとしてみるか、name[1]で見るか。解決済のようだ
Hunk #15 FAILED at 3371. generate_inode_val()が無くなっているので関係なし
Hunk #21 FAILED at 6820. TEXT()の追加のみ
patching file src/w32.c Hunk #1 FAILED at 29. Hunk #2 FAILED at 65. Hunk #3 FAILED at 96. Hunk #4 FAILED at 114. Hunk #5 FAILED at 162. Hunk #6 succeeded at 332 with fuzz 2 (offset 49 lines). Hunk #7 succeeded at 2030 (offset 781 lines). Hunk #8 succeeded at 2530 (offset 845 lines). Hunk #9 succeeded at 2810 with fuzz 2 (offset 888 lines). Hunk #10 FAILED at 2014. Hunk #11 succeeded at 3219 (offset 767 lines). Hunk #12 succeeded at 3238 (offset 767 lines). Hunk #13 FAILED at 2499. Hunk #14 succeeded at 3296 with fuzz 1 (offset 767 lines). Hunk #15 FAILED at 3371. Hunk #16 succeeded at 6823 (offset 1600 lines). Hunk #17 succeeded at 7260 (offset 1605 lines). Hunk #18 succeeded at 8055 (offset 1661 lines). Hunk #19 succeeded at 8129 (offset 1661 lines). Hunk #20 succeeded at 8312 (offset 1660 lines). Hunk #21 FAILED at 6820. Hunk #22 succeeded at 8852 (offset 1997 lines). Hunk #23 succeeded at 8876 (offset 1997 lines). Hunk #24 succeeded at 8971 (offset 1997 lines). 9 out of 24 hunks FAILED -- saving rejects to file src/w32.c.rej
OK
patching file src/w32.h Hunk #2 succeeded at 227 with fuzz 2 (offset 38 lines).
OK
patching file src/w32common.h
w32fns.c かなり重そうだ。。
Hunk #6 FAILED at 233.
ここはかなり重要な部分と思われ。 ImmGetCompositionString_Proc とかの定義を ifndef USE_W32_IME する
@@ -233,21 +316,25 @@ 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 HWND (WINAPI * ImmReleaseContext_Proc) (IN HWND wnd, IN HIMC context); typedef HWND (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); 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;
Hunk #9 FAILED at 328.
check_x_display_info関数の前に、cons2ptr(),ptr2cons()を追加
@@ -328,6 +422,22 @@
#define MB_EMACS_SILENT (0xFFFFFFFF - 1)
+#ifdef USE_W32_CALL_LISP_THREAD
+static void *cons2ptr(Lisp_Object c)
+{
+ return (void *) (XFASTINT(XCAR(c)) << sizeof(EMACS_INT) /2 * 8 |
+ XFASTINT(XCDR(c)) & ((EMACS_INT)1 <<
+ sizeof(EMACS_INT) /2 * 8) - 1);
+}
+
+static Lisp_Object ptr2cons(const void *p)
+{
+ return Fcons(make_number((EMACS_INT)p >> sizeof(EMACS_UINT)/2*8),
+ make_number((EMACS_INT)p &
+ ((EMACS_INT)1 << sizeof(EMACS_UINT)/2*8)-1));
+}
+#endif
+
/* Error if we are not connected to MS-Windows. */
void
check_w32 (void)
Hunk #20 FAILED at 4100.
ここも重要なとこですなあ。
WM_IME_NOTIFY を処理するところ。
@@ -4100,8 +4283,83 @@
return retval;
}
+#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)
+ {
+#if !defined(USE_W32_CALL_LISP_THREAD)
+ my_post_msg (&wmsg, hwnd, WM_MULE_IME_SET_FONT, (WPARAM) f, 0);
+#else /* USE_W32_CALL_LISP_THREAD */
+ w32_set_ime_font(hwnd, f);
+#endif
+ set_ime_font = 1;
+ }
+ }
+ 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;
+
+ case WM_IME_REQUEST:
+ if (wParam == IMR_RECONVERTSTRING) {
+#ifdef RECONVERSION
+ if (!ime_enable_reconversion || !w32_get_ime_status(hwnd))
+ return 0;
+ if (lParam)
+ return w32_get_ime_reconversion_string (hwnd, wParam,
+ (RECONVERTSTRING*) lParam);
+ else
+ return sizeof(RECONVERTSTRING) + (RECONV_LENG * 2 + 1) * CHRSZ;
+#endif
+ } else if (wParam == IMR_DOCUMENTFEED) {
+#ifdef DOCUMENTFEED
+ if (!ime_enable_document_feed)
+ return 0;
+ if (lParam)
+ return w32_get_ime_documentfeed_string (hwnd, wParam,
+ (RECONVERTSTRING*) lParam);
+ else
+ return sizeof(RECONVERTSTRING) + (DOCFEED_LENG * 2 + DOCFEED_CSTR_LENG + 1) * CHRSZ;
+#endif
+ }
+ goto dflt;
+#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)
{
Hunk #26 FAILED at 6408.
要るのか?(LPOFNHOOKPROC)のキャスト
@@ -6408,7 +6684,7 @@
/* Prevent redisplay. */
specbind (Qinhibit_redisplay, Qt);
block_input ();
- file_details->lpfnHook = file_dialog_callback;
+ file_details->lpfnHook = (LPOFNHOOKPROC) file_dialog_callback;
#ifdef NTGUI_UNICODE
file_opened = GetOpenFileNameW (file_details);
Hunk #28 FAILED at 6589.
なるほど、ここも肝の部分だ。 「w32 specialized functions」の括りの前に、「Input Method Editor」の括り(USE_W32_IME〜endif)を挿入している。 diffが変に出ちゃっているのでわかりにくい。 どうせなら、ファイル分ければいいのに、、
@@ -6589,157 +6926,1614 @@
/***********************************************************************
- w32 specialized functions
+ Input Method Editor
***********************************************************************/
+#ifdef USE_W32_IME
+BOOL fIME = FALSE;
-DEFUN ("w32-send-sys-command", Fw32_send_sys_command,
- Sw32_send_sys_command, 1, 2, 0,
- doc: /* Send frame a Windows WM_SYSCOMMAND message of type COMMAND.
-Some useful values for COMMAND are #xf030 to maximize frame (#xf020
-to minimize), #xf120 to restore frame to original size, and #xf100
-to activate the menubar for keyboard access. #xf140 activates the
-screen saver if defined.
+typedef BOOL (WINAPI *IMMGETOPENSTATUSPROC)(HIMC);
+IMMGETOPENSTATUSPROC ImmGetOpenStatusProc;
-If optional parameter FRAME is not specified, use selected frame. */)
- (Lisp_Object command, Lisp_Object frame)
-{
- FRAME_PTR f = check_x_frame (frame);
+typedef BOOL (WINAPI *IMMSETOPENSTATUSPROC)(HIMC, BOOL);
+IMMSETOPENSTATUSPROC ImmSetOpenStatusProc;
- CHECK_NUMBER (command);
+typedef BOOL (WINAPI *IMMSETCOMPOSITIONWINDOWPROC)(HIMC, LPCOMPOSITIONFORM);
+IMMSETCOMPOSITIONWINDOWPROC ImmSetCompositionWindowProc;
- PostMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, XINT (command), 0);
+typedef LONG (WINAPI *IMMGETCOMPOSITIONSTRINGPROC)
+ (HIMC, DWORD, LPVOID, DWORD);
+IMMGETCOMPOSITIONSTRINGPROC ImmGetCompositionStringProc;
- return Qnil;
-}
+typedef LONG (WINAPI *IMMSETCOMPOSITIONSTRINGPROC)
+ (HIMC, DWORD, LPCVOID, DWORD, LPCVOID, DWORD);
+IMMSETCOMPOSITIONSTRINGPROC ImmSetCompositionStringProc;
-DEFUN ("w32-shell-execute", Fw32_shell_execute, Sw32_shell_execute, 2, 4, 0,
- doc: /* Get Windows to perform OPERATION on DOCUMENT.
-This is a wrapper around the ShellExecute system function, which
-invokes the application registered to handle OPERATION for DOCUMENT.
+typedef BOOL (WINAPI *IMMSETCOMPOSITIONFONTPROC) (HIMC, LPLOGFONTA);
+IMMSETCOMPOSITIONFONTPROC ImmSetCompositionFontProc;
-OPERATION is either nil or a string that names a supported operation.
-What operations can be used depends on the particular DOCUMENT and its
-handler application, but typically it is one of the following common
-operations:
+typedef HIMC (WINAPI *IMMGETCONTEXTPROC)(HWND);
+IMMGETCONTEXTPROC ImmGetContextProc;
- ¥"open¥" - open DOCUMENT, which could be a file, a directory, or an
- executable program. If it is an application, that
- application is launched in the current buffer's default
- directory. Otherwise, the application associated with
- DOCUMENT is launched in the buffer's default directory.
- ¥"print¥" - print DOCUMENT, which must be a file
- ¥"explore¥" - start the Windows Explorer on DOCUMENT
- ¥"edit¥" - launch an editor and open DOCUMENT for editing; which
- editor is launched depends on the association for the
- specified DOCUMENT
- ¥"find¥" - initiate search starting from DOCUMENT which must specify
- a directory
- nil - invoke the default OPERATION, or ¥"open¥" if default is
- not defined or unavailable
+typedef BOOL (WINAPI *IMMGETCONVERSIONSTATUSPROC)(HIMC, LPDWORD, LPDWORD);
+IMMGETCONVERSIONSTATUSPROC ImmGetConversionStatusProc;
-DOCUMENT is typically the name of a document file or a URL, but can
-also be a program executable to run, or a directory to open in the
-Windows Explorer.
+typedef BOOL (WINAPI *IMMSETCONVERSIONSTATUSPROC)(HIMC, DWORD, DWORD);
+IMMSETCONVERSIONSTATUSPROC ImmSetConversionStatusProc;
-If DOCUMENT is a program executable, the optional third arg PARAMETERS
-can be a string containing command line parameters that will be passed
-to the program; otherwise, PARAMETERS should be nil or unspecified.
+typedef BOOL (WINAPI *IMMGETCONVERSIONLISTPROC)
+ (HKL, HIMC, LPCTSTR, LPCANDIDATELIST, DWORD, UINT);
+IMMGETCONVERSIONLISTPROC ImmGetConversionListProc;
-Optional fourth argument SHOW-FLAG can be used to control how the
-application will be displayed when it is invoked. If SHOW-FLAG is nil
-or unspecified, the application is displayed normally, otherwise it is
-an integer representing a ShowWindow flag:
+typedef BOOL (WINAPI *IMMCONFIGUREIMEPROC)(HKL, HWND, DWORD, LPVOID);
+IMMCONFIGUREIMEPROC ImmConfigureIMEProc;
- 0 - start hidden
- 1 - start normally
- 3 - start maximized
- 6 - start minimized */)
- (Lisp_Object operation, Lisp_Object document, Lisp_Object parameters, Lisp_Object show_flag)
-{
- Lisp_Object current_dir;
- char *errstr;
+typedef BOOL (WINAPI *IMMNOTIFYIMEPROC)(HIMC, DWORD, DWORD, DWORD);
+IMMNOTIFYIMEPROC ImmNotifyIMEProc;
- CHECK_STRING (document);
+typedef BOOL (WINAPI *IMMRELEASECONTEXTPROC)(HWND, HIMC);
+IMMRELEASECONTEXTPROC ImmReleaseContextProc;
- /* Encode filename, current directory and parameters. */
- current_dir = ENCODE_FILE (BVAR (current_buffer, directory));
- document = ENCODE_FILE (document);
- if (STRINGP (parameters))
- parameters = ENCODE_SYSTEM (parameters);
+typedef HIMC (WINAPI *IMMCREATECONTEXTPROC)(void);
+IMMCREATECONTEXTPROC ImmCreateContextProc;
- if ((int) ShellExecute (NULL,
- (STRINGP (operation) ?
- SDATA (operation) : NULL),
- SDATA (document),
- (STRINGP (parameters) ?
- SDATA (parameters) : NULL),
- SDATA (current_dir),
- (INTEGERP (show_flag) ?
- XINT (show_flag) : SW_SHOWDEFAULT))
- > 32)
- return Qt;
- errstr = w32_strerror (0);
- /* The error string might be encoded in the locale's encoding. */
- if (!NILP (Vlocale_coding_system))
- {
- Lisp_Object decoded =
- code_convert_string_norecord (build_unibyte_string (errstr),
- Vlocale_coding_system, 0);
- errstr = SSDATA (decoded);
+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);
}
- error ("ShellExecute failed: %s", errstr);
}
-/* Lookup virtual keycode from string representing the name of a
- non-ascii keystroke into the corresponding virtual key, using
- lispy_function_keys. */
+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
-lookup_vk_code (char *key)
+w32_get_ime_status (hwnd)
+ HWND hwnd;
{
- int i;
+ HIMC himc;
+ int ret;
- for (i = 0; i < 256; i++)
- if (lispy_function_keys[i]
- && strcmp (lispy_function_keys[i], key) == 0)
- return i;
+ himc = (ImmGetContextProc) (hwnd);
+ ret = (ImmGetOpenStatusProc) (himc);
+ (ImmReleaseContextProc) (hwnd, himc);
- return -1;
+ return ret;
}
-/* Convert a one-element vector style key sequence to a hot key
- definition. */
-static Lisp_Object
-w32_parse_hot_key (Lisp_Object key)
+static int
+w32_set_ime_mode (hwnd, mode, mask)
+ HWND hwnd;
+ int mode;
+ int mask;
{
- /* Copied from Fdefine_key and store_in_keymap. */
- register Lisp_Object c;
- int vk_code;
- int lisp_modifiers;
- int w32_modifiers;
- struct gcpro gcpro1;
+ HIMC himc;
+ DWORD cmode, smode;
- CHECK_VECTOR (key);
+ himc = (ImmGetContextProc) (hwnd);
+ if (!(ImmGetConversionStatusProc) (himc, &cmode, &smode))
+ return 0;
- if (XFASTINT (Flength (key)) != 1)
- return Qnil;
+ cmode = (cmode & (‾mask)) | (mode & mask);
- GCPRO1 (key);
+ (ImmSetConversionStatusProc) (himc, cmode, smode);
+ (ImmReleaseContextProc) (hwnd, himc);
- c = Faref (key, make_number (0));
+ return 1;
+}
- if (CONSP (c) && lucid_event_type_list_p (c))
- c = Fevent_convert_list (c);
+static BOOL
+w32_get_ime_composition_string (hwnd)
+ HWND hwnd;
+{
+ HIMC hIMC;
+ int size;
+ HANDLE himestr;
+#ifdef IME_UNICODE
+ LPWSTR lpstr;
+#else
+ LPSTR lpstr;
+#endif
- UNGCPRO;
+ struct frame *f;
- if (! INTEGERP (c) && ! SYMBOLP (c))
- error ("Key definition is invalid");
+ hIMC = (ImmGetContextProc) (hwnd);
+ if (!hIMC)
+ return FALSE;
+
+ size = (ImmGetCompositionStringProc) (hIMC, GCS_RESULTSTR, NULL, 0);
+#ifdef IME_UNICODE
+ size += sizeof (WCHAR);
+#else
+ size += sizeof (CHAR);
+#endif
+ himestr = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, size);
+ if (!himestr)
+ abort ();
- /* Work out the base key and the modifiers. */
- if (SYMBOLP (c))
- {
- c = parse_modifiers (c);
- lisp_modifiers = XINT (Fcar (Fcdr (c)));
+ (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
+#ifdef USE_W32_CALL_LISP_THREAD
+struct get_reconversion_string_arg {
+ WPARAM wparam;
+ RECONVERTSTRING *reconv; /* in */
+#ifdef IME_UNICODE
+ unsigned short *compstr; /* in */
+#else
+ unsigned char *compstr; /* in */
+#endif
+ DWORD size; /* in,out */
+};
+#endif /* USE_W32_CALL_LISP_THREAD */
+
+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;
+}
+
+#if !defined(USE_W32_CALL_LISP_THREAD)
+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
+ {
+ while (!NILP (Fbolp ()) && NILP (Fbobp ()))
+ Fforward_char (make_number (1));
+ if (!NILP (Fbobp ()))
+ return 0;
+
+ t_end = PT;
+ Fforward_word (make_number (-1));
+ t_start = PT;
+ }
+
+ 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,
+ WPARAM wParam,
+ RECONVERTSTRING *reconv)
+{
+ return get_reconversion_string (hwnd, reconv, NULL);
+}
+#else /* USE_W32_CALL_LISP_THREAD */
+static Lisp_Object
+get_reconversion_string (Lisp_Object arg_)
+{
+ struct get_reconversion_string_arg *arg = cons2ptr(arg_);
+ EMACS_INT pt, pt_byte, point, start, end, len,
+ t_start, t_end, del_start, del_end, compstr_len = 0;
+ Lisp_Object str;
+ struct gcpro gcpro1;
+
+ if (!NILP (BVAR (current_buffer, read_only))) {
+ arg->size = 0;
+ return Qnil;
+ }
+
+ pt = PT;
+ pt_byte = PT_BYTE;
+
+ if (arg->compstr) { /* DOCUMENT_FEED */
+#ifdef DOCUMENTFEED
+ t_start = compstr_beginning_pos(DOCFEED_LENG);
+ t_end = compstr_end_pos(DOCFEED_LENG);
+ point = PT;
+#endif
+ } 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));
+ point = t_end = PT;
+ } else {
+ point = 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 Qnil;
+ t_end = PT;
+ } else {
+ point = PT;
+
+ while (!NILP(Fbolp()) && NILP(Fbobp()))
+ Fforward_char(make_number(1));
+ if (!NILP(Fbobp()))
+ return Qnil;
+
+ t_end = PT;
+ Fforward_word (make_number (-1));
+ t_start = PT;
+ }
+ if (t_start == t_end) {
+ arg->size = 0;
+ return Qnil;
+ }
+
+ if (arg->compstr) {
+ start = t_start;
+ end = t_end;
+ t_start = point - t_start;
+ } else {
+
+ start = compstr_beginning_pos(RECONV_LENG);
+ end = compstr_end_pos(RECONV_LENG);
+
+ del_start = t_start;
+ del_end = t_end;
+
+ t_start -= start;
+ t_end -= start;
+ }
+
+ GCPRO1(str);
+ str = make_buffer_string (start, end, 1);
+
+#ifdef IME_UNICODE
+ len = end - start;
+ if (arg->reconv) {
+ int pos;
+ WCHAR *uc_code, *s;
+
+ uc_code = (WCHAR *) (arg->reconv + 1);
+ s = uc_code;
+
+ for (pos = 0; pos < t_start; pos++)
+ *s++ = (WCHAR) XFASTINT(Faref(str, make_number(pos)));
+
+ if (arg->compstr)
+ for (compstr_len = 0; arg->compstr[compstr_len]; compstr_len++)
+ *s++ = arg->compstr[compstr_len];
+
+ for (; pos < len; pos++)
+ *s++ = (WCHAR) XFASTINT(Faref(str, make_number(pos)));
+
+ *s = 0;
+ } else {
+ if (arg->compstr)
+ for (compstr_len = 0; arg->compstr[compstr_len]; compstr_len++)
+ ;
+ }
+
+#define STROFFSET(s,o) ((o) * CHRSZ)
+#define STRSIZE(s, b, e) ((e) - (b))
+#else /* IME_UNICODE */
+ if (!arg->reconv
+ && !NILP (Ftext_property_any (make_number (0),
+ Flength (str),
+ intern ("read-only"),
+ Qt,
+ str))) {
+ SET_PT_BOTH (pt, pt_byte);
+ UNGCPRO;
+ return Qt; /* Cannot signal here */
+ }
+ str = ENCODE_SYSTEM (str);
+
+ len = SBYTES(str);
+ if (arg->compstr)
+ compstr_len = strlen(arg->compstr);
+
+#define STROFFSET(s,o) (_mbsninc(SDATA(s), (o)) - SDATA(s))
+#define STRSIZE(s, b, e) (_mbsninc(SDATA(s), (e)) - _mbsninc(SDATA(s), (b)))
+
+ if (arg->reconv) {
+ if (arg->compstr) {
+ LPSTR s = (LPSTR)(arg->reconv + 1);
+ strncpy(s, SDATA(str), STROFFSET(str, t_start));
+ strcpy(s + STROFFSET(str, t_start), arg->compstr);
+ strcpy(s + STROFFSET(str, t_start) + compstr_len,
+ SDATA(str) + STROFFSET(str, t_start));
+ } else
+ strcpy ((LPSTR)(arg->reconv + 1), SDATA(str));
+ }
+#endif
+
+ if (arg->reconv) {
+ arg->reconv->dwStrOffset = sizeof (RECONVERTSTRING);
+ arg->reconv->dwStrLen = len + compstr_len;
+
+ if (arg->compstr) {
+ arg->reconv->dwCompStrOffset =
+ arg->reconv->dwTargetStrOffset = STROFFSET(str, t_start);
+ arg->reconv->dwCompStrLen =
+ arg->reconv->dwTargetStrLen = compstr_len;
+
+ } else {
+ arg->reconv->dwTargetStrOffset =
+ arg->reconv->dwCompStrOffset = STROFFSET(str, t_start);
+ arg->reconv->dwTargetStrLen =
+ arg->reconv->dwCompStrLen = STRSIZE(str, t_start, t_end);
+
+ del_range(del_start, del_end);
+ Fgoto_char (make_number(del_start));
+ }
+ } else {
+ SET_PT_BOTH (pt, pt_byte);
+ }
+ arg->size = sizeof(RECONVERTSTRING) + (len + compstr_len + 1) * CHRSZ;
+ if (arg->reconv != NULL && arg->compstr != NULL)
+ arg->compstr[0] = 0;
+
+ UNGCPRO;
+ return Qt;
+}
+
+static LRESULT
+w32_get_ime_reconversion_string(HWND hwnd,
+ WPARAM wParam,
+ RECONVERTSTRING *reconv)
+{
+ struct get_reconversion_string_arg grs =
+ {IMR_RECONVERTSTRING, reconv, NULL, 0};
+
+ if (NILP(w32_call_lisp_thread(get_reconversion_string, &grs)))
+ return 0;
+ return reconv->dwSize;
+}
+#endif /* USE_W32_CALL_LISP_THREAD */
+#endif /* RECONVERSION */
+
+#if defined(DOCUMENTFEED)
+#if !defined(USE_W32_CALL_LISP_THREAD)
+static LRESULT
+w32_get_ime_documentfeed_string (HWND hwnd,
+ WPARAM wParam,
+ 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;
+}
+#else /* USE_W32_CALL_LISP_THREAD */
+static LRESULT
+w32_get_ime_documentfeed_string(HWND hwnd,
+ WPARAM wParam,
+ RECONVERTSTRING *reconv)
+{
+#ifdef IME_UNICODE
+ unsigned short ime_compstr[DOCFEED_CSTR_LENG];
+#else
+ unsigned char ime_compstr[DOCFEED_CSTR_LENG];
+#endif
+ struct get_reconversion_string_arg grs =
+ {IMR_DOCUMENTFEED, reconv, ime_compstr, 0} ;
+ HIMC himc;
+ LONG l;
+
+ if (!(himc = (ImmGetContextProc) (hwnd)))
+ return 0;
+
+ 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);
+
+ grs.size = l;
+
+ if (NILP(w32_call_lisp_thread(get_reconversion_string, &grs)))
+ return 0;
+ return reconv->dwSize;
+}
+#endif /* USE_W32_CALL_LISP_THREAD */
+#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 USE_W32_CALL_LISP_THREAD
+struct apc_data {
+ Lisp_Object (*func)(Lisp_Object);
+ Lisp_Object val;
+ void *arg;
+ HANDLE ev;
+};
+
+static Lisp_Object apc_error_handler (Lisp_Object arg)
+{
+ return Qnil;
+}
+
+static VOID CALLBACK apc_func_stub(ULONG_PTR data_)
+{
+ struct apc_data *apc_data = (struct apc_data *)data_;
+ Lisp_Object arg = ptr2cons(apc_data->arg);
+ struct gcpro gcpro1;
+
+ GCPRO1(arg);
+ apc_data->val =
+ internal_condition_case_1
+ (apc_data->func, arg, Qt, apc_error_handler);
+
+ UNGCPRO;
+ SetEvent(apc_data->ev);
+}
+
+static Lisp_Object w32_call_lisp_thread
+(Lisp_Object (*func)(Lisp_Object), void *arg)
+{
+ struct apc_data apc_data = {
+ func, Qnil, arg,
+ CreateEvent(NULL, FALSE, FALSE, NULL)
+ };
+ DWORD v;
+ deferred_msg dummy = {0};
+
+ dummy.completed = 1;
+
+
+ w32_apc_mutex_acquire();
+ if (apc_data.ev == NULL)
+ abort();
+
+ if (QueueUserAPC(apc_func_stub,
+ hMainThread, (ULONG_PTR)&apc_data) == 0)
+ abort ();
+
+ while ((v = MsgWaitForMultipleObjectsEx
+ (1, &apc_data.ev, INFINITE, QS_SENDMESSAGE, MWMO_ALERTABLE)) != WAIT_OBJECT_0)
+ if (v == WAIT_OBJECT_0 + 1)
+ w32_msg_pump(&dummy);
+ else if (v != WAIT_IO_COMPLETION)
+ abort();
+
+ w32_apc_mutex_release();
+ return apc_data.val;
+}
+#endif
+
+#ifdef HAVE_NTGUI
+EXFUN (Ffont_at, 3);
+#if !defined(USE_W32_CALL_LISP_THREAD)
+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;
+ struct gcpro gcpro1, gcpro2;
+ extern Lisp_Object QCfamily;
+ int fsid = -1;
+ LOGFONT logfont = {0};
+
+ if (!IsWindow (hwnd))
+ return;
+
+ if (!fIME || NILP(Vime_control))
+ return;
+
+ GCPRO2(font, temp);
+
+ 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);
+ }
+ UNGCPRO;
+
+ 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);
+}
+#else /* USE_W32_CALL_LISP_THREAD */
+
+struct get_imefont_arg {
+ HWND hwnd;
+ struct frame *f;
+ LOGFONT lf;
+};
+
+static Lisp_Object
+w32_get_ime_font (Lisp_Object arg_)
+{
+ struct get_imefont_arg *arg = cons2ptr(arg_);
+
+ Lisp_Object ime_font = Qnil, temp = Qnil, font = Qnil, family;
+ struct gcpro gcpro1, gcpro2;
+ extern Lisp_Object QCfamily;
+ int fsid = -1;
+
+ if (!fIME || NILP(Vime_control))
+ return Qnil;
+
+ GCPRO2(font, temp);
+
+ if (STRINGP(ime_font = get_frame_param (arg->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(arg->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 (arg->f, &arg->lf, font);
+ arg->lf.lfWidth = 0;
+
+ family = ENCODE_SYSTEM(family);
+
+#ifdef _MSC_VER
+ strcpy_s(arg->lf.lfFaceName,
+ sizeof(arg->lf.lfFaceName), SDATA(family));
+#else
+ strcpy(arg->lf.lfFaceName, SDATA(family));
+#endif
+
+ /* rescale if ime font isn't ascii*/
+ 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) {
+ arg->lf.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) {
+ arg->lf.lfHeight *= XFLOAT_DATA (XCDR (temp));
+ break;
+ }
+ }
+ }
+ } else {
+ HFONT hfont = FONT_HANDLE (FRAME_FONT (arg->f));
+ GetObject (hfont, sizeof (arg->lf), &arg->lf);
+ }
+ UNGCPRO;
+
+ return Qt;
+}
+
+static void
+w32_set_ime_font (hwnd, f)
+ HWND hwnd;
+ struct frame *f;
+{
+ HIMC himc;
+ struct get_imefont_arg gia = {
+ hwnd, f, {0}
+ };
+
+ if (NILP(w32_call_lisp_thread(w32_get_ime_font, &gia)) ||
+ !(himc = (ImmGetContextProc) (hwnd)))
+ return;
+
+ (ImmSetCompositionFontProc) (himc, &gia.lf);
+ (ImmReleaseContextProc) (hwnd, himc);
+}
+#endif /* USE_W32_CALL_LISP_THREAD */
+#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);
+
+#if !defined(USE_W32_CALL_LISP_THREAD)
+ case WM_MULE_IMM_SET_IMEFONT:
+ w32_set_ime_font (hwnd);
+#endif
+ case WM_MULE_IMM_SET_CONVERSION_WINDOW:
+ if (w32_get_ime_status (hwnd))
+ w32_set_ime_conv_window (hwnd, (struct frame *) wparam);
+ break;
+
+ case WM_MULE_IMM_PERFORM_RECONVERSION:
+ if (ime_enable_reconversion)
+ w32_perform_reconversion(hwnd, (RECONVERTSTRING*)lparam);
+ break;
+
+#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)
+{
+ FRAME_PTR 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, ®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;
+ struct gcpro gcpro1;
+
+ 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;
+ GCPRO1(val);
+#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;
+ }
+ UNGCPRO;
+ 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)
+#if !defined(USE_W32_CALL_LISP_THREAD)
+{
+ 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;
+}
+#else /* USE_W32_CALL_LISP_THREAD */
+{
+ Lisp_Object temp;
+ struct gcpro gcpro1;
+ struct get_reconversion_string_arg grs = {0, NULL, NULL, 0};
+
+ if (!ime_enable_reconversion ||
+ NILP(Fime_get_mode()))
+ return Qnil;
+
+ GCPRO1(temp);
+
+ if (!NILP(get_reconversion_string(temp = ptr2cons(&grs)))
+ && grs.size > 0
+ && (grs.reconv = xmalloc(grs.size)) != NULL
+ && (memset(grs.reconv, 0, grs.size),
+ (grs.reconv->dwSize = grs.size))
+ && !NILP(get_reconversion_string(temp))) {
+
+ // del_range(grs.start, grs.end);
+
+ PostMessage(FRAME_W32_WINDOW(SELECTED_FRAME()),
+ WM_MULE_IMM_PERFORM_RECONVERSION, 0, (LPARAM)grs.reconv);
+ }
+ UNGCPRO;
+ return Qt;
+}
+#endif /* USE_W32_CALL_LISP_THREAD */
+#endif
+
+#endif /* USE_W32_IME */
+
+
+/***********************************************************************
+ w32 specialized functions
+ ***********************************************************************/
+
+DEFUN ("w32-send-sys-command", Fw32_send_sys_command,
+ Sw32_send_sys_command, 1, 2, 0,
+ doc: /* Send frame a Windows WM_SYSCOMMAND message of type COMMAND.
+Some useful values for COMMAND are #xf030 to maximize frame (#xf020
+to minimize), #xf120 to restore frame to original size, and #xf100
+to activate the menubar for keyboard access. #xf140 activates the
+screen saver if defined.
+
+If optional parameter FRAME is not specified, use selected frame. */)
+ (Lisp_Object command, Lisp_Object frame)
+{
+ FRAME_PTR f = check_x_frame (frame);
+
+ CHECK_NUMBER (command);
+
+ PostMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, XINT (command), 0);
+
+ return Qnil;
+}
+
+DEFUN ("w32-shell-execute", Fw32_shell_execute, Sw32_shell_execute, 2, 4, 0,
+ doc: /* Get Windows to perform OPERATION on DOCUMENT.
+This is a wrapper around the ShellExecute system function, which
+invokes the application registered to handle OPERATION for DOCUMENT.
+
+OPERATION is either nil or a string that names a supported operation.
+What operations can be used depends on the particular DOCUMENT and its
+handler application, but typically it is one of the following common
+operations:
+
+ ¥"open¥" - open DOCUMENT, which could be a file, a directory, or an
+ executable program. If it is an application, that
+ application is launched in the current buffer's default
+ directory. Otherwise, the application associated with
+ DOCUMENT is launched in the buffer's default directory.
+ ¥"print¥" - print DOCUMENT, which must be a file
+ ¥"explore¥" - start the Windows Explorer on DOCUMENT
+ ¥"edit¥" - launch an editor and open DOCUMENT for editing; which
+ editor is launched depends on the association for the
+ specified DOCUMENT
+ ¥"find¥" - initiate search starting from DOCUMENT which must specify
+ a directory
+ nil - invoke the default OPERATION, or ¥"open¥" if default is
+ not defined or unavailable
+
+DOCUMENT is typically the name of a document file or a URL, but can
+also be a program executable to run, or a directory to open in the
+Windows Explorer.
+
+If DOCUMENT is a program executable, the optional third arg PARAMETERS
+can be a string containing command line parameters that will be passed
+to the program; otherwise, PARAMETERS should be nil or unspecified.
+
+Optional fourth argument SHOW-FLAG can be used to control how the
+application will be displayed when it is invoked. If SHOW-FLAG is nil
+or unspecified, the application is displayed normally, otherwise it is
+an integer representing a ShowWindow flag:
+
+ 0 - start hidden
+ 1 - start normally
+ 3 - start maximized
+ 6 - start minimized */)
+ (Lisp_Object operation, Lisp_Object document, Lisp_Object parameters, Lisp_Object show_flag)
+{
+ Lisp_Object current_dir;
+ char *errstr;
+
+ CHECK_STRING (document);
+
+ /* Encode filename, current directory and parameters. */
+ current_dir = ENCODE_FILE (BVAR (current_buffer, directory));
+ document = ENCODE_FILE (document);
+ if (STRINGP (parameters))
+ parameters = ENCODE_SYSTEM (parameters);
+
+ if ((uintptr_t)ShellExecute (NULL,(STRINGP (operation) ?
+ SDATA (operation) : NULL),
+ SDATA (document),
+ (STRINGP (parameters) ?
+ SDATA (parameters) : NULL),
+ SDATA (current_dir),
+ (INTEGERP (show_flag) ?
+ XINT (show_flag) : SW_SHOWDEFAULT)) > 32)
+ return Qt;
+ errstr = w32_strerror (0);
+ /* The error string might be encoded in the locale's encoding. */
+ if (!NILP (Vlocale_coding_system))
+ {
+ Lisp_Object decoded =
+ code_convert_string_norecord (build_unibyte_string (errstr),
+ Vlocale_coding_system, 0);
+ errstr = SSDATA (decoded);
+ }
+ error ("ShellExecute failed: %s", errstr);
+}
+
+/* Lookup virtual keycode from string representing the name of a
+ non-ascii keystroke into the corresponding virtual key, using
+ lispy_function_keys. */
+static int
+lookup_vk_code (char *key)
+{
+ int i;
+
+ for (i = 0; i < 256; i++)
+ if (lispy_function_keys[i]
+ && strcmp (lispy_function_keys[i], key) == 0)
+ return i;
+
+ return -1;
+}
+
+/* Convert a one-element vector style key sequence to a hot key
+ definition. */
+static Lisp_Object
+w32_parse_hot_key (Lisp_Object key)
+{
+ /* Copied from Fdefine_key and store_in_keymap. */
+ register Lisp_Object c;
+ int vk_code;
+ int lisp_modifiers;
+ int w32_modifiers;
+ struct gcpro gcpro1;
+
+ CHECK_VECTOR (key);
+
+ if (XFASTINT (Flength (key)) != 1)
+ return Qnil;
+
+ GCPRO1 (key);
+
+ c = Faref (key, make_number (0));
+
+ if (CONSP (c) && lucid_event_type_list_p (c))
+ c = Fevent_convert_list (c);
+
+ UNGCPRO;
+
+ if (! INTEGERP (c) && ! SYMBOLP (c))
+ error ("Key definition is invalid");
+
+ /* Work out the base key and the modifiers. */
+ if (SYMBOLP (c))
+ {
+ c = parse_modifiers (c);
+ lisp_modifiers = XINT (Fcar (Fcdr (c)));
c = Fcar (c);
if (!SYMBOLP (c))
emacs_abort ();
default-printer-name と、w32_strerror()の間に w32-memory-info を追加している。
Hunk #30 FAILED at 7211.
@@ -7211,6 +9007,87 @@
return build_string (pname_buf);
}
+
+DEFUN ("w32-memory-info", Fw32_memory_info, Sw32_memory_info,
+ 0, 0, 0, doc: /* Retrieves information about the memory usage.
+return value is a list of
+
+reserved_heap_size
+
+GlobalMemoryStatusEx:
+ MemoryLoad;
+ TotalPhys;
+ AvailPhys;
+ TotalPageFile;
+ AvailPageFile;
+ TotalVirtual;
+ AvailVirtual;
+ AvailExtendedVirtual;
+
+GetProcessMemoryInfo:
+ PageFaultCount;
+ PeakWorkingSetSize;
+ WorkingSetSize;
+ QuotaPeakPagedPoolUsage;
+ QuotaPagedPoolUsage;
+ QuotaPeakNonPagedPoolUsage;
+ QuotaNonPagedPoolUsage;
+ PagefileUsage;
+ PeakPagefileUsage;
+ PrivateUsage; (Xp or above) */) (void)
+{
+ PROCESS_MEMORY_COUNTERS_EX pmc = {sizeof(PROCESS_MEMORY_COUNTERS_EX)};
+ MEMORYSTATUSEX msx = {sizeof(MEMORYSTATUSEX)};
+ OSVERSIONINFO osi = {sizeof(OSVERSIONINFO)};
+
+ int os_version;
+ struct gcpro gcpro1, gcpro2;
+ Lisp_Object pm, sm;
+
+ if (GetVersionEx(&osi) == 0)
+ return Qnil;
+
+ os_version = (osi.dwMajorVersion << 8) | osi.dwMinorVersion ;
+ if (os_version < 0x501)
+ pmc.cb = sizeof(PROCESS_MEMORY_COUNTERS);
+
+ if (GlobalMemoryStatusEx(&msx) == 0 ||
+ GetProcessMemoryInfo(GetCurrentProcess(),
+ (PPROCESS_MEMORY_COUNTERS)&pmc, sizeof(pmc)) == 0)
+ return Qnil;
+
+ GCPRO2(sm, pm);
+
+ sm = Qnil;
+ sm = Fcons(make_fixnum_or_float(msx.ullAvailExtendedVirtual), sm);
+ sm = Fcons(make_fixnum_or_float(msx.ullAvailVirtual), sm);
+ sm = Fcons(make_fixnum_or_float(msx.ullTotalVirtual), sm);
+ sm = Fcons(make_fixnum_or_float(msx.ullAvailPageFile), sm);
+ sm = Fcons(make_fixnum_or_float(msx.ullTotalPageFile), sm);
+ sm = Fcons(make_fixnum_or_float(msx.ullAvailPhys), sm);
+ sm = Fcons(make_fixnum_or_float(msx.ullTotalPhys), sm);
+ sm = Fcons(make_fixnum_or_float(msx.dwMemoryLoad), sm);
+
+ pm = Qnil;
+ if (os_version >= 0x501)
+ pm = Fcons(make_fixnum_or_float(pmc.PrivateUsage), pm);
+ pm = Fcons(make_fixnum_or_float(pmc.PeakPagefileUsage), pm);
+ pm = Fcons(make_fixnum_or_float(pmc.PagefileUsage), pm);
+ pm = Fcons(make_fixnum_or_float(pmc.QuotaNonPagedPoolUsage), pm);
+ pm = Fcons(make_fixnum_or_float(pmc.QuotaPeakNonPagedPoolUsage), pm);
+ pm = Fcons(make_fixnum_or_float(pmc.QuotaPagedPoolUsage), pm);
+ pm = Fcons(make_fixnum_or_float(pmc.QuotaPeakPagedPoolUsage), pm);
+ pm = Fcons(make_fixnum_or_float(pmc.WorkingSetSize), pm);
+ pm = Fcons(make_fixnum_or_float(pmc.PeakWorkingSetSize), pm);
+ pm = Fcons(make_fixnum_or_float(pmc.PageFaultCount), pm);
+ pm = Fcons(pm, Qnil);
+
+ sm = Fcons(sm, pm);
+
+ RETURN_UNGCPRO(Fcons(make_fixnum_or_float(reserved_heap_size), sm));
+}
+
+
/* Equivalent of strerror for W32 error codes. */
Hunk #36 FAILED at 7966.
globals_of_w32fns() の中の USE_W32_IME 切り分け
USE_W32_CALL_LISP_THREAD と IME_UNICODE を参照した切り分け。
わっかりにくいなあ。。
@@ -7966,14 +9885,18 @@
set_ime_composition_window_fn = (ImmSetCompositionWindow_Proc)
GetProcAddress (imm32_lib, "ImmSetCompositionWindow");
}
+#endif /* USE_W32_IME */
+
DEFVAR_INT ("w32-ansi-code-page",
w32_ansi_code_page,
doc: /* The ANSI code page used by the system. */);
w32_ansi_code_page = GetACP ();
+#if !defined(USE_W32_CALL_LISP_THREAD) || defined(IME_UNICODE)
if (os_subtype == OS_NT)
w32_unicode_gui = 1;
else
+#endif
w32_unicode_gui = 0;
/* MessageBox does not work without this when linked to comctl32.dll 6.0. */
emacs_abort()の TEXTマクロ
Hunk #37 FAILED at 7987.
@@ -7987,14 +9910,14 @@
{
int button;
button = MessageBox (NULL,
- "A fatal error has occurred!¥n¥n"
+ TEXT("A fatal error has occurred!¥n¥n"
"Would you like to attach a debugger?¥n¥n"
"Select YES to debug, NO to abort Emacs"
#if __GNUC__
"¥n¥n(type ¥"gdb -p <emacs-PID>¥" and¥n"
"¥"continue¥" inside GDB before clicking YES.)"
#endif
- , "Emacs Abort Dialog",
+ ), TEXT("Emacs Abort Dialog"),
MB_ICONEXCLAMATION | MB_TASKMODAL
| MB_SETFOREGROUND | MB_YESNO);
switch (button)
Hunk #38 FAILED at 8008.
USE_W32_CALL_LISP_THREAD 切り分け部分を最後に追加
@@ -8008,3 +9931,63 @@
break;
}
}
+
+
+#ifdef USE_W32_CALL_LISP_THREAD
+#ifdef _MSC_VER
+#include <intrin.h>
+#pragma intrinsic(_InterlockedCompareExchange, _InterlockedExchange)
+#endif
+
+static long apc_mutex;
+static HANDLE apc_mutex_ev;
+
+void w32_apc_mutex_init(void)
+{
+#if 0
+ apc_mutex = 0;
+ apc_mutex_ev = CreateEvent(NULL, FALSE, FALSE, NULL);
+#endif
+}
+
+void w32_apc_mutex_term(void)
+{
+#if 0
+ CloseHandle(apc_mutex_ev);
+#endif
+}
+
+void w32_apc_mutex_acquire(void)
+{
+#if 0
+ const DWORD tid = GetCurrentThreadId();
+ const BOOL proc_msg = dwWindowsThreadId == tid;
+ DWORD locker, v;
+ deferred_msg dummy = {0};
+ MSG msg;
+ dummy.completed = 1;
+
+ while ((locker =
+ InterlockedCompareExchange(&apc_mutex, tid, 0)) != 0
+ && locker != tid)
+ while ((v = proc_msg
+ ? MsgWaitForMultipleObjectsEx
+ (1, &apc_mutex_ev, INFINITE,
+ QS_ALLINPUT | QS_ALLPOSTMESSAGE, MWMO_ALERTABLE)
+ : WaitForSingleObjectEx(apc_mutex_ev, INFINITE, TRUE))
+ != WAIT_OBJECT_0)
+ if (v == WAIT_OBJECT_0 + 1)
+ w32_msg_pump(&dummy);
+ else if (v != WAIT_IO_COMPLETION)
+ abort();
+#endif
+}
+
+void w32_apc_mutex_release(void)
+{
+#if 0
+ InterlockedExchange(&apc_mutex, 0);
+ SetEvent(apc_mutex_ev);
+#endif
+}
+#endif
patching file src/w32fns.c Hunk #2 succeeded at 69 (offset 3 lines). Hunk #3 succeeded at 91 (offset 3 lines). Hunk #4 succeeded at 108 (offset 3 lines). Hunk #5 succeeded at 137 (offset -1 lines). Hunk #6 FAILED at 233. Hunk #7 succeeded at 286 (offset 29 lines). Hunk #8 succeeded at 323 (offset 29 lines). Hunk #9 FAILED at 328. Hunk #10 succeeded at 427 (offset -11 lines). Hunk #11 succeeded at 1959 (offset 55 lines). Hunk #12 succeeded at 2064 with fuzz 1 (offset 43 lines). Hunk #13 succeeded at 2539 (offset 71 lines). Hunk #14 succeeded at 2569 (offset 71 lines). Hunk #15 succeeded at 2786 (offset 72 lines). Hunk #16 succeeded at 2927 (offset 72 lines). Hunk #17 succeeded at 3260 (offset 72 lines). Hunk #18 succeeded at 3297 (offset 72 lines). Hunk #19 succeeded at 3416 (offset 93 lines). Hunk #20 FAILED at 4100. Hunk #21 succeeded at 4479 (offset 140 lines). Hunk #22 succeeded at 4502 (offset 140 lines). Hunk #23 succeeded at 6609 (offset 361 lines). Hunk #24 succeeded at 6642 (offset 365 lines). Hunk #25 succeeded at 6685 (offset 376 lines). Hunk #26 FAILED at 6408. Hunk #27 succeeded at 6922 (offset 461 lines). Hunk #28 FAILED at 6589. Hunk #29 succeeded at 7785 (offset 693 lines). Hunk #30 FAILED at 7211. Hunk #31 succeeded at 8298 (offset 758 lines). Hunk #32 succeeded at 8315 (offset 756 lines). Hunk #33 succeeded at 8595 (offset 767 lines). Hunk #34 succeeded at 8659 with fuzz 2 (offset 768 lines). Hunk #35 succeeded at 8885 with fuzz 2 (offset 931 lines). Hunk #36 FAILED at 7966. Hunk #37 FAILED at 7987. Hunk #38 FAILED at 8008. 9 out of 38 hunks FAILED -- saving rejects to file src/w32fns.c.rej
fill_in_logfont のグローバル関数化。なんじゃあこりゃあ。。
patching file src/w32font.c Hunk #1 FAILED at 99. Hunk #2 FAILED at 1963. 2 out of 2 hunks FAILED -- saving rejects to file src/w32font.c.rej
OK
patching file src/w32font.h
OK
patching file src/w32heap.c
OK
patching file src/w32heap.h
OK
patching file src/w32inevt.h
patching file src/w32proc.c Hunk #1 FAILED at 41. Hunk #2 succeeded at 66 (offset 4 lines). Hunk #3 succeeded at 1715 (offset 150 lines). Hunk #4 succeeded at 1767 (offset 150 lines). Hunk #5 succeeded at 1795 (offset 150 lines). Hunk #6 succeeded at 1810 (offset 150 lines). Hunk #7 succeeded at 2097 (offset 165 lines). Hunk #8 succeeded at 2113 with fuzz 2 (offset 165 lines). Hunk #9 FAILED at 2866. Hunk #10 FAILED at 2884. Hunk #11 FAILED at 2898. 4 out of 11 hunks FAILED -- saving rejects to file src/w32proc.c.rej
patching file src/w32term.c Hunk #1 succeeded at 64 (offset 1 line). Hunk #2 FAILED at 110. Hunk #3 succeeded at 4910 with fuzz 2 (offset 57 lines). Hunk #4 succeeded at 5379 with fuzz 2 (offset 70 lines). Hunk #5 FAILED at 6562. Hunk #6 succeeded at 6673 (offset 55 lines). 2 out of 6 hunks FAILED -- saving rejects to file src/w32term.c.rej
patching file src/w32term.h Hunk #1 succeeded at 569 (offset -19 lines). Hunk #2 succeeded at 607 with fuzz 2 (offset -18 lines).
patching file src/w32xfns.c Hunk #1 succeeded at 178 (offset 1 line).
patching file src/window.c Hunk #1 succeeded at 132 with fuzz 2 (offset 1 line). Hunk #2 succeeded at 480 with fuzz 2 (offset 20 lines). Hunk #3 FAILED at 528. Hunk #4 succeeded at 3567 (offset 265 lines). Hunk #5 succeeded at 7256 (offset 559 lines). 1 out of 5 hunks FAILED -- saving rejects to file src/window.c.rej
patching file src/xdisp.c Hunk #1 FAILED at 11166. 1 out of 1 hunk FAILED -- saving rejects to file src/xdisp.c.rej