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