(M0_3): Delete it.
[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     ¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥à¾å¤ÇÍѤ¤¤é¤ì¤ëÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѤΥɥ饤¥Ð¤Ç¤¢¤ë¡£
44     ¤³¤Î¥É¥é¥¤¥Ð¤ÏÆþÎÏ¥¹¥Ý¥Ã¥È¤Ë preedit ¥Æ¥­¥¹¥È¤È status 
45     ¥Æ¥­¥¹¥È¤òɽ¼¨¤¹¤ë¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï @c 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 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
56 /*** @addtogroup m17nInternal
57      @{ */
58
59 #include <string.h>
60 #include <ctype.h>
61
62 #include "config.h"
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   else if (command == Minput_reset)
487     {
488       MInputCallbackFunc func;
489
490       if (minput_default_driver.callback_list
491           && (func = ((MInputCallbackFunc)
492                       mplist_get (minput_default_driver.callback_list,
493                                   Minput_reset))))
494         {
495           MInputContextInfo *ic_info
496             = (MInputContextInfo *) win_ic_info->ic_info;
497           ic->info = ic_info;
498           (func) (ic, Minput_reset);
499           ic->info = win_ic_info;
500         }
501       if (ic->preedit_changed)
502         minput__callback (ic, Minput_preedit_draw);
503       if (ic->status_changed)
504         minput__callback (ic, Minput_status_draw);
505       if (ic->candidates_changed)
506         minput__callback (ic, Minput_candidates_draw);
507     }
508 }
509
510 static int
511 win_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
512 {
513   MInputGUIContextInfo *win_ic_info = (MInputGUIContextInfo *) ic->info;
514   MInputContextInfo *ic_info = (MInputContextInfo *) win_ic_info->ic_info;
515   int ret;
516
517   ic->info = ic_info;
518   ret = (*minput_default_driver.lookup) (ic, key, arg, mt);
519   ic->info = win_ic_info;
520   return ret;
521 }
522
523 \f
524
525 int
526 minput__win_init ()
527 {
528   minput_gui_driver = minput_default_driver;
529
530   minput_gui_driver.create_ic = win_create_ic;
531   minput_gui_driver.destroy_ic = win_destroy_ic;
532   minput_gui_driver.filter = win_filter;
533   minput_gui_driver.lookup = win_lookup;
534   {
535     MPlist *plist = mplist ();
536
537     minput_gui_driver.callback_list = plist;
538     plist = mplist_add (plist, Minput_preedit_start, (void *) win_callback);
539     plist = mplist_add (plist, Minput_preedit_draw, (void *) win_callback);
540     plist = mplist_add (plist, Minput_preedit_done, (void *) win_callback);
541     plist = mplist_add (plist, Minput_status_start, (void *) win_callback);
542     plist = mplist_add (plist, Minput_status_draw, (void *) win_callback);
543     plist = mplist_add (plist, Minput_status_done, (void *) win_callback);
544     plist = mplist_add (plist, Minput_candidates_start, (void *) win_callback);
545     plist = mplist_add (plist, Minput_candidates_draw, (void *) win_callback);
546     plist = mplist_add (plist, Minput_candidates_done, (void *) win_callback);
547     plist = mplist_add (plist, Minput_set_spot, (void *) win_callback);
548     plist = mplist_add (plist, Minput_toggle, (void *) win_callback);
549     plist = mplist_add (plist, Minput_reset, (void *) win_callback);
550   }
551 #if 0
552   /* This will make a caller of minput_method_open() pazzled.  */
553   minput_driver = &minput_gui_driver;
554 #endif
555
556   face_box_prop.width = 1;
557   face_box_prop.color_top = face_box_prop.color_left
558     = face_box_prop.color_bottom = face_box_prop.color_right
559     = msymbol ("black");
560   face_box_prop.inner_hmargin = face_box_prop.inner_vmargin = 2;
561   face_box_prop.outer_hmargin = face_box_prop.outer_vmargin = 1;
562   status_face = mface ();
563   mface_put_prop (status_face, Mbox, &face_box_prop);
564
565   return 0;
566 }
567
568 void
569 minput__win_fini ()
570 {
571   M17N_OBJECT_UNREF (status_face);
572   if (minput_gui_driver.callback_list)
573     {
574       M17N_OBJECT_UNREF (minput_gui_driver.callback_list);
575       minput_gui_driver.callback_list = NULL;
576     }
577 }
578
579 /*** @} */
580 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
581
582 \f
583 /* External API */
584
585 /*** @addtogroup m17nInputMethodWin */
586 /*** @{ */
587
588 /*=*/
589 /***en
590     @brief Input driver for internal input methods on window systems.
591
592     The input driver @c minput_gui_driver is for internal input
593     methods to be used on window systems.
594
595     It creates sub-windows for a preedit text and a status text, and
596     displays them at the input spot set by the function
597     minput_set_spot ().
598
599     The macro M17N_INIT () set the variable @c minput_driver to the
600     pointer to this driver so that all internal input methods use it.
601
602     Therefore, unless @c minput_driver is changed from the default,
603     the driver dependent arguments to the functions whose name begin
604     with minput_ must are treated as follows.
605
606     The argument $ARG of the function minput_open_im () is ignored.
607
608     The argument $ARG of the function minput_create_ic () must be a
609     pointer to the structure @c MInputGUIArgIC.  See the documentation
610     of @c MInputGUIArgIC for more details.
611
612     If the argument $KEY of function minput_filter () is @c Mnil, the
613     argument $ARG must be a pointer to the object of type @c XEvent.
614     In that case, $KEY is generated from $ARG.
615
616     The argument $ARG of the function minput_lookup () must be the
617     same one as that of the function minput_filter (). */
618
619 /***ja
620     @brief ¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥à¤ÎÆâÉôÆþÎϥ᥽¥Ã¥ÉÍÑÆþÎϥɥ饤¥Ð.
621
622     ÆþÎϥɥ饤¥Ð @c minput_gui_driver
623     ¤Ï¡¢¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥à¾å¤ÇÍѤ¤¤é¤ì¤ëÆþÎϥ᥽¥Ã¥ÉÍѥɥ饤¥Ð¤Ç¤¢¤ë¡£
624
625     ¤³¤Î¥É¥é¥¤¥Ð¤Ï¡¢´Ø¿ô minput_set_spot () ¤Ë¤è¤Ã¤ÆÀßÄꤵ¤ì¤¿ÆþÎÏ¥¹¥Ý¥Ã¥È¤Ë
626     preedit ¥Æ¥­¥¹¥ÈÍѤΥµ¥Ö¥¦¥£¥ó¥É¥¦¤È status 
627     ¥Æ¥­¥¹¥ÈÍѤΥµ¥Ö¥¦¥£¥ó¥É¥¦¤òºî¤ê¡¢¤½¤ì¤¾¤ì¤òɽ¼¨¤¹¤ë¡£
628
629     ¥Þ¥¯¥í M17N_INIT () ¤ÏÊÑ¿ô @c minput_driver 
630     ¤ò¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤ËÀßÄꤷ¡¢Á´¤Æ¤ÎÆâÉôÆþÎϥ᥽¥Ã¥É¤¬¤³¤Î¥É¥é¥¤¥Ð¤ò»È¤¦¤è¤¦¤Ë¤¹¤ë¡£
631
632     ¤·¤¿¤¬¤Ã¤Æ¡¢@c minput_driver ¤¬¥Ç¥Õ¥©¥ë¥ÈÃͤΤޤޤǤ¢¤ì¤Ð¡¢minput_ 
633     ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä´Ø¿ô¤Î°ú¿ô¤Î¤¦¤Á¥É¥é¥¤¥Ð°Í¸¤Î¤â¤Î¤Ï°Ê²¼¤Î¤è¤¦¤Ë¤Ê¤ë¡£
634
635     ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï̵»ë¤µ¤ì¤ë¡£
636
637     ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂΠ@c MInputGUIArgIC 
638     ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï @c MInputGUIArgIC 
639     ¤ÎÀâÌÀ¤ò»²¾È¤Î¤³¤È¡£
640
641     ´Ø¿ô minput_filter () ¤Î°ú¿ô $ARG ¤¬ @c Mnil ¤Î¾ì¹ç¡¢ $ARG ¤Ï @c
642     XEvent ·¿¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¤³¤Î¾ì¹ç 
643     $KEY ¤Ï $ARG ¤«¤éÀ¸À®¤µ¤ì¤ë¡£
644
645     ´Ø¿ô minput_lookup () ¤Î°ú¿ô $ARG ¤Ï´Ø¿ô minput_filter () ¤Î°ú¿ô 
646     $ARG ¤ÈƱ¤¸¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ */
647
648 MInputDriver minput_gui_driver;
649
650 /*=*/
651
652 /***en
653     @brief Symbol of the name "xim".
654
655     The variable Mxim is a symbol of name "xim".  It is a name of the
656     input method driver #minput_xim_driver.  */ 
657 /***ja
658     @brief "xim"¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë .
659
660     ÊÑ¿ô Mxim ¤Ï"xim"¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£"xim" 
661     ¤ÏÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð #minput_xim_driver ¤Î̾Á°¤Ç¤¢¤ë¡£  */ 
662
663 MSymbol Mxim;
664
665 /*=*/
666
667 /***en
668     @brief Convert an event to an input key.
669
670     The minput_event_to_key () function returns the input key
671     corresponding to event $EVENT on $FRAME by a window system
672     dependent manner.
673
674     In the m17n-X library, $EVENT must be a pointer to the structure
675     @c XKeyEvent, and it is handled as below.
676
677     At first, the keysym name of $EVENT is acquired by the function @c
678     XKeysymToString.  Then, the name is modified as below.
679
680     If the name is one of "a" .. "z" and $EVENT has a Shift modifier,
681     the name is converted to "A" .. "Z" respectively, and the Shift
682     modifier is cleared.
683
684     If the name is one byte length and $EVENT has a Control modifier,
685     the byte is bitwise anded by 0x1F and the Control modifier is
686     cleared.
687
688     If $EVENT still has modifiers, the name is preceded by "H-"
689     (Hyper), "s-" (Super), "A-" (Alt), "M-" (Meta), "C-" (Control),
690     and/or "S-" (Shift) in this order.
691
692     For instance, if the keysym name is "a" and the event has Shift,
693     Meta, and Hyper modifiers, the resulting name is "H-M-A".
694
695     At last, a symbol who has the name is returned.  */
696
697 /***ja
698     @brief ¥¤¥Ù¥ó¥È¤òÆþÎÏ¥­¡¼¤ËÊÑ´¹¤¹¤ë.
699
700     ´Ø¿ô minput_event_to_key () ¤Ï¡¢$FRAME ¤Î¥¤¥Ù¥ó¥È $EVENT 
701     ¤ËÂбþ¤¹¤ëÆþÎÏ¥­¡¼¤òÊÖ¤¹¡£¤³¤³¤Ç¤Î¡ÖÂбþ¡×¤Ï¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥à¤Ë°Í¸¤¹¤ë¡£
702
703     m17n-X ¥é¥¤¥Ö¥é¥ê¤Î¾ì¹ç¤Ë¤Ï¡¢$EVENT ¤Ï ¹½Â¤ÂΠ@c XKeyEvent 
704     ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ê¡¢¼¡¤Î¤è¤¦¤Ë½èÍý¤µ¤ì¤ë¡£
705
706     ¤Þ¤º¡¢´Ø¿ô @c XKeysymToString ¤Ë¤è¤Ã¤Æ¡¢$EVENT ¤Î keysym 
707     Ì¾¤ò¼èÆÀ¤·¡¢¼¡¤¤¤Ç°Ê²¼¤ÎÊѹ¹¤ò²Ã¤¨¤ë¡£
708
709     Ì¾Á°¤¬ "a" .. "z" ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤Ã¤Æ $EVENT ¤Ë Shift 
710     ¥â¥Ç¥£¥Õ¥¡¥¤¥¢¤¬¤¢¤ì¤Ð¡¢Ì¾Á°¤Ï¤½¤ì¤¾¤ì "A" .. "Z" ¤ËÊÑ´¹¤µ¤ì¡¢Shift 
711     ¥â¥Ç¥£¥Õ¥¡¥¤¥¢¤Ï¼è¤ê½ü¤«¤ì¤ë¡£
712
713     Ì¾Á°¤¬£±¥Ð¥¤¥ÈŤǠ$EVENT ¤Ë Control ¥â¥Ç¥£¥Õ¥¡¥¤¥¢¤¬¤¢¤ì¤Ð¡¢Ì¾Á°¤È
714     0x1F ¤È¤ò¥Ó¥Ã¥Èñ°Ì¤Ç and ±é»»¤·¡¢Control ¥â¥Ç¥£¥Õ¥¡¥¤¥¢¤Ï¼è¤ê½ü¤«¤ì¤ë¡£
715
716     ¤½¤ì¤Ç¤â $EVENT ¤Ë¤Þ¤À¥â¥Ç¥£¥Õ¥¡¥¤¥¢¤¬¤¢¤ì¤Ð¡¢Ì¾Á°¤ÎÁ°¤Ë¤½¤ì¤¾¤ì
717     "H-" (Hyper), "s-" (Super), "A-" (Alt), "M-" (Meta), "C-"
718     (Control), "S-" (Shift) ¤¬¤³¤Î½çÈÖ¤ÇÉÕ¤¯¡£
719     
720     ¤¿¤È¤¨¤Ð¡¢keysym Ì¾¤¬ "a" ¤Ç¥¤¥Ù¥ó¥È¤¬ Shift, Meta, and Hyper 
721     ¥â¥Ç¥£¥Õ¥¡¥¤¥¢¤ò»ý¤Æ¤Ð¡¢ÆÀ¤é¤ì¤ë̾Á°¤Ï "H-M-A" ¤Ç¤¢¤ë¡£
722
723     ºÇ¸å¤Ë¤½¤Î̾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤òÊÖ¤¹¡£*/
724
725
726 MSymbol
727 minput_event_to_key (MFrame *frame, void *event)
728 {
729   int modifiers;
730   MSymbol key;
731   char *name, *str;
732
733   M_CHECK_READABLE (frame, MERROR_IM, Mnil);
734   key = (*frame->driver->parse_event) (frame, event, &modifiers);
735   if (! modifiers)
736     return key;
737
738   name = msymbol_name (key);
739   str = alloca (strlen (name) + 2 * 6 + 1);
740   str[0] = '\0';
741   if (modifiers & MINPUT_KEY_SHIFT_MODIFIER)
742     strcat (str, "S-");
743   if (modifiers & MINPUT_KEY_CONTROL_MODIFIER)
744     strcat (str, "C-");
745   if (modifiers & MINPUT_KEY_META_MODIFIER)
746     strcat (str, "M-");
747   if (modifiers & MINPUT_KEY_ALT_MODIFIER)
748     strcat (str, "A-");
749   if (modifiers & MINPUT_KEY_SUPER_MODIFIER)
750     strcat (str, "s-");
751   if (modifiers & MINPUT_KEY_HYPER_MODIFIER)
752     strcat (str, "H-");
753   strcat (str, name);
754
755   return msymbol (str);
756 }
757
758 /*** @} */
759
760 /*
761   Local Variables:
762   coding: euc-japan
763   End:
764 */