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