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