X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Finput.c;h=3cc1086f5774d90e9154486ff79d70b7a8c899d1;hb=398685e3214363bc831a7c29f89e466a96b71e4a;hp=4f1bc0cfd50a2a755fd0bd24e43b43d7bb528344;hpb=49a73c26dc79fbfd1f3c88e7ed3f49d8b1f4a0e5;p=m17n%2Fm17n-lib.git
diff --git a/src/input.c b/src/input.c
index 4f1bc0c..3cc1086 100644
--- a/src/input.c
+++ b/src/input.c
@@ -1,5 +1,5 @@
/* input.c -- input method module.
- Copyright (C) 2003, 2004, 2005
+ Copyright (C) 2003, 2004, 2005, 2006
National Institute of Advanced Industrial Science and Technology (AIST)
Registration Number H15PRO112
@@ -17,7 +17,7 @@
You should have received a copy of the GNU Lesser General Public
License along with the m17n library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
02111-1307, USA. */
/***en
@@ -91,33 +91,35 @@
- ÆâÉôÆþÎϥ᥽¥Ã¥É
- ÆâÉôÆþÎϥ᥽¥Ã¥É¤È¤Ï LANGUAGE ¤¬ @c Mnil °Ê³°¤Î¤â¤Î¤Ç¤¢¤ê¡¢¤½¤ÎËÜÂΤÏm17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë
-
- ¤È¤¤¤¦¥¿¥°¤òÉÕ¤±¤ÆÄêµÁ¤µ¤ì¤Æ¤¤¤ë¡£
- ¤³¤Î¼ï¤ÎÆþÎϥ᥽¥Ã¥É¤ËÂФ·¤Æ¡¢m17n ¥é¥¤¥Ö¥é¥ê¤Ç¤Ï
- CUI ÍÑ¤È GUI ÍѤ½¤ì¤¾¤ì¤ÎÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤ò¤¢¤é¤«¤¸¤áÄêµÁ¤·¤Æ¤¤¤ë¡£
- ¤³¤ì¤é¤Î¥É¥é¥¤¥Ð¤Ï m17n ¥é¥¤¥Ö¥é¥ê¼«ÂΤÎÆþÎϽèÍý¥¨¥ó¥¸¥ó¤òÍøÍѤ¹¤ë¡£
- m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë¤Ï¡¢ÆÃÄê¤Î¸À¸ìÀìÍѤǤʤ¤ÆþÎϥ᥽¥Ã¥É¤òÄêµÁ¤¹¤ë¤³¤È¤â¤Ç¤¡¢
- ¤½¤Î¤è¤¦¤ÊÆþÎϥ᥽¥Ã¥É¤Î LANGUAGE ¤Ï @c Mt ¤Ç¤¢¤ë¡£
-
- ÆâÉôÆþÎϥ᥽¥Ã¥É¤Ï¡¢¥æ¡¼¥¶¤ÎÆþÎÏ¥¤¥Ù¥ó¥È¤ËÂбþ¤·¤¿¥·¥ó¥Ü¥ë¤Ç¤¢¤ëÆþÎÏ¥¡¼¤ò¼õ¤±¼è¤ë¡£
- @c m17n @c ¥é¥¤¥Ö¥é¥ê ¤ÏÆþÎÏ¥¤¥Ù¥ó¥È¤¬¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ç¤É¤¦É½¸½¤µ¤ì¤Æ¤¤¤ë¤«¤òÃΤ뤳¤È¤¬¤Ç¤¤Ê¤¤¤Î¤Ç¡¢
- ÆþÎÏ¥¤¥Ù¥ó¥È¤«¤éÆþÎÏ¥¡¼¤Ø¤ÎÊÑ´¹¤Ï¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥Þ¤ÎÀÕǤ¤Ç¹Ô¤ï¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
- ¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï´Ø¿ô minput_event_to_key () ¤ÎÀâÌÀ¤ò»²¾È¡£
+ ÆâÉôÆþÎϥ᥽¥Ã¥É¤È¤Ï LANGUAGE ¤¬ @c Mnil °Ê³°¤Î¤â¤Î¤Ç¤¢¤ê¡¢¤½¤ÎËÜÂÎ
+ ¤Ïm17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë ¤È¤¤¤¦¥¿¥°¤òÉÕ
+ ¤±¤ÆÄêµÁ¤µ¤ì¤Æ¤¤¤ë¡£¤³¤Î¼ï¤ÎÆþÎϥ᥽¥Ã¥É¤ËÂФ·¤Æ¡¢m17n ¥é¥¤¥Ö¥é¥ê¤Ç
+ ¤ÏCUI ÍÑ¤È GUI ÍѤ½¤ì¤¾¤ì¤ÎÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤ò¤¢¤é¤«¤¸¤áÄêµÁ¤·¤Æ
+ ¤¤¤ë¡£¤³¤ì¤é¤Î¥É¥é¥¤¥Ð¤Ï m17n ¥é¥¤¥Ö¥é¥ê¼«ÂΤÎÆþÎϽèÍý¥¨¥ó¥¸¥ó¤òÍø
+ ÍѤ¹¤ë¡£m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë¤Ï¡¢ÆÃÄê¤Î¸À¸ìÀìÍѤǤʤ¤ÆþÎϥ᥽¥Ã¥É¤òÄê
+ µÁ¤¹¤ë¤³¤È¤â¤Ç¤¡¢¤½¤Î¤è¤¦¤ÊÆþÎϥ᥽¥Ã¥É¤Î LANGUAGE ¤Ï @c Mt ¤Ç¤¢¤ë¡£
+
+ ÆâÉôÆþÎϥ᥽¥Ã¥É¤Ï¡¢¥æ¡¼¥¶¤ÎÆþÎÏ¥¤¥Ù¥ó¥È¤ËÂбþ¤·¤¿¥·¥ó¥Ü¥ë¤Ç¤¢¤ëÆþ
+ ÎÏ¥¡¼¤ò¼õ¤±¼è¤ë¡£@c m17n @c ¥é¥¤¥Ö¥é¥ê ¤ÏÆþÎÏ¥¤¥Ù¥ó¥È¤¬¥¢¥×¥ê¥±¡¼
+ ¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ç¤É¤¦É½¸½¤µ¤ì¤Æ¤¤¤ë¤«¤òÃΤ뤳¤È¤¬¤Ç¤¤Ê¤¤¤Î¤Ç¡¢Æþ
+ ÎÏ¥¤¥Ù¥ó¥È¤«¤éÆþÎÏ¥¡¼¤Ø¤ÎÊÑ´¹¤Ï¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥Þ¤ÎÀÕǤ¤Ç
+ ¹Ô¤ï¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï´Ø¿ô minput_event_to_key () ¤Î
+ ÀâÌÀ¤ò»²¾È¡£
- ³°ÉôÆþÎϥ᥽¥Ã¥É
- ³°ÉôÆþÎϥ᥽¥Ã¥É¤È¤Ï LANGUAGE ¤¬ @c Mnil ¤Î¤â¤Î¤Ç¤¢¤ê¡¢¤½¤ÎËÜÂΤϳ°Éô¤Î¥ê¥½¡¼¥¹¤È¤·¤ÆÄêµÁ¤µ¤ì¤ë¡£
- ¡Ê¤¿¤È¤¨¤ÐX Window System ¤ÎXIM ¤Ê¤É¡£)
- ¤³¤Î¼ï¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢¥·¥ó¥Ü¥ë NAME ¤Ï@c Minput_driver
- ¤ò¥¡¼¤È¤¹¤ë¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Á¡¢¤½¤ÎÃͤÏÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£
- ¤³¤Î¤³¤È¤Ë¤è¤ê¡¢Å¬Àڤʥɥ饤¥Ð¤ò½àÈ÷¤¹¤ë¤³¤È¤Ë¤è¤Ã¤Æ¡¢¤¤¤«¤Ê¤ë¼ïÎà¤ÎÆþÎϥ᥽¥Ã¥É¤â
- @c m17n @c ¥é¥¤¥Ö¥é¥ê ¤ÎÏÈÁȤÎÃæ¤Ç°·¤¦»ö¤¬¤Ç¤¤ë¡£
+ ³°ÉôÆþÎϥ᥽¥Ã¥É¤È¤Ï LANGUAGE ¤¬ @c Mnil ¤Î¤â¤Î¤Ç¤¢¤ê¡¢¤½¤ÎËÜÂΤϳ°
+ Éô¤Î¥ê¥½¡¼¥¹¤È¤·¤ÆÄêµÁ¤µ¤ì¤ë¡£¡Ê¤¿¤È¤¨¤ÐX Window System ¤ÎXIM ¤Ê
+ ¤É¡£) ¤³¤Î¼ï¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢¥·¥ó¥Ü¥ë NAME ¤Ï@c Minput_driver ¤ò
+ ¥¡¼¤È¤¹¤ë¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Á¡¢¤½¤ÎÃͤÏÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó
+ ¥¿¤Ç¤¢¤ë¡£¤³¤Î¤³¤È¤Ë¤è¤ê¡¢Å¬Àڤʥɥ饤¥Ð¤ò½àÈ÷¤¹¤ë¤³¤È¤Ë¤è¤Ã¤Æ¡¢¤¤
+ ¤«¤Ê¤ë¼ïÎà¤ÎÆþÎϥ᥽¥Ã¥É¤â@c m17n @c ¥é¥¤¥Ö¥é¥ê ¤ÎÏÈÁȤÎÃæ¤Ç°·¤¦»ö
+ ¤¬¤Ç¤¤ë¡£
- ÍøÊØÀ¤Î´ÑÅÀ¤«¤é¡¢m17n X ¥é¥¤¥Ö¥é¥ê¤Ï XIM ¤Î OverTheSpot
- ¤ÎÆþÎÏ¥¹¥¿¥¤¥ë¤ò¼Â¸½¤¹¤ëÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤òÄ󶡤·¡¢¤Þ¤¿¥·¥ó¥Ü¥ë @c Mxim ¤Î
- @c Minput_driver ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤȤ·¤Æ¤½¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÝ»ý¤·¤Æ¤¤¤ë¡£
- ¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï m17n GUI API ¤Î¥É¥¥å¥á¥ó¥È¤ò»²¾È¤Î¤³¤È¡£
+ ÍøÊØÀ¤Î´ÑÅÀ¤«¤é¡¢m17n X ¥é¥¤¥Ö¥é¥ê¤Ï XIM ¤Î OverTheSpot ¤ÎÆþÎÏ¥¹¥¿
+ ¥¤¥ë¤ò¼Â¸½¤¹¤ëÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤òÄ󶡤·¡¢¤Þ¤¿¥·¥ó¥Ü¥ë @c Mxim ¤Î
+ @c Minput_driver ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤȤ·¤Æ¤½¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÝ»ý
+ ¤·¤Æ¤¤¤ë¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï m17n GUI API ¤Î¥É¥¥å¥á¥ó¥È¤ò»²¾È¤Î¤³¤È¡£
@@ -143,6 +145,7 @@
#include
#include
#include
+#include
#include "config.h"
@@ -162,6 +165,8 @@
static int mdebug_mask = MDEBUG_INPUT;
+static int fully_initialized;
+
static MSymbol Minput_method;
/** Symbols to load an input method data. */
@@ -169,11 +174,14 @@ static MSymbol Mtitle, Mmacro, Mmodule, Mstate, Minclude;
/** Symbols for actions. */
static MSymbol Minsert, Mdelete, Mmark, Mmove, Mpushback, Mundo, Mcall, Mshift;
-static MSymbol Mselect, Mshow, Mhide, Mcommit, Munhandle;
+static MSymbol Mselect, Mshow, Mhide, Mcommit, Munhandle, Mpop;
static MSymbol Mset, Madd, Msub, Mmul, Mdiv, Mequal, Mless, Mgreater;
static MSymbol Mless_equal, Mgreater_equal;
static MSymbol Mcond;
-static MSymbol Mplus, Mminus, Mstar, Mslush, Mand, Mor, Mnot;
+static MSymbol Mplus, Mminus, Mstar, Mslash, Mand, Mor, Mnot;
+
+/** Special action symbol. */
+static MSymbol Mat_reload;
static MSymbol M_candidates;
@@ -189,14 +197,16 @@ static MSymbol one_char_symbol[256];
static MSymbol M_key_alias;
-static MSymbol M_description, M_command, M_variable;
+static MSymbol Mdescription, Mcommand, Mvariable, Mglobal, Mconfig;
+
+static MSymbol M_gettext;
/** Structure to hold a map. */
struct MIMMap
{
/** List of actions to take when we reach the map. In a root map,
- the actions are executed only when there's no more key. */
+ the actions are executed only when there is no more key. */
MPlist *map_actions;
/** List of deeper maps. If NULL, this is a terminal map. */
@@ -231,246 +241,271 @@ struct MIMState
MIMMap *map;
};
-/* Lookup keys KEY1,2,3 in the nested plist PLIST, and return the
- value. */
-
-static MPlist *
-lookup_nested_list (MPlist *plist, MSymbol key1, MSymbol key2, MSymbol key3)
-{
- MSymbol key[3];
- int i;
-
- key[0] = key1, key[1] = key2, key[2] = key3;
- for (i = 0; i < 3; i++)
- {
- plist = mplist_find_by_value (plist, key[i]);
- if (! plist)
- return NULL;
- plist = MPLIST_NEXT (plist);
- plist = MPLIST_PLIST (plist);
- }
- return plist;
-}
+#define CUSTOM_FILE "config.mic"
-/* Set VAL for keys KEY1,2,3 in the nested plist PLIST. */
+static MPlist *load_im_info_keys;
-static MPlist *
-set_nested_list (MPlist *plist, MSymbol key1, MSymbol key2, MSymbol key3,
- MPlist *val)
-{
- MSymbol key[3];
- int i;
- MPlist *pl;
+/* List of input method information. The format is:
+ (LANGUAGE NAME t:IM_INFO ... ... ...) */
+static MPlist *im_info_list;
- key[0] = key1, key[1] = key2, key[2] = key3;
- for (i = 0; i < 3; i++)
- {
- pl = mplist_find_by_value (plist, key[i]);
- if (pl)
- {
- pl = MPLIST_NEXT (pl);
- plist = MPLIST_PLIST (pl);
- }
- else
- {
- pl = mplist_add (plist, Msymbol, key[i]);
- plist = mplist ();
- pl = mplist_add (pl, Mplist, plist);
- M17N_OBJECT_UNREF (plist);
- }
- }
- mplist_set (pl, Mplist, val);
- M17N_OBJECT_UNREF (val);
- return pl;
-}
+/* Database for user's customization file. */
+static MDatabase *im_custom_mdb;
-/* Parse PLIST as a value of nested list and return an adjusted list.
-
- PLIST has this form;
- (symbol:command
- plist:(symbol:KEY
- [ mtext:DESCRIPTION | symbol:nil ]
- ;; The remaining elements are checked CHECK_FUNC.
- ...)
- plist:(symbol:KEY
- [ mtext:DESCRIPTION | symbol:nil ]
- ;; The remaining elements are checked CHECK_FUNC.
- ...)
- ...)
+/* List of input method information loaded from im_custom_mdb. The
+ format is the same as im_info_list. */
+static MPlist *im_custom_list;
- GLOBAL is a global list. If a description text is missing, it is
- extracted from GLOBAL.
+/* List of input method information configured by
+ minput_config_command and minput_config_variable. The format is
+ the same as im_info_list. */
+static MPlist *im_config_list;
- The return value is a plist of this format:
- (symbol:KEY
- plist:([ mtext:DESCRIPTION | symbol:nil ]
- ...)
- symbol:KEY
- plist:([ mtext:DESCRIPTION | symbol:nil ]
- ...)
- ...)
+/* Global input method information. It points into the element of
+ im_info_list corresponding to LANGUAGE == `nil' and NAME ==
+ `global'. */
+static MInputMethodInfo *global_info;
- PLIST itself is unref-ed. */
+static int update_global_info (void);
+static int update_custom_info (void);
+static MInputMethodInfo *get_im_info (MSymbol, MSymbol, MSymbol, MSymbol);
-static MPlist *
-parse_nested_list_value (MPlist *plist, MPlist *global, MSymbol key,
- int (*check_func) (MPlist *))
+
+void
+fully_initialize ()
{
- MPlist *val, *pl, *p, *p0;
+ char *key_names[32]
+ = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ "BackSpace", "Tab", "Linefeed", "Clear", NULL, "Return", NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, "Escape", NULL, NULL, NULL, NULL };
+ char buf[6], buf2[32];
+ int i, j;
+ /* Maximum case: C-M-a, C-M-A, M-Return, C-A-a, C-A-A, A-Return. */
+ MSymbol alias[7];
- val = mplist ();
- if (! MPLIST_PLIST_P (plist))
+ M_key_alias = msymbol (" key-alias");
+
+ buf[0] = 'C';
+ buf[1] = '-';
+ buf[3] = '\0';
+ for (i = 0, buf[2] = '@'; i < ' '; i++, buf[2]++)
{
- M17N_OBJECT_UNREF (plist);
- return val;
+ one_char_symbol[i] = msymbol (buf);
+ if (key_names[i] || (buf[2] >= 'A' && buf[2] <= 'Z'))
+ {
+ j = 0;
+ alias[j++] = one_char_symbol[i];
+ if (key_names[i])
+ {
+ /* Ex: `Escape' == `C-[' */
+ alias[j++] = msymbol (key_names[i]);
+ }
+ if (buf[2] >= 'A' && buf[2] <= 'Z')
+ {
+ /* Ex: `C-a' == `C-A' */
+ buf[2] += 32;
+ alias[j++] = msymbol (buf);
+ buf[2] -= 32;
+ }
+ /* Establish cyclic alias chain. */
+ alias[j] = alias[0];
+ while (--j >= 0)
+ msymbol_put (alias[j], M_key_alias, alias[j + 1]);
+ }
}
- pl = MPLIST_PLIST (plist);
- if (! MPLIST_SYMBOL_P (pl)
- || MPLIST_SYMBOL (pl) != key)
+ buf[0] = 'S';
+ for (i = buf[2] = ' '; i < 127; i++, buf[2]++)
{
- M17N_OBJECT_UNREF (plist);
- return val;
+ one_char_symbol[i] = msymbol (buf + 2);
+ if (i >= 'A' && i <= 'Z')
+ {
+ /* Ex: `A' == `S-A' == `S-a'. */
+ alias[0] = alias[3] = one_char_symbol[i];
+ alias[1] = msymbol (buf);
+ buf[2] += 32;
+ alias[2] = msymbol (buf);
+ buf[2] -= 32;
+ for (j = 0; j < 3; j++)
+ msymbol_put (alias[j], M_key_alias, alias[j + 1]);
+ }
}
+ buf[0] = 'C';
- MPLIST_DO (pl, MPLIST_NEXT (pl))
- {
- MSymbol name;
- MPlist *global_def = NULL;
+ alias[0] = alias[2] = one_char_symbol[127] = msymbol ("Delete");
+ alias[1] = msymbol ("C-?");
+ for (j = 0; j < 2; j++)
+ msymbol_put (alias[j], M_key_alias, alias[j + 1]);
- if (! MPLIST_PLIST_P (pl))
- continue;
- p = MPLIST_PLIST (pl);
- if (! MPLIST_SYMBOL_P (p))
- continue;
- name = MPLIST_SYMBOL (p);
- p = MPLIST_NEXT (p);
- if (MPLIST_TAIL_P (p))
+ buf[3] = '-';
+ buf[5] = '\0';
+ buf2[1] = '-';
+ for (i = 128, buf[4] = '@'; i < 160; i++, buf[4]++)
+ {
+ j = 0;
+ /* `C-M-a' == `C-A-a' */
+ buf[2] = 'M';
+ alias[j++] = one_char_symbol[i] = msymbol (buf);
+ buf[2] = 'A';
+ alias[j++] = msymbol (buf);
+ if (key_names[i - 128])
{
- if (! global)
- continue;
- global_def = mplist_find_by_value (global, name);
- if (! global_def)
- continue;
- global_def = MPLIST_PLIST (MPLIST_NEXT (global_def));
- mplist__conc (p, global_def);
+ /* Ex: `M-Escape' == `A-Escape' == `C-M-['. */
+ buf2[0] = 'M';
+ strcpy (buf2 + 2, key_names[i - 128]);
+ alias[j++] = msymbol (buf2);
+ buf2[0] = 'A';
+ alias[j++] = msymbol (buf2);
}
- p0 = MPLIST_NEXT (p);
- if (MPLIST_TAIL_P (p0))
+ if (buf[4] >= 'A' && buf[4] <= 'Z')
{
- if (! global || global_def)
- continue;
- global_def = mplist_find_by_value (global, name);
- if (! global_def)
- continue;
- global_def = MPLIST_PLIST (MPLIST_NEXT (global_def));
- global_def = MPLIST_NEXT (global_def);
- if (MPLIST_TAIL_P (global_def))
- continue;
- mplist__conc (p0, global_def);
+ /* Ex: `C-M-a' == `C-M-A'. */
+ buf[4] += 32;
+ buf[2] = 'M';
+ alias[j++] = msymbol (buf);
+ buf[2] = 'A';
+ alias[j++] = msymbol (buf);
+ buf[4] -= 32;
}
- if ((*check_func) (p0) < 0)
- continue;
- mplist_add (val, Msymbol, name);
- mplist_add (val, Mplist, p);
+ /* Establish cyclic alias chain. */
+ alias[j] = alias[0];
+ while (--j >= 0)
+ msymbol_put (alias[j], M_key_alias, alias[j + 1]);
+ }
+ for (i = 160, buf[4] = ' '; i < 256; i++, buf[4]++)
+ {
+ buf[2] = 'M';
+ alias[0] = alias[2] = one_char_symbol[i] = msymbol (buf + 2);
+ buf[2] = 'A';
+ alias[1] = msymbol (buf + 2);
+ for (j = 0; j < 2; j++)
+ msymbol_put (alias[j], M_key_alias, alias[j + 1]);
}
- M17N_OBJECT_UNREF (plist);
- return val;
-}
+ alias[0] = alias[4] = one_char_symbol[255] = msymbol ("M-Delete");
+ alias[1] = msymbol ("A-Delete");
+ alias[2] = msymbol ("C-M-?");
+ alias[3] = msymbol ("C-A-?");
+ for (j = 0; j < 4; j++)
+ msymbol_put (alias[j], M_key_alias, alias[j + 1]);
+
+ Minput_method = msymbol ("input-method");
+ Mtitle = msymbol ("title");
+ Mmacro = msymbol ("macro");
+ Mmodule = msymbol ("module");
+ Mmap = msymbol ("map");
+ Mstate = msymbol ("state");
+ Minclude = msymbol ("include");
+ Minsert = msymbol ("insert");
+ M_candidates = msymbol (" candidates");
+ Mdelete = msymbol ("delete");
+ Mmove = msymbol ("move");
+ Mmark = msymbol ("mark");
+ Mpushback = msymbol ("pushback");
+ Mpop = msymbol ("pop");
+ Mundo = msymbol ("undo");
+ Mcall = msymbol ("call");
+ Mshift = msymbol ("shift");
+ Mselect = msymbol ("select");
+ Mshow = msymbol ("show");
+ Mhide = msymbol ("hide");
+ Mcommit = msymbol ("commit");
+ Munhandle = msymbol ("unhandle");
+ Mset = msymbol ("set");
+ Madd = msymbol ("add");
+ Msub = msymbol ("sub");
+ Mmul = msymbol ("mul");
+ Mdiv = msymbol ("div");
+ Mequal = msymbol ("=");
+ Mless = msymbol ("<");
+ Mgreater = msymbol (">");
+ Mless_equal = msymbol ("<=");
+ Mgreater_equal = msymbol (">=");
+ Mcond = msymbol ("cond");
+ Mplus = msymbol ("+");
+ Mminus = msymbol ("-");
+ Mstar = msymbol ("*");
+ Mslash = msymbol ("/");
+ Mand = msymbol ("&");
+ Mor = msymbol ("|");
+ Mnot = msymbol ("!");
-static MPlist *variable_list, *command_list;
-static int check_variable_list (MPlist *plist);
-static int check_command_list (MPlist *plist);
-static MPlist *load_partial_im_info (MSymbol language, MSymbol name,
- MSymbol extra, MSymbol key);
+ Mat_reload = msymbol ("@reload");
-static MPlist *
-get_nested_list (MSymbol language, MSymbol name, MSymbol extra, MSymbol key)
-{
- MPlist *total_list;
- int (*check_func) (MPlist *);
- MPlist *plist, *global;
+ Mcandidates_group_size = msymbol ("candidates-group-size");
+ Mcandidates_charset = msymbol ("candidates-charset");
- if (key == M_variable)
- {
- if (! variable_list)
- variable_list = mplist ();
- total_list = variable_list;
- check_func = check_variable_list;
- }
- else
- {
- if (! command_list)
- command_list = mplist ();
- total_list = command_list;
- check_func = check_command_list;
- }
+ Mcandidate_list = msymbol_as_managing_key (" candidate-list");
+ Mcandidate_index = msymbol (" candidate-index");
- if (MPLIST_TAIL_P (total_list))
- {
- plist = load_partial_im_info (Mt, Mnil, key, key);
- if (plist)
- global = parse_nested_list_value (plist, NULL, key, check_func);
- else
- global = mplist ();
- set_nested_list (total_list, Mt, Mnil, key, global);
- }
- else
- global = lookup_nested_list (total_list, Mt, Mnil, key);
+ Minit = msymbol ("init");
+ Mfini = msymbol ("fini");
- if (name == Mnil)
- return global;
+ Mdescription = msymbol ("description");
+ Mcommand = msymbol ("command");
+ Mvariable = msymbol ("variable");
+ Mglobal = msymbol ("global");
+ Mconfig = msymbol ("config");
+ M_gettext = msymbol ("_");
- plist = lookup_nested_list (total_list, language, name, extra);
- if (plist)
- return plist;
+ load_im_info_keys = mplist ();
+ mplist_add (load_im_info_keys, Mstate, Mnil);
+ mplist_push (load_im_info_keys, Mmap, Mnil);
- plist = load_partial_im_info (language, name, extra, key);
- if (plist)
- plist = parse_nested_list_value (plist, global, key, check_func);
- else
- plist = mplist ();
- set_nested_list (total_list, language, name, extra, plist);
- return plist;
+ im_info_list = mplist ();
+ im_config_list = im_custom_list = NULL;
+ im_custom_mdb = NULL;
+ update_custom_info ();
+ global_info = NULL;
+ update_global_info ();
+
+ fully_initialized = 1;
}
+#define MINPUT__INIT() \
+ do { \
+ if (! fully_initialized) \
+ fully_initialize (); \
+ } while (0)
+
+
static int
-marker_code (MSymbol sym)
+marker_code (MSymbol sym, int surrounding)
{
char *name;
if (sym == Mnil)
return -1;
name = MSYMBOL_NAME (sym);
- return ((name[0] == '@'
- && ((name[1] >= '0' && name[1] <= '9')
- || name[1] == '<' || name[1] == '>'
- || name[1] == '=' || name[1] == '+' || name[1] == '-'
- || name[1] == '[' || name[1] == ']'
- || name[1] == '@')
- && name[2] == '\0')
- ? name[1] : -1);
+ return (name[0] != '@' ? -1
+ : (((name[1] >= '0' && name[1] <= '9')
+ || name[1] == '<' || name[1] == '>' || name[1] == '='
+ || name[1] == '[' || name[1] == ']'
+ || name[1] == '@')
+ && name[2] == '\0') ? name[1]
+ : (name[1] != '+' && name[1] != '-') ? -1
+ : (name[2] == '\0' || surrounding) ? name[1]
+ : -1);
}
static MPlist *
resolve_variable (MInputContextInfo *ic_info, MSymbol var)
{
- MPlist *p;
+ MPlist *plist = mplist__assq (ic_info->vars, var);
- MPLIST_DO (p, ic_info->vars)
- {
- if (MPLIST_SYMBOL (p) == var)
- break;
- p = MPLIST_NEXT (p);
- }
- if (MPLIST_TAIL_P (p))
+ if (plist)
{
- p = ic_info->vars;
- mplist_push (p, Minteger, (void *) 0);
- mplist_push (p, Msymbol, var);
+ plist = MPLIST_PLIST (plist);
+ return MPLIST_NEXT (plist);
}
- return (MPLIST_NEXT (p));
+
+ plist = mplist ();
+ mplist_push (ic_info->vars, Mplist, plist);
+ M17N_OBJECT_UNREF (plist);
+ plist = mplist_add (plist, Msymbol, var);
+ plist = mplist_add (plist, Minteger, (void *) 0);
+ return plist;
}
static MText *
@@ -479,12 +514,10 @@ get_surrounding_text (MInputContext *ic, int len)
MText *mt = NULL;
mplist_push (ic->plist, Minteger, (void *) len);
- minput__callback (ic, Minput_get_surrounding_text);
- if (MPLIST_MTEXT_P (ic->plist))
- {
- mt = MPLIST_MTEXT (ic->plist);
- mplist_pop (ic->plist);
- }
+ if (minput_callback (ic, Minput_get_surrounding_text) >= 0
+ && MPLIST_MTEXT_P (ic->plist))
+ mt = MPLIST_MTEXT (ic->plist);
+ mplist_pop (ic->plist);
return mt;
}
@@ -494,12 +527,18 @@ delete_surrounding_text (MInputContext *ic, int pos)
MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
mplist_push (ic->plist, Minteger, (void *) pos);
- minput__callback (ic, Minput_delete_surrounding_text);
+ minput_callback (ic, Minput_delete_surrounding_text);
mplist_pop (ic->plist);
if (pos < 0)
- M17N_OBJECT_UNREF (ic_info->preceding_text);
+ {
+ M17N_OBJECT_UNREF (ic_info->preceding_text);
+ ic_info->preceding_text = NULL;
+ }
else if (pos > 0)
- M17N_OBJECT_UNREF (ic_info->following_text);
+ {
+ M17N_OBJECT_UNREF (ic_info->following_text);
+ ic_info->following_text = NULL;
+ }
}
static int
@@ -509,7 +548,7 @@ get_preceding_char (MInputContext *ic, int pos)
MText *mt;
int len;
- if (ic_info->preceding_text)
+ if (pos && ic_info->preceding_text)
{
len = mtext_nchars (ic_info->preceding_text);
if (pos <= len)
@@ -517,7 +556,7 @@ get_preceding_char (MInputContext *ic, int pos)
}
mt = get_surrounding_text (ic, - pos);
if (! mt)
- return -1;
+ return -2;
len = mtext_nchars (mt);
if (ic_info->preceding_text)
{
@@ -526,6 +565,8 @@ get_preceding_char (MInputContext *ic, int pos)
M17N_OBJECT_UNREF (ic_info->preceding_text);
ic_info->preceding_text = mt;
}
+ else
+ M17N_OBJECT_UNREF (mt);
}
else
ic_info->preceding_text = mt;
@@ -549,7 +590,7 @@ get_following_char (MInputContext *ic, int pos)
}
mt = get_surrounding_text (ic, pos);
if (! mt)
- return -1;
+ return -2;
len = mtext_nchars (mt);
if (ic_info->following_text)
{
@@ -558,6 +599,8 @@ get_following_char (MInputContext *ic, int pos)
M17N_OBJECT_UNREF (ic_info->following_text);
ic_info->following_text = mt;
}
+ else
+ M17N_OBJECT_UNREF (mt);
}
else
ic_info->following_text = mt;
@@ -574,7 +617,8 @@ surrounding_pos (MSymbol sym)
if (sym == Mnil)
return 0;
name = MSYMBOL_NAME (sym);
- if ((name[1] == '-' || name[1] == '+')
+ if (name[0] == '@'
+ && (name[1] == '-' || name[1] == '+')
&& name[2] >= '1' && name[2] <= '9')
return (name[1] == '-' ? - atoi (name + 2) : atoi (name + 2));
return 0;
@@ -584,7 +628,7 @@ static int
integer_value (MInputContext *ic, MPlist *arg, MPlist **value, int surrounding)
{
MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
- int code;
+ int code, pos;
MText *preedit = ic->preedit;
int len = mtext_nchars (preedit);
@@ -592,12 +636,8 @@ integer_value (MInputContext *ic, MPlist *arg, MPlist **value, int surrounding)
*value = NULL;
if (MPLIST_INTEGER_P (arg))
return MPLIST_INTEGER (arg);
- if (surrounding
- && (surrounding = surrounding_pos (MPLIST_SYMBOL (arg))) != 0)
- return (surrounding < 0
- ? get_preceding_char (ic, - surrounding)
- : get_following_char (ic, surrounding));
- code = marker_code (MPLIST_SYMBOL (arg));
+
+ code = marker_code (MPLIST_SYMBOL (arg), surrounding);
if (code < 0)
{
MPlist *val = resolve_variable (ic_info, MPLIST_SYMBOL (arg));
@@ -608,19 +648,42 @@ integer_value (MInputContext *ic, MPlist *arg, MPlist **value, int surrounding)
}
if (code == '@')
return ic_info->key_head;
- if (code >= '0' && code <= '9')
- code -= '0';
+ if ((code == '-' || code == '+'))
+ {
+ char *name = MSYMBOL_NAME (MPLIST_SYMBOL (arg));
+
+ if (name[2])
+ {
+ pos = atoi (name + 1);
+ if (pos == 0)
+ return get_preceding_char (ic, 0);
+ pos = ic->cursor_pos + pos;
+ if (pos < 0)
+ {
+ if (ic->produced && mtext_len (ic->produced) + pos >= 0)
+ return mtext_ref_char (ic->produced,
+ mtext_len (ic->produced) + pos);
+ return get_preceding_char (ic, - pos);
+ }
+ if (pos >= len)
+ return get_following_char (ic, pos - len + 1);
+ }
+ else
+ pos = ic->cursor_pos + (code == '+' ? 1 : -1);
+ }
+ else if (code >= '0' && code <= '9')
+ pos = code - '0';
else if (code == '=')
- code = ic->cursor_pos;
- else if (code == '-' || code == '[')
- code = ic->cursor_pos - 1;
- else if (code == '+' || code == ']')
- code = ic->cursor_pos + 1;
+ pos = ic->cursor_pos;
+ else if (code == '[')
+ pos = ic->cursor_pos - 1;
+ else if (code == ']')
+ pos = ic->cursor_pos + 1;
else if (code == '<')
- code = 0;
+ pos = 0;
else if (code == '>')
- code = len;
- return (code >= 0 && code < len ? mtext_ref_char (preedit, code) : -1);
+ pos = len - 1;
+ return (pos >= 0 && pos < len ? mtext_ref_char (preedit, pos) : -1);
}
static int
@@ -634,7 +697,7 @@ parse_expression (MPlist *plist)
return -1;
plist = MPLIST_PLIST (plist);
op = MPLIST_SYMBOL (plist);
- if (op != Mplus && op != Mminus && op != Mstar && op != Mslush
+ if (op != Mplus && op != Mminus && op != Mstar && op != Mslash
&& op != Mand && op != Mor && op != Mnot
&& op != Mless && op != Mgreater && op != Mequal
&& op != Mless_equal && op != Mgreater_equal)
@@ -659,7 +722,7 @@ resolve_expression (MInputContext *ic, MPlist *plist)
return 0;
plist = MPLIST_PLIST (plist);
if (! MPLIST_SYMBOL_P (plist))
- return val;
+ return 0;
op = MPLIST_SYMBOL (plist);
plist = MPLIST_NEXT (plist);
val = resolve_expression (ic, plist);
@@ -672,7 +735,7 @@ resolve_expression (MInputContext *ic, MPlist *plist)
else if (op == Mstar)
MPLIST_DO (plist, MPLIST_NEXT (plist))
val *= resolve_expression (ic, plist);
- else if (op == Mslush)
+ else if (op == Mslash)
MPLIST_DO (plist, MPLIST_NEXT (plist))
val /= resolve_expression (ic, plist);
else if (op == Mand)
@@ -761,7 +824,7 @@ parse_action_list (MPlist *plist, MPlist *macros)
}
else if (MPLIST_PLIST_P (pl))
{
- MPLIST_DO (pl, pl)
+ MPLIST_DO (pl, MPLIST_PLIST (pl))
{
if (MPLIST_PLIST_P (pl))
{
@@ -802,8 +865,7 @@ parse_action_list (MPlist *plist, MPlist *macros)
if (! MPLIST_TAIL_P (pl))
{
if (! MPLIST_SYMBOL_P (pl)
- && (! MPLIST_INTEGER_P (pl)
- || MPLIST_INTEGER (pl) == 0))
+ && ! MPLIST_INTEGER_P (pl))
MERROR (MERROR_IM, -1);
}
}
@@ -854,7 +916,8 @@ parse_action_list (MPlist *plist, MPlist *macros)
MERROR (MERROR_IM, -1);
}
else if (action_name == Mshow || action_name == Mhide
- || action_name == Mcommit || action_name == Munhandle)
+ || action_name == Mcommit || action_name == Munhandle
+ || action_name == Mpop)
;
else if (action_name == Mcond)
{
@@ -865,7 +928,7 @@ parse_action_list (MPlist *plist, MPlist *macros)
else if (! macros || ! mplist_get (macros, action_name))
MERROR (MERROR_IM, -1);
}
- else
+ else if (! MPLIST_SYMBOL_P (plist))
MERROR (MERROR_IM, -1);
}
@@ -873,24 +936,16 @@ parse_action_list (MPlist *plist, MPlist *macros)
}
static MPlist *
-resolve_command (MSymbol language, MSymbol name, MSymbol command)
+resolve_command (MPlist *cmds, MSymbol command)
{
- MPlist *plist = get_nested_list (language, name, Mnil, M_command);
+ MPlist *plist;
- if (! plist)
- MERROR (MERROR_IM, NULL);
- MPLIST_DO (plist, plist)
- {
- if (MPLIST_SYMBOL (plist) == command)
- break;
- plist = MPLIST_NEXT (plist);
- }
- if (MPLIST_TAIL_P (plist))
- MERROR (MERROR_IM, NULL);
- plist = MPLIST_NEXT (plist);
- if (! MPLIST_PLIST_P (plist))
- MERROR (MERROR_IM, NULL);
- plist = MPLIST_NEXT (MPLIST_PLIST (plist));
+ if (! cmds || ! (plist = mplist__assq (cmds, command)))
+ return NULL;
+ plist = MPLIST_PLIST (plist); /* (NAME DESC STATUS [KEYSEQ ...]) */
+ plist = MPLIST_NEXT (plist);
+ plist = MPLIST_NEXT (plist);
+ plist = MPLIST_NEXT (plist);
return plist;
}
@@ -910,19 +965,22 @@ load_translation (MIMMap *map, MPlist *keylist, MPlist *map_actions,
MText *mt = MPLIST_MTEXT (keylist);
len = mtext_nchars (mt);
- if (len == 0 || len != mtext_nbytes (mt))
- MERROR (MERROR_IM, -1);
+ if (MFAILP (len > 0 && len == mtext_nbytes (mt)))
+ return -1;
keyseq = (MSymbol *) alloca (sizeof (MSymbol) * len);
for (i = 0; i < len; i++)
keyseq[i] = one_char_symbol[MTEXT_DATA (mt)[i]];
}
- else if (MPLIST_PLIST_P (keylist))
+ else
{
- MPlist *elt = MPLIST_PLIST (keylist);
+ MPlist *elt;
+ if (MFAILP (MPLIST_PLIST_P (keylist)))
+ return -1;
+ elt = MPLIST_PLIST (keylist);
len = MPLIST_LENGTH (elt);
- if (len == 0)
- MERROR (MERROR_IM, -1);
+ if (MFAILP (len > 0))
+ return -1;
keyseq = (MSymbol *) alloca (sizeof (int) * len);
for (i = 0; i < len; i++, elt = MPLIST_NEXT (elt))
{
@@ -930,18 +988,18 @@ load_translation (MIMMap *map, MPlist *keylist, MPlist *map_actions,
{
int c = MPLIST_INTEGER (elt);
- if (c < 0 || c >= 0x100)
- MERROR (MERROR_IM, -1);
+ if (MFAILP (c >= 0 && c < 0x100))
+ return -1;
keyseq[i] = one_char_symbol[c];
}
- else if (MPLIST_SYMBOL_P (elt))
- keyseq[i] = MPLIST_SYMBOL (elt);
else
- MERROR (MERROR_IM, -1);
+ {
+ if (MFAILP (MPLIST_SYMBOL_P (elt)))
+ return -1;
+ keyseq[i] = MPLIST_SYMBOL (elt);
+ }
}
}
- else
- MERROR (MERROR_IM, -1);
for (i = 0; i < len; i++)
{
@@ -982,25 +1040,22 @@ load_translation (MIMMap *map, MPlist *keylist, MPlist *map_actions,
}
/* Load a branch from PLIST into MAP. PLIST has this form:
- PLIST ::= ( MAP-NAME BRANCH-ACTION * )
- MAPS is a plist of raw maps.
- STATE is the current state. */
+ PLIST ::= ( MAP-NAME BRANCH-ACTION * ) */
static int
-load_branch (MPlist *plist, MPlist *maps, MIMMap *map,
- MSymbol language, MSymbol name, MPlist *macros)
+load_branch (MInputMethodInfo *im_info, MPlist *plist, MIMMap *map)
{
MSymbol map_name;
MPlist *branch_actions;
- if (! MPLIST_SYMBOL_P (plist))
- MERROR (MERROR_IM, -1);
+ if (MFAILP (MPLIST_SYMBOL_P (plist)))
+ return -1;
map_name = MPLIST_SYMBOL (plist);
plist = MPLIST_NEXT (plist);
if (MPLIST_TAIL_P (plist))
branch_actions = NULL;
- else if (parse_action_list (plist, macros) < 0)
- MERROR (MERROR_IM, -1);
+ else if (MFAILP (parse_action_list (plist, im_info->macros) >= 0))
+ return -1;
else
branch_actions = plist;
if (map_name == Mnil)
@@ -1015,7 +1070,8 @@ load_branch (MPlist *plist, MPlist *maps, MIMMap *map,
if (branch_actions)
M17N_OBJECT_REF (branch_actions);
}
- else if ((plist = (MPlist *) mplist_get (maps, map_name)))
+ else if (im_info->maps
+ && (plist = (MPlist *) mplist_get (im_info->maps, map_name)))
{
MPLIST_DO (plist, plist)
{
@@ -1028,31 +1084,33 @@ load_branch (MPlist *plist, MPlist *maps, MIMMap *map,
if (MPLIST_SYMBOL_P (keylist))
{
MSymbol command = MPLIST_SYMBOL (keylist);
- MPlist *pl = resolve_command (language, name, command);
+ MPlist *pl;
- if (! pl)
- return -1;
+ if (MFAILP (command != Mat_reload))
+ continue;
+ pl = resolve_command (im_info->configured_cmds, command);
+ if (MFAILP (pl))
+ continue;
MPLIST_DO (pl, pl)
- if (load_translation (map, pl, map_actions, branch_actions,
- macros) < 0)
- MERROR (MERROR_IM, -1);
+ load_translation (map, pl, map_actions, branch_actions,
+ im_info->macros);
}
else
- if (load_translation (map, keylist, map_actions, branch_actions,
- macros) < 0)
- MERROR (MERROR_IM, -1);
+ load_translation (map, keylist, map_actions, branch_actions,
+ im_info->macros);
}
}
return 0;
}
-/* Load a macro from PLIST into MACROS.
+/* Load a macro from PLIST into IM_INFO->macros.
PLIST has this from:
PLIST ::= ( MACRO-NAME ACTION * )
- MACROS is a plist of macro names vs action list. */
+ IM_INFO->macros is a plist of macro names vs action list. */
+
static int
-load_macros (MPlist *plist, MPlist *macros)
+load_macros (MInputMethodInfo *im_info, MPlist *plist)
{
MSymbol name;
MPlist *pl;
@@ -1062,23 +1120,22 @@ load_macros (MPlist *plist, MPlist *macros)
name = MPLIST_SYMBOL (plist);
plist = MPLIST_NEXT (plist);
if (MPLIST_TAIL_P (plist)
- || parse_action_list (plist, macros) < 0)
+ || parse_action_list (plist, im_info->macros) < 0)
MERROR (MERROR_IM, -1);
- pl = mplist_get (macros, name);
- if (pl)
- M17N_OBJECT_UNREF (pl);
- mplist_put (macros, name, plist);
+ pl = mplist_get (im_info->macros, name);
+ M17N_OBJECT_UNREF (pl);
+ mplist_put (im_info->macros, name, plist);
M17N_OBJECT_REF (plist);
return 0;
}
-/* Load an external module from PLIST into EXTERNALS.
+/* Load an external module from PLIST into IM_INFO->externals.
PLIST has this form:
PLIST ::= ( MODULE-NAME FUNCTION * )
- 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 (MPlist *plist, MPlist *externals)
+load_external_module (MInputMethodInfo *im_info, MPlist *plist)
{
void *handle;
MSymbol module;
@@ -1096,10 +1153,10 @@ load_external_module (MPlist *plist, MPlist *externals)
sprintf (module_file, "%s%s", MSYMBOL_NAME (module), DLOPEN_SHLIB_EXT);
handle = dlopen (module_file, RTLD_NOW);
- if (! handle)
+ if (MFAILP (handle))
{
fprintf (stderr, "%s\n", dlerror ());
- MERROR (MERROR_IM, -1);
+ return -1;
}
func_list = mplist ();
MPLIST_DO (plist, MPLIST_NEXT (plist))
@@ -1107,15 +1164,15 @@ load_external_module (MPlist *plist, MPlist *externals)
if (! MPLIST_SYMBOL_P (plist))
MERROR_GOTO (MERROR_IM, err_label);
func = dlsym (handle, MSYMBOL_NAME (MPLIST_SYMBOL (plist)));
- if (! func)
- MERROR_GOTO (MERROR_IM, err_label);
+ if (MFAILP (func))
+ goto err_label;
mplist_add (func_list, MPLIST_SYMBOL (plist), func);
}
MSTRUCT_MALLOC (external, MERROR_IM);
external->handle = handle;
external->func_list = func_list;
- mplist_add (externals, module, external);
+ mplist_add (im_info->externals, module, external);
return 0;
err_label:
@@ -1146,8 +1203,7 @@ free_state (void *object)
{
MIMState *state = object;
- if (state->title)
- M17N_OBJECT_UNREF (state->title);
+ M17N_OBJECT_UNREF (state->title);
if (state->map)
free_map (state->map, 1);
free (state);
@@ -1157,17 +1213,15 @@ free_state (void *object)
PLIST has this form:
PLIST ::= ( STATE-NAME STATE-TITLE ? BRANCH * )
BRANCH ::= ( MAP-NAME BRANCH-ACTION * )
- MAPS is a plist of defined maps.
Return the state object. */
static MIMState *
-load_state (MPlist *plist, MPlist *maps, MSymbol language, MSymbol name,
- MPlist *macros)
+load_state (MInputMethodInfo *im_info, MPlist *plist)
{
MIMState *state;
- if (! MPLIST_SYMBOL_P (plist))
- MERROR (MERROR_IM, NULL);
+ if (MFAILP (MPLIST_SYMBOL_P (plist)))
+ return NULL;
M17N_OBJECT (state, free_state, MERROR_IM);
state->name = MPLIST_SYMBOL (plist);
plist = MPLIST_NEXT (plist);
@@ -1175,29 +1229,62 @@ load_state (MPlist *plist, MPlist *maps, MSymbol language, MSymbol name,
{
state->title = MPLIST_MTEXT (plist);
mtext_put_prop (state->title, 0, mtext_nchars (state->title),
- Mlanguage, language);
+ Mlanguage, im_info->language);
M17N_OBJECT_REF (state->title);
plist = MPLIST_NEXT (plist);
}
MSTRUCT_CALLOC (state->map, MERROR_IM);
MPLIST_DO (plist, plist)
- if (! MPLIST_PLIST_P (plist)
- || load_branch (MPLIST_PLIST (plist), maps, state->map, language, name,
- macros) < 0)
- MERROR (MERROR_IM, NULL);
+ {
+ if (MFAILP (MPLIST_PLIST_P (plist)))
+ continue;
+ load_branch (im_info, MPLIST_PLIST (plist), state->map);
+ }
return state;
}
+/* Return a newly created IM_INFO for an input method specified by
+ LANUAGE, NAME, and EXTRA. IM_INFO is stored in PLIST. */
-static MPlist *im_info_list;
+static MInputMethodInfo *
+new_im_info (MDatabase *mdb, MSymbol language, MSymbol name, MSymbol extra,
+ MPlist *plist)
+{
+ MInputMethodInfo *im_info;
+ MPlist *elt;
+
+ if (name == Mnil && extra == Mnil)
+ language = Mt, extra = Mglobal;
+ MSTRUCT_CALLOC (im_info, MERROR_IM);
+ im_info->mdb = mdb;
+ im_info->language = language;
+ im_info->name = name;
+ im_info->extra = extra;
+
+ elt = mplist ();
+ mplist_add (plist, Mplist, elt);
+ M17N_OBJECT_UNREF (elt);
+ elt = mplist_add (elt, Msymbol, language);
+ elt = mplist_add (elt, Msymbol, name);
+ elt = mplist_add (elt, Msymbol, extra);
+ mplist_add (elt, Mt, im_info);
+
+ return im_info;
+}
static void
-free_im_info (MInputMethodInfo *im_info)
+fini_im_info (MInputMethodInfo *im_info)
{
MPlist *plist;
- if (im_info->title)
- M17N_OBJECT_UNREF (im_info->title);
+ M17N_OBJECT_UNREF (im_info->cmds);
+ M17N_OBJECT_UNREF (im_info->configured_cmds);
+ M17N_OBJECT_UNREF (im_info->bc_cmds);
+ M17N_OBJECT_UNREF (im_info->vars);
+ M17N_OBJECT_UNREF (im_info->configured_vars);
+ M17N_OBJECT_UNREF (im_info->bc_vars);
+ M17N_OBJECT_UNREF (im_info->description);
+ M17N_OBJECT_UNREF (im_info->title);
if (im_info->states)
{
MPLIST_DO (plist, im_info->states)
@@ -1240,2669 +1327,4648 @@ free_im_info (MInputMethodInfo *im_info)
M17N_OBJECT_UNREF (im_info->maps);
}
- free (im_info);
+ im_info->tick = 0;
}
-static MInputMethodInfo *get_im_info (MSymbol language, MSymbol name,
- MSymbol extra);
+static void
+free_im_info (MInputMethodInfo *im_info)
+{
+ fini_im_info (im_info);
+ free (im_info);
+}
-static MInputMethodInfo *
-get_im_info_by_tags (MPlist *plist)
+static void
+free_im_list (MPlist *plist)
{
- MSymbol tag[3];
- int i;
+ MPlist *pl, *elt;
- for (i = 0; i < 3 && MPLIST_SYMBOL_P (plist);
- i++, plist = MPLIST_NEXT (plist))
- tag[i] = MPLIST_SYMBOL (plist);
- if (i < 2)
- return NULL;
- for (; i < 3; i++)
- tag[i] = Mnil;
- return get_im_info (tag[0], tag[1], tag[2]);
-}
+ MPLIST_DO (pl, plist)
+ {
+ MInputMethodInfo *im_info;
-/* Load an input method from PLIST into IM_INTO, and return it. */
+ elt = MPLIST_NEXT (MPLIST_NEXT (MPLIST_NEXT (MPLIST_PLIST (pl))));
+ im_info = MPLIST_VAL (elt);
+ free_im_info (im_info);
+ }
+ M17N_OBJECT_UNREF (plist);
+}
static MInputMethodInfo *
-load_im_info (MSymbol language, MSymbol name, MPlist *plist)
+lookup_im_info (MPlist *plist, MSymbol language, MSymbol name, MSymbol extra)
{
- MInputMethodInfo *im_info;
- MText *title = NULL;
- MPlist *maps = NULL;
- MPlist *states = NULL;
- MPlist *externals = NULL;
- MPlist *macros = NULL;
- MPlist *elt;
-
- MSTRUCT_CALLOC (im_info, MERROR_IM);
-
- while (MPLIST_PLIST_P (plist))
+ if (name == Mnil && extra == Mnil)
+ language = Mt, extra = Mglobal;
+ while ((plist = mplist__assq (plist, language)))
{
- elt = MPLIST_PLIST (plist);
- if (! MPLIST_SYMBOL_P (elt))
- MERROR_GOTO (MERROR_IM, err);
- if (MPLIST_SYMBOL (elt) == Mtitle)
- {
- elt = MPLIST_NEXT (elt);
- if (! MPLIST_MTEXT_P (elt))
- MERROR_GOTO (MERROR_IM, err);
- im_info->title = title = MPLIST_MTEXT (elt);
- M17N_OBJECT_REF (title);
- }
- else if (MPLIST_SYMBOL (elt) == Mmap)
- {
- MPlist *pl = mplist__from_alist (MPLIST_NEXT (elt));
-
- if (! pl)
- MERROR_GOTO (MERROR_IM, err);
- if (! maps)
- im_info->maps = maps = pl;
- else
- maps = mplist__conc (maps, pl);
- }
- else if (MPLIST_SYMBOL (elt) == Mmacro)
- {
- if (! macros)
- im_info->macros = macros = mplist ();
- MPLIST_DO (elt, MPLIST_NEXT (elt))
- {
- if (! MPLIST_PLIST_P (elt)
- || load_macros (MPLIST_PLIST (elt), macros) < 0)
- MERROR_GOTO (MERROR_IM, err);
- }
- }
- else if (MPLIST_SYMBOL (elt) == Mmodule)
- {
- if (! externals)
- im_info->externals = externals = mplist ();
- MPLIST_DO (elt, MPLIST_NEXT (elt))
- {
- if (! MPLIST_PLIST_P (elt)
- || load_external_module (MPLIST_PLIST (elt), externals) < 0)
- MERROR_GOTO (MERROR_IM, err);
- }
- }
- else if (MPLIST_SYMBOL (elt) == Mstate)
- {
- MPLIST_DO (elt, MPLIST_NEXT (elt))
- {
- MIMState *state;
-
- if (! MPLIST_PLIST_P (elt))
- MERROR_GOTO (MERROR_IM, err);
- state = load_state (MPLIST_PLIST (elt), maps, language, name,
- macros);
- if (! state)
- MERROR_GOTO (MERROR_IM, err);
- if (! states)
- im_info->states = states = mplist ();
- mplist_put (states, state->name, state);
- }
- }
- else if (MPLIST_SYMBOL (elt) == Minclude)
- {
- /* elt ::= include (tag1 tag2 ...) key item ... */
- MSymbol key;
- MInputMethodInfo *temp;
- MPlist *pl, *p;
-
- elt = MPLIST_NEXT (elt);
- if (! MPLIST_PLIST_P (elt))
- MERROR_GOTO (MERROR_IM, err);
- temp = get_im_info_by_tags (MPLIST_PLIST (elt));
- if (! temp)
- MERROR_GOTO (MERROR_IM, err);
- elt = MPLIST_NEXT (elt);
- if (! MPLIST_SYMBOL_P (elt))
- MERROR_GOTO (MERROR_IM, err);
- key = MPLIST_SYMBOL (elt);
- elt = MPLIST_NEXT (elt);
- if (key == Mmap)
- {
- if (! maps)
- im_info->maps = maps = mplist ();
- MPLIST_DO (pl, temp->maps)
- {
- p = MPLIST_VAL (pl);
- MPLIST_ADD_PLIST (maps, MPLIST_KEY (pl), p);
- M17N_OBJECT_REF (p);
- }
- }
- else if (key == Mmacro)
- {
- if (! macros)
- im_info->macros = macros = mplist ();
- MPLIST_DO (pl, temp->macros)
- {
- p = MPLIST_VAL (pl);
- MPLIST_ADD_PLIST (macros, MPLIST_KEY (pl), p);
- M17N_OBJECT_REF (p);
- }
- }
- else if (key == Mstate)
- {
- if (! states)
- im_info->states = states = mplist ();
- MPLIST_DO (pl, temp->states)
- {
- MIMState *state = MPLIST_VAL (pl);
+ MPlist *elt = MPLIST_PLIST (plist);
- mplist_add (states, MPLIST_KEY (pl), state);
- M17N_OBJECT_REF (state);
- }
- }
- else
- MERROR_GOTO (MERROR_IM, err);
- }
plist = MPLIST_NEXT (plist);
+ elt = MPLIST_NEXT (elt);
+ if (MPLIST_SYMBOL (elt) != name)
+ continue;
+ elt = MPLIST_NEXT (elt);
+ if (MPLIST_SYMBOL (elt) != extra)
+ continue;
+ elt = MPLIST_NEXT (elt);
+ return MPLIST_VAL (elt);
}
-
- if (! states)
- goto err;
- if (! title && name)
- im_info->title
- = title = mtext_from_data (MSYMBOL_NAME (name), MSYMBOL_NAMELEN (name),
- MTEXT_FORMAT_US_ASCII);
- return im_info;
-
- err:
- free_im_info (im_info);
return NULL;
}
-
+static void load_im_info (MPlist *, MInputMethodInfo *);
-static int take_action_list (MInputContext *ic, MPlist *action_list);
-static void preedit_commit (MInputContext *ic);
+#define get_custom_info(im_info) \
+ (im_custom_list \
+ ? lookup_im_info (im_custom_list, (im_info)->language, \
+ (im_info)->name, (im_info)->extra) \
+ : NULL)
-static void
-shift_state (MInputContext *ic, MSymbol state_name)
+#define get_config_info(im_info) \
+ (im_config_list \
+ ? lookup_im_info (im_config_list, (im_info)->language, \
+ (im_info)->name, (im_info)->extra) \
+ : NULL)
+
+static int
+update_custom_info (void)
{
- MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
- MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
- MIMState *orig_state = ic_info->state, *state;
+ MPlist *plist, *pl;
- /* Find a state to shift to. If not found, shift to the initial
- state. */
- if (state_name == Mt)
+ if (im_custom_mdb)
{
- if (! ic_info->prev_state)
- return;
- state = ic_info->prev_state;
+ if (mdatabase__check (im_custom_mdb) > 0)
+ return 1;
}
else
{
- state = (MIMState *) mplist_get (im_info->states, state_name);
- if (! state)
- state = (MIMState *) MPLIST_VAL (im_info->states);
+ MDatabaseInfo *custom_dir_info;
+ char custom_path[PATH_MAX + 1];
+
+ custom_dir_info = MPLIST_VAL (mdatabase__dir_list);
+ if (! custom_dir_info->filename
+ || custom_dir_info->len + strlen (CUSTOM_FILE) > PATH_MAX)
+ return -1;
+ strcpy (custom_path, custom_dir_info->filename);
+ strcat (custom_path, CUSTOM_FILE);
+ im_custom_mdb = mdatabase_define (Minput_method, Mt, Mnil, Mconfig,
+ NULL, custom_path);
}
- MDEBUG_PRINT1 ("\n [IM] (shift %s)", MSYMBOL_NAME (state->name));
+ if (im_custom_list)
+ {
+ free_im_list (im_custom_list);
+ im_custom_list = NULL;
+ }
+ plist = mdatabase_load (im_custom_mdb);
+ if (! plist)
+ return -1;
+ im_custom_list = mplist ();
- /* Enter the new state. */
- ic_info->state = state;
- ic_info->map = state->map;
- ic_info->state_key_head = ic_info->key_head;
- if (state == (MIMState *) MPLIST_VAL (im_info->states))
- /* We have shifted to the initial state. */
- preedit_commit (ic);
- mtext_cpy (ic_info->preedit_saved, ic->preedit);
- ic_info->state_pos = ic->cursor_pos;
- if (state != orig_state )
+ MPLIST_DO (pl, plist)
{
- if (state == (MIMState *) MPLIST_VAL (im_info->states))
- ic_info->prev_state = NULL;
- else
- ic_info->prev_state = orig_state;
+ MSymbol language, name, extra;
+ MInputMethodInfo *im_info;
+ MPlist *im_data, *p;
- if (state->title)
- ic->status = state->title;
- else
- ic->status = im_info->title;
- ic->status_changed = 1;
- if (ic_info->map == ic_info->state->map
- && ic_info->map->map_actions)
- {
- MDEBUG_PRINT (" init-actions:");
- take_action_list (ic, ic_info->map->map_actions);
- }
+ if (! MPLIST_PLIST_P (pl))
+ continue;
+ p = MPLIST_PLIST (pl);
+ im_data = MPLIST_NEXT (p);
+ if (! MPLIST_PLIST_P (p))
+ continue;
+ p = MPLIST_PLIST (p);
+ if (! MPLIST_SYMBOL_P (p)
+ || MPLIST_SYMBOL (p) != Minput_method)
+ continue;
+ p = MPLIST_NEXT (p);
+ if (! MPLIST_SYMBOL_P (p))
+ continue;
+ language = MPLIST_SYMBOL (p);
+ p = MPLIST_NEXT (p);
+ if (! MPLIST_SYMBOL_P (p))
+ continue;
+ name = MPLIST_SYMBOL (p);
+ p = MPLIST_NEXT (p);
+ if (MPLIST_TAIL_P (p))
+ extra = Mnil;
+ else if (MPLIST_SYMBOL_P (p))
+ extra = MPLIST_SYMBOL (p);
+ if (language == Mnil || (name == Mnil && extra == Mnil))
+ continue;
+ im_info = new_im_info (NULL, language, name, extra, im_custom_list);
+ load_im_info (im_data, im_info);
}
+ M17N_OBJECT_UNREF (plist);
+ return 0;
}
-/* Find a candidate group that contains a candidate number INDEX from
- PLIST. Set START_INDEX to the first candidate number of the group,
- END_INDEX to the last candidate number plus 1, GROUP_INDEX to the
- candidate group number if they are non-NULL. If INDEX is -1, find
- the last candidate group. */
-
-static MPlist *
-find_candidates_group (MPlist *plist, int index,
- int *start_index, int *end_index, int *group_index)
+static int
+update_global_info (void)
{
- int i = 0, gidx = 0, len;
+ MPlist *plist;
- MPLIST_DO (plist, plist)
+ if (global_info)
{
- if (MPLIST_MTEXT_P (plist))
- len = mtext_nchars (MPLIST_MTEXT (plist));
- else
- len = mplist_length (MPLIST_PLIST (plist));
- if (index < 0 ? MPLIST_TAIL_P (MPLIST_NEXT (plist))
- : i + len > index)
- {
- if (start_index)
- *start_index = i;
- if (end_index)
- *end_index = i + len;
- if (group_index)
- *group_index = gidx;
- return plist;
- }
- i += len;
- gidx++;
+ int ret = mdatabase__check (global_info->mdb);
+
+ if (ret)
+ return ret;
+ fini_im_info (global_info);
}
- return NULL;
-}
+ else
+ {
+ MDatabase *mdb = mdatabase_find (Minput_method, Mt, Mnil, Mglobal);
-static void
-preedit_insert (MInputContext *ic, int pos, MText *mt, int c)
-{
- MInputContextInfo *ic_info = ((MInputContext *) ic)->info;
- MPlist *markers;
- int nchars = mt ? mtext_nchars (mt) : 1;
+ global_info = new_im_info (mdb, Mt, Mnil, Mglobal, im_info_list);
+ }
+ if (! global_info->mdb
+ || ! (plist = mdatabase_load (global_info->mdb)))
+ return -1;
- if (mt)
- mtext_ins (ic->preedit, pos, mt);
- else
- mtext_ins_char (ic->preedit, pos, c, 1);
- MPLIST_DO (markers, ic_info->markers)
- if (MPLIST_INTEGER (markers) > pos)
- MPLIST_VAL (markers) = (void *) (MPLIST_INTEGER (markers) + nchars);
- if (ic->cursor_pos >= pos)
- ic->cursor_pos += nchars;
- ic->preedit_changed = 1;
+ load_im_info (plist, global_info);
+ M17N_OBJECT_UNREF (plist);
+ return 0;
}
-static void
-preedit_delete (MInputContext *ic, int from, int to)
-{
- MInputContextInfo *ic_info = ((MInputContext *) ic)->info;
- MPlist *markers;
-
- mtext_del (ic->preedit, from, to);
- MPLIST_DO (markers, ic_info->markers)
- {
- if (MPLIST_INTEGER (markers) > to)
- MPLIST_VAL (markers)
- = (void *) (MPLIST_INTEGER (markers) - (to - from));
- else if (MPLIST_INTEGER (markers) > from);
- MPLIST_VAL (markers) = (void *) from;
- }
- if (ic->cursor_pos >= to)
- ic->cursor_pos -= to - from;
- else if (ic->cursor_pos > from)
- ic->cursor_pos = from;
- ic->preedit_changed = 1;
-}
+/* Return an IM_INFO for the an 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. */
-static void
-preedit_commit (MInputContext *ic)
+static MInputMethodInfo *
+get_im_info (MSymbol language, MSymbol name, MSymbol extra, MSymbol key)
{
- MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
- int preedit_len = mtext_nchars (ic->preedit);
+ MPlist *plist;
+ MInputMethodInfo *im_info;
+ MDatabase *mdb;
- if (preedit_len > 0)
+ if (name == Mnil && extra == Mnil)
+ language = Mt, extra = Mglobal;
+ im_info = lookup_im_info (im_info_list, language, name, extra);
+ if (im_info)
{
- MPlist *p;
-
- mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit),
- Mcandidate_list, NULL, 0);
- mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit),
- Mcandidate_index, NULL, 0);
- mtext_cat (ic->produced, ic->preedit);
- if ((mdebug__flag & mdebug_mask)
- && mtext_nchars (ic->produced) > 0)
- {
- int i;
-
- MDEBUG_PRINT (" (produced");
- for (i = 0; i < mtext_nchars (ic->produced); i++)
- MDEBUG_PRINT1 (" U+%04X", mtext_ref_char (ic->produced, i));
- MDEBUG_PRINT (")");
- }
- mtext_reset (ic->preedit);
- mtext_reset (ic_info->preedit_saved);
- MPLIST_DO (p, ic_info->markers)
- MPLIST_VAL (p) = 0;
- ic->cursor_pos = ic_info->state_pos = 0;
- ic->preedit_changed = 1;
+ if (key == Mnil ? im_info->states != NULL
+ : key == Mcommand ? im_info->cmds != NULL
+ : key == Mvariable ? im_info->vars != NULL
+ : key == Mtitle ? im_info->title != NULL
+ : key == Mdescription ? im_info->description != NULL
+ : 1)
+ /* IM_INFO already contains required information. */
+ return im_info;
+ /* We have not yet loaded required information. */
}
- if (ic->candidate_list)
+ else
{
- M17N_OBJECT_UNREF (ic->candidate_list);
- ic->candidate_list = NULL;
- ic->candidate_show = 0;
- ic->candidates_changed = MINPUT_CANDIDATES_LIST_CHANGED;
- if (ic->candidate_show)
- {
- ic->candidate_show = 0;
- ic->candidates_changed |= MINPUT_CANDIDATES_SHOW_CHANGED;
- }
+ mdb = mdatabase_find (Minput_method, language, name, extra);
+ if (! mdb)
+ return NULL;
+ im_info = new_im_info (mdb, language, name, extra, im_info_list);
}
- memmove (ic_info->keys, ic_info->keys + ic_info->key_head,
- sizeof (int) * (ic_info->used - ic_info->key_head));
- ic_info->used -= ic_info->key_head;
- ic_info->state_key_head = ic_info->key_head = 0;
+ if (key == Mnil)
+ {
+ plist = mdatabase_load (im_info->mdb);
+ }
+ else
+ {
+ mplist_push (load_im_info_keys, key, Mt);
+ plist = mdatabase__load_for_keys (im_info->mdb, load_im_info_keys);
+ mplist_pop (load_im_info_keys);
+ }
+ im_info->tick = 0;
+ if (! plist)
+ MERROR (MERROR_IM, im_info);
+ update_global_info ();
+ load_im_info (plist, im_info);
+ M17N_OBJECT_UNREF (plist);
+ if (key == Mnil)
+ {
+ if (! im_info->cmds)
+ im_info->cmds = mplist ();
+ if (! im_info->vars)
+ im_info->vars = mplist ();
+ }
+ if (! im_info->title
+ && (key == Mnil || key == Mtitle))
+ im_info->title = (name == Mnil ? mtext ()
+ : mtext_from_data (MSYMBOL_NAME (name),
+ MSYMBOL_NAMELEN (name),
+ MTEXT_FORMAT_US_ASCII));
+ return im_info;
}
+/* Check if IM_INFO->mdb is updated or not. If not updated, return 0.
+ If updated, but got unloadable, return -1. Otherwise, update
+ contents of IM_INFO from the new database, and return 1. */
+
static int
-new_index (MInputContext *ic, int current, int limit, MSymbol sym, MText *mt)
+reload_im_info (MInputMethodInfo *im_info)
{
- int code = marker_code (sym);
+ int check;
+ MPlist *plist;
- if (mt && (code == '[' || code == ']'))
+ update_custom_info ();
+ update_global_info ();
+ check = mdatabase__check (im_info->mdb);
+ if (check < 0)
+ return -1;
+ plist = mdatabase_load (im_info->mdb);
+ if (! plist)
+ return -1;
+ fini_im_info (im_info);
+ load_im_info (plist, im_info);
+ M17N_OBJECT_UNREF (plist);
+ if (! im_info->cmds)
+ im_info->cmds = mplist ();
+ if (! im_info->vars)
+ im_info->vars = mplist ();
+ if (! im_info->title)
{
- int pos = current;
+ MSymbol name = im_info->name;
- if (code == '[' && current > 0)
- {
- if (mtext_prop_range (mt, Mcandidate_list, pos - 1, &pos, NULL, 1)
- && pos > 0)
- current = pos;
- }
- else if (code == ']' && current < mtext_nchars (mt))
- {
- if (mtext_prop_range (mt, Mcandidate_list, pos, NULL, &pos, 1))
- current = pos;
- }
- return current;
+ im_info->title = (name == Mnil ? mtext ()
+ : mtext_from_data (MSYMBOL_NAME (name),
+ MSYMBOL_NAMELEN (name),
+ MTEXT_FORMAT_US_ASCII));
}
- if (code >= 0)
- return (code == '<' ? 0
- : code == '>' ? limit
- : code == '-' ? current - 1
- : code == '+' ? current + 1
- : code == '=' ? current
- : code - '0' > limit ? limit
- : code - '0');
- if (! ic)
- return 0;
- return (int) mplist_get (((MInputContextInfo *) ic->info)->markers, sym);
+ return 1;
}
-static void
-update_candidate (MInputContext *ic, MTextProperty *prop, int idx)
+static MInputMethodInfo *
+get_im_info_by_tags (MPlist *plist)
+{
+ MSymbol tag[3];
+ int i;
+
+ for (i = 0; i < 3 && MPLIST_SYMBOL_P (plist);
+ i++, plist = MPLIST_NEXT (plist))
+ tag[i] = MPLIST_SYMBOL (plist);
+ if (i < 2)
+ return NULL;
+ for (; i < 3; i++)
+ tag[i] = Mnil;
+ return get_im_info (tag[0], tag[1], tag[2], Mnil);
+}
+
+
+static int
+check_description (MPlist *plist)
{
- int from = mtext_property_start (prop);
- int to = mtext_property_end (prop);
- int start;
- MPlist *candidate_list = mtext_property_value (prop);
- MPlist *group = find_candidates_group (candidate_list, idx, &start,
- NULL, NULL);
- int ingroup_index = idx - start;
MText *mt;
- preedit_delete (ic, from, to);
- if (MPLIST_MTEXT_P (group))
- {
- mt = MPLIST_MTEXT (group);
- preedit_insert (ic, from, NULL, mtext_ref_char (mt, ingroup_index));
- to = from + 1;
- }
- else
+ if (MPLIST_MTEXT_P (plist))
+ return 1;
+ if (MPLIST_PLIST_P (plist))
{
- int i;
- MPlist *plist;
+ MPlist *pl = MPLIST_PLIST (plist);
- for (i = 0, plist = MPLIST_PLIST (group); i < ingroup_index;
- i++, plist = MPLIST_NEXT (plist));
- mt = MPLIST_MTEXT (plist);
- preedit_insert (ic, from, mt, 0);
- to = from + mtext_nchars (mt);
+ if (MFAILP (MPLIST_SYMBOL_P (pl) && MPLIST_SYMBOL (pl) == M_gettext))
+ return 0;
+ pl =MPLIST_NEXT (pl);
+ if (MFAILP (MPLIST_MTEXT_P (pl)))
+ return 0;
+ mt = MPLIST_MTEXT (pl);
+ M17N_OBJECT_REF (mt);
+#if ENABLE_NLS
+ {
+ char *translated = dgettext ("m17n-db", (char *) MTEXT_DATA (mt));
+
+ if (translated == (char *) MTEXT_DATA (mt))
+ translated = dgettext ("m17n-contrib", (char *) MTEXT_DATA (mt));
+ if (translated != (char *) MTEXT_DATA (mt))
+ {
+ M17N_OBJECT_UNREF (mt);
+ mt = mtext__from_data (translated, strlen (translated),
+ MTEXT_FORMAT_UTF_8, 1);
+ }
+ }
+#endif
+ mplist_set (plist, Mtext, mt);
+ M17N_OBJECT_UNREF (mt);
+ return 1;
}
- mtext_put_prop (ic->preedit, from, to, Mcandidate_list, candidate_list);
- mtext_put_prop (ic->preedit, from, to, Mcandidate_index, (void *) idx);
- ic->cursor_pos = to;
+ if (MFAILP (MPLIST_SYMBOL_P (plist) && MPLIST_SYMBOL (plist) == Mnil))
+ return 0;
+ return 1;
}
-static MCharset *
-get_select_charset (MInputContextInfo * ic_info)
+
+/* Check KEYSEQ, and return 1 if it is valid as a key sequence, return
+ 0 if not. */
+
+static int
+check_command_keyseq (MPlist *keyseq)
{
- MPlist *plist = resolve_variable (ic_info, Mcandidates_charset);
- MSymbol sym;
+ if (MPLIST_PLIST_P (keyseq))
+ {
+ MPlist *p = MPLIST_PLIST (keyseq);
- if (! MPLIST_VAL (plist))
- return NULL;
- sym = MPLIST_SYMBOL (plist);
- if (sym == Mnil)
- return NULL;
- return MCHARSET (sym);
+ MPLIST_DO (p, p)
+ if (! MPLIST_SYMBOL_P (p) && ! MPLIST_INTEGER_P (p))
+ return 0;
+ return 1;
+ }
+ if (MPLIST_MTEXT_P (keyseq))
+ {
+ MText *mt = MPLIST_MTEXT (keyseq);
+ int i;
+
+ for (i = 0; i < mtext_nchars (mt); i++)
+ if (mtext_ref_char (mt, i) >= 256)
+ return 0;
+ return 1;
+ }
+ return 0;
}
-static MPlist *
-adjust_candidates (MPlist *plist, MCharset *charset)
+/* Load command defitions from PLIST into IM_INFO->cmds.
+
+ PLIST is well-formed and has this form;
+ (command (NAME [DESCRIPTION KEYSEQ ...]) ...)
+ NAME is a symbol. DESCRIPTION is an M-text or `nil'. KEYSEQ is an
+ M-text or a plist of symbols.
+
+ The returned list has the same form, but for each element...
+
+ (1) If DESCRIPTION and the rest are omitted, the element is not
+ stored in the returned list.
+
+ (2) If DESCRIPTION is nil, it is complemented by the corresponding
+ description in global_info->cmds (if any). */
+
+static void
+load_commands (MInputMethodInfo *im_info, MPlist *plist)
{
- MPlist *pl;
+ MPlist *tail;
- /* plist ::= MTEXT ... | PLIST ... */
- plist = mplist_copy (plist);
- if (MPLIST_MTEXT_P (plist))
+ im_info->cmds = tail = mplist ();
+
+ MPLIST_DO (plist, MPLIST_NEXT (plist))
{
- pl = plist;
- while (! MPLIST_TAIL_P (pl))
- {
- /* pl ::= MTEXT ... */
- MText *mt = MPLIST_MTEXT (pl);
- int mt_copied = 0;
- int i, c;
+ /* PLIST ::= ((NAME DESC KEYSEQ ...) ...) */
+ MPlist *pl, *p;
- for (i = mtext_nchars (mt) - 1; i >= 0; i--)
- {
- c = mtext_ref_char (mt, i);
- if (ENCODE_CHAR (charset, c) == MCHAR_INVALID_CODE)
- {
- if (! mt_copied)
- {
- mt = mtext_dup (mt);
- mplist_set (pl, Mtext, mt);
- M17N_OBJECT_UNREF (mt);
- mt_copied = 1;
- }
- mtext_del (mt, i, i + 1);
- }
- }
- if (mtext_len (mt) > 0)
- pl = MPLIST_NEXT (pl);
- else
- {
- mplist_pop (pl);
- M17N_OBJECT_UNREF (mt);
- }
+ if (MFAILP (MPLIST_PLIST_P (plist)))
+ continue;
+ pl = MPLIST_PLIST (plist); /* PL ::= (NAME DESC KEYSEQ ...) */
+ if (MFAILP (MPLIST_SYMBOL_P (pl)))
+ continue;
+ p = MPLIST_NEXT (pl); /* P ::= (DESC KEYSEQ ...) */
+ if (MPLIST_TAIL_P (p)) /* PL ::= (NAME) */
+ {
+ if (MFAILP (im_info != global_info))
+ mplist_add (p, Msymbol, Mnil); /* PL ::= (NAME nil) */
}
- }
- else /* MPLIST_PLIST_P (plist) */
- {
- pl = plist;
- while (! MPLIST_TAIL_P (pl))
+ else
{
- /* pl ::= (MTEXT ...) ... */
- MPlist *p = MPLIST_PLIST (pl);
- int p_copied = 0;
- /* p ::= MTEXT ... */
- MPlist *p0 = p;
- int n = 0;
-
- while (! MPLIST_TAIL_P (p0))
+ if (! check_description (p))
+ mplist_set (p, Msymbol, Mnil);
+ p = MPLIST_NEXT (p);
+ while (! MPLIST_TAIL_P (p))
{
- MText *mt = MPLIST_MTEXT (p0);
- int i, c;
-
- for (i = mtext_nchars (mt) - 1; i >= 0; i--)
- {
- c = mtext_ref_char (mt, i);
- if (ENCODE_CHAR (charset, c) == MCHAR_INVALID_CODE)
- break;
- }
- if (i < 0)
- {
- p0 = MPLIST_NEXT (p0);
- n++;
- }
+ if (MFAILP (check_command_keyseq (p)))
+ mplist__pop_unref (p);
else
- {
- if (! p_copied)
- {
- p = mplist_copy (p);
- mplist_set (pl, Mplist, p);
- M17N_OBJECT_UNREF (p);
- p_copied = 1;
- p0 = p;
- while (n-- > 0)
- p0 = MPLIST_NEXT (p0);
- }
- mplist_pop (p0);
- M17N_OBJECT_UNREF (mt);
- }
- }
- if (! MPLIST_TAIL_P (p))
- pl = MPLIST_NEXT (pl);
- else
- {
- mplist_pop (pl);
- M17N_OBJECT_UNREF (p);
+ p = MPLIST_NEXT (p);
}
}
+ tail = mplist_add (tail, Mplist, pl);
}
- if (MPLIST_TAIL_P (plist))
- {
- M17N_OBJECT_UNREF (plist);
- return NULL;
- }
- return plist;
}
static MPlist *
-get_candidate_list (MInputContextInfo *ic_info, MPlist *args)
+config_command (MPlist *plist, MPlist *global_cmds, MPlist *custom_cmds,
+ MPlist *config_cmds)
{
- MCharset *charset = get_select_charset (ic_info);
- MPlist *plist;
- int column;
- int i, len;
+ MPlist *global = NULL, *custom = NULL, *config = NULL;
+ MSymbol name;
+ MSymbol status;
+ MPlist *description, *keyseq;
- plist = resolve_variable (ic_info, Mcandidates_group_size);
- column = MPLIST_INTEGER (plist);
+ if (global_cmds && (global = mplist__assq (global_cmds, name)))
+ global = MPLIST_NEXT (MPLIST_PLIST (global));
- plist = MPLIST_PLIST (args);
- if (charset)
+ name = MPLIST_SYMBOL (plist);
+ plist = MPLIST_NEXT (plist);
+ if (MPLIST_MTEXT_P (plist) || MPLIST_PLIST_P (plist))
{
- if (! (plist = adjust_candidates (plist, charset)))
- return NULL;
+ description = plist;
+ plist = MPLIST_NEXT (plist);
+ }
+ else
+ {
+ description = global;
+ if (! MPLIST_TAIL_P (plist))
+ plist = MPLIST_NEXT (plist);
+ }
+ if (MPLIST_TAIL_P (plist) && global)
+ {
+ keyseq = MPLIST_NEXT (global);
+ status = Minherited;
}
else
- M17N_OBJECT_REF (plist);
+ {
+ keyseq = plist;
+ status = Mnil;
+ }
- if (column > 0)
+ if (config_cmds && (config = mplist__assq (config_cmds, name)))
{
- if (MPLIST_MTEXT_P (plist))
- {
- MText *mt = MPLIST_MTEXT (plist);
- MPlist *next = MPLIST_NEXT (plist);
+ status = Mconfigured;
+ config = MPLIST_NEXT (MPLIST_PLIST (config));
+ if (! MPLIST_TAIL_P (config))
+ keyseq = config;
+ }
+ else if (custom_cmds && (custom = mplist__assq (custom_cmds, name)))
+ {
+ MPlist *this_keyseq = MPLIST_NEXT (MPLIST_NEXT (MPLIST_PLIST (custom)));
- if (MPLIST_TAIL_P (next))
- M17N_OBJECT_REF (mt);
- else
- {
- mt = mtext_dup (mt);
- while (! MPLIST_TAIL_P (next))
- {
- mt = mtext_cat (mt, MPLIST_MTEXT (next));
- next = MPLIST_NEXT (next);
- }
- }
- M17N_OBJECT_UNREF (plist);
- plist = mplist ();
- len = mtext_nchars (mt);
- if (len <= column)
- mplist_add (plist, Mtext, mt);
- else
- {
- for (i = 0; i < len; i += column)
- {
- int to = (i + column < len ? i + column : len);
- MText *sub = mtext_copy (mtext (), 0, mt, i, to);
-
- mplist_add (plist, Mtext, sub);
- M17N_OBJECT_UNREF (sub);
- }
- }
- M17N_OBJECT_UNREF (mt);
+ if (MPLIST_TAIL_P (this_keyseq))
+ mplist__pop_unref (custom);
+ else
+ {
+ status = Mcustomized;
+ keyseq = this_keyseq;
}
- else /* MPLIST_PLIST_P (plist) */
+ }
+
+ plist = mplist ();
+ mplist_add (plist, Msymbol, name);
+ if (description)
+ mplist_add (plist, MPLIST_KEY (description), MPLIST_VAL (description));
+ else
+ mplist_add (plist, Msymbol, Mnil);
+ mplist_add (plist, Msymbol, status);
+ mplist__conc (plist, keyseq);
+ return plist;
+}
+
+static void
+config_all_commands (MInputMethodInfo *im_info)
+{
+ MPlist *global_cmds, *custom_cmds, *config_cmds;
+ MInputMethodInfo *temp;
+ MPlist *tail, *plist;
+
+ M17N_OBJECT_UNREF (im_info->configured_cmds);
+
+ if (MPLIST_TAIL_P (im_info->cmds)
+ || ! im_info->mdb)
+ return;
+
+ global_cmds = im_info != global_info ? global_info->cmds : NULL;
+ custom_cmds = ((temp = get_custom_info (im_info)) ? temp->cmds : NULL);
+ config_cmds = ((temp = get_config_info (im_info)) ? temp->cmds : NULL);
+
+ im_info->configured_cmds = tail = mplist ();
+ MPLIST_DO (plist, im_info->cmds)
+ {
+ MPlist *pl = config_command (MPLIST_PLIST (plist),
+ global_cmds, custom_cmds, config_cmds);
+ if (pl)
{
- MPlist *pl = MPLIST_PLIST (plist), *p;
- MPlist *next = MPLIST_NEXT (plist);
- int j;
+ tail = mplist_add (tail, Mplist, pl);
+ M17N_OBJECT_UNREF (pl);
+ }
+ }
+}
- if (MPLIST_TAIL_P (next))
- M17N_OBJECT_REF (pl);
- else
+/* Check VAL's value against VALID_VALUES, and return 1 if it is
+ valid, return 0 if not. */
+
+static int
+check_variable_value (MPlist *val, MPlist *global)
+{
+ MSymbol type = MPLIST_KEY (val);
+ MPlist *valids = MPLIST_NEXT (val);
+
+ if (type != Minteger && type != Mtext && type != Msymbol)
+ return 0;
+ if (global)
+ {
+ if (MPLIST_KEY (global) != Mt
+ && MPLIST_KEY (global) != MPLIST_KEY (val))
+ return 0;
+ if (MPLIST_TAIL_P (valids))
+ valids = MPLIST_NEXT (global);
+ }
+ if (MPLIST_TAIL_P (valids))
+ return 1;
+
+ if (type == Minteger)
+ {
+ int n = MPLIST_INTEGER (val);
+
+ MPLIST_DO (valids, valids)
+ {
+ if (MPLIST_INTEGER_P (valids))
{
- pl = mplist_copy (pl);
- while (! MPLIST_TAIL_P (next))
- {
- p = mplist_copy (MPLIST_PLIST (next));
- pl = mplist__conc (pl, p);
- M17N_OBJECT_UNREF (p);
- next = MPLIST_NEXT (next);
- }
+ if (n == MPLIST_INTEGER (valids))
+ break;
}
- M17N_OBJECT_UNREF (plist);
- plist = mplist ();
- len = mplist_length (pl);
- if (len <= column)
- mplist_add (plist, Mplist, pl);
- else
+ else if (MPLIST_PLIST_P (valids))
{
- MPlist *p0 = pl;
-
- for (i = 0; i < len; i += column)
- {
- p = mplist ();
- mplist_add (plist, Mplist, p);
- M17N_OBJECT_UNREF (p);
- for (j = 0; j < column && i + j < len; j++)
- {
- p = mplist_add (p, Mtext, MPLIST_VAL (p0));
- p0 = MPLIST_NEXT (p0);
- }
- }
+ MPlist *p = MPLIST_PLIST (valids);
+ int min_bound, max_bound;
+
+ if (! MPLIST_INTEGER_P (p))
+ MERROR (MERROR_IM, 0);
+ min_bound = MPLIST_INTEGER (p);
+ p = MPLIST_NEXT (p);
+ if (! MPLIST_INTEGER_P (p))
+ MERROR (MERROR_IM, 0);
+ max_bound = MPLIST_INTEGER (p);
+ if (n >= min_bound && n <= max_bound)
+ break;
}
- M17N_OBJECT_UNREF (pl);
}
}
-
- return plist;
-}
-
-
-static MPlist *
-regularize_action (MPlist *action_list)
-{
- MPlist *action = NULL;
- MSymbol name;
- MPlist *args;
-
- if (MPLIST_PLIST_P (action_list))
+ else if (type == Msymbol)
{
- action = MPLIST_PLIST (action_list);
- if (MPLIST_SYMBOL_P (action))
- {
- name = MPLIST_SYMBOL (action);
- args = MPLIST_NEXT (action);
- if (name == Minsert
- && MPLIST_PLIST_P (args))
- mplist_set (action, Msymbol, M_candidates);
- }
- else if (MPLIST_MTEXT_P (action) || MPLIST_PLIST_P (action))
+ MSymbol sym = MPLIST_SYMBOL (val);
+
+ MPLIST_DO (valids, valids)
{
- action = mplist ();
- mplist_push (action, Mplist, MPLIST_VAL (action_list));
- mplist_push (action, Msymbol, M_candidates);
- mplist_set (action_list, Mplist, action);
- M17N_OBJECT_UNREF (action);
+ if (! MPLIST_SYMBOL_P (valids))
+ MERROR (MERROR_IM, 0);
+ if (sym == MPLIST_SYMBOL (valids))
+ break;
}
}
- else if (MPLIST_MTEXT_P (action_list) || MPLIST_INTEGER_P (action_list))
+ else
{
- action = mplist ();
- mplist_push (action, MPLIST_KEY (action_list), MPLIST_VAL (action_list));
- mplist_push (action, Msymbol, Minsert);
- mplist_set (action_list, Mplist, action);
- M17N_OBJECT_UNREF (action);
+ MText *mt = MPLIST_MTEXT (val);
+
+ MPLIST_DO (valids, valids)
+ {
+ if (! MPLIST_MTEXT_P (valids))
+ MERROR (MERROR_IM, 0);
+ if (mtext_cmp (mt, MPLIST_MTEXT (valids)) == 0)
+ break;
+ }
}
- return action;
+
+ return (! MPLIST_TAIL_P (valids));
}
-static int
-take_action_list (MInputContext *ic, MPlist *action_list)
+/* Load variable defitions from PLIST into IM_INFO->vars.
+
+ PLIST is well-formed and has this form;
+ ((NAME [DESCRIPTION DEFAULT-VALUE VALID-VALUE ...])
+ ...)
+ NAME is a symbol. DESCRIPTION is an M-text or `nil'.
+
+ The returned list has the same form, but for each element...
+
+ (1) If DESCRIPTION and the rest are omitted, the element is not
+ stored in the returned list.
+
+ (2) If DESCRIPTION is nil, it is complemented by the corresponding
+ description in global_info->vars (if any). */
+
+static void
+load_variables (MInputMethodInfo *im_info, MPlist *plist)
{
- 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 *global_vars = ((im_info->mdb && im_info != global_info)
+ ? global_info->vars : NULL);
+ MPlist *tail;
- MPLIST_DO (action_list, action_list)
+ im_info->vars = tail = mplist ();
+ MPLIST_DO (plist, MPLIST_NEXT (plist))
{
- MPlist *action = regularize_action (action_list);
- MSymbol name;
- MPlist *args;
+ MPlist *pl, *p;
- if (! action)
+ if (MFAILP (MPLIST_PLIST_P (plist)))
continue;
- name = MPLIST_SYMBOL (action);
- args = MPLIST_NEXT (action);
-
- MDEBUG_PRINT1 (" %s", MSYMBOL_NAME (name));
- if (name == Minsert)
- {
- if (MPLIST_SYMBOL_P (args))
- {
- args = resolve_variable (ic_info, MPLIST_SYMBOL (args));
- if (! MPLIST_MTEXT_P (args) && ! MPLIST_INTEGER_P (args))
- continue;
- }
- if (MPLIST_MTEXT_P (args))
- preedit_insert (ic, ic->cursor_pos, MPLIST_MTEXT (args), 0);
- else /* MPLIST_INTEGER_P (args)) */
- preedit_insert (ic, ic->cursor_pos, NULL, MPLIST_INTEGER (args));
- }
- else if (name == M_candidates)
+ pl = MPLIST_PLIST (plist); /* PL ::= (NAME DESC VALUE VALID ...) */
+ if (MFAILP (MPLIST_SYMBOL_P (pl)))
+ continue;
+ if (im_info == global_info)
{
- MPlist *plist = get_candidate_list (ic_info, args);
- int len;
-
- if (! plist)
- continue;
- if (MPLIST_MTEXT_P (plist))
- {
- preedit_insert (ic, ic->cursor_pos, NULL,
- mtext_ref_char (MPLIST_MTEXT (plist), 0));
- len = 1;
- }
+ /* Loading a global variable. */
+ p = MPLIST_NEXT (pl);
+ if (MPLIST_TAIL_P (p))
+ mplist_add (p, Msymbol, Mnil);
else
{
- MText * mt = MPLIST_MTEXT (MPLIST_PLIST (plist));
-
- preedit_insert (ic, ic->cursor_pos, mt, 0);
- len = mtext_nchars (mt);
+ if (! check_description (p))
+ mplist_set (p, Msymbol, Mnil);
+ p = MPLIST_NEXT (p);
+ if (MFAILP (! MPLIST_TAIL_P (p)
+ && check_variable_value (p, NULL)))
+ mplist_set (p, Mt, NULL);
}
- mtext_put_prop (ic->preedit,
- ic->cursor_pos - len, ic->cursor_pos,
- Mcandidate_list, plist);
- mtext_put_prop (ic->preedit,
- ic->cursor_pos - len, ic->cursor_pos,
- Mcandidate_index, (void *) 0);
- M17N_OBJECT_UNREF (plist);
}
- else if (name == Mselect)
+ else if (im_info->mdb)
{
- int start, end;
- int code, idx, gindex;
- int pos = ic->cursor_pos;
- MPlist *group;
+ /* Loading a local variable. */
+ MSymbol name = MPLIST_SYMBOL (pl);
+ MPlist *global = NULL;
- if (pos == 0
- || ! (prop = mtext_get_property (ic->preedit, pos - 1,
- Mcandidate_list)))
- continue;
- if (MPLIST_SYMBOL_P (args))
+ if (global_vars
+ && (p = mplist__assq (global_vars, name)))
{
- code = marker_code (MPLIST_SYMBOL (args));
- if (code < 0)
- continue;
+ /* P ::= ((NAME DESC ...) ...) */
+ p = MPLIST_PLIST (p); /* P ::= (NAME DESC ...) */
+ global = MPLIST_NEXT (p); /* P ::= (DESC VALUE ...) */
+ global = MPLIST_NEXT (global); /* P ::= (VALUE ...) */
}
- else
- code = -1;
- idx = (int) mtext_get_prop (ic->preedit, pos - 1, Mcandidate_index);
- group = find_candidates_group (mtext_property_value (prop), idx,
- &start, &end, &gindex);
- if (code != '[' && code != ']')
- {
- idx = (start
- + (code >= 0
- ? new_index (NULL, ic->candidate_index - start,
- end - start - 1, MPLIST_SYMBOL (args),
- NULL)
- : MPLIST_INTEGER (args)));
- if (idx < 0)
- {
- find_candidates_group (mtext_property_value (prop), -1,
- NULL, &end, NULL);
- idx = end - 1;
- }
- else if (idx >= end
- && MPLIST_TAIL_P (MPLIST_NEXT (group)))
- idx = 0;
- }
- else
+ p = MPLIST_NEXT (pl); /* P ::= (DESC VALUE VALID ...) */
+ if (! MPLIST_TAIL_P (p))
{
- int ingroup_index = idx - start;
- int len;
-
- group = mtext_property_value (prop);
- len = mplist_length (group);
- if (code == '[')
- {
- gindex--;
- if (gindex < 0)
- gindex = len - 1;;
- }
+ if (! check_description (p))
+ mplist_set (p, Msymbol, Mnil);
+ p = MPLIST_NEXT (p); /* P ::= (VALUE VALID ...) */
+ if (MFAILP (! MPLIST_TAIL_P (p)))
+ mplist_set (p, Mt, NULL);
else
{
- gindex++;
- if (gindex >= len)
- gindex = 0;
+ MPlist *valid_values = MPLIST_NEXT (p);
+
+ if (! MPLIST_TAIL_P (valid_values)
+ ? MFAILP (check_variable_value (p, NULL))
+ : global && MFAILP (check_variable_value (p, global)))
+ mplist_set (p, Mt, NULL);
}
- for (idx = 0; gindex > 0; gindex--, group = MPLIST_NEXT (group))
- idx += (MPLIST_MTEXT_P (group)
- ? mtext_nchars (MPLIST_MTEXT (group))
- : mplist_length (MPLIST_PLIST (group)));
- len = (MPLIST_MTEXT_P (group)
- ? mtext_nchars (MPLIST_MTEXT (group))
- : mplist_length (MPLIST_PLIST (group)));
- if (ingroup_index >= len)
- ingroup_index = len - 1;
- idx += ingroup_index;
}
- update_candidate (ic, prop, idx);
}
- else if (name == Mshow)
- ic->candidate_show = 1;
- else if (name == Mhide)
- ic->candidate_show = 0;
- else if (name == Mdelete)
+ else
{
- int len = mtext_nchars (ic->preedit);
- int pos;
- int to;
-
- if (MPLIST_SYMBOL_P (args)
- && (pos = surrounding_pos (MPLIST_SYMBOL (args))) != 0)
- {
- delete_surrounding_text (ic, pos);
- }
- else
- {
- to = (MPLIST_SYMBOL_P (args)
- ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
- ic->preedit)
- : MPLIST_INTEGER (args));
- if (to < 0)
- to = 0;
- else if (to > len)
- to = len;
- MDEBUG_PRINT1 ("(%d)", to - ic->cursor_pos);
- if (to < ic->cursor_pos)
- preedit_delete (ic, to, ic->cursor_pos);
- else if (to > ic->cursor_pos)
- preedit_delete (ic, ic->cursor_pos, to);
- }
+ /* Loading a variable customization. */
+ p = MPLIST_NEXT (pl); /* P ::= (nil VALUE) */
+ if (MFAILP (! MPLIST_TAIL_P (p)))
+ continue;
+ p = MPLIST_NEXT (p); /* P ::= (VALUE) */
+ if (MFAILP (MPLIST_INTEGER_P (p) || MPLIST_SYMBOL_P (p)
+ || MPLIST_MTEXT_P (p)))
+ continue;
}
- else if (name == Mmove)
- {
- int len = mtext_nchars (ic->preedit);
- int pos
- = (MPLIST_SYMBOL_P (args)
- ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
- ic->preedit)
- : MPLIST_INTEGER (args));
+ tail = mplist_add (tail, Mplist, pl);
+ }
+}
- if (pos < 0)
- pos = 0;
- else if (pos > len)
- pos = len;
- if (pos != ic->cursor_pos)
- {
- ic->cursor_pos = pos;
- ic->preedit_changed = 1;
- }
- }
- else if (name == Mmark)
- {
- int code = marker_code (MPLIST_SYMBOL (args));
+static MPlist *
+config_variable (MPlist *plist, MPlist *global_vars, MPlist *custom_vars,
+ MPlist *config_vars)
+{
+ MPlist *global = NULL, *custom = NULL, *config = NULL;
+ MSymbol name = MPLIST_SYMBOL (plist);
+ MSymbol status;
+ MPlist *description = NULL, *value, *valids;
- if (code < 0)
- mplist_put (ic_info->markers, MPLIST_SYMBOL (args),
- (void *) ic->cursor_pos);
+ if (global_vars)
+ {
+ global = mplist__assq (global_vars, name);
+ if (global)
+ global = MPLIST_NEXT (MPLIST_PLIST (global)); /* (DESC VALUE ...) */
+ }
+
+ plist = MPLIST_NEXT (plist);
+ if (MPLIST_MTEXT_P (plist) || MPLIST_PLIST_P (plist))
+ description = plist;
+ else if (global)
+ description = global;
+ if (global)
+ global = MPLIST_NEXT (global); /* (VALUE VALIDS ...) */
+
+ if (MPLIST_TAIL_P (plist))
+ {
+ /* Inherit from global (if any). */
+ if (global)
+ {
+ value = global;
+ if (MPLIST_KEY (value) == Mt)
+ value = NULL;
+ valids = MPLIST_NEXT (global);
+ status = Minherited;
}
- else if (name == Mpushback)
+ else
{
- if (MPLIST_INTEGER_P (args))
- {
- int num = MPLIST_INTEGER (args);
+ value = NULL;
+ valids = NULL;
+ status = Mnil;
+ plist = NULL;
+ }
+ }
+ else
+ {
+ value = plist = MPLIST_NEXT (plist);
+ valids = MPLIST_NEXT (value);
+ if (MPLIST_KEY (value) == Mt)
+ value = NULL;
+ if (! MPLIST_TAIL_P (valids))
+ global = NULL;
+ else if (global)
+ valids = MPLIST_NEXT (global);
+ status = Mnil;
+ }
- if (num > 0)
- ic_info->key_head -= num;
- else
- ic_info->key_head = num;
- if (ic_info->key_head > ic_info->used)
- ic_info->key_head = ic_info->used;
- }
- else if (MPLIST_MTEXT_P (args))
- {
- MText *mt = MPLIST_MTEXT (args);
- int i, len = mtext_nchars (mt);
- MSymbol key;
+ if (config_vars && (config = mplist__assq (config_vars, name)))
+ {
+ status = Mconfigured;
+ config = MPLIST_NEXT (MPLIST_PLIST (config));
+ if (! MPLIST_TAIL_P (config))
+ {
+ value = config;
+ if (MFAILP (check_variable_value (value, global ? global : plist)))
+ value = NULL;
+ }
+ }
+ else if (custom_vars && (custom = mplist__assq (custom_vars, name)))
+ {
+ MPlist *this_value = MPLIST_NEXT (MPLIST_NEXT (MPLIST_PLIST (custom)));
- ic_info->key_head--;
- for (i = 0; i < len; i++)
- {
- key = one_char_symbol[MTEXT_DATA (mt)[i]];
- if (ic_info->key_head + i < ic_info->used)
- ic_info->keys[ic_info->key_head + i] = key;
- else
- MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
- }
- }
- else
- {
- MPlist *plist = MPLIST_PLIST (args), *pl;
- int i = 0;
- MSymbol key;
+ if (MPLIST_TAIL_P (this_value))
+ mplist__pop_unref (custom);
+ else
+ {
+ value = this_value;
+ if (MFAILP (check_variable_value (value, global ? global : plist)))
+ value = NULL;
+ status = Mcustomized;
+ }
+ }
+
+ plist = mplist ();
+ mplist_add (plist, Msymbol, name);
+ if (description)
+ mplist_add (plist, MPLIST_KEY (description), MPLIST_VAL (description));
+ else
+ mplist_add (plist, Msymbol, Mnil);
+ mplist_add (plist, Msymbol, status);
+ if (value)
+ mplist_add (plist, MPLIST_KEY (value), MPLIST_VAL (value));
+ else
+ mplist_add (plist, Mt, NULL);
+ if (valids && ! MPLIST_TAIL_P (valids))
+ mplist__conc (plist, valids);
+ return plist;
+}
- ic_info->key_head--;
+/* Return a configured variable definition list based on
+ IM_INFO->vars. If a variable in it doesn't contain a value, try to
+ get it from global_info->vars. */
- MPLIST_DO (pl, plist)
- {
- key = MPLIST_SYMBOL (pl);
- if (ic_info->key_head < ic_info->used)
- ic_info->keys[ic_info->key_head + i] = key;
- else
- MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
- i++;
- }
- }
- }
- else if (name == Mcall)
- {
- MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
- MIMExternalFunc func = NULL;
- MSymbol module, func_name;
- MPlist *func_args, *val;
- int ret = 0;
+static void
+config_all_variables (MInputMethodInfo *im_info)
+{
+ MPlist *global_vars, *custom_vars, *config_vars;
+ MInputMethodInfo *temp;
+ MPlist *tail, *plist;
- module = MPLIST_SYMBOL (args);
- args = MPLIST_NEXT (args);
- func_name = MPLIST_SYMBOL (args);
+ M17N_OBJECT_UNREF (im_info->configured_vars);
- if (im_info->externals)
- {
- MIMExternalModule *external
- = (MIMExternalModule *) mplist_get (im_info->externals,
- module);
- if (external)
- func = (MIMExternalFunc) mplist_get (external->func_list,
- func_name);
- }
- if (! func)
- continue;
- func_args = mplist ();
- mplist_add (func_args, Mt, ic);
- MPLIST_DO (args, MPLIST_NEXT (args))
- {
- int code;
+ if (MPLIST_TAIL_P (im_info->vars)
+ || ! im_info->mdb)
+ return;
- if (MPLIST_KEY (args) == Msymbol
- && MPLIST_KEY (args) != Mnil
- && (code = marker_code (MPLIST_SYMBOL (args))) >= 0)
- {
- code = new_index (ic, ic->cursor_pos,
- mtext_nchars (ic->preedit),
- MPLIST_SYMBOL (args), ic->preedit);
- mplist_add (func_args, Minteger, (void *) code);
- }
- else
- mplist_add (func_args, MPLIST_KEY (args), MPLIST_VAL (args));
- }
- val = (func) (func_args);
- M17N_OBJECT_UNREF (func_args);
- if (val && ! MPLIST_TAIL_P (val))
- ret = take_action_list (ic, val);
- M17N_OBJECT_UNREF (val);
- if (ret < 0)
- return ret;
- }
- else if (name == Mshift)
+ global_vars = im_info != global_info ? global_info->vars : NULL;
+ custom_vars = ((temp = get_custom_info (im_info)) ? temp->vars : NULL);
+ config_vars = ((temp = get_config_info (im_info)) ? temp->vars : NULL);
+
+ im_info->configured_vars = tail = mplist ();
+ MPLIST_DO (plist, im_info->vars)
+ {
+ MPlist *pl = config_variable (MPLIST_PLIST (plist),
+ global_vars, custom_vars, config_vars);
+ if (pl)
{
- shift_state (ic, MPLIST_SYMBOL (args));
+ tail = mplist_add (tail, Mplist, pl);
+ M17N_OBJECT_UNREF (pl);
}
- else if (name == Mundo)
- {
- int intarg = (MPLIST_TAIL_P (args)
- ? ic_info->used - 2
- : integer_value (ic, args, NULL, 0));
+ }
+}
- mtext_reset (ic->preedit);
- mtext_reset (ic_info->preedit_saved);
- ic->cursor_pos = ic_info->state_pos = 0;
- ic_info->state_key_head = ic_info->key_head = 0;
+/* Load an input method (LANGUAGE NAME) from PLIST into IM_INFO.
+ CONFIG contains configuration information of the input method. */
- if (intarg < 0)
- ic_info->used += intarg;
- else
- ic_info->used = intarg;
- shift_state (ic, Mnil);
- break;
- }
- else if (name == Mset || name == Madd || name == Msub
- || name == Mmul || name == Mdiv)
- {
- MSymbol sym = MPLIST_SYMBOL (args);
- int val1, val2;
- MPlist *value;
- char *op;
+static void
+load_im_info (MPlist *plist, MInputMethodInfo *im_info)
+{
+ MPlist *pl, *p;
- val1 = integer_value (ic, args, &value, 0);
- args = MPLIST_NEXT (args);
- val2 = resolve_expression (ic, args);
- if (name == Mset)
- val1 = val2, op = "=";
- else if (name == Madd)
- val1 += val2, op = "+=";
- else if (name == Msub)
- val1 -= val2, op = "-=";
- else if (name == Mmul)
- val1 *= val2, op = "*=";
- else
- val1 /= val2, op = "/=";
- MDEBUG_PRINT4 ("(%s %s 0x%X(%d))",
- MSYMBOL_NAME (sym), op, val1, val1);
- if (value)
- mplist_set (value, Minteger, (void *) val1);
- }
- else if (name == Mequal || name == Mless || name == Mgreater
- || name == Mless_equal || name == Mgreater_equal)
- {
- int val1, val2;
- MPlist *actions1, *actions2;
- int ret = 0;
+ if (! im_info->cmds && (pl = mplist__assq (plist, Mcommand)))
+ {
+ load_commands (im_info, MPLIST_PLIST (pl));
+ config_all_commands (im_info);
+ pl = mplist_pop (pl);
+ M17N_OBJECT_UNREF (pl);
+ }
- val1 = resolve_expression (ic, args);
- args = MPLIST_NEXT (args);
- val2 = resolve_expression (ic, args);
- args = MPLIST_NEXT (args);
- actions1 = MPLIST_PLIST (args);
- args = MPLIST_NEXT (args);
- if (MPLIST_TAIL_P (args))
- actions2 = NULL;
- else
- actions2 = MPLIST_PLIST (args);
- MDEBUG_PRINT3 ("(%d %s %d)? ", val1, MSYMBOL_NAME (name), val2);
- if (name == Mequal ? val1 == val2
- : name == Mless ? val1 < val2
- : name == Mgreater ? val1 > val2
- : name == Mless_equal ? val1 <= val2
- : val1 >= val2)
- {
- MDEBUG_PRINT ("ok");
- ret = take_action_list (ic, actions1);
- }
- else
- {
- MDEBUG_PRINT ("no");
- if (actions2)
- ret = take_action_list (ic, actions2);
- }
- if (ret < 0)
- return ret;
- }
- else if (name == Mcond)
- {
- int idx = 0;
+ if (! im_info->vars && (pl = mplist__assq (plist, Mvariable)))
+ {
+ load_variables (im_info, MPLIST_PLIST (pl));
+ config_all_variables (im_info);
+ pl = mplist_pop (pl);
+ M17N_OBJECT_UNREF (pl);
+ }
- MPLIST_DO (args, args)
- {
- MPlist *cond;
+ MPLIST_DO (plist, plist)
+ if (MPLIST_PLIST_P (plist))
+ {
+ MPlist *elt = MPLIST_PLIST (plist);
+ MSymbol key;
- idx++;
- if (! MPLIST_PLIST (args))
- continue;
- cond = MPLIST_PLIST (args);
- if (resolve_expression (ic, cond) != 0)
- {
- MDEBUG_PRINT1 ("(%dth)", idx);
- if (take_action_list (ic, MPLIST_NEXT (cond)) < 0)
- return -1;;
- break;
- }
- }
- }
- else if (name == Mcommit)
- {
- preedit_commit (ic);
- }
- else if (name == Munhandle)
- {
- preedit_commit (ic);
- return -1;
- }
- else
- {
- MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
- MPlist *actions;
+ if (MFAILP (MPLIST_SYMBOL_P (elt)))
+ continue;
+ key = MPLIST_SYMBOL (elt);
+ if (key == Mtitle)
+ {
+ if (im_info->title)
+ continue;
+ elt = MPLIST_NEXT (elt);
+ if (MFAILP (MPLIST_MTEXT_P (elt)))
+ continue;
+ im_info->title = MPLIST_MTEXT (elt);
+ M17N_OBJECT_REF (im_info->title);
+ }
+ else if (key == Mmap)
+ {
+ pl = mplist__from_alist (MPLIST_NEXT (elt));
+ if (MFAILP (pl))
+ continue;
+ if (! im_info->maps)
+ im_info->maps = pl;
+ else
+ {
+ mplist__conc (im_info->maps, pl);
+ M17N_OBJECT_UNREF (pl);
+ }
+ }
+ else if (key == Mmacro)
+ {
+ if (! im_info->macros)
+ im_info->macros = mplist ();
+ MPLIST_DO (elt, MPLIST_NEXT (elt))
+ {
+ if (MFAILP (MPLIST_PLIST_P (elt)))
+ continue;
+ load_macros (im_info, MPLIST_PLIST (elt));
+ }
+ }
+ else if (key == Mmodule)
+ {
+ if (! im_info->externals)
+ im_info->externals = mplist ();
+ MPLIST_DO (elt, MPLIST_NEXT (elt))
+ {
+ if (MFAILP (MPLIST_PLIST_P (elt)))
+ continue;
+ load_external_module (im_info, MPLIST_PLIST (elt));
+ }
+ }
+ else if (key == Mstate)
+ {
+ MPLIST_DO (elt, MPLIST_NEXT (elt))
+ {
+ MIMState *state;
+
+ if (MFAILP (MPLIST_PLIST_P (elt)))
+ continue;
+ pl = MPLIST_PLIST (elt);
+ if (! im_info->states)
+ im_info->states = mplist ();
+ state = load_state (im_info, MPLIST_PLIST (elt));
+ if (MFAILP (state))
+ continue;
+ mplist_put (im_info->states, state->name, state);
+ }
+ }
+ else if (key == Minclude)
+ {
+ /* elt ::= include (tag1 tag2 ...) key item ... */
+ MSymbol key;
+ MInputMethodInfo *temp;
+
+ elt = MPLIST_NEXT (elt);
+ if (MFAILP (MPLIST_PLIST_P (elt)))
+ continue;
+ temp = get_im_info_by_tags (MPLIST_PLIST (elt));
+ if (MFAILP (temp))
+ continue;
+ elt = MPLIST_NEXT (elt);
+ if (MFAILP (MPLIST_SYMBOL_P (elt)))
+ continue;
+ key = MPLIST_SYMBOL (elt);
+ elt = MPLIST_NEXT (elt);
+ if (key == Mmap)
+ {
+ if (! temp->maps || MPLIST_TAIL_P (temp->maps))
+ continue;
+ if (! im_info->maps)
+ im_info->maps = mplist ();
+ MPLIST_DO (pl, temp->maps)
+ {
+ p = MPLIST_VAL (pl);
+ MPLIST_ADD_PLIST (im_info->maps, MPLIST_KEY (pl), p);
+ M17N_OBJECT_REF (p);
+ }
+ }
+ else if (key == Mmacro)
+ {
+ if (! temp->macros || MPLIST_TAIL_P (temp->macros))
+ continue;
+ if (! im_info->macros)
+ im_info->macros = mplist ();
+ MPLIST_DO (pl, temp->macros)
+ {
+ p = MPLIST_VAL (pl);
+ MPLIST_ADD_PLIST (im_info->macros, MPLIST_KEY (pl), p);
+ M17N_OBJECT_REF (p);
+ }
+ }
+ else if (key == Mstate)
+ {
+ if (! temp->states || MPLIST_TAIL_P (temp->states))
+ continue;
+ if (! im_info->states)
+ im_info->states = mplist ();
+ MPLIST_DO (pl, temp->states)
+ {
+ MIMState *state = MPLIST_VAL (pl);
+
+ mplist_add (im_info->states, MPLIST_KEY (pl), state);
+ M17N_OBJECT_REF (state);
+ }
+ }
+ }
+ else if (key == Mdescription)
+ {
+ if (im_info->description)
+ continue;
+ elt = MPLIST_NEXT (elt);
+ if (! check_description (elt))
+ continue;
+ im_info->description = MPLIST_MTEXT (elt);
+ M17N_OBJECT_REF (im_info->description);
+ }
+ }
+ im_info->tick = time (NULL);
+}
- if (im_info->macros
- && (actions = mplist_get (im_info->macros, name)))
- {
- if (take_action_list (ic, actions) < 0)
- return -1;
- };
- }
- }
+
+
+static int take_action_list (MInputContext *ic, MPlist *action_list);
+static void preedit_commit (MInputContext *ic);
+
+static void
+shift_state (MInputContext *ic, MSymbol state_name)
+{
+ MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
+ MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
+ MIMState *orig_state = ic_info->state, *state;
+
+ /* Find a state to shift to. If not found, shift to the initial
+ state. */
+ if (state_name == Mt)
+ {
+ if (! ic_info->prev_state)
+ return;
+ state = ic_info->prev_state;
+ }
+ else if (state_name == Mnil)
+ {
+ state = (MIMState *) MPLIST_VAL (im_info->states);
+ }
+ else
+ {
+ state = (MIMState *) mplist_get (im_info->states, state_name);
+ if (! state)
+ state = (MIMState *) MPLIST_VAL (im_info->states);
+ }
+
+ MDEBUG_PRINT1 ("\n [IM] (shift %s)", MSYMBOL_NAME (state->name));
+
+ /* Enter the new state. */
+ ic_info->state = state;
+ ic_info->map = state->map;
+ ic_info->state_key_head = ic_info->key_head;
+ if (state == (MIMState *) MPLIST_VAL (im_info->states)
+ && orig_state)
+ /* We have shifted to the initial state. */
+ preedit_commit (ic);
+ mtext_cpy (ic_info->preedit_saved, ic->preedit);
+ ic_info->state_pos = ic->cursor_pos;
+ if (state != orig_state)
+ {
+ if (state == (MIMState *) MPLIST_VAL (im_info->states))
+ {
+ /* Shifted to the initial state. */
+ ic_info->prev_state = NULL;
+ M17N_OBJECT_UNREF (ic_info->vars_saved);
+ ic_info->vars_saved = mplist_copy (ic_info->vars);
+ }
+ else
+ ic_info->prev_state = orig_state;
+
+ if (state->title)
+ ic->status = state->title;
+ else
+ ic->status = im_info->title;
+ ic->status_changed = 1;
+ if (ic_info->map == ic_info->state->map
+ && ic_info->map->map_actions)
+ {
+ MDEBUG_PRINT (" init-actions:");
+ take_action_list (ic, ic_info->map->map_actions);
+ }
+ }
+}
+
+/* Find a candidate group that contains a candidate number INDEX from
+ PLIST. Set START_INDEX to the first candidate number of the group,
+ END_INDEX to the last candidate number plus 1, GROUP_INDEX to the
+ candidate group number if they are non-NULL. If INDEX is -1, find
+ the last candidate group. */
+
+static MPlist *
+find_candidates_group (MPlist *plist, int index,
+ int *start_index, int *end_index, int *group_index)
+{
+ int i = 0, gidx = 0, len;
+
+ MPLIST_DO (plist, plist)
+ {
+ if (MPLIST_MTEXT_P (plist))
+ len = mtext_nchars (MPLIST_MTEXT (plist));
+ else
+ len = mplist_length (MPLIST_PLIST (plist));
+ if (index < 0 ? MPLIST_TAIL_P (MPLIST_NEXT (plist))
+ : i + len > index)
+ {
+ if (start_index)
+ *start_index = i;
+ if (end_index)
+ *end_index = i + len;
+ if (group_index)
+ *group_index = gidx;
+ return plist;
+ }
+ i += len;
+ gidx++;
+ }
+ return NULL;
+}
+
+/* Adjust markers for the change of preedit text.
+ If FROM == TO, the change is insertion of INS chars.
+ If FROM < TO and INS == 0, the change is deletion of the range.
+ If FROM < TO and INS > 0, the change is replacement. */
+
+static void
+adjust_markers (MInputContext *ic, int from, int to, int ins)
+{
+ MInputContextInfo *ic_info = ((MInputContext *) ic)->info;
+ MPlist *markers;
+
+ if (from == to)
+ {
+ MPLIST_DO (markers, ic_info->markers)
+ if (MPLIST_INTEGER (markers) > from)
+ MPLIST_VAL (markers) = (void *) (MPLIST_INTEGER (markers) + ins);
+ if (ic->cursor_pos >= from)
+ ic->cursor_pos += ins;
+ }
+ else
+ {
+ MPLIST_DO (markers, ic_info->markers)
+ {
+ if (MPLIST_INTEGER (markers) >= to)
+ MPLIST_VAL (markers)
+ = (void *) (MPLIST_INTEGER (markers) + ins - (to - from));
+ else if (MPLIST_INTEGER (markers) > from)
+ MPLIST_VAL (markers) = (void *) from;
+ }
+ if (ic->cursor_pos >= to)
+ ic->cursor_pos += ins - (to - from);
+ else if (ic->cursor_pos > from)
+ ic->cursor_pos = from;
+ }
+}
+
+
+static void
+preedit_insert (MInputContext *ic, int pos, MText *mt, int c)
+{
+ int nchars = mt ? mtext_nchars (mt) : 1;
+
+ if (mt)
+ mtext_ins (ic->preedit, pos, mt);
+ else
+ mtext_ins_char (ic->preedit, pos, c, 1);
+ adjust_markers (ic, pos, pos, nchars);
+ ic->preedit_changed = 1;
+}
+
+
+static void
+preedit_delete (MInputContext *ic, int from, int to)
+{
+ mtext_del (ic->preedit, from, to);
+ adjust_markers (ic, from, to, 0);
+ ic->preedit_changed = 1;
+}
+
+static void
+preedit_replace (MInputContext *ic, int from, int to, MText *mt, int c)
+{
+ int ins;
+
+ mtext_del (ic->preedit, from, to);
+ if (mt)
+ {
+ mtext_ins (ic->preedit, from, mt);
+ ins = mtext_nchars (mt);
+ }
+ else
+ {
+ mtext_ins_char (ic->preedit, from, c, 1);
+ ins = 1;
+ }
+ adjust_markers (ic, from, to, ins);
+ ic->preedit_changed = 1;
+}
+
+
+static void
+preedit_commit (MInputContext *ic)
+{
+ MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
+ int preedit_len = mtext_nchars (ic->preedit);
+
+ if (preedit_len > 0)
+ {
+ MPlist *p;
+
+ mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit),
+ Mcandidate_list, NULL, 0);
+ mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit),
+ Mcandidate_index, NULL, 0);
+ mtext_cat (ic->produced, ic->preedit);
+ if (mdebug__flag & mdebug_mask)
+ {
+ int i;
+
+ MDEBUG_PRINT (" (commit");
+ for (i = 0; i < mtext_nchars (ic->preedit); i++)
+ MDEBUG_PRINT1 (" U+%04X", mtext_ref_char (ic->preedit, i));
+ MDEBUG_PRINT (")");
+ }
+
+ mtext_reset (ic->preedit);
+ mtext_reset (ic_info->preedit_saved);
+ MPLIST_DO (p, ic_info->markers)
+ MPLIST_VAL (p) = 0;
+ ic->cursor_pos = ic_info->state_pos = 0;
+ ic->preedit_changed = 1;
+ ic_info->commit_key_head = ic_info->key_head;
+ }
+ if (ic->candidate_list)
+ {
+ M17N_OBJECT_UNREF (ic->candidate_list);
+ ic->candidate_list = NULL;
+ ic->candidate_index = 0;
+ ic->candidate_from = ic->candidate_to = 0;
+ ic->candidates_changed = MINPUT_CANDIDATES_LIST_CHANGED;
+ if (ic->candidate_show)
+ {
+ ic->candidate_show = 0;
+ ic->candidates_changed |= MINPUT_CANDIDATES_SHOW_CHANGED;
+ }
+ }
+}
+
+static int
+new_index (MInputContext *ic, int current, int limit, MSymbol sym, MText *mt)
+{
+ int code = marker_code (sym, 0);
+
+ if (mt && (code == '[' || code == ']'))
+ {
+ int pos = current;
+
+ if (code == '[' && current > 0)
+ {
+ if (mtext_prop_range (mt, Mcandidate_list, pos - 1, &pos, NULL, 1)
+ && pos > 0)
+ current = pos;
+ }
+ else if (code == ']' && current < mtext_nchars (mt))
+ {
+ if (mtext_prop_range (mt, Mcandidate_list, pos, NULL, &pos, 1))
+ current = pos;
+ }
+ return current;
+ }
+ if (code >= 0)
+ return (code == '<' ? 0
+ : code == '>' ? limit
+ : code == '-' ? current - 1
+ : code == '+' ? current + 1
+ : code == '=' ? current
+ : code - '0' > limit ? limit
+ : code - '0');
+ if (! ic)
+ return 0;
+ return (int) mplist_get (((MInputContextInfo *) ic->info)->markers, sym);
+}
+
+static void
+update_candidate (MInputContext *ic, MTextProperty *prop, int idx)
+{
+ int from = mtext_property_start (prop);
+ int to = mtext_property_end (prop);
+ int start;
+ MPlist *candidate_list = mtext_property_value (prop);
+ MPlist *group = find_candidates_group (candidate_list, idx, &start,
+ NULL, NULL);
+ int ingroup_index = idx - start;
+ MText *mt;
+
+ if (MPLIST_MTEXT_P (group))
+ {
+ mt = MPLIST_MTEXT (group);
+ preedit_replace (ic, from, to, NULL, mtext_ref_char (mt, ingroup_index));
+ to = from + 1;
+ }
+ else
+ {
+ int i;
+ MPlist *plist;
+
+ for (i = 0, plist = MPLIST_PLIST (group); i < ingroup_index;
+ i++, plist = MPLIST_NEXT (plist));
+ mt = MPLIST_MTEXT (plist);
+ preedit_replace (ic, from, to, mt, 0);
+ to = from + mtext_nchars (mt);
+ }
+ mtext_put_prop (ic->preedit, from, to, Mcandidate_list, candidate_list);
+ mtext_put_prop (ic->preedit, from, to, Mcandidate_index, (void *) idx);
+ ic->cursor_pos = to;
+}
+
+static MCharset *
+get_select_charset (MInputContextInfo * ic_info)
+{
+ MPlist *plist = resolve_variable (ic_info, Mcandidates_charset);
+ MSymbol sym;
+
+ if (! MPLIST_VAL (plist))
+ return NULL;
+ sym = MPLIST_SYMBOL (plist);
+ if (sym == Mnil)
+ return NULL;
+ return MCHARSET (sym);
+}
+
+static MPlist *
+adjust_candidates (MPlist *plist, MCharset *charset)
+{
+ MPlist *pl;
+
+ /* plist ::= MTEXT ... | PLIST ... */
+ plist = mplist_copy (plist);
+ if (MPLIST_MTEXT_P (plist))
+ {
+ pl = plist;
+ while (! MPLIST_TAIL_P (pl))
+ {
+ /* pl ::= MTEXT ... */
+ MText *mt = MPLIST_MTEXT (pl);
+ int mt_copied = 0;
+ int i, c;
+
+ for (i = mtext_nchars (mt) - 1; i >= 0; i--)
+ {
+ c = mtext_ref_char (mt, i);
+ if (ENCODE_CHAR (charset, c) == MCHAR_INVALID_CODE)
+ {
+ if (! mt_copied)
+ {
+ mt = mtext_dup (mt);
+ mplist_set (pl, Mtext, mt);
+ M17N_OBJECT_UNREF (mt);
+ mt_copied = 1;
+ }
+ mtext_del (mt, i, i + 1);
+ }
+ }
+ if (mtext_len (mt) > 0)
+ pl = MPLIST_NEXT (pl);
+ else
+ {
+ mplist_pop (pl);
+ M17N_OBJECT_UNREF (mt);
+ }
+ }
+ }
+ else /* MPLIST_PLIST_P (plist) */
+ {
+ pl = plist;
+ while (! MPLIST_TAIL_P (pl))
+ {
+ /* pl ::= (MTEXT ...) ... */
+ MPlist *p = MPLIST_PLIST (pl);
+ int p_copied = 0;
+ /* p ::= MTEXT ... */
+ MPlist *p0 = p;
+ int n = 0;
+
+ while (! MPLIST_TAIL_P (p0))
+ {
+ MText *mt = MPLIST_MTEXT (p0);
+ int i, c;
+
+ for (i = mtext_nchars (mt) - 1; i >= 0; i--)
+ {
+ c = mtext_ref_char (mt, i);
+ if (ENCODE_CHAR (charset, c) == MCHAR_INVALID_CODE)
+ break;
+ }
+ if (i < 0)
+ {
+ p0 = MPLIST_NEXT (p0);
+ n++;
+ }
+ else
+ {
+ if (! p_copied)
+ {
+ p = mplist_copy (p);
+ mplist_set (pl, Mplist, p);
+ M17N_OBJECT_UNREF (p);
+ p_copied = 1;
+ p0 = p;
+ while (n-- > 0)
+ p0 = MPLIST_NEXT (p0);
+ }
+ mplist_pop (p0);
+ M17N_OBJECT_UNREF (mt);
+ }
+ }
+ if (! MPLIST_TAIL_P (p))
+ pl = MPLIST_NEXT (pl);
+ else
+ {
+ mplist_pop (pl);
+ M17N_OBJECT_UNREF (p);
+ }
+ }
+ }
+ if (MPLIST_TAIL_P (plist))
+ {
+ M17N_OBJECT_UNREF (plist);
+ return NULL;
+ }
+ return plist;
+}
+
+static MPlist *
+get_candidate_list (MInputContextInfo *ic_info, MPlist *args)
+{
+ MCharset *charset = get_select_charset (ic_info);
+ MPlist *plist;
+ int column;
+ int i, len;
+
+ plist = resolve_variable (ic_info, Mcandidates_group_size);
+ column = MPLIST_INTEGER (plist);
+
+ plist = MPLIST_PLIST (args);
+ if (charset)
+ plist = adjust_candidates (plist, charset);
+
+ if (plist && column > 0)
+ {
+ if (MPLIST_MTEXT_P (plist))
+ {
+ MText *mt = MPLIST_MTEXT (plist);
+ MPlist *next = MPLIST_NEXT (plist);
+
+ if (MPLIST_TAIL_P (next))
+ M17N_OBJECT_REF (mt);
+ else
+ {
+ mt = mtext_dup (mt);
+ while (! MPLIST_TAIL_P (next))
+ {
+ mt = mtext_cat (mt, MPLIST_MTEXT (next));
+ next = MPLIST_NEXT (next);
+ }
+ }
+ if (charset)
+ M17N_OBJECT_UNREF (plist);
+ plist = mplist ();
+ len = mtext_nchars (mt);
+ if (len <= column)
+ mplist_add (plist, Mtext, mt);
+ else
+ {
+ for (i = 0; i < len; i += column)
+ {
+ int to = (i + column < len ? i + column : len);
+ MText *sub = mtext_copy (mtext (), 0, mt, i, to);
+
+ mplist_add (plist, Mtext, sub);
+ M17N_OBJECT_UNREF (sub);
+ }
+ }
+ M17N_OBJECT_UNREF (mt);
+ }
+ else if (! MPLIST_TAIL_P (plist))
+ {
+ MPlist *tail = plist;
+ MPlist *new = mplist ();
+ MPlist *this = mplist ();
+ int count = 0;
+
+ MPLIST_DO (tail, tail)
+ {
+ MPlist *p = MPLIST_PLIST (tail);
+
+ MPLIST_DO (p, p)
+ {
+ MText *mt = MPLIST_MTEXT (p);
+
+ if (count == column)
+ {
+ mplist_add (new, Mplist, this);
+ M17N_OBJECT_UNREF (this);
+ this = mplist ();
+ count = 0;
+ }
+ mplist_add (this, Mtext, mt);
+ count++;
+ }
+ }
+ mplist_add (new, Mplist, this);
+ M17N_OBJECT_UNREF (this);
+ mplist_set (plist, Mnil, NULL);
+ MPLIST_DO (tail, new)
+ {
+ MPlist *elt = MPLIST_PLIST (tail);
+
+ mplist_add (plist, Mplist, elt);
+ }
+ M17N_OBJECT_UNREF (new);
+ }
+ }
+
+ return plist;
+}
+
+
+static MPlist *
+regularize_action (MPlist *action_list, MInputContextInfo *ic_info)
+{
+ MPlist *action = NULL;
+ MSymbol name;
+ MPlist *args;
+
+ if (MPLIST_SYMBOL_P (action_list))
+ {
+ MSymbol var = MPLIST_SYMBOL (action_list);
+ MPlist *p;
+
+ MPLIST_DO (p, ic_info->vars)
+ if (MPLIST_SYMBOL (MPLIST_PLIST (p)) == var)
+ break;
+ if (MPLIST_TAIL_P (p))
+ return NULL;
+ action = MPLIST_NEXT (MPLIST_PLIST (p));
+ mplist_set (action_list, MPLIST_KEY (action), MPLIST_VAL (action));
+ }
+
+ if (MPLIST_PLIST_P (action_list))
+ {
+ action = MPLIST_PLIST (action_list);
+ if (MPLIST_SYMBOL_P (action))
+ {
+ name = MPLIST_SYMBOL (action);
+ args = MPLIST_NEXT (action);
+ if (name == Minsert
+ && MPLIST_PLIST_P (args))
+ mplist_set (action, Msymbol, M_candidates);
+ }
+ else if (MPLIST_MTEXT_P (action) || MPLIST_PLIST_P (action))
+ {
+ action = mplist ();
+ mplist_push (action, Mplist, MPLIST_VAL (action_list));
+ mplist_push (action, Msymbol, M_candidates);
+ mplist_set (action_list, Mplist, action);
+ M17N_OBJECT_UNREF (action);
+ }
+ }
+ else if (MPLIST_MTEXT_P (action_list) || MPLIST_INTEGER_P (action_list))
+ {
+ action = mplist ();
+ mplist_push (action, MPLIST_KEY (action_list), MPLIST_VAL (action_list));
+ mplist_push (action, Msymbol, Minsert);
+ mplist_set (action_list, Mplist, action);
+ M17N_OBJECT_UNREF (action);
+ }
+ return action;
+}
+
+/* Perform list of actions in ACTION_LIST for the current input
+ context IC. If unhandle action was not performed, return 0.
+ Otherwise, return -1. */
+
+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)
+ {
+ MPlist *action = regularize_action (action_list, ic_info);
+ MSymbol name;
+ MPlist *args;
+
+ if (! action)
+ continue;
+ name = MPLIST_SYMBOL (action);
+ args = MPLIST_NEXT (action);
+
+ MDEBUG_PRINT1 (" %s", MSYMBOL_NAME (name));
+ if (name == Minsert)
+ {
+ if (MPLIST_SYMBOL_P (args))
+ {
+ args = resolve_variable (ic_info, MPLIST_SYMBOL (args));
+ if (! MPLIST_MTEXT_P (args) && ! MPLIST_INTEGER_P (args))
+ continue;
+ }
+ if (MPLIST_MTEXT_P (args))
+ preedit_insert (ic, ic->cursor_pos, MPLIST_MTEXT (args), 0);
+ else /* MPLIST_INTEGER_P (args)) */
+ preedit_insert (ic, ic->cursor_pos, NULL, MPLIST_INTEGER (args));
+ }
+ else if (name == M_candidates)
+ {
+ MPlist *plist = get_candidate_list (ic_info, args);
+ int len;
+
+ if (! plist || (MPLIST_PLIST_P (plist) && MPLIST_TAIL_P (plist)))
+ continue;
+ if (MPLIST_MTEXT_P (plist))
+ {
+ preedit_insert (ic, ic->cursor_pos, NULL,
+ mtext_ref_char (MPLIST_MTEXT (plist), 0));
+ len = 1;
+ }
+ else if (MPLIST_TAIL_P (MPLIST_PLIST (plist)))
+ continue;
+ else
+ {
+ MText * mt = MPLIST_MTEXT (MPLIST_PLIST (plist));
+
+ preedit_insert (ic, ic->cursor_pos, mt, 0);
+ len = mtext_nchars (mt);
+ }
+ mtext_put_prop (ic->preedit,
+ ic->cursor_pos - len, ic->cursor_pos,
+ Mcandidate_list, plist);
+ mtext_put_prop (ic->preedit,
+ ic->cursor_pos - len, ic->cursor_pos,
+ Mcandidate_index, (void *) 0);
+ }
+ else if (name == Mselect)
+ {
+ int start, end;
+ int code, idx, gindex;
+ int pos = ic->cursor_pos;
+ MPlist *group;
+ int idx_decided = 0;
+
+ if (pos == 0
+ || ! (prop = mtext_get_property (ic->preedit, pos - 1,
+ Mcandidate_list)))
+ continue;
+ idx = (int) mtext_get_prop (ic->preedit, pos - 1, Mcandidate_index);
+ group = find_candidates_group (mtext_property_value (prop), idx,
+ &start, &end, &gindex);
+ if (MPLIST_SYMBOL_P (args))
+ {
+ code = marker_code (MPLIST_SYMBOL (args), 0);
+ if (code < 0)
+ {
+ args = resolve_variable (ic_info, MPLIST_SYMBOL (args));
+ if (! MPLIST_INTEGER_P (args))
+ continue;
+ idx = start + MPLIST_INTEGER (args);
+ if (idx < start || idx >= end)
+ continue;
+ idx_decided = 1;
+ }
+ }
+ else
+ code = -1;
+
+ if (code != '[' && code != ']')
+ {
+ if (! idx_decided)
+ idx = (start
+ + (code >= 0
+ ? new_index (NULL, ic->candidate_index - start,
+ end - start - 1, MPLIST_SYMBOL (args),
+ NULL)
+ : MPLIST_INTEGER (args)));
+ if (idx < 0)
+ {
+ find_candidates_group (mtext_property_value (prop), -1,
+ NULL, &end, NULL);
+ idx = end - 1;
+ }
+ else if (idx >= end
+ && MPLIST_TAIL_P (MPLIST_NEXT (group)))
+ idx = 0;
+ }
+ else
+ {
+ int ingroup_index = idx - start;
+ int len;
+
+ group = mtext_property_value (prop);
+ len = mplist_length (group);
+ if (code == '[')
+ {
+ gindex--;
+ if (gindex < 0)
+ gindex = len - 1;;
+ }
+ else
+ {
+ gindex++;
+ if (gindex >= len)
+ gindex = 0;
+ }
+ for (idx = 0; gindex > 0; gindex--, group = MPLIST_NEXT (group))
+ idx += (MPLIST_MTEXT_P (group)
+ ? mtext_nchars (MPLIST_MTEXT (group))
+ : mplist_length (MPLIST_PLIST (group)));
+ len = (MPLIST_MTEXT_P (group)
+ ? mtext_nchars (MPLIST_MTEXT (group))
+ : mplist_length (MPLIST_PLIST (group)));
+ if (ingroup_index >= len)
+ ingroup_index = len - 1;
+ idx += ingroup_index;
+ }
+ update_candidate (ic, prop, idx);
+ MDEBUG_PRINT1 ("(%d)", idx);
+ }
+ else if (name == Mshow)
+ ic->candidate_show = 1;
+ else if (name == Mhide)
+ ic->candidate_show = 0;
+ else if (name == Mdelete)
+ {
+ int len = mtext_nchars (ic->preedit);
+ int pos;
+ int to;
+
+ if (MPLIST_SYMBOL_P (args)
+ && (pos = surrounding_pos (MPLIST_SYMBOL (args))) != 0)
+ {
+ to = ic->cursor_pos + pos;
+ if (to < 0)
+ {
+ delete_surrounding_text (ic, to);
+ to = 0;
+ }
+ else if (to > len)
+ {
+ delete_surrounding_text (ic, to - len);
+ to = len;
+ }
+ }
+ else
+ {
+ to = (MPLIST_SYMBOL_P (args)
+ ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
+ ic->preedit)
+ : MPLIST_INTEGER (args));
+ if (to < 0)
+ to = 0;
+ else if (to > len)
+ to = len;
+ }
+ MDEBUG_PRINT1 ("(%d)", to - ic->cursor_pos);
+ if (to < ic->cursor_pos)
+ preedit_delete (ic, to, ic->cursor_pos);
+ else if (to > ic->cursor_pos)
+ preedit_delete (ic, ic->cursor_pos, to);
+ }
+ else if (name == Mmove)
+ {
+ int len = mtext_nchars (ic->preedit);
+ int pos
+ = (MPLIST_SYMBOL_P (args)
+ ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
+ ic->preedit)
+ : MPLIST_INTEGER (args));
+
+ if (pos < 0)
+ pos = 0;
+ else if (pos > len)
+ pos = len;
+ if (pos != ic->cursor_pos)
+ {
+ ic->cursor_pos = pos;
+ ic->preedit_changed = 1;
+ }
+ MDEBUG_PRINT1 ("(%d)", ic->cursor_pos);
+ }
+ else if (name == Mmark)
+ {
+ int code = marker_code (MPLIST_SYMBOL (args), 0);
+
+ if (code < 0)
+ {
+ mplist_put (ic_info->markers, MPLIST_SYMBOL (args),
+ (void *) ic->cursor_pos);
+ MDEBUG_PRINT1 ("(%d)", ic->cursor_pos);
+ }
+ }
+ else if (name == Mpushback)
+ {
+ if (MPLIST_INTEGER_P (args) || MPLIST_SYMBOL_P (args))
+ {
+ int num;
+
+ if (MPLIST_SYMBOL_P (args))
+ {
+ args = resolve_variable (ic_info, MPLIST_SYMBOL (args));
+ if (MPLIST_INTEGER_P (args))
+ num = MPLIST_INTEGER (args);
+ else
+ num = 0;
+ }
+ else
+ num = MPLIST_INTEGER (args);
+
+ if (num > 0)
+ ic_info->key_head -= num;
+ else if (num == 0)
+ ic_info->key_head = 0;
+ else
+ ic_info->key_head = - num;
+ if (ic_info->key_head > ic_info->used)
+ ic_info->key_head = ic_info->used;
+ }
+ else if (MPLIST_MTEXT_P (args))
+ {
+ MText *mt = MPLIST_MTEXT (args);
+ int i, len = mtext_nchars (mt);
+ MSymbol key;
+
+ ic_info->key_head--;
+ for (i = 0; i < len; i++)
+ {
+ key = one_char_symbol[MTEXT_DATA (mt)[i]];
+ if (ic_info->key_head + i < ic_info->used)
+ ic_info->keys[ic_info->key_head + i] = key;
+ else
+ MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
+ }
+ }
+ else
+ {
+ MPlist *plist = MPLIST_PLIST (args), *pl;
+ int i = 0;
+ MSymbol key;
+
+ ic_info->key_head--;
+
+ MPLIST_DO (pl, plist)
+ {
+ key = MPLIST_SYMBOL (pl);
+ if (ic_info->key_head < ic_info->used)
+ ic_info->keys[ic_info->key_head + i] = key;
+ else
+ MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
+ i++;
+ }
+ }
+ }
+ else if (name == Mpop)
+ {
+ if (ic_info->key_head < ic_info->used)
+ MLIST_DELETE1 (ic_info, keys, ic_info->key_head, 1);
+ }
+ else if (name == Mcall)
+ {
+ MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
+ MIMExternalFunc func = NULL;
+ MSymbol module, func_name;
+ MPlist *func_args, *val;
+ int ret = 0;
+
+ module = MPLIST_SYMBOL (args);
+ args = MPLIST_NEXT (args);
+ func_name = MPLIST_SYMBOL (args);
+
+ if (im_info->externals)
+ {
+ MIMExternalModule *external
+ = (MIMExternalModule *) mplist_get (im_info->externals,
+ module);
+ if (external)
+ func = ((MIMExternalFunc)
+ mplist_get_func (external->func_list, func_name));
+ }
+ if (! func)
+ continue;
+ func_args = mplist ();
+ mplist_add (func_args, Mt, ic);
+ MPLIST_DO (args, MPLIST_NEXT (args))
+ {
+ int code;
+
+ if (MPLIST_KEY (args) == Msymbol
+ && MPLIST_KEY (args) != Mnil
+ && (code = marker_code (MPLIST_SYMBOL (args), 0)) >= 0)
+ {
+ code = new_index (ic, ic->cursor_pos,
+ mtext_nchars (ic->preedit),
+ MPLIST_SYMBOL (args), ic->preedit);
+ mplist_add (func_args, Minteger, (void *) code);
+ }
+ else
+ mplist_add (func_args, MPLIST_KEY (args), MPLIST_VAL (args));
+ }
+ val = (func) (func_args);
+ M17N_OBJECT_UNREF (func_args);
+ if (val && ! MPLIST_TAIL_P (val))
+ ret = take_action_list (ic, val);
+ M17N_OBJECT_UNREF (val);
+ if (ret < 0)
+ return ret;
+ }
+ else if (name == Mshift)
+ {
+ shift_state (ic, MPLIST_SYMBOL (args));
+ }
+ else if (name == Mundo)
+ {
+ int intarg = (MPLIST_TAIL_P (args)
+ ? ic_info->used - 2
+ : integer_value (ic, args, NULL, 0));
+
+ mtext_reset (ic->preedit);
+ mtext_reset (ic_info->preedit_saved);
+ mtext_reset (ic->produced);
+ M17N_OBJECT_UNREF (ic_info->vars);
+ ic_info->vars = mplist_copy (ic_info->vars_saved);
+ ic->cursor_pos = ic_info->state_pos = 0;
+ ic_info->state_key_head = ic_info->key_head
+ = ic_info->commit_key_head = 0;
+
+ shift_state (ic, Mnil);
+ if (intarg < 0)
+ {
+ if (MPLIST_TAIL_P (args))
+ {
+ ic_info->used = 0;
+ return -1;
+ }
+ ic_info->used += intarg;
+ }
+ else
+ ic_info->used = intarg;
+ break;
+ }
+ else if (name == Mset || name == Madd || name == Msub
+ || name == Mmul || name == Mdiv)
+ {
+ MSymbol sym = MPLIST_SYMBOL (args);
+ int val1, val2;
+ MPlist *value;
+ char *op;
+
+ val1 = integer_value (ic, args, &value, 0);
+ args = MPLIST_NEXT (args);
+ val2 = resolve_expression (ic, args);
+ if (name == Mset)
+ val1 = val2, op = "=";
+ else if (name == Madd)
+ val1 += val2, op = "+=";
+ else if (name == Msub)
+ val1 -= val2, op = "-=";
+ else if (name == Mmul)
+ val1 *= val2, op = "*=";
+ else
+ val1 /= val2, op = "/=";
+ MDEBUG_PRINT4 ("(%s %s 0x%X(%d))",
+ MSYMBOL_NAME (sym), op, val1, val1);
+ if (value)
+ mplist_set (value, Minteger, (void *) val1);
+ }
+ else if (name == Mequal || name == Mless || name == Mgreater
+ || name == Mless_equal || name == Mgreater_equal)
+ {
+ int val1, val2;
+ MPlist *actions1, *actions2;
+ int ret = 0;
+
+ val1 = resolve_expression (ic, args);
+ args = MPLIST_NEXT (args);
+ val2 = resolve_expression (ic, args);
+ args = MPLIST_NEXT (args);
+ actions1 = MPLIST_PLIST (args);
+ args = MPLIST_NEXT (args);
+ if (MPLIST_TAIL_P (args))
+ actions2 = NULL;
+ else
+ actions2 = MPLIST_PLIST (args);
+ MDEBUG_PRINT3 ("(%d %s %d)? ", val1, MSYMBOL_NAME (name), val2);
+ if (name == Mequal ? val1 == val2
+ : name == Mless ? val1 < val2
+ : name == Mgreater ? val1 > val2
+ : name == Mless_equal ? val1 <= val2
+ : val1 >= val2)
+ {
+ MDEBUG_PRINT ("ok");
+ ret = take_action_list (ic, actions1);
+ }
+ else
+ {
+ MDEBUG_PRINT ("no");
+ if (actions2)
+ ret = take_action_list (ic, actions2);
+ }
+ if (ret < 0)
+ return ret;
+ }
+ else if (name == Mcond)
+ {
+ int idx = 0;
+
+ MPLIST_DO (args, args)
+ {
+ MPlist *cond;
+
+ idx++;
+ if (! MPLIST_PLIST (args))
+ continue;
+ cond = MPLIST_PLIST (args);
+ if (resolve_expression (ic, cond) != 0)
+ {
+ MDEBUG_PRINT1 ("(%dth)", idx);
+ if (take_action_list (ic, MPLIST_NEXT (cond)) < 0)
+ return -1;;
+ break;
+ }
+ }
+ }
+ else if (name == Mcommit)
+ {
+ preedit_commit (ic);
+ }
+ else if (name == Munhandle)
+ {
+ preedit_commit (ic);
+ return -1;
+ }
+ else
+ {
+ MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
+ MPlist *actions;
+
+ if (im_info->macros
+ && (actions = mplist_get (im_info->macros, name)))
+ {
+ if (take_action_list (ic, actions) < 0)
+ return -1;
+ };
+ }
+ }
+
+ 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;
+}
+
+
+/* Handle the input key KEY in the current state and map specified in
+ the input context IC. If KEY is handled correctly, return 0.
+ Otherwise, return -1. */
+
+static int
+handle_key (MInputContext *ic)
+{
+ MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
+ MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
+ MIMMap *map = ic_info->map;
+ MIMMap *submap = NULL;
+ MSymbol key = ic_info->keys[ic_info->key_head];
+ MSymbol alias = Mnil;
+ int i;
+
+ MDEBUG_PRINT2 (" [IM] handle `%s' in state %s",
+ msymbol_name (key), MSYMBOL_NAME (ic_info->state->name));
+
+ if (map->submaps)
+ {
+ submap = mplist_get (map->submaps, key);
+ alias = key;
+ while (! submap
+ && (alias = msymbol_get (alias, M_key_alias))
+ && alias != key)
+ submap = mplist_get (map->submaps, alias);
+ }
+
+ if (submap)
+ {
+ if (! alias || alias == key)
+ MDEBUG_PRINT (" submap-found");
+ else
+ MDEBUG_PRINT1 (" submap-found (by alias `%s')", MSYMBOL_NAME (alias));
+ mtext_cpy (ic->preedit, ic_info->preedit_saved);
+ ic->preedit_changed = 1;
+ ic->cursor_pos = ic_info->state_pos;
+ ic_info->key_head++;
+ ic_info->map = map = submap;
+ if (map->map_actions)
+ {
+ MDEBUG_PRINT (" map-actions:");
+ if (take_action_list (ic, map->map_actions) < 0)
+ {
+ MDEBUG_PRINT ("\n");
+ return -1;
+ }
+ }
+ else if (map->submaps)
+ {
+ for (i = ic_info->state_key_head; i < ic_info->key_head; i++)
+ {
+ MSymbol key = ic_info->keys[i];
+ char *name = msymbol_name (key);
+
+ if (! name[0] || ! name[1])
+ mtext_ins_char (ic->preedit, ic->cursor_pos++, name[0], 1);
+ }
+ }
+
+ /* If this is the terminal map or we have shifted to another
+ state, perform branch actions (if any). */
+ if (! map->submaps || map != ic_info->map)
+ {
+ if (map->branch_actions)
+ {
+ MDEBUG_PRINT (" branch-actions:");
+ if (take_action_list (ic, map->branch_actions) < 0)
+ {
+ MDEBUG_PRINT ("\n");
+ return -1;
+ }
+ }
+ /* If MAP is still not the root map, shift to the current
+ state. */
+ if (ic_info->map != ic_info->state->map)
+ shift_state (ic, ic_info->state->name);
+ }
+ }
+ else
+ {
+ /* MAP can not handle KEY. */
+
+ /* Perform branch actions if any. */
+ if (map->branch_actions)
+ {
+ MDEBUG_PRINT (" branch-actions:");
+ if (take_action_list (ic, map->branch_actions) < 0)
+ {
+ MDEBUG_PRINT ("\n");
+ return -1;
+ }
+ }
+
+ if (map == ic_info->map)
+ {
+ /* The above branch actions didn't change the state. */
+
+ /* If MAP is the root map of the initial state, and there
+ still exist an unhandled key, it means that the current
+ input method can not handle it. */
+ if (map == ((MIMState *) MPLIST_VAL (im_info->states))->map
+ && ic_info->key_head < ic_info->used)
+ {
+ MDEBUG_PRINT (" unhandled\n");
+ return -1;
+ }
+
+ if (map != ic_info->state->map)
+ {
+ /* MAP is not the root map. Shift to the root map of the
+ current state. */
+ shift_state (ic, ic_info->state->name);
+ }
+ else if (! map->branch_actions)
+ {
+ /* MAP is the root map without any default branch
+ actions. Shift to the initial state. */
+ shift_state (ic, Mnil);
+ }
+ }
+ }
+ MDEBUG_PRINT ("\n");
+ return 0;
+}
+
+/* Initialize IC->ic_info. */
+
+static void
+init_ic_info (MInputContext *ic)
+{
+ MInputMethodInfo *im_info = ic->im->info;
+ MInputContextInfo *ic_info = ic->info;
+ MPlist *plist;
+
+ MLIST_INIT1 (ic_info, keys, 8);;
+
+ ic_info->markers = mplist ();
+
+ ic_info->vars = mplist ();
+ if (im_info->configured_vars)
+ MPLIST_DO (plist, im_info->configured_vars)
+ {
+ MPlist *pl = MPLIST_PLIST (plist);
+ MSymbol name = MPLIST_SYMBOL (pl);
+
+ pl = MPLIST_NEXT (MPLIST_NEXT (MPLIST_NEXT (pl)));
+ if (MPLIST_KEY (pl) != Mt)
+ {
+ MPlist *p = mplist ();
+
+ mplist_push (ic_info->vars, Mplist, p);
+ M17N_OBJECT_UNREF (p);
+ mplist_add (p, Msymbol, name);
+ mplist_add (p, MPLIST_KEY (pl), MPLIST_VAL (pl));
+ }
+ }
+ ic_info->vars_saved = mplist_copy (ic_info->vars);
+
+ if (im_info->externals)
+ {
+ MPlist *func_args = mplist (), *plist;
+
+ mplist_add (func_args, Mt, ic);
+ MPLIST_DO (plist, im_info->externals)
+ {
+ MIMExternalModule *external = MPLIST_VAL (plist);
+ MIMExternalFunc func
+ = (MIMExternalFunc) mplist_get_func (external->func_list, Minit);
+
+ if (func)
+ (func) (func_args);
+ }
+ M17N_OBJECT_UNREF (func_args);
+ }
+
+ ic_info->preedit_saved = mtext ();
+ ic_info->tick = im_info->tick;
+}
+
+/* Finalize IC->ic_info. */
+
+static void
+fini_ic_info (MInputContext *ic)
+{
+ MInputMethodInfo *im_info = ic->im->info;
+ MInputContextInfo *ic_info = ic->info;
+
+ if (im_info->externals)
+ {
+ MPlist *func_args = mplist (), *plist;
+
+ mplist_add (func_args, Mt, ic);
+ MPLIST_DO (plist, im_info->externals)
+ {
+ MIMExternalModule *external = MPLIST_VAL (plist);
+ MIMExternalFunc func
+ = (MIMExternalFunc) mplist_get_func (external->func_list, Mfini);
+
+ if (func)
+ (func) (func_args);
+ }
+ M17N_OBJECT_UNREF (func_args);
+ }
+
+ MLIST_FREE1 (ic_info, keys);
+ M17N_OBJECT_UNREF (ic_info->preedit_saved);
+ M17N_OBJECT_UNREF (ic_info->markers);
+ M17N_OBJECT_UNREF (ic_info->vars);
+ M17N_OBJECT_UNREF (ic_info->vars_saved);
+ M17N_OBJECT_UNREF (ic_info->preceding_text);
+ M17N_OBJECT_UNREF (ic_info->following_text);
+
+ memset (ic_info, 0, sizeof (MInputContextInfo));
+}
+
+static void
+re_init_ic (MInputContext *ic, int reload)
+{
+ MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
+ MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
+ int status_changed, preedit_changed, cursor_pos_changed, candidates_changed;
+
+ status_changed = ic_info->state != (MIMState *) MPLIST_VAL (im_info->states);
+ preedit_changed = mtext_nchars (ic->preedit) > 0;
+ cursor_pos_changed = ic->cursor_pos > 0;
+ candidates_changed = 0;
+ if (ic->candidate_list)
+ {
+ candidates_changed |= MINPUT_CANDIDATES_LIST_CHANGED;
+ M17N_OBJECT_UNREF (ic->candidate_list);
+ ic->candidate_list = NULL;
+ }
+ if (ic->candidate_show)
+ {
+ candidates_changed |= MINPUT_CANDIDATES_SHOW_CHANGED;
+ ic->candidate_show = 0;
+ }
+ if (ic->candidate_index > 0)
+ {
+ candidates_changed |= MINPUT_CANDIDATES_INDEX_CHANGED;
+ ic->candidate_index = 0;
+ ic->candidate_from = ic->candidate_to = 0;
+ }
+ if (mtext_nchars (ic->produced) > 0)
+ mtext_reset (ic->produced);
+ if (mtext_nchars (ic->preedit) > 0)
+ mtext_reset (ic->preedit);
+ ic->cursor_pos = 0;
+ M17N_OBJECT_UNREF (ic->plist);
+ ic->plist = mplist ();
+
+ fini_ic_info (ic);
+ if (reload)
+ reload_im_info (im_info);
+ init_ic_info (ic);
+ shift_state (ic, Mnil);
+ ic->status_changed = status_changed;
+ ic->preedit_changed = preedit_changed;
+ ic->cursor_pos_changed = cursor_pos_changed;
+ ic->candidates_changed = candidates_changed;
+}
+
+static void
+reset_ic (MInputContext *ic, MSymbol ignore)
+{
+ MDEBUG_PRINT ("\n [IM] reset\n");
+ re_init_ic (ic, 0);
+}
+
+static int
+open_im (MInputMethod *im)
+{
+ MInputMethodInfo *im_info = get_im_info (im->language, im->name, Mnil, Mnil);
+
+ if (! im_info)
+ MERROR (MERROR_IM, -1);
+ im->info = im_info;
+
+ return 0;
+}
+
+static void
+close_im (MInputMethod *im)
+{
+ im->info = NULL;
+}
+
+static int
+create_ic (MInputContext *ic)
+{
+ MInputContextInfo *ic_info;
+
+ MSTRUCT_CALLOC (ic_info, MERROR_IM);
+ ic->info = ic_info;
+ init_ic_info (ic);
+ shift_state (ic, Mnil);
+ return 0;
+}
+
+static void
+destroy_ic (MInputContext *ic)
+{
+ fini_ic_info (ic);
+ free (ic->info);
+}
+
+static int
+check_reload (MInputContext *ic, MSymbol key)
+{
+ MInputMethodInfo *im_info = ic->im->info;
+ MPlist *plist = resolve_command (im_info->configured_cmds, Mat_reload);
+
+ if (! plist)
+ {
+ plist = resolve_command (global_info->configured_cmds, Mat_reload);
+ if (! plist)
+ return 0;
+ }
+ MPLIST_DO (plist, plist)
+ {
+ MSymbol this_key, alias;
+
+ if (MPLIST_MTEXT_P (plist))
+ {
+ MText *mt = MPLIST_MTEXT (plist);
+ int c = mtext_ref_char (mt, 0);
+
+ if (c >= 256)
+ continue;
+ this_key = one_char_symbol[c];
+ }
+ else
+ {
+ MPlist *pl = MPLIST_PLIST (plist);
+
+ this_key = MPLIST_SYMBOL (pl);
+ }
+ alias = this_key;
+ while (alias != key
+ && (alias = msymbol_get (alias, M_key_alias))
+ && alias != this_key);
+ if (alias == key)
+ break;
+ }
+ if (MPLIST_TAIL_P (plist))
+ return 0;
+
+ MDEBUG_PRINT ("\n [IM] reload");
+ re_init_ic (ic, 1);
+ return 1;
+}
+
+
+/** Handle the input key KEY in the current state and map of IC->info.
+ If KEY is handled but no text is produced, return 0, otherwise
+ return 1.
+
+ Ignore ARG. */
+
+static int
+filter (MInputContext *ic, MSymbol key, void *arg)
+{
+ MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
+ MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
+ int i = 0;
+
+ if (check_reload (ic, key))
+ return 0;
+
+ if (! ic_info->state)
+ {
+ ic_info->key_unhandled = 1;
+ return 0;
+ }
+ mtext_reset (ic->produced);
+ ic->status_changed = ic->preedit_changed = ic->candidates_changed = 0;
+ M17N_OBJECT_UNREF (ic_info->preceding_text);
+ M17N_OBJECT_UNREF (ic_info->following_text);
+ ic_info->preceding_text = ic_info->following_text = NULL;
+ MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
+ ic_info->key_unhandled = 0;
+
+ do {
+ if (handle_key (ic) < 0)
+ {
+ /* KEY was not handled. Delete it from the current key sequence. */
+ if (ic_info->used > 0)
+ {
+ memmove (ic_info->keys, ic_info->keys + 1,
+ sizeof (int) * (ic_info->used - 1));
+ ic_info->used--;
+ if (ic_info->state_key_head > 0)
+ ic_info->state_key_head--;
+ if (ic_info->commit_key_head > 0)
+ ic_info->commit_key_head--;
+ }
+ /* This forces returning 1. */
+ ic_info->key_unhandled = 1;
+ break;
+ }
+ if (i++ == 100)
+ {
+ mdebug_hook ();
+ reset_ic (ic, Mnil);
+ ic_info->key_unhandled = 1;
+ break;
+ }
+ /* Break the loop if all keys were handled. */
+ } while (ic_info->key_head < ic_info->used);
+
+ /* If the current map is the root of the initial state, we should
+ produce any preedit text in ic->produced. */
+ if (ic_info->map == ((MIMState *) MPLIST_VAL (im_info->states))->map)
+ preedit_commit (ic);
+
+ if (mtext_nchars (ic->produced) > 0)
+ {
+ MSymbol lang = msymbol_get (ic->im->language, Mlanguage);
+
+ if (mdebug__flag & mdebug_mask)
+ {
+ MDEBUG_PRINT (" (produced");
+ for (i = 0; i < mtext_nchars (ic->produced); i++)
+ MDEBUG_PRINT1 (" U+%04X", mtext_ref_char (ic->produced, i));
+ MDEBUG_PRINT (")");
+ }
+
+ if (lang != Mnil)
+ mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
+ Mlanguage, ic->im->language);
+ }
+ if (ic_info->commit_key_head > 0)
+ {
+ memmove (ic_info->keys, ic_info->keys + ic_info->commit_key_head,
+ sizeof (int) * (ic_info->used - ic_info->commit_key_head));
+ ic_info->used -= ic_info->commit_key_head;
+ ic_info->key_head -= ic_info->commit_key_head;
+ ic_info->state_key_head -= ic_info->commit_key_head;
+ ic_info->commit_key_head = 0;
+ }
+ if (ic_info->key_unhandled)
+ {
+ ic_info->used = 0;
+ ic_info->key_head = ic_info->state_key_head
+ = ic_info->commit_key_head = 0;
+ }
+
+ return (! ic_info->key_unhandled && mtext_nchars (ic->produced) == 0);
+}
+
+
+/** Return 1 if the last event or key was not handled, otherwise
+ return 0.
+
+ There is no need of looking up because ic->produced should already
+ contain the produced text (if any).
+
+ Ignore KEY. */
+
+static int
+lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
+{
+ mtext_cat (mt, ic->produced);
+ mtext_reset (ic->produced);
+ return (((MInputContextInfo *) ic->info)->key_unhandled ? -1 : 0);
+}
+
+
+/* Input method command handler. */
+
+/* List of all (global and local) commands.
+ (LANG:(IM-NAME:(COMMAND ...) ...) ...) ...
+ COMMAND is CMD-NAME:(mtext:DESCRIPTION plist:KEYSEQ ...))
+ Global commands are stored as (t (t COMMAND ...)) */
+
+
+/* Input method variable handler. */
+
+
+/* Support functions for mdebug_dump_im. */
+
+static void
+dump_im_map (MPlist *map_list, int indent)
+{
+ char *prefix;
+ MSymbol key = MPLIST_KEY (map_list);
+ MIMMap *map = (MIMMap *) MPLIST_VAL (map_list);
+
+ prefix = (char *) alloca (indent + 1);
+ memset (prefix, 32, indent);
+ prefix[indent] = '\0';
+
+ fprintf (stderr, "(\"%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);
+ dump_im_map (map_list, indent + 2);
+ }
+ }
+ if (map->branch_actions)
+ {
+ fprintf (stderr, "\n%s (branch\n%s ", prefix, prefix);
+ mdebug_dump_plist (map->branch_actions, indent + 4);
+ fprintf (stderr, ")");
+ }
+ fprintf (stderr, ")");
+}
+
+
+static void
+dump_im_state (MIMState *state, int indent)
+{
+ char *prefix;
+ MPlist *map_list;
+
+ prefix = (char *) alloca (indent + 1);
+ memset (prefix, 32, indent);
+ prefix[indent] = '\0';
+
+ fprintf (stderr, "(%s", msymbol_name (state->name));
+ if (state->map->submaps)
+ {
+ MPLIST_DO (map_list, state->map->submaps)
+ {
+ fprintf (stderr, "\n%s ", prefix);
+ dump_im_map (map_list, indent + 2);
+ }
+ }
+ fprintf (stderr, ")");
+}
+
+
+
+int
+minput__init ()
+{
+ Minput_driver = msymbol ("input-driver");
+
+ Minput_preedit_start = msymbol ("input-preedit-start");
+ Minput_preedit_done = msymbol ("input-preedit-done");
+ Minput_preedit_draw = msymbol ("input-preedit-draw");
+ Minput_status_start = msymbol ("input-status-start");
+ Minput_status_done = msymbol ("input-status-done");
+ Minput_status_draw = msymbol ("input-status-draw");
+ Minput_candidates_start = msymbol ("input-candidates-start");
+ Minput_candidates_done = msymbol ("input-candidates-done");
+ Minput_candidates_draw = msymbol ("input-candidates-draw");
+ Minput_set_spot = msymbol ("input-set-spot");
+ Minput_focus_move = msymbol ("input-focus-move");
+ Minput_focus_in = msymbol ("input-focus-in");
+ Minput_focus_out = msymbol ("input-focus-out");
+ Minput_toggle = msymbol ("input-toggle");
+ Minput_reset = msymbol ("input-reset");
+ Minput_get_surrounding_text = msymbol ("input-get-surrounding-text");
+ Minput_delete_surrounding_text = msymbol ("input-delete-surrounding-text");
+ Mcustomized = msymbol ("customized");
+ Mconfigured = msymbol ("configured");
+ Minherited = msymbol ("inherited");
+
+ minput_default_driver.open_im = open_im;
+ minput_default_driver.close_im = close_im;
+ minput_default_driver.create_ic = create_ic;
+ minput_default_driver.destroy_ic = destroy_ic;
+ minput_default_driver.filter = filter;
+ minput_default_driver.lookup = lookup;
+ minput_default_driver.callback_list = mplist ();
+ mplist_put_func (minput_default_driver.callback_list, Minput_reset,
+ M17N_FUNC (reset_ic));
+ minput_driver = &minput_default_driver;
+
+ fully_initialized = 0;
+ return 0;
+}
+
+void
+minput__fini ()
+{
+ if (fully_initialized)
+ {
+ free_im_list (im_info_list);
+ if (im_custom_list)
+ free_im_list (im_custom_list);
+ if (im_config_list)
+ free_im_list (im_config_list);
+ M17N_OBJECT_UNREF (load_im_info_keys);
+ }
+
+ M17N_OBJECT_UNREF (minput_default_driver.callback_list);
+ M17N_OBJECT_UNREF (minput_driver->callback_list);
+
+}
+
+MSymbol
+minput__char_to_key (int c)
+{
+ if (c < 0 || c >= 0x100)
+ return Mnil;
+
+ return one_char_symbol[c];
+}
+
+/*** @} */
+#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
+
+
+/* External API */
+
+/*** @addtogroup m17nInputMethod */
+/*** @{ */
+/*=*/
+
+/***en
+ @name Variables: Predefined symbols for callback commands.
+
+ These are the predefined symbols that are used as the @c COMMAND
+ argument of callback functions of an input method driver (see
+ #MInputDriver::callback_list).
+
+ Most of them do not require extra argument nor return any value;
+ exceptions are these:
+
+ Minput_get_surrounding_text: When a callback function assigned for
+ this command is called, the first element of #MInputContext::plist
+ has key #Minteger and the value specifies which portion of the
+ surrounding text should be retrieved. If the value is positive,
+ it specifies the number of characters following the current cursor
+ position. If the value is negative, the absolute value specifies
+ the number of characters preceding the current cursor position.
+ If the value is zero, it means that the caller just wants to know
+ if the surrounding text is currently supported or not.
+
+ If the surrounding text is currently supported, the callback
+ function must set the key of this element to #Mtext and the value
+ to the retrieved M-text. The length of the M-text may be shorter
+ than the requested number of characters, if the available text is
+ not that long. The length can be zero in the worst case. Or, the
+ length may be longer if an application thinks it is more efficient
+ to return that length.
+
+ If the surrounding text is not currently supported, the callback
+ function should return without changing the first element of
+ #MInputContext::plist.
+
+ Minput_delete_surrounding_text: When a callback function assigned
+ for this command is called, the first element of
+ #MInputContext::plist has key #Minteger and the value specifies
+ which portion of the surrounding text should be deleted in the
+ same way as the case of Minput_get_surrounding_text. The callback
+ function must delete the specified text. It should not alter
+ #MInputContext::plist. */
+/***ja
+ @name ÊÑ¿ô¡§ ¥³¡¼¥ë¥Ð¥Ã¥¯¥³¥Þ¥ó¥ÉÍÑÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë.
+
+ ÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Î¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Ë¤ª¤¤¤Æ @c COMMAND
+ °ú¿ô¤È¤·¤ÆÍѤ¤¤é¤ì¤ëÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë (#MInputDriver::callback_list »²¾È)¡£
+
+ ¤Û¤È¤ó¤É¤ÏÄɲäΰú¿ô¤òɬÍפȤ·¤Ê¤¤¤·ÃͤòÊÖ¤µ¤Ê¤¤¤¬¡¢°Ê²¼¤ÏÎã³°¤Ç¤¢¤ë¡£
+
+ Minput_get_surrounding_text: ¤³¤Î¥³¥Þ¥ó¥É¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿¥³¡¼¥ë¥Ð¥Ã
+ ¥¯´Ø¿ô¤¬¸Æ¤Ð¤ì¤¿ºÝ¤Ë¤Ï¡¢ #MInputContext::plist ¤ÎÂè°ìÍ×ÁǤϥ¡¼¤È¤·
+ ¤Æ#Minteger ¤ò¤È¤ê¡¢¤½¤ÎÃͤϥµ¥é¥¦¥ó¥Ç¥£¥ó¥°¥Æ¥¥¹¥È¤Î¤¦¤Á¤É¤ÎÉôʬ
+ ¤ò¼è¤Ã¤ÆÍè¤ë¤«¤ò»ØÄꤹ¤ë¡£Ãͤ¬Àµ¤Ç¤¢¤ì¤Ð¡¢¸½ºß¤Î¥«¡¼¥½¥ë°ÌÃ֤˳¤¯
+ ÃͤθĿôʬ¤Îʸ»ú¤ò¼è¤ë¡£Éé¤Ç¤¢¤ì¤Ð¡¢¥«¡¼¥½¥ë°ÌÃÖ¤ËÀè¹Ô¤¹¤ëÃͤÎÀäÂÐ
+ ÃÍʬ¤Îʸ»ú¤ò¼è¤ë¡£¸½ºß¥µ¥é¥¦¥ó¥É¥Æ¥¥¹¥È¤¬¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤ë¤«¤É¤¦
+ ¤«¤òÃΤꤿ¤¤¤À¤±¤Ç¤¢¤ì¤Ð¡¢¤³¤ÎÃͤϥ¼¥í¤Ç¤âÎɤ¤¡£
+
+ ¥µ¥é¥¦¥ó¥Ç¥£¥ó¥°¥Æ¥¥¹¥È¤¬¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤ì¤Ð¡¢¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Ï
+ ¤³¤ÎÍ×ÁǤΥ¡¼¤ò #Mtext ¤Ë¡¢Ãͤò¼è¤ê¹þ¤ó¤ÀM-text ¤ËÀßÄꤷ¤Ê¤¯¤Æ¤Ï¤Ê
+ ¤é¤Ê¤¤¡£¤â¤·¥Æ¥¥¹¥È¤ÎŤµ¤¬½¼Ê¬¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î M-text ¤ÎŤµ¤ÏÍ×
+ µá¤µ¤ì¤Æ¤¤¤ëʸ»ú¿ô¤è¤êû¤¯¤ÆÎɤ¤¡£ºÇ°¤Î¾ì¹ç 0 ¤Ç¤â¤è¤¤¤·¡¢¥¢¥×¥ê¥±¡¼
+ ¥·¥ç¥ó¦¤ÇɬÍפǸúΨŪ¤À¤È»×¤¨¤ÐŤ¯¤Æ¤âÎɤ¤¡£
+
+ ¥µ¥é¥¦¥ó¥Ç¥£¥ó¥°¥Æ¥¥¹¥È¤¬¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¡¢¥³¡¼¥ë¥Ð¥Ã¥¯´Ø
+ ¿ô¤Ï #MInputContext::plist ¤ÎÂè°ìÍ×ÁǤòÊѹ¹¤·¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
+
+ Minput_delete_surrounding_text: ¤³¤Î¥³¥Þ¥ó¥É¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿¥³¡¼¥ë
+ ¥Ð¥Ã¥¯´Ø¿ô¤¬¸Æ¤Ð¤ì¤¿ºÝ¤Ë¤Ï¡¢#MInputContext::plist ¤ÎÂè°ìÍ×ÁǤϡ¢¥¡¼
+ ¤È¤·¤Æ#Minteger ¤ò¤È¤ê¡¢ÃͤϺï½ü¤¹¤ë¤Ù¤¥µ¥é¥¦¥ó¥Ç¥£¥ó¥°¥Æ¥¥¹¥È¤ò
+ Minput_get_surrounding_text ¤ÈƱÍͤΤä¤êÊý¤Ç»ØÄꤹ¤ë¡£¥³¡¼¥ë¥Ð¥Ã¥¯
+ ´Ø¿ô¤Ï»ØÄꤵ¤ì¤¿¥Æ¥¥¹¥È¤òºï½ü¤·¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£¤Þ¤¿
+ #MInputContext::plist ¤òÊѤ¨¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ */
+/*** @{ */
+/*=*/
+
+MSymbol Minput_preedit_start;
+MSymbol Minput_preedit_done;
+MSymbol Minput_preedit_draw;
+MSymbol Minput_status_start;
+MSymbol Minput_status_done;
+MSymbol Minput_status_draw;
+MSymbol Minput_candidates_start;
+MSymbol Minput_candidates_done;
+MSymbol Minput_candidates_draw;
+MSymbol Minput_set_spot;
+MSymbol Minput_toggle;
+MSymbol Minput_reset;
+MSymbol Minput_get_surrounding_text;
+MSymbol Minput_delete_surrounding_text;
+/*** @} */
+
+/*=*/
+
+/***en
+ @name Variables: Predefined symbols for special input events.
+
+ These are the predefined symbols that are used as the @c KEY
+ argument of minput_filter (). */
+/***ja
+ @name ÊÑ¿ô: ÆÃÊ̤ÊÆþÎÏ¥¤¥Ù¥ó¥ÈÍÑÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë.
+
+ minput_filter () ¤Î @c KEY °ú¿ô¤È¤·¤ÆÍѤ¤¤é¤ì¤ëÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë¡£ */
+
+/*** @{ */
+/*=*/
+
+MSymbol Minput_focus_out;
+MSymbol Minput_focus_in;
+MSymbol Minput_focus_move;
+
+/*** @} */
+
+/*=*/
+/***en
+ @name Variables: Predefined symbols used in input method information.
+
+ These are the predefined symbols describing status of input method
+ command and variable, and are used in a return value of
+ minput_get_command () and minput_get_variable (). */
+/***ja
+ @name ÊÑ¿ô: ÆþÎϥ᥽¥Ã¥É¾ðÊóÍÑÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë.
+
+ ÆþÎϥ᥽¥Ã¥É¤Î¥³¥Þ¥ó¥É¤äÊÑ¿ô¤Î¾õÂÖ¤òɽ¤·¡¢minput_get_command () ¤È
+ minput_get_variable () ¤ÎÌá¤êÃͤȤ·¤ÆÍѤ¤¤é¤ì¤ëÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë¡£ */
+/*** @{ */
+/*=*/
+MSymbol Minherited;
+MSymbol Mcustomized;
+MSymbol Mconfigured;
+/*** @} */
+
+/*=*/
+
+/***en
+ @brief The default driver for internal input methods.
+
+ The variable #minput_default_driver is the default driver for
+ internal input methods.
+
+ The member MInputDriver::open_im () searches the m17n database for
+ an input method that matches the tag \< #Minput_method, $LANGUAGE,
+ $NAME\> and loads it.
+
+ The member MInputDriver::callback_list () is @c NULL. Thus, it is
+ programmers responsibility to set it to a plist of proper callback
+ functions. Otherwise, no feedback information (e.g. preedit text)
+ can be shown to users.
+
+ The macro M17N_INIT () sets the variable #minput_driver to the
+ pointer to this driver so that all internal input methods use it.
+
+ Therefore, unless @c minput_driver is set differently, the driver
+ dependent arguments $ARG of the functions whose name begins with
+ "minput_" are all ignored. */
+/***ja
+ @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥǥե©¥ë¥È¥É¥é¥¤¥Ð.
+
+ ÊÑ¿ô #minput_default_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѤΥǥե©¥ë¥È¤Î¥É¥é¥¤¥Ð¤òɽ¤¹¡£
+
+ ¥á¥ó¥Ð MInputDriver::open_im () ¤Ï m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹Ã椫¤é¥¿¥°
+ \< #Minput_method, $LANGUAGE, $NAME\>
+ ¤Ë¹çÃפ¹¤ëÆþÎϥ᥽¥Ã¥É¤òõ¤·¡¢¤½¤ì¤ò¥í¡¼¥É¤¹¤ë¡£
+
+ ¥á¥ó¥Ð MInputDriver::callback_list () ¤Ï @c NULL ¤Ç¤¢¤ê¡¢
+ ¤·¤¿¤¬¤Ã¤Æ¡¢¥×¥í¥°¥é¥Þ¦¤ÇÀÕǤ¤ò»ý¤Ã¤Æ ŬÀڤʥ³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Î plist
+ ¤ËÀßÄꤷ¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¤µ¤â¤Ê¤¤¤È¡¢preedit
+ ¥Æ¥¥¹¥È¤Ê¤É¤Î¥Õ¥£¡¼¥É¥Ð¥Ã¥¯¾ðÊ󤬥桼¥¶¤Ëɽ¼¨¤µ¤ì¤Ê¤¤¡£
+
+ ¥Þ¥¯¥í M17N_INIT () ¤ÏÊÑ¿ô #minput_driver
+ ¤ò¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤ËÀßÄꤷ¡¢Á´¤Æ¤ÎÆâÉôÆþÎϥ᥽¥Ã¥É¤¬¤³¤Î¥É¥é¥¤¥Ð¤ò»È¤¦¤è¤¦¤Ë¤¹¤ë¡£
+
+ ¤·¤¿¤¬¤Ã¤Æ¡¢@c minput_driver ¤¬¥Ç¥Õ¥©¥ë¥ÈÃͤΤޤޤǤ¢¤ì¤Ð¡¢minput_
+ ¤Ç»Ï¤Þ¤ë´Ø¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô $ARG ¤Ï¤¹¤Ù¤Æ̵»ë¤µ¤ì¤ë¡£ */
+
+MInputDriver minput_default_driver;
+/*=*/
+
+/***en
+ @brief The driver for internal input methods.
+
+ The variable #minput_driver is a pointer to the input method
+ driver that is used by internal input methods. The macro
+ M17N_INIT () initializes it to a pointer to #minput_default_driver
+ if .h> is included. */
+/***ja
+ @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥɥ饤¥Ð.
+
+ ÊÑ¿ô #minput_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤Æ»ÈÍѤµ¤ì¤Æ¤¤¤ëÆþÎÏ¥á
+ ¥½¥Ã¥É¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£¥Þ¥¯¥í M17N_INIT () ¤Ï¤³¤Î¥Ý¥¤¥ó
+ ¥¿¤ò#minput_default_driver (.h> ¤¬ include ¤µ¤ì¤Æ¤¤¤ë
+ »þ) ¤Ë½é´ü²½¤¹¤ë¡£ */
+
+MInputDriver *minput_driver;
+
+MSymbol Minput_driver;
+
+/*=*/
+
+/***en
+ @name Functions
+*/
+/***ja
+ @name ´Ø¿ô
+*/
+/*** @{ */
+
+/*=*/
+
+/***en
+ @brief Open an input method.
+
+ The minput_open_im () function opens an input method whose
+ language and name match $LANGUAGE and $NAME, and returns a pointer
+ to the input method object newly allocated.
+
+ This function at first decides a driver for the input method as
+ described below.
+
+ If $LANGUAGE is not #Mnil, the driver pointed by the variable
+ #minput_driver is used.
+
+ If $LANGUAGE is #Mnil and $NAME has the property #Minput_driver, the
+ driver pointed to by the property value is used to open the input
+ method. If $NAME has no such a property, @c NULL is returned.
+
+ Then, the member MInputDriver::open_im () of the driver is
+ called.
+
+ $ARG is set in the member @c arg of the structure MInputMethod so
+ that the driver can refer to it. */
+/***ja
+ @brief ÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë.
+
+ ´Ø¿ô minput_open_im () ¤Ï¸À¸ì $LANGUAGE ¤È̾Á° $NAME
+ ¤Ë¹çÃפ¹¤ëÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤·¡¢¿·¤¿¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿ÆþÎϥ᥽¥Ã¥É¥ª¥Ö¥¸¥§¥¯¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
+
+ ¤³¤Î´Ø¿ô¤Ï¡¢¤Þ¤ºÆþÎϥ᥽¥Ã¥ÉÍѤΥɥ饤¥Ð¤ò°Ê²¼¤Î¤è¤¦¤Ë¤·¤Æ·èÄꤹ¤ë¡£
+
+ $LANGUAGE ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢ÊÑ¿ô #minput_driver
+ ¤Ç»Ø¤µ¤ì¤Æ¤¤¤ë¥É¥é¥¤¥Ð¤òÍѤ¤¤ë¡£
+
+ $LANGUAGE ¤¬ #Mnil ¤Ç¤¢¤ê¡¢$NAME ¤¬ #Minput_driver
+ ¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä¾ì¹ç¤Ë¤Ï¡¢¤½¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤǻؤµ¤ì¤Æ¤¤¤ëÆþÎϥɥ饤¥Ð¤òÍѤ¤¤ÆÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë¡£
+ $NAME ¤Ë¤½¤Î¤è¤¦¤Ê¥×¥í¥Ñ¥Æ¥£¤¬Ìµ¤«¤Ã¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
+
+ ¼¡¤¤¤Ç¡¢¥É¥é¥¤¥Ð¤Î¥á¥ó¥Ð MInputDriver::open_im () ¤¬¸Æ¤Ð¤ì¤ë¡£
+
+ $ARG ¤Ï¹½Â¤ÂÎ MInputMethod ¤Î¥á¥ó¥Ð @c arg ¤ËÀßÄꤵ¤ì¡¢¥É¥é¥¤¥Ð¤«¤é»²¾È¤Ç¤¤ë¡£
+
+ @latexonly \IPAlabel{minput_open} @endlatexonly
+
+*/
+
+MInputMethod *
+minput_open_im (MSymbol language, MSymbol name, void *arg)
+{
+ MInputMethod *im;
+ MInputDriver *driver;
+
+ MINPUT__INIT ();
+
+ MDEBUG_PRINT2 (" [IM] opening (%s %s) ... ",
+ msymbol_name (language), msymbol_name (name));
+ if (language)
+ driver = minput_driver;
+ else
+ {
+ driver = (MInputDriver *) msymbol_get (name, Minput_driver);
+ if (! driver)
+ MERROR (MERROR_IM, NULL);
+ }
+
+ MSTRUCT_CALLOC (im, MERROR_IM);
+ im->language = language;
+ im->name = name;
+ im->arg = arg;
+ im->driver = *driver;
+ if ((*im->driver.open_im) (im) < 0)
+ {
+ MDEBUG_PRINT (" failed\n");
+ free (im);
+ return NULL;
+ }
+ MDEBUG_PRINT (" ok\n");
+ return im;
+}
+
+/*=*/
+
+/***en
+ @brief Close an input method.
+
+ The minput_close_im () function closes the input method $IM, which
+ must have been created by minput_open_im (). */
+
+/***ja
+ @brief ÆþÎϥ᥽¥Ã¥É¤ò¥¯¥í¡¼¥º¤¹¤ë.
+
+ ´Ø¿ô minput_close_im () ¤Ï¡¢ÆþÎϥ᥽¥Ã¥É $IM ¤ò¥¯¥í¡¼¥º¤¹¤ë¡£
+ ¤³¤ÎÆþÎϥ᥽¥Ã¥É $IM ¤Ï minput_open_im () ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£ */
+
+void
+minput_close_im (MInputMethod *im)
+{
+ MDEBUG_PRINT2 (" [IM] closing (%s %s) ... ",
+ msymbol_name (im->name), msymbol_name (im->language));
+ (*im->driver.close_im) (im);
+ free (im);
+ MDEBUG_PRINT (" done\n");
+}
+
+/*=*/
+
+/***en
+ @brief Create an input context.
+
+ The minput_create_ic () function creates an input context object
+ associated with input method $IM, and calls callback functions
+ corresponding to #Minput_preedit_start, #Minput_status_start, and
+ #Minput_status_draw in this order.
+
+ @return
+ If an input context is successfully created, minput_create_ic ()
+ returns a pointer to it. Otherwise it returns @c NULL. */
+
+/***ja
+ @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÀ¸À®¤¹¤ë.
+
+ ´Ø¿ô minput_create_ic () ¤ÏÆþÎϥ᥽¥Ã¥É $IM
+ ¤ËÂбþ¤¹¤ëÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤·¡¢
+ #Minput_preedit_start, #Minput_status_start, #Minput_status_draw
+ ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¤³¤Î½ç¤Ë¸Æ¤Ö¡£
+
+ @return
+ ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤¬À¸À®¤µ¤ì¤¿¾ì¹ç¡¢minput_create_ic ()
+ ¤Ï¤½¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¼ºÇÔ¤·¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
+ */
- prop = NULL;
- if (ic->candidate_list)
+MInputContext *
+minput_create_ic (MInputMethod *im, void *arg)
+{
+ MInputContext *ic;
+
+ MDEBUG_PRINT2 (" [IM] creating context (%s %s) ... ",
+ msymbol_name (im->name), msymbol_name (im->language));
+ MSTRUCT_CALLOC (ic, MERROR_IM);
+ ic->im = im;
+ ic->arg = arg;
+ ic->preedit = mtext ();
+ ic->candidate_list = NULL;
+ ic->produced = mtext ();
+ ic->spot.x = ic->spot.y = 0;
+ ic->active = 1;
+ ic->plist = mplist ();
+ if ((*im->driver.create_ic) (ic) < 0)
{
- 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)))
+ MDEBUG_PRINT (" failed\n");
+ M17N_OBJECT_UNREF (ic->preedit);
+ M17N_OBJECT_UNREF (ic->produced);
+ M17N_OBJECT_UNREF (ic->plist);
+ free (ic);
+ return NULL;
+ };
+
+ if (im->driver.callback_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);
+ minput_callback (ic, Minput_preedit_start);
+ minput_callback (ic, Minput_status_start);
+ minput_callback (ic, Minput_status_draw);
}
- 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;
+ MDEBUG_PRINT (" ok\n");
+ return ic;
}
+/*=*/
-/* Handle the input key KEY in the current state and map specified in
- the input context IC. If KEY is handled correctly, return 0.
- Otherwise, return -1. */
+/***en
+ @brief Destroy an input context.
-static int
-handle_key (MInputContext *ic)
-{
- MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
- MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
- MIMMap *map = ic_info->map;
- MIMMap *submap = NULL;
- MSymbol key = ic_info->keys[ic_info->key_head];
- MSymbol alias = Mnil;
- int i;
+ The minput_destroy_ic () function destroys the input context $IC,
+ which must have been created by minput_create_ic (). It calls
+ callback functions corresponding to #Minput_preedit_done,
+ #Minput_status_done, and #Minput_candidates_done in this order. */
- MDEBUG_PRINT2 (" [IM] handle `%s' in state %s",
- msymbol_name (key), MSYMBOL_NAME (ic_info->state->name));
+/***ja
+ @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÇ˲õ¤¹¤ë.
- if (map->submaps)
+ ´Ø¿ô minput_destroy_ic () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤òÇ˲õ¤¹¤ë¡£
+ ¤³¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ï minput_create_ic ()
+ ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£¤³¤Î´Ø¿ô¤Ï
+ #Minput_preedit_done, #Minput_status_done, #Minput_candidates_done
+ ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¤³¤Î½ç¤Ë¸Æ¤Ö¡£
+ */
+
+void
+minput_destroy_ic (MInputContext *ic)
+{
+ MDEBUG_PRINT2 (" [IM] destroying context (%s %s) ... ",
+ msymbol_name (ic->im->name), msymbol_name (ic->im->language));
+ if (ic->im->driver.callback_list)
{
- submap = mplist_get (map->submaps, key);
- if (! submap && (alias = msymbol_get (key, M_key_alias)) != Mnil)
- submap = mplist_get (map->submaps, alias);
+ minput_callback (ic, Minput_preedit_done);
+ minput_callback (ic, Minput_status_done);
+ minput_callback (ic, Minput_candidates_done);
}
+ (*ic->im->driver.destroy_ic) (ic);
+ M17N_OBJECT_UNREF (ic->preedit);
+ M17N_OBJECT_UNREF (ic->produced);
+ M17N_OBJECT_UNREF (ic->plist);
+ MDEBUG_PRINT (" done\n");
+ free (ic);
+}
- if (submap)
- {
- if (alias == Mnil)
- MDEBUG_PRINT (" submap-found");
- else
- MDEBUG_PRINT1 (" submap-found (by alias `%s')", MSYMBOL_NAME (alias));
- mtext_cpy (ic->preedit, ic_info->preedit_saved);
- ic->preedit_changed = 1;
- ic->cursor_pos = ic_info->state_pos;
- ic_info->key_head++;
- ic_info->map = map = submap;
- if (map->map_actions)
- {
- MDEBUG_PRINT (" map-actions:");
- if (take_action_list (ic, map->map_actions) < 0)
- {
- MDEBUG_PRINT ("\n");
- return -1;
- }
- }
- else if (map->submaps)
- {
- for (i = ic_info->state_key_head; i < ic_info->key_head; i++)
- {
- MSymbol key = ic_info->keys[i];
- char *name = msymbol_name (key);
+/*=*/
- if (! name[0] || ! name[1])
- mtext_ins_char (ic->preedit, ic->cursor_pos++, name[0], 1);
- }
- }
+/***en
+ @brief Filter an input key.
- /* If this is the terminal map or we have shifted to another
- state, perform branch actions (if any). */
- if (! map->submaps || map != ic_info->map)
- {
- if (map->branch_actions)
- {
- MDEBUG_PRINT (" branch-actions:");
- if (take_action_list (ic, map->branch_actions) < 0)
- {
- MDEBUG_PRINT ("\n");
- return -1;
- }
- }
- /* If MAP is still not the root map, shift to the current
- state. */
- if (ic_info->map != ic_info->state->map)
- shift_state (ic, ic_info->state->name);
- }
- }
- else
- {
- /* MAP can not handle KEY. */
+ The minput_filter () function filters input key $KEY according to
+ input context $IC, and calls callback functions corresponding to
+ #Minput_preedit_draw, #Minput_status_draw, and
+ #Minput_candidates_draw if the preedit text, the status, and the
+ current candidate are changed respectively.
- /* If MAP is the root map of the initial state, it means that
- the current input method can not handle KEY. */
- if (map == ((MIMState *) MPLIST_VAL (im_info->states))->map)
- {
- MDEBUG_PRINT (" unhandled\n");
- return -1;
- }
+ To make the input method commit the current preedit text (if any)
+ and shift to the initial state, call this function with #Mnil as
+ $KEY.
- if (map != ic_info->state->map)
- {
- /* If MAP is not the root map... */
- /* If MAP has branch actions, perform them. */
- if (map->branch_actions)
- {
- MDEBUG_PRINT (" branch-actions:");
- if (take_action_list (ic, map->branch_actions) < 0)
- {
- MDEBUG_PRINT ("\n");
- return -1;
- }
- }
- /* If MAP is still not the root map, shift to the current
- state. */
- if (ic_info->map != ic_info->state->map)
- {
- shift_state (ic, ic_info->state->name);
- /* If MAP has branch_actions, perform them. */
- if (ic_info->map->branch_actions)
- {
- MDEBUG_PRINT (" brank-actions:");
- if (take_action_list (ic, ic_info->map->branch_actions) < 0)
- return -1;
- }
- }
- }
- else
- {
- /* MAP is the root map, perform branch actions (if any) or
- shift to the initial state. */
- if (map->branch_actions)
- {
- MDEBUG_PRINT (" branch-actions:");
- if (take_action_list (ic, map->branch_actions) < 0)
- {
- MDEBUG_PRINT ("\n");
- return -1;
- }
- }
- else
- shift_state (ic, Mnil);
- }
- }
- MDEBUG_PRINT ("\n");
- return 0;
-}
+ To inform the input method about the focus-out event, call this
+ function with #Minput_focus_out as $KEY.
-static void
-reset_ic (MInputContext *ic, MSymbol ignore)
-{
- MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
- MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
- MText *status;
+ To inform the input method about the focus-in event, call this
+ function with #Minput_focus_in as $KEY.
- MDEBUG_PRINT ("\n [IM] reset\n");
+ To inform the input method about the focus-move event (i.e. input
+ spot change within the same input context), call this function
+ with #Minput_focus_move as $KEY.
- ic_info->state = (MIMState *) MPLIST_VAL (im_info->states);
- ic_info->prev_state = NULL;
- ic_info->map = ic_info->state->map;
- ic_info->state_key_head = ic_info->key_head;
- MLIST_RESET (ic_info);
- ic_info->key_unhandled = 0;
+ @return
+ If $KEY is filtered out, this function returns 1. In that case,
+ the caller should discard the key. Otherwise, it returns 0, and
+ the caller should handle the key, for instance, by calling the
+ function minput_lookup () with the same key. */
- if (mtext_nchars (ic->produced) > 0)
- mtext_reset (ic->produced);
- if (mtext_nchars (ic->preedit) > 0)
- {
- MPlist *plist;
+/***ja
+ @brief ÆþÎÏ¥¡¼¤ò¥Õ¥£¥ë¥¿¤¹¤ë.
- mtext_reset (ic->preedit);
- MPLIST_DO (plist, ic_info->markers)
- MPLIST_VAL (plist) = 0;
- ic->preedit_changed = 1;
- }
- if (ic->candidate_show)
- {
- ic->candidate_show = 0;
- ic->candidates_changed = MINPUT_CANDIDATES_SHOW_CHANGED;
- if (ic->candidate_list)
- {
- M17N_OBJECT_UNREF (ic->candidate_list);
- ic->candidate_list = NULL;
- ic->candidates_changed |= MINPUT_CANDIDATES_LIST_CHANGED;
- }
- }
- mtext_reset (ic_info->preedit_saved);
- ic_info->state_pos = ic->cursor_pos = 0;
+ ´Ø¿ô minput_filter () ¤ÏÆþÎÏ¥¡¼ $KEY ¤òÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC
+ ¤Ë±þ¤¸¤Æ¥Õ¥£¥ë¥¿¤·¡¢preedit ¥Æ¥¥¹¥È¡¢¥¹¥Æ¡¼¥¿¥¹¡¢¸½»þÅÀ¤Ç¤Î¸õÊ䤬ÊѲ½¤·¤¿»þÅÀ¤Ç¡¢¤½¤ì¤¾¤ì
+ #Minput_preedit_draw, #Minput_status_draw,
+ #Minput_candidates_draw ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¸Æ¤Ö¡£
+
+ @return
+ $KEY ¤¬¥Õ¥£¥ë¥¿¤µ¤ì¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 1 ¤òÊÖ¤¹¡£
+ ¤³¤Î¾ì¹ç¸Æ¤Ó½Ð¤·Â¦¤Ï¤³¤Î¥¡¼¤ò¼Î¤Æ¤ë¤Ù¤¤Ç¤¢¤ë¡£
+ ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0 ¤òÊÖ¤·¡¢¸Æ¤Ó½Ð¤·Â¦¤Ï¡¢¤¿¤È¤¨¤ÐƱ¤¸¥¡¼¤Ç´Ø¿ô minput_lookup ()
+ ¤ò¸Æ¤Ö¤Ê¤É¤·¤Æ¡¢¤³¤Î¥¡¼¤ò½èÍý¤¹¤ë¡£
+
+ @latexonly \IPAlabel{minput_filter} @endlatexonly
+*/
+
+int
+minput_filter (MInputContext *ic, MSymbol key, void *arg)
+{
+ int ret;
+
+ if (! ic
+ || ! ic->active)
+ return 0;
+ if (ic->im->driver.callback_list
+ && mtext_nchars (ic->preedit) > 0)
+ minput_callback (ic, Minput_preedit_draw);
- status = ic_info->state->title ? ic_info->state->title : im_info->title;
- if (ic->status != status)
+ ret = (*ic->im->driver.filter) (ic, key, arg);
+
+ if (ic->im->driver.callback_list)
{
- ic->status = status;
- ic->status_changed = 1;
+ if (ic->preedit_changed)
+ minput_callback (ic, Minput_preedit_draw);
+ if (ic->status_changed)
+ minput_callback (ic, Minput_status_draw);
+ if (ic->candidates_changed)
+ minput_callback (ic, Minput_candidates_draw);
}
+
+ return ret;
}
-static int
-open_im (MInputMethod *im)
-{
- MInputMethodInfo *im_info = get_im_info (im->language, im->name, Mnil);
+/*=*/
- if (! im_info)
- MERROR (MERROR_IM, -1);
- im->info = im_info;
- im_info->im = im;
- return 0;
-}
+/***en
+ @brief Look up a text produced in the input context.
-static void
-close_im (MInputMethod *im)
-{
- im->info = NULL;
-}
+ The minput_lookup () function looks up a text in the input context
+ $IC. $KEY must be identical to the one that was used in the previous call of
+ minput_filter ().
-static int
-create_ic (MInputContext *ic)
-{
- MInputMethod *im = ic->im;
- MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
- MInputContextInfo *ic_info;
- MPlist *plist;
+ If a text was produced by the input method, it is concatenated
+ to M-text $MT.
- if (ic->info)
- ic_info = (MInputContextInfo *) ic->info;
- else
- {
- MSTRUCT_CALLOC (ic_info, MERROR_IM);
- ic->info = ic_info;
- }
- MLIST_INIT1 (ic_info, keys, 8);
- ic_info->markers = mplist ();
- ic_info->vars = mplist ();
- plist = get_nested_list (im->language, im->name, Mnil, M_variable);
- MPLIST_DO (plist, plist)
- {
- MSymbol var = MPLIST_SYMBOL (plist);
- MPlist *pl;
+ This function calls #MInputDriver::lookup .
- plist = MPLIST_NEXT (plist);
- pl = MPLIST_PLIST (plist);
- pl = MPLIST_NEXT (pl); /* Skip description. */
- mplist_push (ic_info->vars, MPLIST_KEY (pl), MPLIST_VAL (pl));
- mplist_push (ic_info->vars, Msymbol, var);
- }
+ @return
+ If $KEY was correctly handled by the input method, this function
+ returns 0. Otherwise, it returns -1, even though some text
+ might be produced in $MT. */
- ic_info->preedit_saved = mtext ();
- if (im_info->externals)
- {
- MPlist *func_args = mplist (), *plist;
+/***ja
+ @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥ÈÃæ¤Î¥Æ¥¥¹¥È¤òõ¤¹.
- mplist_add (func_args, Mt, ic);
- MPLIST_DO (plist, im_info->externals)
- {
- MIMExternalModule *external = MPLIST_VAL (plist);
- MIMExternalFunc func
- = (MIMExternalFunc) mplist_get (external->func_list, Minit);
+ ´Ø¿ô minput_lookup () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC Ãæ¤Î¥Æ¥¥¹¥È¤òõ¤¹¡£
+ $KEY ¤Ï´Ø¿ô minput_filter () ¤Ø¤ÎľÁ°¤Î¸Æ¤Ó½Ð¤·¤ËÍѤ¤¤é¤ì¤¿¤â¤Î¤ÈƱ¤¸¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
- if (func)
- (func) (func_args);
- }
- M17N_OBJECT_UNREF (func_args);
- }
- reset_ic (ic, Mnil);
- return 0;
-}
+ ¥Æ¥¥¹¥È¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆÀ¸À®¤µ¤ì¤Æ¤¤¤ì¤Ð¡¢¥Æ¥¥¹¥È¤Ï M-text
+ $MT ¤ËÏ¢·ë¤µ¤ì¤ë¡£
-static void
-destroy_ic (MInputContext *ic)
-{
- MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
- MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
+ ¤³¤Î´Ø¿ô¤Ï¡¢#MInputDriver::lookup ¤ò¸Æ¤Ö¡£
- if (im_info->externals)
- {
- MPlist *func_args = mplist (), *plist;
+ @return
+ $KEY ¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆŬÀڤ˽èÍý¤Ç¤¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 0 ¤òÊÖ¤¹¡£
+ ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£
+ ¤³¤Î¾ì¹ç¤Ç¤â $MT ¤Ë²¿¤é¤«¤Î¥Æ¥¥¹¥È¤¬À¸À®¤µ¤ì¤Æ¤¤¤ë¤³¤È¤¬¤¢¤ë¡£
- mplist_add (func_args, Mt, ic);
- MPLIST_DO (plist, im_info->externals)
- {
- MIMExternalModule *external = MPLIST_VAL (plist);
- MIMExternalFunc func
- = (MIMExternalFunc) mplist_get (external->func_list, Mfini);
+ @latexonly \IPAlabel{minput_lookup} @endlatexonly */
- if (func)
- (func) (func_args);
- }
- M17N_OBJECT_UNREF (func_args);
- }
- MLIST_FREE1 (ic_info, keys);
- M17N_OBJECT_UNREF (ic_info->preedit_saved);
- M17N_OBJECT_UNREF (ic_info->markers);
- M17N_OBJECT_UNREF (ic_info->vars);
- M17N_OBJECT_UNREF (ic_info->preceding_text);
- M17N_OBJECT_UNREF (ic_info->following_text);
- free (ic->info);
+int
+minput_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
+{
+ return (ic ? (*ic->im->driver.lookup) (ic, key, arg, mt) : -1);
}
+/*=*/
+/***en
+ @brief Set the spot of the input context.
-/** Handle the input key KEY in the current state and map of IC->info.
- If KEY is handled but no text is produced, return 0, otherwise
- return 1.
+ The minput_set_spot () function sets the spot of input context $IC
+ to coordinate ($X, $Y ) with the height specified by $ASCENT and $DESCENT .
+ The semantics of these values depends on the input method driver.
- Ignore ARG. */
+ For instance, a driver designed to work in a CUI environment may
+ use $X and $Y as the column- and row numbers, and may ignore $ASCENT and
+ $DESCENT . A driver designed to work in a window system may
+ interpret $X and $Y as the pixel offsets relative to the origin of the
+ client window, and may interpret $ASCENT and $DESCENT as the ascent- and
+ descent pixels of the line at ($X . $Y ).
-static int
-filter (MInputContext *ic, MSymbol key, void *arg)
-{
- MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
- MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
- int i = 0;
+ $FONTSIZE specifies the fontsize of preedit text in 1/10 point.
- if (! ic_info->state)
- {
- ic_info->key_unhandled = 1;
- return 0;
- }
- mtext_reset (ic->produced);
- ic->status_changed = ic->preedit_changed = ic->candidates_changed = 0;
- M17N_OBJECT_UNREF (ic_info->preceding_text);
- M17N_OBJECT_UNREF (ic_info->following_text);
- MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
- ic_info->key_unhandled = 0;
+ $MT and $POS are the M-text and the character position at the spot.
+ $MT may be @c NULL, in which case, the input method cannot get
+ information about the text around the spot. */
- /* If KEY has Meta or Alt modifier, put M_key_alias property. */
- if (key != Mnil)
- {
- if (! msymbol_get (key, M_key_alias)
- && (strchr (MSYMBOL_NAME (key), 'M')
- || strchr (MSYMBOL_NAME (key), 'A')))
- {
- char *name = MSYMBOL_NAME (key);
- char *meta_or_alt;
+/***ja
+ @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Î¥¹¥Ý¥Ã¥È¤òÀßÄꤹ¤ë.
- while (name[0] && name[1] == '-'
- && (name[0] != 'M' && name[0] != 'A'))
- name += 2;
- if ((name[0] == 'M' || name[0] == 'A') && name[1] == '-')
- {
- MSymbol alias;
-
- meta_or_alt = name;
- name = alloca (MSYMBOL_NAMELEN (key) + 1);
- memcpy (name, MSYMBOL_NAME (key), MSYMBOL_NAMELEN (key) + 1);
- name[meta_or_alt - MSYMBOL_NAME (key)]
- = *meta_or_alt == 'M' ? 'A' : 'M';
- alias = msymbol (name);
- msymbol_put (key, M_key_alias, alias);
- }
- }
- else if (MSYMBOL_NAME (key)[0] == 'S'
- && MSYMBOL_NAME (key)[1] == '-'
- && MSYMBOL_NAME (key)[2] >= 'A' && MSYMBOL_NAME (key)[2] <= 'Z')
- msymbol_put (key, M_key_alias, one_char_symbol[(int)MSYMBOL_NAME (key)[2]]);
- }
+ ´Ø¿ô minput_set_spot () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤Î¥¹¥Ý¥Ã¥È¤ò¡¢ºÂɸ ($X, $Y )
+ ¤Î°ÌÃÖ¤Ë ¡¢¹â¤µ $ASCENT¡¢ $DESCENT
+ ¤ÇÀßÄꤹ¤ë¡£ ¤³¤ì¤é¤ÎÃͤΰÕÌ£¤ÏÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë¡£
- do {
- if (handle_key (ic) < 0)
- {
- /* KEY was not handled. Delete it from the current key sequence. */
- if (ic_info->used > 0)
- {
- memmove (ic_info->keys, ic_info->keys + 1,
- sizeof (int) * (ic_info->used - 1));
- ic_info->used--;
- }
- /* This forces returning 1. */
- ic_info->key_unhandled = 1;
- break;
- }
- if (i++ == 100)
- {
- mdebug_hook ();
- reset_ic (ic, Mnil);
- ic_info->key_unhandled = 1;
- break;
- }
- /* Break the loop if all keys were handled. */
- } while (ic_info->key_head < ic_info->used);
+ ¤¿¤È¤¨¤Ð CUI ´Ä¶¤ÇÆ°ºî¤¹¤ë¥É¥é¥¤¥Ð¤Ï $X ¤È $Y
+ ¤ò¤½¤ì¤¾¤ìÎó¤È¹Ô¤ÎÈÖ¹æ¤È¤·¤ÆÍѤ¤¡¢$ASCENT ¤È $DESCENT
+ ¤ò̵»ë¤¹¤ë¤«¤â¤·¤ì¤Ê¤¤¡£ ¤Þ¤¿¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥àÍѤΥɥ饤¥Ð¤Ï
+ $X ¤È $Y ¤ò¥¯¥é¥¤¥¢¥ó¥È¥¦¥£¥ó¥É¥¦¤Î¸¶ÅÀ¤«¤é¤Î¥ª¥Õ¥»¥Ã¥È¤ò¥Ô¥¯¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¤¡¢
+ $ASCENT ¤È $DESCENT ¤ò ($X . $Y )
+ ¤ÎÎó¤Î¥¢¥»¥ó¥È¤È¥Ç¥£¥»¥ó¥È¤ò¥Ô¥¯¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¦¤«¤â¤·¤ì¤Ê¤¤¡£
- /* If the current map is the root of the initial state, we should
- produce any preedit text in ic->produced. */
- if (ic_info->map == ((MIMState *) MPLIST_VAL (im_info->states))->map
- && mtext_nchars (ic->preedit) > 0)
- shift_state (ic, ((MIMState *) MPLIST_VAL (im_info->states))->name);
+ $FONTSIZE ¤Ë¤Ï preedit ¥Æ¥¥¹¥È¤Î¥Õ¥©¥ó¥È¥µ¥¤¥º¤ò 1/10 ¥Ý¥¤¥ó¥Èñ°Ì¤Ç»ØÄꤹ¤ë¡£
- if (mtext_nchars (ic->produced) > 0)
- {
- MSymbol lang = msymbol_get (ic->im->language, Mlanguage);
+ $MT ¤È $POS ¤Ï¤½¤Î¥¹¥Ý¥Ã¥È¤Î M-text ¤Èʸ»ú°ÌÃ֤Ǥ¢¤ë¡£$MT ¤Ï @c
+ NULL ¤Ç¤â¤è¤¯¡¢¤½¤Î¾ì¹ç¤Ë¤ÏÆþÎϥ᥽¥Ã¥É¤Ï¥¹¥Ý¥Ã¥È¼þÊդΥƥ¥¹¥È¤Ë´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë¤³¤È¤¬¤Ç¤¤Ê¤¤¡£
+ */
- if (lang != Mnil)
- mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
- Mlanguage, ic->im->language);
- }
+void
+minput_set_spot (MInputContext *ic, int x, int y,
+ int ascent, int descent, int fontsize,
+ MText *mt, int pos)
+{
+ ic->spot.x = x;
+ ic->spot.y = y;
+ ic->spot.ascent = ascent;
+ ic->spot.descent = descent;
+ ic->spot.fontsize = fontsize;
+ ic->spot.mt = mt;
+ ic->spot.pos = pos;
+ if (ic->im->driver.callback_list)
+ minput_callback (ic, Minput_set_spot);
+}
+/*=*/
- return (! ic_info->key_unhandled && mtext_nchars (ic->produced) == 0);
+/***en
+ @brief Toggle input method.
+
+ The minput_toggle () function toggles the input method associated
+ with input context $IC. */
+/***ja
+ @brief ÆþÎϥ᥽¥Ã¥É¤òÀÚÂؤ¨¤ë.
+
+ ´Ø¿ô minput_toggle () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC
+ ¤ËÂбþÉÕ¤±¤é¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ò¥È¥°¥ë¤¹¤ë¡£
+ */
+
+void
+minput_toggle (MInputContext *ic)
+{
+ if (ic->im->driver.callback_list)
+ minput_callback (ic, Minput_toggle);
+ ic->active = ! ic->active;
}
+/*=*/
-/** Return 1 if the last event or key was not handled, otherwise
- return 0.
+/***en
+ @brief Reset an input context.
- There is no need of looking up because ic->produced should already
- contain the produced text (if any).
+ The minput_reset_ic () function resets input context $IC by
+ calling a callback function corresponding to #Minput_reset. It
+ resets the status of $IC to its initial one. As the
+ current preedit text is deleted without commitment, if necessary,
+ call minput_filter () with the arg @r key #Mnil to force the input
+ method to commit the preedit in advance. */
- Ignore KEY. */
+/***ja
+ @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤ò¥ê¥»¥Ã¥È¤¹¤ë.
-static int
-lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
-{
- mtext_cat (mt, ic->produced);
- mtext_reset (ic->produced);
- return (((MInputContextInfo *) ic->info)->key_unhandled ? -1 : 0);
+ ´Ø¿ô minput_reset_ic () ¤Ï #Minput_reset ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô
+ ¤ò¸Æ¤Ö¤³¤È¤Ë¤è¤Ã¤ÆÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤ò¥ê¥»¥Ã¥È¤¹¤ë¡£¥ê¥»¥Ã¥È¤È¤Ï¡¢
+ ¼ÂºÝ¤Ë¤ÏÆþÎϥ᥽¥Ã¥É¤ò½é´ü¾õÂ֤˰ܤ¹¤³¤È¤Ç¤¢¤ë¡£¸½ºßÆþÎÏÃæ¤Î¥Æ¥¥¹
+ ¥È¤Ï¥³¥ß¥Ã¥È¤µ¤ì¤ë¤³¤È¤Ê¤¯ºï½ü¤µ¤ì¤ë¤Î¤Ç¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é
+ ¥à¤Ï¡¢É¬Íפʤé¤Ðͽ¤á minput_filter () ¤ò°ú¿ô @r key #Mnil ¤Ç¸Æ¤ó¤Ç
+ ¶¯À©Åª¤Ë¥×¥ê¥¨¥Ç¥£¥Ã¥È¥Æ¥¥¹¥È¤ò¥³¥ß¥Ã¥È¤µ¤»¤ë¤³¤È¡£ */
+
+void
+minput_reset_ic (MInputContext *ic)
+{
+ if (ic->im->driver.callback_list)
+ minput_callback (ic, Minput_reset);
}
-static MPlist *load_im_info_keys;
+/*=*/
-static MPlist *
-load_partial_im_info (MSymbol language, MSymbol name,
- MSymbol extra, MSymbol key)
-{
- MDatabase *mdb;
- MPlist *plist;
+/***en
+ @brief Get title and icon filename of an input method.
- if (language == Mnil)
- MERROR (MERROR_IM, NULL);
- mdb = mdatabase_find (Minput_method, language, name, extra);
- if (! mdb)
- MERROR (MERROR_IM, NULL);
+ The minput_get_title_icon () function returns a plist containing a
+ title and icon filename (if any) of an input method specified by
+ $LANGUAGE and $NAME.
- mplist_push (load_im_info_keys, key, Mt);
- plist = mdatabase__load_for_keys (mdb, load_im_info_keys);
- mplist_pop (load_im_info_keys);
- return plist;
-}
+ The first element of the plist has key #Mtext and the value is an
+ M-text of the title for identifying the input method. The second
+ element (if any) has key #Mtext and the value is an M-text of the
+ icon image (absolute) filename for the same purpose.
+ @return
+ If there exists a specified input method and it defines an title,
+ a plist is returned. Otherwise, NULL is returned. The caller
+ must free the plist by m17n_object_unref (). */
+/***ja
+ @brief ÆþÎϥ᥽¥Ã¥É¤Î¥¿¥¤¥È¥ë¤È¥¢¥¤¥³¥óÍÑ¥Õ¥¡¥¤¥ë̾¤òÆÀ¤ë.
-static MInputMethodInfo *
-get_im_info (MSymbol language, MSymbol name, MSymbol extra)
+ ´Ø¿ô minput_get_title_icon () ¤Ï¡¢ $LANGUAGE ¤È $NAME ¤Ç»ØÄꤵ¤ì¤ë
+ ÆþÎϥ᥽¥Ã¥É¤Î¥¿¥¤¥È¥ë¤È¡Ê¤¢¤ì¤Ð¡Ë¥¢¥¤¥³¥óÍÑ¥Õ¥¡¥¤¥ë¤ò´Þ¤à plist ¤ò
+ ÊÖ¤¹¡£
+
+ plist ¤ÎÂè°ìÍ×ÁǤϡ¢#Mtext ¤ò¥¡¼¤Ë»ý¤Á¡¢ÃͤÏÆþÎϥ᥽¥Ã¥É¤ò¼±Ê̤¹¤ë
+ ¥¿¥¤¥È¥ë¤òɽ¤¹ M-text ¤Ç¤¢¤ë¡£ÂèÆóÍ×ÁǤ¬¤¢¤ì¤Ð¡¢¥¡¼¤Ï #Mtext ¤Ç¤¢
+ ¤ê¡¢Ãͤϼ±ÊÌÍÑ¥¢¥¤¥³¥ó²èÁü¥Õ¥¡¥¤¥ë¤ÎÀäÂХѥ¹¤òɽ¤¹ M-text ¤Ç¤¢¤ë¡£
+
+ @return
+ »ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤¬Â¸ºß¤·¡¢¥¿¥¤¥È¥ë¤¬ÄêµÁ¤µ¤ì¤Æ¤¤¤ì¤Ð
+ plist ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð NULL ¤òÊÖ¤¹¡£¸Æ½Ð¦¤Ï
+ ´Ø¿ô m17n_object_unref () ¤òÍѤ¤¤Æ plist ¤ò²òÊü¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ */
+
+MPlist *
+minput_get_title_icon (MSymbol language, MSymbol name)
{
- MDatabase *mdb;
+ MInputMethodInfo *im_info;
MPlist *plist;
- MInputMethodInfo *im_info = NULL;
+ char *file = NULL;
+ MText *mt;
- if (language == Mnil)
- MERROR (MERROR_IM, NULL);
- mdb = mdatabase_find (Minput_method, language, name, extra);
- if (! mdb)
- MERROR (MERROR_IM, NULL);
+ MINPUT__INIT ();
- if (! im_info_list)
- im_info_list = mplist ();
- else if ((plist = mplist_find_by_value (im_info_list, mdb)))
+ im_info = get_im_info (language, name, Mnil, Mtitle);
+ if (! im_info || !im_info->title)
+ return NULL;
+ mt = mtext_get_prop (im_info->title, 0, Mtext);
+ if (mt)
+ file = mdatabase__find_file ((char *) MTEXT_DATA (mt));
+ else
{
- if (mdatabase__check (mdb))
+ char *buf = alloca (MSYMBOL_NAMELEN (language) + MSYMBOL_NAMELEN (name)
+ + 12);
+
+ sprintf (buf, "icons/%s-%s.png", (char *) MSYMBOL_NAME (language),
+ (char *) MSYMBOL_NAME (name));
+ file = mdatabase__find_file (buf);
+ if (! file && language == Mt)
{
- plist = MPLIST_NEXT (plist);
- im_info = MPLIST_VAL (plist);
- return im_info;
+ sprintf (buf, "icons/%s.png", (char *) MSYMBOL_NAME (name));
+ file = mdatabase__find_file (buf);
}
- mplist_pop (plist);
- free_im_info (MPLIST_VAL (plist));
- mplist_pop (plist);
}
- plist = mdatabase_load (mdb);
- if (! plist)
- MERROR (MERROR_IM, NULL);
- im_info = load_im_info (language, name, plist);
- M17N_OBJECT_UNREF (plist);
- if (! im_info)
- MERROR (MERROR_IM, NULL);
- mplist_push (im_info_list, Mt, im_info);
- mplist_push (im_info_list, Mt, mdb);
- return im_info;
+ plist = mplist ();
+ mplist_add (plist, Mtext, im_info->title);
+ if (file)
+ {
+ mt = mtext__from_data (file, strlen (file), MTEXT_FORMAT_UTF_8, 1);
+ free (file);
+ mplist_add (plist, Mtext, mt);
+ M17N_OBJECT_UNREF (mt);
+ }
+ return plist;
}
-
-/* Input method command handler. */
+/*=*/
-/* List of all (global and local) commands.
- (LANG:(IM-NAME:(COMMAND ...) ...) ...) ...
- COMMAND is CMD-NAME:(mtext:DESCRIPTION plist:KEYSEQ ...))
- Global commands are storead as (t (t COMMAND ...)) */
+/***en
+ @brief Get description text of an input method.
-/* Check if PLIST is a valid command key sequence.
- PLIST must be NULL or:
- [ symbol:KEY | integer:KEY ] ... */
+ The minput_get_description () function returns an M-text that
+ describes the input method specified by $LANGUAGE and $NAME.
-static int
-check_command_keyseq (MPlist *plist)
-{
- if (! plist)
- return 0;
- MPLIST_DO (plist, plist)
- {
- if (MPLIST_SYMBOL_P (plist))
- continue;
- else if (MPLIST_INTEGER_P (plist))
- {
- int n = MPLIST_INTEGER (plist);
+ @return
+ If the specified input method has a description text, a pointer to
+ #MText is returned. The caller has to free it by m17n_object_unref ().
+ If the input method does not have a description text, @c NULL is
+ returned. */
+/***ja
+ @brief ÆþÎϥ᥽¥Ã¥É¤ÎÀâÌÀ¥Æ¥¥¹¥È¤òÆÀ¤ë.
- if (n < 0 || n > 9)
- return -1;
- MPLIST_KEY (plist) = Msymbol;
- MPLIST_VAL (plist) = one_char_symbol['0' + 9];
- }
- else
- return -1;
- }
- return 0;
-}
+ ´Ø¿ô minput_get_description () ¤Ï¡¢$LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ»ØÄê
+ ¤µ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤òÀâÌÀ¤¹¤ë M-text ¤òÊÖ¤¹¡£
-/* Check if PLIST has this form:
- ([ plist:([ symbol:KEY | integer:KEY ]) | mtext:KEYSEQ ]
- ...)
- If the form of PLIST matches, return 0, otherwise return -1. */
+ @return »ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤¬ÀâÌÀ¤¹¤ë¥Æ¥¥¹¥È¤ò»ý¤Ã¤Æ¤¤¤ì¤Ð¡¢
+ #MText ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¸Æ¤Ó½Ð¤·Â¦¤Ï¡¢¤½¤ì¤ò m17n_object_unref
+ () ¤òÍѤ¤¤Æ²òÊü¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ÆþÎϥ᥽¥Ã¥É¤ËÀâÌÀ¥Æ¥¥¹¥È¤¬Ìµ¤±
+ ¤ì¤Ð@c NULL ¤òÊÖ¤¹¡£ */
-static int
-check_command_list (MPlist *plist)
+MText *
+minput_get_description (MSymbol language, MSymbol name)
{
- MPLIST_DO (plist, plist)
- {
- if (MPLIST_PLIST_P (plist))
- {
- MPlist *pl = MPLIST_PLIST (plist);
+ MInputMethodInfo *im_info;
+ MSymbol extra;
- MPLIST_DO (pl, pl)
- if (! MPLIST_SYMBOL_P (pl) && ! MPLIST_INTEGER_P (pl))
- return -1;
- }
- else if (! MPLIST_MTEXT_P (plist))
- return -1;
- }
- return 0;
-}
+ MINPUT__INIT ();
+ if (name != Mnil)
+ extra = Mnil;
+ else
+ extra = language, language = Mt;
-
-/* Input method variable handler. */
+ im_info = get_im_info (language, name, extra, Mdescription);
+ if (! im_info || ! im_info->description)
+ return NULL;
+ M17N_OBJECT_REF (im_info->description);
+ return im_info->description;
+}
-/* Check if PLIST has this form:
- (TYPE:VAL ;; TYPE ::= integer | mtext | symbol
- VALID-VALUE
- ...)
- If the form of PLIST matches, return 0, otherwise return -1. */
+/*=*/
-static int
-check_variable_list (MPlist *plist)
-{
- MSymbol type = MPLIST_KEY (plist);
- MPlist *p;
+/***en
+ @brief Get information about input method command(s).
- if (type != Minteger && type != Mtext && type != Msymbol)
- return -1;
- MPLIST_DO (plist, MPLIST_NEXT (plist))
- {
- if (type == Minteger && MPLIST_PLIST_P (plist))
- {
- MPLIST_DO (p, MPLIST_PLIST (plist))
- if (! MPLIST_INTEGER_P (p))
- return -1;
- }
- else if (type != MPLIST_KEY (plist))
- return -1;
- }
- return 0;
-}
+ The minput_get_command () function returns information about
+ the command $COMMAND of the input method specified by $LANGUAGE and
+ $NAME. An input method command is a pseudo key event to which one
+ or more actual input key sequences are assigned.
-/* Support functions for mdebug_dump_im. */
+ There are two kinds of commands, global and local. A global
+ command has a global definition, and the description and the key
+ assignment may be inherited by a local command. Each input method
+ defines a local command which has a local key assignment. It may
+ also declare a local command that inherits the definition of a
+ global command of the same name.
-static void
-dump_im_map (MPlist *map_list, int indent)
-{
- char *prefix;
- MSymbol key = MPLIST_KEY (map_list);
- MIMMap *map = (MIMMap *) MPLIST_VAL (map_list);
+ If $LANGUAGE is #Mt and $NAME is #Mnil, this function returns
+ information about a global command. Otherwise information about a
+ local command is returned.
- prefix = (char *) alloca (indent + 1);
- memset (prefix, 32, indent);
- prefix[indent] = '\0';
+ If $COMMAND is #Mnil, information about all commands is returned.
- fprintf (stderr, "(\"%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);
- dump_im_map (map_list, indent + 2);
- }
- }
- if (map->branch_actions)
- {
- fprintf (stderr, "\n%s (branch\n%s ", prefix, prefix);
- mdebug_dump_plist (map->branch_actions, indent + 4);
- fprintf (stderr, ")");
- }
- fprintf (stderr, ")");
-}
+ The return value is a @e well-formed plist (#m17nPlist) of this
+ format:
+@verbatim
+ ((NAME DESCRIPTION STATUS [KEYSEQ ...]) ...)
+@endverbatim
+ @c NAME is a symbol representing the command name.
+ @c DESCRIPTION is an M-text describing the command, or #Mnil if the
+ command has no description.
-static void
-dump_im_state (MIMState *state, int indent)
-{
- char *prefix;
- MPlist *map_list;
+ @c STATUS is a symbol representing how the key assignment is decided.
+ The value is #Mnil (the default key assignment), #Mcustomized (the
+ key assignment is customized by per-user customization file), or
+ #Mconfigured (the key assignment is set by the call of
+ minput_config_command ()). For a local command only, it may also
+ be #Minherited (the key assignment is inherited from the
+ corresponding global command).
- prefix = (char *) alloca (indent + 1);
- memset (prefix, 32, indent);
- prefix[indent] = '\0';
+ @c KEYSEQ is a plist of one or more symbols representing a key
+ sequence assigned to the command. If there's no KEYSEQ, the
+ command is currently disabled (i.e. no key sequence can trigger
+ actions of the command).
- fprintf (stderr, "(%s", msymbol_name (state->name));
- if (state->map->submaps)
- {
- MPLIST_DO (map_list, state->map->submaps)
- {
- fprintf (stderr, "\n%s ", prefix);
- dump_im_map (map_list, indent + 2);
- }
- }
- fprintf (stderr, ")");
-}
+ If $COMMAND is not #Mnil, the first element of the returned plist
+ contains the information about $COMMAND.
-
+ @return
-int
-minput__init ()
-{
- char *key_names[32]
- = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- "BackSpace", "Tab", "Linefeed", "Clear", NULL, "Return", NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, "Escape", NULL, NULL, NULL, NULL };
- char buf[6], buf2[256];
- int i;
+ If the requested information was found, a pointer to a non-empty
+ plist is returned. As the plist is kept in the library, the
+ caller must not modify nor free it.
- Minput_method = msymbol ("input-method");
- Minput_driver = msymbol ("input-driver");
- Mtitle = msymbol ("title");
- Mmacro = msymbol ("macro");
- Mmodule = msymbol ("module");
- Mmap = msymbol ("map");
- Mstate = msymbol ("state");
- Minclude = msymbol ("include");
- Minsert = msymbol ("insert");
- M_candidates = msymbol (" candidates");
- Mdelete = msymbol ("delete");
- Mmove = msymbol ("move");
- Mmark = msymbol ("mark");
- Mpushback = msymbol ("pushback");
- Mundo = msymbol ("undo");
- Mcall = msymbol ("call");
- Mshift = msymbol ("shift");
- Mselect = msymbol ("select");
- Mshow = msymbol ("show");
- Mhide = msymbol ("hide");
- Mcommit = msymbol ("commit");
- Munhandle = msymbol ("unhandle");
- Mset = msymbol ("set");
- Madd = msymbol ("add");
- Msub = msymbol ("sub");
- Mmul = msymbol ("mul");
- Mdiv = msymbol ("div");
- Mequal = msymbol ("=");
- Mless = msymbol ("<");
- Mgreater = msymbol (">");
- Mless_equal = msymbol ("<=");
- Mgreater_equal = msymbol (">=");
- Mcond = msymbol ("cond");
- Mplus = msymbol ("+");
- Mminus = msymbol ("-");
- Mstar = msymbol ("*");
- Mslush = msymbol ("/");
- Mand = msymbol ("&");
- Mor = msymbol ("|");
- Mnot = msymbol ("!");
+ Otherwise (the specified input method or the specified command
+ does not exist), @c NULL is returned. */
+/***ja
+ @brief ÆþÎϥ᥽¥Ã¥É¤Î¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë.
- Mcandidates_group_size = msymbol ("candidates-group-size");
- Mcandidates_charset = msymbol ("candidates-charset");
+ ´Ø¿ô minput_get_command () ¤Ï¡¢$LANGUAGE ¤È $NAME ¤Ç»ØÄꤵ¤ì¤ëÆþÎÏ
+ ¥á¥½¥Ã¥É¤Î¥³¥Þ¥ó¥É $COMMAND ¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£ÆþÎϥ᥽¥Ã¥É¤Î¥³¥Þ
+ ¥ó¥É¤È¤Ï¡¢µ¿»÷¥¡¼¥¤¥Ù¥ó¥È¤Ç¤¢¤ê¡¢£±¤Ä°Ê¾å¤Î¼ÂºÝ¤ÎÆþÎÏ¥¡¼¥·¡¼¥¯¥¨
+ ¥ó¥¹¤¬³ä¤êÅö¤Æ¤é¤ì¤ë¡£
- Minput_preedit_start = msymbol ("input-preedit-start");
- Minput_preedit_done = msymbol ("input-preedit-done");
- Minput_preedit_draw = msymbol ("input-preedit-draw");
- Minput_status_start = msymbol ("input-status-start");
- Minput_status_done = msymbol ("input-status-done");
- Minput_status_draw = msymbol ("input-status-draw");
- Minput_candidates_start = msymbol ("input-candidates-start");
- Minput_candidates_done = msymbol ("input-candidates-done");
- Minput_candidates_draw = msymbol ("input-candidates-draw");
- Minput_set_spot = msymbol ("input-set-spot");
- Minput_focus_move = msymbol ("input-focus-move");
- Minput_focus_in = msymbol ("input-focus-in");
- Minput_focus_out = msymbol ("input-focus-out");
- Minput_toggle = msymbol ("input-toggle");
- Minput_reset = msymbol ("input-reset");
- Minput_get_surrounding_text = msymbol ("input-get-surrounding-text");
- Minput_delete_surrounding_text = msymbol ("input-delete-surrounding-text");
+ ¥³¥Þ¥ó¥É¤Ë¤Ï¡¢¥°¥í¡¼¥Ð¥ë¤È¥í¡¼¥«¥ë¤Î£²¼ïÎब¤¢¤ë¡£¥°¥í¡¼¥Ð¥ë¤Ê¥³¥Þ¥ó¥É
+ ¤Ï¥°¥í¡¼¥Ð¥ë¤ËÄêµÁ¤µ¤ì¡¢¥í¡¼¥«¥ë¤Ê¥³¥Þ¥ó¥É¤Ï¤½¤ÎÀâÌÀ¤È¥¡¼³ä¤êÅö¤Æ
+ ¤ò·Ñ¾µ¤¹¤ë¤³¤È¤¬¤Ç¤¤ë¡£³ÆÆþÎϥ᥽¥Ã¥É¤Ï¥í¡¼¥«¥ë¤Ê¥¡¼³äÅö¤ò»ý¤Ä¥í¡¼
+ ¥«¥ë¤Ê¥³¥Þ¥ó¥É¤òÄêµÁ¤¹¤ë¡£¤Þ¤¿Æ±Ì¾¤Î¥°¥í¡¼¥Ð¥ë¤Ê¥³¥Þ¥ó¥É¤ÎÄêµÁ¤ò·Ñ
+ ¾µ¤¹¤ë¥í¡¼¥«¥ë¤Ê¥³¥Þ¥ó¥É¤òÀë¸À¤¹¤ë¤³¤È¤â¤Ç¤¤ë¡£
- Mcandidate_list = msymbol_as_managing_key (" candidate-list");
- Mcandidate_index = msymbol (" candidate-index");
+ $LANGUAGE ¤¬ #Mt ¤Ç $NAME ¤¬ #Mnil ¤Î¾ì¹ç¤Ï¡¢¤³¤Î´Ø¿ô¤Ï¥°¥í¡¼¥Ð¥ë¥³
+ ¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¥í¡¼¥«¥ë¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¤â
+ ¤Î¤òÊÖ¤¹¡£
- Minit = msymbol ("init");
- Mfini = msymbol ("fini");
+ $COMMAND ¤¬ #Mnil ¤Î¾ì¹ç¤Ï¡¢¤¹¤Ù¤Æ¤Î¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£
- M_key_alias = msymbol (" key-alias");
- M_description = msymbol ("description");
- M_command = msymbol ("command");
- M_variable = msymbol ("variable");
+ Ìá¤êÃͤϰʲ¼¤Î·Á¼°¤Î @e well-formed plist (#m17nPlist) ¤Ç¤¢¤ë¡£
- load_im_info_keys = mplist ();
- mplist_add (load_im_info_keys, Mstate, Mnil);
- mplist_push (load_im_info_keys, Mmap, Mnil);
+@verbatim
+ ((NAME DESCRIPTION STATUS [KEYSEQ ...]) ...)
+@endverbatim
+ @c NAME ¤Ï¥³¥Þ¥ó¥É̾¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
- buf[0] = 'C';
- buf[1] = '-';
- buf[3] = '\0';
- for (i = 0, buf[2] = '@'; i < ' '; i++, buf[2]++)
- {
- MSymbol alias;
+ @c DESCRIPTION ¤Ï¥³¥Þ¥ó¥É¤òÀâÌÀ¤¹¤ë M-text ¤Ç¤¢¤ë¤«¡¢ÀâÌÀ¤¬Ìµ¤¤¾ì¹ç¤Ë
+ ¤Ï #Mnil ¤Ç¤¢¤ë¡£
- one_char_symbol[i] = msymbol (buf);
- if (key_names[i])
- {
- alias = msymbol (key_names[i]);
- msymbol_put (one_char_symbol[i], M_key_alias, alias);
- }
- else
- alias = one_char_symbol[i];
- buf[2] += (i == 0) ? -32 : 32;
- msymbol_put (alias, M_key_alias, msymbol (buf));
- buf[2] -= (i == 0) ? -32 : 32;
- }
- for (buf[2] = i; i < 127; i++, buf[2]++)
- one_char_symbol[i] = msymbol (buf + 2);
- one_char_symbol[i++] = msymbol ("Delete");
- buf[2] = 'M';
- buf[3] = '-';
- buf[5] = '\0';
- buf2[0] = 'M';
- buf2[1] = '-';
- for (buf[4] = '@'; i < 160; i++, buf[4]++)
- {
- one_char_symbol[i] = msymbol (buf);
- if (key_names[i - 128])
- {
- strcpy (buf2 + 2, key_names[i - 128]);
- msymbol_put (one_char_symbol[i], M_key_alias, msymbol (buf2));
- }
- }
- for (buf[4] = i - 128; i < 255; i++, buf[4]++)
- one_char_symbol[i] = msymbol (buf + 2);
- one_char_symbol[i] = msymbol ("M-Delete");
+ @c STATUS ¤Ï¥¡¼³ä¤êÅö¤Æ¤¬¤É¤Î¤è¤¦¤ËÄê¤á¤é¤ì¤ë¤«¤ò¤¢¤é¤ï¤¹¥·¥ó¥Ü¥ë
+ ¤Ç¤¢¤ê¡¢¤½¤ÎÃÍ¤Ï #Mnil ¡Ê¥Ç¥Õ¥©¥ë¥È¤Î³ä¤êÅö¤Æ¡Ë, #Mcustomized ¡Ê¥æ¡¼
+ ¥¶Ëè¤Î¥«¥¹¥¿¥Þ¥¤¥º¥Õ¥¡¥¤¥ë¤Ë¤è¤Ã¤Æ¥«¥¹¥¿¥Þ¥¤¥º¤µ¤ì¤¿³ä¤êÅö¤Æ¡Ë,
+ #Mconfigured ¡Êminput_config_command ()¤ò¸Æ¤Ö¤³¤È¤Ë¤è¤Ã¤ÆÀßÄꤵ¤ì¤ë
+ ³ä¤êÅö¤Æ¡Ë¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£¥í¡¼¥«¥ë¥³¥Þ¥ó¥É¤Î¾ì¹ç¤Ë¤Ï¡¢
+ #Minherited ¡ÊÂбþ¤¹¤ë¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É¤«¤é¤Î·Ñ¾µ¤Ë¤è¤ë³ä¤êÅö¤Æ¡Ë
+ ¤Ç¤â¤è¤¤¡£
- command_list = variable_list = NULL;
+ @c KEYSEQ ¤Ï£±¤Ä°Ê¾å¤Î¥·¥ó¥Ü¥ë¤«¤é¤Ê¤ë plist ¤Ç¤¢¤ê¡¢³Æ¥·¥ó¥Ü¥ë¤Ï¥³¥Þ
+ ¥ó¥É¤Ë³ä¤êÅö¤Æ¤é¤ì¤Æ¤¤¤ë¥¡¼¥·¡¼¥¯¥¨¥ó¥¹¤òɽ¤¹¡£KEYSEQ ¤¬Ìµ¤¤¾ì¹ç¤Ï¡¢
+ ¤½¤Î¥³¥Þ¥ó¥É¤Ï¸½¾õ¤Ç»ÈÍÑÉÔǽ¤Ç¤¢¤ë¡£¡Ê¤¹¤Ê¤ï¤Á¥³¥Þ¥ó¥É¤ÎÆ°ºî¤òµ¯
+ Æ°¤Ç¤¤ë¥¡¼¥·¡¼¥¯¥¨¥ó¥¹¤¬Ìµ¤¤¡£¡Ë
- minput_default_driver.open_im = open_im;
- minput_default_driver.close_im = close_im;
- minput_default_driver.create_ic = create_ic;
- minput_default_driver.destroy_ic = destroy_ic;
- minput_default_driver.filter = filter;
- minput_default_driver.lookup = lookup;
- minput_default_driver.callback_list = mplist ();
- mplist_put (minput_default_driver.callback_list, Minput_reset,
- (void *) reset_ic);
- minput_driver = &minput_default_driver;
- return 0;
-}
+ $COMMAND ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢ÊÖ¤µ¤ì¤ë plist ¤ÎºÇ½é¤ÎÍ×ÁǤϡ¢
+ $COMMAND ¤Ë´Ø¤¹¤ë¾ðÊó¤ò´Þ¤à¡£
-void
-minput__fini ()
-{
- if (command_list)
- {
- M17N_OBJECT_UNREF (command_list);
- command_list = NULL;
- }
- if (variable_list)
- {
- M17N_OBJECT_UNREF (variable_list);
- variable_list = NULL;
- }
+ @return
- if (minput_default_driver.callback_list)
- {
- M17N_OBJECT_UNREF (minput_default_driver.callback_list);
- minput_default_driver.callback_list = NULL;
- }
- if (minput_driver->callback_list)
- {
- M17N_OBJECT_UNREF (minput_driver->callback_list);
- minput_driver->callback_list = NULL;
- }
+ µá¤á¤é¤ì¤¿¾ðÊ󤬸«¤Ä¤«¤ì¤Ð¡¢¶õ¤Ç¤Ê¤¤ plist ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¥ê¥¹
+ ¥È¤Ï¥é¥¤¥Ö¥é¥ê¤¬´ÉÍý¤·¤Æ¤¤¤ë¤Î¤Ç¡¢¸Æ½Ð¦¤¬Êѹ¹¤·¤¿¤ê²òÊü¤·¤¿¤ê¤¹¤ë
+ ¤³¤È¤Ï¤Ç¤¤Ê¤¤¡£
- if (im_info_list)
- {
- while (! MPLIST_TAIL_P (im_info_list))
- {
- /* Pop (t . mdb) */
- mplist_pop (im_info_list);
- free_im_info ((MInputMethodInfo *) MPLIST_VAL (im_info_list));
- /* Pop (t . im_info) */
- mplist_pop (im_info_list);
- }
- M17N_OBJECT_UNREF (im_info_list);
- im_info_list = NULL;
- }
-
- M17N_OBJECT_UNREF (load_im_info_keys);
-}
+ ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¤¹¤Ê¤ï¤Á»ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤ä¥³¥Þ¥ó¥É¤¬Â¸ºß¤·¤Ê¤±¤ì¤Ð
+ @c NULL ¤òÊÖ¤¹¡£ */
-void
-minput__callback (MInputContext *ic, MSymbol command)
+#if EXAMPLE_CODE
+MText *
+get_im_command_description (MSymbol language, MSymbol name, MSymbol command)
{
- if (ic->im->driver.callback_list)
- {
- MInputCallbackFunc func
- = (MInputCallbackFunc) mplist_get (ic->im->driver.callback_list,
- command);
+ /* Return a description of the command COMMAND of the input method
+ specified by LANGUAGE and NAME. */
+ MPlist *cmd = minput_get_command (langauge, name, command);
+ MPlist *plist;
- if (func)
- (func) (ic, command);
- }
+ if (! cmds)
+ return NULL;
+ plist = mplist_value (cmds); /* (NAME DESCRIPTION STATUS KEY-SEQ ...) */
+ plist = mplist_next (plist); /* (DESCRIPTION STATUS KEY-SEQ ...) */
+ return (mplist_key (plist) == Mtext
+ ? (MText *) mplist_value (plist)
+ : NULL);
}
+#endif
-MSymbol
-minput__char_to_key (int c)
+MPlist *
+minput_get_command (MSymbol language, MSymbol name, MSymbol command)
{
- if (c < 0 || c >= 0x100)
- return Mnil;
-
- return one_char_symbol[c];
-}
+ MInputMethodInfo *im_info;
-/*** @} */
-#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
+ MINPUT__INIT ();
-
-/* External API */
+ im_info = get_im_info (language, name, Mnil, Mcommand);
+ if (! im_info
+ || ! im_info->configured_cmds
+ || MPLIST_TAIL_P (im_info->configured_cmds))
+ return NULL;
+ if (command == Mnil)
+ return im_info->configured_cmds;
+ return mplist__assq (im_info->configured_cmds, command);
+}
-/*** @addtogroup m17nInputMethod */
-/*** @{ */
/*=*/
/***en
- @name Variables: Predefined symbols for callback commands.
+ @brief Configure the key sequence of an input method command.
- These are the predefined symbols that are used as the @c COMMAND
- argument of callback functions of an input method driver (see
- #MInputDriver::callback_list ).
+ The minput_config_command () function assigns a list of key
+ sequences $KEYSEQLIST to the command $COMMAND of the input method
+ specified by $LANGUAGE and $NAME.
- Most of them don't require extra argument nor return any value;
- exceptions are these:
+ If $KEYSEQLIST is a non-empty plist, it must be a list of key
+ sequences, and each key sequence must be a plist of symbols.
- Minput_get_surrounding_text: When a callback function assigned for
- this command is called, the first element of #MInputContext::plist
- has key #Msymbol and the value specifies which portion of the
- surrounding text should be retrieved. If the value is positive,
- it specifies the number of characters following the current cursor
- position. If the value is negative, the absolute value specifies
- the number of characters preceding the current cursor position.
- The callback function must set the key of this element to #Mtext
- and the value to the retrived M-text (whose length may be shorter
- than the requested number of characters if the available text is
- not that long, or it may be longer if an application thinks it's
- more efficient to return that length).
+ If $KEYSEQLIST is an empty plist, any configuration and
+ customization of the command are cancelled, and default key
+ sequences become effective.
- Minput_delete_surrounding_text: When a callback function assigned
- for this command is called, the first element of
- #MInputContext::plist has key #Msymbol and the value specifies
- which portion of the surrounding text should be deleted in the
- same way as the case of Minput_get_surrounding_text. The callback
- function must delete the specified text. It should not alter
- #MInputContext::plist. */
+ If $KEYSEQLIST is NULL, the configuration of the command is
+ canceled, and the original key sequences (what saved in per-user
+ customization file, or the default one) become effective.
-/***ja
- @name ÊÑ¿ô¡§ ¥³¡¼¥ë¥Ð¥Ã¥¯¥³¥Þ¥ó¥ÉÍÑÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë.
+ In the latter two cases, $COMMAND can be #Mnil to make all the
+ commands of the input method the target of the operation.
- ÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Î¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Ë¤ª¤¤¤Æ @c COMMAND
- °ú¿ô¤È¤·¤ÆÍѤ¤¤é¤ì¤ëÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë (#MInputDriver::callback_list »²¾È)¡£
- */
-/*** @{ */
-/*=*/
+ If $NAME is #Mnil, this function configures the key assignment of a
+ global command, not that of a specific input method.
-MSymbol Minput_preedit_start;
-MSymbol Minput_preedit_done;
-MSymbol Minput_preedit_draw;
-MSymbol Minput_status_start;
-MSymbol Minput_status_done;
-MSymbol Minput_status_draw;
-MSymbol Minput_candidates_start;
-MSymbol Minput_candidates_done;
-MSymbol Minput_candidates_draw;
-MSymbol Minput_set_spot;
-MSymbol Minput_toggle;
-MSymbol Minput_reset;
-MSymbol Minput_get_surrounding_text;
-MSymbol Minput_delete_surrounding_text;
-/*** @} */
+ The configuration takes effect for input methods opened or
+ re-opened later in the current session. In order to make the
+ configuration take effect for the future session, it must be saved
+ in a per-user customization file by the function
+ minput_save_config ().
-/*=*/
+ @return
+ If the operation was successful, this function returns 0,
+ otherwise returns -1. The operation fails in these cases:
+
+ - $KEYSEQLIST is not in a valid form.
+
- $COMMAND is not available for the input method.
+
- $LANGUAGE and $NAME do not specify an existing input method.
+
-/***en
- @name Variables: Predefined symbols for special input events.
+ @seealso
+ minput_get_commands (), minput_save_config ().
+*/
+/***ja
+ @brief ÆþÎϥ᥽¥Ã¥É¤Î¥³¥Þ¥ó¥É¤Î¥¡¼¥·¡¼¥¯¥¨¥ó¥¹¤òÀßÄꤹ¤ë.
- These are the predefined symbols that are used as the @c KEY
- argument of minput_filter (). */
+ ´Ø¿ô minput_config_command () ¤Ï¥¡¼¥·¡¼¥¯¥¨¥ó¥¹¤Î¥ê¥¹¥È
+ $KEYSEQLIST ¤ò¡¢$LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤ëÆþÎϥ᥽¥Ã¥É¤Î
+ ¥³¥Þ¥ó¥É $COMMAND ¤Ë³ä¤êÅö¤Æ¤ë¡£
-/*** @{ */
-/*=*/
+ $KEYSEQLIST ¤¬¶õ¥ê¥¹¥È¤Ç¤Ê¤±¤ì¤Ð¡¢¥¡¼¥·¡¼¥¯¥¨¥ó¥¹¤Î¥ê¥¹¥È¤Ç¤¢¤ê¡¢
+ ³Æ¥¡¼¥·¡¼¥¯¥¨¥ó¥¹¤Ï¥·¥ó¥Ü¥ë¤Î plist ¤Ç¤¢¤ë¡£
-MSymbol Minput_focus_out;
-MSymbol Minput_focus_in;
-MSymbol Minput_focus_move;
+ $KEYSEQLIST ¤¬¶õ¤Î plist ¤Ê¤é¤Ð¡¢¤½¤Î¥³¥Þ¥ó¥É¤ÎÀßÄê¤ä¥«¥¹¥¿¥Þ¥¤¥º¤Ï
+ ¤¹¤Ù¤Æ¥¥ã¥ó¥»¥ë¤µ¤ì¡¢¥Ç¥Õ¥©¥ë¥È¤Î¥¡¼¥·¡¼¥¯¥¨¥ó¥¹¤¬Í¸ú¤Ë¤Ê¤ë¡£
-/*** @} */
+ $KEYSEQLIST ¤¬ NULL ¤Ç¤¢¤ì¤Ð¡¢¤½¤Î¥³¥Þ¥ó¥É¤ÎÀßÄê¤Ï¥¥ã¥ó¥»¥ë¤µ¤ì¡¢
+ ¸µ¤Î¥¡¼¥·¡¼¥¯¥¨¥ó¥¹¡Ê¥æ¡¼¥¶Ëè¤Î¥«¥¹¥¿¥Þ¥¤¥º¥Õ¥¡¥¤¥ë¤ËÊݸ¤µ¤ì¤Æ¤¤
+ ¤ë¤â¤Î¡¢¤¢¤ë¤¤¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¤â¤Î¡Ë¤¬Í¸ú¤Ë¤Ê¤ë¡£
-/*=*/
+ ¸å¤Î¤Õ¤¿¤Ä¤Î¾ì¹ç¤Ë¤Ï¡¢$COMMAND ¤Ï #Mnil ¤ò¤È¤ë¤³¤È¤¬¤Ç¤¡¢»ØÄê¤ÎÆþ
+ Îϥ᥽¥Ã¥É¤ÎÁ´¤Æ¤Î¥³¥Þ¥ó¥ÉÀßÄê¤Î¥¥ã¥ó¥»¥ë¤ò°ÕÌ£¤¹¤ë¡£
-/***en
- @brief The default driver for internal input methods.
+ $NAME ¤¬ #Mnil ¤Ê¤é¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¸Ä¡¹¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¤Ê¤¯¥°¥í¡¼¥Ð
+ ¥ë¤Ê¥³¥Þ¥ó¥É¤Î¥¡¼³ä¤êÅö¤Æ¤òÀßÄꤹ¤ë¡£
- The variable #minput_default_driver is the default driver for
- internal input methods.
+ ¤³¤ì¤é¤ÎÀßÄê¤Ï¡¢¸½¹Ô¤Î¥»¥Ã¥·¥ç¥óÃæ¤ÇÆþÎϥ᥽¥Ã¥É¤¬¥ª¡¼¥×¥ó¡Ê¤Þ¤¿¤Ï
+ ºÆ¥ª¡¼¥×¥ó¡Ë¤µ¤ì¤¿»þÅÀ¤Ç͸ú¤Ë¤Ê¤ë¡£¾Íè¤Î¥»¥Ã¥·¥ç¥óÃæ¤Ç¤â͸ú¤Ë¤¹
+ ¤ë¤¿¤á¤Ë¤Ï¡¢´Ø¿ô minput_save_config () ¤òÍѤ¤¤Æ¥æ¡¼¥¶Ëè¤Î¥«¥¹¥¿¥Þ¥¤
+ ¥º¥Õ¥¡¥¤¥ë¤ËÊݸ¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
- The member MInputDriver::open_im () searches the m17n database for
- an input method that matches the tag \< #Minput_method, $LANGUAGE,
- $NAME\> and loads it.
+ @return
- The member MInputDriver::callback_list () is @c NULL. Thus, it is
- programmers responsibility to set it to a plist of proper callback
- functions. Otherwise, no feedback information (e.g. preedit text)
- can be shown to users.
+ ¤³¤Î´Ø¿ô¤Ï¡¢½èÍý¤¬À®¸ù¤¹¤ì¤Ð 0 ¤ò¡¢¼ºÇÔ¤¹¤ì¤Ð -1 ¤òÊÖ¤¹¡£¼ºÇԤȤϰʲ¼¤Î¾ì¹ç¤Ç¤¢¤ë¡£
+
+ - $KEYSEQLIST ¤¬Í¸ú¤Ê·Á¼°¤Ç¤Ê¤¤¡£
+
- $COMMAND ¤¬»ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤ÇÍøÍѤǤ¤Ê¤¤¡£
+
- $LANGUAGE ¤È $NAME ¤Ç»ØÄꤵ¤ì¤ëÆþÎϥ᥽¥Ã¥É¤¬Â¸ºß¤·¤Ê¤¤¡£
+
- The macro M17N_INIT () sets the variable #minput_driver to the
- pointer to this driver so that all internal input methods use it.
+ @seealso
+ minput_get_commands (), minput_save_config ().
+*/
- Therefore, unless @c minput_driver is set differently, the driver
- dependent arguments $ARG of the functions whose name begins with
- "minput_" are all ignored. */
+#if EXAMPLE_CODE
+/* Add "C-x u" to the "start" command of Unicode input method. */
+{
+ MSymbol start_command = msymbol ("start");
+ MSymbol unicode = msymbol ("unicode");
+ MPlist *cmd, *plist, *key_seq_list, *key_seq;
-/***ja
- @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥǥե©¥ë¥È¥É¥é¥¤¥Ð.
+ /* At first get the current key-sequence assignment. */
+ cmd = minput_get_command (Mt, unicode, start_command);
+ if (! cmd)
+ {
+ /* The input method does not have the command "start". Here
+ should come some error handling code. */
+ }
+ /* Now CMD == ((start DESCRIPTION STATUS KEY-SEQUENCE ...) ...).
+ Extract the part (KEY-SEQUENCE ...). */
+ plist = mplist_next (mplist_next (mplist_next (mplist_value (cmd))));
+ /* Copy it because we should not modify it directly. */
+ key_seq_list = mplist_copy (plist);
+
+ key_seq = mplist ();
+ mplist_add (key_seq, Msymbol, msymbol ("C-x"));
+ mplist_add (key_seq, Msymbol, msymbol ("u"));
+ mplist_add (key_seq_list, Mplist, key_seq);
+ m17n_object_unref (key_seq);
+
+ minput_config_command (Mt, unicode, start_command, key_seq_list);
+ m17n_object_unref (key_seq_list);
+}
+#endif
- ÊÑ¿ô #minput_default_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѤΥǥե©¥ë¥È¤Î¥É¥é¥¤¥Ð¤òɽ¤¹¡£
+int
+minput_config_command (MSymbol language, MSymbol name, MSymbol command,
+ MPlist *keyseqlist)
+{
+ MInputMethodInfo *im_info, *config;
+ MPlist *plist;
- ¥á¥ó¥Ð MInputDriver::open_im () ¤Ï m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹Ã椫¤é¥¿¥°
- \< #Minput_method, $LANGUAGE, $NAME\>
- ¤Ë¹çÃפ¹¤ëÆþÎϥ᥽¥Ã¥É¤òõ¤·¡¢¤½¤ì¤ò¥í¡¼¥É¤¹¤ë¡£
+ MINPUT__INIT ();
- ¥á¥ó¥Ð MInputDriver::callback_list () ¤Ï @c NULL ¤Ç¤¢¤ê¡¢
- ¤·¤¿¤¬¤Ã¤Æ¡¢¥×¥í¥°¥é¥Þ¦¤ÇÀÕǤ¤ò»ý¤Ã¤Æ ŬÀڤʥ³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Î plist
- ¤ËÀßÄꤷ¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¤µ¤â¤Ê¤¤¤È¡¢preedit
- ¥Æ¥¥¹¥È¤Ê¤É¤Î¥Õ¥£¡¼¥É¥Ð¥Ã¥¯¾ðÊ󤬥桼¥¶¤Ëɽ¼¨¤µ¤ì¤Ê¤¤¡£
+ im_info = get_im_info (language, name, Mnil, Mcommand);
+ if (! im_info)
+ MERROR (MERROR_IM, -1);
+ if (command == Mnil ? (keyseqlist && ! MPLIST_TAIL_P (keyseqlist))
+ : (! im_info->cmds
+ || ! mplist__assq (im_info->configured_cmds, command)))
+ MERROR (MERROR_IM, -1);
+ if (keyseqlist && ! MPLIST_TAIL_P (keyseqlist))
+ {
+ MPLIST_DO (plist, keyseqlist)
+ if (! check_command_keyseq (plist))
+ MERROR (MERROR_IM, -1);
+ }
- ¥Þ¥¯¥í M17N_INIT () ¤ÏÊÑ¿ô #minput_driver
- ¤ò¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤ËÀßÄꤷ¡¢Á´¤Æ¤ÎÆâÉôÆþÎϥ᥽¥Ã¥É¤¬¤³¤Î¥É¥é¥¤¥Ð¤ò»È¤¦¤è¤¦¤Ë¤¹¤ë¡£
+ config = get_config_info (im_info);
+ if (! config)
+ {
+ if (! im_config_list)
+ im_config_list = mplist ();
+ config = new_im_info (NULL, language, name, Mnil, im_config_list);
+ config->cmds = mplist ();
+ config->vars = mplist ();
+ }
- ¤·¤¿¤¬¤Ã¤Æ¡¢@c minput_driver ¤¬¥Ç¥Õ¥©¥ë¥ÈÃͤΤޤޤǤ¢¤ì¤Ð¡¢minput_
- ¤Ç»Ï¤Þ¤ë´Ø¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô $ARG ¤Ï¤¹¤Ù¤Æ̵»ë¤µ¤ì¤ë¡£ */
+ if (! keyseqlist && MPLIST_TAIL_P (config->cmds))
+ /* Nothing to do. */
+ return 0;
+
+ if (command == Mnil)
+ {
+ if (! keyseqlist)
+ {
+ /* Cancal the configuration. */
+ if (MPLIST_TAIL_P (config->cmds))
+ return 0;
+ mplist_set (config->cmds, Mnil, NULL);
+ }
+ else
+ {
+ /* Cancal the customization. */
+ MInputMethodInfo *custom = get_custom_info (im_info);
+
+ if (MPLIST_TAIL_P (config->cmds)
+ && (! custom || ! custom->cmds || MPLIST_TAIL_P (custom->cmds)))
+ /* Nothing to do. */
+ return 0;
+ mplist_set (config->cmds, Mnil, NULL);
+ MPLIST_DO (plist, custom->cmds)
+ {
+ command = MPLIST_SYMBOL (MPLIST_PLIST (plist));
+ plist = mplist ();
+ mplist_add (plist, Msymbol, command);
+ mplist_push (config->cmds, Mplist, plist);
+ M17N_OBJECT_UNREF (plist);
+ }
+ }
+ }
+ else
+ {
+ plist = mplist__assq (config->cmds, command);
+ if (! keyseqlist)
+ {
+ /* Cancel the configuration. */
+ if (! plist)
+ return 0;
+ mplist__pop_unref (plist);
+ }
+ else if (MPLIST_TAIL_P (keyseqlist))
+ {
+ /* Cancel the customization. */
+ MInputMethodInfo *custom = get_custom_info (im_info);
+ int no_custom = (! custom || ! custom->cmds
+ || ! mplist__assq (custom->cmds, command));
+ if (! plist)
+ {
+ if (no_custom)
+ return 0;
+ plist = mplist ();
+ mplist_add (config->cmds, Mplist, plist);
+ M17N_OBJECT_UNREF (plist);
+ plist = mplist_add (plist, Msymbol, command);
+ }
+ else
+ {
+ if (no_custom)
+ mplist__pop_unref (plist);
+ else
+ {
+ plist = MPLIST_PLIST (plist); /* (NAME nil KEYSEQ ...) */
+ plist = MPLIST_NEXT (plist);
+ mplist_set (plist, Mnil, NULL);
+ }
+ }
+ }
+ else
+ {
+ MPlist *pl;
+
+ if (plist)
+ {
+ plist = MPLIST_NEXT (MPLIST_PLIST (plist));
+ if (! MPLIST_TAIL_P (plist))
+ mplist_set (plist, Mnil, NULL);
+ }
+ else
+ {
+ plist = mplist ();
+ mplist_add (config->cmds, Mplist, plist);
+ M17N_OBJECT_UNREF (plist);
+ plist = mplist_add (plist, Msymbol, command);
+ plist = MPLIST_NEXT (plist);
+ }
+ MPLIST_DO (keyseqlist, keyseqlist)
+ {
+ pl = mplist_copy (MPLIST_VAL (keyseqlist));
+ plist = mplist_add (plist, Mplist, pl);
+ M17N_OBJECT_UNREF (pl);
+ }
+ }
+ }
+ config_all_commands (im_info);
+ im_info->tick = time (NULL);
+ return 0;
+}
-MInputDriver minput_default_driver;
/*=*/
/***en
- @brief The driver for internal input methods.
+ @brief Get information about input method variable(s).
- The variable #minput_driver is a pointer to the input method
- driver that is used by internal input methods. The macro
- M17N_INIT () initializes it to a pointer to #minput_default_driver
- if .h> is included. */
-/***ja
- @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥɥ饤¥Ð.
+ The minput_get_variable () function returns information about
+ variable $VARIABLE of the input method specified by $LANGUAGE and $NAME.
+ An input method variable controls behavior of an input method.
- ÊÑ¿ô #minput_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤Æ»ÈÍѤµ¤ì¤Æ¤¤¤ëÆþÎÏ¥á
- ¥½¥Ã¥É¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£¥Þ¥¯¥í M17N_INIT () ¤Ï¤³¤Î¥Ý¥¤¥ó
- ¥¿¤ò#minput_default_driver (.h> ¤¬ include ¤µ¤ì¤Æ¤¤¤ë
- »þ) ¤Ë½é´ü²½¤¹¤ë¡£ */
+ There are two kinds of variables, global and local. A global
+ variable has a global definition, and the description and the value
+ may be inherited by a local variable. Each input method defines a
+ local variable which has local value. It may also declare a
+ local variable that inherits definition of a global variable of
+ the same name.
-MInputDriver *minput_driver;
+ If $LANGUAGE is #Mt and $NAME is #Mnil, information about a global
+ variable is returned. Otherwise information about a local variable
+ is returned.
-MSymbol Minput_driver;
+ If $VARIABLE is #Mnil, information about all variables is
+ returned.
-/*=*/
+ The return value is a @e well-formed plist (#m17nPlist) of this
+ format:
+@verbatim
+ ((NAME DESCRIPTION STATUS VALUE [VALID-VALUE ...]) ...)
+@endverbatim
+ @c NAME is a symbol representing the variable name.
+
+ @c DESCRIPTION is an M-text describing the variable, or #Mnil if the
+ variable has no description.
+
+ @c STATUS is a symbol representing how the value is decided. The
+ value is #Mnil (the default value), #Mcustomized (the value is
+ customized by per-user customization file), or #Mconfigured (the
+ value is set by the call of minput_config_variable ()). For a
+ local variable only, it may also be #Minherited (the value is
+ inherited from the corresponding global variable).
+
+ @c VALUE is the initial value of the variable. If the key of this
+ element is #Mt, the variable has no initial value. Otherwise, the
+ key is #Minteger, #Msymbol, or #Mtext and the value is of the
+ corresponding type.
+
+ @c VALID-VALUEs (if any) specify which values the variable can have.
+ They have the same type (i.e. having the same key) as @c VALUE except
+ for the case that VALUE is an integer. In that case, @c VALID-VALUE
+ may be a plist of two integers specifying the range of possible
+ values.
-/***en
- @brief Open an input method.
+ If there no @c VALID-VALUE, the variable can have any value as long
+ as the type is the same as @c VALUE.
- The minput_open_im () function opens an input method whose
- language and name match $LANGUAGE and $NAME, and returns a pointer
- to the input method object newly allocated.
+ If $VARIABLE is not #Mnil, the first element of the returned plist
+ contains the information about $VARIABLE.
- This function at first decides a driver for the input method as
- described below.
+ @return
- If $LANGUAGE is not #Mnil, the driver pointed by the variable
- #minput_driver is used.
+ If the requested information was found, a pointer to a non-empty
+ plist is returned. As the plist is kept in the library, the
+ caller must not modify nor free it.
- If $LANGUAGE is #Mnil and $NAME has the property #Minput_driver, the
- driver pointed to by the property value is used to open the input
- method. If $NAME has no such a property, @c NULL is returned.
+ Otherwise (the specified input method or the specified variable
+ does not exist), @c NULL is returned. */
+/***ja
+ @brief ÆþÎϥ᥽¥Ã¥É¤ÎÊÑ¿ô¤Ë´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë.
+
+ ´Ø¿ô minput_get_variable () ¤Ï¡¢$LANGUAGE ¤È $NAME ¤Ç»ØÄꤵ¤ì¤ëÆþÎÏ
+ ¥á¥½¥Ã¥É¤ÎÊÑ¿ô $VARIABLE ¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£ÆþÎϥ᥽¥Ã¥É¤ÎÊÑ¿ô¤È¤Ï¡¢
+ ÆþÎϥ᥽¥Ã¥É¤Î¿¶Éñ¤òÀ©¸æ¤¹¤ë¤â¤Î¤Ç¤¢¤ë¡£
+
+ ÊÑ¿ô¤Ë¤Ï¡¢¥°¥í¡¼¥Ð¥ë¤È¥í¡¼¥«¥ë¤Î£²¼ïÎब¤¢¤ë¡£¥°¥í¡¼¥Ð¥ë¤ÊÊÑ¿ô¤Ï¥°
+ ¥í¡¼¥Ð¥ë¤ËÄêµÁ¤µ¤ì¡¢¥í¡¼¥«¥ë¤ÊÊÑ¿ô¤Ï¤½¤ÎÀâÌÀ¤ÈÃͤò·Ñ¾µ¤¹¤ë¤³¤È¤¬¤Ç
+ ¤¤ë¡£³ÆÆþÎϥ᥽¥Ã¥É¤Ï¥í¡¼¥«¥ë¤ÊÃͤò»ý¤Ä¥í¡¼¥«¥ë¤ÊÊÑ¿ô¤òÄêµÁ¤¹¤ë¡£
+ ¤Þ¤¿Æ±Ì¾¤Î¥°¥í¡¼¥Ð¥ë¤ÊÊÑ¿ô¤ÎÄêµÁ¤ò·Ñ¾µ¤¹¤ë¥í¡¼¥«¥ë¤ÊÊÑ¿ô¤òÀë¸À¤¹¤ë
+ ¤³¤È¤â¤Ç¤¤ë¡£
+
+ $LANGUAGE ¤¬ #Mt ¤Ç $NAME ¤¬ #Mnil ¤Î¾ì¹ç¤Ï¡¢¤³¤Î´Ø¿ô¤Ï¥°¥í¡¼¥Ð¥ëÊÑ
+ ¿ô¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¥í¡¼¥«¥ëÊÑ¿ô¤Ë´Ø¤¹¤ë¤â¤Î¤òÊÖ¤¹¡£
+
+ $VARIABLE ¤¬ #Mnil ¤Î¾ì¹ç¤Ï¡¢¤¹¤Ù¤Æ¤Î¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£
+
+ Ìá¤êÃͤϰʲ¼¤Î·Á¼°¤Î @e well-formed plist (#m17nPlist) ¤Ç¤¢¤ë¡£
+@verbatim
+ ((NAME DESCRIPTION STATUS VALUE [VALID-VALUE ...]) ...)
+@endverbatim
- Then, the member MInputDriver::open_im () of the driver is
- called.
+ @c NAME ¤ÏÊÑ¿ô¤Î̾Á°¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
- $ARG is set in the member @c arg of the structure MInputMethod so
- that the driver can refer to it. */
+ @c DESCRIPTION ¤ÏÊÑ¿ô¤òÀâÌÀ¤¹¤ë M-text ¤Ç¤¢¤ë¤«¡¢ÀâÌÀ¤¬Ìµ¤¤¾ì¹ç¤Ë¤Ï
+ #Mnil ¤Ç¤¢¤ë¡£
-/***ja
- @brief ÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë.
+ @c STATUS ¤ÏÃͤ¬¤É¤Î¤è¤¦¤ËÄê¤á¤é¤ì¤ë¤«¤ò¤¢¤é¤ï¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢
+ @c STATUS ¤ÎÃÍ¤Ï #Mnil ¡Ê¥Ç¥Õ¥©¥ë¥È¤ÎÃÍ¡Ë, #Mcustomized ¡Ê¥æ¡¼¥¶Ëè¤Î
+ ¥«¥¹¥¿¥Þ¥¤¥º¥Õ¥¡¥¤¥ë¤Ë¤è¤Ã¤Æ¥«¥¹¥¿¥Þ¥¤¥º¤µ¤ì¤¿ÃÍ¡Ë, #Mconfigured
+ ¡Êminput_config_variable ()¤ò¸Æ¤Ö¤³¤È¤Ë¤è¤Ã¤ÆÀßÄꤵ¤ì¤ëÃ͡ˤΤ¤¤º¤ì
+ ¤«¤Ç¤¢¤ë¡£¥í¡¼¥«¥ëÊÑ¿ô¤Î¾ì¹ç¤Ë¤Ï¡¢#Minherited ¡ÊÂбþ¤¹¤ë¥°¥í¡¼¥Ð¥ë
+ ÊÑ¿ô¤«¤é·Ñ¾µ¤·¤¿Ã͡ˤǤâ¤è¤¤¡£
- ´Ø¿ô minput_open_im () ¤Ï¸À¸ì $LANGUAGE ¤È̾Á° $NAME
- ¤Ë¹çÃפ¹¤ëÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤·¡¢¿·¤¿¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿ÆþÎϥ᥽¥Ã¥É¥ª¥Ö¥¸¥§¥¯¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
-
- ¤³¤Î´Ø¿ô¤Ï¡¢¤Þ¤ºÆþÎϥ᥽¥Ã¥ÉÍѤΥɥ饤¥Ð¤ò°Ê²¼¤Î¤è¤¦¤Ë¤·¤Æ·èÄꤹ¤ë¡£
+ @c VALUE ¤ÏÊÑ¿ô¤Î½é´üÃͤǤ¢¤ë¡£¤³¤ÎÍ×ÁǤΥ¡¼¤¬#Mt ¤Ç¤¢¤ì¤Ð½é´üÃͤò»ý
+ ¤¿¤Ê¤¤¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¥¡¼¤Ï #Minteger, #Msymbol, #Mtext ¤Î¤¤¤º¤ì
+ ¤«¤Ç¤¢¤ê¡¢ÃͤϤ½¤ì¤¾¤ìÂбþ¤¹¤ë·¿¤Î¤â¤Î¤Ç¤¢¤ë¡£
- $LANGUAGE ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢ÊÑ¿ô #minput_driver
- ¤Ç»Ø¤µ¤ì¤Æ¤¤¤ë¥É¥é¥¤¥Ð¤òÍѤ¤¤ë¡£
+ @c VALID-VALUE ¤Ï¤â¤·¤¢¤ì¤Ð¡¢ÊÑ¿ô¤Î¼è¤êÆÀ¤ëÃͤò»ØÄꤹ¤ë¡£¤³¤ì¤Ï @c VALUE
+ ¤ÈƱ¤¸·¿(¤¹¤Ê¤ï¤ÁƱ¤¸¥¡¼¤ò»ý¤Ä) ¤Ç¤¢¤ë¤¬¡¢Îã³°¤È¤·¤Æ @c VALUE ¤¬
+ integer ¤Î¾ì¹ç¤Ï @c VALID-VALUE ¤Ï²Äǽ¤ÊÃͤÎÈϰϤò¼¨¤¹Æó¤Ä¤ÎÀ°¿ô¤«¤é
+ ¤Ê¤ë plist ¤È¤Ê¤ë¤³¤È¤¬¤Ç¤¤ë¡£
- $LANGUAGE ¤¬ #Mnil ¤Ç¤¢¤ê¡¢$NAME ¤¬ #Minput_driver
- ¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä¾ì¹ç¤Ë¤Ï¡¢¤½¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤǻؤµ¤ì¤Æ¤¤¤ëÆþÎϥɥ饤¥Ð¤òÍѤ¤¤ÆÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë¡£
- $NAME ¤Ë¤½¤Î¤è¤¦¤Ê¥×¥í¥Ñ¥Æ¥£¤¬Ìµ¤«¤Ã¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
+ @c VALID-VALUE ¤¬¤Ê¤±¤ì¤Ð¡¢ÊÑ¿ô¤Ï @c VALUE ¤ÈƱ¤¸·¿¤Ç¤¢¤ë¸Â¤ê¤¤¤«¤Ê¤ëÃͤâ
+ ¤È¤ë¤³¤È¤¬¤Ç¤¤ë¡£
- ¼¡¤¤¤Ç¡¢¥É¥é¥¤¥Ð¤Î¥á¥ó¥Ð MInputDriver::open_im () ¤¬¸Æ¤Ð¤ì¤ë¡£
+ $VARIABLE ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢ÊÖ¤µ¤ì¤ë plist ¤ÎºÇ½é¤ÎÍ×ÁǤÏ
+ $VARIABLE ¤Ë´Ø¤¹¤ë¾ðÊó¤ò´Þ¤à¡£
- $ARG ¤Ï¹½Â¤ÂÎ MInputMethod ¤Î¥á¥ó¥Ð @c arg ¤ËÀßÄꤵ¤ì¡¢¥É¥é¥¤¥Ð¤«¤é»²¾È¤Ç¤¤ë¡£
+ @return
- @latexonly \IPAlabel{minput_open} @endlatexonly
+ µá¤á¤é¤ì¤¿¾ðÊ󤬸«¤Ä¤«¤ì¤Ð¡¢¶õ¤Ç¤Ê¤¤ plist ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¥ê¥¹
+ ¥È¤Ï¥é¥¤¥Ö¥é¥ê¤¬´ÉÍý¤·¤Æ¤¤¤ë¤Î¤Ç¡¢¸Æ½Ð¦¤¬Êѹ¹¤·¤¿¤ê²òÊü¤·¤¿¤ê¤¹¤ë
+ ¤³¤È¤Ï¤Ç¤¤Ê¤¤¡£
-*/
+ ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¤¹¤Ê¤ï¤Á»ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤äÊÑ¿ô¤¬Â¸ºß¤·¤Ê¤±¤ì¤Ð
+ @c NULL ¤òÊÖ¤¹¡£ */
-MInputMethod *
-minput_open_im (MSymbol language, MSymbol name, void *arg)
+MPlist *
+minput_get_variable (MSymbol language, MSymbol name, MSymbol variable)
{
- MInputMethod *im;
- MInputDriver *driver;
+ MInputMethodInfo *im_info;
- MDEBUG_PRINT2 (" [IM] opening (%s %s) ... ",
- msymbol_name (language), msymbol_name (name));
- if (language)
- driver = minput_driver;
- else
- {
- driver = (MInputDriver *) msymbol_get (name, Minput_driver);
- if (! driver)
- MERROR (MERROR_IM, NULL);
- }
+ MINPUT__INIT ();
- MSTRUCT_CALLOC (im, MERROR_IM);
- im->language = language;
- im->name = name;
- im->arg = arg;
- im->driver = *driver;
- if ((*im->driver.open_im) (im) < 0)
- {
- MDEBUG_PRINT (" failed\n");
- free (im);
- return NULL;
- }
- MDEBUG_PRINT (" ok\n");
- return im;
+ im_info = get_im_info (language, name, Mnil, Mvariable);
+ if (! im_info || ! im_info->configured_vars)
+ return NULL;
+ if (variable == Mnil)
+ return im_info->configured_vars;
+ return mplist__assq (im_info->configured_vars, variable);
}
/*=*/
/***en
- @brief Close an input method.
+ @brief Configure the value of an input method variable.
- The minput_close_im () function closes the input method $IM, which
- must have been created by minput_open_im (). */
+ The minput_config_variable () function assigns $VALUE to the
+ variable $VARIABLE of the input method specified by $LANGUAGE and
+ $NAME.
-/***ja
- @brief ÆþÎϥ᥽¥Ã¥É¤ò¥¯¥í¡¼¥º¤¹¤ë.
+ If $VALUE is a non-empty plist, it must be a plist of one element
+ whose key is #Minteger, #Msymbol, or #Mtext, and the value is of
+ the corresponding type. That value is assigned to the variable.
- ´Ø¿ô minput_close_im () ¤Ï¡¢ÆþÎϥ᥽¥Ã¥É $IM ¤ò¥¯¥í¡¼¥º¤¹¤ë¡£
- ¤³¤ÎÆþÎϥ᥽¥Ã¥É $IM ¤Ï minput_open_im () ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£ */
+ If $VALUE is an empty plist, any configuration and customization
+ of the variable are canceled, and the default value is assigned to
+ the variable.
-void
-minput_close_im (MInputMethod *im)
-{
- MDEBUG_PRINT2 (" [IM] closing (%s %s) ... ",
- msymbol_name (im->name), msymbol_name (im->language));
- (*im->driver.close_im) (im);
- free (im);
- MDEBUG_PRINT (" done\n");
-}
+ If $VALUE is NULL, the configuration of the variable is canceled,
+ and the original value (what saved in per-user customization file,
+ or the default value) is assigned to the variable.
-/*=*/
+ In the latter two cases, $VARIABLE can be #Mnil to make all the
+ variables of the input method the target of the operation.
-/***en
- @brief Create an input context.
+ If $NAME is #Mnil, this function configures the value of global
+ variable, not that of a specific input method.
- The minput_create_ic () function creates an input context object
- associated with input method $IM, and calls callback functions
- corresponding to #Minput_preedit_start, #Minput_status_start, and
- #Minput_status_draw in this order.
+ The configuration takes effect for input methods opened or
+ re-opened later in the current session. To make the configuration
+ take effect for the future session, it must be saved in a per-user
+ customization file by the function minput_save_config ().
@return
- If an input context is successfully created, minput_create_ic ()
- returns a pointer to it. Otherwise it returns @c NULL. */
+ If the operation was successful, this function returns 0,
+ otherwise returns -1. The operation fails in these cases:
+
+ - $VALUE is not in a valid form, the type does not match the
+ definition, or the value is our of range.
+
- $VARIABLE is not available for the input method.
+
- $LANGUAGE and $NAME do not specify an existing input method.
+
+
+ @seealso
+ minput_get_variable (), minput_save_config (). */
/***ja
- @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÀ¸À®¤¹¤ë.
+ @brief ÆþÎϥ᥽¥Ã¥É¤ÎÊÑ¿ô¤ÎÃͤòÀßÄꤹ¤ë.
- ´Ø¿ô minput_create_ic () ¤ÏÆþÎϥ᥽¥Ã¥É $IM
- ¤ËÂбþ¤¹¤ëÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤·¡¢
- #Minput_preedit_start, #Minput_status_start, #Minput_status_draw
- ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¤³¤Î½ç¤Ë¸Æ¤Ö¡£
+ ´Ø¿ô minput_config_variable () ¤ÏÃÍ $VALUE ¤ò¡¢$LANGUAGE ¤È $NAME
+ ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤ëÆþÎϥ᥽¥Ã¥É¤ÎÊÑ¿ô $VARIABLE ¤Ë³ä¤êÅö¤Æ¤ë¡£
- @return
- ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤¬À¸À®¤µ¤ì¤¿¾ì¹ç¡¢minput_create_ic ()
- ¤Ï¤½¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¼ºÇÔ¤·¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
- */
+ $VALUE ¤¬ ¶õ¥ê¥¹¥È¤Ç¤Ê¤±¤ì¤Ð¡¢£±Í×ÁǤΠplist ¤Ç¤¢¤ê¡¢¤½¤Î¥¡¼¤Ï
+ #Minteger, #Msymbol, #Mtext ¤Î¤¤¤º¤ì¤«¡¢ÃͤÏÂбþ¤¹¤ë·¿¤Î¤â¤Î¤Ç¤¢¤ë¡£
+ ¤³¤ÎÃͤ¬ÊÑ¿ô $VARIABLE ¤Ë³ä¤êÅö¤Æ¤é¤ì¤ë¡£
-MInputContext *
-minput_create_ic (MInputMethod *im, void *arg)
-{
- MInputContext *ic;
+ $VALUE ¤¬ ¶õ¥ê¥¹¥È¤Ç¤¢¤ì¤Ð¡¢ÊÑ¿ô¤ÎÀßÄê¤È¥«¥¹¥¿¥Þ¥¤¥º¤¬¥¥ã¥ó¥»¥ë¤µ
+ ¤ì¡¢¥Ç¥Õ¥©¥ë¥ÈÃͤ¬ÊÑ¿ô $VARIABLE ¤Ë³ä¤êÅö¤Æ¤é¤ì¤ë¡£
- MDEBUG_PRINT2 (" [IM] creating context (%s %s) ... ",
- msymbol_name (im->name), msymbol_name (im->language));
- MSTRUCT_CALLOC (ic, MERROR_IM);
- ic->im = im;
- ic->arg = arg;
- ic->preedit = mtext ();
- ic->candidate_list = NULL;
- ic->produced = mtext ();
- ic->spot.x = ic->spot.y = 0;
- ic->active = 1;
- ic->plist = mplist ();
- if ((*im->driver.create_ic) (ic) < 0)
- {
- MDEBUG_PRINT (" failed\n");
- M17N_OBJECT_UNREF (ic->preedit);
- M17N_OBJECT_UNREF (ic->produced);
- M17N_OBJECT_UNREF (ic->plist);
- free (ic);
- return NULL;
- };
+ $VALUE ¤¬ NULL ¤Ç¤¢¤ì¤Ð¡¢ÊÑ¿ô¤ÎÀßÄê¤Ï¥¥ã¥ó¥»¥ë¤µ¤ì¡¢¸µ¤ÎÃ͡ʥ桼¥¶
+ Ëè¤Î¥«¥¹¥¿¥Þ¥¤¥º¥Õ¥¡¥¤¥ëÃæ¤ÎÃÍ¡¢¤Þ¤¿¤Ï¥Ç¥Õ¥©¥ë¥È¤ÎÃ͡ˤ¬³ä¤êÅö¤Æ¤é¤ì¤ë¡£
- if (im->driver.callback_list)
- {
- minput__callback (ic, Minput_preedit_start);
- minput__callback (ic, Minput_status_start);
- minput__callback (ic, Minput_status_draw);
- }
+ ¸å¤Î¤Õ¤¿¤Ä¤Î¾ì¹ç¤Ë¤Ï¡¢$VARIABLE ¤Ï #Mnil ¤ò¤È¤ë¤³¤È¤¬¤Ç¤¡¢»ØÄꤵ¤ì
+ ¤¿ÆþÎϥ᥽¥Ã¥É¤ÎÁ´¤Æ¤ÎÊÑ¿ôÀßÄê¤Î¥¥ã¥ó¥»¥ë¤ò°ÕÌ£¤¹¤ë¡£
- MDEBUG_PRINT (" ok\n");
- return ic;
-}
+ $NAME ¤¬ #Mnil ¤Ê¤é¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¸Ä¡¹¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¤Ê¤¯¥°¥í¡¼¥Ð
+ ¥ë¤ÊÊÑ¿ô¤ÎÃͤòÀßÄꤹ¤ë¡£
-/*=*/
+ ¤³¤ì¤é¤ÎÀßÄê¤Ï¡¢¸½¹Ô¤Î¥»¥Ã¥·¥ç¥óÃæ¤ÇÆþÎϥ᥽¥Ã¥É¤¬¥ª¡¼¥×¥ó¡Ê¤Þ¤¿¤Ï
+ ºÆ¥ª¡¼¥×¥ó¡Ë¤µ¤ì¤¿»þÅÀ¤Ç͸ú¤Ë¤Ê¤ë¡£¾Íè¤Î¥»¥Ã¥·¥ç¥óÃæ¤Ç¤â͸ú¤Ë¤¹
+ ¤ë¤¿¤á¤Ë¤Ï¡¢´Ø¿ô minput_save_config () ¤òÍѤ¤¤Æ¥æ¡¼¥¶Ëè¤Î¥«¥¹¥¿¥Þ¥¤
+ ¥º¥Õ¥¡¥¤¥ë¤ËÊݸ¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
-/***en
- @brief Destroy an input context.
+ @return
- The minput_destroy_ic () function destroys the input context $IC,
- which must have been created by minput_create_ic (). It calls
- callback functions corresponding to #Minput_preedit_done,
- #Minput_status_done, and #Minput_candidates_done in this order. */
+ ¤³¤Î´Ø¿ô¤Ï¡¢½èÍý¤¬À®¸ù¤¹¤ì¤Ð 0 ¤ò¡¢¼ºÇÔ¤¹¤ì¤Ð -1 ¤òÊÖ¤¹¡£¼ºÇԤȤϰʲ¼¤Î¾ì¹ç¤Ç¤¢¤ë¡£
+
+ - $VALUE¤¬Í¸ú¤Ê·Á¼°¤Ç¤Ê¤¤¡£·¿¤¬ÄêµÁ¤Ë¹ç¤ï¤Ê¤¤¡¢¤Þ¤¿¤ÏÃͤ¬Èϰϳ°¤Ç¤¢¤ë¡£
+
- $VARIABLE ¤¬»ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤ÇÍøÍѤǤ¤Ê¤¤¡£
+
- $LANGUAGE ¤È $NAME ¤Ç»ØÄꤵ¤ì¤ëÆþÎϥ᥽¥Ã¥É¤¬Â¸ºß¤·¤Ê¤¤¡£
+
-/***ja
- @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÇ˲õ¤¹¤ë.
+ @seealso
+ minput_get_commands (), minput_save_config ().
+*/
+int
+minput_config_variable (MSymbol language, MSymbol name, MSymbol variable,
+ MPlist *value)
+{
+ MInputMethodInfo *im_info, *config;
+ MPlist *plist;
- ´Ø¿ô minput_destroy_ic () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤òÇ˲õ¤¹¤ë¡£
- ¤³¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ï minput_create_ic ()
- ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£¤³¤Î´Ø¿ô¤Ï
- #Minput_preedit_done, #Minput_status_done, #Minput_candidates_done
- ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¤³¤Î½ç¤Ë¸Æ¤Ö¡£
- */
+ MINPUT__INIT ();
-void
-minput_destroy_ic (MInputContext *ic)
-{
- MDEBUG_PRINT2 (" [IM] destroying context (%s %s) ... ",
- msymbol_name (ic->im->name), msymbol_name (ic->im->language));
- if (ic->im->driver.callback_list)
+ im_info = get_im_info (language, name, Mnil, Mvariable);
+ if (! im_info)
+ MERROR (MERROR_IM, -1);
+ if (variable == Mnil ? (value && ! MPLIST_TAIL_P (value))
+ : (! im_info->vars
+ || ! (plist = mplist__assq (im_info->configured_vars, variable))))
+ MERROR (MERROR_IM, -1);
+
+ if (value && ! MPLIST_TAIL_P (value))
{
- minput__callback (ic, Minput_preedit_done);
- minput__callback (ic, Minput_status_done);
- minput__callback (ic, Minput_candidates_done);
+ plist = MPLIST_PLIST (plist);
+ plist = MPLIST_NEXT (plist); /* (DESC STATUS VALUE VALIDS ...) */
+ plist = MPLIST_NEXT (plist); /* (STATUS VALUE VALIDS ...) */
+ plist = MPLIST_NEXT (plist); /* (VALUE VALIDS ...) */
+ if (MPLIST_KEY (plist) != Mt
+ && ! check_variable_value (value, plist))
+ MERROR (MERROR_IM, -1);
}
- (*ic->im->driver.destroy_ic) (ic);
- M17N_OBJECT_UNREF (ic->preedit);
- M17N_OBJECT_UNREF (ic->produced);
- M17N_OBJECT_UNREF (ic->plist);
- MDEBUG_PRINT (" done\n");
- free (ic);
-}
-
-/*=*/
-
-/***en
- @brief Filter an input key.
- The minput_filter () function filters input key $KEY according to
- input context $IC, and calls callback functions corresponding to
- #Minput_preedit_draw, #Minput_status_draw, and
- #Minput_candidates_draw if the preedit text, the status, and the
- current candidate are changed respectively.
+ config = get_config_info (im_info);
+ if (! config)
+ {
+ if (! im_config_list)
+ im_config_list = mplist ();
+ config = new_im_info (NULL, language, name, Mnil, im_config_list);
+ config->cmds = mplist ();
+ config->vars = mplist ();
+ }
- To make the input method commit the current preedit text (if any)
- and shift to the initial state, call this function with #Mnil as
- $KEY.
+ if (! value && MPLIST_TAIL_P (config->vars))
+ /* Nothing to do. */
+ return 0;
- To inform the input method about the focus-out event, call this
- function with #Minput_focus_out as $KEY.
+ if (variable == Mnil)
+ {
+ if (! value)
+ {
+ /* Cancel the configuration. */
+ if (MPLIST_TAIL_P (config->vars))
+ return 0;
+ mplist_set (config->vars, Mnil, NULL);
+ }
+ else
+ {
+ /* Cancel the customization. */
+ MInputMethodInfo *custom = get_custom_info (im_info);
+
+ if (MPLIST_TAIL_P (config->vars)
+ && (! custom || ! custom->vars || MPLIST_TAIL_P (custom->vars)))
+ /* Nothing to do. */
+ return 0;
+ mplist_set (config->vars, Mnil, NULL);
+ MPLIST_DO (plist, custom->vars)
+ {
+ variable = MPLIST_SYMBOL (MPLIST_PLIST (plist));
+ plist = mplist ();
+ mplist_add (plist, Msymbol, variable);
+ mplist_push (config->vars, Mplist, plist);
+ M17N_OBJECT_UNREF (plist);
+ }
+ }
+ }
+ else
+ {
+ plist = mplist__assq (config->vars, variable);
+ if (! value)
+ {
+ /* Cancel the configuration. */
+ if (! plist)
+ return 0;
+ mplist__pop_unref (plist);
+ }
+ else if (MPLIST_TAIL_P (value))
+ {
+ /* Cancel the customization. */
+ MInputMethodInfo *custom = get_custom_info (im_info);
+ int no_custom = (! custom || ! custom->vars
+ || ! mplist__assq (custom->vars, variable));
+ if (! plist)
+ {
+ if (no_custom)
+ return 0;
+ plist = mplist ();
+ mplist_add (config->vars, Mplist, plist);
+ M17N_OBJECT_UNREF (plist);
+ plist = mplist_add (plist, Msymbol, variable);
+ }
+ else
+ {
+ if (no_custom)
+ mplist__pop_unref (plist);
+ else
+ {
+ plist = MPLIST_PLIST (plist); /* (NAME nil VALUE) */
+ plist = MPLIST_NEXT (plist); /* ([nil VALUE]) */
+ mplist_set (plist, Mnil ,NULL);
+ }
+ }
+ }
+ else
+ {
+ if (plist)
+ {
+ plist = MPLIST_NEXT (MPLIST_PLIST (plist));
+ if (! MPLIST_TAIL_P (plist))
+ mplist_set (plist, Mnil, NULL);
+ }
+ else
+ {
+ plist = mplist ();
+ mplist_add (config->vars, Mplist, plist);
+ M17N_OBJECT_UNREF (plist);
+ plist = mplist_add (plist, Msymbol, variable);
+ plist = MPLIST_NEXT (plist);
+ }
+ mplist_add (plist, MPLIST_KEY (value), MPLIST_VAL (value));
+ }
+ }
+ config_all_variables (im_info);
+ im_info->tick = time (NULL);
+ return 0;
+}
- To inform the input method about the focus-in event, call this
- function with #Minput_focus_in as $KEY.
+/*=*/
- To inform the input method about the focus-move event (i.e. input
- spot change within the same input context), call this function
- with #Minput_focus_move as $KEY.
+/***en
+ @brief Get the name of per-user customization file.
+
+ The minput_config_file () function returns the absolute path name
+ of per-user customization file into which minput_save_config ()
+ save configurations. It is usually @c "config.mic" under the
+ directory @c ".m17n.d" of user's home directory. It is not assured
+ that the file of the returned name exists nor is
+ readable/writable. If minput_save_config () fails and returns -1,
+ an application program might check the file, make it
+ writable (if possible), and try minput_save_config () again.
@return
- If $KEY is filtered out, this function returns 1. In that case,
- the caller should discard the key. Otherwise, it returns 0, and
- the caller should handle the key, for instance, by calling the
- function minput_lookup () with the same key. */
+ This function returns a string. As the string is kept in the
+ library, the caller must not modify nor free it.
+
+ @seealso
+ minput_save_config ()
+*/
/***ja
- @brief ÆþÎÏ¥¡¼¤ò¥Õ¥£¥ë¥¿¤¹¤ë.
+ @brief ¥æ¡¼¥¶Ëè¤Î¥«¥¹¥¿¥Þ¥¤¥º¥Õ¥¡¥¤¥ë¤Î̾Á°¤òÆÀ¤ë.
+
+ ´Ø¿ô minput_config_file () ¤Ï¡¢´Ø¿ô minput_save_config () ¤¬ÀßÄê¤ò
+ Êݸ¤¹¤ë¥æ¡¼¥¶Ëè¤Î¥«¥¹¥¿¥Þ¥¤¥º¥Õ¥¡¥¤¥ë¤Ø¤ÎÀäÂХѥ¹Ì¾¤òÊÖ¤¹¡£Ä̾ï¤Ï¡¢¥æ¡¼¥¶
+ ¤Î¥Û¡¼¥à¥Ç¥£¥ì¥¯¥È¥ê¤Î²¼¤Î¥Ç¥£¥ì¥¯¥È¥ê @c ".m17n.d" ¤Ë¤¢¤ë@c
+ "config.mic" ¤È¤Ê¤ë¡£ÊÖ¤µ¤ì¤¿Ì¾Á°¤Î¥Õ¥¡¥¤¥ë¤¬Â¸ºß¤¹¤ë¤«¡¢Æɤ߽ñ¤¤Ç
+ ¤¤ë¤«¤ÏÊݾڤµ¤ì¤Ê¤¤¡£´Ø¿ôminput_save_config () ¤¬¼ºÇÔ¤·¤Æ -1 ¤òÊÖ
+ ¤·¤¿¾ì¹ç¤Ë¤Ï¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ï¥Õ¥¡¥¤¥ë¤Î¸ºß¤ò³Îǧ¤·¡¢
+ ¡Ê¤Ç¤¤ì¤Ð¡Ë½ñ¤¹þ¤ß²Äǽ¤Ë¤·ºÆÅÙminput_save_config () ¤ò»î¤¹¤³¤È¤¬
+ ¤Ç¤¤ë¡£
- ´Ø¿ô minput_filter () ¤ÏÆþÎÏ¥¡¼ $KEY ¤òÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC
- ¤Ë±þ¤¸¤Æ¥Õ¥£¥ë¥¿¤·¡¢preedit ¥Æ¥¥¹¥È¡¢¥¹¥Æ¡¼¥¿¥¹¡¢¸½»þÅÀ¤Ç¤Î¸õÊ䤬ÊѲ½¤·¤¿»þÅÀ¤Ç¡¢¤½¤ì¤¾¤ì
- #Minput_preedit_draw, #Minput_status_draw,
- #Minput_candidates_draw ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¸Æ¤Ö¡£
+ @return
- @return
- $KEY ¤¬¥Õ¥£¥ë¥¿¤µ¤ì¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 1 ¤òÊÖ¤¹¡£
- ¤³¤Î¾ì¹ç¸Æ¤Ó½Ð¤·Â¦¤Ï¤³¤Î¥¡¼¤ò¼Î¤Æ¤ë¤Ù¤¤Ç¤¢¤ë¡£
- ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0 ¤òÊÖ¤·¡¢¸Æ¤Ó½Ð¤·Â¦¤Ï¡¢¤¿¤È¤¨¤ÐƱ¤¸¥¡¼¤Ç´Ø¿ô minput_lookup ()
- ¤ò¸Æ¤Ö¤Ê¤É¤·¤Æ¡¢¤³¤Î¥¡¼¤ò½èÍý¤¹¤ë¡£
+ ¤³¤Î´Ø¿ô¤Ïʸ»úÎó¤òÊÖ¤¹¡£Ê¸»úÎó¤Ï¥é¥¤¥Ö¥é¥ê¤¬´ÉÍý¤·¤Æ¤¤¤ë¤Î¤Ç¡¢¸Æ½Ð
+ ¦¤¬½¤Àµ¤·¤¿¤ê²òÊü¤·¤¿¤ê¤¹¤ë¤³¤È¤Ï¤Ç¤¤Ê¤¤¡£
- @latexonly \IPAlabel{minput_filter} @endlatexonly
+ @seealso
+ minput_save_config ()
*/
-int
-minput_filter (MInputContext *ic, MSymbol key, void *arg)
+char *
+minput_config_file ()
{
- int ret;
-
- if (! ic
- || ! ic->active)
- return 0;
- ret = (*ic->im->driver.filter) (ic, key, arg);
+ MINPUT__INIT ();
- if (ic->im->driver.callback_list)
- {
- if (ic->preedit_changed)
- minput__callback (ic, Minput_preedit_draw);
- if (ic->status_changed)
- minput__callback (ic, Minput_status_draw);
- if (ic->candidates_changed)
- minput__callback (ic, Minput_candidates_draw);
- }
-
- return ret;
+ return mdatabase__file (im_custom_mdb);
}
/*=*/
/***en
- @brief Look up a text produced in the input context.
-
- The minput_lookup () function looks up a text in the input context
- $IC. $KEY must be identical to the one that was used in the previous call of
- minput_filter ().
-
- If a text was produced by the input method, it is concatenated
- to M-text $MT.
+ @brief Save configurations in per-user customization file.
- This function calls #MInputDriver::lookup .
+ The minput_save_config () function saves the configurations done
+ so far in the current session into the per-user customization
+ file.
@return
- If $KEY was correctly handled by the input method, this function
- returns 0. Otherwise, it returns -1, even though some text
- might be produced in $MT. */
-/***ja
- @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥ÈÃæ¤Î¥Æ¥¥¹¥È¤òõ¤¹.
+ If the operation was successful, 1 is returned. If the per-user
+ customization file is currently locked, 0 is returned. In that
+ case, the caller may wait for a while and try again. If the
+ configuration file is not writable, -1 is returned. In that case,
+ the caller may check the name of the file by calling
+ minput_config_file (), make it writable if possible, and try
+ again.
- ´Ø¿ô minput_lookup () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC Ãæ¤Î¥Æ¥¥¹¥È¤òõ¤¹¡£
- $KEY ¤Ï´Ø¿ô minput_filter () ¤Ø¤ÎľÁ°¤Î¸Æ¤Ó½Ð¤·¤ËÍѤ¤¤é¤ì¤¿¤â¤Î¤ÈƱ¤¸¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
+ @seealso
+ minput_config_file () */
+/***ja
+ @brief ÀßÄê¤ò¥æ¡¼¥¶Ëè¤Î¥«¥¹¥¿¥Þ¥¤¥º¥Õ¥¡¥¤¥ë¤ËÊݸ¤¹¤ë.
- ¥Æ¥¥¹¥È¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆÀ¸À®¤µ¤ì¤Æ¤¤¤ì¤Ð¡¢¥Æ¥¥¹¥È¤Ï M-text
- $MT ¤ËÏ¢·ë¤µ¤ì¤ë¡£
+ ´Ø¿ô minput_save_config () ¤Ï¸½¹Ô¤Î¥»¥Ã¥·¥ç¥ó¤Ç¤³¤ì¤Þ¤Ç¤Ë¹Ô¤Ã¤¿ÀßÄê
+ ¤ò¥æ¡¼¥¶Ëè¤Î¥«¥¹¥¿¥Þ¥¤¥º¥Õ¥¡¥¤¥ë¤ËÊݸ¤¹¤ë¡£
- ¤³¤Î´Ø¿ô¤Ï¡¢#MInputDriver::lookup ¤ò¸Æ¤Ö¡£
+ @return
- @return
- $KEY ¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆŬÀڤ˽èÍý¤Ç¤¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 0 ¤òÊÖ¤¹¡£
- ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£
- ¤³¤Î¾ì¹ç¤Ç¤â $MT ¤Ë²¿¤é¤«¤Î¥Æ¥¥¹¥È¤¬À¸À®¤µ¤ì¤Æ¤¤¤ë¤³¤È¤¬¤¢¤ë¡£
+ À®¸ù¤¹¤ì¤Ð 1 ¤òÊÖ¤¹¡£¥æ¡¼¥¶Ëè¤Î¥«¥¹¥¿¥Þ¥¤¥º¥Õ¥¡¥¤¥ë¤¬¥í¥Ã¥¯¤µ¤ì¤Æ¤¤
+ ¤ì¤Ð 0 ¤òÊÖ¤¹¡£¤³¤Î¾ì¹ç¡¢¸Æ½Ð¦¤Ï¤·¤Ð¤é¤¯ÂԤäƺƻî¹Ô¤Ç¤¤ë¡£ÀßÄê¥Õ¥¡
+ ¥¤¥ë¤¬½ñ¤¹þ¤ßÉԲĤξì¹ç¡¢-1 ¤òÊÖ¤¹¡£¤³¤Î¾ì¹ç¡¢minput_config_file
+ () ¤ò¸Æ¤ó¤Ç¥Õ¥¡¥¤¥ë̾¤ò¥Á¥§¥Ã¥¯¤·¡¢¤Ç¤¤ì¤Ð½ñ¤¹þ¤ß²Äǽ¤Ë¤·¡¢ºÆ»î¹Ô
+ ¤Ç¤¤ë¡£
- @latexonly \IPAlabel{minput_lookup} @endlatexonly */
+ @seealso
+ minput_config_file () */
int
-minput_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
+minput_save_config (void)
{
- return (ic ? (*ic->im->driver.lookup) (ic, key, arg, mt) : -1);
+ MPlist *data, *tail, *plist, *p, *elt;
+ int ret;
+
+ MINPUT__INIT ();
+ ret = mdatabase__lock (im_custom_mdb);
+ if (ret <= 0)
+ return ret;
+ if (! im_config_list)
+ return 1;
+ update_custom_info ();
+ if (! im_custom_list)
+ im_custom_list = mplist ();
+
+ /* At first, reflect configuration in customization. */
+ MPLIST_DO (plist, im_config_list)
+ {
+ MPlist *pl = MPLIST_PLIST (plist);
+ MSymbol language, name, extra, command, variable;
+ MInputMethodInfo *custom, *config;
+
+ language = MPLIST_SYMBOL (pl);
+ pl = MPLIST_NEXT (pl);
+ name = MPLIST_SYMBOL (pl);
+ pl = MPLIST_NEXT (pl);
+ extra = MPLIST_SYMBOL (pl);
+ pl = MPLIST_NEXT (pl);
+ config = MPLIST_VAL (pl);
+ custom = get_custom_info (config);
+ if (! custom)
+ custom = new_im_info (NULL, language, name, extra, im_custom_list);
+ if (config->cmds)
+ MPLIST_DO (pl, config->cmds)
+ {
+ elt = MPLIST_PLIST (pl);
+ command = MPLIST_SYMBOL (elt);
+ if (custom->cmds)
+ p = mplist__assq (custom->cmds, command);
+ else
+ custom->cmds = mplist (), p = NULL;
+ elt = MPLIST_NEXT (elt);
+ if (p)
+ {
+ p = MPLIST_NEXT (MPLIST_NEXT (MPLIST_PLIST (p)));
+ mplist_set (p, Mnil, NULL);
+ }
+ else
+ {
+ p = mplist ();
+ mplist_add (custom->cmds, Mplist, p);
+ M17N_OBJECT_UNREF (p);
+ mplist_add (p, Msymbol, command);
+ p = mplist_add (p, Msymbol, Mnil);
+ p = MPLIST_NEXT (p);
+ }
+ mplist__conc (p, elt);
+ }
+ if (config->vars)
+ MPLIST_DO (pl, config->vars)
+ {
+ elt = MPLIST_PLIST (pl);
+ variable = MPLIST_SYMBOL (elt);
+ if (custom->vars)
+ p = mplist__assq (custom->vars, variable);
+ else
+ custom->vars = mplist (), p = NULL;
+ elt = MPLIST_NEXT (elt);
+ if (p)
+ {
+ p = MPLIST_NEXT (MPLIST_NEXT (MPLIST_PLIST (p)));
+ mplist_set (p, Mnil, NULL);
+ }
+ else
+ {
+ p = mplist ();
+ mplist_add (custom->vars, Mplist, p);
+ M17N_OBJECT_UNREF (p);
+ mplist_add (p, Msymbol, variable);
+ p = mplist_add (p, Msymbol, Mnil);
+ p = MPLIST_NEXT (p);
+ }
+ mplist__conc (p, elt);
+ }
+ }
+ free_im_list (im_config_list);
+ im_config_list = NULL;
+
+ /* Next, reflect customization to the actual plist to be written. */
+ data = tail = mplist ();
+ MPLIST_DO (plist, im_custom_list)
+ {
+ MPlist *pl = MPLIST_PLIST (plist);
+ MSymbol language, name, extra;
+ MInputMethodInfo *custom, *im_info;
+
+ language = MPLIST_SYMBOL (pl);
+ pl = MPLIST_NEXT (pl);
+ name = MPLIST_SYMBOL (pl);
+ pl = MPLIST_NEXT (pl);
+ extra = MPLIST_SYMBOL (pl);
+ pl = MPLIST_NEXT (pl);
+ custom = MPLIST_VAL (pl);
+ if ((! custom->cmds || MPLIST_TAIL_P (custom->cmds))
+ && (! custom->vars || MPLIST_TAIL_P (custom->vars)))
+ continue;
+ im_info = lookup_im_info (im_info_list, language, name, extra);
+ if (im_info)
+ {
+ if (im_info->cmds)
+ config_all_commands (im_info);
+ if (im_info->vars)
+ config_all_variables (im_info);
+ }
+
+ elt = NULL;
+ if (custom->cmds && ! MPLIST_TAIL_P (custom->cmds))
+ {
+ MPLIST_DO (p, custom->cmds)
+ if (! MPLIST_TAIL_P (MPLIST_NEXT (MPLIST_PLIST (p))))
+ break;
+ if (! MPLIST_TAIL_P (p))
+ {
+ elt = mplist ();
+ pl = mplist ();
+ mplist_add (elt, Mplist, pl);
+ M17N_OBJECT_UNREF (pl);
+ pl = mplist_add (pl, Msymbol, Mcommand);
+ MPLIST_DO (p, custom->cmds)
+ if (! MPLIST_TAIL_P (MPLIST_NEXT (MPLIST_PLIST (p))))
+ pl = mplist_add (pl, Mplist, MPLIST_PLIST (p));
+ }
+ }
+ if (custom->vars && ! MPLIST_TAIL_P (custom->vars))
+ {
+ MPLIST_DO (p, custom->vars)
+ if (! MPLIST_TAIL_P (MPLIST_NEXT (MPLIST_PLIST (p))))
+ break;
+ if (! MPLIST_TAIL_P (p))
+ {
+ if (! elt)
+ elt = mplist ();
+ pl = mplist ();
+ mplist_add (elt, Mplist, pl);
+ M17N_OBJECT_UNREF (pl);
+ pl = mplist_add (pl, Msymbol, Mvariable);
+ MPLIST_DO (p, custom->vars)
+ if (! MPLIST_TAIL_P (MPLIST_NEXT (MPLIST_PLIST (p))))
+ pl = mplist_add (pl, Mplist, MPLIST_PLIST (p));
+ }
+ }
+ if (elt)
+ {
+ pl = mplist ();
+ mplist_push (elt, Mplist, pl);
+ M17N_OBJECT_UNREF (pl);
+ pl = mplist_add (pl, Msymbol, Minput_method);
+ pl = mplist_add (pl, Msymbol, language);
+ pl = mplist_add (pl, Msymbol, name);
+ if (extra != Mnil)
+ pl = mplist_add (pl, Msymbol, extra);
+ tail = mplist_add (tail, Mplist, elt);
+ M17N_OBJECT_UNREF (elt);
+ }
+ }
+
+ mplist_push (data, Mstring, ";; -*- mode:lisp; coding:utf-8 -*-");
+ ret = mdatabase__save (im_custom_mdb, data);
+ mdatabase__unlock (im_custom_mdb);
+ M17N_OBJECT_UNREF (data);
+ return (ret < 0 ? -1 : 1);
}
+
+/*=*/
+/*** @} */
/*=*/
+/***en
+ @name Obsolete functions
+*/
+/***ja
+ @name Obsolete ¤Ê´Ø¿ô
+*/
+/*** @{ */
+/*=*/
/***en
- @brief Set the spot of the input context.
+ @brief Get a list of variables of an input method (obsolete).
- The minput_set_spot () function sets the spot of input context $IC
- to coordinate ($X, $Y ) with the height specified by $ASCENT and $DESCENT .
- The semantics of these values depends on the input method driver.
+ This function is obsolete. Use minput_get_variable () instead.
- For instance, a driver designed to work in a CUI environment may
- use $X and $Y as the column- and row numbers, and may ignore $ASCENT and
- $DESCENT . A driver designed to work in a window system may
- interpret $X and $Y as the pixel offsets relative to the origin of the
- client window, and may interpret $ASCENT and $DESCENT as the ascent- and
- descent pixels of the line at ($X . $Y ).
+ The minput_get_variables () function returns a plist (#MPlist) of
+ variables used to control the behavior of the input method
+ specified by $LANGUAGE and $NAME. The plist is @e well-formed
+ (#m17nPlist) of the following format:
- $FONTSIZE specifies the fontsize of preedit text in 1/10 point.
+@verbatim
+ (VARNAME (DOC-MTEXT DEFAULT-VALUE [ VALUE ... ] )
+ VARNAME (DOC-MTEXT DEFAULT-VALUE [ VALUE ... ] )
+ ...)
+@endverbatim
- $MT and $POS are the M-text and the character position at the spot.
- $MT may be @c NULL, in which case, the input method cannot get
- information about the text around the spot. */
+ @c VARNAME is a symbol representing the variable name.
-/***ja
- @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Î¥¹¥Ý¥Ã¥È¤òÀßÄꤹ¤ë.
+ @c DOC-MTEXT is an M-text describing the variable.
- ´Ø¿ô minput_set_spot () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤Î¥¹¥Ý¥Ã¥È¤ò¡¢ºÂɸ ($X, $Y )
- ¤Î°ÌÃÖ¤Ë ¡¢¹â¤µ $ASCENT¡¢ $DESCENT
- ¤ÇÀßÄꤹ¤ë¡£ ¤³¤ì¤é¤ÎÃͤΰÕÌ£¤ÏÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë¡£
+ @c DEFAULT-VALUE is the default value of the variable. It is a
+ symbol, integer, or M-text.
- ¤¿¤È¤¨¤Ð CUI ´Ä¶¤ÇÆ°ºî¤¹¤ë¥É¥é¥¤¥Ð¤Ï $X ¤È $Y
- ¤ò¤½¤ì¤¾¤ìÎó¤È¹Ô¤ÎÈÖ¹æ¤È¤·¤ÆÍѤ¤¡¢$ASCENT ¤È $DESCENT
- ¤ò̵»ë¤¹¤ë¤«¤â¤·¤ì¤Ê¤¤¡£ ¤Þ¤¿¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥àÍѤΥɥ饤¥Ð¤Ï
- $X ¤È $Y ¤ò¥¯¥é¥¤¥¢¥ó¥È¥¦¥£¥ó¥É¥¦¤Î¸¶ÅÀ¤«¤é¤Î¥ª¥Õ¥»¥Ã¥È¤ò¥Ô¥¯¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¤¡¢
- $ASCENT ¤È $DESCENT ¤ò ($X . $Y )
- ¤ÎÎó¤Î¥¢¥»¥ó¥È¤È¥Ç¥£¥»¥ó¥È¤ò¥Ô¥¯¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¦¤«¤â¤·¤ì¤Ê¤¤¡£
+ @c VALUEs (if any) specifies the possible values of the variable.
+ If @c DEFAULT-VALUE is an integer, @c VALUE may be a plist (@c FROM
+ @c TO), where @c FROM and @c TO specifies a range of possible
+ values.
- $FONTSIZE ¤Ë¤Ï preedit ¥Æ¥¥¹¥È¤Î¥Õ¥©¥ó¥È¥µ¥¤¥º¤ò 1/10 ¥Ý¥¤¥ó¥Èñ°Ì¤Ç»ØÄꤹ¤ë¡£
+ For instance, suppose an input method has the variables:
- $MT ¤È $POS ¤Ï¤½¤Î¥¹¥Ý¥Ã¥È¤Î M-text ¤Èʸ»ú°ÌÃ֤Ǥ¢¤ë¡£$MT ¤Ï @c
- NULL ¤Ç¤â¤è¤¯¡¢¤½¤Î¾ì¹ç¤Ë¤ÏÆþÎϥ᥽¥Ã¥É¤Ï¥¹¥Ý¥Ã¥È¼þÊդΥƥ¥¹¥È¤Ë´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë¤³¤È¤¬¤Ç¤¤Ê¤¤¡£
- */
+ @li name:intvar, description:"value is an integer",
+ initial value:0, value-range:0..3,10,20
-void
-minput_set_spot (MInputContext *ic, int x, int y,
- int ascent, int descent, int fontsize,
- MText *mt, int pos)
-{
- ic->spot.x = x;
- ic->spot.y = y;
- ic->spot.ascent = ascent;
- ic->spot.descent = descent;
- ic->spot.fontsize = fontsize;
- ic->spot.mt = mt;
- ic->spot.pos = pos;
- if (ic->im->driver.callback_list)
- minput__callback (ic, Minput_set_spot);
-}
-/*=*/
+ @li name:symvar, description:"value is a symbol",
+ initial value:nil, value-range:a, b, c, nil
-/***en
- @brief Toggle input method.
+ @li name:txtvar, description:"value is an M-text",
+ initial value:empty text, no value-range (i.e. any text)
- The minput_toggle () function toggles the input method associated
- with input context $IC. */
+ Then, the returned plist is as follows.
+
+@verbatim
+ (intvar ("value is an integer" 0 (0 3) 10 20)
+ symvar ("value is a symbol" nil a b c nil)
+ txtvar ("value is an M-text" ""))
+@endverbatim
+
+ @return
+ If the input method uses any variables, a pointer to #MPlist is
+ returned. As the plist is kept in the library, the caller must not
+ modify nor free it. If the input method does not use any
+ variable, @c NULL is returned. */
/***ja
- @brief ÆþÎϥ᥽¥Ã¥É¤òÀÚÂؤ¨¤ë.
+ @brief ÆþÎϥ᥽¥Ã¥É¤ÎÊÑ¿ô¥ê¥¹¥È¤òÆÀ¤ë.
- ´Ø¿ô minput_toggle () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC
- ¤ËÂбþÉÕ¤±¤é¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ò¥È¥°¥ë¤¹¤ë¡£
- */
+ ´Ø¿ô minput_get_variables () ¤Ï¡¢$LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ»ØÄꤵ
+ ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤Î¿¶¤ëÉñ¤¤¤òÀ©¸æ¤¹¤ëÊÑ¿ô¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È
+ (#MPlist) ¤òÊÖ¤¹¡£¤³¤Î¥ê¥¹¥È¤Ï @e well-formed ¤Ç¤¢¤ê(#m17nPlist) °Ê
+ ²¼¤Î·Á¼°¤Ç¤¢¤ë¡£
-void
-minput_toggle (MInputContext *ic)
-{
- if (ic->im->driver.callback_list)
- minput__callback (ic, Minput_toggle);
- ic->active = ! ic->active;
-}
+@verbatim
+ (VARNAME (DOC-MTEXT DEFAULT-VALUE [ VALUE ... ] )
+ VARNAME (DOC-MTEXT DEFAULT-VALUE [ VALUE ... ] )
+ ...)
+@endverbatim
-/*=*/
+ @c VARNAME ¤ÏÊÑ¿ô¤Î̾Á°¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
-/***en
- @brief Reset an input context.
+ @c DOC-MTEXT ¤ÏÊÑ¿ô¤òÀâÌÀ¤¹¤ë M-text ¤Ç¤¢¤ë¡£
- The minput_reset_ic () function resets input context $IC by
- calling a callback function corresponding to #Minput_reset. It
- resets the status of $IC to its initial one. As the
- current preedit text is deleted without commitment, if necessary,
- call minput_filter () with the arg @r key #Mnil to force the input
- method to commit the preedit in advance. */
+ @c DEFAULT-VALUE ¤ÏÊÑ¿ô¤Î¥Ç¥Õ¥©¥ë¥ÈÃͤǤ¢¤ê¡¢¥·¥ó¥Ü¥ë¡¢À°¿ô¤â¤·¤¯¤Ï
+ M-text ¤Ç¤¢¤ë¡£
-/***ja
- @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤ò¥ê¥»¥Ã¥È¤¹¤ë.
+ @c VALUE ¤Ï¡¢¤â¤·»ØÄꤵ¤ì¤Æ¤¤¤ì¤ÐÊÑ¿ô¤Î¼è¤êÆÀ¤ëÃͤò¼¨¤¹¡£¤â¤·
+ @c DEFAULT-VALUE ¤¬À°¿ô¤Ê¤é¡¢ @c VALUE ¤Ï (@c FROM @c TO) ¤È¤¤¤¦·Á
+ ¤Î¥ê¥¹¥È¤Ç¤âÎɤ¤¡£¤³¤Î¾ì¹ç @c FROM ¤È @c TO ¤Ï²Äǽ¤ÊÃͤÎÈϰϤò¼¨¤¹¡£
- ´Ø¿ô minput_reset_ic () ¤Ï #Minput_reset
- ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¸Æ¤Ö¤³¤È¤Ë¤è¤Ã¤ÆÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC
- ¤ò¥ê¥»¥Ã¥È¤¹¤ë¡£¥ê¥»¥Ã¥È¤È¤Ï¡¢¼ÂºÝ¤Ë¤ÏÆþÎϥ᥽¥Ã¥É¤ò½é´ü¾õÂ֤˰ܤ¹¤³¤È¤Ç¤¢¤ê¡¢¤·¤¿¤¬¤Ã¤Æ¡¢¤â¤·¸½ºßÆþÎÏÃæ¤Î¥Æ¥¥¹¥È¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤Ï¥³¥ß¥Ã¥È¤µ¤ì¤ë¡£
- ɬÍפʤé¤Ð¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ï minput_lookup ()
- ¤òÆɤó¤Ç¤½¤Î¥³¥ß¥Ã¥È¤µ¤ì¤¿¥Æ¥¥¹¥È¤ò¼è¤ê½Ð¤¹¤³¤È¤¬¤Ç¤¡¢¤½¤ÎºÝ¡¢
- minput_lookup () ¤Î°ú¿ô @c KEY ¤È @c ARG
- ¤Ï̵»ë¤µ¤ì¤ë¡£ */
-void
-minput_reset_ic (MInputContext *ic)
-{
- if (ic->im->driver.callback_list)
- minput__callback (ic, Minput_reset);
-}
+ Îã¤È¤·¤Æ¡¢¤¢¤ëÆþÎϥ᥽¥Ã¥É¤¬¼¡¤Î¤è¤¦¤ÊÊÑ¿ô¤ò»ý¤Ä¾ì¹ç¤ò¹Í¤¨¤è¤¦¡£
-/*=*/
+ @li name:intvar, ÀâÌÀ:"value is an integer",
+ ½é´üÃÍ:0, ÃͤÎÈÏ°Ï:0..3,10,20
-/***en
- @brief Get title and icon filename of an input method.
+ @li name:symvar, ÀâÌÀ:"value is a symbol",
+ ½é´üÃÍ:nil, ÃͤÎÈÏ°Ï:a, b, c, nil
- The minput_get_title_icon () function returns a plist containing a
- title and icon filename (if any) of the input method specifies by
- $LANGUAGE and $NAME.
+ @li name:txtvar, ÀâÌÀ:"value is an M-text",
+ ½é´üÃÍ:empty text, ÃͤÎÈϰϤʤ·(¤É¤ó¤Ê M-text ¤Ç¤â²Ä)
- The first element of the plist has key Mtext and the value is an
- M-text of the title for identifying the input method. The second
- element (if any) has key M-text and the value is an M-text of the
- icon image (absolute) filename for the same purpose.
+ ¤³¤Î¾ì¹ç¡¢ÊÖ¤µ¤ì¤ë¥ê¥¹¥È¤Ï°Ê²¼¤Î¤è¤¦¤Ë¤Ê¤ë¡£
- @return
- If there exists the specified input method and it defines an
- title, a plist is retured. Otherwise, NULL is returned. A caller
- must free the plist by m17n_object_unref ().
-*/
+@verbatim
+ (intvar ("value is an integer" 0 (0 3) 10 20)
+ symvar ("value is a symbol" nil a b c nil)
+ txtvar ("value is an M-text" ""))
+@endverbatim
+
+ @return
+ ÆþÎϥ᥽¥Ã¥É¤¬²¿¤é¤«¤ÎÊÑ¿ô¤ò»ÈÍѤ·¤Æ¤¤¤ì¤Ð #MPlist ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
+ ÊÖ¤µ¤ì¤ë¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ï¥é¥¤¥Ö¥é¥ê¤Ë¤è¤Ã¤Æ´ÉÍý¤µ¤ì¤Æ¤ª¤ê¡¢¸Æ¤Ó½Ð¤·Â¦¤ÇÊѹ¹¤·¤¿¤ê²òÊü¤·¤¿¤ê¤·¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
+ ÆþÎϥ᥽¥Ã¥É¤¬ÊÑ¿ô¤ò°ìÀÚ»ÈÍѤ·¤Æ¤Ê¤±¤ì¤Ð¡¢@c NULL ¤òÊÖ¤¹¡£ */
MPlist *
-minput_get_title_icon (MSymbol language, MSymbol name)
+minput_get_variables (MSymbol language, MSymbol name)
{
- MPlist *plist = load_partial_im_info (language, name, Mnil, Mtitle);
- MPlist *pl;
- char *file = NULL;
- MText *mt;
-
- if (! plist)
- return NULL;
- if (MPLIST_TAIL_P (plist))
- goto no_title;
- pl = MPLIST_PLIST (plist);
- pl = MPLIST_NEXT (pl);
- if (! MPLIST_MTEXT_P (pl))
- goto no_title;
- M17N_OBJECT_REF (pl);
- M17N_OBJECT_UNREF (plist);
- plist = pl;
- pl = MPLIST_NEXT (pl);
- if (MPLIST_MTEXT_P (pl))
- {
- if (mtext_nchars (MPLIST_MTEXT (pl)) > 0)
- {
- mt = MPLIST_MTEXT (pl);
- file = mdatabase__find_file ((char *) MTEXT_DATA (mt));
- }
- }
- else if (language != Mnil && name != Mnil)
+ MInputMethodInfo *im_info;
+ MPlist *vars;
- {
- char *buf = alloca (MSYMBOL_NAMELEN (language) + MSYMBOL_NAMELEN (name)
- + 12);
+ MINPUT__INIT ();
- sprintf (buf, "icons/%s-%s.png", (char *) MSYMBOL_NAME (language),
- (char *) MSYMBOL_NAME (name));
- file = mdatabase__find_file (buf);
- if (! file && language == Mt)
- {
- sprintf (buf, "icons/%s.png", (char *) MSYMBOL_NAME (name));
- file = mdatabase__find_file (buf);
- }
- }
+ im_info = get_im_info (language, name, Mnil, Mvariable);
+ if (! im_info || ! im_info->configured_vars)
+ return NULL;
- if (file)
+ M17N_OBJECT_UNREF (im_info->bc_vars);
+ im_info->bc_vars = mplist ();
+ MPLIST_DO (vars, im_info->configured_vars)
{
- mt = mtext__from_data (file, strlen (file), MTEXT_FORMAT_UTF_8, 1);
- free (file);
- mplist_set (pl, Mtext, mt);
- M17N_OBJECT_UNREF (mt);
+ MPlist *plist = MPLIST_PLIST (vars);
+ MPlist *elt = mplist ();
+
+ mplist_push (im_info->bc_vars, Mplist, elt);
+ mplist_add (elt, Msymbol, MPLIST_SYMBOL (plist));
+ elt = MPLIST_NEXT (elt);
+ mplist_set (elt, Mplist, mplist_copy (MPLIST_NEXT (plist)));
+ M17N_OBJECT_UNREF (elt);
}
- else
- mplist_set (pl, Mnil, NULL);
- return plist;
-
- no_title:
- M17N_OBJECT_UNREF (plist);
- return NULL;
+ return im_info->bc_vars;
}
/*=*/
/***en
- @brief Get description text of an input method.
+ @brief Set the initial value of an input method variable.
- The minput_get_description () function returns an M-text that
- describes the input method specified by $LANGUAGE and $NAME.
+ The minput_set_variable () function sets the initial value of
+ input method variable $VARIABLE to $VALUE for the input method
+ specified by $LANGUAGE and $NAME.
+
+ By default, the initial value is 0.
+
+ This setting gets effective in a newly opened input method.
@return
- If the specified input method has a description text, a pointer to
- #MText is returned. The caller has to free it by m17n_object_unref ().
- If the input method does not have a description text, @c NULL is
- returned. */
+ If the operation was successful, 0 is returned. Otherwise -1 is
+ returned, and #merror_code is set to #MERROR_IM. */
/***ja
- @brief ÆþÎϥ᥽¥Ã¥É¤ÎÀâÌÀ¥Æ¥¥¹¥È¤òÆÀ¤ë.
+ @brief ÆþÎϥ᥽¥Ã¥ÉÊÑ¿ô¤Î½é´üÃͤòÀßÄꤹ¤ë.
- ´Ø¿ô minput_get_description () ¤Ï¡¢$LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ»ØÄê
- ¤µ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤òÀâÌÀ¤¹¤ë M-text ¤òÊÖ¤¹¡£
+ ´Ø¿ô minput_set_variable () ¤Ï¡¢$LANGUAGE ¤È $NAME
+ ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ÎÆþÎϥ᥽¥Ã¥ÉÊÑ¿ô $VARIABLE
+ ¤Î½é´üÃͤò¡¢ $VALUE ¤ËÀßÄꤹ¤ë¡£
- @return »ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤¬ÀâÌÀ¤¹¤ë¥Æ¥¥¹¥È¤ò»ý¤Ã¤Æ¤¤¤ì¤Ð¡¢
- #MText ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¸Æ¤Ó½Ð¤·Â¦¤Ï¡¢¤½¤ì¤ò m17n_object_unref
- () ¤òÍѤ¤¤Æ²òÊü¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ÆþÎϥ᥽¥Ã¥É¤ËÀâÌÀ¥Æ¥¥¹¥È¤¬Ìµ¤±
- ¤ì¤Ð@c NULL ¤òÊÖ¤¹¡£ */
+ ¥Ç¥Õ¥©¥ë¥È¤Î½é´üÃÍ¤Ï 0 ¤Ç¤¢¤ë¡£
-MText *
-minput_get_description (MSymbol language, MSymbol name)
+ ¤³¤ÎÀßÄê¤Ï¡¢¿·¤·¤¯¥ª¡¼¥×¥ó¤µ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤«¤é͸ú¤È¤Ê¤ë¡£
+
+ @return
+ ½èÍý¤¬À®¸ù¤¹¤ì¤Ð 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤·¡¢
+ #merror_code ¤ò #MERROR_IM ¤ËÀßÄꤹ¤ë¡£ */
+
+int
+minput_set_variable (MSymbol language, MSymbol name,
+ MSymbol variable, void *value)
{
- MPlist *plist = load_partial_im_info (language, name, Mnil, M_description);
- MPlist *pl;
- MText *mt = NULL;
+ MPlist *plist, *pl;
+ MInputMethodInfo *im_info;
+ int ret;
- if (! plist)
- return NULL;
- if (MPLIST_TAIL_P (plist))
- {
- M17N_OBJECT_UNREF (plist);
- return NULL;
- }
- pl = MPLIST_PLIST (plist);
- pl = MPLIST_NEXT (pl);
- if (MPLIST_MTEXT_P (pl))
+ MINPUT__INIT ();
+
+ if (variable == Mnil)
+ MERROR (MERROR_IM, -1);
+ plist = minput_get_variable (language, name, variable);
+ plist = MPLIST_PLIST (plist);
+ plist = MPLIST_NEXT (plist);
+ pl = mplist ();
+ mplist_add (pl, MPLIST_KEY (plist), value);
+ ret = minput_config_variable (language, name, variable, pl);
+ M17N_OBJECT_UNREF (pl);
+ if (ret == 0)
{
- mt = MPLIST_MTEXT (pl);
- M17N_OBJECT_REF (mt);
+ im_info = get_im_info (language, name, Mnil, Mvariable);
+ im_info->tick = 0;
}
- M17N_OBJECT_UNREF (plist);
- return mt;
+ return ret;
}
+/*=*/
+
/***en
@brief Get information about input method commands.
@@ -3995,13 +6061,35 @@ minput_get_description (MSymbol language, MSymbol name)
MPlist *
minput_get_commands (MSymbol language, MSymbol name)
{
- MPlist *plist = get_nested_list (language, name, Mnil, M_command);
+ MInputMethodInfo *im_info;
+ MPlist *cmds;
- return (MPLIST_TAIL_P (plist) ? NULL : plist);
+ MINPUT__INIT ();
+
+ im_info = get_im_info (language, name, Mnil, Mcommand);
+ if (! im_info || ! im_info->configured_vars)
+ return NULL;
+ M17N_OBJECT_UNREF (im_info->bc_cmds);
+ im_info->bc_cmds = mplist ();
+ MPLIST_DO (cmds, im_info->configured_cmds)
+ {
+ MPlist *plist = MPLIST_PLIST (cmds);
+ MPlist *elt = mplist ();
+
+ mplist_push (im_info->bc_cmds, Mplist, elt);
+ mplist_add (elt, MPLIST_SYMBOL (plist),
+ mplist_copy (MPLIST_NEXT (plist)));
+ M17N_OBJECT_UNREF (elt);
+ }
+ return im_info->bc_cmds;
}
+/*=*/
+
/***en
- @brief Assign a key sequence to an input method command.
+ @brief Assign a key sequence to an input method command (obsolete).
+
+ This function is obsolete. Use minput_config_command () instead.
The minput_assign_command_keys () function assigns input key
sequence $KEYSEQ to input method command $COMMAND for the input
@@ -4045,249 +6133,59 @@ int
minput_assign_command_keys (MSymbol language, MSymbol name,
MSymbol command, MPlist *keyseq)
{
- MPlist *plist, *pl, *p;
+ int ret;
+
+ MINPUT__INIT ();
- if (check_command_keyseq (keyseq) < 0
- || ! (plist = get_nested_list (language, name, Mnil, M_command)))
+ if (command == Mnil)
MERROR (MERROR_IM, -1);
- pl = mplist_get (plist, command);
- if (pl)
- {
- pl = MPLIST_NEXT (pl);
- if (! keyseq)
- while ((p = mplist_pop (pl)))
- M17N_OBJECT_UNREF (p);
- else
- {
- keyseq = mplist_copy (keyseq);
- mplist_push (pl, Mplist, keyseq);
- M17N_OBJECT_UNREF (keyseq);
- }
- }
- else
+ if (keyseq)
{
- if (name == Mnil)
- MERROR (MERROR_IM, -1);
- if (! keyseq)
- return 0;
- /* Get global commands. */
- pl = get_nested_list (Mnil, Mnil, Mnil, M_command);
- pl = mplist_get (pl, command);
- if (! pl)
+ MPlist *plist;
+
+ if (! check_command_keyseq (keyseq))
MERROR (MERROR_IM, -1);
- p = mplist ();
- mplist_add (p, Mtext, mplist_value (pl));
- keyseq = mplist_copy (keyseq);
- mplist_add (p, Mplist, keyseq);
- M17N_OBJECT_UNREF (keyseq);
- mplist_push (plist, command, p);
- }
- return 0;
+ plist = mplist ();
+ mplist_add (plist, Mplist, keyseq);
+ keyseq = plist;
+ }
+ else
+ keyseq = mplist ();
+ ret = minput_config_command (language, name, command, keyseq);
+ M17N_OBJECT_UNREF (keyseq);
+ return ret;
}
-/***en
- @brief Get a list of variables of an input method.
-
- The minput_get_variables () function returns a plist (#MPlist) of
- variables used to control the behavior of the input method
- specified by $LANGUAGE and $NAME. The plist is @e well-formed
- (#m17nPlist) of the following format:
-
-@verbatim
- (VARNAME (DOC-MTEXT DEFAULT-VALUE [ VALUE ... ] )
- VARNAME (DOC-MTEXT DEFAULT-VALUE [ VALUE ... ] )
- ...)
-@endverbatim
-
- @c VARNAME is a symbol representing the variable name.
-
- @c DOC-MTEXT is an M-text describing the variable.
-
- @c DEFAULT-VALUE is the default value of the varible. It is a
- symbol, integer, or M-text.
-
- @c VALUEs (if any) specifies the possible values of the variable.
- If @c DEFAULT-VALUE is an integer, @c VALUE may be a plist (@c FROM
- @c TO), where @c FROM and @c TO specifies a range of possible
- values.
-
- For instance, suppose an input method has the variables:
-
- @li name:intvar, description:"value is an integer",
- initial value:0, value-range:0..3,10,20
-
- @li name:symvar, description:"value is a symbol",
- initial value:nil, value-range:a, b, c, nil
-
- @li name:txtvar, description:"value is an M-text",
- initial value:empty text, no value-range (i.e. any text)
-
- Then, the returned plist is as follows.
-
-@verbatim
- (intvar ("value is an integer" 0 (0 3) 10 20)
- symvar ("value is a symbol" nil a b c nil)
- txtvar ("value is an M-text" ""))
-@endverbatim
-
- @return
- If the input method uses any variables, a pointer to #MPlist is
- returned. As the plist is kept in the library, a caller must not
- modify nor free it. If the input method does not use any
- variable, @c NULL is returned. */
-/***ja
- @brief ÆþÎϥ᥽¥Ã¥É¤ÎÊÑ¿ô¥ê¥¹¥È¤òÆÀ¤ë.
-
- ´Ø¿ô minput_get_variables () ¤Ï¡¢$LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ»ØÄꤵ
- ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤Î¿¶¤ëÉñ¤¤¤òÀ©¸æ¤¹¤ëÊÑ¿ô¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È
- (#MPlist) ¤òÊÖ¤¹¡£¤³¤Î¥ê¥¹¥È¤Ï @e well-formed ¤Ç¤¢¤ê(#m17nPlist) °Ê
- ²¼¤Î·Á¼°¤Ç¤¢¤ë¡£
-
-@verbatim
- (VARNAME (DOC-MTEXT DEFAULT-VALUE [ VALUE ... ] )
- VARNAME (DOC-MTEXT DEFAULT-VALUE [ VALUE ... ] )
- ...)
-@endverbatim
-
- @c VARNAME ¤ÏÊÑ¿ô¤Î̾Á°¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
-
- @c DOC-MTEXT ¤ÏÊÑ¿ô¤òÀâÌÀ¤¹¤ë M-text ¤Ç¤¢¤ë¡£
-
- @c DEFAULT-VALUE ¤ÏÊÑ¿ô¤Î¥Ç¥Õ¥©¥ë¥ÈÃͤǤ¢¤ê¡¢¥·¥ó¥Ü¥ë¡¢À°¿ô¤â¤·¤¯¤Ï
- M-text ¤Ç¤¢¤ë¡£
-
- @c VALUE ¤Ï¡¢¤â¤·»ØÄꤵ¤ì¤Æ¤¤¤ì¤ÐÊÑ¿ô¤Î¼è¤êÆÀ¤ëÃͤò¼¨¤¹¡£¤â¤·
- @c DEFAULT-VALUE ¤¬À°¿ô¤Ê¤é¡¢ @c VALUE ¤Ï (@c FROM @c TO) ¤È¤¤¤¦·Á
- ¤Î¥ê¥¹¥È¤Ç¤âÎɤ¤¡£¤³¤Î¾ì¹ç @c FROM ¤È @c TO ¤Ï²Äǽ¤ÊÃͤÎÈϰϤò¼¨¤¹¡£
-
- Îã¤È¤·¤Æ¡¢¤¢¤ëÆþÎϥ᥽¥Ã¥É¤¬¼¡¤Î¤è¤¦¤ÊÊÑ¿ô¤ò»ý¤Ä¾ì¹ç¤ò¹Í¤¨¤è¤¦¡£
-
- @li name:intvar, ÀâÌÀ:"value is an integer",
- ½é´üÃÍ:0, ÃͤÎÈÏ°Ï:0..3,10,20
-
- @li name:symvar, ÀâÌÀ:"value is a symbol",
- ½é´üÃÍ:nil, ÃͤÎÈÏ°Ï:a, b, c, nil
-
- @li name:txtvar, ÀâÌÀ:"value is an M-text",
- ½é´üÃÍ:empty text, ÃͤÎÈϰϤʤ·(¤É¤ó¤Ê M-text ¤Ç¤â²Ä)
-
- ¤³¤Î¾ì¹ç¡¢ÊÖ¤µ¤ì¤ë¥ê¥¹¥È¤Ï°Ê²¼¤Î¤è¤¦¤Ë¤Ê¤ë¡£
-
-@verbatim
- (intvar ("value is an integer" 0 (0 3) 10 20)
- symvar ("value is a symbol" nil a b c nil)
- txtvar ("value is an M-text" ""))
-@endverbatim
-
- @return
- ÆþÎϥ᥽¥Ã¥É¤¬²¿¤é¤«¤ÎÊÑ¿ô¤ò»ÈÍѤ·¤Æ¤¤¤ì¤Ð #MPlist ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
- ÊÖ¤µ¤ì¤ë¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ï¥é¥¤¥Ö¥é¥ê¤Ë¤è¤Ã¤Æ´ÉÍý¤µ¤ì¤Æ¤ª¤ê¡¢¸Æ¤Ó½Ð¤·Â¦¤ÇÊѹ¹¤·¤¿¤ê²òÊü¤·¤¿¤ê¤·¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
- ÆþÎϥ᥽¥Ã¥É¤¬ÊÑ¿ô¤ò°ìÀÚ»ÈÍѤ·¤Æ¤Ê¤±¤ì¤Ð¡¢@c NULL ¤òÊÖ¤¹¡£ */
-
-MPlist *
-minput_get_variables (MSymbol language, MSymbol name)
-{
- MPlist *plist = get_nested_list (language, name, Mnil, M_variable);
-
- return (MPLIST_TAIL_P (plist) ? NULL : plist);
-}
+/*=*/
/***en
- @brief Set the initial value of an input method variable.
-
- The minput_set_variable () function sets the initial value of
- input method variable $VARIABLE to $VALUE for the input method
- specified by $LANGUAGE and $NAME.
-
- By default, the initial value is 0.
-
- This setting gets effective in a newly opened input method.
-
- @return
- If the operation was successful, 0 is returned. Otherwise -1 is
- returned, and #merror_code is set to #MERROR_IM. */
-/***ja
- @brief ÆþÎϥ᥽¥Ã¥ÉÊÑ¿ô¤Î½é´üÃͤòÀßÄꤹ¤ë.
-
- ´Ø¿ô minput_set_variable () ¤Ï¡¢$LANGUAGE ¤È $NAME
- ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ÎÆþÎϥ᥽¥Ã¥ÉÊÑ¿ô $VARIABLE
- ¤Î½é´üÃͤò¡¢ $VALUE ¤ËÀßÄꤹ¤ë¡£
-
- ¥Ç¥Õ¥©¥ë¥È¤Î½é´üÃÍ¤Ï 0 ¤Ç¤¢¤ë¡£
+ @brief Call a callback function
- ¤³¤ÎÀßÄê¤Ï¡¢¿·¤·¤¯¥ª¡¼¥×¥ó¤µ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤«¤é͸ú¤È¤Ê¤ë¡£
+ The minput_callback () functions calls a callback function
+ $COMMAND assigned for the input context $IC. The caller must set
+ specific elements in $IC->plist if the callback function requires.
@return
- ½èÍý¤¬À®¸ù¤¹¤ì¤Ð 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤·¡¢
- #merror_code ¤ò #MERROR_IM ¤ËÀßÄꤹ¤ë¡£ */
+ If there exists a specified callback function, 0 is returned.
+ Otherwise -1 is returned. By side effects, $IC->plist may be
+ modified. */
int
-minput_set_variable (MSymbol language, MSymbol name,
- MSymbol variable, void *value)
+minput_callback (MInputContext *ic, MSymbol command)
{
- MPlist *plist, *val_element, *range_element;
- MSymbol type;
-
- plist = get_nested_list (language, name, Mnil, M_variable);
- if (! plist)
- MERROR (MERROR_IM, -1);
- plist = mplist_find_by_value (plist, variable);
- if (! plist)
- MERROR (MERROR_IM, -1);
- plist = MPLIST_PLIST (MPLIST_NEXT (plist));
- val_element = MPLIST_NEXT (plist);
- type = MPLIST_KEY (val_element);
- range_element = MPLIST_NEXT (val_element);
-
- if (! MPLIST_TAIL_P (range_element))
- {
- if (type == Minteger)
- {
- int val = (int) value, this_val;
-
- MPLIST_DO (plist, range_element)
- {
- this_val = (int) MPLIST_VAL (plist);
- if (MPLIST_PLIST_P (plist))
- {
- int min_bound, max_bound;
- MPlist *pl = MPLIST_PLIST (plist);
-
- min_bound = (int) MPLIST_VAL (pl);
- pl = MPLIST_NEXT (pl);
- max_bound = (int) MPLIST_VAL (pl);
- if (val >= min_bound && val <= max_bound)
- break;
- }
- else if (val == this_val)
- break;
- }
- if (MPLIST_TAIL_P (plist))
- MERROR (MERROR_IM, -1);
- }
- else if (type == Msymbol)
- {
- MPLIST_DO (plist, range_element)
- if (MPLIST_SYMBOL (plist) == (MSymbol) value)
- break;
- if (MPLIST_TAIL_P (plist))
- MERROR (MERROR_IM, -1);
- }
- else /* type == Mtext */
- {
- MPLIST_DO (plist, range_element)
- if (mtext_cmp (MPLIST_MTEXT (plist), (MText *) value) == 0)
- break;
- if (MPLIST_TAIL_P (plist))
- MERROR (MERROR_IM, -1);
- M17N_OBJECT_REF (value);
- }
- }
+ MInputCallbackFunc func;
- mplist_set (val_element, type, value);
+ if (! ic->im->driver.callback_list)
+ return -1;
+ func = ((MInputCallbackFunc)
+ mplist_get_func (ic->im->driver.callback_list, command));
+ if (! func)
+ return -1;
+ (func) (ic, command);
return 0;
}
+/*** @} */
/*** @} */
/*=*/
/*** @addtogroup m17nDebug */