1 /* input.c -- input method module.
2 Copyright (C) 2003, 2004, 2005, 2006
3 National Institute of Advanced Industrial Science and Technology (AIST)
4 Registration Number H15PRO112
6 This file is part of the m17n library.
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.
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.
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
24 @addtogroup m17nInputMethod
25 @brief API for Input method.
27 An input method is an object to enable inputting various
28 characters. An input method is identified by a pair of symbols,
29 LANGUAGE and NAME. This pair decides an input method driver of the
30 input method. An input method driver is a set of functions for
31 handling the input method. There are two kinds of input methods;
32 internal one and foreign one.
35 <li> Internal Input Method
37 An internal input method has non @c Mnil LANGUAGE, and its body is
38 defined in the m17n database by the tag <Minput_method, LANGUAGE,
39 NAME>. For this kind of input methods, the m17n library uses two
40 predefined input method drivers, one for CUI use and the other for
41 GUI use. Those drivers utilize the input processing engine
42 provided by the m17n library itself. The m17n database may
43 provide input methods that are not limited to a specific language.
44 The database uses @c Mt as LANGUAGE of those input methods.
46 An internal input method accepts an input key which is a symbol
47 associated with an input event. As there is no way for the @c
48 m17n @c library to know how input events are represented in an
49 application program, an application programmer has to convert an
50 input event to an input key by himself. See the documentation of
51 the function minput_event_to_key () for the detail.
53 <li> Foreign Input Method
55 A foreign input method has @c Mnil LANGUAGE, and its body is
56 defined in an external resource (e.g. XIM of X Window System).
57 For this kind of input methods, the symbol NAME must have a
58 property of key @c Minput_driver, and the value must be a pointer
59 to an input method driver. Therefore, by preparing a proper
60 driver, any kind of input method can be treated in the framework
61 of the @c m17n @c library.
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
73 The typical processing flow of handling an input method is:
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 */
82 @addtogroup m17nInputMethod
83 @brief ÆþÎϥ᥽¥Ã¥ÉÍÑAPI.
85 ÆþÎϥ᥽¥Ã¥É¤Ï¿ÍͤÊʸ»ú¤òÆþÎϤ¹¤ë¤¿¤á¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¢¤ë¡£
86 ÆþÎϥ᥽¥Ã¥É¤Ï¥·¥ó¥Ü¥ë LANGUAGE ¤È NAME ¤ÎÁȤˤè¤Ã¤Æ¼±Ê̤µ¤ì¡¢
87 ¤³¤ÎÁȹ礻¤Ë¤è¤Ã¤ÆÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤¬·èÄꤹ¤ë¡£
88 ÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤È¤Ï¡¢¤¢¤ëÆþÎϥ᥽¥Ã¥É¤ò°·¤¦¤¿¤á¤Î´Ø¿ô¤Î½¸¤Þ¤ê¤Ç¤¢¤ë¡£
89 ÆþÎϥ᥽¥Ã¥É¤Ë¤ÏÆâÉô¥á¥½¥Ã¥É¤È³°Éô¥á¥½¥Ã¥É¤ÎÆó¼ïÎब¤¢¤ë¡£
94 ÆâÉôÆþÎϥ᥽¥Ã¥É¤È¤Ï LANGUAGE ¤¬ @c Mnil °Ê³°¤Î¤â¤Î¤Ç¤¢¤ê¡¢¤½¤ÎËÜÂÎ
95 ¤Ïm17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë<Minput_method, LANGUAGE, NAME> ¤È¤¤¤¦¥¿¥°¤òÉÕ
96 ¤±¤ÆÄêµÁ¤µ¤ì¤Æ¤¤¤ë¡£¤³¤Î¼ï¤ÎÆþÎϥ᥽¥Ã¥É¤ËÂФ·¤Æ¡¢m17n ¥é¥¤¥Ö¥é¥ê¤Ç
97 ¤ÏCUI ÍÑ¤È GUI ÍѤ½¤ì¤¾¤ì¤ÎÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤ò¤¢¤é¤«¤¸¤áÄêµÁ¤·¤Æ
98 ¤¤¤ë¡£¤³¤ì¤é¤Î¥É¥é¥¤¥Ð¤Ï m17n ¥é¥¤¥Ö¥é¥ê¼«ÂΤÎÆþÎϽèÍý¥¨¥ó¥¸¥ó¤òÍø
99 ÍѤ¹¤ë¡£m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë¤Ï¡¢ÆÃÄê¤Î¸À¸ìÀìÍѤǤʤ¤ÆþÎϥ᥽¥Ã¥É¤òÄê
100 µÁ¤¹¤ë¤³¤È¤â¤Ç¤¡¢¤½¤Î¤è¤¦¤ÊÆþÎϥ᥽¥Ã¥É¤Î LANGUAGE ¤Ï @c Mt ¤Ç¤¢¤ë¡£
102 ÆâÉôÆþÎϥ᥽¥Ã¥É¤Ï¡¢¥æ¡¼¥¶¤ÎÆþÎÏ¥¤¥Ù¥ó¥È¤ËÂбþ¤·¤¿¥·¥ó¥Ü¥ë¤Ç¤¢¤ëÆþ
103 ÎÏ¥¡¼¤ò¼õ¤±¼è¤ë¡£@c m17n @c ¥é¥¤¥Ö¥é¥ê ¤ÏÆþÎÏ¥¤¥Ù¥ó¥È¤¬¥¢¥×¥ê¥±¡¼
104 ¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ç¤É¤¦É½¸½¤µ¤ì¤Æ¤¤¤ë¤«¤òÃΤ뤳¤È¤¬¤Ç¤¤Ê¤¤¤Î¤Ç¡¢Æþ
105 ÎÏ¥¤¥Ù¥ó¥È¤«¤éÆþÎÏ¥¡¼¤Ø¤ÎÊÑ´¹¤Ï¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥Þ¤ÎÀÕǤ¤Ç
106 ¹Ô¤ï¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï´Ø¿ô minput_event_to_key () ¤Î
109 <li> ³°ÉôÆþÎϥ᥽¥Ã¥É
111 ³°ÉôÆþÎϥ᥽¥Ã¥É¤È¤Ï LANGUAGE ¤¬ @c Mnil ¤Î¤â¤Î¤Ç¤¢¤ê¡¢¤½¤ÎËÜÂΤϳ°
112 Éô¤Î¥ê¥½¡¼¥¹¤È¤·¤ÆÄêµÁ¤µ¤ì¤ë¡£¡Ê¤¿¤È¤¨¤ÐX Window System ¤ÎXIM ¤Ê
113 ¤É¡£) ¤³¤Î¼ï¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢¥·¥ó¥Ü¥ë NAME ¤Ï@c Minput_driver ¤ò
114 ¥¡¼¤È¤¹¤ë¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Á¡¢¤½¤ÎÃͤÏÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó
115 ¥¿¤Ç¤¢¤ë¡£¤³¤Î¤³¤È¤Ë¤è¤ê¡¢Å¬Àڤʥɥ饤¥Ð¤ò½àÈ÷¤¹¤ë¤³¤È¤Ë¤è¤Ã¤Æ¡¢¤¤
116 ¤«¤Ê¤ë¼ïÎà¤ÎÆþÎϥ᥽¥Ã¥É¤â@c m17n @c ¥é¥¤¥Ö¥é¥ê ¤ÎÏÈÁȤÎÃæ¤Ç°·¤¦»ö
119 ÍøÊØÀ¤Î´ÑÅÀ¤«¤é¡¢m17n X ¥é¥¤¥Ö¥é¥ê¤Ï XIM ¤Î OverTheSpot ¤ÎÆþÎÏ¥¹¥¿
120 ¥¤¥ë¤ò¼Â¸½¤¹¤ëÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤òÄ󶡤·¡¢¤Þ¤¿¥·¥ó¥Ü¥ë @c Mxim ¤Î
121 @c Minput_driver ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤȤ·¤Æ¤½¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÝ»ý
122 ¤·¤Æ¤¤¤ë¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï m17n GUI API ¤Î¥É¥¥å¥á¥ó¥È¤ò»²¾È¤Î¤³¤È¡£
128 ÆþÎϥ᥽¥Ã¥É½èÍý¤Îŵ·¿Åª¤Ê½èÍý¤Ï°Ê²¼¤Î¤è¤¦¤Ë¤Ê¤ë¡£
130 @li ÆþÎϥ᥽¥Ã¥É¤Î¥ª¡¼¥×¥ó
131 @li ¤½¤ÎÆþÎϥ᥽¥Ã¥É¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤ÎÀ¸À®
132 @li ÆþÎÏ¥¤¥Ù¥ó¥È¤Î¥Õ¥£¥ë¥¿
133 @li ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ç¤ÎÀ¸À®¥Æ¥¥¹¥È¤Î¸¡º÷ */
137 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
138 /*** @addtogroup m17nInternal
144 #include <sys/types.h>
146 #include <sys/stat.h>
156 #include "m17n-gui.h"
157 #include "m17n-misc.h"
158 #include "internal.h"
163 #include "database.h"
166 static int mdebug_mask = MDEBUG_INPUT;
168 static int fully_initialized;
170 static MSymbol Minput_method;
172 /** Symbols to load an input method data. */
173 static MSymbol Mtitle, Mmacro, Mmodule, Mstate, Minclude;
175 /** Symbols for actions. */
176 static MSymbol Minsert, Mdelete, Mmark, Mmove, Mpushback, Mundo, Mcall, Mshift;
177 static MSymbol Mselect, Mshow, Mhide, Mcommit, Munhandle;
178 static MSymbol Mset, Madd, Msub, Mmul, Mdiv, Mequal, Mless, Mgreater;
179 static MSymbol Mless_equal, Mgreater_equal;
180 static MSymbol Mcond;
181 static MSymbol Mplus, Mminus, Mstar, Mslash, Mand, Mor, Mnot;
183 /** Special action symbol. */
184 static MSymbol Mat_reload;
186 static MSymbol M_candidates;
188 static MSymbol Mcandidate_list, Mcandidate_index;
190 static MSymbol Minit, Mfini;
192 /** Symbols for variables. */
193 static MSymbol Mcandidates_group_size, Mcandidates_charset;
195 /** Symbols for key events. */
196 static MSymbol one_char_symbol[256];
198 static MSymbol M_key_alias;
200 static MSymbol Mdescription, Mcommand, Mvariable, Mglobal, Mconfig;
202 /** Structure to hold a map. */
206 /** List of actions to take when we reach the map. In a root map,
207 the actions are executed only when there's no more key. */
210 /** List of deeper maps. If NULL, this is a terminal map. */
213 /** List of actions to take when we leave the map successfully. In
214 a root map, the actions are executed only when none of submaps
215 handle the current key. */
216 MPlist *branch_actions;
219 typedef MPlist *(*MIMExternalFunc) (MPlist *plist);
224 MPlist *func_list; /* function name vs (MIMExternalFunc *) */
231 /** Name of the state. */
234 /** Title of the state, or NULL. */
237 /** Key translation map of the state. Built by merging all maps of
242 #define CUSTOM_FILE "config.mic"
244 static MPlist *load_im_info_keys;
246 /* List of input method information. The format is:
247 (LANGUAGE NAME t:IM_INFO ... ... ...) */
248 static MPlist *im_info_list;
250 /* Database for user's customization file. */
251 static MDatabase *im_custom_mdb;
253 /* List of input method information loaded from im_custom_mdb. The
254 format is the same as im_info_list. */
255 static MPlist *im_custom_list;
257 /* List of input method information configured by
258 minput_config_command and minput_config_variable. The format is
259 the same as im_info_list. */
260 static MPlist *im_config_list;
262 /* Global input method information. It points into the element of
263 im_info_list corresponding to LANGUAGE == `nil' and NAME ==
265 static MInputMethodInfo *global_info;
267 static int update_global_info (void);
268 static int update_custom_info (void);
269 static MInputMethodInfo *get_im_info (MSymbol, MSymbol, MSymbol, MSymbol);
276 = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
277 "BackSpace", "Tab", "Linefeed", "Clear", NULL, "Return", NULL, NULL,
278 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
279 NULL, NULL, NULL, "Escape", NULL, NULL, NULL, NULL };
280 char buf[6], buf2[32];
282 /* Maximum case: C-M-a, C-M-A, M-Return, C-A-a, C-A-A, A-Return. */
285 M_key_alias = msymbol (" key-alias");
290 for (i = 0, buf[2] = '@'; i < ' '; i++, buf[2]++)
292 one_char_symbol[i] = msymbol (buf);
293 if (key_names[i] || (buf[2] >= 'A' && buf[2] <= 'Z'))
296 alias[j++] = one_char_symbol[i];
299 /* Ex: `Escape' == `C-[' */
300 alias[j++] = msymbol (key_names[i]);
302 if (buf[2] >= 'A' && buf[2] <= 'Z')
304 /* Ex: `C-a' == `C-A' */
306 alias[j++] = msymbol (buf);
309 /* Establish cyclic alias chain. */
312 msymbol_put (alias[j], M_key_alias, alias[j + 1]);
316 for (i = buf[2] = ' '; i < 127; i++, buf[2]++)
318 one_char_symbol[i] = msymbol (buf + 2);
319 if (i >= 'A' && i <= 'Z')
321 /* Ex: `A' == `S-A' == `S-a'. */
322 alias[0] = alias[3] = one_char_symbol[i];
323 alias[1] = msymbol (buf);
325 alias[2] = msymbol (buf);
327 for (j = 0; j < 3; j++)
328 msymbol_put (alias[j], M_key_alias, alias[j + 1]);
333 alias[0] = alias[2] = one_char_symbol[127] = msymbol ("Delete");
334 alias[1] = msymbol ("C-?");
335 for (j = 0; j < 2; j++)
336 msymbol_put (alias[j], M_key_alias, alias[j + 1]);
341 for (i = 128, buf[4] = '@'; i < 160; i++, buf[4]++)
344 /* `C-M-a' == `C-A-a' */
346 alias[j++] = one_char_symbol[i] = msymbol (buf);
348 alias[j++] = msymbol (buf);
349 if (key_names[i - 128])
351 /* Ex: `M-Escape' == `A-Escape' == `C-M-['. */
353 strcpy (buf2 + 2, key_names[i - 128]);
354 alias[j++] = msymbol (buf2);
356 alias[j++] = msymbol (buf2);
358 if (buf[4] >= 'A' && buf[4] <= 'Z')
360 /* Ex: `C-M-a' == `C-M-A'. */
363 alias[j++] = msymbol (buf);
365 alias[j++] = msymbol (buf);
368 /* Establish cyclic alias chain. */
371 msymbol_put (alias[j], M_key_alias, alias[j + 1]);
373 for (i = 160, buf[4] = ' '; i < 256; i++, buf[4]++)
376 alias[0] = alias[2] = one_char_symbol[i] = msymbol (buf + 2);
378 alias[1] = msymbol (buf + 2);
379 for (j = 0; j < 2; j++)
380 msymbol_put (alias[j], M_key_alias, alias[j + 1]);
383 alias[0] = alias[4] = one_char_symbol[255] = msymbol ("M-Delete");
384 alias[1] = msymbol ("A-Delete");
385 alias[2] = msymbol ("C-M-?");
386 alias[3] = msymbol ("C-A-?");
387 for (j = 0; j < 4; j++)
388 msymbol_put (alias[j], M_key_alias, alias[j + 1]);
390 Minput_method = msymbol ("input-method");
391 Mtitle = msymbol ("title");
392 Mmacro = msymbol ("macro");
393 Mmodule = msymbol ("module");
394 Mmap = msymbol ("map");
395 Mstate = msymbol ("state");
396 Minclude = msymbol ("include");
397 Minsert = msymbol ("insert");
398 M_candidates = msymbol (" candidates");
399 Mdelete = msymbol ("delete");
400 Mmove = msymbol ("move");
401 Mmark = msymbol ("mark");
402 Mpushback = msymbol ("pushback");
403 Mundo = msymbol ("undo");
404 Mcall = msymbol ("call");
405 Mshift = msymbol ("shift");
406 Mselect = msymbol ("select");
407 Mshow = msymbol ("show");
408 Mhide = msymbol ("hide");
409 Mcommit = msymbol ("commit");
410 Munhandle = msymbol ("unhandle");
411 Mset = msymbol ("set");
412 Madd = msymbol ("add");
413 Msub = msymbol ("sub");
414 Mmul = msymbol ("mul");
415 Mdiv = msymbol ("div");
416 Mequal = msymbol ("=");
417 Mless = msymbol ("<");
418 Mgreater = msymbol (">");
419 Mless_equal = msymbol ("<=");
420 Mgreater_equal = msymbol (">=");
421 Mcond = msymbol ("cond");
422 Mplus = msymbol ("+");
423 Mminus = msymbol ("-");
424 Mstar = msymbol ("*");
425 Mslash = msymbol ("/");
426 Mand = msymbol ("&");
428 Mnot = msymbol ("!");
430 Mat_reload = msymbol ("@reload");
432 Mcandidates_group_size = msymbol ("candidates-group-size");
433 Mcandidates_charset = msymbol ("candidates-charset");
435 Mcandidate_list = msymbol_as_managing_key (" candidate-list");
436 Mcandidate_index = msymbol (" candidate-index");
438 Minit = msymbol ("init");
439 Mfini = msymbol ("fini");
441 Mdescription = msymbol ("description");
442 Mcommand = msymbol ("command");
443 Mvariable = msymbol ("variable");
444 Mglobal = msymbol ("global");
445 Mconfig = msymbol ("config");
447 load_im_info_keys = mplist ();
448 mplist_add (load_im_info_keys, Mstate, Mnil);
449 mplist_push (load_im_info_keys, Mmap, Mnil);
451 im_info_list = mplist ();
452 im_config_list = im_custom_list = NULL;
453 im_custom_mdb = NULL;
454 update_custom_info ();
456 update_global_info ();
458 fully_initialized = 1;
461 #define MINPUT__INIT() \
463 if (! fully_initialized) \
464 fully_initialize (); \
469 marker_code (MSymbol sym)
475 name = MSYMBOL_NAME (sym);
476 return ((name[0] == '@'
477 && ((name[1] >= '0' && name[1] <= '9')
478 || name[1] == '<' || name[1] == '>'
479 || name[1] == '=' || name[1] == '+' || name[1] == '-'
480 || name[1] == '[' || name[1] == ']'
488 resolve_variable (MInputContextInfo *ic_info, MSymbol var)
490 MPlist *plist = mplist__assq (ic_info->vars, var);
494 plist = MPLIST_PLIST (plist);
495 return MPLIST_NEXT (plist);
499 mplist_push (ic_info->vars, Mplist, plist);
500 M17N_OBJECT_UNREF (plist);
501 plist = mplist_add (plist, Msymbol, var);
502 plist = mplist_add (plist, Minteger, (void *) 0);
507 get_surrounding_text (MInputContext *ic, int len)
511 mplist_push (ic->plist, Minteger, (void *) len);
512 if (minput__callback (ic, Minput_get_surrounding_text) >= 0
513 && MPLIST_MTEXT_P (ic->plist))
514 mt = MPLIST_MTEXT (ic->plist);
515 mplist_pop (ic->plist);
520 delete_surrounding_text (MInputContext *ic, int pos)
522 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
524 mplist_push (ic->plist, Minteger, (void *) pos);
525 minput__callback (ic, Minput_delete_surrounding_text);
526 mplist_pop (ic->plist);
528 M17N_OBJECT_UNREF (ic_info->preceding_text);
530 M17N_OBJECT_UNREF (ic_info->following_text);
534 get_preceding_char (MInputContext *ic, int pos)
536 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
540 if (ic_info->preceding_text)
542 len = mtext_nchars (ic_info->preceding_text);
544 return mtext_ref_char (ic_info->preceding_text, len - pos);
546 mt = get_surrounding_text (ic, - pos);
549 len = mtext_nchars (mt);
550 if (ic_info->preceding_text)
552 if (mtext_nchars (ic_info->preceding_text) < len)
554 M17N_OBJECT_UNREF (ic_info->preceding_text);
555 ic_info->preceding_text = mt;
559 ic_info->preceding_text = mt;
562 return mtext_ref_char (ic_info->preceding_text, len - pos);
566 get_following_char (MInputContext *ic, int pos)
568 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
572 if (ic_info->following_text)
574 len = mtext_nchars (ic_info->following_text);
576 return mtext_ref_char (ic_info->following_text, pos - 1);
578 mt = get_surrounding_text (ic, pos);
581 len = mtext_nchars (mt);
582 if (ic_info->following_text)
584 if (mtext_nchars (ic_info->following_text) < len)
586 M17N_OBJECT_UNREF (ic_info->following_text);
587 ic_info->following_text = mt;
591 ic_info->following_text = mt;
594 return mtext_ref_char (ic_info->following_text, pos - 1);
598 surrounding_pos (MSymbol sym)
604 name = MSYMBOL_NAME (sym);
605 if ((name[1] == '-' || name[1] == '+')
606 && name[2] >= '1' && name[2] <= '9')
607 return (name[1] == '-' ? - atoi (name + 2) : atoi (name + 2));
612 integer_value (MInputContext *ic, MPlist *arg, MPlist **value, int surrounding)
614 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
616 MText *preedit = ic->preedit;
617 int len = mtext_nchars (preedit);
621 if (MPLIST_INTEGER_P (arg))
622 return MPLIST_INTEGER (arg);
624 && (surrounding = surrounding_pos (MPLIST_SYMBOL (arg))) != 0)
625 return (surrounding < 0
626 ? get_preceding_char (ic, - surrounding)
627 : get_following_char (ic, surrounding));
628 code = marker_code (MPLIST_SYMBOL (arg));
631 MPlist *val = resolve_variable (ic_info, MPLIST_SYMBOL (arg));
635 return (MPLIST_INTEGER_P (val) ? MPLIST_INTEGER (val) : 0);
638 return ic_info->key_head;
639 if (code >= '0' && code <= '9')
641 else if (code == '=')
642 code = ic->cursor_pos;
643 else if (code == '-' || code == '[')
644 code = ic->cursor_pos - 1;
645 else if (code == '+' || code == ']')
646 code = ic->cursor_pos + 1;
647 else if (code == '<')
649 else if (code == '>')
651 return (code >= 0 && code < len ? mtext_ref_char (preedit, code) : -1);
655 parse_expression (MPlist *plist)
659 if (MPLIST_INTEGER_P (plist) || MPLIST_SYMBOL_P (plist))
661 if (! MPLIST_PLIST_P (plist))
663 plist = MPLIST_PLIST (plist);
664 op = MPLIST_SYMBOL (plist);
665 if (op != Mplus && op != Mminus && op != Mstar && op != Mslash
666 && op != Mand && op != Mor && op != Mnot
667 && op != Mless && op != Mgreater && op != Mequal
668 && op != Mless_equal && op != Mgreater_equal)
669 MERROR (MERROR_IM, -1);
670 MPLIST_DO (plist, MPLIST_NEXT (plist))
671 if (parse_expression (plist) < 0)
677 resolve_expression (MInputContext *ic, MPlist *plist)
682 if (MPLIST_INTEGER_P (plist))
683 return MPLIST_INTEGER (plist);
684 if (MPLIST_SYMBOL_P (plist))
685 return integer_value (ic, plist, NULL, 1);
686 if (! MPLIST_PLIST_P (plist))
688 plist = MPLIST_PLIST (plist);
689 if (! MPLIST_SYMBOL_P (plist))
691 op = MPLIST_SYMBOL (plist);
692 plist = MPLIST_NEXT (plist);
693 val = resolve_expression (ic, plist);
695 MPLIST_DO (plist, MPLIST_NEXT (plist))
696 val += resolve_expression (ic, plist);
697 else if (op == Mminus)
698 MPLIST_DO (plist, MPLIST_NEXT (plist))
699 val -= resolve_expression (ic, plist);
700 else if (op == Mstar)
701 MPLIST_DO (plist, MPLIST_NEXT (plist))
702 val *= resolve_expression (ic, plist);
703 else if (op == Mslash)
704 MPLIST_DO (plist, MPLIST_NEXT (plist))
705 val /= resolve_expression (ic, plist);
707 MPLIST_DO (plist, MPLIST_NEXT (plist))
708 val &= resolve_expression (ic, plist);
710 MPLIST_DO (plist, MPLIST_NEXT (plist))
711 val |= resolve_expression (ic, plist);
714 else if (op == Mless)
715 val = val < resolve_expression (ic, MPLIST_NEXT (plist));
716 else if (op == Mequal)
717 val = val == resolve_expression (ic, MPLIST_NEXT (plist));
718 else if (op == Mgreater)
719 val = val > resolve_expression (ic, MPLIST_NEXT (plist));
720 else if (op == Mless_equal)
721 val = val <= resolve_expression (ic, MPLIST_NEXT (plist));
722 else if (op == Mgreater_equal)
723 val = val >= resolve_expression (ic, MPLIST_NEXT (plist));
727 /* Parse PLIST as an action list. PLIST should have this form:
728 PLIST ::= ( (ACTION-NAME ACTION-ARG *) *).
729 Return 0 if successfully parsed, otherwise return -1. */
732 parse_action_list (MPlist *plist, MPlist *macros)
734 MPLIST_DO (plist, plist)
736 if (MPLIST_MTEXT_P (plist))
738 /* This is a short form of (insert MTEXT). */
739 /* if (mtext_nchars (MPLIST_MTEXT (plist)) == 0)
740 MERROR (MERROR_IM, -1); */
742 else if (MPLIST_PLIST_P (plist)
743 && (MPLIST_MTEXT_P (MPLIST_PLIST (plist))
744 || MPLIST_PLIST_P (MPLIST_PLIST (plist))))
748 /* This is a short form of (insert (GROUPS *)). */
749 MPLIST_DO (pl, MPLIST_PLIST (plist))
751 if (MPLIST_PLIST_P (pl))
755 MPLIST_DO (elt, MPLIST_PLIST (pl))
756 if (! MPLIST_MTEXT_P (elt)
757 || mtext_nchars (MPLIST_MTEXT (elt)) == 0)
758 MERROR (MERROR_IM, -1);
762 if (! MPLIST_MTEXT_P (pl)
763 || mtext_nchars (MPLIST_MTEXT (pl)) == 0)
764 MERROR (MERROR_IM, -1);
768 else if (MPLIST_INTEGER_P (plist))
770 int c = MPLIST_INTEGER (plist);
772 if (c < 0 || c > MCHAR_MAX)
773 MERROR (MERROR_IM, -1);
775 else if (MPLIST_PLIST_P (plist)
776 && MPLIST_SYMBOL_P (MPLIST_PLIST (plist)))
778 MPlist *pl = MPLIST_PLIST (plist);
779 MSymbol action_name = MPLIST_SYMBOL (pl);
781 pl = MPLIST_NEXT (pl);
783 if (action_name == Minsert)
785 if (MPLIST_MTEXT_P (pl))
787 if (mtext_nchars (MPLIST_MTEXT (pl)) == 0)
788 MERROR (MERROR_IM, -1);
790 else if (MPLIST_PLIST_P (pl))
794 if (MPLIST_PLIST_P (pl))
798 MPLIST_DO (elt, MPLIST_PLIST (pl))
799 if (! MPLIST_MTEXT_P (elt)
800 || mtext_nchars (MPLIST_MTEXT (elt)) == 0)
801 MERROR (MERROR_IM, -1);
805 if (! MPLIST_MTEXT_P (pl)
806 || mtext_nchars (MPLIST_MTEXT (pl)) == 0)
807 MERROR (MERROR_IM, -1);
811 else if (! MPLIST_SYMBOL_P (pl))
812 MERROR (MERROR_IM, -1);
814 else if (action_name == Mselect
815 || action_name == Mdelete
816 || action_name == Mmove)
818 if (parse_expression (pl) < 0)
821 else if (action_name == Mmark
822 || action_name == Mcall
823 || action_name == Mshift)
825 if (! MPLIST_SYMBOL_P (pl))
826 MERROR (MERROR_IM, -1);
828 else if (action_name == Mundo)
830 if (! MPLIST_TAIL_P (pl))
832 if (! MPLIST_SYMBOL_P (pl)
833 && (! MPLIST_INTEGER_P (pl)
834 || MPLIST_INTEGER (pl) == 0))
835 MERROR (MERROR_IM, -1);
838 else if (action_name == Mpushback)
840 if (MPLIST_MTEXT_P (pl))
842 MText *mt = MPLIST_MTEXT (pl);
844 if (mtext_nchars (mt) != mtext_nbytes (mt))
845 MERROR (MERROR_IM, -1);
847 else if (MPLIST_PLIST_P (pl))
851 MPLIST_DO (p, MPLIST_PLIST (pl))
852 if (! MPLIST_SYMBOL_P (p))
853 MERROR (MERROR_IM, -1);
855 else if (! MPLIST_INTEGER_P (pl))
856 MERROR (MERROR_IM, -1);
858 else if (action_name == Mset || action_name == Madd
859 || action_name == Msub || action_name == Mmul
860 || action_name == Mdiv)
862 if (! MPLIST_SYMBOL_P (pl))
863 MERROR (MERROR_IM, -1);
864 if (parse_expression (MPLIST_NEXT (pl)) < 0)
867 else if (action_name == Mequal || action_name == Mless
868 || action_name == Mgreater || action_name == Mless_equal
869 || action_name == Mgreater_equal)
871 if (parse_expression (pl) < 0
872 || parse_expression (MPLIST_NEXT (pl)) < 0)
874 pl = MPLIST_NEXT (MPLIST_NEXT (pl));
875 if (! MPLIST_PLIST_P (pl))
876 MERROR (MERROR_IM, -1);
877 if (parse_action_list (MPLIST_PLIST (pl), macros) < 0)
878 MERROR (MERROR_IM, -1);
879 pl = MPLIST_NEXT (pl);
880 if (MPLIST_PLIST_P (pl)
881 && parse_action_list (MPLIST_PLIST (pl), macros) < 0)
882 MERROR (MERROR_IM, -1);
884 else if (action_name == Mshow || action_name == Mhide
885 || action_name == Mcommit || action_name == Munhandle)
887 else if (action_name == Mcond)
890 if (! MPLIST_PLIST_P (pl))
891 MERROR (MERROR_IM, -1);
893 else if (! macros || ! mplist_get (macros, action_name))
894 MERROR (MERROR_IM, -1);
896 else if (! MPLIST_SYMBOL_P (plist))
897 MERROR (MERROR_IM, -1);
904 resolve_command (MPlist *cmds, MSymbol command)
908 if (! cmds || ! (plist = mplist__assq (cmds, command)))
910 plist = MPLIST_PLIST (plist);
911 plist = MPLIST_NEXT (plist);
912 plist = MPLIST_NEXT (plist);
916 /* Load a translation into MAP from PLIST.
918 PLIST ::= ( KEYSEQ MAP-ACTION * ) */
921 load_translation (MIMMap *map, MPlist *keylist, MPlist *map_actions,
922 MPlist *branch_actions, MPlist *macros)
927 if (MPLIST_MTEXT_P (keylist))
929 MText *mt = MPLIST_MTEXT (keylist);
931 len = mtext_nchars (mt);
932 if (MFAILP (len > 0 && len == mtext_nbytes (mt)))
934 keyseq = (MSymbol *) alloca (sizeof (MSymbol) * len);
935 for (i = 0; i < len; i++)
936 keyseq[i] = one_char_symbol[MTEXT_DATA (mt)[i]];
942 if (MFAILP (MPLIST_PLIST_P (keylist)))
944 elt = MPLIST_PLIST (keylist);
945 len = MPLIST_LENGTH (elt);
946 if (MFAILP (len > 0))
948 keyseq = (MSymbol *) alloca (sizeof (int) * len);
949 for (i = 0; i < len; i++, elt = MPLIST_NEXT (elt))
951 if (MPLIST_INTEGER_P (elt))
953 int c = MPLIST_INTEGER (elt);
955 if (MFAILP (c >= 0 && c < 0x100))
957 keyseq[i] = one_char_symbol[c];
961 if (MFAILP (MPLIST_SYMBOL_P (elt)))
963 keyseq[i] = MPLIST_SYMBOL (elt);
968 for (i = 0; i < len; i++)
970 MIMMap *deeper = NULL;
973 deeper = mplist_get (map->submaps, keyseq[i]);
975 map->submaps = mplist ();
978 /* Fixme: It is better to make all deeper maps at once. */
979 MSTRUCT_CALLOC (deeper, MERROR_IM);
980 mplist_put (map->submaps, keyseq[i], deeper);
985 /* We reach a terminal map. */
987 || map->branch_actions)
988 /* This map is already defined. We avoid overriding it. */
991 if (! MPLIST_TAIL_P (map_actions))
993 if (parse_action_list (map_actions, macros) < 0)
994 MERROR (MERROR_IM, -1);
995 map->map_actions = map_actions;
999 map->branch_actions = branch_actions;
1000 M17N_OBJECT_REF (branch_actions);
1006 /* Load a branch from PLIST into MAP. PLIST has this form:
1007 PLIST ::= ( MAP-NAME BRANCH-ACTION * ) */
1010 load_branch (MInputMethodInfo *im_info, MPlist *plist, MIMMap *map)
1013 MPlist *branch_actions;
1015 if (MFAILP (MPLIST_SYMBOL_P (plist)))
1017 map_name = MPLIST_SYMBOL (plist);
1018 plist = MPLIST_NEXT (plist);
1019 if (MPLIST_TAIL_P (plist))
1020 branch_actions = NULL;
1021 else if (MFAILP (parse_action_list (plist, im_info->macros) >= 0))
1024 branch_actions = plist;
1025 if (map_name == Mnil)
1027 map->branch_actions = branch_actions;
1029 M17N_OBJECT_REF (branch_actions);
1031 else if (map_name == Mt)
1033 map->map_actions = branch_actions;
1035 M17N_OBJECT_REF (branch_actions);
1037 else if (im_info->maps
1038 && (plist = (MPlist *) mplist_get (im_info->maps, map_name)))
1040 MPLIST_DO (plist, plist)
1042 MPlist *keylist, *map_actions;
1044 if (! MPLIST_PLIST_P (plist))
1045 MERROR (MERROR_IM, -1);
1046 keylist = MPLIST_PLIST (plist);
1047 map_actions = MPLIST_NEXT (keylist);
1048 if (MPLIST_SYMBOL_P (keylist))
1050 MSymbol command = MPLIST_SYMBOL (keylist);
1053 if (MFAILP (command != Mat_reload))
1055 pl = resolve_command (im_info->configured_cmds, command);
1059 load_translation (map, pl, map_actions, branch_actions,
1063 load_translation (map, keylist, map_actions, branch_actions,
1071 /* Load a macro from PLIST into IM_INFO->macros.
1072 PLIST has this from:
1073 PLIST ::= ( MACRO-NAME ACTION * )
1074 IM_INFO->macros is a plist of macro names vs action list. */
1077 load_macros (MInputMethodInfo *im_info, MPlist *plist)
1082 if (! MPLIST_SYMBOL_P (plist))
1083 MERROR (MERROR_IM, -1);
1084 name = MPLIST_SYMBOL (plist);
1085 plist = MPLIST_NEXT (plist);
1086 if (MPLIST_TAIL_P (plist)
1087 || parse_action_list (plist, im_info->macros) < 0)
1088 MERROR (MERROR_IM, -1);
1089 pl = mplist_get (im_info->macros, name);
1090 M17N_OBJECT_UNREF (pl);
1091 mplist_put (im_info->macros, name, plist);
1092 M17N_OBJECT_REF (plist);
1096 /* Load an external module from PLIST into IM_INFO->externals.
1097 PLIST has this form:
1098 PLIST ::= ( MODULE-NAME FUNCTION * )
1099 IM_INFO->externals is a plist of MODULE-NAME vs (MIMExternalModule *). */
1102 load_external_module (MInputMethodInfo *im_info, MPlist *plist)
1107 MIMExternalModule *external;
1111 if (MPLIST_MTEXT_P (plist))
1112 module = msymbol ((char *) MTEXT_DATA (MPLIST_MTEXT (plist)));
1113 else if (MPLIST_SYMBOL_P (plist))
1114 module = MPLIST_SYMBOL (plist);
1115 module_file = alloca (strlen (MSYMBOL_NAME (module))
1116 + strlen (DLOPEN_SHLIB_EXT) + 1);
1117 sprintf (module_file, "%s%s", MSYMBOL_NAME (module), DLOPEN_SHLIB_EXT);
1119 handle = dlopen (module_file, RTLD_NOW);
1120 if (MFAILP (handle))
1122 fprintf (stderr, "%s\n", dlerror ());
1125 func_list = mplist ();
1126 MPLIST_DO (plist, MPLIST_NEXT (plist))
1128 if (! MPLIST_SYMBOL_P (plist))
1129 MERROR_GOTO (MERROR_IM, err_label);
1130 func = dlsym (handle, MSYMBOL_NAME (MPLIST_SYMBOL (plist)));
1133 mplist_add (func_list, MPLIST_SYMBOL (plist), func);
1136 MSTRUCT_MALLOC (external, MERROR_IM);
1137 external->handle = handle;
1138 external->func_list = func_list;
1139 mplist_add (im_info->externals, module, external);
1144 M17N_OBJECT_UNREF (func_list);
1149 free_map (MIMMap *map, int top)
1154 M17N_OBJECT_UNREF (map->map_actions);
1157 MPLIST_DO (plist, map->submaps)
1158 free_map ((MIMMap *) MPLIST_VAL (plist), 0);
1159 M17N_OBJECT_UNREF (map->submaps);
1161 M17N_OBJECT_UNREF (map->branch_actions);
1166 free_state (void *object)
1168 MIMState *state = object;
1170 M17N_OBJECT_UNREF (state->title);
1172 free_map (state->map, 1);
1176 /** Load a state from PLIST into a newly allocated state object.
1177 PLIST has this form:
1178 PLIST ::= ( STATE-NAME STATE-TITLE ? BRANCH * )
1179 BRANCH ::= ( MAP-NAME BRANCH-ACTION * )
1180 Return the state object. */
1183 load_state (MInputMethodInfo *im_info, MPlist *plist)
1187 if (MFAILP (MPLIST_SYMBOL_P (plist)))
1189 M17N_OBJECT (state, free_state, MERROR_IM);
1190 state->name = MPLIST_SYMBOL (plist);
1191 plist = MPLIST_NEXT (plist);
1192 if (MPLIST_MTEXT_P (plist))
1194 state->title = MPLIST_MTEXT (plist);
1195 mtext_put_prop (state->title, 0, mtext_nchars (state->title),
1196 Mlanguage, im_info->language);
1197 M17N_OBJECT_REF (state->title);
1198 plist = MPLIST_NEXT (plist);
1200 MSTRUCT_CALLOC (state->map, MERROR_IM);
1201 MPLIST_DO (plist, plist)
1203 if (MFAILP (MPLIST_PLIST_P (plist)))
1205 load_branch (im_info, MPLIST_PLIST (plist), state->map);
1210 /* Return a newly created IM_INFO for an input method specified by
1211 LANUAGE, NAME, and EXTRA. IM_INFO is stored in PLIST. */
1213 static MInputMethodInfo *
1214 new_im_info (MDatabase *mdb, MSymbol language, MSymbol name, MSymbol extra,
1217 MInputMethodInfo *im_info;
1220 if (name == Mnil && extra == Mnil)
1221 language = Mt, extra = Mglobal;
1222 MSTRUCT_CALLOC (im_info, MERROR_IM);
1224 im_info->language = language;
1225 im_info->name = name;
1226 im_info->extra = extra;
1229 mplist_add (plist, Mplist, elt);
1230 M17N_OBJECT_UNREF (elt);
1231 elt = mplist_add (elt, Msymbol, language);
1232 elt = mplist_add (elt, Msymbol, name);
1233 elt = mplist_add (elt, Msymbol, extra);
1234 mplist_add (elt, Mt, im_info);
1240 fini_im_info (MInputMethodInfo *im_info)
1244 M17N_OBJECT_UNREF (im_info->cmds);
1245 M17N_OBJECT_UNREF (im_info->configured_cmds);
1246 M17N_OBJECT_UNREF (im_info->bc_cmds);
1247 M17N_OBJECT_UNREF (im_info->vars);
1248 M17N_OBJECT_UNREF (im_info->configured_vars);
1249 M17N_OBJECT_UNREF (im_info->bc_vars);
1250 M17N_OBJECT_UNREF (im_info->description);
1251 M17N_OBJECT_UNREF (im_info->title);
1252 if (im_info->states)
1254 MPLIST_DO (plist, im_info->states)
1256 MIMState *state = (MIMState *) MPLIST_VAL (plist);
1258 M17N_OBJECT_UNREF (state);
1260 M17N_OBJECT_UNREF (im_info->states);
1263 if (im_info->macros)
1265 MPLIST_DO (plist, im_info->macros)
1266 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
1267 M17N_OBJECT_UNREF (im_info->macros);
1270 if (im_info->externals)
1272 MPLIST_DO (plist, im_info->externals)
1274 MIMExternalModule *external = MPLIST_VAL (plist);
1276 dlclose (external->handle);
1277 M17N_OBJECT_UNREF (external->func_list);
1279 MPLIST_KEY (plist) = Mt;
1281 M17N_OBJECT_UNREF (im_info->externals);
1285 MPLIST_DO (plist, im_info->maps)
1287 MPlist *p = MPLIST_PLIST (plist);
1289 M17N_OBJECT_UNREF (p);
1291 M17N_OBJECT_UNREF (im_info->maps);
1298 free_im_info (MInputMethodInfo *im_info)
1300 fini_im_info (im_info);
1305 free_im_list (MPlist *plist)
1309 MPLIST_DO (pl, plist)
1311 MInputMethodInfo *im_info;
1313 elt = MPLIST_NEXT (MPLIST_NEXT (MPLIST_NEXT (MPLIST_PLIST (pl))));
1314 im_info = MPLIST_VAL (elt);
1315 free_im_info (im_info);
1317 M17N_OBJECT_UNREF (plist);
1320 static MInputMethodInfo *
1321 lookup_im_info (MPlist *plist, MSymbol language, MSymbol name, MSymbol extra)
1323 if (name == Mnil && extra == Mnil)
1324 language = Mt, extra = Mglobal;
1325 while ((plist = mplist__assq (plist, language)))
1327 MPlist *elt = MPLIST_PLIST (plist);
1329 plist = MPLIST_NEXT (plist);
1330 elt = MPLIST_NEXT (elt);
1331 if (MPLIST_SYMBOL (elt) != name)
1333 elt = MPLIST_NEXT (elt);
1334 if (MPLIST_SYMBOL (elt) != extra)
1336 elt = MPLIST_NEXT (elt);
1337 return MPLIST_VAL (elt);
1342 static void load_im_info (MPlist *, MInputMethodInfo *);
1344 #define get_custom_info(im_info) \
1346 ? lookup_im_info (im_custom_list, (im_info)->language, \
1347 (im_info)->name, (im_info)->extra) \
1350 #define get_config_info(im_info) \
1352 ? lookup_im_info (im_config_list, (im_info)->language, \
1353 (im_info)->name, (im_info)->extra) \
1357 update_custom_info (void)
1363 if (mdatabase__check (im_custom_mdb) > 0)
1368 MDatabaseInfo *custom_dir_info;
1369 char custom_path[PATH_MAX + 1];
1371 custom_dir_info = MPLIST_VAL (mdatabase__dir_list);
1372 if (! custom_dir_info->filename
1373 || custom_dir_info->len + strlen (CUSTOM_FILE) > PATH_MAX)
1375 strcpy (custom_path, custom_dir_info->filename);
1376 strcat (custom_path, CUSTOM_FILE);
1377 im_custom_mdb = mdatabase_define (Minput_method, Mt, Mnil, Mconfig,
1383 free_im_list (im_custom_list);
1384 im_custom_list = NULL;
1386 plist = mdatabase_load (im_custom_mdb);
1389 im_custom_list = mplist ();
1391 MPLIST_DO (pl, plist)
1393 MSymbol language, name, extra;
1394 MInputMethodInfo *im_info;
1395 MPlist *im_data, *p;
1397 if (! MPLIST_PLIST_P (pl))
1399 p = MPLIST_PLIST (pl);
1400 im_data = MPLIST_NEXT (p);
1401 if (! MPLIST_PLIST_P (p))
1403 p = MPLIST_PLIST (p);
1404 if (! MPLIST_SYMBOL_P (p)
1405 || MPLIST_SYMBOL (p) != Minput_method)
1407 p = MPLIST_NEXT (p);
1408 if (! MPLIST_SYMBOL_P (p))
1410 language = MPLIST_SYMBOL (p);
1411 p = MPLIST_NEXT (p);
1412 if (! MPLIST_SYMBOL_P (p))
1414 name = MPLIST_SYMBOL (p);
1415 if (language == Mnil || name == Mnil)
1417 p = MPLIST_NEXT (p);
1418 if (MPLIST_TAIL_P (p))
1420 else if (MPLIST_SYMBOL_P (p))
1421 extra = MPLIST_SYMBOL (p);
1424 im_info = new_im_info (NULL, language, name, extra, im_custom_list);
1425 load_im_info (im_data, im_info);
1427 M17N_OBJECT_UNREF (plist);
1432 update_global_info (void)
1438 int ret = mdatabase__check (global_info->mdb);
1442 fini_im_info (global_info);
1446 MDatabase *mdb = mdatabase_find (Minput_method, Mt, Mnil, Mglobal);
1448 global_info = new_im_info (mdb, Mt, Mnil, Mglobal, im_info_list);
1450 if (! global_info->mdb
1451 || ! (plist = mdatabase_load (global_info->mdb)))
1454 load_im_info (plist, global_info);
1455 M17N_OBJECT_UNREF (plist);
1460 /* Return an IM_INFO for the an method specified by LANGUAGE, NAME,
1461 and EXTRA. KEY, if not Mnil, tells which kind of information about
1462 the input method is necessary, and the returned IM_INFO may contain
1463 only that information. */
1465 static MInputMethodInfo *
1466 get_im_info (MSymbol language, MSymbol name, MSymbol extra, MSymbol key)
1469 MInputMethodInfo *im_info;
1472 if (name == Mnil && extra == Mnil)
1473 language = Mt, extra = Mglobal;
1474 im_info = lookup_im_info (im_info_list, language, name, extra);
1477 if (key == Mnil ? im_info->states != NULL
1478 : key == Mcommand ? im_info->cmds != NULL
1479 : key == Mvariable ? im_info->vars != NULL
1480 : key == Mtitle ? im_info->title != NULL
1481 : key == Mdescription ? im_info->description != NULL
1483 /* IM_INFO already contains required information. */
1485 /* We have not yet loaded required information. */
1489 mdb = mdatabase_find (Minput_method, language, name, extra);
1492 im_info = new_im_info (mdb, language, name, extra, im_info_list);
1497 plist = mdatabase_load (im_info->mdb);
1501 mplist_push (load_im_info_keys, key, Mt);
1502 plist = mdatabase__load_for_keys (im_info->mdb, load_im_info_keys);
1503 mplist_pop (load_im_info_keys);
1507 MERROR (MERROR_IM, im_info);
1508 update_global_info ();
1509 load_im_info (plist, im_info);
1510 M17N_OBJECT_UNREF (plist);
1513 if (! im_info->cmds)
1514 im_info->cmds = mplist ();
1515 if (! im_info->vars)
1516 im_info->vars = mplist ();
1518 if (! im_info->title
1519 && (key == Mnil || key == Mtitle))
1520 im_info->title = (name == Mnil ? mtext ()
1521 : mtext_from_data (MSYMBOL_NAME (name),
1522 MSYMBOL_NAMELEN (name),
1523 MTEXT_FORMAT_US_ASCII));
1527 /* Check if IM_INFO->mdb is updated or not. If not updated, return 0.
1528 If updated, but got unloadable, return -1. Otherwise, update
1529 contents of IM_INFO from the new database, and return 1. */
1532 reload_im_info (MInputMethodInfo *im_info)
1537 check = mdatabase__check (im_info->mdb);
1542 plist = mdatabase_load (im_info->mdb);
1545 fini_im_info (im_info);
1546 load_im_info (plist, im_info);
1547 M17N_OBJECT_UNREF (plist);
1551 static MInputMethodInfo *
1552 get_im_info_by_tags (MPlist *plist)
1557 for (i = 0; i < 3 && MPLIST_SYMBOL_P (plist);
1558 i++, plist = MPLIST_NEXT (plist))
1559 tag[i] = MPLIST_SYMBOL (plist);
1564 return get_im_info (tag[0], tag[1], tag[2], Mnil);
1567 /* Check KEYSEQ, and return 1 if it is valid as a key sequence, return
1571 check_command_keyseq (MPlist *keyseq)
1573 if (MPLIST_PLIST_P (keyseq))
1575 MPlist *p = MPLIST_PLIST (keyseq);
1578 if (! MPLIST_SYMBOL_P (p) && ! MPLIST_INTEGER_P (p))
1582 if (MPLIST_MTEXT_P (keyseq))
1584 MText *mt = MPLIST_MTEXT (keyseq);
1587 for (i = 0; i < mtext_nchars (mt); i++)
1588 if (mtext_ref_char (mt, i) >= 256)
1595 /* Load command defitions from PLIST into IM_INFO->cmds.
1597 PLIST is well-formed and has this form;
1598 (command (NAME [DESCRIPTION KEYSEQ ...]) ...)
1599 NAME is a symbol. DESCRIPTION is an M-text or `nil'. KEYSEQ is an
1600 M-text or a plist of symbols.
1602 The returned list has the same form, but for each element...
1604 (1) If DESCRIPTION and the rest are omitted, the element is not
1605 stored in the returned list.
1607 (2) If DESCRIPTION is nil, it is complemented by the corresponding
1608 description in global_info->cmds (if any). */
1611 load_commands (MInputMethodInfo *im_info, MPlist *plist)
1613 MPlist *global_cmds = ((im_info->mdb && im_info != global_info)
1614 ? global_info->cmds : NULL);
1617 im_info->cmds = tail = mplist ();
1619 MPLIST_DO (plist, MPLIST_NEXT (plist))
1621 /* PLIST ::= ((NAME DESC KEYSEQ ...) ...) */
1622 MPlist *pl, *p, *global = NULL;
1625 if (MFAILP (MPLIST_PLIST_P (plist)))
1627 pl = MPLIST_PLIST (plist); /* PL ::= (NAME DESC KEYSEQ ...) */
1628 if (MFAILP (MPLIST_SYMBOL_P (pl)))
1630 name = MPLIST_SYMBOL (pl);
1631 p = MPLIST_NEXT (pl); /* P ::= (DESC KEYSEQ ...) */
1633 && (global = mplist__assq (global_cmds, name)))
1635 /* GLOBAL ::= ((NAME DESC ...) ...) */
1636 global = MPLIST_PLIST (global); /* (NAME DESC ...) */
1637 global = MPLIST_NEXT (global); /* (DESC ...) */
1639 if (! MPLIST_MTEXT_P (p))
1641 if (global && MPLIST_MTEXT (global))
1642 mplist_set (p, Mtext, MPLIST_MTEXT (global));
1644 mplist_set (p, Msymbol, Mnil);
1646 p = MPLIST_NEXT (p);
1648 if (MFAILP (check_command_keyseq (p)))
1650 if (! MPLIST_TAIL_P (p))
1652 tail = mplist_add (tail, Mplist, pl);
1657 config_commands (MInputMethodInfo *im_info)
1659 MPlist *tail, *plist;
1660 MInputMethodInfo *custom = NULL, *config = NULL;
1662 M17N_OBJECT_UNREF (im_info->configured_cmds);
1664 if (MPLIST_TAIL_P (im_info->cmds)
1668 im_info->configured_cmds = tail = mplist ();
1669 if ((custom = get_custom_info (im_info)) && ! custom->cmds)
1671 if ((config = get_config_info (im_info)) && ! config->cmds)
1673 MPLIST_DO (plist, im_info->cmds)
1675 MPlist *pl = MPLIST_PLIST (plist), *p = NULL;
1676 MSymbol name = MPLIST_SYMBOL (pl);
1679 p = mplist__assq (config->cmds, name);
1681 p = mplist__assq (custom->cmds, name);
1684 p = MPLIST_PLIST (p);
1685 p = MPLIST_NEXT (p);
1686 if (MPLIST_TAIL_P (p))
1690 p = MPLIST_NEXT (p);
1691 pl = mplist_copy (pl);
1694 tail = mplist_add (tail, Mplist, pl);
1697 M17N_OBJECT_UNREF (pl);
1698 pl = MPLIST_NEXT (pl);
1699 pl = MPLIST_NEXT (pl);
1700 mplist_set (pl, Mnil, NULL);
1701 mplist__conc (pl, p);
1706 /* Check VAL's value against VALID_VALUES, and return 1 if it is
1707 valid, return 0 if not. */
1710 check_variable_value (MPlist *val, MPlist *valid_values)
1712 MSymbol type = MPLIST_KEY (val);
1714 if (type != Minteger && type != Mtext && type != Msymbol)
1716 if (MPLIST_TAIL_P (valid_values))
1717 /* No restriction. Any value is ok. */
1719 if (type == Minteger)
1721 int n = MPLIST_INTEGER (val);
1723 MPLIST_DO (valid_values, valid_values)
1725 if (MPLIST_INTEGER_P (valid_values))
1727 if (n == MPLIST_INTEGER (valid_values))
1730 else if (MPLIST_PLIST_P (valid_values))
1732 MPlist *p = MPLIST_PLIST (valid_values);
1733 int min_bound, max_bound;
1735 if (! MPLIST_INTEGER_P (p))
1736 MERROR (MERROR_IM, 0);
1737 min_bound = MPLIST_INTEGER (p);
1738 p = MPLIST_NEXT (p);
1739 if (! MPLIST_INTEGER_P (p))
1740 MERROR (MERROR_IM, 0);
1741 max_bound = MPLIST_INTEGER (p);
1742 if (n >= min_bound && n <= max_bound)
1747 else if (type == Msymbol)
1749 MSymbol sym = MPLIST_SYMBOL (val);
1751 MPLIST_DO (valid_values, valid_values)
1753 if (! MPLIST_SYMBOL_P (valid_values))
1754 MERROR (MERROR_IM, 0);
1755 if (sym == MPLIST_SYMBOL (valid_values))
1761 MText *mt = MPLIST_MTEXT (val);
1763 MPLIST_DO (valid_values, valid_values)
1765 if (! MPLIST_MTEXT_P (valid_values))
1766 MERROR (MERROR_IM, 0);
1767 if (mtext_cmp (mt, MPLIST_MTEXT (valid_values)) == 0)
1772 return (MPLIST_TAIL_P (valid_values));
1775 /* Load variable defitions from PLIST into IM_INFO->vars.
1777 PLIST is well-formed and has this form;
1778 ((NAME [DESCRIPTION DEFAULT-VALUE VALID-VALUE ...])
1780 NAME is a symbol. DESCRIPTION is an M-text or `nil'.
1782 The returned list has the same form, but for each element...
1784 (1) If DESCRIPTION and the rest are omitted, the element is not
1785 stored in the returned list.
1787 (2) If DESCRIPTION is nil, it is complemented by the corresponding
1788 description in global_info->vars (if any). */
1791 load_variables (MInputMethodInfo *im_info, MPlist *plist)
1793 MPlist *global_vars = ((im_info->mdb && im_info != global_info)
1794 ? global_info->vars : NULL);
1797 im_info->vars = tail = mplist ();
1799 MPLIST_DO (plist, MPLIST_NEXT (plist))
1801 MPlist *pl, *p, *global = NULL;
1803 MPlist *valid_values;
1805 if (MFAILP (MPLIST_PLIST_P (plist)))
1807 pl = MPLIST_PLIST (plist); /* PL ::= (NAME [DESC VALUE VALID ...]) */
1808 if (MFAILP (MPLIST_SYMBOL_P (pl)))
1810 name = MPLIST_SYMBOL (pl);
1811 p = MPLIST_NEXT (pl); /* P ::= ([DESC VALUE VALID ...]) */
1813 && (global = mplist__assq (global_vars, name)))
1815 /* GLOBAL ::= ((NAME DESC ...) ...) */
1816 global = MPLIST_PLIST (global); /* GLOBAL ::= (NAME DESC ...) */
1817 global = MPLIST_NEXT (global); /* GLOBAL ::= (DESC VALUE ...) */
1819 if (! MPLIST_MTEXT_P (p))
1821 if (global && MPLIST_MTEXT_P (global))
1822 mplist_set (p, Mtext, MPLIST_MTEXT (global));
1824 mplist_set (p, Msymbol, Mnil);
1826 p = MPLIST_NEXT (p); /* p ::= ([VALUE VALID ...]) */
1827 if (MPLIST_TAIL_P (p))
1829 if (MFAILP (global))
1831 global = MPLIST_NEXT (global);
1832 mplist__conc (p, global);
1836 if (MFAILP (MPLIST_INTEGER_P (p) || MPLIST_MTEXT_P (p)
1837 || MPLIST_SYMBOL_P (p)))
1839 valid_values = MPLIST_NEXT (p);
1840 if (MPLIST_TAIL_P (valid_values)
1843 global = MPLIST_NEXT (global); /* GLOBAL ::= (VALUE VALID ...) */
1844 if (MFAILP (MPLIST_KEY (p) == MPLIST_KEY (global)))
1846 valid_values = MPLIST_NEXT (global);
1847 if (! MPLIST_TAIL_P (valid_values))
1848 mplist__conc (p, valid_values);
1850 if (MFAILP (check_variable_value (p, valid_values)))
1853 tail = mplist_add (tail, Mplist, pl);
1857 /* Return a configured variable definition list based on
1858 IM_INFO->vars. If a variable in it doesn't contain a value, try to
1859 get it from global_info->vars. */
1862 config_variables (MInputMethodInfo *im_info)
1864 MPlist *tail, *plist;
1865 MInputMethodInfo *custom = NULL, *config = NULL;
1867 M17N_OBJECT_UNREF (im_info->configured_vars);
1869 if (MPLIST_TAIL_P (im_info->vars)
1873 im_info->configured_vars = tail = mplist ();
1874 if ((custom = get_custom_info (im_info)) && ! custom->vars)
1876 if ((config = get_config_info (im_info)) && ! config->vars)
1879 MPLIST_DO (plist, im_info->vars)
1881 MPlist *pl = MPLIST_PLIST (plist), *p = NULL;
1882 MSymbol name = MPLIST_SYMBOL (pl);
1885 p = mplist__assq (config->vars, name);
1887 p = mplist__assq (custom->vars, name);
1890 p = MPLIST_PLIST (p);
1891 p = MPLIST_NEXT (p);
1892 if (MPLIST_TAIL_P (p))
1896 p = MPLIST_NEXT (p);
1897 pl = mplist_copy (pl);
1900 tail = mplist_add (tail, Mplist, pl);
1903 M17N_OBJECT_UNREF (pl);
1904 pl = MPLIST_NEXT (pl);
1905 pl = MPLIST_NEXT (pl);
1906 mplist_set (pl, MPLIST_KEY (p), MPLIST_VAL (p));
1911 /* Load an input method (LANGUAGE NAME) from PLIST into IM_INFO.
1912 CONFIG contains configulation information of the input method. */
1915 load_im_info (MPlist *plist, MInputMethodInfo *im_info)
1919 if (! im_info->cmds && (pl = mplist__assq (plist, Mcommand)))
1921 load_commands (im_info, MPLIST_PLIST (pl));
1922 config_commands (im_info);
1923 pl = mplist_pop (pl);
1924 M17N_OBJECT_UNREF (pl);
1927 if (! im_info->vars && (pl = mplist__assq (plist, Mvariable)))
1929 load_variables (im_info, MPLIST_PLIST (pl));
1930 config_variables (im_info);
1931 pl = mplist_pop (pl);
1932 M17N_OBJECT_UNREF (pl);
1935 MPLIST_DO (plist, plist)
1936 if (MPLIST_PLIST_P (plist))
1938 MPlist *elt = MPLIST_PLIST (plist);
1941 if (MFAILP (MPLIST_SYMBOL_P (elt)))
1943 key = MPLIST_SYMBOL (elt);
1948 elt = MPLIST_NEXT (elt);
1949 if (MFAILP (MPLIST_MTEXT_P (elt)))
1951 im_info->title = MPLIST_MTEXT (elt);
1952 M17N_OBJECT_REF (im_info->title);
1954 else if (key == Mmap)
1956 pl = mplist__from_alist (MPLIST_NEXT (elt));
1959 if (! im_info->maps)
1963 mplist__conc (im_info->maps, pl);
1964 M17N_OBJECT_UNREF (pl);
1967 else if (key == Mmacro)
1969 if (! im_info->macros)
1970 im_info->macros = mplist ();
1971 MPLIST_DO (elt, MPLIST_NEXT (elt))
1973 if (MFAILP (MPLIST_PLIST_P (elt)))
1975 load_macros (im_info, MPLIST_PLIST (elt));
1978 else if (key == Mmodule)
1980 if (! im_info->externals)
1981 im_info->externals = mplist ();
1982 MPLIST_DO (elt, MPLIST_NEXT (elt))
1984 if (MFAILP (MPLIST_PLIST_P (elt)))
1986 load_external_module (im_info, MPLIST_PLIST (elt));
1989 else if (key == Mstate)
1991 MPLIST_DO (elt, MPLIST_NEXT (elt))
1995 if (MFAILP (MPLIST_PLIST_P (elt)))
1997 pl = MPLIST_PLIST (elt);
1998 if (! im_info->states)
1999 im_info->states = mplist ();
2000 state = load_state (im_info, MPLIST_PLIST (elt));
2003 mplist_put (im_info->states, state->name, state);
2006 else if (key == Minclude)
2008 /* elt ::= include (tag1 tag2 ...) key item ... */
2010 MInputMethodInfo *temp;
2012 elt = MPLIST_NEXT (elt);
2013 if (MFAILP (MPLIST_PLIST_P (elt)))
2015 temp = get_im_info_by_tags (MPLIST_PLIST (elt));
2018 elt = MPLIST_NEXT (elt);
2019 if (MFAILP (MPLIST_SYMBOL_P (elt)))
2021 key = MPLIST_SYMBOL (elt);
2022 elt = MPLIST_NEXT (elt);
2025 if (! temp->maps || MPLIST_TAIL_P (temp->maps))
2027 if (! im_info->maps)
2028 im_info->maps = mplist ();
2029 MPLIST_DO (pl, temp->maps)
2031 p = MPLIST_VAL (pl);
2032 MPLIST_ADD_PLIST (im_info->maps, MPLIST_KEY (pl), p);
2033 M17N_OBJECT_REF (p);
2036 else if (key == Mmacro)
2038 if (! temp->macros || MPLIST_TAIL_P (temp->macros))
2040 if (! im_info->macros)
2041 im_info->macros = mplist ();
2042 MPLIST_DO (pl, temp->macros)
2044 p = MPLIST_VAL (pl);
2045 MPLIST_ADD_PLIST (im_info->macros, MPLIST_KEY (pl), p);
2046 M17N_OBJECT_REF (p);
2049 else if (key == Mstate)
2051 if (! temp->states || MPLIST_TAIL_P (temp->states))
2053 if (! im_info->states)
2054 im_info->states = mplist ();
2055 MPLIST_DO (pl, temp->states)
2057 MIMState *state = MPLIST_VAL (pl);
2059 mplist_add (im_info->states, MPLIST_KEY (pl), state);
2060 M17N_OBJECT_REF (state);
2064 else if (key == Mdescription)
2066 if (im_info->description)
2068 elt = MPLIST_NEXT (elt);
2069 if (MFAILP (MPLIST_MTEXT_P (elt)))
2071 im_info->description = MPLIST_MTEXT (elt);
2072 M17N_OBJECT_REF (im_info->description);
2076 im_info->tick = time (NULL);
2081 static int take_action_list (MInputContext *ic, MPlist *action_list);
2082 static void preedit_commit (MInputContext *ic);
2085 shift_state (MInputContext *ic, MSymbol state_name)
2087 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
2088 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
2089 MIMState *orig_state = ic_info->state, *state;
2091 /* Find a state to shift to. If not found, shift to the initial
2093 if (state_name == Mt)
2095 if (! ic_info->prev_state)
2097 state = ic_info->prev_state;
2099 else if (state_name == Mnil)
2101 state = (MIMState *) MPLIST_VAL (im_info->states);
2105 state = (MIMState *) mplist_get (im_info->states, state_name);
2107 state = (MIMState *) MPLIST_VAL (im_info->states);
2110 MDEBUG_PRINT1 ("\n [IM] (shift %s)", MSYMBOL_NAME (state->name));
2112 /* Enter the new state. */
2113 ic_info->state = state;
2114 ic_info->map = state->map;
2115 ic_info->state_key_head = ic_info->key_head;
2116 if (state == (MIMState *) MPLIST_VAL (im_info->states)
2118 /* We have shifted to the initial state. */
2119 preedit_commit (ic);
2120 mtext_cpy (ic_info->preedit_saved, ic->preedit);
2121 ic_info->state_pos = ic->cursor_pos;
2122 if (state != orig_state)
2124 if (state == (MIMState *) MPLIST_VAL (im_info->states))
2125 ic_info->prev_state = NULL;
2127 ic_info->prev_state = orig_state;
2130 ic->status = state->title;
2132 ic->status = im_info->title;
2133 ic->status_changed = 1;
2134 if (ic_info->map == ic_info->state->map
2135 && ic_info->map->map_actions)
2137 MDEBUG_PRINT (" init-actions:");
2138 take_action_list (ic, ic_info->map->map_actions);
2143 /* Find a candidate group that contains a candidate number INDEX from
2144 PLIST. Set START_INDEX to the first candidate number of the group,
2145 END_INDEX to the last candidate number plus 1, GROUP_INDEX to the
2146 candidate group number if they are non-NULL. If INDEX is -1, find
2147 the last candidate group. */
2150 find_candidates_group (MPlist *plist, int index,
2151 int *start_index, int *end_index, int *group_index)
2153 int i = 0, gidx = 0, len;
2155 MPLIST_DO (plist, plist)
2157 if (MPLIST_MTEXT_P (plist))
2158 len = mtext_nchars (MPLIST_MTEXT (plist));
2160 len = mplist_length (MPLIST_PLIST (plist));
2161 if (index < 0 ? MPLIST_TAIL_P (MPLIST_NEXT (plist))
2167 *end_index = i + len;
2169 *group_index = gidx;
2179 preedit_insert (MInputContext *ic, int pos, MText *mt, int c)
2181 MInputContextInfo *ic_info = ((MInputContext *) ic)->info;
2183 int nchars = mt ? mtext_nchars (mt) : 1;
2186 mtext_ins (ic->preedit, pos, mt);
2188 mtext_ins_char (ic->preedit, pos, c, 1);
2189 MPLIST_DO (markers, ic_info->markers)
2190 if (MPLIST_INTEGER (markers) > pos)
2191 MPLIST_VAL (markers) = (void *) (MPLIST_INTEGER (markers) + nchars);
2192 if (ic->cursor_pos >= pos)
2193 ic->cursor_pos += nchars;
2194 ic->preedit_changed = 1;
2199 preedit_delete (MInputContext *ic, int from, int to)
2201 MInputContextInfo *ic_info = ((MInputContext *) ic)->info;
2204 mtext_del (ic->preedit, from, to);
2205 MPLIST_DO (markers, ic_info->markers)
2207 if (MPLIST_INTEGER (markers) > to)
2208 MPLIST_VAL (markers)
2209 = (void *) (MPLIST_INTEGER (markers) - (to - from));
2210 else if (MPLIST_INTEGER (markers) > from);
2211 MPLIST_VAL (markers) = (void *) from;
2213 if (ic->cursor_pos >= to)
2214 ic->cursor_pos -= to - from;
2215 else if (ic->cursor_pos > from)
2216 ic->cursor_pos = from;
2217 ic->preedit_changed = 1;
2221 preedit_commit (MInputContext *ic)
2223 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
2224 int preedit_len = mtext_nchars (ic->preedit);
2226 if (preedit_len > 0)
2230 mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit),
2231 Mcandidate_list, NULL, 0);
2232 mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit),
2233 Mcandidate_index, NULL, 0);
2234 mtext_cat (ic->produced, ic->preedit);
2235 if ((mdebug__flag & mdebug_mask)
2236 && mtext_nchars (ic->preedit) > 0)
2240 MDEBUG_PRINT (" (produced");
2241 for (i = 0; i < mtext_nchars (ic->preedit); i++)
2242 MDEBUG_PRINT1 (" U+%04X", mtext_ref_char (ic->preedit, i));
2245 mtext_reset (ic->preedit);
2246 mtext_reset (ic_info->preedit_saved);
2247 MPLIST_DO (p, ic_info->markers)
2249 ic->cursor_pos = ic_info->state_pos = 0;
2250 ic->preedit_changed = 1;
2252 if (ic->candidate_list)
2254 M17N_OBJECT_UNREF (ic->candidate_list);
2255 ic->candidate_list = NULL;
2256 ic->candidates_changed = MINPUT_CANDIDATES_LIST_CHANGED;
2257 if (ic->candidate_show)
2259 ic->candidate_show = 0;
2260 ic->candidates_changed |= MINPUT_CANDIDATES_SHOW_CHANGED;
2263 memmove (ic_info->keys, ic_info->keys + ic_info->key_head,
2264 sizeof (int) * (ic_info->used - ic_info->key_head));
2265 ic_info->used -= ic_info->key_head;
2266 ic_info->state_key_head = ic_info->key_head = 0;
2270 new_index (MInputContext *ic, int current, int limit, MSymbol sym, MText *mt)
2272 int code = marker_code (sym);
2274 if (mt && (code == '[' || code == ']'))
2278 if (code == '[' && current > 0)
2280 if (mtext_prop_range (mt, Mcandidate_list, pos - 1, &pos, NULL, 1)
2284 else if (code == ']' && current < mtext_nchars (mt))
2286 if (mtext_prop_range (mt, Mcandidate_list, pos, NULL, &pos, 1))
2292 return (code == '<' ? 0
2293 : code == '>' ? limit
2294 : code == '-' ? current - 1
2295 : code == '+' ? current + 1
2296 : code == '=' ? current
2297 : code - '0' > limit ? limit
2301 return (int) mplist_get (((MInputContextInfo *) ic->info)->markers, sym);
2305 update_candidate (MInputContext *ic, MTextProperty *prop, int idx)
2307 int from = mtext_property_start (prop);
2308 int to = mtext_property_end (prop);
2310 MPlist *candidate_list = mtext_property_value (prop);
2311 MPlist *group = find_candidates_group (candidate_list, idx, &start,
2313 int ingroup_index = idx - start;
2316 preedit_delete (ic, from, to);
2317 if (MPLIST_MTEXT_P (group))
2319 mt = MPLIST_MTEXT (group);
2320 preedit_insert (ic, from, NULL, mtext_ref_char (mt, ingroup_index));
2328 for (i = 0, plist = MPLIST_PLIST (group); i < ingroup_index;
2329 i++, plist = MPLIST_NEXT (plist));
2330 mt = MPLIST_MTEXT (plist);
2331 preedit_insert (ic, from, mt, 0);
2332 to = from + mtext_nchars (mt);
2334 mtext_put_prop (ic->preedit, from, to, Mcandidate_list, candidate_list);
2335 mtext_put_prop (ic->preedit, from, to, Mcandidate_index, (void *) idx);
2336 ic->cursor_pos = to;
2340 get_select_charset (MInputContextInfo * ic_info)
2342 MPlist *plist = resolve_variable (ic_info, Mcandidates_charset);
2345 if (! MPLIST_VAL (plist))
2347 sym = MPLIST_SYMBOL (plist);
2350 return MCHARSET (sym);
2354 adjust_candidates (MPlist *plist, MCharset *charset)
2358 /* plist ::= MTEXT ... | PLIST ... */
2359 plist = mplist_copy (plist);
2360 if (MPLIST_MTEXT_P (plist))
2363 while (! MPLIST_TAIL_P (pl))
2365 /* pl ::= MTEXT ... */
2366 MText *mt = MPLIST_MTEXT (pl);
2370 for (i = mtext_nchars (mt) - 1; i >= 0; i--)
2372 c = mtext_ref_char (mt, i);
2373 if (ENCODE_CHAR (charset, c) == MCHAR_INVALID_CODE)
2377 mt = mtext_dup (mt);
2378 mplist_set (pl, Mtext, mt);
2379 M17N_OBJECT_UNREF (mt);
2382 mtext_del (mt, i, i + 1);
2385 if (mtext_len (mt) > 0)
2386 pl = MPLIST_NEXT (pl);
2390 M17N_OBJECT_UNREF (mt);
2394 else /* MPLIST_PLIST_P (plist) */
2397 while (! MPLIST_TAIL_P (pl))
2399 /* pl ::= (MTEXT ...) ... */
2400 MPlist *p = MPLIST_PLIST (pl);
2402 /* p ::= MTEXT ... */
2406 while (! MPLIST_TAIL_P (p0))
2408 MText *mt = MPLIST_MTEXT (p0);
2411 for (i = mtext_nchars (mt) - 1; i >= 0; i--)
2413 c = mtext_ref_char (mt, i);
2414 if (ENCODE_CHAR (charset, c) == MCHAR_INVALID_CODE)
2419 p0 = MPLIST_NEXT (p0);
2426 p = mplist_copy (p);
2427 mplist_set (pl, Mplist, p);
2428 M17N_OBJECT_UNREF (p);
2432 p0 = MPLIST_NEXT (p0);
2435 M17N_OBJECT_UNREF (mt);
2438 if (! MPLIST_TAIL_P (p))
2439 pl = MPLIST_NEXT (pl);
2443 M17N_OBJECT_UNREF (p);
2447 if (MPLIST_TAIL_P (plist))
2449 M17N_OBJECT_UNREF (plist);
2456 get_candidate_list (MInputContextInfo *ic_info, MPlist *args)
2458 MCharset *charset = get_select_charset (ic_info);
2463 plist = resolve_variable (ic_info, Mcandidates_group_size);
2464 column = MPLIST_INTEGER (plist);
2466 plist = MPLIST_PLIST (args);
2469 if (! (plist = adjust_candidates (plist, charset)))
2473 M17N_OBJECT_REF (plist);
2477 if (MPLIST_MTEXT_P (plist))
2479 MText *mt = MPLIST_MTEXT (plist);
2480 MPlist *next = MPLIST_NEXT (plist);
2482 if (MPLIST_TAIL_P (next))
2483 M17N_OBJECT_REF (mt);
2486 mt = mtext_dup (mt);
2487 while (! MPLIST_TAIL_P (next))
2489 mt = mtext_cat (mt, MPLIST_MTEXT (next));
2490 next = MPLIST_NEXT (next);
2493 M17N_OBJECT_UNREF (plist);
2495 len = mtext_nchars (mt);
2497 mplist_add (plist, Mtext, mt);
2500 for (i = 0; i < len; i += column)
2502 int to = (i + column < len ? i + column : len);
2503 MText *sub = mtext_copy (mtext (), 0, mt, i, to);
2505 mplist_add (plist, Mtext, sub);
2506 M17N_OBJECT_UNREF (sub);
2509 M17N_OBJECT_UNREF (mt);
2511 else /* MPLIST_PLIST_P (plist) */
2513 MPlist *pl = MPLIST_PLIST (plist), *p;
2514 MPlist *next = MPLIST_NEXT (plist);
2517 if (MPLIST_TAIL_P (next))
2518 M17N_OBJECT_REF (pl);
2521 pl = mplist_copy (pl);
2522 while (! MPLIST_TAIL_P (next))
2524 p = mplist_copy (MPLIST_PLIST (next));
2525 pl = mplist__conc (pl, p);
2526 M17N_OBJECT_UNREF (p);
2527 next = MPLIST_NEXT (next);
2530 M17N_OBJECT_UNREF (plist);
2532 len = mplist_length (pl);
2534 mplist_add (plist, Mplist, pl);
2539 for (i = 0; i < len; i += column)
2542 mplist_add (plist, Mplist, p);
2543 M17N_OBJECT_UNREF (p);
2544 for (j = 0; j < column && i + j < len; j++)
2546 p = mplist_add (p, Mtext, MPLIST_VAL (p0));
2547 p0 = MPLIST_NEXT (p0);
2551 M17N_OBJECT_UNREF (pl);
2560 regularize_action (MPlist *action_list, MInputContextInfo *ic_info)
2562 MPlist *action = NULL;
2566 if (MPLIST_SYMBOL_P (action_list))
2568 MSymbol var = MPLIST_SYMBOL (action_list);
2571 MPLIST_DO (p, ic_info->vars)
2572 if (MPLIST_SYMBOL (MPLIST_PLIST (p)) == var)
2574 if (MPLIST_TAIL_P (p))
2576 action = MPLIST_NEXT (MPLIST_PLIST (p));
2577 mplist_set (action_list, MPLIST_KEY (action), MPLIST_VAL (action));
2580 if (MPLIST_PLIST_P (action_list))
2582 action = MPLIST_PLIST (action_list);
2583 if (MPLIST_SYMBOL_P (action))
2585 name = MPLIST_SYMBOL (action);
2586 args = MPLIST_NEXT (action);
2588 && MPLIST_PLIST_P (args))
2589 mplist_set (action, Msymbol, M_candidates);
2591 else if (MPLIST_MTEXT_P (action) || MPLIST_PLIST_P (action))
2594 mplist_push (action, Mplist, MPLIST_VAL (action_list));
2595 mplist_push (action, Msymbol, M_candidates);
2596 mplist_set (action_list, Mplist, action);
2597 M17N_OBJECT_UNREF (action);
2600 else if (MPLIST_MTEXT_P (action_list) || MPLIST_INTEGER_P (action_list))
2603 mplist_push (action, MPLIST_KEY (action_list), MPLIST_VAL (action_list));
2604 mplist_push (action, Msymbol, Minsert);
2605 mplist_set (action_list, Mplist, action);
2606 M17N_OBJECT_UNREF (action);
2611 /* Perform list of actions in ACTION_LIST for the current input
2612 context IC. If all actions are performed without error, return 0.
2613 Otherwise, return -1. */
2616 take_action_list (MInputContext *ic, MPlist *action_list)
2618 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
2619 MPlist *candidate_list = ic->candidate_list;
2620 int candidate_index = ic->candidate_index;
2621 int candidate_show = ic->candidate_show;
2622 MTextProperty *prop;
2624 MPLIST_DO (action_list, action_list)
2626 MPlist *action = regularize_action (action_list, ic_info);
2632 name = MPLIST_SYMBOL (action);
2633 args = MPLIST_NEXT (action);
2635 MDEBUG_PRINT1 (" %s", MSYMBOL_NAME (name));
2636 if (name == Minsert)
2638 if (MPLIST_SYMBOL_P (args))
2640 args = resolve_variable (ic_info, MPLIST_SYMBOL (args));
2641 if (! MPLIST_MTEXT_P (args) && ! MPLIST_INTEGER_P (args))
2644 if (MPLIST_MTEXT_P (args))
2645 preedit_insert (ic, ic->cursor_pos, MPLIST_MTEXT (args), 0);
2646 else /* MPLIST_INTEGER_P (args)) */
2647 preedit_insert (ic, ic->cursor_pos, NULL, MPLIST_INTEGER (args));
2649 else if (name == M_candidates)
2651 MPlist *plist = get_candidate_list (ic_info, args);
2656 if (MPLIST_MTEXT_P (plist))
2658 preedit_insert (ic, ic->cursor_pos, NULL,
2659 mtext_ref_char (MPLIST_MTEXT (plist), 0));
2664 MText * mt = MPLIST_MTEXT (MPLIST_PLIST (plist));
2666 preedit_insert (ic, ic->cursor_pos, mt, 0);
2667 len = mtext_nchars (mt);
2669 mtext_put_prop (ic->preedit,
2670 ic->cursor_pos - len, ic->cursor_pos,
2671 Mcandidate_list, plist);
2672 mtext_put_prop (ic->preedit,
2673 ic->cursor_pos - len, ic->cursor_pos,
2674 Mcandidate_index, (void *) 0);
2675 M17N_OBJECT_UNREF (plist);
2677 else if (name == Mselect)
2680 int code, idx, gindex;
2681 int pos = ic->cursor_pos;
2685 || ! (prop = mtext_get_property (ic->preedit, pos - 1,
2688 if (MPLIST_SYMBOL_P (args))
2690 code = marker_code (MPLIST_SYMBOL (args));
2696 idx = (int) mtext_get_prop (ic->preedit, pos - 1, Mcandidate_index);
2697 group = find_candidates_group (mtext_property_value (prop), idx,
2698 &start, &end, &gindex);
2700 if (code != '[' && code != ']')
2704 ? new_index (NULL, ic->candidate_index - start,
2705 end - start - 1, MPLIST_SYMBOL (args),
2707 : MPLIST_INTEGER (args)));
2710 find_candidates_group (mtext_property_value (prop), -1,
2715 && MPLIST_TAIL_P (MPLIST_NEXT (group)))
2720 int ingroup_index = idx - start;
2723 group = mtext_property_value (prop);
2724 len = mplist_length (group);
2737 for (idx = 0; gindex > 0; gindex--, group = MPLIST_NEXT (group))
2738 idx += (MPLIST_MTEXT_P (group)
2739 ? mtext_nchars (MPLIST_MTEXT (group))
2740 : mplist_length (MPLIST_PLIST (group)));
2741 len = (MPLIST_MTEXT_P (group)
2742 ? mtext_nchars (MPLIST_MTEXT (group))
2743 : mplist_length (MPLIST_PLIST (group)));
2744 if (ingroup_index >= len)
2745 ingroup_index = len - 1;
2746 idx += ingroup_index;
2748 update_candidate (ic, prop, idx);
2750 else if (name == Mshow)
2751 ic->candidate_show = 1;
2752 else if (name == Mhide)
2753 ic->candidate_show = 0;
2754 else if (name == Mdelete)
2756 int len = mtext_nchars (ic->preedit);
2760 if (MPLIST_SYMBOL_P (args)
2761 && (pos = surrounding_pos (MPLIST_SYMBOL (args))) != 0)
2763 delete_surrounding_text (ic, pos);
2767 to = (MPLIST_SYMBOL_P (args)
2768 ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
2770 : MPLIST_INTEGER (args));
2775 MDEBUG_PRINT1 ("(%d)", to - ic->cursor_pos);
2776 if (to < ic->cursor_pos)
2777 preedit_delete (ic, to, ic->cursor_pos);
2778 else if (to > ic->cursor_pos)
2779 preedit_delete (ic, ic->cursor_pos, to);
2782 else if (name == Mmove)
2784 int len = mtext_nchars (ic->preedit);
2786 = (MPLIST_SYMBOL_P (args)
2787 ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
2789 : MPLIST_INTEGER (args));
2795 if (pos != ic->cursor_pos)
2797 ic->cursor_pos = pos;
2798 ic->preedit_changed = 1;
2801 else if (name == Mmark)
2803 int code = marker_code (MPLIST_SYMBOL (args));
2806 mplist_put (ic_info->markers, MPLIST_SYMBOL (args),
2807 (void *) ic->cursor_pos);
2809 else if (name == Mpushback)
2811 if (MPLIST_INTEGER_P (args))
2813 int num = MPLIST_INTEGER (args);
2816 ic_info->key_head -= num;
2818 ic_info->key_head = num;
2819 if (ic_info->key_head > ic_info->used)
2820 ic_info->key_head = ic_info->used;
2822 else if (MPLIST_MTEXT_P (args))
2824 MText *mt = MPLIST_MTEXT (args);
2825 int i, len = mtext_nchars (mt);
2828 ic_info->key_head--;
2829 for (i = 0; i < len; i++)
2831 key = one_char_symbol[MTEXT_DATA (mt)[i]];
2832 if (ic_info->key_head + i < ic_info->used)
2833 ic_info->keys[ic_info->key_head + i] = key;
2835 MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
2840 MPlist *plist = MPLIST_PLIST (args), *pl;
2844 ic_info->key_head--;
2846 MPLIST_DO (pl, plist)
2848 key = MPLIST_SYMBOL (pl);
2849 if (ic_info->key_head < ic_info->used)
2850 ic_info->keys[ic_info->key_head + i] = key;
2852 MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
2857 else if (name == Mcall)
2859 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
2860 MIMExternalFunc func = NULL;
2861 MSymbol module, func_name;
2862 MPlist *func_args, *val;
2865 module = MPLIST_SYMBOL (args);
2866 args = MPLIST_NEXT (args);
2867 func_name = MPLIST_SYMBOL (args);
2869 if (im_info->externals)
2871 MIMExternalModule *external
2872 = (MIMExternalModule *) mplist_get (im_info->externals,
2875 func = (MIMExternalFunc) mplist_get (external->func_list,
2880 func_args = mplist ();
2881 mplist_add (func_args, Mt, ic);
2882 MPLIST_DO (args, MPLIST_NEXT (args))
2886 if (MPLIST_KEY (args) == Msymbol
2887 && MPLIST_KEY (args) != Mnil
2888 && (code = marker_code (MPLIST_SYMBOL (args))) >= 0)
2890 code = new_index (ic, ic->cursor_pos,
2891 mtext_nchars (ic->preedit),
2892 MPLIST_SYMBOL (args), ic->preedit);
2893 mplist_add (func_args, Minteger, (void *) code);
2896 mplist_add (func_args, MPLIST_KEY (args), MPLIST_VAL (args));
2898 val = (func) (func_args);
2899 M17N_OBJECT_UNREF (func_args);
2900 if (val && ! MPLIST_TAIL_P (val))
2901 ret = take_action_list (ic, val);
2902 M17N_OBJECT_UNREF (val);
2906 else if (name == Mshift)
2908 shift_state (ic, MPLIST_SYMBOL (args));
2910 else if (name == Mundo)
2912 int intarg = (MPLIST_TAIL_P (args)
2914 : integer_value (ic, args, NULL, 0));
2916 mtext_reset (ic->preedit);
2917 mtext_reset (ic_info->preedit_saved);
2918 ic->cursor_pos = ic_info->state_pos = 0;
2919 ic_info->state_key_head = ic_info->key_head = 0;
2922 ic_info->used += intarg;
2924 ic_info->used = intarg;
2925 shift_state (ic, Mnil);
2928 else if (name == Mset || name == Madd || name == Msub
2929 || name == Mmul || name == Mdiv)
2931 MSymbol sym = MPLIST_SYMBOL (args);
2936 val1 = integer_value (ic, args, &value, 0);
2937 args = MPLIST_NEXT (args);
2938 val2 = resolve_expression (ic, args);
2940 val1 = val2, op = "=";
2941 else if (name == Madd)
2942 val1 += val2, op = "+=";
2943 else if (name == Msub)
2944 val1 -= val2, op = "-=";
2945 else if (name == Mmul)
2946 val1 *= val2, op = "*=";
2948 val1 /= val2, op = "/=";
2949 MDEBUG_PRINT4 ("(%s %s 0x%X(%d))",
2950 MSYMBOL_NAME (sym), op, val1, val1);
2952 mplist_set (value, Minteger, (void *) val1);
2954 else if (name == Mequal || name == Mless || name == Mgreater
2955 || name == Mless_equal || name == Mgreater_equal)
2958 MPlist *actions1, *actions2;
2961 val1 = resolve_expression (ic, args);
2962 args = MPLIST_NEXT (args);
2963 val2 = resolve_expression (ic, args);
2964 args = MPLIST_NEXT (args);
2965 actions1 = MPLIST_PLIST (args);
2966 args = MPLIST_NEXT (args);
2967 if (MPLIST_TAIL_P (args))
2970 actions2 = MPLIST_PLIST (args);
2971 MDEBUG_PRINT3 ("(%d %s %d)? ", val1, MSYMBOL_NAME (name), val2);
2972 if (name == Mequal ? val1 == val2
2973 : name == Mless ? val1 < val2
2974 : name == Mgreater ? val1 > val2
2975 : name == Mless_equal ? val1 <= val2
2978 MDEBUG_PRINT ("ok");
2979 ret = take_action_list (ic, actions1);
2983 MDEBUG_PRINT ("no");
2985 ret = take_action_list (ic, actions2);
2990 else if (name == Mcond)
2994 MPLIST_DO (args, args)
2999 if (! MPLIST_PLIST (args))
3001 cond = MPLIST_PLIST (args);
3002 if (resolve_expression (ic, cond) != 0)
3004 MDEBUG_PRINT1 ("(%dth)", idx);
3005 if (take_action_list (ic, MPLIST_NEXT (cond)) < 0)
3011 else if (name == Mcommit)
3013 preedit_commit (ic);
3015 else if (name == Munhandle)
3017 preedit_commit (ic);
3022 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
3026 && (actions = mplist_get (im_info->macros, name)))
3028 if (take_action_list (ic, actions) < 0)
3034 M17N_OBJECT_UNREF (ic->candidate_list);
3035 if (ic->cursor_pos > 0
3036 && (prop = mtext_get_property (ic->preedit, ic->cursor_pos - 1,
3039 ic->candidate_list = mtext_property_value (prop);
3040 M17N_OBJECT_REF (ic->candidate_list);
3042 = (int) mtext_get_prop (ic->preedit, ic->cursor_pos - 1,
3044 ic->candidate_from = mtext_property_start (prop);
3045 ic->candidate_to = mtext_property_end (prop);
3048 if (candidate_list != ic->candidate_list)
3049 ic->candidates_changed |= MINPUT_CANDIDATES_LIST_CHANGED;
3050 if (candidate_index != ic->candidate_index)
3051 ic->candidates_changed |= MINPUT_CANDIDATES_INDEX_CHANGED;
3052 if (candidate_show != ic->candidate_show)
3053 ic->candidates_changed |= MINPUT_CANDIDATES_SHOW_CHANGED;
3058 /* Handle the input key KEY in the current state and map specified in
3059 the input context IC. If KEY is handled correctly, return 0.
3060 Otherwise, return -1. */
3063 handle_key (MInputContext *ic)
3065 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
3066 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
3067 MIMMap *map = ic_info->map;
3068 MIMMap *submap = NULL;
3069 MSymbol key = ic_info->keys[ic_info->key_head];
3070 MSymbol alias = Mnil;
3073 MDEBUG_PRINT2 (" [IM] handle `%s' in state %s",
3074 msymbol_name (key), MSYMBOL_NAME (ic_info->state->name));
3078 submap = mplist_get (map->submaps, key);
3081 && (alias = msymbol_get (alias, M_key_alias))
3083 submap = mplist_get (map->submaps, alias);
3088 if (! alias || alias == key)
3089 MDEBUG_PRINT (" submap-found");
3091 MDEBUG_PRINT1 (" submap-found (by alias `%s')", MSYMBOL_NAME (alias));
3092 mtext_cpy (ic->preedit, ic_info->preedit_saved);
3093 ic->preedit_changed = 1;
3094 ic->cursor_pos = ic_info->state_pos;
3095 ic_info->key_head++;
3096 ic_info->map = map = submap;
3097 if (map->map_actions)
3099 MDEBUG_PRINT (" map-actions:");
3100 if (take_action_list (ic, map->map_actions) < 0)
3102 MDEBUG_PRINT ("\n");
3106 else if (map->submaps)
3108 for (i = ic_info->state_key_head; i < ic_info->key_head; i++)
3110 MSymbol key = ic_info->keys[i];
3111 char *name = msymbol_name (key);
3113 if (! name[0] || ! name[1])
3114 mtext_ins_char (ic->preedit, ic->cursor_pos++, name[0], 1);
3118 /* If this is the terminal map or we have shifted to another
3119 state, perform branch actions (if any). */
3120 if (! map->submaps || map != ic_info->map)
3122 if (map->branch_actions)
3124 MDEBUG_PRINT (" branch-actions:");
3125 if (take_action_list (ic, map->branch_actions) < 0)
3127 MDEBUG_PRINT ("\n");
3131 /* If MAP is still not the root map, shift to the current
3133 if (ic_info->map != ic_info->state->map)
3134 shift_state (ic, ic_info->state->name);
3139 /* MAP can not handle KEY. */
3141 /* If MAP is the root map of the initial state, it means that
3142 the current input method can not handle KEY. */
3143 if (map == ((MIMState *) MPLIST_VAL (im_info->states))->map)
3145 MDEBUG_PRINT (" unhandled\n");
3149 if (map != ic_info->state->map)
3151 /* If MAP is not the root map... */
3152 /* If MAP has branch actions, perform them. */
3153 if (map->branch_actions)
3155 MDEBUG_PRINT (" branch-actions:");
3156 if (take_action_list (ic, map->branch_actions) < 0)
3158 MDEBUG_PRINT ("\n");
3162 /* If MAP is still not the root map, shift to the current
3164 if (ic_info->map != ic_info->state->map)
3165 shift_state (ic, ic_info->state->name);
3169 /* MAP is the root map, perform branch actions (if any) or
3170 shift to the initial state. */
3171 if (map->branch_actions)
3173 MDEBUG_PRINT (" branch-actions:");
3174 if (take_action_list (ic, map->branch_actions) < 0)
3176 MDEBUG_PRINT ("\n");
3181 shift_state (ic, Mnil);
3184 MDEBUG_PRINT ("\n");
3188 /* Initialize IC->ic_info. */
3191 init_ic_info (MInputContext *ic)
3193 MInputMethodInfo *im_info = ic->im->info;
3194 MInputContextInfo *ic_info = ic->info;
3197 MLIST_INIT1 (ic_info, keys, 8);;
3199 ic_info->markers = mplist ();
3201 ic_info->vars = mplist ();
3202 if (im_info->configured_vars)
3203 MPLIST_DO (plist, im_info->configured_vars)
3205 MPlist *pl = MPLIST_PLIST (plist), *p = mplist ();
3206 MSymbol name = MPLIST_SYMBOL (pl);
3208 pl = MPLIST_NEXT (MPLIST_NEXT (pl));
3209 mplist_push (ic_info->vars, Mplist, p);
3210 M17N_OBJECT_UNREF (p);
3211 mplist_add (p, Msymbol, name);
3212 mplist_add (p, MPLIST_KEY (pl), MPLIST_VAL (pl));
3215 if (im_info->externals)
3217 MPlist *func_args = mplist (), *plist;
3219 mplist_add (func_args, Mt, ic);
3220 MPLIST_DO (plist, im_info->externals)
3222 MIMExternalModule *external = MPLIST_VAL (plist);
3223 MIMExternalFunc func
3224 = (MIMExternalFunc) mplist_get (external->func_list, Minit);
3229 M17N_OBJECT_UNREF (func_args);
3232 ic_info->preedit_saved = mtext ();
3233 ic_info->tick = im_info->tick;
3236 /* Finalize IC->ic_info. */
3239 fini_ic_info (MInputContext *ic)
3241 MInputMethodInfo *im_info = ic->im->info;
3242 MInputContextInfo *ic_info = ic->info;
3244 if (im_info->externals)
3246 MPlist *func_args = mplist (), *plist;
3248 mplist_add (func_args, Mt, ic);
3249 MPLIST_DO (plist, im_info->externals)
3251 MIMExternalModule *external = MPLIST_VAL (plist);
3252 MIMExternalFunc func
3253 = (MIMExternalFunc) mplist_get (external->func_list, Mfini);
3258 M17N_OBJECT_UNREF (func_args);
3261 MLIST_FREE1 (ic_info, keys);
3262 M17N_OBJECT_UNREF (ic_info->preedit_saved);
3263 M17N_OBJECT_UNREF (ic_info->markers);
3264 M17N_OBJECT_UNREF (ic_info->vars);
3265 M17N_OBJECT_UNREF (ic_info->preceding_text);
3266 M17N_OBJECT_UNREF (ic_info->following_text);
3268 memset (ic_info, 0, sizeof (MInputContextInfo));
3272 re_init_ic (MInputContext *ic, int reload)
3274 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
3275 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
3276 int status_changed, preedit_changed, cursor_pos_changed, candidates_changed;
3278 status_changed = ic_info->state != (MIMState *) MPLIST_VAL (im_info->states);
3279 preedit_changed = mtext_nchars (ic->preedit) > 0;
3280 cursor_pos_changed = ic->cursor_pos > 0;
3281 candidates_changed = 0;
3282 if (ic->candidate_list)
3284 candidates_changed |= MINPUT_CANDIDATES_LIST_CHANGED;
3285 M17N_OBJECT_UNREF (ic->candidate_list);
3287 if (ic->candidate_show)
3289 candidates_changed |= MINPUT_CANDIDATES_SHOW_CHANGED;
3290 ic->candidate_show = 0;
3292 if (ic->candidate_index > 0)
3294 candidates_changed |= MINPUT_CANDIDATES_INDEX_CHANGED;
3295 ic->candidate_index = 0;
3296 ic->candidate_from = ic->candidate_to = 0;
3298 if (mtext_nchars (ic->produced) > 0)
3299 mtext_reset (ic->produced);
3300 if (mtext_nchars (ic->preedit) > 0)
3301 mtext_reset (ic->preedit);
3303 M17N_OBJECT_UNREF (ic->plist);
3304 ic->plist = mplist ();
3308 reload_im_info (im_info);
3310 shift_state (ic, Mnil);
3311 ic->status_changed = status_changed;
3312 ic->preedit_changed = preedit_changed;
3313 ic->cursor_pos_changed = cursor_pos_changed;
3314 ic->candidates_changed = candidates_changed;
3318 reset_ic (MInputContext *ic, MSymbol ignore)
3320 MDEBUG_PRINT ("\n [IM] reset\n");
3325 open_im (MInputMethod *im)
3327 MInputMethodInfo *im_info = get_im_info (im->language, im->name, Mnil, Mnil);
3330 MERROR (MERROR_IM, -1);
3337 close_im (MInputMethod *im)
3343 create_ic (MInputContext *ic)
3345 MInputContextInfo *ic_info;
3347 MSTRUCT_CALLOC (ic_info, MERROR_IM);
3350 shift_state (ic, Mnil);
3355 destroy_ic (MInputContext *ic)
3362 check_reload (MInputContext *ic, MSymbol key)
3364 MInputMethodInfo *im_info = ic->im->info;
3365 MPlist *plist = resolve_command (im_info->configured_cmds, Mat_reload);
3369 plist = resolve_command (global_info->configured_cmds, Mat_reload);
3373 MPLIST_DO (plist, plist)
3375 MSymbol this_key, alias;
3377 if (MPLIST_MTEXT_P (plist))
3379 MText *mt = MPLIST_MTEXT (plist);
3380 int c = mtext_ref_char (mt, 0);
3384 this_key = one_char_symbol[c];
3388 MPlist *pl = MPLIST_PLIST (plist);
3390 this_key = MPLIST_SYMBOL (pl);
3394 && (alias = msymbol_get (alias, M_key_alias))
3395 && alias != this_key);
3399 if (MPLIST_TAIL_P (plist))
3402 MDEBUG_PRINT ("\n [IM] reload");
3408 /** Handle the input key KEY in the current state and map of IC->info.
3409 If KEY is handled but no text is produced, return 0, otherwise
3415 filter (MInputContext *ic, MSymbol key, void *arg)
3417 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
3418 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
3421 if (check_reload (ic, key))
3424 if (! ic_info->state)
3426 ic_info->key_unhandled = 1;
3429 mtext_reset (ic->produced);
3430 ic->status_changed = ic->preedit_changed = ic->candidates_changed = 0;
3431 M17N_OBJECT_UNREF (ic_info->preceding_text);
3432 M17N_OBJECT_UNREF (ic_info->following_text);
3433 MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
3434 ic_info->key_unhandled = 0;
3437 if (handle_key (ic) < 0)
3439 /* KEY was not handled. Delete it from the current key sequence. */
3440 if (ic_info->used > 0)
3442 memmove (ic_info->keys, ic_info->keys + 1,
3443 sizeof (int) * (ic_info->used - 1));
3446 /* This forces returning 1. */
3447 ic_info->key_unhandled = 1;
3453 reset_ic (ic, Mnil);
3454 ic_info->key_unhandled = 1;
3457 /* Break the loop if all keys were handled. */
3458 } while (ic_info->key_head < ic_info->used);
3460 /* If the current map is the root of the initial state, we should
3461 produce any preedit text in ic->produced. */
3462 if (ic_info->map == ((MIMState *) MPLIST_VAL (im_info->states))->map
3463 && mtext_nchars (ic->preedit) > 0)
3464 shift_state (ic, ((MIMState *) MPLIST_VAL (im_info->states))->name);
3466 if (mtext_nchars (ic->produced) > 0)
3468 MSymbol lang = msymbol_get (ic->im->language, Mlanguage);
3471 mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
3472 Mlanguage, ic->im->language);
3475 return (! ic_info->key_unhandled && mtext_nchars (ic->produced) == 0);
3479 /** Return 1 if the last event or key was not handled, otherwise
3482 There is no need of looking up because ic->produced should already
3483 contain the produced text (if any).
3488 lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
3490 mtext_cat (mt, ic->produced);
3491 mtext_reset (ic->produced);
3492 return (((MInputContextInfo *) ic->info)->key_unhandled ? -1 : 0);
3496 /* Input method command handler. */
3498 /* List of all (global and local) commands.
3499 (LANG:(IM-NAME:(COMMAND ...) ...) ...) ...
3500 COMMAND is CMD-NAME:(mtext:DESCRIPTION plist:KEYSEQ ...))
3501 Global commands are stored as (t (t COMMAND ...)) */
3504 /* Input method variable handler. */
3507 /* Support functions for mdebug_dump_im. */
3510 dump_im_map (MPlist *map_list, int indent)
3513 MSymbol key = MPLIST_KEY (map_list);
3514 MIMMap *map = (MIMMap *) MPLIST_VAL (map_list);
3516 prefix = (char *) alloca (indent + 1);
3517 memset (prefix, 32, indent);
3518 prefix[indent] = '\0';
3520 fprintf (stderr, "(\"%s\" ", msymbol_name (key));
3521 if (map->map_actions)
3522 mdebug_dump_plist (map->map_actions, indent + 2);
3525 MPLIST_DO (map_list, map->submaps)
3527 fprintf (stderr, "\n%s ", prefix);
3528 dump_im_map (map_list, indent + 2);
3531 if (map->branch_actions)
3533 fprintf (stderr, "\n%s (branch\n%s ", prefix, prefix);
3534 mdebug_dump_plist (map->branch_actions, indent + 4);
3535 fprintf (stderr, ")");
3537 fprintf (stderr, ")");
3542 dump_im_state (MIMState *state, int indent)
3547 prefix = (char *) alloca (indent + 1);
3548 memset (prefix, 32, indent);
3549 prefix[indent] = '\0';
3551 fprintf (stderr, "(%s", msymbol_name (state->name));
3552 if (state->map->submaps)
3554 MPLIST_DO (map_list, state->map->submaps)
3556 fprintf (stderr, "\n%s ", prefix);
3557 dump_im_map (map_list, indent + 2);
3560 fprintf (stderr, ")");
3568 Minput_driver = msymbol ("input-driver");
3570 Minput_preedit_start = msymbol ("input-preedit-start");
3571 Minput_preedit_done = msymbol ("input-preedit-done");
3572 Minput_preedit_draw = msymbol ("input-preedit-draw");
3573 Minput_status_start = msymbol ("input-status-start");
3574 Minput_status_done = msymbol ("input-status-done");
3575 Minput_status_draw = msymbol ("input-status-draw");
3576 Minput_candidates_start = msymbol ("input-candidates-start");
3577 Minput_candidates_done = msymbol ("input-candidates-done");
3578 Minput_candidates_draw = msymbol ("input-candidates-draw");
3579 Minput_set_spot = msymbol ("input-set-spot");
3580 Minput_focus_move = msymbol ("input-focus-move");
3581 Minput_focus_in = msymbol ("input-focus-in");
3582 Minput_focus_out = msymbol ("input-focus-out");
3583 Minput_toggle = msymbol ("input-toggle");
3584 Minput_reset = msymbol ("input-reset");
3585 Minput_get_surrounding_text = msymbol ("input-get-surrounding-text");
3586 Minput_delete_surrounding_text = msymbol ("input-delete-surrounding-text");
3588 minput_default_driver.open_im = open_im;
3589 minput_default_driver.close_im = close_im;
3590 minput_default_driver.create_ic = create_ic;
3591 minput_default_driver.destroy_ic = destroy_ic;
3592 minput_default_driver.filter = filter;
3593 minput_default_driver.lookup = lookup;
3594 minput_default_driver.callback_list = mplist ();
3595 mplist_put (minput_default_driver.callback_list, Minput_reset,
3597 minput_driver = &minput_default_driver;
3599 fully_initialized = 0;
3606 if (fully_initialized)
3608 free_im_list (im_info_list);
3610 free_im_list (im_custom_list);
3612 free_im_list (im_config_list);
3613 M17N_OBJECT_UNREF (load_im_info_keys);
3616 M17N_OBJECT_UNREF (minput_default_driver.callback_list);
3617 M17N_OBJECT_UNREF (minput_driver->callback_list);
3622 minput__callback (MInputContext *ic, MSymbol command)
3624 MInputCallbackFunc func;
3626 if (! ic->im->driver.callback_list)
3628 func = (MInputCallbackFunc) mplist_get (ic->im->driver.callback_list,
3632 (func) (ic, command);
3637 minput__char_to_key (int c)
3639 if (c < 0 || c >= 0x100)
3642 return one_char_symbol[c];
3646 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
3651 /*** @addtogroup m17nInputMethod */
3656 @name Variables: Predefined symbols for callback commands.
3658 These are the predefined symbols that are used as the @c COMMAND
3659 argument of callback functions of an input method driver (see
3660 #MInputDriver::callback_list).
3662 Most of them don't require extra argument nor return any value;
3663 exceptions are these:
3665 Minput_get_surrounding_text: When a callback function assigned for
3666 this command is called, the first element of #MInputContext::plist
3667 has key #Minteger and the value specifies which portion of the
3668 surrounding text should be retrieved. If the value is positive,
3669 it specifies the number of characters following the current cursor
3670 position. If the value is negative, the absolute value specifies
3671 the number of characters preceding the current cursor position.
3673 If the surrounding text is currently supported, the callback
3674 function must set the key of this element to #Mtext and the value
3675 to the retrieved M-text. The length of the M-text may be shorter
3676 than the requested number of characters, if the available text is
3677 not that long. The length can be zero in the worst case. Or, the
3678 length may be longer if an application thinks it's more efficient
3679 to return that length).
3681 If the surrounding text is not currently supported, the callback
3682 function should return without changing the first element of
3683 #MInputContext::plist.
3685 Minput_delete_surrounding_text: When a callback function assigned
3686 for this command is called, the first element of
3687 #MInputContext::plist has key #Minteger and the value specifies
3688 which portion of the surrounding text should be deleted in the
3689 same way as the case of Minput_get_surrounding_text. The callback
3690 function must delete the specified text. It should not alter
3691 #MInputContext::plist. */
3694 @name ÊÑ¿ô¡§ ¥³¡¼¥ë¥Ð¥Ã¥¯¥³¥Þ¥ó¥ÉÍÑÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë.
3696 ÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Î¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Ë¤ª¤¤¤Æ @c COMMAND
3697 °ú¿ô¤È¤·¤ÆÍѤ¤¤é¤ì¤ëÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë (#MInputDriver::callback_list »²¾È)¡£
3702 MSymbol Minput_preedit_start;
3703 MSymbol Minput_preedit_done;
3704 MSymbol Minput_preedit_draw;
3705 MSymbol Minput_status_start;
3706 MSymbol Minput_status_done;
3707 MSymbol Minput_status_draw;
3708 MSymbol Minput_candidates_start;
3709 MSymbol Minput_candidates_done;
3710 MSymbol Minput_candidates_draw;
3711 MSymbol Minput_set_spot;
3712 MSymbol Minput_toggle;
3713 MSymbol Minput_reset;
3714 MSymbol Minput_get_surrounding_text;
3715 MSymbol Minput_delete_surrounding_text;
3721 @name Variables: Predefined symbols for special input events.
3723 These are the predefined symbols that are used as the @c KEY
3724 argument of minput_filter (). */
3729 MSymbol Minput_focus_out;
3730 MSymbol Minput_focus_in;
3731 MSymbol Minput_focus_move;
3738 @brief The default driver for internal input methods.
3740 The variable #minput_default_driver is the default driver for
3741 internal input methods.
3743 The member MInputDriver::open_im () searches the m17n database for
3744 an input method that matches the tag \< #Minput_method, $LANGUAGE,
3745 $NAME\> and loads it.
3747 The member MInputDriver::callback_list () is @c NULL. Thus, it is
3748 programmers responsibility to set it to a plist of proper callback
3749 functions. Otherwise, no feedback information (e.g. preedit text)
3750 can be shown to users.
3752 The macro M17N_INIT () sets the variable #minput_driver to the
3753 pointer to this driver so that all internal input methods use it.
3755 Therefore, unless @c minput_driver is set differently, the driver
3756 dependent arguments $ARG of the functions whose name begins with
3757 "minput_" are all ignored. */
3760 @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥǥե©¥ë¥È¥É¥é¥¤¥Ð.
3762 ÊÑ¿ô #minput_default_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѤΥǥե©¥ë¥È¤Î¥É¥é¥¤¥Ð¤òɽ¤¹¡£
3764 ¥á¥ó¥Ð MInputDriver::open_im () ¤Ï m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹Ã椫¤é¥¿¥°
3765 \< #Minput_method, $LANGUAGE, $NAME\>
3766 ¤Ë¹çÃפ¹¤ëÆþÎϥ᥽¥Ã¥É¤òõ¤·¡¢¤½¤ì¤ò¥í¡¼¥É¤¹¤ë¡£
3768 ¥á¥ó¥Ð MInputDriver::callback_list () ¤Ï @c NULL ¤Ç¤¢¤ê¡¢
3769 ¤·¤¿¤¬¤Ã¤Æ¡¢¥×¥í¥°¥é¥Þ¦¤ÇÀÕǤ¤ò»ý¤Ã¤Æ ŬÀڤʥ³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Î plist
3770 ¤ËÀßÄꤷ¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¤µ¤â¤Ê¤¤¤È¡¢preedit
3771 ¥Æ¥¥¹¥È¤Ê¤É¤Î¥Õ¥£¡¼¥É¥Ð¥Ã¥¯¾ðÊ󤬥桼¥¶¤Ëɽ¼¨¤µ¤ì¤Ê¤¤¡£
3773 ¥Þ¥¯¥í M17N_INIT () ¤ÏÊÑ¿ô #minput_driver
3774 ¤ò¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤ËÀßÄꤷ¡¢Á´¤Æ¤ÎÆâÉôÆþÎϥ᥽¥Ã¥É¤¬¤³¤Î¥É¥é¥¤¥Ð¤ò»È¤¦¤è¤¦¤Ë¤¹¤ë¡£
3776 ¤·¤¿¤¬¤Ã¤Æ¡¢@c minput_driver ¤¬¥Ç¥Õ¥©¥ë¥ÈÃͤΤޤޤǤ¢¤ì¤Ð¡¢minput_
3777 ¤Ç»Ï¤Þ¤ë´Ø¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô $ARG ¤Ï¤¹¤Ù¤Æ̵»ë¤µ¤ì¤ë¡£ */
3779 MInputDriver minput_default_driver;
3783 @brief The driver for internal input methods.
3785 The variable #minput_driver is a pointer to the input method
3786 driver that is used by internal input methods. The macro
3787 M17N_INIT () initializes it to a pointer to #minput_default_driver
3788 if <m17n<EM></EM>.h> is included. */
3790 @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥɥ饤¥Ð.
3792 ÊÑ¿ô #minput_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤Æ»ÈÍѤµ¤ì¤Æ¤¤¤ëÆþÎÏ¥á
3793 ¥½¥Ã¥É¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£¥Þ¥¯¥í M17N_INIT () ¤Ï¤³¤Î¥Ý¥¤¥ó
3794 ¥¿¤ò#minput_default_driver (<m17n<EM></EM>.h> ¤¬ include ¤µ¤ì¤Æ¤¤¤ë
3795 »þ) ¤Ë½é´ü²½¤¹¤ë¡£ */
3797 MInputDriver *minput_driver;
3799 MSymbol Minput_driver;
3804 @brief Open an input method.
3806 The minput_open_im () function opens an input method whose
3807 language and name match $LANGUAGE and $NAME, and returns a pointer
3808 to the input method object newly allocated.
3810 This function at first decides a driver for the input method as
3813 If $LANGUAGE is not #Mnil, the driver pointed by the variable
3814 #minput_driver is used.
3816 If $LANGUAGE is #Mnil and $NAME has the property #Minput_driver, the
3817 driver pointed to by the property value is used to open the input
3818 method. If $NAME has no such a property, @c NULL is returned.
3820 Then, the member MInputDriver::open_im () of the driver is
3823 $ARG is set in the member @c arg of the structure MInputMethod so
3824 that the driver can refer to it. */
3827 @brief ÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë.
3829 ´Ø¿ô minput_open_im () ¤Ï¸À¸ì $LANGUAGE ¤È̾Á° $NAME
3830 ¤Ë¹çÃפ¹¤ëÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤·¡¢¿·¤¿¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿ÆþÎϥ᥽¥Ã¥É¥ª¥Ö¥¸¥§¥¯¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
3832 ¤³¤Î´Ø¿ô¤Ï¡¢¤Þ¤ºÆþÎϥ᥽¥Ã¥ÉÍѤΥɥ饤¥Ð¤ò°Ê²¼¤Î¤è¤¦¤Ë¤·¤Æ·èÄꤹ¤ë¡£
3834 $LANGUAGE ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢ÊÑ¿ô #minput_driver
3835 ¤Ç»Ø¤µ¤ì¤Æ¤¤¤ë¥É¥é¥¤¥Ð¤òÍѤ¤¤ë¡£
3837 $LANGUAGE ¤¬ #Mnil ¤Ç¤¢¤ê¡¢$NAME ¤¬ #Minput_driver
3838 ¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä¾ì¹ç¤Ë¤Ï¡¢¤½¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤǻؤµ¤ì¤Æ¤¤¤ëÆþÎϥɥ饤¥Ð¤òÍѤ¤¤ÆÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë¡£
3839 $NAME ¤Ë¤½¤Î¤è¤¦¤Ê¥×¥í¥Ñ¥Æ¥£¤¬Ìµ¤«¤Ã¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
3841 ¼¡¤¤¤Ç¡¢¥É¥é¥¤¥Ð¤Î¥á¥ó¥Ð MInputDriver::open_im () ¤¬¸Æ¤Ð¤ì¤ë¡£
3843 $ARG ¤Ï¹½Â¤ÂÎ MInputMethod ¤Î¥á¥ó¥Ð @c arg ¤ËÀßÄꤵ¤ì¡¢¥É¥é¥¤¥Ð¤«¤é»²¾È¤Ç¤¤ë¡£
3845 @latexonly \IPAlabel{minput_open} @endlatexonly
3850 minput_open_im (MSymbol language, MSymbol name, void *arg)
3853 MInputDriver *driver;
3857 MDEBUG_PRINT2 (" [IM] opening (%s %s) ... ",
3858 msymbol_name (language), msymbol_name (name));
3860 driver = minput_driver;
3863 driver = (MInputDriver *) msymbol_get (name, Minput_driver);
3865 MERROR (MERROR_IM, NULL);
3868 MSTRUCT_CALLOC (im, MERROR_IM);
3869 im->language = language;
3872 im->driver = *driver;
3873 if ((*im->driver.open_im) (im) < 0)
3875 MDEBUG_PRINT (" failed\n");
3879 MDEBUG_PRINT (" ok\n");
3886 @brief Close an input method.
3888 The minput_close_im () function closes the input method $IM, which
3889 must have been created by minput_open_im (). */
3892 @brief ÆþÎϥ᥽¥Ã¥É¤ò¥¯¥í¡¼¥º¤¹¤ë.
3894 ´Ø¿ô minput_close_im () ¤Ï¡¢ÆþÎϥ᥽¥Ã¥É $IM ¤ò¥¯¥í¡¼¥º¤¹¤ë¡£
3895 ¤³¤ÎÆþÎϥ᥽¥Ã¥É $IM ¤Ï minput_open_im () ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£ */
3898 minput_close_im (MInputMethod *im)
3900 MDEBUG_PRINT2 (" [IM] closing (%s %s) ... ",
3901 msymbol_name (im->name), msymbol_name (im->language));
3902 (*im->driver.close_im) (im);
3904 MDEBUG_PRINT (" done\n");
3910 @brief Create an input context.
3912 The minput_create_ic () function creates an input context object
3913 associated with input method $IM, and calls callback functions
3914 corresponding to #Minput_preedit_start, #Minput_status_start, and
3915 #Minput_status_draw in this order.
3918 If an input context is successfully created, minput_create_ic ()
3919 returns a pointer to it. Otherwise it returns @c NULL. */
3922 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÀ¸À®¤¹¤ë.
3924 ´Ø¿ô minput_create_ic () ¤ÏÆþÎϥ᥽¥Ã¥É $IM
3925 ¤ËÂбþ¤¹¤ëÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤·¡¢
3926 #Minput_preedit_start, #Minput_status_start, #Minput_status_draw
3927 ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¤³¤Î½ç¤Ë¸Æ¤Ö¡£
3930 ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤¬À¸À®¤µ¤ì¤¿¾ì¹ç¡¢minput_create_ic ()
3931 ¤Ï¤½¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¼ºÇÔ¤·¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
3935 minput_create_ic (MInputMethod *im, void *arg)
3939 MDEBUG_PRINT2 (" [IM] creating context (%s %s) ... ",
3940 msymbol_name (im->name), msymbol_name (im->language));
3941 MSTRUCT_CALLOC (ic, MERROR_IM);
3944 ic->preedit = mtext ();
3945 ic->candidate_list = NULL;
3946 ic->produced = mtext ();
3947 ic->spot.x = ic->spot.y = 0;
3949 ic->plist = mplist ();
3950 if ((*im->driver.create_ic) (ic) < 0)
3952 MDEBUG_PRINT (" failed\n");
3953 M17N_OBJECT_UNREF (ic->preedit);
3954 M17N_OBJECT_UNREF (ic->produced);
3955 M17N_OBJECT_UNREF (ic->plist);
3960 if (im->driver.callback_list)
3962 minput__callback (ic, Minput_preedit_start);
3963 minput__callback (ic, Minput_status_start);
3964 minput__callback (ic, Minput_status_draw);
3967 MDEBUG_PRINT (" ok\n");
3974 @brief Destroy an input context.
3976 The minput_destroy_ic () function destroys the input context $IC,
3977 which must have been created by minput_create_ic (). It calls
3978 callback functions corresponding to #Minput_preedit_done,
3979 #Minput_status_done, and #Minput_candidates_done in this order. */
3982 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÇ˲õ¤¹¤ë.
3984 ´Ø¿ô minput_destroy_ic () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤òÇ˲õ¤¹¤ë¡£
3985 ¤³¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ï minput_create_ic ()
3986 ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£¤³¤Î´Ø¿ô¤Ï
3987 #Minput_preedit_done, #Minput_status_done, #Minput_candidates_done
3988 ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¤³¤Î½ç¤Ë¸Æ¤Ö¡£
3992 minput_destroy_ic (MInputContext *ic)
3994 MDEBUG_PRINT2 (" [IM] destroying context (%s %s) ... ",
3995 msymbol_name (ic->im->name), msymbol_name (ic->im->language));
3996 if (ic->im->driver.callback_list)
3998 minput__callback (ic, Minput_preedit_done);
3999 minput__callback (ic, Minput_status_done);
4000 minput__callback (ic, Minput_candidates_done);
4002 (*ic->im->driver.destroy_ic) (ic);
4003 M17N_OBJECT_UNREF (ic->preedit);
4004 M17N_OBJECT_UNREF (ic->produced);
4005 M17N_OBJECT_UNREF (ic->plist);
4006 MDEBUG_PRINT (" done\n");
4013 @brief Filter an input key.
4015 The minput_filter () function filters input key $KEY according to
4016 input context $IC, and calls callback functions corresponding to
4017 #Minput_preedit_draw, #Minput_status_draw, and
4018 #Minput_candidates_draw if the preedit text, the status, and the
4019 current candidate are changed respectively.
4021 To make the input method commit the current preedit text (if any)
4022 and shift to the initial state, call this function with #Mnil as
4025 To inform the input method about the focus-out event, call this
4026 function with #Minput_focus_out as $KEY.
4028 To inform the input method about the focus-in event, call this
4029 function with #Minput_focus_in as $KEY.
4031 To inform the input method about the focus-move event (i.e. input
4032 spot change within the same input context), call this function
4033 with #Minput_focus_move as $KEY.
4036 If $KEY is filtered out, this function returns 1. In that case,
4037 the caller should discard the key. Otherwise, it returns 0, and
4038 the caller should handle the key, for instance, by calling the
4039 function minput_lookup () with the same key. */
4042 @brief ÆþÎÏ¥¡¼¤ò¥Õ¥£¥ë¥¿¤¹¤ë.
4044 ´Ø¿ô minput_filter () ¤ÏÆþÎÏ¥¡¼ $KEY ¤òÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC
4045 ¤Ë±þ¤¸¤Æ¥Õ¥£¥ë¥¿¤·¡¢preedit ¥Æ¥¥¹¥È¡¢¥¹¥Æ¡¼¥¿¥¹¡¢¸½»þÅÀ¤Ç¤Î¸õÊ䤬ÊѲ½¤·¤¿»þÅÀ¤Ç¡¢¤½¤ì¤¾¤ì
4046 #Minput_preedit_draw, #Minput_status_draw,
4047 #Minput_candidates_draw ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¸Æ¤Ö¡£
4050 $KEY ¤¬¥Õ¥£¥ë¥¿¤µ¤ì¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 1 ¤òÊÖ¤¹¡£
4051 ¤³¤Î¾ì¹ç¸Æ¤Ó½Ð¤·Â¦¤Ï¤³¤Î¥¡¼¤ò¼Î¤Æ¤ë¤Ù¤¤Ç¤¢¤ë¡£
4052 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0 ¤òÊÖ¤·¡¢¸Æ¤Ó½Ð¤·Â¦¤Ï¡¢¤¿¤È¤¨¤ÐƱ¤¸¥¡¼¤Ç´Ø¿ô minput_lookup ()
4053 ¤ò¸Æ¤Ö¤Ê¤É¤·¤Æ¡¢¤³¤Î¥¡¼¤ò½èÍý¤¹¤ë¡£
4055 @latexonly \IPAlabel{minput_filter} @endlatexonly
4059 minput_filter (MInputContext *ic, MSymbol key, void *arg)
4066 ret = (*ic->im->driver.filter) (ic, key, arg);
4068 if (ic->im->driver.callback_list)
4070 if (ic->preedit_changed)
4071 minput__callback (ic, Minput_preedit_draw);
4072 if (ic->status_changed)
4073 minput__callback (ic, Minput_status_draw);
4074 if (ic->candidates_changed)
4075 minput__callback (ic, Minput_candidates_draw);
4084 @brief Look up a text produced in the input context.
4086 The minput_lookup () function looks up a text in the input context
4087 $IC. $KEY must be identical to the one that was used in the previous call of
4090 If a text was produced by the input method, it is concatenated
4093 This function calls #MInputDriver::lookup .
4096 If $KEY was correctly handled by the input method, this function
4097 returns 0. Otherwise, it returns -1, even though some text
4098 might be produced in $MT. */
4101 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥ÈÃæ¤Î¥Æ¥¥¹¥È¤òõ¤¹.
4103 ´Ø¿ô minput_lookup () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC Ãæ¤Î¥Æ¥¥¹¥È¤òõ¤¹¡£
4104 $KEY ¤Ï´Ø¿ô minput_filter () ¤Ø¤ÎľÁ°¤Î¸Æ¤Ó½Ð¤·¤ËÍѤ¤¤é¤ì¤¿¤â¤Î¤ÈƱ¤¸¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
4106 ¥Æ¥¥¹¥È¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆÀ¸À®¤µ¤ì¤Æ¤¤¤ì¤Ð¡¢¥Æ¥¥¹¥È¤Ï M-text
4109 ¤³¤Î´Ø¿ô¤Ï¡¢#MInputDriver::lookup ¤ò¸Æ¤Ö¡£
4112 $KEY ¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆŬÀڤ˽èÍý¤Ç¤¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 0 ¤òÊÖ¤¹¡£
4113 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£
4114 ¤³¤Î¾ì¹ç¤Ç¤â $MT ¤Ë²¿¤é¤«¤Î¥Æ¥¥¹¥È¤¬À¸À®¤µ¤ì¤Æ¤¤¤ë¤³¤È¤¬¤¢¤ë¡£
4116 @latexonly \IPAlabel{minput_lookup} @endlatexonly */
4119 minput_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
4121 return (ic ? (*ic->im->driver.lookup) (ic, key, arg, mt) : -1);
4126 @brief Set the spot of the input context.
4128 The minput_set_spot () function sets the spot of input context $IC
4129 to coordinate ($X, $Y ) with the height specified by $ASCENT and $DESCENT .
4130 The semantics of these values depends on the input method driver.
4132 For instance, a driver designed to work in a CUI environment may
4133 use $X and $Y as the column- and row numbers, and may ignore $ASCENT and
4134 $DESCENT . A driver designed to work in a window system may
4135 interpret $X and $Y as the pixel offsets relative to the origin of the
4136 client window, and may interpret $ASCENT and $DESCENT as the ascent- and
4137 descent pixels of the line at ($X . $Y ).
4139 $FONTSIZE specifies the fontsize of preedit text in 1/10 point.
4141 $MT and $POS are the M-text and the character position at the spot.
4142 $MT may be @c NULL, in which case, the input method cannot get
4143 information about the text around the spot. */
4146 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Î¥¹¥Ý¥Ã¥È¤òÀßÄꤹ¤ë.
4148 ´Ø¿ô minput_set_spot () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤Î¥¹¥Ý¥Ã¥È¤ò¡¢ºÂɸ ($X, $Y )
4149 ¤Î°ÌÃÖ¤Ë ¡¢¹â¤µ $ASCENT¡¢ $DESCENT
4150 ¤ÇÀßÄꤹ¤ë¡£ ¤³¤ì¤é¤ÎÃͤΰÕÌ£¤ÏÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë¡£
4152 ¤¿¤È¤¨¤Ð CUI ´Ä¶¤ÇÆ°ºî¤¹¤ë¥É¥é¥¤¥Ð¤Ï $X ¤È $Y
4153 ¤ò¤½¤ì¤¾¤ìÎó¤È¹Ô¤ÎÈÖ¹æ¤È¤·¤ÆÍѤ¤¡¢$ASCENT ¤È $DESCENT
4154 ¤ò̵»ë¤¹¤ë¤«¤â¤·¤ì¤Ê¤¤¡£ ¤Þ¤¿¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥àÍѤΥɥ饤¥Ð¤Ï
4155 $X ¤È $Y ¤ò¥¯¥é¥¤¥¢¥ó¥È¥¦¥£¥ó¥É¥¦¤Î¸¶ÅÀ¤«¤é¤Î¥ª¥Õ¥»¥Ã¥È¤ò¥Ô¥¯¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¤¡¢
4156 $ASCENT ¤È $DESCENT ¤ò ($X . $Y )
4157 ¤ÎÎó¤Î¥¢¥»¥ó¥È¤È¥Ç¥£¥»¥ó¥È¤ò¥Ô¥¯¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¦¤«¤â¤·¤ì¤Ê¤¤¡£
4159 $FONTSIZE ¤Ë¤Ï preedit ¥Æ¥¥¹¥È¤Î¥Õ¥©¥ó¥È¥µ¥¤¥º¤ò 1/10 ¥Ý¥¤¥ó¥Èñ°Ì¤Ç»ØÄꤹ¤ë¡£
4161 $MT ¤È $POS ¤Ï¤½¤Î¥¹¥Ý¥Ã¥È¤Î M-text ¤Èʸ»ú°ÌÃ֤Ǥ¢¤ë¡£$MT ¤Ï @c
4162 NULL ¤Ç¤â¤è¤¯¡¢¤½¤Î¾ì¹ç¤Ë¤ÏÆþÎϥ᥽¥Ã¥É¤Ï¥¹¥Ý¥Ã¥È¼þÊդΥƥ¥¹¥È¤Ë´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë¤³¤È¤¬¤Ç¤¤Ê¤¤¡£
4166 minput_set_spot (MInputContext *ic, int x, int y,
4167 int ascent, int descent, int fontsize,
4172 ic->spot.ascent = ascent;
4173 ic->spot.descent = descent;
4174 ic->spot.fontsize = fontsize;
4177 if (ic->im->driver.callback_list)
4178 minput__callback (ic, Minput_set_spot);
4183 @brief Toggle input method.
4185 The minput_toggle () function toggles the input method associated
4186 with input context $IC. */
4188 @brief ÆþÎϥ᥽¥Ã¥É¤òÀÚÂؤ¨¤ë.
4190 ´Ø¿ô minput_toggle () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC
4191 ¤ËÂбþÉÕ¤±¤é¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ò¥È¥°¥ë¤¹¤ë¡£
4195 minput_toggle (MInputContext *ic)
4197 if (ic->im->driver.callback_list)
4198 minput__callback (ic, Minput_toggle);
4199 ic->active = ! ic->active;
4205 @brief Reset an input context.
4207 The minput_reset_ic () function resets input context $IC by
4208 calling a callback function corresponding to #Minput_reset. It
4209 resets the status of $IC to its initial one. As the
4210 current preedit text is deleted without commitment, if necessary,
4211 call minput_filter () with the arg @r key #Mnil to force the input
4212 method to commit the preedit in advance. */
4215 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤ò¥ê¥»¥Ã¥È¤¹¤ë.
4217 ´Ø¿ô minput_reset_ic () ¤Ï #Minput_reset ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô
4218 ¤ò¸Æ¤Ö¤³¤È¤Ë¤è¤Ã¤ÆÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤ò¥ê¥»¥Ã¥È¤¹¤ë¡£¥ê¥»¥Ã¥È¤È¤Ï¡¢
4219 ¼ÂºÝ¤Ë¤ÏÆþÎϥ᥽¥Ã¥É¤ò½é´ü¾õÂ֤˰ܤ¹¤³¤È¤Ç¤¢¤ë¡£¸½ºßÆþÎÏÃæ¤Î¥Æ¥¥¹
4220 ¥È¤Ï¥³¥ß¥Ã¥È¤µ¤ì¤ë¤³¤È¤Ê¤¯ºï½ü¤µ¤ì¤ë¤Î¤Ç¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é
4221 ¥à¤Ï¡¢É¬Íפʤé¤Ðͽ¤á minput_filter () ¤ò°ú¿ô @r key #Mnil ¤Ç¸Æ¤ó¤Ç
4222 ¶¯À©Åª¤Ë¥×¥ê¥¨¥Ç¥£¥Ã¥È¥Æ¥¥¹¥È¤ò¥³¥ß¥Ã¥È¤µ¤»¤ë¤³¤È¡£ */
4225 minput_reset_ic (MInputContext *ic)
4227 if (ic->im->driver.callback_list)
4228 minput__callback (ic, Minput_reset);
4234 @brief Get title and icon filename of an input method.
4236 The minput_get_title_icon () function returns a plist containing a
4237 title and icon filename (if any) of an input method specified by
4238 $LANGUAGE and $NAME.
4240 The first element of the plist has key #Mtext and the value is an
4241 M-text of the title for identifying the input method. The second
4242 element (if any) has key #Mtext and the value is an M-text of the
4243 icon image (absolute) filename for the same purpose.
4246 If there exists a specified input method and it defines an title,
4247 a plist is returned. Otherwise, NULL is returned. The caller
4248 must free the plist by m17n_object_unref (). */
4251 minput_get_title_icon (MSymbol language, MSymbol name)
4253 MInputMethodInfo *im_info;
4260 im_info = get_im_info (language, name, Mnil, Mtitle);
4261 if (! im_info || !im_info->title)
4263 mt = mtext_get_prop (im_info->title, 0, Mtext);
4265 file = mdatabase__find_file ((char *) MTEXT_DATA (mt));
4268 char *buf = alloca (MSYMBOL_NAMELEN (language) + MSYMBOL_NAMELEN (name)
4271 sprintf (buf, "icons/%s-%s.png", (char *) MSYMBOL_NAME (language),
4272 (char *) MSYMBOL_NAME (name));
4273 file = mdatabase__find_file (buf);
4274 if (! file && language == Mt)
4276 sprintf (buf, "icons/%s.png", (char *) MSYMBOL_NAME (name));
4277 file = mdatabase__find_file (buf);
4282 mplist_add (plist, Mtext, im_info->title);
4285 mt = mtext__from_data (file, strlen (file), MTEXT_FORMAT_UTF_8, 1);
4287 mplist_add (plist, Mtext, mt);
4288 M17N_OBJECT_UNREF (mt);
4296 @brief Get description text of an input method.
4298 The minput_get_description () function returns an M-text that
4299 describes the input method specified by $LANGUAGE and $NAME.
4302 If the specified input method has a description text, a pointer to
4303 #MText is returned. The caller has to free it by m17n_object_unref ().
4304 If the input method does not have a description text, @c NULL is
4307 @brief ÆþÎϥ᥽¥Ã¥É¤ÎÀâÌÀ¥Æ¥¥¹¥È¤òÆÀ¤ë.
4309 ´Ø¿ô minput_get_description () ¤Ï¡¢$LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ»ØÄê
4310 ¤µ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤òÀâÌÀ¤¹¤ë M-text ¤òÊÖ¤¹¡£
4312 @return »ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤¬ÀâÌÀ¤¹¤ë¥Æ¥¥¹¥È¤ò»ý¤Ã¤Æ¤¤¤ì¤Ð¡¢
4313 #MText ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¸Æ¤Ó½Ð¤·Â¦¤Ï¡¢¤½¤ì¤ò m17n_object_unref
4314 () ¤òÍѤ¤¤Æ²òÊü¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ÆþÎϥ᥽¥Ã¥É¤ËÀâÌÀ¥Æ¥¥¹¥È¤¬Ìµ¤±
4315 ¤ì¤Ð@c NULL ¤òÊÖ¤¹¡£ */
4318 minput_get_description (MSymbol language, MSymbol name)
4320 MInputMethodInfo *im_info;
4324 im_info = get_im_info (language, name, Mnil, Mdescription);
4325 if (! im_info || ! im_info->description)
4327 M17N_OBJECT_REF (im_info->description);
4328 return im_info->description;
4332 @brief Get information about input method commands.
4334 The minput_get_commands () function returns information about
4335 input method commands of the input method specified by $LANGUAGE
4336 and $NAME. An input method command is a pseudo key event to which
4337 one or more actual input key sequences are assigned.
4339 There are two kinds of commands, global and local. Global
4340 commands are used by multiple input methods for the same purpose,
4341 and have global key assignments. Local commands are used only by
4342 a specific input method, and have only local key assignments.
4344 Each input method may locally change key assignments for global
4345 commands. The global key assignment for a global command is
4346 effective only when the current input method does not have local
4347 key assignments for that command.
4349 If $NAME is #Mnil, information about global commands is returned.
4350 In this case $LANGUAGE is ignored.
4352 If $NAME is not #Mnil, information about those commands that have
4353 local key assignments in the input method specified by $LANGUAGE
4354 and $NAME is returned.
4357 If no input method commands are found, this function returns @c NULL.
4359 Otherwise, a pointer to a plist is returned. The key of each
4360 element in the plist is a symbol representing a command, and the
4361 value is a plist of the form COMMAND-INFO described below.
4363 The first element of COMMAND-INFO has the key #Mtext, and the
4364 value is an M-text describing the command.
4366 If there are no more elements, that means no key sequences are
4367 assigned to the command. Otherwise, each of the remaining
4368 elements has the key #Mplist, and the value is a plist whose keys are
4369 #Msymbol and values are symbols representing input keys, which are
4370 currently assigned to the command.
4372 As the returned plist is kept in the library, the caller must not
4373 modify nor free it. */
4375 @brief ÆþÎϥ᥽¥Ã¥É¤Î¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë.
4377 ´Ø¿ô minput_get_commands () ¤Ï¡¢ $LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ»ØÄꤵ
4378 ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ÎÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£ÆþÎϥ᥽¥Ã
4379 ¥É¥³¥Þ¥ó¥É¤È¤Ï¡¢µ¿»÷¥¡¼¥¤¥Ù¥ó¥È¤Ç¤¢¤ê¡¢¤½¤ì¤¾¤ì¤Ë£±¤Ä°Ê¾å¤Î¼ÂºÝ¤Î
4380 ÆþÎÏ¥¡¼¥·¡¼¥¯¥¨¥ó¥¹¤¬³ä¤êÅö¤Æ¤é¤ì¤Æ¤¤¤ë¤â¤Î¤ò»Ø¤¹¡£
4382 ¥³¥Þ¥ó¥É¤Ë¤Ï¥°¥í¡¼¥Ð¥ë¤È¥í¡¼¥«¥ë¤Î£²¼ïÎब¤¢¤ë¡£¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É
4383 ¤ÏÊ£¿ô¤ÎÆþÎϥ᥽¥Ã¥É¤Ë¤ª¤¤¤Æ¡¢Æ±¤¸ÌÜŪ¤Ç¡¢¥°¥í¡¼¥Ð¥ë¤Ê¥¡¼³ä¤êÅö¤Æ
4384 ¤ÇÍѤ¤¤é¤ì¤ë¡£¥í¡¼¥«¥ë¥³¥Þ¥ó¥É¤ÏÆÃÄê¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Î¤ß¡¢¥í¡¼¥«¥ë
4385 ¤Ê¥¡¼³äÅö¤Ç»ÈÍѤµ¤ì¤ë¡£
4387 ¸Ä¡¹¤ÎÆþÎϥ᥽¥Ã¥É¤Ï¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É¤Î¥¡¼³äÅö¤òÊѹ¹¤¹¤ë¤³¤È¤â¤Ç
4388 ¤¤ë¡£¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥ÉÍѤΥ°¥í¡¼¥Ð¥ë¥¡¼³ä¤êÅö¤Æ¤Ï¡¢»ÈÍѤ¹¤ëÆþÎÏ
4389 ¥á¥½¥Ã¥É¤Ë¤ª¤¤¤Æ¤½¤Î¥³¥Þ¥ó¥ÉÍÑ¤Î¥í¡¼¥«¥ë¤Ê¥¡¼³äÅö¤¬Â¸ºß¤·¤Ê¤¤¾ì¹ç
4392 $NAME ¤¬ #Mnil ¤Ç¤¢¤ì¤Ð¡¢¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£¤³¤Î
4393 ¾ì¹ç¡¢$LANGUAGE ¤Ï̵»ë¤µ¤ì¤ë¡£
4395 $NAME ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢$LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤ëÆþ
4396 Îϥ᥽¥Ã¥É¤ËÃÖ¤±¤ë¥í¡¼¥«¥ë¤Ê¥¡¼³ä¤êÅö¤Æ¤ò»ý¤Ä¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó
4400 ÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï @c NULL ¤òÊÖ¤¹¡£
4402 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¥ê¥¹¥È¤Î³ÆÍ×ÁǤÎ
4403 ¥¡¼¤Ï¸Ä¡¹¤Î¥³¥Þ¥ó¥É¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢Ãͤϲ¼µ¤Î COMMAND-INFO
4404 ¤Î·Á¼°¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ç¤¢¤ë¡£
4406 COMMAND-INFO ¤ÎÂè°ìÍ×ÁǤΥ¡¼¤Ï #Mtext ¤Þ¤¿¤Ï #Msymbol ¤Ç¤¢¤ë¡£¥¡¼
4407 ¤¬ #Mtext ¤Ê¤é¡¢ÃͤϤ½¤Î¥³¥Þ¥ó¥É¤òÀâÌÀ¤¹¤ë M-text ¤Ç¤¢¤ë¡£¥¡¼¤¬
4408 #Msymbol ¤Ê¤éÃÍ¤Ï #Mnil ¤Ç¤¢¤ê¡¢¤³¤Î¥³¥Þ¥ó¥É¤ÏÀâÌÀ¥Æ¥¥¹¥È¤ò»ý¤¿¤Ê
4411 ¤½¤ì°Ê³°¤ÎÍ×ÁǤ¬Ìµ¤±¤ì¤Ð¡¢¤³¤Î¥³¥Þ¥ó¥É¤ËÂФ·¤Æ¥¡¼¥·¡¼¥¯¥¨¥ó¥¹¤¬³ä
4412 ¤êÅö¤Æ¤é¤ì¤Æ¤¤¤Ê¤¤¤³¤È¤ò°ÕÌ£¤¹¤ë¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢»Ä¤ê¤Î³ÆÍ×ÁǤϥ
4413 ¡¼¤È¤·¤Æ#Mplist ¤ò¡¢ÃͤȤ·¤Æ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ò»ý¤Ä¡£¤³¤Î¥×¥í¥Ñ¥Æ¥£
4414 ¥ê¥¹¥È¤Î¥¡¼¤Ï #Msymbol ¤Ç¤¢¤ê¡¢Ãͤϸ½ºß¤½¤Î¥³¥Þ¥ó¥É¤Ë³ä¤êÅö¤Æ¤é¤ì
4415 ¤Æ¤¤¤ëÆþÎÏ¥¡¼¤òɽ¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
4417 ÊÖ¤µ¤ì¤ë¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ï¥é¥¤¥Ö¥é¥ê¤Ë¤è¤Ã¤Æ´ÉÍý¤µ¤ì¤Æ¤ª¤ê¡¢¸Æ¤Ó½Ð
4418 ¤·Â¦¤ÇÊѹ¹¤·¤¿¤ê²òÊü¤·¤¿¤ê¤·¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£*/
4421 minput_get_commands (MSymbol language, MSymbol name)
4423 MInputMethodInfo *im_info;
4428 im_info = get_im_info (language, name, Mnil, Mcommand);
4429 if (! im_info || ! im_info->configured_vars)
4431 M17N_OBJECT_UNREF (im_info->bc_cmds);
4432 im_info->bc_cmds = mplist ();
4433 MPLIST_DO (cmds, im_info->configured_cmds)
4435 MPlist *plist = MPLIST_PLIST (cmds);
4436 MPlist *elt = mplist ();
4438 mplist_push (im_info->bc_cmds, Mplist, elt);
4439 mplist_add (elt, MPLIST_SYMBOL (plist),
4440 mplist_copy (MPLIST_NEXT (plist)));
4441 M17N_OBJECT_UNREF (elt);
4443 return im_info->bc_cmds;
4447 @brief Assign a key sequence to an input method command (obsolete).
4449 This function is obsolete. Use minput_config_command () instead.
4451 The minput_assign_command_keys () function assigns input key
4452 sequence $KEYSEQ to input method command $COMMAND for the input
4453 method specified by $LANGUAGE and $NAME. If $NAME is #Mnil, the
4454 key sequence is assigned globally no matter what $LANGUAGE is.
4455 Otherwise the key sequence is assigned locally.
4457 Each element of $KEYSEQ must have the key $Msymbol and the value
4458 must be a symbol representing an input key.
4460 $KEYSEQ may be @c NULL, in which case, all assignments are deleted
4461 globally or locally.
4463 This assignment gets effective in a newly opened input method.
4466 If the operation was successful, 0 is returned. Otherwise -1 is
4467 returned, and #merror_code is set to #MERROR_IM. */
4469 @brief ÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤Ë¥¡¼¥·¡¼¥¯¥¨¥ó¥¹¤ò³ä¤êÅö¤Æ¤ë.
4471 ´Ø¿ô minput_assign_command_keys () ¤Ï¡¢ $LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ
4472 »ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥ÉÍѤÎÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É $COMMAND ¤ËÂФ·¤Æ¡¢
4473 ÆþÎÏ¥¡¼¥·¡¼¥¯¥¨¥ó¥¹ $KEYSEQ ¤ò³ä¤êÅö¤Æ¤ë¡£ $NAME ¤¬ #Mnil ¤Ê¤é¤Ð¡¢
4474 $LANGUAGE ¤Ë´Ø·¸¤Ê¤¯¡¢ÆþÎÏ¥¡¼¥·¡¼¥¯¥¨¥ó¥¹¤Ï¥°¥í¡¼¥Ð¥ë¤Ë³ä¤êÅö¤Æ¤é
4475 ¤ì¤ë¡£¤½¤¦¤Ç¤Ê¤ì¤Ð¡¢³ä¤êÅö¤Æ¤Ï¥í¡¼¥«¥ë¤Ç¤¢¤ë¡£
4477 $KEYSEQ ¤Î³ÆÍ×ÁǤϥ¡¼¤È¤·¤Æ $Msymbol ¤ò¡¢ÃͤȤ·¤ÆÆþÎÏ¥¡¼¤òɽ¤¹¥·
4478 ¥ó¥Ü¥ë¤ò»ý¤¿¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
4480 $KEYSEQ ¤Ï @c NULL ¤Ç¤â¤è¤¤¡£¤³¤Î¾ì¹ç¡¢¥°¥í¡¼¥Ð¥ë¤â¤·¤¯¤Ï¥í¡¼¥«¥ë¤Ê
4481 ¤¹¤Ù¤Æ¤Î³ä¤êÅö¤Æ¤¬¾Ãµî¤µ¤ì¤ë¡£
4483 ¤³¤Î³ä¤êÅö¤Æ¤Ï¡¢³ä¤êÅö¤Æ°Ê¹ß¿·¤·¤¯¥ª¡¼¥×¥ó¤µ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤«¤éÍ
4486 @return ½èÍý¤¬À®¸ù¤¹¤ì¤Ð 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤·¡¢
4487 #merror_code ¤ò #MERROR_IM ¤ËÀßÄꤹ¤ë¡£ */
4490 minput_assign_command_keys (MSymbol language, MSymbol name,
4491 MSymbol command, MPlist *keyseq)
4497 if (command == Mnil)
4498 MERROR (MERROR_IM, -1);
4503 if (! check_command_keyseq (keyseq))
4504 MERROR (MERROR_IM, -1);
4506 mplist_add (plist, Mplist, keyseq);
4511 ret = minput_config_command (language, name, command, keyseq);
4512 M17N_OBJECT_UNREF (keyseq);
4517 minput_get_command (MSymbol language, MSymbol name, MSymbol command)
4519 MInputMethodInfo *im_info;
4523 im_info = get_im_info (language, name, Mnil, Mcommand);
4524 if (! im_info || ! im_info->configured_cmds)
4526 if (command == Mnil)
4527 return im_info->configured_cmds;
4528 return mplist__assq (im_info->configured_cmds, command);
4532 /* Return a description of the command COMMAND of the input method
4533 specified by LANGUAGE and NAME. */
4535 get_im_command_help (MSymbol language, MSymbol name, MSymbol command)
4537 MPlist *cmd = minput_get_command (langauge, name, command);
4542 plist = mplist_value (cmds); /* (NAME DESCRIPTION KEY-SEQ ...) */
4543 plist = mplist_next (plist); /* (DESCRIPTION KEY-SEQ ...) */
4544 return (MText *) mplist_value (list);
4549 @brief Configure the key sequence of an input method command.
4551 The minput_config_command () function assigns list of key
4552 sequences $KEYSEQ-LIST to the command $COMMAND for the input
4553 method specified by $LANGUAGE and $NAME.
4555 If $KEYSEQ-LIST is a non-empty plist, it must be a list of key
4556 sequences, and each key sequence must be a plist of key symbols.
4558 If $KEYSEQ is an empty plist, the command become unusable.
4560 If $KEYSEQ is NULL, all configulations of the command for the
4561 input method are canceled, and the default key sequences become
4562 effective. In that case, if $COMMAND is #Mnil, configurations for
4563 all commands of the input method are canceled.
4565 If $NAME is #Mnil, this function configure the global key sequence
4566 assignments, not that of a specific input method.
4568 The configulation (or the cancelling) takes effect instantly for
4569 the current session even for already opened input methods. To
4570 make the configulation take effect for the future session, it must
4571 be saved in a per-user customization file by the function
4572 minput_save_config ().
4575 If the operation was successful, this function returns 0,
4576 otherwise returns -1. The operation fails in these cases:
4578 $KEYSEQ is not in a valid form.
4580 $COMMAND is not available for the input method.
4582 $LANGUAGE and $NAME don't specify an existing input method.
4585 minput_get_commands (), minput_save_config (). */
4588 minput_config_command (MSymbol language, MSymbol name, MSymbol command,
4591 MInputMethodInfo *im_info, *config;
4596 if (keyseq && ! check_command_keyseq (keyseq))
4597 MERROR (MERROR_IM, -1);
4598 im_info = get_im_info (language, name, Mnil, Mcommand);
4600 MERROR (MERROR_IM, -1);
4601 if (command == Mnil)
4604 MERROR (MERROR_IM, -1);
4606 else if (! im_info->cmds
4607 || ! mplist__assq (im_info->cmds, command))
4608 MERROR (MERROR_IM, -1);
4610 config = get_config_info (im_info);
4613 if (! im_config_list)
4614 im_config_list = mplist ();
4615 config = new_im_info (NULL, language, name, Mnil, im_config_list);
4616 config->cmds = mplist ();
4617 config->vars = mplist ();
4620 if (command == Mnil)
4622 MInputMethodInfo *custom = get_custom_info (im_info);
4624 mplist_set (config->cmds, Mnil, NULL);
4625 if (custom && custom->cmds)
4627 MPLIST_DO (plist, custom->cmds)
4629 command = MPLIST_SYMBOL (MPLIST_PLIST (plist));
4631 mplist_add (plist, Msymbol, command);
4632 mplist_push (config->cmds, Mplist, plist);
4633 M17N_OBJECT_UNREF (plist);
4639 plist = mplist__assq (config->cmds, command);
4642 plist = MPLIST_PLIST (plist); /* (NAME DESC KEY-SEQUENCE ...) */
4643 plist = MPLIST_NEXT (plist); /* (DESC ...) */
4644 mplist_set (plist, Mnil, NULL);
4649 mplist_push (config->cmds, Mplist, plist);
4650 M17N_OBJECT_UNREF (plist);
4651 plist = mplist_add (plist, Msymbol, command);
4657 keyseq = mplist_copy (keyseq);
4658 MPLIST_DO (pl, keyseq)
4660 p = mplist_copy (MPLIST_VAL (pl));
4661 mplist_set (pl, Mplist, p);
4662 M17N_OBJECT_UNREF (p);
4664 plist = mplist_add (plist, Msymbol, Mnil);
4665 mplist__conc (plist, keyseq);
4666 M17N_OBJECT_UNREF (keyseq);
4669 config_commands (im_info);
4670 im_info->tick = time (NULL);
4675 /* Add "C-x u" to the "start" command of Unicode input method. */
4677 MSymbol start_command = msymbol ("start");
4678 MSymbol unicode = msymbol ("unicode");
4679 MPlist *cmd, *plist, *key_seq_list, *key_seq;
4681 /* At first get the current key-sequence assignment. */
4682 cmd = mplist_get_command (Mt, unicode, start_command);
4685 /* The input method doesn't have the command "start". Here
4686 comes some error handling code. */
4688 /* Now CMD == ((start DESCRIPTION KEY-SEQUENCE ...) ...). Extract
4689 the part (KEY-SEQUENCE ...). */
4690 plist = mplist_next (mplist_next (mplist_value (cmd)));
4691 /* Copy it because we should not modify it directly. */
4692 key_seq_list = mplist_copy (plist);
4693 m17n_object_unref (cmds);
4695 key_seq = mplist ();
4696 mplist_add (key_seq, Msymbol, msymbol ("C-x"));
4697 mplist_add (key_seq, Msymbo, msymbol ("u"));
4698 mplist_add (key_seq_list, Mplist, key_seq);
4699 m17n_object_unref (key_seq);
4701 minput_config_command (Mt, unicode, start_command, key_seq_list);
4702 m17n_object_unref (key_seq_list);
4707 @brief Get a list of variables of an input method (obsolete).
4709 This function is obsolete. Use minput_get_variable () instead.
4711 The minput_get_variables () function returns a plist (#MPlist) of
4712 variables used to control the behavior of the input method
4713 specified by $LANGUAGE and $NAME. The plist is @e well-formed
4714 (#m17nPlist) of the following format:
4717 (VARNAME (DOC-MTEXT DEFAULT-VALUE [ VALUE ... ] )
4718 VARNAME (DOC-MTEXT DEFAULT-VALUE [ VALUE ... ] )
4722 @c VARNAME is a symbol representing the variable name.
4724 @c DOC-MTEXT is an M-text describing the variable.
4726 @c DEFAULT-VALUE is the default value of the variable. It is a
4727 symbol, integer, or M-text.
4729 @c VALUEs (if any) specifies the possible values of the variable.
4730 If @c DEFAULT-VALUE is an integer, @c VALUE may be a plist (@c FROM
4731 @c TO), where @c FROM and @c TO specifies a range of possible
4734 For instance, suppose an input method has the variables:
4736 @li name:intvar, description:"value is an integer",
4737 initial value:0, value-range:0..3,10,20
4739 @li name:symvar, description:"value is a symbol",
4740 initial value:nil, value-range:a, b, c, nil
4742 @li name:txtvar, description:"value is an M-text",
4743 initial value:empty text, no value-range (i.e. any text)
4745 Then, the returned plist is as follows.
4748 (intvar ("value is an integer" 0 (0 3) 10 20)
4749 symvar ("value is a symbol" nil a b c nil)
4750 txtvar ("value is an M-text" ""))
4754 If the input method uses any variables, a pointer to #MPlist is
4755 returned. As the plist is kept in the library, the caller must not
4756 modify nor free it. If the input method does not use any
4757 variable, @c NULL is returned. */
4759 @brief ÆþÎϥ᥽¥Ã¥É¤ÎÊÑ¿ô¥ê¥¹¥È¤òÆÀ¤ë.
4761 ´Ø¿ô minput_get_variables () ¤Ï¡¢$LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ»ØÄꤵ
4762 ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤Î¿¶¤ëÉñ¤¤¤òÀ©¸æ¤¹¤ëÊÑ¿ô¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È
4763 (#MPlist) ¤òÊÖ¤¹¡£¤³¤Î¥ê¥¹¥È¤Ï @e well-formed ¤Ç¤¢¤ê(#m17nPlist) °Ê
4767 (VARNAME (DOC-MTEXT DEFAULT-VALUE [ VALUE ... ] )
4768 VARNAME (DOC-MTEXT DEFAULT-VALUE [ VALUE ... ] )
4772 @c VARNAME ¤ÏÊÑ¿ô¤Î̾Á°¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
4774 @c DOC-MTEXT ¤ÏÊÑ¿ô¤òÀâÌÀ¤¹¤ë M-text ¤Ç¤¢¤ë¡£
4776 @c DEFAULT-VALUE ¤ÏÊÑ¿ô¤Î¥Ç¥Õ¥©¥ë¥ÈÃͤǤ¢¤ê¡¢¥·¥ó¥Ü¥ë¡¢À°¿ô¤â¤·¤¯¤Ï
4779 @c VALUE ¤Ï¡¢¤â¤·»ØÄꤵ¤ì¤Æ¤¤¤ì¤ÐÊÑ¿ô¤Î¼è¤êÆÀ¤ëÃͤò¼¨¤¹¡£¤â¤·
4780 @c DEFAULT-VALUE ¤¬À°¿ô¤Ê¤é¡¢ @c VALUE ¤Ï (@c FROM @c TO) ¤È¤¤¤¦·Á
4781 ¤Î¥ê¥¹¥È¤Ç¤âÎɤ¤¡£¤³¤Î¾ì¹ç @c FROM ¤È @c TO ¤Ï²Äǽ¤ÊÃͤÎÈϰϤò¼¨¤¹¡£
4783 Îã¤È¤·¤Æ¡¢¤¢¤ëÆþÎϥ᥽¥Ã¥É¤¬¼¡¤Î¤è¤¦¤ÊÊÑ¿ô¤ò»ý¤Ä¾ì¹ç¤ò¹Í¤¨¤è¤¦¡£
4785 @li name:intvar, ÀâÌÀ:"value is an integer",
4786 ½é´üÃÍ:0, ÃͤÎÈÏ°Ï:0..3,10,20
4788 @li name:symvar, ÀâÌÀ:"value is a symbol",
4789 ½é´üÃÍ:nil, ÃͤÎÈÏ°Ï:a, b, c, nil
4791 @li name:txtvar, ÀâÌÀ:"value is an M-text",
4792 ½é´üÃÍ:empty text, ÃͤÎÈϰϤʤ·(¤É¤ó¤Ê M-text ¤Ç¤â²Ä)
4794 ¤³¤Î¾ì¹ç¡¢ÊÖ¤µ¤ì¤ë¥ê¥¹¥È¤Ï°Ê²¼¤Î¤è¤¦¤Ë¤Ê¤ë¡£
4797 (intvar ("value is an integer" 0 (0 3) 10 20)
4798 symvar ("value is a symbol" nil a b c nil)
4799 txtvar ("value is an M-text" ""))
4803 ÆþÎϥ᥽¥Ã¥É¤¬²¿¤é¤«¤ÎÊÑ¿ô¤ò»ÈÍѤ·¤Æ¤¤¤ì¤Ð #MPlist ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
4804 ÊÖ¤µ¤ì¤ë¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ï¥é¥¤¥Ö¥é¥ê¤Ë¤è¤Ã¤Æ´ÉÍý¤µ¤ì¤Æ¤ª¤ê¡¢¸Æ¤Ó½Ð¤·Â¦¤ÇÊѹ¹¤·¤¿¤ê²òÊü¤·¤¿¤ê¤·¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
4805 ÆþÎϥ᥽¥Ã¥É¤¬ÊÑ¿ô¤ò°ìÀÚ»ÈÍѤ·¤Æ¤Ê¤±¤ì¤Ð¡¢@c NULL ¤òÊÖ¤¹¡£ */
4808 minput_get_variables (MSymbol language, MSymbol name)
4810 MInputMethodInfo *im_info;
4815 im_info = get_im_info (language, name, Mnil, Mvariable);
4816 if (! im_info || ! im_info->configured_vars)
4819 M17N_OBJECT_UNREF (im_info->bc_vars);
4820 im_info->bc_vars = mplist ();
4821 MPLIST_DO (vars, im_info->configured_vars)
4823 MPlist *plist = MPLIST_PLIST (vars);
4824 MPlist *elt = mplist ();
4826 mplist_push (im_info->bc_vars, Mplist, elt);
4827 mplist_add (elt, Msymbol, MPLIST_SYMBOL (plist));
4828 elt = MPLIST_NEXT (elt);
4829 mplist_set (elt, Mplist, mplist_copy (MPLIST_NEXT (plist)));
4830 M17N_OBJECT_UNREF (elt);
4832 return im_info->bc_vars;
4836 @brief Set the initial value of an input method variable.
4838 The minput_set_variable () function sets the initial value of
4839 input method variable $VARIABLE to $VALUE for the input method
4840 specified by $LANGUAGE and $NAME.
4842 By default, the initial value is 0.
4844 This setting gets effective in a newly opened input method.
4847 If the operation was successful, 0 is returned. Otherwise -1 is
4848 returned, and #merror_code is set to #MERROR_IM. */
4850 @brief ÆþÎϥ᥽¥Ã¥ÉÊÑ¿ô¤Î½é´üÃͤòÀßÄꤹ¤ë.
4852 ´Ø¿ô minput_set_variable () ¤Ï¡¢$LANGUAGE ¤È $NAME
4853 ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ÎÆþÎϥ᥽¥Ã¥ÉÊÑ¿ô $VARIABLE
4854 ¤Î½é´üÃͤò¡¢ $VALUE ¤ËÀßÄꤹ¤ë¡£
4856 ¥Ç¥Õ¥©¥ë¥È¤Î½é´üÃÍ¤Ï 0 ¤Ç¤¢¤ë¡£
4858 ¤³¤ÎÀßÄê¤Ï¡¢¿·¤·¤¯¥ª¡¼¥×¥ó¤µ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤«¤é͸ú¤È¤Ê¤ë¡£
4861 ½èÍý¤¬À®¸ù¤¹¤ì¤Ð 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤·¡¢
4862 #merror_code ¤ò #MERROR_IM ¤ËÀßÄꤹ¤ë¡£ */
4865 minput_set_variable (MSymbol language, MSymbol name,
4866 MSymbol variable, void *value)
4869 MInputMethodInfo *im_info;
4874 if (variable == Mnil)
4875 MERROR (MERROR_IM, -1);
4876 plist = minput_get_variable (language, name, variable);
4877 plist = MPLIST_PLIST (plist);
4878 plist = MPLIST_NEXT (plist);
4880 mplist_add (pl, MPLIST_KEY (plist), value);
4881 ret = minput_config_variable (language, name, variable, pl);
4882 M17N_OBJECT_UNREF (pl);
4885 im_info = get_im_info (language, name, Mnil, Mvariable);
4892 minput_get_variable (MSymbol language, MSymbol name, MSymbol variable)
4894 MInputMethodInfo *im_info;
4898 im_info = get_im_info (language, name, Mnil, Mvariable);
4899 if (! im_info || ! im_info->configured_vars)
4901 if (variable == Mnil)
4902 return im_info->configured_vars;
4903 return mplist__assq (im_info->configured_vars, variable);
4907 @brief Configure the value of an input method variable.
4909 The minput_config_variable () function assigns the value $VALUE to
4910 the variable $VARIABLE of the input method specified by $LANGUAGE
4913 If $VALUE is not NULL, it must be a plist of one element whose key
4914 is #Minteger, #Msymbol, or #Mtext, and the value is of the
4917 If $VALUE is NULL, configurations for the variable done in the
4918 current session are canceled (except for what saved by
4919 minput_save_config ()). In that case, if $VARIABLE is #Mnil,
4920 configurations for all variables are canceled.
4922 If $NAME is #Mnil, this function configure the global value, not
4923 that of a specific input method.
4925 The configulation takes effect instantly for the current session
4926 even for already opened input methods. To make the configulation
4927 take effect for the future session, it must be saved in a per-user
4928 customization file by the function minput_save_config ().
4930 @return If the operation was successful, this function returns 0,
4931 otherwise returns -1. The operation fails in these cases:
4933 $VALUE is not in a valid form, or the type doesn't much the
4936 $VARIABLE is not available for the input method.
4938 $LANGUAGE and $NAME don't specify an existing input method.
4941 minput_get_variables (), minput_save_config (). */
4944 minput_config_variable (MSymbol language, MSymbol name, MSymbol variable,
4947 MInputMethodInfo *im_info, *config;
4952 im_info = get_im_info (language, name, Mnil, Mvariable);
4954 MERROR (MERROR_IM, -1);
4955 if (variable == Mnil)
4958 MERROR (MERROR_IM, -1);
4960 else if (! im_info->vars
4961 || ! mplist__assq (im_info->vars, variable))
4962 MERROR (MERROR_IM, -1);
4964 config = get_config_info (im_info);
4967 if (! im_config_list)
4968 im_config_list = mplist ();
4969 config = new_im_info (NULL, language, name, Mnil, im_config_list);
4970 config->cmds = mplist ();
4971 config->vars = mplist ();
4974 if (variable == Mnil)
4976 MInputMethodInfo *custom = get_custom_info (im_info);
4978 mplist_set (config->vars, Mnil, NULL);
4979 if (custom && custom->cmds)
4981 MPLIST_DO (plist, custom->vars)
4983 variable = MPLIST_SYMBOL (MPLIST_PLIST (plist));
4985 mplist_add (plist, Msymbol, variable);
4986 mplist_push (config->vars, Mplist, plist);
4987 M17N_OBJECT_UNREF (plist);
4993 plist = mplist__assq (config->vars, variable);
4996 plist = MPLIST_PLIST (plist); /* (NAME DESC VALUE) */
4997 plist = MPLIST_NEXT (plist); /* (DESC VALUE) */
4998 mplist_set (plist, Mnil ,NULL);
5003 mplist_add (config->vars, Mplist, plist);
5004 M17N_OBJECT_UNREF (plist);
5005 plist = mplist_add (plist, Msymbol, variable);
5009 plist = mplist_add (plist, Msymbol, Mnil);
5010 plist = MPLIST_NEXT (plist);
5011 mplist_set (plist, MPLIST_KEY (value), MPLIST_VAL (value));
5014 config_variables (im_info);
5015 im_info->tick = time (NULL);
5020 minput_config_file ()
5023 return mdatabase__file (im_custom_mdb);
5027 minput_save_config (void)
5029 MPlist *data, *tail, *plist, *p, *elt;
5033 ret = mdatabase__lock (im_custom_mdb);
5036 if (! im_config_list)
5038 update_custom_info ();
5039 if (! im_custom_list)
5040 im_custom_list = mplist ();
5041 data = tail = mplist ();
5043 MPLIST_DO (plist, im_config_list)
5045 MPlist *pl = MPLIST_PLIST (plist);
5046 MSymbol language, name, extra, command, variable;
5047 MInputMethodInfo *custom, *config;
5049 language = MPLIST_SYMBOL (pl);
5050 pl = MPLIST_NEXT (pl);
5051 name = MPLIST_SYMBOL (pl);
5052 pl = MPLIST_NEXT (pl);
5053 extra = MPLIST_SYMBOL (pl);
5054 pl = MPLIST_NEXT (pl);
5055 config = MPLIST_VAL (pl);
5056 custom = get_custom_info (config);
5058 custom = new_im_info (NULL, language, name, extra, im_custom_list);
5060 MPLIST_DO (pl, config->cmds)
5062 elt = MPLIST_PLIST (pl);
5063 command = MPLIST_SYMBOL (elt);
5065 p = mplist__assq (custom->cmds, command);
5067 custom->cmds = mplist (), p = NULL;
5068 elt = MPLIST_NEXT (elt);
5069 if (MPLIST_TAIL_P (elt))
5072 mplist__pop_unref (p);
5076 elt = MPLIST_NEXT (elt);
5079 p = MPLIST_NEXT (MPLIST_NEXT (MPLIST_PLIST (p)));
5080 mplist_set (p, Mnil, NULL);
5081 mplist__conc (p, elt);
5085 p = MPLIST_PLIST (pl);
5086 mplist_add (custom->cmds, Mplist, p);
5091 MPLIST_DO (pl, config->vars)
5093 elt = MPLIST_PLIST (pl);
5094 variable = MPLIST_SYMBOL (elt);
5096 p = mplist__assq (custom->vars, variable);
5098 custom->vars = mplist (), p = NULL;
5099 elt = MPLIST_NEXT (elt);
5100 if (MPLIST_TAIL_P (elt))
5103 mplist__pop_unref (p);
5107 elt = MPLIST_NEXT (elt);
5110 p = MPLIST_NEXT (MPLIST_NEXT (MPLIST_PLIST (p)));
5111 mplist_set (p, Mnil, NULL);
5112 mplist__conc (p, elt);
5116 p = MPLIST_PLIST (pl);
5117 mplist_add (custom->vars, Mplist, p);
5122 M17N_OBJECT_UNREF (im_config_list);
5124 MPLIST_DO (plist, im_custom_list)
5126 MPlist *pl = MPLIST_PLIST (plist);
5127 MSymbol language, name, extra;
5128 MInputMethodInfo *custom;
5130 language = MPLIST_SYMBOL (pl);
5131 pl = MPLIST_NEXT (pl);
5132 name = MPLIST_SYMBOL (pl);
5133 pl = MPLIST_NEXT (pl);
5134 extra = MPLIST_SYMBOL (pl);
5135 pl = MPLIST_NEXT (pl);
5136 custom = MPLIST_VAL (pl);
5139 tail = mplist_add (tail, Mplist, elt);
5140 M17N_OBJECT_UNREF (elt);
5142 elt = mplist_add (elt, Mplist, pl);
5143 M17N_OBJECT_UNREF (pl);
5144 pl = mplist_add (pl, Msymbol, Minput_method);
5145 pl = mplist_add (pl, Msymbol, language);
5146 pl = mplist_add (pl, Msymbol, name);
5148 pl = mplist_add (pl, Msymbol, extra);
5149 if (custom->cmds && ! MPLIST_TAIL_P (custom->cmds))
5152 elt = mplist_add (elt, Mplist, pl);
5153 M17N_OBJECT_UNREF (pl);
5154 pl = mplist_add (pl, Msymbol, Mcommand);
5155 MPLIST_DO (p, custom->cmds)
5156 pl = mplist_add (pl, Mplist, MPLIST_PLIST (p));
5158 if (custom->vars && ! MPLIST_TAIL_P (custom->vars))
5161 elt = mplist_add (elt, Mplist, pl);
5162 M17N_OBJECT_UNREF (pl);
5163 pl = mplist_add (pl, Msymbol, Mvariable);
5164 MPLIST_DO (p, custom->vars)
5165 pl = mplist_add (pl, Mplist, MPLIST_PLIST (p));
5169 mplist_push (data, Msymbol, msymbol (";;-*-lisp-*-"));
5170 ret = mdatabase__save (im_custom_mdb, data);
5171 M17N_OBJECT_UNREF (data);
5172 mdatabase__unlock (im_custom_mdb);
5173 return (ret < 0 ? -1 : 1);
5179 /*** @addtogroup m17nDebug */
5185 @brief Dump an input method.
5187 The mdebug_dump_im () function prints the input method $IM in a
5188 human readable way to the stderr. $INDENT specifies how many
5189 columns to indent the lines but the first one.
5192 This function returns $IM. */
5194 @brief ÆþÎϥ᥽¥Ã¥É¤ò¥À¥ó¥×¤¹¤ë.
5196 ´Ø¿ô mdebug_dump_im () ¤ÏÆþÎϥ᥽¥Ã¥É $IM ¤ò stderr
5197 ¤Ë¿Í´Ö¤Ë²ÄÆɤʷÁ¤Ç°õºþ¤¹¤ë¡£$INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£
5200 ¤³¤Î´Ø¿ô¤Ï $IM ¤òÊÖ¤¹¡£ */
5203 mdebug_dump_im (MInputMethod *im, int indent)
5205 MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
5208 prefix = (char *) alloca (indent + 1);
5209 memset (prefix, 32, indent);
5210 prefix[indent] = '\0';
5212 fprintf (stderr, "(input-method %s %s ", msymbol_name (im->language),
5213 msymbol_name (im->name));
5214 mdebug_dump_mtext (im_info->title, 0, 0);
5215 if (im->name != Mnil)
5219 MPLIST_DO (state, im_info->states)
5221 fprintf (stderr, "\n%s ", prefix);
5222 dump_im_state (MPLIST_VAL (state), indent + 2);
5225 fprintf (stderr, ")");