imTrans.c revision 1ab64890
1/* $Xorg: imTrans.c,v 1.3 2000/08/17 19:45:16 cpqbld Exp $ */
2/******************************************************************
3
4           Copyright 1992 by Sun Microsystems, Inc.
5           Copyright 1992, 1993, 1994 by FUJITSU LIMITED
6
7Permission to use, copy, modify, distribute, and sell this software
8and its documentation for any purpose is hereby granted without fee,
9provided that the above copyright notice appear in all copies and
10that both that copyright notice and this permission notice appear
11in supporting documentation, and that the name of Sun Microsystems, Inc.
12and FUJITSU LIMITED not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14Sun Microsystems, Inc. and FUJITSU LIMITED makes no representations about
15the suitability of this software for any purpose.
16It is provided "as is" without express or implied warranty.
17
18Sun Microsystems Inc. AND FUJITSU LIMITED DISCLAIMS ALL WARRANTIES WITH
19REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
20AND FITNESS, IN NO EVENT SHALL Sun Microsystems, Inc. AND FUJITSU LIMITED
21BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
23ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
24IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25
26  Author: Hideki Hiura (hhiura@Sun.COM) Sun Microsystems, Inc.
27          Takashi Fujiwara     FUJITSU LIMITED
28                               fujiwara@a80.tech.yk.fujitsu.co.jp
29
30******************************************************************/
31/* $XFree86: xc/lib/X11/imTrans.c,v 1.3 2003/04/17 02:06:32 dawes Exp $ */
32
33#ifdef HAVE_CONFIG_H
34#include <config.h>
35#endif
36#include <stdio.h>
37#include <X11/Xatom.h>
38#include <X11/Xmd.h>
39#define NEED_EVENTS
40#include "Xlibint.h"
41#include <X11/Xtrans/Xtrans.h>
42#include "Xlcint.h"
43#include "Ximint.h"
44#include "XimTrans.h"
45#include "XimTrInt.h"
46
47#ifdef WIN32
48#include <X11/Xwindows.h>
49#endif
50
51
52#ifndef XIM_CONNECTION_RETRIES
53#define XIM_CONNECTION_RETRIES 5
54#endif
55
56
57Private Bool
58_XimTransConnect(
59    Xim			 im)
60{
61    TransSpecRec	*spec = (TransSpecRec *)im->private.proto.spec;
62    int			connect_stat, retry;
63    Window		window;
64
65    for (retry = XIM_CONNECTION_RETRIES; retry >= 0; retry--)
66    {
67	if ((spec->trans_conn = _XimXTransOpenCOTSClient (
68	    spec->address)) == NULL)
69	{
70	    break;
71	}
72
73	if ((connect_stat = _XimXTransConnect (
74	    spec->trans_conn, spec->address)) < 0)
75	{
76	    _XimXTransClose (spec->trans_conn);
77	    spec->trans_conn = NULL;
78
79	    if (connect_stat == TRANS_TRY_CONNECT_AGAIN)
80	    {
81		sleep(1);
82		continue;
83	    }
84	    else
85		break;
86	}
87	else
88	    break;
89    }
90
91    if (spec->trans_conn == NULL)
92	return False;
93
94    spec->fd = _XimXTransGetConnectionNumber (spec->trans_conn);
95
96    if (!(window = XCreateSimpleWindow(im->core.display,
97		DefaultRootWindow(im->core.display), 0, 0, 1, 1, 1, 0, 0)))
98	return False;
99    spec->window = window;
100
101    _XRegisterFilterByType(im->core.display, window, KeyPress, KeyPress,
102				_XimTransFilterWaitEvent, (XPointer)im);
103
104    return _XRegisterInternalConnection(im->core.display, spec->fd,
105			(_XInternalConnectionProc)_XimTransInternalConnection,
106			(XPointer)im);
107}
108
109
110Private Bool
111_XimTransShutdown(
112    Xim im)
113{
114    TransSpecRec *spec = (TransSpecRec *)im->private.proto.spec;
115
116    _XimXTransDisconnect(spec->trans_conn);
117    (void)_XimXTransClose(spec->trans_conn);
118    _XimFreeTransIntrCallback(im);
119    _XUnregisterInternalConnection(im->core.display, spec->fd);
120    _XUnregisterFilter(im->core.display, spec->window,
121				_XimTransFilterWaitEvent, (XPointer)im);
122    XDestroyWindow(im->core.display, spec->window);
123    Xfree(spec->address);
124    Xfree(spec);
125    return True;
126}
127
128
129
130Public Bool
131_XimTransRegisterDispatcher(
132    Xim				 im,
133    Bool			 (*callback)(
134					     Xim, INT16, XPointer, XPointer
135					     ),
136    XPointer			 call_data)
137{
138    TransSpecRec		*spec = (TransSpecRec *)im->private.proto.spec;
139    TransIntrCallbackPtr	 rec;
140
141    if (!(rec = (TransIntrCallbackPtr)Xmalloc(sizeof(TransIntrCallbackRec))))
142        return False;
143
144    rec->func       = callback;
145    rec->call_data  = call_data;
146    rec->next       = spec->intr_cb;
147    spec->intr_cb   = rec;
148    return True;
149}
150
151
152Public void
153_XimFreeTransIntrCallback(
154    Xim				 im)
155{
156    TransSpecRec		*spec = (TransSpecRec *)im->private.proto.spec;
157    register TransIntrCallbackPtr	 rec, next;
158
159    for (rec = spec->intr_cb; rec;) {
160	next = rec->next;
161	Xfree(rec);
162	rec = next;
163    }
164    return;
165}
166
167
168Public Bool
169_XimTransCallDispatcher(Xim im, INT16 len, XPointer data)
170{
171    TransSpecRec		*spec = (TransSpecRec *)im->private.proto.spec;
172    TransIntrCallbackRec	*rec;
173
174    for (rec = spec->intr_cb; rec; rec = rec->next) {
175	if ((*rec->func)(im, len, data, rec->call_data))
176	    return True;
177    }
178    return False;
179}
180
181
182Public Bool
183_XimTransFilterWaitEvent(
184    Display		*d,
185    Window		 w,
186    XEvent		*ev,
187    XPointer		 arg)
188{
189    Xim			 im = (Xim)arg;
190    TransSpecRec	*spec = (TransSpecRec *)im->private.proto.spec;
191
192    spec->is_putback  = False;
193    return _XimFilterWaitEvent(im);
194}
195
196
197Public void
198_XimTransInternalConnection(
199    Display		*d,
200    int			 fd,
201    XPointer		 arg)
202{
203    Xim			 im = (Xim)arg;
204    XEvent		 ev;
205    XKeyEvent		*kev;
206    TransSpecRec	*spec = (TransSpecRec *)im->private.proto.spec;
207
208    if (spec->is_putback)
209	return;
210    kev = (XKeyEvent *)&ev;
211    kev->type = KeyPress;
212    kev->send_event = False;
213    kev->display = im->core.display;
214    kev->window = spec->window;
215    kev->keycode = 0;
216    XPutBackEvent(im->core.display, &ev);
217    XFlush(im->core.display);
218    spec->is_putback = True;
219    return;
220}
221
222
223Public Bool
224_XimTransWrite(Xim im, INT16 len, XPointer data)
225{
226    TransSpecRec	*spec	= (TransSpecRec *)im->private.proto.spec;
227    char		*buf = (char *)data;
228    register int	 nbyte;
229
230    while (len > 0) {
231	if ((nbyte = _XimXTransWrite(spec->trans_conn, buf, len)) <= 0)
232	    return False;
233	len -= nbyte;
234	buf += nbyte;
235    }
236    return True;
237}
238
239
240Public Bool
241_XimTransRead(
242    Xim			 im,
243    XPointer		 recv_buf,
244    int			 buf_len,
245    int			*ret_len)
246{
247    TransSpecRec	*spec = (TransSpecRec *)im->private.proto.spec;
248    int			 len;
249
250    if (buf_len == 0) {
251	*ret_len = 0;
252	return True;
253    }
254    if ((len = _XimXTransRead(spec->trans_conn, recv_buf, buf_len)) <= 0)
255	return False;
256    *ret_len = len;
257    return True;
258}
259
260
261Public void
262_XimTransFlush(
263    Xim		 im)
264{
265    return;
266}
267
268
269
270Public Bool
271_XimTransConf(
272    Xim		   	 im,
273    char	 	*address)
274{
275    char		*paddr;
276    TransSpecRec	*spec;
277
278    if (!(paddr = (char *)Xmalloc(strlen(address) + 1)))
279	return False;
280
281    if (!(spec = (TransSpecRec *) Xmalloc(sizeof(TransSpecRec)))) {
282	Xfree(paddr);
283	return False;
284    }
285
286    bzero(spec, sizeof(TransSpecRec));
287
288    (void)strcpy(paddr, address);
289    spec->address   = paddr;
290
291    im->private.proto.spec     = (XPointer)spec;
292    im->private.proto.connect  = _XimTransConnect;
293    im->private.proto.shutdown = _XimTransShutdown;
294    im->private.proto.write    = _XimTransWrite;
295    im->private.proto.read     = _XimTransRead;
296    im->private.proto.flush    = _XimTransFlush;
297    im->private.proto.register_dispatcher = _XimTransRegisterDispatcher;
298    im->private.proto.call_dispatcher = _XimTransCallDispatcher;
299
300    return True;
301}
302