From 7495ee4378db1fd6526d96ef253b5f649272882c Mon Sep 17 00:00:00 2001 From: handa Date: Sun, 13 Feb 2011 23:23:03 +0000 Subject: [PATCH] (MIMExternalModule): New member 'name'. (load_external_module): Return value changed. (unload_external_module): New function. (fini_im_info): Use unload_external_module. (load_im_info): Adjuted for the change of load_external_module. (minput_list): New function. --- src/input.c | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 139 insertions(+), 19 deletions(-) diff --git a/src/input.c b/src/input.c index a4f6fe3..ae3021c 100644 --- a/src/input.c +++ b/src/input.c @@ -220,6 +220,7 @@ typedef MPlist *(*MIMExternalFunc) (MPlist *plist); typedef struct { + MSymbol name; void *handle; MPlist *func_list; /* function name vs (MIMExternalFunc *) */ } MIMExternalModule; @@ -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) @@ -5923,6 +5933,116 @@ 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. It is assured that each input + method in the returned list can be successfully opened by + #minput_open_im () function. + + @return + The returned value is a plist of this form: + ((LANGUAGE-NAME INPUT-METHOD-NAME) ...) +*/ +MPlist * +minput_list (MSymbol language) +{ + MPlist *plist, *pl, *p; + 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; + 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++; + } + } + } + if (MPLIST_TAIL_P (p) && num_maps > 0 && num_states > 0) + { + p = mplist (); + mplist_add (p, Msymbol, tag[1]); + mplist_add (p, Msymbol, tag[2]); + mplist_add (imlist, Mplist, p); + M17N_OBJECT_UNREF (p); + } + M17N_OBJECT_UNREF (imdata); + } + return imlist; +} + /*=*/ /*** @} */ /*=*/ -- 1.7.10.4