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