1 /* input.c -- input method module.
2 Copyright (C) 2003, 2004
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 driver of the input
30 method. An input driver is a set of functions for handling the
31 input method. There are two kinds of input methods; internal one
36 <li> Internal Input Method
38 An internal input method has non @c Mnil LANGUAGE, and the body is
39 defined in the m17n database by the tag <Minput_method, LANGUAGE,
40 NAME>. For this kind of input methods, the m17n library uses two
41 predefined input method drivers, one for CUI use and the other for
42 GUI use. Those driver utilize the input processing engine
43 provided by the m17n library itself. The m17n database may
44 provides an input method that is not only for a specific language.
45 The database uses @c Mt as the language of such an input method.
47 An internal input method accepts an input key which is a symbol
48 associated with an input event. As there is no way for the @c
49 m17n @c library to know how input events are represented in an
50 application program, a application programmer have to convert an
51 input event to an input key by himself. See the documentation of
52 the function minput_event_to_key () for the detail.
54 <li> Foreign Input Method
56 A foreign input method has @c Mnil LANGUAGE, and the body is
57 defined in an external resources (e.g. XIM of X Window System).
58 For this kind of input methods, the symbol NAME must have a
59 property of key @c Minput_driver, and the value must be a pointer
60 to an input driver. So, by preparing a proper input
61 driver, any kind of input method can be treated in the framework
62 of the @c m17n @c library.
64 For convenience, the m17n-X library provides an input driver that
65 enables the input style of OverTheSpot for XIM, and stores @c
66 Minput_driver property of the symbol @c Mxim with a pointer to
67 that driver. See the documentation of m17n GUI API for the
74 The typical processing flow of handling an input method is: open
75 an input method, create an input context for the input method,
76 filter an input key, and looking up a produced text in the input
82 @addtogroup m17nInputMethod
83 @brief ÆþÎϥ᥽¥Ã¥ÉÍÑAPI
85 ÆþÎϥ᥽¥Ã¥É¤Ï¿ÍͤÊʸ»ú¤òÆþÎϤ¹¤ë¤¿¤á¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¢¤ë¡£ÆþÎÏ¥á
86 ¥½¥Ã¥É¤Ï¥·¥ó¥Ü¥ë LANGUAGE ¤È NAME ¤ÎÁȤˤè¤Ã¤Æ¼±Ê̤µ¤ì¡¢¤³¤ÎÁȤˤè¤Ã
87 ¤ÆÆþÎϥɥ饤¥Ð¤¬·è¤Þ¤ë¡£ÆþÎϥɥ饤¥Ð¤È¤Ï»ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤ò°·¤¦¤¿
88 ¤á¤Î´Ø¿ô¤Î½¸¤Þ¤ê¤Ç¤¢¤ë¡£
90 ÆþÎϥ᥽¥Ã¥É¤Ë¤ÏÆâÉô¥á¥½¥Ã¥É¤È³°Éô¥á¥½¥Ã¥É¤ÎÆóÄ̤꤬¤¢¤ë¡£
94 ÆâÉôÆþÎϥ᥽¥Ã¥É¤Ï LANGUAGE ¤¬ @c Mnil °Ê³°¤Î¤â¤Î¤Ç¤¢¤ê¡¢ËÜÂΤÏ
95 m17n ¸À¸ì¾ðÊó¥Ù¡¼¥¹¤Ë <Minput_method, LANGUAGE, NAME>¤È¤¤¤¦¥¿¥°ÉÕ
96 ¤¤ÇÄêµÁ¤µ¤ì¤Æ¤¤¤ë¡£¤³¤Î¼ï¤ÎÆþÎϥ᥽¥Ã¥É¤ËÂФ·¤Æ¡¢m17n¥é¥¤¥Ö¥é¥ê¤Ë
97 ¤ÏCUIÍѤÈGUIÍѤ½¤ì¤¾¤ì¤ÎÆþÎϥɥ饤¥Ð¤¬¤¢¤é¤«¤¸¤á½àÈ÷¤µ¤ì¤Æ¤¤¤ë¡£¤³
98 ¤ì¤é¤Î¥É¥é¥¤¥Ð¤Ïm17n¥é¥¤¥Ö¥é¥ê¼«¿È¤ÎÆþÎϽèÍý¥¨¥ó¥¸¥ó¤òÍøÍѤ¹¤ë¡£
100 ÆâÉôÆþÎϥ᥽¥Ã¥É¤Ï¡¢¥æ¡¼¥¶¤ÎÆþÎÏ¥¤¥Ù¥ó¥È¤ËÂбþ¤·¤¿ÆþÎÏ¥¡¼¤ò¼õ¤±¼è
101 ¤ë¡£ÆþÎÏ¥¡¼¤Ï¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£@c m17n @c ¥é¥¤¥Ö¥é¥ê ¤ÏÆþÎÏ¥¤¥Ù¥ó¥È
102 ¤¬¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¡¦¥×¥í¥°¥é¥à¤Ç¤É¤Î¤è¤¦¤Ëɽ¸½¤µ¤ì¤Æ¤¤¤ë¤«¤òÃΤë½Ñ
103 ¤ò»ý¤¿¤Ê¤¤¤Î¤Ç¡¢ÆþÎÏ¥¤¥Ù¥ó¥È¤«¤éÆþÎÏ¥¡¼¤Ø¤ÎÊÑ´¹¤Ï¥×¥í¥°¥é¥Þ¤ÎÀÕǤ
104 ¤Ç¹Ô¤ï¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï´Ø¿ô minput_event_to_key ()
105 ¤Î¥É¥¥å¥á¥ó¥È¤ò»²¾È¤Î¤³¤È¡£
109 ³°ÉôÆþÎϥ᥽¥Ã¥É¤Ï LANGUAGE ¤¬ @c Mnil ¤Î¤â¤Î¤Ç¤¢¤ê¡¢¤ÇËÜÂΤϳ°Éô
110 ¤Î¥ê¥½¡¼¥¹¤È¤·¤ÆÄêµÁ¤µ¤ì¤ë¡£¡Ê¤¿¤È¤¨¤ÐX Window System ¤ÎXIM ¤Ê¤É¡£)
111 ¤³¤Î¼ï¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¥·¥ó¥Ü¥ë NAME ¤Ï@c Minput_driver ¤ò¥¡¼¤È
112 ¤¹¤ë¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Á¡¢¤½¤ÎÃͤÏÆþÎϥɥ饤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê
113 ¤é¤Ê¤¤¡£¤·¤¿¤¬¤Ã¤Æ¡¢Å¬ÀÚ¤ÊÆþÎϥɥ饤¥Ð¤ò½àÈ÷¤¹¤ë¤³¤È¤Ë¤è¤Ã¤Æ¡¢¤¤¤«
114 ¤Ê¤ëÆþÎϥ᥽¥Ã¥É¤â @c m17n @c ¥é¥¤¥Ö¥é¥ê¤ÎÏÈÁȤÎÃæ¤Ç°·¤¦»ö¤¬¤Ç¤¤ë¡£
116 ´Êñ¤Î¤¿¤á¡¢m17n X ¥é¥¤¥Ö¥é¥ê¤ÏXIM ¤Î OverTheSpot ¤ÎÆþÎÏ¥¹¥¿¥¤¥ë¤ò
117 ¼Â¸½¤¹¤ëÆþÎϥɥ饤¥Ð¤òÄ󶡤·¤Æ¤¤¤ë¡£¤Þ¤¿¥·¥ó¥Ü¥ë @c Mxim ¤Î @c
118 Minput_driver ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤȤ·¤Æ¤½¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÝ»ý¤·
119 ¤Æ¤¤¤ë¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ïm17n-win API ¤Î¥É¥¥å¥á¥ó¥È¤ò»²¾È¤Î¤³¤È¡£
123 ÆþÎϥ᥽¥Ã¥É½èÍý¤Îŵ·¿Åª¤Ê½èÍý¤Ï°Ê²¼¤Î¤è¤¦¤Ë¤Ê¤ë¡£ÆþÎϥ᥽¥Ã¥É¤Î¥ª¡¼
124 ¥×¥ó¡¢¤½¤ÎÆþÎϥ᥽¥Ã¥É¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤ÎÀ¸À®¡¢ÆþÎÏ¥¤¥Ù¥ó¥È¤Î¥Õ¥£
125 ¥ë¥¿¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ç¤ÎÀ¸À®¥Æ¥¥¹¥È¤Î¸¡º÷¡£ */
129 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
130 /*** @addtogroup m17nInternal
138 #include "m17n-gui.h"
139 #include "m17n-misc.h"
140 #include "internal.h"
146 static MSymbol Minput_method;
148 /** Symbols to load an input method data. */
149 static MSymbol Mtitle, Mmacro, Mmodule, Mstate;
151 /** Symbols for actions. */
152 static MSymbol Minsert, Mdelete, Mmark, Mmove, Mpushback, Mundo, Mcall, Mshift;
153 static MSymbol Mselect, Mshow, Mhide;
154 static MSymbol Mset, Madd, Msub, Mmul, Mdiv, Mequal, Mless, Mgreater;
156 static MSymbol Mcandidate_list, Mcandidate_index;
158 static MSymbol Minit, Mfini;
160 /** Symbols for key events. */
161 static MSymbol one_char_symbol[256];
163 /** Structure to hold a map. */
167 /** List of actions to take when we reach the map. In a root map,
168 the actions are executed only when there's no more key. */
171 /** List of deeper maps. If NULL, this is a terminal map. */
174 /** List of actions to take when we leave the map successfully. In
175 a root map, the actions are executed only when none of submaps
176 handle the current key. */
177 MPlist *branch_actions;
180 typedef MPlist *(*MIMExternalFunc) (MPlist *plist);
185 MPlist *func_list; /* function name vs (MIMExternalFunc *) */
190 /** Name of the state. */
193 /** Title of the state, or NULL. */
196 /** Key translation map of the state. Built by merging all maps of
203 marker_code (MSymbol sym)
209 name = MSYMBOL_NAME (sym);
210 return ((name[0] == '@'
211 && ((name[1] >= '0' && name[1] <= '9')
212 || name[1] == '<' || name[1] == '>'
213 || name[1] == '=' || name[1] == '+' || name[1] == '-'
214 || name[1] == '[' || name[1] == ']')
220 integer_value (MInputContext *ic, MPlist *arg)
222 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
224 MText *preedit = ic->preedit;
225 int len = mtext_nbytes (preedit);
227 if (MPLIST_INTEGER_P (arg))
228 return MPLIST_INTEGER (arg);
229 code = marker_code (MPLIST_SYMBOL (arg));
231 return (int) mplist_get (ic_info->vars, MPLIST_SYMBOL (arg));
232 if (code >= '0' && code <= '9')
234 else if (code == '=')
235 code = ic->cursor_pos;
236 else if (code == '-' || code == '[')
237 code = ic->cursor_pos - 1;
238 else if (code == '+' || code == ']')
239 code = ic->cursor_pos + 1;
240 else if (code == '<')
242 else if (code == '<')
244 return (code >= 0 && code < len ? mtext_ref_char (preedit, code) : -1);
248 /* Parse PLIST as an action list while modifying the list to regularize
249 actions. PLIST should have this form:
250 PLIST ::= ( (ACTION-NAME ACTION-ARG *) *).
251 Return 0 if successfully parsed, otherwise return -1. */
254 parse_action_list (MPlist *plist, MPlist *macros)
256 MPLIST_DO (plist, plist)
258 if (MPLIST_MTEXT_P (plist))
260 /* This is a short form of (insert MTEXT). */
261 /* if (mtext_nchars (MPLIST_MTEXT (plist)) == 0)
262 MERROR (MERROR_IM, -1); */
264 else if (MPLIST_PLIST_P (plist)
265 && (MPLIST_MTEXT_P (MPLIST_PLIST (plist))
266 || MPLIST_PLIST_P (MPLIST_PLIST (plist))))
270 /* This is a short form of (insert (GROUPS *)). */
271 MPLIST_DO (pl, MPLIST_PLIST (plist))
273 if (MPLIST_PLIST_P (pl))
277 MPLIST_DO (elt, MPLIST_PLIST (pl))
278 if (! MPLIST_MTEXT_P (elt)
279 || mtext_nchars (MPLIST_MTEXT (elt)) == 0)
280 MERROR (MERROR_IM, -1);
284 if (! MPLIST_MTEXT_P (pl)
285 || mtext_nchars (MPLIST_MTEXT (pl)) == 0)
286 MERROR (MERROR_IM, -1);
290 else if (MPLIST_INTEGER_P (plist))
292 int c = MPLIST_INTEGER (plist);
294 if (c < 0 || c > MCHAR_MAX)
295 MERROR (MERROR_IM, -1);
297 else if (MPLIST_PLIST_P (plist)
298 && MPLIST_SYMBOL_P (MPLIST_PLIST (plist)))
300 MPlist *pl = MPLIST_PLIST (plist);
301 MSymbol action_name = MPLIST_SYMBOL (pl);
303 pl = MPLIST_NEXT (pl);
305 if (action_name == Minsert)
307 if (MPLIST_MTEXT_P (pl))
309 if (mtext_nchars (MPLIST_MTEXT (pl)) == 0)
310 MERROR (MERROR_IM, -1);
312 else if (MPLIST_PLIST_P (pl))
316 if (MPLIST_PLIST_P (pl))
320 MPLIST_DO (elt, MPLIST_PLIST (pl))
321 if (! MPLIST_MTEXT_P (elt)
322 || mtext_nchars (MPLIST_MTEXT (elt)) == 0)
323 MERROR (MERROR_IM, -1);
327 if (! MPLIST_MTEXT_P (pl)
328 || mtext_nchars (MPLIST_MTEXT (pl)) == 0)
329 MERROR (MERROR_IM, -1);
333 else if (! MPLIST_SYMBOL_P (pl))
334 MERROR (MERROR_IM, -1);
336 else if (action_name == Mselect
337 || action_name == Mdelete
338 || action_name == Mmove)
340 if (! MPLIST_SYMBOL_P (pl)
341 && ! MPLIST_INTEGER_P (pl))
342 MERROR (MERROR_IM, -1);
344 else if (action_name == Mmark
345 || action_name == Mcall
346 || action_name == Mshift)
348 if (! MPLIST_SYMBOL_P (pl))
349 MERROR (MERROR_IM, -1);
351 else if (action_name == Mshow || action_name == Mhide
352 || action_name == Mundo)
354 if (! MPLIST_TAIL_P (pl))
355 MERROR (MERROR_IM, -1);
357 else if (action_name == Mpushback)
359 if (! MPLIST_INTEGER_P (pl))
360 MERROR (MERROR_IM, -1);
362 else if (action_name == Mset || action_name == Madd
363 || action_name == Msub || action_name == Mmul
364 || action_name == Mdiv)
366 if (! (MPLIST_SYMBOL_P (pl)
367 && (MPLIST_INTEGER_P (MPLIST_NEXT (pl))
368 || MPLIST_SYMBOL_P (MPLIST_NEXT (pl)))))
369 MERROR (MERROR_IM, -1);
371 else if (action_name == Mequal || action_name == Mless
372 || action_name == Mgreater)
374 if (! ((MPLIST_INTEGER_P (pl) || MPLIST_SYMBOL_P (pl))
375 && (MPLIST_INTEGER_P (MPLIST_NEXT (pl))
376 || MPLIST_SYMBOL_P (MPLIST_NEXT (pl)))))
377 MERROR (MERROR_IM, -1);
378 pl = MPLIST_NEXT (MPLIST_NEXT (pl));
379 if (! MPLIST_PLIST_P (pl))
380 MERROR (MERROR_IM, -1);
381 if (parse_action_list (MPLIST_PLIST (pl), macros) < 0)
382 MERROR (MERROR_IM, -1);
383 pl = MPLIST_NEXT (pl);
384 if (MPLIST_PLIST_P (pl)
385 && parse_action_list (MPLIST_PLIST (pl), macros) < 0)
386 MERROR (MERROR_IM, -1);
388 else if (! macros || ! mplist_get (macros, action_name))
389 MERROR (MERROR_IM, -1);
392 MERROR (MERROR_IM, -1);
399 /* Load a translation into MAP from PLIST.
401 PLIST ::= ( KEYSEQ MAP-ACTION * ) */
404 load_translation (MIMMap *map, MPlist *plist, MPlist *branch_actions,
410 if (MPLIST_MTEXT_P (plist))
412 MText *mt = MPLIST_MTEXT (plist);
414 len = mtext_nchars (mt);
415 if (len == 0 || len != mtext_nbytes (mt))
416 MERROR (MERROR_IM, -1);
417 keyseq = (MSymbol *) alloca (sizeof (MSymbol) * len);
418 for (i = 0; i < len; i++)
419 keyseq[i] = one_char_symbol[MTEXT_DATA (mt)[i]];
421 else if (MPLIST_PLIST_P (plist))
423 MPlist *elt = MPLIST_PLIST (plist);
425 len = MPLIST_LENGTH (elt);
427 MERROR (MERROR_IM, -1);
428 keyseq = (MSymbol *) alloca (sizeof (int) * len);
429 for (i = 0; i < len; i++, elt = MPLIST_NEXT (elt))
431 if (MPLIST_INTEGER_P (elt))
433 int c = MPLIST_INTEGER (elt);
435 if (c < 0 || c >= 0x100)
436 MERROR (MERROR_IM, -1);
437 keyseq[i] = one_char_symbol[c];
439 else if (MPLIST_SYMBOL_P (elt))
440 keyseq[i] = MPLIST_SYMBOL (elt);
442 MERROR (MERROR_IM, -1);
446 MERROR (MERROR_IM, -1);
448 for (i = 0; i < len; i++)
450 MIMMap *deeper = NULL;
453 deeper = mplist_get (map->submaps, keyseq[i]);
455 map->submaps = mplist ();
458 /* Fixme: It is better to make all deeper maps at once. */
459 MSTRUCT_CALLOC (deeper, MERROR_IM);
460 mplist_put (map->submaps, keyseq[i], deeper);
465 /* We reach a terminal map. */
467 || map->branch_actions)
468 /* This map is already defined. We avoid overriding it. */
471 plist = MPLIST_NEXT (plist);
472 if (! MPLIST_TAIL_P (plist))
474 if (parse_action_list (plist, macros) < 0)
475 MERROR (MERROR_IM, -1);
476 map->map_actions = plist;
477 M17N_OBJECT_REF (plist);
481 map->branch_actions = branch_actions;
482 M17N_OBJECT_REF (branch_actions);
488 /* Load a branch from PLIST into MAP. PLIST has this form:
489 PLIST ::= ( MAP-NAME BRANCH-ACTION * )
490 MAPS is a plist of raw maps.
491 STATE is the current state. */
494 load_branch (MPlist *plist, MPlist *maps, MIMMap *map, MPlist *macros)
497 MPlist *branch_actions;
499 if (! MPLIST_SYMBOL_P (plist))
500 MERROR (MERROR_IM, -1);
501 map_name = MPLIST_SYMBOL (plist);
502 plist = MPLIST_NEXT (plist);
503 if (MPLIST_TAIL_P (plist))
504 branch_actions = NULL;
505 else if (parse_action_list (plist, macros) < 0)
506 MERROR (MERROR_IM, -1);
508 branch_actions = plist;
509 if (map_name == Mnil)
511 map->branch_actions = branch_actions;
513 M17N_OBJECT_REF (branch_actions);
515 else if (map_name == Mt)
517 map->map_actions = branch_actions;
519 M17N_OBJECT_REF (branch_actions);
523 plist = (MPlist *) mplist_get (maps, map_name);
524 if (! plist || ! MPLIST_PLIST_P (plist))
525 MERROR (MERROR_IM, -1);
526 MPLIST_DO (plist, plist)
527 if (! MPLIST_PLIST_P (plist)
528 || (load_translation (map, MPLIST_PLIST (plist), branch_actions,
531 MERROR (MERROR_IM, -1);
537 /* Load a macro from PLIST into MACROS.
539 PLIST ::= ( MACRO-NAME ACTION * )
540 MACROS is a plist of macro names vs action list. */
542 load_macros (MPlist *plist, MPlist *macros)
546 if (! MPLIST_SYMBOL_P (plist))
547 MERROR (MERROR_IM, -1);
548 name = MPLIST_SYMBOL (plist);
549 plist = MPLIST_NEXT (plist);
550 if (MPLIST_TAIL_P (plist)
551 || parse_action_list (plist, macros) < 0)
552 MERROR (MERROR_IM, -1);
553 mplist_put (macros, name, plist);
554 M17N_OBJECT_REF (plist);
558 /* Load an external module from PLIST into EXTERNALS.
560 PLIST ::= ( MODULE-NAME FUNCTION * )
561 EXTERNALS is a plist of MODULE-NAME vs (MIMExternalModule *). */
563 #ifndef DLOPEN_SHLIB_EXT
564 #define DLOPEN_SHLIB_EXT ".so"
568 load_external_module (MPlist *plist, MPlist *externals)
573 MIMExternalModule *external;
577 if (MPLIST_MTEXT_P (plist))
578 module = msymbol ((char *) MTEXT_DATA (MPLIST_MTEXT (plist)));
579 else if (MPLIST_SYMBOL_P (plist))
580 module = MPLIST_SYMBOL (plist);
581 module_file = alloca (strlen (MSYMBOL_NAME (module))
582 + strlen (DLOPEN_SHLIB_EXT) + 1);
583 sprintf (module_file, "%s%s", MSYMBOL_NAME (module), DLOPEN_SHLIB_EXT);
585 handle = dlopen (module_file, RTLD_NOW);
588 fprintf (stderr, "%s\n", dlerror ());
589 MERROR (MERROR_IM, -1);
591 func_list = mplist ();
592 MPLIST_DO (plist, MPLIST_NEXT (plist))
594 if (! MPLIST_SYMBOL_P (plist))
595 MERROR_GOTO (MERROR_IM, err_label);
596 func = dlsym (handle, MSYMBOL_NAME (MPLIST_SYMBOL (plist)));
598 MERROR_GOTO (MERROR_IM, err_label);
599 mplist_add (func_list, MPLIST_SYMBOL (plist), func);
602 MSTRUCT_MALLOC (external, MERROR_IM);
603 external->handle = handle;
604 external->func_list = func_list;
605 mplist_add (externals, module, external);
610 M17N_OBJECT_UNREF (func_list);
615 /** Load a state from PLIST into a newly allocated state object.
617 PLIST ::= ( STATE-NAME STATE-TITLE ? BRANCH * )
618 BRANCH ::= ( MAP-NAME BRANCH-ACTION * )
619 MAPS is a plist of defined maps.
620 Return the state object. */
623 load_state (MPlist *plist, MPlist *maps, MSymbol language, MPlist *macros)
627 MSTRUCT_CALLOC (state, MERROR_IM);
628 if (! MPLIST_SYMBOL_P (plist))
629 MERROR (MERROR_IM, NULL);
630 state->name = MPLIST_SYMBOL (plist);
631 plist = MPLIST_NEXT (plist);
632 if (MPLIST_MTEXT_P (plist))
634 state->title = MPLIST_MTEXT (plist);
635 mtext_put_prop (state->title, 0, mtext_nchars (state->title),
636 Mlanguage, language);
637 M17N_OBJECT_REF (state->title);
638 plist = MPLIST_NEXT (plist);
640 MSTRUCT_CALLOC (state->map, MERROR_IM);
641 MPLIST_DO (plist, plist)
642 if (! MPLIST_PLIST_P (plist)
643 || load_branch (MPLIST_PLIST (plist), maps, state->map, macros) < 0)
644 MERROR (MERROR_IM, NULL);
650 free_map (MIMMap *map)
654 M17N_OBJECT_UNREF (map->map_actions);
657 MPLIST_DO (plist, map->submaps)
658 free_map ((MIMMap *) MPLIST_VAL (plist));
659 M17N_OBJECT_UNREF (map->submaps);
661 M17N_OBJECT_UNREF (map->branch_actions);
665 /* Load an input method from PLIST into IM_INTO, and return it. */
668 load_input_method (MSymbol language, MSymbol name, MPlist *plist,
669 MInputMethodInfo *im_info)
673 MPlist *states = NULL;
674 MPlist *externals = NULL;
675 MPlist *macros = NULL;
678 if (! MPLIST_PLIST_P (plist))
679 MERROR (MERROR_IM, -1);
680 for (; MPLIST_PLIST_P (plist); plist = MPLIST_NEXT (plist))
682 elt = MPLIST_PLIST (plist);
683 if (! MPLIST_SYMBOL_P (elt))
684 MERROR_GOTO (MERROR_IM, err);
685 if (MPLIST_SYMBOL (elt) == Mtitle)
687 elt = MPLIST_NEXT (elt);
688 if (MPLIST_MTEXT_P (elt))
690 title = MPLIST_MTEXT (elt);
691 M17N_OBJECT_REF (title);
694 MERROR_GOTO (MERROR_IM, err);
696 else if (MPLIST_SYMBOL (elt) == Mmap)
698 maps = mplist__from_alist (MPLIST_NEXT (elt));
700 MERROR_GOTO (MERROR_IM, err);
702 else if (MPLIST_SYMBOL (elt) == Mmacro)
705 MPLIST_DO (elt, MPLIST_NEXT (elt))
707 if (! MPLIST_PLIST_P (elt)
708 || load_macros (MPLIST_PLIST (elt), macros) < 0)
709 MERROR_GOTO (MERROR_IM, err);
712 else if (MPLIST_SYMBOL (elt) == Mmodule)
714 externals = mplist ();
715 MPLIST_DO (elt, MPLIST_NEXT (elt))
717 if (! MPLIST_PLIST_P (elt)
718 || load_external_module (MPLIST_PLIST (elt), externals) < 0)
719 MERROR_GOTO (MERROR_IM, err);
722 else if (MPLIST_SYMBOL (elt) == Mstate)
725 MPLIST_DO (elt, MPLIST_NEXT (elt))
729 if (! MPLIST_PLIST_P (elt))
730 MERROR_GOTO (MERROR_IM, err);
731 state = load_state (MPLIST_PLIST (elt), maps, language, macros);
733 MERROR_GOTO (MERROR_IM, err);
734 mplist_put (states, state->name, state);
739 MPLIST_DO (elt, maps)
740 M17N_OBJECT_UNREF (MPLIST_VAL (elt));
741 M17N_OBJECT_UNREF (maps);
743 title = mtext_from_data (MSYMBOL_NAME (name), MSYMBOL_NAMELEN (name),
744 MTEXT_FORMAT_US_ASCII);
745 im_info->title = title;
746 im_info->externals = externals;
747 im_info->macros = macros;
748 im_info->states = states;
754 MPLIST_DO (elt, maps)
755 M17N_OBJECT_UNREF (MPLIST_VAL (elt));
756 M17N_OBJECT_UNREF (maps);
759 M17N_OBJECT_UNREF (title);
762 MPLIST_DO (plist, states)
764 MIMState *state = (MIMState *) MPLIST_VAL (plist);
767 M17N_OBJECT_UNREF (state->title);
769 free_map (state->map);
772 M17N_OBJECT_UNREF (states);
776 MPLIST_DO (plist, externals)
778 MIMExternalModule *external = MPLIST_VAL (plist);
780 dlclose (external->handle);
781 M17N_OBJECT_UNREF (external->func_list);
783 MPLIST_KEY (plist) = Mt;
785 M17N_OBJECT_UNREF (externals);
792 static int take_action_list (MInputContext *ic, MPlist *action_list);
795 shift_state (MInputContext *ic, MSymbol state_name)
797 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
798 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
799 MIMState *state = ic_info->state;
801 /* Find a state to shift to. If not found, shift to the initial
803 state = (MIMState *) mplist_get (im_info->states, state_name);
805 state = (MIMState *) MPLIST_VAL (im_info->states);
807 /* Enter the new state. */
808 ic_info->state = state;
809 ic_info->map = state->map;
810 ic_info->state_key_head = ic_info->key_head;
811 if (state == (MIMState *) MPLIST_VAL (im_info->states))
813 /* We have shifted to the initial state. */
816 mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit),
817 Mcandidate_list, NULL, 0);
818 mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit),
819 Mcandidate_index, NULL, 0);
820 mtext_cat (ic->produced, ic->preedit);
821 mtext_reset (ic->preedit);
822 ic->candidate_list = NULL;
823 ic->candidate_show = 0;
824 ic->preedit_changed = ic->candidates_changed = 1;
825 MPLIST_DO (p, ic_info->markers)
827 MPLIST_DO (p, ic_info->vars)
830 memmove (ic_info->keys, ic_info->keys + ic_info->state_key_head,
831 sizeof (int) * (ic_info->used - ic_info->state_key_head));
832 ic_info->used -= ic_info->state_key_head;
833 ic_info->state_key_head = ic_info->key_head = 0;
835 mtext_cpy (ic_info->preedit_saved, ic->preedit);
836 ic_info->state_pos = ic->cursor_pos;
837 ic->status = state->title;
839 ic->status = im_info->title;
840 ic->status_changed = 1;
841 if (ic_info->key_head == ic_info->used
842 && ic_info->map == ic_info->state->map
843 && ic_info->map->map_actions)
844 take_action_list (ic, ic_info->map->map_actions);
849 find_candidates_group (MPlist *plist, int index,
850 int *start_index, int *end_index, int *group_index)
852 int i = 0, gidx = 0, len;
854 MPLIST_DO (plist, plist)
856 if (MPLIST_MTEXT_P (plist))
857 len = mtext_nchars (MPLIST_MTEXT (plist));
859 len = mplist_length (MPLIST_PLIST (plist));
865 *end_index = i + len;
877 preedit_insert (MInputContext *ic, int pos, MText *mt, int c)
879 MInputContextInfo *ic_info = ((MInputContext *) ic)->info;
881 int nchars = mt ? mtext_nchars (mt) : 1;
884 mtext_ins (ic->preedit, pos, mt);
886 mtext_ins_char (ic->preedit, pos, c, 1);
887 MPLIST_DO (markers, ic_info->markers)
888 if (MPLIST_INTEGER (markers) > pos)
889 MPLIST_VAL (markers) = (void *) (MPLIST_INTEGER (markers) + nchars);
890 if (ic->cursor_pos >= pos)
891 ic->cursor_pos += nchars;
892 ic->preedit_changed = 1;
897 preedit_delete (MInputContext *ic, int from, int to)
899 MInputContextInfo *ic_info = ((MInputContext *) ic)->info;
902 mtext_del (ic->preedit, from, to);
903 MPLIST_DO (markers, ic_info->markers)
905 if (MPLIST_INTEGER (markers) > to)
907 = (void *) (MPLIST_INTEGER (markers) - (to - from));
908 else if (MPLIST_INTEGER (markers) > from);
909 MPLIST_VAL (markers) = (void *) from;
911 if (ic->cursor_pos >= to)
912 ic->cursor_pos -= to - from;
913 else if (ic->cursor_pos > from)
914 ic->cursor_pos = from;
915 ic->preedit_changed = 1;
920 new_index (MInputContext *ic, int current, int limit, MSymbol sym, MText *mt)
922 int code = marker_code (sym);
924 if (mt && (code == '[' || code == ']'))
928 if (code == '[' && current > 0)
930 if (mtext_prop_range (mt, Mcandidate_list, pos - 1, &pos, NULL, 1)
934 else if (code == ']' && current < mtext_nchars (mt))
936 if (mtext_prop_range (mt, Mcandidate_list, pos, NULL, &pos, 1))
942 return (code == '<' ? 0
943 : code == '>' ? limit
944 : code == '-' ? current - 1
945 : code == '+' ? current + 1
946 : code == '=' ? current
947 : code - '0' > limit ? limit
951 return (int) mplist_get (((MInputContextInfo *) ic->info)->markers, sym);
955 udpate_candidate (MInputContext *ic, MTextProperty *prop, int idx)
957 int from = mtext_property_start (prop);
958 int to = mtext_property_end (prop);
960 MPlist *candidate_list = mtext_property_value (prop);
961 MPlist *group = find_candidates_group (candidate_list, idx, &start,
963 int ingroup_index = idx - start;
966 preedit_delete (ic, from, to);
967 if (MPLIST_MTEXT_P (group))
969 mt = MPLIST_MTEXT (group);
970 preedit_insert (ic, from, NULL, mtext_ref_char (mt, ingroup_index));
978 for (i = 0, plist = MPLIST_PLIST (group); i < ingroup_index;
979 i++, plist = MPLIST_NEXT (plist));
980 mt = MPLIST_MTEXT (plist);
981 preedit_insert (ic, from, mt, 0);
982 to = from + mtext_nchars (mt);
984 mtext_put_prop (ic->preedit, from, to, Mcandidate_list, candidate_list);
985 mtext_put_prop (ic->preedit, from, to, Mcandidate_index, (void *) idx);
991 take_action_list (MInputContext *ic, MPlist *action_list)
993 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
994 MPlist *candidate_list = ic->candidate_list;
995 int candidate_index = ic->candidate_index;
996 int candidate_show = ic->candidate_show;
999 MPLIST_DO (action_list, action_list)
1005 if (MPLIST_MTEXT_P (action_list)
1006 || MPLIST_INTEGER_P (action_list))
1007 name = Minsert, args = action_list;
1008 else if (MPLIST_PLIST_P (action_list)
1009 && (MPLIST_MTEXT_P (MPLIST_PLIST (action_list))
1010 || MPLIST_PLIST_P (MPLIST_PLIST (action_list))))
1011 name = Minsert, args = action_list;
1014 action = MPLIST_PLIST (action_list);
1015 name = MPLIST_SYMBOL (action);
1016 args = MPLIST_NEXT (action);
1019 if (name == Minsert)
1021 if (MPLIST_MTEXT_P (args))
1022 preedit_insert (ic, ic->cursor_pos, MPLIST_MTEXT (args), 0);
1023 else if (MPLIST_INTEGER_P (args))
1024 preedit_insert (ic, ic->cursor_pos, NULL, MPLIST_INTEGER (args));
1025 else if (MPLIST_SYMBOL_P (args))
1027 int c = integer_value (ic, args);
1029 if (c >= 0 && c <= MCHAR_MAX)
1030 preedit_insert (ic, ic->cursor_pos, NULL, c);
1037 args = MPLIST_PLIST (args);
1038 if (MPLIST_MTEXT_P (args))
1040 preedit_insert (ic, ic->cursor_pos, NULL,
1041 mtext_ref_char (MPLIST_MTEXT (args), 0));
1046 mt = MPLIST_MTEXT (MPLIST_PLIST (args));
1047 preedit_insert (ic, ic->cursor_pos, mt, 0);
1048 len = mtext_nchars (mt);
1050 mtext_put_prop (ic->preedit,
1051 ic->cursor_pos - len, ic->cursor_pos,
1052 Mcandidate_list, args);
1053 mtext_put_prop (ic->preedit,
1054 ic->cursor_pos - len, ic->cursor_pos,
1055 Mcandidate_index, (void *) 0);
1058 else if (name == Mselect)
1061 int code, idx, gindex;
1062 int pos = ic->cursor_pos;
1066 || ! (prop = mtext_get_property (ic->preedit, pos - 1,
1069 if (MPLIST_SYMBOL_P (args))
1071 code = marker_code (MPLIST_SYMBOL (args));
1077 idx = (int) mtext_get_prop (ic->preedit, pos - 1, Mcandidate_index);
1078 group = find_candidates_group (mtext_property_value (prop), idx,
1079 &start, &end, &gindex);
1081 if (code != '[' && code != ']')
1085 ? new_index (NULL, ic->candidate_index - start,
1086 end - start - 1, MPLIST_SYMBOL (args),
1088 : MPLIST_INTEGER (args)));
1091 && MPLIST_TAIL_P (MPLIST_NEXT (group))))
1096 int ingroup_index = idx - start;
1099 group = mtext_property_value (prop);
1100 len = mplist_length (group);
1113 for (idx = 0; gindex > 0; gindex--, group = MPLIST_NEXT (group))
1114 idx += (MPLIST_MTEXT_P (group)
1115 ? mtext_nchars (MPLIST_MTEXT (group))
1116 : mplist_length (MPLIST_PLIST (group)));
1117 len = (MPLIST_MTEXT_P (group)
1118 ? mtext_nchars (MPLIST_MTEXT (group))
1119 : mplist_length (MPLIST_PLIST (group)));
1120 if (ingroup_index >= len)
1121 ingroup_index = len - 1;
1122 idx += ingroup_index;
1124 udpate_candidate (ic, prop, idx);
1126 else if (name == Mshow)
1127 ic->candidate_show = 1;
1128 else if (name == Mhide)
1129 ic->candidate_show = 0;
1130 else if (name == Mdelete)
1132 int len = mtext_nchars (ic->preedit);
1133 int to = (MPLIST_SYMBOL_P (args)
1134 ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
1136 : MPLIST_INTEGER (args));
1142 if (to < ic->cursor_pos)
1143 preedit_delete (ic, to, ic->cursor_pos);
1144 else if (to > ic->cursor_pos)
1145 preedit_delete (ic, ic->cursor_pos, to);
1147 else if (name == Mmove)
1149 int len = mtext_nchars (ic->preedit);
1151 = (MPLIST_SYMBOL_P (args)
1152 ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
1154 : MPLIST_INTEGER (args));
1160 if (pos != ic->cursor_pos)
1162 ic->cursor_pos = pos;
1163 ic->preedit_changed = 1;
1166 else if (name == Mmark)
1168 int code = marker_code (MPLIST_SYMBOL (args));
1171 mplist_put (ic_info->markers, MPLIST_SYMBOL (args),
1172 (void *) ic->cursor_pos);
1174 else if (name == Mpushback)
1176 int num = MPLIST_INTEGER (args);
1179 ic_info->key_head -= num;
1181 ic_info->key_head = num;
1182 if (ic_info->key_head > ic_info->used)
1183 ic_info->key_head = ic_info->used;
1185 else if (name == Mcall)
1187 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1188 MIMExternalFunc func = NULL;
1189 MSymbol module, func_name;
1190 MPlist *func_args, *val;
1193 module = MPLIST_SYMBOL (args);
1194 args = MPLIST_NEXT (args);
1195 func_name = MPLIST_SYMBOL (args);
1197 if (im_info->externals)
1199 MIMExternalModule *external
1200 = (MIMExternalModule *) mplist_get (im_info->externals,
1203 func = (MIMExternalFunc) mplist_get (external->func_list,
1208 func_args = mplist ();
1209 mplist_add (func_args, Mt, ic);
1210 MPLIST_DO (args, MPLIST_NEXT (args))
1214 if (MPLIST_KEY (args) == Msymbol
1215 && MPLIST_KEY (args) != Mnil
1216 && (code = marker_code (MPLIST_SYMBOL (args))) >= 0)
1218 code = new_index (ic, ic->cursor_pos,
1219 mtext_nchars (ic->preedit),
1220 MPLIST_SYMBOL (args), ic->preedit);
1221 mplist_add (func_args, Minteger, (void *) code);
1224 mplist_add (func_args, MPLIST_KEY (args), MPLIST_VAL (args));
1226 val = (func) (func_args);
1227 M17N_OBJECT_UNREF (func_args);
1228 if (val && ! MPLIST_TAIL_P (val))
1229 ret = take_action_list (ic, val);
1230 M17N_OBJECT_UNREF (val);
1234 else if (name == Mshift)
1236 shift_state (ic, MPLIST_SYMBOL (args));
1238 else if (name == Mundo)
1240 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1243 mtext_reset (ic->preedit);
1244 mtext_reset (ic_info->preedit_saved);
1245 ic->cursor_pos = ic_info->state_pos = 0;
1246 ic_info->state_key_head = ic_info->key_head = 0;
1248 if (ic_info->used < 0)
1253 shift_state (ic, ((MIMState *) MPLIST_VAL (im_info->states))->name);
1258 else if (name == Mset || name == Madd || name == Msub
1259 || name == Mmul || name == Mdiv)
1261 MSymbol sym = MPLIST_SYMBOL (args);
1262 int val1 = (int) mplist_get (ic_info->vars, sym), val2;
1264 args = MPLIST_NEXT (args);
1265 val2 = integer_value (ic, args);
1268 else if (name == Madd)
1270 else if (name == Msub)
1272 else if (name == Mmul)
1276 mplist_put (ic_info->vars, sym, (void *) val1);
1278 else if (name == Mequal || name == Mless || name == Mgreater)
1281 MPlist *actions1, *actions2;
1284 val1 = integer_value (ic, args);
1285 args = MPLIST_NEXT (args);
1286 val2 = integer_value (ic, args);
1287 args = MPLIST_NEXT (args);
1288 actions1 = MPLIST_PLIST (args);
1289 args = MPLIST_NEXT (args);
1290 if (MPLIST_TAIL_P (args))
1293 actions2 = MPLIST_PLIST (args);
1294 if (name == Mequal ? val1 == val2
1295 : name == Mless ? val1 < val2
1297 ret = take_action_list (ic, actions1);
1299 ret = take_action_list (ic, actions2);
1305 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1309 && (actions = mplist_get (im_info->macros, name)))
1311 if (take_action_list (ic, actions) < 0)
1318 ic->candidate_list = NULL;
1319 if (ic->cursor_pos > 0
1320 && (prop = mtext_get_property (ic->preedit, ic->cursor_pos - 1,
1323 ic->candidate_list = mtext_property_value (prop);
1325 = (int) mtext_get_prop (ic->preedit, ic->cursor_pos - 1,
1327 ic->candidate_from = mtext_property_start (prop);
1328 ic->candidate_to = mtext_property_end (prop);
1331 ic->candidates_changed |= (candidate_list != ic->candidate_list
1332 || candidate_index != ic->candidate_index
1333 || candidate_show != ic->candidate_show);
1338 /* Handle the input key KEY in the current state and map specified in
1339 the input context IC. If KEY is handled correctly, return 0.
1340 Otherwise, return -1. */
1343 handle_key (MInputContext *ic)
1345 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1346 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1347 MIMMap *map = ic_info->map;
1349 MSymbol key = ic_info->keys[ic_info->key_head];
1352 submap = (map->submaps ? mplist_get (map->submaps, key) : NULL);
1355 mtext_cpy (ic->preedit, ic_info->preedit_saved);
1356 ic->cursor_pos = ic_info->state_pos;
1357 ic_info->key_head++;
1358 ic_info->map = map = submap;
1359 if (map->map_actions)
1361 if (take_action_list (ic, map->map_actions) < 0)
1364 else if (map->submaps)
1366 for (i = ic_info->state_key_head; i < ic_info->key_head; i++)
1368 MSymbol key = ic_info->keys[i];
1369 char *name = msymbol_name (key);
1371 if (! name[0] || ! name[1])
1372 mtext_ins_char (ic->preedit, ic->cursor_pos++, name[0], 1);
1374 ic->preedit_changed = 1;
1377 /* If this is the terminal map or we have shifted to another
1378 state, perform branch actions (if any). */
1379 if (! map->submaps || map != ic_info->map)
1381 if (map->branch_actions)
1383 if (take_action_list (ic, map->branch_actions) < 0)
1386 /* If MAP is still not the root map, shift to the current
1388 if (ic_info->map != ic_info->state->map)
1389 shift_state (ic, ic_info->state->name);
1394 /* MAP can not handle KEY. */
1396 /* If MAP is the root map of the initial state, it means that
1397 the current input method can not handle KEY. */
1398 if (map == ((MIMState *) MPLIST_VAL (im_info->states))->map)
1401 if (map != ic_info->state->map)
1403 /* If MAP is not the root map... */
1404 /* If MAP has branch actions, perform them. */
1405 if (map->branch_actions)
1406 take_action_list (ic, map->branch_actions);
1407 /* If MAP is still not the root map, shift to the current
1409 if (ic_info->map != ic_info->state->map)
1411 shift_state (ic, ic_info->state->name);
1412 /* If MAP has branch_actions, perform them. */
1413 if (ic_info->map->branch_actions)
1414 take_action_list (ic, ic_info->map->branch_actions);
1419 /* MAP is the root map, perform branch actions (if any) or
1420 shift to the initial state. */
1421 if (map->branch_actions)
1422 take_action_list (ic, map->branch_actions);
1425 ((MIMState *) MPLIST_VAL (im_info->states))->name);
1432 reset_ic (MInputContext *ic)
1434 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1435 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1437 MLIST_RESET (ic_info);
1438 ic_info->state = (MIMState *) MPLIST_VAL (im_info->states);
1439 ic_info->map = ic_info->state->map;
1440 ic_info->state_key_head = ic_info->key_head = 0;
1441 ic->cursor_pos = ic_info->state_pos = 0;
1442 ic->status = ic_info->state->title;
1444 ic->status = im_info->title;
1445 ic->candidate_list = NULL;
1446 ic->candidate_show = 0;
1447 ic->status_changed = ic->preedit_changed = ic->candidates_changed = 1;
1448 if (ic_info->map->map_actions)
1449 take_action_list (ic, ic_info->map->map_actions);
1453 open_im (MInputMethod *im)
1456 MInputMethodInfo *im_info;
1460 mdb = mdatabase_find (Minput_method, im->language, im->name, Mnil);
1463 plist = mdatabase_load (mdb);
1465 MERROR (MERROR_IM, -1);
1466 MSTRUCT_CALLOC (im_info, MERROR_IM);
1468 result = load_input_method (im->language, im->name, plist, im_info);
1469 M17N_OBJECT_UNREF (plist);
1471 MERROR (MERROR_IM, -1);
1476 close_im (MInputMethod *im)
1478 MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
1482 M17N_OBJECT_UNREF (im_info->title);
1483 if (im_info->states)
1485 MPLIST_DO (plist, im_info->states)
1487 MIMState *state = (MIMState *) MPLIST_VAL (plist);
1490 M17N_OBJECT_UNREF (state->title);
1492 free_map (state->map);
1495 M17N_OBJECT_UNREF (im_info->states);
1498 if (im_info->macros)
1500 MPLIST_DO (plist, im_info->macros)
1501 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
1502 M17N_OBJECT_UNREF (im_info->macros);
1505 if (im_info->externals)
1507 MPLIST_DO (plist, im_info->externals)
1509 MIMExternalModule *external = MPLIST_VAL (plist);
1511 dlclose (external->handle);
1512 M17N_OBJECT_UNREF (external->func_list);
1514 MPLIST_KEY (plist) = Mt;
1516 M17N_OBJECT_UNREF (im_info->externals);
1524 create_ic (MInputContext *ic)
1526 MInputMethod *im = ic->im;
1527 MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
1528 MInputContextInfo *ic_info;
1531 ic_info = (MInputContextInfo *) ic->info;
1534 MSTRUCT_CALLOC (ic_info, MERROR_IM);
1537 MLIST_INIT1 (ic_info, keys, 8);
1538 ic_info->markers = mplist ();
1539 ic_info->vars = mplist ();
1540 ic_info->preedit_saved = mtext ();
1541 if (im_info->externals)
1543 MPlist *func_args = mplist (), *plist;
1545 mplist_add (func_args, Mt, ic);
1546 MPLIST_DO (plist, im_info->externals)
1548 MIMExternalModule *external = MPLIST_VAL (plist);
1549 MIMExternalFunc func
1550 = (MIMExternalFunc) mplist_get (external->func_list, Minit);
1555 M17N_OBJECT_UNREF (func_args);
1562 destroy_ic (MInputContext *ic)
1564 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1565 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1567 if (im_info->externals)
1569 MPlist *func_args = mplist (), *plist;
1571 mplist_add (func_args, Mt, ic);
1572 MPLIST_DO (plist, im_info->externals)
1574 MIMExternalModule *external = MPLIST_VAL (plist);
1575 MIMExternalFunc func
1576 = (MIMExternalFunc) mplist_get (external->func_list, Mfini);
1581 M17N_OBJECT_UNREF (func_args);
1583 MLIST_FREE1 (ic_info, keys);
1584 M17N_OBJECT_UNREF (ic_info->preedit_saved);
1585 M17N_OBJECT_UNREF (ic_info->markers);
1586 M17N_OBJECT_UNREF (ic_info->vars);
1591 /** Handle the input key KEY in the current state and map of IC->info.
1592 If KEY is handled but no text is produced, return 0, otherwise
1598 filter (MInputContext *ic, MSymbol key, void *arg)
1600 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1601 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1604 mtext_reset (ic->produced);
1605 ic->status_changed = ic->preedit_changed = ic->candidates_changed = 0;
1606 MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
1607 ic_info->key_unhandled = 0;
1609 if (handle_key (ic) < 0)
1611 /* KEY was not handled. Reset the status and break the
1614 /* This forces returning 1. */
1615 ic_info->key_unhandled = 1;
1622 ic_info->key_unhandled = 1;
1625 /* Break the loop if all keys were handled. */
1626 } while (ic_info->key_head < ic_info->used);
1628 /* If the current map is the root of the initial state, we should
1629 produce any preedit text in ic->produced. */
1630 if (ic_info->map == ((MIMState *) MPLIST_VAL (im_info->states))->map
1631 && mtext_nchars (ic->preedit) > 0)
1632 shift_state (ic, ((MIMState *) MPLIST_VAL (im_info->states))->name);
1634 if (mtext_nchars (ic->produced) > 0)
1636 MSymbol lang = msymbol_get (ic->im->language, Mlanguage);
1639 mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
1640 Mlanguage, ic->im->language);
1643 return (! ic_info->key_unhandled && mtext_nchars (ic->produced) == 0);
1647 /** Return 1 if the last event or key was not handled, otherwise
1650 There is no need of looking up because ic->produced should already
1651 contain the produced text (if any).
1656 lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
1658 mtext_cat (mt, ic->produced);
1659 mtext_reset (ic->produced);
1660 return (((MInputContextInfo *) ic->info)->key_unhandled ? -1 : 0);
1663 /* Support functions for mdebug_dump_im. */
1666 dump_im_map (MPlist *map_list, int indent)
1669 MSymbol key = MPLIST_KEY (map_list);
1670 MIMMap *map = (MIMMap *) MPLIST_VAL (map_list);
1672 prefix = (char *) alloca (indent + 1);
1673 memset (prefix, 32, indent);
1674 prefix[indent] = '\0';
1676 fprintf (stderr, "(\"%s\" ", msymbol_name (key));
1677 if (map->map_actions)
1678 mdebug_dump_plist (map->map_actions, indent + 2);
1681 MPLIST_DO (map_list, map->submaps)
1683 fprintf (stderr, "\n%s ", prefix);
1684 dump_im_map (map_list, indent + 2);
1687 if (map->branch_actions)
1689 fprintf (stderr, "\n%s (branch\n%s ", prefix, prefix);
1690 mdebug_dump_plist (map->branch_actions, indent + 4);
1691 fprintf (stderr, ")");
1693 fprintf (stderr, ")");
1698 dump_im_state (MIMState *state, int indent)
1703 prefix = (char *) alloca (indent + 1);
1704 memset (prefix, 32, indent);
1705 prefix[indent] = '\0';
1707 fprintf (stderr, "(%s", msymbol_name (state->name));
1708 if (state->map->submaps)
1710 MPLIST_DO (map_list, state->map->submaps)
1712 fprintf (stderr, "\n%s ", prefix);
1713 dump_im_map (map_list, indent + 2);
1716 fprintf (stderr, ")");
1725 = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1726 "BackSpace", "Tab", "Linefeed", "Clear", NULL, "Return", NULL, NULL,
1727 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1728 NULL, NULL, NULL, "Escape", NULL, NULL, NULL, NULL };
1729 char buf[6], buf2[256];
1732 Minput_method = msymbol ("input-method");
1733 Minput_driver = msymbol ("input-driver");
1734 Mtitle = msymbol ("title");
1735 Mmacro = msymbol ("macro");
1736 Mmodule = msymbol ("module");
1737 Mmap = msymbol ("map");
1738 Mstate = msymbol ("state");
1739 Minsert = msymbol ("insert");
1740 Mdelete = msymbol ("delete");
1741 Mmove = msymbol ("move");
1742 Mmark = msymbol ("mark");
1743 Mpushback = msymbol ("pushback");
1744 Mundo = msymbol ("undo");
1745 Mcall = msymbol ("call");
1746 Mshift = msymbol ("shift");
1747 Mselect = msymbol ("select");
1748 Mshow = msymbol ("show");
1749 Mhide = msymbol ("hide");
1750 Mset = msymbol ("set");
1751 Madd = msymbol ("add");
1752 Msub = msymbol ("sub");
1753 Mmul = msymbol ("mul");
1754 Mdiv = msymbol ("div");
1755 Mequal = msymbol ("=");
1756 Mless = msymbol ("<");
1757 Mgreater = msymbol (">");
1759 Minput_preedit_start = msymbol ("input-preedit-start");
1760 Minput_preedit_done = msymbol ("input-preedit-done");
1761 Minput_preedit_draw = msymbol ("input-preedit-draw");
1762 Minput_status_start = msymbol ("input-status-start");
1763 Minput_status_done = msymbol ("input-status-done");
1764 Minput_status_draw = msymbol ("input-status-draw");
1765 Minput_candidates_start = msymbol ("input-candidates-start");
1766 Minput_candidates_done = msymbol ("input-candidates-done");
1767 Minput_candidates_draw = msymbol ("input-candidates-draw");
1768 Minput_set_spot = msymbol ("input-set-spot");
1769 Minput_toggle = msymbol ("input-toggle");
1771 Mcandidate_list = msymbol_as_managing_key (" candidate-list");
1772 Mcandidate_index = msymbol (" candidate-index");
1774 Minit = msymbol ("init");
1775 Mfini = msymbol ("fini");
1780 for (i = 0, buf[2] = '@'; i < ' '; i++, buf[2]++)
1783 one_char_symbol[i] = msymbol (key_names[i]);
1785 one_char_symbol[i] = msymbol (buf);
1787 for (buf[2] = i; i < 127; i++, buf[2]++)
1788 one_char_symbol[i] = msymbol (buf + 2);
1789 one_char_symbol[i++] = msymbol ("Delete");
1795 for (buf[4] = '@'; i < 160; i++, buf[4]++)
1797 if (key_names[i - 128])
1799 strcpy (buf2 + 2, key_names[i - 128]);
1800 one_char_symbol[i] = msymbol (buf2);
1803 one_char_symbol[i] = msymbol (buf);
1805 for (buf[4] = i - 128; i < 255; i++, buf[2]++)
1806 one_char_symbol[i] = msymbol (buf + 2);
1807 one_char_symbol[i] = msymbol ("M-Delete");
1809 minput_default_driver.open_im = open_im;
1810 minput_default_driver.close_im = close_im;
1811 minput_default_driver.create_ic = create_ic;
1812 minput_default_driver.destroy_ic = destroy_ic;
1813 minput_default_driver.filter = filter;
1814 minput_default_driver.lookup = lookup;
1815 minput_default_driver.callback_list = NULL;
1816 minput_driver = &minput_default_driver;
1823 if (minput_default_driver.callback_list)
1825 M17N_OBJECT_UNREF (minput_default_driver.callback_list);
1826 minput_default_driver.callback_list = NULL;
1828 if (minput_driver->callback_list)
1830 M17N_OBJECT_UNREF (minput_driver->callback_list);
1831 minput_driver->callback_list = NULL;
1836 minput__callback (MInputContext *ic, MSymbol command)
1838 if (ic->im->driver.callback_list)
1840 MInputCallbackFunc func
1841 = (MInputCallbackFunc) mplist_get (ic->im->driver.callback_list,
1845 (func) (ic, command);
1850 minput__char_to_key (int c)
1852 if (c < 0 || c >= 0x100)
1855 return one_char_symbol[c];
1859 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1864 /*** @addtogroup m17nInputMethod */
1869 @name Variables: Predefined symbols for callback commands.
1871 These are the predefined symbols that are used as the @c COMMAND
1872 argument of callback functions of an input method driver (see
1873 #MInputDriver::callback_list). */
1877 MSymbol Minput_preedit_start;
1878 MSymbol Minput_preedit_done;
1879 MSymbol Minput_preedit_draw;
1880 MSymbol Minput_status_start;
1881 MSymbol Minput_status_done;
1882 MSymbol Minput_status_draw;
1883 MSymbol Minput_candidates_start;
1884 MSymbol Minput_candidates_done;
1885 MSymbol Minput_candidates_draw;
1886 MSymbol Minput_set_spot;
1887 MSymbol Minput_toggle;
1892 @brief The default input driver for internal input methods.
1894 The variable #minput_default_driver is the default driver for
1895 internal input methods.
1897 The member MInputDriver::open_im () searches the m17n database for
1898 an input method that matches the tag \<#Minput_method, $LANGUAGE,
1899 $NAME\> and loads it.
1901 The member MInputDriver::callback_list () is @c NULL. Thus, it is
1902 programmers responsibility to set it to a plist of proper callback
1903 functions. Otherwise, no feedback information (e.g. preedit text)
1904 can be shown to users.
1906 The macro M17N_INIT () sets the variable #minput_driver to the
1907 pointer to this driver so that all internal input methods use it.
1909 Therefore, unless @c minput_driver is set differently, the driver
1910 dependent arguments $ARG of the functions whose name begin with
1911 "minput_" are all ignored. */
1914 @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥǥե©¥ë¥ÈÆþÎϥɥ饤¥Ð
1916 ÆþÎϥɥ饤¥Ð minput_default_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѤΥǥե©¥ë
1917 ¥È¤ÎÆþÎϥɥ饤¥Ð¤Ç¤¢¤ë¡£
1919 ¤³¤Î¥É¥é¥¤¥Ð¤Î <callback> ¥á¥ó¥Ð¤Ï @c NULL ¤Ê¤Î¤Ç¡¢¥×¥í¥°¥é¥Þ¦¤Ç
1920 ÀÕǤ¤ò»ý¤Ã¤Æ, ŬÀڤʥ³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ËÀßÄꤷ¡¢Preedit ¥Æ¥¥¹¥È,
1921 Status ¥Æ¥¥¹¥È¤¬¥æ¡¼¥¶¤Ëɽ¼¨¤Ç¤¤ë¤è¤¦¤Ë¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
1923 ´Ø¿ô M17N_INIT () ¤ÏÊÑ¿ô @c minput_driver ¤ò¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó
1924 ¥¿¤ËÀßÄꤷ¡¢Á´¤Æ¤ÎÆâÉôÆþÎϥ᥽¥Ã¥É¤¬¤³¤Î¥É¥é¥¤¥Ð¤ò»È¤¦¤è¤¦¤Ë¤¹¤ë¡£
1926 ¤·¤¿¤¬¤Ã¤Æ¡¢@c minput_driver ¤¬¥Ç¥Õ¥©¥ë¥ÈÃͤΤޤޤǤ¢¤ì¤Ð¡¢minput_
1927 ¤Ç»Ï¤Þ¤ë°Ê²¼¤Î´Ø¿ô·²¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô $ARG ¤Ï¤É¤ì¤â̵»ë¤µ¤ì
1930 MInputDriver minput_default_driver;
1934 @brief The input driver for internal input methods.
1936 The variable #minput_driver is a pointer to the input method
1937 driver that is used by internal input methods. The macro
1938 M17N_INIT () initializes it to a pointer to #minput_default_driver
1939 (if <m17n.h> is included) or to #minput_gui_driver (if
1940 <m17n-gui.h> is included). */
1942 MInputDriver *minput_driver;
1944 MSymbol Minput_driver;
1949 @brief Open an input method.
1951 The minput_open_im () function opens an input method that matches
1952 language $LANGUAGE and name $NAME, and returns a pointer to the
1953 input method object newly allocated.
1955 This function at first decides an input driver for the input
1958 If $LANGUAGE is not #Mnil, an input driver pointed by the variable
1959 #minput_driver is used.
1961 If $LANGUAGE is #Mnil and $NAME has #Minput_driver property, the
1962 input driver pointed to by the property value is used to open the
1963 input method. If $NAME has no such property, @c NULL is returned.
1965 Then, the member MInputDriver::open_im () of the input driver is
1968 $ARG is set in the member @c arg of the structure MInputMethod so
1969 that the input driver can refer to it. */
1972 @brief ÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë
1974 ´Ø¿ô mim_open () ¤Ï¸À¸ì $LANGUAGE ¤È̾Á° $NAME ¤ËŬ¹ç¤¹¤ëÆþÎϥ᥽¥Ã
1975 ¥É¤ò¥ª¡¼¥×¥ó¤·¡¢¤½¤Î¿·¤¿¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
1977 $LANGUAGE ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢m17n ¸À¸ì¾ðÊó¥Ù¡¼¥¹Ã椫¤é \<@c
1978 Minput_method, $LANGUAGE, $NAME \> ¤È¤¤¤¦¥¿¥°¤ËŬ¹ç¤¹¤ëÆþÎϥ᥽¥Ã
1979 ¥É¤òõ¤¹¡£¸«¤Ä¤«¤Ã¤¿¾ì¹ç¤Ï¡¢ÊÑ¿ô #minput_driver ¤Ç¥Ý¥¤¥ó¥È¤µ¤ì¤Æ
1980 ¤¤¤ëÆþÎϥɥ饤¥Ð¤òÍѤ¤¤Æ¤½¤ÎÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë¡£¸«¤Ä¤«¤é¤Ê
1981 ¤¤¾ì¹ç¤ä¥ª¡¼¥×¥ó¤Ç¤¤Ê¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï @c NULL ¤òÊÖ¤¹¡£
1983 ÊÑ¿ô #minput_driver ¤Ï¡¢#minput_default_driver ¤« @c
1984 minput_gui_driver ¤Î¤É¤Á¤é¤«¤ò¥Ý¥¤¥ó¥È¤·¤Æ¤¤¤ë¡£Á°¼Ô¤Ï CUI ÍѤǤ¢
1985 ¤ê¡¢´Ø¿ôm17n_initialize () ¤ò¸Æ¤Ö¤³¤È¤Ë¤è¤Ã¤Æ #minput_driver ¤¬
1986 #minput_default_driver ¤ò¥Ý¥¤¥ó¥È¤¹¤ë¤è¤¦¤Ë¤Ê¤ë¡£¸å¼Ô¤Ï GUI ÍѤÇ
1987 ¤¢¤ê¡¢´Ø¿ô m17n_initialize_win () ¤Ë¤è¤Ã¤Æ¥Ý¥¤¥ó¥È¤µ¤ì¤ë¡£¾ÜºÙ¤Ë¤Ä
1988 ¤¤¤Æ¤Ï¤³¤ì¤é¤ÎÊÑ¿ô¤Î¥É¥¥å¥á¥ó¥È¤ò»²¾È¤Î¤³¤È¡£
1990 $LANGUAGE ¤¬ #Mnil ¤Ç¤¢¤ê¡¢$NAME ¤¬ #Minput_driver ¤ò¥¡¼¤È¤¹
1991 ¤ë¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä¾ì¹ç¤Ë¤Ï¡¢¤½¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤǥݥ¤¥ó¥È¤µ¤ì¤Æ¤¤¤ë
1992 ÆþÎϥɥ饤¥Ð¤òÍѤ¤¤ÆÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë¡£$NAME ¤Ë¤½¤Î¤è¤¦¤Ê
1993 ¥×¥í¥Ñ¥Æ¥£¤¬Ìµ¤«¤Ã¤¿¾ì¹ç¤ä¥ª¡¼¥×¥ó¤Ç¤¤Ê¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï @c NULL ¤ò
1996 $ARG ¤Ï¡¢ÆþÎϥɥ饤¥Ð¤¬»²¾È¤Ç¤¤ë¤è¤¦¤Ë¡¢¹½Â¤ÂÎ MInputMethod ¤Î¥á
1997 ¥ó¥Ð @c arg ¤Ë¥»¥Ã¥È¤µ¤ì¤ë¡£
1999 @latexonly \IPAlabel{minput_open} @endlatexonly
2004 minput_open_im (MSymbol language, MSymbol name, void *arg)
2007 MInputDriver *driver;
2010 driver = minput_driver;
2013 driver = (MInputDriver *) msymbol_get (name, Minput_driver);
2015 MERROR (MERROR_IM, NULL);
2018 MSTRUCT_CALLOC (im, MERROR_IM);
2019 im->language = language;
2022 im->driver = *driver;
2023 if ((*im->driver.open_im) (im) < 0)
2034 @brief Close an input method.
2036 The minput_close_im () function closes the input method $IM, which
2037 must have been created by minput_open_im (). */
2040 @brief ÆþÎϥ᥽¥Ã¥É¤ò¥¯¥í¡¼¥º¤¹¤ë
2042 ´Ø¿ô minput_close_im () ¤Ï¡¢ÆþÎϥ᥽¥Ã¥É $IM ¤ò¥¯¥í¡¼¥º¤¹¤ë¡£¤³¤Î
2043 ÆþÎϥ᥽¥Ã¥É $IM ¤Ï minput_open_im () ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê¤±¤ì
2047 minput_close_im (MInputMethod *im)
2049 (*im->driver.close_im) (im);
2056 @brief Create an input context.
2058 The minput_create_ic () function creates an input context object
2059 associated with input method $IM, and calls callback functions
2060 corresponding to #Minput_preedit_start, #Minput_status_start, and
2061 #Minput_status_draw in this order.
2065 If an input context is successfully created, minput_create_ic ()
2066 returns a pointer to it. Otherwise it returns @c NULL. */
2069 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÀ¸À®¤¹¤ë
2071 ´Ø¿ô minput_create_ic () ¤ÏÆþÎϥ᥽¥Ã¥É $IM ¤ËÂбþ¤¹¤ëÆþÎÏ¥³¥ó¥Æ¥¯
2072 ¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤¹¤ë¡£
2075 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢minput_create_ic () ¤ÏÀ¸À®¤·¤¿ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È
2076 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¼ºÇÔ¤·¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£ */
2079 minput_create_ic (MInputMethod *im, void *arg)
2083 MSTRUCT_CALLOC (ic, MERROR_IM);
2086 ic->preedit = mtext ();
2087 ic->candidate_list = NULL;
2088 ic->produced = mtext ();
2089 ic->spot.x = ic->spot.y = 0;
2091 ic->plist = mplist ();
2092 if ((*im->driver.create_ic) (ic) < 0)
2094 M17N_OBJECT_UNREF (ic->preedit);
2095 M17N_OBJECT_UNREF (ic->produced);
2096 M17N_OBJECT_UNREF (ic->plist);
2101 if (im->driver.callback_list)
2103 minput__callback (ic, Minput_preedit_start);
2104 minput__callback (ic, Minput_status_start);
2105 minput__callback (ic, Minput_status_draw);
2114 @brief Destroy an input context.
2116 The minput_destroy_ic () function destroys the input context $IC,
2117 which must have been created by minput_create_ic (). It calls
2118 callback functions corresponding to #Minput_preedit_done,
2119 #Minput_status_done, and #Mcandidate_done in this order. */
2122 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÇ˲õ¤¹¤ë
2124 ´Ø¿ô minput_destroy_ic () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤òÇ˲õ¤¹¤ë¡£¤³
2125 ¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ï minput_create_ic () ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê
2129 minput_destroy_ic (MInputContext *ic)
2131 if (ic->im->driver.callback_list)
2133 minput__callback (ic, Minput_preedit_done);
2134 minput__callback (ic, Minput_status_done);
2135 minput__callback (ic, Minput_candidates_done);
2137 (*ic->im->driver.destroy_ic) (ic);
2138 M17N_OBJECT_UNREF (ic->preedit);
2139 M17N_OBJECT_UNREF (ic->produced);
2140 M17N_OBJECT_UNREF (ic->plist);
2147 @brief Filter an input key.
2149 The minput_filter () function filters input key $KEY according to
2150 input context $IC, and calls callback functions corresponding to
2151 #Minput_preedit_draw, #Minput_status_draw, and #Mcandidate_draw if
2152 the preedit text, the status, and the current candidate are
2153 changed respectively.
2156 If $KEY is filtered out, this function returns 1. In that case,
2157 the caller should discard the key. Otherwise, it returns 0, and
2158 the caller should handle the key, for instance, by calling the
2159 function minput_lookup () with the same $KEY. */
2162 @brief ÆþÎÏ¥¡¼¤Î¥Õ¥£¥ë¥¿¥ê¥ó¥°¤ò¤¹¤ë
2164 ´Ø¿ô minput_filter () ¤ÏÆþÎÏ¥¡¼ $KEY ¤òÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤Ë±þ
2165 ¤¸¤Æ¥Õ¥£¥ë¥¿¥ê¥ó¥°¤¹¤ë¡£
2167 ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤ÎÆþÎϥ᥽¥Ã¥É¤¬ÆþÎÏ¥¡¼¤ò¥Õ¥£¥ë¥¿¤¹¤ì¤Ð¡¢¤³
2168 ¤Î´Ø¿ô¤Ï 1 ¤òÊÖ¤¹¡£¤³¤Î¾ì¹ç¸Æ¤Ó½Ð¤·Â¦¤Ï¤³¤Î¥¡¼¤ò¼Î¤Æ¤ë¤Ù¤¤Ç¤¢¤ë¡£
2169 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0 ¤òÊÖ¤·¡¢¸Æ¤Ó½Ð¤·Â¦¤¬¡¢¤¿¤È¤¨¤ÐƱ¤¸ $KEY ¤Ç´Ø¿ô
2170 minput_lookup () ¤ò¸Æ¤Ö¤Ê¤É¤·¤Æ¡¢¤³¤Î¥¡¼¤ò½èÍý¤¹¤ë¡£
2172 @latexonly \IPAlabel{minput_filter} @endlatexonly
2176 minput_filter (MInputContext *ic, MSymbol key, void *arg)
2183 ret = (*ic->im->driver.filter) (ic, key, arg);
2185 if (ic->im->driver.callback_list)
2187 if (ic->preedit_changed)
2188 minput__callback (ic, Minput_preedit_draw);
2189 if (ic->status_changed)
2190 minput__callback (ic, Minput_status_draw);
2191 if (ic->candidates_changed)
2192 minput__callback (ic, Minput_candidates_draw);
2193 ic->preedit_changed = ic->status_changed = ic->candidates_changed = 0;
2202 @brief Lookup a text produced in the input context.
2204 The minput_lookup () function looks up a text in the input context
2205 $IC. $KEY must be the same one provided to the previous call of
2208 If a text was produced by the input method, it is concatenated
2211 This function calls #MInputDriver::lookup.
2214 If $KEY was correctly handled by the input method, this function
2215 returns 0. Otherwise, returns -1, even in that case, some text
2216 may be produced in $MT. */
2219 @brief ÆþÎϥ᥽¥Ã¥É¤¬ºî¤Ã¤¿¥Æ¥¥¹¥È¤Î³ÍÆÀ
2221 ´Ø¿ô minput_lookup () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC Ãæ¤Î¥Æ¥¥¹¥È¤ò³ÍÆÀ¤¹
2222 ¤ë¡£$KEY ¤Ï´Ø¿ôminput_filter () ¤Ø¤ÎľÁ°¤Î¸Æ¤Ó½Ð¤·¤ËÍѤ¤¤é¤ì¤¿¤â¤Î
2223 ¤ÈƱ¤¸¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2225 ¥Æ¥¥¹¥È¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆÀ¸À®¤µ¤ì¤Æ¤¤¤ì¤Ð¡¢$IC->produced ¤ËÊÝ
2228 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Î <tt>XLookupString ()</tt> ¡¢
2229 <tt>XmbLookupString ()</tt> ¡¢<tt>XwcLookupString ()</tt> ¤ËÂбþ¤¹
2233 $KEY ¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆŬÀڤ˽èÍý¤Ç¤¤Æ¤¤¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 0 ¤ò
2234 ÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤·¡¢¤³¤Î¾ì¹ç¤Ç¤â$IC->produced ¤Ë²¿¤é¤«
2235 ¤Î¥Æ¥¥¹¥È¤¬À¸À®¤µ¤ì¤Æ¤¤¤ë¤³¤È¤¬¤¢¤ë¡£
2237 @latexonly \IPAlabel{minput_lookup} @endlatexonly */
2240 minput_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2242 return (ic ? (*ic->im->driver.lookup) (ic, key, arg, mt) : -1);
2247 @brief Set the spot of the input context.
2249 The minput_set_spot () function set the spot of input context $IC
2250 to coordinate ($X, $Y) with the height $ASCENT and $DESCENT.
2251 $FONTSIZE specfies the fontsize of a preedit text in 1/10 point.
2252 The semantics of these values depend on the input driver.
2254 For instance, an input driver designed to work in CUI environment
2255 may use $X and $Y as column and row numbers, and ignore $ASCENT
2256 and $DESCENT. An input driver designed to work on a window system
2257 may treat $X and $Y as pixel offsets relative to the origin of the
2258 client window, and treat $ASCENT and $DESCENT as ascent and
2259 descent pixels of a line at ($X . $Y).
2261 $MT and $POS is an M-text and a character position at the spot.
2262 $MT may be NULL, in which case, the input method can't get
2263 information about the text around the spot. */
2266 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Î¥¹¥Ý¥Ã¥È¤òÀßÄꤹ¤ë
2268 ´Ø¿ô minput_set_spot () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤Î¥¹¥Ý¥Ã¥È¤ò¡¢ºÂ
2269 ɸ ($X, $Y)¤Ë ¡¢¹â¤µ $ASCENT¡¢$DESCENT ¤ÇÀßÄꤹ¤ë¡£¤³¤ì¤é¤ÎÃͤΰÕ
2270 Ì£¤ÏÆþÎϥɥ饤¥Ð¤Ë°Í¸¤¹¤ë¡£
2272 ¤¿¤È¤¨¤Ð CUI ´Ä¶¤ÇÆ°ºî¤¹¤ëÆþÎϥɥ饤¥Ð¤Ï $X, $Y ¤ò¤½¤ì¤¾¤ìÎó¤È¹Ô
2273 ¤ÎÈÖ¹æ¤È¤·¤ÆÍѤ¤¡¢$ASCENT¡¢$DESCENT ¤ò̵»ë¤¹¤ë¤«¤â¤·¤ì¤Ê¤¤¡£ ¤Þ¤¿
2274 ¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥àÍѤÎÆþÎϥɥ饤¥Ð¤Ï $X,$Y ¤ò¥¯¥é¥¤¥¢¥ó¥È¥¦¥£¥ó¥É
2275 ¥¦¤Î¸¶ÅÀ¤«¤é¤Î¥ª¥Õ¥»¥Ã¥È¤ò¥Ô¥¯¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¤¡¢
2276 $ASCENT ¤È $DESCENT ¤ò ($X . $Y) ¤ÎÎó¤Î¥¢¥»¥ó¥È¤È¥Ç¥£¥»¥ó¥È¤ò¥Ô¥¯
2277 ¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¦¤«¤â¤·¤ì¤Ê¤¤¡£ */
2280 minput_set_spot (MInputContext *ic, int x, int y,
2281 int ascent, int descent, int fontsize,
2286 ic->spot.ascent = ascent;
2287 ic->spot.descent = descent;
2288 ic->spot.fontsize = fontsize;
2291 if (ic->im->driver.callback_list)
2292 minput__callback (ic, Minput_set_spot);
2297 @brief Toggle input method.
2299 The minput_toggle () function toggles the input method associated
2300 with the input context $IC. */
2303 minput_toggle (MInputContext *ic)
2305 if (ic->im->driver.callback_list)
2306 minput__callback (ic, Minput_toggle);
2307 ic->active = ! ic->active;
2313 /*** @addtogroup m17nDebug */
2319 @brief Dump an input method
2321 The mdebug_dump_im () function prints the input method $IM in a
2322 human readable way to the stderr. $INDENT specifies how many
2323 columns to indent the lines but the first one.
2326 This function returns $IM. */
2329 mdebug_dump_im (MInputMethod *im, int indent)
2331 MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
2334 prefix = (char *) alloca (indent + 1);
2335 memset (prefix, 32, indent);
2336 prefix[indent] = '\0';
2338 fprintf (stderr, "(input-method %s %s ", msymbol_name (im->language),
2339 msymbol_name (im->name));
2340 mdebug_dump_mtext (im_info->title, 0, 0);
2341 if (im->name != Mnil)
2345 MPLIST_DO (state, im_info->states)
2347 fprintf (stderr, "\n%s ", prefix);
2348 dump_im_state (MPLIST_VAL (state), indent + 2);
2351 fprintf (stderr, ")");