XlibInt.c revision f2d49d05
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 ">=" comparision 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 register 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 if (dpy->cookiejar == e) 654 dpy->cookiejar = NULL; 655 XFree(e->ev.data); 656 XFree(e); 657 } 658} 659 660/** 661 * Add an event to the display's event list. This event must be freed on the 662 * next call to XNextEvent(). 663 */ 664void 665_XStoreEventCookie(Display *dpy, XEvent *event) 666{ 667 XGenericEventCookie* cookie = &event->xcookie; 668 struct stored_event **head, *add; 669 670 if (!_XIsEventCookie(dpy, event)) 671 return; 672 673 head = (struct stored_event**)(&dpy->cookiejar); 674 675 add = Xmalloc(sizeof(struct stored_event)); 676 if (!add) { 677 ESET(ENOMEM); 678 _XIOError(dpy); 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 } 754 qelt->next = NULL; 755 756 type = event->u.u.type & 0177; 757 extension = ((xGenericEvent*)event)->extension; 758 759 qelt->event.type = type; 760 /* If an extension has registered a generic_event_vec handler, then 761 * it can handle event cookies. Otherwise, proceed with the normal 762 * event handlers. 763 * 764 * If the generic_event_vec is called, qelt->event is a event cookie 765 * with the data pointer and the "free" pointer set. Data pointer is 766 * some memory allocated by the extension. 767 */ 768 if (type == GenericEvent && dpy->generic_event_vec[extension & 0x7F]) { 769 XGenericEventCookie *cookie = &qelt->event.xcookie; 770 (*dpy->generic_event_vec[extension & 0x7F])(dpy, cookie, event); 771 cookie->cookie = ++dpy->next_cookie; 772 773 qelt->qserial_num = dpy->next_event_serial_num++; 774 if (dpy->tail) dpy->tail->next = qelt; 775 else dpy->head = qelt; 776 777 dpy->tail = qelt; 778 dpy->qlen++; 779 } else if ((*dpy->event_vec[type])(dpy, &qelt->event, event)) { 780 qelt->qserial_num = dpy->next_event_serial_num++; 781 if (dpy->tail) dpy->tail->next = qelt; 782 else dpy->head = qelt; 783 784 dpy->tail = qelt; 785 dpy->qlen++; 786 } else { 787 /* ignored, or stashed away for many-to-one compression */ 788 qelt->next = dpy->qfree; 789 dpy->qfree = qelt; 790 } 791} 792 793/* 794 * _XDeq - Remove event packet from the display's queue. 795 */ 796void _XDeq( 797 register Display *dpy, 798 register _XQEvent *prev, /* element before qelt */ 799 register _XQEvent *qelt) /* element to be unlinked */ 800{ 801 if (prev) { 802 if ((prev->next = qelt->next) == NULL) 803 dpy->tail = prev; 804 } else { 805 /* no prev, so removing first elt */ 806 if ((dpy->head = qelt->next) == NULL) 807 dpy->tail = NULL; 808 } 809 qelt->qserial_num = 0; 810 qelt->next = dpy->qfree; 811 dpy->qfree = qelt; 812 dpy->qlen--; 813 814 if (_XIsEventCookie(dpy, &qelt->event)) { 815 XGenericEventCookie* cookie = &qelt->event.xcookie; 816 /* dpy->qfree is re-used, reset memory to avoid double free on 817 * _XFreeDisplayStructure */ 818 cookie->data = NULL; 819 } 820} 821 822/* 823 * EventToWire in separate file in that often not needed. 824 */ 825 826/*ARGSUSED*/ 827Bool 828_XUnknownWireEvent( 829 register Display *dpy, /* pointer to display structure */ 830 register XEvent *re, /* pointer to where event should be reformatted */ 831 register xEvent *event) /* wire protocol event */ 832{ 833#ifdef notdef 834 (void) fprintf(stderr, 835 "Xlib: unhandled wire event! event number = %d, display = %x\n.", 836 event->u.u.type, dpy); 837#endif 838 return(False); 839} 840 841Bool 842_XUnknownWireEventCookie( 843 Display *dpy, /* pointer to display structure */ 844 XGenericEventCookie *re, /* pointer to where event should be reformatted */ 845 xEvent *event) /* wire protocol event */ 846{ 847#ifdef notdef 848 fprintf(stderr, 849 "Xlib: unhandled wire cookie event! extension number = %d, display = %x\n.", 850 ((xGenericEvent*)event)->extension, dpy); 851#endif 852 return(False); 853} 854 855Bool 856_XUnknownCopyEventCookie( 857 Display *dpy, /* pointer to display structure */ 858 XGenericEventCookie *in, /* source */ 859 XGenericEventCookie *out) /* destination */ 860{ 861#ifdef notdef 862 fprintf(stderr, 863 "Xlib: unhandled cookie event copy! extension number = %d, display = %x\n.", 864 in->extension, dpy); 865#endif 866 return(False); 867} 868 869/*ARGSUSED*/ 870Status 871_XUnknownNativeEvent( 872 register Display *dpy, /* pointer to display structure */ 873 register XEvent *re, /* pointer to where event should be reformatted */ 874 register xEvent *event) /* wire protocol event */ 875{ 876#ifdef notdef 877 (void) fprintf(stderr, 878 "Xlib: unhandled native event! event number = %d, display = %x\n.", 879 re->type, dpy); 880#endif 881 return(0); 882} 883/* 884 * reformat a wire event into an XEvent structure of the right type. 885 */ 886Bool 887_XWireToEvent( 888 register Display *dpy, /* pointer to display structure */ 889 register XEvent *re, /* pointer to where event should be reformatted */ 890 register xEvent *event) /* wire protocol event */ 891{ 892 893 re->type = event->u.u.type & 0x7f; 894 ((XAnyEvent *)re)->serial = _XSetLastRequestRead(dpy, 895 (xGenericReply *)event); 896 ((XAnyEvent *)re)->send_event = ((event->u.u.type & 0x80) != 0); 897 ((XAnyEvent *)re)->display = dpy; 898 899 /* Ignore the leading bit of the event type since it is set when a 900 client sends an event rather than the server. */ 901 902 switch (event-> u.u.type & 0177) { 903 case KeyPress: 904 case KeyRelease: 905 { 906 register XKeyEvent *ev = (XKeyEvent*) re; 907 ev->root = event->u.keyButtonPointer.root; 908 ev->window = event->u.keyButtonPointer.event; 909 ev->subwindow = event->u.keyButtonPointer.child; 910 ev->time = event->u.keyButtonPointer.time; 911 ev->x = cvtINT16toInt(event->u.keyButtonPointer.eventX); 912 ev->y = cvtINT16toInt(event->u.keyButtonPointer.eventY); 913 ev->x_root = cvtINT16toInt(event->u.keyButtonPointer.rootX); 914 ev->y_root = cvtINT16toInt(event->u.keyButtonPointer.rootY); 915 ev->state = event->u.keyButtonPointer.state; 916 ev->same_screen = event->u.keyButtonPointer.sameScreen; 917 ev->keycode = event->u.u.detail; 918 } 919 break; 920 case ButtonPress: 921 case ButtonRelease: 922 { 923 register XButtonEvent *ev = (XButtonEvent *) re; 924 ev->root = event->u.keyButtonPointer.root; 925 ev->window = event->u.keyButtonPointer.event; 926 ev->subwindow = event->u.keyButtonPointer.child; 927 ev->time = event->u.keyButtonPointer.time; 928 ev->x = cvtINT16toInt(event->u.keyButtonPointer.eventX); 929 ev->y = cvtINT16toInt(event->u.keyButtonPointer.eventY); 930 ev->x_root = cvtINT16toInt(event->u.keyButtonPointer.rootX); 931 ev->y_root = cvtINT16toInt(event->u.keyButtonPointer.rootY); 932 ev->state = event->u.keyButtonPointer.state; 933 ev->same_screen = event->u.keyButtonPointer.sameScreen; 934 ev->button = event->u.u.detail; 935 } 936 break; 937 case MotionNotify: 938 { 939 register XMotionEvent *ev = (XMotionEvent *)re; 940 ev->root = event->u.keyButtonPointer.root; 941 ev->window = event->u.keyButtonPointer.event; 942 ev->subwindow = event->u.keyButtonPointer.child; 943 ev->time = event->u.keyButtonPointer.time; 944 ev->x = cvtINT16toInt(event->u.keyButtonPointer.eventX); 945 ev->y = cvtINT16toInt(event->u.keyButtonPointer.eventY); 946 ev->x_root = cvtINT16toInt(event->u.keyButtonPointer.rootX); 947 ev->y_root = cvtINT16toInt(event->u.keyButtonPointer.rootY); 948 ev->state = event->u.keyButtonPointer.state; 949 ev->same_screen = event->u.keyButtonPointer.sameScreen; 950 ev->is_hint = event->u.u.detail; 951 } 952 break; 953 case EnterNotify: 954 case LeaveNotify: 955 { 956 register XCrossingEvent *ev = (XCrossingEvent *) re; 957 ev->root = event->u.enterLeave.root; 958 ev->window = event->u.enterLeave.event; 959 ev->subwindow = event->u.enterLeave.child; 960 ev->time = event->u.enterLeave.time; 961 ev->x = cvtINT16toInt(event->u.enterLeave.eventX); 962 ev->y = cvtINT16toInt(event->u.enterLeave.eventY); 963 ev->x_root = cvtINT16toInt(event->u.enterLeave.rootX); 964 ev->y_root = cvtINT16toInt(event->u.enterLeave.rootY); 965 ev->state = event->u.enterLeave.state; 966 ev->mode = event->u.enterLeave.mode; 967 ev->same_screen = (event->u.enterLeave.flags & 968 ELFlagSameScreen) && True; 969 ev->focus = (event->u.enterLeave.flags & 970 ELFlagFocus) && True; 971 ev->detail = event->u.u.detail; 972 } 973 break; 974 case FocusIn: 975 case FocusOut: 976 { 977 register XFocusChangeEvent *ev = (XFocusChangeEvent *) re; 978 ev->window = event->u.focus.window; 979 ev->mode = event->u.focus.mode; 980 ev->detail = event->u.u.detail; 981 } 982 break; 983 case KeymapNotify: 984 { 985 register XKeymapEvent *ev = (XKeymapEvent *) re; 986 ev->window = None; 987 memcpy(&ev->key_vector[1], 988 (char *)((xKeymapEvent *) event)->map, 989 sizeof (((xKeymapEvent *) event)->map)); 990 } 991 break; 992 case Expose: 993 { 994 register XExposeEvent *ev = (XExposeEvent *) re; 995 ev->window = event->u.expose.window; 996 ev->x = event->u.expose.x; 997 ev->y = event->u.expose.y; 998 ev->width = event->u.expose.width; 999 ev->height = event->u.expose.height; 1000 ev->count = event->u.expose.count; 1001 } 1002 break; 1003 case GraphicsExpose: 1004 { 1005 register XGraphicsExposeEvent *ev = 1006 (XGraphicsExposeEvent *) re; 1007 ev->drawable = event->u.graphicsExposure.drawable; 1008 ev->x = event->u.graphicsExposure.x; 1009 ev->y = event->u.graphicsExposure.y; 1010 ev->width = event->u.graphicsExposure.width; 1011 ev->height = event->u.graphicsExposure.height; 1012 ev->count = event->u.graphicsExposure.count; 1013 ev->major_code = event->u.graphicsExposure.majorEvent; 1014 ev->minor_code = event->u.graphicsExposure.minorEvent; 1015 } 1016 break; 1017 case NoExpose: 1018 { 1019 register XNoExposeEvent *ev = (XNoExposeEvent *) re; 1020 ev->drawable = event->u.noExposure.drawable; 1021 ev->major_code = event->u.noExposure.majorEvent; 1022 ev->minor_code = event->u.noExposure.minorEvent; 1023 } 1024 break; 1025 case VisibilityNotify: 1026 { 1027 register XVisibilityEvent *ev = (XVisibilityEvent *) re; 1028 ev->window = event->u.visibility.window; 1029 ev->state = event->u.visibility.state; 1030 } 1031 break; 1032 case CreateNotify: 1033 { 1034 register XCreateWindowEvent *ev = 1035 (XCreateWindowEvent *) re; 1036 ev->window = event->u.createNotify.window; 1037 ev->parent = event->u.createNotify.parent; 1038 ev->x = cvtINT16toInt(event->u.createNotify.x); 1039 ev->y = cvtINT16toInt(event->u.createNotify.y); 1040 ev->width = event->u.createNotify.width; 1041 ev->height = event->u.createNotify.height; 1042 ev->border_width = event->u.createNotify.borderWidth; 1043 ev->override_redirect = event->u.createNotify.override; 1044 } 1045 break; 1046 case DestroyNotify: 1047 { 1048 register XDestroyWindowEvent *ev = 1049 (XDestroyWindowEvent *) re; 1050 ev->window = event->u.destroyNotify.window; 1051 ev->event = event->u.destroyNotify.event; 1052 } 1053 break; 1054 case UnmapNotify: 1055 { 1056 register XUnmapEvent *ev = (XUnmapEvent *) re; 1057 ev->window = event->u.unmapNotify.window; 1058 ev->event = event->u.unmapNotify.event; 1059 ev->from_configure = event->u.unmapNotify.fromConfigure; 1060 } 1061 break; 1062 case MapNotify: 1063 { 1064 register XMapEvent *ev = (XMapEvent *) re; 1065 ev->window = event->u.mapNotify.window; 1066 ev->event = event->u.mapNotify.event; 1067 ev->override_redirect = event->u.mapNotify.override; 1068 } 1069 break; 1070 case MapRequest: 1071 { 1072 register XMapRequestEvent *ev = (XMapRequestEvent *) re; 1073 ev->window = event->u.mapRequest.window; 1074 ev->parent = event->u.mapRequest.parent; 1075 } 1076 break; 1077 case ReparentNotify: 1078 { 1079 register XReparentEvent *ev = (XReparentEvent *) re; 1080 ev->event = event->u.reparent.event; 1081 ev->window = event->u.reparent.window; 1082 ev->parent = event->u.reparent.parent; 1083 ev->x = cvtINT16toInt(event->u.reparent.x); 1084 ev->y = cvtINT16toInt(event->u.reparent.y); 1085 ev->override_redirect = event->u.reparent.override; 1086 } 1087 break; 1088 case ConfigureNotify: 1089 { 1090 register XConfigureEvent *ev = (XConfigureEvent *) re; 1091 ev->event = event->u.configureNotify.event; 1092 ev->window = event->u.configureNotify.window; 1093 ev->above = event->u.configureNotify.aboveSibling; 1094 ev->x = cvtINT16toInt(event->u.configureNotify.x); 1095 ev->y = cvtINT16toInt(event->u.configureNotify.y); 1096 ev->width = event->u.configureNotify.width; 1097 ev->height = event->u.configureNotify.height; 1098 ev->border_width = event->u.configureNotify.borderWidth; 1099 ev->override_redirect = event->u.configureNotify.override; 1100 } 1101 break; 1102 case ConfigureRequest: 1103 { 1104 register XConfigureRequestEvent *ev = 1105 (XConfigureRequestEvent *) re; 1106 ev->window = event->u.configureRequest.window; 1107 ev->parent = event->u.configureRequest.parent; 1108 ev->above = event->u.configureRequest.sibling; 1109 ev->x = cvtINT16toInt(event->u.configureRequest.x); 1110 ev->y = cvtINT16toInt(event->u.configureRequest.y); 1111 ev->width = event->u.configureRequest.width; 1112 ev->height = event->u.configureRequest.height; 1113 ev->border_width = event->u.configureRequest.borderWidth; 1114 ev->value_mask = event->u.configureRequest.valueMask; 1115 ev->detail = event->u.u.detail; 1116 } 1117 break; 1118 case GravityNotify: 1119 { 1120 register XGravityEvent *ev = (XGravityEvent *) re; 1121 ev->window = event->u.gravity.window; 1122 ev->event = event->u.gravity.event; 1123 ev->x = cvtINT16toInt(event->u.gravity.x); 1124 ev->y = cvtINT16toInt(event->u.gravity.y); 1125 } 1126 break; 1127 case ResizeRequest: 1128 { 1129 register XResizeRequestEvent *ev = 1130 (XResizeRequestEvent *) re; 1131 ev->window = event->u.resizeRequest.window; 1132 ev->width = event->u.resizeRequest.width; 1133 ev->height = event->u.resizeRequest.height; 1134 } 1135 break; 1136 case CirculateNotify: 1137 { 1138 register XCirculateEvent *ev = (XCirculateEvent *) re; 1139 ev->window = event->u.circulate.window; 1140 ev->event = event->u.circulate.event; 1141 ev->place = event->u.circulate.place; 1142 } 1143 break; 1144 case CirculateRequest: 1145 { 1146 register XCirculateRequestEvent *ev = 1147 (XCirculateRequestEvent *) re; 1148 ev->window = event->u.circulate.window; 1149 ev->parent = event->u.circulate.event; 1150 ev->place = event->u.circulate.place; 1151 } 1152 break; 1153 case PropertyNotify: 1154 { 1155 register XPropertyEvent *ev = (XPropertyEvent *) re; 1156 ev->window = event->u.property.window; 1157 ev->atom = event->u.property.atom; 1158 ev->time = event->u.property.time; 1159 ev->state = event->u.property.state; 1160 } 1161 break; 1162 case SelectionClear: 1163 { 1164 register XSelectionClearEvent *ev = 1165 (XSelectionClearEvent *) re; 1166 ev->window = event->u.selectionClear.window; 1167 ev->selection = event->u.selectionClear.atom; 1168 ev->time = event->u.selectionClear.time; 1169 } 1170 break; 1171 case SelectionRequest: 1172 { 1173 register XSelectionRequestEvent *ev = 1174 (XSelectionRequestEvent *) re; 1175 ev->owner = event->u.selectionRequest.owner; 1176 ev->requestor = event->u.selectionRequest.requestor; 1177 ev->selection = event->u.selectionRequest.selection; 1178 ev->target = event->u.selectionRequest.target; 1179 ev->property = event->u.selectionRequest.property; 1180 ev->time = event->u.selectionRequest.time; 1181 } 1182 break; 1183 case SelectionNotify: 1184 { 1185 register XSelectionEvent *ev = (XSelectionEvent *) re; 1186 ev->requestor = event->u.selectionNotify.requestor; 1187 ev->selection = event->u.selectionNotify.selection; 1188 ev->target = event->u.selectionNotify.target; 1189 ev->property = event->u.selectionNotify.property; 1190 ev->time = event->u.selectionNotify.time; 1191 } 1192 break; 1193 case ColormapNotify: 1194 { 1195 register XColormapEvent *ev = (XColormapEvent *) re; 1196 ev->window = event->u.colormap.window; 1197 ev->colormap = event->u.colormap.colormap; 1198 ev->new = event->u.colormap.new; 1199 ev->state = event->u.colormap.state; 1200 } 1201 break; 1202 case ClientMessage: 1203 { 1204 register int i; 1205 register XClientMessageEvent *ev 1206 = (XClientMessageEvent *) re; 1207 ev->window = event->u.clientMessage.window; 1208 ev->format = event->u.u.detail; 1209 switch (ev->format) { 1210 case 8: 1211 ev->message_type = event->u.clientMessage.u.b.type; 1212 for (i = 0; i < 20; i++) 1213 ev->data.b[i] = event->u.clientMessage.u.b.bytes[i]; 1214 break; 1215 case 16: 1216 ev->message_type = event->u.clientMessage.u.s.type; 1217 ev->data.s[0] = cvtINT16toShort(event->u.clientMessage.u.s.shorts0); 1218 ev->data.s[1] = cvtINT16toShort(event->u.clientMessage.u.s.shorts1); 1219 ev->data.s[2] = cvtINT16toShort(event->u.clientMessage.u.s.shorts2); 1220 ev->data.s[3] = cvtINT16toShort(event->u.clientMessage.u.s.shorts3); 1221 ev->data.s[4] = cvtINT16toShort(event->u.clientMessage.u.s.shorts4); 1222 ev->data.s[5] = cvtINT16toShort(event->u.clientMessage.u.s.shorts5); 1223 ev->data.s[6] = cvtINT16toShort(event->u.clientMessage.u.s.shorts6); 1224 ev->data.s[7] = cvtINT16toShort(event->u.clientMessage.u.s.shorts7); 1225 ev->data.s[8] = cvtINT16toShort(event->u.clientMessage.u.s.shorts8); 1226 ev->data.s[9] = cvtINT16toShort(event->u.clientMessage.u.s.shorts9); 1227 break; 1228 case 32: 1229 ev->message_type = event->u.clientMessage.u.l.type; 1230 ev->data.l[0] = cvtINT32toLong(event->u.clientMessage.u.l.longs0); 1231 ev->data.l[1] = cvtINT32toLong(event->u.clientMessage.u.l.longs1); 1232 ev->data.l[2] = cvtINT32toLong(event->u.clientMessage.u.l.longs2); 1233 ev->data.l[3] = cvtINT32toLong(event->u.clientMessage.u.l.longs3); 1234 ev->data.l[4] = cvtINT32toLong(event->u.clientMessage.u.l.longs4); 1235 break; 1236 default: /* XXX should never occur */ 1237 break; 1238 } 1239 } 1240 break; 1241 case MappingNotify: 1242 { 1243 register XMappingEvent *ev = (XMappingEvent *)re; 1244 ev->window = 0; 1245 ev->first_keycode = event->u.mappingNotify.firstKeyCode; 1246 ev->request = event->u.mappingNotify.request; 1247 ev->count = event->u.mappingNotify.count; 1248 } 1249 break; 1250 default: 1251 return(_XUnknownWireEvent(dpy, re, event)); 1252 } 1253 return(True); 1254} 1255 1256static int 1257SocketBytesReadable(Display *dpy) 1258{ 1259 int bytes = 0, last_error; 1260#ifdef WIN32 1261 last_error = WSAGetLastError(); 1262 ioctlsocket(ConnectionNumber(dpy), FIONREAD, &bytes); 1263 WSASetLastError(last_error); 1264#else 1265 last_error = errno; 1266 ioctl(ConnectionNumber(dpy), FIONREAD, &bytes); 1267 errno = last_error; 1268#endif 1269 return bytes; 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 if (dpy->lock) 1486 (*dpy->lock->user_lock_display)(dpy); 1487 UnlockDisplay(dpy); 1488#endif 1489 rtn_val = (*_XErrorFunction)(dpy, (XErrorEvent *)&event); /* upcall */ 1490#ifdef XTHREADS 1491 LockDisplay(dpy); 1492 if (dpy->lock) 1493 (*dpy->lock->user_unlock_display)(dpy); 1494#endif 1495 return rtn_val; 1496 } else { 1497 return _XDefaultError(dpy, (XErrorEvent *)&event); 1498 } 1499} 1500 1501/* 1502 * _XIOError - call user connection error handler and exit 1503 */ 1504int 1505_XIOError ( 1506 Display *dpy) 1507{ 1508 dpy->flags |= XlibDisplayIOError; 1509#ifdef WIN32 1510 errno = WSAGetLastError(); 1511#endif 1512 1513 /* This assumes that the thread calling exit will call any atexit handlers. 1514 * If this does not hold, then an alternate solution would involve 1515 * registering an atexit handler to take over the lock, which would only 1516 * assume that the same thread calls all the atexit handlers. */ 1517#ifdef XTHREADS 1518 if (dpy->lock) 1519 (*dpy->lock->user_lock_display)(dpy); 1520#endif 1521 UnlockDisplay(dpy); 1522 1523 if (_XIOErrorFunction != NULL) 1524 (*_XIOErrorFunction)(dpy); 1525 else 1526 _XDefaultIOError(dpy); 1527 exit (1); 1528 /*NOTREACHED*/ 1529} 1530 1531 1532/* 1533 * This routine can be used to (cheaply) get some memory within a single 1534 * Xlib routine for scratch space. A single buffer is reused each time 1535 * if possible. To be MT safe, you can only call this between a call to 1536 * GetReq* and a call to Data* or _XSend*, or in a context when the thread 1537 * is guaranteed to not unlock the display. 1538 */ 1539char *_XAllocScratch( 1540 register Display *dpy, 1541 unsigned long nbytes) 1542{ 1543 if (nbytes > dpy->scratch_length) { 1544 Xfree (dpy->scratch_buffer); 1545 dpy->scratch_buffer = Xmalloc(nbytes); 1546 if (dpy->scratch_buffer) 1547 dpy->scratch_length = nbytes; 1548 else dpy->scratch_length = 0; 1549 } 1550 return (dpy->scratch_buffer); 1551} 1552 1553/* 1554 * Scratch space allocator you can call any time, multiple times, and be 1555 * MT safe, but you must hand the buffer back with _XFreeTemp. 1556 */ 1557char *_XAllocTemp( 1558 register Display *dpy, 1559 unsigned long nbytes) 1560{ 1561 char *buf; 1562 1563 buf = _XAllocScratch(dpy, nbytes); 1564 dpy->scratch_buffer = NULL; 1565 dpy->scratch_length = 0; 1566 return buf; 1567} 1568 1569void _XFreeTemp( 1570 register Display *dpy, 1571 char *buf, 1572 unsigned long nbytes) 1573{ 1574 1575 Xfree(dpy->scratch_buffer); 1576 dpy->scratch_buffer = buf; 1577 dpy->scratch_length = nbytes; 1578} 1579 1580/* 1581 * Given a visual id, find the visual structure for this id on this display. 1582 */ 1583Visual *_XVIDtoVisual( 1584 Display *dpy, 1585 VisualID id) 1586{ 1587 register int i, j, k; 1588 register Screen *sp; 1589 register Depth *dp; 1590 register Visual *vp; 1591 for (i = 0; i < dpy->nscreens; i++) { 1592 sp = &dpy->screens[i]; 1593 for (j = 0; j < sp->ndepths; j++) { 1594 dp = &sp->depths[j]; 1595 /* if nvisuals == 0 then visuals will be NULL */ 1596 for (k = 0; k < dp->nvisuals; k++) { 1597 vp = &dp->visuals[k]; 1598 if (vp->visualid == id) return (vp); 1599 } 1600 } 1601 } 1602 return (NULL); 1603} 1604 1605int 1606XFree (void *data) 1607{ 1608 Xfree (data); 1609 return 1; 1610} 1611 1612#ifdef _XNEEDBCOPYFUNC 1613void _Xbcopy(b1, b2, length) 1614 register char *b1, *b2; 1615 register length; 1616{ 1617 if (b1 < b2) { 1618 b2 += length; 1619 b1 += length; 1620 while (length--) 1621 *--b2 = *--b1; 1622 } else { 1623 while (length--) 1624 *b2++ = *b1++; 1625 } 1626} 1627#endif 1628 1629#ifdef DataRoutineIsProcedure 1630void Data( 1631 Display *dpy, 1632 _Xconst char *data, 1633 long len) 1634{ 1635 if (dpy->bufptr + (len) <= dpy->bufmax) { 1636 memcpy(dpy->bufptr, data, (int)len); 1637 dpy->bufptr += ((len) + 3) & ~3; 1638 } else { 1639 _XSend(dpy, data, len); 1640 } 1641} 1642#endif /* DataRoutineIsProcedure */ 1643 1644 1645#ifdef LONG64 1646int 1647_XData32( 1648 Display *dpy, 1649 register _Xconst long *data, 1650 unsigned len) 1651{ 1652 register int *buf; 1653 register long i; 1654 1655 while (len) { 1656 buf = (int *)dpy->bufptr; 1657 i = dpy->bufmax - (char *)buf; 1658 if (!i) { 1659 _XFlush(dpy); 1660 continue; 1661 } 1662 if (len < i) 1663 i = len; 1664 dpy->bufptr = (char *)buf + i; 1665 len -= i; 1666 i >>= 2; 1667 while (--i >= 0) 1668 *buf++ = *data++; 1669 } 1670 return 0; 1671} 1672#endif /* LONG64 */ 1673 1674 1675 1676/* Make sure this produces the same string as DefineLocal/DefineSelf in xdm. 1677 * Otherwise, Xau will not be able to find your cookies in the Xauthority file. 1678 * 1679 * Note: POSIX says that the ``nodename'' member of utsname does _not_ have 1680 * to have sufficient information for interfacing to the network, 1681 * and so, you may be better off using gethostname (if it exists). 1682 */ 1683 1684#if (defined(_POSIX_SOURCE) && !defined(AIXV3) && !defined(__QNX__)) || defined(hpux) || defined(SVR4) 1685#define NEED_UTSNAME 1686#include <sys/utsname.h> 1687#else 1688#ifdef HAVE_UNISTD_H 1689#include <unistd.h> 1690#endif 1691#endif 1692 1693/* 1694 * _XGetHostname - similar to gethostname but allows special processing. 1695 */ 1696int _XGetHostname ( 1697 char *buf, 1698 int maxlen) 1699{ 1700 int len; 1701 1702#ifdef NEED_UTSNAME 1703 struct utsname name; 1704 1705 if (maxlen <= 0 || buf == NULL) 1706 return 0; 1707 1708 uname (&name); 1709 len = strlen (name.nodename); 1710 if (len >= maxlen) len = maxlen - 1; 1711 strncpy (buf, name.nodename, len); 1712 buf[len] = '\0'; 1713#else 1714 if (maxlen <= 0 || buf == NULL) 1715 return 0; 1716 1717 buf[0] = '\0'; 1718 (void) gethostname (buf, maxlen); 1719 buf [maxlen - 1] = '\0'; 1720 len = strlen(buf); 1721#endif /* NEED_UTSNAME */ 1722 return len; 1723} 1724 1725 1726/* 1727 * _XScreenOfWindow - get the Screen of a given window 1728 */ 1729 1730Screen *_XScreenOfWindow(Display *dpy, Window w) 1731{ 1732 register int i; 1733 Window root; 1734 int x, y; /* dummy variables */ 1735 unsigned int width, height, bw, depth; /* dummy variables */ 1736 1737 if (XGetGeometry (dpy, w, &root, &x, &y, &width, &height, 1738 &bw, &depth) == False) { 1739 return NULL; 1740 } 1741 for (i = 0; i < ScreenCount (dpy); i++) { /* find root from list */ 1742 if (root == RootWindow (dpy, i)) { 1743 return ScreenOfDisplay (dpy, i); 1744 } 1745 } 1746 return NULL; 1747} 1748 1749 1750/* 1751 * WARNING: This implementation's pre-conditions and post-conditions 1752 * must remain compatible with the old macro-based implementations of 1753 * GetReq, GetReqExtra, GetResReq, and GetEmptyReq. The portions of the 1754 * Display structure affected by those macros are part of libX11's 1755 * ABI. 1756 */ 1757void *_XGetRequest(Display *dpy, CARD8 type, size_t len) 1758{ 1759 xReq *req; 1760 1761 if (dpy->bufptr + len > dpy->bufmax) 1762 _XFlush(dpy); 1763 /* Request still too large, so do not allow it to overflow. */ 1764 if (dpy->bufptr + len > dpy->bufmax) { 1765 fprintf(stderr, 1766 "Xlib: request %d length %zd would exceed buffer size.\n", 1767 type, len); 1768 /* Changes failure condition from overflow to NULL dereference. */ 1769 return NULL; 1770 } 1771 1772 if (len % 4) 1773 fprintf(stderr, 1774 "Xlib: request %d length %zd not a multiple of 4.\n", 1775 type, len); 1776 1777 dpy->last_req = dpy->bufptr; 1778 1779 req = (xReq*)dpy->bufptr; 1780 req->reqType = type; 1781 req->length = len / 4; 1782 dpy->bufptr += len; 1783 X_DPY_REQUEST_INCREMENT(dpy); 1784 return req; 1785} 1786 1787#if defined(WIN32) 1788 1789/* 1790 * These functions are intended to be used internally to Xlib only. 1791 * These functions will always prefix the path with a DOS drive in the 1792 * form "<drive-letter>:". As such, these functions are only suitable 1793 * for use by Xlib function that supply a root-based path to some 1794 * particular file, e.g. <ProjectRoot>/lib/X11/locale/locale.dir will 1795 * be converted to "C:/usr/X11R6.3/lib/X11/locale/locale.dir". 1796 */ 1797 1798static int access_file (path, pathbuf, len_pathbuf, pathret) 1799 char* path; 1800 char* pathbuf; 1801 int len_pathbuf; 1802 char** pathret; 1803{ 1804 if (access (path, F_OK) == 0) { 1805 if (strlen (path) < len_pathbuf) 1806 *pathret = pathbuf; 1807 else 1808 *pathret = Xmalloc (strlen (path) + 1); 1809 if (*pathret) { 1810 strcpy (*pathret, path); 1811 return 1; 1812 } 1813 } 1814 return 0; 1815} 1816 1817static int AccessFile (path, pathbuf, len_pathbuf, pathret) 1818 char* path; 1819 char* pathbuf; 1820 int len_pathbuf; 1821 char** pathret; 1822{ 1823 unsigned long drives; 1824 int i, len; 1825 char* drive; 1826 char buf[MAX_PATH]; 1827 char* bufp; 1828 1829 /* just try the "raw" name first and see if it works */ 1830 if (access_file (path, pathbuf, len_pathbuf, pathret)) 1831 return 1; 1832 1833 /* try the places set in the environment */ 1834 drive = getenv ("_XBASEDRIVE"); 1835#ifdef __UNIXOS2__ 1836 if (!drive) 1837 drive = getenv ("X11ROOT"); 1838#endif 1839 if (!drive) 1840 drive = "C:"; 1841 len = strlen (drive) + strlen (path); 1842 if (len < MAX_PATH) bufp = buf; 1843 else bufp = Xmalloc (len + 1); 1844 strcpy (bufp, drive); 1845 strcat (bufp, path); 1846 if (access_file (bufp, pathbuf, len_pathbuf, pathret)) { 1847 if (bufp != buf) Xfree (bufp); 1848 return 1; 1849 } 1850 1851#ifndef __UNIXOS2__ 1852 /* one last place to look */ 1853 drive = getenv ("HOMEDRIVE"); 1854 if (drive) { 1855 len = strlen (drive) + strlen (path); 1856 if (len < MAX_PATH) bufp = buf; 1857 else bufp = Xmalloc (len + 1); 1858 strcpy (bufp, drive); 1859 strcat (bufp, path); 1860 if (access_file (bufp, pathbuf, len_pathbuf, pathret)) { 1861 if (bufp != buf) Xfree (bufp); 1862 return 1; 1863 } 1864 } 1865 1866 /* tried everywhere else, go fishing */ 1867#define C_DRIVE ('C' - 'A') 1868#define Z_DRIVE ('Z' - 'A') 1869 /* does OS/2 (with or with gcc-emx) have getdrives? */ 1870 drives = _getdrives (); 1871 for (i = C_DRIVE; i <= Z_DRIVE; i++) { /* don't check on A: or B: */ 1872 if ((1 << i) & drives) { 1873 len = 2 + strlen (path); 1874 if (len < MAX_PATH) bufp = buf; 1875 else bufp = Xmalloc (len + 1); 1876 *bufp = 'A' + i; 1877 *(bufp + 1) = ':'; 1878 *(bufp + 2) = '\0'; 1879 strcat (bufp, path); 1880 if (access_file (bufp, pathbuf, len_pathbuf, pathret)) { 1881 if (bufp != buf) Xfree (bufp); 1882 return 1; 1883 } 1884 } 1885 } 1886#endif 1887 return 0; 1888} 1889 1890int _XOpenFile(path, flags) 1891 _Xconst char* path; 1892 int flags; 1893{ 1894 char buf[MAX_PATH]; 1895 char* bufp = NULL; 1896 int ret = -1; 1897 UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS); 1898 1899 if (AccessFile (path, buf, MAX_PATH, &bufp)) 1900 ret = open (bufp, flags); 1901 1902 (void) SetErrorMode (olderror); 1903 1904 if (bufp != buf) Xfree (bufp); 1905 1906 return ret; 1907} 1908 1909int _XOpenFileMode(path, flags, mode) 1910 _Xconst char* path; 1911 int flags; 1912 mode_t mode; 1913{ 1914 char buf[MAX_PATH]; 1915 char* bufp = NULL; 1916 int ret = -1; 1917 UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS); 1918 1919 if (AccessFile (path, buf, MAX_PATH, &bufp)) 1920 ret = open (bufp, flags, mode); 1921 1922 (void) SetErrorMode (olderror); 1923 1924 if (bufp != buf) Xfree (bufp); 1925 1926 return ret; 1927} 1928 1929void* _XFopenFile(path, mode) 1930 _Xconst char* path; 1931 _Xconst char* mode; 1932{ 1933 char buf[MAX_PATH]; 1934 char* bufp = NULL; 1935 void* ret = NULL; 1936 UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS); 1937 1938 if (AccessFile (path, buf, MAX_PATH, &bufp)) 1939 ret = fopen (bufp, mode); 1940 1941 (void) SetErrorMode (olderror); 1942 1943 if (bufp != buf) Xfree (bufp); 1944 1945 return ret; 1946} 1947 1948int _XAccessFile(path) 1949 _Xconst char* path; 1950{ 1951 char buf[MAX_PATH]; 1952 char* bufp; 1953 int ret = -1; 1954 UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS); 1955 1956 ret = AccessFile (path, buf, MAX_PATH, &bufp); 1957 1958 (void) SetErrorMode (olderror); 1959 1960 if (bufp != buf) Xfree (bufp); 1961 1962 return ret; 1963} 1964 1965#endif 1966 1967#ifdef WIN32 1968#undef _Xdebug 1969int _Xdebug = 0; 1970int *_Xdebug_p = &_Xdebug; 1971void (**_XCreateMutex_fn_p)(LockInfoPtr) = &_XCreateMutex_fn; 1972void (**_XFreeMutex_fn_p)(LockInfoPtr) = &_XFreeMutex_fn; 1973void (**_XLockMutex_fn_p)(LockInfoPtr 1974#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE) 1975 , char * /* file */ 1976 , int /* line */ 1977#endif 1978 ) = &_XLockMutex_fn; 1979void (**_XUnlockMutex_fn_p)(LockInfoPtr 1980#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE) 1981 , char * /* file */ 1982 , int /* line */ 1983#endif 1984 ) = &_XUnlockMutex_fn; 1985LockInfoPtr *_Xglobal_lock_p = &_Xglobal_lock; 1986#endif 1987