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