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