XEWrappers.c revision 966bf024
1/* $XFree86$ */
2/*****************************************************************************
3Copyright 1987, 1988, 1989, 1990, 1991, 1994 by Digital Equipment Corp.,
4Maynard, MA
5X11R6 Changes Copyright (c) 1994 by Robert Chesler of Absol-Puter, Hudson, NH.
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the name of Digital not be
12used in advertising or publicity pertaining to distribution of the
13software without specific, written prior permission.
14
15DIGITAL AND ABSOL-PUTER DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
16SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL DIGITAL OR ABSOL-PUTER BE LIABLE FOR ANY
18SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
19RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
20CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23*****************************************************************************/
24#include <stdio.h>
25#include <X11/extensions/xtraplib.h>
26#include <X11/extensions/xtraplibp.h>
27#ifdef vms
28#define IS_AT_OR_AFTER(t1, t2) (((t2).high > (t1).high) \
29        || (((t2).high == (t1).high)&& ((t2).low >= (t1).low)))
30typedef struct _vms_time {
31     unsigned long low;
32     unsigned long high;
33}vms_time;                                      /* from IntrinsicP.h */
34#ifdef VMSDW_V3
35typedef struct _ModToKeysymTable {
36    Modifiers mask;
37    int count;
38    int index;
39} ModToKeysymTable;                             /* from TranslateI.h */
40typedef struct _ConverterRec **ConverterTable;  /* from ConvertI.h */
41#include "libdef.h"
42typedef struct _CallbackRec *CallbackList;      /* from CallbackI.h */
43typedef struct _XtGrabRec  *XtGrabList;         /* from EventI.h */
44#include <X11/PassivGraI.h>
45#include <X11/InitialI.h>
46#else  /* VMSDW_V3 */
47typedef struct _ModToKeysymTable {
48    Modifiers mask;
49    int count;
50    int index;
51} ModToKeysymTable;                             /* from TranslateI.h */
52typedef struct _ConverterRec **ConverterTable;  /* from ConvertI.h */
53#include "libdef.h"
54#define NFDBITS	(sizeof(fd_mask) * 8)
55typedef long  fd_mask;
56#ifndef howmany
57#define	howmany(x, y)	(((x)+((y)-1))/(y))
58#endif /* howmany */
59typedef	struct Fd_set {
60	fd_mask	fds_bits[howmany(256, NFDBITS)];
61} Fd_set;                                       /* from fd.h */
62#include <X11/InitializeI.h>
63#endif  /* VMSDW_V3 */
64#else  /* !vms */
65#include <X11/IntrinsicI.h>
66#define IS_AT_OR_AFTER(t1, t2) (((t2).tv_sec > (t1).tv_sec) \
67        || (((t2).tv_sec == (t1).tv_sec)&& ((t2).tv_usec >= (t1).tv_usec)))
68#endif /* vms */
69
70/* The following has been lifted from NextEvent.c  in X11R4 */
71
72#ifndef NEEDS_NTPD_FIXUP
73# ifdef sun
74#  define NEEDS_NTPD_FIXUP 1
75# else
76#  define NEEDS_NTPD_FIXUP 0
77# endif
78#endif
79
80#if NEEDS_NTPD_FIXUP
81#define FIXUP_TIMEVAL(t) { \
82        while ((t).tv_usec >= 1000000) { \
83            (t).tv_usec -= 1000000; \
84            (t).tv_sec++; \
85        } \
86        while ((t).tv_usec < 0) { \
87            if ((t).tv_sec > 0) { \
88                (t).tv_usec += 1000000; \
89                (t).tv_sec--; \
90            } else { \
91                (t).tv_usec = 0; \
92                break; \
93            } \
94        }}
95#else
96#define FIXUP_TIMEVAL(t)
97#endif /*NEEDS_NTPD_FIXUP*/
98
99
100/* The following code is required for the use of the XLIB transport of XTrap
101 * events. This is in line with what MIT wants to see proper extension
102 * implementations do, as compared to using one of the core input event masks.
103 */
104
105Boolean (*XETrapGetEventHandler(XETC *tc, CARD32 id))(XETrapDataEvent *event, XETC *tc)
106{
107    return((id < XETrapNumberEvents) ? tc->eventFunc[id] : NULL);
108}
109
110Boolean (*XETrapSetEventHandler(XETC *tc, CARD32 id,
111			Boolean (*pfunc)(XETrapDataEvent *event, XETC *tc)))(XETrapDataEvent *event, XETC *tc)
112{
113    register Boolean (*rfunc)(XETrapDataEvent *event, XETC *tc) = NULL;
114
115    if (id < XETrapNumberEvents)
116    {
117        rfunc = XETrapGetEventHandler(tc,id);
118        tc->eventFunc[id] = pfunc;
119    }
120    return(rfunc);
121}
122
123Boolean XETrapDispatchEvent(XEvent *pevent, XETC *tc)
124{
125    Boolean status = False;
126    register CARD32 id = pevent->type;
127    register CARD32 firstEvent = tc->eventBase;
128    register CARD32 lastEvent  = tc->eventBase + XETrapNumberEvents - 1L;
129
130    /* If it is our extension event, handle it specially, otherwise, pass
131     * it off to Xt.
132     */
133    if (firstEvent != 0 && id >= firstEvent && id <= lastEvent)
134    {
135        /* We may be ignoring the event */
136        if (tc->eventFunc[id - firstEvent] != NULL)
137        {
138            status = (*tc->eventFunc[id - firstEvent])((XETrapDataEvent*)pevent,tc);
139        }
140    }
141    else
142    {
143        status = XtDispatchEvent(pevent);
144    }
145    return(status);
146}
147
148XtInputMask XETrapAppPending(XtAppContext app)
149{
150    TimerEventRec *te_ptr;
151#ifndef VMS
152    struct timeval cur_time;
153#else  /* vms */
154    vms_time cur_time;
155    long efnMask = 0L;
156    int status;
157#endif /* vms */
158    XtInputMask retmask = XtAppPending(app);        /* Prime XtIMEvent */
159
160    retmask &= ~(XtIMTimer | XtIMAlternateInput);   /* clear timer & input */
161    /* Now test for timer */
162    te_ptr = app->timerQueue;
163    while (te_ptr != NULL)
164    {
165#ifndef vms
166        (void)gettimeofday(&cur_time, NULL);
167        FIXUP_TIMEVAL(cur_time);
168#else
169        sys$gettim(&cur_time);
170#endif /* vms */
171        if (IS_AT_OR_AFTER(te_ptr->te_timer_value, cur_time))
172        {   /* this timer is due to fire */
173            retmask |= XtIMTimer;
174            break;
175        }
176        te_ptr = te_ptr->te_next;
177    }
178
179    /* Now test for alternate input */
180#ifndef vms
181    if (app->outstandingQueue != NULL)
182    {
183        retmask |= XtIMAlternateInput;
184    }
185#else /* vms */
186    if ((app->Input_EF_Mask != 0L) && ((status=SYS$READEF(1,&efnMask)) == 1))
187    {   /* we have input configured & retrieved the efn cluster 0 */
188        efnMask &= app->Input_EF_Mask;  /* mask out non-input */
189        if (efnMask)                    /* any left? */
190        {                               /* yes, an alt-input efn is set */
191            retmask |= XtIMAlternateInput;
192        }
193    }
194#endif  /* vms */
195    return(retmask);
196}
197
198void XETrapAppMainLoop(XtAppContext app, XETC *tc)
199{
200    XEvent event;
201    XtInputMask imask;
202
203    while (1)
204    {
205        imask = XETrapAppPending(app);
206        /* Check to see what's going on so that we don't block
207         * in either NextEvent or ProcessEvent since neither
208         * of these routines can correctly deal with XTrap Events
209         */
210        if (imask & XtIMXEvent)
211        {
212            (void)XtAppNextEvent(app,&event);
213            (void)XETrapDispatchEvent(&event,tc);
214        }
215        else if (imask & (XtIMTimer | XtIMAlternateInput))
216        {
217            XtAppProcessEvent(app, (XtIMTimer | XtIMAlternateInput));
218        }
219        else
220        {   /* Nothing going on, so we need to block */
221            (void)XETrapWaitForSomething(app);
222        }
223    }
224}
225
226int XETrapAppWhileLoop(XtAppContext app, XETC *tc, Bool *done)
227{
228    XEvent event;
229    XtInputMask imask;
230    int status = True;
231
232    if(done)
233    {
234        while (!(*done))
235        {
236            imask = XETrapAppPending(app);
237            /* Check to see what's going on so that we don't block
238             * in either NextEvent or ProcessEvent since neither
239             * of these routines can correctly deal with XTrap Events
240             */
241            if (imask & XtIMXEvent)
242            {
243                (void)XtAppNextEvent(app, &event);
244                (void)XETrapDispatchEvent(&event,tc);
245            }
246            else if (imask & (XtIMTimer | XtIMAlternateInput))
247            {
248                XtAppProcessEvent(app, (XtIMTimer | XtIMAlternateInput));
249            }
250            else
251            {   /* Nothing going on, so we need to block */
252                (void)XETrapWaitForSomething(app);
253            }
254        }
255    }
256    else
257    {
258        status = False;
259    }
260    return(status);
261}
262
263/* Wait for either Timer, Alternate Input, or an X Event to arrive */
264int XETrapWaitForSomething(XtAppContext app)
265{
266#ifndef vms
267    return(_XtWaitForSomething(app, FALSE, FALSE, FALSE, FALSE, TRUE
268#ifdef XTHREADS
269    , FALSE
270#endif /* XTHREADS */
271    , 0L));
272#else   /* vms */
273#define IS_AFTER(t1,t2) (((t2).high > (t1).high) \
274       ||(((t2).high == (t1).high)&& ((t2).low > (t1).low)))
275    long retval = 0L;
276    TimerEventRec *te_ptr;
277    vms_time cur_time,result_time;
278    int status = 0;
279    long quotient, remainder = 0;
280    int d;
281
282    if (app->timerQueue!= NULL)
283    {   /* check timeout queue */
284        cur_time.low = cur_time.high = result_time.low = result_time.high = 0;
285        te_ptr = app->timerQueue;
286        sys$gettim(&cur_time);
287        if ((IS_AFTER(app->timerQueue->te_timer_value, cur_time))  &&
288            (app->timerQueue->te_proc != 0))
289        {   /* it's fired! return! */
290            return(0);
291        }
292        /* Jump through hoops to get the time specified in the queue into
293         * milliseconds
294         */
295        status = lib$sub_times (&(te_ptr->te_timer_value.low), &cur_time,
296                                &result_time);
297        /*
298         * See if this timer has expired.  A timer is considered expired
299         * if it's value in the past (the NEGTIM case) or if there is
300         * less than one integral milli second before it would go off.
301         */
302
303        if (status == LIB$_NEGTIM ||
304            (result_time.high == -1 && result_time.low > -10000))
305        {   /* We've got a timer and it's ready to fire! */
306            return(0);
307        }
308        else if ((status & 1) == 1)
309        {
310            lib$ediv (&(10000), &result_time, &quotient, &remainder);
311            quotient *= -1;         /* flip the sign bit */
312
313            return(XMultiplexInput(app->count, &(app->list[0L]),
314                app->Input_EF_Mask, quotient, 0L, &retval));
315        }
316        else
317        {
318            status = -1;
319        }
320    }
321
322    return((status == -1 ? -1 : XMultiplexInput(app->count, &(app->list[0L]),
323           app->Input_EF_Mask, 0L, 0L, &retval)));
324#endif  /* vms */
325}
326