Mercurial > kinput2.yaz
comparison lib/imlib/imrequest.c @ 0:92745d501b9a
initial import from kinput2-v3.1
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Mon, 08 Mar 2010 04:44:30 +0900 |
parents | |
children | 1f9e9cb00c6c |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:92745d501b9a |
---|---|
1 #ifndef lint | |
2 static char *rcsid = "$Id: imrequest.c,v 1.19 2002/01/27 11:33:37 ishisone Exp $"; | |
3 #endif | |
4 /* | |
5 * Copyright (c) 1994 Software Research Associates, Inc. | |
6 * | |
7 * Permission to use, copy, modify, and distribute this software and its | |
8 * documentation for any purpose and without fee is hereby granted, provided | |
9 * that the above copyright notice appear in all copies and that both that | |
10 * copyright notice and this permission notice appear in supporting | |
11 * documentation, and that the name of Software Research Associates not be | |
12 * used in advertising or publicity pertaining to distribution of the | |
13 * software without specific, written prior permission. Software Research | |
14 * Associates makes no representations about the suitability of this software | |
15 * for any purpose. It is provided "as is" without express or implied | |
16 * warranty. | |
17 * | |
18 * Author: Makoto Ishisone, Software Research Associates, Inc., Japan | |
19 */ | |
20 | |
21 /* in order to include xEvent definition */ | |
22 #define NEED_EVENTS | |
23 #include <X11/Xproto.h> | |
24 | |
25 #include "im.h" | |
26 #include "imreq.h" | |
27 | |
28 /* | |
29 * Request handle functions | |
30 */ | |
31 static void ximDisconnectProc _Pt_((IMConnection *, int, int, int)); | |
32 static void ximErrorProc _Pt_((IMConnection *, int, int, int)); | |
33 static void ximOpenProc _Pt_((IMConnection *, int, int, int)); | |
34 static void ximCloseProc _Pt_((IMConnection *, int, int, int)); | |
35 static void ximTriggerNotifyProc _Pt_((IMConnection *, int, int, int)); | |
36 static void ximEncodingNegotiationProc _Pt_((IMConnection *, int, int, int)); | |
37 static void ximQueryExtensionProc _Pt_((IMConnection *, int, int, int)); | |
38 static void ximSetIMValuesProc _Pt_((IMConnection *, int, int, int)); | |
39 static void ximGetIMValuesProc _Pt_((IMConnection *, int, int, int)); | |
40 static void ximCreateICProc _Pt_((IMConnection *, int, int, int)); | |
41 static void ximDestroyICProc _Pt_((IMConnection *, int, int, int)); | |
42 static void ximSetICValuesProc _Pt_((IMConnection *, int, int, int)); | |
43 static void ximGetICValuesProc _Pt_((IMConnection *, int, int, int)); | |
44 static void ximSetICFocusProc _Pt_((IMConnection *, int, int, int)); | |
45 static void ximUnsetICFocusProc _Pt_((IMConnection *, int, int, int)); | |
46 static void ximForwardEventProc _Pt_((IMConnection *, int, int, int)); | |
47 static void ximExtForwardKeyeventProc _Pt_((IMConnection *, int, int, int)); | |
48 static void ximSyncProc _Pt_((IMConnection *, int, int, int)); | |
49 static void ximSyncReplyProc _Pt_((IMConnection *, int, int, int)); | |
50 static void ximResetICProc _Pt_((IMConnection *, int, int, int)); | |
51 static void ximExtMoveProc _Pt_((IMConnection *, int, int, int)); | |
52 | |
53 static void ximAlreadyConnectedProc _Pt_((IMConnection *, int, int, int)); | |
54 static void ximShouldNotBeSentProc _Pt_((IMConnection *, int, int, int)); | |
55 static void ximAuthPhaseProc _Pt_((IMConnection *, int, int, int)); | |
56 static void ximNopProc _Pt_((IMConnection *, int, int, int)); | |
57 | |
58 /* | |
59 * Core request table | |
60 */ | |
61 static IMRequest coreRequestTbl[] = { | |
62 { "CONNECT", XIM_CONNECT, 0, ximAlreadyConnectedProc }, | |
63 { "CONNECT-REPLY", XIM_CONNECT_REPLY, 0, ximShouldNotBeSentProc }, | |
64 { "DISCONNECT", XIM_DISCONNECT, 0, ximDisconnectProc }, | |
65 { "DISCONNECT-REPLY", XIM_DISCONNECT_REPLY, 0, ximShouldNotBeSentProc }, | |
66 { "AUTH-REQUIRED", XIM_AUTH_REQUIRED, 0, ximAuthPhaseProc }, | |
67 { "AUTH-REPLY", XIM_AUTH_REPLY, 0, ximAuthPhaseProc }, | |
68 { "AUTH-NEXT", XIM_AUTH_NEXT, 0, ximAuthPhaseProc }, | |
69 { "AUTH-SETUP", XIM_AUTH_SETUP, 0, ximShouldNotBeSentProc }, | |
70 { "AUTH-NG", XIM_AUTH_NG, 0, ximAuthPhaseProc }, | |
71 { "ERROR", XIM_ERROR, 0, ximErrorProc }, | |
72 { "OPEN", XIM_OPEN, 0, ximOpenProc }, | |
73 { "OPEN-REPLY", XIM_OPEN_REPLY, 0, ximShouldNotBeSentProc }, | |
74 { "CLOSE", XIM_CLOSE, 0, ximCloseProc }, | |
75 { "CLOSE-REPLY", XIM_CLOSE_REPLY, 0, ximShouldNotBeSentProc }, | |
76 { "SET-EVENT-MASK", XIM_SET_EVENT_MASK, 0, ximShouldNotBeSentProc }, | |
77 { "REGISTER-TRIGGERKEYS", XIM_REGISTER_TRIGGERKEYS, 0, | |
78 ximShouldNotBeSentProc }, | |
79 { "TRIGGER-NOTIFY", XIM_TRIGGER_NOTIFY, 0, ximTriggerNotifyProc }, | |
80 { "TRIGGER-NOTIFY-REPLY", XIM_TRIGGER_NOTIFY_REPLY, 0, | |
81 ximShouldNotBeSentProc }, | |
82 { "ENCODING-NEGOTIATION", XIM_ENCODING_NEGOTIATION, 0, | |
83 ximEncodingNegotiationProc }, | |
84 { "ENCODING-NEGOTIATION-REPLY", XIM_ENCODING_NEGOTIATION_REPLY, 0, | |
85 ximShouldNotBeSentProc }, | |
86 { "QUERY-EXTENSION", XIM_QUERY_EXTENSION, 0, ximQueryExtensionProc }, | |
87 { "QUERY-EXTENSION-REPLY", XIM_QUERY_EXTENSION_REPLY, 0, | |
88 ximShouldNotBeSentProc }, | |
89 { "SET-IM-VALUES", XIM_SET_IM_VALUES, 0, ximSetIMValuesProc }, | |
90 { "SET-IM-VALUES-REPLY", XIM_SET_IM_VALUES_REPLY, 0, | |
91 ximShouldNotBeSentProc }, | |
92 { "GET-IM-VALUES", XIM_GET_IM_VALUES, 0, ximGetIMValuesProc }, | |
93 { "GET-IM-VALUES-REPLY", XIM_GET_IM_VALUES_REPLY, 0, | |
94 ximShouldNotBeSentProc }, | |
95 { "CREATE-IC", XIM_CREATE_IC, 0, ximCreateICProc }, | |
96 { "CREATE-IC-REPLY", XIM_CREATE_IC_REPLY, 0, ximShouldNotBeSentProc }, | |
97 { "DESTROY-IC", XIM_DESTROY_IC, 0, ximDestroyICProc }, | |
98 { "DESTROY-IC-REPLY", XIM_DESTROY_IC_REPLY, 0, ximShouldNotBeSentProc }, | |
99 { "SET-IC-VALUES", XIM_SET_IC_VALUES, 0, ximSetICValuesProc }, | |
100 { "SET-IC-VALUES-REPLY", XIM_SET_IC_VALUES_REPLY, 0, | |
101 ximShouldNotBeSentProc }, | |
102 { "GET-IC-VALUES", XIM_GET_IC_VALUES, 0, ximGetICValuesProc }, | |
103 { "GET-IC-VALUES-REPLY", XIM_GET_IC_VALUES_REPLY, 0, | |
104 ximShouldNotBeSentProc }, | |
105 { "SET-IC-FOCUS", XIM_SET_IC_FOCUS, 0, ximSetICFocusProc }, | |
106 { "UNSET-IC-FOCUS", XIM_UNSET_IC_FOCUS, 0, ximUnsetICFocusProc }, | |
107 { "FORWARD-EVENT", XIM_FORWARD_EVENT, 0, ximForwardEventProc }, | |
108 { "SYNC", XIM_SYNC, 0, ximSyncProc }, | |
109 { "SYNC-REPLY", XIM_SYNC_REPLY, 0, ximSyncReplyProc }, | |
110 { "COMMIT", XIM_COMMIT, 0, ximShouldNotBeSentProc }, | |
111 { "RESET-IC", XIM_RESET_IC, 0, ximResetICProc }, | |
112 { "RESET-IC-REPLY", XIM_RESET_IC_REPLY, 0, ximShouldNotBeSentProc }, | |
113 { "GEOMETRY", XIM_GEOMETRY, 0, ximShouldNotBeSentProc }, | |
114 { "STR-CONVERSION", XIM_STR_CONVERSION, 0, ximShouldNotBeSentProc }, | |
115 { "STR-CONVERSION-REPLY", XIM_STR_CONVERSION_REPLY, 0, | |
116 ximShouldNotBeSentProc }, | |
117 { "PREEDIT-START", XIM_PREEDIT_START, 0, ximShouldNotBeSentProc }, | |
118 { "PREEDIT-START-REPLY", XIM_PREEDIT_START_REPLY, 0, | |
119 ximNopProc }, | |
120 { "PREEDIT-DRAW", XIM_PREEDIT_DRAW, 0, ximShouldNotBeSentProc }, | |
121 { "PREEDIT-CARET", XIM_PREEDIT_CARET, 0, ximShouldNotBeSentProc }, | |
122 { "PREEDIT-CARET-REPLY", XIM_PREEDIT_CARET_REPLY, 0, | |
123 ximNopProc }, | |
124 { "PREEDIT-DONE", XIM_PREEDIT_DONE, 0, ximShouldNotBeSentProc }, | |
125 { "PREEDITSTATE", XIM_PREEDITSTATE, 0, ximShouldNotBeSentProc }, | |
126 { "STATUS-START", XIM_STATUS_START, 0, ximShouldNotBeSentProc }, | |
127 { "STATUS-DRAW", XIM_STATUS_DRAW, 0, ximShouldNotBeSentProc }, | |
128 { "STATUS-DONE", XIM_STATUS_DONE, 0, ximShouldNotBeSentProc }, | |
129 { NULL, 0, 0, NULL }, | |
130 }; | |
131 | |
132 /* | |
133 * Extension request table | |
134 */ | |
135 static IMRequest extRequestTbl[] = { | |
136 { "XIM_EXT_SET_EVENT_MASK", XIM_EXT_SET_EVENT_MASK, 0, | |
137 ximShouldNotBeSentProc, XIM_EXT_SET_EVENT_MASK_MASK }, | |
138 { "XIM_EXT_FORWARD_KEYEVENT", XIM_EXT_FORWARD_KEYEVENT, 0, | |
139 ximExtForwardKeyeventProc, XIM_EXT_FORWARD_KEYEVENT_MASK }, | |
140 { "XIM_EXT_MOVE", XIM_EXT_MOVE, 0, | |
141 ximExtMoveProc, XIM_EXT_MOVE_MASK }, | |
142 { NULL, 0, 0, NULL }, | |
143 }; | |
144 | |
145 /* | |
146 * Request dispatch table (global) | |
147 */ | |
148 IMRequest *IMMainDispatchTable[256]; | |
149 | |
150 | |
151 static void compileTbl _Pt_((IMRequest *req)); | |
152 static char *ecode2str _Pt_((int code)); | |
153 static void putTriggerkeyList _Pt_((IMIM *imp)); | |
154 static int findCtext _Pt_((IMConnection *conn, int arglen)); | |
155 static IMRequest *getExtension _Pt_((char *name)); | |
156 static void putExtension _Pt_((IMConnection *conn, IMRequest *req)); | |
157 static void swapData _Pt_((char *data, char *format)); | |
158 static int getEvent _Pt_((IMConnection *conn, unsigned int serial, | |
159 int offset, XEvent *ev)); | |
160 static void postponeEvent _Pt_((IMIC *icp, int synchronous, XEvent *ev)); | |
161 static void handleForwardedEvent _Pt_((IMIC *icp, int synchronous, XEvent *ev)); | |
162 static void processPendingEvents _Pt_((IMIC *icp, | |
163 IMPendingEvent *pending_event)); | |
164 | |
165 | |
166 /*- compileTbl: assemble IMMainDispatchTbl -*/ | |
167 static void | |
168 compileTbl(req) | |
169 IMRequest *req; | |
170 { | |
171 while (req->name != NULL) { | |
172 req->next = IMMainDispatchTable[req->major]; | |
173 IMMainDispatchTable[req->major] = req; | |
174 req++; | |
175 } | |
176 } | |
177 | |
178 /*- ximDisconnectProc: handle XIM_DISCONNECT request -*/ | |
179 /* ARGSUSED */ | |
180 static void | |
181 ximDisconnectProc(conn, major, minor, arglen) | |
182 IMConnection *conn; | |
183 int major; | |
184 int minor; | |
185 int arglen; | |
186 { | |
187 IMIM *imp = conn->im_list; | |
188 IMIM *imp_next; | |
189 | |
190 TRACE(("ximDisconnectProc(#%d)\n", conn->serial)); | |
191 | |
192 if (arglen != 0) { | |
193 DPRINT(("ximDisconnectProc: arglen != 0\n")); | |
194 IMSendBadLength(conn, 0, 0); | |
195 return; | |
196 } | |
197 | |
198 while (imp != NULL) { | |
199 imp_next = imp->next; | |
200 IMDestroyIM(imp); | |
201 imp = imp_next; | |
202 } | |
203 IMSendSimpleRequest(conn, XIM_DISCONNECT_REPLY, 0); | |
204 IMSchedule(conn, SCHED_CLOSE); | |
205 } | |
206 | |
207 /*- ecode2str: error code to error name string converter -*/ | |
208 static char * | |
209 ecode2str(code) | |
210 int code; | |
211 { | |
212 char *s; | |
213 | |
214 switch (code) { | |
215 case IMBadAlloc: s = "BadAlloc"; break; | |
216 case IMBadStyle: s = "BadStyle"; break; | |
217 case IMBadClientWindow: s = "BadClientWindow"; break; | |
218 case IMBadFocusWindow: s = "BadFocusWindow"; break; | |
219 case IMBadArea: s = "BadArea"; break; | |
220 case IMBadSpotLocation: s = "BadSpotLocation"; break; | |
221 case IMBadColormap: s = "BadColormap"; break; | |
222 case IMBadAtom: s = "BadAtom"; break; | |
223 case IMBadPixel: s = "BadPixel"; break; | |
224 case IMBadPixmap: s = "BadPixmap"; break; | |
225 case IMBadName: s = "BadName"; break; | |
226 case IMBadCursor: s = "BadCursor"; break; | |
227 case IMBadProtocol: s = "BadProtocol"; break; | |
228 case IMBadForeground: s = "BadForeground"; break; | |
229 case IMBadBackground: s = "BadBackground"; break; | |
230 case IMLocaleNotSupported: s = "LocaleNotSupported"; break; | |
231 case IMBadSomething: s = "BadSomething"; break; | |
232 default: s = "? (undefined error code)"; break; | |
233 } | |
234 return s; | |
235 } | |
236 | |
237 /*- ximErrorProc: handle XIM_Error messsage -*/ | |
238 /* ARGSUSED */ | |
239 static void | |
240 ximErrorProc(conn, major, minor, arglen) | |
241 IMConnection *conn; | |
242 int major; | |
243 int minor; | |
244 int arglen; | |
245 { | |
246 unsigned int imid, icid; | |
247 int flag; | |
248 int code; | |
249 int msg_len; | |
250 char msg[256 + 1]; | |
251 | |
252 TRACE(("ximErrorProc(#%d)\n", conn->serial)); | |
253 | |
254 if (arglen < 10) { | |
255 DPRINT(("corrupted XIM_ERROR message (arglen < 10) received\n")); | |
256 return; | |
257 } | |
258 imid = IMGetC16(conn, 0); | |
259 icid = IMGetC16(conn, 2); | |
260 flag = IMGetC16(conn, 4); | |
261 code = IMGetC16(conn, 6); | |
262 msg_len = IMGetC16(conn, 8); | |
263 if (msg_len > 0) { | |
264 if (msg_len + 12 > arglen) { | |
265 DPRINT(("corrupted XIM_ERROR message (message too long) received\n")); | |
266 return; | |
267 } | |
268 if (msg_len > 256) msg_len = 256; | |
269 IMGetString(conn, 12, msg, msg_len); | |
270 } | |
271 if (DEBUG_CONDITION) { | |
272 printf("** XIM_ERROR message received:\n"); | |
273 if (flag & 1) { | |
274 printf("\t input-method ID: %d\n", imid); | |
275 } else { | |
276 printf("\t input-method ID: N/A\n"); | |
277 } | |
278 if (flag & 2) { | |
279 printf("\tinput-context ID: %d\n", icid); | |
280 } else { | |
281 printf("\tinput-context ID: N/A\n"); | |
282 } | |
283 printf("\t error code: %s\n", ecode2str(code)); | |
284 printf("\t error message: %s\n", msg); | |
285 } | |
286 } | |
287 | |
288 /*- putTriggerkeyList: put trigger key list on the output stream -*/ | |
289 static void | |
290 putTriggerkeyList(imp) | |
291 IMIM *imp; | |
292 { | |
293 IMConnection *conn = imp->connection; | |
294 IMTriggerKey *triggers; | |
295 int num_triggers; | |
296 int i; | |
297 | |
298 triggers = IMTriggerKeys(imp, &num_triggers); | |
299 | |
300 IMPutC32(conn, (unsigned long)(12 * num_triggers)); | |
301 for (i = 0; i < num_triggers; i++) { | |
302 IMPutC32(conn, triggers[i].keysym); | |
303 IMPutC32(conn, (unsigned long)triggers[i].modifiers); | |
304 IMPutC32(conn, (unsigned long)triggers[i].check_modifiers); | |
305 } | |
306 } | |
307 | |
308 /*- ximOpenProc: handle XIM_OPEN request -*/ | |
309 /* ARGSUSED */ | |
310 static void | |
311 ximOpenProc(conn, major, minor, arglen) | |
312 IMConnection *conn; | |
313 int major; | |
314 int minor; | |
315 int arglen; | |
316 { | |
317 int locale_len; | |
318 char localename[256 + 1]; | |
319 int offset; | |
320 IMConverter *icp; | |
321 IMIM *imp; | |
322 | |
323 TRACE(("ximOpenProc(#%d)\n", conn->serial)); | |
324 | |
325 if (arglen < 1) { | |
326 DPRINT(("ximOpenProc: arglen < 1\n")); | |
327 IMSendBadLength(conn, 0, 0); | |
328 return; | |
329 } | |
330 | |
331 locale_len = IMGetC8(conn, 0); | |
332 if (arglen < locale_len + 1) { | |
333 DPRINT(("ximOpenProc: locale too long\n")); | |
334 IMSendBadLength(conn, 0, 0); | |
335 return; | |
336 } | |
337 | |
338 bcopy(IMBUFDATA(IM_INBUF(conn)) + 1, localename, locale_len); | |
339 localename[locale_len] = '\0'; | |
340 TRACE(("\tlocalename: %s\n", localename)); | |
341 | |
342 if ((icp = IMGetConverter(conn->proto_widget, localename)) == NULL) { | |
343 DPRINT(("ximOpenProc: unsupported locale %s\n", localename)); | |
344 IMSendError(conn, IMLocaleNotSupported, 0, 0, "unknown locale"); | |
345 return; | |
346 } | |
347 | |
348 imp = IMCreateIM(conn, icp); | |
349 | |
350 /* | |
351 * Send open reply message. | |
352 */ | |
353 offset = IMPutHeader(conn, XIM_OPEN_REPLY, 0, 0); | |
354 IMPutC16(conn, imp->id); | |
355 IMPutIMAttrList(imp); | |
356 IMPutICAttrList(imp); | |
357 IMFinishRequest(conn, offset); | |
358 | |
359 /* | |
360 * Notify conversion trigger keys. | |
361 * | |
362 * Note: | |
363 * The spec says that XIM_REGISTER_TRIGGERKEYS message should | |
364 * be sent to the client bofore XIM_OPEN_REPLY message, in | |
365 * order to use dynamic event flow model. However, this | |
366 * does not work with current Xlib implementation. So we | |
367 * send XIM_REGISTER_TRIGGERKEYS just after XIM_OPEN_REPLY, | |
368 * which works fine. | |
369 */ | |
370 offset = IMPutHeader(conn, XIM_REGISTER_TRIGGERKEYS, 0, 0); | |
371 IMPutC16(conn, imp->id); | |
372 IMPutC16(conn, 0); | |
373 putTriggerkeyList(imp); | |
374 IMFinishRequest(conn, offset); | |
375 } | |
376 | |
377 /*- ximCloseProc: handle XIM_CLOSE request -*/ | |
378 /* ARGSUSED */ | |
379 static void | |
380 ximCloseProc(conn, major, minor, arglen) | |
381 IMConnection *conn; | |
382 int major; | |
383 int minor; | |
384 int arglen; | |
385 { | |
386 IMIM *imp; | |
387 | |
388 TRACE(("ximCloseProc(#%d)\n", conn->serial)); | |
389 | |
390 if ((imp = IMGetIM(conn, arglen)) == NULL) return; | |
391 if (arglen != 4) { | |
392 DPRINT(("ximCloseProc: arglen != 4\n")); | |
393 IMSendBadLength(conn, imp->id, 0); | |
394 return; | |
395 } | |
396 | |
397 IMPutHeader(conn, XIM_CLOSE_REPLY, 0, 4); | |
398 IMPutC16(conn, imp->id); | |
399 IMPutPad(conn); | |
400 IMSchedule(conn, SCHED_WRITE); | |
401 | |
402 IMDestroyIM(imp); | |
403 } | |
404 | |
405 /*- ximTriggerNotifyProc: handle XIM_TRIGGER_NOTIFY request -*/ | |
406 /* ARGSUSED */ | |
407 static void | |
408 ximTriggerNotifyProc(conn, major, minor, arglen) | |
409 IMConnection *conn; | |
410 int major; | |
411 int minor; | |
412 int arglen; | |
413 { | |
414 IMIC *icp; | |
415 int flag; | |
416 int key_index; | |
417 int num_triggers; | |
418 | |
419 TRACE(("ximTriggerNotifyProc(#%d)\n", conn->serial)); | |
420 | |
421 if ((icp = IMGetIC(conn, arglen)) == NULL) return; | |
422 | |
423 if (arglen != 16) { | |
424 DPRINT(("ximTriggerNotifyProc: arglen != 16\n")); | |
425 IMSendBadLength(conn, icp->im->id, icp->id); | |
426 return; | |
427 } | |
428 | |
429 flag = (int)IMGetC32(conn, 4); | |
430 key_index = (int)IMGetC32(conn, 8); | |
431 TRACE(("\tflag=%d, index=%d\n", flag, key_index)); | |
432 | |
433 /* | |
434 * Check flag and index. Since kinput2 does not | |
435 * specifiy off-keys, any off-key notifications | |
436 * are invalid. | |
437 * The current Xlib implementation (as of pl4) | |
438 * specifies incorrect key_index, so index check | |
439 * is turned off until the bug is fixed. | |
440 */ | |
441 | |
442 (void)IMTriggerKeys(icp->im, &num_triggers); | |
443 if (flag != 0 | |
444 #ifndef XIM_BC | |
445 || key_index >= num_triggers | |
446 #endif /* XIM_BC */ | |
447 ) { | |
448 /* invalid parameter */ | |
449 DPRINT(("ximTriggerNotifyProc: invalid trigger spec.\n")); | |
450 IMSendError(conn, IMBadSomething, icp->im->id, icp->id, | |
451 "invalid trigger key specification"); | |
452 return; | |
453 } | |
454 | |
455 /* | |
456 * If we are already in conversion mode, do nothing special. | |
457 */ | |
458 if (!(icp->state & IC_CONVERTING)) { | |
459 /* | |
460 * Start conversion. | |
461 */ | |
462 if (IMStartConversion(icp) < 0) return; | |
463 } | |
464 | |
465 /* | |
466 * Send XIM_TRIGGER_NOTIFY_REPLY request. | |
467 */ | |
468 (void)IMPutHeader(conn, XIM_TRIGGER_NOTIFY_REPLY, 0, 4); | |
469 IMPutC16(conn, icp->im->id); | |
470 IMPutC16(conn, icp->id); | |
471 IMSchedule(conn, SCHED_WRITE); | |
472 } | |
473 | |
474 /*- findCtext: look up COMPOUND_TEXT from encoding list -*/ | |
475 static int | |
476 findCtext(conn, arglen) | |
477 IMConnection *conn; | |
478 int arglen; | |
479 { | |
480 int offset, name_end; | |
481 int encoding_index; | |
482 unsigned int name_bytes; | |
483 | |
484 offset = 2; | |
485 name_bytes = IMGetC16(conn, offset); | |
486 offset += 2; | |
487 name_end = offset + name_bytes; | |
488 if (name_end > arglen) return -2; | |
489 | |
490 /* | |
491 * Examine encodings listed by name. | |
492 */ | |
493 encoding_index = 0; | |
494 while (offset < name_end) { | |
495 char str_buf[256 + 1]; | |
496 int str_len; | |
497 | |
498 str_len = IMGetC8(conn, offset++); | |
499 IMGetString(conn, offset, str_buf, str_len); | |
500 if (!strcmp(str_buf, "COMPOUND_TEXT")) { | |
501 return encoding_index; | |
502 } | |
503 offset += str_len; | |
504 encoding_index++; | |
505 } | |
506 | |
507 /* | |
508 * Encodings listed by detailed data follow, but | |
509 * I have no idea what they are. | |
510 */ | |
511 return -1; | |
512 } | |
513 | |
514 /*- ximEncodingNegotiationProc: handle XIM_ENCODING_NEGOTIATION request -*/ | |
515 /* ARGSUSED */ | |
516 static void | |
517 ximEncodingNegotiationProc(conn, major, minor, arglen) | |
518 IMConnection *conn; | |
519 int major; | |
520 int minor; | |
521 int arglen; | |
522 { | |
523 IMIM *imp; | |
524 int encoding_index; | |
525 | |
526 TRACE(("ximEncodingNegotiationProc(#%d)\n", conn->serial)); | |
527 | |
528 if ((imp = IMGetIM(conn, arglen)) == NULL) return; | |
529 | |
530 if (arglen < 8) { | |
531 DPRINT(("ximEncodingNegotiationProc: arglen < 8\n")); | |
532 IMSendBadLength(conn, imp->id, 0); | |
533 return; | |
534 } | |
535 | |
536 /* | |
537 * Always use COMPOUND_TEXT. | |
538 */ | |
539 if ((encoding_index = findCtext(conn, arglen)) < -1) { | |
540 /* bad argument error */ | |
541 DPRINT(("ximEncodingNegotiationProc: encoding list corrupted\n")); | |
542 IMSendError(conn, IMBadSomething, imp->id, 0, | |
543 "corrupted argument"); | |
544 return; | |
545 } | |
546 TRACE(("\tselected encoding index: %d\n", encoding_index)); | |
547 | |
548 (void)IMPutHeader(conn, XIM_ENCODING_NEGOTIATION_REPLY, 0, 8); | |
549 IMPutC16(conn, imp->id); | |
550 IMPutC16(conn, 0); | |
551 IMPutI16(conn, encoding_index); | |
552 IMPutPad(conn); | |
553 IMSchedule(conn, SCHED_WRITE); | |
554 } | |
555 | |
556 /*- getExtension: search named extension -*/ | |
557 static IMRequest * | |
558 getExtension(name) | |
559 char *name; | |
560 { | |
561 IMRequest *req = extRequestTbl; | |
562 | |
563 while (req->name != NULL) { | |
564 if (!strcmp(req->name, name)) return req; | |
565 req++; | |
566 } | |
567 return NULL; | |
568 } | |
569 | |
570 /*- putExtension: put extension information on the output stream -*/ | |
571 static void | |
572 putExtension(conn, req) | |
573 IMConnection *conn; | |
574 IMRequest *req; | |
575 { | |
576 int text_length; | |
577 | |
578 text_length = strlen(req->name); | |
579 IMPutC8(conn, req->major); | |
580 IMPutC8(conn, req->minor); | |
581 IMPutC16(conn, (unsigned int)text_length); | |
582 IMPutString(conn, req->name, text_length); | |
583 IMPutPad(conn); | |
584 } | |
585 | |
586 /*- ximQueryExtensionProc: handle XIM_QUERY_EXTENSION request -*/ | |
587 /* ARGSUSED */ | |
588 static void | |
589 ximQueryExtensionProc(conn, major, minor, arglen) | |
590 IMConnection *conn; | |
591 int major; | |
592 int minor; | |
593 int arglen; | |
594 { | |
595 IMIM *imp; | |
596 int ext_len; | |
597 int cur_off; | |
598 int req_offset; | |
599 int size_offset; | |
600 int list_start, list_end; | |
601 | |
602 TRACE(("ximQueryExtensionProc(#%d)\n", conn->serial)); | |
603 | |
604 if ((imp = IMGetIM(conn, arglen)) == NULL) return; | |
605 if (arglen < 4) { | |
606 DPRINT(("ximQueryExtensionProc: arglen < 4\n")); | |
607 IMSendBadLength(conn, imp->id, 0); | |
608 return; | |
609 } | |
610 ext_len = IMGetC16(conn, 2); | |
611 if (4 + ext_len > arglen) { | |
612 DPRINT(("ximQueryExtensionProc: extension list too long\n")); | |
613 IMSendBadLength(conn, imp->id, 0); | |
614 return; | |
615 } | |
616 cur_off = 4; | |
617 | |
618 req_offset = IMPutHeader(conn, XIM_QUERY_EXTENSION_REPLY, 0, 0); | |
619 IMPutC16(conn, imp->id); | |
620 size_offset = IMWritePos(conn); | |
621 IMPutC16(conn, 0); /* dummy. overwritten afterwards */ | |
622 | |
623 list_start = IMWritePos(conn); | |
624 | |
625 if (ext_len == 0) { | |
626 IMRequest *ext_req = extRequestTbl; | |
627 | |
628 while (ext_req->name != NULL) { | |
629 putExtension(conn, ext_req); | |
630 ext_req++; | |
631 } | |
632 | |
633 } else { | |
634 IMRequest *ext_req; | |
635 | |
636 while (ext_len > 1) { | |
637 int str_len; | |
638 char ext_name[256 + 1]; | |
639 | |
640 str_len = IMGetC8(conn, cur_off); | |
641 cur_off++; | |
642 | |
643 if (str_len + 1 > ext_len) { | |
644 DPRINT(("ximQueryExtensionProc: extension name too long\n")); | |
645 IMCancelRequest(conn, req_offset); | |
646 /* BadString */ | |
647 IMSendBadLength(conn, imp->id, 0); | |
648 return; | |
649 } | |
650 | |
651 IMGetString(conn, cur_off, ext_name, str_len); | |
652 TRACE(("\tclient queries %s extension\n", ext_name)); | |
653 | |
654 if ((ext_req = getExtension(ext_name)) != NULL) { | |
655 putExtension(conn, ext_req); | |
656 imp->mask |= ext_req->mask; | |
657 } | |
658 cur_off += str_len; | |
659 ext_len -= str_len + 1; | |
660 } | |
661 } | |
662 | |
663 list_end = IMWritePos(conn); | |
664 IMRewriteC16(conn, size_offset, (unsigned int)(list_end - list_start)); | |
665 | |
666 IMFinishRequest(conn, req_offset); | |
667 } | |
668 | |
669 /*- ximSetIMValuesProc: handle XIM_SET_IM_VALUES request -*/ | |
670 /* ARGSUSED */ | |
671 static void | |
672 ximSetIMValuesProc(conn, major, minor, arglen) | |
673 IMConnection *conn; | |
674 int major; | |
675 int minor; | |
676 int arglen; | |
677 { | |
678 IMIM *imp; | |
679 char *attr; | |
680 int attr_len; | |
681 | |
682 TRACE(("ximSetIMValuesProc(#%d)\n", conn->serial)); | |
683 | |
684 if ((imp = IMGetIM(conn, arglen)) == NULL) return; | |
685 if (arglen < 4) { | |
686 DPRINT(("ximSetIMValuesProc: arglen < 4\n")); | |
687 IMSendBadLength(conn, imp->id, 0); | |
688 return; | |
689 } | |
690 | |
691 attr_len = IMGetC16(conn, 2); | |
692 attr = IMBUFDATA(IM_INBUF(conn)) + 4; | |
693 | |
694 if (arglen < attr_len + 4) { | |
695 DPRINT(("ximSetIMValuesProc: attribute len too long\n")); | |
696 IMSendBadLength(conn, imp->id, 0); | |
697 return; | |
698 } | |
699 | |
700 if (IMSetIMValues(imp, attr, attr_len, major) < 0) return; | |
701 | |
702 (void)IMPutHeader(conn, XIM_SET_IM_VALUES_REPLY, 0, 4); | |
703 IMPutC16(conn, imp->id); | |
704 IMPutPad(conn); | |
705 IMSchedule(conn, SCHED_WRITE); | |
706 } | |
707 | |
708 /*- ximGetIMValuesProc: handle XIM_GET_IM_VALUES request -*/ | |
709 /* ARGSUSED */ | |
710 static void | |
711 ximGetIMValuesProc(conn, major, minor, arglen) | |
712 IMConnection *conn; | |
713 int major; | |
714 int minor; | |
715 int arglen; | |
716 { | |
717 IMIM *imp; | |
718 char *attr; | |
719 int attr_len; | |
720 int offset; | |
721 | |
722 TRACE(("ximGetIMValuesProc(#%d)\n", conn->serial)); | |
723 | |
724 if ((imp = IMGetIM(conn, arglen)) == NULL) return; | |
725 if (arglen < 4) { | |
726 DPRINT(("ximGetIMValuesProc: arglen < 4\n")); | |
727 IMSendBadLength(conn, imp->id, 0); | |
728 return; | |
729 } | |
730 | |
731 attr_len = IMGetC16(conn, 2); | |
732 attr = IMBUFDATA(IM_INBUF(conn)) + 4; | |
733 if (arglen < attr_len + 4 || attr_len % 2 == 1) { | |
734 DPRINT(("ximGetIMValuesProc: attr_len too long or an odd number\n")); | |
735 IMSendBadLength(conn, imp->id, 0); | |
736 return; | |
737 } | |
738 | |
739 offset = IMPutHeader(conn, XIM_GET_IM_VALUES_REPLY, 0, 0); | |
740 IMPutC16(conn, imp->id); | |
741 | |
742 if (IMGetIMValues(imp, attr, attr_len, offset) < 0) return; | |
743 | |
744 IMFinishRequest(conn, offset); | |
745 } | |
746 | |
747 /*- ximCreateICProc: handle XIM_CREATE_IC request -*/ | |
748 /* ARGSUSED */ | |
749 static void | |
750 ximCreateICProc(conn, major, minor, arglen) | |
751 IMConnection *conn; | |
752 int major; | |
753 int minor; | |
754 int arglen; | |
755 { | |
756 IMIM *imp; | |
757 IMIC *icp; | |
758 char *attr_data; | |
759 int attr_len; | |
760 | |
761 TRACE(("ximCreateICProc(#%d)\n", conn->serial)); | |
762 | |
763 if ((imp = IMGetIM(conn, arglen)) == NULL) return; | |
764 if (arglen < 4) { | |
765 /* BadArglen */ | |
766 DPRINT(("ximCreateICProc: arglen < 4\n")); | |
767 IMSendBadLength(conn, imp->id, 0); | |
768 return; | |
769 } | |
770 | |
771 attr_len = IMGetC16(conn, 2); | |
772 attr_data = IMBUFDATA(IM_INBUF(conn)) + 4; | |
773 if (arglen < attr_len + 4) { | |
774 DPRINT(("ximCreateICProc: attr_len too long\n")); | |
775 IMSendBadLength(conn, imp->id, 0); | |
776 return; | |
777 } | |
778 icp = IMCreateIC(imp); | |
779 if (IMSetICValues(icp, attr_data, attr_len, major) < 0) { | |
780 IMDestroyIC(icp); | |
781 return; | |
782 } | |
783 IMSendRequestWithIC(conn, XIM_CREATE_IC_REPLY, 0, icp); | |
784 | |
785 IMStatusStart(icp); | |
786 } | |
787 | |
788 /*- ximDestroyICProc: handle XIM_DESTROY_IC request -*/ | |
789 /* ARGSUSED */ | |
790 static void | |
791 ximDestroyICProc(conn, major, minor, arglen) | |
792 IMConnection *conn; | |
793 int major; | |
794 int minor; | |
795 int arglen; | |
796 { | |
797 IMIC *icp; | |
798 unsigned int imid, icid; | |
799 | |
800 TRACE(("ximDestroyICProc(#%d)\n", conn->serial)); | |
801 | |
802 if ((icp = IMGetIC(conn, arglen)) == NULL) return; | |
803 if (arglen != 4) { | |
804 DPRINT(("ximDestroyICProc: arglen != 4\n")); | |
805 IMSendBadLength(conn, icp->im->id, icp->id); | |
806 return; | |
807 } | |
808 | |
809 /* Save ID of IM/IC before IMDestroyIC() */ | |
810 imid = icp->im->id; | |
811 icid = icp->id; | |
812 | |
813 IMStatusDone(icp); | |
814 | |
815 IMDestroyIC(icp); | |
816 | |
817 /* IMSendRequestWithIC(conn, XIM_DESTROY_IC_REPLY, 0, icp); */ | |
818 IMPutHeader(conn, XIM_DESTROY_IC_REPLY, 0, 4); | |
819 IMPutC16(conn, imid); | |
820 IMPutC16(conn, icid); | |
821 IMSchedule(conn, SCHED_WRITE); | |
822 } | |
823 | |
824 /*- ximSetICValuesProc: handle XIM_SET_IC_VALUES request -*/ | |
825 /* ARGSUSED */ | |
826 static void | |
827 ximSetICValuesProc(conn, major, minor, arglen) | |
828 IMConnection *conn; | |
829 int major; | |
830 int minor; | |
831 int arglen; | |
832 { | |
833 IMIC *icp; | |
834 char *attr; | |
835 int attr_len; | |
836 | |
837 TRACE(("ximSetICValuesProc(#%d)\n", conn->serial)); | |
838 | |
839 if ((icp = IMGetIC(conn, arglen)) == NULL) return; | |
840 if (arglen < 8) { | |
841 DPRINT(("ximSetICValuesProc: arglen < 8\n")); | |
842 IMSendBadLength(conn, icp->im->id, icp->id); | |
843 return; | |
844 } | |
845 | |
846 attr_len = IMGetC16(conn, 4); | |
847 attr = IMBUFDATA(IM_INBUF(conn)) + 8; | |
848 | |
849 if (arglen < attr_len + 8) { | |
850 DPRINT(("ximSetICValuesProc: attr_len too long\n")); | |
851 IMSendBadLength(conn, icp->im->id, icp->id); | |
852 return; | |
853 } | |
854 | |
855 if (IMSetICValues(icp, attr, attr_len, major) < 0) return; | |
856 | |
857 IMSendRequestWithIC(conn, XIM_SET_IC_VALUES_REPLY, 0, icp); | |
858 } | |
859 | |
860 /*- ximGetICValuesProc: handle XIM_GET_IC_VALUES request -*/ | |
861 /* ARGSUSED */ | |
862 static void | |
863 ximGetICValuesProc(conn, major, minor, arglen) | |
864 IMConnection *conn; | |
865 int major; | |
866 int minor; | |
867 int arglen; | |
868 { | |
869 IMIC *icp; | |
870 char *attr; | |
871 int attr_len; | |
872 int offset; | |
873 | |
874 TRACE(("ximGetICValuesProc(#%d)\n", conn->serial)); | |
875 | |
876 if ((icp = IMGetIC(conn, arglen)) == NULL) return; | |
877 if (arglen < 6) { | |
878 DPRINT(("ximGetICValuesProc: arglen < 6\n")); | |
879 IMSendBadLength(conn, icp->im->id, icp->id); | |
880 return; | |
881 } | |
882 | |
883 attr_len = IMGetC16(conn, 4); | |
884 attr = IMBUFDATA(IM_INBUF(conn)) + 6; | |
885 if (arglen < attr_len + 6 || attr_len % 2 == 1) { | |
886 DPRINT(("ximGetICValuesProc: attr_len too long or an odd number\n")); | |
887 IMSendBadLength(conn, icp->im->id, icp->id); | |
888 return; | |
889 } | |
890 | |
891 offset = IMPutHeader(conn, XIM_GET_IC_VALUES_REPLY, 0, 0); | |
892 IMPutC16(conn, icp->im->id); | |
893 IMPutC16(conn, icp->id); | |
894 | |
895 if (IMGetICValues(icp, attr, attr_len, offset) < 0) return; | |
896 | |
897 IMFinishRequest(conn, offset); | |
898 } | |
899 | |
900 /*- ximSetICFocusProc: handle XIM_SET_IC_FOCUS request -*/ | |
901 /* ARGSUSED */ | |
902 static void | |
903 ximSetICFocusProc(conn, major, minor, arglen) | |
904 IMConnection *conn; | |
905 int major; | |
906 int minor; | |
907 int arglen; | |
908 { | |
909 IMIC *icp; | |
910 | |
911 TRACE(("ximSetICFocusProc(#%d)\n", conn->serial)); | |
912 | |
913 if ((icp = IMGetIC(conn, arglen)) == NULL) return; | |
914 if (arglen != 4) { | |
915 DPRINT(("ximSetICFocusProc: arglen != 4\n")); | |
916 IMSendBadLength(conn, icp->im->id, icp->id); | |
917 return; | |
918 } | |
919 IMStatusStart(icp); | |
920 IMSetFocus(icp); | |
921 } | |
922 | |
923 /*- ximUnsetICFocusProc: handle XIM_UNSET_IC_FOCUS request -*/ | |
924 /* ARGSUSED */ | |
925 static void | |
926 ximUnsetICFocusProc(conn, major, minor, arglen) | |
927 IMConnection *conn; | |
928 int major; | |
929 int minor; | |
930 int arglen; | |
931 { | |
932 IMIC *icp; | |
933 | |
934 TRACE(("ximUnsetICFocusProc(#%d)\n", conn->serial)); | |
935 | |
936 if ((icp = IMGetIC(conn, arglen)) == NULL) return; | |
937 if (arglen != 4) { | |
938 DPRINT(("ximUnsetICFocusProc: arglen != 4\n")); | |
939 IMSendBadLength(conn, icp->im->id, icp->id); | |
940 return; | |
941 } | |
942 IMUnsetFocus(icp); | |
943 IMStatusDone(icp); | |
944 } | |
945 | |
946 /*- swapData: do byte swapping -*/ | |
947 static void | |
948 swapData(data, format) | |
949 char *data; | |
950 char *format; | |
951 { | |
952 unsigned char *p = (unsigned char *)data; | |
953 int x; | |
954 int f; | |
955 | |
956 #define SWAPB(b1, b2) x = b1; b1 = b2; b2 = x | |
957 while ((f = *format++) != '\0') { | |
958 switch (f) { | |
959 case 'x': | |
960 p++; | |
961 break; | |
962 case 'l': | |
963 SWAPB(p[0], p[3]); | |
964 SWAPB(p[1], p[2]); | |
965 p += 4; | |
966 break; | |
967 case 's': | |
968 SWAPB(p[0], p[1]); | |
969 p += 2; | |
970 break; | |
971 } | |
972 } | |
973 #undef SWAPB | |
974 } | |
975 | |
976 | |
977 /*- getEvent: read a wire event and convert it to XEvent format -*/ | |
978 static int | |
979 getEvent(conn, serial, offset, ev) | |
980 IMConnection *conn; | |
981 unsigned int serial; | |
982 int offset; | |
983 XEvent *ev; | |
984 { | |
985 IMBuffer *ibp = IM_INBUF(conn); | |
986 xEvent wire_event; | |
987 int swap_needed; | |
988 int one = 1; | |
989 char *onep = (char *)&one; | |
990 | |
991 /* | |
992 * Get wire event from input buffer. | |
993 */ | |
994 bcopy(IMBUFDATA(ibp) + offset, (char *)&wire_event, sizeof(wire_event)); | |
995 | |
996 /* | |
997 * Do we need byte swapping? | |
998 */ | |
999 if (*onep == 0) { /* big endian */ | |
1000 swap_needed = (conn->byte_order == ORDER_LITTLE); | |
1001 } else { /* little endian */ | |
1002 swap_needed = (conn->byte_order == ORDER_BIG); | |
1003 } | |
1004 | |
1005 #define SWAPEV(format) if (swap_needed) swapData((char *)&wire_event, format) | |
1006 | |
1007 /* | |
1008 * Get common part of the wire event. | |
1009 */ | |
1010 SWAPEV("xxs"); | |
1011 ev->type = wire_event.u.u.type & 0x7f; | |
1012 ev->xany.serial = (serial << 16) | wire_event.u.u.sequenceNumber; | |
1013 ev->xany.display = XtDisplay(conn->proto_widget); | |
1014 ev->xany.send_event = wire_event.u.u.type > 127; | |
1015 | |
1016 /* | |
1017 * Convert wire format to XEvent format. | |
1018 */ | |
1019 switch (ev->type) { | |
1020 case KeyPress: | |
1021 case KeyRelease: | |
1022 SWAPEV("xxxxllllsssssxx"); | |
1023 #define WIRE wire_event.u.keyButtonPointer | |
1024 ev->xkey.window = WIRE.event; | |
1025 ev->xkey.root = WIRE.root; | |
1026 ev->xkey.subwindow = WIRE.child; | |
1027 ev->xkey.time = WIRE.time; | |
1028 ev->xkey.x = cvtINT16toInt(WIRE.eventX); | |
1029 ev->xkey.y = cvtINT16toInt(WIRE.eventY); | |
1030 ev->xkey.x_root = cvtINT16toInt(WIRE.rootX); | |
1031 ev->xkey.y_root = cvtINT16toInt(WIRE.rootY); | |
1032 ev->xkey.state = WIRE.state; | |
1033 ev->xkey.keycode = wire_event.u.u.detail; | |
1034 ev->xkey.same_screen = WIRE.sameScreen; | |
1035 #undef WIRE | |
1036 break; | |
1037 case ButtonPress: | |
1038 case ButtonRelease: | |
1039 SWAPEV("xxxxllllsssssxx"); | |
1040 #define WIRE wire_event.u.keyButtonPointer | |
1041 ev->xbutton.window = WIRE.event; | |
1042 ev->xbutton.root = WIRE.root; | |
1043 ev->xbutton.subwindow = WIRE.child; | |
1044 ev->xbutton.time = WIRE.time; | |
1045 ev->xbutton.x = cvtINT16toInt(WIRE.eventX); | |
1046 ev->xbutton.y = cvtINT16toInt(WIRE.eventY); | |
1047 ev->xbutton.x_root = cvtINT16toInt(WIRE.rootX); | |
1048 ev->xbutton.y_root = cvtINT16toInt(WIRE.rootY); | |
1049 ev->xbutton.state = WIRE.state; | |
1050 ev->xbutton.button = wire_event.u.u.detail; | |
1051 ev->xbutton.same_screen = WIRE.sameScreen; | |
1052 #undef WIRE | |
1053 break; | |
1054 case MotionNotify: | |
1055 SWAPEV("xxxxllllsssssxx"); | |
1056 #define WIRE wire_event.u.keyButtonPointer | |
1057 ev->xmotion.window = WIRE.event; | |
1058 ev->xmotion.root = WIRE.root; | |
1059 ev->xmotion.subwindow = WIRE.child; | |
1060 ev->xmotion.time = WIRE.time; | |
1061 ev->xmotion.x = cvtINT16toInt(WIRE.eventX); | |
1062 ev->xmotion.y = cvtINT16toInt(WIRE.eventY); | |
1063 ev->xmotion.x_root = cvtINT16toInt(WIRE.rootX); | |
1064 ev->xmotion.y_root = cvtINT16toInt(WIRE.rootY); | |
1065 ev->xmotion.state = WIRE.state; | |
1066 ev->xmotion.is_hint = wire_event.u.u.detail; | |
1067 ev->xmotion.same_screen = WIRE.sameScreen; | |
1068 #undef WIRE | |
1069 break; | |
1070 default: | |
1071 /* | |
1072 * For now, this function deals only Key/Pointer events. | |
1073 */ | |
1074 return 0; | |
1075 } | |
1076 #undef SWAPEV | |
1077 | |
1078 return 1; /* success */ | |
1079 } | |
1080 | |
1081 /*- postponeEvent: record events for delayed processing -*/ | |
1082 static void | |
1083 postponeEvent(icp, synchronous, ev) | |
1084 IMIC *icp; | |
1085 int synchronous; | |
1086 XEvent *ev; | |
1087 { | |
1088 IMPendingEvent *pending; | |
1089 | |
1090 pending = XtNew(IMPendingEvent); | |
1091 pending->ic = icp; | |
1092 pending->synchronous = synchronous; | |
1093 bcopy((char *)ev, (char *)&pending->event, sizeof(XEvent)); | |
1094 pending->next = icp->pending_events; | |
1095 icp->pending_events = pending; | |
1096 } | |
1097 | |
1098 /*- handleForwardedEvent: deal with forwarded events -*/ | |
1099 static void | |
1100 handleForwardedEvent(icp, synchronous, ev) | |
1101 IMIC *icp; | |
1102 int synchronous; | |
1103 XEvent *ev; | |
1104 { | |
1105 IMConnection *conn = icp->im->connection; | |
1106 | |
1107 TRACE(("handleForwardedEvent()\n")); | |
1108 | |
1109 icp->state |= IC_FORWARDING; | |
1110 | |
1111 if (icp->state & IC_SYNCING) { | |
1112 /* | |
1113 * We are waiting for SYNC_REPLY message. | |
1114 * Postpone event processing. | |
1115 */ | |
1116 DDPRINT(2, ("forward event processing suspended\n")); | |
1117 postponeEvent(icp, synchronous, ev); | |
1118 return; | |
1119 } | |
1120 | |
1121 IMForwardEvent(icp, ev); | |
1122 | |
1123 #ifdef notyet | |
1124 if (synchronous) { | |
1125 if (!(icp->state & IC_CONVERTING)) { | |
1126 /* | |
1127 * Stop forwarding key events. | |
1128 */ | |
1129 IMStopForwarding(icp); | |
1130 } | |
1131 /* | |
1132 * All the processing is done. Send XIM_SYNC_REPLY. | |
1133 */ | |
1134 IMSendRequestWithIC(conn, XIM_SYNC_REPLY, 0, icp); | |
1135 } else { | |
1136 int cur_pos2; | |
1137 | |
1138 cur_pos2 = IMWritePos(conn); | |
1139 if (!(icp->state & IC_CONVERTING)) { | |
1140 /* | |
1141 * Stop forwarding key events. | |
1142 */ | |
1143 IMStopForwarding(icp); | |
1144 /* | |
1145 * Put dummy commit request (for setting sync flag). | |
1146 */ | |
1147 } | |
1148 } | |
1149 #else | |
1150 /* | |
1151 * Currently, kinput2 supports only full synchronous method. | |
1152 */ | |
1153 if (!(icp->state & IC_CONVERTING)) { | |
1154 /* | |
1155 * Stop forwarding key events. | |
1156 */ | |
1157 IMStopForwarding(icp); | |
1158 } | |
1159 /* | |
1160 * All the processing is done. Send XIM_SYNC_REPLY. | |
1161 */ | |
1162 if (icp->state & IC_FORWARDING) { | |
1163 icp->state &= ~IC_FORWARDING; | |
1164 IMSendRequestWithIC(conn, XIM_SYNC_REPLY, 0, icp); | |
1165 } | |
1166 #endif | |
1167 } | |
1168 | |
1169 /*- ximForwardEventProc: handle XIM_FORWARD_EVENT request -*/ | |
1170 /* ARGSUSED */ | |
1171 static void | |
1172 ximForwardEventProc(conn, major, minor, arglen) | |
1173 IMConnection *conn; | |
1174 int major; | |
1175 int minor; | |
1176 int arglen; | |
1177 { | |
1178 IMIC *icp; | |
1179 int synchronous; | |
1180 unsigned int serial; | |
1181 XEvent event; | |
1182 | |
1183 TRACE(("ximForwardEventProc(#%d)\n", conn->serial)); | |
1184 | |
1185 if ((icp = IMGetIC(conn, arglen)) == NULL) return; | |
1186 if (arglen != 40) { | |
1187 DPRINT(("ximForwardEventProc: arglen != 40\n")); | |
1188 IMSendBadLength(conn, icp->im->id, icp->id); | |
1189 return; | |
1190 } | |
1191 | |
1192 synchronous = IMGetC16(conn, 4) & 1; | |
1193 serial = IMGetC16(conn, 6); | |
1194 | |
1195 if (getEvent(conn, serial, 8, &event)) { | |
1196 handleForwardedEvent(icp, synchronous, &event); | |
1197 } | |
1198 } | |
1199 | |
1200 /*- ximExtForwardKeyeventProc: handle XIM_EXT_FORWARD_KEYEVENT_MASK request -*/ | |
1201 /* ARGSUSED */ | |
1202 static void | |
1203 ximExtForwardKeyeventProc(conn, major, minor, arglen) | |
1204 IMConnection *conn; | |
1205 int major; | |
1206 int minor; | |
1207 int arglen; | |
1208 { | |
1209 IMIC *icp; | |
1210 int synchronous; | |
1211 int type; | |
1212 unsigned int serial; | |
1213 XEvent event; | |
1214 | |
1215 TRACE(("ximExtForwardKeyeventProc(#%d)\n", conn->serial)); | |
1216 | |
1217 if ((icp = IMGetIC(conn, arglen)) == NULL) return; | |
1218 | |
1219 if (!(icp->im->mask & XIM_EXT_FORWARD_KEYEVENT_MASK)) { | |
1220 DPRINT(("ximExtForwardKeyeventProc: ext_forward_keyevent disabled\n")); | |
1221 IMSendBadProtocol(conn, "ext_forward_keyevent extension not enabled"); | |
1222 return; | |
1223 } | |
1224 | |
1225 if (arglen != 16) { | |
1226 DPRINT(("ximExtForwardKeyeventProc: arglen != 16\n")); | |
1227 IMSendBadLength(conn, icp->im->id, icp->id); | |
1228 return; | |
1229 } | |
1230 | |
1231 synchronous = IMGetC16(conn, 4) & 1; | |
1232 serial = IMGetC16(conn, 6); | |
1233 type = IMGetC8(conn, 8); | |
1234 if (type != KeyPress && type != KeyRelease) { | |
1235 /* Badtype */ | |
1236 IMSendError(conn, IMBadSomething, icp->im->id, icp->id, | |
1237 "forwarded event is invalid type"); | |
1238 return; | |
1239 } | |
1240 | |
1241 event.type = type; | |
1242 event.xkey.serial = serial; /* ??? */ | |
1243 event.xkey.keycode = IMGetC8(conn, 9); | |
1244 event.xkey.state = IMGetC16(conn, 10); | |
1245 event.xkey.time = IMGetC32(conn, 12); | |
1246 event.xkey.window = IMGetC32(conn, 16); | |
1247 event.xkey.root = icp->client_profile.root; | |
1248 event.xkey.subwindow = None; | |
1249 event.xkey.x = 0; | |
1250 event.xkey.y = 0; | |
1251 event.xkey.x_root = 0; | |
1252 event.xkey.y_root = 0; | |
1253 event.xkey.same_screen = True; | |
1254 | |
1255 handleForwardedEvent(icp, synchronous, &event); | |
1256 } | |
1257 | |
1258 /*- ximSyncProc: handle XIM_SYNC request -*/ | |
1259 /* ARGSUSED */ | |
1260 static void | |
1261 ximSyncProc(conn, major, minor, arglen) | |
1262 IMConnection *conn; | |
1263 int major; | |
1264 int minor; | |
1265 int arglen; | |
1266 { | |
1267 IMIC *icp; | |
1268 | |
1269 TRACE(("ximSyncProc(#%d)\n", conn->serial)); | |
1270 | |
1271 if ((icp = IMGetIC(conn, arglen)) == NULL) return; | |
1272 if (arglen != 4) { | |
1273 DPRINT(("ximSyncProc: arglen != 4\n")); | |
1274 IMSendBadLength(conn, icp->im->id, icp->id); | |
1275 return; | |
1276 } | |
1277 IMSendRequestWithIC(conn, XIM_SYNC_REPLY, 0, icp); | |
1278 } | |
1279 | |
1280 /*- processPendingEvents: process pending events forwarded by the client -*/ | |
1281 static void | |
1282 processPendingEvents(icp, pending_event) | |
1283 IMIC *icp; | |
1284 IMPendingEvent *pending_event; | |
1285 { | |
1286 /* | |
1287 * Pending events list is in reverse order. | |
1288 * Processing is done from the tail of the list, using | |
1289 * recursive call. | |
1290 */ | |
1291 if (pending_event == NULL) return; | |
1292 processPendingEvents(icp, pending_event->next); | |
1293 pending_event->next = NULL; | |
1294 handleForwardedEvent(icp, pending_event->synchronous, | |
1295 &pending_event->event); | |
1296 XtFree((char *)pending_event); | |
1297 } | |
1298 | |
1299 /*- ximSyncReplyProc: handle XIM_SYNC_REPLY message -*/ | |
1300 /* ARGSUSED */ | |
1301 static void | |
1302 ximSyncReplyProc(conn, major, minor, arglen) | |
1303 IMConnection *conn; | |
1304 int major; | |
1305 int minor; | |
1306 int arglen; | |
1307 { | |
1308 IMIC *icp; | |
1309 | |
1310 TRACE(("ximSyncReplyProc(#%d)\n", conn->serial)); | |
1311 | |
1312 if ((icp = IMGetIC(conn, arglen)) == NULL) return; | |
1313 if (arglen != 4) { | |
1314 DPRINT(("ximSyncReplyProc: arglen != 4\n")); | |
1315 return; | |
1316 } | |
1317 if (icp->state & IC_SYNCING) { | |
1318 icp->state &= ~IC_SYNCING; | |
1319 processPendingEvents(icp, icp->pending_events); | |
1320 } | |
1321 } | |
1322 | |
1323 /*- ximResetICProc: handle XIM_RESET_IC message -*/ | |
1324 /* ARGSUSED */ | |
1325 static void | |
1326 ximResetICProc(conn, major, minor, arglen) | |
1327 IMConnection *conn; | |
1328 int major; | |
1329 int minor; | |
1330 int arglen; | |
1331 { | |
1332 IMIC *icp; | |
1333 char *text = NULL; | |
1334 int offset; | |
1335 int text_length; | |
1336 | |
1337 TRACE(("ximResetICProc(#%d)\n", conn->serial)); | |
1338 | |
1339 if ((icp = IMGetIC(conn, arglen)) == NULL) return; | |
1340 if (arglen != 4) { | |
1341 DPRINT(("ximResetICProc: arglen != 4\n")); | |
1342 IMSendBadLength(conn, icp->im->id, icp->id); | |
1343 return; | |
1344 } | |
1345 icp->state |= IC_RESETTING; | |
1346 text_length = IMResetIC(icp, &text); | |
1347 | |
1348 offset = IMPutHeader(conn, XIM_RESET_IC_REPLY, 0, 0); | |
1349 IMPutC16(conn, icp->im->id); | |
1350 IMPutC16(conn, icp->id); | |
1351 IMPutC16(conn, (unsigned int)text_length); | |
1352 if (text_length > 0) IMPutString(conn, text, text_length); | |
1353 IMFinishRequest(conn, offset); | |
1354 if (text != NULL) XtFree(text); | |
1355 icp->state &= ~IC_RESETTING; | |
1356 } | |
1357 | |
1358 /*- ximExtMoveProc: handle XIM_EXT_MOVE request -*/ | |
1359 /* ARGSUSED */ | |
1360 static void | |
1361 ximExtMoveProc(conn, major, minor, arglen) | |
1362 IMConnection *conn; | |
1363 int major; | |
1364 int minor; | |
1365 int arglen; | |
1366 { | |
1367 IMIC *icp; | |
1368 int x, y; | |
1369 | |
1370 TRACE(("ximExtMoveProc(#%d)\n", conn->serial)); | |
1371 | |
1372 if ((icp = IMGetIC(conn, arglen)) == NULL) return; | |
1373 x = IMGetI16(conn, 4); | |
1374 y = IMGetI16(conn, 6); | |
1375 IMMoveLocation(icp, x, y); | |
1376 } | |
1377 | |
1378 /*- ximAlreadyConnectedProc: handle duplicate XIM_CONNECT request -*/ | |
1379 /* ARGSUSED */ | |
1380 static void | |
1381 ximAlreadyConnectedProc(conn, major, minor, arglen) | |
1382 IMConnection *conn; | |
1383 int major; | |
1384 int minor; | |
1385 int arglen; | |
1386 { | |
1387 TRACE(("ximAlreadyConnectedProc(#%d)\n", conn->serial)); | |
1388 | |
1389 DPRINT(("connection #%d sent multiple XIM_CONNECT request\n", | |
1390 conn->serial)); | |
1391 IMSendBadProtocol(conn, "duplicate XIM_CONNECT message"); | |
1392 } | |
1393 | |
1394 /*- ximShouldNotBeSentProc: handle requests which clients should not send -*/ | |
1395 /* ARGSUSED */ | |
1396 static void | |
1397 ximShouldNotBeSentProc(conn, major, minor, arglen) | |
1398 IMConnection *conn; | |
1399 int major; | |
1400 int minor; | |
1401 int arglen; | |
1402 { | |
1403 TRACE(("ximShouldNotBeSentProc(#%d)\n", conn->serial)); | |
1404 | |
1405 DPRINT(("connection #%d sent invalid request\n", conn->serial)) | |
1406 IMSendBadProtocol(conn, "Clients should not send this request"); | |
1407 } | |
1408 | |
1409 /*- ximAuthPhaseProc: handle requests for authentication -*/ | |
1410 /* ARGSUSED */ | |
1411 static void | |
1412 ximAuthPhaseProc(conn, major, minor, arglen) | |
1413 IMConnection *conn; | |
1414 int major; | |
1415 int minor; | |
1416 int arglen; | |
1417 { | |
1418 TRACE(("ximAuthPhaseProc(#%d)\n", conn->serial)); | |
1419 | |
1420 DPRINT(("connection #%d sends auth-related request\n", conn->serial)); | |
1421 IMSendBadProtocol(conn, "not authentication phase"); | |
1422 } | |
1423 | |
1424 /*- ximNopProc: nop -*/ | |
1425 /* ARGSUSED */ | |
1426 static void | |
1427 ximNopProc(conn, major, minor, arglen) | |
1428 IMConnection *conn; | |
1429 int major; | |
1430 int minor; | |
1431 int arglen; | |
1432 { | |
1433 TRACE(("ximNopProc(#%d)\n", conn->serial)); | |
1434 | |
1435 /* do nothing */ | |
1436 } | |
1437 | |
1438 /* | |
1439 * Public Function | |
1440 */ | |
1441 | |
1442 /*- IMCompileReq: initialize IMMainDispatchTable -*/ | |
1443 void | |
1444 IMCompileReq() | |
1445 { | |
1446 static int compiled = 0; | |
1447 | |
1448 if (compiled) return; | |
1449 compileTbl(coreRequestTbl); | |
1450 compileTbl(extRequestTbl); | |
1451 compiled = 1; | |
1452 } |