XlibInt.c revision dac667f7
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 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 */ 1241int _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 exit(1); 1386 /*NOTREACHED*/ 1387} 1388 1389/*ARGSUSED*/ 1390Bool _XDefaultWireError(Display *display, XErrorEvent *he, xError *we) 1391{ 1392 return True; 1393} 1394 1395/* 1396 * _XError - upcall internal or user protocol error handler 1397 */ 1398int _XError ( 1399 Display *dpy, 1400 register xError *rep) 1401{ 1402 /* 1403 * X_Error packet encountered! We need to unpack the error before 1404 * giving it to the user. 1405 */ 1406 XEvent event; /* make it a large event */ 1407 register _XAsyncHandler *async, *next; 1408 1409 event.xerror.serial = _XSetLastRequestRead(dpy, (xGenericReply *)rep); 1410 1411 for (async = dpy->async_handlers; async; async = next) { 1412 next = async->next; 1413 if ((*async->handler)(dpy, (xReply *)rep, 1414 (char *)rep, SIZEOF(xError), async->data)) 1415 return 0; 1416 } 1417 1418 event.xerror.display = dpy; 1419 event.xerror.type = X_Error; 1420 event.xerror.resourceid = rep->resourceID; 1421 event.xerror.error_code = rep->errorCode; 1422 event.xerror.request_code = rep->majorCode; 1423 event.xerror.minor_code = rep->minorCode; 1424 if (dpy->error_vec && 1425 !(*dpy->error_vec[rep->errorCode])(dpy, &event.xerror, rep)) 1426 return 0; 1427 if (_XErrorFunction != NULL) { 1428 int rtn_val; 1429#ifdef XTHREADS 1430 if (dpy->lock) 1431 (*dpy->lock->user_lock_display)(dpy); 1432 UnlockDisplay(dpy); 1433#endif 1434 rtn_val = (*_XErrorFunction)(dpy, (XErrorEvent *)&event); /* upcall */ 1435#ifdef XTHREADS 1436 LockDisplay(dpy); 1437 if (dpy->lock) 1438 (*dpy->lock->user_unlock_display)(dpy); 1439#endif 1440 return rtn_val; 1441 } else { 1442 return _XDefaultError(dpy, (XErrorEvent *)&event); 1443 } 1444} 1445 1446/* 1447 * _XIOError - call user connection error handler and exit 1448 */ 1449int 1450_XIOError ( 1451 Display *dpy) 1452{ 1453 dpy->flags |= XlibDisplayIOError; 1454#ifdef WIN32 1455 errno = WSAGetLastError(); 1456#endif 1457 1458 /* This assumes that the thread calling exit will call any atexit handlers. 1459 * If this does not hold, then an alternate solution would involve 1460 * registering an atexit handler to take over the lock, which would only 1461 * assume that the same thread calls all the atexit handlers. */ 1462#ifdef XTHREADS 1463 if (dpy->lock) 1464 (*dpy->lock->user_lock_display)(dpy); 1465#endif 1466 UnlockDisplay(dpy); 1467 1468 if (_XIOErrorFunction != NULL) 1469 (*_XIOErrorFunction)(dpy); 1470 else 1471 _XDefaultIOError(dpy); 1472 exit (1); 1473 /*NOTREACHED*/ 1474} 1475 1476 1477/* 1478 * This routine can be used to (cheaply) get some memory within a single 1479 * Xlib routine for scratch space. A single buffer is reused each time 1480 * if possible. To be MT safe, you can only call this between a call to 1481 * GetReq* and a call to Data* or _XSend*, or in a context when the thread 1482 * is guaranteed to not unlock the display. 1483 */ 1484char *_XAllocScratch( 1485 register Display *dpy, 1486 unsigned long nbytes) 1487{ 1488 if (nbytes > dpy->scratch_length) { 1489 Xfree (dpy->scratch_buffer); 1490 dpy->scratch_buffer = Xmalloc(nbytes); 1491 if (dpy->scratch_buffer) 1492 dpy->scratch_length = nbytes; 1493 else dpy->scratch_length = 0; 1494 } 1495 return (dpy->scratch_buffer); 1496} 1497 1498/* 1499 * Scratch space allocator you can call any time, multiple times, and be 1500 * MT safe, but you must hand the buffer back with _XFreeTemp. 1501 */ 1502char *_XAllocTemp( 1503 register Display *dpy, 1504 unsigned long nbytes) 1505{ 1506 char *buf; 1507 1508 buf = _XAllocScratch(dpy, nbytes); 1509 dpy->scratch_buffer = NULL; 1510 dpy->scratch_length = 0; 1511 return buf; 1512} 1513 1514void _XFreeTemp( 1515 register Display *dpy, 1516 char *buf, 1517 unsigned long nbytes) 1518{ 1519 1520 Xfree(dpy->scratch_buffer); 1521 dpy->scratch_buffer = buf; 1522 dpy->scratch_length = nbytes; 1523} 1524 1525/* 1526 * Given a visual id, find the visual structure for this id on this display. 1527 */ 1528Visual *_XVIDtoVisual( 1529 Display *dpy, 1530 VisualID id) 1531{ 1532 register int i, j, k; 1533 register Screen *sp; 1534 register Depth *dp; 1535 register Visual *vp; 1536 for (i = 0; i < dpy->nscreens; i++) { 1537 sp = &dpy->screens[i]; 1538 for (j = 0; j < sp->ndepths; j++) { 1539 dp = &sp->depths[j]; 1540 /* if nvisuals == 0 then visuals will be NULL */ 1541 for (k = 0; k < dp->nvisuals; k++) { 1542 vp = &dp->visuals[k]; 1543 if (vp->visualid == id) return (vp); 1544 } 1545 } 1546 } 1547 return (NULL); 1548} 1549 1550int 1551XFree (void *data) 1552{ 1553 Xfree (data); 1554 return 1; 1555} 1556 1557#ifdef _XNEEDBCOPYFUNC 1558void _Xbcopy(b1, b2, length) 1559 register char *b1, *b2; 1560 register length; 1561{ 1562 if (b1 < b2) { 1563 b2 += length; 1564 b1 += length; 1565 while (length--) 1566 *--b2 = *--b1; 1567 } else { 1568 while (length--) 1569 *b2++ = *b1++; 1570 } 1571} 1572#endif 1573 1574#ifdef DataRoutineIsProcedure 1575void Data( 1576 Display *dpy, 1577 _Xconst char *data, 1578 long len) 1579{ 1580 if (dpy->bufptr + (len) <= dpy->bufmax) { 1581 memcpy(dpy->bufptr, data, (int)len); 1582 dpy->bufptr += ((len) + 3) & ~3; 1583 } else { 1584 _XSend(dpy, data, len); 1585 } 1586} 1587#endif /* DataRoutineIsProcedure */ 1588 1589 1590#ifdef LONG64 1591int 1592_XData32( 1593 Display *dpy, 1594 register _Xconst long *data, 1595 unsigned len) 1596{ 1597 register int *buf; 1598 register long i; 1599 1600 while (len) { 1601 buf = (int *)dpy->bufptr; 1602 i = dpy->bufmax - (char *)buf; 1603 if (!i) { 1604 _XFlush(dpy); 1605 continue; 1606 } 1607 if (len < i) 1608 i = len; 1609 dpy->bufptr = (char *)buf + i; 1610 len -= i; 1611 i >>= 2; 1612 while (--i >= 0) 1613 *buf++ = *data++; 1614 } 1615 return 0; 1616} 1617#endif /* LONG64 */ 1618 1619 1620 1621/* Make sure this produces the same string as DefineLocal/DefineSelf in xdm. 1622 * Otherwise, Xau will not be able to find your cookies in the Xauthority file. 1623 * 1624 * Note: POSIX says that the ``nodename'' member of utsname does _not_ have 1625 * to have sufficient information for interfacing to the network, 1626 * and so, you may be better off using gethostname (if it exists). 1627 */ 1628 1629#if (defined(_POSIX_SOURCE) && !defined(AIXV3) && !defined(__QNX__)) || defined(hpux) || defined(SVR4) 1630#define NEED_UTSNAME 1631#include <sys/utsname.h> 1632#else 1633#ifdef HAVE_UNISTD_H 1634#include <unistd.h> 1635#endif 1636#endif 1637 1638/* 1639 * _XGetHostname - similar to gethostname but allows special processing. 1640 */ 1641int _XGetHostname ( 1642 char *buf, 1643 int maxlen) 1644{ 1645 int len; 1646 1647#ifdef NEED_UTSNAME 1648 struct utsname name; 1649 1650 if (maxlen <= 0 || buf == NULL) 1651 return 0; 1652 1653 uname (&name); 1654 len = strlen (name.nodename); 1655 if (len >= maxlen) len = maxlen - 1; 1656 strncpy (buf, name.nodename, len); 1657 buf[len] = '\0'; 1658#else 1659 if (maxlen <= 0 || buf == NULL) 1660 return 0; 1661 1662 buf[0] = '\0'; 1663 (void) gethostname (buf, maxlen); 1664 buf [maxlen - 1] = '\0'; 1665 len = strlen(buf); 1666#endif /* NEED_UTSNAME */ 1667 return len; 1668} 1669 1670 1671/* 1672 * _XScreenOfWindow - get the Screen of a given window 1673 */ 1674 1675Screen *_XScreenOfWindow(Display *dpy, Window w) 1676{ 1677 register int i; 1678 Window root; 1679 int x, y; /* dummy variables */ 1680 unsigned int width, height, bw, depth; /* dummy variables */ 1681 1682 if (XGetGeometry (dpy, w, &root, &x, &y, &width, &height, 1683 &bw, &depth) == False) { 1684 return NULL; 1685 } 1686 for (i = 0; i < ScreenCount (dpy); i++) { /* find root from list */ 1687 if (root == RootWindow (dpy, i)) { 1688 return ScreenOfDisplay (dpy, i); 1689 } 1690 } 1691 return NULL; 1692} 1693 1694 1695/* 1696 * WARNING: This implementation's pre-conditions and post-conditions 1697 * must remain compatible with the old macro-based implementations of 1698 * GetReq, GetReqExtra, GetResReq, and GetEmptyReq. The portions of the 1699 * Display structure affected by those macros are part of libX11's 1700 * ABI. 1701 */ 1702void *_XGetRequest(Display *dpy, CARD8 type, size_t len) 1703{ 1704 xReq *req; 1705 1706 if (dpy->bufptr + len > dpy->bufmax) 1707 _XFlush(dpy); 1708 /* Request still too large, so do not allow it to overflow. */ 1709 if (dpy->bufptr + len > dpy->bufmax) { 1710 fprintf(stderr, 1711 "Xlib: request %d length %zd would exceed buffer size.\n", 1712 type, len); 1713 /* Changes failure condition from overflow to NULL dereference. */ 1714 return NULL; 1715 } 1716 1717 if (len % 4) 1718 fprintf(stderr, 1719 "Xlib: request %d length %zd not a multiple of 4.\n", 1720 type, len); 1721 1722 dpy->last_req = dpy->bufptr; 1723 1724 req = (xReq*)dpy->bufptr; 1725 req->reqType = type; 1726 req->length = len / 4; 1727 dpy->bufptr += len; 1728 X_DPY_REQUEST_INCREMENT(dpy); 1729 return req; 1730} 1731 1732#if defined(WIN32) 1733 1734/* 1735 * These functions are intended to be used internally to Xlib only. 1736 * These functions will always prefix the path with a DOS drive in the 1737 * form "<drive-letter>:". As such, these functions are only suitable 1738 * for use by Xlib function that supply a root-based path to some 1739 * particular file, e.g. <ProjectRoot>/lib/X11/locale/locale.dir will 1740 * be converted to "C:/usr/X11R6.3/lib/X11/locale/locale.dir". 1741 */ 1742 1743static int access_file (path, pathbuf, len_pathbuf, pathret) 1744 char* path; 1745 char* pathbuf; 1746 int len_pathbuf; 1747 char** pathret; 1748{ 1749 if (access (path, F_OK) == 0) { 1750 if (strlen (path) < len_pathbuf) 1751 *pathret = pathbuf; 1752 else 1753 *pathret = Xmalloc (strlen (path) + 1); 1754 if (*pathret) { 1755 strcpy (*pathret, path); 1756 return 1; 1757 } 1758 } 1759 return 0; 1760} 1761 1762static int AccessFile (path, pathbuf, len_pathbuf, pathret) 1763 char* path; 1764 char* pathbuf; 1765 int len_pathbuf; 1766 char** pathret; 1767{ 1768 unsigned long drives; 1769 int i, len; 1770 char* drive; 1771 char buf[MAX_PATH]; 1772 char* bufp; 1773 1774 /* just try the "raw" name first and see if it works */ 1775 if (access_file (path, pathbuf, len_pathbuf, pathret)) 1776 return 1; 1777 1778 /* try the places set in the environment */ 1779 drive = getenv ("_XBASEDRIVE"); 1780#ifdef __UNIXOS2__ 1781 if (!drive) 1782 drive = getenv ("X11ROOT"); 1783#endif 1784 if (!drive) 1785 drive = "C:"; 1786 len = strlen (drive) + strlen (path); 1787 if (len < MAX_PATH) bufp = buf; 1788 else bufp = Xmalloc (len + 1); 1789 strcpy (bufp, drive); 1790 strcat (bufp, path); 1791 if (access_file (bufp, pathbuf, len_pathbuf, pathret)) { 1792 if (bufp != buf) Xfree (bufp); 1793 return 1; 1794 } 1795 1796#ifndef __UNIXOS2__ 1797 /* one last place to look */ 1798 drive = getenv ("HOMEDRIVE"); 1799 if (drive) { 1800 len = strlen (drive) + strlen (path); 1801 if (len < MAX_PATH) bufp = buf; 1802 else bufp = Xmalloc (len + 1); 1803 strcpy (bufp, drive); 1804 strcat (bufp, path); 1805 if (access_file (bufp, pathbuf, len_pathbuf, pathret)) { 1806 if (bufp != buf) Xfree (bufp); 1807 return 1; 1808 } 1809 } 1810 1811 /* tried everywhere else, go fishing */ 1812#define C_DRIVE ('C' - 'A') 1813#define Z_DRIVE ('Z' - 'A') 1814 /* does OS/2 (with or with gcc-emx) have getdrives? */ 1815 drives = _getdrives (); 1816 for (i = C_DRIVE; i <= Z_DRIVE; i++) { /* don't check on A: or B: */ 1817 if ((1 << i) & drives) { 1818 len = 2 + strlen (path); 1819 if (len < MAX_PATH) bufp = buf; 1820 else bufp = Xmalloc (len + 1); 1821 *bufp = 'A' + i; 1822 *(bufp + 1) = ':'; 1823 *(bufp + 2) = '\0'; 1824 strcat (bufp, path); 1825 if (access_file (bufp, pathbuf, len_pathbuf, pathret)) { 1826 if (bufp != buf) Xfree (bufp); 1827 return 1; 1828 } 1829 } 1830 } 1831#endif 1832 return 0; 1833} 1834 1835int _XOpenFile(path, flags) 1836 _Xconst char* path; 1837 int flags; 1838{ 1839 char buf[MAX_PATH]; 1840 char* bufp = NULL; 1841 int ret = -1; 1842 UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS); 1843 1844 if (AccessFile (path, buf, MAX_PATH, &bufp)) 1845 ret = open (bufp, flags); 1846 1847 (void) SetErrorMode (olderror); 1848 1849 if (bufp != buf) Xfree (bufp); 1850 1851 return ret; 1852} 1853 1854int _XOpenFileMode(path, flags, mode) 1855 _Xconst char* path; 1856 int flags; 1857 mode_t mode; 1858{ 1859 char buf[MAX_PATH]; 1860 char* bufp = NULL; 1861 int ret = -1; 1862 UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS); 1863 1864 if (AccessFile (path, buf, MAX_PATH, &bufp)) 1865 ret = open (bufp, flags, mode); 1866 1867 (void) SetErrorMode (olderror); 1868 1869 if (bufp != buf) Xfree (bufp); 1870 1871 return ret; 1872} 1873 1874void* _XFopenFile(path, mode) 1875 _Xconst char* path; 1876 _Xconst char* mode; 1877{ 1878 char buf[MAX_PATH]; 1879 char* bufp = NULL; 1880 void* ret = NULL; 1881 UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS); 1882 1883 if (AccessFile (path, buf, MAX_PATH, &bufp)) 1884 ret = fopen (bufp, mode); 1885 1886 (void) SetErrorMode (olderror); 1887 1888 if (bufp != buf) Xfree (bufp); 1889 1890 return ret; 1891} 1892 1893int _XAccessFile(path) 1894 _Xconst char* path; 1895{ 1896 char buf[MAX_PATH]; 1897 char* bufp; 1898 int ret = -1; 1899 UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS); 1900 1901 ret = AccessFile (path, buf, MAX_PATH, &bufp); 1902 1903 (void) SetErrorMode (olderror); 1904 1905 if (bufp != buf) Xfree (bufp); 1906 1907 return ret; 1908} 1909 1910#endif 1911 1912#ifdef WIN32 1913#undef _Xdebug 1914int _Xdebug = 0; 1915int *_Xdebug_p = &_Xdebug; 1916void (**_XCreateMutex_fn_p)(LockInfoPtr) = &_XCreateMutex_fn; 1917void (**_XFreeMutex_fn_p)(LockInfoPtr) = &_XFreeMutex_fn; 1918void (**_XLockMutex_fn_p)(LockInfoPtr 1919#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE) 1920 , char * /* file */ 1921 , int /* line */ 1922#endif 1923 ) = &_XLockMutex_fn; 1924void (**_XUnlockMutex_fn_p)(LockInfoPtr 1925#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE) 1926 , char * /* file */ 1927 , int /* line */ 1928#endif 1929 ) = &_XUnlockMutex_fn; 1930LockInfoPtr *_Xglobal_lock_p = &_Xglobal_lock; 1931#endif 1932