XlibInt.c revision c17aa6b1
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 info_list->watch_data = wd_array; 666 wd_array[dpy->watcher_count] = NULL; /* for cleanliness */ 667 } 668 669 new_watcher = (struct _XConnWatchInfo*)Xmalloc(sizeof(struct _XConnWatchInfo)); 670 if (!new_watcher) { 671 UnlockDisplay(dpy); 672 return 0; 673 } 674 new_watcher->fn = callback; 675 new_watcher->client_data = client_data; 676 new_watcher->next = NULL; 677 678 /* link new structure onto end of list */ 679 for (wptr = &dpy->conn_watchers; *wptr; wptr = &(*wptr)->next) 680 ; 681 *wptr = new_watcher; 682 dpy->watcher_count++; 683 684 /* call new watcher on all currently registered fds */ 685 for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) { 686 (*callback) (dpy, client_data, info_list->fd, True, 687 info_list->watch_data + dpy->watcher_count - 1); 688 } 689 690 UnlockDisplay(dpy); 691 return 1; 692} 693 694/* XRemoveConnectionWatch 695 * Unregister a callback registered by XAddConnectionWatch. 696 * Both callback and client_data must match what was passed to 697 * XAddConnectionWatch. 698 */ 699void 700XRemoveConnectionWatch( 701 Display* dpy, 702 XConnectionWatchProc callback, 703 XPointer client_data 704) 705{ 706 struct _XConnWatchInfo *watch; 707 struct _XConnWatchInfo *previous = NULL; 708 struct _XConnectionInfo *conni; 709 int counter = 0; 710 711 LockDisplay(dpy); 712 for (watch=dpy->conn_watchers; watch; watch=watch->next) { 713 if (watch->fn == callback && watch->client_data == client_data) { 714 if (previous) 715 previous->next = watch->next; 716 else 717 dpy->conn_watchers = watch->next; 718 Xfree (watch); 719 dpy->watcher_count--; 720 /* remove our watch_data for each connection */ 721 for (conni=dpy->im_fd_info; conni; conni=conni->next) { 722 /* don't bother realloc'ing; these arrays are small anyway */ 723 /* overlapping */ 724 memmove(conni->watch_data+counter, 725 conni->watch_data+counter+1, 726 dpy->watcher_count - counter); 727 } 728 break; 729 } 730 previous = watch; 731 counter++; 732 } 733 UnlockDisplay(dpy); 734} 735 736/* end of internal connections support */ 737 738/* Cookie jar implementation 739 dpy->cookiejar is a linked list. _XEnq receives the events but leaves 740 them in the normal EQ. _XStoreEvent returns the cookie event (minus 741 data pointer) and adds it to the cookiejar. _XDeq just removes 742 the entry like any other event but resets the data pointer for 743 cookie events (to avoid double-free, the memory is re-used by Xlib). 744 745 _XFetchEventCookie (called from XGetEventData) removes a cookie from the 746 jar. _XFreeEventCookies removes all unclaimed cookies from the jar 747 (called by XNextEvent). 748 749 _XFreeDisplayStructure calls _XFreeEventCookies for each cookie in the 750 normal EQ. 751 */ 752 753#include "utlist.h" 754struct stored_event { 755 XGenericEventCookie ev; 756 struct stored_event *prev; 757 struct stored_event *next; 758}; 759 760Bool 761_XIsEventCookie(Display *dpy, XEvent *ev) 762{ 763 return (ev->xcookie.type == GenericEvent && 764 dpy->generic_event_vec[ev->xcookie.extension & 0x7F] != NULL); 765} 766 767/** 768 * Free all events in the event list. 769 */ 770void 771_XFreeEventCookies(Display *dpy) 772{ 773 struct stored_event **head, *e, *tmp; 774 775 if (!dpy->cookiejar) 776 return; 777 778 head = (struct stored_event**)&dpy->cookiejar; 779 780 DL_FOREACH_SAFE(*head, e, tmp) { 781 if (dpy->cookiejar == e) 782 dpy->cookiejar = NULL; 783 XFree(e->ev.data); 784 XFree(e); 785 } 786} 787 788/** 789 * Add an event to the display's event list. This event must be freed on the 790 * next call to XNextEvent(). 791 */ 792void 793_XStoreEventCookie(Display *dpy, XEvent *event) 794{ 795 XGenericEventCookie* cookie = &event->xcookie; 796 struct stored_event **head, *add; 797 798 if (!_XIsEventCookie(dpy, event)) 799 return; 800 801 head = (struct stored_event**)(&dpy->cookiejar); 802 803 add = Xmalloc(sizeof(struct stored_event)); 804 if (!add) { 805 ESET(ENOMEM); 806 _XIOError(dpy); 807 } 808 add->ev = *cookie; 809 DL_APPEND(*head, add); 810 cookie->data = NULL; /* don't return data yet, must be claimed */ 811} 812 813/** 814 * Return the event with the given cookie and remove it from the list. 815 */ 816Bool 817_XFetchEventCookie(Display *dpy, XGenericEventCookie* ev) 818{ 819 Bool ret = False; 820 struct stored_event **head, *event; 821 head = (struct stored_event**)&dpy->cookiejar; 822 823 if (!_XIsEventCookie(dpy, (XEvent*)ev)) 824 return ret; 825 826 DL_FOREACH(*head, event) { 827 if (event->ev.cookie == ev->cookie && 828 event->ev.extension == ev->extension && 829 event->ev.evtype == ev->evtype) { 830 *ev = event->ev; 831 DL_DELETE(*head, event); 832 Xfree(event); 833 ret = True; 834 break; 835 } 836 } 837 838 return ret; 839} 840 841Bool 842_XCopyEventCookie(Display *dpy, XGenericEventCookie *in, XGenericEventCookie *out) 843{ 844 Bool ret = False; 845 int extension; 846 847 if (!_XIsEventCookie(dpy, (XEvent*)in) || !out) 848 return ret; 849 850 extension = in->extension & 0x7F; 851 852 if (!dpy->generic_event_copy_vec[extension]) 853 return ret; 854 855 ret = ((*dpy->generic_event_copy_vec[extension])(dpy, in, out)); 856 out->cookie = ret ? ++dpy->next_cookie : 0; 857 return ret; 858} 859 860 861/* 862 * _XEnq - Place event packets on the display's queue. 863 * note that no squishing of move events in V11, since there 864 * is pointer motion hints.... 865 */ 866void _XEnq( 867 register Display *dpy, 868 register xEvent *event) 869{ 870 register _XQEvent *qelt; 871 int type, extension; 872 873 if ((qelt = dpy->qfree)) { 874 /* If dpy->qfree is non-NULL do this, else malloc a new one. */ 875 dpy->qfree = qelt->next; 876 } 877 else if ((qelt = 878 (_XQEvent *) Xmalloc((unsigned)sizeof(_XQEvent))) == NULL) { 879 /* Malloc call failed! */ 880 ESET(ENOMEM); 881 _XIOError(dpy); 882 } 883 qelt->next = NULL; 884 885 type = event->u.u.type & 0177; 886 extension = ((xGenericEvent*)event)->extension; 887 888 qelt->event.type = type; 889 /* If an extension has registerd a generic_event_vec handler, then 890 * it can handle event cookies. Otherwise, proceed with the normal 891 * event handlers. 892 * 893 * If the generic_event_vec is called, qelt->event is a event cookie 894 * with the data pointer and the "free" pointer set. Data pointer is 895 * some memory allocated by the extension. 896 */ 897 if (type == GenericEvent && dpy->generic_event_vec[extension & 0x7F]) { 898 XGenericEventCookie *cookie = &qelt->event.xcookie; 899 (*dpy->generic_event_vec[extension & 0x7F])(dpy, cookie, event); 900 cookie->cookie = ++dpy->next_cookie; 901 902 qelt->qserial_num = dpy->next_event_serial_num++; 903 if (dpy->tail) dpy->tail->next = qelt; 904 else dpy->head = qelt; 905 906 dpy->tail = qelt; 907 dpy->qlen++; 908 } else if ((*dpy->event_vec[type])(dpy, &qelt->event, event)) { 909 qelt->qserial_num = dpy->next_event_serial_num++; 910 if (dpy->tail) dpy->tail->next = qelt; 911 else dpy->head = qelt; 912 913 dpy->tail = qelt; 914 dpy->qlen++; 915 } else { 916 /* ignored, or stashed away for many-to-one compression */ 917 qelt->next = dpy->qfree; 918 dpy->qfree = qelt; 919 } 920} 921 922/* 923 * _XDeq - Remove event packet from the display's queue. 924 */ 925void _XDeq( 926 register Display *dpy, 927 register _XQEvent *prev, /* element before qelt */ 928 register _XQEvent *qelt) /* element to be unlinked */ 929{ 930 if (prev) { 931 if ((prev->next = qelt->next) == NULL) 932 dpy->tail = prev; 933 } else { 934 /* no prev, so removing first elt */ 935 if ((dpy->head = qelt->next) == NULL) 936 dpy->tail = NULL; 937 } 938 qelt->qserial_num = 0; 939 qelt->next = dpy->qfree; 940 dpy->qfree = qelt; 941 dpy->qlen--; 942 943 if (_XIsEventCookie(dpy, &qelt->event)) { 944 XGenericEventCookie* cookie = &qelt->event.xcookie; 945 /* dpy->qfree is re-used, reset memory to avoid double free on 946 * _XFreeDisplayStructure */ 947 cookie->data = NULL; 948 } 949} 950 951/* 952 * EventToWire in separate file in that often not needed. 953 */ 954 955/*ARGSUSED*/ 956Bool 957_XUnknownWireEvent( 958 register Display *dpy, /* pointer to display structure */ 959 register XEvent *re, /* pointer to where event should be reformatted */ 960 register xEvent *event) /* wire protocol event */ 961{ 962#ifdef notdef 963 (void) fprintf(stderr, 964 "Xlib: unhandled wire event! event number = %d, display = %x\n.", 965 event->u.u.type, dpy); 966#endif 967 return(False); 968} 969 970Bool 971_XUnknownWireEventCookie( 972 Display *dpy, /* pointer to display structure */ 973 XGenericEventCookie *re, /* pointer to where event should be reformatted */ 974 xEvent *event) /* wire protocol event */ 975{ 976#ifdef notdef 977 fprintf(stderr, 978 "Xlib: unhandled wire cookie event! extension number = %d, display = %x\n.", 979 ((xGenericEvent*)event)->extension, dpy); 980#endif 981 return(False); 982} 983 984Bool 985_XUnknownCopyEventCookie( 986 Display *dpy, /* pointer to display structure */ 987 XGenericEventCookie *in, /* source */ 988 XGenericEventCookie *out) /* destination */ 989{ 990#ifdef notdef 991 fprintf(stderr, 992 "Xlib: unhandled cookie event copy! extension number = %d, display = %x\n.", 993 in->extension, dpy); 994#endif 995 return(False); 996} 997 998/*ARGSUSED*/ 999Status 1000_XUnknownNativeEvent( 1001 register Display *dpy, /* pointer to display structure */ 1002 register XEvent *re, /* pointer to where event should be reformatted */ 1003 register xEvent *event) /* wire protocol event */ 1004{ 1005#ifdef notdef 1006 (void) fprintf(stderr, 1007 "Xlib: unhandled native event! event number = %d, display = %x\n.", 1008 re->type, dpy); 1009#endif 1010 return(0); 1011} 1012/* 1013 * reformat a wire event into an XEvent structure of the right type. 1014 */ 1015Bool 1016_XWireToEvent( 1017 register Display *dpy, /* pointer to display structure */ 1018 register XEvent *re, /* pointer to where event should be reformatted */ 1019 register xEvent *event) /* wire protocol event */ 1020{ 1021 1022 re->type = event->u.u.type & 0x7f; 1023 ((XAnyEvent *)re)->serial = _XSetLastRequestRead(dpy, 1024 (xGenericReply *)event); 1025 ((XAnyEvent *)re)->send_event = ((event->u.u.type & 0x80) != 0); 1026 ((XAnyEvent *)re)->display = dpy; 1027 1028 /* Ignore the leading bit of the event type since it is set when a 1029 client sends an event rather than the server. */ 1030 1031 switch (event-> u.u.type & 0177) { 1032 case KeyPress: 1033 case KeyRelease: 1034 { 1035 register XKeyEvent *ev = (XKeyEvent*) re; 1036 ev->root = event->u.keyButtonPointer.root; 1037 ev->window = event->u.keyButtonPointer.event; 1038 ev->subwindow = event->u.keyButtonPointer.child; 1039 ev->time = event->u.keyButtonPointer.time; 1040 ev->x = cvtINT16toInt(event->u.keyButtonPointer.eventX); 1041 ev->y = cvtINT16toInt(event->u.keyButtonPointer.eventY); 1042 ev->x_root = cvtINT16toInt(event->u.keyButtonPointer.rootX); 1043 ev->y_root = cvtINT16toInt(event->u.keyButtonPointer.rootY); 1044 ev->state = event->u.keyButtonPointer.state; 1045 ev->same_screen = event->u.keyButtonPointer.sameScreen; 1046 ev->keycode = event->u.u.detail; 1047 } 1048 break; 1049 case ButtonPress: 1050 case ButtonRelease: 1051 { 1052 register XButtonEvent *ev = (XButtonEvent *) re; 1053 ev->root = event->u.keyButtonPointer.root; 1054 ev->window = event->u.keyButtonPointer.event; 1055 ev->subwindow = event->u.keyButtonPointer.child; 1056 ev->time = event->u.keyButtonPointer.time; 1057 ev->x = cvtINT16toInt(event->u.keyButtonPointer.eventX); 1058 ev->y = cvtINT16toInt(event->u.keyButtonPointer.eventY); 1059 ev->x_root = cvtINT16toInt(event->u.keyButtonPointer.rootX); 1060 ev->y_root = cvtINT16toInt(event->u.keyButtonPointer.rootY); 1061 ev->state = event->u.keyButtonPointer.state; 1062 ev->same_screen = event->u.keyButtonPointer.sameScreen; 1063 ev->button = event->u.u.detail; 1064 } 1065 break; 1066 case MotionNotify: 1067 { 1068 register XMotionEvent *ev = (XMotionEvent *)re; 1069 ev->root = event->u.keyButtonPointer.root; 1070 ev->window = event->u.keyButtonPointer.event; 1071 ev->subwindow = event->u.keyButtonPointer.child; 1072 ev->time = event->u.keyButtonPointer.time; 1073 ev->x = cvtINT16toInt(event->u.keyButtonPointer.eventX); 1074 ev->y = cvtINT16toInt(event->u.keyButtonPointer.eventY); 1075 ev->x_root = cvtINT16toInt(event->u.keyButtonPointer.rootX); 1076 ev->y_root = cvtINT16toInt(event->u.keyButtonPointer.rootY); 1077 ev->state = event->u.keyButtonPointer.state; 1078 ev->same_screen = event->u.keyButtonPointer.sameScreen; 1079 ev->is_hint = event->u.u.detail; 1080 } 1081 break; 1082 case EnterNotify: 1083 case LeaveNotify: 1084 { 1085 register XCrossingEvent *ev = (XCrossingEvent *) re; 1086 ev->root = event->u.enterLeave.root; 1087 ev->window = event->u.enterLeave.event; 1088 ev->subwindow = event->u.enterLeave.child; 1089 ev->time = event->u.enterLeave.time; 1090 ev->x = cvtINT16toInt(event->u.enterLeave.eventX); 1091 ev->y = cvtINT16toInt(event->u.enterLeave.eventY); 1092 ev->x_root = cvtINT16toInt(event->u.enterLeave.rootX); 1093 ev->y_root = cvtINT16toInt(event->u.enterLeave.rootY); 1094 ev->state = event->u.enterLeave.state; 1095 ev->mode = event->u.enterLeave.mode; 1096 ev->same_screen = (event->u.enterLeave.flags & 1097 ELFlagSameScreen) && True; 1098 ev->focus = (event->u.enterLeave.flags & 1099 ELFlagFocus) && True; 1100 ev->detail = event->u.u.detail; 1101 } 1102 break; 1103 case FocusIn: 1104 case FocusOut: 1105 { 1106 register XFocusChangeEvent *ev = (XFocusChangeEvent *) re; 1107 ev->window = event->u.focus.window; 1108 ev->mode = event->u.focus.mode; 1109 ev->detail = event->u.u.detail; 1110 } 1111 break; 1112 case KeymapNotify: 1113 { 1114 register XKeymapEvent *ev = (XKeymapEvent *) re; 1115 ev->window = None; 1116 memcpy(&ev->key_vector[1], 1117 (char *)((xKeymapEvent *) event)->map, 1118 sizeof (((xKeymapEvent *) event)->map)); 1119 } 1120 break; 1121 case Expose: 1122 { 1123 register XExposeEvent *ev = (XExposeEvent *) re; 1124 ev->window = event->u.expose.window; 1125 ev->x = event->u.expose.x; 1126 ev->y = event->u.expose.y; 1127 ev->width = event->u.expose.width; 1128 ev->height = event->u.expose.height; 1129 ev->count = event->u.expose.count; 1130 } 1131 break; 1132 case GraphicsExpose: 1133 { 1134 register XGraphicsExposeEvent *ev = 1135 (XGraphicsExposeEvent *) re; 1136 ev->drawable = event->u.graphicsExposure.drawable; 1137 ev->x = event->u.graphicsExposure.x; 1138 ev->y = event->u.graphicsExposure.y; 1139 ev->width = event->u.graphicsExposure.width; 1140 ev->height = event->u.graphicsExposure.height; 1141 ev->count = event->u.graphicsExposure.count; 1142 ev->major_code = event->u.graphicsExposure.majorEvent; 1143 ev->minor_code = event->u.graphicsExposure.minorEvent; 1144 } 1145 break; 1146 case NoExpose: 1147 { 1148 register XNoExposeEvent *ev = (XNoExposeEvent *) re; 1149 ev->drawable = event->u.noExposure.drawable; 1150 ev->major_code = event->u.noExposure.majorEvent; 1151 ev->minor_code = event->u.noExposure.minorEvent; 1152 } 1153 break; 1154 case VisibilityNotify: 1155 { 1156 register XVisibilityEvent *ev = (XVisibilityEvent *) re; 1157 ev->window = event->u.visibility.window; 1158 ev->state = event->u.visibility.state; 1159 } 1160 break; 1161 case CreateNotify: 1162 { 1163 register XCreateWindowEvent *ev = 1164 (XCreateWindowEvent *) re; 1165 ev->window = event->u.createNotify.window; 1166 ev->parent = event->u.createNotify.parent; 1167 ev->x = cvtINT16toInt(event->u.createNotify.x); 1168 ev->y = cvtINT16toInt(event->u.createNotify.y); 1169 ev->width = event->u.createNotify.width; 1170 ev->height = event->u.createNotify.height; 1171 ev->border_width = event->u.createNotify.borderWidth; 1172 ev->override_redirect = event->u.createNotify.override; 1173 } 1174 break; 1175 case DestroyNotify: 1176 { 1177 register XDestroyWindowEvent *ev = 1178 (XDestroyWindowEvent *) re; 1179 ev->window = event->u.destroyNotify.window; 1180 ev->event = event->u.destroyNotify.event; 1181 } 1182 break; 1183 case UnmapNotify: 1184 { 1185 register XUnmapEvent *ev = (XUnmapEvent *) re; 1186 ev->window = event->u.unmapNotify.window; 1187 ev->event = event->u.unmapNotify.event; 1188 ev->from_configure = event->u.unmapNotify.fromConfigure; 1189 } 1190 break; 1191 case MapNotify: 1192 { 1193 register XMapEvent *ev = (XMapEvent *) re; 1194 ev->window = event->u.mapNotify.window; 1195 ev->event = event->u.mapNotify.event; 1196 ev->override_redirect = event->u.mapNotify.override; 1197 } 1198 break; 1199 case MapRequest: 1200 { 1201 register XMapRequestEvent *ev = (XMapRequestEvent *) re; 1202 ev->window = event->u.mapRequest.window; 1203 ev->parent = event->u.mapRequest.parent; 1204 } 1205 break; 1206 case ReparentNotify: 1207 { 1208 register XReparentEvent *ev = (XReparentEvent *) re; 1209 ev->event = event->u.reparent.event; 1210 ev->window = event->u.reparent.window; 1211 ev->parent = event->u.reparent.parent; 1212 ev->x = cvtINT16toInt(event->u.reparent.x); 1213 ev->y = cvtINT16toInt(event->u.reparent.y); 1214 ev->override_redirect = event->u.reparent.override; 1215 } 1216 break; 1217 case ConfigureNotify: 1218 { 1219 register XConfigureEvent *ev = (XConfigureEvent *) re; 1220 ev->event = event->u.configureNotify.event; 1221 ev->window = event->u.configureNotify.window; 1222 ev->above = event->u.configureNotify.aboveSibling; 1223 ev->x = cvtINT16toInt(event->u.configureNotify.x); 1224 ev->y = cvtINT16toInt(event->u.configureNotify.y); 1225 ev->width = event->u.configureNotify.width; 1226 ev->height = event->u.configureNotify.height; 1227 ev->border_width = event->u.configureNotify.borderWidth; 1228 ev->override_redirect = event->u.configureNotify.override; 1229 } 1230 break; 1231 case ConfigureRequest: 1232 { 1233 register XConfigureRequestEvent *ev = 1234 (XConfigureRequestEvent *) re; 1235 ev->window = event->u.configureRequest.window; 1236 ev->parent = event->u.configureRequest.parent; 1237 ev->above = event->u.configureRequest.sibling; 1238 ev->x = cvtINT16toInt(event->u.configureRequest.x); 1239 ev->y = cvtINT16toInt(event->u.configureRequest.y); 1240 ev->width = event->u.configureRequest.width; 1241 ev->height = event->u.configureRequest.height; 1242 ev->border_width = event->u.configureRequest.borderWidth; 1243 ev->value_mask = event->u.configureRequest.valueMask; 1244 ev->detail = event->u.u.detail; 1245 } 1246 break; 1247 case GravityNotify: 1248 { 1249 register XGravityEvent *ev = (XGravityEvent *) re; 1250 ev->window = event->u.gravity.window; 1251 ev->event = event->u.gravity.event; 1252 ev->x = cvtINT16toInt(event->u.gravity.x); 1253 ev->y = cvtINT16toInt(event->u.gravity.y); 1254 } 1255 break; 1256 case ResizeRequest: 1257 { 1258 register XResizeRequestEvent *ev = 1259 (XResizeRequestEvent *) re; 1260 ev->window = event->u.resizeRequest.window; 1261 ev->width = event->u.resizeRequest.width; 1262 ev->height = event->u.resizeRequest.height; 1263 } 1264 break; 1265 case CirculateNotify: 1266 { 1267 register XCirculateEvent *ev = (XCirculateEvent *) re; 1268 ev->window = event->u.circulate.window; 1269 ev->event = event->u.circulate.event; 1270 ev->place = event->u.circulate.place; 1271 } 1272 break; 1273 case CirculateRequest: 1274 { 1275 register XCirculateRequestEvent *ev = 1276 (XCirculateRequestEvent *) re; 1277 ev->window = event->u.circulate.window; 1278 ev->parent = event->u.circulate.event; 1279 ev->place = event->u.circulate.place; 1280 } 1281 break; 1282 case PropertyNotify: 1283 { 1284 register XPropertyEvent *ev = (XPropertyEvent *) re; 1285 ev->window = event->u.property.window; 1286 ev->atom = event->u.property.atom; 1287 ev->time = event->u.property.time; 1288 ev->state = event->u.property.state; 1289 } 1290 break; 1291 case SelectionClear: 1292 { 1293 register XSelectionClearEvent *ev = 1294 (XSelectionClearEvent *) re; 1295 ev->window = event->u.selectionClear.window; 1296 ev->selection = event->u.selectionClear.atom; 1297 ev->time = event->u.selectionClear.time; 1298 } 1299 break; 1300 case SelectionRequest: 1301 { 1302 register XSelectionRequestEvent *ev = 1303 (XSelectionRequestEvent *) re; 1304 ev->owner = event->u.selectionRequest.owner; 1305 ev->requestor = event->u.selectionRequest.requestor; 1306 ev->selection = event->u.selectionRequest.selection; 1307 ev->target = event->u.selectionRequest.target; 1308 ev->property = event->u.selectionRequest.property; 1309 ev->time = event->u.selectionRequest.time; 1310 } 1311 break; 1312 case SelectionNotify: 1313 { 1314 register XSelectionEvent *ev = (XSelectionEvent *) re; 1315 ev->requestor = event->u.selectionNotify.requestor; 1316 ev->selection = event->u.selectionNotify.selection; 1317 ev->target = event->u.selectionNotify.target; 1318 ev->property = event->u.selectionNotify.property; 1319 ev->time = event->u.selectionNotify.time; 1320 } 1321 break; 1322 case ColormapNotify: 1323 { 1324 register XColormapEvent *ev = (XColormapEvent *) re; 1325 ev->window = event->u.colormap.window; 1326 ev->colormap = event->u.colormap.colormap; 1327 ev->new = event->u.colormap.new; 1328 ev->state = event->u.colormap.state; 1329 } 1330 break; 1331 case ClientMessage: 1332 { 1333 register int i; 1334 register XClientMessageEvent *ev 1335 = (XClientMessageEvent *) re; 1336 ev->window = event->u.clientMessage.window; 1337 ev->format = event->u.u.detail; 1338 switch (ev->format) { 1339 case 8: 1340 ev->message_type = event->u.clientMessage.u.b.type; 1341 for (i = 0; i < 20; i++) 1342 ev->data.b[i] = event->u.clientMessage.u.b.bytes[i]; 1343 break; 1344 case 16: 1345 ev->message_type = event->u.clientMessage.u.s.type; 1346 ev->data.s[0] = cvtINT16toShort(event->u.clientMessage.u.s.shorts0); 1347 ev->data.s[1] = cvtINT16toShort(event->u.clientMessage.u.s.shorts1); 1348 ev->data.s[2] = cvtINT16toShort(event->u.clientMessage.u.s.shorts2); 1349 ev->data.s[3] = cvtINT16toShort(event->u.clientMessage.u.s.shorts3); 1350 ev->data.s[4] = cvtINT16toShort(event->u.clientMessage.u.s.shorts4); 1351 ev->data.s[5] = cvtINT16toShort(event->u.clientMessage.u.s.shorts5); 1352 ev->data.s[6] = cvtINT16toShort(event->u.clientMessage.u.s.shorts6); 1353 ev->data.s[7] = cvtINT16toShort(event->u.clientMessage.u.s.shorts7); 1354 ev->data.s[8] = cvtINT16toShort(event->u.clientMessage.u.s.shorts8); 1355 ev->data.s[9] = cvtINT16toShort(event->u.clientMessage.u.s.shorts9); 1356 break; 1357 case 32: 1358 ev->message_type = event->u.clientMessage.u.l.type; 1359 ev->data.l[0] = cvtINT32toLong(event->u.clientMessage.u.l.longs0); 1360 ev->data.l[1] = cvtINT32toLong(event->u.clientMessage.u.l.longs1); 1361 ev->data.l[2] = cvtINT32toLong(event->u.clientMessage.u.l.longs2); 1362 ev->data.l[3] = cvtINT32toLong(event->u.clientMessage.u.l.longs3); 1363 ev->data.l[4] = cvtINT32toLong(event->u.clientMessage.u.l.longs4); 1364 break; 1365 default: /* XXX should never occur */ 1366 break; 1367 } 1368 } 1369 break; 1370 case MappingNotify: 1371 { 1372 register XMappingEvent *ev = (XMappingEvent *)re; 1373 ev->window = 0; 1374 ev->first_keycode = event->u.mappingNotify.firstKeyCode; 1375 ev->request = event->u.mappingNotify.request; 1376 ev->count = event->u.mappingNotify.count; 1377 } 1378 break; 1379 default: 1380 return(_XUnknownWireEvent(dpy, re, event)); 1381 } 1382 return(True); 1383} 1384 1385 1386/* 1387 * _XDefaultIOError - Default fatal system error reporting routine. Called 1388 * when an X internal system error is encountered. 1389 */ 1390int _XDefaultIOError( 1391 Display *dpy) 1392{ 1393 if (ECHECK(EPIPE)) { 1394 (void) fprintf (stderr, 1395 "X connection to %s broken (explicit kill or server shutdown).\r\n", 1396 DisplayString (dpy)); 1397 } else { 1398 (void) fprintf (stderr, 1399 "XIO: fatal IO error %d (%s) on X server \"%s\"\r\n", 1400#ifdef WIN32 1401 WSAGetLastError(), strerror(WSAGetLastError()), 1402#else 1403 errno, strerror (errno), 1404#endif 1405 DisplayString (dpy)); 1406 (void) fprintf (stderr, 1407 " after %lu requests (%lu known processed) with %d events remaining.\r\n", 1408 NextRequest(dpy) - 1, LastKnownRequestProcessed(dpy), 1409 QLength(dpy)); 1410 1411 } 1412 exit(1); 1413 return(0); /* dummy - function should never return */ 1414} 1415 1416 1417static int _XPrintDefaultError( 1418 Display *dpy, 1419 XErrorEvent *event, 1420 FILE *fp) 1421{ 1422 char buffer[BUFSIZ]; 1423 char mesg[BUFSIZ]; 1424 char number[32]; 1425 const char *mtype = "XlibMessage"; 1426 register _XExtension *ext = (_XExtension *)NULL; 1427 _XExtension *bext = (_XExtension *)NULL; 1428 XGetErrorText(dpy, event->error_code, buffer, BUFSIZ); 1429 XGetErrorDatabaseText(dpy, mtype, "XError", "X Error", mesg, BUFSIZ); 1430 (void) fprintf(fp, "%s: %s\n ", mesg, buffer); 1431 XGetErrorDatabaseText(dpy, mtype, "MajorCode", "Request Major code %d", 1432 mesg, BUFSIZ); 1433 (void) fprintf(fp, mesg, event->request_code); 1434 if (event->request_code < 128) { 1435 sprintf(number, "%d", event->request_code); 1436 XGetErrorDatabaseText(dpy, "XRequest", number, "", buffer, BUFSIZ); 1437 } else { 1438 for (ext = dpy->ext_procs; 1439 ext && (ext->codes.major_opcode != event->request_code); 1440 ext = ext->next) 1441 ; 1442 if (ext) { 1443 strncpy(buffer, ext->name, BUFSIZ); 1444 buffer[BUFSIZ - 1] = '\0'; 1445 } else 1446 buffer[0] = '\0'; 1447 } 1448 (void) fprintf(fp, " (%s)\n", buffer); 1449 if (event->request_code >= 128) { 1450 XGetErrorDatabaseText(dpy, mtype, "MinorCode", "Request Minor code %d", 1451 mesg, BUFSIZ); 1452 fputs(" ", fp); 1453 (void) fprintf(fp, mesg, event->minor_code); 1454 if (ext) { 1455 sprintf(mesg, "%s.%d", ext->name, event->minor_code); 1456 XGetErrorDatabaseText(dpy, "XRequest", mesg, "", buffer, BUFSIZ); 1457 (void) fprintf(fp, " (%s)", buffer); 1458 } 1459 fputs("\n", fp); 1460 } 1461 if (event->error_code >= 128) { 1462 /* kludge, try to find the extension that caused it */ 1463 buffer[0] = '\0'; 1464 for (ext = dpy->ext_procs; ext; ext = ext->next) { 1465 if (ext->error_string) 1466 (*ext->error_string)(dpy, event->error_code, &ext->codes, 1467 buffer, BUFSIZ); 1468 if (buffer[0]) { 1469 bext = ext; 1470 break; 1471 } 1472 if (ext->codes.first_error && 1473 ext->codes.first_error < (int)event->error_code && 1474 (!bext || ext->codes.first_error > bext->codes.first_error)) 1475 bext = ext; 1476 } 1477 if (bext) 1478 sprintf(buffer, "%s.%d", bext->name, 1479 event->error_code - bext->codes.first_error); 1480 else 1481 strcpy(buffer, "Value"); 1482 XGetErrorDatabaseText(dpy, mtype, buffer, "", mesg, BUFSIZ); 1483 if (mesg[0]) { 1484 fputs(" ", fp); 1485 (void) fprintf(fp, mesg, event->resourceid); 1486 fputs("\n", fp); 1487 } 1488 /* let extensions try to print the values */ 1489 for (ext = dpy->ext_procs; ext; ext = ext->next) { 1490 if (ext->error_values) 1491 (*ext->error_values)(dpy, event, fp); 1492 } 1493 } else if ((event->error_code == BadWindow) || 1494 (event->error_code == BadPixmap) || 1495 (event->error_code == BadCursor) || 1496 (event->error_code == BadFont) || 1497 (event->error_code == BadDrawable) || 1498 (event->error_code == BadColor) || 1499 (event->error_code == BadGC) || 1500 (event->error_code == BadIDChoice) || 1501 (event->error_code == BadValue) || 1502 (event->error_code == BadAtom)) { 1503 if (event->error_code == BadValue) 1504 XGetErrorDatabaseText(dpy, mtype, "Value", "Value 0x%x", 1505 mesg, BUFSIZ); 1506 else if (event->error_code == BadAtom) 1507 XGetErrorDatabaseText(dpy, mtype, "AtomID", "AtomID 0x%x", 1508 mesg, BUFSIZ); 1509 else 1510 XGetErrorDatabaseText(dpy, mtype, "ResourceID", "ResourceID 0x%x", 1511 mesg, BUFSIZ); 1512 fputs(" ", fp); 1513 (void) fprintf(fp, mesg, event->resourceid); 1514 fputs("\n", fp); 1515 } 1516 XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d", 1517 mesg, BUFSIZ); 1518 fputs(" ", fp); 1519 (void) fprintf(fp, mesg, event->serial); 1520 XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%d", 1521 mesg, BUFSIZ); 1522 fputs("\n ", fp); 1523 (void) fprintf(fp, mesg, dpy->request); 1524 fputs("\n", fp); 1525 if (event->error_code == BadImplementation) return 0; 1526 return 1; 1527} 1528 1529int _XDefaultError( 1530 Display *dpy, 1531 XErrorEvent *event) 1532{ 1533 if (_XPrintDefaultError (dpy, event, stderr) == 0) return 0; 1534 exit(1); 1535 /*NOTREACHED*/ 1536} 1537 1538/*ARGSUSED*/ 1539Bool _XDefaultWireError(Display *display, XErrorEvent *he, xError *we) 1540{ 1541 return True; 1542} 1543 1544/* 1545 * _XError - upcall internal or user protocol error handler 1546 */ 1547int _XError ( 1548 Display *dpy, 1549 register xError *rep) 1550{ 1551 /* 1552 * X_Error packet encountered! We need to unpack the error before 1553 * giving it to the user. 1554 */ 1555 XEvent event; /* make it a large event */ 1556 register _XAsyncHandler *async, *next; 1557 1558 event.xerror.serial = _XSetLastRequestRead(dpy, (xGenericReply *)rep); 1559 1560 for (async = dpy->async_handlers; async; async = next) { 1561 next = async->next; 1562 if ((*async->handler)(dpy, (xReply *)rep, 1563 (char *)rep, SIZEOF(xError), async->data)) 1564 return 0; 1565 } 1566 1567 event.xerror.display = dpy; 1568 event.xerror.type = X_Error; 1569 event.xerror.resourceid = rep->resourceID; 1570 event.xerror.error_code = rep->errorCode; 1571 event.xerror.request_code = rep->majorCode; 1572 event.xerror.minor_code = rep->minorCode; 1573 if (dpy->error_vec && 1574 !(*dpy->error_vec[rep->errorCode])(dpy, &event.xerror, rep)) 1575 return 0; 1576 if (_XErrorFunction != NULL) { 1577 int rtn_val; 1578#ifdef XTHREADS 1579 if (dpy->lock) 1580 (*dpy->lock->user_lock_display)(dpy); 1581 UnlockDisplay(dpy); 1582#endif 1583 rtn_val = (*_XErrorFunction)(dpy, (XErrorEvent *)&event); /* upcall */ 1584#ifdef XTHREADS 1585 LockDisplay(dpy); 1586 if (dpy->lock) 1587 (*dpy->lock->user_unlock_display)(dpy); 1588#endif 1589 return rtn_val; 1590 } else { 1591 return _XDefaultError(dpy, (XErrorEvent *)&event); 1592 } 1593} 1594 1595/* 1596 * _XIOError - call user connection error handler and exit 1597 */ 1598int 1599_XIOError ( 1600 Display *dpy) 1601{ 1602 dpy->flags |= XlibDisplayIOError; 1603#ifdef WIN32 1604 errno = WSAGetLastError(); 1605#endif 1606 1607 /* This assumes that the thread calling exit will call any atexit handlers. 1608 * If this does not hold, then an alternate solution would involve 1609 * registering an atexit handler to take over the lock, which would only 1610 * assume that the same thread calls all the atexit handlers. */ 1611#ifdef XTHREADS 1612 if (dpy->lock) 1613 (*dpy->lock->user_lock_display)(dpy); 1614#endif 1615 UnlockDisplay(dpy); 1616 1617 if (_XIOErrorFunction != NULL) 1618 (*_XIOErrorFunction)(dpy); 1619 else 1620 _XDefaultIOError(dpy); 1621 exit (1); 1622 return 0; 1623} 1624 1625 1626/* 1627 * This routine can be used to (cheaply) get some memory within a single 1628 * Xlib routine for scratch space. A single buffer is reused each time 1629 * if possible. To be MT safe, you can only call this between a call to 1630 * GetReq* and a call to Data* or _XSend*, or in a context when the thread 1631 * is guaranteed to not unlock the display. 1632 */ 1633char *_XAllocScratch( 1634 register Display *dpy, 1635 unsigned long nbytes) 1636{ 1637 if (nbytes > dpy->scratch_length) { 1638 if (dpy->scratch_buffer) Xfree (dpy->scratch_buffer); 1639 if ((dpy->scratch_buffer = Xmalloc((unsigned) nbytes))) 1640 dpy->scratch_length = nbytes; 1641 else dpy->scratch_length = 0; 1642 } 1643 return (dpy->scratch_buffer); 1644} 1645 1646/* 1647 * Scratch space allocator you can call any time, multiple times, and be 1648 * MT safe, but you must hand the buffer back with _XFreeTemp. 1649 */ 1650char *_XAllocTemp( 1651 register Display *dpy, 1652 unsigned long nbytes) 1653{ 1654 char *buf; 1655 1656 buf = _XAllocScratch(dpy, nbytes); 1657 dpy->scratch_buffer = NULL; 1658 dpy->scratch_length = 0; 1659 return buf; 1660} 1661 1662void _XFreeTemp( 1663 register Display *dpy, 1664 char *buf, 1665 unsigned long nbytes) 1666{ 1667 if (dpy->scratch_buffer) 1668 Xfree(dpy->scratch_buffer); 1669 dpy->scratch_buffer = buf; 1670 dpy->scratch_length = nbytes; 1671} 1672 1673/* 1674 * Given a visual id, find the visual structure for this id on this display. 1675 */ 1676Visual *_XVIDtoVisual( 1677 Display *dpy, 1678 VisualID id) 1679{ 1680 register int i, j, k; 1681 register Screen *sp; 1682 register Depth *dp; 1683 register Visual *vp; 1684 for (i = 0; i < dpy->nscreens; i++) { 1685 sp = &dpy->screens[i]; 1686 for (j = 0; j < sp->ndepths; j++) { 1687 dp = &sp->depths[j]; 1688 /* if nvisuals == 0 then visuals will be NULL */ 1689 for (k = 0; k < dp->nvisuals; k++) { 1690 vp = &dp->visuals[k]; 1691 if (vp->visualid == id) return (vp); 1692 } 1693 } 1694 } 1695 return (NULL); 1696} 1697 1698int 1699XFree (void *data) 1700{ 1701 Xfree (data); 1702 return 1; 1703} 1704 1705#ifdef _XNEEDBCOPYFUNC 1706void _Xbcopy(b1, b2, length) 1707 register char *b1, *b2; 1708 register length; 1709{ 1710 if (b1 < b2) { 1711 b2 += length; 1712 b1 += length; 1713 while (length--) 1714 *--b2 = *--b1; 1715 } else { 1716 while (length--) 1717 *b2++ = *b1++; 1718 } 1719} 1720#endif 1721 1722#ifdef DataRoutineIsProcedure 1723void Data( 1724 Display *dpy, 1725 char *data, 1726 long len) 1727{ 1728 if (dpy->bufptr + (len) <= dpy->bufmax) { 1729 memcpy(dpy->bufptr, data, (int)len); 1730 dpy->bufptr += ((len) + 3) & ~3; 1731 } else { 1732 _XSend(dpy, data, len); 1733 } 1734} 1735#endif /* DataRoutineIsProcedure */ 1736 1737 1738#ifdef LONG64 1739int 1740_XData32( 1741 Display *dpy, 1742 register long *data, 1743 unsigned len) 1744{ 1745 register int *buf; 1746 register long i; 1747 1748 while (len) { 1749 buf = (int *)dpy->bufptr; 1750 i = dpy->bufmax - (char *)buf; 1751 if (!i) { 1752 _XFlush(dpy); 1753 continue; 1754 } 1755 if (len < i) 1756 i = len; 1757 dpy->bufptr = (char *)buf + i; 1758 len -= i; 1759 i >>= 2; 1760 while (--i >= 0) 1761 *buf++ = *data++; 1762 } 1763 return 0; 1764} 1765#endif /* LONG64 */ 1766 1767#ifdef WORD64 1768 1769/* 1770 * XXX This is a *really* stupid way of doing this. It should just use 1771 * dpy->bufptr directly, taking into account where in the word it is. 1772 */ 1773 1774/* 1775 * Data16 - Place 16 bit data in the buffer. 1776 * 1777 * "dpy" is a pointer to a Display. 1778 * "data" is a pointer to the data. 1779 * "len" is the length in bytes of the data. 1780 */ 1781 1782static doData16( 1783 register Display *dpy, 1784 short *data, 1785 unsigned len, 1786 char *packbuffer) 1787{ 1788 long *lp,*lpack; 1789 long i, nwords,bits; 1790 long mask16 = 0x000000000000ffff; 1791 1792 lp = (long *)data; 1793 lpack = (long *)packbuffer; 1794 1795/* nwords is the number of 16 bit values to be packed, 1796 * the low order 16 bits of each word will be packed 1797 * into 64 bit words 1798 */ 1799 nwords = len >> 1; 1800 bits = 48; 1801 1802 for(i=0;i<nwords;i++){ 1803 if (bits == 48) *lpack = 0; 1804 *lpack ^= (*lp & mask16) << bits; 1805 bits -= 16 ; 1806 lp++; 1807 if(bits < 0){ 1808 lpack++; 1809 bits = 48; 1810 } 1811 } 1812 Data(dpy, packbuffer, len); 1813} 1814 1815_XData16 ( 1816 Display *dpy, 1817 short *data, 1818 unsigned len) 1819{ 1820 char packbuffer[PACKBUFFERSIZE]; 1821 unsigned nunits = PACKBUFFERSIZE >> 1; 1822 1823 for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) { 1824 doData16 (dpy, data, PACKBUFFERSIZE, packbuffer); 1825 } 1826 if (len) doData16 (dpy, data, len, packbuffer); 1827} 1828 1829/* 1830 * Data32 - Place 32 bit data in the buffer. 1831 * 1832 * "dpy" is a pointer to a Display. 1833 * "data" is a pointer to the data. 1834 * "len" is the length in bytes of the data. 1835 */ 1836 1837static doData32( 1838 register Display *dpy 1839 long *data, 1840 unsigned len, 1841 char *packbuffer) 1842{ 1843 long *lp,*lpack; 1844 long i,bits,nwords; 1845 long mask32 = 0x00000000ffffffff; 1846 1847 lpack = (long *) packbuffer; 1848 lp = data; 1849 1850/* nwords is the number of 32 bit values to be packed 1851 * the low order 32 bits of each word will be packed 1852 * into 64 bit words 1853 */ 1854 nwords = len >> 2; 1855 bits = 32; 1856 1857 for(i=0;i<nwords;i++){ 1858 if (bits == 32) *lpack = 0; 1859 *lpack ^= (*lp & mask32) << bits; 1860 bits = bits ^32; 1861 lp++; 1862 if(bits) 1863 lpack++; 1864 } 1865 Data(dpy, packbuffer, len); 1866} 1867 1868void _XData32( 1869 Display *dpy, 1870 long *data, 1871 unsigned len) 1872{ 1873 char packbuffer[PACKBUFFERSIZE]; 1874 unsigned nunits = PACKBUFFERSIZE >> 2; 1875 1876 for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) { 1877 doData32 (dpy, data, PACKBUFFERSIZE, packbuffer); 1878 } 1879 if (len) doData32 (dpy, data, len, packbuffer); 1880} 1881 1882#endif /* WORD64 */ 1883 1884 1885/* Make sure this produces the same string as DefineLocal/DefineSelf in xdm. 1886 * Otherwise, Xau will not be able to find your cookies in the Xauthority file. 1887 * 1888 * Note: POSIX says that the ``nodename'' member of utsname does _not_ have 1889 * to have sufficient information for interfacing to the network, 1890 * and so, you may be better off using gethostname (if it exists). 1891 */ 1892 1893#if (defined(_POSIX_SOURCE) && !defined(AIXV3) && !defined(__QNX__)) || defined(hpux) || defined(SVR4) 1894#define NEED_UTSNAME 1895#include <sys/utsname.h> 1896#else 1897#ifdef HAVE_UNISTD_H 1898#include <unistd.h> 1899#endif 1900#endif 1901 1902/* 1903 * _XGetHostname - similar to gethostname but allows special processing. 1904 */ 1905int _XGetHostname ( 1906 char *buf, 1907 int maxlen) 1908{ 1909 int len; 1910 1911#ifdef NEED_UTSNAME 1912 struct utsname name; 1913 1914 if (maxlen <= 0 || buf == NULL) 1915 return 0; 1916 1917 uname (&name); 1918 len = strlen (name.nodename); 1919 if (len >= maxlen) len = maxlen - 1; 1920 strncpy (buf, name.nodename, len); 1921 buf[len] = '\0'; 1922#else 1923 if (maxlen <= 0 || buf == NULL) 1924 return 0; 1925 1926 buf[0] = '\0'; 1927 (void) gethostname (buf, maxlen); 1928 buf [maxlen - 1] = '\0'; 1929 len = strlen(buf); 1930#endif /* NEED_UTSNAME */ 1931 return len; 1932} 1933 1934 1935/* 1936 * _XScreenOfWindow - get the Screen of a given window 1937 */ 1938 1939Screen *_XScreenOfWindow(Display *dpy, Window w) 1940{ 1941 register int i; 1942 Window root; 1943 int x, y; /* dummy variables */ 1944 unsigned int width, height, bw, depth; /* dummy variables */ 1945 1946 if (XGetGeometry (dpy, w, &root, &x, &y, &width, &height, 1947 &bw, &depth) == False) { 1948 return NULL; 1949 } 1950 for (i = 0; i < ScreenCount (dpy); i++) { /* find root from list */ 1951 if (root == RootWindow (dpy, i)) { 1952 return ScreenOfDisplay (dpy, i); 1953 } 1954 } 1955 return NULL; 1956} 1957 1958 1959#if defined(WIN32) 1960 1961/* 1962 * These functions are intended to be used internally to Xlib only. 1963 * These functions will always prefix the path with a DOS drive in the 1964 * form "<drive-letter>:". As such, these functions are only suitable 1965 * for use by Xlib function that supply a root-based path to some 1966 * particular file, e.g. <ProjectRoot>/lib/X11/locale/locale.dir will 1967 * be converted to "C:/usr/X11R6.3/lib/X11/locale/locale.dir". 1968 */ 1969 1970static int access_file (path, pathbuf, len_pathbuf, pathret) 1971 char* path; 1972 char* pathbuf; 1973 int len_pathbuf; 1974 char** pathret; 1975{ 1976 if (access (path, F_OK) == 0) { 1977 if (strlen (path) < len_pathbuf) 1978 *pathret = pathbuf; 1979 else 1980 *pathret = Xmalloc (strlen (path) + 1); 1981 if (*pathret) { 1982 strcpy (*pathret, path); 1983 return 1; 1984 } 1985 } 1986 return 0; 1987} 1988 1989static int AccessFile (path, pathbuf, len_pathbuf, pathret) 1990 char* path; 1991 char* pathbuf; 1992 int len_pathbuf; 1993 char** pathret; 1994{ 1995 unsigned long drives; 1996 int i, len; 1997 char* drive; 1998 char buf[MAX_PATH]; 1999 char* bufp; 2000 2001 /* just try the "raw" name first and see if it works */ 2002 if (access_file (path, pathbuf, len_pathbuf, pathret)) 2003 return 1; 2004 2005 /* try the places set in the environment */ 2006 drive = getenv ("_XBASEDRIVE"); 2007#ifdef __UNIXOS2__ 2008 if (!drive) 2009 drive = getenv ("X11ROOT"); 2010#endif 2011 if (!drive) 2012 drive = "C:"; 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#ifndef __UNIXOS2__ 2024 /* one last place to look */ 2025 drive = getenv ("HOMEDRIVE"); 2026 if (drive) { 2027 len = strlen (drive) + strlen (path); 2028 if (len < MAX_PATH) bufp = buf; 2029 else bufp = Xmalloc (len + 1); 2030 strcpy (bufp, drive); 2031 strcat (bufp, path); 2032 if (access_file (bufp, pathbuf, len_pathbuf, pathret)) { 2033 if (bufp != buf) Xfree (bufp); 2034 return 1; 2035 } 2036 } 2037 2038 /* tried everywhere else, go fishing */ 2039#define C_DRIVE ('C' - 'A') 2040#define Z_DRIVE ('Z' - 'A') 2041 /* does OS/2 (with or with gcc-emx) have getdrives? */ 2042 drives = _getdrives (); 2043 for (i = C_DRIVE; i <= Z_DRIVE; i++) { /* don't check on A: or B: */ 2044 if ((1 << i) & drives) { 2045 len = 2 + strlen (path); 2046 if (len < MAX_PATH) bufp = buf; 2047 else bufp = Xmalloc (len + 1); 2048 *bufp = 'A' + i; 2049 *(bufp + 1) = ':'; 2050 *(bufp + 2) = '\0'; 2051 strcat (bufp, path); 2052 if (access_file (bufp, pathbuf, len_pathbuf, pathret)) { 2053 if (bufp != buf) Xfree (bufp); 2054 return 1; 2055 } 2056 } 2057 } 2058#endif 2059 return 0; 2060} 2061 2062int _XOpenFile(path, flags) 2063 _Xconst char* path; 2064 int flags; 2065{ 2066 char buf[MAX_PATH]; 2067 char* bufp = NULL; 2068 int ret = -1; 2069 UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS); 2070 2071 if (AccessFile (path, buf, MAX_PATH, &bufp)) 2072 ret = open (bufp, flags); 2073 2074 (void) SetErrorMode (olderror); 2075 2076 if (bufp != buf) Xfree (bufp); 2077 2078 return ret; 2079} 2080 2081int _XOpenFileMode(path, flags, mode) 2082 _Xconst char* path; 2083 int flags; 2084 mode_t mode; 2085{ 2086 char buf[MAX_PATH]; 2087 char* bufp = NULL; 2088 int ret = -1; 2089 UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS); 2090 2091 if (AccessFile (path, buf, MAX_PATH, &bufp)) 2092 ret = open (bufp, flags, mode); 2093 2094 (void) SetErrorMode (olderror); 2095 2096 if (bufp != buf) Xfree (bufp); 2097 2098 return ret; 2099} 2100 2101void* _XFopenFile(path, mode) 2102 _Xconst char* path; 2103 _Xconst char* mode; 2104{ 2105 char buf[MAX_PATH]; 2106 char* bufp = NULL; 2107 void* ret = NULL; 2108 UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS); 2109 2110 if (AccessFile (path, buf, MAX_PATH, &bufp)) 2111 ret = fopen (bufp, mode); 2112 2113 (void) SetErrorMode (olderror); 2114 2115 if (bufp != buf) Xfree (bufp); 2116 2117 return ret; 2118} 2119 2120int _XAccessFile(path) 2121 _Xconst char* path; 2122{ 2123 char buf[MAX_PATH]; 2124 char* bufp; 2125 int ret = -1; 2126 UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS); 2127 2128 ret = AccessFile (path, buf, MAX_PATH, &bufp); 2129 2130 (void) SetErrorMode (olderror); 2131 2132 if (bufp != buf) Xfree (bufp); 2133 2134 return ret; 2135} 2136 2137#endif 2138 2139#ifdef WIN32 2140#undef _Xdebug 2141int _Xdebug = 0; 2142int *_Xdebug_p = &_Xdebug; 2143void (**_XCreateMutex_fn_p)(LockInfoPtr) = &_XCreateMutex_fn; 2144void (**_XFreeMutex_fn_p)(LockInfoPtr) = &_XFreeMutex_fn; 2145void (**_XLockMutex_fn_p)(LockInfoPtr 2146#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE) 2147 , char * /* file */ 2148 , int /* line */ 2149#endif 2150 ) = &_XLockMutex_fn; 2151void (**_XUnlockMutex_fn_p)(LockInfoPtr 2152#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE) 2153 , char * /* file */ 2154 , int /* line */ 2155#endif 2156 ) = &_XUnlockMutex_fn; 2157LockInfoPtr *_Xglobal_lock_p = &_Xglobal_lock; 2158#endif 2159