1 /******************************************************************
2
3 Copyright 1994, 1995 by Sun Microsystems, Inc.
4 Copyright 1993, 1994 by Hewlett-Packard Company
5
6 Permission to use, copy, modify, distribute, and sell this software
7 and its documentation for any purpose is hereby granted without fee,
8 provided that the above copyright notice appear in all copies and
9 that both that copyright notice and this permission notice appear
10 in supporting documentation, and that the name of Sun Microsystems, Inc.
11 and Hewlett-Packard not be used in advertising or publicity pertaining to
12 distribution of the software without specific, written prior permission.
13 Sun Microsystems, Inc. and Hewlett-Packard make no representations about
14 the suitability of this software for any purpose. It is provided "as is"
15 without express or implied warranty.
16
17 SUN MICROSYSTEMS INC. AND HEWLETT-PACKARD COMPANY DISCLAIMS ALL
18 WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
20 SUN MICROSYSTEMS, INC. AND HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY
21 SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
22 RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
23 CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
24 IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25
26 Author: Hidetoshi Tajima(tajima@Eng.Sun.COM) Sun Microsystems, Inc.
27
28 This version tidied and debugged by Steve Underwood May 1999
29
30 ******************************************************************/
31
32 #include <X11/Xlib.h>
33 #include <X11/Xatom.h>
34 #ifndef NEED_EVENTS
35 #define NEED_EVENTS
36 #endif
37 #include <X11/Xproto.h>
38 #undef NEED_EVENTS
39 #include "FrameMgr.h"
40 #include "IMdkit.h"
41 #include "Xi18n.h"
42 #include "XimFunc.h"
43
44 extern Xi18nClient *_Xi18nFindClient (Xi18n, CARD16);
45
46 static void *xi18n_setup (Display *, XIMArg *);
47 static Status xi18n_openIM (XIMS);
48 static Status xi18n_closeIM (XIMS);
49 static char *xi18n_setIMValues (XIMS, XIMArg *);
50 static char *xi18n_getIMValues (XIMS, XIMArg *);
51 static Status xi18n_forwardEvent (XIMS, XPointer);
52 static Status xi18n_commit (XIMS, XPointer);
53 static int xi18n_callCallback (XIMS, XPointer);
54 static int xi18n_preeditStart (XIMS, XPointer);
55 static int xi18n_preeditEnd (XIMS, XPointer);
56 static int xi18n_syncXlib (XIMS, XPointer);
57
58 #ifndef XIM_SERVERS
59 #define XIM_SERVERS "XIM_SERVERS"
60 #endif
61 static Atom XIM_Servers = None;
62
63
64 IMMethodsRec Xi18n_im_methods =
65 {
66 xi18n_setup,
67 xi18n_openIM,
68 xi18n_closeIM,
69 xi18n_setIMValues,
70 xi18n_getIMValues,
71 xi18n_forwardEvent,
72 xi18n_commit,
73 xi18n_callCallback,
74 xi18n_preeditStart,
75 xi18n_preeditEnd,
76 xi18n_syncXlib,
77 };
78
79 extern Bool _Xi18nCheckXAddress (Xi18n, TransportSW *, char *);
80 extern Bool _Xi18nCheckTransAddress (Xi18n, TransportSW *, char *);
81
82 TransportSW _TransR[] =
83 {
84 {"X", 1, _Xi18nCheckXAddress},
85 #ifdef TCPCONN
86 {"tcp", 3, _Xi18nCheckTransAddress},
87 {"local", 5, _Xi18nCheckTransAddress},
88 #endif
89 #ifdef DNETCONN
90 {"decnet", 6, _Xi18nCheckTransAddress},
91 #endif
92 {(char *) NULL, 0, (Bool (*) ()) NULL}
93 };
94
GetInputStyles(Xi18n i18n_core,XIMStyles ** p_style)95 static Bool GetInputStyles (Xi18n i18n_core, XIMStyles **p_style)
96 {
97 Xi18nAddressRec *address = (Xi18nAddressRec *) &i18n_core->address;
98 XIMStyles *p;
99 int i;
100
101 p = &address->input_styles;
102 if ((*p_style = (XIMStyles *) malloc (sizeof (XIMStyles)
103 + p->count_styles*sizeof (XIMStyle)))
104 == NULL)
105 {
106 return False;
107 }
108 /*endif*/
109 (*p_style)->count_styles = p->count_styles;
110 (*p_style)->supported_styles = (XIMStyle *) ((XPointer) *p_style + sizeof (XIMStyles));
111 for (i = 0; i < (int) p->count_styles; i++)
112 (*p_style)->supported_styles[i] = p->supported_styles[i];
113 /*endfor*/
114 return True;
115 }
116
GetOnOffKeys(Xi18n i18n_core,long mask,XIMTriggerKeys ** p_key)117 static Bool GetOnOffKeys (Xi18n i18n_core, long mask, XIMTriggerKeys **p_key)
118 {
119 Xi18nAddressRec *address = (Xi18nAddressRec *) &i18n_core->address;
120 XIMTriggerKeys *p;
121 int i;
122
123 if (mask & I18N_ON_KEYS)
124 p = &address->on_keys;
125 else
126 p = &address->off_keys;
127 /*endif*/
128 if ((*p_key = (XIMTriggerKeys *) malloc (sizeof(XIMTriggerKeys)
129 + p->count_keys*sizeof(XIMTriggerKey)))
130 == NULL)
131 {
132 return False;
133 }
134 /*endif*/
135 (*p_key)->count_keys = p->count_keys;
136 (*p_key)->keylist =
137 (XIMTriggerKey *) ((XPointer) *p_key + sizeof(XIMTriggerKeys));
138 for (i = 0; i < (int) p->count_keys; i++)
139 {
140 (*p_key)->keylist[i].keysym = p->keylist[i].keysym;
141 (*p_key)->keylist[i].modifier = p->keylist[i].modifier;
142 (*p_key)->keylist[i].modifier_mask = p->keylist[i].modifier_mask;
143 }
144 /*endfor*/
145 return True;
146 }
147
GetEncodings(Xi18n i18n_core,XIMEncodings ** p_encoding)148 static Bool GetEncodings(Xi18n i18n_core, XIMEncodings **p_encoding)
149 {
150 Xi18nAddressRec *address = (Xi18nAddressRec *) &i18n_core->address;
151 XIMEncodings *p;
152 int i;
153
154 p = &address->encoding_list;
155
156 if ((*p_encoding = (XIMEncodings *) malloc (sizeof (XIMEncodings)
157 + p->count_encodings*sizeof(XIMEncoding))) == NULL)
158 {
159 return False;
160 }
161 /*endif*/
162 (*p_encoding)->count_encodings = p->count_encodings;
163 (*p_encoding)->supported_encodings =
164 (XIMEncoding *) ((XPointer)*p_encoding + sizeof (XIMEncodings));
165 for (i = 0; i < (int) p->count_encodings; i++)
166 {
167 (*p_encoding)->supported_encodings[i]
168 = (char *) malloc (strlen (p->supported_encodings[i]) + 1);
169 strcpy ((*p_encoding)->supported_encodings[i],
170 p->supported_encodings[i]);
171 }
172 /*endif*/
173 return True;
174 }
175
ParseArgs(Xi18n i18n_core,int mode,XIMArg * args)176 static char *ParseArgs (Xi18n i18n_core, int mode, XIMArg *args)
177 {
178 Xi18nAddressRec *address = (Xi18nAddressRec *) &i18n_core->address;
179 XIMArg *p;
180
181 if (mode == I18N_OPEN || mode == I18N_SET)
182 {
183 for (p = args; p->name != NULL; p++)
184 {
185 if (strcmp (p->name, IMLocale) == 0)
186 {
187 if (address->imvalue_mask & I18N_IM_LOCALE)
188 return IMLocale;
189 /*endif*/
190 address->im_locale = (char *) malloc (strlen (p->value) + 1);
191 if (!address->im_locale)
192 return IMLocale;
193 /*endif*/
194 strcpy (address->im_locale, p->value);
195 address->imvalue_mask |= I18N_IM_LOCALE;
196 }
197 else if (strcmp (p->name, IMServerTransport) == 0)
198 {
199 if (address->imvalue_mask & I18N_IM_ADDRESS)
200 return IMServerTransport;
201 /*endif*/
202 address->im_addr = (char *) malloc (strlen (p->value) + 1);
203 if (!address->im_addr)
204 return IMServerTransport;
205 /*endif*/
206 strcpy(address->im_addr, p->value);
207 address->imvalue_mask |= I18N_IM_ADDRESS;
208 }
209 else if (strcmp (p->name, IMServerName) == 0)
210 {
211 if (address->imvalue_mask & I18N_IM_NAME)
212 return IMServerName;
213 /*endif*/
214 address->im_name = (char *) malloc (strlen (p->value) + 1);
215 if (!address->im_name)
216 return IMServerName;
217 /*endif*/
218 strcpy (address->im_name, p->value);
219 address->imvalue_mask |= I18N_IM_NAME;
220 }
221 else if (strcmp (p->name, IMServerWindow) == 0)
222 {
223 if (address->imvalue_mask & I18N_IMSERVER_WIN)
224 return IMServerWindow;
225 /*endif*/
226 address->im_window = (Window) p->value;
227 address->imvalue_mask |= I18N_IMSERVER_WIN;
228 }
229 else if (strcmp (p->name, IMInputStyles) == 0)
230 {
231 if (address->imvalue_mask & I18N_INPUT_STYLES)
232 return IMInputStyles;
233 /*endif*/
234 address->input_styles.count_styles =
235 ((XIMStyles*)p->value)->count_styles;
236 address->input_styles.supported_styles =
237 (XIMStyle *) malloc (sizeof (XIMStyle)*address->input_styles.count_styles);
238 if (address->input_styles.supported_styles == (XIMStyle *) NULL)
239 return IMInputStyles;
240 /*endif*/
241 memmove (address->input_styles.supported_styles,
242 ((XIMStyles *) p->value)->supported_styles,
243 sizeof (XIMStyle)*address->input_styles.count_styles);
244 address->imvalue_mask |= I18N_INPUT_STYLES;
245 }
246 else if (strcmp (p->name, IMProtocolHandler) == 0)
247 {
248 address->improto = (IMProtoHandler) p->value;
249 address->imvalue_mask |= I18N_IM_HANDLER;
250 }
251 else if (strcmp (p->name, IMOnKeysList) == 0)
252 {
253 if (address->on_keys.keylist != NULL)
254 free(address->on_keys.keylist);
255
256 address->on_keys.count_keys =
257 ((XIMTriggerKeys *) p->value)->count_keys;
258 address->on_keys.keylist =
259 (XIMTriggerKey *) malloc (sizeof (XIMTriggerKey)*address->on_keys.count_keys);
260 if (address->on_keys.keylist == (XIMTriggerKey *) NULL)
261 return IMOnKeysList;
262 /*endif*/
263 memmove (address->on_keys.keylist,
264 ((XIMTriggerKeys *) p->value)->keylist,
265 sizeof (XIMTriggerKey)*address->on_keys.count_keys);
266 address->imvalue_mask |= I18N_ON_KEYS;
267 }
268 else if (strcmp (p->name, IMOffKeysList) == 0)
269 {
270 if (address->imvalue_mask & I18N_OFF_KEYS)
271 return IMOffKeysList;
272 /*endif*/
273 address->off_keys.count_keys =
274 ((XIMTriggerKeys *) p->value)->count_keys;
275 address->off_keys.keylist =
276 (XIMTriggerKey *) malloc (sizeof (XIMTriggerKey)*address->off_keys.count_keys);
277 if (address->off_keys.keylist == (XIMTriggerKey *) NULL)
278 return IMOffKeysList;
279 /*endif*/
280 memmove (address->off_keys.keylist,
281 ((XIMTriggerKeys *) p->value)->keylist,
282 sizeof (XIMTriggerKey)*address->off_keys.count_keys);
283 address->imvalue_mask |= I18N_OFF_KEYS;
284 }
285 else if (strcmp (p->name, IMEncodingList) == 0)
286 {
287 if (address->imvalue_mask & I18N_ENCODINGS)
288 return IMEncodingList;
289 /*endif*/
290 address->encoding_list.count_encodings =
291 ((XIMEncodings *) p->value)->count_encodings;
292 address->encoding_list.supported_encodings =
293 (XIMEncoding *) malloc (sizeof (XIMEncoding)*address->encoding_list.count_encodings);
294 if (address->encoding_list.supported_encodings
295 == (XIMEncoding *) NULL)
296 {
297 return IMEncodingList;
298 }
299 /*endif*/
300 memmove (address->encoding_list.supported_encodings,
301 ((XIMEncodings *) p->value)->supported_encodings,
302 sizeof (XIMEncoding)*address->encoding_list.count_encodings);
303 address->imvalue_mask |= I18N_ENCODINGS;
304 }
305 else if (strcmp (p->name, IMFilterEventMask) == 0)
306 {
307 if (address->imvalue_mask & I18N_FILTERMASK)
308 return IMFilterEventMask;
309 /*endif*/
310 address->filterevent_mask = (long) p->value;
311 address->imvalue_mask |= I18N_FILTERMASK;
312 }
313 /*endif*/
314 }
315 /*endfor*/
316 if (mode == I18N_OPEN)
317 {
318 /* check mandatory IM values */
319 if (!(address->imvalue_mask & I18N_IM_LOCALE))
320 {
321 /* locales must be set in IMOpenIM */
322 return IMLocale;
323 }
324 /*endif*/
325 if (!(address->imvalue_mask & I18N_IM_ADDRESS))
326 {
327 /* address must be set in IMOpenIM */
328 return IMServerTransport;
329 }
330 /*endif*/
331 }
332 /*endif*/
333 }
334 else if (mode == I18N_GET)
335 {
336 for (p = args; p->name != NULL; p++)
337 {
338 if (strcmp (p->name, IMLocale) == 0)
339 {
340 p->value = (char *) malloc (strlen (address->im_locale) + 1);
341 if (!p->value)
342 return IMLocale;
343 /*endif*/
344 strcpy (p->value, address->im_locale);
345 }
346 else if (strcmp (p->name, IMServerTransport) == 0)
347 {
348 p->value = (char *) malloc (strlen (address->im_addr) + 1);
349 if (!p->value)
350 return IMServerTransport;
351 /*endif*/
352 strcpy (p->value, address->im_addr);
353 }
354 else if (strcmp (p->name, IMServerName) == 0)
355 {
356 if (address->imvalue_mask & I18N_IM_NAME)
357 {
358 p->value = (char *) malloc (strlen (address->im_name) + 1);
359 if (!p->value)
360 return IMServerName;
361 /*endif*/
362 strcpy (p->value, address->im_name);
363 }
364 else
365 {
366 return IMServerName;
367 }
368 /*endif*/
369 }
370 else if (strcmp (p->name, IMServerWindow) == 0)
371 {
372 if (address->imvalue_mask & I18N_IMSERVER_WIN)
373 *((Window *) (p->value)) = address->im_window;
374 else
375 return IMServerWindow;
376 /*endif*/
377 }
378 else if (strcmp (p->name, IMInputStyles) == 0)
379 {
380 if (GetInputStyles (i18n_core,
381 (XIMStyles **) p->value) == False)
382 {
383 return IMInputStyles;
384 }
385 /*endif*/
386 }
387 else if (strcmp (p->name, IMProtocolHandler) == 0)
388 {
389 if (address->imvalue_mask & I18N_IM_HANDLER)
390 *((IMProtoHandler *) (p->value)) = address->improto;
391 else
392 return IMProtocolHandler;
393 /*endif*/
394 }
395 else if (strcmp (p->name, IMOnKeysList) == 0)
396 {
397 if (address->imvalue_mask & I18N_ON_KEYS)
398 {
399 if (GetOnOffKeys (i18n_core,
400 I18N_ON_KEYS,
401 (XIMTriggerKeys **) p->value) == False)
402 {
403 return IMOnKeysList;
404 }
405 /*endif*/
406 }
407 else
408 {
409 return IMOnKeysList;
410 }
411 /*endif*/
412 }
413 else if (strcmp (p->name, IMOffKeysList) == 0)
414 {
415 if (address->imvalue_mask & I18N_OFF_KEYS)
416 {
417 if (GetOnOffKeys (i18n_core,
418 I18N_OFF_KEYS,
419 (XIMTriggerKeys **) p->value) == False)
420 {
421 return IMOffKeysList;
422 }
423 /*endif*/
424 }
425 else
426 {
427 return IMOffKeysList;
428 }
429 /*endif*/
430 }
431 else if (strcmp (p->name, IMEncodingList) == 0)
432 {
433 if (address->imvalue_mask & I18N_ENCODINGS)
434 {
435 if (GetEncodings (i18n_core,
436 (XIMEncodings **) p->value) == False)
437 {
438 return IMEncodingList;
439 }
440 /*endif*/
441 }
442 else
443 {
444 return IMEncodingList;
445 }
446 /*endif*/
447 }
448 else if (strcmp (p->name, IMFilterEventMask) == 0)
449 {
450 if (address->imvalue_mask & I18N_FILTERMASK)
451 *((long *) (p->value)) = address->filterevent_mask;
452 else
453 return IMFilterEventMask;
454 /*endif*/
455 }
456 /*endif*/
457 }
458 /*endfor*/
459 }
460 /*endif*/
461 return NULL;
462 }
463
CheckIMName(Xi18n i18n_core)464 static int CheckIMName (Xi18n i18n_core)
465 {
466 char *address = i18n_core->address.im_addr;
467 int i;
468
469 for (i = 0; _TransR[i].transportname; i++)
470 {
471 while (*address == ' ' || *address == '\t')
472 address++;
473 /*endwhile*/
474 if (strncmp (address,
475 _TransR[i].transportname,
476 _TransR[i].namelen) == 0
477 &&
478 address[_TransR[i].namelen] == '/')
479 {
480 if (_TransR[i].checkAddr (i18n_core,
481 &_TransR[i],
482 address + _TransR[i].namelen + 1) == True)
483 {
484 return True;
485 }
486 /*endif*/
487 return False;
488 }
489 /*endif*/
490 }
491 /*endfor*/
492 return False;
493 }
494
SetXi18nSelectionOwner(Xi18n i18n_core)495 static int SetXi18nSelectionOwner(Xi18n i18n_core)
496 {
497 Display *dpy = i18n_core->address.dpy;
498 Window ims_win = i18n_core->address.im_window;
499 Window root = RootWindow (dpy, DefaultScreen (dpy));
500 Atom realtype;
501 int realformat;
502 unsigned long bytesafter;
503 long *data=NULL;
504 unsigned long length;
505 Atom atom;
506 int i;
507 int found;
508 int forse = False;
509 char buf[256];
510
511 (void)snprintf(buf, sizeof(buf), "@server=%s", i18n_core->address.im_name);
512 buf[sizeof(buf) - 1] = '\0';
513 if ((atom = XInternAtom(dpy, buf, False)) == 0)
514 return False;
515 i18n_core->address.selection = atom;
516
517 if (XIM_Servers == None)
518 XIM_Servers = XInternAtom (dpy, XIM_SERVERS, False);
519 /*endif*/
520 XGetWindowProperty (dpy,
521 root,
522 XIM_Servers,
523 0L,
524 1000000L,
525 False,
526 XA_ATOM,
527 &realtype,
528 &realformat,
529 &length,
530 &bytesafter,
531 (unsigned char **) (&data));
532 if (realtype != None && (realtype != XA_ATOM || realformat != 32)) {
533 if (data != NULL)
534 XFree ((char *) data);
535 return False;
536 }
537
538 found = False;
539 for (i = 0; i < length; i++) {
540 if (data[i] == atom) {
541 Window owner;
542 found = True;
543 if ((owner = XGetSelectionOwner (dpy, atom)) != ims_win) {
544 if (owner == None || forse == True)
545 XSetSelectionOwner (dpy, atom, ims_win, CurrentTime);
546 else
547 return False;
548 }
549 break;
550 }
551 }
552
553 if (found == False) {
554 XSetSelectionOwner (dpy, atom, ims_win, CurrentTime);
555 XChangeProperty (dpy,
556 root,
557 XIM_Servers,
558 XA_ATOM,
559 32,
560 PropModePrepend,
561 (unsigned char *) &atom,
562 1);
563 }
564 else {
565 /*
566 * We always need to generate the PropertyNotify to the Root Window
567 */
568 XChangeProperty (dpy,
569 root,
570 XIM_Servers,
571 XA_ATOM,
572 32,
573 PropModePrepend,
574 (unsigned char *) data,
575 0);
576 }
577 if (data != NULL)
578 XFree ((char *) data);
579
580 /* Intern "LOCALES" and "TRANSOPORT" Target Atoms */
581 i18n_core->address.Localename = XInternAtom (dpy, LOCALES, False);
582 i18n_core->address.Transportname = XInternAtom (dpy, TRANSPORT, False);
583 return (XGetSelectionOwner (dpy, atom) == ims_win);
584 }
585
DeleteXi18nAtom(Xi18n i18n_core)586 static int DeleteXi18nAtom(Xi18n i18n_core)
587 {
588 Display *dpy = i18n_core->address.dpy;
589 Window root = RootWindow (dpy, DefaultScreen (dpy));
590 Atom realtype;
591 int realformat;
592 unsigned long bytesafter;
593 long *data=NULL;
594 unsigned long length;
595 Atom atom;
596 int i, ret;
597 int found;
598 char buf[256];
599
600 (void)snprintf(buf, sizeof(buf), "@server=%s", i18n_core->address.im_name);
601 buf[sizeof(buf) - 1] = '\0';
602 if ((atom = XInternAtom(dpy, buf, False)) == 0)
603 return False;
604 i18n_core->address.selection = atom;
605
606 if (XIM_Servers == None)
607 XIM_Servers = XInternAtom (dpy, XIM_SERVERS, False);
608 XGetWindowProperty (dpy,
609 root,
610 XIM_Servers,
611 0L,
612 1000000L,
613 False,
614 XA_ATOM,
615 &realtype,
616 &realformat,
617 &length,
618 &bytesafter,
619 (unsigned char **) (&data));
620 if (realtype != XA_ATOM || realformat != 32) {
621 if (data != NULL)
622 XFree ((char *) data);
623 return False;
624 }
625
626 found = False;
627 for (i = 0; i < length; i++) {
628 if (data[i] == atom) {
629 found = True;
630 break;
631 }
632 }
633
634 if (found == True) {
635 for (i=i+1; i<length; i++)
636 data[i-1] = data[i];
637 XChangeProperty (dpy,
638 root,
639 XIM_Servers,
640 XA_ATOM,
641 32,
642 PropModeReplace,
643 (unsigned char *)data,
644 length-1);
645 ret = True;
646 }
647 else {
648 XChangeProperty (dpy,
649 root,
650 XIM_Servers,
651 XA_ATOM,
652 32,
653 PropModePrepend,
654 (unsigned char *)data,
655 0);
656 ret = False;
657 }
658 if (data != NULL)
659 XFree ((char *) data);
660 return ret;
661 }
662
663
664 /* XIM protocol methods */
xi18n_setup(Display * dpy,XIMArg * args)665 static void *xi18n_setup (Display *dpy, XIMArg *args)
666 {
667 Xi18n i18n_core;
668 CARD16 endian = 1;
669
670 if ((i18n_core = (Xi18n) malloc (sizeof (Xi18nCore))) == (Xi18n) NULL)
671 return NULL;
672 /*endif*/
673
674 memset (i18n_core, 0, sizeof (Xi18nCore));
675
676 i18n_core->address.dpy = dpy;
677
678 if (ParseArgs (i18n_core, I18N_OPEN, args) != NULL)
679 {
680 free (i18n_core);
681 return NULL;
682 }
683 /*endif*/
684 if (*(char *) &endian)
685 i18n_core->address.im_byteOrder = 'l';
686 else
687 i18n_core->address.im_byteOrder = 'B';
688 /*endif*/
689
690 /* install IMAttr and ICAttr list in i18n_core */
691 _Xi18nInitAttrList (i18n_core);
692
693 /* install IMExtension list in i18n_core */
694 _Xi18nInitExtension (i18n_core);
695
696 return i18n_core;
697 }
698
ReturnSelectionNotify(Xi18n i18n_core,XSelectionRequestEvent * ev)699 static void ReturnSelectionNotify (Xi18n i18n_core, XSelectionRequestEvent *ev)
700 {
701 XEvent event;
702 Display *dpy = i18n_core->address.dpy;
703 char buf[4096];
704
705 event.type = SelectionNotify;
706 event.xselection.requestor = ev->requestor;
707 event.xselection.selection = ev->selection;
708 event.xselection.target = ev->target;
709 event.xselection.time = ev->time;
710 event.xselection.property = ev->property;
711 if (ev->target == i18n_core->address.Localename)
712 {
713 snprintf (buf, sizeof(buf), "@locale=%s", i18n_core->address.im_locale);
714 buf[sizeof(buf) - 1] = '\0';
715 }
716 else if (ev->target == i18n_core->address.Transportname)
717 {
718 snprintf (buf, sizeof(buf), "@transport=%s", i18n_core->address.im_addr);
719 buf[sizeof(buf) - 1] = '\0';
720 }
721 /*endif*/
722 XChangeProperty (dpy,
723 event.xselection.requestor,
724 ev->target,
725 ev->target,
726 8,
727 PropModeReplace,
728 (unsigned char *) buf,
729 strlen (buf));
730 XSendEvent (dpy, event.xselection.requestor, False, NoEventMask, &event);
731 XFlush (i18n_core->address.dpy);
732 }
733
WaitXSelectionRequest(Display * dpy,Window win,XEvent * ev,XPointer client_data)734 static Bool WaitXSelectionRequest (Display *dpy,
735 Window win,
736 XEvent *ev,
737 XPointer client_data)
738 {
739 XIMS ims = (XIMS) client_data;
740 Xi18n i18n_core = ims->protocol;
741
742 if (((XSelectionRequestEvent *) ev)->selection
743 == i18n_core->address.selection)
744 {
745 ReturnSelectionNotify (i18n_core, (XSelectionRequestEvent *) ev);
746 return True;
747 }
748 /*endif*/
749 return False;
750 }
751
xi18n_openIM(XIMS ims)752 static Status xi18n_openIM(XIMS ims)
753 {
754 Xi18n i18n_core = ims->protocol;
755 Display *dpy = i18n_core->address.dpy;
756
757 if (!CheckIMName (i18n_core)
758 ||
759 !SetXi18nSelectionOwner (i18n_core)
760 ||
761 !i18n_core->methods.begin (ims))
762 {
763 free (i18n_core->address.im_name);
764 free (i18n_core->address.im_locale);
765 free (i18n_core->address.im_addr);
766 free (i18n_core);
767 return False;
768 }
769 /*endif*/
770
771 _XRegisterFilterByType (dpy,
772 i18n_core->address.im_window,
773 SelectionRequest,
774 SelectionRequest,
775 WaitXSelectionRequest,
776 (XPointer)ims);
777 XFlush(dpy);
778 return True;
779 }
780
xi18n_closeIM(XIMS ims)781 static Status xi18n_closeIM(XIMS ims)
782 {
783 Xi18n i18n_core = ims->protocol;
784 Display *dpy = i18n_core->address.dpy;
785
786 /* remove all client connections */
787 while (i18n_core->address.clients != NULL) {
788 int connect_id = i18n_core->address.clients->connect_id;
789 i18n_core->methods.disconnect(ims, connect_id);
790 }
791
792 DeleteXi18nAtom(i18n_core);
793 if (!i18n_core->methods.end (ims))
794 return False;
795
796 _XUnregisterFilter (dpy,
797 i18n_core->address.im_window,
798 WaitXSelectionRequest,
799 (XPointer)ims);
800
801 _Xi18nDeleteAllClients(i18n_core);
802 _Xi18nDeleteFreeClients(i18n_core);
803
804 free (i18n_core->address.im_name);
805 free (i18n_core->address.im_locale);
806 free (i18n_core->address.im_addr);
807 free (i18n_core->address.input_styles.supported_styles);
808 free (i18n_core->address.on_keys.keylist);
809 free (i18n_core->address.off_keys.keylist);
810 free (i18n_core->address.encoding_list.supported_encodings);
811 free (i18n_core->address.xim_attr);
812 free (i18n_core->address.xic_attr);
813 free (i18n_core->address.connect_addr);
814 free (i18n_core);
815 return True;
816 }
817
xi18n_setIMValues(XIMS ims,XIMArg * args)818 static char *xi18n_setIMValues (XIMS ims, XIMArg *args)
819 {
820 Xi18n i18n_core = ims->protocol;
821 char *ret;
822
823 if ((ret = ParseArgs (i18n_core, I18N_SET, args)) != NULL)
824 return ret;
825 /*endif*/
826 return NULL;
827 }
828
xi18n_getIMValues(XIMS ims,XIMArg * args)829 static char *xi18n_getIMValues (XIMS ims, XIMArg *args)
830 {
831 Xi18n i18n_core = ims->protocol;
832 char *ret;
833
834 if ((ret = ParseArgs (i18n_core, I18N_GET, args)) != NULL)
835 return ret;
836 /*endif*/
837 return NULL;
838 }
839
840 /* For byte swapping */
841 #define Swap16(n) \
842 (((n) << 8 & 0xFF00) | \
843 ((n) >> 8 & 0xFF) \
844 )
845 #define Swap32(n) \
846 (((n) << 24 & 0xFF000000) | \
847 ((n) << 8 & 0xFF0000) | \
848 ((n) >> 8 & 0xFF00) | \
849 ((n) >> 24 & 0xFF) \
850 )
851 #define Swap64(n) \
852 (((n) << 56 & 0xFF00000000000000) | \
853 ((n) << 40 & 0xFF000000000000) | \
854 ((n) << 24 & 0xFF0000000000) | \
855 ((n) << 8 & 0xFF00000000) | \
856 ((n) >> 8 & 0xFF000000) | \
857 ((n) >> 24 & 0xFF0000) | \
858 ((n) >> 40 & 0xFF00) | \
859 ((n) >> 56 & 0xFF) \
860 )
861
EventToWireEvent(XEvent * ev,xEvent * event,CARD16 * serial,Bool need_swap)862 static void EventToWireEvent (XEvent *ev, xEvent *event, CARD16 *serial, Bool need_swap)
863 {
864 *serial = (CARD16) (ev->xany.serial >> 16);
865 event->u.u.sequenceNumber =
866 (CARD16) (ev->xany.serial & (unsigned long) 0xFFFF);
867
868 switch (ev->type)
869 {
870 case KeyPress:
871 case KeyRelease:
872 {
873 XKeyEvent *kev = (XKeyEvent *) ev;
874
875 if (need_swap) {
876 event->u.u.type = ev->type;
877 event->u.keyButtonPointer.root = Swap32(kev->root);
878 event->u.keyButtonPointer.state = Swap16(kev->state);
879 event->u.keyButtonPointer.time = Swap32(kev->time);
880 event->u.keyButtonPointer.event = Swap32(kev->window);
881 event->u.keyButtonPointer.child = Swap32(kev->subwindow);
882 event->u.keyButtonPointer.eventX = Swap16(kev->x);
883 event->u.keyButtonPointer.eventY = Swap16(kev->y);
884 event->u.keyButtonPointer.rootX = Swap16(kev->x_root);
885 event->u.keyButtonPointer.rootY = Swap16(kev->y_root);
886 event->u.keyButtonPointer.sameScreen = kev->same_screen;
887 event->u.u.detail = kev->keycode;
888 } else {
889 event->u.u.type = ev->type;
890 event->u.keyButtonPointer.root = kev->root;
891 event->u.keyButtonPointer.state = kev->state;
892 event->u.keyButtonPointer.time = kev->time;
893 event->u.keyButtonPointer.event = kev->window;
894 event->u.keyButtonPointer.child = kev->subwindow;
895 event->u.keyButtonPointer.eventX = kev->x;
896 event->u.keyButtonPointer.eventY = kev->y;
897 event->u.keyButtonPointer.rootX = kev->x_root;
898 event->u.keyButtonPointer.rootY = kev->y_root;
899 event->u.keyButtonPointer.sameScreen = kev->same_screen;
900 event->u.u.detail = kev->keycode;
901 }
902 }
903 }
904 /*endswitch*/
905 }
906
xi18n_forwardEvent(XIMS ims,XPointer xp)907 static Status xi18n_forwardEvent (XIMS ims, XPointer xp)
908 {
909 Xi18n i18n_core = ims->protocol;
910 IMForwardEventStruct *call_data = (IMForwardEventStruct *)xp;
911 FrameMgr fm;
912 extern XimFrameRec forward_event_fr[];
913 register int total_size;
914 unsigned char *reply = NULL;
915 unsigned char *replyp;
916 CARD16 serial;
917 int event_size;
918 Xi18nClient *client;
919 Bool need_swap;
920
921 client = (Xi18nClient *) _Xi18nFindClient (i18n_core, call_data->connect_id);
922
923 /* create FrameMgr */
924 need_swap = _Xi18nNeedSwap (i18n_core, call_data->connect_id);
925 fm = FrameMgrInit (forward_event_fr,
926 NULL,
927 need_swap);
928
929 total_size = FrameMgrGetTotalSize (fm);
930 event_size = sizeof (xEvent);
931 reply = (unsigned char *) malloc (total_size + event_size);
932 if (!reply)
933 {
934 _Xi18nSendMessage (ims,
935 call_data->connect_id,
936 XIM_ERROR,
937 0,
938 0,
939 0);
940 return False;
941 }
942 /*endif*/
943 memset (reply, 0, total_size + event_size);
944 FrameMgrSetBuffer (fm, reply);
945 replyp = reply;
946
947 call_data->sync_bit = 1; /* always sync */
948 client->sync = True;
949
950 FrameMgrPutToken (fm, call_data->connect_id);
951 FrameMgrPutToken (fm, call_data->icid);
952 FrameMgrPutToken (fm, call_data->sync_bit);
953
954 replyp += total_size;
955 EventToWireEvent (&(call_data->event), (xEvent *) replyp, &serial, need_swap);
956
957 FrameMgrPutToken (fm, serial);
958
959 _Xi18nSendMessage (ims,
960 call_data->connect_id,
961 XIM_FORWARD_EVENT,
962 0,
963 reply,
964 total_size + event_size);
965
966 free (reply);
967 FrameMgrFree (fm);
968
969 return True;
970 }
971
xi18n_commit(XIMS ims,XPointer xp)972 static Status xi18n_commit (XIMS ims, XPointer xp)
973 {
974 Xi18n i18n_core = ims->protocol;
975 IMCommitStruct *call_data = (IMCommitStruct *)xp;
976 FrameMgr fm;
977 extern XimFrameRec commit_chars_fr[];
978 extern XimFrameRec commit_both_fr[];
979 register int total_size;
980 unsigned char *reply = NULL;
981 CARD16 str_length;
982
983 call_data->flag |= XimSYNCHRONUS; /* always sync */
984
985 if (!(call_data->flag & XimLookupKeySym)
986 &&
987 (call_data->flag & XimLookupChars))
988 {
989 fm = FrameMgrInit (commit_chars_fr,
990 NULL,
991 _Xi18nNeedSwap (i18n_core, call_data->connect_id));
992
993 /* set length of STRING8 */
994 str_length = strlen (call_data->commit_string);
995 FrameMgrSetSize (fm, str_length);
996 total_size = FrameMgrGetTotalSize (fm);
997 reply = (unsigned char *) malloc (total_size);
998 if (!reply)
999 {
1000 _Xi18nSendMessage (ims,
1001 call_data->connect_id,
1002 XIM_ERROR,
1003 0,
1004 0,
1005 0);
1006 return False;
1007 }
1008 /*endif*/
1009 memset (reply, 0, total_size);
1010 FrameMgrSetBuffer (fm, reply);
1011
1012 str_length = FrameMgrGetSize (fm);
1013 FrameMgrPutToken (fm, call_data->connect_id);
1014 FrameMgrPutToken (fm, call_data->icid);
1015 FrameMgrPutToken (fm, call_data->flag);
1016 FrameMgrPutToken (fm, str_length);
1017 FrameMgrPutToken (fm, call_data->commit_string);
1018 }
1019 else
1020 {
1021 fm = FrameMgrInit (commit_both_fr,
1022 NULL,
1023 _Xi18nNeedSwap (i18n_core, call_data->connect_id));
1024 /* set length of STRING8 */
1025 str_length = strlen (call_data->commit_string);
1026 if (str_length > 0)
1027 FrameMgrSetSize (fm, str_length);
1028 /*endif*/
1029 total_size = FrameMgrGetTotalSize (fm);
1030 reply = (unsigned char *) malloc (total_size);
1031 if (!reply)
1032 {
1033 _Xi18nSendMessage (ims,
1034 call_data->connect_id,
1035 XIM_ERROR,
1036 0,
1037 0,
1038 0);
1039 return False;
1040 }
1041 /*endif*/
1042 FrameMgrSetBuffer (fm, reply);
1043 FrameMgrPutToken (fm, call_data->connect_id);
1044 FrameMgrPutToken (fm, call_data->icid);
1045 FrameMgrPutToken (fm, call_data->flag);
1046 FrameMgrPutToken (fm, call_data->keysym);
1047 if (str_length > 0)
1048 {
1049 str_length = FrameMgrGetSize (fm);
1050 FrameMgrPutToken (fm, str_length);
1051 FrameMgrPutToken (fm, call_data->commit_string);
1052 }
1053 /*endif*/
1054 }
1055 /*endif*/
1056 _Xi18nSendMessage (ims,
1057 call_data->connect_id,
1058 XIM_COMMIT,
1059 0,
1060 reply,
1061 total_size);
1062 FrameMgrFree (fm);
1063 free (reply);
1064
1065 return True;
1066 }
1067
xi18n_callCallback(XIMS ims,XPointer xp)1068 static int xi18n_callCallback (XIMS ims, XPointer xp)
1069 {
1070 IMProtocol *call_data = (IMProtocol *)xp;
1071 switch (call_data->major_code)
1072 {
1073 case XIM_GEOMETRY:
1074 return _Xi18nGeometryCallback (ims, call_data);
1075
1076 case XIM_PREEDIT_START:
1077 return _Xi18nPreeditStartCallback (ims, call_data);
1078
1079 case XIM_PREEDIT_DRAW:
1080 return _Xi18nPreeditDrawCallback (ims, call_data);
1081
1082 case XIM_PREEDIT_CARET:
1083 return _Xi18nPreeditCaretCallback (ims, call_data);
1084
1085 case XIM_PREEDIT_DONE:
1086 return _Xi18nPreeditDoneCallback (ims, call_data);
1087
1088 case XIM_STATUS_START:
1089 return _Xi18nStatusStartCallback (ims, call_data);
1090
1091 case XIM_STATUS_DRAW:
1092 return _Xi18nStatusDrawCallback (ims, call_data);
1093
1094 case XIM_STATUS_DONE:
1095 return _Xi18nStatusDoneCallback (ims, call_data);
1096
1097 case XIM_STR_CONVERSION:
1098 return _Xi18nStringConversionCallback (ims, call_data);
1099 }
1100 /*endswitch*/
1101 return False;
1102 }
1103
1104 /* preeditStart and preeditEnd are used only for Dynamic Event Flow. */
xi18n_preeditStart(XIMS ims,XPointer xp)1105 static int xi18n_preeditStart (XIMS ims, XPointer xp)
1106 {
1107 IMProtocol *call_data = (IMProtocol *)xp;
1108 Xi18n i18n_core = ims->protocol;
1109 IMPreeditStateStruct *preedit_state =
1110 (IMPreeditStateStruct *) &call_data->preedit_state;
1111 long mask;
1112 int on_key_num = i18n_core->address.on_keys.count_keys;
1113 int off_key_num = i18n_core->address.off_keys.count_keys;
1114
1115 if (on_key_num == 0 && off_key_num == 0)
1116 return False;
1117 /*endif*/
1118 if (i18n_core->address.imvalue_mask & I18N_FILTERMASK)
1119 mask = i18n_core->address.filterevent_mask;
1120 else
1121 mask = DEFAULT_FILTER_MASK;
1122 /*endif*/
1123 _Xi18nSetEventMask (ims,
1124 preedit_state->connect_id,
1125 preedit_state->connect_id,
1126 preedit_state->icid,
1127 mask,
1128 ~mask);
1129 return True;
1130 }
1131
xi18n_preeditEnd(XIMS ims,XPointer xp)1132 static int xi18n_preeditEnd (XIMS ims, XPointer xp)
1133 {
1134 IMProtocol *call_data = (IMProtocol *)xp;
1135 Xi18n i18n_core = ims->protocol;
1136 int on_key_num = i18n_core->address.on_keys.count_keys;
1137 int off_key_num = i18n_core->address.off_keys.count_keys;
1138 IMPreeditStateStruct *preedit_state;
1139
1140 preedit_state = (IMPreeditStateStruct *) &call_data->preedit_state;
1141
1142 if (on_key_num == 0 && off_key_num == 0)
1143 return False;
1144 /*endif*/
1145
1146 _Xi18nSetEventMask (ims,
1147 preedit_state->connect_id,
1148 preedit_state->connect_id,
1149 preedit_state->icid,
1150 0,
1151 0);
1152 return True;
1153 }
1154
xi18n_syncXlib(XIMS ims,XPointer xp)1155 static int xi18n_syncXlib (XIMS ims, XPointer xp)
1156 {
1157 IMProtocol *call_data = (IMProtocol *)xp;
1158 Xi18n i18n_core = ims->protocol;
1159 IMSyncXlibStruct *sync_xlib;
1160
1161 extern XimFrameRec sync_fr[];
1162 FrameMgr fm;
1163 CARD16 connect_id = call_data->any.connect_id;
1164 int total_size;
1165 unsigned char *reply;
1166
1167 sync_xlib = (IMSyncXlibStruct *) &call_data->sync_xlib;
1168 fm = FrameMgrInit (sync_fr, NULL,
1169 _Xi18nNeedSwap (i18n_core, connect_id));
1170 total_size = FrameMgrGetTotalSize(fm);
1171 reply = (unsigned char *) malloc (total_size);
1172 if (!reply) {
1173 _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0);
1174 return False;
1175 }
1176 memset (reply, 0, total_size);
1177 FrameMgrSetBuffer (fm, reply);
1178
1179 /* input input-method ID */
1180 FrameMgrPutToken (fm, connect_id);
1181 /* input input-context ID */
1182 FrameMgrPutToken (fm, sync_xlib->icid);
1183 _Xi18nSendMessage (ims, connect_id, XIM_SYNC, 0, reply, total_size);
1184
1185 FrameMgrFree (fm);
1186 free(reply);
1187 return True;
1188 }
1189
1190