1/*
2 * Copyright (c) 1992, Oracle and/or its affiliates.
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
75static 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
125static 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
145Bool
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 = 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
167void
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    spec->intr_cb = NULL;
180    return;
181}
182
183
184Bool
185_XimTransCallDispatcher(Xim im, INT16 len, XPointer data)
186{
187    TransSpecRec		*spec = (TransSpecRec *)im->private.proto.spec;
188    TransIntrCallbackRec	*rec;
189
190    for (rec = spec->intr_cb; rec; rec = rec->next) {
191	if ((*rec->func)(im, len, data, rec->call_data))
192	    return True;
193    }
194    return False;
195}
196
197
198Bool
199_XimTransFilterWaitEvent(
200    Display		*d,
201    Window		 w,
202    XEvent		*ev,
203    XPointer		 arg)
204{
205    Xim			 im = (Xim)arg;
206    TransSpecRec	*spec = (TransSpecRec *)im->private.proto.spec;
207
208    spec->is_putback  = False;
209    return _XimFilterWaitEvent(im);
210}
211
212
213void
214_XimTransInternalConnection(
215    Display		*d,
216    int			 fd,
217    XPointer		 arg)
218{
219    Xim			 im = (Xim)arg;
220    XEvent		 ev;
221    XKeyEvent		*kev;
222    TransSpecRec	*spec = (TransSpecRec *)im->private.proto.spec;
223
224    if (spec->is_putback)
225	return;
226
227    bzero(&ev, sizeof(ev));	/* FIXME: other fields may be accessed, too. */
228    kev = (XKeyEvent *)&ev;
229    kev->type = KeyPress;
230    kev->send_event = False;
231    kev->display = im->core.display;
232    kev->window = spec->window;
233    kev->keycode = 0;
234    kev->time = 0L;
235    kev->serial = LastKnownRequestProcessed(im->core.display);
236#if 0
237    fprintf(stderr,"%s,%d: putback FIXED kev->time=0 kev->serial=%lu\n", __FILE__, __LINE__, kev->serial);
238#endif
239
240    XPutBackEvent(im->core.display, &ev);
241    XFlush(im->core.display);
242    spec->is_putback = True;
243    return;
244}
245
246
247Bool
248_XimTransWrite(Xim im, INT16 len, XPointer data)
249{
250    TransSpecRec	*spec	= (TransSpecRec *)im->private.proto.spec;
251    char		*buf = (char *)data;
252    register int	 nbyte;
253
254    while (len > 0) {
255	if ((nbyte = _XimXTransWrite(spec->trans_conn, buf, len)) <= 0)
256	    return False;
257	len -= nbyte;
258	buf += nbyte;
259    }
260    return True;
261}
262
263
264Bool
265_XimTransRead(
266    Xim			 im,
267    XPointer		 recv_buf,
268    int			 buf_len,
269    int			*ret_len)
270{
271    TransSpecRec	*spec = (TransSpecRec *)im->private.proto.spec;
272    int			 len;
273
274    if (buf_len == 0) {
275	*ret_len = 0;
276	return True;
277    }
278    if ((len = _XimXTransRead(spec->trans_conn, recv_buf, buf_len)) <= 0)
279	return False;
280    *ret_len = len;
281    return True;
282}
283
284
285void
286_XimTransFlush(
287    Xim		 im)
288{
289    return;
290}
291
292
293
294Bool
295_XimTransConf(
296    Xim		   	 im,
297    char	 	*address)
298{
299    char		*paddr;
300    TransSpecRec	*spec;
301
302    if (!(paddr = strdup(address)))
303	return False;
304
305    if (!(spec = Xcalloc(1, sizeof(TransSpecRec)))) {
306	Xfree(paddr);
307	return False;
308    }
309
310    spec->address   = paddr;
311
312    im->private.proto.spec     = (XPointer)spec;
313    im->private.proto.connect  = _XimTransConnect;
314    im->private.proto.shutdown = _XimTransShutdown;
315    im->private.proto.write    = _XimTransWrite;
316    im->private.proto.read     = _XimTransRead;
317    im->private.proto.flush    = _XimTransFlush;
318    im->private.proto.register_dispatcher = _XimTransRegisterDispatcher;
319    im->private.proto.call_dispatcher = _XimTransCallDispatcher;
320
321    return True;
322}
323