/* 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
typedef struct
{
+ MSymbol name;
void *handle;
MPlist *func_list; /* function name vs (MIMExternalFunc *) */
} MIMExternalModule;
static MInputMethodInfo *get_im_info (MSymbol, MSymbol, MSymbol, MSymbol);
\f
-void
+static void
fully_initialize ()
{
char *key_names[32]
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");
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;
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))
{
}
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
{
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);
}
-/* 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. */
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)
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)
{
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))
{
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;
}
}
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)
};
}
}
-
- 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;
}
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));
&& ic_info->key_head < ic_info->used)
{
MDEBUG_PRINT (" unhandled\n");
+ ic_info->state_hook = map->map_actions;
return -1;
}
{
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;
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)
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, ")");
}
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, ")");
}
\f
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 <stdio.h>
+#include <string.h>
+#include <m17n.h>
+
+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;
+}
+
/*=*/
/*** @} */
/*=*/
@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 ¤òÊÖ¤¹¡£ */
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)
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;
}