1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */
2 /* IM-JA Japanese Input Method
3  *
4  * Copyright (C) 2003 Botond Botyanszki
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  *
20  * Based on handler.c from nabi by Choe Hwanjin
21  *
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27 
28 #include <X11/Xlib.h>
29 #include <X11/Xutil.h>
30 #include <X11/keysym.h>
31 #include <gtk/gtk.h>
32 #include <gdk/gdkkeysyms.h>
33 #include <gdk/gdkx.h>
34 
35 #include "IMdkit/IMdkit.h"
36 #include "IMdkit/Xi18n.h"
37 
38 #include "../error.h"
39 #include "../im-ja.h"
40 
41 #include "xim-ic.h"
42 #include "xim-server.h"
43 
44 extern IMJAXimServer *im_ja_xim_server;
45 
xim_protocol_name(int major_code)46 static const char *xim_protocol_name(int major_code) {
47 	switch (major_code) {
48 	case XIM_CONNECT:
49 		return "XIM_CONNECT";
50 	case XIM_CONNECT_REPLY:
51 		return "XIM_CONNECT_REPLY";
52 	case XIM_DISCONNECT:
53 		return "XIM_DISCONNECT";
54 	case XIM_DISCONNECT_REPLY:
55 		return "XIM_DISCONNECT_REPLY";
56 	case XIM_AUTH_REQUIRED:
57 		return "XIM_AUTH_REQUIRED";
58 	case XIM_AUTH_REPLY:
59 		return "XIM_AUTH_REPLY";
60 	case XIM_AUTH_NEXT:
61 		return "XIM_AUTH_NEXT";
62 	case XIM_AUTH_SETUP:
63 		return "XIM_AUTH_SETUP";
64 	case XIM_AUTH_NG:
65 		return "XIM_AUTH_NG";
66 	case XIM_ERROR:
67 		return "XIM_ERROR";
68 	case XIM_OPEN:
69 		return "XIM_OPEN";
70 	case XIM_OPEN_REPLY:
71 		return "XIM_OPEN_REPLY";
72 	case XIM_CLOSE:
73 		return "XIM_CLOSE";
74 	case XIM_CLOSE_REPLY:
75 		return "XIM_CLOSE_REPLY";
76 	case XIM_REGISTER_TRIGGERKEYS:
77 		return "XIM_REGISTER_TRIGGERKEYS";
78 	case XIM_TRIGGER_NOTIFY:
79 		return "XIM_TRIGGER_NOTIFY";
80 	case XIM_TRIGGER_NOTIFY_REPLY:
81 		return "XIM_TRIGGER_NOTIFY_REPLY";
82 	case XIM_SET_EVENT_MASK:
83 		return "XIM_SET_EVENT_MASK";
84 	case XIM_ENCODING_NEGOTIATION:
85 		return "XIM_ENCODING_NEGOTIATION";
86 	case XIM_ENCODING_NEGOTIATION_REPLY:
87 		return "XIM_ENCODING_NEGOTIATION_REPLY";
88 	case XIM_QUERY_EXTENSION:
89 		return "XIM_QUERY_EXTENSION";
90 	case XIM_QUERY_EXTENSION_REPLY:
91 		return "XIM_QUERY_EXTENSION_REPLY";
92 	case XIM_SET_IM_VALUES:
93 		return "XIM_SET_IM_VALUES";
94 	case XIM_SET_IM_VALUES_REPLY:
95 		return "XIM_SET_IM_VALUES_REPLY";
96 	case XIM_GET_IM_VALUES:
97 		return "XIM_GET_IM_VALUES";
98 	case XIM_GET_IM_VALUES_REPLY:
99 		return "XIM_GET_IM_VALUES_REPLY";
100 	case XIM_CREATE_IC:
101 		return "XIM_CREATE_IC";
102 	case XIM_CREATE_IC_REPLY:
103 		return "XIM_CREATE_IC_REPLY";
104 	case XIM_DESTROY_IC:
105 		return "XIM_DESTROY_IC";
106 	case XIM_DESTROY_IC_REPLY:
107 		return "XIM_DESTROY_IC_REPLY";
108 	case XIM_SET_IC_VALUES:
109 		return "XIM_SET_IC_VALUES";
110 	case XIM_SET_IC_VALUES_REPLY:
111 		return "XIM_SET_IC_VALUES_REPLY";
112 	case XIM_GET_IC_VALUES:
113 		return "XIM_GET_IC_VALUES";
114 	case XIM_GET_IC_VALUES_REPLY:
115 		return "XIM_GET_IC_VALUES_REPLY";
116 	case XIM_SET_IC_FOCUS:
117 		return "XIM_SET_IC_FOCUS";
118 	case XIM_UNSET_IC_FOCUS:
119 		return "XIM_UNSET_IC_FOCUS";
120 	case XIM_FORWARD_EVENT:
121 		return "XIM_FORWARD_EVENT";
122 	case XIM_SYNC:
123 		return "XIM_SYNC";
124 	case XIM_SYNC_REPLY:
125 		return "XIM_SYNC_REPLY";
126 	case XIM_COMMIT:
127 		return "XIM_COMMIT";
128 	case XIM_RESET_IC:
129 		return "XIM_RESET_IC";
130 	case XIM_RESET_IC_REPLY:
131 		return "XIM_RESET_IC_REPLY";
132 	case XIM_GEOMETRY:
133 		return "XIM_GEOMETRY";
134 	case XIM_STR_CONVERSION:
135 		return "XIM_STR_CONVERSION";
136 	case XIM_STR_CONVERSION_REPLY:
137 		return "XIM_STR_CONVERSION_REPLY";
138 	case XIM_PREEDIT_START:
139 		return "XIM_PREEDIT_START";
140 	case XIM_PREEDIT_START_REPLY:
141 		return "XIM_PREEDIT_START_REPLY";
142 	case XIM_PREEDIT_DRAW:
143 		return "XIM_PREEDIT_DRAW";
144 	case XIM_PREEDIT_CARET:
145 		return "XIM_PREEDIT_CARET";
146 	case XIM_PREEDIT_CARET_REPLY:
147 		return "XIM_PREEDIT_CARET_REPLY";
148 	case XIM_PREEDIT_DONE:
149 		return "XIM_PREEDIT_DONE";
150 	case XIM_STATUS_START:
151 		return "XIM_STATUS_START";
152 	case XIM_STATUS_DRAW:
153 		return "XIM_STATUS_DRAW";
154 	case XIM_STATUS_DONE:
155 		return "XIM_STATUS_DONE";
156 	default:
157 		break;
158 	}
159 
160 	return "XIM_UNKNOWN";
161 }
162 
im_ja_xim_handler_open(XIMS ims,IMProtocol * call_data)163 static Bool im_ja_xim_handler_open(XIMS ims, IMProtocol *call_data) {
164 	IMJAXimConnect* connect;
165 	IMOpenStruct *data = (IMOpenStruct *)call_data;
166 
167 	IM_JA_DEBUG("open connect_id = 0x%x\n", (int)data->connect_id);
168 
169 	connect = im_ja_xim_connect_create(data->connect_id);
170 	im_ja_xim_server_add_connect(connect);
171 
172 	return True;
173 }
174 
im_ja_xim_handler_close(XIMS ims,IMProtocol * call_data)175 static Bool im_ja_xim_handler_close(XIMS ims, IMProtocol *call_data) {
176 	IMCloseStruct *data = (IMCloseStruct *)call_data;
177 	IMJAXimConnect *connect;
178 
179 	IM_JA_DEBUG("im_ja_xim_handler_close: ");
180 
181 	connect = im_ja_xim_server_get_connect_by_id(data->connect_id);
182 	im_ja_xim_server_remove_connect(connect);
183 	im_ja_xim_connect_destroy(connect);
184 
185 	IM_JA_DEBUG("closing connect_id 0x%x\n", (int)data->connect_id);
186 	return True;
187 }
188 
im_ja_xim_handler_create_ic(XIMS ims,IMProtocol * call_data)189 static Bool im_ja_xim_handler_create_ic(XIMS ims, IMProtocol *call_data) {
190 	IMJAContext *ic;
191 	IMChangeICStruct *data = (IMChangeICStruct *)call_data;
192 
193 	IM_JA_DEBUG("im_ja_xim_handler_create_ic \t 0x%x\n", (int)data->connect_id);
194 
195 	ic = im_ja_xim_server_ic_create(data);
196 	im_ja_xim_connect_add_ic(ic->connect, ic);
197 
198 	return True;
199 }
200 
im_ja_xim_handler_destroy_ic(XIMS ims,IMProtocol * call_data)201 static Bool im_ja_xim_handler_destroy_ic(XIMS ims, IMProtocol *call_data) {
202 	IMJAContext *ic;
203 
204 	IM_JA_DEBUG("im_ja_xim_handler_destroy_ic\n");
205   ic = im_ja_xim_server_get_ic(call_data->changeic.icid);
206 
207 	if (ic != NULL) {
208 		im_ja_xim_connect_remove_ic(ic->connect, ic);
209 		im_ja_context_destroy(ic);
210 	}
211 
212 	return True;
213 }
214 
im_ja_xim_handler_set_ic_values(XIMS ims,IMProtocol * call_data)215 static Bool im_ja_xim_handler_set_ic_values(XIMS ims, IMProtocol *call_data) {
216 	IMChangeICStruct *data = (IMChangeICStruct *)call_data;
217 	IMJAContext *ic;
218 
219 	IM_JA_DEBUG("im_ja_xim_handler_set_ic_values\n");
220 	ic = im_ja_xim_server_get_ic(data->icid);
221 
222 	if (ic != NULL)  im_ja_xim_ic_set_values(ic, data);
223 
224 	return True;
225 }
226 
im_ja_xim_handler_get_ic_values(XIMS ims,IMProtocol * call_data)227 static Bool im_ja_xim_handler_get_ic_values(XIMS ims, IMProtocol *call_data) {
228 	IMChangeICStruct *data = (IMChangeICStruct *)call_data;
229 	IMJAContext *ic;
230 
231 	IM_JA_DEBUG("im_ja_xim_handler_get_ic_values\n");
232 
233 	ic = im_ja_xim_server_get_ic(data->icid);
234 
235 	if (ic != NULL) im_ja_xim_ic_get_values(ic, data);
236 	return True;
237 }
238 
im_ja_xim_handler_forward_event(XIMS ims,IMProtocol * call_data)239 static Bool im_ja_xim_handler_forward_event(XIMS ims, IMProtocol *call_data) {
240 	gchar buf[64];
241 	KeySym keysym;
242 	XKeyEvent *kevent;
243 	IMForwardEventStruct *data;
244 	GdkKeymap *keymap;
245 	GdkEvent *event;
246 	GdkDisplay *display;
247 	IMJAContext *ic;
248 
249 	IM_JA_DEBUG("im_ja_xim_handler_forward_event\n");
250 
251  	data = (IMForwardEventStruct *)call_data;
252 
253 	ic = im_ja_xim_server_get_ic(data->icid);
254 	if (ic == NULL) return True;
255 
256 	if (data->event.type != KeyPress) {
257 		IM_JA_DEBUG("Not a key press\n");
258 		return True;
259 	}
260 
261 	kevent = (XKeyEvent*)&data->event;
262 
263 	display = gdk_x11_lookup_xdisplay(im_ja_xim_server->display);
264 
265 	keymap = gdk_keymap_get_for_display(display);
266 	event = gdk_event_new(GDK_KEY_PRESS);
267 
268 	event->key.time = kevent->time;
269   event->key.state = (guint) kevent->state;
270   event->key.hardware_keycode = kevent->keycode;
271 	XLookupString(kevent, buf, 64, &keysym, NULL);
272 	event->key.keyval = keysym;
273 
274 	if (im_ja_filter_keypress(ic, &event->key) == TRUE) return True;
275 
276  	IMForwardEvent(ims, (XPointer)data);
277 	return True;
278 }
279 
im_ja_xim_handler_set_ic_focus(XIMS ims,IMProtocol * call_data)280 static Bool im_ja_xim_handler_set_ic_focus(XIMS ims, IMProtocol *call_data) {
281 	IMJAContext *ic;
282 
283 	IM_JA_DEBUG("im_ja_xim_handler_set_ic_focus\n");
284 
285 	ic = im_ja_xim_server_get_ic(call_data->changefocus.icid);
286 
287 	if (ic == NULL) return True;
288 
289 	if (ic->connect != NULL) im_ja_xim_ic_preedit_start(ic); /* FIXME */
290 	im_ja_got_focus(ic);
291 
292 	return True;
293 }
294 
im_ja_xim_handler_unset_ic_focus(XIMS ims,IMProtocol * call_data)295 static Bool im_ja_xim_handler_unset_ic_focus(XIMS ims, IMProtocol *call_data) {
296 	IMJAContext *ic;
297 
298 	IM_JA_DEBUG("im_ja_xim_handler_unset_ic_focus\n");
299 
300 	ic = im_ja_xim_server_get_ic(call_data->changefocus.icid);
301 	if (ic == NULL) return True;
302 	im_ja_lost_focus(ic);
303 
304 	return True;
305 }
306 
im_ja_xim_handler_reset_ic(XIMS ims,IMProtocol * call_data)307 static Bool im_ja_xim_handler_reset_ic(XIMS ims, IMProtocol *call_data) {
308 	IM_JA_DEBUG("FIXME: im_ja_xim_handler_reset_ic\n");
309 
310 	return True;
311 }
312 
im_ja_xim_handler_trigger_notify(XIMS ims,IMProtocol * call_data)313 static Bool im_ja_xim_handler_trigger_notify(XIMS ims, IMProtocol *call_data) {
314 	/*IMTriggerNotifyStruct *data = (IMTriggerNotifyStruct *)call_data;*/
315 
316 	IM_JA_DEBUG("FIXME: im_ja_xim_handler_trigger_notify\n");
317 	return True;
318 }
319 
im_ja_xim_handler_preedit_start_reply(XIMS ims,IMProtocol * call_data)320 static Bool im_ja_xim_handler_preedit_start_reply(XIMS ims, IMProtocol *call_data) {
321 	IM_JA_DEBUG("FIXME: im_ja_xim_handler_preedit_start_reply\n");
322 	return True;
323 }
324 
im_ja_xim_handler_preedit_caret_reply(XIMS ims,IMProtocol * call_data)325 static Bool im_ja_xim_handler_preedit_caret_reply(XIMS ims, IMProtocol *call_data) {
326 	IM_JA_DEBUG("FIXME: im_ja_xim_handler_preedit_caret_reply\n");
327 	return True;
328 }
329 
im_ja_xim_handler(XIMS ims,IMProtocol * call_data)330 Bool im_ja_xim_handler(XIMS ims, IMProtocol *call_data) {
331     IM_JA_DEBUG("im_ja_xim_handler: %s\t 0x%x 0x%x\n",
332 								xim_protocol_name(call_data->major_code),
333 								call_data->any.connect_id,
334 								call_data->changeic.icid);
335 
336     switch (call_data->major_code) {
337     case XIM_OPEN:
338 	    return im_ja_xim_handler_open(ims, call_data);
339     case XIM_CLOSE:
340 	    return im_ja_xim_handler_close(ims, call_data);
341     case XIM_CREATE_IC:
342 	    return im_ja_xim_handler_create_ic(ims, call_data);
343     case XIM_DESTROY_IC:
344 	    return im_ja_xim_handler_destroy_ic(ims, call_data);
345     case XIM_SET_IC_VALUES:
346 	    return im_ja_xim_handler_set_ic_values(ims, call_data);
347     case XIM_GET_IC_VALUES:
348 	    return im_ja_xim_handler_get_ic_values(ims, call_data);
349     case XIM_FORWARD_EVENT:
350 	    return im_ja_xim_handler_forward_event(ims, call_data);
351     case XIM_SET_IC_FOCUS:
352 	    return im_ja_xim_handler_set_ic_focus(ims, call_data);
353     case XIM_UNSET_IC_FOCUS:
354 	    return im_ja_xim_handler_unset_ic_focus(ims, call_data);
355     case XIM_RESET_IC:
356 	    return im_ja_xim_handler_reset_ic(ims, call_data);
357     case XIM_TRIGGER_NOTIFY:
358 	    return im_ja_xim_handler_trigger_notify(ims, call_data);
359     case XIM_PREEDIT_START_REPLY:
360 	    return im_ja_xim_handler_preedit_start_reply(ims, call_data);
361     case XIM_PREEDIT_CARET_REPLY:
362 	    return im_ja_xim_handler_preedit_caret_reply(ims, call_data);
363     default:
364 	    IM_JA_DEBUG("Unknown IMDKit Protocol message type\n");
365 	    break;
366     }
367     return True;
368 }
369