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