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 an input driver of the input
30 method. An input driver is a set of functions for handling the
31 input method. There are two kinds of input methods; internal one
36 <li> Internal Input Method
38 An internal input method has non @c Mnil LANGUAGE, and the body is
39 defined in the m17n database by the tag <Minput_method, LANGUAGE,
40 NAME>. For this kind of input methods, the m17n library uses two
41 predefined input method drivers, one for CUI use and the other for
42 GUI use. Those driver utilize the input processing engine
43 provided by the m17n library itself. The m17n database may
44 provides an input method that is not only for a specific language.
45 The database uses @c Mt as the language of such an input method.
47 An internal input method accepts an input key which is a symbol
48 associated with an input event. As there is no way for the @c
49 m17n @c library to know how input events are represented in an
50 application program, a application programmer have to convert an
51 input event to an input key by himself. See the documentation of
52 the function minput_event_to_key () for the detail.
54 <li> Foreign Input Method
56 A foreign input method has @c Mnil LANGUAGE, and the body is
57 defined in an external resources (e.g. XIM of X Window System).
58 For this kind of input methods, the symbol NAME must have a
59 property of key @c Minput_driver, and the value must be a pointer
60 to an input driver. So, by preparing a proper input
61 driver, any kind of input method can be treated in the framework
62 of the @c m17n @c library.
64 For convenience, the m17n-X library provides an input driver that
65 enables the input style of OverTheSpot for XIM, and stores @c
66 Minput_driver property of the symbol @c Mxim with a pointer to
67 that driver. See the documentation of m17n GUI API for the
74 The typical processing flow of handling an input method is: open
75 an input method, create an input context for the input method,
76 filter an input key, and looking up a produced text in the input
82 @addtogroup m17nInputMethod
83 @brief ÆþÎϥ᥽¥Ã¥ÉÍÑAPI
85 ÆþÎϥ᥽¥Ã¥É¤Ï¿ÍͤÊʸ»ú¤òÆþÎϤ¹¤ë¤¿¤á¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¢¤ë¡£ÆþÎÏ¥á
86 ¥½¥Ã¥É¤Ï¥·¥ó¥Ü¥ë LANGUAGE ¤È NAME ¤ÎÁȤˤè¤Ã¤Æ¼±Ê̤µ¤ì¡¢¤³¤ÎÁȤˤè¤Ã
87 ¤ÆÆþÎϥɥ饤¥Ð¤¬·è¤Þ¤ë¡£ÆþÎϥɥ饤¥Ð¤È¤Ï»ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤ò°·¤¦¤¿
88 ¤á¤Î´Ø¿ô¤Î½¸¤Þ¤ê¤Ç¤¢¤ë¡£
90 ÆþÎϥ᥽¥Ã¥É¤Ë¤ÏÆâÉô¥á¥½¥Ã¥É¤È³°Éô¥á¥½¥Ã¥É¤ÎÆóÄ̤꤬¤¢¤ë¡£
94 ÆâÉôÆþÎϥ᥽¥Ã¥É¤Ï LANGUAGE ¤¬ @c Mnil °Ê³°¤Î¤â¤Î¤Ç¤¢¤ê¡¢ËÜÂΤÏ
95 m17n ¸À¸ì¾ðÊó¥Ù¡¼¥¹¤Ë <Minput_method, LANGUAGE, NAME>¤È¤¤¤¦¥¿¥°ÉÕ
96 ¤¤ÇÄêµÁ¤µ¤ì¤Æ¤¤¤ë¡£¤³¤Î¼ï¤ÎÆþÎϥ᥽¥Ã¥É¤ËÂФ·¤Æ¡¢m17n¥é¥¤¥Ö¥é¥ê¤Ë
97 ¤ÏCUIÍѤÈGUIÍѤ½¤ì¤¾¤ì¤ÎÆþÎϥɥ饤¥Ð¤¬¤¢¤é¤«¤¸¤á½àÈ÷¤µ¤ì¤Æ¤¤¤ë¡£¤³
98 ¤ì¤é¤Î¥É¥é¥¤¥Ð¤Ïm17n¥é¥¤¥Ö¥é¥ê¼«¿È¤ÎÆþÎϽèÍý¥¨¥ó¥¸¥ó¤òÍøÍѤ¹¤ë¡£
100 ÆâÉôÆþÎϥ᥽¥Ã¥É¤Ï¡¢¥æ¡¼¥¶¤ÎÆþÎÏ¥¤¥Ù¥ó¥È¤ËÂбþ¤·¤¿ÆþÎÏ¥¡¼¤ò¼õ¤±¼è
101 ¤ë¡£ÆþÎÏ¥¡¼¤Ï¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£@c m17n @c ¥é¥¤¥Ö¥é¥ê ¤ÏÆþÎÏ¥¤¥Ù¥ó¥È
102 ¤¬¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¡¦¥×¥í¥°¥é¥à¤Ç¤É¤Î¤è¤¦¤Ëɽ¸½¤µ¤ì¤Æ¤¤¤ë¤«¤òÃΤë½Ñ
103 ¤ò»ý¤¿¤Ê¤¤¤Î¤Ç¡¢ÆþÎÏ¥¤¥Ù¥ó¥È¤«¤éÆþÎÏ¥¡¼¤Ø¤ÎÊÑ´¹¤Ï¥×¥í¥°¥é¥Þ¤ÎÀÕǤ
104 ¤Ç¹Ô¤ï¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï´Ø¿ô minput_event_to_key ()
105 ¤Î¥É¥¥å¥á¥ó¥È¤ò»²¾È¤Î¤³¤È¡£
109 ³°ÉôÆþÎϥ᥽¥Ã¥É¤Ï LANGUAGE ¤¬ @c Mnil ¤Î¤â¤Î¤Ç¤¢¤ê¡¢¤ÇËÜÂΤϳ°Éô
110 ¤Î¥ê¥½¡¼¥¹¤È¤·¤ÆÄêµÁ¤µ¤ì¤ë¡£¡Ê¤¿¤È¤¨¤ÐX Window System ¤ÎXIM ¤Ê¤É¡£)
111 ¤³¤Î¼ï¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¥·¥ó¥Ü¥ë NAME ¤Ï@c Minput_driver ¤ò¥¡¼¤È
112 ¤¹¤ë¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Á¡¢¤½¤ÎÃͤÏÆþÎϥɥ饤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê
113 ¤é¤Ê¤¤¡£¤·¤¿¤¬¤Ã¤Æ¡¢Å¬ÀÚ¤ÊÆþÎϥɥ饤¥Ð¤ò½àÈ÷¤¹¤ë¤³¤È¤Ë¤è¤Ã¤Æ¡¢¤¤¤«
114 ¤Ê¤ëÆþÎϥ᥽¥Ã¥É¤â @c m17n @c ¥é¥¤¥Ö¥é¥ê¤ÎÏÈÁȤÎÃæ¤Ç°·¤¦»ö¤¬¤Ç¤¤ë¡£
116 ´Êñ¤Î¤¿¤á¡¢m17n X ¥é¥¤¥Ö¥é¥ê¤ÏXIM ¤Î OverTheSpot ¤ÎÆþÎÏ¥¹¥¿¥¤¥ë¤ò
117 ¼Â¸½¤¹¤ëÆþÎϥɥ饤¥Ð¤òÄ󶡤·¤Æ¤¤¤ë¡£¤Þ¤¿¥·¥ó¥Ü¥ë @c Mxim ¤Î @c
118 Minput_driver ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤȤ·¤Æ¤½¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÝ»ý¤·
119 ¤Æ¤¤¤ë¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ïm17n-win API ¤Î¥É¥¥å¥á¥ó¥È¤ò»²¾È¤Î¤³¤È¡£
123 ÆþÎϥ᥽¥Ã¥É½èÍý¤Îŵ·¿Åª¤Ê½èÍý¤Ï°Ê²¼¤Î¤è¤¦¤Ë¤Ê¤ë¡£ÆþÎϥ᥽¥Ã¥É¤Î¥ª¡¼
124 ¥×¥ó¡¢¤½¤ÎÆþÎϥ᥽¥Ã¥É¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤ÎÀ¸À®¡¢ÆþÎÏ¥¤¥Ù¥ó¥È¤Î¥Õ¥£
125 ¥ë¥¿¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ç¤ÎÀ¸À®¥Æ¥¥¹¥È¤Î¸¡º÷¡£ */
129 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
130 /*** @addtogroup m17nInternal
138 #include "m17n-gui.h"
139 #include "m17n-misc.h"
140 #include "internal.h"
146 static MSymbol Minput_method;
148 /** Symbols to load an input method data. */
149 static MSymbol Mtitle, Mmacro, Mmodule, Mstate;
151 /** Symbols for actions. */
152 static MSymbol Minsert, Mdelete, Mmark, Mmove, Mpushback, Mundo, Mcall, Mshift;
153 static MSymbol Mselect, Mshow, Mhide;
154 static MSymbol Mset, Madd, Msub, Mmul, Mdiv, Mequal, Mless, Mgreater;
156 static MSymbol Mcandidate_list, Mcandidate_index;
158 static MSymbol Minit, Mfini;
160 /** Symbols for key events. */
161 static MSymbol one_char_symbol[256];
163 static MSymbol M_key_alias;
165 /** Structure to hold a map. */
169 /** List of actions to take when we reach the map. In a root map,
170 the actions are executed only when there's no more key. */
173 /** List of deeper maps. If NULL, this is a terminal map. */
176 /** List of actions to take when we leave the map successfully. In
177 a root map, the actions are executed only when none of submaps
178 handle the current key. */
179 MPlist *branch_actions;
182 typedef MPlist *(*MIMExternalFunc) (MPlist *plist);
187 MPlist *func_list; /* function name vs (MIMExternalFunc *) */
192 /** Name of the state. */
195 /** Title of the state, or NULL. */
198 /** Key translation map of the state. Built by merging all maps of
205 marker_code (MSymbol sym)
211 name = MSYMBOL_NAME (sym);
212 return ((name[0] == '@'
213 && ((name[1] >= '0' && name[1] <= '9')
214 || name[1] == '<' || name[1] == '>'
215 || name[1] == '=' || name[1] == '+' || name[1] == '-'
216 || name[1] == '[' || name[1] == ']')
222 integer_value (MInputContext *ic, MPlist *arg)
224 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
226 MText *preedit = ic->preedit;
227 int len = mtext_nbytes (preedit);
229 if (MPLIST_INTEGER_P (arg))
230 return MPLIST_INTEGER (arg);
231 code = marker_code (MPLIST_SYMBOL (arg));
233 return (int) mplist_get (ic_info->vars, MPLIST_SYMBOL (arg));
234 if (code >= '0' && code <= '9')
236 else if (code == '=')
237 code = ic->cursor_pos;
238 else if (code == '-' || code == '[')
239 code = ic->cursor_pos - 1;
240 else if (code == '+' || code == ']')
241 code = ic->cursor_pos + 1;
242 else if (code == '<')
244 else if (code == '<')
246 return (code >= 0 && code < len ? mtext_ref_char (preedit, code) : -1);
250 /* Parse PLIST as an action list while modifying the list to regularize
251 actions. PLIST should have this form:
252 PLIST ::= ( (ACTION-NAME ACTION-ARG *) *).
253 Return 0 if successfully parsed, otherwise return -1. */
256 parse_action_list (MPlist *plist, MPlist *macros)
258 MPLIST_DO (plist, plist)
260 if (MPLIST_MTEXT_P (plist))
262 /* This is a short form of (insert MTEXT). */
263 /* if (mtext_nchars (MPLIST_MTEXT (plist)) == 0)
264 MERROR (MERROR_IM, -1); */
266 else if (MPLIST_PLIST_P (plist)
267 && (MPLIST_MTEXT_P (MPLIST_PLIST (plist))
268 || MPLIST_PLIST_P (MPLIST_PLIST (plist))))
272 /* This is a short form of (insert (GROUPS *)). */
273 MPLIST_DO (pl, MPLIST_PLIST (plist))
275 if (MPLIST_PLIST_P (pl))
279 MPLIST_DO (elt, MPLIST_PLIST (pl))
280 if (! MPLIST_MTEXT_P (elt)
281 || mtext_nchars (MPLIST_MTEXT (elt)) == 0)
282 MERROR (MERROR_IM, -1);
286 if (! MPLIST_MTEXT_P (pl)
287 || mtext_nchars (MPLIST_MTEXT (pl)) == 0)
288 MERROR (MERROR_IM, -1);
292 else if (MPLIST_INTEGER_P (plist))
294 int c = MPLIST_INTEGER (plist);
296 if (c < 0 || c > MCHAR_MAX)
297 MERROR (MERROR_IM, -1);
299 else if (MPLIST_PLIST_P (plist)
300 && MPLIST_SYMBOL_P (MPLIST_PLIST (plist)))
302 MPlist *pl = MPLIST_PLIST (plist);
303 MSymbol action_name = MPLIST_SYMBOL (pl);
305 pl = MPLIST_NEXT (pl);
307 if (action_name == Minsert)
309 if (MPLIST_MTEXT_P (pl))
311 if (mtext_nchars (MPLIST_MTEXT (pl)) == 0)
312 MERROR (MERROR_IM, -1);
314 else if (MPLIST_PLIST_P (pl))
318 if (MPLIST_PLIST_P (pl))
322 MPLIST_DO (elt, MPLIST_PLIST (pl))
323 if (! MPLIST_MTEXT_P (elt)
324 || mtext_nchars (MPLIST_MTEXT (elt)) == 0)
325 MERROR (MERROR_IM, -1);
329 if (! MPLIST_MTEXT_P (pl)
330 || mtext_nchars (MPLIST_MTEXT (pl)) == 0)
331 MERROR (MERROR_IM, -1);
335 else if (! MPLIST_SYMBOL_P (pl))
336 MERROR (MERROR_IM, -1);
338 else if (action_name == Mselect
339 || action_name == Mdelete
340 || action_name == Mmove)
342 if (! MPLIST_SYMBOL_P (pl)
343 && ! MPLIST_INTEGER_P (pl))
344 MERROR (MERROR_IM, -1);
346 else if (action_name == Mmark
347 || action_name == Mcall
348 || action_name == Mshift)
350 if (! MPLIST_SYMBOL_P (pl))
351 MERROR (MERROR_IM, -1);
353 else if (action_name == Mshow || action_name == Mhide
354 || action_name == Mundo)
356 if (! MPLIST_TAIL_P (pl))
357 MERROR (MERROR_IM, -1);
359 else if (action_name == Mpushback)
361 if (! MPLIST_INTEGER_P (pl))
362 MERROR (MERROR_IM, -1);
364 else if (action_name == Mset || action_name == Madd
365 || action_name == Msub || action_name == Mmul
366 || action_name == Mdiv)
368 if (! (MPLIST_SYMBOL_P (pl)
369 && (MPLIST_INTEGER_P (MPLIST_NEXT (pl))
370 || MPLIST_SYMBOL_P (MPLIST_NEXT (pl)))))
371 MERROR (MERROR_IM, -1);
373 else if (action_name == Mequal || action_name == Mless
374 || action_name == Mgreater)
376 if (! ((MPLIST_INTEGER_P (pl) || MPLIST_SYMBOL_P (pl))
377 && (MPLIST_INTEGER_P (MPLIST_NEXT (pl))
378 || MPLIST_SYMBOL_P (MPLIST_NEXT (pl)))))
379 MERROR (MERROR_IM, -1);
380 pl = MPLIST_NEXT (MPLIST_NEXT (pl));
381 if (! MPLIST_PLIST_P (pl))
382 MERROR (MERROR_IM, -1);
383 if (parse_action_list (MPLIST_PLIST (pl), macros) < 0)
384 MERROR (MERROR_IM, -1);
385 pl = MPLIST_NEXT (pl);
386 if (MPLIST_PLIST_P (pl)
387 && parse_action_list (MPLIST_PLIST (pl), macros) < 0)
388 MERROR (MERROR_IM, -1);
390 else if (! macros || ! mplist_get (macros, action_name))
391 MERROR (MERROR_IM, -1);
394 MERROR (MERROR_IM, -1);
401 /* Load a translation into MAP from PLIST.
403 PLIST ::= ( KEYSEQ MAP-ACTION * ) */
406 load_translation (MIMMap *map, MPlist *plist, MPlist *branch_actions,
412 if (MPLIST_MTEXT_P (plist))
414 MText *mt = MPLIST_MTEXT (plist);
416 len = mtext_nchars (mt);
417 if (len == 0 || len != mtext_nbytes (mt))
418 MERROR (MERROR_IM, -1);
419 keyseq = (MSymbol *) alloca (sizeof (MSymbol) * len);
420 for (i = 0; i < len; i++)
421 keyseq[i] = one_char_symbol[MTEXT_DATA (mt)[i]];
423 else if (MPLIST_PLIST_P (plist))
425 MPlist *elt = MPLIST_PLIST (plist);
427 len = MPLIST_LENGTH (elt);
429 MERROR (MERROR_IM, -1);
430 keyseq = (MSymbol *) alloca (sizeof (int) * len);
431 for (i = 0; i < len; i++, elt = MPLIST_NEXT (elt))
433 if (MPLIST_INTEGER_P (elt))
435 int c = MPLIST_INTEGER (elt);
437 if (c < 0 || c >= 0x100)
438 MERROR (MERROR_IM, -1);
439 keyseq[i] = one_char_symbol[c];
441 else if (MPLIST_SYMBOL_P (elt))
442 keyseq[i] = MPLIST_SYMBOL (elt);
444 MERROR (MERROR_IM, -1);
448 MERROR (MERROR_IM, -1);
450 for (i = 0; i < len; i++)
452 MIMMap *deeper = NULL;
455 deeper = mplist_get (map->submaps, keyseq[i]);
457 map->submaps = mplist ();
460 /* Fixme: It is better to make all deeper maps at once. */
461 MSTRUCT_CALLOC (deeper, MERROR_IM);
462 mplist_put (map->submaps, keyseq[i], deeper);
467 /* We reach a terminal map. */
469 || map->branch_actions)
470 /* This map is already defined. We avoid overriding it. */
473 plist = MPLIST_NEXT (plist);
474 if (! MPLIST_TAIL_P (plist))
476 if (parse_action_list (plist, macros) < 0)
477 MERROR (MERROR_IM, -1);
478 map->map_actions = plist;
479 M17N_OBJECT_REF (plist);
483 map->branch_actions = branch_actions;
484 M17N_OBJECT_REF (branch_actions);
490 /* Load a branch from PLIST into MAP. PLIST has this form:
491 PLIST ::= ( MAP-NAME BRANCH-ACTION * )
492 MAPS is a plist of raw maps.
493 STATE is the current state. */
496 load_branch (MPlist *plist, MPlist *maps, MIMMap *map, MPlist *macros)
499 MPlist *branch_actions;
501 if (! MPLIST_SYMBOL_P (plist))
502 MERROR (MERROR_IM, -1);
503 map_name = MPLIST_SYMBOL (plist);
504 plist = MPLIST_NEXT (plist);
505 if (MPLIST_TAIL_P (plist))
506 branch_actions = NULL;
507 else if (parse_action_list (plist, macros) < 0)
508 MERROR (MERROR_IM, -1);
510 branch_actions = plist;
511 if (map_name == Mnil)
513 map->branch_actions = branch_actions;
515 M17N_OBJECT_REF (branch_actions);
517 else if (map_name == Mt)
519 map->map_actions = branch_actions;
521 M17N_OBJECT_REF (branch_actions);
525 plist = (MPlist *) mplist_get (maps, map_name);
526 if (! plist || ! MPLIST_PLIST_P (plist))
527 MERROR (MERROR_IM, -1);
528 MPLIST_DO (plist, plist)
529 if (! MPLIST_PLIST_P (plist)
530 || (load_translation (map, MPLIST_PLIST (plist), branch_actions,
533 MERROR (MERROR_IM, -1);
539 /* Load a macro from PLIST into MACROS.
541 PLIST ::= ( MACRO-NAME ACTION * )
542 MACROS is a plist of macro names vs action list. */
544 load_macros (MPlist *plist, MPlist *macros)
548 if (! MPLIST_SYMBOL_P (plist))
549 MERROR (MERROR_IM, -1);
550 name = MPLIST_SYMBOL (plist);
551 plist = MPLIST_NEXT (plist);
552 if (MPLIST_TAIL_P (plist)
553 || parse_action_list (plist, macros) < 0)
554 MERROR (MERROR_IM, -1);
555 mplist_put (macros, name, plist);
556 M17N_OBJECT_REF (plist);
560 /* Load an external module from PLIST into EXTERNALS.
562 PLIST ::= ( MODULE-NAME FUNCTION * )
563 EXTERNALS is a plist of MODULE-NAME vs (MIMExternalModule *). */
565 #ifndef DLOPEN_SHLIB_EXT
566 #define DLOPEN_SHLIB_EXT ".so"
570 load_external_module (MPlist *plist, MPlist *externals)
575 MIMExternalModule *external;
579 if (MPLIST_MTEXT_P (plist))
580 module = msymbol ((char *) MTEXT_DATA (MPLIST_MTEXT (plist)));
581 else if (MPLIST_SYMBOL_P (plist))
582 module = MPLIST_SYMBOL (plist);
583 module_file = alloca (strlen (MSYMBOL_NAME (module))
584 + strlen (DLOPEN_SHLIB_EXT) + 1);
585 sprintf (module_file, "%s%s", MSYMBOL_NAME (module), DLOPEN_SHLIB_EXT);
587 handle = dlopen (module_file, RTLD_NOW);
590 fprintf (stderr, "%s\n", dlerror ());
591 MERROR (MERROR_IM, -1);
593 func_list = mplist ();
594 MPLIST_DO (plist, MPLIST_NEXT (plist))
596 if (! MPLIST_SYMBOL_P (plist))
597 MERROR_GOTO (MERROR_IM, err_label);
598 func = dlsym (handle, MSYMBOL_NAME (MPLIST_SYMBOL (plist)));
600 MERROR_GOTO (MERROR_IM, err_label);
601 mplist_add (func_list, MPLIST_SYMBOL (plist), func);
604 MSTRUCT_MALLOC (external, MERROR_IM);
605 external->handle = handle;
606 external->func_list = func_list;
607 mplist_add (externals, module, external);
612 M17N_OBJECT_UNREF (func_list);
617 /** Load a state from PLIST into a newly allocated state object.
619 PLIST ::= ( STATE-NAME STATE-TITLE ? BRANCH * )
620 BRANCH ::= ( MAP-NAME BRANCH-ACTION * )
621 MAPS is a plist of defined maps.
622 Return the state object. */
625 load_state (MPlist *plist, MPlist *maps, MSymbol language, MPlist *macros)
629 MSTRUCT_CALLOC (state, MERROR_IM);
630 if (! MPLIST_SYMBOL_P (plist))
631 MERROR (MERROR_IM, NULL);
632 state->name = MPLIST_SYMBOL (plist);
633 plist = MPLIST_NEXT (plist);
634 if (MPLIST_MTEXT_P (plist))
636 state->title = MPLIST_MTEXT (plist);
637 mtext_put_prop (state->title, 0, mtext_nchars (state->title),
638 Mlanguage, language);
639 M17N_OBJECT_REF (state->title);
640 plist = MPLIST_NEXT (plist);
642 MSTRUCT_CALLOC (state->map, MERROR_IM);
643 MPLIST_DO (plist, plist)
644 if (! MPLIST_PLIST_P (plist)
645 || load_branch (MPLIST_PLIST (plist), maps, state->map, macros) < 0)
646 MERROR (MERROR_IM, NULL);
652 free_map (MIMMap *map)
656 M17N_OBJECT_UNREF (map->map_actions);
659 MPLIST_DO (plist, map->submaps)
660 free_map ((MIMMap *) MPLIST_VAL (plist));
661 M17N_OBJECT_UNREF (map->submaps);
663 M17N_OBJECT_UNREF (map->branch_actions);
667 /* Load an input method from PLIST into IM_INTO, and return it. */
670 load_input_method (MSymbol language, MSymbol name, MPlist *plist,
671 MInputMethodInfo *im_info)
675 MPlist *states = NULL;
676 MPlist *externals = NULL;
677 MPlist *macros = NULL;
680 if (! MPLIST_PLIST_P (plist))
681 MERROR (MERROR_IM, -1);
682 for (; MPLIST_PLIST_P (plist); plist = MPLIST_NEXT (plist))
684 elt = MPLIST_PLIST (plist);
685 if (! MPLIST_SYMBOL_P (elt))
686 MERROR_GOTO (MERROR_IM, err);
687 if (MPLIST_SYMBOL (elt) == Mtitle)
689 elt = MPLIST_NEXT (elt);
690 if (MPLIST_MTEXT_P (elt))
692 title = MPLIST_MTEXT (elt);
693 M17N_OBJECT_REF (title);
696 MERROR_GOTO (MERROR_IM, err);
698 else if (MPLIST_SYMBOL (elt) == Mmap)
700 maps = mplist__from_alist (MPLIST_NEXT (elt));
702 MERROR_GOTO (MERROR_IM, err);
704 else if (MPLIST_SYMBOL (elt) == Mmacro)
707 MPLIST_DO (elt, MPLIST_NEXT (elt))
709 if (! MPLIST_PLIST_P (elt)
710 || load_macros (MPLIST_PLIST (elt), macros) < 0)
711 MERROR_GOTO (MERROR_IM, err);
714 else if (MPLIST_SYMBOL (elt) == Mmodule)
716 externals = mplist ();
717 MPLIST_DO (elt, MPLIST_NEXT (elt))
719 if (! MPLIST_PLIST_P (elt)
720 || load_external_module (MPLIST_PLIST (elt), externals) < 0)
721 MERROR_GOTO (MERROR_IM, err);
724 else if (MPLIST_SYMBOL (elt) == Mstate)
727 MPLIST_DO (elt, MPLIST_NEXT (elt))
731 if (! MPLIST_PLIST_P (elt))
732 MERROR_GOTO (MERROR_IM, err);
733 state = load_state (MPLIST_PLIST (elt), maps, language, macros);
735 MERROR_GOTO (MERROR_IM, err);
736 mplist_put (states, state->name, state);
741 MPLIST_DO (elt, maps)
742 M17N_OBJECT_UNREF (MPLIST_VAL (elt));
743 M17N_OBJECT_UNREF (maps);
745 title = mtext_from_data (MSYMBOL_NAME (name), MSYMBOL_NAMELEN (name),
746 MTEXT_FORMAT_US_ASCII);
747 im_info->title = title;
748 im_info->externals = externals;
749 im_info->macros = macros;
750 im_info->states = states;
756 MPLIST_DO (elt, maps)
757 M17N_OBJECT_UNREF (MPLIST_VAL (elt));
758 M17N_OBJECT_UNREF (maps);
761 M17N_OBJECT_UNREF (title);
764 MPLIST_DO (plist, states)
766 MIMState *state = (MIMState *) MPLIST_VAL (plist);
769 M17N_OBJECT_UNREF (state->title);
771 free_map (state->map);
774 M17N_OBJECT_UNREF (states);
778 MPLIST_DO (plist, externals)
780 MIMExternalModule *external = MPLIST_VAL (plist);
782 dlclose (external->handle);
783 M17N_OBJECT_UNREF (external->func_list);
785 MPLIST_KEY (plist) = Mt;
787 M17N_OBJECT_UNREF (externals);
794 static int take_action_list (MInputContext *ic, MPlist *action_list);
797 shift_state (MInputContext *ic, MSymbol state_name)
799 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
800 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
801 MIMState *state = ic_info->state;
803 /* Find a state to shift to. If not found, shift to the initial
805 state = (MIMState *) mplist_get (im_info->states, state_name);
807 state = (MIMState *) MPLIST_VAL (im_info->states);
809 /* Enter the new state. */
810 ic_info->state = state;
811 ic_info->map = state->map;
812 ic_info->state_key_head = ic_info->key_head;
813 if (state == (MIMState *) MPLIST_VAL (im_info->states))
815 /* We have shifted to the initial state. */
818 mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit),
819 Mcandidate_list, NULL, 0);
820 mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit),
821 Mcandidate_index, NULL, 0);
822 mtext_cat (ic->produced, ic->preedit);
823 mtext_reset (ic->preedit);
824 ic->candidate_list = NULL;
825 ic->candidate_show = 0;
826 ic->preedit_changed = ic->candidates_changed = 1;
827 MPLIST_DO (p, ic_info->markers)
829 MPLIST_DO (p, ic_info->vars)
832 memmove (ic_info->keys, ic_info->keys + ic_info->state_key_head,
833 sizeof (int) * (ic_info->used - ic_info->state_key_head));
834 ic_info->used -= ic_info->state_key_head;
835 ic_info->state_key_head = ic_info->key_head = 0;
837 mtext_cpy (ic_info->preedit_saved, ic->preedit);
838 ic_info->state_pos = ic->cursor_pos;
839 ic->status = state->title;
841 ic->status = im_info->title;
842 ic->status_changed = 1;
843 if (ic_info->key_head == ic_info->used
844 && ic_info->map == ic_info->state->map
845 && ic_info->map->map_actions)
846 take_action_list (ic, ic_info->map->map_actions);
851 find_candidates_group (MPlist *plist, int index,
852 int *start_index, int *end_index, int *group_index)
854 int i = 0, gidx = 0, len;
856 MPLIST_DO (plist, plist)
858 if (MPLIST_MTEXT_P (plist))
859 len = mtext_nchars (MPLIST_MTEXT (plist));
861 len = mplist_length (MPLIST_PLIST (plist));
867 *end_index = i + len;
879 preedit_insert (MInputContext *ic, int pos, MText *mt, int c)
881 MInputContextInfo *ic_info = ((MInputContext *) ic)->info;
883 int nchars = mt ? mtext_nchars (mt) : 1;
886 mtext_ins (ic->preedit, pos, mt);
888 mtext_ins_char (ic->preedit, pos, c, 1);
889 MPLIST_DO (markers, ic_info->markers)
890 if (MPLIST_INTEGER (markers) > pos)
891 MPLIST_VAL (markers) = (void *) (MPLIST_INTEGER (markers) + nchars);
892 if (ic->cursor_pos >= pos)
893 ic->cursor_pos += nchars;
894 ic->preedit_changed = 1;
899 preedit_delete (MInputContext *ic, int from, int to)
901 MInputContextInfo *ic_info = ((MInputContext *) ic)->info;
904 mtext_del (ic->preedit, from, to);
905 MPLIST_DO (markers, ic_info->markers)
907 if (MPLIST_INTEGER (markers) > to)
909 = (void *) (MPLIST_INTEGER (markers) - (to - from));
910 else if (MPLIST_INTEGER (markers) > from);
911 MPLIST_VAL (markers) = (void *) from;
913 if (ic->cursor_pos >= to)
914 ic->cursor_pos -= to - from;
915 else if (ic->cursor_pos > from)
916 ic->cursor_pos = from;
917 ic->preedit_changed = 1;
922 new_index (MInputContext *ic, int current, int limit, MSymbol sym, MText *mt)
924 int code = marker_code (sym);
926 if (mt && (code == '[' || code == ']'))
930 if (code == '[' && current > 0)
932 if (mtext_prop_range (mt, Mcandidate_list, pos - 1, &pos, NULL, 1)
936 else if (code == ']' && current < mtext_nchars (mt))
938 if (mtext_prop_range (mt, Mcandidate_list, pos, NULL, &pos, 1))
944 return (code == '<' ? 0
945 : code == '>' ? limit
946 : code == '-' ? current - 1
947 : code == '+' ? current + 1
948 : code == '=' ? current
949 : code - '0' > limit ? limit
953 return (int) mplist_get (((MInputContextInfo *) ic->info)->markers, sym);
957 udpate_candidate (MInputContext *ic, MTextProperty *prop, int idx)
959 int from = mtext_property_start (prop);
960 int to = mtext_property_end (prop);
962 MPlist *candidate_list = mtext_property_value (prop);
963 MPlist *group = find_candidates_group (candidate_list, idx, &start,
965 int ingroup_index = idx - start;
968 preedit_delete (ic, from, to);
969 if (MPLIST_MTEXT_P (group))
971 mt = MPLIST_MTEXT (group);
972 preedit_insert (ic, from, NULL, mtext_ref_char (mt, ingroup_index));
980 for (i = 0, plist = MPLIST_PLIST (group); i < ingroup_index;
981 i++, plist = MPLIST_NEXT (plist));
982 mt = MPLIST_MTEXT (plist);
983 preedit_insert (ic, from, mt, 0);
984 to = from + mtext_nchars (mt);
986 mtext_put_prop (ic->preedit, from, to, Mcandidate_list, candidate_list);
987 mtext_put_prop (ic->preedit, from, to, Mcandidate_index, (void *) idx);
993 take_action_list (MInputContext *ic, MPlist *action_list)
995 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
996 MPlist *candidate_list = ic->candidate_list;
997 int candidate_index = ic->candidate_index;
998 int candidate_show = ic->candidate_show;
1001 MPLIST_DO (action_list, action_list)
1007 if (MPLIST_MTEXT_P (action_list)
1008 || MPLIST_INTEGER_P (action_list))
1009 name = Minsert, args = action_list;
1010 else if (MPLIST_PLIST_P (action_list)
1011 && (MPLIST_MTEXT_P (MPLIST_PLIST (action_list))
1012 || MPLIST_PLIST_P (MPLIST_PLIST (action_list))))
1013 name = Minsert, args = action_list;
1016 action = MPLIST_PLIST (action_list);
1017 name = MPLIST_SYMBOL (action);
1018 args = MPLIST_NEXT (action);
1021 if (name == Minsert)
1023 if (MPLIST_MTEXT_P (args))
1024 preedit_insert (ic, ic->cursor_pos, MPLIST_MTEXT (args), 0);
1025 else if (MPLIST_INTEGER_P (args))
1026 preedit_insert (ic, ic->cursor_pos, NULL, MPLIST_INTEGER (args));
1027 else if (MPLIST_SYMBOL_P (args))
1029 int c = integer_value (ic, args);
1031 if (c >= 0 && c <= MCHAR_MAX)
1032 preedit_insert (ic, ic->cursor_pos, NULL, c);
1039 args = MPLIST_PLIST (args);
1040 if (MPLIST_MTEXT_P (args))
1042 preedit_insert (ic, ic->cursor_pos, NULL,
1043 mtext_ref_char (MPLIST_MTEXT (args), 0));
1048 mt = MPLIST_MTEXT (MPLIST_PLIST (args));
1049 preedit_insert (ic, ic->cursor_pos, mt, 0);
1050 len = mtext_nchars (mt);
1052 mtext_put_prop (ic->preedit,
1053 ic->cursor_pos - len, ic->cursor_pos,
1054 Mcandidate_list, args);
1055 mtext_put_prop (ic->preedit,
1056 ic->cursor_pos - len, ic->cursor_pos,
1057 Mcandidate_index, (void *) 0);
1060 else if (name == Mselect)
1063 int code, idx, gindex;
1064 int pos = ic->cursor_pos;
1068 || ! (prop = mtext_get_property (ic->preedit, pos - 1,
1071 if (MPLIST_SYMBOL_P (args))
1073 code = marker_code (MPLIST_SYMBOL (args));
1079 idx = (int) mtext_get_prop (ic->preedit, pos - 1, Mcandidate_index);
1080 group = find_candidates_group (mtext_property_value (prop), idx,
1081 &start, &end, &gindex);
1083 if (code != '[' && code != ']')
1087 ? new_index (NULL, ic->candidate_index - start,
1088 end - start - 1, MPLIST_SYMBOL (args),
1090 : MPLIST_INTEGER (args)));
1093 && MPLIST_TAIL_P (MPLIST_NEXT (group))))
1098 int ingroup_index = idx - start;
1101 group = mtext_property_value (prop);
1102 len = mplist_length (group);
1115 for (idx = 0; gindex > 0; gindex--, group = MPLIST_NEXT (group))
1116 idx += (MPLIST_MTEXT_P (group)
1117 ? mtext_nchars (MPLIST_MTEXT (group))
1118 : mplist_length (MPLIST_PLIST (group)));
1119 len = (MPLIST_MTEXT_P (group)
1120 ? mtext_nchars (MPLIST_MTEXT (group))
1121 : mplist_length (MPLIST_PLIST (group)));
1122 if (ingroup_index >= len)
1123 ingroup_index = len - 1;
1124 idx += ingroup_index;
1126 udpate_candidate (ic, prop, idx);
1128 else if (name == Mshow)
1129 ic->candidate_show = 1;
1130 else if (name == Mhide)
1131 ic->candidate_show = 0;
1132 else if (name == Mdelete)
1134 int len = mtext_nchars (ic->preedit);
1135 int to = (MPLIST_SYMBOL_P (args)
1136 ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
1138 : MPLIST_INTEGER (args));
1144 if (to < ic->cursor_pos)
1145 preedit_delete (ic, to, ic->cursor_pos);
1146 else if (to > ic->cursor_pos)
1147 preedit_delete (ic, ic->cursor_pos, to);
1149 else if (name == Mmove)
1151 int len = mtext_nchars (ic->preedit);
1153 = (MPLIST_SYMBOL_P (args)
1154 ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
1156 : MPLIST_INTEGER (args));
1162 if (pos != ic->cursor_pos)
1164 ic->cursor_pos = pos;
1165 ic->preedit_changed = 1;
1168 else if (name == Mmark)
1170 int code = marker_code (MPLIST_SYMBOL (args));
1173 mplist_put (ic_info->markers, MPLIST_SYMBOL (args),
1174 (void *) ic->cursor_pos);
1176 else if (name == Mpushback)
1178 int num = MPLIST_INTEGER (args);
1181 ic_info->key_head -= num;
1183 ic_info->key_head = num;
1184 if (ic_info->key_head > ic_info->used)
1185 ic_info->key_head = ic_info->used;
1187 else if (name == Mcall)
1189 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1190 MIMExternalFunc func = NULL;
1191 MSymbol module, func_name;
1192 MPlist *func_args, *val;
1195 module = MPLIST_SYMBOL (args);
1196 args = MPLIST_NEXT (args);
1197 func_name = MPLIST_SYMBOL (args);
1199 if (im_info->externals)
1201 MIMExternalModule *external
1202 = (MIMExternalModule *) mplist_get (im_info->externals,
1205 func = (MIMExternalFunc) mplist_get (external->func_list,
1210 func_args = mplist ();
1211 mplist_add (func_args, Mt, ic);
1212 MPLIST_DO (args, MPLIST_NEXT (args))
1216 if (MPLIST_KEY (args) == Msymbol
1217 && MPLIST_KEY (args) != Mnil
1218 && (code = marker_code (MPLIST_SYMBOL (args))) >= 0)
1220 code = new_index (ic, ic->cursor_pos,
1221 mtext_nchars (ic->preedit),
1222 MPLIST_SYMBOL (args), ic->preedit);
1223 mplist_add (func_args, Minteger, (void *) code);
1226 mplist_add (func_args, MPLIST_KEY (args), MPLIST_VAL (args));
1228 val = (func) (func_args);
1229 M17N_OBJECT_UNREF (func_args);
1230 if (val && ! MPLIST_TAIL_P (val))
1231 ret = take_action_list (ic, val);
1232 M17N_OBJECT_UNREF (val);
1236 else if (name == Mshift)
1238 shift_state (ic, MPLIST_SYMBOL (args));
1240 else if (name == Mundo)
1242 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1245 mtext_reset (ic->preedit);
1246 mtext_reset (ic_info->preedit_saved);
1247 ic->cursor_pos = ic_info->state_pos = 0;
1248 ic_info->state_key_head = ic_info->key_head = 0;
1250 if (ic_info->used < 0)
1255 shift_state (ic, ((MIMState *) MPLIST_VAL (im_info->states))->name);
1260 else if (name == Mset || name == Madd || name == Msub
1261 || name == Mmul || name == Mdiv)
1263 MSymbol sym = MPLIST_SYMBOL (args);
1264 int val1 = (int) mplist_get (ic_info->vars, sym), val2;
1266 args = MPLIST_NEXT (args);
1267 val2 = integer_value (ic, args);
1270 else if (name == Madd)
1272 else if (name == Msub)
1274 else if (name == Mmul)
1278 mplist_put (ic_info->vars, sym, (void *) val1);
1280 else if (name == Mequal || name == Mless || name == Mgreater)
1283 MPlist *actions1, *actions2;
1286 val1 = integer_value (ic, args);
1287 args = MPLIST_NEXT (args);
1288 val2 = integer_value (ic, args);
1289 args = MPLIST_NEXT (args);
1290 actions1 = MPLIST_PLIST (args);
1291 args = MPLIST_NEXT (args);
1292 if (MPLIST_TAIL_P (args))
1295 actions2 = MPLIST_PLIST (args);
1296 if (name == Mequal ? val1 == val2
1297 : name == Mless ? val1 < val2
1299 ret = take_action_list (ic, actions1);
1301 ret = take_action_list (ic, actions2);
1307 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1311 && (actions = mplist_get (im_info->macros, name)))
1313 if (take_action_list (ic, actions) < 0)
1320 ic->candidate_list = NULL;
1321 if (ic->cursor_pos > 0
1322 && (prop = mtext_get_property (ic->preedit, ic->cursor_pos - 1,
1325 ic->candidate_list = mtext_property_value (prop);
1327 = (int) mtext_get_prop (ic->preedit, ic->cursor_pos - 1,
1329 ic->candidate_from = mtext_property_start (prop);
1330 ic->candidate_to = mtext_property_end (prop);
1333 ic->candidates_changed |= (candidate_list != ic->candidate_list
1334 || candidate_index != ic->candidate_index
1335 || candidate_show != ic->candidate_show);
1340 /* Handle the input key KEY in the current state and map specified in
1341 the input context IC. If KEY is handled correctly, return 0.
1342 Otherwise, return -1. */
1345 handle_key (MInputContext *ic)
1347 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1348 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1349 MIMMap *map = ic_info->map;
1350 MIMMap *submap = NULL;
1351 MSymbol key = ic_info->keys[ic_info->key_head];
1356 submap = mplist_get (map->submaps, key);
1357 if (! submap && (key = msymbol_get (key, M_key_alias)) != Mnil)
1358 submap = mplist_get (map->submaps, key);
1363 mtext_cpy (ic->preedit, ic_info->preedit_saved);
1364 ic->cursor_pos = ic_info->state_pos;
1365 ic_info->key_head++;
1366 ic_info->map = map = submap;
1367 if (map->map_actions)
1369 if (take_action_list (ic, map->map_actions) < 0)
1372 else if (map->submaps)
1374 for (i = ic_info->state_key_head; i < ic_info->key_head; i++)
1376 MSymbol key = ic_info->keys[i];
1377 char *name = msymbol_name (key);
1379 if (! name[0] || ! name[1])
1380 mtext_ins_char (ic->preedit, ic->cursor_pos++, name[0], 1);
1382 ic->preedit_changed = 1;
1385 /* If this is the terminal map or we have shifted to another
1386 state, perform branch actions (if any). */
1387 if (! map->submaps || map != ic_info->map)
1389 if (map->branch_actions)
1391 if (take_action_list (ic, map->branch_actions) < 0)
1394 /* If MAP is still not the root map, shift to the current
1396 if (ic_info->map != ic_info->state->map)
1397 shift_state (ic, ic_info->state->name);
1402 /* MAP can not handle KEY. */
1404 /* If MAP is the root map of the initial state, it means that
1405 the current input method can not handle KEY. */
1406 if (map == ((MIMState *) MPLIST_VAL (im_info->states))->map)
1409 if (map != ic_info->state->map)
1411 /* If MAP is not the root map... */
1412 /* If MAP has branch actions, perform them. */
1413 if (map->branch_actions)
1414 take_action_list (ic, map->branch_actions);
1415 /* If MAP is still not the root map, shift to the current
1417 if (ic_info->map != ic_info->state->map)
1419 shift_state (ic, ic_info->state->name);
1420 /* If MAP has branch_actions, perform them. */
1421 if (ic_info->map->branch_actions)
1422 take_action_list (ic, ic_info->map->branch_actions);
1427 /* MAP is the root map, perform branch actions (if any) or
1428 shift to the initial state. */
1429 if (map->branch_actions)
1430 take_action_list (ic, map->branch_actions);
1433 ((MIMState *) MPLIST_VAL (im_info->states))->name);
1440 reset_ic (MInputContext *ic)
1442 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1443 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1445 MLIST_RESET (ic_info);
1446 ic_info->state = (MIMState *) MPLIST_VAL (im_info->states);
1447 ic_info->map = ic_info->state->map;
1448 ic_info->state_key_head = ic_info->key_head = 0;
1449 ic->cursor_pos = ic_info->state_pos = 0;
1450 ic->status = ic_info->state->title;
1452 ic->status = im_info->title;
1453 ic->candidate_list = NULL;
1454 ic->candidate_show = 0;
1455 ic->status_changed = ic->preedit_changed = ic->candidates_changed = 1;
1456 if (ic_info->map->map_actions)
1457 take_action_list (ic, ic_info->map->map_actions);
1461 open_im (MInputMethod *im)
1464 MInputMethodInfo *im_info;
1468 mdb = mdatabase_find (Minput_method, im->language, im->name, Mnil);
1471 plist = mdatabase_load (mdb);
1473 MERROR (MERROR_IM, -1);
1474 MSTRUCT_CALLOC (im_info, MERROR_IM);
1476 result = load_input_method (im->language, im->name, plist, im_info);
1477 M17N_OBJECT_UNREF (plist);
1479 MERROR (MERROR_IM, -1);
1484 close_im (MInputMethod *im)
1486 MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
1490 M17N_OBJECT_UNREF (im_info->title);
1491 if (im_info->states)
1493 MPLIST_DO (plist, im_info->states)
1495 MIMState *state = (MIMState *) MPLIST_VAL (plist);
1498 M17N_OBJECT_UNREF (state->title);
1500 free_map (state->map);
1503 M17N_OBJECT_UNREF (im_info->states);
1506 if (im_info->macros)
1508 MPLIST_DO (plist, im_info->macros)
1509 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
1510 M17N_OBJECT_UNREF (im_info->macros);
1513 if (im_info->externals)
1515 MPLIST_DO (plist, im_info->externals)
1517 MIMExternalModule *external = MPLIST_VAL (plist);
1519 dlclose (external->handle);
1520 M17N_OBJECT_UNREF (external->func_list);
1522 MPLIST_KEY (plist) = Mt;
1524 M17N_OBJECT_UNREF (im_info->externals);
1532 create_ic (MInputContext *ic)
1534 MInputMethod *im = ic->im;
1535 MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
1536 MInputContextInfo *ic_info;
1539 ic_info = (MInputContextInfo *) ic->info;
1542 MSTRUCT_CALLOC (ic_info, MERROR_IM);
1545 MLIST_INIT1 (ic_info, keys, 8);
1546 ic_info->markers = mplist ();
1547 ic_info->vars = mplist ();
1548 ic_info->preedit_saved = mtext ();
1549 if (im_info->externals)
1551 MPlist *func_args = mplist (), *plist;
1553 mplist_add (func_args, Mt, ic);
1554 MPLIST_DO (plist, im_info->externals)
1556 MIMExternalModule *external = MPLIST_VAL (plist);
1557 MIMExternalFunc func
1558 = (MIMExternalFunc) mplist_get (external->func_list, Minit);
1563 M17N_OBJECT_UNREF (func_args);
1570 destroy_ic (MInputContext *ic)
1572 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1573 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1575 if (im_info->externals)
1577 MPlist *func_args = mplist (), *plist;
1579 mplist_add (func_args, Mt, ic);
1580 MPLIST_DO (plist, im_info->externals)
1582 MIMExternalModule *external = MPLIST_VAL (plist);
1583 MIMExternalFunc func
1584 = (MIMExternalFunc) mplist_get (external->func_list, Mfini);
1589 M17N_OBJECT_UNREF (func_args);
1591 MLIST_FREE1 (ic_info, keys);
1592 M17N_OBJECT_UNREF (ic_info->preedit_saved);
1593 M17N_OBJECT_UNREF (ic_info->markers);
1594 M17N_OBJECT_UNREF (ic_info->vars);
1599 /** Handle the input key KEY in the current state and map of IC->info.
1600 If KEY is handled but no text is produced, return 0, otherwise
1606 filter (MInputContext *ic, MSymbol key, void *arg)
1608 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1609 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1612 mtext_reset (ic->produced);
1613 ic->status_changed = ic->preedit_changed = ic->candidates_changed = 0;
1614 MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
1615 ic_info->key_unhandled = 0;
1617 if (handle_key (ic) < 0)
1619 /* KEY was not handled. Reset the status and break the
1622 /* This forces returning 1. */
1623 ic_info->key_unhandled = 1;
1630 ic_info->key_unhandled = 1;
1633 /* Break the loop if all keys were handled. */
1634 } while (ic_info->key_head < ic_info->used);
1636 /* If the current map is the root of the initial state, we should
1637 produce any preedit text in ic->produced. */
1638 if (ic_info->map == ((MIMState *) MPLIST_VAL (im_info->states))->map
1639 && mtext_nchars (ic->preedit) > 0)
1640 shift_state (ic, ((MIMState *) MPLIST_VAL (im_info->states))->name);
1642 if (mtext_nchars (ic->produced) > 0)
1644 MSymbol lang = msymbol_get (ic->im->language, Mlanguage);
1647 mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
1648 Mlanguage, ic->im->language);
1651 return (! ic_info->key_unhandled && mtext_nchars (ic->produced) == 0);
1655 /** Return 1 if the last event or key was not handled, otherwise
1658 There is no need of looking up because ic->produced should already
1659 contain the produced text (if any).
1664 lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
1666 mtext_cat (mt, ic->produced);
1667 mtext_reset (ic->produced);
1668 return (((MInputContextInfo *) ic->info)->key_unhandled ? -1 : 0);
1671 /* Support functions for mdebug_dump_im. */
1674 dump_im_map (MPlist *map_list, int indent)
1677 MSymbol key = MPLIST_KEY (map_list);
1678 MIMMap *map = (MIMMap *) MPLIST_VAL (map_list);
1680 prefix = (char *) alloca (indent + 1);
1681 memset (prefix, 32, indent);
1682 prefix[indent] = '\0';
1684 fprintf (stderr, "(\"%s\" ", msymbol_name (key));
1685 if (map->map_actions)
1686 mdebug_dump_plist (map->map_actions, indent + 2);
1689 MPLIST_DO (map_list, map->submaps)
1691 fprintf (stderr, "\n%s ", prefix);
1692 dump_im_map (map_list, indent + 2);
1695 if (map->branch_actions)
1697 fprintf (stderr, "\n%s (branch\n%s ", prefix, prefix);
1698 mdebug_dump_plist (map->branch_actions, indent + 4);
1699 fprintf (stderr, ")");
1701 fprintf (stderr, ")");
1706 dump_im_state (MIMState *state, int indent)
1711 prefix = (char *) alloca (indent + 1);
1712 memset (prefix, 32, indent);
1713 prefix[indent] = '\0';
1715 fprintf (stderr, "(%s", msymbol_name (state->name));
1716 if (state->map->submaps)
1718 MPLIST_DO (map_list, state->map->submaps)
1720 fprintf (stderr, "\n%s ", prefix);
1721 dump_im_map (map_list, indent + 2);
1724 fprintf (stderr, ")");
1733 = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1734 "BackSpace", "Tab", "Linefeed", "Clear", NULL, "Return", NULL, NULL,
1735 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1736 NULL, NULL, NULL, "Escape", NULL, NULL, NULL, NULL };
1737 char buf[6], buf2[256];
1740 Minput_method = msymbol ("input-method");
1741 Minput_driver = msymbol ("input-driver");
1742 Mtitle = msymbol ("title");
1743 Mmacro = msymbol ("macro");
1744 Mmodule = msymbol ("module");
1745 Mmap = msymbol ("map");
1746 Mstate = msymbol ("state");
1747 Minsert = msymbol ("insert");
1748 Mdelete = msymbol ("delete");
1749 Mmove = msymbol ("move");
1750 Mmark = msymbol ("mark");
1751 Mpushback = msymbol ("pushback");
1752 Mundo = msymbol ("undo");
1753 Mcall = msymbol ("call");
1754 Mshift = msymbol ("shift");
1755 Mselect = msymbol ("select");
1756 Mshow = msymbol ("show");
1757 Mhide = msymbol ("hide");
1758 Mset = msymbol ("set");
1759 Madd = msymbol ("add");
1760 Msub = msymbol ("sub");
1761 Mmul = msymbol ("mul");
1762 Mdiv = msymbol ("div");
1763 Mequal = msymbol ("=");
1764 Mless = msymbol ("<");
1765 Mgreater = msymbol (">");
1767 Minput_preedit_start = msymbol ("input-preedit-start");
1768 Minput_preedit_done = msymbol ("input-preedit-done");
1769 Minput_preedit_draw = msymbol ("input-preedit-draw");
1770 Minput_status_start = msymbol ("input-status-start");
1771 Minput_status_done = msymbol ("input-status-done");
1772 Minput_status_draw = msymbol ("input-status-draw");
1773 Minput_candidates_start = msymbol ("input-candidates-start");
1774 Minput_candidates_done = msymbol ("input-candidates-done");
1775 Minput_candidates_draw = msymbol ("input-candidates-draw");
1776 Minput_set_spot = msymbol ("input-set-spot");
1777 Minput_toggle = msymbol ("input-toggle");
1779 Mcandidate_list = msymbol_as_managing_key (" candidate-list");
1780 Mcandidate_index = msymbol (" candidate-index");
1782 Minit = msymbol ("init");
1783 Mfini = msymbol ("fini");
1785 M_key_alias = msymbol (" key-alias");
1790 for (i = 0, buf[2] = '@'; i < ' '; i++, buf[2]++)
1792 one_char_symbol[i] = msymbol (buf);
1794 msymbol_put (one_char_symbol[i], M_key_alias, msymbol (key_names[i]));
1796 for (buf[2] = i; i < 127; i++, buf[2]++)
1797 one_char_symbol[i] = msymbol (buf + 2);
1798 one_char_symbol[i++] = msymbol ("Delete");
1804 for (buf[4] = '@'; i < 160; i++, buf[4]++)
1806 one_char_symbol[i] = msymbol (buf);
1807 if (key_names[i - 128])
1809 strcpy (buf2 + 2, key_names[i - 128]);
1810 msymbol_put (one_char_symbol[i], M_key_alias, msymbol (buf2));
1813 for (buf[4] = i - 128; i < 255; i++, buf[4]++)
1814 one_char_symbol[i] = msymbol (buf + 2);
1815 one_char_symbol[i] = msymbol ("M-Delete");
1817 minput_default_driver.open_im = open_im;
1818 minput_default_driver.close_im = close_im;
1819 minput_default_driver.create_ic = create_ic;
1820 minput_default_driver.destroy_ic = destroy_ic;
1821 minput_default_driver.filter = filter;
1822 minput_default_driver.lookup = lookup;
1823 minput_default_driver.callback_list = NULL;
1824 minput_driver = &minput_default_driver;
1831 if (minput_default_driver.callback_list)
1833 M17N_OBJECT_UNREF (minput_default_driver.callback_list);
1834 minput_default_driver.callback_list = NULL;
1836 if (minput_driver->callback_list)
1838 M17N_OBJECT_UNREF (minput_driver->callback_list);
1839 minput_driver->callback_list = NULL;
1844 minput__callback (MInputContext *ic, MSymbol command)
1846 if (ic->im->driver.callback_list)
1848 MInputCallbackFunc func
1849 = (MInputCallbackFunc) mplist_get (ic->im->driver.callback_list,
1853 (func) (ic, command);
1858 minput__char_to_key (int c)
1860 if (c < 0 || c >= 0x100)
1863 return one_char_symbol[c];
1867 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1872 /*** @addtogroup m17nInputMethod */
1877 @name Variables: Predefined symbols for callback commands.
1879 These are the predefined symbols that are used as the @c COMMAND
1880 argument of callback functions of an input method driver (see
1881 #MInputDriver::callback_list). */
1885 MSymbol Minput_preedit_start;
1886 MSymbol Minput_preedit_done;
1887 MSymbol Minput_preedit_draw;
1888 MSymbol Minput_status_start;
1889 MSymbol Minput_status_done;
1890 MSymbol Minput_status_draw;
1891 MSymbol Minput_candidates_start;
1892 MSymbol Minput_candidates_done;
1893 MSymbol Minput_candidates_draw;
1894 MSymbol Minput_set_spot;
1895 MSymbol Minput_toggle;
1900 @brief The default input driver for internal input methods.
1902 The variable #minput_default_driver is the default driver for
1903 internal input methods.
1905 The member MInputDriver::open_im () searches the m17n database for
1906 an input method that matches the tag \<#Minput_method, $LANGUAGE,
1907 $NAME\> and loads it.
1909 The member MInputDriver::callback_list () is @c NULL. Thus, it is
1910 programmers responsibility to set it to a plist of proper callback
1911 functions. Otherwise, no feedback information (e.g. preedit text)
1912 can be shown to users.
1914 The macro M17N_INIT () sets the variable #minput_driver to the
1915 pointer to this driver so that all internal input methods use it.
1917 Therefore, unless @c minput_driver is set differently, the driver
1918 dependent arguments $ARG of the functions whose name begin with
1919 "minput_" are all ignored. */
1922 @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥǥե©¥ë¥ÈÆþÎϥɥ饤¥Ð
1924 ÆþÎϥɥ饤¥Ð minput_default_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѤΥǥե©¥ë
1925 ¥È¤ÎÆþÎϥɥ饤¥Ð¤Ç¤¢¤ë¡£
1927 ¤³¤Î¥É¥é¥¤¥Ð¤Î <callback> ¥á¥ó¥Ð¤Ï @c NULL ¤Ê¤Î¤Ç¡¢¥×¥í¥°¥é¥Þ¦¤Ç
1928 ÀÕǤ¤ò»ý¤Ã¤Æ, ŬÀڤʥ³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ËÀßÄꤷ¡¢Preedit ¥Æ¥¥¹¥È,
1929 Status ¥Æ¥¥¹¥È¤¬¥æ¡¼¥¶¤Ëɽ¼¨¤Ç¤¤ë¤è¤¦¤Ë¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
1931 ´Ø¿ô M17N_INIT () ¤ÏÊÑ¿ô @c minput_driver ¤ò¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó
1932 ¥¿¤ËÀßÄꤷ¡¢Á´¤Æ¤ÎÆâÉôÆþÎϥ᥽¥Ã¥É¤¬¤³¤Î¥É¥é¥¤¥Ð¤ò»È¤¦¤è¤¦¤Ë¤¹¤ë¡£
1934 ¤·¤¿¤¬¤Ã¤Æ¡¢@c minput_driver ¤¬¥Ç¥Õ¥©¥ë¥ÈÃͤΤޤޤǤ¢¤ì¤Ð¡¢minput_
1935 ¤Ç»Ï¤Þ¤ë°Ê²¼¤Î´Ø¿ô·²¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô $ARG ¤Ï¤É¤ì¤â̵»ë¤µ¤ì
1938 MInputDriver minput_default_driver;
1942 @brief The input driver for internal input methods.
1944 The variable #minput_driver is a pointer to the input method
1945 driver that is used by internal input methods. The macro
1946 M17N_INIT () initializes it to a pointer to #minput_default_driver
1947 (if <m17n.h> is included) or to #minput_gui_driver (if
1948 <m17n-gui.h> is included). */
1950 MInputDriver *minput_driver;
1952 MSymbol Minput_driver;
1957 @brief Open an input method.
1959 The minput_open_im () function opens an input method that matches
1960 language $LANGUAGE and name $NAME, and returns a pointer to the
1961 input method object newly allocated.
1963 This function at first decides an input driver for the input
1966 If $LANGUAGE is not #Mnil, an input driver pointed by the variable
1967 #minput_driver is used.
1969 If $LANGUAGE is #Mnil and $NAME has #Minput_driver property, the
1970 input driver pointed to by the property value is used to open the
1971 input method. If $NAME has no such property, @c NULL is returned.
1973 Then, the member MInputDriver::open_im () of the input driver is
1976 $ARG is set in the member @c arg of the structure MInputMethod so
1977 that the input driver can refer to it. */
1980 @brief ÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë
1982 ´Ø¿ô mim_open () ¤Ï¸À¸ì $LANGUAGE ¤È̾Á° $NAME ¤ËŬ¹ç¤¹¤ëÆþÎϥ᥽¥Ã
1983 ¥É¤ò¥ª¡¼¥×¥ó¤·¡¢¤½¤Î¿·¤¿¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
1985 $LANGUAGE ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢m17n ¸À¸ì¾ðÊó¥Ù¡¼¥¹Ã椫¤é \<@c
1986 Minput_method, $LANGUAGE, $NAME \> ¤È¤¤¤¦¥¿¥°¤ËŬ¹ç¤¹¤ëÆþÎϥ᥽¥Ã
1987 ¥É¤òõ¤¹¡£¸«¤Ä¤«¤Ã¤¿¾ì¹ç¤Ï¡¢ÊÑ¿ô #minput_driver ¤Ç¥Ý¥¤¥ó¥È¤µ¤ì¤Æ
1988 ¤¤¤ëÆþÎϥɥ饤¥Ð¤òÍѤ¤¤Æ¤½¤ÎÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë¡£¸«¤Ä¤«¤é¤Ê
1989 ¤¤¾ì¹ç¤ä¥ª¡¼¥×¥ó¤Ç¤¤Ê¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï @c NULL ¤òÊÖ¤¹¡£
1991 ÊÑ¿ô #minput_driver ¤Ï¡¢#minput_default_driver ¤« @c
1992 minput_gui_driver ¤Î¤É¤Á¤é¤«¤ò¥Ý¥¤¥ó¥È¤·¤Æ¤¤¤ë¡£Á°¼Ô¤Ï CUI ÍѤǤ¢
1993 ¤ê¡¢´Ø¿ôm17n_initialize () ¤ò¸Æ¤Ö¤³¤È¤Ë¤è¤Ã¤Æ #minput_driver ¤¬
1994 #minput_default_driver ¤ò¥Ý¥¤¥ó¥È¤¹¤ë¤è¤¦¤Ë¤Ê¤ë¡£¸å¼Ô¤Ï GUI ÍѤÇ
1995 ¤¢¤ê¡¢´Ø¿ô m17n_initialize_win () ¤Ë¤è¤Ã¤Æ¥Ý¥¤¥ó¥È¤µ¤ì¤ë¡£¾ÜºÙ¤Ë¤Ä
1996 ¤¤¤Æ¤Ï¤³¤ì¤é¤ÎÊÑ¿ô¤Î¥É¥¥å¥á¥ó¥È¤ò»²¾È¤Î¤³¤È¡£
1998 $LANGUAGE ¤¬ #Mnil ¤Ç¤¢¤ê¡¢$NAME ¤¬ #Minput_driver ¤ò¥¡¼¤È¤¹
1999 ¤ë¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä¾ì¹ç¤Ë¤Ï¡¢¤½¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤǥݥ¤¥ó¥È¤µ¤ì¤Æ¤¤¤ë
2000 ÆþÎϥɥ饤¥Ð¤òÍѤ¤¤ÆÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë¡£$NAME ¤Ë¤½¤Î¤è¤¦¤Ê
2001 ¥×¥í¥Ñ¥Æ¥£¤¬Ìµ¤«¤Ã¤¿¾ì¹ç¤ä¥ª¡¼¥×¥ó¤Ç¤¤Ê¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï @c NULL ¤ò
2004 $ARG ¤Ï¡¢ÆþÎϥɥ饤¥Ð¤¬»²¾È¤Ç¤¤ë¤è¤¦¤Ë¡¢¹½Â¤ÂÎ MInputMethod ¤Î¥á
2005 ¥ó¥Ð @c arg ¤Ë¥»¥Ã¥È¤µ¤ì¤ë¡£
2007 @latexonly \IPAlabel{minput_open} @endlatexonly
2012 minput_open_im (MSymbol language, MSymbol name, void *arg)
2015 MInputDriver *driver;
2018 driver = minput_driver;
2021 driver = (MInputDriver *) msymbol_get (name, Minput_driver);
2023 MERROR (MERROR_IM, NULL);
2026 MSTRUCT_CALLOC (im, MERROR_IM);
2027 im->language = language;
2030 im->driver = *driver;
2031 if ((*im->driver.open_im) (im) < 0)
2042 @brief Close an input method.
2044 The minput_close_im () function closes the input method $IM, which
2045 must have been created by minput_open_im (). */
2048 @brief ÆþÎϥ᥽¥Ã¥É¤ò¥¯¥í¡¼¥º¤¹¤ë
2050 ´Ø¿ô minput_close_im () ¤Ï¡¢ÆþÎϥ᥽¥Ã¥É $IM ¤ò¥¯¥í¡¼¥º¤¹¤ë¡£¤³¤Î
2051 ÆþÎϥ᥽¥Ã¥É $IM ¤Ï minput_open_im () ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê¤±¤ì
2055 minput_close_im (MInputMethod *im)
2057 (*im->driver.close_im) (im);
2064 @brief Create an input context.
2066 The minput_create_ic () function creates an input context object
2067 associated with input method $IM, and calls callback functions
2068 corresponding to #Minput_preedit_start, #Minput_status_start, and
2069 #Minput_status_draw in this order.
2073 If an input context is successfully created, minput_create_ic ()
2074 returns a pointer to it. Otherwise it returns @c NULL. */
2077 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÀ¸À®¤¹¤ë
2079 ´Ø¿ô minput_create_ic () ¤ÏÆþÎϥ᥽¥Ã¥É $IM ¤ËÂбþ¤¹¤ëÆþÎÏ¥³¥ó¥Æ¥¯
2080 ¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤¹¤ë¡£
2083 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢minput_create_ic () ¤ÏÀ¸À®¤·¤¿ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È
2084 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¼ºÇÔ¤·¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£ */
2087 minput_create_ic (MInputMethod *im, void *arg)
2091 MSTRUCT_CALLOC (ic, MERROR_IM);
2094 ic->preedit = mtext ();
2095 ic->candidate_list = NULL;
2096 ic->produced = mtext ();
2097 ic->spot.x = ic->spot.y = 0;
2099 ic->plist = mplist ();
2100 if ((*im->driver.create_ic) (ic) < 0)
2102 M17N_OBJECT_UNREF (ic->preedit);
2103 M17N_OBJECT_UNREF (ic->produced);
2104 M17N_OBJECT_UNREF (ic->plist);
2109 if (im->driver.callback_list)
2111 minput__callback (ic, Minput_preedit_start);
2112 minput__callback (ic, Minput_status_start);
2113 minput__callback (ic, Minput_status_draw);
2122 @brief Destroy an input context.
2124 The minput_destroy_ic () function destroys the input context $IC,
2125 which must have been created by minput_create_ic (). It calls
2126 callback functions corresponding to #Minput_preedit_done,
2127 #Minput_status_done, and #Mcandidate_done in this order. */
2130 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÇ˲õ¤¹¤ë
2132 ´Ø¿ô minput_destroy_ic () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤òÇ˲õ¤¹¤ë¡£¤³
2133 ¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ï minput_create_ic () ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê
2137 minput_destroy_ic (MInputContext *ic)
2139 if (ic->im->driver.callback_list)
2141 minput__callback (ic, Minput_preedit_done);
2142 minput__callback (ic, Minput_status_done);
2143 minput__callback (ic, Minput_candidates_done);
2145 (*ic->im->driver.destroy_ic) (ic);
2146 M17N_OBJECT_UNREF (ic->preedit);
2147 M17N_OBJECT_UNREF (ic->produced);
2148 M17N_OBJECT_UNREF (ic->plist);
2155 @brief Filter an input key.
2157 The minput_filter () function filters input key $KEY according to
2158 input context $IC, and calls callback functions corresponding to
2159 #Minput_preedit_draw, #Minput_status_draw, and #Mcandidate_draw if
2160 the preedit text, the status, and the current candidate are
2161 changed respectively.
2164 If $KEY is filtered out, this function returns 1. In that case,
2165 the caller should discard the key. Otherwise, it returns 0, and
2166 the caller should handle the key, for instance, by calling the
2167 function minput_lookup () with the same $KEY. */
2170 @brief ÆþÎÏ¥¡¼¤Î¥Õ¥£¥ë¥¿¥ê¥ó¥°¤ò¤¹¤ë
2172 ´Ø¿ô minput_filter () ¤ÏÆþÎÏ¥¡¼ $KEY ¤òÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤Ë±þ
2173 ¤¸¤Æ¥Õ¥£¥ë¥¿¥ê¥ó¥°¤¹¤ë¡£
2175 ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤ÎÆþÎϥ᥽¥Ã¥É¤¬ÆþÎÏ¥¡¼¤ò¥Õ¥£¥ë¥¿¤¹¤ì¤Ð¡¢¤³
2176 ¤Î´Ø¿ô¤Ï 1 ¤òÊÖ¤¹¡£¤³¤Î¾ì¹ç¸Æ¤Ó½Ð¤·Â¦¤Ï¤³¤Î¥¡¼¤ò¼Î¤Æ¤ë¤Ù¤¤Ç¤¢¤ë¡£
2177 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0 ¤òÊÖ¤·¡¢¸Æ¤Ó½Ð¤·Â¦¤¬¡¢¤¿¤È¤¨¤ÐƱ¤¸ $KEY ¤Ç´Ø¿ô
2178 minput_lookup () ¤ò¸Æ¤Ö¤Ê¤É¤·¤Æ¡¢¤³¤Î¥¡¼¤ò½èÍý¤¹¤ë¡£
2180 @latexonly \IPAlabel{minput_filter} @endlatexonly
2184 minput_filter (MInputContext *ic, MSymbol key, void *arg)
2191 ret = (*ic->im->driver.filter) (ic, key, arg);
2193 if (ic->im->driver.callback_list)
2195 if (ic->preedit_changed)
2196 minput__callback (ic, Minput_preedit_draw);
2197 if (ic->status_changed)
2198 minput__callback (ic, Minput_status_draw);
2199 if (ic->candidates_changed)
2200 minput__callback (ic, Minput_candidates_draw);
2201 ic->preedit_changed = ic->status_changed = ic->candidates_changed = 0;
2210 @brief Lookup a text produced in the input context.
2212 The minput_lookup () function looks up a text in the input context
2213 $IC. $KEY must be the same one provided to the previous call of
2216 If a text was produced by the input method, it is concatenated
2219 This function calls #MInputDriver::lookup.
2222 If $KEY was correctly handled by the input method, this function
2223 returns 0. Otherwise, returns -1, even in that case, some text
2224 may be produced in $MT. */
2227 @brief ÆþÎϥ᥽¥Ã¥É¤¬ºî¤Ã¤¿¥Æ¥¥¹¥È¤Î³ÍÆÀ
2229 ´Ø¿ô minput_lookup () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC Ãæ¤Î¥Æ¥¥¹¥È¤ò³ÍÆÀ¤¹
2230 ¤ë¡£$KEY ¤Ï´Ø¿ôminput_filter () ¤Ø¤ÎľÁ°¤Î¸Æ¤Ó½Ð¤·¤ËÍѤ¤¤é¤ì¤¿¤â¤Î
2231 ¤ÈƱ¤¸¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2233 ¥Æ¥¥¹¥È¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆÀ¸À®¤µ¤ì¤Æ¤¤¤ì¤Ð¡¢$IC->produced ¤ËÊÝ
2236 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Î <tt>XLookupString ()</tt> ¡¢
2237 <tt>XmbLookupString ()</tt> ¡¢<tt>XwcLookupString ()</tt> ¤ËÂбþ¤¹
2241 $KEY ¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆŬÀڤ˽èÍý¤Ç¤¤Æ¤¤¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 0 ¤ò
2242 ÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤·¡¢¤³¤Î¾ì¹ç¤Ç¤â$IC->produced ¤Ë²¿¤é¤«
2243 ¤Î¥Æ¥¥¹¥È¤¬À¸À®¤µ¤ì¤Æ¤¤¤ë¤³¤È¤¬¤¢¤ë¡£
2245 @latexonly \IPAlabel{minput_lookup} @endlatexonly */
2248 minput_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2250 return (ic ? (*ic->im->driver.lookup) (ic, key, arg, mt) : -1);
2255 @brief Set the spot of the input context.
2257 The minput_set_spot () function set the spot of input context $IC
2258 to coordinate ($X, $Y) with the height $ASCENT and $DESCENT.
2259 $FONTSIZE specfies the fontsize of a preedit text in 1/10 point.
2260 The semantics of these values depend on the input driver.
2262 For instance, an input driver designed to work in CUI environment
2263 may use $X and $Y as column and row numbers, and ignore $ASCENT
2264 and $DESCENT. An input driver designed to work on a window system
2265 may treat $X and $Y as pixel offsets relative to the origin of the
2266 client window, and treat $ASCENT and $DESCENT as ascent and
2267 descent pixels of a line at ($X . $Y).
2269 $MT and $POS is an M-text and a character position at the spot.
2270 $MT may be NULL, in which case, the input method can't get
2271 information about the text around the spot. */
2274 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Î¥¹¥Ý¥Ã¥È¤òÀßÄꤹ¤ë
2276 ´Ø¿ô minput_set_spot () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤Î¥¹¥Ý¥Ã¥È¤ò¡¢ºÂ
2277 ɸ ($X, $Y)¤Ë ¡¢¹â¤µ $ASCENT¡¢$DESCENT ¤ÇÀßÄꤹ¤ë¡£¤³¤ì¤é¤ÎÃͤΰÕ
2278 Ì£¤ÏÆþÎϥɥ饤¥Ð¤Ë°Í¸¤¹¤ë¡£
2280 ¤¿¤È¤¨¤Ð CUI ´Ä¶¤ÇÆ°ºî¤¹¤ëÆþÎϥɥ饤¥Ð¤Ï $X, $Y ¤ò¤½¤ì¤¾¤ìÎó¤È¹Ô
2281 ¤ÎÈÖ¹æ¤È¤·¤ÆÍѤ¤¡¢$ASCENT¡¢$DESCENT ¤ò̵»ë¤¹¤ë¤«¤â¤·¤ì¤Ê¤¤¡£ ¤Þ¤¿
2282 ¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥àÍѤÎÆþÎϥɥ饤¥Ð¤Ï $X,$Y ¤ò¥¯¥é¥¤¥¢¥ó¥È¥¦¥£¥ó¥É
2283 ¥¦¤Î¸¶ÅÀ¤«¤é¤Î¥ª¥Õ¥»¥Ã¥È¤ò¥Ô¥¯¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¤¡¢
2284 $ASCENT ¤È $DESCENT ¤ò ($X . $Y) ¤ÎÎó¤Î¥¢¥»¥ó¥È¤È¥Ç¥£¥»¥ó¥È¤ò¥Ô¥¯
2285 ¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¦¤«¤â¤·¤ì¤Ê¤¤¡£ */
2288 minput_set_spot (MInputContext *ic, int x, int y,
2289 int ascent, int descent, int fontsize,
2294 ic->spot.ascent = ascent;
2295 ic->spot.descent = descent;
2296 ic->spot.fontsize = fontsize;
2299 if (ic->im->driver.callback_list)
2300 minput__callback (ic, Minput_set_spot);
2305 @brief Toggle input method.
2307 The minput_toggle () function toggles the input method associated
2308 with the input context $IC. */
2311 minput_toggle (MInputContext *ic)
2313 if (ic->im->driver.callback_list)
2314 minput__callback (ic, Minput_toggle);
2315 ic->active = ! ic->active;
2321 /*** @addtogroup m17nDebug */
2327 @brief Dump an input method
2329 The mdebug_dump_im () function prints the input method $IM in a
2330 human readable way to the stderr. $INDENT specifies how many
2331 columns to indent the lines but the first one.
2334 This function returns $IM. */
2337 mdebug_dump_im (MInputMethod *im, int indent)
2339 MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
2342 prefix = (char *) alloca (indent + 1);
2343 memset (prefix, 32, indent);
2344 prefix[indent] = '\0';
2346 fprintf (stderr, "(input-method %s %s ", msymbol_name (im->language),
2347 msymbol_name (im->name));
2348 mdebug_dump_mtext (im_info->title, 0, 0);
2349 if (im->name != Mnil)
2353 MPLIST_DO (state, im_info->states)
2355 fprintf (stderr, "\n%s ", prefix);
2356 dump_im_state (MPLIST_VAL (state), indent + 2);
2359 fprintf (stderr, ")");