1 /******************************************************************
2 
3            Copyright 1992, 1993, 1994 by FUJITSU LIMITED
4 
5 Permission to use, copy, modify, distribute, and sell this software
6 and its documentation for any purpose is hereby granted without fee,
7 provided that the above copyright notice appear in all copies and
8 that both that copyright notice and this permission notice appear
9 in supporting documentation, and that the name of FUJITSU LIMITED
10 not be used in advertising or publicity pertaining to distribution
11 of the software without specific, written prior permission.
12 FUJITSU LIMITED makes no representations about the suitability of
13 this software for any purpose.
14 It is provided "as is" without express or implied warranty.
15 
16 FUJITSU LIMITED DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 EVENT SHALL FUJITSU LIMITED BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
20 USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22 PERFORMANCE OF THIS SOFTWARE.
23 
24   Author: Takashi Fujiwara     FUJITSU LIMITED
25                                fujiwara@a80.tech.yk.fujitsu.co.jp
26 
27 ******************************************************************/
28 
29 #ifdef HAVE_CONFIG_H
30 #include <config.h>
31 #endif
32 #include <X11/Xatom.h>
33 #include <X11/Xlib.h>
34 #include <X11/Xmd.h>
35 #include "Xlibint.h"
36 #include "Xlcint.h"
37 #include "Ximint.h"
38 #include "XimImSw.h"
39 
40 static Xim 		*_XimCurrentIMlist  = (Xim *)NULL;
41 static int		 _XimCurrentIMcount = 0;
42 
43 static Bool
_XimSetIMStructureList(Xim im)44 _XimSetIMStructureList(
45     Xim		  im)
46 {
47     register int  i;
48     Xim		 *xim;
49 
50     if(!(_XimCurrentIMlist)) {
51 	if(!(_XimCurrentIMlist = Xmalloc(sizeof(Xim))))
52 	    return False;
53 	_XimCurrentIMlist[0] = im;
54 	_XimCurrentIMcount   = 1;
55     }
56     else {
57 	for(i = 0; i < _XimCurrentIMcount; i++) {
58 	    if(!( _XimCurrentIMlist[i])) {
59 		_XimCurrentIMlist[i] = im;
60 		break;
61 	    }
62 	}
63 	if(i >= _XimCurrentIMcount) {
64 	    if(!(xim = Xrealloc(_XimCurrentIMlist,
65 					 ((i + 1) * sizeof(Xim)))))
66 		return False;
67 	    _XimCurrentIMlist			  = xim;
68 	    _XimCurrentIMlist[_XimCurrentIMcount] = im;
69 	    _XimCurrentIMcount++;
70 	}
71     }
72     return True;
73 }
74 
75 void
_XimDestroyIMStructureList(Xim im)76 _XimDestroyIMStructureList(Xim im)
77 {
78     register int  i;
79 
80     for(i = 0; i < _XimCurrentIMcount; i++) {
81 	if(_XimCurrentIMlist[i] == im) {
82 	    _XimCurrentIMlist[i] = NULL;
83 	    break;
84 	}
85     }
86     return;
87 }
88 
89 void
_XimServerDestroy(Xim im_2_destroy)90 _XimServerDestroy(Xim im_2_destroy)
91 {
92     register int  i;
93     Xim		  im;
94     XIC		  ic;
95 
96     for(i = 0; i < _XimCurrentIMcount; i++) {
97 	if(!(im = _XimCurrentIMlist[i]))
98 	    continue;
99 	/*
100 	 * Only continue if this im is the one to be destroyed.
101 	 */
102 	if (im != im_2_destroy)
103 	    continue;
104 
105 	if (im->core.destroy_callback.callback)
106 	    (*im->core.destroy_callback.callback)((XIM)im,
107 			im->core.destroy_callback.client_data, NULL);
108 	for (ic = im->core.ic_chain; ic; ic = ic->core.next) {
109 	    if (ic->core.destroy_callback.callback) {
110 		(*ic->core.destroy_callback.callback)(ic,
111 			ic->core.destroy_callback.client_data, NULL);
112 	    }
113 	}
114 	_XimResetIMInstantiateCallback( im );
115 	(void)im->methods->close((XIM)im);
116 	Xfree(im);
117 	_XimCurrentIMlist[i] = NULL;
118 	return;
119     }
120 }
121 
122 #ifdef XIM_CONNECTABLE
123 void
_XimServerReconectableDestroy(void)124 _XimServerReconectableDestroy(void)
125 {
126     register int  i;
127     Xim		  im;
128     XIC		  ic;
129 
130     for(i = 0; i < _XimCurrentIMcount; i++) {
131 	if(!(im = _XimCurrentIMlist[i]))
132 	    continue;
133 
134 	if (im->core.destroy_callback.callback)
135 	    (*im->core.destroy_callback.callback)(im,
136 			im->core.destroy_callback.client_data, NULL);
137 	for (ic = im->core.ic_chain; ic; ic = ic->core.next) {
138 	    if (ic->core.destroy_callback.callback) {
139 		(*ic->core.destroy_callback.callback)(ic,
140 			ic->core.destroy_callback.client_data, NULL);
141 	    }
142 	}
143 	_XimResetIMInstantiateCallback( im );
144 	(void)im->methods->close((XIM)im);
145     }
146     return;
147 }
148 #endif /* XIM_CONNECTABLE */
149 
150 static const char *
_XimStrstr(register const char * src,register const char * dest)151 _XimStrstr(
152     register const char *src,
153     register const char *dest)
154 {
155     int			 len;
156 
157     len = strlen(dest);
158     while((src = strchr(src, *dest))) {
159 	if(!strncmp(src, dest, len))
160 	    return src;
161 	src++;
162     }
163     return NULL;
164 }
165 
166 static char *
_XimMakeImName(XLCd lcd)167 _XimMakeImName(
168     XLCd	   lcd)
169 {
170     const char* begin = NULL;
171     const char* end = NULL;
172     char* ret = NULL;
173     const char* ximmodifier = XIMMODIFIER;
174 
175     if(lcd->core->modifiers != NULL && *lcd->core->modifiers != '\0') {
176 	begin = _XimStrstr(lcd->core->modifiers, ximmodifier);
177 	if (begin != NULL) {
178 	    end = begin += strlen(ximmodifier);
179 	    while (*end && *end != '@')
180 		end++;
181 	}
182     }
183     ret = Xmalloc(end - begin + 1);
184     if (ret != NULL) {
185 	if (begin != NULL && end != NULL) {
186 	    (void)strncpy(ret, begin, end - begin);
187 	    ret[end - begin] = '\0';
188 	} else {
189 	    ret[0] = '\0';
190 	}
191     }
192 
193     return ret;
194 }
195 
196 XIM
_XimOpenIM(XLCd lcd,Display * dpy,XrmDatabase rdb,char * res_name,char * res_class)197 _XimOpenIM(
198     XLCd		 lcd,
199     Display		*dpy,
200     XrmDatabase		 rdb,
201     char		*res_name,
202     char		*res_class)
203 {
204     Xim			 im;
205     register int	 i;
206 
207     if (!(im = Xcalloc(1, sizeof(XimRec))))
208 	return (XIM)NULL;
209 
210     im->core.lcd       = lcd;
211     im->core.ic_chain  = (XIC)NULL;
212     im->core.display   = dpy;
213     im->core.rdb       = rdb;
214     im->core.res_name  = NULL;
215     im->core.res_class = NULL;
216     if((res_name != NULL) && (*res_name != '\0')){
217 	if(!(im->core.res_name  = strdup(res_name)))
218 	    goto Error1;
219     }
220     if((res_class != NULL) && (*res_class != '\0')){
221 	if(!(im->core.res_class = strdup(res_class)))
222 	    goto Error2;
223     }
224     if(!(im->core.im_name = _XimMakeImName(lcd)))
225 	goto Error3;
226 
227     for(i= 0; ; i++) {
228 	if(_XimImSportRec[i].checkprocessing(im)) {
229 	    if(!(_XimImSportRec[i].im_open(im)))
230 		goto Error4;
231 	    if(!_XimSetIMStructureList(im))
232 		goto Error4;
233 	    return (XIM)im;
234 	}
235     }
236 
237 Error4 :
238     _XimImSportRec[i].im_free(im);
239     Xfree(im);
240     return NULL;
241 Error3 :
242     Xfree(im->core.im_name);
243 Error2:
244     Xfree(im->core.res_class);
245 Error1:
246     Xfree(im->core.res_name);
247     Xfree(im);
248     return NULL;
249 }
250 
251 Bool
_XInitIM(XLCd lcd)252 _XInitIM(XLCd lcd)
253 {
254     if(lcd == (XLCd)NULL)
255 	return False;
256     lcd->methods->open_im = _XimOpenIM;
257     lcd->methods->register_callback = _XimRegisterIMInstantiateCallback;
258     lcd->methods->unregister_callback = _XimUnRegisterIMInstantiateCallback;
259     return True;
260 }
261