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);
742 im_info->title = title;
743 im_info->externals = externals;
744 im_info->macros = macros;
745 im_info->states = states;
751 MPLIST_DO (elt, maps)
752 M17N_OBJECT_UNREF (MPLIST_VAL (elt));
753 M17N_OBJECT_UNREF (maps);
756 M17N_OBJECT_UNREF (title);
759 MPLIST_DO (plist, states)
761 MIMState *state = (MIMState *) MPLIST_VAL (plist);
764 M17N_OBJECT_UNREF (state->title);
766 free_map (state->map);
769 M17N_OBJECT_UNREF (states);
773 MPLIST_DO (plist, externals)
775 MIMExternalModule *external = MPLIST_VAL (plist);
777 dlclose (external->handle);
778 M17N_OBJECT_UNREF (external->func_list);
780 MPLIST_KEY (plist) = Mt;
782 M17N_OBJECT_UNREF (externals);
789 static int take_action_list (MInputContext *ic, MPlist *action_list);
792 shift_state (MInputContext *ic, MSymbol state_name)
794 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
795 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
796 MIMState *state = ic_info->state;
798 /* Find a state to shift to. If not found, shift to the initial
800 state = (MIMState *) mplist_get (im_info->states, state_name);
802 state = (MIMState *) MPLIST_VAL (im_info->states);
804 /* Enter the new state. */
805 ic_info->state = state;
806 ic_info->map = state->map;
807 ic_info->state_key_head = ic_info->key_head;
808 if (state == (MIMState *) MPLIST_VAL (im_info->states))
810 /* We have shifted to the initial state. */
813 mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit),
814 Mcandidate_list, NULL, 0);
815 mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit),
816 Mcandidate_index, NULL, 0);
817 mtext_cat (ic->produced, ic->preedit);
818 mtext_reset (ic->preedit);
819 ic->candidate_list = NULL;
820 ic->candidate_show = 0;
821 ic->preedit_changed = ic->candidates_changed = 1;
822 MPLIST_DO (p, ic_info->markers)
824 MPLIST_DO (p, ic_info->vars)
827 memmove (ic_info->keys, ic_info->keys + ic_info->state_key_head,
828 sizeof (int) * (ic_info->used - ic_info->state_key_head));
829 ic_info->used -= ic_info->state_key_head;
830 ic_info->state_key_head = ic_info->key_head = 0;
832 mtext_cpy (ic_info->preedit_saved, ic->preedit);
833 ic_info->state_pos = ic->cursor_pos;
834 ic->status = state->title;
836 ic->status = im_info->title;
837 ic->status_changed = 1;
838 if (ic_info->key_head == ic_info->used
839 && ic_info->map == ic_info->state->map
840 && ic_info->map->map_actions)
841 take_action_list (ic, ic_info->map->map_actions);
846 find_candidates_group (MPlist *plist, int index,
847 int *start_index, int *end_index, int *group_index)
849 int i = 0, gidx = 0, len;
851 MPLIST_DO (plist, plist)
853 if (MPLIST_MTEXT_P (plist))
854 len = mtext_nchars (MPLIST_MTEXT (plist));
856 len = mplist_length (MPLIST_PLIST (plist));
862 *end_index = i + len;
874 preedit_insert (MInputContext *ic, int pos, MText *mt, int c)
876 MInputContextInfo *ic_info = ((MInputContext *) ic)->info;
878 int nchars = mt ? mtext_nchars (mt) : 1;
881 mtext_ins (ic->preedit, pos, mt);
883 mtext_ins_char (ic->preedit, pos, c, 1);
884 MPLIST_DO (markers, ic_info->markers)
885 if (MPLIST_INTEGER (markers) > pos)
886 MPLIST_VAL (markers) = (void *) (MPLIST_INTEGER (markers) + nchars);
887 if (ic->cursor_pos >= pos)
888 ic->cursor_pos += nchars;
889 ic->preedit_changed = 1;
894 preedit_delete (MInputContext *ic, int from, int to)
896 MInputContextInfo *ic_info = ((MInputContext *) ic)->info;
899 mtext_del (ic->preedit, from, to);
900 MPLIST_DO (markers, ic_info->markers)
902 if (MPLIST_INTEGER (markers) > to)
904 = (void *) (MPLIST_INTEGER (markers) - (to - from));
905 else if (MPLIST_INTEGER (markers) > from);
906 MPLIST_VAL (markers) = (void *) from;
908 if (ic->cursor_pos >= to)
909 ic->cursor_pos -= to - from;
910 else if (ic->cursor_pos > from)
911 ic->cursor_pos = from;
912 ic->preedit_changed = 1;
917 new_index (MInputContext *ic, int current, int limit, MSymbol sym, MText *mt)
919 int code = marker_code (sym);
921 if (mt && (code == '[' || code == ']'))
925 if (code == '[' && current > 0)
927 if (mtext_prop_range (mt, Mcandidate_list, pos - 1, &pos, NULL, 1)
931 else if (code == ']' && current < mtext_nchars (mt))
933 if (mtext_prop_range (mt, Mcandidate_list, pos, NULL, &pos, 1))
939 return (code == '<' ? 0
940 : code == '>' ? limit
941 : code == '-' ? current - 1
942 : code == '+' ? current + 1
943 : code == '=' ? current
944 : code - '0' > limit ? limit
948 return (int) mplist_get (((MInputContextInfo *) ic->info)->markers, sym);
952 udpate_candidate (MInputContext *ic, MTextProperty *prop, int idx)
954 int from = mtext_property_start (prop);
955 int to = mtext_property_end (prop);
957 MPlist *candidate_list = mtext_property_value (prop);
958 MPlist *group = find_candidates_group (candidate_list, idx, &start,
960 int ingroup_index = idx - start;
963 preedit_delete (ic, from, to);
964 if (MPLIST_MTEXT_P (group))
966 mt = MPLIST_MTEXT (group);
967 preedit_insert (ic, from, NULL, mtext_ref_char (mt, ingroup_index));
975 for (i = 0, plist = MPLIST_PLIST (group); i < ingroup_index;
976 i++, plist = MPLIST_NEXT (plist));
977 mt = MPLIST_MTEXT (plist);
978 preedit_insert (ic, from, mt, 0);
979 to = from + mtext_nchars (mt);
981 mtext_put_prop (ic->preedit, from, to, Mcandidate_list, candidate_list);
982 mtext_put_prop (ic->preedit, from, to, Mcandidate_index, (void *) idx);
988 take_action_list (MInputContext *ic, MPlist *action_list)
990 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
991 MPlist *candidate_list = ic->candidate_list;
992 int candidate_index = ic->candidate_index;
993 int candidate_show = ic->candidate_show;
996 MPLIST_DO (action_list, action_list)
1002 if (MPLIST_MTEXT_P (action_list)
1003 || MPLIST_INTEGER_P (action_list))
1004 name = Minsert, args = action_list;
1005 else if (MPLIST_PLIST_P (action_list)
1006 && (MPLIST_MTEXT_P (MPLIST_PLIST (action_list))
1007 || MPLIST_PLIST_P (MPLIST_PLIST (action_list))))
1008 name = Minsert, args = action_list;
1011 action = MPLIST_PLIST (action_list);
1012 name = MPLIST_SYMBOL (action);
1013 args = MPLIST_NEXT (action);
1016 if (name == Minsert)
1018 if (MPLIST_MTEXT_P (args))
1019 preedit_insert (ic, ic->cursor_pos, MPLIST_MTEXT (args), 0);
1020 else if (MPLIST_INTEGER_P (args))
1021 preedit_insert (ic, ic->cursor_pos, NULL, MPLIST_INTEGER (args));
1022 else if (MPLIST_SYMBOL_P (args))
1024 int c = integer_value (ic, args);
1026 if (c >= 0 && c <= MCHAR_MAX)
1027 preedit_insert (ic, ic->cursor_pos, NULL, c);
1034 args = MPLIST_PLIST (args);
1035 if (MPLIST_MTEXT_P (args))
1037 preedit_insert (ic, ic->cursor_pos, NULL,
1038 mtext_ref_char (MPLIST_MTEXT (args), 0));
1043 mt = MPLIST_MTEXT (MPLIST_PLIST (args));
1044 preedit_insert (ic, ic->cursor_pos, mt, 0);
1045 len = mtext_nchars (mt);
1047 mtext_put_prop (ic->preedit,
1048 ic->cursor_pos - len, ic->cursor_pos,
1049 Mcandidate_list, args);
1050 mtext_put_prop (ic->preedit,
1051 ic->cursor_pos - len, ic->cursor_pos,
1052 Mcandidate_index, (void *) 0);
1055 else if (name == Mselect)
1058 int code, idx, gindex;
1059 int pos = ic->cursor_pos;
1063 || ! (prop = mtext_get_property (ic->preedit, pos - 1,
1066 if (MPLIST_SYMBOL_P (args))
1068 code = marker_code (MPLIST_SYMBOL (args));
1074 idx = (int) mtext_get_prop (ic->preedit, pos - 1, Mcandidate_index);
1075 group = find_candidates_group (mtext_property_value (prop), idx,
1076 &start, &end, &gindex);
1078 if (code != '[' && code != ']')
1082 ? new_index (NULL, ic->candidate_index - start,
1083 end - start - 1, MPLIST_SYMBOL (args),
1085 : MPLIST_INTEGER (args)));
1088 && MPLIST_TAIL_P (MPLIST_NEXT (group))))
1093 int ingroup_index = idx - start;
1096 group = mtext_property_value (prop);
1097 len = mplist_length (group);
1110 for (idx = 0; gindex > 0; gindex--, group = MPLIST_NEXT (group))
1111 idx += (MPLIST_MTEXT_P (group)
1112 ? mtext_nchars (MPLIST_MTEXT (group))
1113 : mplist_length (MPLIST_PLIST (group)));
1114 len = (MPLIST_MTEXT_P (group)
1115 ? mtext_nchars (MPLIST_MTEXT (group))
1116 : mplist_length (MPLIST_PLIST (group)));
1117 if (ingroup_index >= len)
1118 ingroup_index = len - 1;
1119 idx += ingroup_index;
1121 udpate_candidate (ic, prop, idx);
1123 else if (name == Mshow)
1124 ic->candidate_show = 1;
1125 else if (name == Mhide)
1126 ic->candidate_show = 0;
1127 else if (name == Mdelete)
1129 int len = mtext_nchars (ic->preedit);
1130 int to = (MPLIST_SYMBOL_P (args)
1131 ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
1133 : MPLIST_INTEGER (args));
1139 if (to < ic->cursor_pos)
1140 preedit_delete (ic, to, ic->cursor_pos);
1141 else if (to > ic->cursor_pos)
1142 preedit_delete (ic, ic->cursor_pos, to);
1144 else if (name == Mmove)
1146 int len = mtext_nchars (ic->preedit);
1148 = (MPLIST_SYMBOL_P (args)
1149 ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
1151 : MPLIST_INTEGER (args));
1157 if (pos != ic->cursor_pos)
1159 ic->cursor_pos = pos;
1160 ic->preedit_changed = 1;
1163 else if (name == Mmark)
1165 int code = marker_code (MPLIST_SYMBOL (args));
1168 mplist_put (ic_info->markers, MPLIST_SYMBOL (args),
1169 (void *) ic->cursor_pos);
1171 else if (name == Mpushback)
1173 int num = MPLIST_INTEGER (args);
1176 ic_info->key_head -= num;
1178 ic_info->key_head = num;
1179 if (ic_info->key_head > ic_info->used)
1180 ic_info->key_head = ic_info->used;
1182 else if (name == Mcall)
1184 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1185 MIMExternalFunc func = NULL;
1186 MSymbol module, func_name;
1187 MPlist *func_args, *val;
1190 module = MPLIST_SYMBOL (args);
1191 args = MPLIST_NEXT (args);
1192 func_name = MPLIST_SYMBOL (args);
1194 if (im_info->externals)
1196 MIMExternalModule *external
1197 = (MIMExternalModule *) mplist_get (im_info->externals,
1200 func = (MIMExternalFunc) mplist_get (external->func_list,
1205 func_args = mplist ();
1206 mplist_add (func_args, Mt, ic);
1207 MPLIST_DO (args, MPLIST_NEXT (args))
1211 if (MPLIST_KEY (args) == Msymbol
1212 && MPLIST_KEY (args) != Mnil
1213 && (code = marker_code (MPLIST_SYMBOL (args))) >= 0)
1215 code = new_index (ic, ic->cursor_pos,
1216 mtext_nchars (ic->preedit),
1217 MPLIST_SYMBOL (args), ic->preedit);
1218 mplist_add (func_args, Minteger, (void *) code);
1221 mplist_add (func_args, MPLIST_KEY (args), MPLIST_VAL (args));
1223 val = (func) (func_args);
1224 M17N_OBJECT_UNREF (func_args);
1225 if (val && ! MPLIST_TAIL_P (val))
1226 ret = take_action_list (ic, val);
1227 M17N_OBJECT_UNREF (val);
1231 else if (name == Mshift)
1233 shift_state (ic, MPLIST_SYMBOL (args));
1235 else if (name == Mundo)
1237 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1240 mtext_reset (ic->preedit);
1241 mtext_reset (ic_info->preedit_saved);
1242 ic->cursor_pos = ic_info->state_pos = 0;
1243 ic_info->state_key_head = ic_info->key_head = 0;
1245 if (ic_info->used < 0)
1250 shift_state (ic, ((MIMState *) MPLIST_VAL (im_info->states))->name);
1255 else if (name == Mset || name == Madd || name == Msub
1256 || name == Mmul || name == Mdiv)
1258 MSymbol sym = MPLIST_SYMBOL (args);
1259 int val1 = (int) mplist_get (ic_info->vars, sym), val2;
1261 args = MPLIST_NEXT (args);
1262 val2 = integer_value (ic, args);
1265 else if (name == Madd)
1267 else if (name == Msub)
1269 else if (name == Mmul)
1273 mplist_put (ic_info->vars, sym, (void *) val1);
1275 else if (name == Mequal || name == Mless || name == Mgreater)
1278 MPlist *actions1, *actions2;
1281 val1 = integer_value (ic, args);
1282 args = MPLIST_NEXT (args);
1283 val2 = integer_value (ic, args);
1284 args = MPLIST_NEXT (args);
1285 actions1 = MPLIST_PLIST (args);
1286 args = MPLIST_NEXT (args);
1287 if (MPLIST_TAIL_P (args))
1290 actions2 = MPLIST_PLIST (args);
1291 if (name == Mequal ? val1 == val2
1292 : name == Mless ? val1 < val2
1294 ret = take_action_list (ic, actions1);
1296 ret = take_action_list (ic, actions2);
1302 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1306 && (actions = mplist_get (im_info->macros, name)))
1308 if (take_action_list (ic, actions) < 0)
1315 ic->candidate_list = NULL;
1316 if (ic->cursor_pos > 0
1317 && (prop = mtext_get_property (ic->preedit, ic->cursor_pos - 1,
1320 ic->candidate_list = mtext_property_value (prop);
1322 = (int) mtext_get_prop (ic->preedit, ic->cursor_pos - 1,
1324 ic->candidate_from = mtext_property_start (prop);
1325 ic->candidate_to = mtext_property_end (prop);
1328 ic->candidates_changed |= (candidate_list != ic->candidate_list
1329 || candidate_index != ic->candidate_index
1330 || candidate_show != ic->candidate_show);
1335 /* Handle the input key KEY in the current state and map specified in
1336 the input context IC. If KEY is handled correctly, return 0.
1337 Otherwise, return -1. */
1340 handle_key (MInputContext *ic)
1342 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1343 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1344 MIMMap *map = ic_info->map;
1346 MSymbol key = ic_info->keys[ic_info->key_head];
1349 submap = (map->submaps ? mplist_get (map->submaps, key) : NULL);
1352 mtext_cpy (ic->preedit, ic_info->preedit_saved);
1353 ic->cursor_pos = ic_info->state_pos;
1354 ic_info->key_head++;
1355 ic_info->map = map = submap;
1356 if (map->map_actions)
1358 if (take_action_list (ic, map->map_actions) < 0)
1361 else if (map->submaps)
1363 for (i = ic_info->state_key_head; i < ic_info->key_head; i++)
1365 MSymbol key = ic_info->keys[i];
1366 char *name = msymbol_name (key);
1368 if (! name[0] || ! name[1])
1369 mtext_ins_char (ic->preedit, ic->cursor_pos++, name[0], 1);
1371 ic->preedit_changed = 1;
1374 /* If this is the terminal map or we have shifted to another
1375 state, perform branch actions (if any). */
1376 if (! map->submaps || map != ic_info->map)
1378 if (map->branch_actions)
1380 if (take_action_list (ic, map->branch_actions) < 0)
1383 /* If MAP is still not the root map, shift to the current
1385 if (ic_info->map != ic_info->state->map)
1386 shift_state (ic, ic_info->state->name);
1391 /* MAP can not handle KEY. */
1393 /* If MAP is the root map of the initial state, it means that
1394 the current input method can not handle KEY. */
1395 if (map == ((MIMState *) MPLIST_VAL (im_info->states))->map)
1398 if (map != ic_info->state->map)
1400 /* If MAP is not the root map... */
1401 /* If MAP has branch actions, perform them. */
1402 if (map->branch_actions)
1403 take_action_list (ic, map->branch_actions);
1404 /* If MAP is still not the root map, shift to the current
1406 if (ic_info->map != ic_info->state->map)
1408 shift_state (ic, ic_info->state->name);
1409 /* If MAP has branch_actions, perform them. */
1410 if (ic_info->map->branch_actions)
1411 take_action_list (ic, ic_info->map->branch_actions);
1416 /* MAP is the root map, perform branch actions (if any) or
1417 shift to the initial state. */
1418 if (map->branch_actions)
1419 take_action_list (ic, map->branch_actions);
1422 ((MIMState *) MPLIST_VAL (im_info->states))->name);
1429 reset_ic (MInputContext *ic)
1431 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1432 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1434 MLIST_RESET (ic_info);
1435 ic_info->state = (MIMState *) MPLIST_VAL (im_info->states);
1436 ic_info->map = ic_info->state->map;
1437 ic_info->state_key_head = ic_info->key_head = 0;
1438 ic->cursor_pos = ic_info->state_pos = 0;
1439 ic->status = ic_info->state->title;
1441 ic->status = im_info->title;
1442 ic->candidate_list = NULL;
1443 ic->candidate_show = 0;
1444 ic->status_changed = ic->preedit_changed = ic->candidates_changed = 1;
1445 if (ic_info->map->map_actions)
1446 take_action_list (ic, ic_info->map->map_actions);
1450 open_im (MInputMethod *im)
1453 MInputMethodInfo *im_info;
1457 mdb = mdatabase_find (Minput_method, im->language, im->name, Mnil);
1460 plist = mdatabase_load (mdb);
1462 MERROR (MERROR_IM, -1);
1463 MSTRUCT_CALLOC (im_info, MERROR_IM);
1465 result = load_input_method (im->language, im->name, plist, im_info);
1466 M17N_OBJECT_UNREF (plist);
1468 MERROR (MERROR_IM, -1);
1473 close_im (MInputMethod *im)
1475 MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
1479 M17N_OBJECT_UNREF (im_info->title);
1480 if (im_info->states)
1482 MPLIST_DO (plist, im_info->states)
1484 MIMState *state = (MIMState *) MPLIST_VAL (plist);
1487 M17N_OBJECT_UNREF (state->title);
1489 free_map (state->map);
1492 M17N_OBJECT_UNREF (im_info->states);
1495 if (im_info->macros)
1497 MPLIST_DO (plist, im_info->macros)
1498 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
1499 M17N_OBJECT_UNREF (im_info->macros);
1502 if (im_info->externals)
1504 MPLIST_DO (plist, im_info->externals)
1506 MIMExternalModule *external = MPLIST_VAL (plist);
1508 dlclose (external->handle);
1509 M17N_OBJECT_UNREF (external->func_list);
1511 MPLIST_KEY (plist) = Mt;
1513 M17N_OBJECT_UNREF (im_info->externals);
1521 create_ic (MInputContext *ic)
1523 MInputMethod *im = ic->im;
1524 MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
1525 MInputContextInfo *ic_info;
1528 ic_info = (MInputContextInfo *) ic->info;
1531 MSTRUCT_CALLOC (ic_info, MERROR_IM);
1534 MLIST_INIT1 (ic_info, keys, 8);
1535 ic_info->markers = mplist ();
1536 ic_info->vars = mplist ();
1537 ic_info->preedit_saved = mtext ();
1538 if (im_info->externals)
1540 MPlist *func_args = mplist (), *plist;
1542 mplist_add (func_args, Mt, ic);
1543 MPLIST_DO (plist, im_info->externals)
1545 MIMExternalModule *external = MPLIST_VAL (plist);
1546 MIMExternalFunc func
1547 = (MIMExternalFunc) mplist_get (external->func_list, Minit);
1552 M17N_OBJECT_UNREF (func_args);
1559 destroy_ic (MInputContext *ic)
1561 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1562 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1564 if (im_info->externals)
1566 MPlist *func_args = mplist (), *plist;
1568 mplist_add (func_args, Mt, ic);
1569 MPLIST_DO (plist, im_info->externals)
1571 MIMExternalModule *external = MPLIST_VAL (plist);
1572 MIMExternalFunc func
1573 = (MIMExternalFunc) mplist_get (external->func_list, Mfini);
1578 M17N_OBJECT_UNREF (func_args);
1580 MLIST_FREE1 (ic_info, keys);
1581 M17N_OBJECT_UNREF (ic_info->preedit_saved);
1582 M17N_OBJECT_UNREF (ic_info->markers);
1583 M17N_OBJECT_UNREF (ic_info->vars);
1588 /** Handle the input key KEY in the current state and map of IC->info.
1589 If KEY is handled but no text is produced, return 0, otherwise
1595 filter (MInputContext *ic, MSymbol key, void *arg)
1597 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1598 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1601 mtext_reset (ic->produced);
1602 ic->status_changed = ic->preedit_changed = ic->candidates_changed = 0;
1603 MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
1604 ic_info->key_unhandled = 0;
1606 if (handle_key (ic) < 0)
1608 /* KEY was not handled. Reset the status and break the
1611 /* This forces returning 1. */
1612 ic_info->key_unhandled = 1;
1619 ic_info->key_unhandled = 1;
1622 /* Break the loop if all keys were handled. */
1623 } while (ic_info->key_head < ic_info->used);
1625 /* If the current map is the root of the initial state, we should
1626 produce any preedit text in ic->produced. */
1627 if (ic_info->map == ((MIMState *) MPLIST_VAL (im_info->states))->map
1628 && mtext_nchars (ic->preedit) > 0)
1629 shift_state (ic, ((MIMState *) MPLIST_VAL (im_info->states))->name);
1631 if (mtext_nchars (ic->produced) > 0)
1633 MSymbol lang = msymbol_get (ic->im->language, Mlanguage);
1636 mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
1637 Mlanguage, ic->im->language);
1640 return (! ic_info->key_unhandled && mtext_nchars (ic->produced) == 0);
1644 /** Return 1 if the last event or key was not handled, otherwise
1647 There is no need of looking up because ic->produced should already
1648 contain the produced text (if any).
1653 lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
1655 mtext_cat (mt, ic->produced);
1656 mtext_reset (ic->produced);
1657 return (((MInputContextInfo *) ic->info)->key_unhandled ? -1 : 0);
1660 /* Support functions for mdebug_dump_im. */
1663 dump_im_map (MPlist *map_list, int indent)
1666 MSymbol key = MPLIST_KEY (map_list);
1667 MIMMap *map = (MIMMap *) MPLIST_VAL (map_list);
1669 prefix = (char *) alloca (indent + 1);
1670 memset (prefix, 32, indent);
1671 prefix[indent] = '\0';
1673 fprintf (stderr, "(\"%s\" ", msymbol_name (key));
1674 if (map->map_actions)
1675 mdebug_dump_plist (map->map_actions, indent + 2);
1678 MPLIST_DO (map_list, map->submaps)
1680 fprintf (stderr, "\n%s ", prefix);
1681 dump_im_map (map_list, indent + 2);
1684 if (map->branch_actions)
1686 fprintf (stderr, "\n%s (branch\n%s ", prefix, prefix);
1687 mdebug_dump_plist (map->branch_actions, indent + 4);
1688 fprintf (stderr, ")");
1690 fprintf (stderr, ")");
1695 dump_im_state (MIMState *state, int indent)
1700 prefix = (char *) alloca (indent + 1);
1701 memset (prefix, 32, indent);
1702 prefix[indent] = '\0';
1704 fprintf (stderr, "(%s", msymbol_name (state->name));
1705 if (state->map->submaps)
1707 MPLIST_DO (map_list, state->map->submaps)
1709 fprintf (stderr, "\n%s ", prefix);
1710 dump_im_map (map_list, indent + 2);
1713 fprintf (stderr, ")");
1722 = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1723 "BackSpace", "Tab", "Linefeed", "Clear", NULL, "Return", NULL, NULL,
1724 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1725 NULL, NULL, NULL, "Escape", NULL, NULL, NULL, NULL };
1726 char buf[6], buf2[256];
1729 Minput_method = msymbol ("input-method");
1730 Minput_driver = msymbol ("input-driver");
1731 Mtitle = msymbol ("title");
1732 Mmacro = msymbol ("macro");
1733 Mmodule = msymbol ("module");
1734 Mmap = msymbol ("map");
1735 Mstate = msymbol ("state");
1736 Minsert = msymbol ("insert");
1737 Mdelete = msymbol ("delete");
1738 Mmove = msymbol ("move");
1739 Mmark = msymbol ("mark");
1740 Mpushback = msymbol ("pushback");
1741 Mundo = msymbol ("undo");
1742 Mcall = msymbol ("call");
1743 Mshift = msymbol ("shift");
1744 Mselect = msymbol ("select");
1745 Mshow = msymbol ("show");
1746 Mhide = msymbol ("hide");
1747 Mset = msymbol ("set");
1748 Madd = msymbol ("add");
1749 Msub = msymbol ("sub");
1750 Mmul = msymbol ("mul");
1751 Mdiv = msymbol ("div");
1752 Mequal = msymbol ("=");
1753 Mless = msymbol ("<");
1754 Mgreater = msymbol (">");
1756 Minput_preedit_start = msymbol ("input-preedit-start");
1757 Minput_preedit_done = msymbol ("input-preedit-done");
1758 Minput_preedit_draw = msymbol ("input-preedit-draw");
1759 Minput_status_start = msymbol ("input-status-start");
1760 Minput_status_done = msymbol ("input-status-done");
1761 Minput_status_draw = msymbol ("input-status-draw");
1762 Minput_candidates_start = msymbol ("input-candidates-start");
1763 Minput_candidates_done = msymbol ("input-candidates-done");
1764 Minput_candidates_draw = msymbol ("input-candidates-draw");
1765 Minput_set_spot = msymbol ("input-set-spot");
1766 Minput_toggle = msymbol ("input-toggle");
1768 Mcandidate_list = msymbol_as_managing_key (" candidate-list");
1769 Mcandidate_index = msymbol (" candidate-index");
1771 Minit = msymbol ("init");
1772 Mfini = msymbol ("fini");
1777 for (i = 0, buf[2] = '@'; i < ' '; i++, buf[2]++)
1780 one_char_symbol[i] = msymbol (key_names[i]);
1782 one_char_symbol[i] = msymbol (buf);
1784 for (buf[2] = i; i < 127; i++, buf[2]++)
1785 one_char_symbol[i] = msymbol (buf + 2);
1786 one_char_symbol[i++] = msymbol ("Delete");
1792 for (buf[4] = '@'; i < 160; i++, buf[4]++)
1794 if (key_names[i - 128])
1796 strcpy (buf2 + 2, key_names[i - 128]);
1797 one_char_symbol[i] = msymbol (buf2);
1800 one_char_symbol[i] = msymbol (buf);
1802 for (buf[4] = i - 128; i < 255; i++, buf[2]++)
1803 one_char_symbol[i] = msymbol (buf + 2);
1804 one_char_symbol[i] = msymbol ("M-Delete");
1806 minput_default_driver.open_im = open_im;
1807 minput_default_driver.close_im = close_im;
1808 minput_default_driver.create_ic = create_ic;
1809 minput_default_driver.destroy_ic = destroy_ic;
1810 minput_default_driver.filter = filter;
1811 minput_default_driver.lookup = lookup;
1812 minput_default_driver.callback_list = NULL;
1813 minput_driver = &minput_default_driver;
1820 if (minput_default_driver.callback_list)
1822 M17N_OBJECT_UNREF (minput_default_driver.callback_list);
1823 minput_default_driver.callback_list = NULL;
1825 if (minput_driver->callback_list)
1827 M17N_OBJECT_UNREF (minput_driver->callback_list);
1828 minput_driver->callback_list = NULL;
1833 minput__callback (MInputContext *ic, MSymbol command)
1835 if (ic->im->driver.callback_list)
1837 MInputCallbackFunc func
1838 = (MInputCallbackFunc) mplist_get (ic->im->driver.callback_list,
1842 (func) (ic, command);
1847 minput__char_to_key (int c)
1849 if (c < 0 || c >= 0x100)
1852 return one_char_symbol[c];
1856 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1861 /*** @addtogroup m17nInputMethod */
1866 @name Variables: Predefined symbols for callback commands.
1868 These are the predefined symbols that are used as the @c COMMAND
1869 argument of callback functions of an input method driver (see
1870 #MInputDriver::callback_list). */
1874 MSymbol Minput_preedit_start;
1875 MSymbol Minput_preedit_done;
1876 MSymbol Minput_preedit_draw;
1877 MSymbol Minput_status_start;
1878 MSymbol Minput_status_done;
1879 MSymbol Minput_status_draw;
1880 MSymbol Minput_candidates_start;
1881 MSymbol Minput_candidates_done;
1882 MSymbol Minput_candidates_draw;
1883 MSymbol Minput_set_spot;
1884 MSymbol Minput_toggle;
1889 @brief The default input driver for internal input methods.
1891 The variable #minput_default_driver is the default driver for
1892 internal input methods.
1894 The member MInputDriver::open_im () searches the m17n database for
1895 an input method that matches the tag \<#Minput_method, $LANGUAGE,
1896 $NAME\> and loads it.
1898 The member MInputDriver::callback_list () is @c NULL. Thus, it is
1899 programmers responsibility to set it to a plist of proper callback
1900 functions. Otherwise, no feedback information (e.g. preedit text)
1901 can be shown to users.
1903 The macro M17N_INIT () sets the variable #minput_driver to the
1904 pointer to this driver so that all internal input methods use it.
1906 Therefore, unless @c minput_driver is set differently, the driver
1907 dependent arguments $ARG of the functions whose name begin with
1908 "minput_" are all ignored. */
1911 @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥǥե©¥ë¥ÈÆþÎϥɥ饤¥Ð
1913 ÆþÎϥɥ饤¥Ð minput_default_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѤΥǥե©¥ë
1914 ¥È¤ÎÆþÎϥɥ饤¥Ð¤Ç¤¢¤ë¡£
1916 ¤³¤Î¥É¥é¥¤¥Ð¤Î <callback> ¥á¥ó¥Ð¤Ï @c NULL ¤Ê¤Î¤Ç¡¢¥×¥í¥°¥é¥Þ¦¤Ç
1917 ÀÕǤ¤ò»ý¤Ã¤Æ, ŬÀڤʥ³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ËÀßÄꤷ¡¢Preedit ¥Æ¥¥¹¥È,
1918 Status ¥Æ¥¥¹¥È¤¬¥æ¡¼¥¶¤Ëɽ¼¨¤Ç¤¤ë¤è¤¦¤Ë¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
1920 ´Ø¿ô M17N_INIT () ¤ÏÊÑ¿ô @c minput_driver ¤ò¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó
1921 ¥¿¤ËÀßÄꤷ¡¢Á´¤Æ¤ÎÆâÉôÆþÎϥ᥽¥Ã¥É¤¬¤³¤Î¥É¥é¥¤¥Ð¤ò»È¤¦¤è¤¦¤Ë¤¹¤ë¡£
1923 ¤·¤¿¤¬¤Ã¤Æ¡¢@c minput_driver ¤¬¥Ç¥Õ¥©¥ë¥ÈÃͤΤޤޤǤ¢¤ì¤Ð¡¢minput_
1924 ¤Ç»Ï¤Þ¤ë°Ê²¼¤Î´Ø¿ô·²¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô $ARG ¤Ï¤É¤ì¤â̵»ë¤µ¤ì
1927 MInputDriver minput_default_driver;
1931 @brief The input driver for internal input methods.
1933 The variable #minput_driver is a pointer to the input method
1934 driver that is used by internal input methods. The macro
1935 M17N_INIT () initializes it to a pointer to #minput_default_driver
1936 (if <m17n.h> is included) or to #minput_gui_driver (if
1937 <m17n-gui.h> is included). */
1939 MInputDriver *minput_driver;
1941 MSymbol Minput_driver;
1946 @brief Open an input method.
1948 The minput_open_im () function opens an input method that matches
1949 language $LANGUAGE and name $NAME, and returns a pointer to the
1950 input method object newly allocated.
1952 This function at first decides an input driver for the input
1955 If $LANGUAGE is not #Mnil, an input driver pointed by the variable
1956 #minput_driver is used.
1958 If $LANGUAGE is #Mnil and $NAME has #Minput_driver property, the
1959 input driver pointed to by the property value is used to open the
1960 input method. If $NAME has no such property, @c NULL is returned.
1962 Then, the member MInputDriver::open_im () of the input driver is
1965 $ARG is set in the member @c arg of the structure MInputMethod so
1966 that the input driver can refer to it. */
1969 @brief ÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë
1971 ´Ø¿ô mim_open () ¤Ï¸À¸ì $LANGUAGE ¤È̾Á° $NAME ¤ËŬ¹ç¤¹¤ëÆþÎϥ᥽¥Ã
1972 ¥É¤ò¥ª¡¼¥×¥ó¤·¡¢¤½¤Î¿·¤¿¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
1974 $LANGUAGE ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢m17n ¸À¸ì¾ðÊó¥Ù¡¼¥¹Ã椫¤é \<@c
1975 Minput_method, $LANGUAGE, $NAME \> ¤È¤¤¤¦¥¿¥°¤ËŬ¹ç¤¹¤ëÆþÎϥ᥽¥Ã
1976 ¥É¤òõ¤¹¡£¸«¤Ä¤«¤Ã¤¿¾ì¹ç¤Ï¡¢ÊÑ¿ô #minput_driver ¤Ç¥Ý¥¤¥ó¥È¤µ¤ì¤Æ
1977 ¤¤¤ëÆþÎϥɥ饤¥Ð¤òÍѤ¤¤Æ¤½¤ÎÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë¡£¸«¤Ä¤«¤é¤Ê
1978 ¤¤¾ì¹ç¤ä¥ª¡¼¥×¥ó¤Ç¤¤Ê¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï @c NULL ¤òÊÖ¤¹¡£
1980 ÊÑ¿ô #minput_driver ¤Ï¡¢#minput_default_driver ¤« @c
1981 minput_gui_driver ¤Î¤É¤Á¤é¤«¤ò¥Ý¥¤¥ó¥È¤·¤Æ¤¤¤ë¡£Á°¼Ô¤Ï CUI ÍѤǤ¢
1982 ¤ê¡¢´Ø¿ôm17n_initialize () ¤ò¸Æ¤Ö¤³¤È¤Ë¤è¤Ã¤Æ #minput_driver ¤¬
1983 #minput_default_driver ¤ò¥Ý¥¤¥ó¥È¤¹¤ë¤è¤¦¤Ë¤Ê¤ë¡£¸å¼Ô¤Ï GUI ÍѤÇ
1984 ¤¢¤ê¡¢´Ø¿ô m17n_initialize_win () ¤Ë¤è¤Ã¤Æ¥Ý¥¤¥ó¥È¤µ¤ì¤ë¡£¾ÜºÙ¤Ë¤Ä
1985 ¤¤¤Æ¤Ï¤³¤ì¤é¤ÎÊÑ¿ô¤Î¥É¥¥å¥á¥ó¥È¤ò»²¾È¤Î¤³¤È¡£
1987 $LANGUAGE ¤¬ #Mnil ¤Ç¤¢¤ê¡¢$NAME ¤¬ #Minput_driver ¤ò¥¡¼¤È¤¹
1988 ¤ë¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä¾ì¹ç¤Ë¤Ï¡¢¤½¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤǥݥ¤¥ó¥È¤µ¤ì¤Æ¤¤¤ë
1989 ÆþÎϥɥ饤¥Ð¤òÍѤ¤¤ÆÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë¡£$NAME ¤Ë¤½¤Î¤è¤¦¤Ê
1990 ¥×¥í¥Ñ¥Æ¥£¤¬Ìµ¤«¤Ã¤¿¾ì¹ç¤ä¥ª¡¼¥×¥ó¤Ç¤¤Ê¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï @c NULL ¤ò
1993 $ARG ¤Ï¡¢ÆþÎϥɥ饤¥Ð¤¬»²¾È¤Ç¤¤ë¤è¤¦¤Ë¡¢¹½Â¤ÂÎ MInputMethod ¤Î¥á
1994 ¥ó¥Ð @c arg ¤Ë¥»¥Ã¥È¤µ¤ì¤ë¡£
1996 @latexonly \IPAlabel{minput_open} @endlatexonly
2001 minput_open_im (MSymbol language, MSymbol name, void *arg)
2004 MInputDriver *driver;
2007 driver = minput_driver;
2010 driver = (MInputDriver *) msymbol_get (name, Minput_driver);
2012 MERROR (MERROR_IM, NULL);
2015 MSTRUCT_CALLOC (im, MERROR_IM);
2016 im->language = language;
2019 im->driver = *driver;
2020 if ((*im->driver.open_im) (im) < 0)
2031 @brief Close an input method.
2033 The minput_close_im () function closes the input method $IM, which
2034 must have been created by minput_open_im (). */
2037 @brief ÆþÎϥ᥽¥Ã¥É¤ò¥¯¥í¡¼¥º¤¹¤ë
2039 ´Ø¿ô minput_close_im () ¤Ï¡¢ÆþÎϥ᥽¥Ã¥É $IM ¤ò¥¯¥í¡¼¥º¤¹¤ë¡£¤³¤Î
2040 ÆþÎϥ᥽¥Ã¥É $IM ¤Ï minput_open_im () ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê¤±¤ì
2044 minput_close_im (MInputMethod *im)
2046 (*im->driver.close_im) (im);
2053 @brief Create an input context.
2055 The minput_create_ic () function creates an input context object
2056 associated with input method $IM, and calls callback functions
2057 corresponding to #Minput_preedit_start, #Minput_status_start, and
2058 #Minput_status_draw in this order.
2062 If an input context is successfully created, minput_create_ic ()
2063 returns a pointer to it. Otherwise it returns @c NULL. */
2066 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÀ¸À®¤¹¤ë
2068 ´Ø¿ô minput_create_ic () ¤ÏÆþÎϥ᥽¥Ã¥É $IM ¤ËÂбþ¤¹¤ëÆþÎÏ¥³¥ó¥Æ¥¯
2069 ¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤¹¤ë¡£
2072 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢minput_create_ic () ¤ÏÀ¸À®¤·¤¿ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È
2073 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¼ºÇÔ¤·¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£ */
2076 minput_create_ic (MInputMethod *im, void *arg)
2080 MSTRUCT_CALLOC (ic, MERROR_IM);
2083 ic->preedit = mtext ();
2084 ic->candidate_list = NULL;
2085 ic->produced = mtext ();
2086 ic->spot.x = ic->spot.y = 0;
2088 ic->plist = mplist ();
2089 if ((*im->driver.create_ic) (ic) < 0)
2091 M17N_OBJECT_UNREF (ic->preedit);
2092 M17N_OBJECT_UNREF (ic->produced);
2093 M17N_OBJECT_UNREF (ic->plist);
2098 if (im->driver.callback_list)
2100 minput__callback (ic, Minput_preedit_start);
2101 minput__callback (ic, Minput_status_start);
2102 minput__callback (ic, Minput_status_draw);
2111 @brief Destroy an input context.
2113 The minput_destroy_ic () function destroys the input context $IC,
2114 which must have been created by minput_create_ic (). It calls
2115 callback functions corresponding to #Minput_preedit_done,
2116 #Minput_status_done, and #Mcandidate_done in this order. */
2119 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÇ˲õ¤¹¤ë
2121 ´Ø¿ô minput_destroy_ic () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤òÇ˲õ¤¹¤ë¡£¤³
2122 ¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ï minput_create_ic () ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê
2126 minput_destroy_ic (MInputContext *ic)
2128 if (ic->im->driver.callback_list)
2130 minput__callback (ic, Minput_preedit_done);
2131 minput__callback (ic, Minput_status_done);
2132 minput__callback (ic, Minput_candidates_done);
2134 (*ic->im->driver.destroy_ic) (ic);
2135 M17N_OBJECT_UNREF (ic->preedit);
2136 M17N_OBJECT_UNREF (ic->produced);
2137 M17N_OBJECT_UNREF (ic->plist);
2144 @brief Filter an input key.
2146 The minput_filter () function filters input key $KEY according to
2147 input context $IC, and calls callback functions corresponding to
2148 #Minput_preedit_draw, #Minput_status_draw, and #Mcandidate_draw if
2149 the preedit text, the status, and the current candidate are
2150 changed respectively.
2153 If $KEY is filtered out, this function returns 1. In that case,
2154 the caller should discard the key. Otherwise, it returns 0, and
2155 the caller should handle the key, for instance, by calling the
2156 function minput_lookup () with the same $KEY. */
2159 @brief ÆþÎÏ¥¡¼¤Î¥Õ¥£¥ë¥¿¥ê¥ó¥°¤ò¤¹¤ë
2161 ´Ø¿ô minput_filter () ¤ÏÆþÎÏ¥¡¼ $KEY ¤òÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤Ë±þ
2162 ¤¸¤Æ¥Õ¥£¥ë¥¿¥ê¥ó¥°¤¹¤ë¡£
2164 ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤ÎÆþÎϥ᥽¥Ã¥É¤¬ÆþÎÏ¥¡¼¤ò¥Õ¥£¥ë¥¿¤¹¤ì¤Ð¡¢¤³
2165 ¤Î´Ø¿ô¤Ï 1 ¤òÊÖ¤¹¡£¤³¤Î¾ì¹ç¸Æ¤Ó½Ð¤·Â¦¤Ï¤³¤Î¥¡¼¤ò¼Î¤Æ¤ë¤Ù¤¤Ç¤¢¤ë¡£
2166 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0 ¤òÊÖ¤·¡¢¸Æ¤Ó½Ð¤·Â¦¤¬¡¢¤¿¤È¤¨¤ÐƱ¤¸ $KEY ¤Ç´Ø¿ô
2167 minput_lookup () ¤ò¸Æ¤Ö¤Ê¤É¤·¤Æ¡¢¤³¤Î¥¡¼¤ò½èÍý¤¹¤ë¡£
2169 @latexonly \IPAlabel{minput_filter} @endlatexonly
2173 minput_filter (MInputContext *ic, MSymbol key, void *arg)
2180 ret = (*ic->im->driver.filter) (ic, key, arg);
2182 if (ic->im->driver.callback_list)
2184 if (ic->preedit_changed)
2185 minput__callback (ic, Minput_preedit_draw);
2186 if (ic->status_changed)
2187 minput__callback (ic, Minput_status_draw);
2188 if (ic->candidates_changed)
2189 minput__callback (ic, Minput_candidates_draw);
2190 ic->preedit_changed = ic->status_changed = ic->candidates_changed = 0;
2199 @brief Lookup a text produced in the input context.
2201 The minput_lookup () function looks up a text in the input context
2202 $IC. $KEY must be the same one provided to the previous call of
2205 If a text was produced by the input method, it is concatenated
2208 This function calls #MInputDriver::lookup.
2211 If $KEY was correctly handled by the input method, this function
2212 returns 0. Otherwise, returns -1, even in that case, some text
2213 may be produced in $MT. */
2216 @brief ÆþÎϥ᥽¥Ã¥É¤¬ºî¤Ã¤¿¥Æ¥¥¹¥È¤Î³ÍÆÀ
2218 ´Ø¿ô minput_lookup () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC Ãæ¤Î¥Æ¥¥¹¥È¤ò³ÍÆÀ¤¹
2219 ¤ë¡£$KEY ¤Ï´Ø¿ôminput_filter () ¤Ø¤ÎľÁ°¤Î¸Æ¤Ó½Ð¤·¤ËÍѤ¤¤é¤ì¤¿¤â¤Î
2220 ¤ÈƱ¤¸¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2222 ¥Æ¥¥¹¥È¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆÀ¸À®¤µ¤ì¤Æ¤¤¤ì¤Ð¡¢$IC->produced ¤ËÊÝ
2225 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Î <tt>XLookupString ()</tt> ¡¢
2226 <tt>XmbLookupString ()</tt> ¡¢<tt>XwcLookupString ()</tt> ¤ËÂбþ¤¹
2230 $KEY ¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆŬÀڤ˽èÍý¤Ç¤¤Æ¤¤¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 0 ¤ò
2231 ÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤·¡¢¤³¤Î¾ì¹ç¤Ç¤â$IC->produced ¤Ë²¿¤é¤«
2232 ¤Î¥Æ¥¥¹¥È¤¬À¸À®¤µ¤ì¤Æ¤¤¤ë¤³¤È¤¬¤¢¤ë¡£
2234 @latexonly \IPAlabel{minput_lookup} @endlatexonly */
2237 minput_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2239 return (ic ? (*ic->im->driver.lookup) (ic, key, arg, mt) : -1);
2244 @brief Set the spot of the input context.
2246 The minput_set_spot () function set the spot of input context $IC
2247 to coordinate ($X, $Y) with the height $ASCENT and $DESCENT.
2248 $FONTSIZE specfies the fontsize of a preedit text in 1/10 point.
2249 The semantics of these values depend on the input driver.
2251 For instance, an input driver designed to work in CUI environment
2252 may use $X and $Y as column and row numbers, and ignore $ASCENT
2253 and $DESCENT. An input driver designed to work on a window system
2254 may treat $X and $Y as pixel offsets relative to the origin of the
2255 client window, and treat $ASCENT and $DESCENT as ascent and
2256 descent pixels of a line at ($X . $Y).
2258 $MT and $POS is an M-text and a character position at the spot.
2259 $MT may be NULL, in which case, the input method can't get
2260 information about the text around the spot. */
2263 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Î¥¹¥Ý¥Ã¥È¤òÀßÄꤹ¤ë
2265 ´Ø¿ô minput_set_spot () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤Î¥¹¥Ý¥Ã¥È¤ò¡¢ºÂ
2266 ɸ ($X, $Y)¤Ë ¡¢¹â¤µ $ASCENT¡¢$DESCENT ¤ÇÀßÄꤹ¤ë¡£¤³¤ì¤é¤ÎÃͤΰÕ
2267 Ì£¤ÏÆþÎϥɥ饤¥Ð¤Ë°Í¸¤¹¤ë¡£
2269 ¤¿¤È¤¨¤Ð CUI ´Ä¶¤ÇÆ°ºî¤¹¤ëÆþÎϥɥ饤¥Ð¤Ï $X, $Y ¤ò¤½¤ì¤¾¤ìÎó¤È¹Ô
2270 ¤ÎÈÖ¹æ¤È¤·¤ÆÍѤ¤¡¢$ASCENT¡¢$DESCENT ¤ò̵»ë¤¹¤ë¤«¤â¤·¤ì¤Ê¤¤¡£ ¤Þ¤¿
2271 ¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥àÍѤÎÆþÎϥɥ饤¥Ð¤Ï $X,$Y ¤ò¥¯¥é¥¤¥¢¥ó¥È¥¦¥£¥ó¥É
2272 ¥¦¤Î¸¶ÅÀ¤«¤é¤Î¥ª¥Õ¥»¥Ã¥È¤ò¥Ô¥¯¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¤¡¢
2273 $ASCENT ¤È $DESCENT ¤ò ($X . $Y) ¤ÎÎó¤Î¥¢¥»¥ó¥È¤È¥Ç¥£¥»¥ó¥È¤ò¥Ô¥¯
2274 ¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¦¤«¤â¤·¤ì¤Ê¤¤¡£ */
2277 minput_set_spot (MInputContext *ic, int x, int y,
2278 int ascent, int descent, int fontsize,
2283 ic->spot.ascent = ascent;
2284 ic->spot.descent = descent;
2285 ic->spot.fontsize = fontsize;
2288 if (ic->im->driver.callback_list)
2289 minput__callback (ic, Minput_set_spot);
2294 @brief Toggle input method.
2296 The minput_toggle () function toggles the input method associated
2297 with the input context $IC. */
2300 minput_toggle (MInputContext *ic)
2302 if (ic->im->driver.callback_list)
2303 minput__callback (ic, Minput_toggle);
2304 ic->active = ! ic->active;
2310 /*** @addtogroup m17nDebug */
2316 @brief Dump an input method
2318 The mdebug_dump_im () function prints the input method $IM in a
2319 human readable way to the stderr. $INDENT specifies how many
2320 columns to indent the lines but the first one.
2323 This function returns $IM. */
2326 mdebug_dump_im (MInputMethod *im, int indent)
2328 MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
2331 prefix = (char *) alloca (indent + 1);
2332 memset (prefix, 32, indent);
2333 prefix[indent] = '\0';
2335 fprintf (stderr, "(input-method %s %s ", msymbol_name (im->language),
2336 msymbol_name (im->name));
2337 mdebug_dump_mtext (im_info->title, 0, 0);
2338 if (im->name != Mnil)
2342 MPLIST_DO (state, im_info->states)
2344 fprintf (stderr, "\n%s ", prefix);
2345 dump_im_state (MPLIST_VAL (state), indent + 2);
2348 fprintf (stderr, ")");