Index: lib-src/makefile.w32-in =================================================================== RCS file: /cvsroot/emacs/emacs/lib-src/makefile.w32-in,v retrieving revision 2.25.2.27 diff -c -r2.25.2.27 makefile.w32-in *** lib-src/makefile.w32-in 6 Jun 2007 20:27:53 -0000 2.25.2.27 --- lib-src/makefile.w32-in 1 Jul 2007 00:37:17 -0000 *************** *** 148,154 **** w32.o w32bdf.o w32console.o w32fns.o w32heap.o w32inevt.o \ w32menu.o w32proc.o w32reg.o w32select.o w32term.o w32xfns.o \ dispnew.o frame.o scroll.o xdisp.o window.o \ ! charset.o coding.o category.o ccl.o \ cm.o term.o xfaces.o \ emacs.o keyboard.o macros.o keymap.o sysdep.o \ buffer.o filelock.o insdel.o marker.o \ --- 148,154 ---- w32.o w32bdf.o w32console.o w32fns.o w32heap.o w32inevt.o \ w32menu.o w32proc.o w32reg.o w32select.o w32term.o w32xfns.o \ dispnew.o frame.o scroll.o xdisp.o window.o \ ! charset.o coding.o category.o ccl.o character.o\ cm.o term.o xfaces.o \ emacs.o keyboard.o macros.o keymap.o sysdep.o \ buffer.o filelock.o insdel.o marker.o \ *************** *** 167,173 **** lispsource = ../lisp/ MOUSE_SUPPORT = $(lispsource)select.elc $(lispsource)scroll-bar.elc $(lispsource)mouse.elc $(lispsource)tooltip.elc ! WINNT_SUPPORT = $(lispsource)ls-lisp.elc $(lispsource)disp-table.elc $(lispsource)w32-fns.elc $(lispsource)dos-w32.elc $(lispsource)w32-vars.elc # lisp files that are loaded up on other platforms MSDOS_SUPPORT = $(lispsource)dos-fns.elc $(lispsource)dos-vars.elc $(lispsource)international/ccl.elc $(lispsource)international/codepage.elc --- 167,174 ---- lispsource = ../lisp/ MOUSE_SUPPORT = $(lispsource)select.elc $(lispsource)scroll-bar.elc $(lispsource)mouse.elc $(lispsource)tooltip.elc ! WINNT_SUPPORT = $(lispsource)ls-lisp.elc $(lispsource)disp-table.elc $(lispsource)w32-fns.elc $(lispsource)dos-w32.elc $(lispsource)w32-vars.elc $(lispsource)international/w32-ime.elc ! # lisp files that are loaded up on other platforms MSDOS_SUPPORT = $(lispsource)dos-fns.elc $(lispsource)dos-vars.elc $(lispsource)international/ccl.elc $(lispsource)international/codepage.elc Index: lisp/loadup.el =================================================================== RCS file: /cvsroot/emacs/emacs/lisp/loadup.el,v retrieving revision 1.131.2.19 diff -c -r1.131.2.19 loadup.el *** lisp/loadup.el 16 Jun 2007 01:58:37 -0000 1.131.2.19 --- lisp/loadup.el 1 Jul 2007 00:37:18 -0000 *************** *** 182,187 **** --- 182,188 ---- (progn (load "ls-lisp") (load "disp-table") ; needed to setup ibm-pc char set, see internal.el + (load "international/w32-ime") (load "dos-w32") (load "w32-vars") (load "w32-fns"))) Index: man/makefile.w32-in =================================================================== RCS file: /cvsroot/emacs/emacs/man/makefile.w32-in,v retrieving revision 1.4.2.19 diff -c -r1.4.2.19 makefile.w32-in *** man/makefile.w32-in 26 Jan 2007 06:15:33 -0000 1.4.2.19 --- man/makefile.w32-in 1 Jul 2007 00:37:20 -0000 *************** *** 29,35 **** # The makeinfo program is part of the Texinfo distribution. MAKEINFO = makeinfo --force ! MULTI_INSTALL_INFO = $(srcdir)\..\nt\multi-install-info.bat INFO_TARGETS = $(infodir)/emacs $(infodir)/ccmode \ $(infodir)/cl $(infodir)/dired-x $(infodir)/ediff \ $(infodir)/forms $(infodir)/gnus $(infodir)/message \ --- 29,35 ---- # The makeinfo program is part of the Texinfo distribution. MAKEINFO = makeinfo --force ! MULTI_INSTALL_INFO = $(srcdir)/../nt/multi-install-info.bat INFO_TARGETS = $(infodir)/emacs $(infodir)/ccmode \ $(infodir)/cl $(infodir)/dired-x $(infodir)/ediff \ $(infodir)/forms $(infodir)/gnus $(infodir)/message \ *************** *** 59,65 **** texi2dvi $< TEXI2DVI = texi2dvi ! ENVADD = $(srcdir)\..\nt\envadd.bat "TEXINPUTS=$(srcdir);$(TEXINPUTS)" \ "MAKEINFO=$(MAKEINFO) -I$(srcdir)" /C EMACS_XTRA=\ --- 59,65 ---- texi2dvi $< TEXI2DVI = texi2dvi ! ENVADD = $(srcdir)/../nt/envadd.bat "TEXINPUTS=$(srcdir);$(TEXINPUTS)" \ "MAKEINFO=$(MAKEINFO) -I$(srcdir)" /C EMACS_XTRA=\ Index: nt/configure.bat =================================================================== RCS file: /cvsroot/emacs/emacs/nt/configure.bat,v retrieving revision 1.23.4.13 diff -c -r1.23.4.13 configure.bat *** nt/configure.bat 4 Jun 2007 21:57:45 -0000 1.23.4.13 --- nt/configure.bat 1 Jul 2007 00:37:21 -0000 *************** *** 106,111 **** --- 106,112 ---- if "%1" == "--without-gif" goto withoutgif if "%1" == "--without-tiff" goto withouttiff if "%1" == "--without-xpm" goto withoutxpm + if "%1" == "--enable-w32-ime" goto withime if "%1" == "--enable-font-backend" goto withfont if "%1" == "" goto checkutils :usage *************** *** 124,129 **** --- 125,131 ---- echo. --without-gif do not use libungif even if it is installed echo. --without-tiff do not use libtiff even if it is installed echo. --without-xpm do not use libXpm even if it is installed + echo. --enable-w32-ime build with w32 input method editor echo. --enable-font-backend build with font backend support goto end rem ---------------------------------------------------------------------- *************** *** 211,223 **** --- 213,237 ---- shift goto again + rem ---------------------------------------------------------------------- + :withfont set usercflags=%usercflags%%sep1%-DUSE_FONT_BACKEND + set sep1= %nothing% set usefontbackend=Y shift goto again rem ---------------------------------------------------------------------- + + :withime + set usercflags=%usercflags%%sep1%-DUSE_W32_IME + set sep1= %nothing% + set usew32ime=Y + shift + goto again + + rem ---------------------------------------------------------------------- rem Check that necessary utilities (cp and rm) are present. :checkutils echo Checking for 'cp'... *************** *** 226,232 **** echo Checking for 'rm'... rm junk.bat if exist junk.bat goto needrm ! goto checkcompiler :needcp echo You need 'cp' (the Unix file copy program) to build Emacs. goto end --- 240,246 ---- echo Checking for 'rm'... rm junk.bat if exist junk.bat goto needrm ! goto checkversion :needcp echo You need 'cp' (the Unix file copy program) to build Emacs. goto end *************** *** 236,241 **** --- 250,284 ---- goto end rem ---------------------------------------------------------------------- + rem Check for Windows Version. + rem _WIN32_WINDOWS and _WIN32_WINNT are automatically defined by WINVER. + + :checkversion + echo Checking for Windows Version ... + + %COMSPEC% /q /c ver > junk.txt + + %COMSPEC% /c findstr "XP" junk.txt > NUL + if %errorlevel%==0 goto WXP + + %COMSPEC% /c findstr "2000" junk.txt > NUL + if %errorlevel%==0 goto W2K + + if %errorlevel%==1 goto WNT + + :WXP + set usercflags=%usercflags%%sep1%-DWINVER=0x0501 + goto ver_end + :W2k + set usercflags=%usercflags%%sep1%-DWINVER=0x0500 + goto ver_end + :WNT + set usercflags=%usercflags%%sep1%-DWINVER=0x0400 + goto ver_end + :ver_end + rm -f junk.txt + + rem ---------------------------------------------------------------------- rem Auto-detect compiler if not specified, and validate GCC if chosen. :checkcompiler if (%COMPILER%)==(cl) goto compilercheckdone *************** *** 465,470 **** --- 508,539 ---- rm -f junk.c junk.obj junk.err junk.out rem ---------------------------------------------------------------------- + rem check for RECONVERTSTRING + rem + + echo checking for RECONVERTSTRING... + + echo #include "windows.h" >junk.c + echo #include "imm.h" >>junk.c + echo main(){RECONVERTSTRING x;} >>junk.c + + %COMPILER% %usercflags% %mingwflag% -c junk.c -o junk.obj >>config.log 2>&1 + if exist junk.obj goto haveReconvertstring + + echo ...RECONVERTSTRING isn't defined. + echo The failed program was: >>config.log + type junk.c >>config.log + set HAVE_RECONVERTSTRING= + goto recoverstringDone + + :haveReconvertstring + echo ...RECONVERTSTRING is defined. + set HAVE_RECONVERTSTRING=1 + + :recoverstringDone + rm -f junk.c junk.obj + + rem ---------------------------------------------------------------------- :genmakefiles echo Generating makefiles if %COMPILER% == gcc set MAKECMD=gmake *************** *** 484,489 **** --- 553,559 ---- if not "(%usercflags%)" == "()" echo USER_CFLAGS=%usercflags%>>config.settings if not "(%userldflags%)" == "()" echo USER_LDFLAGS=%userldflags%>>config.settings if (%usefontbackend%) == (Y) echo USE_FONTBACKEND=1 >>config.settings + if (%usew32ime%) == (Y) echo USE_W32IME=1 >>config.settings echo # End of settings from configure.bat>>config.settings echo. >>config.settings *************** *** 497,502 **** --- 567,573 ---- if not "(%HAVE_GIF%)" == "()" echo #define HAVE_GIF 1 >>config.tmp if not "(%HAVE_TIFF%)" == "()" echo #define HAVE_TIFF 1 >>config.tmp if not "(%HAVE_XPM%)" == "()" echo #define HAVE_XPM 1 >>config.tmp + if not "(%HAVE_RECONVERTSTRING%)" == "()" echo #define HAVE_RECONVERTSTRING 1 >>config.tmp echo /* End of settings from configure.bat. */ >>config.tmp Rem See if fc.exe returns a meaningful exit status. If it does, we Index: nt/gmake.defs =================================================================== RCS file: /cvsroot/emacs/emacs/nt/gmake.defs,v retrieving revision 1.18.4.9 diff -c -r1.18.4.9 gmake.defs *** nt/gmake.defs 26 Jan 2007 06:15:47 -0000 1.18.4.9 --- nt/gmake.defs 1 Jul 2007 00:37:21 -0000 *************** *** 184,191 **** else DEBUG_CFLAGS = endif ! CFLAGS = -I. -DWIN32_LEAN_AND_MEAN -D_WIN32_WINNT=0x0400 $(ARCH_CFLAGS) -D$(ARCH) \ ! -D_CRTAPI1=_cdecl \ $(DEBUG_CFLAGS) $(USER_CFLAGS) $(LOCAL_FLAGS) EMACS_EXTRA_C_FLAGS = -DUSE_CRT_DLL=1 --- 184,190 ---- else DEBUG_CFLAGS = endif ! CFLAGS = -I. -DWIN32_LEAN_AND_MEAN $(ARCH_CFLAGS) -D$(ARCH) -D_CRTAPI1=_cdecl \ $(DEBUG_CFLAGS) $(USER_CFLAGS) $(LOCAL_FLAGS) EMACS_EXTRA_C_FLAGS = -DUSE_CRT_DLL=1 Index: src/frame.c =================================================================== RCS file: /cvsroot/emacs/emacs/src/frame.c,v retrieving revision 1.300.2.41 diff -c -r1.300.2.41 frame.c *** src/frame.c 11 Jun 2007 00:57:40 -0000 1.300.2.41 --- src/frame.c 1 Jul 2007 00:37:26 -0000 *************** *** 2568,2573 **** --- 2568,2577 ---- has an `x-frame-parameter' property which is an integer in Lisp that is an index in this table. */ + #ifdef USE_W32_IME + extern void x_set_ime_font (struct frame *, Lisp_Object, Lisp_Object); + #endif + struct frame_parm_table { char *name; Lisp_Object *variable; *************** *** 2583,2588 **** --- 2587,2595 ---- {"cursor-color", &Qcursor_color}, {"cursor-type", &Qcursor_type}, {"font", 0}, + #ifdef USE_W32_IME + {"ime-font", &Qime_font}, + #endif {"foreground-color", 0}, {"icon-name", &Qicon_name}, {"icon-type", &Qicon_type}, Index: src/frame.h =================================================================== RCS file: /cvsroot/emacs/emacs/src/frame.h,v retrieving revision 1.103.2.18 diff -c -r1.103.2.18 frame.h *** src/frame.h 29 Jun 2007 03:37:31 -0000 1.103.2.18 --- src/frame.h 1 Jul 2007 00:37:28 -0000 *************** *** 1007,1012 **** --- 1007,1015 ---- extern Lisp_Object Qbuffer_predicate, Qbuffer_list; extern Lisp_Object Qcursor_color, Qcursor_type; extern Lisp_Object Qfont; + #ifdef USE_W32_IME + extern Lisp_Object Qime_font; + #endif extern Lisp_Object Qbackground_color, Qforeground_color; extern Lisp_Object Qicon, Qicon_name, Qicon_type, Qicon_left, Qicon_top; extern Lisp_Object Qinternal_border_width; Index: src/keyboard.c =================================================================== RCS file: /cvsroot/emacs/emacs/src/keyboard.c,v retrieving revision 1.753.2.68 diff -c -r1.753.2.68 keyboard.c *** src/keyboard.c 11 Jun 2007 00:57:43 -0000 1.753.2.68 --- src/keyboard.c 1 Jul 2007 00:37:42 -0000 *************** *** 4800,4810 **** --- 4800,4824 ---- "pause", /* VK_PAUSE 0x13 */ "capslock", /* VK_CAPITAL 0x14 */ + #ifdef USE_W32_IME /* 95.8.27 Modified by himi */ + "kana", /* VK_KANA 0x15 */ + 0, 0, 0, /* 0x16 .. 0x18 */ + "kanji", /* VK_KANJI 0x19 */ + "compend", /* VK_COMPEND 0x1A */ + #else 0, 0, 0, 0, 0, 0, /* 0x15 .. 0x1A */ + #endif "escape", /* VK_ESCAPE 0x1B */ + + #ifdef USE_W32_IME + "convert", /* VK_CONVERT */ + "noconvert", /* VK_NOCONVERT */ + 0, 0, /* 0x1C .. 0x1F */ + #else 0, 0, 0, 0, /* 0x1C .. 0x1F */ + #endif 0, /* VK_SPACE 0x20 */ "prior", /* VK_PRIOR 0x21 */ *************** *** 8873,8878 **** --- 8887,8899 ---- volatile Lisp_Object from_string; volatile int count = SPECPDL_INDEX (); + /* To control IME ( by himi ) */ + #ifdef USE_W32_IME + extern Lisp_Object Fime_force_on (), Fime_force_off (), Fime_get_mode (); + Lisp_Object VIME_command_off_flag = Qnil; + Lisp_Object IME_command_loop_flag = Qnil; + #endif + /* How many keys there are in the current key sequence. */ volatile int t; *************** *** 9018,9023 **** --- 9039,9050 ---- 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. (by himi 96.10.13) */ + IME_command_loop_flag = Qnil; + #endif + starting_buffer = current_buffer; first_unbound = bufsize + 1; *************** *** 9144,9149 **** --- 9171,9186 ---- 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 + if (t >= bufsize) error ("Key sequence too long"); *************** *** 9831,9836 **** --- 9868,9879 ---- ? defs[first_binding] : Qnil); + /* to control IME (by himi) */ + #ifdef USE_W32_IME + if (!NILP (VIME_command_off_flag)) + Fime_force_on (Qnil); + #endif + unread_switch_frame = delayed_switch_frame; unbind_to (count, Qnil); Index: src/w32.c =================================================================== RCS file: /cvsroot/emacs/emacs/src/w32.c,v retrieving revision 1.83.6.22 diff -c -r1.83.6.22 w32.c *** src/w32.c 16 Jun 2007 22:31:56 -0000 1.83.6.22 --- src/w32.c 1 Jul 2007 00:37:47 -0000 *************** *** 4026,4043 **** + strlen (load_path)); sprintf (buffer, ! "The Emacs Windows initialization file \"%s.el\" " ! "could not be found in your Emacs installation. " ! "Emacs checked the following directories for this file:\n" ! "\n%s\n\n" ! "When Emacs cannot find this file, it usually means that it " ! "was not installed properly, or its distribution file was " ! "not unpacked properly.\nSee the README.W32 file in the " ! "top-level Emacs directory for more information.", init_file_name, load_path); MessageBox (NULL, buffer, ! "Emacs Abort Dialog", MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL); /* Use the low-level Emacs abort. */ #undef abort --- 4026,4043 ---- + strlen (load_path)); sprintf (buffer, ! TEXT ("The Emacs Windows initialization file \"%s.el\" " ! "could not be found in your Emacs installation. " ! "Emacs checked the following directories for this file:\n" ! "\n%s\n\n" ! "When Emacs cannot find this file, it usually means that it " ! "was not installed properly, or its distribution file was " ! "not unpacked properly.\nSee the README.W32 file in the " ! "top-level Emacs directory for more information."), init_file_name, load_path); MessageBox (NULL, buffer, ! TEXT ("Emacs Abort Dialog"), MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL); /* Use the low-level Emacs abort. */ #undef abort Index: src/w32bdf.c =================================================================== RCS file: /cvsroot/emacs/emacs/src/w32bdf.c,v retrieving revision 1.17.6.10 diff -c -r1.17.6.10 w32bdf.c *** src/w32bdf.c 21 Jun 2007 23:28:41 -0000 1.17.6.10 --- src/w32bdf.c 1 Jul 2007 00:37:48 -0000 *************** *** 302,308 **** font_char *pch; cache_bitmap *pcb; ! UnmapViewOfFile(fontp->hfilemap); CloseHandle(fontp->hfilemap); CloseHandle(fontp->hfile); --- 302,308 ---- font_char *pch; cache_bitmap *pcb; ! UnmapViewOfFile(fontp->font); CloseHandle(fontp->hfilemap); CloseHandle(fontp->hfile); Index: src/w32fns.c =================================================================== RCS file: /cvsroot/emacs/emacs/src/w32fns.c,v retrieving revision 1.219.2.47 diff -c -r1.219.2.47 w32fns.c *** src/w32fns.c 29 Jun 2007 03:37:29 -0000 1.219.2.47 --- src/w32fns.c 1 Jul 2007 00:38:00 -0000 *************** *** 54,59 **** --- 54,68 ---- #include #include + #ifdef USE_W32_IME + #include + #include + + #ifndef HAVE_NTGUI + #include + #endif + #endif + #include #define FILE_NAME_TEXT_FIELD edt1 *************** *** 71,76 **** --- 80,90 ---- extern void w32_free_menu_strings P_ ((HWND)); extern XCharStruct *w32_per_char_metric P_ ((XFontStruct *, wchar_t *, int)); + #ifdef RECONVERSION + extern LRESULT w32_get_ime_reconversion_length (); + extern BOOL w32_get_ime_reconversion_string (HWND, WPARAM, RECONVERTSTRING*); + #endif + extern int quit_char; extern char *lispy_function_keys[]; *************** *** 201,206 **** --- 215,229 ---- Lisp_Object Qnone; Lisp_Object Qsuppress_icon; Lisp_Object Qundefined_color; + + #ifdef USE_W32_IME + Lisp_Object Qime_font; + static int IME_event_off_count; + #ifndef HAVE_NTGUI + HWND hwndConsole; + #endif + #endif + Lisp_Object Qcancel_timer; Lisp_Object Qhyper; Lisp_Object Qsuper; *************** *** 424,430 **** void x_set_tool_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object)); static void x_edge_detection P_ ((struct frame *, struct image *, Lisp_Object, Lisp_Object)); ! --- 447,465 ---- void x_set_tool_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object)); static void x_edge_detection P_ ((struct frame *, struct image *, Lisp_Object, Lisp_Object)); ! #ifdef USE_W32_IME ! void x_set_ime_font P_ ((struct frame *, Lisp_Object, Lisp_Object)); ! void w32_get_ime_logfont P_ ((HWND)); ! static void w32_set_ime_conv_window P_ ((struct frame *)); ! static void w32_set_ime_status P_ ((HWND, int)); ! static int w32_get_ime_status P_ ((HWND)); ! static int w32_set_ime_mode P_ ((HWND, int, int)); ! void w32_ime_control_init P_ ((void)); ! static void w32_set_ime_font P_ ((HWND, LPLOGFONT)); ! static BOOL w32_get_ime_composition_string P_ ((HWND)); ! static LRESULT CALLBACK conversion_agent_wndproc P_ ((HWND, UINT, WPARAM, LPARAM)); ! static int initialize_conversion_agent P_ (()); ! #endif *************** *** 2017,2030 **** Cursor w32_load_cursor (LPCTSTR name) { ! /* Try first to load cursor from application resource. */ ! Cursor cursor = LoadImage ((HINSTANCE) GetModuleHandle(NULL), ! name, IMAGE_CURSOR, 0, 0, ! LR_DEFAULTCOLOR | LR_DEFAULTSIZE | LR_SHARED); ! if (!cursor) { ! /* Then try to load a shared predefined cursor. */ ! cursor = LoadImage (NULL, name, IMAGE_CURSOR, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE | LR_SHARED); } return cursor; --- 2052,2065 ---- Cursor w32_load_cursor (LPCTSTR name) { ! /* Try first to load a shared predefined cursor. */ ! Cursor cursor = LoadImage (NULL, name, IMAGE_CURSOR, 0, 0, ! LR_DEFAULTCOLOR | LR_DEFAULTSIZE | LR_SHARED); ! if (!cursor) { ! /* Then try to load cursor from application resource. */ ! cursor = LoadImage ((HINSTANCE) GetModuleHandle(NULL), ! name, IMAGE_CURSOR, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE | LR_SHARED); } return cursor; *************** *** 3902,3909 **** --- 3937,4005 ---- return retval; } + #ifdef USE_W32_IME + case WM_IME_NOTIFY: + if (wParam == IMN_SETOPENSTATUS) + { + 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: + { + W32Msg wmsg; + my_post_msg (&wmsg, hwnd, WM_MULE_IMM_SET_COMPOSITION_FONT, 0, 0); + goto dflt; + } + + case WM_MULE_IMM_SET_COMPOSITION_FONT_REPLY: + w32_set_ime_conv_window ((struct frame *) wParam); + w32_set_ime_font (hwnd, (LPLOGFONT) lParam); + break; + + case WM_IME_ENDCOMPOSITION: + 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_MULE_IMM_SET_CONVERSION_WINDOW: + w32_set_ime_conv_window ((struct frame *) wParam); + break; + + #ifdef RECONVERSION + case WM_IME_REQUEST: + if (wParam == IMR_RECONVERTSTRING) + if (lParam) + return w32_get_ime_reconversion_string (hwnd, wParam, + (RECONVERTSTRING*) lParam); + else + return w32_get_ime_reconversion_length (); + 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 + /* Check for messages registered at runtime. */ if (msg == msh_mousewheel) { *************** *** 4347,4352 **** --- 4443,4454 ---- x_default_parameter (f, parameters, Qfont, font, "font", "Font", RES_TYPE_STRING); + #ifdef USE_W32_IME + /* fix me. I don't know how to get a font name.*/ + x_default_parameter (f, parameters, Qime_font, font, + "ime-font", "IME-Font", RES_TYPE_STRING); + #endif + } x_default_parameter (f, parameters, Qborder_width, make_number (2), *************** *** 8114,8119 **** --- 8216,9158 ---- /*********************************************************************** + Input Method Editor + ***********************************************************************/ + #ifdef USE_W32_IME + #define MAX_CONVAGENT 100 + + typedef struct conversion_agent { + HIMC himc; + HWND hwnd; + } conversion_agent; + + static conversion_agent agent[MAX_CONVAGENT]; + static int conversion_agent_num = -1; + + BOOL fIME = FALSE; + + typedef BOOL (WINAPI *IMMGETOPENSTATUSPROC)(HIMC); + IMMGETOPENSTATUSPROC ImmGetOpenStatusProc; + + typedef BOOL (WINAPI *IMMSETOPENSTATUSPROC)(HIMC, BOOL); + IMMSETOPENSTATUSPROC ImmSetOpenStatusProc; + + typedef HWND (WINAPI *IMMGETDEFAULTIMEWNDPROC)(HWND); + IMMGETDEFAULTIMEWNDPROC ImmGetDefaultIMEWndProc; + + 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 BOOL (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; + + Lisp_Object Vime_control; + + static void + w32_set_ime_conv_window (f) + struct frame *f; + { + if (fIME && !NILP (Vime_control)) + { + HWND IMEhwnd; + COMPOSITIONFORM compform; + struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f)); + + IMEhwnd = (ImmGetDefaultIMEWndProc)(FRAME_W32_WINDOW (f)); + 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); + + 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)); + + compform.rcArea.bottom = (WINDOW_BOTTOM_EDGE_Y (w) + - WINDOW_MODE_LINE_HEIGHT (w)); + + SendMessage(IMEhwnd, WM_IME_CONTROL, (WPARAM)IMC_SETCOMPOSITIONWINDOW, + (LPARAM)(&compform)); + } + } + + static void + w32_set_ime_status (hwnd, openp) + HWND hwnd; + int openp; + { + HIMC himc; + + himc = (ImmGetContextProc) (hwnd); + (ImmSetOpenStatusProc) (himc, openp); + (ImmReleaseContextProc) (hwnd, himc); + } + + static int + w32_get_ime_status (hwnd) + HWND hwnd; + { + HIMC himc; + int ret; + + himc = (ImmGetContextProc) (hwnd); + ret = (ImmGetOpenStatusProc) (himc); + (ImmReleaseContextProc) (hwnd, himc); + + return ret; + } + + static int + w32_set_ime_mode (hwnd, mode, mask) + HWND hwnd; + int mode; + int mask; + { + HIMC himc; + DWORD cmode, smode; + + himc = (ImmGetContextProc) (hwnd); + if (!(ImmGetConversionStatusProc) (himc, &cmode, &smode)) + return 0; + + cmode = (cmode & (~mask)) | (mode & mask); + + (ImmSetConversionStatusProc) (himc, cmode, smode); + (ImmReleaseContextProc) (hwnd, himc); + + return 1; + } + + static BOOL + w32_get_ime_composition_string (hwnd) + HWND hwnd; + { + HIMC hIMC; + int size; + HANDLE himestr; + #ifdef _UNICODE + LPWSTR lpstr; + #else + LPSTR lpstr; + #endif + + struct frame *f; + + hIMC = (ImmGetContextProc) (hwnd); + if (!hIMC) + return FALSE; + + size = (ImmGetCompositionStringProc) (hIMC, GCS_RESULTSTR, NULL, 0); + #ifdef _UNICODE + size += sizeof (WCHAR); + #else + size += sizeof (CHAR); + #endif + 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 + LRESULT + w32_get_ime_reconversion_length () + { + int len, pt, pt_byte, start, end; + Lisp_Object str, point; + LRESULT lResult = 0; + #ifdef _UNICODE + int pos; + WCHAR *uc_code, *s; + #else + struct coding_system coding; + #endif + + pt = PT; + pt_byte = PT_BYTE; + + if (!NILP (current_buffer->read_only)) + return 0; + + if (!NILP (current_buffer->mark_active) + && !NILP (Vtransient_mark_mode)) + { + if (marker_position (current_buffer->mark) < PT) + { + start = marker_position (current_buffer->mark); + point = Fpoint (); + end = PT; + } + else + { + start = PT; + point = Fpoint (); + end = marker_position (current_buffer->mark); + } + } + else + { + if (NILP (Feobp ())) + Fforward_char (make_number (1)); + Fforward_word (make_number (-1)); + start = PT; + point = Fpoint (); + Fforward_word (make_number (1)); + end = PT; + } + str = make_buffer_string (start, end, 1); + if (!NILP (Ftext_property_any (make_number (0), + Flength (str), + intern ("read-only"), + Qt, + str))) + { + SET_PT_BOTH (pt, pt_byte); + return FALSE; /* Cannot signal here */ + } + #ifdef _UNICODE + uc_code = (WCHAR *) alloca ((SCHARS (str) + 1) * sizeof (WCHAR)); + s = uc_code; + for (pos = start; pos < end; pos++) + *s++ = (WCHAR) FETCH_CHAR (CHAR_TO_BYTE (pos)); + *s = (WCHAR) '\0'; + len = (lstrlenW (uc_code) + 1) * sizeof (WCHAR); + #else + str = Fdecode_coding_region (start, end, Vlocale_coding_system, Qt); + setup_coding_system (Fcheck_coding_system (Vlocale_coding_system), + &coding); + coding.mode |= (CODING_MODE_SAFE_ENCODING | CODING_MODE_LAST_BLOCK); + coding.common_flags &= ~CODING_ANNOTATION_MASK; + + coding.dst_bytes = SCHARS (str) * 2; + coding.destination = (unsigned char *) xmalloc (coding.dst_bytes + 1); + encode_coding_object (&coding, str, 0, 0, SCHARS (str), SBYTES (str), Qnil); + + len = coding.produced + 1; + xfree (coding.destination); + #endif + SET_PT_BOTH (pt, pt_byte); + + /* Return need size on reconverted string */ + lResult = sizeof (RECONVERTSTRING) + len; + return lResult; + } + + BOOL + w32_get_ime_reconversion_string (hwnd, wParam, reconv) + HWND hwnd; + WPARAM wParam; + RECONVERTSTRING *reconv; + { + HIMC hIMC; + int len, result, start, end; + Lisp_Object str, point; + struct w32_display_info *dpyinfo = &one_w32_display_info; + struct frame *f = x_window_to_frame (dpyinfo, hwnd); + #ifdef _UNICODE + int pos; + WCHAR *uc_code, *s; + #else + struct coding_system coding; + #endif + + if (!NILP (current_buffer->mark_active) + && !NILP (Vtransient_mark_mode)) + { + if (marker_position (current_buffer->mark) < PT) + { + start = marker_position (current_buffer->mark); + point = Fpoint (); + end = PT; + } + else + { + start = PT; + point = Fpoint (); + end = marker_position (current_buffer->mark); + } + } + else + { + if (NILP (Feobp ())) + Fforward_char (make_number (1)); + Fforward_word (make_number (-1)); + start = PT; + point = Fpoint (); + Fforward_word (make_number (1)); + end = PT; + } + + #ifdef _UNICODE + str = make_buffer_string (start, end, 0); + uc_code = (WCHAR *) alloca ((SCHARS (str) + 1) * sizeof (WCHAR)); + s = uc_code; + for (pos = start; pos < end; pos++) + *s++ = (WCHAR) FETCH_CHAR (CHAR_TO_BYTE (pos)); + *s = (WCHAR) '\0'; + len = lstrlenW (uc_code) + 1; + Fgoto_char (point); + + hIMC = (ImmGetContextProc) (hwnd); + if (!hIMC) + { + return FALSE; + } + + memcpy ((LPSTR) reconv + sizeof (RECONVERTSTRING), + uc_code, len * sizeof (WCHAR)); + #else + str = Fdecode_coding_region (start, end, Vlocale_coding_system, Qt); + setup_coding_system (Fcheck_coding_system (Vlocale_coding_system), + &coding); + coding.mode |= (CODING_MODE_SAFE_ENCODING | CODING_MODE_LAST_BLOCK); + coding.common_flags &= ~CODING_ANNOTATION_MASK; + + coding.dst_bytes = SCHARS (str) * 2; + coding.destination = (unsigned char *) xmalloc (coding.dst_bytes + 1); + encode_coding_object (&coding, str, 0, 0, SCHARS (str), SBYTES (str), Qnil); + coding.destination[coding.produced] = '\0'; + len = coding.produced; + Fgoto_char (point); + + hIMC = (ImmGetContextProc) (hwnd); + if (!hIMC) + { + xfree (coding.destination); + return FALSE; + } + strcpy ((LPSTR) reconv + sizeof (RECONVERTSTRING), coding.destination); + xfree (coding.destination); + #endif + reconv->dwStrLen = len; + reconv->dwStrOffset = sizeof (RECONVERTSTRING); + reconv->dwCompStrLen = len; + reconv->dwCompStrOffset = 0; + + /* Reconverted area is all of selected strings. */ + reconv->dwTargetStrLen = len; + reconv->dwTargetStrOffset = 0; + + #if 0 + /* Automatically adjust RECONVERTSTRING if not selected. */ + if (NILP (current_buffer->mark_active)) + (ImmSetCompositionStringProc) (hIMC, + SCS_QUERYRECONVERTSTRING, + (LPCVOID) reconv, + reconv->dwSize, + NULL, 0 ); + #endif + if ((ImmSetCompositionStringProc) (hIMC, + SCS_SETRECONVERTSTRING, + (LPCVOID) reconv, + reconv->dwSize, + NULL, 0)) + { + /* Delete the selected area. */ + del_range (start, end); + /* Set the position of candidate list dialog. */ + w32_set_ime_conv_window (f); + result = TRUE; + } + else + result = FALSE; + + (ImmReleaseContextProc) (hwnd, hIMC); + return result; + } + #endif /* RECONVERSION */ + + 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"); + ImmSetOpenStatusProc = + (IMMSETOPENSTATUSPROC) + GetProcAddress (hImm32, + "ImmSetOpenStatus"); + ImmGetDefaultIMEWndProc = + (IMMGETDEFAULTIMEWNDPROC) + GetProcAddress (hImm32, + "ImmGetDefaultIMEWnd"); + ImmGetContextProc = + (IMMGETCONTEXTPROC) + GetProcAddress (hImm32, + "ImmGetContext"); + ImmGetConversionStatusProc = + (IMMGETCONVERSIONSTATUSPROC) + GetProcAddress (hImm32, + "ImmGetConversionStatus"); + ImmSetConversionStatusProc = + (IMMSETCONVERSIONSTATUSPROC) + GetProcAddress (hImm32, + "ImmSetConversionStatus"); + ImmNotifyIMEProc = + (IMMNOTIFYIMEPROC) + GetProcAddress (hImm32, + "ImmNotifyIME"); + ImmReleaseContextProc = + (IMMRELEASECONTEXTPROC) + GetProcAddress (hImm32, + "ImmReleaseContext"); + ImmCreateContextProc = + (IMMCREATECONTEXTPROC) + GetProcAddress (hImm32, + "ImmCreateContext"); + ImmDestroyContextProc = + (IMMDESTROYCONTEXTPROC) + GetProcAddress (hImm32, + "ImmDestroyContext"); + ImmAssociateContextProc = + (IMMASSOCIATECONTEXTPROC) + GetProcAddress (hImm32, + "ImmAssociateContext"); + ImmGetHotKeyProc = + (IMMGETHOTKEYPROC) + GetProcAddress (hImm32, + "ImmGetHotKey"); + #ifdef _UNICODE + ImmGetCompositionStringProc = + (IMMGETCOMPOSITIONSTRINGPROC) + GetProcAddress (hImm32, "ImmGetCompositionStringW"); + ImmSetCompositionStringProc = + (IMMSETCOMPOSITIONSTRINGPROC) + GetProcAddress (hImm32, "ImmSetCompositionStringW"); + ImmSetCompositionFontProc = + (IMMSETCOMPOSITIONFONTPROC) + GetProcAddress (hImm32, "ImmSetCompositionFontW"); + ImmGetConversionListProc = + (IMMGETCONVERSIONLISTPROC) + GetProcAddress (hImm32, + "ImmGetConversionListW"); + ImmConfigureIMEProc = + (IMMCONFIGUREIMEPROC) + GetProcAddress (hImm32, + "ImmConfigureIMEW"); + ImmGetCandidateListProc = + (IMMGETCANDIDATELISTPROC) + GetProcAddress (hImm32, + "ImmGetCandidateListW"); + ImmGetCandidateListCountProc = + (IMMGETCANDIDATELISTCOUNTPROC) + GetProcAddress (hImm32, + "ImmGetCandidateListCountW"); + #else + ImmGetCompositionStringProc = + (IMMGETCOMPOSITIONSTRINGPROC) + GetProcAddress (hImm32, "ImmGetCompositionStringA"); + ImmSetCompositionStringProc = + (IMMSETCOMPOSITIONSTRINGPROC) + GetProcAddress (hImm32, "ImmSetCompositionStringA"); + ImmSetCompositionFontProc = + (IMMSETCOMPOSITIONFONTPROC) + GetProcAddress (hImm32, "ImmSetCompositionFontA"); + ImmGetConversionListProc = + (IMMGETCONVERSIONLISTPROC) + GetProcAddress (hImm32, + "ImmGetConversionListA"); + ImmConfigureIMEProc = + (IMMCONFIGUREIMEPROC) + GetProcAddress (hImm32, + "ImmConfigureIMEA"); + ImmGetCandidateListProc = + (IMMGETCANDIDATELISTPROC) + GetProcAddress (hImm32, + "ImmGetCandidateListA"); + ImmGetCandidateListCountProc = + (IMMGETCANDIDATELISTCOUNTPROC) + GetProcAddress (hImm32, + "ImmGetCandidateListCountA"); + #endif + + if (ImmGetOpenStatusProc && + ImmSetOpenStatusProc && + ImmGetDefaultIMEWndProc && + ImmGetCompositionStringProc && + ImmSetCompositionStringProc && + ImmSetCompositionFontProc && + ImmGetContextProc && + ImmGetConversionStatusProc && + ImmSetConversionStatusProc && + ImmGetConversionListProc && + ImmConfigureIMEProc && + ImmNotifyIMEProc && + ImmReleaseContextProc && + ImmCreateContextProc && + ImmDestroyContextProc && + ImmAssociateContextProc && + ImmGetCandidateListProc && + ImmGetCandidateListCountProc && + ImmGetHotKeyProc) + { + fIME = TRUE; + Vime_control = Qt; + } + } + } + + #ifdef HAVE_NTGUI + static void + w32_set_ime_font (hwnd, psetlf) + HWND hwnd; + LPLOGFONT psetlf; + { + HIMC himc; + if (fIME && psetlf && !NILP (Vime_control)) + { + himc = (ImmGetContextProc) (hwnd); + if (!himc) + return; + (ImmSetCompositionFontProc) (himc, psetlf); + (ImmReleaseContextProc) (hwnd, himc); + } + } + #endif /* HAVE_NTGUI */ + + /* From here, communication programs to make IME a conversion machine. */ + static HIMC + immcontext (context) + Lisp_Object context; + { + if (NUMBERP (context)) + return agent[XFASTINT (context)].himc; + else + return ((((unsigned long) XCAR (context)) << 16) | + (((unsigned long) XCDR (context)) & 0xffff)); + } + + 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_CREATE: + himc = (ImmCreateContextProc) (); + holdimc = (ImmAssociateContextProc) (hwnd, himc); + SetWindowLong (hwnd, 0, himc); + SetWindowLong (hwnd, 4, holdimc); + break; + + case WM_DESTROY: + holdimc = GetWindowLong (hwnd, 4); + himc = (ImmAssociateContextProc) (hwnd, holdimc); + (ImmDestroyContextProc) (himc); + break; + + case WM_MULE_IMM_SET_STATUS: + 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_GET_COMPOSITION_STRING: + return w32_get_ime_composition_string (hwnd); + + default: + return DefWindowProc (hwnd, message, wparam, lparam); + } + return 0; + } + + static int + initialize_conversion_agent () + { + int i; + WNDCLASS wc; + + for (i = 0;i < MAX_CONVAGENT;i++) + { + agent[i].hwnd = 0; + agent[i].himc = 0; + } + + wc.style = 0; + wc.lpfnWndProc = conversion_agent_wndproc; + wc.cbClsExtra = 0; + wc.cbWndExtra = sizeof(long) * 2; + wc.hInstance = hinst; + wc.hIcon = NULL; + wc.hCursor = NULL; + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = CONVAGENT_CLASS; + + if (!RegisterClass (&wc)) + return 0; + + return 1; + } + + + /* + Emacs Lisp function entries + */ + + DEFUN ("ime-force-on", Fime_force_on, Sime_force_on, 0, 1, 0, + doc: /* Force status of IME open. */) + (eventp) + 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. */) + (eventp) + 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. */) + () + { + 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. */) + (mode, frame) + Lisp_Object mode, 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 ("noconvert"))) + { + 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. */) + (reading, word) + Lisp_Object reading, 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; + } + + void + x_set_ime_font (f, arg, oldval) + struct frame *f; + Lisp_Object arg, oldval; + { + LOGFONT lf; + + CHECK_STRING (arg); + + if (!x_to_w32_font (SDATA (arg), &lf)) + error ("Font `%s' is not defined", SDATA (arg)); + SendMessage (FRAME_W32_WINDOW(f), + WM_MULE_IMM_SET_COMPOSITION_FONT, + (WPARAM) f, (LPARAM) &lf); + } + + void + w32_get_ime_logfont (hwnd) + HWND hwnd; + { + struct face *face, *dflt_face; + struct frame *f; + struct window *w; + struct w32_display_info *dpyinfo = &one_w32_display_info; + LOGFONT dflt_lf, lf; + Lisp_Object ime_font; + char *font_string; + int pos, pos_byte, c, face_id, dummy; + + f = x_window_to_frame (dpyinfo, hwnd); + + if (PT <= BEGV || PT > ZV) + { + ime_font = Fframe_parameter (Qnil, Qime_font); + if (!NILP (ime_font)) + font_string = SDATA (ime_font); + else + { + dflt_face = FACE_FROM_ID (f, DEFAULT_FACE_ID); + font_string = dflt_face->font_name; + } + } + else + { + pos = PT - 1; + /* This code is from Finternal_char_font(). */ + pos_byte = CHAR_TO_BYTE (pos); + c = FETCH_CHAR (pos_byte); + w = XWINDOW (FRAME_ROOT_WINDOW (f)); + + face_id = face_at_buffer_position (w, pos, -1, -1, &dummy, pos + 100, 0); + face = FACE_FROM_ID (f, face_id); + + face_id = FACE_FOR_CHAR (f, FACE_FROM_ID (f, face_id), c, pos, Qnil); + face = FACE_FROM_ID (f, face_id); + font_string = face->font_name; + } + + x_to_w32_font (font_string, &f->output_data.w32->ime_logfont); + + if (!(f->output_data.w32->ime_logfont.lfCharSet == SHIFTJIS_CHARSET + || f->output_data.w32->ime_logfont.lfCharSet == HANGEUL_CHARSET + || f->output_data.w32->ime_logfont.lfCharSet == CHINESEBIG5_CHARSET + || f->output_data.w32->ime_logfont.lfCharSet == GB2312_CHARSET)) + { + ime_font = Fframe_parameter (Qnil, Qime_font); + + if (!NILP (ime_font)) + { + int len; + + font_string = SDATA (ime_font); + x_to_w32_font (font_string, &dflt_lf); + + f->output_data.w32->ime_logfont.lfCharSet = dflt_lf.lfCharSet; + len = strlen (dflt_lf.lfFaceName); + strncpy (f->output_data.w32->ime_logfont.lfFaceName, dflt_lf.lfFaceName, LF_FACESIZE); + f->output_data.w32->ime_logfont.lfFaceName[len] = '\0'; + } + } + + /* Calculate the width automatically, otherwise it is too wide. */ + f->output_data.w32->ime_logfont.lfWidth = 0; + } + #endif /* USE_W32_IME */ + + + /*********************************************************************** w32 specialized functions ***********************************************************************/ *************** *** 8712,8717 **** --- 9751,9759 ---- x_set_cursor_color, x_set_cursor_type, x_set_font, + #ifdef USE_W32_IME + x_set_ime_font, + #endif x_set_foreground_color, x_set_icon_name, x_set_icon_type, *************** *** 8751,8756 **** --- 9793,9801 ---- DEFSYM (Qnone, "none"); DEFSYM (Qsuppress_icon, "suppress-icon"); DEFSYM (Qundefined_color, "undefined-color"); + #ifdef USE_W32_IME + DEFSYM (Qcancel_timer, "ime-font"); + #endif DEFSYM (Qcancel_timer, "cancel-timer"); DEFSYM (Qhyper, "hyper"); DEFSYM (Qsuper, "super"); *************** *** 9027,9032 **** --- 10072,10082 ---- versions of Windows) characters. */); Vw32_charset_info_alist = Qnil; + #ifdef USE_W32_IME + DEFVAR_LISP ("ime-control", &Vime_control, "IME control flag"); + Vime_control = Qnil; + #endif + DEFSYM (Qw32_charset_ansi, "w32-charset-ansi"); DEFSYM (Qw32_charset_symbol, "w32-charset-symbol"); DEFSYM (Qw32_charset_default, "w32-charset-default"); *************** *** 9110,9115 **** --- 10160,10172 ---- defsubr (&Sw32_toggle_lock_key); defsubr (&Sw32_window_exists_p); defsubr (&Sw32_find_bdf_fonts); + #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); + #endif defsubr (&Sfile_system_info); defsubr (&Sdefault_printer_name); *************** *** 9182,9195 **** { int button; button = MessageBox (NULL, ! "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 \" and\n" "\"continue\" inside GDB before clicking YES.)" #endif ! , "Emacs Abort Dialog", MB_ICONEXCLAMATION | MB_TASKMODAL | MB_SETFOREGROUND | MB_YESNO); switch (button) --- 10239,10252 ---- { int button; button = MessageBox (NULL, ! 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 \" and\n" "\"continue\" inside GDB before clicking YES.)" #endif ! ), TEXT("Emacs Abort Dialog"), MB_ICONEXCLAMATION | MB_TASKMODAL | MB_SETFOREGROUND | MB_YESNO); switch (button) Index: src/w32select.c =================================================================== RCS file: /cvsroot/emacs/emacs/src/w32select.c,v retrieving revision 1.29.2.12 diff -c -r1.29.2.12 w32select.c *** src/w32select.c 13 Jun 2007 21:05:52 -0000 1.29.2.12 --- src/w32select.c 1 Jul 2007 00:38:01 -0000 *************** *** 85,91 **** #include "character.h" #include "composite.h" - static HGLOBAL convert_to_handle_as_ascii (void); static HGLOBAL convert_to_handle_as_coded (Lisp_Object coding_system); static Lisp_Object render (Lisp_Object oformat); --- 85,90 ---- Index: src/w32term.c =================================================================== RCS file: /cvsroot/emacs/emacs/src/w32term.c,v retrieving revision 1.193.4.46 diff -c -r1.193.4.46 w32term.c *** src/w32term.c 29 Jun 2007 03:37:28 -0000 1.193.4.46 --- src/w32term.c 1 Jul 2007 00:38:09 -0000 *************** *** 128,134 **** Lisp_Object w32_display_name_list; ! #ifndef GLYPHSET /* Pre Windows 2000, this was not available, but define it here so that Emacs compiled on such a platform will run on newer versions. */ --- 128,134 ---- Lisp_Object w32_display_name_list; ! #if !defined(GLYPHSET) && (_WIN32_WINNT < 0x0500) /* Pre Windows 2000, this was not available, but define it here so that Emacs compiled on such a platform will run on newer versions. */ *************** *** 5180,5185 **** --- 5180,5259 ---- check_visibility = 1; break; + #ifdef USE_W32_IME + case WM_MULE_IME_STATUS: + f = x_window_to_frame (dpyinfo, msg.msg.hwnd); + + if (f && !f->iconified && f->visible) + { + inev.kind = NON_ASCII_KEYSTROKE_EVENT; + inev.code = VK_KANJI; + inev.modifiers = 0; + XSETFRAME (inev.frame_or_window, f); + inev.timestamp = msg.msg.time; + } + break; + + case WM_MULE_IME_REPORT: + { + #ifdef _UNICODE + LPWSTR lpStr; + #else + LPSTR lpStr; + #endif + struct input_event buf; + HANDLE hw32_ime_string = (HANDLE) msg.msg.wParam; + + f = (struct frame *) msg.msg.lParam; + if (f && !f->iconified && f->visible) + { + #ifdef _UNICODE + lpStr = (LPWSTR) hw32_ime_string; + #else + lpStr = (LPSTR) hw32_ime_string; + #endif + 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; + buf.code = *lpStr; + kbd_buffer_store_event (&buf); + lpStr++; + } + 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_IMM_SET_COMPOSITION_FONT: + { + extern w32_get_ime_logfont (HWND); + f = x_window_to_frame (dpyinfo, msg.msg.hwnd); + w32_get_ime_logfont (msg.msg.hwnd); + + PostMessage (msg.msg.hwnd, WM_MULE_IMM_SET_COMPOSITION_FONT_REPLY, + (LPARAM) f, + (WPARAM) &f->output_data.w32->ime_logfont); + break; + } + #endif /* USE_W32_IME */ + default: /* Check for messages registered at runtime. */ if (msg.msg.message == msh_mousewheel) *************** *** 5530,5535 **** --- 5604,5614 ---- struct frame *f = XFRAME (WINDOW_FRAME (w)); HWND hwnd = FRAME_W32_WINDOW (f); + #ifdef USE_W32_IME + if (f == FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame) + PostMessage (hwnd, + WM_MULE_IMM_SET_CONVERSION_WINDOW, (WPARAM) f, 0); + #endif w32_system_caret_x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x); w32_system_caret_y *************** *** 5841,5861 **** #endif /* USE_FONT_BACKEND */ - /*********************************************************************** - TODO: W32 Input Methods - ***********************************************************************/ - /* Listing missing functions from xterm.c helps diff stay in step. - - xim_destroy_callback (xim, client_data, call_data) - xim_open_dpy (dpyinfo, resource_name) - struct xim_inst_t - xim_instantiate_callback (display, client_data, call_data) - xim_initialize (dpyinfo, resource_name) - xim_close_dpy (dpyinfo) - - */ - - /* Calculate the absolute position in frame F from its current recorded position values and gravity. */ --- 5920,5925 ---- *************** *** 6997,7002 **** --- 7061,7069 ---- && SystemParametersInfo (SPI_GETFONTSMOOTHINGTYPE, 0, &smoothing_type, 0) && smoothing_type == FE_FONTSMOOTHINGCLEARTYPE; } + #ifdef USE_W32_IME + w32_ime_control_init(); + #endif } void Index: src/w32term.h =================================================================== RCS file: /cvsroot/emacs/emacs/src/w32term.h,v retrieving revision 1.57.2.12 diff -c -r1.57.2.12 w32term.h *** src/w32term.h 2 Jun 2007 22:06:44 -0000 1.57.2.12 --- src/w32term.h 1 Jul 2007 00:38:11 -0000 *************** *** 400,405 **** --- 400,410 ---- /* The background for which the above relief GCs were set up. They are changed only when a different background is involved. */ unsigned long relief_background; + + #ifdef USE_W32_IME + /* logfont for IME */ + LOGFONT ime_logfont; + #endif }; extern struct w32_output w32term_display; *************** *** 639,644 **** --- 644,745 ---- #define WM_EMACS_SETCURSOR (WM_EMACS_START + 19) #define WM_EMACS_END (WM_EMACS_START + 20) + #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 + + /* 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) + + /* 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_MESSAGE_END (WM_USER+2399) + #define MESSAGE_IMM_COM_P(message) \ + (((message) >= WM_MULE_IMM_MESSAGE_START) && \ + ((message) <= WM_MULE_IMM_MESSAGE_END)) + + #if 0 + /* For synchronization + to create conversion agent + between main thread and event loop. */ + #define WM_MULE_IME_CREATE_AGENT (WM_USER+2400) + #define WM_MULE_IME_CREATE_AGENT_REPLY (WM_USER+2401) + #define WM_MULE_IME_DESTROY_AGENT (WM_USER+2402) + #define WM_MULE_IME_DESTROY_AGENT_REPLY (WM_USER+2403) + #endif + #define CONVAGENT_CLASS "ConvAgent" + + #define WM_MULE_IMM_SET_COMPOSITION_FONT (WM_USER+2404) + #define WM_MULE_IMM_SET_COMPOSITION_FONT_REPLY (WM_USER+2405) + + #define WM_MULE_IMM_SET_CONVERSION_WINDOW (WM_USER+2406) + #if 0 + #define WM_MULE_IMM_SET_CONVERSION_WINDOW_REPLY (WM_USER+2407) + #endif + + #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) *************** *** 750,755 **** --- 851,882 ---- EXFUN (Fx_display_color_p, 1); EXFUN (Fx_display_grayscale_p, 1); + #ifdef USE_W32_IME + /* + You should avoid using this method to send message to the + message thread if possible. Although this method guarantee + message reachablity even when message thread has no window, + you must deal with any messages sent by this method + both in the thread message loop(W32read_socket) and + in the window procedure(normally w32_WndProc). + */ + #define SEND_MSGTHREAD_INFORM_MESSAGE(message, wparam, lparam) \ + do { \ + if (FRAME_W32_WINDOW(SELECTED_FRAME()) != INVALID_HANDLE_VALUE) \ + SendMessage(FRAME_W32_WINDOW(SELECTED_FRAME()), (message), \ + (wparam), (lparam)); \ + else \ + while (!PostThreadMessage (dwWindowsThreadId, (message), \ + (wparam), (lparam))) \ + sleep(1); \ + }while(0) + + #define WAIT_REPLY_MESSAGE(ret, msgno) \ + do { \ + GetMessage ((ret), NULL, 0, 0); \ + } while((ret)->message != (msgno)) + #endif /* USE_W32_IME */ + #define FONT_TYPE_FOR_UNIBYTE(font, ch) \ ((font)->bdf ? BDF_1D_FONT : ANSI_FONT) Index: src/window.c =================================================================== RCS file: /cvsroot/emacs/emacs/src/window.c,v retrieving revision 1.445.2.66 diff -c -r1.445.2.66 window.c *** src/window.c 11 Jun 2007 00:57:46 -0000 1.445.2.66 --- src/window.c 1 Jul 2007 00:38:19 -0000 *************** *** 224,229 **** --- 224,236 ---- static int inhibit_frame_unsplittable; #endif /* 0 */ + #ifdef USE_W32_IME + Lisp_Object Vset_selected_window_buffer_functions; + Lisp_Object Qset_selected_window_buffer_functions; + Lisp_Object Vselect_window_functions; + Lisp_Object Qselect_window_functions; + #endif + extern EMACS_INT scroll_margin; extern Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions; *************** *** 3396,3401 **** --- 3403,3421 ---- } set_window_buffer (window, buffer, 1, !NILP (keep_margins)); + + #ifdef USE_W32_IME + if (! NILP (Vset_selected_window_buffer_functions)) + { + Lisp_Object temp[4]; + temp[0] = Qset_selected_window_buffer_functions; + temp[1] = tem; + temp[2] = window; + temp[3] = buffer; + Frun_hook_with_args (4, temp); + } + #endif + return Qnil; } *************** *** 3417,3422 **** --- 3437,3445 ---- register struct window *w; register struct window *ow; struct frame *sf; + #ifdef USE_W32_IME + Lisp_Object oldwin = selected_window; + #endif CHECK_LIVE_WINDOW (window); *************** *** 3476,3481 **** --- 3499,3510 ---- } windows_or_buffers_changed++; + + #ifdef USE_W32_IME + if (!NILP (Vselect_window_functions)) + run_hook_with_args_2 (Qselect_window_functions, oldwin, window); + #endif + return window; } *************** *** 7280,7285 **** --- 7309,7324 ---- Qwindow_configuration_change_hook = intern ("window-configuration-change-hook"); + #ifdef USE_W32_IME + staticpro (&Qset_selected_window_buffer_functions); + Qset_selected_window_buffer_functions + = intern ("set-selected-window-buffer-functions"); + + staticpro (&Qselect_window_functions); + Qselect_window_functions + = intern ("select-window-functions"); + #endif + Qwindowp = intern ("windowp"); staticpro (&Qwindowp); *************** *** 7492,7497 **** --- 7531,7551 ---- The selected frame is the one whose configuration has changed. */); Vwindow_configuration_change_hook = Qnil; + #ifdef USE_W32_IME + DEFVAR_LISP ("select-window-functions", &Vselect_window_functions, + doc: /* "This is a hook when select-window is called. + The hook is called with two arguments OLD-WINDOW and NEW-WINDOW. */); + Vselect_window_functions = Qnil; + + DEFVAR_LISP ("set-selected-window-buffer-functions", + &Vset_selected_window_buffer_functions, + doc: /* "This is a hook when set-selected-window-buffer is called. + This is called with three arguments + OLD-BUFFER, NEW-WINDOW and NEW-BUFFER. + If NEW-WINDOW is first being set up, OLD-BUFFER is t. */); + Vset_selected_window_buffer_functions = Qnil; + #endif + defsubr (&Sselected_window); defsubr (&Sminibuffer_window); defsubr (&Swindow_minibuffer_p); --- /dev/null 2007-07-01 09:38:23.738324800 +0900 +++ lisp/international/w32-ime.el 2007-04-17 08:15:53.322745200 +0900 @@ -0,0 +1,226 @@ +;;;;; w32-ime.el ---- Meadow features for NTEmacs. +;; +;; Author H.Miyashita +;; +;;;;; + +(defgroup W32-IME nil + "w32-ime" + :group 'emacs) + +(defvar w32-last-selection nil + "It is stored the last data from Emacs.") + +;---------- + +(defvar w32-ime-on-hook nil + "Functions to eval when IME is turned on at least. +Even if IME state is not changed, these functiona are maybe called.") +(defvar w32-ime-off-hook nil + "Functions to eval when IME is turned off at least. +Even if IME state is not changed, these functiona are maybe called.") +(defvar w32-ime-buffer-switch-p t + "If this variable is nil, IME control when buffer is switched is disabled.") +(defvar w32-ime-show-mode-line t + "When t, mode line indicates IME state.") +(defvar w32-ime-mode-line-state-indicator "[O]" + "This is shown at the mode line. It is regarded as state of ime.") +(make-variable-buffer-local 'w32-ime-mode-line-state-indicator) +(put 'w32-ime-mode-line-state-indicator 'permanent-local t) +(defvar w32-ime-mode-line-state-indicator-list '("-" "[|]" "[O]") + "List of IME state indicator string.") +(defvar w32-ime-mode-line-format-original nil + "Original mode line format.") + +;; +;; Section: IME +;; + +;; ;; This is temporal solution. In the future, we will prepare +;; ;; dynamic configuration. +;; (defvar w32-ime-coding-system-language-environment-alist +;; '(("Japanese" . japanese-shift-jis) +;; ("Chinese-GB" . chinese-iso-8bit) +;; ("Chinese-BIG5" . chinese-big5) +;; ("Korean" . korean-iso-8bit))) + +;; +;; IME state indicator +;; +(global-set-key [kanji] 'ignore) +(global-set-key [compend] 'ignore) + +(defun wrap-function-to-control-ime + (function interactive-p interactive-arg &optional suffix) + "Wrap FUNCTION, and IME control is enabled when FUNCTION is called. +An original function is saved to FUNCTION-SUFFIX when suffix is string. +If SUFFIX is nil, \"-original\" is added. " + (let ((original-function + (intern (concat (symbol-name function) + (if suffix suffix "-original"))))) + (cond + ((not (fboundp original-function)) + (fset original-function + (symbol-function function)) + (fset function + (list + 'lambda '(&rest arguments) + (when interactive-p + (list 'interactive interactive-arg)) + (`(cond + ((and (ime-get-mode) + (equal current-input-method "W32-IME")) + (ime-force-off) + (unwind-protect + (apply '(, original-function) arguments) + (when (and (not (ime-get-mode)) + (equal current-input-method "W32-IME")) + (ime-force-on)))) + (t + (apply '(, original-function) + arguments)))))))))) + +(defvar w32-ime-toroku-region-yomigana nil + "* if this variable is string, toroku-region regard this value as yomigana.") + +(defun w32-ime-toroku-region (begin end) + (interactive "r") + (let ((string (buffer-substring begin end)) + (w32-ime-buffer-switch-p nil) + (reading w32-ime-toroku-region-yomigana)) + (unless (stringp reading) + (w32-set-ime-mode 'hiragana) + (setq reading + (read-multilingual-string + (format "Input reading of \"%s\": " string) nil "W32-IME"))) + (w32-ime-register-word-dialog reading string))) + +;; for IME management system. + +(defun w32-ime-sync-state (window) + (when w32-ime-buffer-switch-p + (with-current-buffer (window-buffer window) + (let* ((frame (window-frame window)) + (ime-state (ime-get-mode))) + (cond + ((and (not ime-state) + (equal current-input-method "W32-IME")) + (ime-force-on nil) + (run-hooks 'w32-ime-on-hook)) + ((and ime-state + (not (equal current-input-method "W32-IME"))) +;;; (when (= (w32-ime-undetermined-string-length) 0) + (ime-force-off nil) + (run-hooks 'w32-ime-off-hook))))))) + +(defun w32-ime-set-selected-window-buffer-hook (oldbuf newwin newbuf) + (w32-ime-sync-state newwin)) + +(defun w32-ime-select-window-hook (old new) + (w32-ime-sync-state new)) + +(defun w32-ime-mode-line-update () + (cond + (w32-ime-show-mode-line + (unless (window-minibuffer-p (selected-window)) + (setq w32-ime-mode-line-state-indicator + (nth (if (ime-get-mode) 1 2) + w32-ime-mode-line-state-indicator-list)))) + (t + (setq w32-ime-mode-line-state-indicator + (nth 0 w32-ime-mode-line-state-indicator-list)))) + (force-mode-line-update)) + +(defun w32-ime-init-mode-line-display () + (unless (member 'w32-ime-mode-line-state-indicator mode-line-format) + (setq w32-ime-mode-line-format-original + (default-value 'mode-line-format)) + (if (and (stringp (car mode-line-format)) + (string= (car mode-line-format) "-")) + (setq-default mode-line-format + (cons "" + (cons 'w32-ime-mode-line-state-indicator + (cdr mode-line-format)))) + (setq-default mode-line-format + (cons "" + (cons 'w32-ime-mode-line-state-indicator + mode-line-format)))) + (force-mode-line-update t))) + +;; (defun w32-ime-toggle () +;; (interactive) +;; (if (equal current-input-method "W32-IME") +;; (inactivate-input-method) +;; (activate-input-method "W32-IME"))) + +(defun w32-ime-initialize () +;; (cond +;; ((and (eq system-type 'windows-nt) +;; (eq window-system 'w32) +;; (featurep 'w32-ime)) +;; (let ((coding-system +;; (assoc-string current-language-environment +;; w32-ime-coding-system-language-environment-alist +;; t))) +;; (w32-ime-init-mode-line-display) +;; (w32-ime-mode-line-update) +;; (add-hook 'select-window-functions +;; 'w32-ime-select-window-hook) +;; (add-hook 'set-selected-window-buffer-functions +;; 'w32-ime-set-selected-window-buffer-hook) +;; (define-key global-map [kanji] 'w32-ime-toggle) +;; (define-key global-map [kanji] 'toggle-input-method) +;; (if coding-system +;; (set-keyboard-coding-system (cdr coding-system))))))) + (when (and (eq system-type 'windows-nt) + (eq window-system 'w32) + (featurep 'w32-ime)) + (w32-ime-init-mode-line-display) + (w32-ime-mode-line-update) + (add-hook 'select-window-functions + 'w32-ime-select-window-hook) + (add-hook 'set-selected-window-buffer-functions + 'w32-ime-set-selected-window-buffer-hook) + (define-key global-map [kanji] 'toggle-input-method) + (set-keyboard-coding-system 'utf-8))) + +(defun w32-ime-uninitialize () + (when (and (eq system-type 'windows-nt) + (eq window-system 'w32) + (featurep 'w32-ime)) + (setq-default mode-line-format + w32-ime-mode-line-format-original) + (force-mode-line-update t) + (remove-hook 'select-window-functions + 'w32-ime-select-window-hook) + (remove-hook 'set-selected-window-buffer-functions + 'w32-ime-set-selected-window-buffer-hook) + (define-key global-map [kanji] 'ignore))) + +(defun w32-ime-exit-from-minibuffer () + (inactivate-input-method) + (when (<= (minibuffer-depth) 1) + (remove-hook 'minibuffer-exit-hook 'w32-ime-exit-from-minibuffer))) + +(defun w32-ime-state-switch (&optional arg) + (if arg + (progn + (setq inactivate-current-input-method-function + 'w32-ime-state-switch) + (run-hooks 'input-method-activate-hook) + (run-hooks 'w32-ime-on-hook) + (setq describe-current-input-method-function nil) + (when (eq (selected-window) (minibuffer-window)) + (add-hook 'minibuffer-exit-hook 'w32-ime-exit-from-minibuffer)) + (ime-force-on)) + (setq current-input-method nil) + (run-hooks 'input-method-inactivate-hook) + (run-hooks 'w32-ime-off-hook) + (setq describe-current-input-method-function nil) + (ime-force-off)) + (w32-ime-mode-line-update)) + +(register-input-method "W32-IME" "Japanese" 'w32-ime-state-switch "" + "W32 System IME") + +(provide 'w32-ime)