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 MSymbol Minput_method;
161 /** Symbols to load an input method data. */
162 static MSymbol Mtitle, Mmacro, Mmodule, Mstate;
164 /** Symbols for actions. */
165 static MSymbol Minsert, Mdelete, Mmark, Mmove, Mpushback, Mundo, Mcall, Mshift;
166 static MSymbol Mselect, Mshow, Mhide;
167 static MSymbol Mset, Madd, Msub, Mmul, Mdiv, Mequal, Mless, Mgreater;
169 static MSymbol Mcandidate_list, Mcandidate_index;
171 static MSymbol Minit, Mfini;
173 /** Symbols for key events. */
174 static MSymbol one_char_symbol[256];
176 static MSymbol M_key_alias;
178 /** Structure to hold a map. */
182 /** List of actions to take when we reach the map. In a root map,
183 the actions are executed only when there's no more key. */
186 /** List of deeper maps. If NULL, this is a terminal map. */
189 /** List of actions to take when we leave the map successfully. In
190 a root map, the actions are executed only when none of submaps
191 handle the current key. */
192 MPlist *branch_actions;
195 typedef MPlist *(*MIMExternalFunc) (MPlist *plist);
200 MPlist *func_list; /* function name vs (MIMExternalFunc *) */
205 /** Name of the state. */
208 /** Title of the state, or NULL. */
211 /** Key translation map of the state. Built by merging all maps of
218 marker_code (MSymbol sym)
224 name = MSYMBOL_NAME (sym);
225 return ((name[0] == '@'
226 && ((name[1] >= '0' && name[1] <= '9')
227 || name[1] == '<' || name[1] == '>'
228 || name[1] == '=' || name[1] == '+' || name[1] == '-'
229 || name[1] == '[' || name[1] == ']')
235 integer_value (MInputContext *ic, MPlist *arg)
237 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
239 MText *preedit = ic->preedit;
240 int len = mtext_nbytes (preedit);
242 if (MPLIST_INTEGER_P (arg))
243 return MPLIST_INTEGER (arg);
244 code = marker_code (MPLIST_SYMBOL (arg));
246 return (int) mplist_get (ic_info->vars, MPLIST_SYMBOL (arg));
247 if (code >= '0' && code <= '9')
249 else if (code == '=')
250 code = ic->cursor_pos;
251 else if (code == '-' || code == '[')
252 code = ic->cursor_pos - 1;
253 else if (code == '+' || code == ']')
254 code = ic->cursor_pos + 1;
255 else if (code == '<')
257 else if (code == '<')
259 return (code >= 0 && code < len ? mtext_ref_char (preedit, code) : -1);
263 /* Parse PLIST as an action list while modifying the list to regularize
264 actions. PLIST should have this form:
265 PLIST ::= ( (ACTION-NAME ACTION-ARG *) *).
266 Return 0 if successfully parsed, otherwise return -1. */
269 parse_action_list (MPlist *plist, MPlist *macros)
271 MPLIST_DO (plist, plist)
273 if (MPLIST_MTEXT_P (plist))
275 /* This is a short form of (insert MTEXT). */
276 /* if (mtext_nchars (MPLIST_MTEXT (plist)) == 0)
277 MERROR (MERROR_IM, -1); */
279 else if (MPLIST_PLIST_P (plist)
280 && (MPLIST_MTEXT_P (MPLIST_PLIST (plist))
281 || MPLIST_PLIST_P (MPLIST_PLIST (plist))))
285 /* This is a short form of (insert (GROUPS *)). */
286 MPLIST_DO (pl, MPLIST_PLIST (plist))
288 if (MPLIST_PLIST_P (pl))
292 MPLIST_DO (elt, MPLIST_PLIST (pl))
293 if (! MPLIST_MTEXT_P (elt)
294 || mtext_nchars (MPLIST_MTEXT (elt)) == 0)
295 MERROR (MERROR_IM, -1);
299 if (! MPLIST_MTEXT_P (pl)
300 || mtext_nchars (MPLIST_MTEXT (pl)) == 0)
301 MERROR (MERROR_IM, -1);
305 else if (MPLIST_INTEGER_P (plist))
307 int c = MPLIST_INTEGER (plist);
309 if (c < 0 || c > MCHAR_MAX)
310 MERROR (MERROR_IM, -1);
312 else if (MPLIST_PLIST_P (plist)
313 && MPLIST_SYMBOL_P (MPLIST_PLIST (plist)))
315 MPlist *pl = MPLIST_PLIST (plist);
316 MSymbol action_name = MPLIST_SYMBOL (pl);
318 pl = MPLIST_NEXT (pl);
320 if (action_name == Minsert)
322 if (MPLIST_MTEXT_P (pl))
324 if (mtext_nchars (MPLIST_MTEXT (pl)) == 0)
325 MERROR (MERROR_IM, -1);
327 else if (MPLIST_PLIST_P (pl))
331 if (MPLIST_PLIST_P (pl))
335 MPLIST_DO (elt, MPLIST_PLIST (pl))
336 if (! MPLIST_MTEXT_P (elt)
337 || mtext_nchars (MPLIST_MTEXT (elt)) == 0)
338 MERROR (MERROR_IM, -1);
342 if (! MPLIST_MTEXT_P (pl)
343 || mtext_nchars (MPLIST_MTEXT (pl)) == 0)
344 MERROR (MERROR_IM, -1);
348 else if (! MPLIST_SYMBOL_P (pl))
349 MERROR (MERROR_IM, -1);
351 else if (action_name == Mselect
352 || action_name == Mdelete
353 || action_name == Mmove)
355 if (! MPLIST_SYMBOL_P (pl)
356 && ! MPLIST_INTEGER_P (pl))
357 MERROR (MERROR_IM, -1);
359 else if (action_name == Mmark
360 || action_name == Mcall
361 || action_name == Mshift)
363 if (! MPLIST_SYMBOL_P (pl))
364 MERROR (MERROR_IM, -1);
366 else if (action_name == Mshow || action_name == Mhide
367 || action_name == Mundo)
369 if (! MPLIST_TAIL_P (pl))
370 MERROR (MERROR_IM, -1);
372 else if (action_name == Mpushback)
374 if (! MPLIST_INTEGER_P (pl))
375 MERROR (MERROR_IM, -1);
377 else if (action_name == Mset || action_name == Madd
378 || action_name == Msub || action_name == Mmul
379 || action_name == Mdiv)
381 if (! (MPLIST_SYMBOL_P (pl)
382 && (MPLIST_INTEGER_P (MPLIST_NEXT (pl))
383 || MPLIST_SYMBOL_P (MPLIST_NEXT (pl)))))
384 MERROR (MERROR_IM, -1);
386 else if (action_name == Mequal || action_name == Mless
387 || action_name == Mgreater)
389 if (! ((MPLIST_INTEGER_P (pl) || MPLIST_SYMBOL_P (pl))
390 && (MPLIST_INTEGER_P (MPLIST_NEXT (pl))
391 || MPLIST_SYMBOL_P (MPLIST_NEXT (pl)))))
392 MERROR (MERROR_IM, -1);
393 pl = MPLIST_NEXT (MPLIST_NEXT (pl));
394 if (! MPLIST_PLIST_P (pl))
395 MERROR (MERROR_IM, -1);
396 if (parse_action_list (MPLIST_PLIST (pl), macros) < 0)
397 MERROR (MERROR_IM, -1);
398 pl = MPLIST_NEXT (pl);
399 if (MPLIST_PLIST_P (pl)
400 && parse_action_list (MPLIST_PLIST (pl), macros) < 0)
401 MERROR (MERROR_IM, -1);
403 else if (! macros || ! mplist_get (macros, action_name))
404 MERROR (MERROR_IM, -1);
407 MERROR (MERROR_IM, -1);
414 /* Load a translation into MAP from PLIST.
416 PLIST ::= ( KEYSEQ MAP-ACTION * ) */
419 load_translation (MIMMap *map, MPlist *plist, MPlist *branch_actions,
425 if (MPLIST_MTEXT_P (plist))
427 MText *mt = MPLIST_MTEXT (plist);
429 len = mtext_nchars (mt);
430 if (len == 0 || len != mtext_nbytes (mt))
431 MERROR (MERROR_IM, -1);
432 keyseq = (MSymbol *) alloca (sizeof (MSymbol) * len);
433 for (i = 0; i < len; i++)
434 keyseq[i] = one_char_symbol[MTEXT_DATA (mt)[i]];
436 else if (MPLIST_PLIST_P (plist))
438 MPlist *elt = MPLIST_PLIST (plist);
440 len = MPLIST_LENGTH (elt);
442 MERROR (MERROR_IM, -1);
443 keyseq = (MSymbol *) alloca (sizeof (int) * len);
444 for (i = 0; i < len; i++, elt = MPLIST_NEXT (elt))
446 if (MPLIST_INTEGER_P (elt))
448 int c = MPLIST_INTEGER (elt);
450 if (c < 0 || c >= 0x100)
451 MERROR (MERROR_IM, -1);
452 keyseq[i] = one_char_symbol[c];
454 else if (MPLIST_SYMBOL_P (elt))
455 keyseq[i] = MPLIST_SYMBOL (elt);
457 MERROR (MERROR_IM, -1);
461 MERROR (MERROR_IM, -1);
463 for (i = 0; i < len; i++)
465 MIMMap *deeper = NULL;
468 deeper = mplist_get (map->submaps, keyseq[i]);
470 map->submaps = mplist ();
473 /* Fixme: It is better to make all deeper maps at once. */
474 MSTRUCT_CALLOC (deeper, MERROR_IM);
475 mplist_put (map->submaps, keyseq[i], deeper);
480 /* We reach a terminal map. */
482 || map->branch_actions)
483 /* This map is already defined. We avoid overriding it. */
486 plist = MPLIST_NEXT (plist);
487 if (! MPLIST_TAIL_P (plist))
489 if (parse_action_list (plist, macros) < 0)
490 MERROR (MERROR_IM, -1);
491 map->map_actions = plist;
492 M17N_OBJECT_REF (plist);
496 map->branch_actions = branch_actions;
497 M17N_OBJECT_REF (branch_actions);
503 /* Load a branch from PLIST into MAP. PLIST has this form:
504 PLIST ::= ( MAP-NAME BRANCH-ACTION * )
505 MAPS is a plist of raw maps.
506 STATE is the current state. */
509 load_branch (MPlist *plist, MPlist *maps, MIMMap *map, MPlist *macros)
512 MPlist *branch_actions;
514 if (! MPLIST_SYMBOL_P (plist))
515 MERROR (MERROR_IM, -1);
516 map_name = MPLIST_SYMBOL (plist);
517 plist = MPLIST_NEXT (plist);
518 if (MPLIST_TAIL_P (plist))
519 branch_actions = NULL;
520 else if (parse_action_list (plist, macros) < 0)
521 MERROR (MERROR_IM, -1);
523 branch_actions = plist;
524 if (map_name == Mnil)
526 map->branch_actions = branch_actions;
528 M17N_OBJECT_REF (branch_actions);
530 else if (map_name == Mt)
532 map->map_actions = branch_actions;
534 M17N_OBJECT_REF (branch_actions);
538 plist = (MPlist *) mplist_get (maps, map_name);
539 if (! plist || ! MPLIST_PLIST_P (plist))
540 MERROR (MERROR_IM, -1);
541 MPLIST_DO (plist, plist)
542 if (! MPLIST_PLIST_P (plist)
543 || (load_translation (map, MPLIST_PLIST (plist), branch_actions,
546 MERROR (MERROR_IM, -1);
552 /* Load a macro from PLIST into MACROS.
554 PLIST ::= ( MACRO-NAME ACTION * )
555 MACROS is a plist of macro names vs action list. */
557 load_macros (MPlist *plist, MPlist *macros)
561 if (! MPLIST_SYMBOL_P (plist))
562 MERROR (MERROR_IM, -1);
563 name = MPLIST_SYMBOL (plist);
564 plist = MPLIST_NEXT (plist);
565 if (MPLIST_TAIL_P (plist)
566 || parse_action_list (plist, macros) < 0)
567 MERROR (MERROR_IM, -1);
568 mplist_put (macros, name, plist);
569 M17N_OBJECT_REF (plist);
573 /* Load an external module from PLIST into EXTERNALS.
575 PLIST ::= ( MODULE-NAME FUNCTION * )
576 EXTERNALS is a plist of MODULE-NAME vs (MIMExternalModule *). */
578 #ifndef DLOPEN_SHLIB_EXT
579 #define DLOPEN_SHLIB_EXT ".so"
583 load_external_module (MPlist *plist, MPlist *externals)
588 MIMExternalModule *external;
592 if (MPLIST_MTEXT_P (plist))
593 module = msymbol ((char *) MTEXT_DATA (MPLIST_MTEXT (plist)));
594 else if (MPLIST_SYMBOL_P (plist))
595 module = MPLIST_SYMBOL (plist);
596 module_file = alloca (strlen (MSYMBOL_NAME (module))
597 + strlen (DLOPEN_SHLIB_EXT) + 1);
598 sprintf (module_file, "%s%s", MSYMBOL_NAME (module), DLOPEN_SHLIB_EXT);
600 handle = dlopen (module_file, RTLD_NOW);
603 fprintf (stderr, "%s\n", dlerror ());
604 MERROR (MERROR_IM, -1);
606 func_list = mplist ();
607 MPLIST_DO (plist, MPLIST_NEXT (plist))
609 if (! MPLIST_SYMBOL_P (plist))
610 MERROR_GOTO (MERROR_IM, err_label);
611 func = dlsym (handle, MSYMBOL_NAME (MPLIST_SYMBOL (plist)));
613 MERROR_GOTO (MERROR_IM, err_label);
614 mplist_add (func_list, MPLIST_SYMBOL (plist), func);
617 MSTRUCT_MALLOC (external, MERROR_IM);
618 external->handle = handle;
619 external->func_list = func_list;
620 mplist_add (externals, module, external);
625 M17N_OBJECT_UNREF (func_list);
630 /** Load a state from PLIST into a newly allocated state object.
632 PLIST ::= ( STATE-NAME STATE-TITLE ? BRANCH * )
633 BRANCH ::= ( MAP-NAME BRANCH-ACTION * )
634 MAPS is a plist of defined maps.
635 Return the state object. */
638 load_state (MPlist *plist, MPlist *maps, MSymbol language, MPlist *macros)
642 MSTRUCT_CALLOC (state, MERROR_IM);
643 if (! MPLIST_SYMBOL_P (plist))
644 MERROR (MERROR_IM, NULL);
645 state->name = MPLIST_SYMBOL (plist);
646 plist = MPLIST_NEXT (plist);
647 if (MPLIST_MTEXT_P (plist))
649 state->title = MPLIST_MTEXT (plist);
650 mtext_put_prop (state->title, 0, mtext_nchars (state->title),
651 Mlanguage, language);
652 M17N_OBJECT_REF (state->title);
653 plist = MPLIST_NEXT (plist);
655 MSTRUCT_CALLOC (state->map, MERROR_IM);
656 MPLIST_DO (plist, plist)
657 if (! MPLIST_PLIST_P (plist)
658 || load_branch (MPLIST_PLIST (plist), maps, state->map, macros) < 0)
659 MERROR (MERROR_IM, NULL);
665 free_map (MIMMap *map)
669 M17N_OBJECT_UNREF (map->map_actions);
672 MPLIST_DO (plist, map->submaps)
673 free_map ((MIMMap *) MPLIST_VAL (plist));
674 M17N_OBJECT_UNREF (map->submaps);
676 M17N_OBJECT_UNREF (map->branch_actions);
680 /* Load an input method from PLIST into IM_INTO, and return it. */
683 load_input_method (MSymbol language, MSymbol name, MPlist *plist,
684 MInputMethodInfo *im_info)
688 MPlist *states = NULL;
689 MPlist *externals = NULL;
690 MPlist *macros = NULL;
693 if (! MPLIST_PLIST_P (plist))
694 MERROR (MERROR_IM, -1);
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);
754 MPLIST_DO (elt, maps)
755 M17N_OBJECT_UNREF (MPLIST_VAL (elt));
756 M17N_OBJECT_UNREF (maps);
758 title = mtext_from_data (MSYMBOL_NAME (name), MSYMBOL_NAMELEN (name),
759 MTEXT_FORMAT_US_ASCII);
760 im_info->title = title;
761 im_info->externals = externals;
762 im_info->macros = macros;
763 im_info->states = states;
769 MPLIST_DO (elt, maps)
770 M17N_OBJECT_UNREF (MPLIST_VAL (elt));
771 M17N_OBJECT_UNREF (maps);
774 M17N_OBJECT_UNREF (title);
777 MPLIST_DO (plist, states)
779 MIMState *state = (MIMState *) MPLIST_VAL (plist);
782 M17N_OBJECT_UNREF (state->title);
784 free_map (state->map);
787 M17N_OBJECT_UNREF (states);
791 MPLIST_DO (plist, externals)
793 MIMExternalModule *external = MPLIST_VAL (plist);
795 dlclose (external->handle);
796 M17N_OBJECT_UNREF (external->func_list);
798 MPLIST_KEY (plist) = Mt;
800 M17N_OBJECT_UNREF (externals);
807 static int take_action_list (MInputContext *ic, MPlist *action_list);
810 shift_state (MInputContext *ic, MSymbol state_name)
812 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
813 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
814 MIMState *state = ic_info->state;
816 /* Find a state to shift to. If not found, shift to the initial
818 state = (MIMState *) mplist_get (im_info->states, state_name);
820 state = (MIMState *) MPLIST_VAL (im_info->states);
822 /* Enter the new state. */
823 ic_info->state = state;
824 ic_info->map = state->map;
825 ic_info->state_key_head = ic_info->key_head;
826 if (state == (MIMState *) MPLIST_VAL (im_info->states))
828 /* We have shifted to the initial state. */
831 mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit),
832 Mcandidate_list, NULL, 0);
833 mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit),
834 Mcandidate_index, NULL, 0);
835 mtext_cat (ic->produced, ic->preedit);
836 mtext_reset (ic->preedit);
837 ic->candidate_list = NULL;
838 ic->candidate_show = 0;
839 ic->preedit_changed = ic->candidates_changed = 1;
840 MPLIST_DO (p, ic_info->markers)
842 MPLIST_DO (p, ic_info->vars)
845 memmove (ic_info->keys, ic_info->keys + ic_info->state_key_head,
846 sizeof (int) * (ic_info->used - ic_info->state_key_head));
847 ic_info->used -= ic_info->state_key_head;
848 ic_info->state_key_head = ic_info->key_head = 0;
850 mtext_cpy (ic_info->preedit_saved, ic->preedit);
851 ic_info->state_pos = ic->cursor_pos;
852 ic->status = state->title;
854 ic->status = im_info->title;
855 ic->status_changed = 1;
856 if (ic_info->key_head == ic_info->used
857 && ic_info->map == ic_info->state->map
858 && ic_info->map->map_actions)
859 take_action_list (ic, ic_info->map->map_actions);
864 find_candidates_group (MPlist *plist, int index,
865 int *start_index, int *end_index, int *group_index)
867 int i = 0, gidx = 0, len;
869 MPLIST_DO (plist, plist)
871 if (MPLIST_MTEXT_P (plist))
872 len = mtext_nchars (MPLIST_MTEXT (plist));
874 len = mplist_length (MPLIST_PLIST (plist));
880 *end_index = i + len;
892 preedit_insert (MInputContext *ic, int pos, MText *mt, int c)
894 MInputContextInfo *ic_info = ((MInputContext *) ic)->info;
896 int nchars = mt ? mtext_nchars (mt) : 1;
899 mtext_ins (ic->preedit, pos, mt);
901 mtext_ins_char (ic->preedit, pos, c, 1);
902 MPLIST_DO (markers, ic_info->markers)
903 if (MPLIST_INTEGER (markers) > pos)
904 MPLIST_VAL (markers) = (void *) (MPLIST_INTEGER (markers) + nchars);
905 if (ic->cursor_pos >= pos)
906 ic->cursor_pos += nchars;
907 ic->preedit_changed = 1;
912 preedit_delete (MInputContext *ic, int from, int to)
914 MInputContextInfo *ic_info = ((MInputContext *) ic)->info;
917 mtext_del (ic->preedit, from, to);
918 MPLIST_DO (markers, ic_info->markers)
920 if (MPLIST_INTEGER (markers) > to)
922 = (void *) (MPLIST_INTEGER (markers) - (to - from));
923 else if (MPLIST_INTEGER (markers) > from);
924 MPLIST_VAL (markers) = (void *) from;
926 if (ic->cursor_pos >= to)
927 ic->cursor_pos -= to - from;
928 else if (ic->cursor_pos > from)
929 ic->cursor_pos = from;
930 ic->preedit_changed = 1;
935 new_index (MInputContext *ic, int current, int limit, MSymbol sym, MText *mt)
937 int code = marker_code (sym);
939 if (mt && (code == '[' || code == ']'))
943 if (code == '[' && current > 0)
945 if (mtext_prop_range (mt, Mcandidate_list, pos - 1, &pos, NULL, 1)
949 else if (code == ']' && current < mtext_nchars (mt))
951 if (mtext_prop_range (mt, Mcandidate_list, pos, NULL, &pos, 1))
957 return (code == '<' ? 0
958 : code == '>' ? limit
959 : code == '-' ? current - 1
960 : code == '+' ? current + 1
961 : code == '=' ? current
962 : code - '0' > limit ? limit
966 return (int) mplist_get (((MInputContextInfo *) ic->info)->markers, sym);
970 udpate_candidate (MInputContext *ic, MTextProperty *prop, int idx)
972 int from = mtext_property_start (prop);
973 int to = mtext_property_end (prop);
975 MPlist *candidate_list = mtext_property_value (prop);
976 MPlist *group = find_candidates_group (candidate_list, idx, &start,
978 int ingroup_index = idx - start;
981 preedit_delete (ic, from, to);
982 if (MPLIST_MTEXT_P (group))
984 mt = MPLIST_MTEXT (group);
985 preedit_insert (ic, from, NULL, mtext_ref_char (mt, ingroup_index));
993 for (i = 0, plist = MPLIST_PLIST (group); i < ingroup_index;
994 i++, plist = MPLIST_NEXT (plist));
995 mt = MPLIST_MTEXT (plist);
996 preedit_insert (ic, from, mt, 0);
997 to = from + mtext_nchars (mt);
999 mtext_put_prop (ic->preedit, from, to, Mcandidate_list, candidate_list);
1000 mtext_put_prop (ic->preedit, from, to, Mcandidate_index, (void *) idx);
1001 ic->cursor_pos = to;
1006 take_action_list (MInputContext *ic, MPlist *action_list)
1008 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1009 MPlist *candidate_list = ic->candidate_list;
1010 int candidate_index = ic->candidate_index;
1011 int candidate_show = ic->candidate_show;
1012 MTextProperty *prop;
1014 MPLIST_DO (action_list, action_list)
1020 if (MPLIST_MTEXT_P (action_list)
1021 || MPLIST_INTEGER_P (action_list))
1022 name = Minsert, args = action_list;
1023 else if (MPLIST_PLIST_P (action_list)
1024 && (MPLIST_MTEXT_P (MPLIST_PLIST (action_list))
1025 || MPLIST_PLIST_P (MPLIST_PLIST (action_list))))
1026 name = Minsert, args = action_list;
1029 action = MPLIST_PLIST (action_list);
1030 name = MPLIST_SYMBOL (action);
1031 args = MPLIST_NEXT (action);
1034 if (name == Minsert)
1036 if (MPLIST_MTEXT_P (args))
1037 preedit_insert (ic, ic->cursor_pos, MPLIST_MTEXT (args), 0);
1038 else if (MPLIST_INTEGER_P (args))
1039 preedit_insert (ic, ic->cursor_pos, NULL, MPLIST_INTEGER (args));
1040 else if (MPLIST_SYMBOL_P (args))
1042 int c = integer_value (ic, args);
1044 if (c >= 0 && c <= MCHAR_MAX)
1045 preedit_insert (ic, ic->cursor_pos, NULL, c);
1052 args = MPLIST_PLIST (args);
1053 if (MPLIST_MTEXT_P (args))
1055 preedit_insert (ic, ic->cursor_pos, NULL,
1056 mtext_ref_char (MPLIST_MTEXT (args), 0));
1061 mt = MPLIST_MTEXT (MPLIST_PLIST (args));
1062 preedit_insert (ic, ic->cursor_pos, mt, 0);
1063 len = mtext_nchars (mt);
1065 mtext_put_prop (ic->preedit,
1066 ic->cursor_pos - len, ic->cursor_pos,
1067 Mcandidate_list, args);
1068 mtext_put_prop (ic->preedit,
1069 ic->cursor_pos - len, ic->cursor_pos,
1070 Mcandidate_index, (void *) 0);
1073 else if (name == Mselect)
1076 int code, idx, gindex;
1077 int pos = ic->cursor_pos;
1081 || ! (prop = mtext_get_property (ic->preedit, pos - 1,
1084 if (MPLIST_SYMBOL_P (args))
1086 code = marker_code (MPLIST_SYMBOL (args));
1092 idx = (int) mtext_get_prop (ic->preedit, pos - 1, Mcandidate_index);
1093 group = find_candidates_group (mtext_property_value (prop), idx,
1094 &start, &end, &gindex);
1096 if (code != '[' && code != ']')
1100 ? new_index (NULL, ic->candidate_index - start,
1101 end - start - 1, MPLIST_SYMBOL (args),
1103 : MPLIST_INTEGER (args)));
1106 && MPLIST_TAIL_P (MPLIST_NEXT (group))))
1111 int ingroup_index = idx - start;
1114 group = mtext_property_value (prop);
1115 len = mplist_length (group);
1128 for (idx = 0; gindex > 0; gindex--, group = MPLIST_NEXT (group))
1129 idx += (MPLIST_MTEXT_P (group)
1130 ? mtext_nchars (MPLIST_MTEXT (group))
1131 : mplist_length (MPLIST_PLIST (group)));
1132 len = (MPLIST_MTEXT_P (group)
1133 ? mtext_nchars (MPLIST_MTEXT (group))
1134 : mplist_length (MPLIST_PLIST (group)));
1135 if (ingroup_index >= len)
1136 ingroup_index = len - 1;
1137 idx += ingroup_index;
1139 udpate_candidate (ic, prop, idx);
1141 else if (name == Mshow)
1142 ic->candidate_show = 1;
1143 else if (name == Mhide)
1144 ic->candidate_show = 0;
1145 else if (name == Mdelete)
1147 int len = mtext_nchars (ic->preedit);
1148 int to = (MPLIST_SYMBOL_P (args)
1149 ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
1151 : MPLIST_INTEGER (args));
1157 if (to < ic->cursor_pos)
1158 preedit_delete (ic, to, ic->cursor_pos);
1159 else if (to > ic->cursor_pos)
1160 preedit_delete (ic, ic->cursor_pos, to);
1162 else if (name == Mmove)
1164 int len = mtext_nchars (ic->preedit);
1166 = (MPLIST_SYMBOL_P (args)
1167 ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
1169 : MPLIST_INTEGER (args));
1175 if (pos != ic->cursor_pos)
1177 ic->cursor_pos = pos;
1178 ic->preedit_changed = 1;
1181 else if (name == Mmark)
1183 int code = marker_code (MPLIST_SYMBOL (args));
1186 mplist_put (ic_info->markers, MPLIST_SYMBOL (args),
1187 (void *) ic->cursor_pos);
1189 else if (name == Mpushback)
1191 int num = MPLIST_INTEGER (args);
1194 ic_info->key_head -= num;
1196 ic_info->key_head = num;
1197 if (ic_info->key_head > ic_info->used)
1198 ic_info->key_head = ic_info->used;
1200 else if (name == Mcall)
1202 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1203 MIMExternalFunc func = NULL;
1204 MSymbol module, func_name;
1205 MPlist *func_args, *val;
1208 module = MPLIST_SYMBOL (args);
1209 args = MPLIST_NEXT (args);
1210 func_name = MPLIST_SYMBOL (args);
1212 if (im_info->externals)
1214 MIMExternalModule *external
1215 = (MIMExternalModule *) mplist_get (im_info->externals,
1218 func = (MIMExternalFunc) mplist_get (external->func_list,
1223 func_args = mplist ();
1224 mplist_add (func_args, Mt, ic);
1225 MPLIST_DO (args, MPLIST_NEXT (args))
1229 if (MPLIST_KEY (args) == Msymbol
1230 && MPLIST_KEY (args) != Mnil
1231 && (code = marker_code (MPLIST_SYMBOL (args))) >= 0)
1233 code = new_index (ic, ic->cursor_pos,
1234 mtext_nchars (ic->preedit),
1235 MPLIST_SYMBOL (args), ic->preedit);
1236 mplist_add (func_args, Minteger, (void *) code);
1239 mplist_add (func_args, MPLIST_KEY (args), MPLIST_VAL (args));
1241 val = (func) (func_args);
1242 M17N_OBJECT_UNREF (func_args);
1243 if (val && ! MPLIST_TAIL_P (val))
1244 ret = take_action_list (ic, val);
1245 M17N_OBJECT_UNREF (val);
1249 else if (name == Mshift)
1251 shift_state (ic, MPLIST_SYMBOL (args));
1253 else if (name == Mundo)
1255 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1258 mtext_reset (ic->preedit);
1259 mtext_reset (ic_info->preedit_saved);
1260 ic->cursor_pos = ic_info->state_pos = 0;
1261 ic_info->state_key_head = ic_info->key_head = 0;
1263 if (ic_info->used < 0)
1268 shift_state (ic, ((MIMState *) MPLIST_VAL (im_info->states))->name);
1273 else if (name == Mset || name == Madd || name == Msub
1274 || name == Mmul || name == Mdiv)
1276 MSymbol sym = MPLIST_SYMBOL (args);
1277 int val1 = (int) mplist_get (ic_info->vars, sym), val2;
1279 args = MPLIST_NEXT (args);
1280 val2 = integer_value (ic, args);
1283 else if (name == Madd)
1285 else if (name == Msub)
1287 else if (name == Mmul)
1291 mplist_put (ic_info->vars, sym, (void *) val1);
1293 else if (name == Mequal || name == Mless || name == Mgreater)
1296 MPlist *actions1, *actions2;
1299 val1 = integer_value (ic, args);
1300 args = MPLIST_NEXT (args);
1301 val2 = integer_value (ic, args);
1302 args = MPLIST_NEXT (args);
1303 actions1 = MPLIST_PLIST (args);
1304 args = MPLIST_NEXT (args);
1305 if (MPLIST_TAIL_P (args))
1308 actions2 = MPLIST_PLIST (args);
1309 if (name == Mequal ? val1 == val2
1310 : name == Mless ? val1 < val2
1312 ret = take_action_list (ic, actions1);
1314 ret = take_action_list (ic, actions2);
1320 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1324 && (actions = mplist_get (im_info->macros, name)))
1326 if (take_action_list (ic, actions) < 0)
1333 ic->candidate_list = NULL;
1334 if (ic->cursor_pos > 0
1335 && (prop = mtext_get_property (ic->preedit, ic->cursor_pos - 1,
1338 ic->candidate_list = mtext_property_value (prop);
1340 = (int) mtext_get_prop (ic->preedit, ic->cursor_pos - 1,
1342 ic->candidate_from = mtext_property_start (prop);
1343 ic->candidate_to = mtext_property_end (prop);
1346 ic->candidates_changed |= (candidate_list != ic->candidate_list
1347 || candidate_index != ic->candidate_index
1348 || candidate_show != ic->candidate_show);
1353 /* Handle the input key KEY in the current state and map specified in
1354 the input context IC. If KEY is handled correctly, return 0.
1355 Otherwise, return -1. */
1358 handle_key (MInputContext *ic)
1360 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1361 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1362 MIMMap *map = ic_info->map;
1363 MIMMap *submap = NULL;
1364 MSymbol key = ic_info->keys[ic_info->key_head];
1369 submap = mplist_get (map->submaps, key);
1370 if (! submap && (key = msymbol_get (key, M_key_alias)) != Mnil)
1371 submap = mplist_get (map->submaps, key);
1376 mtext_cpy (ic->preedit, ic_info->preedit_saved);
1377 ic->cursor_pos = ic_info->state_pos;
1378 ic_info->key_head++;
1379 ic_info->map = map = submap;
1380 if (map->map_actions)
1382 if (take_action_list (ic, map->map_actions) < 0)
1385 else if (map->submaps)
1387 for (i = ic_info->state_key_head; i < ic_info->key_head; i++)
1389 MSymbol key = ic_info->keys[i];
1390 char *name = msymbol_name (key);
1392 if (! name[0] || ! name[1])
1393 mtext_ins_char (ic->preedit, ic->cursor_pos++, name[0], 1);
1395 ic->preedit_changed = 1;
1398 /* If this is the terminal map or we have shifted to another
1399 state, perform branch actions (if any). */
1400 if (! map->submaps || map != ic_info->map)
1402 if (map->branch_actions)
1404 if (take_action_list (ic, map->branch_actions) < 0)
1407 /* If MAP is still not the root map, shift to the current
1409 if (ic_info->map != ic_info->state->map)
1410 shift_state (ic, ic_info->state->name);
1415 /* MAP can not handle KEY. */
1417 /* If MAP is the root map of the initial state, it means that
1418 the current input method can not handle KEY. */
1419 if (map == ((MIMState *) MPLIST_VAL (im_info->states))->map)
1422 if (map != ic_info->state->map)
1424 /* If MAP is not the root map... */
1425 /* If MAP has branch actions, perform them. */
1426 if (map->branch_actions)
1427 take_action_list (ic, map->branch_actions);
1428 /* If MAP is still not the root map, shift to the current
1430 if (ic_info->map != ic_info->state->map)
1432 shift_state (ic, ic_info->state->name);
1433 /* If MAP has branch_actions, perform them. */
1434 if (ic_info->map->branch_actions)
1435 take_action_list (ic, ic_info->map->branch_actions);
1440 /* MAP is the root map, perform branch actions (if any) or
1441 shift to the initial state. */
1442 if (map->branch_actions)
1443 take_action_list (ic, map->branch_actions);
1446 ((MIMState *) MPLIST_VAL (im_info->states))->name);
1453 reset_ic (MInputContext *ic)
1455 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1456 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1458 MLIST_RESET (ic_info);
1459 ic_info->state = (MIMState *) MPLIST_VAL (im_info->states);
1460 ic_info->map = ic_info->state->map;
1461 ic_info->state_key_head = ic_info->key_head = 0;
1462 ic->cursor_pos = ic_info->state_pos = 0;
1463 ic->status = ic_info->state->title;
1465 ic->status = im_info->title;
1466 ic->candidate_list = NULL;
1467 ic->candidate_show = 0;
1468 ic->status_changed = ic->preedit_changed = ic->candidates_changed = 1;
1469 if (ic_info->map->map_actions)
1470 take_action_list (ic, ic_info->map->map_actions);
1474 open_im (MInputMethod *im)
1477 MInputMethodInfo *im_info;
1481 mdb = mdatabase_find (Minput_method, im->language, im->name, Mnil);
1484 plist = mdatabase_load (mdb);
1486 MERROR (MERROR_IM, -1);
1487 MSTRUCT_CALLOC (im_info, MERROR_IM);
1489 result = load_input_method (im->language, im->name, plist, im_info);
1490 M17N_OBJECT_UNREF (plist);
1492 MERROR (MERROR_IM, -1);
1497 close_im (MInputMethod *im)
1499 MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
1503 M17N_OBJECT_UNREF (im_info->title);
1504 if (im_info->states)
1506 MPLIST_DO (plist, im_info->states)
1508 MIMState *state = (MIMState *) MPLIST_VAL (plist);
1511 M17N_OBJECT_UNREF (state->title);
1513 free_map (state->map);
1516 M17N_OBJECT_UNREF (im_info->states);
1519 if (im_info->macros)
1521 MPLIST_DO (plist, im_info->macros)
1522 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
1523 M17N_OBJECT_UNREF (im_info->macros);
1526 if (im_info->externals)
1528 MPLIST_DO (plist, im_info->externals)
1530 MIMExternalModule *external = MPLIST_VAL (plist);
1532 dlclose (external->handle);
1533 M17N_OBJECT_UNREF (external->func_list);
1535 MPLIST_KEY (plist) = Mt;
1537 M17N_OBJECT_UNREF (im_info->externals);
1545 create_ic (MInputContext *ic)
1547 MInputMethod *im = ic->im;
1548 MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
1549 MInputContextInfo *ic_info;
1552 ic_info = (MInputContextInfo *) ic->info;
1555 MSTRUCT_CALLOC (ic_info, MERROR_IM);
1558 MLIST_INIT1 (ic_info, keys, 8);
1559 ic_info->markers = mplist ();
1560 ic_info->vars = mplist ();
1561 ic_info->preedit_saved = mtext ();
1562 if (im_info->externals)
1564 MPlist *func_args = mplist (), *plist;
1566 mplist_add (func_args, Mt, ic);
1567 MPLIST_DO (plist, im_info->externals)
1569 MIMExternalModule *external = MPLIST_VAL (plist);
1570 MIMExternalFunc func
1571 = (MIMExternalFunc) mplist_get (external->func_list, Minit);
1576 M17N_OBJECT_UNREF (func_args);
1583 destroy_ic (MInputContext *ic)
1585 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1586 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1588 if (im_info->externals)
1590 MPlist *func_args = mplist (), *plist;
1592 mplist_add (func_args, Mt, ic);
1593 MPLIST_DO (plist, im_info->externals)
1595 MIMExternalModule *external = MPLIST_VAL (plist);
1596 MIMExternalFunc func
1597 = (MIMExternalFunc) mplist_get (external->func_list, Mfini);
1602 M17N_OBJECT_UNREF (func_args);
1604 MLIST_FREE1 (ic_info, keys);
1605 M17N_OBJECT_UNREF (ic_info->preedit_saved);
1606 M17N_OBJECT_UNREF (ic_info->markers);
1607 M17N_OBJECT_UNREF (ic_info->vars);
1612 /** Handle the input key KEY in the current state and map of IC->info.
1613 If KEY is handled but no text is produced, return 0, otherwise
1619 filter (MInputContext *ic, MSymbol key, void *arg)
1621 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1622 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1625 mtext_reset (ic->produced);
1626 ic->status_changed = ic->preedit_changed = ic->candidates_changed = 0;
1627 MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
1628 ic_info->key_unhandled = 0;
1630 if (handle_key (ic) < 0)
1632 /* KEY was not handled. Reset the status and break the
1635 /* This forces returning 1. */
1636 ic_info->key_unhandled = 1;
1643 ic_info->key_unhandled = 1;
1646 /* Break the loop if all keys were handled. */
1647 } while (ic_info->key_head < ic_info->used);
1649 /* If the current map is the root of the initial state, we should
1650 produce any preedit text in ic->produced. */
1651 if (ic_info->map == ((MIMState *) MPLIST_VAL (im_info->states))->map
1652 && mtext_nchars (ic->preedit) > 0)
1653 shift_state (ic, ((MIMState *) MPLIST_VAL (im_info->states))->name);
1655 if (mtext_nchars (ic->produced) > 0)
1657 MSymbol lang = msymbol_get (ic->im->language, Mlanguage);
1660 mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
1661 Mlanguage, ic->im->language);
1664 return (! ic_info->key_unhandled && mtext_nchars (ic->produced) == 0);
1668 /** Return 1 if the last event or key was not handled, otherwise
1671 There is no need of looking up because ic->produced should already
1672 contain the produced text (if any).
1677 lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
1679 mtext_cat (mt, ic->produced);
1680 mtext_reset (ic->produced);
1681 return (((MInputContextInfo *) ic->info)->key_unhandled ? -1 : 0);
1684 /* Support functions for mdebug_dump_im. */
1687 dump_im_map (MPlist *map_list, int indent)
1690 MSymbol key = MPLIST_KEY (map_list);
1691 MIMMap *map = (MIMMap *) MPLIST_VAL (map_list);
1693 prefix = (char *) alloca (indent + 1);
1694 memset (prefix, 32, indent);
1695 prefix[indent] = '\0';
1697 fprintf (stderr, "(\"%s\" ", msymbol_name (key));
1698 if (map->map_actions)
1699 mdebug_dump_plist (map->map_actions, indent + 2);
1702 MPLIST_DO (map_list, map->submaps)
1704 fprintf (stderr, "\n%s ", prefix);
1705 dump_im_map (map_list, indent + 2);
1708 if (map->branch_actions)
1710 fprintf (stderr, "\n%s (branch\n%s ", prefix, prefix);
1711 mdebug_dump_plist (map->branch_actions, indent + 4);
1712 fprintf (stderr, ")");
1714 fprintf (stderr, ")");
1719 dump_im_state (MIMState *state, int indent)
1724 prefix = (char *) alloca (indent + 1);
1725 memset (prefix, 32, indent);
1726 prefix[indent] = '\0';
1728 fprintf (stderr, "(%s", msymbol_name (state->name));
1729 if (state->map->submaps)
1731 MPLIST_DO (map_list, state->map->submaps)
1733 fprintf (stderr, "\n%s ", prefix);
1734 dump_im_map (map_list, indent + 2);
1737 fprintf (stderr, ")");
1746 = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1747 "BackSpace", "Tab", "Linefeed", "Clear", NULL, "Return", NULL, NULL,
1748 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1749 NULL, NULL, NULL, "Escape", NULL, NULL, NULL, NULL };
1750 char buf[6], buf2[256];
1753 Minput_method = msymbol ("input-method");
1754 Minput_driver = msymbol ("input-driver");
1755 Mtitle = msymbol ("title");
1756 Mmacro = msymbol ("macro");
1757 Mmodule = msymbol ("module");
1758 Mmap = msymbol ("map");
1759 Mstate = msymbol ("state");
1760 Minsert = msymbol ("insert");
1761 Mdelete = msymbol ("delete");
1762 Mmove = msymbol ("move");
1763 Mmark = msymbol ("mark");
1764 Mpushback = msymbol ("pushback");
1765 Mundo = msymbol ("undo");
1766 Mcall = msymbol ("call");
1767 Mshift = msymbol ("shift");
1768 Mselect = msymbol ("select");
1769 Mshow = msymbol ("show");
1770 Mhide = msymbol ("hide");
1771 Mset = msymbol ("set");
1772 Madd = msymbol ("add");
1773 Msub = msymbol ("sub");
1774 Mmul = msymbol ("mul");
1775 Mdiv = msymbol ("div");
1776 Mequal = msymbol ("=");
1777 Mless = msymbol ("<");
1778 Mgreater = msymbol (">");
1780 Minput_preedit_start = msymbol ("input-preedit-start");
1781 Minput_preedit_done = msymbol ("input-preedit-done");
1782 Minput_preedit_draw = msymbol ("input-preedit-draw");
1783 Minput_status_start = msymbol ("input-status-start");
1784 Minput_status_done = msymbol ("input-status-done");
1785 Minput_status_draw = msymbol ("input-status-draw");
1786 Minput_candidates_start = msymbol ("input-candidates-start");
1787 Minput_candidates_done = msymbol ("input-candidates-done");
1788 Minput_candidates_draw = msymbol ("input-candidates-draw");
1789 Minput_set_spot = msymbol ("input-set-spot");
1790 Minput_toggle = msymbol ("input-toggle");
1792 Mcandidate_list = msymbol_as_managing_key (" candidate-list");
1793 Mcandidate_index = msymbol (" candidate-index");
1795 Minit = msymbol ("init");
1796 Mfini = msymbol ("fini");
1798 M_key_alias = msymbol (" key-alias");
1803 for (i = 0, buf[2] = '@'; i < ' '; i++, buf[2]++)
1805 one_char_symbol[i] = msymbol (buf);
1807 msymbol_put (one_char_symbol[i], M_key_alias, msymbol (key_names[i]));
1809 for (buf[2] = i; i < 127; i++, buf[2]++)
1810 one_char_symbol[i] = msymbol (buf + 2);
1811 one_char_symbol[i++] = msymbol ("Delete");
1817 for (buf[4] = '@'; i < 160; i++, buf[4]++)
1819 one_char_symbol[i] = msymbol (buf);
1820 if (key_names[i - 128])
1822 strcpy (buf2 + 2, key_names[i - 128]);
1823 msymbol_put (one_char_symbol[i], M_key_alias, msymbol (buf2));
1826 for (buf[4] = i - 128; i < 255; i++, buf[4]++)
1827 one_char_symbol[i] = msymbol (buf + 2);
1828 one_char_symbol[i] = msymbol ("M-Delete");
1830 minput_default_driver.open_im = open_im;
1831 minput_default_driver.close_im = close_im;
1832 minput_default_driver.create_ic = create_ic;
1833 minput_default_driver.destroy_ic = destroy_ic;
1834 minput_default_driver.filter = filter;
1835 minput_default_driver.lookup = lookup;
1836 minput_default_driver.callback_list = NULL;
1837 minput_driver = &minput_default_driver;
1844 if (minput_default_driver.callback_list)
1846 M17N_OBJECT_UNREF (minput_default_driver.callback_list);
1847 minput_default_driver.callback_list = NULL;
1849 if (minput_driver->callback_list)
1851 M17N_OBJECT_UNREF (minput_driver->callback_list);
1852 minput_driver->callback_list = NULL;
1857 minput__callback (MInputContext *ic, MSymbol command)
1859 if (ic->im->driver.callback_list)
1861 MInputCallbackFunc func
1862 = (MInputCallbackFunc) mplist_get (ic->im->driver.callback_list,
1866 (func) (ic, command);
1871 minput__char_to_key (int c)
1873 if (c < 0 || c >= 0x100)
1876 return one_char_symbol[c];
1880 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1885 /*** @addtogroup m17nInputMethod */
1890 @name Variables: Predefined symbols for callback commands.
1892 These are the predefined symbols that are used as the @c COMMAND
1893 argument of callback functions of an input method driver (see
1894 #MInputDriver::callback_list ). */
1896 @name ÊÑ¿ô¡§ ¥³¡¼¥ë¥Ð¥Ã¥¯¥³¥Þ¥ó¥ÉÍÑÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë.
1898 ÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Î¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Ë¤ª¤¤¤Æ @c COMMAND °ú¿ô¤È¤·
1899 ¤ÆÍѤ¤¤é¤ì¤ëÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë (#MInputDriver::callback_list »²¾È)¡£
1904 MSymbol Minput_preedit_start;
1905 MSymbol Minput_preedit_done;
1906 MSymbol Minput_preedit_draw;
1907 MSymbol Minput_status_start;
1908 MSymbol Minput_status_done;
1909 MSymbol Minput_status_draw;
1910 MSymbol Minput_candidates_start;
1911 MSymbol Minput_candidates_done;
1912 MSymbol Minput_candidates_draw;
1913 MSymbol Minput_set_spot;
1914 MSymbol Minput_toggle;
1919 @brief The default driver for internal input methods.
1921 The variable #minput_default_driver is the default driver for
1922 internal input methods.
1924 The member MInputDriver::open_im () searches the m17n database for
1925 an input method that matches the tag \< #Minput_method, $LANGUAGE,
1926 $NAME\> and loads it.
1928 The member MInputDriver::callback_list () is @c NULL. Thus, it is
1929 programmers responsibility to set it to a plist of proper callback
1930 functions. Otherwise, no feedback information (e.g. preedit text)
1931 can be shown to users.
1933 The macro M17N_INIT () sets the variable #minput_driver to the
1934 pointer to this driver so that all internal input methods use it.
1936 Therefore, unless @c minput_driver is set differently, the driver
1937 dependent arguments $ARG of the functions whose name begin with
1938 "minput_" are all ignored. */
1941 @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥǥե©¥ë¥È¥É¥é¥¤¥Ð.
1943 ÆþÎϥɥ饤¥Ð #minput_default_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѤΥǥե©¥ë
1944 ¥È¤Î¥É¥é¥¤¥Ð¤Ç¤¢¤ë¡£
1946 ¥á¥ó¥Ð MInputDriver::open_im () ¤Ï m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹Ã椫¤é¥¿¥°
1947 \< #Minput_method, $LANGUAGE, $NAME\> ¤Ë¹çÃפ¹¤ëÆþÎϥ᥽¥Ã¥É¤òõ¤·¡¢
1950 ¥á¥ó¥Ð MInputDriver::callback_list () ¤Ï @c NULL ¤Ê¤Î¤Ç¡¢¥×¥í¥°¥é
1951 ¥Þ¦¤ÇÀÕǤ¤ò»ý¤Ã¤Æ, ŬÀڤʥ³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Î plist ¤ËÀßÄꤷ¤Ê¤¯¤Æ
1952 ¤Ï¤Ê¤é¤Ê¤¤¡£¤µ¤â¤Ê¤¤¤È¡¢preedit ¥Æ¥¥¹¥È¤Ê¤É¤Î¥Õ¥£¡¼¥É¥Ð¥Ã¥¯¾ðÊó¤¬
1953 ¥æ¡¼¥¶¤Ëɽ¼¨¤µ¤ì¤Ê¤¤¡£
1955 ¥Þ¥¯¥í M17N_INIT () ¤ÏÊÑ¿ô #minput_driver ¤ò¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó
1956 ¥¿¤ËÀßÄꤷ¡¢Á´¤Æ¤ÎÆâÉôÆþÎϥ᥽¥Ã¥É¤¬¤³¤Î¥É¥é¥¤¥Ð¤ò»È¤¦¤è¤¦¤Ë¤¹¤ë¡£
1958 ¤·¤¿¤¬¤Ã¤Æ¡¢@c minput_driver ¤¬¥Ç¥Õ¥©¥ë¥ÈÃͤΤޤޤǤ¢¤ì¤Ð¡¢minput_
1959 ¤Ç»Ï¤Þ¤ë´Ø¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô $ARG ¤Ï¤¹¤Ù¤Æ̵»ë¤µ¤ì¤ë¡£ */
1961 MInputDriver minput_default_driver;
1965 @brief The driver for internal input methods.
1967 The variable #minput_driver is a pointer to the input method
1968 driver that is used by internal input methods. The macro
1969 M17N_INIT () initializes it to a pointer to #minput_default_driver
1970 (if <m17n.h> is included) or to #minput_gui_driver (if
1971 <m17n-gui.h> is included). */
1973 @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥɥ饤¥Ð.
1975 ÊÑ¿ô #minput_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤Æ»ÈÍѤµ¤ì¤Æ¤¤¤ëÆþÎÏ¥á
1976 ¥½¥Ã¥É¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£¥Þ¥¯¥íM17N_INIT () ¤Ï¤³¤Î¥Ý¥¤¥ó
1977 ¥¿¤ò #minput_default_driver (<m17n.h> ¤¬´Þ¤Þ¤ì¤ë»þ) ¤Þ¤¿¤Ï
1978 #minput_gui_driver ( <m17n-gui.h> ¤¬´Þ¤Þ¤ì¤ë»þ) ¤Ë½é´ü²½¤¹¤ë¡£ */
1980 MInputDriver *minput_driver;
1982 MSymbol Minput_driver;
1987 @brief Open an input method.
1989 The minput_open_im () function opens an input method that matches
1990 language $LANGUAGE and name $NAME, and returns a pointer to the
1991 input method object newly allocated.
1993 This function at first decides an driver for the input method as
1996 If $LANGUAGE is not #Mnil, the driver pointed by the variable
1997 #minput_driver is used.
1999 If $LANGUAGE is #Mnil and $NAME has #Minput_driver property, the
2000 driver pointed to by the property value is used to open the input
2001 method. If $NAME has no such property, @c NULL is returned.
2003 Then, the member MInputDriver::open_im () of the driver is
2006 $ARG is set in the member @c arg of the structure MInputMethod so
2007 that the driver can refer to it. */
2010 @brief ÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë.
2012 ´Ø¿ô minput_open_im () ¤Ï¸À¸ì $LANGUAGE ¤È̾Á° $NAME ¤Ë¹çÃפ¹¤ëÆþ
2013 Îϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤·¡¢¿·¤¿¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿ÆþÎϥ᥽¥Ã¥É¥ª¥Ö¥¸¥§¥¯
2014 ¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
2016 ¤³¤Î´Ø¿ô¤Ï¡¢¤Þ¤ºÆþÎϥ᥽¥Ã¥ÉÍѤΥɥ饤¥Ð¤ò°Ê²¼¤Î¤è¤¦¤Ë¤·¤Æ·èÄꤹ¤ë¡£
2018 $LANGUAGE ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢ÊÑ¿ô #minput_driver ¤Ç»Ø¤µ¤ì¤Æ¤¤¤ë
2021 $LANGUAGE ¤¬ #Mnil ¤Ç¤¢¤ê¡¢$NAME ¤¬ #Minput_driver ¥×¥í¥Ñ¥Æ¥£¤ò»ý
2022 ¤Ä¾ì¹ç¤Ë¤Ï¡¢¤½¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤǻؤµ¤ì¤Æ¤¤¤ëÆþÎϥɥ饤¥Ð¤òÍѤ¤¤ÆÆþ
2023 Îϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë¡£$NAME ¤Ë¤½¤Î¤è¤¦¤Ê¥×¥í¥Ñ¥Æ¥£¤¬Ìµ¤«¤Ã¤¿¾ì
2024 ¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
2026 ¼¡¤¤¤Ç¡¢¥É¥é¥¤¥Ð¤Î¥á¥ó¥Ð MInputDriver::open_im () ¤¬¸Æ¤Ð¤ì¤ë¡£
2028 $ARG ¤Ï¡¢¥É¥é¥¤¥Ð¤¬»²¾È¤Ç¤¤ë¤è¤¦¤Ë¡¢¹½Â¤ÂÎ MInputMethod ¤Î¥á¥ó¥Ð
2029 @c arg ¤ËÀßÄꤵ¤ì¤ë¡£
2031 @latexonly \IPAlabel{minput_open} @endlatexonly
2036 minput_open_im (MSymbol language, MSymbol name, void *arg)
2039 MInputDriver *driver;
2042 driver = minput_driver;
2045 driver = (MInputDriver *) msymbol_get (name, Minput_driver);
2047 MERROR (MERROR_IM, NULL);
2050 MSTRUCT_CALLOC (im, MERROR_IM);
2051 im->language = language;
2054 im->driver = *driver;
2055 if ((*im->driver.open_im) (im) < 0)
2066 @brief Close an input method.
2068 The minput_close_im () function closes the input method $IM, which
2069 must have been created by minput_open_im (). */
2072 @brief ÆþÎϥ᥽¥Ã¥É¤ò¥¯¥í¡¼¥º¤¹¤ë.
2074 ´Ø¿ô minput_close_im () ¤Ï¡¢ÆþÎϥ᥽¥Ã¥É $IM ¤ò¥¯¥í¡¼¥º¤¹¤ë¡£¤³¤Î
2075 ÆþÎϥ᥽¥Ã¥É $IM ¤Ï minput_open_im () ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê¤±¤ì
2079 minput_close_im (MInputMethod *im)
2081 (*im->driver.close_im) (im);
2088 @brief Create an input context.
2090 The minput_create_ic () function creates an input context object
2091 associated with input method $IM, and calls callback functions
2092 corresponding to #Minput_preedit_start, #Minput_status_start, and
2093 #Minput_status_draw in this order.
2097 If an input context is successfully created, minput_create_ic ()
2098 returns a pointer to it. Otherwise it returns @c NULL. */
2101 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÀ¸À®¤¹¤ë.
2103 ´Ø¿ô minput_create_ic () ¤ÏÆþÎϥ᥽¥Ã¥É $IM ¤ËÂбþ¤¹¤ëÆþÎÏ¥³¥ó¥Æ¥¯
2104 ¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤·¡¢ #Minput_preedit_start,
2105 #Minput_status_start, #Minput_status_draw ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø
2110 ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤¬À¸À®¤µ¤ì¤¿¾ì¹ç¡¢minput_create_ic () ¤Ï¤½¤ÎÆþÎÏ¥³
2111 ¥ó¥Æ¥¯¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¼ºÇÔ¤·¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
2115 minput_create_ic (MInputMethod *im, void *arg)
2119 MSTRUCT_CALLOC (ic, MERROR_IM);
2122 ic->preedit = mtext ();
2123 ic->candidate_list = NULL;
2124 ic->produced = mtext ();
2125 ic->spot.x = ic->spot.y = 0;
2127 ic->plist = mplist ();
2128 if ((*im->driver.create_ic) (ic) < 0)
2130 M17N_OBJECT_UNREF (ic->preedit);
2131 M17N_OBJECT_UNREF (ic->produced);
2132 M17N_OBJECT_UNREF (ic->plist);
2137 if (im->driver.callback_list)
2139 minput__callback (ic, Minput_preedit_start);
2140 minput__callback (ic, Minput_status_start);
2141 minput__callback (ic, Minput_status_draw);
2150 @brief Destroy an input context.
2152 The minput_destroy_ic () function destroys the input context $IC,
2153 which must have been created by minput_create_ic (). It calls
2154 callback functions corresponding to #Minput_preedit_done,
2155 #Minput_status_done, and #Minput_candidates_done in this order. */
2158 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÇ˲õ¤¹¤ë.
2160 ´Ø¿ô minput_destroy_ic () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤òÇ˲õ¤¹¤ë¡£¤³
2161 ¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ï minput_create_ic () ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê
2162 ¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£¤³¤Î´Ø¿ô¤Ï#Minput_preedit_done,
2163 #Minput_status_done, #Minput_candidates_done ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò
2168 minput_destroy_ic (MInputContext *ic)
2170 if (ic->im->driver.callback_list)
2172 minput__callback (ic, Minput_preedit_done);
2173 minput__callback (ic, Minput_status_done);
2174 minput__callback (ic, Minput_candidates_done);
2176 (*ic->im->driver.destroy_ic) (ic);
2177 M17N_OBJECT_UNREF (ic->preedit);
2178 M17N_OBJECT_UNREF (ic->produced);
2179 M17N_OBJECT_UNREF (ic->plist);
2186 @brief Filter an input key.
2188 The minput_filter () function filters input key $KEY according to
2189 input context $IC, and calls callback functions corresponding to
2190 #Minput_preedit_draw, #Minput_status_draw, and
2191 #Minput_candidates_draw if the preedit text, the status, and the
2192 current candidate are changed respectively.
2195 If $KEY is filtered out, this function returns 1. In that case,
2196 the caller should discard the key. Otherwise, it returns 0, and
2197 the caller should handle the key, for instance, by calling the
2198 function minput_lookup () with the same key. */
2201 @brief ÆþÎÏ¥¡¼¤ò¥Õ¥£¥ë¥¿¤¹¤ë.
2203 ´Ø¿ô minput_filter () ¤ÏÆþÎÏ¥¡¼ $KEY ¤òÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤Ë±þ
2204 ¤¸¤Æ¥Õ¥£¥ë¥¿¤·¡¢preedit ¥Æ¥¥¹¥È¡¢¥¹¥Æ¡¼¥¿¥¹¡¢¸½»þÅÀ¤Ç¤Î¸õÊ䤬ÊѲ½
2205 ¤·¤¿ºÝ¤Ë¤Ï¤½¤ì¤¾¤ì#Minput_preedit_draw, #Minput_status_draw,
2206 #Minput_candidates_draw ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¸Æ¤Ö¡£
2209 $KEY ¤¬¥Õ¥£¥ë¥¿¤µ¤ì¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 1 ¤òÊÖ¤¹¡£¤³¤Î¾ì¹ç¸Æ¤Ó
2210 ½Ð¤·Â¦¤Ï¤³¤Î¥¡¼¤ò¼Î¤Æ¤ë¤Ù¤¤Ç¤¢¤ë¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0 ¤òÊÖ¤·¡¢¸Æ¤Ó
2211 ½Ð¤·Â¦¤Ï¡¢¤¿¤È¤¨¤ÐƱ¤¸¥¡¼¤Ç´Ø¿ô minput_lookup () ¤ò¸Æ¤Ö¤Ê¤É¤·¤Æ¡¢
2212 ¤³¤Î¥¡¼¤ò½èÍý¤¹¤ë¡£
2214 @latexonly \IPAlabel{minput_filter} @endlatexonly
2218 minput_filter (MInputContext *ic, MSymbol key, void *arg)
2225 ret = (*ic->im->driver.filter) (ic, key, arg);
2227 if (ic->im->driver.callback_list)
2229 if (ic->preedit_changed)
2230 minput__callback (ic, Minput_preedit_draw);
2231 if (ic->status_changed)
2232 minput__callback (ic, Minput_status_draw);
2233 if (ic->candidates_changed)
2234 minput__callback (ic, Minput_candidates_draw);
2235 ic->preedit_changed = ic->status_changed = ic->candidates_changed = 0;
2244 @brief Lookup a text produced in the input context.
2246 The minput_lookup () function looks up a text in the input context
2247 $IC. $KEY must be the same one provided to the previous call of
2250 If a text was produced by the input method, it is concatenated
2253 This function calls #MInputDriver::lookup .
2256 If $KEY was correctly handled by the input method, this function
2257 returns 0. Otherwise, returns -1, even in that case, some text
2258 may be produced in $MT. */
2261 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥ÈÃæ¤Î¥Æ¥¥¹¥È¤Î¸¡º÷.
2263 ´Ø¿ô minput_lookup () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC Ãæ¤Î¥Æ¥¥¹¥È¤ò¸¡º÷¤¹
2264 ¤ë¡£$KEY ¤Ï´Ø¿ôminput_filter () ¤Ø¤ÎľÁ°¤Î¸Æ¤Ó½Ð¤·¤ËÍѤ¤¤é¤ì¤¿¤â¤Î
2265 ¤ÈƱ¤¸¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2267 ¥Æ¥¥¹¥È¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆÀ¸À®¤µ¤ì¤Æ¤¤¤ì¤Ð¡¢¥Æ¥¥¹¥È¤Ï M-text
2270 ¤³¤Î´Ø¿ô¤Ï¡¢#MInputDriver::lookup ¤ò¸Æ¤Ö¡£
2273 $KEY ¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆŬÀڤ˽èÍý¤Ç¤¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 0 ¤òÊÖ¤¹¡£
2274 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£¤³¤Î¾ì¹ç¤Ç¤â $MT ¤Ë²¿¤é¤«¤Î¥Æ¥¥¹¥È¤¬À¸
2275 À®¤µ¤ì¤Æ¤¤¤ë¤³¤È¤¬¤¢¤ë¡£
2277 @latexonly \IPAlabel{minput_lookup} @endlatexonly */
2280 minput_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2282 return (ic ? (*ic->im->driver.lookup) (ic, key, arg, mt) : -1);
2287 @brief Set the spot of the input context.
2289 The minput_set_spot () function set the spot of input context $IC
2290 to coordinate ($X, $Y ) with the height $ASCENT and $DESCENT .
2291 The semantics of these values depend on the input method driver.
2292 $FONTSIZE specfies the fontsize of a preedit text in 1/10 point.
2294 For instance, an driver designed to work in CUI environment may
2295 use $X and $Y as column and row numbers, and ignore $ASCENT and
2296 $DESCENT . An driver designed to work on a window system may
2297 treat $X and $Y as pixel offsets relative to the origin of the
2298 client window, and treat $ASCENT and $DESCENT as ascent and
2299 descent pixels of a line at ($X . $Y ).
2301 $MT and $POS is an M-text and a character position at the spot.
2302 $MT may be @c NULL, in which case, the input method cannot get
2303 information about the text around the spot. */
2306 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Î¥¹¥Ý¥Ã¥È¤òÀßÄꤹ¤ë
2308 ´Ø¿ô minput_set_spot () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤Î¥¹¥Ý¥Ã¥È¤ò¡¢ºÂ
2309 ɸ ($X, $Y )¤Ë ¡¢¹â¤µ $ASCENT¡¢ $DESCENT ¤ÇÀßÄꤹ¤ë¡£ ¤³¤ì¤é¤ÎÃͤÎ
2310 °ÕÌ£¤ÏÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë¡£$FONTSIZE ¤Ïpreedit ¥Æ¥¥¹¥È
2311 ¤Î¥Õ¥©¥ó¥È¥µ¥¤¥º¤ò 1/10 ¥Ý¥¤¥ó¥Èñ°Ì¤Ç»ØÄꤹ¤ë¡£
2313 ¤¿¤È¤¨¤Ð CUI ´Ä¶¤ÇÆ°ºî¤¹¤ë¥É¥é¥¤¥Ð¤Ï $X ¤È $Y ¤ò¤½¤ì¤¾¤ìÎó¤È¹Ô¤Î
2314 ÈÖ¹æ¤È¤·¤ÆÍѤ¤¡¢$ASCENT ¤È $DESCENT ¤ò̵»ë¤¹¤ë¤«¤â¤·¤ì¤Ê¤¤¡£ ¤Þ¤¿
2315 ¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥àÍѤΥɥ饤¥Ð¤Ï $X ¤È $Y ¤ò¥¯¥é¥¤¥¢¥ó¥È¥¦¥£¥ó¥É¥¦
2316 ¤Î¸¶ÅÀ¤«¤é¤Î¥ª¥Õ¥»¥Ã¥È¤ò¥Ô¥¯¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¤¡¢
2317 $ASCENT ¤È $DESCENT ¤ò ($X . $Y ) ¤ÎÎó¤Î¥¢¥»¥ó¥È¤È¥Ç¥£¥»¥ó¥È¤ò¥Ô¥¯
2318 ¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¦¤«¤â¤·¤ì¤Ê¤¤¡£
2320 $MT ¤È $POS ¤Ï¤½¤Î¥¹¥Ý¥Ã¥È¤Î M-text ¤Èʸ»ú°ÌÃ֤Ǥ¢¤ë¡£$MT ¤Ï @c
2321 NULL ¤Ç¤â¤è¤¯¡¢¤½¤Î¾ì¹ç¤Ë¤ÏÆþÎϥ᥽¥Ã¥É¤Ï¥¹¥Ý¥Ã¥È¼þÊդΥƥ¥¹¥È¤Ë
2322 ´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë¤³¤È¤¬¤Ç¤¤Ê¤¤¡£
2326 minput_set_spot (MInputContext *ic, int x, int y,
2327 int ascent, int descent, int fontsize,
2332 ic->spot.ascent = ascent;
2333 ic->spot.descent = descent;
2334 ic->spot.fontsize = fontsize;
2337 if (ic->im->driver.callback_list)
2338 minput__callback (ic, Minput_set_spot);
2343 @brief Toggle input method.
2345 The minput_toggle () function toggles the input method associated
2346 with the input context $IC. */
2348 @brief ÆþÎϥ᥽¥Ã¥É¤òÀÚÂؤ¨¤ë.
2350 ´Ø¿ô minput_toggle () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤ËÂбþÉÕ¤±¤é¤ì¤¿ÆþÎÏ
2351 ¥á¥½¥Ã¥É¤ò¥È¥°¥ë¤¹¤ë¡£
2355 minput_toggle (MInputContext *ic)
2357 if (ic->im->driver.callback_list)
2358 minput__callback (ic, Minput_toggle);
2359 ic->active = ! ic->active;
2365 /*** @addtogroup m17nDebug */
2371 @brief Dump an input method.
2373 The mdebug_dump_im () function prints the input method $IM in a
2374 human readable way to the stderr. $INDENT specifies how many
2375 columns to indent the lines but the first one.
2378 This function returns $IM. */
2380 @brief ÆþÎϥ᥽¥Ã¥É¤ò¥À¥ó¥×¤¹¤ë.
2382 ´Ø¿ô mdebug_dump_im () ¤ÏÆþÎϥ᥽¥Ã¥É $IM ¤ò stderr ¤Ë¿Í´Ö¤Ë²ÄÆɤÊ
2383 ·Á¤Ç°õºþ¤¹¤ë¡£$INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£
2386 ¤³¤Î´Ø¿ô¤Ï $IM ¤òÊÖ¤¹¡£ */
2389 mdebug_dump_im (MInputMethod *im, int indent)
2391 MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
2394 prefix = (char *) alloca (indent + 1);
2395 memset (prefix, 32, indent);
2396 prefix[indent] = '\0';
2398 fprintf (stderr, "(input-method %s %s ", msymbol_name (im->language),
2399 msymbol_name (im->name));
2400 mdebug_dump_mtext (im_info->title, 0, 0);
2401 if (im->name != Mnil)
2405 MPLIST_DO (state, im_info->states)
2407 fprintf (stderr, "\n%s ", prefix);
2408 dump_im_state (MPLIST_VAL (state), indent + 2);
2411 fprintf (stderr, ")");