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
144 #include <sys/types.h>
153 #include "m17n-gui.h"
154 #include "m17n-misc.h"
155 #include "internal.h"
160 #include "database.h"
162 static int mdebug_mask = MDEBUG_INPUT;
164 static MSymbol Minput_method;
166 /** Symbols to load an input method data. */
167 static MSymbol Mtitle, Mmacro, Mmodule, Mstate;
169 /** Symbols for actions. */
170 static MSymbol Minsert, Mdelete, Mmark, Mmove, Mpushback, Mundo, Mcall, Mshift;
171 static MSymbol Mselect, Mshow, Mhide;
172 static MSymbol Mset, Madd, Msub, Mmul, Mdiv, Mequal, Mless, Mgreater;
174 static MSymbol Mcandidate_list, Mcandidate_index;
176 static MSymbol Minit, Mfini;
178 /** Symbols for key events. */
179 static MSymbol one_char_symbol[256];
181 static MSymbol M_key_alias;
183 static MSymbol M_description, M_command, M_variable;
185 /** Structure to hold a map. */
189 /** List of actions to take when we reach the map. In a root map,
190 the actions are executed only when there's no more key. */
193 /** List of deeper maps. If NULL, this is a terminal map. */
196 /** List of actions to take when we leave the map successfully. In
197 a root map, the actions are executed only when none of submaps
198 handle the current key. */
199 MPlist *branch_actions;
202 typedef MPlist *(*MIMExternalFunc) (MPlist *plist);
207 MPlist *func_list; /* function name vs (MIMExternalFunc *) */
212 /** Name of the state. */
215 /** Title of the state, or NULL. */
218 /** Key translation map of the state. Built by merging all maps of
225 marker_code (MSymbol sym)
231 name = MSYMBOL_NAME (sym);
232 return ((name[0] == '@'
233 && ((name[1] >= '0' && name[1] <= '9')
234 || name[1] == '<' || name[1] == '>'
235 || name[1] == '=' || name[1] == '+' || name[1] == '-'
236 || name[1] == '[' || name[1] == ']')
242 integer_value (MInputContext *ic, MPlist *arg)
244 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
246 MText *preedit = ic->preedit;
247 int len = mtext_nchars (preedit);
249 if (MPLIST_INTEGER_P (arg))
250 return MPLIST_INTEGER (arg);
251 code = marker_code (MPLIST_SYMBOL (arg));
253 return (int) mplist_get (ic_info->vars, MPLIST_SYMBOL (arg));
254 if (code >= '0' && code <= '9')
256 else if (code == '=')
257 code = ic->cursor_pos;
258 else if (code == '-' || code == '[')
259 code = ic->cursor_pos - 1;
260 else if (code == '+' || code == ']')
261 code = ic->cursor_pos + 1;
262 else if (code == '<')
264 else if (code == '>')
266 return (code >= 0 && code < len ? mtext_ref_char (preedit, code) : -1);
270 /* Parse PLIST as an action list while modifying the list to regularize
271 actions. PLIST should have this form:
272 PLIST ::= ( (ACTION-NAME ACTION-ARG *) *).
273 Return 0 if successfully parsed, otherwise return -1. */
276 parse_action_list (MPlist *plist, MPlist *macros)
278 MPLIST_DO (plist, plist)
280 if (MPLIST_MTEXT_P (plist))
282 /* This is a short form of (insert MTEXT). */
283 /* if (mtext_nchars (MPLIST_MTEXT (plist)) == 0)
284 MERROR (MERROR_IM, -1); */
286 else if (MPLIST_PLIST_P (plist)
287 && (MPLIST_MTEXT_P (MPLIST_PLIST (plist))
288 || MPLIST_PLIST_P (MPLIST_PLIST (plist))))
292 /* This is a short form of (insert (GROUPS *)). */
293 MPLIST_DO (pl, MPLIST_PLIST (plist))
295 if (MPLIST_PLIST_P (pl))
299 MPLIST_DO (elt, MPLIST_PLIST (pl))
300 if (! MPLIST_MTEXT_P (elt)
301 || mtext_nchars (MPLIST_MTEXT (elt)) == 0)
302 MERROR (MERROR_IM, -1);
306 if (! MPLIST_MTEXT_P (pl)
307 || mtext_nchars (MPLIST_MTEXT (pl)) == 0)
308 MERROR (MERROR_IM, -1);
312 else if (MPLIST_INTEGER_P (plist))
314 int c = MPLIST_INTEGER (plist);
316 if (c < 0 || c > MCHAR_MAX)
317 MERROR (MERROR_IM, -1);
319 else if (MPLIST_PLIST_P (plist)
320 && MPLIST_SYMBOL_P (MPLIST_PLIST (plist)))
322 MPlist *pl = MPLIST_PLIST (plist);
323 MSymbol action_name = MPLIST_SYMBOL (pl);
325 pl = MPLIST_NEXT (pl);
327 if (action_name == Minsert)
329 if (MPLIST_MTEXT_P (pl))
331 if (mtext_nchars (MPLIST_MTEXT (pl)) == 0)
332 MERROR (MERROR_IM, -1);
334 else if (MPLIST_PLIST_P (pl))
338 if (MPLIST_PLIST_P (pl))
342 MPLIST_DO (elt, MPLIST_PLIST (pl))
343 if (! MPLIST_MTEXT_P (elt)
344 || mtext_nchars (MPLIST_MTEXT (elt)) == 0)
345 MERROR (MERROR_IM, -1);
349 if (! MPLIST_MTEXT_P (pl)
350 || mtext_nchars (MPLIST_MTEXT (pl)) == 0)
351 MERROR (MERROR_IM, -1);
355 else if (! MPLIST_SYMBOL_P (pl))
356 MERROR (MERROR_IM, -1);
358 else if (action_name == Mselect
359 || action_name == Mdelete
360 || action_name == Mmove)
362 if (! MPLIST_SYMBOL_P (pl)
363 && ! MPLIST_INTEGER_P (pl))
364 MERROR (MERROR_IM, -1);
366 else if (action_name == Mmark
367 || action_name == Mcall
368 || action_name == Mshift)
370 if (! MPLIST_SYMBOL_P (pl))
371 MERROR (MERROR_IM, -1);
373 else if (action_name == Mshow || action_name == Mhide
374 || action_name == Mundo)
376 if (! MPLIST_TAIL_P (pl))
377 MERROR (MERROR_IM, -1);
379 else if (action_name == Mpushback)
381 if (! MPLIST_INTEGER_P (pl))
382 MERROR (MERROR_IM, -1);
384 else if (action_name == Mset || action_name == Madd
385 || action_name == Msub || action_name == Mmul
386 || action_name == Mdiv)
388 if (! (MPLIST_SYMBOL_P (pl)
389 && (MPLIST_INTEGER_P (MPLIST_NEXT (pl))
390 || MPLIST_SYMBOL_P (MPLIST_NEXT (pl)))))
391 MERROR (MERROR_IM, -1);
393 else if (action_name == Mequal || action_name == Mless
394 || action_name == Mgreater)
396 if (! ((MPLIST_INTEGER_P (pl) || MPLIST_SYMBOL_P (pl))
397 && (MPLIST_INTEGER_P (MPLIST_NEXT (pl))
398 || MPLIST_SYMBOL_P (MPLIST_NEXT (pl)))))
399 MERROR (MERROR_IM, -1);
400 pl = MPLIST_NEXT (MPLIST_NEXT (pl));
401 if (! MPLIST_PLIST_P (pl))
402 MERROR (MERROR_IM, -1);
403 if (parse_action_list (MPLIST_PLIST (pl), macros) < 0)
404 MERROR (MERROR_IM, -1);
405 pl = MPLIST_NEXT (pl);
406 if (MPLIST_PLIST_P (pl)
407 && parse_action_list (MPLIST_PLIST (pl), macros) < 0)
408 MERROR (MERROR_IM, -1);
410 else if (! macros || ! mplist_get (macros, action_name))
411 MERROR (MERROR_IM, -1);
414 MERROR (MERROR_IM, -1);
421 /* Load a translation into MAP from PLIST.
423 PLIST ::= ( KEYSEQ MAP-ACTION * ) */
426 load_translation (MIMMap *map, MPlist *plist, MPlist *branch_actions,
432 if (MPLIST_MTEXT_P (plist))
434 MText *mt = MPLIST_MTEXT (plist);
436 len = mtext_nchars (mt);
437 if (len == 0 || len != mtext_nbytes (mt))
438 MERROR (MERROR_IM, -1);
439 keyseq = (MSymbol *) alloca (sizeof (MSymbol) * len);
440 for (i = 0; i < len; i++)
441 keyseq[i] = one_char_symbol[MTEXT_DATA (mt)[i]];
443 else if (MPLIST_PLIST_P (plist))
445 MPlist *elt = MPLIST_PLIST (plist);
447 len = MPLIST_LENGTH (elt);
449 MERROR (MERROR_IM, -1);
450 keyseq = (MSymbol *) alloca (sizeof (int) * len);
451 for (i = 0; i < len; i++, elt = MPLIST_NEXT (elt))
453 if (MPLIST_INTEGER_P (elt))
455 int c = MPLIST_INTEGER (elt);
457 if (c < 0 || c >= 0x100)
458 MERROR (MERROR_IM, -1);
459 keyseq[i] = one_char_symbol[c];
461 else if (MPLIST_SYMBOL_P (elt))
462 keyseq[i] = MPLIST_SYMBOL (elt);
464 MERROR (MERROR_IM, -1);
468 MERROR (MERROR_IM, -1);
470 for (i = 0; i < len; i++)
472 MIMMap *deeper = NULL;
475 deeper = mplist_get (map->submaps, keyseq[i]);
477 map->submaps = mplist ();
480 /* Fixme: It is better to make all deeper maps at once. */
481 MSTRUCT_CALLOC (deeper, MERROR_IM);
482 mplist_put (map->submaps, keyseq[i], deeper);
487 /* We reach a terminal map. */
489 || map->branch_actions)
490 /* This map is already defined. We avoid overriding it. */
493 plist = MPLIST_NEXT (plist);
494 if (! MPLIST_TAIL_P (plist))
496 if (parse_action_list (plist, macros) < 0)
497 MERROR (MERROR_IM, -1);
498 map->map_actions = plist;
499 M17N_OBJECT_REF (plist);
503 map->branch_actions = branch_actions;
504 M17N_OBJECT_REF (branch_actions);
510 /* Load a branch from PLIST into MAP. PLIST has this form:
511 PLIST ::= ( MAP-NAME BRANCH-ACTION * )
512 MAPS is a plist of raw maps.
513 STATE is the current state. */
516 load_branch (MPlist *plist, MPlist *maps, MIMMap *map, MPlist *macros)
519 MPlist *branch_actions;
521 if (! MPLIST_SYMBOL_P (plist))
522 MERROR (MERROR_IM, -1);
523 map_name = MPLIST_SYMBOL (plist);
524 plist = MPLIST_NEXT (plist);
525 if (MPLIST_TAIL_P (plist))
526 branch_actions = NULL;
527 else if (parse_action_list (plist, macros) < 0)
528 MERROR (MERROR_IM, -1);
530 branch_actions = plist;
531 if (map_name == Mnil)
533 map->branch_actions = branch_actions;
535 M17N_OBJECT_REF (branch_actions);
537 else if (map_name == Mt)
539 map->map_actions = branch_actions;
541 M17N_OBJECT_REF (branch_actions);
545 plist = (MPlist *) mplist_get (maps, map_name);
546 if (! plist || ! MPLIST_PLIST_P (plist))
547 MERROR (MERROR_IM, -1);
548 MPLIST_DO (plist, plist)
549 if (! MPLIST_PLIST_P (plist)
550 || (load_translation (map, MPLIST_PLIST (plist), branch_actions,
553 MERROR (MERROR_IM, -1);
559 /* Load a macro from PLIST into MACROS.
561 PLIST ::= ( MACRO-NAME ACTION * )
562 MACROS is a plist of macro names vs action list. */
564 load_macros (MPlist *plist, MPlist *macros)
568 if (! MPLIST_SYMBOL_P (plist))
569 MERROR (MERROR_IM, -1);
570 name = MPLIST_SYMBOL (plist);
571 plist = MPLIST_NEXT (plist);
572 if (MPLIST_TAIL_P (plist)
573 || parse_action_list (plist, macros) < 0)
574 MERROR (MERROR_IM, -1);
575 mplist_put (macros, name, plist);
576 M17N_OBJECT_REF (plist);
580 /* Load an external module from PLIST into EXTERNALS.
582 PLIST ::= ( MODULE-NAME FUNCTION * )
583 EXTERNALS is a plist of MODULE-NAME vs (MIMExternalModule *). */
585 #ifndef DLOPEN_SHLIB_EXT
586 #define DLOPEN_SHLIB_EXT ".so"
590 load_external_module (MPlist *plist, MPlist *externals)
595 MIMExternalModule *external;
599 if (MPLIST_MTEXT_P (plist))
600 module = msymbol ((char *) MTEXT_DATA (MPLIST_MTEXT (plist)));
601 else if (MPLIST_SYMBOL_P (plist))
602 module = MPLIST_SYMBOL (plist);
603 module_file = alloca (strlen (MSYMBOL_NAME (module))
604 + strlen (DLOPEN_SHLIB_EXT) + 1);
605 sprintf (module_file, "%s%s", MSYMBOL_NAME (module), DLOPEN_SHLIB_EXT);
607 handle = dlopen (module_file, RTLD_NOW);
610 fprintf (stderr, "%s\n", dlerror ());
611 MERROR (MERROR_IM, -1);
613 func_list = mplist ();
614 MPLIST_DO (plist, MPLIST_NEXT (plist))
616 if (! MPLIST_SYMBOL_P (plist))
617 MERROR_GOTO (MERROR_IM, err_label);
618 func = dlsym (handle, MSYMBOL_NAME (MPLIST_SYMBOL (plist)));
620 MERROR_GOTO (MERROR_IM, err_label);
621 mplist_add (func_list, MPLIST_SYMBOL (plist), func);
624 MSTRUCT_MALLOC (external, MERROR_IM);
625 external->handle = handle;
626 external->func_list = func_list;
627 mplist_add (externals, module, external);
632 M17N_OBJECT_UNREF (func_list);
637 /** Load a state from PLIST into a newly allocated state object.
639 PLIST ::= ( STATE-NAME STATE-TITLE ? BRANCH * )
640 BRANCH ::= ( MAP-NAME BRANCH-ACTION * )
641 MAPS is a plist of defined maps.
642 Return the state object. */
645 load_state (MPlist *plist, MPlist *maps, MSymbol language, MPlist *macros)
649 MSTRUCT_CALLOC (state, MERROR_IM);
650 if (! MPLIST_SYMBOL_P (plist))
651 MERROR (MERROR_IM, NULL);
652 state->name = MPLIST_SYMBOL (plist);
653 plist = MPLIST_NEXT (plist);
654 if (MPLIST_MTEXT_P (plist))
656 state->title = MPLIST_MTEXT (plist);
657 mtext_put_prop (state->title, 0, mtext_nchars (state->title),
658 Mlanguage, language);
659 M17N_OBJECT_REF (state->title);
660 plist = MPLIST_NEXT (plist);
662 MSTRUCT_CALLOC (state->map, MERROR_IM);
663 MPLIST_DO (plist, plist)
664 if (! MPLIST_PLIST_P (plist)
665 || load_branch (MPLIST_PLIST (plist), maps, state->map, macros) < 0)
666 MERROR (MERROR_IM, NULL);
672 free_map (MIMMap *map)
676 M17N_OBJECT_UNREF (map->map_actions);
679 MPLIST_DO (plist, map->submaps)
680 free_map ((MIMMap *) MPLIST_VAL (plist));
681 M17N_OBJECT_UNREF (map->submaps);
683 M17N_OBJECT_UNREF (map->branch_actions);
687 /* Load an input method from PLIST into IM_INTO, and return it. */
690 load_input_method (MSymbol language, MSymbol name, MPlist *plist,
691 MInputMethodInfo *im_info)
695 MPlist *states = NULL;
696 MPlist *externals = NULL;
697 MPlist *macros = NULL;
700 for (; MPLIST_PLIST_P (plist); plist = MPLIST_NEXT (plist))
702 elt = MPLIST_PLIST (plist);
703 if (! MPLIST_SYMBOL_P (elt))
704 MERROR_GOTO (MERROR_IM, err);
705 if (MPLIST_SYMBOL (elt) == Mtitle)
707 elt = MPLIST_NEXT (elt);
708 if (MPLIST_MTEXT_P (elt))
710 title = MPLIST_MTEXT (elt);
711 M17N_OBJECT_REF (title);
714 MERROR_GOTO (MERROR_IM, err);
716 else if (MPLIST_SYMBOL (elt) == Mmap)
718 maps = mplist__from_alist (MPLIST_NEXT (elt));
720 MERROR_GOTO (MERROR_IM, err);
722 else if (MPLIST_SYMBOL (elt) == Mmacro)
725 MPLIST_DO (elt, MPLIST_NEXT (elt))
727 if (! MPLIST_PLIST_P (elt)
728 || load_macros (MPLIST_PLIST (elt), macros) < 0)
729 MERROR_GOTO (MERROR_IM, err);
732 else if (MPLIST_SYMBOL (elt) == Mmodule)
734 externals = mplist ();
735 MPLIST_DO (elt, MPLIST_NEXT (elt))
737 if (! MPLIST_PLIST_P (elt)
738 || load_external_module (MPLIST_PLIST (elt), externals) < 0)
739 MERROR_GOTO (MERROR_IM, err);
742 else if (MPLIST_SYMBOL (elt) == Mstate)
745 MPLIST_DO (elt, MPLIST_NEXT (elt))
749 if (! MPLIST_PLIST_P (elt))
750 MERROR_GOTO (MERROR_IM, err);
751 state = load_state (MPLIST_PLIST (elt), maps, language, macros);
753 MERROR_GOTO (MERROR_IM, err);
754 mplist_put (states, state->name, state);
761 MPLIST_DO (elt, maps)
762 M17N_OBJECT_UNREF (MPLIST_VAL (elt));
763 M17N_OBJECT_UNREF (maps);
766 title = mtext_from_data (MSYMBOL_NAME (name), MSYMBOL_NAMELEN (name),
767 MTEXT_FORMAT_US_ASCII);
768 im_info->title = title;
769 im_info->externals = externals;
770 im_info->macros = macros;
771 im_info->states = states;
777 MPLIST_DO (elt, maps)
778 M17N_OBJECT_UNREF (MPLIST_VAL (elt));
779 M17N_OBJECT_UNREF (maps);
782 M17N_OBJECT_UNREF (title);
785 MPLIST_DO (plist, states)
787 MIMState *state = (MIMState *) MPLIST_VAL (plist);
790 M17N_OBJECT_UNREF (state->title);
792 free_map (state->map);
795 M17N_OBJECT_UNREF (states);
799 MPLIST_DO (plist, externals)
801 MIMExternalModule *external = MPLIST_VAL (plist);
803 dlclose (external->handle);
804 M17N_OBJECT_UNREF (external->func_list);
806 MPLIST_KEY (plist) = Mt;
808 M17N_OBJECT_UNREF (externals);
815 static int take_action_list (MInputContext *ic, MPlist *action_list);
818 shift_state (MInputContext *ic, MSymbol state_name)
820 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
821 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
824 /* Find a state to shift to. If not found, shift to the initial
826 state = (MIMState *) mplist_get (im_info->states, state_name);
828 state = (MIMState *) MPLIST_VAL (im_info->states);
830 MDEBUG_PRINT1 ("\n[IM] state-shift (%s)", MSYMBOL_NAME (state->name));
832 /* Enter the new state. */
833 ic_info->state = state;
834 ic_info->map = state->map;
835 ic_info->state_key_head = ic_info->key_head;
836 if (state == (MIMState *) MPLIST_VAL (im_info->states))
838 /* We have shifted to the initial state. */
841 mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit),
842 Mcandidate_list, NULL, 0);
843 mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit),
844 Mcandidate_index, NULL, 0);
845 mtext_cat (ic->produced, ic->preedit);
846 if ((mdebug__flag & mdebug_mask)
847 && mtext_nchars (ic->produced) > 0)
851 MDEBUG_PRINT (" (produced");
852 for (i = 0; i < mtext_nchars (ic->produced); i++)
853 MDEBUG_PRINT1 (" U+%04X", mtext_ref_char (ic->produced, i));
856 mtext_reset (ic->preedit);
857 ic->candidate_list = NULL;
858 ic->candidate_show = 0;
859 ic->preedit_changed = ic->candidates_changed = 1;
860 MPLIST_DO (p, ic_info->markers)
862 MPLIST_DO (p, ic_info->vars)
865 memmove (ic_info->keys, ic_info->keys + ic_info->state_key_head,
866 sizeof (int) * (ic_info->used - ic_info->state_key_head));
867 ic_info->used -= ic_info->state_key_head;
868 ic_info->state_key_head = ic_info->key_head = 0;
870 mtext_cpy (ic_info->preedit_saved, ic->preedit);
871 ic_info->state_pos = ic->cursor_pos;
872 ic->status = state->title;
874 ic->status = im_info->title;
875 ic->status_changed = 1;
876 if (ic_info->key_head == ic_info->used
877 && ic_info->map == ic_info->state->map
878 && ic_info->map->map_actions)
880 MDEBUG_PRINT (" init-actions:");
881 take_action_list (ic, ic_info->map->map_actions);
885 /* Find a candidate group that contains a candidate number INDEX from
886 PLIST. Set START_INDEX to the first candidate number of the group,
887 END_INDEX to the last candidate number plus 1, GROUP_INDEX to the
888 candidate group number if they are non-NULL. If INDEX is -1, find
889 the last candidate group. */
892 find_candidates_group (MPlist *plist, int index,
893 int *start_index, int *end_index, int *group_index)
895 int i = 0, gidx = 0, len;
897 MPLIST_DO (plist, plist)
899 if (MPLIST_MTEXT_P (plist))
900 len = mtext_nchars (MPLIST_MTEXT (plist));
902 len = mplist_length (MPLIST_PLIST (plist));
903 if (index < 0 ? MPLIST_TAIL_P (MPLIST_NEXT (plist))
909 *end_index = i + len;
921 preedit_insert (MInputContext *ic, int pos, MText *mt, int c)
923 MInputContextInfo *ic_info = ((MInputContext *) ic)->info;
925 int nchars = mt ? mtext_nchars (mt) : 1;
928 mtext_ins (ic->preedit, pos, mt);
930 mtext_ins_char (ic->preedit, pos, c, 1);
931 MPLIST_DO (markers, ic_info->markers)
932 if (MPLIST_INTEGER (markers) > pos)
933 MPLIST_VAL (markers) = (void *) (MPLIST_INTEGER (markers) + nchars);
934 if (ic->cursor_pos >= pos)
935 ic->cursor_pos += nchars;
936 ic->preedit_changed = 1;
941 preedit_delete (MInputContext *ic, int from, int to)
943 MInputContextInfo *ic_info = ((MInputContext *) ic)->info;
946 mtext_del (ic->preedit, from, to);
947 MPLIST_DO (markers, ic_info->markers)
949 if (MPLIST_INTEGER (markers) > to)
951 = (void *) (MPLIST_INTEGER (markers) - (to - from));
952 else if (MPLIST_INTEGER (markers) > from);
953 MPLIST_VAL (markers) = (void *) from;
955 if (ic->cursor_pos >= to)
956 ic->cursor_pos -= to - from;
957 else if (ic->cursor_pos > from)
958 ic->cursor_pos = from;
959 ic->preedit_changed = 1;
964 new_index (MInputContext *ic, int current, int limit, MSymbol sym, MText *mt)
966 int code = marker_code (sym);
968 if (mt && (code == '[' || code == ']'))
972 if (code == '[' && current > 0)
974 if (mtext_prop_range (mt, Mcandidate_list, pos - 1, &pos, NULL, 1)
978 else if (code == ']' && current < mtext_nchars (mt))
980 if (mtext_prop_range (mt, Mcandidate_list, pos, NULL, &pos, 1))
986 return (code == '<' ? 0
987 : code == '>' ? limit
988 : code == '-' ? current - 1
989 : code == '+' ? current + 1
990 : code == '=' ? current
991 : code - '0' > limit ? limit
995 return (int) mplist_get (((MInputContextInfo *) ic->info)->markers, sym);
999 update_candidate (MInputContext *ic, MTextProperty *prop, int idx)
1001 int from = mtext_property_start (prop);
1002 int to = mtext_property_end (prop);
1004 MPlist *candidate_list = mtext_property_value (prop);
1005 MPlist *group = find_candidates_group (candidate_list, idx, &start,
1007 int ingroup_index = idx - start;
1010 preedit_delete (ic, from, to);
1011 if (MPLIST_MTEXT_P (group))
1013 mt = MPLIST_MTEXT (group);
1014 preedit_insert (ic, from, NULL, mtext_ref_char (mt, ingroup_index));
1022 for (i = 0, plist = MPLIST_PLIST (group); i < ingroup_index;
1023 i++, plist = MPLIST_NEXT (plist));
1024 mt = MPLIST_MTEXT (plist);
1025 preedit_insert (ic, from, mt, 0);
1026 to = from + mtext_nchars (mt);
1028 mtext_put_prop (ic->preedit, from, to, Mcandidate_list, candidate_list);
1029 mtext_put_prop (ic->preedit, from, to, Mcandidate_index, (void *) idx);
1030 ic->cursor_pos = to;
1035 take_action_list (MInputContext *ic, MPlist *action_list)
1037 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1038 MPlist *candidate_list = ic->candidate_list;
1039 int candidate_index = ic->candidate_index;
1040 int candidate_show = ic->candidate_show;
1041 MTextProperty *prop;
1043 MPLIST_DO (action_list, action_list)
1049 if (MPLIST_MTEXT_P (action_list)
1050 || MPLIST_INTEGER_P (action_list))
1051 name = Minsert, args = action_list;
1052 else if (MPLIST_PLIST_P (action_list)
1053 && (MPLIST_MTEXT_P (MPLIST_PLIST (action_list))
1054 || MPLIST_PLIST_P (MPLIST_PLIST (action_list))))
1055 name = Minsert, args = action_list;
1058 action = MPLIST_PLIST (action_list);
1059 name = MPLIST_SYMBOL (action);
1060 args = MPLIST_NEXT (action);
1063 MDEBUG_PRINT1 (" %s", MSYMBOL_NAME (name));
1064 if (name == Minsert)
1066 if (MPLIST_MTEXT_P (args))
1067 preedit_insert (ic, ic->cursor_pos, MPLIST_MTEXT (args), 0);
1068 else if (MPLIST_INTEGER_P (args))
1069 preedit_insert (ic, ic->cursor_pos, NULL, MPLIST_INTEGER (args));
1070 else if (MPLIST_SYMBOL_P (args))
1072 int c = integer_value (ic, args);
1074 if (c >= 0 && c <= MCHAR_MAX)
1075 preedit_insert (ic, ic->cursor_pos, NULL, c);
1082 args = MPLIST_PLIST (args);
1083 if (MPLIST_MTEXT_P (args))
1085 preedit_insert (ic, ic->cursor_pos, NULL,
1086 mtext_ref_char (MPLIST_MTEXT (args), 0));
1091 mt = MPLIST_MTEXT (MPLIST_PLIST (args));
1092 preedit_insert (ic, ic->cursor_pos, mt, 0);
1093 len = mtext_nchars (mt);
1095 mtext_put_prop (ic->preedit,
1096 ic->cursor_pos - len, ic->cursor_pos,
1097 Mcandidate_list, args);
1098 mtext_put_prop (ic->preedit,
1099 ic->cursor_pos - len, ic->cursor_pos,
1100 Mcandidate_index, (void *) 0);
1103 else if (name == Mselect)
1106 int code, idx, gindex;
1107 int pos = ic->cursor_pos;
1111 || ! (prop = mtext_get_property (ic->preedit, pos - 1,
1114 if (MPLIST_SYMBOL_P (args))
1116 code = marker_code (MPLIST_SYMBOL (args));
1122 idx = (int) mtext_get_prop (ic->preedit, pos - 1, Mcandidate_index);
1123 group = find_candidates_group (mtext_property_value (prop), idx,
1124 &start, &end, &gindex);
1126 if (code != '[' && code != ']')
1130 ? new_index (NULL, ic->candidate_index - start,
1131 end - start - 1, MPLIST_SYMBOL (args),
1133 : MPLIST_INTEGER (args)));
1136 find_candidates_group (mtext_property_value (prop), -1,
1141 && MPLIST_TAIL_P (MPLIST_NEXT (group)))
1146 int ingroup_index = idx - start;
1149 group = mtext_property_value (prop);
1150 len = mplist_length (group);
1163 for (idx = 0; gindex > 0; gindex--, group = MPLIST_NEXT (group))
1164 idx += (MPLIST_MTEXT_P (group)
1165 ? mtext_nchars (MPLIST_MTEXT (group))
1166 : mplist_length (MPLIST_PLIST (group)));
1167 len = (MPLIST_MTEXT_P (group)
1168 ? mtext_nchars (MPLIST_MTEXT (group))
1169 : mplist_length (MPLIST_PLIST (group)));
1170 if (ingroup_index >= len)
1171 ingroup_index = len - 1;
1172 idx += ingroup_index;
1174 update_candidate (ic, prop, idx);
1176 else if (name == Mshow)
1177 ic->candidate_show = 1;
1178 else if (name == Mhide)
1179 ic->candidate_show = 0;
1180 else if (name == Mdelete)
1182 int len = mtext_nchars (ic->preedit);
1183 int to = (MPLIST_SYMBOL_P (args)
1184 ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
1186 : MPLIST_INTEGER (args));
1192 if (to < ic->cursor_pos)
1193 preedit_delete (ic, to, ic->cursor_pos);
1194 else if (to > ic->cursor_pos)
1195 preedit_delete (ic, ic->cursor_pos, to);
1197 else if (name == Mmove)
1199 int len = mtext_nchars (ic->preedit);
1201 = (MPLIST_SYMBOL_P (args)
1202 ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args),
1204 : MPLIST_INTEGER (args));
1210 if (pos != ic->cursor_pos)
1212 ic->cursor_pos = pos;
1213 ic->preedit_changed = 1;
1216 else if (name == Mmark)
1218 int code = marker_code (MPLIST_SYMBOL (args));
1221 mplist_put (ic_info->markers, MPLIST_SYMBOL (args),
1222 (void *) ic->cursor_pos);
1224 else if (name == Mpushback)
1226 int num = MPLIST_INTEGER (args);
1229 ic_info->key_head -= num;
1231 ic_info->key_head = num;
1232 if (ic_info->key_head > ic_info->used)
1233 ic_info->key_head = ic_info->used;
1235 else if (name == Mcall)
1237 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1238 MIMExternalFunc func = NULL;
1239 MSymbol module, func_name;
1240 MPlist *func_args, *val;
1243 module = MPLIST_SYMBOL (args);
1244 args = MPLIST_NEXT (args);
1245 func_name = MPLIST_SYMBOL (args);
1247 if (im_info->externals)
1249 MIMExternalModule *external
1250 = (MIMExternalModule *) mplist_get (im_info->externals,
1253 func = (MIMExternalFunc) mplist_get (external->func_list,
1258 func_args = mplist ();
1259 mplist_add (func_args, Mt, ic);
1260 MPLIST_DO (args, MPLIST_NEXT (args))
1264 if (MPLIST_KEY (args) == Msymbol
1265 && MPLIST_KEY (args) != Mnil
1266 && (code = marker_code (MPLIST_SYMBOL (args))) >= 0)
1268 code = new_index (ic, ic->cursor_pos,
1269 mtext_nchars (ic->preedit),
1270 MPLIST_SYMBOL (args), ic->preedit);
1271 mplist_add (func_args, Minteger, (void *) code);
1274 mplist_add (func_args, MPLIST_KEY (args), MPLIST_VAL (args));
1276 val = (func) (func_args);
1277 M17N_OBJECT_UNREF (func_args);
1278 if (val && ! MPLIST_TAIL_P (val))
1279 ret = take_action_list (ic, val);
1280 M17N_OBJECT_UNREF (val);
1284 else if (name == Mshift)
1286 shift_state (ic, MPLIST_SYMBOL (args));
1288 else if (name == Mundo)
1290 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1293 mtext_reset (ic->preedit);
1294 mtext_reset (ic_info->preedit_saved);
1295 ic->cursor_pos = ic_info->state_pos = 0;
1296 ic_info->state_key_head = ic_info->key_head = 0;
1298 if (ic_info->used < 0)
1303 shift_state (ic, ((MIMState *) MPLIST_VAL (im_info->states))->name);
1308 else if (name == Mset || name == Madd || name == Msub
1309 || name == Mmul || name == Mdiv)
1311 MSymbol sym = MPLIST_SYMBOL (args);
1312 int val1 = (int) mplist_get (ic_info->vars, sym), val2;
1314 args = MPLIST_NEXT (args);
1315 val2 = integer_value (ic, args);
1318 else if (name == Madd)
1320 else if (name == Msub)
1322 else if (name == Mmul)
1326 mplist_put (ic_info->vars, sym, (void *) val1);
1327 MDEBUG_PRINT2 ("(%s=%d)", MSYMBOL_NAME (sym), val1);
1329 else if (name == Mequal || name == Mless || name == Mgreater)
1332 MPlist *actions1, *actions2;
1335 val1 = integer_value (ic, args);
1336 args = MPLIST_NEXT (args);
1337 val2 = integer_value (ic, args);
1338 args = MPLIST_NEXT (args);
1339 actions1 = MPLIST_PLIST (args);
1340 args = MPLIST_NEXT (args);
1341 if (MPLIST_TAIL_P (args))
1344 actions2 = MPLIST_PLIST (args);
1345 if (name == Mequal ? val1 == val2
1346 : name == Mless ? val1 < val2
1348 ret = take_action_list (ic, actions1);
1350 ret = take_action_list (ic, actions2);
1356 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1360 && (actions = mplist_get (im_info->macros, name)))
1362 if (take_action_list (ic, actions) < 0)
1369 ic->candidate_list = NULL;
1370 if (ic->cursor_pos > 0
1371 && (prop = mtext_get_property (ic->preedit, ic->cursor_pos - 1,
1374 ic->candidate_list = mtext_property_value (prop);
1376 = (int) mtext_get_prop (ic->preedit, ic->cursor_pos - 1,
1378 ic->candidate_from = mtext_property_start (prop);
1379 ic->candidate_to = mtext_property_end (prop);
1382 ic->candidates_changed |= (candidate_list != ic->candidate_list
1383 || candidate_index != ic->candidate_index
1384 || candidate_show != ic->candidate_show);
1389 /* Handle the input key KEY in the current state and map specified in
1390 the input context IC. If KEY is handled correctly, return 0.
1391 Otherwise, return -1. */
1394 handle_key (MInputContext *ic)
1396 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1397 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1398 MIMMap *map = ic_info->map;
1399 MIMMap *submap = NULL;
1400 MSymbol key = ic_info->keys[ic_info->key_head];
1403 MDEBUG_PRINT2 ("[IM] handle `%s' in state %s",
1404 MSYMBOL_NAME (key), MSYMBOL_NAME (ic_info->state->name));
1408 submap = mplist_get (map->submaps, key);
1409 if (! submap && (key = msymbol_get (key, M_key_alias)) != Mnil)
1410 submap = mplist_get (map->submaps, key);
1415 MDEBUG_PRINT (" submap-found");
1416 mtext_cpy (ic->preedit, ic_info->preedit_saved);
1417 ic->cursor_pos = ic_info->state_pos;
1418 ic_info->key_head++;
1419 ic_info->map = map = submap;
1420 if (map->map_actions)
1422 MDEBUG_PRINT (" map-actions:");
1423 if (take_action_list (ic, map->map_actions) < 0)
1426 else if (map->submaps)
1428 for (i = ic_info->state_key_head; i < ic_info->key_head; i++)
1430 MSymbol key = ic_info->keys[i];
1431 char *name = msymbol_name (key);
1433 if (! name[0] || ! name[1])
1434 mtext_ins_char (ic->preedit, ic->cursor_pos++, name[0], 1);
1436 ic->preedit_changed = 1;
1439 /* If this is the terminal map or we have shifted to another
1440 state, perform branch actions (if any). */
1441 if (! map->submaps || map != ic_info->map)
1443 if (map->branch_actions)
1445 MDEBUG_PRINT (" branch-actions:");
1446 if (take_action_list (ic, map->branch_actions) < 0)
1449 /* If MAP is still not the root map, shift to the current
1451 if (ic_info->map != ic_info->state->map)
1452 shift_state (ic, ic_info->state->name);
1454 MDEBUG_PRINT ("\n");
1458 /* MAP can not handle KEY. */
1460 /* If MAP is the root map of the initial state, it means that
1461 the current input method can not handle KEY. */
1462 if (map == ((MIMState *) MPLIST_VAL (im_info->states))->map)
1464 MDEBUG_PRINT (" unhandled\n");
1468 if (map != ic_info->state->map)
1470 /* If MAP is not the root map... */
1471 /* If MAP has branch actions, perform them. */
1472 if (map->branch_actions)
1474 MDEBUG_PRINT (" branch-actions:");
1475 take_action_list (ic, map->branch_actions);
1477 /* If MAP is still not the root map, shift to the current
1479 if (ic_info->map != ic_info->state->map)
1481 shift_state (ic, ic_info->state->name);
1482 /* If MAP has branch_actions, perform them. */
1483 if (ic_info->map->branch_actions)
1485 MDEBUG_PRINT (" init-actions:");
1486 take_action_list (ic, ic_info->map->branch_actions);
1492 /* MAP is the root map, perform branch actions (if any) or
1493 shift to the initial state. */
1494 if (map->branch_actions)
1496 MDEBUG_PRINT (" branch-actions:");
1497 take_action_list (ic, map->branch_actions);
1501 ((MIMState *) MPLIST_VAL (im_info->states))->name);
1503 MDEBUG_PRINT ("\n");
1509 reset_ic (MInputContext *ic, MSymbol ignore)
1511 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1512 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1514 if (im_info->states)
1515 /* Shift to the initial state. */
1516 shift_state (ic, Mnil);
1518 ic_info->state = NULL;
1519 MLIST_RESET (ic_info);
1520 ic_info->map = ic_info->state ? ic_info->state->map : NULL;
1521 ic_info->state_key_head = ic_info->key_head = 0;
1522 ic_info->key_unhandled = 0;
1523 ic->cursor_pos = ic_info->state_pos = 0;
1524 ic->status = ic_info->state ? ic_info->state->title : NULL;
1526 ic->status = im_info->title;
1527 ic->candidate_list = NULL;
1528 ic->candidate_show = 0;
1529 ic->status_changed = ic->preedit_changed = ic->candidates_changed = 1;
1530 if (ic_info->map && ic_info->map->map_actions)
1531 take_action_list (ic, ic_info->map->map_actions);
1535 open_im (MInputMethod *im)
1538 MInputMethodInfo *im_info;
1542 mdb = mdatabase_find (Minput_method, im->language, im->name, Mnil);
1545 plist = mdatabase_load (mdb);
1547 MERROR (MERROR_IM, -1);
1548 MSTRUCT_CALLOC (im_info, MERROR_IM);
1550 result = load_input_method (im->language, im->name, plist, im_info);
1551 M17N_OBJECT_UNREF (plist);
1553 MERROR (MERROR_IM, -1);
1558 close_im (MInputMethod *im)
1560 MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
1564 M17N_OBJECT_UNREF (im_info->title);
1565 if (im_info->states)
1567 MPLIST_DO (plist, im_info->states)
1569 MIMState *state = (MIMState *) MPLIST_VAL (plist);
1572 M17N_OBJECT_UNREF (state->title);
1574 free_map (state->map);
1577 M17N_OBJECT_UNREF (im_info->states);
1580 if (im_info->macros)
1582 MPLIST_DO (plist, im_info->macros)
1583 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
1584 M17N_OBJECT_UNREF (im_info->macros);
1587 if (im_info->externals)
1589 MPLIST_DO (plist, im_info->externals)
1591 MIMExternalModule *external = MPLIST_VAL (plist);
1593 dlclose (external->handle);
1594 M17N_OBJECT_UNREF (external->func_list);
1596 MPLIST_KEY (plist) = Mt;
1598 M17N_OBJECT_UNREF (im_info->externals);
1606 create_ic (MInputContext *ic)
1608 MInputMethod *im = ic->im;
1609 MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
1610 MInputContextInfo *ic_info;
1613 ic_info = (MInputContextInfo *) ic->info;
1616 MSTRUCT_CALLOC (ic_info, MERROR_IM);
1619 MLIST_INIT1 (ic_info, keys, 8);
1620 ic_info->markers = mplist ();
1621 ic_info->vars = mplist ();
1622 ic_info->preedit_saved = mtext ();
1623 if (im_info->externals)
1625 MPlist *func_args = mplist (), *plist;
1627 mplist_add (func_args, Mt, ic);
1628 MPLIST_DO (plist, im_info->externals)
1630 MIMExternalModule *external = MPLIST_VAL (plist);
1631 MIMExternalFunc func
1632 = (MIMExternalFunc) mplist_get (external->func_list, Minit);
1637 M17N_OBJECT_UNREF (func_args);
1639 reset_ic (ic, Mnil);
1644 destroy_ic (MInputContext *ic)
1646 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1647 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1649 if (im_info->externals)
1651 MPlist *func_args = mplist (), *plist;
1653 mplist_add (func_args, Mt, ic);
1654 MPLIST_DO (plist, im_info->externals)
1656 MIMExternalModule *external = MPLIST_VAL (plist);
1657 MIMExternalFunc func
1658 = (MIMExternalFunc) mplist_get (external->func_list, Mfini);
1663 M17N_OBJECT_UNREF (func_args);
1665 MLIST_FREE1 (ic_info, keys);
1666 M17N_OBJECT_UNREF (ic_info->preedit_saved);
1667 M17N_OBJECT_UNREF (ic_info->markers);
1668 M17N_OBJECT_UNREF (ic_info->vars);
1673 /** Handle the input key KEY in the current state and map of IC->info.
1674 If KEY is handled but no text is produced, return 0, otherwise
1680 filter (MInputContext *ic, MSymbol key, void *arg)
1682 MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
1683 MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
1686 if (! ic_info->state)
1688 ic_info->key_unhandled = 1;
1691 mtext_reset (ic->produced);
1692 ic->status_changed = ic->preedit_changed = ic->candidates_changed = 0;
1693 MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
1694 ic_info->key_unhandled = 0;
1696 if (handle_key (ic) < 0)
1698 /* KEY was not handled. Reset the status and break the
1700 reset_ic (ic, Mnil);
1701 /* This forces returning 1. */
1702 ic_info->key_unhandled = 1;
1708 reset_ic (ic, Mnil);
1709 ic_info->key_unhandled = 1;
1712 /* Break the loop if all keys were handled. */
1713 } while (ic_info->key_head < ic_info->used);
1715 /* If the current map is the root of the initial state, we should
1716 produce any preedit text in ic->produced. */
1717 if (ic_info->map == ((MIMState *) MPLIST_VAL (im_info->states))->map
1718 && mtext_nchars (ic->preedit) > 0)
1719 shift_state (ic, ((MIMState *) MPLIST_VAL (im_info->states))->name);
1721 if (mtext_nchars (ic->produced) > 0)
1723 MSymbol lang = msymbol_get (ic->im->language, Mlanguage);
1726 mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
1727 Mlanguage, ic->im->language);
1730 return (! ic_info->key_unhandled && mtext_nchars (ic->produced) == 0);
1734 /** Return 1 if the last event or key was not handled, otherwise
1737 There is no need of looking up because ic->produced should already
1738 contain the produced text (if any).
1743 lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
1745 mtext_cat (mt, ic->produced);
1746 mtext_reset (ic->produced);
1747 return (((MInputContextInfo *) ic->info)->key_unhandled ? -1 : 0);
1750 static MPlist *load_im_info_keys;
1753 load_im_info (MSymbol language, MSymbol name, MSymbol key)
1758 if (language == Mnil || name == Mnil)
1759 MERROR (MERROR_IM, NULL);
1761 mdb = mdatabase_find (Minput_method, language, name, Mnil);
1763 MERROR (MERROR_IM, NULL);
1764 mplist_push (load_im_info_keys, key, Mt);
1765 plist = mdatabase__load_for_keys (mdb, load_im_info_keys);
1766 mplist_pop (load_im_info_keys);
1771 /* Input method command handler. */
1773 /* List of all (global and local) commands.
1774 (LANG:(IM-NAME:(COMMAND ...) ...) ...) ...
1775 COMMAND is CMD-NAME:(mtext:DESCRIPTION plist:KEYSEQ ...))
1776 Global commands are storead as (t (t COMMAND ...)) */
1777 static MPlist *command_list;
1779 /* Check if PLIST is a valid command key sequence.
1780 PLIST must be NULL or:
1781 [ symbol:KEY | integer:KEY ] ... */
1784 check_command_keyseq (MPlist *plist)
1788 MPLIST_DO (plist, plist)
1790 if (MPLIST_SYMBOL_P (plist))
1792 else if (MPLIST_INTEGER_P (plist))
1794 int n = MPLIST_INTEGER (plist);
1798 MPLIST_KEY (plist) = Msymbol;
1799 MPLIST_VAL (plist) = one_char_symbol['0' + 9];
1808 get_description_advance (MPlist *plist)
1813 if (! MPLIST_MTEXT_P (plist))
1815 mt = mplist_pop (plist);
1816 pos = mtext_chr (mt, '\n');
1819 MText *detail = mtext_copy (mtext (), 0, mt, pos + 1, mtext_nchars (mt));
1820 mtext_del (mt, pos, mtext_nchars (mt));
1821 mtext_put_prop (mt, 0, pos, Mdetail_text, detail);
1822 M17N_OBJECT_UNREF (detail);
1828 parse_command_list (MPlist *plist, MPlist *global_list)
1830 MPlist *val = mplist ();
1832 /* PLIST ::= (sym:CMD mtext:DESCRIPTION ? (sym:KEY ...) ...) ... */
1833 MPLIST_DO (plist, plist)
1837 MPlist *this_val, *pl, *p;
1839 if (! MPLIST_PLIST_P (plist))
1841 pl = MPLIST_PLIST (plist);
1842 if (! MPLIST_SYMBOL_P (pl))
1844 cmd = MPLIST_SYMBOL (pl);
1845 pl = MPLIST_NEXT (pl);
1846 mt = get_description_advance (pl);
1847 this_val = mplist ();
1849 if (! mt && global_list)
1851 /* Get the description from global_list. */
1852 p = mplist_get (global_list, cmd);
1853 if (p && MPLIST_MTEXT (p))
1855 mt = MPLIST_MTEXT (p);
1856 M17N_OBJECT_REF (mt);
1861 mplist_add (this_val, Mtext, mt);
1862 M17N_OBJECT_UNREF (mt);
1864 /* PL ::= (sym:KEY ...) ... */
1867 if (MPLIST_PLIST_P (pl)
1868 && check_command_keyseq (MPLIST_PLIST (pl)) >= 0)
1869 /* All the elements are valid keys. */
1870 mplist_add (this_val, Mplist, MPLIST_PLIST (pl));
1873 mplist_put (val, cmd, this_val);
1879 get_command_list (MSymbol language, MSymbol name)
1885 language = name = Mt;
1889 MDatabase *mdb = mdatabase_find (msymbol ("input"), M_command,
1892 if (mdb && (plist = mdatabase_load (mdb)))
1894 pl = parse_command_list (plist, NULL);
1895 M17N_OBJECT_UNREF (plist);
1900 mplist_add (plist, Mt, pl);
1901 command_list = mplist ();
1902 mplist_add (command_list, Mt, plist);
1905 per_lang = mplist_get (command_list, language);
1908 plist = mplist_find_by_key (per_lang, name);
1910 return (MPLIST_VAL (plist));
1914 per_lang = mplist ();
1915 mplist_add (command_list, language, per_lang);
1918 /* Now we are sure that we are loading per-im info. */
1919 /* Get the global command list. */
1920 plist = load_im_info (language, name, M_command);
1921 if (! plist || mplist_key (plist) == Mnil)
1925 mplist_add (per_lang, name, plist);
1928 pl = parse_command_list (mplist_value (plist),
1929 mplist_get ((MPlist *) mplist_get (command_list, Mt),
1931 M17N_OBJECT_UNREF (plist);
1932 mplist_put (per_lang, name, pl);
1937 /* Input method variable handler. */
1939 /* List of all variables.
1940 (LANG:(IM-NAME:(VAR ...) ...) ...) ...
1941 VAR is VAR-NAME:(mtext:DESCRIPTION TYPE:VALUE ...)) */
1943 static MPlist *variable_list;
1946 parse_variable_list (MPlist *plist)
1948 MPlist *val = mplist (), *pl, *p;
1950 /* PLIST ::= (sym:VAR mtext:DESCRIPTION TYPE:INIT-VAL ...) ... */
1951 MPLIST_DO (plist, plist)
1957 if (! MPLIST_PLIST_P (plist))
1959 pl = MPLIST_PLIST (plist);
1960 if (! MPLIST_SYMBOL_P (pl))
1962 var = MPLIST_SYMBOL (pl);
1963 pl = MPLIST_NEXT (pl);
1964 mt = get_description_advance (pl);
1965 if (! mt || MPLIST_TAIL_P (pl))
1967 this_val = mplist ();
1968 mplist_add (this_val, Mtext, mt);
1969 M17N_OBJECT_UNREF (mt);
1970 type = MPLIST_KEY (pl);
1971 mplist_add (this_val, type, MPLIST_VAL (pl));
1972 MPLIST_DO (pl, MPLIST_NEXT (pl))
1974 if (type != MPLIST_KEY (pl)
1975 && (type != Minteger || ! MPLIST_PLIST_P (pl)))
1977 if (MPLIST_PLIST_P (pl))
1979 MPLIST_DO (p, MPLIST_PLIST (pl))
1980 if (! MPLIST_INTEGER_P (p))
1982 if (! MPLIST_TAIL_P (p))
1985 mplist_add (this_val, MPLIST_KEY (pl), MPLIST_VAL (pl));
1988 mplist_put (val, var, this_val);
1995 get_variable_list (MSymbol language, MSymbol name)
2000 if (language == Mnil || name == Mnil)
2001 MERROR (MERROR_IM, NULL);
2002 if (! variable_list)
2003 variable_list = mplist ();
2004 per_lang = mplist_get (variable_list, language);
2007 plist = mplist_find_by_key (per_lang, name);
2009 return (MPLIST_VAL (plist));
2013 per_lang = mplist ();
2014 mplist_add (variable_list, language, per_lang);
2016 plist = load_im_info (language, name, M_variable);
2017 if (! plist || mplist_key (plist) == Mnil)
2021 mplist_add (per_lang, name, plist);
2024 pl = parse_variable_list (mplist_value (plist));
2025 M17N_OBJECT_UNREF (plist);
2026 mplist_put (per_lang, name, pl);
2031 input_method_hook (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
2033 MPlist *plist, *pl, *p;
2034 char path[PATH_MAX];
2036 /* Cancel the hook. */
2037 msymbol_put (tag0, M_database_hook, NULL);
2040 mplist_push (load_im_info_keys, M_description, Mt);
2041 MPLIST_DO (plist, mdatabase__dir_list)
2043 char *dirname = (char *) MPLIST_VAL (plist);
2045 DIR *dir = opendir (dirname);
2050 dirlen = strlen (dirname);
2051 strcpy (path, dirname);
2052 while ((dp = readdir (dir)) != NULL)
2054 /* We can't trust dp->d_nameln. */
2055 int len = strlen (dp->d_name);
2058 if (len > 4 && memcmp (dp->d_name + len - 4, ".mim", 4) == 0)
2060 strcpy (path + dirlen, dp->d_name);
2061 fp = fopen (path, "r");
2064 pl = mplist__from_file (fp, load_im_info_keys);
2068 if (MPLIST_PLIST_P (pl))
2070 p = MPLIST_PLIST (pl);
2071 p = MPLIST_NEXT (p);
2072 if (MPLIST_SYMBOL_P (p))
2074 tag1 = MPLIST_VAL (p);
2075 p = MPLIST_NEXT (p);
2076 if (MPLIST_SYMBOL_P (p))
2078 tag2 = MPLIST_VAL (p);
2079 mdatabase_define (tag0, tag1, tag2, tag3,
2084 M17N_OBJECT_UNREF (pl);
2090 mplist_pop (load_im_info_keys);
2094 /* Support functions for mdebug_dump_im. */
2097 dump_im_map (MPlist *map_list, int indent)
2100 MSymbol key = MPLIST_KEY (map_list);
2101 MIMMap *map = (MIMMap *) MPLIST_VAL (map_list);
2103 prefix = (char *) alloca (indent + 1);
2104 memset (prefix, 32, indent);
2105 prefix[indent] = '\0';
2107 fprintf (stderr, "(\"%s\" ", msymbol_name (key));
2108 if (map->map_actions)
2109 mdebug_dump_plist (map->map_actions, indent + 2);
2112 MPLIST_DO (map_list, map->submaps)
2114 fprintf (stderr, "\n%s ", prefix);
2115 dump_im_map (map_list, indent + 2);
2118 if (map->branch_actions)
2120 fprintf (stderr, "\n%s (branch\n%s ", prefix, prefix);
2121 mdebug_dump_plist (map->branch_actions, indent + 4);
2122 fprintf (stderr, ")");
2124 fprintf (stderr, ")");
2129 dump_im_state (MIMState *state, int indent)
2134 prefix = (char *) alloca (indent + 1);
2135 memset (prefix, 32, indent);
2136 prefix[indent] = '\0';
2138 fprintf (stderr, "(%s", msymbol_name (state->name));
2139 if (state->map->submaps)
2141 MPLIST_DO (map_list, state->map->submaps)
2143 fprintf (stderr, "\n%s ", prefix);
2144 dump_im_map (map_list, indent + 2);
2147 fprintf (stderr, ")");
2156 = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2157 "BackSpace", "Tab", "Linefeed", "Clear", NULL, "Return", NULL, NULL,
2158 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2159 NULL, NULL, NULL, "Escape", NULL, NULL, NULL, NULL };
2160 char buf[6], buf2[256];
2164 Minput_method = msymbol ("input-method");
2165 msymbol_put (Minput_method, M_database_hook, (void *) input_method_hook);
2166 Minput_driver = msymbol ("input-driver");
2167 Mtitle = msymbol ("title");
2168 Mmacro = msymbol ("macro");
2169 Mmodule = msymbol ("module");
2170 Mmap = msymbol ("map");
2171 Mstate = msymbol ("state");
2172 Minsert = msymbol ("insert");
2173 Mdelete = msymbol ("delete");
2174 Mmove = msymbol ("move");
2175 Mmark = msymbol ("mark");
2176 Mpushback = msymbol ("pushback");
2177 Mundo = msymbol ("undo");
2178 Mcall = msymbol ("call");
2179 Mshift = msymbol ("shift");
2180 Mselect = msymbol ("select");
2181 Mshow = msymbol ("show");
2182 Mhide = msymbol ("hide");
2183 Mset = msymbol ("set");
2184 Madd = msymbol ("add");
2185 Msub = msymbol ("sub");
2186 Mmul = msymbol ("mul");
2187 Mdiv = msymbol ("div");
2188 Mequal = msymbol ("=");
2189 Mless = msymbol ("<");
2190 Mgreater = msymbol (">");
2192 Minput_preedit_start = msymbol ("input-preedit-start");
2193 Minput_preedit_done = msymbol ("input-preedit-done");
2194 Minput_preedit_draw = msymbol ("input-preedit-draw");
2195 Minput_status_start = msymbol ("input-status-start");
2196 Minput_status_done = msymbol ("input-status-done");
2197 Minput_status_draw = msymbol ("input-status-draw");
2198 Minput_candidates_start = msymbol ("input-candidates-start");
2199 Minput_candidates_done = msymbol ("input-candidates-done");
2200 Minput_candidates_draw = msymbol ("input-candidates-draw");
2201 Minput_set_spot = msymbol ("input-set-spot");
2202 Minput_toggle = msymbol ("input-toggle");
2203 Minput_reset = msymbol ("input-reset");
2205 Mcandidate_list = msymbol_as_managing_key (" candidate-list");
2206 Mcandidate_index = msymbol (" candidate-index");
2208 Minit = msymbol ("init");
2209 Mfini = msymbol ("fini");
2211 M_key_alias = msymbol (" key-alias");
2212 M_description = msymbol ("description");
2213 M_command = msymbol ("command");
2214 M_variable = msymbol ("variable");
2216 Mdetail_text = msymbol_as_managing_key (" detail-text");
2218 load_im_info_keys = mplist ();
2219 plist = mplist_add (load_im_info_keys, Mmap, Mnil);
2220 plist = mplist_add (plist, Mstate, Mnil);
2221 plist = mplist_add (plist, Mmacro, Mnil);
2222 plist = mplist_add (plist, Mmodule, Mnil);
2227 for (i = 0, buf[2] = '@'; i < ' '; i++, buf[2]++)
2229 one_char_symbol[i] = msymbol (buf);
2231 msymbol_put (one_char_symbol[i], M_key_alias, msymbol (key_names[i]));
2233 for (buf[2] = i; i < 127; i++, buf[2]++)
2234 one_char_symbol[i] = msymbol (buf + 2);
2235 one_char_symbol[i++] = msymbol ("Delete");
2241 for (buf[4] = '@'; i < 160; i++, buf[4]++)
2243 one_char_symbol[i] = msymbol (buf);
2244 if (key_names[i - 128])
2246 strcpy (buf2 + 2, key_names[i - 128]);
2247 msymbol_put (one_char_symbol[i], M_key_alias, msymbol (buf2));
2250 for (buf[4] = i - 128; i < 255; i++, buf[4]++)
2251 one_char_symbol[i] = msymbol (buf + 2);
2252 one_char_symbol[i] = msymbol ("M-Delete");
2254 command_list = variable_list = NULL;
2256 minput_default_driver.open_im = open_im;
2257 minput_default_driver.close_im = close_im;
2258 minput_default_driver.create_ic = create_ic;
2259 minput_default_driver.destroy_ic = destroy_ic;
2260 minput_default_driver.filter = filter;
2261 minput_default_driver.lookup = lookup;
2262 minput_default_driver.callback_list = mplist ();
2263 mplist_put (minput_default_driver.callback_list, Minput_reset,
2265 minput_driver = &minput_default_driver;
2272 MPlist *par_lang, *par_im, *p;
2276 MPLIST_DO (par_lang, command_list)
2278 MPLIST_DO (par_im, MPLIST_VAL (par_lang))
2280 MPLIST_DO (p, MPLIST_VAL (par_im))
2281 M17N_OBJECT_UNREF (MPLIST_VAL (p));
2282 M17N_OBJECT_UNREF (MPLIST_VAL (par_im));
2284 M17N_OBJECT_UNREF (MPLIST_VAL (par_lang));
2286 M17N_OBJECT_UNREF (command_list);
2287 command_list = NULL;
2291 MPLIST_DO (par_lang, variable_list)
2293 MPLIST_DO (par_im, MPLIST_VAL (par_lang))
2295 MPLIST_DO (p, MPLIST_VAL (par_im))
2296 M17N_OBJECT_UNREF (MPLIST_VAL (p));
2297 M17N_OBJECT_UNREF (MPLIST_VAL (par_im));
2299 M17N_OBJECT_UNREF (MPLIST_VAL (par_lang));
2301 M17N_OBJECT_UNREF (variable_list);
2302 variable_list = NULL;
2305 if (minput_default_driver.callback_list)
2307 M17N_OBJECT_UNREF (minput_default_driver.callback_list);
2308 minput_default_driver.callback_list = NULL;
2310 if (minput_driver->callback_list)
2312 M17N_OBJECT_UNREF (minput_driver->callback_list);
2313 minput_driver->callback_list = NULL;
2316 M17N_OBJECT_UNREF (load_im_info_keys);
2320 minput__callback (MInputContext *ic, MSymbol command)
2322 if (ic->im->driver.callback_list)
2324 MInputCallbackFunc func
2325 = (MInputCallbackFunc) mplist_get (ic->im->driver.callback_list,
2329 (func) (ic, command);
2334 minput__char_to_key (int c)
2336 if (c < 0 || c >= 0x100)
2339 return one_char_symbol[c];
2343 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
2348 /*** @addtogroup m17nInputMethod */
2353 @name Variables: Predefined symbols for callback commands.
2355 These are the predefined symbols that are used as the @c COMMAND
2356 argument of callback functions of an input method driver (see
2357 #MInputDriver::callback_list ). */
2359 @name ÊÑ¿ô¡§ ¥³¡¼¥ë¥Ð¥Ã¥¯¥³¥Þ¥ó¥ÉÍÑÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë.
2361 ÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Î¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Ë¤ª¤¤¤Æ @c COMMAND °ú¿ô¤È¤·
2362 ¤ÆÍѤ¤¤é¤ì¤ëÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë (#MInputDriver::callback_list »²¾È)¡£
2367 MSymbol Minput_preedit_start;
2368 MSymbol Minput_preedit_done;
2369 MSymbol Minput_preedit_draw;
2370 MSymbol Minput_status_start;
2371 MSymbol Minput_status_done;
2372 MSymbol Minput_status_draw;
2373 MSymbol Minput_candidates_start;
2374 MSymbol Minput_candidates_done;
2375 MSymbol Minput_candidates_draw;
2376 MSymbol Minput_set_spot;
2377 MSymbol Minput_toggle;
2378 MSymbol Minput_reset;
2383 @brief The default driver for internal input methods.
2385 The variable #minput_default_driver is the default driver for
2386 internal input methods.
2388 The member MInputDriver::open_im () searches the m17n database for
2389 an input method that matches the tag \< #Minput_method, $LANGUAGE,
2390 $NAME\> and loads it.
2392 The member MInputDriver::callback_list () is @c NULL. Thus, it is
2393 programmers responsibility to set it to a plist of proper callback
2394 functions. Otherwise, no feedback information (e.g. preedit text)
2395 can be shown to users.
2397 The macro M17N_INIT () sets the variable #minput_driver to the
2398 pointer to this driver so that all internal input methods use it.
2400 Therefore, unless @c minput_driver is set differently, the driver
2401 dependent arguments $ARG of the functions whose name begin with
2402 "minput_" are all ignored. */
2405 @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥǥե©¥ë¥È¥É¥é¥¤¥Ð.
2407 ÆþÎϥɥ饤¥Ð #minput_default_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѤΥǥե©¥ë
2408 ¥È¤Î¥É¥é¥¤¥Ð¤Ç¤¢¤ë¡£
2410 ¥á¥ó¥Ð MInputDriver::open_im () ¤Ï m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹Ã椫¤é¥¿¥°
2411 \< #Minput_method, $LANGUAGE, $NAME\> ¤Ë¹çÃפ¹¤ëÆþÎϥ᥽¥Ã¥É¤òõ¤·¡¢
2414 ¥á¥ó¥Ð MInputDriver::callback_list () ¤Ï @c NULL ¤Ê¤Î¤Ç¡¢¥×¥í¥°¥é
2415 ¥Þ¦¤ÇÀÕǤ¤ò»ý¤Ã¤Æ, ŬÀڤʥ³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤Î plist ¤ËÀßÄꤷ¤Ê¤¯¤Æ
2416 ¤Ï¤Ê¤é¤Ê¤¤¡£¤µ¤â¤Ê¤¤¤È¡¢preedit ¥Æ¥¥¹¥È¤Ê¤É¤Î¥Õ¥£¡¼¥É¥Ð¥Ã¥¯¾ðÊó¤¬
2417 ¥æ¡¼¥¶¤Ëɽ¼¨¤µ¤ì¤Ê¤¤¡£
2419 ¥Þ¥¯¥í M17N_INIT () ¤ÏÊÑ¿ô #minput_driver ¤ò¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó
2420 ¥¿¤ËÀßÄꤷ¡¢Á´¤Æ¤ÎÆâÉôÆþÎϥ᥽¥Ã¥É¤¬¤³¤Î¥É¥é¥¤¥Ð¤ò»È¤¦¤è¤¦¤Ë¤¹¤ë¡£
2422 ¤·¤¿¤¬¤Ã¤Æ¡¢@c minput_driver ¤¬¥Ç¥Õ¥©¥ë¥ÈÃͤΤޤޤǤ¢¤ì¤Ð¡¢minput_
2423 ¤Ç»Ï¤Þ¤ë´Ø¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô $ARG ¤Ï¤¹¤Ù¤Æ̵»ë¤µ¤ì¤ë¡£ */
2425 MInputDriver minput_default_driver;
2429 @brief The driver for internal input methods.
2431 The variable #minput_driver is a pointer to the input method
2432 driver that is used by internal input methods. The macro
2433 M17N_INIT () initializes it to a pointer to #minput_default_driver
2434 (if <m17n<EM></EM>.h> is included) or to #minput_gui_driver (if
2435 <m17n-gui<EM></EM>.h> is included). */
2437 @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥɥ饤¥Ð.
2439 ÊÑ¿ô #minput_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤Æ»ÈÍѤµ¤ì¤Æ¤¤¤ëÆþÎÏ¥á
2440 ¥½¥Ã¥É¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£¥Þ¥¯¥í M17N_INIT () ¤Ï¤³¤Î¥Ý¥¤¥ó
2441 ¥¿¤ò #minput_default_driver (<m17n<EM></EM>.h> ¤¬´Þ¤Þ¤ì¤ë»þ) ¤Þ¤¿¤Ï
2442 #minput_gui_driver ( <m17n-gui<EM></EM>.h> ¤¬´Þ¤Þ¤ì¤ë»þ) ¤Ë½é´ü²½¤¹
2445 MInputDriver *minput_driver;
2447 MSymbol Minput_driver;
2452 @brief Open an input method.
2454 The minput_open_im () function opens an input method that matches
2455 language $LANGUAGE and name $NAME, and returns a pointer to the
2456 input method object newly allocated.
2458 This function at first decides an driver for the input method as
2461 If $LANGUAGE is not #Mnil, the driver pointed by the variable
2462 #minput_driver is used.
2464 If $LANGUAGE is #Mnil and $NAME has #Minput_driver property, the
2465 driver pointed to by the property value is used to open the input
2466 method. If $NAME has no such property, @c NULL is returned.
2468 Then, the member MInputDriver::open_im () of the driver is
2471 $ARG is set in the member @c arg of the structure MInputMethod so
2472 that the driver can refer to it. */
2475 @brief ÆþÎϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë.
2477 ´Ø¿ô minput_open_im () ¤Ï¸À¸ì $LANGUAGE ¤È̾Á° $NAME ¤Ë¹çÃפ¹¤ëÆþ
2478 Îϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤·¡¢¿·¤¿¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿ÆþÎϥ᥽¥Ã¥É¥ª¥Ö¥¸¥§¥¯
2479 ¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
2481 ¤³¤Î´Ø¿ô¤Ï¡¢¤Þ¤ºÆþÎϥ᥽¥Ã¥ÉÍѤΥɥ饤¥Ð¤ò°Ê²¼¤Î¤è¤¦¤Ë¤·¤Æ·èÄꤹ¤ë¡£
2483 $LANGUAGE ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢ÊÑ¿ô #minput_driver ¤Ç»Ø¤µ¤ì¤Æ¤¤¤ë
2486 $LANGUAGE ¤¬ #Mnil ¤Ç¤¢¤ê¡¢$NAME ¤¬ #Minput_driver ¥×¥í¥Ñ¥Æ¥£¤ò»ý
2487 ¤Ä¾ì¹ç¤Ë¤Ï¡¢¤½¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤǻؤµ¤ì¤Æ¤¤¤ëÆþÎϥɥ饤¥Ð¤òÍѤ¤¤ÆÆþ
2488 Îϥ᥽¥Ã¥É¤ò¥ª¡¼¥×¥ó¤¹¤ë¡£$NAME ¤Ë¤½¤Î¤è¤¦¤Ê¥×¥í¥Ñ¥Æ¥£¤¬Ìµ¤«¤Ã¤¿¾ì
2489 ¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
2491 ¼¡¤¤¤Ç¡¢¥É¥é¥¤¥Ð¤Î¥á¥ó¥Ð MInputDriver::open_im () ¤¬¸Æ¤Ð¤ì¤ë¡£
2493 $ARG ¤Ï¡¢¥É¥é¥¤¥Ð¤¬»²¾È¤Ç¤¤ë¤è¤¦¤Ë¡¢¹½Â¤ÂÎ MInputMethod ¤Î¥á¥ó¥Ð
2494 @c arg ¤ËÀßÄꤵ¤ì¤ë¡£
2496 @latexonly \IPAlabel{minput_open} @endlatexonly
2501 minput_open_im (MSymbol language, MSymbol name, void *arg)
2504 MInputDriver *driver;
2507 driver = minput_driver;
2510 driver = (MInputDriver *) msymbol_get (name, Minput_driver);
2512 MERROR (MERROR_IM, NULL);
2515 MSTRUCT_CALLOC (im, MERROR_IM);
2516 im->language = language;
2519 im->driver = *driver;
2520 if ((*im->driver.open_im) (im) < 0)
2531 @brief Close an input method.
2533 The minput_close_im () function closes the input method $IM, which
2534 must have been created by minput_open_im (). */
2537 @brief ÆþÎϥ᥽¥Ã¥É¤ò¥¯¥í¡¼¥º¤¹¤ë.
2539 ´Ø¿ô minput_close_im () ¤Ï¡¢ÆþÎϥ᥽¥Ã¥É $IM ¤ò¥¯¥í¡¼¥º¤¹¤ë¡£¤³¤Î
2540 ÆþÎϥ᥽¥Ã¥É $IM ¤Ï minput_open_im () ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê¤±¤ì
2544 minput_close_im (MInputMethod *im)
2546 (*im->driver.close_im) (im);
2553 @brief Create an input context.
2555 The minput_create_ic () function creates an input context object
2556 associated with input method $IM, and calls callback functions
2557 corresponding to #Minput_preedit_start, #Minput_status_start, and
2558 #Minput_status_draw in this order.
2562 If an input context is successfully created, minput_create_ic ()
2563 returns a pointer to it. Otherwise it returns @c NULL. */
2566 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÀ¸À®¤¹¤ë.
2568 ´Ø¿ô minput_create_ic () ¤ÏÆþÎϥ᥽¥Ã¥É $IM ¤ËÂбþ¤¹¤ëÆþÎÏ¥³¥ó¥Æ¥¯
2569 ¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤·¡¢ #Minput_preedit_start,
2570 #Minput_status_start, #Minput_status_draw ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø
2575 ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤¬À¸À®¤µ¤ì¤¿¾ì¹ç¡¢minput_create_ic () ¤Ï¤½¤ÎÆþÎÏ¥³
2576 ¥ó¥Æ¥¯¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¼ºÇÔ¤·¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤¹¡£
2580 minput_create_ic (MInputMethod *im, void *arg)
2584 MSTRUCT_CALLOC (ic, MERROR_IM);
2587 ic->preedit = mtext ();
2588 ic->candidate_list = NULL;
2589 ic->produced = mtext ();
2590 ic->spot.x = ic->spot.y = 0;
2592 ic->plist = mplist ();
2593 if ((*im->driver.create_ic) (ic) < 0)
2595 M17N_OBJECT_UNREF (ic->preedit);
2596 M17N_OBJECT_UNREF (ic->produced);
2597 M17N_OBJECT_UNREF (ic->plist);
2602 if (im->driver.callback_list)
2604 minput__callback (ic, Minput_preedit_start);
2605 minput__callback (ic, Minput_status_start);
2606 minput__callback (ic, Minput_status_draw);
2615 @brief Destroy an input context.
2617 The minput_destroy_ic () function destroys the input context $IC,
2618 which must have been created by minput_create_ic (). It calls
2619 callback functions corresponding to #Minput_preedit_done,
2620 #Minput_status_done, and #Minput_candidates_done in this order. */
2623 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤òÇ˲õ¤¹¤ë.
2625 ´Ø¿ô minput_destroy_ic () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤òÇ˲õ¤¹¤ë¡£¤³
2626 ¤ÎÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Ï minput_create_ic () ¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¤â¤Î¤Ç¤Ê
2627 ¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£¤³¤Î´Ø¿ô¤Ï#Minput_preedit_done,
2628 #Minput_status_done, #Minput_candidates_done ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò
2633 minput_destroy_ic (MInputContext *ic)
2635 if (ic->im->driver.callback_list)
2637 minput__callback (ic, Minput_preedit_done);
2638 minput__callback (ic, Minput_status_done);
2639 minput__callback (ic, Minput_candidates_done);
2641 (*ic->im->driver.destroy_ic) (ic);
2642 M17N_OBJECT_UNREF (ic->preedit);
2643 M17N_OBJECT_UNREF (ic->produced);
2644 M17N_OBJECT_UNREF (ic->plist);
2651 @brief Filter an input key.
2653 The minput_filter () function filters input key $KEY according to
2654 input context $IC, and calls callback functions corresponding to
2655 #Minput_preedit_draw, #Minput_status_draw, and
2656 #Minput_candidates_draw if the preedit text, the status, and the
2657 current candidate are changed respectively.
2660 If $KEY is filtered out, this function returns 1. In that case,
2661 the caller should discard the key. Otherwise, it returns 0, and
2662 the caller should handle the key, for instance, by calling the
2663 function minput_lookup () with the same key. */
2666 @brief ÆþÎÏ¥¡¼¤ò¥Õ¥£¥ë¥¿¤¹¤ë.
2668 ´Ø¿ô minput_filter () ¤ÏÆþÎÏ¥¡¼ $KEY ¤òÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤Ë±þ
2669 ¤¸¤Æ¥Õ¥£¥ë¥¿¤·¡¢preedit ¥Æ¥¥¹¥È¡¢¥¹¥Æ¡¼¥¿¥¹¡¢¸½»þÅÀ¤Ç¤Î¸õÊ䤬ÊѲ½
2670 ¤·¤¿ºÝ¤Ë¤Ï¤½¤ì¤¾¤ì#Minput_preedit_draw, #Minput_status_draw,
2671 #Minput_candidates_draw ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô¤ò¸Æ¤Ö¡£
2674 $KEY ¤¬¥Õ¥£¥ë¥¿¤µ¤ì¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 1 ¤òÊÖ¤¹¡£¤³¤Î¾ì¹ç¸Æ¤Ó
2675 ½Ð¤·Â¦¤Ï¤³¤Î¥¡¼¤ò¼Î¤Æ¤ë¤Ù¤¤Ç¤¢¤ë¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0 ¤òÊÖ¤·¡¢¸Æ¤Ó
2676 ½Ð¤·Â¦¤Ï¡¢¤¿¤È¤¨¤ÐƱ¤¸¥¡¼¤Ç´Ø¿ô minput_lookup () ¤ò¸Æ¤Ö¤Ê¤É¤·¤Æ¡¢
2677 ¤³¤Î¥¡¼¤ò½èÍý¤¹¤ë¡£
2679 @latexonly \IPAlabel{minput_filter} @endlatexonly
2683 minput_filter (MInputContext *ic, MSymbol key, void *arg)
2690 ret = (*ic->im->driver.filter) (ic, key, arg);
2692 if (ic->im->driver.callback_list)
2694 if (ic->preedit_changed)
2695 minput__callback (ic, Minput_preedit_draw);
2696 if (ic->status_changed)
2697 minput__callback (ic, Minput_status_draw);
2698 if (ic->candidates_changed)
2699 minput__callback (ic, Minput_candidates_draw);
2708 @brief Lookup a text produced in the input context.
2710 The minput_lookup () function looks up a text in the input context
2711 $IC. $KEY must be the same one provided to the previous call of
2714 If a text was produced by the input method, it is concatenated
2717 This function calls #MInputDriver::lookup .
2720 If $KEY was correctly handled by the input method, this function
2721 returns 0. Otherwise, returns -1, even in that case, some text
2722 may be produced in $MT. */
2725 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥ÈÃæ¤Î¥Æ¥¥¹¥È¤Î¸¡º÷.
2727 ´Ø¿ô minput_lookup () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC Ãæ¤Î¥Æ¥¥¹¥È¤ò¸¡º÷¤¹
2728 ¤ë¡£$KEY ¤Ï´Ø¿ôminput_filter () ¤Ø¤ÎľÁ°¤Î¸Æ¤Ó½Ð¤·¤ËÍѤ¤¤é¤ì¤¿¤â¤Î
2729 ¤ÈƱ¤¸¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2731 ¥Æ¥¥¹¥È¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆÀ¸À®¤µ¤ì¤Æ¤¤¤ì¤Ð¡¢¥Æ¥¥¹¥È¤Ï M-text
2734 ¤³¤Î´Ø¿ô¤Ï¡¢#MInputDriver::lookup ¤ò¸Æ¤Ö¡£
2737 $KEY ¤¬ÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤ÆŬÀڤ˽èÍý¤Ç¤¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï 0 ¤òÊÖ¤¹¡£
2738 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£¤³¤Î¾ì¹ç¤Ç¤â $MT ¤Ë²¿¤é¤«¤Î¥Æ¥¥¹¥È¤¬À¸
2739 À®¤µ¤ì¤Æ¤¤¤ë¤³¤È¤¬¤¢¤ë¡£
2741 @latexonly \IPAlabel{minput_lookup} @endlatexonly */
2744 minput_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2746 return (ic ? (*ic->im->driver.lookup) (ic, key, arg, mt) : -1);
2751 @brief Set the spot of the input context.
2753 The minput_set_spot () function set the spot of input context $IC
2754 to coordinate ($X, $Y ) with the height specified by $ASCENT and $DESCENT .
2755 The semantics of these values depend on the input method driver.
2756 $FONTSIZE specfies the fontsize of preedit text in 1/10 point.
2758 For instance, a driver designed to work in a CUI environment may
2759 use $X and $Y as column and row numbers, and ignore $ASCENT and
2760 $DESCENT . A driver designed to work in a window system may
2761 interpret $X and $Y as pixel offsets relative to the origin of the
2762 client window, and may interpret $ASCENT and $DESCENT as the ascent- and
2763 descent pixels of the line at ($X . $Y ).
2765 $MT and $POS is the M-text and the character position at the spot.
2766 $MT may be @c NULL, in which case, the input method cannot get
2767 information about the text around the spot. */
2770 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤Î¥¹¥Ý¥Ã¥È¤òÀßÄꤹ¤ë
2772 ´Ø¿ô minput_set_spot () ¤Ï¡¢ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤Î¥¹¥Ý¥Ã¥È¤ò¡¢ºÂ
2773 ɸ ($X, $Y )¤Ë ¡¢¹â¤µ $ASCENT¡¢ $DESCENT ¤ÇÀßÄꤹ¤ë¡£ ¤³¤ì¤é¤ÎÃͤÎ
2774 °ÕÌ£¤ÏÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë¡£$FONTSIZE ¤Ïpreedit ¥Æ¥¥¹¥È
2775 ¤Î¥Õ¥©¥ó¥È¥µ¥¤¥º¤ò 1/10 ¥Ý¥¤¥ó¥Èñ°Ì¤Ç»ØÄꤹ¤ë¡£
2777 ¤¿¤È¤¨¤Ð CUI ´Ä¶¤ÇÆ°ºî¤¹¤ë¥É¥é¥¤¥Ð¤Ï $X ¤È $Y ¤ò¤½¤ì¤¾¤ìÎó¤È¹Ô¤Î
2778 ÈÖ¹æ¤È¤·¤ÆÍѤ¤¡¢$ASCENT ¤È $DESCENT ¤ò̵»ë¤¹¤ë¤«¤â¤·¤ì¤Ê¤¤¡£ ¤Þ¤¿
2779 ¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥àÍѤΥɥ饤¥Ð¤Ï $X ¤È $Y ¤ò¥¯¥é¥¤¥¢¥ó¥È¥¦¥£¥ó¥É¥¦
2780 ¤Î¸¶ÅÀ¤«¤é¤Î¥ª¥Õ¥»¥Ã¥È¤ò¥Ô¥¯¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¤¡¢
2781 $ASCENT ¤È $DESCENT ¤ò ($X . $Y ) ¤ÎÎó¤Î¥¢¥»¥ó¥È¤È¥Ç¥£¥»¥ó¥È¤ò¥Ô¥¯
2782 ¥»¥ëñ°Ì¤Çɽ¤·¤¿¤â¤Î¤È¤·¤Æ°·¤¦¤«¤â¤·¤ì¤Ê¤¤¡£
2784 $MT ¤È $POS ¤Ï¤½¤Î¥¹¥Ý¥Ã¥È¤Î M-text ¤Èʸ»ú°ÌÃ֤Ǥ¢¤ë¡£$MT ¤Ï @c
2785 NULL ¤Ç¤â¤è¤¯¡¢¤½¤Î¾ì¹ç¤Ë¤ÏÆþÎϥ᥽¥Ã¥É¤Ï¥¹¥Ý¥Ã¥È¼þÊդΥƥ¥¹¥È¤Ë
2786 ´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë¤³¤È¤¬¤Ç¤¤Ê¤¤¡£
2790 minput_set_spot (MInputContext *ic, int x, int y,
2791 int ascent, int descent, int fontsize,
2796 ic->spot.ascent = ascent;
2797 ic->spot.descent = descent;
2798 ic->spot.fontsize = fontsize;
2801 if (ic->im->driver.callback_list)
2802 minput__callback (ic, Minput_set_spot);
2807 @brief Toggle input method.
2809 The minput_toggle () function toggles the input method associated
2810 with input context $IC. */
2812 @brief ÆþÎϥ᥽¥Ã¥É¤òÀÚÂؤ¨¤ë.
2814 ´Ø¿ô minput_toggle () ¤ÏÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤ËÂбþÉÕ¤±¤é¤ì¤¿ÆþÎÏ
2815 ¥á¥½¥Ã¥É¤ò¥È¥°¥ë¤¹¤ë¡£
2819 minput_toggle (MInputContext *ic)
2821 if (ic->im->driver.callback_list)
2822 minput__callback (ic, Minput_toggle);
2823 ic->active = ! ic->active;
2827 @brief Reset an input context.
2829 The minput_reset_ic () function resets input context $IC by
2830 calling a callback function corresponding to #Minput_reset. It
2831 actually shifts the state to the initial one, and thus the current
2832 preediting text (if any) is committed. If necessary, a program
2833 can extract that committed text by calling minput_lookup () just
2834 after the call of minput_reset_ic (). In that case, the arguments
2835 @c KEY and @c ARG of minput_lookup () are ignored. */
2837 @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤ò¥ê¥»¥Ã¥È¤¹¤ë.
2839 ´Ø¿ô minput_reset_ic () ¤Ï #Minput_reset ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø
2840 ¿ô¤ò¸Æ¤Ö¤³¤È¤Ë¤è¤Ã¤ÆÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤ò¥ê¥»¥Ã¥È¤¹¤ë¡£¤³¤ì¤Ï¼Â
2841 ºÝ¤ÏÆþÎϥ᥽¥Ã¥É¤ò½é´ü¾õÂ֤˥·¥Õ¥È¤µ¤»¤ë¡£¤·¤¿¤¬¤Ã¤Æ¡¢¤â¤·¸½ºßÆþÎÏ
2842 Ãæ¤Î¥Æ¥¥¹¥È¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤Ï¥³¥ß¥Ã¥È¤µ¤ì¤ë¡£É¬Íפʤ饢¥×¥ê¥±¡¼¥·¥ç
2843 ¥ó¥×¥í¥°¥é¥à¤Ï minput_lookup () ¤òÆɤó¤Ç¤½¤Î¥³¥ß¥Ã¥È¤µ¤ì¤¿¥Æ¥¥¹¥È
2844 ¤ò¼è¤ê½Ð¤»¤ë¡£¤½¤ÎºÝ¡¢minput_lookup () ¤Î°ú¿ô @c KEY ¤È @c ARG ¤Ï
2847 minput_reset_ic (MInputContext *ic)
2849 if (ic->im->driver.callback_list)
2850 minput__callback (ic, Minput_reset);
2855 @brief Key of a text property for detailed description.
2857 The symbol #Mdetail_text is a managing key usually used for a
2858 text property whose value is an M-text that contains detailed
2860 MSymbol Mdetail_text;
2863 @brief Get description text of an input method
2865 The minput_get_description () function returns an M-text that
2866 briefly describs the input method specified by $LANGUAGE and
2867 $NAME. The returned M-text may have a text property, from its
2868 beginning to end, #Mdetail_text whose value is an M-text
2869 describing the input method in more detail.
2872 If the specified input method has a description text, a pointer to
2873 #MText is returned. A caller have to free it by m17n_object_unref ().
2874 If the input method does not have a description text, @c NULL is
2878 minput_get_description (MSymbol language, MSymbol name)
2880 MPlist *plist = load_im_info (language, name, M_description);
2886 if (! MPLIST_PLIST_P (plist))
2888 M17N_OBJECT_UNREF (plist);
2891 pl = MPLIST_PLIST (plist);
2892 while (! MPLIST_TAIL_P (pl) && ! MPLIST_MTEXT_P (pl))
2893 pl = MPLIST_NEXT (pl);
2894 if (MPLIST_MTEXT_P (pl))
2895 mt = get_description_advance (pl);
2896 M17N_OBJECT_UNREF (plist);
2901 @brief Get information about input method commands
2903 The minput_get_commands () function returns information about
2904 input method commands of the input method specified by $LANGUAGE
2905 and $NAME. An input method command is a pseudo key event to which
2906 one or more actual input key sequences are assigned.
2908 There are two kinds of commands, global and local. Global
2909 commands are used by multiple input methods for the same purpose,
2910 and have global key assignments. Each input method may locally
2911 change key assignments for glabal commands. Local commands are
2912 used only in a specific input method, and have only local key
2915 Global key assignments for a global command are effective only
2916 when the current input method does not have local key assignments
2919 If $NAME is #Mnil, information about global commands is returned.
2920 In this case $LANGUAGE is ignored.
2922 If $NAME is not #Mnil, information about those commands that have
2923 local key assignments in the input method specified by $LANGUAGE
2924 and $NAME is returned.
2927 If no input method commands are found, this function returns @c NULL.
2929 Otherwise, a pointer to a plist is returned. The key of each
2930 element in the plist is a symbol representing a command, and the
2931 value is a plist of the form COMMAND-INFO (see below).
2933 The first element of COMMAND-INFO has the key #Mtext, and the
2934 value is an M-text describing the command briefly. This M-text
2935 may have a text property whose key is #Mdetail_text and whose
2936 value is an M-text describing the command in more detail.
2938 If there are no more elements, that means no key sequences are
2939 assigned to the command. Otherwise, each of the remaining
2940 elements has the key #Mplist, and the value is a plist whose keys are
2941 #Msymbol and values are symbols representing input keys, which are
2942 currently assigned to the command.
2944 As the returned plist is kept in the library, the caller must not
2945 modify nor free it. */
2948 minput_get_commands (MSymbol language, MSymbol name)
2950 MPlist *plist = get_command_list (language, name);
2952 return (! plist || MPLIST_TAIL_P (plist) ? NULL : plist);
2956 @brief Assign a key sequence to an input method command
2958 The minput_assign_command_keys () function assigns input key
2959 sequence $KEYSEQ to input method command $COMMAND for the input
2960 method specified by $LANGUAGE and $NAME. If $NAME is #Mnil, the
2961 key sequence is assigned globally no matter what $LANGUAGE is.
2962 Otherwise the key sequence is assigned locally.
2964 Each element of $KEYSEQ must have the key $Msymbol and the value
2965 must be a symbol representing an input key.
2967 $KEYSEQ may be @c NULL, in which case, all assignments are deleted
2968 globally or locally.
2970 This assignment gets effective in a newly opened input method.
2973 If the operation was successful, 0 is returned. Otherwise -1 is
2974 returned, and #merror_code is set to #MERROR_IM. */
2977 minput_assign_command_keys (MSymbol language, MSymbol name,
2978 MSymbol command, MPlist *keyseq)
2980 MPlist *plist, *pl, *p;
2982 if (check_command_keyseq (keyseq) < 0
2983 || ! (plist = get_command_list (language, name)))
2984 MERROR (MERROR_IM, -1);
2985 pl = mplist_get (plist, command);
2988 pl = MPLIST_NEXT (pl);
2990 while ((p = mplist_pop (pl)))
2991 M17N_OBJECT_UNREF (p);
2994 keyseq = mplist_copy (keyseq);
2995 mplist_push (pl, Mplist, keyseq);
2996 M17N_OBJECT_UNREF (keyseq);
3002 MERROR (MERROR_IM, -1);
3005 pl = get_command_list (Mnil, Mnil); /* Get global commands. */
3006 pl = mplist_get (pl, command);
3008 MERROR (MERROR_IM, -1);
3010 mplist_add (p, Mtext, mplist_value (pl));
3011 keyseq = mplist_copy (keyseq);
3012 mplist_add (p, Mplist, keyseq);
3013 M17N_OBJECT_UNREF (keyseq);
3014 mplist_push (plist, command, p);
3020 @brief Get a list of variables of an input method
3022 The minput_get_variables () function returns a plist (#MPlist) of
3023 variables used to control the behavior of the input method
3024 specified by $LANGUAGE and $NAME. The key of an element of the
3025 plist is a symbol representing a variable, and the value is a
3026 plist of the form VAR-INFO (see below) carrying the information
3029 The first element of VAR-INFO has the key #Mtext, and the value is
3030 an M-text describing the variable briefly. This M-text may have a
3031 text property #Mdetail_text whose value is an M-text describing
3032 the variable in more detail.
3034 The second element of VAR-INFO is for the value of the variable.
3035 The key is #Minteger, #Msymbol, or #Mtext, and the value is an
3036 intetger, a symbol, or an M-text, respectively. The variable is
3037 set to this value when an input context is created for the input
3040 If there are no more elements, the variable can take any value
3041 that matches with the above type. Otherwise, the remaining
3042 elements of VAR-INFO are to specify valid values of the variable.
3044 If the type of the variable is integer, the third and later elements
3045 have the key #Minteger or #Mplist. If it is #Minteger, the value
3046 is a valid integer value. If it is #Mplist, the value is a plist
3047 of two of elements. Both of them have the key #Minteger, and
3048 values are the minimum and maximum bounds of the valid value
3051 If the type of the variable is symbol or M-text, the third and
3052 later elements of the plist have the key #Msymbol or #Mtext,
3053 respectively, and the value must be a valid one.
3055 For instance, suppose an input method has the following variables:
3057 <li> name:intvar, description:"value is an integer",
3058 initial value:0, value-range:0..3,10,20
3060 <li> name:symvar, description:"value is a symbol",
3061 initial value:nil, value-range:a, b, c, nil
3063 <li> name:txtvar, description:"value is an M-text",
3064 initial value:empty text, no value-range (i.e. any text)
3066 Then, the returned plist has this form ('X:Y' means X is a key and Y is
3067 a value, and '(...)' means a plist):
3070 plist:(intvar:(mtext:"value is an integer"
3072 plist:(integer:0 integer:3)
3075 symvar:(mtext:"value is a symbol"
3081 txtvar:(mtext:"value is an M-text"
3086 If the input method uses any variables, a pointer to #MPlist is
3087 returned. As the plist is kept in the library, a caller must not
3088 modify nor free it. If the input method does not use any
3089 variable, @c NULL is returned. */
3092 minput_get_variables (MSymbol language, MSymbol name)
3094 MPlist *plist = get_variable_list (language, name);
3096 return (! plist || MPLIST_TAIL_P (plist) ? NULL : plist);
3100 @brief Set the initial value of an input method variable
3102 The minput_set_variable () function sets the initial value of
3103 input method variable $VARIABLE to $VALUE for the input method
3104 specified by $LANGUAGE and $NAME.
3106 By default, the initial value is 0.
3108 This setting gets effective in a newly opened input method.
3111 If the operation was successful, 0 is returned. Otherwise -1 is
3112 returned, and #merror_code is set to #MERROR_IM. */
3115 minput_set_variable (MSymbol language, MSymbol name,
3116 MSymbol variable, void *value)
3118 MPlist *plist, *val_element, *range_element;
3121 if (language == Mnil || name == Mnil)
3122 MERROR (MERROR_IM, -1);
3123 plist = get_variable_list (language, name);
3125 MERROR (MERROR_IM, -1);
3126 plist = (MPlist *) mplist_get (plist, variable);
3128 MERROR (MERROR_IM, -1);
3129 val_element = MPLIST_NEXT (plist);
3130 type = MPLIST_KEY (val_element);
3131 range_element = MPLIST_NEXT (val_element);
3133 if (! MPLIST_TAIL_P (range_element))
3135 if (type == Minteger)
3137 int val = (int) value, this_val;
3139 MPLIST_DO (plist, range_element)
3141 this_val = (int) MPLIST_VAL (plist);
3142 if (MPLIST_PLIST_P (plist))
3144 int min_bound, max_bound;
3145 MPlist *pl = MPLIST_PLIST (plist);
3147 min_bound = (int) MPLIST_VAL (pl);
3148 pl = MPLIST_NEXT (pl);
3149 max_bound = (int) MPLIST_VAL (pl);
3150 if (val >= min_bound && val <= max_bound)
3153 else if (val == this_val)
3156 if (MPLIST_TAIL_P (plist))
3157 MERROR (MERROR_IM, -1);
3159 else if (type == Msymbol)
3161 MPLIST_DO (plist, range_element)
3162 if (MPLIST_SYMBOL (plist) == (MSymbol) value)
3164 if (MPLIST_TAIL_P (plist))
3165 MERROR (MERROR_IM, -1);
3167 else /* type == Mtext */
3169 MPLIST_DO (plist, range_element)
3170 if (mtext_cmp (MPLIST_MTEXT (plist), (MText *) value) == 0)
3172 if (MPLIST_TAIL_P (plist))
3173 MERROR (MERROR_IM, -1);
3174 M17N_OBJECT_REF (value);
3178 mplist_set (val_element, type, value);
3184 /*** @addtogroup m17nDebug */
3190 @brief Dump an input method.
3192 The mdebug_dump_im () function prints the input method $IM in a
3193 human readable way to the stderr. $INDENT specifies how many
3194 columns to indent the lines but the first one.
3197 This function returns $IM. */
3199 @brief ÆþÎϥ᥽¥Ã¥É¤ò¥À¥ó¥×¤¹¤ë.
3201 ´Ø¿ô mdebug_dump_im () ¤ÏÆþÎϥ᥽¥Ã¥É $IM ¤ò stderr ¤Ë¿Í´Ö¤Ë²ÄÆɤÊ
3202 ·Á¤Ç°õºþ¤¹¤ë¡£$INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£
3205 ¤³¤Î´Ø¿ô¤Ï $IM ¤òÊÖ¤¹¡£ */
3208 mdebug_dump_im (MInputMethod *im, int indent)
3210 MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
3213 prefix = (char *) alloca (indent + 1);
3214 memset (prefix, 32, indent);
3215 prefix[indent] = '\0';
3217 fprintf (stderr, "(input-method %s %s ", msymbol_name (im->language),
3218 msymbol_name (im->name));
3219 mdebug_dump_mtext (im_info->title, 0, 0);
3220 if (im->name != Mnil)
3224 MPLIST_DO (state, im_info->states)
3226 fprintf (stderr, "\n%s ", prefix);
3227 dump_im_state (MPLIST_VAL (state), indent + 2);
3230 fprintf (stderr, ")");