(marker_code): New arg surrounding. Callers changed.
[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 (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
2877           if (pos == 0
2878               || ! (prop = mtext_get_property (ic->preedit, pos - 1,
2879                                                Mcandidate_list)))
2880             continue;
2881           if (MPLIST_SYMBOL_P (args))
2882             {
2883               code = marker_code (MPLIST_SYMBOL (args), 0);
2884               if (code < 0)
2885                 continue;
2886             }
2887           else
2888             code = -1;
2889           idx = (int) mtext_get_prop (ic->preedit, pos - 1, Mcandidate_index);
2890           group = find_candidates_group (mtext_property_value (prop), idx,
2891                                          &start, &end, &gindex);
2892
2893           if (code != '[' && code != ']')
2894             {
2895               idx = (start
2896                      + (code >= 0
2897                         ? new_index (NULL, ic->candidate_index - start,
2898                                      end - start - 1, MPLIST_SYMBOL (args),
2899                                      NULL)
2900                         : MPLIST_INTEGER (args)));
2901               if (idx < 0)
2902                 {
2903                   find_candidates_group (mtext_property_value (prop), -1,
2904                                          NULL, &end, NULL);
2905                   idx = end - 1;
2906                 }
2907               else if (idx >= end
2908                        && MPLIST_TAIL_P (MPLIST_NEXT (group)))
2909                 idx = 0;
2910             }
2911           else
2912             {
2913               int ingroup_index = idx - start;
2914               int len;
2915
2916               group = mtext_property_value (prop);
2917               len = mplist_length (group);
2918               if (code == '[')
2919                 {
2920                   gindex--;
2921                   if (gindex < 0)
2922                     gindex = len - 1;;
2923                 }
2924               else
2925                 {
2926                   gindex++;
2927                   if (gindex >= len)
2928                     gindex = 0;
2929                 }
2930               for (idx = 0; gindex > 0; gindex--, group = MPLIST_NEXT (group))
2931                 idx += (MPLIST_MTEXT_P (group)
2932                         ? mtext_nchars (MPLIST_MTEXT (group))
2933                         : mplist_length (MPLIST_PLIST (group)));
2934               len = (MPLIST_MTEXT_P (group)
2935                      ? mtext_nchars (MPLIST_MTEXT (group))
2936                      : mplist_length (MPLIST_PLIST (group)));
2937               if (ingroup_index >= len)
2938                 ingroup_index = len - 1;
2939               idx += ingroup_index;
2940             }
2941           update_candidate (ic, prop, idx);
2942         }
2943       else if (name == Mshow)
2944         ic->candidate_show = 1;
2945       else if (name == Mhide)
2946         ic->candidate_show = 0;
2947       else if (name == Mdelete)
2948         {
2949           int len = mtext_nchars (ic->preedit);
2950           int pos;
2951           int to;
2952
2953           if (MPLIST_SYMBOL_P (args)
2954               && (pos = surrounding_pos (MPLIST_SYMBOL (args))) != 0)
2955             {
2956               delete_surrounding_text (ic, pos);
2957             }
2958           else
2959             {
2960               to = (MPLIST_SYMBOL_P (args)
2961                     ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
2962                                  ic->preedit)
2963                     : MPLIST_INTEGER (args));
2964               if (to < 0)
2965                 to = 0;
2966               else if (to > len)
2967                 to = len;
2968               MDEBUG_PRINT1 ("(%d)", to - ic->cursor_pos);
2969               if (to < ic->cursor_pos)
2970                 preedit_delete (ic, to, ic->cursor_pos);
2971               else if (to > ic->cursor_pos)
2972                 preedit_delete (ic, ic->cursor_pos, to);
2973             }
2974         }
2975       else if (name == Mmove)
2976         {
2977           int len = mtext_nchars (ic->preedit);
2978           int pos
2979             = (MPLIST_SYMBOL_P (args)
2980                ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
2981                             ic->preedit)
2982                : MPLIST_INTEGER (args));
2983
2984           if (pos < 0)
2985             pos = 0;
2986           else if (pos > len)
2987             pos = len;
2988           if (pos != ic->cursor_pos)
2989             {
2990               ic->cursor_pos = pos;
2991               ic->preedit_changed = 1;
2992             }
2993         }
2994       else if (name == Mmark)
2995         {
2996           int code = marker_code (MPLIST_SYMBOL (args), 0);
2997
2998           if (code < 0)
2999             mplist_put (ic_info->markers, MPLIST_SYMBOL (args),
3000                         (void *) ic->cursor_pos);
3001         }
3002       else if (name == Mpushback)
3003         {
3004           if (MPLIST_INTEGER_P (args))
3005             {
3006               int num = MPLIST_INTEGER (args);
3007
3008               if (num > 0)
3009                 ic_info->key_head -= num;
3010               else
3011                 ic_info->key_head = num;
3012               if (ic_info->key_head > ic_info->used)
3013                 ic_info->key_head = ic_info->used;
3014             }
3015           else if (MPLIST_MTEXT_P (args))
3016             {
3017               MText *mt = MPLIST_MTEXT (args);
3018               int i, len = mtext_nchars (mt);
3019               MSymbol key;
3020
3021               ic_info->key_head--;
3022               for (i = 0; i < len; i++)
3023                 {
3024                   key = one_char_symbol[MTEXT_DATA (mt)[i]];
3025                   if (ic_info->key_head + i < ic_info->used)
3026                     ic_info->keys[ic_info->key_head + i] = key;
3027                   else
3028                     MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
3029                 }
3030             }
3031           else
3032             {
3033               MPlist *plist = MPLIST_PLIST (args), *pl;
3034               int i = 0;
3035               MSymbol key;
3036
3037               ic_info->key_head--;
3038
3039               MPLIST_DO (pl, plist)
3040                 {
3041                   key = MPLIST_SYMBOL (pl);
3042                   if (ic_info->key_head < ic_info->used)
3043                     ic_info->keys[ic_info->key_head + i] = key;
3044                   else
3045                     MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
3046                   i++;
3047                 }
3048             }
3049         }
3050       else if (name == Mcall)
3051         {
3052           MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
3053           MIMExternalFunc func = NULL;
3054           MSymbol module, func_name;
3055           MPlist *func_args, *val;
3056           int ret = 0;
3057
3058           module = MPLIST_SYMBOL (args);
3059           args = MPLIST_NEXT (args);
3060           func_name = MPLIST_SYMBOL (args);
3061
3062           if (im_info->externals)
3063             {
3064               MIMExternalModule *external
3065                 = (MIMExternalModule *) mplist_get (im_info->externals,
3066                                                     module);
3067               if (external)
3068                 func = (MIMExternalFunc) mplist_get (external->func_list,
3069                                                      func_name);
3070             }
3071           if (! func)
3072             continue;
3073           func_args = mplist ();
3074           mplist_add (func_args, Mt, ic);
3075           MPLIST_DO (args, MPLIST_NEXT (args))
3076             {
3077               int code;
3078
3079               if (MPLIST_KEY (args) == Msymbol
3080                   && MPLIST_KEY (args) != Mnil
3081                   && (code = marker_code (MPLIST_SYMBOL (args), 0)) >= 0)
3082                 {
3083                   code = new_index (ic, ic->cursor_pos, 
3084                                     mtext_nchars (ic->preedit),
3085                                     MPLIST_SYMBOL (args), ic->preedit);
3086                   mplist_add (func_args, Minteger, (void *) code);
3087                 }
3088               else
3089                 mplist_add (func_args, MPLIST_KEY (args), MPLIST_VAL (args));
3090             }
3091           val = (func) (func_args);
3092           M17N_OBJECT_UNREF (func_args);
3093           if (val && ! MPLIST_TAIL_P (val))
3094             ret = take_action_list (ic, val);
3095           M17N_OBJECT_UNREF (val);
3096           if (ret < 0)
3097             return ret;
3098         }
3099       else if (name == Mshift)
3100         {
3101           shift_state (ic, MPLIST_SYMBOL (args));
3102         }
3103       else if (name == Mundo)
3104         {
3105           int intarg = (MPLIST_TAIL_P (args)
3106                         ? ic_info->used - 2
3107                         : integer_value (ic, args, NULL, 0));
3108
3109           mtext_reset (ic->preedit);
3110           mtext_reset (ic_info->preedit_saved);
3111           mtext_reset (ic->produced);
3112           M17N_OBJECT_UNREF (ic_info->vars);
3113           ic_info->vars = mplist_copy (ic_info->vars_saved);
3114           ic->cursor_pos = ic_info->state_pos = 0;
3115           ic_info->state_key_head = ic_info->key_head = 0;
3116
3117           shift_state (ic, Mnil);
3118           if (intarg < 0)
3119             {
3120               if (MPLIST_TAIL_P (args))
3121                 {
3122                   ic_info->used = 0;
3123                   return -1;
3124                 }
3125               ic_info->used += intarg;
3126             }
3127           else
3128             ic_info->used = intarg;
3129           break;
3130         }
3131       else if (name == Mset || name == Madd || name == Msub
3132                || name == Mmul || name == Mdiv)
3133         {
3134           MSymbol sym = MPLIST_SYMBOL (args);
3135           int val1, val2;
3136           MPlist *value;
3137           char *op;
3138
3139           val1 = integer_value (ic, args, &value, 0);
3140           args = MPLIST_NEXT (args);
3141           val2 = resolve_expression (ic, args);
3142           if (name == Mset)
3143             val1 = val2, op = "=";
3144           else if (name == Madd)
3145             val1 += val2, op = "+=";
3146           else if (name == Msub)
3147             val1 -= val2, op = "-=";
3148           else if (name == Mmul)
3149             val1 *= val2, op = "*=";
3150           else
3151             val1 /= val2, op = "/=";
3152           MDEBUG_PRINT4 ("(%s %s 0x%X(%d))",
3153                          MSYMBOL_NAME (sym), op, val1, val1);
3154           if (value)
3155             mplist_set (value, Minteger, (void *) val1);
3156         }
3157       else if (name == Mequal || name == Mless || name == Mgreater
3158                || name == Mless_equal || name == Mgreater_equal)
3159         {
3160           int val1, val2;
3161           MPlist *actions1, *actions2;
3162           int ret = 0;
3163
3164           val1 = resolve_expression (ic, args);
3165           args = MPLIST_NEXT (args);
3166           val2 = resolve_expression (ic, args);
3167           args = MPLIST_NEXT (args);
3168           actions1 = MPLIST_PLIST (args);
3169           args = MPLIST_NEXT (args);
3170           if (MPLIST_TAIL_P (args))
3171             actions2 = NULL;
3172           else
3173             actions2 = MPLIST_PLIST (args);
3174           MDEBUG_PRINT3 ("(%d %s %d)? ", val1, MSYMBOL_NAME (name), val2);
3175           if (name == Mequal ? val1 == val2
3176               : name == Mless ? val1 < val2
3177               : name == Mgreater ? val1 > val2
3178               : name == Mless_equal ? val1 <= val2
3179               : val1 >= val2)
3180             {
3181               MDEBUG_PRINT ("ok");
3182               ret = take_action_list (ic, actions1);
3183             }
3184           else
3185             {
3186               MDEBUG_PRINT ("no");
3187               if (actions2)
3188                 ret = take_action_list (ic, actions2);
3189             }
3190           if (ret < 0)
3191             return ret;
3192         }
3193       else if (name == Mcond)
3194         {
3195           int idx = 0;
3196
3197           MPLIST_DO (args, args)
3198             {
3199               MPlist *cond;
3200
3201               idx++;
3202               if (! MPLIST_PLIST (args))
3203                 continue;
3204               cond = MPLIST_PLIST (args);
3205               if (resolve_expression (ic, cond) != 0)
3206                 {
3207                   MDEBUG_PRINT1 ("(%dth)", idx);
3208                   if (take_action_list (ic, MPLIST_NEXT (cond)) < 0)
3209                     return -1;;
3210                   break;
3211                 }
3212             }
3213         }
3214       else if (name == Mcommit)
3215         {
3216           preedit_commit (ic);
3217         }
3218       else if (name == Munhandle)
3219         {
3220           preedit_commit (ic);
3221           return -1;
3222         }
3223       else
3224         {
3225           MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
3226           MPlist *actions;
3227
3228           if (im_info->macros
3229               && (actions = mplist_get (im_info->macros, name)))
3230             {
3231               if (take_action_list (ic, actions) < 0)
3232                 return -1;
3233             };
3234         }
3235     }
3236
3237   if (ic->candidate_list)
3238     {
3239       M17N_OBJECT_UNREF (ic->candidate_list);
3240       ic->candidate_list = NULL;
3241     }
3242   if (ic->cursor_pos > 0
3243       && (prop = mtext_get_property (ic->preedit, ic->cursor_pos - 1,
3244                                      Mcandidate_list)))
3245     {
3246       ic->candidate_list = mtext_property_value (prop);
3247       M17N_OBJECT_REF (ic->candidate_list);
3248       ic->candidate_index
3249         = (int) mtext_get_prop (ic->preedit, ic->cursor_pos - 1,
3250                                 Mcandidate_index);
3251       ic->candidate_from = mtext_property_start (prop);
3252       ic->candidate_to = mtext_property_end (prop);
3253     }
3254
3255   if (candidate_list != ic->candidate_list)
3256     ic->candidates_changed |= MINPUT_CANDIDATES_LIST_CHANGED;
3257   if (candidate_index != ic->candidate_index)
3258     ic->candidates_changed |= MINPUT_CANDIDATES_INDEX_CHANGED;
3259   if (candidate_show != ic->candidate_show)
3260     ic->candidates_changed |= MINPUT_CANDIDATES_SHOW_CHANGED;    
3261   return 0;
3262 }
3263
3264
3265 /* Handle the input key KEY in the current state and map specified in
3266    the input context IC.  If KEY is handled correctly, return 0.
3267    Otherwise, return -1.  */
3268
3269 static int
3270 handle_key (MInputContext *ic)
3271 {
3272   MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
3273   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
3274   MIMMap *map = ic_info->map;
3275   MIMMap *submap = NULL;
3276   MSymbol key = ic_info->keys[ic_info->key_head];
3277   MSymbol alias = Mnil;
3278   int i;
3279
3280   MDEBUG_PRINT2 ("  [IM] handle `%s' in state %s", 
3281                  msymbol_name (key), MSYMBOL_NAME (ic_info->state->name));
3282
3283   if (map->submaps)
3284     {
3285       submap = mplist_get (map->submaps, key);
3286       alias = key;
3287       while (! submap
3288              && (alias = msymbol_get (alias, M_key_alias))
3289              && alias != key)
3290         submap = mplist_get (map->submaps, alias);
3291     }
3292
3293   if (submap)
3294     {
3295       if (! alias || alias == key)
3296         MDEBUG_PRINT (" submap-found");
3297       else
3298         MDEBUG_PRINT1 (" submap-found (by alias `%s')", MSYMBOL_NAME (alias));
3299       mtext_cpy (ic->preedit, ic_info->preedit_saved);
3300       ic->preedit_changed = 1;
3301       ic->cursor_pos = ic_info->state_pos;
3302       ic_info->key_head++;
3303       ic_info->map = map = submap;
3304       if (map->map_actions)
3305         {
3306           MDEBUG_PRINT (" map-actions:");
3307           if (take_action_list (ic, map->map_actions) < 0)
3308             {
3309               MDEBUG_PRINT ("\n");
3310               return -1;
3311             }
3312         }
3313       else if (map->submaps)
3314         {
3315           for (i = ic_info->state_key_head; i < ic_info->key_head; i++)
3316             {
3317               MSymbol key = ic_info->keys[i];
3318               char *name = msymbol_name (key);
3319
3320               if (! name[0] || ! name[1])
3321                 mtext_ins_char (ic->preedit, ic->cursor_pos++, name[0], 1);
3322             }
3323         }
3324
3325       /* If this is the terminal map or we have shifted to another
3326          state, perform branch actions (if any).  */
3327       if (! map->submaps || map != ic_info->map)
3328         {
3329           if (map->branch_actions)
3330             {
3331               MDEBUG_PRINT (" branch-actions:");
3332               if (take_action_list (ic, map->branch_actions) < 0)
3333                 {
3334                   MDEBUG_PRINT ("\n");
3335                   return -1;
3336                 }
3337             }
3338           /* If MAP is still not the root map, shift to the current
3339              state.  */
3340           if (ic_info->map != ic_info->state->map)
3341             shift_state (ic, ic_info->state->name);
3342         }
3343     }
3344   else
3345     {
3346       /* MAP can not handle KEY.  */
3347
3348       /* If MAP is the root map of the initial state, it means that
3349          the current input method can not handle KEY.  */
3350       if (map == ((MIMState *) MPLIST_VAL (im_info->states))->map)
3351         {
3352           MDEBUG_PRINT (" unhandled\n");
3353           return -1;
3354         }
3355
3356       if (map != ic_info->state->map)
3357         {
3358           /* If MAP is not the root map... */
3359           /* If MAP has branch actions, perform them.  */
3360           if (map->branch_actions)
3361             {
3362               MDEBUG_PRINT (" branch-actions:");
3363               if (take_action_list (ic, map->branch_actions) < 0)
3364                 {
3365                   MDEBUG_PRINT ("\n");
3366                   return -1;
3367                 }
3368             }
3369           /* If MAP is still not the root map, shift to the current
3370              state. */
3371           if (ic_info->map != ic_info->state->map)
3372             shift_state (ic, ic_info->state->name);
3373         }
3374       else
3375         {
3376           /* MAP is the root map, perform branch actions (if any) or
3377              shift to the initial state.  */
3378           if (map->branch_actions)
3379             {
3380               MDEBUG_PRINT (" branch-actions:");
3381               if (take_action_list (ic, map->branch_actions) < 0)
3382                 {
3383                   MDEBUG_PRINT ("\n");
3384                   return -1;
3385                 }
3386             }
3387           else
3388             shift_state (ic, Mnil);
3389         }
3390     }
3391   MDEBUG_PRINT ("\n");
3392   return 0;
3393 }
3394
3395 /* Initialize IC->ic_info.  */
3396
3397 static void
3398 init_ic_info (MInputContext *ic)
3399 {
3400   MInputMethodInfo *im_info = ic->im->info;
3401   MInputContextInfo *ic_info = ic->info;
3402   MPlist *plist;
3403   
3404   MLIST_INIT1 (ic_info, keys, 8);;
3405
3406   ic_info->markers = mplist ();
3407
3408   ic_info->vars = mplist ();
3409   if (im_info->configured_vars)
3410     MPLIST_DO (plist, im_info->configured_vars)
3411       {
3412         MPlist *pl = MPLIST_PLIST (plist);
3413         MSymbol name = MPLIST_SYMBOL (pl);
3414
3415         pl = MPLIST_NEXT (MPLIST_NEXT (MPLIST_NEXT (pl)));
3416         if (MPLIST_KEY (pl) != Mt)
3417           {
3418             MPlist *p = mplist ();
3419
3420             mplist_push (ic_info->vars, Mplist, p);
3421             M17N_OBJECT_UNREF (p);
3422             mplist_add (p, Msymbol, name);
3423             mplist_add (p, MPLIST_KEY (pl), MPLIST_VAL (pl));
3424           }
3425       }
3426   ic_info->vars_saved = mplist_copy (ic_info->vars);
3427
3428   if (im_info->externals)
3429     {
3430       MPlist *func_args = mplist (), *plist;
3431
3432       mplist_add (func_args, Mt, ic);
3433       MPLIST_DO (plist, im_info->externals)
3434         {
3435           MIMExternalModule *external = MPLIST_VAL (plist);
3436           MIMExternalFunc func
3437             = (MIMExternalFunc) mplist_get (external->func_list, Minit);
3438
3439           if (func)
3440             (func) (func_args);
3441         }
3442       M17N_OBJECT_UNREF (func_args);
3443     }
3444
3445   ic_info->preedit_saved = mtext ();
3446   ic_info->tick = im_info->tick;
3447 }
3448
3449 /* Finalize IC->ic_info.  */
3450
3451 static void
3452 fini_ic_info (MInputContext *ic)
3453 {
3454   MInputMethodInfo *im_info = ic->im->info;
3455   MInputContextInfo *ic_info = ic->info;
3456
3457   if (im_info->externals)
3458     {
3459       MPlist *func_args = mplist (), *plist;
3460
3461       mplist_add (func_args, Mt, ic);
3462       MPLIST_DO (plist, im_info->externals)
3463         {
3464           MIMExternalModule *external = MPLIST_VAL (plist);
3465           MIMExternalFunc func
3466             = (MIMExternalFunc) mplist_get (external->func_list, Mfini);
3467
3468           if (func)
3469             (func) (func_args);
3470         }
3471       M17N_OBJECT_UNREF (func_args);
3472     }
3473
3474   MLIST_FREE1 (ic_info, keys);
3475   M17N_OBJECT_UNREF (ic_info->preedit_saved);
3476   M17N_OBJECT_UNREF (ic_info->markers);
3477   M17N_OBJECT_UNREF (ic_info->vars);
3478   M17N_OBJECT_UNREF (ic_info->vars_saved);
3479   M17N_OBJECT_UNREF (ic_info->preceding_text);
3480   M17N_OBJECT_UNREF (ic_info->following_text);
3481
3482   memset (ic_info, 0, sizeof (MInputContextInfo));
3483 }
3484
3485 static void
3486 re_init_ic (MInputContext *ic, int reload)
3487 {
3488   MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
3489   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
3490   int status_changed, preedit_changed, cursor_pos_changed, candidates_changed;
3491
3492   status_changed = ic_info->state != (MIMState *) MPLIST_VAL (im_info->states);
3493   preedit_changed = mtext_nchars (ic->preedit) > 0;
3494   cursor_pos_changed = ic->cursor_pos > 0;
3495   candidates_changed = 0;
3496   if (ic->candidate_list)
3497     {
3498       candidates_changed |= MINPUT_CANDIDATES_LIST_CHANGED;
3499       M17N_OBJECT_UNREF (ic->candidate_list);
3500       ic->candidate_list = NULL;
3501     }
3502   if (ic->candidate_show)
3503     {
3504       candidates_changed |= MINPUT_CANDIDATES_SHOW_CHANGED;
3505       ic->candidate_show = 0;
3506     }
3507   if (ic->candidate_index > 0)
3508     {
3509       candidates_changed |= MINPUT_CANDIDATES_INDEX_CHANGED;
3510       ic->candidate_index = 0;
3511       ic->candidate_from = ic->candidate_to = 0;
3512     }
3513   if (mtext_nchars (ic->produced) > 0)
3514     mtext_reset (ic->produced);
3515   if (mtext_nchars (ic->preedit) > 0)
3516     mtext_reset (ic->preedit);
3517   ic->cursor_pos = 0;
3518   M17N_OBJECT_UNREF (ic->plist);
3519   ic->plist = mplist ();
3520
3521   fini_ic_info (ic);
3522   if (reload)
3523     reload_im_info (im_info);
3524   init_ic_info (ic);
3525   shift_state (ic, Mnil);
3526   ic->status_changed = status_changed;
3527   ic->preedit_changed = preedit_changed;
3528   ic->cursor_pos_changed = cursor_pos_changed;
3529   ic->candidates_changed = candidates_changed;
3530 }
3531
3532 static void
3533 reset_ic (MInputContext *ic, MSymbol ignore)
3534 {
3535   MDEBUG_PRINT ("\n  [IM] reset\n");
3536   re_init_ic (ic, 0);
3537 }
3538
3539 static int
3540 open_im (MInputMethod *im)
3541 {
3542   MInputMethodInfo *im_info = get_im_info (im->language, im->name, Mnil, Mnil);
3543
3544   if (! im_info)
3545     MERROR (MERROR_IM, -1);
3546   im->info = im_info;
3547
3548   return 0;
3549 }
3550
3551 static void
3552 close_im (MInputMethod *im)
3553 {
3554   im->info = NULL;
3555 }
3556
3557 static int
3558 create_ic (MInputContext *ic)
3559 {
3560   MInputContextInfo *ic_info;
3561
3562   MSTRUCT_CALLOC (ic_info, MERROR_IM);
3563   ic->info = ic_info;
3564   init_ic_info (ic);
3565   shift_state (ic, Mnil);
3566   return 0;
3567 }
3568
3569 static void
3570 destroy_ic (MInputContext *ic)
3571 {
3572   fini_ic_info (ic);
3573   free (ic->info);
3574 }
3575
3576 static int
3577 check_reload (MInputContext *ic, MSymbol key)
3578 {
3579   MInputMethodInfo *im_info = ic->im->info;
3580   MPlist *plist = resolve_command (im_info->configured_cmds, Mat_reload);
3581
3582   if (! plist)
3583     {
3584       plist = resolve_command (global_info->configured_cmds, Mat_reload);
3585       if (! plist)
3586         return 0;
3587     }
3588   MPLIST_DO (plist, plist)
3589     {
3590       MSymbol this_key, alias;
3591
3592       if (MPLIST_MTEXT_P (plist))
3593         {
3594           MText *mt = MPLIST_MTEXT (plist);
3595           int c = mtext_ref_char (mt, 0);
3596
3597           if (c >= 256)
3598             continue;
3599           this_key = one_char_symbol[c];
3600         }
3601       else
3602         {
3603           MPlist *pl = MPLIST_PLIST (plist);
3604       
3605           this_key = MPLIST_SYMBOL (pl);
3606         }
3607       alias = this_key;
3608       while (alias != key 
3609              && (alias = msymbol_get (alias, M_key_alias))
3610              && alias != this_key);
3611       if (alias == key)
3612         break;
3613     }
3614   if (MPLIST_TAIL_P (plist))
3615     return 0;
3616
3617   MDEBUG_PRINT ("\n  [IM] reload");
3618   re_init_ic (ic, 1);
3619   return 1;
3620 }
3621
3622
3623 /** Handle the input key KEY in the current state and map of IC->info.
3624     If KEY is handled but no text is produced, return 0, otherwise
3625     return 1.
3626
3627     Ignore ARG.  */
3628
3629 static int
3630 filter (MInputContext *ic, MSymbol key, void *arg)
3631 {
3632   MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
3633   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
3634   int i = 0;
3635
3636   if (check_reload (ic, key))
3637     return 0;
3638
3639   if (! ic_info->state)
3640     {
3641       ic_info->key_unhandled = 1;
3642       return 0;
3643     }
3644   mtext_reset (ic->produced);
3645   ic->status_changed = ic->preedit_changed = ic->candidates_changed = 0;
3646   M17N_OBJECT_UNREF (ic_info->preceding_text);
3647   M17N_OBJECT_UNREF (ic_info->following_text);
3648   ic_info->preceding_text = ic_info->following_text = NULL;
3649   MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
3650   ic_info->key_unhandled = 0;
3651
3652   do {
3653     if (handle_key (ic) < 0)
3654       {
3655         /* KEY was not handled.  Delete it from the current key sequence.  */
3656         if (ic_info->used > 0)
3657           {
3658             memmove (ic_info->keys, ic_info->keys + 1,
3659                      sizeof (int) * (ic_info->used - 1));
3660             ic_info->used--;
3661             if (ic_info->state_key_head > 0)
3662               ic_info->state_key_head--;              
3663           }
3664         /* This forces returning 1.  */
3665         ic_info->key_unhandled = 1;
3666         break;
3667       }
3668     if (i++ == 100)
3669       {
3670         mdebug_hook ();
3671         reset_ic (ic, Mnil);
3672         ic_info->key_unhandled = 1;
3673         break;
3674       }
3675     /* Break the loop if all keys were handled.  */
3676   } while (ic_info->key_head < ic_info->used);
3677
3678   /* If the current map is the root of the initial state, we should
3679      produce any preedit text in ic->produced.  */
3680   if (ic_info->map == ((MIMState *) MPLIST_VAL (im_info->states))->map)
3681     preedit_commit (ic);
3682
3683   if (mtext_nchars (ic->produced) > 0)
3684     {
3685       MSymbol lang = msymbol_get (ic->im->language, Mlanguage);
3686
3687       if (mdebug__flag & mdebug_mask)
3688         {
3689           MDEBUG_PRINT (" (produced");
3690           for (i = 0; i < mtext_nchars (ic->produced); i++)
3691             MDEBUG_PRINT1 (" U+%04X", mtext_ref_char (ic->produced, i));
3692           MDEBUG_PRINT (")");
3693         }
3694
3695       if (lang != Mnil)
3696         mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
3697                         Mlanguage, ic->im->language);
3698       if (ic_info->state_key_head > 0)
3699         {
3700           memmove (ic_info->keys, ic_info->keys + ic_info->state_key_head,
3701                    sizeof (int) * (ic_info->used - ic_info->state_key_head));
3702           ic_info->used -= ic_info->state_key_head;
3703           ic_info->key_head -= ic_info->state_key_head;
3704           ic_info->state_key_head = 0;
3705         }
3706     }
3707
3708   if (ic_info->key_unhandled)
3709     {
3710       ic_info->used = 0;
3711       ic_info->key_head = ic_info->state_key_head = 0;
3712     }
3713
3714   return (! ic_info->key_unhandled && mtext_nchars (ic->produced) == 0);
3715 }
3716
3717
3718 /** Return 1 if the last event or key was not handled, otherwise
3719     return 0.
3720
3721     There is no need of looking up because ic->produced should already
3722     contain the produced text (if any).
3723
3724     Ignore KEY.  */
3725
3726 static int
3727 lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
3728 {
3729   mtext_cat (mt, ic->produced);
3730   mtext_reset (ic->produced);
3731   return (((MInputContextInfo *) ic->info)->key_unhandled ? -1 : 0);
3732 }
3733
3734 \f
3735 /* Input method command handler.  */
3736
3737 /* List of all (global and local) commands. 
3738    (LANG:(IM-NAME:(COMMAND ...) ...) ...) ...
3739    COMMAND is CMD-NAME:(mtext:DESCRIPTION plist:KEYSEQ ...))
3740    Global commands are stored as (t (t COMMAND ...))  */
3741
3742 \f
3743 /* Input method variable handler.  */
3744
3745
3746 /* Support functions for mdebug_dump_im.  */
3747
3748 static void
3749 dump_im_map (MPlist *map_list, int indent)
3750 {
3751   char *prefix;
3752   MSymbol key = MPLIST_KEY (map_list);
3753   MIMMap *map = (MIMMap *) MPLIST_VAL (map_list);
3754
3755   prefix = (char *) alloca (indent + 1);
3756   memset (prefix, 32, indent);
3757   prefix[indent] = '\0';
3758
3759   fprintf (stderr, "(\"%s\" ", msymbol_name (key));
3760   if (map->map_actions)
3761     mdebug_dump_plist (map->map_actions, indent + 2);
3762   if (map->submaps)
3763     {
3764       MPLIST_DO (map_list, map->submaps)
3765         {
3766           fprintf (stderr, "\n%s  ", prefix);
3767           dump_im_map (map_list, indent + 2);
3768         }
3769     }
3770   if (map->branch_actions)
3771     {
3772       fprintf (stderr, "\n%s  (branch\n%s    ", prefix, prefix);
3773       mdebug_dump_plist (map->branch_actions, indent + 4);
3774       fprintf (stderr, ")");      
3775     }
3776   fprintf (stderr, ")");
3777 }
3778
3779
3780 static void
3781 dump_im_state (MIMState *state, int indent)
3782 {
3783   char *prefix;
3784   MPlist *map_list;
3785
3786   prefix = (char *) alloca (indent + 1);
3787   memset (prefix, 32, indent);
3788   prefix[indent] = '\0';
3789
3790   fprintf (stderr, "(%s", msymbol_name (state->name));
3791   if (state->map->submaps)
3792     {
3793       MPLIST_DO (map_list, state->map->submaps)
3794         {
3795           fprintf (stderr, "\n%s  ", prefix);
3796           dump_im_map (map_list, indent + 2);
3797         }
3798     }
3799   fprintf (stderr, ")");
3800 }
3801
3802 \f
3803
3804 int
3805 minput__init ()
3806 {
3807   Minput_driver = msymbol ("input-driver");
3808
3809   Minput_preedit_start = msymbol ("input-preedit-start");
3810   Minput_preedit_done = msymbol ("input-preedit-done");
3811   Minput_preedit_draw = msymbol ("input-preedit-draw");
3812   Minput_status_start = msymbol ("input-status-start");
3813   Minput_status_done = msymbol ("input-status-done");
3814   Minput_status_draw = msymbol ("input-status-draw");
3815   Minput_candidates_start = msymbol ("input-candidates-start");
3816   Minput_candidates_done = msymbol ("input-candidates-done");
3817   Minput_candidates_draw = msymbol ("input-candidates-draw");
3818   Minput_set_spot = msymbol ("input-set-spot");
3819   Minput_focus_move = msymbol ("input-focus-move");
3820   Minput_focus_in = msymbol ("input-focus-in");
3821   Minput_focus_out = msymbol ("input-focus-out");
3822   Minput_toggle = msymbol ("input-toggle");
3823   Minput_reset = msymbol ("input-reset");
3824   Minput_get_surrounding_text = msymbol ("input-get-surrounding-text");
3825   Minput_delete_surrounding_text = msymbol ("input-delete-surrounding-text");
3826   Mcustomized = msymbol ("customized");
3827   Mconfigured = msymbol ("configured");
3828   Minherited = msymbol ("inherited");
3829
3830   minput_default_driver.open_im = open_im;
3831   minput_default_driver.close_im = close_im;
3832   minput_default_driver.create_ic = create_ic;
3833   minput_default_driver.destroy_ic = destroy_ic;
3834   minput_default_driver.filter = filter;
3835   minput_default_driver.lookup = lookup;
3836   minput_default_driver.callback_list = mplist ();
3837   mplist_put (minput_default_driver.callback_list, Minput_reset,
3838               (void *) reset_ic);
3839   minput_driver = &minput_default_driver;
3840
3841   fully_initialized = 0;
3842   return 0;
3843 }
3844
3845 void
3846 minput__fini ()
3847 {
3848   if (fully_initialized)
3849     {
3850       free_im_list (im_info_list);
3851       if (im_custom_list)
3852         free_im_list (im_custom_list);
3853       if (im_config_list)
3854         free_im_list (im_config_list);
3855       M17N_OBJECT_UNREF (load_im_info_keys);
3856     }
3857
3858   M17N_OBJECT_UNREF (minput_default_driver.callback_list);
3859   M17N_OBJECT_UNREF (minput_driver->callback_list);
3860
3861 }
3862
3863 int
3864 minput__callback (MInputContext *ic, MSymbol command)
3865 {
3866   MInputCallbackFunc func;
3867
3868   if (! ic->im->driver.callback_list)
3869     return -1;
3870   func = (MInputCallbackFunc) mplist_get (ic->im->driver.callback_list,
3871                                           command);
3872   if (! func)
3873     return -1;
3874   (func) (ic, command);
3875   return 0;
3876 }
3877
3878 MSymbol
3879 minput__char_to_key (int c)
3880 {
3881   if (c < 0 || c >= 0x100)
3882     return Mnil;
3883
3884   return one_char_symbol[c];
3885 }
3886
3887 /*** @} */
3888 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
3889
3890 \f
3891 /* External API */
3892
3893 /*** @addtogroup m17nInputMethod */
3894 /*** @{ */
3895 /*=*/
3896
3897 /***en
3898     @name Variables: Predefined symbols for callback commands.
3899
3900     These are the predefined symbols that are used as the @c COMMAND
3901     argument of callback functions of an input method driver (see
3902     #MInputDriver::callback_list).  
3903
3904     Most of them do not require extra argument nor return any value;
3905     exceptions are these:
3906
3907     Minput_get_surrounding_text: When a callback function assigned for
3908     this command is called, the first element of #MInputContext::plist
3909     has key #Minteger and the value specifies which portion of the
3910     surrounding text should be retrieved.  If the value is positive,
3911     it specifies the number of characters following the current cursor
3912     position.  If the value is negative, the absolute value specifies
3913     the number of characters preceding the current cursor position.
3914
3915     If the surrounding text is currently supported, the callback
3916     function must set the key of this element to #Mtext and the value
3917     to the retrieved M-text.  The length of the M-text may be shorter
3918     than the requested number of characters, if the available text is
3919     not that long.  The length can be zero in the worst case.  Or, the
3920     length may be longer if an application thinks it is more efficient
3921     to return that length.
3922
3923     If the surrounding text is not currently supported, the callback
3924     function should return without changing the first element of
3925     #MInputContext::plist.
3926
3927     Minput_delete_surrounding_text: When a callback function assigned
3928     for this command is called, the first element of
3929     #MInputContext::plist has key #Minteger and the value specifies
3930     which portion of the surrounding text should be deleted in the
3931     same way as the case of Minput_get_surrounding_text.  The callback
3932     function must delete the specified text.  It should not alter
3933     #MInputContext::plist.  */ 
3934 /***ja
3935     @name ÊÑ¿ô¡§ ¥³¡¼¥ë¥Ð¥Ã¥¯¥³¥Þ¥ó¥ÉÍÑÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë.
3936
3937     ÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Î¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Ë¤ª¤¤¤Æ @c COMMAND 
3938     °ú¿ô¤È¤·¤ÆÍѤ¤¤é¤ì¤ëÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë (#MInputDriver::callback_list »²¾È)¡£
3939
3940     ¤Û¤È¤ó¤É¤ÏÄɲäΰú¿ô¤òɬÍפȤ·¤Ê¤¤¤·ÃͤòÊÖ¤µ¤Ê¤¤¤¬¡¢°Ê²¼¤ÏÎã³°¤Ç¤¢¤ë¡£
3941
3942     Minput_get_surrounding_text: ¤³¤Î¥³¥Þ¥ó¥É¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿¥³¡¼¥ë¥Ð¥Ã
3943     ¥¯´Ø¿ô¤¬¸Æ¤Ð¤ì¤¿ºÝ¤Ë¤Ï¡¢ #MInputContext::plist ¤ÎÂè°ìÍ×ÁǤϥ­¡¼¤È¤·
3944     ¤Æ#Minteger ¤ò¤È¤ê¡¢¤½¤ÎÃͤϥµ¥é¥¦¥ó¥Ç¥£¥ó¥°¥Æ¥­¥¹¥È¤Î¤¦¤Á¤É¤ÎÉôʬ
3945     ¤ò¼è¤Ã¤ÆÍè¤ë¤«¤ò»ØÄꤹ¤ë¡£Ãͤ¬Àµ¤Ç¤¢¤ì¤Ð¡¢¸½ºß¤Î¥«¡¼¥½¥ë°ÌÃ֤˳¤¯
3946     ÃͤθĿôʬ¤Îʸ»ú¤ò¼è¤ë¡£Éé¤Ç¤¢¤ì¤Ð¡¢¥«¡¼¥½¥ë°ÌÃÖ¤ËÀè¹Ô¤¹¤ëÃͤÎÀäÂÐ
3947     ÃÍʬ¤Îʸ»ú¤ò¼è¤ë¡£
3948
3949     ¥µ¥é¥¦¥ó¥Ç¥£¥ó¥°¥Æ¥­¥¹¥È¤¬¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤ì¤Ð¡¢¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Ï
3950     ¤³¤ÎÍ×ÁǤΥ­¡¼¤ò #Mtext ¤Ë¡¢Ãͤò¼è¤ê¹þ¤ó¤ÀM-text ¤ËÀßÄꤷ¤Ê¤¯¤Æ¤Ï¤Ê
3951     ¤é¤Ê¤¤¡£¤â¤·¥Æ¥­¥¹¥È¤ÎŤµ¤¬½¼Ê¬¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î M-text ¤ÎŤµ¤ÏÍ×
3952     µá¤µ¤ì¤Æ¤¤¤ëʸ»ú¿ô¤è¤êû¤¯¤ÆÎɤ¤¡£ºÇ°­¤Î¾ì¹ç 0 ¤Ç¤â¤è¤¤¤·¡¢¥¢¥×¥ê¥±¡¼
3953     ¥·¥ç¥ó¦¤ÇɬÍפǸúΨŪ¤À¤È»×¤¨¤ÐŤ¯¤Æ¤âÎɤ¤¡£
3954
3955     ¥µ¥é¥¦¥ó¥Ç¥£¥ó¥°¥Æ¥­¥¹¥È¤¬¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¡¢¥³¡¼¥ë¥Ð¥Ã¥¯´Ø
3956     ¿ô¤Ï #MInputContext::plist ¤ÎÂè°ìÍ×ÁǤòÊѲ½¤µ¤»¤ë¤³¤È¤Ê¤¯ÊÖ¤µ¤Ê¤¯¤Æ
3957     ¤Ï¤Ê¤é¤Ê¤¤¡£
3958
3959     Minput_delete_surrounding_text: ¤³¤Î¥³¥Þ¥ó¥É¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿¥³¡¼¥ë
3960     ¥Ð¥Ã¥¯´Ø¿ô¤¬¸Æ¤Ð¤ì¤¿ºÝ¤Ë¤Ï¡¢#MInputContext::plist ¤ÎÂè°ìÍ×ÁǤϡ¢¥­¡¼
3961     ¤È¤·¤Æ#Minteger ¤ò¤È¤ê¡¢ÃͤϺï½ü¤¹¤ë¤Ù¤­¥µ¥é¥¦¥ó¥Ç¥£¥ó¥°¥Æ¥­¥¹¥È¤ò
3962     Minput_get_surrounding_text ¤ÈƱÍͤΤä¤êÊý¤Ç»ØÄꤹ¤ë¡£¥³¡¼¥ë¥Ð¥Ã¥¯
3963     ´Ø¿ô¤Ï»ØÄꤵ¤ì¤¿¥Æ¥­¥¹¥È¤òºï½ü¤·¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£¤Þ¤¿
3964     #MInputContext::plist ¤òÊѤ¨¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£  */ 
3965 /*** @{ */ 
3966 /*=*/
3967
3968 MSymbol Minput_preedit_start;
3969 MSymbol Minput_preedit_done;
3970 MSymbol Minput_preedit_draw;
3971 MSymbol Minput_status_start;
3972 MSymbol Minput_status_done;
3973 MSymbol Minput_status_draw;
3974 MSymbol Minput_candidates_start;
3975 MSymbol Minput_candidates_done;
3976 MSymbol Minput_candidates_draw;
3977 MSymbol Minput_set_spot;
3978 MSymbol Minput_toggle;
3979 MSymbol Minput_reset;
3980 MSymbol Minput_get_surrounding_text;
3981 MSymbol Minput_delete_surrounding_text;
3982 /*** @} */
3983
3984 /*=*/
3985
3986 /***en
3987     @name Variables: Predefined symbols for special input events.
3988
3989     These are the predefined symbols that are used as the @c KEY
3990     argument of minput_filter ().  */ 
3991 /***ja
3992     @name ÊÑ¿ô: ÆÃÊ̤ÊÆþÎÏ¥¤¥Ù¥ó¥ÈÍÑÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë.
3993
3994     minput_filter () ¤Î @c KEY °ú¿ô¤È¤·¤ÆÍѤ¤¤é¤ì¤ëÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë¡£  */ 
3995
3996 /*** @{ */ 
3997 /*=*/
3998
3999 MSymbol Minput_focus_out;
4000 MSymbol Minput_focus_in;
4001 MSymbol Minput_focus_move;
4002
4003 /*** @} */
4004
4005 /*=*/
4006 /***en
4007     @name Variables: Predefined symbols used in input method information.
4008
4009     These are the predefined symbols describing status of input method
4010     command and variable, and are used in a return value of
4011     minput_get_command () and minput_get_variable ().  */
4012 /***ja
4013     @name ÊÑ¿ô: ÆþÎϥ᥽¥Ã¥É¾ðÊóÍÑÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë.
4014
4015     ÆþÎϥ᥽¥Ã¥É¤Î¥³¥Þ¥ó¥É¤äÊÑ¿ô¤Î¾õÂÖ¤òɽ¤·¡¢minput_get_command () ¤È
4016     minput_get_variable () ¤ÎÌá¤êÃͤȤ·¤ÆÍѤ¤¤é¤ì¤ëÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë¡£  */
4017 /*** @{ */ 
4018 /*=*/
4019 MSymbol Minherited;
4020 MSymbol Mcustomized;
4021 MSymbol Mconfigured;
4022 /*** @} */ 
4023
4024 /*=*/
4025
4026 /***en
4027     @brief The default driver for internal input methods.
4028
4029     The variable #minput_default_driver is the default driver for
4030     internal input methods.
4031
4032     The member MInputDriver::open_im () searches the m17n database for
4033     an input method that matches the tag \< #Minput_method, $LANGUAGE,
4034     $NAME\> and loads it.
4035
4036     The member MInputDriver::callback_list () is @c NULL.  Thus, it is
4037     programmers responsibility to set it to a plist of proper callback
4038     functions.  Otherwise, no feedback information (e.g. preedit text)
4039     can be shown to users.
4040
4041     The macro M17N_INIT () sets the variable #minput_driver to the
4042     pointer to this driver so that all internal input methods use it.
4043
4044     Therefore, unless @c minput_driver is set differently, the driver
4045     dependent arguments $ARG of the functions whose name begins with
4046     "minput_" are all ignored.  */
4047 /***ja
4048     @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥǥե©¥ë¥È¥É¥é¥¤¥Ð.
4049
4050     ÊÑ¿ô #minput_default_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѤΥǥե©¥ë¥È¤Î¥É¥é¥¤¥Ð¤òɽ¤¹¡£
4051
4052     ¥á¥ó¥Ð MInputDriver::open_im () ¤Ï m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹Ã椫¤é¥¿¥° 
4053     \< #Minput_method, $LANGUAGE, $NAME\> 
4054     ¤Ë¹çÃפ¹¤ëÆþÎϥ᥽¥Ã¥É¤òõ¤·¡¢¤½¤ì¤ò¥í¡¼¥É¤¹¤ë¡£
4055
4056     ¥á¥ó¥Ð MInputDriver::callback_list () ¤Ï @c NULL ¤Ç¤¢¤ê¡¢
4057     ¤·¤¿¤¬¤Ã¤Æ¡¢¥×¥í¥°¥é¥Þ¦¤ÇÀÕǤ¤ò»ý¤Ã¤Æ Å¬Àڤʥ³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Î plist
4058     ¤ËÀßÄꤷ¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¤µ¤â¤Ê¤¤¤È¡¢preedit 
4059     ¥Æ¥­¥¹¥È¤Ê¤É¤Î¥Õ¥£¡¼¥É¥Ð¥Ã¥¯¾ðÊ󤬥桼¥¶¤Ëɽ¼¨¤µ¤ì¤Ê¤¤¡£
4060
4061     ¥Þ¥¯¥í M17N_INIT () ¤ÏÊÑ¿ô #minput_driver 
4062     ¤ò¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤ËÀßÄꤷ¡¢Á´¤Æ¤ÎÆâÉôÆþÎϥ᥽¥Ã¥É¤¬¤³¤Î¥É¥é¥¤¥Ð¤ò»È¤¦¤è¤¦¤Ë¤¹¤ë¡£
4063
4064     ¤·¤¿¤¬¤Ã¤Æ¡¢@c minput_driver ¤¬¥Ç¥Õ¥©¥ë¥ÈÃͤΤޤޤǤ¢¤ì¤Ð¡¢minput_ 
4065     ¤Ç»Ï¤Þ¤ë´Ø¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô $ARG ¤Ï¤¹¤Ù¤Æ̵»ë¤µ¤ì¤ë¡£  */
4066
4067 MInputDriver minput_default_driver;
4068 /*=*/
4069
4070 /***en
4071     @brief The driver for internal input methods.
4072
4073     The variable #minput_driver is a pointer to the input method
4074     driver that is used by internal input methods.  The macro
4075     M17N_INIT () initializes it to a pointer to #minput_default_driver
4076     if <m17n<EM></EM>.h> is included.  */ 
4077 /***ja
4078     @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥɥ饤¥Ð.
4079
4080     ÊÑ¿ô #minput_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤Æ»ÈÍѤµ¤ì¤Æ¤¤¤ëÆþÎÏ¥á
4081     ¥½¥Ã¥É¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£¥Þ¥¯¥í M17N_INIT () ¤Ï¤³¤Î¥Ý¥¤¥ó
4082     ¥¿¤ò#minput_default_driver (<m17n<EM></EM>.h> ¤¬ include ¤µ¤ì¤Æ¤¤¤ë
4083     »þ) ¤Ë½é´ü²½¤¹¤ë¡£  */ 
4084
4085 MInputDriver *minput_driver;
4086
4087 MSymbol Minput_driver;
4088
4089 /*=*/
4090
4091 /***en
4092     @name Functions
4093 */
4094 /***ja
4095     @name ´Ø¿ô
4096 */
4097 /*** @{ */
4098
4099 /*=*/
4100
4101 /***en
4102     @brief Open an input method.
4103
4104     The minput_open_im () function opens an input method whose
4105     language and name match $LANGUAGE and $NAME, and returns a pointer
4106     to the input method object newly allocated.
4107
4108     This function at first decides a driver for the input method as
4109     described below.
4110
4111     If $LANGUAGE is not #Mnil, the driver pointed by the variable
4112     #minput_driver is used.
4113
4114     If $LANGUAGE is #Mnil and $NAME has the property #Minput_driver, the
4115     driver pointed to by the property value is used to open the input
4116     method.  If $NAME has no such a property, @c NULL is returned.
4117
4118     Then, the member MInputDriver::open_im () of the driver is
4119     called.  
4120
4121     $ARG is set in the member @c arg of the structure MInputMethod so
4122     that the driver can refer to it.  */
4123 /***ja
4124     @brief ÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë.
4125
4126     ´Ø¿ô minput_open_im () ¤Ï¸À¸ì $LANGUAGE ¤È̾Á° $NAME 
4127     ¤Ë¹çÃפ¹¤ëÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤·¡¢¿·¤¿¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿ÆþÎϥ᥽¥Ã¥É¥ª¥Ö¥¸¥§¥¯¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
4128     
4129     ¤³¤Î´Ø¿ô¤Ï¡¢¤Þ¤ºÆþÎϥ᥽¥Ã¥ÉÍѤΥɥ饤¥Ð¤ò°Ê²¼¤Î¤è¤¦¤Ë¤·¤Æ·èÄꤹ¤ë¡£
4130
4131     $LANGUAGE ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢ÊÑ¿ô #minput_driver 
4132     ¤Ç»Ø¤µ¤ì¤Æ¤¤¤ë¥É¥é¥¤¥Ð¤òÍѤ¤¤ë¡£
4133
4134     $LANGUAGE ¤¬ #Mnil ¤Ç¤¢¤ê¡¢$NAME ¤¬ #Minput_driver
4135     ¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä¾ì¹ç¤Ë¤Ï¡¢¤½¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤǻؤµ¤ì¤Æ¤¤¤ëÆþÎϥɥ饤¥Ð¤òÍѤ¤¤ÆÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë¡£
4136     $NAME ¤Ë¤½¤Î¤è¤¦¤Ê¥×¥í¥Ñ¥Æ¥£¤¬Ìµ¤«¤Ã¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
4137
4138     ¼¡¤¤¤Ç¡¢¥É¥é¥¤¥Ð¤Î¥á¥ó¥Ð MInputDriver::open_im () ¤¬¸Æ¤Ð¤ì¤ë¡£
4139
4140     $ARG ¤Ï¹½Â¤ÂΠMInputMethod ¤Î¥á¥ó¥Ð @c arg ¤ËÀßÄꤵ¤ì¡¢¥É¥é¥¤¥Ð¤«¤é»²¾È¤Ç¤­¤ë¡£
4141
4142     @latexonly \IPAlabel{minput_open} @endlatexonly
4143
4144 */
4145
4146 MInputMethod *
4147 minput_open_im (MSymbol language, MSymbol name, void *arg)
4148 {
4149   MInputMethod *im;
4150   MInputDriver *driver;
4151
4152   MINPUT__INIT ();
4153
4154   MDEBUG_PRINT2 ("  [IM] opening (%s %s) ... ",
4155                  msymbol_name (language), msymbol_name (name));
4156   if (language)
4157     driver = minput_driver;
4158   else
4159     {
4160       driver = (MInputDriver *) msymbol_get (name, Minput_driver);
4161       if (! driver)
4162         MERROR (MERROR_IM, NULL);
4163     }
4164
4165   MSTRUCT_CALLOC (im, MERROR_IM);
4166   im->language = language;
4167   im->name = name;
4168   im->arg = arg;
4169   im->driver = *driver;
4170   if ((*im->driver.open_im) (im) < 0)
4171     {
4172       MDEBUG_PRINT (" failed\n");
4173       free (im);
4174       return NULL;
4175     }
4176   MDEBUG_PRINT (" ok\n");
4177   return im;
4178 }
4179
4180 /*=*/
4181
4182 /***en
4183     @brief Close an input method.
4184
4185     The minput_close_im () function closes the input method $IM, which
4186     must have been created by minput_open_im ().  */
4187
4188 /***ja
4189     @brief ÆþÎϥ᥽¥Ã¥É¤ò¥¯¥í¡¼¥º¤¹¤ë.
4190
4191     ´Ø¿ô minput_close_im () ¤Ï¡¢ÆþÎϥ᥽¥Ã¥É $IM ¤ò¥¯¥í¡¼¥º¤¹¤ë¡£
4192     ¤³¤ÎÆþÎϥ᥽¥Ã¥É $IM ¤Ï minput_open_im () ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£  */
4193
4194 void
4195 minput_close_im (MInputMethod *im)
4196 {
4197   MDEBUG_PRINT2 ("  [IM] closing (%s %s) ... ",
4198                  msymbol_name (im->name), msymbol_name (im->language));
4199   (*im->driver.close_im) (im);
4200   free (im);
4201   MDEBUG_PRINT (" done\n");
4202 }
4203
4204 /*=*/
4205
4206 /***en
4207     @brief Create an input context.
4208
4209     The minput_create_ic () function creates an input context object
4210     associated with input method $IM, and calls callback functions
4211     corresponding to #Minput_preedit_start, #Minput_status_start, and
4212     #Minput_status_draw in this order.
4213
4214     @return
4215     If an input context is successfully created, minput_create_ic ()
4216     returns a pointer to it.  Otherwise it returns @c NULL.  */
4217
4218 /***ja
4219     @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÀ¸À®¤¹¤ë.
4220
4221     ´Ø¿ô minput_create_ic () ¤ÏÆþÎϥ᥽¥Ã¥É $IM
4222     ¤ËÂбþ¤¹¤ëÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤·¡¢
4223     #Minput_preedit_start, #Minput_status_start, #Minput_status_draw
4224     ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¤³¤Î½ç¤Ë¸Æ¤Ö¡£
4225
4226     @return
4227     ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤¬À¸À®¤µ¤ì¤¿¾ì¹ç¡¢minput_create_ic () 
4228     ¤Ï¤½¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¼ºÇÔ¤·¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
4229       */
4230
4231 MInputContext *
4232 minput_create_ic (MInputMethod *im, void *arg)
4233 {
4234   MInputContext *ic;
4235
4236   MDEBUG_PRINT2 ("  [IM] creating context (%s %s) ... ",
4237                  msymbol_name (im->name), msymbol_name (im->language));
4238   MSTRUCT_CALLOC (ic, MERROR_IM);
4239   ic->im = im;
4240   ic->arg = arg;
4241   ic->preedit = mtext ();
4242   ic->candidate_list = NULL;
4243   ic->produced = mtext ();
4244   ic->spot.x = ic->spot.y = 0;
4245   ic->active = 1;
4246   ic->plist = mplist ();
4247   if ((*im->driver.create_ic) (ic) < 0)
4248     {
4249       MDEBUG_PRINT (" failed\n");
4250       M17N_OBJECT_UNREF (ic->preedit);
4251       M17N_OBJECT_UNREF (ic->produced);
4252       M17N_OBJECT_UNREF (ic->plist);
4253       free (ic);
4254       return NULL;
4255     };
4256
4257   if (im->driver.callback_list)
4258     {
4259       minput__callback (ic, Minput_preedit_start);
4260       minput__callback (ic, Minput_status_start);
4261       minput__callback (ic, Minput_status_draw);
4262     }
4263
4264   MDEBUG_PRINT (" ok\n");
4265   return ic;
4266 }
4267
4268 /*=*/
4269
4270 /***en
4271     @brief Destroy an input context.
4272
4273     The minput_destroy_ic () function destroys the input context $IC,
4274     which must have been created by minput_create_ic ().  It calls
4275     callback functions corresponding to #Minput_preedit_done,
4276     #Minput_status_done, and #Minput_candidates_done in this order.  */
4277
4278 /***ja
4279     @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÇ˲õ¤¹¤ë.
4280
4281     ´Ø¿ô minput_destroy_ic () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤òÇ˲õ¤¹¤ë¡£
4282     ¤³¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ï minput_create_ic () 
4283     ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£¤³¤Î´Ø¿ô¤Ï 
4284     #Minput_preedit_done, #Minput_status_done, #Minput_candidates_done 
4285     ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¤³¤Î½ç¤Ë¸Æ¤Ö¡£
4286   */
4287
4288 void
4289 minput_destroy_ic (MInputContext *ic)
4290 {
4291   MDEBUG_PRINT2 ("  [IM] destroying context (%s %s) ... ",
4292                  msymbol_name (ic->im->name), msymbol_name (ic->im->language));
4293   if (ic->im->driver.callback_list)
4294     {
4295       minput__callback (ic, Minput_preedit_done);
4296       minput__callback (ic, Minput_status_done);
4297       minput__callback (ic, Minput_candidates_done);
4298     }
4299   (*ic->im->driver.destroy_ic) (ic);
4300   M17N_OBJECT_UNREF (ic->preedit);
4301   M17N_OBJECT_UNREF (ic->produced);
4302   M17N_OBJECT_UNREF (ic->plist);
4303   MDEBUG_PRINT (" done\n");
4304   free (ic);
4305 }
4306
4307 /*=*/
4308
4309 /***en
4310     @brief Filter an input key.
4311
4312     The minput_filter () function filters input key $KEY according to
4313     input context $IC, and calls callback functions corresponding to
4314     #Minput_preedit_draw, #Minput_status_draw, and
4315     #Minput_candidates_draw if the preedit text, the status, and the
4316     current candidate are changed respectively.
4317
4318     To make the input method commit the current preedit text (if any)
4319     and shift to the initial state, call this function with #Mnil as
4320     $KEY.
4321
4322     To inform the input method about the focus-out event, call this
4323     function with #Minput_focus_out as $KEY.
4324
4325     To inform the input method about the focus-in event, call this
4326     function with #Minput_focus_in as $KEY.
4327
4328     To inform the input method about the focus-move event (i.e. input
4329     spot change within the same input context), call this function
4330     with #Minput_focus_move as $KEY.
4331
4332     @return
4333     If $KEY is filtered out, this function returns 1.  In that case,
4334     the caller should discard the key.  Otherwise, it returns 0, and
4335     the caller should handle the key, for instance, by calling the
4336     function minput_lookup () with the same key.  */
4337
4338 /***ja
4339     @brief ÆþÎÏ¥­¡¼¤ò¥Õ¥£¥ë¥¿¤¹¤ë.
4340
4341     ´Ø¿ô minput_filter () ¤ÏÆþÎÏ¥­¡¼ $KEY ¤òÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC 
4342     ¤Ë±þ¤¸¤Æ¥Õ¥£¥ë¥¿¤·¡¢preedit ¥Æ¥­¥¹¥È¡¢¥¹¥Æ¡¼¥¿¥¹¡¢¸½»þÅÀ¤Ç¤Î¸õÊ䤬ÊѲ½¤·¤¿»þÅÀ¤Ç¡¢¤½¤ì¤¾¤ì
4343     #Minput_preedit_draw, #Minput_status_draw,
4344     #Minput_candidates_draw ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¸Æ¤Ö¡£
4345
4346     @return 
4347     $KEY ¤¬¥Õ¥£¥ë¥¿¤µ¤ì¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 1 ¤òÊÖ¤¹¡£
4348     ¤³¤Î¾ì¹ç¸Æ¤Ó½Ð¤·Â¦¤Ï¤³¤Î¥­¡¼¤ò¼Î¤Æ¤ë¤Ù¤­¤Ç¤¢¤ë¡£
4349     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0 ¤òÊÖ¤·¡¢¸Æ¤Ó½Ð¤·Â¦¤Ï¡¢¤¿¤È¤¨¤ÐƱ¤¸¥­¡¼¤Ç´Ø¿ô minput_lookup ()
4350     ¤ò¸Æ¤Ö¤Ê¤É¤·¤Æ¡¢¤³¤Î¥­¡¼¤ò½èÍý¤¹¤ë¡£
4351
4352     @latexonly \IPAlabel{minput_filter} @endlatexonly
4353 */
4354
4355 int
4356 minput_filter (MInputContext *ic, MSymbol key, void *arg)
4357 {
4358   int ret;
4359
4360   if (! ic
4361       || ! ic->active)
4362     return 0;
4363   ret = (*ic->im->driver.filter) (ic, key, arg);
4364
4365   if (ic->im->driver.callback_list)
4366     {
4367       if (ic->preedit_changed)
4368         minput__callback (ic, Minput_preedit_draw);
4369       if (ic->status_changed)
4370         minput__callback (ic, Minput_status_draw);
4371       if (ic->candidates_changed)
4372         minput__callback (ic, Minput_candidates_draw);
4373     }
4374
4375   return ret;
4376 }
4377
4378 /*=*/
4379
4380 /***en
4381     @brief Look up a text produced in the input context.
4382
4383     The minput_lookup () function looks up a text in the input context
4384     $IC.  $KEY must be identical to the one that was used in the previous call of
4385     minput_filter ().
4386
4387     If a text was produced by the input method, it is concatenated
4388     to M-text $MT.
4389
4390     This function calls #MInputDriver::lookup .
4391
4392     @return
4393     If $KEY was correctly handled by the input method, this function
4394     returns 0.  Otherwise, it returns -1, even though some text
4395     might be produced in $MT.  */
4396
4397 /***ja
4398     @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥ÈÃæ¤Î¥Æ¥­¥¹¥È¤òõ¤¹.
4399
4400     ´Ø¿ô minput_lookup () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC Ãæ¤Î¥Æ¥­¥¹¥È¤òõ¤¹¡£
4401     $KEY ¤Ï´Ø¿ô minput_filter () ¤Ø¤ÎľÁ°¤Î¸Æ¤Ó½Ð¤·¤ËÍѤ¤¤é¤ì¤¿¤â¤Î¤ÈƱ¤¸¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
4402
4403     ¥Æ¥­¥¹¥È¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆÀ¸À®¤µ¤ì¤Æ¤¤¤ì¤Ð¡¢¥Æ¥­¥¹¥È¤Ï M-text
4404     $MT ¤ËÏ¢·ë¤µ¤ì¤ë¡£
4405
4406     ¤³¤Î´Ø¿ô¤Ï¡¢#MInputDriver::lookup ¤ò¸Æ¤Ö¡£
4407
4408     @return 
4409     $KEY ¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆŬÀڤ˽èÍý¤Ç¤­¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 0 ¤òÊÖ¤¹¡£
4410     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£
4411     ¤³¤Î¾ì¹ç¤Ç¤â $MT ¤Ë²¿¤é¤«¤Î¥Æ¥­¥¹¥È¤¬À¸À®¤µ¤ì¤Æ¤¤¤ë¤³¤È¤¬¤¢¤ë¡£
4412
4413     @latexonly \IPAlabel{minput_lookup} @endlatexonly  */
4414
4415 int
4416 minput_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
4417 {
4418   return (ic ? (*ic->im->driver.lookup) (ic, key, arg, mt) : -1);
4419 }
4420 /*=*/
4421
4422 /***en
4423     @brief Set the spot of the input context.
4424
4425     The minput_set_spot () function sets the spot of input context $IC
4426     to coordinate ($X, $Y ) with the height specified by $ASCENT and $DESCENT .
4427     The semantics of these values depends on the input method driver.
4428
4429     For instance, a driver designed to work in a CUI environment may
4430     use $X and $Y as the column- and row numbers, and may ignore $ASCENT and
4431     $DESCENT .  A driver designed to work in a window system may
4432     interpret $X and $Y as the pixel offsets relative to the origin of the
4433     client window, and may interpret $ASCENT and $DESCENT as the ascent- and
4434     descent pixels of the line at ($X . $Y ).
4435
4436     $FONTSIZE specifies the fontsize of preedit text in 1/10 point.
4437
4438     $MT and $POS are the M-text and the character position at the spot.
4439     $MT may be @c NULL, in which case, the input method cannot get
4440     information about the text around the spot.  */
4441
4442 /***ja
4443     @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Î¥¹¥Ý¥Ã¥È¤òÀßÄꤹ¤ë.
4444
4445     ´Ø¿ô minput_set_spot () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤Î¥¹¥Ý¥Ã¥È¤ò¡¢ºÂɸ ($X, $Y )
4446     ¤Î°ÌÃ֤ˠ¡¢¹â¤µ $ASCENT¡¢ $DESCENT 
4447     ¤ÇÀßÄꤹ¤ë¡£ ¤³¤ì¤é¤ÎÃͤΰÕÌ£¤ÏÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë¡£
4448
4449     ¤¿¤È¤¨¤Ð CUI ´Ä¶­¤ÇÆ°ºî¤¹¤ë¥É¥é¥¤¥Ð¤Ï $X ¤È $Y 
4450     ¤ò¤½¤ì¤¾¤ìÎó¤È¹Ô¤ÎÈÖ¹æ¤È¤·¤ÆÍѤ¤¡¢$ASCENT ¤È $DESCENT 
4451     ¤ò̵»ë¤¹¤ë¤«¤â¤·¤ì¤Ê¤¤¡£ ¤Þ¤¿¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥àÍѤΥɥ饤¥Ð¤Ï
4452     $X ¤È $Y ¤ò¥¯¥é¥¤¥¢¥ó¥È¥¦¥£¥ó¥É¥¦¤Î¸¶ÅÀ¤«¤é¤Î¥ª¥Õ¥»¥Ã¥È¤ò¥Ô¥¯¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¤¡¢
4453     $ASCENT ¤È $DESCENT ¤ò ($X . $Y )
4454     ¤ÎÎó¤Î¥¢¥»¥ó¥È¤È¥Ç¥£¥»¥ó¥È¤ò¥Ô¥¯¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¦¤«¤â¤·¤ì¤Ê¤¤¡£
4455
4456     $FONTSIZE ¤Ë¤Ï preedit ¥Æ¥­¥¹¥È¤Î¥Õ¥©¥ó¥È¥µ¥¤¥º¤ò 1/10 ¥Ý¥¤¥ó¥Èñ°Ì¤Ç»ØÄꤹ¤ë¡£
4457
4458     $MT ¤È $POS ¤Ï¤½¤Î¥¹¥Ý¥Ã¥È¤Î M-text ¤Èʸ»ú°ÌÃ֤Ǥ¢¤ë¡£$MT ¤Ï @c
4459     NULL ¤Ç¤â¤è¤¯¡¢¤½¤Î¾ì¹ç¤Ë¤ÏÆþÎϥ᥽¥Ã¥É¤Ï¥¹¥Ý¥Ã¥È¼þÊդΥƥ­¥¹¥È¤Ë´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë¤³¤È¤¬¤Ç¤­¤Ê¤¤¡£
4460     */
4461
4462 void
4463 minput_set_spot (MInputContext *ic, int x, int y,
4464                  int ascent, int descent, int fontsize,
4465                  MText *mt, int pos)
4466 {
4467   ic->spot.x = x;
4468   ic->spot.y = y;
4469   ic->spot.ascent = ascent;
4470   ic->spot.descent = descent;
4471   ic->spot.fontsize = fontsize;
4472   ic->spot.mt = mt;
4473   ic->spot.pos = pos;
4474   if (ic->im->driver.callback_list)
4475     minput__callback (ic, Minput_set_spot);
4476 }
4477 /*=*/
4478
4479 /***en
4480     @brief Toggle input method.
4481
4482     The minput_toggle () function toggles the input method associated
4483     with input context $IC.  */
4484 /***ja
4485     @brief ÆþÎϥ᥽¥Ã¥É¤òÀÚÂؤ¨¤ë.
4486
4487     ´Ø¿ô minput_toggle () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC 
4488     ¤ËÂбþÉÕ¤±¤é¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ò¥È¥°¥ë¤¹¤ë¡£
4489     */
4490
4491 void
4492 minput_toggle (MInputContext *ic)
4493 {
4494   if (ic->im->driver.callback_list)
4495     minput__callback (ic, Minput_toggle);
4496   ic->active = ! ic->active;
4497 }
4498
4499 /*=*/
4500
4501 /***en
4502     @brief Reset an input context.
4503
4504     The minput_reset_ic () function resets input context $IC by
4505     calling a callback function corresponding to #Minput_reset.  It
4506     resets the status of $IC to its initial one.  As the
4507     current preedit text is deleted without commitment, if necessary,
4508     call minput_filter () with the arg @r key #Mnil to force the input
4509     method to commit the preedit in advance.  */
4510
4511 /***ja
4512     @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤ò¥ê¥»¥Ã¥È¤¹¤ë.
4513
4514     ´Ø¿ô minput_reset_ic () ¤Ï #Minput_reset ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô
4515     ¤ò¸Æ¤Ö¤³¤È¤Ë¤è¤Ã¤ÆÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤ò¥ê¥»¥Ã¥È¤¹¤ë¡£¥ê¥»¥Ã¥È¤È¤Ï¡¢
4516     ¼ÂºÝ¤Ë¤ÏÆþÎϥ᥽¥Ã¥É¤ò½é´ü¾õÂ֤˰ܤ¹¤³¤È¤Ç¤¢¤ë¡£¸½ºßÆþÎÏÃæ¤Î¥Æ¥­¥¹
4517     ¥È¤Ï¥³¥ß¥Ã¥È¤µ¤ì¤ë¤³¤È¤Ê¤¯ºï½ü¤µ¤ì¤ë¤Î¤Ç¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é
4518     ¥à¤Ï¡¢É¬Íפʤé¤Ðͽ¤á minput_filter () ¤ò°ú¿ô @r key #Mnil ¤Ç¸Æ¤ó¤Ç
4519     ¶¯À©Åª¤Ë¥×¥ê¥¨¥Ç¥£¥Ã¥È¥Æ¥­¥¹¥È¤ò¥³¥ß¥Ã¥È¤µ¤»¤ë¤³¤È¡£  */
4520
4521 void
4522 minput_reset_ic (MInputContext *ic)
4523 {
4524   if (ic->im->driver.callback_list)
4525     minput__callback (ic, Minput_reset);
4526 }
4527
4528 /*=*/
4529
4530 /***en
4531     @brief Get title and icon filename of an input method.
4532
4533     The minput_get_title_icon () function returns a plist containing a
4534     title and icon filename (if any) of an input method specified by
4535     $LANGUAGE and $NAME.
4536
4537     The first element of the plist has key #Mtext and the value is an
4538     M-text of the title for identifying the input method.  The second
4539     element (if any) has key #Mtext and the value is an M-text of the
4540     icon image (absolute) filename for the same purpose.
4541
4542     @return
4543     If there exists a specified input method and it defines an title,
4544     a plist is returned.  Otherwise, NULL is returned.  The caller
4545     must free the plist by m17n_object_unref ().  */
4546 /***ja
4547     @brief ÆþÎϥ᥽¥Ã¥É¤Î¥¿¥¤¥È¥ë¤È¥¢¥¤¥³¥óÍÑ¥Õ¥¡¥¤¥ë̾¤òÆÀ¤ë.
4548
4549     ´Ø¿ô minput_get_title_icon () ¤Ï¡¢ $LANGUAGE ¤È $NAME ¤Ç»ØÄꤵ¤ì¤ë
4550     ÆþÎϥ᥽¥Ã¥É¤Î¥¿¥¤¥È¥ë¤È¡Ê¤¢¤ì¤Ð¡Ë¥¢¥¤¥³¥óÍÑ¥Õ¥¡¥¤¥ë¤ò´Þ¤à plist ¤ò
4551     ÊÖ¤¹¡£
4552
4553     plist ¤ÎÂè°ìÍ×ÁǤϡ¢#Mtext ¤ò¥­¡¼¤Ë»ý¤Á¡¢ÃͤÏÆþÎϥ᥽¥Ã¥É¤ò¼±Ê̤¹¤ë
4554     ¥¿¥¤¥È¥ë¤òɽ¤¹ M-text ¤Ç¤¢¤ë¡£ÂèÆóÍ×ÁǤ¬¤¢¤ì¤Ð¡¢¥­¡¼¤Ï #Mtext ¤Ç¤¢
4555     ¤ê¡¢Ãͤϼ±ÊÌÍÑ¥¢¥¤¥³¥ó²èÁü¤ÎÀäÂÐ¥Õ¥¡¥¤¥ë¥Í¡¼¥à¤òɽ¤¹ M-text ¤Ç¤¢¤ë¡£
4556
4557     @return
4558     »ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤¬Â¸ºß¤·¡¢¥¿¥¤¥È¥ë¤¬ÄêµÁ¤µ¤ì¤Æ¤¤¤ì¤Ð
4559      plist ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð NULL ¤òÊÖ¤¹¡£¸Æ½Ð¦¤Ï
4560      ´Ø¿ô m17n_object_unref () ¤òÍѤ¤¤Æ plist ¤ò²òÊü¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£  */
4561
4562 MPlist *
4563 minput_get_title_icon (MSymbol language, MSymbol name)
4564 {
4565   MInputMethodInfo *im_info;
4566   MPlist *plist;
4567   char *file = NULL;
4568   MText *mt;
4569
4570   MINPUT__INIT ();
4571
4572   im_info = get_im_info (language, name, Mnil, Mtitle);
4573   if (! im_info || !im_info->title)
4574     return NULL;
4575   mt = mtext_get_prop (im_info->title, 0, Mtext);
4576   if (mt)
4577     file = mdatabase__find_file ((char *) MTEXT_DATA (mt));
4578   else
4579     {
4580       char *buf = alloca (MSYMBOL_NAMELEN (language) + MSYMBOL_NAMELEN (name)
4581                           + 12);
4582
4583       sprintf (buf, "icons/%s-%s.png", (char *) MSYMBOL_NAME (language), 
4584                (char *) MSYMBOL_NAME (name));
4585       file = mdatabase__find_file (buf);
4586       if (! file && language == Mt)
4587         {
4588           sprintf (buf, "icons/%s.png", (char *) MSYMBOL_NAME (name));
4589           file = mdatabase__find_file (buf);
4590         }
4591     }
4592
4593   plist = mplist ();
4594   mplist_add (plist, Mtext, im_info->title);
4595   if (file)
4596     {
4597       mt = mtext__from_data (file, strlen (file), MTEXT_FORMAT_UTF_8, 1);
4598       free (file);
4599       mplist_add (plist, Mtext, mt);
4600       M17N_OBJECT_UNREF (mt);
4601     }
4602   return plist;
4603 }
4604
4605 /*=*/
4606
4607 /***en
4608     @brief Get description text of an input method.
4609
4610     The minput_get_description () function returns an M-text that
4611     describes the input method specified by $LANGUAGE and $NAME.
4612
4613     @return
4614     If the specified input method has a description text, a pointer to
4615     #MText is returned.  The caller has to free it by m17n_object_unref ().
4616     If the input method does not have a description text, @c NULL is
4617     returned.  */
4618 /***ja
4619     @brief ÆþÎϥ᥽¥Ã¥É¤ÎÀâÌÀ¥Æ¥­¥¹¥È¤òÆÀ¤ë.
4620
4621     ´Ø¿ô minput_get_description () ¤Ï¡¢$LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ»ØÄê
4622     ¤µ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤òÀâÌÀ¤¹¤ë M-text ¤òÊÖ¤¹¡£
4623
4624     @return »ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤¬ÀâÌÀ¤¹¤ë¥Æ¥­¥¹¥È¤ò»ý¤Ã¤Æ¤¤¤ì¤Ð¡¢
4625     #MText ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¸Æ¤Ó½Ð¤·Â¦¤Ï¡¢¤½¤ì¤ò m17n_object_unref
4626     () ¤òÍѤ¤¤Æ²òÊü¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ÆþÎϥ᥽¥Ã¥É¤ËÀâÌÀ¥Æ¥­¥¹¥È¤¬Ìµ¤±
4627     ¤ì¤Ð@c NULL ¤òÊÖ¤¹¡£ */
4628
4629 MText *
4630 minput_get_description (MSymbol language, MSymbol name)
4631 {
4632   MInputMethodInfo *im_info;
4633   MSymbol extra;
4634
4635   MINPUT__INIT ();
4636
4637   if (name != Mnil)
4638     extra = Mnil;
4639   else
4640     extra = language, language = Mt;
4641
4642   im_info = get_im_info (language, name, extra, Mdescription);
4643   if (! im_info || ! im_info->description)
4644     return NULL;
4645   M17N_OBJECT_REF (im_info->description);
4646   return im_info->description;
4647 }
4648
4649 /*=*/
4650
4651 /***en
4652     @brief Get information about input method command(s).
4653
4654     The minput_get_command () function returns information about
4655     the command $COMMAND of the input method specified by $LANGUAGE and
4656     $NAME.  An input method command is a pseudo key event to which one
4657     or more actual input key sequences are assigned.
4658
4659     There are two kinds of commands, global and local.  A global
4660     command has a global definition, and the description and the key
4661     assignment may be inherited by a local command.  Each input method
4662     defines a local command which has a local key assignment.  It may
4663     also declare a local command that inherits the definition of a
4664     global command of the same name.
4665
4666     If $LANGUAGE is #Mt and $NAME is #Mnil, this function returns
4667     information about a global command.  Otherwise information about a
4668     local command is returned.
4669
4670     If $COMMAND is #Mnil, information about all commands is returned.
4671
4672     The return value is a @e well-formed plist (#m17nPlist) of this
4673     format:
4674 @verbatim
4675   ((NAME DESCRIPTION STATUS [KEYSEQ ...]) ...)
4676 @endverbatim
4677     @c NAME is a symbol representing the command name.
4678
4679     @c DESCRIPTION is an M-text describing the command, or #Mnil if the
4680     command has no description.
4681
4682     @c STATUS is a symbol representing how the key assignment is decided.
4683     The value is #Mnil (the default key assignment), #Mcustomized (the
4684     key assignment is customized by per-user configuration file), or
4685     #Mconfigured (the key assignment is set by the call of
4686     minput_config_command ()).  For a local command only, it may also
4687     be #Minherited (the key assignment is inherited from the
4688     corresponding global command).
4689
4690     @c KEYSEQ is a plist of one or more symbols representing a key
4691     sequence assigned to the command.  If there's no KEYSEQ, the
4692     command is currently disabled (i.e. no key sequence can trigger
4693     actions of the command).
4694
4695     If $COMMAND is not #Mnil, the first element of the returned plist
4696     contains the information about $COMMAND.
4697
4698     @return
4699
4700     If the requested information was found, a pointer to a non-empty
4701     plist is returned.  As the plist is kept in the library, the
4702     caller must not modify nor free it.
4703
4704     Otherwise (the specified input method or the specified command
4705     does not exist), @c NULL is returned.  */
4706 /***ja
4707     @brief ÆþÎϥ᥽¥Ã¥É¤Î¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë.
4708
4709     ´Ø¿ô minput_get_command () ¤Ï¡¢$LANGUAGE ¤È $NAME ¤Ç»ØÄꤵ¤ì¤ëÆþÎÏ
4710     ¥á¥½¥Ã¥É¤Î¥³¥Þ¥ó¥É $COMMAND ¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£ÆþÎϥ᥽¥Ã¥É¤Î¥³¥Þ
4711     ¥ó¥É¤È¤Ï¡¢µ¿»÷¥­¡¼¥¤¥Ù¥ó¥È¤Ç¤¢¤ê¡¢£±¤Ä°Ê¾å¤Î¼ÂºÝ¤ÎÆþÎÏ¥­¡¼¥·¡¼¥¯¥¨
4712     ¥ó¥¹¤¬³ä¤êÅö¤Æ¤é¤ì¤ë¡£
4713
4714     ¥³¥Þ¥ó¥É¤Ë¤Ï¡¢¥°¥í¡¼¥Ð¥ë¤È¥í¡¼¥«¥ë¤Î£²¼ïÎब¤¢¤ë¡£¥°¥í¡¼¥Ð¥ë¤Ê¥³¥Þ¥ó¥É
4715     ¤Ï¥°¥í¡¼¥Ð¥ë¤ËÄêµÁ¤µ¤ì¡¢¥í¡¼¥«¥ë¤Ê¥³¥Þ¥ó¥É¤Ï¤½¤ÎÀâÌÀ¤È¥­¡¼³ä¤êÅö¤Æ
4716     ¤ò·Ñ¾µ¤¹¤ë¤³¤È¤¬¤Ç¤­¤ë¡£³ÆÆþÎϥ᥽¥Ã¥É¤Ï¥í¡¼¥«¥ë¤Ê¥­¡¼³äÅö¤ò»ý¤Ä¥í¡¼
4717     ¥«¥ë¤Ê¥³¥Þ¥ó¥É¤òÄêµÁ¤¹¤ë¡£¤Þ¤¿Æ±Ì¾¤Î¥°¥í¡¼¥Ð¥ë¤Ê¥³¥Þ¥ó¥É¤ÎÄêµÁ¤ò·Ñ
4718     ¾µ¤¹¤ë¥í¡¼¥«¥ë¤Ê¥³¥Þ¥ó¥É¤òÀë¸À¤¹¤ë¤³¤È¤â¤Ç¤­¤ë¡£
4719
4720     $LANGUAGE ¤¬ #Mt ¤Ç $NAME ¤¬ #Mnil ¤Î¾ì¹ç¤Ï¡¢¤³¤Î´Ø¿ô¤Ï¥°¥í¡¼¥Ð¥ë¥³
4721     ¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¥í¡¼¥«¥ë¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¤â
4722     ¤Î¤òÊÖ¤¹¡£
4723
4724     $COMMAND ¤¬ #Mnil ¤Î¾ì¹ç¤Ï¡¢¤¹¤Ù¤Æ¤Î¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£
4725
4726     Ìá¤êÃͤϰʲ¼¤Î·Á¼°¤Î @e well-formed plist (#m17nPlist) ¤Ç¤¢¤ë¡£
4727
4728 @verbatim
4729   ((NAME DESCRIPTION STATUS [KEYSEQ ...]) ...)
4730 @endverbatim
4731     @c NAME ¤Ï¥³¥Þ¥ó¥É̾¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
4732
4733     @c DESCRIPTION ¤Ï¥³¥Þ¥ó¥É¤òÀâÌÀ¤¹¤ë M-text ¤Ç¤¢¤ë¤«¡¢ÀâÌÀ¤¬Ìµ¤¤¾ì¹ç¤Ë
4734     ¤Ï #Mnil ¤Ç¤¢¤ë¡£
4735
4736     @c STATUS ¤Ï¥­¡¼³ä¤êÅö¤Æ¤¬¤É¤Î¤è¤¦¤ËÄê¤á¤é¤ì¤ë¤«¤ò¤¢¤é¤ï¤¹¥·¥ó¥Ü¥ë¤Ç¤¢
4737     ¤ê¡¢¤½¤ÎÃͤϠ#Mnil ¡Ê¥Ç¥Õ¥©¥ë¥È¤Î³ä¤êÅö¤Æ¡Ë, #Mcustomized ¡Ê¥æ¡¼¥¶
4738     Ëè¤ÎÀßÄê¥Õ¥¡¥¤¥ë¤Ë¤è¤Ã¤Æ¥«¥¹¥¿¥Þ¥¤¥º¤µ¤ì¤¿³ä¤êÅö¤Æ¡Ë, #Mconfigured
4739     ¡Êminput_config_command ()¤ò¸Æ¤Ö¤³¤È¤Ë¤è¤Ã¤ÆÀßÄꤵ¤ì¤ë³ä¤êÅö¤Æ¡Ë¤Î
4740     ¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£¥í¡¼¥«¥ë¥³¥Þ¥ó¥É¤Î¾ì¹ç¤Ë¤Ï¡¢#Minherited ¡ÊÂбþ¤¹¤ë
4741     ¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É¤«¤é¤Î·Ñ¾µ¤Ë¤è¤ë³ä¤êÅö¤Æ¡Ë¤Ç¤â¤è¤¤¡£
4742
4743     @c KEYSEQ ¤Ï£±¤Ä°Ê¾å¤Î¥·¥ó¥Ü¥ë¤«¤é¤Ê¤ë plist ¤Ç¤¢¤ê¡¢³Æ¥·¥ó¥Ü¥ë¤Ï¥³¥Þ
4744     ¥ó¥É¤Ë³ä¤êÅö¤Æ¤é¤ì¤Æ¤¤¤ë¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤òɽ¤¹¡£KEYSEQ ¤¬Ìµ¤¤¾ì¹ç¤Ï¡¢
4745     ¤½¤Î¥³¥Þ¥ó¥É¤Ï¸½¾õ¤Ç»ÈÍÑÉÔǽ¤Ç¤¢¤ë¡£¡Ê¤¹¤Ê¤ï¤Á¥³¥Þ¥ó¥É¤ÎÆ°ºî¤òµ¯
4746     Æ°¤Ç¤­¤ë¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤¬Ìµ¤¤¡£¡Ë
4747
4748     $COMMAND ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢ÊÖ¤µ¤ì¤ë plist ¤ÎºÇ½é¤ÎÍ×ÁǤϡ¢
4749     $COMMAND ¤Ë´Ø¤¹¤ë¾ðÊó¤ò´Þ¤à¡£
4750
4751     @return
4752
4753     µá¤á¤é¤ì¤¿¾ðÊ󤬸«¤Ä¤«¤ì¤Ð¡¢¶õ¤Ç¤Ê¤¤ plist ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¥ê¥¹
4754     ¥È¤Ï¥é¥¤¥Ö¥é¥ê¤¬´ÉÍý¤·¤Æ¤¤¤ë¤Î¤Ç¡¢¸Æ½Ð¦¤¬Êѹ¹¤·¤¿¤ê²òÊü¤·¤¿¤ê¤¹¤ë
4755     ¤³¤È¤Ï¤Ç¤­¤Ê¤¤¡£
4756
4757     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¤¹¤Ê¤ï¤Á»ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤ä¥³¥Þ¥ó¥É¤¬Â¸ºß¤·¤Ê¤±¤ì¤Ð
4758     @c NULL ¤òÊÖ¤¹¡£  */
4759
4760 #if EXAMPLE_CODE
4761 MText *
4762 get_im_command_description (MSymbol language, MSymbol name, MSymbol command)
4763 {
4764   /* Return a description of the command COMMAND of the input method
4765      specified by LANGUAGE and NAME.  */
4766   MPlist *cmd = minput_get_command (langauge, name, command);
4767   MPlist *plist;
4768
4769   if (! cmds)
4770     return NULL;
4771   plist = mplist_value (cmds);  /* (NAME DESCRIPTION KEY-SEQ ...) */
4772   plist = mplist_next (plist);  /* (DESCRIPTION KEY-SEQ ...) */
4773   return  (mplist_key (plist) == Mtext
4774            ? (MText *) mplist_value (plist)
4775            : NULL);
4776 }
4777 #endif
4778
4779 MPlist *
4780 minput_get_command (MSymbol language, MSymbol name, MSymbol command)
4781 {
4782   MInputMethodInfo *im_info;
4783
4784   MINPUT__INIT ();
4785
4786   im_info = get_im_info (language, name, Mnil, Mcommand);
4787   if (! im_info
4788       || ! im_info->configured_cmds
4789       || MPLIST_TAIL_P (im_info->configured_cmds))
4790     return NULL;
4791   if (command == Mnil)
4792     return im_info->configured_cmds;
4793   return mplist__assq (im_info->configured_cmds, command);
4794 }
4795
4796 /*=*/
4797
4798 /***en
4799     @brief Configure the key sequence of an input method command.
4800
4801     The minput_config_command () function assigns a list of key
4802     sequences $KEYSEQLIST to the command $COMMAND of the input method
4803     specified by $LANGUAGE and $NAME.
4804
4805     If $KEYSEQLIST is a non-empty plist, it must be a list of key
4806     sequences, and each key sequence must be a plist of symbols.
4807
4808     If $KEYSEQLIST is an empty plist, the command becomes unusable.
4809
4810     If $KEYSEQLIST is NULL, the configuration of the command for the
4811     input method is canceled, and the default key sequences become
4812     effective.  In such case, if $COMMAND is #Mnil, configurations for
4813     all commands of the input method are canceled.
4814
4815     If $NAME is #Mnil, this function configures the key assignment of a
4816     global command, not that of a specific input method.
4817
4818     The configuration takes effect for input methods opened or
4819     re-opened later in the current session.  In order to make the
4820     configuration take effect for the future session, it must be saved
4821     in a per-user configuration file by the function
4822     minput_save_config ().
4823
4824     @return
4825
4826     If the operation was successful, this function returns 0,
4827     otherwise returns -1.  The operation fails in these cases:
4828     <ul>
4829     <li>$KEYSEQLIST is not in a valid form.
4830     <li>$COMMAND is not available for the input method.
4831     <li>$LANGUAGE and $NAME do not specify an existing input method.
4832     </ul>
4833
4834     @seealso
4835     minput_get_commands (), minput_save_config ().
4836 */
4837 /***ja
4838     @brief ÆþÎϥ᥽¥Ã¥É¤Î¥³¥Þ¥ó¥É¤Î¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤òÀßÄꤹ¤ë.
4839
4840     ´Ø¿ô minput_config_command () ¤Ï¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤Î¥ê¥¹¥È
4841     $KEYSEQLIST ¤ò¡¢$LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤ëÆþÎϥ᥽¥Ã¥É¤Î
4842     ¥³¥Þ¥ó¥É $COMMAND ¤Ë³ä¤êÅö¤Æ¤ë¡£
4843
4844     $KEYSEQLIST ¤¬¶õ¥ê¥¹¥È¤Ç¤Ê¤±¤ì¤Ð¡¢¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤Î¥ê¥¹¥È¤Ç¤¢¤ê¡¢
4845     ³Æ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤Ï¥·¥ó¥Ü¥ë¤Î plist ¤Ç¤¢¤ë¡£
4846
4847     $KEYSEQLIST ¤¬¶õ¤Î plist ¤Ê¤é¤Ð¡¢¥³¥Þ¥ó¥É¤Ï»ÈÍѤǤ­¤Ê¤¯¤Ê¤ë¡£
4848
4849     $KEYSEQLIST ¤¬ NULL ¤Ç¤¢¤ì¤Ð¡¢»ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤Î¥³¥Þ¥ó¥É¤ÎÀßÄê¤Ï
4850     ¥­¥ã¥ó¥»¥ë¤µ¤ì¡¢¥Ç¥Õ¥©¥ë¥È¤Î¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤¬Í­¸ú¤Ë¤Ê¤ë¡£¤³¤Î¾ì¹ç¡¢
4851     $COMMAND ¤¬ #Mnil ¤Ê¤é¤Ð»ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤ÎÁ´¤Æ¤Î¥³¥Þ¥ó¥É¤ÎÀßÄ꤬
4852     ¥­¥ã¥ó¥»¥ë¤µ¤ì¤ë¡£
4853
4854     $NAME ¤¬ #Mnil ¤Ê¤é¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¸Ä¡¹¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¤Ê¤¯¥°¥í¡¼¥Ð
4855     ¥ë¤Ê¥³¥Þ¥ó¥É¤Î¥­¡¼³ä¤êÅö¤Æ¤òÀßÄꤹ¤ë¡£
4856
4857     ¤³¤ì¤é¤ÎÀßÄê¤Ï¡¢¸½¹Ô¤Î¥»¥Ã¥·¥ç¥óÃæ¤ÇÆþÎϥ᥽¥Ã¥É¤¬¥ª¡¼¥×¥ó¡Ê¤Þ¤¿¤Ï
4858     ºÆ¥ª¡¼¥×¥ó¡Ë¤µ¤ì¤¿»þÅÀ¤ÇÍ­¸ú¤Ë¤Ê¤ë¡£¾­Íè¤Î¥»¥Ã¥·¥ç¥óÃæ¤Ç¤âÍ­¸ú¤Ë¤¹
4859     ¤ë¤¿¤á¤Ë¤Ï¡¢´Ø¿ô minput_save_config () ¤òÍѤ¤¤Æ¥æ¡¼¥¶Ëè¤ÎÀßÄê¥Õ¥¡¥¤
4860     ¥ë¤ËÊݸ¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
4861
4862     @return
4863
4864     ¤³¤Î´Ø¿ô¤Ï¡¢½èÍý¤¬À®¸ù¤¹¤ì¤Ð 0 ¤ò¡¢¼ºÇÔ¤¹¤ì¤Ð -1 ¤òÊÖ¤¹¡£¼ºÇԤȤϰʲ¼¤Î¾ì¹ç¤Ç¤¢¤ë¡£
4865     <ul>
4866     <li>$KEYSEQLIST ¤¬Í­¸ú¤Ê·Á¼°¤Ç¤Ê¤¤¡£
4867     <li>$COMMAND ¤¬»ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤ÇÍøÍѤǤ­¤Ê¤¤¡£
4868     <li>$LANGUAGE ¤È $NAME ¤Ç»ØÄꤵ¤ì¤ëÆþÎϥ᥽¥Ã¥É¤¬Â¸ºß¤·¤Ê¤¤¡£
4869     </ul>
4870
4871     @seealso
4872     minput_get_commands (), minput_save_config ().
4873 */
4874
4875 #if EXAMPLE_CODE
4876 /* Add "C-x u" to the "start" command of Unicode input method.  */
4877 {
4878   MSymbol start_command = msymbol ("start");
4879   MSymbol unicode = msymbol ("unicode");
4880   MPlist *cmd, *plist, *key_seq_list, *key_seq;
4881
4882   /* At first get the current key-sequence assignment.  */
4883   cmd = mplist_get_command (Mt, unicode, start_command);
4884   if (! cmd)
4885     {
4886       /* The input method does not have the command "start".  Here
4887          should come some error handling code.  */
4888     }
4889   /* Now CMD == ((start DESCRIPTION KEY-SEQUENCE ...) ...).  Extract
4890      the part (KEY-SEQUENCE ...).  */
4891   plist = mplist_next (mplist_next (mplist_value (cmd)));
4892   /* Copy it because we should not modify it directly.  */
4893   key_seq_list = mplist_copy (plist);
4894   m17n_object_unref (cmds);
4895   
4896   key_seq = mplist ();
4897   mplist_add (key_seq, Msymbol, msymbol ("C-x"));
4898   mplist_add (key_seq, Msymbol, msymbol ("u"));
4899   mplist_add (key_seq_list, Mplist, key_seq);
4900   m17n_object_unref (key_seq);
4901
4902   minput_config_command (Mt, unicode, start_command, key_seq_list);
4903   m17n_object_unref (key_seq_list);
4904 }
4905 #endif
4906
4907 int
4908 minput_config_command (MSymbol language, MSymbol name, MSymbol command,
4909                        MPlist *keyseqlist)
4910 {
4911   MInputMethodInfo *im_info, *config;
4912   MPlist *plist;
4913
4914   MINPUT__INIT ();
4915
4916   if (keyseqlist)
4917     {
4918       if (command == Mnil)
4919         MERROR (MERROR_IM, -1);
4920       MPLIST_DO (plist, keyseqlist)
4921         if (! MPLIST_PLIST_P (plist)
4922             || ! check_command_keyseq (plist))
4923           MERROR (MERROR_IM, -1);
4924     }
4925
4926   im_info = get_im_info (language, name, Mnil, Mcommand);
4927   if (! im_info)
4928     MERROR (MERROR_IM, -1);
4929   if (command != Mnil
4930       && (! im_info->cmds
4931           || ! mplist__assq (im_info->cmds, command)))
4932     MERROR (MERROR_IM, -1);
4933
4934   config = get_config_info (im_info);
4935   if (! config)
4936     {
4937       if (! im_config_list)
4938         im_config_list = mplist ();
4939       config = new_im_info (NULL, language, name, Mnil, im_config_list);
4940       config->cmds = mplist ();
4941       config->vars = mplist ();
4942     }
4943
4944   if (command == Mnil)
4945     {
4946       MInputMethodInfo *custom = get_custom_info (im_info);
4947
4948       mplist_set (config->cmds, Mnil, NULL);
4949       if (custom && custom->cmds)
4950         {
4951           MPLIST_DO (plist, custom->cmds)
4952             {
4953               command = MPLIST_SYMBOL (MPLIST_PLIST (plist));
4954               plist = mplist ();
4955               mplist_add (plist, Msymbol, command);
4956               mplist_push (config->cmds, Mplist, plist);
4957               M17N_OBJECT_UNREF (plist);
4958             }
4959         }
4960     }
4961   else
4962     {
4963       plist = mplist__assq (config->cmds, command);
4964       if (plist)
4965         {
4966           plist = MPLIST_PLIST (plist); /* (NAME [nil KEY-SEQUENCE ...])  */
4967           plist = MPLIST_NEXT (plist);  /* ([nil ...]) */
4968           if (! MPLIST_TAIL_P (plist))
4969             mplist_set (plist, Mnil, NULL); /* () */
4970         }
4971       else
4972         {
4973           plist = mplist ();
4974           mplist_add (config->cmds, Mplist, plist);
4975           M17N_OBJECT_UNREF (plist);
4976           plist = mplist_add (plist, Msymbol, command);
4977           plist = MPLIST_NEXT (plist);
4978         }
4979       if (keyseqlist)
4980         {
4981           MPlist *pl;
4982
4983           plist = mplist_add (plist, Msymbol, Mnil);
4984           MPLIST_DO (keyseqlist, keyseqlist)
4985             {
4986               pl = mplist_copy (MPLIST_VAL (keyseqlist));
4987               plist = mplist_add (plist, Mplist, pl);
4988               M17N_OBJECT_UNREF (pl);
4989             }
4990         }
4991     }
4992   config_all_commands (im_info);
4993   im_info->tick = time (NULL);
4994   return 0;
4995 }
4996
4997 /*=*/
4998
4999 /***en
5000     @brief Get information about input method variable(s).
5001
5002     The minput_get_variable () function returns information about
5003     the variable $VARIABLE of the input method specified by $LANGUAGE and $NAME.
5004     An input method variable controls behavior of an input method.
5005
5006     There are two kinds of variables, global and local.  A global
5007     variable has a global definition, and the description and the value
5008     may be inherited by a local variable.  Each input method defines a
5009     local variable which has local value.  It may also declare a
5010     local variable that inherits definition of a global variable of
5011     the same name.
5012
5013     If $LANGUAGE is #Mt and $NAME is #Mnil, information about a global
5014     variable is returned.  Otherwise information about a local variable
5015     is returned.
5016
5017     If $VARIABLE is #Mnil, information about all variables is
5018     returned.
5019
5020     The return value is a @e well-formed plist (#m17nPlist) of this
5021     format:
5022 @verbatim
5023   ((NAME DESCRIPTION STATUS VALUE [VALID-VALUE ...]) ...)
5024 @endverbatim
5025     @c NAME is a symbol representing the variable name.
5026
5027     @c DESCRIPTION is an M-text describing the variable, or #Mnil if the
5028     variable has no description.
5029
5030     @c STATUS is a symbol representing how the value is decided.  The
5031     value is #Mnil (the default value), #Mcustomized (the value is
5032     customized by per-user configuration file), or #Mconfigured (the
5033     value is set by the call of minput_config_variable ()).  For a
5034     local variable only, it may also be #Minherited (the value is
5035     inherited from the corresponding global variable).
5036
5037     @c VALUE is the initial value of the variable.  If the key of this
5038     element is #Mt, the variable has no initial value.  Otherwise, the
5039     key is #Minteger, #Msymbol, or #Mtext and the value is of the
5040     corresponding type.
5041
5042     @c VALID-VALUEs (if any) specify which values the variable can have.
5043     They have the same type (i.e. having the same key) as @c VALUE except
5044     for the case that VALUE is an integer.  In that case, @c VALID-VALUE
5045     may be a plist of two integers specifying the range of possible
5046     values.
5047
5048     If there no @c VALID-VALUE, the variable can have any value as long
5049     as the type is the same as @c VALUE.
5050
5051     If $VARIABLE is not #Mnil, the first element of the returned plist
5052     contains the information about $VARIABLE.
5053
5054     @return
5055
5056     If the requested information was found, a pointer to a non-empty
5057     plist is returned.  As the plist is kept in the library, the
5058     caller must not modify nor free it.
5059
5060     Otherwise (the specified input method or the specified variable
5061     does not exist), @c NULL is returned.  */
5062 /***ja
5063     @brief ÆþÎϥ᥽¥Ã¥É¤ÎÊÑ¿ô¤Ë´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë.
5064
5065     ´Ø¿ô minput_get_variable () ¤Ï¡¢$LANGUAGE ¤È $NAME ¤Ç»ØÄꤵ¤ì¤ëÆþÎÏ
5066     ¥á¥½¥Ã¥É¤ÎÊÑ¿ô $VARIABLE ¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£ÆþÎϥ᥽¥Ã¥É¤ÎÊÑ¿ô¤È¤Ï¡¢
5067     ÆþÎϥ᥽¥Ã¥É¤Î¿¶Éñ¤òÀ©¸æ¤¹¤ë¤â¤Î¤Ç¤¢¤ë¡£
5068
5069     ÊÑ¿ô¤Ë¤Ï¡¢¥°¥í¡¼¥Ð¥ë¤È¥í¡¼¥«¥ë¤Î£²¼ïÎब¤¢¤ë¡£¥°¥í¡¼¥Ð¥ë¤ÊÊÑ¿ô¤Ï¥°
5070     ¥í¡¼¥Ð¥ë¤ËÄêµÁ¤µ¤ì¡¢¥í¡¼¥«¥ë¤ÊÊÑ¿ô¤Ï¤½¤ÎÀâÌÀ¤ÈÃͤò·Ñ¾µ¤¹¤ë¤³¤È¤¬¤Ç
5071     ¤­¤ë¡£³ÆÆþÎϥ᥽¥Ã¥É¤Ï¥í¡¼¥«¥ë¤ÊÃͤò»ý¤Ä¥í¡¼¥«¥ë¤ÊÊÑ¿ô¤òÄêµÁ¤¹¤ë¡£
5072     ¤Þ¤¿Æ±Ì¾¤Î¥°¥í¡¼¥Ð¥ë¤ÊÊÑ¿ô¤ÎÄêµÁ¤ò·Ñ¾µ¤¹¤ë¥í¡¼¥«¥ë¤ÊÊÑ¿ô¤òÀë¸À¤¹¤ë
5073     ¤³¤È¤â¤Ç¤­¤ë¡£
5074
5075     $LANGUAGE ¤¬ #Mt ¤Ç $NAME ¤¬ #Mnil ¤Î¾ì¹ç¤Ï¡¢¤³¤Î´Ø¿ô¤Ï¥°¥í¡¼¥Ð¥ëÊÑ
5076     ¿ô¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¥í¡¼¥«¥ëÊÑ¿ô¤Ë´Ø¤¹¤ë¤â¤Î¤òÊÖ¤¹¡£
5077
5078     $VARIABLE ¤¬ #Mnil ¤Î¾ì¹ç¤Ï¡¢¤¹¤Ù¤Æ¤Î¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£
5079
5080     Ìá¤êÃͤϰʲ¼¤Î·Á¼°¤Î @e well-formed plist (#m17nPlist) ¤Ç¤¢¤ë¡£
5081 @verbatim
5082   ((NAME DESCRIPTION STATUS VALUE [VALID-VALUE ...]) ...)
5083 @endverbatim
5084
5085     @c NAME ¤ÏÊÑ¿ô¤Î̾Á°¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
5086
5087     @c DESCRIPTION ¤ÏÊÑ¿ô¤òÀâÌÀ¤¹¤ë M-text ¤Ç¤¢¤ë¤«¡¢ÀâÌÀ¤¬Ìµ¤¤¾ì¹ç¤Ë¤Ï
5088     #Mnil ¤Ç¤¢¤ë¡£
5089
5090     @c STATUS ¤ÏÃͤ¬¤É¤Î¤è¤¦¤ËÄê¤á¤é¤ì¤ë¤«¤ò¤¢¤é¤ï¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢
5091     @c STATUS ¤ÎÃͤϠ#Mnil ¡Ê¥Ç¥Õ¥©¥ë¥È¤ÎÃÍ¡Ë, #Mcustomized ¡Ê¥æ¡¼¥¶Ëè¤ÎÀß
5092     Äê¥Õ¥¡¥¤¥ë¤Ë¤è¤Ã¤Æ¥«¥¹¥¿¥Þ¥¤¥º¤µ¤ì¤¿ÃÍ¡Ë, #Mconfigured
5093     ¡Êminput_config_variable ()¤ò¸Æ¤Ö¤³¤È¤Ë¤è¤Ã¤ÆÀßÄꤵ¤ì¤ëÃ͡ˤΤ¤¤º¤ì
5094     ¤«¤Ç¤¢¤ë¡£¥í¡¼¥«¥ëÊÑ¿ô¤Î¾ì¹ç¤Ë¤Ï¡¢#Minherited ¡ÊÂбþ¤¹¤ë¥°¥í¡¼¥Ð¥ë
5095     ÊÑ¿ô¤«¤é·Ñ¾µ¤·¤¿Ã͡ˤǤâ¤è¤¤¡£
5096
5097     @c VALUE ¤ÏÊÑ¿ô¤Î½é´üÃͤǤ¢¤ë¡£¤³¤ÎÍ×ÁǤΥ­¡¼¤¬#Mt ¤Ç¤¢¤ì¤Ð½é´üÃͤò»ý
5098     ¤¿¤Ê¤¤¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¥­¡¼¤Ï #Minteger, #Msymbol, #Mtext ¤Î¤¤¤º¤ì
5099     ¤«¤Ç¤¢¤ê¡¢ÃͤϤ½¤ì¤¾¤ìÂбþ¤¹¤ë·¿¤Î¤â¤Î¤Ç¤¢¤ë¡£
5100
5101     @c VALID-VALUE ¤Ï¤â¤·¤¢¤ì¤Ð¡¢ÊÑ¿ô¤Î¼è¤êÆÀ¤ëÃͤò»ØÄꤹ¤ë¡£¤³¤ì¤Ï @c VALUE
5102     ¤ÈƱ¤¸·¿(¤¹¤Ê¤ï¤ÁƱ¤¸¥­¡¼¤ò»ý¤Ä) ¤Ç¤¢¤ë¤¬¡¢Îã³°¤È¤·¤Æ @c VALUE ¤¬
5103     integer ¤Î¾ì¹ç¤Ï @c VALID-VALUE ¤Ï²Äǽ¤ÊÃͤÎÈϰϤò¼¨¤¹Æó¤Ä¤ÎÀ°¿ô¤«¤é
5104     ¤Ê¤ë plist ¤È¤Ê¤ë¤³¤È¤¬¤Ç¤­¤ë¡£
5105
5106     @c VALID-VALUE ¤¬¤Ê¤±¤ì¤Ð¡¢ÊÑ¿ô¤Ï @c VALUE ¤ÈƱ¤¸·¿¤Ç¤¢¤ë¸Â¤ê¤¤¤«¤Ê¤ëÃͤâ
5107     ¤È¤ë¤³¤È¤¬¤Ç¤­¤ë¡£
5108
5109     $VARIABLE ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢ÊÖ¤µ¤ì¤ë plist ¤ÎºÇ½é¤ÎÍ×ÁǤÏ
5110     $VARIABLE ¤Ë´Ø¤¹¤ë¾ðÊó¤ò´Þ¤à¡£
5111
5112     @return
5113
5114     µá¤á¤é¤ì¤¿¾ðÊ󤬸«¤Ä¤«¤ì¤Ð¡¢¶õ¤Ç¤Ê¤¤ plist ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¥ê¥¹
5115     ¥È¤Ï¥é¥¤¥Ö¥é¥ê¤¬´ÉÍý¤·¤Æ¤¤¤ë¤Î¤Ç¡¢¸Æ½Ð¦¤¬Êѹ¹¤·¤¿¤ê²òÊü¤·¤¿¤ê¤¹¤ë
5116     ¤³¤È¤Ï¤Ç¤­¤Ê¤¤¡£
5117
5118     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¤¹¤Ê¤ï¤Á»ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤äÊÑ¿ô¤¬Â¸ºß¤·¤Ê¤±¤ì¤Ð
5119     @c NULL ¤òÊÖ¤¹¡£ */
5120
5121 MPlist *
5122 minput_get_variable (MSymbol language, MSymbol name, MSymbol variable)
5123 {
5124   MInputMethodInfo *im_info;
5125
5126   MINPUT__INIT ();
5127
5128   im_info = get_im_info (language, name, Mnil, Mvariable);
5129   if (! im_info || ! im_info->configured_vars)
5130     return NULL;
5131   if (variable == Mnil)
5132     return im_info->configured_vars;
5133   return mplist__assq (im_info->configured_vars, variable);
5134 }
5135
5136 /*=*/
5137
5138 /***en
5139     @brief Configure the value of an input method variable.
5140
5141     The minput_config_variable () function assigns $VALUE to the
5142     variable $VARIABLE of the input method specified by $LANGUAGE and
5143     $NAME.
5144
5145     If $VALUE is not NULL, it must be a plist of one element whose key
5146     is #Minteger, #Msymbol, or #Mtext, and the value is of the
5147     corresponding type.
5148
5149     If $VALUE is NULL, a configuration for the variable for the input
5150     method is canceled, and the variable is initialized to the default
5151     value.  In that case, if $VARIABLE is #Mnil, configurations for
5152     all variables of the input method are canceled.
5153
5154     If $NAME is #Mnil, this function configure the value of global
5155     variable, not that of a specific input method.
5156
5157     The configuration takes effect for input methods opened or
5158     re-opened later in the current session.  To make the configuration
5159     take effect for the future session, it must be saved in a per-user
5160     configuration file by the function minput_save_config ().
5161
5162     @return
5163
5164     If the operation was successful, this function returns 0,
5165     otherwise returns -1.  The operation fails in these cases:
5166     <ul>
5167     <li>$VALUE is not in a valid form, the type does not match the
5168     definition, or the value is our of range.
5169     <li>$VARIABLE is not available for the input method.
5170     <li>$LANGUAGE and $NAME do not specify an existing input method.  
5171     </ul>
5172
5173     @seealso
5174     minput_get_variable (), minput_save_config ().  */
5175 /***ja
5176     @brief ÆþÎϥ᥽¥Ã¥É¤ÎÊÑ¿ô¤ÎÃͤòÀßÄꤹ¤ë.
5177
5178     ´Ø¿ô minput_config_variable () ¤ÏÃÍ $VALUE ¤ò¡¢$LANGUAGE ¤È $NAME
5179     ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤ëÆþÎϥ᥽¥Ã¥É¤ÎÊÑ¿ô $VARIABLE ¤Ë³ä¤êÅö¤Æ¤ë¡£
5180
5181     $VALUE ¤¬ NULL¤Ç¤Ê¤±¤ì¤Ð¡¢£±Í×ÁǤΠplist ¤Ç¤¢¤ê¡¢¤½¤Î¥­¡¼¤Ï
5182     #Minteger, #Msymbol, #Mtext ¤Î¤¤¤º¤ì¤«¡¢ÃͤÏÂбþ¤¹¤ë·¿¤Î¤â¤Î¤Ç¤¢¤ë¡£
5183
5184     $VALUE ¤¬ NULL ¤Ç¤¢¤ì¤Ð¡¢»ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤ÎÊÑ¿ô¤ÎÀßÄê¤Ï¥­¥ã¥ó¥»¥ë
5185     ¤µ¤ì¡¢ÊÑ¿ô¤Ï¥Ç¥Õ¥©¥ë¥ÈÃͤ˽é´ü²½¤µ¤ì¤ë¡£¤³¤Î¾ì¹ç¡¢$VARIABLE ¤¬
5186     #Mnil ¤Ê¤é¤Ð»ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤ÎÁ´¤Æ¤ÎÊÑ¿ô¤ÎÀßÄ꤬¥­¥ã¥ó¥»¥ë¤µ¤ì¤ë¡£
5187
5188     $NAME ¤¬ #Mnil ¤Ê¤é¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¸Ä¡¹¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¤Ê¤¯¥°¥í¡¼¥Ð
5189     ¥ë¤ÊÊÑ¿ô¤ÎÃͤòÀßÄꤹ¤ë¡£
5190
5191     ¤³¤ì¤é¤ÎÀßÄê¤Ï¡¢¸½¹Ô¤Î¥»¥Ã¥·¥ç¥óÃæ¤ÇÆþÎϥ᥽¥Ã¥É¤¬¥ª¡¼¥×¥ó¡Ê¤Þ¤¿¤Ï
5192     ºÆ¥ª¡¼¥×¥ó¡Ë¤µ¤ì¤¿»þÅÀ¤ÇÍ­¸ú¤Ë¤Ê¤ë¡£¾­Íè¤Î¥»¥Ã¥·¥ç¥óÃæ¤Ç¤âÍ­¸ú¤Ë¤¹
5193     ¤ë¤¿¤á¤Ë¤Ï¡¢´Ø¿ô minput_save_config () ¤òÍѤ¤¤Æ¥æ¡¼¥¶Ëè¤ÎÀßÄê¥Õ¥¡¥¤
5194     ¥ë¤ËÊݸ¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
5195
5196     @return
5197
5198     ¤³¤Î´Ø¿ô¤Ï¡¢½èÍý¤¬À®¸ù¤¹¤ì¤Ð 0 ¤ò¡¢¼ºÇÔ¤¹¤ì¤Ð -1 ¤òÊÖ¤¹¡£¼ºÇԤȤϰʲ¼¤Î¾ì¹ç¤Ç¤¢¤ë¡£
5199     <ul>
5200     <li>$VALUE¤¬Í­¸ú¤Ê·Á¼°¤Ç¤Ê¤¤¡£·¿¤¬ÄêµÁ¤Ë¹ç¤ï¤Ê¤¤¡¢¤Þ¤¿¤ÏÃͤ¬Èϰϳ°¤Ç¤¢¤ë¡£
5201     <li>$VARIABLE ¤¬»ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤ÇÍøÍѤǤ­¤Ê¤¤¡£
5202     <li>$LANGUAGE ¤È $NAME ¤Ç»ØÄꤵ¤ì¤ëÆþÎϥ᥽¥Ã¥É¤¬Â¸ºß¤·¤Ê¤¤¡£
5203     </ul>
5204
5205     @seealso
5206     minput_get_commands (), minput_save_config ().
5207 */
5208 int
5209 minput_config_variable (MSymbol language, MSymbol name, MSymbol variable,
5210                         MPlist *value)
5211 {
5212   MInputMethodInfo *im_info, *config;
5213   MPlist *plist;
5214
5215   MINPUT__INIT ();
5216
5217   im_info = get_im_info (language, name, Mnil, Mvariable);
5218   if (! im_info)
5219     MERROR (MERROR_IM, -1);
5220   if (variable == Mnil)
5221     {
5222       if (value)
5223         MERROR (MERROR_IM, -1);
5224     }
5225   else if (! im_info->vars
5226            || ! (plist = mplist__assq (im_info->configured_vars, variable)))
5227     MERROR (MERROR_IM, -1);
5228
5229   if (variable != Mnil && value)
5230     {
5231       plist = MPLIST_PLIST (plist);
5232       plist = MPLIST_NEXT (plist); /* (DESC STATUS VALUE VALIDS ...) */
5233       plist = MPLIST_NEXT (plist); /* (STATUS VALUE VALIDS ...) */
5234       plist = MPLIST_NEXT (plist); /* (VALUE VALIDS ...) */
5235       if (MPLIST_KEY (plist) != Mt
5236           && ! check_variable_value (value, plist))
5237         MERROR (MERROR_IM, -1);
5238     }
5239
5240   config = get_config_info (im_info);
5241   if (! config)
5242     {
5243       if (! im_config_list)
5244         im_config_list = mplist ();
5245       config = new_im_info (NULL, language, name, Mnil, im_config_list);
5246       config->cmds = mplist ();
5247       config->vars = mplist ();
5248     }
5249
5250   if (variable == Mnil)
5251     {
5252       MInputMethodInfo *custom = get_custom_info (im_info);
5253
5254       mplist_set (config->vars, Mnil, NULL);
5255       if (custom && custom->cmds)
5256         {
5257           MPLIST_DO (plist, custom->vars)
5258             {
5259               variable = MPLIST_SYMBOL (MPLIST_PLIST (plist));
5260               plist = mplist ();
5261               mplist_add (plist, Msymbol, variable);
5262               mplist_push (config->vars, Mplist, plist);
5263               M17N_OBJECT_UNREF (plist);
5264             }
5265         }
5266     }
5267   else
5268     {
5269       plist = mplist__assq (config->vars, variable);
5270       if (plist)
5271         {
5272           plist = MPLIST_PLIST (plist); /* (NAME nil VALUE) */
5273           plist = MPLIST_NEXT (plist);  /* ([nil VALUE]) */
5274           if (! MPLIST_TAIL_P (plist))
5275             mplist_set (plist, Mnil ,NULL); /* () */
5276         }
5277       else
5278         {
5279           plist = mplist ();
5280           mplist_add (config->vars, Mplist, plist);
5281           M17N_OBJECT_UNREF (plist);
5282           plist = mplist_add (plist, Msymbol, variable);
5283           plist = MPLIST_NEXT (plist);
5284         }
5285       if (value)
5286         {
5287           plist = mplist_add (plist, Msymbol, Mnil);
5288           mplist_add (plist, MPLIST_KEY (value), MPLIST_VAL (value));
5289         }
5290     }
5291   config_all_variables (im_info);
5292   im_info->tick = time (NULL);
5293   return 0;
5294 }
5295
5296 /*=*/
5297
5298 /***en
5299     @brief Get the name of per-user configuration file.
5300     
5301     The minput_config_file () function returns the absolute path name
5302     of per-user configuration file into which minput_save_config ()
5303     save configurations.  It is usually @c "config.mic" under the
5304     directory @c ".m17n.d" of user's home directory.  It is not assured
5305     that the file of the returned name exists nor is
5306     readable/writable.  If minput_save_config () fails and returns -1,
5307     an application program might check the file, make it
5308     writable (if possible), and try minput_save_config () again.
5309
5310     @return
5311
5312     This function returns a string.  As the string is kept in the
5313     library, the caller must not modify nor free it.
5314
5315     @seealso
5316     minput_save_config ()
5317 */
5318 /***ja
5319     @brief ¥æ¡¼¥¶Ëè¤ÎÀßÄê¥Õ¥¡¥¤¥ë¤Î̾Á°¤òÆÀ¤ë.
5320     
5321     ´Ø¿ô minput_config_file () ¤Ï¡¢´Ø¿ô minput_save_config () ¤¬ÀßÄê¤ò
5322     Êݸ¤¹¤ë¥æ¡¼¥¶Ëè¤ÎÀßÄê¥Õ¥¡¥¤¥ë¤Ø¤ÎÀäÂХѥ¹Ì¾¤òÊÖ¤¹¡£Ä̾ï¤Ï¡¢¥æ¡¼¥¶
5323     ¤Î¥Û¡¼¥à¥Ç¥£¥ì¥¯¥È¥ê¤Î²¼¤Î¥Ç¥£¥ì¥¯¥È¥ê @c ".m17n.d" ¤Ë¤¢¤ë@c
5324     "config.mic" ¤È¤Ê¤ë¡£ÊÖ¤µ¤ì¤¿Ì¾Á°¤Î¥Õ¥¡¥¤¥ë¤¬Â¸ºß¤¹¤ë¤«¡¢Æɤ߽ñ¤­¤Ç
5325     ¤­¤ë¤«¤ÏÊݾڤµ¤ì¤Ê¤¤¡£´Ø¿ôminput_save_config () ¤¬¼ºÇÔ¤·¤Æ -1 ¤òÊÖ
5326     ¤·¤¿¾ì¹ç¤Ë¤Ï¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ï¥Õ¥¡¥¤¥ë¤Î¸ºß¤ò³Îǧ¤·¡¢
5327     ¡Ê¤Ç¤­¤ì¤Ð¡Ë½ñ¤­¹þ¤ß²Äǽ¤Ë¤·ºÆÅÙminput_save_config () ¤ò»î¤¹¤³¤È¤¬
5328     ¤Ç¤­¤ë¡£
5329
5330     @return
5331
5332     ¤³¤Î´Ø¿ô¤Ïʸ»úÎó¤òÊÖ¤¹¡£Ê¸»úÎó¤Ï¥é¥¤¥Ö¥é¥ê¤¬´ÉÍý¤·¤Æ¤¤¤ë¤Î¤Ç¡¢¸Æ½Ð
5333     Â¦¤¬½¤Àµ¤·¤¿¤ê²òÊü¤·¤¿¤ê¤¹¤ë¤³¤È¤Ï¤Ç¤­¤Ê¤¤¡£
5334
5335     @seealso
5336     minput_save_config ()
5337 */
5338
5339 char *
5340 minput_config_file ()
5341 {
5342   MINPUT__INIT ();
5343
5344   return mdatabase__file (im_custom_mdb);
5345 }
5346
5347 /*=*/
5348
5349 /***en
5350     @brief Save configurations in per-user configuration file.
5351
5352     The minput_save_config () function saves the configurations done
5353     so far in the current session into the per-user configuration
5354     file.
5355
5356     @return
5357
5358     If the operation was successful, 1 is returned.  If the per-user
5359     configuration file is currently locked, 0 is returned.  In that
5360     case, the caller may wait for a while and try again.  If the
5361     configuration file is not writable, -1 is returned.  In that case,
5362     the caller may check the name of the file by calling
5363     minput_config_file (), make it writable if possible, and try
5364     again.
5365
5366     @seealso
5367     minput_config_file ()  */
5368 /***ja
5369     @brief ÀßÄê¤ò¥æ¡¼¥¶Ëè¤ÎÀßÄê¥Õ¥¡¥¤¥ë¤ËÊݸ¤¹¤ë.
5370
5371     ´Ø¿ô minput_save_config () ¤Ï¸½¹Ô¤Î¥»¥Ã¥·¥ç¥ó¤Ç¤³¤ì¤Þ¤Ç¤Ë¹Ô¤Ã¤¿ÀßÄê
5372     ¤ò¥æ¡¼¥¶Ëè¤ÎÀßÄê¥Õ¥¡¥¤¥ë¤ËÊݸ¤¹¤ë¡£
5373
5374     @return
5375
5376     À®¸ù¤¹¤ì¤Ð 1 ¤òÊÖ¤¹¡£¥æ¡¼¥¶Ëè¤ÎÀßÄê¥Õ¥¡¥¤¥ë¤¬¥í¥Ã¥¯¤µ¤ì¤Æ¤¤¤ì¤Ð 0
5377     ¤òÊÖ¤¹¡£¤³¤Î¾ì¹ç¡¢¸Æ½Ð¦¤Ï¤·¤Ð¤é¤¯ÂԤäƺƻî¹Ô¤Ç¤­¤ë¡£ÀßÄê¥Õ¥¡¥¤¥ë
5378     ¤¬½ñ¤­¹þ¤ßÉԲĤξì¹ç¡¢-1 ¤òÊÖ¤¹¡£¤³¤Î¾ì¹ç¡¢minput_config_file () ¤ò
5379     ¸Æ¤ó¤Ç¥Õ¥¡¥¤¥ë̾¤ò¥Á¥§¥Ã¥¯¤·¡¢¤Ç¤­¤ì¤Ð½ñ¤­¹þ¤ß²Äǽ¤Ë¤·¡¢ºÆ»î¹Ô¤Ç¤­
5380     ¤ë¡£
5381
5382     @seealso
5383     minput_config_file ()  */
5384
5385 int
5386 minput_save_config (void)
5387 {
5388   MPlist *data, *tail, *plist, *p, *elt;
5389   int ret;
5390
5391   MINPUT__INIT ();
5392   ret = mdatabase__lock (im_custom_mdb);
5393   if (ret <= 0)
5394     return ret;
5395   if (! im_config_list)
5396     return 1;
5397   update_custom_info ();
5398   if (! im_custom_list)
5399     im_custom_list = mplist ();
5400   data = tail = mplist ();
5401
5402   MPLIST_DO (plist, im_config_list)
5403     {
5404       MPlist *pl = MPLIST_PLIST (plist);
5405       MSymbol language, name, extra, command, variable;
5406       MInputMethodInfo *custom, *config;
5407
5408       language = MPLIST_SYMBOL (pl);
5409       pl = MPLIST_NEXT (pl);
5410       name = MPLIST_SYMBOL (pl);
5411       pl = MPLIST_NEXT (pl);
5412       extra = MPLIST_SYMBOL (pl);
5413       pl = MPLIST_NEXT (pl);
5414       config = MPLIST_VAL (pl);
5415       custom = get_custom_info (config);
5416       if (! custom)
5417         custom = new_im_info (NULL, language, name, extra, im_custom_list);
5418       if (config->cmds)
5419         MPLIST_DO (pl, config->cmds)
5420           {
5421             elt = MPLIST_PLIST (pl);
5422             command = MPLIST_SYMBOL (elt);
5423             if (custom->cmds)
5424               p = mplist__assq (custom->cmds, command);
5425             else
5426               custom->cmds = mplist (), p = NULL;
5427             elt = MPLIST_NEXT (elt);
5428             if (MPLIST_TAIL_P (elt))
5429               {
5430                 if (p)
5431                   mplist__pop_unref (p);
5432               }
5433             else
5434               {
5435                 elt = MPLIST_NEXT (elt);
5436                 if (p)
5437                   {
5438                     p = MPLIST_NEXT (MPLIST_NEXT (MPLIST_PLIST (p)));
5439                     mplist_set (p, Mnil, NULL);
5440                     mplist__conc (p, elt);
5441                   }
5442                 else
5443                   {
5444                     p = MPLIST_PLIST (pl);
5445                     mplist_add (custom->cmds, Mplist, p);
5446                   }
5447               }
5448           }
5449       if (config->vars)
5450         MPLIST_DO (pl, config->vars)
5451           {
5452             elt = MPLIST_PLIST (pl);
5453             variable = MPLIST_SYMBOL (elt);
5454             if (custom->vars)
5455               p = mplist__assq (custom->vars, variable);
5456             else
5457               custom->vars = mplist (), p = NULL;
5458             elt = MPLIST_NEXT (elt);
5459             if (MPLIST_TAIL_P (elt))
5460               {
5461                 if (p)
5462                   mplist__pop_unref (p);
5463               }
5464             else
5465               {
5466                 elt = MPLIST_NEXT (elt);
5467                 if (p)
5468                   {
5469                     p = MPLIST_NEXT (MPLIST_NEXT (MPLIST_PLIST (p)));
5470                     mplist_set (p, Mnil, NULL);
5471                     mplist__conc (p, elt);
5472                   }
5473                 else
5474                   {
5475                     p = MPLIST_PLIST (pl);
5476                     mplist_add (custom->vars, Mplist, p);
5477                   }
5478               }
5479           }
5480     }
5481   M17N_OBJECT_UNREF (im_config_list);
5482
5483   MPLIST_DO (plist, im_custom_list)
5484     {
5485       MPlist *pl = MPLIST_PLIST (plist);
5486       MSymbol language, name, extra;
5487       MInputMethodInfo *custom, *im_info;
5488
5489       language = MPLIST_SYMBOL (pl);
5490       pl  = MPLIST_NEXT (pl);
5491       name = MPLIST_SYMBOL (pl);
5492       pl = MPLIST_NEXT (pl);
5493       extra = MPLIST_SYMBOL (pl);
5494       pl = MPLIST_NEXT (pl);
5495       custom = MPLIST_VAL (pl);
5496       im_info = lookup_im_info (im_info_list, language, name, extra);
5497       if (im_info)
5498         {
5499           if (im_info->cmds)
5500             config_all_commands (im_info);
5501           if (im_info->vars)
5502             config_all_variables (im_info);
5503         }
5504       
5505       elt = mplist ();
5506       tail = mplist_add (tail, Mplist, elt);
5507       M17N_OBJECT_UNREF (elt);
5508       pl = mplist ();
5509       elt = mplist_add (elt, Mplist, pl);
5510       M17N_OBJECT_UNREF (pl);
5511       pl = mplist_add (pl, Msymbol, Minput_method);
5512       pl = mplist_add (pl, Msymbol, language);
5513       pl = mplist_add (pl, Msymbol, name);
5514       if (extra != Mnil)
5515         pl = mplist_add (pl, Msymbol, extra);
5516       if (custom->cmds && ! MPLIST_TAIL_P (custom->cmds))
5517         {
5518           pl = mplist ();
5519           elt = mplist_add (elt, Mplist, pl);
5520           M17N_OBJECT_UNREF (pl);
5521           pl = mplist_add (pl, Msymbol, Mcommand);
5522           MPLIST_DO (p, custom->cmds)
5523             pl = mplist_add (pl, Mplist, MPLIST_PLIST (p));
5524         }
5525       if (custom->vars && ! MPLIST_TAIL_P (custom->vars))
5526         {
5527           pl = mplist ();
5528           elt = mplist_add (elt, Mplist, pl);
5529           M17N_OBJECT_UNREF (pl);
5530           pl = mplist_add (pl, Msymbol, Mvariable);
5531           MPLIST_DO (p, custom->vars)
5532             pl = mplist_add (pl, Mplist, MPLIST_PLIST (p));
5533         }
5534     }
5535
5536   mplist_push (data, Mstring, ";; -*- mode:lisp; coding:utf-8 -*-");
5537   ret = mdatabase__save (im_custom_mdb, data);
5538   mdatabase__unlock (im_custom_mdb);
5539   M17N_OBJECT_UNREF (data);
5540   return (ret < 0 ? -1 : 1);
5541 }
5542
5543 /*=*/
5544 /*** @} */
5545 /*=*/
5546 /***en
5547     @name Obsolete functions
5548 */
5549 /***ja
5550     @name Obsolete ¤Ê´Ø¿ô
5551 */
5552 /*** @{ */
5553
5554 /*=*/
5555 /***en
5556     @brief Get a list of variables of an input method (obsolete).
5557
5558     This function is obsolete.  Use minput_get_variable () instead.
5559
5560     The minput_get_variables () function returns a plist (#MPlist) of
5561     variables used to control the behavior of the input method
5562     specified by $LANGUAGE and $NAME.  The plist is @e well-formed
5563     (#m17nPlist) of the following format:
5564
5565 @verbatim
5566     (VARNAME (DOC-MTEXT DEFAULT-VALUE [ VALUE ... ] )
5567      VARNAME (DOC-MTEXT DEFAULT-VALUE [ VALUE ... ] )
5568      ...)
5569 @endverbatim
5570
5571     @c VARNAME is a symbol representing the variable name.
5572
5573     @c DOC-MTEXT is an M-text describing the variable.
5574
5575     @c DEFAULT-VALUE is the default value of the variable.  It is a
5576     symbol, integer, or M-text.
5577
5578     @c VALUEs (if any) specifies the possible values of the variable.
5579     If @c DEFAULT-VALUE is an integer, @c VALUE may be a plist (@c FROM
5580     @c TO), where @c FROM and @c TO specifies a range of possible
5581     values.
5582
5583     For instance, suppose an input method has the variables:
5584
5585     @li name:intvar, description:"value is an integer",
5586          initial value:0, value-range:0..3,10,20
5587
5588     @li name:symvar, description:"value is a symbol",
5589          initial value:nil, value-range:a, b, c, nil
5590
5591     @li name:txtvar, description:"value is an M-text",
5592          initial value:empty text, no value-range (i.e. any text)
5593
5594     Then, the returned plist is as follows.
5595
5596 @verbatim
5597     (intvar ("value is an integer" 0 (0 3) 10 20)
5598      symvar ("value is a symbol" nil a b c nil)
5599      txtvar ("value is an M-text" ""))
5600 @endverbatim
5601
5602     @return
5603     If the input method uses any variables, a pointer to #MPlist is
5604     returned.  As the plist is kept in the library, the caller must not
5605     modify nor free it.  If the input method does not use any
5606     variable, @c NULL is returned.  */
5607 /***ja
5608     @brief ÆþÎϥ᥽¥Ã¥É¤ÎÊÑ¿ô¥ê¥¹¥È¤òÆÀ¤ë.
5609
5610     ´Ø¿ô minput_get_variables () ¤Ï¡¢$LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ»ØÄꤵ
5611     ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤Î¿¶¤ëÉñ¤¤¤òÀ©¸æ¤¹¤ëÊÑ¿ô¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È
5612     (#MPlist) ¤òÊÖ¤¹¡£¤³¤Î¥ê¥¹¥È¤Ï @e well-formed ¤Ç¤¢¤ê(#m17nPlist) °Ê
5613     ²¼¤Î·Á¼°¤Ç¤¢¤ë¡£
5614
5615 @verbatim
5616     (VARNAME (DOC-MTEXT DEFAULT-VALUE [ VALUE ... ] )
5617      VARNAME (DOC-MTEXT DEFAULT-VALUE [ VALUE ... ] )
5618      ...)
5619 @endverbatim
5620
5621     @c VARNAME ¤ÏÊÑ¿ô¤Î̾Á°¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
5622
5623     @c DOC-MTEXT ¤ÏÊÑ¿ô¤òÀâÌÀ¤¹¤ë M-text ¤Ç¤¢¤ë¡£
5624
5625     @c DEFAULT-VALUE ¤ÏÊÑ¿ô¤Î¥Ç¥Õ¥©¥ë¥ÈÃͤǤ¢¤ê¡¢¥·¥ó¥Ü¥ë¡¢À°¿ô¤â¤·¤¯¤Ï
5626     M-text ¤Ç¤¢¤ë¡£
5627
5628     @c VALUE ¤Ï¡¢¤â¤·»ØÄꤵ¤ì¤Æ¤¤¤ì¤ÐÊÑ¿ô¤Î¼è¤êÆÀ¤ëÃͤò¼¨¤¹¡£¤â¤·
5629     @c DEFAULT-VALUE ¤¬À°¿ô¤Ê¤é¡¢ @c VALUE ¤Ï (@c FROM @c TO) ¤È¤¤¤¦·Á
5630     ¤Î¥ê¥¹¥È¤Ç¤âÎɤ¤¡£¤³¤Î¾ì¹ç @c FROM ¤È @c TO ¤Ï²Äǽ¤ÊÃͤÎÈϰϤò¼¨¤¹¡£
5631
5632     Îã¤È¤·¤Æ¡¢¤¢¤ëÆþÎϥ᥽¥Ã¥É¤¬¼¡¤Î¤è¤¦¤ÊÊÑ¿ô¤ò»ý¤Ä¾ì¹ç¤ò¹Í¤¨¤è¤¦¡£
5633
5634     @li name:intvar, ÀâÌÀ:"value is an integer",
5635         ½é´üÃÍ:0, ÃͤÎÈÏ°Ï:0..3,10,20
5636
5637     @li name:symvar, ÀâÌÀ:"value is a symbol",
5638          ½é´üÃÍ:nil, ÃͤÎÈÏ°Ï:a, b, c, nil
5639
5640     @li name:txtvar, ÀâÌÀ:"value is an M-text",
5641         ½é´üÃÍ:empty text, ÃͤÎÈϰϤʤ·(¤É¤ó¤Ê M-text ¤Ç¤â²Ä)
5642
5643     ¤³¤Î¾ì¹ç¡¢ÊÖ¤µ¤ì¤ë¥ê¥¹¥È¤Ï°Ê²¼¤Î¤è¤¦¤Ë¤Ê¤ë¡£
5644
5645 @verbatim
5646     (intvar ("value is an integer" 0 (0 3) 10 20)
5647      symvar ("value is a symbol" nil a b c nil)
5648      txtvar ("value is an M-text" ""))
5649 @endverbatim
5650
5651     @return 
5652     ÆþÎϥ᥽¥Ã¥É¤¬²¿¤é¤«¤ÎÊÑ¿ô¤ò»ÈÍѤ·¤Æ¤¤¤ì¤Ð #MPlist ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
5653     ÊÖ¤µ¤ì¤ë¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ï¥é¥¤¥Ö¥é¥ê¤Ë¤è¤Ã¤Æ´ÉÍý¤µ¤ì¤Æ¤ª¤ê¡¢¸Æ¤Ó½Ð¤·Â¦¤ÇÊѹ¹¤·¤¿¤ê²òÊü¤·¤¿¤ê¤·¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
5654     ÆþÎϥ᥽¥Ã¥É¤¬ÊÑ¿ô¤ò°ìÀÚ»ÈÍѤ·¤Æ¤Ê¤±¤ì¤Ð¡¢@c NULL ¤òÊÖ¤¹¡£  */
5655
5656 MPlist *
5657 minput_get_variables (MSymbol language, MSymbol name)
5658 {
5659   MInputMethodInfo *im_info;
5660   MPlist *vars;
5661
5662   MINPUT__INIT ();
5663
5664   im_info = get_im_info (language, name, Mnil, Mvariable);
5665   if (! im_info || ! im_info->configured_vars)
5666     return NULL;
5667
5668   M17N_OBJECT_UNREF (im_info->bc_vars);
5669   im_info->bc_vars = mplist ();
5670   MPLIST_DO (vars, im_info->configured_vars)
5671     {
5672       MPlist *plist = MPLIST_PLIST (vars);
5673       MPlist *elt = mplist ();
5674
5675       mplist_push (im_info->bc_vars, Mplist, elt);
5676       mplist_add (elt, Msymbol, MPLIST_SYMBOL (plist));
5677       elt = MPLIST_NEXT (elt);
5678       mplist_set (elt, Mplist, mplist_copy (MPLIST_NEXT (plist)));
5679       M17N_OBJECT_UNREF (elt);
5680     }
5681   return im_info->bc_vars;
5682 }
5683
5684 /*=*/
5685
5686 /***en
5687     @brief Set the initial value of an input method variable.
5688
5689     The minput_set_variable () function sets the initial value of
5690     input method variable $VARIABLE to $VALUE for the input method
5691     specified by $LANGUAGE and $NAME.
5692
5693     By default, the initial value is 0.
5694
5695     This setting gets effective in a newly opened input method.
5696
5697     @return
5698     If the operation was successful, 0 is returned.  Otherwise -1 is
5699     returned, and #merror_code is set to #MERROR_IM.  */
5700 /***ja
5701     @brief ÆþÎϥ᥽¥Ã¥ÉÊÑ¿ô¤Î½é´üÃͤòÀßÄꤹ¤ë.
5702
5703     ´Ø¿ô minput_set_variable () ¤Ï¡¢$LANGUAGE ¤È $NAME 
5704     ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ÎÆþÎϥ᥽¥Ã¥ÉÊÑ¿ô $VARIABLE
5705     ¤Î½é´üÃͤò¡¢ $VALUE ¤ËÀßÄꤹ¤ë¡£
5706
5707     ¥Ç¥Õ¥©¥ë¥È¤Î½é´üÃͤϠ0 ¤Ç¤¢¤ë¡£
5708
5709     ¤³¤ÎÀßÄê¤Ï¡¢¿·¤·¤¯¥ª¡¼¥×¥ó¤µ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤«¤éÍ­¸ú¤È¤Ê¤ë¡£
5710
5711     @return
5712     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤·¡¢
5713     #merror_code ¤ò #MERROR_IM ¤ËÀßÄꤹ¤ë¡£  */
5714
5715 int
5716 minput_set_variable (MSymbol language, MSymbol name,
5717                      MSymbol variable, void *value)
5718 {
5719   MPlist *plist, *pl;
5720   MInputMethodInfo *im_info;
5721   int ret;
5722
5723   MINPUT__INIT ();
5724
5725   if (variable == Mnil)
5726     MERROR (MERROR_IM, -1);
5727   plist = minput_get_variable (language, name, variable);
5728   plist = MPLIST_PLIST (plist);
5729   plist = MPLIST_NEXT (plist);
5730   pl = mplist ();
5731   mplist_add (pl, MPLIST_KEY (plist), value);
5732   ret = minput_config_variable (language, name, variable, pl);
5733   M17N_OBJECT_UNREF (pl);
5734   if (ret == 0)
5735     {
5736       im_info = get_im_info (language, name, Mnil, Mvariable);
5737       im_info->tick = 0;
5738     }
5739   return ret;
5740 }
5741
5742 /*=*/
5743
5744 /***en
5745     @brief Get information about input method commands.
5746
5747     The minput_get_commands () function returns information about
5748     input method commands of the input method specified by $LANGUAGE
5749     and $NAME.  An input method command is a pseudo key event to which
5750     one or more actual input key sequences are assigned.
5751
5752     There are two kinds of commands, global and local.  Global
5753     commands are used by multiple input methods for the same purpose,
5754     and have global key assignments.  Local commands are used only by
5755     a specific input method, and have only local key assignments.
5756
5757     Each input method may locally change key assignments for global
5758     commands.  The global key assignment for a global command is
5759     effective only when the current input method does not have local
5760     key assignments for that command.
5761
5762     If $NAME is #Mnil, information about global commands is returned.
5763     In this case $LANGUAGE is ignored.
5764
5765     If $NAME is not #Mnil, information about those commands that have
5766     local key assignments in the input method specified by $LANGUAGE
5767     and $NAME is returned.
5768
5769     @return
5770     If no input method commands are found, this function returns @c NULL.
5771
5772     Otherwise, a pointer to a plist is returned.  The key of each
5773     element in the plist is a symbol representing a command, and the
5774     value is a plist of the form COMMAND-INFO described below.
5775
5776     The first element of COMMAND-INFO has the key #Mtext, and the
5777     value is an M-text describing the command.
5778
5779     If there are no more elements, that means no key sequences are
5780     assigned to the command.  Otherwise, each of the remaining
5781     elements has the key #Mplist, and the value is a plist whose keys are
5782     #Msymbol and values are symbols representing input keys, which are
5783     currently assigned to the command.
5784
5785     As the returned plist is kept in the library, the caller must not
5786     modify nor free it.  */
5787 /***ja
5788     @brief ÆþÎϥ᥽¥Ã¥É¤Î¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë.
5789
5790     ´Ø¿ô minput_get_commands () ¤Ï¡¢ $LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ»ØÄꤵ
5791     ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ÎÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£ÆþÎϥ᥽¥Ã
5792     ¥É¥³¥Þ¥ó¥É¤È¤Ï¡¢µ¿»÷¥­¡¼¥¤¥Ù¥ó¥È¤Ç¤¢¤ê¡¢¤½¤ì¤¾¤ì¤Ë£±¤Ä°Ê¾å¤Î¼ÂºÝ¤Î
5793     ÆþÎÏ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤¬³ä¤êÅö¤Æ¤é¤ì¤Æ¤¤¤ë¤â¤Î¤ò»Ø¤¹¡£
5794
5795     ¥³¥Þ¥ó¥É¤Ë¤Ï¥°¥í¡¼¥Ð¥ë¤È¥í¡¼¥«¥ë¤Î£²¼ïÎब¤¢¤ë¡£¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É
5796     ¤ÏÊ£¿ô¤ÎÆþÎϥ᥽¥Ã¥É¤Ë¤ª¤¤¤Æ¡¢Æ±¤¸ÌÜŪ¤Ç¡¢¥°¥í¡¼¥Ð¥ë¤Ê¥­¡¼³ä¤êÅö¤Æ
5797     ¤ÇÍѤ¤¤é¤ì¤ë¡£¥í¡¼¥«¥ë¥³¥Þ¥ó¥É¤ÏÆÃÄê¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Î¤ß¡¢¥í¡¼¥«¥ë
5798     ¤Ê¥­¡¼³äÅö¤Ç»ÈÍѤµ¤ì¤ë¡£
5799
5800     ¸Ä¡¹¤ÎÆþÎϥ᥽¥Ã¥É¤Ï¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É¤Î¥­¡¼³äÅö¤òÊѹ¹¤¹¤ë¤³¤È¤â¤Ç
5801     ¤­¤ë¡£¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥ÉÍѤΥ°¥í¡¼¥Ð¥ë¥­¡¼³ä¤êÅö¤Æ¤Ï¡¢»ÈÍѤ¹¤ëÆþÎÏ
5802     ¥á¥½¥Ã¥É¤Ë¤ª¤¤¤Æ¤½¤Î¥³¥Þ¥ó¥ÉÍÑ¤Î¥í¡¼¥«¥ë¤Ê¥­¡¼³äÅö¤¬Â¸ºß¤·¤Ê¤¤¾ì¹ç
5803     ¤Ë¤Î¤ßÍ­¸ú¤Ç¤¢¤ë¡£
5804
5805     $NAME ¤¬ #Mnil ¤Ç¤¢¤ì¤Ð¡¢¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£¤³¤Î
5806     ¾ì¹ç¡¢$LANGUAGE ¤Ï̵»ë¤µ¤ì¤ë¡£
5807
5808     $NAME ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢$LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤ëÆþ
5809     Îϥ᥽¥Ã¥É¤ËÃÖ¤±¤ë¥í¡¼¥«¥ë¤Ê¥­¡¼³ä¤êÅö¤Æ¤ò»ý¤Ä¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó
5810     ¤òÊÖ¤¹¡£
5811
5812     @return
5813     ÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï @c NULL ¤òÊÖ¤¹¡£
5814
5815     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¥ê¥¹¥È¤Î³ÆÍ×ÁǤÎ
5816     ¥­¡¼¤Ï¸Ä¡¹¤Î¥³¥Þ¥ó¥É¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢Ãͤϲ¼µ­¤Î COMMAND-INFO
5817     ¤Î·Á¼°¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ç¤¢¤ë¡£
5818
5819     COMMAND-INFO ¤ÎÂè°ìÍ×ÁǤΥ­¡¼¤Ï #Mtext ¤Þ¤¿¤Ï #Msymbol ¤Ç¤¢¤ë¡£¥­¡¼
5820     ¤¬ #Mtext ¤Ê¤é¡¢ÃͤϤ½¤Î¥³¥Þ¥ó¥É¤òÀâÌÀ¤¹¤ë M-text ¤Ç¤¢¤ë¡£¥­¡¼¤¬
5821     #Msymbol ¤Ê¤éÃͤϠ#Mnil ¤Ç¤¢¤ê¡¢¤³¤Î¥³¥Þ¥ó¥É¤ÏÀâÌÀ¥Æ¥­¥¹¥È¤ò»ý¤¿¤Ê
5822     ¤¤¤³¤È¤Ë¤Ê¤ë¡£
5823
5824     ¤½¤ì°Ê³°¤ÎÍ×ÁǤ¬Ìµ¤±¤ì¤Ð¡¢¤³¤Î¥³¥Þ¥ó¥É¤ËÂФ·¤Æ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤¬³ä
5825     ¤êÅö¤Æ¤é¤ì¤Æ¤¤¤Ê¤¤¤³¤È¤ò°ÕÌ£¤¹¤ë¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢»Ä¤ê¤Î³ÆÍ×ÁǤϥ­
5826     ¡¼¤È¤·¤Æ#Mplist ¤ò¡¢ÃͤȤ·¤Æ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ò»ý¤Ä¡£¤³¤Î¥×¥í¥Ñ¥Æ¥£
5827     ¥ê¥¹¥È¤Î¥­¡¼¤Ï #Msymbol ¤Ç¤¢¤ê¡¢Ãͤϸ½ºß¤½¤Î¥³¥Þ¥ó¥É¤Ë³ä¤êÅö¤Æ¤é¤ì
5828     ¤Æ¤¤¤ëÆþÎÏ¥­¡¼¤òɽ¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
5829
5830     ÊÖ¤µ¤ì¤ë¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ï¥é¥¤¥Ö¥é¥ê¤Ë¤è¤Ã¤Æ´ÉÍý¤µ¤ì¤Æ¤ª¤ê¡¢¸Æ¤Ó½Ð
5831     ¤·Â¦¤ÇÊѹ¹¤·¤¿¤ê²òÊü¤·¤¿¤ê¤·¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£*/
5832
5833 MPlist *
5834 minput_get_commands (MSymbol language, MSymbol name)
5835 {
5836   MInputMethodInfo *im_info;
5837   MPlist *cmds;
5838
5839   MINPUT__INIT ();
5840
5841   im_info = get_im_info (language, name, Mnil, Mcommand);
5842   if (! im_info || ! im_info->configured_vars)
5843     return NULL;
5844   M17N_OBJECT_UNREF (im_info->bc_cmds);
5845   im_info->bc_cmds = mplist ();
5846   MPLIST_DO (cmds, im_info->configured_cmds)
5847     {
5848       MPlist *plist = MPLIST_PLIST (cmds);
5849       MPlist *elt = mplist ();
5850
5851       mplist_push (im_info->bc_cmds, Mplist, elt);
5852       mplist_add (elt, MPLIST_SYMBOL (plist),
5853                   mplist_copy (MPLIST_NEXT (plist)));
5854       M17N_OBJECT_UNREF (elt);
5855     }
5856   return im_info->bc_cmds;
5857 }
5858
5859 /*=*/
5860
5861 /***en
5862     @brief Assign a key sequence to an input method command (obsolete).
5863
5864     This function is obsolete.  Use minput_config_command () instead.
5865
5866     The minput_assign_command_keys () function assigns input key
5867     sequence $KEYSEQ to input method command $COMMAND for the input
5868     method specified by $LANGUAGE and $NAME.  If $NAME is #Mnil, the
5869     key sequence is assigned globally no matter what $LANGUAGE is.
5870     Otherwise the key sequence is assigned locally.
5871
5872     Each element of $KEYSEQ must have the key $Msymbol and the value
5873     must be a symbol representing an input key.
5874
5875     $KEYSEQ may be @c NULL, in which case, all assignments are deleted
5876     globally or locally.
5877
5878     This assignment gets effective in a newly opened input method.
5879
5880     @return
5881     If the operation was successful, 0 is returned.  Otherwise -1 is
5882     returned, and #merror_code is set to #MERROR_IM.  */
5883 /***ja
5884     @brief ÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤Ë¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤ò³ä¤êÅö¤Æ¤ë.
5885
5886     ´Ø¿ô minput_assign_command_keys () ¤Ï¡¢ $LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ
5887     »ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥ÉÍѤÎÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É $COMMAND ¤ËÂФ·¤Æ¡¢
5888     ÆþÎÏ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹ $KEYSEQ ¤ò³ä¤êÅö¤Æ¤ë¡£ $NAME ¤¬ #Mnil ¤Ê¤é¤Ð¡¢
5889     $LANGUAGE ¤Ë´Ø·¸¤Ê¤¯¡¢ÆþÎÏ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤Ï¥°¥í¡¼¥Ð¥ë¤Ë³ä¤êÅö¤Æ¤é
5890     ¤ì¤ë¡£¤½¤¦¤Ç¤Ê¤ì¤Ð¡¢³ä¤êÅö¤Æ¤Ï¥í¡¼¥«¥ë¤Ç¤¢¤ë¡£
5891
5892     $KEYSEQ ¤Î³ÆÍ×ÁǤϥ­¡¼¤È¤·¤Æ $Msymbol ¤ò¡¢ÃͤȤ·¤ÆÆþÎÏ¥­¡¼¤òɽ¤¹¥·
5893     ¥ó¥Ü¥ë¤ò»ý¤¿¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
5894
5895     $KEYSEQ ¤Ï @c NULL ¤Ç¤â¤è¤¤¡£¤³¤Î¾ì¹ç¡¢¥°¥í¡¼¥Ð¥ë¤â¤·¤¯¤Ï¥í¡¼¥«¥ë¤Ê
5896     ¤¹¤Ù¤Æ¤Î³ä¤êÅö¤Æ¤¬¾Ãµî¤µ¤ì¤ë¡£
5897
5898     ¤³¤Î³ä¤êÅö¤Æ¤Ï¡¢³ä¤êÅö¤Æ°Ê¹ß¿·¤·¤¯¥ª¡¼¥×¥ó¤µ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤«¤éÍ­
5899     ¸ú¤Ë¤Ê¤ë¡£
5900
5901     @return ½èÍý¤¬À®¸ù¤¹¤ì¤Ð 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤·¡¢
5902     #merror_code ¤ò #MERROR_IM ¤ËÀßÄꤹ¤ë¡£  */
5903
5904 int
5905 minput_assign_command_keys (MSymbol language, MSymbol name,
5906                             MSymbol command, MPlist *keyseq)
5907 {
5908   int ret;
5909
5910   MINPUT__INIT ();
5911
5912   if (command == Mnil)
5913     MERROR (MERROR_IM, -1);
5914   if (keyseq)
5915     {
5916       MPlist *plist;
5917
5918       if  (! check_command_keyseq (keyseq))
5919         MERROR (MERROR_IM, -1);
5920       plist = mplist ();
5921       mplist_add (plist, Mplist, keyseq);
5922       keyseq = plist;
5923     }  
5924   else
5925     keyseq = mplist ();
5926   ret = minput_config_command (language, name, command, keyseq);
5927   M17N_OBJECT_UNREF (keyseq);
5928   return ret;
5929 }
5930
5931 /*** @} */ 
5932 /*** @} */
5933 /*=*/
5934 /*** @addtogroup m17nDebug */
5935 /*=*/
5936 /*** @{  */
5937 /*=*/
5938
5939 /***en
5940     @brief Dump an input method.
5941
5942     The mdebug_dump_im () function prints the input method $IM in a
5943     human readable way to the stderr.  $INDENT specifies how many
5944     columns to indent the lines but the first one.
5945
5946     @return
5947     This function returns $IM.  */
5948 /***ja
5949     @brief ÆþÎϥ᥽¥Ã¥É¤ò¥À¥ó¥×¤¹¤ë.
5950
5951     ´Ø¿ô mdebug_dump_im () ¤ÏÆþÎϥ᥽¥Ã¥É $IM ¤ò stderr 
5952     ¤Ë¿Í´Ö¤Ë²ÄÆɤʷÁ¤Ç°õºþ¤¹¤ë¡£$INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£
5953
5954     @return
5955     ¤³¤Î´Ø¿ô¤Ï $IM ¤òÊÖ¤¹¡£  */
5956
5957 MInputMethod *
5958 mdebug_dump_im (MInputMethod *im, int indent)
5959 {
5960   MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
5961   char *prefix;
5962
5963   prefix = (char *) alloca (indent + 1);
5964   memset (prefix, 32, indent);
5965   prefix[indent] = '\0';
5966
5967   fprintf (stderr, "(input-method %s %s ", msymbol_name (im->language),
5968            msymbol_name (im->name));
5969   mdebug_dump_mtext (im_info->title, 0, 0);
5970   if (im->name != Mnil)
5971     {
5972       MPlist *state;
5973
5974       MPLIST_DO (state, im_info->states)
5975         {
5976           fprintf (stderr, "\n%s  ", prefix);
5977           dump_im_state (MPLIST_VAL (state), indent + 2);
5978         }
5979     }
5980   fprintf (stderr, ")");
5981   return im;
5982 }
5983
5984 /*** @} */ 
5985
5986 /*
5987   Local Variables:
5988   coding: euc-japan
5989   End:
5990 */