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 } |
