1 /* input.c -- input method module.
2 Copyright (C) 2003, 2004, 2005, 2006
3 National Institute of Advanced Industrial Science and Technology (AIST)
4 Registration Number H15PRO112
6 This file is part of the m17n library.
8 The m17n library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public License
10 as published by the Free Software Foundation; either version 2.1 of
11 the License, or (at your option) any later version.
13 The m17n library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with the m17n library; if not, write to the Free
20 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
24 @addtogroup m17nInputMethod
25 @brief API for Input method.
27 An input method is an object to enable inputting various
28 characters. An input method is identified by a pair of symbols,
29 LANGUAGE and NAME. This pair decides an input method driver of the
30 input method. An input method driver is a set of functions for
31 handling the input method. There are two kinds of input methods;
32 internal one and foreign one.
35 <li> Internal Input Method
37 An internal input method has non @c Mnil LANGUAGE, and its body is
38 defined in the m17n database by the tag <Minput_method, LANGUAGE,
39 NAME>. For this kind of input methods, the m17n library uses two
40 predefined input method drivers, one for CUI use and the other for
41 GUI use. Those drivers utilize the input processing engine
42 provided by the m17n library itself. The m17n database may
43 provide input methods that are not limited to a specific language.
44 The database uses @c Mt as LANGUAGE of those input methods.
46 An internal input method accepts an input key which is a symbol
47 associated with an input event. As there is no way for the @c
48 m17n @c library to know how input events are represented in an
49 application program, an application programmer has to convert an
50 input event to an input key by himself. See the documentation of
51 the function minput_event_to_key () for the detail.
53 <li> Foreign Input Method
55 A foreign input method has @c Mnil LANGUAGE, and its body is
56 defined in an external resource (e.g. XIM of X Window System).
57 For this kind of input methods, the symbol NAME must have a
58 property of key @c Minput_driver, and the value must be a pointer
59 to an input method driver. Therefore, by preparing a proper
60 driver, any kind of input method can be treated in the framework
61 of the @c m17n @c library.
63 For convenience, the m17n-X library provides an input method
64 driver that enables the input style of OverTheSpot for XIM, and
65 stores @c Minput_driver property of the symbol @c Mxim with a
66 pointer to the driver. See the documentation of m17n GUI API for
73 The typical processing flow of handling an input method is:
75 @li open an input method
76 @li create an input context for the input method
77 @li filter an input key
78 @li look up a produced text in the input context */
82 @addtogroup m17nInputMethod
83 @brief ÆþÎϥ᥽¥Ã¥ÉÍÑAPI.
85 ÆþÎϥ᥽¥Ã¥É¤Ï¿ÍͤÊʸ»ú¤òÆþÎϤ¹¤ë¤¿¤á¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¢¤ë¡£
86 ÆþÎϥ᥽¥Ã¥É¤Ï¥·¥ó¥Ü¥ë LANGUAGE ¤È NAME ¤ÎÁȤˤè¤Ã¤Æ¼±Ê̤µ¤ì¡¢
87 ¤³¤ÎÁȹ礻¤Ë¤è¤Ã¤ÆÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤¬·èÄꤹ¤ë¡£
88 ÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤È¤Ï¡¢¤¢¤ëÆþÎϥ᥽¥Ã¥É¤ò°·¤¦¤¿¤á¤Î´Ø¿ô¤Î½¸¤Þ¤ê¤Ç¤¢¤ë¡£
89 ÆþÎϥ᥽¥Ã¥É¤Ë¤ÏÆâÉô¥á¥½¥Ã¥É¤È³°Éô¥á¥½¥Ã¥É¤ÎÆó¼ïÎब¤¢¤ë¡£
94 ÆâÉôÆþÎϥ᥽¥Ã¥É¤È¤Ï LANGUAGE ¤¬ @c Mnil °Ê³°¤Î¤â¤Î¤Ç¤¢¤ê¡¢¤½¤ÎËÜÂΤÏ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))
484 mt = MPLIST_MTEXT (ic->plist);
485 mplist_pop (ic->plist);
490 delete_surrounding_text (MInputContext *ic, int pos)
492 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
494 mplist_push (ic->plist, Minteger, (void *) pos);
495 minput__callback (ic, Minput_delete_surrounding_text);
496 mplist_pop (ic->plist);
498 M17N_OBJECT_UNREF (ic_info->preceding_text);
500 M17N_OBJECT_UNREF (ic_info->following_text);
504 get_preceding_char (MInputContext *ic, int pos)
506 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
510 if (ic_info->preceding_text)
512 len = mtext_nchars (ic_info->preceding_text);
514 return mtext_ref_char (ic_info->preceding_text, len - pos);
516 mt = get_surrounding_text (ic, - pos);
519 len = mtext_nchars (mt);
520 if (ic_info->preceding_text)
522 if (mtext_nchars (ic_info->preceding_text) < len)
524 M17N_OBJECT_UNREF (ic_info->preceding_text);
525 ic_info->preceding_text = mt;
529 ic_info->preceding_text = mt;
532 return mtext_ref_char (ic_info->preceding_text, len - pos);
536 get_following_char (MInputContext *ic, int pos)
538 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
542 if (ic_info->following_text)
544 len = mtext_nchars (ic_info->following_text);
546 return mtext_ref_char (ic_info->following_text, pos - 1);
548 mt = get_surrounding_text (ic, pos);
551 len = mtext_nchars (mt);
552 if (ic_info->following_text)
554 if (mtext_nchars (ic_info->following_text) < len)
556 M17N_OBJECT_UNREF (ic_info->following_text);
557 ic_info->following_text = mt;
561 ic_info->following_text = mt;
564 return mtext_ref_char (ic_info->following_text, pos - 1);
568 surrounding_pos (MSymbol sym)
574 name = MSYMBOL_NAME (sym);
575 if ((name[1] == '-' || name[1] == '+')
576 && name[2] >= '1' && name[2] <= '9')
577 return (name[1] == '-' ? - atoi (name + 2) : atoi (name + 2));
582 integer_value (MInputContext *ic, MPlist *arg, MPlist **value, int surrounding)
584 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
586 MText *preedit = ic->preedit;
587 int len = mtext_nchars (preedit);
591 if (MPLIST_INTEGER_P (arg))
592 return MPLIST_INTEGER (arg);
594 && (surrounding = surrounding_pos (MPLIST_SYMBOL (arg))) != 0)
595 return (surrounding < 0
596 ? get_preceding_char (ic, - surrounding)
597 : get_following_char (ic, surrounding));
598 code = marker_code (MPLIST_SYMBOL (arg));
601 MPlist *val = resolve_variable (ic_info, MPLIST_SYMBOL (arg));
605 return (MPLIST_INTEGER_P (val) ? MPLIST_INTEGER (val) : 0);
608 return ic_info->key_head;
609 if (code >= '0' && code <= '9')
611 else if (code == '=')
612 code = ic->cursor_pos;
613 else if (code == '-' || code == '[')
614 code = ic->cursor_pos - 1;
615 else if (code == '+' || code == ']')
616 code = ic->cursor_pos + 1;
617 else if (code == '<')
619 else if (code == '>')
621 return (code >= 0 && code < len ? mtext_ref_char (preedit, code) : -1);
625 parse_expression (MPlist *plist)
629 if (MPLIST_INTEGER_P (plist) || MPLIST_SYMBOL_P (plist))
631 if (! MPLIST_PLIST_P (plist))
633 plist = MPLIST_PLIST (plist);
634 op = MPLIST_SYMBOL (plist);
635 if (op != Mplus && op != Mminus && op != Mstar && op != Mslush
636 && op != Mand && op != Mor && op != Mnot
637 && op != Mless && op != Mgreater && op != Mequal
638 && op != Mless_equal && op != Mgreater_equal)
639 MERROR (MERROR_IM, -1);
640 MPLIST_DO (plist, MPLIST_NEXT (plist))
641 if (parse_expression (plist) < 0)
647 resolve_expression (MInputContext *ic, MPlist *plist)
652 if (MPLIST_INTEGER_P (plist))
653 return MPLIST_INTEGER (plist);
654 if (MPLIST_SYMBOL_P (plist))
655 return integer_value (ic, plist, NULL, 1);
656 if (! MPLIST_PLIST_P (plist))
658 plist = MPLIST_PLIST (plist);
659 if (! MPLIST_SYMBOL_P (plist))
661 op = MPLIST_SYMBOL (plist);
662 plist = MPLIST_NEXT (plist);
663 val = resolve_expression (ic, plist);
665 MPLIST_DO (plist, MPLIST_NEXT (plist))
666 val += resolve_expression (ic, plist);
667 else if (op == Mminus)
668 MPLIST_DO (plist, MPLIST_NEXT (plist))
669 val -= resolve_expression (ic, plist);
670 else if (op == Mstar)
671 MPLIST_DO (plist, MPLIST_NEXT (plist))
672 val *= resolve_expression (ic, plist);
673 else if (op == Mslush)
674 MPLIST_DO (plist, MPLIST_NEXT (plist))
675 val /= resolve_expression (ic, plist);
677 MPLIST_DO (plist, MPLIST_NEXT (plist))
678 val &= resolve_expression (ic, plist);
680 MPLIST_DO (plist, MPLIST_NEXT (plist))
681 val |= resolve_expression (ic, plist);
684 else if (op == Mless)
685 val = val < resolve_expression (ic, MPLIST_NEXT (plist));
686 else if (op == Mequal)
687 val = val == resolve_expression (ic, MPLIST_NEXT (plist));
688 else if (op == Mgreater)
689 val = val > resolve_expression (ic, MPLIST_NEXT (plist));
690 else if (op == Mless_equal)
691 val = val <= resolve_expression (ic, MPLIST_NEXT (plist));
692 else if (op == Mgreater_equal)
693 val = val >= resolve_expression (ic, MPLIST_NEXT (plist));
697 /* Parse PLIST as an action list. PLIST should have this form:
698 PLIST ::= ( (ACTION-NAME ACTION-ARG *) *).
699 Return 0 if successfully parsed, otherwise return -1. */
702 parse_action_list (MPlist *plist, MPlist *macros)
704 MPLIST_DO (plist, plist)
706 if (MPLIST_MTEXT_P (plist))
708 /* This is a short form of (insert MTEXT). */
709 /* if (mtext_nchars (MPLIST_MTEXT (plist)) == 0)
710 MERROR (MERROR_IM, -1); */
712 else if (MPLIST_PLIST_P (plist)
713 && (MPLIST_MTEXT_P (MPLIST_PLIST (plist))
714 || MPLIST_PLIST_P (MPLIST_PLIST (plist))))
718 /* This is a short form of (insert (GROUPS *)). */
719 MPLIST_DO (pl, MPLIST_PLIST (plist))
721 if (MPLIST_PLIST_P (pl))
725 MPLIST_DO (elt, MPLIST_PLIST (pl))
726 if (! MPLIST_MTEXT_P (elt)
727 || mtext_nchars (MPLIST_MTEXT (elt)) == 0)
728 MERROR (MERROR_IM, -1);
732 if (! MPLIST_MTEXT_P (pl)
733 || mtext_nchars (MPLIST_MTEXT (pl)) == 0)
734 MERROR (MERROR_IM, -1);
738 else if (MPLIST_INTEGER_P (plist))
740 int c = MPLIST_INTEGER (plist);
742 if (c < 0 || c > MCHAR_MAX)
743 MERROR (MERROR_IM, -1);
745 else if (MPLIST_PLIST_P (plist)
746 && MPLIST_SYMBOL_P (MPLIST_PLIST (plist)))
748 MPlist *pl = MPLIST_PLIST (plist);
749 MSymbol action_name = MPLIST_SYMBOL (pl);
751 pl = MPLIST_NEXT (pl);
753 if (action_name == Minsert)
755 if (MPLIST_MTEXT_P (pl))
757 if (mtext_nchars (MPLIST_MTEXT (pl)) == 0)
758 MERROR (MERROR_IM, -1);
760 else if (MPLIST_PLIST_P (pl))
764 if (MPLIST_PLIST_P (pl))
768 MPLIST_DO (elt, MPLIST_PLIST (pl))
769 if (! MPLIST_MTEXT_P (elt)
770 || mtext_nchars (MPLIST_MTEXT (elt)) == 0)
771 MERROR (MERROR_IM, -1);
775 if (! MPLIST_MTEXT_P (pl)
776 || mtext_nchars (MPLIST_MTEXT (pl)) == 0)
777 MERROR (MERROR_IM, -1);
781 else if (! MPLIST_SYMBOL_P (pl))
782 MERROR (MERROR_IM, -1);
784 else if (action_name == Mselect
785 || action_name == Mdelete
786 || action_name == Mmove)
788 if (parse_expression (pl) < 0)
791 else if (action_name == Mmark
792 || action_name == Mcall
793 || action_name == Mshift)
795 if (! MPLIST_SYMBOL_P (pl))
796 MERROR (MERROR_IM, -1);
798 else if (action_name == Mundo)
800 if (! MPLIST_TAIL_P (pl))
802 if (! MPLIST_SYMBOL_P (pl)
803 && (! MPLIST_INTEGER_P (pl)
804 || MPLIST_INTEGER (pl) == 0))
805 MERROR (MERROR_IM, -1);
808 else if (action_name == Mpushback)
810 if (MPLIST_MTEXT_P (pl))
812 MText *mt = MPLIST_MTEXT (pl);
814 if (mtext_nchars (mt) != mtext_nbytes (mt))
815 MERROR (MERROR_IM, -1);
817 else if (MPLIST_PLIST_P (pl))
821 MPLIST_DO (p, MPLIST_PLIST (pl))
822 if (! MPLIST_SYMBOL_P (p))
823 MERROR (MERROR_IM, -1);
825 else if (! MPLIST_INTEGER_P (pl))
826 MERROR (MERROR_IM, -1);
828 else if (action_name == Mset || action_name == Madd
829 || action_name == Msub || action_name == Mmul
830 || action_name == Mdiv)
832 if (! MPLIST_SYMBOL_P (pl))
833 MERROR (MERROR_IM, -1);
834 if (parse_expression (MPLIST_NEXT (pl)) < 0)
837 else if (action_name == Mequal || action_name == Mless
838 || action_name == Mgreater || action_name == Mless_equal
839 || action_name == Mgreater_equal)
841 if (parse_expression (pl) < 0
842 || parse_expression (MPLIST_NEXT (pl)) < 0)
844 pl = MPLIST_NEXT (MPLIST_NEXT (pl));
845 if (! MPLIST_PLIST_P (pl))
846 MERROR (MERROR_IM, -1);
847 if (parse_action_list (MPLIST_PLIST (pl), macros) < 0)
848 MERROR (MERROR_IM, -1);
849 pl = MPLIST_NEXT (pl);
850 if (MPLIST_PLIST_P (pl)
851 && parse_action_list (MPLIST_PLIST (pl), macros) < 0)
852 MERROR (MERROR_IM, -1);
854 else if (action_name == Mshow || action_name == Mhide
855 || action_name == Mcommit || action_name == Munhandle)
857 else if (action_name == Mcond)
860 if (! MPLIST_PLIST_P (pl))
861 MERROR (MERROR_IM, -1);
863 else if (! macros || ! mplist_get (macros, action_name))
864 MERROR (MERROR_IM, -1);
867 MERROR (MERROR_IM, -1);
874 resolve_command (MSymbol language, MSymbol name, MSymbol command)
876 MPlist *plist = get_nested_list (language, name, Mnil, M_command);
879 MERROR (MERROR_IM, NULL);
880 MPLIST_DO (plist, plist)
882 if (MPLIST_SYMBOL (plist) == command)
884 plist = MPLIST_NEXT (plist);
886 if (MPLIST_TAIL_P (plist))
887 MERROR (MERROR_IM, NULL);
888 plist = MPLIST_NEXT (plist);
889 if (! MPLIST_PLIST_P (plist))
890 MERROR (MERROR_IM, NULL);
891 plist = MPLIST_NEXT (MPLIST_PLIST (plist));
895 /* Load a translation into MAP from PLIST.
897 PLIST ::= ( KEYSEQ MAP-ACTION * ) */
900 load_translation (MIMMap *map, MPlist *keylist, MPlist *map_actions,
901 MPlist *branch_actions, MPlist *macros)
906 if (MPLIST_MTEXT_P (keylist))
908 MText *mt = MPLIST_MTEXT (keylist);
910 len = mtext_nchars (mt);
911 if (len == 0 || len != mtext_nbytes (mt))
912 MERROR (MERROR_IM, -1);
913 keyseq = (MSymbol *) alloca (sizeof (MSymbol) * len);
914 for (i = 0; i < len; i++)
915 keyseq[i] = one_char_symbol[MTEXT_DATA (mt)[i]];
917 else if (MPLIST_PLIST_P (keylist))
919 MPlist *elt = MPLIST_PLIST (keylist);
921 len = MPLIST_LENGTH (elt);
923 MERROR (MERROR_IM, -1);
924 keyseq = (MSymbol *) alloca (sizeof (int) * len);
925 for (i = 0; i < len; i++, elt = MPLIST_NEXT (elt))
927 if (MPLIST_INTEGER_P (elt))
929 int c = MPLIST_INTEGER (elt);
931 if (c < 0 || c >= 0x100)
932 MERROR (MERROR_IM, -1);
933 keyseq[i] = one_char_symbol[c];
935 else if (MPLIST_SYMBOL_P (elt))
936 keyseq[i] = MPLIST_SYMBOL (elt);
938 MERROR (MERROR_IM, -1);
942 MERROR (MERROR_IM, -1);
944 for (i = 0; i < len; i++)
946 MIMMap *deeper = NULL;
949 deeper = mplist_get (map->submaps, keyseq[i]);
951 map->submaps = mplist ();
954 /* Fixme: It is better to make all deeper maps at once. */
955 MSTRUCT_CALLOC (deeper, MERROR_IM);
956 mplist_put (map->submaps, keyseq[i], deeper);
961 /* We reach a terminal map. */
963 || map->branch_actions)
964 /* This map is already defined. We avoid overriding it. */
967 if (! MPLIST_TAIL_P (map_actions))
969 if (parse_action_list (map_actions, macros) < 0)
970 MERROR (MERROR_IM, -1);
971 map->map_actions = map_actions;
975 map->branch_actions = branch_actions;
976 M17N_OBJECT_REF (branch_actions);
982 /* Load a branch from PLIST into MAP. PLIST has this form:
983 PLIST ::= ( MAP-NAME BRANCH-ACTION * )
984 MAPS is a plist of raw maps.
985 STATE is the current state. */
988 load_branch (MPlist *plist, MPlist *maps, MIMMap *map,
989 MSymbol language, MSymbol name, MPlist *macros)
992 MPlist *branch_actions;
994 if (! MPLIST_SYMBOL_P (plist))
995 MERROR (MERROR_IM, -1);
996 map_name = MPLIST_SYMBOL (plist);
997 plist = MPLIST_NEXT (plist);
998 if (MPLIST_TAIL_P (plist))
999 branch_actions = NULL;
1000 else if (parse_action_list (plist, macros) < 0)
1001 MERROR (MERROR_IM, -1);
1003 branch_actions = plist;
1004 if (map_name == Mnil)
1006 map->branch_actions = branch_actions;
1008 M17N_OBJECT_REF (branch_actions);
1010 else if (map_name == Mt)
1012 map->map_actions = branch_actions;
1014 M17N_OBJECT_REF (branch_actions);
1016 else if (maps && (plist = (MPlist *) mplist_get (maps, map_name)))
1018 MPLIST_DO (plist, plist)
1020 MPlist *keylist, *map_actions;
1022 if (! MPLIST_PLIST_P (plist))
1023 MERROR (MERROR_IM, -1);
1024 keylist = MPLIST_PLIST (plist);
1025 map_actions = MPLIST_NEXT (keylist);
1026 if (MPLIST_SYMBOL_P (keylist))
1028 MSymbol command = MPLIST_SYMBOL (keylist);
1029 MPlist *pl = resolve_command (language, name, command);
1034 if (load_translation (map, pl, map_actions, branch_actions,
1036 MERROR (MERROR_IM, -1);
1039 if (load_translation (map, keylist, map_actions, branch_actions,
1041 MERROR (MERROR_IM, -1);
1048 /* Load a macro from PLIST into MACROS.
1049 PLIST has this from:
1050 PLIST ::= ( MACRO-NAME ACTION * )
1051 MACROS is a plist of macro names vs action list. */
1053 load_macros (MPlist *plist, MPlist *macros)
1058 if (! MPLIST_SYMBOL_P (plist))
1059 MERROR (MERROR_IM, -1);
1060 name = MPLIST_SYMBOL (plist);
1061 plist = MPLIST_NEXT (plist);
1062 if (MPLIST_TAIL_P (plist)
1063 || parse_action_list (plist, macros) < 0)
1064 MERROR (MERROR_IM, -1);
1065 pl = mplist_get (macros, name);
1067 M17N_OBJECT_UNREF (pl);
1068 mplist_put (macros, name, plist);
1069 M17N_OBJECT_REF (plist);
1073 /* Load an external module from PLIST into EXTERNALS.
1074 PLIST has this form:
1075 PLIST ::= ( MODULE-NAME FUNCTION * )
1076 EXTERNALS is a plist of MODULE-NAME vs (MIMExternalModule *). */
1079 load_external_module (MPlist *plist, MPlist *externals)
1084 MIMExternalModule *external;
1088 if (MPLIST_MTEXT_P (plist))
1089 module = msymbol ((char *) MTEXT_DATA (MPLIST_MTEXT (plist)));
1090 else if (MPLIST_SYMBOL_P (plist))
1091 module = MPLIST_SYMBOL (plist);
1092 module_file = alloca (strlen (MSYMBOL_NAME (module))
1093 + strlen (DLOPEN_SHLIB_EXT) + 1);
1094 sprintf (module_file, "%s%s", MSYMBOL_NAME (module), DLOPEN_SHLIB_EXT);
1096 handle = dlopen (module_file, RTLD_NOW);
1099 fprintf (stderr, "%s\n", dlerror ());
1100 MERROR (MERROR_IM, -1);
1102 func_list = mplist ();
1103 MPLIST_DO (plist, MPLIST_NEXT (plist))
1105 if (! MPLIST_SYMBOL_P (plist))
1106 MERROR_GOTO (MERROR_IM, err_label);
1107 func = dlsym (handle, MSYMBOL_NAME (MPLIST_SYMBOL (plist)));
1109 MERROR_GOTO (MERROR_IM, err_label);
1110 mplist_add (func_list, MPLIST_SYMBOL (plist), func);
1113 MSTRUCT_MALLOC (external, MERROR_IM);
1114 external->handle = handle;
1115 external->func_list = func_list;
1116 mplist_add (externals, module, external);
1121 M17N_OBJECT_UNREF (func_list);
1126 free_map (MIMMap *map, int top)
1131 M17N_OBJECT_UNREF (map->map_actions);
1134 MPLIST_DO (plist, map->submaps)
1135 free_map ((MIMMap *) MPLIST_VAL (plist), 0);
1136 M17N_OBJECT_UNREF (map->submaps);
1138 M17N_OBJECT_UNREF (map->branch_actions);
1143 free_state (void *object)
1145 MIMState *state = object;
1148 M17N_OBJECT_UNREF (state->title);
1150 free_map (state->map, 1);
1154 /** Load a state from PLIST into a newly allocated state object.
1155 PLIST has this form:
1156 PLIST ::= ( STATE-NAME STATE-TITLE ? BRANCH * )
1157 BRANCH ::= ( MAP-NAME BRANCH-ACTION * )
1158 MAPS is a plist of defined maps.
1159 Return the state object. */
1162 load_state (MPlist *plist, MPlist *maps, MSymbol language, MSymbol name,
1167 if (! MPLIST_SYMBOL_P (plist))
1168 MERROR (MERROR_IM, NULL);
1169 M17N_OBJECT (state, free_state, MERROR_IM);
1170 state->name = MPLIST_SYMBOL (plist);
1171 plist = MPLIST_NEXT (plist);
1172 if (MPLIST_MTEXT_P (plist))
1174 state->title = MPLIST_MTEXT (plist);
1175 mtext_put_prop (state->title, 0, mtext_nchars (state->title),
1176 Mlanguage, language);
1177 M17N_OBJECT_REF (state->title);
1178 plist = MPLIST_NEXT (plist);
1180 MSTRUCT_CALLOC (state->map, MERROR_IM);
1181 MPLIST_DO (plist, plist)
1182 if (! MPLIST_PLIST_P (plist)
1183 || load_branch (MPLIST_PLIST (plist), maps, state->map, language, name,
1185 MERROR (MERROR_IM, NULL);
1190 static MPlist *im_info_list;
1193 free_im_info (MInputMethodInfo *im_info)
1198 M17N_OBJECT_UNREF (im_info->title);
1199 if (im_info->states)
1201 MPLIST_DO (plist, im_info->states)
1203 MIMState *state = (MIMState *) MPLIST_VAL (plist);
1205 M17N_OBJECT_UNREF (state);
1207 M17N_OBJECT_UNREF (im_info->states);
1210 if (im_info->macros)
1212 MPLIST_DO (plist, im_info->macros)
1213 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
1214 M17N_OBJECT_UNREF (im_info->macros);
1217 if (im_info->externals)
1219 MPLIST_DO (plist, im_info->externals)
1221 MIMExternalModule *external = MPLIST_VAL (plist);
1223 dlclose (external->handle);
1224 M17N_OBJECT_UNREF (external->func_list);
1226 MPLIST_KEY (plist) = Mt;
1228 M17N_OBJECT_UNREF (im_info->externals);
1232 MPLIST_DO (plist, im_info->maps)
1234 MPlist *p = MPLIST_PLIST (plist);
1236 M17N_OBJECT_UNREF (p);
1238 M17N_OBJECT_UNREF (im_info->maps);
1244 static MInputMethodInfo *get_im_info (MSymbol language, MSymbol name,
1247 static MInputMethodInfo *
1248 get_im_info_by_tags (MPlist *plist)
1253 for (i = 0; i < 3 && MPLIST_SYMBOL_P (plist);
1254 i++, plist = MPLIST_NEXT (plist))
1255 tag[i] = MPLIST_SYMBOL (plist);
1260 return get_im_info (tag[0], tag[1], tag[2]);
1263 /* Load an input method from PLIST into IM_INTO, and return it. */
1265 static MInputMethodInfo *
1266 load_im_info (MSymbol language, MSymbol name, MPlist *plist)
1268 MInputMethodInfo *im_info;
1269 MText *title = NULL;
1270 MPlist *maps = NULL;
1271 MPlist *states = NULL;
1272 MPlist *externals = NULL;
1273 MPlist *macros = NULL;
1276 MSTRUCT_CALLOC (im_info, MERROR_IM);
1278 while (MPLIST_PLIST_P (plist))
1280 elt = MPLIST_PLIST (plist);
1281 if (! MPLIST_SYMBOL_P (elt))
1282 MERROR_GOTO (MERROR_IM, err);
1283 if (MPLIST_SYMBOL (elt) == Mtitle)
1285 elt = MPLIST_NEXT (elt);
1286 if (! MPLIST_MTEXT_P (elt))
1287 MERROR_GOTO (MERROR_IM, err);
1288 im_info->title = title = MPLIST_MTEXT (elt);
1289 M17N_OBJECT_REF (title);
1291 else if (MPLIST_SYMBOL (elt) == Mmap)
1293 MPlist *pl = mplist__from_alist (MPLIST_NEXT (elt));
1296 MERROR_GOTO (MERROR_IM, err);
1298 im_info->maps = maps = pl;
1300 maps = mplist__conc (maps, pl);
1302 else if (MPLIST_SYMBOL (elt) == Mmacro)
1305 im_info->macros = macros = mplist ();
1306 MPLIST_DO (elt, MPLIST_NEXT (elt))
1308 if (! MPLIST_PLIST_P (elt)
1309 || load_macros (MPLIST_PLIST (elt), macros) < 0)
1310 MERROR_GOTO (MERROR_IM, err);
1313 else if (MPLIST_SYMBOL (elt) == Mmodule)
1316 im_info->externals = externals = mplist ();
1317 MPLIST_DO (elt, MPLIST_NEXT (elt))
1319 if (! MPLIST_PLIST_P (elt)
1320 || load_external_module (MPLIST_PLIST (elt), externals) < 0)
1321 MERROR_GOTO (MERROR_IM, err);
1324 else if (MPLIST_SYMBOL (elt) == Mstate)
1326 MPLIST_DO (elt, MPLIST_NEXT (elt))
1330 if (! MPLIST_PLIST_P (elt))
1331 MERROR_GOTO (MERROR_IM, err);
1332 state = load_state (MPLIST_PLIST (elt), maps, language, name,
1335 MERROR_GOTO (MERROR_IM, err);
1337 im_info->states = states = mplist ();
1338 mplist_put (states, state->name, state);
1341 else if (MPLIST_SYMBOL (elt) == Minclude)
1343 /* elt ::= include (tag1 tag2 ...) key item ... */
1345 MInputMethodInfo *temp;
1348 elt = MPLIST_NEXT (elt);
1349 if (! MPLIST_PLIST_P (elt))
1350 MERROR_GOTO (MERROR_IM, err);
1351 temp = get_im_info_by_tags (MPLIST_PLIST (elt));
1353 MERROR_GOTO (MERROR_IM, err);
1354 elt = MPLIST_NEXT (elt);
1355 if (! MPLIST_SYMBOL_P (elt))
1356 MERROR_GOTO (MERROR_IM, err);
1357 key = MPLIST_SYMBOL (elt);
1358 elt = MPLIST_NEXT (elt);
1362 im_info->maps = maps = mplist ();
1363 MPLIST_DO (pl, temp->maps)
1365 p = MPLIST_VAL (pl);
1366 MPLIST_ADD_PLIST (maps, MPLIST_KEY (pl), p);
1367 M17N_OBJECT_REF (p);
1370 else if (key == Mmacro)
1373 im_info->macros = macros = mplist ();
1374 MPLIST_DO (pl, temp->macros)
1376 p = MPLIST_VAL (pl);
1377 MPLIST_ADD_PLIST (macros, MPLIST_KEY (pl), p);
1378 M17N_OBJECT_REF (p);
1381 else if (key == Mstate)
1384 im_info->states = states = mplist ();
1385 MPLIST_DO (pl, temp->states)
1387 MIMState *state = MPLIST_VAL (pl);
1389 mplist_add (states, MPLIST_KEY (pl), state);
1390 M17N_OBJECT_REF (state);
1394 MERROR_GOTO (MERROR_IM, err);
1396 plist = MPLIST_NEXT (plist);
1401 if (! title && name)
1403 = title = mtext_from_data (MSYMBOL_NAME (name), MSYMBOL_NAMELEN (name),
1404 MTEXT_FORMAT_US_ASCII);
1408 free_im_info (im_info);
1414 static int take_action_list (MInputContext *ic, MPlist *action_list);
1415 static void preedit_commit (MInputContext *ic);
1418 shift_state (MInputContext *ic, MSymbol state_name)
1420 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1421 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1422 MIMState *orig_state = ic_info->state, *state;
1424 /* Find a state to shift to. If not found, shift to the initial
1426 if (state_name == Mt)
1428 if (! ic_info->prev_state)
1430 state = ic_info->prev_state;
1434 state = (MIMState *) mplist_get (im_info->states, state_name);
1436 state = (MIMState *) MPLIST_VAL (im_info->states);
1439 MDEBUG_PRINT1 ("\n [IM] (shift %s)", MSYMBOL_NAME (state->name));
1441 /* Enter the new state. */
1442 ic_info->state = state;
1443 ic_info->map = state->map;
1444 ic_info->state_key_head = ic_info->key_head;
1445 if (state == (MIMState *) MPLIST_VAL (im_info->states))
1446 /* We have shifted to the initial state. */
1447 preedit_commit (ic);
1448 mtext_cpy (ic_info->preedit_saved, ic->preedit);
1449 ic_info->state_pos = ic->cursor_pos;
1450 if (state != orig_state )
1452 if (state == (MIMState *) MPLIST_VAL (im_info->states))
1453 ic_info->prev_state = NULL;
1455 ic_info->prev_state = orig_state;
1458 ic->status = state->title;
1460 ic->status = im_info->title;
1461 ic->status_changed = 1;
1462 if (ic_info->map == ic_info->state->map
1463 && ic_info->map->map_actions)
1465 MDEBUG_PRINT (" init-actions:");
1466 take_action_list (ic, ic_info->map->map_actions);
1471 /* Find a candidate group that contains a candidate number INDEX from
1472 PLIST. Set START_INDEX to the first candidate number of the group,
1473 END_INDEX to the last candidate number plus 1, GROUP_INDEX to the
1474 candidate group number if they are non-NULL. If INDEX is -1, find
1475 the last candidate group. */
1478 find_candidates_group (MPlist *plist, int index,
1479 int *start_index, int *end_index, int *group_index)
1481 int i = 0, gidx = 0, len;
1483 MPLIST_DO (plist, plist)
1485 if (MPLIST_MTEXT_P (plist))
1486 len = mtext_nchars (MPLIST_MTEXT (plist));
1488 len = mplist_length (MPLIST_PLIST (plist));
1489 if (index < 0 ? MPLIST_TAIL_P (MPLIST_NEXT (plist))
1495 *end_index = i + len;
1497 *group_index = gidx;
1507 preedit_insert (MInputContext *ic, int pos, MText *mt, int c)
1509 MInputContextInfo *ic_info = ((MInputContext *) ic)->info;
1511 int nchars = mt ? mtext_nchars (mt) : 1;
1514 mtext_ins (ic->preedit, pos, mt);
1516 mtext_ins_char (ic->preedit, pos, c, 1);
1517 MPLIST_DO (markers, ic_info->markers)
1518 if (MPLIST_INTEGER (markers) > pos)
1519 MPLIST_VAL (markers) = (void *) (MPLIST_INTEGER (markers) + nchars);
1520 if (ic->cursor_pos >= pos)
1521 ic->cursor_pos += nchars;
1522 ic->preedit_changed = 1;
1527 preedit_delete (MInputContext *ic, int from, int to)
1529 MInputContextInfo *ic_info = ((MInputContext *) ic)->info;
1532 mtext_del (ic->preedit, from, to);
1533 MPLIST_DO (markers, ic_info->markers)
1535 if (MPLIST_INTEGER (markers) > to)
1536 MPLIST_VAL (markers)
1537 = (void *) (MPLIST_INTEGER (markers) - (to - from));
1538 else if (MPLIST_INTEGER (markers) > from);
1539 MPLIST_VAL (markers) = (void *) from;
1541 if (ic->cursor_pos >= to)
1542 ic->cursor_pos -= to - from;
1543 else if (ic->cursor_pos > from)
1544 ic->cursor_pos = from;
1545 ic->preedit_changed = 1;
1549 preedit_commit (MInputContext *ic)
1551 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1552 int preedit_len = mtext_nchars (ic->preedit);
1554 if (preedit_len > 0)
1558 mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit),
1559 Mcandidate_list, NULL, 0);
1560 mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit),
1561 Mcandidate_index, NULL, 0);
1562 mtext_cat (ic->produced, ic->preedit);
1563 if ((mdebug__flag & mdebug_mask)
1564 && mtext_nchars (ic->preedit) > 0)
1568 MDEBUG_PRINT (" (produced");
1569 for (i = 0; i < mtext_nchars (ic->preedit); i++)
1570 MDEBUG_PRINT1 (" U+%04X", mtext_ref_char (ic->preedit, i));
1573 mtext_reset (ic->preedit);
1574 mtext_reset (ic_info->preedit_saved);
1575 MPLIST_DO (p, ic_info->markers)
1577 ic->cursor_pos = ic_info->state_pos = 0;
1578 ic->preedit_changed = 1;
1580 if (ic->candidate_list)
1582 M17N_OBJECT_UNREF (ic->candidate_list);
1583 ic->candidate_list = NULL;
1584 ic->candidates_changed = MINPUT_CANDIDATES_LIST_CHANGED;
1585 if (ic->candidate_show)
1587 ic->candidate_show = 0;
1588 ic->candidates_changed |= MINPUT_CANDIDATES_SHOW_CHANGED;
1592 memmove (ic_info->keys, ic_info->keys + ic_info->key_head,
1593 sizeof (int) * (ic_info->used - ic_info->key_head));
1594 ic_info->used -= ic_info->key_head;
1595 ic_info->state_key_head = ic_info->key_head = 0;
1599 new_index (MInputContext *ic, int current, int limit, MSymbol sym, MText *mt)
1601 int code = marker_code (sym);
1603 if (mt && (code == '[' || code == ']'))
1607 if (code == '[' && current > 0)
1609 if (mtext_prop_range (mt, Mcandidate_list, pos - 1, &pos, NULL, 1)
1613 else if (code == ']' && current < mtext_nchars (mt))
1615 if (mtext_prop_range (mt, Mcandidate_list, pos, NULL, &pos, 1))
1621 return (code == '<' ? 0
1622 : code == '>' ? limit
1623 : code == '-' ? current - 1
1624 : code == '+' ? current + 1
1625 : code == '=' ? current
1626 : code - '0' > limit ? limit
1630 return (int) mplist_get (((MInputContextInfo *) ic->info)->markers, sym);
1634 update_candidate (MInputContext *ic, MTextProperty *prop, int idx)
1636 int from = mtext_property_start (prop);
1637 int to = mtext_property_end (prop);
1639 MPlist *candidate_list = mtext_property_value (prop);
1640 MPlist *group = find_candidates_group (candidate_list, idx, &start,
1642 int ingroup_index = idx - start;
1645 preedit_delete (ic, from, to);
1646 if (MPLIST_MTEXT_P (group))
1648 mt = MPLIST_MTEXT (group);
1649 preedit_insert (ic, from, NULL, mtext_ref_char (mt, ingroup_index));
1657 for (i = 0, plist = MPLIST_PLIST (group); i < ingroup_index;
1658 i++, plist = MPLIST_NEXT (plist));
1659 mt = MPLIST_MTEXT (plist);
1660 preedit_insert (ic, from, mt, 0);
1661 to = from + mtext_nchars (mt);
1663 mtext_put_prop (ic->preedit, from, to, Mcandidate_list, candidate_list);
1664 mtext_put_prop (ic->preedit, from, to, Mcandidate_index, (void *) idx);
1665 ic->cursor_pos = to;
1669 get_select_charset (MInputContextInfo * ic_info)
1671 MPlist *plist = resolve_variable (ic_info, Mcandidates_charset);
1674 if (! MPLIST_VAL (plist))
1676 sym = MPLIST_SYMBOL (plist);
1679 return MCHARSET (sym);
1683 adjust_candidates (MPlist *plist, MCharset *charset)
1687 /* plist ::= MTEXT ... | PLIST ... */
1688 plist = mplist_copy (plist);
1689 if (MPLIST_MTEXT_P (plist))
1692 while (! MPLIST_TAIL_P (pl))
1694 /* pl ::= MTEXT ... */
1695 MText *mt = MPLIST_MTEXT (pl);
1699 for (i = mtext_nchars (mt) - 1; i >= 0; i--)
1701 c = mtext_ref_char (mt, i);
1702 if (ENCODE_CHAR (charset, c) == MCHAR_INVALID_CODE)
1706 mt = mtext_dup (mt);
1707 mplist_set (pl, Mtext, mt);
1708 M17N_OBJECT_UNREF (mt);
1711 mtext_del (mt, i, i + 1);
1714 if (mtext_len (mt) > 0)
1715 pl = MPLIST_NEXT (pl);
1719 M17N_OBJECT_UNREF (mt);
1723 else /* MPLIST_PLIST_P (plist) */
1726 while (! MPLIST_TAIL_P (pl))
1728 /* pl ::= (MTEXT ...) ... */
1729 MPlist *p = MPLIST_PLIST (pl);
1731 /* p ::= MTEXT ... */
1735 while (! MPLIST_TAIL_P (p0))
1737 MText *mt = MPLIST_MTEXT (p0);
1740 for (i = mtext_nchars (mt) - 1; i >= 0; i--)
1742 c = mtext_ref_char (mt, i);
1743 if (ENCODE_CHAR (charset, c) == MCHAR_INVALID_CODE)
1748 p0 = MPLIST_NEXT (p0);
1755 p = mplist_copy (p);
1756 mplist_set (pl, Mplist, p);
1757 M17N_OBJECT_UNREF (p);
1761 p0 = MPLIST_NEXT (p0);
1764 M17N_OBJECT_UNREF (mt);
1767 if (! MPLIST_TAIL_P (p))
1768 pl = MPLIST_NEXT (pl);
1772 M17N_OBJECT_UNREF (p);
1776 if (MPLIST_TAIL_P (plist))
1778 M17N_OBJECT_UNREF (plist);
1785 get_candidate_list (MInputContextInfo *ic_info, MPlist *args)
1787 MCharset *charset = get_select_charset (ic_info);
1792 plist = resolve_variable (ic_info, Mcandidates_group_size);
1793 column = MPLIST_INTEGER (plist);
1795 plist = MPLIST_PLIST (args);
1798 if (! (plist = adjust_candidates (plist, charset)))
1802 M17N_OBJECT_REF (plist);
1806 if (MPLIST_MTEXT_P (plist))
1808 MText *mt = MPLIST_MTEXT (plist);
1809 MPlist *next = MPLIST_NEXT (plist);
1811 if (MPLIST_TAIL_P (next))
1812 M17N_OBJECT_REF (mt);
1815 mt = mtext_dup (mt);
1816 while (! MPLIST_TAIL_P (next))
1818 mt = mtext_cat (mt, MPLIST_MTEXT (next));
1819 next = MPLIST_NEXT (next);
1822 M17N_OBJECT_UNREF (plist);
1824 len = mtext_nchars (mt);
1826 mplist_add (plist, Mtext, mt);
1829 for (i = 0; i < len; i += column)
1831 int to = (i + column < len ? i + column : len);
1832 MText *sub = mtext_copy (mtext (), 0, mt, i, to);
1834 mplist_add (plist, Mtext, sub);
1835 M17N_OBJECT_UNREF (sub);
1838 M17N_OBJECT_UNREF (mt);
1840 else /* MPLIST_PLIST_P (plist) */
1842 MPlist *pl = MPLIST_PLIST (plist), *p;
1843 MPlist *next = MPLIST_NEXT (plist);
1846 if (MPLIST_TAIL_P (next))
1847 M17N_OBJECT_REF (pl);
1850 pl = mplist_copy (pl);
1851 while (! MPLIST_TAIL_P (next))
1853 p = mplist_copy (MPLIST_PLIST (next));
1854 pl = mplist__conc (pl, p);
1855 M17N_OBJECT_UNREF (p);
1856 next = MPLIST_NEXT (next);
1859 M17N_OBJECT_UNREF (plist);
1861 len = mplist_length (pl);
1863 mplist_add (plist, Mplist, pl);
1868 for (i = 0; i < len; i += column)
1871 mplist_add (plist, Mplist, p);
1872 M17N_OBJECT_UNREF (p);
1873 for (j = 0; j < column && i + j < len; j++)
1875 p = mplist_add (p, Mtext, MPLIST_VAL (p0));
1876 p0 = MPLIST_NEXT (p0);
1880 M17N_OBJECT_UNREF (pl);
1889 regularize_action (MPlist *action_list)
1891 MPlist *action = NULL;
1895 if (MPLIST_PLIST_P (action_list))
1897 action = MPLIST_PLIST (action_list);
1898 if (MPLIST_SYMBOL_P (action))
1900 name = MPLIST_SYMBOL (action);
1901 args = MPLIST_NEXT (action);
1903 && MPLIST_PLIST_P (args))
1904 mplist_set (action, Msymbol, M_candidates);
1906 else if (MPLIST_MTEXT_P (action) || MPLIST_PLIST_P (action))
1909 mplist_push (action, Mplist, MPLIST_VAL (action_list));
1910 mplist_push (action, Msymbol, M_candidates);
1911 mplist_set (action_list, Mplist, action);
1912 M17N_OBJECT_UNREF (action);
1915 else if (MPLIST_MTEXT_P (action_list) || MPLIST_INTEGER_P (action_list))
1918 mplist_push (action, MPLIST_KEY (action_list), MPLIST_VAL (action_list));
1919 mplist_push (action, Msymbol, Minsert);
1920 mplist_set (action_list, Mplist, action);
1921 M17N_OBJECT_UNREF (action);
1927 take_action_list (MInputContext *ic, MPlist *action_list)
1929 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1930 MPlist *candidate_list = ic->candidate_list;
1931 int candidate_index = ic->candidate_index;
1932 int candidate_show = ic->candidate_show;
1933 MTextProperty *prop;
1935 MPLIST_DO (action_list, action_list)
1937 MPlist *action = regularize_action (action_list);
1943 name = MPLIST_SYMBOL (action);
1944 args = MPLIST_NEXT (action);
1946 MDEBUG_PRINT1 (" %s", MSYMBOL_NAME (name));
1947 if (name == Minsert)
1949 if (MPLIST_SYMBOL_P (args))
1951 args = resolve_variable (ic_info, MPLIST_SYMBOL (args));
1952 if (! MPLIST_MTEXT_P (args) && ! MPLIST_INTEGER_P (args))
1955 if (MPLIST_MTEXT_P (args))
1956 preedit_insert (ic, ic->cursor_pos, MPLIST_MTEXT (args), 0);
1957 else /* MPLIST_INTEGER_P (args)) */
1958 preedit_insert (ic, ic->cursor_pos, NULL, MPLIST_INTEGER (args));
1960 else if (name == M_candidates)
1962 MPlist *plist = get_candidate_list (ic_info, args);
1967 if (MPLIST_MTEXT_P (plist))
1969 preedit_insert (ic, ic->cursor_pos, NULL,
1970 mtext_ref_char (MPLIST_MTEXT (plist), 0));
1975 MText * mt = MPLIST_MTEXT (MPLIST_PLIST (plist));
1977 preedit_insert (ic, ic->cursor_pos, mt, 0);
1978 len = mtext_nchars (mt);
1980 mtext_put_prop (ic->preedit,
1981 ic->cursor_pos - len, ic->cursor_pos,
1982 Mcandidate_list, plist);
1983 mtext_put_prop (ic->preedit,
1984 ic->cursor_pos - len, ic->cursor_pos,
1985 Mcandidate_index, (void *) 0);
1986 M17N_OBJECT_UNREF (plist);
1988 else if (name == Mselect)
1991 int code, idx, gindex;
1992 int pos = ic->cursor_pos;
1996 || ! (prop = mtext_get_property (ic->preedit, pos - 1,
1999 if (MPLIST_SYMBOL_P (args))
2001 code = marker_code (MPLIST_SYMBOL (args));
2007 idx = (int) mtext_get_prop (ic->preedit, pos - 1, Mcandidate_index);
2008 group = find_candidates_group (mtext_property_value (prop), idx,
2009 &start, &end, &gindex);
2011 if (code != '[' && code != ']')
2015 ? new_index (NULL, ic->candidate_index - start,
2016 end - start - 1, MPLIST_SYMBOL (args),
2018 : MPLIST_INTEGER (args)));
2021 find_candidates_group (mtext_property_value (prop), -1,
2026 && MPLIST_TAIL_P (MPLIST_NEXT (group)))
2031 int ingroup_index = idx - start;
2034 group = mtext_property_value (prop);
2035 len = mplist_length (group);
2048 for (idx = 0; gindex > 0; gindex--, group = MPLIST_NEXT (group))
2049 idx += (MPLIST_MTEXT_P (group)
2050 ? mtext_nchars (MPLIST_MTEXT (group))
2051 : mplist_length (MPLIST_PLIST (group)));
2052 len = (MPLIST_MTEXT_P (group)
2053 ? mtext_nchars (MPLIST_MTEXT (group))
2054 : mplist_length (MPLIST_PLIST (group)));
2055 if (ingroup_index >= len)
2056 ingroup_index = len - 1;
2057 idx += ingroup_index;
2059 update_candidate (ic, prop, idx);
2061 else if (name == Mshow)
2062 ic->candidate_show = 1;
2063 else if (name == Mhide)
2064 ic->candidate_show = 0;
2065 else if (name == Mdelete)
2067 int len = mtext_nchars (ic->preedit);
2071 if (MPLIST_SYMBOL_P (args)
2072 && (pos = surrounding_pos (MPLIST_SYMBOL (args))) != 0)
2074 delete_surrounding_text (ic, pos);
2078 to = (MPLIST_SYMBOL_P (args)
2079 ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
2081 : MPLIST_INTEGER (args));
2086 MDEBUG_PRINT1 ("(%d)", to - ic->cursor_pos);
2087 if (to < ic->cursor_pos)
2088 preedit_delete (ic, to, ic->cursor_pos);
2089 else if (to > ic->cursor_pos)
2090 preedit_delete (ic, ic->cursor_pos, to);
2093 else if (name == Mmove)
2095 int len = mtext_nchars (ic->preedit);
2097 = (MPLIST_SYMBOL_P (args)
2098 ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
2100 : MPLIST_INTEGER (args));
2106 if (pos != ic->cursor_pos)
2108 ic->cursor_pos = pos;
2109 ic->preedit_changed = 1;
2112 else if (name == Mmark)
2114 int code = marker_code (MPLIST_SYMBOL (args));
2117 mplist_put (ic_info->markers, MPLIST_SYMBOL (args),
2118 (void *) ic->cursor_pos);
2120 else if (name == Mpushback)
2122 if (MPLIST_INTEGER_P (args))
2124 int num = MPLIST_INTEGER (args);
2127 ic_info->key_head -= num;
2129 ic_info->key_head = num;
2130 if (ic_info->key_head > ic_info->used)
2131 ic_info->key_head = ic_info->used;
2133 else if (MPLIST_MTEXT_P (args))
2135 MText *mt = MPLIST_MTEXT (args);
2136 int i, len = mtext_nchars (mt);
2139 ic_info->key_head--;
2140 for (i = 0; i < len; i++)
2142 key = one_char_symbol[MTEXT_DATA (mt)[i]];
2143 if (ic_info->key_head + i < ic_info->used)
2144 ic_info->keys[ic_info->key_head + i] = key;
2146 MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
2151 MPlist *plist = MPLIST_PLIST (args), *pl;
2155 ic_info->key_head--;
2157 MPLIST_DO (pl, plist)
2159 key = MPLIST_SYMBOL (pl);
2160 if (ic_info->key_head < ic_info->used)
2161 ic_info->keys[ic_info->key_head + i] = key;
2163 MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
2168 else if (name == Mcall)
2170 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
2171 MIMExternalFunc func = NULL;
2172 MSymbol module, func_name;
2173 MPlist *func_args, *val;
2176 module = MPLIST_SYMBOL (args);
2177 args = MPLIST_NEXT (args);
2178 func_name = MPLIST_SYMBOL (args);
2180 if (im_info->externals)
2182 MIMExternalModule *external
2183 = (MIMExternalModule *) mplist_get (im_info->externals,
2186 func = (MIMExternalFunc) mplist_get (external->func_list,
2191 func_args = mplist ();
2192 mplist_add (func_args, Mt, ic);
2193 MPLIST_DO (args, MPLIST_NEXT (args))
2197 if (MPLIST_KEY (args) == Msymbol
2198 && MPLIST_KEY (args) != Mnil
2199 && (code = marker_code (MPLIST_SYMBOL (args))) >= 0)
2201 code = new_index (ic, ic->cursor_pos,
2202 mtext_nchars (ic->preedit),
2203 MPLIST_SYMBOL (args), ic->preedit);
2204 mplist_add (func_args, Minteger, (void *) code);
2207 mplist_add (func_args, MPLIST_KEY (args), MPLIST_VAL (args));
2209 val = (func) (func_args);
2210 M17N_OBJECT_UNREF (func_args);
2211 if (val && ! MPLIST_TAIL_P (val))
2212 ret = take_action_list (ic, val);
2213 M17N_OBJECT_UNREF (val);
2217 else if (name == Mshift)
2219 shift_state (ic, MPLIST_SYMBOL (args));
2221 else if (name == Mundo)
2223 int intarg = (MPLIST_TAIL_P (args)
2225 : integer_value (ic, args, NULL, 0));
2227 mtext_reset (ic->preedit);
2228 mtext_reset (ic_info->preedit_saved);
2229 ic->cursor_pos = ic_info->state_pos = 0;
2230 ic_info->state_key_head = ic_info->key_head = 0;
2233 ic_info->used += intarg;
2235 ic_info->used = intarg;
2236 shift_state (ic, Mnil);
2239 else if (name == Mset || name == Madd || name == Msub
2240 || name == Mmul || name == Mdiv)
2242 MSymbol sym = MPLIST_SYMBOL (args);
2247 val1 = integer_value (ic, args, &value, 0);
2248 args = MPLIST_NEXT (args);
2249 val2 = resolve_expression (ic, args);
2251 val1 = val2, op = "=";
2252 else if (name == Madd)
2253 val1 += val2, op = "+=";
2254 else if (name == Msub)
2255 val1 -= val2, op = "-=";
2256 else if (name == Mmul)
2257 val1 *= val2, op = "*=";
2259 val1 /= val2, op = "/=";
2260 MDEBUG_PRINT4 ("(%s %s 0x%X(%d))",
2261 MSYMBOL_NAME (sym), op, val1, val1);
2263 mplist_set (value, Minteger, (void *) val1);
2265 else if (name == Mequal || name == Mless || name == Mgreater
2266 || name == Mless_equal || name == Mgreater_equal)
2269 MPlist *actions1, *actions2;
2272 val1 = resolve_expression (ic, args);
2273 args = MPLIST_NEXT (args);
2274 val2 = resolve_expression (ic, args);
2275 args = MPLIST_NEXT (args);
2276 actions1 = MPLIST_PLIST (args);
2277 args = MPLIST_NEXT (args);
2278 if (MPLIST_TAIL_P (args))
2281 actions2 = MPLIST_PLIST (args);
2282 MDEBUG_PRINT3 ("(%d %s %d)? ", val1, MSYMBOL_NAME (name), val2);
2283 if (name == Mequal ? val1 == val2
2284 : name == Mless ? val1 < val2
2285 : name == Mgreater ? val1 > val2
2286 : name == Mless_equal ? val1 <= val2
2289 MDEBUG_PRINT ("ok");
2290 ret = take_action_list (ic, actions1);
2294 MDEBUG_PRINT ("no");
2296 ret = take_action_list (ic, actions2);
2301 else if (name == Mcond)
2305 MPLIST_DO (args, args)
2310 if (! MPLIST_PLIST (args))
2312 cond = MPLIST_PLIST (args);
2313 if (resolve_expression (ic, cond) != 0)
2315 MDEBUG_PRINT1 ("(%dth)", idx);
2316 if (take_action_list (ic, MPLIST_NEXT (cond)) < 0)
2322 else if (name == Mcommit)
2324 preedit_commit (ic);
2326 else if (name == Munhandle)
2328 preedit_commit (ic);
2333 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
2337 && (actions = mplist_get (im_info->macros, name)))
2339 if (take_action_list (ic, actions) < 0)
2346 if (ic->candidate_list)
2348 M17N_OBJECT_UNREF (ic->candidate_list);
2349 ic->candidate_list = NULL;
2351 if (ic->cursor_pos > 0
2352 && (prop = mtext_get_property (ic->preedit, ic->cursor_pos - 1,
2355 ic->candidate_list = mtext_property_value (prop);
2356 M17N_OBJECT_REF (ic->candidate_list);
2358 = (int) mtext_get_prop (ic->preedit, ic->cursor_pos - 1,
2360 ic->candidate_from = mtext_property_start (prop);
2361 ic->candidate_to = mtext_property_end (prop);
2364 if (candidate_list != ic->candidate_list)
2365 ic->candidates_changed |= MINPUT_CANDIDATES_LIST_CHANGED;
2366 if (candidate_index != ic->candidate_index)
2367 ic->candidates_changed |= MINPUT_CANDIDATES_INDEX_CHANGED;
2368 if (candidate_show != ic->candidate_show)
2369 ic->candidates_changed |= MINPUT_CANDIDATES_SHOW_CHANGED;
2374 /* Handle the input key KEY in the current state and map specified in
2375 the input context IC. If KEY is handled correctly, return 0.
2376 Otherwise, return -1. */
2379 handle_key (MInputContext *ic)
2381 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
2382 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
2383 MIMMap *map = ic_info->map;
2384 MIMMap *submap = NULL;
2385 MSymbol key = ic_info->keys[ic_info->key_head];
2386 MSymbol alias = Mnil;
2389 MDEBUG_PRINT2 (" [IM] handle `%s' in state %s",
2390 msymbol_name (key), MSYMBOL_NAME (ic_info->state->name));
2394 submap = mplist_get (map->submaps, key);
2395 if (! submap && (alias = msymbol_get (key, M_key_alias)) != Mnil)
2396 submap = mplist_get (map->submaps, alias);
2402 MDEBUG_PRINT (" submap-found");
2404 MDEBUG_PRINT1 (" submap-found (by alias `%s')", MSYMBOL_NAME (alias));
2405 mtext_cpy (ic->preedit, ic_info->preedit_saved);
2406 ic->preedit_changed = 1;
2407 ic->cursor_pos = ic_info->state_pos;
2408 ic_info->key_head++;
2409 ic_info->map = map = submap;
2410 if (map->map_actions)
2412 MDEBUG_PRINT (" map-actions:");
2413 if (take_action_list (ic, map->map_actions) < 0)
2415 MDEBUG_PRINT ("\n");
2419 else if (map->submaps)
2421 for (i = ic_info->state_key_head; i < ic_info->key_head; i++)
2423 MSymbol key = ic_info->keys[i];
2424 char *name = msymbol_name (key);
2426 if (! name[0] || ! name[1])
2427 mtext_ins_char (ic->preedit, ic->cursor_pos++, name[0], 1);
2431 /* If this is the terminal map or we have shifted to another
2432 state, perform branch actions (if any). */
2433 if (! map->submaps || map != ic_info->map)
2435 if (map->branch_actions)
2437 MDEBUG_PRINT (" branch-actions:");
2438 if (take_action_list (ic, map->branch_actions) < 0)
2440 MDEBUG_PRINT ("\n");
2444 /* If MAP is still not the root map, shift to the current
2446 if (ic_info->map != ic_info->state->map)
2447 shift_state (ic, ic_info->state->name);
2452 /* MAP can not handle KEY. */
2454 /* If MAP is the root map of the initial state, it means that
2455 the current input method can not handle KEY. */
2456 if (map == ((MIMState *) MPLIST_VAL (im_info->states))->map)
2458 MDEBUG_PRINT (" unhandled\n");
2462 if (map != ic_info->state->map)
2464 /* If MAP is not the root map... */
2465 /* If MAP has branch actions, perform them. */
2466 if (map->branch_actions)
2468 MDEBUG_PRINT (" branch-actions:");
2469 if (take_action_list (ic, map->branch_actions) < 0)
2471 MDEBUG_PRINT ("\n");
2475 /* If MAP is still not the root map, shift to the current
2477 if (ic_info->map != ic_info->state->map)
2478 shift_state (ic, ic_info->state->name);
2482 /* MAP is the root map, perform branch actions (if any) or
2483 shift to the initial state. */
2484 if (map->branch_actions)
2486 MDEBUG_PRINT (" branch-actions:");
2487 if (take_action_list (ic, map->branch_actions) < 0)
2489 MDEBUG_PRINT ("\n");
2494 shift_state (ic, Mnil);
2497 MDEBUG_PRINT ("\n");
2502 reset_ic (MInputContext *ic, MSymbol ignore)
2504 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
2505 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
2509 MDEBUG_PRINT ("\n [IM] reset\n");
2511 ic_info->state = (MIMState *) MPLIST_VAL (im_info->states);
2512 ic_info->prev_state = NULL;
2513 ic_info->map = ic_info->state->map;
2514 ic_info->state_key_head = ic_info->key_head = 0;
2515 MLIST_RESET (ic_info);
2516 ic_info->key_unhandled = 0;
2518 if (mtext_nchars (ic->produced) > 0)
2519 mtext_reset (ic->produced);
2520 if (mtext_nchars (ic->preedit) > 0)
2522 mtext_reset (ic->preedit);
2523 ic->preedit_changed = ic->cursor_pos_changed = 1;
2525 MPLIST_DO (plist, ic_info->markers)
2526 MPLIST_VAL (plist) = 0;
2528 M17N_OBJECT_UNREF (ic_info->vars);
2529 ic_info->vars = mplist ();
2530 plist = get_nested_list (ic->im->language, ic->im->name, Mnil, M_variable);
2531 MPLIST_DO (plist, plist)
2533 MSymbol var = MPLIST_SYMBOL (plist);
2536 plist = MPLIST_NEXT (plist);
2537 pl = MPLIST_PLIST (plist);
2538 pl = MPLIST_NEXT (pl); /* Skip description. */
2539 mplist_push (ic_info->vars, MPLIST_KEY (pl), MPLIST_VAL (pl));
2540 mplist_push (ic_info->vars, Msymbol, var);
2543 if (ic->candidate_list)
2545 M17N_OBJECT_UNREF (ic->candidate_list);
2546 ic->candidate_list = NULL;
2547 ic->candidates_changed |= MINPUT_CANDIDATES_LIST_CHANGED;
2549 if (ic->candidate_show)
2551 ic->candidate_show = 0;
2552 ic->candidates_changed |= MINPUT_CANDIDATES_SHOW_CHANGED;
2554 if (ic->candidate_index > 0)
2556 ic->candidate_index = 0;
2557 ic->candidates_changed |= MINPUT_CANDIDATES_INDEX_CHANGED;
2560 mtext_reset (ic_info->preedit_saved);
2561 ic_info->state_pos = ic->cursor_pos = 0;
2563 status = ic_info->state->title ? ic_info->state->title : im_info->title;
2564 if (ic->status != status)
2566 ic->status = status;
2567 ic->status_changed = 1;
2572 open_im (MInputMethod *im)
2574 MInputMethodInfo *im_info = get_im_info (im->language, im->name, Mnil);
2577 MERROR (MERROR_IM, -1);
2584 close_im (MInputMethod *im)
2590 create_ic (MInputContext *ic)
2592 MInputMethod *im = ic->im;
2593 MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
2594 MInputContextInfo *ic_info;
2598 ic_info = (MInputContextInfo *) ic->info;
2601 MSTRUCT_CALLOC (ic_info, MERROR_IM);
2604 MLIST_INIT1 (ic_info, keys, 8);
2605 ic_info->markers = mplist ();
2606 ic_info->vars = mplist ();
2607 plist = get_nested_list (im->language, im->name, Mnil, M_variable);
2608 MPLIST_DO (plist, plist)
2610 MSymbol var = MPLIST_SYMBOL (plist);
2613 plist = MPLIST_NEXT (plist);
2614 pl = MPLIST_PLIST (plist);
2615 pl = MPLIST_NEXT (pl); /* Skip description. */
2616 mplist_push (ic_info->vars, MPLIST_KEY (pl), MPLIST_VAL (pl));
2617 mplist_push (ic_info->vars, Msymbol, var);
2620 ic_info->preedit_saved = mtext ();
2621 if (im_info->externals)
2623 MPlist *func_args = mplist (), *plist;
2625 mplist_add (func_args, Mt, ic);
2626 MPLIST_DO (plist, im_info->externals)
2628 MIMExternalModule *external = MPLIST_VAL (plist);
2629 MIMExternalFunc func
2630 = (MIMExternalFunc) mplist_get (external->func_list, Minit);
2635 M17N_OBJECT_UNREF (func_args);
2637 reset_ic (ic, Mnil);
2642 destroy_ic (MInputContext *ic)
2644 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
2645 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
2647 if (im_info->externals)
2649 MPlist *func_args = mplist (), *plist;
2651 mplist_add (func_args, Mt, ic);
2652 MPLIST_DO (plist, im_info->externals)
2654 MIMExternalModule *external = MPLIST_VAL (plist);
2655 MIMExternalFunc func
2656 = (MIMExternalFunc) mplist_get (external->func_list, Mfini);
2661 M17N_OBJECT_UNREF (func_args);
2663 MLIST_FREE1 (ic_info, keys);
2664 M17N_OBJECT_UNREF (ic_info->preedit_saved);
2665 M17N_OBJECT_UNREF (ic_info->markers);
2666 M17N_OBJECT_UNREF (ic_info->vars);
2667 M17N_OBJECT_UNREF (ic_info->preceding_text);
2668 M17N_OBJECT_UNREF (ic_info->following_text);
2673 /** Handle the input key KEY in the current state and map of IC->info.
2674 If KEY is handled but no text is produced, return 0, otherwise
2680 filter (MInputContext *ic, MSymbol key, void *arg)
2682 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
2683 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
2686 if (! ic_info->state)
2688 ic_info->key_unhandled = 1;
2691 mtext_reset (ic->produced);
2692 ic->status_changed = ic->preedit_changed = ic->candidates_changed = 0;
2693 M17N_OBJECT_UNREF (ic_info->preceding_text);
2694 M17N_OBJECT_UNREF (ic_info->following_text);
2695 MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
2696 ic_info->key_unhandled = 0;
2698 /* If KEY has Meta or Alt modifier, put M_key_alias property. */
2701 if (! msymbol_get (key, M_key_alias)
2702 && (strchr (MSYMBOL_NAME (key), 'M')
2703 || strchr (MSYMBOL_NAME (key), 'A')))
2705 char *name = MSYMBOL_NAME (key);
2708 while (name[0] && name[1] == '-'
2709 && (name[0] != 'M' && name[0] != 'A'))
2711 if ((name[0] == 'M' || name[0] == 'A') && name[1] == '-')
2716 name = alloca (MSYMBOL_NAMELEN (key) + 1);
2717 memcpy (name, MSYMBOL_NAME (key), MSYMBOL_NAMELEN (key) + 1);
2718 name[meta_or_alt - MSYMBOL_NAME (key)]
2719 = *meta_or_alt == 'M' ? 'A' : 'M';
2720 alias = msymbol (name);
2721 msymbol_put (key, M_key_alias, alias);
2724 else if (MSYMBOL_NAMELEN (key) == 3
2725 && MSYMBOL_NAME (key)[0] == 'S'
2726 && MSYMBOL_NAME (key)[1] == '-'
2727 && MSYMBOL_NAME (key)[2] >= 'A' && MSYMBOL_NAME (key)[2] <= 'Z')
2728 msymbol_put (key, M_key_alias, one_char_symbol[(int)MSYMBOL_NAME (key)[2]]);
2732 if (handle_key (ic) < 0)
2734 /* KEY was not handled. Delete it from the current key sequence. */
2735 if (ic_info->used > 0)
2737 memmove (ic_info->keys, ic_info->keys + 1,
2738 sizeof (int) * (ic_info->used - 1));
2741 /* This forces returning 1. */
2742 ic_info->key_unhandled = 1;
2748 reset_ic (ic, Mnil);
2749 ic_info->key_unhandled = 1;
2752 /* Break the loop if all keys were handled. */
2753 } while (ic_info->key_head < ic_info->used);
2755 /* If the current map is the root of the initial state, we should
2756 produce any preedit text in ic->produced. */
2757 if (ic_info->map == ((MIMState *) MPLIST_VAL (im_info->states))->map
2758 && mtext_nchars (ic->preedit) > 0)
2759 shift_state (ic, ((MIMState *) MPLIST_VAL (im_info->states))->name);
2761 if (mtext_nchars (ic->produced) > 0)
2763 MSymbol lang = msymbol_get (ic->im->language, Mlanguage);
2766 mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
2767 Mlanguage, ic->im->language);
2770 return (! ic_info->key_unhandled && mtext_nchars (ic->produced) == 0);
2774 /** Return 1 if the last event or key was not handled, otherwise
2777 There is no need of looking up because ic->produced should already
2778 contain the produced text (if any).
2783 lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2785 mtext_cat (mt, ic->produced);
2786 mtext_reset (ic->produced);
2787 return (((MInputContextInfo *) ic->info)->key_unhandled ? -1 : 0);
2790 static MPlist *load_im_info_keys;
2793 load_partial_im_info (MSymbol language, MSymbol name,
2794 MSymbol extra, MSymbol key)
2799 if (language == Mnil)
2800 MERROR (MERROR_IM, NULL);
2801 mdb = mdatabase_find (Minput_method, language, name, extra);
2803 MERROR (MERROR_IM, NULL);
2805 mplist_push (load_im_info_keys, key, Mt);
2806 plist = mdatabase__load_for_keys (mdb, load_im_info_keys);
2807 mplist_pop (load_im_info_keys);
2812 static MInputMethodInfo *
2813 get_im_info (MSymbol language, MSymbol name, MSymbol extra)
2817 MInputMethodInfo *im_info = NULL;
2819 if (language == Mnil)
2820 MERROR (MERROR_IM, NULL);
2821 mdb = mdatabase_find (Minput_method, language, name, extra);
2823 MERROR (MERROR_IM, NULL);
2826 im_info_list = mplist ();
2827 else if ((plist = mplist_find_by_value (im_info_list, mdb)))
2829 if (mdatabase__check (mdb))
2831 plist = MPLIST_NEXT (plist);
2832 im_info = MPLIST_VAL (plist);
2836 free_im_info (MPLIST_VAL (plist));
2840 plist = mdatabase_load (mdb);
2842 MERROR (MERROR_IM, NULL);
2843 im_info = load_im_info (language, name, plist);
2844 M17N_OBJECT_UNREF (plist);
2846 MERROR (MERROR_IM, NULL);
2847 mplist_push (im_info_list, Mt, im_info);
2848 mplist_push (im_info_list, Mt, mdb);
2853 /* Input method command handler. */
2855 /* List of all (global and local) commands.
2856 (LANG:(IM-NAME:(COMMAND ...) ...) ...) ...
2857 COMMAND is CMD-NAME:(mtext:DESCRIPTION plist:KEYSEQ ...))
2858 Global commands are storead as (t (t COMMAND ...)) */
2860 /* Check if PLIST is a valid command key sequence.
2861 PLIST must be NULL or:
2862 [ symbol:KEY | integer:KEY ] ... */
2865 check_command_keyseq (MPlist *plist)
2869 MPLIST_DO (plist, plist)
2871 if (MPLIST_SYMBOL_P (plist))
2873 else if (MPLIST_INTEGER_P (plist))
2875 int n = MPLIST_INTEGER (plist);
2879 MPLIST_KEY (plist) = Msymbol;
2880 MPLIST_VAL (plist) = one_char_symbol['0' + 9];
2888 /* Check if PLIST has this form:
2889 ([ plist:([ symbol:KEY | integer:KEY ]) | mtext:KEYSEQ ]
2891 If the form of PLIST matches, return 0, otherwise return -1. */
2894 check_command_list (MPlist *plist)
2896 MPLIST_DO (plist, plist)
2898 if (MPLIST_PLIST_P (plist))
2900 MPlist *pl = MPLIST_PLIST (plist);
2903 if (! MPLIST_SYMBOL_P (pl) && ! MPLIST_INTEGER_P (pl))
2906 else if (! MPLIST_MTEXT_P (plist))
2914 /* Input method variable handler. */
2916 /* Check if PLIST has this form:
2917 (TYPE:VAL ;; TYPE ::= integer | mtext | symbol
2920 If the form of PLIST matches, return 0, otherwise return -1. */
2923 check_variable_list (MPlist *plist)
2925 MSymbol type = MPLIST_KEY (plist);
2928 if (type != Minteger && type != Mtext && type != Msymbol)
2930 MPLIST_DO (plist, MPLIST_NEXT (plist))
2932 if (type == Minteger && MPLIST_PLIST_P (plist))
2934 MPLIST_DO (p, MPLIST_PLIST (plist))
2935 if (! MPLIST_INTEGER_P (p))
2938 else if (type != MPLIST_KEY (plist))
2944 /* Support functions for mdebug_dump_im. */
2947 dump_im_map (MPlist *map_list, int indent)
2950 MSymbol key = MPLIST_KEY (map_list);
2951 MIMMap *map = (MIMMap *) MPLIST_VAL (map_list);
2953 prefix = (char *) alloca (indent + 1);
2954 memset (prefix, 32, indent);
2955 prefix[indent] = '\0';
2957 fprintf (stderr, "(\"%s\" ", msymbol_name (key));
2958 if (map->map_actions)
2959 mdebug_dump_plist (map->map_actions, indent + 2);
2962 MPLIST_DO (map_list, map->submaps)
2964 fprintf (stderr, "\n%s ", prefix);
2965 dump_im_map (map_list, indent + 2);
2968 if (map->branch_actions)
2970 fprintf (stderr, "\n%s (branch\n%s ", prefix, prefix);
2971 mdebug_dump_plist (map->branch_actions, indent + 4);
2972 fprintf (stderr, ")");
2974 fprintf (stderr, ")");
2979 dump_im_state (MIMState *state, int indent)
2984 prefix = (char *) alloca (indent + 1);
2985 memset (prefix, 32, indent);
2986 prefix[indent] = '\0';
2988 fprintf (stderr, "(%s", msymbol_name (state->name));
2989 if (state->map->submaps)
2991 MPLIST_DO (map_list, state->map->submaps)
2993 fprintf (stderr, "\n%s ", prefix);
2994 dump_im_map (map_list, indent + 2);
2997 fprintf (stderr, ")");
3006 = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3007 "BackSpace", "Tab", "Linefeed", "Clear", NULL, "Return", NULL, NULL,
3008 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3009 NULL, NULL, NULL, "Escape", NULL, NULL, NULL, NULL };
3010 char buf[6], buf2[256];
3013 Minput_method = msymbol ("input-method");
3014 Minput_driver = msymbol ("input-driver");
3015 Mtitle = msymbol ("title");
3016 Mmacro = msymbol ("macro");
3017 Mmodule = msymbol ("module");
3018 Mmap = msymbol ("map");
3019 Mstate = msymbol ("state");
3020 Minclude = msymbol ("include");
3021 Minsert = msymbol ("insert");
3022 M_candidates = msymbol (" candidates");
3023 Mdelete = msymbol ("delete");
3024 Mmove = msymbol ("move");
3025 Mmark = msymbol ("mark");
3026 Mpushback = msymbol ("pushback");
3027 Mundo = msymbol ("undo");
3028 Mcall = msymbol ("call");
3029 Mshift = msymbol ("shift");
3030 Mselect = msymbol ("select");
3031 Mshow = msymbol ("show");
3032 Mhide = msymbol ("hide");
3033 Mcommit = msymbol ("commit");
3034 Munhandle = msymbol ("unhandle");
3035 Mset = msymbol ("set");
3036 Madd = msymbol ("add");
3037 Msub = msymbol ("sub");
3038 Mmul = msymbol ("mul");
3039 Mdiv = msymbol ("div");
3040 Mequal = msymbol ("=");
3041 Mless = msymbol ("<");
3042 Mgreater = msymbol (">");
3043 Mless_equal = msymbol ("<=");
3044 Mgreater_equal = msymbol (">=");
3045 Mcond = msymbol ("cond");
3046 Mplus = msymbol ("+");
3047 Mminus = msymbol ("-");
3048 Mstar = msymbol ("*");
3049 Mslush = msymbol ("/");
3050 Mand = msymbol ("&");
3051 Mor = msymbol ("|");
3052 Mnot = msymbol ("!");
3054 Mcandidates_group_size = msymbol ("candidates-group-size");
3055 Mcandidates_charset = msymbol ("candidates-charset");
3057 Minput_preedit_start = msymbol ("input-preedit-start");
3058 Minput_preedit_done = msymbol ("input-preedit-done");
3059 Minput_preedit_draw = msymbol ("input-preedit-draw");
3060 Minput_status_start = msymbol ("input-status-start");
3061 Minput_status_done = msymbol ("input-status-done");
3062 Minput_status_draw = msymbol ("input-status-draw");
3063 Minput_candidates_start = msymbol ("input-candidates-start");
3064 Minput_candidates_done = msymbol ("input-candidates-done");
3065 Minput_candidates_draw = msymbol ("input-candidates-draw");
3066 Minput_set_spot = msymbol ("input-set-spot");
3067 Minput_focus_move = msymbol ("input-focus-move");
3068 Minput_focus_in = msymbol ("input-focus-in");
3069 Minput_focus_out = msymbol ("input-focus-out");
3070 Minput_toggle = msymbol ("input-toggle");
3071 Minput_reset = msymbol ("input-reset");
3072 Minput_get_surrounding_text = msymbol ("input-get-surrounding-text");
3073 Minput_delete_surrounding_text = msymbol ("input-delete-surrounding-text");
3075 Mcandidate_list = msymbol_as_managing_key (" candidate-list");
3076 Mcandidate_index = msymbol (" candidate-index");
3078 Minit = msymbol ("init");
3079 Mfini = msymbol ("fini");
3081 M_key_alias = msymbol (" key-alias");
3082 M_description = msymbol ("description");
3083 M_command = msymbol ("command");
3084 M_variable = msymbol ("variable");
3086 load_im_info_keys = mplist ();
3087 mplist_add (load_im_info_keys, Mstate, Mnil);
3088 mplist_push (load_im_info_keys, Mmap, Mnil);
3093 for (i = 0, buf[2] = '@'; i < ' '; i++, buf[2]++)
3097 one_char_symbol[i] = msymbol (buf);
3100 alias = msymbol (key_names[i]);
3101 msymbol_put (one_char_symbol[i], M_key_alias, alias);
3104 alias = one_char_symbol[i];
3105 buf[2] += (i == 0) ? -32 : 32;
3106 msymbol_put (alias, M_key_alias, msymbol (buf));
3107 buf[2] -= (i == 0) ? -32 : 32;
3109 for (buf[2] = i; i < 127; i++, buf[2]++)
3110 one_char_symbol[i] = msymbol (buf + 2);
3111 one_char_symbol[i++] = msymbol ("Delete");
3117 for (buf[4] = '@'; i < 160; i++, buf[4]++)
3119 one_char_symbol[i] = msymbol (buf);
3120 if (key_names[i - 128])
3122 strcpy (buf2 + 2, key_names[i - 128]);
3123 msymbol_put (one_char_symbol[i], M_key_alias, msymbol (buf2));
3126 for (buf[4] = i - 128; i < 255; i++, buf[4]++)
3127 one_char_symbol[i] = msymbol (buf + 2);
3128 one_char_symbol[i] = msymbol ("M-Delete");
3130 command_list = variable_list = NULL;
3132 minput_default_driver.open_im = open_im;
3133 minput_default_driver.close_im = close_im;
3134 minput_default_driver.create_ic = create_ic;
3135 minput_default_driver.destroy_ic = destroy_ic;
3136 minput_default_driver.filter = filter;
3137 minput_default_driver.lookup = lookup;
3138 minput_default_driver.callback_list = mplist ();
3139 mplist_put (minput_default_driver.callback_list, Minput_reset,
3141 minput_driver = &minput_default_driver;
3150 M17N_OBJECT_UNREF (command_list);
3151 command_list = NULL;
3155 M17N_OBJECT_UNREF (variable_list);
3156 variable_list = NULL;
3159 if (minput_default_driver.callback_list)
3161 M17N_OBJECT_UNREF (minput_default_driver.callback_list);
3162 minput_default_driver.callback_list = NULL;
3164 if (minput_driver->callback_list)
3166 M17N_OBJECT_UNREF (minput_driver->callback_list);
3167 minput_driver->callback_list = NULL;
3172 while (! MPLIST_TAIL_P (im_info_list))
3175 mplist_pop (im_info_list);
3176 free_im_info ((MInputMethodInfo *) MPLIST_VAL (im_info_list));
3177 /* Pop (t . im_info) */
3178 mplist_pop (im_info_list);
3180 M17N_OBJECT_UNREF (im_info_list);
3181 im_info_list = NULL;
3184 M17N_OBJECT_UNREF (load_im_info_keys);
3188 minput__callback (MInputContext *ic, MSymbol command)
3190 if (ic->im->driver.callback_list)
3192 MInputCallbackFunc func
3193 = (MInputCallbackFunc) mplist_get (ic->im->driver.callback_list,
3197 (func) (ic, command);
3202 minput__char_to_key (int c)
3204 if (c < 0 || c >= 0x100)
3207 return one_char_symbol[c];
3211 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
3216 /*** @addtogroup m17nInputMethod */
3221 @name Variables: Predefined symbols for callback commands.
3223 These are the predefined symbols that are used as the @c COMMAND
3224 argument of callback functions of an input method driver (see
3225 #MInputDriver::callback_list ).
3227 Most of them don't require extra argument nor return any value;
3228 exceptions are these:
3230 Minput_get_surrounding_text: When a callback function assigned for
3231 this command is called, the first element of #MInputContext::plist
3232 has key #Msymbol and the value specifies which portion of the
3233 surrounding text should be retrieved. If the value is positive,
3234 it specifies the number of characters following the current cursor
3235 position. If the value is negative, the absolute value specifies
3236 the number of characters preceding the current cursor position.
3237 The callback function must set the key of this element to #Mtext
3238 and the value to the retrived M-text (whose length may be shorter
3239 than the requested number of characters if the available text is
3240 not that long, or it may be longer if an application thinks it's
3241 more efficient to return that length).
3243 Minput_delete_surrounding_text: When a callback function assigned
3244 for this command is called, the first element of
3245 #MInputContext::plist has key #Msymbol and the value specifies
3246 which portion of the surrounding text should be deleted in the
3247 same way as the case of Minput_get_surrounding_text. The callback
3248 function must delete the specified text. It should not alter
3249 #MInputContext::plist. */
3252 @name ÊÑ¿ô¡§ ¥³¡¼¥ë¥Ð¥Ã¥¯¥³¥Þ¥ó¥ÉÍÑÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë.
3254 ÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Î¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Ë¤ª¤¤¤Æ @c COMMAND
3255 °ú¿ô¤È¤·¤ÆÍѤ¤¤é¤ì¤ëÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë (#MInputDriver::callback_list »²¾È)¡£
3260 MSymbol Minput_preedit_start;
3261 MSymbol Minput_preedit_done;
3262 MSymbol Minput_preedit_draw;
3263 MSymbol Minput_status_start;
3264 MSymbol Minput_status_done;
3265 MSymbol Minput_status_draw;
3266 MSymbol Minput_candidates_start;
3267 MSymbol Minput_candidates_done;
3268 MSymbol Minput_candidates_draw;
3269 MSymbol Minput_set_spot;
3270 MSymbol Minput_toggle;
3271 MSymbol Minput_reset;
3272 MSymbol Minput_get_surrounding_text;
3273 MSymbol Minput_delete_surrounding_text;
3279 @name Variables: Predefined symbols for special input events.
3281 These are the predefined symbols that are used as the @c KEY
3282 argument of minput_filter (). */
3287 MSymbol Minput_focus_out;
3288 MSymbol Minput_focus_in;
3289 MSymbol Minput_focus_move;
3296 @brief The default driver for internal input methods.
3298 The variable #minput_default_driver is the default driver for
3299 internal input methods.
3301 The member MInputDriver::open_im () searches the m17n database for
3302 an input method that matches the tag \< #Minput_method, $LANGUAGE,
3303 $NAME\> and loads it.
3305 The member MInputDriver::callback_list () is @c NULL. Thus, it is
3306 programmers responsibility to set it to a plist of proper callback
3307 functions. Otherwise, no feedback information (e.g. preedit text)
3308 can be shown to users.
3310 The macro M17N_INIT () sets the variable #minput_driver to the
3311 pointer to this driver so that all internal input methods use it.
3313 Therefore, unless @c minput_driver is set differently, the driver
3314 dependent arguments $ARG of the functions whose name begins with
3315 "minput_" are all ignored. */
3318 @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥǥե©¥ë¥È¥É¥é¥¤¥Ð.
3320 ÊÑ¿ô #minput_default_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѤΥǥե©¥ë¥È¤Î¥É¥é¥¤¥Ð¤òɽ¤¹¡£
3322 ¥á¥ó¥Ð MInputDriver::open_im () ¤Ï m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹Ã椫¤é¥¿¥°
3323 \< #Minput_method, $LANGUAGE, $NAME\>
3324 ¤Ë¹çÃפ¹¤ëÆþÎϥ᥽¥Ã¥É¤òõ¤·¡¢¤½¤ì¤ò¥í¡¼¥É¤¹¤ë¡£
3326 ¥á¥ó¥Ð MInputDriver::callback_list () ¤Ï @c NULL ¤Ç¤¢¤ê¡¢
3327 ¤·¤¿¤¬¤Ã¤Æ¡¢¥×¥í¥°¥é¥Þ¦¤ÇÀÕǤ¤ò»ý¤Ã¤Æ ŬÀڤʥ³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Î plist
3328 ¤ËÀßÄꤷ¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¤µ¤â¤Ê¤¤¤È¡¢preedit
3329 ¥Æ¥¥¹¥È¤Ê¤É¤Î¥Õ¥£¡¼¥É¥Ð¥Ã¥¯¾ðÊ󤬥桼¥¶¤Ëɽ¼¨¤µ¤ì¤Ê¤¤¡£
3331 ¥Þ¥¯¥í M17N_INIT () ¤ÏÊÑ¿ô #minput_driver
3332 ¤ò¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤ËÀßÄꤷ¡¢Á´¤Æ¤ÎÆâÉôÆþÎϥ᥽¥Ã¥É¤¬¤³¤Î¥É¥é¥¤¥Ð¤ò»È¤¦¤è¤¦¤Ë¤¹¤ë¡£
3334 ¤·¤¿¤¬¤Ã¤Æ¡¢@c minput_driver ¤¬¥Ç¥Õ¥©¥ë¥ÈÃͤΤޤޤǤ¢¤ì¤Ð¡¢minput_
3335 ¤Ç»Ï¤Þ¤ë´Ø¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô $ARG ¤Ï¤¹¤Ù¤Æ̵»ë¤µ¤ì¤ë¡£ */
3337 MInputDriver minput_default_driver;
3341 @brief The driver for internal input methods.
3343 The variable #minput_driver is a pointer to the input method
3344 driver that is used by internal input methods. The macro
3345 M17N_INIT () initializes it to a pointer to #minput_default_driver
3346 if <m17n<EM></EM>.h> is included. */
3348 @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥɥ饤¥Ð.
3350 ÊÑ¿ô #minput_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤Æ»ÈÍѤµ¤ì¤Æ¤¤¤ëÆþÎÏ¥á
3351 ¥½¥Ã¥É¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£¥Þ¥¯¥í M17N_INIT () ¤Ï¤³¤Î¥Ý¥¤¥ó
3352 ¥¿¤ò#minput_default_driver (<m17n<EM></EM>.h> ¤¬ include ¤µ¤ì¤Æ¤¤¤ë
3353 »þ) ¤Ë½é´ü²½¤¹¤ë¡£ */
3355 MInputDriver *minput_driver;
3357 MSymbol Minput_driver;
3362 @brief Open an input method.
3364 The minput_open_im () function opens an input method whose
3365 language and name match $LANGUAGE and $NAME, and returns a pointer
3366 to the input method object newly allocated.
3368 This function at first decides a driver for the input method as
3371 If $LANGUAGE is not #Mnil, the driver pointed by the variable
3372 #minput_driver is used.
3374 If $LANGUAGE is #Mnil and $NAME has the property #Minput_driver, the
3375 driver pointed to by the property value is used to open the input
3376 method. If $NAME has no such a property, @c NULL is returned.
3378 Then, the member MInputDriver::open_im () of the driver is
3381 $ARG is set in the member @c arg of the structure MInputMethod so
3382 that the driver can refer to it. */
3385 @brief ÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë.
3387 ´Ø¿ô minput_open_im () ¤Ï¸À¸ì $LANGUAGE ¤È̾Á° $NAME
3388 ¤Ë¹çÃפ¹¤ëÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤·¡¢¿·¤¿¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿ÆþÎϥ᥽¥Ã¥É¥ª¥Ö¥¸¥§¥¯¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
3390 ¤³¤Î´Ø¿ô¤Ï¡¢¤Þ¤ºÆþÎϥ᥽¥Ã¥ÉÍѤΥɥ饤¥Ð¤ò°Ê²¼¤Î¤è¤¦¤Ë¤·¤Æ·èÄꤹ¤ë¡£
3392 $LANGUAGE ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢ÊÑ¿ô #minput_driver
3393 ¤Ç»Ø¤µ¤ì¤Æ¤¤¤ë¥É¥é¥¤¥Ð¤òÍѤ¤¤ë¡£
3395 $LANGUAGE ¤¬ #Mnil ¤Ç¤¢¤ê¡¢$NAME ¤¬ #Minput_driver
3396 ¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä¾ì¹ç¤Ë¤Ï¡¢¤½¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤǻؤµ¤ì¤Æ¤¤¤ëÆþÎϥɥ饤¥Ð¤òÍѤ¤¤ÆÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë¡£
3397 $NAME ¤Ë¤½¤Î¤è¤¦¤Ê¥×¥í¥Ñ¥Æ¥£¤¬Ìµ¤«¤Ã¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
3399 ¼¡¤¤¤Ç¡¢¥É¥é¥¤¥Ð¤Î¥á¥ó¥Ð MInputDriver::open_im () ¤¬¸Æ¤Ð¤ì¤ë¡£
3401 $ARG ¤Ï¹½Â¤ÂÎ MInputMethod ¤Î¥á¥ó¥Ð @c arg ¤ËÀßÄꤵ¤ì¡¢¥É¥é¥¤¥Ð¤«¤é»²¾È¤Ç¤¤ë¡£
3403 @latexonly \IPAlabel{minput_open} @endlatexonly
3408 minput_open_im (MSymbol language, MSymbol name, void *arg)
3411 MInputDriver *driver;
3413 MDEBUG_PRINT2 (" [IM] opening (%s %s) ... ",
3414 msymbol_name (language), msymbol_name (name));
3416 driver = minput_driver;
3419 driver = (MInputDriver *) msymbol_get (name, Minput_driver);
3421 MERROR (MERROR_IM, NULL);
3424 MSTRUCT_CALLOC (im, MERROR_IM);
3425 im->language = language;
3428 im->driver = *driver;
3429 if ((*im->driver.open_im) (im) < 0)
3431 MDEBUG_PRINT (" failed\n");
3435 MDEBUG_PRINT (" ok\n");
3442 @brief Close an input method.
3444 The minput_close_im () function closes the input method $IM, which
3445 must have been created by minput_open_im (). */
3448 @brief ÆþÎϥ᥽¥Ã¥É¤ò¥¯¥í¡¼¥º¤¹¤ë.
3450 ´Ø¿ô minput_close_im () ¤Ï¡¢ÆþÎϥ᥽¥Ã¥É $IM ¤ò¥¯¥í¡¼¥º¤¹¤ë¡£
3451 ¤³¤ÎÆþÎϥ᥽¥Ã¥É $IM ¤Ï minput_open_im () ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£ */
3454 minput_close_im (MInputMethod *im)
3456 MDEBUG_PRINT2 (" [IM] closing (%s %s) ... ",
3457 msymbol_name (im->name), msymbol_name (im->language));
3458 (*im->driver.close_im) (im);
3460 MDEBUG_PRINT (" done\n");
3466 @brief Create an input context.
3468 The minput_create_ic () function creates an input context object
3469 associated with input method $IM, and calls callback functions
3470 corresponding to #Minput_preedit_start, #Minput_status_start, and
3471 #Minput_status_draw in this order.
3474 If an input context is successfully created, minput_create_ic ()
3475 returns a pointer to it. Otherwise it returns @c NULL. */
3478 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÀ¸À®¤¹¤ë.
3480 ´Ø¿ô minput_create_ic () ¤ÏÆþÎϥ᥽¥Ã¥É $IM
3481 ¤ËÂбþ¤¹¤ëÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤·¡¢
3482 #Minput_preedit_start, #Minput_status_start, #Minput_status_draw
3483 ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¤³¤Î½ç¤Ë¸Æ¤Ö¡£
3486 ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤¬À¸À®¤µ¤ì¤¿¾ì¹ç¡¢minput_create_ic ()
3487 ¤Ï¤½¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¼ºÇÔ¤·¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
3491 minput_create_ic (MInputMethod *im, void *arg)
3495 MDEBUG_PRINT2 (" [IM] creating context (%s %s) ... ",
3496 msymbol_name (im->name), msymbol_name (im->language));
3497 MSTRUCT_CALLOC (ic, MERROR_IM);
3500 ic->preedit = mtext ();
3501 ic->candidate_list = NULL;
3502 ic->produced = mtext ();
3503 ic->spot.x = ic->spot.y = 0;
3505 ic->plist = mplist ();
3506 if ((*im->driver.create_ic) (ic) < 0)
3508 MDEBUG_PRINT (" failed\n");
3509 M17N_OBJECT_UNREF (ic->preedit);
3510 M17N_OBJECT_UNREF (ic->produced);
3511 M17N_OBJECT_UNREF (ic->plist);
3516 if (im->driver.callback_list)
3518 minput__callback (ic, Minput_preedit_start);
3519 minput__callback (ic, Minput_status_start);
3520 minput__callback (ic, Minput_status_draw);
3523 MDEBUG_PRINT (" ok\n");
3530 @brief Destroy an input context.
3532 The minput_destroy_ic () function destroys the input context $IC,
3533 which must have been created by minput_create_ic (). It calls
3534 callback functions corresponding to #Minput_preedit_done,
3535 #Minput_status_done, and #Minput_candidates_done in this order. */
3538 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÇ˲õ¤¹¤ë.
3540 ´Ø¿ô minput_destroy_ic () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤òÇ˲õ¤¹¤ë¡£
3541 ¤³¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ï minput_create_ic ()
3542 ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£¤³¤Î´Ø¿ô¤Ï
3543 #Minput_preedit_done, #Minput_status_done, #Minput_candidates_done
3544 ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¤³¤Î½ç¤Ë¸Æ¤Ö¡£
3548 minput_destroy_ic (MInputContext *ic)
3550 MDEBUG_PRINT2 (" [IM] destroying context (%s %s) ... ",
3551 msymbol_name (ic->im->name), msymbol_name (ic->im->language));
3552 if (ic->im->driver.callback_list)
3554 minput__callback (ic, Minput_preedit_done);
3555 minput__callback (ic, Minput_status_done);
3556 minput__callback (ic, Minput_candidates_done);
3558 (*ic->im->driver.destroy_ic) (ic);
3559 M17N_OBJECT_UNREF (ic->preedit);
3560 M17N_OBJECT_UNREF (ic->produced);
3561 M17N_OBJECT_UNREF (ic->plist);
3562 MDEBUG_PRINT (" done\n");
3569 @brief Filter an input key.
3571 The minput_filter () function filters input key $KEY according to
3572 input context $IC, and calls callback functions corresponding to
3573 #Minput_preedit_draw, #Minput_status_draw, and
3574 #Minput_candidates_draw if the preedit text, the status, and the
3575 current candidate are changed respectively.
3577 To make the input method commit the current preedit text (if any)
3578 and shift to the initial state, call this function with #Mnil as
3581 To inform the input method about the focus-out event, call this
3582 function with #Minput_focus_out as $KEY.
3584 To inform the input method about the focus-in event, call this
3585 function with #Minput_focus_in as $KEY.
3587 To inform the input method about the focus-move event (i.e. input
3588 spot change within the same input context), call this function
3589 with #Minput_focus_move as $KEY.
3592 If $KEY is filtered out, this function returns 1. In that case,
3593 the caller should discard the key. Otherwise, it returns 0, and
3594 the caller should handle the key, for instance, by calling the
3595 function minput_lookup () with the same key. */
3598 @brief ÆþÎÏ¥¡¼¤ò¥Õ¥£¥ë¥¿¤¹¤ë.
3600 ´Ø¿ô minput_filter () ¤ÏÆþÎÏ¥¡¼ $KEY ¤òÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC
3601 ¤Ë±þ¤¸¤Æ¥Õ¥£¥ë¥¿¤·¡¢preedit ¥Æ¥¥¹¥È¡¢¥¹¥Æ¡¼¥¿¥¹¡¢¸½»þÅÀ¤Ç¤Î¸õÊ䤬ÊѲ½¤·¤¿»þÅÀ¤Ç¡¢¤½¤ì¤¾¤ì
3602 #Minput_preedit_draw, #Minput_status_draw,
3603 #Minput_candidates_draw ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¸Æ¤Ö¡£
3606 $KEY ¤¬¥Õ¥£¥ë¥¿¤µ¤ì¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 1 ¤òÊÖ¤¹¡£
3607 ¤³¤Î¾ì¹ç¸Æ¤Ó½Ð¤·Â¦¤Ï¤³¤Î¥¡¼¤ò¼Î¤Æ¤ë¤Ù¤¤Ç¤¢¤ë¡£
3608 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0 ¤òÊÖ¤·¡¢¸Æ¤Ó½Ð¤·Â¦¤Ï¡¢¤¿¤È¤¨¤ÐƱ¤¸¥¡¼¤Ç´Ø¿ô minput_lookup ()
3609 ¤ò¸Æ¤Ö¤Ê¤É¤·¤Æ¡¢¤³¤Î¥¡¼¤ò½èÍý¤¹¤ë¡£
3611 @latexonly \IPAlabel{minput_filter} @endlatexonly
3615 minput_filter (MInputContext *ic, MSymbol key, void *arg)
3622 ret = (*ic->im->driver.filter) (ic, key, arg);
3624 if (ic->im->driver.callback_list)
3626 if (ic->preedit_changed)
3627 minput__callback (ic, Minput_preedit_draw);
3628 if (ic->status_changed)
3629 minput__callback (ic, Minput_status_draw);
3630 if (ic->candidates_changed)
3631 minput__callback (ic, Minput_candidates_draw);
3640 @brief Look up a text produced in the input context.
3642 The minput_lookup () function looks up a text in the input context
3643 $IC. $KEY must be identical to the one that was used in the previous call of
3646 If a text was produced by the input method, it is concatenated
3649 This function calls #MInputDriver::lookup .
3652 If $KEY was correctly handled by the input method, this function
3653 returns 0. Otherwise, it returns -1, even though some text
3654 might be produced in $MT. */
3657 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥ÈÃæ¤Î¥Æ¥¥¹¥È¤òõ¤¹.
3659 ´Ø¿ô minput_lookup () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC Ãæ¤Î¥Æ¥¥¹¥È¤òõ¤¹¡£
3660 $KEY ¤Ï´Ø¿ô minput_filter () ¤Ø¤ÎľÁ°¤Î¸Æ¤Ó½Ð¤·¤ËÍѤ¤¤é¤ì¤¿¤â¤Î¤ÈƱ¤¸¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
3662 ¥Æ¥¥¹¥È¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆÀ¸À®¤µ¤ì¤Æ¤¤¤ì¤Ð¡¢¥Æ¥¥¹¥È¤Ï M-text
3665 ¤³¤Î´Ø¿ô¤Ï¡¢#MInputDriver::lookup ¤ò¸Æ¤Ö¡£
3668 $KEY ¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆŬÀڤ˽èÍý¤Ç¤¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 0 ¤òÊÖ¤¹¡£
3669 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£
3670 ¤³¤Î¾ì¹ç¤Ç¤â $MT ¤Ë²¿¤é¤«¤Î¥Æ¥¥¹¥È¤¬À¸À®¤µ¤ì¤Æ¤¤¤ë¤³¤È¤¬¤¢¤ë¡£
3672 @latexonly \IPAlabel{minput_lookup} @endlatexonly */
3675 minput_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
3677 return (ic ? (*ic->im->driver.lookup) (ic, key, arg, mt) : -1);
3682 @brief Set the spot of the input context.
3684 The minput_set_spot () function sets the spot of input context $IC
3685 to coordinate ($X, $Y ) with the height specified by $ASCENT and $DESCENT .
3686 The semantics of these values depends on the input method driver.
3688 For instance, a driver designed to work in a CUI environment may
3689 use $X and $Y as the column- and row numbers, and may ignore $ASCENT and
3690 $DESCENT . A driver designed to work in a window system may
3691 interpret $X and $Y as the pixel offsets relative to the origin of the
3692 client window, and may interpret $ASCENT and $DESCENT as the ascent- and
3693 descent pixels of the line at ($X . $Y ).
3695 $FONTSIZE specifies the fontsize of preedit text in 1/10 point.
3697 $MT and $POS are the M-text and the character position at the spot.
3698 $MT may be @c NULL, in which case, the input method cannot get
3699 information about the text around the spot. */
3702 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Î¥¹¥Ý¥Ã¥È¤òÀßÄꤹ¤ë.
3704 ´Ø¿ô minput_set_spot () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤Î¥¹¥Ý¥Ã¥È¤ò¡¢ºÂɸ ($X, $Y )
3705 ¤Î°ÌÃÖ¤Ë ¡¢¹â¤µ $ASCENT¡¢ $DESCENT
3706 ¤ÇÀßÄꤹ¤ë¡£ ¤³¤ì¤é¤ÎÃͤΰÕÌ£¤ÏÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë¡£
3708 ¤¿¤È¤¨¤Ð CUI ´Ä¶¤ÇÆ°ºî¤¹¤ë¥É¥é¥¤¥Ð¤Ï $X ¤È $Y
3709 ¤ò¤½¤ì¤¾¤ìÎó¤È¹Ô¤ÎÈÖ¹æ¤È¤·¤ÆÍѤ¤¡¢$ASCENT ¤È $DESCENT
3710 ¤ò̵»ë¤¹¤ë¤«¤â¤·¤ì¤Ê¤¤¡£ ¤Þ¤¿¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥àÍѤΥɥ饤¥Ð¤Ï
3711 $X ¤È $Y ¤ò¥¯¥é¥¤¥¢¥ó¥È¥¦¥£¥ó¥É¥¦¤Î¸¶ÅÀ¤«¤é¤Î¥ª¥Õ¥»¥Ã¥È¤ò¥Ô¥¯¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¤¡¢
3712 $ASCENT ¤È $DESCENT ¤ò ($X . $Y )
3713 ¤ÎÎó¤Î¥¢¥»¥ó¥È¤È¥Ç¥£¥»¥ó¥È¤ò¥Ô¥¯¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¦¤«¤â¤·¤ì¤Ê¤¤¡£
3715 $FONTSIZE ¤Ë¤Ï preedit ¥Æ¥¥¹¥È¤Î¥Õ¥©¥ó¥È¥µ¥¤¥º¤ò 1/10 ¥Ý¥¤¥ó¥Èñ°Ì¤Ç»ØÄꤹ¤ë¡£
3717 $MT ¤È $POS ¤Ï¤½¤Î¥¹¥Ý¥Ã¥È¤Î M-text ¤Èʸ»ú°ÌÃ֤Ǥ¢¤ë¡£$MT ¤Ï @c
3718 NULL ¤Ç¤â¤è¤¯¡¢¤½¤Î¾ì¹ç¤Ë¤ÏÆþÎϥ᥽¥Ã¥É¤Ï¥¹¥Ý¥Ã¥È¼þÊդΥƥ¥¹¥È¤Ë´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë¤³¤È¤¬¤Ç¤¤Ê¤¤¡£
3722 minput_set_spot (MInputContext *ic, int x, int y,
3723 int ascent, int descent, int fontsize,
3728 ic->spot.ascent = ascent;
3729 ic->spot.descent = descent;
3730 ic->spot.fontsize = fontsize;
3733 if (ic->im->driver.callback_list)
3734 minput__callback (ic, Minput_set_spot);
3739 @brief Toggle input method.
3741 The minput_toggle () function toggles the input method associated
3742 with input context $IC. */
3744 @brief ÆþÎϥ᥽¥Ã¥É¤òÀÚÂؤ¨¤ë.
3746 ´Ø¿ô minput_toggle () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC
3747 ¤ËÂбþÉÕ¤±¤é¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ò¥È¥°¥ë¤¹¤ë¡£
3751 minput_toggle (MInputContext *ic)
3753 if (ic->im->driver.callback_list)
3754 minput__callback (ic, Minput_toggle);
3755 ic->active = ! ic->active;
3761 @brief Reset an input context.
3763 The minput_reset_ic () function resets input context $IC by
3764 calling a callback function corresponding to #Minput_reset. It
3765 resets the status of $IC to its initial one. As the
3766 current preedit text is deleted without commitment, if necessary,
3767 call minput_filter () with the arg @r key #Mnil to force the input
3768 method to commit the preedit in advance. */
3771 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤ò¥ê¥»¥Ã¥È¤¹¤ë.
3773 ´Ø¿ô minput_reset_ic () ¤Ï #Minput_reset
3774 ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¸Æ¤Ö¤³¤È¤Ë¤è¤Ã¤ÆÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC
3775 ¤ò¥ê¥»¥Ã¥È¤¹¤ë¡£¥ê¥»¥Ã¥È¤È¤Ï¡¢¼ÂºÝ¤Ë¤ÏÆþÎϥ᥽¥Ã¥É¤ò½é´ü¾õÂ֤˰ܤ¹¤³¤È¤Ç¤¢¤ê¡¢¤·¤¿¤¬¤Ã¤Æ¡¢¤â¤·¸½ºßÆþÎÏÃæ¤Î¥Æ¥¥¹¥È¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤Ï¥³¥ß¥Ã¥È¤µ¤ì¤ë¡£
3776 ɬÍפʤé¤Ð¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ï minput_lookup ()
3777 ¤òÆɤó¤Ç¤½¤Î¥³¥ß¥Ã¥È¤µ¤ì¤¿¥Æ¥¥¹¥È¤ò¼è¤ê½Ð¤¹¤³¤È¤¬¤Ç¤¡¢¤½¤ÎºÝ¡¢
3778 minput_lookup () ¤Î°ú¿ô @c KEY ¤È @c ARG
3781 minput_reset_ic (MInputContext *ic)
3783 if (ic->im->driver.callback_list)
3784 minput__callback (ic, Minput_reset);
3790 @brief Get title and icon filename of an input method.
3792 The minput_get_title_icon () function returns a plist containing a
3793 title and icon filename (if any) of the input method specifies by
3794 $LANGUAGE and $NAME.
3796 The first element of the plist has key Mtext and the value is an
3797 M-text of the title for identifying the input method. The second
3798 element (if any) has key M-text and the value is an M-text of the
3799 icon image (absolute) filename for the same purpose.
3802 If there exists the specified input method and it defines an
3803 title, a plist is retured. Otherwise, NULL is returned. A caller
3804 must free the plist by m17n_object_unref ().
3808 minput_get_title_icon (MSymbol language, MSymbol name)
3810 MPlist *plist = load_partial_im_info (language, name, Mnil, Mtitle);
3817 if (MPLIST_TAIL_P (plist))
3819 pl = MPLIST_PLIST (plist);
3820 pl = MPLIST_NEXT (pl);
3821 if (! MPLIST_MTEXT_P (pl))
3823 M17N_OBJECT_REF (pl);
3824 M17N_OBJECT_UNREF (plist);
3826 pl = MPLIST_NEXT (pl);
3827 if (MPLIST_MTEXT_P (pl))
3829 if (mtext_nchars (MPLIST_MTEXT (pl)) > 0)
3831 mt = MPLIST_MTEXT (pl);
3832 file = mdatabase__find_file ((char *) MTEXT_DATA (mt));
3835 else if (language != Mnil && name != Mnil)
3838 char *buf = alloca (MSYMBOL_NAMELEN (language) + MSYMBOL_NAMELEN (name)
3841 sprintf (buf, "icons/%s-%s.png", (char *) MSYMBOL_NAME (language),
3842 (char *) MSYMBOL_NAME (name));
3843 file = mdatabase__find_file (buf);
3844 if (! file && language == Mt)
3846 sprintf (buf, "icons/%s.png", (char *) MSYMBOL_NAME (name));
3847 file = mdatabase__find_file (buf);
3853 mt = mtext__from_data (file, strlen (file), MTEXT_FORMAT_UTF_8, 1);
3855 mplist_set (pl, Mtext, mt);
3856 M17N_OBJECT_UNREF (mt);
3859 mplist_set (pl, Mnil, NULL);
3863 M17N_OBJECT_UNREF (plist);
3870 @brief Get description text of an input method.
3872 The minput_get_description () function returns an M-text that
3873 describes the input method specified by $LANGUAGE and $NAME.
3876 If the specified input method has a description text, a pointer to
3877 #MText is returned. The caller has to free it by m17n_object_unref ().
3878 If the input method does not have a description text, @c NULL is
3881 @brief ÆþÎϥ᥽¥Ã¥É¤ÎÀâÌÀ¥Æ¥¥¹¥È¤òÆÀ¤ë.
3883 ´Ø¿ô minput_get_description () ¤Ï¡¢$LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ»ØÄê
3884 ¤µ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤òÀâÌÀ¤¹¤ë M-text ¤òÊÖ¤¹¡£
3886 @return »ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤¬ÀâÌÀ¤¹¤ë¥Æ¥¥¹¥È¤ò»ý¤Ã¤Æ¤¤¤ì¤Ð¡¢
3887 #MText ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¸Æ¤Ó½Ð¤·Â¦¤Ï¡¢¤½¤ì¤ò m17n_object_unref
3888 () ¤òÍѤ¤¤Æ²òÊü¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ÆþÎϥ᥽¥Ã¥É¤ËÀâÌÀ¥Æ¥¥¹¥È¤¬Ìµ¤±
3889 ¤ì¤Ð@c NULL ¤òÊÖ¤¹¡£ */
3892 minput_get_description (MSymbol language, MSymbol name)
3894 MPlist *plist = load_partial_im_info (language, name, Mnil, M_description);
3900 if (MPLIST_TAIL_P (plist))
3902 M17N_OBJECT_UNREF (plist);
3905 pl = MPLIST_PLIST (plist);
3906 pl = MPLIST_NEXT (pl);
3907 if (MPLIST_MTEXT_P (pl))
3909 mt = MPLIST_MTEXT (pl);
3910 M17N_OBJECT_REF (mt);
3912 M17N_OBJECT_UNREF (plist);
3917 @brief Get information about input method commands.
3919 The minput_get_commands () function returns information about
3920 input method commands of the input method specified by $LANGUAGE
3921 and $NAME. An input method command is a pseudo key event to which
3922 one or more actual input key sequences are assigned.
3924 There are two kinds of commands, global and local. Global
3925 commands are used by multiple input methods for the same purpose,
3926 and have global key assignments. Local commands are used only by
3927 a specific input method, and have only local key assignments.
3929 Each input method may locally change key assignments for global
3930 commands. The global key assignment for a global command is
3931 effective only when the current input method does not have local
3932 key assignments for that command.
3934 If $NAME is #Mnil, information about global commands is returned.
3935 In this case $LANGUAGE is ignored.
3937 If $NAME is not #Mnil, information about those commands that have
3938 local key assignments in the input method specified by $LANGUAGE
3939 and $NAME is returned.
3942 If no input method commands are found, this function returns @c NULL.
3944 Otherwise, a pointer to a plist is returned. The key of each
3945 element in the plist is a symbol representing a command, and the
3946 value is a plist of the form COMMAND-INFO described below.
3948 The first element of COMMAND-INFO has the key #Mtext, and the
3949 value is an M-text describing the command.
3951 If there are no more elements, that means no key sequences are
3952 assigned to the command. Otherwise, each of the remaining
3953 elements has the key #Mplist, and the value is a plist whose keys are
3954 #Msymbol and values are symbols representing input keys, which are
3955 currently assigned to the command.
3957 As the returned plist is kept in the library, the caller must not
3958 modify nor free it. */
3960 @brief ÆþÎϥ᥽¥Ã¥É¤Î¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë.
3962 ´Ø¿ô minput_get_commands () ¤Ï¡¢ $LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ»ØÄꤵ
3963 ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ÎÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£ÆþÎϥ᥽¥Ã
3964 ¥É¥³¥Þ¥ó¥É¤È¤Ï¡¢µ¿»÷¥¡¼¥¤¥Ù¥ó¥È¤Ç¤¢¤ê¡¢¤½¤ì¤¾¤ì¤Ë£±¤Ä°Ê¾å¤Î¼ÂºÝ¤Î
3965 ÆþÎÏ¥¡¼¥·¡¼¥¯¥¨¥ó¥¹¤¬³ä¤êÅö¤Æ¤é¤ì¤Æ¤¤¤ë¤â¤Î¤ò»Ø¤¹¡£
3967 ¥³¥Þ¥ó¥É¤Ë¤Ï¥°¥í¡¼¥Ð¥ë¤È¥í¡¼¥«¥ë¤Î£²¼ïÎब¤¢¤ë¡£¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É
3968 ¤ÏÊ£¿ô¤ÎÆþÎϥ᥽¥Ã¥É¤Ë¤ª¤¤¤Æ¡¢Æ±¤¸ÌÜŪ¤Ç¡¢¥°¥í¡¼¥Ð¥ë¤Ê¥¡¼³ä¤êÅö¤Æ
3969 ¤ÇÍѤ¤¤é¤ì¤ë¡£¥í¡¼¥«¥ë¥³¥Þ¥ó¥É¤ÏÆÃÄê¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Î¤ß¡¢¥í¡¼¥«¥ë
3970 ¤Ê¥¡¼³äÅö¤Ç»ÈÍѤµ¤ì¤ë¡£
3972 ¸Ä¡¹¤ÎÆþÎϥ᥽¥Ã¥É¤Ï¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É¤Î¥¡¼³äÅö¤òÊѹ¹¤¹¤ë¤³¤È¤â¤Ç
3973 ¤¤ë¡£¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥ÉÍѤΥ°¥í¡¼¥Ð¥ë¥¡¼³ä¤êÅö¤Æ¤Ï¡¢»ÈÍѤ¹¤ëÆþÎÏ
3974 ¥á¥½¥Ã¥É¤Ë¤ª¤¤¤Æ¤½¤Î¥³¥Þ¥ó¥ÉÍÑ¤Î¥í¡¼¥«¥ë¤Ê¥¡¼³äÅö¤¬Â¸ºß¤·¤Ê¤¤¾ì¹ç
3977 $NAME ¤¬ #Mnil ¤Ç¤¢¤ì¤Ð¡¢¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£¤³¤Î
3978 ¾ì¹ç¡¢$LANGUAGE ¤Ï̵»ë¤µ¤ì¤ë¡£
3980 $NAME ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢$LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤ëÆþ
3981 Îϥ᥽¥Ã¥É¤ËÃÖ¤±¤ë¥í¡¼¥«¥ë¤Ê¥¡¼³ä¤êÅö¤Æ¤ò»ý¤Ä¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó
3985 ÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï @c NULL ¤òÊÖ¤¹¡£
3987 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¥ê¥¹¥È¤Î³ÆÍ×ÁǤÎ
3988 ¥¡¼¤Ï¸Ä¡¹¤Î¥³¥Þ¥ó¥É¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢Ãͤϲ¼µ¤Î COMMAND-INFO
3989 ¤Î·Á¼°¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ç¤¢¤ë¡£
3991 COMMAND-INFO ¤ÎÂè°ìÍ×ÁǤΥ¡¼¤Ï #Mtext ¤Þ¤¿¤Ï #Msymbol ¤Ç¤¢¤ë¡£¥¡¼
3992 ¤¬ #Mtext ¤Ê¤é¡¢ÃͤϤ½¤Î¥³¥Þ¥ó¥É¤òÀâÌÀ¤¹¤ë M-text ¤Ç¤¢¤ë¡£¥¡¼¤¬
3993 #Msymbol ¤Ê¤éÃÍ¤Ï #Mnil ¤Ç¤¢¤ê¡¢¤³¤Î¥³¥Þ¥ó¥É¤ÏÀâÌÀ¥Æ¥¥¹¥È¤ò»ý¤¿¤Ê
3996 ¤½¤ì°Ê³°¤ÎÍ×ÁǤ¬Ìµ¤±¤ì¤Ð¡¢¤³¤Î¥³¥Þ¥ó¥É¤ËÂФ·¤Æ¥¡¼¥·¡¼¥¯¥¨¥ó¥¹¤¬³ä
3997 ¤êÅö¤Æ¤é¤ì¤Æ¤¤¤Ê¤¤¤³¤È¤ò°ÕÌ£¤¹¤ë¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢»Ä¤ê¤Î³ÆÍ×ÁǤϥ
3998 ¡¼¤È¤·¤Æ#Mplist ¤ò¡¢ÃͤȤ·¤Æ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ò»ý¤Ä¡£¤³¤Î¥×¥í¥Ñ¥Æ¥£
3999 ¥ê¥¹¥È¤Î¥¡¼¤Ï #Msymbol ¤Ç¤¢¤ê¡¢Ãͤϸ½ºß¤½¤Î¥³¥Þ¥ó¥É¤Ë³ä¤êÅö¤Æ¤é¤ì
4000 ¤Æ¤¤¤ëÆþÎÏ¥¡¼¤òɽ¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
4002 ÊÖ¤µ¤ì¤ë¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ï¥é¥¤¥Ö¥é¥ê¤Ë¤è¤Ã¤Æ´ÉÍý¤µ¤ì¤Æ¤ª¤ê¡¢¸Æ¤Ó½Ð
4003 ¤·Â¦¤ÇÊѹ¹¤·¤¿¤ê²òÊü¤·¤¿¤ê¤·¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£*/
4006 minput_get_commands (MSymbol language, MSymbol name)
4008 MPlist *plist = get_nested_list (language, name, Mnil, M_command);
4010 return (MPLIST_TAIL_P (plist) ? NULL : plist);
4014 @brief Assign a key sequence to an input method command.
4016 The minput_assign_command_keys () function assigns input key
4017 sequence $KEYSEQ to input method command $COMMAND for the input
4018 method specified by $LANGUAGE and $NAME. If $NAME is #Mnil, the
4019 key sequence is assigned globally no matter what $LANGUAGE is.
4020 Otherwise the key sequence is assigned locally.
4022 Each element of $KEYSEQ must have the key $Msymbol and the value
4023 must be a symbol representing an input key.
4025 $KEYSEQ may be @c NULL, in which case, all assignments are deleted
4026 globally or locally.
4028 This assignment gets effective in a newly opened input method.
4031 If the operation was successful, 0 is returned. Otherwise -1 is
4032 returned, and #merror_code is set to #MERROR_IM. */
4034 @brief ÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤Ë¥¡¼¥·¡¼¥¯¥¨¥ó¥¹¤ò³ä¤êÅö¤Æ¤ë.
4036 ´Ø¿ô minput_assign_command_keys () ¤Ï¡¢ $LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ
4037 »ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥ÉÍѤÎÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É $COMMAND ¤ËÂФ·¤Æ¡¢
4038 ÆþÎÏ¥¡¼¥·¡¼¥¯¥¨¥ó¥¹ $KEYSEQ ¤ò³ä¤êÅö¤Æ¤ë¡£ $NAME ¤¬ #Mnil ¤Ê¤é¤Ð¡¢
4039 $LANGUAGE ¤Ë´Ø·¸¤Ê¤¯¡¢ÆþÎÏ¥¡¼¥·¡¼¥¯¥¨¥ó¥¹¤Ï¥°¥í¡¼¥Ð¥ë¤Ë³ä¤êÅö¤Æ¤é
4040 ¤ì¤ë¡£¤½¤¦¤Ç¤Ê¤ì¤Ð¡¢³ä¤êÅö¤Æ¤Ï¥í¡¼¥«¥ë¤Ç¤¢¤ë¡£
4042 $KEYSEQ ¤Î³ÆÍ×ÁǤϥ¡¼¤È¤·¤Æ $Msymbol ¤ò¡¢ÃͤȤ·¤ÆÆþÎÏ¥¡¼¤òɽ¤¹¥·
4043 ¥ó¥Ü¥ë¤ò»ý¤¿¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
4045 $KEYSEQ ¤Ï @c NULL ¤Ç¤â¤è¤¤¡£¤³¤Î¾ì¹ç¡¢¥°¥í¡¼¥Ð¥ë¤â¤·¤¯¤Ï¥í¡¼¥«¥ë¤Ê
4046 ¤¹¤Ù¤Æ¤Î³ä¤êÅö¤Æ¤¬¾Ãµî¤µ¤ì¤ë¡£
4048 ¤³¤Î³ä¤êÅö¤Æ¤Ï¡¢³ä¤êÅö¤Æ°Ê¹ß¿·¤·¤¯¥ª¡¼¥×¥ó¤µ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤«¤éÍ
4051 @return ½èÍý¤¬À®¸ù¤¹¤ì¤Ð 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤·¡¢
4052 #merror_code ¤ò #MERROR_IM ¤ËÀßÄꤹ¤ë¡£ */
4055 minput_assign_command_keys (MSymbol language, MSymbol name,
4056 MSymbol command, MPlist *keyseq)
4058 MPlist *plist, *pl, *p;
4060 if (check_command_keyseq (keyseq) < 0
4061 || ! (plist = get_nested_list (language, name, Mnil, M_command)))
4062 MERROR (MERROR_IM, -1);
4063 pl = mplist_get (plist, command);
4066 pl = MPLIST_NEXT (pl);
4068 while ((p = mplist_pop (pl)))
4069 M17N_OBJECT_UNREF (p);
4072 keyseq = mplist_copy (keyseq);
4073 mplist_push (pl, Mplist, keyseq);
4074 M17N_OBJECT_UNREF (keyseq);
4080 MERROR (MERROR_IM, -1);
4083 /* Get global commands. */
4084 pl = get_nested_list (Mnil, Mnil, Mnil, M_command);
4085 pl = mplist_get (pl, command);
4087 MERROR (MERROR_IM, -1);
4089 mplist_add (p, Mtext, mplist_value (pl));
4090 keyseq = mplist_copy (keyseq);
4091 mplist_add (p, Mplist, keyseq);
4092 M17N_OBJECT_UNREF (keyseq);
4093 mplist_push (plist, command, p);
4099 @brief Get a list of variables of an input method.
4101 The minput_get_variables () function returns a plist (#MPlist) of
4102 variables used to control the behavior of the input method
4103 specified by $LANGUAGE and $NAME. The plist is @e well-formed
4104 (#m17nPlist) of the following format:
4107 (VARNAME (DOC-MTEXT DEFAULT-VALUE [ VALUE ... ] )
4108 VARNAME (DOC-MTEXT DEFAULT-VALUE [ VALUE ... ] )
4112 @c VARNAME is a symbol representing the variable name.
4114 @c DOC-MTEXT is an M-text describing the variable.
4116 @c DEFAULT-VALUE is the default value of the varible. It is a
4117 symbol, integer, or M-text.
4119 @c VALUEs (if any) specifies the possible values of the variable.
4120 If @c DEFAULT-VALUE is an integer, @c VALUE may be a plist (@c FROM
4121 @c TO), where @c FROM and @c TO specifies a range of possible
4124 For instance, suppose an input method has the variables:
4126 @li name:intvar, description:"value is an integer",
4127 initial value:0, value-range:0..3,10,20
4129 @li name:symvar, description:"value is a symbol",
4130 initial value:nil, value-range:a, b, c, nil
4132 @li name:txtvar, description:"value is an M-text",
4133 initial value:empty text, no value-range (i.e. any text)
4135 Then, the returned plist is as follows.
4138 (intvar ("value is an integer" 0 (0 3) 10 20)
4139 symvar ("value is a symbol" nil a b c nil)
4140 txtvar ("value is an M-text" ""))
4144 If the input method uses any variables, a pointer to #MPlist is
4145 returned. As the plist is kept in the library, a caller must not
4146 modify nor free it. If the input method does not use any
4147 variable, @c NULL is returned. */
4149 @brief ÆþÎϥ᥽¥Ã¥É¤ÎÊÑ¿ô¥ê¥¹¥È¤òÆÀ¤ë.
4151 ´Ø¿ô minput_get_variables () ¤Ï¡¢$LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ»ØÄꤵ
4152 ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤Î¿¶¤ëÉñ¤¤¤òÀ©¸æ¤¹¤ëÊÑ¿ô¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È
4153 (#MPlist) ¤òÊÖ¤¹¡£¤³¤Î¥ê¥¹¥È¤Ï @e well-formed ¤Ç¤¢¤ê(#m17nPlist) °Ê
4157 (VARNAME (DOC-MTEXT DEFAULT-VALUE [ VALUE ... ] )
4158 VARNAME (DOC-MTEXT DEFAULT-VALUE [ VALUE ... ] )
4162 @c VARNAME ¤ÏÊÑ¿ô¤Î̾Á°¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
4164 @c DOC-MTEXT ¤ÏÊÑ¿ô¤òÀâÌÀ¤¹¤ë M-text ¤Ç¤¢¤ë¡£
4166 @c DEFAULT-VALUE ¤ÏÊÑ¿ô¤Î¥Ç¥Õ¥©¥ë¥ÈÃͤǤ¢¤ê¡¢¥·¥ó¥Ü¥ë¡¢À°¿ô¤â¤·¤¯¤Ï
4169 @c VALUE ¤Ï¡¢¤â¤·»ØÄꤵ¤ì¤Æ¤¤¤ì¤ÐÊÑ¿ô¤Î¼è¤êÆÀ¤ëÃͤò¼¨¤¹¡£¤â¤·
4170 @c DEFAULT-VALUE ¤¬À°¿ô¤Ê¤é¡¢ @c VALUE ¤Ï (@c FROM @c TO) ¤È¤¤¤¦·Á
4171 ¤Î¥ê¥¹¥È¤Ç¤âÎɤ¤¡£¤³¤Î¾ì¹ç @c FROM ¤È @c TO ¤Ï²Äǽ¤ÊÃͤÎÈϰϤò¼¨¤¹¡£
4173 Îã¤È¤·¤Æ¡¢¤¢¤ëÆþÎϥ᥽¥Ã¥É¤¬¼¡¤Î¤è¤¦¤ÊÊÑ¿ô¤ò»ý¤Ä¾ì¹ç¤ò¹Í¤¨¤è¤¦¡£
4175 @li name:intvar, ÀâÌÀ:"value is an integer",
4176 ½é´üÃÍ:0, ÃͤÎÈÏ°Ï:0..3,10,20
4178 @li name:symvar, ÀâÌÀ:"value is a symbol",
4179 ½é´üÃÍ:nil, ÃͤÎÈÏ°Ï:a, b, c, nil
4181 @li name:txtvar, ÀâÌÀ:"value is an M-text",
4182 ½é´üÃÍ:empty text, ÃͤÎÈϰϤʤ·(¤É¤ó¤Ê M-text ¤Ç¤â²Ä)
4184 ¤³¤Î¾ì¹ç¡¢ÊÖ¤µ¤ì¤ë¥ê¥¹¥È¤Ï°Ê²¼¤Î¤è¤¦¤Ë¤Ê¤ë¡£
4187 (intvar ("value is an integer" 0 (0 3) 10 20)
4188 symvar ("value is a symbol" nil a b c nil)
4189 txtvar ("value is an M-text" ""))
4193 ÆþÎϥ᥽¥Ã¥É¤¬²¿¤é¤«¤ÎÊÑ¿ô¤ò»ÈÍѤ·¤Æ¤¤¤ì¤Ð #MPlist ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
4194 ÊÖ¤µ¤ì¤ë¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ï¥é¥¤¥Ö¥é¥ê¤Ë¤è¤Ã¤Æ´ÉÍý¤µ¤ì¤Æ¤ª¤ê¡¢¸Æ¤Ó½Ð¤·Â¦¤ÇÊѹ¹¤·¤¿¤ê²òÊü¤·¤¿¤ê¤·¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
4195 ÆþÎϥ᥽¥Ã¥É¤¬ÊÑ¿ô¤ò°ìÀÚ»ÈÍѤ·¤Æ¤Ê¤±¤ì¤Ð¡¢@c NULL ¤òÊÖ¤¹¡£ */
4198 minput_get_variables (MSymbol language, MSymbol name)
4200 MPlist *plist = get_nested_list (language, name, Mnil, M_variable);
4202 return (MPLIST_TAIL_P (plist) ? NULL : plist);
4206 @brief Set the initial value of an input method variable.
4208 The minput_set_variable () function sets the initial value of
4209 input method variable $VARIABLE to $VALUE for the input method
4210 specified by $LANGUAGE and $NAME.
4212 By default, the initial value is 0.
4214 This setting gets effective in a newly opened input method.
4217 If the operation was successful, 0 is returned. Otherwise -1 is
4218 returned, and #merror_code is set to #MERROR_IM. */
4220 @brief ÆþÎϥ᥽¥Ã¥ÉÊÑ¿ô¤Î½é´üÃͤòÀßÄꤹ¤ë.
4222 ´Ø¿ô minput_set_variable () ¤Ï¡¢$LANGUAGE ¤È $NAME
4223 ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ÎÆþÎϥ᥽¥Ã¥ÉÊÑ¿ô $VARIABLE
4224 ¤Î½é´üÃͤò¡¢ $VALUE ¤ËÀßÄꤹ¤ë¡£
4226 ¥Ç¥Õ¥©¥ë¥È¤Î½é´üÃÍ¤Ï 0 ¤Ç¤¢¤ë¡£
4228 ¤³¤ÎÀßÄê¤Ï¡¢¿·¤·¤¯¥ª¡¼¥×¥ó¤µ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤«¤é͸ú¤È¤Ê¤ë¡£
4231 ½èÍý¤¬À®¸ù¤¹¤ì¤Ð 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤·¡¢
4232 #merror_code ¤ò #MERROR_IM ¤ËÀßÄꤹ¤ë¡£ */
4235 minput_set_variable (MSymbol language, MSymbol name,
4236 MSymbol variable, void *value)
4238 MPlist *plist, *val_element, *range_element;
4241 plist = get_nested_list (language, name, Mnil, M_variable);
4243 MERROR (MERROR_IM, -1);
4244 plist = mplist_find_by_value (plist, variable);
4246 MERROR (MERROR_IM, -1);
4247 plist = MPLIST_PLIST (MPLIST_NEXT (plist));
4248 val_element = MPLIST_NEXT (plist);
4249 type = MPLIST_KEY (val_element);
4250 range_element = MPLIST_NEXT (val_element);
4252 if (! MPLIST_TAIL_P (range_element))
4254 if (type == Minteger)
4256 int val = (int) value, this_val;
4258 MPLIST_DO (plist, range_element)
4260 this_val = (int) MPLIST_VAL (plist);
4261 if (MPLIST_PLIST_P (plist))
4263 int min_bound, max_bound;
4264 MPlist *pl = MPLIST_PLIST (plist);
4266 min_bound = (int) MPLIST_VAL (pl);
4267 pl = MPLIST_NEXT (pl);
4268 max_bound = (int) MPLIST_VAL (pl);
4269 if (val >= min_bound && val <= max_bound)
4272 else if (val == this_val)
4275 if (MPLIST_TAIL_P (plist))
4276 MERROR (MERROR_IM, -1);
4278 else if (type == Msymbol)
4280 MPLIST_DO (plist, range_element)
4281 if (MPLIST_SYMBOL (plist) == (MSymbol) value)
4283 if (MPLIST_TAIL_P (plist))
4284 MERROR (MERROR_IM, -1);
4286 else /* type == Mtext */
4288 MPLIST_DO (plist, range_element)
4289 if (mtext_cmp (MPLIST_MTEXT (plist), (MText *) value) == 0)
4291 if (MPLIST_TAIL_P (plist))
4292 MERROR (MERROR_IM, -1);
4293 M17N_OBJECT_REF (value);
4297 mplist_set (val_element, type, value);
4303 /*** @addtogroup m17nDebug */
4309 @brief Dump an input method.
4311 The mdebug_dump_im () function prints the input method $IM in a
4312 human readable way to the stderr. $INDENT specifies how many
4313 columns to indent the lines but the first one.
4316 This function returns $IM. */
4318 @brief ÆþÎϥ᥽¥Ã¥É¤ò¥À¥ó¥×¤¹¤ë.
4320 ´Ø¿ô mdebug_dump_im () ¤ÏÆþÎϥ᥽¥Ã¥É $IM ¤ò stderr
4321 ¤Ë¿Í´Ö¤Ë²ÄÆɤʷÁ¤Ç°õºþ¤¹¤ë¡£$INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£
4324 ¤³¤Î´Ø¿ô¤Ï $IM ¤òÊÖ¤¹¡£ */
4327 mdebug_dump_im (MInputMethod *im, int indent)
4329 MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
4332 prefix = (char *) alloca (indent + 1);
4333 memset (prefix, 32, indent);
4334 prefix[indent] = '\0';
4336 fprintf (stderr, "(input-method %s %s ", msymbol_name (im->language),
4337 msymbol_name (im->name));
4338 mdebug_dump_mtext (im_info->title, 0, 0);
4339 if (im->name != Mnil)
4343 MPLIST_DO (state, im_info->states)
4345 fprintf (stderr, "\n%s ", prefix);
4346 dump_im_state (MPLIST_VAL (state), indent + 2);
4349 fprintf (stderr, ")");