1 /* input.c -- input method module.
2 Copyright (C) 2003, 2004
3 National Institute of Advanced Industrial Science and Technology (AIST)
4 Registration Number H15PRO112
6 This file is part of the m17n library.
8 The m17n library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public License
10 as published by the Free Software Foundation; either version 2.1 of
11 the License, or (at your option) any later version.
13 The m17n library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with the m17n library; if not, write to the Free
20 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
24 @addtogroup m17nInputMethod
25 @brief API for Input method.
27 An input method is an object to enable inputting various
28 characters. An input method is identified by a pair of symbols,
29 LANGUAGE and NAME. This pair decides a input method driver of the
30 input method. An input method driver is a set of functions for
31 handling the input method. There are two kinds of input methods;
32 internal one and foreign one.
35 <li> Internal Input Method
37 An internal input method has non @c Mnil LANGUAGE, and the body is
38 defined in the m17n database by the tag <Minput_method, LANGUAGE,
39 NAME>. For this kind of input methods, the m17n library uses two
40 predefined input method drivers, one for CUI use and the other for
41 GUI use. Those driver utilize the input processing engine
42 provided by the m17n library itself. The m17n database may
43 provides an input method that is not only for a specific language.
44 The database uses @c Mt as LANGUAGE of such an input method.
46 An internal input method accepts an input key which is a symbol
47 associated with an input event. As there is no way for the @c
48 m17n @c library to know how input events are represented in an
49 application program, an application programmer have to convert an
50 input event to an input key by himself. See the documentation of
51 the function minput_event_to_key () for the detail.
53 <li> Foreign Input Method
55 A foreign input method has @c Mnil LANGUAGE, and the body is
56 defined in an external resources (e.g. XIM of X Window System).
57 For this kind of input methods, the symbol NAME must have a
58 property of key @c Minput_driver, and the value must be a pointer
59 to an input method driver. Therefore, by preparing a proper
60 driver, any kind of input method can be treated in the framework
61 of the @c m17n @c library.
63 For convenience, the m17n-X library provides an input method
64 driver that enables the input style of OverTheSpot for XIM, and
65 stores @c Minput_driver property of the symbol @c Mxim with a
66 pointer to the driver. See the documentation of m17n GUI API for
73 The typical processing flow of handling an input method is:
75 @li open an input method
76 @li create an input context for the input method
77 @li filter an input key
78 @li look up a produced text in the input context */
82 @addtogroup m17nInputMethod
83 @brief ÆþÎϥ᥽¥Ã¥ÉÍÑAPI.
85 ÆþÎϥ᥽¥Ã¥É¤Ï¿ÍͤÊʸ»ú¤òÆþÎϤ¹¤ë¤¿¤á¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¢¤ë¡£ÆþÎÏ¥á
86 ¥½¥Ã¥É¤Ï¥·¥ó¥Ü¥ë LANGUAGE ¤È NAME ¤ÎÁȤˤè¤Ã¤Æ¼±Ê̤µ¤ì¡¢¤³¤ÎÁȤˤè¤Ã
87 ¤ÆÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤¬·è¤Þ¤ë¡£ÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤È¤Ï¤¢¤ëÆþÎÏ¥á
88 ¥½¥Ã¥É¤ò°·¤¦¤¿¤á¤Î´Ø¿ô¤Î½¸¤Þ¤ê¤Ç¤¢¤ë¡£ ÆþÎϥ᥽¥Ã¥É¤Ë¤ÏÆâÉô¥á¥½¥Ã
89 ¥É¤È³°Éô¥á¥½¥Ã¥É¤ÎÆóÄ̤꤬¤¢¤ë¡£
94 ÆâÉôÆþÎϥ᥽¥Ã¥É¤Ï LANGUAGE ¤¬ @c Mnil °Ê³°¤Î¤â¤Î¤Ç¤¢¤ê¡¢ËÜÂΤÏ
95 m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë <Minput_method, LANGUAGE, NAME>¤È¤¤¤¦¥¿¥°ÉÕ¤
96 ¤ÇÄêµÁ¤µ¤ì¤Æ¤¤¤ë¡£¤³¤Î¼ï¤ÎÆþÎϥ᥽¥Ã¥É¤ËÂФ·¤Æ¡¢m17n ¥é¥¤¥Ö¥é¥ê¤Ë
97 ¤ÏCUIÍѤÈGUIÍѤ½¤ì¤¾¤ì¤ÎÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤¬¤¢¤é¤«¤¸¤á½àÈ÷¤µ¤ì¤Æ
98 ¤¤¤ë¡£¤³¤ì¤é¤Î¥É¥é¥¤¥Ð¤Ïm17n¥é¥¤¥Ö¥é¥ê¼«¿È¤ÎÆþÎϽèÍý¥¨¥ó¥¸¥ó¤òÍøÍÑ
99 ¤¹¤ë¡£m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë¤Ï¡¢ÆÃÄê¤Î¸À¸ìÀìÍѤǤʤ¤ÆþÎϥ᥽¥Ã¥É¤âÄê
100 µÁ¤¹¤ë¤³¤È¤¬¤Ç¤¡¢¤½¤Î¤è¤¦¤ÊÆþÎϥ᥽¥Ã¥É¤Î LANGUAGE ¤Ï @c Mt ¤Ç¤¢
103 ÆâÉôÆþÎϥ᥽¥Ã¥É¤Ï¡¢¥æ¡¼¥¶¤ÎÆþÎÏ¥¤¥Ù¥ó¥È¤ËÂбþ¤·¤¿¥·¥ó¥Ü¥ë¤Ç¤¢¤ëÆþ
104 ÎÏ¥¡¼¤ò¼õ¤±¼è¤ë¡£@c m17n @c ¥é¥¤¥Ö¥é¥ê ¤ÏÆþÎÏ¥¤¥Ù¥ó¥È¤¬¥¢¥×¥ê¥±¡¼
105 ¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ç¤É¤¦É½¸½¤µ¤ì¤Æ¤¤¤ë¤«¤òÃΤë½Ñ¤ò»ý¤¿¤Ê¤¤¤Î¤Ç¡¢ÆþÎÏ
106 ¥¤¥Ù¥ó¥È¤«¤éÆþÎÏ¥¡¼¤Ø¤ÎÊÑ´¹¤Ï¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥Þ¤ÎÀÕǤ¤Ç¹Ô
107 ¤ï¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï´Ø¿ô minput_event_to_key () ¤ÎÀâ
110 <li> ³°ÉôÆþÎϥ᥽¥Ã¥É
112 ³°ÉôÆþÎϥ᥽¥Ã¥É¤Ï LANGUAGE ¤¬ @c Mnil ¤Î¤â¤Î¤Ç¤¢¤ê¡¢ËÜÂΤϳ°Éô¤Î
113 ¥ê¥½¡¼¥¹¤È¤·¤ÆÄêµÁ¤µ¤ì¤ë¡£¡Ê¤¿¤È¤¨¤ÐX Window System ¤ÎXIM ¤Ê¤É¡£)
114 ¤³¤Î¼ï¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢¥·¥ó¥Ü¥ë NAME ¤Ï@c Minput_driver ¤ò¥¡¼
115 ¤È¤¹¤ë¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Á¡¢¤½¤ÎÃͤÏÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç
116 ¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¤·¤¿¤¬¤Ã¤Æ¡¢Å¬Àڤʥɥ饤¥Ð¤ò½àÈ÷¤¹¤ë¤³¤È¤Ë¤è¤Ã¤Æ¡¢
117 ¤¤¤«¤Ê¤ë¼ïÎà¤ÎÆþÎϥ᥽¥Ã¥É¤â @c m17n @c ¥é¥¤¥Ö¥é¥ê ¤ÎÏÈÁȤÎÃæ¤Ç°·
120 ÍøÊØÀ¤Î¤¿¤á¡¢m17n X ¥é¥¤¥Ö¥é¥ê¤Ï XIM ¤Î OverTheSpot ¤ÎÆþÎÏ¥¹¥¿¥¤¥ë
121 ¤ò¼Â¸½¤¹¤ëÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤òÄ󶡤·¡¢¤Þ¤¿¥·¥ó¥Ü¥ë @c Mxim ¤Î @c
122 Minput_driver ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤȤ·¤Æ¤½¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÝ»ý¤·
123 ¤Æ¤¤¤ë¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï m17n GUI API ¤Î¥É¥¥å¥á¥ó¥È¤ò»²¾È¤Î¤³¤È¡£
129 ÆþÎϥ᥽¥Ã¥É½èÍý¤Îŵ·¿Åª¤Ê½èÍý¤Ï°Ê²¼¤Î¤è¤¦¤Ë¤Ê¤ë¡£
131 @li ÆþÎϥ᥽¥Ã¥É¤Î¥ª¡¼¥×¥ó
132 @li ¤½¤ÎÆþÎϥ᥽¥Ã¥É¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤ÎÀ¸À®
133 @li ÆþÎÏ¥¤¥Ù¥ó¥È¤Î¥Õ¥£¥ë¥¿
134 @li ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ç¤ÎÀ¸À®¥Æ¥¥¹¥È¤Î¸¡º÷ */
138 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
139 /*** @addtogroup m17nInternal
151 #include "m17n-gui.h"
152 #include "m17n-misc.h"
153 #include "internal.h"
159 static int mdebug_mask = MDEBUG_INPUT;
161 static MSymbol Minput_method;
163 /** Symbols to load an input method data. */
164 static MSymbol Mtitle, Mmacro, Mmodule, Mstate;
166 /** Symbols for actions. */
167 static MSymbol Minsert, Mdelete, Mmark, Mmove, Mpushback, Mundo, Mcall, Mshift;
168 static MSymbol Mselect, Mshow, Mhide;
169 static MSymbol Mset, Madd, Msub, Mmul, Mdiv, Mequal, Mless, Mgreater;
171 static MSymbol Mcandidate_list, Mcandidate_index;
173 static MSymbol Minit, Mfini;
175 /** Symbols for key events. */
176 static MSymbol one_char_symbol[256];
178 static MSymbol M_key_alias;
180 /** Structure to hold a map. */
184 /** List of actions to take when we reach the map. In a root map,
185 the actions are executed only when there's no more key. */
188 /** List of deeper maps. If NULL, this is a terminal map. */
191 /** List of actions to take when we leave the map successfully. In
192 a root map, the actions are executed only when none of submaps
193 handle the current key. */
194 MPlist *branch_actions;
197 typedef MPlist *(*MIMExternalFunc) (MPlist *plist);
202 MPlist *func_list; /* function name vs (MIMExternalFunc *) */
207 /** Name of the state. */
210 /** Title of the state, or NULL. */
213 /** Key translation map of the state. Built by merging all maps of
220 marker_code (MSymbol sym)
226 name = MSYMBOL_NAME (sym);
227 return ((name[0] == '@'
228 && ((name[1] >= '0' && name[1] <= '9')
229 || name[1] == '<' || name[1] == '>'
230 || name[1] == '=' || name[1] == '+' || name[1] == '-'
231 || name[1] == '[' || name[1] == ']')
237 integer_value (MInputContext *ic, MPlist *arg)
239 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
241 MText *preedit = ic->preedit;
242 int len = mtext_nbytes (preedit);
244 if (MPLIST_INTEGER_P (arg))
245 return MPLIST_INTEGER (arg);
246 code = marker_code (MPLIST_SYMBOL (arg));
248 return (int) mplist_get (ic_info->vars, MPLIST_SYMBOL (arg));
249 if (code >= '0' && code <= '9')
251 else if (code == '=')
252 code = ic->cursor_pos;
253 else if (code == '-' || code == '[')
254 code = ic->cursor_pos - 1;
255 else if (code == '+' || code == ']')
256 code = ic->cursor_pos + 1;
257 else if (code == '<')
259 else if (code == '<')
261 return (code >= 0 && code < len ? mtext_ref_char (preedit, code) : -1);
265 /* Parse PLIST as an action list while modifying the list to regularize
266 actions. PLIST should have this form:
267 PLIST ::= ( (ACTION-NAME ACTION-ARG *) *).
268 Return 0 if successfully parsed, otherwise return -1. */
271 parse_action_list (MPlist *plist, MPlist *macros)
273 MPLIST_DO (plist, plist)
275 if (MPLIST_MTEXT_P (plist))
277 /* This is a short form of (insert MTEXT). */
278 /* if (mtext_nchars (MPLIST_MTEXT (plist)) == 0)
279 MERROR (MERROR_IM, -1); */
281 else if (MPLIST_PLIST_P (plist)
282 && (MPLIST_MTEXT_P (MPLIST_PLIST (plist))
283 || MPLIST_PLIST_P (MPLIST_PLIST (plist))))
287 /* This is a short form of (insert (GROUPS *)). */
288 MPLIST_DO (pl, MPLIST_PLIST (plist))
290 if (MPLIST_PLIST_P (pl))
294 MPLIST_DO (elt, MPLIST_PLIST (pl))
295 if (! MPLIST_MTEXT_P (elt)
296 || mtext_nchars (MPLIST_MTEXT (elt)) == 0)
297 MERROR (MERROR_IM, -1);
301 if (! MPLIST_MTEXT_P (pl)
302 || mtext_nchars (MPLIST_MTEXT (pl)) == 0)
303 MERROR (MERROR_IM, -1);
307 else if (MPLIST_INTEGER_P (plist))
309 int c = MPLIST_INTEGER (plist);
311 if (c < 0 || c > MCHAR_MAX)
312 MERROR (MERROR_IM, -1);
314 else if (MPLIST_PLIST_P (plist)
315 && MPLIST_SYMBOL_P (MPLIST_PLIST (plist)))
317 MPlist *pl = MPLIST_PLIST (plist);
318 MSymbol action_name = MPLIST_SYMBOL (pl);
320 pl = MPLIST_NEXT (pl);
322 if (action_name == Minsert)
324 if (MPLIST_MTEXT_P (pl))
326 if (mtext_nchars (MPLIST_MTEXT (pl)) == 0)
327 MERROR (MERROR_IM, -1);
329 else if (MPLIST_PLIST_P (pl))
333 if (MPLIST_PLIST_P (pl))
337 MPLIST_DO (elt, MPLIST_PLIST (pl))
338 if (! MPLIST_MTEXT_P (elt)
339 || mtext_nchars (MPLIST_MTEXT (elt)) == 0)
340 MERROR (MERROR_IM, -1);
344 if (! MPLIST_MTEXT_P (pl)
345 || mtext_nchars (MPLIST_MTEXT (pl)) == 0)
346 MERROR (MERROR_IM, -1);
350 else if (! MPLIST_SYMBOL_P (pl))
351 MERROR (MERROR_IM, -1);
353 else if (action_name == Mselect
354 || action_name == Mdelete
355 || action_name == Mmove)
357 if (! MPLIST_SYMBOL_P (pl)
358 && ! MPLIST_INTEGER_P (pl))
359 MERROR (MERROR_IM, -1);
361 else if (action_name == Mmark
362 || action_name == Mcall
363 || action_name == Mshift)
365 if (! MPLIST_SYMBOL_P (pl))
366 MERROR (MERROR_IM, -1);
368 else if (action_name == Mshow || action_name == Mhide
369 || action_name == Mundo)
371 if (! MPLIST_TAIL_P (pl))
372 MERROR (MERROR_IM, -1);
374 else if (action_name == Mpushback)
376 if (! MPLIST_INTEGER_P (pl))
377 MERROR (MERROR_IM, -1);
379 else if (action_name == Mset || action_name == Madd
380 || action_name == Msub || action_name == Mmul
381 || action_name == Mdiv)
383 if (! (MPLIST_SYMBOL_P (pl)
384 && (MPLIST_INTEGER_P (MPLIST_NEXT (pl))
385 || MPLIST_SYMBOL_P (MPLIST_NEXT (pl)))))
386 MERROR (MERROR_IM, -1);
388 else if (action_name == Mequal || action_name == Mless
389 || action_name == Mgreater)
391 if (! ((MPLIST_INTEGER_P (pl) || MPLIST_SYMBOL_P (pl))
392 && (MPLIST_INTEGER_P (MPLIST_NEXT (pl))
393 || MPLIST_SYMBOL_P (MPLIST_NEXT (pl)))))
394 MERROR (MERROR_IM, -1);
395 pl = MPLIST_NEXT (MPLIST_NEXT (pl));
396 if (! MPLIST_PLIST_P (pl))
397 MERROR (MERROR_IM, -1);
398 if (parse_action_list (MPLIST_PLIST (pl), macros) < 0)
399 MERROR (MERROR_IM, -1);
400 pl = MPLIST_NEXT (pl);
401 if (MPLIST_PLIST_P (pl)
402 && parse_action_list (MPLIST_PLIST (pl), macros) < 0)
403 MERROR (MERROR_IM, -1);
405 else if (! macros || ! mplist_get (macros, action_name))
406 MERROR (MERROR_IM, -1);
409 MERROR (MERROR_IM, -1);
416 /* Load a translation into MAP from PLIST.
418 PLIST ::= ( KEYSEQ MAP-ACTION * ) */
421 load_translation (MIMMap *map, MPlist *plist, MPlist *branch_actions,
427 if (MPLIST_MTEXT_P (plist))
429 MText *mt = MPLIST_MTEXT (plist);
431 len = mtext_nchars (mt);
432 if (len == 0 || len != mtext_nbytes (mt))
433 MERROR (MERROR_IM, -1);
434 keyseq = (MSymbol *) alloca (sizeof (MSymbol) * len);
435 for (i = 0; i < len; i++)
436 keyseq[i] = one_char_symbol[MTEXT_DATA (mt)[i]];
438 else if (MPLIST_PLIST_P (plist))
440 MPlist *elt = MPLIST_PLIST (plist);
442 len = MPLIST_LENGTH (elt);
444 MERROR (MERROR_IM, -1);
445 keyseq = (MSymbol *) alloca (sizeof (int) * len);
446 for (i = 0; i < len; i++, elt = MPLIST_NEXT (elt))
448 if (MPLIST_INTEGER_P (elt))
450 int c = MPLIST_INTEGER (elt);
452 if (c < 0 || c >= 0x100)
453 MERROR (MERROR_IM, -1);
454 keyseq[i] = one_char_symbol[c];
456 else if (MPLIST_SYMBOL_P (elt))
457 keyseq[i] = MPLIST_SYMBOL (elt);
459 MERROR (MERROR_IM, -1);
463 MERROR (MERROR_IM, -1);
465 for (i = 0; i < len; i++)
467 MIMMap *deeper = NULL;
470 deeper = mplist_get (map->submaps, keyseq[i]);
472 map->submaps = mplist ();
475 /* Fixme: It is better to make all deeper maps at once. */
476 MSTRUCT_CALLOC (deeper, MERROR_IM);
477 mplist_put (map->submaps, keyseq[i], deeper);
482 /* We reach a terminal map. */
484 || map->branch_actions)
485 /* This map is already defined. We avoid overriding it. */
488 plist = MPLIST_NEXT (plist);
489 if (! MPLIST_TAIL_P (plist))
491 if (parse_action_list (plist, macros) < 0)
492 MERROR (MERROR_IM, -1);
493 map->map_actions = plist;
494 M17N_OBJECT_REF (plist);
498 map->branch_actions = branch_actions;
499 M17N_OBJECT_REF (branch_actions);
505 /* Load a branch from PLIST into MAP. PLIST has this form:
506 PLIST ::= ( MAP-NAME BRANCH-ACTION * )
507 MAPS is a plist of raw maps.
508 STATE is the current state. */
511 load_branch (MPlist *plist, MPlist *maps, MIMMap *map, MPlist *macros)
514 MPlist *branch_actions;
516 if (! MPLIST_SYMBOL_P (plist))
517 MERROR (MERROR_IM, -1);
518 map_name = MPLIST_SYMBOL (plist);
519 plist = MPLIST_NEXT (plist);
520 if (MPLIST_TAIL_P (plist))
521 branch_actions = NULL;
522 else if (parse_action_list (plist, macros) < 0)
523 MERROR (MERROR_IM, -1);
525 branch_actions = plist;
526 if (map_name == Mnil)
528 map->branch_actions = branch_actions;
530 M17N_OBJECT_REF (branch_actions);
532 else if (map_name == Mt)
534 map->map_actions = branch_actions;
536 M17N_OBJECT_REF (branch_actions);
540 plist = (MPlist *) mplist_get (maps, map_name);
541 if (! plist || ! MPLIST_PLIST_P (plist))
542 MERROR (MERROR_IM, -1);
543 MPLIST_DO (plist, plist)
544 if (! MPLIST_PLIST_P (plist)
545 || (load_translation (map, MPLIST_PLIST (plist), branch_actions,
548 MERROR (MERROR_IM, -1);
554 /* Load a macro from PLIST into MACROS.
556 PLIST ::= ( MACRO-NAME ACTION * )
557 MACROS is a plist of macro names vs action list. */
559 load_macros (MPlist *plist, MPlist *macros)
563 if (! MPLIST_SYMBOL_P (plist))
564 MERROR (MERROR_IM, -1);
565 name = MPLIST_SYMBOL (plist);
566 plist = MPLIST_NEXT (plist);
567 if (MPLIST_TAIL_P (plist)
568 || parse_action_list (plist, macros) < 0)
569 MERROR (MERROR_IM, -1);
570 mplist_put (macros, name, plist);
571 M17N_OBJECT_REF (plist);
575 /* Load an external module from PLIST into EXTERNALS.
577 PLIST ::= ( MODULE-NAME FUNCTION * )
578 EXTERNALS is a plist of MODULE-NAME vs (MIMExternalModule *). */
580 #ifndef DLOPEN_SHLIB_EXT
581 #define DLOPEN_SHLIB_EXT ".so"
585 load_external_module (MPlist *plist, MPlist *externals)
590 MIMExternalModule *external;
594 if (MPLIST_MTEXT_P (plist))
595 module = msymbol ((char *) MTEXT_DATA (MPLIST_MTEXT (plist)));
596 else if (MPLIST_SYMBOL_P (plist))
597 module = MPLIST_SYMBOL (plist);
598 module_file = alloca (strlen (MSYMBOL_NAME (module))
599 + strlen (DLOPEN_SHLIB_EXT) + 1);
600 sprintf (module_file, "%s%s", MSYMBOL_NAME (module), DLOPEN_SHLIB_EXT);
602 handle = dlopen (module_file, RTLD_NOW);
605 fprintf (stderr, "%s\n", dlerror ());
606 MERROR (MERROR_IM, -1);
608 func_list = mplist ();
609 MPLIST_DO (plist, MPLIST_NEXT (plist))
611 if (! MPLIST_SYMBOL_P (plist))
612 MERROR_GOTO (MERROR_IM, err_label);
613 func = dlsym (handle, MSYMBOL_NAME (MPLIST_SYMBOL (plist)));
615 MERROR_GOTO (MERROR_IM, err_label);
616 mplist_add (func_list, MPLIST_SYMBOL (plist), func);
619 MSTRUCT_MALLOC (external, MERROR_IM);
620 external->handle = handle;
621 external->func_list = func_list;
622 mplist_add (externals, module, external);
627 M17N_OBJECT_UNREF (func_list);
632 /** Load a state from PLIST into a newly allocated state object.
634 PLIST ::= ( STATE-NAME STATE-TITLE ? BRANCH * )
635 BRANCH ::= ( MAP-NAME BRANCH-ACTION * )
636 MAPS is a plist of defined maps.
637 Return the state object. */
640 load_state (MPlist *plist, MPlist *maps, MSymbol language, MPlist *macros)
644 MSTRUCT_CALLOC (state, MERROR_IM);
645 if (! MPLIST_SYMBOL_P (plist))
646 MERROR (MERROR_IM, NULL);
647 state->name = MPLIST_SYMBOL (plist);
648 plist = MPLIST_NEXT (plist);
649 if (MPLIST_MTEXT_P (plist))
651 state->title = MPLIST_MTEXT (plist);
652 mtext_put_prop (state->title, 0, mtext_nchars (state->title),
653 Mlanguage, language);
654 M17N_OBJECT_REF (state->title);
655 plist = MPLIST_NEXT (plist);
657 MSTRUCT_CALLOC (state->map, MERROR_IM);
658 MPLIST_DO (plist, plist)
659 if (! MPLIST_PLIST_P (plist)
660 || load_branch (MPLIST_PLIST (plist), maps, state->map, macros) < 0)
661 MERROR (MERROR_IM, NULL);
667 free_map (MIMMap *map)
671 M17N_OBJECT_UNREF (map->map_actions);
674 MPLIST_DO (plist, map->submaps)
675 free_map ((MIMMap *) MPLIST_VAL (plist));
676 M17N_OBJECT_UNREF (map->submaps);
678 M17N_OBJECT_UNREF (map->branch_actions);
682 /* Load an input method from PLIST into IM_INTO, and return it. */
685 load_input_method (MSymbol language, MSymbol name, MPlist *plist,
686 MInputMethodInfo *im_info)
690 MPlist *states = NULL;
691 MPlist *externals = NULL;
692 MPlist *macros = NULL;
695 if (! MPLIST_PLIST_P (plist))
696 MERROR (MERROR_IM, -1);
697 for (; MPLIST_PLIST_P (plist); plist = MPLIST_NEXT (plist))
699 elt = MPLIST_PLIST (plist);
700 if (! MPLIST_SYMBOL_P (elt))
701 MERROR_GOTO (MERROR_IM, err);
702 if (MPLIST_SYMBOL (elt) == Mtitle)
704 elt = MPLIST_NEXT (elt);
705 if (MPLIST_MTEXT_P (elt))
707 title = MPLIST_MTEXT (elt);
708 M17N_OBJECT_REF (title);
711 MERROR_GOTO (MERROR_IM, err);
713 else if (MPLIST_SYMBOL (elt) == Mmap)
715 maps = mplist__from_alist (MPLIST_NEXT (elt));
717 MERROR_GOTO (MERROR_IM, err);
719 else if (MPLIST_SYMBOL (elt) == Mmacro)
722 MPLIST_DO (elt, MPLIST_NEXT (elt))
724 if (! MPLIST_PLIST_P (elt)
725 || load_macros (MPLIST_PLIST (elt), macros) < 0)
726 MERROR_GOTO (MERROR_IM, err);
729 else if (MPLIST_SYMBOL (elt) == Mmodule)
731 externals = mplist ();
732 MPLIST_DO (elt, MPLIST_NEXT (elt))
734 if (! MPLIST_PLIST_P (elt)
735 || load_external_module (MPLIST_PLIST (elt), externals) < 0)
736 MERROR_GOTO (MERROR_IM, err);
739 else if (MPLIST_SYMBOL (elt) == Mstate)
742 MPLIST_DO (elt, MPLIST_NEXT (elt))
746 if (! MPLIST_PLIST_P (elt))
747 MERROR_GOTO (MERROR_IM, err);
748 state = load_state (MPLIST_PLIST (elt), maps, language, macros);
750 MERROR_GOTO (MERROR_IM, err);
751 mplist_put (states, state->name, state);
756 MPLIST_DO (elt, maps)
757 M17N_OBJECT_UNREF (MPLIST_VAL (elt));
758 M17N_OBJECT_UNREF (maps);
760 title = mtext_from_data (MSYMBOL_NAME (name), MSYMBOL_NAMELEN (name),
761 MTEXT_FORMAT_US_ASCII);
762 im_info->title = title;
763 im_info->externals = externals;
764 im_info->macros = macros;
765 im_info->states = states;
771 MPLIST_DO (elt, maps)
772 M17N_OBJECT_UNREF (MPLIST_VAL (elt));
773 M17N_OBJECT_UNREF (maps);
776 M17N_OBJECT_UNREF (title);
779 MPLIST_DO (plist, states)
781 MIMState *state = (MIMState *) MPLIST_VAL (plist);
784 M17N_OBJECT_UNREF (state->title);
786 free_map (state->map);
789 M17N_OBJECT_UNREF (states);
793 MPLIST_DO (plist, externals)
795 MIMExternalModule *external = MPLIST_VAL (plist);
797 dlclose (external->handle);
798 M17N_OBJECT_UNREF (external->func_list);
800 MPLIST_KEY (plist) = Mt;
802 M17N_OBJECT_UNREF (externals);
809 static int take_action_list (MInputContext *ic, MPlist *action_list);
812 shift_state (MInputContext *ic, MSymbol state_name)
814 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
815 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
816 MIMState *state = ic_info->state;
818 /* Find a state to shift to. If not found, shift to the initial
820 state = (MIMState *) mplist_get (im_info->states, state_name);
822 state = (MIMState *) MPLIST_VAL (im_info->states);
824 MDEBUG_PRINT1 ("\n[IM] state-shift (%s)", MSYMBOL_NAME (state->name));
826 /* Enter the new state. */
827 ic_info->state = state;
828 ic_info->map = state->map;
829 ic_info->state_key_head = ic_info->key_head;
830 if (state == (MIMState *) MPLIST_VAL (im_info->states))
832 /* We have shifted to the initial state. */
835 mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit),
836 Mcandidate_list, NULL, 0);
837 mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit),
838 Mcandidate_index, NULL, 0);
839 mtext_cat (ic->produced, ic->preedit);
840 if ((mdebug__flag & mdebug_mask)
841 && mtext_nchars (ic->produced) > 0)
845 MDEBUG_PRINT (" (produced");
846 for (i = 0; i < mtext_nchars (ic->produced); i++)
847 MDEBUG_PRINT1 (" U+%04X", mtext_ref_char (ic->produced, i));
850 mtext_reset (ic->preedit);
851 ic->candidate_list = NULL;
852 ic->candidate_show = 0;
853 ic->preedit_changed = ic->candidates_changed = 1;
854 MPLIST_DO (p, ic_info->markers)
856 MPLIST_DO (p, ic_info->vars)
859 memmove (ic_info->keys, ic_info->keys + ic_info->state_key_head,
860 sizeof (int) * (ic_info->used - ic_info->state_key_head));
861 ic_info->used -= ic_info->state_key_head;
862 ic_info->state_key_head = ic_info->key_head = 0;
864 mtext_cpy (ic_info->preedit_saved, ic->preedit);
865 ic_info->state_pos = ic->cursor_pos;
866 ic->status = state->title;
868 ic->status = im_info->title;
869 ic->status_changed = 1;
870 if (ic_info->key_head == ic_info->used
871 && ic_info->map == ic_info->state->map
872 && ic_info->map->map_actions)
874 MDEBUG_PRINT (" init-actions:");
875 take_action_list (ic, ic_info->map->map_actions);
881 find_candidates_group (MPlist *plist, int index,
882 int *start_index, int *end_index, int *group_index)
884 int i = 0, gidx = 0, len;
886 MPLIST_DO (plist, plist)
888 if (MPLIST_MTEXT_P (plist))
889 len = mtext_nchars (MPLIST_MTEXT (plist));
891 len = mplist_length (MPLIST_PLIST (plist));
897 *end_index = i + len;
909 preedit_insert (MInputContext *ic, int pos, MText *mt, int c)
911 MInputContextInfo *ic_info = ((MInputContext *) ic)->info;
913 int nchars = mt ? mtext_nchars (mt) : 1;
916 mtext_ins (ic->preedit, pos, mt);
918 mtext_ins_char (ic->preedit, pos, c, 1);
919 MPLIST_DO (markers, ic_info->markers)
920 if (MPLIST_INTEGER (markers) > pos)
921 MPLIST_VAL (markers) = (void *) (MPLIST_INTEGER (markers) + nchars);
922 if (ic->cursor_pos >= pos)
923 ic->cursor_pos += nchars;
924 ic->preedit_changed = 1;
929 preedit_delete (MInputContext *ic, int from, int to)
931 MInputContextInfo *ic_info = ((MInputContext *) ic)->info;
934 mtext_del (ic->preedit, from, to);
935 MPLIST_DO (markers, ic_info->markers)
937 if (MPLIST_INTEGER (markers) > to)
939 = (void *) (MPLIST_INTEGER (markers) - (to - from));
940 else if (MPLIST_INTEGER (markers) > from);
941 MPLIST_VAL (markers) = (void *) from;
943 if (ic->cursor_pos >= to)
944 ic->cursor_pos -= to - from;
945 else if (ic->cursor_pos > from)
946 ic->cursor_pos = from;
947 ic->preedit_changed = 1;
952 new_index (MInputContext *ic, int current, int limit, MSymbol sym, MText *mt)
954 int code = marker_code (sym);
956 if (mt && (code == '[' || code == ']'))
960 if (code == '[' && current > 0)
962 if (mtext_prop_range (mt, Mcandidate_list, pos - 1, &pos, NULL, 1)
966 else if (code == ']' && current < mtext_nchars (mt))
968 if (mtext_prop_range (mt, Mcandidate_list, pos, NULL, &pos, 1))
974 return (code == '<' ? 0
975 : code == '>' ? limit
976 : code == '-' ? current - 1
977 : code == '+' ? current + 1
978 : code == '=' ? current
979 : code - '0' > limit ? limit
983 return (int) mplist_get (((MInputContextInfo *) ic->info)->markers, sym);
987 update_candidate (MInputContext *ic, MTextProperty *prop, int idx)
989 int from = mtext_property_start (prop);
990 int to = mtext_property_end (prop);
992 MPlist *candidate_list = mtext_property_value (prop);
993 MPlist *group = find_candidates_group (candidate_list, idx, &start,
995 int ingroup_index = idx - start;
998 preedit_delete (ic, from, to);
999 if (MPLIST_MTEXT_P (group))
1001 mt = MPLIST_MTEXT (group);
1002 preedit_insert (ic, from, NULL, mtext_ref_char (mt, ingroup_index));
1010 for (i = 0, plist = MPLIST_PLIST (group); i < ingroup_index;
1011 i++, plist = MPLIST_NEXT (plist));
1012 mt = MPLIST_MTEXT (plist);
1013 preedit_insert (ic, from, mt, 0);
1014 to = from + mtext_nchars (mt);
1016 mtext_put_prop (ic->preedit, from, to, Mcandidate_list, candidate_list);
1017 mtext_put_prop (ic->preedit, from, to, Mcandidate_index, (void *) idx);
1018 ic->cursor_pos = to;
1023 take_action_list (MInputContext *ic, MPlist *action_list)
1025 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1026 MPlist *candidate_list = ic->candidate_list;
1027 int candidate_index = ic->candidate_index;
1028 int candidate_show = ic->candidate_show;
1029 MTextProperty *prop;
1031 MPLIST_DO (action_list, action_list)
1037 if (MPLIST_MTEXT_P (action_list)
1038 || MPLIST_INTEGER_P (action_list))
1039 name = Minsert, args = action_list;
1040 else if (MPLIST_PLIST_P (action_list)
1041 && (MPLIST_MTEXT_P (MPLIST_PLIST (action_list))
1042 || MPLIST_PLIST_P (MPLIST_PLIST (action_list))))
1043 name = Minsert, args = action_list;
1046 action = MPLIST_PLIST (action_list);
1047 name = MPLIST_SYMBOL (action);
1048 args = MPLIST_NEXT (action);
1051 MDEBUG_PRINT1 (" %s", MSYMBOL_NAME (name));
1052 if (name == Minsert)
1054 if (MPLIST_MTEXT_P (args))
1055 preedit_insert (ic, ic->cursor_pos, MPLIST_MTEXT (args), 0);
1056 else if (MPLIST_INTEGER_P (args))
1057 preedit_insert (ic, ic->cursor_pos, NULL, MPLIST_INTEGER (args));
1058 else if (MPLIST_SYMBOL_P (args))
1060 int c = integer_value (ic, args);
1062 if (c >= 0 && c <= MCHAR_MAX)
1063 preedit_insert (ic, ic->cursor_pos, NULL, c);
1070 args = MPLIST_PLIST (args);
1071 if (MPLIST_MTEXT_P (args))
1073 preedit_insert (ic, ic->cursor_pos, NULL,
1074 mtext_ref_char (MPLIST_MTEXT (args), 0));
1079 mt = MPLIST_MTEXT (MPLIST_PLIST (args));
1080 preedit_insert (ic, ic->cursor_pos, mt, 0);
1081 len = mtext_nchars (mt);
1083 mtext_put_prop (ic->preedit,
1084 ic->cursor_pos - len, ic->cursor_pos,
1085 Mcandidate_list, args);
1086 mtext_put_prop (ic->preedit,
1087 ic->cursor_pos - len, ic->cursor_pos,
1088 Mcandidate_index, (void *) 0);
1091 else if (name == Mselect)
1094 int code, idx, gindex;
1095 int pos = ic->cursor_pos;
1099 || ! (prop = mtext_get_property (ic->preedit, pos - 1,
1102 if (MPLIST_SYMBOL_P (args))
1104 code = marker_code (MPLIST_SYMBOL (args));
1110 idx = (int) mtext_get_prop (ic->preedit, pos - 1, Mcandidate_index);
1111 group = find_candidates_group (mtext_property_value (prop), idx,
1112 &start, &end, &gindex);
1114 if (code != '[' && code != ']')
1118 ? new_index (NULL, ic->candidate_index - start,
1119 end - start - 1, MPLIST_SYMBOL (args),
1121 : MPLIST_INTEGER (args)));
1124 && MPLIST_TAIL_P (MPLIST_NEXT (group))))
1129 int ingroup_index = idx - start;
1132 group = mtext_property_value (prop);
1133 len = mplist_length (group);
1146 for (idx = 0; gindex > 0; gindex--, group = MPLIST_NEXT (group))
1147 idx += (MPLIST_MTEXT_P (group)
1148 ? mtext_nchars (MPLIST_MTEXT (group))
1149 : mplist_length (MPLIST_PLIST (group)));
1150 len = (MPLIST_MTEXT_P (group)
1151 ? mtext_nchars (MPLIST_MTEXT (group))
1152 : mplist_length (MPLIST_PLIST (group)));
1153 if (ingroup_index >= len)
1154 ingroup_index = len - 1;
1155 idx += ingroup_index;
1157 update_candidate (ic, prop, idx);
1159 else if (name == Mshow)
1160 ic->candidate_show = 1;
1161 else if (name == Mhide)
1162 ic->candidate_show = 0;
1163 else if (name == Mdelete)
1165 int len = mtext_nchars (ic->preedit);
1166 int to = (MPLIST_SYMBOL_P (args)
1167 ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
1169 : MPLIST_INTEGER (args));
1175 if (to < ic->cursor_pos)
1176 preedit_delete (ic, to, ic->cursor_pos);
1177 else if (to > ic->cursor_pos)
1178 preedit_delete (ic, ic->cursor_pos, to);
1180 else if (name == Mmove)
1182 int len = mtext_nchars (ic->preedit);
1184 = (MPLIST_SYMBOL_P (args)
1185 ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
1187 : MPLIST_INTEGER (args));
1193 if (pos != ic->cursor_pos)
1195 ic->cursor_pos = pos;
1196 ic->preedit_changed = 1;
1199 else if (name == Mmark)
1201 int code = marker_code (MPLIST_SYMBOL (args));
1204 mplist_put (ic_info->markers, MPLIST_SYMBOL (args),
1205 (void *) ic->cursor_pos);
1207 else if (name == Mpushback)
1209 int num = MPLIST_INTEGER (args);
1212 ic_info->key_head -= num;
1214 ic_info->key_head = num;
1215 if (ic_info->key_head > ic_info->used)
1216 ic_info->key_head = ic_info->used;
1218 else if (name == Mcall)
1220 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1221 MIMExternalFunc func = NULL;
1222 MSymbol module, func_name;
1223 MPlist *func_args, *val;
1226 module = MPLIST_SYMBOL (args);
1227 args = MPLIST_NEXT (args);
1228 func_name = MPLIST_SYMBOL (args);
1230 if (im_info->externals)
1232 MIMExternalModule *external
1233 = (MIMExternalModule *) mplist_get (im_info->externals,
1236 func = (MIMExternalFunc) mplist_get (external->func_list,
1241 func_args = mplist ();
1242 mplist_add (func_args, Mt, ic);
1243 MPLIST_DO (args, MPLIST_NEXT (args))
1247 if (MPLIST_KEY (args) == Msymbol
1248 && MPLIST_KEY (args) != Mnil
1249 && (code = marker_code (MPLIST_SYMBOL (args))) >= 0)
1251 code = new_index (ic, ic->cursor_pos,
1252 mtext_nchars (ic->preedit),
1253 MPLIST_SYMBOL (args), ic->preedit);
1254 mplist_add (func_args, Minteger, (void *) code);
1257 mplist_add (func_args, MPLIST_KEY (args), MPLIST_VAL (args));
1259 val = (func) (func_args);
1260 M17N_OBJECT_UNREF (func_args);
1261 if (val && ! MPLIST_TAIL_P (val))
1262 ret = take_action_list (ic, val);
1263 M17N_OBJECT_UNREF (val);
1267 else if (name == Mshift)
1269 shift_state (ic, MPLIST_SYMBOL (args));
1271 else if (name == Mundo)
1273 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1276 mtext_reset (ic->preedit);
1277 mtext_reset (ic_info->preedit_saved);
1278 ic->cursor_pos = ic_info->state_pos = 0;
1279 ic_info->state_key_head = ic_info->key_head = 0;
1281 if (ic_info->used < 0)
1286 shift_state (ic, ((MIMState *) MPLIST_VAL (im_info->states))->name);
1291 else if (name == Mset || name == Madd || name == Msub
1292 || name == Mmul || name == Mdiv)
1294 MSymbol sym = MPLIST_SYMBOL (args);
1295 int val1 = (int) mplist_get (ic_info->vars, sym), val2;
1297 args = MPLIST_NEXT (args);
1298 val2 = integer_value (ic, args);
1301 else if (name == Madd)
1303 else if (name == Msub)
1305 else if (name == Mmul)
1309 mplist_put (ic_info->vars, sym, (void *) val1);
1310 MDEBUG_PRINT2 ("(%s=%d)", MSYMBOL_NAME (sym), val1);
1312 else if (name == Mequal || name == Mless || name == Mgreater)
1315 MPlist *actions1, *actions2;
1318 val1 = integer_value (ic, args);
1319 args = MPLIST_NEXT (args);
1320 val2 = integer_value (ic, args);
1321 args = MPLIST_NEXT (args);
1322 actions1 = MPLIST_PLIST (args);
1323 args = MPLIST_NEXT (args);
1324 if (MPLIST_TAIL_P (args))
1327 actions2 = MPLIST_PLIST (args);
1328 if (name == Mequal ? val1 == val2
1329 : name == Mless ? val1 < val2
1331 ret = take_action_list (ic, actions1);
1333 ret = take_action_list (ic, actions2);
1339 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1343 && (actions = mplist_get (im_info->macros, name)))
1345 if (take_action_list (ic, actions) < 0)
1352 ic->candidate_list = NULL;
1353 if (ic->cursor_pos > 0
1354 && (prop = mtext_get_property (ic->preedit, ic->cursor_pos - 1,
1357 ic->candidate_list = mtext_property_value (prop);
1359 = (int) mtext_get_prop (ic->preedit, ic->cursor_pos - 1,
1361 ic->candidate_from = mtext_property_start (prop);
1362 ic->candidate_to = mtext_property_end (prop);
1365 ic->candidates_changed |= (candidate_list != ic->candidate_list
1366 || candidate_index != ic->candidate_index
1367 || candidate_show != ic->candidate_show);
1372 /* Handle the input key KEY in the current state and map specified in
1373 the input context IC. If KEY is handled correctly, return 0.
1374 Otherwise, return -1. */
1377 handle_key (MInputContext *ic)
1379 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1380 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1381 MIMMap *map = ic_info->map;
1382 MIMMap *submap = NULL;
1383 MSymbol key = ic_info->keys[ic_info->key_head];
1386 MDEBUG_PRINT2 ("[IM] handle `%s' in state %s",
1387 MSYMBOL_NAME (key), MSYMBOL_NAME (ic_info->state->name));
1391 submap = mplist_get (map->submaps, key);
1392 if (! submap && (key = msymbol_get (key, M_key_alias)) != Mnil)
1393 submap = mplist_get (map->submaps, key);
1398 MDEBUG_PRINT (" submap-found");
1399 mtext_cpy (ic->preedit, ic_info->preedit_saved);
1400 ic->cursor_pos = ic_info->state_pos;
1401 ic_info->key_head++;
1402 ic_info->map = map = submap;
1403 if (map->map_actions)
1405 MDEBUG_PRINT (" map-actions:");
1406 if (take_action_list (ic, map->map_actions) < 0)
1409 else if (map->submaps)
1411 for (i = ic_info->state_key_head; i < ic_info->key_head; i++)
1413 MSymbol key = ic_info->keys[i];
1414 char *name = msymbol_name (key);
1416 if (! name[0] || ! name[1])
1417 mtext_ins_char (ic->preedit, ic->cursor_pos++, name[0], 1);
1419 ic->preedit_changed = 1;
1422 /* If this is the terminal map or we have shifted to another
1423 state, perform branch actions (if any). */
1424 if (! map->submaps || map != ic_info->map)
1426 if (map->branch_actions)
1428 MDEBUG_PRINT (" branch-actions:");
1429 if (take_action_list (ic, map->branch_actions) < 0)
1432 /* If MAP is still not the root map, shift to the current
1434 if (ic_info->map != ic_info->state->map)
1435 shift_state (ic, ic_info->state->name);
1437 MDEBUG_PRINT ("\n");
1441 /* MAP can not handle KEY. */
1443 /* If MAP is the root map of the initial state, it means that
1444 the current input method can not handle KEY. */
1445 if (map == ((MIMState *) MPLIST_VAL (im_info->states))->map)
1447 MDEBUG_PRINT (" unhandled\n");
1451 if (map != ic_info->state->map)
1453 /* If MAP is not the root map... */
1454 /* If MAP has branch actions, perform them. */
1455 if (map->branch_actions)
1457 MDEBUG_PRINT (" branch-actions:");
1458 take_action_list (ic, map->branch_actions);
1460 /* If MAP is still not the root map, shift to the current
1462 if (ic_info->map != ic_info->state->map)
1464 shift_state (ic, ic_info->state->name);
1465 /* If MAP has branch_actions, perform them. */
1466 if (ic_info->map->branch_actions)
1468 MDEBUG_PRINT (" init-actions:");
1469 take_action_list (ic, ic_info->map->branch_actions);
1475 /* MAP is the root map, perform branch actions (if any) or
1476 shift to the initial state. */
1477 if (map->branch_actions)
1479 MDEBUG_PRINT (" branch-actions:");
1480 take_action_list (ic, map->branch_actions);
1484 ((MIMState *) MPLIST_VAL (im_info->states))->name);
1486 MDEBUG_PRINT ("\n");
1492 reset_ic (MInputContext *ic)
1494 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1495 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1497 MLIST_RESET (ic_info);
1498 ic_info->state = (MIMState *) MPLIST_VAL (im_info->states);
1499 ic_info->map = ic_info->state->map;
1500 ic_info->state_key_head = ic_info->key_head = 0;
1501 ic->cursor_pos = ic_info->state_pos = 0;
1502 ic->status = ic_info->state->title;
1504 ic->status = im_info->title;
1505 ic->candidate_list = NULL;
1506 ic->candidate_show = 0;
1507 ic->status_changed = ic->preedit_changed = ic->candidates_changed = 1;
1508 if (ic_info->map->map_actions)
1509 take_action_list (ic, ic_info->map->map_actions);
1513 open_im (MInputMethod *im)
1516 MInputMethodInfo *im_info;
1520 mdb = mdatabase_find (Minput_method, im->language, im->name, Mnil);
1523 plist = mdatabase_load (mdb);
1525 MERROR (MERROR_IM, -1);
1526 MSTRUCT_CALLOC (im_info, MERROR_IM);
1528 result = load_input_method (im->language, im->name, plist, im_info);
1529 M17N_OBJECT_UNREF (plist);
1531 MERROR (MERROR_IM, -1);
1536 close_im (MInputMethod *im)
1538 MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
1542 M17N_OBJECT_UNREF (im_info->title);
1543 if (im_info->states)
1545 MPLIST_DO (plist, im_info->states)
1547 MIMState *state = (MIMState *) MPLIST_VAL (plist);
1550 M17N_OBJECT_UNREF (state->title);
1552 free_map (state->map);
1555 M17N_OBJECT_UNREF (im_info->states);
1558 if (im_info->macros)
1560 MPLIST_DO (plist, im_info->macros)
1561 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
1562 M17N_OBJECT_UNREF (im_info->macros);
1565 if (im_info->externals)
1567 MPLIST_DO (plist, im_info->externals)
1569 MIMExternalModule *external = MPLIST_VAL (plist);
1571 dlclose (external->handle);
1572 M17N_OBJECT_UNREF (external->func_list);
1574 MPLIST_KEY (plist) = Mt;
1576 M17N_OBJECT_UNREF (im_info->externals);
1584 create_ic (MInputContext *ic)
1586 MInputMethod *im = ic->im;
1587 MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
1588 MInputContextInfo *ic_info;
1591 ic_info = (MInputContextInfo *) ic->info;
1594 MSTRUCT_CALLOC (ic_info, MERROR_IM);
1597 MLIST_INIT1 (ic_info, keys, 8);
1598 ic_info->markers = mplist ();
1599 ic_info->vars = mplist ();
1600 ic_info->preedit_saved = mtext ();
1601 if (im_info->externals)
1603 MPlist *func_args = mplist (), *plist;
1605 mplist_add (func_args, Mt, ic);
1606 MPLIST_DO (plist, im_info->externals)
1608 MIMExternalModule *external = MPLIST_VAL (plist);
1609 MIMExternalFunc func
1610 = (MIMExternalFunc) mplist_get (external->func_list, Minit);
1615 M17N_OBJECT_UNREF (func_args);
1622 destroy_ic (MInputContext *ic)
1624 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1625 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1627 if (im_info->externals)
1629 MPlist *func_args = mplist (), *plist;
1631 mplist_add (func_args, Mt, ic);
1632 MPLIST_DO (plist, im_info->externals)
1634 MIMExternalModule *external = MPLIST_VAL (plist);
1635 MIMExternalFunc func
1636 = (MIMExternalFunc) mplist_get (external->func_list, Mfini);
1641 M17N_OBJECT_UNREF (func_args);
1643 MLIST_FREE1 (ic_info, keys);
1644 M17N_OBJECT_UNREF (ic_info->preedit_saved);
1645 M17N_OBJECT_UNREF (ic_info->markers);
1646 M17N_OBJECT_UNREF (ic_info->vars);
1651 /** Handle the input key KEY in the current state and map of IC->info.
1652 If KEY is handled but no text is produced, return 0, otherwise
1658 filter (MInputContext *ic, MSymbol key, void *arg)
1660 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1661 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1664 mtext_reset (ic->produced);
1665 ic->status_changed = ic->preedit_changed = ic->candidates_changed = 0;
1666 MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
1667 ic_info->key_unhandled = 0;
1669 if (handle_key (ic) < 0)
1671 /* KEY was not handled. Reset the status and break the
1674 /* This forces returning 1. */
1675 ic_info->key_unhandled = 1;
1682 ic_info->key_unhandled = 1;
1685 /* Break the loop if all keys were handled. */
1686 } while (ic_info->key_head < ic_info->used);
1688 /* If the current map is the root of the initial state, we should
1689 produce any preedit text in ic->produced. */
1690 if (ic_info->map == ((MIMState *) MPLIST_VAL (im_info->states))->map
1691 && mtext_nchars (ic->preedit) > 0)
1692 shift_state (ic, ((MIMState *) MPLIST_VAL (im_info->states))->name);
1694 if (mtext_nchars (ic->produced) > 0)
1696 MSymbol lang = msymbol_get (ic->im->language, Mlanguage);
1699 mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
1700 Mlanguage, ic->im->language);
1703 return (! ic_info->key_unhandled && mtext_nchars (ic->produced) == 0);
1707 /** Return 1 if the last event or key was not handled, otherwise
1710 There is no need of looking up because ic->produced should already
1711 contain the produced text (if any).
1716 lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
1718 mtext_cat (mt, ic->produced);
1719 mtext_reset (ic->produced);
1720 return (((MInputContextInfo *) ic->info)->key_unhandled ? -1 : 0);
1723 /* Support functions for mdebug_dump_im. */
1726 dump_im_map (MPlist *map_list, int indent)
1729 MSymbol key = MPLIST_KEY (map_list);
1730 MIMMap *map = (MIMMap *) MPLIST_VAL (map_list);
1732 prefix = (char *) alloca (indent + 1);
1733 memset (prefix, 32, indent);
1734 prefix[indent] = '\0';
1736 fprintf (stderr, "(\"%s\" ", msymbol_name (key));
1737 if (map->map_actions)
1738 mdebug_dump_plist (map->map_actions, indent + 2);
1741 MPLIST_DO (map_list, map->submaps)
1743 fprintf (stderr, "\n%s ", prefix);
1744 dump_im_map (map_list, indent + 2);
1747 if (map->branch_actions)
1749 fprintf (stderr, "\n%s (branch\n%s ", prefix, prefix);
1750 mdebug_dump_plist (map->branch_actions, indent + 4);
1751 fprintf (stderr, ")");
1753 fprintf (stderr, ")");
1758 dump_im_state (MIMState *state, int indent)
1763 prefix = (char *) alloca (indent + 1);
1764 memset (prefix, 32, indent);
1765 prefix[indent] = '\0';
1767 fprintf (stderr, "(%s", msymbol_name (state->name));
1768 if (state->map->submaps)
1770 MPLIST_DO (map_list, state->map->submaps)
1772 fprintf (stderr, "\n%s ", prefix);
1773 dump_im_map (map_list, indent + 2);
1776 fprintf (stderr, ")");
1785 = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1786 "BackSpace", "Tab", "Linefeed", "Clear", NULL, "Return", NULL, NULL,
1787 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1788 NULL, NULL, NULL, "Escape", NULL, NULL, NULL, NULL };
1789 char buf[6], buf2[256];
1792 Minput_method = msymbol ("input-method");
1793 Minput_driver = msymbol ("input-driver");
1794 Mtitle = msymbol ("title");
1795 Mmacro = msymbol ("macro");
1796 Mmodule = msymbol ("module");
1797 Mmap = msymbol ("map");
1798 Mstate = msymbol ("state");
1799 Minsert = msymbol ("insert");
1800 Mdelete = msymbol ("delete");
1801 Mmove = msymbol ("move");
1802 Mmark = msymbol ("mark");
1803 Mpushback = msymbol ("pushback");
1804 Mundo = msymbol ("undo");
1805 Mcall = msymbol ("call");
1806 Mshift = msymbol ("shift");
1807 Mselect = msymbol ("select");
1808 Mshow = msymbol ("show");
1809 Mhide = msymbol ("hide");
1810 Mset = msymbol ("set");
1811 Madd = msymbol ("add");
1812 Msub = msymbol ("sub");
1813 Mmul = msymbol ("mul");
1814 Mdiv = msymbol ("div");
1815 Mequal = msymbol ("=");
1816 Mless = msymbol ("<");
1817 Mgreater = msymbol (">");
1819 Minput_preedit_start = msymbol ("input-preedit-start");
1820 Minput_preedit_done = msymbol ("input-preedit-done");
1821 Minput_preedit_draw = msymbol ("input-preedit-draw");
1822 Minput_status_start = msymbol ("input-status-start");
1823 Minput_status_done = msymbol ("input-status-done");
1824 Minput_status_draw = msymbol ("input-status-draw");
1825 Minput_candidates_start = msymbol ("input-candidates-start");
1826 Minput_candidates_done = msymbol ("input-candidates-done");
1827 Minput_candidates_draw = msymbol ("input-candidates-draw");
1828 Minput_set_spot = msymbol ("input-set-spot");
1829 Minput_toggle = msymbol ("input-toggle");
1831 Mcandidate_list = msymbol_as_managing_key (" candidate-list");
1832 Mcandidate_index = msymbol (" candidate-index");
1834 Minit = msymbol ("init");
1835 Mfini = msymbol ("fini");
1837 M_key_alias = msymbol (" key-alias");
1842 for (i = 0, buf[2] = '@'; i < ' '; i++, buf[2]++)
1844 one_char_symbol[i] = msymbol (buf);
1846 msymbol_put (one_char_symbol[i], M_key_alias, msymbol (key_names[i]));
1848 for (buf[2] = i; i < 127; i++, buf[2]++)
1849 one_char_symbol[i] = msymbol (buf + 2);
1850 one_char_symbol[i++] = msymbol ("Delete");
1856 for (buf[4] = '@'; i < 160; i++, buf[4]++)
1858 one_char_symbol[i] = msymbol (buf);
1859 if (key_names[i - 128])
1861 strcpy (buf2 + 2, key_names[i - 128]);
1862 msymbol_put (one_char_symbol[i], M_key_alias, msymbol (buf2));
1865 for (buf[4] = i - 128; i < 255; i++, buf[4]++)
1866 one_char_symbol[i] = msymbol (buf + 2);
1867 one_char_symbol[i] = msymbol ("M-Delete");
1869 minput_default_driver.open_im = open_im;
1870 minput_default_driver.close_im = close_im;
1871 minput_default_driver.create_ic = create_ic;
1872 minput_default_driver.destroy_ic = destroy_ic;
1873 minput_default_driver.filter = filter;
1874 minput_default_driver.lookup = lookup;
1875 minput_default_driver.callback_list = NULL;
1876 minput_driver = &minput_default_driver;
1883 if (minput_default_driver.callback_list)
1885 M17N_OBJECT_UNREF (minput_default_driver.callback_list);
1886 minput_default_driver.callback_list = NULL;
1888 if (minput_driver->callback_list)
1890 M17N_OBJECT_UNREF (minput_driver->callback_list);
1891 minput_driver->callback_list = NULL;
1896 minput__callback (MInputContext *ic, MSymbol command)
1898 if (ic->im->driver.callback_list)
1900 MInputCallbackFunc func
1901 = (MInputCallbackFunc) mplist_get (ic->im->driver.callback_list,
1905 (func) (ic, command);
1910 minput__char_to_key (int c)
1912 if (c < 0 || c >= 0x100)
1915 return one_char_symbol[c];
1919 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1924 /*** @addtogroup m17nInputMethod */
1929 @name Variables: Predefined symbols for callback commands.
1931 These are the predefined symbols that are used as the @c COMMAND
1932 argument of callback functions of an input method driver (see
1933 #MInputDriver::callback_list ). */
1935 @name ÊÑ¿ô¡§ ¥³¡¼¥ë¥Ð¥Ã¥¯¥³¥Þ¥ó¥ÉÍÑÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë.
1937 ÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Î¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Ë¤ª¤¤¤Æ @c COMMAND °ú¿ô¤È¤·
1938 ¤ÆÍѤ¤¤é¤ì¤ëÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë (#MInputDriver::callback_list »²¾È)¡£
1943 MSymbol Minput_preedit_start;
1944 MSymbol Minput_preedit_done;
1945 MSymbol Minput_preedit_draw;
1946 MSymbol Minput_status_start;
1947 MSymbol Minput_status_done;
1948 MSymbol Minput_status_draw;
1949 MSymbol Minput_candidates_start;
1950 MSymbol Minput_candidates_done;
1951 MSymbol Minput_candidates_draw;
1952 MSymbol Minput_set_spot;
1953 MSymbol Minput_toggle;
1958 @brief The default driver for internal input methods.
1960 The variable #minput_default_driver is the default driver for
1961 internal input methods.
1963 The member MInputDriver::open_im () searches the m17n database for
1964 an input method that matches the tag \< #Minput_method, $LANGUAGE,
1965 $NAME\> and loads it.
1967 The member MInputDriver::callback_list () is @c NULL. Thus, it is
1968 programmers responsibility to set it to a plist of proper callback
1969 functions. Otherwise, no feedback information (e.g. preedit text)
1970 can be shown to users.
1972 The macro M17N_INIT () sets the variable #minput_driver to the
1973 pointer to this driver so that all internal input methods use it.
1975 Therefore, unless @c minput_driver is set differently, the driver
1976 dependent arguments $ARG of the functions whose name begin with
1977 "minput_" are all ignored. */
1980 @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥǥե©¥ë¥È¥É¥é¥¤¥Ð.
1982 ÆþÎϥɥ饤¥Ð #minput_default_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѤΥǥե©¥ë
1983 ¥È¤Î¥É¥é¥¤¥Ð¤Ç¤¢¤ë¡£
1985 ¥á¥ó¥Ð MInputDriver::open_im () ¤Ï m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹Ã椫¤é¥¿¥°
1986 \< #Minput_method, $LANGUAGE, $NAME\> ¤Ë¹çÃפ¹¤ëÆþÎϥ᥽¥Ã¥É¤òõ¤·¡¢
1989 ¥á¥ó¥Ð MInputDriver::callback_list () ¤Ï @c NULL ¤Ê¤Î¤Ç¡¢¥×¥í¥°¥é
1990 ¥Þ¦¤ÇÀÕǤ¤ò»ý¤Ã¤Æ, ŬÀڤʥ³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Î plist ¤ËÀßÄꤷ¤Ê¤¯¤Æ
1991 ¤Ï¤Ê¤é¤Ê¤¤¡£¤µ¤â¤Ê¤¤¤È¡¢preedit ¥Æ¥¥¹¥È¤Ê¤É¤Î¥Õ¥£¡¼¥É¥Ð¥Ã¥¯¾ðÊó¤¬
1992 ¥æ¡¼¥¶¤Ëɽ¼¨¤µ¤ì¤Ê¤¤¡£
1994 ¥Þ¥¯¥í M17N_INIT () ¤ÏÊÑ¿ô #minput_driver ¤ò¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó
1995 ¥¿¤ËÀßÄꤷ¡¢Á´¤Æ¤ÎÆâÉôÆþÎϥ᥽¥Ã¥É¤¬¤³¤Î¥É¥é¥¤¥Ð¤ò»È¤¦¤è¤¦¤Ë¤¹¤ë¡£
1997 ¤·¤¿¤¬¤Ã¤Æ¡¢@c minput_driver ¤¬¥Ç¥Õ¥©¥ë¥ÈÃͤΤޤޤǤ¢¤ì¤Ð¡¢minput_
1998 ¤Ç»Ï¤Þ¤ë´Ø¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô $ARG ¤Ï¤¹¤Ù¤Æ̵»ë¤µ¤ì¤ë¡£ */
2000 MInputDriver minput_default_driver;
2004 @brief The driver for internal input methods.
2006 The variable #minput_driver is a pointer to the input method
2007 driver that is used by internal input methods. The macro
2008 M17N_INIT () initializes it to a pointer to #minput_default_driver
2009 (if <m17n.h> is included) or to #minput_gui_driver (if
2010 <m17n-gui.h> is included). */
2012 @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥɥ饤¥Ð.
2014 ÊÑ¿ô #minput_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤Æ»ÈÍѤµ¤ì¤Æ¤¤¤ëÆþÎÏ¥á
2015 ¥½¥Ã¥É¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£¥Þ¥¯¥íM17N_INIT () ¤Ï¤³¤Î¥Ý¥¤¥ó
2016 ¥¿¤ò #minput_default_driver (<m17n.h> ¤¬´Þ¤Þ¤ì¤ë»þ) ¤Þ¤¿¤Ï
2017 #minput_gui_driver ( <m17n-gui.h> ¤¬´Þ¤Þ¤ì¤ë»þ) ¤Ë½é´ü²½¤¹¤ë¡£ */
2019 MInputDriver *minput_driver;
2021 MSymbol Minput_driver;
2026 @brief Open an input method.
2028 The minput_open_im () function opens an input method that matches
2029 language $LANGUAGE and name $NAME, and returns a pointer to the
2030 input method object newly allocated.
2032 This function at first decides an driver for the input method as
2035 If $LANGUAGE is not #Mnil, the driver pointed by the variable
2036 #minput_driver is used.
2038 If $LANGUAGE is #Mnil and $NAME has #Minput_driver property, the
2039 driver pointed to by the property value is used to open the input
2040 method. If $NAME has no such property, @c NULL is returned.
2042 Then, the member MInputDriver::open_im () of the driver is
2045 $ARG is set in the member @c arg of the structure MInputMethod so
2046 that the driver can refer to it. */
2049 @brief ÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë.
2051 ´Ø¿ô minput_open_im () ¤Ï¸À¸ì $LANGUAGE ¤È̾Á° $NAME ¤Ë¹çÃפ¹¤ëÆþ
2052 Îϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤·¡¢¿·¤¿¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿ÆþÎϥ᥽¥Ã¥É¥ª¥Ö¥¸¥§¥¯
2053 ¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
2055 ¤³¤Î´Ø¿ô¤Ï¡¢¤Þ¤ºÆþÎϥ᥽¥Ã¥ÉÍѤΥɥ饤¥Ð¤ò°Ê²¼¤Î¤è¤¦¤Ë¤·¤Æ·èÄꤹ¤ë¡£
2057 $LANGUAGE ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢ÊÑ¿ô #minput_driver ¤Ç»Ø¤µ¤ì¤Æ¤¤¤ë
2060 $LANGUAGE ¤¬ #Mnil ¤Ç¤¢¤ê¡¢$NAME ¤¬ #Minput_driver ¥×¥í¥Ñ¥Æ¥£¤ò»ý
2061 ¤Ä¾ì¹ç¤Ë¤Ï¡¢¤½¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤǻؤµ¤ì¤Æ¤¤¤ëÆþÎϥɥ饤¥Ð¤òÍѤ¤¤ÆÆþ
2062 Îϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë¡£$NAME ¤Ë¤½¤Î¤è¤¦¤Ê¥×¥í¥Ñ¥Æ¥£¤¬Ìµ¤«¤Ã¤¿¾ì
2063 ¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
2065 ¼¡¤¤¤Ç¡¢¥É¥é¥¤¥Ð¤Î¥á¥ó¥Ð MInputDriver::open_im () ¤¬¸Æ¤Ð¤ì¤ë¡£
2067 $ARG ¤Ï¡¢¥É¥é¥¤¥Ð¤¬»²¾È¤Ç¤¤ë¤è¤¦¤Ë¡¢¹½Â¤ÂÎ MInputMethod ¤Î¥á¥ó¥Ð
2068 @c arg ¤ËÀßÄꤵ¤ì¤ë¡£
2070 @latexonly \IPAlabel{minput_open} @endlatexonly
2075 minput_open_im (MSymbol language, MSymbol name, void *arg)
2078 MInputDriver *driver;
2081 driver = minput_driver;
2084 driver = (MInputDriver *) msymbol_get (name, Minput_driver);
2086 MERROR (MERROR_IM, NULL);
2089 MSTRUCT_CALLOC (im, MERROR_IM);
2090 im->language = language;
2093 im->driver = *driver;
2094 if ((*im->driver.open_im) (im) < 0)
2105 @brief Close an input method.
2107 The minput_close_im () function closes the input method $IM, which
2108 must have been created by minput_open_im (). */
2111 @brief ÆþÎϥ᥽¥Ã¥É¤ò¥¯¥í¡¼¥º¤¹¤ë.
2113 ´Ø¿ô minput_close_im () ¤Ï¡¢ÆþÎϥ᥽¥Ã¥É $IM ¤ò¥¯¥í¡¼¥º¤¹¤ë¡£¤³¤Î
2114 ÆþÎϥ᥽¥Ã¥É $IM ¤Ï minput_open_im () ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê¤±¤ì
2118 minput_close_im (MInputMethod *im)
2120 (*im->driver.close_im) (im);
2127 @brief Create an input context.
2129 The minput_create_ic () function creates an input context object
2130 associated with input method $IM, and calls callback functions
2131 corresponding to #Minput_preedit_start, #Minput_status_start, and
2132 #Minput_status_draw in this order.
2136 If an input context is successfully created, minput_create_ic ()
2137 returns a pointer to it. Otherwise it returns @c NULL. */
2140 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÀ¸À®¤¹¤ë.
2142 ´Ø¿ô minput_create_ic () ¤ÏÆþÎϥ᥽¥Ã¥É $IM ¤ËÂбþ¤¹¤ëÆþÎÏ¥³¥ó¥Æ¥¯
2143 ¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤·¡¢ #Minput_preedit_start,
2144 #Minput_status_start, #Minput_status_draw ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø
2149 ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤¬À¸À®¤µ¤ì¤¿¾ì¹ç¡¢minput_create_ic () ¤Ï¤½¤ÎÆþÎÏ¥³
2150 ¥ó¥Æ¥¯¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¼ºÇÔ¤·¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
2154 minput_create_ic (MInputMethod *im, void *arg)
2158 MSTRUCT_CALLOC (ic, MERROR_IM);
2161 ic->preedit = mtext ();
2162 ic->candidate_list = NULL;
2163 ic->produced = mtext ();
2164 ic->spot.x = ic->spot.y = 0;
2166 ic->plist = mplist ();
2167 if ((*im->driver.create_ic) (ic) < 0)
2169 M17N_OBJECT_UNREF (ic->preedit);
2170 M17N_OBJECT_UNREF (ic->produced);
2171 M17N_OBJECT_UNREF (ic->plist);
2176 if (im->driver.callback_list)
2178 minput__callback (ic, Minput_preedit_start);
2179 minput__callback (ic, Minput_status_start);
2180 minput__callback (ic, Minput_status_draw);
2189 @brief Destroy an input context.
2191 The minput_destroy_ic () function destroys the input context $IC,
2192 which must have been created by minput_create_ic (). It calls
2193 callback functions corresponding to #Minput_preedit_done,
2194 #Minput_status_done, and #Minput_candidates_done in this order. */
2197 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÇ˲õ¤¹¤ë.
2199 ´Ø¿ô minput_destroy_ic () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤òÇ˲õ¤¹¤ë¡£¤³
2200 ¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ï minput_create_ic () ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê
2201 ¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£¤³¤Î´Ø¿ô¤Ï#Minput_preedit_done,
2202 #Minput_status_done, #Minput_candidates_done ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò
2207 minput_destroy_ic (MInputContext *ic)
2209 if (ic->im->driver.callback_list)
2211 minput__callback (ic, Minput_preedit_done);
2212 minput__callback (ic, Minput_status_done);
2213 minput__callback (ic, Minput_candidates_done);
2215 (*ic->im->driver.destroy_ic) (ic);
2216 M17N_OBJECT_UNREF (ic->preedit);
2217 M17N_OBJECT_UNREF (ic->produced);
2218 M17N_OBJECT_UNREF (ic->plist);
2225 @brief Filter an input key.
2227 The minput_filter () function filters input key $KEY according to
2228 input context $IC, and calls callback functions corresponding to
2229 #Minput_preedit_draw, #Minput_status_draw, and
2230 #Minput_candidates_draw if the preedit text, the status, and the
2231 current candidate are changed respectively.
2234 If $KEY is filtered out, this function returns 1. In that case,
2235 the caller should discard the key. Otherwise, it returns 0, and
2236 the caller should handle the key, for instance, by calling the
2237 function minput_lookup () with the same key. */
2240 @brief ÆþÎÏ¥¡¼¤ò¥Õ¥£¥ë¥¿¤¹¤ë.
2242 ´Ø¿ô minput_filter () ¤ÏÆþÎÏ¥¡¼ $KEY ¤òÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤Ë±þ
2243 ¤¸¤Æ¥Õ¥£¥ë¥¿¤·¡¢preedit ¥Æ¥¥¹¥È¡¢¥¹¥Æ¡¼¥¿¥¹¡¢¸½»þÅÀ¤Ç¤Î¸õÊ䤬ÊѲ½
2244 ¤·¤¿ºÝ¤Ë¤Ï¤½¤ì¤¾¤ì#Minput_preedit_draw, #Minput_status_draw,
2245 #Minput_candidates_draw ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¸Æ¤Ö¡£
2248 $KEY ¤¬¥Õ¥£¥ë¥¿¤µ¤ì¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 1 ¤òÊÖ¤¹¡£¤³¤Î¾ì¹ç¸Æ¤Ó
2249 ½Ð¤·Â¦¤Ï¤³¤Î¥¡¼¤ò¼Î¤Æ¤ë¤Ù¤¤Ç¤¢¤ë¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0 ¤òÊÖ¤·¡¢¸Æ¤Ó
2250 ½Ð¤·Â¦¤Ï¡¢¤¿¤È¤¨¤ÐƱ¤¸¥¡¼¤Ç´Ø¿ô minput_lookup () ¤ò¸Æ¤Ö¤Ê¤É¤·¤Æ¡¢
2251 ¤³¤Î¥¡¼¤ò½èÍý¤¹¤ë¡£
2253 @latexonly \IPAlabel{minput_filter} @endlatexonly
2257 minput_filter (MInputContext *ic, MSymbol key, void *arg)
2264 ret = (*ic->im->driver.filter) (ic, key, arg);
2266 if (ic->im->driver.callback_list)
2268 if (ic->preedit_changed)
2269 minput__callback (ic, Minput_preedit_draw);
2270 if (ic->status_changed)
2271 minput__callback (ic, Minput_status_draw);
2272 if (ic->candidates_changed)
2273 minput__callback (ic, Minput_candidates_draw);
2274 ic->preedit_changed = ic->status_changed = ic->candidates_changed = 0;
2283 @brief Lookup a text produced in the input context.
2285 The minput_lookup () function looks up a text in the input context
2286 $IC. $KEY must be the same one provided to the previous call of
2289 If a text was produced by the input method, it is concatenated
2292 This function calls #MInputDriver::lookup .
2295 If $KEY was correctly handled by the input method, this function
2296 returns 0. Otherwise, returns -1, even in that case, some text
2297 may be produced in $MT. */
2300 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥ÈÃæ¤Î¥Æ¥¥¹¥È¤Î¸¡º÷.
2302 ´Ø¿ô minput_lookup () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC Ãæ¤Î¥Æ¥¥¹¥È¤ò¸¡º÷¤¹
2303 ¤ë¡£$KEY ¤Ï´Ø¿ôminput_filter () ¤Ø¤ÎľÁ°¤Î¸Æ¤Ó½Ð¤·¤ËÍѤ¤¤é¤ì¤¿¤â¤Î
2304 ¤ÈƱ¤¸¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2306 ¥Æ¥¥¹¥È¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆÀ¸À®¤µ¤ì¤Æ¤¤¤ì¤Ð¡¢¥Æ¥¥¹¥È¤Ï M-text
2309 ¤³¤Î´Ø¿ô¤Ï¡¢#MInputDriver::lookup ¤ò¸Æ¤Ö¡£
2312 $KEY ¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆŬÀڤ˽èÍý¤Ç¤¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 0 ¤òÊÖ¤¹¡£
2313 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£¤³¤Î¾ì¹ç¤Ç¤â $MT ¤Ë²¿¤é¤«¤Î¥Æ¥¥¹¥È¤¬À¸
2314 À®¤µ¤ì¤Æ¤¤¤ë¤³¤È¤¬¤¢¤ë¡£
2316 @latexonly \IPAlabel{minput_lookup} @endlatexonly */
2319 minput_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2321 return (ic ? (*ic->im->driver.lookup) (ic, key, arg, mt) : -1);
2326 @brief Set the spot of the input context.
2328 The minput_set_spot () function set the spot of input context $IC
2329 to coordinate ($X, $Y ) with the height $ASCENT and $DESCENT .
2330 The semantics of these values depend on the input method driver.
2331 $FONTSIZE specfies the fontsize of a preedit text in 1/10 point.
2333 For instance, an driver designed to work in CUI environment may
2334 use $X and $Y as column and row numbers, and ignore $ASCENT and
2335 $DESCENT . An driver designed to work on a window system may
2336 treat $X and $Y as pixel offsets relative to the origin of the
2337 client window, and treat $ASCENT and $DESCENT as ascent and
2338 descent pixels of a line at ($X . $Y ).
2340 $MT and $POS is an M-text and a character position at the spot.
2341 $MT may be @c NULL, in which case, the input method cannot get
2342 information about the text around the spot. */
2345 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Î¥¹¥Ý¥Ã¥È¤òÀßÄꤹ¤ë
2347 ´Ø¿ô minput_set_spot () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤Î¥¹¥Ý¥Ã¥È¤ò¡¢ºÂ
2348 ɸ ($X, $Y )¤Ë ¡¢¹â¤µ $ASCENT¡¢ $DESCENT ¤ÇÀßÄꤹ¤ë¡£ ¤³¤ì¤é¤ÎÃͤÎ
2349 °ÕÌ£¤ÏÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë¡£$FONTSIZE ¤Ïpreedit ¥Æ¥¥¹¥È
2350 ¤Î¥Õ¥©¥ó¥È¥µ¥¤¥º¤ò 1/10 ¥Ý¥¤¥ó¥Èñ°Ì¤Ç»ØÄꤹ¤ë¡£
2352 ¤¿¤È¤¨¤Ð CUI ´Ä¶¤ÇÆ°ºî¤¹¤ë¥É¥é¥¤¥Ð¤Ï $X ¤È $Y ¤ò¤½¤ì¤¾¤ìÎó¤È¹Ô¤Î
2353 ÈÖ¹æ¤È¤·¤ÆÍѤ¤¡¢$ASCENT ¤È $DESCENT ¤ò̵»ë¤¹¤ë¤«¤â¤·¤ì¤Ê¤¤¡£ ¤Þ¤¿
2354 ¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥àÍѤΥɥ饤¥Ð¤Ï $X ¤È $Y ¤ò¥¯¥é¥¤¥¢¥ó¥È¥¦¥£¥ó¥É¥¦
2355 ¤Î¸¶ÅÀ¤«¤é¤Î¥ª¥Õ¥»¥Ã¥È¤ò¥Ô¥¯¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¤¡¢
2356 $ASCENT ¤È $DESCENT ¤ò ($X . $Y ) ¤ÎÎó¤Î¥¢¥»¥ó¥È¤È¥Ç¥£¥»¥ó¥È¤ò¥Ô¥¯
2357 ¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¦¤«¤â¤·¤ì¤Ê¤¤¡£
2359 $MT ¤È $POS ¤Ï¤½¤Î¥¹¥Ý¥Ã¥È¤Î M-text ¤Èʸ»ú°ÌÃ֤Ǥ¢¤ë¡£$MT ¤Ï @c
2360 NULL ¤Ç¤â¤è¤¯¡¢¤½¤Î¾ì¹ç¤Ë¤ÏÆþÎϥ᥽¥Ã¥É¤Ï¥¹¥Ý¥Ã¥È¼þÊդΥƥ¥¹¥È¤Ë
2361 ´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë¤³¤È¤¬¤Ç¤¤Ê¤¤¡£
2365 minput_set_spot (MInputContext *ic, int x, int y,
2366 int ascent, int descent, int fontsize,
2371 ic->spot.ascent = ascent;
2372 ic->spot.descent = descent;
2373 ic->spot.fontsize = fontsize;
2376 if (ic->im->driver.callback_list)
2377 minput__callback (ic, Minput_set_spot);
2382 @brief Toggle input method.
2384 The minput_toggle () function toggles the input method associated
2385 with the input context $IC. */
2387 @brief ÆþÎϥ᥽¥Ã¥É¤òÀÚÂؤ¨¤ë.
2389 ´Ø¿ô minput_toggle () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤ËÂбþÉÕ¤±¤é¤ì¤¿ÆþÎÏ
2390 ¥á¥½¥Ã¥É¤ò¥È¥°¥ë¤¹¤ë¡£
2394 minput_toggle (MInputContext *ic)
2396 if (ic->im->driver.callback_list)
2397 minput__callback (ic, Minput_toggle);
2398 ic->active = ! ic->active;
2404 /*** @addtogroup m17nDebug */
2410 @brief Dump an input method.
2412 The mdebug_dump_im () function prints the input method $IM in a
2413 human readable way to the stderr. $INDENT specifies how many
2414 columns to indent the lines but the first one.
2417 This function returns $IM. */
2419 @brief ÆþÎϥ᥽¥Ã¥É¤ò¥À¥ó¥×¤¹¤ë.
2421 ´Ø¿ô mdebug_dump_im () ¤ÏÆþÎϥ᥽¥Ã¥É $IM ¤ò stderr ¤Ë¿Í´Ö¤Ë²ÄÆɤÊ
2422 ·Á¤Ç°õºþ¤¹¤ë¡£$INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£
2425 ¤³¤Î´Ø¿ô¤Ï $IM ¤òÊÖ¤¹¡£ */
2428 mdebug_dump_im (MInputMethod *im, int indent)
2430 MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
2433 prefix = (char *) alloca (indent + 1);
2434 memset (prefix, 32, indent);
2435 prefix[indent] = '\0';
2437 fprintf (stderr, "(input-method %s %s ", msymbol_name (im->language),
2438 msymbol_name (im->name));
2439 mdebug_dump_mtext (im_info->title, 0, 0);
2440 if (im->name != Mnil)
2444 MPLIST_DO (state, im_info->states)
2446 fprintf (stderr, "\n%s ", prefix);
2447 dump_im_state (MPLIST_VAL (state), indent + 2);
2450 fprintf (stderr, ")");