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