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