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
147 #include "m17n-gui.h"
148 #include "m17n-misc.h"
149 #include "internal.h"
155 static MSymbol Minput_method;
157 /** Symbols to load an input method data. */
158 static MSymbol Mtitle, Mmacro, Mmodule, Mstate;
160 /** Symbols for actions. */
161 static MSymbol Minsert, Mdelete, Mmark, Mmove, Mpushback, Mundo, Mcall, Mshift;
162 static MSymbol Mselect, Mshow, Mhide;
163 static MSymbol Mset, Madd, Msub, Mmul, Mdiv, Mequal, Mless, Mgreater;
165 static MSymbol Mcandidate_list, Mcandidate_index;
167 static MSymbol Minit, Mfini;
169 /** Symbols for key events. */
170 static MSymbol one_char_symbol[256];
172 static MSymbol M_key_alias;
174 /** Structure to hold a map. */
178 /** List of actions to take when we reach the map. In a root map,
179 the actions are executed only when there's no more key. */
182 /** List of deeper maps. If NULL, this is a terminal map. */
185 /** List of actions to take when we leave the map successfully. In
186 a root map, the actions are executed only when none of submaps
187 handle the current key. */
188 MPlist *branch_actions;
191 typedef MPlist *(*MIMExternalFunc) (MPlist *plist);
196 MPlist *func_list; /* function name vs (MIMExternalFunc *) */
201 /** Name of the state. */
204 /** Title of the state, or NULL. */
207 /** Key translation map of the state. Built by merging all maps of
214 marker_code (MSymbol sym)
220 name = MSYMBOL_NAME (sym);
221 return ((name[0] == '@'
222 && ((name[1] >= '0' && name[1] <= '9')
223 || name[1] == '<' || name[1] == '>'
224 || name[1] == '=' || name[1] == '+' || name[1] == '-'
225 || name[1] == '[' || name[1] == ']')
231 integer_value (MInputContext *ic, MPlist *arg)
233 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
235 MText *preedit = ic->preedit;
236 int len = mtext_nbytes (preedit);
238 if (MPLIST_INTEGER_P (arg))
239 return MPLIST_INTEGER (arg);
240 code = marker_code (MPLIST_SYMBOL (arg));
242 return (int) mplist_get (ic_info->vars, MPLIST_SYMBOL (arg));
243 if (code >= '0' && code <= '9')
245 else if (code == '=')
246 code = ic->cursor_pos;
247 else if (code == '-' || code == '[')
248 code = ic->cursor_pos - 1;
249 else if (code == '+' || code == ']')
250 code = ic->cursor_pos + 1;
251 else if (code == '<')
253 else if (code == '<')
255 return (code >= 0 && code < len ? mtext_ref_char (preedit, code) : -1);
259 /* Parse PLIST as an action list while modifying the list to regularize
260 actions. PLIST should have this form:
261 PLIST ::= ( (ACTION-NAME ACTION-ARG *) *).
262 Return 0 if successfully parsed, otherwise return -1. */
265 parse_action_list (MPlist *plist, MPlist *macros)
267 MPLIST_DO (plist, plist)
269 if (MPLIST_MTEXT_P (plist))
271 /* This is a short form of (insert MTEXT). */
272 /* if (mtext_nchars (MPLIST_MTEXT (plist)) == 0)
273 MERROR (MERROR_IM, -1); */
275 else if (MPLIST_PLIST_P (plist)
276 && (MPLIST_MTEXT_P (MPLIST_PLIST (plist))
277 || MPLIST_PLIST_P (MPLIST_PLIST (plist))))
281 /* This is a short form of (insert (GROUPS *)). */
282 MPLIST_DO (pl, MPLIST_PLIST (plist))
284 if (MPLIST_PLIST_P (pl))
288 MPLIST_DO (elt, MPLIST_PLIST (pl))
289 if (! MPLIST_MTEXT_P (elt)
290 || mtext_nchars (MPLIST_MTEXT (elt)) == 0)
291 MERROR (MERROR_IM, -1);
295 if (! MPLIST_MTEXT_P (pl)
296 || mtext_nchars (MPLIST_MTEXT (pl)) == 0)
297 MERROR (MERROR_IM, -1);
301 else if (MPLIST_INTEGER_P (plist))
303 int c = MPLIST_INTEGER (plist);
305 if (c < 0 || c > MCHAR_MAX)
306 MERROR (MERROR_IM, -1);
308 else if (MPLIST_PLIST_P (plist)
309 && MPLIST_SYMBOL_P (MPLIST_PLIST (plist)))
311 MPlist *pl = MPLIST_PLIST (plist);
312 MSymbol action_name = MPLIST_SYMBOL (pl);
314 pl = MPLIST_NEXT (pl);
316 if (action_name == Minsert)
318 if (MPLIST_MTEXT_P (pl))
320 if (mtext_nchars (MPLIST_MTEXT (pl)) == 0)
321 MERROR (MERROR_IM, -1);
323 else if (MPLIST_PLIST_P (pl))
327 if (MPLIST_PLIST_P (pl))
331 MPLIST_DO (elt, MPLIST_PLIST (pl))
332 if (! MPLIST_MTEXT_P (elt)
333 || mtext_nchars (MPLIST_MTEXT (elt)) == 0)
334 MERROR (MERROR_IM, -1);
338 if (! MPLIST_MTEXT_P (pl)
339 || mtext_nchars (MPLIST_MTEXT (pl)) == 0)
340 MERROR (MERROR_IM, -1);
344 else if (! MPLIST_SYMBOL_P (pl))
345 MERROR (MERROR_IM, -1);
347 else if (action_name == Mselect
348 || action_name == Mdelete
349 || action_name == Mmove)
351 if (! MPLIST_SYMBOL_P (pl)
352 && ! MPLIST_INTEGER_P (pl))
353 MERROR (MERROR_IM, -1);
355 else if (action_name == Mmark
356 || action_name == Mcall
357 || action_name == Mshift)
359 if (! MPLIST_SYMBOL_P (pl))
360 MERROR (MERROR_IM, -1);
362 else if (action_name == Mshow || action_name == Mhide
363 || action_name == Mundo)
365 if (! MPLIST_TAIL_P (pl))
366 MERROR (MERROR_IM, -1);
368 else if (action_name == Mpushback)
370 if (! MPLIST_INTEGER_P (pl))
371 MERROR (MERROR_IM, -1);
373 else if (action_name == Mset || action_name == Madd
374 || action_name == Msub || action_name == Mmul
375 || action_name == Mdiv)
377 if (! (MPLIST_SYMBOL_P (pl)
378 && (MPLIST_INTEGER_P (MPLIST_NEXT (pl))
379 || MPLIST_SYMBOL_P (MPLIST_NEXT (pl)))))
380 MERROR (MERROR_IM, -1);
382 else if (action_name == Mequal || action_name == Mless
383 || action_name == Mgreater)
385 if (! ((MPLIST_INTEGER_P (pl) || MPLIST_SYMBOL_P (pl))
386 && (MPLIST_INTEGER_P (MPLIST_NEXT (pl))
387 || MPLIST_SYMBOL_P (MPLIST_NEXT (pl)))))
388 MERROR (MERROR_IM, -1);
389 pl = MPLIST_NEXT (MPLIST_NEXT (pl));
390 if (! MPLIST_PLIST_P (pl))
391 MERROR (MERROR_IM, -1);
392 if (parse_action_list (MPLIST_PLIST (pl), macros) < 0)
393 MERROR (MERROR_IM, -1);
394 pl = MPLIST_NEXT (pl);
395 if (MPLIST_PLIST_P (pl)
396 && parse_action_list (MPLIST_PLIST (pl), macros) < 0)
397 MERROR (MERROR_IM, -1);
399 else if (! macros || ! mplist_get (macros, action_name))
400 MERROR (MERROR_IM, -1);
403 MERROR (MERROR_IM, -1);
410 /* Load a translation into MAP from PLIST.
412 PLIST ::= ( KEYSEQ MAP-ACTION * ) */
415 load_translation (MIMMap *map, MPlist *plist, MPlist *branch_actions,
421 if (MPLIST_MTEXT_P (plist))
423 MText *mt = MPLIST_MTEXT (plist);
425 len = mtext_nchars (mt);
426 if (len == 0 || len != mtext_nbytes (mt))
427 MERROR (MERROR_IM, -1);
428 keyseq = (MSymbol *) alloca (sizeof (MSymbol) * len);
429 for (i = 0; i < len; i++)
430 keyseq[i] = one_char_symbol[MTEXT_DATA (mt)[i]];
432 else if (MPLIST_PLIST_P (plist))
434 MPlist *elt = MPLIST_PLIST (plist);
436 len = MPLIST_LENGTH (elt);
438 MERROR (MERROR_IM, -1);
439 keyseq = (MSymbol *) alloca (sizeof (int) * len);
440 for (i = 0; i < len; i++, elt = MPLIST_NEXT (elt))
442 if (MPLIST_INTEGER_P (elt))
444 int c = MPLIST_INTEGER (elt);
446 if (c < 0 || c >= 0x100)
447 MERROR (MERROR_IM, -1);
448 keyseq[i] = one_char_symbol[c];
450 else if (MPLIST_SYMBOL_P (elt))
451 keyseq[i] = MPLIST_SYMBOL (elt);
453 MERROR (MERROR_IM, -1);
457 MERROR (MERROR_IM, -1);
459 for (i = 0; i < len; i++)
461 MIMMap *deeper = NULL;
464 deeper = mplist_get (map->submaps, keyseq[i]);
466 map->submaps = mplist ();
469 /* Fixme: It is better to make all deeper maps at once. */
470 MSTRUCT_CALLOC (deeper, MERROR_IM);
471 mplist_put (map->submaps, keyseq[i], deeper);
476 /* We reach a terminal map. */
478 || map->branch_actions)
479 /* This map is already defined. We avoid overriding it. */
482 plist = MPLIST_NEXT (plist);
483 if (! MPLIST_TAIL_P (plist))
485 if (parse_action_list (plist, macros) < 0)
486 MERROR (MERROR_IM, -1);
487 map->map_actions = plist;
488 M17N_OBJECT_REF (plist);
492 map->branch_actions = branch_actions;
493 M17N_OBJECT_REF (branch_actions);
499 /* Load a branch from PLIST into MAP. PLIST has this form:
500 PLIST ::= ( MAP-NAME BRANCH-ACTION * )
501 MAPS is a plist of raw maps.
502 STATE is the current state. */
505 load_branch (MPlist *plist, MPlist *maps, MIMMap *map, MPlist *macros)
508 MPlist *branch_actions;
510 if (! MPLIST_SYMBOL_P (plist))
511 MERROR (MERROR_IM, -1);
512 map_name = MPLIST_SYMBOL (plist);
513 plist = MPLIST_NEXT (plist);
514 if (MPLIST_TAIL_P (plist))
515 branch_actions = NULL;
516 else if (parse_action_list (plist, macros) < 0)
517 MERROR (MERROR_IM, -1);
519 branch_actions = plist;
520 if (map_name == Mnil)
522 map->branch_actions = branch_actions;
524 M17N_OBJECT_REF (branch_actions);
526 else if (map_name == Mt)
528 map->map_actions = branch_actions;
530 M17N_OBJECT_REF (branch_actions);
534 plist = (MPlist *) mplist_get (maps, map_name);
535 if (! plist || ! MPLIST_PLIST_P (plist))
536 MERROR (MERROR_IM, -1);
537 MPLIST_DO (plist, plist)
538 if (! MPLIST_PLIST_P (plist)
539 || (load_translation (map, MPLIST_PLIST (plist), branch_actions,
542 MERROR (MERROR_IM, -1);
548 /* Load a macro from PLIST into MACROS.
550 PLIST ::= ( MACRO-NAME ACTION * )
551 MACROS is a plist of macro names vs action list. */
553 load_macros (MPlist *plist, MPlist *macros)
557 if (! MPLIST_SYMBOL_P (plist))
558 MERROR (MERROR_IM, -1);
559 name = MPLIST_SYMBOL (plist);
560 plist = MPLIST_NEXT (plist);
561 if (MPLIST_TAIL_P (plist)
562 || parse_action_list (plist, macros) < 0)
563 MERROR (MERROR_IM, -1);
564 mplist_put (macros, name, plist);
565 M17N_OBJECT_REF (plist);
569 /* Load an external module from PLIST into EXTERNALS.
571 PLIST ::= ( MODULE-NAME FUNCTION * )
572 EXTERNALS is a plist of MODULE-NAME vs (MIMExternalModule *). */
574 #ifndef DLOPEN_SHLIB_EXT
575 #define DLOPEN_SHLIB_EXT ".so"
579 load_external_module (MPlist *plist, MPlist *externals)
584 MIMExternalModule *external;
588 if (MPLIST_MTEXT_P (plist))
589 module = msymbol ((char *) MTEXT_DATA (MPLIST_MTEXT (plist)));
590 else if (MPLIST_SYMBOL_P (plist))
591 module = MPLIST_SYMBOL (plist);
592 module_file = alloca (strlen (MSYMBOL_NAME (module))
593 + strlen (DLOPEN_SHLIB_EXT) + 1);
594 sprintf (module_file, "%s%s", MSYMBOL_NAME (module), DLOPEN_SHLIB_EXT);
596 handle = dlopen (module_file, RTLD_NOW);
599 fprintf (stderr, "%s\n", dlerror ());
600 MERROR (MERROR_IM, -1);
602 func_list = mplist ();
603 MPLIST_DO (plist, MPLIST_NEXT (plist))
605 if (! MPLIST_SYMBOL_P (plist))
606 MERROR_GOTO (MERROR_IM, err_label);
607 func = dlsym (handle, MSYMBOL_NAME (MPLIST_SYMBOL (plist)));
609 MERROR_GOTO (MERROR_IM, err_label);
610 mplist_add (func_list, MPLIST_SYMBOL (plist), func);
613 MSTRUCT_MALLOC (external, MERROR_IM);
614 external->handle = handle;
615 external->func_list = func_list;
616 mplist_add (externals, module, external);
621 M17N_OBJECT_UNREF (func_list);
626 /** Load a state from PLIST into a newly allocated state object.
628 PLIST ::= ( STATE-NAME STATE-TITLE ? BRANCH * )
629 BRANCH ::= ( MAP-NAME BRANCH-ACTION * )
630 MAPS is a plist of defined maps.
631 Return the state object. */
634 load_state (MPlist *plist, MPlist *maps, MSymbol language, MPlist *macros)
638 MSTRUCT_CALLOC (state, MERROR_IM);
639 if (! MPLIST_SYMBOL_P (plist))
640 MERROR (MERROR_IM, NULL);
641 state->name = MPLIST_SYMBOL (plist);
642 plist = MPLIST_NEXT (plist);
643 if (MPLIST_MTEXT_P (plist))
645 state->title = MPLIST_MTEXT (plist);
646 mtext_put_prop (state->title, 0, mtext_nchars (state->title),
647 Mlanguage, language);
648 M17N_OBJECT_REF (state->title);
649 plist = MPLIST_NEXT (plist);
651 MSTRUCT_CALLOC (state->map, MERROR_IM);
652 MPLIST_DO (plist, plist)
653 if (! MPLIST_PLIST_P (plist)
654 || load_branch (MPLIST_PLIST (plist), maps, state->map, macros) < 0)
655 MERROR (MERROR_IM, NULL);
661 free_map (MIMMap *map)
665 M17N_OBJECT_UNREF (map->map_actions);
668 MPLIST_DO (plist, map->submaps)
669 free_map ((MIMMap *) MPLIST_VAL (plist));
670 M17N_OBJECT_UNREF (map->submaps);
672 M17N_OBJECT_UNREF (map->branch_actions);
676 /* Load an input method from PLIST into IM_INTO, and return it. */
679 load_input_method (MSymbol language, MSymbol name, MPlist *plist,
680 MInputMethodInfo *im_info)
684 MPlist *states = NULL;
685 MPlist *externals = NULL;
686 MPlist *macros = NULL;
689 if (! MPLIST_PLIST_P (plist))
690 MERROR (MERROR_IM, -1);
691 for (; MPLIST_PLIST_P (plist); plist = MPLIST_NEXT (plist))
693 elt = MPLIST_PLIST (plist);
694 if (! MPLIST_SYMBOL_P (elt))
695 MERROR_GOTO (MERROR_IM, err);
696 if (MPLIST_SYMBOL (elt) == Mtitle)
698 elt = MPLIST_NEXT (elt);
699 if (MPLIST_MTEXT_P (elt))
701 title = MPLIST_MTEXT (elt);
702 M17N_OBJECT_REF (title);
705 MERROR_GOTO (MERROR_IM, err);
707 else if (MPLIST_SYMBOL (elt) == Mmap)
709 maps = mplist__from_alist (MPLIST_NEXT (elt));
711 MERROR_GOTO (MERROR_IM, err);
713 else if (MPLIST_SYMBOL (elt) == Mmacro)
716 MPLIST_DO (elt, MPLIST_NEXT (elt))
718 if (! MPLIST_PLIST_P (elt)
719 || load_macros (MPLIST_PLIST (elt), macros) < 0)
720 MERROR_GOTO (MERROR_IM, err);
723 else if (MPLIST_SYMBOL (elt) == Mmodule)
725 externals = mplist ();
726 MPLIST_DO (elt, MPLIST_NEXT (elt))
728 if (! MPLIST_PLIST_P (elt)
729 || load_external_module (MPLIST_PLIST (elt), externals) < 0)
730 MERROR_GOTO (MERROR_IM, err);
733 else if (MPLIST_SYMBOL (elt) == Mstate)
736 MPLIST_DO (elt, MPLIST_NEXT (elt))
740 if (! MPLIST_PLIST_P (elt))
741 MERROR_GOTO (MERROR_IM, err);
742 state = load_state (MPLIST_PLIST (elt), maps, language, macros);
744 MERROR_GOTO (MERROR_IM, err);
745 mplist_put (states, state->name, state);
750 MPLIST_DO (elt, maps)
751 M17N_OBJECT_UNREF (MPLIST_VAL (elt));
752 M17N_OBJECT_UNREF (maps);
754 title = mtext_from_data (MSYMBOL_NAME (name), MSYMBOL_NAMELEN (name),
755 MTEXT_FORMAT_US_ASCII);
756 im_info->title = title;
757 im_info->externals = externals;
758 im_info->macros = macros;
759 im_info->states = states;
765 MPLIST_DO (elt, maps)
766 M17N_OBJECT_UNREF (MPLIST_VAL (elt));
767 M17N_OBJECT_UNREF (maps);
770 M17N_OBJECT_UNREF (title);
773 MPLIST_DO (plist, states)
775 MIMState *state = (MIMState *) MPLIST_VAL (plist);
778 M17N_OBJECT_UNREF (state->title);
780 free_map (state->map);
783 M17N_OBJECT_UNREF (states);
787 MPLIST_DO (plist, externals)
789 MIMExternalModule *external = MPLIST_VAL (plist);
791 dlclose (external->handle);
792 M17N_OBJECT_UNREF (external->func_list);
794 MPLIST_KEY (plist) = Mt;
796 M17N_OBJECT_UNREF (externals);
803 static int take_action_list (MInputContext *ic, MPlist *action_list);
806 shift_state (MInputContext *ic, MSymbol state_name)
808 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
809 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
810 MIMState *state = ic_info->state;
812 /* Find a state to shift to. If not found, shift to the initial
814 state = (MIMState *) mplist_get (im_info->states, state_name);
816 state = (MIMState *) MPLIST_VAL (im_info->states);
818 /* Enter the new state. */
819 ic_info->state = state;
820 ic_info->map = state->map;
821 ic_info->state_key_head = ic_info->key_head;
822 if (state == (MIMState *) MPLIST_VAL (im_info->states))
824 /* We have shifted to the initial state. */
827 mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit),
828 Mcandidate_list, NULL, 0);
829 mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit),
830 Mcandidate_index, NULL, 0);
831 mtext_cat (ic->produced, ic->preedit);
832 mtext_reset (ic->preedit);
833 ic->candidate_list = NULL;
834 ic->candidate_show = 0;
835 ic->preedit_changed = ic->candidates_changed = 1;
836 MPLIST_DO (p, ic_info->markers)
838 MPLIST_DO (p, ic_info->vars)
841 memmove (ic_info->keys, ic_info->keys + ic_info->state_key_head,
842 sizeof (int) * (ic_info->used - ic_info->state_key_head));
843 ic_info->used -= ic_info->state_key_head;
844 ic_info->state_key_head = ic_info->key_head = 0;
846 mtext_cpy (ic_info->preedit_saved, ic->preedit);
847 ic_info->state_pos = ic->cursor_pos;
848 ic->status = state->title;
850 ic->status = im_info->title;
851 ic->status_changed = 1;
852 if (ic_info->key_head == ic_info->used
853 && ic_info->map == ic_info->state->map
854 && ic_info->map->map_actions)
855 take_action_list (ic, ic_info->map->map_actions);
860 find_candidates_group (MPlist *plist, int index,
861 int *start_index, int *end_index, int *group_index)
863 int i = 0, gidx = 0, len;
865 MPLIST_DO (plist, plist)
867 if (MPLIST_MTEXT_P (plist))
868 len = mtext_nchars (MPLIST_MTEXT (plist));
870 len = mplist_length (MPLIST_PLIST (plist));
876 *end_index = i + len;
888 preedit_insert (MInputContext *ic, int pos, MText *mt, int c)
890 MInputContextInfo *ic_info = ((MInputContext *) ic)->info;
892 int nchars = mt ? mtext_nchars (mt) : 1;
895 mtext_ins (ic->preedit, pos, mt);
897 mtext_ins_char (ic->preedit, pos, c, 1);
898 MPLIST_DO (markers, ic_info->markers)
899 if (MPLIST_INTEGER (markers) > pos)
900 MPLIST_VAL (markers) = (void *) (MPLIST_INTEGER (markers) + nchars);
901 if (ic->cursor_pos >= pos)
902 ic->cursor_pos += nchars;
903 ic->preedit_changed = 1;
908 preedit_delete (MInputContext *ic, int from, int to)
910 MInputContextInfo *ic_info = ((MInputContext *) ic)->info;
913 mtext_del (ic->preedit, from, to);
914 MPLIST_DO (markers, ic_info->markers)
916 if (MPLIST_INTEGER (markers) > to)
918 = (void *) (MPLIST_INTEGER (markers) - (to - from));
919 else if (MPLIST_INTEGER (markers) > from);
920 MPLIST_VAL (markers) = (void *) from;
922 if (ic->cursor_pos >= to)
923 ic->cursor_pos -= to - from;
924 else if (ic->cursor_pos > from)
925 ic->cursor_pos = from;
926 ic->preedit_changed = 1;
931 new_index (MInputContext *ic, int current, int limit, MSymbol sym, MText *mt)
933 int code = marker_code (sym);
935 if (mt && (code == '[' || code == ']'))
939 if (code == '[' && current > 0)
941 if (mtext_prop_range (mt, Mcandidate_list, pos - 1, &pos, NULL, 1)
945 else if (code == ']' && current < mtext_nchars (mt))
947 if (mtext_prop_range (mt, Mcandidate_list, pos, NULL, &pos, 1))
953 return (code == '<' ? 0
954 : code == '>' ? limit
955 : code == '-' ? current - 1
956 : code == '+' ? current + 1
957 : code == '=' ? current
958 : code - '0' > limit ? limit
962 return (int) mplist_get (((MInputContextInfo *) ic->info)->markers, sym);
966 udpate_candidate (MInputContext *ic, MTextProperty *prop, int idx)
968 int from = mtext_property_start (prop);
969 int to = mtext_property_end (prop);
971 MPlist *candidate_list = mtext_property_value (prop);
972 MPlist *group = find_candidates_group (candidate_list, idx, &start,
974 int ingroup_index = idx - start;
977 preedit_delete (ic, from, to);
978 if (MPLIST_MTEXT_P (group))
980 mt = MPLIST_MTEXT (group);
981 preedit_insert (ic, from, NULL, mtext_ref_char (mt, ingroup_index));
989 for (i = 0, plist = MPLIST_PLIST (group); i < ingroup_index;
990 i++, plist = MPLIST_NEXT (plist));
991 mt = MPLIST_MTEXT (plist);
992 preedit_insert (ic, from, mt, 0);
993 to = from + mtext_nchars (mt);
995 mtext_put_prop (ic->preedit, from, to, Mcandidate_list, candidate_list);
996 mtext_put_prop (ic->preedit, from, to, Mcandidate_index, (void *) idx);
1002 take_action_list (MInputContext *ic, MPlist *action_list)
1004 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1005 MPlist *candidate_list = ic->candidate_list;
1006 int candidate_index = ic->candidate_index;
1007 int candidate_show = ic->candidate_show;
1008 MTextProperty *prop;
1010 MPLIST_DO (action_list, action_list)
1016 if (MPLIST_MTEXT_P (action_list)
1017 || MPLIST_INTEGER_P (action_list))
1018 name = Minsert, args = action_list;
1019 else if (MPLIST_PLIST_P (action_list)
1020 && (MPLIST_MTEXT_P (MPLIST_PLIST (action_list))
1021 || MPLIST_PLIST_P (MPLIST_PLIST (action_list))))
1022 name = Minsert, args = action_list;
1025 action = MPLIST_PLIST (action_list);
1026 name = MPLIST_SYMBOL (action);
1027 args = MPLIST_NEXT (action);
1030 if (name == Minsert)
1032 if (MPLIST_MTEXT_P (args))
1033 preedit_insert (ic, ic->cursor_pos, MPLIST_MTEXT (args), 0);
1034 else if (MPLIST_INTEGER_P (args))
1035 preedit_insert (ic, ic->cursor_pos, NULL, MPLIST_INTEGER (args));
1036 else if (MPLIST_SYMBOL_P (args))
1038 int c = integer_value (ic, args);
1040 if (c >= 0 && c <= MCHAR_MAX)
1041 preedit_insert (ic, ic->cursor_pos, NULL, c);
1048 args = MPLIST_PLIST (args);
1049 if (MPLIST_MTEXT_P (args))
1051 preedit_insert (ic, ic->cursor_pos, NULL,
1052 mtext_ref_char (MPLIST_MTEXT (args), 0));
1057 mt = MPLIST_MTEXT (MPLIST_PLIST (args));
1058 preedit_insert (ic, ic->cursor_pos, mt, 0);
1059 len = mtext_nchars (mt);
1061 mtext_put_prop (ic->preedit,
1062 ic->cursor_pos - len, ic->cursor_pos,
1063 Mcandidate_list, args);
1064 mtext_put_prop (ic->preedit,
1065 ic->cursor_pos - len, ic->cursor_pos,
1066 Mcandidate_index, (void *) 0);
1069 else if (name == Mselect)
1072 int code, idx, gindex;
1073 int pos = ic->cursor_pos;
1077 || ! (prop = mtext_get_property (ic->preedit, pos - 1,
1080 if (MPLIST_SYMBOL_P (args))
1082 code = marker_code (MPLIST_SYMBOL (args));
1088 idx = (int) mtext_get_prop (ic->preedit, pos - 1, Mcandidate_index);
1089 group = find_candidates_group (mtext_property_value (prop), idx,
1090 &start, &end, &gindex);
1092 if (code != '[' && code != ']')
1096 ? new_index (NULL, ic->candidate_index - start,
1097 end - start - 1, MPLIST_SYMBOL (args),
1099 : MPLIST_INTEGER (args)));
1102 && MPLIST_TAIL_P (MPLIST_NEXT (group))))
1107 int ingroup_index = idx - start;
1110 group = mtext_property_value (prop);
1111 len = mplist_length (group);
1124 for (idx = 0; gindex > 0; gindex--, group = MPLIST_NEXT (group))
1125 idx += (MPLIST_MTEXT_P (group)
1126 ? mtext_nchars (MPLIST_MTEXT (group))
1127 : mplist_length (MPLIST_PLIST (group)));
1128 len = (MPLIST_MTEXT_P (group)
1129 ? mtext_nchars (MPLIST_MTEXT (group))
1130 : mplist_length (MPLIST_PLIST (group)));
1131 if (ingroup_index >= len)
1132 ingroup_index = len - 1;
1133 idx += ingroup_index;
1135 udpate_candidate (ic, prop, idx);
1137 else if (name == Mshow)
1138 ic->candidate_show = 1;
1139 else if (name == Mhide)
1140 ic->candidate_show = 0;
1141 else if (name == Mdelete)
1143 int len = mtext_nchars (ic->preedit);
1144 int to = (MPLIST_SYMBOL_P (args)
1145 ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
1147 : MPLIST_INTEGER (args));
1153 if (to < ic->cursor_pos)
1154 preedit_delete (ic, to, ic->cursor_pos);
1155 else if (to > ic->cursor_pos)
1156 preedit_delete (ic, ic->cursor_pos, to);
1158 else if (name == Mmove)
1160 int len = mtext_nchars (ic->preedit);
1162 = (MPLIST_SYMBOL_P (args)
1163 ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
1165 : MPLIST_INTEGER (args));
1171 if (pos != ic->cursor_pos)
1173 ic->cursor_pos = pos;
1174 ic->preedit_changed = 1;
1177 else if (name == Mmark)
1179 int code = marker_code (MPLIST_SYMBOL (args));
1182 mplist_put (ic_info->markers, MPLIST_SYMBOL (args),
1183 (void *) ic->cursor_pos);
1185 else if (name == Mpushback)
1187 int num = MPLIST_INTEGER (args);
1190 ic_info->key_head -= num;
1192 ic_info->key_head = num;
1193 if (ic_info->key_head > ic_info->used)
1194 ic_info->key_head = ic_info->used;
1196 else if (name == Mcall)
1198 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1199 MIMExternalFunc func = NULL;
1200 MSymbol module, func_name;
1201 MPlist *func_args, *val;
1204 module = MPLIST_SYMBOL (args);
1205 args = MPLIST_NEXT (args);
1206 func_name = MPLIST_SYMBOL (args);
1208 if (im_info->externals)
1210 MIMExternalModule *external
1211 = (MIMExternalModule *) mplist_get (im_info->externals,
1214 func = (MIMExternalFunc) mplist_get (external->func_list,
1219 func_args = mplist ();
1220 mplist_add (func_args, Mt, ic);
1221 MPLIST_DO (args, MPLIST_NEXT (args))
1225 if (MPLIST_KEY (args) == Msymbol
1226 && MPLIST_KEY (args) != Mnil
1227 && (code = marker_code (MPLIST_SYMBOL (args))) >= 0)
1229 code = new_index (ic, ic->cursor_pos,
1230 mtext_nchars (ic->preedit),
1231 MPLIST_SYMBOL (args), ic->preedit);
1232 mplist_add (func_args, Minteger, (void *) code);
1235 mplist_add (func_args, MPLIST_KEY (args), MPLIST_VAL (args));
1237 val = (func) (func_args);
1238 M17N_OBJECT_UNREF (func_args);
1239 if (val && ! MPLIST_TAIL_P (val))
1240 ret = take_action_list (ic, val);
1241 M17N_OBJECT_UNREF (val);
1245 else if (name == Mshift)
1247 shift_state (ic, MPLIST_SYMBOL (args));
1249 else if (name == Mundo)
1251 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1254 mtext_reset (ic->preedit);
1255 mtext_reset (ic_info->preedit_saved);
1256 ic->cursor_pos = ic_info->state_pos = 0;
1257 ic_info->state_key_head = ic_info->key_head = 0;
1259 if (ic_info->used < 0)
1264 shift_state (ic, ((MIMState *) MPLIST_VAL (im_info->states))->name);
1269 else if (name == Mset || name == Madd || name == Msub
1270 || name == Mmul || name == Mdiv)
1272 MSymbol sym = MPLIST_SYMBOL (args);
1273 int val1 = (int) mplist_get (ic_info->vars, sym), val2;
1275 args = MPLIST_NEXT (args);
1276 val2 = integer_value (ic, args);
1279 else if (name == Madd)
1281 else if (name == Msub)
1283 else if (name == Mmul)
1287 mplist_put (ic_info->vars, sym, (void *) val1);
1289 else if (name == Mequal || name == Mless || name == Mgreater)
1292 MPlist *actions1, *actions2;
1295 val1 = integer_value (ic, args);
1296 args = MPLIST_NEXT (args);
1297 val2 = integer_value (ic, args);
1298 args = MPLIST_NEXT (args);
1299 actions1 = MPLIST_PLIST (args);
1300 args = MPLIST_NEXT (args);
1301 if (MPLIST_TAIL_P (args))
1304 actions2 = MPLIST_PLIST (args);
1305 if (name == Mequal ? val1 == val2
1306 : name == Mless ? val1 < val2
1308 ret = take_action_list (ic, actions1);
1310 ret = take_action_list (ic, actions2);
1316 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1320 && (actions = mplist_get (im_info->macros, name)))
1322 if (take_action_list (ic, actions) < 0)
1329 ic->candidate_list = NULL;
1330 if (ic->cursor_pos > 0
1331 && (prop = mtext_get_property (ic->preedit, ic->cursor_pos - 1,
1334 ic->candidate_list = mtext_property_value (prop);
1336 = (int) mtext_get_prop (ic->preedit, ic->cursor_pos - 1,
1338 ic->candidate_from = mtext_property_start (prop);
1339 ic->candidate_to = mtext_property_end (prop);
1342 ic->candidates_changed |= (candidate_list != ic->candidate_list
1343 || candidate_index != ic->candidate_index
1344 || candidate_show != ic->candidate_show);
1349 /* Handle the input key KEY in the current state and map specified in
1350 the input context IC. If KEY is handled correctly, return 0.
1351 Otherwise, return -1. */
1354 handle_key (MInputContext *ic)
1356 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1357 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1358 MIMMap *map = ic_info->map;
1359 MIMMap *submap = NULL;
1360 MSymbol key = ic_info->keys[ic_info->key_head];
1365 submap = mplist_get (map->submaps, key);
1366 if (! submap && (key = msymbol_get (key, M_key_alias)) != Mnil)
1367 submap = mplist_get (map->submaps, key);
1372 mtext_cpy (ic->preedit, ic_info->preedit_saved);
1373 ic->cursor_pos = ic_info->state_pos;
1374 ic_info->key_head++;
1375 ic_info->map = map = submap;
1376 if (map->map_actions)
1378 if (take_action_list (ic, map->map_actions) < 0)
1381 else if (map->submaps)
1383 for (i = ic_info->state_key_head; i < ic_info->key_head; i++)
1385 MSymbol key = ic_info->keys[i];
1386 char *name = msymbol_name (key);
1388 if (! name[0] || ! name[1])
1389 mtext_ins_char (ic->preedit, ic->cursor_pos++, name[0], 1);
1391 ic->preedit_changed = 1;
1394 /* If this is the terminal map or we have shifted to another
1395 state, perform branch actions (if any). */
1396 if (! map->submaps || map != ic_info->map)
1398 if (map->branch_actions)
1400 if (take_action_list (ic, map->branch_actions) < 0)
1403 /* If MAP is still not the root map, shift to the current
1405 if (ic_info->map != ic_info->state->map)
1406 shift_state (ic, ic_info->state->name);
1411 /* MAP can not handle KEY. */
1413 /* If MAP is the root map of the initial state, it means that
1414 the current input method can not handle KEY. */
1415 if (map == ((MIMState *) MPLIST_VAL (im_info->states))->map)
1418 if (map != ic_info->state->map)
1420 /* If MAP is not the root map... */
1421 /* If MAP has branch actions, perform them. */
1422 if (map->branch_actions)
1423 take_action_list (ic, map->branch_actions);
1424 /* If MAP is still not the root map, shift to the current
1426 if (ic_info->map != ic_info->state->map)
1428 shift_state (ic, ic_info->state->name);
1429 /* If MAP has branch_actions, perform them. */
1430 if (ic_info->map->branch_actions)
1431 take_action_list (ic, ic_info->map->branch_actions);
1436 /* MAP is the root map, perform branch actions (if any) or
1437 shift to the initial state. */
1438 if (map->branch_actions)
1439 take_action_list (ic, map->branch_actions);
1442 ((MIMState *) MPLIST_VAL (im_info->states))->name);
1449 reset_ic (MInputContext *ic)
1451 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1452 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1454 MLIST_RESET (ic_info);
1455 ic_info->state = (MIMState *) MPLIST_VAL (im_info->states);
1456 ic_info->map = ic_info->state->map;
1457 ic_info->state_key_head = ic_info->key_head = 0;
1458 ic->cursor_pos = ic_info->state_pos = 0;
1459 ic->status = ic_info->state->title;
1461 ic->status = im_info->title;
1462 ic->candidate_list = NULL;
1463 ic->candidate_show = 0;
1464 ic->status_changed = ic->preedit_changed = ic->candidates_changed = 1;
1465 if (ic_info->map->map_actions)
1466 take_action_list (ic, ic_info->map->map_actions);
1470 open_im (MInputMethod *im)
1473 MInputMethodInfo *im_info;
1477 mdb = mdatabase_find (Minput_method, im->language, im->name, Mnil);
1480 plist = mdatabase_load (mdb);
1482 MERROR (MERROR_IM, -1);
1483 MSTRUCT_CALLOC (im_info, MERROR_IM);
1485 result = load_input_method (im->language, im->name, plist, im_info);
1486 M17N_OBJECT_UNREF (plist);
1488 MERROR (MERROR_IM, -1);
1493 close_im (MInputMethod *im)
1495 MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
1499 M17N_OBJECT_UNREF (im_info->title);
1500 if (im_info->states)
1502 MPLIST_DO (plist, im_info->states)
1504 MIMState *state = (MIMState *) MPLIST_VAL (plist);
1507 M17N_OBJECT_UNREF (state->title);
1509 free_map (state->map);
1512 M17N_OBJECT_UNREF (im_info->states);
1515 if (im_info->macros)
1517 MPLIST_DO (plist, im_info->macros)
1518 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
1519 M17N_OBJECT_UNREF (im_info->macros);
1522 if (im_info->externals)
1524 MPLIST_DO (plist, im_info->externals)
1526 MIMExternalModule *external = MPLIST_VAL (plist);
1528 dlclose (external->handle);
1529 M17N_OBJECT_UNREF (external->func_list);
1531 MPLIST_KEY (plist) = Mt;
1533 M17N_OBJECT_UNREF (im_info->externals);
1541 create_ic (MInputContext *ic)
1543 MInputMethod *im = ic->im;
1544 MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
1545 MInputContextInfo *ic_info;
1548 ic_info = (MInputContextInfo *) ic->info;
1551 MSTRUCT_CALLOC (ic_info, MERROR_IM);
1554 MLIST_INIT1 (ic_info, keys, 8);
1555 ic_info->markers = mplist ();
1556 ic_info->vars = mplist ();
1557 ic_info->preedit_saved = mtext ();
1558 if (im_info->externals)
1560 MPlist *func_args = mplist (), *plist;
1562 mplist_add (func_args, Mt, ic);
1563 MPLIST_DO (plist, im_info->externals)
1565 MIMExternalModule *external = MPLIST_VAL (plist);
1566 MIMExternalFunc func
1567 = (MIMExternalFunc) mplist_get (external->func_list, Minit);
1572 M17N_OBJECT_UNREF (func_args);
1579 destroy_ic (MInputContext *ic)
1581 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1582 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1584 if (im_info->externals)
1586 MPlist *func_args = mplist (), *plist;
1588 mplist_add (func_args, Mt, ic);
1589 MPLIST_DO (plist, im_info->externals)
1591 MIMExternalModule *external = MPLIST_VAL (plist);
1592 MIMExternalFunc func
1593 = (MIMExternalFunc) mplist_get (external->func_list, Mfini);
1598 M17N_OBJECT_UNREF (func_args);
1600 MLIST_FREE1 (ic_info, keys);
1601 M17N_OBJECT_UNREF (ic_info->preedit_saved);
1602 M17N_OBJECT_UNREF (ic_info->markers);
1603 M17N_OBJECT_UNREF (ic_info->vars);
1608 /** Handle the input key KEY in the current state and map of IC->info.
1609 If KEY is handled but no text is produced, return 0, otherwise
1615 filter (MInputContext *ic, MSymbol key, void *arg)
1617 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1618 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1621 mtext_reset (ic->produced);
1622 ic->status_changed = ic->preedit_changed = ic->candidates_changed = 0;
1623 MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
1624 ic_info->key_unhandled = 0;
1626 if (handle_key (ic) < 0)
1628 /* KEY was not handled. Reset the status and break the
1631 /* This forces returning 1. */
1632 ic_info->key_unhandled = 1;
1639 ic_info->key_unhandled = 1;
1642 /* Break the loop if all keys were handled. */
1643 } while (ic_info->key_head < ic_info->used);
1645 /* If the current map is the root of the initial state, we should
1646 produce any preedit text in ic->produced. */
1647 if (ic_info->map == ((MIMState *) MPLIST_VAL (im_info->states))->map
1648 && mtext_nchars (ic->preedit) > 0)
1649 shift_state (ic, ((MIMState *) MPLIST_VAL (im_info->states))->name);
1651 if (mtext_nchars (ic->produced) > 0)
1653 MSymbol lang = msymbol_get (ic->im->language, Mlanguage);
1656 mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
1657 Mlanguage, ic->im->language);
1660 return (! ic_info->key_unhandled && mtext_nchars (ic->produced) == 0);
1664 /** Return 1 if the last event or key was not handled, otherwise
1667 There is no need of looking up because ic->produced should already
1668 contain the produced text (if any).
1673 lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
1675 mtext_cat (mt, ic->produced);
1676 mtext_reset (ic->produced);
1677 return (((MInputContextInfo *) ic->info)->key_unhandled ? -1 : 0);
1680 /* Support functions for mdebug_dump_im. */
1683 dump_im_map (MPlist *map_list, int indent)
1686 MSymbol key = MPLIST_KEY (map_list);
1687 MIMMap *map = (MIMMap *) MPLIST_VAL (map_list);
1689 prefix = (char *) alloca (indent + 1);
1690 memset (prefix, 32, indent);
1691 prefix[indent] = '\0';
1693 fprintf (stderr, "(\"%s\" ", msymbol_name (key));
1694 if (map->map_actions)
1695 mdebug_dump_plist (map->map_actions, indent + 2);
1698 MPLIST_DO (map_list, map->submaps)
1700 fprintf (stderr, "\n%s ", prefix);
1701 dump_im_map (map_list, indent + 2);
1704 if (map->branch_actions)
1706 fprintf (stderr, "\n%s (branch\n%s ", prefix, prefix);
1707 mdebug_dump_plist (map->branch_actions, indent + 4);
1708 fprintf (stderr, ")");
1710 fprintf (stderr, ")");
1715 dump_im_state (MIMState *state, int indent)
1720 prefix = (char *) alloca (indent + 1);
1721 memset (prefix, 32, indent);
1722 prefix[indent] = '\0';
1724 fprintf (stderr, "(%s", msymbol_name (state->name));
1725 if (state->map->submaps)
1727 MPLIST_DO (map_list, state->map->submaps)
1729 fprintf (stderr, "\n%s ", prefix);
1730 dump_im_map (map_list, indent + 2);
1733 fprintf (stderr, ")");
1742 = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1743 "BackSpace", "Tab", "Linefeed", "Clear", NULL, "Return", NULL, NULL,
1744 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1745 NULL, NULL, NULL, "Escape", NULL, NULL, NULL, NULL };
1746 char buf[6], buf2[256];
1749 Minput_method = msymbol ("input-method");
1750 Minput_driver = msymbol ("input-driver");
1751 Mtitle = msymbol ("title");
1752 Mmacro = msymbol ("macro");
1753 Mmodule = msymbol ("module");
1754 Mmap = msymbol ("map");
1755 Mstate = msymbol ("state");
1756 Minsert = msymbol ("insert");
1757 Mdelete = msymbol ("delete");
1758 Mmove = msymbol ("move");
1759 Mmark = msymbol ("mark");
1760 Mpushback = msymbol ("pushback");
1761 Mundo = msymbol ("undo");
1762 Mcall = msymbol ("call");
1763 Mshift = msymbol ("shift");
1764 Mselect = msymbol ("select");
1765 Mshow = msymbol ("show");
1766 Mhide = msymbol ("hide");
1767 Mset = msymbol ("set");
1768 Madd = msymbol ("add");
1769 Msub = msymbol ("sub");
1770 Mmul = msymbol ("mul");
1771 Mdiv = msymbol ("div");
1772 Mequal = msymbol ("=");
1773 Mless = msymbol ("<");
1774 Mgreater = msymbol (">");
1776 Minput_preedit_start = msymbol ("input-preedit-start");
1777 Minput_preedit_done = msymbol ("input-preedit-done");
1778 Minput_preedit_draw = msymbol ("input-preedit-draw");
1779 Minput_status_start = msymbol ("input-status-start");
1780 Minput_status_done = msymbol ("input-status-done");
1781 Minput_status_draw = msymbol ("input-status-draw");
1782 Minput_candidates_start = msymbol ("input-candidates-start");
1783 Minput_candidates_done = msymbol ("input-candidates-done");
1784 Minput_candidates_draw = msymbol ("input-candidates-draw");
1785 Minput_set_spot = msymbol ("input-set-spot");
1786 Minput_toggle = msymbol ("input-toggle");
1788 Mcandidate_list = msymbol_as_managing_key (" candidate-list");
1789 Mcandidate_index = msymbol (" candidate-index");
1791 Minit = msymbol ("init");
1792 Mfini = msymbol ("fini");
1794 M_key_alias = msymbol (" key-alias");
1799 for (i = 0, buf[2] = '@'; i < ' '; i++, buf[2]++)
1801 one_char_symbol[i] = msymbol (buf);
1803 msymbol_put (one_char_symbol[i], M_key_alias, msymbol (key_names[i]));
1805 for (buf[2] = i; i < 127; i++, buf[2]++)
1806 one_char_symbol[i] = msymbol (buf + 2);
1807 one_char_symbol[i++] = msymbol ("Delete");
1813 for (buf[4] = '@'; i < 160; i++, buf[4]++)
1815 one_char_symbol[i] = msymbol (buf);
1816 if (key_names[i - 128])
1818 strcpy (buf2 + 2, key_names[i - 128]);
1819 msymbol_put (one_char_symbol[i], M_key_alias, msymbol (buf2));
1822 for (buf[4] = i - 128; i < 255; i++, buf[4]++)
1823 one_char_symbol[i] = msymbol (buf + 2);
1824 one_char_symbol[i] = msymbol ("M-Delete");
1826 minput_default_driver.open_im = open_im;
1827 minput_default_driver.close_im = close_im;
1828 minput_default_driver.create_ic = create_ic;
1829 minput_default_driver.destroy_ic = destroy_ic;
1830 minput_default_driver.filter = filter;
1831 minput_default_driver.lookup = lookup;
1832 minput_default_driver.callback_list = NULL;
1833 minput_driver = &minput_default_driver;
1840 if (minput_default_driver.callback_list)
1842 M17N_OBJECT_UNREF (minput_default_driver.callback_list);
1843 minput_default_driver.callback_list = NULL;
1845 if (minput_driver->callback_list)
1847 M17N_OBJECT_UNREF (minput_driver->callback_list);
1848 minput_driver->callback_list = NULL;
1853 minput__callback (MInputContext *ic, MSymbol command)
1855 if (ic->im->driver.callback_list)
1857 MInputCallbackFunc func
1858 = (MInputCallbackFunc) mplist_get (ic->im->driver.callback_list,
1862 (func) (ic, command);
1867 minput__char_to_key (int c)
1869 if (c < 0 || c >= 0x100)
1872 return one_char_symbol[c];
1876 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1881 /*** @addtogroup m17nInputMethod */
1886 @name Variables: Predefined symbols for callback commands.
1888 These are the predefined symbols that are used as the @c COMMAND
1889 argument of callback functions of an input method driver (see
1890 #MInputDriver::callback_list ). */
1892 @name ÊÑ¿ô¡§ ¥³¡¼¥ë¥Ð¥Ã¥¯¥³¥Þ¥ó¥ÉÍÑÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë.
1894 ÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Î¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Ë¤ª¤¤¤Æ @c COMMAND °ú¿ô¤È¤·
1895 ¤ÆÍѤ¤¤é¤ì¤ëÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë (#MInputDriver::callback_list »²¾È)¡£
1900 MSymbol Minput_preedit_start;
1901 MSymbol Minput_preedit_done;
1902 MSymbol Minput_preedit_draw;
1903 MSymbol Minput_status_start;
1904 MSymbol Minput_status_done;
1905 MSymbol Minput_status_draw;
1906 MSymbol Minput_candidates_start;
1907 MSymbol Minput_candidates_done;
1908 MSymbol Minput_candidates_draw;
1909 MSymbol Minput_set_spot;
1910 MSymbol Minput_toggle;
1915 @brief The default driver for internal input methods.
1917 The variable #minput_default_driver is the default driver for
1918 internal input methods.
1920 The member MInputDriver::open_im () searches the m17n database for
1921 an input method that matches the tag \< #Minput_method, $LANGUAGE,
1922 $NAME\> and loads it.
1924 The member MInputDriver::callback_list () is @c NULL. Thus, it is
1925 programmers responsibility to set it to a plist of proper callback
1926 functions. Otherwise, no feedback information (e.g. preedit text)
1927 can be shown to users.
1929 The macro M17N_INIT () sets the variable #minput_driver to the
1930 pointer to this driver so that all internal input methods use it.
1932 Therefore, unless @c minput_driver is set differently, the driver
1933 dependent arguments $ARG of the functions whose name begin with
1934 "minput_" are all ignored. */
1937 @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥǥե©¥ë¥È¥É¥é¥¤¥Ð.
1939 ÆþÎϥɥ饤¥Ð #minput_default_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѤΥǥե©¥ë
1940 ¥È¤Î¥É¥é¥¤¥Ð¤Ç¤¢¤ë¡£
1942 ¥á¥ó¥Ð MInputDriver::open_im () ¤Ï m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹Ã椫¤é¥¿¥°
1943 \< #Minput_method, $LANGUAGE, $NAME\> ¤Ë¹çÃפ¹¤ëÆþÎϥ᥽¥Ã¥É¤òõ¤·¡¢
1946 ¥á¥ó¥Ð MInputDriver::callback_list () ¤Ï @c NULL ¤Ê¤Î¤Ç¡¢¥×¥í¥°¥é
1947 ¥Þ¦¤ÇÀÕǤ¤ò»ý¤Ã¤Æ, ŬÀڤʥ³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Î plist ¤ËÀßÄꤷ¤Ê¤¯¤Æ
1948 ¤Ï¤Ê¤é¤Ê¤¤¡£¤µ¤â¤Ê¤¤¤È¡¢preedit ¥Æ¥¥¹¥È¤Ê¤É¤Î¥Õ¥£¡¼¥É¥Ð¥Ã¥¯¾ðÊó¤¬
1949 ¥æ¡¼¥¶¤Ëɽ¼¨¤µ¤ì¤Ê¤¤¡£
1951 ¥Þ¥¯¥í M17N_INIT () ¤ÏÊÑ¿ô #minput_driver ¤ò¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó
1952 ¥¿¤ËÀßÄꤷ¡¢Á´¤Æ¤ÎÆâÉôÆþÎϥ᥽¥Ã¥É¤¬¤³¤Î¥É¥é¥¤¥Ð¤ò»È¤¦¤è¤¦¤Ë¤¹¤ë¡£
1954 ¤·¤¿¤¬¤Ã¤Æ¡¢@c minput_driver ¤¬¥Ç¥Õ¥©¥ë¥ÈÃͤΤޤޤǤ¢¤ì¤Ð¡¢minput_
1955 ¤Ç»Ï¤Þ¤ë´Ø¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô $ARG ¤Ï¤¹¤Ù¤Æ̵»ë¤µ¤ì¤ë¡£ */
1957 MInputDriver minput_default_driver;
1961 @brief The driver for internal input methods.
1963 The variable #minput_driver is a pointer to the input method
1964 driver that is used by internal input methods. The macro
1965 M17N_INIT () initializes it to a pointer to #minput_default_driver
1966 (if <m17n.h> is included) or to #minput_gui_driver (if
1967 <m17n-gui.h> is included). */
1969 @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥɥ饤¥Ð.
1971 ÊÑ¿ô #minput_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤Æ»ÈÍѤµ¤ì¤Æ¤¤¤ëÆþÎÏ¥á
1972 ¥½¥Ã¥É¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£¥Þ¥¯¥íM17N_INIT () ¤Ï¤³¤Î¥Ý¥¤¥ó
1973 ¥¿¤ò #minput_default_driver (<m17n.h> ¤¬´Þ¤Þ¤ì¤ë»þ) ¤Þ¤¿¤Ï
1974 #minput_gui_driver ( <m17n-gui.h> ¤¬´Þ¤Þ¤ì¤ë»þ) ¤Ë½é´ü²½¤¹¤ë¡£ */
1976 MInputDriver *minput_driver;
1978 MSymbol Minput_driver;
1983 @brief Open an input method.
1985 The minput_open_im () function opens an input method that matches
1986 language $LANGUAGE and name $NAME, and returns a pointer to the
1987 input method object newly allocated.
1989 This function at first decides an driver for the input method as
1992 If $LANGUAGE is not #Mnil, the driver pointed by the variable
1993 #minput_driver is used.
1995 If $LANGUAGE is #Mnil and $NAME has #Minput_driver property, the
1996 driver pointed to by the property value is used to open the input
1997 method. If $NAME has no such property, @c NULL is returned.
1999 Then, the member MInputDriver::open_im () of the driver is
2002 $ARG is set in the member @c arg of the structure MInputMethod so
2003 that the driver can refer to it. */
2006 @brief ÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë.
2008 ´Ø¿ô minput_open_im () ¤Ï¸À¸ì $LANGUAGE ¤È̾Á° $NAME ¤Ë¹çÃפ¹¤ëÆþ
2009 Îϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤·¡¢¿·¤¿¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿ÆþÎϥ᥽¥Ã¥É¥ª¥Ö¥¸¥§¥¯
2010 ¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
2012 ¤³¤Î´Ø¿ô¤Ï¡¢¤Þ¤ºÆþÎϥ᥽¥Ã¥ÉÍѤΥɥ饤¥Ð¤ò°Ê²¼¤Î¤è¤¦¤Ë¤·¤Æ·èÄꤹ¤ë¡£
2014 $LANGUAGE ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢ÊÑ¿ô #minput_driver ¤Ç»Ø¤µ¤ì¤Æ¤¤¤ë
2017 $LANGUAGE ¤¬ #Mnil ¤Ç¤¢¤ê¡¢$NAME ¤¬ #Minput_driver ¥×¥í¥Ñ¥Æ¥£¤ò»ý
2018 ¤Ä¾ì¹ç¤Ë¤Ï¡¢¤½¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤǻؤµ¤ì¤Æ¤¤¤ëÆþÎϥɥ饤¥Ð¤òÍѤ¤¤ÆÆþ
2019 Îϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë¡£$NAME ¤Ë¤½¤Î¤è¤¦¤Ê¥×¥í¥Ñ¥Æ¥£¤¬Ìµ¤«¤Ã¤¿¾ì
2020 ¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
2022 ¼¡¤¤¤Ç¡¢¥É¥é¥¤¥Ð¤Î¥á¥ó¥Ð MInputDriver::open_im () ¤¬¸Æ¤Ð¤ì¤ë¡£
2024 $ARG ¤Ï¡¢¥É¥é¥¤¥Ð¤¬»²¾È¤Ç¤¤ë¤è¤¦¤Ë¡¢¹½Â¤ÂÎ MInputMethod ¤Î¥á¥ó¥Ð
2025 @c arg ¤ËÀßÄꤵ¤ì¤ë¡£
2027 @latexonly \IPAlabel{minput_open} @endlatexonly
2032 minput_open_im (MSymbol language, MSymbol name, void *arg)
2035 MInputDriver *driver;
2038 driver = minput_driver;
2041 driver = (MInputDriver *) msymbol_get (name, Minput_driver);
2043 MERROR (MERROR_IM, NULL);
2046 MSTRUCT_CALLOC (im, MERROR_IM);
2047 im->language = language;
2050 im->driver = *driver;
2051 if ((*im->driver.open_im) (im) < 0)
2062 @brief Close an input method.
2064 The minput_close_im () function closes the input method $IM, which
2065 must have been created by minput_open_im (). */
2068 @brief ÆþÎϥ᥽¥Ã¥É¤ò¥¯¥í¡¼¥º¤¹¤ë.
2070 ´Ø¿ô minput_close_im () ¤Ï¡¢ÆþÎϥ᥽¥Ã¥É $IM ¤ò¥¯¥í¡¼¥º¤¹¤ë¡£¤³¤Î
2071 ÆþÎϥ᥽¥Ã¥É $IM ¤Ï minput_open_im () ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê¤±¤ì
2075 minput_close_im (MInputMethod *im)
2077 (*im->driver.close_im) (im);
2084 @brief Create an input context.
2086 The minput_create_ic () function creates an input context object
2087 associated with input method $IM, and calls callback functions
2088 corresponding to #Minput_preedit_start, #Minput_status_start, and
2089 #Minput_status_draw in this order.
2093 If an input context is successfully created, minput_create_ic ()
2094 returns a pointer to it. Otherwise it returns @c NULL. */
2097 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÀ¸À®¤¹¤ë.
2099 ´Ø¿ô minput_create_ic () ¤ÏÆþÎϥ᥽¥Ã¥É $IM ¤ËÂбþ¤¹¤ëÆþÎÏ¥³¥ó¥Æ¥¯
2100 ¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤·¡¢ #Minput_preedit_start,
2101 #Minput_status_start, #Minput_status_draw ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø
2106 ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤¬À¸À®¤µ¤ì¤¿¾ì¹ç¡¢minput_create_ic () ¤Ï¤½¤ÎÆþÎÏ¥³
2107 ¥ó¥Æ¥¯¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¼ºÇÔ¤·¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
2111 minput_create_ic (MInputMethod *im, void *arg)
2115 MSTRUCT_CALLOC (ic, MERROR_IM);
2118 ic->preedit = mtext ();
2119 ic->candidate_list = NULL;
2120 ic->produced = mtext ();
2121 ic->spot.x = ic->spot.y = 0;
2123 ic->plist = mplist ();
2124 if ((*im->driver.create_ic) (ic) < 0)
2126 M17N_OBJECT_UNREF (ic->preedit);
2127 M17N_OBJECT_UNREF (ic->produced);
2128 M17N_OBJECT_UNREF (ic->plist);
2133 if (im->driver.callback_list)
2135 minput__callback (ic, Minput_preedit_start);
2136 minput__callback (ic, Minput_status_start);
2137 minput__callback (ic, Minput_status_draw);
2146 @brief Destroy an input context.
2148 The minput_destroy_ic () function destroys the input context $IC,
2149 which must have been created by minput_create_ic (). It calls
2150 callback functions corresponding to #Minput_preedit_done,
2151 #Minput_status_done, and #Minput_candidates_done in this order. */
2154 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÇ˲õ¤¹¤ë.
2156 ´Ø¿ô minput_destroy_ic () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤òÇ˲õ¤¹¤ë¡£¤³
2157 ¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ï minput_create_ic () ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê
2158 ¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£¤³¤Î´Ø¿ô¤Ï#Minput_preedit_done,
2159 #Minput_status_done, #Minput_candidates_done ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò
2164 minput_destroy_ic (MInputContext *ic)
2166 if (ic->im->driver.callback_list)
2168 minput__callback (ic, Minput_preedit_done);
2169 minput__callback (ic, Minput_status_done);
2170 minput__callback (ic, Minput_candidates_done);
2172 (*ic->im->driver.destroy_ic) (ic);
2173 M17N_OBJECT_UNREF (ic->preedit);
2174 M17N_OBJECT_UNREF (ic->produced);
2175 M17N_OBJECT_UNREF (ic->plist);
2182 @brief Filter an input key.
2184 The minput_filter () function filters input key $KEY according to
2185 input context $IC, and calls callback functions corresponding to
2186 #Minput_preedit_draw, #Minput_status_draw, and
2187 #Minput_candidates_draw if the preedit text, the status, and the
2188 current candidate are changed respectively.
2191 If $KEY is filtered out, this function returns 1. In that case,
2192 the caller should discard the key. Otherwise, it returns 0, and
2193 the caller should handle the key, for instance, by calling the
2194 function minput_lookup () with the same key. */
2197 @brief ÆþÎÏ¥¡¼¤ò¥Õ¥£¥ë¥¿¤¹¤ë.
2199 ´Ø¿ô minput_filter () ¤ÏÆþÎÏ¥¡¼ $KEY ¤òÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤Ë±þ
2200 ¤¸¤Æ¥Õ¥£¥ë¥¿¤·¡¢preedit ¥Æ¥¥¹¥È¡¢¥¹¥Æ¡¼¥¿¥¹¡¢¸½»þÅÀ¤Ç¤Î¸õÊ䤬ÊѲ½
2201 ¤·¤¿ºÝ¤Ë¤Ï¤½¤ì¤¾¤ì#Minput_preedit_draw, #Minput_status_draw,
2202 #Minput_candidates_draw ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¸Æ¤Ö¡£
2205 $KEY ¤¬¥Õ¥£¥ë¥¿¤µ¤ì¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 1 ¤òÊÖ¤¹¡£¤³¤Î¾ì¹ç¸Æ¤Ó
2206 ½Ð¤·Â¦¤Ï¤³¤Î¥¡¼¤ò¼Î¤Æ¤ë¤Ù¤¤Ç¤¢¤ë¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0 ¤òÊÖ¤·¡¢¸Æ¤Ó
2207 ½Ð¤·Â¦¤Ï¡¢¤¿¤È¤¨¤ÐƱ¤¸¥¡¼¤Ç´Ø¿ô minput_lookup () ¤ò¸Æ¤Ö¤Ê¤É¤·¤Æ¡¢
2208 ¤³¤Î¥¡¼¤ò½èÍý¤¹¤ë¡£
2210 @latexonly \IPAlabel{minput_filter} @endlatexonly
2214 minput_filter (MInputContext *ic, MSymbol key, void *arg)
2221 ret = (*ic->im->driver.filter) (ic, key, arg);
2223 if (ic->im->driver.callback_list)
2225 if (ic->preedit_changed)
2226 minput__callback (ic, Minput_preedit_draw);
2227 if (ic->status_changed)
2228 minput__callback (ic, Minput_status_draw);
2229 if (ic->candidates_changed)
2230 minput__callback (ic, Minput_candidates_draw);
2231 ic->preedit_changed = ic->status_changed = ic->candidates_changed = 0;
2240 @brief Lookup a text produced in the input context.
2242 The minput_lookup () function looks up a text in the input context
2243 $IC. $KEY must be the same one provided to the previous call of
2246 If a text was produced by the input method, it is concatenated
2249 This function calls #MInputDriver::lookup .
2252 If $KEY was correctly handled by the input method, this function
2253 returns 0. Otherwise, returns -1, even in that case, some text
2254 may be produced in $MT. */
2257 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥ÈÃæ¤Î¥Æ¥¥¹¥È¤Î¸¡º÷.
2259 ´Ø¿ô minput_lookup () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC Ãæ¤Î¥Æ¥¥¹¥È¤ò¸¡º÷¤¹
2260 ¤ë¡£$KEY ¤Ï´Ø¿ôminput_filter () ¤Ø¤ÎľÁ°¤Î¸Æ¤Ó½Ð¤·¤ËÍѤ¤¤é¤ì¤¿¤â¤Î
2261 ¤ÈƱ¤¸¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2263 ¥Æ¥¥¹¥È¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆÀ¸À®¤µ¤ì¤Æ¤¤¤ì¤Ð¡¢¥Æ¥¥¹¥È¤Ï M-text
2266 ¤³¤Î´Ø¿ô¤Ï¡¢#MInputDriver::lookup ¤ò¸Æ¤Ö¡£
2269 $KEY ¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆŬÀڤ˽èÍý¤Ç¤¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 0 ¤òÊÖ¤¹¡£
2270 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£¤³¤Î¾ì¹ç¤Ç¤â $MT ¤Ë²¿¤é¤«¤Î¥Æ¥¥¹¥È¤¬À¸
2271 À®¤µ¤ì¤Æ¤¤¤ë¤³¤È¤¬¤¢¤ë¡£
2273 @latexonly \IPAlabel{minput_lookup} @endlatexonly */
2276 minput_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2278 return (ic ? (*ic->im->driver.lookup) (ic, key, arg, mt) : -1);
2283 @brief Set the spot of the input context.
2285 The minput_set_spot () function set the spot of input context $IC
2286 to coordinate ($X, $Y ) with the height $ASCENT and $DESCENT .
2287 The semantics of these values depend on the input method driver.
2288 $FONTSIZE specfies the fontsize of a preedit text in 1/10 point.
2290 For instance, an driver designed to work in CUI environment may
2291 use $X and $Y as column and row numbers, and ignore $ASCENT and
2292 $DESCENT . An driver designed to work on a window system may
2293 treat $X and $Y as pixel offsets relative to the origin of the
2294 client window, and treat $ASCENT and $DESCENT as ascent and
2295 descent pixels of a line at ($X . $Y ).
2297 $MT and $POS is an M-text and a character position at the spot.
2298 $MT may be @c NULL, in which case, the input method cannot get
2299 information about the text around the spot. */
2302 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Î¥¹¥Ý¥Ã¥È¤òÀßÄꤹ¤ë
2304 ´Ø¿ô minput_set_spot () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤Î¥¹¥Ý¥Ã¥È¤ò¡¢ºÂ
2305 ɸ ($X, $Y )¤Ë ¡¢¹â¤µ $ASCENT¡¢ $DESCENT ¤ÇÀßÄꤹ¤ë¡£ ¤³¤ì¤é¤ÎÃͤÎ
2306 °ÕÌ£¤ÏÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë¡£$FONTSIZE ¤Ïpreedit ¥Æ¥¥¹¥È
2307 ¤Î¥Õ¥©¥ó¥È¥µ¥¤¥º¤ò 1/10 ¥Ý¥¤¥ó¥Èñ°Ì¤Ç»ØÄꤹ¤ë¡£
2309 ¤¿¤È¤¨¤Ð CUI ´Ä¶¤ÇÆ°ºî¤¹¤ë¥É¥é¥¤¥Ð¤Ï $X ¤È $Y ¤ò¤½¤ì¤¾¤ìÎó¤È¹Ô¤Î
2310 ÈÖ¹æ¤È¤·¤ÆÍѤ¤¡¢$ASCENT ¤È $DESCENT ¤ò̵»ë¤¹¤ë¤«¤â¤·¤ì¤Ê¤¤¡£ ¤Þ¤¿
2311 ¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥àÍѤΥɥ饤¥Ð¤Ï $X ¤È $Y ¤ò¥¯¥é¥¤¥¢¥ó¥È¥¦¥£¥ó¥É¥¦
2312 ¤Î¸¶ÅÀ¤«¤é¤Î¥ª¥Õ¥»¥Ã¥È¤ò¥Ô¥¯¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¤¡¢
2313 $ASCENT ¤È $DESCENT ¤ò ($X . $Y ) ¤ÎÎó¤Î¥¢¥»¥ó¥È¤È¥Ç¥£¥»¥ó¥È¤ò¥Ô¥¯
2314 ¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¦¤«¤â¤·¤ì¤Ê¤¤¡£
2316 $MT ¤È $POS ¤Ï¤½¤Î¥¹¥Ý¥Ã¥È¤Î M-text ¤Èʸ»ú°ÌÃ֤Ǥ¢¤ë¡£$MT ¤Ï @c
2317 NULL ¤Ç¤â¤è¤¯¡¢¤½¤Î¾ì¹ç¤Ë¤ÏÆþÎϥ᥽¥Ã¥É¤Ï¥¹¥Ý¥Ã¥È¼þÊդΥƥ¥¹¥È¤Ë
2318 ´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë¤³¤È¤¬¤Ç¤¤Ê¤¤¡£
2322 minput_set_spot (MInputContext *ic, int x, int y,
2323 int ascent, int descent, int fontsize,
2328 ic->spot.ascent = ascent;
2329 ic->spot.descent = descent;
2330 ic->spot.fontsize = fontsize;
2333 if (ic->im->driver.callback_list)
2334 minput__callback (ic, Minput_set_spot);
2339 @brief Toggle input method.
2341 The minput_toggle () function toggles the input method associated
2342 with the input context $IC. */
2344 @brief ÆþÎϥ᥽¥Ã¥É¤òÀÚÂؤ¨¤ë.
2346 ´Ø¿ô minput_toggle () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤ËÂбþÉÕ¤±¤é¤ì¤¿ÆþÎÏ
2347 ¥á¥½¥Ã¥É¤ò¥È¥°¥ë¤¹¤ë¡£
2351 minput_toggle (MInputContext *ic)
2353 if (ic->im->driver.callback_list)
2354 minput__callback (ic, Minput_toggle);
2355 ic->active = ! ic->active;
2361 /*** @addtogroup m17nDebug */
2367 @brief Dump an input method.
2369 The mdebug_dump_im () function prints the input method $IM in a
2370 human readable way to the stderr. $INDENT specifies how many
2371 columns to indent the lines but the first one.
2374 This function returns $IM. */
2376 @brief ÆþÎϥ᥽¥Ã¥É¤ò¥À¥ó¥×¤¹¤ë.
2378 ´Ø¿ô mdebug_dump_im () ¤ÏÆþÎϥ᥽¥Ã¥É $IM ¤ò stderr ¤Ë¿Í´Ö¤Ë²ÄÆɤÊ
2379 ·Á¤Ç°õºþ¤¹¤ë¡£$INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£
2382 ¤³¤Î´Ø¿ô¤Ï $IM ¤òÊÖ¤¹¡£ */
2385 mdebug_dump_im (MInputMethod *im, int indent)
2387 MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
2390 prefix = (char *) alloca (indent + 1);
2391 memset (prefix, 32, indent);
2392 prefix[indent] = '\0';
2394 fprintf (stderr, "(input-method %s %s ", msymbol_name (im->language),
2395 msymbol_name (im->name));
2396 mdebug_dump_mtext (im_info->title, 0, 0);
2397 if (im->name != Mnil)
2401 MPLIST_DO (state, im_info->states)
2403 fprintf (stderr, "\n%s ", prefix);
2404 dump_im_state (MPLIST_VAL (state), indent + 2);
2407 fprintf (stderr, ")");