(parse_action_list): Handle the case that the arg is a
[m17n/m17n-lib.git] / src / input.c
1 /* input.c -- input method module.
2    Copyright (C) 2003, 2004, 2005
3      National Institute of Advanced Industrial Science and Technology (AIST)
4      Registration Number H15PRO112
5
6    This file is part of the m17n library.
7
8    The m17n library is free software; you can redistribute it and/or
9    modify it under the terms of the GNU Lesser General Public License
10    as published by the Free Software Foundation; either version 2.1 of
11    the License, or (at your option) any later version.
12
13    The m17n library is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    Lesser General Public License for more details.
17
18    You should have received a copy of the GNU Lesser General Public
19    License along with the m17n library; if not, write to the Free
20    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21    02111-1307, USA.  */
22
23 /***en
24     @addtogroup m17nInputMethod
25     @brief API for Input method.
26
27     An input method is an object to enable inputting various
28     characters.  An input method is identified by a pair of symbols,
29     LANGUAGE and NAME.  This pair decides a 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 the 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 driver utilize the input processing engine
42     provided by the m17n library itself.  The m17n database may
43     provides an input method that is not only for a specific language.
44     The database uses @c Mt as LANGUAGE of such an input method.
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 have 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 the body is
56     defined in an external resources (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 °Ê³°¤Î¤â¤Î¤Ç¤¢¤ê¡¢¤½¤ÎËÜÂΤÏm17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë
95     <Minput_method, LANGUAGE, NAME> 
96     ¤È¤¤¤¦¥¿¥°¤òÉÕ¤±¤ÆÄêµÁ¤µ¤ì¤Æ¤¤¤ë¡£
97     ¤³¤Î¼ï¤ÎÆþÎϥ᥽¥Ã¥É¤ËÂФ·¤Æ¡¢m17n ¥é¥¤¥Ö¥é¥ê¤Ç¤Ï
98     CUI ÍѤȠGUI ÍѤ½¤ì¤¾¤ì¤ÎÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤ò¤¢¤é¤«¤¸¤áÄêµÁ¤·¤Æ¤¤¤ë¡£
99     ¤³¤ì¤é¤Î¥É¥é¥¤¥Ð¤Ï m17n ¥é¥¤¥Ö¥é¥ê¼«ÂΤÎÆþÎϽèÍý¥¨¥ó¥¸¥ó¤òÍøÍѤ¹¤ë¡£
100     m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë¤Ï¡¢ÆÃÄê¤Î¸À¸ìÀìÍѤǤʤ¤ÆþÎϥ᥽¥Ã¥É¤òÄêµÁ¤¹¤ë¤³¤È¤â¤Ç¤­¡¢
101     ¤½¤Î¤è¤¦¤ÊÆþÎϥ᥽¥Ã¥É¤Î LANGUAGE ¤Ï @c Mt ¤Ç¤¢¤ë¡£
102
103     ÆâÉôÆþÎϥ᥽¥Ã¥É¤Ï¡¢¥æ¡¼¥¶¤ÎÆþÎÏ¥¤¥Ù¥ó¥È¤ËÂбþ¤·¤¿¥·¥ó¥Ü¥ë¤Ç¤¢¤ëÆþÎÏ¥­¡¼¤ò¼õ¤±¼è¤ë¡£
104     @c m17n @c ¥é¥¤¥Ö¥é¥ê ¤ÏÆþÎÏ¥¤¥Ù¥ó¥È¤¬¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ç¤É¤¦É½¸½¤µ¤ì¤Æ¤¤¤ë¤«¤òÃΤ뤳¤È¤¬¤Ç¤­¤Ê¤¤¤Î¤Ç¡¢
105     ÆþÎÏ¥¤¥Ù¥ó¥È¤«¤éÆþÎÏ¥­¡¼¤Ø¤ÎÊÑ´¹¤Ï¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥Þ¤ÎÀÕǤ¤Ç¹Ô¤ï¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
106     ¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï´Ø¿ô minput_event_to_key () ¤ÎÀâÌÀ¤ò»²¾È¡£
107
108     <li> ³°ÉôÆþÎϥ᥽¥Ã¥É
109
110     ³°ÉôÆþÎϥ᥽¥Ã¥É¤È¤Ï LANGUAGE ¤¬ @c Mnil ¤Î¤â¤Î¤Ç¤¢¤ê¡¢¤½¤ÎËÜÂΤϳ°Éô¤Î¥ê¥½¡¼¥¹¤È¤·¤ÆÄêµÁ¤µ¤ì¤ë¡£
111     ¡Ê¤¿¤È¤¨¤ÐX Window System ¤ÎXIM ¤Ê¤É¡£) 
112     ¤³¤Î¼ï¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢¥·¥ó¥Ü¥ë NAME ¤Ï@c Minput_driver 
113     ¤ò¥­¡¼¤È¤¹¤ë¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Á¡¢¤½¤ÎÃͤÏÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£
114     ¤³¤Î¤³¤È¤Ë¤è¤ê¡¢Å¬Àڤʥɥ饤¥Ð¤ò½àÈ÷¤¹¤ë¤³¤È¤Ë¤è¤Ã¤Æ¡¢¤¤¤«¤Ê¤ë¼ïÎà¤ÎÆþÎϥ᥽¥Ã¥É¤â
115     @c m17n @c ¥é¥¤¥Ö¥é¥ê ¤ÎÏÈÁȤÎÃæ¤Ç°·¤¦»ö¤¬¤Ç¤­¤ë¡£
116
117     ÍøÊØÀ­¤Î´ÑÅÀ¤«¤é¡¢m17n X ¥é¥¤¥Ö¥é¥ê¤Ï XIM ¤Î OverTheSpot 
118     ¤ÎÆþÎÏ¥¹¥¿¥¤¥ë¤ò¼Â¸½¤¹¤ëÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤òÄ󶡤·¡¢¤Þ¤¿¥·¥ó¥Ü¥ë @c Mxim ¤Î 
119     @c Minput_driver ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤȤ·¤Æ¤½¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÝ»ý¤·¤Æ¤¤¤ë¡£
120     ¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï m17n GUI API ¤Î¥É¥­¥å¥á¥ó¥È¤ò»²¾È¤Î¤³¤È¡£
121
122     </ul> 
123
124     ½èÍý¤Îή¤ì
125
126     ÆþÎϥ᥽¥Ã¥É½èÍý¤Îŵ·¿Åª¤Ê½èÍý¤Ï°Ê²¼¤Î¤è¤¦¤Ë¤Ê¤ë¡£
127     
128     @li ÆþÎϥ᥽¥Ã¥É¤Î¥ª¡¼¥×¥ó
129     @li ¤½¤ÎÆþÎϥ᥽¥Ã¥É¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤ÎÀ¸À®
130     @li ÆþÎÏ¥¤¥Ù¥ó¥È¤Î¥Õ¥£¥ë¥¿
131     @li ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ç¤ÎÀ¸À®¥Æ¥­¥¹¥È¤Î¸¡º÷     */
132
133 /*=*/
134
135 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
136 /*** @addtogroup m17nInternal
137      @{ */
138
139 #include <stdio.h>
140 #include <string.h>
141 #include <sys/types.h>
142 #include <dirent.h>
143
144 #include "config.h"
145
146 #ifdef HAVE_DLFCN_H
147 #include <dlfcn.h>
148 #endif
149
150 #include "m17n-gui.h"
151 #include "m17n-misc.h"
152 #include "internal.h"
153 #include "mtext.h"
154 #include "input.h"
155 #include "symbol.h"
156 #include "plist.h"
157 #include "database.h"
158
159 static int mdebug_mask = MDEBUG_INPUT;
160
161 static MSymbol Minput_method;
162
163 /** Symbols to load an input method data.  */
164 static MSymbol Mtitle, Mmacro, Mmodule, Mstate;
165
166 /** Symbols for actions.  */
167 static MSymbol Minsert, Mdelete, Mmark, Mmove, Mpushback, Mundo, Mcall, Mshift;
168 static MSymbol Mselect, Mshow, Mhide;
169 static MSymbol Mset, Madd, Msub, Mmul, Mdiv, Mequal, Mless, Mgreater;
170
171 static MSymbol Mcandidate_list, Mcandidate_index;
172
173 static MSymbol Minit, Mfini;
174
175 /** Symbols for key events.  */
176 static MSymbol one_char_symbol[256];
177
178 static MSymbol M_key_alias;
179
180 static MSymbol M_description, M_command, M_variable;
181
182 /** Structure to hold a map.  */
183
184 struct MIMMap
185 {
186   /** List of actions to take when we reach the map.  In a root map,
187       the actions are executed only when there's no more key.  */
188   MPlist *map_actions;
189
190   /** List of deeper maps.  If NULL, this is a terminal map.  */
191   MPlist *submaps;
192
193   /** List of actions to take when we leave the map successfully.  In
194       a root map, the actions are executed only when none of submaps
195       handle the current key.  */
196   MPlist *branch_actions;
197 };
198
199 typedef MPlist *(*MIMExternalFunc) (MPlist *plist);
200
201 typedef struct
202 {
203   void *handle;
204   MPlist *func_list;            /* function name vs (MIMExternalFunc *) */
205 } MIMExternalModule;
206
207 struct MIMState
208 {
209   /** Name of the state.  */
210   MSymbol name;
211
212   /** Title of the state, or NULL.  */
213   MText *title;
214
215   /** Key translation map of the state.  Built by merging all maps of
216       branches.  */
217   MIMMap *map;
218 };
219
220
221 static int
222 marker_code (MSymbol sym)
223 {
224   char *name;
225
226   if (sym == Mnil)
227     return -1;
228   name = MSYMBOL_NAME (sym);
229   return ((name[0] == '@'
230            && ((name[1] >= '0' && name[1] <= '9')
231                || name[1] == '<' || name[1] == '>'
232                || name[1] == '=' || name[1] == '+' || name[1] == '-'
233                || name[1] == '[' || name[1] == ']')
234            && name[2] == '\0')
235           ? name[1] : -1);
236 }
237
238 int
239 integer_value (MInputContext *ic, MPlist *arg)
240 {
241   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
242   int code;
243   MText *preedit = ic->preedit;
244   int len = mtext_nchars (preedit);
245
246   if (MPLIST_INTEGER_P (arg))
247     return MPLIST_INTEGER (arg);
248   code = marker_code (MPLIST_SYMBOL (arg));
249   if (code < 0)
250     return (int) mplist_get (ic_info->vars, MPLIST_SYMBOL (arg));
251   if (code >= '0' && code <= '9')
252     code -= '0';
253   else if (code == '=')
254     code = ic->cursor_pos;
255   else if (code == '-' || code == '[')
256     code = ic->cursor_pos - 1;
257   else if (code == '+' || code == ']')
258     code = ic->cursor_pos + 1;
259   else if (code == '<')
260     code = 0;
261   else if (code == '>')
262     code = len;
263   return (code >= 0 && code < len ? mtext_ref_char (preedit, code) : -1);
264 }
265
266
267 /* Parse PLIST as an action list while modifying the list to regularize
268    actions.  PLIST should have this form:
269       PLIST ::= ( (ACTION-NAME ACTION-ARG *) *).
270    Return 0 if successfully parsed, otherwise return -1.  */
271
272 static int
273 parse_action_list (MPlist *plist, MPlist *macros)
274 {
275   MPLIST_DO (plist, plist)
276     {
277       if (MPLIST_MTEXT_P (plist))
278         {
279           /* This is a short form of (insert MTEXT).  */
280           /* if (mtext_nchars (MPLIST_MTEXT (plist)) == 0)
281              MERROR (MERROR_IM, -1); */
282         }
283       else if (MPLIST_PLIST_P (plist)
284                && (MPLIST_MTEXT_P (MPLIST_PLIST (plist))
285                    || MPLIST_PLIST_P (MPLIST_PLIST (plist))))
286         {
287           MPlist *pl;
288
289           /* This is a short form of (insert (GROUPS *)).  */
290           MPLIST_DO (pl, MPLIST_PLIST (plist))
291             {
292               if (MPLIST_PLIST_P (pl))
293                 {
294                   MPlist *elt;
295
296                   MPLIST_DO (elt, MPLIST_PLIST (pl))
297                     if (! MPLIST_MTEXT_P (elt)
298                         || mtext_nchars (MPLIST_MTEXT (elt)) == 0)
299                       MERROR (MERROR_IM, -1);
300                 }
301               else
302                 {
303                   if (! MPLIST_MTEXT_P (pl)
304                       || mtext_nchars (MPLIST_MTEXT (pl)) == 0)
305                     MERROR (MERROR_IM, -1);
306                 }
307             }
308         }
309       else if (MPLIST_INTEGER_P (plist))
310         {
311           int c = MPLIST_INTEGER (plist);
312
313           if (c < 0 || c > MCHAR_MAX)
314             MERROR (MERROR_IM, -1);
315         }
316       else if (MPLIST_PLIST_P (plist)
317                && MPLIST_SYMBOL_P (MPLIST_PLIST (plist)))
318         {
319           MPlist *pl = MPLIST_PLIST (plist);
320           MSymbol action_name = MPLIST_SYMBOL (pl);
321
322           pl = MPLIST_NEXT (pl);
323
324           if (action_name == Minsert)
325             {
326               if (MPLIST_MTEXT_P (pl))
327                 {
328                   if (mtext_nchars (MPLIST_MTEXT (pl)) == 0)
329                     MERROR (MERROR_IM, -1);
330                 }
331               else if (MPLIST_PLIST_P (pl))
332                 {
333                   MPLIST_DO (pl, pl)
334                     {
335                       if (MPLIST_PLIST_P (pl))
336                         {
337                           MPlist *elt;
338
339                           MPLIST_DO (elt, MPLIST_PLIST (pl))
340                             if (! MPLIST_MTEXT_P (elt)
341                                 || mtext_nchars (MPLIST_MTEXT (elt)) == 0)
342                               MERROR (MERROR_IM, -1);
343                         }
344                       else
345                         {
346                           if (! MPLIST_MTEXT_P (pl)
347                               || mtext_nchars (MPLIST_MTEXT (pl)) == 0)
348                             MERROR (MERROR_IM, -1);
349                         }
350                     }
351                 }
352               else if (! MPLIST_SYMBOL_P (pl))
353                 MERROR (MERROR_IM, -1); 
354             }
355           else if (action_name == Mselect
356                    || action_name == Mdelete
357                    || action_name == Mmove)
358             {
359               if (! MPLIST_SYMBOL_P (pl)
360                   && ! MPLIST_INTEGER_P (pl))
361                 MERROR (MERROR_IM, -1);
362             }
363           else if (action_name == Mmark
364                    || action_name == Mcall
365                    || action_name == Mshift)
366             {
367               if (! MPLIST_SYMBOL_P (pl))
368                 MERROR (MERROR_IM, -1);
369             }
370           else if (action_name == Mshow || action_name == Mhide
371                    || action_name == Mundo)
372             {
373               if (! MPLIST_TAIL_P (pl))
374                 MERROR (MERROR_IM, -1);
375             }
376           else if (action_name == Mpushback)
377             {
378               if (MPLIST_MTEXT_P (pl))
379                 {
380                   MText *mt = MPLIST_MTEXT (pl);
381
382                   if (mtext_nchars (mt) != mtext_nbytes (mt))
383                     MERROR (MERROR_IM, -1);                 
384                 }
385               else if (MPLIST_PLIST_P (pl))
386                 {
387                   MPlist *p;
388
389                   MPLIST_DO (p, MPLIST_PLIST (pl))
390                     if (! MPLIST_SYMBOL_P (p))
391                       MERROR (MERROR_IM, -1);
392                 }
393               else if (! MPLIST_INTEGER_P (pl))
394                 MERROR (MERROR_IM, -1);
395             }
396           else if (action_name == Mset || action_name == Madd
397                    || action_name == Msub || action_name == Mmul
398                    || action_name == Mdiv)
399             {
400               if (! (MPLIST_SYMBOL_P (pl)
401                      && (MPLIST_INTEGER_P (MPLIST_NEXT (pl))
402                          || MPLIST_SYMBOL_P (MPLIST_NEXT (pl)))))
403                 MERROR (MERROR_IM, -1);
404             }
405           else if (action_name == Mequal || action_name == Mless
406                    || action_name == Mgreater)
407             {
408               if (! ((MPLIST_INTEGER_P (pl) || MPLIST_SYMBOL_P (pl))
409                      && (MPLIST_INTEGER_P (MPLIST_NEXT (pl))
410                          || MPLIST_SYMBOL_P (MPLIST_NEXT (pl)))))
411                 MERROR (MERROR_IM, -1);
412               pl = MPLIST_NEXT (MPLIST_NEXT (pl));
413               if (! MPLIST_PLIST_P (pl))
414                 MERROR (MERROR_IM, -1);
415               if (parse_action_list (MPLIST_PLIST (pl), macros) < 0)
416                 MERROR (MERROR_IM, -1);
417               pl = MPLIST_NEXT (pl);
418               if (MPLIST_PLIST_P (pl)
419                   && parse_action_list (MPLIST_PLIST (pl), macros) < 0)
420                 MERROR (MERROR_IM, -1);
421             }
422           else if (! macros || ! mplist_get (macros, action_name))
423             MERROR (MERROR_IM, -1);
424         }
425       else
426         MERROR (MERROR_IM, -1);
427     }
428
429   return 0;
430 }
431
432
433 /* Load a translation into MAP from PLIST.
434    PLIST has this form:
435       PLIST ::= ( KEYSEQ MAP-ACTION * )  */
436
437 static int
438 load_translation (MIMMap *map, MPlist *plist, MPlist *branch_actions,
439                   MPlist *macros)
440 {
441   MSymbol *keyseq;
442   int len, i;
443
444   if (MPLIST_MTEXT_P (plist))
445     {
446       MText *mt = MPLIST_MTEXT (plist);
447
448       len = mtext_nchars (mt);
449       if (len == 0 || len != mtext_nbytes (mt))
450         MERROR (MERROR_IM, -1);
451       keyseq = (MSymbol *) alloca (sizeof (MSymbol) * len);
452       for (i = 0; i < len; i++)
453         keyseq[i] = one_char_symbol[MTEXT_DATA (mt)[i]];
454     }
455   else if (MPLIST_PLIST_P (plist))
456     {
457       MPlist *elt = MPLIST_PLIST (plist);
458           
459       len = MPLIST_LENGTH (elt);
460       if (len == 0)
461         MERROR (MERROR_IM, -1);
462       keyseq = (MSymbol *) alloca (sizeof (int) * len);
463       for (i = 0; i < len; i++, elt = MPLIST_NEXT (elt))
464         {
465           if (MPLIST_INTEGER_P (elt))
466             {
467               int c = MPLIST_INTEGER (elt);
468
469               if (c < 0 || c >= 0x100)
470                 MERROR (MERROR_IM, -1);
471               keyseq[i] = one_char_symbol[c];
472             }
473           else if (MPLIST_SYMBOL_P (elt))
474             keyseq[i] = MPLIST_SYMBOL (elt);
475           else
476             MERROR (MERROR_IM, -1);
477         }
478     }
479   else
480     MERROR (MERROR_IM, -1);
481
482   for (i = 0; i < len; i++)
483     {
484       MIMMap *deeper = NULL;
485
486       if (map->submaps)
487         deeper = mplist_get (map->submaps, keyseq[i]);
488       else
489         map->submaps = mplist ();
490       if (! deeper)
491         {
492           /* Fixme: It is better to make all deeper maps at once.  */
493           MSTRUCT_CALLOC (deeper, MERROR_IM);
494           mplist_put (map->submaps, keyseq[i], deeper);
495         }
496       map = deeper;
497     }
498
499   /* We reach a terminal map.  */
500   if (map->map_actions
501       || map->branch_actions)
502     /* This map is already defined.  We avoid overriding it.  */
503     return 0;
504
505   plist = MPLIST_NEXT (plist);
506   if (! MPLIST_TAIL_P (plist))
507     {
508       if (parse_action_list (plist, macros) < 0)
509         MERROR (MERROR_IM, -1);
510       map->map_actions = plist;
511       M17N_OBJECT_REF (plist);
512     }
513   if (branch_actions)
514     {
515       map->branch_actions = branch_actions;
516       M17N_OBJECT_REF (branch_actions);
517     }
518
519   return 0;
520 }
521
522 /* Load a branch from PLIST into MAP.  PLIST has this form:
523       PLIST ::= ( MAP-NAME BRANCH-ACTION * )
524    MAPS is a plist of raw maps.
525    STATE is the current state.  */
526
527 static int
528 load_branch (MPlist *plist, MPlist *maps, MIMMap *map, MPlist *macros)
529 {
530   MSymbol map_name;
531   MPlist *branch_actions;
532
533   if (! MPLIST_SYMBOL_P (plist))
534     MERROR (MERROR_IM, -1);
535   map_name = MPLIST_SYMBOL (plist);
536   plist = MPLIST_NEXT (plist);
537   if (MPLIST_TAIL_P (plist))
538     branch_actions = NULL;
539   else if (parse_action_list (plist, macros) < 0)
540     MERROR (MERROR_IM, -1);
541   else
542     branch_actions = plist;
543   if (map_name == Mnil)
544     {
545       map->branch_actions = branch_actions;
546       if (branch_actions)
547         M17N_OBJECT_REF (branch_actions);
548     }
549   else if (map_name == Mt)
550     {
551       map->map_actions = branch_actions;
552       if (branch_actions)
553         M17N_OBJECT_REF (branch_actions);
554     }
555   else
556     {
557       plist = (MPlist *) mplist_get (maps, map_name);
558       if (! plist || ! MPLIST_PLIST_P (plist))
559         MERROR (MERROR_IM, -1);
560       MPLIST_DO (plist, plist)
561         if (! MPLIST_PLIST_P (plist)
562             || (load_translation (map, MPLIST_PLIST (plist), branch_actions,
563                                   macros)
564                 < 0))
565           MERROR (MERROR_IM, -1);
566     }
567
568   return 0;
569 }
570
571 /* Load a macro from PLIST into MACROS.
572    PLIST has this from:
573       PLIST ::= ( MACRO-NAME ACTION * )
574    MACROS is a plist of macro names vs action list.  */
575 static int
576 load_macros (MPlist *plist, MPlist *macros)
577 {
578   MSymbol name; 
579
580   if (! MPLIST_SYMBOL_P (plist))
581     MERROR (MERROR_IM, -1);
582   name = MPLIST_SYMBOL (plist);
583   plist = MPLIST_NEXT (plist);
584   if (MPLIST_TAIL_P (plist)
585       || parse_action_list (plist, macros) < 0)
586     MERROR (MERROR_IM, -1);
587   mplist_put (macros, name, plist);
588   M17N_OBJECT_REF (plist);
589   return 0;
590 }
591
592 /* Load an external module from PLIST into EXTERNALS.
593    PLIST has this form:
594       PLIST ::= ( MODULE-NAME FUNCTION * )
595    EXTERNALS is a plist of MODULE-NAME vs (MIMExternalModule *).  */
596
597 static int
598 load_external_module (MPlist *plist, MPlist *externals)
599 {
600   void *handle;
601   MSymbol module;
602   char *module_file;
603   MIMExternalModule *external;
604   MPlist *func_list;
605   void *func;
606
607   if (MPLIST_MTEXT_P (plist))
608     module = msymbol ((char *) MTEXT_DATA (MPLIST_MTEXT (plist)));
609   else if (MPLIST_SYMBOL_P (plist))
610     module = MPLIST_SYMBOL (plist);
611   module_file = alloca (strlen (MSYMBOL_NAME (module))
612                         + strlen (DLOPEN_SHLIB_EXT) + 1);
613   sprintf (module_file, "%s%s", MSYMBOL_NAME (module), DLOPEN_SHLIB_EXT);
614
615   handle = dlopen (module_file, RTLD_NOW);
616   if (! handle)
617     {
618       fprintf (stderr, "%s\n", dlerror ());
619       MERROR (MERROR_IM, -1);
620     }
621   func_list = mplist ();
622   MPLIST_DO (plist, MPLIST_NEXT (plist))
623     {
624       if (! MPLIST_SYMBOL_P (plist))
625         MERROR_GOTO (MERROR_IM, err_label);
626       func = dlsym (handle, MSYMBOL_NAME (MPLIST_SYMBOL (plist)));
627       if (! func)
628         MERROR_GOTO (MERROR_IM, err_label);
629       mplist_add (func_list, MPLIST_SYMBOL (plist), func);
630     }
631
632   MSTRUCT_MALLOC (external, MERROR_IM);
633   external->handle = handle;
634   external->func_list = func_list;
635   mplist_add (externals, module, external);
636   return 0;
637
638  err_label:
639   dlclose (handle);
640   M17N_OBJECT_UNREF (func_list);
641   return -1;
642 }
643
644
645 /** Load a state from PLIST into a newly allocated state object.
646     PLIST has this form:
647       PLIST ::= ( STATE-NAME STATE-TITLE ? BRANCH * )
648       BRANCH ::= ( MAP-NAME BRANCH-ACTION * )
649    MAPS is a plist of defined maps.
650    Return the state object.  */
651
652 static MIMState *
653 load_state (MPlist *plist, MPlist *maps, MSymbol language, MPlist *macros)
654 {
655   MIMState *state;
656
657   MSTRUCT_CALLOC (state, MERROR_IM);
658   if (! MPLIST_SYMBOL_P (plist))
659     MERROR (MERROR_IM, NULL);
660   state->name = MPLIST_SYMBOL (plist);
661   plist = MPLIST_NEXT (plist);
662   if (MPLIST_MTEXT_P (plist))
663     {
664       state->title = MPLIST_MTEXT (plist);
665       mtext_put_prop (state->title, 0, mtext_nchars (state->title),
666                       Mlanguage, language);
667       M17N_OBJECT_REF (state->title);
668       plist = MPLIST_NEXT (plist);
669     }
670   MSTRUCT_CALLOC (state->map, MERROR_IM);
671   MPLIST_DO (plist, plist)
672     if (! MPLIST_PLIST_P (plist)
673         || load_branch (MPLIST_PLIST (plist), maps, state->map, macros) < 0)
674       MERROR (MERROR_IM, NULL);
675   return state;
676 }
677
678
679 static void
680 free_map (MIMMap *map)
681 {
682   MPlist *plist;
683
684   M17N_OBJECT_UNREF (map->map_actions);
685   if (map->submaps)
686     {
687       MPLIST_DO (plist, map->submaps)
688         free_map ((MIMMap *) MPLIST_VAL (plist));
689       M17N_OBJECT_UNREF (map->submaps);
690     }
691   M17N_OBJECT_UNREF (map->branch_actions);
692   free (map);
693 }
694
695 /* Load an input method from PLIST into IM_INTO, and return it.  */
696
697 static int
698 load_input_method (MSymbol language, MSymbol name, MPlist *plist,
699                    MInputMethodInfo *im_info)
700 {
701   MText *title = NULL;
702   MPlist *maps = NULL;
703   MPlist *states = NULL;
704   MPlist *externals = NULL;
705   MPlist *macros = NULL;
706   MPlist *elt;
707
708   for (; MPLIST_PLIST_P (plist); plist = MPLIST_NEXT (plist))
709     {
710       elt = MPLIST_PLIST (plist);
711       if (! MPLIST_SYMBOL_P (elt))
712         MERROR_GOTO (MERROR_IM, err);
713       if (MPLIST_SYMBOL (elt) == Mtitle)
714         {
715           elt = MPLIST_NEXT (elt);
716           if (MPLIST_MTEXT_P (elt))
717             {
718               title = MPLIST_MTEXT (elt);
719               M17N_OBJECT_REF (title);
720             }
721           else
722             MERROR_GOTO (MERROR_IM, err);
723         }
724       else if (MPLIST_SYMBOL (elt) == Mmap)
725         {
726           maps = mplist__from_alist (MPLIST_NEXT (elt));
727           if (! maps)
728             MERROR_GOTO (MERROR_IM, err);
729         }
730       else if (MPLIST_SYMBOL (elt) == Mmacro)
731         {
732           macros = mplist ();
733           MPLIST_DO (elt, MPLIST_NEXT (elt))
734           {
735             if (! MPLIST_PLIST_P (elt)
736                 || load_macros (MPLIST_PLIST (elt), macros) < 0)
737               MERROR_GOTO (MERROR_IM, err);
738           }
739         }
740       else if (MPLIST_SYMBOL (elt) == Mmodule)
741         {
742           externals = mplist ();
743           MPLIST_DO (elt, MPLIST_NEXT (elt))
744           {
745             if (! MPLIST_PLIST_P (elt)
746                 || load_external_module (MPLIST_PLIST (elt), externals) < 0)
747               MERROR_GOTO (MERROR_IM, err);
748           }
749         }
750       else if (MPLIST_SYMBOL (elt) == Mstate)
751         {
752           states = mplist ();
753           MPLIST_DO (elt, MPLIST_NEXT (elt))
754           {
755             MIMState *state;
756
757             if (! MPLIST_PLIST_P (elt))
758               MERROR_GOTO (MERROR_IM, err);
759             state = load_state (MPLIST_PLIST (elt), maps, language, macros);
760             if (! state)
761               MERROR_GOTO (MERROR_IM, err);
762             mplist_put (states, state->name, state);
763           }
764         }
765     }
766
767   if (maps)
768     {
769       MPLIST_DO (elt, maps)
770         M17N_OBJECT_UNREF (MPLIST_VAL (elt));
771       M17N_OBJECT_UNREF (maps);
772     }
773   if (! title)
774     title = mtext_from_data (MSYMBOL_NAME (name), MSYMBOL_NAMELEN (name),
775                              MTEXT_FORMAT_US_ASCII);
776   im_info->title = title;
777   im_info->externals = externals;
778   im_info->macros = macros;
779   im_info->states = states;
780   return 0;
781
782  err:
783   if (maps)
784     {
785       MPLIST_DO (elt, maps)
786         M17N_OBJECT_UNREF (MPLIST_VAL (elt));
787       M17N_OBJECT_UNREF (maps);
788     }
789   if (title)
790     M17N_OBJECT_UNREF (title);
791   if (states)
792     {
793       MPLIST_DO (plist, states)
794       {
795         MIMState *state = (MIMState *) MPLIST_VAL (plist);
796
797         if (state->title)
798           M17N_OBJECT_UNREF (state->title);
799         if (state->map)
800           free_map (state->map);
801         free (state);
802       }
803       M17N_OBJECT_UNREF (states);
804     }
805   if (externals)
806     {
807       MPLIST_DO (plist, externals)
808       {
809         MIMExternalModule *external = MPLIST_VAL (plist);
810
811         dlclose (external->handle);
812         M17N_OBJECT_UNREF (external->func_list);
813         free (external);
814         MPLIST_KEY (plist) = Mt;
815       }
816       M17N_OBJECT_UNREF (externals);
817     }
818   return -1;
819 }
820
821 \f
822
823 static int take_action_list (MInputContext *ic, MPlist *action_list);
824
825 static void
826 shift_state (MInputContext *ic, MSymbol state_name)
827 {
828   MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
829   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
830   MIMState *state;
831
832   /* Find a state to shift to.  If not found, shift to the initial
833      state.  */
834   state = (MIMState *) mplist_get (im_info->states, state_name);
835   if (! state)
836     state = (MIMState *) MPLIST_VAL (im_info->states);
837
838   MDEBUG_PRINT1 ("\n[IM] (shift %s)", MSYMBOL_NAME (state->name));
839
840   /* Enter the new state.  */
841   ic_info->state = state;
842   ic_info->map = state->map;
843   ic_info->state_key_head = ic_info->key_head;
844   if (state == (MIMState *) MPLIST_VAL (im_info->states))
845     {
846       /* We have shifted to the initial state.  */
847       MPlist *p;
848
849       mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit),
850                              Mcandidate_list, NULL, 0);
851       mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit),
852                              Mcandidate_index, NULL, 0);
853       mtext_cat (ic->produced, ic->preedit);
854       if ((mdebug__flag & mdebug_mask)
855           && mtext_nchars (ic->produced) > 0)
856         {
857           int i;
858
859           MDEBUG_PRINT (" (produced");
860             for (i = 0; i < mtext_nchars (ic->produced); i++)
861               MDEBUG_PRINT1 (" U+%04X", mtext_ref_char (ic->produced, i));
862           MDEBUG_PRINT (")");
863         }
864       mtext_reset (ic->preedit);
865       ic->candidate_list = NULL;
866       ic->candidate_show = 0;
867       ic->preedit_changed = ic->candidates_changed = 1;
868       MPLIST_DO (p, ic_info->markers)
869         MPLIST_VAL (p) = 0;
870       ic->cursor_pos = 0;
871       memmove (ic_info->keys, ic_info->keys + ic_info->state_key_head,
872                sizeof (int) * (ic_info->used - ic_info->state_key_head));
873       ic_info->used -= ic_info->state_key_head;
874       ic_info->state_key_head = ic_info->key_head = 0;
875     }
876   mtext_cpy (ic_info->preedit_saved, ic->preedit);
877   ic_info->state_pos = ic->cursor_pos;
878   ic->status = state->title;
879   if (! ic->status)
880     ic->status = im_info->title;
881   ic->status_changed = 1;
882   if (ic_info->key_head == ic_info->used
883       && ic_info->map == ic_info->state->map
884       && ic_info->map->map_actions)
885     {
886       MDEBUG_PRINT (" init-actions:");
887       take_action_list (ic, ic_info->map->map_actions);
888     }
889 }
890
891 /* Find a candidate group that contains a candidate number INDEX from
892    PLIST.  Set START_INDEX to the first candidate number of the group,
893    END_INDEX to the last candidate number plus 1, GROUP_INDEX to the
894    candidate group number if they are non-NULL.  If INDEX is -1, find
895    the last candidate group.  */
896
897 static MPlist *
898 find_candidates_group (MPlist *plist, int index,
899                        int *start_index, int *end_index, int *group_index)
900 {
901   int i = 0, gidx = 0, len;
902
903   MPLIST_DO (plist, plist)
904     {
905       if (MPLIST_MTEXT_P (plist))
906         len = mtext_nchars (MPLIST_MTEXT (plist));
907       else
908         len = mplist_length (MPLIST_PLIST (plist));
909       if (index < 0 ? MPLIST_TAIL_P (MPLIST_NEXT (plist))
910           : i + len > index)
911         {
912           if (start_index)
913             *start_index = i;
914           if (end_index)
915             *end_index = i + len;
916           if (group_index)
917             *group_index = gidx;
918           return plist;
919         }
920       i += len;
921       gidx++;
922     }
923   return NULL;
924 }
925
926 static void
927 preedit_insert (MInputContext *ic, int pos, MText *mt, int c)
928 {
929   MInputContextInfo *ic_info = ((MInputContext *) ic)->info;
930   MPlist *markers;
931   int nchars = mt ? mtext_nchars (mt) : 1;
932
933   if (mt)
934     mtext_ins (ic->preedit, pos, mt);
935   else
936     mtext_ins_char (ic->preedit, pos, c, 1);
937   MPLIST_DO (markers, ic_info->markers)
938     if (MPLIST_INTEGER (markers) > pos)
939       MPLIST_VAL (markers) = (void *) (MPLIST_INTEGER (markers) + nchars);
940   if (ic->cursor_pos >= pos)
941     ic->cursor_pos += nchars;
942   ic->preedit_changed = 1;
943 }
944
945
946 static void
947 preedit_delete (MInputContext *ic, int from, int to)
948 {
949   MInputContextInfo *ic_info = ((MInputContext *) ic)->info;
950   MPlist *markers;
951
952   mtext_del (ic->preedit, from, to);
953   MPLIST_DO (markers, ic_info->markers)
954     {
955       if (MPLIST_INTEGER (markers) > to)
956         MPLIST_VAL (markers)
957           = (void *) (MPLIST_INTEGER (markers) - (to - from));
958       else if (MPLIST_INTEGER (markers) > from);
959         MPLIST_VAL (markers) = (void *) from;
960     }
961   if (ic->cursor_pos >= to)
962     ic->cursor_pos -= to - from;
963   else if (ic->cursor_pos > from)
964     ic->cursor_pos = from;
965   ic->preedit_changed = 1;
966 }
967
968
969 static int
970 new_index (MInputContext *ic, int current, int limit, MSymbol sym, MText *mt)
971 {
972   int code = marker_code (sym);
973
974   if (mt && (code == '[' || code == ']'))
975     {
976       int pos = current;
977
978       if (code == '[' && current > 0)
979         {
980           if (mtext_prop_range (mt, Mcandidate_list, pos - 1, &pos, NULL, 1)
981               && pos > 0)
982             current = pos;
983         }
984       else if (code == ']' && current < mtext_nchars (mt))
985         {
986           if (mtext_prop_range (mt, Mcandidate_list, pos, NULL, &pos, 1))
987             current = pos;
988         }
989       return current;
990     }
991   if (code >= 0)
992     return (code == '<' ? 0
993             : code == '>' ? limit
994             : code == '-' ? current - 1
995             : code == '+' ? current + 1
996             : code == '=' ? current
997             : code - '0' > limit ? limit
998             : code - '0');
999   if (! ic)  
1000     return 0;
1001   return (int) mplist_get (((MInputContextInfo *) ic->info)->markers, sym);
1002 }
1003
1004 static void
1005 update_candidate (MInputContext *ic, MTextProperty *prop, int idx)
1006 {
1007   int from = mtext_property_start (prop);
1008   int to = mtext_property_end (prop);
1009   int start;
1010   MPlist *candidate_list = mtext_property_value (prop);
1011   MPlist *group = find_candidates_group (candidate_list, idx, &start,
1012                                          NULL, NULL);
1013   int ingroup_index = idx - start;
1014   MText *mt;
1015
1016   preedit_delete (ic, from, to);
1017   if (MPLIST_MTEXT_P (group))
1018     {
1019       mt = MPLIST_MTEXT (group);
1020       preedit_insert (ic, from, NULL, mtext_ref_char (mt, ingroup_index));
1021       to = from + 1;
1022     }
1023   else
1024     {
1025       int i;
1026       MPlist *plist;
1027
1028       for (i = 0, plist = MPLIST_PLIST (group); i < ingroup_index;
1029            i++, plist = MPLIST_NEXT (plist));
1030       mt = MPLIST_MTEXT (plist);
1031       preedit_insert (ic, from, mt, 0);
1032       to = from + mtext_nchars (mt);
1033     }
1034   mtext_put_prop (ic->preedit, from, to, Mcandidate_list, candidate_list);
1035   mtext_put_prop (ic->preedit, from, to, Mcandidate_index, (void *) idx);
1036   ic->cursor_pos = to;
1037 }
1038
1039
1040 static int
1041 take_action_list (MInputContext *ic, MPlist *action_list)
1042 {
1043   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1044   MPlist *candidate_list = ic->candidate_list;
1045   int candidate_index = ic->candidate_index;
1046   int candidate_show = ic->candidate_show;
1047   MTextProperty *prop;
1048
1049   MPLIST_DO (action_list, action_list)
1050     {
1051       MPlist *action;
1052       MSymbol name;
1053       MPlist *args;
1054
1055       if (MPLIST_MTEXT_P (action_list)
1056           || MPLIST_INTEGER_P (action_list))
1057         name = Minsert, args = action_list;
1058       else if (MPLIST_PLIST_P (action_list)
1059                && (MPLIST_MTEXT_P (MPLIST_PLIST (action_list))
1060                    || MPLIST_PLIST_P (MPLIST_PLIST (action_list))))
1061         name = Minsert, args = action_list;
1062       else
1063         {
1064           action = MPLIST_PLIST (action_list);
1065           name = MPLIST_SYMBOL (action);
1066           args = MPLIST_NEXT (action);
1067         }
1068
1069       MDEBUG_PRINT1 (" %s", MSYMBOL_NAME (name));
1070       if (name == Minsert)
1071         {
1072           if (MPLIST_MTEXT_P (args))
1073             preedit_insert (ic, ic->cursor_pos, MPLIST_MTEXT (args), 0);
1074           else if (MPLIST_INTEGER_P (args))
1075             preedit_insert (ic, ic->cursor_pos, NULL, MPLIST_INTEGER (args));
1076           else if (MPLIST_SYMBOL_P (args))
1077             {
1078               int c = integer_value (ic, args);
1079
1080               if (c >= 0 && c <= MCHAR_MAX)
1081                 preedit_insert (ic, ic->cursor_pos, NULL, c);
1082             }
1083           else
1084             {
1085               MText *mt;
1086               int len;
1087
1088               args = MPLIST_PLIST (args);
1089               if (MPLIST_MTEXT_P (args))
1090                 {
1091                   preedit_insert (ic, ic->cursor_pos, NULL,
1092                                   mtext_ref_char (MPLIST_MTEXT (args), 0));
1093                   len = 1;
1094                 }
1095               else
1096                 {
1097                   mt = MPLIST_MTEXT (MPLIST_PLIST (args));
1098                   preedit_insert (ic, ic->cursor_pos, mt, 0);
1099                   len = mtext_nchars (mt);
1100                 }
1101               mtext_put_prop (ic->preedit,
1102                               ic->cursor_pos - len, ic->cursor_pos,
1103                               Mcandidate_list, args);
1104               mtext_put_prop (ic->preedit,
1105                               ic->cursor_pos - len, ic->cursor_pos,
1106                               Mcandidate_index, (void *) 0);
1107             }
1108         }
1109       else if (name == Mselect)
1110         {
1111           int start, end;
1112           int code, idx, gindex;
1113           int pos = ic->cursor_pos;
1114           MPlist *group;
1115
1116           if (pos == 0
1117               || ! (prop = mtext_get_property (ic->preedit, pos - 1,
1118                                                Mcandidate_list)))
1119             continue;
1120           if (MPLIST_SYMBOL_P (args))
1121             {
1122               code = marker_code (MPLIST_SYMBOL (args));
1123               if (code < 0)
1124                 continue;
1125             }
1126           else
1127             code = -1;
1128           idx = (int) mtext_get_prop (ic->preedit, pos - 1, Mcandidate_index);
1129           group = find_candidates_group (mtext_property_value (prop), idx,
1130                                          &start, &end, &gindex);
1131
1132           if (code != '[' && code != ']')
1133             {
1134               idx = (start
1135                      + (code >= 0
1136                         ? new_index (NULL, ic->candidate_index - start,
1137                                      end - start - 1, MPLIST_SYMBOL (args),
1138                                      NULL)
1139                         : MPLIST_INTEGER (args)));
1140               if (idx < 0)
1141                 {
1142                   find_candidates_group (mtext_property_value (prop), -1,
1143                                          NULL, &end, NULL);
1144                   idx = end - 1;
1145                 }
1146               else if (idx >= end
1147                        && MPLIST_TAIL_P (MPLIST_NEXT (group)))
1148                 idx = 0;
1149             }
1150           else
1151             {
1152               int ingroup_index = idx - start;
1153               int len;
1154
1155               group = mtext_property_value (prop);
1156               len = mplist_length (group);
1157               if (code == '[')
1158                 {
1159                   gindex--;
1160                   if (gindex < 0)
1161                     gindex = len - 1;;
1162                 }
1163               else
1164                 {
1165                   gindex++;
1166                   if (gindex >= len)
1167                     gindex = 0;
1168                 }
1169               for (idx = 0; gindex > 0; gindex--, group = MPLIST_NEXT (group))
1170                 idx += (MPLIST_MTEXT_P (group)
1171                         ? mtext_nchars (MPLIST_MTEXT (group))
1172                         : mplist_length (MPLIST_PLIST (group)));
1173               len = (MPLIST_MTEXT_P (group)
1174                      ? mtext_nchars (MPLIST_MTEXT (group))
1175                      : mplist_length (MPLIST_PLIST (group)));
1176               if (ingroup_index >= len)
1177                 ingroup_index = len - 1;
1178               idx += ingroup_index;
1179             }
1180           update_candidate (ic, prop, idx);
1181         }
1182       else if (name == Mshow)
1183         ic->candidate_show = 1;
1184       else if (name == Mhide)
1185         ic->candidate_show = 0;
1186       else if (name == Mdelete)
1187         {
1188           int len = mtext_nchars (ic->preedit);
1189           int to = (MPLIST_SYMBOL_P (args)
1190                     ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
1191                                  ic->preedit)
1192                     : MPLIST_INTEGER (args));
1193
1194           if (to < 0)
1195             to = 0;
1196           else if (to > len)
1197             to = len;
1198           if (to < ic->cursor_pos)
1199             preedit_delete (ic, to, ic->cursor_pos);
1200           else if (to > ic->cursor_pos)
1201             preedit_delete (ic, ic->cursor_pos, to);
1202         }
1203       else if (name == Mmove)
1204         {
1205           int len = mtext_nchars (ic->preedit);
1206           int pos
1207             = (MPLIST_SYMBOL_P (args)
1208                ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
1209                             ic->preedit)
1210                : MPLIST_INTEGER (args));
1211
1212           if (pos < 0)
1213             pos = 0;
1214           else if (pos > len)
1215             pos = len;
1216           if (pos != ic->cursor_pos)
1217             {
1218               ic->cursor_pos = pos;
1219               ic->preedit_changed = 1;
1220             }
1221         }
1222       else if (name == Mmark)
1223         {
1224           int code = marker_code (MPLIST_SYMBOL (args));
1225
1226           if (code < 0)
1227             mplist_put (ic_info->markers, MPLIST_SYMBOL (args),
1228                         (void *) ic->cursor_pos);
1229         }
1230       else if (name == Mpushback)
1231         {
1232           if (MPLIST_INTEGER_P (args))
1233             {
1234               int num = MPLIST_INTEGER (args);
1235
1236               if (num > 0)
1237                 ic_info->key_head -= num;
1238               else
1239                 ic_info->key_head = num;
1240               if (ic_info->key_head > ic_info->used)
1241                 ic_info->key_head = ic_info->used;
1242             }
1243           else if (MPLIST_MTEXT_P (args))
1244             {
1245               MText *mt = MPLIST_MTEXT (args);
1246               int i, len = mtext_nchars (mt);
1247               MSymbol key;
1248
1249               ic_info->key_head--;
1250               for (i = 0; i < len; i++)
1251                 {
1252                   key = one_char_symbol[MTEXT_DATA (mt)[i]];
1253                   if (ic_info->key_head < ic_info->used)
1254                     ic_info->keys[ic_info->key_head + i] = key;
1255                   else
1256                     MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
1257                 }
1258             }
1259           else
1260             {
1261               MPlist *plist = MPLIST_PLIST (args), *pl;
1262               int i = 0;
1263               MSymbol key;
1264
1265               ic_info->key_head--;
1266
1267               MPLIST_DO (pl, plist)
1268                 {
1269                   key = MPLIST_SYMBOL (pl);
1270                   if (ic_info->key_head < ic_info->used)
1271                     ic_info->keys[ic_info->key_head + i] = key;
1272                   else
1273                     MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
1274                   i++;
1275                 }
1276             }
1277         }
1278       else if (name == Mcall)
1279         {
1280           MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1281           MIMExternalFunc func = NULL;
1282           MSymbol module, func_name;
1283           MPlist *func_args, *val;
1284           int ret = 0;
1285
1286           module = MPLIST_SYMBOL (args);
1287           args = MPLIST_NEXT (args);
1288           func_name = MPLIST_SYMBOL (args);
1289
1290           if (im_info->externals)
1291             {
1292               MIMExternalModule *external
1293                 = (MIMExternalModule *) mplist_get (im_info->externals,
1294                                                     module);
1295               if (external)
1296                 func = (MIMExternalFunc) mplist_get (external->func_list,
1297                                                      func_name);
1298             }
1299           if (! func)
1300             continue;
1301           func_args = mplist ();
1302           mplist_add (func_args, Mt, ic);
1303           MPLIST_DO (args, MPLIST_NEXT (args))
1304             {
1305               int code;
1306
1307               if (MPLIST_KEY (args) == Msymbol
1308                   && MPLIST_KEY (args) != Mnil
1309                   && (code = marker_code (MPLIST_SYMBOL (args))) >= 0)
1310                 {
1311                   code = new_index (ic, ic->cursor_pos, 
1312                                     mtext_nchars (ic->preedit),
1313                                     MPLIST_SYMBOL (args), ic->preedit);
1314                   mplist_add (func_args, Minteger, (void *) code);
1315                 }
1316               else
1317                 mplist_add (func_args, MPLIST_KEY (args), MPLIST_VAL (args));
1318             }
1319           val = (func) (func_args);
1320           M17N_OBJECT_UNREF (func_args);
1321           if (val && ! MPLIST_TAIL_P (val))
1322             ret = take_action_list (ic, val);
1323           M17N_OBJECT_UNREF (val);
1324           if (ret < 0)
1325             return ret;
1326         }
1327       else if (name == Mshift)
1328         {
1329           shift_state (ic, MPLIST_SYMBOL (args));
1330         }
1331       else if (name == Mundo)
1332         {
1333           MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1334           int unhandle = 0;
1335
1336           mtext_reset (ic->preedit);
1337           mtext_reset (ic_info->preedit_saved);
1338           ic->cursor_pos = ic_info->state_pos = 0;
1339           ic_info->state_key_head = ic_info->key_head = 0;
1340           ic_info->used -= 2;
1341           if (ic_info->used < 0)
1342             {
1343               ic_info->used = 0;
1344               unhandle = 1;
1345             }
1346           shift_state (ic, ((MIMState *) MPLIST_VAL (im_info->states))->name);
1347           if (unhandle)
1348             return -1;
1349           break;
1350         }
1351       else if (name == Mset || name == Madd || name == Msub
1352                || name == Mmul || name == Mdiv)
1353         {
1354           MSymbol sym = MPLIST_SYMBOL (args);
1355           int val1 = (int) mplist_get (ic_info->vars, sym), val2;
1356
1357           args = MPLIST_NEXT (args);
1358           val2 = integer_value (ic, args);
1359           if (name == Mset)
1360             val1 = val2;
1361           else if (name == Madd)
1362             val1 += val2;
1363           else if (name == Msub)
1364             val1 -= val2;
1365           else if (name == Mmul)
1366             val1 *= val2;
1367           else
1368             val1 /= val2;
1369           mplist_put (ic_info->vars, sym, (void *) val1);
1370           MDEBUG_PRINT2 ("(%s=%d)", MSYMBOL_NAME (sym), val1);
1371         }
1372       else if (name == Mequal || name == Mless || name == Mgreater)
1373         {
1374           int val1, val2;
1375           MPlist *actions1, *actions2;
1376           int ret = 0;
1377
1378           val1 = integer_value (ic, args);
1379           args = MPLIST_NEXT (args);
1380           val2 = integer_value (ic, args);
1381           args = MPLIST_NEXT (args);
1382           actions1 = MPLIST_PLIST (args);
1383           args = MPLIST_NEXT (args);
1384           if (MPLIST_TAIL_P (args))
1385             actions2 = NULL;
1386           else
1387             actions2 = MPLIST_PLIST (args);
1388           MDEBUG_PRINT2 ("(%d,%d)", val1, val2);
1389           if (name == Mequal ? val1 == val2
1390               : name == Mless ? val1 < val2
1391               : val1 > val2)
1392             {
1393               MDEBUG_PRINT ("ok");
1394               ret = take_action_list (ic, actions1);
1395             }
1396           else
1397             {
1398               MDEBUG_PRINT ("no");
1399               if (actions2)
1400                 ret = take_action_list (ic, actions2);
1401             }
1402           if (ret < 0)
1403             return ret;
1404         }
1405       else
1406         {
1407           MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1408           MPlist *actions;
1409
1410           if (im_info->macros
1411               && (actions = mplist_get (im_info->macros, name)))
1412             {
1413               if (take_action_list (ic, actions) < 0)
1414                 return -1;
1415             };
1416         }
1417     }
1418
1419   prop = NULL;
1420   ic->candidate_list = NULL;
1421   if (ic->cursor_pos > 0
1422       && (prop = mtext_get_property (ic->preedit, ic->cursor_pos - 1,
1423                                      Mcandidate_list)))
1424     {
1425       ic->candidate_list = mtext_property_value (prop);
1426       ic->candidate_index
1427         = (int) mtext_get_prop (ic->preedit, ic->cursor_pos - 1,
1428                                 Mcandidate_index);
1429       ic->candidate_from = mtext_property_start (prop);
1430       ic->candidate_to = mtext_property_end (prop);
1431     }
1432
1433   ic->candidates_changed |= (candidate_list != ic->candidate_list
1434                              || candidate_index != ic->candidate_index
1435                              || candidate_show != ic->candidate_show);
1436   return 0;
1437 }
1438
1439
1440 /* Handle the input key KEY in the current state and map specified in
1441    the input context IC.  If KEY is handled correctly, return 0.
1442    Otherwise, return -1.  */
1443
1444 static int
1445 handle_key (MInputContext *ic)
1446 {
1447   MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1448   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1449   MIMMap *map = ic_info->map;
1450   MIMMap *submap = NULL;
1451   MSymbol key = ic_info->keys[ic_info->key_head];
1452   int i;
1453
1454   MDEBUG_PRINT2 ("[IM] handle `%s' in state %s", 
1455                  MSYMBOL_NAME (key), MSYMBOL_NAME (ic_info->state->name));
1456
1457   if (map->submaps)
1458     {
1459       submap = mplist_get (map->submaps, key);
1460       if (! submap && (key = msymbol_get (key, M_key_alias)) != Mnil)
1461         submap = mplist_get (map->submaps, key);
1462     }
1463
1464   if (submap)
1465     {
1466       MDEBUG_PRINT (" submap-found");
1467       mtext_cpy (ic->preedit, ic_info->preedit_saved);
1468       ic->cursor_pos = ic_info->state_pos;
1469       ic_info->key_head++;
1470       ic_info->map = map = submap;
1471       if (map->map_actions)
1472         {
1473           MDEBUG_PRINT (" map-actions:");
1474           if (take_action_list (ic, map->map_actions) < 0)
1475             {
1476               MDEBUG_PRINT ("\n");
1477               return -1;
1478             }
1479         }
1480       else if (map->submaps)
1481         {
1482           for (i = ic_info->state_key_head; i < ic_info->key_head; i++)
1483             {
1484               MSymbol key = ic_info->keys[i];
1485               char *name = msymbol_name (key);
1486
1487               if (! name[0] || ! name[1])
1488                 mtext_ins_char (ic->preedit, ic->cursor_pos++, name[0], 1);
1489             }
1490           ic->preedit_changed = 1;
1491         }
1492
1493       /* If this is the terminal map or we have shifted to another
1494          state, perform branch actions (if any).  */
1495       if (! map->submaps || map != ic_info->map)
1496         {
1497           if (map->branch_actions)
1498             {
1499               MDEBUG_PRINT (" branch-actions:");
1500               if (take_action_list (ic, map->branch_actions) < 0)
1501                 {
1502                   MDEBUG_PRINT ("\n");
1503                   return -1;
1504                 }
1505             }
1506           /* If MAP is still not the root map, shift to the current
1507              state.  */
1508           if (ic_info->map != ic_info->state->map)
1509             shift_state (ic, ic_info->state->name);
1510         }
1511     }
1512   else
1513     {
1514       /* MAP can not handle KEY.  */
1515
1516       /* If MAP is the root map of the initial state, it means that
1517          the current input method can not handle KEY.  */
1518       if (map == ((MIMState *) MPLIST_VAL (im_info->states))->map)
1519         {
1520           MDEBUG_PRINT (" unhandled\n");
1521           return -1;
1522         }
1523
1524       if (map != ic_info->state->map)
1525         {
1526           /* If MAP is not the root map... */
1527           /* If MAP has branch actions, perform them.  */
1528           if (map->branch_actions)
1529             {
1530               MDEBUG_PRINT (" branch-actions:");
1531               take_action_list (ic, map->branch_actions);
1532             }
1533           /* If MAP is still not the root map, shift to the current
1534              state. */
1535           if (ic_info->map != ic_info->state->map)
1536             {
1537               shift_state (ic, ic_info->state->name);
1538               /* If MAP has branch_actions, perform them.  */
1539               if (ic_info->map->branch_actions)
1540                 {
1541                   MDEBUG_PRINT (" init-actions:");
1542                   take_action_list (ic, ic_info->map->branch_actions);
1543                 }
1544             }
1545         }
1546       else
1547         {
1548           /* MAP is the root map, perform branch actions (if any) or
1549              shift to the initial state.  */
1550           if (map->branch_actions)
1551             {
1552               MDEBUG_PRINT (" branch-actions:");
1553               take_action_list (ic, map->branch_actions);
1554             }
1555           else
1556             shift_state (ic,
1557                          ((MIMState *) MPLIST_VAL (im_info->states))->name);
1558         }
1559     }
1560   MDEBUG_PRINT ("\n");
1561   return 0;
1562 }
1563
1564 static void
1565 reset_ic (MInputContext *ic, MSymbol ignore)
1566 {
1567   MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1568   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1569
1570   if (im_info->states)
1571     /* Shift to the initial state.  */
1572     shift_state (ic, Mnil);
1573   else
1574     ic_info->state = NULL;
1575   MLIST_RESET (ic_info);
1576   ic_info->map = ic_info->state ? ic_info->state->map : NULL;
1577   ic_info->state_key_head = ic_info->key_head = 0;
1578   ic_info->key_unhandled = 0;
1579   ic->cursor_pos = ic_info->state_pos = 0;
1580   ic->status = ic_info->state ? ic_info->state->title : NULL;
1581   if (! ic->status)
1582     ic->status = im_info->title;
1583   ic->candidate_list = NULL;
1584   ic->candidate_show = 0;
1585   ic->status_changed = ic->preedit_changed = ic->candidates_changed = 1;
1586 }
1587
1588 static int
1589 open_im (MInputMethod *im)
1590 {
1591   MDatabase *mdb;
1592   MInputMethodInfo *im_info;
1593   MPlist *plist;
1594   int result;
1595
1596   mdb = mdatabase_find (Minput_method, im->language, im->name, Mnil);
1597   if (! mdb)
1598     return -1;
1599   plist = mdatabase_load (mdb);
1600   if (! plist)
1601     MERROR (MERROR_IM, -1);
1602   MSTRUCT_CALLOC (im_info, MERROR_IM);
1603   im->info = im_info;
1604   result = load_input_method (im->language, im->name, plist, im_info);
1605   M17N_OBJECT_UNREF (plist);
1606   if (result < 0)
1607     MERROR (MERROR_IM, -1);
1608   return 0;
1609 }
1610
1611 static void
1612 close_im (MInputMethod *im)
1613 {
1614   MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
1615   MPlist *plist;
1616
1617   if (im_info->title)
1618     M17N_OBJECT_UNREF (im_info->title);
1619   if (im_info->states)
1620     {
1621       MPLIST_DO (plist, im_info->states)
1622         {
1623           MIMState *state = (MIMState *) MPLIST_VAL (plist);
1624
1625           if (state->title)
1626             M17N_OBJECT_UNREF (state->title);
1627           if (state->map)
1628             free_map (state->map);
1629           free (state);
1630         }
1631       M17N_OBJECT_UNREF (im_info->states);
1632     }
1633
1634   if (im_info->macros)
1635     {
1636       MPLIST_DO (plist, im_info->macros)
1637         M17N_OBJECT_UNREF (MPLIST_VAL (plist)); 
1638       M17N_OBJECT_UNREF (im_info->macros);
1639     }
1640
1641   if (im_info->externals)
1642     {
1643       MPLIST_DO (plist, im_info->externals)
1644         {
1645           MIMExternalModule *external = MPLIST_VAL (plist);
1646
1647           dlclose (external->handle);
1648           M17N_OBJECT_UNREF (external->func_list);
1649           free (external);
1650           MPLIST_KEY (plist) = Mt;
1651         }
1652       M17N_OBJECT_UNREF (im_info->externals);
1653     }
1654   free (im_info);
1655   im->info = NULL;
1656 }
1657
1658
1659 static int
1660 create_ic (MInputContext *ic)
1661 {
1662   MInputMethod *im = ic->im;
1663   MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
1664   MInputContextInfo *ic_info;
1665
1666   if (ic->info)
1667     ic_info = (MInputContextInfo *) ic->info;
1668   else
1669     {
1670       MSTRUCT_CALLOC (ic_info, MERROR_IM);
1671       ic->info = ic_info;
1672     }
1673   MLIST_INIT1 (ic_info, keys, 8);
1674   ic_info->markers = mplist ();
1675   ic_info->vars = mplist ();
1676   ic_info->preedit_saved = mtext ();
1677   if (im_info->externals)
1678     {
1679       MPlist *func_args = mplist (), *plist;
1680
1681       mplist_add (func_args, Mt, ic);
1682       MPLIST_DO (plist, im_info->externals)
1683         {
1684           MIMExternalModule *external = MPLIST_VAL (plist);
1685           MIMExternalFunc func
1686             = (MIMExternalFunc) mplist_get (external->func_list, Minit);
1687
1688           if (func)
1689             (func) (func_args);
1690         }
1691       M17N_OBJECT_UNREF (func_args);
1692     }
1693   reset_ic (ic, Mnil);
1694   return 0;
1695 }
1696
1697 static void
1698 destroy_ic (MInputContext *ic)
1699 {
1700   MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1701   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1702
1703   if (im_info->externals)
1704     {
1705       MPlist *func_args = mplist (), *plist;
1706
1707       mplist_add (func_args, Mt, ic);
1708       MPLIST_DO (plist, im_info->externals)
1709         {
1710           MIMExternalModule *external = MPLIST_VAL (plist);
1711           MIMExternalFunc func
1712             = (MIMExternalFunc) mplist_get (external->func_list, Mfini);
1713
1714           if (func)
1715             (func) (func_args);
1716         }
1717       M17N_OBJECT_UNREF (func_args);
1718     }
1719   MLIST_FREE1 (ic_info, keys);
1720   M17N_OBJECT_UNREF (ic_info->preedit_saved);
1721   M17N_OBJECT_UNREF (ic_info->markers);
1722   M17N_OBJECT_UNREF (ic_info->vars);
1723   free (ic->info);
1724 }
1725
1726
1727 /** Handle the input key KEY in the current state and map of IC->info.
1728     If KEY is handled but no text is produced, return 0, otherwise
1729     return 1.
1730
1731     Ignore ARG.  */
1732
1733 static int
1734 filter (MInputContext *ic, MSymbol key, void *arg)
1735 {
1736   MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1737   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1738   int i = 0;
1739
1740   if (! ic_info->state)
1741     {
1742       ic_info->key_unhandled = 1;
1743       return 0;
1744     }
1745   mtext_reset (ic->produced);
1746   ic->status_changed = ic->preedit_changed = ic->candidates_changed = 0;
1747   MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
1748   ic_info->key_unhandled = 0;
1749   do {
1750     if (handle_key (ic) < 0)
1751       {
1752         /* KEY was not handled.  Reset the status and break the
1753            loop.  */
1754         reset_ic (ic, Mnil);
1755         /* This forces returning 1.  */
1756         ic_info->key_unhandled = 1;
1757         break;
1758       }
1759     if (i++ == 100)
1760       {
1761         mdebug_hook ();
1762         reset_ic (ic, Mnil);
1763         ic_info->key_unhandled = 1;
1764         break;
1765       }
1766     /* Break the loop if all keys were handled.  */
1767   } while (ic_info->key_head < ic_info->used);
1768
1769   /* If the current map is the root of the initial state, we should
1770      produce any preedit text in ic->produced.  */
1771   if (ic_info->map == ((MIMState *) MPLIST_VAL (im_info->states))->map
1772       && mtext_nchars (ic->preedit) > 0)
1773     shift_state (ic, ((MIMState *) MPLIST_VAL (im_info->states))->name);
1774
1775   if (mtext_nchars (ic->produced) > 0)
1776     {
1777       MSymbol lang = msymbol_get (ic->im->language, Mlanguage);
1778
1779       if (lang != Mnil)
1780         mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
1781                         Mlanguage, ic->im->language);
1782     }
1783
1784   return (! ic_info->key_unhandled && mtext_nchars (ic->produced) == 0);
1785 }
1786
1787
1788 /** Return 1 if the last event or key was not handled, otherwise
1789     return 0.
1790
1791     There is no need of looking up because ic->produced should already
1792     contain the produced text (if any).
1793
1794     Ignore KEY.  */
1795
1796 static int
1797 lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
1798 {
1799   mtext_cat (mt, ic->produced);
1800   mtext_reset (ic->produced);
1801   return (((MInputContextInfo *) ic->info)->key_unhandled ? -1 : 0);
1802 }
1803
1804 static MPlist *load_im_info_keys;
1805
1806 static MPlist *
1807 load_im_info (MSymbol language, MSymbol name, MSymbol key)
1808 {
1809   MDatabase *mdb;
1810   MPlist *plist;
1811
1812   if (language == Mnil || name == Mnil)
1813     MERROR (MERROR_IM, NULL);
1814
1815   mdb = mdatabase_find (Minput_method, language, name, Mnil);
1816   if (! mdb)
1817     MERROR (MERROR_IM, NULL);
1818   mplist_push (load_im_info_keys, key, Mt);
1819   plist = mdatabase__load_for_keys (mdb, load_im_info_keys);
1820   mplist_pop (load_im_info_keys);
1821   return plist;
1822 }
1823
1824 \f
1825 /* Input method command handler.  */
1826
1827 /* List of all (global and local) commands. 
1828    (LANG:(IM-NAME:(COMMAND ...) ...) ...) ...
1829    COMMAND is CMD-NAME:(mtext:DESCRIPTION plist:KEYSEQ ...))
1830    Global commands are storead as (t (t COMMAND ...))  */
1831 static MPlist *command_list;
1832
1833 /* Check if PLIST is a valid command key sequence.
1834    PLIST must be NULL or:
1835    [ symbol:KEY | integer:KEY ] ...  */
1836
1837 static int
1838 check_command_keyseq (MPlist *plist)
1839 {
1840   if (! plist)
1841     return 0;
1842   MPLIST_DO (plist, plist)
1843     {
1844       if (MPLIST_SYMBOL_P (plist))
1845         continue;
1846       else if (MPLIST_INTEGER_P (plist))
1847         {
1848           int n = MPLIST_INTEGER (plist);
1849
1850           if (n < 0 || n > 9)
1851             return -1;
1852           MPLIST_KEY (plist) = Msymbol;
1853           MPLIST_VAL (plist) = one_char_symbol['0' + 9];
1854         }
1855       else
1856         return -1;
1857     }
1858   return 0;
1859 }
1860
1861 static MText *
1862 get_description_advance (MPlist *plist)
1863 {
1864   MText *mt;
1865   int pos;
1866
1867   if (! MPLIST_MTEXT_P (plist))
1868     return NULL;
1869   mt = mplist_pop (plist);
1870   pos = mtext_chr (mt, '\n'); 
1871   if (pos > 0)
1872     {
1873       MText *detail = mtext_copy (mtext (), 0, mt, pos + 1, mtext_nchars (mt));
1874       mtext_del (mt, pos, mtext_nchars (mt));
1875       mtext_put_prop (mt, 0, pos, Mdetail_text, detail);
1876       M17N_OBJECT_UNREF (detail);
1877     }
1878   return mt;
1879 }
1880
1881 static MPlist *
1882 parse_command_list (MPlist *plist, MPlist *global_list)
1883 {
1884   MPlist *val = mplist ();
1885
1886   /* PLIST ::= (sym:CMD mtext:DESCRIPTION ? (sym:KEY ...) ...) ... */
1887   MPLIST_DO (plist, plist)
1888     {
1889       MSymbol cmd;
1890       MText *mt;
1891       MPlist *this_val, *pl, *p;
1892
1893       if (! MPLIST_PLIST_P (plist))
1894         continue;
1895       pl = MPLIST_PLIST (plist);
1896       if (! MPLIST_SYMBOL_P (pl))
1897         continue;
1898       cmd = MPLIST_SYMBOL (pl);
1899       pl = MPLIST_NEXT (pl);
1900       mt = get_description_advance (pl);
1901       this_val = mplist ();
1902
1903       if (! mt && global_list)
1904         {
1905           /* Get the description from global_list.  */
1906           p = mplist_get (global_list, cmd);
1907           if (p && MPLIST_MTEXT (p))
1908             {
1909               mt = MPLIST_MTEXT (p);
1910               M17N_OBJECT_REF (mt);
1911             }
1912         }
1913       if (! mt)
1914         mt = mtext ();
1915       mplist_add (this_val, Mtext, mt);
1916       M17N_OBJECT_UNREF (mt);
1917
1918       /* PL ::= (sym:KEY ...) ... */
1919       MPLIST_DO (pl, pl)
1920         {
1921           if (MPLIST_PLIST_P (pl)
1922               && check_command_keyseq (MPLIST_PLIST (pl)) >= 0)
1923             /* All the elements are valid keys.  */
1924             mplist_add (this_val, Mplist, MPLIST_PLIST (pl));
1925         }
1926
1927       mplist_put (val, cmd, this_val);
1928     }
1929   return val;
1930 }
1931
1932 static MPlist *
1933 get_command_list (MSymbol language, MSymbol name)
1934 {
1935   MPlist *per_lang;
1936   MPlist *plist, *pl;
1937
1938   if (name == Mnil)
1939     language = name = Mt;
1940
1941   if (! command_list)
1942     {
1943       MDatabase *mdb = mdatabase_find (msymbol ("input"), M_command,
1944                                        Mnil, Mnil);
1945
1946       if (mdb && (plist = mdatabase_load (mdb)))
1947         {
1948           pl = parse_command_list (plist, NULL);
1949           M17N_OBJECT_UNREF (plist);
1950         }
1951       else
1952         pl = mplist ();
1953       plist = mplist ();
1954       mplist_add (plist, Mt, pl);
1955       command_list = mplist ();
1956       mplist_add (command_list, Mt, plist);
1957     }
1958
1959   per_lang = mplist_get (command_list, language);
1960   if (per_lang)
1961     {
1962       plist = mplist_find_by_key (per_lang, name);
1963       if (plist)
1964         return (MPLIST_VAL (plist));
1965     }
1966   else
1967     {
1968       per_lang = mplist ();
1969       mplist_add (command_list, language, per_lang);
1970     }
1971
1972   /* Now we are sure that we are loading per-im info.  */
1973   /* Get the global command list.  */
1974   plist = load_im_info (language, name, M_command);
1975   if (! plist || mplist_key (plist) == Mnil)
1976     {
1977       if (! plist)
1978         plist = mplist ();
1979       mplist_add (per_lang, name, plist);
1980       return plist;
1981     }
1982   pl = parse_command_list (mplist_value (plist),
1983                            mplist_get ((MPlist *) mplist_get (command_list, Mt),
1984                                        Mt));
1985   M17N_OBJECT_UNREF (plist);
1986   mplist_put (per_lang, name, pl);
1987   return pl;
1988 }
1989
1990 \f
1991 /* Input method variable handler.  */
1992
1993 /* List of all variables. 
1994    (LANG:(IM-NAME:(VAR ...) ...) ...) ...
1995    VAR is VAR-NAME:(mtext:DESCRIPTION TYPE:VALUE ...))  */
1996
1997 static MPlist *variable_list;
1998
1999 static MPlist *
2000 parse_variable_list (MPlist *plist)
2001 {
2002   MPlist *val = mplist (), *pl, *p;
2003
2004   /* PLIST ::= (sym:VAR mtext:DESCRIPTION TYPE:INIT-VAL ...) ...  */
2005   MPLIST_DO (plist, plist)
2006     {
2007       MSymbol var, type;
2008       MText *mt;
2009       MPlist *this_val;
2010
2011       if (! MPLIST_PLIST_P (plist))
2012         continue;
2013       pl = MPLIST_PLIST (plist);
2014       if (! MPLIST_SYMBOL_P (pl))
2015         continue;
2016       var = MPLIST_SYMBOL (pl);
2017       pl = MPLIST_NEXT (pl);
2018       mt = get_description_advance (pl);
2019       if (! mt || MPLIST_TAIL_P (pl))
2020         continue;
2021       this_val = mplist ();
2022       mplist_add (this_val, Mtext, mt);
2023       M17N_OBJECT_UNREF (mt);
2024       type = MPLIST_KEY (pl);
2025       mplist_add (this_val, type, MPLIST_VAL (pl));
2026       MPLIST_DO (pl, MPLIST_NEXT (pl))
2027         {
2028           if (type != MPLIST_KEY (pl)
2029               && (type != Minteger || ! MPLIST_PLIST_P (pl)))
2030             break;
2031           if (MPLIST_PLIST_P (pl))
2032             {
2033               MPLIST_DO (p, MPLIST_PLIST (pl))
2034                 if (! MPLIST_INTEGER_P (p))
2035                   break;
2036               if (! MPLIST_TAIL_P (p))
2037                 break;
2038             }
2039           mplist_add (this_val, MPLIST_KEY (pl), MPLIST_VAL (pl));
2040         }
2041
2042       mplist_put (val, var, this_val);
2043     }
2044   return val;
2045 }
2046
2047
2048 static MPlist *
2049 get_variable_list (MSymbol language, MSymbol name)
2050 {
2051   MPlist *per_lang;
2052   MPlist *plist, *pl;
2053
2054   if (language == Mnil || name == Mnil)
2055     MERROR (MERROR_IM, NULL);
2056   if (! variable_list)
2057     variable_list = mplist ();
2058   per_lang = mplist_get (variable_list, language);
2059   if (per_lang)
2060     {
2061       plist = mplist_find_by_key (per_lang, name);
2062       if (plist)
2063         return (MPLIST_VAL (plist));
2064     }
2065   else
2066     {
2067       per_lang = mplist ();
2068       mplist_add (variable_list, language, per_lang);
2069     }
2070   plist = load_im_info (language, name, M_variable);
2071   if (! plist || mplist_key (plist) == Mnil)
2072     {
2073       if (! plist)
2074         plist = mplist ();
2075       mplist_add (per_lang, name, plist);
2076       return plist;
2077     }
2078   pl = parse_variable_list (mplist_value (plist));
2079   M17N_OBJECT_UNREF (plist);
2080   mplist_put (per_lang, name, pl);
2081   return pl;
2082 }
2083
2084 static void
2085 input_method_hook (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
2086 {
2087   MPlist *plist, *pl, *p;
2088   char path[PATH_MAX];
2089
2090   /* Cancel the hook.  */
2091   msymbol_put (tag0, M_database_hook, NULL);
2092   tag3 = Mnil;
2093
2094   mplist_push (load_im_info_keys, M_description, Mt);
2095   MPLIST_DO (plist, mdatabase__dir_list)
2096     {
2097       char *dirname = (char *) MPLIST_VAL (plist);
2098       int dirlen;
2099       DIR *dir = opendir (dirname);
2100       struct dirent *dp;
2101
2102       if (! dir)
2103         continue;
2104       dirlen = strlen (dirname);
2105       strcpy (path, dirname);
2106       while ((dp = readdir (dir)) != NULL)
2107         {
2108           /* We can't trust dp->d_nameln.  */
2109           int len = strlen (dp->d_name);
2110           FILE *fp;
2111
2112           if (len > 4 && memcmp (dp->d_name + len - 4, ".mim", 4) == 0)
2113             {
2114               strcpy (path + dirlen, dp->d_name);
2115               fp = fopen (path, "r");
2116               if (! fp)
2117                 continue;
2118               pl = mplist__from_file (fp, load_im_info_keys);
2119               fclose (fp);
2120               if (pl)
2121                 {
2122                   if (MPLIST_PLIST_P (pl))
2123                     {
2124                       p = MPLIST_PLIST (pl);
2125                       p = MPLIST_NEXT (p);
2126                       if (MPLIST_SYMBOL_P (p))
2127                         {
2128                           tag1 = MPLIST_VAL (p);
2129                           p = MPLIST_NEXT (p);
2130                           if (MPLIST_SYMBOL_P (p))
2131                             {
2132                               tag2 = MPLIST_VAL (p);
2133                               mdatabase_define (tag0, tag1, tag2, tag3,
2134                                                 NULL, path);
2135                             }
2136                         }
2137                     }
2138                   M17N_OBJECT_UNREF (pl);
2139                 }
2140             }
2141         }
2142       closedir (dir);
2143     }
2144   mplist_pop (load_im_info_keys);
2145 }
2146
2147
2148 /* Support functions for mdebug_dump_im.  */
2149
2150 static void
2151 dump_im_map (MPlist *map_list, int indent)
2152 {
2153   char *prefix;
2154   MSymbol key = MPLIST_KEY (map_list);
2155   MIMMap *map = (MIMMap *) MPLIST_VAL (map_list);
2156
2157   prefix = (char *) alloca (indent + 1);
2158   memset (prefix, 32, indent);
2159   prefix[indent] = '\0';
2160
2161   fprintf (stderr, "(\"%s\" ", msymbol_name (key));
2162   if (map->map_actions)
2163     mdebug_dump_plist (map->map_actions, indent + 2);
2164   if (map->submaps)
2165     {
2166       MPLIST_DO (map_list, map->submaps)
2167         {
2168           fprintf (stderr, "\n%s  ", prefix);
2169           dump_im_map (map_list, indent + 2);
2170         }
2171     }
2172   if (map->branch_actions)
2173     {
2174       fprintf (stderr, "\n%s  (branch\n%s    ", prefix, prefix);
2175       mdebug_dump_plist (map->branch_actions, indent + 4);
2176       fprintf (stderr, ")");      
2177     }
2178   fprintf (stderr, ")");
2179 }
2180
2181
2182 static void
2183 dump_im_state (MIMState *state, int indent)
2184 {
2185   char *prefix;
2186   MPlist *map_list;
2187
2188   prefix = (char *) alloca (indent + 1);
2189   memset (prefix, 32, indent);
2190   prefix[indent] = '\0';
2191
2192   fprintf (stderr, "(%s", msymbol_name (state->name));
2193   if (state->map->submaps)
2194     {
2195       MPLIST_DO (map_list, state->map->submaps)
2196         {
2197           fprintf (stderr, "\n%s  ", prefix);
2198           dump_im_map (map_list, indent + 2);
2199         }
2200     }
2201   fprintf (stderr, ")");
2202 }
2203
2204 \f
2205
2206 int
2207 minput__init ()
2208 {
2209   char *key_names[32]
2210     = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2211         "BackSpace", "Tab", "Linefeed", "Clear", NULL, "Return", NULL, NULL,
2212         NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2213         NULL, NULL, NULL, "Escape", NULL, NULL, NULL, NULL };
2214   char buf[6], buf2[256];
2215   int i;
2216   MPlist *plist;
2217
2218   Minput_method = msymbol ("input-method");
2219   msymbol_put (Minput_method, M_database_hook, (void *) input_method_hook);
2220   Minput_driver = msymbol ("input-driver");
2221   Mtitle = msymbol ("title");
2222   Mmacro = msymbol ("macro");
2223   Mmodule = msymbol ("module");
2224   Mmap = msymbol ("map");
2225   Mstate = msymbol ("state");
2226   Minsert = msymbol ("insert");
2227   Mdelete = msymbol ("delete");
2228   Mmove = msymbol ("move");
2229   Mmark = msymbol ("mark");
2230   Mpushback = msymbol ("pushback");
2231   Mundo = msymbol ("undo");
2232   Mcall = msymbol ("call");
2233   Mshift = msymbol ("shift");
2234   Mselect = msymbol ("select");
2235   Mshow = msymbol ("show");
2236   Mhide = msymbol ("hide");
2237   Mset = msymbol ("set");
2238   Madd = msymbol ("add");
2239   Msub = msymbol ("sub");
2240   Mmul = msymbol ("mul");
2241   Mdiv = msymbol ("div");
2242   Mequal = msymbol ("=");
2243   Mless = msymbol ("<");
2244   Mgreater = msymbol (">");
2245
2246   Minput_preedit_start = msymbol ("input-preedit-start");
2247   Minput_preedit_done = msymbol ("input-preedit-done");
2248   Minput_preedit_draw = msymbol ("input-preedit-draw");
2249   Minput_status_start = msymbol ("input-status-start");
2250   Minput_status_done = msymbol ("input-status-done");
2251   Minput_status_draw = msymbol ("input-status-draw");
2252   Minput_candidates_start = msymbol ("input-candidates-start");
2253   Minput_candidates_done = msymbol ("input-candidates-done");
2254   Minput_candidates_draw = msymbol ("input-candidates-draw");
2255   Minput_set_spot = msymbol ("input-set-spot");
2256   Minput_toggle = msymbol ("input-toggle");
2257   Minput_reset = msymbol ("input-reset");
2258
2259   Mcandidate_list = msymbol_as_managing_key ("  candidate-list");
2260   Mcandidate_index = msymbol ("  candidate-index");
2261
2262   Minit = msymbol ("init");
2263   Mfini = msymbol ("fini");
2264
2265   M_key_alias = msymbol ("  key-alias");
2266   M_description = msymbol ("description");
2267   M_command = msymbol ("command");
2268   M_variable = msymbol ("variable");
2269
2270   Mdetail_text = msymbol_as_managing_key ("  detail-text");
2271
2272   load_im_info_keys = mplist ();
2273   plist = mplist_add (load_im_info_keys, Mmap, Mnil);
2274   plist = mplist_add (plist, Mstate, Mnil);
2275   plist = mplist_add (plist, Mmacro, Mnil);
2276   plist = mplist_add (plist, Mmodule, Mnil);
2277
2278   buf[0] = 'C';
2279   buf[1] = '-';
2280   buf[3] = '\0';
2281   for (i = 0, buf[2] = '@'; i < ' '; i++, buf[2]++)
2282     {
2283       one_char_symbol[i] = msymbol (buf);
2284       if (key_names[i])
2285         msymbol_put (one_char_symbol[i], M_key_alias,  msymbol (key_names[i]));
2286     }
2287   for (buf[2] = i; i < 127; i++, buf[2]++)
2288     one_char_symbol[i] = msymbol (buf + 2);
2289   one_char_symbol[i++] = msymbol ("Delete");
2290   buf[2] = 'M';
2291   buf[3] = '-';
2292   buf[5] = '\0';
2293   buf2[0] = 'M';
2294   buf2[1] = '-';
2295   for (buf[4] = '@'; i < 160; i++, buf[4]++)
2296     {
2297       one_char_symbol[i] = msymbol (buf);
2298       if (key_names[i - 128])
2299         {
2300           strcpy (buf2 + 2, key_names[i - 128]);
2301           msymbol_put (one_char_symbol[i], M_key_alias,  msymbol (buf2));
2302         }
2303     }
2304   for (buf[4] = i - 128; i < 255; i++, buf[4]++)
2305     one_char_symbol[i] = msymbol (buf + 2);
2306   one_char_symbol[i] = msymbol ("M-Delete");
2307
2308   command_list = variable_list = NULL;
2309
2310   minput_default_driver.open_im = open_im;
2311   minput_default_driver.close_im = close_im;
2312   minput_default_driver.create_ic = create_ic;
2313   minput_default_driver.destroy_ic = destroy_ic;
2314   minput_default_driver.filter = filter;
2315   minput_default_driver.lookup = lookup;
2316   minput_default_driver.callback_list = mplist ();
2317   mplist_put (minput_default_driver.callback_list, Minput_reset,
2318               (void *) reset_ic);
2319   minput_driver = &minput_default_driver;
2320   return 0;
2321 }
2322
2323 void
2324 minput__fini ()
2325 {
2326   MPlist *par_lang, *par_im, *p;
2327
2328   if (command_list)
2329     {
2330       MPLIST_DO (par_lang, command_list)
2331         {
2332           MPLIST_DO (par_im, MPLIST_VAL (par_lang))
2333             {
2334               MPLIST_DO (p, MPLIST_VAL (par_im))
2335                 M17N_OBJECT_UNREF (MPLIST_VAL (p));
2336               M17N_OBJECT_UNREF (MPLIST_VAL (par_im));
2337             }
2338           M17N_OBJECT_UNREF (MPLIST_VAL (par_lang));
2339         }
2340       M17N_OBJECT_UNREF (command_list);
2341       command_list = NULL;
2342     }
2343   if (variable_list)
2344     {
2345       MPLIST_DO (par_lang, variable_list)
2346         {
2347           MPLIST_DO (par_im, MPLIST_VAL (par_lang))
2348             {
2349               MPLIST_DO (p, MPLIST_VAL (par_im))
2350                 M17N_OBJECT_UNREF (MPLIST_VAL (p));
2351               M17N_OBJECT_UNREF (MPLIST_VAL (par_im));
2352             }
2353           M17N_OBJECT_UNREF (MPLIST_VAL (par_lang));
2354         }
2355       M17N_OBJECT_UNREF (variable_list);
2356       variable_list = NULL;
2357     }
2358
2359   if (minput_default_driver.callback_list)
2360     {
2361       M17N_OBJECT_UNREF (minput_default_driver.callback_list);
2362       minput_default_driver.callback_list = NULL;
2363     }
2364   if (minput_driver->callback_list)
2365     {
2366       M17N_OBJECT_UNREF (minput_driver->callback_list);
2367       minput_driver->callback_list = NULL;
2368     }
2369
2370   M17N_OBJECT_UNREF (load_im_info_keys);
2371 }
2372
2373 void
2374 minput__callback (MInputContext *ic, MSymbol command)
2375 {
2376   if (ic->im->driver.callback_list)
2377     {
2378       MInputCallbackFunc func
2379         = (MInputCallbackFunc) mplist_get (ic->im->driver.callback_list,
2380                                            command);
2381
2382       if (func)
2383         (func) (ic, command);
2384     }
2385 }
2386
2387 MSymbol
2388 minput__char_to_key (int c)
2389 {
2390   if (c < 0 || c >= 0x100)
2391     return Mnil;
2392
2393   return one_char_symbol[c];
2394 }
2395
2396 /*** @} */
2397 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
2398
2399 \f
2400 /* External API */
2401
2402 /*** @addtogroup m17nInputMethod */
2403 /*** @{ */
2404 /*=*/
2405
2406 /***en
2407     @name Variables: Predefined symbols for callback commands.
2408
2409     These are the predefined symbols that are used as the @c COMMAND
2410     argument of callback functions of an input method driver (see
2411     #MInputDriver::callback_list ).  */ 
2412 /***ja
2413     @name ÊÑ¿ô¡§ ¥³¡¼¥ë¥Ð¥Ã¥¯¥³¥Þ¥ó¥ÉÍÑÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë.
2414
2415     ÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Î¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Ë¤ª¤¤¤Æ @c COMMAND 
2416     °ú¿ô¤È¤·¤ÆÍѤ¤¤é¤ì¤ëÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë (#MInputDriver::callback_list »²¾È)¡£
2417       */ 
2418 /*** @{ */ 
2419 /*=*/
2420
2421 MSymbol Minput_preedit_start;
2422 MSymbol Minput_preedit_done;
2423 MSymbol Minput_preedit_draw;
2424 MSymbol Minput_status_start;
2425 MSymbol Minput_status_done;
2426 MSymbol Minput_status_draw;
2427 MSymbol Minput_candidates_start;
2428 MSymbol Minput_candidates_done;
2429 MSymbol Minput_candidates_draw;
2430 MSymbol Minput_set_spot;
2431 MSymbol Minput_toggle;
2432 MSymbol Minput_reset;
2433 /*** @} */
2434 /*=*/
2435
2436 /***en
2437     @brief The default driver for internal input methods.
2438
2439     The variable #minput_default_driver is the default driver for
2440     internal input methods.
2441
2442     The member MInputDriver::open_im () searches the m17n database for
2443     an input method that matches the tag \< #Minput_method, $LANGUAGE,
2444     $NAME\> and loads it.
2445
2446     The member MInputDriver::callback_list () is @c NULL.  Thus, it is
2447     programmers responsibility to set it to a plist of proper callback
2448     functions.  Otherwise, no feedback information (e.g. preedit text)
2449     can be shown to users.
2450
2451     The macro M17N_INIT () sets the variable #minput_driver to the
2452     pointer to this driver so that all internal input methods use it.
2453
2454     Therefore, unless @c minput_driver is set differently, the driver
2455     dependent arguments $ARG of the functions whose name begin with
2456     "minput_" are all ignored.  */
2457
2458 /***ja
2459     @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥǥե©¥ë¥È¥É¥é¥¤¥Ð.
2460
2461     ÊÑ¿ô #minput_default_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѤΥǥե©¥ë¥È¤Î¥É¥é¥¤¥Ð¤òɽ¤¹¡£
2462
2463     ¥á¥ó¥Ð MInputDriver::open_im () ¤Ï m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹Ã椫¤é¥¿¥° 
2464     \< #Minput_method, $LANGUAGE, $NAME\> 
2465     ¤Ë¹çÃפ¹¤ëÆþÎϥ᥽¥Ã¥É¤òõ¤·¡¢¤½¤ì¤ò¥í¡¼¥É¤¹¤ë¡£
2466
2467     ¥á¥ó¥Ð MInputDriver::callback_list () ¤Ï @c NULL ¤Ç¤¢¤ê¡¢
2468     ¤·¤¿¤¬¤Ã¤Æ¡¢¥×¥í¥°¥é¥Þ¦¤ÇÀÕǤ¤ò»ý¤Ã¤Æ Å¬Àڤʥ³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Î plist
2469     ¤ËÀßÄꤷ¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¤µ¤â¤Ê¤¤¤È¡¢preedit 
2470     ¥Æ¥­¥¹¥È¤Ê¤É¤Î¥Õ¥£¡¼¥É¥Ð¥Ã¥¯¾ðÊ󤬥桼¥¶¤Ëɽ¼¨¤µ¤ì¤Ê¤¤¡£
2471
2472     ¥Þ¥¯¥í M17N_INIT () ¤ÏÊÑ¿ô #minput_driver 
2473     ¤ò¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤ËÀßÄꤷ¡¢Á´¤Æ¤ÎÆâÉôÆþÎϥ᥽¥Ã¥É¤¬¤³¤Î¥É¥é¥¤¥Ð¤ò»È¤¦¤è¤¦¤Ë¤¹¤ë¡£
2474
2475     ¤·¤¿¤¬¤Ã¤Æ¡¢@c minput_driver ¤¬¥Ç¥Õ¥©¥ë¥ÈÃͤΤޤޤǤ¢¤ì¤Ð¡¢minput_ 
2476     ¤Ç»Ï¤Þ¤ë´Ø¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô $ARG ¤Ï¤¹¤Ù¤Æ̵»ë¤µ¤ì¤ë¡£  */
2477
2478 MInputDriver minput_default_driver;
2479 /*=*/
2480
2481 /***en
2482     @brief The driver for internal input methods.
2483
2484     The variable #minput_driver is a pointer to the input method
2485     driver that is used by internal input methods.  The macro
2486     M17N_INIT () initializes it to a pointer to #minput_default_driver
2487     if <m17n<EM></EM>.h> is included.  */ 
2488 /***ja
2489     @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥɥ饤¥Ð.
2490
2491     ÊÑ¿ô #minput_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤Æ»ÈÍѤµ¤ì¤Æ¤¤¤ëÆþÎÏ¥á
2492     ¥½¥Ã¥É¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£¥Þ¥¯¥í M17N_INIT () ¤Ï¤³¤Î¥Ý¥¤¥ó
2493     ¥¿¤ò#minput_default_driver (<m17n<EM></EM>.h> ¤¬ include ¤µ¤ì¤Æ¤¤¤ë
2494     »þ) ¤Ë½é´ü²½¤¹¤ë¡£  */ 
2495
2496 MInputDriver *minput_driver;
2497
2498 MSymbol Minput_driver;
2499
2500 /*=*/
2501
2502 /***en
2503     @brief Open an input method.
2504
2505     The minput_open_im () function opens an input method that matches
2506     language $LANGUAGE and name $NAME, and returns a pointer to the
2507     input method object newly allocated.
2508
2509     This function at first decides an driver for the input method as
2510     below.
2511
2512     If $LANGUAGE is not #Mnil, the driver pointed by the variable
2513     #minput_driver is used.
2514
2515     If $LANGUAGE is #Mnil and $NAME has #Minput_driver property, the
2516     driver pointed to by the property value is used to open the input
2517     method.  If $NAME has no such property, @c NULL is returned.
2518
2519     Then, the member MInputDriver::open_im () of the driver is
2520     called.  
2521
2522     $ARG is set in the member @c arg of the structure MInputMethod so
2523     that the driver can refer to it.  */
2524
2525 /***ja
2526     @brief ÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë.
2527
2528     ´Ø¿ô minput_open_im () ¤Ï¸À¸ì $LANGUAGE ¤È̾Á° $NAME 
2529     ¤Ë¹çÃפ¹¤ëÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤·¡¢¿·¤¿¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿ÆþÎϥ᥽¥Ã¥É¥ª¥Ö¥¸¥§¥¯¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
2530     
2531     ¤³¤Î´Ø¿ô¤Ï¡¢¤Þ¤ºÆþÎϥ᥽¥Ã¥ÉÍѤΥɥ饤¥Ð¤ò°Ê²¼¤Î¤è¤¦¤Ë¤·¤Æ·èÄꤹ¤ë¡£
2532
2533     $LANGUAGE ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢ÊÑ¿ô #minput_driver 
2534     ¤Ç»Ø¤µ¤ì¤Æ¤¤¤ë¥É¥é¥¤¥Ð¤òÍѤ¤¤ë¡£
2535
2536     $LANGUAGE ¤¬ #Mnil ¤Ç¤¢¤ê¡¢$NAME ¤¬ #Minput_driver
2537     ¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä¾ì¹ç¤Ë¤Ï¡¢¤½¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤǻؤµ¤ì¤Æ¤¤¤ëÆþÎϥɥ饤¥Ð¤òÍѤ¤¤ÆÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë¡£
2538     $NAME ¤Ë¤½¤Î¤è¤¦¤Ê¥×¥í¥Ñ¥Æ¥£¤¬Ìµ¤«¤Ã¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
2539
2540     ¼¡¤¤¤Ç¡¢¥É¥é¥¤¥Ð¤Î¥á¥ó¥Ð MInputDriver::open_im () ¤¬¸Æ¤Ð¤ì¤ë¡£
2541
2542     $ARG ¤Ï¹½Â¤ÂΠMInputMethod ¤Î¥á¥ó¥Ð @c arg ¤ËÀßÄꤵ¤ì¡¢¥É¥é¥¤¥Ð¤«¤é»²¾È¤Ç¤­¤ë¡£
2543
2544     @latexonly \IPAlabel{minput_open} @endlatexonly
2545
2546 */
2547
2548 MInputMethod *
2549 minput_open_im (MSymbol language, MSymbol name, void *arg)
2550 {
2551   MInputMethod *im;
2552   MInputDriver *driver;
2553
2554   MDEBUG_PRINT2 ("[IM] opening (%s %s) ... ",
2555          msymbol_name (language), msymbol_name (name));
2556   if (language)
2557     driver = minput_driver;
2558   else
2559     {
2560       driver = (MInputDriver *) msymbol_get (name, Minput_driver);
2561       if (! driver)
2562         MERROR (MERROR_IM, NULL);
2563     }
2564
2565   MSTRUCT_CALLOC (im, MERROR_IM);
2566   im->language = language;
2567   im->name = name;
2568   im->arg = arg;
2569   im->driver = *driver;
2570   if ((*im->driver.open_im) (im) < 0)
2571     {
2572       MDEBUG_PRINT (" failed\n");
2573       free (im);
2574       return NULL;
2575     }
2576   MDEBUG_PRINT (" ok\n");
2577   return im;
2578 }
2579
2580 /*=*/
2581
2582 /***en
2583     @brief Close an input method.
2584
2585     The minput_close_im () function closes the input method $IM, which
2586     must have been created by minput_open_im ().  */
2587
2588 /***ja
2589     @brief ÆþÎϥ᥽¥Ã¥É¤ò¥¯¥í¡¼¥º¤¹¤ë.
2590
2591     ´Ø¿ô minput_close_im () ¤Ï¡¢ÆþÎϥ᥽¥Ã¥É $IM ¤ò¥¯¥í¡¼¥º¤¹¤ë¡£
2592     ¤³¤ÎÆþÎϥ᥽¥Ã¥É $IM ¤Ï minput_open_im () ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£  */
2593
2594 void
2595 minput_close_im (MInputMethod *im)
2596 {
2597   MDEBUG_PRINT2 ("[IM] closing (%s %s) ... ",
2598                  msymbol_name (im->name), msymbol_name (im->language));
2599   (*im->driver.close_im) (im);
2600   free (im);
2601   MDEBUG_PRINT (" done\n");
2602 }
2603
2604 /*=*/
2605
2606 /***en
2607     @brief Create an input context.
2608
2609     The minput_create_ic () function creates an input context object
2610     associated with input method $IM, and calls callback functions
2611     corresponding to #Minput_preedit_start, #Minput_status_start, and
2612     #Minput_status_draw in this order.
2613
2614     @return
2615
2616     If an input context is successfully created, minput_create_ic ()
2617     returns a pointer to it.  Otherwise it returns @c NULL.  */
2618
2619 /***ja
2620     @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÀ¸À®¤¹¤ë.
2621
2622     ´Ø¿ô minput_create_ic () ¤ÏÆþÎϥ᥽¥Ã¥É $IM
2623     ¤ËÂбþ¤¹¤ëÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤·¡¢
2624     #Minput_preedit_start, #Minput_status_start, #Minput_status_draw
2625     ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¤³¤Î½ç¤Ë¸Æ¤Ö¡£
2626
2627     @return
2628
2629     ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤¬À¸À®¤µ¤ì¤¿¾ì¹ç¡¢minput_create_ic () 
2630     ¤Ï¤½¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¼ºÇÔ¤·¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
2631       */
2632
2633 MInputContext *
2634 minput_create_ic (MInputMethod *im, void *arg)
2635 {
2636   MInputContext *ic;
2637
2638   MDEBUG_PRINT2 ("[IM] creating context (%s %s) ... ",
2639                  msymbol_name (im->name), msymbol_name (im->language));
2640   MSTRUCT_CALLOC (ic, MERROR_IM);
2641   ic->im = im;
2642   ic->arg = arg;
2643   ic->preedit = mtext ();
2644   ic->candidate_list = NULL;
2645   ic->produced = mtext ();
2646   ic->spot.x = ic->spot.y = 0;
2647   ic->active = 1;
2648   ic->plist = mplist ();
2649   if ((*im->driver.create_ic) (ic) < 0)
2650     {
2651       MDEBUG_PRINT (" failed\n");
2652       M17N_OBJECT_UNREF (ic->preedit);
2653       M17N_OBJECT_UNREF (ic->produced);
2654       M17N_OBJECT_UNREF (ic->plist);
2655       free (ic);
2656       return NULL;
2657     };
2658
2659   if (im->driver.callback_list)
2660     {
2661       minput__callback (ic, Minput_preedit_start);
2662       minput__callback (ic, Minput_status_start);
2663       minput__callback (ic, Minput_status_draw);
2664     }
2665
2666   MDEBUG_PRINT (" ok\n");
2667   return ic;
2668 }
2669
2670 /*=*/
2671
2672 /***en
2673     @brief Destroy an input context.
2674
2675     The minput_destroy_ic () function destroys the input context $IC,
2676     which must have been created by minput_create_ic ().  It calls
2677     callback functions corresponding to #Minput_preedit_done,
2678     #Minput_status_done, and #Minput_candidates_done in this order.  */
2679
2680 /***ja
2681     @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÇ˲õ¤¹¤ë.
2682
2683     ´Ø¿ô minput_destroy_ic () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤òÇ˲õ¤¹¤ë¡£
2684     ¤³¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ï minput_create_ic () 
2685     ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£¤³¤Î´Ø¿ô¤Ï 
2686     #Minput_preedit_done, #Minput_status_done, #Minput_candidates_done 
2687     ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¤³¤Î½ç¤Ë¸Æ¤Ö¡£
2688   */
2689
2690 void
2691 minput_destroy_ic (MInputContext *ic)
2692 {
2693   MDEBUG_PRINT2 ("[IM] destroying context (%s %s) ... ",
2694                  msymbol_name (ic->im->name), msymbol_name (ic->im->language));
2695   if (ic->im->driver.callback_list)
2696     {
2697       minput__callback (ic, Minput_preedit_done);
2698       minput__callback (ic, Minput_status_done);
2699       minput__callback (ic, Minput_candidates_done);
2700     }
2701   (*ic->im->driver.destroy_ic) (ic);
2702   M17N_OBJECT_UNREF (ic->preedit);
2703   M17N_OBJECT_UNREF (ic->produced);
2704   M17N_OBJECT_UNREF (ic->plist);
2705   MDEBUG_PRINT (" done\n");
2706   free (ic);
2707 }
2708
2709 /*=*/
2710
2711 /***en
2712     @brief Filter an input key.
2713
2714     The minput_filter () function filters input key $KEY according to
2715     input context $IC, and calls callback functions corresponding to
2716     #Minput_preedit_draw, #Minput_status_draw, and
2717     #Minput_candidates_draw if the preedit text, the status, and the
2718     current candidate are changed respectively.
2719
2720     @return
2721     If $KEY is filtered out, this function returns 1.  In that case,
2722     the caller should discard the key.  Otherwise, it returns 0, and
2723     the caller should handle the key, for instance, by calling the
2724     function minput_lookup () with the same key.  */
2725
2726 /***ja
2727     @brief ÆþÎÏ¥­¡¼¤ò¥Õ¥£¥ë¥¿¤¹¤ë.
2728
2729     ´Ø¿ô minput_filter () ¤ÏÆþÎÏ¥­¡¼ $KEY ¤òÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC 
2730     ¤Ë±þ¤¸¤Æ¥Õ¥£¥ë¥¿¤·¡¢preedit ¥Æ¥­¥¹¥È¡¢¥¹¥Æ¡¼¥¿¥¹¡¢¸½»þÅÀ¤Ç¤Î¸õÊ䤬ÊѲ½¤·¤¿»þÅÀ¤Ç¡¢¤½¤ì¤¾¤ì
2731     #Minput_preedit_draw, #Minput_status_draw,
2732     #Minput_candidates_draw ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¸Æ¤Ö¡£
2733
2734     @return 
2735     $KEY ¤¬¥Õ¥£¥ë¥¿¤µ¤ì¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 1 ¤òÊÖ¤¹¡£
2736     ¤³¤Î¾ì¹ç¸Æ¤Ó½Ð¤·Â¦¤Ï¤³¤Î¥­¡¼¤ò¼Î¤Æ¤ë¤Ù¤­¤Ç¤¢¤ë¡£
2737     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0 ¤òÊÖ¤·¡¢¸Æ¤Ó½Ð¤·Â¦¤Ï¡¢¤¿¤È¤¨¤ÐƱ¤¸¥­¡¼¤Ç´Ø¿ô minput_lookup ()
2738     ¤ò¸Æ¤Ö¤Ê¤É¤·¤Æ¡¢¤³¤Î¥­¡¼¤ò½èÍý¤¹¤ë¡£
2739
2740     @latexonly \IPAlabel{minput_filter} @endlatexonly
2741 */
2742
2743 int
2744 minput_filter (MInputContext *ic, MSymbol key, void *arg)
2745 {
2746   int ret;
2747
2748   if (! ic
2749       || ! ic->active)
2750     return 0;
2751   ret = (*ic->im->driver.filter) (ic, key, arg);
2752
2753   if (ic->im->driver.callback_list)
2754     {
2755       if (ic->preedit_changed)
2756         minput__callback (ic, Minput_preedit_draw);
2757       if (ic->status_changed)
2758         minput__callback (ic, Minput_status_draw);
2759       if (ic->candidates_changed)
2760         minput__callback (ic, Minput_candidates_draw);
2761     }
2762
2763   return ret;
2764 }
2765
2766 /*=*/
2767
2768 /***en
2769     @brief Look up a text produced in the input context.
2770
2771     The minput_lookup () function looks up a text in the input context
2772     $IC.  $KEY must be the same one provided to the previous call of
2773     minput_filter ().
2774
2775     If a text was produced by the input method, it is concatenated
2776     to M-text $MT.
2777
2778     This function calls #MInputDriver::lookup .
2779
2780     @return
2781     If $KEY was correctly handled by the input method, this function
2782     returns 0.  Otherwise, returns -1, even in that case, some text
2783     may be produced in $MT.  */
2784
2785 /***ja
2786     @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥ÈÃæ¤Î¥Æ¥­¥¹¥È¤òõ¤¹.
2787
2788     ´Ø¿ô minput_lookup () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC Ãæ¤Î¥Æ¥­¥¹¥È¤òõ¤¹¡£
2789     $KEY ¤Ï´Ø¿ô minput_filter () ¤Ø¤ÎľÁ°¤Î¸Æ¤Ó½Ð¤·¤ËÍѤ¤¤é¤ì¤¿¤â¤Î¤ÈƱ¤¸¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2790
2791     ¥Æ¥­¥¹¥È¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆÀ¸À®¤µ¤ì¤Æ¤¤¤ì¤Ð¡¢¥Æ¥­¥¹¥È¤Ï M-text
2792     $MT ¤ËÏ¢·ë¤µ¤ì¤ë¡£
2793
2794     ¤³¤Î´Ø¿ô¤Ï¡¢#MInputDriver::lookup ¤ò¸Æ¤Ö¡£
2795
2796     @return 
2797     $KEY ¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆŬÀڤ˽èÍý¤Ç¤­¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 0 ¤òÊÖ¤¹¡£
2798     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£
2799     ¤³¤Î¾ì¹ç¤Ç¤â $MT ¤Ë²¿¤é¤«¤Î¥Æ¥­¥¹¥È¤¬À¸À®¤µ¤ì¤Æ¤¤¤ë¤³¤È¤¬¤¢¤ë¡£
2800
2801     @latexonly \IPAlabel{minput_lookup} @endlatexonly  */
2802
2803 int
2804 minput_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2805 {
2806   return (ic ? (*ic->im->driver.lookup) (ic, key, arg, mt) : -1);
2807 }
2808 /*=*/
2809
2810 /***en
2811     @brief Set the spot of the input context.
2812
2813     The minput_set_spot () function set the spot of input context $IC
2814     to coordinate ($X, $Y ) with the height specified by $ASCENT and $DESCENT .
2815     The semantics of these values depend on the input method driver.
2816
2817     For instance, a driver designed to work in a CUI environment may
2818     use $X and $Y as column and row numbers, and ignore $ASCENT and
2819     $DESCENT .  A driver designed to work in a window system may
2820     interpret $X and $Y as pixel offsets relative to the origin of the
2821     client window, and may interpret $ASCENT and $DESCENT as the ascent- and
2822     descent pixels of the line at ($X . $Y ).
2823
2824     $FONTSIZE specifies the fontsize of preedit text in 1/10 point.
2825
2826     $MT and $POS is the M-text and the character position at the spot.
2827     $MT may be @c NULL, in which case, the input method cannot get
2828     information about the text around the spot.  */
2829
2830 /***ja
2831     @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Î¥¹¥Ý¥Ã¥È¤òÀßÄꤹ¤ë.
2832
2833     ´Ø¿ô minput_set_spot () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤Î¥¹¥Ý¥Ã¥È¤ò¡¢ºÂɸ ($X, $Y )
2834     ¤Î°ÌÃ֤ˠ¡¢¹â¤µ $ASCENT¡¢ $DESCENT 
2835     ¤ÇÀßÄꤹ¤ë¡£ ¤³¤ì¤é¤ÎÃͤΰÕÌ£¤ÏÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë¡£
2836
2837     ¤¿¤È¤¨¤Ð CUI ´Ä¶­¤ÇÆ°ºî¤¹¤ë¥É¥é¥¤¥Ð¤Ï $X ¤È $Y 
2838     ¤ò¤½¤ì¤¾¤ìÎó¤È¹Ô¤ÎÈÖ¹æ¤È¤·¤ÆÍѤ¤¡¢$ASCENT ¤È $DESCENT 
2839     ¤ò̵»ë¤¹¤ë¤«¤â¤·¤ì¤Ê¤¤¡£ ¤Þ¤¿¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥àÍѤΥɥ饤¥Ð¤Ï
2840     $X ¤È $Y ¤ò¥¯¥é¥¤¥¢¥ó¥È¥¦¥£¥ó¥É¥¦¤Î¸¶ÅÀ¤«¤é¤Î¥ª¥Õ¥»¥Ã¥È¤ò¥Ô¥¯¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¤¡¢
2841     $ASCENT ¤È $DESCENT ¤ò ($X . $Y )
2842     ¤ÎÎó¤Î¥¢¥»¥ó¥È¤È¥Ç¥£¥»¥ó¥È¤ò¥Ô¥¯¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¦¤«¤â¤·¤ì¤Ê¤¤¡£
2843
2844     $FONTSIZE ¤Ë¤Ï preedit ¥Æ¥­¥¹¥È¤Î¥Õ¥©¥ó¥È¥µ¥¤¥º¤ò 1/10 ¥Ý¥¤¥ó¥Èñ°Ì¤Ç»ØÄꤹ¤ë¡£
2845
2846     $MT ¤È $POS ¤Ï¤½¤Î¥¹¥Ý¥Ã¥È¤Î M-text ¤Èʸ»ú°ÌÃ֤Ǥ¢¤ë¡£$MT ¤Ï @c
2847     NULL ¤Ç¤â¤è¤¯¡¢¤½¤Î¾ì¹ç¤Ë¤ÏÆþÎϥ᥽¥Ã¥É¤Ï¥¹¥Ý¥Ã¥È¼þÊդΥƥ­¥¹¥È¤Ë´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë¤³¤È¤¬¤Ç¤­¤Ê¤¤¡£
2848     */
2849
2850 void
2851 minput_set_spot (MInputContext *ic, int x, int y,
2852                  int ascent, int descent, int fontsize,
2853                  MText *mt, int pos)
2854 {
2855   ic->spot.x = x;
2856   ic->spot.y = y;
2857   ic->spot.ascent = ascent;
2858   ic->spot.descent = descent;
2859   ic->spot.fontsize = fontsize;
2860   ic->spot.mt = mt;
2861   ic->spot.pos = pos;
2862   if (ic->im->driver.callback_list)
2863     minput__callback (ic, Minput_set_spot);
2864 }
2865 /*=*/
2866
2867 /***en
2868     @brief Toggle input method.
2869
2870     The minput_toggle () function toggles the input method associated
2871     with input context $IC.  */
2872 /***ja
2873     @brief ÆþÎϥ᥽¥Ã¥É¤òÀÚÂؤ¨¤ë.
2874
2875     ´Ø¿ô minput_toggle () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC 
2876     ¤ËÂбþÉÕ¤±¤é¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ò¥È¥°¥ë¤¹¤ë¡£
2877     */
2878
2879 void
2880 minput_toggle (MInputContext *ic)
2881 {
2882   if (ic->im->driver.callback_list)
2883     minput__callback (ic, Minput_toggle);
2884   ic->active = ! ic->active;
2885 }
2886
2887 /***en
2888     @brief Reset an input context.
2889
2890     The minput_reset_ic () function resets input context $IC by
2891     calling a callback function corresponding to #Minput_reset.  It
2892     actually shifts the state to the initial one, and thus the current
2893     preediting text (if any) is committed.  If necessary, a program
2894     can extract that committed text by calling minput_lookup () just
2895     after the call of minput_reset_ic ().  In that case, the arguments
2896     @c KEY and @c ARG of minput_lookup () are ignored.  */
2897 /***ja
2898     @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤ò¥ê¥»¥Ã¥È¤¹¤ë.
2899
2900     ´Ø¿ô minput_reset_ic () ¤Ï #Minput_reset 
2901     ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¸Æ¤Ö¤³¤È¤Ë¤è¤Ã¤ÆÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC 
2902     ¤ò¥ê¥»¥Ã¥È¤¹¤ë¡£¥ê¥»¥Ã¥È¤È¤Ï¡¢¼ÂºÝ¤Ë¤ÏÆþÎϥ᥽¥Ã¥É¤ò½é´ü¾õÂ֤˰ܤ¹¤³¤È¤Ç¤¢¤ê¡¢¤·¤¿¤¬¤Ã¤Æ¡¢¤â¤·¸½ºßÆþÎÏÃæ¤Î¥Æ¥­¥¹¥È¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤Ï¥³¥ß¥Ã¥È¤µ¤ì¤ë¡£
2903     É¬Íפʤé¤Ð¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ï minput_lookup () 
2904     ¤òÆɤó¤Ç¤½¤Î¥³¥ß¥Ã¥È¤µ¤ì¤¿¥Æ¥­¥¹¥È¤ò¼è¤ê½Ð¤¹¤³¤È¤¬¤Ç¤­¡¢¤½¤ÎºÝ¡¢
2905     minput_lookup () ¤Î°ú¿ô @c KEY ¤È @c ARG 
2906     ¤Ï̵»ë¤µ¤ì¤ë¡£ */
2907 void
2908 minput_reset_ic (MInputContext *ic)
2909 {
2910   if (ic->im->driver.callback_list)
2911     minput__callback (ic, Minput_reset);
2912 }
2913
2914 /*=*/
2915 /***en
2916     @brief Key of a text property for detailed description.
2917
2918     The symbol #Mdetail_text is a managing key usually used for a
2919     text property whose value is an M-text that contains detailed
2920     description.  */
2921 /***ja
2922     @brief ¾ÜºÙÀâÌÀÍѥƥ­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
2923
2924     ¥·¥ó¥Ü¥ë #Mdetail_text ¤Ï´ÉÍý¥­¡¼¤Ç¤¢¤ê¡¢Ä̾ï¾ÜºÙ¤ÊÀâÌÀ¤ò´Þ¤à 
2925     M-text ¤òÃͤȤ·¤Æ»ý¤Ä¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ËÍѤ¤¤é¤ì¤ë¡£
2926     */
2927 MSymbol Mdetail_text;
2928
2929 /***en
2930     @brief Get description text of an input method.
2931
2932     The minput_get_description () function returns an M-text that
2933     briefly describes the input method specified by $LANGUAGE and
2934     $NAME.  The returned M-text may have a text property, from its
2935     beginning to end, #Mdetail_text whose value is an M-text
2936     describing the input method in more detail.
2937
2938     @return
2939     If the specified input method has a description text, a pointer to
2940     #MText is returned.  A caller have to free it by m17n_object_unref ().
2941     If the input method does not have a description text, @c NULL is
2942     returned.  */
2943 /***ja
2944     @brief ÆþÎϥ᥽¥Ã¥É¤ÎÀâÌÀ¥Æ¥­¥¹¥È¤òÆÀ¤ë.
2945
2946     ´Ø¿ô minput_get_description () ¤Ï¡¢$LANGUAGE ¤È $NAME 
2947     ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ò´Êñ¤ËÀâÌÀ¤¹¤ë M-text ¤òÊÖ¤¹¡£ÊÖ¤µ¤ì¤ë M-text 
2948     ¤Ë¤Ï¡¢¤½¤ÎÁ´ÂΤËÂФ·¤Æ #Mdetail_text 
2949     ¤È¤¤¤¦¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬Éղ䵤ì¤Æ¤¤¤ë¾ì¹ç¤¬¤¢¤ê¡¢¤½¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤÏÆþÎϥ᥽¥Ã¥É¤ò¤µ¤é¤Ë¾ÜºÙ¤ËÀâÌÀ¤¹¤ë
2950     M-text ¤Ç¤¢¤ë¡£
2951
2952     @return 
2953     »ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤¬ÀâÌÀ¤¹¤ë¥Æ¥­¥¹¥È¤ò»ý¤Ã¤Æ¤¤¤ì¤Ð¡¢ 
2954     #MText ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¸Æ¤Ó½Ð¤·Â¦¤Ï¡¢¤½¤ì¤ò m17n_object_unref
2955     () ¤òÍѤ¤¤Æ²òÊü¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ÆþÎϥ᥽¥Ã¥É¤ËÀâÌÀ¥Æ¥­¥¹¥È¤¬Ìµ¤±¤ì¤Ð@c NULL ¤òÊÖ¤¹¡£ */
2956
2957 MText *
2958 minput_get_description (MSymbol language, MSymbol name)
2959 {
2960   MPlist *plist = load_im_info (language, name, M_description);
2961   MPlist *pl;
2962   MText *mt = NULL;
2963
2964   if (! plist)
2965     return NULL;
2966   if (! MPLIST_PLIST_P (plist))
2967     {
2968       M17N_OBJECT_UNREF (plist);      
2969       return NULL;
2970     }
2971   pl = MPLIST_PLIST (plist);
2972   while (! MPLIST_TAIL_P (pl) && ! MPLIST_MTEXT_P (pl))
2973     pl = MPLIST_NEXT (pl);
2974   if (MPLIST_MTEXT_P (pl))
2975     mt = get_description_advance (pl);
2976   M17N_OBJECT_UNREF (plist);
2977   return mt;
2978 }
2979
2980 /***en
2981     @brief Get information about input method commands.
2982
2983     The minput_get_commands () function returns information about
2984     input method commands of the input method specified by $LANGUAGE
2985     and $NAME.  An input method command is a pseudo key event to which
2986     one or more actual input key sequences are assigned.
2987
2988     There are two kinds of commands, global and local.  Global
2989     commands are used by multiple input methods for the same purpose,
2990     and have global key assignments.  Local commands are used only in
2991     a specific input method, and have only local key assignments.
2992
2993     Each input method may locally change key assignments for global
2994     commands.  A global key assignment for a global command are
2995     effective only when the current input method does not have local
2996     key assignments for that command.
2997
2998     If $NAME is #Mnil, information about global commands is returned.
2999     In this case $LANGUAGE is ignored.
3000
3001     If $NAME is not #Mnil, information about those commands that have
3002     local key assignments in the input method specified by $LANGUAGE
3003     and $NAME is returned.
3004
3005     @return
3006     If no input method commands are found, this function returns @c NULL.
3007
3008     Otherwise, a pointer to a plist is returned.  The key of each
3009     element in the plist is a symbol representing a command, and the
3010     value is a plist of the form COMMAND-INFO described below.
3011
3012     The first element of COMMAND-INFO has the key #Mtext, and the
3013     value is an M-text describing the command briefly.  This M-text
3014     may have a text property whose key is #Mdetail_text and whose
3015     value is an M-text describing the command in more detail.
3016
3017     If there are no more elements, that means no key sequences are
3018     assigned to the command.  Otherwise, each of the remaining
3019     elements has the key #Mplist, and the value is a plist whose keys are
3020     #Msymbol and values are symbols representing input keys, which are
3021     currently assigned to the command.
3022
3023     As the returned plist is kept in the library, the caller must not
3024     modify nor free it.  */
3025 /***ja
3026     @brief ÆþÎϥ᥽¥Ã¥É¤Î¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë.
3027
3028     ´Ø¿ô minput_get_commands () ¤Ï¡¢ $LANGUAGE ¤È $NAME 
3029     ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ÎÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£
3030     ÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤È¤Ï¡¢µ¿»÷¥­¡¼¥¤¥Ù¥ó¥È¤Ç¤¢¤ê¡¢¤½¤ì¤¾¤ì¤Ë£±¤Ä°Ê¾å¤Î¼ÂºÝ¤ÎÆþÎÏ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤¬³ä¤êÅö¤Æ¤é¤ì¤Æ¤¤¤ë¤â¤Î¤ò»Ø¤¹¡£
3031
3032     ¥³¥Þ¥ó¥É¤Ë¤Ï¥°¥í¡¼¥Ð¥ë¤È¥í¡¼¥«¥ë¤Î£²¼ïÎब¤¢¤ë¡£
3033     ¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É¤ÏÊ£¿ô¤ÎÆþÎϥ᥽¥Ã¥É¤Ë¤ª¤¤¤Æ¡¢Æ±¤¸ÌÜŪ¤Ç¡¢¥°¥í¡¼¥Ð¥ë¤Ê¥­¡¼³ä¤êÅö¤Æ¤ÇÍѤ¤¤é¤ì¤ë¡£
3034     ¥í¡¼¥«¥ë¥³¥Þ¥ó¥É¤ÏÆÃÄê¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Î¤ß¡¢¥í¡¼¥«¥ë¤Ê¥­¡¼³äÅö¤Ç»ÈÍѤµ¤ì¤ë¡£
3035
3036     ¸Ä¡¹¤ÎÆþÎϥ᥽¥Ã¥É¤Ï¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É¤Î¥­¡¼³äÅö¤òÊѹ¹¤¹¤ë¤³¤È¤â¤Ç¤­¤ë¡£
3037     ¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥ÉÍѤΥ°¥í¡¼¥Ð¥ë¥­¡¼³ä¤êÅö¤Æ¤Ï¡¢»ÈÍѤ¹¤ëÆþÎϥ᥽¥Ã¥É¤Ë¤ª¤¤¤Æ¤½¤Î¥³¥Þ¥ó¥ÉÍÑ¤Î¥í¡¼¥«¥ë¤Ê¥­¡¼³äÅö¤¬Â¸ºß¤·¤Ê¤¤¾ì¹ç¤Ë¤Î¤ßÍ­¸ú¤Ç¤¢¤ë¡£
3038
3039     $NAME ¤¬ #Mnil ¤Ç¤¢¤ì¤Ð¡¢¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£
3040     ¤³¤Î¾ì¹ç¡¢$LANGUAGE ¤Ï̵»ë¤µ¤ì¤ë¡£
3041
3042     $NAME ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢$LANGUAGE ¤È $NAME 
3043     ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤ëÆþÎϥ᥽¥Ã¥É¤ËÃÖ¤±¤ë¥í¡¼¥«¥ë¤Ê¥­¡¼³ä¤êÅö¤Æ¤ò»ý¤Ä¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£
3044
3045     @return
3046     ÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï @c NULL ¤òÊÖ¤¹¡£
3047
3048     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
3049     ¥ê¥¹¥È¤Î³ÆÍ×ÁǤΥ­¡¼¤Ï¸Ä¡¹¤Î¥³¥Þ¥ó¥É¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢Ãͤϲ¼µ­¤Î 
3050     COMMAND-INFO ¤Î·Á¼°¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ç¤¢¤ë¡£
3051
3052     COMMAND-INFO ¤ÎÂè°ìÍ×ÁǤϥ­¡¼¤È¤·¤Æ #Mtext 
3053     ¤ò¡¢ÃͤȤ·¤Æ¤½¤Î¥³¥Þ¥ó¥É¤ò´Êñ¤ËÀâÌÀ¤¹¤ë M-text ¤ò»ý¤Ä¡£¤³¤Î M-text 
3054     ¤Ï¡¢#Mdetail_text 
3055     ¤ò¥­¡¼¤È¤¹¤ë¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä¤³¤È¤¬¤Ç¤­¡¢¤½¤ÎÃͤϤ½¤Î¥³¥Þ¥ó¥É¤ò¤è¤ê¾ÜºÙ¤ËÀâÌÀ¤¹¤ë
3056     M-text ¤Ç¤¢¤ë¡£
3057
3058     ¤½¤ì°Ê³°¤ÎÍ×ÁǤ¬Ìµ¤±¤ì¤Ð¡¢¤³¤Î¥³¥Þ¥ó¥É¤ËÂФ·¤Æ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤¬³ä¤êÅö¤Æ¤é¤ì¤Æ¤¤¤Ê¤¤¤³¤È¤ò°ÕÌ£¤¹¤ë¡£
3059     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢»Ä¤ê¤Î³ÆÍ×ÁǤϥ­¡¼¤È¤·¤Æ#Mplist 
3060     ¤ò¡¢ÃͤȤ·¤Æ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ò»ý¤Ä¡£
3061     ¤³¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Î¥­¡¼¤Ï #Msymbol 
3062     ¤Ç¤¢¤ê¡¢Ãͤϸ½ºß¤½¤Î¥³¥Þ¥ó¥É¤Ë³ä¤êÅö¤Æ¤é¤ì¤Æ¤¤¤ëÆþÎÏ¥­¡¼¤òɽ¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
3063
3064     ÊÖ¤µ¤ì¤ë¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ï¥é¥¤¥Ö¥é¥ê¤Ë¤è¤Ã¤Æ´ÉÍý¤µ¤ì¤Æ¤ª¤ê¡¢¸Æ¤Ó½Ð¤·Â¦¤ÇÊѹ¹¤·¤¿¤ê²òÊü¤·¤¿¤ê¤·¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£*/
3065
3066 MPlist *
3067 minput_get_commands (MSymbol language, MSymbol name)
3068 {
3069   MPlist *plist = get_command_list (language, name);
3070
3071   return (! plist || MPLIST_TAIL_P (plist) ? NULL : plist);
3072 }
3073
3074 /***en
3075     @brief Assign a key sequence to an input method command.
3076
3077     The minput_assign_command_keys () function assigns input key
3078     sequence $KEYSEQ to input method command $COMMAND for the input
3079     method specified by $LANGUAGE and $NAME.  If $NAME is #Mnil, the
3080     key sequence is assigned globally no matter what $LANGUAGE is.
3081     Otherwise the key sequence is assigned locally.
3082
3083     Each element of $KEYSEQ must have the key $Msymbol and the value
3084     must be a symbol representing an input key.
3085
3086     $KEYSEQ may be @c NULL, in which case, all assignments are deleted
3087     globally or locally.
3088
3089     This assignment gets effective in a newly opened input method.
3090
3091     @return
3092     If the operation was successful, 0 is returned.  Otherwise -1 is
3093     returned, and #merror_code is set to #MERROR_IM.  */
3094 /***ja
3095     @brief ÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤Ë¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤ò³ä¤êÅö¤Æ¤ë.
3096
3097     ´Ø¿ô minput_assign_command_keys () ¤Ï¡¢ $LANGUAGE ¤È $NAME 
3098     ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥ÉÍѤÎÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É $COMMAND 
3099     ¤ËÂФ·¤Æ¡¢ÆþÎÏ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹ $KEYSEQ ¤ò³ä¤êÅö¤Æ¤ë¡£ $NAME ¤¬ #Mnil
3100     ¤Ê¤é¤Ð¡¢$LANGUAGE ¤Ë´Ø·¸¤Ê¤¯¡¢ÆþÎÏ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤Ï¥°¥í¡¼¥Ð¥ë¤Ë³ä¤êÅö¤Æ¤é¤ì¤ë¡£
3101     ¤½¤¦¤Ç¤Ê¤ì¤Ð¡¢³ä¤êÅö¤Æ¤Ï¥í¡¼¥«¥ë¤Ç¤¢¤ë¡£
3102
3103     $KEYSEQ ¤Î³ÆÍ×ÁǤϥ­¡¼¤È¤·¤Æ $Msymbol 
3104     ¤ò¡¢ÃͤȤ·¤ÆÆþÎÏ¥­¡¼¤òɽ¤¹¥·¥ó¥Ü¥ë¤ò»ý¤¿¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
3105
3106     $KEYSEQ ¤Ï @c NULL ¤Ç¤â¤è¤¤¡£
3107     ¤³¤Î¾ì¹ç¡¢¥°¥í¡¼¥Ð¥ë¤â¤·¤¯¤Ï¥í¡¼¥«¥ë¤Ê¤¹¤Ù¤Æ¤Î³ä¤êÅö¤Æ¤¬¾Ãµî¤µ¤ì¤ë¡£
3108
3109     ¤³¤Î³ä¤êÅö¤Æ¤Ï¡¢³ä¤êÅö¤Æ°Ê¹ß¿·¤·¤¯¥ª¡¼¥×¥ó¤µ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤«¤éÍ­¸ú¤Ë¤Ê¤ë¡£
3110
3111     @return 
3112     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤·¡¢
3113     #merror_code ¤ò #MERROR_IM ¤ËÀßÄꤹ¤ë¡£  */
3114
3115 int
3116 minput_assign_command_keys (MSymbol language, MSymbol name,
3117                             MSymbol command, MPlist *keyseq)
3118 {
3119   MPlist *plist, *pl, *p;
3120
3121   if (check_command_keyseq (keyseq) < 0
3122       || ! (plist = get_command_list (language, name)))
3123     MERROR (MERROR_IM, -1);
3124   pl = mplist_get (plist, command);
3125   if (pl)
3126     {
3127       pl = MPLIST_NEXT (pl);
3128       if (! keyseq)
3129         while ((p = mplist_pop (pl)))
3130           M17N_OBJECT_UNREF (p);
3131       else
3132         {
3133           keyseq = mplist_copy (keyseq);
3134           mplist_push (pl, Mplist, keyseq);
3135           M17N_OBJECT_UNREF (keyseq);
3136         }
3137     }
3138   else
3139     {
3140       if (name == Mnil)
3141         MERROR (MERROR_IM, -1);
3142       if (! keyseq)
3143         return 0;
3144       pl = get_command_list (Mnil, Mnil); /* Get global commands.  */
3145       pl = mplist_get (pl, command);
3146       if (! pl)
3147         MERROR (MERROR_IM, -1);
3148       p = mplist ();
3149       mplist_add (p, Mtext, mplist_value (pl));
3150       keyseq = mplist_copy (keyseq);
3151       mplist_add (p, Mplist, keyseq);
3152       M17N_OBJECT_UNREF (keyseq);
3153       mplist_push (plist, command, p);
3154     }
3155   return 0;
3156 }
3157
3158 /***en
3159     @brief Get a list of variables of an input method.
3160
3161     The minput_get_variables () function returns a plist (#MPlist) of
3162     variables used to control the behavior of the input method
3163     specified by $LANGUAGE and $NAME.  The key of an element of the
3164     plist is a symbol representing a variable, and the value is a
3165     plist of the form VAR-INFO (described below) that carries the
3166     information about the variable.
3167
3168     The first element of VAR-INFO has the key #Mtext, and the value is
3169     an M-text describing the variable briefly.  This M-text may have a
3170     text property #Mdetail_text whose value is an M-text describing
3171     the variable in more detail.
3172
3173     The second element of VAR-INFO is for the value of the variable.
3174     The key is #Minteger, #Msymbol, or #Mtext, and the value is an
3175     integer, a symbol, or an M-text, respectively.  The variable is
3176     set to this value when an input context is created for the input
3177     method.
3178
3179     If there are no more elements, the variable can take any value
3180     that matches with the above type.  Otherwise, the remaining
3181     elements of VAR-INFO are to specify valid values of the variable.
3182
3183     If the type of the variable is integer, the following elements
3184     have the key #Minteger or #Mplist.  If it is #Minteger, the value
3185     is a valid integer value.  If it is #Mplist, the value is a plist
3186     of two of elements.  Both of them have the key #Minteger, and
3187     values are the minimum and maximum bounds of the valid value
3188     range.
3189
3190     If the type of the variable is symbol or M-text, the following
3191     elements of the plist have the key #Msymbol or #Mtext,
3192     respectively, and the value must be a valid one.
3193
3194     For instance, suppose an input method has the variables:
3195
3196     @li name:intvar, description: "value is an integer",
3197          initial value:0, value-range:0..3,10,20
3198
3199     @li name:symvar, description: "value is a symbol",
3200          initial value:nil, value-range:a, b, c, nil
3201
3202     @li name:txtvar, description: "value is an M-text",
3203          initial value:empty text, no value-range (i.e. any text)
3204
3205     Then, the returned plist has this form ('X:Y' means X is a key and Y is
3206     a value, and '(...)' means a plist):
3207
3208 @verbatim
3209     plist:(intvar:(mtext:'value is an integer'
3210                    integer:0
3211                    plist:(integer:0 integer:3)
3212                    integer:10
3213                    integer:20))
3214            symvar:(mtext:"value is a symbol"
3215                    symbol:nil
3216                    symbol:a
3217                    symbol:b
3218                    symbol:c
3219                    symbol:nil))
3220            txtvar:(mtext:"value is an M-text"
3221                    mtext:""))
3222 @endverbatim
3223
3224     @return
3225     If the input method uses any variables, a pointer to #MPlist is
3226     returned.  As the plist is kept in the library, a caller must not
3227     modify nor free it.  If the input method does not use any
3228     variable, @c NULL is returned.  */
3229 /***ja
3230     @brief ÆþÎϥ᥽¥Ã¥É¤ÎÊÑ¿ô¥ê¥¹¥È¤òÆÀ¤ë.
3231
3232     ´Ø¿ô minput_get_variables () ¤Ï¡¢$LANGUAGE ¤È $NAME 
3233     ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤Î¿¶¤ëÉñ¤¤¤òÀ©¸æ¤¹¤ëÊÑ¿ô¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È 
3234     (#MPlist) ¤òÊÖ¤¹¡£¥ê¥¹¥È¤Î³ÆÍ×ÁǤΥ­¡¼¤ÏÊÑ¿ô¤òɽ¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
3235     ³ÆÍ×ÁǤÎÃͤϲ¼µ­¤Î VAR-INFO 
3236     ¤Î·Á¼°¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ç¤¢¤ê¡¢³ÆÊÑ¿ô¤Ë´Ø¤¹¤ë¾ðÊó¤ò¼¨¤·¤Æ¤¤¤ë¡£
3237
3238     VAR-INFO ¤ÎÂè°ìÍ×ÁǤϥ­¡¼¤È¤·¤Æ #Mtext ¤ò¡¢ÃͤȤ·¤Æ¤½¤ÎÊÑ¿ô¤ò´Êñ¤ËÀâÌÀ¤¹¤ë
3239     M-text ¤ò»ý¤Ä¡£¤³¤Î M-text ¤Ï¡¢#Mdetail_text 
3240     ¤ò¥­¡¼¤È¤¹¤ë¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä¤³¤È¤¬¤Ç¤­¡¢¤½¤ÎÃͤϤ½¤ÎÊÑ¿ô¤ò¤è¤ê¾ÜºÙ¤ËÀâÌÀ¤¹¤ë
3241     M-text ¤Ç¤¢¤ë¡£
3242
3243     VAR-INFO ¤ÎÂèÆóÍ×ÁǤÏÊÑ¿ô¤ÎÃͤò¼¨¤¹¡£¥­¡¼¤Ï #Minteger, #Msymbol,
3244     #Mtext ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ê¡¢ÃͤϤ½¤ì¤¾¤ìÀ°¿ôÃÍ¡¢¥·¥ó¥Ü¥ë¡¢M-text  ¤Ç¤¢¤ë¡£
3245     ¤³¤ÎÆþÎϥ᥽¥Ã¥ÉÍѤÎÆþÎÏ¥³¥ó¥Æ¥¹¥È¤¬ºî¤é¤ì¤ë»þÅÀ¤Ç¤Ï¡¢ÊÑ¿ô¤Ï¤³¤ÎÃͤËÀßÄꤵ¤ì¤Æ¤¤¤ë¡£
3246
3247     VAR-INFO ¤Ë¤½¤ì°Ê³°¤ÎÍ×ÁǤ¬Ìµ¤±¤ì¤Ð¡¢ÊÑ¿ô¤Ï¾åµ­¤Î·¿¤Ë¹çÃפ¹¤ë¸Â¤ê¤É¤Î¤è¤¦¤ÊÃͤò¤È¤ë¤³¤È¤â¤Ç¤­¤ë¡£
3248     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢VAR-INFO ¤Î»Ä¤ê¤ÎÍ×ÁǤˤè¤Ã¤ÆÊÑ¿ô¤ÎÍ­¸ú¤ÊÃͤ¬»ØÄꤵ¤ì¤ë¡£
3249
3250     ÊÑ¿ô¤Î·¿¤¬À°¿ô¤Ç¤¢¤ì¤Ð¡¢¤½¤ì°Ê¹ß¤ÎÍ×ÁǤϠ#Minteger ¤« #Mplist 
3251     ¤ò¥­¡¼¤È¤·¤Æ»ý¤Ä¡£ #Minteger ¤Ç¤¢¤ì¤Ð¡¢ÃͤÏÍ­¸ú¤ÊÃͤò¼¨¤¹À°¿ôÃͤǤ¢¤ë¡£
3252     #Mplist ¤Ç¤¢¤ì¤Ð¡¢ÃͤÏÆó¤Ä¤ÎÍ×ÁǤò»ý¤Ä¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ç¤¢¤ê¡¢³ÆÍ×ÁǤϥ­¡¼¤È¤·¤Æ
3253     #Minteger ¤ò¡¢ÃͤȤ·¤Æ¤½¤ì¤¾¤ìÍ­¸ú¤ÊÃͤξå¸ÂÃͤȲ¼¸ÂÃͤò¤È¤ë¡£
3254
3255     ÊÑ¿ô¤Î·¿¤¬¥·¥ó¥Ü¥ë¤« M-text ¤Ç¤¢¤ì¤Ð¡¢¤½¤ì°Ê¹ß¤ÎÍ×ÁǤϥ­¡¼¤È¤·¤Æ¤½¤ì¤¾¤ì
3256     #Msymbol ¤« #Mtext ¤ò»ý¤Á¡¢ÃͤϤ½¤Î·¿¤Ë¹çÃפ¹¤ë¤â¤Î¤Ç¤¢¤ë¡£
3257
3258     Îã¤È¤·¤Æ¡¢¤¢¤ëÆþÎϥ᥽¥Ã¥É¤¬¼¡¤Î¤è¤¦¤ÊÊÑ¿ô¤ò»ý¤Ä¾ì¹ç¤ò¹Í¤¨¤è¤¦¡£
3259
3260     @li name:intvar, ÀâÌÀ:"value is an integer",
3261         ½é´üÃÍ:0, ÃͤÎÈÏ°Ï:0..3,10,20
3262
3263     @li name:symvar, ÀâÌÀ:"value is a symbol",
3264          ½é´üÃÍ:nil, ÃͤÎÈÏ°Ï:a, b, c, nil
3265
3266     @li name:txtvar, ÀâÌÀ:"value is an M-text",
3267         ½é´üÃÍ:empty text, ÃͤÎÈϰϤʤ·(¤É¤ó¤Ê M-text ¤Ç¤â²Ä)
3268
3269     ¤³¤Î¾ì¹ç¡¢ÊÖ¤µ¤ì¤ë¥ê¥¹¥È¤Ï°Ê²¼¤Î¤è¤¦¤Ë¤Ê¤ë¡£¡Ê'X:Y' ¤È¤¤¤¦µ­Ë¡¤Ï X 
3270     ¤¬¥­¡¼¤Ç Y ¤¬ÃͤǤ¢¤ë¤³¤È¤ò¡¢¤Þ¤¿ '(...)' ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ò¼¨¤¹¡£¡Ë
3271
3272 @verbatim
3273     plist:(intvar:(mtext:"value is an integer"
3274                    integer:0
3275                    plist:(integer:0 integer:3)
3276                    integer:10
3277                    integer:20))
3278            symvar:(mtext:"value is a symbol"
3279                    symbol:nil
3280                    symbol:a
3281                    symbol:b
3282                    symbol:c
3283                    symbol:nil))
3284            txtvar:(mtext:"value is an M-text"
3285                    mtext:""))
3286 @endverbatim
3287
3288     @return 
3289     ÆþÎϥ᥽¥Ã¥É¤¬²¿¤é¤«¤ÎÊÑ¿ô¤ò»ÈÍѤ·¤Æ¤¤¤ì¤Ð #MPlist ¤Ø¤ÎÊÑ¿ô¤òÊÖ¤¹¡£
3290     ÊÖ¤µ¤ì¤ë¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ï¥é¥¤¥Ö¥é¥ê¤Ë¤è¤Ã¤Æ´ÉÍý¤µ¤ì¤Æ¤ª¤ê¡¢¸Æ¤Ó½Ð¤·Â¦¤ÇÊѹ¹¤·¤¿¤ê²òÊü¤·¤¿¤ê¤·¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
3291     ÆþÎϥ᥽¥Ã¥É¤¬ÊÑ¿ô¤ò°ìÀÚ»ÈÍѤ·¤Æ¤Ê¤±¤ì¤Ð¡¢@c NULL ¤òÊÖ¤¹¡£  */
3292
3293 MPlist *
3294 minput_get_variables (MSymbol language, MSymbol name)
3295 {
3296   MPlist *plist = get_variable_list (language, name);
3297
3298   return (! plist || MPLIST_TAIL_P (plist) ? NULL : plist);
3299 }
3300
3301 /***en
3302     @brief Set the initial value of an input method variable.
3303
3304     The minput_set_variable () function sets the initial value of
3305     input method variable $VARIABLE to $VALUE for the input method
3306     specified by $LANGUAGE and $NAME.
3307
3308     By default, the initial value is 0.
3309
3310     This setting gets effective in a newly opened input method.
3311
3312     @return
3313     If the operation was successful, 0 is returned.  Otherwise -1 is
3314     returned, and #merror_code is set to #MERROR_IM.  */
3315 /***ja
3316     @brief ÆþÎϥ᥽¥Ã¥ÉÊÑ¿ô¤Î½é´üÃͤòÀßÄꤹ¤ë.
3317
3318     ´Ø¿ô minput_set_variable () ¤Ï¡¢$LANGUAGE ¤È $NAME 
3319     ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ÎÆþÎϥ᥽¥Ã¥ÉÊÑ¿ô $VARIABLE
3320     ¤Î½é´üÃͤò¡¢ $VALUE ¤ËÀßÄꤹ¤ë¡£
3321
3322     ¥Ç¥Õ¥©¥ë¥È¤Î½é´üÃͤϠ0 ¤Ç¤¢¤ë¡£
3323
3324     ¤³¤ÎÀßÄê¤Ï¡¢¿·¤·¤¯¥ª¡¼¥×¥ó¤µ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤«¤éÍ­¸ú¤È¤Ê¤ë¡£
3325
3326     @return
3327     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤·¡¢
3328     #merror_code ¤ò #MERROR_IM ¤ËÀßÄꤹ¤ë¡£  */
3329
3330 int
3331 minput_set_variable (MSymbol language, MSymbol name,
3332                      MSymbol variable, void *value)
3333 {
3334   MPlist *plist, *val_element, *range_element;
3335   MSymbol type;
3336
3337   if (language == Mnil || name == Mnil)
3338     MERROR (MERROR_IM, -1);
3339   plist = get_variable_list (language, name);
3340   if (! plist)
3341     MERROR (MERROR_IM, -1);
3342   plist = (MPlist *) mplist_get (plist, variable);
3343   if (! plist)
3344     MERROR (MERROR_IM, -1);
3345   val_element = MPLIST_NEXT (plist);
3346   type = MPLIST_KEY (val_element);
3347   range_element = MPLIST_NEXT (val_element);
3348     
3349   if (! MPLIST_TAIL_P (range_element))
3350     {
3351       if (type == Minteger)
3352         {
3353           int val = (int) value, this_val;
3354       
3355           MPLIST_DO (plist, range_element)
3356             {
3357               this_val = (int) MPLIST_VAL (plist);
3358               if (MPLIST_PLIST_P (plist))
3359                 {
3360                   int min_bound, max_bound;
3361                   MPlist *pl = MPLIST_PLIST (plist);
3362
3363                   min_bound = (int) MPLIST_VAL (pl);
3364                   pl = MPLIST_NEXT (pl);
3365                   max_bound = (int) MPLIST_VAL (pl);
3366                   if (val >= min_bound && val <= max_bound)
3367                     break;
3368                 }
3369               else if (val == this_val)
3370                 break;
3371             }
3372           if (MPLIST_TAIL_P (plist))
3373             MERROR (MERROR_IM, -1);
3374         }
3375       else if (type == Msymbol)
3376         {
3377           MPLIST_DO (plist, range_element)
3378             if (MPLIST_SYMBOL (plist) == (MSymbol) value)
3379               break;
3380           if (MPLIST_TAIL_P (plist))
3381             MERROR (MERROR_IM, -1);
3382         }
3383       else                      /* type == Mtext */
3384         {
3385           MPLIST_DO (plist, range_element)
3386             if (mtext_cmp (MPLIST_MTEXT (plist), (MText *) value) == 0)
3387               break;
3388           if (MPLIST_TAIL_P (plist))
3389             MERROR (MERROR_IM, -1);
3390           M17N_OBJECT_REF (value);
3391         }
3392     }
3393
3394   mplist_set (val_element, type, value);
3395   return 0;
3396 }
3397
3398 /*** @} */
3399 /*=*/
3400 /*** @addtogroup m17nDebug */
3401 /*=*/
3402 /*** @{  */
3403 /*=*/
3404
3405 /***en
3406     @brief Dump an input method.
3407
3408     The mdebug_dump_im () function prints the input method $IM in a
3409     human readable way to the stderr.  $INDENT specifies how many
3410     columns to indent the lines but the first one.
3411
3412     @return
3413     This function returns $IM.  */
3414 /***ja
3415     @brief ÆþÎϥ᥽¥Ã¥É¤ò¥À¥ó¥×¤¹¤ë.
3416
3417     ´Ø¿ô mdebug_dump_im () ¤ÏÆþÎϥ᥽¥Ã¥É $IM ¤ò stderr 
3418     ¤Ë¿Í´Ö¤Ë²ÄÆɤʷÁ¤Ç°õºþ¤¹¤ë¡£$INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£
3419
3420     @return
3421     ¤³¤Î´Ø¿ô¤Ï $IM ¤òÊÖ¤¹¡£  */
3422
3423 MInputMethod *
3424 mdebug_dump_im (MInputMethod *im, int indent)
3425 {
3426   MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
3427   char *prefix;
3428
3429   prefix = (char *) alloca (indent + 1);
3430   memset (prefix, 32, indent);
3431   prefix[indent] = '\0';
3432
3433   fprintf (stderr, "(input-method %s %s ", msymbol_name (im->language),
3434            msymbol_name (im->name));
3435   mdebug_dump_mtext (im_info->title, 0, 0);
3436   if (im->name != Mnil)
3437     {
3438       MPlist *state;
3439
3440       MPLIST_DO (state, im_info->states)
3441         {
3442           fprintf (stderr, "\n%s  ", prefix);
3443           dump_im_state (MPLIST_VAL (state), indent + 2);
3444         }
3445     }
3446   fprintf (stderr, ")");
3447   return im;
3448 }
3449
3450 /*** @} */ 
3451
3452 /*
3453   Local Variables:
3454   coding: euc-japan
3455   End:
3456 */