(shift_state): Fix the condition of taking init actions.
[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->map == ic_info->state->map
883       && ic_info->map->map_actions)
884     {
885       MDEBUG_PRINT (" init-actions:");
886       take_action_list (ic, ic_info->map->map_actions);
887     }
888 }
889
890 /* Find a candidate group that contains a candidate number INDEX from
891    PLIST.  Set START_INDEX to the first candidate number of the group,
892    END_INDEX to the last candidate number plus 1, GROUP_INDEX to the
893    candidate group number if they are non-NULL.  If INDEX is -1, find
894    the last candidate group.  */
895
896 static MPlist *
897 find_candidates_group (MPlist *plist, int index,
898                        int *start_index, int *end_index, int *group_index)
899 {
900   int i = 0, gidx = 0, len;
901
902   MPLIST_DO (plist, plist)
903     {
904       if (MPLIST_MTEXT_P (plist))
905         len = mtext_nchars (MPLIST_MTEXT (plist));
906       else
907         len = mplist_length (MPLIST_PLIST (plist));
908       if (index < 0 ? MPLIST_TAIL_P (MPLIST_NEXT (plist))
909           : i + len > index)
910         {
911           if (start_index)
912             *start_index = i;
913           if (end_index)
914             *end_index = i + len;
915           if (group_index)
916             *group_index = gidx;
917           return plist;
918         }
919       i += len;
920       gidx++;
921     }
922   return NULL;
923 }
924
925 static void
926 preedit_insert (MInputContext *ic, int pos, MText *mt, int c)
927 {
928   MInputContextInfo *ic_info = ((MInputContext *) ic)->info;
929   MPlist *markers;
930   int nchars = mt ? mtext_nchars (mt) : 1;
931
932   if (mt)
933     mtext_ins (ic->preedit, pos, mt);
934   else
935     mtext_ins_char (ic->preedit, pos, c, 1);
936   MPLIST_DO (markers, ic_info->markers)
937     if (MPLIST_INTEGER (markers) > pos)
938       MPLIST_VAL (markers) = (void *) (MPLIST_INTEGER (markers) + nchars);
939   if (ic->cursor_pos >= pos)
940     ic->cursor_pos += nchars;
941   ic->preedit_changed = 1;
942 }
943
944
945 static void
946 preedit_delete (MInputContext *ic, int from, int to)
947 {
948   MInputContextInfo *ic_info = ((MInputContext *) ic)->info;
949   MPlist *markers;
950
951   mtext_del (ic->preedit, from, to);
952   MPLIST_DO (markers, ic_info->markers)
953     {
954       if (MPLIST_INTEGER (markers) > to)
955         MPLIST_VAL (markers)
956           = (void *) (MPLIST_INTEGER (markers) - (to - from));
957       else if (MPLIST_INTEGER (markers) > from);
958         MPLIST_VAL (markers) = (void *) from;
959     }
960   if (ic->cursor_pos >= to)
961     ic->cursor_pos -= to - from;
962   else if (ic->cursor_pos > from)
963     ic->cursor_pos = from;
964   ic->preedit_changed = 1;
965 }
966
967
968 static int
969 new_index (MInputContext *ic, int current, int limit, MSymbol sym, MText *mt)
970 {
971   int code = marker_code (sym);
972
973   if (mt && (code == '[' || code == ']'))
974     {
975       int pos = current;
976
977       if (code == '[' && current > 0)
978         {
979           if (mtext_prop_range (mt, Mcandidate_list, pos - 1, &pos, NULL, 1)
980               && pos > 0)
981             current = pos;
982         }
983       else if (code == ']' && current < mtext_nchars (mt))
984         {
985           if (mtext_prop_range (mt, Mcandidate_list, pos, NULL, &pos, 1))
986             current = pos;
987         }
988       return current;
989     }
990   if (code >= 0)
991     return (code == '<' ? 0
992             : code == '>' ? limit
993             : code == '-' ? current - 1
994             : code == '+' ? current + 1
995             : code == '=' ? current
996             : code - '0' > limit ? limit
997             : code - '0');
998   if (! ic)  
999     return 0;
1000   return (int) mplist_get (((MInputContextInfo *) ic->info)->markers, sym);
1001 }
1002
1003 static void
1004 update_candidate (MInputContext *ic, MTextProperty *prop, int idx)
1005 {
1006   int from = mtext_property_start (prop);
1007   int to = mtext_property_end (prop);
1008   int start;
1009   MPlist *candidate_list = mtext_property_value (prop);
1010   MPlist *group = find_candidates_group (candidate_list, idx, &start,
1011                                          NULL, NULL);
1012   int ingroup_index = idx - start;
1013   MText *mt;
1014
1015   preedit_delete (ic, from, to);
1016   if (MPLIST_MTEXT_P (group))
1017     {
1018       mt = MPLIST_MTEXT (group);
1019       preedit_insert (ic, from, NULL, mtext_ref_char (mt, ingroup_index));
1020       to = from + 1;
1021     }
1022   else
1023     {
1024       int i;
1025       MPlist *plist;
1026
1027       for (i = 0, plist = MPLIST_PLIST (group); i < ingroup_index;
1028            i++, plist = MPLIST_NEXT (plist));
1029       mt = MPLIST_MTEXT (plist);
1030       preedit_insert (ic, from, mt, 0);
1031       to = from + mtext_nchars (mt);
1032     }
1033   mtext_put_prop (ic->preedit, from, to, Mcandidate_list, candidate_list);
1034   mtext_put_prop (ic->preedit, from, to, Mcandidate_index, (void *) idx);
1035   ic->cursor_pos = to;
1036 }
1037
1038
1039 static int
1040 take_action_list (MInputContext *ic, MPlist *action_list)
1041 {
1042   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1043   MPlist *candidate_list = ic->candidate_list;
1044   int candidate_index = ic->candidate_index;
1045   int candidate_show = ic->candidate_show;
1046   MTextProperty *prop;
1047
1048   MPLIST_DO (action_list, action_list)
1049     {
1050       MPlist *action;
1051       MSymbol name;
1052       MPlist *args;
1053
1054       if (MPLIST_MTEXT_P (action_list)
1055           || MPLIST_INTEGER_P (action_list))
1056         name = Minsert, args = action_list;
1057       else if (MPLIST_PLIST_P (action_list)
1058                && (MPLIST_MTEXT_P (MPLIST_PLIST (action_list))
1059                    || MPLIST_PLIST_P (MPLIST_PLIST (action_list))))
1060         name = Minsert, args = action_list;
1061       else
1062         {
1063           action = MPLIST_PLIST (action_list);
1064           name = MPLIST_SYMBOL (action);
1065           args = MPLIST_NEXT (action);
1066         }
1067
1068       MDEBUG_PRINT1 (" %s", MSYMBOL_NAME (name));
1069       if (name == Minsert)
1070         {
1071           if (MPLIST_MTEXT_P (args))
1072             preedit_insert (ic, ic->cursor_pos, MPLIST_MTEXT (args), 0);
1073           else if (MPLIST_INTEGER_P (args))
1074             preedit_insert (ic, ic->cursor_pos, NULL, MPLIST_INTEGER (args));
1075           else if (MPLIST_SYMBOL_P (args))
1076             {
1077               int c = integer_value (ic, args);
1078
1079               if (c >= 0 && c <= MCHAR_MAX)
1080                 preedit_insert (ic, ic->cursor_pos, NULL, c);
1081             }
1082           else
1083             {
1084               MText *mt;
1085               int len;
1086
1087               args = MPLIST_PLIST (args);
1088               if (MPLIST_MTEXT_P (args))
1089                 {
1090                   preedit_insert (ic, ic->cursor_pos, NULL,
1091                                   mtext_ref_char (MPLIST_MTEXT (args), 0));
1092                   len = 1;
1093                 }
1094               else
1095                 {
1096                   mt = MPLIST_MTEXT (MPLIST_PLIST (args));
1097                   preedit_insert (ic, ic->cursor_pos, mt, 0);
1098                   len = mtext_nchars (mt);
1099                 }
1100               mtext_put_prop (ic->preedit,
1101                               ic->cursor_pos - len, ic->cursor_pos,
1102                               Mcandidate_list, args);
1103               mtext_put_prop (ic->preedit,
1104                               ic->cursor_pos - len, ic->cursor_pos,
1105                               Mcandidate_index, (void *) 0);
1106             }
1107         }
1108       else if (name == Mselect)
1109         {
1110           int start, end;
1111           int code, idx, gindex;
1112           int pos = ic->cursor_pos;
1113           MPlist *group;
1114
1115           if (pos == 0
1116               || ! (prop = mtext_get_property (ic->preedit, pos - 1,
1117                                                Mcandidate_list)))
1118             continue;
1119           if (MPLIST_SYMBOL_P (args))
1120             {
1121               code = marker_code (MPLIST_SYMBOL (args));
1122               if (code < 0)
1123                 continue;
1124             }
1125           else
1126             code = -1;
1127           idx = (int) mtext_get_prop (ic->preedit, pos - 1, Mcandidate_index);
1128           group = find_candidates_group (mtext_property_value (prop), idx,
1129                                          &start, &end, &gindex);
1130
1131           if (code != '[' && code != ']')
1132             {
1133               idx = (start
1134                      + (code >= 0
1135                         ? new_index (NULL, ic->candidate_index - start,
1136                                      end - start - 1, MPLIST_SYMBOL (args),
1137                                      NULL)
1138                         : MPLIST_INTEGER (args)));
1139               if (idx < 0)
1140                 {
1141                   find_candidates_group (mtext_property_value (prop), -1,
1142                                          NULL, &end, NULL);
1143                   idx = end - 1;
1144                 }
1145               else if (idx >= end
1146                        && MPLIST_TAIL_P (MPLIST_NEXT (group)))
1147                 idx = 0;
1148             }
1149           else
1150             {
1151               int ingroup_index = idx - start;
1152               int len;
1153
1154               group = mtext_property_value (prop);
1155               len = mplist_length (group);
1156               if (code == '[')
1157                 {
1158                   gindex--;
1159                   if (gindex < 0)
1160                     gindex = len - 1;;
1161                 }
1162               else
1163                 {
1164                   gindex++;
1165                   if (gindex >= len)
1166                     gindex = 0;
1167                 }
1168               for (idx = 0; gindex > 0; gindex--, group = MPLIST_NEXT (group))
1169                 idx += (MPLIST_MTEXT_P (group)
1170                         ? mtext_nchars (MPLIST_MTEXT (group))
1171                         : mplist_length (MPLIST_PLIST (group)));
1172               len = (MPLIST_MTEXT_P (group)
1173                      ? mtext_nchars (MPLIST_MTEXT (group))
1174                      : mplist_length (MPLIST_PLIST (group)));
1175               if (ingroup_index >= len)
1176                 ingroup_index = len - 1;
1177               idx += ingroup_index;
1178             }
1179           update_candidate (ic, prop, idx);
1180         }
1181       else if (name == Mshow)
1182         ic->candidate_show = 1;
1183       else if (name == Mhide)
1184         ic->candidate_show = 0;
1185       else if (name == Mdelete)
1186         {
1187           int len = mtext_nchars (ic->preedit);
1188           int to = (MPLIST_SYMBOL_P (args)
1189                     ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
1190                                  ic->preedit)
1191                     : MPLIST_INTEGER (args));
1192
1193           if (to < 0)
1194             to = 0;
1195           else if (to > len)
1196             to = len;
1197           if (to < ic->cursor_pos)
1198             preedit_delete (ic, to, ic->cursor_pos);
1199           else if (to > ic->cursor_pos)
1200             preedit_delete (ic, ic->cursor_pos, to);
1201         }
1202       else if (name == Mmove)
1203         {
1204           int len = mtext_nchars (ic->preedit);
1205           int pos
1206             = (MPLIST_SYMBOL_P (args)
1207                ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
1208                             ic->preedit)
1209                : MPLIST_INTEGER (args));
1210
1211           if (pos < 0)
1212             pos = 0;
1213           else if (pos > len)
1214             pos = len;
1215           if (pos != ic->cursor_pos)
1216             {
1217               ic->cursor_pos = pos;
1218               ic->preedit_changed = 1;
1219             }
1220         }
1221       else if (name == Mmark)
1222         {
1223           int code = marker_code (MPLIST_SYMBOL (args));
1224
1225           if (code < 0)
1226             mplist_put (ic_info->markers, MPLIST_SYMBOL (args),
1227                         (void *) ic->cursor_pos);
1228         }
1229       else if (name == Mpushback)
1230         {
1231           if (MPLIST_INTEGER_P (args))
1232             {
1233               int num = MPLIST_INTEGER (args);
1234
1235               if (num > 0)
1236                 ic_info->key_head -= num;
1237               else
1238                 ic_info->key_head = num;
1239               if (ic_info->key_head > ic_info->used)
1240                 ic_info->key_head = ic_info->used;
1241             }
1242           else if (MPLIST_MTEXT_P (args))
1243             {
1244               MText *mt = MPLIST_MTEXT (args);
1245               int i, len = mtext_nchars (mt);
1246               MSymbol key;
1247
1248               ic_info->key_head--;
1249               for (i = 0; i < len; i++)
1250                 {
1251                   key = one_char_symbol[MTEXT_DATA (mt)[i]];
1252                   if (ic_info->key_head + i < ic_info->used)
1253                     ic_info->keys[ic_info->key_head + i] = key;
1254                   else
1255                     MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
1256                 }
1257             }
1258           else
1259             {
1260               MPlist *plist = MPLIST_PLIST (args), *pl;
1261               int i = 0;
1262               MSymbol key;
1263
1264               ic_info->key_head--;
1265
1266               MPLIST_DO (pl, plist)
1267                 {
1268                   key = MPLIST_SYMBOL (pl);
1269                   if (ic_info->key_head < ic_info->used)
1270                     ic_info->keys[ic_info->key_head + i] = key;
1271                   else
1272                     MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
1273                   i++;
1274                 }
1275             }
1276         }
1277       else if (name == Mcall)
1278         {
1279           MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1280           MIMExternalFunc func = NULL;
1281           MSymbol module, func_name;
1282           MPlist *func_args, *val;
1283           int ret = 0;
1284
1285           module = MPLIST_SYMBOL (args);
1286           args = MPLIST_NEXT (args);
1287           func_name = MPLIST_SYMBOL (args);
1288
1289           if (im_info->externals)
1290             {
1291               MIMExternalModule *external
1292                 = (MIMExternalModule *) mplist_get (im_info->externals,
1293                                                     module);
1294               if (external)
1295                 func = (MIMExternalFunc) mplist_get (external->func_list,
1296                                                      func_name);
1297             }
1298           if (! func)
1299             continue;
1300           func_args = mplist ();
1301           mplist_add (func_args, Mt, ic);
1302           MPLIST_DO (args, MPLIST_NEXT (args))
1303             {
1304               int code;
1305
1306               if (MPLIST_KEY (args) == Msymbol
1307                   && MPLIST_KEY (args) != Mnil
1308                   && (code = marker_code (MPLIST_SYMBOL (args))) >= 0)
1309                 {
1310                   code = new_index (ic, ic->cursor_pos, 
1311                                     mtext_nchars (ic->preedit),
1312                                     MPLIST_SYMBOL (args), ic->preedit);
1313                   mplist_add (func_args, Minteger, (void *) code);
1314                 }
1315               else
1316                 mplist_add (func_args, MPLIST_KEY (args), MPLIST_VAL (args));
1317             }
1318           val = (func) (func_args);
1319           M17N_OBJECT_UNREF (func_args);
1320           if (val && ! MPLIST_TAIL_P (val))
1321             ret = take_action_list (ic, val);
1322           M17N_OBJECT_UNREF (val);
1323           if (ret < 0)
1324             return ret;
1325         }
1326       else if (name == Mshift)
1327         {
1328           shift_state (ic, MPLIST_SYMBOL (args));
1329         }
1330       else if (name == Mundo)
1331         {
1332           MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1333           int unhandle = 0;
1334
1335           mtext_reset (ic->preedit);
1336           mtext_reset (ic_info->preedit_saved);
1337           ic->cursor_pos = ic_info->state_pos = 0;
1338           ic_info->state_key_head = ic_info->key_head = 0;
1339           ic_info->used -= 2;
1340           if (ic_info->used < 0)
1341             {
1342               ic_info->used = 0;
1343               unhandle = 1;
1344             }
1345           shift_state (ic, ((MIMState *) MPLIST_VAL (im_info->states))->name);
1346           if (unhandle)
1347             return -1;
1348           break;
1349         }
1350       else if (name == Mset || name == Madd || name == Msub
1351                || name == Mmul || name == Mdiv)
1352         {
1353           MSymbol sym = MPLIST_SYMBOL (args);
1354           int val1 = (int) mplist_get (ic_info->vars, sym), val2;
1355
1356           args = MPLIST_NEXT (args);
1357           val2 = integer_value (ic, args);
1358           if (name == Mset)
1359             val1 = val2;
1360           else if (name == Madd)
1361             val1 += val2;
1362           else if (name == Msub)
1363             val1 -= val2;
1364           else if (name == Mmul)
1365             val1 *= val2;
1366           else
1367             val1 /= val2;
1368           mplist_put (ic_info->vars, sym, (void *) val1);
1369           MDEBUG_PRINT2 ("(%s=%d)", MSYMBOL_NAME (sym), val1);
1370         }
1371       else if (name == Mequal || name == Mless || name == Mgreater)
1372         {
1373           int val1, val2;
1374           MPlist *actions1, *actions2;
1375           int ret = 0;
1376
1377           val1 = integer_value (ic, args);
1378           args = MPLIST_NEXT (args);
1379           val2 = integer_value (ic, args);
1380           args = MPLIST_NEXT (args);
1381           actions1 = MPLIST_PLIST (args);
1382           args = MPLIST_NEXT (args);
1383           if (MPLIST_TAIL_P (args))
1384             actions2 = NULL;
1385           else
1386             actions2 = MPLIST_PLIST (args);
1387           MDEBUG_PRINT2 ("(%d,%d)", val1, val2);
1388           if (name == Mequal ? val1 == val2
1389               : name == Mless ? val1 < val2
1390               : val1 > val2)
1391             {
1392               MDEBUG_PRINT ("ok");
1393               ret = take_action_list (ic, actions1);
1394             }
1395           else
1396             {
1397               MDEBUG_PRINT ("no");
1398               if (actions2)
1399                 ret = take_action_list (ic, actions2);
1400             }
1401           if (ret < 0)
1402             return ret;
1403         }
1404       else
1405         {
1406           MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1407           MPlist *actions;
1408
1409           if (im_info->macros
1410               && (actions = mplist_get (im_info->macros, name)))
1411             {
1412               if (take_action_list (ic, actions) < 0)
1413                 return -1;
1414             };
1415         }
1416     }
1417
1418   prop = NULL;
1419   ic->candidate_list = NULL;
1420   if (ic->cursor_pos > 0
1421       && (prop = mtext_get_property (ic->preedit, ic->cursor_pos - 1,
1422                                      Mcandidate_list)))
1423     {
1424       ic->candidate_list = mtext_property_value (prop);
1425       ic->candidate_index
1426         = (int) mtext_get_prop (ic->preedit, ic->cursor_pos - 1,
1427                                 Mcandidate_index);
1428       ic->candidate_from = mtext_property_start (prop);
1429       ic->candidate_to = mtext_property_end (prop);
1430     }
1431
1432   ic->candidates_changed |= (candidate_list != ic->candidate_list
1433                              || candidate_index != ic->candidate_index
1434                              || candidate_show != ic->candidate_show);
1435   return 0;
1436 }
1437
1438
1439 /* Handle the input key KEY in the current state and map specified in
1440    the input context IC.  If KEY is handled correctly, return 0.
1441    Otherwise, return -1.  */
1442
1443 static int
1444 handle_key (MInputContext *ic)
1445 {
1446   MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1447   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1448   MIMMap *map = ic_info->map;
1449   MIMMap *submap = NULL;
1450   MSymbol key = ic_info->keys[ic_info->key_head];
1451   int i;
1452
1453   MDEBUG_PRINT2 ("  [IM] handle `%s' in state %s", 
1454                  MSYMBOL_NAME (key), MSYMBOL_NAME (ic_info->state->name));
1455
1456   if (map->submaps)
1457     {
1458       MSymbol alias;
1459
1460       submap = mplist_get (map->submaps, key);
1461       if (! submap && (alias = msymbol_get (key, M_key_alias)) != Mnil)
1462         submap = mplist_get (map->submaps, alias);
1463     }
1464
1465   if (submap)
1466     {
1467       MDEBUG_PRINT (" submap-found");
1468       mtext_cpy (ic->preedit, ic_info->preedit_saved);
1469       ic->cursor_pos = ic_info->state_pos;
1470       ic_info->key_head++;
1471       ic_info->map = map = submap;
1472       if (map->map_actions)
1473         {
1474           MDEBUG_PRINT (" map-actions:");
1475           if (take_action_list (ic, map->map_actions) < 0)
1476             {
1477               MDEBUG_PRINT ("\n");
1478               return -1;
1479             }
1480         }
1481       else if (map->submaps)
1482         {
1483           for (i = ic_info->state_key_head; i < ic_info->key_head; i++)
1484             {
1485               MSymbol key = ic_info->keys[i];
1486               char *name = msymbol_name (key);
1487
1488               if (! name[0] || ! name[1])
1489                 mtext_ins_char (ic->preedit, ic->cursor_pos++, name[0], 1);
1490             }
1491           ic->preedit_changed = 1;
1492         }
1493
1494       /* If this is the terminal map or we have shifted to another
1495          state, perform branch actions (if any).  */
1496       if (! map->submaps || map != ic_info->map)
1497         {
1498           if (map->branch_actions)
1499             {
1500               MDEBUG_PRINT (" branch-actions:");
1501               if (take_action_list (ic, map->branch_actions) < 0)
1502                 {
1503                   MDEBUG_PRINT ("\n");
1504                   return -1;
1505                 }
1506             }
1507           /* If MAP is still not the root map, shift to the current
1508              state.  */
1509           if (ic_info->map != ic_info->state->map)
1510             shift_state (ic, ic_info->state->name);
1511         }
1512     }
1513   else
1514     {
1515       /* MAP can not handle KEY.  */
1516
1517       /* If MAP is the root map of the initial state, it means that
1518          the current input method can not handle KEY.  */
1519       if (map == ((MIMState *) MPLIST_VAL (im_info->states))->map)
1520         {
1521           MDEBUG_PRINT (" unhandled\n");
1522           return -1;
1523         }
1524
1525       if (map != ic_info->state->map)
1526         {
1527           /* If MAP is not the root map... */
1528           /* If MAP has branch actions, perform them.  */
1529           if (map->branch_actions)
1530             {
1531               MDEBUG_PRINT (" branch-actions:");
1532               take_action_list (ic, map->branch_actions);
1533             }
1534           /* If MAP is still not the root map, shift to the current
1535              state. */
1536           if (ic_info->map != ic_info->state->map)
1537             {
1538               shift_state (ic, ic_info->state->name);
1539               /* If MAP has branch_actions, perform them.  */
1540               if (ic_info->map->branch_actions)
1541                 {
1542                   MDEBUG_PRINT (" init-actions:");
1543                   take_action_list (ic, ic_info->map->branch_actions);
1544                 }
1545             }
1546         }
1547       else
1548         {
1549           /* MAP is the root map, perform branch actions (if any) or
1550              shift to the initial state.  */
1551           if (map->branch_actions)
1552             {
1553               MDEBUG_PRINT (" branch-actions:");
1554               take_action_list (ic, map->branch_actions);
1555             }
1556           else
1557             shift_state (ic,
1558                          ((MIMState *) MPLIST_VAL (im_info->states))->name);
1559         }
1560     }
1561   MDEBUG_PRINT ("\n");
1562   return 0;
1563 }
1564
1565 static void
1566 reset_ic (MInputContext *ic, MSymbol ignore)
1567 {
1568   MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1569   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1570
1571   if (im_info->states)
1572     /* Shift to the initial state.  */
1573     shift_state (ic, Mnil);
1574   else
1575     ic_info->state = NULL;
1576   MLIST_RESET (ic_info);
1577   ic_info->map = ic_info->state ? ic_info->state->map : NULL;
1578   ic_info->state_key_head = ic_info->key_head = 0;
1579   ic_info->key_unhandled = 0;
1580   ic->cursor_pos = ic_info->state_pos = 0;
1581   ic->status = ic_info->state ? ic_info->state->title : NULL;
1582   if (! ic->status)
1583     ic->status = im_info->title;
1584   ic->candidate_list = NULL;
1585   ic->candidate_show = 0;
1586   ic->status_changed = ic->preedit_changed = ic->candidates_changed = 1;
1587 }
1588
1589 static int
1590 open_im (MInputMethod *im)
1591 {
1592   MDatabase *mdb;
1593   MInputMethodInfo *im_info;
1594   MPlist *plist;
1595   int result;
1596
1597   mdb = mdatabase_find (Minput_method, im->language, im->name, Mnil);
1598   if (! mdb)
1599     return -1;
1600   plist = mdatabase_load (mdb);
1601   if (! plist)
1602     MERROR (MERROR_IM, -1);
1603   MSTRUCT_CALLOC (im_info, MERROR_IM);
1604   im->info = im_info;
1605   result = load_input_method (im->language, im->name, plist, im_info);
1606   M17N_OBJECT_UNREF (plist);
1607   if (result < 0)
1608     MERROR (MERROR_IM, -1);
1609   return 0;
1610 }
1611
1612 static void
1613 close_im (MInputMethod *im)
1614 {
1615   MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
1616   MPlist *plist;
1617
1618   if (im_info->title)
1619     M17N_OBJECT_UNREF (im_info->title);
1620   if (im_info->states)
1621     {
1622       MPLIST_DO (plist, im_info->states)
1623         {
1624           MIMState *state = (MIMState *) MPLIST_VAL (plist);
1625
1626           if (state->title)
1627             M17N_OBJECT_UNREF (state->title);
1628           if (state->map)
1629             free_map (state->map);
1630           free (state);
1631         }
1632       M17N_OBJECT_UNREF (im_info->states);
1633     }
1634
1635   if (im_info->macros)
1636     {
1637       MPLIST_DO (plist, im_info->macros)
1638         M17N_OBJECT_UNREF (MPLIST_VAL (plist)); 
1639       M17N_OBJECT_UNREF (im_info->macros);
1640     }
1641
1642   if (im_info->externals)
1643     {
1644       MPLIST_DO (plist, im_info->externals)
1645         {
1646           MIMExternalModule *external = MPLIST_VAL (plist);
1647
1648           dlclose (external->handle);
1649           M17N_OBJECT_UNREF (external->func_list);
1650           free (external);
1651           MPLIST_KEY (plist) = Mt;
1652         }
1653       M17N_OBJECT_UNREF (im_info->externals);
1654     }
1655   free (im_info);
1656   im->info = NULL;
1657 }
1658
1659
1660 static int
1661 create_ic (MInputContext *ic)
1662 {
1663   MInputMethod *im = ic->im;
1664   MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
1665   MInputContextInfo *ic_info;
1666
1667   if (ic->info)
1668     ic_info = (MInputContextInfo *) ic->info;
1669   else
1670     {
1671       MSTRUCT_CALLOC (ic_info, MERROR_IM);
1672       ic->info = ic_info;
1673     }
1674   MLIST_INIT1 (ic_info, keys, 8);
1675   ic_info->markers = mplist ();
1676   ic_info->vars = mplist ();
1677   ic_info->preedit_saved = mtext ();
1678   if (im_info->externals)
1679     {
1680       MPlist *func_args = mplist (), *plist;
1681
1682       mplist_add (func_args, Mt, ic);
1683       MPLIST_DO (plist, im_info->externals)
1684         {
1685           MIMExternalModule *external = MPLIST_VAL (plist);
1686           MIMExternalFunc func
1687             = (MIMExternalFunc) mplist_get (external->func_list, Minit);
1688
1689           if (func)
1690             (func) (func_args);
1691         }
1692       M17N_OBJECT_UNREF (func_args);
1693     }
1694   reset_ic (ic, Mnil);
1695   return 0;
1696 }
1697
1698 static void
1699 destroy_ic (MInputContext *ic)
1700 {
1701   MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1702   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1703
1704   if (im_info->externals)
1705     {
1706       MPlist *func_args = mplist (), *plist;
1707
1708       mplist_add (func_args, Mt, ic);
1709       MPLIST_DO (plist, im_info->externals)
1710         {
1711           MIMExternalModule *external = MPLIST_VAL (plist);
1712           MIMExternalFunc func
1713             = (MIMExternalFunc) mplist_get (external->func_list, Mfini);
1714
1715           if (func)
1716             (func) (func_args);
1717         }
1718       M17N_OBJECT_UNREF (func_args);
1719     }
1720   MLIST_FREE1 (ic_info, keys);
1721   M17N_OBJECT_UNREF (ic_info->preedit_saved);
1722   M17N_OBJECT_UNREF (ic_info->markers);
1723   M17N_OBJECT_UNREF (ic_info->vars);
1724   free (ic->info);
1725 }
1726
1727
1728 /** Handle the input key KEY in the current state and map of IC->info.
1729     If KEY is handled but no text is produced, return 0, otherwise
1730     return 1.
1731
1732     Ignore ARG.  */
1733
1734 static int
1735 filter (MInputContext *ic, MSymbol key, void *arg)
1736 {
1737   MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1738   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1739   int i = 0;
1740
1741   if (! ic_info->state)
1742     {
1743       ic_info->key_unhandled = 1;
1744       return 0;
1745     }
1746   mtext_reset (ic->produced);
1747   ic->status_changed = ic->preedit_changed = ic->candidates_changed = 0;
1748   MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
1749   ic_info->key_unhandled = 0;
1750   do {
1751     if (handle_key (ic) < 0)
1752       {
1753         /* KEY was not handled.  Reset the status and break the
1754            loop.  */
1755         reset_ic (ic, Mnil);
1756         /* This forces returning 1.  */
1757         ic_info->key_unhandled = 1;
1758         break;
1759       }
1760     if (i++ == 100)
1761       {
1762         mdebug_hook ();
1763         reset_ic (ic, Mnil);
1764         ic_info->key_unhandled = 1;
1765         break;
1766       }
1767     /* Break the loop if all keys were handled.  */
1768   } while (ic_info->key_head < ic_info->used);
1769
1770   /* If the current map is the root of the initial state, we should
1771      produce any preedit text in ic->produced.  */
1772   if (ic_info->map == ((MIMState *) MPLIST_VAL (im_info->states))->map
1773       && mtext_nchars (ic->preedit) > 0)
1774     shift_state (ic, ((MIMState *) MPLIST_VAL (im_info->states))->name);
1775
1776   if (mtext_nchars (ic->produced) > 0)
1777     {
1778       MSymbol lang = msymbol_get (ic->im->language, Mlanguage);
1779
1780       if (lang != Mnil)
1781         mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
1782                         Mlanguage, ic->im->language);
1783     }
1784
1785   return (! ic_info->key_unhandled && mtext_nchars (ic->produced) == 0);
1786 }
1787
1788
1789 /** Return 1 if the last event or key was not handled, otherwise
1790     return 0.
1791
1792     There is no need of looking up because ic->produced should already
1793     contain the produced text (if any).
1794
1795     Ignore KEY.  */
1796
1797 static int
1798 lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
1799 {
1800   mtext_cat (mt, ic->produced);
1801   mtext_reset (ic->produced);
1802   return (((MInputContextInfo *) ic->info)->key_unhandled ? -1 : 0);
1803 }
1804
1805 static MPlist *load_im_info_keys;
1806
1807 static MPlist *
1808 load_im_info (MSymbol language, MSymbol name, MSymbol key)
1809 {
1810   MDatabase *mdb;
1811   MPlist *plist;
1812
1813   if (language == Mnil || name == Mnil)
1814     MERROR (MERROR_IM, NULL);
1815
1816   mdb = mdatabase_find (Minput_method, language, name, Mnil);
1817   if (! mdb)
1818     MERROR (MERROR_IM, NULL);
1819   mplist_push (load_im_info_keys, key, Mt);
1820   plist = mdatabase__load_for_keys (mdb, load_im_info_keys);
1821   mplist_pop (load_im_info_keys);
1822   return plist;
1823 }
1824
1825 \f
1826 /* Input method command handler.  */
1827
1828 /* List of all (global and local) commands. 
1829    (LANG:(IM-NAME:(COMMAND ...) ...) ...) ...
1830    COMMAND is CMD-NAME:(mtext:DESCRIPTION plist:KEYSEQ ...))
1831    Global commands are storead as (t (t COMMAND ...))  */
1832 static MPlist *command_list;
1833
1834 /* Check if PLIST is a valid command key sequence.
1835    PLIST must be NULL or:
1836    [ symbol:KEY | integer:KEY ] ...  */
1837
1838 static int
1839 check_command_keyseq (MPlist *plist)
1840 {
1841   if (! plist)
1842     return 0;
1843   MPLIST_DO (plist, plist)
1844     {
1845       if (MPLIST_SYMBOL_P (plist))
1846         continue;
1847       else if (MPLIST_INTEGER_P (plist))
1848         {
1849           int n = MPLIST_INTEGER (plist);
1850
1851           if (n < 0 || n > 9)
1852             return -1;
1853           MPLIST_KEY (plist) = Msymbol;
1854           MPLIST_VAL (plist) = one_char_symbol['0' + 9];
1855         }
1856       else
1857         return -1;
1858     }
1859   return 0;
1860 }
1861
1862 static MText *
1863 get_description_advance (MPlist *plist)
1864 {
1865   MText *mt;
1866   int pos;
1867
1868   if (! MPLIST_MTEXT_P (plist))
1869     return NULL;
1870   mt = mplist_pop (plist);
1871   pos = mtext_chr (mt, '\n'); 
1872   if (pos > 0)
1873     {
1874       MText *detail = mtext_copy (mtext (), 0, mt, pos + 1, mtext_nchars (mt));
1875       mtext_del (mt, pos, mtext_nchars (mt));
1876       mtext_put_prop (mt, 0, pos, Mdetail_text, detail);
1877       M17N_OBJECT_UNREF (detail);
1878     }
1879   return mt;
1880 }
1881
1882 static MPlist *
1883 parse_command_list (MPlist *plist, MPlist *global_list)
1884 {
1885   MPlist *val = mplist ();
1886
1887   /* PLIST ::= (sym:CMD mtext:DESCRIPTION ? (sym:KEY ...) ...) ... */
1888   MPLIST_DO (plist, plist)
1889     {
1890       MSymbol cmd;
1891       MText *mt;
1892       MPlist *this_val, *pl, *p;
1893
1894       if (! MPLIST_PLIST_P (plist))
1895         continue;
1896       pl = MPLIST_PLIST (plist);
1897       if (! MPLIST_SYMBOL_P (pl))
1898         continue;
1899       cmd = MPLIST_SYMBOL (pl);
1900       pl = MPLIST_NEXT (pl);
1901       mt = get_description_advance (pl);
1902       this_val = mplist ();
1903
1904       if (! mt && global_list)
1905         {
1906           /* Get the description from global_list.  */
1907           p = mplist_get (global_list, cmd);
1908           if (p && MPLIST_MTEXT (p))
1909             {
1910               mt = MPLIST_MTEXT (p);
1911               M17N_OBJECT_REF (mt);
1912             }
1913         }
1914       if (! mt)
1915         mt = mtext ();
1916       mplist_add (this_val, Mtext, mt);
1917       M17N_OBJECT_UNREF (mt);
1918
1919       /* PL ::= (sym:KEY ...) ... */
1920       MPLIST_DO (pl, pl)
1921         {
1922           if (MPLIST_PLIST_P (pl)
1923               && check_command_keyseq (MPLIST_PLIST (pl)) >= 0)
1924             /* All the elements are valid keys.  */
1925             mplist_add (this_val, Mplist, MPLIST_PLIST (pl));
1926         }
1927
1928       mplist_put (val, cmd, this_val);
1929     }
1930   return val;
1931 }
1932
1933 static MPlist *
1934 get_command_list (MSymbol language, MSymbol name)
1935 {
1936   MPlist *per_lang;
1937   MPlist *plist, *pl;
1938
1939   if (name == Mnil)
1940     language = name = Mt;
1941
1942   if (! command_list)
1943     {
1944       MDatabase *mdb = mdatabase_find (msymbol ("input"), M_command,
1945                                        Mnil, Mnil);
1946
1947       if (mdb && (plist = mdatabase_load (mdb)))
1948         {
1949           pl = parse_command_list (plist, NULL);
1950           M17N_OBJECT_UNREF (plist);
1951         }
1952       else
1953         pl = mplist ();
1954       plist = mplist ();
1955       mplist_add (plist, Mt, pl);
1956       command_list = mplist ();
1957       mplist_add (command_list, Mt, plist);
1958     }
1959
1960   per_lang = mplist_get (command_list, language);
1961   if (per_lang)
1962     {
1963       plist = mplist_find_by_key (per_lang, name);
1964       if (plist)
1965         return (MPLIST_VAL (plist));
1966     }
1967   else
1968     {
1969       per_lang = mplist ();
1970       mplist_add (command_list, language, per_lang);
1971     }
1972
1973   /* Now we are sure that we are loading per-im info.  */
1974   /* Get the global command list.  */
1975   plist = load_im_info (language, name, M_command);
1976   if (! plist || mplist_key (plist) == Mnil)
1977     {
1978       if (! plist)
1979         plist = mplist ();
1980       mplist_add (per_lang, name, plist);
1981       return plist;
1982     }
1983   pl = parse_command_list (mplist_value (plist),
1984                            mplist_get ((MPlist *) mplist_get (command_list, Mt),
1985                                        Mt));
1986   M17N_OBJECT_UNREF (plist);
1987   mplist_put (per_lang, name, pl);
1988   return pl;
1989 }
1990
1991 \f
1992 /* Input method variable handler.  */
1993
1994 /* List of all variables. 
1995    (LANG:(IM-NAME:(VAR ...) ...) ...) ...
1996    VAR is VAR-NAME:(mtext:DESCRIPTION TYPE:VALUE ...))  */
1997
1998 static MPlist *variable_list;
1999
2000 static MPlist *
2001 parse_variable_list (MPlist *plist)
2002 {
2003   MPlist *val = mplist (), *pl, *p;
2004
2005   /* PLIST ::= (sym:VAR mtext:DESCRIPTION TYPE:INIT-VAL ...) ...  */
2006   MPLIST_DO (plist, plist)
2007     {
2008       MSymbol var, type;
2009       MText *mt;
2010       MPlist *this_val;
2011
2012       if (! MPLIST_PLIST_P (plist))
2013         continue;
2014       pl = MPLIST_PLIST (plist);
2015       if (! MPLIST_SYMBOL_P (pl))
2016         continue;
2017       var = MPLIST_SYMBOL (pl);
2018       pl = MPLIST_NEXT (pl);
2019       mt = get_description_advance (pl);
2020       if (! mt || MPLIST_TAIL_P (pl))
2021         continue;
2022       this_val = mplist ();
2023       mplist_add (this_val, Mtext, mt);
2024       M17N_OBJECT_UNREF (mt);
2025       type = MPLIST_KEY (pl);
2026       mplist_add (this_val, type, MPLIST_VAL (pl));
2027       MPLIST_DO (pl, MPLIST_NEXT (pl))
2028         {
2029           if (type != MPLIST_KEY (pl)
2030               && (type != Minteger || ! MPLIST_PLIST_P (pl)))
2031             break;
2032           if (MPLIST_PLIST_P (pl))
2033             {
2034               MPLIST_DO (p, MPLIST_PLIST (pl))
2035                 if (! MPLIST_INTEGER_P (p))
2036                   break;
2037               if (! MPLIST_TAIL_P (p))
2038                 break;
2039             }
2040           mplist_add (this_val, MPLIST_KEY (pl), MPLIST_VAL (pl));
2041         }
2042
2043       mplist_put (val, var, this_val);
2044     }
2045   return val;
2046 }
2047
2048
2049 static MPlist *
2050 get_variable_list (MSymbol language, MSymbol name)
2051 {
2052   MPlist *per_lang;
2053   MPlist *plist, *pl;
2054
2055   if (language == Mnil || name == Mnil)
2056     MERROR (MERROR_IM, NULL);
2057   if (! variable_list)
2058     variable_list = mplist ();
2059   per_lang = mplist_get (variable_list, language);
2060   if (per_lang)
2061     {
2062       plist = mplist_find_by_key (per_lang, name);
2063       if (plist)
2064         return (MPLIST_VAL (plist));
2065     }
2066   else
2067     {
2068       per_lang = mplist ();
2069       mplist_add (variable_list, language, per_lang);
2070     }
2071   plist = load_im_info (language, name, M_variable);
2072   if (! plist || mplist_key (plist) == Mnil)
2073     {
2074       if (! plist)
2075         plist = mplist ();
2076       mplist_add (per_lang, name, plist);
2077       return plist;
2078     }
2079   pl = parse_variable_list (mplist_value (plist));
2080   M17N_OBJECT_UNREF (plist);
2081   mplist_put (per_lang, name, pl);
2082   return pl;
2083 }
2084
2085 static void
2086 input_method_hook (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
2087 {
2088   MPlist *plist, *pl, *p;
2089   char path[PATH_MAX];
2090
2091   /* Cancel the hook.  */
2092   msymbol_put (tag0, M_database_hook, NULL);
2093   tag3 = Mnil;
2094
2095   mplist_push (load_im_info_keys, M_description, Mt);
2096   MPLIST_DO (plist, mdatabase__dir_list)
2097     {
2098       char *dirname = (char *) MPLIST_VAL (plist);
2099       int dirlen;
2100       DIR *dir = opendir (dirname);
2101       struct dirent *dp;
2102
2103       if (! dir)
2104         continue;
2105       dirlen = strlen (dirname);
2106       strcpy (path, dirname);
2107       while ((dp = readdir (dir)) != NULL)
2108         {
2109           /* We can't trust dp->d_nameln.  */
2110           int len = strlen (dp->d_name);
2111           FILE *fp;
2112
2113           if (len > 4 && memcmp (dp->d_name + len - 4, ".mim", 4) == 0)
2114             {
2115               strcpy (path + dirlen, dp->d_name);
2116               fp = fopen (path, "r");
2117               if (! fp)
2118                 continue;
2119               pl = mplist__from_file (fp, load_im_info_keys);
2120               fclose (fp);
2121               if (pl)
2122                 {
2123                   if (MPLIST_PLIST_P (pl))
2124                     {
2125                       p = MPLIST_PLIST (pl);
2126                       p = MPLIST_NEXT (p);
2127                       if (MPLIST_SYMBOL_P (p))
2128                         {
2129                           tag1 = MPLIST_VAL (p);
2130                           p = MPLIST_NEXT (p);
2131                           if (MPLIST_SYMBOL_P (p))
2132                             {
2133                               tag2 = MPLIST_VAL (p);
2134                               mdatabase_define (tag0, tag1, tag2, tag3,
2135                                                 NULL, path);
2136                             }
2137                         }
2138                     }
2139                   M17N_OBJECT_UNREF (pl);
2140                 }
2141             }
2142         }
2143       closedir (dir);
2144     }
2145   mplist_pop (load_im_info_keys);
2146 }
2147
2148
2149 /* Support functions for mdebug_dump_im.  */
2150
2151 static void
2152 dump_im_map (MPlist *map_list, int indent)
2153 {
2154   char *prefix;
2155   MSymbol key = MPLIST_KEY (map_list);
2156   MIMMap *map = (MIMMap *) MPLIST_VAL (map_list);
2157
2158   prefix = (char *) alloca (indent + 1);
2159   memset (prefix, 32, indent);
2160   prefix[indent] = '\0';
2161
2162   fprintf (stderr, "(\"%s\" ", msymbol_name (key));
2163   if (map->map_actions)
2164     mdebug_dump_plist (map->map_actions, indent + 2);
2165   if (map->submaps)
2166     {
2167       MPLIST_DO (map_list, map->submaps)
2168         {
2169           fprintf (stderr, "\n%s  ", prefix);
2170           dump_im_map (map_list, indent + 2);
2171         }
2172     }
2173   if (map->branch_actions)
2174     {
2175       fprintf (stderr, "\n%s  (branch\n%s    ", prefix, prefix);
2176       mdebug_dump_plist (map->branch_actions, indent + 4);
2177       fprintf (stderr, ")");      
2178     }
2179   fprintf (stderr, ")");
2180 }
2181
2182
2183 static void
2184 dump_im_state (MIMState *state, int indent)
2185 {
2186   char *prefix;
2187   MPlist *map_list;
2188
2189   prefix = (char *) alloca (indent + 1);
2190   memset (prefix, 32, indent);
2191   prefix[indent] = '\0';
2192
2193   fprintf (stderr, "(%s", msymbol_name (state->name));
2194   if (state->map->submaps)
2195     {
2196       MPLIST_DO (map_list, state->map->submaps)
2197         {
2198           fprintf (stderr, "\n%s  ", prefix);
2199           dump_im_map (map_list, indent + 2);
2200         }
2201     }
2202   fprintf (stderr, ")");
2203 }
2204
2205 \f
2206
2207 int
2208 minput__init ()
2209 {
2210   char *key_names[32]
2211     = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2212         "BackSpace", "Tab", "Linefeed", "Clear", NULL, "Return", NULL, NULL,
2213         NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2214         NULL, NULL, NULL, "Escape", NULL, NULL, NULL, NULL };
2215   char buf[6], buf2[256];
2216   int i;
2217   MPlist *plist;
2218
2219   Minput_method = msymbol ("input-method");
2220   msymbol_put (Minput_method, M_database_hook, (void *) input_method_hook);
2221   Minput_driver = msymbol ("input-driver");
2222   Mtitle = msymbol ("title");
2223   Mmacro = msymbol ("macro");
2224   Mmodule = msymbol ("module");
2225   Mmap = msymbol ("map");
2226   Mstate = msymbol ("state");
2227   Minsert = msymbol ("insert");
2228   Mdelete = msymbol ("delete");
2229   Mmove = msymbol ("move");
2230   Mmark = msymbol ("mark");
2231   Mpushback = msymbol ("pushback");
2232   Mundo = msymbol ("undo");
2233   Mcall = msymbol ("call");
2234   Mshift = msymbol ("shift");
2235   Mselect = msymbol ("select");
2236   Mshow = msymbol ("show");
2237   Mhide = msymbol ("hide");
2238   Mset = msymbol ("set");
2239   Madd = msymbol ("add");
2240   Msub = msymbol ("sub");
2241   Mmul = msymbol ("mul");
2242   Mdiv = msymbol ("div");
2243   Mequal = msymbol ("=");
2244   Mless = msymbol ("<");
2245   Mgreater = msymbol (">");
2246
2247   Minput_preedit_start = msymbol ("input-preedit-start");
2248   Minput_preedit_done = msymbol ("input-preedit-done");
2249   Minput_preedit_draw = msymbol ("input-preedit-draw");
2250   Minput_status_start = msymbol ("input-status-start");
2251   Minput_status_done = msymbol ("input-status-done");
2252   Minput_status_draw = msymbol ("input-status-draw");
2253   Minput_candidates_start = msymbol ("input-candidates-start");
2254   Minput_candidates_done = msymbol ("input-candidates-done");
2255   Minput_candidates_draw = msymbol ("input-candidates-draw");
2256   Minput_set_spot = msymbol ("input-set-spot");
2257   Minput_focus_move = msymbol ("input-focus-move");
2258   Minput_focus_in = msymbol ("input-focus-in");
2259   Minput_focus_out = msymbol ("input-focus-out");
2260   Minput_toggle = msymbol ("input-toggle");
2261   Minput_reset = msymbol ("input-reset");
2262
2263   Mcandidate_list = msymbol_as_managing_key ("  candidate-list");
2264   Mcandidate_index = msymbol ("  candidate-index");
2265
2266   Minit = msymbol ("init");
2267   Mfini = msymbol ("fini");
2268
2269   M_key_alias = msymbol ("  key-alias");
2270   M_description = msymbol ("description");
2271   M_command = msymbol ("command");
2272   M_variable = msymbol ("variable");
2273
2274   Mdetail_text = msymbol_as_managing_key ("  detail-text");
2275
2276   load_im_info_keys = mplist ();
2277   plist = mplist_add (load_im_info_keys, Mmap, Mnil);
2278   plist = mplist_add (plist, Mstate, Mnil);
2279   plist = mplist_add (plist, Mmacro, Mnil);
2280   plist = mplist_add (plist, Mmodule, Mnil);
2281
2282   buf[0] = 'C';
2283   buf[1] = '-';
2284   buf[3] = '\0';
2285   for (i = 0, buf[2] = '@'; i < ' '; i++, buf[2]++)
2286     {
2287       one_char_symbol[i] = msymbol (buf);
2288       if (key_names[i])
2289         msymbol_put (one_char_symbol[i], M_key_alias,  msymbol (key_names[i]));
2290     }
2291   for (buf[2] = i; i < 127; i++, buf[2]++)
2292     one_char_symbol[i] = msymbol (buf + 2);
2293   one_char_symbol[i++] = msymbol ("Delete");
2294   buf[2] = 'M';
2295   buf[3] = '-';
2296   buf[5] = '\0';
2297   buf2[0] = 'M';
2298   buf2[1] = '-';
2299   for (buf[4] = '@'; i < 160; i++, buf[4]++)
2300     {
2301       one_char_symbol[i] = msymbol (buf);
2302       if (key_names[i - 128])
2303         {
2304           strcpy (buf2 + 2, key_names[i - 128]);
2305           msymbol_put (one_char_symbol[i], M_key_alias,  msymbol (buf2));
2306         }
2307     }
2308   for (buf[4] = i - 128; i < 255; i++, buf[4]++)
2309     one_char_symbol[i] = msymbol (buf + 2);
2310   one_char_symbol[i] = msymbol ("M-Delete");
2311
2312   command_list = variable_list = NULL;
2313
2314   minput_default_driver.open_im = open_im;
2315   minput_default_driver.close_im = close_im;
2316   minput_default_driver.create_ic = create_ic;
2317   minput_default_driver.destroy_ic = destroy_ic;
2318   minput_default_driver.filter = filter;
2319   minput_default_driver.lookup = lookup;
2320   minput_default_driver.callback_list = mplist ();
2321   mplist_put (minput_default_driver.callback_list, Minput_reset,
2322               (void *) reset_ic);
2323   minput_driver = &minput_default_driver;
2324   return 0;
2325 }
2326
2327 void
2328 minput__fini ()
2329 {
2330   MPlist *par_lang, *par_im, *p;
2331
2332   if (command_list)
2333     {
2334       MPLIST_DO (par_lang, command_list)
2335         {
2336           MPLIST_DO (par_im, MPLIST_VAL (par_lang))
2337             {
2338               MPLIST_DO (p, MPLIST_VAL (par_im))
2339                 M17N_OBJECT_UNREF (MPLIST_VAL (p));
2340               M17N_OBJECT_UNREF (MPLIST_VAL (par_im));
2341             }
2342           M17N_OBJECT_UNREF (MPLIST_VAL (par_lang));
2343         }
2344       M17N_OBJECT_UNREF (command_list);
2345       command_list = NULL;
2346     }
2347   if (variable_list)
2348     {
2349       MPLIST_DO (par_lang, variable_list)
2350         {
2351           MPLIST_DO (par_im, MPLIST_VAL (par_lang))
2352             {
2353               MPLIST_DO (p, MPLIST_VAL (par_im))
2354                 M17N_OBJECT_UNREF (MPLIST_VAL (p));
2355               M17N_OBJECT_UNREF (MPLIST_VAL (par_im));
2356             }
2357           M17N_OBJECT_UNREF (MPLIST_VAL (par_lang));
2358         }
2359       M17N_OBJECT_UNREF (variable_list);
2360       variable_list = NULL;
2361     }
2362
2363   if (minput_default_driver.callback_list)
2364     {
2365       M17N_OBJECT_UNREF (minput_default_driver.callback_list);
2366       minput_default_driver.callback_list = NULL;
2367     }
2368   if (minput_driver->callback_list)
2369     {
2370       M17N_OBJECT_UNREF (minput_driver->callback_list);
2371       minput_driver->callback_list = NULL;
2372     }
2373
2374   M17N_OBJECT_UNREF (load_im_info_keys);
2375 }
2376
2377 void
2378 minput__callback (MInputContext *ic, MSymbol command)
2379 {
2380   if (ic->im->driver.callback_list)
2381     {
2382       MInputCallbackFunc func
2383         = (MInputCallbackFunc) mplist_get (ic->im->driver.callback_list,
2384                                            command);
2385
2386       if (func)
2387         (func) (ic, command);
2388     }
2389 }
2390
2391 MSymbol
2392 minput__char_to_key (int c)
2393 {
2394   if (c < 0 || c >= 0x100)
2395     return Mnil;
2396
2397   return one_char_symbol[c];
2398 }
2399
2400 /*** @} */
2401 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
2402
2403 \f
2404 /* External API */
2405
2406 /*** @addtogroup m17nInputMethod */
2407 /*** @{ */
2408 /*=*/
2409
2410 /***en
2411     @name Variables: Predefined symbols for callback commands.
2412
2413     These are the predefined symbols that are used as the @c COMMAND
2414     argument of callback functions of an input method driver (see
2415     #MInputDriver::callback_list ).  */ 
2416 /***ja
2417     @name ÊÑ¿ô¡§ ¥³¡¼¥ë¥Ð¥Ã¥¯¥³¥Þ¥ó¥ÉÍÑÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë.
2418
2419     ÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Î¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Ë¤ª¤¤¤Æ @c COMMAND 
2420     °ú¿ô¤È¤·¤ÆÍѤ¤¤é¤ì¤ëÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë (#MInputDriver::callback_list »²¾È)¡£
2421       */ 
2422 /*** @{ */ 
2423 /*=*/
2424
2425 MSymbol Minput_preedit_start;
2426 MSymbol Minput_preedit_done;
2427 MSymbol Minput_preedit_draw;
2428 MSymbol Minput_status_start;
2429 MSymbol Minput_status_done;
2430 MSymbol Minput_status_draw;
2431 MSymbol Minput_candidates_start;
2432 MSymbol Minput_candidates_done;
2433 MSymbol Minput_candidates_draw;
2434 MSymbol Minput_set_spot;
2435 MSymbol Minput_focus_move;
2436 MSymbol Minput_focus_in;
2437 MSymbol Minput_focus_out;
2438 MSymbol Minput_toggle;
2439 MSymbol Minput_reset;
2440 /*** @} */
2441
2442 /*=*/
2443
2444 /***en
2445     @brief The default driver for internal input methods.
2446
2447     The variable #minput_default_driver is the default driver for
2448     internal input methods.
2449
2450     The member MInputDriver::open_im () searches the m17n database for
2451     an input method that matches the tag \< #Minput_method, $LANGUAGE,
2452     $NAME\> and loads it.
2453
2454     The member MInputDriver::callback_list () is @c NULL.  Thus, it is
2455     programmers responsibility to set it to a plist of proper callback
2456     functions.  Otherwise, no feedback information (e.g. preedit text)
2457     can be shown to users.
2458
2459     The macro M17N_INIT () sets the variable #minput_driver to the
2460     pointer to this driver so that all internal input methods use it.
2461
2462     Therefore, unless @c minput_driver is set differently, the driver
2463     dependent arguments $ARG of the functions whose name begin with
2464     "minput_" are all ignored.  */
2465
2466 /***ja
2467     @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥǥե©¥ë¥È¥É¥é¥¤¥Ð.
2468
2469     ÊÑ¿ô #minput_default_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѤΥǥե©¥ë¥È¤Î¥É¥é¥¤¥Ð¤òɽ¤¹¡£
2470
2471     ¥á¥ó¥Ð MInputDriver::open_im () ¤Ï m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹Ã椫¤é¥¿¥° 
2472     \< #Minput_method, $LANGUAGE, $NAME\> 
2473     ¤Ë¹çÃפ¹¤ëÆþÎϥ᥽¥Ã¥É¤òõ¤·¡¢¤½¤ì¤ò¥í¡¼¥É¤¹¤ë¡£
2474
2475     ¥á¥ó¥Ð MInputDriver::callback_list () ¤Ï @c NULL ¤Ç¤¢¤ê¡¢
2476     ¤·¤¿¤¬¤Ã¤Æ¡¢¥×¥í¥°¥é¥Þ¦¤ÇÀÕǤ¤ò»ý¤Ã¤Æ Å¬Àڤʥ³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Î plist
2477     ¤ËÀßÄꤷ¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¤µ¤â¤Ê¤¤¤È¡¢preedit 
2478     ¥Æ¥­¥¹¥È¤Ê¤É¤Î¥Õ¥£¡¼¥É¥Ð¥Ã¥¯¾ðÊ󤬥桼¥¶¤Ëɽ¼¨¤µ¤ì¤Ê¤¤¡£
2479
2480     ¥Þ¥¯¥í M17N_INIT () ¤ÏÊÑ¿ô #minput_driver 
2481     ¤ò¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤ËÀßÄꤷ¡¢Á´¤Æ¤ÎÆâÉôÆþÎϥ᥽¥Ã¥É¤¬¤³¤Î¥É¥é¥¤¥Ð¤ò»È¤¦¤è¤¦¤Ë¤¹¤ë¡£
2482
2483     ¤·¤¿¤¬¤Ã¤Æ¡¢@c minput_driver ¤¬¥Ç¥Õ¥©¥ë¥ÈÃͤΤޤޤǤ¢¤ì¤Ð¡¢minput_ 
2484     ¤Ç»Ï¤Þ¤ë´Ø¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô $ARG ¤Ï¤¹¤Ù¤Æ̵»ë¤µ¤ì¤ë¡£  */
2485
2486 MInputDriver minput_default_driver;
2487 /*=*/
2488
2489 /***en
2490     @brief The driver for internal input methods.
2491
2492     The variable #minput_driver is a pointer to the input method
2493     driver that is used by internal input methods.  The macro
2494     M17N_INIT () initializes it to a pointer to #minput_default_driver
2495     if <m17n<EM></EM>.h> is included.  */ 
2496 /***ja
2497     @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥɥ饤¥Ð.
2498
2499     ÊÑ¿ô #minput_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤Æ»ÈÍѤµ¤ì¤Æ¤¤¤ëÆþÎÏ¥á
2500     ¥½¥Ã¥É¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£¥Þ¥¯¥í M17N_INIT () ¤Ï¤³¤Î¥Ý¥¤¥ó
2501     ¥¿¤ò#minput_default_driver (<m17n<EM></EM>.h> ¤¬ include ¤µ¤ì¤Æ¤¤¤ë
2502     »þ) ¤Ë½é´ü²½¤¹¤ë¡£  */ 
2503
2504 MInputDriver *minput_driver;
2505
2506 MSymbol Minput_driver;
2507
2508 /*=*/
2509
2510 /***en
2511     @brief Open an input method.
2512
2513     The minput_open_im () function opens an input method that matches
2514     language $LANGUAGE and name $NAME, and returns a pointer to the
2515     input method object newly allocated.
2516
2517     This function at first decides an driver for the input method as
2518     below.
2519
2520     If $LANGUAGE is not #Mnil, the driver pointed by the variable
2521     #minput_driver is used.
2522
2523     If $LANGUAGE is #Mnil and $NAME has #Minput_driver property, the
2524     driver pointed to by the property value is used to open the input
2525     method.  If $NAME has no such property, @c NULL is returned.
2526
2527     Then, the member MInputDriver::open_im () of the driver is
2528     called.  
2529
2530     $ARG is set in the member @c arg of the structure MInputMethod so
2531     that the driver can refer to it.  */
2532
2533 /***ja
2534     @brief ÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë.
2535
2536     ´Ø¿ô minput_open_im () ¤Ï¸À¸ì $LANGUAGE ¤È̾Á° $NAME 
2537     ¤Ë¹çÃפ¹¤ëÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤·¡¢¿·¤¿¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿ÆþÎϥ᥽¥Ã¥É¥ª¥Ö¥¸¥§¥¯¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
2538     
2539     ¤³¤Î´Ø¿ô¤Ï¡¢¤Þ¤ºÆþÎϥ᥽¥Ã¥ÉÍѤΥɥ饤¥Ð¤ò°Ê²¼¤Î¤è¤¦¤Ë¤·¤Æ·èÄꤹ¤ë¡£
2540
2541     $LANGUAGE ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢ÊÑ¿ô #minput_driver 
2542     ¤Ç»Ø¤µ¤ì¤Æ¤¤¤ë¥É¥é¥¤¥Ð¤òÍѤ¤¤ë¡£
2543
2544     $LANGUAGE ¤¬ #Mnil ¤Ç¤¢¤ê¡¢$NAME ¤¬ #Minput_driver
2545     ¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä¾ì¹ç¤Ë¤Ï¡¢¤½¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤǻؤµ¤ì¤Æ¤¤¤ëÆþÎϥɥ饤¥Ð¤òÍѤ¤¤ÆÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë¡£
2546     $NAME ¤Ë¤½¤Î¤è¤¦¤Ê¥×¥í¥Ñ¥Æ¥£¤¬Ìµ¤«¤Ã¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
2547
2548     ¼¡¤¤¤Ç¡¢¥É¥é¥¤¥Ð¤Î¥á¥ó¥Ð MInputDriver::open_im () ¤¬¸Æ¤Ð¤ì¤ë¡£
2549
2550     $ARG ¤Ï¹½Â¤ÂΠMInputMethod ¤Î¥á¥ó¥Ð @c arg ¤ËÀßÄꤵ¤ì¡¢¥É¥é¥¤¥Ð¤«¤é»²¾È¤Ç¤­¤ë¡£
2551
2552     @latexonly \IPAlabel{minput_open} @endlatexonly
2553
2554 */
2555
2556 MInputMethod *
2557 minput_open_im (MSymbol language, MSymbol name, void *arg)
2558 {
2559   MInputMethod *im;
2560   MInputDriver *driver;
2561
2562   MDEBUG_PRINT2 ("  [IM] opening (%s %s) ... ",
2563          msymbol_name (language), msymbol_name (name));
2564   if (language)
2565     driver = minput_driver;
2566   else
2567     {
2568       driver = (MInputDriver *) msymbol_get (name, Minput_driver);
2569       if (! driver)
2570         MERROR (MERROR_IM, NULL);
2571     }
2572
2573   MSTRUCT_CALLOC (im, MERROR_IM);
2574   im->language = language;
2575   im->name = name;
2576   im->arg = arg;
2577   im->driver = *driver;
2578   if ((*im->driver.open_im) (im) < 0)
2579     {
2580       MDEBUG_PRINT (" failed\n");
2581       free (im);
2582       return NULL;
2583     }
2584   MDEBUG_PRINT (" ok\n");
2585   return im;
2586 }
2587
2588 /*=*/
2589
2590 /***en
2591     @brief Close an input method.
2592
2593     The minput_close_im () function closes the input method $IM, which
2594     must have been created by minput_open_im ().  */
2595
2596 /***ja
2597     @brief ÆþÎϥ᥽¥Ã¥É¤ò¥¯¥í¡¼¥º¤¹¤ë.
2598
2599     ´Ø¿ô minput_close_im () ¤Ï¡¢ÆþÎϥ᥽¥Ã¥É $IM ¤ò¥¯¥í¡¼¥º¤¹¤ë¡£
2600     ¤³¤ÎÆþÎϥ᥽¥Ã¥É $IM ¤Ï minput_open_im () ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£  */
2601
2602 void
2603 minput_close_im (MInputMethod *im)
2604 {
2605   MDEBUG_PRINT2 ("  [IM] closing (%s %s) ... ",
2606                  msymbol_name (im->name), msymbol_name (im->language));
2607   (*im->driver.close_im) (im);
2608   free (im);
2609   MDEBUG_PRINT (" done\n");
2610 }
2611
2612 /*=*/
2613
2614 /***en
2615     @brief Create an input context.
2616
2617     The minput_create_ic () function creates an input context object
2618     associated with input method $IM, and calls callback functions
2619     corresponding to #Minput_preedit_start, #Minput_status_start, and
2620     #Minput_status_draw in this order.
2621
2622     @return
2623
2624     If an input context is successfully created, minput_create_ic ()
2625     returns a pointer to it.  Otherwise it returns @c NULL.  */
2626
2627 /***ja
2628     @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÀ¸À®¤¹¤ë.
2629
2630     ´Ø¿ô minput_create_ic () ¤ÏÆþÎϥ᥽¥Ã¥É $IM
2631     ¤ËÂбþ¤¹¤ëÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤·¡¢
2632     #Minput_preedit_start, #Minput_status_start, #Minput_status_draw
2633     ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¤³¤Î½ç¤Ë¸Æ¤Ö¡£
2634
2635     @return
2636
2637     ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤¬À¸À®¤µ¤ì¤¿¾ì¹ç¡¢minput_create_ic () 
2638     ¤Ï¤½¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¼ºÇÔ¤·¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
2639       */
2640
2641 MInputContext *
2642 minput_create_ic (MInputMethod *im, void *arg)
2643 {
2644   MInputContext *ic;
2645
2646   MDEBUG_PRINT2 ("  [IM] creating context (%s %s) ... ",
2647                  msymbol_name (im->name), msymbol_name (im->language));
2648   MSTRUCT_CALLOC (ic, MERROR_IM);
2649   ic->im = im;
2650   ic->arg = arg;
2651   ic->preedit = mtext ();
2652   ic->candidate_list = NULL;
2653   ic->produced = mtext ();
2654   ic->spot.x = ic->spot.y = 0;
2655   ic->active = 1;
2656   ic->plist = mplist ();
2657   if ((*im->driver.create_ic) (ic) < 0)
2658     {
2659       MDEBUG_PRINT (" failed\n");
2660       M17N_OBJECT_UNREF (ic->preedit);
2661       M17N_OBJECT_UNREF (ic->produced);
2662       M17N_OBJECT_UNREF (ic->plist);
2663       free (ic);
2664       return NULL;
2665     };
2666
2667   if (im->driver.callback_list)
2668     {
2669       minput__callback (ic, Minput_preedit_start);
2670       minput__callback (ic, Minput_status_start);
2671       minput__callback (ic, Minput_status_draw);
2672     }
2673
2674   MDEBUG_PRINT (" ok\n");
2675   return ic;
2676 }
2677
2678 /*=*/
2679
2680 /***en
2681     @brief Destroy an input context.
2682
2683     The minput_destroy_ic () function destroys the input context $IC,
2684     which must have been created by minput_create_ic ().  It calls
2685     callback functions corresponding to #Minput_preedit_done,
2686     #Minput_status_done, and #Minput_candidates_done in this order.  */
2687
2688 /***ja
2689     @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÇ˲õ¤¹¤ë.
2690
2691     ´Ø¿ô minput_destroy_ic () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤òÇ˲õ¤¹¤ë¡£
2692     ¤³¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ï minput_create_ic () 
2693     ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£¤³¤Î´Ø¿ô¤Ï 
2694     #Minput_preedit_done, #Minput_status_done, #Minput_candidates_done 
2695     ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¤³¤Î½ç¤Ë¸Æ¤Ö¡£
2696   */
2697
2698 void
2699 minput_destroy_ic (MInputContext *ic)
2700 {
2701   MDEBUG_PRINT2 ("  [IM] destroying context (%s %s) ... ",
2702                  msymbol_name (ic->im->name), msymbol_name (ic->im->language));
2703   if (ic->im->driver.callback_list)
2704     {
2705       minput__callback (ic, Minput_preedit_done);
2706       minput__callback (ic, Minput_status_done);
2707       minput__callback (ic, Minput_candidates_done);
2708     }
2709   (*ic->im->driver.destroy_ic) (ic);
2710   M17N_OBJECT_UNREF (ic->preedit);
2711   M17N_OBJECT_UNREF (ic->produced);
2712   M17N_OBJECT_UNREF (ic->plist);
2713   MDEBUG_PRINT (" done\n");
2714   free (ic);
2715 }
2716
2717 /*=*/
2718
2719 /***en
2720     @brief Filter an input key.
2721
2722     The minput_filter () function filters input key $KEY according to
2723     input context $IC, and calls callback functions corresponding to
2724     #Minput_preedit_draw, #Minput_status_draw, and
2725     #Minput_candidates_draw if the preedit text, the status, and the
2726     current candidate are changed respectively.
2727
2728     @return
2729     If $KEY is filtered out, this function returns 1.  In that case,
2730     the caller should discard the key.  Otherwise, it returns 0, and
2731     the caller should handle the key, for instance, by calling the
2732     function minput_lookup () with the same key.  */
2733
2734 /***ja
2735     @brief ÆþÎÏ¥­¡¼¤ò¥Õ¥£¥ë¥¿¤¹¤ë.
2736
2737     ´Ø¿ô minput_filter () ¤ÏÆþÎÏ¥­¡¼ $KEY ¤òÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC 
2738     ¤Ë±þ¤¸¤Æ¥Õ¥£¥ë¥¿¤·¡¢preedit ¥Æ¥­¥¹¥È¡¢¥¹¥Æ¡¼¥¿¥¹¡¢¸½»þÅÀ¤Ç¤Î¸õÊ䤬ÊѲ½¤·¤¿»þÅÀ¤Ç¡¢¤½¤ì¤¾¤ì
2739     #Minput_preedit_draw, #Minput_status_draw,
2740     #Minput_candidates_draw ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¸Æ¤Ö¡£
2741
2742     @return 
2743     $KEY ¤¬¥Õ¥£¥ë¥¿¤µ¤ì¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 1 ¤òÊÖ¤¹¡£
2744     ¤³¤Î¾ì¹ç¸Æ¤Ó½Ð¤·Â¦¤Ï¤³¤Î¥­¡¼¤ò¼Î¤Æ¤ë¤Ù¤­¤Ç¤¢¤ë¡£
2745     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0 ¤òÊÖ¤·¡¢¸Æ¤Ó½Ð¤·Â¦¤Ï¡¢¤¿¤È¤¨¤ÐƱ¤¸¥­¡¼¤Ç´Ø¿ô minput_lookup ()
2746     ¤ò¸Æ¤Ö¤Ê¤É¤·¤Æ¡¢¤³¤Î¥­¡¼¤ò½èÍý¤¹¤ë¡£
2747
2748     @latexonly \IPAlabel{minput_filter} @endlatexonly
2749 */
2750
2751 int
2752 minput_filter (MInputContext *ic, MSymbol key, void *arg)
2753 {
2754   int ret;
2755
2756   if (! ic
2757       || ! ic->active)
2758     return 0;
2759   ret = (*ic->im->driver.filter) (ic, key, arg);
2760
2761   if (ic->im->driver.callback_list)
2762     {
2763       if (ic->preedit_changed)
2764         minput__callback (ic, Minput_preedit_draw);
2765       if (ic->status_changed)
2766         minput__callback (ic, Minput_status_draw);
2767       if (ic->candidates_changed)
2768         minput__callback (ic, Minput_candidates_draw);
2769     }
2770
2771   return ret;
2772 }
2773
2774 /*=*/
2775
2776 /***en
2777     @brief Look up a text produced in the input context.
2778
2779     The minput_lookup () function looks up a text in the input context
2780     $IC.  $KEY must be the same one provided to the previous call of
2781     minput_filter ().
2782
2783     If a text was produced by the input method, it is concatenated
2784     to M-text $MT.
2785
2786     This function calls #MInputDriver::lookup .
2787
2788     @return
2789     If $KEY was correctly handled by the input method, this function
2790     returns 0.  Otherwise, returns -1, even in that case, some text
2791     may be produced in $MT.  */
2792
2793 /***ja
2794     @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥ÈÃæ¤Î¥Æ¥­¥¹¥È¤òõ¤¹.
2795
2796     ´Ø¿ô minput_lookup () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC Ãæ¤Î¥Æ¥­¥¹¥È¤òõ¤¹¡£
2797     $KEY ¤Ï´Ø¿ô minput_filter () ¤Ø¤ÎľÁ°¤Î¸Æ¤Ó½Ð¤·¤ËÍѤ¤¤é¤ì¤¿¤â¤Î¤ÈƱ¤¸¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2798
2799     ¥Æ¥­¥¹¥È¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆÀ¸À®¤µ¤ì¤Æ¤¤¤ì¤Ð¡¢¥Æ¥­¥¹¥È¤Ï M-text
2800     $MT ¤ËÏ¢·ë¤µ¤ì¤ë¡£
2801
2802     ¤³¤Î´Ø¿ô¤Ï¡¢#MInputDriver::lookup ¤ò¸Æ¤Ö¡£
2803
2804     @return 
2805     $KEY ¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆŬÀڤ˽èÍý¤Ç¤­¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 0 ¤òÊÖ¤¹¡£
2806     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£
2807     ¤³¤Î¾ì¹ç¤Ç¤â $MT ¤Ë²¿¤é¤«¤Î¥Æ¥­¥¹¥È¤¬À¸À®¤µ¤ì¤Æ¤¤¤ë¤³¤È¤¬¤¢¤ë¡£
2808
2809     @latexonly \IPAlabel{minput_lookup} @endlatexonly  */
2810
2811 int
2812 minput_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2813 {
2814   return (ic ? (*ic->im->driver.lookup) (ic, key, arg, mt) : -1);
2815 }
2816 /*=*/
2817
2818 /***en
2819     @brief Set the spot of the input context.
2820
2821     The minput_set_spot () function set the spot of input context $IC
2822     to coordinate ($X, $Y ) with the height specified by $ASCENT and $DESCENT .
2823     The semantics of these values depend on the input method driver.
2824
2825     For instance, a driver designed to work in a CUI environment may
2826     use $X and $Y as column and row numbers, and ignore $ASCENT and
2827     $DESCENT .  A driver designed to work in a window system may
2828     interpret $X and $Y as pixel offsets relative to the origin of the
2829     client window, and may interpret $ASCENT and $DESCENT as the ascent- and
2830     descent pixels of the line at ($X . $Y ).
2831
2832     $FONTSIZE specifies the fontsize of preedit text in 1/10 point.
2833
2834     $MT and $POS is the M-text and the character position at the spot.
2835     $MT may be @c NULL, in which case, the input method cannot get
2836     information about the text around the spot.  */
2837
2838 /***ja
2839     @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Î¥¹¥Ý¥Ã¥È¤òÀßÄꤹ¤ë.
2840
2841     ´Ø¿ô minput_set_spot () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤Î¥¹¥Ý¥Ã¥È¤ò¡¢ºÂɸ ($X, $Y )
2842     ¤Î°ÌÃ֤ˠ¡¢¹â¤µ $ASCENT¡¢ $DESCENT 
2843     ¤ÇÀßÄꤹ¤ë¡£ ¤³¤ì¤é¤ÎÃͤΰÕÌ£¤ÏÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë¡£
2844
2845     ¤¿¤È¤¨¤Ð CUI ´Ä¶­¤ÇÆ°ºî¤¹¤ë¥É¥é¥¤¥Ð¤Ï $X ¤È $Y 
2846     ¤ò¤½¤ì¤¾¤ìÎó¤È¹Ô¤ÎÈÖ¹æ¤È¤·¤ÆÍѤ¤¡¢$ASCENT ¤È $DESCENT 
2847     ¤ò̵»ë¤¹¤ë¤«¤â¤·¤ì¤Ê¤¤¡£ ¤Þ¤¿¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥àÍѤΥɥ饤¥Ð¤Ï
2848     $X ¤È $Y ¤ò¥¯¥é¥¤¥¢¥ó¥È¥¦¥£¥ó¥É¥¦¤Î¸¶ÅÀ¤«¤é¤Î¥ª¥Õ¥»¥Ã¥È¤ò¥Ô¥¯¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¤¡¢
2849     $ASCENT ¤È $DESCENT ¤ò ($X . $Y )
2850     ¤ÎÎó¤Î¥¢¥»¥ó¥È¤È¥Ç¥£¥»¥ó¥È¤ò¥Ô¥¯¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¦¤«¤â¤·¤ì¤Ê¤¤¡£
2851
2852     $FONTSIZE ¤Ë¤Ï preedit ¥Æ¥­¥¹¥È¤Î¥Õ¥©¥ó¥È¥µ¥¤¥º¤ò 1/10 ¥Ý¥¤¥ó¥Èñ°Ì¤Ç»ØÄꤹ¤ë¡£
2853
2854     $MT ¤È $POS ¤Ï¤½¤Î¥¹¥Ý¥Ã¥È¤Î M-text ¤Èʸ»ú°ÌÃ֤Ǥ¢¤ë¡£$MT ¤Ï @c
2855     NULL ¤Ç¤â¤è¤¯¡¢¤½¤Î¾ì¹ç¤Ë¤ÏÆþÎϥ᥽¥Ã¥É¤Ï¥¹¥Ý¥Ã¥È¼þÊդΥƥ­¥¹¥È¤Ë´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë¤³¤È¤¬¤Ç¤­¤Ê¤¤¡£
2856     */
2857
2858 void
2859 minput_set_spot (MInputContext *ic, int x, int y,
2860                  int ascent, int descent, int fontsize,
2861                  MText *mt, int pos)
2862 {
2863   ic->spot.x = x;
2864   ic->spot.y = y;
2865   ic->spot.ascent = ascent;
2866   ic->spot.descent = descent;
2867   ic->spot.fontsize = fontsize;
2868   ic->spot.mt = mt;
2869   ic->spot.pos = pos;
2870   if (ic->im->driver.callback_list)
2871     minput__callback (ic, Minput_set_spot);
2872 }
2873 /*=*/
2874
2875 /***en
2876     @brief Toggle input method.
2877
2878     The minput_toggle () function toggles the input method associated
2879     with input context $IC.  */
2880 /***ja
2881     @brief ÆþÎϥ᥽¥Ã¥É¤òÀÚÂؤ¨¤ë.
2882
2883     ´Ø¿ô minput_toggle () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC 
2884     ¤ËÂбþÉÕ¤±¤é¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ò¥È¥°¥ë¤¹¤ë¡£
2885     */
2886
2887 void
2888 minput_toggle (MInputContext *ic)
2889 {
2890   if (ic->im->driver.callback_list)
2891     minput__callback (ic, Minput_toggle);
2892   ic->active = ! ic->active;
2893 }
2894
2895 /***en
2896     @brief Reset an input context.
2897
2898     The minput_reset_ic () function resets input context $IC by
2899     calling a callback function corresponding to #Minput_reset.  It
2900     actually shifts the state to the initial one, and thus the current
2901     preediting text (if any) is committed.  If necessary, a program
2902     can extract that committed text by calling minput_lookup () just
2903     after the call of minput_reset_ic ().  In that case, the arguments
2904     @c KEY and @c ARG of minput_lookup () are ignored.  */
2905 /***ja
2906     @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤ò¥ê¥»¥Ã¥È¤¹¤ë.
2907
2908     ´Ø¿ô minput_reset_ic () ¤Ï #Minput_reset 
2909     ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¸Æ¤Ö¤³¤È¤Ë¤è¤Ã¤ÆÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC 
2910     ¤ò¥ê¥»¥Ã¥È¤¹¤ë¡£¥ê¥»¥Ã¥È¤È¤Ï¡¢¼ÂºÝ¤Ë¤ÏÆþÎϥ᥽¥Ã¥É¤ò½é´ü¾õÂ֤˰ܤ¹¤³¤È¤Ç¤¢¤ê¡¢¤·¤¿¤¬¤Ã¤Æ¡¢¤â¤·¸½ºßÆþÎÏÃæ¤Î¥Æ¥­¥¹¥È¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤Ï¥³¥ß¥Ã¥È¤µ¤ì¤ë¡£
2911     É¬Íפʤé¤Ð¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ï minput_lookup () 
2912     ¤òÆɤó¤Ç¤½¤Î¥³¥ß¥Ã¥È¤µ¤ì¤¿¥Æ¥­¥¹¥È¤ò¼è¤ê½Ð¤¹¤³¤È¤¬¤Ç¤­¡¢¤½¤ÎºÝ¡¢
2913     minput_lookup () ¤Î°ú¿ô @c KEY ¤È @c ARG 
2914     ¤Ï̵»ë¤µ¤ì¤ë¡£ */
2915 void
2916 minput_reset_ic (MInputContext *ic)
2917 {
2918   if (ic->im->driver.callback_list)
2919     minput__callback (ic, Minput_reset);
2920 }
2921
2922 /*=*/
2923 /***en
2924     @brief Key of a text property for detailed description.
2925
2926     The symbol #Mdetail_text is a managing key usually used for a
2927     text property whose value is an M-text that contains detailed
2928     description.  */
2929 /***ja
2930     @brief ¾ÜºÙÀâÌÀÍѥƥ­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
2931
2932     ¥·¥ó¥Ü¥ë #Mdetail_text ¤Ï´ÉÍý¥­¡¼¤Ç¤¢¤ê¡¢Ä̾ï¾ÜºÙ¤ÊÀâÌÀ¤ò´Þ¤à 
2933     M-text ¤òÃͤȤ·¤Æ»ý¤Ä¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ËÍѤ¤¤é¤ì¤ë¡£
2934     */
2935 MSymbol Mdetail_text;
2936
2937 /***en
2938     @brief Get description text of an input method.
2939
2940     The minput_get_description () function returns an M-text that
2941     briefly describes the input method specified by $LANGUAGE and
2942     $NAME.  The returned M-text may have a text property, from its
2943     beginning to end, #Mdetail_text whose value is an M-text
2944     describing the input method in more detail.
2945
2946     @return
2947     If the specified input method has a description text, a pointer to
2948     #MText is returned.  A caller have to free it by m17n_object_unref ().
2949     If the input method does not have a description text, @c NULL is
2950     returned.  */
2951 /***ja
2952     @brief ÆþÎϥ᥽¥Ã¥É¤ÎÀâÌÀ¥Æ¥­¥¹¥È¤òÆÀ¤ë.
2953
2954     ´Ø¿ô minput_get_description () ¤Ï¡¢$LANGUAGE ¤È $NAME 
2955     ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ò´Êñ¤ËÀâÌÀ¤¹¤ë M-text ¤òÊÖ¤¹¡£ÊÖ¤µ¤ì¤ë M-text 
2956     ¤Ë¤Ï¡¢¤½¤ÎÁ´ÂΤËÂФ·¤Æ #Mdetail_text 
2957     ¤È¤¤¤¦¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬Éղ䵤ì¤Æ¤¤¤ë¾ì¹ç¤¬¤¢¤ê¡¢¤½¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤÏÆþÎϥ᥽¥Ã¥É¤ò¤µ¤é¤Ë¾ÜºÙ¤ËÀâÌÀ¤¹¤ë
2958     M-text ¤Ç¤¢¤ë¡£
2959
2960     @return 
2961     »ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤¬ÀâÌÀ¤¹¤ë¥Æ¥­¥¹¥È¤ò»ý¤Ã¤Æ¤¤¤ì¤Ð¡¢ 
2962     #MText ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¸Æ¤Ó½Ð¤·Â¦¤Ï¡¢¤½¤ì¤ò m17n_object_unref
2963     () ¤òÍѤ¤¤Æ²òÊü¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ÆþÎϥ᥽¥Ã¥É¤ËÀâÌÀ¥Æ¥­¥¹¥È¤¬Ìµ¤±¤ì¤Ð@c NULL ¤òÊÖ¤¹¡£ */
2964
2965 MText *
2966 minput_get_description (MSymbol language, MSymbol name)
2967 {
2968   MPlist *plist = load_im_info (language, name, M_description);
2969   MPlist *pl;
2970   MText *mt = NULL;
2971
2972   if (! plist)
2973     return NULL;
2974   if (! MPLIST_PLIST_P (plist))
2975     {
2976       M17N_OBJECT_UNREF (plist);      
2977       return NULL;
2978     }
2979   pl = MPLIST_PLIST (plist);
2980   while (! MPLIST_TAIL_P (pl) && ! MPLIST_MTEXT_P (pl))
2981     pl = MPLIST_NEXT (pl);
2982   if (MPLIST_MTEXT_P (pl))
2983     mt = get_description_advance (pl);
2984   M17N_OBJECT_UNREF (plist);
2985   return mt;
2986 }
2987
2988 /***en
2989     @brief Get information about input method commands.
2990
2991     The minput_get_commands () function returns information about
2992     input method commands of the input method specified by $LANGUAGE
2993     and $NAME.  An input method command is a pseudo key event to which
2994     one or more actual input key sequences are assigned.
2995
2996     There are two kinds of commands, global and local.  Global
2997     commands are used by multiple input methods for the same purpose,
2998     and have global key assignments.  Local commands are used only in
2999     a specific input method, and have only local key assignments.
3000
3001     Each input method may locally change key assignments for global
3002     commands.  A global key assignment for a global command are
3003     effective only when the current input method does not have local
3004     key assignments for that command.
3005
3006     If $NAME is #Mnil, information about global commands is returned.
3007     In this case $LANGUAGE is ignored.
3008
3009     If $NAME is not #Mnil, information about those commands that have
3010     local key assignments in the input method specified by $LANGUAGE
3011     and $NAME is returned.
3012
3013     @return
3014     If no input method commands are found, this function returns @c NULL.
3015
3016     Otherwise, a pointer to a plist is returned.  The key of each
3017     element in the plist is a symbol representing a command, and the
3018     value is a plist of the form COMMAND-INFO described below.
3019
3020     The first element of COMMAND-INFO has the key #Mtext, and the
3021     value is an M-text describing the command briefly.  This M-text
3022     may have a text property whose key is #Mdetail_text and whose
3023     value is an M-text describing the command in more detail.
3024
3025     If there are no more elements, that means no key sequences are
3026     assigned to the command.  Otherwise, each of the remaining
3027     elements has the key #Mplist, and the value is a plist whose keys are
3028     #Msymbol and values are symbols representing input keys, which are
3029     currently assigned to the command.
3030
3031     As the returned plist is kept in the library, the caller must not
3032     modify nor free it.  */
3033 /***ja
3034     @brief ÆþÎϥ᥽¥Ã¥É¤Î¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë.
3035
3036     ´Ø¿ô minput_get_commands () ¤Ï¡¢ $LANGUAGE ¤È $NAME 
3037     ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ÎÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£
3038     ÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤È¤Ï¡¢µ¿»÷¥­¡¼¥¤¥Ù¥ó¥È¤Ç¤¢¤ê¡¢¤½¤ì¤¾¤ì¤Ë£±¤Ä°Ê¾å¤Î¼ÂºÝ¤ÎÆþÎÏ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤¬³ä¤êÅö¤Æ¤é¤ì¤Æ¤¤¤ë¤â¤Î¤ò»Ø¤¹¡£
3039
3040     ¥³¥Þ¥ó¥É¤Ë¤Ï¥°¥í¡¼¥Ð¥ë¤È¥í¡¼¥«¥ë¤Î£²¼ïÎब¤¢¤ë¡£
3041     ¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É¤ÏÊ£¿ô¤ÎÆþÎϥ᥽¥Ã¥É¤Ë¤ª¤¤¤Æ¡¢Æ±¤¸ÌÜŪ¤Ç¡¢¥°¥í¡¼¥Ð¥ë¤Ê¥­¡¼³ä¤êÅö¤Æ¤ÇÍѤ¤¤é¤ì¤ë¡£
3042     ¥í¡¼¥«¥ë¥³¥Þ¥ó¥É¤ÏÆÃÄê¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Î¤ß¡¢¥í¡¼¥«¥ë¤Ê¥­¡¼³äÅö¤Ç»ÈÍѤµ¤ì¤ë¡£
3043
3044     ¸Ä¡¹¤ÎÆþÎϥ᥽¥Ã¥É¤Ï¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É¤Î¥­¡¼³äÅö¤òÊѹ¹¤¹¤ë¤³¤È¤â¤Ç¤­¤ë¡£
3045     ¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥ÉÍѤΥ°¥í¡¼¥Ð¥ë¥­¡¼³ä¤êÅö¤Æ¤Ï¡¢»ÈÍѤ¹¤ëÆþÎϥ᥽¥Ã¥É¤Ë¤ª¤¤¤Æ¤½¤Î¥³¥Þ¥ó¥ÉÍÑ¤Î¥í¡¼¥«¥ë¤Ê¥­¡¼³äÅö¤¬Â¸ºß¤·¤Ê¤¤¾ì¹ç¤Ë¤Î¤ßÍ­¸ú¤Ç¤¢¤ë¡£
3046
3047     $NAME ¤¬ #Mnil ¤Ç¤¢¤ì¤Ð¡¢¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£
3048     ¤³¤Î¾ì¹ç¡¢$LANGUAGE ¤Ï̵»ë¤µ¤ì¤ë¡£
3049
3050     $NAME ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢$LANGUAGE ¤È $NAME 
3051     ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤ëÆþÎϥ᥽¥Ã¥É¤ËÃÖ¤±¤ë¥í¡¼¥«¥ë¤Ê¥­¡¼³ä¤êÅö¤Æ¤ò»ý¤Ä¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£
3052
3053     @return
3054     ÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï @c NULL ¤òÊÖ¤¹¡£
3055
3056     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
3057     ¥ê¥¹¥È¤Î³ÆÍ×ÁǤΥ­¡¼¤Ï¸Ä¡¹¤Î¥³¥Þ¥ó¥É¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢Ãͤϲ¼µ­¤Î 
3058     COMMAND-INFO ¤Î·Á¼°¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ç¤¢¤ë¡£
3059
3060     COMMAND-INFO ¤ÎÂè°ìÍ×ÁǤϥ­¡¼¤È¤·¤Æ #Mtext 
3061     ¤ò¡¢ÃͤȤ·¤Æ¤½¤Î¥³¥Þ¥ó¥É¤ò´Êñ¤ËÀâÌÀ¤¹¤ë M-text ¤ò»ý¤Ä¡£¤³¤Î M-text 
3062     ¤Ï¡¢#Mdetail_text 
3063     ¤ò¥­¡¼¤È¤¹¤ë¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä¤³¤È¤¬¤Ç¤­¡¢¤½¤ÎÃͤϤ½¤Î¥³¥Þ¥ó¥É¤ò¤è¤ê¾ÜºÙ¤ËÀâÌÀ¤¹¤ë
3064     M-text ¤Ç¤¢¤ë¡£
3065
3066     ¤½¤ì°Ê³°¤ÎÍ×ÁǤ¬Ìµ¤±¤ì¤Ð¡¢¤³¤Î¥³¥Þ¥ó¥É¤ËÂФ·¤Æ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤¬³ä¤êÅö¤Æ¤é¤ì¤Æ¤¤¤Ê¤¤¤³¤È¤ò°ÕÌ£¤¹¤ë¡£
3067     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢»Ä¤ê¤Î³ÆÍ×ÁǤϥ­¡¼¤È¤·¤Æ#Mplist 
3068     ¤ò¡¢ÃͤȤ·¤Æ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ò»ý¤Ä¡£
3069     ¤³¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Î¥­¡¼¤Ï #Msymbol 
3070     ¤Ç¤¢¤ê¡¢Ãͤϸ½ºß¤½¤Î¥³¥Þ¥ó¥É¤Ë³ä¤êÅö¤Æ¤é¤ì¤Æ¤¤¤ëÆþÎÏ¥­¡¼¤òɽ¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
3071
3072     ÊÖ¤µ¤ì¤ë¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ï¥é¥¤¥Ö¥é¥ê¤Ë¤è¤Ã¤Æ´ÉÍý¤µ¤ì¤Æ¤ª¤ê¡¢¸Æ¤Ó½Ð¤·Â¦¤ÇÊѹ¹¤·¤¿¤ê²òÊü¤·¤¿¤ê¤·¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£*/
3073
3074 MPlist *
3075 minput_get_commands (MSymbol language, MSymbol name)
3076 {
3077   MPlist *plist = get_command_list (language, name);
3078
3079   return (! plist || MPLIST_TAIL_P (plist) ? NULL : plist);
3080 }
3081
3082 /***en
3083     @brief Assign a key sequence to an input method command.
3084
3085     The minput_assign_command_keys () function assigns input key
3086     sequence $KEYSEQ to input method command $COMMAND for the input
3087     method specified by $LANGUAGE and $NAME.  If $NAME is #Mnil, the
3088     key sequence is assigned globally no matter what $LANGUAGE is.
3089     Otherwise the key sequence is assigned locally.
3090
3091     Each element of $KEYSEQ must have the key $Msymbol and the value
3092     must be a symbol representing an input key.
3093
3094     $KEYSEQ may be @c NULL, in which case, all assignments are deleted
3095     globally or locally.
3096
3097     This assignment gets effective in a newly opened input method.
3098
3099     @return
3100     If the operation was successful, 0 is returned.  Otherwise -1 is
3101     returned, and #merror_code is set to #MERROR_IM.  */
3102 /***ja
3103     @brief ÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤Ë¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤ò³ä¤êÅö¤Æ¤ë.
3104
3105     ´Ø¿ô minput_assign_command_keys () ¤Ï¡¢ $LANGUAGE ¤È $NAME 
3106     ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥ÉÍѤÎÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É $COMMAND 
3107     ¤ËÂФ·¤Æ¡¢ÆþÎÏ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹ $KEYSEQ ¤ò³ä¤êÅö¤Æ¤ë¡£ $NAME ¤¬ #Mnil
3108     ¤Ê¤é¤Ð¡¢$LANGUAGE ¤Ë´Ø·¸¤Ê¤¯¡¢ÆþÎÏ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤Ï¥°¥í¡¼¥Ð¥ë¤Ë³ä¤êÅö¤Æ¤é¤ì¤ë¡£
3109     ¤½¤¦¤Ç¤Ê¤ì¤Ð¡¢³ä¤êÅö¤Æ¤Ï¥í¡¼¥«¥ë¤Ç¤¢¤ë¡£
3110
3111     $KEYSEQ ¤Î³ÆÍ×ÁǤϥ­¡¼¤È¤·¤Æ $Msymbol 
3112     ¤ò¡¢ÃͤȤ·¤ÆÆþÎÏ¥­¡¼¤òɽ¤¹¥·¥ó¥Ü¥ë¤ò»ý¤¿¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
3113
3114     $KEYSEQ ¤Ï @c NULL ¤Ç¤â¤è¤¤¡£
3115     ¤³¤Î¾ì¹ç¡¢¥°¥í¡¼¥Ð¥ë¤â¤·¤¯¤Ï¥í¡¼¥«¥ë¤Ê¤¹¤Ù¤Æ¤Î³ä¤êÅö¤Æ¤¬¾Ãµî¤µ¤ì¤ë¡£
3116
3117     ¤³¤Î³ä¤êÅö¤Æ¤Ï¡¢³ä¤êÅö¤Æ°Ê¹ß¿·¤·¤¯¥ª¡¼¥×¥ó¤µ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤«¤éÍ­¸ú¤Ë¤Ê¤ë¡£
3118
3119     @return 
3120     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤·¡¢
3121     #merror_code ¤ò #MERROR_IM ¤ËÀßÄꤹ¤ë¡£  */
3122
3123 int
3124 minput_assign_command_keys (MSymbol language, MSymbol name,
3125                             MSymbol command, MPlist *keyseq)
3126 {
3127   MPlist *plist, *pl, *p;
3128
3129   if (check_command_keyseq (keyseq) < 0
3130       || ! (plist = get_command_list (language, name)))
3131     MERROR (MERROR_IM, -1);
3132   pl = mplist_get (plist, command);
3133   if (pl)
3134     {
3135       pl = MPLIST_NEXT (pl);
3136       if (! keyseq)
3137         while ((p = mplist_pop (pl)))
3138           M17N_OBJECT_UNREF (p);
3139       else
3140         {
3141           keyseq = mplist_copy (keyseq);
3142           mplist_push (pl, Mplist, keyseq);
3143           M17N_OBJECT_UNREF (keyseq);
3144         }
3145     }
3146   else
3147     {
3148       if (name == Mnil)
3149         MERROR (MERROR_IM, -1);
3150       if (! keyseq)
3151         return 0;
3152       pl = get_command_list (Mnil, Mnil); /* Get global commands.  */
3153       pl = mplist_get (pl, command);
3154       if (! pl)
3155         MERROR (MERROR_IM, -1);
3156       p = mplist ();
3157       mplist_add (p, Mtext, mplist_value (pl));
3158       keyseq = mplist_copy (keyseq);
3159       mplist_add (p, Mplist, keyseq);
3160       M17N_OBJECT_UNREF (keyseq);
3161       mplist_push (plist, command, p);
3162     }
3163   return 0;
3164 }
3165
3166 /***en
3167     @brief Get a list of variables of an input method.
3168
3169     The minput_get_variables () function returns a plist (#MPlist) of
3170     variables used to control the behavior of the input method
3171     specified by $LANGUAGE and $NAME.  The key of an element of the
3172     plist is a symbol representing a variable, and the value is a
3173     plist of the form VAR-INFO (described below) that carries the
3174     information about the variable.
3175
3176     The first element of VAR-INFO has the key #Mtext, and the value is
3177     an M-text describing the variable briefly.  This M-text may have a
3178     text property #Mdetail_text whose value is an M-text describing
3179     the variable in more detail.
3180
3181     The second element of VAR-INFO is for the value of the variable.
3182     The key is #Minteger, #Msymbol, or #Mtext, and the value is an
3183     integer, a symbol, or an M-text, respectively.  The variable is
3184     set to this value when an input context is created for the input
3185     method.
3186
3187     If there are no more elements, the variable can take any value
3188     that matches with the above type.  Otherwise, the remaining
3189     elements of VAR-INFO are to specify valid values of the variable.
3190
3191     If the type of the variable is integer, the following elements
3192     have the key #Minteger or #Mplist.  If it is #Minteger, the value
3193     is a valid integer value.  If it is #Mplist, the value is a plist
3194     of two of elements.  Both of them have the key #Minteger, and
3195     values are the minimum and maximum bounds of the valid value
3196     range.
3197
3198     If the type of the variable is symbol or M-text, the following
3199     elements of the plist have the key #Msymbol or #Mtext,
3200     respectively, and the value must be a valid one.
3201
3202     For instance, suppose an input method has the variables:
3203
3204     @li name:intvar, description: "value is an integer",
3205          initial value:0, value-range:0..3,10,20
3206
3207     @li name:symvar, description: "value is a symbol",
3208          initial value:nil, value-range:a, b, c, nil
3209
3210     @li name:txtvar, description: "value is an M-text",
3211          initial value:empty text, no value-range (i.e. any text)
3212
3213     Then, the returned plist has this form ('X:Y' means X is a key and Y is
3214     a value, and '(...)' means a plist):
3215
3216 @verbatim
3217     plist:(intvar:(mtext:'value is an integer'
3218                    integer:0
3219                    plist:(integer:0 integer:3)
3220                    integer:10
3221                    integer:20))
3222            symvar:(mtext:"value is a symbol"
3223                    symbol:nil
3224                    symbol:a
3225                    symbol:b
3226                    symbol:c
3227                    symbol:nil))
3228            txtvar:(mtext:"value is an M-text"
3229                    mtext:""))
3230 @endverbatim
3231
3232     @return
3233     If the input method uses any variables, a pointer to #MPlist is
3234     returned.  As the plist is kept in the library, a caller must not
3235     modify nor free it.  If the input method does not use any
3236     variable, @c NULL is returned.  */
3237 /***ja
3238     @brief ÆþÎϥ᥽¥Ã¥É¤ÎÊÑ¿ô¥ê¥¹¥È¤òÆÀ¤ë.
3239
3240     ´Ø¿ô minput_get_variables () ¤Ï¡¢$LANGUAGE ¤È $NAME 
3241     ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤Î¿¶¤ëÉñ¤¤¤òÀ©¸æ¤¹¤ëÊÑ¿ô¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È 
3242     (#MPlist) ¤òÊÖ¤¹¡£¥ê¥¹¥È¤Î³ÆÍ×ÁǤΥ­¡¼¤ÏÊÑ¿ô¤òɽ¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
3243     ³ÆÍ×ÁǤÎÃͤϲ¼µ­¤Î VAR-INFO 
3244     ¤Î·Á¼°¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ç¤¢¤ê¡¢³ÆÊÑ¿ô¤Ë´Ø¤¹¤ë¾ðÊó¤ò¼¨¤·¤Æ¤¤¤ë¡£
3245
3246     VAR-INFO ¤ÎÂè°ìÍ×ÁǤϥ­¡¼¤È¤·¤Æ #Mtext ¤ò¡¢ÃͤȤ·¤Æ¤½¤ÎÊÑ¿ô¤ò´Êñ¤ËÀâÌÀ¤¹¤ë
3247     M-text ¤ò»ý¤Ä¡£¤³¤Î M-text ¤Ï¡¢#Mdetail_text 
3248     ¤ò¥­¡¼¤È¤¹¤ë¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä¤³¤È¤¬¤Ç¤­¡¢¤½¤ÎÃͤϤ½¤ÎÊÑ¿ô¤ò¤è¤ê¾ÜºÙ¤ËÀâÌÀ¤¹¤ë
3249     M-text ¤Ç¤¢¤ë¡£
3250
3251     VAR-INFO ¤ÎÂèÆóÍ×ÁǤÏÊÑ¿ô¤ÎÃͤò¼¨¤¹¡£¥­¡¼¤Ï #Minteger, #Msymbol,
3252     #Mtext ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ê¡¢ÃͤϤ½¤ì¤¾¤ìÀ°¿ôÃÍ¡¢¥·¥ó¥Ü¥ë¡¢M-text  ¤Ç¤¢¤ë¡£
3253     ¤³¤ÎÆþÎϥ᥽¥Ã¥ÉÍѤÎÆþÎÏ¥³¥ó¥Æ¥¹¥È¤¬ºî¤é¤ì¤ë»þÅÀ¤Ç¤Ï¡¢ÊÑ¿ô¤Ï¤³¤ÎÃͤËÀßÄꤵ¤ì¤Æ¤¤¤ë¡£
3254
3255     VAR-INFO ¤Ë¤½¤ì°Ê³°¤ÎÍ×ÁǤ¬Ìµ¤±¤ì¤Ð¡¢ÊÑ¿ô¤Ï¾åµ­¤Î·¿¤Ë¹çÃפ¹¤ë¸Â¤ê¤É¤Î¤è¤¦¤ÊÃͤò¤È¤ë¤³¤È¤â¤Ç¤­¤ë¡£
3256     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢VAR-INFO ¤Î»Ä¤ê¤ÎÍ×ÁǤˤè¤Ã¤ÆÊÑ¿ô¤ÎÍ­¸ú¤ÊÃͤ¬»ØÄꤵ¤ì¤ë¡£
3257
3258     ÊÑ¿ô¤Î·¿¤¬À°¿ô¤Ç¤¢¤ì¤Ð¡¢¤½¤ì°Ê¹ß¤ÎÍ×ÁǤϠ#Minteger ¤« #Mplist 
3259     ¤ò¥­¡¼¤È¤·¤Æ»ý¤Ä¡£ #Minteger ¤Ç¤¢¤ì¤Ð¡¢ÃͤÏÍ­¸ú¤ÊÃͤò¼¨¤¹À°¿ôÃͤǤ¢¤ë¡£
3260     #Mplist ¤Ç¤¢¤ì¤Ð¡¢ÃͤÏÆó¤Ä¤ÎÍ×ÁǤò»ý¤Ä¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ç¤¢¤ê¡¢³ÆÍ×ÁǤϥ­¡¼¤È¤·¤Æ
3261     #Minteger ¤ò¡¢ÃͤȤ·¤Æ¤½¤ì¤¾¤ìÍ­¸ú¤ÊÃͤξå¸ÂÃͤȲ¼¸ÂÃͤò¤È¤ë¡£
3262
3263     ÊÑ¿ô¤Î·¿¤¬¥·¥ó¥Ü¥ë¤« M-text ¤Ç¤¢¤ì¤Ð¡¢¤½¤ì°Ê¹ß¤ÎÍ×ÁǤϥ­¡¼¤È¤·¤Æ¤½¤ì¤¾¤ì
3264     #Msymbol ¤« #Mtext ¤ò»ý¤Á¡¢ÃͤϤ½¤Î·¿¤Ë¹çÃפ¹¤ë¤â¤Î¤Ç¤¢¤ë¡£
3265
3266     Îã¤È¤·¤Æ¡¢¤¢¤ëÆþÎϥ᥽¥Ã¥É¤¬¼¡¤Î¤è¤¦¤ÊÊÑ¿ô¤ò»ý¤Ä¾ì¹ç¤ò¹Í¤¨¤è¤¦¡£
3267
3268     @li name:intvar, ÀâÌÀ:"value is an integer",
3269         ½é´üÃÍ:0, ÃͤÎÈÏ°Ï:0..3,10,20
3270
3271     @li name:symvar, ÀâÌÀ:"value is a symbol",
3272          ½é´üÃÍ:nil, ÃͤÎÈÏ°Ï:a, b, c, nil
3273
3274     @li name:txtvar, ÀâÌÀ:"value is an M-text",
3275         ½é´üÃÍ:empty text, ÃͤÎÈϰϤʤ·(¤É¤ó¤Ê M-text ¤Ç¤â²Ä)
3276
3277     ¤³¤Î¾ì¹ç¡¢ÊÖ¤µ¤ì¤ë¥ê¥¹¥È¤Ï°Ê²¼¤Î¤è¤¦¤Ë¤Ê¤ë¡£¡Ê'X:Y' ¤È¤¤¤¦µ­Ë¡¤Ï X 
3278     ¤¬¥­¡¼¤Ç Y ¤¬ÃͤǤ¢¤ë¤³¤È¤ò¡¢¤Þ¤¿ '(...)' ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ò¼¨¤¹¡£¡Ë
3279
3280 @verbatim
3281     plist:(intvar:(mtext:"value is an integer"
3282                    integer:0
3283                    plist:(integer:0 integer:3)
3284                    integer:10
3285                    integer:20))
3286            symvar:(mtext:"value is a symbol"
3287                    symbol:nil
3288                    symbol:a
3289                    symbol:b
3290                    symbol:c
3291                    symbol:nil))
3292            txtvar:(mtext:"value is an M-text"
3293                    mtext:""))
3294 @endverbatim
3295
3296     @return 
3297     ÆþÎϥ᥽¥Ã¥É¤¬²¿¤é¤«¤ÎÊÑ¿ô¤ò»ÈÍѤ·¤Æ¤¤¤ì¤Ð #MPlist ¤Ø¤ÎÊÑ¿ô¤òÊÖ¤¹¡£
3298     ÊÖ¤µ¤ì¤ë¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ï¥é¥¤¥Ö¥é¥ê¤Ë¤è¤Ã¤Æ´ÉÍý¤µ¤ì¤Æ¤ª¤ê¡¢¸Æ¤Ó½Ð¤·Â¦¤ÇÊѹ¹¤·¤¿¤ê²òÊü¤·¤¿¤ê¤·¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
3299     ÆþÎϥ᥽¥Ã¥É¤¬ÊÑ¿ô¤ò°ìÀÚ»ÈÍѤ·¤Æ¤Ê¤±¤ì¤Ð¡¢@c NULL ¤òÊÖ¤¹¡£  */
3300
3301 MPlist *
3302 minput_get_variables (MSymbol language, MSymbol name)
3303 {
3304   MPlist *plist = get_variable_list (language, name);
3305
3306   return (! plist || MPLIST_TAIL_P (plist) ? NULL : plist);
3307 }
3308
3309 /***en
3310     @brief Set the initial value of an input method variable.
3311
3312     The minput_set_variable () function sets the initial value of
3313     input method variable $VARIABLE to $VALUE for the input method
3314     specified by $LANGUAGE and $NAME.
3315
3316     By default, the initial value is 0.
3317
3318     This setting gets effective in a newly opened input method.
3319
3320     @return
3321     If the operation was successful, 0 is returned.  Otherwise -1 is
3322     returned, and #merror_code is set to #MERROR_IM.  */
3323 /***ja
3324     @brief ÆþÎϥ᥽¥Ã¥ÉÊÑ¿ô¤Î½é´üÃͤòÀßÄꤹ¤ë.
3325
3326     ´Ø¿ô minput_set_variable () ¤Ï¡¢$LANGUAGE ¤È $NAME 
3327     ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ÎÆþÎϥ᥽¥Ã¥ÉÊÑ¿ô $VARIABLE
3328     ¤Î½é´üÃͤò¡¢ $VALUE ¤ËÀßÄꤹ¤ë¡£
3329
3330     ¥Ç¥Õ¥©¥ë¥È¤Î½é´üÃͤϠ0 ¤Ç¤¢¤ë¡£
3331
3332     ¤³¤ÎÀßÄê¤Ï¡¢¿·¤·¤¯¥ª¡¼¥×¥ó¤µ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤«¤éÍ­¸ú¤È¤Ê¤ë¡£
3333
3334     @return
3335     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤·¡¢
3336     #merror_code ¤ò #MERROR_IM ¤ËÀßÄꤹ¤ë¡£  */
3337
3338 int
3339 minput_set_variable (MSymbol language, MSymbol name,
3340                      MSymbol variable, void *value)
3341 {
3342   MPlist *plist, *val_element, *range_element;
3343   MSymbol type;
3344
3345   if (language == Mnil || name == Mnil)
3346     MERROR (MERROR_IM, -1);
3347   plist = get_variable_list (language, name);
3348   if (! plist)
3349     MERROR (MERROR_IM, -1);
3350   plist = (MPlist *) mplist_get (plist, variable);
3351   if (! plist)
3352     MERROR (MERROR_IM, -1);
3353   val_element = MPLIST_NEXT (plist);
3354   type = MPLIST_KEY (val_element);
3355   range_element = MPLIST_NEXT (val_element);
3356     
3357   if (! MPLIST_TAIL_P (range_element))
3358     {
3359       if (type == Minteger)
3360         {
3361           int val = (int) value, this_val;
3362       
3363           MPLIST_DO (plist, range_element)
3364             {
3365               this_val = (int) MPLIST_VAL (plist);
3366               if (MPLIST_PLIST_P (plist))
3367                 {
3368                   int min_bound, max_bound;
3369                   MPlist *pl = MPLIST_PLIST (plist);
3370
3371                   min_bound = (int) MPLIST_VAL (pl);
3372                   pl = MPLIST_NEXT (pl);
3373                   max_bound = (int) MPLIST_VAL (pl);
3374                   if (val >= min_bound && val <= max_bound)
3375                     break;
3376                 }
3377               else if (val == this_val)
3378                 break;
3379             }
3380           if (MPLIST_TAIL_P (plist))
3381             MERROR (MERROR_IM, -1);
3382         }
3383       else if (type == Msymbol)
3384         {
3385           MPLIST_DO (plist, range_element)
3386             if (MPLIST_SYMBOL (plist) == (MSymbol) value)
3387               break;
3388           if (MPLIST_TAIL_P (plist))
3389             MERROR (MERROR_IM, -1);
3390         }
3391       else                      /* type == Mtext */
3392         {
3393           MPLIST_DO (plist, range_element)
3394             if (mtext_cmp (MPLIST_MTEXT (plist), (MText *) value) == 0)
3395               break;
3396           if (MPLIST_TAIL_P (plist))
3397             MERROR (MERROR_IM, -1);
3398           M17N_OBJECT_REF (value);
3399         }
3400     }
3401
3402   mplist_set (val_element, type, value);
3403   return 0;
3404 }
3405
3406 /*** @} */
3407 /*=*/
3408 /*** @addtogroup m17nDebug */
3409 /*=*/
3410 /*** @{  */
3411 /*=*/
3412
3413 /***en
3414     @brief Dump an input method.
3415
3416     The mdebug_dump_im () function prints the input method $IM in a
3417     human readable way to the stderr.  $INDENT specifies how many
3418     columns to indent the lines but the first one.
3419
3420     @return
3421     This function returns $IM.  */
3422 /***ja
3423     @brief ÆþÎϥ᥽¥Ã¥É¤ò¥À¥ó¥×¤¹¤ë.
3424
3425     ´Ø¿ô mdebug_dump_im () ¤ÏÆþÎϥ᥽¥Ã¥É $IM ¤ò stderr 
3426     ¤Ë¿Í´Ö¤Ë²ÄÆɤʷÁ¤Ç°õºþ¤¹¤ë¡£$INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£
3427
3428     @return
3429     ¤³¤Î´Ø¿ô¤Ï $IM ¤òÊÖ¤¹¡£  */
3430
3431 MInputMethod *
3432 mdebug_dump_im (MInputMethod *im, int indent)
3433 {
3434   MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
3435   char *prefix;
3436
3437   prefix = (char *) alloca (indent + 1);
3438   memset (prefix, 32, indent);
3439   prefix[indent] = '\0';
3440
3441   fprintf (stderr, "(input-method %s %s ", msymbol_name (im->language),
3442            msymbol_name (im->name));
3443   mdebug_dump_mtext (im_info->title, 0, 0);
3444   if (im->name != Mnil)
3445     {
3446       MPlist *state;
3447
3448       MPLIST_DO (state, im_info->states)
3449         {
3450           fprintf (stderr, "\n%s  ", prefix);
3451           dump_im_state (MPLIST_VAL (state), indent + 2);
3452         }
3453     }
3454   fprintf (stderr, ")");
3455   return im;
3456 }
3457
3458 /*** @} */ 
3459
3460 /*
3461   Local Variables:
3462   coding: euc-japan
3463   End:
3464 */