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