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