1/******************************************************************
2
3           Copyright 1992, 1993, 1994 by FUJITSU LIMITED
4
5Permission to use, copy, modify, distribute, and sell this software
6and its documentation for any purpose is hereby granted without fee,
7provided that the above copyright notice appear in all copies and
8that both that copyright notice and this permission notice appear
9in supporting documentation, and that the name of FUJITSU LIMITED
10not be used in advertising or publicity pertaining to distribution
11of the software without specific, written prior permission.
12FUJITSU LIMITED makes no representations about the suitability of
13this software for any purpose.
14It is provided "as is" without express or implied warranty.
15
16FUJITSU LIMITED DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18EVENT SHALL FUJITSU LIMITED BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
20USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22PERFORMANCE 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
40static Xim 		*_XimCurrentIMlist  = (Xim *)NULL;
41static int		 _XimCurrentIMcount = 0;
42
43static Bool
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
75void
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
89void
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
123void
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
150static const char *
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
166static char *
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
196XIM
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
237Error4 :
238    _XimImSportRec[i].im_free(im);
239    Xfree(im);
240    return NULL;
241Error3 :
242    Xfree(im->core.im_name);
243Error2:
244    Xfree(im->core.res_class);
245Error1:
246    Xfree(im->core.res_name);
247    Xfree(im);
248    return NULL;
249}
250
251Bool
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