changeset 12920:327e1264b9bf v8.0.1336

patch 8.0.1336: cannot use imactivatefunc() unless compiled with +xim commit https://github.com/vim/vim/commit/6315a9ae924d2104b61d1667ea71af3ac7cf48fa Author: Bram Moolenaar <Bram@vim.org> Date: Sat Nov 25 15:20:02 2017 +0100 patch 8.0.1336: cannot use imactivatefunc() unless compiled with +xim Problem: Cannot use imactivatefunc() unless compiled with +xim. Solution: Allow using imactivatefunc() when not compiled with +xim. (Yasuhiro Matsumoto, closes #2349)
author Christian Brabandt <cb@256bit.org>
date Sat, 25 Nov 2017 15:30:06 +0100
parents ddb76d6af5de
children dc69d522aa2a
files runtime/doc/mbyte.txt runtime/doc/options.txt src/Makefile src/mbyte.c src/option.c src/option.h src/structs.h src/testdir/Make_all.mak src/testdir/test_iminsert.vim src/version.c src/vim.h
diffstat 11 files changed, 146 insertions(+), 38 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/mbyte.txt
+++ b/runtime/doc/mbyte.txt
@@ -26,8 +26,9 @@ 6.  Fonts on MS-Windows			|mbyte-fonts-M
 7.  Input on X11			|mbyte-XIM|
 8.  Input on MS-Windows			|mbyte-IME|
 9.  Input with a keymap			|mbyte-keymap|
-10. Using UTF-8				|mbyte-utf8|
-11. Overview of options			|mbyte-options|
+10. Input with imactivatefunc()		|mbyte-func|
+11. Using UTF-8				|mbyte-utf8|
+12. Overview of options			|mbyte-options|
 
 NOTE: This file contains UTF-8 characters.  These may show up as strange
 characters or boxes when using another encoding.
@@ -1254,7 +1255,35 @@ Combining forms:
 ﭏ    0xfb4f  Xal  alef-lamed
 
 ==============================================================================
-10. Using UTF-8				*mbyte-utf8* *UTF-8* *utf-8* *utf8*
+10.  Input with imactivatefunc()				*mbyte-func*
+
+Vim has |imactivatefunc()| and |imstatusfunc()|. This is useful to
+activate/deativate input method from Vim in any way, also with an external
+command. For example, fcitx provide fcitx-remote command: >
+
+	set iminsert=2
+	set imsearch=2
+	set imcmdline
+
+	set imactivatefunc=ImActivate
+	function! ImActivate(active)
+	  if a:active
+	    call system('fcitx-remote -o')
+	  else
+	    call system('fcitx-remote -c')
+	  endif
+	endfunction
+
+	set imstatusfunc=ImStatus
+	function! ImStatus()
+	  return system('fcitx-remote')[0] is# '2'
+	endfunction
+
+Using this script, you can activate/deactivate XIM via Vim even when it is not
+compiled with |+xim|.
+
+==============================================================================
+11. Using UTF-8				*mbyte-utf8* *UTF-8* *utf-8* *utf8*
 							*Unicode* *unicode*
 The Unicode character set was designed to include all characters from other
 character sets.  Therefore it is possible to write text in any language using
@@ -1402,7 +1431,7 @@ not everybody is able to type a composin
 
 
 ==============================================================================
-11. Overview of options					*mbyte-options*
+12. Overview of options					*mbyte-options*
 
 These options are relevant for editing multi-byte files.  Check the help in
 options.txt for detailed information.
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -4256,8 +4256,7 @@ A jump table for the options with a shor
 'imactivatefunc' 'imaf'	string (default "")
 			global
 			{not in Vi}
-			{only available when compiled with |+xim| and
-			|+GUI_GTK|}
+			{only available when compiled with |+mbyte|}
 	This option specifies a function that will be called to
 	activate/inactivate Input Method.
 
@@ -4308,8 +4307,7 @@ A jump table for the options with a shor
 'imcmdline' 'imc'	boolean (default off)
 			global
 			{not in Vi}
-			{only available when compiled with the |+xim|,
-			|+multi_byte_ime| or |global-ime| features}
+			{only available when compiled with |+mbyte|}
 	When set the Input Method is always on when starting to edit a command
 	line, unless entering a search pattern (see 'imsearch' for that).
 	Setting this option is useful when your input method allows entering
@@ -4320,8 +4318,7 @@ A jump table for the options with a shor
 'imdisable' 'imd'	boolean (default off, on for some systems (SGI))
 			global
 			{not in Vi}
-			{only available when compiled with the |+xim|,
-			|+multi_byte_ime| or |global-ime| features}
+			{only available when compiled with |+mbyte|}
 	When set the Input Method is never used.  This is useful to disable
 	the IM when it doesn't work properly.
 	Currently this option is on by default for SGI/IRIX machines.  This
@@ -4336,8 +4333,6 @@ A jump table for the options with a shor
 		0	:lmap is off and IM is off
 		1	:lmap is ON and IM is off
 		2	:lmap is off and IM is ON
-	2 is available only when compiled with the |+multi_byte_ime|, |+xim|
-	or |global-ime|.
 	To always reset the option to zero when leaving Insert mode with <Esc>
 	this can be used: >
 		:inoremap <ESC> <ESC>:set iminsert=0<CR>
@@ -4350,6 +4345,10 @@ A jump table for the options with a shor
 	The value 0 may not work correctly with Athena and Motif with some XIM
 	methods.  Use 'imdisable' to disable XIM then.
 
+	You can set 'imactivatefunc' and 'imstatusfunc' to handle IME/XIM
+	via external command if vim is not compiled with the |+xim|,
+	|+multi_byte_ime| or |global-ime|.
+
 						*'imsearch'* *'ims'*
 'imsearch' 'ims'	number (default -1)
 			local to buffer
@@ -4372,8 +4371,7 @@ A jump table for the options with a shor
 'imstatusfunc' 'imsf'	string (default "")
 			global
 			{not in Vi}
-			{only available when compiled with |+xim| and
-			|+GUI_GTK|}
+			{only available when compiled with |+mbyte|}
 	This option specifies a function that is called to obtain the status
 	of Input Method.  It must return a positive number when IME is active.
 
--- a/src/Makefile
+++ b/src/Makefile
@@ -2190,6 +2190,7 @@ test_arglist \
 	test_highlight \
 	test_history \
 	test_hlsearch \
+	test_iminsert \
 	test_increment \
 	test_increment_dbcs \
 	test_ins_complete \
--- a/src/mbyte.c
+++ b/src/mbyte.c
@@ -4782,6 +4782,20 @@ iconv_end(void)
 
 #endif /* FEAT_MBYTE */
 
+#ifdef FEAT_EVAL
+    static void
+call_imactivatefunc(int active)
+{
+    char_u *argv[1];
+
+    if (active)
+	argv[0] = (char_u *)"1";
+    else
+	argv[0] = (char_u *)"0";
+    (void)call_func_retnr(p_imaf, 1, argv, FALSE);
+}
+#endif
+
 #if defined(FEAT_XIM) || defined(PROTO)
 
 # if defined(FEAT_GUI_GTK) || defined(PROTO)
@@ -4824,7 +4838,14 @@ im_set_active(int active)
     im_is_active = (active && !p_imdisable);
 
     if (im_is_active != was_active)
-	xim_reset();
+    {
+#ifdef FEAT_EVAL
+	if (p_imaf[0] != NUL)
+	    call_imactivatefunc(im_is_active);
+	else
+#endif
+	    xim_reset();
+    }
 }
 
     void
@@ -5666,15 +5687,7 @@ xim_reset(void)
 
 #  ifdef FEAT_EVAL
 	    if (p_imaf[0] != NUL)
-	    {
-		char_u *argv[1];
-
-		if (im_is_active)
-		    argv[0] = (char_u *)"1";
-		else
-		    argv[0] = (char_u *)"0";
-		(void)call_func_retnr(p_imaf, 1, argv, FALSE);
-	    }
+		call_imactivatefunc(im_is_active);
 	    else
 #  endif
 		if (im_activatekey_keyval != GDK_VoidSymbol)
@@ -6442,6 +6455,45 @@ xim_get_status_area_height(void)
 }
 # endif
 
+#else /* !defined(FEAT_XIM) */
+
+# ifndef FEAT_GUI_W32
+    int
+im_get_status()
+{
+#  ifdef FEAT_EVAL
+    if (p_imsf[0] != NUL)
+    {
+	int is_active;
+
+	/* FIXME: Don't execute user function in unsafe situation. */
+	if (exiting
+#   ifdef FEAT_AUTOCMD
+		|| is_autocmd_blocked()
+#   endif
+		)
+	    return FALSE;
+	/* FIXME: :py print 'xxx' is shown duplicate result.
+	 * Use silent to avoid it. */
+	++msg_silent;
+	is_active = call_func_retnr(p_imsf, 0, NULL, FALSE);
+	--msg_silent;
+	return (is_active > 0);
+    }
+#  endif
+    return FALSE;
+}
+
+    void
+im_set_active(int active)
+{
+#  ifdef(USE_IM_CONTROL) && defined(FEAT_EVAL)
+    if (p_imaf[0] != NUL)
+	call_imactivatefunc(p_imdisable ? FALSE : active);
+#  endif
+}
+# endif
+
 #endif /* FEAT_XIM */
 
 #if defined(FEAT_MBYTE) || defined(PROTO)
--- a/src/option.c
+++ b/src/option.c
@@ -1539,7 +1539,7 @@ static struct vimoption options[] =
 			    (char_u *)&p_ic, PV_NONE,
 			    {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT},
     {"imactivatefunc","imaf",P_STRING|P_VI_DEF|P_SECURE,
-# if defined(FEAT_EVAL) && defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
+#if defined(FEAT_EVAL) && defined(USE_IM_CONTROL)
 			    (char_u *)&p_imaf, PV_NONE,
 			    {(char_u *)"", (char_u *)NULL}
 # else
@@ -1582,7 +1582,7 @@ static struct vimoption options[] =
 			    {(char_u *)B_IMODE_USE_INSERT, (char_u *)0L}
 			    SCRIPTID_INIT},
     {"imstatusfunc","imsf",P_STRING|P_VI_DEF|P_SECURE,
-#if defined(FEAT_EVAL) && defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
+#if defined(FEAT_EVAL) && defined(USE_IM_CONTROL)
 			    (char_u *)&p_imsf, PV_NONE,
 			    {(char_u *)"", (char_u *)NULL}
 #else
--- a/src/option.h
+++ b/src/option.h
@@ -581,11 +581,13 @@ EXTERN char_u	*p_iconstring;	/* 'iconstr
 EXTERN int	p_ic;		/* 'ignorecase' */
 #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
 EXTERN char_u	*p_imak;	/* 'imactivatekey' */
+#define IM_ON_THE_SPOT		0L
+#define IM_OVER_THE_SPOT	1L
+EXTERN long	p_imst;		/* 'imstyle' */
+#endif
+#if defined(FEAT_EVAL) && defined(USE_IM_CONTROL)
 EXTERN char_u	*p_imaf;	/* 'imactivatefunc' */
 EXTERN char_u	*p_imsf;	/* 'imstatusfunc' */
-EXTERN long	p_imst;		/* 'imstyle' */
-# define IM_ON_THE_SPOT		0L
-# define IM_OVER_THE_SPOT	1L
 #endif
 #ifdef USE_IM_CONTROL
 EXTERN int	p_imcmdline;	/* 'imcmdline' */
--- a/src/structs.h
+++ b/src/structs.h
@@ -2091,12 +2091,8 @@ struct file_buffer
 #define B_IMODE_USE_INSERT -1	/*	Use b_p_iminsert value for search */
 #define B_IMODE_NONE 0		/*	Input via none */
 #define B_IMODE_LMAP 1		/*	Input via langmap */
-#ifndef USE_IM_CONTROL
-# define B_IMODE_LAST 1
-#else
-# define B_IMODE_IM 2		/*	Input via input method */
-# define B_IMODE_LAST 2
-#endif
+#define B_IMODE_IM 2		/*	Input via input method */
+#define B_IMODE_LAST 2
 
 #ifdef FEAT_KEYMAP
     short	b_kmap_state;	/* using "lmap" mappings */
--- a/src/testdir/Make_all.mak
+++ b/src/testdir/Make_all.mak
@@ -115,6 +115,7 @@ NEW_TESTS = test_arabic.res \
 	    test_highlight.res \
 	    test_history.res \
 	    test_hlsearch.res \
+	    test_iminsert.res \
 	    test_increment.res \
 	    test_increment_dbcs.res \
 	    test_ins_complete.res \
new file mode 100644
--- /dev/null
+++ b/src/testdir/test_iminsert.vim
@@ -0,0 +1,29 @@
+if !has('multi_byte')
+  finish
+endif
+
+source view_util.vim
+
+let s:imactivatefunc_called = 0
+let s:imstatusfunc_called = 0
+
+func IM_activatefunc(active)
+  let s:imactivatefunc_called = 1
+endfunc
+
+func IM_statusfunc()
+  let s:imstatusfunc_called = 1
+  return 0
+endfunc
+
+func Test_iminsert2()
+  set imactivatefunc=IM_activatefunc
+  set imstatusfunc=IM_statusfunc
+  set iminsert=2
+  normal! i
+  set iminsert=0
+  set imactivatefunc=
+  set imstatusfunc=
+  call assert_equal(1, s:imactivatefunc_called)
+  call assert_equal(1, s:imstatusfunc_called)
+endfunc
--- a/src/version.c
+++ b/src/version.c
@@ -772,6 +772,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1336,
+/**/
     1335,
 /**/
     1334,
--- a/src/vim.h
+++ b/src/vim.h
@@ -536,9 +536,7 @@ typedef unsigned long u8char_T;	    /* l
 /*
  * Check input method control.
  */
-#if defined(FEAT_XIM) \
-    || (defined(FEAT_GUI) && (defined(FEAT_MBYTE_IME) || defined(GLOBAL_IME))) \
-    || (defined(FEAT_GUI_MAC) && defined(FEAT_MBYTE))
+#if defined(FEAT_MBYTE)
 # define USE_IM_CONTROL
 #endif