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