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 a input method driver of the
30 input method. An input method driver is a set of functions for
31 handling the input method. There are two kinds of input methods;
32 internal one and foreign one.
35 <li> Internal Input Method
37 An internal input method has non @c Mnil LANGUAGE, and the body is
38 defined in the m17n database by the tag <Minput_method, LANGUAGE,
39 NAME>. For this kind of input methods, the m17n library uses two
40 predefined input method drivers, one for CUI use and the other for
41 GUI use. Those driver utilize the input processing engine
42 provided by the m17n library itself. The m17n database may
43 provides an input method that is not only for a specific language.
44 The database uses @c Mt as LANGUAGE of such an input method.
46 An internal input method accepts an input key which is a symbol
47 associated with an input event. As there is no way for the @c
48 m17n @c library to know how input events are represented in an
49 application program, an application programmer have to convert an
50 input event to an input key by himself. See the documentation of
51 the function minput_event_to_key () for the detail.
53 <li> Foreign Input Method
55 A foreign input method has @c Mnil LANGUAGE, and the body is
56 defined in an external resources (e.g. XIM of X Window System).
57 For this kind of input methods, the symbol NAME must have a
58 property of key @c Minput_driver, and the value must be a pointer
59 to an input method driver. Therefore, by preparing a proper
60 driver, any kind of input method can be treated in the framework
61 of the @c m17n @c library.
63 For convenience, the m17n-X library provides an input method
64 driver that enables the input style of OverTheSpot for XIM, and
65 stores @c Minput_driver property of the symbol @c Mxim with a
66 pointer to the driver. See the documentation of m17n GUI API for
73 The typical processing flow of handling an input method is:
75 @li open an input method
76 @li create an input context for the input method
77 @li filter an input key
78 @li look up a produced text in the input context */
82 @addtogroup m17nInputMethod
83 @brief ÆþÎϥ᥽¥Ã¥ÉÍÑAPI.
85 ÆþÎϥ᥽¥Ã¥É¤Ï¿ÍͤÊʸ»ú¤òÆþÎϤ¹¤ë¤¿¤á¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¢¤ë¡£ÆþÎÏ¥á
86 ¥½¥Ã¥É¤Ï¥·¥ó¥Ü¥ë LANGUAGE ¤È NAME ¤ÎÁȤˤè¤Ã¤Æ¼±Ê̤µ¤ì¡¢¤³¤ÎÁȤˤè¤Ã
87 ¤ÆÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤¬·è¤Þ¤ë¡£ÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤È¤Ï¤¢¤ëÆþÎÏ¥á
88 ¥½¥Ã¥É¤ò°·¤¦¤¿¤á¤Î´Ø¿ô¤Î½¸¤Þ¤ê¤Ç¤¢¤ë¡£ ÆþÎϥ᥽¥Ã¥É¤Ë¤ÏÆâÉô¥á¥½¥Ã
89 ¥É¤È³°Éô¥á¥½¥Ã¥É¤ÎÆóÄ̤꤬¤¢¤ë¡£
94 ÆâÉôÆþÎϥ᥽¥Ã¥É¤Ï LANGUAGE ¤¬ @c Mnil °Ê³°¤Î¤â¤Î¤Ç¤¢¤ê¡¢ËÜÂΤÏ
95 m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë <Minput_method, LANGUAGE, NAME>¤È¤¤¤¦¥¿¥°ÉÕ¤
96 ¤ÇÄêµÁ¤µ¤ì¤Æ¤¤¤ë¡£¤³¤Î¼ï¤ÎÆþÎϥ᥽¥Ã¥É¤ËÂФ·¤Æ¡¢m17n ¥é¥¤¥Ö¥é¥ê¤Ë
97 ¤ÏCUIÍѤÈGUIÍѤ½¤ì¤¾¤ì¤ÎÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤¬¤¢¤é¤«¤¸¤á½àÈ÷¤µ¤ì¤Æ
98 ¤¤¤ë¡£¤³¤ì¤é¤Î¥É¥é¥¤¥Ð¤Ïm17n¥é¥¤¥Ö¥é¥ê¼«¿È¤ÎÆþÎϽèÍý¥¨¥ó¥¸¥ó¤òÍøÍÑ
99 ¤¹¤ë¡£m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë¤Ï¡¢ÆÃÄê¤Î¸À¸ìÀìÍѤǤʤ¤ÆþÎϥ᥽¥Ã¥É¤âÄê
100 µÁ¤¹¤ë¤³¤È¤¬¤Ç¤¡¢¤½¤Î¤è¤¦¤ÊÆþÎϥ᥽¥Ã¥É¤Î LANGUAGE ¤Ï @c Mt ¤Ç¤¢
103 ÆâÉôÆþÎϥ᥽¥Ã¥É¤Ï¡¢¥æ¡¼¥¶¤ÎÆþÎÏ¥¤¥Ù¥ó¥È¤ËÂбþ¤·¤¿¥·¥ó¥Ü¥ë¤Ç¤¢¤ëÆþ
104 ÎÏ¥¡¼¤ò¼õ¤±¼è¤ë¡£@c m17n @c ¥é¥¤¥Ö¥é¥ê ¤ÏÆþÎÏ¥¤¥Ù¥ó¥È¤¬¥¢¥×¥ê¥±¡¼
105 ¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ç¤É¤¦É½¸½¤µ¤ì¤Æ¤¤¤ë¤«¤òÃΤë½Ñ¤ò»ý¤¿¤Ê¤¤¤Î¤Ç¡¢ÆþÎÏ
106 ¥¤¥Ù¥ó¥È¤«¤éÆþÎÏ¥¡¼¤Ø¤ÎÊÑ´¹¤Ï¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥Þ¤ÎÀÕǤ¤Ç¹Ô
107 ¤ï¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï´Ø¿ô minput_event_to_key () ¤ÎÀâ
110 <li> ³°ÉôÆþÎϥ᥽¥Ã¥É
112 ³°ÉôÆþÎϥ᥽¥Ã¥É¤Ï LANGUAGE ¤¬ @c Mnil ¤Î¤â¤Î¤Ç¤¢¤ê¡¢ËÜÂΤϳ°Éô¤Î
113 ¥ê¥½¡¼¥¹¤È¤·¤ÆÄêµÁ¤µ¤ì¤ë¡£¡Ê¤¿¤È¤¨¤ÐX Window System ¤ÎXIM ¤Ê¤É¡£)
114 ¤³¤Î¼ï¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢¥·¥ó¥Ü¥ë NAME ¤Ï@c Minput_driver ¤ò¥¡¼
115 ¤È¤¹¤ë¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Á¡¢¤½¤ÎÃͤÏÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç
116 ¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¤·¤¿¤¬¤Ã¤Æ¡¢Å¬Àڤʥɥ饤¥Ð¤ò½àÈ÷¤¹¤ë¤³¤È¤Ë¤è¤Ã¤Æ¡¢
117 ¤¤¤«¤Ê¤ë¼ïÎà¤ÎÆþÎϥ᥽¥Ã¥É¤â @c m17n @c ¥é¥¤¥Ö¥é¥ê ¤ÎÏÈÁȤÎÃæ¤Ç°·
120 ÍøÊØÀ¤Î¤¿¤á¡¢m17n X ¥é¥¤¥Ö¥é¥ê¤Ï XIM ¤Î OverTheSpot ¤ÎÆþÎÏ¥¹¥¿¥¤¥ë
121 ¤ò¼Â¸½¤¹¤ëÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤òÄ󶡤·¡¢¤Þ¤¿¥·¥ó¥Ü¥ë @c Mxim ¤Î @c
122 Minput_driver ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤȤ·¤Æ¤½¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÝ»ý¤·
123 ¤Æ¤¤¤ë¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï m17n GUI API ¤Î¥É¥¥å¥á¥ó¥È¤ò»²¾È¤Î¤³¤È¡£
129 ÆþÎϥ᥽¥Ã¥É½èÍý¤Îŵ·¿Åª¤Ê½èÍý¤Ï°Ê²¼¤Î¤è¤¦¤Ë¤Ê¤ë¡£
131 @li ÆþÎϥ᥽¥Ã¥É¤Î¥ª¡¼¥×¥ó
132 @li ¤½¤ÎÆþÎϥ᥽¥Ã¥É¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤ÎÀ¸À®
133 @li ÆþÎÏ¥¤¥Ù¥ó¥È¤Î¥Õ¥£¥ë¥¿
134 @li ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ç¤ÎÀ¸À®¥Æ¥¥¹¥È¤Î¸¡º÷ */
138 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
139 /*** @addtogroup m17nInternal
151 #include "m17n-gui.h"
152 #include "m17n-misc.h"
153 #include "internal.h"
159 static int mdebug_mask = MDEBUG_INPUT;
161 static MSymbol Minput_method;
163 /** Symbols to load an input method data. */
164 static MSymbol Mtitle, Mmacro, Mmodule, Mstate;
166 /** Symbols for actions. */
167 static MSymbol Minsert, Mdelete, Mmark, Mmove, Mpushback, Mundo, Mcall, Mshift;
168 static MSymbol Mselect, Mshow, Mhide;
169 static MSymbol Mset, Madd, Msub, Mmul, Mdiv, Mequal, Mless, Mgreater;
171 static MSymbol Mcandidate_list, Mcandidate_index;
173 static MSymbol Minit, Mfini;
175 /** Symbols for key events. */
176 static MSymbol one_char_symbol[256];
178 static MSymbol M_key_alias;
180 /** Structure to hold a map. */
184 /** List of actions to take when we reach the map. In a root map,
185 the actions are executed only when there's no more key. */
188 /** List of deeper maps. If NULL, this is a terminal map. */
191 /** List of actions to take when we leave the map successfully. In
192 a root map, the actions are executed only when none of submaps
193 handle the current key. */
194 MPlist *branch_actions;
197 typedef MPlist *(*MIMExternalFunc) (MPlist *plist);
202 MPlist *func_list; /* function name vs (MIMExternalFunc *) */
207 /** Name of the state. */
210 /** Title of the state, or NULL. */
213 /** Key translation map of the state. Built by merging all maps of
220 marker_code (MSymbol sym)
226 name = MSYMBOL_NAME (sym);
227 return ((name[0] == '@'
228 && ((name[1] >= '0' && name[1] <= '9')
229 || name[1] == '<' || name[1] == '>'
230 || name[1] == '=' || name[1] == '+' || name[1] == '-'
231 || name[1] == '[' || name[1] == ']')
237 integer_value (MInputContext *ic, MPlist *arg)
239 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
241 MText *preedit = ic->preedit;
242 int len = mtext_nbytes (preedit);
244 if (MPLIST_INTEGER_P (arg))
245 return MPLIST_INTEGER (arg);
246 code = marker_code (MPLIST_SYMBOL (arg));
248 return (int) mplist_get (ic_info->vars, MPLIST_SYMBOL (arg));
249 if (code >= '0' && code <= '9')
251 else if (code == '=')
252 code = ic->cursor_pos;
253 else if (code == '-' || code == '[')
254 code = ic->cursor_pos - 1;
255 else if (code == '+' || code == ']')
256 code = ic->cursor_pos + 1;
257 else if (code == '<')
259 else if (code == '<')
261 return (code >= 0 && code < len ? mtext_ref_char (preedit, code) : -1);
265 /* Parse PLIST as an action list while modifying the list to regularize
266 actions. PLIST should have this form:
267 PLIST ::= ( (ACTION-NAME ACTION-ARG *) *).
268 Return 0 if successfully parsed, otherwise return -1. */
271 parse_action_list (MPlist *plist, MPlist *macros)
273 MPLIST_DO (plist, plist)
275 if (MPLIST_MTEXT_P (plist))
277 /* This is a short form of (insert MTEXT). */
278 /* if (mtext_nchars (MPLIST_MTEXT (plist)) == 0)
279 MERROR (MERROR_IM, -1); */
281 else if (MPLIST_PLIST_P (plist)
282 && (MPLIST_MTEXT_P (MPLIST_PLIST (plist))
283 || MPLIST_PLIST_P (MPLIST_PLIST (plist))))
287 /* This is a short form of (insert (GROUPS *)). */
288 MPLIST_DO (pl, MPLIST_PLIST (plist))
290 if (MPLIST_PLIST_P (pl))
294 MPLIST_DO (elt, MPLIST_PLIST (pl))
295 if (! MPLIST_MTEXT_P (elt)
296 || mtext_nchars (MPLIST_MTEXT (elt)) == 0)
297 MERROR (MERROR_IM, -1);
301 if (! MPLIST_MTEXT_P (pl)
302 || mtext_nchars (MPLIST_MTEXT (pl)) == 0)
303 MERROR (MERROR_IM, -1);
307 else if (MPLIST_INTEGER_P (plist))
309 int c = MPLIST_INTEGER (plist);
311 if (c < 0 || c > MCHAR_MAX)
312 MERROR (MERROR_IM, -1);
314 else if (MPLIST_PLIST_P (plist)
315 && MPLIST_SYMBOL_P (MPLIST_PLIST (plist)))
317 MPlist *pl = MPLIST_PLIST (plist);
318 MSymbol action_name = MPLIST_SYMBOL (pl);
320 pl = MPLIST_NEXT (pl);
322 if (action_name == Minsert)
324 if (MPLIST_MTEXT_P (pl))
326 if (mtext_nchars (MPLIST_MTEXT (pl)) == 0)
327 MERROR (MERROR_IM, -1);
329 else if (MPLIST_PLIST_P (pl))
333 if (MPLIST_PLIST_P (pl))
337 MPLIST_DO (elt, MPLIST_PLIST (pl))
338 if (! MPLIST_MTEXT_P (elt)
339 || mtext_nchars (MPLIST_MTEXT (elt)) == 0)
340 MERROR (MERROR_IM, -1);
344 if (! MPLIST_MTEXT_P (pl)
345 || mtext_nchars (MPLIST_MTEXT (pl)) == 0)
346 MERROR (MERROR_IM, -1);
350 else if (! MPLIST_SYMBOL_P (pl))
351 MERROR (MERROR_IM, -1);
353 else if (action_name == Mselect
354 || action_name == Mdelete
355 || action_name == Mmove)
357 if (! MPLIST_SYMBOL_P (pl)
358 && ! MPLIST_INTEGER_P (pl))
359 MERROR (MERROR_IM, -1);
361 else if (action_name == Mmark
362 || action_name == Mcall
363 || action_name == Mshift)
365 if (! MPLIST_SYMBOL_P (pl))
366 MERROR (MERROR_IM, -1);
368 else if (action_name == Mshow || action_name == Mhide
369 || action_name == Mundo)
371 if (! MPLIST_TAIL_P (pl))
372 MERROR (MERROR_IM, -1);
374 else if (action_name == Mpushback)
376 if (! MPLIST_INTEGER_P (pl))
377 MERROR (MERROR_IM, -1);
379 else if (action_name == Mset || action_name == Madd
380 || action_name == Msub || action_name == Mmul
381 || action_name == Mdiv)
383 if (! (MPLIST_SYMBOL_P (pl)
384 && (MPLIST_INTEGER_P (MPLIST_NEXT (pl))
385 || MPLIST_SYMBOL_P (MPLIST_NEXT (pl)))))
386 MERROR (MERROR_IM, -1);
388 else if (action_name == Mequal || action_name == Mless
389 || action_name == Mgreater)
391 if (! ((MPLIST_INTEGER_P (pl) || MPLIST_SYMBOL_P (pl))
392 && (MPLIST_INTEGER_P (MPLIST_NEXT (pl))
393 || MPLIST_SYMBOL_P (MPLIST_NEXT (pl)))))
394 MERROR (MERROR_IM, -1);
395 pl = MPLIST_NEXT (MPLIST_NEXT (pl));
396 if (! MPLIST_PLIST_P (pl))
397 MERROR (MERROR_IM, -1);
398 if (parse_action_list (MPLIST_PLIST (pl), macros) < 0)
399 MERROR (MERROR_IM, -1);
400 pl = MPLIST_NEXT (pl);
401 if (MPLIST_PLIST_P (pl)
402 && parse_action_list (MPLIST_PLIST (pl), macros) < 0)
403 MERROR (MERROR_IM, -1);
405 else if (! macros || ! mplist_get (macros, action_name))
406 MERROR (MERROR_IM, -1);
409 MERROR (MERROR_IM, -1);
416 /* Load a translation into MAP from PLIST.
418 PLIST ::= ( KEYSEQ MAP-ACTION * ) */
421 load_translation (MIMMap *map, MPlist *plist, MPlist *branch_actions,
427 if (MPLIST_MTEXT_P (plist))
429 MText *mt = MPLIST_MTEXT (plist);
431 len = mtext_nchars (mt);
432 if (len == 0 || len != mtext_nbytes (mt))
433 MERROR (MERROR_IM, -1);
434 keyseq = (MSymbol *) alloca (sizeof (MSymbol) * len);
435 for (i = 0; i < len; i++)
436 keyseq[i] = one_char_symbol[MTEXT_DATA (mt)[i]];
438 else if (MPLIST_PLIST_P (plist))
440 MPlist *elt = MPLIST_PLIST (plist);
442 len = MPLIST_LENGTH (elt);
444 MERROR (MERROR_IM, -1);
445 keyseq = (MSymbol *) alloca (sizeof (int) * len);
446 for (i = 0; i < len; i++, elt = MPLIST_NEXT (elt))
448 if (MPLIST_INTEGER_P (elt))
450 int c = MPLIST_INTEGER (elt);
452 if (c < 0 || c >= 0x100)
453 MERROR (MERROR_IM, -1);
454 keyseq[i] = one_char_symbol[c];
456 else if (MPLIST_SYMBOL_P (elt))
457 keyseq[i] = MPLIST_SYMBOL (elt);
459 MERROR (MERROR_IM, -1);
463 MERROR (MERROR_IM, -1);
465 for (i = 0; i < len; i++)
467 MIMMap *deeper = NULL;
470 deeper = mplist_get (map->submaps, keyseq[i]);
472 map->submaps = mplist ();
475 /* Fixme: It is better to make all deeper maps at once. */
476 MSTRUCT_CALLOC (deeper, MERROR_IM);
477 mplist_put (map->submaps, keyseq[i], deeper);
482 /* We reach a terminal map. */
484 || map->branch_actions)
485 /* This map is already defined. We avoid overriding it. */
488 plist = MPLIST_NEXT (plist);
489 if (! MPLIST_TAIL_P (plist))
491 if (parse_action_list (plist, macros) < 0)
492 MERROR (MERROR_IM, -1);
493 map->map_actions = plist;
494 M17N_OBJECT_REF (plist);
498 map->branch_actions = branch_actions;
499 M17N_OBJECT_REF (branch_actions);
505 /* Load a branch from PLIST into MAP. PLIST has this form:
506 PLIST ::= ( MAP-NAME BRANCH-ACTION * )
507 MAPS is a plist of raw maps.
508 STATE is the current state. */
511 load_branch (MPlist *plist, MPlist *maps, MIMMap *map, MPlist *macros)
514 MPlist *branch_actions;
516 if (! MPLIST_SYMBOL_P (plist))
517 MERROR (MERROR_IM, -1);
518 map_name = MPLIST_SYMBOL (plist);
519 plist = MPLIST_NEXT (plist);
520 if (MPLIST_TAIL_P (plist))
521 branch_actions = NULL;
522 else if (parse_action_list (plist, macros) < 0)
523 MERROR (MERROR_IM, -1);
525 branch_actions = plist;
526 if (map_name == Mnil)
528 map->branch_actions = branch_actions;
530 M17N_OBJECT_REF (branch_actions);
532 else if (map_name == Mt)
534 map->map_actions = branch_actions;
536 M17N_OBJECT_REF (branch_actions);
540 plist = (MPlist *) mplist_get (maps, map_name);
541 if (! plist || ! MPLIST_PLIST_P (plist))
542 MERROR (MERROR_IM, -1);
543 MPLIST_DO (plist, plist)
544 if (! MPLIST_PLIST_P (plist)
545 || (load_translation (map, MPLIST_PLIST (plist), branch_actions,
548 MERROR (MERROR_IM, -1);
554 /* Load a macro from PLIST into MACROS.
556 PLIST ::= ( MACRO-NAME ACTION * )
557 MACROS is a plist of macro names vs action list. */
559 load_macros (MPlist *plist, MPlist *macros)
563 if (! MPLIST_SYMBOL_P (plist))
564 MERROR (MERROR_IM, -1);
565 name = MPLIST_SYMBOL (plist);
566 plist = MPLIST_NEXT (plist);
567 if (MPLIST_TAIL_P (plist)
568 || parse_action_list (plist, macros) < 0)
569 MERROR (MERROR_IM, -1);
570 mplist_put (macros, name, plist);
571 M17N_OBJECT_REF (plist);
575 /* Load an external module from PLIST into EXTERNALS.
577 PLIST ::= ( MODULE-NAME FUNCTION * )
578 EXTERNALS is a plist of MODULE-NAME vs (MIMExternalModule *). */
580 #ifndef DLOPEN_SHLIB_EXT
581 #define DLOPEN_SHLIB_EXT ".so"
585 load_external_module (MPlist *plist, MPlist *externals)
590 MIMExternalModule *external;
594 if (MPLIST_MTEXT_P (plist))
595 module = msymbol ((char *) MTEXT_DATA (MPLIST_MTEXT (plist)));
596 else if (MPLIST_SYMBOL_P (plist))
597 module = MPLIST_SYMBOL (plist);
598 module_file = alloca (strlen (MSYMBOL_NAME (module))
599 + strlen (DLOPEN_SHLIB_EXT) + 1);
600 sprintf (module_file, "%s%s", MSYMBOL_NAME (module), DLOPEN_SHLIB_EXT);
602 handle = dlopen (module_file, RTLD_NOW);
605 fprintf (stderr, "%s\n", dlerror ());
606 MERROR (MERROR_IM, -1);
608 func_list = mplist ();
609 MPLIST_DO (plist, MPLIST_NEXT (plist))
611 if (! MPLIST_SYMBOL_P (plist))
612 MERROR_GOTO (MERROR_IM, err_label);
613 func = dlsym (handle, MSYMBOL_NAME (MPLIST_SYMBOL (plist)));
615 MERROR_GOTO (MERROR_IM, err_label);
616 mplist_add (func_list, MPLIST_SYMBOL (plist), func);
619 MSTRUCT_MALLOC (external, MERROR_IM);
620 external->handle = handle;
621 external->func_list = func_list;
622 mplist_add (externals, module, external);
627 M17N_OBJECT_UNREF (func_list);
632 /** Load a state from PLIST into a newly allocated state object.
634 PLIST ::= ( STATE-NAME STATE-TITLE ? BRANCH * )
635 BRANCH ::= ( MAP-NAME BRANCH-ACTION * )
636 MAPS is a plist of defined maps.
637 Return the state object. */
640 load_state (MPlist *plist, MPlist *maps, MSymbol language, MPlist *macros)
644 MSTRUCT_CALLOC (state, MERROR_IM);
645 if (! MPLIST_SYMBOL_P (plist))
646 MERROR (MERROR_IM, NULL);
647 state->name = MPLIST_SYMBOL (plist);
648 plist = MPLIST_NEXT (plist);
649 if (MPLIST_MTEXT_P (plist))
651 state->title = MPLIST_MTEXT (plist);
652 mtext_put_prop (state->title, 0, mtext_nchars (state->title),
653 Mlanguage, language);
654 M17N_OBJECT_REF (state->title);
655 plist = MPLIST_NEXT (plist);
657 MSTRUCT_CALLOC (state->map, MERROR_IM);
658 MPLIST_DO (plist, plist)
659 if (! MPLIST_PLIST_P (plist)
660 || load_branch (MPLIST_PLIST (plist), maps, state->map, macros) < 0)
661 MERROR (MERROR_IM, NULL);
667 free_map (MIMMap *map)
671 M17N_OBJECT_UNREF (map->map_actions);
674 MPLIST_DO (plist, map->submaps)
675 free_map ((MIMMap *) MPLIST_VAL (plist));
676 M17N_OBJECT_UNREF (map->submaps);
678 M17N_OBJECT_UNREF (map->branch_actions);
682 /* Load an input method from PLIST into IM_INTO, and return it. */
685 load_input_method (MSymbol language, MSymbol name, MPlist *plist,
686 MInputMethodInfo *im_info)
690 MPlist *states = NULL;
691 MPlist *externals = NULL;
692 MPlist *macros = NULL;
695 if (! MPLIST_PLIST_P (plist))
696 MERROR (MERROR_IM, -1);
697 for (; MPLIST_PLIST_P (plist); plist = MPLIST_NEXT (plist))
699 elt = MPLIST_PLIST (plist);
700 if (! MPLIST_SYMBOL_P (elt))
701 MERROR_GOTO (MERROR_IM, err);
702 if (MPLIST_SYMBOL (elt) == Mtitle)
704 elt = MPLIST_NEXT (elt);
705 if (MPLIST_MTEXT_P (elt))
707 title = MPLIST_MTEXT (elt);
708 M17N_OBJECT_REF (title);
711 MERROR_GOTO (MERROR_IM, err);
713 else if (MPLIST_SYMBOL (elt) == Mmap)
715 maps = mplist__from_alist (MPLIST_NEXT (elt));
717 MERROR_GOTO (MERROR_IM, err);
719 else if (MPLIST_SYMBOL (elt) == Mmacro)
722 MPLIST_DO (elt, MPLIST_NEXT (elt))
724 if (! MPLIST_PLIST_P (elt)
725 || load_macros (MPLIST_PLIST (elt), macros) < 0)
726 MERROR_GOTO (MERROR_IM, err);
729 else if (MPLIST_SYMBOL (elt) == Mmodule)
731 externals = mplist ();
732 MPLIST_DO (elt, MPLIST_NEXT (elt))
734 if (! MPLIST_PLIST_P (elt)
735 || load_external_module (MPLIST_PLIST (elt), externals) < 0)
736 MERROR_GOTO (MERROR_IM, err);
739 else if (MPLIST_SYMBOL (elt) == Mstate)
742 MPLIST_DO (elt, MPLIST_NEXT (elt))
746 if (! MPLIST_PLIST_P (elt))
747 MERROR_GOTO (MERROR_IM, err);
748 state = load_state (MPLIST_PLIST (elt), maps, language, macros);
750 MERROR_GOTO (MERROR_IM, err);
751 mplist_put (states, state->name, state);
756 MPLIST_DO (elt, maps)
757 M17N_OBJECT_UNREF (MPLIST_VAL (elt));
758 M17N_OBJECT_UNREF (maps);
760 title = mtext_from_data (MSYMBOL_NAME (name), MSYMBOL_NAMELEN (name),
761 MTEXT_FORMAT_US_ASCII);
762 im_info->title = title;
763 im_info->externals = externals;
764 im_info->macros = macros;
765 im_info->states = states;
771 MPLIST_DO (elt, maps)
772 M17N_OBJECT_UNREF (MPLIST_VAL (elt));
773 M17N_OBJECT_UNREF (maps);
776 M17N_OBJECT_UNREF (title);
779 MPLIST_DO (plist, states)
781 MIMState *state = (MIMState *) MPLIST_VAL (plist);
784 M17N_OBJECT_UNREF (state->title);
786 free_map (state->map);
789 M17N_OBJECT_UNREF (states);
793 MPLIST_DO (plist, externals)
795 MIMExternalModule *external = MPLIST_VAL (plist);
797 dlclose (external->handle);
798 M17N_OBJECT_UNREF (external->func_list);
800 MPLIST_KEY (plist) = Mt;
802 M17N_OBJECT_UNREF (externals);
809 static int take_action_list (MInputContext *ic, MPlist *action_list);
812 shift_state (MInputContext *ic, MSymbol state_name)
814 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
815 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
816 MIMState *state = ic_info->state;
818 /* Find a state to shift to. If not found, shift to the initial
820 state = (MIMState *) mplist_get (im_info->states, state_name);
822 state = (MIMState *) MPLIST_VAL (im_info->states);
824 MDEBUG_PRINT1 ("\n[IM] state-shift (%s)", MSYMBOL_NAME (state->name));
826 /* Enter the new state. */
827 ic_info->state = state;
828 ic_info->map = state->map;
829 ic_info->state_key_head = ic_info->key_head;
830 if (state == (MIMState *) MPLIST_VAL (im_info->states))
832 /* We have shifted to the initial state. */
835 mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit),
836 Mcandidate_list, NULL, 0);
837 mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit),
838 Mcandidate_index, NULL, 0);
839 mtext_cat (ic->produced, ic->preedit);
840 if ((mdebug__flag & mdebug_mask)
841 && mtext_nchars (ic->produced) > 0)
845 MDEBUG_PRINT (" (produced");
846 for (i = 0; i < mtext_nchars (ic->produced); i++)
847 MDEBUG_PRINT1 (" U+%04X", mtext_ref_char (ic->produced, i));
850 mtext_reset (ic->preedit);
851 ic->candidate_list = NULL;
852 ic->candidate_show = 0;
853 ic->preedit_changed = ic->candidates_changed = 1;
854 MPLIST_DO (p, ic_info->markers)
856 MPLIST_DO (p, ic_info->vars)
859 memmove (ic_info->keys, ic_info->keys + ic_info->state_key_head,
860 sizeof (int) * (ic_info->used - ic_info->state_key_head));
861 ic_info->used -= ic_info->state_key_head;
862 ic_info->state_key_head = ic_info->key_head = 0;
864 mtext_cpy (ic_info->preedit_saved, ic->preedit);
865 ic_info->state_pos = ic->cursor_pos;
866 ic->status = state->title;
868 ic->status = im_info->title;
869 ic->status_changed = 1;
870 if (ic_info->key_head == ic_info->used
871 && ic_info->map == ic_info->state->map
872 && ic_info->map->map_actions)
874 MDEBUG_PRINT (" init-actions:");
875 take_action_list (ic, ic_info->map->map_actions);
879 /* Find a candidate group that contains a candidate number INDEX from
880 PLIST. Set START_INDEX to the first candidate number of the group,
881 END_INDEX to the last candidate number plus 1, GROUP_INDEX to the
882 candidate group number if they are non-NULL. If INDEX is -1, find
883 the last candidate group. */
886 find_candidates_group (MPlist *plist, int index,
887 int *start_index, int *end_index, int *group_index)
889 int i = 0, gidx = 0, len;
891 MPLIST_DO (plist, plist)
893 if (MPLIST_MTEXT_P (plist))
894 len = mtext_nchars (MPLIST_MTEXT (plist));
896 len = mplist_length (MPLIST_PLIST (plist));
897 if (index < 0 ? MPLIST_TAIL_P (MPLIST_NEXT (plist))
903 *end_index = i + len;
915 preedit_insert (MInputContext *ic, int pos, MText *mt, int c)
917 MInputContextInfo *ic_info = ((MInputContext *) ic)->info;
919 int nchars = mt ? mtext_nchars (mt) : 1;
922 mtext_ins (ic->preedit, pos, mt);
924 mtext_ins_char (ic->preedit, pos, c, 1);
925 MPLIST_DO (markers, ic_info->markers)
926 if (MPLIST_INTEGER (markers) > pos)
927 MPLIST_VAL (markers) = (void *) (MPLIST_INTEGER (markers) + nchars);
928 if (ic->cursor_pos >= pos)
929 ic->cursor_pos += nchars;
930 ic->preedit_changed = 1;
935 preedit_delete (MInputContext *ic, int from, int to)
937 MInputContextInfo *ic_info = ((MInputContext *) ic)->info;
940 mtext_del (ic->preedit, from, to);
941 MPLIST_DO (markers, ic_info->markers)
943 if (MPLIST_INTEGER (markers) > to)
945 = (void *) (MPLIST_INTEGER (markers) - (to - from));
946 else if (MPLIST_INTEGER (markers) > from);
947 MPLIST_VAL (markers) = (void *) from;
949 if (ic->cursor_pos >= to)
950 ic->cursor_pos -= to - from;
951 else if (ic->cursor_pos > from)
952 ic->cursor_pos = from;
953 ic->preedit_changed = 1;
958 new_index (MInputContext *ic, int current, int limit, MSymbol sym, MText *mt)
960 int code = marker_code (sym);
962 if (mt && (code == '[' || code == ']'))
966 if (code == '[' && current > 0)
968 if (mtext_prop_range (mt, Mcandidate_list, pos - 1, &pos, NULL, 1)
972 else if (code == ']' && current < mtext_nchars (mt))
974 if (mtext_prop_range (mt, Mcandidate_list, pos, NULL, &pos, 1))
980 return (code == '<' ? 0
981 : code == '>' ? limit
982 : code == '-' ? current - 1
983 : code == '+' ? current + 1
984 : code == '=' ? current
985 : code - '0' > limit ? limit
989 return (int) mplist_get (((MInputContextInfo *) ic->info)->markers, sym);
993 update_candidate (MInputContext *ic, MTextProperty *prop, int idx)
995 int from = mtext_property_start (prop);
996 int to = mtext_property_end (prop);
998 MPlist *candidate_list = mtext_property_value (prop);
999 MPlist *group = find_candidates_group (candidate_list, idx, &start,
1001 int ingroup_index = idx - start;
1004 preedit_delete (ic, from, to);
1005 if (MPLIST_MTEXT_P (group))
1007 mt = MPLIST_MTEXT (group);
1008 preedit_insert (ic, from, NULL, mtext_ref_char (mt, ingroup_index));
1016 for (i = 0, plist = MPLIST_PLIST (group); i < ingroup_index;
1017 i++, plist = MPLIST_NEXT (plist));
1018 mt = MPLIST_MTEXT (plist);
1019 preedit_insert (ic, from, mt, 0);
1020 to = from + mtext_nchars (mt);
1022 mtext_put_prop (ic->preedit, from, to, Mcandidate_list, candidate_list);
1023 mtext_put_prop (ic->preedit, from, to, Mcandidate_index, (void *) idx);
1024 ic->cursor_pos = to;
1029 take_action_list (MInputContext *ic, MPlist *action_list)
1031 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1032 MPlist *candidate_list = ic->candidate_list;
1033 int candidate_index = ic->candidate_index;
1034 int candidate_show = ic->candidate_show;
1035 MTextProperty *prop;
1037 MPLIST_DO (action_list, action_list)
1043 if (MPLIST_MTEXT_P (action_list)
1044 || MPLIST_INTEGER_P (action_list))
1045 name = Minsert, args = action_list;
1046 else if (MPLIST_PLIST_P (action_list)
1047 && (MPLIST_MTEXT_P (MPLIST_PLIST (action_list))
1048 || MPLIST_PLIST_P (MPLIST_PLIST (action_list))))
1049 name = Minsert, args = action_list;
1052 action = MPLIST_PLIST (action_list);
1053 name = MPLIST_SYMBOL (action);
1054 args = MPLIST_NEXT (action);
1057 MDEBUG_PRINT1 (" %s", MSYMBOL_NAME (name));
1058 if (name == Minsert)
1060 if (MPLIST_MTEXT_P (args))
1061 preedit_insert (ic, ic->cursor_pos, MPLIST_MTEXT (args), 0);
1062 else if (MPLIST_INTEGER_P (args))
1063 preedit_insert (ic, ic->cursor_pos, NULL, MPLIST_INTEGER (args));
1064 else if (MPLIST_SYMBOL_P (args))
1066 int c = integer_value (ic, args);
1068 if (c >= 0 && c <= MCHAR_MAX)
1069 preedit_insert (ic, ic->cursor_pos, NULL, c);
1076 args = MPLIST_PLIST (args);
1077 if (MPLIST_MTEXT_P (args))
1079 preedit_insert (ic, ic->cursor_pos, NULL,
1080 mtext_ref_char (MPLIST_MTEXT (args), 0));
1085 mt = MPLIST_MTEXT (MPLIST_PLIST (args));
1086 preedit_insert (ic, ic->cursor_pos, mt, 0);
1087 len = mtext_nchars (mt);
1089 mtext_put_prop (ic->preedit,
1090 ic->cursor_pos - len, ic->cursor_pos,
1091 Mcandidate_list, args);
1092 mtext_put_prop (ic->preedit,
1093 ic->cursor_pos - len, ic->cursor_pos,
1094 Mcandidate_index, (void *) 0);
1097 else if (name == Mselect)
1100 int code, idx, gindex;
1101 int pos = ic->cursor_pos;
1105 || ! (prop = mtext_get_property (ic->preedit, pos - 1,
1108 if (MPLIST_SYMBOL_P (args))
1110 code = marker_code (MPLIST_SYMBOL (args));
1116 idx = (int) mtext_get_prop (ic->preedit, pos - 1, Mcandidate_index);
1117 group = find_candidates_group (mtext_property_value (prop), idx,
1118 &start, &end, &gindex);
1120 if (code != '[' && code != ']')
1124 ? new_index (NULL, ic->candidate_index - start,
1125 end - start - 1, MPLIST_SYMBOL (args),
1127 : MPLIST_INTEGER (args)));
1130 find_candidates_group (mtext_property_value (prop), -1,
1135 && MPLIST_TAIL_P (MPLIST_NEXT (group)))
1140 int ingroup_index = idx - start;
1143 group = mtext_property_value (prop);
1144 len = mplist_length (group);
1157 for (idx = 0; gindex > 0; gindex--, group = MPLIST_NEXT (group))
1158 idx += (MPLIST_MTEXT_P (group)
1159 ? mtext_nchars (MPLIST_MTEXT (group))
1160 : mplist_length (MPLIST_PLIST (group)));
1161 len = (MPLIST_MTEXT_P (group)
1162 ? mtext_nchars (MPLIST_MTEXT (group))
1163 : mplist_length (MPLIST_PLIST (group)));
1164 if (ingroup_index >= len)
1165 ingroup_index = len - 1;
1166 idx += ingroup_index;
1168 update_candidate (ic, prop, idx);
1170 else if (name == Mshow)
1171 ic->candidate_show = 1;
1172 else if (name == Mhide)
1173 ic->candidate_show = 0;
1174 else if (name == Mdelete)
1176 int len = mtext_nchars (ic->preedit);
1177 int to = (MPLIST_SYMBOL_P (args)
1178 ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
1180 : MPLIST_INTEGER (args));
1186 if (to < ic->cursor_pos)
1187 preedit_delete (ic, to, ic->cursor_pos);
1188 else if (to > ic->cursor_pos)
1189 preedit_delete (ic, ic->cursor_pos, to);
1191 else if (name == Mmove)
1193 int len = mtext_nchars (ic->preedit);
1195 = (MPLIST_SYMBOL_P (args)
1196 ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
1198 : MPLIST_INTEGER (args));
1204 if (pos != ic->cursor_pos)
1206 ic->cursor_pos = pos;
1207 ic->preedit_changed = 1;
1210 else if (name == Mmark)
1212 int code = marker_code (MPLIST_SYMBOL (args));
1215 mplist_put (ic_info->markers, MPLIST_SYMBOL (args),
1216 (void *) ic->cursor_pos);
1218 else if (name == Mpushback)
1220 int num = MPLIST_INTEGER (args);
1223 ic_info->key_head -= num;
1225 ic_info->key_head = num;
1226 if (ic_info->key_head > ic_info->used)
1227 ic_info->key_head = ic_info->used;
1229 else if (name == Mcall)
1231 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1232 MIMExternalFunc func = NULL;
1233 MSymbol module, func_name;
1234 MPlist *func_args, *val;
1237 module = MPLIST_SYMBOL (args);
1238 args = MPLIST_NEXT (args);
1239 func_name = MPLIST_SYMBOL (args);
1241 if (im_info->externals)
1243 MIMExternalModule *external
1244 = (MIMExternalModule *) mplist_get (im_info->externals,
1247 func = (MIMExternalFunc) mplist_get (external->func_list,
1252 func_args = mplist ();
1253 mplist_add (func_args, Mt, ic);
1254 MPLIST_DO (args, MPLIST_NEXT (args))
1258 if (MPLIST_KEY (args) == Msymbol
1259 && MPLIST_KEY (args) != Mnil
1260 && (code = marker_code (MPLIST_SYMBOL (args))) >= 0)
1262 code = new_index (ic, ic->cursor_pos,
1263 mtext_nchars (ic->preedit),
1264 MPLIST_SYMBOL (args), ic->preedit);
1265 mplist_add (func_args, Minteger, (void *) code);
1268 mplist_add (func_args, MPLIST_KEY (args), MPLIST_VAL (args));
1270 val = (func) (func_args);
1271 M17N_OBJECT_UNREF (func_args);
1272 if (val && ! MPLIST_TAIL_P (val))
1273 ret = take_action_list (ic, val);
1274 M17N_OBJECT_UNREF (val);
1278 else if (name == Mshift)
1280 shift_state (ic, MPLIST_SYMBOL (args));
1282 else if (name == Mundo)
1284 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1287 mtext_reset (ic->preedit);
1288 mtext_reset (ic_info->preedit_saved);
1289 ic->cursor_pos = ic_info->state_pos = 0;
1290 ic_info->state_key_head = ic_info->key_head = 0;
1292 if (ic_info->used < 0)
1297 shift_state (ic, ((MIMState *) MPLIST_VAL (im_info->states))->name);
1302 else if (name == Mset || name == Madd || name == Msub
1303 || name == Mmul || name == Mdiv)
1305 MSymbol sym = MPLIST_SYMBOL (args);
1306 int val1 = (int) mplist_get (ic_info->vars, sym), val2;
1308 args = MPLIST_NEXT (args);
1309 val2 = integer_value (ic, args);
1312 else if (name == Madd)
1314 else if (name == Msub)
1316 else if (name == Mmul)
1320 mplist_put (ic_info->vars, sym, (void *) val1);
1321 MDEBUG_PRINT2 ("(%s=%d)", MSYMBOL_NAME (sym), val1);
1323 else if (name == Mequal || name == Mless || name == Mgreater)
1326 MPlist *actions1, *actions2;
1329 val1 = integer_value (ic, args);
1330 args = MPLIST_NEXT (args);
1331 val2 = integer_value (ic, args);
1332 args = MPLIST_NEXT (args);
1333 actions1 = MPLIST_PLIST (args);
1334 args = MPLIST_NEXT (args);
1335 if (MPLIST_TAIL_P (args))
1338 actions2 = MPLIST_PLIST (args);
1339 if (name == Mequal ? val1 == val2
1340 : name == Mless ? val1 < val2
1342 ret = take_action_list (ic, actions1);
1344 ret = take_action_list (ic, actions2);
1350 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1354 && (actions = mplist_get (im_info->macros, name)))
1356 if (take_action_list (ic, actions) < 0)
1363 ic->candidate_list = NULL;
1364 if (ic->cursor_pos > 0
1365 && (prop = mtext_get_property (ic->preedit, ic->cursor_pos - 1,
1368 ic->candidate_list = mtext_property_value (prop);
1370 = (int) mtext_get_prop (ic->preedit, ic->cursor_pos - 1,
1372 ic->candidate_from = mtext_property_start (prop);
1373 ic->candidate_to = mtext_property_end (prop);
1376 ic->candidates_changed |= (candidate_list != ic->candidate_list
1377 || candidate_index != ic->candidate_index
1378 || candidate_show != ic->candidate_show);
1383 /* Handle the input key KEY in the current state and map specified in
1384 the input context IC. If KEY is handled correctly, return 0.
1385 Otherwise, return -1. */
1388 handle_key (MInputContext *ic)
1390 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1391 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1392 MIMMap *map = ic_info->map;
1393 MIMMap *submap = NULL;
1394 MSymbol key = ic_info->keys[ic_info->key_head];
1397 MDEBUG_PRINT2 ("[IM] handle `%s' in state %s",
1398 MSYMBOL_NAME (key), MSYMBOL_NAME (ic_info->state->name));
1402 submap = mplist_get (map->submaps, key);
1403 if (! submap && (key = msymbol_get (key, M_key_alias)) != Mnil)
1404 submap = mplist_get (map->submaps, key);
1409 MDEBUG_PRINT (" submap-found");
1410 mtext_cpy (ic->preedit, ic_info->preedit_saved);
1411 ic->cursor_pos = ic_info->state_pos;
1412 ic_info->key_head++;
1413 ic_info->map = map = submap;
1414 if (map->map_actions)
1416 MDEBUG_PRINT (" map-actions:");
1417 if (take_action_list (ic, map->map_actions) < 0)
1420 else if (map->submaps)
1422 for (i = ic_info->state_key_head; i < ic_info->key_head; i++)
1424 MSymbol key = ic_info->keys[i];
1425 char *name = msymbol_name (key);
1427 if (! name[0] || ! name[1])
1428 mtext_ins_char (ic->preedit, ic->cursor_pos++, name[0], 1);
1430 ic->preedit_changed = 1;
1433 /* If this is the terminal map or we have shifted to another
1434 state, perform branch actions (if any). */
1435 if (! map->submaps || map != ic_info->map)
1437 if (map->branch_actions)
1439 MDEBUG_PRINT (" branch-actions:");
1440 if (take_action_list (ic, map->branch_actions) < 0)
1443 /* If MAP is still not the root map, shift to the current
1445 if (ic_info->map != ic_info->state->map)
1446 shift_state (ic, ic_info->state->name);
1448 MDEBUG_PRINT ("\n");
1452 /* MAP can not handle KEY. */
1454 /* If MAP is the root map of the initial state, it means that
1455 the current input method can not handle KEY. */
1456 if (map == ((MIMState *) MPLIST_VAL (im_info->states))->map)
1458 MDEBUG_PRINT (" unhandled\n");
1462 if (map != ic_info->state->map)
1464 /* If MAP is not the root map... */
1465 /* If MAP has branch actions, perform them. */
1466 if (map->branch_actions)
1468 MDEBUG_PRINT (" branch-actions:");
1469 take_action_list (ic, map->branch_actions);
1471 /* If MAP is still not the root map, shift to the current
1473 if (ic_info->map != ic_info->state->map)
1475 shift_state (ic, ic_info->state->name);
1476 /* If MAP has branch_actions, perform them. */
1477 if (ic_info->map->branch_actions)
1479 MDEBUG_PRINT (" init-actions:");
1480 take_action_list (ic, ic_info->map->branch_actions);
1486 /* MAP is the root map, perform branch actions (if any) or
1487 shift to the initial state. */
1488 if (map->branch_actions)
1490 MDEBUG_PRINT (" branch-actions:");
1491 take_action_list (ic, map->branch_actions);
1495 ((MIMState *) MPLIST_VAL (im_info->states))->name);
1497 MDEBUG_PRINT ("\n");
1503 reset_ic (MInputContext *ic)
1505 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1506 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1508 MLIST_RESET (ic_info);
1509 ic_info->state = (MIMState *) MPLIST_VAL (im_info->states);
1510 ic_info->map = ic_info->state ? ic_info->state->map : NULL;
1511 ic_info->state_key_head = ic_info->key_head = 0;
1512 ic->cursor_pos = ic_info->state_pos = 0;
1513 ic->status = ic_info->state ? ic_info->state->title : NULL;
1515 ic->status = im_info->title;
1516 ic->candidate_list = NULL;
1517 ic->candidate_show = 0;
1518 ic->status_changed = ic->preedit_changed = ic->candidates_changed = 1;
1519 if (ic_info->map && ic_info->map->map_actions)
1520 take_action_list (ic, ic_info->map->map_actions);
1524 open_im (MInputMethod *im)
1527 MInputMethodInfo *im_info;
1531 mdb = mdatabase_find (Minput_method, im->language, im->name, Mnil);
1534 plist = mdatabase_load (mdb);
1536 MERROR (MERROR_IM, -1);
1537 MSTRUCT_CALLOC (im_info, MERROR_IM);
1539 result = load_input_method (im->language, im->name, plist, im_info);
1540 M17N_OBJECT_UNREF (plist);
1542 MERROR (MERROR_IM, -1);
1547 close_im (MInputMethod *im)
1549 MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
1553 M17N_OBJECT_UNREF (im_info->title);
1554 if (im_info->states)
1556 MPLIST_DO (plist, im_info->states)
1558 MIMState *state = (MIMState *) MPLIST_VAL (plist);
1561 M17N_OBJECT_UNREF (state->title);
1563 free_map (state->map);
1566 M17N_OBJECT_UNREF (im_info->states);
1569 if (im_info->macros)
1571 MPLIST_DO (plist, im_info->macros)
1572 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
1573 M17N_OBJECT_UNREF (im_info->macros);
1576 if (im_info->externals)
1578 MPLIST_DO (plist, im_info->externals)
1580 MIMExternalModule *external = MPLIST_VAL (plist);
1582 dlclose (external->handle);
1583 M17N_OBJECT_UNREF (external->func_list);
1585 MPLIST_KEY (plist) = Mt;
1587 M17N_OBJECT_UNREF (im_info->externals);
1595 create_ic (MInputContext *ic)
1597 MInputMethod *im = ic->im;
1598 MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
1599 MInputContextInfo *ic_info;
1602 ic_info = (MInputContextInfo *) ic->info;
1605 MSTRUCT_CALLOC (ic_info, MERROR_IM);
1608 MLIST_INIT1 (ic_info, keys, 8);
1609 ic_info->markers = mplist ();
1610 ic_info->vars = mplist ();
1611 ic_info->preedit_saved = mtext ();
1612 if (im_info->externals)
1614 MPlist *func_args = mplist (), *plist;
1616 mplist_add (func_args, Mt, ic);
1617 MPLIST_DO (plist, im_info->externals)
1619 MIMExternalModule *external = MPLIST_VAL (plist);
1620 MIMExternalFunc func
1621 = (MIMExternalFunc) mplist_get (external->func_list, Minit);
1626 M17N_OBJECT_UNREF (func_args);
1633 destroy_ic (MInputContext *ic)
1635 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1636 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1638 if (im_info->externals)
1640 MPlist *func_args = mplist (), *plist;
1642 mplist_add (func_args, Mt, ic);
1643 MPLIST_DO (plist, im_info->externals)
1645 MIMExternalModule *external = MPLIST_VAL (plist);
1646 MIMExternalFunc func
1647 = (MIMExternalFunc) mplist_get (external->func_list, Mfini);
1652 M17N_OBJECT_UNREF (func_args);
1654 MLIST_FREE1 (ic_info, keys);
1655 M17N_OBJECT_UNREF (ic_info->preedit_saved);
1656 M17N_OBJECT_UNREF (ic_info->markers);
1657 M17N_OBJECT_UNREF (ic_info->vars);
1662 /** Handle the input key KEY in the current state and map of IC->info.
1663 If KEY is handled but no text is produced, return 0, otherwise
1669 filter (MInputContext *ic, MSymbol key, void *arg)
1671 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1672 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1675 if (! ic_info->state)
1677 ic_info->key_unhandled = 1;
1680 mtext_reset (ic->produced);
1681 ic->status_changed = ic->preedit_changed = ic->candidates_changed = 0;
1682 MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
1683 ic_info->key_unhandled = 0;
1685 if (handle_key (ic) < 0)
1687 /* KEY was not handled. Reset the status and break the
1690 /* This forces returning 1. */
1691 ic_info->key_unhandled = 1;
1698 ic_info->key_unhandled = 1;
1701 /* Break the loop if all keys were handled. */
1702 } while (ic_info->key_head < ic_info->used);
1704 /* If the current map is the root of the initial state, we should
1705 produce any preedit text in ic->produced. */
1706 if (ic_info->map == ((MIMState *) MPLIST_VAL (im_info->states))->map
1707 && mtext_nchars (ic->preedit) > 0)
1708 shift_state (ic, ((MIMState *) MPLIST_VAL (im_info->states))->name);
1710 if (mtext_nchars (ic->produced) > 0)
1712 MSymbol lang = msymbol_get (ic->im->language, Mlanguage);
1715 mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
1716 Mlanguage, ic->im->language);
1719 return (! ic_info->key_unhandled && mtext_nchars (ic->produced) == 0);
1723 /** Return 1 if the last event or key was not handled, otherwise
1726 There is no need of looking up because ic->produced should already
1727 contain the produced text (if any).
1732 lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
1734 mtext_cat (mt, ic->produced);
1735 mtext_reset (ic->produced);
1736 return (((MInputContextInfo *) ic->info)->key_unhandled ? -1 : 0);
1739 /* Support functions for mdebug_dump_im. */
1742 dump_im_map (MPlist *map_list, int indent)
1745 MSymbol key = MPLIST_KEY (map_list);
1746 MIMMap *map = (MIMMap *) MPLIST_VAL (map_list);
1748 prefix = (char *) alloca (indent + 1);
1749 memset (prefix, 32, indent);
1750 prefix[indent] = '\0';
1752 fprintf (stderr, "(\"%s\" ", msymbol_name (key));
1753 if (map->map_actions)
1754 mdebug_dump_plist (map->map_actions, indent + 2);
1757 MPLIST_DO (map_list, map->submaps)
1759 fprintf (stderr, "\n%s ", prefix);
1760 dump_im_map (map_list, indent + 2);
1763 if (map->branch_actions)
1765 fprintf (stderr, "\n%s (branch\n%s ", prefix, prefix);
1766 mdebug_dump_plist (map->branch_actions, indent + 4);
1767 fprintf (stderr, ")");
1769 fprintf (stderr, ")");
1774 dump_im_state (MIMState *state, int indent)
1779 prefix = (char *) alloca (indent + 1);
1780 memset (prefix, 32, indent);
1781 prefix[indent] = '\0';
1783 fprintf (stderr, "(%s", msymbol_name (state->name));
1784 if (state->map->submaps)
1786 MPLIST_DO (map_list, state->map->submaps)
1788 fprintf (stderr, "\n%s ", prefix);
1789 dump_im_map (map_list, indent + 2);
1792 fprintf (stderr, ")");
1801 = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1802 "BackSpace", "Tab", "Linefeed", "Clear", NULL, "Return", NULL, NULL,
1803 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1804 NULL, NULL, NULL, "Escape", NULL, NULL, NULL, NULL };
1805 char buf[6], buf2[256];
1808 Minput_method = msymbol ("input-method");
1809 Minput_driver = msymbol ("input-driver");
1810 Mtitle = msymbol ("title");
1811 Mmacro = msymbol ("macro");
1812 Mmodule = msymbol ("module");
1813 Mmap = msymbol ("map");
1814 Mstate = msymbol ("state");
1815 Minsert = msymbol ("insert");
1816 Mdelete = msymbol ("delete");
1817 Mmove = msymbol ("move");
1818 Mmark = msymbol ("mark");
1819 Mpushback = msymbol ("pushback");
1820 Mundo = msymbol ("undo");
1821 Mcall = msymbol ("call");
1822 Mshift = msymbol ("shift");
1823 Mselect = msymbol ("select");
1824 Mshow = msymbol ("show");
1825 Mhide = msymbol ("hide");
1826 Mset = msymbol ("set");
1827 Madd = msymbol ("add");
1828 Msub = msymbol ("sub");
1829 Mmul = msymbol ("mul");
1830 Mdiv = msymbol ("div");
1831 Mequal = msymbol ("=");
1832 Mless = msymbol ("<");
1833 Mgreater = msymbol (">");
1835 Minput_preedit_start = msymbol ("input-preedit-start");
1836 Minput_preedit_done = msymbol ("input-preedit-done");
1837 Minput_preedit_draw = msymbol ("input-preedit-draw");
1838 Minput_status_start = msymbol ("input-status-start");
1839 Minput_status_done = msymbol ("input-status-done");
1840 Minput_status_draw = msymbol ("input-status-draw");
1841 Minput_candidates_start = msymbol ("input-candidates-start");
1842 Minput_candidates_done = msymbol ("input-candidates-done");
1843 Minput_candidates_draw = msymbol ("input-candidates-draw");
1844 Minput_set_spot = msymbol ("input-set-spot");
1845 Minput_toggle = msymbol ("input-toggle");
1847 Mcandidate_list = msymbol_as_managing_key (" candidate-list");
1848 Mcandidate_index = msymbol (" candidate-index");
1850 Minit = msymbol ("init");
1851 Mfini = msymbol ("fini");
1853 M_key_alias = msymbol (" key-alias");
1858 for (i = 0, buf[2] = '@'; i < ' '; i++, buf[2]++)
1860 one_char_symbol[i] = msymbol (buf);
1862 msymbol_put (one_char_symbol[i], M_key_alias, msymbol (key_names[i]));
1864 for (buf[2] = i; i < 127; i++, buf[2]++)
1865 one_char_symbol[i] = msymbol (buf + 2);
1866 one_char_symbol[i++] = msymbol ("Delete");
1872 for (buf[4] = '@'; i < 160; i++, buf[4]++)
1874 one_char_symbol[i] = msymbol (buf);
1875 if (key_names[i - 128])
1877 strcpy (buf2 + 2, key_names[i - 128]);
1878 msymbol_put (one_char_symbol[i], M_key_alias, msymbol (buf2));
1881 for (buf[4] = i - 128; i < 255; i++, buf[4]++)
1882 one_char_symbol[i] = msymbol (buf + 2);
1883 one_char_symbol[i] = msymbol ("M-Delete");
1885 minput_default_driver.open_im = open_im;
1886 minput_default_driver.close_im = close_im;
1887 minput_default_driver.create_ic = create_ic;
1888 minput_default_driver.destroy_ic = destroy_ic;
1889 minput_default_driver.filter = filter;
1890 minput_default_driver.lookup = lookup;
1891 minput_default_driver.callback_list = NULL;
1892 minput_driver = &minput_default_driver;
1899 if (minput_default_driver.callback_list)
1901 M17N_OBJECT_UNREF (minput_default_driver.callback_list);
1902 minput_default_driver.callback_list = NULL;
1904 if (minput_driver->callback_list)
1906 M17N_OBJECT_UNREF (minput_driver->callback_list);
1907 minput_driver->callback_list = NULL;
1912 minput__callback (MInputContext *ic, MSymbol command)
1914 if (ic->im->driver.callback_list)
1916 MInputCallbackFunc func
1917 = (MInputCallbackFunc) mplist_get (ic->im->driver.callback_list,
1921 (func) (ic, command);
1926 minput__char_to_key (int c)
1928 if (c < 0 || c >= 0x100)
1931 return one_char_symbol[c];
1935 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1940 /*** @addtogroup m17nInputMethod */
1945 @name Variables: Predefined symbols for callback commands.
1947 These are the predefined symbols that are used as the @c COMMAND
1948 argument of callback functions of an input method driver (see
1949 #MInputDriver::callback_list ). */
1951 @name ÊÑ¿ô¡§ ¥³¡¼¥ë¥Ð¥Ã¥¯¥³¥Þ¥ó¥ÉÍÑÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë.
1953 ÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Î¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Ë¤ª¤¤¤Æ @c COMMAND °ú¿ô¤È¤·
1954 ¤ÆÍѤ¤¤é¤ì¤ëÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë (#MInputDriver::callback_list »²¾È)¡£
1959 MSymbol Minput_preedit_start;
1960 MSymbol Minput_preedit_done;
1961 MSymbol Minput_preedit_draw;
1962 MSymbol Minput_status_start;
1963 MSymbol Minput_status_done;
1964 MSymbol Minput_status_draw;
1965 MSymbol Minput_candidates_start;
1966 MSymbol Minput_candidates_done;
1967 MSymbol Minput_candidates_draw;
1968 MSymbol Minput_set_spot;
1969 MSymbol Minput_toggle;
1974 @brief The default driver for internal input methods.
1976 The variable #minput_default_driver is the default driver for
1977 internal input methods.
1979 The member MInputDriver::open_im () searches the m17n database for
1980 an input method that matches the tag \< #Minput_method, $LANGUAGE,
1981 $NAME\> and loads it.
1983 The member MInputDriver::callback_list () is @c NULL. Thus, it is
1984 programmers responsibility to set it to a plist of proper callback
1985 functions. Otherwise, no feedback information (e.g. preedit text)
1986 can be shown to users.
1988 The macro M17N_INIT () sets the variable #minput_driver to the
1989 pointer to this driver so that all internal input methods use it.
1991 Therefore, unless @c minput_driver is set differently, the driver
1992 dependent arguments $ARG of the functions whose name begin with
1993 "minput_" are all ignored. */
1996 @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥǥե©¥ë¥È¥É¥é¥¤¥Ð.
1998 ÆþÎϥɥ饤¥Ð #minput_default_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѤΥǥե©¥ë
1999 ¥È¤Î¥É¥é¥¤¥Ð¤Ç¤¢¤ë¡£
2001 ¥á¥ó¥Ð MInputDriver::open_im () ¤Ï m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹Ã椫¤é¥¿¥°
2002 \< #Minput_method, $LANGUAGE, $NAME\> ¤Ë¹çÃפ¹¤ëÆþÎϥ᥽¥Ã¥É¤òõ¤·¡¢
2005 ¥á¥ó¥Ð MInputDriver::callback_list () ¤Ï @c NULL ¤Ê¤Î¤Ç¡¢¥×¥í¥°¥é
2006 ¥Þ¦¤ÇÀÕǤ¤ò»ý¤Ã¤Æ, ŬÀڤʥ³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Î plist ¤ËÀßÄꤷ¤Ê¤¯¤Æ
2007 ¤Ï¤Ê¤é¤Ê¤¤¡£¤µ¤â¤Ê¤¤¤È¡¢preedit ¥Æ¥¥¹¥È¤Ê¤É¤Î¥Õ¥£¡¼¥É¥Ð¥Ã¥¯¾ðÊó¤¬
2008 ¥æ¡¼¥¶¤Ëɽ¼¨¤µ¤ì¤Ê¤¤¡£
2010 ¥Þ¥¯¥í M17N_INIT () ¤ÏÊÑ¿ô #minput_driver ¤ò¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó
2011 ¥¿¤ËÀßÄꤷ¡¢Á´¤Æ¤ÎÆâÉôÆþÎϥ᥽¥Ã¥É¤¬¤³¤Î¥É¥é¥¤¥Ð¤ò»È¤¦¤è¤¦¤Ë¤¹¤ë¡£
2013 ¤·¤¿¤¬¤Ã¤Æ¡¢@c minput_driver ¤¬¥Ç¥Õ¥©¥ë¥ÈÃͤΤޤޤǤ¢¤ì¤Ð¡¢minput_
2014 ¤Ç»Ï¤Þ¤ë´Ø¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô $ARG ¤Ï¤¹¤Ù¤Æ̵»ë¤µ¤ì¤ë¡£ */
2016 MInputDriver minput_default_driver;
2020 @brief The driver for internal input methods.
2022 The variable #minput_driver is a pointer to the input method
2023 driver that is used by internal input methods. The macro
2024 M17N_INIT () initializes it to a pointer to #minput_default_driver
2025 (if <m17n.h> is included) or to #minput_gui_driver (if
2026 <m17n-gui.h> is included). */
2028 @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥɥ饤¥Ð.
2030 ÊÑ¿ô #minput_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤Æ»ÈÍѤµ¤ì¤Æ¤¤¤ëÆþÎÏ¥á
2031 ¥½¥Ã¥É¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£¥Þ¥¯¥íM17N_INIT () ¤Ï¤³¤Î¥Ý¥¤¥ó
2032 ¥¿¤ò #minput_default_driver (<m17n.h> ¤¬´Þ¤Þ¤ì¤ë»þ) ¤Þ¤¿¤Ï
2033 #minput_gui_driver ( <m17n-gui.h> ¤¬´Þ¤Þ¤ì¤ë»þ) ¤Ë½é´ü²½¤¹¤ë¡£ */
2035 MInputDriver *minput_driver;
2037 MSymbol Minput_driver;
2042 @brief Open an input method.
2044 The minput_open_im () function opens an input method that matches
2045 language $LANGUAGE and name $NAME, and returns a pointer to the
2046 input method object newly allocated.
2048 This function at first decides an driver for the input method as
2051 If $LANGUAGE is not #Mnil, the driver pointed by the variable
2052 #minput_driver is used.
2054 If $LANGUAGE is #Mnil and $NAME has #Minput_driver property, the
2055 driver pointed to by the property value is used to open the input
2056 method. If $NAME has no such property, @c NULL is returned.
2058 Then, the member MInputDriver::open_im () of the driver is
2061 $ARG is set in the member @c arg of the structure MInputMethod so
2062 that the driver can refer to it. */
2065 @brief ÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë.
2067 ´Ø¿ô minput_open_im () ¤Ï¸À¸ì $LANGUAGE ¤È̾Á° $NAME ¤Ë¹çÃפ¹¤ëÆþ
2068 Îϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤·¡¢¿·¤¿¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿ÆþÎϥ᥽¥Ã¥É¥ª¥Ö¥¸¥§¥¯
2069 ¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
2071 ¤³¤Î´Ø¿ô¤Ï¡¢¤Þ¤ºÆþÎϥ᥽¥Ã¥ÉÍѤΥɥ饤¥Ð¤ò°Ê²¼¤Î¤è¤¦¤Ë¤·¤Æ·èÄꤹ¤ë¡£
2073 $LANGUAGE ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢ÊÑ¿ô #minput_driver ¤Ç»Ø¤µ¤ì¤Æ¤¤¤ë
2076 $LANGUAGE ¤¬ #Mnil ¤Ç¤¢¤ê¡¢$NAME ¤¬ #Minput_driver ¥×¥í¥Ñ¥Æ¥£¤ò»ý
2077 ¤Ä¾ì¹ç¤Ë¤Ï¡¢¤½¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤǻؤµ¤ì¤Æ¤¤¤ëÆþÎϥɥ饤¥Ð¤òÍѤ¤¤ÆÆþ
2078 Îϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë¡£$NAME ¤Ë¤½¤Î¤è¤¦¤Ê¥×¥í¥Ñ¥Æ¥£¤¬Ìµ¤«¤Ã¤¿¾ì
2079 ¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
2081 ¼¡¤¤¤Ç¡¢¥É¥é¥¤¥Ð¤Î¥á¥ó¥Ð MInputDriver::open_im () ¤¬¸Æ¤Ð¤ì¤ë¡£
2083 $ARG ¤Ï¡¢¥É¥é¥¤¥Ð¤¬»²¾È¤Ç¤¤ë¤è¤¦¤Ë¡¢¹½Â¤ÂÎ MInputMethod ¤Î¥á¥ó¥Ð
2084 @c arg ¤ËÀßÄꤵ¤ì¤ë¡£
2086 @latexonly \IPAlabel{minput_open} @endlatexonly
2091 minput_open_im (MSymbol language, MSymbol name, void *arg)
2094 MInputDriver *driver;
2097 driver = minput_driver;
2100 driver = (MInputDriver *) msymbol_get (name, Minput_driver);
2102 MERROR (MERROR_IM, NULL);
2105 MSTRUCT_CALLOC (im, MERROR_IM);
2106 im->language = language;
2109 im->driver = *driver;
2110 if ((*im->driver.open_im) (im) < 0)
2121 @brief Close an input method.
2123 The minput_close_im () function closes the input method $IM, which
2124 must have been created by minput_open_im (). */
2127 @brief ÆþÎϥ᥽¥Ã¥É¤ò¥¯¥í¡¼¥º¤¹¤ë.
2129 ´Ø¿ô minput_close_im () ¤Ï¡¢ÆþÎϥ᥽¥Ã¥É $IM ¤ò¥¯¥í¡¼¥º¤¹¤ë¡£¤³¤Î
2130 ÆþÎϥ᥽¥Ã¥É $IM ¤Ï minput_open_im () ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê¤±¤ì
2134 minput_close_im (MInputMethod *im)
2136 (*im->driver.close_im) (im);
2143 @brief Create an input context.
2145 The minput_create_ic () function creates an input context object
2146 associated with input method $IM, and calls callback functions
2147 corresponding to #Minput_preedit_start, #Minput_status_start, and
2148 #Minput_status_draw in this order.
2152 If an input context is successfully created, minput_create_ic ()
2153 returns a pointer to it. Otherwise it returns @c NULL. */
2156 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÀ¸À®¤¹¤ë.
2158 ´Ø¿ô minput_create_ic () ¤ÏÆþÎϥ᥽¥Ã¥É $IM ¤ËÂбþ¤¹¤ëÆþÎÏ¥³¥ó¥Æ¥¯
2159 ¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤·¡¢ #Minput_preedit_start,
2160 #Minput_status_start, #Minput_status_draw ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø
2165 ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤¬À¸À®¤µ¤ì¤¿¾ì¹ç¡¢minput_create_ic () ¤Ï¤½¤ÎÆþÎÏ¥³
2166 ¥ó¥Æ¥¯¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¼ºÇÔ¤·¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
2170 minput_create_ic (MInputMethod *im, void *arg)
2174 MSTRUCT_CALLOC (ic, MERROR_IM);
2177 ic->preedit = mtext ();
2178 ic->candidate_list = NULL;
2179 ic->produced = mtext ();
2180 ic->spot.x = ic->spot.y = 0;
2182 ic->plist = mplist ();
2183 if ((*im->driver.create_ic) (ic) < 0)
2185 M17N_OBJECT_UNREF (ic->preedit);
2186 M17N_OBJECT_UNREF (ic->produced);
2187 M17N_OBJECT_UNREF (ic->plist);
2192 if (im->driver.callback_list)
2194 minput__callback (ic, Minput_preedit_start);
2195 minput__callback (ic, Minput_status_start);
2196 minput__callback (ic, Minput_status_draw);
2205 @brief Destroy an input context.
2207 The minput_destroy_ic () function destroys the input context $IC,
2208 which must have been created by minput_create_ic (). It calls
2209 callback functions corresponding to #Minput_preedit_done,
2210 #Minput_status_done, and #Minput_candidates_done in this order. */
2213 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÇ˲õ¤¹¤ë.
2215 ´Ø¿ô minput_destroy_ic () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤òÇ˲õ¤¹¤ë¡£¤³
2216 ¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ï minput_create_ic () ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê
2217 ¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£¤³¤Î´Ø¿ô¤Ï#Minput_preedit_done,
2218 #Minput_status_done, #Minput_candidates_done ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò
2223 minput_destroy_ic (MInputContext *ic)
2225 if (ic->im->driver.callback_list)
2227 minput__callback (ic, Minput_preedit_done);
2228 minput__callback (ic, Minput_status_done);
2229 minput__callback (ic, Minput_candidates_done);
2231 (*ic->im->driver.destroy_ic) (ic);
2232 M17N_OBJECT_UNREF (ic->preedit);
2233 M17N_OBJECT_UNREF (ic->produced);
2234 M17N_OBJECT_UNREF (ic->plist);
2241 @brief Filter an input key.
2243 The minput_filter () function filters input key $KEY according to
2244 input context $IC, and calls callback functions corresponding to
2245 #Minput_preedit_draw, #Minput_status_draw, and
2246 #Minput_candidates_draw if the preedit text, the status, and the
2247 current candidate are changed respectively.
2250 If $KEY is filtered out, this function returns 1. In that case,
2251 the caller should discard the key. Otherwise, it returns 0, and
2252 the caller should handle the key, for instance, by calling the
2253 function minput_lookup () with the same key. */
2256 @brief ÆþÎÏ¥¡¼¤ò¥Õ¥£¥ë¥¿¤¹¤ë.
2258 ´Ø¿ô minput_filter () ¤ÏÆþÎÏ¥¡¼ $KEY ¤òÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤Ë±þ
2259 ¤¸¤Æ¥Õ¥£¥ë¥¿¤·¡¢preedit ¥Æ¥¥¹¥È¡¢¥¹¥Æ¡¼¥¿¥¹¡¢¸½»þÅÀ¤Ç¤Î¸õÊ䤬ÊѲ½
2260 ¤·¤¿ºÝ¤Ë¤Ï¤½¤ì¤¾¤ì#Minput_preedit_draw, #Minput_status_draw,
2261 #Minput_candidates_draw ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¸Æ¤Ö¡£
2264 $KEY ¤¬¥Õ¥£¥ë¥¿¤µ¤ì¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 1 ¤òÊÖ¤¹¡£¤³¤Î¾ì¹ç¸Æ¤Ó
2265 ½Ð¤·Â¦¤Ï¤³¤Î¥¡¼¤ò¼Î¤Æ¤ë¤Ù¤¤Ç¤¢¤ë¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0 ¤òÊÖ¤·¡¢¸Æ¤Ó
2266 ½Ð¤·Â¦¤Ï¡¢¤¿¤È¤¨¤ÐƱ¤¸¥¡¼¤Ç´Ø¿ô minput_lookup () ¤ò¸Æ¤Ö¤Ê¤É¤·¤Æ¡¢
2267 ¤³¤Î¥¡¼¤ò½èÍý¤¹¤ë¡£
2269 @latexonly \IPAlabel{minput_filter} @endlatexonly
2273 minput_filter (MInputContext *ic, MSymbol key, void *arg)
2280 ret = (*ic->im->driver.filter) (ic, key, arg);
2282 if (ic->im->driver.callback_list)
2284 if (ic->preedit_changed)
2285 minput__callback (ic, Minput_preedit_draw);
2286 if (ic->status_changed)
2287 minput__callback (ic, Minput_status_draw);
2288 if (ic->candidates_changed)
2289 minput__callback (ic, Minput_candidates_draw);
2290 ic->preedit_changed = ic->status_changed = ic->candidates_changed = 0;
2299 @brief Lookup a text produced in the input context.
2301 The minput_lookup () function looks up a text in the input context
2302 $IC. $KEY must be the same one provided to the previous call of
2305 If a text was produced by the input method, it is concatenated
2308 This function calls #MInputDriver::lookup .
2311 If $KEY was correctly handled by the input method, this function
2312 returns 0. Otherwise, returns -1, even in that case, some text
2313 may be produced in $MT. */
2316 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥ÈÃæ¤Î¥Æ¥¥¹¥È¤Î¸¡º÷.
2318 ´Ø¿ô minput_lookup () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC Ãæ¤Î¥Æ¥¥¹¥È¤ò¸¡º÷¤¹
2319 ¤ë¡£$KEY ¤Ï´Ø¿ôminput_filter () ¤Ø¤ÎľÁ°¤Î¸Æ¤Ó½Ð¤·¤ËÍѤ¤¤é¤ì¤¿¤â¤Î
2320 ¤ÈƱ¤¸¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2322 ¥Æ¥¥¹¥È¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆÀ¸À®¤µ¤ì¤Æ¤¤¤ì¤Ð¡¢¥Æ¥¥¹¥È¤Ï M-text
2325 ¤³¤Î´Ø¿ô¤Ï¡¢#MInputDriver::lookup ¤ò¸Æ¤Ö¡£
2328 $KEY ¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆŬÀڤ˽èÍý¤Ç¤¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 0 ¤òÊÖ¤¹¡£
2329 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£¤³¤Î¾ì¹ç¤Ç¤â $MT ¤Ë²¿¤é¤«¤Î¥Æ¥¥¹¥È¤¬À¸
2330 À®¤µ¤ì¤Æ¤¤¤ë¤³¤È¤¬¤¢¤ë¡£
2332 @latexonly \IPAlabel{minput_lookup} @endlatexonly */
2335 minput_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2337 return (ic ? (*ic->im->driver.lookup) (ic, key, arg, mt) : -1);
2342 @brief Set the spot of the input context.
2344 The minput_set_spot () function set the spot of input context $IC
2345 to coordinate ($X, $Y ) with the height $ASCENT and $DESCENT .
2346 The semantics of these values depend on the input method driver.
2347 $FONTSIZE specfies the fontsize of a preedit text in 1/10 point.
2349 For instance, an driver designed to work in CUI environment may
2350 use $X and $Y as column and row numbers, and ignore $ASCENT and
2351 $DESCENT . An driver designed to work on a window system may
2352 treat $X and $Y as pixel offsets relative to the origin of the
2353 client window, and treat $ASCENT and $DESCENT as ascent and
2354 descent pixels of a line at ($X . $Y ).
2356 $MT and $POS is an M-text and a character position at the spot.
2357 $MT may be @c NULL, in which case, the input method cannot get
2358 information about the text around the spot. */
2361 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Î¥¹¥Ý¥Ã¥È¤òÀßÄꤹ¤ë
2363 ´Ø¿ô minput_set_spot () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤Î¥¹¥Ý¥Ã¥È¤ò¡¢ºÂ
2364 ɸ ($X, $Y )¤Ë ¡¢¹â¤µ $ASCENT¡¢ $DESCENT ¤ÇÀßÄꤹ¤ë¡£ ¤³¤ì¤é¤ÎÃͤÎ
2365 °ÕÌ£¤ÏÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë¡£$FONTSIZE ¤Ïpreedit ¥Æ¥¥¹¥È
2366 ¤Î¥Õ¥©¥ó¥È¥µ¥¤¥º¤ò 1/10 ¥Ý¥¤¥ó¥Èñ°Ì¤Ç»ØÄꤹ¤ë¡£
2368 ¤¿¤È¤¨¤Ð CUI ´Ä¶¤ÇÆ°ºî¤¹¤ë¥É¥é¥¤¥Ð¤Ï $X ¤È $Y ¤ò¤½¤ì¤¾¤ìÎó¤È¹Ô¤Î
2369 ÈÖ¹æ¤È¤·¤ÆÍѤ¤¡¢$ASCENT ¤È $DESCENT ¤ò̵»ë¤¹¤ë¤«¤â¤·¤ì¤Ê¤¤¡£ ¤Þ¤¿
2370 ¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥àÍѤΥɥ饤¥Ð¤Ï $X ¤È $Y ¤ò¥¯¥é¥¤¥¢¥ó¥È¥¦¥£¥ó¥É¥¦
2371 ¤Î¸¶ÅÀ¤«¤é¤Î¥ª¥Õ¥»¥Ã¥È¤ò¥Ô¥¯¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¤¡¢
2372 $ASCENT ¤È $DESCENT ¤ò ($X . $Y ) ¤ÎÎó¤Î¥¢¥»¥ó¥È¤È¥Ç¥£¥»¥ó¥È¤ò¥Ô¥¯
2373 ¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¦¤«¤â¤·¤ì¤Ê¤¤¡£
2375 $MT ¤È $POS ¤Ï¤½¤Î¥¹¥Ý¥Ã¥È¤Î M-text ¤Èʸ»ú°ÌÃ֤Ǥ¢¤ë¡£$MT ¤Ï @c
2376 NULL ¤Ç¤â¤è¤¯¡¢¤½¤Î¾ì¹ç¤Ë¤ÏÆþÎϥ᥽¥Ã¥É¤Ï¥¹¥Ý¥Ã¥È¼þÊդΥƥ¥¹¥È¤Ë
2377 ´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë¤³¤È¤¬¤Ç¤¤Ê¤¤¡£
2381 minput_set_spot (MInputContext *ic, int x, int y,
2382 int ascent, int descent, int fontsize,
2387 ic->spot.ascent = ascent;
2388 ic->spot.descent = descent;
2389 ic->spot.fontsize = fontsize;
2392 if (ic->im->driver.callback_list)
2393 minput__callback (ic, Minput_set_spot);
2398 @brief Toggle input method.
2400 The minput_toggle () function toggles the input method associated
2401 with the input context $IC. */
2403 @brief ÆþÎϥ᥽¥Ã¥É¤òÀÚÂؤ¨¤ë.
2405 ´Ø¿ô minput_toggle () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤ËÂбþÉÕ¤±¤é¤ì¤¿ÆþÎÏ
2406 ¥á¥½¥Ã¥É¤ò¥È¥°¥ë¤¹¤ë¡£
2410 minput_toggle (MInputContext *ic)
2412 if (ic->im->driver.callback_list)
2413 minput__callback (ic, Minput_toggle);
2414 ic->active = ! ic->active;
2420 /*** @addtogroup m17nDebug */
2426 @brief Dump an input method.
2428 The mdebug_dump_im () function prints the input method $IM in a
2429 human readable way to the stderr. $INDENT specifies how many
2430 columns to indent the lines but the first one.
2433 This function returns $IM. */
2435 @brief ÆþÎϥ᥽¥Ã¥É¤ò¥À¥ó¥×¤¹¤ë.
2437 ´Ø¿ô mdebug_dump_im () ¤ÏÆþÎϥ᥽¥Ã¥É $IM ¤ò stderr ¤Ë¿Í´Ö¤Ë²ÄÆɤÊ
2438 ·Á¤Ç°õºþ¤¹¤ë¡£$INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£
2441 ¤³¤Î´Ø¿ô¤Ï $IM ¤òÊÖ¤¹¡£ */
2444 mdebug_dump_im (MInputMethod *im, int indent)
2446 MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
2449 prefix = (char *) alloca (indent + 1);
2450 memset (prefix, 32, indent);
2451 prefix[indent] = '\0';
2453 fprintf (stderr, "(input-method %s %s ", msymbol_name (im->language),
2454 msymbol_name (im->name));
2455 mdebug_dump_mtext (im_info->title, 0, 0);
2456 if (im->name != Mnil)
2460 MPLIST_DO (state, im_info->states)
2462 fprintf (stderr, "\n%s ", prefix);
2463 dump_im_state (MPLIST_VAL (state), indent + 2);
2466 fprintf (stderr, ")");