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