Tizen 2.1 base
[platform/core/uifw/ise-engine-sunpinyin.git] / wrapper / xim / IMdkit / i18nMethod.c
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
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
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
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
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
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
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
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 */
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
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
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
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
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
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
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
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
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
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
1018     _Xi18nSendMessage (ims,
1019                        call_data->connect_id,
1020                        XIM_COMMIT,
1021                        0,
1022                        reply,
1023                        total_size);
1024     FrameMgrFree (fm);
1025     XFree (reply);
1026
1027     return True;
1028 }
1029
1030 static int xi18n_callCallback (XIMS ims, XPointer xp)
1031 {
1032     IMProtocol *call_data = (IMProtocol *)xp;
1033     switch (call_data->major_code)
1034     {
1035     case XIM_GEOMETRY:
1036         return _Xi18nGeometryCallback (ims, call_data);
1037
1038     case XIM_PREEDIT_START:
1039         return _Xi18nPreeditStartCallback (ims, call_data);
1040
1041     case XIM_PREEDIT_DRAW:
1042         return _Xi18nPreeditDrawCallback (ims, call_data);
1043
1044     case XIM_PREEDIT_CARET:
1045         return _Xi18nPreeditCaretCallback (ims, call_data);
1046
1047     case XIM_PREEDIT_DONE:
1048         return _Xi18nPreeditDoneCallback (ims, call_data);
1049
1050     case XIM_STATUS_START:
1051         return _Xi18nStatusStartCallback (ims, call_data);
1052
1053     case XIM_STATUS_DRAW:
1054         return _Xi18nStatusDrawCallback (ims, call_data);
1055
1056     case XIM_STATUS_DONE:
1057         return _Xi18nStatusDoneCallback (ims, call_data);
1058
1059     case XIM_STR_CONVERSION:
1060         return _Xi18nStringConversionCallback (ims, call_data);
1061     }
1062     /*endswitch*/
1063     return False;
1064 }
1065
1066 /* preeditStart and preeditEnd are used only for Dynamic Event Flow. */
1067 static int xi18n_preeditStart (XIMS ims, XPointer xp)
1068 {
1069     IMProtocol *call_data = (IMProtocol *)xp;
1070     Xi18n i18n_core = ims->protocol;
1071     IMPreeditStateStruct *preedit_state =
1072         (IMPreeditStateStruct *) &call_data->preedit_state;
1073     long mask;
1074     int on_key_num = i18n_core->address.on_keys.count_keys;
1075     int off_key_num = i18n_core->address.off_keys.count_keys;
1076
1077     if (on_key_num == 0  &&  off_key_num == 0)
1078         return False;
1079     /*endif*/
1080     if (i18n_core->address.imvalue_mask & I18N_FILTERMASK)
1081         mask = i18n_core->address.filterevent_mask;
1082     else
1083         mask = DEFAULT_FILTER_MASK;
1084     /*endif*/
1085     _Xi18nSetEventMask (ims,
1086                         preedit_state->connect_id,
1087                         preedit_state->connect_id,
1088                         preedit_state->icid,
1089                         mask,
1090                         ~mask);
1091     return True;
1092 }
1093
1094 static int xi18n_preeditEnd (XIMS ims, XPointer xp)
1095 {
1096     IMProtocol *call_data = (IMProtocol *)xp;
1097     Xi18n i18n_core = ims->protocol;
1098     int on_key_num = i18n_core->address.on_keys.count_keys;
1099     int off_key_num = i18n_core->address.off_keys.count_keys;
1100     IMPreeditStateStruct *preedit_state;
1101
1102     preedit_state = (IMPreeditStateStruct *) &call_data->preedit_state;
1103
1104     if (on_key_num == 0  &&  off_key_num == 0)
1105         return False;
1106     /*endif*/
1107
1108     _Xi18nSetEventMask (ims,
1109                         preedit_state->connect_id,
1110                         preedit_state->connect_id,
1111                         preedit_state->icid,
1112                         0,
1113                         0);
1114     return True;
1115 }
1116
1117 static int xi18n_syncXlib (XIMS ims, XPointer xp)
1118 {
1119     IMProtocol *call_data = (IMProtocol *)xp;
1120     Xi18n i18n_core = ims->protocol;
1121     IMSyncXlibStruct *sync_xlib;
1122
1123     extern XimFrameRec sync_fr[];
1124     FrameMgr fm;
1125     CARD16 connect_id = call_data->any.connect_id;
1126     int total_size;
1127     unsigned char *reply;
1128
1129     sync_xlib = (IMSyncXlibStruct *) &call_data->sync_xlib;
1130     fm = FrameMgrInit (sync_fr, NULL,
1131                        _Xi18nNeedSwap (i18n_core, connect_id));
1132     total_size = FrameMgrGetTotalSize(fm);
1133     reply = (unsigned char *) malloc (total_size);
1134     if (!reply) {
1135         _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0);
1136         return False;
1137     }
1138     memset (reply, 0, total_size);
1139     FrameMgrSetBuffer (fm, reply);
1140
1141     /* input input-method ID */
1142     FrameMgrPutToken (fm, connect_id);
1143     /* input input-context ID */
1144     FrameMgrPutToken (fm, sync_xlib->icid);
1145     _Xi18nSendMessage (ims, connect_id, XIM_SYNC, 0, reply, total_size);
1146
1147     FrameMgrFree (fm);
1148     XFree(reply);
1149     return True;
1150 }
1151