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