# HG changeset patch # User Bram Moolenaar # Date 1372267085 -7200 # Node ID 3717d569027d8ec8b62e42e33f91333ac22ce6ba # Parent e285b27368d1e356e2802af04b65155b6ce1e82b updated for version 7.3.1248 Problem: Still have old hacking code for Input Method. Solution: Add 'imactivatefunc' and 'imstatusfunc' as a generic solution to Input Method activation. (Yukihiro Nakadaira) diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -3993,6 +3993,26 @@ A jump table for the options with a shor Can be overruled by using "\c" or "\C" in the pattern, see |/ignorecase|. + *'imactivatefunc'* *'imaf'* +'imactivatefunc' 'imaf' string (default "") + global + {not in Vi} + {only available when compiled with |+xim| and + |+GUI_GTK|} + This option specifies a function that will be called to + activate/inactivate Input Method. + + Example: > + function ImActivateFunc(active) + if a:active + ... do something + else + ... do something + endif + " return value is not used + endfunction + set imactivatefunc=ImActivateFunc +< *'imactivatekey'* *'imak'* 'imactivatekey' 'imak' string (default "") global @@ -4089,6 +4109,24 @@ 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. + *'imstatusfunc'* *'imsf'* +'imstatusfunc' 'imsf' string (default "") + global + {not in Vi} + {only available when compiled with |+xim| and + |+GUI_GTK|} + 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. + + Example: > + function ImStatusFunc() + let is_active = ...do something + return is_active ? 1 : 0 + endfunction + set imstatusfunc=ImStatusFunc +< + NOTE: This function is invoked very often. Keep it fast. + *'include'* *'inc'* 'include' 'inc' string (default "^\s*#\s*include") global or local to buffer |global-local| diff --git a/src/fileio.c b/src/fileio.c --- a/src/fileio.c +++ b/src/fileio.c @@ -9572,6 +9572,12 @@ unblock_autocmds() # endif } + int +is_autocmd_blocked() +{ + return autocmd_blocked != 0; +} + /* * Find next autocommand pattern that matches. */ diff --git a/src/mbyte.c b/src/mbyte.c --- a/src/mbyte.c +++ b/src/mbyte.c @@ -4447,7 +4447,7 @@ im_set_active(int active) { int was_active; - was_active = !!im_is_active; + was_active = !!im_get_status(); im_is_active = (active && !p_imdisable); if (im_is_active != was_active) @@ -5071,44 +5071,25 @@ xim_reset(void) { if (xic != NULL) { - /* - * The third-party imhangul module (and maybe others too) ignores - * gtk_im_context_reset() or at least doesn't reset the active state. - * Thus sending imactivatekey would turn it off if it was on before, - * which is clearly not what we want. Fortunately we can work around - * that for imhangul by sending GDK_Escape, but I don't know if it - * works with all IM modules that support an activation key :/ - * - * An alternative approach would be to destroy the IM context and - * recreate it. But that means loading/unloading the IM module on - * every mode switch, which causes a quite noticeable delay even on - * my rather fast box... - * * - * Moreover, there are some XIM which cannot respond to - * im_synthesize_keypress(). we hope that they reset by - * xim_shutdown(). - */ - if (im_activatekey_keyval != GDK_VoidSymbol && im_is_active) - im_synthesize_keypress(GDK_Escape, 0U); - gtk_im_context_reset(xic); - /* - * HACK for Ami: This sequence of function calls makes Ami handle - * the IM reset graciously, without breaking loads of other stuff. - * It seems to force English mode as well, which is exactly what we - * want because it makes the Ami status display work reliably. - */ - gtk_im_context_set_use_preedit(xic, FALSE); - if (p_imdisable) im_shutdown(); else { - gtk_im_context_set_use_preedit(xic, TRUE); xim_set_focus(gui.in_focus); - if (im_activatekey_keyval != GDK_VoidSymbol) + 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); + } + else if (im_activatekey_keyval != GDK_VoidSymbol) { if (im_is_active) { @@ -5268,6 +5249,20 @@ xim_queue_key_press_event(GdkEventKey *e int im_get_status(void) { + if (p_imsf[0] != NUL) + { + int is_active; + + /* FIXME: Don't execute user function in unsafe situation. */ + if (exiting || is_autocmd_blocked()) + 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); + } return im_is_active; } diff --git a/src/option.c b/src/option.c --- a/src/option.c +++ b/src/option.c @@ -1425,6 +1425,15 @@ static struct vimoption {"ignorecase", "ic", P_BOOL|P_VI_DEF, (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) + (char_u *)&p_imaf, PV_NONE, + {(char_u *)"", (char_u *)NULL} +# else + (char_u *)NULL, PV_NONE, + {(char_u *)NULL, (char_u *)0L} +# endif + SCRIPTID_INIT}, {"imactivatekey","imak",P_STRING|P_VI_DEF, #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK) (char_u *)&p_imak, PV_NONE, @@ -1467,6 +1476,15 @@ static struct vimoption {(char_u *)B_IMODE_NONE, (char_u *)0L} #endif SCRIPTID_INIT}, + {"imstatusfunc","imse",P_STRING|P_VI_DEF|P_SECURE, +# if defined(FEAT_EVAL) && defined(FEAT_XIM) && defined(FEAT_GUI_GTK) + (char_u *)&p_imsf, PV_NONE, + {(char_u *)"", (char_u *)NULL} +# else + (char_u *)NULL, PV_NONE, + {(char_u *)NULL, (char_u *)0L} +# endif + SCRIPTID_INIT}, {"include", "inc", P_STRING|P_ALLOCED|P_VI_DEF, #ifdef FEAT_FIND_ID (char_u *)&p_inc, PV_INC, diff --git a/src/option.h b/src/option.h --- a/src/option.h +++ b/src/option.h @@ -558,6 +558,8 @@ 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' */ +EXTERN char_u *p_imaf; /* 'imactivatefunc' */ +EXTERN char_u *p_imsf; /* 'imstatusfunc' */ #endif #ifdef USE_IM_CONTROL EXTERN int p_imcmdline; /* 'imcmdline' */ diff --git a/src/proto/fileio.pro b/src/proto/fileio.pro --- a/src/proto/fileio.pro +++ b/src/proto/fileio.pro @@ -49,6 +49,7 @@ int has_textchangedI __ARGS((void)); int has_insertcharpre __ARGS((void)); void block_autocmds __ARGS((void)); void unblock_autocmds __ARGS((void)); +int is_autocmd_blocked __ARGS((void)); char_u *getnextac __ARGS((int c, void *cookie, int indent)); int has_autocmd __ARGS((event_T event, char_u *sfname, buf_T *buf)); char_u *get_augroup_name __ARGS((expand_T *xp, int idx)); diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -729,6 +729,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1248, +/**/ 1247, /**/ 1246,