1 /* input.c -- input method module.
2 Copyright (C) 2003, 2004, 2005
3 National Institute of Advanced Industrial Science and Technology (AIST)
4 Registration Number H15PRO112
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 a input method driver of the
30 input method. An input method driver is a set of functions for
31 handling the input method. There are two kinds of input methods;
32 internal one and foreign one.
35 <li> Internal Input Method
37 An internal input method has non @c Mnil LANGUAGE, and the body is
38 defined in the m17n database by the tag <Minput_method, LANGUAGE,
39 NAME>. For this kind of input methods, the m17n library uses two
40 predefined input method drivers, one for CUI use and the other for
41 GUI use. Those driver utilize the input processing engine
42 provided by the m17n library itself. The m17n database may
43 provides an input method that is not only for a specific language.
44 The database uses @c Mt as LANGUAGE of such an input method.
46 An internal input method accepts an input key which is a symbol
47 associated with an input event. As there is no way for the @c
48 m17n @c library to know how input events are represented in an
49 application program, an application programmer have to convert an
50 input event to an input key by himself. See the documentation of
51 the function minput_event_to_key () for the detail.
53 <li> Foreign Input Method
55 A foreign input method has @c Mnil LANGUAGE, and the body is
56 defined in an external resources (e.g. XIM of X Window System).
57 For this kind of input methods, the symbol NAME must have a
58 property of key @c Minput_driver, and the value must be a pointer
59 to an input method driver. Therefore, by preparing a proper
60 driver, any kind of input method can be treated in the framework
61 of the @c m17n @c library.
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 °Ê³°¤Î¤â¤Î¤Ç¤¢¤ê¡¢¤½¤ÎËÜÂΤÏm17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë
95 <Minput_method, LANGUAGE, NAME>
96 ¤È¤¤¤¦¥¿¥°¤òÉÕ¤±¤ÆÄêµÁ¤µ¤ì¤Æ¤¤¤ë¡£
97 ¤³¤Î¼ï¤ÎÆþÎϥ᥽¥Ã¥É¤ËÂФ·¤Æ¡¢m17n ¥é¥¤¥Ö¥é¥ê¤Ç¤Ï
98 CUI ÍÑ¤È GUI ÍѤ½¤ì¤¾¤ì¤ÎÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤ò¤¢¤é¤«¤¸¤áÄêµÁ¤·¤Æ¤¤¤ë¡£
99 ¤³¤ì¤é¤Î¥É¥é¥¤¥Ð¤Ï m17n ¥é¥¤¥Ö¥é¥ê¼«ÂΤÎÆþÎϽèÍý¥¨¥ó¥¸¥ó¤òÍøÍѤ¹¤ë¡£
100 m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë¤Ï¡¢ÆÃÄê¤Î¸À¸ìÀìÍѤǤʤ¤ÆþÎϥ᥽¥Ã¥É¤òÄêµÁ¤¹¤ë¤³¤È¤â¤Ç¤¡¢
101 ¤½¤Î¤è¤¦¤ÊÆþÎϥ᥽¥Ã¥É¤Î LANGUAGE ¤Ï @c Mt ¤Ç¤¢¤ë¡£
103 ÆâÉôÆþÎϥ᥽¥Ã¥É¤Ï¡¢¥æ¡¼¥¶¤ÎÆþÎÏ¥¤¥Ù¥ó¥È¤ËÂбþ¤·¤¿¥·¥ó¥Ü¥ë¤Ç¤¢¤ëÆþÎÏ¥¡¼¤ò¼õ¤±¼è¤ë¡£
104 @c m17n @c ¥é¥¤¥Ö¥é¥ê ¤ÏÆþÎÏ¥¤¥Ù¥ó¥È¤¬¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ç¤É¤¦É½¸½¤µ¤ì¤Æ¤¤¤ë¤«¤òÃΤ뤳¤È¤¬¤Ç¤¤Ê¤¤¤Î¤Ç¡¢
105 ÆþÎÏ¥¤¥Ù¥ó¥È¤«¤éÆþÎÏ¥¡¼¤Ø¤ÎÊÑ´¹¤Ï¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥Þ¤ÎÀÕǤ¤Ç¹Ô¤ï¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
106 ¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï´Ø¿ô minput_event_to_key () ¤ÎÀâÌÀ¤ò»²¾È¡£
108 <li> ³°ÉôÆþÎϥ᥽¥Ã¥É
110 ³°ÉôÆþÎϥ᥽¥Ã¥É¤È¤Ï LANGUAGE ¤¬ @c Mnil ¤Î¤â¤Î¤Ç¤¢¤ê¡¢¤½¤ÎËÜÂΤϳ°Éô¤Î¥ê¥½¡¼¥¹¤È¤·¤ÆÄêµÁ¤µ¤ì¤ë¡£
111 ¡Ê¤¿¤È¤¨¤ÐX Window System ¤ÎXIM ¤Ê¤É¡£)
112 ¤³¤Î¼ï¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢¥·¥ó¥Ü¥ë NAME ¤Ï@c Minput_driver
113 ¤ò¥¡¼¤È¤¹¤ë¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Á¡¢¤½¤ÎÃͤÏÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£
114 ¤³¤Î¤³¤È¤Ë¤è¤ê¡¢Å¬Àڤʥɥ饤¥Ð¤ò½àÈ÷¤¹¤ë¤³¤È¤Ë¤è¤Ã¤Æ¡¢¤¤¤«¤Ê¤ë¼ïÎà¤ÎÆþÎϥ᥽¥Ã¥É¤â
115 @c m17n @c ¥é¥¤¥Ö¥é¥ê ¤ÎÏÈÁȤÎÃæ¤Ç°·¤¦»ö¤¬¤Ç¤¤ë¡£
117 ÍøÊØÀ¤Î´ÑÅÀ¤«¤é¡¢m17n X ¥é¥¤¥Ö¥é¥ê¤Ï XIM ¤Î OverTheSpot
118 ¤ÎÆþÎÏ¥¹¥¿¥¤¥ë¤ò¼Â¸½¤¹¤ëÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤òÄ󶡤·¡¢¤Þ¤¿¥·¥ó¥Ü¥ë @c Mxim ¤Î
119 @c Minput_driver ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤȤ·¤Æ¤½¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÝ»ý¤·¤Æ¤¤¤ë¡£
120 ¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï m17n GUI API ¤Î¥É¥¥å¥á¥ó¥È¤ò»²¾È¤Î¤³¤È¡£
126 ÆþÎϥ᥽¥Ã¥É½èÍý¤Îŵ·¿Åª¤Ê½èÍý¤Ï°Ê²¼¤Î¤è¤¦¤Ë¤Ê¤ë¡£
128 @li ÆþÎϥ᥽¥Ã¥É¤Î¥ª¡¼¥×¥ó
129 @li ¤½¤ÎÆþÎϥ᥽¥Ã¥É¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤ÎÀ¸À®
130 @li ÆþÎÏ¥¤¥Ù¥ó¥È¤Î¥Õ¥£¥ë¥¿
131 @li ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ç¤ÎÀ¸À®¥Æ¥¥¹¥È¤Î¸¡º÷ */
135 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
136 /*** @addtogroup m17nInternal
142 #include <sys/types.h>
144 #include <sys/stat.h>
153 #include "m17n-gui.h"
154 #include "m17n-misc.h"
155 #include "internal.h"
160 #include "database.h"
163 static int mdebug_mask = MDEBUG_INPUT;
165 static MSymbol Minput_method;
167 /** Symbols to load an input method data. */
168 static MSymbol Mtitle, Mmacro, Mmodule, Mstate, Minclude;
170 /** Symbols for actions. */
171 static MSymbol Minsert, Mdelete, Mmark, Mmove, Mpushback, Mundo, Mcall, Mshift;
172 static MSymbol Mselect, Mshow, Mhide, Mcommit, Munhandle;
173 static MSymbol Mset, Madd, Msub, Mmul, Mdiv, Mequal, Mless, Mgreater;
174 static MSymbol Mless_equal, Mgreater_equal;
175 static MSymbol Mcond;
176 static MSymbol Mplus, Mminus, Mstar, Mslush, Mand, Mor, Mnot;
178 static MSymbol M_candidates;
180 static MSymbol Mcandidate_list, Mcandidate_index;
182 static MSymbol Minit, Mfini;
184 /** Symbols for variables. */
185 static MSymbol Mcandidates_group_size, Mcandidates_charset;
187 /** Symbols for key events. */
188 static MSymbol one_char_symbol[256];
190 static MSymbol M_key_alias;
192 static MSymbol M_description, M_command, M_variable;
194 /** Structure to hold a map. */
198 /** List of actions to take when we reach the map. In a root map,
199 the actions are executed only when there's no more key. */
202 /** List of deeper maps. If NULL, this is a terminal map. */
205 /** List of actions to take when we leave the map successfully. In
206 a root map, the actions are executed only when none of submaps
207 handle the current key. */
208 MPlist *branch_actions;
211 typedef MPlist *(*MIMExternalFunc) (MPlist *plist);
216 MPlist *func_list; /* function name vs (MIMExternalFunc *) */
223 /** Name of the state. */
226 /** Title of the state, or NULL. */
229 /** Key translation map of the state. Built by merging all maps of
234 /* Lookup keys KEY1,2,3 in the nested plist PLIST, and return the
238 lookup_nested_list (MPlist *plist, MSymbol key1, MSymbol key2, MSymbol key3)
243 key[0] = key1, key[1] = key2, key[2] = key3;
244 for (i = 0; i < 3; i++)
246 plist = mplist_find_by_value (plist, key[i]);
249 plist = MPLIST_NEXT (plist);
250 plist = MPLIST_PLIST (plist);
255 /* Set VAL for keys KEY1,2,3 in the nested plist PLIST. */
258 set_nested_list (MPlist *plist, MSymbol key1, MSymbol key2, MSymbol key3,
265 key[0] = key1, key[1] = key2, key[2] = key3;
266 for (i = 0; i < 3; i++)
268 pl = mplist_find_by_value (plist, key[i]);
271 pl = MPLIST_NEXT (pl);
272 plist = MPLIST_PLIST (pl);
276 pl = mplist_add (plist, Msymbol, key[i]);
278 pl = mplist_add (pl, Mplist, plist);
279 M17N_OBJECT_UNREF (plist);
282 mplist_set (pl, Mplist, val);
283 M17N_OBJECT_UNREF (val);
287 /* Parse PLIST as a value of nested list and return an adjusted list.
292 [ mtext:DESCRIPTION | symbol:nil ]
293 ;; The remaining elements are checked CHECK_FUNC.
296 [ mtext:DESCRIPTION | symbol:nil ]
297 ;; The remaining elements are checked CHECK_FUNC.
301 GLOBAL is a global list. If a description text is missing, it is
302 extracted from GLOBAL.
304 The return value is a plist of this format:
306 plist:([ mtext:DESCRIPTION | symbol:nil ]
309 plist:([ mtext:DESCRIPTION | symbol:nil ]
313 PLIST itself is unref-ed. */
316 parse_nested_list_value (MPlist *plist, MPlist *global, MSymbol key,
317 int (*check_func) (MPlist *))
319 MPlist *val, *pl, *p, *p0;
322 if (! MPLIST_PLIST_P (plist))
324 M17N_OBJECT_UNREF (plist);
327 pl = MPLIST_PLIST (plist);
328 if (! MPLIST_SYMBOL_P (pl)
329 || MPLIST_SYMBOL (pl) != key)
331 M17N_OBJECT_UNREF (plist);
335 MPLIST_DO (pl, MPLIST_NEXT (pl))
338 MPlist *global_def = NULL;
340 if (! MPLIST_PLIST_P (pl))
342 p = MPLIST_PLIST (pl);
343 if (! MPLIST_SYMBOL_P (p))
345 name = MPLIST_SYMBOL (p);
347 if (MPLIST_TAIL_P (p))
351 global_def = mplist_find_by_value (global, name);
354 global_def = MPLIST_PLIST (MPLIST_NEXT (global_def));
355 mplist__conc (p, global_def);
357 p0 = MPLIST_NEXT (p);
358 if (MPLIST_TAIL_P (p0))
360 if (! global || global_def)
362 global_def = mplist_find_by_value (global, name);
365 global_def = MPLIST_PLIST (MPLIST_NEXT (global_def));
366 global_def = MPLIST_NEXT (global_def);
367 if (MPLIST_TAIL_P (global_def))
369 mplist__conc (p0, global_def);
371 if ((*check_func) (p0) < 0)
373 mplist_add (val, Msymbol, name);
374 mplist_add (val, Mplist, p);
377 M17N_OBJECT_UNREF (plist);
381 static MPlist *variable_list, *command_list;
382 static int check_variable_list (MPlist *plist);
383 static int check_command_list (MPlist *plist);
384 static MPlist *load_partial_im_info (MSymbol language, MSymbol name,
385 MSymbol extra, MSymbol key);
388 get_nested_list (MSymbol language, MSymbol name, MSymbol extra, MSymbol key)
391 int (*check_func) (MPlist *);
392 MPlist *plist, *global;
394 if (key == M_variable)
397 variable_list = mplist ();
398 total_list = variable_list;
399 check_func = check_variable_list;
404 command_list = mplist ();
405 total_list = command_list;
406 check_func = check_command_list;
409 if (MPLIST_TAIL_P (total_list))
411 plist = load_partial_im_info (Mt, Mnil, key, key);
413 global = parse_nested_list_value (plist, NULL, key, check_func);
416 set_nested_list (total_list, Mt, Mnil, key, global);
419 global = lookup_nested_list (total_list, Mt, Mnil, key);
424 plist = lookup_nested_list (total_list, language, name, extra);
428 plist = load_partial_im_info (language, name, extra, key);
430 plist = parse_nested_list_value (plist, global, key, check_func);
433 set_nested_list (total_list, language, name, extra, plist);
438 marker_code (MSymbol sym)
444 name = MSYMBOL_NAME (sym);
445 return ((name[0] == '@'
446 && ((name[1] >= '0' && name[1] <= '9')
447 || name[1] == '<' || name[1] == '>'
448 || name[1] == '=' || name[1] == '+' || name[1] == '-'
449 || name[1] == '[' || name[1] == ']'
457 resolve_variable (MInputContextInfo *ic_info, MSymbol var)
461 MPLIST_DO (p, ic_info->vars)
463 if (MPLIST_SYMBOL (p) == var)
467 if (MPLIST_TAIL_P (p))
470 mplist_push (p, Minteger, (void *) 0);
471 mplist_push (p, Msymbol, var);
473 return (MPLIST_NEXT (p));
477 get_surrounding_text (MInputContext *ic, int len)
481 mplist_push (ic->plist, Minteger, (void *) len);
482 minput__callback (ic, Minput_get_surrounding_text);
483 if (MPLIST_MTEXT_P (ic->plist))
485 mt = MPLIST_MTEXT (ic->plist);
486 mplist_pop (ic->plist);
492 delete_surrounding_text (MInputContext *ic, int pos)
494 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
496 mplist_push (ic->plist, Minteger, (void *) pos);
497 minput__callback (ic, Minput_delete_surrounding_text);
498 mplist_pop (ic->plist);
500 M17N_OBJECT_UNREF (ic_info->preceding_text);
502 M17N_OBJECT_UNREF (ic_info->following_text);
506 get_preceding_char (MInputContext *ic, int pos)
508 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
512 if (ic_info->preceding_text)
514 len = mtext_nchars (ic_info->preceding_text);
516 return mtext_ref_char (ic_info->preceding_text, len - pos);
518 mt = get_surrounding_text (ic, - pos);
521 len = mtext_nchars (mt);
522 if (ic_info->preceding_text)
524 if (mtext_nchars (ic_info->preceding_text) < len)
526 M17N_OBJECT_UNREF (ic_info->preceding_text);
527 ic_info->preceding_text = mt;
531 ic_info->preceding_text = mt;
534 return mtext_ref_char (ic_info->preceding_text, len - pos);
538 get_following_char (MInputContext *ic, int pos)
540 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
544 if (ic_info->following_text)
546 len = mtext_nchars (ic_info->following_text);
548 return mtext_ref_char (ic_info->following_text, pos - 1);
550 mt = get_surrounding_text (ic, pos);
553 len = mtext_nchars (mt);
554 if (ic_info->following_text)
556 if (mtext_nchars (ic_info->following_text) < len)
558 M17N_OBJECT_UNREF (ic_info->following_text);
559 ic_info->following_text = mt;
563 ic_info->following_text = mt;
566 return mtext_ref_char (ic_info->following_text, pos - 1);
570 surrounding_pos (MSymbol sym)
576 name = MSYMBOL_NAME (sym);
577 if ((name[1] == '-' || name[1] == '+')
578 && name[2] >= '1' && name[2] <= '9')
579 return (name[1] == '-' ? - atoi (name + 2) : atoi (name + 2));
584 integer_value (MInputContext *ic, MPlist *arg, MPlist **value, int surrounding)
586 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
588 MText *preedit = ic->preedit;
589 int len = mtext_nchars (preedit);
593 if (MPLIST_INTEGER_P (arg))
594 return MPLIST_INTEGER (arg);
596 && (surrounding = surrounding_pos (MPLIST_SYMBOL (arg))) != 0)
597 return (surrounding < 0
598 ? get_preceding_char (ic, - surrounding)
599 : get_following_char (ic, surrounding));
600 code = marker_code (MPLIST_SYMBOL (arg));
603 MPlist *val = resolve_variable (ic_info, MPLIST_SYMBOL (arg));
607 return (MPLIST_INTEGER_P (val) ? MPLIST_INTEGER (val) : 0);
610 return ic_info->key_head;
611 if (code >= '0' && code <= '9')
613 else if (code == '=')
614 code = ic->cursor_pos;
615 else if (code == '-' || code == '[')
616 code = ic->cursor_pos - 1;
617 else if (code == '+' || code == ']')
618 code = ic->cursor_pos + 1;
619 else if (code == '<')
621 else if (code == '>')
623 return (code >= 0 && code < len ? mtext_ref_char (preedit, code) : -1);
627 parse_expression (MPlist *plist)
631 if (MPLIST_INTEGER_P (plist) || MPLIST_SYMBOL_P (plist))
633 if (! MPLIST_PLIST_P (plist))
635 plist = MPLIST_PLIST (plist);
636 op = MPLIST_SYMBOL (plist);
637 if (op != Mplus && op != Mminus && op != Mstar && op != Mslush
638 && op != Mand && op != Mor && op != Mnot
639 && op != Mless && op != Mgreater && op != Mequal
640 && op != Mless_equal && op != Mgreater_equal)
641 MERROR (MERROR_IM, -1);
642 MPLIST_DO (plist, MPLIST_NEXT (plist))
643 if (parse_expression (plist) < 0)
649 resolve_expression (MInputContext *ic, MPlist *plist)
654 if (MPLIST_INTEGER_P (plist))
655 return MPLIST_INTEGER (plist);
656 if (MPLIST_SYMBOL_P (plist))
657 return integer_value (ic, plist, NULL, 1);
658 if (! MPLIST_PLIST_P (plist))
660 plist = MPLIST_PLIST (plist);
661 if (! MPLIST_SYMBOL_P (plist))
663 op = MPLIST_SYMBOL (plist);
664 plist = MPLIST_NEXT (plist);
665 val = resolve_expression (ic, plist);
667 MPLIST_DO (plist, MPLIST_NEXT (plist))
668 val += resolve_expression (ic, plist);
669 else if (op == Mminus)
670 MPLIST_DO (plist, MPLIST_NEXT (plist))
671 val -= resolve_expression (ic, plist);
672 else if (op == Mstar)
673 MPLIST_DO (plist, MPLIST_NEXT (plist))
674 val *= resolve_expression (ic, plist);
675 else if (op == Mslush)
676 MPLIST_DO (plist, MPLIST_NEXT (plist))
677 val /= resolve_expression (ic, plist);
679 MPLIST_DO (plist, MPLIST_NEXT (plist))
680 val &= resolve_expression (ic, plist);
682 MPLIST_DO (plist, MPLIST_NEXT (plist))
683 val |= resolve_expression (ic, plist);
686 else if (op == Mless)
687 val = val < resolve_expression (ic, MPLIST_NEXT (plist));
688 else if (op == Mequal)
689 val = val == resolve_expression (ic, MPLIST_NEXT (plist));
690 else if (op == Mgreater)
691 val = val > resolve_expression (ic, MPLIST_NEXT (plist));
692 else if (op == Mless_equal)
693 val = val <= resolve_expression (ic, MPLIST_NEXT (plist));
694 else if (op == Mgreater_equal)
695 val = val >= resolve_expression (ic, MPLIST_NEXT (plist));
699 /* Parse PLIST as an action list. PLIST should have this form:
700 PLIST ::= ( (ACTION-NAME ACTION-ARG *) *).
701 Return 0 if successfully parsed, otherwise return -1. */
704 parse_action_list (MPlist *plist, MPlist *macros)
706 MPLIST_DO (plist, plist)
708 if (MPLIST_MTEXT_P (plist))
710 /* This is a short form of (insert MTEXT). */
711 /* if (mtext_nchars (MPLIST_MTEXT (plist)) == 0)
712 MERROR (MERROR_IM, -1); */
714 else if (MPLIST_PLIST_P (plist)
715 && (MPLIST_MTEXT_P (MPLIST_PLIST (plist))
716 || MPLIST_PLIST_P (MPLIST_PLIST (plist))))
720 /* This is a short form of (insert (GROUPS *)). */
721 MPLIST_DO (pl, MPLIST_PLIST (plist))
723 if (MPLIST_PLIST_P (pl))
727 MPLIST_DO (elt, MPLIST_PLIST (pl))
728 if (! MPLIST_MTEXT_P (elt)
729 || mtext_nchars (MPLIST_MTEXT (elt)) == 0)
730 MERROR (MERROR_IM, -1);
734 if (! MPLIST_MTEXT_P (pl)
735 || mtext_nchars (MPLIST_MTEXT (pl)) == 0)
736 MERROR (MERROR_IM, -1);
740 else if (MPLIST_INTEGER_P (plist))
742 int c = MPLIST_INTEGER (plist);
744 if (c < 0 || c > MCHAR_MAX)
745 MERROR (MERROR_IM, -1);
747 else if (MPLIST_PLIST_P (plist)
748 && MPLIST_SYMBOL_P (MPLIST_PLIST (plist)))
750 MPlist *pl = MPLIST_PLIST (plist);
751 MSymbol action_name = MPLIST_SYMBOL (pl);
753 pl = MPLIST_NEXT (pl);
755 if (action_name == Minsert)
757 if (MPLIST_MTEXT_P (pl))
759 if (mtext_nchars (MPLIST_MTEXT (pl)) == 0)
760 MERROR (MERROR_IM, -1);
762 else if (MPLIST_PLIST_P (pl))
766 if (MPLIST_PLIST_P (pl))
770 MPLIST_DO (elt, MPLIST_PLIST (pl))
771 if (! MPLIST_MTEXT_P (elt)
772 || mtext_nchars (MPLIST_MTEXT (elt)) == 0)
773 MERROR (MERROR_IM, -1);
777 if (! MPLIST_MTEXT_P (pl)
778 || mtext_nchars (MPLIST_MTEXT (pl)) == 0)
779 MERROR (MERROR_IM, -1);
783 else if (! MPLIST_SYMBOL_P (pl))
784 MERROR (MERROR_IM, -1);
786 else if (action_name == Mselect
787 || action_name == Mdelete
788 || action_name == Mmove)
790 if (parse_expression (pl) < 0)
793 else if (action_name == Mmark
794 || action_name == Mcall
795 || action_name == Mshift)
797 if (! MPLIST_SYMBOL_P (pl))
798 MERROR (MERROR_IM, -1);
800 else if (action_name == Mundo)
802 if (! MPLIST_TAIL_P (pl))
804 if (! MPLIST_SYMBOL_P (pl)
805 && (! MPLIST_INTEGER_P (pl)
806 || MPLIST_INTEGER (pl) == 0))
807 MERROR (MERROR_IM, -1);
810 else if (action_name == Mpushback)
812 if (MPLIST_MTEXT_P (pl))
814 MText *mt = MPLIST_MTEXT (pl);
816 if (mtext_nchars (mt) != mtext_nbytes (mt))
817 MERROR (MERROR_IM, -1);
819 else if (MPLIST_PLIST_P (pl))
823 MPLIST_DO (p, MPLIST_PLIST (pl))
824 if (! MPLIST_SYMBOL_P (p))
825 MERROR (MERROR_IM, -1);
827 else if (! MPLIST_INTEGER_P (pl))
828 MERROR (MERROR_IM, -1);
830 else if (action_name == Mset || action_name == Madd
831 || action_name == Msub || action_name == Mmul
832 || action_name == Mdiv)
834 if (! MPLIST_SYMBOL_P (pl))
835 MERROR (MERROR_IM, -1);
836 if (parse_expression (MPLIST_NEXT (pl)) < 0)
839 else if (action_name == Mequal || action_name == Mless
840 || action_name == Mgreater || action_name == Mless_equal
841 || action_name == Mgreater_equal)
843 if (parse_expression (pl) < 0
844 || parse_expression (MPLIST_NEXT (pl)) < 0)
846 pl = MPLIST_NEXT (MPLIST_NEXT (pl));
847 if (! MPLIST_PLIST_P (pl))
848 MERROR (MERROR_IM, -1);
849 if (parse_action_list (MPLIST_PLIST (pl), macros) < 0)
850 MERROR (MERROR_IM, -1);
851 pl = MPLIST_NEXT (pl);
852 if (MPLIST_PLIST_P (pl)
853 && parse_action_list (MPLIST_PLIST (pl), macros) < 0)
854 MERROR (MERROR_IM, -1);
856 else if (action_name == Mshow || action_name == Mhide
857 || action_name == Mcommit || action_name == Munhandle)
859 else if (action_name == Mcond)
862 if (! MPLIST_PLIST_P (pl))
863 MERROR (MERROR_IM, -1);
865 else if (! macros || ! mplist_get (macros, action_name))
866 MERROR (MERROR_IM, -1);
869 MERROR (MERROR_IM, -1);
876 resolve_command (MSymbol language, MSymbol name, MSymbol command)
878 MPlist *plist = get_nested_list (language, name, Mnil, M_command);
881 MERROR (MERROR_IM, NULL);
882 MPLIST_DO (plist, plist)
884 if (MPLIST_SYMBOL (plist) == command)
886 plist = MPLIST_NEXT (plist);
888 if (MPLIST_TAIL_P (plist))
889 MERROR (MERROR_IM, NULL);
890 plist = MPLIST_NEXT (plist);
891 if (! MPLIST_PLIST_P (plist))
892 MERROR (MERROR_IM, NULL);
893 plist = MPLIST_NEXT (MPLIST_PLIST (plist));
897 /* Load a translation into MAP from PLIST.
899 PLIST ::= ( KEYSEQ MAP-ACTION * ) */
902 load_translation (MIMMap *map, MPlist *keylist, MPlist *map_actions,
903 MPlist *branch_actions, MPlist *macros)
908 if (MPLIST_MTEXT_P (keylist))
910 MText *mt = MPLIST_MTEXT (keylist);
912 len = mtext_nchars (mt);
913 if (len == 0 || len != mtext_nbytes (mt))
914 MERROR (MERROR_IM, -1);
915 keyseq = (MSymbol *) alloca (sizeof (MSymbol) * len);
916 for (i = 0; i < len; i++)
917 keyseq[i] = one_char_symbol[MTEXT_DATA (mt)[i]];
919 else if (MPLIST_PLIST_P (keylist))
921 MPlist *elt = MPLIST_PLIST (keylist);
923 len = MPLIST_LENGTH (elt);
925 MERROR (MERROR_IM, -1);
926 keyseq = (MSymbol *) alloca (sizeof (int) * len);
927 for (i = 0; i < len; i++, elt = MPLIST_NEXT (elt))
929 if (MPLIST_INTEGER_P (elt))
931 int c = MPLIST_INTEGER (elt);
933 if (c < 0 || c >= 0x100)
934 MERROR (MERROR_IM, -1);
935 keyseq[i] = one_char_symbol[c];
937 else if (MPLIST_SYMBOL_P (elt))
938 keyseq[i] = MPLIST_SYMBOL (elt);
940 MERROR (MERROR_IM, -1);
944 MERROR (MERROR_IM, -1);
946 for (i = 0; i < len; i++)
948 MIMMap *deeper = NULL;
951 deeper = mplist_get (map->submaps, keyseq[i]);
953 map->submaps = mplist ();
956 /* Fixme: It is better to make all deeper maps at once. */
957 MSTRUCT_CALLOC (deeper, MERROR_IM);
958 mplist_put (map->submaps, keyseq[i], deeper);
963 /* We reach a terminal map. */
965 || map->branch_actions)
966 /* This map is already defined. We avoid overriding it. */
969 if (! MPLIST_TAIL_P (map_actions))
971 if (parse_action_list (map_actions, macros) < 0)
972 MERROR (MERROR_IM, -1);
973 map->map_actions = map_actions;
977 map->branch_actions = branch_actions;
978 M17N_OBJECT_REF (branch_actions);
984 /* Load a branch from PLIST into MAP. PLIST has this form:
985 PLIST ::= ( MAP-NAME BRANCH-ACTION * )
986 MAPS is a plist of raw maps.
987 STATE is the current state. */
990 load_branch (MPlist *plist, MPlist *maps, MIMMap *map,
991 MSymbol language, MSymbol name, MPlist *macros)
994 MPlist *branch_actions;
996 if (! MPLIST_SYMBOL_P (plist))
997 MERROR (MERROR_IM, -1);
998 map_name = MPLIST_SYMBOL (plist);
999 plist = MPLIST_NEXT (plist);
1000 if (MPLIST_TAIL_P (plist))
1001 branch_actions = NULL;
1002 else if (parse_action_list (plist, macros) < 0)
1003 MERROR (MERROR_IM, -1);
1005 branch_actions = plist;
1006 if (map_name == Mnil)
1008 map->branch_actions = branch_actions;
1010 M17N_OBJECT_REF (branch_actions);
1012 else if (map_name == Mt)
1014 map->map_actions = branch_actions;
1016 M17N_OBJECT_REF (branch_actions);
1018 else if ((plist = (MPlist *) mplist_get (maps, map_name)))
1020 MPLIST_DO (plist, plist)
1022 MPlist *keylist, *map_actions;
1024 if (! MPLIST_PLIST_P (plist))
1025 MERROR (MERROR_IM, -1);
1026 keylist = MPLIST_PLIST (plist);
1027 map_actions = MPLIST_NEXT (keylist);
1028 if (MPLIST_SYMBOL_P (keylist))
1030 MSymbol command = MPLIST_SYMBOL (keylist);
1031 MPlist *pl = resolve_command (language, name, command);
1036 if (load_translation (map, pl, map_actions, branch_actions,
1038 MERROR (MERROR_IM, -1);
1041 if (load_translation (map, keylist, map_actions, branch_actions,
1043 MERROR (MERROR_IM, -1);
1050 /* Load a macro from PLIST into MACROS.
1051 PLIST has this from:
1052 PLIST ::= ( MACRO-NAME ACTION * )
1053 MACROS is a plist of macro names vs action list. */
1055 load_macros (MPlist *plist, MPlist *macros)
1059 if (! MPLIST_SYMBOL_P (plist))
1060 MERROR (MERROR_IM, -1);
1061 name = MPLIST_SYMBOL (plist);
1062 plist = MPLIST_NEXT (plist);
1063 if (MPLIST_TAIL_P (plist)
1064 || parse_action_list (plist, macros) < 0)
1065 MERROR (MERROR_IM, -1);
1066 mplist_put (macros, name, plist);
1067 M17N_OBJECT_REF (plist);
1071 /* Load an external module from PLIST into EXTERNALS.
1072 PLIST has this form:
1073 PLIST ::= ( MODULE-NAME FUNCTION * )
1074 EXTERNALS is a plist of MODULE-NAME vs (MIMExternalModule *). */
1077 load_external_module (MPlist *plist, MPlist *externals)
1082 MIMExternalModule *external;
1086 if (MPLIST_MTEXT_P (plist))
1087 module = msymbol ((char *) MTEXT_DATA (MPLIST_MTEXT (plist)));
1088 else if (MPLIST_SYMBOL_P (plist))
1089 module = MPLIST_SYMBOL (plist);
1090 module_file = alloca (strlen (MSYMBOL_NAME (module))
1091 + strlen (DLOPEN_SHLIB_EXT) + 1);
1092 sprintf (module_file, "%s%s", MSYMBOL_NAME (module), DLOPEN_SHLIB_EXT);
1094 handle = dlopen (module_file, RTLD_NOW);
1097 fprintf (stderr, "%s\n", dlerror ());
1098 MERROR (MERROR_IM, -1);
1100 func_list = mplist ();
1101 MPLIST_DO (plist, MPLIST_NEXT (plist))
1103 if (! MPLIST_SYMBOL_P (plist))
1104 MERROR_GOTO (MERROR_IM, err_label);
1105 func = dlsym (handle, MSYMBOL_NAME (MPLIST_SYMBOL (plist)));
1107 MERROR_GOTO (MERROR_IM, err_label);
1108 mplist_add (func_list, MPLIST_SYMBOL (plist), func);
1111 MSTRUCT_MALLOC (external, MERROR_IM);
1112 external->handle = handle;
1113 external->func_list = func_list;
1114 mplist_add (externals, module, external);
1119 M17N_OBJECT_UNREF (func_list);
1124 free_map (MIMMap *map, int top)
1129 M17N_OBJECT_UNREF (map->map_actions);
1132 MPLIST_DO (plist, map->submaps)
1133 free_map ((MIMMap *) MPLIST_VAL (plist), 0);
1134 M17N_OBJECT_UNREF (map->submaps);
1136 M17N_OBJECT_UNREF (map->branch_actions);
1141 free_state (void *object)
1143 MIMState *state = object;
1146 M17N_OBJECT_UNREF (state->title);
1148 free_map (state->map, 1);
1152 /** Load a state from PLIST into a newly allocated state object.
1153 PLIST has this form:
1154 PLIST ::= ( STATE-NAME STATE-TITLE ? BRANCH * )
1155 BRANCH ::= ( MAP-NAME BRANCH-ACTION * )
1156 MAPS is a plist of defined maps.
1157 Return the state object. */
1160 load_state (MPlist *plist, MPlist *maps, MSymbol language, MSymbol name,
1165 if (! MPLIST_SYMBOL_P (plist))
1166 MERROR (MERROR_IM, NULL);
1167 M17N_OBJECT (state, free_state, MERROR_IM);
1168 state->name = MPLIST_SYMBOL (plist);
1169 plist = MPLIST_NEXT (plist);
1170 if (MPLIST_MTEXT_P (plist))
1172 state->title = MPLIST_MTEXT (plist);
1173 mtext_put_prop (state->title, 0, mtext_nchars (state->title),
1174 Mlanguage, language);
1175 M17N_OBJECT_REF (state->title);
1176 plist = MPLIST_NEXT (plist);
1178 MSTRUCT_CALLOC (state->map, MERROR_IM);
1179 MPLIST_DO (plist, plist)
1180 if (! MPLIST_PLIST_P (plist)
1181 || load_branch (MPLIST_PLIST (plist), maps, state->map, language, name,
1183 MERROR (MERROR_IM, NULL);
1188 static MPlist *im_info_list;
1191 free_im_info (MInputMethodInfo *im_info)
1196 M17N_OBJECT_UNREF (im_info->title);
1197 if (im_info->states)
1199 MPLIST_DO (plist, im_info->states)
1201 MIMState *state = (MIMState *) MPLIST_VAL (plist);
1203 M17N_OBJECT_UNREF (state);
1205 M17N_OBJECT_UNREF (im_info->states);
1208 if (im_info->macros)
1210 MPLIST_DO (plist, im_info->macros)
1211 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
1212 M17N_OBJECT_UNREF (im_info->macros);
1215 if (im_info->externals)
1217 MPLIST_DO (plist, im_info->externals)
1219 MIMExternalModule *external = MPLIST_VAL (plist);
1221 dlclose (external->handle);
1222 M17N_OBJECT_UNREF (external->func_list);
1224 MPLIST_KEY (plist) = Mt;
1226 M17N_OBJECT_UNREF (im_info->externals);
1230 MPLIST_DO (plist, im_info->maps)
1232 MPlist *p = MPLIST_PLIST (plist);
1234 M17N_OBJECT_UNREF (p);
1236 M17N_OBJECT_UNREF (im_info->maps);
1242 static MInputMethodInfo *get_im_info (MSymbol language, MSymbol name,
1245 static MInputMethodInfo *
1246 get_im_info_by_tags (MPlist *plist)
1251 for (i = 0; i < 3 && MPLIST_SYMBOL_P (plist);
1252 i++, plist = MPLIST_NEXT (plist))
1253 tag[i] = MPLIST_SYMBOL (plist);
1258 return get_im_info (tag[0], tag[1], tag[2]);
1261 /* Load an input method from PLIST into IM_INTO, and return it. */
1263 static MInputMethodInfo *
1264 load_im_info (MSymbol language, MSymbol name, MPlist *plist)
1266 MInputMethodInfo *im_info;
1267 MText *title = NULL;
1268 MPlist *maps = NULL;
1269 MPlist *states = NULL;
1270 MPlist *externals = NULL;
1271 MPlist *macros = NULL;
1274 MSTRUCT_CALLOC (im_info, MERROR_IM);
1276 while (MPLIST_PLIST_P (plist))
1278 elt = MPLIST_PLIST (plist);
1279 if (! MPLIST_SYMBOL_P (elt))
1280 MERROR_GOTO (MERROR_IM, err);
1281 if (MPLIST_SYMBOL (elt) == Mtitle)
1283 elt = MPLIST_NEXT (elt);
1284 if (! MPLIST_MTEXT_P (elt))
1285 MERROR_GOTO (MERROR_IM, err);
1286 im_info->title = title = MPLIST_MTEXT (elt);
1287 M17N_OBJECT_REF (title);
1289 else if (MPLIST_SYMBOL (elt) == Mmap)
1291 MPlist *pl = mplist__from_alist (MPLIST_NEXT (elt));
1294 MERROR_GOTO (MERROR_IM, err);
1296 im_info->maps = maps = pl;
1298 maps = mplist__conc (maps, pl);
1300 else if (MPLIST_SYMBOL (elt) == Mmacro)
1303 im_info->macros = macros = mplist ();
1304 MPLIST_DO (elt, MPLIST_NEXT (elt))
1306 if (! MPLIST_PLIST_P (elt)
1307 || load_macros (MPLIST_PLIST (elt), macros) < 0)
1308 MERROR_GOTO (MERROR_IM, err);
1311 else if (MPLIST_SYMBOL (elt) == Mmodule)
1314 im_info->externals = externals = mplist ();
1315 MPLIST_DO (elt, MPLIST_NEXT (elt))
1317 if (! MPLIST_PLIST_P (elt)
1318 || load_external_module (MPLIST_PLIST (elt), externals) < 0)
1319 MERROR_GOTO (MERROR_IM, err);
1322 else if (MPLIST_SYMBOL (elt) == Mstate)
1324 MPLIST_DO (elt, MPLIST_NEXT (elt))
1328 if (! MPLIST_PLIST_P (elt))
1329 MERROR_GOTO (MERROR_IM, err);
1330 state = load_state (MPLIST_PLIST (elt), maps, language, name,
1333 MERROR_GOTO (MERROR_IM, err);
1335 im_info->states = states = mplist ();
1336 mplist_put (states, state->name, state);
1339 else if (MPLIST_SYMBOL (elt) == Minclude)
1341 /* elt ::= include (tag1 tag2 ...) key item ... */
1343 MInputMethodInfo *temp;
1346 elt = MPLIST_NEXT (elt);
1347 if (! MPLIST_PLIST_P (elt))
1348 MERROR_GOTO (MERROR_IM, err);
1349 temp = get_im_info_by_tags (MPLIST_PLIST (elt));
1351 MERROR_GOTO (MERROR_IM, err);
1352 elt = MPLIST_NEXT (elt);
1353 if (! MPLIST_SYMBOL_P (elt))
1354 MERROR_GOTO (MERROR_IM, err);
1355 key = MPLIST_SYMBOL (elt);
1356 elt = MPLIST_NEXT (elt);
1360 im_info->maps = maps = mplist ();
1361 MPLIST_DO (pl, temp->maps)
1363 p = MPLIST_VAL (pl);
1364 MPLIST_ADD_PLIST (maps, MPLIST_KEY (pl), p);
1365 M17N_OBJECT_REF (p);
1368 else if (key == Mmacro)
1371 im_info->macros = macros = mplist ();
1372 MPLIST_DO (pl, temp->macros)
1374 p = MPLIST_VAL (pl);
1375 MPLIST_ADD_PLIST (macros, MPLIST_KEY (pl), p);
1376 M17N_OBJECT_REF (p);
1379 else if (key == Mstate)
1382 im_info->states = states = mplist ();
1383 MPLIST_DO (pl, temp->states)
1385 MIMState *state = MPLIST_VAL (pl);
1387 mplist_add (states, MPLIST_KEY (pl), state);
1388 M17N_OBJECT_REF (state);
1392 MERROR_GOTO (MERROR_IM, err);
1394 plist = MPLIST_NEXT (plist);
1399 if (! title && name)
1401 = title = mtext_from_data (MSYMBOL_NAME (name), MSYMBOL_NAMELEN (name),
1402 MTEXT_FORMAT_US_ASCII);
1406 free_im_info (im_info);
1412 static int take_action_list (MInputContext *ic, MPlist *action_list);
1413 static void preedit_commit (MInputContext *ic);
1416 shift_state (MInputContext *ic, MSymbol state_name)
1418 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1419 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1420 MIMState *orig_state = ic_info->state, *state;
1422 /* Find a state to shift to. If not found, shift to the initial
1424 if (state_name == Mt)
1426 if (! ic_info->prev_state)
1428 state = ic_info->prev_state;
1432 state = (MIMState *) mplist_get (im_info->states, state_name);
1434 state = (MIMState *) MPLIST_VAL (im_info->states);
1437 MDEBUG_PRINT1 ("\n [IM] (shift %s)", MSYMBOL_NAME (state->name));
1439 /* Enter the new state. */
1440 ic_info->state = state;
1441 ic_info->map = state->map;
1442 ic_info->state_key_head = ic_info->key_head;
1443 if (state == (MIMState *) MPLIST_VAL (im_info->states))
1444 /* We have shifted to the initial state. */
1445 preedit_commit (ic);
1446 mtext_cpy (ic_info->preedit_saved, ic->preedit);
1447 ic_info->state_pos = ic->cursor_pos;
1448 if (state != orig_state )
1450 if (state == (MIMState *) MPLIST_VAL (im_info->states))
1451 ic_info->prev_state = NULL;
1453 ic_info->prev_state = orig_state;
1456 ic->status = state->title;
1458 ic->status = im_info->title;
1459 ic->status_changed = 1;
1460 if (ic_info->map == ic_info->state->map
1461 && ic_info->map->map_actions)
1463 MDEBUG_PRINT (" init-actions:");
1464 take_action_list (ic, ic_info->map->map_actions);
1469 /* Find a candidate group that contains a candidate number INDEX from
1470 PLIST. Set START_INDEX to the first candidate number of the group,
1471 END_INDEX to the last candidate number plus 1, GROUP_INDEX to the
1472 candidate group number if they are non-NULL. If INDEX is -1, find
1473 the last candidate group. */
1476 find_candidates_group (MPlist *plist, int index,
1477 int *start_index, int *end_index, int *group_index)
1479 int i = 0, gidx = 0, len;
1481 MPLIST_DO (plist, plist)
1483 if (MPLIST_MTEXT_P (plist))
1484 len = mtext_nchars (MPLIST_MTEXT (plist));
1486 len = mplist_length (MPLIST_PLIST (plist));
1487 if (index < 0 ? MPLIST_TAIL_P (MPLIST_NEXT (plist))
1493 *end_index = i + len;
1495 *group_index = gidx;
1505 preedit_insert (MInputContext *ic, int pos, MText *mt, int c)
1507 MInputContextInfo *ic_info = ((MInputContext *) ic)->info;
1509 int nchars = mt ? mtext_nchars (mt) : 1;
1512 mtext_ins (ic->preedit, pos, mt);
1514 mtext_ins_char (ic->preedit, pos, c, 1);
1515 MPLIST_DO (markers, ic_info->markers)
1516 if (MPLIST_INTEGER (markers) > pos)
1517 MPLIST_VAL (markers) = (void *) (MPLIST_INTEGER (markers) + nchars);
1518 if (ic->cursor_pos >= pos)
1519 ic->cursor_pos += nchars;
1520 ic->preedit_changed = 1;
1525 preedit_delete (MInputContext *ic, int from, int to)
1527 MInputContextInfo *ic_info = ((MInputContext *) ic)->info;
1530 mtext_del (ic->preedit, from, to);
1531 MPLIST_DO (markers, ic_info->markers)
1533 if (MPLIST_INTEGER (markers) > to)
1534 MPLIST_VAL (markers)
1535 = (void *) (MPLIST_INTEGER (markers) - (to - from));
1536 else if (MPLIST_INTEGER (markers) > from);
1537 MPLIST_VAL (markers) = (void *) from;
1539 if (ic->cursor_pos >= to)
1540 ic->cursor_pos -= to - from;
1541 else if (ic->cursor_pos > from)
1542 ic->cursor_pos = from;
1543 ic->preedit_changed = 1;
1547 preedit_commit (MInputContext *ic)
1549 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1550 int preedit_len = mtext_nchars (ic->preedit);
1552 if (preedit_len > 0)
1556 mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit),
1557 Mcandidate_list, NULL, 0);
1558 mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit),
1559 Mcandidate_index, NULL, 0);
1560 mtext_cat (ic->produced, ic->preedit);
1561 if ((mdebug__flag & mdebug_mask)
1562 && mtext_nchars (ic->produced) > 0)
1566 MDEBUG_PRINT (" (produced");
1567 for (i = 0; i < mtext_nchars (ic->produced); i++)
1568 MDEBUG_PRINT1 (" U+%04X", mtext_ref_char (ic->produced, i));
1571 mtext_reset (ic->preedit);
1572 mtext_reset (ic_info->preedit_saved);
1573 MPLIST_DO (p, ic_info->markers)
1575 ic->cursor_pos = ic_info->state_pos = 0;
1576 ic->preedit_changed = 1;
1578 if (ic->candidate_list)
1580 M17N_OBJECT_UNREF (ic->candidate_list);
1581 ic->candidate_list = NULL;
1582 ic->candidate_show = 0;
1583 ic->candidates_changed = MINPUT_CANDIDATES_LIST_CHANGED;
1584 if (ic->candidate_show)
1586 ic->candidate_show = 0;
1587 ic->candidates_changed |= MINPUT_CANDIDATES_SHOW_CHANGED;
1591 memmove (ic_info->keys, ic_info->keys + ic_info->key_head,
1592 sizeof (int) * (ic_info->used - ic_info->key_head));
1593 ic_info->used -= ic_info->key_head;
1594 ic_info->state_key_head = ic_info->key_head = 0;
1598 new_index (MInputContext *ic, int current, int limit, MSymbol sym, MText *mt)
1600 int code = marker_code (sym);
1602 if (mt && (code == '[' || code == ']'))
1606 if (code == '[' && current > 0)
1608 if (mtext_prop_range (mt, Mcandidate_list, pos - 1, &pos, NULL, 1)
1612 else if (code == ']' && current < mtext_nchars (mt))
1614 if (mtext_prop_range (mt, Mcandidate_list, pos, NULL, &pos, 1))
1620 return (code == '<' ? 0
1621 : code == '>' ? limit
1622 : code == '-' ? current - 1
1623 : code == '+' ? current + 1
1624 : code == '=' ? current
1625 : code - '0' > limit ? limit
1629 return (int) mplist_get (((MInputContextInfo *) ic->info)->markers, sym);
1633 update_candidate (MInputContext *ic, MTextProperty *prop, int idx)
1635 int from = mtext_property_start (prop);
1636 int to = mtext_property_end (prop);
1638 MPlist *candidate_list = mtext_property_value (prop);
1639 MPlist *group = find_candidates_group (candidate_list, idx, &start,
1641 int ingroup_index = idx - start;
1644 preedit_delete (ic, from, to);
1645 if (MPLIST_MTEXT_P (group))
1647 mt = MPLIST_MTEXT (group);
1648 preedit_insert (ic, from, NULL, mtext_ref_char (mt, ingroup_index));
1656 for (i = 0, plist = MPLIST_PLIST (group); i < ingroup_index;
1657 i++, plist = MPLIST_NEXT (plist));
1658 mt = MPLIST_MTEXT (plist);
1659 preedit_insert (ic, from, mt, 0);
1660 to = from + mtext_nchars (mt);
1662 mtext_put_prop (ic->preedit, from, to, Mcandidate_list, candidate_list);
1663 mtext_put_prop (ic->preedit, from, to, Mcandidate_index, (void *) idx);
1664 ic->cursor_pos = to;
1668 get_select_charset (MInputContextInfo * ic_info)
1670 MPlist *plist = resolve_variable (ic_info, Mcandidates_charset);
1673 if (! MPLIST_VAL (plist))
1675 sym = MPLIST_SYMBOL (plist);
1678 return MCHARSET (sym);
1682 adjust_candidates (MPlist *plist, MCharset *charset)
1686 /* plist ::= MTEXT ... | PLIST ... */
1687 plist = mplist_copy (plist);
1688 if (MPLIST_MTEXT_P (plist))
1691 while (! MPLIST_TAIL_P (pl))
1693 /* pl ::= MTEXT ... */
1694 MText *mt = MPLIST_MTEXT (pl);
1698 for (i = mtext_nchars (mt) - 1; i >= 0; i--)
1700 c = mtext_ref_char (mt, i);
1701 if (ENCODE_CHAR (charset, c) == MCHAR_INVALID_CODE)
1705 mt = mtext_dup (mt);
1706 mplist_set (pl, Mtext, mt);
1707 M17N_OBJECT_UNREF (mt);
1710 mtext_del (mt, i, i + 1);
1713 if (mtext_len (mt) > 0)
1714 pl = MPLIST_NEXT (pl);
1718 M17N_OBJECT_UNREF (mt);
1722 else /* MPLIST_PLIST_P (plist) */
1725 while (! MPLIST_TAIL_P (pl))
1727 /* pl ::= (MTEXT ...) ... */
1728 MPlist *p = MPLIST_PLIST (pl);
1730 /* p ::= MTEXT ... */
1734 while (! MPLIST_TAIL_P (p0))
1736 MText *mt = MPLIST_MTEXT (p0);
1739 for (i = mtext_nchars (mt) - 1; i >= 0; i--)
1741 c = mtext_ref_char (mt, i);
1742 if (ENCODE_CHAR (charset, c) == MCHAR_INVALID_CODE)
1747 p0 = MPLIST_NEXT (p0);
1754 p = mplist_copy (p);
1755 mplist_set (pl, Mplist, p);
1756 M17N_OBJECT_UNREF (p);
1760 p0 = MPLIST_NEXT (p0);
1763 M17N_OBJECT_UNREF (mt);
1766 if (! MPLIST_TAIL_P (p))
1767 pl = MPLIST_NEXT (pl);
1771 M17N_OBJECT_UNREF (p);
1775 if (MPLIST_TAIL_P (plist))
1777 M17N_OBJECT_UNREF (plist);
1784 get_candidate_list (MInputContextInfo *ic_info, MPlist *args)
1786 MCharset *charset = get_select_charset (ic_info);
1791 plist = resolve_variable (ic_info, Mcandidates_group_size);
1792 column = MPLIST_INTEGER (plist);
1794 plist = MPLIST_PLIST (args);
1797 if (! (plist = adjust_candidates (plist, charset)))
1801 M17N_OBJECT_REF (plist);
1805 if (MPLIST_MTEXT_P (plist))
1807 MText *mt = MPLIST_MTEXT (plist);
1808 MPlist *next = MPLIST_NEXT (plist);
1810 if (MPLIST_TAIL_P (next))
1811 M17N_OBJECT_REF (mt);
1814 mt = mtext_dup (mt);
1815 while (! MPLIST_TAIL_P (next))
1817 mt = mtext_cat (mt, MPLIST_MTEXT (next));
1818 next = MPLIST_NEXT (next);
1821 M17N_OBJECT_UNREF (plist);
1823 len = mtext_nchars (mt);
1825 mplist_add (plist, Mtext, mt);
1828 for (i = 0; i < len; i += column)
1830 int to = (i + column < len ? i + column : len);
1831 MText *sub = mtext_copy (mtext (), 0, mt, i, to);
1833 mplist_add (plist, Mtext, sub);
1834 M17N_OBJECT_UNREF (sub);
1837 M17N_OBJECT_UNREF (mt);
1839 else /* MPLIST_PLIST_P (plist) */
1841 MPlist *pl = MPLIST_PLIST (plist), *p;
1842 MPlist *next = MPLIST_NEXT (plist);
1845 if (MPLIST_TAIL_P (next))
1846 M17N_OBJECT_REF (pl);
1849 pl = mplist_copy (pl);
1850 while (! MPLIST_TAIL_P (next))
1852 p = mplist_copy (MPLIST_PLIST (next));
1853 pl = mplist__conc (pl, p);
1854 M17N_OBJECT_UNREF (p);
1855 next = MPLIST_NEXT (next);
1858 M17N_OBJECT_UNREF (plist);
1860 len = mplist_length (pl);
1862 mplist_add (plist, Mplist, pl);
1867 for (i = 0; i < len; i += column)
1870 mplist_add (plist, Mplist, p);
1871 M17N_OBJECT_UNREF (p);
1872 for (j = 0; j < column && i + j < len; j++)
1874 p = mplist_add (p, Mtext, MPLIST_VAL (p0));
1875 p0 = MPLIST_NEXT (p0);
1879 M17N_OBJECT_UNREF (pl);
1888 regularize_action (MPlist *action_list)
1890 MPlist *action = NULL;
1894 if (MPLIST_PLIST_P (action_list))
1896 action = MPLIST_PLIST (action_list);
1897 if (MPLIST_SYMBOL_P (action))
1899 name = MPLIST_SYMBOL (action);
1900 args = MPLIST_NEXT (action);
1902 && MPLIST_PLIST_P (args))
1903 mplist_set (action, Msymbol, M_candidates);
1905 else if (MPLIST_MTEXT_P (action) || MPLIST_PLIST_P (action))
1908 mplist_push (action, Mplist, MPLIST_VAL (action_list));
1909 mplist_push (action, Msymbol, M_candidates);
1910 mplist_set (action_list, Mplist, action);
1911 M17N_OBJECT_UNREF (action);
1914 else if (MPLIST_MTEXT_P (action_list) || MPLIST_INTEGER_P (action_list))
1917 mplist_push (action, MPLIST_KEY (action_list), MPLIST_VAL (action_list));
1918 mplist_push (action, Msymbol, Minsert);
1919 mplist_set (action_list, Mplist, action);
1920 M17N_OBJECT_UNREF (action);
1926 take_action_list (MInputContext *ic, MPlist *action_list)
1928 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1929 MPlist *candidate_list = ic->candidate_list;
1930 int candidate_index = ic->candidate_index;
1931 int candidate_show = ic->candidate_show;
1932 MTextProperty *prop;
1934 MPLIST_DO (action_list, action_list)
1936 MPlist *action = regularize_action (action_list);
1942 name = MPLIST_SYMBOL (action);
1943 args = MPLIST_NEXT (action);
1945 MDEBUG_PRINT1 (" %s", MSYMBOL_NAME (name));
1946 if (name == Minsert)
1948 if (MPLIST_SYMBOL_P (args))
1950 args = resolve_variable (ic_info, MPLIST_SYMBOL (args));
1951 if (! MPLIST_MTEXT_P (args) && ! MPLIST_INTEGER_P (args))
1954 if (MPLIST_MTEXT_P (args))
1955 preedit_insert (ic, ic->cursor_pos, MPLIST_MTEXT (args), 0);
1956 else /* MPLIST_INTEGER_P (args)) */
1957 preedit_insert (ic, ic->cursor_pos, NULL, MPLIST_INTEGER (args));
1959 else if (name == M_candidates)
1961 MPlist *plist = get_candidate_list (ic_info, args);
1966 if (MPLIST_MTEXT_P (plist))
1968 preedit_insert (ic, ic->cursor_pos, NULL,
1969 mtext_ref_char (MPLIST_MTEXT (plist), 0));
1974 MText * mt = MPLIST_MTEXT (MPLIST_PLIST (plist));
1976 preedit_insert (ic, ic->cursor_pos, mt, 0);
1977 len = mtext_nchars (mt);
1979 mtext_put_prop (ic->preedit,
1980 ic->cursor_pos - len, ic->cursor_pos,
1981 Mcandidate_list, plist);
1982 mtext_put_prop (ic->preedit,
1983 ic->cursor_pos - len, ic->cursor_pos,
1984 Mcandidate_index, (void *) 0);
1985 M17N_OBJECT_UNREF (plist);
1987 else if (name == Mselect)
1990 int code, idx, gindex;
1991 int pos = ic->cursor_pos;
1995 || ! (prop = mtext_get_property (ic->preedit, pos - 1,
1998 if (MPLIST_SYMBOL_P (args))
2000 code = marker_code (MPLIST_SYMBOL (args));
2006 idx = (int) mtext_get_prop (ic->preedit, pos - 1, Mcandidate_index);
2007 group = find_candidates_group (mtext_property_value (prop), idx,
2008 &start, &end, &gindex);
2010 if (code != '[' && code != ']')
2014 ? new_index (NULL, ic->candidate_index - start,
2015 end - start - 1, MPLIST_SYMBOL (args),
2017 : MPLIST_INTEGER (args)));
2020 find_candidates_group (mtext_property_value (prop), -1,
2025 && MPLIST_TAIL_P (MPLIST_NEXT (group)))
2030 int ingroup_index = idx - start;
2033 group = mtext_property_value (prop);
2034 len = mplist_length (group);
2047 for (idx = 0; gindex > 0; gindex--, group = MPLIST_NEXT (group))
2048 idx += (MPLIST_MTEXT_P (group)
2049 ? mtext_nchars (MPLIST_MTEXT (group))
2050 : mplist_length (MPLIST_PLIST (group)));
2051 len = (MPLIST_MTEXT_P (group)
2052 ? mtext_nchars (MPLIST_MTEXT (group))
2053 : mplist_length (MPLIST_PLIST (group)));
2054 if (ingroup_index >= len)
2055 ingroup_index = len - 1;
2056 idx += ingroup_index;
2058 update_candidate (ic, prop, idx);
2060 else if (name == Mshow)
2061 ic->candidate_show = 1;
2062 else if (name == Mhide)
2063 ic->candidate_show = 0;
2064 else if (name == Mdelete)
2066 int len = mtext_nchars (ic->preedit);
2070 if (MPLIST_SYMBOL_P (args)
2071 && (pos = surrounding_pos (MPLIST_SYMBOL (args))) != 0)
2073 delete_surrounding_text (ic, pos);
2077 to = (MPLIST_SYMBOL_P (args)
2078 ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
2080 : MPLIST_INTEGER (args));
2085 MDEBUG_PRINT1 ("(%d)", to - ic->cursor_pos);
2086 if (to < ic->cursor_pos)
2087 preedit_delete (ic, to, ic->cursor_pos);
2088 else if (to > ic->cursor_pos)
2089 preedit_delete (ic, ic->cursor_pos, to);
2092 else if (name == Mmove)
2094 int len = mtext_nchars (ic->preedit);
2096 = (MPLIST_SYMBOL_P (args)
2097 ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
2099 : MPLIST_INTEGER (args));
2105 if (pos != ic->cursor_pos)
2107 ic->cursor_pos = pos;
2108 ic->preedit_changed = 1;
2111 else if (name == Mmark)
2113 int code = marker_code (MPLIST_SYMBOL (args));
2116 mplist_put (ic_info->markers, MPLIST_SYMBOL (args),
2117 (void *) ic->cursor_pos);
2119 else if (name == Mpushback)
2121 if (MPLIST_INTEGER_P (args))
2123 int num = MPLIST_INTEGER (args);
2126 ic_info->key_head -= num;
2128 ic_info->key_head = num;
2129 if (ic_info->key_head > ic_info->used)
2130 ic_info->key_head = ic_info->used;
2132 else if (MPLIST_MTEXT_P (args))
2134 MText *mt = MPLIST_MTEXT (args);
2135 int i, len = mtext_nchars (mt);
2138 ic_info->key_head--;
2139 for (i = 0; i < len; i++)
2141 key = one_char_symbol[MTEXT_DATA (mt)[i]];
2142 if (ic_info->key_head + i < ic_info->used)
2143 ic_info->keys[ic_info->key_head + i] = key;
2145 MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
2150 MPlist *plist = MPLIST_PLIST (args), *pl;
2154 ic_info->key_head--;
2156 MPLIST_DO (pl, plist)
2158 key = MPLIST_SYMBOL (pl);
2159 if (ic_info->key_head < ic_info->used)
2160 ic_info->keys[ic_info->key_head + i] = key;
2162 MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
2167 else if (name == Mcall)
2169 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
2170 MIMExternalFunc func = NULL;
2171 MSymbol module, func_name;
2172 MPlist *func_args, *val;
2175 module = MPLIST_SYMBOL (args);
2176 args = MPLIST_NEXT (args);
2177 func_name = MPLIST_SYMBOL (args);
2179 if (im_info->externals)
2181 MIMExternalModule *external
2182 = (MIMExternalModule *) mplist_get (im_info->externals,
2185 func = (MIMExternalFunc) mplist_get (external->func_list,
2190 func_args = mplist ();
2191 mplist_add (func_args, Mt, ic);
2192 MPLIST_DO (args, MPLIST_NEXT (args))
2196 if (MPLIST_KEY (args) == Msymbol
2197 && MPLIST_KEY (args) != Mnil
2198 && (code = marker_code (MPLIST_SYMBOL (args))) >= 0)
2200 code = new_index (ic, ic->cursor_pos,
2201 mtext_nchars (ic->preedit),
2202 MPLIST_SYMBOL (args), ic->preedit);
2203 mplist_add (func_args, Minteger, (void *) code);
2206 mplist_add (func_args, MPLIST_KEY (args), MPLIST_VAL (args));
2208 val = (func) (func_args);
2209 M17N_OBJECT_UNREF (func_args);
2210 if (val && ! MPLIST_TAIL_P (val))
2211 ret = take_action_list (ic, val);
2212 M17N_OBJECT_UNREF (val);
2216 else if (name == Mshift)
2218 shift_state (ic, MPLIST_SYMBOL (args));
2220 else if (name == Mundo)
2222 int intarg = (MPLIST_TAIL_P (args)
2224 : integer_value (ic, args, NULL, 0));
2226 mtext_reset (ic->preedit);
2227 mtext_reset (ic_info->preedit_saved);
2228 ic->cursor_pos = ic_info->state_pos = 0;
2229 ic_info->state_key_head = ic_info->key_head = 0;
2232 ic_info->used += intarg;
2234 ic_info->used = intarg;
2235 shift_state (ic, Mnil);
2238 else if (name == Mset || name == Madd || name == Msub
2239 || name == Mmul || name == Mdiv)
2241 MSymbol sym = MPLIST_SYMBOL (args);
2246 val1 = integer_value (ic, args, &value, 0);
2247 args = MPLIST_NEXT (args);
2248 val2 = resolve_expression (ic, args);
2250 val1 = val2, op = "=";
2251 else if (name == Madd)
2252 val1 += val2, op = "+=";
2253 else if (name == Msub)
2254 val1 -= val2, op = "-=";
2255 else if (name == Mmul)
2256 val1 *= val2, op = "*=";
2258 val1 /= val2, op = "/=";
2259 MDEBUG_PRINT4 ("(%s %s 0x%X(%d))",
2260 MSYMBOL_NAME (sym), op, val1, val1);
2262 mplist_set (value, Minteger, (void *) val1);
2264 else if (name == Mequal || name == Mless || name == Mgreater
2265 || name == Mless_equal || name == Mgreater_equal)
2268 MPlist *actions1, *actions2;
2271 val1 = resolve_expression (ic, args);
2272 args = MPLIST_NEXT (args);
2273 val2 = resolve_expression (ic, args);
2274 args = MPLIST_NEXT (args);
2275 actions1 = MPLIST_PLIST (args);
2276 args = MPLIST_NEXT (args);
2277 if (MPLIST_TAIL_P (args))
2280 actions2 = MPLIST_PLIST (args);
2281 MDEBUG_PRINT3 ("(%d %s %d)? ", val1, MSYMBOL_NAME (name), val2);
2282 if (name == Mequal ? val1 == val2
2283 : name == Mless ? val1 < val2
2284 : name == Mgreater ? val1 > val2
2285 : name == Mless_equal ? val1 <= val2
2288 MDEBUG_PRINT ("ok");
2289 ret = take_action_list (ic, actions1);
2293 MDEBUG_PRINT ("no");
2295 ret = take_action_list (ic, actions2);
2300 else if (name == Mcond)
2304 MPLIST_DO (args, args)
2309 if (! MPLIST_PLIST (args))
2311 cond = MPLIST_PLIST (args);
2312 if (resolve_expression (ic, cond) != 0)
2314 MDEBUG_PRINT1 ("(%dth)", idx);
2315 if (take_action_list (ic, MPLIST_NEXT (cond)) < 0)
2321 else if (name == Mcommit)
2323 preedit_commit (ic);
2325 else if (name == Munhandle)
2327 preedit_commit (ic);
2332 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
2336 && (actions = mplist_get (im_info->macros, name)))
2338 if (take_action_list (ic, actions) < 0)
2345 if (ic->candidate_list)
2347 M17N_OBJECT_UNREF (ic->candidate_list);
2348 ic->candidate_list = NULL;
2350 if (ic->cursor_pos > 0
2351 && (prop = mtext_get_property (ic->preedit, ic->cursor_pos - 1,
2354 ic->candidate_list = mtext_property_value (prop);
2355 M17N_OBJECT_REF (ic->candidate_list);
2357 = (int) mtext_get_prop (ic->preedit, ic->cursor_pos - 1,
2359 ic->candidate_from = mtext_property_start (prop);
2360 ic->candidate_to = mtext_property_end (prop);
2363 if (candidate_list != ic->candidate_list)
2364 ic->candidates_changed |= MINPUT_CANDIDATES_LIST_CHANGED;
2365 if (candidate_index != ic->candidate_index)
2366 ic->candidates_changed |= MINPUT_CANDIDATES_INDEX_CHANGED;
2367 if (candidate_show != ic->candidate_show)
2368 ic->candidates_changed |= MINPUT_CANDIDATES_SHOW_CHANGED;
2373 /* Handle the input key KEY in the current state and map specified in
2374 the input context IC. If KEY is handled correctly, return 0.
2375 Otherwise, return -1. */
2378 handle_key (MInputContext *ic)
2380 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
2381 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
2382 MIMMap *map = ic_info->map;
2383 MIMMap *submap = NULL;
2384 MSymbol key = ic_info->keys[ic_info->key_head];
2385 MSymbol alias = Mnil;
2388 MDEBUG_PRINT2 (" [IM] handle `%s' in state %s",
2389 MSYMBOL_NAME (key), MSYMBOL_NAME (ic_info->state->name));
2393 submap = mplist_get (map->submaps, key);
2394 if (! submap && (alias = msymbol_get (key, M_key_alias)) != Mnil)
2395 submap = mplist_get (map->submaps, alias);
2401 MDEBUG_PRINT (" submap-found");
2403 MDEBUG_PRINT1 (" submap-found (by alias `%s')", MSYMBOL_NAME (alias));
2404 mtext_cpy (ic->preedit, ic_info->preedit_saved);
2405 ic->preedit_changed = 1;
2406 ic->cursor_pos = ic_info->state_pos;
2407 ic_info->key_head++;
2408 ic_info->map = map = submap;
2409 if (map->map_actions)
2411 MDEBUG_PRINT (" map-actions:");
2412 if (take_action_list (ic, map->map_actions) < 0)
2414 MDEBUG_PRINT ("\n");
2418 else if (map->submaps)
2420 for (i = ic_info->state_key_head; i < ic_info->key_head; i++)
2422 MSymbol key = ic_info->keys[i];
2423 char *name = msymbol_name (key);
2425 if (! name[0] || ! name[1])
2426 mtext_ins_char (ic->preedit, ic->cursor_pos++, name[0], 1);
2430 /* If this is the terminal map or we have shifted to another
2431 state, perform branch actions (if any). */
2432 if (! map->submaps || map != ic_info->map)
2434 if (map->branch_actions)
2436 MDEBUG_PRINT (" branch-actions:");
2437 if (take_action_list (ic, map->branch_actions) < 0)
2439 MDEBUG_PRINT ("\n");
2443 /* If MAP is still not the root map, shift to the current
2445 if (ic_info->map != ic_info->state->map)
2446 shift_state (ic, ic_info->state->name);
2451 /* MAP can not handle KEY. */
2453 /* If MAP is the root map of the initial state, it means that
2454 the current input method can not handle KEY. */
2455 if (map == ((MIMState *) MPLIST_VAL (im_info->states))->map)
2457 MDEBUG_PRINT (" unhandled\n");
2461 if (map != ic_info->state->map)
2463 /* If MAP is not the root map... */
2464 /* If MAP has branch actions, perform them. */
2465 if (map->branch_actions)
2467 MDEBUG_PRINT (" branch-actions:");
2468 if (take_action_list (ic, map->branch_actions) < 0)
2470 MDEBUG_PRINT ("\n");
2474 /* If MAP is still not the root map, shift to the current
2476 if (ic_info->map != ic_info->state->map)
2478 shift_state (ic, ic_info->state->name);
2479 /* If MAP has branch_actions, perform them. */
2480 if (ic_info->map->branch_actions)
2482 MDEBUG_PRINT (" brank-actions:");
2483 if (take_action_list (ic, ic_info->map->branch_actions) < 0)
2490 /* MAP is the root map, perform branch actions (if any) or
2491 shift to the initial state. */
2492 if (map->branch_actions)
2494 MDEBUG_PRINT (" branch-actions:");
2495 if (take_action_list (ic, map->branch_actions) < 0)
2497 MDEBUG_PRINT ("\n");
2502 shift_state (ic, Mnil);
2505 MDEBUG_PRINT ("\n");
2510 reset_ic (MInputContext *ic, MSymbol ignore)
2512 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
2513 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
2516 MDEBUG_PRINT ("\n [IM] reset\n");
2518 ic_info->state = (MIMState *) MPLIST_VAL (im_info->states);
2519 ic_info->prev_state = NULL;
2520 ic_info->map = ic_info->state->map;
2521 ic_info->state_key_head = ic_info->key_head;
2522 MLIST_RESET (ic_info);
2523 ic_info->key_unhandled = 0;
2525 if (mtext_nchars (ic->produced) > 0)
2526 mtext_reset (ic->produced);
2527 if (mtext_nchars (ic->preedit) > 0)
2531 mtext_reset (ic->preedit);
2532 MPLIST_DO (plist, ic_info->markers)
2533 MPLIST_VAL (plist) = 0;
2534 ic->preedit_changed = 1;
2536 if (ic->candidate_show)
2538 ic->candidate_show = 0;
2539 ic->candidates_changed = MINPUT_CANDIDATES_SHOW_CHANGED;
2540 if (ic->candidate_list)
2542 M17N_OBJECT_UNREF (ic->candidate_list);
2543 ic->candidate_list = NULL;
2544 ic->candidates_changed |= MINPUT_CANDIDATES_LIST_CHANGED;
2547 mtext_reset (ic_info->preedit_saved);
2548 ic_info->state_pos = ic->cursor_pos = 0;
2550 status = ic_info->state->title ? ic_info->state->title : im_info->title;
2551 if (ic->status != status)
2553 ic->status = status;
2554 ic->status_changed = 1;
2559 open_im (MInputMethod *im)
2561 MInputMethodInfo *im_info = get_im_info (im->language, im->name, Mnil);
2564 MERROR (MERROR_IM, -1);
2571 close_im (MInputMethod *im)
2577 create_ic (MInputContext *ic)
2579 MInputMethod *im = ic->im;
2580 MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
2581 MInputContextInfo *ic_info;
2585 ic_info = (MInputContextInfo *) ic->info;
2588 MSTRUCT_CALLOC (ic_info, MERROR_IM);
2591 MLIST_INIT1 (ic_info, keys, 8);
2592 ic_info->markers = mplist ();
2593 ic_info->vars = mplist ();
2594 plist = get_nested_list (im->language, im->name, Mnil, M_variable);
2595 MPLIST_DO (plist, plist)
2597 MSymbol var = MPLIST_SYMBOL (plist);
2600 plist = MPLIST_NEXT (plist);
2601 pl = MPLIST_PLIST (plist);
2602 pl = MPLIST_NEXT (pl); /* Skip description. */
2603 mplist_push (ic_info->vars, MPLIST_KEY (pl), MPLIST_VAL (pl));
2604 mplist_push (ic_info->vars, Msymbol, var);
2607 ic_info->preedit_saved = mtext ();
2608 if (im_info->externals)
2610 MPlist *func_args = mplist (), *plist;
2612 mplist_add (func_args, Mt, ic);
2613 MPLIST_DO (plist, im_info->externals)
2615 MIMExternalModule *external = MPLIST_VAL (plist);
2616 MIMExternalFunc func
2617 = (MIMExternalFunc) mplist_get (external->func_list, Minit);
2622 M17N_OBJECT_UNREF (func_args);
2624 reset_ic (ic, Mnil);
2629 destroy_ic (MInputContext *ic)
2631 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
2632 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
2634 if (im_info->externals)
2636 MPlist *func_args = mplist (), *plist;
2638 mplist_add (func_args, Mt, ic);
2639 MPLIST_DO (plist, im_info->externals)
2641 MIMExternalModule *external = MPLIST_VAL (plist);
2642 MIMExternalFunc func
2643 = (MIMExternalFunc) mplist_get (external->func_list, Mfini);
2648 M17N_OBJECT_UNREF (func_args);
2650 MLIST_FREE1 (ic_info, keys);
2651 M17N_OBJECT_UNREF (ic_info->preedit_saved);
2652 M17N_OBJECT_UNREF (ic_info->markers);
2653 M17N_OBJECT_UNREF (ic_info->vars);
2654 M17N_OBJECT_UNREF (ic_info->preceding_text);
2655 M17N_OBJECT_UNREF (ic_info->following_text);
2660 /** Handle the input key KEY in the current state and map of IC->info.
2661 If KEY is handled but no text is produced, return 0, otherwise
2667 filter (MInputContext *ic, MSymbol key, void *arg)
2669 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
2670 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
2673 if (! ic_info->state)
2675 ic_info->key_unhandled = 1;
2678 mtext_reset (ic->produced);
2679 ic->status_changed = ic->preedit_changed = ic->candidates_changed = 0;
2680 M17N_OBJECT_UNREF (ic_info->preceding_text);
2681 M17N_OBJECT_UNREF (ic_info->following_text);
2682 MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
2683 ic_info->key_unhandled = 0;
2685 /* If KEY has Meta or Alt modifier, put M_key_alias property. */
2686 if (! msymbol_get (key, M_key_alias)
2687 && (strchr (MSYMBOL_NAME (key), 'M')
2688 || strchr (MSYMBOL_NAME (key), 'A')))
2690 char *name = MSYMBOL_NAME (key);
2693 while (name[0] && name[1] == '-'
2694 && (name[0] != 'M' && name[0] != 'A'))
2696 if ((name[0] == 'M' || name[0] == 'A') && name[1] == '-')
2701 name = alloca (MSYMBOL_NAMELEN (key) + 1);
2702 memcpy (name, MSYMBOL_NAME (key), MSYMBOL_NAMELEN (key) + 1);
2703 name[meta_or_alt - MSYMBOL_NAME (key)]
2704 = *meta_or_alt == 'M' ? 'A' : 'M';
2705 alias = msymbol (name);
2706 msymbol_put (key, M_key_alias, alias);
2709 else if (MSYMBOL_NAME (key)[0] == 'S'
2710 && MSYMBOL_NAME (key)[1] == '-'
2711 && MSYMBOL_NAME (key)[2] >= 'A' && MSYMBOL_NAME (key)[2] <= 'Z')
2712 msymbol_put (key, M_key_alias, one_char_symbol[(int)MSYMBOL_NAME (key)[2]]);
2715 if (handle_key (ic) < 0)
2717 /* KEY was not handled. Delete it from the current key sequence. */
2718 if (ic_info->used > 0)
2720 memmove (ic_info->keys, ic_info->keys + 1,
2721 sizeof (int) * (ic_info->used - 1));
2724 /* This forces returning 1. */
2725 ic_info->key_unhandled = 1;
2731 reset_ic (ic, Mnil);
2732 ic_info->key_unhandled = 1;
2735 /* Break the loop if all keys were handled. */
2736 } while (ic_info->key_head < ic_info->used);
2738 /* If the current map is the root of the initial state, we should
2739 produce any preedit text in ic->produced. */
2740 if (ic_info->map == ((MIMState *) MPLIST_VAL (im_info->states))->map
2741 && mtext_nchars (ic->preedit) > 0)
2742 shift_state (ic, ((MIMState *) MPLIST_VAL (im_info->states))->name);
2744 if (mtext_nchars (ic->produced) > 0)
2746 MSymbol lang = msymbol_get (ic->im->language, Mlanguage);
2749 mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
2750 Mlanguage, ic->im->language);
2753 return (! ic_info->key_unhandled && mtext_nchars (ic->produced) == 0);
2757 /** Return 1 if the last event or key was not handled, otherwise
2760 There is no need of looking up because ic->produced should already
2761 contain the produced text (if any).
2766 lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2768 mtext_cat (mt, ic->produced);
2769 mtext_reset (ic->produced);
2770 return (((MInputContextInfo *) ic->info)->key_unhandled ? -1 : 0);
2773 static MPlist *load_im_info_keys;
2776 load_partial_im_info (MSymbol language, MSymbol name,
2777 MSymbol extra, MSymbol key)
2782 if (language == Mnil)
2783 MERROR (MERROR_IM, NULL);
2784 mdb = mdatabase_find (Minput_method, language, name, extra);
2786 MERROR (MERROR_IM, NULL);
2788 mplist_push (load_im_info_keys, key, Mt);
2789 plist = mdatabase__load_for_keys (mdb, load_im_info_keys);
2790 mplist_pop (load_im_info_keys);
2795 static MInputMethodInfo *
2796 get_im_info (MSymbol language, MSymbol name, MSymbol extra)
2800 MInputMethodInfo *im_info = NULL;
2802 if (language == Mnil)
2803 MERROR (MERROR_IM, NULL);
2804 mdb = mdatabase_find (Minput_method, language, name, extra);
2806 MERROR (MERROR_IM, NULL);
2809 im_info_list = mplist ();
2810 else if ((plist = mplist_find_by_value (im_info_list, mdb)))
2812 if (mdatabase__check (mdb))
2814 plist = MPLIST_NEXT (plist);
2815 im_info = MPLIST_VAL (plist);
2819 free_im_info (MPLIST_VAL (plist));
2823 plist = mdatabase_load (mdb);
2825 MERROR (MERROR_IM, NULL);
2826 im_info = load_im_info (language, name, plist);
2827 M17N_OBJECT_UNREF (plist);
2829 MERROR (MERROR_IM, NULL);
2830 mplist_push (im_info_list, Mt, im_info);
2831 mplist_push (im_info_list, Mt, mdb);
2836 /* Input method command handler. */
2838 /* List of all (global and local) commands.
2839 (LANG:(IM-NAME:(COMMAND ...) ...) ...) ...
2840 COMMAND is CMD-NAME:(mtext:DESCRIPTION plist:KEYSEQ ...))
2841 Global commands are storead as (t (t COMMAND ...)) */
2843 /* Check if PLIST is a valid command key sequence.
2844 PLIST must be NULL or:
2845 [ symbol:KEY | integer:KEY ] ... */
2848 check_command_keyseq (MPlist *plist)
2852 MPLIST_DO (plist, plist)
2854 if (MPLIST_SYMBOL_P (plist))
2856 else if (MPLIST_INTEGER_P (plist))
2858 int n = MPLIST_INTEGER (plist);
2862 MPLIST_KEY (plist) = Msymbol;
2863 MPLIST_VAL (plist) = one_char_symbol['0' + 9];
2871 /* Check if PLIST has this form:
2872 ([ plist:([ symbol:KEY | integer:KEY ]) | mtext:KEYSEQ ]
2874 If the form of PLIST matches, return 0, otherwise return -1. */
2877 check_command_list (MPlist *plist)
2879 MPLIST_DO (plist, plist)
2881 if (MPLIST_PLIST_P (plist))
2883 MPlist *pl = MPLIST_PLIST (plist);
2886 if (! MPLIST_SYMBOL_P (pl) && ! MPLIST_INTEGER_P (pl))
2889 else if (! MPLIST_MTEXT_P (plist))
2897 /* Input method variable handler. */
2899 /* Check if PLIST has this form:
2900 (TYPE:VAL ;; TYPE ::= integer | mtext | symbol
2903 If the form of PLIST matches, return 0, otherwise return -1. */
2906 check_variable_list (MPlist *plist)
2908 MSymbol type = MPLIST_KEY (plist);
2911 if (type != Minteger && type != Mtext && type != Msymbol)
2913 MPLIST_DO (plist, MPLIST_NEXT (plist))
2915 if (type == Minteger && MPLIST_PLIST_P (plist))
2917 MPLIST_DO (p, MPLIST_PLIST (plist))
2918 if (! MPLIST_INTEGER_P (p))
2921 else if (type != MPLIST_KEY (plist))
2927 /* Support functions for mdebug_dump_im. */
2930 dump_im_map (MPlist *map_list, int indent)
2933 MSymbol key = MPLIST_KEY (map_list);
2934 MIMMap *map = (MIMMap *) MPLIST_VAL (map_list);
2936 prefix = (char *) alloca (indent + 1);
2937 memset (prefix, 32, indent);
2938 prefix[indent] = '\0';
2940 fprintf (stderr, "(\"%s\" ", msymbol_name (key));
2941 if (map->map_actions)
2942 mdebug_dump_plist (map->map_actions, indent + 2);
2945 MPLIST_DO (map_list, map->submaps)
2947 fprintf (stderr, "\n%s ", prefix);
2948 dump_im_map (map_list, indent + 2);
2951 if (map->branch_actions)
2953 fprintf (stderr, "\n%s (branch\n%s ", prefix, prefix);
2954 mdebug_dump_plist (map->branch_actions, indent + 4);
2955 fprintf (stderr, ")");
2957 fprintf (stderr, ")");
2962 dump_im_state (MIMState *state, int indent)
2967 prefix = (char *) alloca (indent + 1);
2968 memset (prefix, 32, indent);
2969 prefix[indent] = '\0';
2971 fprintf (stderr, "(%s", msymbol_name (state->name));
2972 if (state->map->submaps)
2974 MPLIST_DO (map_list, state->map->submaps)
2976 fprintf (stderr, "\n%s ", prefix);
2977 dump_im_map (map_list, indent + 2);
2980 fprintf (stderr, ")");
2989 = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2990 "BackSpace", "Tab", "Linefeed", "Clear", NULL, "Return", NULL, NULL,
2991 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2992 NULL, NULL, NULL, "Escape", NULL, NULL, NULL, NULL };
2993 char buf[6], buf2[256];
2997 Minput_method = msymbol ("input-method");
2998 Minput_driver = msymbol ("input-driver");
2999 Mtitle = msymbol ("title");
3000 Mmacro = msymbol ("macro");
3001 Mmodule = msymbol ("module");
3002 Mmap = msymbol ("map");
3003 Mstate = msymbol ("state");
3004 Minclude = msymbol ("include");
3005 Minsert = msymbol ("insert");
3006 M_candidates = msymbol (" candidates");
3007 Mdelete = msymbol ("delete");
3008 Mmove = msymbol ("move");
3009 Mmark = msymbol ("mark");
3010 Mpushback = msymbol ("pushback");
3011 Mundo = msymbol ("undo");
3012 Mcall = msymbol ("call");
3013 Mshift = msymbol ("shift");
3014 Mselect = msymbol ("select");
3015 Mshow = msymbol ("show");
3016 Mhide = msymbol ("hide");
3017 Mcommit = msymbol ("commit");
3018 Munhandle = msymbol ("unhandle");
3019 Mset = msymbol ("set");
3020 Madd = msymbol ("add");
3021 Msub = msymbol ("sub");
3022 Mmul = msymbol ("mul");
3023 Mdiv = msymbol ("div");
3024 Mequal = msymbol ("=");
3025 Mless = msymbol ("<");
3026 Mgreater = msymbol (">");
3027 Mless_equal = msymbol ("<=");
3028 Mgreater_equal = msymbol (">=");
3029 Mcond = msymbol ("cond");
3030 Mplus = msymbol ("+");
3031 Mminus = msymbol ("-");
3032 Mstar = msymbol ("*");
3033 Mslush = msymbol ("/");
3034 Mand = msymbol ("&");
3035 Mor = msymbol ("|");
3036 Mnot = msymbol ("!");
3038 Mcandidates_group_size = msymbol ("candidates-group-size");
3039 Mcandidates_charset = msymbol ("candidates-charset");
3041 Minput_preedit_start = msymbol ("input-preedit-start");
3042 Minput_preedit_done = msymbol ("input-preedit-done");
3043 Minput_preedit_draw = msymbol ("input-preedit-draw");
3044 Minput_status_start = msymbol ("input-status-start");
3045 Minput_status_done = msymbol ("input-status-done");
3046 Minput_status_draw = msymbol ("input-status-draw");
3047 Minput_candidates_start = msymbol ("input-candidates-start");
3048 Minput_candidates_done = msymbol ("input-candidates-done");
3049 Minput_candidates_draw = msymbol ("input-candidates-draw");
3050 Minput_set_spot = msymbol ("input-set-spot");
3051 Minput_focus_move = msymbol ("input-focus-move");
3052 Minput_focus_in = msymbol ("input-focus-in");
3053 Minput_focus_out = msymbol ("input-focus-out");
3054 Minput_toggle = msymbol ("input-toggle");
3055 Minput_reset = msymbol ("input-reset");
3056 Minput_get_surrounding_text = msymbol ("input-get-surrounding-text");
3057 Minput_delete_surrounding_text = msymbol ("input-delete-surrounding-text");
3059 Mcandidate_list = msymbol_as_managing_key (" candidate-list");
3060 Mcandidate_index = msymbol (" candidate-index");
3062 Minit = msymbol ("init");
3063 Mfini = msymbol ("fini");
3065 M_key_alias = msymbol (" key-alias");
3066 M_description = msymbol ("description");
3067 M_command = msymbol ("command");
3068 M_variable = msymbol ("variable");
3070 load_im_info_keys = mplist ();
3071 plist = mplist_add (load_im_info_keys, Mstate, Mnil);
3076 for (i = 0, buf[2] = '@'; i < ' '; i++, buf[2]++)
3080 one_char_symbol[i] = msymbol (buf);
3083 alias = msymbol (key_names[i]);
3084 msymbol_put (one_char_symbol[i], M_key_alias, alias);
3087 alias = one_char_symbol[i];
3088 buf[2] += (i == 0) ? -32 : 32;
3089 msymbol_put (alias, M_key_alias, msymbol (buf));
3090 buf[2] -= (i == 0) ? -32 : 32;
3092 for (buf[2] = i; i < 127; i++, buf[2]++)
3093 one_char_symbol[i] = msymbol (buf + 2);
3094 one_char_symbol[i++] = msymbol ("Delete");
3100 for (buf[4] = '@'; i < 160; i++, buf[4]++)
3102 one_char_symbol[i] = msymbol (buf);
3103 if (key_names[i - 128])
3105 strcpy (buf2 + 2, key_names[i - 128]);
3106 msymbol_put (one_char_symbol[i], M_key_alias, msymbol (buf2));
3109 for (buf[4] = i - 128; i < 255; i++, buf[4]++)
3110 one_char_symbol[i] = msymbol (buf + 2);
3111 one_char_symbol[i] = msymbol ("M-Delete");
3113 command_list = variable_list = NULL;
3115 minput_default_driver.open_im = open_im;
3116 minput_default_driver.close_im = close_im;
3117 minput_default_driver.create_ic = create_ic;
3118 minput_default_driver.destroy_ic = destroy_ic;
3119 minput_default_driver.filter = filter;
3120 minput_default_driver.lookup = lookup;
3121 minput_default_driver.callback_list = mplist ();
3122 mplist_put (minput_default_driver.callback_list, Minput_reset,
3124 minput_driver = &minput_default_driver;
3133 M17N_OBJECT_UNREF (command_list);
3134 command_list = NULL;
3138 M17N_OBJECT_UNREF (variable_list);
3139 variable_list = NULL;
3142 if (minput_default_driver.callback_list)
3144 M17N_OBJECT_UNREF (minput_default_driver.callback_list);
3145 minput_default_driver.callback_list = NULL;
3147 if (minput_driver->callback_list)
3149 M17N_OBJECT_UNREF (minput_driver->callback_list);
3150 minput_driver->callback_list = NULL;
3155 while (! MPLIST_TAIL_P (im_info_list))
3158 mplist_pop (im_info_list);
3159 free_im_info ((MInputMethodInfo *) MPLIST_VAL (im_info_list));
3160 /* Pop (t . im_info) */
3161 mplist_pop (im_info_list);
3163 M17N_OBJECT_UNREF (im_info_list);
3164 im_info_list = NULL;
3167 M17N_OBJECT_UNREF (load_im_info_keys);
3171 minput__callback (MInputContext *ic, MSymbol command)
3173 if (ic->im->driver.callback_list)
3175 MInputCallbackFunc func
3176 = (MInputCallbackFunc) mplist_get (ic->im->driver.callback_list,
3180 (func) (ic, command);
3185 minput__char_to_key (int c)
3187 if (c < 0 || c >= 0x100)
3190 return one_char_symbol[c];
3194 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
3199 /*** @addtogroup m17nInputMethod */
3204 @name Variables: Predefined symbols for callback commands.
3206 These are the predefined symbols that are used as the @c COMMAND
3207 argument of callback functions of an input method driver (see
3208 #MInputDriver::callback_list ).
3210 Most of them don't require extra argument nor return any value;
3211 exceptions are these:
3213 Minput_get_surrounding_text: When a callback function assigned for
3214 this command is called, the first element of #MInputContext::plist
3215 has key #Msymbol and the value specifies which portion of the
3216 surrounding text should be retrieved. If the value is positive,
3217 it specifies the number of characters following the current cursor
3218 position. If the value is negative, the absolute value specifies
3219 the number of characters preceding the current cursor position.
3220 The callback function must set the key of this element to #Mtext
3221 and the value to the retrived M-text (whose length may be shorter
3222 than the requested number of characters if the available text is
3223 not that long, or it may be longer if an application thinks it's
3224 more efficient to return that length).
3226 Minput_delete_surrounding_text: When a callback function assigned
3227 for this command is called, the first element of
3228 #MInputContext::plist has key #Msymbol and the value specifies
3229 which portion of the surrounding text should be deleted in the
3230 same way as the case of Minput_get_surrounding_text. The callback
3231 function must delete the specified text. It should not alter
3232 #MInputContext::plist. */
3235 @name ÊÑ¿ô¡§ ¥³¡¼¥ë¥Ð¥Ã¥¯¥³¥Þ¥ó¥ÉÍÑÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë.
3237 ÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Î¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Ë¤ª¤¤¤Æ @c COMMAND
3238 °ú¿ô¤È¤·¤ÆÍѤ¤¤é¤ì¤ëÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë (#MInputDriver::callback_list »²¾È)¡£
3243 MSymbol Minput_preedit_start;
3244 MSymbol Minput_preedit_done;
3245 MSymbol Minput_preedit_draw;
3246 MSymbol Minput_status_start;
3247 MSymbol Minput_status_done;
3248 MSymbol Minput_status_draw;
3249 MSymbol Minput_candidates_start;
3250 MSymbol Minput_candidates_done;
3251 MSymbol Minput_candidates_draw;
3252 MSymbol Minput_set_spot;
3253 MSymbol Minput_toggle;
3254 MSymbol Minput_reset;
3255 MSymbol Minput_get_surrounding_text;
3256 MSymbol Minput_delete_surrounding_text;
3262 @name Variables: Predefined symbols for special input events.
3264 These are the predefined symbols that are used as the @c KEY
3265 argument of minput_filter (). */
3270 MSymbol Minput_focus_out;
3271 MSymbol Minput_focus_in;
3272 MSymbol Minput_focus_move;
3279 @brief The default driver for internal input methods.
3281 The variable #minput_default_driver is the default driver for
3282 internal input methods.
3284 The member MInputDriver::open_im () searches the m17n database for
3285 an input method that matches the tag \< #Minput_method, $LANGUAGE,
3286 $NAME\> and loads it.
3288 The member MInputDriver::callback_list () is @c NULL. Thus, it is
3289 programmers responsibility to set it to a plist of proper callback
3290 functions. Otherwise, no feedback information (e.g. preedit text)
3291 can be shown to users.
3293 The macro M17N_INIT () sets the variable #minput_driver to the
3294 pointer to this driver so that all internal input methods use it.
3296 Therefore, unless @c minput_driver is set differently, the driver
3297 dependent arguments $ARG of the functions whose name begin with
3298 "minput_" are all ignored. */
3301 @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥǥե©¥ë¥È¥É¥é¥¤¥Ð.
3303 ÊÑ¿ô #minput_default_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѤΥǥե©¥ë¥È¤Î¥É¥é¥¤¥Ð¤òɽ¤¹¡£
3305 ¥á¥ó¥Ð MInputDriver::open_im () ¤Ï m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹Ã椫¤é¥¿¥°
3306 \< #Minput_method, $LANGUAGE, $NAME\>
3307 ¤Ë¹çÃפ¹¤ëÆþÎϥ᥽¥Ã¥É¤òõ¤·¡¢¤½¤ì¤ò¥í¡¼¥É¤¹¤ë¡£
3309 ¥á¥ó¥Ð MInputDriver::callback_list () ¤Ï @c NULL ¤Ç¤¢¤ê¡¢
3310 ¤·¤¿¤¬¤Ã¤Æ¡¢¥×¥í¥°¥é¥Þ¦¤ÇÀÕǤ¤ò»ý¤Ã¤Æ ŬÀڤʥ³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Î plist
3311 ¤ËÀßÄꤷ¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¤µ¤â¤Ê¤¤¤È¡¢preedit
3312 ¥Æ¥¥¹¥È¤Ê¤É¤Î¥Õ¥£¡¼¥É¥Ð¥Ã¥¯¾ðÊ󤬥桼¥¶¤Ëɽ¼¨¤µ¤ì¤Ê¤¤¡£
3314 ¥Þ¥¯¥í M17N_INIT () ¤ÏÊÑ¿ô #minput_driver
3315 ¤ò¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤ËÀßÄꤷ¡¢Á´¤Æ¤ÎÆâÉôÆþÎϥ᥽¥Ã¥É¤¬¤³¤Î¥É¥é¥¤¥Ð¤ò»È¤¦¤è¤¦¤Ë¤¹¤ë¡£
3317 ¤·¤¿¤¬¤Ã¤Æ¡¢@c minput_driver ¤¬¥Ç¥Õ¥©¥ë¥ÈÃͤΤޤޤǤ¢¤ì¤Ð¡¢minput_
3318 ¤Ç»Ï¤Þ¤ë´Ø¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô $ARG ¤Ï¤¹¤Ù¤Æ̵»ë¤µ¤ì¤ë¡£ */
3320 MInputDriver minput_default_driver;
3324 @brief The driver for internal input methods.
3326 The variable #minput_driver is a pointer to the input method
3327 driver that is used by internal input methods. The macro
3328 M17N_INIT () initializes it to a pointer to #minput_default_driver
3329 if <m17n<EM></EM>.h> is included. */
3331 @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥɥ饤¥Ð.
3333 ÊÑ¿ô #minput_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤Æ»ÈÍѤµ¤ì¤Æ¤¤¤ëÆþÎÏ¥á
3334 ¥½¥Ã¥É¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£¥Þ¥¯¥í M17N_INIT () ¤Ï¤³¤Î¥Ý¥¤¥ó
3335 ¥¿¤ò#minput_default_driver (<m17n<EM></EM>.h> ¤¬ include ¤µ¤ì¤Æ¤¤¤ë
3336 »þ) ¤Ë½é´ü²½¤¹¤ë¡£ */
3338 MInputDriver *minput_driver;
3340 MSymbol Minput_driver;
3345 @brief Open an input method.
3347 The minput_open_im () function opens an input method that matches
3348 language $LANGUAGE and name $NAME, and returns a pointer to the
3349 input method object newly allocated.
3351 This function at first decides an driver for the input method as
3354 If $LANGUAGE is not #Mnil, the driver pointed by the variable
3355 #minput_driver is used.
3357 If $LANGUAGE is #Mnil and $NAME has #Minput_driver property, the
3358 driver pointed to by the property value is used to open the input
3359 method. If $NAME has no such property, @c NULL is returned.
3361 Then, the member MInputDriver::open_im () of the driver is
3364 $ARG is set in the member @c arg of the structure MInputMethod so
3365 that the driver can refer to it. */
3368 @brief ÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë.
3370 ´Ø¿ô minput_open_im () ¤Ï¸À¸ì $LANGUAGE ¤È̾Á° $NAME
3371 ¤Ë¹çÃפ¹¤ëÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤·¡¢¿·¤¿¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿ÆþÎϥ᥽¥Ã¥É¥ª¥Ö¥¸¥§¥¯¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
3373 ¤³¤Î´Ø¿ô¤Ï¡¢¤Þ¤ºÆþÎϥ᥽¥Ã¥ÉÍѤΥɥ饤¥Ð¤ò°Ê²¼¤Î¤è¤¦¤Ë¤·¤Æ·èÄꤹ¤ë¡£
3375 $LANGUAGE ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢ÊÑ¿ô #minput_driver
3376 ¤Ç»Ø¤µ¤ì¤Æ¤¤¤ë¥É¥é¥¤¥Ð¤òÍѤ¤¤ë¡£
3378 $LANGUAGE ¤¬ #Mnil ¤Ç¤¢¤ê¡¢$NAME ¤¬ #Minput_driver
3379 ¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä¾ì¹ç¤Ë¤Ï¡¢¤½¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤǻؤµ¤ì¤Æ¤¤¤ëÆþÎϥɥ饤¥Ð¤òÍѤ¤¤ÆÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë¡£
3380 $NAME ¤Ë¤½¤Î¤è¤¦¤Ê¥×¥í¥Ñ¥Æ¥£¤¬Ìµ¤«¤Ã¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
3382 ¼¡¤¤¤Ç¡¢¥É¥é¥¤¥Ð¤Î¥á¥ó¥Ð MInputDriver::open_im () ¤¬¸Æ¤Ð¤ì¤ë¡£
3384 $ARG ¤Ï¹½Â¤ÂÎ MInputMethod ¤Î¥á¥ó¥Ð @c arg ¤ËÀßÄꤵ¤ì¡¢¥É¥é¥¤¥Ð¤«¤é»²¾È¤Ç¤¤ë¡£
3386 @latexonly \IPAlabel{minput_open} @endlatexonly
3391 minput_open_im (MSymbol language, MSymbol name, void *arg)
3394 MInputDriver *driver;
3396 MDEBUG_PRINT2 (" [IM] opening (%s %s) ... ",
3397 msymbol_name (language), msymbol_name (name));
3399 driver = minput_driver;
3402 driver = (MInputDriver *) msymbol_get (name, Minput_driver);
3404 MERROR (MERROR_IM, NULL);
3407 MSTRUCT_CALLOC (im, MERROR_IM);
3408 im->language = language;
3411 im->driver = *driver;
3412 if ((*im->driver.open_im) (im) < 0)
3414 MDEBUG_PRINT (" failed\n");
3418 MDEBUG_PRINT (" ok\n");
3425 @brief Close an input method.
3427 The minput_close_im () function closes the input method $IM, which
3428 must have been created by minput_open_im (). */
3431 @brief ÆþÎϥ᥽¥Ã¥É¤ò¥¯¥í¡¼¥º¤¹¤ë.
3433 ´Ø¿ô minput_close_im () ¤Ï¡¢ÆþÎϥ᥽¥Ã¥É $IM ¤ò¥¯¥í¡¼¥º¤¹¤ë¡£
3434 ¤³¤ÎÆþÎϥ᥽¥Ã¥É $IM ¤Ï minput_open_im () ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£ */
3437 minput_close_im (MInputMethod *im)
3439 MDEBUG_PRINT2 (" [IM] closing (%s %s) ... ",
3440 msymbol_name (im->name), msymbol_name (im->language));
3441 (*im->driver.close_im) (im);
3443 MDEBUG_PRINT (" done\n");
3449 @brief Create an input context.
3451 The minput_create_ic () function creates an input context object
3452 associated with input method $IM, and calls callback functions
3453 corresponding to #Minput_preedit_start, #Minput_status_start, and
3454 #Minput_status_draw in this order.
3457 If an input context is successfully created, minput_create_ic ()
3458 returns a pointer to it. Otherwise it returns @c NULL. */
3461 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÀ¸À®¤¹¤ë.
3463 ´Ø¿ô minput_create_ic () ¤ÏÆþÎϥ᥽¥Ã¥É $IM
3464 ¤ËÂбþ¤¹¤ëÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤·¡¢
3465 #Minput_preedit_start, #Minput_status_start, #Minput_status_draw
3466 ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¤³¤Î½ç¤Ë¸Æ¤Ö¡£
3469 ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤¬À¸À®¤µ¤ì¤¿¾ì¹ç¡¢minput_create_ic ()
3470 ¤Ï¤½¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¼ºÇÔ¤·¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
3474 minput_create_ic (MInputMethod *im, void *arg)
3478 MDEBUG_PRINT2 (" [IM] creating context (%s %s) ... ",
3479 msymbol_name (im->name), msymbol_name (im->language));
3480 MSTRUCT_CALLOC (ic, MERROR_IM);
3483 ic->preedit = mtext ();
3484 ic->candidate_list = NULL;
3485 ic->produced = mtext ();
3486 ic->spot.x = ic->spot.y = 0;
3488 ic->plist = mplist ();
3489 if ((*im->driver.create_ic) (ic) < 0)
3491 MDEBUG_PRINT (" failed\n");
3492 M17N_OBJECT_UNREF (ic->preedit);
3493 M17N_OBJECT_UNREF (ic->produced);
3494 M17N_OBJECT_UNREF (ic->plist);
3499 if (im->driver.callback_list)
3501 minput__callback (ic, Minput_preedit_start);
3502 minput__callback (ic, Minput_status_start);
3503 minput__callback (ic, Minput_status_draw);
3506 MDEBUG_PRINT (" ok\n");
3513 @brief Destroy an input context.
3515 The minput_destroy_ic () function destroys the input context $IC,
3516 which must have been created by minput_create_ic (). It calls
3517 callback functions corresponding to #Minput_preedit_done,
3518 #Minput_status_done, and #Minput_candidates_done in this order. */
3521 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÇ˲õ¤¹¤ë.
3523 ´Ø¿ô minput_destroy_ic () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤òÇ˲õ¤¹¤ë¡£
3524 ¤³¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ï minput_create_ic ()
3525 ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£¤³¤Î´Ø¿ô¤Ï
3526 #Minput_preedit_done, #Minput_status_done, #Minput_candidates_done
3527 ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¤³¤Î½ç¤Ë¸Æ¤Ö¡£
3531 minput_destroy_ic (MInputContext *ic)
3533 MDEBUG_PRINT2 (" [IM] destroying context (%s %s) ... ",
3534 msymbol_name (ic->im->name), msymbol_name (ic->im->language));
3535 if (ic->im->driver.callback_list)
3537 minput__callback (ic, Minput_preedit_done);
3538 minput__callback (ic, Minput_status_done);
3539 minput__callback (ic, Minput_candidates_done);
3541 (*ic->im->driver.destroy_ic) (ic);
3542 M17N_OBJECT_UNREF (ic->preedit);
3543 M17N_OBJECT_UNREF (ic->produced);
3544 M17N_OBJECT_UNREF (ic->plist);
3545 MDEBUG_PRINT (" done\n");
3552 @brief Filter an input key.
3554 The minput_filter () function filters input key $KEY according to
3555 input context $IC, and calls callback functions corresponding to
3556 #Minput_preedit_draw, #Minput_status_draw, and
3557 #Minput_candidates_draw if the preedit text, the status, and the
3558 current candidate are changed respectively.
3560 To make the input method commit the current preedit text (if any)
3561 and shift to the initial state, call this function with #Mnil as
3564 To inform the input method about the focus-out event, call this
3565 function with #Minput_focus_out as $KEY.
3567 To inform the input method about the focus-in event, call this
3568 function with #Minput_focus_in as $KEY.
3570 To inform the input method about the focus-move event (i.e. input
3571 spot change within the same input context), call this function
3572 with #Minput_focus_move as $KEY.
3575 If $KEY is filtered out, this function returns 1. In that case,
3576 the caller should discard the key. Otherwise, it returns 0, and
3577 the caller should handle the key, for instance, by calling the
3578 function minput_lookup () with the same key. */
3581 @brief ÆþÎÏ¥¡¼¤ò¥Õ¥£¥ë¥¿¤¹¤ë.
3583 ´Ø¿ô minput_filter () ¤ÏÆþÎÏ¥¡¼ $KEY ¤òÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC
3584 ¤Ë±þ¤¸¤Æ¥Õ¥£¥ë¥¿¤·¡¢preedit ¥Æ¥¥¹¥È¡¢¥¹¥Æ¡¼¥¿¥¹¡¢¸½»þÅÀ¤Ç¤Î¸õÊ䤬ÊѲ½¤·¤¿»þÅÀ¤Ç¡¢¤½¤ì¤¾¤ì
3585 #Minput_preedit_draw, #Minput_status_draw,
3586 #Minput_candidates_draw ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¸Æ¤Ö¡£
3589 $KEY ¤¬¥Õ¥£¥ë¥¿¤µ¤ì¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 1 ¤òÊÖ¤¹¡£
3590 ¤³¤Î¾ì¹ç¸Æ¤Ó½Ð¤·Â¦¤Ï¤³¤Î¥¡¼¤ò¼Î¤Æ¤ë¤Ù¤¤Ç¤¢¤ë¡£
3591 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0 ¤òÊÖ¤·¡¢¸Æ¤Ó½Ð¤·Â¦¤Ï¡¢¤¿¤È¤¨¤ÐƱ¤¸¥¡¼¤Ç´Ø¿ô minput_lookup ()
3592 ¤ò¸Æ¤Ö¤Ê¤É¤·¤Æ¡¢¤³¤Î¥¡¼¤ò½èÍý¤¹¤ë¡£
3594 @latexonly \IPAlabel{minput_filter} @endlatexonly
3598 minput_filter (MInputContext *ic, MSymbol key, void *arg)
3605 ret = (*ic->im->driver.filter) (ic, key, arg);
3607 if (ic->im->driver.callback_list)
3609 if (ic->preedit_changed)
3610 minput__callback (ic, Minput_preedit_draw);
3611 if (ic->status_changed)
3612 minput__callback (ic, Minput_status_draw);
3613 if (ic->candidates_changed)
3614 minput__callback (ic, Minput_candidates_draw);
3623 @brief Look up a text produced in the input context.
3625 The minput_lookup () function looks up a text in the input context
3626 $IC. $KEY must be the same one provided to the previous call of
3629 If a text was produced by the input method, it is concatenated
3632 This function calls #MInputDriver::lookup .
3635 If $KEY was correctly handled by the input method, this function
3636 returns 0. Otherwise, returns -1, even in that case, some text
3637 may be produced in $MT. */
3640 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥ÈÃæ¤Î¥Æ¥¥¹¥È¤òõ¤¹.
3642 ´Ø¿ô minput_lookup () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC Ãæ¤Î¥Æ¥¥¹¥È¤òõ¤¹¡£
3643 $KEY ¤Ï´Ø¿ô minput_filter () ¤Ø¤ÎľÁ°¤Î¸Æ¤Ó½Ð¤·¤ËÍѤ¤¤é¤ì¤¿¤â¤Î¤ÈƱ¤¸¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
3645 ¥Æ¥¥¹¥È¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆÀ¸À®¤µ¤ì¤Æ¤¤¤ì¤Ð¡¢¥Æ¥¥¹¥È¤Ï M-text
3648 ¤³¤Î´Ø¿ô¤Ï¡¢#MInputDriver::lookup ¤ò¸Æ¤Ö¡£
3651 $KEY ¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆŬÀڤ˽èÍý¤Ç¤¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 0 ¤òÊÖ¤¹¡£
3652 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£
3653 ¤³¤Î¾ì¹ç¤Ç¤â $MT ¤Ë²¿¤é¤«¤Î¥Æ¥¥¹¥È¤¬À¸À®¤µ¤ì¤Æ¤¤¤ë¤³¤È¤¬¤¢¤ë¡£
3655 @latexonly \IPAlabel{minput_lookup} @endlatexonly */
3658 minput_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
3660 return (ic ? (*ic->im->driver.lookup) (ic, key, arg, mt) : -1);
3665 @brief Set the spot of the input context.
3667 The minput_set_spot () function set the spot of input context $IC
3668 to coordinate ($X, $Y ) with the height specified by $ASCENT and $DESCENT .
3669 The semantics of these values depend on the input method driver.
3671 For instance, a driver designed to work in a CUI environment may
3672 use $X and $Y as column and row numbers, and ignore $ASCENT and
3673 $DESCENT . A driver designed to work in a window system may
3674 interpret $X and $Y as pixel offsets relative to the origin of the
3675 client window, and may interpret $ASCENT and $DESCENT as the ascent- and
3676 descent pixels of the line at ($X . $Y ).
3678 $FONTSIZE specifies the fontsize of preedit text in 1/10 point.
3680 $MT and $POS is the M-text and the character position at the spot.
3681 $MT may be @c NULL, in which case, the input method cannot get
3682 information about the text around the spot. */
3685 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Î¥¹¥Ý¥Ã¥È¤òÀßÄꤹ¤ë.
3687 ´Ø¿ô minput_set_spot () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤Î¥¹¥Ý¥Ã¥È¤ò¡¢ºÂɸ ($X, $Y )
3688 ¤Î°ÌÃÖ¤Ë ¡¢¹â¤µ $ASCENT¡¢ $DESCENT
3689 ¤ÇÀßÄꤹ¤ë¡£ ¤³¤ì¤é¤ÎÃͤΰÕÌ£¤ÏÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë¡£
3691 ¤¿¤È¤¨¤Ð CUI ´Ä¶¤ÇÆ°ºî¤¹¤ë¥É¥é¥¤¥Ð¤Ï $X ¤È $Y
3692 ¤ò¤½¤ì¤¾¤ìÎó¤È¹Ô¤ÎÈÖ¹æ¤È¤·¤ÆÍѤ¤¡¢$ASCENT ¤È $DESCENT
3693 ¤ò̵»ë¤¹¤ë¤«¤â¤·¤ì¤Ê¤¤¡£ ¤Þ¤¿¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥àÍѤΥɥ饤¥Ð¤Ï
3694 $X ¤È $Y ¤ò¥¯¥é¥¤¥¢¥ó¥È¥¦¥£¥ó¥É¥¦¤Î¸¶ÅÀ¤«¤é¤Î¥ª¥Õ¥»¥Ã¥È¤ò¥Ô¥¯¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¤¡¢
3695 $ASCENT ¤È $DESCENT ¤ò ($X . $Y )
3696 ¤ÎÎó¤Î¥¢¥»¥ó¥È¤È¥Ç¥£¥»¥ó¥È¤ò¥Ô¥¯¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¦¤«¤â¤·¤ì¤Ê¤¤¡£
3698 $FONTSIZE ¤Ë¤Ï preedit ¥Æ¥¥¹¥È¤Î¥Õ¥©¥ó¥È¥µ¥¤¥º¤ò 1/10 ¥Ý¥¤¥ó¥Èñ°Ì¤Ç»ØÄꤹ¤ë¡£
3700 $MT ¤È $POS ¤Ï¤½¤Î¥¹¥Ý¥Ã¥È¤Î M-text ¤Èʸ»ú°ÌÃ֤Ǥ¢¤ë¡£$MT ¤Ï @c
3701 NULL ¤Ç¤â¤è¤¯¡¢¤½¤Î¾ì¹ç¤Ë¤ÏÆþÎϥ᥽¥Ã¥É¤Ï¥¹¥Ý¥Ã¥È¼þÊդΥƥ¥¹¥È¤Ë´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë¤³¤È¤¬¤Ç¤¤Ê¤¤¡£
3705 minput_set_spot (MInputContext *ic, int x, int y,
3706 int ascent, int descent, int fontsize,
3711 ic->spot.ascent = ascent;
3712 ic->spot.descent = descent;
3713 ic->spot.fontsize = fontsize;
3716 if (ic->im->driver.callback_list)
3717 minput__callback (ic, Minput_set_spot);
3722 @brief Toggle input method.
3724 The minput_toggle () function toggles the input method associated
3725 with input context $IC. */
3727 @brief ÆþÎϥ᥽¥Ã¥É¤òÀÚÂؤ¨¤ë.
3729 ´Ø¿ô minput_toggle () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC
3730 ¤ËÂбþÉÕ¤±¤é¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ò¥È¥°¥ë¤¹¤ë¡£
3734 minput_toggle (MInputContext *ic)
3736 if (ic->im->driver.callback_list)
3737 minput__callback (ic, Minput_toggle);
3738 ic->active = ! ic->active;
3744 @brief Reset an input context.
3746 The minput_reset_ic () function resets input context $IC by
3747 calling a callback function corresponding to #Minput_reset. It
3748 resets the status of $IC to the one of just after created. As the
3749 current preedit text is deleted without commitment, if necessary,
3750 call minput_filter () with the arg @r key #Mnil to force the input
3751 method to commit the preedit in advance. */
3754 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤ò¥ê¥»¥Ã¥È¤¹¤ë.
3756 ´Ø¿ô minput_reset_ic () ¤Ï #Minput_reset
3757 ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¸Æ¤Ö¤³¤È¤Ë¤è¤Ã¤ÆÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC
3758 ¤ò¥ê¥»¥Ã¥È¤¹¤ë¡£¥ê¥»¥Ã¥È¤È¤Ï¡¢¼ÂºÝ¤Ë¤ÏÆþÎϥ᥽¥Ã¥É¤ò½é´ü¾õÂ֤˰ܤ¹¤³¤È¤Ç¤¢¤ê¡¢¤·¤¿¤¬¤Ã¤Æ¡¢¤â¤·¸½ºßÆþÎÏÃæ¤Î¥Æ¥¥¹¥È¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤Ï¥³¥ß¥Ã¥È¤µ¤ì¤ë¡£
3759 ɬÍפʤé¤Ð¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ï minput_lookup ()
3760 ¤òÆɤó¤Ç¤½¤Î¥³¥ß¥Ã¥È¤µ¤ì¤¿¥Æ¥¥¹¥È¤ò¼è¤ê½Ð¤¹¤³¤È¤¬¤Ç¤¡¢¤½¤ÎºÝ¡¢
3761 minput_lookup () ¤Î°ú¿ô @c KEY ¤È @c ARG
3764 minput_reset_ic (MInputContext *ic)
3766 if (ic->im->driver.callback_list)
3767 minput__callback (ic, Minput_reset);
3773 @brief Get title and icon filename of an input method.
3775 The minput_get_title_icon () function returns a plist containing a
3776 title and icon filename (if any) of the input method specifies by
3777 $LANGUAGE and $NAME.
3779 The first element of the plist has key Mtext and the value is an
3780 M-text of the title for identifying the input method. The second
3781 element (if any) has key M-text and the value is an M-text of the
3782 icon image (absolute) filename for the same purpose.
3785 If there exists the specified input method and it defines an
3786 title, a plist is retured. Otherwise, NULL is returned. A caller
3787 must free the plist by m17n_object_unref ().
3791 minput_get_title_icon (MSymbol language, MSymbol name)
3793 MPlist *plist = load_partial_im_info (language, name, Mnil, Mtitle);
3800 pl = MPLIST_PLIST (plist);
3801 pl = MPLIST_NEXT (pl);
3802 if (! MPLIST_MTEXT_P (pl))
3804 M17N_OBJECT_UNREF (plist);
3807 M17N_OBJECT_REF (pl);
3808 M17N_OBJECT_UNREF (plist);
3810 pl = MPLIST_NEXT (pl);
3811 if (MPLIST_MTEXT_P (pl))
3813 if (mtext_nchars (MPLIST_MTEXT (pl)) > 0)
3815 mt = MPLIST_MTEXT (pl);
3816 file = mdatabase__find_file ((char *) MTEXT_DATA (mt));
3819 else if (language != Mnil && name != Mnil)
3822 file = alloca (MSYMBOL_NAMELEN (language) + MSYMBOL_NAMELEN (name) + 12);
3823 sprintf (file, "icon/%s-%s.png", (char *) MSYMBOL_NAME (language),
3824 (char *) MSYMBOL_NAME (name));
3825 file = mdatabase__find_file (file);
3830 mt = mtext__from_data (file, strlen (file), MTEXT_FORMAT_UTF_8, 1);
3832 mplist_set (pl, Mtext, mt);
3833 M17N_OBJECT_UNREF (mt);
3836 mplist_set (pl, Mnil, NULL);
3843 @brief Get description text of an input method.
3845 The minput_get_description () function returns an M-text that
3846 describes the input method specified by $LANGUAGE and $NAME.
3849 If the specified input method has a description text, a pointer to
3850 #MText is returned. A caller have to free it by m17n_object_unref ().
3851 If the input method does not have a description text, @c NULL is
3854 @brief ÆþÎϥ᥽¥Ã¥É¤ÎÀâÌÀ¥Æ¥¥¹¥È¤òÆÀ¤ë.
3856 ´Ø¿ô minput_get_description () ¤Ï¡¢$LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ»ØÄê
3857 ¤µ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤òÀâÌÀ¤¹¤ë M-text ¤òÊÖ¤¹¡£
3859 @return »ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤¬ÀâÌÀ¤¹¤ë¥Æ¥¥¹¥È¤ò»ý¤Ã¤Æ¤¤¤ì¤Ð¡¢
3860 #MText ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¸Æ¤Ó½Ð¤·Â¦¤Ï¡¢¤½¤ì¤ò m17n_object_unref
3861 () ¤òÍѤ¤¤Æ²òÊü¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ÆþÎϥ᥽¥Ã¥É¤ËÀâÌÀ¥Æ¥¥¹¥È¤¬Ìµ¤±
3862 ¤ì¤Ð@c NULL ¤òÊÖ¤¹¡£ */
3865 minput_get_description (MSymbol language, MSymbol name)
3867 MPlist *plist = load_partial_im_info (language, name, Mnil, M_description);
3873 pl = MPLIST_PLIST (plist);
3874 pl = MPLIST_NEXT (pl);
3875 if (MPLIST_MTEXT_P (pl))
3877 mt = MPLIST_MTEXT (pl);
3878 M17N_OBJECT_REF (mt);
3880 M17N_OBJECT_UNREF (plist);
3885 @brief Get information about input method commands.
3887 The minput_get_commands () function returns information about
3888 input method commands of the input method specified by $LANGUAGE
3889 and $NAME. An input method command is a pseudo key event to which
3890 one or more actual input key sequences are assigned.
3892 There are two kinds of commands, global and local. Global
3893 commands are used by multiple input methods for the same purpose,
3894 and have global key assignments. Local commands are used only in
3895 a specific input method, and have only local key assignments.
3897 Each input method may locally change key assignments for global
3898 commands. A global key assignment for a global command are
3899 effective only when the current input method does not have local
3900 key assignments for that command.
3902 If $NAME is #Mnil, information about global commands is returned.
3903 In this case $LANGUAGE is ignored.
3905 If $NAME is not #Mnil, information about those commands that have
3906 local key assignments in the input method specified by $LANGUAGE
3907 and $NAME is returned.
3910 If no input method commands are found, this function returns @c NULL.
3912 Otherwise, a pointer to a plist is returned. The key of each
3913 element in the plist is a symbol representing a command, and the
3914 value is a plist of the form COMMAND-INFO described below.
3916 The first element of COMMAND-INFO has the key #Mtext, and the
3917 value is an M-text describing the command.
3919 If there are no more elements, that means no key sequences are
3920 assigned to the command. Otherwise, each of the remaining
3921 elements has the key #Mplist, and the value is a plist whose keys are
3922 #Msymbol and values are symbols representing input keys, which are
3923 currently assigned to the command.
3925 As the returned plist is kept in the library, the caller must not
3926 modify nor free it. */
3928 @brief ÆþÎϥ᥽¥Ã¥É¤Î¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë.
3930 ´Ø¿ô minput_get_commands () ¤Ï¡¢ $LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ»ØÄꤵ
3931 ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ÎÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£ÆþÎϥ᥽¥Ã
3932 ¥É¥³¥Þ¥ó¥É¤È¤Ï¡¢µ¿»÷¥¡¼¥¤¥Ù¥ó¥È¤Ç¤¢¤ê¡¢¤½¤ì¤¾¤ì¤Ë£±¤Ä°Ê¾å¤Î¼ÂºÝ¤Î
3933 ÆþÎÏ¥¡¼¥·¡¼¥¯¥¨¥ó¥¹¤¬³ä¤êÅö¤Æ¤é¤ì¤Æ¤¤¤ë¤â¤Î¤ò»Ø¤¹¡£
3935 ¥³¥Þ¥ó¥É¤Ë¤Ï¥°¥í¡¼¥Ð¥ë¤È¥í¡¼¥«¥ë¤Î£²¼ïÎब¤¢¤ë¡£¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É
3936 ¤ÏÊ£¿ô¤ÎÆþÎϥ᥽¥Ã¥É¤Ë¤ª¤¤¤Æ¡¢Æ±¤¸ÌÜŪ¤Ç¡¢¥°¥í¡¼¥Ð¥ë¤Ê¥¡¼³ä¤êÅö¤Æ
3937 ¤ÇÍѤ¤¤é¤ì¤ë¡£¥í¡¼¥«¥ë¥³¥Þ¥ó¥É¤ÏÆÃÄê¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Î¤ß¡¢¥í¡¼¥«¥ë
3938 ¤Ê¥¡¼³äÅö¤Ç»ÈÍѤµ¤ì¤ë¡£
3940 ¸Ä¡¹¤ÎÆþÎϥ᥽¥Ã¥É¤Ï¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É¤Î¥¡¼³äÅö¤òÊѹ¹¤¹¤ë¤³¤È¤â¤Ç
3941 ¤¤ë¡£¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥ÉÍѤΥ°¥í¡¼¥Ð¥ë¥¡¼³ä¤êÅö¤Æ¤Ï¡¢»ÈÍѤ¹¤ëÆþÎÏ
3942 ¥á¥½¥Ã¥É¤Ë¤ª¤¤¤Æ¤½¤Î¥³¥Þ¥ó¥ÉÍÑ¤Î¥í¡¼¥«¥ë¤Ê¥¡¼³äÅö¤¬Â¸ºß¤·¤Ê¤¤¾ì¹ç
3945 $NAME ¤¬ #Mnil ¤Ç¤¢¤ì¤Ð¡¢¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£¤³¤Î
3946 ¾ì¹ç¡¢$LANGUAGE ¤Ï̵»ë¤µ¤ì¤ë¡£
3948 $NAME ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢$LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤ëÆþ
3949 Îϥ᥽¥Ã¥É¤ËÃÖ¤±¤ë¥í¡¼¥«¥ë¤Ê¥¡¼³ä¤êÅö¤Æ¤ò»ý¤Ä¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó
3953 ÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï @c NULL ¤òÊÖ¤¹¡£
3955 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¥ê¥¹¥È¤Î³ÆÍ×ÁǤÎ
3956 ¥¡¼¤Ï¸Ä¡¹¤Î¥³¥Þ¥ó¥É¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢Ãͤϲ¼µ¤Î COMMAND-INFO
3957 ¤Î·Á¼°¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ç¤¢¤ë¡£
3959 COMMAND-INFO ¤ÎÂè°ìÍ×ÁǤΥ¡¼¤Ï #Mtext ¤Þ¤¿¤Ï #Msymbol ¤Ç¤¢¤ë¡£¥¡¼
3960 ¤¬ #Mtext ¤Ê¤é¡¢ÃͤϤ½¤Î¥³¥Þ¥ó¥É¤òÀâÌÀ¤¹¤ë M-text ¤Ç¤¢¤ë¡£¥¡¼¤¬
3961 #Msymbol ¤Ê¤éÃÍ¤Ï #Mnil ¤Ç¤¢¤ê¡¢¤³¤Î¥³¥Þ¥ó¥É¤ÏÀâÌÀ¥Æ¥¥¹¥È¤ò»ý¤¿¤Ê
3964 ¤½¤ì°Ê³°¤ÎÍ×ÁǤ¬Ìµ¤±¤ì¤Ð¡¢¤³¤Î¥³¥Þ¥ó¥É¤ËÂФ·¤Æ¥¡¼¥·¡¼¥¯¥¨¥ó¥¹¤¬³ä
3965 ¤êÅö¤Æ¤é¤ì¤Æ¤¤¤Ê¤¤¤³¤È¤ò°ÕÌ£¤¹¤ë¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢»Ä¤ê¤Î³ÆÍ×ÁǤϥ
3966 ¡¼¤È¤·¤Æ#Mplist ¤ò¡¢ÃͤȤ·¤Æ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ò»ý¤Ä¡£¤³¤Î¥×¥í¥Ñ¥Æ¥£
3967 ¥ê¥¹¥È¤Î¥¡¼¤Ï #Msymbol ¤Ç¤¢¤ê¡¢Ãͤϸ½ºß¤½¤Î¥³¥Þ¥ó¥É¤Ë³ä¤êÅö¤Æ¤é¤ì
3968 ¤Æ¤¤¤ëÆþÎÏ¥¡¼¤òɽ¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
3970 ÊÖ¤µ¤ì¤ë¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ï¥é¥¤¥Ö¥é¥ê¤Ë¤è¤Ã¤Æ´ÉÍý¤µ¤ì¤Æ¤ª¤ê¡¢¸Æ¤Ó½Ð
3971 ¤·Â¦¤ÇÊѹ¹¤·¤¿¤ê²òÊü¤·¤¿¤ê¤·¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£*/
3974 minput_get_commands (MSymbol language, MSymbol name)
3976 MPlist *plist = get_nested_list (language, name, Mnil, M_command);
3978 return (MPLIST_TAIL_P (plist) ? NULL : plist);
3982 @brief Assign a key sequence to an input method command.
3984 The minput_assign_command_keys () function assigns input key
3985 sequence $KEYSEQ to input method command $COMMAND for the input
3986 method specified by $LANGUAGE and $NAME. If $NAME is #Mnil, the
3987 key sequence is assigned globally no matter what $LANGUAGE is.
3988 Otherwise the key sequence is assigned locally.
3990 Each element of $KEYSEQ must have the key $Msymbol and the value
3991 must be a symbol representing an input key.
3993 $KEYSEQ may be @c NULL, in which case, all assignments are deleted
3994 globally or locally.
3996 This assignment gets effective in a newly opened input method.
3999 If the operation was successful, 0 is returned. Otherwise -1 is
4000 returned, and #merror_code is set to #MERROR_IM. */
4002 @brief ÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤Ë¥¡¼¥·¡¼¥¯¥¨¥ó¥¹¤ò³ä¤êÅö¤Æ¤ë.
4004 ´Ø¿ô minput_assign_command_keys () ¤Ï¡¢ $LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ
4005 »ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥ÉÍѤÎÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É $COMMAND ¤ËÂФ·¤Æ¡¢
4006 ÆþÎÏ¥¡¼¥·¡¼¥¯¥¨¥ó¥¹ $KEYSEQ ¤ò³ä¤êÅö¤Æ¤ë¡£ $NAME ¤¬ #Mnil ¤Ê¤é¤Ð¡¢
4007 $LANGUAGE ¤Ë´Ø·¸¤Ê¤¯¡¢ÆþÎÏ¥¡¼¥·¡¼¥¯¥¨¥ó¥¹¤Ï¥°¥í¡¼¥Ð¥ë¤Ë³ä¤êÅö¤Æ¤é
4008 ¤ì¤ë¡£¤½¤¦¤Ç¤Ê¤ì¤Ð¡¢³ä¤êÅö¤Æ¤Ï¥í¡¼¥«¥ë¤Ç¤¢¤ë¡£
4010 $KEYSEQ ¤Î³ÆÍ×ÁǤϥ¡¼¤È¤·¤Æ $Msymbol ¤ò¡¢ÃͤȤ·¤ÆÆþÎÏ¥¡¼¤òɽ¤¹¥·
4011 ¥ó¥Ü¥ë¤ò»ý¤¿¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
4013 $KEYSEQ ¤Ï @c NULL ¤Ç¤â¤è¤¤¡£¤³¤Î¾ì¹ç¡¢¥°¥í¡¼¥Ð¥ë¤â¤·¤¯¤Ï¥í¡¼¥«¥ë¤Ê
4014 ¤¹¤Ù¤Æ¤Î³ä¤êÅö¤Æ¤¬¾Ãµî¤µ¤ì¤ë¡£
4016 ¤³¤Î³ä¤êÅö¤Æ¤Ï¡¢³ä¤êÅö¤Æ°Ê¹ß¿·¤·¤¯¥ª¡¼¥×¥ó¤µ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤«¤éÍ
4019 @return ½èÍý¤¬À®¸ù¤¹¤ì¤Ð 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤·¡¢
4020 #merror_code ¤ò #MERROR_IM ¤ËÀßÄꤹ¤ë¡£ */
4023 minput_assign_command_keys (MSymbol language, MSymbol name,
4024 MSymbol command, MPlist *keyseq)
4026 MPlist *plist, *pl, *p;
4028 if (check_command_keyseq (keyseq) < 0
4029 || ! (plist = get_nested_list (language, name, Mnil, M_command)))
4030 MERROR (MERROR_IM, -1);
4031 pl = mplist_get (plist, command);
4034 pl = MPLIST_NEXT (pl);
4036 while ((p = mplist_pop (pl)))
4037 M17N_OBJECT_UNREF (p);
4040 keyseq = mplist_copy (keyseq);
4041 mplist_push (pl, Mplist, keyseq);
4042 M17N_OBJECT_UNREF (keyseq);
4048 MERROR (MERROR_IM, -1);
4051 /* Get global commands. */
4052 pl = get_nested_list (Mnil, Mnil, Mnil, M_command);
4053 pl = mplist_get (pl, command);
4055 MERROR (MERROR_IM, -1);
4057 mplist_add (p, Mtext, mplist_value (pl));
4058 keyseq = mplist_copy (keyseq);
4059 mplist_add (p, Mplist, keyseq);
4060 M17N_OBJECT_UNREF (keyseq);
4061 mplist_push (plist, command, p);
4067 @brief Get a list of variables of an input method.
4069 The minput_get_variables () function returns a plist (#MPlist) of
4070 variables used to control the behavior of the input method
4071 specified by $LANGUAGE and $NAME. The key of an element of the
4072 plist is a symbol representing a variable, and the value is a
4073 plist of the form VAR-INFO (described below) that carries the
4074 information about the variable.
4076 The first element of VAR-INFO has the key #Mtext or #Msymbol. If
4077 the key is #Mtext, the value is an M-text describing the variable.
4078 If the key is #Msymbol, that value is #Mnil which means the
4079 variable has no description text.
4081 The second element of VAR-INFO is for the value of the variable.
4082 The key is #Minteger, #Msymbol, or #Mtext, and the value is an
4083 integer, a symbol, or an M-text, respectively. The variable is
4084 set to this value when an input context is created for the input
4087 If there are no more elements, the variable can take any value
4088 that matches with the above type. Otherwise, the remaining
4089 elements of VAR-INFO are to specify valid values of the variable.
4091 If the type of the variable is integer, the following elements
4092 have the key #Minteger or #Mplist. If it is #Minteger, the value
4093 is a valid integer value. If it is #Mplist, the value is a plist
4094 of two of elements. Both of them have the key #Minteger, and
4095 values are the minimum and maximum bounds of the valid value
4098 If the type of the variable is symbol or M-text, the following
4099 elements of the plist have the key #Msymbol or #Mtext,
4100 respectively, and the value must be a valid one.
4102 For instance, suppose an input method has the variables:
4104 @li name:intvar, description:"value is an integer",
4105 initial value:0, value-range:0..3,10,20
4107 @li name:symvar, description:"value is a symbol",
4108 initial value:nil, value-range:a, b, c, nil
4110 @li name:txtvar, description:"value is an M-text",
4111 initial value:empty text, no value-range (i.e. any text)
4113 Then, the returned plist has this form ('X:Y' means X is a key and Y is
4114 a value, and '(...)' means a plist):
4117 plist:(intvar:(mtext:"value is an integer"
4119 plist:(integer:0 integer:3)
4122 symvar:(mtext:"value is a symbol"
4128 txtvar:(mtext:"value is an M-text"
4133 If the input method uses any variables, a pointer to #MPlist is
4134 returned. As the plist is kept in the library, a caller must not
4135 modify nor free it. If the input method does not use any
4136 variable, @c NULL is returned. */
4138 @brief ÆþÎϥ᥽¥Ã¥É¤ÎÊÑ¿ô¥ê¥¹¥È¤òÆÀ¤ë.
4140 ´Ø¿ô minput_get_variables () ¤Ï¡¢$LANGUAGE ¤È $NAME
4141 ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤Î¿¶¤ëÉñ¤¤¤òÀ©¸æ¤¹¤ëÊÑ¿ô¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È
4142 (#MPlist) ¤òÊÖ¤¹¡£¥ê¥¹¥È¤Î³ÆÍ×ÁǤΥ¡¼¤ÏÊÑ¿ô¤òɽ¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
4143 ³ÆÍ×ÁǤÎÃͤϲ¼µ¤Î VAR-INFO
4144 ¤Î·Á¼°¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ç¤¢¤ê¡¢³ÆÊÑ¿ô¤Ë´Ø¤¹¤ë¾ðÊó¤ò¼¨¤·¤Æ¤¤¤ë¡£
4146 VAR-INFO ¤ÎÂè°ìÍ×ÁǤΥ¡¼¤Ï #Mtext ¤Þ¤¿¤Ï #Msymbol ¤Ç¤¢¤ë¡£¥¡¼¤¬
4147 #Mtext ¤Ê¤é¡¢ÃͤϤ½¤ÎÊÑ¿ô¤òÀâÌÀ¤¹¤ë M-text ¤Ç¤¢¤ë¡£¥¡¼¤¬ #Msymbol
4148 ¤Ê¤éÃÍ¤Ï #Mnil ¤Ç¤¢¤ê¡¢¤³¤ÎÊÑ¿ô¤ÏÀâÌÀ¥Æ¥¥¹¥È¤ò»ý¤¿¤Ê¤¤¤³¤È¤Ë¤Ê¤ë¡£
4150 VAR-INFO ¤ÎÂèÆóÍ×ÁǤÏÊÑ¿ô¤ÎÃͤò¼¨¤¹¡£¥¡¼¤Ï #Minteger, #Msymbol,
4151 #Mtext ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ê¡¢ÃͤϤ½¤ì¤¾¤ìÀ°¿ôÃÍ¡¢¥·¥ó¥Ü¥ë¡¢M-text ¤Ç¤¢¤ë¡£
4152 ¤³¤ÎÆþÎϥ᥽¥Ã¥ÉÍѤÎÆþÎÏ¥³¥ó¥Æ¥¹¥È¤¬ºî¤é¤ì¤ë»þÅÀ¤Ç¤Ï¡¢ÊÑ¿ô¤Ï¤³¤ÎÃͤËÀßÄꤵ¤ì¤Æ¤¤¤ë¡£
4154 VAR-INFO ¤Ë¤½¤ì°Ê³°¤ÎÍ×ÁǤ¬Ìµ¤±¤ì¤Ð¡¢ÊÑ¿ô¤Ï¾åµ¤Î·¿¤Ë¹çÃפ¹¤ë¸Â¤ê¤É¤Î¤è¤¦¤ÊÃͤò¤È¤ë¤³¤È¤â¤Ç¤¤ë¡£
4155 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢VAR-INFO ¤Î»Ä¤ê¤ÎÍ×ÁǤˤè¤Ã¤ÆÊÑ¿ô¤Î͸ú¤ÊÃͤ¬»ØÄꤵ¤ì¤ë¡£
4157 ÊÑ¿ô¤Î·¿¤¬À°¿ô¤Ç¤¢¤ì¤Ð¡¢¤½¤ì°Ê¹ß¤ÎÍ×ÁÇ¤Ï #Minteger ¤« #Mplist
4158 ¤ò¥¡¼¤È¤·¤Æ»ý¤Ä¡£ #Minteger ¤Ç¤¢¤ì¤Ð¡¢ÃͤÏ͸ú¤ÊÃͤò¼¨¤¹À°¿ôÃͤǤ¢¤ë¡£
4159 #Mplist ¤Ç¤¢¤ì¤Ð¡¢ÃͤÏÆó¤Ä¤ÎÍ×ÁǤò»ý¤Ä¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ç¤¢¤ê¡¢³ÆÍ×ÁǤϥ¡¼¤È¤·¤Æ
4160 #Minteger ¤ò¡¢ÃͤȤ·¤Æ¤½¤ì¤¾¤ì͸ú¤ÊÃͤξå¸ÂÃͤȲ¼¸ÂÃͤò¤È¤ë¡£
4162 ÊÑ¿ô¤Î·¿¤¬¥·¥ó¥Ü¥ë¤« M-text ¤Ç¤¢¤ì¤Ð¡¢¤½¤ì°Ê¹ß¤ÎÍ×ÁǤϥ¡¼¤È¤·¤Æ¤½¤ì¤¾¤ì
4163 #Msymbol ¤« #Mtext ¤ò»ý¤Á¡¢ÃͤϤ½¤Î·¿¤Ë¹çÃפ¹¤ë¤â¤Î¤Ç¤¢¤ë¡£
4165 Îã¤È¤·¤Æ¡¢¤¢¤ëÆþÎϥ᥽¥Ã¥É¤¬¼¡¤Î¤è¤¦¤ÊÊÑ¿ô¤ò»ý¤Ä¾ì¹ç¤ò¹Í¤¨¤è¤¦¡£
4167 @li name:intvar, ÀâÌÀ:"value is an integer",
4168 ½é´üÃÍ:0, ÃͤÎÈÏ°Ï:0..3,10,20
4170 @li name:symvar, ÀâÌÀ:"value is a symbol",
4171 ½é´üÃÍ:nil, ÃͤÎÈÏ°Ï:a, b, c, nil
4173 @li name:txtvar, ÀâÌÀ:"value is an M-text",
4174 ½é´üÃÍ:empty text, ÃͤÎÈϰϤʤ·(¤É¤ó¤Ê M-text ¤Ç¤â²Ä)
4176 ¤³¤Î¾ì¹ç¡¢ÊÖ¤µ¤ì¤ë¥ê¥¹¥È¤Ï°Ê²¼¤Î¤è¤¦¤Ë¤Ê¤ë¡£¡Ê'X:Y' ¤È¤¤¤¦µË¡¤Ï X
4177 ¤¬¥¡¼¤Ç Y ¤¬ÃͤǤ¢¤ë¤³¤È¤ò¡¢¤Þ¤¿ '(...)' ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ò¼¨¤¹¡£¡Ë
4180 plist:(intvar:(mtext:"value is an integer"
4182 plist:(integer:0 integer:3)
4185 symvar:(mtext:"value is a symbol"
4191 txtvar:(mtext:"value is an M-text"
4196 ÆþÎϥ᥽¥Ã¥É¤¬²¿¤é¤«¤ÎÊÑ¿ô¤ò»ÈÍѤ·¤Æ¤¤¤ì¤Ð #MPlist ¤Ø¤ÎÊÑ¿ô¤òÊÖ¤¹¡£
4197 ÊÖ¤µ¤ì¤ë¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ï¥é¥¤¥Ö¥é¥ê¤Ë¤è¤Ã¤Æ´ÉÍý¤µ¤ì¤Æ¤ª¤ê¡¢¸Æ¤Ó½Ð¤·Â¦¤ÇÊѹ¹¤·¤¿¤ê²òÊü¤·¤¿¤ê¤·¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
4198 ÆþÎϥ᥽¥Ã¥É¤¬ÊÑ¿ô¤ò°ìÀÚ»ÈÍѤ·¤Æ¤Ê¤±¤ì¤Ð¡¢@c NULL ¤òÊÖ¤¹¡£ */
4201 minput_get_variables (MSymbol language, MSymbol name)
4203 MPlist *plist = get_nested_list (language, name, Mnil, M_variable);
4205 return (MPLIST_TAIL_P (plist) ? NULL : plist);
4209 @brief Set the initial value of an input method variable.
4211 The minput_set_variable () function sets the initial value of
4212 input method variable $VARIABLE to $VALUE for the input method
4213 specified by $LANGUAGE and $NAME.
4215 By default, the initial value is 0.
4217 This setting gets effective in a newly opened input method.
4220 If the operation was successful, 0 is returned. Otherwise -1 is
4221 returned, and #merror_code is set to #MERROR_IM. */
4223 @brief ÆþÎϥ᥽¥Ã¥ÉÊÑ¿ô¤Î½é´üÃͤòÀßÄꤹ¤ë.
4225 ´Ø¿ô minput_set_variable () ¤Ï¡¢$LANGUAGE ¤È $NAME
4226 ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ÎÆþÎϥ᥽¥Ã¥ÉÊÑ¿ô $VARIABLE
4227 ¤Î½é´üÃͤò¡¢ $VALUE ¤ËÀßÄꤹ¤ë¡£
4229 ¥Ç¥Õ¥©¥ë¥È¤Î½é´üÃÍ¤Ï 0 ¤Ç¤¢¤ë¡£
4231 ¤³¤ÎÀßÄê¤Ï¡¢¿·¤·¤¯¥ª¡¼¥×¥ó¤µ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤«¤é͸ú¤È¤Ê¤ë¡£
4234 ½èÍý¤¬À®¸ù¤¹¤ì¤Ð 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤·¡¢
4235 #merror_code ¤ò #MERROR_IM ¤ËÀßÄꤹ¤ë¡£ */
4238 minput_set_variable (MSymbol language, MSymbol name,
4239 MSymbol variable, void *value)
4241 MPlist *plist, *val_element, *range_element;
4244 plist = get_nested_list (language, name, Mnil, M_variable);
4246 MERROR (MERROR_IM, -1);
4247 plist = mplist_find_by_value (plist, variable);
4249 MERROR (MERROR_IM, -1);
4250 plist = MPLIST_PLIST (MPLIST_NEXT (plist));
4251 val_element = MPLIST_NEXT (plist);
4252 type = MPLIST_KEY (val_element);
4253 range_element = MPLIST_NEXT (val_element);
4255 if (! MPLIST_TAIL_P (range_element))
4257 if (type == Minteger)
4259 int val = (int) value, this_val;
4261 MPLIST_DO (plist, range_element)
4263 this_val = (int) MPLIST_VAL (plist);
4264 if (MPLIST_PLIST_P (plist))
4266 int min_bound, max_bound;
4267 MPlist *pl = MPLIST_PLIST (plist);
4269 min_bound = (int) MPLIST_VAL (pl);
4270 pl = MPLIST_NEXT (pl);
4271 max_bound = (int) MPLIST_VAL (pl);
4272 if (val >= min_bound && val <= max_bound)
4275 else if (val == this_val)
4278 if (MPLIST_TAIL_P (plist))
4279 MERROR (MERROR_IM, -1);
4281 else if (type == Msymbol)
4283 MPLIST_DO (plist, range_element)
4284 if (MPLIST_SYMBOL (plist) == (MSymbol) value)
4286 if (MPLIST_TAIL_P (plist))
4287 MERROR (MERROR_IM, -1);
4289 else /* type == Mtext */
4291 MPLIST_DO (plist, range_element)
4292 if (mtext_cmp (MPLIST_MTEXT (plist), (MText *) value) == 0)
4294 if (MPLIST_TAIL_P (plist))
4295 MERROR (MERROR_IM, -1);
4296 M17N_OBJECT_REF (value);
4300 mplist_set (val_element, type, value);
4306 /*** @addtogroup m17nDebug */
4312 @brief Dump an input method.
4314 The mdebug_dump_im () function prints the input method $IM in a
4315 human readable way to the stderr. $INDENT specifies how many
4316 columns to indent the lines but the first one.
4319 This function returns $IM. */
4321 @brief ÆþÎϥ᥽¥Ã¥É¤ò¥À¥ó¥×¤¹¤ë.
4323 ´Ø¿ô mdebug_dump_im () ¤ÏÆþÎϥ᥽¥Ã¥É $IM ¤ò stderr
4324 ¤Ë¿Í´Ö¤Ë²ÄÆɤʷÁ¤Ç°õºþ¤¹¤ë¡£$INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£
4327 ¤³¤Î´Ø¿ô¤Ï $IM ¤òÊÖ¤¹¡£ */
4330 mdebug_dump_im (MInputMethod *im, int indent)
4332 MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
4335 prefix = (char *) alloca (indent + 1);
4336 memset (prefix, 32, indent);
4337 prefix[indent] = '\0';
4339 fprintf (stderr, "(input-method %s %s ", msymbol_name (im->language),
4340 msymbol_name (im->name));
4341 mdebug_dump_mtext (im_info->title, 0, 0);
4342 if (im->name != Mnil)
4346 MPLIST_DO (state, im_info->states)
4348 fprintf (stderr, "\n%s ", prefix);
4349 dump_im_state (MPLIST_VAL (state), indent + 2);
4352 fprintf (stderr, ")");