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