#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "IntrinsicI.h"
#include <stdio.h>
#include <errno.h>
#ifdef __UNIXOS2__
#include <sys/time.h>
#endif
static TimerEventRec* freeTimerRecs;
static WorkProcRec* freeWorkRecs;
static SignalEventRec* freeSignalRecs;
#ifndef NEEDS_NTPD_FIXUP
# if defined(sun) || defined(MOTOROLA) || (defined(__osf__) && defined(__alpha))
# define NEEDS_NTPD_FIXUP 1
# else
# define NEEDS_NTPD_FIXUP 0
# endif
#endif
#if NEEDS_NTPD_FIXUP
#define FIXUP_TIMEVAL(t) { \
while ((t).tv_usec >= 1000000) { \
(t).tv_usec -= 1000000; \
(t).tv_sec++; \
} \
while ((t).tv_usec < 0) { \
if ((t).tv_sec > 0) { \
(t).tv_usec += 1000000; \
(t).tv_sec--; \
} else { \
(t).tv_usec = 0; \
break; \
} \
}}
#else
#define FIXUP_TIMEVAL(t)
#endif
#define ADD_TIME(dest, src1, src2) { \
if(((dest).tv_usec = (src1).tv_usec + (src2).tv_usec) >= 1000000) {\
(dest).tv_usec -= 1000000;\
(dest).tv_sec = (src1).tv_sec + (src2).tv_sec + 1 ; \
} else { (dest).tv_sec = (src1).tv_sec + (src2).tv_sec ; \
if(((dest).tv_sec >= 1) && (((dest).tv_usec <0))) { \
(dest).tv_sec --;(dest).tv_usec += 1000000; } } }
#define TIMEDELTA(dest, src1, src2) { \
if(((dest).tv_usec = (src1).tv_usec - (src2).tv_usec) < 0) {\
(dest).tv_usec += 1000000;\
(dest).tv_sec = (src1).tv_sec - (src2).tv_sec - 1;\
} else (dest).tv_sec = (src1).tv_sec - (src2).tv_sec; }
#define IS_AFTER(t1, t2) (((t2).tv_sec > (t1).tv_sec) \
|| (((t2).tv_sec == (t1).tv_sec)&& ((t2).tv_usec > (t1).tv_usec)))
#define IS_AT_OR_AFTER(t1, t2) (((t2).tv_sec > (t1).tv_sec) \
|| (((t2).tv_sec == (t1).tv_sec)&& ((t2).tv_usec >= (t1).tv_usec)))
#ifdef USE_POLL
#ifndef XT_DEFAULT_FDLIST_SIZE
#define XT_DEFAULT_FDLIST_SIZE 32
#endif
#endif
static void AdjustHowLong (
unsigned long *howlong,
struct timeval *start_time)
{
struct timeval new_time, time_spent, lstart_time;
lstart_time = *start_time;
X_GETTIMEOFDAY (&new_time);
FIXUP_TIMEVAL(new_time);
TIMEDELTA(time_spent, new_time, lstart_time);
if(*howlong <= (unsigned long)(time_spent.tv_sec*1000+time_spent.tv_usec/1000))
*howlong = (unsigned long)0;
else
*howlong -= (time_spent.tv_sec*1000+time_spent.tv_usec/1000);
}
typedef struct {
struct timeval cur_time;
struct timeval start_time;
struct timeval wait_time;
struct timeval new_time;
struct timeval time_spent;
struct timeval max_wait_time;
#ifndef USE_POLL
struct timeval *wait_time_ptr;
#else
int poll_wait;
#endif
} wait_times_t, *wait_times_ptr_t;
static struct timeval zero_time = { 0 , 0};
#ifndef USE_POLL
static fd_set zero_fd;
#else
#define X_BLOCK -1
#define X_DONT_BLOCK 0
#endif
static void InitTimes (
Boolean block,
unsigned long* howlong,
wait_times_ptr_t wt)
{
if (block) {
X_GETTIMEOFDAY (&wt->cur_time);
FIXUP_TIMEVAL(wt->cur_time);
wt->start_time = wt->cur_time;
if(howlong == NULL) {
#ifndef USE_POLL
wt->wait_time_ptr = NULL;
#else
wt->poll_wait = X_BLOCK;
#endif
} else {
wt->max_wait_time.tv_sec = *howlong/1000;
wt->max_wait_time.tv_usec = (*howlong %1000)*1000;
#ifndef USE_POLL
wt->wait_time_ptr = &wt->max_wait_time;
#else
wt->poll_wait = *howlong;
#endif
}
} else {
wt->max_wait_time = zero_time;
#ifndef USE_POLL
wt->wait_time_ptr = &wt->max_wait_time;
#else
wt->poll_wait = X_DONT_BLOCK;
#endif
}
}
typedef struct {
#ifndef USE_POLL
fd_set rmask, wmask, emask;
int nfds;
#else
struct pollfd* fdlist;
struct pollfd* stack;
int fdlistlen, num_dpys;
#endif
} wait_fds_t, *wait_fds_ptr_t;
static void InitFds (
XtAppContext app,
Boolean ignoreEvents,
Boolean ignoreInputs,
wait_fds_ptr_t wf)
{
int ii;
app->rebuild_fdlist = FALSE;
#ifndef USE_POLL
wf->nfds = app->fds.nfds;
if( !ignoreInputs ) {
wf->rmask = app->fds.rmask;
wf->wmask = app->fds.wmask;
wf->emask = app->fds.emask;
} else
wf->rmask = wf->wmask = wf->emask = zero_fd;
if (!ignoreEvents)
for (ii = 0; ii < app->count; ii++) {
FD_SET (ConnectionNumber(app->list[ii]), &wf->rmask);
}
#else
#ifndef POLLRDNORM
#define POLLRDNORM 0
#endif
#ifndef POLLRDBAND
#define POLLRDBAND 0
#endif
#ifndef POLLWRNORM
#define POLLWRNORM 0
#endif
#ifndef POLLWRBAND
#define POLLWRBAND 0
#endif
#define XPOLL_READ (POLLIN|POLLRDNORM|POLLPRI|POLLRDBAND)
#define XPOLL_WRITE (POLLOUT|POLLWRNORM|POLLWRBAND)
#define XPOLL_EXCEPT 0
if (!ignoreEvents)
wf->fdlistlen = wf->num_dpys = app->count;
else
wf->fdlistlen = wf->num_dpys = 0;
if (!ignoreInputs && app->input_list != NULL) {
int ii;
for (ii = 0; ii < (int) app->input_max; ii++)
if (app->input_list[ii] != NULL)
wf->fdlistlen++;
}
if (!wf->fdlist || wf->fdlist == wf->stack) {
wf->fdlist = (struct pollfd*)
XtStackAlloc (sizeof (struct pollfd) * wf->fdlistlen, wf->stack);
} else {
wf->fdlist = (struct pollfd*)
XtRealloc ((char*) wf->fdlist,
sizeof (struct pollfd) * wf->fdlistlen);
}
if (wf->fdlistlen) {
struct pollfd* fdlp = wf->fdlist;
InputEvent* iep;
if (!ignoreEvents)
for (ii = 0 ; ii < wf->num_dpys; ii++, fdlp++) {
fdlp->fd = ConnectionNumber (app->list[ii]);
fdlp->events = POLLIN;
}
if (!ignoreInputs && app->input_list != NULL)
for (ii = 0; ii < app->input_max; ii++)
if (app->input_list[ii] != NULL) {
iep = app->input_list[ii];
fdlp->fd = ii;
fdlp->events = 0;
for ( ; iep; iep = iep->ie_next) {
if (iep->ie_condition & XtInputReadMask)
fdlp->events |= XPOLL_READ;
if (iep->ie_condition & XtInputWriteMask)
fdlp->events |= XPOLL_WRITE;
if (iep->ie_condition & XtInputExceptMask)
fdlp->events |= XPOLL_EXCEPT;
}
fdlp++;
}
}
#endif
}
static void AdjustTimes (
XtAppContext app,
Boolean block,
unsigned long* howlong,
Boolean ignoreTimers,
wait_times_ptr_t wt)
{
if (app->timerQueue != NULL && !ignoreTimers && block) {
if (IS_AFTER (wt->cur_time, app->timerQueue->te_timer_value)) {
TIMEDELTA (wt->wait_time, app->timerQueue->te_timer_value, wt->cur_time);
if (howlong == NULL || IS_AFTER (wt->wait_time, wt->max_wait_time))
#ifndef USE_POLL
wt->wait_time_ptr = &wt->wait_time;
else
wt->wait_time_ptr = &wt->max_wait_time;
} else
wt->wait_time_ptr = &zero_time;
}
#else
wt->poll_wait = wt->wait_time.tv_sec * 1000 + wt->wait_time.tv_usec / 1000;
else
wt->poll_wait = wt->max_wait_time.tv_sec * 1000 + wt->max_wait_time.tv_usec / 1000;
} else
wt->poll_wait = X_DONT_BLOCK;
}
#endif
}
static int IoWait (
wait_times_ptr_t wt,
wait_fds_ptr_t wf)
{
#ifndef USE_POLL
return Select (wf->nfds, &wf->rmask, &wf->wmask, &wf->emask,
wt->wait_time_ptr);
#else
return poll (wf->fdlist, wf->fdlistlen, wt->poll_wait);
#endif
}
static void FindInputs (
XtAppContext app,
wait_fds_ptr_t wf,
int nfds,
Boolean ignoreEvents,
Boolean ignoreInputs,
int* dpy_no,
int* found_input)
{
XtInputMask condition;
InputEvent *ep;
int ii;
#ifndef USE_POLL
#ifdef XTHREADS
fd_set rmask;
#endif
int dd;
*dpy_no = -1;
*found_input = False;
#ifdef XTHREADS
rmask = app->fds.rmask;
for (dd = app->count; dd-- > 0; )
FD_SET (ConnectionNumber (app->list[dd]), &rmask);
#endif
for (ii = 0; ii < wf->nfds && nfds > 0; ii++) {
condition = 0;
if (FD_ISSET (ii, &wf->rmask)
#ifdef XTHREADS
&& FD_ISSET (ii, &rmask)
#endif
) {
nfds--;
if (!ignoreEvents) {
for (dd = 0; dd < app->count; dd++) {
if (ii == ConnectionNumber (app->list[dd])) {
if (*dpy_no == -1) {
if (XEventsQueued (app->list[dd], QueuedAfterReading ))
*dpy_no = dd;
}
goto ENDILOOP;
}
}
}
condition = XtInputReadMask;
}
if (FD_ISSET (ii, &wf->wmask)
#ifdef XTHREADS
&& FD_ISSET (ii, &app->fds.wmask)
#endif
) {
condition |= XtInputWriteMask;
nfds--;
}
if (FD_ISSET (ii, &wf->emask)
#ifdef XTHREADS
&& FD_ISSET (ii, &app->fds.emask)
#endif
) {
condition |= XtInputExceptMask;
nfds--;
}
if (condition) {
for (ep = app->input_list[ii]; ep; ep = ep->ie_next)
if (condition & ep->ie_condition) {
InputEvent *oq;
for (oq = app->outstandingQueue; oq; oq = oq->ie_oq)
if (oq == ep)
break;
if (!oq)
{
ep->ie_oq = app->outstandingQueue;
app->outstandingQueue = ep;
}
}
*found_input = True;
}
ENDILOOP: ;
}
#else
struct pollfd* fdlp;
*dpy_no = -1;
*found_input = False;
if (!ignoreEvents) {
fdlp = wf->fdlist;
for (ii = 0; ii < wf->num_dpys; ii++, fdlp++) {
if (*dpy_no == -1 && fdlp->revents & (POLLIN|POLLHUP|POLLERR) &&
#ifdef XTHREADS
!(fdlp->revents & POLLNVAL) &&
#endif
XEventsQueued (app->list[ii], QueuedAfterReading)) {
*dpy_no = ii;
break;
}
}
}
if (!ignoreInputs) {
fdlp = &wf->fdlist[wf->num_dpys];
for (ii = wf->num_dpys; ii < wf->fdlistlen; ii++, fdlp++) {
condition = 0;
if (fdlp->revents) {
if (fdlp->revents & (XPOLL_READ|POLLHUP|POLLERR)
#ifdef XTHREADS
&& !(fdlp->revents & POLLNVAL)
#endif
)
condition = XtInputReadMask;
if (fdlp->revents & XPOLL_WRITE)
condition |= XtInputWriteMask;
if (fdlp->revents & XPOLL_EXCEPT)
condition |= XtInputExceptMask;
}
if (condition) {
*found_input = True;
for (ep = app->input_list[fdlp->fd]; ep; ep = ep->ie_next)
if (condition & ep->ie_condition) {
InputEvent *oq;
for (oq = app->outstandingQueue; oq; oq = oq->ie_oq)
if (oq == ep)
break;
if (!oq)
{
ep->ie_oq = app->outstandingQueue;
app->outstandingQueue = ep;
}
}
}
}
}
#endif
}
int _XtWaitForSomething(
XtAppContext app,
_XtBoolean ignoreEvents,
_XtBoolean ignoreTimers,
_XtBoolean ignoreInputs,
_XtBoolean ignoreSignals,
_XtBoolean block,
#ifdef XTHREADS
_XtBoolean drop_lock,
#endif
unsigned long *howlong)
{
wait_times_t wt;
wait_fds_t wf;
int nfds, dpy_no, found_input, dd;
#ifdef XTHREADS
Boolean push_thread = TRUE;
Boolean pushed_thread = FALSE;
int level = 0;
#endif
#ifdef USE_POLL
struct pollfd fdlist[XT_DEFAULT_FDLIST_SIZE];
#endif
#ifdef XTHREADS
if (app->lock == (ThreadAppProc) NULL)
drop_lock = FALSE;
#endif
InitTimes (block, howlong, &wt);
#ifdef USE_POLL
wf.fdlist = NULL;
wf.stack = fdlist;
#endif
app->rebuild_fdlist = TRUE;
while (1) {
WaitLoop:
AdjustTimes (app, block, howlong, ignoreTimers, &wt);
if (block && app->block_hook_list) {
BlockHook hook;
for (hook = app->block_hook_list;
hook != NULL;
hook = hook->next)
(*hook->proc) (hook->closure);
if (!ignoreEvents)
for (dd = 0; dd < app->count; dd++)
if (XEventsQueued(app->list[dd], QueuedAlready)) {
#ifdef USE_POLL
XtStackFree ((XtPointer) wf.fdlist, fdlist);
#endif
return dd;
}
}
if (app->rebuild_fdlist)
InitFds (app, ignoreEvents, ignoreInputs, &wf);
#ifdef XTHREADS
if (drop_lock) {
YIELD_APP_LOCK(app, &push_thread, &pushed_thread, &level);
nfds = IoWait (&wt, &wf);
RESTORE_APP_LOCK(app, level, &pushed_thread);
} else
#endif
nfds = IoWait (&wt, &wf);
if (nfds == -1) {
if (errno == EINTR || errno == EAGAIN) {
if (errno == EAGAIN) {
errno = 0;
continue;
}
errno = 0;
if (!ignoreSignals && app->signalQueue != NULL) {
SignalEventRec *se_ptr = app->signalQueue;
while (se_ptr != NULL) {
if (se_ptr->se_notice) {
if (block && howlong != NULL)
AdjustHowLong (howlong, &wt.start_time);
#ifdef USE_POLL
XtStackFree ((XtPointer) wf.fdlist, fdlist);
#endif
return -1;
}
se_ptr = se_ptr->se_next;
}
}
if (!ignoreEvents)
for (dd = 0; dd < app->count; dd++)
if (XEventsQueued(app->list[dd], QueuedAfterReading)) {
#ifdef USE_POLL
XtStackFree ((XtPointer) wf.fdlist, fdlist);
#endif
return dd;
}
if (block) {
#ifndef USE_POLL
if (wt.wait_time_ptr == NULL)
#else
if (wt.poll_wait == X_BLOCK)
#endif
continue;
X_GETTIMEOFDAY (&wt.new_time);
FIXUP_TIMEVAL (wt.new_time);
TIMEDELTA (wt.time_spent, wt.new_time, wt.cur_time);
wt.cur_time = wt.new_time;
#ifndef USE_POLL
if (IS_AFTER (wt.time_spent, *wt.wait_time_ptr)) {
TIMEDELTA (wt.wait_time, *wt.wait_time_ptr, wt.time_spent);
wt.wait_time_ptr = &wt.wait_time;
continue;
} else
#else
if ((wt.time_spent.tv_sec * 1000 + wt.time_spent.tv_usec / 1000) < wt.poll_wait) {
wt.poll_wait -= (wt.time_spent.tv_sec * 1000 + wt.time_spent.tv_usec / 1000);
continue;
} else
#endif
nfds = 0;
}
} else {
char Errno[12];
String param = Errno;
Cardinal param_count = 1;
sprintf( Errno, "%d", errno);
XtAppWarningMsg(app, "communicationError","select",
XtCXtToolkitError,"Select failed; error code %s",
¶m, ¶m_count);
continue;
}
}
break;
}
if (nfds == 0) {
if (howlong)
*howlong = (unsigned long)0;
#ifdef USE_POLL
XtStackFree ((XtPointer) wf.fdlist, fdlist);
#endif
return -1;
}
if (block && howlong != NULL)
AdjustHowLong (howlong, &wt.start_time);
if (ignoreInputs && ignoreEvents) {
#ifdef USE_POLL
XtStackFree ((XtPointer) wf.fdlist, fdlist);
#endif
return -1;
} else
FindInputs (app, &wf, nfds,
ignoreEvents, ignoreInputs,
&dpy_no, &found_input);
if (dpy_no >= 0 || found_input) {
#ifdef USE_POLL
XtStackFree ((XtPointer) wf.fdlist, fdlist);
#endif
return dpy_no;
}
goto WaitLoop;
}
#define IeCallProc(ptr) \
(*ptr->ie_proc) (ptr->ie_closure, &ptr->ie_source, (XtInputId*)&ptr);
#define TeCallProc(ptr) \
(*ptr->te_proc) (ptr->te_closure, (XtIntervalId*)&ptr);
#define SeCallProc(ptr) \
(*ptr->se_proc) (ptr->se_closure, (XtSignalId*)&ptr);
XtIntervalId XtAddTimeOut(
unsigned long interval,
XtTimerCallbackProc proc,
XtPointer closure)
{
return XtAppAddTimeOut(_XtDefaultAppContext(),
interval, proc, closure);
}
static void QueueTimerEvent(
XtAppContext app,
TimerEventRec *ptr)
{
TimerEventRec *t,**tt;
tt = &app->timerQueue;
t = *tt;
while (t != NULL &&
IS_AFTER(t->te_timer_value, ptr->te_timer_value)) {
tt = &t->te_next;
t = *tt;
}
ptr->te_next = t;
*tt = ptr;
}
XtIntervalId XtAppAddTimeOut(
XtAppContext app,
unsigned long interval,
XtTimerCallbackProc proc,
XtPointer closure)
{
TimerEventRec *tptr;
struct timeval current_time;
LOCK_APP(app);
LOCK_PROCESS;
if (freeTimerRecs) {
tptr = freeTimerRecs;
freeTimerRecs = tptr->te_next;
}
else tptr = XtNew(TimerEventRec);
UNLOCK_PROCESS;
tptr->te_next = NULL;
tptr->te_closure = closure;
tptr->te_proc = proc;
tptr->app = app;
tptr->te_timer_value.tv_sec = interval/1000;
tptr->te_timer_value.tv_usec = (interval%1000)*1000;
X_GETTIMEOFDAY (¤t_time);
FIXUP_TIMEVAL(current_time);
ADD_TIME(tptr->te_timer_value,tptr->te_timer_value,current_time);
QueueTimerEvent(app, tptr);
UNLOCK_APP(app);
return( (XtIntervalId) tptr);
}
void XtRemoveTimeOut(
XtIntervalId id)
{
TimerEventRec *t, *last, *tid = (TimerEventRec *) id;
XtAppContext app = tid->app;
LOCK_APP(app);
for(t = app->timerQueue, last = NULL;
t != NULL && t != tid;
t = t->te_next) last = t;
if (t == NULL) {
UNLOCK_APP(app);
return;
}
if(last == NULL) {
app->timerQueue = t->te_next;
} else last->te_next = t->te_next;
LOCK_PROCESS;
t->te_next = freeTimerRecs;
freeTimerRecs = t;
UNLOCK_PROCESS;
UNLOCK_APP(app);
}
XtWorkProcId XtAddWorkProc(
XtWorkProc proc,
XtPointer closure)
{
return XtAppAddWorkProc(_XtDefaultAppContext(), proc, closure);
}
XtWorkProcId XtAppAddWorkProc(
XtAppContext app,
XtWorkProc proc,
XtPointer closure)
{
WorkProcRec *wptr;
LOCK_APP(app);
LOCK_PROCESS;
if (freeWorkRecs) {
wptr = freeWorkRecs;
freeWorkRecs = wptr->next;
} else wptr = XtNew(WorkProcRec);
UNLOCK_PROCESS;
wptr->next = app->workQueue;
wptr->closure = closure;
wptr->proc = proc;
wptr->app = app;
app->workQueue = wptr;
UNLOCK_APP(app);
return (XtWorkProcId) wptr;
}
void XtRemoveWorkProc(
XtWorkProcId id)
{
WorkProcRec *wid= (WorkProcRec *) id, *w, *last;
XtAppContext app = wid->app;
LOCK_APP(app);
for(w = app->workQueue, last = NULL;
w != NULL && w != wid; w = w->next) last = w;
if (w == NULL) {
UNLOCK_APP(app);
return;
}
if(last == NULL) app->workQueue = w->next;
else last->next = w->next;
LOCK_PROCESS;
w->next = freeWorkRecs;
freeWorkRecs = w;
UNLOCK_PROCESS;
UNLOCK_APP(app);
}
XtSignalId XtAddSignal(
XtSignalCallbackProc proc,
XtPointer closure)
{
return XtAppAddSignal(_XtDefaultAppContext(), proc, closure);
}
XtSignalId XtAppAddSignal(
XtAppContext app,
XtSignalCallbackProc proc,
XtPointer closure)
{
SignalEventRec *sptr;
LOCK_APP(app);
LOCK_PROCESS;
if (freeSignalRecs) {
sptr = freeSignalRecs;
freeSignalRecs = sptr->se_next;
} else
sptr = XtNew(SignalEventRec);
UNLOCK_PROCESS;
sptr->se_next = app->signalQueue;
sptr->se_closure = closure;
sptr->se_proc = proc;
sptr->app = app;
sptr->se_notice = FALSE;
app->signalQueue = sptr;
UNLOCK_APP(app);
return (XtSignalId) sptr;
}
void XtRemoveSignal(
XtSignalId id)
{
SignalEventRec *sid = (SignalEventRec*) id, *s, *last = NULL;
XtAppContext app = sid->app;
LOCK_APP(app);
for (s = app->signalQueue; s != NULL && s != sid; s = s->se_next)
last = s;
if (s == NULL) {
UNLOCK_APP(app);
return;
}
if (last == NULL)
app->signalQueue = s->se_next;
else
last->se_next = s->se_next;
LOCK_PROCESS;
s->se_next = freeSignalRecs;
freeSignalRecs = s;
UNLOCK_PROCESS;
UNLOCK_APP(app);
}
void XtNoticeSignal(
XtSignalId id)
{
SignalEventRec *sid = (SignalEventRec*) id;
sid->se_notice = TRUE;
}
XtInputId XtAddInput(
int source,
XtPointer Condition,
XtInputCallbackProc proc,
XtPointer closure)
{
return XtAppAddInput(_XtDefaultAppContext(),
source, Condition, proc, closure);
}
XtInputId XtAppAddInput(
XtAppContext app,
int source,
XtPointer Condition,
XtInputCallbackProc proc,
XtPointer closure)
{
InputEvent* sptr;
XtInputMask condition = (XtInputMask) Condition;
LOCK_APP(app);
if (!condition ||
condition & ~(XtInputReadMask|XtInputWriteMask|XtInputExceptMask))
XtAppErrorMsg(app,"invalidParameter","xtAddInput",XtCXtToolkitError,
"invalid condition passed to XtAppAddInput",
(String *)NULL, (Cardinal *)NULL);
if (app->input_max <= source) {
Cardinal n = source + 1;
int ii;
app->input_list = (InputEvent**)XtRealloc((char*) app->input_list,
n * sizeof(InputEvent*));
for (ii = app->input_max; ii < (int) n; ii++)
app->input_list[ii] = (InputEvent*) NULL;
app->input_max = n;
}
sptr = XtNew(InputEvent);
sptr->ie_proc = proc;
sptr->ie_closure = closure;
sptr->app = app;
sptr->ie_oq = NULL;
sptr->ie_source = source;
sptr->ie_condition = condition;
sptr->ie_next = app->input_list[source];
app->input_list[source] = sptr;
#ifndef USE_POLL
if (condition & XtInputReadMask) FD_SET(source, &app->fds.rmask);
if (condition & XtInputWriteMask) FD_SET(source, &app->fds.wmask);
if (condition & XtInputExceptMask) FD_SET(source, &app->fds.emask);
if (app->fds.nfds < (source+1)) app->fds.nfds = source+1;
#else
if (sptr->ie_next == NULL)
app->fds.nfds++;
#endif
app->input_count++;
app->rebuild_fdlist = TRUE;
UNLOCK_APP(app);
return((XtInputId)sptr);
}
void XtRemoveInput(
register XtInputId id)
{
register InputEvent *sptr, *lptr;
XtAppContext app = ((InputEvent *)id)->app;
register int source = ((InputEvent *)id)->ie_source;
Boolean found = False;
LOCK_APP(app);
sptr = app->outstandingQueue;
lptr = NULL;
for (; sptr != NULL; sptr = sptr->ie_oq) {
if (sptr == (InputEvent *)id) {
if (lptr == NULL) app->outstandingQueue = sptr->ie_oq;
else lptr->ie_oq = sptr->ie_oq;
}
lptr = sptr;
}
if(app->input_list && (sptr = app->input_list[source]) != NULL) {
for( lptr = NULL ; sptr; sptr = sptr->ie_next ){
if(sptr == (InputEvent *) id) {
#ifndef USE_POLL
XtInputMask condition = 0;
#endif
if(lptr == NULL) {
app->input_list[source] = sptr->ie_next;
} else {
lptr->ie_next = sptr->ie_next;
}
#ifndef USE_POLL
for (lptr = app->input_list[source];
lptr; lptr = lptr->ie_next)
condition |= lptr->ie_condition;
if ((sptr->ie_condition & XtInputReadMask) &&
!(condition & XtInputReadMask))
FD_CLR(source, &app->fds.rmask);
if ((sptr->ie_condition & XtInputWriteMask) &&
!(condition & XtInputWriteMask))
FD_CLR(source, &app->fds.wmask);
if ((sptr->ie_condition & XtInputExceptMask) &&
!(condition & XtInputExceptMask))
FD_CLR(source, &app->fds.emask);
#endif
XtFree((char *) sptr);
found = True;
break;
}
lptr = sptr;
}
}
if (found) {
app->input_count--;
#ifdef USE_POLL
if (app->input_list[source] == NULL)
app->fds.nfds--;
#endif
app->rebuild_fdlist = TRUE;
} else
XtAppWarningMsg(app, "invalidProcedure","inputHandler",
XtCXtToolkitError,
"XtRemoveInput: Input handler not found",
(String *)NULL, (Cardinal *)NULL);
UNLOCK_APP(app);
}
void _XtRemoveAllInputs(
XtAppContext app)
{
int i;
for (i = 0; i < app->input_max; i++) {
InputEvent* ep = app->input_list[i];
while (ep) {
InputEvent *next = ep->ie_next;
XtFree( (char*)ep );
ep = next;
}
}
XtFree((char *) app->input_list);
}
static void DoOtherSources(
XtAppContext app)
{
TimerEventRec *te_ptr;
InputEvent *ie_ptr;
struct timeval cur_time;
#define DrainQueue() \
for (ie_ptr = app->outstandingQueue; ie_ptr != NULL;) { \
app->outstandingQueue = ie_ptr->ie_oq; \
ie_ptr ->ie_oq = NULL; \
IeCallProc(ie_ptr); \
ie_ptr = app->outstandingQueue; \
}
DrainQueue();
if (app->input_count > 0) {
(void) _XtWaitForSomething (app,
TRUE, TRUE, FALSE, TRUE,
FALSE,
#ifdef XTHREADS
TRUE,
#endif
(unsigned long *)NULL);
DrainQueue();
}
if (app->timerQueue != NULL) {
X_GETTIMEOFDAY (&cur_time);
FIXUP_TIMEVAL(cur_time);
while(IS_AT_OR_AFTER (app->timerQueue->te_timer_value, cur_time)) {
te_ptr = app->timerQueue;
app->timerQueue = te_ptr->te_next;
te_ptr->te_next = NULL;
if (te_ptr->te_proc != NULL)
TeCallProc(te_ptr);
LOCK_PROCESS;
te_ptr->te_next = freeTimerRecs;
freeTimerRecs = te_ptr;
UNLOCK_PROCESS;
if (app->timerQueue == NULL) break;
}
}
if (app->signalQueue != NULL) {
SignalEventRec *se_ptr = app->signalQueue;
while (se_ptr != NULL) {
if (se_ptr->se_notice) {
se_ptr->se_notice = FALSE;
if (se_ptr->se_proc != NULL)
SeCallProc(se_ptr);
}
se_ptr = se_ptr->se_next;
}
}
#undef DrainQueue
}
static Boolean CallWorkProc(
XtAppContext app)
{
register WorkProcRec *w = app->workQueue;
Boolean delete;
if (w == NULL) return FALSE;
app->workQueue = w->next;
delete = (*(w->proc)) (w->closure);
if (delete) {
LOCK_PROCESS;
w->next = freeWorkRecs;
freeWorkRecs = w;
UNLOCK_PROCESS;
}
else {
w->next = app->workQueue;
app->workQueue = w;
}
return TRUE;
}
void XtNextEvent(
XEvent *event)
{
XtAppNextEvent(_XtDefaultAppContext(), event);
}
void _XtRefreshMapping(
XEvent* event,
_XtBoolean dispatch)
{
XtPerDisplay pd;
LOCK_PROCESS;
pd = _XtGetPerDisplay(event->xmapping.display);
if (event->xmapping.request != MappingPointer &&
pd && pd->keysyms && (event->xmapping.serial >= pd->keysyms_serial))
_XtBuildKeysymTables( event->xmapping.display, pd );
XRefreshKeyboardMapping(&event->xmapping);
if (dispatch && pd && pd->mapping_callbacks)
XtCallCallbackList((Widget) NULL,
(XtCallbackList)pd->mapping_callbacks,
(XtPointer)event );
UNLOCK_PROCESS;
}
void XtAppNextEvent(
XtAppContext app,
XEvent *event)
{
int i, d;
LOCK_APP(app);
for (;;) {
if (app->count == 0)
DoOtherSources(app);
else {
for (i = 1; i <= app->count; i++) {
d = (i + app->last) % app->count;
if (d == 0) DoOtherSources(app);
if (XEventsQueued(app->list[d], QueuedAfterReading))
goto GotEvent;
}
for (i = 1; i <= app->count; i++) {
d = (i + app->last) % app->count;
if (XEventsQueued(app->list[d], QueuedAfterFlush))
goto GotEvent;
}
}
if (CallWorkProc(app)) continue;
d = _XtWaitForSomething (app,
FALSE, FALSE, FALSE, FALSE,
TRUE,
#ifdef XTHREADS
TRUE,
#endif
(unsigned long *) NULL);
if (d != -1) {
GotEvent:
XNextEvent (app->list[d], event);
#ifdef XTHREADS
#endif
app->last = d;
if (event->xany.type == MappingNotify)
_XtRefreshMapping(event, False);
UNLOCK_APP(app);
return;
}
}
}
void XtProcessEvent(
XtInputMask mask)
{
XtAppProcessEvent(_XtDefaultAppContext(), mask);
}
void XtAppProcessEvent(
XtAppContext app,
XtInputMask mask)
{
int i, d;
XEvent event;
struct timeval cur_time;
LOCK_APP(app);
if (mask == 0) {
UNLOCK_APP(app);
return;
}
for (;;) {
if (mask & XtIMSignal && app->signalQueue != NULL) {
SignalEventRec *se_ptr = app->signalQueue;
while (se_ptr != NULL) {
if (se_ptr->se_notice) {
se_ptr->se_notice = FALSE;
SeCallProc(se_ptr);
UNLOCK_APP(app);
return;
}
se_ptr = se_ptr->se_next;
}
}
if (mask & XtIMTimer && app->timerQueue != NULL) {
X_GETTIMEOFDAY (&cur_time);
FIXUP_TIMEVAL(cur_time);
if (IS_AT_OR_AFTER(app->timerQueue->te_timer_value, cur_time)){
TimerEventRec *te_ptr = app->timerQueue;
app->timerQueue = app->timerQueue->te_next;
te_ptr->te_next = NULL;
if (te_ptr->te_proc != NULL)
TeCallProc(te_ptr);
LOCK_PROCESS;
te_ptr->te_next = freeTimerRecs;
freeTimerRecs = te_ptr;
UNLOCK_PROCESS;
UNLOCK_APP(app);
return;
}
}
if (mask & XtIMAlternateInput) {
if (app->input_count > 0 && app->outstandingQueue == NULL) {
(void) _XtWaitForSomething (app,
TRUE, TRUE, FALSE, TRUE,
FALSE,
#ifdef XTHREADS
TRUE,
#endif
(unsigned long *)NULL);
}
if (app->outstandingQueue != NULL) {
InputEvent *ie_ptr = app->outstandingQueue;
app->outstandingQueue = ie_ptr->ie_oq;
ie_ptr->ie_oq = NULL;
IeCallProc(ie_ptr);
UNLOCK_APP(app);
return;
}
}
if (mask & XtIMXEvent) {
for (i = 1; i <= app->count; i++) {
d = (i + app->last) % app->count;
if (XEventsQueued(app->list[d], QueuedAfterReading))
goto GotEvent;
}
for (i = 1; i <= app->count; i++) {
d = (i + app->last) % app->count;
if (XEventsQueued(app->list[d], QueuedAfterFlush))
goto GotEvent;
}
}
if (CallWorkProc(app)) continue;
d = _XtWaitForSomething (app,
(mask & XtIMXEvent ? FALSE : TRUE),
(mask & XtIMTimer ? FALSE : TRUE),
(mask & XtIMAlternateInput ? FALSE : TRUE),
(mask & XtIMSignal ? FALSE : TRUE),
TRUE,
#ifdef XTHREADS
TRUE,
#endif
(unsigned long *) NULL);
if (mask & XtIMXEvent && d != -1) {
GotEvent:
XNextEvent(app->list[d], &event);
#ifdef XTHREADS
#endif
app->last = d;
if (event.xany.type == MappingNotify) {
_XtRefreshMapping(&event, False);
}
XtDispatchEvent(&event);
UNLOCK_APP(app);
return;
}
}
}
Boolean XtPending(void)
{
return (XtAppPending(_XtDefaultAppContext()) != 0);
}
XtInputMask XtAppPending(
XtAppContext app)
{
struct timeval cur_time;
int d;
XtInputMask ret = 0;
LOCK_APP(app);
for (d = 0; d < app->count; d++) {
if (XEventsQueued(app->list[d], QueuedAfterReading)) {
ret = XtIMXEvent;
break;
}
}
if (ret == 0) {
for (d = 0; d < app->count; d++) {
if (XEventsQueued(app->list[d], QueuedAfterFlush)) {
ret = XtIMXEvent;
break;
}
}
}
if (app->signalQueue != NULL) {
SignalEventRec *se_ptr = app->signalQueue;
while (se_ptr != NULL) {
if (se_ptr->se_notice) {
ret |= XtIMSignal;
break;
}
se_ptr = se_ptr->se_next;
}
}
if (app->timerQueue != NULL) {
X_GETTIMEOFDAY (&cur_time);
FIXUP_TIMEVAL(cur_time);
if ((IS_AT_OR_AFTER(app->timerQueue->te_timer_value, cur_time)) &&
(app->timerQueue->te_proc != 0)) {
ret |= XtIMTimer;
}
}
if (app->outstandingQueue != NULL) ret |= XtIMAlternateInput;
else {
if(_XtWaitForSomething (app,
FALSE, TRUE, FALSE, TRUE,
FALSE,
#ifdef XTHREADS
TRUE,
#endif
(unsigned long *) NULL) != -1)
ret |= XtIMXEvent;
if (app->outstandingQueue != NULL) ret |= XtIMAlternateInput;
}
UNLOCK_APP(app);
return ret;
}
static Boolean PeekOtherSources(
XtAppContext app)
{
struct timeval cur_time;
if (app->outstandingQueue != NULL) return TRUE;
if (app->signalQueue != NULL) {
SignalEventRec *se_ptr = app->signalQueue;
while (se_ptr != NULL) {
if (se_ptr->se_notice)
return TRUE;
se_ptr = se_ptr->se_next;
}
}
if (app->input_count > 0) {
(void) _XtWaitForSomething (app,
TRUE, TRUE, FALSE, TRUE,
FALSE,
#ifdef XTHREADS
TRUE,
#endif
(unsigned long *)NULL);
if (app->outstandingQueue != NULL) return TRUE;
}
if (app->timerQueue != NULL) {
X_GETTIMEOFDAY (&cur_time);
FIXUP_TIMEVAL(cur_time);
if (IS_AT_OR_AFTER (app->timerQueue->te_timer_value, cur_time))
return TRUE;
}
return FALSE;
}
Boolean XtPeekEvent(
XEvent *event)
{
return XtAppPeekEvent(_XtDefaultAppContext(), event);
}
Boolean XtAppPeekEvent_SkipTimer;
Boolean XtAppPeekEvent(
XtAppContext app,
XEvent *event)
{
int i, d;
Boolean foundCall = FALSE;
LOCK_APP(app);
for (i = 1; i <= app->count; i++) {
d = (i + app->last) % app->count;
if (d == 0) foundCall = PeekOtherSources(app);
if (XEventsQueued(app->list[d], QueuedAfterReading))
goto GotEvent;
}
for (i = 1; i <= app->count; i++) {
d = (i + app->last) % app->count;
if (XEventsQueued(app->list[d], QueuedAfterFlush))
goto GotEvent;
}
if (foundCall) {
event->xany.type = 0;
event->xany.display = NULL;
event->xany.window = 0;
UNLOCK_APP(app);
return FALSE;
}
while (1) {
d = _XtWaitForSomething (app,
FALSE, FALSE, FALSE, FALSE,
TRUE,
#ifdef XTHREADS
TRUE,
#endif
(unsigned long *) NULL);
if (d != -1) {
GotEvent:
XPeekEvent(app->list[d], event);
app->last = (d == 0 ? app->count : d) - 1;
UNLOCK_APP(app);
return TRUE;
}
else {
if ((app->timerQueue != NULL) && ! XtAppPeekEvent_SkipTimer) {
struct timeval cur_time;
Bool did_timer = False;
X_GETTIMEOFDAY (&cur_time);
FIXUP_TIMEVAL(cur_time);
while (IS_AT_OR_AFTER(app->timerQueue->te_timer_value, cur_time)) {
TimerEventRec *te_ptr = app->timerQueue;
app->timerQueue = app->timerQueue->te_next;
te_ptr->te_next = NULL;
if (te_ptr->te_proc != NULL) {
TeCallProc(te_ptr);
did_timer = True;
}
LOCK_PROCESS;
te_ptr->te_next = freeTimerRecs;
freeTimerRecs = te_ptr;
UNLOCK_PROCESS;
if (app->timerQueue == NULL) break;
}
if (did_timer)
{
for (d = 0; d < app->count; d++)
if (XEventsQueued(app->list[d], QueuedAfterFlush)) {
goto GotEvent;
}
continue;
}
}
#if 0
if (app->signalQueue != NULL) {
event->xany.type = 0;
event->xany.display = NULL;
event->xany.window = 0;
UNLOCK_APP(app);
return FALSE;
}
else
#endif
{
event->xany.type = 0;
event->xany.display = NULL;
event->xany.window = 0;
UNLOCK_APP(app);
return FALSE;
}
}
}
}