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