(mwin__parse_event): Fix for non-ASCII keys.
[m17n/m17n-lib.git] / src / input-gui.c
1 /* input-gui.c -- gui-based input method module.
2    Copyright (C) 2003, 2004
3      National Institute of Advanced Industrial Science and Technology (AIST)
4      Registration Number H15PRO112
5
6    This file is part of the m17n library.
7
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.
12
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.
17
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
21    02111-1307, USA.  */
22
23 /***en
24     @addtogroup m17nInputMethodWin
25     @brief Input method support on window systems.
26
27     The input driver @c minput_gui_driver is provided for internal
28     input methods that is useful on window systems.  It displays
29     preedit text and status text at the inputting spot.  See the
30     documentation of @c minput_gui_driver for more details.
31
32     In the m17n-X library, the foreign input method of name @c Mxim is
33     provided.  It uses XIM (X Input Method) as a background input
34     engine.  The symbol @c Mxim has a property @c Minput_driver whose
35     value is a pointer to the input driver @c minput_xim_driver.  See
36     the documentation of @c minput_xim_driver for more details.  */
37
38 /***ja
39     @addtogroup m17nInputMethodWin
40     @brief ¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥à¾å¤ÎÆþÎϥ᥽¥Ã¥É¤Î¥µ¥Ý¡¼¥È.
41
42     ÆþÎϥɥ饤¥Ð @c minput_gui_driver ¤Ï¡¢¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥à¾å¤ÇÍѤ¤¤é
43     ¤ì¤ëÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѤǤ¢¤ë¡£¤³¤Î¥É¥é¥¤¥Ð¤ÏÆþÎÏ¥¹¥Ý¥Ã¥È¤Ë preedit 
44     ¥Æ¥­¥¹¥È¤È status ¥Æ¥­¥¹¥È¤òɽ¼¨¤¹¤ë¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï @c
45     minput_gui_driver ¤ÎÀâÌÀ¤ò»²¾È¤Î¤³¤È¡£
46
47     m17n-X ¥é¥¤¥Ö¥é¥ê¤Ï¡¢@c Mxim ¤È¸À¤¦Ì¾Á°¤ò»ý¤Ä³°ÉôÆþÎϥ᥽¥Ã¥É¤òÄó
48     ¶¡¤·¤Æ¤¤¤ë¡£¤³¤ì¤Ï XIM (X Input Method) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤ÎÆþÎÏ¥¨
49     ¥ó¥¸¥ó¤È¤·¤ÆÍøÍѤ¹¤ë¡£¥·¥ó¥Ü¥ë @c Mxim ¤Ï @c Minput_driver ¤È¤¤¤¦
50     ¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤ª¤ê¡¢¤½¤ÎÃͤÏÆþÎϥɥ饤¥Ð @c minput_xim_driver 
51     ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£ ¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï @c minput_xim_driver ¤ÎÀâÌÀ¤ò
52     »²¾È¤Î¤³¤È¡£  */
53
54 /*=*/
55
56 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
57 /*** @addtogroup m17nInternal
58      @{ */
59
60 #include <string.h>
61 #include <ctype.h>
62
63 #include "config.h"
64 #include "m17n-gui.h"
65 #include "m17n-misc.h"
66 #include "internal.h"
67 #include "internal-gui.h"
68 #include "input.h"
69
70 typedef struct
71 {
72   MDrawWindow win;
73   MDrawMetric geometry;
74   MDrawControl control;
75   int mapped;
76 } MInputGUIWinInfo;
77
78 typedef struct
79 {
80   MInputContextInfo *ic_info;
81
82   MFrame *frame;
83   /* <geometry>.x and <geometry>.y are not used.  */
84   MInputGUIWinInfo client;
85   /* In the following members, <geometry> is relative to <client>.  */
86   MInputGUIWinInfo focus;
87   MInputGUIWinInfo preedit;
88   MInputGUIWinInfo status;
89   MInputGUIWinInfo candidates;
90 } MInputGUIContextInfo;
91
92 static MFace *status_face;
93 static MFaceBoxProp face_box_prop;
94
95 static int
96 win_create_ic (MInputContext *ic)
97 {
98   MInputGUIContextInfo *win_ic_info;
99   MInputGUIArgIC *win_info = (MInputGUIArgIC *) ic->arg;
100   MFrame *frame = win_info->frame;
101
102   if ((*minput_default_driver.create_ic) (ic) < 0)
103     return -1;
104
105   MSTRUCT_CALLOC (win_ic_info, MERROR_IM);
106   win_ic_info->ic_info = (MInputContextInfo *) ic->info;
107   win_ic_info->frame = frame;
108   win_ic_info->client.win = win_info->client;
109   (*frame->driver->window_geometry) (frame, win_info->client, win_info->client,
110                          &win_ic_info->client.geometry);
111   win_ic_info->focus.win = win_info->focus;
112   (*frame->driver->window_geometry) (frame, win_info->focus, win_info->client,
113                          &win_ic_info->focus.geometry);
114
115   win_ic_info->preedit.win = (*frame->driver->create_window) (frame, win_info->client);
116   win_ic_info->preedit.control.two_dimensional = 1;
117   win_ic_info->preedit.control.as_image = 0;
118   win_ic_info->preedit.control.with_cursor = 1;
119   win_ic_info->preedit.control.cursor_width = 1;
120   win_ic_info->preedit.control.enable_bidi = 1;
121   win_ic_info->preedit.geometry.x = -1;
122   win_ic_info->preedit.geometry.y = -1;
123
124   win_ic_info->status.win = (*frame->driver->create_window) (frame, win_info->client);
125   win_ic_info->status.control.as_image = 1;
126   win_ic_info->status.control.enable_bidi = 1;
127
128   win_ic_info->candidates.win = (*frame->driver->create_window) (frame, win_info->client);
129   win_ic_info->candidates.control.as_image = 1;
130
131   ic->info = win_ic_info;
132
133   return 0;
134 }
135
136 static void
137 win_destroy_ic (MInputContext *ic)
138 {
139   MInputGUIContextInfo *win_ic_info = (MInputGUIContextInfo *) ic->info;
140   MInputContextInfo *ic_info = (MInputContextInfo *) win_ic_info->ic_info;
141   MFrame *frame = win_ic_info->frame;
142
143   (*frame->driver->destroy_window) (frame, win_ic_info->preedit.win);
144   (*frame->driver->destroy_window) (frame, win_ic_info->status.win);
145   (*frame->driver->destroy_window) (frame, win_ic_info->candidates.win);
146   ic->info = ic_info;
147   (*minput_default_driver.destroy_ic) (ic);
148   free (win_ic_info);
149 }
150
151 static int
152 win_filter (MInputContext *ic, MSymbol key, void *arg)
153 {
154   MInputGUIContextInfo *win_ic_info = (MInputGUIContextInfo *) ic->info;
155   MInputContextInfo *ic_info = (MInputContextInfo *) win_ic_info->ic_info;
156   int ret;
157
158   if (! ic
159       || ! ic->active)
160     return 0;
161
162   if (key == Mnil)
163     {
164       if (! arg)
165         return 0;
166       key = minput_event_to_key (win_ic_info->frame, arg);
167       if (key == Mnil)
168         return 1;
169     }
170   ic->info = ic_info;
171   ret = (*minput_default_driver.filter) (ic, key, arg);
172   ic->info = win_ic_info;
173   return ret;
174 }
175
176 static void
177 adjust_window_and_draw (MFrame *frame, MInputContext *ic, MText *mt, int type)
178 {
179   MInputGUIContextInfo *win_ic_info = (MInputGUIContextInfo *) ic->info;
180   MDrawControl *control;
181   MDrawWindow win;
182   MDrawMetric *geometry, physical, logical;
183   int xoff = win_ic_info->focus.geometry.x;
184   int yoff = win_ic_info->focus.geometry.y;
185   int x0, x1, y0, y1;
186   int len = mtext_nchars (mt);
187
188   if (type == 0)
189     {
190       win = win_ic_info->preedit.win;
191       control = &win_ic_info->preedit.control;
192       geometry = &win_ic_info->preedit.geometry;
193       len++;
194     }
195   else if (type == 1)
196     {
197       win = win_ic_info->status.win;
198       control = &win_ic_info->status.control;
199       geometry = &win_ic_info->status.geometry;
200     }
201   else
202     {
203       win = win_ic_info->candidates.win;
204       control = &win_ic_info->candidates.control;
205       geometry = &win_ic_info->candidates.geometry;
206     }
207
208   mdraw_text_extents (frame, mt, 0, len, control, &physical, &logical, NULL);
209   x0 = physical.x, x1 = x0 + physical.width;
210   y0 = physical.y, y1 = y0 + physical.height;
211   if (x0 > logical.x)
212     x0 = logical.x;
213   if (x1 < logical.x + logical.width)
214     x1 = logical.x + logical.width;
215   if (y0 > logical.y)
216     y0 = logical.y;
217   if (y1 < logical.y + logical.height)
218     y1 = logical.y + logical.height;
219   physical.width = x1 - x0;
220   physical.height = y1 - y0;
221   physical.x = xoff + ic->spot.x;
222   if (physical.x + physical.width > win_ic_info->client.geometry.width)
223     physical.x = win_ic_info->client.geometry.width - physical.width;
224   if (type == 0)
225     {
226       if (len <= 1)
227         {
228           physical.height = physical.width = 1;
229           physical.x = physical.y = -1;
230         }
231       else
232         {
233           if (y0 > - ic->spot.ascent)
234             {
235               physical.height += y0 + ic->spot.ascent;
236               y0 = - ic->spot.ascent;
237             }
238           if (y1 < ic->spot.descent)
239             {
240               physical.height += ic->spot.descent - y1;
241             }
242           physical.y = yoff + ic->spot.y + y0;
243         }
244     }
245   else if (type == 1)
246     {
247       physical.y = yoff + ic->spot.y + ic->spot.descent + 2;
248       if (physical.y + physical.height > win_ic_info->client.geometry.height
249           && yoff + ic->spot.y - ic->spot.ascent - 2 - physical.height >= 0)
250         physical.y = yoff + ic->spot.y - ic->spot.ascent - 2 - physical.height;
251     }
252   else
253     {
254       if (win_ic_info->status.mapped)
255         {
256           /* We assume that status is already drawn.  */
257           if (win_ic_info->status.geometry.y < yoff + ic->spot.y)
258             /* As there was no lower room for status, candidates must also
259                be drawn upper.  */
260             physical.y = win_ic_info->status.geometry.y - 1 - physical.height;
261           else
262             {
263               /* There was a lower room for status.  */
264               physical.y = (win_ic_info->status.geometry.y
265                             + win_ic_info->status.geometry.height
266                             + 1);
267               if (physical.y + physical.height
268                   > win_ic_info->client.geometry.height)
269                 /* But not for candidates.  */
270                 physical.y = (yoff + ic->spot.y - ic->spot.ascent - 1
271                               - physical.height);
272             }
273         }
274       else
275         {
276           physical.y = yoff + ic->spot.y + ic->spot.descent + 2;
277           if ((physical.y + physical.height
278                > win_ic_info->client.geometry.height)
279               && (yoff + ic->spot.y - ic->spot.ascent - 2 - physical.height
280                   >= 0))
281             physical.y = (yoff + ic->spot.y - ic->spot.ascent - 2
282                           - physical.height);
283         }
284     }
285
286   (*frame->driver->adjust_window) (frame, win, geometry, &physical);
287   mdraw_text_with_control (frame, win, -x0, -y0, mt, 0, len, control);
288 }
289
290 static void
291 win_callback (MInputContext *ic, MSymbol command)
292 {
293   MInputGUIContextInfo *win_ic_info = (MInputGUIContextInfo *) ic->info;
294   MFrame *frame = win_ic_info->frame;
295
296   if (command == Minput_preedit_draw)
297     {
298       MText *mt;
299       MFace *face = mface ();
300
301       if (! win_ic_info->preedit.mapped)
302         {
303           (*frame->driver->map_window) (frame, win_ic_info->preedit.win);
304           win_ic_info->preedit.mapped = 1;
305         }
306       win_ic_info->preedit.control.cursor_pos = ic->cursor_pos;
307       if (ic->spot.fontsize)
308         mface_put_prop (face, Msize, (void *) ic->spot.fontsize);
309       mface_merge (face, mface_underline);
310       mtext_push_prop (ic->preedit, 0, mtext_nchars (ic->preedit),
311                        Mface, face);
312       M17N_OBJECT_UNREF (face);
313       if (ic->im->language != Mnil)
314         mtext_put_prop (ic->preedit, 0, mtext_nchars (ic->preedit), Mlanguage,
315                         ic->im->language);
316       if (ic->candidate_list)
317         mtext_push_prop (ic->preedit, ic->candidate_from, ic->candidate_to,
318                          Mface, mface_reverse_video);
319       if (mtext_nchars (ic->produced) == 0)
320         mt = ic->preedit;
321       else
322         {
323           mt = mtext_dup (ic->produced);
324           mtext_cat (mt, ic->preedit);
325           win_ic_info->preedit.control.cursor_pos
326             += mtext_nchars (ic->produced);
327         }
328       adjust_window_and_draw (frame, ic, mt, 0);
329       if (ic->candidate_list)
330         mtext_pop_prop (ic->preedit, 0, mtext_nchars (ic->preedit), Mface);
331       mtext_pop_prop (ic->preedit, 0, mtext_nchars (ic->preedit), Mface);
332       if (mtext_nchars (ic->produced) != 0)
333         M17N_OBJECT_UNREF (mt);
334     }
335   else if (command == Minput_status_draw)
336     {
337       if (! win_ic_info->client.win)
338         return;
339       mtext_put_prop (ic->status, 0, mtext_nchars (ic->status), Mface,
340                       status_face);
341       if (ic->im->language != Mnil)
342         mtext_put_prop (ic->status, 0, mtext_nchars (ic->status), Mlanguage,
343                         ic->im->language);
344       adjust_window_and_draw (frame, ic, ic->status, 1);
345     }
346   else if (command == Minput_candidates_draw)
347     {
348       MPlist *group;
349       MText *mt;
350       int i, len;
351       int from, to;
352
353       if (! ic->candidate_list || ! ic->candidate_show)
354         {
355           if (win_ic_info->candidates.mapped)
356             {
357               (*frame->driver->unmap_window) (frame, win_ic_info->candidates.win);
358               win_ic_info->candidates.mapped = 0;
359             }
360           return;
361         }
362
363       if (! win_ic_info->candidates.mapped)
364         {
365           (*frame->driver->map_window) (frame, win_ic_info->candidates.win);
366           win_ic_info->candidates.mapped = 1;
367         }
368
369       i = 0;
370       group = ic->candidate_list;
371       while (1)
372         {
373           if (mplist_key (group) == Mtext)
374             len = mtext_len (mplist_value (group));
375           else
376             len = mplist_length (mplist_value (group));
377           if (i + len > ic->candidate_index)
378             break;
379           i += len;
380           group = mplist_next (group);
381         }
382
383       mt = mtext ();
384       if (mplist_key (group) == Mtext)
385         {
386           MText *candidates = (MText *) mplist_value (group);
387
388           from = (ic->candidate_index - i) * 2 + 1;
389           to = from + 1;
390           for (i = 0; i < len; i++)
391             {
392               mtext_cat_char (mt, ' ');
393               mtext_cat_char (mt, mtext_ref_char (candidates, i));
394             }
395         }
396       else
397         {
398           MPlist *pl;
399
400           for (pl = (MPlist *) mplist_value (group);
401                i < ic->candidate_index && mplist_key (pl) != Mnil;
402                i++, pl = mplist_next (pl))
403             {
404               mtext_cat_char (mt, ' ');
405               mtext_cat (mt, (MText *) mplist_value (pl));
406             }
407           from = mtext_nchars (mt) + 1;
408           to = from + mtext_nchars ((MText *) mplist_value (pl));
409           for (; mplist_key (pl) != Mnil; pl = mplist_next (pl))
410             {
411               mtext_cat_char (mt, ' ');
412               mtext_cat (mt, (MText *) mplist_value (pl));
413             }
414         }
415       mtext_cat_char (mt, ' ');
416       mtext_push_prop (mt, 0, mtext_nchars (mt), Mface, status_face);
417       mtext_push_prop (mt, from, to, Mface, mface_reverse_video);
418       if (ic->im->language != Mnil)
419         mtext_put_prop (mt, 0, mtext_nchars (mt), Mlanguage, ic->im->language);
420       adjust_window_and_draw (frame, ic, mt, 2);
421       M17N_OBJECT_UNREF (mt);
422     }
423   else if (command == Minput_set_spot)
424     {
425       minput__callback (ic, Minput_preedit_draw);
426       minput__callback (ic, Minput_status_draw);
427       minput__callback (ic, Minput_candidates_draw);
428     }
429   else if (command == Minput_toggle)
430     {
431       if (ic->active)
432         {
433           minput__callback (ic, Minput_preedit_done);
434           minput__callback (ic, Minput_status_done);
435           minput__callback (ic, Minput_candidates_done);
436         }
437       else
438         {
439           minput__callback (ic, Minput_preedit_start);
440           minput__callback (ic, Minput_status_start);
441           minput__callback (ic, Minput_candidates_start);
442         }
443     }
444   else if (command == Minput_preedit_start)
445     {
446     }
447   else if (command == Minput_preedit_done)
448     {
449       if (win_ic_info->preedit.mapped)
450         {
451           (*frame->driver->unmap_window) (frame, win_ic_info->preedit.win);
452           win_ic_info->preedit.mapped = 0;
453         }
454     }
455   else if (command == Minput_status_start)
456     {
457       if (! win_ic_info->status.mapped)
458         {
459           (*frame->driver->map_window) (frame, win_ic_info->status.win);
460           win_ic_info->status.mapped = 1;
461         }
462     }
463   else if (command == Minput_status_done)
464     {
465       if (win_ic_info->status.mapped)
466         {
467           (*frame->driver->unmap_window) (frame, win_ic_info->status.win);
468           win_ic_info->status.mapped = 0;
469         }
470     }
471   else if (command == Minput_candidates_start)
472     {
473       if (! win_ic_info->candidates.mapped)
474         {
475           (*frame->driver->map_window) (frame, win_ic_info->candidates.win);
476           win_ic_info->candidates.mapped = 1;
477         }
478     }
479   else if (command == Minput_candidates_done)
480     {
481       if (win_ic_info->candidates.mapped)
482         {
483           (*frame->driver->unmap_window) (frame, win_ic_info->candidates.win);
484           win_ic_info->candidates.mapped = 0;
485         }
486     }
487 }
488
489 static int
490 win_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
491 {
492   MInputGUIContextInfo *win_ic_info = (MInputGUIContextInfo *) ic->info;
493   MInputContextInfo *ic_info = (MInputContextInfo *) win_ic_info->ic_info;
494   int ret;
495
496   ic->info = ic_info;
497   ret = (*minput_default_driver.lookup) (ic, key, arg, mt);
498   ic->info = win_ic_info;
499   return ret;
500 }
501
502 \f
503
504 int
505 minput__win_init ()
506 {
507   minput_gui_driver = minput_default_driver;
508
509   minput_gui_driver.create_ic = win_create_ic;
510   minput_gui_driver.destroy_ic = win_destroy_ic;
511   minput_gui_driver.filter = win_filter;
512   minput_gui_driver.lookup = win_lookup;
513   {
514     MPlist *plist = mplist ();
515
516     minput_gui_driver.callback_list = plist;
517     plist = mplist_add (plist, Minput_preedit_start, (void *) win_callback);
518     plist = mplist_add (plist, Minput_preedit_draw, (void *) win_callback);
519     plist = mplist_add (plist, Minput_preedit_done, (void *) win_callback);
520     plist = mplist_add (plist, Minput_status_start, (void *) win_callback);
521     plist = mplist_add (plist, Minput_status_draw, (void *) win_callback);
522     plist = mplist_add (plist, Minput_status_done, (void *) win_callback);
523     plist = mplist_add (plist, Minput_candidates_start, (void *) win_callback);
524     plist = mplist_add (plist, Minput_candidates_draw, (void *) win_callback);
525     plist = mplist_add (plist, Minput_candidates_done, (void *) win_callback);
526     plist = mplist_add (plist, Minput_set_spot, (void *) win_callback);
527     plist = mplist_add (plist, Minput_toggle, (void *) win_callback);
528   }
529   minput_driver = &minput_gui_driver;
530
531   face_box_prop.width = 1;
532   face_box_prop.color_top = face_box_prop.color_left
533     = face_box_prop.color_bottom = face_box_prop.color_right
534     = msymbol ("black");
535   face_box_prop.inner_hmargin = face_box_prop.inner_vmargin = 2;
536   face_box_prop.outer_hmargin = face_box_prop.outer_vmargin = 1;
537   status_face = mface ();
538   mface_put_prop (status_face, Mbox, &face_box_prop);
539
540   return 0;
541 }
542
543 void
544 minput__win_fini ()
545 {
546   M17N_OBJECT_UNREF (status_face);
547   if (minput_gui_driver.callback_list)
548     {
549       M17N_OBJECT_UNREF (minput_gui_driver.callback_list);
550       minput_gui_driver.callback_list = NULL;
551     }
552 }
553
554 /*** @} */
555 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
556
557 \f
558 /* External API */
559
560 /*** @addtogroup m17nInputMethodWin */
561 /*** @{ */
562
563 /*=*/
564 /***en
565     @brief Input driver for internal input methods on window systems.
566
567     The input driver @c minput_gui_driver is for internal input
568     methods to be used on window systems.
569
570     It creates sub-windows for a preedit text and a status text, and
571     displays them at the input spot set by the function
572     minput_set_spot ().
573
574     The macro M17N_INIT () set the variable @c minput_driver to the
575     pointer to this driver so that all internal input methods use it.
576
577     Therefore, unless @c minput_driver is changed from the default,
578     the driver dependent arguments to the functions whose name begin
579     with minput_ must are treated as follows.
580
581     The argument $ARG of the function minput_open_im () is ignored.
582
583     The argument $ARG of the function minput_create_ic () must be a
584     pointer to the structure @c MInputGUIArgIC.  See the documentation
585     of @c MInputGUIArgIC for more details.
586
587     If the argument $KEY is @c Mnil, the argument $ARG of the
588     function minput_filter () must be a pointer to the object of type
589     @c XEvent.  In that case, $KEY is generated from $ARG.
590
591     The argument $ARG of the function minput_lookup () must be the
592     same one as that of the function minput_filter (). */
593
594 /***ja
595     @brief ¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥à¤ÎÆâÉôÆþÎϥ᥽¥Ã¥ÉÍÑÆþÎϥɥ饤¥Ð.
596
597     ÆþÎϥɥ饤¥Ð @c minput_gui_driver ¤Ï¡¢¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥à¾å¤ÇÍѤ¤¤é
598     ¤ì¤ëÆþÎϥ᥽¥Ã¥ÉÍѤǤ¢¤ë¡£
599
600     ¤³¤Î¥É¥é¥¤¥Ð¤Ï¡¢´Ø¿ô minput_set_spot () ¤Ë¤è¤Ã¤ÆÀßÄꤵ¤ì¤¿ÆþÎÏ¥¹¥Ý¥Ã
601     ¥È¤Ë preedit ¥Æ¥­¥¹¥ÈÍѤΥµ¥Ö¥¦¥£¥ó¥É¥¦¤È status ¥Æ¥­¥¹¥ÈÍѤΥµ¥Ö
602     ¥¦¥£¥ó¥É¥¦¤òºî¤ê¡¢¤½¤ì¤¾¤ì¤òɽ¼¨¤¹¤ë¡£
603
604     ¥Þ¥¯¥í M17N_INIT () ¤ÏÊÑ¿ô @c minput_driver ¤ò¤³¤Î¥É¥é¥¤¥Ð
605     ¤Ø¤Î¥Ý¥¤¥ó¥¿¤ËÀßÄꤷ¡¢Á´¤Æ¤ÎÆâÉôÆþÎϥ᥽¥Ã¥É¤¬¤³¤Î¥É¥é¥¤¥Ð¤ò»È¤¦¤è
606     ¤¦¤Ë¤¹¤ë¡£
607
608     ¤·¤¿¤¬¤Ã¤Æ¡¢@c minput_driver ¤¬¥Ç¥Õ¥©¥ë¥ÈÃͤΤޤޤǤ¢¤ì¤Ð¡¢minput_ 
609     ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä´Ø¿ô¤Î°ú¿ô¤Î¤¦¤Á¥É¥é¥¤¥Ð°Í¸¤Î¤â¤Î¤Ï°Ê²¼¤Î¤è¤¦¤Ë
610     ¤Ê¤ë¡£
611
612     ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï̵»ë¤µ¤ì¤ë¡£
613
614     ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂΠ@c MInputGUIArgIC ¤Ø
615     ¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï @c MInputGUIArgIC ¤Î
616     ÀâÌÀ¤ò»²¾È¤Î¤³¤È¡£
617
618     ´Ø¿ô minput_filter () ¤Î°ú¿ô $ARG ¤¬ @c Mnil ¤Î¾ì¹ç¡¢ $ARG ¤Ï @c
619     XEvent ·¿¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¤³¤Î¾ì¹ç 
620     $KEY ¤Ï $ARG ¤«¤éÀ¸À®¤µ¤ì¤ë¡£
621
622     ´Ø¿ô minput_lookup () ¤Î°ú¿ô $ARG ¤Ï´Ø¿ô minput_filter () ¤Î°ú¿ô 
623     $ARG ¤ÈƱ¤¸¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ */
624
625 MInputDriver minput_gui_driver;
626
627 /*=*/
628
629 /***en
630     @brief Symbol of the name "xim".
631
632     The variable Mxim is a symbol of name "xim".  It is a name of the
633     input method driver #minput_xim_driver.  */ 
634 /***ja
635     @brief "xim"¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë .
636
637     ÊÑ¿ô Mxim ¤Ï"xim"¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£"xim" ¤ÏÆþÎϥ᥽¥Ã
638     ¥É¥É¥é¥¤¥Ð #minput_xim_driver ¤Î̾Á°¤Ç¤¢¤ë¡£  */ 
639
640 MSymbol Mxim;
641
642 /*=*/
643
644 /***en
645     @brief Convert an event to an input key.
646
647     The minput_event_to_key () function returns the input key
648     corresponding to event $EVENT on $FRAME by a window system
649     dependent manner.
650
651     In the m17n-X library, $EVENT must be a pointer to the structure
652     @c XKeyEvent, and it is handled as below.
653
654     At first, the keysym name of $EVENT is acquired by the function @c
655     XKeysymToString.  Then, the name is modified as below.
656
657     If the name is one of "a" .. "z" and $EVENT has a Shift modifier,
658     the name is converted to "A" .. "Z" respectively, and the Shift
659     modifier is cleared.
660
661     If the name is one byte length and $EVENT has a Control modifier,
662     the byte is bitwise anded by 0x1F and the Control modifier is
663     cleared.
664
665     If $EVENT still has Shift, Control, Meta, Alt, Super, and/or Hyper
666     modifiers, the name is preceded by "S-", "C-", "M-", "A-", "s-",
667     and/or "H-" respectively in this order.
668
669     For instance, if the keysym name is "a" and the event has Shift,
670     Meta, and Hyper modifiers, the resulting name is "H-M-A".
671
672     At last, a symbol who has the name is returned.  */
673
674 /***ja
675     @brief ¥¤¥Ù¥ó¥È¤òÆþÎÏ¥­¡¼¤ËÊÑ´¹¤¹¤ë.
676
677     ´Ø¿ô minput_name_to_key () ¤Ï¡¢$FRAME ¤Î¥¤¥Ù¥ó¥È $EVENT ¤ËÂбþ¤¹¤ë
678     ÆþÎÏ¥­¡¼¤òÊÖ¤¹¡£¤³¤³¤Ç¤Î¡ÖÂбþ¡×¤Ï¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥à°Í¸¤Ç¤¢¤ë¡£
679
680     m17n-X ¥é¥¤¥Ö¥é¥ê¤Î¾ì¹ç¤Ë¤Ï¡¢$EVENT ¤Ï ¹½Â¤ÂΠ@c XKeyEvent ¤Ø¤Î¥Ý
681     ¥¤¥ó¥¿¤Ç¤¢¤ê¡¢¼¡¤Î¤è¤¦¤Ë½èÍý¤µ¤ì¤ë¡£
682
683     ¤Þ¤º¡¢´Ø¿ô @c XKeysymToString ¤Ë¤è¤Ã¤Æ¡¢$EVENT ¤Î keysym Ì¾¤ò¼èÆÀ
684     ¤·¡¢¼¡¤¤¤Ç°Ê²¼¤ÎÊѹ¹¤ò²Ã¤¨¤ë¡£
685
686     Ì¾Á°¤¬ "a" .. "z" ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤Ã¤Æ $EVENT ¤Ë Shift ¥â¥Ç¥£¥Õ¥¡¥¤
687     ¥¢¤¬¤¢¤ì¤Ð¡¢Ì¾Á°¤Ï¤½¤ì¤¾¤ì "A" .. "Z" ¤ËÊÑ´¹¤µ¤ì¡¢Shift ¥â¥Ç¥£¥Õ¥¡
688     ¥¤¥¢¤Ï¼è¤ê½ü¤«¤ì¤ë¡£
689
690     Ì¾Á°¤¬£±¥Ð¥¤¥ÈŤǠ$EVENT ¤Ë Control ¥â¥Ç¥£¥Õ¥¡¥¤¥¢¤¬¤¢¤ì¤Ð¡¢Ì¾Á°
691     ¤È 0x1F ¤ò¥Ó¥Ã¥Èñ°Ì and ±é»»¤¹¤ë¡£Control ¥â¥Ç¥£¥Õ¥¡¥¤¥¢¤Ï¼è¤ê½ü
692     ¤«¤ì¤ë¡£
693
694     $EVENT ¤Ë¤Þ¤À Shift, Control, Meta, Alt, Super, Hyper ¤Ê¤É¤Î¥â¥Ç¥£
695     ¥Õ¥¡¥¤¥¢¤¬¤¢¤ì¤Ð¡¢Ì¾Á°¤ÎÁ°¤Ë¤½¤ì¤¾¤ì"S-", "C-", "M-", "A-", "s-",
696     "H-" ¤¬ÉÕ¤¯¡£
697     
698     ¤¿¤È¤¨¤Ð¡¢keysym Ì¾¤¬ "a" ¤Ç¥¤¥Ù¥ó¥È¤¬ Shift, Meta, and Hyper ¥â¥Ç¥£
699     ¥Õ¥¡¥¤¥¢¤ò»ý¤Æ¤Ð¡¢ÆÀ¤é¤ì¤ë̾Á°¤Ï "H-M-A" ¤Ç¤¢¤ë¡£
700
701     ºÇ¸å¤Ë¤½¤Î̾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤òÊÖ¤¹¡£*/
702
703
704 MSymbol
705 minput_event_to_key (MFrame *frame, void *event)
706 {
707   int modifiers;
708   MSymbol key;
709   char *name, *str;
710
711   M_CHECK_READABLE (frame, MERROR_IM, Mnil);
712   key = (*frame->driver->parse_event) (frame, event, &modifiers);
713   if (! modifiers)
714     return key;
715
716   name = msymbol_name (key);
717   str = alloca (strlen (name) + 2 * 6 + 1);
718   str[0] = '\0';
719   if (modifiers & MINPUT_KEY_SHIFT_MODIFIER)
720     strcat (str, "S-");
721   if (modifiers & MINPUT_KEY_CONTROL_MODIFIER)
722     strcat (str, "C-");
723   if (modifiers & MINPUT_KEY_META_MODIFIER)
724     strcat (str, "M-");
725   if (modifiers & MINPUT_KEY_ALT_MODIFIER)
726     strcat (str, "A-");
727   if (modifiers & MINPUT_KEY_SUPER_MODIFIER)
728     strcat (str, "s-");
729   if (modifiers & MINPUT_KEY_HYPER_MODIFIER)
730     strcat (str, "H-");
731   strcat (str, name);
732
733   return msymbol (str);
734 }
735
736 /*** @} */
737
738 /*
739   Local Variables:
740   coding: euc-japan
741   End:
742 */