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)sprintf(buf, "@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)sprintf(buf, "@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[256];
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 sprintf (buf, "@locale=%s", i18n_core->address.im_locale);
712 }
713 else if (ev->target == i18n_core->address.Transportname)
714 {
715 sprintf (buf, "@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)819 static void EventToWireEvent (XEvent *ev, xEvent *event, CARD16 *serial)
820 {
821 *serial = (CARD16) (ev->xany.serial >> 16);
822 event->u.u.sequenceNumber =
823 (CARD16) (ev->xany.serial & (unsigned long) 0xFFFF);
824
825 switch (ev->type)
826 {
827 case KeyPress:
828 case KeyRelease:
829 {
830 XKeyEvent *kev = (XKeyEvent *) ev;
831
832 event->u.u.type = ev->type;
833 event->u.keyButtonPointer.root = kev->root;
834 event->u.keyButtonPointer.state = kev->state;
835 event->u.keyButtonPointer.time = kev->time;
836 event->u.keyButtonPointer.event = kev->window;
837 event->u.keyButtonPointer.child = kev->subwindow;
838 event->u.keyButtonPointer.eventX = kev->x;
839 event->u.keyButtonPointer.eventY = kev->y;
840 event->u.keyButtonPointer.rootX = kev->x_root;
841 event->u.keyButtonPointer.rootY = kev->y_root;
842 event->u.keyButtonPointer.sameScreen = kev->same_screen;
843 event->u.u.detail = kev->keycode;
844 }
845 }
846 /*endswitch*/
847 }
848
xi18n_forwardEvent(XIMS ims,XPointer xp)849 static Status xi18n_forwardEvent (XIMS ims, XPointer xp)
850 {
851 Xi18n i18n_core = ims->protocol;
852 IMForwardEventStruct *call_data = (IMForwardEventStruct *)xp;
853 FrameMgr fm;
854 extern XimFrameRec forward_event_fr[];
855 register int total_size;
856 unsigned char *reply = NULL;
857 unsigned char *replyp;
858 CARD16 serial;
859 int event_size;
860 Xi18nClient *client;
861
862 client = (Xi18nClient *) _Xi18nFindClient (i18n_core, call_data->connect_id);
863
864 /* create FrameMgr */
865 fm = FrameMgrInit (forward_event_fr,
866 NULL,
867 _Xi18nNeedSwap (i18n_core, call_data->connect_id));
868
869 total_size = FrameMgrGetTotalSize (fm);
870 event_size = sizeof (xEvent);
871 reply = (unsigned char *) malloc (total_size + event_size);
872 if (!reply)
873 {
874 _Xi18nSendMessage (ims,
875 call_data->connect_id,
876 XIM_ERROR,
877 0,
878 0,
879 0);
880 return False;
881 }
882 /*endif*/
883 memset (reply, 0, total_size + event_size);
884 FrameMgrSetBuffer (fm, reply);
885 replyp = reply;
886
887 call_data->sync_bit = 1; /* always sync */
888 client->sync = True;
889
890 FrameMgrPutToken (fm, call_data->connect_id);
891 FrameMgrPutToken (fm, call_data->icid);
892 FrameMgrPutToken (fm, call_data->sync_bit);
893
894 replyp += total_size;
895 EventToWireEvent (&(call_data->event), (xEvent *) replyp, &serial);
896
897 FrameMgrPutToken (fm, serial);
898
899 _Xi18nSendMessage (ims,
900 call_data->connect_id,
901 XIM_FORWARD_EVENT,
902 0,
903 reply,
904 total_size + event_size);
905
906 XFree (reply);
907 FrameMgrFree (fm);
908
909 return True;
910 }
911
xi18n_commit(XIMS ims,XPointer xp)912 static Status xi18n_commit (XIMS ims, XPointer xp)
913 {
914 Xi18n i18n_core = ims->protocol;
915 IMCommitStruct *call_data = (IMCommitStruct *)xp;
916 FrameMgr fm;
917 extern XimFrameRec commit_chars_fr[];
918 extern XimFrameRec commit_both_fr[];
919 register int total_size;
920 unsigned char *reply = NULL;
921 CARD16 str_length;
922
923 call_data->flag |= XimSYNCHRONUS; /* always sync */
924
925 if (!(call_data->flag & XimLookupKeySym)
926 &&
927 (call_data->flag & XimLookupChars))
928 {
929 fm = FrameMgrInit (commit_chars_fr,
930 NULL,
931 _Xi18nNeedSwap (i18n_core, call_data->connect_id));
932
933 /* set length of STRING8 */
934 str_length = strlen (call_data->commit_string);
935 FrameMgrSetSize (fm, str_length);
936 total_size = FrameMgrGetTotalSize (fm);
937 reply = (unsigned char *) malloc (total_size);
938 if (!reply)
939 {
940 _Xi18nSendMessage (ims,
941 call_data->connect_id,
942 XIM_ERROR,
943 0,
944 0,
945 0);
946 return False;
947 }
948 /*endif*/
949 memset (reply, 0, total_size);
950 FrameMgrSetBuffer (fm, reply);
951
952 str_length = FrameMgrGetSize (fm);
953 FrameMgrPutToken (fm, call_data->connect_id);
954 FrameMgrPutToken (fm, call_data->icid);
955 FrameMgrPutToken (fm, call_data->flag);
956 FrameMgrPutToken (fm, str_length);
957 FrameMgrPutToken (fm, call_data->commit_string);
958 }
959 else
960 {
961 fm = FrameMgrInit (commit_both_fr,
962 NULL,
963 _Xi18nNeedSwap (i18n_core, call_data->connect_id));
964 /* set length of STRING8 */
965 str_length = strlen (call_data->commit_string);
966 if (str_length > 0)
967 FrameMgrSetSize (fm, str_length);
968 /*endif*/
969 total_size = FrameMgrGetTotalSize (fm);
970 reply = (unsigned char *) malloc (total_size);
971 if (!reply)
972 {
973 _Xi18nSendMessage (ims,
974 call_data->connect_id,
975 XIM_ERROR,
976 0,
977 0,
978 0);
979 return False;
980 }
981 /*endif*/
982 FrameMgrSetBuffer (fm, reply);
983 FrameMgrPutToken (fm, call_data->connect_id);
984 FrameMgrPutToken (fm, call_data->icid);
985 FrameMgrPutToken (fm, call_data->flag);
986 FrameMgrPutToken (fm, call_data->keysym);
987 if (str_length > 0)
988 {
989 str_length = FrameMgrGetSize (fm);
990 FrameMgrPutToken (fm, str_length);
991 FrameMgrPutToken (fm, call_data->commit_string);
992 }
993 /*endif*/
994 }
995 /*endif*/
996 _Xi18nSendMessage (ims,
997 call_data->connect_id,
998 XIM_COMMIT,
999 0,
1000 reply,
1001 total_size);
1002 FrameMgrFree (fm);
1003 XFree (reply);
1004
1005 return True;
1006 }
1007
xi18n_callCallback(XIMS ims,XPointer xp)1008 static int xi18n_callCallback (XIMS ims, XPointer xp)
1009 {
1010 IMProtocol *call_data = (IMProtocol *)xp;
1011 switch (call_data->major_code)
1012 {
1013 case XIM_GEOMETRY:
1014 return _Xi18nGeometryCallback (ims, call_data);
1015
1016 case XIM_PREEDIT_START:
1017 return _Xi18nPreeditStartCallback (ims, call_data);
1018
1019 case XIM_PREEDIT_DRAW:
1020 return _Xi18nPreeditDrawCallback (ims, call_data);
1021
1022 case XIM_PREEDIT_CARET:
1023 return _Xi18nPreeditCaretCallback (ims, call_data);
1024
1025 case XIM_PREEDIT_DONE:
1026 return _Xi18nPreeditDoneCallback (ims, call_data);
1027
1028 case XIM_STATUS_START:
1029 return _Xi18nStatusStartCallback (ims, call_data);
1030
1031 case XIM_STATUS_DRAW:
1032 return _Xi18nStatusDrawCallback (ims, call_data);
1033
1034 case XIM_STATUS_DONE:
1035 return _Xi18nStatusDoneCallback (ims, call_data);
1036
1037 case XIM_STR_CONVERSION:
1038 return _Xi18nStringConversionCallback (ims, call_data);
1039 }
1040 /*endswitch*/
1041 return False;
1042 }
1043
1044 /* preeditStart and preeditEnd are used only for Dynamic Event Flow. */
xi18n_preeditStart(XIMS ims,XPointer xp)1045 static int xi18n_preeditStart (XIMS ims, XPointer xp)
1046 {
1047 IMProtocol *call_data = (IMProtocol *)xp;
1048 Xi18n i18n_core = ims->protocol;
1049 IMPreeditStateStruct *preedit_state =
1050 (IMPreeditStateStruct *) &call_data->preedit_state;
1051 long mask;
1052 int on_key_num = i18n_core->address.on_keys.count_keys;
1053 int off_key_num = i18n_core->address.off_keys.count_keys;
1054
1055 if (on_key_num == 0 && off_key_num == 0)
1056 return False;
1057 /*endif*/
1058 if (i18n_core->address.imvalue_mask & I18N_FILTERMASK)
1059 mask = i18n_core->address.filterevent_mask;
1060 else
1061 mask = DEFAULT_FILTER_MASK;
1062 /*endif*/
1063 _Xi18nSetEventMask (ims,
1064 preedit_state->connect_id,
1065 preedit_state->connect_id,
1066 preedit_state->icid,
1067 mask,
1068 ~mask);
1069 return True;
1070 }
1071
xi18n_preeditEnd(XIMS ims,XPointer xp)1072 static int xi18n_preeditEnd (XIMS ims, XPointer xp)
1073 {
1074 IMProtocol *call_data = (IMProtocol *)xp;
1075 Xi18n i18n_core = ims->protocol;
1076 int on_key_num = i18n_core->address.on_keys.count_keys;
1077 int off_key_num = i18n_core->address.off_keys.count_keys;
1078 IMPreeditStateStruct *preedit_state;
1079
1080 preedit_state = (IMPreeditStateStruct *) &call_data->preedit_state;
1081
1082 if (on_key_num == 0 && off_key_num == 0)
1083 return False;
1084 /*endif*/
1085
1086 _Xi18nSetEventMask (ims,
1087 preedit_state->connect_id,
1088 preedit_state->connect_id,
1089 preedit_state->icid,
1090 0,
1091 0);
1092 return True;
1093 }
1094
xi18n_syncXlib(XIMS ims,XPointer xp)1095 static int xi18n_syncXlib (XIMS ims, XPointer xp)
1096 {
1097 IMProtocol *call_data = (IMProtocol *)xp;
1098 Xi18n i18n_core = ims->protocol;
1099 IMSyncXlibStruct *sync_xlib;
1100
1101 extern XimFrameRec sync_fr[];
1102 FrameMgr fm;
1103 CARD16 connect_id = call_data->any.connect_id;
1104 int total_size;
1105 unsigned char *reply;
1106
1107 sync_xlib = (IMSyncXlibStruct *) &call_data->sync_xlib;
1108 fm = FrameMgrInit (sync_fr, NULL,
1109 _Xi18nNeedSwap (i18n_core, connect_id));
1110 total_size = FrameMgrGetTotalSize(fm);
1111 reply = (unsigned char *) malloc (total_size);
1112 if (!reply) {
1113 _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0);
1114 return False;
1115 }
1116 memset (reply, 0, total_size);
1117 FrameMgrSetBuffer (fm, reply);
1118
1119 /* input input-method ID */
1120 FrameMgrPutToken (fm, connect_id);
1121 /* input input-context ID */
1122 FrameMgrPutToken (fm, sync_xlib->icid);
1123 _Xi18nSendMessage (ims, connect_id, XIM_SYNC, 0, reply, total_size);
1124
1125 FrameMgrFree (fm);
1126 XFree(reply);
1127 return True;
1128 }
1129
1130