]> Pileus Git - ~andy/gtk/blob - gtk/gtkimmulticontext.c
Removed warning
[~andy/gtk] / gtk / gtkimmulticontext.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 2000 Red Hat, Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include <string.h>
21
22 #ifdef GDK_WINDOWING_X11
23 #include <X11/Xlocale.h>        /* so we get the right setlocale */
24 #else
25 #include <locale.h>
26 #endif
27
28 #include "gtksignal.h"
29 #include "gtkimmulticontext.h"
30 #include "gtkimmodule.h"
31 #include "gtkmenuitem.h"
32
33 static void     gtk_im_multicontext_class_init         (GtkIMMulticontextClass  *class);
34 static void     gtk_im_multicontext_init               (GtkIMMulticontext       *im_multicontext);
35 static void     gtk_im_multicontext_finalize           (GObject                 *object);
36
37 static void     gtk_im_multicontext_set_slave          (GtkIMMulticontext       *multicontext,
38                                                         GtkIMContext            *slave);
39
40 static void     gtk_im_multicontext_set_client_window  (GtkIMContext            *context,
41                                                         GdkWindow               *window);
42 static void     gtk_im_multicontext_get_preedit_string (GtkIMContext            *context,
43                                                         gchar                  **str,
44                                                         PangoAttrList          **attrs,
45                                                         gint                   *cursor_pos);
46 static gboolean gtk_im_multicontext_filter_keypress    (GtkIMContext            *context,
47                                                         GdkEventKey             *event);
48 static void     gtk_im_multicontext_focus_in           (GtkIMContext            *context);
49 static void     gtk_im_multicontext_focus_out          (GtkIMContext            *context);
50 static void     gtk_im_multicontext_reset              (GtkIMContext            *context);
51
52 void            gtk_im_multicontext_preedit_start_cb   (GtkIMContext            *slave,
53                                                         GtkIMMulticontext       *multicontext);
54 void            gtk_im_multicontext_preedit_end_cb     (GtkIMContext            *slave,
55                                                         GtkIMMulticontext       *multicontext);
56 void            gtk_im_multicontext_preedit_changed_cb (GtkIMContext            *slave,
57                                                         GtkIMMulticontext       *multicontext);
58 void            gtk_im_multicontext_commit_cb          (GtkIMContext            *slave,
59                                                         const gchar             *str,
60                                                         GtkIMMulticontext       *multicontext);
61
62 static GtkIMContextClass *parent_class;
63
64 static const gchar *global_context_id = NULL;
65
66 GtkType
67 gtk_im_multicontext_get_type (void)
68 {
69   static GtkType im_multicontext_type = 0;
70
71   if (!im_multicontext_type)
72     {
73       static const GtkTypeInfo im_multicontext_info =
74       {
75         "GtkIMMulticontext",
76         sizeof (GtkIMMulticontext),
77         sizeof (GtkIMMulticontextClass),
78         (GtkClassInitFunc) gtk_im_multicontext_class_init,
79         (GtkObjectInitFunc) gtk_im_multicontext_init,
80         /* reserved_1 */ NULL,
81         /* reserved_2 */ NULL,
82         (GtkClassInitFunc) NULL,
83       };
84
85       im_multicontext_type = gtk_type_unique (GTK_TYPE_IM_CONTEXT, &im_multicontext_info);
86     }
87
88   return im_multicontext_type;
89 }
90
91 static void
92 gtk_im_multicontext_class_init (GtkIMMulticontextClass *class)
93 {
94   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
95   GtkIMContextClass *im_context_class = GTK_IM_CONTEXT_CLASS (class);
96   
97   parent_class = g_type_class_peek_parent (class);
98
99   im_context_class->set_client_window = gtk_im_multicontext_set_client_window;
100   im_context_class->get_preedit_string = gtk_im_multicontext_get_preedit_string;
101   im_context_class->filter_keypress = gtk_im_multicontext_filter_keypress;
102   im_context_class->focus_in = gtk_im_multicontext_focus_in;
103   im_context_class->focus_out = gtk_im_multicontext_focus_out;
104   im_context_class->reset = gtk_im_multicontext_reset;
105
106   gobject_class->finalize = gtk_im_multicontext_finalize;
107 }
108
109 static void
110 gtk_im_multicontext_init (GtkIMMulticontext *multicontext)
111 {
112   multicontext->slave = NULL;
113 }
114
115 GtkIMContext *
116 gtk_im_multicontext_new (void)
117 {
118   return GTK_IM_CONTEXT (gtk_type_new (GTK_TYPE_IM_MULTICONTEXT));
119 }
120
121 static void
122 gtk_im_multicontext_finalize (GObject *object)
123 {
124   gtk_im_multicontext_set_slave (GTK_IM_MULTICONTEXT (object), NULL);
125
126   G_OBJECT_CLASS (parent_class)->finalize (object);
127 }
128
129 static void
130 gtk_im_multicontext_set_slave (GtkIMMulticontext *multicontext,
131                                GtkIMContext      *slave)
132 {
133   if (multicontext->slave)
134     {
135       gtk_signal_disconnect_by_data (GTK_OBJECT (multicontext->slave), multicontext);
136       gtk_object_unref (GTK_OBJECT (multicontext->slave));
137     }
138   
139   multicontext->slave = slave;
140
141   if (multicontext->slave)
142     {
143       gtk_object_ref (GTK_OBJECT (multicontext->slave));
144       gtk_object_sink (GTK_OBJECT (multicontext->slave));
145
146       gtk_signal_connect (GTK_OBJECT (multicontext->slave), "preedit_start",
147                           GTK_SIGNAL_FUNC (gtk_im_multicontext_preedit_start_cb),
148                           multicontext);
149       gtk_signal_connect (GTK_OBJECT (multicontext->slave), "preedit_end",
150                           GTK_SIGNAL_FUNC (gtk_im_multicontext_preedit_end_cb),
151                           multicontext);
152       gtk_signal_connect (GTK_OBJECT (multicontext->slave), "preedit_changed",
153                           GTK_SIGNAL_FUNC (gtk_im_multicontext_preedit_changed_cb),
154                           multicontext);
155       gtk_signal_connect (GTK_OBJECT (multicontext->slave), "commit",
156                           GTK_SIGNAL_FUNC (gtk_im_multicontext_commit_cb),
157                           multicontext);
158
159       if (multicontext->client_window)
160         gtk_im_context_set_client_window (slave, multicontext->client_window);
161     }
162 }
163
164 static GtkIMContext *
165 gtk_im_multicontext_get_slave (GtkIMMulticontext *multicontext)
166 {
167   if (!multicontext->slave)
168     {
169       if (!global_context_id)
170         {
171           const char *locale;
172           
173 #ifdef HAVE_LC_MESSAGES
174           locale = setlocale (LC_MESSAGES, NULL);
175 #else
176           locale = setlocale (LC_CTYPE, NULL);
177 #endif
178           global_context_id = _gtk_im_module_get_default_context_id (locale);
179         }
180         
181       gtk_im_multicontext_set_slave (multicontext, _gtk_im_module_create (global_context_id));
182       multicontext->context_id = global_context_id;
183     }
184
185   return multicontext->slave;
186 }
187
188 static void
189 gtk_im_multicontext_set_client_window (GtkIMContext *context,
190                                        GdkWindow    *window)
191 {
192   GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
193   GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
194
195   multicontext->client_window = window;
196   
197   if (slave)
198     gtk_im_context_set_client_window (slave, window);
199 }
200
201 static void
202 gtk_im_multicontext_get_preedit_string (GtkIMContext   *context,
203                                         gchar         **str,
204                                         PangoAttrList **attrs,
205                                         gint           *cursor_pos)
206 {
207   GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
208   GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
209
210   if (slave)
211     gtk_im_context_get_preedit_string (slave, str, attrs, cursor_pos);
212   else
213     {
214       if (str)
215         *str = g_strdup ("");
216       if (attrs)
217         *attrs = pango_attr_list_new ();
218     }
219 }
220
221 static gboolean
222 gtk_im_multicontext_filter_keypress (GtkIMContext *context,
223                                      GdkEventKey  *event)
224 {
225   GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
226   GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
227
228   if (slave)
229     return gtk_im_context_filter_keypress (slave, event);
230   else
231     return FALSE;
232 }
233
234 static void
235 gtk_im_multicontext_focus_in (GtkIMContext   *context)
236 {
237   GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
238   GtkIMContext *slave;
239
240   /* If the global context type is different from the context we were
241    * using before, get rid of the old slave and create a new one
242    * for the new global context type.
243    */
244   if (!multicontext->context_id ||
245       strcmp (global_context_id, multicontext->context_id) != 0)
246     gtk_im_multicontext_set_slave (multicontext, NULL);
247
248   slave = gtk_im_multicontext_get_slave (multicontext);
249
250   if (slave)
251     gtk_im_context_focus_in (slave);
252 }
253
254 static void
255 gtk_im_multicontext_focus_out (GtkIMContext   *context)
256 {
257   GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
258   GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
259
260   if (slave)
261     gtk_im_context_focus_out (slave);
262 }
263
264 static void
265 gtk_im_multicontext_reset (GtkIMContext   *context)
266 {
267   GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
268   GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
269
270   if (slave)
271     gtk_im_context_reset (slave);
272 }
273
274 void
275 gtk_im_multicontext_preedit_start_cb   (GtkIMContext      *slave,
276                                         GtkIMMulticontext *multicontext)
277 {
278   gtk_signal_emit_by_name (GTK_OBJECT (multicontext), "preedit_start");
279 }
280
281 void
282 gtk_im_multicontext_preedit_end_cb (GtkIMContext      *slave,
283                                     GtkIMMulticontext *multicontext)
284 {
285   gtk_signal_emit_by_name (GTK_OBJECT (multicontext), "preedit_end");
286 }
287
288 void
289 gtk_im_multicontext_preedit_changed_cb (GtkIMContext      *slave,
290                                         GtkIMMulticontext *multicontext)
291 {
292   gtk_signal_emit_by_name (GTK_OBJECT (multicontext), "preedit_changed");
293 }
294
295 void
296 gtk_im_multicontext_commit_cb (GtkIMContext      *slave,
297                                const gchar       *str,
298                                GtkIMMulticontext *multicontext)
299 {
300   gtk_signal_emit_by_name (GTK_OBJECT (multicontext), "commit", str);;
301 }
302
303 static void
304 activate_cb (GtkWidget         *menuitem,
305              GtkIMMulticontext *context)
306 {
307   const gchar *id = gtk_object_get_data (GTK_OBJECT (menuitem), "gtk-context-id");
308
309   gtk_im_context_reset (GTK_IM_CONTEXT (context));
310
311   global_context_id = id;
312   gtk_im_multicontext_set_slave (context, NULL);
313 }
314
315 /**
316  * gtk_im_multicontext_append_menuitems:
317  * @context: a #GtkIMMultiContext
318  * @menushell: a #GtkMenuShell
319  * 
320  * Add menuitems for various available input methods to a menu;
321  * the menuitems, when selected, will switch the input method
322  * for the context and the global default input method.
323  **/
324 void
325 gtk_im_multicontext_append_menuitems (GtkIMMulticontext *context,
326                                       GtkMenuShell      *menushell)
327 {
328   const GtkIMContextInfo **contexts;
329   gint n_contexts, i;
330   
331   _gtk_im_module_list (&contexts, &n_contexts);
332
333   for (i=0; i < n_contexts; i++)
334     {
335       GtkWidget *menuitem;
336
337       menuitem = gtk_menu_item_new_with_label (contexts[i]->context_name);
338
339       gtk_object_set_data (GTK_OBJECT (menuitem), "gtk-context-id",
340                            (char *)contexts[i]->context_id);
341       gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
342                           activate_cb, context);
343
344       gtk_widget_show (menuitem);
345       gtk_menu_shell_append (menushell, menuitem);
346     }
347 }
348