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->imvalue_mask & I18N_ON_KEYS)
254 return IMOnKeysList;
255 /*endif*/
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, 256, "@server=%s", i18n_core->address.im_name);
512 if ((atom = XInternAtom(dpy, buf, False)) == 0)
513 return False;
514 i18n_core->address.selection = atom;
515
516 if (XIM_Servers == None)
517 XIM_Servers = XInternAtom (dpy, XIM_SERVERS, False);
518 /*endif*/
519 XGetWindowProperty (dpy,
520 root,
521 XIM_Servers,
522 0L,
523 1000000L,
524 False,
525 XA_ATOM,
526 &realtype,
527 &realformat,
528 &length,
529 &bytesafter,
530 (unsigned char **) (&data));
531 if (realtype != None && (realtype != XA_ATOM || realformat != 32)) {
532 if (data != NULL)
533 XFree ((char *) data);
534 return False;
535 }
536
537 found = False;
538 for (i = 0; i < length; i++) {
539 if (data[i] == atom) {
540 Window owner;
541 found = True;
542 if ((owner = XGetSelectionOwner (dpy, atom)) != ims_win) {
543 if (owner == None || forse == True)
544 XSetSelectionOwner (dpy, atom, ims_win, CurrentTime);
545 else
546 return False;
547 }
548 break;
549 }
550 }
551
552 if (found == False) {
553 XSetSelectionOwner (dpy, atom, ims_win, CurrentTime);
554 XChangeProperty (dpy,
555 root,
556 XIM_Servers,
557 XA_ATOM,
558 32,
559 PropModePrepend,
560 (unsigned char *) &atom,
561 1);
562 }
563 else {
564 /*
565 * We always need to generate the PropertyNotify to the Root Window
566 */
567 XChangeProperty (dpy,
568 root,
569 XIM_Servers,
570 XA_ATOM,
571 32,
572 PropModePrepend,
573 (unsigned char *) data,
574 0);
575 }
576 if (data != NULL)
577 XFree ((char *) data);
578
579 /* Intern "LOCALES" and "TRANSOPORT" Target Atoms */
580 i18n_core->address.Localename = XInternAtom (dpy, LOCALES, False);
581 i18n_core->address.Transportname = XInternAtom (dpy, TRANSPORT, False);
582 return (XGetSelectionOwner (dpy, atom) == ims_win);
583 }
584
DeleteXi18nAtom(Xi18n i18n_core)585 static int DeleteXi18nAtom(Xi18n i18n_core)
586 {
587 Display *dpy = i18n_core->address.dpy;
588 Window root = RootWindow (dpy, DefaultScreen (dpy));
589 Atom realtype;
590 int realformat;
591 unsigned long bytesafter;
592 long *data=NULL;
593 unsigned long length;
594 Atom atom;
595 int i, ret;
596 int found;
597 char buf[256];
598
599 (void)snprintf(buf, 256, "@server=%s", i18n_core->address.im_name);
600 if ((atom = XInternAtom(dpy, buf, False)) == 0)
601 return False;
602 i18n_core->address.selection = atom;
603
604 if (XIM_Servers == None)
605 XIM_Servers = XInternAtom (dpy, XIM_SERVERS, False);
606 XGetWindowProperty (dpy,
607 root,
608 XIM_Servers,
609 0L,
610 1000000L,
611 False,
612 XA_ATOM,
613 &realtype,
614 &realformat,
615 &length,
616 &bytesafter,
617 (unsigned char **) (&data));
618 if (realtype != XA_ATOM || realformat != 32) {
619 if (data != NULL)
620 XFree ((char *) data);
621 return False;
622 }
623
624 found = False;
625 for (i = 0; i < length; i++) {
626 if (data[i] == atom) {
627 found = True;
628 break;
629 }
630 }
631
632 if (found == True) {
633 for (i=i+1; i<length; i++)
634 data[i-1] = data[i];
635 XChangeProperty (dpy,
636 root,
637 XIM_Servers,
638 XA_ATOM,
639 32,
640 PropModeReplace,
641 (unsigned char *)data,
642 length-1);
643 ret = True;
644 }
645 else {
646 XChangeProperty (dpy,
647 root,
648 XIM_Servers,
649 XA_ATOM,
650 32,
651 PropModePrepend,
652 (unsigned char *)data,
653 0);
654 ret = False;
655 }
656 if (data != NULL)
657 XFree ((char *) data);
658 return ret;
659 }
660
661
662 /* XIM protocol methods */
xi18n_setup(Display * dpy,XIMArg * args)663 static void *xi18n_setup (Display *dpy, XIMArg *args)
664 {
665 Xi18n i18n_core;
666 CARD16 endian = 1;
667
668 if ((i18n_core = (Xi18n) malloc (sizeof (Xi18nCore))) == (Xi18n) NULL)
669 return NULL;
670 /*endif*/
671
672 memset (i18n_core, 0, sizeof (Xi18nCore));
673
674 i18n_core->address.dpy = dpy;
675
676 if (ParseArgs (i18n_core, I18N_OPEN, args) != NULL)
677 {
678 XFree (i18n_core);
679 return NULL;
680 }
681 /*endif*/
682 if (*(char *) &endian)
683 i18n_core->address.im_byteOrder = 'l';
684 else
685 i18n_core->address.im_byteOrder = 'B';
686 /*endif*/
687
688 /* install IMAttr and ICAttr list in i18n_core */
689 _Xi18nInitAttrList (i18n_core);
690
691 /* install IMExtension list in i18n_core */
692 _Xi18nInitExtension (i18n_core);
693
694 return i18n_core;
695 }
696
ReturnSelectionNotify(Xi18n i18n_core,XSelectionRequestEvent * ev)697 static void ReturnSelectionNotify (Xi18n i18n_core, XSelectionRequestEvent *ev)
698 {
699 XEvent event;
700 Display *dpy = i18n_core->address.dpy;
701 char buf[4096];
702
703 event.type = SelectionNotify;
704 event.xselection.requestor = ev->requestor;
705 event.xselection.selection = ev->selection;
706 event.xselection.target = ev->target;
707 event.xselection.time = ev->time;
708 event.xselection.property = ev->property;
709 if (ev->target == i18n_core->address.Localename)
710 {
711 snprintf (buf, 4096, "@locale=%s", i18n_core->address.im_locale);
712 }
713 else if (ev->target == i18n_core->address.Transportname)
714 {
715 snprintf (buf, 4096, "@transport=%s", i18n_core->address.im_addr);
716 }
717 /*endif*/
718 XChangeProperty (dpy,
719 event.xselection.requestor,
720 ev->target,
721 ev->target,
722 8,
723 PropModeReplace,
724 (unsigned char *) buf,
725 strlen (buf));
726 XSendEvent (dpy, event.xselection.requestor, False, NoEventMask, &event);
727 XFlush (i18n_core->address.dpy);
728 }
729
WaitXSelectionRequest(Display * dpy,Window win,XEvent * ev,XPointer client_data)730 static Bool WaitXSelectionRequest (Display *dpy,
731 Window win,
732 XEvent *ev,
733 XPointer client_data)
734 {
735 XIMS ims = (XIMS) client_data;
736 Xi18n i18n_core = ims->protocol;
737
738 if (((XSelectionRequestEvent *) ev)->selection
739 == i18n_core->address.selection)
740 {
741 ReturnSelectionNotify (i18n_core, (XSelectionRequestEvent *) ev);
742 return True;
743 }
744 /*endif*/
745 return False;
746 }
747
xi18n_openIM(XIMS ims)748 static Status xi18n_openIM(XIMS ims)
749 {
750 Xi18n i18n_core = ims->protocol;
751 Display *dpy = i18n_core->address.dpy;
752
753 if (!CheckIMName (i18n_core)
754 ||
755 !SetXi18nSelectionOwner (i18n_core)
756 ||
757 !i18n_core->methods.begin (ims))
758 {
759 XFree (i18n_core->address.im_name);
760 XFree (i18n_core->address.im_locale);
761 XFree (i18n_core->address.im_addr);
762 XFree (i18n_core);
763 return False;
764 }
765 /*endif*/
766
767 _XRegisterFilterByType (dpy,
768 i18n_core->address.im_window,
769 SelectionRequest,
770 SelectionRequest,
771 WaitXSelectionRequest,
772 (XPointer)ims);
773 XFlush(dpy);
774 return True;
775 }
776
xi18n_closeIM(XIMS ims)777 static Status xi18n_closeIM(XIMS ims)
778 {
779 Xi18n i18n_core = ims->protocol;
780 Display *dpy = i18n_core->address.dpy;
781
782 DeleteXi18nAtom(i18n_core);
783 if (!i18n_core->methods.end (ims))
784 return False;
785
786 _XUnregisterFilter (dpy,
787 i18n_core->address.im_window,
788 WaitXSelectionRequest,
789 (XPointer)ims);
790 XFree (i18n_core->address.im_name);
791 XFree (i18n_core->address.im_locale);
792 XFree (i18n_core->address.im_addr);
793 XFree (i18n_core);
794 return True;
795 }
796
xi18n_setIMValues(XIMS ims,XIMArg * args)797 static char *xi18n_setIMValues (XIMS ims, XIMArg *args)
798 {
799 Xi18n i18n_core = ims->protocol;
800 char *ret;
801
802 if ((ret = ParseArgs (i18n_core, I18N_SET, args)) != NULL)
803 return ret;
804 /*endif*/
805 return NULL;
806 }
807
xi18n_getIMValues(XIMS ims,XIMArg * args)808 static char *xi18n_getIMValues (XIMS ims, XIMArg *args)
809 {
810 Xi18n i18n_core = ims->protocol;
811 char *ret;
812
813 if ((ret = ParseArgs (i18n_core, I18N_GET, args)) != NULL)
814 return ret;
815 /*endif*/
816 return NULL;
817 }
818
EventToWireEvent(XEvent * ev,xEvent * event,CARD16 * serial,Bool byte_swap)819 static void EventToWireEvent (XEvent *ev, xEvent *event,
820 CARD16 *serial, Bool byte_swap)
821 {
822 FrameMgr fm;
823 extern XimFrameRec wire_keyevent_fr[];
824 extern XimFrameRec short_fr[];
825 BYTE b;
826 CARD16 c16;
827 CARD32 c32;
828
829 *serial = (CARD16)(ev->xany.serial >> 16);
830 switch (ev->type) {
831 case KeyPress:
832 case KeyRelease:
833 {
834 XKeyEvent *kev = (XKeyEvent*)ev;
835 /* create FrameMgr */
836 fm = FrameMgrInit(wire_keyevent_fr, (char *)(&(event->u)), byte_swap);
837
838 /* set values */
839 b = (BYTE)kev->type; FrameMgrPutToken(fm, b);
840 b = (BYTE)kev->keycode; FrameMgrPutToken(fm, b);
841 c16 = (CARD16)(kev->serial & (unsigned long)0xffff);
842 FrameMgrPutToken(fm, c16);
843 c32 = (CARD32)kev->time; FrameMgrPutToken(fm, c32);
844 c32 = (CARD32)kev->root; FrameMgrPutToken(fm, c32);
845 c32 = (CARD32)kev->window; FrameMgrPutToken(fm, c32);
846 c32 = (CARD32)kev->subwindow; FrameMgrPutToken(fm, c32);
847 c16 = (CARD16)kev->x_root; FrameMgrPutToken(fm, c16);
848 c16 = (CARD16)kev->y_root; FrameMgrPutToken(fm, c16);
849 c16 = (CARD16)kev->x; FrameMgrPutToken(fm, c16);
850 c16 = (CARD16)kev->y; FrameMgrPutToken(fm, c16);
851 c16 = (CARD16)kev->state; FrameMgrPutToken(fm, c16);
852 b = (BYTE)kev->same_screen; FrameMgrPutToken(fm, b);
853 }
854 break;
855 default:
856 /* create FrameMgr */
857 fm = FrameMgrInit(short_fr, (char *)(&(event->u.u.sequenceNumber)),
858 byte_swap);
859 c16 = (CARD16)(ev->xany.serial & (unsigned long)0xffff);
860 FrameMgrPutToken(fm, c16);
861 break;
862 }
863 /* free FrameMgr */
864 FrameMgrFree(fm);
865 }
866
xi18n_forwardEvent(XIMS ims,XPointer xp)867 static Status xi18n_forwardEvent (XIMS ims, XPointer xp)
868 {
869 Xi18n i18n_core = ims->protocol;
870 IMForwardEventStruct *call_data = (IMForwardEventStruct *)xp;
871 FrameMgr fm;
872 extern XimFrameRec forward_event_fr[];
873 register int total_size;
874 unsigned char *reply = NULL;
875 unsigned char *replyp;
876 CARD16 serial;
877 int event_size;
878 Xi18nClient *client;
879
880 client = (Xi18nClient *) _Xi18nFindClient (i18n_core, call_data->connect_id);
881
882 /* create FrameMgr */
883 fm = FrameMgrInit (forward_event_fr,
884 NULL,
885 _Xi18nNeedSwap (i18n_core, call_data->connect_id));
886
887 total_size = FrameMgrGetTotalSize (fm);
888 event_size = sizeof (xEvent);
889 reply = (unsigned char *) malloc (total_size + event_size);
890 if (!reply)
891 {
892 _Xi18nSendMessage (ims,
893 call_data->connect_id,
894 XIM_ERROR,
895 0,
896 0,
897 0);
898 return False;
899 }
900 /*endif*/
901 memset (reply, 0, total_size + event_size);
902 FrameMgrSetBuffer (fm, reply);
903 replyp = reply;
904
905 call_data->sync_bit = 1; /* always sync */
906 client->sync = True;
907
908 FrameMgrPutToken (fm, call_data->connect_id);
909 FrameMgrPutToken (fm, call_data->icid);
910 FrameMgrPutToken (fm, call_data->sync_bit);
911
912 replyp += total_size;
913 EventToWireEvent (&(call_data->event),
914 (xEvent *) replyp,
915 &serial,
916 _Xi18nNeedSwap (i18n_core, call_data->connect_id));
917
918 FrameMgrPutToken (fm, serial);
919
920 _Xi18nSendMessage (ims,
921 call_data->connect_id,
922 XIM_FORWARD_EVENT,
923 0,
924 reply,
925 total_size + event_size);
926
927 XFree (reply);
928 FrameMgrFree (fm);
929
930 return True;
931 }
932
xi18n_commit(XIMS ims,XPointer xp)933 static Status xi18n_commit (XIMS ims, XPointer xp)
934 {
935 Xi18n i18n_core = ims->protocol;
936 IMCommitStruct *call_data = (IMCommitStruct *)xp;
937 FrameMgr fm;
938 extern XimFrameRec commit_chars_fr[];
939 extern XimFrameRec commit_both_fr[];
940 register int total_size;
941 unsigned char *reply = NULL;
942 CARD16 str_length;
943
944 call_data->flag |= XimSYNCHRONUS; /* always sync */
945
946 if (!(call_data->flag & XimLookupKeySym)
947 &&
948 (call_data->flag & XimLookupChars))
949 {
950 fm = FrameMgrInit (commit_chars_fr,
951 NULL,
952 _Xi18nNeedSwap (i18n_core, call_data->connect_id));
953
954 /* set length of STRING8 */
955 str_length = strlen (call_data->commit_string);
956 FrameMgrSetSize (fm, str_length);
957 total_size = FrameMgrGetTotalSize (fm);
958 reply = (unsigned char *) malloc (total_size);
959 if (!reply)
960 {
961 _Xi18nSendMessage (ims,
962 call_data->connect_id,
963 XIM_ERROR,
964 0,
965 0,
966 0);
967 return False;
968 }
969 /*endif*/
970 memset (reply, 0, total_size);
971 FrameMgrSetBuffer (fm, reply);
972
973 str_length = FrameMgrGetSize (fm);
974 FrameMgrPutToken (fm, call_data->connect_id);
975 FrameMgrPutToken (fm, call_data->icid);
976 FrameMgrPutToken (fm, call_data->flag);
977 FrameMgrPutToken (fm, str_length);
978 FrameMgrPutToken (fm, call_data->commit_string);
979 }
980 else
981 {
982 fm = FrameMgrInit (commit_both_fr,
983 NULL,
984 _Xi18nNeedSwap (i18n_core, call_data->connect_id));
985 /* set length of STRING8 */
986 str_length = strlen (call_data->commit_string);
987 if (str_length > 0)
988 FrameMgrSetSize (fm, str_length);
989 /*endif*/
990 total_size = FrameMgrGetTotalSize (fm);
991 reply = (unsigned char *) malloc (total_size);
992 if (!reply)
993 {
994 _Xi18nSendMessage (ims,
995 call_data->connect_id,
996 XIM_ERROR,
997 0,
998 0,
999 0);
1000 return False;
1001 }
1002 /*endif*/
1003 FrameMgrSetBuffer (fm, reply);
1004 FrameMgrPutToken (fm, call_data->connect_id);
1005 FrameMgrPutToken (fm, call_data->icid);
1006 FrameMgrPutToken (fm, call_data->flag);
1007 FrameMgrPutToken (fm, call_data->keysym);
1008 if (str_length > 0)
1009 {
1010 str_length = FrameMgrGetSize (fm);
1011 FrameMgrPutToken (fm, str_length);
1012 FrameMgrPutToken (fm, call_data->commit_string);
1013 }
1014 /*endif*/
1015 }
1016 /*endif*/
1017 _Xi18nSendMessage (ims,
1018 call_data->connect_id,
1019 XIM_COMMIT,
1020 0,
1021 reply,
1022 total_size);
1023 FrameMgrFree (fm);
1024 XFree (reply);
1025
1026 return True;
1027 }
1028
xi18n_callCallback(XIMS ims,XPointer xp)1029 static int xi18n_callCallback (XIMS ims, XPointer xp)
1030 {
1031 IMProtocol *call_data = (IMProtocol *)xp;
1032 switch (call_data->major_code)
1033 {
1034 case XIM_GEOMETRY:
1035 return _Xi18nGeometryCallback (ims, call_data);
1036
1037 case XIM_PREEDIT_START:
1038 return _Xi18nPreeditStartCallback (ims, call_data);
1039
1040 case XIM_PREEDIT_DRAW:
1041 return _Xi18nPreeditDrawCallback (ims, call_data);
1042
1043 case XIM_PREEDIT_CARET:
1044 return _Xi18nPreeditCaretCallback (ims, call_data);
1045
1046 case XIM_PREEDIT_DONE:
1047 return _Xi18nPreeditDoneCallback (ims, call_data);
1048
1049 case XIM_STATUS_START:
1050 return _Xi18nStatusStartCallback (ims, call_data);
1051
1052 case XIM_STATUS_DRAW:
1053 return _Xi18nStatusDrawCallback (ims, call_data);
1054
1055 case XIM_STATUS_DONE:
1056 return _Xi18nStatusDoneCallback (ims, call_data);
1057
1058 case XIM_STR_CONVERSION:
1059 return _Xi18nStringConversionCallback (ims, call_data);
1060 }
1061 /*endswitch*/
1062 return False;
1063 }
1064
1065 /* preeditStart and preeditEnd are used only for Dynamic Event Flow. */
xi18n_preeditStart(XIMS ims,XPointer xp)1066 static int xi18n_preeditStart (XIMS ims, XPointer xp)
1067 {
1068 IMProtocol *call_data = (IMProtocol *)xp;
1069 Xi18n i18n_core = ims->protocol;
1070 IMPreeditStateStruct *preedit_state =
1071 (IMPreeditStateStruct *) &call_data->preedit_state;
1072 long mask;
1073 int on_key_num = i18n_core->address.on_keys.count_keys;
1074 int off_key_num = i18n_core->address.off_keys.count_keys;
1075
1076 if (on_key_num == 0 && off_key_num == 0)
1077 return False;
1078 /*endif*/
1079 if (i18n_core->address.imvalue_mask & I18N_FILTERMASK)
1080 mask = i18n_core->address.filterevent_mask;
1081 else
1082 mask = DEFAULT_FILTER_MASK;
1083 /*endif*/
1084 _Xi18nSetEventMask (ims,
1085 preedit_state->connect_id,
1086 preedit_state->connect_id,
1087 preedit_state->icid,
1088 mask,
1089 ~mask);
1090 return True;
1091 }
1092
xi18n_preeditEnd(XIMS ims,XPointer xp)1093 static int xi18n_preeditEnd (XIMS ims, XPointer xp)
1094 {
1095 IMProtocol *call_data = (IMProtocol *)xp;
1096 Xi18n i18n_core = ims->protocol;
1097 int on_key_num = i18n_core->address.on_keys.count_keys;
1098 int off_key_num = i18n_core->address.off_keys.count_keys;
1099 IMPreeditStateStruct *preedit_state;
1100
1101 preedit_state = (IMPreeditStateStruct *) &call_data->preedit_state;
1102
1103 if (on_key_num == 0 && off_key_num == 0)
1104 return False;
1105 /*endif*/
1106
1107 _Xi18nSetEventMask (ims,
1108 preedit_state->connect_id,
1109 preedit_state->connect_id,
1110 preedit_state->icid,
1111 0,
1112 0);
1113 return True;
1114 }
1115
xi18n_syncXlib(XIMS ims,XPointer xp)1116 static int xi18n_syncXlib (XIMS ims, XPointer xp)
1117 {
1118 IMProtocol *call_data = (IMProtocol *)xp;
1119 Xi18n i18n_core = ims->protocol;
1120 IMSyncXlibStruct *sync_xlib;
1121
1122 extern XimFrameRec sync_fr[];
1123 FrameMgr fm;
1124 CARD16 connect_id = call_data->any.connect_id;
1125 int total_size;
1126 unsigned char *reply;
1127
1128 sync_xlib = (IMSyncXlibStruct *) &call_data->sync_xlib;
1129 fm = FrameMgrInit (sync_fr, NULL,
1130 _Xi18nNeedSwap (i18n_core, connect_id));
1131 total_size = FrameMgrGetTotalSize(fm);
1132 reply = (unsigned char *) malloc (total_size);
1133 if (!reply) {
1134 _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0);
1135 return False;
1136 }
1137 memset (reply, 0, total_size);
1138 FrameMgrSetBuffer (fm, reply);
1139
1140 /* input input-method ID */
1141 FrameMgrPutToken (fm, connect_id);
1142 /* input input-context ID */
1143 FrameMgrPutToken (fm, sync_xlib->icid);
1144 _Xi18nSendMessage (ims, connect_id, XIM_SYNC, 0, reply, total_size);
1145
1146 FrameMgrFree (fm);
1147 XFree(reply);
1148 return True;
1149 }
1150
1151