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