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