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