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