1 /*
2 
3 Copyright 1985, 1986, 1987, 1998  The Open Group
4 
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
10 
11 The above copyright notice and this permission notice shall be included
12 in all copies or substantial portions of the Software.
13 
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 OTHER DEALINGS IN THE SOFTWARE.
21 
22 Except as contained in this notice, the name of The Open Group shall
23 not be used in advertising or otherwise to promote the sale, use or
24 other dealings in this Software without prior written authorization
25 from The Open Group.
26 
27 */
28 
29 /*
30  *	XlibInt.c - Internal support routines for the C subroutine
31  *	interface library (Xlib) to the X Window System Protocol V11.0.
32  */
33 
34 #ifdef WIN32
35 #define _XLIBINT_
36 #endif
37 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif
40 #include "Xlibint.h"
41 #include "Xprivate.h"
42 #include "reallocarray.h"
43 #include <X11/Xpoll.h>
44 #include <assert.h>
45 #include <stdio.h>
46 #ifdef WIN32
47 #include <direct.h>
48 #endif
49 
50 /* Needed for FIONREAD on Solaris */
51 #ifdef HAVE_SYS_FILIO_H
52 #include <sys/filio.h>
53 #endif
54 
55 /* Needed for FIONREAD on Cygwin */
56 #ifdef HAVE_SYS_SOCKET_H
57 #include <sys/socket.h>
58 #endif
59 
60 /* Needed for ioctl() on Solaris */
61 #ifdef HAVE_UNISTD_H
62 #include <unistd.h>
63 #endif
64 
65 #ifdef XTHREADS
66 #include "locking.h"
67 
68 #ifdef HAVE_SYS_IOCTL_H
69 #include <sys/ioctl.h>
70 #endif
71 
72 /* these pointers get initialized by XInitThreads */
73 LockInfoPtr _Xglobal_lock = NULL;
74 void (*_XCreateMutex_fn)(LockInfoPtr) = NULL;
75 /* struct _XCVList *(*_XCreateCVL_fn)() = NULL; */
76 void (*_XFreeMutex_fn)(LockInfoPtr) = NULL;
77 void (*_XLockMutex_fn)(
78     LockInfoPtr /* lock */
79 #if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
80     , char * /* file */
81     , int /* line */
82 #endif
83     ) = NULL;
84 void (*_XUnlockMutex_fn)(
85     LockInfoPtr /* lock */
86 #if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
87     , char * /* file */
88     , int /* line */
89 #endif
90     ) = NULL;
91 xthread_t (*_Xthread_self_fn)(void) = NULL;
92 
93 #define XThread_Self()	((*_Xthread_self_fn)())
94 
95 #endif /* XTHREADS */
96 
97 #ifdef WIN32
98 #define ECHECK(err) (WSAGetLastError() == err)
99 #define ESET(val) WSASetLastError(val)
100 #else
101 #ifdef __UNIXOS2__
102 #define ECHECK(err) (errno == err)
103 #define ESET(val)
104 #else
105 #define ECHECK(err) (errno == err)
106 #define ESET(val) errno = val
107 #endif
108 #endif
109 
110 #ifdef __UNIXOS2__
111 #include <limits.h>
112 #define MAX_PATH _POSIX_PATH_MAX
113 #endif
114 
115 /*
116  * The following routines are internal routines used by Xlib for protocol
117  * packet transmission and reception.
118  *
119  * _XIOError(Display *) will be called if any sort of system call error occurs.
120  * This is assumed to be a fatal condition, i.e., XIOError should not return.
121  *
122  * _XError(Display *, xError *) will be called whenever an X_Error event is
123  * received.  This is not assumed to be a fatal condition, i.e., it is
124  * acceptable for this procedure to return.  However, XError should NOT
125  * perform any operations (directly or indirectly) on the DISPLAY.
126  *
127  * Routines declared with a return type of 'Status' return 0 on failure,
128  * and non 0 on success.  Routines with no declared return type don't
129  * return anything.  Whenever possible routines that create objects return
130  * the object they have created.
131  */
132 
133 #define POLLFD_CACHE_SIZE 5
134 
135 /* initialize the struct array passed to poll() below */
_XPollfdCacheInit(Display * dpy)136 Bool _XPollfdCacheInit(
137     Display *dpy)
138 {
139 #ifdef USE_POLL
140     struct pollfd *pfp;
141 
142     pfp = Xmalloc(POLLFD_CACHE_SIZE * sizeof(struct pollfd));
143     if (!pfp)
144 	return False;
145     pfp[0].fd = dpy->fd;
146     pfp[0].events = POLLIN;
147 
148     dpy->filedes = (XPointer)pfp;
149 #endif
150     return True;
151 }
152 
_XPollfdCacheAdd(Display * dpy,int fd)153 void _XPollfdCacheAdd(
154     Display *dpy,
155     int fd)
156 {
157 #ifdef USE_POLL
158     struct pollfd *pfp = (struct pollfd *)dpy->filedes;
159 
160     if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) {
161 	pfp[dpy->im_fd_length].fd = fd;
162 	pfp[dpy->im_fd_length].events = POLLIN;
163     }
164 #endif
165 }
166 
167 /* ARGSUSED */
_XPollfdCacheDel(Display * dpy,int fd)168 void _XPollfdCacheDel(
169     Display *dpy,
170     int fd)			/* not used */
171 {
172 #ifdef USE_POLL
173     struct pollfd *pfp = (struct pollfd *)dpy->filedes;
174     struct _XConnectionInfo *conni;
175 
176     /* just recalculate whole list */
177     if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) {
178 	int loc = 1;
179 	for (conni = dpy->im_fd_info; conni; conni=conni->next) {
180 	    pfp[loc].fd = conni->fd;
181 	    pfp[loc].events = POLLIN;
182 	    loc++;
183 	}
184     }
185 #endif
186 }
187 
sync_hazard(Display * dpy)188 static int sync_hazard(Display *dpy)
189 {
190     /*
191      * "span" and "hazard" need to be signed such that the ">=" comparison
192      * works correctly in the case that hazard is greater than 65525
193      */
194     int64_t span = X_DPY_GET_REQUEST(dpy) - X_DPY_GET_LAST_REQUEST_READ(dpy);
195     int64_t hazard = min((dpy->bufmax - dpy->buffer) / SIZEOF(xReq), 65535 - 10);
196     return span >= 65535 - hazard - 10;
197 }
198 
199 static
sync_while_locked(Display * dpy)200 void sync_while_locked(Display *dpy)
201 {
202 #ifdef XTHREADS
203     if (dpy->lock)
204         (*dpy->lock->user_lock_display)(dpy);
205 #endif
206     UnlockDisplay(dpy);
207     SyncHandle();
208     InternalLockDisplay(dpy, /* don't skip user locks */ 0);
209 #ifdef XTHREADS
210     if (dpy->lock)
211         (*dpy->lock->user_unlock_display)(dpy);
212 #endif
213 }
214 
_XSeqSyncFunction(register Display * dpy)215 void _XSeqSyncFunction(
216     register Display *dpy)
217 {
218     xGetInputFocusReply rep;
219     _X_UNUSED register xReq *req;
220 
221     if ((X_DPY_GET_REQUEST(dpy) - X_DPY_GET_LAST_REQUEST_READ(dpy)) >= (65535 - BUFSIZE/SIZEOF(xReq))) {
222 	GetEmptyReq(GetInputFocus, req);
223 	(void) _XReply (dpy, (xReply *)&rep, 0, xTrue);
224 	sync_while_locked(dpy);
225     } else if (sync_hazard(dpy))
226 	_XSetPrivSyncFunction(dpy);
227 }
228 
229 /* NOTE: only called if !XTHREADS, or when XInitThreads wasn't called. */
230 static int
_XPrivSyncFunction(Display * dpy)231 _XPrivSyncFunction (Display *dpy)
232 {
233 #ifdef XTHREADS
234     assert(!dpy->lock_fns);
235 #endif
236     assert(dpy->synchandler == _XPrivSyncFunction);
237     assert((dpy->flags & XlibDisplayPrivSync) != 0);
238     dpy->synchandler = dpy->savedsynchandler;
239     dpy->savedsynchandler = NULL;
240     dpy->flags &= ~XlibDisplayPrivSync;
241     if(dpy->synchandler)
242         dpy->synchandler(dpy);
243     _XIDHandler(dpy);
244     _XSeqSyncFunction(dpy);
245     return 0;
246 }
247 
_XSetPrivSyncFunction(Display * dpy)248 void _XSetPrivSyncFunction(Display *dpy)
249 {
250 #ifdef XTHREADS
251     if (dpy->lock_fns)
252         return;
253 #endif
254     if (!(dpy->flags & XlibDisplayPrivSync)) {
255 	dpy->savedsynchandler = dpy->synchandler;
256 	dpy->synchandler = _XPrivSyncFunction;
257 	dpy->flags |= XlibDisplayPrivSync;
258     }
259 }
260 
_XSetSeqSyncFunction(Display * dpy)261 void _XSetSeqSyncFunction(Display *dpy)
262 {
263     if (sync_hazard(dpy))
264 	_XSetPrivSyncFunction (dpy);
265 }
266 
267 #ifdef LONG64
_XRead32(Display * dpy,long * data,long len)268 void _XRead32(
269     Display *dpy,
270     long *data,
271     long len)
272 {
273     register int *buf;
274     register long i;
275 
276     if (len) {
277 	(void) _XRead(dpy, (char *)data, len);
278 	i = len >> 2;
279 	buf = (int *)data + i;
280 	data += i;
281 	while (--i >= 0)
282 	    *--data = *--buf;
283     }
284 }
285 #endif /* LONG64 */
286 
287 
288 /*
289  * The hard part about this is that we only get 16 bits from a reply.
290  * We have three values that will march along, with the following invariant:
291  *	dpy->last_request_read <= rep->sequenceNumber <= dpy->request
292  * We have to keep
293  *	dpy->request - dpy->last_request_read < 2^16
294  * or else we won't know for sure what value to use in events.  We do this
295  * by forcing syncs when we get close.
296  */
297 
298 unsigned long
_XSetLastRequestRead(register Display * dpy,register xGenericReply * rep)299 _XSetLastRequestRead(
300     register Display *dpy,
301     register xGenericReply *rep)
302 {
303     register uint64_t	newseq, lastseq;
304 
305     lastseq = X_DPY_GET_LAST_REQUEST_READ(dpy);
306     /*
307      * KeymapNotify has no sequence number, but is always guaranteed
308      * to immediately follow another event, except when generated via
309      * SendEvent (hmmm).
310      */
311     if ((rep->type & 0x7f) == KeymapNotify)
312 	return(lastseq);
313 
314     newseq = (lastseq & ~((uint64_t)0xffff)) | rep->sequenceNumber;
315 
316     if (newseq < lastseq) {
317 	newseq += 0x10000;
318 	if (newseq > X_DPY_GET_REQUEST(dpy)) {
319 	    (void) fprintf (stderr,
320 	    "Xlib: sequence lost (0x%llx > 0x%llx) in reply type 0x%x!\n",
321 			    (unsigned long long)newseq,
322 			    (unsigned long long)(X_DPY_GET_REQUEST(dpy)),
323 			    (unsigned int) rep->type);
324 	    newseq -= 0x10000;
325 	}
326     }
327 
328     X_DPY_SET_LAST_REQUEST_READ(dpy, newseq);
329     return(newseq);
330 }
331 
332 /*
333  * Support for internal connections, such as an IM might use.
334  * By Stephen Gildea, X Consortium, September 1993
335  */
336 
337 /* _XRegisterInternalConnection
338  * Each IM (or Xlib extension) that opens a file descriptor that Xlib should
339  * include in its select/poll mask must call this function to register the
340  * fd with Xlib.  Any XConnectionWatchProc registered by XAddConnectionWatch
341  * will also be called.
342  *
343  * Whenever Xlib detects input available on fd, it will call callback
344  * with call_data to process it.  If non-Xlib code calls select/poll
345  * and detects input available, it must call XProcessInternalConnection,
346  * which will call the associated callback.
347  *
348  * Non-Xlib code can learn about these additional fds by calling
349  * XInternalConnectionNumbers or, more typically, by registering
350  * a XConnectionWatchProc with XAddConnectionWatch
351  * to be called when fds are registered or unregistered.
352  *
353  * Returns True if registration succeeded, False if not, typically
354  * because could not allocate memory.
355  * Assumes Display locked when called.
356  */
357 Status
_XRegisterInternalConnection(Display * dpy,int fd,_XInternalConnectionProc callback,XPointer call_data)358 _XRegisterInternalConnection(
359     Display* dpy,
360     int fd,
361     _XInternalConnectionProc callback,
362     XPointer call_data
363 )
364 {
365     struct _XConnectionInfo *new_conni, **iptr;
366     struct _XConnWatchInfo *watchers;
367     XPointer *wd;
368 
369     new_conni = Xmalloc(sizeof(struct _XConnectionInfo));
370     if (!new_conni)
371 	return 0;
372     new_conni->watch_data = Xmallocarray(dpy->watcher_count, sizeof(XPointer));
373     if (!new_conni->watch_data) {
374 	Xfree(new_conni);
375 	return 0;
376     }
377     new_conni->fd = fd;
378     new_conni->read_callback = callback;
379     new_conni->call_data = call_data;
380     new_conni->next = NULL;
381     /* link new structure onto end of list */
382     for (iptr = &dpy->im_fd_info; *iptr; iptr = &(*iptr)->next)
383 	;
384     *iptr = new_conni;
385     dpy->im_fd_length++;
386     _XPollfdCacheAdd(dpy, fd);
387 
388     for (watchers=dpy->conn_watchers, wd=new_conni->watch_data;
389 	 watchers;
390 	 watchers=watchers->next, wd++) {
391 	*wd = NULL;		/* for cleanliness */
392 	(*watchers->fn) (dpy, watchers->client_data, fd, True, wd);
393     }
394 
395     return 1;
396 }
397 
398 /* _XUnregisterInternalConnection
399  * Each IM (or Xlib extension) that closes a file descriptor previously
400  * registered with _XRegisterInternalConnection must call this function.
401  * Any XConnectionWatchProc registered by XAddConnectionWatch
402  * will also be called.
403  *
404  * Assumes Display locked when called.
405  */
406 void
_XUnregisterInternalConnection(Display * dpy,int fd)407 _XUnregisterInternalConnection(
408     Display* dpy,
409     int fd
410 )
411 {
412     struct _XConnectionInfo *info_list, **prev;
413     struct _XConnWatchInfo *watch;
414     XPointer *wd;
415 
416     for (prev = &dpy->im_fd_info; (info_list = *prev);
417 	 prev = &info_list->next) {
418 	if (info_list->fd == fd) {
419 	    *prev = info_list->next;
420 	    dpy->im_fd_length--;
421 	    for (watch=dpy->conn_watchers, wd=info_list->watch_data;
422 		 watch;
423 		 watch=watch->next, wd++) {
424 		(*watch->fn) (dpy, watch->client_data, fd, False, wd);
425 	    }
426 	    Xfree (info_list->watch_data);
427 	    Xfree (info_list);
428 	    break;
429 	}
430     }
431     _XPollfdCacheDel(dpy, fd);
432 }
433 
434 /* XInternalConnectionNumbers
435  * Returns an array of fds and an array of corresponding call data.
436  * Typically a XConnectionWatchProc registered with XAddConnectionWatch
437  * will be used instead of this function to discover
438  * additional fds to include in the select/poll mask.
439  *
440  * The list is allocated with Xmalloc and should be freed by the caller
441  * with Xfree;
442  */
443 Status
XInternalConnectionNumbers(Display * dpy,int ** fd_return,int * count_return)444 XInternalConnectionNumbers(
445     Display *dpy,
446     int **fd_return,
447     int *count_return
448 )
449 {
450     int count;
451     struct _XConnectionInfo *info_list;
452     int *fd_list;
453 
454     LockDisplay(dpy);
455     count = 0;
456     for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next)
457 	count++;
458     fd_list = Xmallocarray (count, sizeof(int));
459     if (!fd_list) {
460 	UnlockDisplay(dpy);
461 	return 0;
462     }
463     count = 0;
464     for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
465 	fd_list[count] = info_list->fd;
466 	count++;
467     }
468     UnlockDisplay(dpy);
469 
470     *fd_return = fd_list;
471     *count_return = count;
472     return 1;
473 }
474 
_XProcessInternalConnection(Display * dpy,struct _XConnectionInfo * conn_info)475 void _XProcessInternalConnection(
476     Display *dpy,
477     struct _XConnectionInfo *conn_info)
478 {
479     dpy->flags |= XlibDisplayProcConni;
480     UnlockDisplay(dpy);
481     (*conn_info->read_callback) (dpy, conn_info->fd, conn_info->call_data);
482     LockDisplay(dpy);
483     dpy->flags &= ~XlibDisplayProcConni;
484 }
485 
486 /* XProcessInternalConnection
487  * Call the _XInternalConnectionProc registered by _XRegisterInternalConnection
488  * for this fd.
489  * The Display is NOT locked during the call.
490  */
491 void
XProcessInternalConnection(Display * dpy,int fd)492 XProcessInternalConnection(
493     Display* dpy,
494     int fd
495 )
496 {
497     struct _XConnectionInfo *info_list;
498 
499     LockDisplay(dpy);
500     for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
501 	if (info_list->fd == fd) {
502 	    _XProcessInternalConnection(dpy, info_list);
503 	    break;
504 	}
505     }
506     UnlockDisplay(dpy);
507 }
508 
509 /* XAddConnectionWatch
510  * Register a callback to be called whenever _XRegisterInternalConnection
511  * or _XUnregisterInternalConnection is called.
512  * Callbacks are called with the Display locked.
513  * If any connections are already registered, the callback is immediately
514  * called for each of them.
515  */
516 Status
XAddConnectionWatch(Display * dpy,XConnectionWatchProc callback,XPointer client_data)517 XAddConnectionWatch(
518     Display* dpy,
519     XConnectionWatchProc callback,
520     XPointer client_data
521 )
522 {
523     struct _XConnWatchInfo *new_watcher, **wptr;
524     struct _XConnectionInfo *info_list;
525     XPointer *wd_array;
526 
527     LockDisplay(dpy);
528 
529     /* allocate new watch data */
530     for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
531 	wd_array = Xreallocarray(info_list->watch_data,
532                                  dpy->watcher_count + 1, sizeof(XPointer));
533 	if (!wd_array) {
534 	    UnlockDisplay(dpy);
535 	    return 0;
536 	}
537 	info_list->watch_data = wd_array;
538 	wd_array[dpy->watcher_count] = NULL;	/* for cleanliness */
539     }
540 
541     new_watcher = Xmalloc(sizeof(struct _XConnWatchInfo));
542     if (!new_watcher) {
543 	UnlockDisplay(dpy);
544 	return 0;
545     }
546     new_watcher->fn = callback;
547     new_watcher->client_data = client_data;
548     new_watcher->next = NULL;
549 
550     /* link new structure onto end of list */
551     for (wptr = &dpy->conn_watchers; *wptr; wptr = &(*wptr)->next)
552 	;
553     *wptr = new_watcher;
554     dpy->watcher_count++;
555 
556     /* call new watcher on all currently registered fds */
557     for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
558 	(*callback) (dpy, client_data, info_list->fd, True,
559 		     info_list->watch_data + dpy->watcher_count - 1);
560     }
561 
562     UnlockDisplay(dpy);
563     return 1;
564 }
565 
566 /* XRemoveConnectionWatch
567  * Unregister a callback registered by XAddConnectionWatch.
568  * Both callback and client_data must match what was passed to
569  * XAddConnectionWatch.
570  */
571 void
XRemoveConnectionWatch(Display * dpy,XConnectionWatchProc callback,XPointer client_data)572 XRemoveConnectionWatch(
573     Display* dpy,
574     XConnectionWatchProc callback,
575     XPointer client_data
576 )
577 {
578     struct _XConnWatchInfo *watch;
579     struct _XConnWatchInfo *previous = NULL;
580     struct _XConnectionInfo *conni;
581     int counter = 0;
582 
583     LockDisplay(dpy);
584     for (watch=dpy->conn_watchers; watch; watch=watch->next) {
585 	if (watch->fn == callback  &&  watch->client_data == client_data) {
586 	    if (previous)
587 		previous->next = watch->next;
588 	    else
589 		dpy->conn_watchers = watch->next;
590 	    Xfree (watch);
591 	    dpy->watcher_count--;
592 	    /* remove our watch_data for each connection */
593 	    for (conni=dpy->im_fd_info; conni; conni=conni->next) {
594 		/* don't bother realloc'ing; these arrays are small anyway */
595 		/* overlapping */
596 		memmove(conni->watch_data+counter,
597 			conni->watch_data+counter+1,
598 			dpy->watcher_count - counter);
599 	    }
600 	    break;
601 	}
602 	previous = watch;
603 	counter++;
604     }
605     UnlockDisplay(dpy);
606 }
607 
608 /* end of internal connections support */
609 
610 /* Cookie jar implementation
611    dpy->cookiejar is a linked list. _XEnq receives the events but leaves
612    them in the normal EQ. _XStoreEvent returns the cookie event (minus
613    data pointer) and adds it to the cookiejar. _XDeq just removes
614    the entry like any other event but resets the data pointer for
615    cookie events (to avoid double-free, the memory is re-used by Xlib).
616 
617    _XFetchEventCookie (called from XGetEventData) removes a cookie from the
618    jar. _XFreeEventCookies removes all unclaimed cookies from the jar
619    (called by XNextEvent).
620 
621    _XFreeDisplayStructure calls _XFreeEventCookies for each cookie in the
622    normal EQ.
623  */
624 
625 #include "utlist.h"
626 struct stored_event {
627     XGenericEventCookie ev;
628     struct stored_event *prev;
629     struct stored_event *next;
630 };
631 
632 Bool
_XIsEventCookie(Display * dpy,XEvent * ev)633 _XIsEventCookie(Display *dpy, XEvent *ev)
634 {
635     return (ev->xcookie.type == GenericEvent &&
636 	    dpy->generic_event_vec[ev->xcookie.extension & 0x7F] != NULL);
637 }
638 
639 /**
640  * Free all events in the event list.
641  */
642 void
_XFreeEventCookies(Display * dpy)643 _XFreeEventCookies(Display *dpy)
644 {
645     struct stored_event **head, *e, *tmp;
646 
647     if (!dpy->cookiejar)
648         return;
649 
650     head = (struct stored_event**)&dpy->cookiejar;
651 
652     DL_FOREACH_SAFE(*head, e, tmp) {
653         XFree(e->ev.data);
654         XFree(e);
655     }
656     dpy->cookiejar = NULL;
657 }
658 
659 /**
660  * Add an event to the display's event list. This event must be freed on the
661  * next call to XNextEvent().
662  */
663 void
_XStoreEventCookie(Display * dpy,XEvent * event)664 _XStoreEventCookie(Display *dpy, XEvent *event)
665 {
666     XGenericEventCookie* cookie = &event->xcookie;
667     struct stored_event **head, *add;
668 
669     if (!_XIsEventCookie(dpy, event))
670         return;
671 
672     head = (struct stored_event**)(&dpy->cookiejar);
673 
674     add = Xmalloc(sizeof(struct stored_event));
675     if (!add) {
676         ESET(ENOMEM);
677         _XIOError(dpy);
678         return;
679     }
680     add->ev = *cookie;
681     DL_APPEND(*head, add);
682     cookie->data = NULL; /* don't return data yet, must be claimed */
683 }
684 
685 /**
686  * Return the event with the given cookie and remove it from the list.
687  */
688 Bool
_XFetchEventCookie(Display * dpy,XGenericEventCookie * ev)689 _XFetchEventCookie(Display *dpy, XGenericEventCookie* ev)
690 {
691     Bool ret = False;
692     struct stored_event **head, *event;
693     head = (struct stored_event**)&dpy->cookiejar;
694 
695     if (!_XIsEventCookie(dpy, (XEvent*)ev))
696         return ret;
697 
698     DL_FOREACH(*head, event) {
699         if (event->ev.cookie == ev->cookie &&
700             event->ev.extension == ev->extension &&
701             event->ev.evtype == ev->evtype) {
702             *ev = event->ev;
703             DL_DELETE(*head, event);
704             Xfree(event);
705             ret = True;
706             break;
707         }
708     }
709 
710     return ret;
711 }
712 
713 Bool
_XCopyEventCookie(Display * dpy,XGenericEventCookie * in,XGenericEventCookie * out)714 _XCopyEventCookie(Display *dpy, XGenericEventCookie *in, XGenericEventCookie *out)
715 {
716     Bool ret = False;
717     int extension;
718 
719     if (!_XIsEventCookie(dpy, (XEvent*)in) || !out)
720         return ret;
721 
722     extension = in->extension & 0x7F;
723 
724     if (!dpy->generic_event_copy_vec[extension])
725         return ret;
726 
727     ret = ((*dpy->generic_event_copy_vec[extension])(dpy, in, out));
728     out->cookie = ret ? ++dpy->next_cookie  : 0;
729     return ret;
730 }
731 
732 
733 /*
734  * _XEnq - Place event packets on the display's queue.
735  * note that no squishing of move events in V11, since there
736  * is pointer motion hints....
737  */
_XEnq(register Display * dpy,register xEvent * event)738 void _XEnq(
739 	register Display *dpy,
740 	register xEvent *event)
741 {
742 	register _XQEvent *qelt;
743 	int type, extension;
744 
745 	if ((qelt = dpy->qfree)) {
746 		/* If dpy->qfree is non-NULL do this, else malloc a new one. */
747 		dpy->qfree = qelt->next;
748 	}
749 	else if ((qelt = Xmalloc(sizeof(_XQEvent))) == NULL) {
750 		/* Malloc call failed! */
751 		ESET(ENOMEM);
752 		_XIOError(dpy);
753 		return;
754 	}
755 	qelt->next = NULL;
756 
757 	type = event->u.u.type & 0177;
758 	extension = ((xGenericEvent*)event)->extension;
759 
760 	qelt->event.type = type;
761 	/* If an extension has registered a generic_event_vec handler, then
762 	 * it can handle event cookies. Otherwise, proceed with the normal
763 	 * event handlers.
764 	 *
765 	 * If the generic_event_vec is called, qelt->event is a event cookie
766 	 * with the data pointer and the "free" pointer set. Data pointer is
767 	 * some memory allocated by the extension.
768 	 */
769         if (type == GenericEvent && dpy->generic_event_vec[extension & 0x7F]) {
770 	    XGenericEventCookie *cookie = &qelt->event.xcookie;
771 	    (*dpy->generic_event_vec[extension & 0x7F])(dpy, cookie, event);
772 	    cookie->cookie = ++dpy->next_cookie;
773 
774 	    qelt->qserial_num = dpy->next_event_serial_num++;
775 	    if (dpy->tail)	dpy->tail->next = qelt;
776 	    else		dpy->head = qelt;
777 
778 	    dpy->tail = qelt;
779 	    dpy->qlen++;
780 	} else if ((*dpy->event_vec[type])(dpy, &qelt->event, event)) {
781 	    qelt->qserial_num = dpy->next_event_serial_num++;
782 	    if (dpy->tail)	dpy->tail->next = qelt;
783 	    else 		dpy->head = qelt;
784 
785 	    dpy->tail = qelt;
786 	    dpy->qlen++;
787 	} else {
788 	    /* ignored, or stashed away for many-to-one compression */
789 	    qelt->next = dpy->qfree;
790 	    dpy->qfree = qelt;
791 	}
792 }
793 
794 /*
795  * _XDeq - Remove event packet from the display's queue.
796  */
_XDeq(register Display * dpy,register _XQEvent * prev,register _XQEvent * qelt)797 void _XDeq(
798     register Display *dpy,
799     register _XQEvent *prev,	/* element before qelt */
800     register _XQEvent *qelt)	/* element to be unlinked */
801 {
802     if (prev) {
803 	if ((prev->next = qelt->next) == NULL)
804 	    dpy->tail = prev;
805     } else {
806 	/* no prev, so removing first elt */
807 	if ((dpy->head = qelt->next) == NULL)
808 	    dpy->tail = NULL;
809     }
810     qelt->qserial_num = 0;
811     qelt->next = dpy->qfree;
812     dpy->qfree = qelt;
813     dpy->qlen--;
814 
815     if (_XIsEventCookie(dpy, &qelt->event)) {
816 	XGenericEventCookie* cookie = &qelt->event.xcookie;
817 	/* dpy->qfree is re-used, reset memory to avoid double free on
818 	 * _XFreeDisplayStructure */
819 	cookie->data = NULL;
820     }
821 }
822 
823 /*
824  * EventToWire in separate file in that often not needed.
825  */
826 
827 /*ARGSUSED*/
828 Bool
_XUnknownWireEvent(register Display * dpy,register XEvent * re,register xEvent * event)829 _XUnknownWireEvent(
830     register Display *dpy,	/* pointer to display structure */
831     register XEvent *re,	/* pointer to where event should be reformatted */
832     register xEvent *event)	/* wire protocol event */
833 {
834 #ifdef notdef
835 	(void) fprintf(stderr,
836 	    "Xlib: unhandled wire event! event number = %d, display = %x\n.",
837 			event->u.u.type, dpy);
838 #endif
839 	return(False);
840 }
841 
842 Bool
_XUnknownWireEventCookie(Display * dpy,XGenericEventCookie * re,xEvent * event)843 _XUnknownWireEventCookie(
844     Display *dpy,	/* pointer to display structure */
845     XGenericEventCookie *re,	/* pointer to where event should be reformatted */
846     xEvent *event)	/* wire protocol event */
847 {
848 #ifdef notdef
849 	fprintf(stderr,
850 	    "Xlib: unhandled wire cookie event! extension number = %d, display = %x\n.",
851 			((xGenericEvent*)event)->extension, dpy);
852 #endif
853 	return(False);
854 }
855 
856 Bool
_XUnknownCopyEventCookie(Display * dpy,XGenericEventCookie * in,XGenericEventCookie * out)857 _XUnknownCopyEventCookie(
858     Display *dpy,	/* pointer to display structure */
859     XGenericEventCookie *in,	/* source */
860     XGenericEventCookie *out)	/* destination */
861 {
862 #ifdef notdef
863 	fprintf(stderr,
864 	    "Xlib: unhandled cookie event copy! extension number = %d, display = %x\n.",
865 			in->extension, dpy);
866 #endif
867 	return(False);
868 }
869 
870 /*ARGSUSED*/
871 Status
_XUnknownNativeEvent(register Display * dpy,register XEvent * re,register xEvent * event)872 _XUnknownNativeEvent(
873     register Display *dpy,	/* pointer to display structure */
874     register XEvent *re,	/* pointer to where event should be reformatted */
875     register xEvent *event)	/* wire protocol event */
876 {
877 #ifdef notdef
878 	(void) fprintf(stderr,
879  	   "Xlib: unhandled native event! event number = %d, display = %x\n.",
880 			re->type, dpy);
881 #endif
882 	return(0);
883 }
884 /*
885  * reformat a wire event into an XEvent structure of the right type.
886  */
887 Bool
_XWireToEvent(register Display * dpy,register XEvent * re,register xEvent * event)888 _XWireToEvent(
889     register Display *dpy,	/* pointer to display structure */
890     register XEvent *re,	/* pointer to where event should be reformatted */
891     register xEvent *event)	/* wire protocol event */
892 {
893 
894 	re->type = event->u.u.type & 0x7f;
895 	((XAnyEvent *)re)->serial = _XSetLastRequestRead(dpy,
896 					(xGenericReply *)event);
897 	((XAnyEvent *)re)->send_event = ((event->u.u.type & 0x80) != 0);
898 	((XAnyEvent *)re)->display = dpy;
899 
900 	/* Ignore the leading bit of the event type since it is set when a
901 		client sends an event rather than the server. */
902 
903 	switch (event-> u.u.type & 0177) {
904 	      case KeyPress:
905 	      case KeyRelease:
906 	        {
907 			register XKeyEvent *ev = (XKeyEvent*) re;
908 			ev->root 	= event->u.keyButtonPointer.root;
909 			ev->window 	= event->u.keyButtonPointer.event;
910 			ev->subwindow 	= event->u.keyButtonPointer.child;
911 			ev->time 	= event->u.keyButtonPointer.time;
912 			ev->x 		= cvtINT16toInt(event->u.keyButtonPointer.eventX);
913 			ev->y 		= cvtINT16toInt(event->u.keyButtonPointer.eventY);
914 			ev->x_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootX);
915 			ev->y_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootY);
916 			ev->state	= event->u.keyButtonPointer.state;
917 			ev->same_screen	= event->u.keyButtonPointer.sameScreen;
918 			ev->keycode 	= event->u.u.detail;
919 		}
920 	      	break;
921 	      case ButtonPress:
922 	      case ButtonRelease:
923 	        {
924 			register XButtonEvent *ev =  (XButtonEvent *) re;
925 			ev->root 	= event->u.keyButtonPointer.root;
926 			ev->window 	= event->u.keyButtonPointer.event;
927 			ev->subwindow 	= event->u.keyButtonPointer.child;
928 			ev->time 	= event->u.keyButtonPointer.time;
929 			ev->x 		= cvtINT16toInt(event->u.keyButtonPointer.eventX);
930 			ev->y 		= cvtINT16toInt(event->u.keyButtonPointer.eventY);
931 			ev->x_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootX);
932 			ev->y_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootY);
933 			ev->state	= event->u.keyButtonPointer.state;
934 			ev->same_screen	= event->u.keyButtonPointer.sameScreen;
935 			ev->button 	= event->u.u.detail;
936 		}
937 	        break;
938 	      case MotionNotify:
939 	        {
940 			register XMotionEvent *ev =   (XMotionEvent *)re;
941 			ev->root 	= event->u.keyButtonPointer.root;
942 			ev->window 	= event->u.keyButtonPointer.event;
943 			ev->subwindow 	= event->u.keyButtonPointer.child;
944 			ev->time 	= event->u.keyButtonPointer.time;
945 			ev->x 		= cvtINT16toInt(event->u.keyButtonPointer.eventX);
946 			ev->y 		= cvtINT16toInt(event->u.keyButtonPointer.eventY);
947 			ev->x_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootX);
948 			ev->y_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootY);
949 			ev->state	= event->u.keyButtonPointer.state;
950 			ev->same_screen	= event->u.keyButtonPointer.sameScreen;
951 			ev->is_hint 	= event->u.u.detail;
952 		}
953 	        break;
954 	      case EnterNotify:
955 	      case LeaveNotify:
956 		{
957 			register XCrossingEvent *ev   = (XCrossingEvent *) re;
958 			ev->root	= event->u.enterLeave.root;
959 			ev->window	= event->u.enterLeave.event;
960 			ev->subwindow	= event->u.enterLeave.child;
961 			ev->time	= event->u.enterLeave.time;
962 			ev->x		= cvtINT16toInt(event->u.enterLeave.eventX);
963 			ev->y		= cvtINT16toInt(event->u.enterLeave.eventY);
964 			ev->x_root	= cvtINT16toInt(event->u.enterLeave.rootX);
965 			ev->y_root	= cvtINT16toInt(event->u.enterLeave.rootY);
966 			ev->state	= event->u.enterLeave.state;
967 			ev->mode	= event->u.enterLeave.mode;
968 			ev->same_screen = (event->u.enterLeave.flags &
969 				ELFlagSameScreen) && True;
970 			ev->focus	= (event->u.enterLeave.flags &
971 			  	ELFlagFocus) && True;
972 			ev->detail	= event->u.u.detail;
973 		}
974 		  break;
975 	      case FocusIn:
976 	      case FocusOut:
977 		{
978 			register XFocusChangeEvent *ev = (XFocusChangeEvent *) re;
979 			ev->window 	= event->u.focus.window;
980 			ev->mode	= event->u.focus.mode;
981 			ev->detail	= event->u.u.detail;
982 		}
983 		  break;
984 	      case KeymapNotify:
985 		{
986 			register XKeymapEvent *ev = (XKeymapEvent *) re;
987 			ev->window	= None;
988 			memcpy(&ev->key_vector[1],
989 			       (char *)((xKeymapEvent *) event)->map,
990 			       sizeof (((xKeymapEvent *) event)->map));
991 		}
992 		break;
993 	      case Expose:
994 		{
995 			register XExposeEvent *ev = (XExposeEvent *) re;
996 			ev->window	= event->u.expose.window;
997 			ev->x		= event->u.expose.x;
998 			ev->y		= event->u.expose.y;
999 			ev->width	= event->u.expose.width;
1000 			ev->height	= event->u.expose.height;
1001 			ev->count	= event->u.expose.count;
1002 		}
1003 		break;
1004 	      case GraphicsExpose:
1005 		{
1006 		    register XGraphicsExposeEvent *ev =
1007 			(XGraphicsExposeEvent *) re;
1008 		    ev->drawable	= event->u.graphicsExposure.drawable;
1009 		    ev->x		= event->u.graphicsExposure.x;
1010 		    ev->y		= event->u.graphicsExposure.y;
1011 		    ev->width		= event->u.graphicsExposure.width;
1012 		    ev->height		= event->u.graphicsExposure.height;
1013 		    ev->count		= event->u.graphicsExposure.count;
1014 		    ev->major_code	= event->u.graphicsExposure.majorEvent;
1015 		    ev->minor_code	= event->u.graphicsExposure.minorEvent;
1016 		}
1017 		break;
1018 	      case NoExpose:
1019 		{
1020 		    register XNoExposeEvent *ev = (XNoExposeEvent *) re;
1021 		    ev->drawable	= event->u.noExposure.drawable;
1022 		    ev->major_code	= event->u.noExposure.majorEvent;
1023 		    ev->minor_code	= event->u.noExposure.minorEvent;
1024 		}
1025 		break;
1026 	      case VisibilityNotify:
1027 		{
1028 		    register XVisibilityEvent *ev = (XVisibilityEvent *) re;
1029 		    ev->window		= event->u.visibility.window;
1030 		    ev->state		= event->u.visibility.state;
1031 		}
1032 		break;
1033 	      case CreateNotify:
1034 		{
1035 		    register XCreateWindowEvent *ev =
1036 			 (XCreateWindowEvent *) re;
1037 		    ev->window		= event->u.createNotify.window;
1038 		    ev->parent		= event->u.createNotify.parent;
1039 		    ev->x		= cvtINT16toInt(event->u.createNotify.x);
1040 		    ev->y		= cvtINT16toInt(event->u.createNotify.y);
1041 		    ev->width		= event->u.createNotify.width;
1042 		    ev->height		= event->u.createNotify.height;
1043 		    ev->border_width	= event->u.createNotify.borderWidth;
1044 		    ev->override_redirect	= event->u.createNotify.override;
1045 		}
1046 		break;
1047 	      case DestroyNotify:
1048 		{
1049 		    register XDestroyWindowEvent *ev =
1050 				(XDestroyWindowEvent *) re;
1051 		    ev->window		= event->u.destroyNotify.window;
1052 		    ev->event		= event->u.destroyNotify.event;
1053 		}
1054 		break;
1055 	      case UnmapNotify:
1056 		{
1057 		    register XUnmapEvent *ev = (XUnmapEvent *) re;
1058 		    ev->window		= event->u.unmapNotify.window;
1059 		    ev->event		= event->u.unmapNotify.event;
1060 		    ev->from_configure	= event->u.unmapNotify.fromConfigure;
1061 		}
1062 		break;
1063 	      case MapNotify:
1064 		{
1065 		    register XMapEvent *ev = (XMapEvent *) re;
1066 		    ev->window		= event->u.mapNotify.window;
1067 		    ev->event		= event->u.mapNotify.event;
1068 		    ev->override_redirect	= event->u.mapNotify.override;
1069 		}
1070 		break;
1071 	      case MapRequest:
1072 		{
1073 		    register XMapRequestEvent *ev = (XMapRequestEvent *) re;
1074 		    ev->window		= event->u.mapRequest.window;
1075 		    ev->parent		= event->u.mapRequest.parent;
1076 		}
1077 		break;
1078 	      case ReparentNotify:
1079 		{
1080 		    register XReparentEvent *ev = (XReparentEvent *) re;
1081 		    ev->event		= event->u.reparent.event;
1082 		    ev->window		= event->u.reparent.window;
1083 		    ev->parent		= event->u.reparent.parent;
1084 		    ev->x		= cvtINT16toInt(event->u.reparent.x);
1085 		    ev->y		= cvtINT16toInt(event->u.reparent.y);
1086 		    ev->override_redirect	= event->u.reparent.override;
1087 		}
1088 		break;
1089 	      case ConfigureNotify:
1090 		{
1091 		    register XConfigureEvent *ev = (XConfigureEvent *) re;
1092 		    ev->event	= event->u.configureNotify.event;
1093 		    ev->window	= event->u.configureNotify.window;
1094 		    ev->above	= event->u.configureNotify.aboveSibling;
1095 		    ev->x	= cvtINT16toInt(event->u.configureNotify.x);
1096 		    ev->y	= cvtINT16toInt(event->u.configureNotify.y);
1097 		    ev->width	= event->u.configureNotify.width;
1098 		    ev->height	= event->u.configureNotify.height;
1099 		    ev->border_width  = event->u.configureNotify.borderWidth;
1100 		    ev->override_redirect = event->u.configureNotify.override;
1101 		}
1102 		break;
1103 	      case ConfigureRequest:
1104 		{
1105 		    register XConfigureRequestEvent *ev =
1106 		        (XConfigureRequestEvent *) re;
1107 		    ev->window		= event->u.configureRequest.window;
1108 		    ev->parent		= event->u.configureRequest.parent;
1109 		    ev->above		= event->u.configureRequest.sibling;
1110 		    ev->x		= cvtINT16toInt(event->u.configureRequest.x);
1111 		    ev->y		= cvtINT16toInt(event->u.configureRequest.y);
1112 		    ev->width		= event->u.configureRequest.width;
1113 		    ev->height		= event->u.configureRequest.height;
1114 		    ev->border_width	= event->u.configureRequest.borderWidth;
1115 		    ev->value_mask	= event->u.configureRequest.valueMask;
1116 		    ev->detail  	= event->u.u.detail;
1117 		}
1118 		break;
1119 	      case GravityNotify:
1120 		{
1121 		    register XGravityEvent *ev = (XGravityEvent *) re;
1122 		    ev->window		= event->u.gravity.window;
1123 		    ev->event		= event->u.gravity.event;
1124 		    ev->x		= cvtINT16toInt(event->u.gravity.x);
1125 		    ev->y		= cvtINT16toInt(event->u.gravity.y);
1126 		}
1127 		break;
1128 	      case ResizeRequest:
1129 		{
1130 		    register XResizeRequestEvent *ev =
1131 			(XResizeRequestEvent *) re;
1132 		    ev->window		= event->u.resizeRequest.window;
1133 		    ev->width		= event->u.resizeRequest.width;
1134 		    ev->height		= event->u.resizeRequest.height;
1135 		}
1136 		break;
1137 	      case CirculateNotify:
1138 		{
1139 		    register XCirculateEvent *ev = (XCirculateEvent *) re;
1140 		    ev->window		= event->u.circulate.window;
1141 		    ev->event		= event->u.circulate.event;
1142 		    ev->place		= event->u.circulate.place;
1143 		}
1144 		break;
1145 	      case CirculateRequest:
1146 		{
1147 		    register XCirculateRequestEvent *ev =
1148 		        (XCirculateRequestEvent *) re;
1149 		    ev->window		= event->u.circulate.window;
1150 		    ev->parent		= event->u.circulate.event;
1151 		    ev->place		= event->u.circulate.place;
1152 		}
1153 		break;
1154 	      case PropertyNotify:
1155 		{
1156 		    register XPropertyEvent *ev = (XPropertyEvent *) re;
1157 		    ev->window		= event->u.property.window;
1158 		    ev->atom		= event->u.property.atom;
1159 		    ev->time		= event->u.property.time;
1160 		    ev->state		= event->u.property.state;
1161 		}
1162 		break;
1163 	      case SelectionClear:
1164 		{
1165 		    register XSelectionClearEvent *ev =
1166 			 (XSelectionClearEvent *) re;
1167 		    ev->window		= event->u.selectionClear.window;
1168 		    ev->selection	= event->u.selectionClear.atom;
1169 		    ev->time		= event->u.selectionClear.time;
1170 		}
1171 		break;
1172 	      case SelectionRequest:
1173 		{
1174 		    register XSelectionRequestEvent *ev =
1175 		        (XSelectionRequestEvent *) re;
1176 		    ev->owner		= event->u.selectionRequest.owner;
1177 		    ev->requestor	= event->u.selectionRequest.requestor;
1178 		    ev->selection	= event->u.selectionRequest.selection;
1179 		    ev->target		= event->u.selectionRequest.target;
1180 		    ev->property	= event->u.selectionRequest.property;
1181 		    ev->time		= event->u.selectionRequest.time;
1182 		}
1183 		break;
1184 	      case SelectionNotify:
1185 		{
1186 		    register XSelectionEvent *ev = (XSelectionEvent *) re;
1187 		    ev->requestor	= event->u.selectionNotify.requestor;
1188 		    ev->selection	= event->u.selectionNotify.selection;
1189 		    ev->target		= event->u.selectionNotify.target;
1190 		    ev->property	= event->u.selectionNotify.property;
1191 		    ev->time		= event->u.selectionNotify.time;
1192 		}
1193 		break;
1194 	      case ColormapNotify:
1195 		{
1196 		    register XColormapEvent *ev = (XColormapEvent *) re;
1197 		    ev->window		= event->u.colormap.window;
1198 		    ev->colormap	= event->u.colormap.colormap;
1199 		    ev->new		= event->u.colormap.new;
1200 		    ev->state		= event->u.colormap.state;
1201 	        }
1202 		break;
1203 	      case ClientMessage:
1204 		{
1205 		   register int i;
1206 		   register XClientMessageEvent *ev
1207 		   			= (XClientMessageEvent *) re;
1208 		   ev->window		= event->u.clientMessage.window;
1209 		   ev->format		= event->u.u.detail;
1210 		   switch (ev->format) {
1211 			case 8:
1212 			   ev->message_type = event->u.clientMessage.u.b.type;
1213 			   for (i = 0; i < 20; i++)
1214 			     ev->data.b[i] = event->u.clientMessage.u.b.bytes[i];
1215 			   break;
1216 			case 16:
1217 			   ev->message_type = event->u.clientMessage.u.s.type;
1218 			   ev->data.s[0] = cvtINT16toShort(event->u.clientMessage.u.s.shorts0);
1219 			   ev->data.s[1] = cvtINT16toShort(event->u.clientMessage.u.s.shorts1);
1220 			   ev->data.s[2] = cvtINT16toShort(event->u.clientMessage.u.s.shorts2);
1221 			   ev->data.s[3] = cvtINT16toShort(event->u.clientMessage.u.s.shorts3);
1222 			   ev->data.s[4] = cvtINT16toShort(event->u.clientMessage.u.s.shorts4);
1223 			   ev->data.s[5] = cvtINT16toShort(event->u.clientMessage.u.s.shorts5);
1224 			   ev->data.s[6] = cvtINT16toShort(event->u.clientMessage.u.s.shorts6);
1225 			   ev->data.s[7] = cvtINT16toShort(event->u.clientMessage.u.s.shorts7);
1226 			   ev->data.s[8] = cvtINT16toShort(event->u.clientMessage.u.s.shorts8);
1227 			   ev->data.s[9] = cvtINT16toShort(event->u.clientMessage.u.s.shorts9);
1228 			   break;
1229 			case 32:
1230 			   ev->message_type = event->u.clientMessage.u.l.type;
1231 			   ev->data.l[0] = cvtINT32toLong(event->u.clientMessage.u.l.longs0);
1232 			   ev->data.l[1] = cvtINT32toLong(event->u.clientMessage.u.l.longs1);
1233 			   ev->data.l[2] = cvtINT32toLong(event->u.clientMessage.u.l.longs2);
1234 			   ev->data.l[3] = cvtINT32toLong(event->u.clientMessage.u.l.longs3);
1235 			   ev->data.l[4] = cvtINT32toLong(event->u.clientMessage.u.l.longs4);
1236 			   break;
1237 			default: /* XXX should never occur */
1238 				break;
1239 		    }
1240 	        }
1241 		break;
1242 	      case MappingNotify:
1243 		{
1244 		   register XMappingEvent *ev = (XMappingEvent *)re;
1245 		   ev->window		= 0;
1246 		   ev->first_keycode 	= event->u.mappingNotify.firstKeyCode;
1247 		   ev->request 		= event->u.mappingNotify.request;
1248 		   ev->count 		= event->u.mappingNotify.count;
1249 		}
1250 		break;
1251 	      default:
1252 		return(_XUnknownWireEvent(dpy, re, event));
1253 	}
1254 	return(True);
1255 }
1256 
1257 static int
SocketBytesReadable(Display * dpy)1258 SocketBytesReadable(Display *dpy)
1259 {
1260     int bytes = 0, last_error;
1261 #ifdef WIN32
1262     last_error = WSAGetLastError();
1263     ioctlsocket(ConnectionNumber(dpy), FIONREAD, &bytes);
1264     WSASetLastError(last_error);
1265 #else
1266     last_error = errno;
1267     ioctl(ConnectionNumber(dpy), FIONREAD, &bytes);
1268     errno = last_error;
1269 #endif
1270     return bytes;
1271 }
1272 
_XDefaultIOErrorExit(Display * dpy,void * user_data)1273 _X_NORETURN void _XDefaultIOErrorExit(
1274 	Display *dpy,
1275 	void *user_data)
1276 {
1277     exit(1);
1278     /*NOTREACHED*/
1279 }
1280 
1281 /*
1282  * _XDefaultIOError - Default fatal system error reporting routine.  Called
1283  * when an X internal system error is encountered.
1284  */
_XDefaultIOError(Display * dpy)1285 _X_NORETURN int _XDefaultIOError(
1286 	Display *dpy)
1287 {
1288 	int killed = ECHECK(EPIPE);
1289 
1290 	/*
1291 	 * If the socket was closed on the far end, the final recvmsg in
1292 	 * xcb will have thrown EAGAIN because we're non-blocking. Detect
1293 	 * this to get the more informative error message.
1294 	 */
1295 	if (ECHECK(EAGAIN) && SocketBytesReadable(dpy) <= 0)
1296 	    killed = True;
1297 
1298 	if (killed) {
1299 	    fprintf (stderr,
1300                      "X connection to %s broken (explicit kill or server shutdown).\r\n",
1301                      DisplayString (dpy));
1302 	} else {
1303             fprintf (stderr,
1304                      "XIO:  fatal IO error %d (%s) on X server \"%s\"\r\n",
1305 #ifdef WIN32
1306                       WSAGetLastError(), strerror(WSAGetLastError()),
1307 #else
1308                       errno, strerror (errno),
1309 #endif
1310                       DisplayString (dpy));
1311 	    fprintf (stderr,
1312 		     "      after %lu requests (%lu known processed) with %d events remaining.\r\n",
1313 		     NextRequest(dpy) - 1, LastKnownRequestProcessed(dpy),
1314 		     QLength(dpy));
1315         }
1316 
1317 	exit(1);
1318 	/*NOTREACHED*/
1319 }
1320 
1321 
_XPrintDefaultError(Display * dpy,XErrorEvent * event,FILE * fp)1322 static int _XPrintDefaultError(
1323     Display *dpy,
1324     XErrorEvent *event,
1325     FILE *fp)
1326 {
1327     char buffer[BUFSIZ];
1328     char mesg[BUFSIZ];
1329     char number[32];
1330     const char *mtype = "XlibMessage";
1331     register _XExtension *ext = (_XExtension *)NULL;
1332     _XExtension *bext = (_XExtension *)NULL;
1333     XGetErrorText(dpy, event->error_code, buffer, BUFSIZ);
1334     XGetErrorDatabaseText(dpy, mtype, "XError", "X Error", mesg, BUFSIZ);
1335     (void) fprintf(fp, "%s:  %s\n  ", mesg, buffer);
1336     XGetErrorDatabaseText(dpy, mtype, "MajorCode", "Request Major code %d",
1337 	mesg, BUFSIZ);
1338     (void) fprintf(fp, mesg, event->request_code);
1339     if (event->request_code < 128) {
1340 	snprintf(number, sizeof(number), "%d", event->request_code);
1341 	XGetErrorDatabaseText(dpy, "XRequest", number, "", buffer, BUFSIZ);
1342     } else {
1343 	for (ext = dpy->ext_procs;
1344 	     ext && (ext->codes.major_opcode != event->request_code);
1345 	     ext = ext->next)
1346 	  ;
1347 	if (ext) {
1348 	    strncpy(buffer, ext->name, BUFSIZ);
1349 	    buffer[BUFSIZ - 1] = '\0';
1350         } else
1351 	    buffer[0] = '\0';
1352     }
1353     (void) fprintf(fp, " (%s)\n", buffer);
1354     if (event->request_code >= 128) {
1355 	XGetErrorDatabaseText(dpy, mtype, "MinorCode", "Request Minor code %d",
1356 			      mesg, BUFSIZ);
1357 	fputs("  ", fp);
1358 	(void) fprintf(fp, mesg, event->minor_code);
1359 	if (ext) {
1360 	    snprintf(mesg, sizeof(mesg), "%s.%d", ext->name, event->minor_code);
1361 	    XGetErrorDatabaseText(dpy, "XRequest", mesg, "", buffer, BUFSIZ);
1362 	    (void) fprintf(fp, " (%s)", buffer);
1363 	}
1364 	fputs("\n", fp);
1365     }
1366     if (event->error_code >= 128) {
1367 	/* kludge, try to find the extension that caused it */
1368 	buffer[0] = '\0';
1369 	for (ext = dpy->ext_procs; ext; ext = ext->next) {
1370 	    if (ext->error_string)
1371 		(*ext->error_string)(dpy, event->error_code, &ext->codes,
1372 				     buffer, BUFSIZ);
1373 	    if (buffer[0]) {
1374 		bext = ext;
1375 		break;
1376 	    }
1377 	    if (ext->codes.first_error &&
1378 		ext->codes.first_error < (int)event->error_code &&
1379 		(!bext || ext->codes.first_error > bext->codes.first_error))
1380 		bext = ext;
1381 	}
1382 	if (bext)
1383 	    snprintf(buffer, sizeof(buffer), "%s.%d", bext->name,
1384                      event->error_code - bext->codes.first_error);
1385 	else
1386 	    strcpy(buffer, "Value");
1387 	XGetErrorDatabaseText(dpy, mtype, buffer, "", mesg, BUFSIZ);
1388 	if (mesg[0]) {
1389 	    fputs("  ", fp);
1390 	    (void) fprintf(fp, mesg, event->resourceid);
1391 	    fputs("\n", fp);
1392 	}
1393 	/* let extensions try to print the values */
1394 	for (ext = dpy->ext_procs; ext; ext = ext->next) {
1395 	    if (ext->error_values)
1396 		(*ext->error_values)(dpy, event, fp);
1397 	}
1398     } else if ((event->error_code == BadWindow) ||
1399 	       (event->error_code == BadPixmap) ||
1400 	       (event->error_code == BadCursor) ||
1401 	       (event->error_code == BadFont) ||
1402 	       (event->error_code == BadDrawable) ||
1403 	       (event->error_code == BadColor) ||
1404 	       (event->error_code == BadGC) ||
1405 	       (event->error_code == BadIDChoice) ||
1406 	       (event->error_code == BadValue) ||
1407 	       (event->error_code == BadAtom)) {
1408 	if (event->error_code == BadValue)
1409 	    XGetErrorDatabaseText(dpy, mtype, "Value", "Value 0x%x",
1410 				  mesg, BUFSIZ);
1411 	else if (event->error_code == BadAtom)
1412 	    XGetErrorDatabaseText(dpy, mtype, "AtomID", "AtomID 0x%x",
1413 				  mesg, BUFSIZ);
1414 	else
1415 	    XGetErrorDatabaseText(dpy, mtype, "ResourceID", "ResourceID 0x%x",
1416 				  mesg, BUFSIZ);
1417 	fputs("  ", fp);
1418 	(void) fprintf(fp, mesg, event->resourceid);
1419 	fputs("\n", fp);
1420     }
1421     XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d",
1422 			  mesg, BUFSIZ);
1423     fputs("  ", fp);
1424     (void) fprintf(fp, mesg, event->serial);
1425     XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%lld",
1426 			  mesg, BUFSIZ);
1427     fputs("\n  ", fp);
1428     (void) fprintf(fp, mesg, (unsigned long long)(X_DPY_GET_REQUEST(dpy)));
1429     fputs("\n", fp);
1430     if (event->error_code == BadImplementation) return 0;
1431     return 1;
1432 }
1433 
_XDefaultError(Display * dpy,XErrorEvent * event)1434 int _XDefaultError(
1435 	Display *dpy,
1436 	XErrorEvent *event)
1437 {
1438     if (_XPrintDefaultError (dpy, event, stderr) == 0) return 0;
1439 
1440     /*
1441      * Store in dpy flags that the client is exiting on an unhandled XError
1442      * (pretend it is an IOError, since the application is dying anyway it
1443      * does not make a difference).
1444      * This is useful for _XReply not to hang if the application makes Xlib
1445      * calls in _fini as part of process termination.
1446      */
1447     dpy->flags |= XlibDisplayIOError;
1448 
1449     exit(1);
1450     /*NOTREACHED*/
1451 }
1452 
1453 /*ARGSUSED*/
_XDefaultWireError(Display * display,XErrorEvent * he,xError * we)1454 Bool _XDefaultWireError(Display *display, XErrorEvent *he, xError *we)
1455 {
1456     return True;
1457 }
1458 
1459 /*
1460  * _XError - upcall internal or user protocol error handler
1461  */
_XError(Display * dpy,register xError * rep)1462 int _XError (
1463     Display *dpy,
1464     register xError *rep)
1465 {
1466     /*
1467      * X_Error packet encountered!  We need to unpack the error before
1468      * giving it to the user.
1469      */
1470     XEvent event; /* make it a large event */
1471     register _XAsyncHandler *async, *next;
1472 
1473     event.xerror.serial = _XSetLastRequestRead(dpy, (xGenericReply *)rep);
1474 
1475     for (async = dpy->async_handlers; async; async = next) {
1476 	next = async->next;
1477 	if ((*async->handler)(dpy, (xReply *)rep,
1478 			      (char *)rep, SIZEOF(xError), async->data))
1479 	    return 0;
1480     }
1481 
1482     event.xerror.display = dpy;
1483     event.xerror.type = X_Error;
1484     event.xerror.resourceid = rep->resourceID;
1485     event.xerror.error_code = rep->errorCode;
1486     event.xerror.request_code = rep->majorCode;
1487     event.xerror.minor_code = rep->minorCode;
1488     if (dpy->error_vec &&
1489 	!(*dpy->error_vec[rep->errorCode])(dpy, &event.xerror, rep))
1490 	return 0;
1491     if (_XErrorFunction != NULL) {
1492 	int rtn_val;
1493 #ifdef XTHREADS
1494 	struct _XErrorThreadInfo thread_info = {
1495 		.error_thread = xthread_self(),
1496 		.next = dpy->error_threads
1497 	}, **prev;
1498 	dpy->error_threads = &thread_info;
1499 	if (dpy->lock)
1500 	    (*dpy->lock->user_lock_display)(dpy);
1501 	UnlockDisplay(dpy);
1502 #endif
1503 	rtn_val = (*_XErrorFunction)(dpy, (XErrorEvent *)&event); /* upcall */
1504 #ifdef XTHREADS
1505 	LockDisplay(dpy);
1506 	if (dpy->lock)
1507 	    (*dpy->lock->user_unlock_display)(dpy);
1508 
1509 	/* unlink thread_info from the list */
1510 	for (prev = &dpy->error_threads; *prev != &thread_info; prev = &(*prev)->next)
1511 		;
1512 	*prev = thread_info.next;
1513 #endif
1514 	return rtn_val;
1515     } else {
1516 	return _XDefaultError(dpy, (XErrorEvent *)&event);
1517     }
1518 }
1519 
1520 /*
1521  * _XIOError - call user connection error handler and exit
1522  */
1523 int
_XIOError(Display * dpy)1524 _XIOError (
1525     Display *dpy)
1526 {
1527     XIOErrorExitHandler exit_handler;
1528     void *exit_handler_data;
1529 
1530     dpy->flags |= XlibDisplayIOError;
1531 #ifdef WIN32
1532     errno = WSAGetLastError();
1533 #endif
1534 
1535     /* This assumes that the thread calling exit will call any atexit handlers.
1536      * If this does not hold, then an alternate solution would involve
1537      * registering an atexit handler to take over the lock, which would only
1538      * assume that the same thread calls all the atexit handlers. */
1539 #ifdef XTHREADS
1540     if (dpy->lock)
1541 	(*dpy->lock->user_lock_display)(dpy);
1542 #endif
1543     exit_handler = dpy->exit_handler;
1544     exit_handler_data = dpy->exit_handler_data;
1545     UnlockDisplay(dpy);
1546 
1547     if (_XIOErrorFunction != NULL)
1548 	(*_XIOErrorFunction)(dpy);
1549     else
1550 	_XDefaultIOError(dpy);
1551 
1552     exit_handler(dpy, exit_handler_data);
1553     return 1;
1554 }
1555 
1556 
1557 /*
1558  * This routine can be used to (cheaply) get some memory within a single
1559  * Xlib routine for scratch space.  A single buffer is reused each time
1560  * if possible.  To be MT safe, you can only call this between a call to
1561  * GetReq* and a call to Data* or _XSend*, or in a context when the thread
1562  * is guaranteed to not unlock the display.
1563  */
_XAllocScratch(register Display * dpy,unsigned long nbytes)1564 char *_XAllocScratch(
1565 	register Display *dpy,
1566 	unsigned long nbytes)
1567 {
1568 	if (nbytes > dpy->scratch_length) {
1569 	    Xfree (dpy->scratch_buffer);
1570 	    dpy->scratch_buffer = Xmalloc(nbytes);
1571 	    if (dpy->scratch_buffer)
1572 		dpy->scratch_length = nbytes;
1573 	    else dpy->scratch_length = 0;
1574 	}
1575 	return (dpy->scratch_buffer);
1576 }
1577 
1578 /*
1579  * Scratch space allocator you can call any time, multiple times, and be
1580  * MT safe, but you must hand the buffer back with _XFreeTemp.
1581  */
_XAllocTemp(register Display * dpy,unsigned long nbytes)1582 char *_XAllocTemp(
1583     register Display *dpy,
1584     unsigned long nbytes)
1585 {
1586     char *buf;
1587 
1588     buf = _XAllocScratch(dpy, nbytes);
1589     dpy->scratch_buffer = NULL;
1590     dpy->scratch_length = 0;
1591     return buf;
1592 }
1593 
_XFreeTemp(register Display * dpy,char * buf,unsigned long nbytes)1594 void _XFreeTemp(
1595     register Display *dpy,
1596     char *buf,
1597     unsigned long nbytes)
1598 {
1599 
1600     Xfree(dpy->scratch_buffer);
1601     dpy->scratch_buffer = buf;
1602     dpy->scratch_length = nbytes;
1603 }
1604 
1605 /*
1606  * Given a visual id, find the visual structure for this id on this display.
1607  */
_XVIDtoVisual(Display * dpy,VisualID id)1608 Visual *_XVIDtoVisual(
1609 	Display *dpy,
1610 	VisualID id)
1611 {
1612 	register int i, j, k;
1613 	register Screen *sp;
1614 	register Depth *dp;
1615 	register Visual *vp;
1616 	for (i = 0; i < dpy->nscreens; i++) {
1617 		sp = &dpy->screens[i];
1618 		for (j = 0; j < sp->ndepths; j++) {
1619 			dp = &sp->depths[j];
1620 			/* if nvisuals == 0 then visuals will be NULL */
1621 			for (k = 0; k < dp->nvisuals; k++) {
1622 				vp = &dp->visuals[k];
1623 				if (vp->visualid == id) return (vp);
1624 			}
1625 		}
1626 	}
1627 	return (NULL);
1628 }
1629 
1630 int
XFree(void * data)1631 XFree (void *data)
1632 {
1633 	Xfree (data);
1634 	return 1;
1635 }
1636 
1637 #ifdef _XNEEDBCOPYFUNC
_Xbcopy(b1,b2,length)1638 void _Xbcopy(b1, b2, length)
1639     register char *b1, *b2;
1640     register length;
1641 {
1642     if (b1 < b2) {
1643 	b2 += length;
1644 	b1 += length;
1645 	while (length--)
1646 	    *--b2 = *--b1;
1647     } else {
1648 	while (length--)
1649 	    *b2++ = *b1++;
1650     }
1651 }
1652 #endif
1653 
1654 #ifdef DataRoutineIsProcedure
Data(Display * dpy,_Xconst char * data,long len)1655 void Data(
1656 	Display *dpy,
1657 	_Xconst char *data,
1658 	long len)
1659 {
1660 	if (dpy->bufptr + (len) <= dpy->bufmax) {
1661 		memcpy(dpy->bufptr, data, (int)len);
1662 		dpy->bufptr += ((len) + 3) & ~3;
1663 	} else {
1664 		_XSend(dpy, data, len);
1665 	}
1666 }
1667 #endif /* DataRoutineIsProcedure */
1668 
1669 
1670 #ifdef LONG64
1671 int
_XData32(Display * dpy,_Xconst long * data,unsigned len)1672 _XData32(
1673     Display *dpy,
1674     _Xconst long *data,
1675     unsigned len)
1676 {
1677     register int *buf;
1678     register long i;
1679 
1680     while (len) {
1681 	buf = (int *)dpy->bufptr;
1682 	i = dpy->bufmax - (char *)buf;
1683 	if (!i) {
1684 	    _XFlush(dpy);
1685 	    continue;
1686 	}
1687 	if (len < i)
1688 	    i = len;
1689 	dpy->bufptr = (char *)buf + i;
1690 	len -= i;
1691 	i >>= 2;
1692 	while (--i >= 0)
1693 	    *buf++ = *data++;
1694     }
1695     return 0;
1696 }
1697 #endif /* LONG64 */
1698 
1699 
1700 
1701 /* Make sure this produces the same string as DefineLocal/DefineSelf in xdm.
1702  * Otherwise, Xau will not be able to find your cookies in the Xauthority file.
1703  *
1704  * Note: POSIX says that the ``nodename'' member of utsname does _not_ have
1705  *       to have sufficient information for interfacing to the network,
1706  *       and so, you may be better off using gethostname (if it exists).
1707  */
1708 
1709 #if (defined(_POSIX_SOURCE) && !defined(AIXV3) && !defined(__QNX__)) || defined(hpux) || defined(SVR4)
1710 #define NEED_UTSNAME
1711 #include <sys/utsname.h>
1712 #else
1713 #ifdef HAVE_UNISTD_H
1714 #include <unistd.h>
1715 #endif
1716 #endif
1717 
1718 /*
1719  * _XGetHostname - similar to gethostname but allows special processing.
1720  */
_XGetHostname(char * buf,int maxlen)1721 int _XGetHostname (
1722     char *buf,
1723     int maxlen)
1724 {
1725     int len;
1726 
1727 #ifdef NEED_UTSNAME
1728     struct utsname name;
1729 
1730     if (maxlen <= 0 || buf == NULL)
1731 	return 0;
1732 
1733     uname (&name);
1734     len = (int) strlen (name.nodename);
1735     if (len >= maxlen) len = maxlen - 1;
1736     strncpy (buf, name.nodename, (size_t) len);
1737     buf[len] = '\0';
1738 #else
1739     if (maxlen <= 0 || buf == NULL)
1740 	return 0;
1741 
1742     buf[0] = '\0';
1743     (void) gethostname (buf, maxlen);
1744     buf [maxlen - 1] = '\0';
1745     len = (int) strlen(buf);
1746 #endif /* NEED_UTSNAME */
1747     return len;
1748 }
1749 
1750 
1751 /*
1752  * _XScreenOfWindow - get the Screen of a given window
1753  */
1754 
_XScreenOfWindow(Display * dpy,Window w)1755 Screen *_XScreenOfWindow(Display *dpy, Window w)
1756 {
1757     register int i;
1758     Window root;
1759     int x, y;				/* dummy variables */
1760     unsigned int width, height, bw, depth;  /* dummy variables */
1761 
1762     if (XGetGeometry (dpy, w, &root, &x, &y, &width, &height,
1763 		      &bw, &depth) == False) {
1764 	return NULL;
1765     }
1766     for (i = 0; i < ScreenCount (dpy); i++) {	/* find root from list */
1767 	if (root == RootWindow (dpy, i)) {
1768 	    return ScreenOfDisplay (dpy, i);
1769 	}
1770     }
1771     return NULL;
1772 }
1773 
1774 
1775 /*
1776  * WARNING: This implementation's pre-conditions and post-conditions
1777  * must remain compatible with the old macro-based implementations of
1778  * GetReq, GetReqExtra, GetResReq, and GetEmptyReq. The portions of the
1779  * Display structure affected by those macros are part of libX11's
1780  * ABI.
1781  */
_XGetRequest(Display * dpy,CARD8 type,size_t len)1782 void *_XGetRequest(Display *dpy, CARD8 type, size_t len)
1783 {
1784     xReq *req;
1785 
1786     if (dpy->bufptr + len > dpy->bufmax)
1787 	_XFlush(dpy);
1788     /* Request still too large, so do not allow it to overflow. */
1789     if (dpy->bufptr + len > dpy->bufmax) {
1790 	fprintf(stderr,
1791 		"Xlib: request %d length %zd would exceed buffer size.\n",
1792 		type, len);
1793 	/* Changes failure condition from overflow to NULL dereference. */
1794 	return NULL;
1795     }
1796 
1797     if (len % 4)
1798 	fprintf(stderr,
1799 		"Xlib: request %d length %zd not a multiple of 4.\n",
1800 		type, len);
1801 
1802     dpy->last_req = dpy->bufptr;
1803 
1804     req = (xReq*)dpy->bufptr;
1805     req->reqType = type;
1806     req->length = len / 4;
1807     dpy->bufptr += len;
1808     X_DPY_REQUEST_INCREMENT(dpy);
1809     return req;
1810 }
1811 
1812 #if defined(WIN32)
1813 
1814 /*
1815  * These functions are intended to be used internally to Xlib only.
1816  * These functions will always prefix the path with a DOS drive in the
1817  * form "<drive-letter>:". As such, these functions are only suitable
1818  * for use by Xlib function that supply a root-based path to some
1819  * particular file, e.g. <ProjectRoot>/lib/X11/locale/locale.dir will
1820  * be converted to "C:/usr/X11R6.3/lib/X11/locale/locale.dir".
1821  */
1822 
access_file(path,pathbuf,len_pathbuf,pathret)1823 static int access_file (path, pathbuf, len_pathbuf, pathret)
1824     char* path;
1825     char* pathbuf;
1826     int len_pathbuf;
1827     char** pathret;
1828 {
1829     if (access (path, F_OK) == 0) {
1830 	if (strlen (path) < len_pathbuf)
1831 	    *pathret = pathbuf;
1832 	else
1833 	    *pathret = Xmalloc (strlen (path) + 1);
1834 	if (*pathret) {
1835 	    strcpy (*pathret, path);
1836 	    return 1;
1837 	}
1838     }
1839     return 0;
1840 }
1841 
AccessFile(path,pathbuf,len_pathbuf,pathret)1842 static int AccessFile (path, pathbuf, len_pathbuf, pathret)
1843     char* path;
1844     char* pathbuf;
1845     int len_pathbuf;
1846     char** pathret;
1847 {
1848     unsigned long drives;
1849     int i, len;
1850     char* drive;
1851     char buf[MAX_PATH];
1852     char* bufp;
1853 
1854     /* just try the "raw" name first and see if it works */
1855     if (access_file (path, pathbuf, len_pathbuf, pathret))
1856 	return 1;
1857 
1858     /* try the places set in the environment */
1859     drive = getenv ("_XBASEDRIVE");
1860 #ifdef __UNIXOS2__
1861     if (!drive)
1862 	drive = getenv ("X11ROOT");
1863 #endif
1864     if (!drive)
1865 	drive = "C:";
1866     len = strlen (drive) + strlen (path);
1867     if (len < MAX_PATH) bufp = buf;
1868     else bufp = Xmalloc (len + 1);
1869     strcpy (bufp, drive);
1870     strcat (bufp, path);
1871     if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
1872 	if (bufp != buf) Xfree (bufp);
1873 	return 1;
1874     }
1875 
1876 #ifndef __UNIXOS2__
1877     /* one last place to look */
1878     drive = getenv ("HOMEDRIVE");
1879     if (drive) {
1880 	len = strlen (drive) + strlen (path);
1881 	if (len < MAX_PATH) bufp = buf;
1882 	else bufp = Xmalloc (len + 1);
1883 	strcpy (bufp, drive);
1884 	strcat (bufp, path);
1885 	if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
1886 	    if (bufp != buf) Xfree (bufp);
1887 	    return 1;
1888 	}
1889     }
1890 
1891     /* tried everywhere else, go fishing */
1892 #define C_DRIVE ('C' - 'A')
1893 #define Z_DRIVE ('Z' - 'A')
1894     /* does OS/2 (with or with gcc-emx) have getdrives? */
1895     drives = _getdrives ();
1896     for (i = C_DRIVE; i <= Z_DRIVE; i++) { /* don't check on A: or B: */
1897 	if ((1 << i) & drives) {
1898 	    len = 2 + strlen (path);
1899 	    if (len < MAX_PATH) bufp = buf;
1900 	    else bufp = Xmalloc (len + 1);
1901 	    *bufp = 'A' + i;
1902 	    *(bufp + 1) = ':';
1903 	    *(bufp + 2) = '\0';
1904 	    strcat (bufp, path);
1905 	    if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
1906 		if (bufp != buf) Xfree (bufp);
1907 		return 1;
1908 	    }
1909 	}
1910     }
1911 #endif
1912     return 0;
1913 }
1914 
_XOpenFile(path,flags)1915 int _XOpenFile(path, flags)
1916     _Xconst char* path;
1917     int flags;
1918 {
1919     char buf[MAX_PATH];
1920     char* bufp = NULL;
1921     int ret = -1;
1922     UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
1923 
1924     if (AccessFile (path, buf, MAX_PATH, &bufp))
1925 	ret = open (bufp, flags);
1926 
1927     (void) SetErrorMode (olderror);
1928 
1929     if (bufp != buf) Xfree (bufp);
1930 
1931     return ret;
1932 }
1933 
_XOpenFileMode(path,flags,mode)1934 int _XOpenFileMode(path, flags, mode)
1935     _Xconst char* path;
1936     int flags;
1937     mode_t mode;
1938 {
1939     char buf[MAX_PATH];
1940     char* bufp = NULL;
1941     int ret = -1;
1942     UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
1943 
1944     if (AccessFile (path, buf, MAX_PATH, &bufp))
1945 	ret = open (bufp, flags, mode);
1946 
1947     (void) SetErrorMode (olderror);
1948 
1949     if (bufp != buf) Xfree (bufp);
1950 
1951     return ret;
1952 }
1953 
_XFopenFile(path,mode)1954 void* _XFopenFile(path, mode)
1955     _Xconst char* path;
1956     _Xconst char* mode;
1957 {
1958     char buf[MAX_PATH];
1959     char* bufp = NULL;
1960     void* ret = NULL;
1961     UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
1962 
1963     if (AccessFile (path, buf, MAX_PATH, &bufp))
1964 	ret = fopen (bufp, mode);
1965 
1966     (void) SetErrorMode (olderror);
1967 
1968     if (bufp != buf) Xfree (bufp);
1969 
1970     return ret;
1971 }
1972 
_XAccessFile(path)1973 int _XAccessFile(path)
1974     _Xconst char* path;
1975 {
1976     char buf[MAX_PATH];
1977     char* bufp;
1978     int ret = -1;
1979     UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
1980 
1981     ret = AccessFile (path, buf, MAX_PATH, &bufp);
1982 
1983     (void) SetErrorMode (olderror);
1984 
1985     if (bufp != buf) Xfree (bufp);
1986 
1987     return ret;
1988 }
1989 
1990 #endif
1991 
1992 #ifdef WIN32
1993 #undef _Xdebug
1994 int _Xdebug = 0;
1995 int *_Xdebug_p = &_Xdebug;
1996 void (**_XCreateMutex_fn_p)(LockInfoPtr) = &_XCreateMutex_fn;
1997 void (**_XFreeMutex_fn_p)(LockInfoPtr) = &_XFreeMutex_fn;
1998 void (**_XLockMutex_fn_p)(LockInfoPtr
1999 #if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
2000     , char * /* file */
2001     , int /* line */
2002 #endif
2003         ) = &_XLockMutex_fn;
2004 void (**_XUnlockMutex_fn_p)(LockInfoPtr
2005 #if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
2006     , char * /* file */
2007     , int /* line */
2008 #endif
2009         ) = &_XUnlockMutex_fn;
2010 LockInfoPtr *_Xglobal_lock_p = &_Xglobal_lock;
2011 #endif
2012