Fix typo in a comment.
[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   minput_driver = &minput_gui_driver;
552
553   face_box_prop.width = 1;
554   face_box_prop.color_top = face_box_prop.color_left
555     = face_box_prop.color_bottom = face_box_prop.color_right
556     = msymbol ("black");
557   face_box_prop.inner_hmargin = face_box_prop.inner_vmargin = 2;
558   face_box_prop.outer_hmargin = face_box_prop.outer_vmargin = 1;
559   status_face = mface ();
560   mface_put_prop (status_face, Mbox, &face_box_prop);
561
562   return 0;
563 }
564
565 void
566 minput__win_fini ()
567 {
568   M17N_OBJECT_UNREF (status_face);
569   if (minput_gui_driver.callback_list)
570     {
571       M17N_OBJECT_UNREF (minput_gui_driver.callback_list);
572       minput_gui_driver.callback_list = NULL;
573     }
574 }
575
576 /*** @} */
577 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
578
579 \f
580 /* External API */
581
582 /*** @addtogroup m17nInputMethodWin */
583 /*** @{ */
584
585 /*=*/
586 /***en
587     @brief Input driver for internal input methods on window systems.
588
589     The input driver @c minput_gui_driver is for internal input
590     methods to be used on window systems.
591
592     It creates sub-windows for a preedit text and a status text, and
593     displays them at the input spot set by the function
594     minput_set_spot ().
595
596     The macro M17N_INIT () set the variable @c minput_driver to the
597     pointer to this driver so that all internal input methods use it.
598
599     Therefore, unless @c minput_driver is changed from the default,
600     the driver dependent arguments to the functions whose name begin
601     with minput_ must are treated as follows.
602
603     The argument $ARG of the function minput_open_im () is ignored.
604
605     The argument $ARG of the function minput_create_ic () must be a
606     pointer to the structure @c MInputGUIArgIC.  See the documentation
607     of @c MInputGUIArgIC for more details.
608
609     If the argument $KEY of function minput_filter () is @c Mnil, the
610     argument $ARG must be a pointer to the object of type @c XEvent.
611     In that case, $KEY is generated from $ARG.
612
613     The argument $ARG of the function minput_lookup () must be the
614     same one as that of the function minput_filter (). */
615
616 /***ja
617     @brief ¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥à¤ÎÆâÉôÆþÎϥ᥽¥Ã¥ÉÍÑÆþÎϥɥ饤¥Ð.
618
619     ÆþÎϥɥ饤¥Ð @c minput_gui_driver
620     ¤Ï¡¢¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥à¾å¤ÇÍѤ¤¤é¤ì¤ëÆþÎϥ᥽¥Ã¥ÉÍѥɥ饤¥Ð¤Ç¤¢¤ë¡£
621
622     ¤³¤Î¥É¥é¥¤¥Ð¤Ï¡¢´Ø¿ô minput_set_spot () ¤Ë¤è¤Ã¤ÆÀßÄꤵ¤ì¤¿ÆþÎÏ¥¹¥Ý¥Ã¥È¤Ë
623     preedit ¥Æ¥­¥¹¥ÈÍѤΥµ¥Ö¥¦¥£¥ó¥É¥¦¤È status 
624     ¥Æ¥­¥¹¥ÈÍѤΥµ¥Ö¥¦¥£¥ó¥É¥¦¤òºî¤ê¡¢¤½¤ì¤¾¤ì¤òɽ¼¨¤¹¤ë¡£
625
626     ¥Þ¥¯¥í M17N_INIT () ¤ÏÊÑ¿ô @c minput_driver 
627     ¤ò¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤ËÀßÄꤷ¡¢Á´¤Æ¤ÎÆâÉôÆþÎϥ᥽¥Ã¥É¤¬¤³¤Î¥É¥é¥¤¥Ð¤ò»È¤¦¤è¤¦¤Ë¤¹¤ë¡£
628
629     ¤·¤¿¤¬¤Ã¤Æ¡¢@c minput_driver ¤¬¥Ç¥Õ¥©¥ë¥ÈÃͤΤޤޤǤ¢¤ì¤Ð¡¢minput_ 
630     ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä´Ø¿ô¤Î°ú¿ô¤Î¤¦¤Á¥É¥é¥¤¥Ð°Í¸¤Î¤â¤Î¤Ï°Ê²¼¤Î¤è¤¦¤Ë¤Ê¤ë¡£
631
632     ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï̵»ë¤µ¤ì¤ë¡£
633
634     ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂΠ@c MInputGUIArgIC 
635     ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï @c MInputGUIArgIC 
636     ¤ÎÀâÌÀ¤ò»²¾È¤Î¤³¤È¡£
637
638     ´Ø¿ô minput_filter () ¤Î°ú¿ô $ARG ¤¬ @c Mnil ¤Î¾ì¹ç¡¢ $ARG ¤Ï @c
639     XEvent ·¿¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¤³¤Î¾ì¹ç 
640     $KEY ¤Ï $ARG ¤«¤éÀ¸À®¤µ¤ì¤ë¡£
641
642     ´Ø¿ô minput_lookup () ¤Î°ú¿ô $ARG ¤Ï´Ø¿ô minput_filter () ¤Î°ú¿ô 
643     $ARG ¤ÈƱ¤¸¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ */
644
645 MInputDriver minput_gui_driver;
646
647 /*=*/
648
649 /***en
650     @brief Symbol of the name "xim".
651
652     The variable Mxim is a symbol of name "xim".  It is a name of the
653     input method driver #minput_xim_driver.  */ 
654 /***ja
655     @brief "xim"¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë .
656
657     ÊÑ¿ô Mxim ¤Ï"xim"¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£"xim" 
658     ¤ÏÆþÎϥ᥽¥Ã¥É¥É¥é¥¤¥Ð #minput_xim_driver ¤Î̾Á°¤Ç¤¢¤ë¡£  */ 
659
660 MSymbol Mxim;
661
662 /*=*/
663
664 /***en
665     @brief Convert an event to an input key.
666
667     The minput_event_to_key () function returns the input key
668     corresponding to event $EVENT on $FRAME by a window system
669     dependent manner.
670
671     In the m17n-X library, $EVENT must be a pointer to the structure
672     @c XKeyEvent, and it is handled as below.
673
674     At first, the keysym name of $EVENT is acquired by the function @c
675     XKeysymToString.  Then, the name is modified as below.
676
677     If the name is one of "a" .. "z" and $EVENT has a Shift modifier,
678     the name is converted to "A" .. "Z" respectively, and the Shift
679     modifier is cleared.
680
681     If the name is one byte length and $EVENT has a Control modifier,
682     the byte is bitwise anded by 0x1F and the Control modifier is
683     cleared.
684
685     If $EVENT still has Shift, Control, Meta, Alt, Super, and/or Hyper
686     modifiers, the name is preceded by "S-", "C-", "M-", "A-", "s-",
687     and/or "H-" respectively in this order.
688
689     For instance, if the keysym name is "a" and the event has Shift,
690     Meta, and Hyper modifiers, the resulting name is "H-M-A".
691
692     At last, a symbol who has the name is returned.  */
693
694 /***ja
695     @brief ¥¤¥Ù¥ó¥È¤òÆþÎÏ¥­¡¼¤ËÊÑ´¹¤¹¤ë.
696
697     ´Ø¿ô minput_name_to_key () ¤Ï¡¢$FRAME ¤Î¥¤¥Ù¥ó¥È $EVENT 
698     ¤ËÂбþ¤¹¤ëÆþÎÏ¥­¡¼¤òÊÖ¤¹¡£¤³¤³¤Ç¤Î¡ÖÂбþ¡×¤Ï¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥à¤Ë°Í¸¤¹¤ë¡£
699
700     m17n-X ¥é¥¤¥Ö¥é¥ê¤Î¾ì¹ç¤Ë¤Ï¡¢$EVENT ¤Ï ¹½Â¤ÂΠ@c XKeyEvent 
701     ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ê¡¢¼¡¤Î¤è¤¦¤Ë½èÍý¤µ¤ì¤ë¡£
702
703     ¤Þ¤º¡¢´Ø¿ô @c XKeysymToString ¤Ë¤è¤Ã¤Æ¡¢$EVENT ¤Î keysym 
704     Ì¾¤ò¼èÆÀ¤·¡¢¼¡¤¤¤Ç°Ê²¼¤ÎÊѹ¹¤ò²Ã¤¨¤ë¡£
705
706     Ì¾Á°¤¬ "a" .. "z" ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤Ã¤Æ $EVENT ¤Ë Shift 
707     ¥â¥Ç¥£¥Õ¥¡¥¤¥¢¤¬¤¢¤ì¤Ð¡¢Ì¾Á°¤Ï¤½¤ì¤¾¤ì "A" .. "Z" ¤ËÊÑ´¹¤µ¤ì¡¢Shift 
708     ¥â¥Ç¥£¥Õ¥¡¥¤¥¢¤Ï¼è¤ê½ü¤«¤ì¤ë¡£
709
710     Ì¾Á°¤¬£±¥Ð¥¤¥ÈŤǠ$EVENT ¤Ë Control ¥â¥Ç¥£¥Õ¥¡¥¤¥¢¤¬¤¢¤ì¤Ð¡¢Ì¾Á°¤È
711     0x1F ¤È¤ò¥Ó¥Ã¥Èñ°Ì and ±é»»¤¹¤ë¡£Control ¥â¥Ç¥£¥Õ¥¡¥¤¥¢¤Ï¼è¤ê½ü¤«¤ì¤ë¡£
712
713     $EVENT ¤Ë¤Þ¤À Shift, Control, Meta, Alt, Super, Hyper 
714     ¤Ê¤É¤Î¥â¥Ç¥£¥Õ¥¡¥¤¥¢¤¬¤¢¤ì¤Ð¡¢Ì¾Á°¤ÎÁ°¤Ë¤½¤ì¤¾¤ì"S-", "C-", "M-", "A-", "s-",
715     "H-" ¤¬ÉÕ¤¯¡£
716     
717     ¤¿¤È¤¨¤Ð¡¢keysym Ì¾¤¬ "a" ¤Ç¥¤¥Ù¥ó¥È¤¬ Shift, Meta, and Hyper 
718     ¥â¥Ç¥£¥Õ¥¡¥¤¥¢¤ò»ý¤Æ¤Ð¡¢ÆÀ¤é¤ì¤ë̾Á°¤Ï "H-M-A" ¤Ç¤¢¤ë¡£
719
720     ºÇ¸å¤Ë¤½¤Î̾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤òÊÖ¤¹¡£*/
721
722
723 MSymbol
724 minput_event_to_key (MFrame *frame, void *event)
725 {
726   int modifiers;
727   MSymbol key;
728   char *name, *str;
729
730   M_CHECK_READABLE (frame, MERROR_IM, Mnil);
731   key = (*frame->driver->parse_event) (frame, event, &modifiers);
732   if (! modifiers)
733     return key;
734
735   name = msymbol_name (key);
736   str = alloca (strlen (name) + 2 * 6 + 1);
737   str[0] = '\0';
738   if (modifiers & MINPUT_KEY_SHIFT_MODIFIER)
739     strcat (str, "S-");
740   if (modifiers & MINPUT_KEY_CONTROL_MODIFIER)
741     strcat (str, "C-");
742   if (modifiers & MINPUT_KEY_META_MODIFIER)
743     strcat (str, "M-");
744   if (modifiers & MINPUT_KEY_ALT_MODIFIER)
745     strcat (str, "A-");
746   if (modifiers & MINPUT_KEY_SUPER_MODIFIER)
747     strcat (str, "s-");
748   if (modifiers & MINPUT_KEY_HYPER_MODIFIER)
749     strcat (str, "H-");
750   strcat (str, name);
751
752   return msymbol (str);
753 }
754
755 /*** @} */
756
757 /*
758   Local Variables:
759   coding: euc-japan
760   End:
761 */