*** 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 is 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 /***ja
3843     @name ÊÑ¿ô¡§ ¥³¡¼¥ë¥Ð¥Ã¥¯¥³¥Þ¥ó¥ÉÍÑÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë.
3844
3845     ÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Î¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Ë¤ª¤¤¤Æ @c COMMAND 
3846     °ú¿ô¤È¤·¤ÆÍѤ¤¤é¤ì¤ëÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë (#MInputDriver::callback_list »²¾È)¡£
3847
3848     ¤Û¤È¤ó¤É¤ÏÄɲäΰú¿ô¤òɬÍפȤ·¤Ê¤¤¤·ÃͤòÊÖ¤µ¤Ê¤¤¤¬¡¢°Ê²¼¤ÏÎã³°¤Ç¤¢¤ë¡£
3849
3850     Minput_get_surrounding_text: ¤³¤Î¥³¥Þ¥ó¥É¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿¥³¡¼¥ë¥Ð¥Ã
3851     ¥¯´Ø¿ô¤¬¸Æ¤Ð¤ì¤¿ºÝ¤Ë¤Ï¡¢ #MInputContext::plist ¤ÎÂè°ìÍ×ÁǤϥ­¡¼¤È¤·
3852     ¤Æ#Minteger ¤ò¤È¤ê¡¢¤½¤ÎÃͤϥµ¥é¥¦¥ó¥Ç¥£¥ó¥°¥Æ¥­¥¹¥È¤Î¤¦¤Á¤É¤ÎÉôʬ
3853     ¤ò¼è¤Ã¤ÆÍè¤ë¤«¤ò»ØÄꤹ¤ë¡£Ãͤ¬Àµ¤Ç¤¢¤ì¤Ð¡¢¸½ºß¤Î¥«¡¼¥½¥ë°ÌÃ֤˳¤¯
3854     ÃͤθĿôʬ¤Îʸ»ú¤ò¼è¤ë¡£Éé¤Ç¤¢¤ì¤Ð¡¢¥«¡¼¥½¥ë°ÌÃÖ¤ËÀè¹Ô¤¹¤ëÃͤÎÀäÂÐ
3855     ÃÍʬ¤Îʸ»ú¤ò¼è¤ë¡£
3856
3857     ¥µ¥é¥¦¥ó¥Ç¥£¥ó¥°¥Æ¥­¥¹¥È¤¬¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤ì¤Ð¡¢¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Ï
3858     ¤³¤ÎÍ×ÁǤΥ­¡¼¤ò #Mtext ¤Ë¡¢Ãͤò¼è¤ê¹þ¤ó¤ÀM-text ¤ËÀßÄꤷ¤Ê¤¯¤Æ¤Ï¤Ê
3859     ¤é¤Ê¤¤¡£¤â¤·¥Æ¥­¥¹¥È¤ÎŤµ¤¬½¼Ê¬¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î M-text ¤ÎŤµ¤ÏÍ×
3860     µá¤µ¤ì¤Æ¤¤¤ëʸ»ú¿ô¤è¤êû¤¯¤ÆÎɤ¤¡£ºÇ°­¤Î¾ì¹ç 0 ¤Ç¤â¤è¤¤¤·¡¢¥¢¥×¥ê¥±¡¼
3861     ¥·¥ç¥ó¦¤ÇɬÍפǸúΨŪ¤À¤È»×¤¨¤ÐŤ¯¤Æ¤âÎɤ¤¡£
3862
3863     ¥µ¥é¥¦¥ó¥Ç¥£¥ó¥°¥Æ¥­¥¹¥È¤¬¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¡¢¥³¡¼¥ë¥Ð¥Ã¥¯´Ø
3864     ¿ô¤Ï #MInputContext::plist ¤ÎÂè°ìÍ×ÁǤòÊѲ½¤µ¤»¤ë¤³¤È¤Ê¤¯ÊÖ¤µ¤Ê¤¯¤Æ
3865     ¤Ï¤Ê¤é¤Ê¤¤¡£
3866
3867     Minput_delete_surrounding_text: ¤³¤Î¥³¥Þ¥ó¥É¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿¥³¡¼¥ë
3868     ¥Ð¥Ã¥¯´Ø¿ô¤¬¸Æ¤Ð¤ì¤¿ºÝ¤Ë¤Ï¡¢#MInputContext::plist ¤ÎÂè°ìÍ×ÁǤϡ¢¥­¡¼
3869     ¤È¤·¤Æ#Minteger ¤ò¤È¤ê¡¢ÃͤϺï½ü¤¹¤ë¤Ù¤­¥µ¥é¥¦¥ó¥Ç¥£¥ó¥°¥Æ¥­¥¹¥È¤ò
3870     Minput_get_surrounding_text ¤ÈƱÍͤΤä¤êÊý¤Ç»ØÄꤹ¤ë¡£¥³¡¼¥ë¥Ð¥Ã¥¯
3871     ´Ø¿ô¤Ï»ØÄꤵ¤ì¤¿¥Æ¥­¥¹¥È¤òºï½ü¤·¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£¤Þ¤¿
3872     #MInputContext::plist ¤òÊѤ¨¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£  */ 
3873 /*** @{ */ 
3874 /*=*/
3875
3876 MSymbol Minput_preedit_start;
3877 MSymbol Minput_preedit_done;
3878 MSymbol Minput_preedit_draw;
3879 MSymbol Minput_status_start;
3880 MSymbol Minput_status_done;
3881 MSymbol Minput_status_draw;
3882 MSymbol Minput_candidates_start;
3883 MSymbol Minput_candidates_done;
3884 MSymbol Minput_candidates_draw;
3885 MSymbol Minput_set_spot;
3886 MSymbol Minput_toggle;
3887 MSymbol Minput_reset;
3888 MSymbol Minput_get_surrounding_text;
3889 MSymbol Minput_delete_surrounding_text;
3890 /*** @} */
3891
3892 /*=*/
3893
3894 /***en
3895     @name Variables: Predefined symbols for special input events.
3896
3897     These are the predefined symbols that are used as the @c KEY
3898     argument of minput_filter ().  */ 
3899 /***ja
3900     @name ÊÑ¿ô: ÆÃÊ̤ÊÆþÎÏ¥¤¥Ù¥ó¥ÈÍÑÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë.
3901
3902     minput_filter () ¤Î @c KEY °ú¿ô¤È¤·¤ÆÍѤ¤¤é¤ì¤ëÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë¡£  */ 
3903
3904 /*** @{ */ 
3905 /*=*/
3906
3907 MSymbol Minput_focus_out;
3908 MSymbol Minput_focus_in;
3909 MSymbol Minput_focus_move;
3910
3911 /*** @} */
3912
3913 /*=*/
3914 /***en
3915     @name Variables: Predefined symbols used in input method information.
3916
3917     These are the predefined symbols describing status of input method
3918     command and variable, and are used in a return value of
3919     minput_get_command () and minput_get_variable ().  */
3920 /***ja
3921     @name ÊÑ¿ô: ÆþÎϥ᥽¥Ã¥É¾ðÊóÍÑÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë.
3922
3923     ÆþÎϥ᥽¥Ã¥É¤Î¥³¥Þ¥ó¥É¤äÊÑ¿ô¤Î¾õÂÖ¤òɽ¤·¡¢minput_get_command () ¤È
3924     minput_get_variable () ¤ÎÌá¤êÃͤȤ·¤ÆÍѤ¤¤é¤ì¤ëÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë¡£  */
3925 /*** @{ */ 
3926 /*=*/
3927 MSymbol Minherited;
3928 MSymbol Mcustomized;
3929 MSymbol Mconfigured;
3930 /*** @} */ 
3931
3932 /*=*/
3933
3934 /***en
3935     @brief The default driver for internal input methods.
3936
3937     The variable #minput_default_driver is the default driver for
3938     internal input methods.
3939
3940     The member MInputDriver::open_im () searches the m17n database for
3941     an input method that matches the tag \< #Minput_method, $LANGUAGE,
3942     $NAME\> and loads it.
3943
3944     The member MInputDriver::callback_list () is @c NULL.  Thus, it is
3945     programmers responsibility to set it to a plist of proper callback
3946     functions.  Otherwise, no feedback information (e.g. preedit text)
3947     can be shown to users.
3948
3949     The macro M17N_INIT () sets the variable #minput_driver to the
3950     pointer to this driver so that all internal input methods use it.
3951
3952     Therefore, unless @c minput_driver is set differently, the driver
3953     dependent arguments $ARG of the functions whose name begins with
3954     "minput_" are all ignored.  */
3955 /***ja
3956     @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥǥե©¥ë¥È¥É¥é¥¤¥Ð.
3957
3958     ÊÑ¿ô #minput_default_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѤΥǥե©¥ë¥È¤Î¥É¥é¥¤¥Ð¤òɽ¤¹¡£
3959
3960     ¥á¥ó¥Ð MInputDriver::open_im () ¤Ï m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹Ã椫¤é¥¿¥° 
3961     \< #Minput_method, $LANGUAGE, $NAME\> 
3962     ¤Ë¹çÃפ¹¤ëÆþÎϥ᥽¥Ã¥É¤òõ¤·¡¢¤½¤ì¤ò¥í¡¼¥É¤¹¤ë¡£
3963
3964     ¥á¥ó¥Ð MInputDriver::callback_list () ¤Ï @c NULL ¤Ç¤¢¤ê¡¢
3965     ¤·¤¿¤¬¤Ã¤Æ¡¢¥×¥í¥°¥é¥Þ¦¤ÇÀÕǤ¤ò»ý¤Ã¤Æ Å¬Àڤʥ³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Î plist
3966     ¤ËÀßÄꤷ¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¤µ¤â¤Ê¤¤¤È¡¢preedit 
3967     ¥Æ¥­¥¹¥È¤Ê¤É¤Î¥Õ¥£¡¼¥É¥Ð¥Ã¥¯¾ðÊ󤬥桼¥¶¤Ëɽ¼¨¤µ¤ì¤Ê¤¤¡£
3968
3969     ¥Þ¥¯¥í M17N_INIT () ¤ÏÊÑ¿ô #minput_driver 
3970     ¤ò¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤ËÀßÄꤷ¡¢Á´¤Æ¤ÎÆâÉôÆþÎϥ᥽¥Ã¥É¤¬¤³¤Î¥É¥é¥¤¥Ð¤ò»È¤¦¤è¤¦¤Ë¤¹¤ë¡£
3971
3972     ¤·¤¿¤¬¤Ã¤Æ¡¢@c minput_driver ¤¬¥Ç¥Õ¥©¥ë¥ÈÃͤΤޤޤǤ¢¤ì¤Ð¡¢minput_ 
3973     ¤Ç»Ï¤Þ¤ë´Ø¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô $ARG ¤Ï¤¹¤Ù¤Æ̵»ë¤µ¤ì¤ë¡£  */
3974
3975 MInputDriver minput_default_driver;
3976 /*=*/
3977
3978 /***en
3979     @brief The driver for internal input methods.
3980
3981     The variable #minput_driver is a pointer to the input method
3982     driver that is used by internal input methods.  The macro
3983     M17N_INIT () initializes it to a pointer to #minput_default_driver
3984     if <m17n<EM></EM>.h> is included.  */ 
3985 /***ja
3986     @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥɥ饤¥Ð.
3987
3988     ÊÑ¿ô #minput_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤Æ»ÈÍѤµ¤ì¤Æ¤¤¤ëÆþÎÏ¥á
3989     ¥½¥Ã¥É¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£¥Þ¥¯¥í M17N_INIT () ¤Ï¤³¤Î¥Ý¥¤¥ó
3990     ¥¿¤ò#minput_default_driver (<m17n<EM></EM>.h> ¤¬ include ¤µ¤ì¤Æ¤¤¤ë
3991     »þ) ¤Ë½é´ü²½¤¹¤ë¡£  */ 
3992
3993 MInputDriver *minput_driver;
3994
3995 MSymbol Minput_driver;
3996
3997 /*=*/
3998
3999 /***en
4000     @brief Open an input method.
4001
4002     The minput_open_im () function opens an input method whose
4003     language and name match $LANGUAGE and $NAME, and returns a pointer
4004     to the input method object newly allocated.
4005
4006     This function at first decides a driver for the input method as
4007     described below.
4008
4009     If $LANGUAGE is not #Mnil, the driver pointed by the variable
4010     #minput_driver is used.
4011
4012     If $LANGUAGE is #Mnil and $NAME has the property #Minput_driver, the
4013     driver pointed to by the property value is used to open the input
4014     method.  If $NAME has no such a property, @c NULL is returned.
4015
4016     Then, the member MInputDriver::open_im () of the driver is
4017     called.  
4018
4019     $ARG is set in the member @c arg of the structure MInputMethod so
4020     that the driver can refer to it.  */
4021 /***ja
4022     @brief ÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë.
4023
4024     ´Ø¿ô minput_open_im () ¤Ï¸À¸ì $LANGUAGE ¤È̾Á° $NAME 
4025     ¤Ë¹çÃפ¹¤ëÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤·¡¢¿·¤¿¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿ÆþÎϥ᥽¥Ã¥É¥ª¥Ö¥¸¥§¥¯¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
4026     
4027     ¤³¤Î´Ø¿ô¤Ï¡¢¤Þ¤ºÆþÎϥ᥽¥Ã¥ÉÍѤΥɥ饤¥Ð¤ò°Ê²¼¤Î¤è¤¦¤Ë¤·¤Æ·èÄꤹ¤ë¡£
4028
4029     $LANGUAGE ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢ÊÑ¿ô #minput_driver 
4030     ¤Ç»Ø¤µ¤ì¤Æ¤¤¤ë¥É¥é¥¤¥Ð¤òÍѤ¤¤ë¡£
4031
4032     $LANGUAGE ¤¬ #Mnil ¤Ç¤¢¤ê¡¢$NAME ¤¬ #Minput_driver
4033     ¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä¾ì¹ç¤Ë¤Ï¡¢¤½¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤǻؤµ¤ì¤Æ¤¤¤ëÆþÎϥɥ饤¥Ð¤òÍѤ¤¤ÆÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë¡£
4034     $NAME ¤Ë¤½¤Î¤è¤¦¤Ê¥×¥í¥Ñ¥Æ¥£¤¬Ìµ¤«¤Ã¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
4035
4036     ¼¡¤¤¤Ç¡¢¥É¥é¥¤¥Ð¤Î¥á¥ó¥Ð MInputDriver::open_im () ¤¬¸Æ¤Ð¤ì¤ë¡£
4037
4038     $ARG ¤Ï¹½Â¤ÂΠMInputMethod ¤Î¥á¥ó¥Ð @c arg ¤ËÀßÄꤵ¤ì¡¢¥É¥é¥¤¥Ð¤«¤é»²¾È¤Ç¤­¤ë¡£
4039
4040     @latexonly \IPAlabel{minput_open} @endlatexonly
4041
4042 */
4043
4044 MInputMethod *
4045 minput_open_im (MSymbol language, MSymbol name, void *arg)
4046 {
4047   MInputMethod *im;
4048   MInputDriver *driver;
4049
4050   MINPUT__INIT ();
4051
4052   MDEBUG_PRINT2 ("  [IM] opening (%s %s) ... ",
4053                  msymbol_name (language), msymbol_name (name));
4054   if (language)
4055     driver = minput_driver;
4056   else
4057     {
4058       driver = (MInputDriver *) msymbol_get (name, Minput_driver);
4059       if (! driver)
4060         MERROR (MERROR_IM, NULL);
4061     }
4062
4063   MSTRUCT_CALLOC (im, MERROR_IM);
4064   im->language = language;
4065   im->name = name;
4066   im->arg = arg;
4067   im->driver = *driver;
4068   if ((*im->driver.open_im) (im) < 0)
4069     {
4070       MDEBUG_PRINT (" failed\n");
4071       free (im);
4072       return NULL;
4073     }
4074   MDEBUG_PRINT (" ok\n");
4075   return im;
4076 }
4077
4078 /*=*/
4079
4080 /***en
4081     @brief Close an input method.
4082
4083     The minput_close_im () function closes the input method $IM, which
4084     must have been created by minput_open_im ().  */
4085
4086 /***ja
4087     @brief ÆþÎϥ᥽¥Ã¥É¤ò¥¯¥í¡¼¥º¤¹¤ë.
4088
4089     ´Ø¿ô minput_close_im () ¤Ï¡¢ÆþÎϥ᥽¥Ã¥É $IM ¤ò¥¯¥í¡¼¥º¤¹¤ë¡£
4090     ¤³¤ÎÆþÎϥ᥽¥Ã¥É $IM ¤Ï minput_open_im () ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£  */
4091
4092 void
4093 minput_close_im (MInputMethod *im)
4094 {
4095   MDEBUG_PRINT2 ("  [IM] closing (%s %s) ... ",
4096                  msymbol_name (im->name), msymbol_name (im->language));
4097   (*im->driver.close_im) (im);
4098   free (im);
4099   MDEBUG_PRINT (" done\n");
4100 }
4101
4102 /*=*/
4103
4104 /***en
4105     @brief Create an input context.
4106
4107     The minput_create_ic () function creates an input context object
4108     associated with input method $IM, and calls callback functions
4109     corresponding to #Minput_preedit_start, #Minput_status_start, and
4110     #Minput_status_draw in this order.
4111
4112     @return
4113     If an input context is successfully created, minput_create_ic ()
4114     returns a pointer to it.  Otherwise it returns @c NULL.  */
4115
4116 /***ja
4117     @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÀ¸À®¤¹¤ë.
4118
4119     ´Ø¿ô minput_create_ic () ¤ÏÆþÎϥ᥽¥Ã¥É $IM
4120     ¤ËÂбþ¤¹¤ëÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤·¡¢
4121     #Minput_preedit_start, #Minput_status_start, #Minput_status_draw
4122     ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¤³¤Î½ç¤Ë¸Æ¤Ö¡£
4123
4124     @return
4125     ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤¬À¸À®¤µ¤ì¤¿¾ì¹ç¡¢minput_create_ic () 
4126     ¤Ï¤½¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¼ºÇÔ¤·¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
4127       */
4128
4129 MInputContext *
4130 minput_create_ic (MInputMethod *im, void *arg)
4131 {
4132   MInputContext *ic;
4133
4134   MDEBUG_PRINT2 ("  [IM] creating context (%s %s) ... ",
4135                  msymbol_name (im->name), msymbol_name (im->language));
4136   MSTRUCT_CALLOC (ic, MERROR_IM);
4137   ic->im = im;
4138   ic->arg = arg;
4139   ic->preedit = mtext ();
4140   ic->candidate_list = NULL;
4141   ic->produced = mtext ();
4142   ic->spot.x = ic->spot.y = 0;
4143   ic->active = 1;
4144   ic->plist = mplist ();
4145   if ((*im->driver.create_ic) (ic) < 0)
4146     {
4147       MDEBUG_PRINT (" failed\n");
4148       M17N_OBJECT_UNREF (ic->preedit);
4149       M17N_OBJECT_UNREF (ic->produced);
4150       M17N_OBJECT_UNREF (ic->plist);
4151       free (ic);
4152       return NULL;
4153     };
4154
4155   if (im->driver.callback_list)
4156     {
4157       minput__callback (ic, Minput_preedit_start);
4158       minput__callback (ic, Minput_status_start);
4159       minput__callback (ic, Minput_status_draw);
4160     }
4161
4162   MDEBUG_PRINT (" ok\n");
4163   return ic;
4164 }
4165
4166 /*=*/
4167
4168 /***en
4169     @brief Destroy an input context.
4170
4171     The minput_destroy_ic () function destroys the input context $IC,
4172     which must have been created by minput_create_ic ().  It calls
4173     callback functions corresponding to #Minput_preedit_done,
4174     #Minput_status_done, and #Minput_candidates_done in this order.  */
4175
4176 /***ja
4177     @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÇ˲õ¤¹¤ë.
4178
4179     ´Ø¿ô minput_destroy_ic () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤òÇ˲õ¤¹¤ë¡£
4180     ¤³¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ï minput_create_ic () 
4181     ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£¤³¤Î´Ø¿ô¤Ï 
4182     #Minput_preedit_done, #Minput_status_done, #Minput_candidates_done 
4183     ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¤³¤Î½ç¤Ë¸Æ¤Ö¡£
4184   */
4185
4186 void
4187 minput_destroy_ic (MInputContext *ic)
4188 {
4189   MDEBUG_PRINT2 ("  [IM] destroying context (%s %s) ... ",
4190                  msymbol_name (ic->im->name), msymbol_name (ic->im->language));
4191   if (ic->im->driver.callback_list)
4192     {
4193       minput__callback (ic, Minput_preedit_done);
4194       minput__callback (ic, Minput_status_done);
4195       minput__callback (ic, Minput_candidates_done);
4196     }
4197   (*ic->im->driver.destroy_ic) (ic);
4198   M17N_OBJECT_UNREF (ic->preedit);
4199   M17N_OBJECT_UNREF (ic->produced);
4200   M17N_OBJECT_UNREF (ic->plist);
4201   MDEBUG_PRINT (" done\n");
4202   free (ic);
4203 }
4204
4205 /*=*/
4206
4207 /***en
4208     @brief Filter an input key.
4209
4210     The minput_filter () function filters input key $KEY according to
4211     input context $IC, and calls callback functions corresponding to
4212     #Minput_preedit_draw, #Minput_status_draw, and
4213     #Minput_candidates_draw if the preedit text, the status, and the
4214     current candidate are changed respectively.
4215
4216     To make the input method commit the current preedit text (if any)
4217     and shift to the initial state, call this function with #Mnil as
4218     $KEY.
4219
4220     To inform the input method about the focus-out event, call this
4221     function with #Minput_focus_out as $KEY.
4222
4223     To inform the input method about the focus-in event, call this
4224     function with #Minput_focus_in as $KEY.
4225
4226     To inform the input method about the focus-move event (i.e. input
4227     spot change within the same input context), call this function
4228     with #Minput_focus_move as $KEY.
4229
4230     @return
4231     If $KEY is filtered out, this function returns 1.  In that case,
4232     the caller should discard the key.  Otherwise, it returns 0, and
4233     the caller should handle the key, for instance, by calling the
4234     function minput_lookup () with the same key.  */
4235
4236 /***ja
4237     @brief ÆþÎÏ¥­¡¼¤ò¥Õ¥£¥ë¥¿¤¹¤ë.
4238
4239     ´Ø¿ô minput_filter () ¤ÏÆþÎÏ¥­¡¼ $KEY ¤òÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC 
4240     ¤Ë±þ¤¸¤Æ¥Õ¥£¥ë¥¿¤·¡¢preedit ¥Æ¥­¥¹¥È¡¢¥¹¥Æ¡¼¥¿¥¹¡¢¸½»þÅÀ¤Ç¤Î¸õÊ䤬ÊѲ½¤·¤¿»þÅÀ¤Ç¡¢¤½¤ì¤¾¤ì
4241     #Minput_preedit_draw, #Minput_status_draw,
4242     #Minput_candidates_draw ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¸Æ¤Ö¡£
4243
4244     @return 
4245     $KEY ¤¬¥Õ¥£¥ë¥¿¤µ¤ì¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 1 ¤òÊÖ¤¹¡£
4246     ¤³¤Î¾ì¹ç¸Æ¤Ó½Ð¤·Â¦¤Ï¤³¤Î¥­¡¼¤ò¼Î¤Æ¤ë¤Ù¤­¤Ç¤¢¤ë¡£
4247     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0 ¤òÊÖ¤·¡¢¸Æ¤Ó½Ð¤·Â¦¤Ï¡¢¤¿¤È¤¨¤ÐƱ¤¸¥­¡¼¤Ç´Ø¿ô minput_lookup ()
4248     ¤ò¸Æ¤Ö¤Ê¤É¤·¤Æ¡¢¤³¤Î¥­¡¼¤ò½èÍý¤¹¤ë¡£
4249
4250     @latexonly \IPAlabel{minput_filter} @endlatexonly
4251 */
4252
4253 int
4254 minput_filter (MInputContext *ic, MSymbol key, void *arg)
4255 {
4256   int ret;
4257
4258   if (! ic
4259       || ! ic->active)
4260     return 0;
4261   ret = (*ic->im->driver.filter) (ic, key, arg);
4262
4263   if (ic->im->driver.callback_list)
4264     {
4265       if (ic->preedit_changed)
4266         minput__callback (ic, Minput_preedit_draw);
4267       if (ic->status_changed)
4268         minput__callback (ic, Minput_status_draw);
4269       if (ic->candidates_changed)
4270         minput__callback (ic, Minput_candidates_draw);
4271     }
4272
4273   return ret;
4274 }
4275
4276 /*=*/
4277
4278 /***en
4279     @brief Look up a text produced in the input context.
4280
4281     The minput_lookup () function looks up a text in the input context
4282     $IC.  $KEY must be identical to the one that was used in the previous call of
4283     minput_filter ().
4284
4285     If a text was produced by the input method, it is concatenated
4286     to M-text $MT.
4287
4288     This function calls #MInputDriver::lookup .
4289
4290     @return
4291     If $KEY was correctly handled by the input method, this function
4292     returns 0.  Otherwise, it returns -1, even though some text
4293     might be produced in $MT.  */
4294
4295 /***ja
4296     @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥ÈÃæ¤Î¥Æ¥­¥¹¥È¤òõ¤¹.
4297
4298     ´Ø¿ô minput_lookup () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC Ãæ¤Î¥Æ¥­¥¹¥È¤òõ¤¹¡£
4299     $KEY ¤Ï´Ø¿ô minput_filter () ¤Ø¤ÎľÁ°¤Î¸Æ¤Ó½Ð¤·¤ËÍѤ¤¤é¤ì¤¿¤â¤Î¤ÈƱ¤¸¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
4300
4301     ¥Æ¥­¥¹¥È¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆÀ¸À®¤µ¤ì¤Æ¤¤¤ì¤Ð¡¢¥Æ¥­¥¹¥È¤Ï M-text
4302     $MT ¤ËÏ¢·ë¤µ¤ì¤ë¡£
4303
4304     ¤³¤Î´Ø¿ô¤Ï¡¢#MInputDriver::lookup ¤ò¸Æ¤Ö¡£
4305
4306     @return 
4307     $KEY ¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆŬÀڤ˽èÍý¤Ç¤­¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 0 ¤òÊÖ¤¹¡£
4308     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£
4309     ¤³¤Î¾ì¹ç¤Ç¤â $MT ¤Ë²¿¤é¤«¤Î¥Æ¥­¥¹¥È¤¬À¸À®¤µ¤ì¤Æ¤¤¤ë¤³¤È¤¬¤¢¤ë¡£
4310
4311     @latexonly \IPAlabel{minput_lookup} @endlatexonly  */
4312
4313 int
4314 minput_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
4315 {
4316   return (ic ? (*ic->im->driver.lookup) (ic, key, arg, mt) : -1);
4317 }
4318 /*=*/
4319
4320 /***en
4321     @brief Set the spot of the input context.
4322
4323     The minput_set_spot () function sets the spot of input context $IC
4324     to coordinate ($X, $Y ) with the height specified by $ASCENT and $DESCENT .
4325     The semantics of these values depends on the input method driver.
4326
4327     For instance, a driver designed to work in a CUI environment may
4328     use $X and $Y as the column- and row numbers, and may ignore $ASCENT and
4329     $DESCENT .  A driver designed to work in a window system may
4330     interpret $X and $Y as the pixel offsets relative to the origin of the
4331     client window, and may interpret $ASCENT and $DESCENT as the ascent- and
4332     descent pixels of the line at ($X . $Y ).
4333
4334     $FONTSIZE specifies the fontsize of preedit text in 1/10 point.
4335
4336     $MT and $POS are the M-text and the character position at the spot.
4337     $MT may be @c NULL, in which case, the input method cannot get
4338     information about the text around the spot.  */
4339
4340 /***ja
4341     @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Î¥¹¥Ý¥Ã¥È¤òÀßÄꤹ¤ë.
4342
4343     ´Ø¿ô minput_set_spot () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤Î¥¹¥Ý¥Ã¥È¤ò¡¢ºÂɸ ($X, $Y )
4344     ¤Î°ÌÃ֤ˠ¡¢¹â¤µ $ASCENT¡¢ $DESCENT 
4345     ¤ÇÀßÄꤹ¤ë¡£ ¤³¤ì¤é¤ÎÃͤΰÕÌ£¤ÏÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë¡£
4346
4347     ¤¿¤È¤¨¤Ð CUI ´Ä¶­¤ÇÆ°ºî¤¹¤ë¥É¥é¥¤¥Ð¤Ï $X ¤È $Y 
4348     ¤ò¤½¤ì¤¾¤ìÎó¤È¹Ô¤ÎÈÖ¹æ¤È¤·¤ÆÍѤ¤¡¢$ASCENT ¤È $DESCENT 
4349     ¤ò̵»ë¤¹¤ë¤«¤â¤·¤ì¤Ê¤¤¡£ ¤Þ¤¿¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥àÍѤΥɥ饤¥Ð¤Ï
4350     $X ¤È $Y ¤ò¥¯¥é¥¤¥¢¥ó¥È¥¦¥£¥ó¥É¥¦¤Î¸¶ÅÀ¤«¤é¤Î¥ª¥Õ¥»¥Ã¥È¤ò¥Ô¥¯¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¤¡¢
4351     $ASCENT ¤È $DESCENT ¤ò ($X . $Y )
4352     ¤ÎÎó¤Î¥¢¥»¥ó¥È¤È¥Ç¥£¥»¥ó¥È¤ò¥Ô¥¯¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¦¤«¤â¤·¤ì¤Ê¤¤¡£
4353
4354     $FONTSIZE ¤Ë¤Ï preedit ¥Æ¥­¥¹¥È¤Î¥Õ¥©¥ó¥È¥µ¥¤¥º¤ò 1/10 ¥Ý¥¤¥ó¥Èñ°Ì¤Ç»ØÄꤹ¤ë¡£
4355
4356     $MT ¤È $POS ¤Ï¤½¤Î¥¹¥Ý¥Ã¥È¤Î M-text ¤Èʸ»ú°ÌÃ֤Ǥ¢¤ë¡£$MT ¤Ï @c
4357     NULL ¤Ç¤â¤è¤¯¡¢¤½¤Î¾ì¹ç¤Ë¤ÏÆþÎϥ᥽¥Ã¥É¤Ï¥¹¥Ý¥Ã¥È¼þÊդΥƥ­¥¹¥È¤Ë´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë¤³¤È¤¬¤Ç¤­¤Ê¤¤¡£
4358     */
4359
4360 void
4361 minput_set_spot (MInputContext *ic, int x, int y,
4362                  int ascent, int descent, int fontsize,
4363                  MText *mt, int pos)
4364 {
4365   ic->spot.x = x;
4366   ic->spot.y = y;
4367   ic->spot.ascent = ascent;
4368   ic->spot.descent = descent;
4369   ic->spot.fontsize = fontsize;
4370   ic->spot.mt = mt;
4371   ic->spot.pos = pos;
4372   if (ic->im->driver.callback_list)
4373     minput__callback (ic, Minput_set_spot);
4374 }
4375 /*=*/
4376
4377 /***en
4378     @brief Toggle input method.
4379
4380     The minput_toggle () function toggles the input method associated
4381     with input context $IC.  */
4382 /***ja
4383     @brief ÆþÎϥ᥽¥Ã¥É¤òÀÚÂؤ¨¤ë.
4384
4385     ´Ø¿ô minput_toggle () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC 
4386     ¤ËÂбþÉÕ¤±¤é¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ò¥È¥°¥ë¤¹¤ë¡£
4387     */
4388
4389 void
4390 minput_toggle (MInputContext *ic)
4391 {
4392   if (ic->im->driver.callback_list)
4393     minput__callback (ic, Minput_toggle);
4394   ic->active = ! ic->active;
4395 }
4396
4397 /*=*/
4398
4399 /***en
4400     @brief Reset an input context.
4401
4402     The minput_reset_ic () function resets input context $IC by
4403     calling a callback function corresponding to #Minput_reset.  It
4404     resets the status of $IC to its initial one.  As the
4405     current preedit text is deleted without commitment, if necessary,
4406     call minput_filter () with the arg @r key #Mnil to force the input
4407     method to commit the preedit in advance.  */
4408
4409 /***ja
4410     @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤ò¥ê¥»¥Ã¥È¤¹¤ë.
4411
4412     ´Ø¿ô minput_reset_ic () ¤Ï #Minput_reset ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô
4413     ¤ò¸Æ¤Ö¤³¤È¤Ë¤è¤Ã¤ÆÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤ò¥ê¥»¥Ã¥È¤¹¤ë¡£¥ê¥»¥Ã¥È¤È¤Ï¡¢
4414     ¼ÂºÝ¤Ë¤ÏÆþÎϥ᥽¥Ã¥É¤ò½é´ü¾õÂ֤˰ܤ¹¤³¤È¤Ç¤¢¤ë¡£¸½ºßÆþÎÏÃæ¤Î¥Æ¥­¥¹
4415     ¥È¤Ï¥³¥ß¥Ã¥È¤µ¤ì¤ë¤³¤È¤Ê¤¯ºï½ü¤µ¤ì¤ë¤Î¤Ç¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é
4416     ¥à¤Ï¡¢É¬Íפʤé¤Ðͽ¤á minput_filter () ¤ò°ú¿ô @r key #Mnil ¤Ç¸Æ¤ó¤Ç
4417     ¶¯À©Åª¤Ë¥×¥ê¥¨¥Ç¥£¥Ã¥È¥Æ¥­¥¹¥È¤ò¥³¥ß¥Ã¥È¤µ¤»¤ë¤³¤È¡£  */
4418
4419 void
4420 minput_reset_ic (MInputContext *ic)
4421 {
4422   if (ic->im->driver.callback_list)
4423     minput__callback (ic, Minput_reset);
4424 }
4425
4426 /*=*/
4427
4428 /***en
4429     @brief Get title and icon filename of an input method.
4430
4431     The minput_get_title_icon () function returns a plist containing a
4432     title and icon filename (if any) of an input method specified by
4433     $LANGUAGE and $NAME.
4434
4435     The first element of the plist has key #Mtext and the value is an
4436     M-text of the title for identifying the input method.  The second
4437     element (if any) has key #Mtext and the value is an M-text of the
4438     icon image (absolute) filename for the same purpose.
4439
4440     @return
4441     If there exists a specified input method and it defines an title,
4442     a plist is returned.  Otherwise, NULL is returned.  The caller
4443     must free the plist by m17n_object_unref ().  */
4444 /***ja
4445     @brief ÆþÎϥ᥽¥Ã¥É¤Î¥¿¥¤¥È¥ë¤È¥¢¥¤¥³¥óÍÑ¥Õ¥¡¥¤¥ë̾¤òÆÀ¤ë.
4446
4447     ´Ø¿ô minput_get_title_icon () ¤Ï¡¢ $LANGUAGE ¤È $NAME ¤Ç»ØÄꤵ¤ì¤ë
4448     ÆþÎϥ᥽¥Ã¥É¤Î¥¿¥¤¥È¥ë¤È¡Ê¤¢¤ì¤Ð¡Ë¥¢¥¤¥³¥óÍÑ¥Õ¥¡¥¤¥ë¤ò´Þ¤à plist ¤ò
4449     ÊÖ¤¹¡£
4450
4451     plist ¤ÎÂè°ìÍ×ÁǤϡ¢#Mtext ¤ò¥­¡¼¤Ë»ý¤Á¡¢ÃͤÏÆþÎϥ᥽¥Ã¥É¤ò¼±Ê̤¹¤ë
4452     ¥¿¥¤¥È¥ë¤òɽ¤¹ M-text ¤Ç¤¢¤ë¡£ÂèÆóÍ×ÁǤ¬¤¢¤ì¤Ð¡¢¥­¡¼¤Ï #Mtext ¤Ç¤¢
4453     ¤ê¡¢Ãͤϼ±ÊÌÍÑ¥¢¥¤¥³¥ó²èÁü¤ÎÀäÂÐ¥Õ¥¡¥¤¥ë¥Í¡¼¥à¤òɽ¤¹ M-text ¤Ç¤¢¤ë¡£
4454
4455     @return
4456     »ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤¬Â¸ºß¤·¡¢¥¿¥¤¥È¥ë¤¬ÄêµÁ¤µ¤ì¤Æ¤¤¤ì¤Ð
4457      plist ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð NULL ¤òÊÖ¤¹¡£¸Æ½Ð¦¤Ï
4458      ´Ø¿ô m17n_object_unref () ¤òÍѤ¤¤Æ plist ¤ò²òÊü¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£  */
4459
4460 MPlist *
4461 minput_get_title_icon (MSymbol language, MSymbol name)
4462 {
4463   MInputMethodInfo *im_info;
4464   MPlist *plist;
4465   char *file = NULL;
4466   MText *mt;
4467
4468   MINPUT__INIT ();
4469
4470   im_info = get_im_info (language, name, Mnil, Mtitle);
4471   if (! im_info || !im_info->title)
4472     return NULL;
4473   mt = mtext_get_prop (im_info->title, 0, Mtext);
4474   if (mt)
4475     file = mdatabase__find_file ((char *) MTEXT_DATA (mt));
4476   else
4477     {
4478       char *buf = alloca (MSYMBOL_NAMELEN (language) + MSYMBOL_NAMELEN (name)
4479                           + 12);
4480
4481       sprintf (buf, "icons/%s-%s.png", (char *) MSYMBOL_NAME (language), 
4482                (char *) MSYMBOL_NAME (name));
4483       file = mdatabase__find_file (buf);
4484       if (! file && language == Mt)
4485         {
4486           sprintf (buf, "icons/%s.png", (char *) MSYMBOL_NAME (name));
4487           file = mdatabase__find_file (buf);
4488         }
4489     }
4490
4491   plist = mplist ();
4492   mplist_add (plist, Mtext, im_info->title);
4493   if (file)
4494     {
4495       mt = mtext__from_data (file, strlen (file), MTEXT_FORMAT_UTF_8, 1);
4496       free (file);
4497       mplist_add (plist, Mtext, mt);
4498       M17N_OBJECT_UNREF (mt);
4499     }
4500   return plist;
4501 }
4502
4503 /*=*/
4504
4505 /***en
4506     @brief Get description text of an input method.
4507
4508     The minput_get_description () function returns an M-text that
4509     describes the input method specified by $LANGUAGE and $NAME.
4510
4511     @return
4512     If the specified input method has a description text, a pointer to
4513     #MText is returned.  The caller has to free it by m17n_object_unref ().
4514     If the input method does not have a description text, @c NULL is
4515     returned.  */
4516 /***ja
4517     @brief ÆþÎϥ᥽¥Ã¥É¤ÎÀâÌÀ¥Æ¥­¥¹¥È¤òÆÀ¤ë.
4518
4519     ´Ø¿ô minput_get_description () ¤Ï¡¢$LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ»ØÄê
4520     ¤µ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤òÀâÌÀ¤¹¤ë M-text ¤òÊÖ¤¹¡£
4521
4522     @return »ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤¬ÀâÌÀ¤¹¤ë¥Æ¥­¥¹¥È¤ò»ý¤Ã¤Æ¤¤¤ì¤Ð¡¢
4523     #MText ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¸Æ¤Ó½Ð¤·Â¦¤Ï¡¢¤½¤ì¤ò m17n_object_unref
4524     () ¤òÍѤ¤¤Æ²òÊü¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ÆþÎϥ᥽¥Ã¥É¤ËÀâÌÀ¥Æ¥­¥¹¥È¤¬Ìµ¤±
4525     ¤ì¤Ð@c NULL ¤òÊÖ¤¹¡£ */
4526
4527 MText *
4528 minput_get_description (MSymbol language, MSymbol name)
4529 {
4530   MInputMethodInfo *im_info;
4531
4532   MINPUT__INIT ();
4533
4534   im_info = get_im_info (language, name, Mnil, Mdescription);
4535   if (! im_info || ! im_info->description)
4536     return NULL;
4537   M17N_OBJECT_REF (im_info->description);
4538   return im_info->description;
4539 }
4540
4541 /*=*/
4542
4543 /***en
4544     @brief Get information about input method command(s).
4545
4546     The minput_get_command () function returns information about
4547     the command $COMMAND of the input method specified by $LANGUAGE and
4548     $NAME.  An input method command is a pseudo key event to which one
4549     or more actual input key sequences are assigned.
4550
4551     There are two kinds of commands, global and local.  A global
4552     command has a global definition, and the description and the key
4553     assignment may be inherited by a local command.  Each input method
4554     defines a local command which has a local key assignment.  It may
4555     also declare a local command that inherits the definition of a
4556     global command of the same name.
4557
4558     If $LANGUAGE is #Mt and $NAME is #Mnil, this function returns
4559     information about a global command.  Otherwise information about a
4560     local command is returned.
4561
4562     If $COMMAND is #Mnil, information about all commands is returned.
4563
4564     The return value is a @e well-formed plist (#m17nPlist) of this
4565     format:
4566 @verbatim
4567   ((NAME DESCRIPTION STATUS [KEYSEQ ...]) ...)
4568 @endverbatim
4569     @c NAME is a symbol representing the command name.
4570
4571     @c DESCRIPTION is an M-text describing the command, or #Mnil if the
4572     command has no description.
4573
4574     @c STATUS is a symbol representing how the key assignment is decided.
4575     The value is #Mnil (the default key assignment), #Mcustomized (the
4576     key assignment is customized by per-user configuration file), or
4577     #Mconfigured (the key assignment is set by the call of
4578     minput_config_command ()).  For a local command only, it may also
4579     be #Minherited (the key assignment is inherited from the
4580     corresponding global command).
4581
4582     @c KEYSEQ is a plist of one or more symbols representing a key
4583     sequence assigned to the command.  If there's no KEYSEQ, the
4584     command is currently disabled (i.e. no key sequence can trigger
4585     actions of the command).
4586
4587     If $COMMAND is not #Mnil, the first element of the returned plist
4588     contains the information about $COMMAND.
4589
4590     @return
4591
4592     If the requested information was found, a pointer to a non-empty
4593     plist is returned.  As the plist is kept in the library, the
4594     caller must not modify nor free it.
4595
4596     Otherwise (the specified input method or the specified command
4597     does not exist), @c NULL is returned.  */
4598 /***ja
4599     @brief ÆþÎϥ᥽¥Ã¥É¤Î¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë.
4600
4601     ´Ø¿ô minput_get_command () ¤Ï¡¢$LANGUAGE ¤È $NAME ¤Ç»ØÄꤵ¤ì¤ëÆþÎÏ
4602     ¥á¥½¥Ã¥É¤Î¥³¥Þ¥ó¥É $COMMAND ¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£ÆþÎϥ᥽¥Ã¥É¤Î¥³¥Þ
4603     ¥ó¥É¤È¤Ï¡¢µ¿»÷¥­¡¼¥¤¥Ù¥ó¥È¤Ç¤¢¤ê¡¢£±¤Ä°Ê¾å¤Î¼ÂºÝ¤ÎÆþÎÏ¥­¡¼¥·¡¼¥¯¥¨
4604     ¥ó¥¹¤¬³ä¤êÅö¤Æ¤é¤ì¤ë¡£
4605
4606     ¥³¥Þ¥ó¥É¤Ë¤Ï¡¢¥°¥í¡¼¥Ð¥ë¤È¥í¡¼¥«¥ë¤Î£²¼ïÎब¤¢¤ë¡£¥°¥í¡¼¥Ð¥ë¤Ê¥³¥Þ¥ó¥É
4607     ¤Ï¥°¥í¡¼¥Ð¥ë¤ËÄêµÁ¤µ¤ì¡¢¥í¡¼¥«¥ë¤Ê¥³¥Þ¥ó¥É¤Ï¤½¤ÎÀâÌÀ¤È¥­¡¼³ä¤êÅö¤Æ
4608     ¤ò·Ñ¾µ¤¹¤ë¤³¤È¤¬¤Ç¤­¤ë¡£³ÆÆþÎϥ᥽¥Ã¥É¤Ï¥í¡¼¥«¥ë¤Ê¥­¡¼³äÅö¤ò»ý¤Ä¥í¡¼
4609     ¥«¥ë¤Ê¥³¥Þ¥ó¥É¤òÄêµÁ¤¹¤ë¡£¤Þ¤¿Æ±Ì¾¤Î¥°¥í¡¼¥Ð¥ë¤Ê¥³¥Þ¥ó¥É¤ÎÄêµÁ¤ò·Ñ
4610     ¾µ¤¹¤ë¥í¡¼¥«¥ë¤Ê¥³¥Þ¥ó¥É¤òÀë¸À¤¹¤ë¤³¤È¤â¤Ç¤­¤ë¡£
4611
4612     $LANGUAGE ¤¬ #Mt ¤Ç $NAME ¤¬ #Mnil ¤Î¾ì¹ç¤Ï¡¢¤³¤Î´Ø¿ô¤Ï¥°¥í¡¼¥Ð¥ë¥³
4613     ¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¥í¡¼¥«¥ë¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¤â
4614     ¤Î¤òÊÖ¤¹¡£
4615
4616     $COMMAND ¤¬ #Mnil ¤Î¾ì¹ç¤Ï¡¢¤¹¤Ù¤Æ¤Î¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£
4617
4618     Ìá¤êÃͤϰʲ¼¤Î·Á¼°¤Î @e well-formed plist (#m17nPlist) ¤Ç¤¢¤ë¡£
4619
4620 @verbatim
4621   ((NAME DESCRIPTION STATUS [KEYSEQ ...]) ...)
4622 @endverbatim
4623     @c NAME ¤Ï¥³¥Þ¥ó¥É̾¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
4624
4625     @c DESCRIPTION ¤Ï¥³¥Þ¥ó¥É¤òÀâÌÀ¤¹¤ë M-text ¤Ç¤¢¤ë¤«¡¢ÀâÌÀ¤¬Ìµ¤¤¾ì¹ç¤Ë
4626     ¤Ï #Mnil ¤Ç¤¢¤ë¡£
4627
4628     @c STATUS ¤Ï¥­¡¼³ä¤êÅö¤Æ¤¬¤É¤Î¤è¤¦¤ËÄê¤á¤é¤ì¤ë¤«¤ò¤¢¤é¤ï¤¹¥·¥ó¥Ü¥ë¤Ç¤¢
4629     ¤ê¡¢¤½¤ÎÃͤϠ#Mnil ¡Ê¥Ç¥Õ¥©¥ë¥È¤Î³ä¤êÅö¤Æ¡Ë, #Mcustomized ¡Ê¥æ¡¼¥¶
4630     Ëè¤ÎÀßÄê¥Õ¥¡¥¤¥ë¤Ë¤è¤Ã¤Æ¥«¥¹¥¿¥Þ¥¤¥º¤µ¤ì¤¿³ä¤êÅö¤Æ¡Ë, #Mconfigured
4631     ¡Êminput_config_command ()¤ò¸Æ¤Ö¤³¤È¤Ë¤è¤Ã¤ÆÀßÄꤵ¤ì¤ë³ä¤êÅö¤Æ¡Ë¤Î
4632     ¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£¥í¡¼¥«¥ë¥³¥Þ¥ó¥É¤Î¾ì¹ç¤Ë¤Ï¡¢#Minherited ¡ÊÂбþ¤¹¤ë
4633     ¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É¤«¤é¤Î·Ñ¾µ¤Ë¤è¤ë³ä¤êÅö¤Æ¡Ë¤Ç¤â¤è¤¤¡£
4634
4635     @c KEYSEQ ¤Ï£±¤Ä°Ê¾å¤Î¥·¥ó¥Ü¥ë¤«¤é¤Ê¤ë plist ¤Ç¤¢¤ê¡¢³Æ¥·¥ó¥Ü¥ë¤Ï¥³¥Þ
4636     ¥ó¥É¤Ë³ä¤êÅö¤Æ¤é¤ì¤Æ¤¤¤ë¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤òɽ¤¹¡£KEYSEQ ¤¬Ìµ¤¤¾ì¹ç¤Ï¡¢
4637     ¤½¤Î¥³¥Þ¥ó¥É¤Ï¸½¾õ¤Ç»ÈÍÑÉÔǽ¤Ç¤¢¤ë¡£¡Ê¤¹¤Ê¤ï¤Á¥³¥Þ¥ó¥É¤ÎÆ°ºî¤òµ¯
4638     Æ°¤Ç¤­¤ë¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤¬Ìµ¤¤¡£¡Ë
4639
4640     $COMMAND ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢ÊÖ¤µ¤ì¤ë plist ¤ÎºÇ½é¤ÎÍ×ÁǤϡ¢
4641     $COMMAND ¤Ë´Ø¤¹¤ë¾ðÊó¤ò´Þ¤à¡£
4642
4643     @return
4644
4645     µá¤á¤é¤ì¤¿¾ðÊ󤬸«¤Ä¤«¤ì¤Ð¡¢¶õ¤Ç¤Ê¤¤ plist ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¥ê¥¹
4646     ¥È¤Ï¥é¥¤¥Ö¥é¥ê¤¬´ÉÍý¤·¤Æ¤¤¤ë¤Î¤Ç¡¢¸Æ½Ð¦¤¬Êѹ¹¤·¤¿¤ê²òÊü¤·¤¿¤ê¤¹¤ë
4647     ¤³¤È¤Ï¤Ç¤­¤Ê¤¤¡£
4648
4649     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¤¹¤Ê¤ï¤Á»ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤ä¥³¥Þ¥ó¥É¤¬Â¸ºß¤·¤Ê¤±¤ì¤Ð
4650     @c NULL ¤òÊÖ¤¹¡£  */
4651
4652 #if EXAMPLE_CODE
4653 MText *
4654 get_im_command_description (MSymbol language, MSymbol name, MSymbol command)
4655 {
4656   /* Return a description of the command COMMAND of the input method */
4657   /* specified by LANGUAGE and NAME.  */
4658   MPlist *cmd = minput_get_command (langauge, name, command);
4659   MPlist *plist;
4660
4661   if (! cmds)
4662     return NULL;
4663   plist = mplist_value (cmds);  /* (NAME DESCRIPTION KEY-SEQ ...) */
4664   plist = mplist_next (plist);  /* (DESCRIPTION KEY-SEQ ...) */
4665   return  (mplist_key (plist) == Mtext
4666            ? (MText *) mplist_value (plist)
4667            : NULL);
4668 }
4669 #endif
4670
4671 MPlist *
4672 minput_get_command (MSymbol language, MSymbol name, MSymbol command)
4673 {
4674   MInputMethodInfo *im_info;
4675
4676   MINPUT__INIT ();
4677
4678   im_info = get_im_info (language, name, Mnil, Mcommand);
4679   if (! im_info
4680       || ! im_info->configured_cmds
4681       || MPLIST_TAIL_P (im_info->configured_cmds))
4682     return NULL;
4683   if (command == Mnil)
4684     return im_info->configured_cmds;
4685   return mplist__assq (im_info->configured_cmds, command);
4686 }
4687
4688 /*=*/
4689
4690 /***en
4691     @brief Configure the key sequence of an input method command.
4692
4693     The minput_config_command () function assigns a list of key
4694     sequences $KEYSEQLIST to the command $COMMAND of the input method
4695     specified by $LANGUAGE and $NAME.
4696
4697     If $KEYSEQLIST is a non-empty plist, it must be a list of key
4698     sequences, and each key sequence must be a plist of symbols.
4699
4700     If $KEYSEQLIST is an empty plist, the command becomes unusable.
4701
4702     If $KEYSEQLIST is NULL, the configuration of the command for the
4703     input method is canceled, and the default key sequences become
4704     effective.  In such case, if $COMMAND is #Mnil, configurations for
4705     all commands of the input method are canceled.
4706
4707     If $NAME is #Mnil, this function configures the key assignment of a
4708     global command, not that of a specific input method.
4709
4710     The configuration takes effect for input methods opened or
4711     re-opened later in the current session.  In order to make the
4712     configuration take effect for the future session, it must be saved
4713     in a per-user configuration file by the function
4714     minput_save_config ().
4715
4716     @return
4717
4718     If the operation was successful, this function returns 0,
4719     otherwise returns -1.  The operation fails in these cases:
4720     <ul>
4721     <li>$KEYSEQLIST is not in a valid form.
4722     <li>$COMMAND is not available for the input method.
4723     <li>$LANGUAGE and $NAME do not specify an existing input method.
4724     </ul>
4725
4726     @seealso
4727     minput_get_commands (), minput_save_config ().
4728 */
4729 /***ja
4730     @brief ÆþÎϥ᥽¥Ã¥É¤Î¥³¥Þ¥ó¥É¤Î¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤òÀßÄꤹ¤ë.
4731
4732     ´Ø¿ô minput_config_command () ¤Ï¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤Î¥ê¥¹¥È
4733     $KEYSEQLIST ¤ò¡¢$LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤ëÆþÎϥ᥽¥Ã¥É¤Î
4734     ¥³¥Þ¥ó¥É $COMMAND ¤Ë³ä¤êÅö¤Æ¤ë¡£
4735
4736     $KEYSEQLIST ¤¬¶õ¥ê¥¹¥È¤Ç¤Ê¤±¤ì¤Ð¡¢¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤Î¥ê¥¹¥È¤Ç¤¢¤ê¡¢
4737     ³Æ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤Ï¥·¥ó¥Ü¥ë¤Î plist ¤Ç¤¢¤ë¡£
4738
4739     $KEYSEQLIST ¤¬¶õ¤Î plist ¤Ê¤é¤Ð¡¢¥³¥Þ¥ó¥É¤Ï»ÈÍѤǤ­¤Ê¤¯¤Ê¤ë¡£
4740
4741     $KEYSEQLIST ¤¬ NULL ¤Ç¤¢¤ì¤Ð¡¢»ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤Î¥³¥Þ¥ó¥É¤ÎÀßÄê¤Ï
4742     ¥­¥ã¥ó¥»¥ë¤µ¤ì¡¢¥Ç¥Õ¥©¥ë¥È¤Î¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤¬Í­¸ú¤Ë¤Ê¤ë¡£¤³¤Î¾ì¹ç¡¢
4743     $COMMAND ¤¬ #Mnil ¤Ê¤é¤Ð»ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤ÎÁ´¤Æ¤Î¥³¥Þ¥ó¥É¤ÎÀßÄ꤬
4744     ¥­¥ã¥ó¥»¥ë¤µ¤ì¤ë¡£
4745
4746     $NAME ¤¬ #Mnil ¤Ê¤é¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¸Ä¡¹¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¤Ê¤¯¥°¥í¡¼¥Ð
4747     ¥ë¤Ê¥³¥Þ¥ó¥É¤Î¥­¡¼³ä¤êÅö¤Æ¤òÀßÄꤹ¤ë¡£
4748
4749     ¤³¤ì¤é¤ÎÀßÄê¤Ï¡¢¸½¹Ô¤Î¥»¥Ã¥·¥ç¥óÃæ¤ÇÆþÎϥ᥽¥Ã¥É¤¬¥ª¡¼¥×¥ó¡Ê¤Þ¤¿¤Ï
4750     ºÆ¥ª¡¼¥×¥ó¡Ë¤µ¤ì¤¿»þÅÀ¤ÇÍ­¸ú¤Ë¤Ê¤ë¡£¾­Íè¤Î¥»¥Ã¥·¥ç¥óÃæ¤Ç¤âÍ­¸ú¤Ë¤¹
4751     ¤ë¤¿¤á¤Ë¤Ï¡¢´Ø¿ô minput_save_config () ¤òÍѤ¤¤Æ¥æ¡¼¥¶Ëè¤ÎÀßÄê¥Õ¥¡¥¤
4752     ¥ë¤ËÊݸ¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
4753
4754     @return
4755
4756     ¤³¤Î´Ø¿ô¤Ï¡¢½èÍý¤¬À®¸ù¤¹¤ì¤Ð 0 ¤ò¡¢¼ºÇÔ¤¹¤ì¤Ð -1 ¤òÊÖ¤¹¡£¼ºÇԤȤϰʲ¼¤Î¾ì¹ç¤Ç¤¢¤ë¡£
4757     <ul>
4758     <li>$KEYSEQLIST ¤¬Í­¸ú¤Ê·Á¼°¤Ç¤Ê¤¤¡£
4759     <li>$COMMAND ¤¬»ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤ÇÍøÍѤǤ­¤Ê¤¤¡£
4760     <li>$LANGUAGE ¤È $NAME ¤Ç»ØÄꤵ¤ì¤ëÆþÎϥ᥽¥Ã¥É¤¬Â¸ºß¤·¤Ê¤¤¡£
4761     </ul>
4762
4763     @seealso
4764     minput_get_commands (), minput_save_config ().
4765 */
4766
4767 #if EXAMPLE_CODE
4768 /* Add "C-x u" to the "start" command of Unicode input method.  */
4769 {
4770   MSymbol start_command = msymbol ("start");
4771   MSymbol unicode = msymbol ("unicode");
4772   MPlist *cmd, *plist, *key_seq_list, *key_seq;
4773
4774   /* At first get the current key-sequence assignment.  */
4775   cmd = mplist_get_command (Mt, unicode, start_command);
4776   if (! cmd)
4777     {
4778       /* The input method does not have the command "start".  Here */
4779       /* should come some error handling code.  */
4780     }
4781   /* Now CMD == ((start DESCRIPTION KEY-SEQUENCE ...) ...).  Extract */
4782   /* the part (KEY-SEQUENCE ...).  */
4783   plist = mplist_next (mplist_next (mplist_value (cmd)));
4784   /* Copy it because we should not modify it directly.  */
4785   key_seq_list = mplist_copy (plist);
4786   m17n_object_unref (cmds);
4787   
4788   key_seq = mplist ();
4789   mplist_add (key_seq, Msymbol, msymbol ("C-x"));
4790   mplist_add (key_seq, Msymbo, msymbol ("u"));
4791   mplist_add (key_seq_list, Mplist, key_seq);
4792   m17n_object_unref (key_seq);
4793
4794   minput_config_command (Mt, unicode, start_command, key_seq_list);
4795   m17n_object_unref (key_seq_list);
4796 }
4797 #endif
4798
4799 int
4800 minput_config_command (MSymbol language, MSymbol name, MSymbol command,
4801                        MPlist *keyseqlist)
4802 {
4803   MInputMethodInfo *im_info, *config;
4804   MPlist *plist;
4805
4806   MINPUT__INIT ();
4807
4808   if (keyseqlist)
4809     {
4810       if (command == Mnil)
4811         MERROR (MERROR_IM, -1);
4812       MPLIST_DO (plist, keyseqlist)
4813         if (! MPLIST_PLIST_P (plist)
4814             || ! check_command_keyseq (plist))
4815           MERROR (MERROR_IM, -1);
4816     }
4817
4818   im_info = get_im_info (language, name, Mnil, Mcommand);
4819   if (! im_info)
4820     MERROR (MERROR_IM, -1);
4821   if (command != Mnil
4822       && (! im_info->cmds
4823           || ! mplist__assq (im_info->cmds, command)))
4824     MERROR (MERROR_IM, -1);
4825
4826   config = get_config_info (im_info);
4827   if (! config)
4828     {
4829       if (! im_config_list)
4830         im_config_list = mplist ();
4831       config = new_im_info (NULL, language, name, Mnil, im_config_list);
4832       config->cmds = mplist ();
4833       config->vars = mplist ();
4834     }
4835
4836   if (command == Mnil)
4837     {
4838       MInputMethodInfo *custom = get_custom_info (im_info);
4839
4840       mplist_set (config->cmds, Mnil, NULL);
4841       if (custom && custom->cmds)
4842         {
4843           MPLIST_DO (plist, custom->cmds)
4844             {
4845               command = MPLIST_SYMBOL (MPLIST_PLIST (plist));
4846               plist = mplist ();
4847               mplist_add (plist, Msymbol, command);
4848               mplist_push (config->cmds, Mplist, plist);
4849               M17N_OBJECT_UNREF (plist);
4850             }
4851         }
4852     }
4853   else
4854     {
4855       plist = mplist__assq (config->cmds, command);
4856       if (plist)
4857         {
4858           plist = MPLIST_PLIST (plist); /* (NAME [nil KEY-SEQUENCE ...])  */
4859           plist = MPLIST_NEXT (plist);  /* ([nil ...]) */
4860           if (! MPLIST_TAIL_P (plist))
4861             mplist_set (plist, Mnil, NULL); /* () */
4862         }
4863       else
4864         {
4865           plist = mplist ();
4866           mplist_add (config->cmds, Mplist, plist);
4867           M17N_OBJECT_UNREF (plist);
4868           plist = mplist_add (plist, Msymbol, command);
4869           plist = MPLIST_NEXT (plist);
4870         }
4871       if (keyseqlist)
4872         {
4873           MPlist *pl;
4874
4875           plist = mplist_add (plist, Msymbol, Mnil);
4876           MPLIST_DO (keyseqlist, keyseqlist)
4877             {
4878               pl = mplist_copy (MPLIST_VAL (keyseqlist));
4879               plist = mplist_add (plist, Mplist, pl);
4880               M17N_OBJECT_UNREF (pl);
4881             }
4882         }
4883     }
4884   config_all_commands (im_info);
4885   im_info->tick = time (NULL);
4886   return 0;
4887 }
4888
4889 /*=*/
4890
4891 /***en
4892     @brief Get information about input method variable(s).
4893
4894     The minput_get_variable () function returns information about
4895     the variable $VARIABLE of the input method specified by $LANGUAGE and $NAME.
4896     An input method variable controls behavior of an input method.
4897
4898     There are two kinds of variables, global and local.  A global
4899     variable has a global definition, and the description and the value
4900     may be inherited by a local variable.  Each input method defines a
4901     local variable which has local value.  It may also declare a
4902     local variable that inherits definition of a global variable of
4903     the same name.
4904
4905     If $LANGUAGE is #Mt and $NAME is #Mnil, information about a global
4906     variable is returned.  Otherwise information about a local variable
4907     is returned.
4908
4909     If $VARIABLE is #Mnil, information about all variables is
4910     returned.
4911
4912     The return value is a @e well-formed plist (#m17nPlist) of this
4913     format:
4914 @verbatim
4915   ((NAME DESCRIPTION STATUS VALUE [VALID-VALUE ...]) ...)
4916 @endverbatim
4917     @c NAME is a symbol representing the variable name.
4918
4919     @c DESCRIPTION is an M-text describing the variable, or #Mnil if the
4920     variable has no description.
4921
4922     @c STATUS is a symbol representing how the value is decided.  The
4923     value is #Mnil (the default value), #Mcustomized (the value is
4924     customized by per-user configuration file), or #Mconfigured (the
4925     value is set by the call of minput_config_variable ()).  For a
4926     local variable only, it may also be #Minherited (the value is
4927     inherited from the corresponding global variable).
4928
4929     @c VALUE is the initial value of the variable.  If the key of this
4930     element is #Mt, the variable has no initial value.  Otherwise, the
4931     key is #Minteger, #Msymbol, or #Mtext and the value is of the
4932     corresponding type.
4933
4934     @c VALID-VALUEs (if any) specify which values the variable can have.
4935     They have the same type (i.e. having the same key) as @c VALUE except
4936     for the case that VALUE is an integer.  In that case, @c VALID-VALUE
4937     may be a plist of two integers specifying the range of possible
4938     values.
4939
4940     If there no @c VALID-VALUE, the variable can have any value as long
4941     as the type is the same as @c VALUE.
4942
4943     If $VARIABLE is not #Mnil, the first element of the returned plist
4944     contains the information about $VARIABLE.
4945
4946     @return
4947
4948     If the requested information was found, a pointer to a non-empty
4949     plist is returned.  As the plist is kept in the library, the
4950     caller must not modify nor free it.
4951
4952     Otherwise (the specified input method or the specified variable
4953     does not exist), @c NULL is returned.  */
4954 /***ja
4955     @brief ÆþÎϥ᥽¥Ã¥É¤ÎÊÑ¿ô¤Ë´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë.
4956
4957     ´Ø¿ô minput_get_variable () ¤Ï¡¢$LANGUAGE ¤È $NAME ¤Ç»ØÄꤵ¤ì¤ëÆþÎÏ
4958     ¥á¥½¥Ã¥É¤ÎÊÑ¿ô $VARIABLE ¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£ÆþÎϥ᥽¥Ã¥É¤ÎÊÑ¿ô¤È¤Ï¡¢
4959     ÆþÎϥ᥽¥Ã¥É¤Î¿¶Éñ¤òÀ©¸æ¤¹¤ë¤â¤Î¤Ç¤¢¤ë¡£
4960
4961     ÊÑ¿ô¤Ë¤Ï¡¢¥°¥í¡¼¥Ð¥ë¤È¥í¡¼¥«¥ë¤Î£²¼ïÎब¤¢¤ë¡£¥°¥í¡¼¥Ð¥ë¤ÊÊÑ¿ô¤Ï¥°
4962     ¥í¡¼¥Ð¥ë¤ËÄêµÁ¤µ¤ì¡¢¥í¡¼¥«¥ë¤ÊÊÑ¿ô¤Ï¤½¤ÎÀâÌÀ¤ÈÃͤò·Ñ¾µ¤¹¤ë¤³¤È¤¬¤Ç
4963     ¤­¤ë¡£³ÆÆþÎϥ᥽¥Ã¥É¤Ï¥í¡¼¥«¥ë¤ÊÃͤò»ý¤Ä¥í¡¼¥«¥ë¤ÊÊÑ¿ô¤òÄêµÁ¤¹¤ë¡£
4964     ¤Þ¤¿Æ±Ì¾¤Î¥°¥í¡¼¥Ð¥ë¤ÊÊÑ¿ô¤ÎÄêµÁ¤ò·Ñ¾µ¤¹¤ë¥í¡¼¥«¥ë¤ÊÊÑ¿ô¤òÀë¸À¤¹¤ë
4965     ¤³¤È¤â¤Ç¤­¤ë¡£
4966
4967     $LANGUAGE ¤¬ #Mt ¤Ç $NAME ¤¬ #Mnil ¤Î¾ì¹ç¤Ï¡¢¤³¤Î´Ø¿ô¤Ï¥°¥í¡¼¥Ð¥ëÊÑ
4968     ¿ô¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¥í¡¼¥«¥ëÊÑ¿ô¤Ë´Ø¤¹¤ë¤â¤Î¤òÊÖ¤¹¡£
4969
4970     $VARIABLE ¤¬ #Mnil ¤Î¾ì¹ç¤Ï¡¢¤¹¤Ù¤Æ¤Î¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£
4971
4972     Ìá¤êÃͤϰʲ¼¤Î·Á¼°¤Î @e well-formed plist (#m17nPlist) ¤Ç¤¢¤ë¡£
4973 @verbatim
4974   ((NAME DESCRIPTION STATUS VALUE [VALID-VALUE ...]) ...)
4975 @endverbatim
4976
4977     @c NAME ¤ÏÊÑ¿ô¤Î̾Á°¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
4978
4979     @c DESCRIPTION ¤ÏÊÑ¿ô¤òÀâÌÀ¤¹¤ë M-text ¤Ç¤¢¤ë¤«¡¢ÀâÌÀ¤¬Ìµ¤¤¾ì¹ç¤Ë¤Ï
4980     #Mnil ¤Ç¤¢¤ë¡£
4981
4982     @c STATUS ¤ÏÃͤ¬¤É¤Î¤è¤¦¤ËÄê¤á¤é¤ì¤ë¤«¤ò¤¢¤é¤ï¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢
4983     @c STATUS ¤ÎÃͤϠ#Mnil ¡Ê¥Ç¥Õ¥©¥ë¥È¤ÎÃÍ¡Ë, #Mcustomized ¡Ê¥æ¡¼¥¶Ëè¤ÎÀß
4984     Äê¥Õ¥¡¥¤¥ë¤Ë¤è¤Ã¤Æ¥«¥¹¥¿¥Þ¥¤¥º¤µ¤ì¤¿ÃÍ¡Ë, #Mconfigured
4985     ¡Êminput_config_variable ()¤ò¸Æ¤Ö¤³¤È¤Ë¤è¤Ã¤ÆÀßÄꤵ¤ì¤ëÃ͡ˤΤ¤¤º¤ì
4986     ¤«¤Ç¤¢¤ë¡£¥í¡¼¥«¥ëÊÑ¿ô¤Î¾ì¹ç¤Ë¤Ï¡¢#Minherited ¡ÊÂбþ¤¹¤ë¥°¥í¡¼¥Ð¥ë
4987     ÊÑ¿ô¤«¤é·Ñ¾µ¤·¤¿Ã͡ˤǤâ¤è¤¤¡£
4988
4989     @c VALUE ¤ÏÊÑ¿ô¤Î½é´üÃͤǤ¢¤ë¡£¤³¤ÎÍ×ÁǤΥ­¡¼¤¬#Mt ¤Ç¤¢¤ì¤Ð½é´üÃͤò»ý
4990     ¤¿¤Ê¤¤¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¥­¡¼¤Ï #Minteger, #Msymbol, #Mtext ¤Î¤¤¤º¤ì
4991     ¤«¤Ç¤¢¤ê¡¢ÃͤϤ½¤ì¤¾¤ìÂбþ¤¹¤ë·¿¤Î¤â¤Î¤Ç¤¢¤ë¡£
4992
4993     @c VALID-VALUE ¤Ï¤â¤·¤¢¤ì¤Ð¡¢ÊÑ¿ô¤Î¼è¤êÆÀ¤ëÃͤò»ØÄꤹ¤ë¡£¤³¤ì¤Ï @c VALUE
4994     ¤ÈƱ¤¸·¿(¤¹¤Ê¤ï¤ÁƱ¤¸¥­¡¼¤ò»ý¤Ä) ¤Ç¤¢¤ë¤¬¡¢Îã³°¤È¤·¤Æ @c VALUE ¤¬
4995     integer ¤Î¾ì¹ç¤Ï @c VALID-VALUE ¤Ï²Äǽ¤ÊÃͤÎÈϰϤò¼¨¤¹Æó¤Ä¤ÎÀ°¿ô¤«¤é
4996     ¤Ê¤ë plist ¤È¤Ê¤ë¤³¤È¤¬¤Ç¤­¤ë¡£
4997
4998     @c VALID-VALUE ¤¬¤Ê¤±¤ì¤Ð¡¢ÊÑ¿ô¤Ï @c VALUE ¤ÈƱ¤¸·¿¤Ç¤¢¤ë¸Â¤ê¤¤¤«¤Ê¤ëÃͤâ
4999     ¤È¤ë¤³¤È¤¬¤Ç¤­¤ë¡£
5000
5001     $VARIABLE ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢ÊÖ¤µ¤ì¤ë plist ¤ÎºÇ½é¤ÎÍ×ÁǤÏ
5002     $VARIABLE ¤Ë´Ø¤¹¤ë¾ðÊó¤ò´Þ¤à¡£
5003
5004     @return
5005
5006     µá¤á¤é¤ì¤¿¾ðÊ󤬸«¤Ä¤«¤ì¤Ð¡¢¶õ¤Ç¤Ê¤¤ plist ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¥ê¥¹
5007     ¥È¤Ï¥é¥¤¥Ö¥é¥ê¤¬´ÉÍý¤·¤Æ¤¤¤ë¤Î¤Ç¡¢¸Æ½Ð¦¤¬Êѹ¹¤·¤¿¤ê²òÊü¤·¤¿¤ê¤¹¤ë
5008     ¤³¤È¤Ï¤Ç¤­¤Ê¤¤¡£
5009
5010     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¤¹¤Ê¤ï¤Á»ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤äÊÑ¿ô¤¬Â¸ºß¤·¤Ê¤±¤ì¤Ð
5011     @c NULL ¤òÊÖ¤¹¡£ */
5012
5013 MPlist *
5014 minput_get_variable (MSymbol language, MSymbol name, MSymbol variable)
5015 {
5016   MInputMethodInfo *im_info;
5017
5018   MINPUT__INIT ();
5019
5020   im_info = get_im_info (language, name, Mnil, Mvariable);
5021   if (! im_info || ! im_info->configured_vars)
5022     return NULL;
5023   if (variable == Mnil)
5024     return im_info->configured_vars;
5025   return mplist__assq (im_info->configured_vars, variable);
5026 }
5027
5028 /*=*/
5029
5030 /***en
5031     @brief Configure the value of an input method variable.
5032
5033     The minput_config_variable () function assigns $VALUE to the
5034     variable $VARIABLE of the input method specified by $LANGUAGE and
5035     $NAME.
5036
5037     If $VALUE is not NULL, it must be a plist of one element whose key
5038     is #Minteger, #Msymbol, or #Mtext, and the value is of the
5039     corresponding type.
5040
5041     If $VALUE is NULL, a configuration for the variable for the input
5042     method is canceled, and the variable is initialized to the default
5043     value.  In that case, if $VARIABLE is #Mnil, configurations for
5044     all variables of the input method are canceled.
5045
5046     If $NAME is #Mnil, this function configure the value of global
5047     variable, not that of a specific input method.
5048
5049     The configuration takes effect for input methods opened or
5050     re-opened later in the current session.  To make the configuration
5051     take effect for the future session, it must be saved in a per-user
5052     configuration file by the function minput_save_config ().
5053
5054     @return
5055
5056     If the operation was successful, this function returns 0,
5057     otherwise returns -1.  The operation fails in these cases:
5058     <ul>
5059     <li>$VALUE is not in a valid form, the type does not match the
5060     definition, or the value is our of range.
5061     <li>$VARIABLE is not available for the input method.
5062     <li>$LANGUAGE and $NAME do not specify an existing input method.  
5063     </ul>
5064
5065     @seealso
5066     minput_get_variable (), minput_save_config ().  */
5067 /***ja
5068     @brief ÆþÎϥ᥽¥Ã¥É¤ÎÊÑ¿ô¤ÎÃͤòÀßÄꤹ¤ë.
5069
5070     ´Ø¿ô minput_config_variable () ¤ÏÃÍ $VALUE ¤ò¡¢$LANGUAGE ¤È $NAME
5071     ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤ëÆþÎϥ᥽¥Ã¥É¤ÎÊÑ¿ô $VARIABLE ¤Ë³ä¤êÅö¤Æ¤ë¡£
5072
5073     $VALUE ¤¬ NULL¤Ç¤Ê¤±¤ì¤Ð¡¢£±Í×ÁǤΠplist ¤Ç¤¢¤ê¡¢¤½¤Î¥­¡¼¤Ï
5074     #Minteger, #Msymbol, #Mtext ¤Î¤¤¤º¤ì¤«¡¢ÃͤÏÂбþ¤¹¤ë·¿¤Î¤â¤Î¤Ç¤¢¤ë¡£
5075
5076     $VALUE ¤¬ NULL ¤Ç¤¢¤ì¤Ð¡¢»ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤ÎÊÑ¿ô¤ÎÀßÄê¤Ï¥­¥ã¥ó¥»¥ë
5077     ¤µ¤ì¡¢ÊÑ¿ô¤Ï¥Ç¥Õ¥©¥ë¥ÈÃͤ˽é´ü²½¤µ¤ì¤ë¡£¤³¤Î¾ì¹ç¡¢$VARIABLE ¤¬
5078     #Mnil ¤Ê¤é¤Ð»ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤ÎÁ´¤Æ¤ÎÊÑ¿ô¤ÎÀßÄ꤬¥­¥ã¥ó¥»¥ë¤µ¤ì¤ë¡£
5079
5080     $NAME ¤¬ #Mnil ¤Ê¤é¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¸Ä¡¹¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¤Ê¤¯¥°¥í¡¼¥Ð
5081     ¥ë¤ÊÊÑ¿ô¤ÎÃͤòÀßÄꤹ¤ë¡£
5082
5083     ¤³¤ì¤é¤ÎÀßÄê¤Ï¡¢¸½¹Ô¤Î¥»¥Ã¥·¥ç¥óÃæ¤ÇÆþÎϥ᥽¥Ã¥É¤¬¥ª¡¼¥×¥ó¡Ê¤Þ¤¿¤Ï
5084     ºÆ¥ª¡¼¥×¥ó¡Ë¤µ¤ì¤¿»þÅÀ¤ÇÍ­¸ú¤Ë¤Ê¤ë¡£¾­Íè¤Î¥»¥Ã¥·¥ç¥óÃæ¤Ç¤âÍ­¸ú¤Ë¤¹
5085     ¤ë¤¿¤á¤Ë¤Ï¡¢´Ø¿ô minput_save_config () ¤òÍѤ¤¤Æ¥æ¡¼¥¶Ëè¤ÎÀßÄê¥Õ¥¡¥¤
5086     ¥ë¤ËÊݸ¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
5087
5088     @return
5089
5090     ¤³¤Î´Ø¿ô¤Ï¡¢½èÍý¤¬À®¸ù¤¹¤ì¤Ð 0 ¤ò¡¢¼ºÇÔ¤¹¤ì¤Ð -1 ¤òÊÖ¤¹¡£¼ºÇԤȤϰʲ¼¤Î¾ì¹ç¤Ç¤¢¤ë¡£
5091     <ul>
5092     <li>$VALUE¤¬Í­¸ú¤Ê·Á¼°¤Ç¤Ê¤¤¡£·¿¤¬ÄêµÁ¤Ë¹ç¤ï¤Ê¤¤¡¢¤Þ¤¿¤ÏÃͤ¬Èϰϳ°¤Ç¤¢¤ë¡£
5093     <li>$VARIABLE ¤¬»ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤ÇÍøÍѤǤ­¤Ê¤¤¡£
5094     <li>$LANGUAGE ¤È $NAME ¤Ç»ØÄꤵ¤ì¤ëÆþÎϥ᥽¥Ã¥É¤¬Â¸ºß¤·¤Ê¤¤¡£
5095     </ul>
5096
5097     @seealso
5098     minput_get_commands (), minput_save_config ().
5099 */
5100 int
5101 minput_config_variable (MSymbol language, MSymbol name, MSymbol variable,
5102                         MPlist *value)
5103 {
5104   MInputMethodInfo *im_info, *config;
5105   MPlist *plist;
5106
5107   MINPUT__INIT ();
5108
5109   im_info = get_im_info (language, name, Mnil, Mvariable);
5110   if (! im_info)
5111     MERROR (MERROR_IM, -1);
5112   if (variable == Mnil)
5113     {
5114       if (value)
5115         MERROR (MERROR_IM, -1);
5116     }
5117   else if (! im_info->vars
5118            || ! (plist = mplist__assq (im_info->configured_vars, variable)))
5119     MERROR (MERROR_IM, -1);
5120
5121   if (variable != Mnil && value)
5122     {
5123       plist = MPLIST_PLIST (plist);
5124       plist = MPLIST_NEXT (plist); /* (DESC STATUS VALUE VALIDS ...) */
5125       plist = MPLIST_NEXT (plist); /* (STATUS VALUE VALIDS ...) */
5126       plist = MPLIST_NEXT (plist); /* (VALUE VALIDS ...) */
5127       if (MPLIST_KEY (plist) != Mt
5128           && ! check_variable_value (value, plist))
5129         MERROR (MERROR_IM, -1);
5130     }
5131
5132   config = get_config_info (im_info);
5133   if (! config)
5134     {
5135       if (! im_config_list)
5136         im_config_list = mplist ();
5137       config = new_im_info (NULL, language, name, Mnil, im_config_list);
5138       config->cmds = mplist ();
5139       config->vars = mplist ();
5140     }
5141
5142   if (variable == Mnil)
5143     {
5144       MInputMethodInfo *custom = get_custom_info (im_info);
5145
5146       mplist_set (config->vars, Mnil, NULL);
5147       if (custom && custom->cmds)
5148         {
5149           MPLIST_DO (plist, custom->vars)
5150             {
5151               variable = MPLIST_SYMBOL (MPLIST_PLIST (plist));
5152               plist = mplist ();
5153               mplist_add (plist, Msymbol, variable);
5154               mplist_push (config->vars, Mplist, plist);
5155               M17N_OBJECT_UNREF (plist);
5156             }
5157         }
5158     }
5159   else
5160     {
5161       plist = mplist__assq (config->vars, variable);
5162       if (plist)
5163         {
5164           plist = MPLIST_PLIST (plist); /* (NAME nil VALUE) */
5165           plist = MPLIST_NEXT (plist);  /* ([nil VALUE]) */
5166           if (! MPLIST_TAIL_P (plist))
5167             mplist_set (plist, Mnil ,NULL); /* () */
5168         }
5169       else
5170         {
5171           plist = mplist ();
5172           mplist_add (config->vars, Mplist, plist);
5173           M17N_OBJECT_UNREF (plist);
5174           plist = mplist_add (plist, Msymbol, variable);
5175           plist = MPLIST_NEXT (plist);
5176         }
5177       if (value)
5178         {
5179           plist = mplist_add (plist, Msymbol, Mnil);
5180           mplist_add (plist, MPLIST_KEY (value), MPLIST_VAL (value));
5181         }
5182     }
5183   config_all_variables (im_info);
5184   im_info->tick = time (NULL);
5185   return 0;
5186 }
5187
5188 /*=*/
5189
5190 /***en
5191     @brief Get the name of per-user configuration file.
5192     
5193     The minput_config_file () function returns the absolute path name
5194     of per-user configuration file into which minput_save_config ()
5195     save configurations.  It is usually @c "config.mic" under the
5196     directory @c ".m17n.d" of user's home directory.  It is not assured
5197     that the file of the returned name exists nor is
5198     readable/writable.  If minput_save_config () fails and returns -1,
5199     an application program might check the file, make it
5200     writable (if possible), and try minput_save_config () again.
5201
5202     @return
5203
5204     This function returns a string.  As the string is kept in the
5205     library, the caller must not modify nor free it.
5206
5207     @seealso
5208     minput_save_config ()
5209 */
5210 /***ja
5211     @brief ¥æ¡¼¥¶Ëè¤ÎÀßÄê¥Õ¥¡¥¤¥ë¤Î̾Á°¤òÆÀ¤ë.
5212     
5213     ´Ø¿ô minput_config_file () ¤Ï¡¢´Ø¿ô minput_save_config () ¤¬ÀßÄê¤ò
5214     Êݸ¤¹¤ë¥æ¡¼¥¶Ëè¤ÎÀßÄê¥Õ¥¡¥¤¥ë¤Ø¤ÎÀäÂХѥ¹Ì¾¤òÊÖ¤¹¡£Ä̾ï¤Ï¡¢¥æ¡¼¥¶
5215     ¤Î¥Û¡¼¥à¥Ç¥£¥ì¥¯¥È¥ê¤Î²¼¤Î¥Ç¥£¥ì¥¯¥È¥ê @c ".m17n.d" ¤Ë¤¢¤ë@c
5216     "config.mic" ¤È¤Ê¤ë¡£ÊÖ¤µ¤ì¤¿Ì¾Á°¤Î¥Õ¥¡¥¤¥ë¤¬Â¸ºß¤¹¤ë¤«¡¢Æɤ߽ñ¤­¤Ç
5217     ¤­¤ë¤«¤ÏÊݾڤµ¤ì¤Ê¤¤¡£´Ø¿ôminput_save_config () ¤¬¼ºÇÔ¤·¤Æ -1 ¤òÊÖ
5218     ¤·¤¿¾ì¹ç¤Ë¤Ï¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ï¥Õ¥¡¥¤¥ë¤Î¸ºß¤ò³Îǧ¤·¡¢
5219     ¡Ê¤Ç¤­¤ì¤Ð¡Ë½ñ¤­¹þ¤ß²Äǽ¤Ë¤·ºÆÅÙminput_save_config () ¤ò»î¤¹¤³¤È¤¬
5220     ¤Ç¤­¤ë¡£
5221
5222     @return
5223
5224     ¤³¤Î´Ø¿ô¤Ïʸ»úÎó¤òÊÖ¤¹¡£Ê¸»úÎó¤Ï¥é¥¤¥Ö¥é¥ê¤¬´ÉÍý¤·¤Æ¤¤¤ë¤Î¤Ç¡¢¸Æ½Ð
5225     Â¦¤¬½¤Àµ¤·¤¿¤ê²òÊü¤·¤¿¤ê¤¹¤ë¤³¤È¤Ï¤Ç¤­¤Ê¤¤¡£
5226
5227     @seealso
5228     minput_save_config ()
5229 */
5230
5231 char *
5232 minput_config_file ()
5233 {
5234   MINPUT__INIT ();
5235
5236   return mdatabase__file (im_custom_mdb);
5237 }
5238
5239 /*=*/
5240
5241 /***en
5242     @brief Save configurations in per-user configuration file.
5243
5244     The minput_save_config () functions saves the configurations done
5245     so far in the current session into the per-user configuration
5246     file.
5247
5248     @return
5249
5250     If the operation was successful, 1 is returned.  If the per-user
5251     configuration file is currently locked, 0 is returned.  In that
5252     case, the caller may wait for a while and try again.  If the
5253     configuration file is not writable, -1 is returned.  In that case,
5254     the caller may check the name of the file by calling
5255     minput_config_file (), make it writable if possible, and try
5256     again.
5257
5258     @seealso
5259     minput_config_file ()  */
5260 /***ja
5261     @brief ÀßÄê¤ò¥æ¡¼¥¶Ëè¤ÎÀßÄê¥Õ¥¡¥¤¥ë¤ËÊݸ¤¹¤ë.
5262
5263     ´Ø¿ô minput_save_config () ¤Ï¸½¹Ô¤Î¥»¥Ã¥·¥ç¥ó¤Ç¤³¤ì¤Þ¤Ç¤Ë¹Ô¤Ã¤¿ÀßÄê
5264     ¤ò¥æ¡¼¥¶Ëè¤ÎÀßÄê¥Õ¥¡¥¤¥ë¤ËÊݸ¤¹¤ë¡£
5265
5266     @return
5267
5268     À®¸ù¤¹¤ì¤Ð 1 ¤òÊÖ¤¹¡£¥æ¡¼¥¶Ëè¤ÎÀßÄê¥Õ¥¡¥¤¥ë¤¬¥í¥Ã¥¯¤µ¤ì¤Æ¤¤¤ì¤Ð 0
5269     ¤òÊÖ¤¹¡£¤³¤Î¾ì¹ç¡¢¸Æ½Ð¦¤Ï¤·¤Ð¤é¤¯ÂԤäƺƻî¹Ô¤Ç¤­¤ë¡£ÀßÄê¥Õ¥¡¥¤¥ë
5270     ¤¬½ñ¤­¹þ¤ßÉԲĤξì¹ç¡¢-1 ¤òÊÖ¤¹¡£¤³¤Î¾ì¹ç¡¢minput_config_file () ¤ò
5271     ¸Æ¤ó¤Ç¥Õ¥¡¥¤¥ë̾¤ò¥Á¥§¥Ã¥¯¤·¡¢¤Ç¤­¤ì¤Ð½ñ¤­¹þ¤ß²Äǽ¤Ë¤·¡¢ºÆ»î¹Ô¤Ç¤­
5272     ¤ë¡£
5273
5274     @seealso
5275     minput_config_file ()  */
5276
5277 int
5278 minput_save_config (void)
5279 {
5280   MPlist *data, *tail, *plist, *p, *elt;
5281   int ret;
5282
5283   MINPUT__INIT ();
5284   ret = mdatabase__lock (im_custom_mdb);
5285   if (ret <= 0)
5286     return ret;
5287   if (! im_config_list)
5288     return 1;
5289   update_custom_info ();
5290   if (! im_custom_list)
5291     im_custom_list = mplist ();
5292   data = tail = mplist ();
5293
5294   MPLIST_DO (plist, im_config_list)
5295     {
5296       MPlist *pl = MPLIST_PLIST (plist);
5297       MSymbol language, name, extra, command, variable;
5298       MInputMethodInfo *custom, *config;
5299
5300       language = MPLIST_SYMBOL (pl);
5301       pl = MPLIST_NEXT (pl);
5302       name = MPLIST_SYMBOL (pl);
5303       pl = MPLIST_NEXT (pl);
5304       extra = MPLIST_SYMBOL (pl);
5305       pl = MPLIST_NEXT (pl);
5306       config = MPLIST_VAL (pl);
5307       custom = get_custom_info (config);
5308       if (! custom)
5309         custom = new_im_info (NULL, language, name, extra, im_custom_list);
5310       if (config->cmds)
5311         MPLIST_DO (pl, config->cmds)
5312           {
5313             elt = MPLIST_PLIST (pl);
5314             command = MPLIST_SYMBOL (elt);
5315             if (custom->cmds)
5316               p = mplist__assq (custom->cmds, command);
5317             else
5318               custom->cmds = mplist (), p = NULL;
5319             elt = MPLIST_NEXT (elt);
5320             if (MPLIST_TAIL_P (elt))
5321               {
5322                 if (p)
5323                   mplist__pop_unref (p);
5324               }
5325             else
5326               {
5327                 elt = MPLIST_NEXT (elt);
5328                 if (p)
5329                   {
5330                     p = MPLIST_NEXT (MPLIST_NEXT (MPLIST_PLIST (p)));
5331                     mplist_set (p, Mnil, NULL);
5332                     mplist__conc (p, elt);
5333                   }
5334                 else
5335                   {
5336                     p = MPLIST_PLIST (pl);
5337                     mplist_add (custom->cmds, Mplist, p);
5338                   }
5339               }
5340           }
5341       if (config->vars)
5342         MPLIST_DO (pl, config->vars)
5343           {
5344             elt = MPLIST_PLIST (pl);
5345             variable = MPLIST_SYMBOL (elt);
5346             if (custom->vars)
5347               p = mplist__assq (custom->vars, variable);
5348             else
5349               custom->vars = mplist (), p = NULL;
5350             elt = MPLIST_NEXT (elt);
5351             if (MPLIST_TAIL_P (elt))
5352               {
5353                 if (p)
5354                   mplist__pop_unref (p);
5355               }
5356             else
5357               {
5358                 elt = MPLIST_NEXT (elt);
5359                 if (p)
5360                   {
5361                     p = MPLIST_NEXT (MPLIST_NEXT (MPLIST_PLIST (p)));
5362                     mplist_set (p, Mnil, NULL);
5363                     mplist__conc (p, elt);
5364                   }
5365                 else
5366                   {
5367                     p = MPLIST_PLIST (pl);
5368                     mplist_add (custom->vars, Mplist, p);
5369                   }
5370               }
5371           }
5372     }
5373   M17N_OBJECT_UNREF (im_config_list);
5374
5375   MPLIST_DO (plist, im_custom_list)
5376     {
5377       MPlist *pl = MPLIST_PLIST (plist);
5378       MSymbol language, name, extra;
5379       MInputMethodInfo *custom, *im_info;
5380
5381       language = MPLIST_SYMBOL (pl);
5382       pl  = MPLIST_NEXT (pl);
5383       name = MPLIST_SYMBOL (pl);
5384       pl = MPLIST_NEXT (pl);
5385       extra = MPLIST_SYMBOL (pl);
5386       pl = MPLIST_NEXT (pl);
5387       custom = MPLIST_VAL (pl);
5388       im_info = lookup_im_info (im_info_list, language, name, extra);
5389       if (im_info)
5390         {
5391           if (im_info->cmds)
5392             config_all_commands (im_info);
5393           if (im_info->vars)
5394             config_all_variables (im_info);
5395         }
5396       
5397       elt = mplist ();
5398       tail = mplist_add (tail, Mplist, elt);
5399       M17N_OBJECT_UNREF (elt);
5400       pl = mplist ();
5401       elt = mplist_add (elt, Mplist, pl);
5402       M17N_OBJECT_UNREF (pl);
5403       pl = mplist_add (pl, Msymbol, Minput_method);
5404       pl = mplist_add (pl, Msymbol, language);
5405       pl = mplist_add (pl, Msymbol, name);
5406       if (extra != Mnil)
5407         pl = mplist_add (pl, Msymbol, extra);
5408       if (custom->cmds && ! MPLIST_TAIL_P (custom->cmds))
5409         {
5410           pl = mplist ();
5411           elt = mplist_add (elt, Mplist, pl);
5412           M17N_OBJECT_UNREF (pl);
5413           pl = mplist_add (pl, Msymbol, Mcommand);
5414           MPLIST_DO (p, custom->cmds)
5415             pl = mplist_add (pl, Mplist, MPLIST_PLIST (p));
5416         }
5417       if (custom->vars && ! MPLIST_TAIL_P (custom->vars))
5418         {
5419           pl = mplist ();
5420           elt = mplist_add (elt, Mplist, pl);
5421           M17N_OBJECT_UNREF (pl);
5422           pl = mplist_add (pl, Msymbol, Mvariable);
5423           MPLIST_DO (p, custom->vars)
5424             pl = mplist_add (pl, Mplist, MPLIST_PLIST (p));
5425         }
5426     }
5427
5428   mplist_push (data, Mstring, ";; -*- mode:lisp; coding:utf-8 -*-");
5429   ret = mdatabase__save (im_custom_mdb, data);
5430   mdatabase__unlock (im_custom_mdb);
5431   M17N_OBJECT_UNREF (data);
5432   return (ret < 0 ? -1 : 1);
5433 }
5434
5435 /*=*/
5436
5437 /***en
5438     @name Obsolete functions
5439 */
5440 /***ja
5441     @name Obsolete ¤Ê´Ø¿ô
5442 */
5443 /*** @{ */
5444
5445 /*=*/
5446 /***en
5447     @brief Get a list of variables of an input method (obsolete).
5448
5449     This function is obsolete.  Use minput_get_variable () instead.
5450
5451     The minput_get_variables () function returns a plist (#MPlist) of
5452     variables used to control the behavior of the input method
5453     specified by $LANGUAGE and $NAME.  The plist is @e well-formed
5454     (#m17nPlist) of the following format:
5455
5456 @verbatim
5457     (VARNAME (DOC-MTEXT DEFAULT-VALUE [ VALUE ... ] )
5458      VARNAME (DOC-MTEXT DEFAULT-VALUE [ VALUE ... ] )
5459      ...)
5460 @endverbatim
5461
5462     @c VARNAME is a symbol representing the variable name.
5463
5464     @c DOC-MTEXT is an M-text describing the variable.
5465
5466     @c DEFAULT-VALUE is the default value of the variable.  It is a
5467     symbol, integer, or M-text.
5468
5469     @c VALUEs (if any) specifies the possible values of the variable.
5470     If @c DEFAULT-VALUE is an integer, @c VALUE may be a plist (@c FROM
5471     @c TO), where @c FROM and @c TO specifies a range of possible
5472     values.
5473
5474     For instance, suppose an input method has the variables:
5475
5476     @li name:intvar, description:"value is an integer",
5477          initial value:0, value-range:0..3,10,20
5478
5479     @li name:symvar, description:"value is a symbol",
5480          initial value:nil, value-range:a, b, c, nil
5481
5482     @li name:txtvar, description:"value is an M-text",
5483          initial value:empty text, no value-range (i.e. any text)
5484
5485     Then, the returned plist is as follows.
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     If the input method uses any variables, a pointer to #MPlist is
5495     returned.  As the plist is kept in the library, the caller must not
5496     modify nor free it.  If the input method does not use any
5497     variable, @c NULL is returned.  */
5498 /***ja
5499     @brief ÆþÎϥ᥽¥Ã¥É¤ÎÊÑ¿ô¥ê¥¹¥È¤òÆÀ¤ë.
5500
5501     ´Ø¿ô minput_get_variables () ¤Ï¡¢$LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ»ØÄꤵ
5502     ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤Î¿¶¤ëÉñ¤¤¤òÀ©¸æ¤¹¤ëÊÑ¿ô¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È
5503     (#MPlist) ¤òÊÖ¤¹¡£¤³¤Î¥ê¥¹¥È¤Ï @e well-formed ¤Ç¤¢¤ê(#m17nPlist) °Ê
5504     ²¼¤Î·Á¼°¤Ç¤¢¤ë¡£
5505
5506 @verbatim
5507     (VARNAME (DOC-MTEXT DEFAULT-VALUE [ VALUE ... ] )
5508      VARNAME (DOC-MTEXT DEFAULT-VALUE [ VALUE ... ] )
5509      ...)
5510 @endverbatim
5511
5512     @c VARNAME ¤ÏÊÑ¿ô¤Î̾Á°¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
5513
5514     @c DOC-MTEXT ¤ÏÊÑ¿ô¤òÀâÌÀ¤¹¤ë M-text ¤Ç¤¢¤ë¡£
5515
5516     @c DEFAULT-VALUE ¤ÏÊÑ¿ô¤Î¥Ç¥Õ¥©¥ë¥ÈÃͤǤ¢¤ê¡¢¥·¥ó¥Ü¥ë¡¢À°¿ô¤â¤·¤¯¤Ï
5517     M-text ¤Ç¤¢¤ë¡£
5518
5519     @c VALUE ¤Ï¡¢¤â¤·»ØÄꤵ¤ì¤Æ¤¤¤ì¤ÐÊÑ¿ô¤Î¼è¤êÆÀ¤ëÃͤò¼¨¤¹¡£¤â¤·
5520     @c DEFAULT-VALUE ¤¬À°¿ô¤Ê¤é¡¢ @c VALUE ¤Ï (@c FROM @c TO) ¤È¤¤¤¦·Á
5521     ¤Î¥ê¥¹¥È¤Ç¤âÎɤ¤¡£¤³¤Î¾ì¹ç @c FROM ¤È @c TO ¤Ï²Äǽ¤ÊÃͤÎÈϰϤò¼¨¤¹¡£
5522
5523     Îã¤È¤·¤Æ¡¢¤¢¤ëÆþÎϥ᥽¥Ã¥É¤¬¼¡¤Î¤è¤¦¤ÊÊÑ¿ô¤ò»ý¤Ä¾ì¹ç¤ò¹Í¤¨¤è¤¦¡£
5524
5525     @li name:intvar, ÀâÌÀ:"value is an integer",
5526         ½é´üÃÍ:0, ÃͤÎÈÏ°Ï:0..3,10,20
5527
5528     @li name:symvar, ÀâÌÀ:"value is a symbol",
5529          ½é´üÃÍ:nil, ÃͤÎÈÏ°Ï:a, b, c, nil
5530
5531     @li name:txtvar, ÀâÌÀ:"value is an M-text",
5532         ½é´üÃÍ:empty text, ÃͤÎÈϰϤʤ·(¤É¤ó¤Ê M-text ¤Ç¤â²Ä)
5533
5534     ¤³¤Î¾ì¹ç¡¢ÊÖ¤µ¤ì¤ë¥ê¥¹¥È¤Ï°Ê²¼¤Î¤è¤¦¤Ë¤Ê¤ë¡£
5535
5536 @verbatim
5537     (intvar ("value is an integer" 0 (0 3) 10 20)
5538      symvar ("value is a symbol" nil a b c nil)
5539      txtvar ("value is an M-text" ""))
5540 @endverbatim
5541
5542     @return 
5543     ÆþÎϥ᥽¥Ã¥É¤¬²¿¤é¤«¤ÎÊÑ¿ô¤ò»ÈÍѤ·¤Æ¤¤¤ì¤Ð #MPlist ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
5544     ÊÖ¤µ¤ì¤ë¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ï¥é¥¤¥Ö¥é¥ê¤Ë¤è¤Ã¤Æ´ÉÍý¤µ¤ì¤Æ¤ª¤ê¡¢¸Æ¤Ó½Ð¤·Â¦¤ÇÊѹ¹¤·¤¿¤ê²òÊü¤·¤¿¤ê¤·¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
5545     ÆþÎϥ᥽¥Ã¥É¤¬ÊÑ¿ô¤ò°ìÀÚ»ÈÍѤ·¤Æ¤Ê¤±¤ì¤Ð¡¢@c NULL ¤òÊÖ¤¹¡£  */
5546
5547 MPlist *
5548 minput_get_variables (MSymbol language, MSymbol name)
5549 {
5550   MInputMethodInfo *im_info;
5551   MPlist *vars;
5552
5553   MINPUT__INIT ();
5554
5555   im_info = get_im_info (language, name, Mnil, Mvariable);
5556   if (! im_info || ! im_info->configured_vars)
5557     return NULL;
5558
5559   M17N_OBJECT_UNREF (im_info->bc_vars);
5560   im_info->bc_vars = mplist ();
5561   MPLIST_DO (vars, im_info->configured_vars)
5562     {
5563       MPlist *plist = MPLIST_PLIST (vars);
5564       MPlist *elt = mplist ();
5565
5566       mplist_push (im_info->bc_vars, Mplist, elt);
5567       mplist_add (elt, Msymbol, MPLIST_SYMBOL (plist));
5568       elt = MPLIST_NEXT (elt);
5569       mplist_set (elt, Mplist, mplist_copy (MPLIST_NEXT (plist)));
5570       M17N_OBJECT_UNREF (elt);
5571     }
5572   return im_info->bc_vars;
5573 }
5574
5575 /*=*/
5576
5577 /***en
5578     @brief Set the initial value of an input method variable.
5579
5580     The minput_set_variable () function sets the initial value of
5581     input method variable $VARIABLE to $VALUE for the input method
5582     specified by $LANGUAGE and $NAME.
5583
5584     By default, the initial value is 0.
5585
5586     This setting gets effective in a newly opened input method.
5587
5588     @return
5589     If the operation was successful, 0 is returned.  Otherwise -1 is
5590     returned, and #merror_code is set to #MERROR_IM.  */
5591 /***ja
5592     @brief ÆþÎϥ᥽¥Ã¥ÉÊÑ¿ô¤Î½é´üÃͤòÀßÄꤹ¤ë.
5593
5594     ´Ø¿ô minput_set_variable () ¤Ï¡¢$LANGUAGE ¤È $NAME 
5595     ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ÎÆþÎϥ᥽¥Ã¥ÉÊÑ¿ô $VARIABLE
5596     ¤Î½é´üÃͤò¡¢ $VALUE ¤ËÀßÄꤹ¤ë¡£
5597
5598     ¥Ç¥Õ¥©¥ë¥È¤Î½é´üÃͤϠ0 ¤Ç¤¢¤ë¡£
5599
5600     ¤³¤ÎÀßÄê¤Ï¡¢¿·¤·¤¯¥ª¡¼¥×¥ó¤µ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤«¤éÍ­¸ú¤È¤Ê¤ë¡£
5601
5602     @return
5603     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤·¡¢
5604     #merror_code ¤ò #MERROR_IM ¤ËÀßÄꤹ¤ë¡£  */
5605
5606 int
5607 minput_set_variable (MSymbol language, MSymbol name,
5608                      MSymbol variable, void *value)
5609 {
5610   MPlist *plist, *pl;
5611   MInputMethodInfo *im_info;
5612   int ret;
5613
5614   MINPUT__INIT ();
5615
5616   if (variable == Mnil)
5617     MERROR (MERROR_IM, -1);
5618   plist = minput_get_variable (language, name, variable);
5619   plist = MPLIST_PLIST (plist);
5620   plist = MPLIST_NEXT (plist);
5621   pl = mplist ();
5622   mplist_add (pl, MPLIST_KEY (plist), value);
5623   ret = minput_config_variable (language, name, variable, pl);
5624   M17N_OBJECT_UNREF (pl);
5625   if (ret == 0)
5626     {
5627       im_info = get_im_info (language, name, Mnil, Mvariable);
5628       im_info->tick = 0;
5629     }
5630   return ret;
5631 }
5632
5633 /*=*/
5634
5635 /***en
5636     @brief Get information about input method commands.
5637
5638     The minput_get_commands () function returns information about
5639     input method commands of the input method specified by $LANGUAGE
5640     and $NAME.  An input method command is a pseudo key event to which
5641     one or more actual input key sequences are assigned.
5642
5643     There are two kinds of commands, global and local.  Global
5644     commands are used by multiple input methods for the same purpose,
5645     and have global key assignments.  Local commands are used only by
5646     a specific input method, and have only local key assignments.
5647
5648     Each input method may locally change key assignments for global
5649     commands.  The global key assignment for a global command is
5650     effective only when the current input method does not have local
5651     key assignments for that command.
5652
5653     If $NAME is #Mnil, information about global commands is returned.
5654     In this case $LANGUAGE is ignored.
5655
5656     If $NAME is not #Mnil, information about those commands that have
5657     local key assignments in the input method specified by $LANGUAGE
5658     and $NAME is returned.
5659
5660     @return
5661     If no input method commands are found, this function returns @c NULL.
5662
5663     Otherwise, a pointer to a plist is returned.  The key of each
5664     element in the plist is a symbol representing a command, and the
5665     value is a plist of the form COMMAND-INFO described below.
5666
5667     The first element of COMMAND-INFO has the key #Mtext, and the
5668     value is an M-text describing the command.
5669
5670     If there are no more elements, that means no key sequences are
5671     assigned to the command.  Otherwise, each of the remaining
5672     elements has the key #Mplist, and the value is a plist whose keys are
5673     #Msymbol and values are symbols representing input keys, which are
5674     currently assigned to the command.
5675
5676     As the returned plist is kept in the library, the caller must not
5677     modify nor free it.  */
5678 /***ja
5679     @brief ÆþÎϥ᥽¥Ã¥É¤Î¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë.
5680
5681     ´Ø¿ô minput_get_commands () ¤Ï¡¢ $LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ»ØÄꤵ
5682     ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ÎÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£ÆþÎϥ᥽¥Ã
5683     ¥É¥³¥Þ¥ó¥É¤È¤Ï¡¢µ¿»÷¥­¡¼¥¤¥Ù¥ó¥È¤Ç¤¢¤ê¡¢¤½¤ì¤¾¤ì¤Ë£±¤Ä°Ê¾å¤Î¼ÂºÝ¤Î
5684     ÆþÎÏ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤¬³ä¤êÅö¤Æ¤é¤ì¤Æ¤¤¤ë¤â¤Î¤ò»Ø¤¹¡£
5685
5686     ¥³¥Þ¥ó¥É¤Ë¤Ï¥°¥í¡¼¥Ð¥ë¤È¥í¡¼¥«¥ë¤Î£²¼ïÎब¤¢¤ë¡£¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É
5687     ¤ÏÊ£¿ô¤ÎÆþÎϥ᥽¥Ã¥É¤Ë¤ª¤¤¤Æ¡¢Æ±¤¸ÌÜŪ¤Ç¡¢¥°¥í¡¼¥Ð¥ë¤Ê¥­¡¼³ä¤êÅö¤Æ
5688     ¤ÇÍѤ¤¤é¤ì¤ë¡£¥í¡¼¥«¥ë¥³¥Þ¥ó¥É¤ÏÆÃÄê¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Î¤ß¡¢¥í¡¼¥«¥ë
5689     ¤Ê¥­¡¼³äÅö¤Ç»ÈÍѤµ¤ì¤ë¡£
5690
5691     ¸Ä¡¹¤ÎÆþÎϥ᥽¥Ã¥É¤Ï¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É¤Î¥­¡¼³äÅö¤òÊѹ¹¤¹¤ë¤³¤È¤â¤Ç
5692     ¤­¤ë¡£¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥ÉÍѤΥ°¥í¡¼¥Ð¥ë¥­¡¼³ä¤êÅö¤Æ¤Ï¡¢»ÈÍѤ¹¤ëÆþÎÏ
5693     ¥á¥½¥Ã¥É¤Ë¤ª¤¤¤Æ¤½¤Î¥³¥Þ¥ó¥ÉÍÑ¤Î¥í¡¼¥«¥ë¤Ê¥­¡¼³äÅö¤¬Â¸ºß¤·¤Ê¤¤¾ì¹ç
5694     ¤Ë¤Î¤ßÍ­¸ú¤Ç¤¢¤ë¡£
5695
5696     $NAME ¤¬ #Mnil ¤Ç¤¢¤ì¤Ð¡¢¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£¤³¤Î
5697     ¾ì¹ç¡¢$LANGUAGE ¤Ï̵»ë¤µ¤ì¤ë¡£
5698
5699     $NAME ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢$LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤ëÆþ
5700     Îϥ᥽¥Ã¥É¤ËÃÖ¤±¤ë¥í¡¼¥«¥ë¤Ê¥­¡¼³ä¤êÅö¤Æ¤ò»ý¤Ä¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó
5701     ¤òÊÖ¤¹¡£
5702
5703     @return
5704     ÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï @c NULL ¤òÊÖ¤¹¡£
5705
5706     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¥ê¥¹¥È¤Î³ÆÍ×ÁǤÎ
5707     ¥­¡¼¤Ï¸Ä¡¹¤Î¥³¥Þ¥ó¥É¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢Ãͤϲ¼µ­¤Î COMMAND-INFO
5708     ¤Î·Á¼°¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ç¤¢¤ë¡£
5709
5710     COMMAND-INFO ¤ÎÂè°ìÍ×ÁǤΥ­¡¼¤Ï #Mtext ¤Þ¤¿¤Ï #Msymbol ¤Ç¤¢¤ë¡£¥­¡¼
5711     ¤¬ #Mtext ¤Ê¤é¡¢ÃͤϤ½¤Î¥³¥Þ¥ó¥É¤òÀâÌÀ¤¹¤ë M-text ¤Ç¤¢¤ë¡£¥­¡¼¤¬
5712     #Msymbol ¤Ê¤éÃͤϠ#Mnil ¤Ç¤¢¤ê¡¢¤³¤Î¥³¥Þ¥ó¥É¤ÏÀâÌÀ¥Æ¥­¥¹¥È¤ò»ý¤¿¤Ê
5713     ¤¤¤³¤È¤Ë¤Ê¤ë¡£
5714
5715     ¤½¤ì°Ê³°¤ÎÍ×ÁǤ¬Ìµ¤±¤ì¤Ð¡¢¤³¤Î¥³¥Þ¥ó¥É¤ËÂФ·¤Æ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤¬³ä
5716     ¤êÅö¤Æ¤é¤ì¤Æ¤¤¤Ê¤¤¤³¤È¤ò°ÕÌ£¤¹¤ë¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢»Ä¤ê¤Î³ÆÍ×ÁǤϥ­
5717     ¡¼¤È¤·¤Æ#Mplist ¤ò¡¢ÃͤȤ·¤Æ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ò»ý¤Ä¡£¤³¤Î¥×¥í¥Ñ¥Æ¥£
5718     ¥ê¥¹¥È¤Î¥­¡¼¤Ï #Msymbol ¤Ç¤¢¤ê¡¢Ãͤϸ½ºß¤½¤Î¥³¥Þ¥ó¥É¤Ë³ä¤êÅö¤Æ¤é¤ì
5719     ¤Æ¤¤¤ëÆþÎÏ¥­¡¼¤òɽ¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
5720
5721     ÊÖ¤µ¤ì¤ë¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ï¥é¥¤¥Ö¥é¥ê¤Ë¤è¤Ã¤Æ´ÉÍý¤µ¤ì¤Æ¤ª¤ê¡¢¸Æ¤Ó½Ð
5722     ¤·Â¦¤ÇÊѹ¹¤·¤¿¤ê²òÊü¤·¤¿¤ê¤·¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£*/
5723
5724 MPlist *
5725 minput_get_commands (MSymbol language, MSymbol name)
5726 {
5727   MInputMethodInfo *im_info;
5728   MPlist *cmds;
5729
5730   MINPUT__INIT ();
5731
5732   im_info = get_im_info (language, name, Mnil, Mcommand);
5733   if (! im_info || ! im_info->configured_vars)
5734     return NULL;
5735   M17N_OBJECT_UNREF (im_info->bc_cmds);
5736   im_info->bc_cmds = mplist ();
5737   MPLIST_DO (cmds, im_info->configured_cmds)
5738     {
5739       MPlist *plist = MPLIST_PLIST (cmds);
5740       MPlist *elt = mplist ();
5741
5742       mplist_push (im_info->bc_cmds, Mplist, elt);
5743       mplist_add (elt, MPLIST_SYMBOL (plist),
5744                   mplist_copy (MPLIST_NEXT (plist)));
5745       M17N_OBJECT_UNREF (elt);
5746     }
5747   return im_info->bc_cmds;
5748 }
5749
5750 /*=*/
5751
5752 /***en
5753     @brief Assign a key sequence to an input method command (obsolete).
5754
5755     This function is obsolete.  Use minput_config_command () instead.
5756
5757     The minput_assign_command_keys () function assigns input key
5758     sequence $KEYSEQ to input method command $COMMAND for the input
5759     method specified by $LANGUAGE and $NAME.  If $NAME is #Mnil, the
5760     key sequence is assigned globally no matter what $LANGUAGE is.
5761     Otherwise the key sequence is assigned locally.
5762
5763     Each element of $KEYSEQ must have the key $Msymbol and the value
5764     must be a symbol representing an input key.
5765
5766     $KEYSEQ may be @c NULL, in which case, all assignments are deleted
5767     globally or locally.
5768
5769     This assignment gets effective in a newly opened input method.
5770
5771     @return
5772     If the operation was successful, 0 is returned.  Otherwise -1 is
5773     returned, and #merror_code is set to #MERROR_IM.  */
5774 /***ja
5775     @brief ÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤Ë¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤ò³ä¤êÅö¤Æ¤ë.
5776
5777     ´Ø¿ô minput_assign_command_keys () ¤Ï¡¢ $LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ
5778     »ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥ÉÍѤÎÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É $COMMAND ¤ËÂФ·¤Æ¡¢
5779     ÆþÎÏ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹ $KEYSEQ ¤ò³ä¤êÅö¤Æ¤ë¡£ $NAME ¤¬ #Mnil ¤Ê¤é¤Ð¡¢
5780     $LANGUAGE ¤Ë´Ø·¸¤Ê¤¯¡¢ÆþÎÏ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤Ï¥°¥í¡¼¥Ð¥ë¤Ë³ä¤êÅö¤Æ¤é
5781     ¤ì¤ë¡£¤½¤¦¤Ç¤Ê¤ì¤Ð¡¢³ä¤êÅö¤Æ¤Ï¥í¡¼¥«¥ë¤Ç¤¢¤ë¡£
5782
5783     $KEYSEQ ¤Î³ÆÍ×ÁǤϥ­¡¼¤È¤·¤Æ $Msymbol ¤ò¡¢ÃͤȤ·¤ÆÆþÎÏ¥­¡¼¤òɽ¤¹¥·
5784     ¥ó¥Ü¥ë¤ò»ý¤¿¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
5785
5786     $KEYSEQ ¤Ï @c NULL ¤Ç¤â¤è¤¤¡£¤³¤Î¾ì¹ç¡¢¥°¥í¡¼¥Ð¥ë¤â¤·¤¯¤Ï¥í¡¼¥«¥ë¤Ê
5787     ¤¹¤Ù¤Æ¤Î³ä¤êÅö¤Æ¤¬¾Ãµî¤µ¤ì¤ë¡£
5788
5789     ¤³¤Î³ä¤êÅö¤Æ¤Ï¡¢³ä¤êÅö¤Æ°Ê¹ß¿·¤·¤¯¥ª¡¼¥×¥ó¤µ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤«¤éÍ­
5790     ¸ú¤Ë¤Ê¤ë¡£
5791
5792     @return ½èÍý¤¬À®¸ù¤¹¤ì¤Ð 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤·¡¢
5793     #merror_code ¤ò #MERROR_IM ¤ËÀßÄꤹ¤ë¡£  */
5794
5795 int
5796 minput_assign_command_keys (MSymbol language, MSymbol name,
5797                             MSymbol command, MPlist *keyseq)
5798 {
5799   int ret;
5800
5801   MINPUT__INIT ();
5802
5803   if (command == Mnil)
5804     MERROR (MERROR_IM, -1);
5805   if (keyseq)
5806     {
5807       MPlist *plist;
5808
5809       if  (! check_command_keyseq (keyseq))
5810         MERROR (MERROR_IM, -1);
5811       plist = mplist ();
5812       mplist_add (plist, Mplist, keyseq);
5813       keyseq = plist;
5814     }  
5815   else
5816     keyseq = mplist ();
5817   ret = minput_config_command (language, name, command, keyseq);
5818   M17N_OBJECT_UNREF (keyseq);
5819   return ret;
5820 }
5821
5822 /*** @} */ 
5823 /*** @} */
5824 /*=*/
5825 /*** @addtogroup m17nDebug */
5826 /*=*/
5827 /*** @{  */
5828 /*=*/
5829
5830 /***en
5831     @brief Dump an input method.
5832
5833     The mdebug_dump_im () function prints the input method $IM in a
5834     human readable way to the stderr.  $INDENT specifies how many
5835     columns to indent the lines but the first one.
5836
5837     @return
5838     This function returns $IM.  */
5839 /***ja
5840     @brief ÆþÎϥ᥽¥Ã¥É¤ò¥À¥ó¥×¤¹¤ë.
5841
5842     ´Ø¿ô mdebug_dump_im () ¤ÏÆþÎϥ᥽¥Ã¥É $IM ¤ò stderr 
5843     ¤Ë¿Í´Ö¤Ë²ÄÆɤʷÁ¤Ç°õºþ¤¹¤ë¡£$INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£
5844
5845     @return
5846     ¤³¤Î´Ø¿ô¤Ï $IM ¤òÊÖ¤¹¡£  */
5847
5848 MInputMethod *
5849 mdebug_dump_im (MInputMethod *im, int indent)
5850 {
5851   MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
5852   char *prefix;
5853
5854   prefix = (char *) alloca (indent + 1);
5855   memset (prefix, 32, indent);
5856   prefix[indent] = '\0';
5857
5858   fprintf (stderr, "(input-method %s %s ", msymbol_name (im->language),
5859            msymbol_name (im->name));
5860   mdebug_dump_mtext (im_info->title, 0, 0);
5861   if (im->name != Mnil)
5862     {
5863       MPlist *state;
5864
5865       MPLIST_DO (state, im_info->states)
5866         {
5867           fprintf (stderr, "\n%s  ", prefix);
5868           dump_im_state (MPLIST_VAL (state), indent + 2);
5869         }
5870     }
5871   fprintf (stderr, ")");
5872   return im;
5873 }
5874
5875 /*** @} */ 
5876
5877 /*
5878   Local Variables:
5879   coding: euc-japan
5880   End:
5881 */