X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=src%2Finput.c;h=2de5547311bf64de17a67685c99a0c162b85773c;hb=02c5d90ea3694c6fa6422de2ad4cbdfda46ce854;hp=6fbd21d0d5639ee00d05fc4f1e9e7b21a20dfd7c;hpb=f2834223388500696694f941b9dbc8200e8e795a;p=m17n%2Fm17n-lib.git diff --git a/src/input.c b/src/input.c index 6fbd21d..2de5547 100644 --- a/src/input.c +++ b/src/input.c @@ -1,5 +1,5 @@ /* input.c -- input method module. - Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 National Institute of Advanced Industrial Science and Technology (AIST) Registration Number H15PRO112 @@ -220,6 +220,7 @@ typedef MPlist *(*MIMExternalFunc) (MPlist *plist); typedef struct { + MSymbol name; void *handle; MPlist *func_list; /* function name vs (MIMExternalFunc *) */ } MIMExternalModule; @@ -269,7 +270,7 @@ static int update_custom_info (void); static MInputMethodInfo *get_im_info (MSymbol, MSymbol, MSymbol, MSymbol); -void +static void fully_initialize () { char *key_names[32] @@ -401,7 +402,7 @@ fully_initialize () msymbol_put (alias[j], M_key_alias, alias[j + 1]); } - buf3[0] = 255; + buf3[0] = (char) 255; alias[0] = alias[3] = msymbol (buf3); alias[1] = one_char_symbol[255] = msymbol ("M-Delete"); alias[2] = msymbol ("A-Delete"); @@ -1200,13 +1201,17 @@ load_macros (MInputMethodInfo *im_info, MPlist *plist) return 0; } -/* Load an external module from PLIST into IM_INFO->externals. +/* Load an external module from PLIST, and return a pointer to + MIMExternalModule. + PLIST has this form: PLIST ::= ( MODULE-NAME FUNCTION * ) - IM_INFO->externals is a plist of MODULE-NAME vs (MIMExternalModule *). */ + IM_INFO->externals is a plist of MODULE-NAME vs (MIMExternalModule *). -static int -load_external_module (MInputMethodInfo *im_info, MPlist *plist) + On error, return NULL. */ + +static MIMExternalModule * +load_external_module (MPlist *plist) { void *handle; MSymbol module; @@ -1227,10 +1232,7 @@ load_external_module (MInputMethodInfo *im_info, MPlist *plist) handle = dlopen (module_file, RTLD_NOW); if (MFAILP (handle)) - { - fprintf (stderr, "%s\n", dlerror ()); - return -1; - } + return NULL; func_list = mplist (); MPLIST_DO (plist, MPLIST_NEXT (plist)) { @@ -1243,15 +1245,23 @@ load_external_module (MInputMethodInfo *im_info, MPlist *plist) } MSTRUCT_MALLOC (external, MERROR_IM); + external->name = module; external->handle = handle; external->func_list = func_list; - mplist_add (im_info->externals, module, external); - return 0; + return external; err_label: - dlclose (handle); M17N_OBJECT_UNREF (func_list); - return -1; + dlclose (handle); + return NULL; +} + +static void +unload_external_module (MIMExternalModule *external) +{ + dlclose (external->handle); + M17N_OBJECT_UNREF (external->func_list); + free (external); } static void @@ -1380,11 +1390,7 @@ fini_im_info (MInputMethodInfo *im_info) { MPLIST_DO (plist, im_info->externals) { - MIMExternalModule *external = MPLIST_VAL (plist); - - dlclose (external->handle); - M17N_OBJECT_UNREF (external->func_list); - free (external); + unload_external_module (MPLIST_VAL (plist)); MPLIST_KEY (plist) = Mt; } M17N_OBJECT_UNREF (im_info->externals); @@ -1566,7 +1572,7 @@ update_global_info (void) } -/* Return an IM_INFO for the an method specified by LANGUAGE, NAME, +/* Return an IM_INFO for the input method specified by LANGUAGE, NAME, and EXTRA. KEY, if not Mnil, tells which kind of information about the input method is necessary, and the returned IM_INFO may contain only that information. */ @@ -2290,9 +2296,13 @@ load_im_info (MPlist *plist, MInputMethodInfo *im_info) im_info->externals = mplist (); MPLIST_DO (elt, MPLIST_NEXT (elt)) { + MIMExternalModule *external; + if (MFAILP (MPLIST_PLIST_P (elt))) continue; - load_external_module (im_info, MPLIST_PLIST (elt)); + external = load_external_module (MPLIST_PLIST (elt)); + if (external) + mplist_add (im_info->externals, external->name, external); } } else if (key == Mstate) @@ -2395,6 +2405,10 @@ load_im_info (MPlist *plist, MInputMethodInfo *im_info) static int take_action_list (MInputContext *ic, MPlist *action_list); static void preedit_commit (MInputContext *ic, int need_prefix); +/* Shift to the state of name STATE_NAME. If STATE_NAME is `t', shift + to the previous state (if any). If STATE_NAME is `nil', shift to + the initial state. */ + static void shift_state (MInputContext *ic, MSymbol state_name) { @@ -2441,7 +2455,7 @@ shift_state (MInputContext *ic, MSymbol state_name) preedit_commit (ic, 0); mtext_cpy (ic_info->preedit_saved, ic->preedit); ic_info->state_pos = ic->cursor_pos; - if (state != orig_state) + if (state != orig_state || state_name == Mnil) { if (state == (MIMState *) MPLIST_VAL (im_info->states)) { @@ -2458,13 +2472,7 @@ shift_state (MInputContext *ic, MSymbol state_name) else ic->status = im_info->title; ic->status_changed = 1; - if (ic_info->map == ic_info->state->map - && ic_info->map->map_actions) - { - MDEBUG_PRINT1 (" [IM] [%s] init-actions:", - MSYMBOL_NAME (state->name)); - take_action_list (ic, ic_info->map->map_actions); - } + ic_info->state_hook = ic_info->map->map_actions; } } @@ -2996,9 +3004,6 @@ static int take_action_list (MInputContext *ic, MPlist *action_list) { MInputContextInfo *ic_info = (MInputContextInfo *) ic->info; - MPlist *candidate_list = ic->candidate_list; - int candidate_index = ic->candidate_index; - int candidate_show = ic->candidate_show; MTextProperty *prop; MPLIST_DO (action_list, action_list) @@ -3472,31 +3477,6 @@ take_action_list (MInputContext *ic, MPlist *action_list) }; } } - - if (ic->candidate_list) - { - M17N_OBJECT_UNREF (ic->candidate_list); - ic->candidate_list = NULL; - } - if (ic->cursor_pos > 0 - && (prop = mtext_get_property (ic->preedit, ic->cursor_pos - 1, - Mcandidate_list))) - { - ic->candidate_list = mtext_property_value (prop); - M17N_OBJECT_REF (ic->candidate_list); - ic->candidate_index - = (int) mtext_get_prop (ic->preedit, ic->cursor_pos - 1, - Mcandidate_index); - ic->candidate_from = mtext_property_start (prop); - ic->candidate_to = mtext_property_end (prop); - } - - if (candidate_list != ic->candidate_list) - ic->candidates_changed |= MINPUT_CANDIDATES_LIST_CHANGED; - if (candidate_index != ic->candidate_index) - ic->candidates_changed |= MINPUT_CANDIDATES_INDEX_CHANGED; - if (candidate_show != ic->candidate_show) - ic->candidates_changed |= MINPUT_CANDIDATES_SHOW_CHANGED; return 0; } @@ -3516,6 +3496,14 @@ handle_key (MInputContext *ic) MSymbol alias = Mnil; int i; + if (ic_info->state_hook) + { + MDEBUG_PRINT1 (" [IM] [%s] init-actions:", + MSYMBOL_NAME (ic_info->state->name)); + take_action_list (ic, ic_info->state_hook); + ic_info->state_hook = NULL; + } + MDEBUG_PRINT2 (" [IM] [%s] handle `%s'", MSYMBOL_NAME (ic_info->state->name), msymbol_name (key)); @@ -3606,6 +3594,7 @@ handle_key (MInputContext *ic) && ic_info->key_head < ic_info->used) { MDEBUG_PRINT (" unhandled\n"); + ic_info->state_hook = map->map_actions; return -1; } @@ -3788,7 +3777,7 @@ open_im (MInputMethod *im) { MInputMethodInfo *im_info = get_im_info (im->language, im->name, Mnil, Mnil); - if (! im_info || ! im_info->states) + if (! im_info || ! im_info->states || MPLIST_LENGTH (im_info->states) == 0) MERROR (MERROR_IM, -1); im->info = im_info; @@ -3897,7 +3886,37 @@ filter (MInputContext *ic, MSymbol key, void *arg) ic_info->key_unhandled = 0; do { - if (handle_key (ic) < 0) + MPlist *candidate_list = ic->candidate_list; + int candidate_index = ic->candidate_index; + int candidate_show = ic->candidate_show; + MTextProperty *prop; + int result = handle_key (ic); + + if (ic->candidate_list) + { + M17N_OBJECT_UNREF (ic->candidate_list); + ic->candidate_list = NULL; + } + if (ic->cursor_pos > 0 + && (prop = mtext_get_property (ic->preedit, ic->cursor_pos - 1, + Mcandidate_list))) + { + ic->candidate_list = mtext_property_value (prop); + M17N_OBJECT_REF (ic->candidate_list); + ic->candidate_index + = (int) mtext_get_prop (ic->preedit, ic->cursor_pos - 1, + Mcandidate_index); + ic->candidate_from = mtext_property_start (prop); + ic->candidate_to = mtext_property_end (prop); + } + if (candidate_list != ic->candidate_list) + ic->candidates_changed |= MINPUT_CANDIDATES_LIST_CHANGED; + if (candidate_index != ic->candidate_index) + ic->candidates_changed |= MINPUT_CANDIDATES_INDEX_CHANGED; + if (candidate_show != ic->candidate_show) + ic->candidates_changed |= MINPUT_CANDIDATES_SHOW_CHANGED; + + if (result < 0) { /* KEY was not handled. Delete it from the current key sequence. */ if (ic_info->used > 0) @@ -4004,24 +4023,24 @@ dump_im_map (MPlist *map_list, int indent) memset (prefix, 32, indent); prefix[indent] = '\0'; - fprintf (stderr, "(\"%s\" ", msymbol_name (key)); + fprintf (mdebug__output, "(\"%s\" ", msymbol_name (key)); if (map->map_actions) mdebug_dump_plist (map->map_actions, indent + 2); if (map->submaps) { MPLIST_DO (map_list, map->submaps) { - fprintf (stderr, "\n%s ", prefix); + fprintf (mdebug__output, "\n%s ", prefix); dump_im_map (map_list, indent + 2); } } if (map->branch_actions) { - fprintf (stderr, "\n%s (branch\n%s ", prefix, prefix); + fprintf (mdebug__output, "\n%s (branch\n%s ", prefix, prefix); mdebug_dump_plist (map->branch_actions, indent + 4); - fprintf (stderr, ")"); + fprintf (mdebug__output, ")"); } - fprintf (stderr, ")"); + fprintf (mdebug__output, ")"); } @@ -4035,16 +4054,16 @@ dump_im_state (MIMState *state, int indent) memset (prefix, 32, indent); prefix[indent] = '\0'; - fprintf (stderr, "(%s", msymbol_name (state->name)); + fprintf (mdebug__output, "(%s", msymbol_name (state->name)); if (state->map->submaps) { MPLIST_DO (map_list, state->map->submaps) { - fprintf (stderr, "\n%s ", prefix); + fprintf (mdebug__output, "\n%s ", prefix); dump_im_map (map_list, indent + 2); } } - fprintf (stderr, ")"); + fprintf (mdebug__output, ")"); } @@ -5916,6 +5935,153 @@ minput_save_config (void) return (ret < 0 ? -1 : 1); } +/***en + @brief List available input methods. + + The minput_list () function returns a list of currently available + input methods whose language is $LANGUAGE. If $LANGUAGE is #Mnil, + all input methods are listed. + + @return + The returned value is a plist of this form: + ((LANGUAGE-NAME INPUT-METHOD-NAME SANE) ...) + The third element SANE of each input method is #Mt if it can be + successfully used, or #Mnil if it has some problem (e.g. syntax + error of MIM file, unavailable external module, unavailable + including input method). */ + +#if EXAMPLE_CODE +#include +#include +#include + +int +main (int argc, char **argv) +{ + MPlist *imlist, *pl; + + M17N_INIT (); + imlist = minput_list ((argc > 1) ? msymbol (argv[1]) : Mnil); + for (pl = imlist; mplist_key (pl) != Mnil; pl = mplist_next (pl)) + { + MPlist *p = mplist_value (pl); + MSymbol lang, name, sane; + + lang = mplist_value (p); + p = mplist_next (p); + name = mplist_value (p); + p = mplist_next (p); + sane = mplist_value (p); + + printf ("%s %s %s\n", msymbol_name (lang), msymbol_name (name), + sane == Mt ? "ok" : "no"); + } + + m17n_object_unref (imlist); + M17N_FINI (); + exit (0); +} +#endif + +MPlist * +minput_list (MSymbol language) +{ + MPlist *plist, *pl; + MPlist *imlist = mplist (); + + MINPUT__INIT (); + plist = mdatabase_list (Minput_method, language, Mnil, Mnil); + if (! plist) + return imlist; + MPLIST_DO (pl, plist) + { + MDatabase *mdb = MPLIST_VAL (pl); + MSymbol *tag = mdatabase_tag (mdb); + MPlist *imdata, *p, *elm; + int num_maps = 0, num_states = 0; + + if (tag[2] == Mnil) + continue; + imdata = mdatabase_load (mdb); + if (! imdata) + continue; + MPLIST_DO (p, imdata) + if (MPLIST_PLIST_P (p)) + { + /* Check these basic functionarity: + All external modules (if any) are loadable. + All included input method (if any) are loadable. + At least one map is defined or included. + At least one state is defined or included. */ + MPlist *elt = MPLIST_PLIST (p); + MSymbol key; + + if (MFAILP (MPLIST_SYMBOL_P (elt))) + break; + key = MPLIST_SYMBOL (elt); + if (key == Mmap) + num_maps++; + else if (key == Mstate) + num_states++; + else if (key == Mmodule) + { + MPLIST_DO (elt, MPLIST_NEXT (elt)) + { + MIMExternalModule *external; + + if (MFAILP (MPLIST_PLIST_P (elt))) + break; + external = load_external_module (MPLIST_PLIST (elt)); + if (MFAILP (external)) + break; + unload_external_module (external); + } + if (! MPLIST_TAIL_P (elt)) + break; + } + else if (key == Minclude) + { + MInputMethodInfo *im_info; + + elt = MPLIST_NEXT (elt); + if (MFAILP (MPLIST_PLIST_P (elt))) + break; + im_info = get_im_info_by_tags (MPLIST_PLIST (elt)); + if (MFAILP (im_info)) + break; + elt = MPLIST_NEXT (elt); + if (MFAILP (MPLIST_SYMBOL_P (elt))) + break; + key = MPLIST_SYMBOL (elt); + if (key == Mmap) + { + if (! im_info->maps) + break; + num_maps++; + } + else if (key == Mstate) + { + if (! im_info->states) + break; + num_states++; + } + } + } + elm = mplist (); + mplist_add (elm, Msymbol, tag[1]); + mplist_add (elm, Msymbol, tag[2]); + if (MPLIST_TAIL_P (p) && num_maps > 0 && num_states > 0) + mplist_add (elm, Msymbol, Mt); + else + mplist_add (elm, Msymbol, Mnil); + mplist_push (imlist, Mplist, elm); + M17N_OBJECT_UNREF (elm); + M17N_OBJECT_UNREF (imdata); + } + M17N_OBJECT_UNREF (plist); + return imlist; +} + /*=*/ /*** @} */ /*=*/ @@ -6346,16 +6512,18 @@ minput_callback (MInputContext *ic, MSymbol command) @brief Dump an input method. The mdebug_dump_im () function prints the input method $IM in a - human readable way to the stderr. $INDENT specifies how many - columns to indent the lines but the first one. + human readable way to the stderr or to what specified by the + environment variable MDEBUG_OUTPUT_FILE. $INDENT specifies how + many columns to indent the lines but the first one. @return This function returns $IM. */ /***ja @brief ÆþÎϥ᥽¥Ã¥É¤ò¥À¥ó¥×¤¹¤ë. - ´Ø¿ô mdebug_dump_im () ¤ÏÆþÎϥ᥽¥Ã¥É $IM ¤ò stderr - ¤Ë¿Í´Ö¤Ë²ÄÆɤʷÁ¤Ç°õºþ¤¹¤ë¡£$INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£ + ´Ø¿ô mdebug_dump_im () ¤ÏÆþÎϥ᥽¥Ã¥É $IM ¤òɸ½à¥¨¥é¡¼½ÐÎϤ⤷¤¯¤Ï + ´Ä¶­ÊÑ¿ô MDEBUG_DUMP_FONT ¤Ç»ØÄꤵ¤ì¤¿¥Õ¥¡¥¤¥ë¤Ë¿Í´Ö¤Ë²ÄÆɤʷÁ¤Ç½Ð + ÎϤ¹¤ë¡£$INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£ @return ¤³¤Î´Ø¿ô¤Ï $IM ¤òÊÖ¤¹¡£ */ @@ -6370,7 +6538,7 @@ mdebug_dump_im (MInputMethod *im, int indent) memset (prefix, 32, indent); prefix[indent] = '\0'; - fprintf (stderr, "(input-method %s %s ", msymbol_name (im->language), + fprintf (mdebug__output, "(input-method %s %s ", msymbol_name (im->language), msymbol_name (im->name)); mdebug_dump_mtext (im_info->title, 0, 0); if (im->name != Mnil) @@ -6379,11 +6547,11 @@ mdebug_dump_im (MInputMethod *im, int indent) MPLIST_DO (state, im_info->states) { - fprintf (stderr, "\n%s ", prefix); + fprintf (mdebug__output, "\n%s ", prefix); dump_im_state (MPLIST_VAL (state), indent + 2); } } - fprintf (stderr, ")"); + fprintf (mdebug__output, ")"); return im; }