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