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_nchars (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 for (; MPLIST_PLIST_P (plist); plist = MPLIST_NEXT (plist))
697 elt = MPLIST_PLIST (plist);
698 if (! MPLIST_SYMBOL_P (elt))
699 MERROR_GOTO (MERROR_IM, err);
700 if (MPLIST_SYMBOL (elt) == Mtitle)
702 elt = MPLIST_NEXT (elt);
703 if (MPLIST_MTEXT_P (elt))
705 title = MPLIST_MTEXT (elt);
706 M17N_OBJECT_REF (title);
709 MERROR_GOTO (MERROR_IM, err);
711 else if (MPLIST_SYMBOL (elt) == Mmap)
713 maps = mplist__from_alist (MPLIST_NEXT (elt));
715 MERROR_GOTO (MERROR_IM, err);
717 else if (MPLIST_SYMBOL (elt) == Mmacro)
720 MPLIST_DO (elt, MPLIST_NEXT (elt))
722 if (! MPLIST_PLIST_P (elt)
723 || load_macros (MPLIST_PLIST (elt), macros) < 0)
724 MERROR_GOTO (MERROR_IM, err);
727 else if (MPLIST_SYMBOL (elt) == Mmodule)
729 externals = mplist ();
730 MPLIST_DO (elt, MPLIST_NEXT (elt))
732 if (! MPLIST_PLIST_P (elt)
733 || load_external_module (MPLIST_PLIST (elt), externals) < 0)
734 MERROR_GOTO (MERROR_IM, err);
737 else if (MPLIST_SYMBOL (elt) == Mstate)
740 MPLIST_DO (elt, MPLIST_NEXT (elt))
744 if (! MPLIST_PLIST_P (elt))
745 MERROR_GOTO (MERROR_IM, err);
746 state = load_state (MPLIST_PLIST (elt), maps, language, macros);
748 MERROR_GOTO (MERROR_IM, err);
749 mplist_put (states, state->name, state);
756 MPLIST_DO (elt, maps)
757 M17N_OBJECT_UNREF (MPLIST_VAL (elt));
758 M17N_OBJECT_UNREF (maps);
761 title = mtext_from_data (MSYMBOL_NAME (name), MSYMBOL_NAMELEN (name),
762 MTEXT_FORMAT_US_ASCII);
763 im_info->title = title;
764 im_info->externals = externals;
765 im_info->macros = macros;
766 im_info->states = states;
772 MPLIST_DO (elt, maps)
773 M17N_OBJECT_UNREF (MPLIST_VAL (elt));
774 M17N_OBJECT_UNREF (maps);
777 M17N_OBJECT_UNREF (title);
780 MPLIST_DO (plist, states)
782 MIMState *state = (MIMState *) MPLIST_VAL (plist);
785 M17N_OBJECT_UNREF (state->title);
787 free_map (state->map);
790 M17N_OBJECT_UNREF (states);
794 MPLIST_DO (plist, externals)
796 MIMExternalModule *external = MPLIST_VAL (plist);
798 dlclose (external->handle);
799 M17N_OBJECT_UNREF (external->func_list);
801 MPLIST_KEY (plist) = Mt;
803 M17N_OBJECT_UNREF (externals);
810 static int take_action_list (MInputContext *ic, MPlist *action_list);
813 shift_state (MInputContext *ic, MSymbol state_name)
815 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
816 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
819 /* Find a state to shift to. If not found, shift to the initial
821 state = (MIMState *) mplist_get (im_info->states, state_name);
823 state = (MIMState *) MPLIST_VAL (im_info->states);
825 MDEBUG_PRINT1 ("\n[IM] state-shift (%s)", MSYMBOL_NAME (state->name));
827 /* Enter the new state. */
828 ic_info->state = state;
829 ic_info->map = state->map;
830 ic_info->state_key_head = ic_info->key_head;
831 if (state == (MIMState *) MPLIST_VAL (im_info->states))
833 /* We have shifted to the initial state. */
836 mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit),
837 Mcandidate_list, NULL, 0);
838 mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit),
839 Mcandidate_index, NULL, 0);
840 mtext_cat (ic->produced, ic->preedit);
841 if ((mdebug__flag & mdebug_mask)
842 && mtext_nchars (ic->produced) > 0)
846 MDEBUG_PRINT (" (produced");
847 for (i = 0; i < mtext_nchars (ic->produced); i++)
848 MDEBUG_PRINT1 (" U+%04X", mtext_ref_char (ic->produced, i));
851 mtext_reset (ic->preedit);
852 ic->candidate_list = NULL;
853 ic->candidate_show = 0;
854 ic->preedit_changed = ic->candidates_changed = 1;
855 MPLIST_DO (p, ic_info->markers)
857 MPLIST_DO (p, ic_info->vars)
860 memmove (ic_info->keys, ic_info->keys + ic_info->state_key_head,
861 sizeof (int) * (ic_info->used - ic_info->state_key_head));
862 ic_info->used -= ic_info->state_key_head;
863 ic_info->state_key_head = ic_info->key_head = 0;
865 mtext_cpy (ic_info->preedit_saved, ic->preedit);
866 ic_info->state_pos = ic->cursor_pos;
867 ic->status = state->title;
869 ic->status = im_info->title;
870 ic->status_changed = 1;
871 if (ic_info->key_head == ic_info->used
872 && ic_info->map == ic_info->state->map
873 && ic_info->map->map_actions)
875 MDEBUG_PRINT (" init-actions:");
876 take_action_list (ic, ic_info->map->map_actions);
880 /* Find a candidate group that contains a candidate number INDEX from
881 PLIST. Set START_INDEX to the first candidate number of the group,
882 END_INDEX to the last candidate number plus 1, GROUP_INDEX to the
883 candidate group number if they are non-NULL. If INDEX is -1, find
884 the last candidate group. */
887 find_candidates_group (MPlist *plist, int index,
888 int *start_index, int *end_index, int *group_index)
890 int i = 0, gidx = 0, len;
892 MPLIST_DO (plist, plist)
894 if (MPLIST_MTEXT_P (plist))
895 len = mtext_nchars (MPLIST_MTEXT (plist));
897 len = mplist_length (MPLIST_PLIST (plist));
898 if (index < 0 ? MPLIST_TAIL_P (MPLIST_NEXT (plist))
904 *end_index = i + len;
916 preedit_insert (MInputContext *ic, int pos, MText *mt, int c)
918 MInputContextInfo *ic_info = ((MInputContext *) ic)->info;
920 int nchars = mt ? mtext_nchars (mt) : 1;
923 mtext_ins (ic->preedit, pos, mt);
925 mtext_ins_char (ic->preedit, pos, c, 1);
926 MPLIST_DO (markers, ic_info->markers)
927 if (MPLIST_INTEGER (markers) > pos)
928 MPLIST_VAL (markers) = (void *) (MPLIST_INTEGER (markers) + nchars);
929 if (ic->cursor_pos >= pos)
930 ic->cursor_pos += nchars;
931 ic->preedit_changed = 1;
936 preedit_delete (MInputContext *ic, int from, int to)
938 MInputContextInfo *ic_info = ((MInputContext *) ic)->info;
941 mtext_del (ic->preedit, from, to);
942 MPLIST_DO (markers, ic_info->markers)
944 if (MPLIST_INTEGER (markers) > to)
946 = (void *) (MPLIST_INTEGER (markers) - (to - from));
947 else if (MPLIST_INTEGER (markers) > from);
948 MPLIST_VAL (markers) = (void *) from;
950 if (ic->cursor_pos >= to)
951 ic->cursor_pos -= to - from;
952 else if (ic->cursor_pos > from)
953 ic->cursor_pos = from;
954 ic->preedit_changed = 1;
959 new_index (MInputContext *ic, int current, int limit, MSymbol sym, MText *mt)
961 int code = marker_code (sym);
963 if (mt && (code == '[' || code == ']'))
967 if (code == '[' && current > 0)
969 if (mtext_prop_range (mt, Mcandidate_list, pos - 1, &pos, NULL, 1)
973 else if (code == ']' && current < mtext_nchars (mt))
975 if (mtext_prop_range (mt, Mcandidate_list, pos, NULL, &pos, 1))
981 return (code == '<' ? 0
982 : code == '>' ? limit
983 : code == '-' ? current - 1
984 : code == '+' ? current + 1
985 : code == '=' ? current
986 : code - '0' > limit ? limit
990 return (int) mplist_get (((MInputContextInfo *) ic->info)->markers, sym);
994 update_candidate (MInputContext *ic, MTextProperty *prop, int idx)
996 int from = mtext_property_start (prop);
997 int to = mtext_property_end (prop);
999 MPlist *candidate_list = mtext_property_value (prop);
1000 MPlist *group = find_candidates_group (candidate_list, idx, &start,
1002 int ingroup_index = idx - start;
1005 preedit_delete (ic, from, to);
1006 if (MPLIST_MTEXT_P (group))
1008 mt = MPLIST_MTEXT (group);
1009 preedit_insert (ic, from, NULL, mtext_ref_char (mt, ingroup_index));
1017 for (i = 0, plist = MPLIST_PLIST (group); i < ingroup_index;
1018 i++, plist = MPLIST_NEXT (plist));
1019 mt = MPLIST_MTEXT (plist);
1020 preedit_insert (ic, from, mt, 0);
1021 to = from + mtext_nchars (mt);
1023 mtext_put_prop (ic->preedit, from, to, Mcandidate_list, candidate_list);
1024 mtext_put_prop (ic->preedit, from, to, Mcandidate_index, (void *) idx);
1025 ic->cursor_pos = to;
1030 take_action_list (MInputContext *ic, MPlist *action_list)
1032 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1033 MPlist *candidate_list = ic->candidate_list;
1034 int candidate_index = ic->candidate_index;
1035 int candidate_show = ic->candidate_show;
1036 MTextProperty *prop;
1038 MPLIST_DO (action_list, action_list)
1044 if (MPLIST_MTEXT_P (action_list)
1045 || MPLIST_INTEGER_P (action_list))
1046 name = Minsert, args = action_list;
1047 else if (MPLIST_PLIST_P (action_list)
1048 && (MPLIST_MTEXT_P (MPLIST_PLIST (action_list))
1049 || MPLIST_PLIST_P (MPLIST_PLIST (action_list))))
1050 name = Minsert, args = action_list;
1053 action = MPLIST_PLIST (action_list);
1054 name = MPLIST_SYMBOL (action);
1055 args = MPLIST_NEXT (action);
1058 MDEBUG_PRINT1 (" %s", MSYMBOL_NAME (name));
1059 if (name == Minsert)
1061 if (MPLIST_MTEXT_P (args))
1062 preedit_insert (ic, ic->cursor_pos, MPLIST_MTEXT (args), 0);
1063 else if (MPLIST_INTEGER_P (args))
1064 preedit_insert (ic, ic->cursor_pos, NULL, MPLIST_INTEGER (args));
1065 else if (MPLIST_SYMBOL_P (args))
1067 int c = integer_value (ic, args);
1069 if (c >= 0 && c <= MCHAR_MAX)
1070 preedit_insert (ic, ic->cursor_pos, NULL, c);
1077 args = MPLIST_PLIST (args);
1078 if (MPLIST_MTEXT_P (args))
1080 preedit_insert (ic, ic->cursor_pos, NULL,
1081 mtext_ref_char (MPLIST_MTEXT (args), 0));
1086 mt = MPLIST_MTEXT (MPLIST_PLIST (args));
1087 preedit_insert (ic, ic->cursor_pos, mt, 0);
1088 len = mtext_nchars (mt);
1090 mtext_put_prop (ic->preedit,
1091 ic->cursor_pos - len, ic->cursor_pos,
1092 Mcandidate_list, args);
1093 mtext_put_prop (ic->preedit,
1094 ic->cursor_pos - len, ic->cursor_pos,
1095 Mcandidate_index, (void *) 0);
1098 else if (name == Mselect)
1101 int code, idx, gindex;
1102 int pos = ic->cursor_pos;
1106 || ! (prop = mtext_get_property (ic->preedit, pos - 1,
1109 if (MPLIST_SYMBOL_P (args))
1111 code = marker_code (MPLIST_SYMBOL (args));
1117 idx = (int) mtext_get_prop (ic->preedit, pos - 1, Mcandidate_index);
1118 group = find_candidates_group (mtext_property_value (prop), idx,
1119 &start, &end, &gindex);
1121 if (code != '[' && code != ']')
1125 ? new_index (NULL, ic->candidate_index - start,
1126 end - start - 1, MPLIST_SYMBOL (args),
1128 : MPLIST_INTEGER (args)));
1131 find_candidates_group (mtext_property_value (prop), -1,
1136 && MPLIST_TAIL_P (MPLIST_NEXT (group)))
1141 int ingroup_index = idx - start;
1144 group = mtext_property_value (prop);
1145 len = mplist_length (group);
1158 for (idx = 0; gindex > 0; gindex--, group = MPLIST_NEXT (group))
1159 idx += (MPLIST_MTEXT_P (group)
1160 ? mtext_nchars (MPLIST_MTEXT (group))
1161 : mplist_length (MPLIST_PLIST (group)));
1162 len = (MPLIST_MTEXT_P (group)
1163 ? mtext_nchars (MPLIST_MTEXT (group))
1164 : mplist_length (MPLIST_PLIST (group)));
1165 if (ingroup_index >= len)
1166 ingroup_index = len - 1;
1167 idx += ingroup_index;
1169 update_candidate (ic, prop, idx);
1171 else if (name == Mshow)
1172 ic->candidate_show = 1;
1173 else if (name == Mhide)
1174 ic->candidate_show = 0;
1175 else if (name == Mdelete)
1177 int len = mtext_nchars (ic->preedit);
1178 int to = (MPLIST_SYMBOL_P (args)
1179 ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
1181 : MPLIST_INTEGER (args));
1187 if (to < ic->cursor_pos)
1188 preedit_delete (ic, to, ic->cursor_pos);
1189 else if (to > ic->cursor_pos)
1190 preedit_delete (ic, ic->cursor_pos, to);
1192 else if (name == Mmove)
1194 int len = mtext_nchars (ic->preedit);
1196 = (MPLIST_SYMBOL_P (args)
1197 ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
1199 : MPLIST_INTEGER (args));
1205 if (pos != ic->cursor_pos)
1207 ic->cursor_pos = pos;
1208 ic->preedit_changed = 1;
1211 else if (name == Mmark)
1213 int code = marker_code (MPLIST_SYMBOL (args));
1216 mplist_put (ic_info->markers, MPLIST_SYMBOL (args),
1217 (void *) ic->cursor_pos);
1219 else if (name == Mpushback)
1221 int num = MPLIST_INTEGER (args);
1224 ic_info->key_head -= num;
1226 ic_info->key_head = num;
1227 if (ic_info->key_head > ic_info->used)
1228 ic_info->key_head = ic_info->used;
1230 else if (name == Mcall)
1232 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1233 MIMExternalFunc func = NULL;
1234 MSymbol module, func_name;
1235 MPlist *func_args, *val;
1238 module = MPLIST_SYMBOL (args);
1239 args = MPLIST_NEXT (args);
1240 func_name = MPLIST_SYMBOL (args);
1242 if (im_info->externals)
1244 MIMExternalModule *external
1245 = (MIMExternalModule *) mplist_get (im_info->externals,
1248 func = (MIMExternalFunc) mplist_get (external->func_list,
1253 func_args = mplist ();
1254 mplist_add (func_args, Mt, ic);
1255 MPLIST_DO (args, MPLIST_NEXT (args))
1259 if (MPLIST_KEY (args) == Msymbol
1260 && MPLIST_KEY (args) != Mnil
1261 && (code = marker_code (MPLIST_SYMBOL (args))) >= 0)
1263 code = new_index (ic, ic->cursor_pos,
1264 mtext_nchars (ic->preedit),
1265 MPLIST_SYMBOL (args), ic->preedit);
1266 mplist_add (func_args, Minteger, (void *) code);
1269 mplist_add (func_args, MPLIST_KEY (args), MPLIST_VAL (args));
1271 val = (func) (func_args);
1272 M17N_OBJECT_UNREF (func_args);
1273 if (val && ! MPLIST_TAIL_P (val))
1274 ret = take_action_list (ic, val);
1275 M17N_OBJECT_UNREF (val);
1279 else if (name == Mshift)
1281 shift_state (ic, MPLIST_SYMBOL (args));
1283 else if (name == Mundo)
1285 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1288 mtext_reset (ic->preedit);
1289 mtext_reset (ic_info->preedit_saved);
1290 ic->cursor_pos = ic_info->state_pos = 0;
1291 ic_info->state_key_head = ic_info->key_head = 0;
1293 if (ic_info->used < 0)
1298 shift_state (ic, ((MIMState *) MPLIST_VAL (im_info->states))->name);
1303 else if (name == Mset || name == Madd || name == Msub
1304 || name == Mmul || name == Mdiv)
1306 MSymbol sym = MPLIST_SYMBOL (args);
1307 int val1 = (int) mplist_get (ic_info->vars, sym), val2;
1309 args = MPLIST_NEXT (args);
1310 val2 = integer_value (ic, args);
1313 else if (name == Madd)
1315 else if (name == Msub)
1317 else if (name == Mmul)
1321 mplist_put (ic_info->vars, sym, (void *) val1);
1322 MDEBUG_PRINT2 ("(%s=%d)", MSYMBOL_NAME (sym), val1);
1324 else if (name == Mequal || name == Mless || name == Mgreater)
1327 MPlist *actions1, *actions2;
1330 val1 = integer_value (ic, args);
1331 args = MPLIST_NEXT (args);
1332 val2 = integer_value (ic, args);
1333 args = MPLIST_NEXT (args);
1334 actions1 = MPLIST_PLIST (args);
1335 args = MPLIST_NEXT (args);
1336 if (MPLIST_TAIL_P (args))
1339 actions2 = MPLIST_PLIST (args);
1340 if (name == Mequal ? val1 == val2
1341 : name == Mless ? val1 < val2
1343 ret = take_action_list (ic, actions1);
1345 ret = take_action_list (ic, actions2);
1351 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1355 && (actions = mplist_get (im_info->macros, name)))
1357 if (take_action_list (ic, actions) < 0)
1364 ic->candidate_list = NULL;
1365 if (ic->cursor_pos > 0
1366 && (prop = mtext_get_property (ic->preedit, ic->cursor_pos - 1,
1369 ic->candidate_list = mtext_property_value (prop);
1371 = (int) mtext_get_prop (ic->preedit, ic->cursor_pos - 1,
1373 ic->candidate_from = mtext_property_start (prop);
1374 ic->candidate_to = mtext_property_end (prop);
1377 ic->candidates_changed |= (candidate_list != ic->candidate_list
1378 || candidate_index != ic->candidate_index
1379 || candidate_show != ic->candidate_show);
1384 /* Handle the input key KEY in the current state and map specified in
1385 the input context IC. If KEY is handled correctly, return 0.
1386 Otherwise, return -1. */
1389 handle_key (MInputContext *ic)
1391 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1392 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1393 MIMMap *map = ic_info->map;
1394 MIMMap *submap = NULL;
1395 MSymbol key = ic_info->keys[ic_info->key_head];
1398 MDEBUG_PRINT2 ("[IM] handle `%s' in state %s",
1399 MSYMBOL_NAME (key), MSYMBOL_NAME (ic_info->state->name));
1403 submap = mplist_get (map->submaps, key);
1404 if (! submap && (key = msymbol_get (key, M_key_alias)) != Mnil)
1405 submap = mplist_get (map->submaps, key);
1410 MDEBUG_PRINT (" submap-found");
1411 mtext_cpy (ic->preedit, ic_info->preedit_saved);
1412 ic->cursor_pos = ic_info->state_pos;
1413 ic_info->key_head++;
1414 ic_info->map = map = submap;
1415 if (map->map_actions)
1417 MDEBUG_PRINT (" map-actions:");
1418 if (take_action_list (ic, map->map_actions) < 0)
1421 else if (map->submaps)
1423 for (i = ic_info->state_key_head; i < ic_info->key_head; i++)
1425 MSymbol key = ic_info->keys[i];
1426 char *name = msymbol_name (key);
1428 if (! name[0] || ! name[1])
1429 mtext_ins_char (ic->preedit, ic->cursor_pos++, name[0], 1);
1431 ic->preedit_changed = 1;
1434 /* If this is the terminal map or we have shifted to another
1435 state, perform branch actions (if any). */
1436 if (! map->submaps || map != ic_info->map)
1438 if (map->branch_actions)
1440 MDEBUG_PRINT (" branch-actions:");
1441 if (take_action_list (ic, map->branch_actions) < 0)
1444 /* If MAP is still not the root map, shift to the current
1446 if (ic_info->map != ic_info->state->map)
1447 shift_state (ic, ic_info->state->name);
1449 MDEBUG_PRINT ("\n");
1453 /* MAP can not handle KEY. */
1455 /* If MAP is the root map of the initial state, it means that
1456 the current input method can not handle KEY. */
1457 if (map == ((MIMState *) MPLIST_VAL (im_info->states))->map)
1459 MDEBUG_PRINT (" unhandled\n");
1463 if (map != ic_info->state->map)
1465 /* If MAP is not the root map... */
1466 /* If MAP has branch actions, perform them. */
1467 if (map->branch_actions)
1469 MDEBUG_PRINT (" branch-actions:");
1470 take_action_list (ic, map->branch_actions);
1472 /* If MAP is still not the root map, shift to the current
1474 if (ic_info->map != ic_info->state->map)
1476 shift_state (ic, ic_info->state->name);
1477 /* If MAP has branch_actions, perform them. */
1478 if (ic_info->map->branch_actions)
1480 MDEBUG_PRINT (" init-actions:");
1481 take_action_list (ic, ic_info->map->branch_actions);
1487 /* MAP is the root map, perform branch actions (if any) or
1488 shift to the initial state. */
1489 if (map->branch_actions)
1491 MDEBUG_PRINT (" branch-actions:");
1492 take_action_list (ic, map->branch_actions);
1496 ((MIMState *) MPLIST_VAL (im_info->states))->name);
1498 MDEBUG_PRINT ("\n");
1504 reset_ic (MInputContext *ic, MSymbol ignore)
1506 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1507 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1509 if (im_info->states)
1510 /* Shift to the initial state. */
1511 shift_state (ic, Mnil);
1513 ic_info->state = NULL;
1514 MLIST_RESET (ic_info);
1515 ic_info->map = ic_info->state ? ic_info->state->map : NULL;
1516 ic_info->state_key_head = ic_info->key_head = 0;
1517 ic_info->key_unhandled = 0;
1518 ic->cursor_pos = ic_info->state_pos = 0;
1519 ic->status = ic_info->state ? ic_info->state->title : NULL;
1521 ic->status = im_info->title;
1522 ic->candidate_list = NULL;
1523 ic->candidate_show = 0;
1524 ic->status_changed = ic->preedit_changed = ic->candidates_changed = 1;
1525 if (ic_info->map && ic_info->map->map_actions)
1526 take_action_list (ic, ic_info->map->map_actions);
1530 open_im (MInputMethod *im)
1533 MInputMethodInfo *im_info;
1537 mdb = mdatabase_find (Minput_method, im->language, im->name, Mnil);
1540 plist = mdatabase_load (mdb);
1542 MERROR (MERROR_IM, -1);
1543 MSTRUCT_CALLOC (im_info, MERROR_IM);
1545 result = load_input_method (im->language, im->name, plist, im_info);
1546 M17N_OBJECT_UNREF (plist);
1548 MERROR (MERROR_IM, -1);
1553 close_im (MInputMethod *im)
1555 MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
1559 M17N_OBJECT_UNREF (im_info->title);
1560 if (im_info->states)
1562 MPLIST_DO (plist, im_info->states)
1564 MIMState *state = (MIMState *) MPLIST_VAL (plist);
1567 M17N_OBJECT_UNREF (state->title);
1569 free_map (state->map);
1572 M17N_OBJECT_UNREF (im_info->states);
1575 if (im_info->macros)
1577 MPLIST_DO (plist, im_info->macros)
1578 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
1579 M17N_OBJECT_UNREF (im_info->macros);
1582 if (im_info->externals)
1584 MPLIST_DO (plist, im_info->externals)
1586 MIMExternalModule *external = MPLIST_VAL (plist);
1588 dlclose (external->handle);
1589 M17N_OBJECT_UNREF (external->func_list);
1591 MPLIST_KEY (plist) = Mt;
1593 M17N_OBJECT_UNREF (im_info->externals);
1601 create_ic (MInputContext *ic)
1603 MInputMethod *im = ic->im;
1604 MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
1605 MInputContextInfo *ic_info;
1608 ic_info = (MInputContextInfo *) ic->info;
1611 MSTRUCT_CALLOC (ic_info, MERROR_IM);
1614 MLIST_INIT1 (ic_info, keys, 8);
1615 ic_info->markers = mplist ();
1616 ic_info->vars = mplist ();
1617 ic_info->preedit_saved = mtext ();
1618 if (im_info->externals)
1620 MPlist *func_args = mplist (), *plist;
1622 mplist_add (func_args, Mt, ic);
1623 MPLIST_DO (plist, im_info->externals)
1625 MIMExternalModule *external = MPLIST_VAL (plist);
1626 MIMExternalFunc func
1627 = (MIMExternalFunc) mplist_get (external->func_list, Minit);
1632 M17N_OBJECT_UNREF (func_args);
1634 reset_ic (ic, Mnil);
1639 destroy_ic (MInputContext *ic)
1641 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1642 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1644 if (im_info->externals)
1646 MPlist *func_args = mplist (), *plist;
1648 mplist_add (func_args, Mt, ic);
1649 MPLIST_DO (plist, im_info->externals)
1651 MIMExternalModule *external = MPLIST_VAL (plist);
1652 MIMExternalFunc func
1653 = (MIMExternalFunc) mplist_get (external->func_list, Mfini);
1658 M17N_OBJECT_UNREF (func_args);
1660 MLIST_FREE1 (ic_info, keys);
1661 M17N_OBJECT_UNREF (ic_info->preedit_saved);
1662 M17N_OBJECT_UNREF (ic_info->markers);
1663 M17N_OBJECT_UNREF (ic_info->vars);
1668 /** Handle the input key KEY in the current state and map of IC->info.
1669 If KEY is handled but no text is produced, return 0, otherwise
1675 filter (MInputContext *ic, MSymbol key, void *arg)
1677 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1678 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1681 if (! ic_info->state)
1683 ic_info->key_unhandled = 1;
1686 mtext_reset (ic->produced);
1687 ic->status_changed = ic->preedit_changed = ic->candidates_changed = 0;
1688 MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
1689 ic_info->key_unhandled = 0;
1691 if (handle_key (ic) < 0)
1693 /* KEY was not handled. Reset the status and break the
1695 reset_ic (ic, Mnil);
1696 /* This forces returning 1. */
1697 ic_info->key_unhandled = 1;
1703 reset_ic (ic, Mnil);
1704 ic_info->key_unhandled = 1;
1707 /* Break the loop if all keys were handled. */
1708 } while (ic_info->key_head < ic_info->used);
1710 /* If the current map is the root of the initial state, we should
1711 produce any preedit text in ic->produced. */
1712 if (ic_info->map == ((MIMState *) MPLIST_VAL (im_info->states))->map
1713 && mtext_nchars (ic->preedit) > 0)
1714 shift_state (ic, ((MIMState *) MPLIST_VAL (im_info->states))->name);
1716 if (mtext_nchars (ic->produced) > 0)
1718 MSymbol lang = msymbol_get (ic->im->language, Mlanguage);
1721 mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
1722 Mlanguage, ic->im->language);
1725 return (! ic_info->key_unhandled && mtext_nchars (ic->produced) == 0);
1729 /** Return 1 if the last event or key was not handled, otherwise
1732 There is no need of looking up because ic->produced should already
1733 contain the produced text (if any).
1738 lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
1740 mtext_cat (mt, ic->produced);
1741 mtext_reset (ic->produced);
1742 return (((MInputContextInfo *) ic->info)->key_unhandled ? -1 : 0);
1745 /* Support functions for mdebug_dump_im. */
1748 dump_im_map (MPlist *map_list, int indent)
1751 MSymbol key = MPLIST_KEY (map_list);
1752 MIMMap *map = (MIMMap *) MPLIST_VAL (map_list);
1754 prefix = (char *) alloca (indent + 1);
1755 memset (prefix, 32, indent);
1756 prefix[indent] = '\0';
1758 fprintf (stderr, "(\"%s\" ", msymbol_name (key));
1759 if (map->map_actions)
1760 mdebug_dump_plist (map->map_actions, indent + 2);
1763 MPLIST_DO (map_list, map->submaps)
1765 fprintf (stderr, "\n%s ", prefix);
1766 dump_im_map (map_list, indent + 2);
1769 if (map->branch_actions)
1771 fprintf (stderr, "\n%s (branch\n%s ", prefix, prefix);
1772 mdebug_dump_plist (map->branch_actions, indent + 4);
1773 fprintf (stderr, ")");
1775 fprintf (stderr, ")");
1780 dump_im_state (MIMState *state, int indent)
1785 prefix = (char *) alloca (indent + 1);
1786 memset (prefix, 32, indent);
1787 prefix[indent] = '\0';
1789 fprintf (stderr, "(%s", msymbol_name (state->name));
1790 if (state->map->submaps)
1792 MPLIST_DO (map_list, state->map->submaps)
1794 fprintf (stderr, "\n%s ", prefix);
1795 dump_im_map (map_list, indent + 2);
1798 fprintf (stderr, ")");
1807 = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1808 "BackSpace", "Tab", "Linefeed", "Clear", NULL, "Return", NULL, NULL,
1809 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1810 NULL, NULL, NULL, "Escape", NULL, NULL, NULL, NULL };
1811 char buf[6], buf2[256];
1814 Minput_method = msymbol ("input-method");
1815 Minput_driver = msymbol ("input-driver");
1816 Mtitle = msymbol ("title");
1817 Mmacro = msymbol ("macro");
1818 Mmodule = msymbol ("module");
1819 Mmap = msymbol ("map");
1820 Mstate = msymbol ("state");
1821 Minsert = msymbol ("insert");
1822 Mdelete = msymbol ("delete");
1823 Mmove = msymbol ("move");
1824 Mmark = msymbol ("mark");
1825 Mpushback = msymbol ("pushback");
1826 Mundo = msymbol ("undo");
1827 Mcall = msymbol ("call");
1828 Mshift = msymbol ("shift");
1829 Mselect = msymbol ("select");
1830 Mshow = msymbol ("show");
1831 Mhide = msymbol ("hide");
1832 Mset = msymbol ("set");
1833 Madd = msymbol ("add");
1834 Msub = msymbol ("sub");
1835 Mmul = msymbol ("mul");
1836 Mdiv = msymbol ("div");
1837 Mequal = msymbol ("=");
1838 Mless = msymbol ("<");
1839 Mgreater = msymbol (">");
1841 Minput_preedit_start = msymbol ("input-preedit-start");
1842 Minput_preedit_done = msymbol ("input-preedit-done");
1843 Minput_preedit_draw = msymbol ("input-preedit-draw");
1844 Minput_status_start = msymbol ("input-status-start");
1845 Minput_status_done = msymbol ("input-status-done");
1846 Minput_status_draw = msymbol ("input-status-draw");
1847 Minput_candidates_start = msymbol ("input-candidates-start");
1848 Minput_candidates_done = msymbol ("input-candidates-done");
1849 Minput_candidates_draw = msymbol ("input-candidates-draw");
1850 Minput_set_spot = msymbol ("input-set-spot");
1851 Minput_toggle = msymbol ("input-toggle");
1852 Minput_reset = msymbol ("input-reset");
1854 Mcandidate_list = msymbol_as_managing_key (" candidate-list");
1855 Mcandidate_index = msymbol (" candidate-index");
1857 Minit = msymbol ("init");
1858 Mfini = msymbol ("fini");
1860 M_key_alias = msymbol (" key-alias");
1865 for (i = 0, buf[2] = '@'; i < ' '; i++, buf[2]++)
1867 one_char_symbol[i] = msymbol (buf);
1869 msymbol_put (one_char_symbol[i], M_key_alias, msymbol (key_names[i]));
1871 for (buf[2] = i; i < 127; i++, buf[2]++)
1872 one_char_symbol[i] = msymbol (buf + 2);
1873 one_char_symbol[i++] = msymbol ("Delete");
1879 for (buf[4] = '@'; i < 160; i++, buf[4]++)
1881 one_char_symbol[i] = msymbol (buf);
1882 if (key_names[i - 128])
1884 strcpy (buf2 + 2, key_names[i - 128]);
1885 msymbol_put (one_char_symbol[i], M_key_alias, msymbol (buf2));
1888 for (buf[4] = i - 128; i < 255; i++, buf[4]++)
1889 one_char_symbol[i] = msymbol (buf + 2);
1890 one_char_symbol[i] = msymbol ("M-Delete");
1892 minput_default_driver.open_im = open_im;
1893 minput_default_driver.close_im = close_im;
1894 minput_default_driver.create_ic = create_ic;
1895 minput_default_driver.destroy_ic = destroy_ic;
1896 minput_default_driver.filter = filter;
1897 minput_default_driver.lookup = lookup;
1898 minput_default_driver.callback_list = mplist ();
1899 mplist_put (minput_default_driver.callback_list, Minput_reset,
1901 minput_driver = &minput_default_driver;
1908 if (minput_default_driver.callback_list)
1910 M17N_OBJECT_UNREF (minput_default_driver.callback_list);
1911 minput_default_driver.callback_list = NULL;
1913 if (minput_driver->callback_list)
1915 M17N_OBJECT_UNREF (minput_driver->callback_list);
1916 minput_driver->callback_list = NULL;
1921 minput__callback (MInputContext *ic, MSymbol command)
1923 if (ic->im->driver.callback_list)
1925 MInputCallbackFunc func
1926 = (MInputCallbackFunc) mplist_get (ic->im->driver.callback_list,
1930 (func) (ic, command);
1935 minput__char_to_key (int c)
1937 if (c < 0 || c >= 0x100)
1940 return one_char_symbol[c];
1944 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1949 /*** @addtogroup m17nInputMethod */
1954 @name Variables: Predefined symbols for callback commands.
1956 These are the predefined symbols that are used as the @c COMMAND
1957 argument of callback functions of an input method driver (see
1958 #MInputDriver::callback_list ). */
1960 @name ÊÑ¿ô¡§ ¥³¡¼¥ë¥Ð¥Ã¥¯¥³¥Þ¥ó¥ÉÍÑÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë.
1962 ÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Î¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Ë¤ª¤¤¤Æ @c COMMAND °ú¿ô¤È¤·
1963 ¤ÆÍѤ¤¤é¤ì¤ëÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë (#MInputDriver::callback_list »²¾È)¡£
1968 MSymbol Minput_preedit_start;
1969 MSymbol Minput_preedit_done;
1970 MSymbol Minput_preedit_draw;
1971 MSymbol Minput_status_start;
1972 MSymbol Minput_status_done;
1973 MSymbol Minput_status_draw;
1974 MSymbol Minput_candidates_start;
1975 MSymbol Minput_candidates_done;
1976 MSymbol Minput_candidates_draw;
1977 MSymbol Minput_set_spot;
1978 MSymbol Minput_toggle;
1979 MSymbol Minput_reset;
1984 @brief The default driver for internal input methods.
1986 The variable #minput_default_driver is the default driver for
1987 internal input methods.
1989 The member MInputDriver::open_im () searches the m17n database for
1990 an input method that matches the tag \< #Minput_method, $LANGUAGE,
1991 $NAME\> and loads it.
1993 The member MInputDriver::callback_list () is @c NULL. Thus, it is
1994 programmers responsibility to set it to a plist of proper callback
1995 functions. Otherwise, no feedback information (e.g. preedit text)
1996 can be shown to users.
1998 The macro M17N_INIT () sets the variable #minput_driver to the
1999 pointer to this driver so that all internal input methods use it.
2001 Therefore, unless @c minput_driver is set differently, the driver
2002 dependent arguments $ARG of the functions whose name begin with
2003 "minput_" are all ignored. */
2006 @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥǥե©¥ë¥È¥É¥é¥¤¥Ð.
2008 ÆþÎϥɥ饤¥Ð #minput_default_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѤΥǥե©¥ë
2009 ¥È¤Î¥É¥é¥¤¥Ð¤Ç¤¢¤ë¡£
2011 ¥á¥ó¥Ð MInputDriver::open_im () ¤Ï m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹Ã椫¤é¥¿¥°
2012 \< #Minput_method, $LANGUAGE, $NAME\> ¤Ë¹çÃפ¹¤ëÆþÎϥ᥽¥Ã¥É¤òõ¤·¡¢
2015 ¥á¥ó¥Ð MInputDriver::callback_list () ¤Ï @c NULL ¤Ê¤Î¤Ç¡¢¥×¥í¥°¥é
2016 ¥Þ¦¤ÇÀÕǤ¤ò»ý¤Ã¤Æ, ŬÀڤʥ³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Î plist ¤ËÀßÄꤷ¤Ê¤¯¤Æ
2017 ¤Ï¤Ê¤é¤Ê¤¤¡£¤µ¤â¤Ê¤¤¤È¡¢preedit ¥Æ¥¥¹¥È¤Ê¤É¤Î¥Õ¥£¡¼¥É¥Ð¥Ã¥¯¾ðÊó¤¬
2018 ¥æ¡¼¥¶¤Ëɽ¼¨¤µ¤ì¤Ê¤¤¡£
2020 ¥Þ¥¯¥í M17N_INIT () ¤ÏÊÑ¿ô #minput_driver ¤ò¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó
2021 ¥¿¤ËÀßÄꤷ¡¢Á´¤Æ¤ÎÆâÉôÆþÎϥ᥽¥Ã¥É¤¬¤³¤Î¥É¥é¥¤¥Ð¤ò»È¤¦¤è¤¦¤Ë¤¹¤ë¡£
2023 ¤·¤¿¤¬¤Ã¤Æ¡¢@c minput_driver ¤¬¥Ç¥Õ¥©¥ë¥ÈÃͤΤޤޤǤ¢¤ì¤Ð¡¢minput_
2024 ¤Ç»Ï¤Þ¤ë´Ø¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô $ARG ¤Ï¤¹¤Ù¤Æ̵»ë¤µ¤ì¤ë¡£ */
2026 MInputDriver minput_default_driver;
2030 @brief The driver for internal input methods.
2032 The variable #minput_driver is a pointer to the input method
2033 driver that is used by internal input methods. The macro
2034 M17N_INIT () initializes it to a pointer to #minput_default_driver
2035 (if <m17n<EM></EM>.h> is included) or to #minput_gui_driver (if
2036 <m17n-gui<EM></EM>.h> is included). */
2038 @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥɥ饤¥Ð.
2040 ÊÑ¿ô #minput_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤Æ»ÈÍѤµ¤ì¤Æ¤¤¤ëÆþÎÏ¥á
2041 ¥½¥Ã¥É¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£¥Þ¥¯¥í M17N_INIT () ¤Ï¤³¤Î¥Ý¥¤¥ó
2042 ¥¿¤ò #minput_default_driver (<m17n<EM></EM>.h> ¤¬´Þ¤Þ¤ì¤ë»þ) ¤Þ¤¿¤Ï
2043 #minput_gui_driver ( <m17n-gui<EM></EM>.h> ¤¬´Þ¤Þ¤ì¤ë»þ) ¤Ë½é´ü²½¤¹
2046 MInputDriver *minput_driver;
2048 MSymbol Minput_driver;
2053 @brief Open an input method.
2055 The minput_open_im () function opens an input method that matches
2056 language $LANGUAGE and name $NAME, and returns a pointer to the
2057 input method object newly allocated.
2059 This function at first decides an driver for the input method as
2062 If $LANGUAGE is not #Mnil, the driver pointed by the variable
2063 #minput_driver is used.
2065 If $LANGUAGE is #Mnil and $NAME has #Minput_driver property, the
2066 driver pointed to by the property value is used to open the input
2067 method. If $NAME has no such property, @c NULL is returned.
2069 Then, the member MInputDriver::open_im () of the driver is
2072 $ARG is set in the member @c arg of the structure MInputMethod so
2073 that the driver can refer to it. */
2076 @brief ÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë.
2078 ´Ø¿ô minput_open_im () ¤Ï¸À¸ì $LANGUAGE ¤È̾Á° $NAME ¤Ë¹çÃפ¹¤ëÆþ
2079 Îϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤·¡¢¿·¤¿¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿ÆþÎϥ᥽¥Ã¥É¥ª¥Ö¥¸¥§¥¯
2080 ¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
2082 ¤³¤Î´Ø¿ô¤Ï¡¢¤Þ¤ºÆþÎϥ᥽¥Ã¥ÉÍѤΥɥ饤¥Ð¤ò°Ê²¼¤Î¤è¤¦¤Ë¤·¤Æ·èÄꤹ¤ë¡£
2084 $LANGUAGE ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢ÊÑ¿ô #minput_driver ¤Ç»Ø¤µ¤ì¤Æ¤¤¤ë
2087 $LANGUAGE ¤¬ #Mnil ¤Ç¤¢¤ê¡¢$NAME ¤¬ #Minput_driver ¥×¥í¥Ñ¥Æ¥£¤ò»ý
2088 ¤Ä¾ì¹ç¤Ë¤Ï¡¢¤½¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤǻؤµ¤ì¤Æ¤¤¤ëÆþÎϥɥ饤¥Ð¤òÍѤ¤¤ÆÆþ
2089 Îϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë¡£$NAME ¤Ë¤½¤Î¤è¤¦¤Ê¥×¥í¥Ñ¥Æ¥£¤¬Ìµ¤«¤Ã¤¿¾ì
2090 ¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
2092 ¼¡¤¤¤Ç¡¢¥É¥é¥¤¥Ð¤Î¥á¥ó¥Ð MInputDriver::open_im () ¤¬¸Æ¤Ð¤ì¤ë¡£
2094 $ARG ¤Ï¡¢¥É¥é¥¤¥Ð¤¬»²¾È¤Ç¤¤ë¤è¤¦¤Ë¡¢¹½Â¤ÂÎ MInputMethod ¤Î¥á¥ó¥Ð
2095 @c arg ¤ËÀßÄꤵ¤ì¤ë¡£
2097 @latexonly \IPAlabel{minput_open} @endlatexonly
2102 minput_open_im (MSymbol language, MSymbol name, void *arg)
2105 MInputDriver *driver;
2108 driver = minput_driver;
2111 driver = (MInputDriver *) msymbol_get (name, Minput_driver);
2113 MERROR (MERROR_IM, NULL);
2116 MSTRUCT_CALLOC (im, MERROR_IM);
2117 im->language = language;
2120 im->driver = *driver;
2121 if ((*im->driver.open_im) (im) < 0)
2132 @brief Close an input method.
2134 The minput_close_im () function closes the input method $IM, which
2135 must have been created by minput_open_im (). */
2138 @brief ÆþÎϥ᥽¥Ã¥É¤ò¥¯¥í¡¼¥º¤¹¤ë.
2140 ´Ø¿ô minput_close_im () ¤Ï¡¢ÆþÎϥ᥽¥Ã¥É $IM ¤ò¥¯¥í¡¼¥º¤¹¤ë¡£¤³¤Î
2141 ÆþÎϥ᥽¥Ã¥É $IM ¤Ï minput_open_im () ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê¤±¤ì
2145 minput_close_im (MInputMethod *im)
2147 (*im->driver.close_im) (im);
2154 @brief Create an input context.
2156 The minput_create_ic () function creates an input context object
2157 associated with input method $IM, and calls callback functions
2158 corresponding to #Minput_preedit_start, #Minput_status_start, and
2159 #Minput_status_draw in this order.
2163 If an input context is successfully created, minput_create_ic ()
2164 returns a pointer to it. Otherwise it returns @c NULL. */
2167 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÀ¸À®¤¹¤ë.
2169 ´Ø¿ô minput_create_ic () ¤ÏÆþÎϥ᥽¥Ã¥É $IM ¤ËÂбþ¤¹¤ëÆþÎÏ¥³¥ó¥Æ¥¯
2170 ¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤·¡¢ #Minput_preedit_start,
2171 #Minput_status_start, #Minput_status_draw ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø
2176 ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤¬À¸À®¤µ¤ì¤¿¾ì¹ç¡¢minput_create_ic () ¤Ï¤½¤ÎÆþÎÏ¥³
2177 ¥ó¥Æ¥¯¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¼ºÇÔ¤·¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
2181 minput_create_ic (MInputMethod *im, void *arg)
2185 MSTRUCT_CALLOC (ic, MERROR_IM);
2188 ic->preedit = mtext ();
2189 ic->candidate_list = NULL;
2190 ic->produced = mtext ();
2191 ic->spot.x = ic->spot.y = 0;
2193 ic->plist = mplist ();
2194 if ((*im->driver.create_ic) (ic) < 0)
2196 M17N_OBJECT_UNREF (ic->preedit);
2197 M17N_OBJECT_UNREF (ic->produced);
2198 M17N_OBJECT_UNREF (ic->plist);
2203 if (im->driver.callback_list)
2205 minput__callback (ic, Minput_preedit_start);
2206 minput__callback (ic, Minput_status_start);
2207 minput__callback (ic, Minput_status_draw);
2216 @brief Destroy an input context.
2218 The minput_destroy_ic () function destroys the input context $IC,
2219 which must have been created by minput_create_ic (). It calls
2220 callback functions corresponding to #Minput_preedit_done,
2221 #Minput_status_done, and #Minput_candidates_done in this order. */
2224 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÇ˲õ¤¹¤ë.
2226 ´Ø¿ô minput_destroy_ic () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤òÇ˲õ¤¹¤ë¡£¤³
2227 ¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ï minput_create_ic () ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê
2228 ¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£¤³¤Î´Ø¿ô¤Ï#Minput_preedit_done,
2229 #Minput_status_done, #Minput_candidates_done ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò
2234 minput_destroy_ic (MInputContext *ic)
2236 if (ic->im->driver.callback_list)
2238 minput__callback (ic, Minput_preedit_done);
2239 minput__callback (ic, Minput_status_done);
2240 minput__callback (ic, Minput_candidates_done);
2242 (*ic->im->driver.destroy_ic) (ic);
2243 M17N_OBJECT_UNREF (ic->preedit);
2244 M17N_OBJECT_UNREF (ic->produced);
2245 M17N_OBJECT_UNREF (ic->plist);
2252 @brief Filter an input key.
2254 The minput_filter () function filters input key $KEY according to
2255 input context $IC, and calls callback functions corresponding to
2256 #Minput_preedit_draw, #Minput_status_draw, and
2257 #Minput_candidates_draw if the preedit text, the status, and the
2258 current candidate are changed respectively.
2261 If $KEY is filtered out, this function returns 1. In that case,
2262 the caller should discard the key. Otherwise, it returns 0, and
2263 the caller should handle the key, for instance, by calling the
2264 function minput_lookup () with the same key. */
2267 @brief ÆþÎÏ¥¡¼¤ò¥Õ¥£¥ë¥¿¤¹¤ë.
2269 ´Ø¿ô minput_filter () ¤ÏÆþÎÏ¥¡¼ $KEY ¤òÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤Ë±þ
2270 ¤¸¤Æ¥Õ¥£¥ë¥¿¤·¡¢preedit ¥Æ¥¥¹¥È¡¢¥¹¥Æ¡¼¥¿¥¹¡¢¸½»þÅÀ¤Ç¤Î¸õÊ䤬ÊѲ½
2271 ¤·¤¿ºÝ¤Ë¤Ï¤½¤ì¤¾¤ì#Minput_preedit_draw, #Minput_status_draw,
2272 #Minput_candidates_draw ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¸Æ¤Ö¡£
2275 $KEY ¤¬¥Õ¥£¥ë¥¿¤µ¤ì¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 1 ¤òÊÖ¤¹¡£¤³¤Î¾ì¹ç¸Æ¤Ó
2276 ½Ð¤·Â¦¤Ï¤³¤Î¥¡¼¤ò¼Î¤Æ¤ë¤Ù¤¤Ç¤¢¤ë¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0 ¤òÊÖ¤·¡¢¸Æ¤Ó
2277 ½Ð¤·Â¦¤Ï¡¢¤¿¤È¤¨¤ÐƱ¤¸¥¡¼¤Ç´Ø¿ô minput_lookup () ¤ò¸Æ¤Ö¤Ê¤É¤·¤Æ¡¢
2278 ¤³¤Î¥¡¼¤ò½èÍý¤¹¤ë¡£
2280 @latexonly \IPAlabel{minput_filter} @endlatexonly
2284 minput_filter (MInputContext *ic, MSymbol key, void *arg)
2291 ret = (*ic->im->driver.filter) (ic, key, arg);
2293 if (ic->im->driver.callback_list)
2295 if (ic->preedit_changed)
2296 minput__callback (ic, Minput_preedit_draw);
2297 if (ic->status_changed)
2298 minput__callback (ic, Minput_status_draw);
2299 if (ic->candidates_changed)
2300 minput__callback (ic, Minput_candidates_draw);
2302 ic->preedit_changed = ic->status_changed = ic->candidates_changed = 0;
2310 @brief Lookup a text produced in the input context.
2312 The minput_lookup () function looks up a text in the input context
2313 $IC. $KEY must be the same one provided to the previous call of
2316 If a text was produced by the input method, it is concatenated
2319 This function calls #MInputDriver::lookup .
2322 If $KEY was correctly handled by the input method, this function
2323 returns 0. Otherwise, returns -1, even in that case, some text
2324 may be produced in $MT. */
2327 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥ÈÃæ¤Î¥Æ¥¥¹¥È¤Î¸¡º÷.
2329 ´Ø¿ô minput_lookup () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC Ãæ¤Î¥Æ¥¥¹¥È¤ò¸¡º÷¤¹
2330 ¤ë¡£$KEY ¤Ï´Ø¿ôminput_filter () ¤Ø¤ÎľÁ°¤Î¸Æ¤Ó½Ð¤·¤ËÍѤ¤¤é¤ì¤¿¤â¤Î
2331 ¤ÈƱ¤¸¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2333 ¥Æ¥¥¹¥È¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆÀ¸À®¤µ¤ì¤Æ¤¤¤ì¤Ð¡¢¥Æ¥¥¹¥È¤Ï M-text
2336 ¤³¤Î´Ø¿ô¤Ï¡¢#MInputDriver::lookup ¤ò¸Æ¤Ö¡£
2339 $KEY ¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆŬÀڤ˽èÍý¤Ç¤¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 0 ¤òÊÖ¤¹¡£
2340 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£¤³¤Î¾ì¹ç¤Ç¤â $MT ¤Ë²¿¤é¤«¤Î¥Æ¥¥¹¥È¤¬À¸
2341 À®¤µ¤ì¤Æ¤¤¤ë¤³¤È¤¬¤¢¤ë¡£
2343 @latexonly \IPAlabel{minput_lookup} @endlatexonly */
2346 minput_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2348 return (ic ? (*ic->im->driver.lookup) (ic, key, arg, mt) : -1);
2353 @brief Set the spot of the input context.
2355 The minput_set_spot () function set the spot of input context $IC
2356 to coordinate ($X, $Y ) with the height $ASCENT and $DESCENT .
2357 The semantics of these values depend on the input method driver.
2358 $FONTSIZE specfies the fontsize of a preedit text in 1/10 point.
2360 For instance, an driver designed to work in CUI environment may
2361 use $X and $Y as column and row numbers, and ignore $ASCENT and
2362 $DESCENT . An driver designed to work on a window system may
2363 treat $X and $Y as pixel offsets relative to the origin of the
2364 client window, and treat $ASCENT and $DESCENT as ascent and
2365 descent pixels of a line at ($X . $Y ).
2367 $MT and $POS is an M-text and a character position at the spot.
2368 $MT may be @c NULL, in which case, the input method cannot get
2369 information about the text around the spot. */
2372 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Î¥¹¥Ý¥Ã¥È¤òÀßÄꤹ¤ë
2374 ´Ø¿ô minput_set_spot () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤Î¥¹¥Ý¥Ã¥È¤ò¡¢ºÂ
2375 ɸ ($X, $Y )¤Ë ¡¢¹â¤µ $ASCENT¡¢ $DESCENT ¤ÇÀßÄꤹ¤ë¡£ ¤³¤ì¤é¤ÎÃͤÎ
2376 °ÕÌ£¤ÏÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë¡£$FONTSIZE ¤Ïpreedit ¥Æ¥¥¹¥È
2377 ¤Î¥Õ¥©¥ó¥È¥µ¥¤¥º¤ò 1/10 ¥Ý¥¤¥ó¥Èñ°Ì¤Ç»ØÄꤹ¤ë¡£
2379 ¤¿¤È¤¨¤Ð CUI ´Ä¶¤ÇÆ°ºî¤¹¤ë¥É¥é¥¤¥Ð¤Ï $X ¤È $Y ¤ò¤½¤ì¤¾¤ìÎó¤È¹Ô¤Î
2380 ÈÖ¹æ¤È¤·¤ÆÍѤ¤¡¢$ASCENT ¤È $DESCENT ¤ò̵»ë¤¹¤ë¤«¤â¤·¤ì¤Ê¤¤¡£ ¤Þ¤¿
2381 ¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥àÍѤΥɥ饤¥Ð¤Ï $X ¤È $Y ¤ò¥¯¥é¥¤¥¢¥ó¥È¥¦¥£¥ó¥É¥¦
2382 ¤Î¸¶ÅÀ¤«¤é¤Î¥ª¥Õ¥»¥Ã¥È¤ò¥Ô¥¯¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¤¡¢
2383 $ASCENT ¤È $DESCENT ¤ò ($X . $Y ) ¤ÎÎó¤Î¥¢¥»¥ó¥È¤È¥Ç¥£¥»¥ó¥È¤ò¥Ô¥¯
2384 ¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¦¤«¤â¤·¤ì¤Ê¤¤¡£
2386 $MT ¤È $POS ¤Ï¤½¤Î¥¹¥Ý¥Ã¥È¤Î M-text ¤Èʸ»ú°ÌÃ֤Ǥ¢¤ë¡£$MT ¤Ï @c
2387 NULL ¤Ç¤â¤è¤¯¡¢¤½¤Î¾ì¹ç¤Ë¤ÏÆþÎϥ᥽¥Ã¥É¤Ï¥¹¥Ý¥Ã¥È¼þÊդΥƥ¥¹¥È¤Ë
2388 ´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë¤³¤È¤¬¤Ç¤¤Ê¤¤¡£
2392 minput_set_spot (MInputContext *ic, int x, int y,
2393 int ascent, int descent, int fontsize,
2398 ic->spot.ascent = ascent;
2399 ic->spot.descent = descent;
2400 ic->spot.fontsize = fontsize;
2403 if (ic->im->driver.callback_list)
2404 minput__callback (ic, Minput_set_spot);
2409 @brief Toggle input method.
2411 The minput_toggle () function toggles the input method associated
2412 with the input context $IC. */
2414 @brief ÆþÎϥ᥽¥Ã¥É¤òÀÚÂؤ¨¤ë.
2416 ´Ø¿ô minput_toggle () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤ËÂбþÉÕ¤±¤é¤ì¤¿ÆþÎÏ
2417 ¥á¥½¥Ã¥É¤ò¥È¥°¥ë¤¹¤ë¡£
2421 minput_toggle (MInputContext *ic)
2423 if (ic->im->driver.callback_list)
2424 minput__callback (ic, Minput_toggle);
2425 ic->active = ! ic->active;
2429 @brief Reset an input context.
2431 The minput_reset_ic () function resets the input context $IC by
2432 calling a callback functions corresponding to #Minput_reset. It
2433 actually shifts the state to the initial one, and thus the current
2434 preediting text (if any) is committed. If necessary, a program
2435 can extract that text by calling minput_lookup () just after the
2436 call of minput_reset_ic (). In that case, the arguments @c KEY
2437 and @c ARG of minput_lookup () are ignored. */
2439 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤ò¥ê¥»¥Ã¥È¤¹¤ë.
2441 ´Ø¿ô minput_reset_ic () ¤Ï #Minput_reset ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô
2442 ¤ò¸Æ¤Ö¤³¤È¤Ë¤è¤Ã¤ÆÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤ò¥ê¥»¥Ã¥È¤¹¤ë¡£¤³¤ì¤Ï¼ÂºÝ¤Ï
2443 ÆþÎϥ᥽¥Ã¥É¤ò½é´ü¾õÂ֤˥·¥Õ¥È¤µ¤»¤ë¡£¤·¤¿¤¬¤Ã¤Æ¡¢¤â¤·¸½ºßÆþÎÏÃæ¤Î
2444 ¥Æ¥¥¹¥È¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤Ï¥³¥ß¥Ã¥È¤µ¤ì¤ë¡£É¬Íפʤ饢¥×¥ê¥±¡¼¥·¥ç¥ó¥×
2445 ¥í¥°¥é¥à¤Ï minput_lookup () ¤òÆɤó¤Ç¤½¤Î¥Æ¥¥¹¥È¤ò¼è¤ê½Ð¤»¤ë¡£¤½¤Î
2446 ºÝ¡¢minput_lookup () ¤Î°ú¿ô @c KEY ¤È @c ARG ¤Ï̵»ë¤µ¤ì¤ë¡£ */
2448 minput_reset_ic (MInputContext *ic)
2450 if (ic->im->driver.callback_list)
2451 minput__callback (ic, Minput_reset);
2457 /*** @addtogroup m17nDebug */
2463 @brief Dump an input method.
2465 The mdebug_dump_im () function prints the input method $IM in a
2466 human readable way to the stderr. $INDENT specifies how many
2467 columns to indent the lines but the first one.
2470 This function returns $IM. */
2472 @brief ÆþÎϥ᥽¥Ã¥É¤ò¥À¥ó¥×¤¹¤ë.
2474 ´Ø¿ô mdebug_dump_im () ¤ÏÆþÎϥ᥽¥Ã¥É $IM ¤ò stderr ¤Ë¿Í´Ö¤Ë²ÄÆɤÊ
2475 ·Á¤Ç°õºþ¤¹¤ë¡£$INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£
2478 ¤³¤Î´Ø¿ô¤Ï $IM ¤òÊÖ¤¹¡£ */
2481 mdebug_dump_im (MInputMethod *im, int indent)
2483 MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
2486 prefix = (char *) alloca (indent + 1);
2487 memset (prefix, 32, indent);
2488 prefix[indent] = '\0';
2490 fprintf (stderr, "(input-method %s %s ", msymbol_name (im->language),
2491 msymbol_name (im->name));
2492 mdebug_dump_mtext (im_info->title, 0, 0);
2493 if (im->name != Mnil)
2497 MPLIST_DO (state, im_info->states)
2499 fprintf (stderr, "\n%s ", prefix);
2500 dump_im_state (MPLIST_VAL (state), indent + 2);
2503 fprintf (stderr, ")");