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