*** empty log message ***
[m17n/m17n-lib.git] / src / input.c
1 /* input.c -- input method module.
2    Copyright (C) 2003, 2004
3      National Institute of Advanced Industrial Science and Technology (AIST)
4      Registration Number H15PRO112
5
6    This file is part of the m17n library.
7
8    The m17n library is free software; you can redistribute it and/or
9    modify it under the terms of the GNU Lesser General Public License
10    as published by the Free Software Foundation; either version 2.1 of
11    the License, or (at your option) any later version.
12
13    The m17n library is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    Lesser General Public License for more details.
17
18    You should have received a copy of the GNU Lesser General Public
19    License along with the m17n library; if not, write to the Free
20    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21    02111-1307, USA.  */
22
23 /***en
24     @addtogroup m17nInputMethod
25     @brief API for Input method.
26
27     An input method is an object to enable inputting various
28     characters.  An input method is identified by a pair of symbols,
29     LANGUAGE and NAME.  This pair decides a input method driver of the
30     input method.  An input method driver is a set of functions for
31     handling the input method.  There are two kinds of input methods;
32     internal one and foreign one.
33
34     <ul>
35     <li> Internal Input Method
36
37     An internal input method has non @c Mnil LANGUAGE, and the body is
38     defined in the m17n database by the tag <Minput_method, LANGUAGE,
39     NAME>.  For this kind of input methods, the m17n library uses two
40     predefined input method drivers, one for CUI use and the other for
41     GUI use.  Those driver utilize the input processing engine
42     provided by the m17n library itself.  The m17n database may
43     provides an input method that is not only for a specific language.
44     The database uses @c Mt as LANGUAGE of such an input method.
45
46     An internal input method accepts an input key which is a symbol
47     associated with an input event.  As there is no way for the @c
48     m17n @c library to know how input events are represented in an
49     application program, an application programmer have to convert an
50     input event to an input key by himself.  See the documentation of
51     the function minput_event_to_key () for the detail.
52
53     <li> Foreign Input Method
54
55     A foreign input method has @c Mnil LANGUAGE, and the body is
56     defined in an external resources (e.g. XIM of X Window System).
57     For this kind of input methods, the symbol NAME must have a
58     property of key @c Minput_driver, and the value must be a pointer
59     to an input method driver.  Therefore, by preparing a proper
60     driver, any kind of input method can be treated in the framework
61     of the @c m17n @c library.
62
63     For convenience, the m17n-X library provides an input method
64     driver that enables the input style of OverTheSpot for XIM, and
65     stores @c Minput_driver property of the symbol @c Mxim with a
66     pointer to the driver.  See the documentation of m17n GUI API for
67     the detail.
68
69     </ul>
70
71     PROCESSING FLOW
72
73     The typical processing flow of handling an input method is: 
74
75      @li open an input method
76      @li create an input context for the input method
77      @li filter an input key
78      @li look up a produced text in the input context  */
79
80 /*=*/
81 /***ja
82     @addtogroup m17nInputMethod
83     @brief ÆþÎϥ᥽¥Ã¥ÉÍÑAPI.
84
85     ÆþÎϥ᥽¥Ã¥É¤Ï¿ÍͤÊʸ»ú¤òÆþÎϤ¹¤ë¤¿¤á¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¢¤ë¡£
86     ÆþÎϥ᥽¥Ã¥É¤Ï¥·¥ó¥Ü¥ë LANGUAGE ¤È NAME ¤ÎÁȤˤè¤Ã¤Æ¼±Ê̤µ¤ì¡¢
87     ¤³¤ÎÁȹ礻¤Ë¤è¤Ã¤ÆÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤¬·èÄꤹ¤ë¡£
88     ÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤È¤Ï¡¢¤¢¤ëÆþÎϥ᥽¥Ã¥É¤ò°·¤¦¤¿¤á¤Î´Ø¿ô¤Î½¸¤Þ¤ê¤Ç¤¢¤ë¡£
89     ÆþÎϥ᥽¥Ã¥É¤Ë¤ÏÆâÉô¥á¥½¥Ã¥É¤È³°Éô¥á¥½¥Ã¥É¤ÎÆó¼ïÎब¤¢¤ë¡£
90
91     <ul> 
92     <li> ÆâÉôÆþÎϥ᥽¥Ã¥É
93
94     ÆâÉôÆþÎϥ᥽¥Ã¥É¤È¤Ï LANGUAGE ¤¬ @c Mnil °Ê³°¤Î¤â¤Î¤Ç¤¢¤ê¡¢¤½¤ÎËÜÂΤÏm17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë
95     <Minput_method, LANGUAGE, NAME> 
96     ¤È¤¤¤¦¥¿¥°¤òÉÕ¤±¤ÆÄêµÁ¤µ¤ì¤Æ¤¤¤ë¡£
97     ¤³¤Î¼ï¤ÎÆþÎϥ᥽¥Ã¥É¤ËÂФ·¤Æ¡¢m17n ¥é¥¤¥Ö¥é¥ê¤Ç¤Ï
98     CUI ÍѤȠGUI ÍѤ½¤ì¤¾¤ì¤ÎÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤ò¤¢¤é¤«¤¸¤áÄêµÁ¤·¤Æ¤¤¤ë¡£
99     ¤³¤ì¤é¤Î¥É¥é¥¤¥Ð¤Ï m17n ¥é¥¤¥Ö¥é¥ê¼«ÂΤÎÆþÎϽèÍý¥¨¥ó¥¸¥ó¤òÍøÍѤ¹¤ë¡£
100     m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë¤Ï¡¢ÆÃÄê¤Î¸À¸ìÀìÍѤǤʤ¤ÆþÎϥ᥽¥Ã¥É¤òÄêµÁ¤¹¤ë¤³¤È¤â¤Ç¤­¡¢
101     ¤½¤Î¤è¤¦¤ÊÆþÎϥ᥽¥Ã¥É¤Î LANGUAGE ¤Ï @c Mt ¤Ç¤¢¤ë¡£
102
103     ÆâÉôÆþÎϥ᥽¥Ã¥É¤Ï¡¢¥æ¡¼¥¶¤ÎÆþÎÏ¥¤¥Ù¥ó¥È¤ËÂбþ¤·¤¿¥·¥ó¥Ü¥ë¤Ç¤¢¤ëÆþÎÏ¥­¡¼¤ò¼õ¤±¼è¤ë¡£
104     @c m17n @c ¥é¥¤¥Ö¥é¥ê ¤ÏÆþÎÏ¥¤¥Ù¥ó¥È¤¬¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ç¤É¤¦É½¸½¤µ¤ì¤Æ¤¤¤ë¤«¤òÃΤ뤳¤È¤¬¤Ç¤­¤Ê¤¤¤Î¤Ç¡¢
105     ÆþÎÏ¥¤¥Ù¥ó¥È¤«¤éÆþÎÏ¥­¡¼¤Ø¤ÎÊÑ´¹¤Ï¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥Þ¤ÎÀÕǤ¤Ç¹Ô¤ï¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
106     ¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï´Ø¿ô minput_event_to_key () ¤ÎÀâÌÀ¤ò»²¾È¡£
107
108     <li> ³°ÉôÆþÎϥ᥽¥Ã¥É
109
110     ³°ÉôÆþÎϥ᥽¥Ã¥É¤È¤Ï LANGUAGE ¤¬ @c Mnil ¤Î¤â¤Î¤Ç¤¢¤ê¡¢¤½¤ÎËÜÂΤϳ°Éô¤Î¥ê¥½¡¼¥¹¤È¤·¤ÆÄêµÁ¤µ¤ì¤ë¡£
111     ¡Ê¤¿¤È¤¨¤ÐX Window System ¤ÎXIM ¤Ê¤É¡£) 
112     ¤³¤Î¼ï¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢¥·¥ó¥Ü¥ë NAME ¤Ï@c Minput_driver 
113     ¤ò¥­¡¼¤È¤¹¤ë¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Á¡¢¤½¤ÎÃͤÏÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£
114     ¤³¤Î¤³¤È¤Ë¤è¤ê¡¢Å¬Àڤʥɥ饤¥Ð¤ò½àÈ÷¤¹¤ë¤³¤È¤Ë¤è¤Ã¤Æ¡¢¤¤¤«¤Ê¤ë¼ïÎà¤ÎÆþÎϥ᥽¥Ã¥É¤â
115     @c m17n @c ¥é¥¤¥Ö¥é¥ê ¤ÎÏÈÁȤÎÃæ¤Ç°·¤¦»ö¤¬¤Ç¤­¤ë¡£
116
117     ÍøÊØÀ­¤Î´ÑÅÀ¤«¤é¡¢m17n X ¥é¥¤¥Ö¥é¥ê¤Ï XIM ¤Î OverTheSpot 
118     ¤ÎÆþÎÏ¥¹¥¿¥¤¥ë¤ò¼Â¸½¤¹¤ëÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤òÄ󶡤·¡¢¤Þ¤¿¥·¥ó¥Ü¥ë @c Mxim ¤Î 
119     @c Minput_driver ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤȤ·¤Æ¤½¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÝ»ý¤·¤Æ¤¤¤ë¡£
120     ¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï m17n GUI API ¤Î¥É¥­¥å¥á¥ó¥È¤ò»²¾È¤Î¤³¤È¡£
121
122     </ul> 
123
124     ½èÍý¤Îή¤ì
125
126     ÆþÎϥ᥽¥Ã¥É½èÍý¤Îŵ·¿Åª¤Ê½èÍý¤Ï°Ê²¼¤Î¤è¤¦¤Ë¤Ê¤ë¡£
127     
128     @li ÆþÎϥ᥽¥Ã¥É¤Î¥ª¡¼¥×¥ó
129     @li ¤½¤ÎÆþÎϥ᥽¥Ã¥É¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤ÎÀ¸À®
130     @li ÆþÎÏ¥¤¥Ù¥ó¥È¤Î¥Õ¥£¥ë¥¿
131     @li ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ç¤ÎÀ¸À®¥Æ¥­¥¹¥È¤Î¸¡º÷     */
132
133 /*=*/
134
135 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
136 /*** @addtogroup m17nInternal
137      @{ */
138
139 #include <stdio.h>
140 #include <string.h>
141 #include <sys/types.h>
142 #include <dirent.h>
143
144 #include "config.h"
145
146 #ifdef HAVE_DLFCN_H
147 #include <dlfcn.h>
148 #endif
149
150 #include "m17n-gui.h"
151 #include "m17n-misc.h"
152 #include "internal.h"
153 #include "mtext.h"
154 #include "input.h"
155 #include "symbol.h"
156 #include "plist.h"
157 #include "database.h"
158
159 static int mdebug_mask = MDEBUG_INPUT;
160
161 static MSymbol Minput_method;
162
163 /** Symbols to load an input method data.  */
164 static MSymbol Mtitle, Mmacro, Mmodule, Mstate;
165
166 /** Symbols for actions.  */
167 static MSymbol Minsert, Mdelete, Mmark, Mmove, Mpushback, Mundo, Mcall, Mshift;
168 static MSymbol Mselect, Mshow, Mhide;
169 static MSymbol Mset, Madd, Msub, Mmul, Mdiv, Mequal, Mless, Mgreater;
170
171 static MSymbol Mcandidate_list, Mcandidate_index;
172
173 static MSymbol Minit, Mfini;
174
175 /** Symbols for key events.  */
176 static MSymbol one_char_symbol[256];
177
178 static MSymbol M_key_alias;
179
180 static MSymbol M_description, M_command, M_variable;
181
182 /** Structure to hold a map.  */
183
184 struct MIMMap
185 {
186   /** List of actions to take when we reach the map.  In a root map,
187       the actions are executed only when there's no more key.  */
188   MPlist *map_actions;
189
190   /** List of deeper maps.  If NULL, this is a terminal map.  */
191   MPlist *submaps;
192
193   /** List of actions to take when we leave the map successfully.  In
194       a root map, the actions are executed only when none of submaps
195       handle the current key.  */
196   MPlist *branch_actions;
197 };
198
199 typedef MPlist *(*MIMExternalFunc) (MPlist *plist);
200
201 typedef struct
202 {
203   void *handle;
204   MPlist *func_list;            /* function name vs (MIMExternalFunc *) */
205 } MIMExternalModule;
206
207 struct MIMState
208 {
209   /** Name of the state.  */
210   MSymbol name;
211
212   /** Title of the state, or NULL.  */
213   MText *title;
214
215   /** Key translation map of the state.  Built by merging all maps of
216       branches.  */
217   MIMMap *map;
218 };
219
220
221 static int
222 marker_code (MSymbol sym)
223 {
224   char *name;
225
226   if (sym == Mnil)
227     return -1;
228   name = MSYMBOL_NAME (sym);
229   return ((name[0] == '@'
230            && ((name[1] >= '0' && name[1] <= '9')
231                || name[1] == '<' || name[1] == '>'
232                || name[1] == '=' || name[1] == '+' || name[1] == '-'
233                || name[1] == '[' || name[1] == ']')
234            && name[2] == '\0')
235           ? name[1] : -1);
236 }
237
238 int
239 integer_value (MInputContext *ic, MPlist *arg)
240 {
241   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
242   int code;
243   MText *preedit = ic->preedit;
244   int len = mtext_nchars (preedit);
245
246   if (MPLIST_INTEGER_P (arg))
247     return MPLIST_INTEGER (arg);
248   code = marker_code (MPLIST_SYMBOL (arg));
249   if (code < 0)
250     return (int) mplist_get (ic_info->vars, MPLIST_SYMBOL (arg));
251   if (code >= '0' && code <= '9')
252     code -= '0';
253   else if (code == '=')
254     code = ic->cursor_pos;
255   else if (code == '-' || code == '[')
256     code = ic->cursor_pos - 1;
257   else if (code == '+' || code == ']')
258     code = ic->cursor_pos + 1;
259   else if (code == '<')
260     code = 0;
261   else if (code == '>')
262     code = len;
263   return (code >= 0 && code < len ? mtext_ref_char (preedit, code) : -1);
264 }
265
266
267 /* Parse PLIST as an action list while modifying the list to regularize
268    actions.  PLIST should have this form:
269       PLIST ::= ( (ACTION-NAME ACTION-ARG *) *).
270    Return 0 if successfully parsed, otherwise return -1.  */
271
272 static int
273 parse_action_list (MPlist *plist, MPlist *macros)
274 {
275   MPLIST_DO (plist, plist)
276     {
277       if (MPLIST_MTEXT_P (plist))
278         {
279           /* This is a short form of (insert MTEXT).  */
280           /* if (mtext_nchars (MPLIST_MTEXT (plist)) == 0)
281              MERROR (MERROR_IM, -1); */
282         }
283       else if (MPLIST_PLIST_P (plist)
284                && (MPLIST_MTEXT_P (MPLIST_PLIST (plist))
285                    || MPLIST_PLIST_P (MPLIST_PLIST (plist))))
286         {
287           MPlist *pl;
288
289           /* This is a short form of (insert (GROUPS *)).  */
290           MPLIST_DO (pl, MPLIST_PLIST (plist))
291             {
292               if (MPLIST_PLIST_P (pl))
293                 {
294                   MPlist *elt;
295
296                   MPLIST_DO (elt, MPLIST_PLIST (pl))
297                     if (! MPLIST_MTEXT_P (elt)
298                         || mtext_nchars (MPLIST_MTEXT (elt)) == 0)
299                       MERROR (MERROR_IM, -1);
300                 }
301               else
302                 {
303                   if (! MPLIST_MTEXT_P (pl)
304                       || mtext_nchars (MPLIST_MTEXT (pl)) == 0)
305                     MERROR (MERROR_IM, -1);
306                 }
307             }
308         }
309       else if (MPLIST_INTEGER_P (plist))
310         {
311           int c = MPLIST_INTEGER (plist);
312
313           if (c < 0 || c > MCHAR_MAX)
314             MERROR (MERROR_IM, -1);
315         }
316       else if (MPLIST_PLIST_P (plist)
317                && MPLIST_SYMBOL_P (MPLIST_PLIST (plist)))
318         {
319           MPlist *pl = MPLIST_PLIST (plist);
320           MSymbol action_name = MPLIST_SYMBOL (pl);
321
322           pl = MPLIST_NEXT (pl);
323
324           if (action_name == Minsert)
325             {
326               if (MPLIST_MTEXT_P (pl))
327                 {
328                   if (mtext_nchars (MPLIST_MTEXT (pl)) == 0)
329                     MERROR (MERROR_IM, -1);
330                 }
331               else if (MPLIST_PLIST_P (pl))
332                 {
333                   MPLIST_DO (pl, pl)
334                     {
335                       if (MPLIST_PLIST_P (pl))
336                         {
337                           MPlist *elt;
338
339                           MPLIST_DO (elt, MPLIST_PLIST (pl))
340                             if (! MPLIST_MTEXT_P (elt)
341                                 || mtext_nchars (MPLIST_MTEXT (elt)) == 0)
342                               MERROR (MERROR_IM, -1);
343                         }
344                       else
345                         {
346                           if (! MPLIST_MTEXT_P (pl)
347                               || mtext_nchars (MPLIST_MTEXT (pl)) == 0)
348                             MERROR (MERROR_IM, -1);
349                         }
350                     }
351                 }
352               else if (! MPLIST_SYMBOL_P (pl))
353                 MERROR (MERROR_IM, -1); 
354             }
355           else if (action_name == Mselect
356                    || action_name == Mdelete
357                    || action_name == Mmove)
358             {
359               if (! MPLIST_SYMBOL_P (pl)
360                   && ! MPLIST_INTEGER_P (pl))
361                 MERROR (MERROR_IM, -1);
362             }
363           else if (action_name == Mmark
364                    || action_name == Mcall
365                    || action_name == Mshift)
366             {
367               if (! MPLIST_SYMBOL_P (pl))
368                 MERROR (MERROR_IM, -1);
369             }
370           else if (action_name == Mshow || action_name == Mhide
371                    || action_name == Mundo)
372             {
373               if (! MPLIST_TAIL_P (pl))
374                 MERROR (MERROR_IM, -1);
375             }
376           else if (action_name == Mpushback)
377             {
378               if (! MPLIST_INTEGER_P (pl))
379                 MERROR (MERROR_IM, -1);
380             }
381           else if (action_name == Mset || action_name == Madd
382                    || action_name == Msub || action_name == Mmul
383                    || action_name == Mdiv)
384             {
385               if (! (MPLIST_SYMBOL_P (pl)
386                      && (MPLIST_INTEGER_P (MPLIST_NEXT (pl))
387                          || MPLIST_SYMBOL_P (MPLIST_NEXT (pl)))))
388                 MERROR (MERROR_IM, -1);
389             }
390           else if (action_name == Mequal || action_name == Mless
391                    || action_name == Mgreater)
392             {
393               if (! ((MPLIST_INTEGER_P (pl) || MPLIST_SYMBOL_P (pl))
394                      && (MPLIST_INTEGER_P (MPLIST_NEXT (pl))
395                          || MPLIST_SYMBOL_P (MPLIST_NEXT (pl)))))
396                 MERROR (MERROR_IM, -1);
397               pl = MPLIST_NEXT (MPLIST_NEXT (pl));
398               if (! MPLIST_PLIST_P (pl))
399                 MERROR (MERROR_IM, -1);
400               if (parse_action_list (MPLIST_PLIST (pl), macros) < 0)
401                 MERROR (MERROR_IM, -1);
402               pl = MPLIST_NEXT (pl);
403               if (MPLIST_PLIST_P (pl)
404                   && parse_action_list (MPLIST_PLIST (pl), macros) < 0)
405                 MERROR (MERROR_IM, -1);
406             }
407           else if (! macros || ! mplist_get (macros, action_name))
408             MERROR (MERROR_IM, -1);
409         }
410       else
411         MERROR (MERROR_IM, -1);
412     }
413
414   return 0;
415 }
416
417
418 /* Load a translation into MAP from PLIST.
419    PLIST has this form:
420       PLIST ::= ( KEYSEQ MAP-ACTION * )  */
421
422 static int
423 load_translation (MIMMap *map, MPlist *plist, MPlist *branch_actions,
424                   MPlist *macros)
425 {
426   MSymbol *keyseq;
427   int len, i;
428
429   if (MPLIST_MTEXT_P (plist))
430     {
431       MText *mt = MPLIST_MTEXT (plist);
432
433       len = mtext_nchars (mt);
434       if (len == 0 || len != mtext_nbytes (mt))
435         MERROR (MERROR_IM, -1);
436       keyseq = (MSymbol *) alloca (sizeof (MSymbol) * len);
437       for (i = 0; i < len; i++)
438         keyseq[i] = one_char_symbol[MTEXT_DATA (mt)[i]];
439     }
440   else if (MPLIST_PLIST_P (plist))
441     {
442       MPlist *elt = MPLIST_PLIST (plist);
443           
444       len = MPLIST_LENGTH (elt);
445       if (len == 0)
446         MERROR (MERROR_IM, -1);
447       keyseq = (MSymbol *) alloca (sizeof (int) * len);
448       for (i = 0; i < len; i++, elt = MPLIST_NEXT (elt))
449         {
450           if (MPLIST_INTEGER_P (elt))
451             {
452               int c = MPLIST_INTEGER (elt);
453
454               if (c < 0 || c >= 0x100)
455                 MERROR (MERROR_IM, -1);
456               keyseq[i] = one_char_symbol[c];
457             }
458           else if (MPLIST_SYMBOL_P (elt))
459             keyseq[i] = MPLIST_SYMBOL (elt);
460           else
461             MERROR (MERROR_IM, -1);
462         }
463     }
464   else
465     MERROR (MERROR_IM, -1);
466
467   for (i = 0; i < len; i++)
468     {
469       MIMMap *deeper = NULL;
470
471       if (map->submaps)
472         deeper = mplist_get (map->submaps, keyseq[i]);
473       else
474         map->submaps = mplist ();
475       if (! deeper)
476         {
477           /* Fixme: It is better to make all deeper maps at once.  */
478           MSTRUCT_CALLOC (deeper, MERROR_IM);
479           mplist_put (map->submaps, keyseq[i], deeper);
480         }
481       map = deeper;
482     }
483
484   /* We reach a terminal map.  */
485   if (map->map_actions
486       || map->branch_actions)
487     /* This map is already defined.  We avoid overriding it.  */
488     return 0;
489
490   plist = MPLIST_NEXT (plist);
491   if (! MPLIST_TAIL_P (plist))
492     {
493       if (parse_action_list (plist, macros) < 0)
494         MERROR (MERROR_IM, -1);
495       map->map_actions = plist;
496       M17N_OBJECT_REF (plist);
497     }
498   if (branch_actions)
499     {
500       map->branch_actions = branch_actions;
501       M17N_OBJECT_REF (branch_actions);
502     }
503
504   return 0;
505 }
506
507 /* Load a branch from PLIST into MAP.  PLIST has this form:
508       PLIST ::= ( MAP-NAME BRANCH-ACTION * )
509    MAPS is a plist of raw maps.
510    STATE is the current state.  */
511
512 static int
513 load_branch (MPlist *plist, MPlist *maps, MIMMap *map, MPlist *macros)
514 {
515   MSymbol map_name;
516   MPlist *branch_actions;
517
518   if (! MPLIST_SYMBOL_P (plist))
519     MERROR (MERROR_IM, -1);
520   map_name = MPLIST_SYMBOL (plist);
521   plist = MPLIST_NEXT (plist);
522   if (MPLIST_TAIL_P (plist))
523     branch_actions = NULL;
524   else if (parse_action_list (plist, macros) < 0)
525     MERROR (MERROR_IM, -1);
526   else
527     branch_actions = plist;
528   if (map_name == Mnil)
529     {
530       map->branch_actions = branch_actions;
531       if (branch_actions)
532         M17N_OBJECT_REF (branch_actions);
533     }
534   else if (map_name == Mt)
535     {
536       map->map_actions = branch_actions;
537       if (branch_actions)
538         M17N_OBJECT_REF (branch_actions);
539     }
540   else
541     {
542       plist = (MPlist *) mplist_get (maps, map_name);
543       if (! plist || ! MPLIST_PLIST_P (plist))
544         MERROR (MERROR_IM, -1);
545       MPLIST_DO (plist, plist)
546         if (! MPLIST_PLIST_P (plist)
547             || (load_translation (map, MPLIST_PLIST (plist), branch_actions,
548                                   macros)
549                 < 0))
550           MERROR (MERROR_IM, -1);
551     }
552
553   return 0;
554 }
555
556 /* Load a macro from PLIST into MACROS.
557    PLIST has this from:
558       PLIST ::= ( MACRO-NAME ACTION * )
559    MACROS is a plist of macro names vs action list.  */
560 static int
561 load_macros (MPlist *plist, MPlist *macros)
562 {
563   MSymbol name; 
564
565   if (! MPLIST_SYMBOL_P (plist))
566     MERROR (MERROR_IM, -1);
567   name = MPLIST_SYMBOL (plist);
568   plist = MPLIST_NEXT (plist);
569   if (MPLIST_TAIL_P (plist)
570       || parse_action_list (plist, macros) < 0)
571     MERROR (MERROR_IM, -1);
572   mplist_put (macros, name, plist);
573   M17N_OBJECT_REF (plist);
574   return 0;
575 }
576
577 /* Load an external module from PLIST into EXTERNALS.
578    PLIST has this form:
579       PLIST ::= ( MODULE-NAME FUNCTION * )
580    EXTERNALS is a plist of MODULE-NAME vs (MIMExternalModule *).  */
581
582 static int
583 load_external_module (MPlist *plist, MPlist *externals)
584 {
585   void *handle;
586   MSymbol module;
587   char *module_file;
588   MIMExternalModule *external;
589   MPlist *func_list;
590   void *func;
591
592   if (MPLIST_MTEXT_P (plist))
593     module = msymbol ((char *) MTEXT_DATA (MPLIST_MTEXT (plist)));
594   else if (MPLIST_SYMBOL_P (plist))
595     module = MPLIST_SYMBOL (plist);
596   module_file = alloca (strlen (MSYMBOL_NAME (module))
597                         + strlen (DLOPEN_SHLIB_EXT) + 1);
598   sprintf (module_file, "%s%s", MSYMBOL_NAME (module), DLOPEN_SHLIB_EXT);
599
600   handle = dlopen (module_file, RTLD_NOW);
601   if (! handle)
602     {
603       fprintf (stderr, "%s\n", dlerror ());
604       MERROR (MERROR_IM, -1);
605     }
606   func_list = mplist ();
607   MPLIST_DO (plist, MPLIST_NEXT (plist))
608     {
609       if (! MPLIST_SYMBOL_P (plist))
610         MERROR_GOTO (MERROR_IM, err_label);
611       func = dlsym (handle, MSYMBOL_NAME (MPLIST_SYMBOL (plist)));
612       if (! func)
613         MERROR_GOTO (MERROR_IM, err_label);
614       mplist_add (func_list, MPLIST_SYMBOL (plist), func);
615     }
616
617   MSTRUCT_MALLOC (external, MERROR_IM);
618   external->handle = handle;
619   external->func_list = func_list;
620   mplist_add (externals, module, external);
621   return 0;
622
623  err_label:
624   dlclose (handle);
625   M17N_OBJECT_UNREF (func_list);
626   return -1;
627 }
628
629
630 /** Load a state from PLIST into a newly allocated state object.
631     PLIST has this form:
632       PLIST ::= ( STATE-NAME STATE-TITLE ? BRANCH * )
633       BRANCH ::= ( MAP-NAME BRANCH-ACTION * )
634    MAPS is a plist of defined maps.
635    Return the state object.  */
636
637 static MIMState *
638 load_state (MPlist *plist, MPlist *maps, MSymbol language, MPlist *macros)
639 {
640   MIMState *state;
641
642   MSTRUCT_CALLOC (state, MERROR_IM);
643   if (! MPLIST_SYMBOL_P (plist))
644     MERROR (MERROR_IM, NULL);
645   state->name = MPLIST_SYMBOL (plist);
646   plist = MPLIST_NEXT (plist);
647   if (MPLIST_MTEXT_P (plist))
648     {
649       state->title = MPLIST_MTEXT (plist);
650       mtext_put_prop (state->title, 0, mtext_nchars (state->title),
651                       Mlanguage, language);
652       M17N_OBJECT_REF (state->title);
653       plist = MPLIST_NEXT (plist);
654     }
655   MSTRUCT_CALLOC (state->map, MERROR_IM);
656   MPLIST_DO (plist, plist)
657     if (! MPLIST_PLIST_P (plist)
658         || load_branch (MPLIST_PLIST (plist), maps, state->map, macros) < 0)
659       MERROR (MERROR_IM, NULL);
660   return state;
661 }
662
663
664 static void
665 free_map (MIMMap *map)
666 {
667   MPlist *plist;
668
669   M17N_OBJECT_UNREF (map->map_actions);
670   if (map->submaps)
671     {
672       MPLIST_DO (plist, map->submaps)
673         free_map ((MIMMap *) MPLIST_VAL (plist));
674       M17N_OBJECT_UNREF (map->submaps);
675     }
676   M17N_OBJECT_UNREF (map->branch_actions);
677   free (map);
678 }
679
680 /* Load an input method from PLIST into IM_INTO, and return it.  */
681
682 static int
683 load_input_method (MSymbol language, MSymbol name, MPlist *plist,
684                    MInputMethodInfo *im_info)
685 {
686   MText *title = NULL;
687   MPlist *maps = NULL;
688   MPlist *states = NULL;
689   MPlist *externals = NULL;
690   MPlist *macros = NULL;
691   MPlist *elt;
692
693   for (; MPLIST_PLIST_P (plist); plist = MPLIST_NEXT (plist))
694     {
695       elt = MPLIST_PLIST (plist);
696       if (! MPLIST_SYMBOL_P (elt))
697         MERROR_GOTO (MERROR_IM, err);
698       if (MPLIST_SYMBOL (elt) == Mtitle)
699         {
700           elt = MPLIST_NEXT (elt);
701           if (MPLIST_MTEXT_P (elt))
702             {
703               title = MPLIST_MTEXT (elt);
704               M17N_OBJECT_REF (title);
705             }
706           else
707             MERROR_GOTO (MERROR_IM, err);
708         }
709       else if (MPLIST_SYMBOL (elt) == Mmap)
710         {
711           maps = mplist__from_alist (MPLIST_NEXT (elt));
712           if (! maps)
713             MERROR_GOTO (MERROR_IM, err);
714         }
715       else if (MPLIST_SYMBOL (elt) == Mmacro)
716         {
717           macros = mplist ();
718           MPLIST_DO (elt, MPLIST_NEXT (elt))
719           {
720             if (! MPLIST_PLIST_P (elt)
721                 || load_macros (MPLIST_PLIST (elt), macros) < 0)
722               MERROR_GOTO (MERROR_IM, err);
723           }
724         }
725       else if (MPLIST_SYMBOL (elt) == Mmodule)
726         {
727           externals = mplist ();
728           MPLIST_DO (elt, MPLIST_NEXT (elt))
729           {
730             if (! MPLIST_PLIST_P (elt)
731                 || load_external_module (MPLIST_PLIST (elt), externals) < 0)
732               MERROR_GOTO (MERROR_IM, err);
733           }
734         }
735       else if (MPLIST_SYMBOL (elt) == Mstate)
736         {
737           states = mplist ();
738           MPLIST_DO (elt, MPLIST_NEXT (elt))
739           {
740             MIMState *state;
741
742             if (! MPLIST_PLIST_P (elt))
743               MERROR_GOTO (MERROR_IM, err);
744             state = load_state (MPLIST_PLIST (elt), maps, language, macros);
745             if (! state)
746               MERROR_GOTO (MERROR_IM, err);
747             mplist_put (states, state->name, state);
748           }
749         }
750     }
751
752   if (maps)
753     {
754       MPLIST_DO (elt, maps)
755         M17N_OBJECT_UNREF (MPLIST_VAL (elt));
756       M17N_OBJECT_UNREF (maps);
757     }
758   if (! title)
759     title = mtext_from_data (MSYMBOL_NAME (name), MSYMBOL_NAMELEN (name),
760                              MTEXT_FORMAT_US_ASCII);
761   im_info->title = title;
762   im_info->externals = externals;
763   im_info->macros = macros;
764   im_info->states = states;
765   return 0;
766
767  err:
768   if (maps)
769     {
770       MPLIST_DO (elt, maps)
771         M17N_OBJECT_UNREF (MPLIST_VAL (elt));
772       M17N_OBJECT_UNREF (maps);
773     }
774   if (title)
775     M17N_OBJECT_UNREF (title);
776   if (states)
777     {
778       MPLIST_DO (plist, states)
779       {
780         MIMState *state = (MIMState *) MPLIST_VAL (plist);
781
782         if (state->title)
783           M17N_OBJECT_UNREF (state->title);
784         if (state->map)
785           free_map (state->map);
786         free (state);
787       }
788       M17N_OBJECT_UNREF (states);
789     }
790   if (externals)
791     {
792       MPLIST_DO (plist, externals)
793       {
794         MIMExternalModule *external = MPLIST_VAL (plist);
795
796         dlclose (external->handle);
797         M17N_OBJECT_UNREF (external->func_list);
798         free (external);
799         MPLIST_KEY (plist) = Mt;
800       }
801       M17N_OBJECT_UNREF (externals);
802     }
803   return -1;
804 }
805
806 \f
807
808 static int take_action_list (MInputContext *ic, MPlist *action_list);
809
810 static void
811 shift_state (MInputContext *ic, MSymbol state_name)
812 {
813   MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
814   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
815   MIMState *state;
816
817   /* Find a state to shift to.  If not found, shift to the initial
818      state.  */
819   state = (MIMState *) mplist_get (im_info->states, state_name);
820   if (! state)
821     state = (MIMState *) MPLIST_VAL (im_info->states);
822
823   MDEBUG_PRINT1 ("\n[IM] state-shift (%s)", MSYMBOL_NAME (state->name));
824
825   /* Enter the new state.  */
826   ic_info->state = state;
827   ic_info->map = state->map;
828   ic_info->state_key_head = ic_info->key_head;
829   if (state == (MIMState *) MPLIST_VAL (im_info->states))
830     {
831       /* We have shifted to the initial state.  */
832       MPlist *p;
833
834       mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit),
835                              Mcandidate_list, NULL, 0);
836       mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit),
837                              Mcandidate_index, NULL, 0);
838       mtext_cat (ic->produced, ic->preedit);
839       if ((mdebug__flag & mdebug_mask)
840           && mtext_nchars (ic->produced) > 0)
841         {
842           int i;
843
844           MDEBUG_PRINT (" (produced");
845             for (i = 0; i < mtext_nchars (ic->produced); i++)
846               MDEBUG_PRINT1 (" U+%04X", mtext_ref_char (ic->produced, i));
847           MDEBUG_PRINT (")");
848         }
849       mtext_reset (ic->preedit);
850       ic->candidate_list = NULL;
851       ic->candidate_show = 0;
852       ic->preedit_changed = ic->candidates_changed = 1;
853       MPLIST_DO (p, ic_info->markers)
854         MPLIST_VAL (p) = 0;
855       MPLIST_DO (p, ic_info->vars)
856         MPLIST_VAL (p) = 0;
857       ic->cursor_pos = 0;
858       memmove (ic_info->keys, ic_info->keys + ic_info->state_key_head,
859                sizeof (int) * (ic_info->used - ic_info->state_key_head));
860       ic_info->used -= ic_info->state_key_head;
861       ic_info->state_key_head = ic_info->key_head = 0;
862     }
863   mtext_cpy (ic_info->preedit_saved, ic->preedit);
864   ic_info->state_pos = ic->cursor_pos;
865   ic->status = state->title;
866   if (! ic->status)
867     ic->status = im_info->title;
868   ic->status_changed = 1;
869   if (ic_info->key_head == ic_info->used
870       && ic_info->map == ic_info->state->map
871       && ic_info->map->map_actions)
872     {
873       MDEBUG_PRINT (" init-actions:");
874       take_action_list (ic, ic_info->map->map_actions);
875     }
876 }
877
878 /* Find a candidate group that contains a candidate number INDEX from
879    PLIST.  Set START_INDEX to the first candidate number of the group,
880    END_INDEX to the last candidate number plus 1, GROUP_INDEX to the
881    candidate group number if they are non-NULL.  If INDEX is -1, find
882    the last candidate group.  */
883
884 static MPlist *
885 find_candidates_group (MPlist *plist, int index,
886                        int *start_index, int *end_index, int *group_index)
887 {
888   int i = 0, gidx = 0, len;
889
890   MPLIST_DO (plist, plist)
891     {
892       if (MPLIST_MTEXT_P (plist))
893         len = mtext_nchars (MPLIST_MTEXT (plist));
894       else
895         len = mplist_length (MPLIST_PLIST (plist));
896       if (index < 0 ? MPLIST_TAIL_P (MPLIST_NEXT (plist))
897           : i + len > index)
898         {
899           if (start_index)
900             *start_index = i;
901           if (end_index)
902             *end_index = i + len;
903           if (group_index)
904             *group_index = gidx;
905           return plist;
906         }
907       i += len;
908       gidx++;
909     }
910   return NULL;
911 }
912
913 static void
914 preedit_insert (MInputContext *ic, int pos, MText *mt, int c)
915 {
916   MInputContextInfo *ic_info = ((MInputContext *) ic)->info;
917   MPlist *markers;
918   int nchars = mt ? mtext_nchars (mt) : 1;
919
920   if (mt)
921     mtext_ins (ic->preedit, pos, mt);
922   else
923     mtext_ins_char (ic->preedit, pos, c, 1);
924   MPLIST_DO (markers, ic_info->markers)
925     if (MPLIST_INTEGER (markers) > pos)
926       MPLIST_VAL (markers) = (void *) (MPLIST_INTEGER (markers) + nchars);
927   if (ic->cursor_pos >= pos)
928     ic->cursor_pos += nchars;
929   ic->preedit_changed = 1;
930 }
931
932
933 static void
934 preedit_delete (MInputContext *ic, int from, int to)
935 {
936   MInputContextInfo *ic_info = ((MInputContext *) ic)->info;
937   MPlist *markers;
938
939   mtext_del (ic->preedit, from, to);
940   MPLIST_DO (markers, ic_info->markers)
941     {
942       if (MPLIST_INTEGER (markers) > to)
943         MPLIST_VAL (markers)
944           = (void *) (MPLIST_INTEGER (markers) - (to - from));
945       else if (MPLIST_INTEGER (markers) > from);
946         MPLIST_VAL (markers) = (void *) from;
947     }
948   if (ic->cursor_pos >= to)
949     ic->cursor_pos -= to - from;
950   else if (ic->cursor_pos > from)
951     ic->cursor_pos = from;
952   ic->preedit_changed = 1;
953 }
954
955
956 static int
957 new_index (MInputContext *ic, int current, int limit, MSymbol sym, MText *mt)
958 {
959   int code = marker_code (sym);
960
961   if (mt && (code == '[' || code == ']'))
962     {
963       int pos = current;
964
965       if (code == '[' && current > 0)
966         {
967           if (mtext_prop_range (mt, Mcandidate_list, pos - 1, &pos, NULL, 1)
968               && pos > 0)
969             current = pos;
970         }
971       else if (code == ']' && current < mtext_nchars (mt))
972         {
973           if (mtext_prop_range (mt, Mcandidate_list, pos, NULL, &pos, 1))
974             current = pos;
975         }
976       return current;
977     }
978   if (code >= 0)
979     return (code == '<' ? 0
980             : code == '>' ? limit
981             : code == '-' ? current - 1
982             : code == '+' ? current + 1
983             : code == '=' ? current
984             : code - '0' > limit ? limit
985             : code - '0');
986   if (! ic)  
987     return 0;
988   return (int) mplist_get (((MInputContextInfo *) ic->info)->markers, sym);
989 }
990
991 static void
992 update_candidate (MInputContext *ic, MTextProperty *prop, int idx)
993 {
994   int from = mtext_property_start (prop);
995   int to = mtext_property_end (prop);
996   int start;
997   MPlist *candidate_list = mtext_property_value (prop);
998   MPlist *group = find_candidates_group (candidate_list, idx, &start,
999                                          NULL, NULL);
1000   int ingroup_index = idx - start;
1001   MText *mt;
1002
1003   preedit_delete (ic, from, to);
1004   if (MPLIST_MTEXT_P (group))
1005     {
1006       mt = MPLIST_MTEXT (group);
1007       preedit_insert (ic, from, NULL, mtext_ref_char (mt, ingroup_index));
1008       to = from + 1;
1009     }
1010   else
1011     {
1012       int i;
1013       MPlist *plist;
1014
1015       for (i = 0, plist = MPLIST_PLIST (group); i < ingroup_index;
1016            i++, plist = MPLIST_NEXT (plist));
1017       mt = MPLIST_MTEXT (plist);
1018       preedit_insert (ic, from, mt, 0);
1019       to = from + mtext_nchars (mt);
1020     }
1021   mtext_put_prop (ic->preedit, from, to, Mcandidate_list, candidate_list);
1022   mtext_put_prop (ic->preedit, from, to, Mcandidate_index, (void *) idx);
1023   ic->cursor_pos = to;
1024 }
1025
1026
1027 static int
1028 take_action_list (MInputContext *ic, MPlist *action_list)
1029 {
1030   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1031   MPlist *candidate_list = ic->candidate_list;
1032   int candidate_index = ic->candidate_index;
1033   int candidate_show = ic->candidate_show;
1034   MTextProperty *prop;
1035
1036   MPLIST_DO (action_list, action_list)
1037     {
1038       MPlist *action;
1039       MSymbol name;
1040       MPlist *args;
1041
1042       if (MPLIST_MTEXT_P (action_list)
1043           || MPLIST_INTEGER_P (action_list))
1044         name = Minsert, args = action_list;
1045       else if (MPLIST_PLIST_P (action_list)
1046                && (MPLIST_MTEXT_P (MPLIST_PLIST (action_list))
1047                    || MPLIST_PLIST_P (MPLIST_PLIST (action_list))))
1048         name = Minsert, args = action_list;
1049       else
1050         {
1051           action = MPLIST_PLIST (action_list);
1052           name = MPLIST_SYMBOL (action);
1053           args = MPLIST_NEXT (action);
1054         }
1055
1056       MDEBUG_PRINT1 (" %s", MSYMBOL_NAME (name));
1057       if (name == Minsert)
1058         {
1059           if (MPLIST_MTEXT_P (args))
1060             preedit_insert (ic, ic->cursor_pos, MPLIST_MTEXT (args), 0);
1061           else if (MPLIST_INTEGER_P (args))
1062             preedit_insert (ic, ic->cursor_pos, NULL, MPLIST_INTEGER (args));
1063           else if (MPLIST_SYMBOL_P (args))
1064             {
1065               int c = integer_value (ic, args);
1066
1067               if (c >= 0 && c <= MCHAR_MAX)
1068                 preedit_insert (ic, ic->cursor_pos, NULL, c);
1069             }
1070           else
1071             {
1072               MText *mt;
1073               int len;
1074
1075               args = MPLIST_PLIST (args);
1076               if (MPLIST_MTEXT_P (args))
1077                 {
1078                   preedit_insert (ic, ic->cursor_pos, NULL,
1079                                   mtext_ref_char (MPLIST_MTEXT (args), 0));
1080                   len = 1;
1081                 }
1082               else
1083                 {
1084                   mt = MPLIST_MTEXT (MPLIST_PLIST (args));
1085                   preedit_insert (ic, ic->cursor_pos, mt, 0);
1086                   len = mtext_nchars (mt);
1087                 }
1088               mtext_put_prop (ic->preedit,
1089                               ic->cursor_pos - len, ic->cursor_pos,
1090                               Mcandidate_list, args);
1091               mtext_put_prop (ic->preedit,
1092                               ic->cursor_pos - len, ic->cursor_pos,
1093                               Mcandidate_index, (void *) 0);
1094             }
1095         }
1096       else if (name == Mselect)
1097         {
1098           int start, end;
1099           int code, idx, gindex;
1100           int pos = ic->cursor_pos;
1101           MPlist *group;
1102
1103           if (pos == 0
1104               || ! (prop = mtext_get_property (ic->preedit, pos - 1,
1105                                                Mcandidate_list)))
1106             continue;
1107           if (MPLIST_SYMBOL_P (args))
1108             {
1109               code = marker_code (MPLIST_SYMBOL (args));
1110               if (code < 0)
1111                 continue;
1112             }
1113           else
1114             code = -1;
1115           idx = (int) mtext_get_prop (ic->preedit, pos - 1, Mcandidate_index);
1116           group = find_candidates_group (mtext_property_value (prop), idx,
1117                                          &start, &end, &gindex);
1118
1119           if (code != '[' && code != ']')
1120             {
1121               idx = (start
1122                      + (code >= 0
1123                         ? new_index (NULL, ic->candidate_index - start,
1124                                      end - start - 1, MPLIST_SYMBOL (args),
1125                                      NULL)
1126                         : MPLIST_INTEGER (args)));
1127               if (idx < 0)
1128                 {
1129                   find_candidates_group (mtext_property_value (prop), -1,
1130                                          NULL, &end, NULL);
1131                   idx = end - 1;
1132                 }
1133               else if (idx >= end
1134                        && MPLIST_TAIL_P (MPLIST_NEXT (group)))
1135                 idx = 0;
1136             }
1137           else
1138             {
1139               int ingroup_index = idx - start;
1140               int len;
1141
1142               group = mtext_property_value (prop);
1143               len = mplist_length (group);
1144               if (code == '[')
1145                 {
1146                   gindex--;
1147                   if (gindex < 0)
1148                     gindex = len - 1;;
1149                 }
1150               else
1151                 {
1152                   gindex++;
1153                   if (gindex >= len)
1154                     gindex = 0;
1155                 }
1156               for (idx = 0; gindex > 0; gindex--, group = MPLIST_NEXT (group))
1157                 idx += (MPLIST_MTEXT_P (group)
1158                         ? mtext_nchars (MPLIST_MTEXT (group))
1159                         : mplist_length (MPLIST_PLIST (group)));
1160               len = (MPLIST_MTEXT_P (group)
1161                      ? mtext_nchars (MPLIST_MTEXT (group))
1162                      : mplist_length (MPLIST_PLIST (group)));
1163               if (ingroup_index >= len)
1164                 ingroup_index = len - 1;
1165               idx += ingroup_index;
1166             }
1167           update_candidate (ic, prop, idx);
1168         }
1169       else if (name == Mshow)
1170         ic->candidate_show = 1;
1171       else if (name == Mhide)
1172         ic->candidate_show = 0;
1173       else if (name == Mdelete)
1174         {
1175           int len = mtext_nchars (ic->preedit);
1176           int to = (MPLIST_SYMBOL_P (args)
1177                     ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
1178                                  ic->preedit)
1179                     : MPLIST_INTEGER (args));
1180
1181           if (to < 0)
1182             to = 0;
1183           else if (to > len)
1184             to = len;
1185           if (to < ic->cursor_pos)
1186             preedit_delete (ic, to, ic->cursor_pos);
1187           else if (to > ic->cursor_pos)
1188             preedit_delete (ic, ic->cursor_pos, to);
1189         }
1190       else if (name == Mmove)
1191         {
1192           int len = mtext_nchars (ic->preedit);
1193           int pos
1194             = (MPLIST_SYMBOL_P (args)
1195                ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
1196                             ic->preedit)
1197                : MPLIST_INTEGER (args));
1198
1199           if (pos < 0)
1200             pos = 0;
1201           else if (pos > len)
1202             pos = len;
1203           if (pos != ic->cursor_pos)
1204             {
1205               ic->cursor_pos = pos;
1206               ic->preedit_changed = 1;
1207             }
1208         }
1209       else if (name == Mmark)
1210         {
1211           int code = marker_code (MPLIST_SYMBOL (args));
1212
1213           if (code < 0)
1214             mplist_put (ic_info->markers, MPLIST_SYMBOL (args),
1215                         (void *) ic->cursor_pos);
1216         }
1217       else if (name == Mpushback)
1218         {
1219           int num = MPLIST_INTEGER (args);
1220
1221           if (num > 0)
1222             ic_info->key_head -= num;
1223           else
1224             ic_info->key_head = num;
1225           if (ic_info->key_head > ic_info->used)
1226             ic_info->key_head = ic_info->used;
1227         }
1228       else if (name == Mcall)
1229         {
1230           MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1231           MIMExternalFunc func = NULL;
1232           MSymbol module, func_name;
1233           MPlist *func_args, *val;
1234           int ret = 0;
1235
1236           module = MPLIST_SYMBOL (args);
1237           args = MPLIST_NEXT (args);
1238           func_name = MPLIST_SYMBOL (args);
1239
1240           if (im_info->externals)
1241             {
1242               MIMExternalModule *external
1243                 = (MIMExternalModule *) mplist_get (im_info->externals,
1244                                                     module);
1245               if (external)
1246                 func = (MIMExternalFunc) mplist_get (external->func_list,
1247                                                      func_name);
1248             }
1249           if (! func)
1250             continue;
1251           func_args = mplist ();
1252           mplist_add (func_args, Mt, ic);
1253           MPLIST_DO (args, MPLIST_NEXT (args))
1254             {
1255               int code;
1256
1257               if (MPLIST_KEY (args) == Msymbol
1258                   && MPLIST_KEY (args) != Mnil
1259                   && (code = marker_code (MPLIST_SYMBOL (args))) >= 0)
1260                 {
1261                   code = new_index (ic, ic->cursor_pos, 
1262                                     mtext_nchars (ic->preedit),
1263                                     MPLIST_SYMBOL (args), ic->preedit);
1264                   mplist_add (func_args, Minteger, (void *) code);
1265                 }
1266               else
1267                 mplist_add (func_args, MPLIST_KEY (args), MPLIST_VAL (args));
1268             }
1269           val = (func) (func_args);
1270           M17N_OBJECT_UNREF (func_args);
1271           if (val && ! MPLIST_TAIL_P (val))
1272             ret = take_action_list (ic, val);
1273           M17N_OBJECT_UNREF (val);
1274           if (ret < 0)
1275             return ret;
1276         }
1277       else if (name == Mshift)
1278         {
1279           shift_state (ic, MPLIST_SYMBOL (args));
1280         }
1281       else if (name == Mundo)
1282         {
1283           MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1284           int unhandle = 0;
1285
1286           mtext_reset (ic->preedit);
1287           mtext_reset (ic_info->preedit_saved);
1288           ic->cursor_pos = ic_info->state_pos = 0;
1289           ic_info->state_key_head = ic_info->key_head = 0;
1290           ic_info->used -= 2;
1291           if (ic_info->used < 0)
1292             {
1293               ic_info->used = 0;
1294               unhandle = 1;
1295             }
1296           shift_state (ic, ((MIMState *) MPLIST_VAL (im_info->states))->name);
1297           if (unhandle)
1298             return -1;
1299           break;
1300         }
1301       else if (name == Mset || name == Madd || name == Msub
1302                || name == Mmul || name == Mdiv)
1303         {
1304           MSymbol sym = MPLIST_SYMBOL (args);
1305           int val1 = (int) mplist_get (ic_info->vars, sym), val2;
1306
1307           args = MPLIST_NEXT (args);
1308           val2 = integer_value (ic, args);
1309           if (name == Mset)
1310             val1 = val2;
1311           else if (name == Madd)
1312             val1 += val2;
1313           else if (name == Msub)
1314             val1 -= val2;
1315           else if (name == Mmul)
1316             val1 *= val2;
1317           else
1318             val1 /= val2;
1319           mplist_put (ic_info->vars, sym, (void *) val1);
1320           MDEBUG_PRINT2 ("(%s=%d)", MSYMBOL_NAME (sym), val1);
1321         }
1322       else if (name == Mequal || name == Mless || name == Mgreater)
1323         {
1324           int val1, val2;
1325           MPlist *actions1, *actions2;
1326           int ret = 0;
1327
1328           val1 = integer_value (ic, args);
1329           args = MPLIST_NEXT (args);
1330           val2 = integer_value (ic, args);
1331           args = MPLIST_NEXT (args);
1332           actions1 = MPLIST_PLIST (args);
1333           args = MPLIST_NEXT (args);
1334           if (MPLIST_TAIL_P (args))
1335             actions2 = NULL;
1336           else
1337             actions2 = MPLIST_PLIST (args);
1338           if (name == Mequal ? val1 == val2
1339               : name == Mless ? val1 < val2
1340               : val1 > val2)
1341             ret = take_action_list (ic, actions1);
1342           else if (actions2)
1343             ret = take_action_list (ic, actions2);
1344           if (ret < 0)
1345             return ret;
1346         }
1347       else
1348         {
1349           MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1350           MPlist *actions;
1351
1352           if (im_info->macros
1353               && (actions = mplist_get (im_info->macros, name)))
1354             {
1355               if (take_action_list (ic, actions) < 0)
1356                 return -1;
1357             };
1358         }
1359     }
1360
1361   prop = NULL;
1362   ic->candidate_list = NULL;
1363   if (ic->cursor_pos > 0
1364       && (prop = mtext_get_property (ic->preedit, ic->cursor_pos - 1,
1365                                      Mcandidate_list)))
1366     {
1367       ic->candidate_list = mtext_property_value (prop);
1368       ic->candidate_index
1369         = (int) mtext_get_prop (ic->preedit, ic->cursor_pos - 1,
1370                                 Mcandidate_index);
1371       ic->candidate_from = mtext_property_start (prop);
1372       ic->candidate_to = mtext_property_end (prop);
1373     }
1374
1375   ic->candidates_changed |= (candidate_list != ic->candidate_list
1376                              || candidate_index != ic->candidate_index
1377                              || candidate_show != ic->candidate_show);
1378   return 0;
1379 }
1380
1381
1382 /* Handle the input key KEY in the current state and map specified in
1383    the input context IC.  If KEY is handled correctly, return 0.
1384    Otherwise, return -1.  */
1385
1386 static int
1387 handle_key (MInputContext *ic)
1388 {
1389   MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1390   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1391   MIMMap *map = ic_info->map;
1392   MIMMap *submap = NULL;
1393   MSymbol key = ic_info->keys[ic_info->key_head];
1394   int i;
1395
1396   MDEBUG_PRINT2 ("[IM] handle `%s' in state %s", 
1397                  MSYMBOL_NAME (key), MSYMBOL_NAME (ic_info->state->name));
1398
1399   if (map->submaps)
1400     {
1401       submap = mplist_get (map->submaps, key);
1402       if (! submap && (key = msymbol_get (key, M_key_alias)) != Mnil)
1403         submap = mplist_get (map->submaps, key);
1404     }
1405
1406   if (submap)
1407     {
1408       MDEBUG_PRINT (" submap-found");
1409       mtext_cpy (ic->preedit, ic_info->preedit_saved);
1410       ic->cursor_pos = ic_info->state_pos;
1411       ic_info->key_head++;
1412       ic_info->map = map = submap;
1413       if (map->map_actions)
1414         {
1415           MDEBUG_PRINT (" map-actions:");
1416           if (take_action_list (ic, map->map_actions) < 0)
1417             return -1;
1418         }
1419       else if (map->submaps)
1420         {
1421           for (i = ic_info->state_key_head; i < ic_info->key_head; i++)
1422             {
1423               MSymbol key = ic_info->keys[i];
1424               char *name = msymbol_name (key);
1425
1426               if (! name[0] || ! name[1])
1427                 mtext_ins_char (ic->preedit, ic->cursor_pos++, name[0], 1);
1428             }
1429           ic->preedit_changed = 1;
1430         }
1431
1432       /* If this is the terminal map or we have shifted to another
1433          state, perform branch actions (if any).  */
1434       if (! map->submaps || map != ic_info->map)
1435         {
1436           if (map->branch_actions)
1437             {
1438               MDEBUG_PRINT (" branch-actions:");
1439               if (take_action_list (ic, map->branch_actions) < 0)
1440                 return -1;
1441             }
1442           /* If MAP is still not the root map, shift to the current
1443              state.  */
1444           if (ic_info->map != ic_info->state->map)
1445             shift_state (ic, ic_info->state->name);
1446         }
1447       MDEBUG_PRINT ("\n");
1448     }
1449   else
1450     {
1451       /* MAP can not handle KEY.  */
1452
1453       /* If MAP is the root map of the initial state, it means that
1454          the current input method can not handle KEY.  */
1455       if (map == ((MIMState *) MPLIST_VAL (im_info->states))->map)
1456         {
1457           MDEBUG_PRINT (" unhandled\n");
1458           return -1;
1459         }
1460
1461       if (map != ic_info->state->map)
1462         {
1463           /* If MAP is not the root map... */
1464           /* If MAP has branch actions, perform them.  */
1465           if (map->branch_actions)
1466             {
1467               MDEBUG_PRINT (" branch-actions:");
1468               take_action_list (ic, map->branch_actions);
1469             }
1470           /* If MAP is still not the root map, shift to the current
1471              state. */
1472           if (ic_info->map != ic_info->state->map)
1473             {
1474               shift_state (ic, ic_info->state->name);
1475               /* If MAP has branch_actions, perform them.  */
1476               if (ic_info->map->branch_actions)
1477                 {
1478                   MDEBUG_PRINT (" init-actions:");
1479                   take_action_list (ic, ic_info->map->branch_actions);
1480                 }
1481             }
1482         }
1483       else
1484         {
1485           /* MAP is the root map, perform branch actions (if any) or
1486              shift to the initial state.  */
1487           if (map->branch_actions)
1488             {
1489               MDEBUG_PRINT (" branch-actions:");
1490               take_action_list (ic, map->branch_actions);
1491             }
1492           else
1493             shift_state (ic,
1494                          ((MIMState *) MPLIST_VAL (im_info->states))->name);
1495         }
1496       MDEBUG_PRINT ("\n");
1497     }
1498   return 0;
1499 }
1500
1501 static void
1502 reset_ic (MInputContext *ic, MSymbol ignore)
1503 {
1504   MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1505   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1506
1507   if (im_info->states)
1508     /* Shift to the initial state.  */
1509     shift_state (ic, Mnil);
1510   else
1511     ic_info->state = NULL;
1512   MLIST_RESET (ic_info);
1513   ic_info->map = ic_info->state ? ic_info->state->map : NULL;
1514   ic_info->state_key_head = ic_info->key_head = 0;
1515   ic_info->key_unhandled = 0;
1516   ic->cursor_pos = ic_info->state_pos = 0;
1517   ic->status = ic_info->state ? ic_info->state->title : NULL;
1518   if (! ic->status)
1519     ic->status = im_info->title;
1520   ic->candidate_list = NULL;
1521   ic->candidate_show = 0;
1522   ic->status_changed = ic->preedit_changed = ic->candidates_changed = 1;
1523   if (ic_info->map && ic_info->map->map_actions)
1524     take_action_list (ic, ic_info->map->map_actions);
1525 }
1526
1527 static int
1528 open_im (MInputMethod *im)
1529 {
1530   MDatabase *mdb;
1531   MInputMethodInfo *im_info;
1532   MPlist *plist;
1533   int result;
1534
1535   mdb = mdatabase_find (Minput_method, im->language, im->name, Mnil);
1536   if (! mdb)
1537     return -1;
1538   plist = mdatabase_load (mdb);
1539   if (! plist)
1540     MERROR (MERROR_IM, -1);
1541   MSTRUCT_CALLOC (im_info, MERROR_IM);
1542   im->info = im_info;
1543   result = load_input_method (im->language, im->name, plist, im_info);
1544   M17N_OBJECT_UNREF (plist);
1545   if (result < 0)
1546     MERROR (MERROR_IM, -1);
1547   return 0;
1548 }
1549
1550 static void
1551 close_im (MInputMethod *im)
1552 {
1553   MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
1554   MPlist *plist;
1555
1556   if (im_info->title)
1557     M17N_OBJECT_UNREF (im_info->title);
1558   if (im_info->states)
1559     {
1560       MPLIST_DO (plist, im_info->states)
1561         {
1562           MIMState *state = (MIMState *) MPLIST_VAL (plist);
1563
1564           if (state->title)
1565             M17N_OBJECT_UNREF (state->title);
1566           if (state->map)
1567             free_map (state->map);
1568           free (state);
1569         }
1570       M17N_OBJECT_UNREF (im_info->states);
1571     }
1572
1573   if (im_info->macros)
1574     {
1575       MPLIST_DO (plist, im_info->macros)
1576         M17N_OBJECT_UNREF (MPLIST_VAL (plist)); 
1577       M17N_OBJECT_UNREF (im_info->macros);
1578     }
1579
1580   if (im_info->externals)
1581     {
1582       MPLIST_DO (plist, im_info->externals)
1583         {
1584           MIMExternalModule *external = MPLIST_VAL (plist);
1585
1586           dlclose (external->handle);
1587           M17N_OBJECT_UNREF (external->func_list);
1588           free (external);
1589           MPLIST_KEY (plist) = Mt;
1590         }
1591       M17N_OBJECT_UNREF (im_info->externals);
1592     }
1593   free (im_info);
1594   im->info = NULL;
1595 }
1596
1597
1598 static int
1599 create_ic (MInputContext *ic)
1600 {
1601   MInputMethod *im = ic->im;
1602   MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
1603   MInputContextInfo *ic_info;
1604
1605   if (ic->info)
1606     ic_info = (MInputContextInfo *) ic->info;
1607   else
1608     {
1609       MSTRUCT_CALLOC (ic_info, MERROR_IM);
1610       ic->info = ic_info;
1611     }
1612   MLIST_INIT1 (ic_info, keys, 8);
1613   ic_info->markers = mplist ();
1614   ic_info->vars = mplist ();
1615   ic_info->preedit_saved = mtext ();
1616   if (im_info->externals)
1617     {
1618       MPlist *func_args = mplist (), *plist;
1619
1620       mplist_add (func_args, Mt, ic);
1621       MPLIST_DO (plist, im_info->externals)
1622         {
1623           MIMExternalModule *external = MPLIST_VAL (plist);
1624           MIMExternalFunc func
1625             = (MIMExternalFunc) mplist_get (external->func_list, Minit);
1626
1627           if (func)
1628             (func) (func_args);
1629         }
1630       M17N_OBJECT_UNREF (func_args);
1631     }
1632   reset_ic (ic, Mnil);
1633   return 0;
1634 }
1635
1636 static void
1637 destroy_ic (MInputContext *ic)
1638 {
1639   MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1640   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1641
1642   if (im_info->externals)
1643     {
1644       MPlist *func_args = mplist (), *plist;
1645
1646       mplist_add (func_args, Mt, ic);
1647       MPLIST_DO (plist, im_info->externals)
1648         {
1649           MIMExternalModule *external = MPLIST_VAL (plist);
1650           MIMExternalFunc func
1651             = (MIMExternalFunc) mplist_get (external->func_list, Mfini);
1652
1653           if (func)
1654             (func) (func_args);
1655         }
1656       M17N_OBJECT_UNREF (func_args);
1657     }
1658   MLIST_FREE1 (ic_info, keys);
1659   M17N_OBJECT_UNREF (ic_info->preedit_saved);
1660   M17N_OBJECT_UNREF (ic_info->markers);
1661   M17N_OBJECT_UNREF (ic_info->vars);
1662   free (ic->info);
1663 }
1664
1665
1666 /** Handle the input key KEY in the current state and map of IC->info.
1667     If KEY is handled but no text is produced, return 0, otherwise
1668     return 1.
1669
1670     Ignore ARG.  */
1671
1672 static int
1673 filter (MInputContext *ic, MSymbol key, void *arg)
1674 {
1675   MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1676   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1677   int i = 0;
1678
1679   if (! ic_info->state)
1680     {
1681       ic_info->key_unhandled = 1;
1682       return 0;
1683     }
1684   mtext_reset (ic->produced);
1685   ic->status_changed = ic->preedit_changed = ic->candidates_changed = 0;
1686   MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
1687   ic_info->key_unhandled = 0;
1688   do {
1689     if (handle_key (ic) < 0)
1690       {
1691         /* KEY was not handled.  Reset the status and break the
1692            loop.  */
1693         reset_ic (ic, Mnil);
1694         /* This forces returning 1.  */
1695         ic_info->key_unhandled = 1;
1696         break;
1697       }
1698     if (i++ == 100)
1699       {
1700         mdebug_hook ();
1701         reset_ic (ic, Mnil);
1702         ic_info->key_unhandled = 1;
1703         break;
1704       }
1705     /* Break the loop if all keys were handled.  */
1706   } while (ic_info->key_head < ic_info->used);
1707
1708   /* If the current map is the root of the initial state, we should
1709      produce any preedit text in ic->produced.  */
1710   if (ic_info->map == ((MIMState *) MPLIST_VAL (im_info->states))->map
1711       && mtext_nchars (ic->preedit) > 0)
1712     shift_state (ic, ((MIMState *) MPLIST_VAL (im_info->states))->name);
1713
1714   if (mtext_nchars (ic->produced) > 0)
1715     {
1716       MSymbol lang = msymbol_get (ic->im->language, Mlanguage);
1717
1718       if (lang != Mnil)
1719         mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
1720                         Mlanguage, ic->im->language);
1721     }
1722
1723   return (! ic_info->key_unhandled && mtext_nchars (ic->produced) == 0);
1724 }
1725
1726
1727 /** Return 1 if the last event or key was not handled, otherwise
1728     return 0.
1729
1730     There is no need of looking up because ic->produced should already
1731     contain the produced text (if any).
1732
1733     Ignore KEY.  */
1734
1735 static int
1736 lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
1737 {
1738   mtext_cat (mt, ic->produced);
1739   mtext_reset (ic->produced);
1740   return (((MInputContextInfo *) ic->info)->key_unhandled ? -1 : 0);
1741 }
1742
1743 static MPlist *load_im_info_keys;
1744
1745 static MPlist *
1746 load_im_info (MSymbol language, MSymbol name, MSymbol key)
1747 {
1748   MDatabase *mdb;
1749   MPlist *plist;
1750
1751   if (language == Mnil || name == Mnil)
1752     MERROR (MERROR_IM, NULL);
1753
1754   mdb = mdatabase_find (Minput_method, language, name, Mnil);
1755   if (! mdb)
1756     MERROR (MERROR_IM, NULL);
1757   mplist_push (load_im_info_keys, key, Mt);
1758   plist = mdatabase__load_for_keys (mdb, load_im_info_keys);
1759   mplist_pop (load_im_info_keys);
1760   return plist;
1761 }
1762
1763 \f
1764 /* Input method command handler.  */
1765
1766 /* List of all (global and local) commands. 
1767    (LANG:(IM-NAME:(COMMAND ...) ...) ...) ...
1768    COMMAND is CMD-NAME:(mtext:DESCRIPTION plist:KEYSEQ ...))
1769    Global commands are storead as (t (t COMMAND ...))  */
1770 static MPlist *command_list;
1771
1772 /* Check if PLIST is a valid command key sequence.
1773    PLIST must be NULL or:
1774    [ symbol:KEY | integer:KEY ] ...  */
1775
1776 static int
1777 check_command_keyseq (MPlist *plist)
1778 {
1779   if (! plist)
1780     return 0;
1781   MPLIST_DO (plist, plist)
1782     {
1783       if (MPLIST_SYMBOL_P (plist))
1784         continue;
1785       else if (MPLIST_INTEGER_P (plist))
1786         {
1787           int n = MPLIST_INTEGER (plist);
1788
1789           if (n < 0 || n > 9)
1790             return -1;
1791           MPLIST_KEY (plist) = Msymbol;
1792           MPLIST_VAL (plist) = one_char_symbol['0' + 9];
1793         }
1794       else
1795         return -1;
1796     }
1797   return 0;
1798 }
1799
1800 static MText *
1801 get_description_advance (MPlist *plist)
1802 {
1803   MText *mt;
1804   int pos;
1805
1806   if (! MPLIST_MTEXT_P (plist))
1807     return NULL;
1808   mt = mplist_pop (plist);
1809   pos = mtext_chr (mt, '\n'); 
1810   if (pos > 0)
1811     {
1812       MText *detail = mtext_copy (mtext (), 0, mt, pos + 1, mtext_nchars (mt));
1813       mtext_del (mt, pos, mtext_nchars (mt));
1814       mtext_put_prop (mt, 0, pos, Mdetail_text, detail);
1815       M17N_OBJECT_UNREF (detail);
1816     }
1817   return mt;
1818 }
1819
1820 static MPlist *
1821 parse_command_list (MPlist *plist, MPlist *global_list)
1822 {
1823   MPlist *val = mplist ();
1824
1825   /* PLIST ::= (sym:CMD mtext:DESCRIPTION ? (sym:KEY ...) ...) ... */
1826   MPLIST_DO (plist, plist)
1827     {
1828       MSymbol cmd;
1829       MText *mt;
1830       MPlist *this_val, *pl, *p;
1831
1832       if (! MPLIST_PLIST_P (plist))
1833         continue;
1834       pl = MPLIST_PLIST (plist);
1835       if (! MPLIST_SYMBOL_P (pl))
1836         continue;
1837       cmd = MPLIST_SYMBOL (pl);
1838       pl = MPLIST_NEXT (pl);
1839       mt = get_description_advance (pl);
1840       this_val = mplist ();
1841
1842       if (! mt && global_list)
1843         {
1844           /* Get the description from global_list.  */
1845           p = mplist_get (global_list, cmd);
1846           if (p && MPLIST_MTEXT (p))
1847             {
1848               mt = MPLIST_MTEXT (p);
1849               M17N_OBJECT_REF (mt);
1850             }
1851         }
1852       if (! mt)
1853         mt = mtext ();
1854       mplist_add (this_val, Mtext, mt);
1855       M17N_OBJECT_UNREF (mt);
1856
1857       /* PL ::= (sym:KEY ...) ... */
1858       MPLIST_DO (pl, pl)
1859         {
1860           if (MPLIST_PLIST_P (pl)
1861               && check_command_keyseq (MPLIST_PLIST (pl)) >= 0)
1862             /* All the elements are valid keys.  */
1863             mplist_add (this_val, Mplist, MPLIST_PLIST (pl));
1864         }
1865
1866       mplist_put (val, cmd, this_val);
1867     }
1868   return val;
1869 }
1870
1871 static MPlist *
1872 get_command_list (MSymbol language, MSymbol name)
1873 {
1874   MPlist *per_lang;
1875   MPlist *plist, *pl;
1876
1877   if (name == Mnil)
1878     language = name = Mt;
1879
1880   if (! command_list)
1881     {
1882       MDatabase *mdb = mdatabase_find (msymbol ("input"), M_command,
1883                                        Mnil, Mnil);
1884
1885       if (mdb && (plist = mdatabase_load (mdb)))
1886         {
1887           pl = parse_command_list (plist, NULL);
1888           M17N_OBJECT_UNREF (plist);
1889         }
1890       else
1891         pl = mplist ();
1892       plist = mplist ();
1893       mplist_add (plist, Mt, pl);
1894       command_list = mplist ();
1895       mplist_add (command_list, Mt, plist);
1896     }
1897
1898   per_lang = mplist_get (command_list, language);
1899   if (per_lang)
1900     {
1901       plist = mplist_find_by_key (per_lang, name);
1902       if (plist)
1903         return (MPLIST_VAL (plist));
1904     }
1905   else
1906     {
1907       per_lang = mplist ();
1908       mplist_add (command_list, language, per_lang);
1909     }
1910
1911   /* Now we are sure that we are loading per-im info.  */
1912   /* Get the global command list.  */
1913   plist = load_im_info (language, name, M_command);
1914   if (! plist || mplist_key (plist) == Mnil)
1915     {
1916       if (! plist)
1917         plist = mplist ();
1918       mplist_add (per_lang, name, plist);
1919       return plist;
1920     }
1921   pl = parse_command_list (mplist_value (plist),
1922                            mplist_get ((MPlist *) mplist_get (command_list, Mt),
1923                                        Mt));
1924   M17N_OBJECT_UNREF (plist);
1925   mplist_put (per_lang, name, pl);
1926   return pl;
1927 }
1928
1929 \f
1930 /* Input method variable handler.  */
1931
1932 /* List of all variables. 
1933    (LANG:(IM-NAME:(VAR ...) ...) ...) ...
1934    VAR is VAR-NAME:(mtext:DESCRIPTION TYPE:VALUE ...))  */
1935
1936 static MPlist *variable_list;
1937
1938 static MPlist *
1939 parse_variable_list (MPlist *plist)
1940 {
1941   MPlist *val = mplist (), *pl, *p;
1942
1943   /* PLIST ::= (sym:VAR mtext:DESCRIPTION TYPE:INIT-VAL ...) ...  */
1944   MPLIST_DO (plist, plist)
1945     {
1946       MSymbol var, type;
1947       MText *mt;
1948       MPlist *this_val;
1949
1950       if (! MPLIST_PLIST_P (plist))
1951         continue;
1952       pl = MPLIST_PLIST (plist);
1953       if (! MPLIST_SYMBOL_P (pl))
1954         continue;
1955       var = MPLIST_SYMBOL (pl);
1956       pl = MPLIST_NEXT (pl);
1957       mt = get_description_advance (pl);
1958       if (! mt || MPLIST_TAIL_P (pl))
1959         continue;
1960       this_val = mplist ();
1961       mplist_add (this_val, Mtext, mt);
1962       M17N_OBJECT_UNREF (mt);
1963       type = MPLIST_KEY (pl);
1964       mplist_add (this_val, type, MPLIST_VAL (pl));
1965       MPLIST_DO (pl, MPLIST_NEXT (pl))
1966         {
1967           if (type != MPLIST_KEY (pl)
1968               && (type != Minteger || ! MPLIST_PLIST_P (pl)))
1969             break;
1970           if (MPLIST_PLIST_P (pl))
1971             {
1972               MPLIST_DO (p, MPLIST_PLIST (pl))
1973                 if (! MPLIST_INTEGER_P (p))
1974                   break;
1975               if (! MPLIST_TAIL_P (p))
1976                 break;
1977             }
1978           mplist_add (this_val, MPLIST_KEY (pl), MPLIST_VAL (pl));
1979         }
1980
1981       mplist_put (val, var, this_val);
1982     }
1983   return val;
1984 }
1985
1986
1987 static MPlist *
1988 get_variable_list (MSymbol language, MSymbol name)
1989 {
1990   MPlist *per_lang;
1991   MPlist *plist, *pl;
1992
1993   if (language == Mnil || name == Mnil)
1994     MERROR (MERROR_IM, NULL);
1995   if (! variable_list)
1996     variable_list = mplist ();
1997   per_lang = mplist_get (variable_list, language);
1998   if (per_lang)
1999     {
2000       plist = mplist_find_by_key (per_lang, name);
2001       if (plist)
2002         return (MPLIST_VAL (plist));
2003     }
2004   else
2005     {
2006       per_lang = mplist ();
2007       mplist_add (variable_list, language, per_lang);
2008     }
2009   plist = load_im_info (language, name, M_variable);
2010   if (! plist || mplist_key (plist) == Mnil)
2011     {
2012       if (! plist)
2013         plist = mplist ();
2014       mplist_add (per_lang, name, plist);
2015       return plist;
2016     }
2017   pl = parse_variable_list (mplist_value (plist));
2018   M17N_OBJECT_UNREF (plist);
2019   mplist_put (per_lang, name, pl);
2020   return pl;
2021 }
2022
2023 static void
2024 input_method_hook (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
2025 {
2026   MPlist *plist, *pl, *p;
2027   char path[PATH_MAX];
2028
2029   /* Cancel the hook.  */
2030   msymbol_put (tag0, M_database_hook, NULL);
2031   tag3 = Mnil;
2032
2033   mplist_push (load_im_info_keys, M_description, Mt);
2034   MPLIST_DO (plist, mdatabase__dir_list)
2035     {
2036       char *dirname = (char *) MPLIST_VAL (plist);
2037       int dirlen;
2038       DIR *dir = opendir (dirname);
2039       struct dirent *dp;
2040
2041       if (! dir)
2042         continue;
2043       dirlen = strlen (dirname);
2044       strcpy (path, dirname);
2045       while ((dp = readdir (dir)) != NULL)
2046         {
2047           /* We can't trust dp->d_nameln.  */
2048           int len = strlen (dp->d_name);
2049           FILE *fp;
2050
2051           if (len > 4 && memcmp (dp->d_name + len - 4, ".mim", 4) == 0)
2052             {
2053               strcpy (path + dirlen, dp->d_name);
2054               fp = fopen (path, "r");
2055               if (! fp)
2056                 continue;
2057               pl = mplist__from_file (fp, load_im_info_keys);
2058               fclose (fp);
2059               if (pl)
2060                 {
2061                   if (MPLIST_PLIST_P (pl))
2062                     {
2063                       p = MPLIST_PLIST (pl);
2064                       p = MPLIST_NEXT (p);
2065                       if (MPLIST_SYMBOL_P (p))
2066                         {
2067                           tag1 = MPLIST_VAL (p);
2068                           p = MPLIST_NEXT (p);
2069                           if (MPLIST_SYMBOL_P (p))
2070                             {
2071                               tag2 = MPLIST_VAL (p);
2072                               mdatabase_define (tag0, tag1, tag2, tag3,
2073                                                 NULL, path);
2074                             }
2075                         }
2076                     }
2077                   M17N_OBJECT_UNREF (pl);
2078                 }
2079             }
2080         }
2081       closedir (dir);
2082     }
2083   mplist_pop (load_im_info_keys);
2084 }
2085
2086
2087 /* Support functions for mdebug_dump_im.  */
2088
2089 static void
2090 dump_im_map (MPlist *map_list, int indent)
2091 {
2092   char *prefix;
2093   MSymbol key = MPLIST_KEY (map_list);
2094   MIMMap *map = (MIMMap *) MPLIST_VAL (map_list);
2095
2096   prefix = (char *) alloca (indent + 1);
2097   memset (prefix, 32, indent);
2098   prefix[indent] = '\0';
2099
2100   fprintf (stderr, "(\"%s\" ", msymbol_name (key));
2101   if (map->map_actions)
2102     mdebug_dump_plist (map->map_actions, indent + 2);
2103   if (map->submaps)
2104     {
2105       MPLIST_DO (map_list, map->submaps)
2106         {
2107           fprintf (stderr, "\n%s  ", prefix);
2108           dump_im_map (map_list, indent + 2);
2109         }
2110     }
2111   if (map->branch_actions)
2112     {
2113       fprintf (stderr, "\n%s  (branch\n%s    ", prefix, prefix);
2114       mdebug_dump_plist (map->branch_actions, indent + 4);
2115       fprintf (stderr, ")");      
2116     }
2117   fprintf (stderr, ")");
2118 }
2119
2120
2121 static void
2122 dump_im_state (MIMState *state, int indent)
2123 {
2124   char *prefix;
2125   MPlist *map_list;
2126
2127   prefix = (char *) alloca (indent + 1);
2128   memset (prefix, 32, indent);
2129   prefix[indent] = '\0';
2130
2131   fprintf (stderr, "(%s", msymbol_name (state->name));
2132   if (state->map->submaps)
2133     {
2134       MPLIST_DO (map_list, state->map->submaps)
2135         {
2136           fprintf (stderr, "\n%s  ", prefix);
2137           dump_im_map (map_list, indent + 2);
2138         }
2139     }
2140   fprintf (stderr, ")");
2141 }
2142
2143 \f
2144
2145 int
2146 minput__init ()
2147 {
2148   char *key_names[32]
2149     = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2150         "BackSpace", "Tab", "Linefeed", "Clear", NULL, "Return", NULL, NULL,
2151         NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2152         NULL, NULL, NULL, "Escape", NULL, NULL, NULL, NULL };
2153   char buf[6], buf2[256];
2154   int i;
2155   MPlist *plist;
2156
2157   Minput_method = msymbol ("input-method");
2158   msymbol_put (Minput_method, M_database_hook, (void *) input_method_hook);
2159   Minput_driver = msymbol ("input-driver");
2160   Mtitle = msymbol ("title");
2161   Mmacro = msymbol ("macro");
2162   Mmodule = msymbol ("module");
2163   Mmap = msymbol ("map");
2164   Mstate = msymbol ("state");
2165   Minsert = msymbol ("insert");
2166   Mdelete = msymbol ("delete");
2167   Mmove = msymbol ("move");
2168   Mmark = msymbol ("mark");
2169   Mpushback = msymbol ("pushback");
2170   Mundo = msymbol ("undo");
2171   Mcall = msymbol ("call");
2172   Mshift = msymbol ("shift");
2173   Mselect = msymbol ("select");
2174   Mshow = msymbol ("show");
2175   Mhide = msymbol ("hide");
2176   Mset = msymbol ("set");
2177   Madd = msymbol ("add");
2178   Msub = msymbol ("sub");
2179   Mmul = msymbol ("mul");
2180   Mdiv = msymbol ("div");
2181   Mequal = msymbol ("=");
2182   Mless = msymbol ("<");
2183   Mgreater = msymbol (">");
2184
2185   Minput_preedit_start = msymbol ("input-preedit-start");
2186   Minput_preedit_done = msymbol ("input-preedit-done");
2187   Minput_preedit_draw = msymbol ("input-preedit-draw");
2188   Minput_status_start = msymbol ("input-status-start");
2189   Minput_status_done = msymbol ("input-status-done");
2190   Minput_status_draw = msymbol ("input-status-draw");
2191   Minput_candidates_start = msymbol ("input-candidates-start");
2192   Minput_candidates_done = msymbol ("input-candidates-done");
2193   Minput_candidates_draw = msymbol ("input-candidates-draw");
2194   Minput_set_spot = msymbol ("input-set-spot");
2195   Minput_toggle = msymbol ("input-toggle");
2196   Minput_reset = msymbol ("input-reset");
2197
2198   Mcandidate_list = msymbol_as_managing_key ("  candidate-list");
2199   Mcandidate_index = msymbol ("  candidate-index");
2200
2201   Minit = msymbol ("init");
2202   Mfini = msymbol ("fini");
2203
2204   M_key_alias = msymbol ("  key-alias");
2205   M_description = msymbol ("description");
2206   M_command = msymbol ("command");
2207   M_variable = msymbol ("variable");
2208
2209   Mdetail_text = msymbol_as_managing_key ("  detail-text");
2210
2211   load_im_info_keys = mplist ();
2212   plist = mplist_add (load_im_info_keys, Mmap, Mnil);
2213   plist = mplist_add (plist, Mstate, Mnil);
2214   plist = mplist_add (plist, Mmacro, Mnil);
2215   plist = mplist_add (plist, Mmodule, Mnil);
2216
2217   buf[0] = 'C';
2218   buf[1] = '-';
2219   buf[3] = '\0';
2220   for (i = 0, buf[2] = '@'; i < ' '; i++, buf[2]++)
2221     {
2222       one_char_symbol[i] = msymbol (buf);
2223       if (key_names[i])
2224         msymbol_put (one_char_symbol[i], M_key_alias,  msymbol (key_names[i]));
2225     }
2226   for (buf[2] = i; i < 127; i++, buf[2]++)
2227     one_char_symbol[i] = msymbol (buf + 2);
2228   one_char_symbol[i++] = msymbol ("Delete");
2229   buf[2] = 'M';
2230   buf[3] = '-';
2231   buf[5] = '\0';
2232   buf2[0] = 'M';
2233   buf2[1] = '-';
2234   for (buf[4] = '@'; i < 160; i++, buf[4]++)
2235     {
2236       one_char_symbol[i] = msymbol (buf);
2237       if (key_names[i - 128])
2238         {
2239           strcpy (buf2 + 2, key_names[i - 128]);
2240           msymbol_put (one_char_symbol[i], M_key_alias,  msymbol (buf2));
2241         }
2242     }
2243   for (buf[4] = i - 128; i < 255; i++, buf[4]++)
2244     one_char_symbol[i] = msymbol (buf + 2);
2245   one_char_symbol[i] = msymbol ("M-Delete");
2246
2247   command_list = variable_list = NULL;
2248
2249   minput_default_driver.open_im = open_im;
2250   minput_default_driver.close_im = close_im;
2251   minput_default_driver.create_ic = create_ic;
2252   minput_default_driver.destroy_ic = destroy_ic;
2253   minput_default_driver.filter = filter;
2254   minput_default_driver.lookup = lookup;
2255   minput_default_driver.callback_list = mplist ();
2256   mplist_put (minput_default_driver.callback_list, Minput_reset,
2257               (void *) reset_ic);
2258   minput_driver = &minput_default_driver;
2259   return 0;
2260 }
2261
2262 void
2263 minput__fini ()
2264 {
2265   MPlist *par_lang, *par_im, *p;
2266
2267   if (command_list)
2268     {
2269       MPLIST_DO (par_lang, command_list)
2270         {
2271           MPLIST_DO (par_im, MPLIST_VAL (par_lang))
2272             {
2273               MPLIST_DO (p, MPLIST_VAL (par_im))
2274                 M17N_OBJECT_UNREF (MPLIST_VAL (p));
2275               M17N_OBJECT_UNREF (MPLIST_VAL (par_im));
2276             }
2277           M17N_OBJECT_UNREF (MPLIST_VAL (par_lang));
2278         }
2279       M17N_OBJECT_UNREF (command_list);
2280       command_list = NULL;
2281     }
2282   if (variable_list)
2283     {
2284       MPLIST_DO (par_lang, variable_list)
2285         {
2286           MPLIST_DO (par_im, MPLIST_VAL (par_lang))
2287             {
2288               MPLIST_DO (p, MPLIST_VAL (par_im))
2289                 M17N_OBJECT_UNREF (MPLIST_VAL (p));
2290               M17N_OBJECT_UNREF (MPLIST_VAL (par_im));
2291             }
2292           M17N_OBJECT_UNREF (MPLIST_VAL (par_lang));
2293         }
2294       M17N_OBJECT_UNREF (variable_list);
2295       variable_list = NULL;
2296     }
2297
2298   if (minput_default_driver.callback_list)
2299     {
2300       M17N_OBJECT_UNREF (minput_default_driver.callback_list);
2301       minput_default_driver.callback_list = NULL;
2302     }
2303   if (minput_driver->callback_list)
2304     {
2305       M17N_OBJECT_UNREF (minput_driver->callback_list);
2306       minput_driver->callback_list = NULL;
2307     }
2308
2309   M17N_OBJECT_UNREF (load_im_info_keys);
2310 }
2311
2312 void
2313 minput__callback (MInputContext *ic, MSymbol command)
2314 {
2315   if (ic->im->driver.callback_list)
2316     {
2317       MInputCallbackFunc func
2318         = (MInputCallbackFunc) mplist_get (ic->im->driver.callback_list,
2319                                            command);
2320
2321       if (func)
2322         (func) (ic, command);
2323     }
2324 }
2325
2326 MSymbol
2327 minput__char_to_key (int c)
2328 {
2329   if (c < 0 || c >= 0x100)
2330     return Mnil;
2331
2332   return one_char_symbol[c];
2333 }
2334
2335 /*** @} */
2336 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
2337
2338 \f
2339 /* External API */
2340
2341 /*** @addtogroup m17nInputMethod */
2342 /*** @{ */
2343 /*=*/
2344
2345 /***en
2346     @name Variables: Predefined symbols for callback commands.
2347
2348     These are the predefined symbols that are used as the @c COMMAND
2349     argument of callback functions of an input method driver (see
2350     #MInputDriver::callback_list ).  */ 
2351 /***ja
2352     @name ÊÑ¿ô¡§ ¥³¡¼¥ë¥Ð¥Ã¥¯¥³¥Þ¥ó¥ÉÍÑÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë.
2353
2354     ÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Î¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Ë¤ª¤¤¤Æ @c COMMAND 
2355     °ú¿ô¤È¤·¤ÆÍѤ¤¤é¤ì¤ëÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë (#MInputDriver::callback_list »²¾È)¡£
2356       */ 
2357 /*** @{ */ 
2358 /*=*/
2359
2360 MSymbol Minput_preedit_start;
2361 MSymbol Minput_preedit_done;
2362 MSymbol Minput_preedit_draw;
2363 MSymbol Minput_status_start;
2364 MSymbol Minput_status_done;
2365 MSymbol Minput_status_draw;
2366 MSymbol Minput_candidates_start;
2367 MSymbol Minput_candidates_done;
2368 MSymbol Minput_candidates_draw;
2369 MSymbol Minput_set_spot;
2370 MSymbol Minput_toggle;
2371 MSymbol Minput_reset;
2372 /*** @} */
2373 /*=*/
2374
2375 /***en
2376     @brief The default driver for internal input methods.
2377
2378     The variable #minput_default_driver is the default driver for
2379     internal input methods.
2380
2381     The member MInputDriver::open_im () searches the m17n database for
2382     an input method that matches the tag \< #Minput_method, $LANGUAGE,
2383     $NAME\> and loads it.
2384
2385     The member MInputDriver::callback_list () is @c NULL.  Thus, it is
2386     programmers responsibility to set it to a plist of proper callback
2387     functions.  Otherwise, no feedback information (e.g. preedit text)
2388     can be shown to users.
2389
2390     The macro M17N_INIT () sets the variable #minput_driver to the
2391     pointer to this driver so that all internal input methods use it.
2392
2393     Therefore, unless @c minput_driver is set differently, the driver
2394     dependent arguments $ARG of the functions whose name begin with
2395     "minput_" are all ignored.  */
2396
2397 /***ja
2398     @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥǥե©¥ë¥È¥É¥é¥¤¥Ð.
2399
2400     ÊÑ¿ô #minput_default_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѤΥǥե©¥ë¥È¤Î¥É¥é¥¤¥Ð¤òɽ¤¹¡£
2401
2402     ¥á¥ó¥Ð MInputDriver::open_im () ¤Ï m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹Ã椫¤é¥¿¥° 
2403     \< #Minput_method, $LANGUAGE, $NAME\> 
2404     ¤Ë¹çÃפ¹¤ëÆþÎϥ᥽¥Ã¥É¤òõ¤·¡¢¤½¤ì¤ò¥í¡¼¥É¤¹¤ë¡£
2405
2406     ¥á¥ó¥Ð MInputDriver::callback_list () ¤Ï @c NULL ¤Ç¤¢¤ê¡¢
2407     ¤·¤¿¤¬¤Ã¤Æ¡¢¥×¥í¥°¥é¥Þ¦¤ÇÀÕǤ¤ò»ý¤Ã¤Æ Å¬Àڤʥ³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Î plist
2408     ¤ËÀßÄꤷ¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¤µ¤â¤Ê¤¤¤È¡¢preedit 
2409     ¥Æ¥­¥¹¥È¤Ê¤É¤Î¥Õ¥£¡¼¥É¥Ð¥Ã¥¯¾ðÊ󤬥桼¥¶¤Ëɽ¼¨¤µ¤ì¤Ê¤¤¡£
2410
2411     ¥Þ¥¯¥í M17N_INIT () ¤ÏÊÑ¿ô #minput_driver 
2412     ¤ò¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤ËÀßÄꤷ¡¢Á´¤Æ¤ÎÆâÉôÆþÎϥ᥽¥Ã¥É¤¬¤³¤Î¥É¥é¥¤¥Ð¤ò»È¤¦¤è¤¦¤Ë¤¹¤ë¡£
2413
2414     ¤·¤¿¤¬¤Ã¤Æ¡¢@c minput_driver ¤¬¥Ç¥Õ¥©¥ë¥ÈÃͤΤޤޤǤ¢¤ì¤Ð¡¢minput_ 
2415     ¤Ç»Ï¤Þ¤ë´Ø¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô $ARG ¤Ï¤¹¤Ù¤Æ̵»ë¤µ¤ì¤ë¡£  */
2416
2417 MInputDriver minput_default_driver;
2418 /*=*/
2419
2420 /***en
2421     @brief The driver for internal input methods.
2422
2423     The variable #minput_driver is a pointer to the input method
2424     driver that is used by internal input methods.  The macro
2425     M17N_INIT () initializes it to a pointer to #minput_default_driver
2426     if <m17n<EM></EM>.h> is included.  */ 
2427 /***ja
2428     @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥɥ饤¥Ð.
2429
2430     ÊÑ¿ô #minput_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤Æ»ÈÍѤµ¤ì¤Æ¤¤¤ëÆþÎÏ¥á
2431     ¥½¥Ã¥É¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£¥Þ¥¯¥í M17N_INIT () ¤Ï¤³¤Î¥Ý¥¤¥ó
2432     ¥¿¤ò#minput_default_driver (<m17n<EM></EM>.h> ¤¬ include ¤µ¤ì¤Æ¤¤¤ë
2433     »þ) ¤Ë½é´ü²½¤¹¤ë¡£  */ 
2434
2435 MInputDriver *minput_driver;
2436
2437 MSymbol Minput_driver;
2438
2439 /*=*/
2440
2441 /***en
2442     @brief Open an input method.
2443
2444     The minput_open_im () function opens an input method that matches
2445     language $LANGUAGE and name $NAME, and returns a pointer to the
2446     input method object newly allocated.
2447
2448     This function at first decides an driver for the input method as
2449     below.
2450
2451     If $LANGUAGE is not #Mnil, the driver pointed by the variable
2452     #minput_driver is used.
2453
2454     If $LANGUAGE is #Mnil and $NAME has #Minput_driver property, the
2455     driver pointed to by the property value is used to open the input
2456     method.  If $NAME has no such property, @c NULL is returned.
2457
2458     Then, the member MInputDriver::open_im () of the driver is
2459     called.  
2460
2461     $ARG is set in the member @c arg of the structure MInputMethod so
2462     that the driver can refer to it.  */
2463
2464 /***ja
2465     @brief ÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë.
2466
2467     ´Ø¿ô minput_open_im () ¤Ï¸À¸ì $LANGUAGE ¤È̾Á° $NAME 
2468     ¤Ë¹çÃפ¹¤ëÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤·¡¢¿·¤¿¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿ÆþÎϥ᥽¥Ã¥É¥ª¥Ö¥¸¥§¥¯¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
2469     
2470     ¤³¤Î´Ø¿ô¤Ï¡¢¤Þ¤ºÆþÎϥ᥽¥Ã¥ÉÍѤΥɥ饤¥Ð¤ò°Ê²¼¤Î¤è¤¦¤Ë¤·¤Æ·èÄꤹ¤ë¡£
2471
2472     $LANGUAGE ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢ÊÑ¿ô #minput_driver 
2473     ¤Ç»Ø¤µ¤ì¤Æ¤¤¤ë¥É¥é¥¤¥Ð¤òÍѤ¤¤ë¡£
2474
2475     $LANGUAGE ¤¬ #Mnil ¤Ç¤¢¤ê¡¢$NAME ¤¬ #Minput_driver
2476     ¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä¾ì¹ç¤Ë¤Ï¡¢¤½¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤǻؤµ¤ì¤Æ¤¤¤ëÆþÎϥɥ饤¥Ð¤òÍѤ¤¤ÆÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë¡£
2477     $NAME ¤Ë¤½¤Î¤è¤¦¤Ê¥×¥í¥Ñ¥Æ¥£¤¬Ìµ¤«¤Ã¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
2478
2479     ¼¡¤¤¤Ç¡¢¥É¥é¥¤¥Ð¤Î¥á¥ó¥Ð MInputDriver::open_im () ¤¬¸Æ¤Ð¤ì¤ë¡£
2480
2481     $ARG ¤Ï¹½Â¤ÂΠMInputMethod ¤Î¥á¥ó¥Ð @c arg ¤ËÀßÄꤵ¤ì¡¢¥É¥é¥¤¥Ð¤«¤é»²¾È¤Ç¤­¤ë¡£
2482
2483     @latexonly \IPAlabel{minput_open} @endlatexonly
2484
2485 */
2486
2487 MInputMethod *
2488 minput_open_im (MSymbol language, MSymbol name, void *arg)
2489 {
2490   MInputMethod *im;
2491   MInputDriver *driver;
2492
2493   if (language)
2494     driver = minput_driver;
2495   else
2496     {
2497       driver = (MInputDriver *) msymbol_get (name, Minput_driver);
2498       if (! driver)
2499         MERROR (MERROR_IM, NULL);
2500     }
2501
2502   MSTRUCT_CALLOC (im, MERROR_IM);
2503   im->language = language;
2504   im->name = name;
2505   im->arg = arg;
2506   im->driver = *driver;
2507   if ((*im->driver.open_im) (im) < 0)
2508     {
2509       free (im);
2510       return NULL;
2511     }
2512   return im;
2513 }
2514
2515 /*=*/
2516
2517 /***en
2518     @brief Close an input method.
2519
2520     The minput_close_im () function closes the input method $IM, which
2521     must have been created by minput_open_im ().  */
2522
2523 /***ja
2524     @brief ÆþÎϥ᥽¥Ã¥É¤ò¥¯¥í¡¼¥º¤¹¤ë.
2525
2526     ´Ø¿ô minput_close_im () ¤Ï¡¢ÆþÎϥ᥽¥Ã¥É $IM ¤ò¥¯¥í¡¼¥º¤¹¤ë¡£
2527     ¤³¤ÎÆþÎϥ᥽¥Ã¥É $IM ¤Ï minput_open_im () ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£  */
2528
2529 void
2530 minput_close_im (MInputMethod *im)
2531 {
2532   (*im->driver.close_im) (im);
2533   free (im);
2534 }
2535
2536 /*=*/
2537
2538 /***en
2539     @brief Create an input context.
2540
2541     The minput_create_ic () function creates an input context object
2542     associated with input method $IM, and calls callback functions
2543     corresponding to #Minput_preedit_start, #Minput_status_start, and
2544     #Minput_status_draw in this order.
2545
2546     @return
2547
2548     If an input context is successfully created, minput_create_ic ()
2549     returns a pointer to it.  Otherwise it returns @c NULL.  */
2550
2551 /***ja
2552     @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÀ¸À®¤¹¤ë.
2553
2554     ´Ø¿ô minput_create_ic () ¤ÏÆþÎϥ᥽¥Ã¥É $IM
2555     ¤ËÂбþ¤¹¤ëÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤·¡¢
2556     #Minput_preedit_start, #Minput_status_start, #Minput_status_draw
2557     ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¤³¤Î½ç¤Ë¸Æ¤Ö¡£
2558
2559     @return
2560
2561     ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤¬À¸À®¤µ¤ì¤¿¾ì¹ç¡¢minput_create_ic () 
2562     ¤Ï¤½¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¼ºÇÔ¤·¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
2563       */
2564
2565 MInputContext *
2566 minput_create_ic (MInputMethod *im, void *arg)
2567 {
2568   MInputContext *ic;
2569
2570   MSTRUCT_CALLOC (ic, MERROR_IM);
2571   ic->im = im;
2572   ic->arg = arg;
2573   ic->preedit = mtext ();
2574   ic->candidate_list = NULL;
2575   ic->produced = mtext ();
2576   ic->spot.x = ic->spot.y = 0;
2577   ic->active = 1;
2578   ic->plist = mplist ();
2579   if ((*im->driver.create_ic) (ic) < 0)
2580     {
2581       M17N_OBJECT_UNREF (ic->preedit);
2582       M17N_OBJECT_UNREF (ic->produced);
2583       M17N_OBJECT_UNREF (ic->plist);
2584       free (ic);
2585       return NULL;
2586     };
2587
2588   if (im->driver.callback_list)
2589     {
2590       minput__callback (ic, Minput_preedit_start);
2591       minput__callback (ic, Minput_status_start);
2592       minput__callback (ic, Minput_status_draw);
2593     }
2594
2595   return ic;
2596 }
2597
2598 /*=*/
2599
2600 /***en
2601     @brief Destroy an input context.
2602
2603     The minput_destroy_ic () function destroys the input context $IC,
2604     which must have been created by minput_create_ic ().  It calls
2605     callback functions corresponding to #Minput_preedit_done,
2606     #Minput_status_done, and #Minput_candidates_done in this order.  */
2607
2608 /***ja
2609     @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÇ˲õ¤¹¤ë.
2610
2611     ´Ø¿ô minput_destroy_ic () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤òÇ˲õ¤¹¤ë¡£
2612     ¤³¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ï minput_create_ic () 
2613     ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£¤³¤Î´Ø¿ô¤Ï 
2614     #Minput_preedit_done, #Minput_status_done, #Minput_candidates_done 
2615     ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¤³¤Î½ç¤Ë¸Æ¤Ö¡£
2616   */
2617
2618 void
2619 minput_destroy_ic (MInputContext *ic)
2620 {
2621   if (ic->im->driver.callback_list)
2622     {
2623       minput__callback (ic, Minput_preedit_done);
2624       minput__callback (ic, Minput_status_done);
2625       minput__callback (ic, Minput_candidates_done);
2626     }
2627   (*ic->im->driver.destroy_ic) (ic);
2628   M17N_OBJECT_UNREF (ic->preedit);
2629   M17N_OBJECT_UNREF (ic->produced);
2630   M17N_OBJECT_UNREF (ic->plist);
2631   free (ic);
2632 }
2633
2634 /*=*/
2635
2636 /***en
2637     @brief Filter an input key.
2638
2639     The minput_filter () function filters input key $KEY according to
2640     input context $IC, and calls callback functions corresponding to
2641     #Minput_preedit_draw, #Minput_status_draw, and
2642     #Minput_candidates_draw if the preedit text, the status, and the
2643     current candidate are changed respectively.
2644
2645     @return
2646     If $KEY is filtered out, this function returns 1.  In that case,
2647     the caller should discard the key.  Otherwise, it returns 0, and
2648     the caller should handle the key, for instance, by calling the
2649     function minput_lookup () with the same key.  */
2650
2651 /***ja
2652     @brief ÆþÎÏ¥­¡¼¤ò¥Õ¥£¥ë¥¿¤¹¤ë.
2653
2654     ´Ø¿ô minput_filter () ¤ÏÆþÎÏ¥­¡¼ $KEY ¤òÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC 
2655     ¤Ë±þ¤¸¤Æ¥Õ¥£¥ë¥¿¤·¡¢preedit ¥Æ¥­¥¹¥È¡¢¥¹¥Æ¡¼¥¿¥¹¡¢¸½»þÅÀ¤Ç¤Î¸õÊ䤬ÊѲ½¤·¤¿»þÅÀ¤Ç¡¢¤½¤ì¤¾¤ì
2656     #Minput_preedit_draw, #Minput_status_draw,
2657     #Minput_candidates_draw ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¸Æ¤Ö¡£
2658
2659     @return 
2660     $KEY ¤¬¥Õ¥£¥ë¥¿¤µ¤ì¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 1 ¤òÊÖ¤¹¡£
2661     ¤³¤Î¾ì¹ç¸Æ¤Ó½Ð¤·Â¦¤Ï¤³¤Î¥­¡¼¤ò¼Î¤Æ¤ë¤Ù¤­¤Ç¤¢¤ë¡£
2662     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0 ¤òÊÖ¤·¡¢¸Æ¤Ó½Ð¤·Â¦¤Ï¡¢¤¿¤È¤¨¤ÐƱ¤¸¥­¡¼¤Ç´Ø¿ô minput_lookup ()
2663     ¤ò¸Æ¤Ö¤Ê¤É¤·¤Æ¡¢¤³¤Î¥­¡¼¤ò½èÍý¤¹¤ë¡£
2664
2665     @latexonly \IPAlabel{minput_filter} @endlatexonly
2666 */
2667
2668 int
2669 minput_filter (MInputContext *ic, MSymbol key, void *arg)
2670 {
2671   int ret;
2672
2673   if (! ic
2674       || ! ic->active)
2675     return 0;
2676   ret = (*ic->im->driver.filter) (ic, key, arg);
2677
2678   if (ic->im->driver.callback_list)
2679     {
2680       if (ic->preedit_changed)
2681         minput__callback (ic, Minput_preedit_draw);
2682       if (ic->status_changed)
2683         minput__callback (ic, Minput_status_draw);
2684       if (ic->candidates_changed)
2685         minput__callback (ic, Minput_candidates_draw);
2686     }
2687
2688   return ret;
2689 }
2690
2691 /*=*/
2692
2693 /***en
2694     @brief Look up a text produced in the input context.
2695
2696     The minput_lookup () function looks up a text in the input context
2697     $IC.  $KEY must be the same one provided to the previous call of
2698     minput_filter ().
2699
2700     If a text was produced by the input method, it is concatenated
2701     to M-text $MT.
2702
2703     This function calls #MInputDriver::lookup .
2704
2705     @return
2706     If $KEY was correctly handled by the input method, this function
2707     returns 0.  Otherwise, returns -1, even in that case, some text
2708     may be produced in $MT.  */
2709
2710 /***ja
2711     @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥ÈÃæ¤Î¥Æ¥­¥¹¥È¤òõ¤¹.
2712
2713     ´Ø¿ô minput_lookup () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC Ãæ¤Î¥Æ¥­¥¹¥È¤òõ¤¹¡£
2714     $KEY ¤Ï´Ø¿ô minput_filter () ¤Ø¤ÎľÁ°¤Î¸Æ¤Ó½Ð¤·¤ËÍѤ¤¤é¤ì¤¿¤â¤Î¤ÈƱ¤¸¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2715
2716     ¥Æ¥­¥¹¥È¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆÀ¸À®¤µ¤ì¤Æ¤¤¤ì¤Ð¡¢¥Æ¥­¥¹¥È¤Ï M-text
2717     $MT ¤ËÏ¢·ë¤µ¤ì¤ë¡£
2718
2719     ¤³¤Î´Ø¿ô¤Ï¡¢#MInputDriver::lookup ¤ò¸Æ¤Ö¡£
2720
2721     @return 
2722     $KEY ¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆŬÀڤ˽èÍý¤Ç¤­¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 0 ¤òÊÖ¤¹¡£
2723     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£
2724     ¤³¤Î¾ì¹ç¤Ç¤â $MT ¤Ë²¿¤é¤«¤Î¥Æ¥­¥¹¥È¤¬À¸À®¤µ¤ì¤Æ¤¤¤ë¤³¤È¤¬¤¢¤ë¡£
2725
2726     @latexonly \IPAlabel{minput_lookup} @endlatexonly  */
2727
2728 int
2729 minput_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2730 {
2731   return (ic ? (*ic->im->driver.lookup) (ic, key, arg, mt) : -1);
2732 }
2733 /*=*/
2734
2735 /***en
2736     @brief Set the spot of the input context.
2737
2738     The minput_set_spot () function set the spot of input context $IC
2739     to coordinate ($X, $Y ) with the height specified by $ASCENT and $DESCENT .
2740     The semantics of these values depend on the input method driver.
2741
2742     For instance, a driver designed to work in a CUI environment may
2743     use $X and $Y as column and row numbers, and ignore $ASCENT and
2744     $DESCENT .  A driver designed to work in a window system may
2745     interpret $X and $Y as pixel offsets relative to the origin of the
2746     client window, and may interpret $ASCENT and $DESCENT as the ascent- and
2747     descent pixels of the line at ($X . $Y ).
2748
2749     $FONTSIZE specifies the fontsize of preedit text in 1/10 point.
2750
2751     $MT and $POS is the M-text and the character position at the spot.
2752     $MT may be @c NULL, in which case, the input method cannot get
2753     information about the text around the spot.  */
2754
2755 /***ja
2756     @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Î¥¹¥Ý¥Ã¥È¤òÀßÄꤹ¤ë.
2757
2758     ´Ø¿ô minput_set_spot () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤Î¥¹¥Ý¥Ã¥È¤ò¡¢ºÂɸ ($X, $Y )
2759     ¤Î°ÌÃ֤ˠ¡¢¹â¤µ $ASCENT¡¢ $DESCENT 
2760     ¤ÇÀßÄꤹ¤ë¡£ ¤³¤ì¤é¤ÎÃͤΰÕÌ£¤ÏÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë¡£
2761
2762     ¤¿¤È¤¨¤Ð CUI ´Ä¶­¤ÇÆ°ºî¤¹¤ë¥É¥é¥¤¥Ð¤Ï $X ¤È $Y 
2763     ¤ò¤½¤ì¤¾¤ìÎó¤È¹Ô¤ÎÈÖ¹æ¤È¤·¤ÆÍѤ¤¡¢$ASCENT ¤È $DESCENT 
2764     ¤ò̵»ë¤¹¤ë¤«¤â¤·¤ì¤Ê¤¤¡£ ¤Þ¤¿¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥àÍѤΥɥ饤¥Ð¤Ï
2765     $X ¤È $Y ¤ò¥¯¥é¥¤¥¢¥ó¥È¥¦¥£¥ó¥É¥¦¤Î¸¶ÅÀ¤«¤é¤Î¥ª¥Õ¥»¥Ã¥È¤ò¥Ô¥¯¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¤¡¢
2766     $ASCENT ¤È $DESCENT ¤ò ($X . $Y )
2767     ¤ÎÎó¤Î¥¢¥»¥ó¥È¤È¥Ç¥£¥»¥ó¥È¤ò¥Ô¥¯¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¦¤«¤â¤·¤ì¤Ê¤¤¡£
2768
2769     $FONTSIZE ¤Ë¤Ï preedit ¥Æ¥­¥¹¥È¤Î¥Õ¥©¥ó¥È¥µ¥¤¥º¤ò 1/10 ¥Ý¥¤¥ó¥Èñ°Ì¤Ç»ØÄꤹ¤ë¡£
2770
2771     $MT ¤È $POS ¤Ï¤½¤Î¥¹¥Ý¥Ã¥È¤Î M-text ¤Èʸ»ú°ÌÃ֤Ǥ¢¤ë¡£$MT ¤Ï @c
2772     NULL ¤Ç¤â¤è¤¯¡¢¤½¤Î¾ì¹ç¤Ë¤ÏÆþÎϥ᥽¥Ã¥É¤Ï¥¹¥Ý¥Ã¥È¼þÊդΥƥ­¥¹¥È¤Ë´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë¤³¤È¤¬¤Ç¤­¤Ê¤¤¡£
2773     */
2774
2775 void
2776 minput_set_spot (MInputContext *ic, int x, int y,
2777                  int ascent, int descent, int fontsize,
2778                  MText *mt, int pos)
2779 {
2780   ic->spot.x = x;
2781   ic->spot.y = y;
2782   ic->spot.ascent = ascent;
2783   ic->spot.descent = descent;
2784   ic->spot.fontsize = fontsize;
2785   ic->spot.mt = mt;
2786   ic->spot.pos = pos;
2787   if (ic->im->driver.callback_list)
2788     minput__callback (ic, Minput_set_spot);
2789 }
2790 /*=*/
2791
2792 /***en
2793     @brief Toggle input method.
2794
2795     The minput_toggle () function toggles the input method associated
2796     with input context $IC.  */
2797 /***ja
2798     @brief ÆþÎϥ᥽¥Ã¥É¤òÀÚÂؤ¨¤ë.
2799
2800     ´Ø¿ô minput_toggle () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC 
2801     ¤ËÂбþÉÕ¤±¤é¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ò¥È¥°¥ë¤¹¤ë¡£
2802     */
2803
2804 void
2805 minput_toggle (MInputContext *ic)
2806 {
2807   if (ic->im->driver.callback_list)
2808     minput__callback (ic, Minput_toggle);
2809   ic->active = ! ic->active;
2810 }
2811
2812 /***en
2813     @brief Reset an input context.
2814
2815     The minput_reset_ic () function resets input context $IC by
2816     calling a callback function corresponding to #Minput_reset.  It
2817     actually shifts the state to the initial one, and thus the current
2818     preediting text (if any) is committed.  If necessary, a program
2819     can extract that committed text by calling minput_lookup () just
2820     after the call of minput_reset_ic ().  In that case, the arguments
2821     @c KEY and @c ARG of minput_lookup () are ignored.  */
2822 /***ja
2823     @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤ò¥ê¥»¥Ã¥È¤¹¤ë.
2824
2825     ´Ø¿ô minput_reset_ic () ¤Ï #Minput_reset 
2826     ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¸Æ¤Ö¤³¤È¤Ë¤è¤Ã¤ÆÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC 
2827     ¤ò¥ê¥»¥Ã¥È¤¹¤ë¡£¥ê¥»¥Ã¥È¤È¤Ï¡¢¼ÂºÝ¤Ë¤ÏÆþÎϥ᥽¥Ã¥É¤ò½é´ü¾õÂ֤˰ܤ¹¤³¤È¤Ç¤¢¤ê¡¢¤·¤¿¤¬¤Ã¤Æ¡¢¤â¤·¸½ºßÆþÎÏÃæ¤Î¥Æ¥­¥¹¥È¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤Ï¥³¥ß¥Ã¥È¤µ¤ì¤ë¡£
2828     É¬Íפʤé¤Ð¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ï minput_lookup () 
2829     ¤òÆɤó¤Ç¤½¤Î¥³¥ß¥Ã¥È¤µ¤ì¤¿¥Æ¥­¥¹¥È¤ò¼è¤ê½Ð¤¹¤³¤È¤¬¤Ç¤­¡¢¤½¤ÎºÝ¡¢
2830     minput_lookup () ¤Î°ú¿ô @c KEY ¤È @c ARG 
2831     ¤Ï̵»ë¤µ¤ì¤ë¡£ */
2832 void
2833 minput_reset_ic (MInputContext *ic)
2834 {
2835   if (ic->im->driver.callback_list)
2836     minput__callback (ic, Minput_reset);
2837 }
2838
2839 /*=*/
2840 /***en
2841     @brief Key of a text property for detailed description.
2842
2843     The symbol #Mdetail_text is a managing key usually used for a
2844     text property whose value is an M-text that contains detailed
2845     description.  */
2846 /***ja
2847     @brief ¾ÜºÙÀâÌÀÍѥƥ­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
2848
2849     ¥·¥ó¥Ü¥ë #Mdetail_text ¤Ï´ÉÍý¥­¡¼¤Ç¤¢¤ê¡¢Ä̾ï¾ÜºÙ¤ÊÀâÌÀ¤ò´Þ¤à 
2850     M-text ¤òÃͤȤ·¤Æ»ý¤Ä¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ËÍѤ¤¤é¤ì¤ë¡£
2851     */
2852 MSymbol Mdetail_text;
2853
2854 /***en
2855     @brief Get description text of an input method.
2856
2857     The minput_get_description () function returns an M-text that
2858     briefly describes the input method specified by $LANGUAGE and
2859     $NAME.  The returned M-text may have a text property, from its
2860     beginning to end, #Mdetail_text whose value is an M-text
2861     describing the input method in more detail.
2862
2863     @return
2864     If the specified input method has a description text, a pointer to
2865     #MText is returned.  A caller have to free it by m17n_object_unref ().
2866     If the input method does not have a description text, @c NULL is
2867     returned.  */
2868 /***ja
2869     @brief ÆþÎϥ᥽¥Ã¥É¤ÎÀâÌÀ¥Æ¥­¥¹¥È¤òÆÀ¤ë.
2870
2871     ´Ø¿ô minput_get_description () ¤Ï¡¢$LANGUAGE ¤È $NAME 
2872     ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ò´Êñ¤ËÀâÌÀ¤¹¤ë M-text ¤òÊÖ¤¹¡£ÊÖ¤µ¤ì¤ë M-text 
2873     ¤Ë¤Ï¡¢¤½¤ÎÁ´ÂΤËÂФ·¤Æ #Mdetail_text 
2874     ¤È¤¤¤¦¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬Éղ䵤ì¤Æ¤¤¤ë¾ì¹ç¤¬¤¢¤ê¡¢¤½¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤÏÆþÎϥ᥽¥Ã¥É¤ò¤µ¤é¤Ë¾ÜºÙ¤ËÀâÌÀ¤¹¤ë
2875     M-text ¤Ç¤¢¤ë¡£
2876
2877     @return 
2878     »ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤¬ÀâÌÀ¤¹¤ë¥Æ¥­¥¹¥È¤ò»ý¤Ã¤Æ¤¤¤ì¤Ð¡¢ 
2879     #MText ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¸Æ¤Ó½Ð¤·Â¦¤Ï¡¢¤½¤ì¤ò m17n_object_unref
2880     () ¤òÍѤ¤¤Æ²òÊü¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ÆþÎϥ᥽¥Ã¥É¤ËÀâÌÀ¥Æ¥­¥¹¥È¤¬Ìµ¤±¤ì¤Ð@c NULL ¤òÊÖ¤¹¡£ */
2881
2882 MText *
2883 minput_get_description (MSymbol language, MSymbol name)
2884 {
2885   MPlist *plist = load_im_info (language, name, M_description);
2886   MPlist *pl;
2887   MText *mt = NULL;
2888
2889   if (! plist)
2890     return NULL;
2891   if (! MPLIST_PLIST_P (plist))
2892     {
2893       M17N_OBJECT_UNREF (plist);      
2894       return NULL;
2895     }
2896   pl = MPLIST_PLIST (plist);
2897   while (! MPLIST_TAIL_P (pl) && ! MPLIST_MTEXT_P (pl))
2898     pl = MPLIST_NEXT (pl);
2899   if (MPLIST_MTEXT_P (pl))
2900     mt = get_description_advance (pl);
2901   M17N_OBJECT_UNREF (plist);
2902   return mt;
2903 }
2904
2905 /***en
2906     @brief Get information about input method commands.
2907
2908     The minput_get_commands () function returns information about
2909     input method commands of the input method specified by $LANGUAGE
2910     and $NAME.  An input method command is a pseudo key event to which
2911     one or more actual input key sequences are assigned.
2912
2913     There are two kinds of commands, global and local.  Global
2914     commands are used by multiple input methods for the same purpose,
2915     and have global key assignments.  Local commands are used only in
2916     a specific input method, and have only local key assignments.
2917
2918     Each input method may locally change key assignments for global
2919     commands.  A global key assignment for a global command are
2920     effective only when the current input method does not have local
2921     key assignments for that command.
2922
2923     If $NAME is #Mnil, information about global commands is returned.
2924     In this case $LANGUAGE is ignored.
2925
2926     If $NAME is not #Mnil, information about those commands that have
2927     local key assignments in the input method specified by $LANGUAGE
2928     and $NAME is returned.
2929
2930     @return
2931     If no input method commands are found, this function returns @c NULL.
2932
2933     Otherwise, a pointer to a plist is returned.  The key of each
2934     element in the plist is a symbol representing a command, and the
2935     value is a plist of the form COMMAND-INFO described below.
2936
2937     The first element of COMMAND-INFO has the key #Mtext, and the
2938     value is an M-text describing the command briefly.  This M-text
2939     may have a text property whose key is #Mdetail_text and whose
2940     value is an M-text describing the command in more detail.
2941
2942     If there are no more elements, that means no key sequences are
2943     assigned to the command.  Otherwise, each of the remaining
2944     elements has the key #Mplist, and the value is a plist whose keys are
2945     #Msymbol and values are symbols representing input keys, which are
2946     currently assigned to the command.
2947
2948     As the returned plist is kept in the library, the caller must not
2949     modify nor free it.  */
2950 /***ja
2951     @brief ÆþÎϥ᥽¥Ã¥É¤Î¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë.
2952
2953     ´Ø¿ô minput_get_commands () ¤Ï¡¢ $LANGUAGE ¤È $NAME 
2954     ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ÎÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£
2955     ÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤È¤Ï¡¢µ¿»÷¥­¡¼¥¤¥Ù¥ó¥È¤Ç¤¢¤ê¡¢¤½¤ì¤¾¤ì¤Ë£±¤Ä°Ê¾å¤Î¼ÂºÝ¤ÎÆþÎÏ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤¬³ä¤êÅö¤Æ¤é¤ì¤Æ¤¤¤ë¤â¤Î¤ò»Ø¤¹¡£
2956
2957     ¥³¥Þ¥ó¥É¤Ë¤Ï¥°¥í¡¼¥Ð¥ë¤È¥í¡¼¥«¥ë¤Î£²¼ïÎब¤¢¤ë¡£
2958     ¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É¤ÏÊ£¿ô¤ÎÆþÎϥ᥽¥Ã¥É¤Ë¤ª¤¤¤Æ¡¢Æ±¤¸ÌÜŪ¤Ç¡¢¥°¥í¡¼¥Ð¥ë¤Ê¥­¡¼³ä¤êÅö¤Æ¤ÇÍѤ¤¤é¤ì¤ë¡£
2959     ¥í¡¼¥«¥ë¥³¥Þ¥ó¥É¤ÏÆÃÄê¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Î¤ß¡¢¥í¡¼¥«¥ë¤Ê¥­¡¼³äÅö¤Ç»ÈÍѤµ¤ì¤ë¡£
2960
2961     ¸Ä¡¹¤ÎÆþÎϥ᥽¥Ã¥É¤Ï¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É¤Î¥­¡¼³äÅö¤òÊѹ¹¤¹¤ë¤³¤È¤â¤Ç¤­¤ë¡£
2962     ¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥ÉÍѤΥ°¥í¡¼¥Ð¥ë¥­¡¼³ä¤êÅö¤Æ¤Ï¡¢»ÈÍѤ¹¤ëÆþÎϥ᥽¥Ã¥É¤Ë¤ª¤¤¤Æ¤½¤Î¥³¥Þ¥ó¥ÉÍÑ¤Î¥í¡¼¥«¥ë¤Ê¥­¡¼³äÅö¤¬Â¸ºß¤·¤Ê¤¤¾ì¹ç¤Ë¤Î¤ßÍ­¸ú¤Ç¤¢¤ë¡£
2963
2964     $NAME ¤¬ #Mnil ¤Ç¤¢¤ì¤Ð¡¢¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£
2965     ¤³¤Î¾ì¹ç¡¢$LANGUAGE ¤Ï̵»ë¤µ¤ì¤ë¡£
2966
2967     $NAME ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢$LANGUAGE ¤È $NAME 
2968     ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤ëÆþÎϥ᥽¥Ã¥É¤ËÃÖ¤±¤ë¥í¡¼¥«¥ë¤Ê¥­¡¼³ä¤êÅö¤Æ¤ò»ý¤Ä¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£
2969
2970     @return
2971     ÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï @c NULL ¤òÊÖ¤¹¡£
2972
2973     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
2974     ¥ê¥¹¥È¤Î³ÆÍ×ÁǤΥ­¡¼¤Ï¸Ä¡¹¤Î¥³¥Þ¥ó¥É¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢Ãͤϲ¼µ­¤Î 
2975     COMMAND-INFO ¤Î·Á¼°¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ç¤¢¤ë¡£
2976
2977     COMMAND-INFO ¤ÎÂè°ìÍ×ÁǤϥ­¡¼¤È¤·¤Æ #Mtext 
2978     ¤ò¡¢ÃͤȤ·¤Æ¤½¤Î¥³¥Þ¥ó¥É¤ò´Êñ¤ËÀâÌÀ¤¹¤ë M-text ¤ò»ý¤Ä¡£¤³¤Î M-text 
2979     ¤Ï¡¢#Mdetail_text 
2980     ¤ò¥­¡¼¤È¤¹¤ë¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä¤³¤È¤¬¤Ç¤­¡¢¤½¤ÎÃͤϤ½¤Î¥³¥Þ¥ó¥É¤ò¤è¤ê¾ÜºÙ¤ËÀâÌÀ¤¹¤ë
2981     M-text ¤Ç¤¢¤ë¡£
2982
2983     ¤½¤ì°Ê³°¤ÎÍ×ÁǤ¬Ìµ¤±¤ì¤Ð¡¢¤³¤Î¥³¥Þ¥ó¥É¤ËÂФ·¤Æ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤¬³ä¤êÅö¤Æ¤é¤ì¤Æ¤¤¤Ê¤¤¤³¤È¤ò°ÕÌ£¤¹¤ë¡£
2984     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢»Ä¤ê¤Î³ÆÍ×ÁǤϥ­¡¼¤È¤·¤Æ#Mplist 
2985     ¤ò¡¢ÃͤȤ·¤Æ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ò»ý¤Ä¡£
2986     ¤³¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Î¥­¡¼¤Ï #Msymbol 
2987     ¤Ç¤¢¤ê¡¢Ãͤϸ½ºß¤½¤Î¥³¥Þ¥ó¥É¤Ë³ä¤êÅö¤Æ¤é¤ì¤Æ¤¤¤ëÆþÎÏ¥­¡¼¤òɽ¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
2988
2989     ÊÖ¤µ¤ì¤ë¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ï¥é¥¤¥Ö¥é¥ê¤Ë¤è¤Ã¤Æ´ÉÍý¤µ¤ì¤Æ¤ª¤ê¡¢¸Æ¤Ó½Ð¤·Â¦¤ÇÊѹ¹¤·¤¿¤ê²òÊü¤·¤¿¤ê¤·¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£*/
2990
2991 MPlist *
2992 minput_get_commands (MSymbol language, MSymbol name)
2993 {
2994   MPlist *plist = get_command_list (language, name);
2995
2996   return (! plist || MPLIST_TAIL_P (plist) ? NULL : plist);
2997 }
2998
2999 /***en
3000     @brief Assign a key sequence to an input method command.
3001
3002     The minput_assign_command_keys () function assigns input key
3003     sequence $KEYSEQ to input method command $COMMAND for the input
3004     method specified by $LANGUAGE and $NAME.  If $NAME is #Mnil, the
3005     key sequence is assigned globally no matter what $LANGUAGE is.
3006     Otherwise the key sequence is assigned locally.
3007
3008     Each element of $KEYSEQ must have the key $Msymbol and the value
3009     must be a symbol representing an input key.
3010
3011     $KEYSEQ may be @c NULL, in which case, all assignments are deleted
3012     globally or locally.
3013
3014     This assignment gets effective in a newly opened input method.
3015
3016     @return
3017     If the operation was successful, 0 is returned.  Otherwise -1 is
3018     returned, and #merror_code is set to #MERROR_IM.  */
3019 /***ja
3020     @brief ÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤Ë¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤ò³ä¤êÅö¤Æ¤ë.
3021
3022     ´Ø¿ô minput_assign_command_keys () ¤Ï¡¢ $LANGUAGE ¤È $NAME 
3023     ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥ÉÍѤÎÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É $COMMAND 
3024     ¤ËÂФ·¤Æ¡¢ÆþÎÏ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹ $KEYSEQ ¤ò³ä¤êÅö¤Æ¤ë¡£ $NAME ¤¬ #Mnil
3025     ¤Ê¤é¤Ð¡¢$LANGUAGE ¤Ë´Ø·¸¤Ê¤¯¡¢ÆþÎÏ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤Ï¥°¥í¡¼¥Ð¥ë¤Ë³ä¤êÅö¤Æ¤é¤ì¤ë¡£
3026     ¤½¤¦¤Ç¤Ê¤ì¤Ð¡¢³ä¤êÅö¤Æ¤Ï¥í¡¼¥«¥ë¤Ç¤¢¤ë¡£
3027
3028     $KEYSEQ ¤Î³ÆÍ×ÁǤϥ­¡¼¤È¤·¤Æ $Msymbol 
3029     ¤ò¡¢ÃͤȤ·¤ÆÆþÎÏ¥­¡¼¤òɽ¤¹¥·¥ó¥Ü¥ë¤ò»ý¤¿¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
3030
3031     $KEYSEQ ¤Ï @c NULL ¤Ç¤â¤è¤¤¡£
3032     ¤³¤Î¾ì¹ç¡¢¥°¥í¡¼¥Ð¥ë¤â¤·¤¯¤Ï¥í¡¼¥«¥ë¤Ê¤¹¤Ù¤Æ¤Î³ä¤êÅö¤Æ¤¬¾Ãµî¤µ¤ì¤ë¡£
3033
3034     ¤³¤Î³ä¤êÅö¤Æ¤Ï¡¢³ä¤êÅö¤Æ°Ê¹ß¿·¤·¤¯¥ª¡¼¥×¥ó¤µ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤«¤éÍ­¸ú¤Ë¤Ê¤ë¡£
3035
3036     @return 
3037     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤·¡¢
3038     #merror_code ¤ò #MERROR_IM ¤ËÀßÄꤹ¤ë¡£  */
3039
3040 int
3041 minput_assign_command_keys (MSymbol language, MSymbol name,
3042                             MSymbol command, MPlist *keyseq)
3043 {
3044   MPlist *plist, *pl, *p;
3045
3046   if (check_command_keyseq (keyseq) < 0
3047       || ! (plist = get_command_list (language, name)))
3048     MERROR (MERROR_IM, -1);
3049   pl = mplist_get (plist, command);
3050   if (pl)
3051     {
3052       pl = MPLIST_NEXT (pl);
3053       if (! keyseq)
3054         while ((p = mplist_pop (pl)))
3055           M17N_OBJECT_UNREF (p);
3056       else
3057         {
3058           keyseq = mplist_copy (keyseq);
3059           mplist_push (pl, Mplist, keyseq);
3060           M17N_OBJECT_UNREF (keyseq);
3061         }
3062     }
3063   else
3064     {
3065       if (name == Mnil)
3066         MERROR (MERROR_IM, -1);
3067       if (! keyseq)
3068         return 0;
3069       pl = get_command_list (Mnil, Mnil); /* Get global commands.  */
3070       pl = mplist_get (pl, command);
3071       if (! pl)
3072         MERROR (MERROR_IM, -1);
3073       p = mplist ();
3074       mplist_add (p, Mtext, mplist_value (pl));
3075       keyseq = mplist_copy (keyseq);
3076       mplist_add (p, Mplist, keyseq);
3077       M17N_OBJECT_UNREF (keyseq);
3078       mplist_push (plist, command, p);
3079     }
3080   return 0;
3081 }
3082
3083 /***en
3084     @brief Get a list of variables of an input method.
3085
3086     The minput_get_variables () function returns a plist (#MPlist) of
3087     variables used to control the behavior of the input method
3088     specified by $LANGUAGE and $NAME.  The key of an element of the
3089     plist is a symbol representing a variable, and the value is a
3090     plist of the form VAR-INFO (described below) that carries the
3091     information about the variable.
3092
3093     The first element of VAR-INFO has the key #Mtext, and the value is
3094     an M-text describing the variable briefly.  This M-text may have a
3095     text property #Mdetail_text whose value is an M-text describing
3096     the variable in more detail.
3097
3098     The second element of VAR-INFO is for the value of the variable.
3099     The key is #Minteger, #Msymbol, or #Mtext, and the value is an
3100     integer, a symbol, or an M-text, respectively.  The variable is
3101     set to this value when an input context is created for the input
3102     method.
3103
3104     If there are no more elements, the variable can take any value
3105     that matches with the above type.  Otherwise, the remaining
3106     elements of VAR-INFO are to specify valid values of the variable.
3107
3108     If the type of the variable is integer, the following elements
3109     have the key #Minteger or #Mplist.  If it is #Minteger, the value
3110     is a valid integer value.  If it is #Mplist, the value is a plist
3111     of two of elements.  Both of them have the key #Minteger, and
3112     values are the minimum and maximum bounds of the valid value
3113     range.
3114
3115     If the type of the variable is symbol or M-text, the following
3116     elements of the plist have the key #Msymbol or #Mtext,
3117     respectively, and the value must be a valid one.
3118
3119     For instance, suppose an input method has the variables:
3120
3121     @li name:intvar, description: "value is an integer",
3122          initial value:0, value-range:0..3,10,20
3123
3124     @li name:symvar, description: "value is a symbol",
3125          initial value:nil, value-range:a, b, c, nil
3126
3127     @li name:txtvar, description: "value is an M-text",
3128          initial value:empty text, no value-range (i.e. any text)
3129
3130     Then, the returned plist has this form ('X:Y' means X is a key and Y is
3131     a value, and '(...)' means a plist):
3132
3133 @verbatim
3134     plist:(intvar:(mtext:'value is an integer'
3135                    integer:0
3136                    plist:(integer:0 integer:3)
3137                    integer:10
3138                    integer:20))
3139            symvar:(mtext:"value is a symbol"
3140                    symbol:nil
3141                    symbol:a
3142                    symbol:b
3143                    symbol:c
3144                    symbol:nil))
3145            txtvar:(mtext:"value is an M-text"
3146                    mtext:""))
3147 @endverbatim
3148
3149     @return
3150     If the input method uses any variables, a pointer to #MPlist is
3151     returned.  As the plist is kept in the library, a caller must not
3152     modify nor free it.  If the input method does not use any
3153     variable, @c NULL is returned.  */
3154 /***ja
3155     @brief ÆþÎϥ᥽¥Ã¥É¤ÎÊÑ¿ô¥ê¥¹¥È¤òÆÀ¤ë.
3156
3157     ´Ø¿ô minput_get_variables () ¤Ï¡¢$LANGUAGE ¤È $NAME 
3158     ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤Î¿¶¤ëÉñ¤¤¤òÀ©¸æ¤¹¤ëÊÑ¿ô¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È 
3159     (#MPlist) ¤òÊÖ¤¹¡£¥ê¥¹¥È¤Î³ÆÍ×ÁǤΥ­¡¼¤ÏÊÑ¿ô¤òɽ¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
3160     ³ÆÍ×ÁǤÎÃͤϲ¼µ­¤Î VAR-INFO 
3161     ¤Î·Á¼°¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ç¤¢¤ê¡¢³ÆÊÑ¿ô¤Ë´Ø¤¹¤ë¾ðÊó¤ò¼¨¤·¤Æ¤¤¤ë¡£
3162
3163     VAR-INFO ¤ÎÂè°ìÍ×ÁǤϥ­¡¼¤È¤·¤Æ #Mtext ¤ò¡¢ÃͤȤ·¤Æ¤½¤ÎÊÑ¿ô¤ò´Êñ¤ËÀâÌÀ¤¹¤ë
3164     M-text ¤ò»ý¤Ä¡£¤³¤Î M-text ¤Ï¡¢#Mdetail_text 
3165     ¤ò¥­¡¼¤È¤¹¤ë¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä¤³¤È¤¬¤Ç¤­¡¢¤½¤ÎÃͤϤ½¤ÎÊÑ¿ô¤ò¤è¤ê¾ÜºÙ¤ËÀâÌÀ¤¹¤ë
3166     M-text ¤Ç¤¢¤ë¡£
3167
3168     VAR-INFO ¤ÎÂèÆóÍ×ÁǤÏÊÑ¿ô¤ÎÃͤò¼¨¤¹¡£¥­¡¼¤Ï #Minteger, #Msymbol,
3169     #Mtext ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ê¡¢ÃͤϤ½¤ì¤¾¤ìÀ°¿ôÃÍ¡¢¥·¥ó¥Ü¥ë¡¢M-text  ¤Ç¤¢¤ë¡£
3170     ¤³¤ÎÆþÎϥ᥽¥Ã¥ÉÍѤÎÆþÎÏ¥³¥ó¥Æ¥¹¥È¤¬ºî¤é¤ì¤ë»þÅÀ¤Ç¤Ï¡¢ÊÑ¿ô¤Ï¤³¤ÎÃͤËÀßÄꤵ¤ì¤Æ¤¤¤ë¡£
3171
3172     VAR-INFO ¤Ë¤½¤ì°Ê³°¤ÎÍ×ÁǤ¬Ìµ¤±¤ì¤Ð¡¢ÊÑ¿ô¤Ï¾åµ­¤Î·¿¤Ë¹çÃפ¹¤ë¸Â¤ê¤É¤Î¤è¤¦¤ÊÃͤò¤È¤ë¤³¤È¤â¤Ç¤­¤ë¡£
3173     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢VAR-INFO ¤Î»Ä¤ê¤ÎÍ×ÁǤˤè¤Ã¤ÆÊÑ¿ô¤ÎÍ­¸ú¤ÊÃͤ¬»ØÄꤵ¤ì¤ë¡£
3174
3175     ÊÑ¿ô¤Î·¿¤¬À°¿ô¤Ç¤¢¤ì¤Ð¡¢¤½¤ì°Ê¹ß¤ÎÍ×ÁǤϠ#Minteger ¤« #Mplist 
3176     ¤ò¥­¡¼¤È¤·¤Æ»ý¤Ä¡£ #Minteger ¤Ç¤¢¤ì¤Ð¡¢ÃͤÏÍ­¸ú¤ÊÃͤò¼¨¤¹À°¿ôÃͤǤ¢¤ë¡£
3177     #Mplist ¤Ç¤¢¤ì¤Ð¡¢ÃͤÏÆó¤Ä¤ÎÍ×ÁǤò»ý¤Ä¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ç¤¢¤ê¡¢³ÆÍ×ÁǤϥ­¡¼¤È¤·¤Æ
3178     #Minteger ¤ò¡¢ÃͤȤ·¤Æ¤½¤ì¤¾¤ìÍ­¸ú¤ÊÃͤξå¸ÂÃͤȲ¼¸ÂÃͤò¤È¤ë¡£
3179
3180     ÊÑ¿ô¤Î·¿¤¬¥·¥ó¥Ü¥ë¤« M-text ¤Ç¤¢¤ì¤Ð¡¢¤½¤ì°Ê¹ß¤ÎÍ×ÁǤϥ­¡¼¤È¤·¤Æ¤½¤ì¤¾¤ì
3181     #Msymbol ¤« #Mtext ¤ò»ý¤Á¡¢ÃͤϤ½¤Î·¿¤Ë¹çÃפ¹¤ë¤â¤Î¤Ç¤¢¤ë¡£
3182
3183     Îã¤È¤·¤Æ¡¢¤¢¤ëÆþÎϥ᥽¥Ã¥É¤¬¼¡¤Î¤è¤¦¤ÊÊÑ¿ô¤ò»ý¤Ä¾ì¹ç¤ò¹Í¤¨¤è¤¦¡£
3184
3185     @li name:intvar, ÀâÌÀ:"value is an integer",
3186         ½é´üÃÍ:0, ÃͤÎÈÏ°Ï:0..3,10,20
3187
3188     @li name:symvar, ÀâÌÀ:"value is a symbol",
3189          ½é´üÃÍ:nil, ÃͤÎÈÏ°Ï:a, b, c, nil
3190
3191     @li name:txtvar, ÀâÌÀ:"value is an M-text",
3192         ½é´üÃÍ:empty text, ÃͤÎÈϰϤʤ·(¤É¤ó¤Ê M-text ¤Ç¤â²Ä)
3193
3194     ¤³¤Î¾ì¹ç¡¢ÊÖ¤µ¤ì¤ë¥ê¥¹¥È¤Ï°Ê²¼¤Î¤è¤¦¤Ë¤Ê¤ë¡£¡Ê'X:Y' ¤È¤¤¤¦µ­Ë¡¤Ï X 
3195     ¤¬¥­¡¼¤Ç Y ¤¬ÃͤǤ¢¤ë¤³¤È¤ò¡¢¤Þ¤¿ '(...)' ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ò¼¨¤¹¡£¡Ë
3196
3197 @verbatim
3198     plist:(intvar:(mtext:"value is an integer"
3199                    integer:0
3200                    plist:(integer:0 integer:3)
3201                    integer:10
3202                    integer:20))
3203            symvar:(mtext:"value is a symbol"
3204                    symbol:nil
3205                    symbol:a
3206                    symbol:b
3207                    symbol:c
3208                    symbol:nil))
3209            txtvar:(mtext:"value is an M-text"
3210                    mtext:""))
3211 @endverbatim
3212
3213     @return 
3214     ÆþÎϥ᥽¥Ã¥É¤¬²¿¤é¤«¤ÎÊÑ¿ô¤ò»ÈÍѤ·¤Æ¤¤¤ì¤Ð #MPlist ¤Ø¤ÎÊÑ¿ô¤òÊÖ¤¹¡£
3215     ÊÖ¤µ¤ì¤ë¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ï¥é¥¤¥Ö¥é¥ê¤Ë¤è¤Ã¤Æ´ÉÍý¤µ¤ì¤Æ¤ª¤ê¡¢¸Æ¤Ó½Ð¤·Â¦¤ÇÊѹ¹¤·¤¿¤ê²òÊü¤·¤¿¤ê¤·¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
3216     ÆþÎϥ᥽¥Ã¥É¤¬ÊÑ¿ô¤ò°ìÀÚ»ÈÍѤ·¤Æ¤Ê¤±¤ì¤Ð¡¢@c NULL ¤òÊÖ¤¹¡£  */
3217
3218 MPlist *
3219 minput_get_variables (MSymbol language, MSymbol name)
3220 {
3221   MPlist *plist = get_variable_list (language, name);
3222
3223   return (! plist || MPLIST_TAIL_P (plist) ? NULL : plist);
3224 }
3225
3226 /***en
3227     @brief Set the initial value of an input method variable.
3228
3229     The minput_set_variable () function sets the initial value of
3230     input method variable $VARIABLE to $VALUE for the input method
3231     specified by $LANGUAGE and $NAME.
3232
3233     By default, the initial value is 0.
3234
3235     This setting gets effective in a newly opened input method.
3236
3237     @return
3238     If the operation was successful, 0 is returned.  Otherwise -1 is
3239     returned, and #merror_code is set to #MERROR_IM.  */
3240 /***ja
3241     @brief ÆþÎϥ᥽¥Ã¥ÉÊÑ¿ô¤Î½é´üÃͤòÀßÄꤹ¤ë.
3242
3243     ´Ø¿ô minput_set_variable () ¤Ï¡¢$LANGUAGE ¤È $NAME 
3244     ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ÎÆþÎϥ᥽¥Ã¥ÉÊÑ¿ô $VARIABLE
3245     ¤Î½é´üÃͤò¡¢ $VALUE ¤ËÀßÄꤹ¤ë¡£
3246
3247     ¥Ç¥Õ¥©¥ë¥È¤Î½é´üÃͤϠ0 ¤Ç¤¢¤ë¡£
3248
3249     ¤³¤ÎÀßÄê¤Ï¡¢¿·¤·¤¯¥ª¡¼¥×¥ó¤µ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤«¤éÍ­¸ú¤È¤Ê¤ë¡£
3250
3251     @return
3252     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤·¡¢
3253     #merror_code ¤ò #MERROR_IM ¤ËÀßÄꤹ¤ë¡£  */
3254
3255 int
3256 minput_set_variable (MSymbol language, MSymbol name,
3257                      MSymbol variable, void *value)
3258 {
3259   MPlist *plist, *val_element, *range_element;
3260   MSymbol type;
3261
3262   if (language == Mnil || name == Mnil)
3263     MERROR (MERROR_IM, -1);
3264   plist = get_variable_list (language, name);
3265   if (! plist)
3266     MERROR (MERROR_IM, -1);
3267   plist = (MPlist *) mplist_get (plist, variable);
3268   if (! plist)
3269     MERROR (MERROR_IM, -1);
3270   val_element = MPLIST_NEXT (plist);
3271   type = MPLIST_KEY (val_element);
3272   range_element = MPLIST_NEXT (val_element);
3273     
3274   if (! MPLIST_TAIL_P (range_element))
3275     {
3276       if (type == Minteger)
3277         {
3278           int val = (int) value, this_val;
3279       
3280           MPLIST_DO (plist, range_element)
3281             {
3282               this_val = (int) MPLIST_VAL (plist);
3283               if (MPLIST_PLIST_P (plist))
3284                 {
3285                   int min_bound, max_bound;
3286                   MPlist *pl = MPLIST_PLIST (plist);
3287
3288                   min_bound = (int) MPLIST_VAL (pl);
3289                   pl = MPLIST_NEXT (pl);
3290                   max_bound = (int) MPLIST_VAL (pl);
3291                   if (val >= min_bound && val <= max_bound)
3292                     break;
3293                 }
3294               else if (val == this_val)
3295                 break;
3296             }
3297           if (MPLIST_TAIL_P (plist))
3298             MERROR (MERROR_IM, -1);
3299         }
3300       else if (type == Msymbol)
3301         {
3302           MPLIST_DO (plist, range_element)
3303             if (MPLIST_SYMBOL (plist) == (MSymbol) value)
3304               break;
3305           if (MPLIST_TAIL_P (plist))
3306             MERROR (MERROR_IM, -1);
3307         }
3308       else                      /* type == Mtext */
3309         {
3310           MPLIST_DO (plist, range_element)
3311             if (mtext_cmp (MPLIST_MTEXT (plist), (MText *) value) == 0)
3312               break;
3313           if (MPLIST_TAIL_P (plist))
3314             MERROR (MERROR_IM, -1);
3315           M17N_OBJECT_REF (value);
3316         }
3317     }
3318
3319   mplist_set (val_element, type, value);
3320   return 0;
3321 }
3322
3323 /*** @} */
3324 /*=*/
3325 /*** @addtogroup m17nDebug */
3326 /*=*/
3327 /*** @{  */
3328 /*=*/
3329
3330 /***en
3331     @brief Dump an input method.
3332
3333     The mdebug_dump_im () function prints the input method $IM in a
3334     human readable way to the stderr.  $INDENT specifies how many
3335     columns to indent the lines but the first one.
3336
3337     @return
3338     This function returns $IM.  */
3339 /***ja
3340     @brief ÆþÎϥ᥽¥Ã¥É¤ò¥À¥ó¥×¤¹¤ë.
3341
3342     ´Ø¿ô mdebug_dump_im () ¤ÏÆþÎϥ᥽¥Ã¥É $IM ¤ò stderr 
3343     ¤Ë¿Í´Ö¤Ë²ÄÆɤʷÁ¤Ç°õºþ¤¹¤ë¡£$INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£
3344
3345     @return
3346     ¤³¤Î´Ø¿ô¤Ï $IM ¤òÊÖ¤¹¡£  */
3347
3348 MInputMethod *
3349 mdebug_dump_im (MInputMethod *im, int indent)
3350 {
3351   MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
3352   char *prefix;
3353
3354   prefix = (char *) alloca (indent + 1);
3355   memset (prefix, 32, indent);
3356   prefix[indent] = '\0';
3357
3358   fprintf (stderr, "(input-method %s %s ", msymbol_name (im->language),
3359            msymbol_name (im->name));
3360   mdebug_dump_mtext (im_info->title, 0, 0);
3361   if (im->name != Mnil)
3362     {
3363       MPlist *state;
3364
3365       MPLIST_DO (state, im_info->states)
3366         {
3367           fprintf (stderr, "\n%s  ", prefix);
3368           dump_im_state (MPLIST_VAL (state), indent + 2);
3369         }
3370     }
3371   fprintf (stderr, ")");
3372   return im;
3373 }
3374
3375 /*** @} */ 
3376
3377 /*
3378   Local Variables:
3379   coding: euc-japan
3380   End:
3381 */