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