(preedit_delete): Fix typo.
[m17n/m17n-lib.git] / src / input.c
1 /* input.c -- input method module.
2    Copyright (C) 2003, 2004, 2005, 2006
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 an 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 its 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 drivers utilize the input processing engine
42     provided by the m17n library itself.  The m17n database may
43     provide input methods that are not limited to a specific language.
44     The database uses @c Mt as LANGUAGE of those input methods.
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 has 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 its body is
56     defined in an external resource (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 °Ê³°¤Î¤â¤Î¤Ç¤¢¤ê¡¢¤½¤ÎËÜÂÎ
95     ¤Ïm17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë<Minput_method, LANGUAGE, NAME> ¤È¤¤¤¦¥¿¥°¤òÉÕ
96     ¤±¤ÆÄêµÁ¤µ¤ì¤Æ¤¤¤ë¡£¤³¤Î¼ï¤ÎÆþÎϥ᥽¥Ã¥É¤ËÂФ·¤Æ¡¢m17n ¥é¥¤¥Ö¥é¥ê¤Ç
97     ¤ÏCUI ÍѤȠGUI ÍѤ½¤ì¤¾¤ì¤ÎÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤ò¤¢¤é¤«¤¸¤áÄêµÁ¤·¤Æ
98     ¤¤¤ë¡£¤³¤ì¤é¤Î¥É¥é¥¤¥Ð¤Ï m17n ¥é¥¤¥Ö¥é¥ê¼«ÂΤÎÆþÎϽèÍý¥¨¥ó¥¸¥ó¤òÍø
99     ÍѤ¹¤ë¡£m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë¤Ï¡¢ÆÃÄê¤Î¸À¸ìÀìÍѤǤʤ¤ÆþÎϥ᥽¥Ã¥É¤òÄê
100     µÁ¤¹¤ë¤³¤È¤â¤Ç¤­¡¢¤½¤Î¤è¤¦¤ÊÆþÎϥ᥽¥Ã¥É¤Î LANGUAGE ¤Ï @c Mt ¤Ç¤¢¤ë¡£
101
102     ÆâÉôÆþÎϥ᥽¥Ã¥É¤Ï¡¢¥æ¡¼¥¶¤ÎÆþÎÏ¥¤¥Ù¥ó¥È¤ËÂбþ¤·¤¿¥·¥ó¥Ü¥ë¤Ç¤¢¤ëÆþ
103     ÎÏ¥­¡¼¤ò¼õ¤±¼è¤ë¡£@c m17n @c ¥é¥¤¥Ö¥é¥ê ¤ÏÆþÎÏ¥¤¥Ù¥ó¥È¤¬¥¢¥×¥ê¥±¡¼
104     ¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ç¤É¤¦É½¸½¤µ¤ì¤Æ¤¤¤ë¤«¤òÃΤ뤳¤È¤¬¤Ç¤­¤Ê¤¤¤Î¤Ç¡¢Æþ
105     ÎÏ¥¤¥Ù¥ó¥È¤«¤éÆþÎÏ¥­¡¼¤Ø¤ÎÊÑ´¹¤Ï¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥Þ¤ÎÀÕǤ¤Ç
106     ¹Ô¤ï¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï´Ø¿ô minput_event_to_key () ¤Î
107     ÀâÌÀ¤ò»²¾È¡£
108
109     <li> ³°ÉôÆþÎϥ᥽¥Ã¥É
110
111     ³°ÉôÆþÎϥ᥽¥Ã¥É¤È¤Ï LANGUAGE ¤¬ @c Mnil ¤Î¤â¤Î¤Ç¤¢¤ê¡¢¤½¤ÎËÜÂΤϳ°
112     Éô¤Î¥ê¥½¡¼¥¹¤È¤·¤ÆÄêµÁ¤µ¤ì¤ë¡£¡Ê¤¿¤È¤¨¤ÐX Window System ¤ÎXIM ¤Ê
113     ¤É¡£) ¤³¤Î¼ï¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢¥·¥ó¥Ü¥ë NAME ¤Ï@c Minput_driver ¤ò
114     ¥­¡¼¤È¤¹¤ë¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Á¡¢¤½¤ÎÃͤÏÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó
115     ¥¿¤Ç¤¢¤ë¡£¤³¤Î¤³¤È¤Ë¤è¤ê¡¢Å¬Àڤʥɥ饤¥Ð¤ò½àÈ÷¤¹¤ë¤³¤È¤Ë¤è¤Ã¤Æ¡¢¤¤
116     ¤«¤Ê¤ë¼ïÎà¤ÎÆþÎϥ᥽¥Ã¥É¤â@c m17n @c ¥é¥¤¥Ö¥é¥ê ¤ÎÏÈÁȤÎÃæ¤Ç°·¤¦»ö
117     ¤¬¤Ç¤­¤ë¡£
118
119     ÍøÊØÀ­¤Î´ÑÅÀ¤«¤é¡¢m17n X ¥é¥¤¥Ö¥é¥ê¤Ï XIM ¤Î OverTheSpot ¤ÎÆþÎÏ¥¹¥¿
120     ¥¤¥ë¤ò¼Â¸½¤¹¤ëÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤òÄ󶡤·¡¢¤Þ¤¿¥·¥ó¥Ü¥ë @c Mxim ¤Î
121     @c Minput_driver ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤȤ·¤Æ¤½¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÝ»ý
122     ¤·¤Æ¤¤¤ë¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï m17n GUI API ¤Î¥É¥­¥å¥á¥ó¥È¤ò»²¾È¤Î¤³¤È¡£
123
124     </ul> 
125
126     ½èÍý¤Îή¤ì
127
128     ÆþÎϥ᥽¥Ã¥É½èÍý¤Îŵ·¿Åª¤Ê½èÍý¤Ï°Ê²¼¤Î¤è¤¦¤Ë¤Ê¤ë¡£
129     
130     @li ÆþÎϥ᥽¥Ã¥É¤Î¥ª¡¼¥×¥ó
131     @li ¤½¤ÎÆþÎϥ᥽¥Ã¥É¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤ÎÀ¸À®
132     @li ÆþÎÏ¥¤¥Ù¥ó¥È¤Î¥Õ¥£¥ë¥¿
133     @li ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ç¤ÎÀ¸À®¥Æ¥­¥¹¥È¤Î¸¡º÷     */
134
135 /*=*/
136
137 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
138 /*** @addtogroup m17nInternal
139      @{ */
140
141 #include <stdio.h>
142 #include <stdlib.h>
143 #include <string.h>
144 #include <sys/types.h>
145 #include <dirent.h>
146 #include <sys/stat.h>
147 #include <unistd.h>
148 #include <time.h>
149
150 #include "config.h"
151
152 #ifdef HAVE_DLFCN_H
153 #include <dlfcn.h>
154 #endif
155
156 #include "m17n-gui.h"
157 #include "m17n-misc.h"
158 #include "internal.h"
159 #include "mtext.h"
160 #include "input.h"
161 #include "symbol.h"
162 #include "plist.h"
163 #include "database.h"
164 #include "charset.h"
165
166 static int mdebug_mask = MDEBUG_INPUT;
167
168 static int fully_initialized;
169
170 static MSymbol Minput_method;
171
172 /** Symbols to load an input method data.  */
173 static MSymbol Mtitle, Mmacro, Mmodule, Mstate, Minclude;
174
175 /** Symbols for actions.  */
176 static MSymbol Minsert, Mdelete, Mmark, Mmove, Mpushback, Mundo, Mcall, Mshift;
177 static MSymbol Mselect, Mshow, Mhide, Mcommit, Munhandle;
178 static MSymbol Mset, Madd, Msub, Mmul, Mdiv, Mequal, Mless, Mgreater;
179 static MSymbol Mless_equal, Mgreater_equal;
180 static MSymbol Mcond;
181 static MSymbol Mplus, Mminus, Mstar, Mslash, Mand, Mor, Mnot;
182
183 /** Special action symbol.  */
184 static MSymbol Mat_reload;
185
186 static MSymbol M_candidates;
187
188 static MSymbol Mcandidate_list, Mcandidate_index;
189
190 static MSymbol Minit, Mfini;
191
192 /** Symbols for variables.  */
193 static MSymbol Mcandidates_group_size, Mcandidates_charset;
194
195 /** Symbols for key events.  */
196 static MSymbol one_char_symbol[256];
197
198 static MSymbol M_key_alias;
199
200 static MSymbol Mdescription, Mcommand, Mvariable, Mglobal, Mconfig;
201
202 static MSymbol M_gettext;
203
204 /** Structure to hold a map.  */
205
206 struct MIMMap
207 {
208   /** List of actions to take when we reach the map.  In a root map,
209       the actions are executed only when there is no more key.  */
210   MPlist *map_actions;
211
212   /** List of deeper maps.  If NULL, this is a terminal map.  */
213   MPlist *submaps;
214
215   /** List of actions to take when we leave the map successfully.  In
216       a root map, the actions are executed only when none of submaps
217       handle the current key.  */
218   MPlist *branch_actions;
219 };
220
221 typedef MPlist *(*MIMExternalFunc) (MPlist *plist);
222
223 typedef struct
224 {
225   void *handle;
226   MPlist *func_list;            /* function name vs (MIMExternalFunc *) */
227 } MIMExternalModule;
228
229 struct MIMState
230 {
231   M17NObject control;
232
233   /** Name of the state.  */
234   MSymbol name;
235
236   /** Title of the state, or NULL.  */
237   MText *title;
238
239   /** Key translation map of the state.  Built by merging all maps of
240       branches.  */
241   MIMMap *map;
242 };
243
244 #define CUSTOM_FILE "config.mic"
245
246 static MPlist *load_im_info_keys;
247
248 /* List of input method information.  The format is:
249      (LANGUAGE NAME t:IM_INFO ... ... ...)  */
250 static MPlist *im_info_list;
251
252 /* Database for user's customization file.  */
253 static MDatabase *im_custom_mdb;
254
255 /* List of input method information loaded from im_custom_mdb.  The
256    format is the same as im_info_list.  */
257 static MPlist *im_custom_list;
258
259 /* List of input method information configured by
260    minput_config_command and minput_config_variable.  The format is
261    the same as im_info_list.  */
262 static MPlist *im_config_list;
263
264 /* Global input method information.  It points into the element of
265    im_info_list corresponding to LANGUAGE == `nil' and NAME ==
266    `global'.  */
267 static MInputMethodInfo *global_info;
268
269 static int update_global_info (void);
270 static int update_custom_info (void);
271 static MInputMethodInfo *get_im_info (MSymbol, MSymbol, MSymbol, MSymbol);
272
273 \f
274 void
275 fully_initialize ()
276 {
277   char *key_names[32]
278     = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
279         "BackSpace", "Tab", "Linefeed", "Clear", NULL, "Return", NULL, NULL,
280         NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
281         NULL, NULL, NULL, "Escape", NULL, NULL, NULL, NULL };
282   char buf[6], buf2[32];
283   int i, j;
284   /* Maximum case: C-M-a, C-M-A, M-Return, C-A-a, C-A-A, A-Return.  */
285   MSymbol alias[7];
286
287   M_key_alias = msymbol ("  key-alias");
288
289   buf[0] = 'C';
290   buf[1] = '-';
291   buf[3] = '\0';
292   for (i = 0, buf[2] = '@'; i < ' '; i++, buf[2]++)
293     {
294       one_char_symbol[i] = msymbol (buf);
295       if (key_names[i] || (buf[2] >= 'A' && buf[2] <= 'Z'))
296         {
297           j = 0;
298           alias[j++] = one_char_symbol[i];
299           if (key_names[i])
300             {
301               /* Ex: `Escape' == `C-['  */
302               alias[j++] = msymbol (key_names[i]);
303             }
304           if (buf[2] >= 'A' && buf[2] <= 'Z')
305             {
306               /* Ex: `C-a' == `C-A'  */
307               buf[2] += 32;
308               alias[j++] = msymbol (buf);
309               buf[2] -= 32;
310             }
311           /* Establish cyclic alias chain.  */
312           alias[j] = alias[0];
313           while (--j >= 0)
314             msymbol_put (alias[j], M_key_alias, alias[j + 1]);
315         }
316     }
317   buf[0] = 'S';
318   for (i = buf[2] = ' '; i < 127; i++, buf[2]++)
319     {
320       one_char_symbol[i] = msymbol (buf + 2);
321       if (i >= 'A' && i <= 'Z')
322         {
323           /* Ex: `A' == `S-A' == `S-a'.  */
324           alias[0] = alias[3] = one_char_symbol[i];
325           alias[1] = msymbol (buf);
326           buf[2] += 32;
327           alias[2] = msymbol (buf);
328           buf[2] -= 32;
329           for (j = 0; j < 3; j++)
330             msymbol_put (alias[j], M_key_alias, alias[j + 1]);
331         }
332     }
333   buf[0] = 'C';
334
335   alias[0] = alias[2] = one_char_symbol[127] = msymbol ("Delete");
336   alias[1] = msymbol ("C-?");
337   for (j = 0; j < 2; j++)
338     msymbol_put (alias[j], M_key_alias, alias[j + 1]);
339
340   buf[3] = '-';
341   buf[5] = '\0';
342   buf2[1] = '-';
343   for (i = 128, buf[4] = '@'; i < 160; i++, buf[4]++)
344     {
345       j = 0;
346       /* `C-M-a' == `C-A-a' */
347       buf[2] = 'M';
348       alias[j++] = one_char_symbol[i] = msymbol (buf);
349       buf[2] = 'A';
350       alias[j++] = msymbol (buf);
351       if (key_names[i - 128])
352         {
353           /* Ex: `M-Escape' == `A-Escape' == `C-M-['.  */
354           buf2[0] = 'M';
355           strcpy (buf2 + 2, key_names[i - 128]);
356           alias[j++] = msymbol (buf2);
357           buf2[0] = 'A';
358           alias[j++] = msymbol (buf2);
359         }
360       if (buf[4] >= 'A' && buf[4] <= 'Z')
361         {
362           /* Ex: `C-M-a' == `C-M-A'.  */
363           buf[4] += 32;
364           buf[2] = 'M';
365           alias[j++] = msymbol (buf);
366           buf[2] = 'A';
367           alias[j++] = msymbol (buf);
368           buf[4] -= 32;
369         }
370       /* Establish cyclic alias chain.  */
371       alias[j] = alias[0];
372       while (--j >= 0)
373         msymbol_put (alias[j], M_key_alias, alias[j + 1]);
374     }
375   for (i = 160, buf[4] = ' '; i < 256; i++, buf[4]++)
376     {
377       buf[2] = 'M';
378       alias[0] = alias[2] = one_char_symbol[i] = msymbol (buf + 2);
379       buf[2] = 'A';
380       alias[1] = msymbol (buf + 2);
381       for (j = 0; j < 2; j++)
382         msymbol_put (alias[j], M_key_alias, alias[j + 1]);
383     }
384
385   alias[0] = alias[4] = one_char_symbol[255] = msymbol ("M-Delete");
386   alias[1] = msymbol ("A-Delete");
387   alias[2] = msymbol ("C-M-?");
388   alias[3] = msymbol ("C-A-?");
389   for (j = 0; j < 4; j++)
390     msymbol_put (alias[j], M_key_alias, alias[j + 1]);
391
392   Minput_method = msymbol ("input-method");
393   Mtitle = msymbol ("title");
394   Mmacro = msymbol ("macro");
395   Mmodule = msymbol ("module");
396   Mmap = msymbol ("map");
397   Mstate = msymbol ("state");
398   Minclude = msymbol ("include");
399   Minsert = msymbol ("insert");
400   M_candidates = msymbol ("  candidates");
401   Mdelete = msymbol ("delete");
402   Mmove = msymbol ("move");
403   Mmark = msymbol ("mark");
404   Mpushback = msymbol ("pushback");
405   Mundo = msymbol ("undo");
406   Mcall = msymbol ("call");
407   Mshift = msymbol ("shift");
408   Mselect = msymbol ("select");
409   Mshow = msymbol ("show");
410   Mhide = msymbol ("hide");
411   Mcommit = msymbol ("commit");
412   Munhandle = msymbol ("unhandle");
413   Mset = msymbol ("set");
414   Madd = msymbol ("add");
415   Msub = msymbol ("sub");
416   Mmul = msymbol ("mul");
417   Mdiv = msymbol ("div");
418   Mequal = msymbol ("=");
419   Mless = msymbol ("<");
420   Mgreater = msymbol (">");
421   Mless_equal = msymbol ("<=");
422   Mgreater_equal = msymbol (">=");
423   Mcond = msymbol ("cond");
424   Mplus = msymbol ("+");
425   Mminus = msymbol ("-");
426   Mstar = msymbol ("*");
427   Mslash = msymbol ("/");
428   Mand = msymbol ("&");
429   Mor = msymbol ("|");
430   Mnot = msymbol ("!");
431
432   Mat_reload = msymbol ("@reload");
433
434   Mcandidates_group_size = msymbol ("candidates-group-size");
435   Mcandidates_charset = msymbol ("candidates-charset");
436
437   Mcandidate_list = msymbol_as_managing_key ("  candidate-list");
438   Mcandidate_index = msymbol ("  candidate-index");
439
440   Minit = msymbol ("init");
441   Mfini = msymbol ("fini");
442
443   Mdescription = msymbol ("description");
444   Mcommand = msymbol ("command");
445   Mvariable = msymbol ("variable");
446   Mglobal = msymbol ("global");
447   Mconfig = msymbol ("config");
448   M_gettext = msymbol ("_");
449
450   load_im_info_keys = mplist ();
451   mplist_add (load_im_info_keys, Mstate, Mnil);
452   mplist_push (load_im_info_keys, Mmap, Mnil);
453
454   im_info_list = mplist ();
455   im_config_list = im_custom_list = NULL;
456   im_custom_mdb = NULL;
457   update_custom_info ();
458   global_info = NULL;
459   update_global_info ();
460
461   fully_initialized = 1;
462 }
463
464 #define MINPUT__INIT()          \
465   do {                          \
466     if (! fully_initialized)    \
467       fully_initialize ();      \
468   } while (0)
469
470 \f
471 static int
472 marker_code (MSymbol sym, int surrounding)
473 {
474   char *name;
475
476   if (sym == Mnil)
477     return -1;
478   name = MSYMBOL_NAME (sym);
479   return (name[0] != '@' ? -1
480           : (((name[1] >= '0' && name[1] <= '9')
481               || name[1] == '<' || name[1] == '>' || name[1] == '='
482               || name[1] == '[' || name[1] == ']'
483               || name[1] == '@')
484              && name[2] == '\0') ? name[1]
485           : (name[1] != '+' && name[1] != '-') ? -1
486           : (name[2] == '\0' || surrounding) ? name[1]
487           : -1);
488 }
489
490
491 static MPlist *
492 resolve_variable (MInputContextInfo *ic_info, MSymbol var)
493 {
494   MPlist *plist = mplist__assq (ic_info->vars, var);
495
496   if (plist)
497     {
498       plist = MPLIST_PLIST (plist);
499       return MPLIST_NEXT (plist);
500     }
501
502   plist = mplist ();
503   mplist_push (ic_info->vars, Mplist, plist);
504   M17N_OBJECT_UNREF (plist);
505   plist = mplist_add (plist, Msymbol, var);
506   plist = mplist_add (plist, Minteger, (void *) 0);
507   return plist;
508 }
509
510 static MText *
511 get_surrounding_text (MInputContext *ic, int len)
512 {
513   MText *mt = NULL;
514
515   mplist_push (ic->plist, Minteger, (void *) len);
516   if (minput__callback (ic, Minput_get_surrounding_text) >= 0
517       && MPLIST_MTEXT_P (ic->plist))
518     mt = MPLIST_MTEXT (ic->plist);
519   mplist_pop (ic->plist);
520   return mt;
521 }
522
523 static void
524 delete_surrounding_text (MInputContext *ic, int pos)
525 {
526   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
527
528   mplist_push (ic->plist, Minteger, (void *) pos);
529   minput__callback (ic, Minput_delete_surrounding_text);
530   mplist_pop (ic->plist);
531   if (pos < 0)
532     {
533       M17N_OBJECT_UNREF (ic_info->preceding_text);
534       ic_info->preceding_text = NULL;
535     }
536   else if (pos > 0)
537     {
538       M17N_OBJECT_UNREF (ic_info->following_text);
539       ic_info->following_text = NULL;
540     }
541 }
542
543 static int
544 get_preceding_char (MInputContext *ic, int pos)
545 {
546   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
547   MText *mt;
548   int len;
549
550   if (pos && ic_info->preceding_text)
551     {
552       len = mtext_nchars (ic_info->preceding_text);
553       if (pos <= len)
554         return mtext_ref_char (ic_info->preceding_text, len - pos);
555     }
556   mt = get_surrounding_text (ic, - pos);
557   if (! mt)
558     return -2;
559   len = mtext_nchars (mt);
560   if (ic_info->preceding_text)
561     {
562       if (mtext_nchars (ic_info->preceding_text) < len)
563         {
564           M17N_OBJECT_UNREF (ic_info->preceding_text);
565           ic_info->preceding_text = mt;
566         }
567     }
568   else
569     ic_info->preceding_text = mt;
570   if (pos > len)
571     return -1;
572   return mtext_ref_char (ic_info->preceding_text, len - pos);
573 }
574
575 static int
576 get_following_char (MInputContext *ic, int pos)
577 {
578   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
579   MText *mt;
580   int len;
581
582   if (ic_info->following_text)
583     {
584       len = mtext_nchars (ic_info->following_text);
585       if (pos <= len)
586         return mtext_ref_char (ic_info->following_text, pos - 1);
587     }
588   mt = get_surrounding_text (ic, pos);
589   if (! mt)
590     return -2;
591   len = mtext_nchars (mt);
592   if (ic_info->following_text)
593     {
594       if (mtext_nchars (ic_info->following_text) < len)
595         {
596           M17N_OBJECT_UNREF (ic_info->following_text);
597           ic_info->following_text = mt;
598         }
599     }
600   else
601     ic_info->following_text = mt;
602   if (pos > len)
603     return -1;
604   return mtext_ref_char (ic_info->following_text, pos - 1);
605 }
606
607 static int
608 surrounding_pos (MSymbol sym)
609 {
610   char *name;
611
612   if (sym == Mnil)
613     return 0;
614   name = MSYMBOL_NAME (sym);
615   if (name[0] == '@'
616       && (name[1] == '-' || name[1] == '+')
617       && name[2] >= '1' && name[2] <= '9')
618     return (name[1] == '-' ? - atoi (name + 2) : atoi (name + 2));
619   return 0;
620 }
621
622 static int
623 integer_value (MInputContext *ic, MPlist *arg, MPlist **value, int surrounding)
624 {
625   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
626   int code, pos;
627   MText *preedit = ic->preedit;
628   int len = mtext_nchars (preedit);
629
630   if (value)
631     *value = NULL;
632   if (MPLIST_INTEGER_P (arg))
633     return MPLIST_INTEGER (arg);
634
635   code = marker_code (MPLIST_SYMBOL (arg), surrounding);
636   if (code < 0)
637     {
638       MPlist *val = resolve_variable (ic_info, MPLIST_SYMBOL (arg));
639
640       if (value)
641         *value = val;
642       return (MPLIST_INTEGER_P (val) ? MPLIST_INTEGER (val) : 0);
643     }
644   if (code == '@')
645     return ic_info->key_head;
646   if ((code == '-' || code == '+'))
647     {
648       char *name = MSYMBOL_NAME (MPLIST_SYMBOL (arg));
649
650       if (name[2])
651         {
652           pos = atoi (name + 1);
653           if (pos == 0)
654             return get_preceding_char (ic, 0);
655           pos = ic->cursor_pos + pos;
656           if (pos < 0)
657             return get_preceding_char (ic, - pos);
658           if (pos >= len)
659             return get_following_char (ic, pos - len + 1);
660         }
661       else
662         pos = ic->cursor_pos + (code == '+' ? 1 : -1);
663     }
664   else if (code >= '0' && code <= '9')
665     pos = code - '0';
666   else if (code == '=')
667     pos = ic->cursor_pos;
668   else if (code == '[')
669     pos = ic->cursor_pos - 1;
670   else if (code == ']')
671     pos = ic->cursor_pos + 1;
672   else if (code == '<')
673     pos = 0;
674   else if (code == '>')
675     pos = len - 1;
676   return (pos >= 0 && pos < len ? mtext_ref_char (preedit, pos) : -1);
677 }
678
679 static int
680 parse_expression (MPlist *plist)
681 {
682   MSymbol op;
683
684   if (MPLIST_INTEGER_P (plist) || MPLIST_SYMBOL_P (plist))
685     return 0;
686   if (! MPLIST_PLIST_P (plist))
687     return -1;
688   plist = MPLIST_PLIST (plist);
689   op = MPLIST_SYMBOL (plist);
690   if (op != Mplus && op != Mminus && op != Mstar && op != Mslash
691       && op != Mand && op != Mor && op != Mnot
692       && op != Mless && op != Mgreater && op != Mequal
693       && op != Mless_equal && op != Mgreater_equal)
694     MERROR (MERROR_IM, -1);
695   MPLIST_DO (plist, MPLIST_NEXT (plist))
696     if (parse_expression (plist) < 0)
697       return -1;
698   return 0;
699 }
700
701 static int
702 resolve_expression (MInputContext *ic, MPlist *plist)
703 {
704   int val;
705   MSymbol op;
706   
707   if (MPLIST_INTEGER_P (plist))
708     return MPLIST_INTEGER (plist);
709   if (MPLIST_SYMBOL_P (plist))
710     return integer_value (ic, plist, NULL, 1);
711   if (! MPLIST_PLIST_P (plist))
712     return 0;
713   plist = MPLIST_PLIST (plist);
714   if (! MPLIST_SYMBOL_P (plist))
715     return 0;
716   op = MPLIST_SYMBOL (plist);
717   plist = MPLIST_NEXT (plist);
718   val = resolve_expression (ic, plist);
719   if (op == Mplus)
720     MPLIST_DO (plist, MPLIST_NEXT (plist))
721       val += resolve_expression (ic, plist);
722   else if (op == Mminus)
723     MPLIST_DO (plist, MPLIST_NEXT (plist))
724       val -= resolve_expression (ic, plist);
725   else if (op == Mstar)
726     MPLIST_DO (plist, MPLIST_NEXT (plist))
727       val *= resolve_expression (ic, plist);
728   else if (op == Mslash)
729     MPLIST_DO (plist, MPLIST_NEXT (plist))
730       val /= resolve_expression (ic, plist);
731   else if (op == Mand)
732     MPLIST_DO (plist, MPLIST_NEXT (plist))
733       val &= resolve_expression (ic, plist);
734   else if (op == Mor)
735     MPLIST_DO (plist, MPLIST_NEXT (plist))
736       val |= resolve_expression (ic, plist);
737   else if (op == Mnot)
738     val = ! val;
739   else if (op == Mless)
740     val = val < resolve_expression (ic, MPLIST_NEXT (plist));
741   else if (op == Mequal)
742     val = val == resolve_expression (ic, MPLIST_NEXT (plist));
743   else if (op == Mgreater)
744     val = val > resolve_expression (ic, MPLIST_NEXT (plist));
745   else if (op == Mless_equal)
746     val = val <= resolve_expression (ic, MPLIST_NEXT (plist));
747   else if (op == Mgreater_equal)
748     val = val >= resolve_expression (ic, MPLIST_NEXT (plist));
749   return val;
750 }
751
752 /* Parse PLIST as an action list.  PLIST should have this form:
753       PLIST ::= ( (ACTION-NAME ACTION-ARG *) *).
754    Return 0 if successfully parsed, otherwise return -1.  */
755
756 static int
757 parse_action_list (MPlist *plist, MPlist *macros)
758 {
759   MPLIST_DO (plist, plist)
760     {
761       if (MPLIST_MTEXT_P (plist))
762         {
763           /* This is a short form of (insert MTEXT).  */
764           /* if (mtext_nchars (MPLIST_MTEXT (plist)) == 0)
765              MERROR (MERROR_IM, -1); */
766         }
767       else if (MPLIST_PLIST_P (plist)
768                && (MPLIST_MTEXT_P (MPLIST_PLIST (plist))
769                    || MPLIST_PLIST_P (MPLIST_PLIST (plist))))
770         {
771           MPlist *pl;
772
773           /* This is a short form of (insert (GROUPS *)).  */
774           MPLIST_DO (pl, MPLIST_PLIST (plist))
775             {
776               if (MPLIST_PLIST_P (pl))
777                 {
778                   MPlist *elt;
779
780                   MPLIST_DO (elt, MPLIST_PLIST (pl))
781                     if (! MPLIST_MTEXT_P (elt)
782                         || mtext_nchars (MPLIST_MTEXT (elt)) == 0)
783                       MERROR (MERROR_IM, -1);
784                 }
785               else
786                 {
787                   if (! MPLIST_MTEXT_P (pl)
788                       || mtext_nchars (MPLIST_MTEXT (pl)) == 0)
789                     MERROR (MERROR_IM, -1);
790                 }
791             }
792         }
793       else if (MPLIST_INTEGER_P (plist))
794         {
795           int c = MPLIST_INTEGER (plist);
796
797           if (c < 0 || c > MCHAR_MAX)
798             MERROR (MERROR_IM, -1);
799         }
800       else if (MPLIST_PLIST_P (plist)
801                && MPLIST_SYMBOL_P (MPLIST_PLIST (plist)))
802         {
803           MPlist *pl = MPLIST_PLIST (plist);
804           MSymbol action_name = MPLIST_SYMBOL (pl);
805
806           pl = MPLIST_NEXT (pl);
807
808           if (action_name == Minsert)
809             {
810               if (MPLIST_MTEXT_P (pl))
811                 {
812                   if (mtext_nchars (MPLIST_MTEXT (pl)) == 0)
813                     MERROR (MERROR_IM, -1);
814                 }
815               else if (MPLIST_PLIST_P (pl))
816                 {
817                   MPLIST_DO (pl, pl)
818                     {
819                       if (MPLIST_PLIST_P (pl))
820                         {
821                           MPlist *elt;
822
823                           MPLIST_DO (elt, MPLIST_PLIST (pl))
824                             if (! MPLIST_MTEXT_P (elt)
825                                 || mtext_nchars (MPLIST_MTEXT (elt)) == 0)
826                               MERROR (MERROR_IM, -1);
827                         }
828                       else
829                         {
830                           if (! MPLIST_MTEXT_P (pl)
831                               || mtext_nchars (MPLIST_MTEXT (pl)) == 0)
832                             MERROR (MERROR_IM, -1);
833                         }
834                     }
835                 }
836               else if (! MPLIST_SYMBOL_P (pl))
837                 MERROR (MERROR_IM, -1); 
838             }
839           else if (action_name == Mselect
840                    || action_name == Mdelete
841                    || action_name == Mmove)
842             {
843               if (parse_expression (pl) < 0)
844                 return -1;
845             }
846           else if (action_name == Mmark
847                    || action_name == Mcall
848                    || action_name == Mshift)
849             {
850               if (! MPLIST_SYMBOL_P (pl))
851                 MERROR (MERROR_IM, -1);
852             }
853           else if (action_name == Mundo)
854             {
855               if (! MPLIST_TAIL_P (pl))
856                 {
857                   if (! MPLIST_SYMBOL_P (pl)
858                       && (! MPLIST_INTEGER_P (pl)
859                           || MPLIST_INTEGER (pl) == 0))
860                     MERROR (MERROR_IM, -1);                 
861                 }
862             }
863           else if (action_name == Mpushback)
864             {
865               if (MPLIST_MTEXT_P (pl))
866                 {
867                   MText *mt = MPLIST_MTEXT (pl);
868
869                   if (mtext_nchars (mt) != mtext_nbytes (mt))
870                     MERROR (MERROR_IM, -1);                 
871                 }
872               else if (MPLIST_PLIST_P (pl))
873                 {
874                   MPlist *p;
875
876                   MPLIST_DO (p, MPLIST_PLIST (pl))
877                     if (! MPLIST_SYMBOL_P (p))
878                       MERROR (MERROR_IM, -1);
879                 }
880               else if (! MPLIST_INTEGER_P (pl))
881                 MERROR (MERROR_IM, -1);
882             }
883           else if (action_name == Mset || action_name == Madd
884                    || action_name == Msub || action_name == Mmul
885                    || action_name == Mdiv)
886             {
887               if (! MPLIST_SYMBOL_P (pl))
888                 MERROR (MERROR_IM, -1);
889               if (parse_expression (MPLIST_NEXT (pl)) < 0)
890                 return -1;
891             }
892           else if (action_name == Mequal || action_name == Mless
893                    || action_name == Mgreater || action_name == Mless_equal
894                    || action_name == Mgreater_equal)
895             {
896               if (parse_expression (pl) < 0
897                   || parse_expression (MPLIST_NEXT (pl)) < 0)
898                 return -1;
899               pl = MPLIST_NEXT (MPLIST_NEXT (pl));
900               if (! MPLIST_PLIST_P (pl))
901                 MERROR (MERROR_IM, -1);
902               if (parse_action_list (MPLIST_PLIST (pl), macros) < 0)
903                 MERROR (MERROR_IM, -1);
904               pl = MPLIST_NEXT (pl);
905               if (MPLIST_PLIST_P (pl)
906                   && parse_action_list (MPLIST_PLIST (pl), macros) < 0)
907                 MERROR (MERROR_IM, -1);
908             }
909           else if (action_name == Mshow || action_name == Mhide
910                    || action_name == Mcommit || action_name == Munhandle)
911             ;
912           else if (action_name == Mcond)
913             {
914               MPLIST_DO (pl, pl)
915                 if (! MPLIST_PLIST_P (pl))
916                   MERROR (MERROR_IM, -1);
917             }
918           else if (! macros || ! mplist_get (macros, action_name))
919             MERROR (MERROR_IM, -1);
920         }
921       else if (! MPLIST_SYMBOL_P (plist))
922         MERROR (MERROR_IM, -1);
923     }
924
925   return 0;
926 }
927
928 static MPlist *
929 resolve_command (MPlist *cmds, MSymbol command)
930 {
931   MPlist *plist;
932
933   if (! cmds || ! (plist = mplist__assq (cmds, command)))
934     return NULL;
935   plist = MPLIST_PLIST (plist); /* (NAME DESC STATUS [KEYSEQ ...]) */
936   plist = MPLIST_NEXT (plist);
937   plist = MPLIST_NEXT (plist);
938   plist = MPLIST_NEXT (plist);
939   return plist;
940 }
941
942 /* Load a translation into MAP from PLIST.
943    PLIST has this form:
944       PLIST ::= ( KEYSEQ MAP-ACTION * )  */
945
946 static int
947 load_translation (MIMMap *map, MPlist *keylist, MPlist *map_actions,
948                   MPlist *branch_actions, MPlist *macros)
949 {
950   MSymbol *keyseq;
951   int len, i;
952
953   if (MPLIST_MTEXT_P (keylist))
954     {
955       MText *mt = MPLIST_MTEXT (keylist);
956
957       len = mtext_nchars (mt);
958       if (MFAILP (len > 0 && len == mtext_nbytes (mt)))
959         return -1;
960       keyseq = (MSymbol *) alloca (sizeof (MSymbol) * len);
961       for (i = 0; i < len; i++)
962         keyseq[i] = one_char_symbol[MTEXT_DATA (mt)[i]];
963     }
964   else
965     {
966       MPlist *elt;
967           
968       if (MFAILP (MPLIST_PLIST_P (keylist)))
969         return -1;
970       elt = MPLIST_PLIST (keylist);
971       len = MPLIST_LENGTH (elt);
972       if (MFAILP (len > 0))
973         return -1;
974       keyseq = (MSymbol *) alloca (sizeof (int) * len);
975       for (i = 0; i < len; i++, elt = MPLIST_NEXT (elt))
976         {
977           if (MPLIST_INTEGER_P (elt))
978             {
979               int c = MPLIST_INTEGER (elt);
980
981               if (MFAILP (c >= 0 && c < 0x100))
982                 return -1;
983               keyseq[i] = one_char_symbol[c];
984             }
985           else
986             {
987               if (MFAILP (MPLIST_SYMBOL_P (elt)))
988                 return -1;
989               keyseq[i] = MPLIST_SYMBOL (elt);
990             }
991         }
992     }
993
994   for (i = 0; i < len; i++)
995     {
996       MIMMap *deeper = NULL;
997
998       if (map->submaps)
999         deeper = mplist_get (map->submaps, keyseq[i]);
1000       else
1001         map->submaps = mplist ();
1002       if (! deeper)
1003         {
1004           /* Fixme: It is better to make all deeper maps at once.  */
1005           MSTRUCT_CALLOC (deeper, MERROR_IM);
1006           mplist_put (map->submaps, keyseq[i], deeper);
1007         }
1008       map = deeper;
1009     }
1010
1011   /* We reach a terminal map.  */
1012   if (map->map_actions
1013       || map->branch_actions)
1014     /* This map is already defined.  We avoid overriding it.  */
1015     return 0;
1016
1017   if (! MPLIST_TAIL_P (map_actions))
1018     {
1019       if (parse_action_list (map_actions, macros) < 0)
1020         MERROR (MERROR_IM, -1);
1021       map->map_actions = map_actions;
1022     }
1023   if (branch_actions)
1024     {
1025       map->branch_actions = branch_actions;
1026       M17N_OBJECT_REF (branch_actions);
1027     }
1028
1029   return 0;
1030 }
1031
1032 /* Load a branch from PLIST into MAP.  PLIST has this form:
1033       PLIST ::= ( MAP-NAME BRANCH-ACTION * )  */
1034
1035 static int
1036 load_branch (MInputMethodInfo *im_info, MPlist *plist, MIMMap *map)
1037 {
1038   MSymbol map_name;
1039   MPlist *branch_actions;
1040
1041   if (MFAILP (MPLIST_SYMBOL_P (plist)))
1042     return -1;
1043   map_name = MPLIST_SYMBOL (plist);
1044   plist = MPLIST_NEXT (plist);
1045   if (MPLIST_TAIL_P (plist))
1046     branch_actions = NULL;
1047   else if (MFAILP (parse_action_list (plist, im_info->macros) >= 0))
1048     return -1;
1049   else
1050     branch_actions = plist;
1051   if (map_name == Mnil)
1052     {
1053       map->branch_actions = branch_actions;
1054       if (branch_actions)
1055         M17N_OBJECT_REF (branch_actions);
1056     }
1057   else if (map_name == Mt)
1058     {
1059       map->map_actions = branch_actions;
1060       if (branch_actions)
1061         M17N_OBJECT_REF (branch_actions);
1062     }
1063   else if (im_info->maps
1064            && (plist = (MPlist *) mplist_get (im_info->maps, map_name)))
1065     {
1066       MPLIST_DO (plist, plist)
1067         {
1068           MPlist *keylist, *map_actions;
1069
1070           if (! MPLIST_PLIST_P (plist))
1071             MERROR (MERROR_IM, -1);
1072           keylist = MPLIST_PLIST (plist);
1073           map_actions = MPLIST_NEXT (keylist);
1074           if (MPLIST_SYMBOL_P (keylist))
1075             {
1076               MSymbol command = MPLIST_SYMBOL (keylist);
1077               MPlist *pl;
1078
1079               if (MFAILP (command != Mat_reload))
1080                 continue;
1081               pl = resolve_command (im_info->configured_cmds, command);
1082               if (MFAILP (pl))
1083                 continue;
1084               MPLIST_DO (pl, pl)
1085                 load_translation (map, pl, map_actions, branch_actions,
1086                                   im_info->macros);
1087             }
1088           else
1089             load_translation (map, keylist, map_actions, branch_actions,
1090                               im_info->macros);
1091         }
1092     }
1093
1094   return 0;
1095 }
1096
1097 /* Load a macro from PLIST into IM_INFO->macros.
1098    PLIST has this from:
1099       PLIST ::= ( MACRO-NAME ACTION * )
1100    IM_INFO->macros is a plist of macro names vs action list.  */
1101
1102 static int
1103 load_macros (MInputMethodInfo *im_info, MPlist *plist)
1104 {
1105   MSymbol name; 
1106   MPlist *pl;
1107
1108   if (! MPLIST_SYMBOL_P (plist))
1109     MERROR (MERROR_IM, -1);
1110   name = MPLIST_SYMBOL (plist);
1111   plist = MPLIST_NEXT (plist);
1112   if (MPLIST_TAIL_P (plist)
1113       || parse_action_list (plist, im_info->macros) < 0)
1114     MERROR (MERROR_IM, -1);
1115   pl = mplist_get (im_info->macros, name);
1116   M17N_OBJECT_UNREF (pl);
1117   mplist_put (im_info->macros, name, plist);
1118   M17N_OBJECT_REF (plist);
1119   return 0;
1120 }
1121
1122 /* Load an external module from PLIST into IM_INFO->externals.
1123    PLIST has this form:
1124       PLIST ::= ( MODULE-NAME FUNCTION * )
1125    IM_INFO->externals is a plist of MODULE-NAME vs (MIMExternalModule *).  */
1126
1127 static int
1128 load_external_module (MInputMethodInfo *im_info, MPlist *plist)
1129 {
1130   void *handle;
1131   MSymbol module;
1132   char *module_file;
1133   MIMExternalModule *external;
1134   MPlist *func_list;
1135   void *func;
1136
1137   if (MPLIST_MTEXT_P (plist))
1138     module = msymbol ((char *) MTEXT_DATA (MPLIST_MTEXT (plist)));
1139   else if (MPLIST_SYMBOL_P (plist))
1140     module = MPLIST_SYMBOL (plist);
1141   module_file = alloca (strlen (MSYMBOL_NAME (module))
1142                         + strlen (DLOPEN_SHLIB_EXT) + 1);
1143   sprintf (module_file, "%s%s", MSYMBOL_NAME (module), DLOPEN_SHLIB_EXT);
1144
1145   handle = dlopen (module_file, RTLD_NOW);
1146   if (MFAILP (handle))
1147     {
1148       fprintf (stderr, "%s\n", dlerror ());
1149       return -1;
1150     }
1151   func_list = mplist ();
1152   MPLIST_DO (plist, MPLIST_NEXT (plist))
1153     {
1154       if (! MPLIST_SYMBOL_P (plist))
1155         MERROR_GOTO (MERROR_IM, err_label);
1156       func = dlsym (handle, MSYMBOL_NAME (MPLIST_SYMBOL (plist)));
1157       if (MFAILP (func))
1158         goto err_label;
1159       mplist_add (func_list, MPLIST_SYMBOL (plist), func);
1160     }
1161
1162   MSTRUCT_MALLOC (external, MERROR_IM);
1163   external->handle = handle;
1164   external->func_list = func_list;
1165   mplist_add (im_info->externals, module, external);
1166   return 0;
1167
1168  err_label:
1169   dlclose (handle);
1170   M17N_OBJECT_UNREF (func_list);
1171   return -1;
1172 }
1173
1174 static void
1175 free_map (MIMMap *map, int top)
1176 {
1177   MPlist *plist;
1178
1179   if (top)
1180     M17N_OBJECT_UNREF (map->map_actions);
1181   if (map->submaps)
1182     {
1183       MPLIST_DO (plist, map->submaps)
1184         free_map ((MIMMap *) MPLIST_VAL (plist), 0);
1185       M17N_OBJECT_UNREF (map->submaps);
1186     }
1187   M17N_OBJECT_UNREF (map->branch_actions);
1188   free (map);
1189 }
1190
1191 static void
1192 free_state (void *object)
1193 {
1194   MIMState *state = object;
1195
1196   M17N_OBJECT_UNREF (state->title);
1197   if (state->map)
1198     free_map (state->map, 1);
1199   free (state);
1200 }
1201
1202 /** Load a state from PLIST into a newly allocated state object.
1203     PLIST has this form:
1204       PLIST ::= ( STATE-NAME STATE-TITLE ? BRANCH * )
1205       BRANCH ::= ( MAP-NAME BRANCH-ACTION * )
1206    Return the state object.  */
1207
1208 static MIMState *
1209 load_state (MInputMethodInfo *im_info, MPlist *plist)
1210 {
1211   MIMState *state;
1212
1213   if (MFAILP (MPLIST_SYMBOL_P (plist)))
1214     return NULL;
1215   M17N_OBJECT (state, free_state, MERROR_IM);
1216   state->name = MPLIST_SYMBOL (plist);
1217   plist = MPLIST_NEXT (plist);
1218   if (MPLIST_MTEXT_P (plist))
1219     {
1220       state->title = MPLIST_MTEXT (plist);
1221       mtext_put_prop (state->title, 0, mtext_nchars (state->title),
1222                       Mlanguage, im_info->language);
1223       M17N_OBJECT_REF (state->title);
1224       plist = MPLIST_NEXT (plist);
1225     }
1226   MSTRUCT_CALLOC (state->map, MERROR_IM);
1227   MPLIST_DO (plist, plist)
1228     {
1229       if (MFAILP (MPLIST_PLIST_P (plist)))
1230         continue;
1231       load_branch (im_info, MPLIST_PLIST (plist), state->map);
1232     }
1233   return state;
1234 }
1235
1236 /* Return a newly created IM_INFO for an input method specified by
1237    LANUAGE, NAME, and EXTRA.  IM_INFO is stored in PLIST.  */
1238
1239 static MInputMethodInfo *
1240 new_im_info (MDatabase *mdb, MSymbol language, MSymbol name, MSymbol extra,
1241              MPlist *plist)
1242 {
1243   MInputMethodInfo *im_info;
1244   MPlist *elt;
1245
1246   if (name == Mnil && extra == Mnil)
1247     language = Mt, extra = Mglobal;
1248   MSTRUCT_CALLOC (im_info, MERROR_IM);
1249   im_info->mdb = mdb;
1250   im_info->language = language;
1251   im_info->name = name;
1252   im_info->extra = extra;
1253
1254   elt = mplist ();
1255   mplist_add (plist, Mplist, elt);
1256   M17N_OBJECT_UNREF (elt);
1257   elt = mplist_add (elt, Msymbol, language);
1258   elt = mplist_add (elt, Msymbol, name);
1259   elt = mplist_add (elt, Msymbol, extra);
1260   mplist_add (elt, Mt, im_info);
1261
1262   return im_info;
1263 }
1264
1265 static void
1266 fini_im_info (MInputMethodInfo *im_info)
1267 {
1268   MPlist *plist;
1269
1270   M17N_OBJECT_UNREF (im_info->cmds);
1271   M17N_OBJECT_UNREF (im_info->configured_cmds);
1272   M17N_OBJECT_UNREF (im_info->bc_cmds);
1273   M17N_OBJECT_UNREF (im_info->vars);
1274   M17N_OBJECT_UNREF (im_info->configured_vars);
1275   M17N_OBJECT_UNREF (im_info->bc_vars);
1276   M17N_OBJECT_UNREF (im_info->description);
1277   M17N_OBJECT_UNREF (im_info->title);
1278   if (im_info->states)
1279     {
1280       MPLIST_DO (plist, im_info->states)
1281         {
1282           MIMState *state = (MIMState *) MPLIST_VAL (plist);
1283
1284           M17N_OBJECT_UNREF (state);
1285         }
1286       M17N_OBJECT_UNREF (im_info->states);
1287     }
1288
1289   if (im_info->macros)
1290     {
1291       MPLIST_DO (plist, im_info->macros)
1292         M17N_OBJECT_UNREF (MPLIST_VAL (plist)); 
1293       M17N_OBJECT_UNREF (im_info->macros);
1294     }
1295
1296   if (im_info->externals)
1297     {
1298       MPLIST_DO (plist, im_info->externals)
1299         {
1300           MIMExternalModule *external = MPLIST_VAL (plist);
1301
1302           dlclose (external->handle);
1303           M17N_OBJECT_UNREF (external->func_list);
1304           free (external);
1305           MPLIST_KEY (plist) = Mt;
1306         }
1307       M17N_OBJECT_UNREF (im_info->externals);
1308     }
1309   if (im_info->maps)
1310     {
1311       MPLIST_DO (plist, im_info->maps)
1312         {
1313           MPlist *p = MPLIST_PLIST (plist);
1314
1315           M17N_OBJECT_UNREF (p);
1316         }
1317       M17N_OBJECT_UNREF (im_info->maps);
1318     }
1319
1320   im_info->tick = 0;
1321 }
1322
1323 static void
1324 free_im_info (MInputMethodInfo *im_info)
1325 {
1326   fini_im_info (im_info);
1327   free (im_info);
1328 }
1329
1330 static void
1331 free_im_list (MPlist *plist)
1332 {
1333   MPlist *pl, *elt;
1334
1335   MPLIST_DO (pl, plist)
1336     {
1337       MInputMethodInfo *im_info;
1338
1339       elt = MPLIST_NEXT (MPLIST_NEXT (MPLIST_NEXT (MPLIST_PLIST (pl))));
1340       im_info = MPLIST_VAL (elt);
1341       free_im_info (im_info);
1342     }
1343   M17N_OBJECT_UNREF (plist);
1344 }
1345
1346 static MInputMethodInfo *
1347 lookup_im_info (MPlist *plist, MSymbol language, MSymbol name, MSymbol extra)
1348 {
1349   if (name == Mnil && extra == Mnil)
1350     language = Mt, extra = Mglobal;
1351   while ((plist = mplist__assq (plist, language)))
1352     {
1353       MPlist *elt = MPLIST_PLIST (plist);
1354
1355       plist = MPLIST_NEXT (plist);
1356       elt = MPLIST_NEXT (elt);
1357       if (MPLIST_SYMBOL (elt) != name)
1358         continue;
1359       elt = MPLIST_NEXT (elt);
1360       if (MPLIST_SYMBOL (elt) != extra)
1361         continue;
1362       elt = MPLIST_NEXT (elt);
1363       return MPLIST_VAL (elt);
1364     }
1365   return NULL;
1366 }
1367
1368 static void load_im_info (MPlist *, MInputMethodInfo *);
1369
1370 #define get_custom_info(im_info)                                \
1371   (im_custom_list                                               \
1372    ? lookup_im_info (im_custom_list, (im_info)->language,       \
1373                      (im_info)->name, (im_info)->extra)         \
1374    : NULL)
1375
1376 #define get_config_info(im_info)                                \
1377   (im_config_list                                               \
1378    ? lookup_im_info (im_config_list, (im_info)->language,       \
1379                      (im_info)->name, (im_info)->extra)         \
1380    : NULL)
1381
1382 static int
1383 update_custom_info (void)
1384 {
1385   MPlist *plist, *pl;
1386
1387   if (im_custom_mdb)
1388     {
1389       if (mdatabase__check (im_custom_mdb) > 0)
1390         return 1;
1391     }
1392   else
1393     {
1394       MDatabaseInfo *custom_dir_info;
1395       char custom_path[PATH_MAX + 1];
1396
1397       custom_dir_info = MPLIST_VAL (mdatabase__dir_list);
1398       if (! custom_dir_info->filename
1399           || custom_dir_info->len + strlen (CUSTOM_FILE) > PATH_MAX)
1400         return -1;
1401       strcpy (custom_path, custom_dir_info->filename);
1402       strcat (custom_path, CUSTOM_FILE);
1403       im_custom_mdb = mdatabase_define (Minput_method, Mt, Mnil, Mconfig,
1404                                         NULL, custom_path);
1405     }
1406
1407   if (im_custom_list)
1408     {
1409       free_im_list (im_custom_list);
1410       im_custom_list = NULL;
1411     }
1412   plist = mdatabase_load (im_custom_mdb);
1413   if (! plist)
1414     return -1;
1415   im_custom_list = mplist ();
1416
1417   MPLIST_DO (pl, plist)
1418     {
1419       MSymbol language, name, extra;
1420       MInputMethodInfo *im_info;
1421       MPlist *im_data, *p;
1422
1423       if (! MPLIST_PLIST_P (pl))
1424         continue;
1425       p = MPLIST_PLIST (pl);
1426       im_data = MPLIST_NEXT (p);
1427       if (! MPLIST_PLIST_P (p))
1428         continue;
1429       p = MPLIST_PLIST (p);
1430       if (! MPLIST_SYMBOL_P (p)
1431           || MPLIST_SYMBOL (p) != Minput_method)
1432         continue;
1433       p = MPLIST_NEXT (p);
1434       if (! MPLIST_SYMBOL_P (p))
1435         continue;
1436       language = MPLIST_SYMBOL (p);
1437       p = MPLIST_NEXT (p);
1438       if (! MPLIST_SYMBOL_P (p))
1439         continue;
1440       name = MPLIST_SYMBOL (p);
1441       if (language == Mnil || name == Mnil)
1442         continue;
1443       p = MPLIST_NEXT (p);
1444       if (MPLIST_TAIL_P (p))
1445         extra = Mnil;
1446       else if (MPLIST_SYMBOL_P (p))
1447         extra = MPLIST_SYMBOL (p);
1448       else
1449         continue;
1450       im_info = new_im_info (NULL, language, name, extra, im_custom_list);
1451       load_im_info (im_data, im_info);
1452     }
1453   M17N_OBJECT_UNREF (plist);
1454   return 0;
1455 }
1456
1457 static int
1458 update_global_info (void)
1459 {
1460   MPlist *plist;
1461
1462   if (global_info)
1463     {
1464       int ret = mdatabase__check (global_info->mdb);
1465
1466       if (ret)
1467         return ret;
1468       fini_im_info (global_info);
1469     }
1470   else
1471     {
1472       MDatabase *mdb = mdatabase_find (Minput_method, Mt, Mnil, Mglobal);
1473
1474       global_info = new_im_info (mdb, Mt, Mnil, Mglobal, im_info_list);
1475     }
1476   if (! global_info->mdb
1477       || ! (plist = mdatabase_load (global_info->mdb)))
1478     return -1;
1479
1480   load_im_info (plist, global_info);
1481   M17N_OBJECT_UNREF (plist);
1482   return 0;
1483 }
1484
1485
1486 /* Return an IM_INFO for the an method specified by LANGUAGE, NAME,
1487    and EXTRA.  KEY, if not Mnil, tells which kind of information about
1488    the input method is necessary, and the returned IM_INFO may contain
1489    only that information.  */
1490
1491 static MInputMethodInfo *
1492 get_im_info (MSymbol language, MSymbol name, MSymbol extra, MSymbol key)
1493 {
1494   MPlist *plist;
1495   MInputMethodInfo *im_info;
1496   MDatabase *mdb;
1497
1498   if (name == Mnil && extra == Mnil)
1499     language = Mt, extra = Mglobal;
1500   im_info = lookup_im_info (im_info_list, language, name, extra);
1501   if (im_info)
1502     {
1503       if (key == Mnil ? im_info->states != NULL
1504           : key == Mcommand ? im_info->cmds != NULL
1505           : key == Mvariable ? im_info->vars != NULL
1506           : key == Mtitle ? im_info->title != NULL
1507           : key == Mdescription ? im_info->description != NULL
1508           : 1)
1509         /* IM_INFO already contains required information.  */
1510         return im_info;
1511       /* We have not yet loaded required information.  */
1512     }
1513   else
1514     {
1515       mdb = mdatabase_find (Minput_method, language, name, extra);
1516       if (! mdb)
1517         return NULL;
1518       im_info = new_im_info (mdb, language, name, extra, im_info_list);
1519     }
1520
1521   if (key == Mnil)
1522     {
1523       plist = mdatabase_load (im_info->mdb);
1524     }
1525   else
1526     {
1527       mplist_push (load_im_info_keys, key, Mt);
1528       plist = mdatabase__load_for_keys (im_info->mdb, load_im_info_keys);
1529       mplist_pop (load_im_info_keys);
1530     }
1531   im_info->tick = 0;
1532   if (! plist)
1533     MERROR (MERROR_IM, im_info);
1534   update_global_info ();
1535   load_im_info (plist, im_info);
1536   M17N_OBJECT_UNREF (plist);
1537   if (key == Mnil)
1538     {
1539       if (! im_info->cmds)
1540         im_info->cmds = mplist ();
1541       if (! im_info->vars)
1542         im_info->vars = mplist ();
1543     }
1544   if (! im_info->title
1545       && (key == Mnil || key == Mtitle))
1546     im_info->title = (name == Mnil ? mtext ()
1547                       : mtext_from_data (MSYMBOL_NAME (name),
1548                                          MSYMBOL_NAMELEN (name),
1549                                          MTEXT_FORMAT_US_ASCII));
1550   return im_info;
1551 }
1552
1553 /* Check if IM_INFO->mdb is updated or not.  If not updated, return 0.
1554    If updated, but got unloadable, return -1.  Otherwise, update
1555    contents of IM_INFO from the new database, and return 1.  */
1556
1557 static int
1558 reload_im_info (MInputMethodInfo *im_info)
1559 {
1560   int check;
1561   MPlist *plist;
1562
1563   update_custom_info ();
1564   update_global_info ();
1565   check = mdatabase__check (im_info->mdb);
1566   if (check < 0)
1567     return -1;
1568   plist = mdatabase_load (im_info->mdb);
1569   if (! plist)
1570     return -1;
1571   fini_im_info (im_info);
1572   load_im_info (plist, im_info);
1573   M17N_OBJECT_UNREF (plist);
1574   return 1;
1575 }
1576
1577 static MInputMethodInfo *
1578 get_im_info_by_tags (MPlist *plist)
1579 {
1580   MSymbol tag[3];
1581   int i;
1582
1583   for (i = 0; i < 3 && MPLIST_SYMBOL_P (plist);
1584        i++, plist = MPLIST_NEXT (plist))
1585     tag[i] = MPLIST_SYMBOL (plist);
1586   if (i < 2)
1587     return NULL;
1588   for (; i < 3; i++)
1589     tag[i] = Mnil;
1590   return get_im_info (tag[0], tag[1], tag[2], Mnil);
1591 }
1592
1593
1594 static int
1595 check_description (MPlist *plist)
1596 {
1597   MText *mt;
1598
1599   if (MPLIST_MTEXT_P (plist))
1600     return 1;
1601   if (MPLIST_PLIST_P (plist))
1602     {
1603       MPlist *pl = MPLIST_PLIST (plist);
1604
1605       if (MFAILP (MPLIST_SYMBOL_P (pl) && MPLIST_SYMBOL (pl) == M_gettext))
1606         return 0;
1607       pl =MPLIST_NEXT (pl);
1608       if (MFAILP (MPLIST_MTEXT_P (pl)))
1609         return 0;
1610       mt = MPLIST_MTEXT (pl);
1611       M17N_OBJECT_REF (mt);
1612 #if ENABLE_NLS
1613       {
1614         char *translated = dgettext ("m17n-db", (char *) MTEXT_DATA (mt));
1615
1616         if (translated == (char *) MTEXT_DATA (mt))
1617           translated = dgettext ("m17n-contrib", (char *) MTEXT_DATA (mt));
1618         if (translated != (char *) MTEXT_DATA (mt))
1619           {
1620             M17N_OBJECT_UNREF (mt);
1621             mt = mtext__from_data (translated, strlen (translated),
1622                                    MTEXT_FORMAT_UTF_8, 0);
1623           }
1624       }
1625 #endif
1626       mplist_set (plist, Mtext, mt);
1627       M17N_OBJECT_UNREF (mt);
1628       return 1;
1629     }
1630   if (MFAILP (MPLIST_SYMBOL_P (plist) && MPLIST_SYMBOL (plist) == Mnil))
1631     return 0;
1632   return 1;
1633 }
1634
1635
1636 /* Check KEYSEQ, and return 1 if it is valid as a key sequence, return
1637    0 if not.  */
1638
1639 static int
1640 check_command_keyseq (MPlist *keyseq)
1641 {
1642   if (MPLIST_PLIST_P (keyseq))
1643     {
1644       MPlist *p = MPLIST_PLIST (keyseq);
1645
1646       MPLIST_DO (p, p)
1647         if (! MPLIST_SYMBOL_P (p) && ! MPLIST_INTEGER_P (p))
1648           return 0;
1649       return 1;
1650     }
1651   if (MPLIST_MTEXT_P (keyseq))
1652     {
1653       MText *mt = MPLIST_MTEXT (keyseq);
1654       int i;
1655       
1656       for (i = 0; i < mtext_nchars (mt); i++)
1657         if (mtext_ref_char (mt, i) >= 256)
1658           return 0;
1659       return 1;
1660     }
1661   return 0;
1662 }
1663
1664 /* Load command defitions from PLIST into IM_INFO->cmds.
1665
1666    PLIST is well-formed and has this form;
1667      (command (NAME [DESCRIPTION KEYSEQ ...]) ...)
1668    NAME is a symbol.  DESCRIPTION is an M-text or `nil'.  KEYSEQ is an
1669    M-text or a plist of symbols.
1670
1671    The returned list has the same form, but for each element...
1672
1673    (1) If DESCRIPTION and the rest are omitted, the element is not
1674    stored in the returned list.
1675
1676    (2) If DESCRIPTION is nil, it is complemented by the corresponding
1677    description in global_info->cmds (if any).  */
1678
1679 static void
1680 load_commands (MInputMethodInfo *im_info, MPlist *plist)
1681 {
1682   MPlist *tail;
1683
1684   im_info->cmds = tail = mplist ();
1685
1686   MPLIST_DO (plist, MPLIST_NEXT (plist))
1687     {
1688       /* PLIST ::= ((NAME DESC KEYSEQ ...) ...) */
1689       MPlist *pl, *p;
1690
1691       if (MFAILP (MPLIST_PLIST_P (plist)))
1692         continue;
1693       pl = MPLIST_PLIST (plist); /* PL ::= (NAME DESC KEYSEQ ...) */
1694       if (MFAILP (MPLIST_SYMBOL_P (pl)))
1695         continue;
1696       p = MPLIST_NEXT (pl);     /* P ::= (DESC KEYSEQ ...) */
1697       if (MPLIST_TAIL_P (p))    /* PL ::= (NAME) */
1698         {
1699           if (MFAILP (im_info != global_info))
1700             mplist_add (p, Msymbol, Mnil); /* PL ::= (NAME nil) */
1701         }
1702       else
1703         {
1704           if (! check_description (p))
1705             mplist_set (p, Msymbol, Mnil);
1706           p = MPLIST_NEXT (p);
1707           while (! MPLIST_TAIL_P (p))
1708             {
1709               if (MFAILP (check_command_keyseq (p)))
1710                 mplist__pop_unref (p);
1711               else
1712                 p = MPLIST_NEXT (p);
1713             }
1714         }
1715       tail = mplist_add (tail, Mplist, pl);
1716     }
1717 }
1718
1719 static MPlist *
1720 config_command (MPlist *plist, MPlist *global_cmds, MPlist *custom_cmds,
1721                 MPlist *config_cmds)
1722 {
1723   MPlist *global = NULL, *custom = NULL, *config = NULL;
1724   MSymbol name;
1725   MSymbol status;
1726   MPlist *description = NULL, *keyseq;
1727
1728   name = MPLIST_SYMBOL (plist);
1729   plist = MPLIST_NEXT (plist);
1730   if (MPLIST_MTEXT_P (plist) || MPLIST_PLIST_P (plist))
1731     description = plist;
1732   else if (global_cmds && ((global = mplist__assq (global_cmds, name))))
1733     description = global = MPLIST_NEXT (MPLIST_PLIST (global));
1734   if (MPLIST_TAIL_P (plist))
1735     {
1736       if (! global
1737           && global_cmds && ((global = mplist__assq (global_cmds, name))))
1738         global = MPLIST_NEXT (MPLIST_PLIST (global));
1739       if (global)
1740         {
1741           keyseq = MPLIST_NEXT (global);
1742           status = Minherited;
1743         }
1744       else
1745         {
1746           keyseq = plist;
1747           status = Mnil;
1748         }
1749     }
1750   else
1751     {
1752       keyseq = MPLIST_NEXT (plist);
1753       status = Mnil;
1754     }
1755
1756   if (config_cmds && (config = mplist__assq (config_cmds, name)))
1757     {
1758       config = MPLIST_NEXT (MPLIST_PLIST (config));
1759       if (! MPLIST_TAIL_P (config))
1760         {
1761           keyseq = MPLIST_NEXT (config);
1762           status = Mconfigured;
1763         }
1764     }
1765   else if (custom_cmds && (custom = mplist__assq (custom_cmds, name)))
1766     {
1767       custom = MPLIST_NEXT (MPLIST_PLIST (custom));
1768       if (! MPLIST_TAIL_P (custom))
1769         {
1770           keyseq = MPLIST_NEXT (custom);
1771           status = Mcustomized;
1772         }
1773     }
1774   
1775   plist = mplist ();
1776   mplist_add (plist, Msymbol, name);
1777   if (description)
1778     mplist_add (plist, MPLIST_KEY (description), MPLIST_VAL (description));
1779   else
1780     mplist_add (plist, Msymbol, Mnil);
1781   mplist_add (plist, Msymbol, status);
1782   mplist__conc (plist, keyseq);
1783   return plist;
1784 }
1785
1786 static void
1787 config_all_commands (MInputMethodInfo *im_info)
1788 {
1789   MPlist *global_cmds, *custom_cmds, *config_cmds;
1790   MInputMethodInfo *temp;
1791   MPlist *tail, *plist;
1792
1793   M17N_OBJECT_UNREF (im_info->configured_cmds);
1794
1795   if (MPLIST_TAIL_P (im_info->cmds)
1796       || ! im_info->mdb)
1797     return;
1798
1799   global_cmds = im_info != global_info ? global_info->cmds : NULL;
1800   custom_cmds = ((temp = get_custom_info (im_info)) ? temp->cmds : NULL);
1801   config_cmds = ((temp = get_config_info (im_info)) ? temp->cmds : NULL);
1802
1803   im_info->configured_cmds = tail = mplist ();
1804   MPLIST_DO (plist, im_info->cmds)
1805     {
1806       MPlist *pl = config_command (MPLIST_PLIST (plist),
1807                                    global_cmds, custom_cmds, config_cmds);
1808       if (pl)
1809         {
1810           tail = mplist_add (tail, Mplist, pl);
1811           M17N_OBJECT_UNREF (pl);
1812         }
1813     }
1814 }
1815
1816 /* Check VAL's value against VALID_VALUES, and return 1 if it is
1817    valid, return 0 if not.  */
1818
1819 static int
1820 check_variable_value (MPlist *val, MPlist *global)
1821 {
1822   MSymbol type = MPLIST_KEY (val);
1823   MPlist *valids = MPLIST_NEXT (val);
1824
1825   if (type != Minteger && type != Mtext && type != Msymbol)
1826     return 0;
1827   if (global)
1828     {
1829       if (MPLIST_KEY (global) != Mt
1830           && MPLIST_KEY (global) != MPLIST_KEY (val))
1831         return 0;
1832       if (MPLIST_TAIL_P (valids))
1833         valids = MPLIST_NEXT (global);
1834     }
1835   if (MPLIST_TAIL_P (valids))
1836     return 1;
1837
1838   if (type == Minteger)
1839     {
1840       int n = MPLIST_INTEGER (val);
1841
1842       MPLIST_DO (valids, valids)
1843         {
1844           if (MPLIST_INTEGER_P (valids))
1845             {
1846               if (n == MPLIST_INTEGER (valids))
1847                 break;
1848             }
1849           else if (MPLIST_PLIST_P (valids))
1850             {
1851               MPlist *p = MPLIST_PLIST (valids);
1852               int min_bound, max_bound;
1853
1854               if (! MPLIST_INTEGER_P (p))
1855                 MERROR (MERROR_IM, 0);
1856               min_bound = MPLIST_INTEGER (p);
1857               p = MPLIST_NEXT (p);
1858               if (! MPLIST_INTEGER_P (p))
1859                 MERROR (MERROR_IM, 0);
1860               max_bound = MPLIST_INTEGER (p);
1861               if (n >= min_bound && n <= max_bound)
1862                 break;
1863             }
1864         }
1865     }
1866   else if (type == Msymbol)
1867     {
1868       MSymbol sym = MPLIST_SYMBOL (val);
1869
1870       MPLIST_DO (valids, valids)
1871         {
1872           if (! MPLIST_SYMBOL_P (valids))
1873             MERROR (MERROR_IM, 0);
1874           if (sym == MPLIST_SYMBOL (valids))
1875             break;
1876         }
1877     }
1878   else
1879     {
1880       MText *mt = MPLIST_MTEXT (val);
1881
1882       MPLIST_DO (valids, valids)
1883         {
1884           if (! MPLIST_MTEXT_P (valids))
1885             MERROR (MERROR_IM, 0);
1886           if (mtext_cmp (mt, MPLIST_MTEXT (valids)) == 0)
1887             break;
1888         }
1889     }
1890
1891   return (MPLIST_TAIL_P (valids));
1892 }
1893
1894 /* Load variable defitions from PLIST into IM_INFO->vars.
1895
1896    PLIST is well-formed and has this form;
1897      ((NAME [DESCRIPTION DEFAULT-VALUE VALID-VALUE ...])
1898       ...)
1899    NAME is a symbol.  DESCRIPTION is an M-text or `nil'.
1900
1901    The returned list has the same form, but for each element...
1902
1903    (1) If DESCRIPTION and the rest are omitted, the element is not
1904    stored in the returned list.
1905
1906    (2) If DESCRIPTION is nil, it is complemented by the corresponding
1907    description in global_info->vars (if any).  */
1908
1909 static void
1910 load_variables (MInputMethodInfo *im_info, MPlist *plist)
1911 {
1912   MPlist *global_vars = ((im_info->mdb && im_info != global_info)
1913                          ? global_info->vars : NULL);
1914   MPlist *tail;
1915
1916   im_info->vars = tail = mplist ();
1917   MPLIST_DO (plist, MPLIST_NEXT (plist))
1918     {
1919       MPlist *pl, *p;
1920
1921       if (MFAILP (MPLIST_PLIST_P (plist)))
1922         continue;
1923       pl = MPLIST_PLIST (plist); /* PL ::= (NAME DESC VALUE VALID ...) */
1924       if (MFAILP (MPLIST_SYMBOL_P (pl)))
1925         continue;
1926       if (im_info == global_info)
1927         {
1928           /* Loading a global variable.  */
1929           p = MPLIST_NEXT (pl);
1930           if (MPLIST_TAIL_P (p))
1931             mplist_add (p, Msymbol, Mnil);
1932           else
1933             {
1934               if (! check_description (p))
1935                 mplist_set (p, Msymbol, Mnil);
1936               p = MPLIST_NEXT (p);
1937               if (MFAILP (! MPLIST_TAIL_P (p)
1938                           && check_variable_value (p, NULL)))
1939                 mplist_set (p, Mt, NULL);
1940             }
1941         }
1942       else if (im_info->mdb)
1943         {
1944           /* Loading a local variable.  */
1945           MSymbol name = MPLIST_SYMBOL (pl);
1946           MPlist *global = NULL;
1947
1948           if (global_vars
1949               && (p = mplist__assq (global_vars, name)))
1950             {
1951               /* P ::= ((NAME DESC ...) ...) */
1952               p = MPLIST_PLIST (p); /* P ::= (NAME DESC ...) */
1953               global = MPLIST_NEXT (p); /* P ::= (DESC VALUE ...) */
1954               global = MPLIST_NEXT (global); /* P ::= (VALUE ...) */
1955             }
1956
1957           p = MPLIST_NEXT (pl); /* P ::= (DESC VALUE VALID ...) */
1958           if (! MPLIST_TAIL_P (p))
1959             {
1960               if (! check_description (p))
1961                 mplist_set (p, Msymbol, Mnil);
1962               p = MPLIST_NEXT (p); /* P ::= (VALUE VALID ...) */
1963               if (MFAILP (! MPLIST_TAIL_P (p)))
1964                 mplist_set (p, Mt, NULL);
1965               else
1966                 {
1967                   MPlist *valid_values = MPLIST_NEXT (p);
1968
1969                   if (! MPLIST_TAIL_P (valid_values)
1970                       ? MFAILP (check_variable_value (p, NULL))
1971                       : global && MFAILP (check_variable_value (p, global)))
1972                     mplist_set (p, Mt, NULL);
1973                 }
1974             }
1975         }
1976       else
1977         {
1978           /* Loading a variable customization.  */
1979           p = MPLIST_NEXT (pl); /* P ::= (nil VALUE) */
1980           if (MFAILP (! MPLIST_TAIL_P (p)))
1981             continue;
1982           p = MPLIST_NEXT (p);  /* P ::= (VALUE) */
1983           if (MFAILP (MPLIST_INTEGER_P (p) || MPLIST_SYMBOL_P (p)
1984                       || MPLIST_MTEXT_P (p)))
1985             continue;
1986         }
1987       tail = mplist_add (tail, Mplist, pl);
1988     }
1989 }
1990
1991 static MPlist *
1992 config_variable (MPlist *plist, MPlist *global_vars, MPlist *custom_vars,
1993                  MPlist *config_vars)
1994 {
1995   MPlist *global = NULL, *custom = NULL, *config = NULL;
1996   MSymbol name = MPLIST_SYMBOL (plist);
1997   MSymbol status;
1998   MPlist *description = NULL, *value, *valids;
1999
2000   if (global_vars)
2001     {
2002       global = mplist__assq (global_vars, name);
2003       if (global)
2004         global = MPLIST_NEXT (MPLIST_PLIST (global)); /* (DESC VALUE ...) */
2005     }
2006
2007   plist = MPLIST_NEXT (plist);
2008   if (MPLIST_MTEXT_P (plist) || MPLIST_PLIST_P (plist))
2009     description = plist;
2010   else if (global)
2011     description = global;
2012   if (global)
2013     global = MPLIST_NEXT (global); /* (VALUE VALIDS ...) */
2014
2015   if (MPLIST_TAIL_P (plist))
2016     {
2017       /* Inherit from global (if any).  */
2018       if (global)
2019         {
2020           value = global;
2021           if (MPLIST_KEY (value) == Mt)
2022             value = NULL;
2023           valids = MPLIST_NEXT (global);
2024           status = Minherited;
2025         }
2026       else
2027         {
2028           value = NULL;
2029           valids = NULL;
2030           status = Mnil;
2031           plist = NULL;
2032         }
2033     }
2034   else
2035     {
2036       value = plist = MPLIST_NEXT (plist);
2037       valids = MPLIST_NEXT (value);
2038       if (MPLIST_KEY (value) == Mt)
2039         value = NULL;
2040       if (! MPLIST_TAIL_P (valids))
2041         global = NULL;
2042       else if (global)
2043         valids = MPLIST_NEXT (global);
2044       status = Mnil;
2045     }
2046
2047   if (config_vars && (config = mplist__assq (config_vars, name)))
2048     {
2049       config = MPLIST_NEXT (MPLIST_PLIST (config));
2050       if (! MPLIST_TAIL_P (config))
2051         {
2052           value = MPLIST_NEXT (config);
2053           if (MFAILP (check_variable_value (value, global ? global : plist)))
2054             value = NULL;
2055           status = Mconfigured;
2056         }
2057     }
2058   else if (custom_vars && (custom = mplist__assq (custom_vars, name)))
2059     {
2060       custom = MPLIST_NEXT (MPLIST_PLIST (custom));
2061       if (! MPLIST_TAIL_P (custom))
2062         {
2063           value = MPLIST_NEXT (custom);
2064           if (MFAILP (check_variable_value (value, global ? global : plist)))
2065             value = NULL;
2066           status = Mcustomized;
2067         }
2068     }
2069   
2070   plist = mplist ();
2071   mplist_add (plist, Msymbol, name);
2072   if (description)
2073     mplist_add (plist, MPLIST_KEY (description), MPLIST_VAL (description));
2074   else
2075     mplist_add (plist, Msymbol, Mnil);
2076   mplist_add (plist, Msymbol, status);
2077   if (value)
2078     mplist_add (plist, MPLIST_KEY (value), MPLIST_VAL (value));
2079   else
2080     mplist_add (plist, Mt, NULL);
2081   if (valids && ! MPLIST_TAIL_P (valids))
2082     mplist__conc (plist, valids);
2083   return plist;
2084 }
2085
2086 /* Return a configured variable definition list based on
2087    IM_INFO->vars.  If a variable in it doesn't contain a value, try to
2088    get it from global_info->vars.  */
2089
2090 static void
2091 config_all_variables (MInputMethodInfo *im_info)
2092 {
2093   MPlist *global_vars, *custom_vars, *config_vars;
2094   MInputMethodInfo *temp;
2095   MPlist *tail, *plist;
2096
2097   M17N_OBJECT_UNREF (im_info->configured_vars);
2098
2099   if (MPLIST_TAIL_P (im_info->vars)
2100       || ! im_info->mdb)
2101     return;
2102
2103   global_vars = im_info != global_info ? global_info->vars : NULL;
2104   custom_vars = ((temp = get_custom_info (im_info)) ? temp->vars : NULL);
2105   config_vars = ((temp = get_config_info (im_info)) ? temp->vars : NULL);
2106
2107   im_info->configured_vars = tail = mplist ();
2108   MPLIST_DO (plist, im_info->vars)
2109     {
2110       MPlist *pl = config_variable (MPLIST_PLIST (plist),
2111                                     global_vars, custom_vars, config_vars);
2112       if (pl)
2113         {
2114           tail = mplist_add (tail, Mplist, pl);
2115           M17N_OBJECT_UNREF (pl);
2116         }
2117     }
2118 }
2119
2120 /* Load an input method (LANGUAGE NAME) from PLIST into IM_INFO.
2121    CONFIG contains configuration information of the input method.  */
2122
2123 static void
2124 load_im_info (MPlist *plist, MInputMethodInfo *im_info)
2125 {
2126   MPlist *pl, *p;
2127
2128   if (! im_info->cmds && (pl = mplist__assq (plist, Mcommand)))
2129     {
2130       load_commands (im_info, MPLIST_PLIST (pl));
2131       config_all_commands (im_info);
2132       pl = mplist_pop (pl);
2133       M17N_OBJECT_UNREF (pl);
2134     }
2135
2136   if (! im_info->vars && (pl = mplist__assq (plist, Mvariable)))
2137     {
2138       load_variables (im_info, MPLIST_PLIST (pl));
2139       config_all_variables (im_info);
2140       pl = mplist_pop (pl);
2141       M17N_OBJECT_UNREF (pl);
2142     }
2143
2144   MPLIST_DO (plist, plist)
2145     if (MPLIST_PLIST_P (plist))
2146       {
2147         MPlist *elt = MPLIST_PLIST (plist);
2148         MSymbol key;
2149
2150         if (MFAILP (MPLIST_SYMBOL_P (elt)))
2151           continue;
2152         key = MPLIST_SYMBOL (elt);
2153         if (key == Mtitle)
2154           {
2155             if (im_info->title)
2156               continue;
2157             elt = MPLIST_NEXT (elt);
2158             if (MFAILP (MPLIST_MTEXT_P (elt)))
2159               continue;
2160             im_info->title = MPLIST_MTEXT (elt);
2161             M17N_OBJECT_REF (im_info->title);
2162           }
2163         else if (key == Mmap)
2164           {
2165             pl = mplist__from_alist (MPLIST_NEXT (elt));
2166             if (MFAILP (pl))
2167               continue;
2168             if (! im_info->maps)
2169               im_info->maps = pl;
2170             else
2171               {
2172                 mplist__conc (im_info->maps, pl);
2173                 M17N_OBJECT_UNREF (pl);
2174               }
2175           }
2176         else if (key == Mmacro)
2177           {
2178             if (! im_info->macros)
2179               im_info->macros = mplist ();
2180             MPLIST_DO (elt, MPLIST_NEXT (elt))
2181               {
2182                 if (MFAILP (MPLIST_PLIST_P (elt)))
2183                   continue;
2184                 load_macros (im_info, MPLIST_PLIST (elt));
2185               }
2186           }
2187         else if (key == Mmodule)
2188           {
2189             if (! im_info->externals)
2190               im_info->externals = mplist ();
2191             MPLIST_DO (elt, MPLIST_NEXT (elt))
2192               {
2193                 if (MFAILP (MPLIST_PLIST_P (elt)))
2194                   continue;
2195                 load_external_module (im_info, MPLIST_PLIST (elt));
2196               }
2197           }
2198         else if (key == Mstate)
2199           {
2200             MPLIST_DO (elt, MPLIST_NEXT (elt))
2201               {
2202                 MIMState *state;
2203
2204                 if (MFAILP (MPLIST_PLIST_P (elt)))
2205                   continue;
2206                 pl = MPLIST_PLIST (elt);
2207                 if (! im_info->states)
2208                   im_info->states = mplist ();
2209                 state = load_state (im_info, MPLIST_PLIST (elt));
2210                 if (MFAILP (state))
2211                   continue;
2212                 mplist_put (im_info->states, state->name, state);
2213               }
2214           }
2215         else if (key == Minclude)
2216           {
2217             /* elt ::= include (tag1 tag2 ...) key item ... */
2218             MSymbol key;
2219             MInputMethodInfo *temp;
2220
2221             elt = MPLIST_NEXT (elt);
2222             if (MFAILP (MPLIST_PLIST_P (elt)))
2223               continue;
2224             temp = get_im_info_by_tags (MPLIST_PLIST (elt));
2225             if (MFAILP (temp))
2226               continue;
2227             elt = MPLIST_NEXT (elt);
2228             if (MFAILP (MPLIST_SYMBOL_P (elt)))
2229               continue;
2230             key = MPLIST_SYMBOL (elt);
2231             elt = MPLIST_NEXT (elt);
2232             if (key == Mmap)
2233               {
2234                 if (! temp->maps || MPLIST_TAIL_P (temp->maps))
2235                   continue;
2236                 if (! im_info->maps)
2237                   im_info->maps = mplist ();
2238                 MPLIST_DO (pl, temp->maps)
2239                   {
2240                     p = MPLIST_VAL (pl);
2241                     MPLIST_ADD_PLIST (im_info->maps, MPLIST_KEY (pl), p);
2242                     M17N_OBJECT_REF (p);
2243                   }
2244               }
2245             else if (key == Mmacro)
2246               {
2247                 if (! temp->macros || MPLIST_TAIL_P (temp->macros))
2248                   continue;
2249                 if (! im_info->macros)
2250                   im_info->macros = mplist ();
2251                 MPLIST_DO (pl, temp->macros)
2252                   {
2253                     p = MPLIST_VAL (pl);
2254                     MPLIST_ADD_PLIST (im_info->macros, MPLIST_KEY (pl), p);
2255                     M17N_OBJECT_REF (p);
2256                   }
2257               }
2258             else if (key == Mstate)
2259               {
2260                 if (! temp->states || MPLIST_TAIL_P (temp->states))
2261                   continue;
2262                 if (! im_info->states)
2263                   im_info->states = mplist ();
2264                 MPLIST_DO (pl, temp->states)
2265                   {
2266                     MIMState *state = MPLIST_VAL (pl);
2267
2268                     mplist_add (im_info->states, MPLIST_KEY (pl), state);
2269                     M17N_OBJECT_REF (state);
2270                   }
2271               }
2272           }
2273         else if (key == Mdescription)
2274           {
2275             if (im_info->description)
2276               continue;
2277             elt = MPLIST_NEXT (elt);
2278             if (! check_description (elt))
2279               continue;
2280             im_info->description = MPLIST_MTEXT (elt);
2281             M17N_OBJECT_REF (im_info->description);
2282           }
2283       }
2284   im_info->tick = time (NULL);
2285 }
2286
2287 \f
2288
2289 static int take_action_list (MInputContext *ic, MPlist *action_list);
2290 static void preedit_commit (MInputContext *ic);
2291
2292 static void
2293 shift_state (MInputContext *ic, MSymbol state_name)
2294 {
2295   MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
2296   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
2297   MIMState *orig_state = ic_info->state, *state;
2298
2299   /* Find a state to shift to.  If not found, shift to the initial
2300      state.  */
2301   if (state_name == Mt)
2302     {
2303       if (! ic_info->prev_state)
2304         return;
2305       state = ic_info->prev_state;
2306     }
2307   else if (state_name == Mnil)
2308     {
2309       state = (MIMState *) MPLIST_VAL (im_info->states);
2310     }
2311   else
2312     {
2313       state = (MIMState *) mplist_get (im_info->states, state_name);
2314       if (! state)
2315         state = (MIMState *) MPLIST_VAL (im_info->states);
2316     }
2317
2318   MDEBUG_PRINT1 ("\n  [IM] (shift %s)", MSYMBOL_NAME (state->name));
2319
2320   /* Enter the new state.  */
2321   ic_info->state = state;
2322   ic_info->map = state->map;
2323   ic_info->state_key_head = ic_info->key_head;
2324   if (state == (MIMState *) MPLIST_VAL (im_info->states)
2325       && orig_state)
2326     /* We have shifted to the initial state.  */
2327     preedit_commit (ic);
2328   mtext_cpy (ic_info->preedit_saved, ic->preedit);
2329   ic_info->state_pos = ic->cursor_pos;
2330   if (state != orig_state)
2331     {
2332       if (state == (MIMState *) MPLIST_VAL (im_info->states))
2333         {
2334           /* Shifted to the initial state.  */
2335           ic_info->prev_state = NULL;
2336           M17N_OBJECT_UNREF (ic_info->vars_saved);
2337           ic_info->vars_saved = mplist_copy (ic_info->vars);
2338         }
2339       else
2340         ic_info->prev_state = orig_state;
2341
2342       if (state->title)
2343         ic->status = state->title;
2344       else
2345         ic->status = im_info->title;
2346       ic->status_changed = 1;
2347       if (ic_info->map == ic_info->state->map
2348           && ic_info->map->map_actions)
2349         {
2350           MDEBUG_PRINT (" init-actions:");
2351           take_action_list (ic, ic_info->map->map_actions);
2352         }
2353     }
2354 }
2355
2356 /* Find a candidate group that contains a candidate number INDEX from
2357    PLIST.  Set START_INDEX to the first candidate number of the group,
2358    END_INDEX to the last candidate number plus 1, GROUP_INDEX to the
2359    candidate group number if they are non-NULL.  If INDEX is -1, find
2360    the last candidate group.  */
2361
2362 static MPlist *
2363 find_candidates_group (MPlist *plist, int index,
2364                        int *start_index, int *end_index, int *group_index)
2365 {
2366   int i = 0, gidx = 0, len;
2367
2368   MPLIST_DO (plist, plist)
2369     {
2370       if (MPLIST_MTEXT_P (plist))
2371         len = mtext_nchars (MPLIST_MTEXT (plist));
2372       else
2373         len = mplist_length (MPLIST_PLIST (plist));
2374       if (index < 0 ? MPLIST_TAIL_P (MPLIST_NEXT (plist))
2375           : i + len > index)
2376         {
2377           if (start_index)
2378             *start_index = i;
2379           if (end_index)
2380             *end_index = i + len;
2381           if (group_index)
2382             *group_index = gidx;
2383           return plist;
2384         }
2385       i += len;
2386       gidx++;
2387     }
2388   return NULL;
2389 }
2390
2391 static void
2392 preedit_insert (MInputContext *ic, int pos, MText *mt, int c)
2393 {
2394   MInputContextInfo *ic_info = ((MInputContext *) ic)->info;
2395   MPlist *markers;
2396   int nchars = mt ? mtext_nchars (mt) : 1;
2397
2398   if (mt)
2399     mtext_ins (ic->preedit, pos, mt);
2400   else
2401     mtext_ins_char (ic->preedit, pos, c, 1);
2402   MPLIST_DO (markers, ic_info->markers)
2403     if (MPLIST_INTEGER (markers) > pos)
2404       MPLIST_VAL (markers) = (void *) (MPLIST_INTEGER (markers) + nchars);
2405   if (ic->cursor_pos >= pos)
2406     ic->cursor_pos += nchars;
2407   ic->preedit_changed = 1;
2408 }
2409
2410
2411 static void
2412 preedit_delete (MInputContext *ic, int from, int to)
2413 {
2414   MInputContextInfo *ic_info = ((MInputContext *) ic)->info;
2415   MPlist *markers;
2416
2417   mtext_del (ic->preedit, from, to);
2418   MPLIST_DO (markers, ic_info->markers)
2419     {
2420       if (MPLIST_INTEGER (markers) > to)
2421         MPLIST_VAL (markers)
2422           = (void *) (MPLIST_INTEGER (markers) - (to - from));
2423       else if (MPLIST_INTEGER (markers) > from)
2424         MPLIST_VAL (markers) = (void *) from;
2425     }
2426   if (ic->cursor_pos >= to)
2427     ic->cursor_pos -= to - from;
2428   else if (ic->cursor_pos > from)
2429     ic->cursor_pos = from;
2430   ic->preedit_changed = 1;
2431 }
2432
2433 static void
2434 preedit_commit (MInputContext *ic)
2435 {
2436   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
2437   int preedit_len = mtext_nchars (ic->preedit);
2438
2439   if (preedit_len > 0)
2440     {
2441       MPlist *p;
2442
2443       mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit),
2444                              Mcandidate_list, NULL, 0);
2445       mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit),
2446                              Mcandidate_index, NULL, 0);
2447       mtext_cat (ic->produced, ic->preedit);
2448       mtext_reset (ic->preedit);
2449       mtext_reset (ic_info->preedit_saved);
2450       MPLIST_DO (p, ic_info->markers)
2451         MPLIST_VAL (p) = 0;
2452       ic->cursor_pos = ic_info->state_pos = 0;
2453       ic->preedit_changed = 1;
2454     }
2455   if (ic->candidate_list)
2456     {
2457       M17N_OBJECT_UNREF (ic->candidate_list);
2458       ic->candidate_list = NULL;
2459       ic->candidates_changed = MINPUT_CANDIDATES_LIST_CHANGED;
2460       if (ic->candidate_show)
2461         {
2462           ic->candidate_show = 0;
2463           ic->candidates_changed |= MINPUT_CANDIDATES_SHOW_CHANGED;
2464         }
2465     }
2466 }
2467
2468 static int
2469 new_index (MInputContext *ic, int current, int limit, MSymbol sym, MText *mt)
2470 {
2471   int code = marker_code (sym, 0);
2472
2473   if (mt && (code == '[' || code == ']'))
2474     {
2475       int pos = current;
2476
2477       if (code == '[' && current > 0)
2478         {
2479           if (mtext_prop_range (mt, Mcandidate_list, pos - 1, &pos, NULL, 1)
2480               && pos > 0)
2481             current = pos;
2482         }
2483       else if (code == ']' && current < mtext_nchars (mt))
2484         {
2485           if (mtext_prop_range (mt, Mcandidate_list, pos, NULL, &pos, 1))
2486             current = pos;
2487         }
2488       return current;
2489     }
2490   if (code >= 0)
2491     return (code == '<' ? 0
2492             : code == '>' ? limit
2493             : code == '-' ? current - 1
2494             : code == '+' ? current + 1
2495             : code == '=' ? current
2496             : code - '0' > limit ? limit
2497             : code - '0');
2498   if (! ic)  
2499     return 0;
2500   return (int) mplist_get (((MInputContextInfo *) ic->info)->markers, sym);
2501 }
2502
2503 static void
2504 update_candidate (MInputContext *ic, MTextProperty *prop, int idx)
2505 {
2506   int from = mtext_property_start (prop);
2507   int to = mtext_property_end (prop);
2508   int start;
2509   MPlist *candidate_list = mtext_property_value (prop);
2510   MPlist *group = find_candidates_group (candidate_list, idx, &start,
2511                                          NULL, NULL);
2512   int ingroup_index = idx - start;
2513   MText *mt;
2514
2515   preedit_delete (ic, from, to);
2516   if (MPLIST_MTEXT_P (group))
2517     {
2518       mt = MPLIST_MTEXT (group);
2519       preedit_insert (ic, from, NULL, mtext_ref_char (mt, ingroup_index));
2520       to = from + 1;
2521     }
2522   else
2523     {
2524       int i;
2525       MPlist *plist;
2526
2527       for (i = 0, plist = MPLIST_PLIST (group); i < ingroup_index;
2528            i++, plist = MPLIST_NEXT (plist));
2529       mt = MPLIST_MTEXT (plist);
2530       preedit_insert (ic, from, mt, 0);
2531       to = from + mtext_nchars (mt);
2532     }
2533   mtext_put_prop (ic->preedit, from, to, Mcandidate_list, candidate_list);
2534   mtext_put_prop (ic->preedit, from, to, Mcandidate_index, (void *) idx);
2535   ic->cursor_pos = to;
2536 }
2537
2538 static MCharset *
2539 get_select_charset (MInputContextInfo * ic_info)
2540 {
2541   MPlist *plist = resolve_variable (ic_info, Mcandidates_charset);
2542   MSymbol sym;
2543
2544   if (! MPLIST_VAL (plist))
2545     return NULL;
2546   sym = MPLIST_SYMBOL (plist);
2547   if (sym == Mnil)
2548     return NULL;
2549   return MCHARSET (sym);
2550 }
2551
2552 static MPlist *
2553 adjust_candidates (MPlist *plist, MCharset *charset)
2554 {
2555   MPlist *pl;
2556
2557   /* plist ::= MTEXT ... | PLIST ... */
2558   plist = mplist_copy (plist);
2559   if (MPLIST_MTEXT_P (plist))
2560     {
2561       pl = plist;
2562       while (! MPLIST_TAIL_P (pl))
2563         {
2564           /* pl ::= MTEXT ... */
2565           MText *mt = MPLIST_MTEXT (pl);
2566           int mt_copied = 0;
2567           int i, c;
2568
2569           for (i = mtext_nchars (mt) - 1; i >= 0; i--)
2570             {
2571               c = mtext_ref_char (mt, i);
2572               if (ENCODE_CHAR (charset, c) == MCHAR_INVALID_CODE)
2573                 {
2574                   if (! mt_copied)
2575                     {
2576                       mt = mtext_dup (mt);
2577                       mplist_set (pl, Mtext, mt);
2578                       M17N_OBJECT_UNREF (mt);
2579                       mt_copied = 1;
2580                     }
2581                   mtext_del (mt, i, i + 1);
2582                 }
2583             }
2584           if (mtext_len (mt) > 0)
2585             pl = MPLIST_NEXT (pl);
2586           else
2587             {
2588               mplist_pop (pl);
2589               M17N_OBJECT_UNREF (mt);
2590             }
2591         }
2592     }
2593   else                          /* MPLIST_PLIST_P (plist) */
2594     {
2595       pl = plist;
2596       while (! MPLIST_TAIL_P (pl))
2597         {
2598           /* pl ::= (MTEXT ...) ... */
2599           MPlist *p = MPLIST_PLIST (pl);
2600           int p_copied = 0;
2601           /* p ::= MTEXT ... */
2602           MPlist *p0 = p;
2603           int n = 0;
2604
2605           while (! MPLIST_TAIL_P (p0))
2606             {
2607               MText *mt = MPLIST_MTEXT (p0);
2608               int i, c;
2609
2610               for (i = mtext_nchars (mt) - 1; i >= 0; i--)
2611                 {
2612                   c = mtext_ref_char (mt, i);
2613                   if (ENCODE_CHAR (charset, c) == MCHAR_INVALID_CODE)
2614                     break;
2615                 }
2616               if (i < 0)
2617                 {
2618                   p0 = MPLIST_NEXT (p0);
2619                   n++;
2620                 }
2621               else
2622                 {
2623                   if (! p_copied)
2624                     {
2625                       p = mplist_copy (p);
2626                       mplist_set (pl, Mplist, p);
2627                       M17N_OBJECT_UNREF (p);
2628                       p_copied = 1;
2629                       p0 = p;
2630                       while (n-- > 0)
2631                         p0 = MPLIST_NEXT (p0);
2632                     }     
2633                   mplist_pop (p0);
2634                   M17N_OBJECT_UNREF (mt);
2635                 }
2636             }
2637           if (! MPLIST_TAIL_P (p))
2638             pl = MPLIST_NEXT (pl);
2639           else
2640             {
2641               mplist_pop (pl);
2642               M17N_OBJECT_UNREF (p);
2643             }
2644         }
2645     }
2646   if (MPLIST_TAIL_P (plist))
2647     {
2648       M17N_OBJECT_UNREF (plist);
2649       return NULL;
2650     }      
2651   return plist;
2652 }
2653
2654 static MPlist *
2655 get_candidate_list (MInputContextInfo *ic_info, MPlist *args)
2656 {
2657   MCharset *charset = get_select_charset (ic_info);
2658   MPlist *plist;
2659   int column;
2660   int i, len;
2661
2662   plist = resolve_variable (ic_info, Mcandidates_group_size);
2663   column = MPLIST_INTEGER (plist);
2664
2665   plist = MPLIST_PLIST (args);
2666   if (charset)
2667     plist = adjust_candidates (plist, charset);
2668
2669   if (plist && column > 0)
2670     {
2671       if (MPLIST_MTEXT_P (plist))
2672         {
2673           MText *mt = MPLIST_MTEXT (plist);
2674           MPlist *next = MPLIST_NEXT (plist);
2675
2676           if (MPLIST_TAIL_P (next))
2677             M17N_OBJECT_REF (mt);
2678           else
2679             {
2680               mt = mtext_dup (mt);
2681               while (! MPLIST_TAIL_P (next))
2682                 {
2683                   mt = mtext_cat (mt, MPLIST_MTEXT (next));
2684                   next = MPLIST_NEXT (next);
2685                 }
2686             }
2687           M17N_OBJECT_UNREF (plist);
2688           plist = mplist ();
2689           len = mtext_nchars (mt);
2690           if (len <= column)
2691             mplist_add (plist, Mtext, mt);
2692           else
2693             {
2694               for (i = 0; i < len; i += column)
2695                 {
2696                   int to = (i + column < len ? i + column : len);
2697                   MText *sub = mtext_copy (mtext (), 0, mt, i, to);
2698                                                        
2699                   mplist_add (plist, Mtext, sub);
2700                   M17N_OBJECT_UNREF (sub);
2701                 }
2702             }
2703           M17N_OBJECT_UNREF (mt);
2704         }
2705       else              /* MPLIST_PLIST_P (plist) */
2706         {
2707           MPlist *pl = MPLIST_PLIST (plist), *p;
2708           MPlist *next = MPLIST_NEXT (plist);
2709           int j;
2710
2711           if (MPLIST_TAIL_P (next))
2712             M17N_OBJECT_REF (pl);
2713           else
2714             {
2715               pl = mplist_copy (pl);
2716               while (! MPLIST_TAIL_P (next))
2717                 {
2718                   p = mplist_copy (MPLIST_PLIST (next));
2719                   pl = mplist__conc (pl, p);
2720                   M17N_OBJECT_UNREF (p);
2721                   next = MPLIST_NEXT (next);
2722                 }
2723             }
2724           M17N_OBJECT_UNREF (plist);
2725           plist = mplist ();
2726           len = mplist_length (pl);
2727           if (len <= column)
2728             mplist_add (plist, Mplist, pl);
2729           else
2730             {
2731               MPlist *p0 = pl;
2732
2733               for (i = 0; i < len; i += column)
2734                 {
2735                   p = mplist ();
2736                   mplist_add (plist, Mplist, p);
2737                   M17N_OBJECT_UNREF (p);
2738                   for (j = 0; j < column && i + j < len; j++)
2739                     {
2740                       p = mplist_add (p, Mtext, MPLIST_VAL (p0));
2741                       p0 = MPLIST_NEXT (p0);
2742                     }
2743                 }
2744             }
2745           M17N_OBJECT_UNREF (pl);
2746         }
2747     }
2748
2749   return plist;
2750 }
2751
2752
2753 static MPlist *
2754 regularize_action (MPlist *action_list, MInputContextInfo *ic_info)
2755 {
2756   MPlist *action = NULL;
2757   MSymbol name;
2758   MPlist *args;
2759
2760   if (MPLIST_SYMBOL_P (action_list))
2761     {
2762       MSymbol var = MPLIST_SYMBOL (action_list);
2763       MPlist *p;
2764
2765       MPLIST_DO (p, ic_info->vars)
2766         if (MPLIST_SYMBOL (MPLIST_PLIST (p)) == var)
2767           break;
2768       if (MPLIST_TAIL_P (p))
2769         return NULL;
2770       action = MPLIST_NEXT (MPLIST_PLIST (p));
2771       mplist_set (action_list, MPLIST_KEY (action), MPLIST_VAL (action));
2772     }
2773
2774   if (MPLIST_PLIST_P (action_list))
2775     {
2776       action = MPLIST_PLIST (action_list);
2777       if (MPLIST_SYMBOL_P (action))
2778         {
2779           name = MPLIST_SYMBOL (action);
2780           args = MPLIST_NEXT (action);
2781           if (name == Minsert
2782               && MPLIST_PLIST_P (args))
2783             mplist_set (action, Msymbol, M_candidates);
2784         }
2785       else if (MPLIST_MTEXT_P (action) || MPLIST_PLIST_P (action))
2786         {
2787           action = mplist ();
2788           mplist_push (action, Mplist, MPLIST_VAL (action_list));
2789           mplist_push (action, Msymbol, M_candidates);
2790           mplist_set (action_list, Mplist, action);
2791           M17N_OBJECT_UNREF (action);
2792         }
2793     }
2794   else if (MPLIST_MTEXT_P (action_list) || MPLIST_INTEGER_P (action_list))
2795     {
2796       action = mplist ();
2797       mplist_push (action, MPLIST_KEY (action_list), MPLIST_VAL (action_list));
2798       mplist_push (action, Msymbol, Minsert);
2799       mplist_set (action_list, Mplist, action);
2800       M17N_OBJECT_UNREF (action);
2801     }
2802   return action;
2803 }
2804
2805 /* Perform list of actions in ACTION_LIST for the current input
2806    context IC.  If all actions are performed without error, return 0.
2807    Otherwise, return -1.  */
2808
2809 static int
2810 take_action_list (MInputContext *ic, MPlist *action_list)
2811 {
2812   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
2813   MPlist *candidate_list = ic->candidate_list;
2814   int candidate_index = ic->candidate_index;
2815   int candidate_show = ic->candidate_show;
2816   MTextProperty *prop;
2817
2818   MPLIST_DO (action_list, action_list)
2819     {
2820       MPlist *action = regularize_action (action_list, ic_info);
2821       MSymbol name;
2822       MPlist *args;
2823
2824       if (! action)
2825         continue;
2826       name = MPLIST_SYMBOL (action);
2827       args = MPLIST_NEXT (action);
2828
2829       MDEBUG_PRINT1 (" %s", MSYMBOL_NAME (name));
2830       if (name == Minsert)
2831         {
2832           if (MPLIST_SYMBOL_P (args))
2833             {
2834               args = resolve_variable (ic_info, MPLIST_SYMBOL (args));
2835               if (! MPLIST_MTEXT_P (args) && ! MPLIST_INTEGER_P (args))
2836                 continue;
2837             }
2838           if (MPLIST_MTEXT_P (args))
2839             preedit_insert (ic, ic->cursor_pos, MPLIST_MTEXT (args), 0);
2840           else                  /* MPLIST_INTEGER_P (args)) */
2841             preedit_insert (ic, ic->cursor_pos, NULL, MPLIST_INTEGER (args));
2842         }
2843       else if (name == M_candidates)
2844         {
2845           MPlist *plist = get_candidate_list (ic_info, args);
2846           int len;
2847
2848           if (! plist)
2849             continue;
2850           if (MPLIST_MTEXT_P (plist))
2851             {
2852               preedit_insert (ic, ic->cursor_pos, NULL,
2853                               mtext_ref_char (MPLIST_MTEXT (plist), 0));
2854               len = 1;
2855             }
2856           else
2857             {
2858               MText * mt = MPLIST_MTEXT (MPLIST_PLIST (plist));
2859
2860               preedit_insert (ic, ic->cursor_pos, mt, 0);
2861               len = mtext_nchars (mt);
2862             }
2863           mtext_put_prop (ic->preedit,
2864                           ic->cursor_pos - len, ic->cursor_pos,
2865                           Mcandidate_list, plist);
2866           mtext_put_prop (ic->preedit,
2867                           ic->cursor_pos - len, ic->cursor_pos,
2868                           Mcandidate_index, (void *) 0);
2869         }
2870       else if (name == Mselect)
2871         {
2872           int start, end;
2873           int code, idx, gindex;
2874           int pos = ic->cursor_pos;
2875           MPlist *group;
2876           int idx_decided = 0;
2877
2878           if (pos == 0
2879               || ! (prop = mtext_get_property (ic->preedit, pos - 1,
2880                                                Mcandidate_list)))
2881             continue;
2882           idx = (int) mtext_get_prop (ic->preedit, pos - 1, Mcandidate_index);
2883           group = find_candidates_group (mtext_property_value (prop), idx,
2884                                          &start, &end, &gindex);
2885           if (MPLIST_SYMBOL_P (args))
2886             {
2887               code = marker_code (MPLIST_SYMBOL (args), 0);
2888               if (code < 0)
2889                 {
2890                   args = resolve_variable (ic_info, MPLIST_SYMBOL (args));
2891                   if (! MPLIST_INTEGER_P (args))
2892                     continue;
2893                   idx = start + MPLIST_INTEGER (args);
2894                   if (idx < start || idx >= end)
2895                     continue;
2896                   idx_decided = 1;
2897                 }                 
2898             }
2899           else
2900             code = -1;
2901
2902           if (code != '[' && code != ']')
2903             {
2904               if (! idx_decided)
2905                 idx = (start
2906                        + (code >= 0
2907                           ? new_index (NULL, ic->candidate_index - start,
2908                                        end - start - 1, MPLIST_SYMBOL (args),
2909                                        NULL)
2910                           : MPLIST_INTEGER (args)));
2911               if (idx < 0)
2912                 {
2913                   find_candidates_group (mtext_property_value (prop), -1,
2914                                          NULL, &end, NULL);
2915                   idx = end - 1;
2916                 }
2917               else if (idx >= end
2918                        && MPLIST_TAIL_P (MPLIST_NEXT (group)))
2919                 idx = 0;
2920             }
2921           else
2922             {
2923               int ingroup_index = idx - start;
2924               int len;
2925
2926               group = mtext_property_value (prop);
2927               len = mplist_length (group);
2928               if (code == '[')
2929                 {
2930                   gindex--;
2931                   if (gindex < 0)
2932                     gindex = len - 1;;
2933                 }
2934               else
2935                 {
2936                   gindex++;
2937                   if (gindex >= len)
2938                     gindex = 0;
2939                 }
2940               for (idx = 0; gindex > 0; gindex--, group = MPLIST_NEXT (group))
2941                 idx += (MPLIST_MTEXT_P (group)
2942                         ? mtext_nchars (MPLIST_MTEXT (group))
2943                         : mplist_length (MPLIST_PLIST (group)));
2944               len = (MPLIST_MTEXT_P (group)
2945                      ? mtext_nchars (MPLIST_MTEXT (group))
2946                      : mplist_length (MPLIST_PLIST (group)));
2947               if (ingroup_index >= len)
2948                 ingroup_index = len - 1;
2949               idx += ingroup_index;
2950             }
2951           update_candidate (ic, prop, idx);
2952           MDEBUG_PRINT1 ("(%d)", idx);
2953         }
2954       else if (name == Mshow)
2955         ic->candidate_show = 1;
2956       else if (name == Mhide)
2957         ic->candidate_show = 0;
2958       else if (name == Mdelete)
2959         {
2960           int len = mtext_nchars (ic->preedit);
2961           int pos;
2962           int to;
2963
2964           if (MPLIST_SYMBOL_P (args)
2965               && (pos = surrounding_pos (MPLIST_SYMBOL (args))) != 0)
2966             {
2967               to = ic->cursor_pos + pos;
2968               if (to < 0)
2969                 {
2970                   delete_surrounding_text (ic, to);
2971                   to = 0;
2972                 }
2973               else if (to > len)
2974                 {
2975                   delete_surrounding_text (ic, to - len);
2976                   to = len;
2977                 }
2978             }
2979           else
2980             {
2981               to = (MPLIST_SYMBOL_P (args)
2982                     ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
2983                                  ic->preedit)
2984                     : MPLIST_INTEGER (args));
2985               if (to < 0)
2986                 to = 0;
2987               else if (to > len)
2988                 to = len;
2989             }
2990           MDEBUG_PRINT1 ("(%d)", to - ic->cursor_pos);
2991           if (to < ic->cursor_pos)
2992             preedit_delete (ic, to, ic->cursor_pos);
2993           else if (to > ic->cursor_pos)
2994             preedit_delete (ic, ic->cursor_pos, to);
2995         }
2996       else if (name == Mmove)
2997         {
2998           int len = mtext_nchars (ic->preedit);
2999           int pos
3000             = (MPLIST_SYMBOL_P (args)
3001                ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
3002                             ic->preedit)
3003                : MPLIST_INTEGER (args));
3004
3005           if (pos < 0)
3006             pos = 0;
3007           else if (pos > len)
3008             pos = len;
3009           if (pos != ic->cursor_pos)
3010             {
3011               ic->cursor_pos = pos;
3012               ic->preedit_changed = 1;
3013             }
3014           MDEBUG_PRINT1 ("(%d)", ic->cursor_pos);
3015         }
3016       else if (name == Mmark)
3017         {
3018           int code = marker_code (MPLIST_SYMBOL (args), 0);
3019
3020           if (code < 0)
3021             {
3022               mplist_put (ic_info->markers, MPLIST_SYMBOL (args),
3023                           (void *) ic->cursor_pos);
3024               MDEBUG_PRINT1 ("(%d)", ic->cursor_pos);
3025             }
3026         }
3027       else if (name == Mpushback)
3028         {
3029           if (MPLIST_INTEGER_P (args) || MPLIST_SYMBOL_P (args))
3030             {
3031               int num;
3032
3033               if (MPLIST_SYMBOL_P (args))
3034                 {
3035                   args = resolve_variable (ic_info, MPLIST_SYMBOL (args));
3036                   if (MPLIST_INTEGER_P (args))
3037                     num = MPLIST_INTEGER (args);
3038                   else
3039                     num = 0;
3040                 }
3041               else
3042                 num = MPLIST_INTEGER (args);
3043
3044               if (num > 0)
3045                 ic_info->key_head -= num;
3046               else if (num == 0)
3047                 ic_info->key_head = 0;
3048               else
3049                 ic_info->key_head = - num;
3050               if (ic_info->key_head > ic_info->used)
3051                 ic_info->key_head = ic_info->used;
3052             }
3053           else if (MPLIST_MTEXT_P (args))
3054             {
3055               MText *mt = MPLIST_MTEXT (args);
3056               int i, len = mtext_nchars (mt);
3057               MSymbol key;
3058
3059               ic_info->key_head--;
3060               for (i = 0; i < len; i++)
3061                 {
3062                   key = one_char_symbol[MTEXT_DATA (mt)[i]];
3063                   if (ic_info->key_head + i < ic_info->used)
3064                     ic_info->keys[ic_info->key_head + i] = key;
3065                   else
3066                     MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
3067                 }
3068             }
3069           else
3070             {
3071               MPlist *plist = MPLIST_PLIST (args), *pl;
3072               int i = 0;
3073               MSymbol key;
3074
3075               ic_info->key_head--;
3076
3077               MPLIST_DO (pl, plist)
3078                 {
3079                   key = MPLIST_SYMBOL (pl);
3080                   if (ic_info->key_head < ic_info->used)
3081                     ic_info->keys[ic_info->key_head + i] = key;
3082                   else
3083                     MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
3084                   i++;
3085                 }
3086             }
3087         }
3088       else if (name == Mcall)
3089         {
3090           MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
3091           MIMExternalFunc func = NULL;
3092           MSymbol module, func_name;
3093           MPlist *func_args, *val;
3094           int ret = 0;
3095
3096           module = MPLIST_SYMBOL (args);
3097           args = MPLIST_NEXT (args);
3098           func_name = MPLIST_SYMBOL (args);
3099
3100           if (im_info->externals)
3101             {
3102               MIMExternalModule *external
3103                 = (MIMExternalModule *) mplist_get (im_info->externals,
3104                                                     module);
3105               if (external)
3106                 func = (MIMExternalFunc) mplist_get (external->func_list,
3107                                                      func_name);
3108             }
3109           if (! func)
3110             continue;
3111           func_args = mplist ();
3112           mplist_add (func_args, Mt, ic);
3113           MPLIST_DO (args, MPLIST_NEXT (args))
3114             {
3115               int code;
3116
3117               if (MPLIST_KEY (args) == Msymbol
3118                   && MPLIST_KEY (args) != Mnil
3119                   && (code = marker_code (MPLIST_SYMBOL (args), 0)) >= 0)
3120                 {
3121                   code = new_index (ic, ic->cursor_pos, 
3122                                     mtext_nchars (ic->preedit),
3123                                     MPLIST_SYMBOL (args), ic->preedit);
3124                   mplist_add (func_args, Minteger, (void *) code);
3125                 }
3126               else
3127                 mplist_add (func_args, MPLIST_KEY (args), MPLIST_VAL (args));
3128             }
3129           val = (func) (func_args);
3130           M17N_OBJECT_UNREF (func_args);
3131           if (val && ! MPLIST_TAIL_P (val))
3132             ret = take_action_list (ic, val);
3133           M17N_OBJECT_UNREF (val);
3134           if (ret < 0)
3135             return ret;
3136         }
3137       else if (name == Mshift)
3138         {
3139           shift_state (ic, MPLIST_SYMBOL (args));
3140         }
3141       else if (name == Mundo)
3142         {
3143           int intarg = (MPLIST_TAIL_P (args)
3144                         ? ic_info->used - 2
3145                         : integer_value (ic, args, NULL, 0));
3146
3147           mtext_reset (ic->preedit);
3148           mtext_reset (ic_info->preedit_saved);
3149           mtext_reset (ic->produced);
3150           M17N_OBJECT_UNREF (ic_info->vars);
3151           ic_info->vars = mplist_copy (ic_info->vars_saved);
3152           ic->cursor_pos = ic_info->state_pos = 0;
3153           ic_info->state_key_head = ic_info->key_head = 0;
3154
3155           shift_state (ic, Mnil);
3156           if (intarg < 0)
3157             {
3158               if (MPLIST_TAIL_P (args))
3159                 {
3160                   ic_info->used = 0;
3161                   return -1;
3162                 }
3163               ic_info->used += intarg;
3164             }
3165           else
3166             ic_info->used = intarg;
3167           break;
3168         }
3169       else if (name == Mset || name == Madd || name == Msub
3170                || name == Mmul || name == Mdiv)
3171         {
3172           MSymbol sym = MPLIST_SYMBOL (args);
3173           int val1, val2;
3174           MPlist *value;
3175           char *op;
3176
3177           val1 = integer_value (ic, args, &value, 0);
3178           args = MPLIST_NEXT (args);
3179           val2 = resolve_expression (ic, args);
3180           if (name == Mset)
3181             val1 = val2, op = "=";
3182           else if (name == Madd)
3183             val1 += val2, op = "+=";
3184           else if (name == Msub)
3185             val1 -= val2, op = "-=";
3186           else if (name == Mmul)
3187             val1 *= val2, op = "*=";
3188           else
3189             val1 /= val2, op = "/=";
3190           MDEBUG_PRINT4 ("(%s %s 0x%X(%d))",
3191                          MSYMBOL_NAME (sym), op, val1, val1);
3192           if (value)
3193             mplist_set (value, Minteger, (void *) val1);
3194         }
3195       else if (name == Mequal || name == Mless || name == Mgreater
3196                || name == Mless_equal || name == Mgreater_equal)
3197         {
3198           int val1, val2;
3199           MPlist *actions1, *actions2;
3200           int ret = 0;
3201
3202           val1 = resolve_expression (ic, args);
3203           args = MPLIST_NEXT (args);
3204           val2 = resolve_expression (ic, args);
3205           args = MPLIST_NEXT (args);
3206           actions1 = MPLIST_PLIST (args);
3207           args = MPLIST_NEXT (args);
3208           if (MPLIST_TAIL_P (args))
3209             actions2 = NULL;
3210           else
3211             actions2 = MPLIST_PLIST (args);
3212           MDEBUG_PRINT3 ("(%d %s %d)? ", val1, MSYMBOL_NAME (name), val2);
3213           if (name == Mequal ? val1 == val2
3214               : name == Mless ? val1 < val2
3215               : name == Mgreater ? val1 > val2
3216               : name == Mless_equal ? val1 <= val2
3217               : val1 >= val2)
3218             {
3219               MDEBUG_PRINT ("ok");
3220               ret = take_action_list (ic, actions1);
3221             }
3222           else
3223             {
3224               MDEBUG_PRINT ("no");
3225               if (actions2)
3226                 ret = take_action_list (ic, actions2);
3227             }
3228           if (ret < 0)
3229             return ret;
3230         }
3231       else if (name == Mcond)
3232         {
3233           int idx = 0;
3234
3235           MPLIST_DO (args, args)
3236             {
3237               MPlist *cond;
3238
3239               idx++;
3240               if (! MPLIST_PLIST (args))
3241                 continue;
3242               cond = MPLIST_PLIST (args);
3243               if (resolve_expression (ic, cond) != 0)
3244                 {
3245                   MDEBUG_PRINT1 ("(%dth)", idx);
3246                   if (take_action_list (ic, MPLIST_NEXT (cond)) < 0)
3247                     return -1;;
3248                   break;
3249                 }
3250             }
3251         }
3252       else if (name == Mcommit)
3253         {
3254           preedit_commit (ic);
3255         }
3256       else if (name == Munhandle)
3257         {
3258           preedit_commit (ic);
3259           return -1;
3260         }
3261       else
3262         {
3263           MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
3264           MPlist *actions;
3265
3266           if (im_info->macros
3267               && (actions = mplist_get (im_info->macros, name)))
3268             {
3269               if (take_action_list (ic, actions) < 0)
3270                 return -1;
3271             };
3272         }
3273     }
3274
3275   if (ic->candidate_list)
3276     {
3277       M17N_OBJECT_UNREF (ic->candidate_list);
3278       ic->candidate_list = NULL;
3279     }
3280   if (ic->cursor_pos > 0
3281       && (prop = mtext_get_property (ic->preedit, ic->cursor_pos - 1,
3282                                      Mcandidate_list)))
3283     {
3284       ic->candidate_list = mtext_property_value (prop);
3285       M17N_OBJECT_REF (ic->candidate_list);
3286       ic->candidate_index
3287         = (int) mtext_get_prop (ic->preedit, ic->cursor_pos - 1,
3288                                 Mcandidate_index);
3289       ic->candidate_from = mtext_property_start (prop);
3290       ic->candidate_to = mtext_property_end (prop);
3291     }
3292
3293   if (candidate_list != ic->candidate_list)
3294     ic->candidates_changed |= MINPUT_CANDIDATES_LIST_CHANGED;
3295   if (candidate_index != ic->candidate_index)
3296     ic->candidates_changed |= MINPUT_CANDIDATES_INDEX_CHANGED;
3297   if (candidate_show != ic->candidate_show)
3298     ic->candidates_changed |= MINPUT_CANDIDATES_SHOW_CHANGED;    
3299   return 0;
3300 }
3301
3302
3303 /* Handle the input key KEY in the current state and map specified in
3304    the input context IC.  If KEY is handled correctly, return 0.
3305    Otherwise, return -1.  */
3306
3307 static int
3308 handle_key (MInputContext *ic)
3309 {
3310   MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
3311   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
3312   MIMMap *map = ic_info->map;
3313   MIMMap *submap = NULL;
3314   MSymbol key = ic_info->keys[ic_info->key_head];
3315   MSymbol alias = Mnil;
3316   int i;
3317
3318   MDEBUG_PRINT2 ("  [IM] handle `%s' in state %s", 
3319                  msymbol_name (key), MSYMBOL_NAME (ic_info->state->name));
3320
3321   if (map->submaps)
3322     {
3323       submap = mplist_get (map->submaps, key);
3324       alias = key;
3325       while (! submap
3326              && (alias = msymbol_get (alias, M_key_alias))
3327              && alias != key)
3328         submap = mplist_get (map->submaps, alias);
3329     }
3330
3331   if (submap)
3332     {
3333       if (! alias || alias == key)
3334         MDEBUG_PRINT (" submap-found");
3335       else
3336         MDEBUG_PRINT1 (" submap-found (by alias `%s')", MSYMBOL_NAME (alias));
3337       mtext_cpy (ic->preedit, ic_info->preedit_saved);
3338       ic->preedit_changed = 1;
3339       ic->cursor_pos = ic_info->state_pos;
3340       ic_info->key_head++;
3341       ic_info->map = map = submap;
3342       if (map->map_actions)
3343         {
3344           MDEBUG_PRINT (" map-actions:");
3345           if (take_action_list (ic, map->map_actions) < 0)
3346             {
3347               MDEBUG_PRINT ("\n");
3348               return -1;
3349             }
3350         }
3351       else if (map->submaps)
3352         {
3353           for (i = ic_info->state_key_head; i < ic_info->key_head; i++)
3354             {
3355               MSymbol key = ic_info->keys[i];
3356               char *name = msymbol_name (key);
3357
3358               if (! name[0] || ! name[1])
3359                 mtext_ins_char (ic->preedit, ic->cursor_pos++, name[0], 1);
3360             }
3361         }
3362
3363       /* If this is the terminal map or we have shifted to another
3364          state, perform branch actions (if any).  */
3365       if (! map->submaps || map != ic_info->map)
3366         {
3367           if (map->branch_actions)
3368             {
3369               MDEBUG_PRINT (" branch-actions:");
3370               if (take_action_list (ic, map->branch_actions) < 0)
3371                 {
3372                   MDEBUG_PRINT ("\n");
3373                   return -1;
3374                 }
3375             }
3376           /* If MAP is still not the root map, shift to the current
3377              state.  */
3378           if (ic_info->map != ic_info->state->map)
3379             shift_state (ic, ic_info->state->name);
3380         }
3381     }
3382   else
3383     {
3384       /* MAP can not handle KEY.  */
3385
3386       /* If MAP is the root map of the initial state, it means that
3387          the current input method can not handle KEY.  */
3388       if (map == ((MIMState *) MPLIST_VAL (im_info->states))->map)
3389         {
3390           MDEBUG_PRINT (" unhandled\n");
3391           return -1;
3392         }
3393
3394       if (map != ic_info->state->map)
3395         {
3396           /* If MAP is not the root map... */
3397           /* If MAP has branch actions, perform them.  */
3398           if (map->branch_actions)
3399             {
3400               MDEBUG_PRINT (" branch-actions:");
3401               if (take_action_list (ic, map->branch_actions) < 0)
3402                 {
3403                   MDEBUG_PRINT ("\n");
3404                   return -1;
3405                 }
3406             }
3407           /* If MAP is still not the root map, shift to the current
3408              state. */
3409           if (ic_info->map != ic_info->state->map)
3410             shift_state (ic, ic_info->state->name);
3411         }
3412       else
3413         {
3414           /* MAP is the root map, perform branch actions (if any) or
3415              shift to the initial state.  */
3416           if (map->branch_actions)
3417             {
3418               MDEBUG_PRINT (" branch-actions:");
3419               if (take_action_list (ic, map->branch_actions) < 0)
3420                 {
3421                   MDEBUG_PRINT ("\n");
3422                   return -1;
3423                 }
3424             }
3425           else
3426             shift_state (ic, Mnil);
3427         }
3428     }
3429   MDEBUG_PRINT ("\n");
3430   return 0;
3431 }
3432
3433 /* Initialize IC->ic_info.  */
3434
3435 static void
3436 init_ic_info (MInputContext *ic)
3437 {
3438   MInputMethodInfo *im_info = ic->im->info;
3439   MInputContextInfo *ic_info = ic->info;
3440   MPlist *plist;
3441   
3442   MLIST_INIT1 (ic_info, keys, 8);;
3443
3444   ic_info->markers = mplist ();
3445
3446   ic_info->vars = mplist ();
3447   if (im_info->configured_vars)
3448     MPLIST_DO (plist, im_info->configured_vars)
3449       {
3450         MPlist *pl = MPLIST_PLIST (plist);
3451         MSymbol name = MPLIST_SYMBOL (pl);
3452
3453         pl = MPLIST_NEXT (MPLIST_NEXT (MPLIST_NEXT (pl)));
3454         if (MPLIST_KEY (pl) != Mt)
3455           {
3456             MPlist *p = mplist ();
3457
3458             mplist_push (ic_info->vars, Mplist, p);
3459             M17N_OBJECT_UNREF (p);
3460             mplist_add (p, Msymbol, name);
3461             mplist_add (p, MPLIST_KEY (pl), MPLIST_VAL (pl));
3462           }
3463       }
3464   ic_info->vars_saved = mplist_copy (ic_info->vars);
3465
3466   if (im_info->externals)
3467     {
3468       MPlist *func_args = mplist (), *plist;
3469
3470       mplist_add (func_args, Mt, ic);
3471       MPLIST_DO (plist, im_info->externals)
3472         {
3473           MIMExternalModule *external = MPLIST_VAL (plist);
3474           MIMExternalFunc func
3475             = (MIMExternalFunc) mplist_get (external->func_list, Minit);
3476
3477           if (func)
3478             (func) (func_args);
3479         }
3480       M17N_OBJECT_UNREF (func_args);
3481     }
3482
3483   ic_info->preedit_saved = mtext ();
3484   ic_info->tick = im_info->tick;
3485 }
3486
3487 /* Finalize IC->ic_info.  */
3488
3489 static void
3490 fini_ic_info (MInputContext *ic)
3491 {
3492   MInputMethodInfo *im_info = ic->im->info;
3493   MInputContextInfo *ic_info = ic->info;
3494
3495   if (im_info->externals)
3496     {
3497       MPlist *func_args = mplist (), *plist;
3498
3499       mplist_add (func_args, Mt, ic);
3500       MPLIST_DO (plist, im_info->externals)
3501         {
3502           MIMExternalModule *external = MPLIST_VAL (plist);
3503           MIMExternalFunc func
3504             = (MIMExternalFunc) mplist_get (external->func_list, Mfini);
3505
3506           if (func)
3507             (func) (func_args);
3508         }
3509       M17N_OBJECT_UNREF (func_args);
3510     }
3511
3512   MLIST_FREE1 (ic_info, keys);
3513   M17N_OBJECT_UNREF (ic_info->preedit_saved);
3514   M17N_OBJECT_UNREF (ic_info->markers);
3515   M17N_OBJECT_UNREF (ic_info->vars);
3516   M17N_OBJECT_UNREF (ic_info->vars_saved);
3517   M17N_OBJECT_UNREF (ic_info->preceding_text);
3518   M17N_OBJECT_UNREF (ic_info->following_text);
3519
3520   memset (ic_info, 0, sizeof (MInputContextInfo));
3521 }
3522
3523 static void
3524 re_init_ic (MInputContext *ic, int reload)
3525 {
3526   MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
3527   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
3528   int status_changed, preedit_changed, cursor_pos_changed, candidates_changed;
3529
3530   status_changed = ic_info->state != (MIMState *) MPLIST_VAL (im_info->states);
3531   preedit_changed = mtext_nchars (ic->preedit) > 0;
3532   cursor_pos_changed = ic->cursor_pos > 0;
3533   candidates_changed = 0;
3534   if (ic->candidate_list)
3535     {
3536       candidates_changed |= MINPUT_CANDIDATES_LIST_CHANGED;
3537       M17N_OBJECT_UNREF (ic->candidate_list);
3538       ic->candidate_list = NULL;
3539     }
3540   if (ic->candidate_show)
3541     {
3542       candidates_changed |= MINPUT_CANDIDATES_SHOW_CHANGED;
3543       ic->candidate_show = 0;
3544     }
3545   if (ic->candidate_index > 0)
3546     {
3547       candidates_changed |= MINPUT_CANDIDATES_INDEX_CHANGED;
3548       ic->candidate_index = 0;
3549       ic->candidate_from = ic->candidate_to = 0;
3550     }
3551   if (mtext_nchars (ic->produced) > 0)
3552     mtext_reset (ic->produced);
3553   if (mtext_nchars (ic->preedit) > 0)
3554     mtext_reset (ic->preedit);
3555   ic->cursor_pos = 0;
3556   M17N_OBJECT_UNREF (ic->plist);
3557   ic->plist = mplist ();
3558
3559   fini_ic_info (ic);
3560   if (reload)
3561     reload_im_info (im_info);
3562   init_ic_info (ic);
3563   shift_state (ic, Mnil);
3564   ic->status_changed = status_changed;
3565   ic->preedit_changed = preedit_changed;
3566   ic->cursor_pos_changed = cursor_pos_changed;
3567   ic->candidates_changed = candidates_changed;
3568 }
3569
3570 static void
3571 reset_ic (MInputContext *ic, MSymbol ignore)
3572 {
3573   MDEBUG_PRINT ("\n  [IM] reset\n");
3574   re_init_ic (ic, 0);
3575 }
3576
3577 static int
3578 open_im (MInputMethod *im)
3579 {
3580   MInputMethodInfo *im_info = get_im_info (im->language, im->name, Mnil, Mnil);
3581
3582   if (! im_info)
3583     MERROR (MERROR_IM, -1);
3584   im->info = im_info;
3585
3586   return 0;
3587 }
3588
3589 static void
3590 close_im (MInputMethod *im)
3591 {
3592   im->info = NULL;
3593 }
3594
3595 static int
3596 create_ic (MInputContext *ic)
3597 {
3598   MInputContextInfo *ic_info;
3599
3600   MSTRUCT_CALLOC (ic_info, MERROR_IM);
3601   ic->info = ic_info;
3602   init_ic_info (ic);
3603   shift_state (ic, Mnil);
3604   return 0;
3605 }
3606
3607 static void
3608 destroy_ic (MInputContext *ic)
3609 {
3610   fini_ic_info (ic);
3611   free (ic->info);
3612 }
3613
3614 static int
3615 check_reload (MInputContext *ic, MSymbol key)
3616 {
3617   MInputMethodInfo *im_info = ic->im->info;
3618   MPlist *plist = resolve_command (im_info->configured_cmds, Mat_reload);
3619
3620   if (! plist)
3621     {
3622       plist = resolve_command (global_info->configured_cmds, Mat_reload);
3623       if (! plist)
3624         return 0;
3625     }
3626   MPLIST_DO (plist, plist)
3627     {
3628       MSymbol this_key, alias;
3629
3630       if (MPLIST_MTEXT_P (plist))
3631         {
3632           MText *mt = MPLIST_MTEXT (plist);
3633           int c = mtext_ref_char (mt, 0);
3634
3635           if (c >= 256)
3636             continue;
3637           this_key = one_char_symbol[c];
3638         }
3639       else
3640         {
3641           MPlist *pl = MPLIST_PLIST (plist);
3642       
3643           this_key = MPLIST_SYMBOL (pl);
3644         }
3645       alias = this_key;
3646       while (alias != key 
3647              && (alias = msymbol_get (alias, M_key_alias))
3648              && alias != this_key);
3649       if (alias == key)
3650         break;
3651     }
3652   if (MPLIST_TAIL_P (plist))
3653     return 0;
3654
3655   MDEBUG_PRINT ("\n  [IM] reload");
3656   re_init_ic (ic, 1);
3657   return 1;
3658 }
3659
3660
3661 /** Handle the input key KEY in the current state and map of IC->info.
3662     If KEY is handled but no text is produced, return 0, otherwise
3663     return 1.
3664
3665     Ignore ARG.  */
3666
3667 static int
3668 filter (MInputContext *ic, MSymbol key, void *arg)
3669 {
3670   MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
3671   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
3672   int i = 0;
3673
3674   if (check_reload (ic, key))
3675     return 0;
3676
3677   if (! ic_info->state)
3678     {
3679       ic_info->key_unhandled = 1;
3680       return 0;
3681     }
3682   mtext_reset (ic->produced);
3683   ic->status_changed = ic->preedit_changed = ic->candidates_changed = 0;
3684   M17N_OBJECT_UNREF (ic_info->preceding_text);
3685   M17N_OBJECT_UNREF (ic_info->following_text);
3686   ic_info->preceding_text = ic_info->following_text = NULL;
3687   MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
3688   ic_info->key_unhandled = 0;
3689
3690   do {
3691     if (handle_key (ic) < 0)
3692       {
3693         /* KEY was not handled.  Delete it from the current key sequence.  */
3694         if (ic_info->used > 0)
3695           {
3696             memmove (ic_info->keys, ic_info->keys + 1,
3697                      sizeof (int) * (ic_info->used - 1));
3698             ic_info->used--;
3699             if (ic_info->state_key_head > 0)
3700               ic_info->state_key_head--;              
3701           }
3702         /* This forces returning 1.  */
3703         ic_info->key_unhandled = 1;
3704         break;
3705       }
3706     if (i++ == 100)
3707       {
3708         mdebug_hook ();
3709         reset_ic (ic, Mnil);
3710         ic_info->key_unhandled = 1;
3711         break;
3712       }
3713     /* Break the loop if all keys were handled.  */
3714   } while (ic_info->key_head < ic_info->used);
3715
3716   /* If the current map is the root of the initial state, we should
3717      produce any preedit text in ic->produced.  */
3718   if (ic_info->map == ((MIMState *) MPLIST_VAL (im_info->states))->map)
3719     preedit_commit (ic);
3720
3721   if (mtext_nchars (ic->produced) > 0)
3722     {
3723       MSymbol lang = msymbol_get (ic->im->language, Mlanguage);
3724
3725       if (mdebug__flag & mdebug_mask)
3726         {
3727           MDEBUG_PRINT (" (produced");
3728           for (i = 0; i < mtext_nchars (ic->produced); i++)
3729             MDEBUG_PRINT1 (" U+%04X", mtext_ref_char (ic->produced, i));
3730           MDEBUG_PRINT (")");
3731         }
3732
3733       if (lang != Mnil)
3734         mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
3735                         Mlanguage, ic->im->language);
3736       if (ic_info->state_key_head > 0)
3737         {
3738           memmove (ic_info->keys, ic_info->keys + ic_info->state_key_head,
3739                    sizeof (int) * (ic_info->used - ic_info->state_key_head));
3740           ic_info->used -= ic_info->state_key_head;
3741           ic_info->key_head -= ic_info->state_key_head;
3742           ic_info->state_key_head = 0;
3743         }
3744     }
3745
3746   if (ic_info->key_unhandled)
3747     {
3748       ic_info->used = 0;
3749       ic_info->key_head = ic_info->state_key_head = 0;
3750     }
3751
3752   return (! ic_info->key_unhandled && mtext_nchars (ic->produced) == 0);
3753 }
3754
3755
3756 /** Return 1 if the last event or key was not handled, otherwise
3757     return 0.
3758
3759     There is no need of looking up because ic->produced should already
3760     contain the produced text (if any).
3761
3762     Ignore KEY.  */
3763
3764 static int
3765 lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
3766 {
3767   mtext_cat (mt, ic->produced);
3768   mtext_reset (ic->produced);
3769   return (((MInputContextInfo *) ic->info)->key_unhandled ? -1 : 0);
3770 }
3771
3772 \f
3773 /* Input method command handler.  */
3774
3775 /* List of all (global and local) commands. 
3776    (LANG:(IM-NAME:(COMMAND ...) ...) ...) ...
3777    COMMAND is CMD-NAME:(mtext:DESCRIPTION plist:KEYSEQ ...))
3778    Global commands are stored as (t (t COMMAND ...))  */
3779
3780 \f
3781 /* Input method variable handler.  */
3782
3783
3784 /* Support functions for mdebug_dump_im.  */
3785
3786 static void
3787 dump_im_map (MPlist *map_list, int indent)
3788 {
3789   char *prefix;
3790   MSymbol key = MPLIST_KEY (map_list);
3791   MIMMap *map = (MIMMap *) MPLIST_VAL (map_list);
3792
3793   prefix = (char *) alloca (indent + 1);
3794   memset (prefix, 32, indent);
3795   prefix[indent] = '\0';
3796
3797   fprintf (stderr, "(\"%s\" ", msymbol_name (key));
3798   if (map->map_actions)
3799     mdebug_dump_plist (map->map_actions, indent + 2);
3800   if (map->submaps)
3801     {
3802       MPLIST_DO (map_list, map->submaps)
3803         {
3804           fprintf (stderr, "\n%s  ", prefix);
3805           dump_im_map (map_list, indent + 2);
3806         }
3807     }
3808   if (map->branch_actions)
3809     {
3810       fprintf (stderr, "\n%s  (branch\n%s    ", prefix, prefix);
3811       mdebug_dump_plist (map->branch_actions, indent + 4);
3812       fprintf (stderr, ")");      
3813     }
3814   fprintf (stderr, ")");
3815 }
3816
3817
3818 static void
3819 dump_im_state (MIMState *state, int indent)
3820 {
3821   char *prefix;
3822   MPlist *map_list;
3823
3824   prefix = (char *) alloca (indent + 1);
3825   memset (prefix, 32, indent);
3826   prefix[indent] = '\0';
3827
3828   fprintf (stderr, "(%s", msymbol_name (state->name));
3829   if (state->map->submaps)
3830     {
3831       MPLIST_DO (map_list, state->map->submaps)
3832         {
3833           fprintf (stderr, "\n%s  ", prefix);
3834           dump_im_map (map_list, indent + 2);
3835         }
3836     }
3837   fprintf (stderr, ")");
3838 }
3839
3840 \f
3841
3842 int
3843 minput__init ()
3844 {
3845   Minput_driver = msymbol ("input-driver");
3846
3847   Minput_preedit_start = msymbol ("input-preedit-start");
3848   Minput_preedit_done = msymbol ("input-preedit-done");
3849   Minput_preedit_draw = msymbol ("input-preedit-draw");
3850   Minput_status_start = msymbol ("input-status-start");
3851   Minput_status_done = msymbol ("input-status-done");
3852   Minput_status_draw = msymbol ("input-status-draw");
3853   Minput_candidates_start = msymbol ("input-candidates-start");
3854   Minput_candidates_done = msymbol ("input-candidates-done");
3855   Minput_candidates_draw = msymbol ("input-candidates-draw");
3856   Minput_set_spot = msymbol ("input-set-spot");
3857   Minput_focus_move = msymbol ("input-focus-move");
3858   Minput_focus_in = msymbol ("input-focus-in");
3859   Minput_focus_out = msymbol ("input-focus-out");
3860   Minput_toggle = msymbol ("input-toggle");
3861   Minput_reset = msymbol ("input-reset");
3862   Minput_get_surrounding_text = msymbol ("input-get-surrounding-text");
3863   Minput_delete_surrounding_text = msymbol ("input-delete-surrounding-text");
3864   Mcustomized = msymbol ("customized");
3865   Mconfigured = msymbol ("configured");
3866   Minherited = msymbol ("inherited");
3867
3868   minput_default_driver.open_im = open_im;
3869   minput_default_driver.close_im = close_im;
3870   minput_default_driver.create_ic = create_ic;
3871   minput_default_driver.destroy_ic = destroy_ic;
3872   minput_default_driver.filter = filter;
3873   minput_default_driver.lookup = lookup;
3874   minput_default_driver.callback_list = mplist ();
3875   mplist_put (minput_default_driver.callback_list, Minput_reset,
3876               (void *) reset_ic);
3877   minput_driver = &minput_default_driver;
3878
3879   fully_initialized = 0;
3880   return 0;
3881 }
3882
3883 void
3884 minput__fini ()
3885 {
3886   if (fully_initialized)
3887     {
3888       free_im_list (im_info_list);
3889       if (im_custom_list)
3890         free_im_list (im_custom_list);
3891       if (im_config_list)
3892         free_im_list (im_config_list);
3893       M17N_OBJECT_UNREF (load_im_info_keys);
3894     }
3895
3896   M17N_OBJECT_UNREF (minput_default_driver.callback_list);
3897   M17N_OBJECT_UNREF (minput_driver->callback_list);
3898
3899 }
3900
3901 int
3902 minput__callback (MInputContext *ic, MSymbol command)
3903 {
3904   MInputCallbackFunc func;
3905
3906   if (! ic->im->driver.callback_list)
3907     return -1;
3908   func = (MInputCallbackFunc) mplist_get (ic->im->driver.callback_list,
3909                                           command);
3910   if (! func)
3911     return -1;
3912   (func) (ic, command);
3913   return 0;
3914 }
3915
3916 MSymbol
3917 minput__char_to_key (int c)
3918 {
3919   if (c < 0 || c >= 0x100)
3920     return Mnil;
3921
3922   return one_char_symbol[c];
3923 }
3924
3925 /*** @} */
3926 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
3927
3928 \f
3929 /* External API */
3930
3931 /*** @addtogroup m17nInputMethod */
3932 /*** @{ */
3933 /*=*/
3934
3935 /***en
3936     @name Variables: Predefined symbols for callback commands.
3937
3938     These are the predefined symbols that are used as the @c COMMAND
3939     argument of callback functions of an input method driver (see
3940     #MInputDriver::callback_list).  
3941
3942     Most of them do not require extra argument nor return any value;
3943     exceptions are these:
3944
3945     Minput_get_surrounding_text: When a callback function assigned for
3946     this command is called, the first element of #MInputContext::plist
3947     has key #Minteger and the value specifies which portion of the
3948     surrounding text should be retrieved.  If the value is positive,
3949     it specifies the number of characters following the current cursor
3950     position.  If the value is negative, the absolute value specifies
3951     the number of characters preceding the current cursor position.
3952
3953     If the surrounding text is currently supported, the callback
3954     function must set the key of this element to #Mtext and the value
3955     to the retrieved M-text.  The length of the M-text may be shorter
3956     than the requested number of characters, if the available text is
3957     not that long.  The length can be zero in the worst case.  Or, the
3958     length may be longer if an application thinks it is more efficient
3959     to return that length.
3960
3961     If the surrounding text is not currently supported, the callback
3962     function should return without changing the first element of
3963     #MInputContext::plist.
3964
3965     Minput_delete_surrounding_text: When a callback function assigned
3966     for this command is called, the first element of
3967     #MInputContext::plist has key #Minteger and the value specifies
3968     which portion of the surrounding text should be deleted in the
3969     same way as the case of Minput_get_surrounding_text.  The callback
3970     function must delete the specified text.  It should not alter
3971     #MInputContext::plist.  */ 
3972 /***ja
3973     @name ÊÑ¿ô¡§ ¥³¡¼¥ë¥Ð¥Ã¥¯¥³¥Þ¥ó¥ÉÍÑÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë.
3974
3975     ÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Î¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Ë¤ª¤¤¤Æ @c COMMAND 
3976     °ú¿ô¤È¤·¤ÆÍѤ¤¤é¤ì¤ëÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë (#MInputDriver::callback_list »²¾È)¡£
3977
3978     ¤Û¤È¤ó¤É¤ÏÄɲäΰú¿ô¤òɬÍפȤ·¤Ê¤¤¤·ÃͤòÊÖ¤µ¤Ê¤¤¤¬¡¢°Ê²¼¤ÏÎã³°¤Ç¤¢¤ë¡£
3979
3980     Minput_get_surrounding_text: ¤³¤Î¥³¥Þ¥ó¥É¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿¥³¡¼¥ë¥Ð¥Ã
3981     ¥¯´Ø¿ô¤¬¸Æ¤Ð¤ì¤¿ºÝ¤Ë¤Ï¡¢ #MInputContext::plist ¤ÎÂè°ìÍ×ÁǤϥ­¡¼¤È¤·
3982     ¤Æ#Minteger ¤ò¤È¤ê¡¢¤½¤ÎÃͤϥµ¥é¥¦¥ó¥Ç¥£¥ó¥°¥Æ¥­¥¹¥È¤Î¤¦¤Á¤É¤ÎÉôʬ
3983     ¤ò¼è¤Ã¤ÆÍè¤ë¤«¤ò»ØÄꤹ¤ë¡£Ãͤ¬Àµ¤Ç¤¢¤ì¤Ð¡¢¸½ºß¤Î¥«¡¼¥½¥ë°ÌÃ֤˳¤¯
3984     ÃͤθĿôʬ¤Îʸ»ú¤ò¼è¤ë¡£Éé¤Ç¤¢¤ì¤Ð¡¢¥«¡¼¥½¥ë°ÌÃÖ¤ËÀè¹Ô¤¹¤ëÃͤÎÀäÂÐ
3985     ÃÍʬ¤Îʸ»ú¤ò¼è¤ë¡£
3986
3987     ¥µ¥é¥¦¥ó¥Ç¥£¥ó¥°¥Æ¥­¥¹¥È¤¬¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤ì¤Ð¡¢¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Ï
3988     ¤³¤ÎÍ×ÁǤΥ­¡¼¤ò #Mtext ¤Ë¡¢Ãͤò¼è¤ê¹þ¤ó¤ÀM-text ¤ËÀßÄꤷ¤Ê¤¯¤Æ¤Ï¤Ê
3989     ¤é¤Ê¤¤¡£¤â¤·¥Æ¥­¥¹¥È¤ÎŤµ¤¬½¼Ê¬¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î M-text ¤ÎŤµ¤ÏÍ×
3990     µá¤µ¤ì¤Æ¤¤¤ëʸ»ú¿ô¤è¤êû¤¯¤ÆÎɤ¤¡£ºÇ°­¤Î¾ì¹ç 0 ¤Ç¤â¤è¤¤¤·¡¢¥¢¥×¥ê¥±¡¼
3991     ¥·¥ç¥ó¦¤ÇɬÍפǸúΨŪ¤À¤È»×¤¨¤ÐŤ¯¤Æ¤âÎɤ¤¡£
3992
3993     ¥µ¥é¥¦¥ó¥Ç¥£¥ó¥°¥Æ¥­¥¹¥È¤¬¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¡¢¥³¡¼¥ë¥Ð¥Ã¥¯´Ø
3994     ¿ô¤Ï #MInputContext::plist ¤ÎÂè°ìÍ×ÁǤòÊѲ½¤µ¤»¤ë¤³¤È¤Ê¤¯ÊÖ¤µ¤Ê¤¯¤Æ
3995     ¤Ï¤Ê¤é¤Ê¤¤¡£
3996
3997     Minput_delete_surrounding_text: ¤³¤Î¥³¥Þ¥ó¥É¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿¥³¡¼¥ë
3998     ¥Ð¥Ã¥¯´Ø¿ô¤¬¸Æ¤Ð¤ì¤¿ºÝ¤Ë¤Ï¡¢#MInputContext::plist ¤ÎÂè°ìÍ×ÁǤϡ¢¥­¡¼
3999     ¤È¤·¤Æ#Minteger ¤ò¤È¤ê¡¢ÃͤϺï½ü¤¹¤ë¤Ù¤­¥µ¥é¥¦¥ó¥Ç¥£¥ó¥°¥Æ¥­¥¹¥È¤ò
4000     Minput_get_surrounding_text ¤ÈƱÍͤΤä¤êÊý¤Ç»ØÄꤹ¤ë¡£¥³¡¼¥ë¥Ð¥Ã¥¯
4001     ´Ø¿ô¤Ï»ØÄꤵ¤ì¤¿¥Æ¥­¥¹¥È¤òºï½ü¤·¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£¤Þ¤¿
4002     #MInputContext::plist ¤òÊѤ¨¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£  */ 
4003 /*** @{ */ 
4004 /*=*/
4005
4006 MSymbol Minput_preedit_start;
4007 MSymbol Minput_preedit_done;
4008 MSymbol Minput_preedit_draw;
4009 MSymbol Minput_status_start;
4010 MSymbol Minput_status_done;
4011 MSymbol Minput_status_draw;
4012 MSymbol Minput_candidates_start;
4013 MSymbol Minput_candidates_done;
4014 MSymbol Minput_candidates_draw;
4015 MSymbol Minput_set_spot;
4016 MSymbol Minput_toggle;
4017 MSymbol Minput_reset;
4018 MSymbol Minput_get_surrounding_text;
4019 MSymbol Minput_delete_surrounding_text;
4020 /*** @} */
4021
4022 /*=*/
4023
4024 /***en
4025     @name Variables: Predefined symbols for special input events.
4026
4027     These are the predefined symbols that are used as the @c KEY
4028     argument of minput_filter ().  */ 
4029 /***ja
4030     @name ÊÑ¿ô: ÆÃÊ̤ÊÆþÎÏ¥¤¥Ù¥ó¥ÈÍÑÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë.
4031
4032     minput_filter () ¤Î @c KEY °ú¿ô¤È¤·¤ÆÍѤ¤¤é¤ì¤ëÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë¡£  */ 
4033
4034 /*** @{ */ 
4035 /*=*/
4036
4037 MSymbol Minput_focus_out;
4038 MSymbol Minput_focus_in;
4039 MSymbol Minput_focus_move;
4040
4041 /*** @} */
4042
4043 /*=*/
4044 /***en
4045     @name Variables: Predefined symbols used in input method information.
4046
4047     These are the predefined symbols describing status of input method
4048     command and variable, and are used in a return value of
4049     minput_get_command () and minput_get_variable ().  */
4050 /***ja
4051     @name ÊÑ¿ô: ÆþÎϥ᥽¥Ã¥É¾ðÊóÍÑÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë.
4052
4053     ÆþÎϥ᥽¥Ã¥É¤Î¥³¥Þ¥ó¥É¤äÊÑ¿ô¤Î¾õÂÖ¤òɽ¤·¡¢minput_get_command () ¤È
4054     minput_get_variable () ¤ÎÌá¤êÃͤȤ·¤ÆÍѤ¤¤é¤ì¤ëÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë¡£  */
4055 /*** @{ */ 
4056 /*=*/
4057 MSymbol Minherited;
4058 MSymbol Mcustomized;
4059 MSymbol Mconfigured;
4060 /*** @} */ 
4061
4062 /*=*/
4063
4064 /***en
4065     @brief The default driver for internal input methods.
4066
4067     The variable #minput_default_driver is the default driver for
4068     internal input methods.
4069
4070     The member MInputDriver::open_im () searches the m17n database for
4071     an input method that matches the tag \< #Minput_method, $LANGUAGE,
4072     $NAME\> and loads it.
4073
4074     The member MInputDriver::callback_list () is @c NULL.  Thus, it is
4075     programmers responsibility to set it to a plist of proper callback
4076     functions.  Otherwise, no feedback information (e.g. preedit text)
4077     can be shown to users.
4078
4079     The macro M17N_INIT () sets the variable #minput_driver to the
4080     pointer to this driver so that all internal input methods use it.
4081
4082     Therefore, unless @c minput_driver is set differently, the driver
4083     dependent arguments $ARG of the functions whose name begins with
4084     "minput_" are all ignored.  */
4085 /***ja
4086     @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥǥե©¥ë¥È¥É¥é¥¤¥Ð.
4087
4088     ÊÑ¿ô #minput_default_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѤΥǥե©¥ë¥È¤Î¥É¥é¥¤¥Ð¤òɽ¤¹¡£
4089
4090     ¥á¥ó¥Ð MInputDriver::open_im () ¤Ï m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹Ã椫¤é¥¿¥° 
4091     \< #Minput_method, $LANGUAGE, $NAME\> 
4092     ¤Ë¹çÃפ¹¤ëÆþÎϥ᥽¥Ã¥É¤òõ¤·¡¢¤½¤ì¤ò¥í¡¼¥É¤¹¤ë¡£
4093
4094     ¥á¥ó¥Ð MInputDriver::callback_list () ¤Ï @c NULL ¤Ç¤¢¤ê¡¢
4095     ¤·¤¿¤¬¤Ã¤Æ¡¢¥×¥í¥°¥é¥Þ¦¤ÇÀÕǤ¤ò»ý¤Ã¤Æ Å¬Àڤʥ³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Î plist
4096     ¤ËÀßÄꤷ¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¤µ¤â¤Ê¤¤¤È¡¢preedit 
4097     ¥Æ¥­¥¹¥È¤Ê¤É¤Î¥Õ¥£¡¼¥É¥Ð¥Ã¥¯¾ðÊ󤬥桼¥¶¤Ëɽ¼¨¤µ¤ì¤Ê¤¤¡£
4098
4099     ¥Þ¥¯¥í M17N_INIT () ¤ÏÊÑ¿ô #minput_driver 
4100     ¤ò¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤ËÀßÄꤷ¡¢Á´¤Æ¤ÎÆâÉôÆþÎϥ᥽¥Ã¥É¤¬¤³¤Î¥É¥é¥¤¥Ð¤ò»È¤¦¤è¤¦¤Ë¤¹¤ë¡£
4101
4102     ¤·¤¿¤¬¤Ã¤Æ¡¢@c minput_driver ¤¬¥Ç¥Õ¥©¥ë¥ÈÃͤΤޤޤǤ¢¤ì¤Ð¡¢minput_ 
4103     ¤Ç»Ï¤Þ¤ë´Ø¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô $ARG ¤Ï¤¹¤Ù¤Æ̵»ë¤µ¤ì¤ë¡£  */
4104
4105 MInputDriver minput_default_driver;
4106 /*=*/
4107
4108 /***en
4109     @brief The driver for internal input methods.
4110
4111     The variable #minput_driver is a pointer to the input method
4112     driver that is used by internal input methods.  The macro
4113     M17N_INIT () initializes it to a pointer to #minput_default_driver
4114     if <m17n<EM></EM>.h> is included.  */ 
4115 /***ja
4116     @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥɥ饤¥Ð.
4117
4118     ÊÑ¿ô #minput_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤Æ»ÈÍѤµ¤ì¤Æ¤¤¤ëÆþÎÏ¥á
4119     ¥½¥Ã¥É¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£¥Þ¥¯¥í M17N_INIT () ¤Ï¤³¤Î¥Ý¥¤¥ó
4120     ¥¿¤ò#minput_default_driver (<m17n<EM></EM>.h> ¤¬ include ¤µ¤ì¤Æ¤¤¤ë
4121     »þ) ¤Ë½é´ü²½¤¹¤ë¡£  */ 
4122
4123 MInputDriver *minput_driver;
4124
4125 MSymbol Minput_driver;
4126
4127 /*=*/
4128
4129 /***en
4130     @name Functions
4131 */
4132 /***ja
4133     @name ´Ø¿ô
4134 */
4135 /*** @{ */
4136
4137 /*=*/
4138
4139 /***en
4140     @brief Open an input method.
4141
4142     The minput_open_im () function opens an input method whose
4143     language and name match $LANGUAGE and $NAME, and returns a pointer
4144     to the input method object newly allocated.
4145
4146     This function at first decides a driver for the input method as
4147     described below.
4148
4149     If $LANGUAGE is not #Mnil, the driver pointed by the variable
4150     #minput_driver is used.
4151
4152     If $LANGUAGE is #Mnil and $NAME has the property #Minput_driver, the
4153     driver pointed to by the property value is used to open the input
4154     method.  If $NAME has no such a property, @c NULL is returned.
4155
4156     Then, the member MInputDriver::open_im () of the driver is
4157     called.  
4158
4159     $ARG is set in the member @c arg of the structure MInputMethod so
4160     that the driver can refer to it.  */
4161 /***ja
4162     @brief ÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë.
4163
4164     ´Ø¿ô minput_open_im () ¤Ï¸À¸ì $LANGUAGE ¤È̾Á° $NAME 
4165     ¤Ë¹çÃפ¹¤ëÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤·¡¢¿·¤¿¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿ÆþÎϥ᥽¥Ã¥É¥ª¥Ö¥¸¥§¥¯¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
4166     
4167     ¤³¤Î´Ø¿ô¤Ï¡¢¤Þ¤ºÆþÎϥ᥽¥Ã¥ÉÍѤΥɥ饤¥Ð¤ò°Ê²¼¤Î¤è¤¦¤Ë¤·¤Æ·èÄꤹ¤ë¡£
4168
4169     $LANGUAGE ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢ÊÑ¿ô #minput_driver 
4170     ¤Ç»Ø¤µ¤ì¤Æ¤¤¤ë¥É¥é¥¤¥Ð¤òÍѤ¤¤ë¡£
4171
4172     $LANGUAGE ¤¬ #Mnil ¤Ç¤¢¤ê¡¢$NAME ¤¬ #Minput_driver
4173     ¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä¾ì¹ç¤Ë¤Ï¡¢¤½¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤǻؤµ¤ì¤Æ¤¤¤ëÆþÎϥɥ饤¥Ð¤òÍѤ¤¤ÆÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë¡£
4174     $NAME ¤Ë¤½¤Î¤è¤¦¤Ê¥×¥í¥Ñ¥Æ¥£¤¬Ìµ¤«¤Ã¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
4175
4176     ¼¡¤¤¤Ç¡¢¥É¥é¥¤¥Ð¤Î¥á¥ó¥Ð MInputDriver::open_im () ¤¬¸Æ¤Ð¤ì¤ë¡£
4177
4178     $ARG ¤Ï¹½Â¤ÂΠMInputMethod ¤Î¥á¥ó¥Ð @c arg ¤ËÀßÄꤵ¤ì¡¢¥É¥é¥¤¥Ð¤«¤é»²¾È¤Ç¤­¤ë¡£
4179
4180     @latexonly \IPAlabel{minput_open} @endlatexonly
4181
4182 */
4183
4184 MInputMethod *
4185 minput_open_im (MSymbol language, MSymbol name, void *arg)
4186 {
4187   MInputMethod *im;
4188   MInputDriver *driver;
4189
4190   MINPUT__INIT ();
4191
4192   MDEBUG_PRINT2 ("  [IM] opening (%s %s) ... ",
4193                  msymbol_name (language), msymbol_name (name));
4194   if (language)
4195     driver = minput_driver;
4196   else
4197     {
4198       driver = (MInputDriver *) msymbol_get (name, Minput_driver);
4199       if (! driver)
4200         MERROR (MERROR_IM, NULL);
4201     }
4202
4203   MSTRUCT_CALLOC (im, MERROR_IM);
4204   im->language = language;
4205   im->name = name;
4206   im->arg = arg;
4207   im->driver = *driver;
4208   if ((*im->driver.open_im) (im) < 0)
4209     {
4210       MDEBUG_PRINT (" failed\n");
4211       free (im);
4212       return NULL;
4213     }
4214   MDEBUG_PRINT (" ok\n");
4215   return im;
4216 }
4217
4218 /*=*/
4219
4220 /***en
4221     @brief Close an input method.
4222
4223     The minput_close_im () function closes the input method $IM, which
4224     must have been created by minput_open_im ().  */
4225
4226 /***ja
4227     @brief ÆþÎϥ᥽¥Ã¥É¤ò¥¯¥í¡¼¥º¤¹¤ë.
4228
4229     ´Ø¿ô minput_close_im () ¤Ï¡¢ÆþÎϥ᥽¥Ã¥É $IM ¤ò¥¯¥í¡¼¥º¤¹¤ë¡£
4230     ¤³¤ÎÆþÎϥ᥽¥Ã¥É $IM ¤Ï minput_open_im () ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£  */
4231
4232 void
4233 minput_close_im (MInputMethod *im)
4234 {
4235   MDEBUG_PRINT2 ("  [IM] closing (%s %s) ... ",
4236                  msymbol_name (im->name), msymbol_name (im->language));
4237   (*im->driver.close_im) (im);
4238   free (im);
4239   MDEBUG_PRINT (" done\n");
4240 }
4241
4242 /*=*/
4243
4244 /***en
4245     @brief Create an input context.
4246
4247     The minput_create_ic () function creates an input context object
4248     associated with input method $IM, and calls callback functions
4249     corresponding to #Minput_preedit_start, #Minput_status_start, and
4250     #Minput_status_draw in this order.
4251
4252     @return
4253     If an input context is successfully created, minput_create_ic ()
4254     returns a pointer to it.  Otherwise it returns @c NULL.  */
4255
4256 /***ja
4257     @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÀ¸À®¤¹¤ë.
4258
4259     ´Ø¿ô minput_create_ic () ¤ÏÆþÎϥ᥽¥Ã¥É $IM
4260     ¤ËÂбþ¤¹¤ëÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤·¡¢
4261     #Minput_preedit_start, #Minput_status_start, #Minput_status_draw
4262     ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¤³¤Î½ç¤Ë¸Æ¤Ö¡£
4263
4264     @return
4265     ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤¬À¸À®¤µ¤ì¤¿¾ì¹ç¡¢minput_create_ic () 
4266     ¤Ï¤½¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¼ºÇÔ¤·¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
4267       */
4268
4269 MInputContext *
4270 minput_create_ic (MInputMethod *im, void *arg)
4271 {
4272   MInputContext *ic;
4273
4274   MDEBUG_PRINT2 ("  [IM] creating context (%s %s) ... ",
4275                  msymbol_name (im->name), msymbol_name (im->language));
4276   MSTRUCT_CALLOC (ic, MERROR_IM);
4277   ic->im = im;
4278   ic->arg = arg;
4279   ic->preedit = mtext ();
4280   ic->candidate_list = NULL;
4281   ic->produced = mtext ();
4282   ic->spot.x = ic->spot.y = 0;
4283   ic->active = 1;
4284   ic->plist = mplist ();
4285   if ((*im->driver.create_ic) (ic) < 0)
4286     {
4287       MDEBUG_PRINT (" failed\n");
4288       M17N_OBJECT_UNREF (ic->preedit);
4289       M17N_OBJECT_UNREF (ic->produced);
4290       M17N_OBJECT_UNREF (ic->plist);
4291       free (ic);
4292       return NULL;
4293     };
4294
4295   if (im->driver.callback_list)
4296     {
4297       minput__callback (ic, Minput_preedit_start);
4298       minput__callback (ic, Minput_status_start);
4299       minput__callback (ic, Minput_status_draw);
4300     }
4301
4302   MDEBUG_PRINT (" ok\n");
4303   return ic;
4304 }
4305
4306 /*=*/
4307
4308 /***en
4309     @brief Destroy an input context.
4310
4311     The minput_destroy_ic () function destroys the input context $IC,
4312     which must have been created by minput_create_ic ().  It calls
4313     callback functions corresponding to #Minput_preedit_done,
4314     #Minput_status_done, and #Minput_candidates_done in this order.  */
4315
4316 /***ja
4317     @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÇ˲õ¤¹¤ë.
4318
4319     ´Ø¿ô minput_destroy_ic () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤òÇ˲õ¤¹¤ë¡£
4320     ¤³¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ï minput_create_ic () 
4321     ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£¤³¤Î´Ø¿ô¤Ï 
4322     #Minput_preedit_done, #Minput_status_done, #Minput_candidates_done 
4323     ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¤³¤Î½ç¤Ë¸Æ¤Ö¡£
4324   */
4325
4326 void
4327 minput_destroy_ic (MInputContext *ic)
4328 {
4329   MDEBUG_PRINT2 ("  [IM] destroying context (%s %s) ... ",
4330                  msymbol_name (ic->im->name), msymbol_name (ic->im->language));
4331   if (ic->im->driver.callback_list)
4332     {
4333       minput__callback (ic, Minput_preedit_done);
4334       minput__callback (ic, Minput_status_done);
4335       minput__callback (ic, Minput_candidates_done);
4336     }
4337   (*ic->im->driver.destroy_ic) (ic);
4338   M17N_OBJECT_UNREF (ic->preedit);
4339   M17N_OBJECT_UNREF (ic->produced);
4340   M17N_OBJECT_UNREF (ic->plist);
4341   MDEBUG_PRINT (" done\n");
4342   free (ic);
4343 }
4344
4345 /*=*/
4346
4347 /***en
4348     @brief Filter an input key.
4349
4350     The minput_filter () function filters input key $KEY according to
4351     input context $IC, and calls callback functions corresponding to
4352     #Minput_preedit_draw, #Minput_status_draw, and
4353     #Minput_candidates_draw if the preedit text, the status, and the
4354     current candidate are changed respectively.
4355
4356     To make the input method commit the current preedit text (if any)
4357     and shift to the initial state, call this function with #Mnil as
4358     $KEY.
4359
4360     To inform the input method about the focus-out event, call this
4361     function with #Minput_focus_out as $KEY.
4362
4363     To inform the input method about the focus-in event, call this
4364     function with #Minput_focus_in as $KEY.
4365
4366     To inform the input method about the focus-move event (i.e. input
4367     spot change within the same input context), call this function
4368     with #Minput_focus_move as $KEY.
4369
4370     @return
4371     If $KEY is filtered out, this function returns 1.  In that case,
4372     the caller should discard the key.  Otherwise, it returns 0, and
4373     the caller should handle the key, for instance, by calling the
4374     function minput_lookup () with the same key.  */
4375
4376 /***ja
4377     @brief ÆþÎÏ¥­¡¼¤ò¥Õ¥£¥ë¥¿¤¹¤ë.
4378
4379     ´Ø¿ô minput_filter () ¤ÏÆþÎÏ¥­¡¼ $KEY ¤òÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC 
4380     ¤Ë±þ¤¸¤Æ¥Õ¥£¥ë¥¿¤·¡¢preedit ¥Æ¥­¥¹¥È¡¢¥¹¥Æ¡¼¥¿¥¹¡¢¸½»þÅÀ¤Ç¤Î¸õÊ䤬ÊѲ½¤·¤¿»þÅÀ¤Ç¡¢¤½¤ì¤¾¤ì
4381     #Minput_preedit_draw, #Minput_status_draw,
4382     #Minput_candidates_draw ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¸Æ¤Ö¡£
4383
4384     @return 
4385     $KEY ¤¬¥Õ¥£¥ë¥¿¤µ¤ì¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 1 ¤òÊÖ¤¹¡£
4386     ¤³¤Î¾ì¹ç¸Æ¤Ó½Ð¤·Â¦¤Ï¤³¤Î¥­¡¼¤ò¼Î¤Æ¤ë¤Ù¤­¤Ç¤¢¤ë¡£
4387     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0 ¤òÊÖ¤·¡¢¸Æ¤Ó½Ð¤·Â¦¤Ï¡¢¤¿¤È¤¨¤ÐƱ¤¸¥­¡¼¤Ç´Ø¿ô minput_lookup ()
4388     ¤ò¸Æ¤Ö¤Ê¤É¤·¤Æ¡¢¤³¤Î¥­¡¼¤ò½èÍý¤¹¤ë¡£
4389
4390     @latexonly \IPAlabel{minput_filter} @endlatexonly
4391 */
4392
4393 int
4394 minput_filter (MInputContext *ic, MSymbol key, void *arg)
4395 {
4396   int ret;
4397
4398   if (! ic
4399       || ! ic->active)
4400     return 0;
4401   ret = (*ic->im->driver.filter) (ic, key, arg);
4402
4403   if (ic->im->driver.callback_list)
4404     {
4405       if (ic->preedit_changed)
4406         minput__callback (ic, Minput_preedit_draw);
4407       if (ic->status_changed)
4408         minput__callback (ic, Minput_status_draw);
4409       if (ic->candidates_changed)
4410         minput__callback (ic, Minput_candidates_draw);
4411     }
4412
4413   return ret;
4414 }
4415
4416 /*=*/
4417
4418 /***en
4419     @brief Look up a text produced in the input context.
4420
4421     The minput_lookup () function looks up a text in the input context
4422     $IC.  $KEY must be identical to the one that was used in the previous call of
4423     minput_filter ().
4424
4425     If a text was produced by the input method, it is concatenated
4426     to M-text $MT.
4427
4428     This function calls #MInputDriver::lookup .
4429
4430     @return
4431     If $KEY was correctly handled by the input method, this function
4432     returns 0.  Otherwise, it returns -1, even though some text
4433     might be produced in $MT.  */
4434
4435 /***ja
4436     @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥ÈÃæ¤Î¥Æ¥­¥¹¥È¤òõ¤¹.
4437
4438     ´Ø¿ô minput_lookup () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC Ãæ¤Î¥Æ¥­¥¹¥È¤òõ¤¹¡£
4439     $KEY ¤Ï´Ø¿ô minput_filter () ¤Ø¤ÎľÁ°¤Î¸Æ¤Ó½Ð¤·¤ËÍѤ¤¤é¤ì¤¿¤â¤Î¤ÈƱ¤¸¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
4440
4441     ¥Æ¥­¥¹¥È¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆÀ¸À®¤µ¤ì¤Æ¤¤¤ì¤Ð¡¢¥Æ¥­¥¹¥È¤Ï M-text
4442     $MT ¤ËÏ¢·ë¤µ¤ì¤ë¡£
4443
4444     ¤³¤Î´Ø¿ô¤Ï¡¢#MInputDriver::lookup ¤ò¸Æ¤Ö¡£
4445
4446     @return 
4447     $KEY ¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆŬÀڤ˽èÍý¤Ç¤­¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 0 ¤òÊÖ¤¹¡£
4448     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£
4449     ¤³¤Î¾ì¹ç¤Ç¤â $MT ¤Ë²¿¤é¤«¤Î¥Æ¥­¥¹¥È¤¬À¸À®¤µ¤ì¤Æ¤¤¤ë¤³¤È¤¬¤¢¤ë¡£
4450
4451     @latexonly \IPAlabel{minput_lookup} @endlatexonly  */
4452
4453 int
4454 minput_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
4455 {
4456   return (ic ? (*ic->im->driver.lookup) (ic, key, arg, mt) : -1);
4457 }
4458 /*=*/
4459
4460 /***en
4461     @brief Set the spot of the input context.
4462
4463     The minput_set_spot () function sets the spot of input context $IC
4464     to coordinate ($X, $Y ) with the height specified by $ASCENT and $DESCENT .
4465     The semantics of these values depends on the input method driver.
4466
4467     For instance, a driver designed to work in a CUI environment may
4468     use $X and $Y as the column- and row numbers, and may ignore $ASCENT and
4469     $DESCENT .  A driver designed to work in a window system may
4470     interpret $X and $Y as the pixel offsets relative to the origin of the
4471     client window, and may interpret $ASCENT and $DESCENT as the ascent- and
4472     descent pixels of the line at ($X . $Y ).
4473
4474     $FONTSIZE specifies the fontsize of preedit text in 1/10 point.
4475
4476     $MT and $POS are the M-text and the character position at the spot.
4477     $MT may be @c NULL, in which case, the input method cannot get
4478     information about the text around the spot.  */
4479
4480 /***ja
4481     @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Î¥¹¥Ý¥Ã¥È¤òÀßÄꤹ¤ë.
4482
4483     ´Ø¿ô minput_set_spot () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤Î¥¹¥Ý¥Ã¥È¤ò¡¢ºÂɸ ($X, $Y )
4484     ¤Î°ÌÃ֤ˠ¡¢¹â¤µ $ASCENT¡¢ $DESCENT 
4485     ¤ÇÀßÄꤹ¤ë¡£ ¤³¤ì¤é¤ÎÃͤΰÕÌ£¤ÏÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë¡£
4486
4487     ¤¿¤È¤¨¤Ð CUI ´Ä¶­¤ÇÆ°ºî¤¹¤ë¥É¥é¥¤¥Ð¤Ï $X ¤È $Y 
4488     ¤ò¤½¤ì¤¾¤ìÎó¤È¹Ô¤ÎÈÖ¹æ¤È¤·¤ÆÍѤ¤¡¢$ASCENT ¤È $DESCENT 
4489     ¤ò̵»ë¤¹¤ë¤«¤â¤·¤ì¤Ê¤¤¡£ ¤Þ¤¿¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥àÍѤΥɥ饤¥Ð¤Ï
4490     $X ¤È $Y ¤ò¥¯¥é¥¤¥¢¥ó¥È¥¦¥£¥ó¥É¥¦¤Î¸¶ÅÀ¤«¤é¤Î¥ª¥Õ¥»¥Ã¥È¤ò¥Ô¥¯¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¤¡¢
4491     $ASCENT ¤È $DESCENT ¤ò ($X . $Y )
4492     ¤ÎÎó¤Î¥¢¥»¥ó¥È¤È¥Ç¥£¥»¥ó¥È¤ò¥Ô¥¯¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¦¤«¤â¤·¤ì¤Ê¤¤¡£
4493
4494     $FONTSIZE ¤Ë¤Ï preedit ¥Æ¥­¥¹¥È¤Î¥Õ¥©¥ó¥È¥µ¥¤¥º¤ò 1/10 ¥Ý¥¤¥ó¥Èñ°Ì¤Ç»ØÄꤹ¤ë¡£
4495
4496     $MT ¤È $POS ¤Ï¤½¤Î¥¹¥Ý¥Ã¥È¤Î M-text ¤Èʸ»ú°ÌÃ֤Ǥ¢¤ë¡£$MT ¤Ï @c
4497     NULL ¤Ç¤â¤è¤¯¡¢¤½¤Î¾ì¹ç¤Ë¤ÏÆþÎϥ᥽¥Ã¥É¤Ï¥¹¥Ý¥Ã¥È¼þÊդΥƥ­¥¹¥È¤Ë´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë¤³¤È¤¬¤Ç¤­¤Ê¤¤¡£
4498     */
4499
4500 void
4501 minput_set_spot (MInputContext *ic, int x, int y,
4502                  int ascent, int descent, int fontsize,
4503                  MText *mt, int pos)
4504 {
4505   ic->spot.x = x;
4506   ic->spot.y = y;
4507   ic->spot.ascent = ascent;
4508   ic->spot.descent = descent;
4509   ic->spot.fontsize = fontsize;
4510   ic->spot.mt = mt;
4511   ic->spot.pos = pos;
4512   if (ic->im->driver.callback_list)
4513     minput__callback (ic, Minput_set_spot);
4514 }
4515 /*=*/
4516
4517 /***en
4518     @brief Toggle input method.
4519
4520     The minput_toggle () function toggles the input method associated
4521     with input context $IC.  */
4522 /***ja
4523     @brief ÆþÎϥ᥽¥Ã¥É¤òÀÚÂؤ¨¤ë.
4524
4525     ´Ø¿ô minput_toggle () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC 
4526     ¤ËÂбþÉÕ¤±¤é¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ò¥È¥°¥ë¤¹¤ë¡£
4527     */
4528
4529 void
4530 minput_toggle (MInputContext *ic)
4531 {
4532   if (ic->im->driver.callback_list)
4533     minput__callback (ic, Minput_toggle);
4534   ic->active = ! ic->active;
4535 }
4536
4537 /*=*/
4538
4539 /***en
4540     @brief Reset an input context.
4541
4542     The minput_reset_ic () function resets input context $IC by
4543     calling a callback function corresponding to #Minput_reset.  It
4544     resets the status of $IC to its initial one.  As the
4545     current preedit text is deleted without commitment, if necessary,
4546     call minput_filter () with the arg @r key #Mnil to force the input
4547     method to commit the preedit in advance.  */
4548
4549 /***ja
4550     @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤ò¥ê¥»¥Ã¥È¤¹¤ë.
4551
4552     ´Ø¿ô minput_reset_ic () ¤Ï #Minput_reset ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô
4553     ¤ò¸Æ¤Ö¤³¤È¤Ë¤è¤Ã¤ÆÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤ò¥ê¥»¥Ã¥È¤¹¤ë¡£¥ê¥»¥Ã¥È¤È¤Ï¡¢
4554     ¼ÂºÝ¤Ë¤ÏÆþÎϥ᥽¥Ã¥É¤ò½é´ü¾õÂ֤˰ܤ¹¤³¤È¤Ç¤¢¤ë¡£¸½ºßÆþÎÏÃæ¤Î¥Æ¥­¥¹
4555     ¥È¤Ï¥³¥ß¥Ã¥È¤µ¤ì¤ë¤³¤È¤Ê¤¯ºï½ü¤µ¤ì¤ë¤Î¤Ç¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é
4556     ¥à¤Ï¡¢É¬Íפʤé¤Ðͽ¤á minput_filter () ¤ò°ú¿ô @r key #Mnil ¤Ç¸Æ¤ó¤Ç
4557     ¶¯À©Åª¤Ë¥×¥ê¥¨¥Ç¥£¥Ã¥È¥Æ¥­¥¹¥È¤ò¥³¥ß¥Ã¥È¤µ¤»¤ë¤³¤È¡£  */
4558
4559 void
4560 minput_reset_ic (MInputContext *ic)
4561 {
4562   if (ic->im->driver.callback_list)
4563     minput__callback (ic, Minput_reset);
4564 }
4565
4566 /*=*/
4567
4568 /***en
4569     @brief Get title and icon filename of an input method.
4570
4571     The minput_get_title_icon () function returns a plist containing a
4572     title and icon filename (if any) of an input method specified by
4573     $LANGUAGE and $NAME.
4574
4575     The first element of the plist has key #Mtext and the value is an
4576     M-text of the title for identifying the input method.  The second
4577     element (if any) has key #Mtext and the value is an M-text of the
4578     icon image (absolute) filename for the same purpose.
4579
4580     @return
4581     If there exists a specified input method and it defines an title,
4582     a plist is returned.  Otherwise, NULL is returned.  The caller
4583     must free the plist by m17n_object_unref ().  */
4584 /***ja
4585     @brief ÆþÎϥ᥽¥Ã¥É¤Î¥¿¥¤¥È¥ë¤È¥¢¥¤¥³¥óÍÑ¥Õ¥¡¥¤¥ë̾¤òÆÀ¤ë.
4586
4587     ´Ø¿ô minput_get_title_icon () ¤Ï¡¢ $LANGUAGE ¤È $NAME ¤Ç»ØÄꤵ¤ì¤ë
4588     ÆþÎϥ᥽¥Ã¥É¤Î¥¿¥¤¥È¥ë¤È¡Ê¤¢¤ì¤Ð¡Ë¥¢¥¤¥³¥óÍÑ¥Õ¥¡¥¤¥ë¤ò´Þ¤à plist ¤ò
4589     ÊÖ¤¹¡£
4590
4591     plist ¤ÎÂè°ìÍ×ÁǤϡ¢#Mtext ¤ò¥­¡¼¤Ë»ý¤Á¡¢ÃͤÏÆþÎϥ᥽¥Ã¥É¤ò¼±Ê̤¹¤ë
4592     ¥¿¥¤¥È¥ë¤òɽ¤¹ M-text ¤Ç¤¢¤ë¡£ÂèÆóÍ×ÁǤ¬¤¢¤ì¤Ð¡¢¥­¡¼¤Ï #Mtext ¤Ç¤¢
4593     ¤ê¡¢Ãͤϼ±ÊÌÍÑ¥¢¥¤¥³¥ó²èÁü¤ÎÀäÂÐ¥Õ¥¡¥¤¥ë¥Í¡¼¥à¤òɽ¤¹ M-text ¤Ç¤¢¤ë¡£
4594
4595     @return
4596     »ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤¬Â¸ºß¤·¡¢¥¿¥¤¥È¥ë¤¬ÄêµÁ¤µ¤ì¤Æ¤¤¤ì¤Ð
4597      plist ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð NULL ¤òÊÖ¤¹¡£¸Æ½Ð¦¤Ï
4598      ´Ø¿ô m17n_object_unref () ¤òÍѤ¤¤Æ plist ¤ò²òÊü¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£  */
4599
4600 MPlist *
4601 minput_get_title_icon (MSymbol language, MSymbol name)
4602 {
4603   MInputMethodInfo *im_info;
4604   MPlist *plist;
4605   char *file = NULL;
4606   MText *mt;
4607
4608   MINPUT__INIT ();
4609
4610   im_info = get_im_info (language, name, Mnil, Mtitle);
4611   if (! im_info || !im_info->title)
4612     return NULL;
4613   mt = mtext_get_prop (im_info->title, 0, Mtext);
4614   if (mt)
4615     file = mdatabase__find_file ((char *) MTEXT_DATA (mt));
4616   else
4617     {
4618       char *buf = alloca (MSYMBOL_NAMELEN (language) + MSYMBOL_NAMELEN (name)
4619                           + 12);
4620
4621       sprintf (buf, "icons/%s-%s.png", (char *) MSYMBOL_NAME (language), 
4622                (char *) MSYMBOL_NAME (name));
4623       file = mdatabase__find_file (buf);
4624       if (! file && language == Mt)
4625         {
4626           sprintf (buf, "icons/%s.png", (char *) MSYMBOL_NAME (name));
4627           file = mdatabase__find_file (buf);
4628         }
4629     }
4630
4631   plist = mplist ();
4632   mplist_add (plist, Mtext, im_info->title);
4633   if (file)
4634     {
4635       mt = mtext__from_data (file, strlen (file), MTEXT_FORMAT_UTF_8, 1);
4636       free (file);
4637       mplist_add (plist, Mtext, mt);
4638       M17N_OBJECT_UNREF (mt);
4639     }
4640   return plist;
4641 }
4642
4643 /*=*/
4644
4645 /***en
4646     @brief Get description text of an input method.
4647
4648     The minput_get_description () function returns an M-text that
4649     describes the input method specified by $LANGUAGE and $NAME.
4650
4651     @return
4652     If the specified input method has a description text, a pointer to
4653     #MText is returned.  The caller has to free it by m17n_object_unref ().
4654     If the input method does not have a description text, @c NULL is
4655     returned.  */
4656 /***ja
4657     @brief ÆþÎϥ᥽¥Ã¥É¤ÎÀâÌÀ¥Æ¥­¥¹¥È¤òÆÀ¤ë.
4658
4659     ´Ø¿ô minput_get_description () ¤Ï¡¢$LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ»ØÄê
4660     ¤µ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤òÀâÌÀ¤¹¤ë M-text ¤òÊÖ¤¹¡£
4661
4662     @return »ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤¬ÀâÌÀ¤¹¤ë¥Æ¥­¥¹¥È¤ò»ý¤Ã¤Æ¤¤¤ì¤Ð¡¢
4663     #MText ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¸Æ¤Ó½Ð¤·Â¦¤Ï¡¢¤½¤ì¤ò m17n_object_unref
4664     () ¤òÍѤ¤¤Æ²òÊü¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ÆþÎϥ᥽¥Ã¥É¤ËÀâÌÀ¥Æ¥­¥¹¥È¤¬Ìµ¤±
4665     ¤ì¤Ð@c NULL ¤òÊÖ¤¹¡£ */
4666
4667 MText *
4668 minput_get_description (MSymbol language, MSymbol name)
4669 {
4670   MInputMethodInfo *im_info;
4671   MSymbol extra;
4672
4673   MINPUT__INIT ();
4674
4675   if (name != Mnil)
4676     extra = Mnil;
4677   else
4678     extra = language, language = Mt;
4679
4680   im_info = get_im_info (language, name, extra, Mdescription);
4681   if (! im_info || ! im_info->description)
4682     return NULL;
4683   M17N_OBJECT_REF (im_info->description);
4684   return im_info->description;
4685 }
4686
4687 /*=*/
4688
4689 /***en
4690     @brief Get information about input method command(s).
4691
4692     The minput_get_command () function returns information about
4693     the command $COMMAND of the input method specified by $LANGUAGE and
4694     $NAME.  An input method command is a pseudo key event to which one
4695     or more actual input key sequences are assigned.
4696
4697     There are two kinds of commands, global and local.  A global
4698     command has a global definition, and the description and the key
4699     assignment may be inherited by a local command.  Each input method
4700     defines a local command which has a local key assignment.  It may
4701     also declare a local command that inherits the definition of a
4702     global command of the same name.
4703
4704     If $LANGUAGE is #Mt and $NAME is #Mnil, this function returns
4705     information about a global command.  Otherwise information about a
4706     local command is returned.
4707
4708     If $COMMAND is #Mnil, information about all commands is returned.
4709
4710     The return value is a @e well-formed plist (#m17nPlist) of this
4711     format:
4712 @verbatim
4713   ((NAME DESCRIPTION STATUS [KEYSEQ ...]) ...)
4714 @endverbatim
4715     @c NAME is a symbol representing the command name.
4716
4717     @c DESCRIPTION is an M-text describing the command, or #Mnil if the
4718     command has no description.
4719
4720     @c STATUS is a symbol representing how the key assignment is decided.
4721     The value is #Mnil (the default key assignment), #Mcustomized (the
4722     key assignment is customized by per-user configuration file), or
4723     #Mconfigured (the key assignment is set by the call of
4724     minput_config_command ()).  For a local command only, it may also
4725     be #Minherited (the key assignment is inherited from the
4726     corresponding global command).
4727
4728     @c KEYSEQ is a plist of one or more symbols representing a key
4729     sequence assigned to the command.  If there's no KEYSEQ, the
4730     command is currently disabled (i.e. no key sequence can trigger
4731     actions of the command).
4732
4733     If $COMMAND is not #Mnil, the first element of the returned plist
4734     contains the information about $COMMAND.
4735
4736     @return
4737
4738     If the requested information was found, a pointer to a non-empty
4739     plist is returned.  As the plist is kept in the library, the
4740     caller must not modify nor free it.
4741
4742     Otherwise (the specified input method or the specified command
4743     does not exist), @c NULL is returned.  */
4744 /***ja
4745     @brief ÆþÎϥ᥽¥Ã¥É¤Î¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë.
4746
4747     ´Ø¿ô minput_get_command () ¤Ï¡¢$LANGUAGE ¤È $NAME ¤Ç»ØÄꤵ¤ì¤ëÆþÎÏ
4748     ¥á¥½¥Ã¥É¤Î¥³¥Þ¥ó¥É $COMMAND ¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£ÆþÎϥ᥽¥Ã¥É¤Î¥³¥Þ
4749     ¥ó¥É¤È¤Ï¡¢µ¿»÷¥­¡¼¥¤¥Ù¥ó¥È¤Ç¤¢¤ê¡¢£±¤Ä°Ê¾å¤Î¼ÂºÝ¤ÎÆþÎÏ¥­¡¼¥·¡¼¥¯¥¨
4750     ¥ó¥¹¤¬³ä¤êÅö¤Æ¤é¤ì¤ë¡£
4751
4752     ¥³¥Þ¥ó¥É¤Ë¤Ï¡¢¥°¥í¡¼¥Ð¥ë¤È¥í¡¼¥«¥ë¤Î£²¼ïÎब¤¢¤ë¡£¥°¥í¡¼¥Ð¥ë¤Ê¥³¥Þ¥ó¥É
4753     ¤Ï¥°¥í¡¼¥Ð¥ë¤ËÄêµÁ¤µ¤ì¡¢¥í¡¼¥«¥ë¤Ê¥³¥Þ¥ó¥É¤Ï¤½¤ÎÀâÌÀ¤È¥­¡¼³ä¤êÅö¤Æ
4754     ¤ò·Ñ¾µ¤¹¤ë¤³¤È¤¬¤Ç¤­¤ë¡£³ÆÆþÎϥ᥽¥Ã¥É¤Ï¥í¡¼¥«¥ë¤Ê¥­¡¼³äÅö¤ò»ý¤Ä¥í¡¼
4755     ¥«¥ë¤Ê¥³¥Þ¥ó¥É¤òÄêµÁ¤¹¤ë¡£¤Þ¤¿Æ±Ì¾¤Î¥°¥í¡¼¥Ð¥ë¤Ê¥³¥Þ¥ó¥É¤ÎÄêµÁ¤ò·Ñ
4756     ¾µ¤¹¤ë¥í¡¼¥«¥ë¤Ê¥³¥Þ¥ó¥É¤òÀë¸À¤¹¤ë¤³¤È¤â¤Ç¤­¤ë¡£
4757
4758     $LANGUAGE ¤¬ #Mt ¤Ç $NAME ¤¬ #Mnil ¤Î¾ì¹ç¤Ï¡¢¤³¤Î´Ø¿ô¤Ï¥°¥í¡¼¥Ð¥ë¥³
4759     ¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¥í¡¼¥«¥ë¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¤â
4760     ¤Î¤òÊÖ¤¹¡£
4761
4762     $COMMAND ¤¬ #Mnil ¤Î¾ì¹ç¤Ï¡¢¤¹¤Ù¤Æ¤Î¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£
4763
4764     Ìá¤êÃͤϰʲ¼¤Î·Á¼°¤Î @e well-formed plist (#m17nPlist) ¤Ç¤¢¤ë¡£
4765
4766 @verbatim
4767   ((NAME DESCRIPTION STATUS [KEYSEQ ...]) ...)
4768 @endverbatim
4769     @c NAME ¤Ï¥³¥Þ¥ó¥É̾¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
4770
4771     @c DESCRIPTION ¤Ï¥³¥Þ¥ó¥É¤òÀâÌÀ¤¹¤ë M-text ¤Ç¤¢¤ë¤«¡¢ÀâÌÀ¤¬Ìµ¤¤¾ì¹ç¤Ë
4772     ¤Ï #Mnil ¤Ç¤¢¤ë¡£
4773
4774     @c STATUS ¤Ï¥­¡¼³ä¤êÅö¤Æ¤¬¤É¤Î¤è¤¦¤ËÄê¤á¤é¤ì¤ë¤«¤ò¤¢¤é¤ï¤¹¥·¥ó¥Ü¥ë¤Ç¤¢
4775     ¤ê¡¢¤½¤ÎÃͤϠ#Mnil ¡Ê¥Ç¥Õ¥©¥ë¥È¤Î³ä¤êÅö¤Æ¡Ë, #Mcustomized ¡Ê¥æ¡¼¥¶
4776     Ëè¤ÎÀßÄê¥Õ¥¡¥¤¥ë¤Ë¤è¤Ã¤Æ¥«¥¹¥¿¥Þ¥¤¥º¤µ¤ì¤¿³ä¤êÅö¤Æ¡Ë, #Mconfigured
4777     ¡Êminput_config_command ()¤ò¸Æ¤Ö¤³¤È¤Ë¤è¤Ã¤ÆÀßÄꤵ¤ì¤ë³ä¤êÅö¤Æ¡Ë¤Î
4778     ¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£¥í¡¼¥«¥ë¥³¥Þ¥ó¥É¤Î¾ì¹ç¤Ë¤Ï¡¢#Minherited ¡ÊÂбþ¤¹¤ë
4779     ¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É¤«¤é¤Î·Ñ¾µ¤Ë¤è¤ë³ä¤êÅö¤Æ¡Ë¤Ç¤â¤è¤¤¡£
4780
4781     @c KEYSEQ ¤Ï£±¤Ä°Ê¾å¤Î¥·¥ó¥Ü¥ë¤«¤é¤Ê¤ë plist ¤Ç¤¢¤ê¡¢³Æ¥·¥ó¥Ü¥ë¤Ï¥³¥Þ
4782     ¥ó¥É¤Ë³ä¤êÅö¤Æ¤é¤ì¤Æ¤¤¤ë¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤òɽ¤¹¡£KEYSEQ ¤¬Ìµ¤¤¾ì¹ç¤Ï¡¢
4783     ¤½¤Î¥³¥Þ¥ó¥É¤Ï¸½¾õ¤Ç»ÈÍÑÉÔǽ¤Ç¤¢¤ë¡£¡Ê¤¹¤Ê¤ï¤Á¥³¥Þ¥ó¥É¤ÎÆ°ºî¤òµ¯
4784     Æ°¤Ç¤­¤ë¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤¬Ìµ¤¤¡£¡Ë
4785
4786     $COMMAND ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢ÊÖ¤µ¤ì¤ë plist ¤ÎºÇ½é¤ÎÍ×ÁǤϡ¢
4787     $COMMAND ¤Ë´Ø¤¹¤ë¾ðÊó¤ò´Þ¤à¡£
4788
4789     @return
4790
4791     µá¤á¤é¤ì¤¿¾ðÊ󤬸«¤Ä¤«¤ì¤Ð¡¢¶õ¤Ç¤Ê¤¤ plist ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¥ê¥¹
4792     ¥È¤Ï¥é¥¤¥Ö¥é¥ê¤¬´ÉÍý¤·¤Æ¤¤¤ë¤Î¤Ç¡¢¸Æ½Ð¦¤¬Êѹ¹¤·¤¿¤ê²òÊü¤·¤¿¤ê¤¹¤ë
4793     ¤³¤È¤Ï¤Ç¤­¤Ê¤¤¡£
4794
4795     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¤¹¤Ê¤ï¤Á»ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤ä¥³¥Þ¥ó¥É¤¬Â¸ºß¤·¤Ê¤±¤ì¤Ð
4796     @c NULL ¤òÊÖ¤¹¡£  */
4797
4798 #if EXAMPLE_CODE
4799 MText *
4800 get_im_command_description (MSymbol language, MSymbol name, MSymbol command)
4801 {
4802   /* Return a description of the command COMMAND of the input method
4803      specified by LANGUAGE and NAME.  */
4804   MPlist *cmd = minput_get_command (langauge, name, command);
4805   MPlist *plist;
4806
4807   if (! cmds)
4808     return NULL;
4809   plist = mplist_value (cmds);  /* (NAME DESCRIPTION KEY-SEQ ...) */
4810   plist = mplist_next (plist);  /* (DESCRIPTION KEY-SEQ ...) */
4811   return  (mplist_key (plist) == Mtext
4812            ? (MText *) mplist_value (plist)
4813            : NULL);
4814 }
4815 #endif
4816
4817 MPlist *
4818 minput_get_command (MSymbol language, MSymbol name, MSymbol command)
4819 {
4820   MInputMethodInfo *im_info;
4821
4822   MINPUT__INIT ();
4823
4824   im_info = get_im_info (language, name, Mnil, Mcommand);
4825   if (! im_info
4826       || ! im_info->configured_cmds
4827       || MPLIST_TAIL_P (im_info->configured_cmds))
4828     return NULL;
4829   if (command == Mnil)
4830     return im_info->configured_cmds;
4831   return mplist__assq (im_info->configured_cmds, command);
4832 }
4833
4834 /*=*/
4835
4836 /***en
4837     @brief Configure the key sequence of an input method command.
4838
4839     The minput_config_command () function assigns a list of key
4840     sequences $KEYSEQLIST to the command $COMMAND of the input method
4841     specified by $LANGUAGE and $NAME.
4842
4843     If $KEYSEQLIST is a non-empty plist, it must be a list of key
4844     sequences, and each key sequence must be a plist of symbols.
4845
4846     If $KEYSEQLIST is an empty plist, the command becomes unusable.
4847
4848     If $KEYSEQLIST is NULL, the configuration of the command for the
4849     input method is canceled, and the default key sequences become
4850     effective.  In such case, if $COMMAND is #Mnil, configurations for
4851     all commands of the input method are canceled.
4852
4853     If $NAME is #Mnil, this function configures the key assignment of a
4854     global command, not that of a specific input method.
4855
4856     The configuration takes effect for input methods opened or
4857     re-opened later in the current session.  In order to make the
4858     configuration take effect for the future session, it must be saved
4859     in a per-user configuration file by the function
4860     minput_save_config ().
4861
4862     @return
4863
4864     If the operation was successful, this function returns 0,
4865     otherwise returns -1.  The operation fails in these cases:
4866     <ul>
4867     <li>$KEYSEQLIST is not in a valid form.
4868     <li>$COMMAND is not available for the input method.
4869     <li>$LANGUAGE and $NAME do not specify an existing input method.
4870     </ul>
4871
4872     @seealso
4873     minput_get_commands (), minput_save_config ().
4874 */
4875 /***ja
4876     @brief ÆþÎϥ᥽¥Ã¥É¤Î¥³¥Þ¥ó¥É¤Î¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤òÀßÄꤹ¤ë.
4877
4878     ´Ø¿ô minput_config_command () ¤Ï¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤Î¥ê¥¹¥È
4879     $KEYSEQLIST ¤ò¡¢$LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤ëÆþÎϥ᥽¥Ã¥É¤Î
4880     ¥³¥Þ¥ó¥É $COMMAND ¤Ë³ä¤êÅö¤Æ¤ë¡£
4881
4882     $KEYSEQLIST ¤¬¶õ¥ê¥¹¥È¤Ç¤Ê¤±¤ì¤Ð¡¢¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤Î¥ê¥¹¥È¤Ç¤¢¤ê¡¢
4883     ³Æ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤Ï¥·¥ó¥Ü¥ë¤Î plist ¤Ç¤¢¤ë¡£
4884
4885     $KEYSEQLIST ¤¬¶õ¤Î plist ¤Ê¤é¤Ð¡¢¥³¥Þ¥ó¥É¤Ï»ÈÍѤǤ­¤Ê¤¯¤Ê¤ë¡£
4886
4887     $KEYSEQLIST ¤¬ NULL ¤Ç¤¢¤ì¤Ð¡¢»ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤Î¥³¥Þ¥ó¥É¤ÎÀßÄê¤Ï
4888     ¥­¥ã¥ó¥»¥ë¤µ¤ì¡¢¥Ç¥Õ¥©¥ë¥È¤Î¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤¬Í­¸ú¤Ë¤Ê¤ë¡£¤³¤Î¾ì¹ç¡¢
4889     $COMMAND ¤¬ #Mnil ¤Ê¤é¤Ð»ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤ÎÁ´¤Æ¤Î¥³¥Þ¥ó¥É¤ÎÀßÄ꤬
4890     ¥­¥ã¥ó¥»¥ë¤µ¤ì¤ë¡£
4891
4892     $NAME ¤¬ #Mnil ¤Ê¤é¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¸Ä¡¹¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¤Ê¤¯¥°¥í¡¼¥Ð
4893     ¥ë¤Ê¥³¥Þ¥ó¥É¤Î¥­¡¼³ä¤êÅö¤Æ¤òÀßÄꤹ¤ë¡£
4894
4895     ¤³¤ì¤é¤ÎÀßÄê¤Ï¡¢¸½¹Ô¤Î¥»¥Ã¥·¥ç¥óÃæ¤ÇÆþÎϥ᥽¥Ã¥É¤¬¥ª¡¼¥×¥ó¡Ê¤Þ¤¿¤Ï
4896     ºÆ¥ª¡¼¥×¥ó¡Ë¤µ¤ì¤¿»þÅÀ¤ÇÍ­¸ú¤Ë¤Ê¤ë¡£¾­Íè¤Î¥»¥Ã¥·¥ç¥óÃæ¤Ç¤âÍ­¸ú¤Ë¤¹
4897     ¤ë¤¿¤á¤Ë¤Ï¡¢´Ø¿ô minput_save_config () ¤òÍѤ¤¤Æ¥æ¡¼¥¶Ëè¤ÎÀßÄê¥Õ¥¡¥¤
4898     ¥ë¤ËÊݸ¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
4899
4900     @return
4901
4902     ¤³¤Î´Ø¿ô¤Ï¡¢½èÍý¤¬À®¸ù¤¹¤ì¤Ð 0 ¤ò¡¢¼ºÇÔ¤¹¤ì¤Ð -1 ¤òÊÖ¤¹¡£¼ºÇԤȤϰʲ¼¤Î¾ì¹ç¤Ç¤¢¤ë¡£
4903     <ul>
4904     <li>$KEYSEQLIST ¤¬Í­¸ú¤Ê·Á¼°¤Ç¤Ê¤¤¡£
4905     <li>$COMMAND ¤¬»ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤ÇÍøÍѤǤ­¤Ê¤¤¡£
4906     <li>$LANGUAGE ¤È $NAME ¤Ç»ØÄꤵ¤ì¤ëÆþÎϥ᥽¥Ã¥É¤¬Â¸ºß¤·¤Ê¤¤¡£
4907     </ul>
4908
4909     @seealso
4910     minput_get_commands (), minput_save_config ().
4911 */
4912
4913 #if EXAMPLE_CODE
4914 /* Add "C-x u" to the "start" command of Unicode input method.  */
4915 {
4916   MSymbol start_command = msymbol ("start");
4917   MSymbol unicode = msymbol ("unicode");
4918   MPlist *cmd, *plist, *key_seq_list, *key_seq;
4919
4920   /* At first get the current key-sequence assignment.  */
4921   cmd = mplist_get_command (Mt, unicode, start_command);
4922   if (! cmd)
4923     {
4924       /* The input method does not have the command "start".  Here
4925          should come some error handling code.  */
4926     }
4927   /* Now CMD == ((start DESCRIPTION KEY-SEQUENCE ...) ...).  Extract
4928      the part (KEY-SEQUENCE ...).  */
4929   plist = mplist_next (mplist_next (mplist_value (cmd)));
4930   /* Copy it because we should not modify it directly.  */
4931   key_seq_list = mplist_copy (plist);
4932   m17n_object_unref (cmds);
4933   
4934   key_seq = mplist ();
4935   mplist_add (key_seq, Msymbol, msymbol ("C-x"));
4936   mplist_add (key_seq, Msymbol, msymbol ("u"));
4937   mplist_add (key_seq_list, Mplist, key_seq);
4938   m17n_object_unref (key_seq);
4939
4940   minput_config_command (Mt, unicode, start_command, key_seq_list);
4941   m17n_object_unref (key_seq_list);
4942 }
4943 #endif
4944
4945 int
4946 minput_config_command (MSymbol language, MSymbol name, MSymbol command,
4947                        MPlist *keyseqlist)
4948 {
4949   MInputMethodInfo *im_info, *config;
4950   MPlist *plist;
4951
4952   MINPUT__INIT ();
4953
4954   if (keyseqlist)
4955     {
4956       if (command == Mnil)
4957         MERROR (MERROR_IM, -1);
4958       MPLIST_DO (plist, keyseqlist)
4959         if (! MPLIST_PLIST_P (plist)
4960             || ! check_command_keyseq (plist))
4961           MERROR (MERROR_IM, -1);
4962     }
4963
4964   im_info = get_im_info (language, name, Mnil, Mcommand);
4965   if (! im_info)
4966     MERROR (MERROR_IM, -1);
4967   if (command != Mnil
4968       && (! im_info->cmds
4969           || ! mplist__assq (im_info->cmds, command)))
4970     MERROR (MERROR_IM, -1);
4971
4972   config = get_config_info (im_info);
4973   if (! config)
4974     {
4975       if (! im_config_list)
4976         im_config_list = mplist ();
4977       config = new_im_info (NULL, language, name, Mnil, im_config_list);
4978       config->cmds = mplist ();
4979       config->vars = mplist ();
4980     }
4981
4982   if (command == Mnil)
4983     {
4984       MInputMethodInfo *custom = get_custom_info (im_info);
4985
4986       mplist_set (config->cmds, Mnil, NULL);
4987       if (custom && custom->cmds)
4988         {
4989           MPLIST_DO (plist, custom->cmds)
4990             {
4991               command = MPLIST_SYMBOL (MPLIST_PLIST (plist));
4992               plist = mplist ();
4993               mplist_add (plist, Msymbol, command);
4994               mplist_push (config->cmds, Mplist, plist);
4995               M17N_OBJECT_UNREF (plist);
4996             }
4997         }
4998     }
4999   else
5000     {
5001       plist = mplist__assq (config->cmds, command);
5002       if (plist)
5003         {
5004           plist = MPLIST_PLIST (plist); /* (NAME [nil KEY-SEQUENCE ...])  */
5005           plist = MPLIST_NEXT (plist);  /* ([nil ...]) */
5006           if (! MPLIST_TAIL_P (plist))
5007             mplist_set (plist, Mnil, NULL); /* () */
5008         }
5009       else
5010         {
5011           plist = mplist ();
5012           mplist_add (config->cmds, Mplist, plist);
5013           M17N_OBJECT_UNREF (plist);
5014           plist = mplist_add (plist, Msymbol, command);
5015           plist = MPLIST_NEXT (plist);
5016         }
5017       if (keyseqlist)
5018         {
5019           MPlist *pl;
5020
5021           plist = mplist_add (plist, Msymbol, Mnil);
5022           MPLIST_DO (keyseqlist, keyseqlist)
5023             {
5024               pl = mplist_copy (MPLIST_VAL (keyseqlist));
5025               plist = mplist_add (plist, Mplist, pl);
5026               M17N_OBJECT_UNREF (pl);
5027             }
5028         }
5029     }
5030   config_all_commands (im_info);
5031   im_info->tick = time (NULL);
5032   return 0;
5033 }
5034
5035 /*=*/
5036
5037 /***en
5038     @brief Get information about input method variable(s).
5039
5040     The minput_get_variable () function returns information about
5041     the variable $VARIABLE of the input method specified by $LANGUAGE and $NAME.
5042     An input method variable controls behavior of an input method.
5043
5044     There are two kinds of variables, global and local.  A global
5045     variable has a global definition, and the description and the value
5046     may be inherited by a local variable.  Each input method defines a
5047     local variable which has local value.  It may also declare a
5048     local variable that inherits definition of a global variable of
5049     the same name.
5050
5051     If $LANGUAGE is #Mt and $NAME is #Mnil, information about a global
5052     variable is returned.  Otherwise information about a local variable
5053     is returned.
5054
5055     If $VARIABLE is #Mnil, information about all variables is
5056     returned.
5057
5058     The return value is a @e well-formed plist (#m17nPlist) of this
5059     format:
5060 @verbatim
5061   ((NAME DESCRIPTION STATUS VALUE [VALID-VALUE ...]) ...)
5062 @endverbatim
5063     @c NAME is a symbol representing the variable name.
5064
5065     @c DESCRIPTION is an M-text describing the variable, or #Mnil if the
5066     variable has no description.
5067
5068     @c STATUS is a symbol representing how the value is decided.  The
5069     value is #Mnil (the default value), #Mcustomized (the value is
5070     customized by per-user configuration file), or #Mconfigured (the
5071     value is set by the call of minput_config_variable ()).  For a
5072     local variable only, it may also be #Minherited (the value is
5073     inherited from the corresponding global variable).
5074
5075     @c VALUE is the initial value of the variable.  If the key of this
5076     element is #Mt, the variable has no initial value.  Otherwise, the
5077     key is #Minteger, #Msymbol, or #Mtext and the value is of the
5078     corresponding type.
5079
5080     @c VALID-VALUEs (if any) specify which values the variable can have.
5081     They have the same type (i.e. having the same key) as @c VALUE except
5082     for the case that VALUE is an integer.  In that case, @c VALID-VALUE
5083     may be a plist of two integers specifying the range of possible
5084     values.
5085
5086     If there no @c VALID-VALUE, the variable can have any value as long
5087     as the type is the same as @c VALUE.
5088
5089     If $VARIABLE is not #Mnil, the first element of the returned plist
5090     contains the information about $VARIABLE.
5091
5092     @return
5093
5094     If the requested information was found, a pointer to a non-empty
5095     plist is returned.  As the plist is kept in the library, the
5096     caller must not modify nor free it.
5097
5098     Otherwise (the specified input method or the specified variable
5099     does not exist), @c NULL is returned.  */
5100 /***ja
5101     @brief ÆþÎϥ᥽¥Ã¥É¤ÎÊÑ¿ô¤Ë´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë.
5102
5103     ´Ø¿ô minput_get_variable () ¤Ï¡¢$LANGUAGE ¤È $NAME ¤Ç»ØÄꤵ¤ì¤ëÆþÎÏ
5104     ¥á¥½¥Ã¥É¤ÎÊÑ¿ô $VARIABLE ¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£ÆþÎϥ᥽¥Ã¥É¤ÎÊÑ¿ô¤È¤Ï¡¢
5105     ÆþÎϥ᥽¥Ã¥É¤Î¿¶Éñ¤òÀ©¸æ¤¹¤ë¤â¤Î¤Ç¤¢¤ë¡£
5106
5107     ÊÑ¿ô¤Ë¤Ï¡¢¥°¥í¡¼¥Ð¥ë¤È¥í¡¼¥«¥ë¤Î£²¼ïÎब¤¢¤ë¡£¥°¥í¡¼¥Ð¥ë¤ÊÊÑ¿ô¤Ï¥°
5108     ¥í¡¼¥Ð¥ë¤ËÄêµÁ¤µ¤ì¡¢¥í¡¼¥«¥ë¤ÊÊÑ¿ô¤Ï¤½¤ÎÀâÌÀ¤ÈÃͤò·Ñ¾µ¤¹¤ë¤³¤È¤¬¤Ç
5109     ¤­¤ë¡£³ÆÆþÎϥ᥽¥Ã¥É¤Ï¥í¡¼¥«¥ë¤ÊÃͤò»ý¤Ä¥í¡¼¥«¥ë¤ÊÊÑ¿ô¤òÄêµÁ¤¹¤ë¡£
5110     ¤Þ¤¿Æ±Ì¾¤Î¥°¥í¡¼¥Ð¥ë¤ÊÊÑ¿ô¤ÎÄêµÁ¤ò·Ñ¾µ¤¹¤ë¥í¡¼¥«¥ë¤ÊÊÑ¿ô¤òÀë¸À¤¹¤ë
5111     ¤³¤È¤â¤Ç¤­¤ë¡£
5112
5113     $LANGUAGE ¤¬ #Mt ¤Ç $NAME ¤¬ #Mnil ¤Î¾ì¹ç¤Ï¡¢¤³¤Î´Ø¿ô¤Ï¥°¥í¡¼¥Ð¥ëÊÑ
5114     ¿ô¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¥í¡¼¥«¥ëÊÑ¿ô¤Ë´Ø¤¹¤ë¤â¤Î¤òÊÖ¤¹¡£
5115
5116     $VARIABLE ¤¬ #Mnil ¤Î¾ì¹ç¤Ï¡¢¤¹¤Ù¤Æ¤Î¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£
5117
5118     Ìá¤êÃͤϰʲ¼¤Î·Á¼°¤Î @e well-formed plist (#m17nPlist) ¤Ç¤¢¤ë¡£
5119 @verbatim
5120   ((NAME DESCRIPTION STATUS VALUE [VALID-VALUE ...]) ...)
5121 @endverbatim
5122
5123     @c NAME ¤ÏÊÑ¿ô¤Î̾Á°¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
5124
5125     @c DESCRIPTION ¤ÏÊÑ¿ô¤òÀâÌÀ¤¹¤ë M-text ¤Ç¤¢¤ë¤«¡¢ÀâÌÀ¤¬Ìµ¤¤¾ì¹ç¤Ë¤Ï
5126     #Mnil ¤Ç¤¢¤ë¡£
5127
5128     @c STATUS ¤ÏÃͤ¬¤É¤Î¤è¤¦¤ËÄê¤á¤é¤ì¤ë¤«¤ò¤¢¤é¤ï¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢
5129     @c STATUS ¤ÎÃͤϠ#Mnil ¡Ê¥Ç¥Õ¥©¥ë¥È¤ÎÃÍ¡Ë, #Mcustomized ¡Ê¥æ¡¼¥¶Ëè¤ÎÀß
5130     Äê¥Õ¥¡¥¤¥ë¤Ë¤è¤Ã¤Æ¥«¥¹¥¿¥Þ¥¤¥º¤µ¤ì¤¿ÃÍ¡Ë, #Mconfigured
5131     ¡Êminput_config_variable ()¤ò¸Æ¤Ö¤³¤È¤Ë¤è¤Ã¤ÆÀßÄꤵ¤ì¤ëÃ͡ˤΤ¤¤º¤ì
5132     ¤«¤Ç¤¢¤ë¡£¥í¡¼¥«¥ëÊÑ¿ô¤Î¾ì¹ç¤Ë¤Ï¡¢#Minherited ¡ÊÂбþ¤¹¤ë¥°¥í¡¼¥Ð¥ë
5133     ÊÑ¿ô¤«¤é·Ñ¾µ¤·¤¿Ã͡ˤǤâ¤è¤¤¡£
5134
5135     @c VALUE ¤ÏÊÑ¿ô¤Î½é´üÃͤǤ¢¤ë¡£¤³¤ÎÍ×ÁǤΥ­¡¼¤¬#Mt ¤Ç¤¢¤ì¤Ð½é´üÃͤò»ý
5136     ¤¿¤Ê¤¤¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¥­¡¼¤Ï #Minteger, #Msymbol, #Mtext ¤Î¤¤¤º¤ì
5137     ¤«¤Ç¤¢¤ê¡¢ÃͤϤ½¤ì¤¾¤ìÂбþ¤¹¤ë·¿¤Î¤â¤Î¤Ç¤¢¤ë¡£
5138
5139     @c VALID-VALUE ¤Ï¤â¤·¤¢¤ì¤Ð¡¢ÊÑ¿ô¤Î¼è¤êÆÀ¤ëÃͤò»ØÄꤹ¤ë¡£¤³¤ì¤Ï @c VALUE
5140     ¤ÈƱ¤¸·¿(¤¹¤Ê¤ï¤ÁƱ¤¸¥­¡¼¤ò»ý¤Ä) ¤Ç¤¢¤ë¤¬¡¢Îã³°¤È¤·¤Æ @c VALUE ¤¬
5141     integer ¤Î¾ì¹ç¤Ï @c VALID-VALUE ¤Ï²Äǽ¤ÊÃͤÎÈϰϤò¼¨¤¹Æó¤Ä¤ÎÀ°¿ô¤«¤é
5142     ¤Ê¤ë plist ¤È¤Ê¤ë¤³¤È¤¬¤Ç¤­¤ë¡£
5143
5144     @c VALID-VALUE ¤¬¤Ê¤±¤ì¤Ð¡¢ÊÑ¿ô¤Ï @c VALUE ¤ÈƱ¤¸·¿¤Ç¤¢¤ë¸Â¤ê¤¤¤«¤Ê¤ëÃͤâ
5145     ¤È¤ë¤³¤È¤¬¤Ç¤­¤ë¡£
5146
5147     $VARIABLE ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢ÊÖ¤µ¤ì¤ë plist ¤ÎºÇ½é¤ÎÍ×ÁǤÏ
5148     $VARIABLE ¤Ë´Ø¤¹¤ë¾ðÊó¤ò´Þ¤à¡£
5149
5150     @return
5151
5152     µá¤á¤é¤ì¤¿¾ðÊ󤬸«¤Ä¤«¤ì¤Ð¡¢¶õ¤Ç¤Ê¤¤ plist ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¥ê¥¹
5153     ¥È¤Ï¥é¥¤¥Ö¥é¥ê¤¬´ÉÍý¤·¤Æ¤¤¤ë¤Î¤Ç¡¢¸Æ½Ð¦¤¬Êѹ¹¤·¤¿¤ê²òÊü¤·¤¿¤ê¤¹¤ë
5154     ¤³¤È¤Ï¤Ç¤­¤Ê¤¤¡£
5155
5156     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¤¹¤Ê¤ï¤Á»ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤äÊÑ¿ô¤¬Â¸ºß¤·¤Ê¤±¤ì¤Ð
5157     @c NULL ¤òÊÖ¤¹¡£ */
5158
5159 MPlist *
5160 minput_get_variable (MSymbol language, MSymbol name, MSymbol variable)
5161 {
5162   MInputMethodInfo *im_info;
5163
5164   MINPUT__INIT ();
5165
5166   im_info = get_im_info (language, name, Mnil, Mvariable);
5167   if (! im_info || ! im_info->configured_vars)
5168     return NULL;
5169   if (variable == Mnil)
5170     return im_info->configured_vars;
5171   return mplist__assq (im_info->configured_vars, variable);
5172 }
5173
5174 /*=*/
5175
5176 /***en
5177     @brief Configure the value of an input method variable.
5178
5179     The minput_config_variable () function assigns $VALUE to the
5180     variable $VARIABLE of the input method specified by $LANGUAGE and
5181     $NAME.
5182
5183     If $VALUE is not NULL, it must be a plist of one element whose key
5184     is #Minteger, #Msymbol, or #Mtext, and the value is of the
5185     corresponding type.
5186
5187     If $VALUE is NULL, a configuration for the variable for the input
5188     method is canceled, and the variable is initialized to the default
5189     value.  In that case, if $VARIABLE is #Mnil, configurations for
5190     all variables of the input method are canceled.
5191
5192     If $NAME is #Mnil, this function configure the value of global
5193     variable, not that of a specific input method.
5194
5195     The configuration takes effect for input methods opened or
5196     re-opened later in the current session.  To make the configuration
5197     take effect for the future session, it must be saved in a per-user
5198     configuration file by the function minput_save_config ().
5199
5200     @return
5201
5202     If the operation was successful, this function returns 0,
5203     otherwise returns -1.  The operation fails in these cases:
5204     <ul>
5205     <li>$VALUE is not in a valid form, the type does not match the
5206     definition, or the value is our of range.
5207     <li>$VARIABLE is not available for the input method.
5208     <li>$LANGUAGE and $NAME do not specify an existing input method.  
5209     </ul>
5210
5211     @seealso
5212     minput_get_variable (), minput_save_config ().  */
5213 /***ja
5214     @brief ÆþÎϥ᥽¥Ã¥É¤ÎÊÑ¿ô¤ÎÃͤòÀßÄꤹ¤ë.
5215
5216     ´Ø¿ô minput_config_variable () ¤ÏÃÍ $VALUE ¤ò¡¢$LANGUAGE ¤È $NAME
5217     ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤ëÆþÎϥ᥽¥Ã¥É¤ÎÊÑ¿ô $VARIABLE ¤Ë³ä¤êÅö¤Æ¤ë¡£
5218
5219     $VALUE ¤¬ NULL¤Ç¤Ê¤±¤ì¤Ð¡¢£±Í×ÁǤΠplist ¤Ç¤¢¤ê¡¢¤½¤Î¥­¡¼¤Ï
5220     #Minteger, #Msymbol, #Mtext ¤Î¤¤¤º¤ì¤«¡¢ÃͤÏÂбþ¤¹¤ë·¿¤Î¤â¤Î¤Ç¤¢¤ë¡£
5221
5222     $VALUE ¤¬ NULL ¤Ç¤¢¤ì¤Ð¡¢»ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤ÎÊÑ¿ô¤ÎÀßÄê¤Ï¥­¥ã¥ó¥»¥ë
5223     ¤µ¤ì¡¢ÊÑ¿ô¤Ï¥Ç¥Õ¥©¥ë¥ÈÃͤ˽é´ü²½¤µ¤ì¤ë¡£¤³¤Î¾ì¹ç¡¢$VARIABLE ¤¬
5224     #Mnil ¤Ê¤é¤Ð»ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤ÎÁ´¤Æ¤ÎÊÑ¿ô¤ÎÀßÄ꤬¥­¥ã¥ó¥»¥ë¤µ¤ì¤ë¡£
5225
5226     $NAME ¤¬ #Mnil ¤Ê¤é¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¸Ä¡¹¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¤Ê¤¯¥°¥í¡¼¥Ð
5227     ¥ë¤ÊÊÑ¿ô¤ÎÃͤòÀßÄꤹ¤ë¡£
5228
5229     ¤³¤ì¤é¤ÎÀßÄê¤Ï¡¢¸½¹Ô¤Î¥»¥Ã¥·¥ç¥óÃæ¤ÇÆþÎϥ᥽¥Ã¥É¤¬¥ª¡¼¥×¥ó¡Ê¤Þ¤¿¤Ï
5230     ºÆ¥ª¡¼¥×¥ó¡Ë¤µ¤ì¤¿»þÅÀ¤ÇÍ­¸ú¤Ë¤Ê¤ë¡£¾­Íè¤Î¥»¥Ã¥·¥ç¥óÃæ¤Ç¤âÍ­¸ú¤Ë¤¹
5231     ¤ë¤¿¤á¤Ë¤Ï¡¢´Ø¿ô minput_save_config () ¤òÍѤ¤¤Æ¥æ¡¼¥¶Ëè¤ÎÀßÄê¥Õ¥¡¥¤
5232     ¥ë¤ËÊݸ¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
5233
5234     @return
5235
5236     ¤³¤Î´Ø¿ô¤Ï¡¢½èÍý¤¬À®¸ù¤¹¤ì¤Ð 0 ¤ò¡¢¼ºÇÔ¤¹¤ì¤Ð -1 ¤òÊÖ¤¹¡£¼ºÇԤȤϰʲ¼¤Î¾ì¹ç¤Ç¤¢¤ë¡£
5237     <ul>
5238     <li>$VALUE¤¬Í­¸ú¤Ê·Á¼°¤Ç¤Ê¤¤¡£·¿¤¬ÄêµÁ¤Ë¹ç¤ï¤Ê¤¤¡¢¤Þ¤¿¤ÏÃͤ¬Èϰϳ°¤Ç¤¢¤ë¡£
5239     <li>$VARIABLE ¤¬»ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤ÇÍøÍѤǤ­¤Ê¤¤¡£
5240     <li>$LANGUAGE ¤È $NAME ¤Ç»ØÄꤵ¤ì¤ëÆþÎϥ᥽¥Ã¥É¤¬Â¸ºß¤·¤Ê¤¤¡£
5241     </ul>
5242
5243     @seealso
5244     minput_get_commands (), minput_save_config ().
5245 */
5246 int
5247 minput_config_variable (MSymbol language, MSymbol name, MSymbol variable,
5248                         MPlist *value)
5249 {
5250   MInputMethodInfo *im_info, *config;
5251   MPlist *plist;
5252
5253   MINPUT__INIT ();
5254
5255   im_info = get_im_info (language, name, Mnil, Mvariable);
5256   if (! im_info)
5257     MERROR (MERROR_IM, -1);
5258   if (variable == Mnil)
5259     {
5260       if (value)
5261         MERROR (MERROR_IM, -1);
5262     }
5263   else if (! im_info->vars
5264            || ! (plist = mplist__assq (im_info->configured_vars, variable)))
5265     MERROR (MERROR_IM, -1);
5266
5267   if (variable != Mnil && value)
5268     {
5269       plist = MPLIST_PLIST (plist);
5270       plist = MPLIST_NEXT (plist); /* (DESC STATUS VALUE VALIDS ...) */
5271       plist = MPLIST_NEXT (plist); /* (STATUS VALUE VALIDS ...) */
5272       plist = MPLIST_NEXT (plist); /* (VALUE VALIDS ...) */
5273       if (MPLIST_KEY (plist) != Mt
5274           && ! check_variable_value (value, plist))
5275         MERROR (MERROR_IM, -1);
5276     }
5277
5278   config = get_config_info (im_info);
5279   if (! config)
5280     {
5281       if (! im_config_list)
5282         im_config_list = mplist ();
5283       config = new_im_info (NULL, language, name, Mnil, im_config_list);
5284       config->cmds = mplist ();
5285       config->vars = mplist ();
5286     }
5287
5288   if (variable == Mnil)
5289     {
5290       MInputMethodInfo *custom = get_custom_info (im_info);
5291
5292       mplist_set (config->vars, Mnil, NULL);
5293       if (custom && custom->cmds)
5294         {
5295           MPLIST_DO (plist, custom->vars)
5296             {
5297               variable = MPLIST_SYMBOL (MPLIST_PLIST (plist));
5298               plist = mplist ();
5299               mplist_add (plist, Msymbol, variable);
5300               mplist_push (config->vars, Mplist, plist);
5301               M17N_OBJECT_UNREF (plist);
5302             }
5303         }
5304     }
5305   else
5306     {
5307       plist = mplist__assq (config->vars, variable);
5308       if (plist)
5309         {
5310           plist = MPLIST_PLIST (plist); /* (NAME nil VALUE) */
5311           plist = MPLIST_NEXT (plist);  /* ([nil VALUE]) */
5312           if (! MPLIST_TAIL_P (plist))
5313             mplist_set (plist, Mnil ,NULL); /* () */
5314         }
5315       else
5316         {
5317           plist = mplist ();
5318           mplist_add (config->vars, Mplist, plist);
5319           M17N_OBJECT_UNREF (plist);
5320           plist = mplist_add (plist, Msymbol, variable);
5321           plist = MPLIST_NEXT (plist);
5322         }
5323       if (value)
5324         {
5325           plist = mplist_add (plist, Msymbol, Mnil);
5326           mplist_add (plist, MPLIST_KEY (value), MPLIST_VAL (value));
5327         }
5328     }
5329   config_all_variables (im_info);
5330   im_info->tick = time (NULL);
5331   return 0;
5332 }
5333
5334 /*=*/
5335
5336 /***en
5337     @brief Get the name of per-user configuration file.
5338     
5339     The minput_config_file () function returns the absolute path name
5340     of per-user configuration file into which minput_save_config ()
5341     save configurations.  It is usually @c "config.mic" under the
5342     directory @c ".m17n.d" of user's home directory.  It is not assured
5343     that the file of the returned name exists nor is
5344     readable/writable.  If minput_save_config () fails and returns -1,
5345     an application program might check the file, make it
5346     writable (if possible), and try minput_save_config () again.
5347
5348     @return
5349
5350     This function returns a string.  As the string is kept in the
5351     library, the caller must not modify nor free it.
5352
5353     @seealso
5354     minput_save_config ()
5355 */
5356 /***ja
5357     @brief ¥æ¡¼¥¶Ëè¤ÎÀßÄê¥Õ¥¡¥¤¥ë¤Î̾Á°¤òÆÀ¤ë.
5358     
5359     ´Ø¿ô minput_config_file () ¤Ï¡¢´Ø¿ô minput_save_config () ¤¬ÀßÄê¤ò
5360     Êݸ¤¹¤ë¥æ¡¼¥¶Ëè¤ÎÀßÄê¥Õ¥¡¥¤¥ë¤Ø¤ÎÀäÂХѥ¹Ì¾¤òÊÖ¤¹¡£Ä̾ï¤Ï¡¢¥æ¡¼¥¶
5361     ¤Î¥Û¡¼¥à¥Ç¥£¥ì¥¯¥È¥ê¤Î²¼¤Î¥Ç¥£¥ì¥¯¥È¥ê @c ".m17n.d" ¤Ë¤¢¤ë@c
5362     "config.mic" ¤È¤Ê¤ë¡£ÊÖ¤µ¤ì¤¿Ì¾Á°¤Î¥Õ¥¡¥¤¥ë¤¬Â¸ºß¤¹¤ë¤«¡¢Æɤ߽ñ¤­¤Ç
5363     ¤­¤ë¤«¤ÏÊݾڤµ¤ì¤Ê¤¤¡£´Ø¿ôminput_save_config () ¤¬¼ºÇÔ¤·¤Æ -1 ¤òÊÖ
5364     ¤·¤¿¾ì¹ç¤Ë¤Ï¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ï¥Õ¥¡¥¤¥ë¤Î¸ºß¤ò³Îǧ¤·¡¢
5365     ¡Ê¤Ç¤­¤ì¤Ð¡Ë½ñ¤­¹þ¤ß²Äǽ¤Ë¤·ºÆÅÙminput_save_config () ¤ò»î¤¹¤³¤È¤¬
5366     ¤Ç¤­¤ë¡£
5367
5368     @return
5369
5370     ¤³¤Î´Ø¿ô¤Ïʸ»úÎó¤òÊÖ¤¹¡£Ê¸»úÎó¤Ï¥é¥¤¥Ö¥é¥ê¤¬´ÉÍý¤·¤Æ¤¤¤ë¤Î¤Ç¡¢¸Æ½Ð
5371     Â¦¤¬½¤Àµ¤·¤¿¤ê²òÊü¤·¤¿¤ê¤¹¤ë¤³¤È¤Ï¤Ç¤­¤Ê¤¤¡£
5372
5373     @seealso
5374     minput_save_config ()
5375 */
5376
5377 char *
5378 minput_config_file ()
5379 {
5380   MINPUT__INIT ();
5381
5382   return mdatabase__file (im_custom_mdb);
5383 }
5384
5385 /*=*/
5386
5387 /***en
5388     @brief Save configurations in per-user configuration file.
5389
5390     The minput_save_config () function saves the configurations done
5391     so far in the current session into the per-user configuration
5392     file.
5393
5394     @return
5395
5396     If the operation was successful, 1 is returned.  If the per-user
5397     configuration file is currently locked, 0 is returned.  In that
5398     case, the caller may wait for a while and try again.  If the
5399     configuration file is not writable, -1 is returned.  In that case,
5400     the caller may check the name of the file by calling
5401     minput_config_file (), make it writable if possible, and try
5402     again.
5403
5404     @seealso
5405     minput_config_file ()  */
5406 /***ja
5407     @brief ÀßÄê¤ò¥æ¡¼¥¶Ëè¤ÎÀßÄê¥Õ¥¡¥¤¥ë¤ËÊݸ¤¹¤ë.
5408
5409     ´Ø¿ô minput_save_config () ¤Ï¸½¹Ô¤Î¥»¥Ã¥·¥ç¥ó¤Ç¤³¤ì¤Þ¤Ç¤Ë¹Ô¤Ã¤¿ÀßÄê
5410     ¤ò¥æ¡¼¥¶Ëè¤ÎÀßÄê¥Õ¥¡¥¤¥ë¤ËÊݸ¤¹¤ë¡£
5411
5412     @return
5413
5414     À®¸ù¤¹¤ì¤Ð 1 ¤òÊÖ¤¹¡£¥æ¡¼¥¶Ëè¤ÎÀßÄê¥Õ¥¡¥¤¥ë¤¬¥í¥Ã¥¯¤µ¤ì¤Æ¤¤¤ì¤Ð 0
5415     ¤òÊÖ¤¹¡£¤³¤Î¾ì¹ç¡¢¸Æ½Ð¦¤Ï¤·¤Ð¤é¤¯ÂԤäƺƻî¹Ô¤Ç¤­¤ë¡£ÀßÄê¥Õ¥¡¥¤¥ë
5416     ¤¬½ñ¤­¹þ¤ßÉԲĤξì¹ç¡¢-1 ¤òÊÖ¤¹¡£¤³¤Î¾ì¹ç¡¢minput_config_file () ¤ò
5417     ¸Æ¤ó¤Ç¥Õ¥¡¥¤¥ë̾¤ò¥Á¥§¥Ã¥¯¤·¡¢¤Ç¤­¤ì¤Ð½ñ¤­¹þ¤ß²Äǽ¤Ë¤·¡¢ºÆ»î¹Ô¤Ç¤­
5418     ¤ë¡£
5419
5420     @seealso
5421     minput_config_file ()  */
5422
5423 int
5424 minput_save_config (void)
5425 {
5426   MPlist *data, *tail, *plist, *p, *elt;
5427   int ret;
5428
5429   MINPUT__INIT ();
5430   ret = mdatabase__lock (im_custom_mdb);
5431   if (ret <= 0)
5432     return ret;
5433   if (! im_config_list)
5434     return 1;
5435   update_custom_info ();
5436   if (! im_custom_list)
5437     im_custom_list = mplist ();
5438   data = tail = mplist ();
5439
5440   MPLIST_DO (plist, im_config_list)
5441     {
5442       MPlist *pl = MPLIST_PLIST (plist);
5443       MSymbol language, name, extra, command, variable;
5444       MInputMethodInfo *custom, *config;
5445
5446       language = MPLIST_SYMBOL (pl);
5447       pl = MPLIST_NEXT (pl);
5448       name = MPLIST_SYMBOL (pl);
5449       pl = MPLIST_NEXT (pl);
5450       extra = MPLIST_SYMBOL (pl);
5451       pl = MPLIST_NEXT (pl);
5452       config = MPLIST_VAL (pl);
5453       custom = get_custom_info (config);
5454       if (! custom)
5455         custom = new_im_info (NULL, language, name, extra, im_custom_list);
5456       if (config->cmds)
5457         MPLIST_DO (pl, config->cmds)
5458           {
5459             elt = MPLIST_PLIST (pl);
5460             command = MPLIST_SYMBOL (elt);
5461             if (custom->cmds)
5462               p = mplist__assq (custom->cmds, command);
5463             else
5464               custom->cmds = mplist (), p = NULL;
5465             elt = MPLIST_NEXT (elt);
5466             if (MPLIST_TAIL_P (elt))
5467               {
5468                 if (p)
5469                   mplist__pop_unref (p);
5470               }
5471             else
5472               {
5473                 elt = MPLIST_NEXT (elt);
5474                 if (p)
5475                   {
5476                     p = MPLIST_NEXT (MPLIST_NEXT (MPLIST_PLIST (p)));
5477                     mplist_set (p, Mnil, NULL);
5478                     mplist__conc (p, elt);
5479                   }
5480                 else
5481                   {
5482                     p = MPLIST_PLIST (pl);
5483                     mplist_add (custom->cmds, Mplist, p);
5484                   }
5485               }
5486           }
5487       if (config->vars)
5488         MPLIST_DO (pl, config->vars)
5489           {
5490             elt = MPLIST_PLIST (pl);
5491             variable = MPLIST_SYMBOL (elt);
5492             if (custom->vars)
5493               p = mplist__assq (custom->vars, variable);
5494             else
5495               custom->vars = mplist (), p = NULL;
5496             elt = MPLIST_NEXT (elt);
5497             if (MPLIST_TAIL_P (elt))
5498               {
5499                 if (p)
5500                   mplist__pop_unref (p);
5501               }
5502             else
5503               {
5504                 elt = MPLIST_NEXT (elt);
5505                 if (p)
5506                   {
5507                     p = MPLIST_NEXT (MPLIST_NEXT (MPLIST_PLIST (p)));
5508                     mplist_set (p, Mnil, NULL);
5509                     mplist__conc (p, elt);
5510                   }
5511                 else
5512                   {
5513                     p = MPLIST_PLIST (pl);
5514                     mplist_add (custom->vars, Mplist, p);
5515                   }
5516               }
5517           }
5518     }
5519   M17N_OBJECT_UNREF (im_config_list);
5520
5521   MPLIST_DO (plist, im_custom_list)
5522     {
5523       MPlist *pl = MPLIST_PLIST (plist);
5524       MSymbol language, name, extra;
5525       MInputMethodInfo *custom, *im_info;
5526
5527       language = MPLIST_SYMBOL (pl);
5528       pl  = MPLIST_NEXT (pl);
5529       name = MPLIST_SYMBOL (pl);
5530       pl = MPLIST_NEXT (pl);
5531       extra = MPLIST_SYMBOL (pl);
5532       pl = MPLIST_NEXT (pl);
5533       custom = MPLIST_VAL (pl);
5534       im_info = lookup_im_info (im_info_list, language, name, extra);
5535       if (im_info)
5536         {
5537           if (im_info->cmds)
5538             config_all_commands (im_info);
5539           if (im_info->vars)
5540             config_all_variables (im_info);
5541         }
5542       
5543       elt = mplist ();
5544       tail = mplist_add (tail, Mplist, elt);
5545       M17N_OBJECT_UNREF (elt);
5546       pl = mplist ();
5547       elt = mplist_add (elt, Mplist, pl);
5548       M17N_OBJECT_UNREF (pl);
5549       pl = mplist_add (pl, Msymbol, Minput_method);
5550       pl = mplist_add (pl, Msymbol, language);
5551       pl = mplist_add (pl, Msymbol, name);
5552       if (extra != Mnil)
5553         pl = mplist_add (pl, Msymbol, extra);
5554       if (custom->cmds && ! MPLIST_TAIL_P (custom->cmds))
5555         {
5556           pl = mplist ();
5557           elt = mplist_add (elt, Mplist, pl);
5558           M17N_OBJECT_UNREF (pl);
5559           pl = mplist_add (pl, Msymbol, Mcommand);
5560           MPLIST_DO (p, custom->cmds)
5561             pl = mplist_add (pl, Mplist, MPLIST_PLIST (p));
5562         }
5563       if (custom->vars && ! MPLIST_TAIL_P (custom->vars))
5564         {
5565           pl = mplist ();
5566           elt = mplist_add (elt, Mplist, pl);
5567           M17N_OBJECT_UNREF (pl);
5568           pl = mplist_add (pl, Msymbol, Mvariable);
5569           MPLIST_DO (p, custom->vars)
5570             pl = mplist_add (pl, Mplist, MPLIST_PLIST (p));
5571         }
5572     }
5573
5574   mplist_push (data, Mstring, ";; -*- mode:lisp; coding:utf-8 -*-");
5575   ret = mdatabase__save (im_custom_mdb, data);
5576   mdatabase__unlock (im_custom_mdb);
5577   M17N_OBJECT_UNREF (data);
5578   return (ret < 0 ? -1 : 1);
5579 }
5580
5581 /*=*/
5582 /*** @} */
5583 /*=*/
5584 /***en
5585     @name Obsolete functions
5586 */
5587 /***ja
5588     @name Obsolete ¤Ê´Ø¿ô
5589 */
5590 /*** @{ */
5591
5592 /*=*/
5593 /***en
5594     @brief Get a list of variables of an input method (obsolete).
5595
5596     This function is obsolete.  Use minput_get_variable () instead.
5597
5598     The minput_get_variables () function returns a plist (#MPlist) of
5599     variables used to control the behavior of the input method
5600     specified by $LANGUAGE and $NAME.  The plist is @e well-formed
5601     (#m17nPlist) of the following format:
5602
5603 @verbatim
5604     (VARNAME (DOC-MTEXT DEFAULT-VALUE [ VALUE ... ] )
5605      VARNAME (DOC-MTEXT DEFAULT-VALUE [ VALUE ... ] )
5606      ...)
5607 @endverbatim
5608
5609     @c VARNAME is a symbol representing the variable name.
5610
5611     @c DOC-MTEXT is an M-text describing the variable.
5612
5613     @c DEFAULT-VALUE is the default value of the variable.  It is a
5614     symbol, integer, or M-text.
5615
5616     @c VALUEs (if any) specifies the possible values of the variable.
5617     If @c DEFAULT-VALUE is an integer, @c VALUE may be a plist (@c FROM
5618     @c TO), where @c FROM and @c TO specifies a range of possible
5619     values.
5620
5621     For instance, suppose an input method has the variables:
5622
5623     @li name:intvar, description:"value is an integer",
5624          initial value:0, value-range:0..3,10,20
5625
5626     @li name:symvar, description:"value is a symbol",
5627          initial value:nil, value-range:a, b, c, nil
5628
5629     @li name:txtvar, description:"value is an M-text",
5630          initial value:empty text, no value-range (i.e. any text)
5631
5632     Then, the returned plist is as follows.
5633
5634 @verbatim
5635     (intvar ("value is an integer" 0 (0 3) 10 20)
5636      symvar ("value is a symbol" nil a b c nil)
5637      txtvar ("value is an M-text" ""))
5638 @endverbatim
5639
5640     @return
5641     If the input method uses any variables, a pointer to #MPlist is
5642     returned.  As the plist is kept in the library, the caller must not
5643     modify nor free it.  If the input method does not use any
5644     variable, @c NULL is returned.  */
5645 /***ja
5646     @brief ÆþÎϥ᥽¥Ã¥É¤ÎÊÑ¿ô¥ê¥¹¥È¤òÆÀ¤ë.
5647
5648     ´Ø¿ô minput_get_variables () ¤Ï¡¢$LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ»ØÄꤵ
5649     ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤Î¿¶¤ëÉñ¤¤¤òÀ©¸æ¤¹¤ëÊÑ¿ô¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È
5650     (#MPlist) ¤òÊÖ¤¹¡£¤³¤Î¥ê¥¹¥È¤Ï @e well-formed ¤Ç¤¢¤ê(#m17nPlist) °Ê
5651     ²¼¤Î·Á¼°¤Ç¤¢¤ë¡£
5652
5653 @verbatim
5654     (VARNAME (DOC-MTEXT DEFAULT-VALUE [ VALUE ... ] )
5655      VARNAME (DOC-MTEXT DEFAULT-VALUE [ VALUE ... ] )
5656      ...)
5657 @endverbatim
5658
5659     @c VARNAME ¤ÏÊÑ¿ô¤Î̾Á°¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
5660
5661     @c DOC-MTEXT ¤ÏÊÑ¿ô¤òÀâÌÀ¤¹¤ë M-text ¤Ç¤¢¤ë¡£
5662
5663     @c DEFAULT-VALUE ¤ÏÊÑ¿ô¤Î¥Ç¥Õ¥©¥ë¥ÈÃͤǤ¢¤ê¡¢¥·¥ó¥Ü¥ë¡¢À°¿ô¤â¤·¤¯¤Ï
5664     M-text ¤Ç¤¢¤ë¡£
5665
5666     @c VALUE ¤Ï¡¢¤â¤·»ØÄꤵ¤ì¤Æ¤¤¤ì¤ÐÊÑ¿ô¤Î¼è¤êÆÀ¤ëÃͤò¼¨¤¹¡£¤â¤·
5667     @c DEFAULT-VALUE ¤¬À°¿ô¤Ê¤é¡¢ @c VALUE ¤Ï (@c FROM @c TO) ¤È¤¤¤¦·Á
5668     ¤Î¥ê¥¹¥È¤Ç¤âÎɤ¤¡£¤³¤Î¾ì¹ç @c FROM ¤È @c TO ¤Ï²Äǽ¤ÊÃͤÎÈϰϤò¼¨¤¹¡£
5669
5670     Îã¤È¤·¤Æ¡¢¤¢¤ëÆþÎϥ᥽¥Ã¥É¤¬¼¡¤Î¤è¤¦¤ÊÊÑ¿ô¤ò»ý¤Ä¾ì¹ç¤ò¹Í¤¨¤è¤¦¡£
5671
5672     @li name:intvar, ÀâÌÀ:"value is an integer",
5673         ½é´üÃÍ:0, ÃͤÎÈÏ°Ï:0..3,10,20
5674
5675     @li name:symvar, ÀâÌÀ:"value is a symbol",
5676          ½é´üÃÍ:nil, ÃͤÎÈÏ°Ï:a, b, c, nil
5677
5678     @li name:txtvar, ÀâÌÀ:"value is an M-text",
5679         ½é´üÃÍ:empty text, ÃͤÎÈϰϤʤ·(¤É¤ó¤Ê M-text ¤Ç¤â²Ä)
5680
5681     ¤³¤Î¾ì¹ç¡¢ÊÖ¤µ¤ì¤ë¥ê¥¹¥È¤Ï°Ê²¼¤Î¤è¤¦¤Ë¤Ê¤ë¡£
5682
5683 @verbatim
5684     (intvar ("value is an integer" 0 (0 3) 10 20)
5685      symvar ("value is a symbol" nil a b c nil)
5686      txtvar ("value is an M-text" ""))
5687 @endverbatim
5688
5689     @return 
5690     ÆþÎϥ᥽¥Ã¥É¤¬²¿¤é¤«¤ÎÊÑ¿ô¤ò»ÈÍѤ·¤Æ¤¤¤ì¤Ð #MPlist ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
5691     ÊÖ¤µ¤ì¤ë¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ï¥é¥¤¥Ö¥é¥ê¤Ë¤è¤Ã¤Æ´ÉÍý¤µ¤ì¤Æ¤ª¤ê¡¢¸Æ¤Ó½Ð¤·Â¦¤ÇÊѹ¹¤·¤¿¤ê²òÊü¤·¤¿¤ê¤·¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
5692     ÆþÎϥ᥽¥Ã¥É¤¬ÊÑ¿ô¤ò°ìÀÚ»ÈÍѤ·¤Æ¤Ê¤±¤ì¤Ð¡¢@c NULL ¤òÊÖ¤¹¡£  */
5693
5694 MPlist *
5695 minput_get_variables (MSymbol language, MSymbol name)
5696 {
5697   MInputMethodInfo *im_info;
5698   MPlist *vars;
5699
5700   MINPUT__INIT ();
5701
5702   im_info = get_im_info (language, name, Mnil, Mvariable);
5703   if (! im_info || ! im_info->configured_vars)
5704     return NULL;
5705
5706   M17N_OBJECT_UNREF (im_info->bc_vars);
5707   im_info->bc_vars = mplist ();
5708   MPLIST_DO (vars, im_info->configured_vars)
5709     {
5710       MPlist *plist = MPLIST_PLIST (vars);
5711       MPlist *elt = mplist ();
5712
5713       mplist_push (im_info->bc_vars, Mplist, elt);
5714       mplist_add (elt, Msymbol, MPLIST_SYMBOL (plist));
5715       elt = MPLIST_NEXT (elt);
5716       mplist_set (elt, Mplist, mplist_copy (MPLIST_NEXT (plist)));
5717       M17N_OBJECT_UNREF (elt);
5718     }
5719   return im_info->bc_vars;
5720 }
5721
5722 /*=*/
5723
5724 /***en
5725     @brief Set the initial value of an input method variable.
5726
5727     The minput_set_variable () function sets the initial value of
5728     input method variable $VARIABLE to $VALUE for the input method
5729     specified by $LANGUAGE and $NAME.
5730
5731     By default, the initial value is 0.
5732
5733     This setting gets effective in a newly opened input method.
5734
5735     @return
5736     If the operation was successful, 0 is returned.  Otherwise -1 is
5737     returned, and #merror_code is set to #MERROR_IM.  */
5738 /***ja
5739     @brief ÆþÎϥ᥽¥Ã¥ÉÊÑ¿ô¤Î½é´üÃͤòÀßÄꤹ¤ë.
5740
5741     ´Ø¿ô minput_set_variable () ¤Ï¡¢$LANGUAGE ¤È $NAME 
5742     ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ÎÆþÎϥ᥽¥Ã¥ÉÊÑ¿ô $VARIABLE
5743     ¤Î½é´üÃͤò¡¢ $VALUE ¤ËÀßÄꤹ¤ë¡£
5744
5745     ¥Ç¥Õ¥©¥ë¥È¤Î½é´üÃͤϠ0 ¤Ç¤¢¤ë¡£
5746
5747     ¤³¤ÎÀßÄê¤Ï¡¢¿·¤·¤¯¥ª¡¼¥×¥ó¤µ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤«¤éÍ­¸ú¤È¤Ê¤ë¡£
5748
5749     @return
5750     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤·¡¢
5751     #merror_code ¤ò #MERROR_IM ¤ËÀßÄꤹ¤ë¡£  */
5752
5753 int
5754 minput_set_variable (MSymbol language, MSymbol name,
5755                      MSymbol variable, void *value)
5756 {
5757   MPlist *plist, *pl;
5758   MInputMethodInfo *im_info;
5759   int ret;
5760
5761   MINPUT__INIT ();
5762
5763   if (variable == Mnil)
5764     MERROR (MERROR_IM, -1);
5765   plist = minput_get_variable (language, name, variable);
5766   plist = MPLIST_PLIST (plist);
5767   plist = MPLIST_NEXT (plist);
5768   pl = mplist ();
5769   mplist_add (pl, MPLIST_KEY (plist), value);
5770   ret = minput_config_variable (language, name, variable, pl);
5771   M17N_OBJECT_UNREF (pl);
5772   if (ret == 0)
5773     {
5774       im_info = get_im_info (language, name, Mnil, Mvariable);
5775       im_info->tick = 0;
5776     }
5777   return ret;
5778 }
5779
5780 /*=*/
5781
5782 /***en
5783     @brief Get information about input method commands.
5784
5785     The minput_get_commands () function returns information about
5786     input method commands of the input method specified by $LANGUAGE
5787     and $NAME.  An input method command is a pseudo key event to which
5788     one or more actual input key sequences are assigned.
5789
5790     There are two kinds of commands, global and local.  Global
5791     commands are used by multiple input methods for the same purpose,
5792     and have global key assignments.  Local commands are used only by
5793     a specific input method, and have only local key assignments.
5794
5795     Each input method may locally change key assignments for global
5796     commands.  The global key assignment for a global command is
5797     effective only when the current input method does not have local
5798     key assignments for that command.
5799
5800     If $NAME is #Mnil, information about global commands is returned.
5801     In this case $LANGUAGE is ignored.
5802
5803     If $NAME is not #Mnil, information about those commands that have
5804     local key assignments in the input method specified by $LANGUAGE
5805     and $NAME is returned.
5806
5807     @return
5808     If no input method commands are found, this function returns @c NULL.
5809
5810     Otherwise, a pointer to a plist is returned.  The key of each
5811     element in the plist is a symbol representing a command, and the
5812     value is a plist of the form COMMAND-INFO described below.
5813
5814     The first element of COMMAND-INFO has the key #Mtext, and the
5815     value is an M-text describing the command.
5816
5817     If there are no more elements, that means no key sequences are
5818     assigned to the command.  Otherwise, each of the remaining
5819     elements has the key #Mplist, and the value is a plist whose keys are
5820     #Msymbol and values are symbols representing input keys, which are
5821     currently assigned to the command.
5822
5823     As the returned plist is kept in the library, the caller must not
5824     modify nor free it.  */
5825 /***ja
5826     @brief ÆþÎϥ᥽¥Ã¥É¤Î¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë.
5827
5828     ´Ø¿ô minput_get_commands () ¤Ï¡¢ $LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ»ØÄꤵ
5829     ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ÎÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£ÆþÎϥ᥽¥Ã
5830     ¥É¥³¥Þ¥ó¥É¤È¤Ï¡¢µ¿»÷¥­¡¼¥¤¥Ù¥ó¥È¤Ç¤¢¤ê¡¢¤½¤ì¤¾¤ì¤Ë£±¤Ä°Ê¾å¤Î¼ÂºÝ¤Î
5831     ÆþÎÏ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤¬³ä¤êÅö¤Æ¤é¤ì¤Æ¤¤¤ë¤â¤Î¤ò»Ø¤¹¡£
5832
5833     ¥³¥Þ¥ó¥É¤Ë¤Ï¥°¥í¡¼¥Ð¥ë¤È¥í¡¼¥«¥ë¤Î£²¼ïÎब¤¢¤ë¡£¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É
5834     ¤ÏÊ£¿ô¤ÎÆþÎϥ᥽¥Ã¥É¤Ë¤ª¤¤¤Æ¡¢Æ±¤¸ÌÜŪ¤Ç¡¢¥°¥í¡¼¥Ð¥ë¤Ê¥­¡¼³ä¤êÅö¤Æ
5835     ¤ÇÍѤ¤¤é¤ì¤ë¡£¥í¡¼¥«¥ë¥³¥Þ¥ó¥É¤ÏÆÃÄê¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Î¤ß¡¢¥í¡¼¥«¥ë
5836     ¤Ê¥­¡¼³äÅö¤Ç»ÈÍѤµ¤ì¤ë¡£
5837
5838     ¸Ä¡¹¤ÎÆþÎϥ᥽¥Ã¥É¤Ï¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É¤Î¥­¡¼³äÅö¤òÊѹ¹¤¹¤ë¤³¤È¤â¤Ç
5839     ¤­¤ë¡£¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥ÉÍѤΥ°¥í¡¼¥Ð¥ë¥­¡¼³ä¤êÅö¤Æ¤Ï¡¢»ÈÍѤ¹¤ëÆþÎÏ
5840     ¥á¥½¥Ã¥É¤Ë¤ª¤¤¤Æ¤½¤Î¥³¥Þ¥ó¥ÉÍÑ¤Î¥í¡¼¥«¥ë¤Ê¥­¡¼³äÅö¤¬Â¸ºß¤·¤Ê¤¤¾ì¹ç
5841     ¤Ë¤Î¤ßÍ­¸ú¤Ç¤¢¤ë¡£
5842
5843     $NAME ¤¬ #Mnil ¤Ç¤¢¤ì¤Ð¡¢¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£¤³¤Î
5844     ¾ì¹ç¡¢$LANGUAGE ¤Ï̵»ë¤µ¤ì¤ë¡£
5845
5846     $NAME ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢$LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤ëÆþ
5847     Îϥ᥽¥Ã¥É¤ËÃÖ¤±¤ë¥í¡¼¥«¥ë¤Ê¥­¡¼³ä¤êÅö¤Æ¤ò»ý¤Ä¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó
5848     ¤òÊÖ¤¹¡£
5849
5850     @return
5851     ÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï @c NULL ¤òÊÖ¤¹¡£
5852
5853     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¥ê¥¹¥È¤Î³ÆÍ×ÁǤÎ
5854     ¥­¡¼¤Ï¸Ä¡¹¤Î¥³¥Þ¥ó¥É¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢Ãͤϲ¼µ­¤Î COMMAND-INFO
5855     ¤Î·Á¼°¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ç¤¢¤ë¡£
5856
5857     COMMAND-INFO ¤ÎÂè°ìÍ×ÁǤΥ­¡¼¤Ï #Mtext ¤Þ¤¿¤Ï #Msymbol ¤Ç¤¢¤ë¡£¥­¡¼
5858     ¤¬ #Mtext ¤Ê¤é¡¢ÃͤϤ½¤Î¥³¥Þ¥ó¥É¤òÀâÌÀ¤¹¤ë M-text ¤Ç¤¢¤ë¡£¥­¡¼¤¬
5859     #Msymbol ¤Ê¤éÃͤϠ#Mnil ¤Ç¤¢¤ê¡¢¤³¤Î¥³¥Þ¥ó¥É¤ÏÀâÌÀ¥Æ¥­¥¹¥È¤ò»ý¤¿¤Ê
5860     ¤¤¤³¤È¤Ë¤Ê¤ë¡£
5861
5862     ¤½¤ì°Ê³°¤ÎÍ×ÁǤ¬Ìµ¤±¤ì¤Ð¡¢¤³¤Î¥³¥Þ¥ó¥É¤ËÂФ·¤Æ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤¬³ä
5863     ¤êÅö¤Æ¤é¤ì¤Æ¤¤¤Ê¤¤¤³¤È¤ò°ÕÌ£¤¹¤ë¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢»Ä¤ê¤Î³ÆÍ×ÁǤϥ­
5864     ¡¼¤È¤·¤Æ#Mplist ¤ò¡¢ÃͤȤ·¤Æ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ò»ý¤Ä¡£¤³¤Î¥×¥í¥Ñ¥Æ¥£
5865     ¥ê¥¹¥È¤Î¥­¡¼¤Ï #Msymbol ¤Ç¤¢¤ê¡¢Ãͤϸ½ºß¤½¤Î¥³¥Þ¥ó¥É¤Ë³ä¤êÅö¤Æ¤é¤ì
5866     ¤Æ¤¤¤ëÆþÎÏ¥­¡¼¤òɽ¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
5867
5868     ÊÖ¤µ¤ì¤ë¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ï¥é¥¤¥Ö¥é¥ê¤Ë¤è¤Ã¤Æ´ÉÍý¤µ¤ì¤Æ¤ª¤ê¡¢¸Æ¤Ó½Ð
5869     ¤·Â¦¤ÇÊѹ¹¤·¤¿¤ê²òÊü¤·¤¿¤ê¤·¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£*/
5870
5871 MPlist *
5872 minput_get_commands (MSymbol language, MSymbol name)
5873 {
5874   MInputMethodInfo *im_info;
5875   MPlist *cmds;
5876
5877   MINPUT__INIT ();
5878
5879   im_info = get_im_info (language, name, Mnil, Mcommand);
5880   if (! im_info || ! im_info->configured_vars)
5881     return NULL;
5882   M17N_OBJECT_UNREF (im_info->bc_cmds);
5883   im_info->bc_cmds = mplist ();
5884   MPLIST_DO (cmds, im_info->configured_cmds)
5885     {
5886       MPlist *plist = MPLIST_PLIST (cmds);
5887       MPlist *elt = mplist ();
5888
5889       mplist_push (im_info->bc_cmds, Mplist, elt);
5890       mplist_add (elt, MPLIST_SYMBOL (plist),
5891                   mplist_copy (MPLIST_NEXT (plist)));
5892       M17N_OBJECT_UNREF (elt);
5893     }
5894   return im_info->bc_cmds;
5895 }
5896
5897 /*=*/
5898
5899 /***en
5900     @brief Assign a key sequence to an input method command (obsolete).
5901
5902     This function is obsolete.  Use minput_config_command () instead.
5903
5904     The minput_assign_command_keys () function assigns input key
5905     sequence $KEYSEQ to input method command $COMMAND for the input
5906     method specified by $LANGUAGE and $NAME.  If $NAME is #Mnil, the
5907     key sequence is assigned globally no matter what $LANGUAGE is.
5908     Otherwise the key sequence is assigned locally.
5909
5910     Each element of $KEYSEQ must have the key $Msymbol and the value
5911     must be a symbol representing an input key.
5912
5913     $KEYSEQ may be @c NULL, in which case, all assignments are deleted
5914     globally or locally.
5915
5916     This assignment gets effective in a newly opened input method.
5917
5918     @return
5919     If the operation was successful, 0 is returned.  Otherwise -1 is
5920     returned, and #merror_code is set to #MERROR_IM.  */
5921 /***ja
5922     @brief ÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤Ë¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤ò³ä¤êÅö¤Æ¤ë.
5923
5924     ´Ø¿ô minput_assign_command_keys () ¤Ï¡¢ $LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ
5925     »ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥ÉÍѤÎÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É $COMMAND ¤ËÂФ·¤Æ¡¢
5926     ÆþÎÏ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹ $KEYSEQ ¤ò³ä¤êÅö¤Æ¤ë¡£ $NAME ¤¬ #Mnil ¤Ê¤é¤Ð¡¢
5927     $LANGUAGE ¤Ë´Ø·¸¤Ê¤¯¡¢ÆþÎÏ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤Ï¥°¥í¡¼¥Ð¥ë¤Ë³ä¤êÅö¤Æ¤é
5928     ¤ì¤ë¡£¤½¤¦¤Ç¤Ê¤ì¤Ð¡¢³ä¤êÅö¤Æ¤Ï¥í¡¼¥«¥ë¤Ç¤¢¤ë¡£
5929
5930     $KEYSEQ ¤Î³ÆÍ×ÁǤϥ­¡¼¤È¤·¤Æ $Msymbol ¤ò¡¢ÃͤȤ·¤ÆÆþÎÏ¥­¡¼¤òɽ¤¹¥·
5931     ¥ó¥Ü¥ë¤ò»ý¤¿¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
5932
5933     $KEYSEQ ¤Ï @c NULL ¤Ç¤â¤è¤¤¡£¤³¤Î¾ì¹ç¡¢¥°¥í¡¼¥Ð¥ë¤â¤·¤¯¤Ï¥í¡¼¥«¥ë¤Ê
5934     ¤¹¤Ù¤Æ¤Î³ä¤êÅö¤Æ¤¬¾Ãµî¤µ¤ì¤ë¡£
5935
5936     ¤³¤Î³ä¤êÅö¤Æ¤Ï¡¢³ä¤êÅö¤Æ°Ê¹ß¿·¤·¤¯¥ª¡¼¥×¥ó¤µ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤«¤éÍ­
5937     ¸ú¤Ë¤Ê¤ë¡£
5938
5939     @return ½èÍý¤¬À®¸ù¤¹¤ì¤Ð 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤·¡¢
5940     #merror_code ¤ò #MERROR_IM ¤ËÀßÄꤹ¤ë¡£  */
5941
5942 int
5943 minput_assign_command_keys (MSymbol language, MSymbol name,
5944                             MSymbol command, MPlist *keyseq)
5945 {
5946   int ret;
5947
5948   MINPUT__INIT ();
5949
5950   if (command == Mnil)
5951     MERROR (MERROR_IM, -1);
5952   if (keyseq)
5953     {
5954       MPlist *plist;
5955
5956       if  (! check_command_keyseq (keyseq))
5957         MERROR (MERROR_IM, -1);
5958       plist = mplist ();
5959       mplist_add (plist, Mplist, keyseq);
5960       keyseq = plist;
5961     }  
5962   else
5963     keyseq = mplist ();
5964   ret = minput_config_command (language, name, command, keyseq);
5965   M17N_OBJECT_UNREF (keyseq);
5966   return ret;
5967 }
5968
5969 /*** @} */ 
5970 /*** @} */
5971 /*=*/
5972 /*** @addtogroup m17nDebug */
5973 /*=*/
5974 /*** @{  */
5975 /*=*/
5976
5977 /***en
5978     @brief Dump an input method.
5979
5980     The mdebug_dump_im () function prints the input method $IM in a
5981     human readable way to the stderr.  $INDENT specifies how many
5982     columns to indent the lines but the first one.
5983
5984     @return
5985     This function returns $IM.  */
5986 /***ja
5987     @brief ÆþÎϥ᥽¥Ã¥É¤ò¥À¥ó¥×¤¹¤ë.
5988
5989     ´Ø¿ô mdebug_dump_im () ¤ÏÆþÎϥ᥽¥Ã¥É $IM ¤ò stderr 
5990     ¤Ë¿Í´Ö¤Ë²ÄÆɤʷÁ¤Ç°õºþ¤¹¤ë¡£$INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£
5991
5992     @return
5993     ¤³¤Î´Ø¿ô¤Ï $IM ¤òÊÖ¤¹¡£  */
5994
5995 MInputMethod *
5996 mdebug_dump_im (MInputMethod *im, int indent)
5997 {
5998   MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
5999   char *prefix;
6000
6001   prefix = (char *) alloca (indent + 1);
6002   memset (prefix, 32, indent);
6003   prefix[indent] = '\0';
6004
6005   fprintf (stderr, "(input-method %s %s ", msymbol_name (im->language),
6006            msymbol_name (im->name));
6007   mdebug_dump_mtext (im_info->title, 0, 0);
6008   if (im->name != Mnil)
6009     {
6010       MPlist *state;
6011
6012       MPLIST_DO (state, im_info->states)
6013         {
6014           fprintf (stderr, "\n%s  ", prefix);
6015           dump_im_state (MPLIST_VAL (state), indent + 2);
6016         }
6017     }
6018   fprintf (stderr, ")");
6019   return im;
6020 }
6021
6022 /*** @} */ 
6023
6024 /*
6025   Local Variables:
6026   coding: euc-japan
6027   End:
6028 */