This source file includes following definitions.
- im_context_commit_cb
- im_context_retrieve_surrounding_cb
- im_context_delete_surrounding_cb
- make_color_string
- im_context_preedit_changed_cb
- im_context_preedit_end_cb
- im_context_preedit_start_cb
- pgtk_im_focus_in
- pgtk_im_focus_out
- pgtk_im_filter_keypress
- pgtk_im_set_cursor_location
- pgtk_im_use_context
- pgtk_im_init
- pgtk_im_finish
- syms_of_pgtkim
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 #include <config.h>
24
25 #include "pgtkterm.h"
26
27 static void
28 im_context_commit_cb (GtkIMContext *imc,
29 gchar *str,
30 gpointer user_data)
31 {
32 struct pgtk_display_info *dpyinfo = user_data;
33 struct frame *f = dpyinfo->im.focused_frame;
34
35 if (dpyinfo->im.context == NULL)
36 return;
37 if (f == NULL)
38 return;
39
40 pgtk_enqueue_string (f, str);
41 }
42
43 static gboolean
44 im_context_retrieve_surrounding_cb (GtkIMContext *imc, gpointer user_data)
45 {
46 gtk_im_context_set_surrounding (imc, "", -1, 0);
47 return TRUE;
48 }
49
50 static gboolean
51 im_context_delete_surrounding_cb (GtkIMContext *imc, int offset, int n_chars,
52 gpointer user_data)
53 {
54 return TRUE;
55 }
56
57 static Lisp_Object
58 make_color_string (PangoAttrColor *pac)
59 {
60 char buf[256];
61 sprintf (buf, "#%02x%02x%02x",
62 pac->color.red >> 8, pac->color.green >> 8, pac->color.blue >> 8);
63 return build_string (buf);
64 }
65
66 static void
67 im_context_preedit_changed_cb (GtkIMContext *imc, gpointer user_data)
68 {
69 struct pgtk_display_info *dpyinfo = user_data;
70 struct frame *f = dpyinfo->im.focused_frame;
71 char *str;
72 PangoAttrList *attrs;
73 int pos;
74
75 if (dpyinfo->im.context == NULL)
76 return;
77 if (f == NULL)
78 return;
79
80 gtk_im_context_get_preedit_string (imc, &str, &attrs, &pos);
81
82
83
84
85
86
87
88
89 Lisp_Object list = Qnil;
90
91 PangoAttrIterator *iter;
92 iter = pango_attr_list_get_iterator (attrs);
93 do
94 {
95 int st, ed;
96 int has_underline = 0;
97 Lisp_Object part = Qnil;
98
99 pango_attr_iterator_range (iter, &st, &ed);
100
101 if (ed > strlen (str))
102 ed = strlen (str);
103 if (st >= ed)
104 continue;
105
106 Lisp_Object text = make_string (str + st, ed - st);
107 part = Fcons (text, part);
108
109 PangoAttrInt *ul =
110 (PangoAttrInt *) pango_attr_iterator_get (iter, PANGO_ATTR_UNDERLINE);
111 if (ul != NULL)
112 {
113 if (ul->value != PANGO_UNDERLINE_NONE)
114 has_underline = 1;
115 }
116
117 PangoAttrColor *pac;
118 if (has_underline)
119 {
120 pac =
121 (PangoAttrColor *) pango_attr_iterator_get (iter,
122 PANGO_ATTR_UNDERLINE_COLOR);
123 if (pac != NULL)
124 part = Fcons (Fcons (Qul, make_color_string (pac)), part);
125 else
126 part = Fcons (Fcons (Qul, Qt), part);
127 }
128
129 pac =
130 (PangoAttrColor *) pango_attr_iterator_get (iter,
131 PANGO_ATTR_FOREGROUND);
132 if (pac != NULL)
133 part = Fcons (Fcons (Qfg, make_color_string (pac)), part);
134
135 pac =
136 (PangoAttrColor *) pango_attr_iterator_get (iter,
137 PANGO_ATTR_BACKGROUND);
138 if (pac != NULL)
139 part = Fcons (Fcons (Qbg, make_color_string (pac)), part);
140
141 part = Fnreverse (part);
142 list = Fcons (part, list);
143 }
144 while (pango_attr_iterator_next (iter));
145
146 list = Fnreverse (list);
147 pgtk_enqueue_preedit (f, list);
148
149 g_free (str);
150 pango_attr_list_unref (attrs);
151 }
152
153 static void
154 im_context_preedit_end_cb (GtkIMContext *imc, gpointer user_data)
155 {
156 struct pgtk_display_info *dpyinfo = user_data;
157 struct frame *f = dpyinfo->im.focused_frame;
158
159 if (dpyinfo->im.context == NULL)
160 return;
161 if (f == NULL)
162 return;
163
164 pgtk_enqueue_preedit (f, Qnil);
165 }
166
167 static void
168 im_context_preedit_start_cb (GtkIMContext *imc, gpointer user_data)
169 {
170 }
171
172 void
173 pgtk_im_focus_in (struct frame *f)
174 {
175 struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
176 if (dpyinfo->im.context != NULL)
177 {
178 gtk_im_context_reset (dpyinfo->im.context);
179 gtk_im_context_set_client_window (dpyinfo->im.context,
180 gtk_widget_get_window
181 (FRAME_GTK_WIDGET (f)));
182 gtk_im_context_focus_in (dpyinfo->im.context);
183 }
184 dpyinfo->im.focused_frame = f;
185 }
186
187 void
188 pgtk_im_focus_out (struct frame *f)
189 {
190 struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
191 if (dpyinfo->im.focused_frame == f)
192 {
193 if (dpyinfo->im.context != NULL)
194 {
195 gtk_im_context_reset (dpyinfo->im.context);
196 gtk_im_context_focus_out (dpyinfo->im.context);
197 gtk_im_context_set_client_window (dpyinfo->im.context, NULL);
198 }
199 dpyinfo->im.focused_frame = NULL;
200 }
201 }
202
203 bool
204 pgtk_im_filter_keypress (struct frame *f, GdkEventKey * ev)
205 {
206 struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
207 if (dpyinfo->im.context != NULL)
208 {
209 if (gtk_im_context_filter_keypress (dpyinfo->im.context, ev))
210 return true;
211 }
212 return false;
213 }
214
215 void
216 pgtk_im_set_cursor_location (struct frame *f, int x, int y, int width,
217 int height)
218 {
219 struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
220 if (dpyinfo->im.context != NULL && dpyinfo->im.focused_frame == f)
221 {
222 GdkRectangle area = { x, y, width, height };
223 gtk_im_context_set_cursor_location (dpyinfo->im.context, &area);
224 }
225 }
226
227 static void
228 pgtk_im_use_context (struct pgtk_display_info *dpyinfo, bool use_p)
229 {
230 if (!use_p)
231 {
232 if (dpyinfo->im.context != NULL)
233 {
234 gtk_im_context_reset (dpyinfo->im.context);
235 gtk_im_context_focus_out (dpyinfo->im.context);
236 gtk_im_context_set_client_window (dpyinfo->im.context, NULL);
237
238 g_object_unref (dpyinfo->im.context);
239 dpyinfo->im.context = NULL;
240 }
241 }
242 else
243 {
244 if (dpyinfo->im.context == NULL)
245 {
246 dpyinfo->im.context = gtk_im_multicontext_new ();
247 g_signal_connect (dpyinfo->im.context, "commit",
248 G_CALLBACK (im_context_commit_cb), dpyinfo);
249 g_signal_connect (dpyinfo->im.context, "retrieve-surrounding",
250 G_CALLBACK (im_context_retrieve_surrounding_cb),
251 dpyinfo);
252 g_signal_connect (dpyinfo->im.context, "delete-surrounding",
253 G_CALLBACK (im_context_delete_surrounding_cb),
254 dpyinfo);
255 g_signal_connect (dpyinfo->im.context, "preedit-changed",
256 G_CALLBACK (im_context_preedit_changed_cb),
257 dpyinfo);
258 g_signal_connect (dpyinfo->im.context, "preedit-end",
259 G_CALLBACK (im_context_preedit_end_cb), dpyinfo);
260 g_signal_connect (dpyinfo->im.context, "preedit-start",
261 G_CALLBACK (im_context_preedit_start_cb),
262 dpyinfo);
263 gtk_im_context_set_use_preedit (dpyinfo->im.context, TRUE);
264
265 if (dpyinfo->im.focused_frame)
266 pgtk_im_focus_in (dpyinfo->im.focused_frame);
267 }
268 }
269 }
270
271 void
272 pgtk_im_init (struct pgtk_display_info *dpyinfo)
273 {
274 dpyinfo->im.context = NULL;
275
276 pgtk_im_use_context (dpyinfo, !NILP (Vpgtk_use_im_context_on_new_connection));
277 }
278
279 void
280 pgtk_im_finish (struct pgtk_display_info *dpyinfo)
281 {
282 if (dpyinfo->im.context != NULL)
283 g_object_unref (dpyinfo->im.context);
284 dpyinfo->im.context = NULL;
285 }
286
287 DEFUN ("pgtk-use-im-context", Fpgtk_use_im_context, Spgtk_use_im_context, 1, 2, 0,
288 doc: )
289 (Lisp_Object use_p, Lisp_Object terminal)
290 {
291 struct pgtk_display_info *dpyinfo = check_pgtk_display_info (terminal);
292
293 pgtk_im_use_context (dpyinfo, !NILP (use_p));
294
295 return Qnil;
296 }
297
298 void
299 syms_of_pgtkim (void)
300 {
301 defsubr (&Spgtk_use_im_context);
302
303 DEFSYM (Qpgtk_refresh_preedit, "pgtk-refresh-preedit");
304 DEFSYM (Qul, "ul");
305 DEFSYM (Qfg, "fg");
306 DEFSYM (Qbg, "bg");
307
308 DEFVAR_LISP ("pgtk-use-im-context-on-new-connection", Vpgtk_use_im_context_on_new_connection,
309 doc:
310
311 );
312 Vpgtk_use_im_context_on_new_connection = Qt;
313 }