XlibInt.c revision 88de56cc
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#define NEED_EVENTS 34#define NEED_REPLIES 35 36#ifdef WIN32 37#define _XLIBINT_ 38#endif 39#ifdef HAVE_CONFIG_H 40#include <config.h> 41#endif 42#include "Xlibint.h" 43#include "Xprivate.h" 44#include <X11/Xpoll.h> 45#if !USE_XCB 46#include <X11/Xtrans/Xtrans.h> 47#include <X11/extensions/xcmiscstr.h> 48#endif /* !USE_XCB */ 49#include <assert.h> 50#include <stdio.h> 51#ifdef WIN32 52#include <direct.h> 53#endif 54 55#ifdef XTHREADS 56#include "locking.h" 57 58/* these pointers get initialized by XInitThreads */ 59LockInfoPtr _Xglobal_lock = NULL; 60void (*_XCreateMutex_fn)(LockInfoPtr) = NULL; 61/* struct _XCVList *(*_XCreateCVL_fn)() = NULL; */ 62void (*_XFreeMutex_fn)(LockInfoPtr) = NULL; 63void (*_XLockMutex_fn)( 64 LockInfoPtr /* lock */ 65#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE) 66 , char * /* file */ 67 , int /* line */ 68#endif 69 ) = NULL; 70void (*_XUnlockMutex_fn)( 71 LockInfoPtr /* lock */ 72#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE) 73 , char * /* file */ 74 , int /* line */ 75#endif 76 ) = NULL; 77xthread_t (*_Xthread_self_fn)(void) = NULL; 78 79#define XThread_Self() ((*_Xthread_self_fn)()) 80 81#if !USE_XCB 82#define UnlockNextReplyReader(d) if ((d)->lock) \ 83 (*(d)->lock->pop_reader)((d),&(d)->lock->reply_awaiters,&(d)->lock->reply_awaiters_tail) 84 85#define QueueReplyReaderLock(d) ((d)->lock ? \ 86 (*(d)->lock->push_reader)(d,&(d)->lock->reply_awaiters_tail) : NULL) 87#define QueueEventReaderLock(d) ((d)->lock ? \ 88 (*(d)->lock->push_reader)(d,&(d)->lock->event_awaiters_tail) : NULL) 89#endif /* !USE_XCB */ 90 91#else /* XTHREADS else */ 92 93#if !USE_XCB 94#define UnlockNextReplyReader(d) 95#define UnlockNextEventReader(d) 96#endif /* !USE_XCB */ 97 98#endif /* XTHREADS else */ 99 100/* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX 101 * systems are broken and return EWOULDBLOCK when they should return EAGAIN 102 */ 103#ifdef WIN32 104#define ETEST() (WSAGetLastError() == WSAEWOULDBLOCK) 105#else 106#ifdef __CYGWIN__ /* Cygwin uses ENOBUFS to signal socket is full */ 107#define ETEST() (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS) 108#else 109#if defined(EAGAIN) && defined(EWOULDBLOCK) 110#define ETEST() (errno == EAGAIN || errno == EWOULDBLOCK) 111#else 112#ifdef EAGAIN 113#define ETEST() (errno == EAGAIN) 114#else 115#define ETEST() (errno == EWOULDBLOCK) 116#endif /* EAGAIN */ 117#endif /* EAGAIN && EWOULDBLOCK */ 118#endif /* __CYGWIN__ */ 119#endif /* WIN32 */ 120 121#ifdef WIN32 122#define ECHECK(err) (WSAGetLastError() == err) 123#define ESET(val) WSASetLastError(val) 124#else 125#ifdef __UNIXOS2__ 126#define ECHECK(err) (errno == err) 127#define ESET(val) 128#else 129#define ECHECK(err) (errno == err) 130#define ESET(val) errno = val 131#endif 132#endif 133 134#if defined(LOCALCONN) || defined(LACHMAN) 135#ifdef EMSGSIZE 136#define ESZTEST() (ECHECK(EMSGSIZE) || ECHECK(ERANGE)) 137#else 138#define ESZTEST() ECHECK(ERANGE) 139#endif 140#else 141#ifdef EMSGSIZE 142#define ESZTEST() ECHECK(EMSGSIZE) 143#endif 144#endif 145 146#ifdef __UNIXOS2__ 147#if !USE_XCB 148#define select(n,r,w,x,t) os2ClientSelect(n,r,w,x,t) 149#endif /* !USE_XCB */ 150#include <limits.h> 151#define MAX_PATH _POSIX_PATH_MAX 152#endif 153 154#if !USE_XCB 155#ifdef MUSTCOPY 156 157#define STARTITERATE(tpvar,type,start,endcond) \ 158 { register char *cpvar; \ 159 for (cpvar = (char *) (start); endcond; ) { \ 160 type dummy; memcpy ((char *) &dummy, cpvar, SIZEOF(type)); \ 161 tpvar = &dummy; 162#define ITERPTR(tpvar) cpvar 163#define RESETITERPTR(tpvar,type,start) cpvar = start 164#define INCITERPTR(tpvar,type) cpvar += SIZEOF(type) 165#define ENDITERATE }} 166 167#else 168 169#define STARTITERATE(tpvar,type,start,endcond) \ 170 for (tpvar = (type *) (start); endcond; ) 171#define ITERPTR(tpvar) (char *)tpvar 172#define RESETITERPTR(tpvar,type,start) tpvar = (type *) (start) 173#define INCITERPTR(tpvar,type) tpvar++ 174#define ENDITERATE 175 176#endif /* MUSTCOPY */ 177 178typedef union { 179 xReply rep; 180 char buf[BUFSIZE]; 181} _XAlignedBuffer; 182 183static char *_XAsyncReply( 184 Display *dpy, 185 register xReply *rep, 186 char *buf, 187 register int *lenp, 188 Bool discard); 189#endif /* !USE_XCB */ 190 191/* 192 * The following routines are internal routines used by Xlib for protocol 193 * packet transmission and reception. 194 * 195 * _XIOError(Display *) will be called if any sort of system call error occurs. 196 * This is assumed to be a fatal condition, i.e., XIOError should not return. 197 * 198 * _XError(Display *, xError *) will be called whenever an X_Error event is 199 * received. This is not assumed to be a fatal condition, i.e., it is 200 * acceptable for this procedure to return. However, XError should NOT 201 * perform any operations (directly or indirectly) on the DISPLAY. 202 * 203 * Routines declared with a return type of 'Status' return 0 on failure, 204 * and non 0 on success. Routines with no declared return type don't 205 * return anything. Whenever possible routines that create objects return 206 * the object they have created. 207 */ 208 209#if !USE_XCB 210static xReq _dummy_request = { 211 0, 0, 0 212}; 213 214/* 215 * This is an OS dependent routine which: 216 * 1) returns as soon as the connection can be written on.... 217 * 2) if the connection can be read, must enqueue events and handle errors, 218 * until the connection is writable. 219 */ 220static void 221_XWaitForWritable( 222 Display *dpy 223#ifdef XTHREADS 224 , 225 xcondition_t cv /* our reading condition variable */ 226#endif 227 ) 228{ 229#ifdef USE_POLL 230 struct pollfd filedes; 231#else 232 fd_set r_mask; 233 fd_set w_mask; 234#endif 235 int nfound; 236 237#ifdef USE_POLL 238 filedes.fd = dpy->fd; 239 filedes.events = 0; 240#else 241 FD_ZERO(&r_mask); 242 FD_ZERO(&w_mask); 243#endif 244 245 for (;;) { 246#ifdef XTHREADS 247 /* We allow only one thread at a time to read, to minimize 248 passing of read data between threads. 249 Now, who is it? If there is a non-NULL reply_awaiters and 250 we (i.e., our cv) are not at the head of it, then whoever 251 is at the head is the reader, and we don't read. 252 Otherwise there is no reply_awaiters or we are at the 253 head, having just appended ourselves. 254 In this case, if there is a event_awaiters, then whoever 255 is at the head of it got there before we did, and they are the 256 reader. 257 258 Last cases: no event_awaiters and we are at the head of 259 reply_awaiters or reply_awaiters is NULL: we are the reader, 260 since there is obviously no one else involved. 261 262 XXX - what if cv is NULL and someone else comes along after 263 us while we are waiting? 264 */ 265 266 if (!dpy->lock || 267 (!dpy->lock->event_awaiters && 268 (!dpy->lock->reply_awaiters || 269 dpy->lock->reply_awaiters->cv == cv))) 270#endif 271#ifdef USE_POLL 272 filedes.events = POLLIN; 273 filedes.events |= POLLOUT; 274#else 275 FD_SET(dpy->fd, &r_mask); 276 FD_SET(dpy->fd, &w_mask); 277#endif 278 279 do { 280 UnlockDisplay(dpy); 281#ifdef USE_POLL 282 nfound = poll (&filedes, 1, -1); 283#else 284 nfound = Select (dpy->fd + 1, &r_mask, &w_mask, NULL, NULL); 285#endif 286 InternalLockDisplay(dpy, cv != NULL); 287 if (nfound < 0 && !(ECHECK(EINTR) || ETEST())) 288 _XIOError(dpy); 289 } while (nfound <= 0); 290 291 if ( 292#ifdef USE_POLL 293 filedes.revents & POLLIN 294#else 295 FD_ISSET(dpy->fd, &r_mask) 296#endif 297 ) 298 { 299 _XAlignedBuffer buf; 300 BytesReadable_t pend; 301 register int len; 302 register xReply *rep; 303 304 /* find out how much data can be read */ 305 if (_X11TransBytesReadable(dpy->trans_conn, &pend) < 0) 306 _XIOError(dpy); 307 len = pend; 308 309 /* must read at least one xEvent; if none is pending, then 310 we'll just block waiting for it */ 311 if (len < SIZEOF(xReply) 312#ifdef XTHREADS 313 || dpy->async_handlers 314#endif 315 ) 316 len = SIZEOF(xReply); 317 318 /* but we won't read more than the max buffer size */ 319 if (len > BUFSIZE) len = BUFSIZE; 320 321 /* round down to an integral number of XReps */ 322 len = (len / SIZEOF(xReply)) * SIZEOF(xReply); 323 324 (void) _XRead (dpy, buf.buf, (long) len); 325 326 STARTITERATE(rep,xReply,buf.buf,len > 0) { 327 if (rep->generic.type == X_Reply) { 328 int tmp = len; 329 RESETITERPTR(rep,xReply, 330 _XAsyncReply (dpy, rep, 331 ITERPTR(rep), &tmp, True)); 332 len = tmp; 333 pend = len; 334 } else { 335 if (rep->generic.type == X_Error) 336 _XError (dpy, (xError *)rep); 337 else /* must be an event packet */ 338 _XEnq (dpy, (xEvent *)rep); 339 INCITERPTR(rep,xReply); 340 len -= SIZEOF(xReply); 341 } 342 } ENDITERATE 343#ifdef XTHREADS 344 if (dpy->lock && dpy->lock->event_awaiters) 345 ConditionSignal(dpy, dpy->lock->event_awaiters->cv); 346#endif 347 } 348#ifdef USE_POLL 349 if (filedes.revents & (POLLOUT|POLLHUP|POLLERR)) 350#else 351 if (FD_ISSET(dpy->fd, &w_mask)) 352#endif 353 { 354#ifdef XTHREADS 355 if (dpy->lock) { 356 ConditionBroadcast(dpy, dpy->lock->writers); 357 } 358#endif 359 return; 360 } 361 } 362} 363#endif /* !USE_XCB */ 364 365 366#define POLLFD_CACHE_SIZE 5 367 368/* initialize the struct array passed to poll() below */ 369Bool _XPollfdCacheInit( 370 Display *dpy) 371{ 372#ifdef USE_POLL 373 struct pollfd *pfp; 374 375 pfp = (struct pollfd *)Xmalloc(POLLFD_CACHE_SIZE * sizeof(struct pollfd)); 376 if (!pfp) 377 return False; 378 pfp[0].fd = dpy->fd; 379 pfp[0].events = POLLIN; 380 381 dpy->filedes = (XPointer)pfp; 382#endif 383 return True; 384} 385 386void _XPollfdCacheAdd( 387 Display *dpy, 388 int fd) 389{ 390#ifdef USE_POLL 391 struct pollfd *pfp = (struct pollfd *)dpy->filedes; 392 393 if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) { 394 pfp[dpy->im_fd_length].fd = fd; 395 pfp[dpy->im_fd_length].events = POLLIN; 396 } 397#endif 398} 399 400/* ARGSUSED */ 401void _XPollfdCacheDel( 402 Display *dpy, 403 int fd) /* not used */ 404{ 405#ifdef USE_POLL 406 struct pollfd *pfp = (struct pollfd *)dpy->filedes; 407 struct _XConnectionInfo *conni; 408 409 /* just recalculate whole list */ 410 if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) { 411 int loc = 1; 412 for (conni = dpy->im_fd_info; conni; conni=conni->next) { 413 pfp[loc].fd = conni->fd; 414 pfp[loc].events = POLLIN; 415 loc++; 416 } 417 } 418#endif 419} 420 421#if !USE_XCB 422/* returns True iff there is an event in the queue newer than serial_num */ 423 424static Bool 425_XNewerQueuedEvent( 426 Display *dpy, 427 int serial_num) 428{ 429 _XQEvent *qev; 430 431 if (dpy->next_event_serial_num == serial_num) 432 return False; 433 434 qev = dpy->head; 435 while (qev) { 436 if (qev->qserial_num >= serial_num) { 437 return True; 438 } 439 qev = qev->next; 440 } 441 return False; 442} 443 444static int 445_XWaitForReadable( 446 Display *dpy) 447{ 448 int result; 449 int fd = dpy->fd; 450 struct _XConnectionInfo *ilist; 451 register int saved_event_serial = 0; 452 int in_read_events = 0; 453 register Bool did_proc_conni = False; 454#ifdef USE_POLL 455 struct pollfd *filedes; 456#else 457 fd_set r_mask; 458 int highest_fd = fd; 459#endif 460 461#ifdef USE_POLL 462 if (dpy->im_fd_length + 1 > POLLFD_CACHE_SIZE 463 && !(dpy->flags & XlibDisplayProcConni)) { 464 /* XXX - this fallback is gross */ 465 int i; 466 467 filedes = (struct pollfd *)Xmalloc(dpy->im_fd_length * sizeof(struct pollfd)); 468 filedes[0].fd = fd; 469 filedes[0].events = POLLIN; 470 for (ilist=dpy->im_fd_info, i=1; ilist; ilist=ilist->next, i++) { 471 filedes[i].fd = ilist->fd; 472 filedes[i].events = POLLIN; 473 } 474 } else { 475 filedes = (struct pollfd *)dpy->filedes; 476 } 477#else 478 FD_ZERO(&r_mask); 479#endif 480 for (;;) { 481#ifndef USE_POLL 482 FD_SET(fd, &r_mask); 483 if (!(dpy->flags & XlibDisplayProcConni)) 484 for (ilist=dpy->im_fd_info; ilist; ilist=ilist->next) { 485 FD_SET(ilist->fd, &r_mask); 486 if (ilist->fd > highest_fd) 487 highest_fd = ilist->fd; 488 } 489#endif 490 UnlockDisplay(dpy); 491#ifdef USE_POLL 492 result = poll(filedes, 493 (dpy->flags & XlibDisplayProcConni) ? 1 : 1+dpy->im_fd_length, 494 -1); 495#else 496 result = Select(highest_fd + 1, &r_mask, NULL, NULL, NULL); 497#endif 498 InternalLockDisplay(dpy, dpy->flags & XlibDisplayReply); 499 if (result == -1 && !(ECHECK(EINTR) || ETEST())) _XIOError(dpy); 500 if (result <= 0) 501 continue; 502#ifdef USE_POLL 503 if (filedes[0].revents & (POLLIN|POLLHUP|POLLERR)) 504#else 505 if (FD_ISSET(fd, &r_mask)) 506#endif 507 break; 508 if (!(dpy->flags & XlibDisplayProcConni)) { 509 int i; 510 511 saved_event_serial = dpy->next_event_serial_num; 512 /* dpy flags can be clobbered by internal connection callback */ 513 in_read_events = dpy->flags & XlibDisplayReadEvents; 514 for (ilist=dpy->im_fd_info, i=1; ilist; ilist=ilist->next, i++) { 515#ifdef USE_POLL 516 if (filedes[i].revents & POLLIN) 517#else 518 if (FD_ISSET(ilist->fd, &r_mask)) 519#endif 520 { 521 _XProcessInternalConnection(dpy, ilist); 522 did_proc_conni = True; 523 } 524 } 525#ifdef USE_POLL 526 if (dpy->im_fd_length + 1 > POLLFD_CACHE_SIZE) 527 Xfree(filedes); 528#endif 529 } 530 if (did_proc_conni) { 531 /* some internal connection callback might have done an 532 XPutBackEvent. We notice it here and if we needed an event, 533 we can return all the way. */ 534 if (_XNewerQueuedEvent(dpy, saved_event_serial) 535 && (in_read_events 536#ifdef XTHREADS 537 || (dpy->lock && dpy->lock->event_awaiters) 538#endif 539 )) 540 return -2; 541 did_proc_conni = False; 542 } 543 } 544#ifdef XTHREADS 545#ifdef XTHREADS_DEBUG 546 printf("thread %x _XWaitForReadable returning\n", XThread_Self()); 547#endif 548#endif 549 return 0; 550} 551#endif /* !USE_XCB */ 552 553static int sync_hazard(Display *dpy) 554{ 555 unsigned long span = dpy->request - dpy->last_request_read; 556 unsigned long hazard = min((dpy->bufmax - dpy->buffer) / SIZEOF(xReq), 65535 - 10); 557 return span >= 65535 - hazard - 10; 558} 559 560static 561void sync_while_locked(Display *dpy) 562{ 563#ifdef XTHREADS 564 if (dpy->lock) 565 (*dpy->lock->user_lock_display)(dpy); 566#endif 567 UnlockDisplay(dpy); 568 SyncHandle(); 569 InternalLockDisplay(dpy, /* don't skip user locks */ 0); 570#ifdef XTHREADS 571 if (dpy->lock) 572 (*dpy->lock->user_unlock_display)(dpy); 573#endif 574} 575 576void _XSeqSyncFunction( 577 register Display *dpy) 578{ 579 xGetInputFocusReply rep; 580 register xReq *req; 581 582 if ((dpy->request - dpy->last_request_read) >= (65535 - BUFSIZE/SIZEOF(xReq))) { 583 GetEmptyReq(GetInputFocus, req); 584 (void) _XReply (dpy, (xReply *)&rep, 0, xTrue); 585 sync_while_locked(dpy); 586 } else if (sync_hazard(dpy)) 587 _XSetPrivSyncFunction(dpy); 588} 589 590/* NOTE: only called if !XTHREADS, or when XInitThreads wasn't called. */ 591static int 592_XPrivSyncFunction (Display *dpy) 593{ 594#if XTHREADS 595 assert(!dpy->lock_fns); 596#endif 597 assert(dpy->synchandler == _XPrivSyncFunction); 598 assert((dpy->flags & XlibDisplayPrivSync) != 0); 599 dpy->synchandler = dpy->savedsynchandler; 600 dpy->savedsynchandler = NULL; 601 dpy->flags &= ~XlibDisplayPrivSync; 602 if(dpy->synchandler) 603 dpy->synchandler(dpy); 604 _XIDHandler(dpy); 605 _XSeqSyncFunction(dpy); 606 return 0; 607} 608 609void _XSetPrivSyncFunction(Display *dpy) 610{ 611#ifdef XTHREADS 612 if (dpy->lock_fns) 613 return; 614#endif 615 if (!(dpy->flags & XlibDisplayPrivSync)) { 616 dpy->savedsynchandler = dpy->synchandler; 617 dpy->synchandler = _XPrivSyncFunction; 618 dpy->flags |= XlibDisplayPrivSync; 619 } 620} 621 622void _XSetSeqSyncFunction(Display *dpy) 623{ 624 if (sync_hazard(dpy)) 625 _XSetPrivSyncFunction (dpy); 626} 627 628#if !USE_XCB 629#ifdef XTHREADS 630static void _XFlushInt( 631 register Display *dpy, 632 register xcondition_t cv); 633#endif 634 635/* 636 * _XFlush - Flush the X request buffer. If the buffer is empty, no 637 * action is taken. This routine correctly handles incremental writes. 638 * This routine may have to be reworked if int < long. 639 */ 640void _XFlush( 641 register Display *dpy) 642{ 643#ifdef XTHREADS 644 /* With multi-threading we introduce an internal routine to which 645 we can pass a condition variable to do locking correctly. */ 646 647 _XFlushInt(dpy, NULL); 648} 649 650/* _XFlushInt - Internal version of _XFlush used to do multi-threaded 651 * locking correctly. 652 */ 653 654static void _XFlushInt( 655 register Display *dpy, 656 register xcondition_t cv) 657{ 658#endif /* XTHREADS*/ 659 register long size, todo; 660 register int write_stat; 661 register char *bufindex; 662 _XExtension *ext; 663 664 /* This fix resets the bufptr to the front of the buffer so 665 * additional appends to the bufptr will not corrupt memory. Since 666 * the server is down, these appends are no-op's anyway but 667 * callers of _XFlush() are not verifying this before they call it. 668 */ 669 if (dpy->flags & XlibDisplayIOError) 670 { 671 dpy->bufptr = dpy->buffer; 672 dpy->last_req = (char *)&_dummy_request; 673 return; 674 } 675 676#ifdef XTHREADS 677 while (dpy->flags & XlibDisplayWriting) { 678 if (dpy->lock) { 679 ConditionWait(dpy, dpy->lock->writers); 680 } else { 681 _XWaitForWritable (dpy, cv); 682 } 683 } 684#endif 685 size = todo = dpy->bufptr - dpy->buffer; 686 if (!size) return; 687#ifdef XTHREADS 688 dpy->flags |= XlibDisplayWriting; 689 /* make sure no one else can put in data */ 690 dpy->bufptr = dpy->bufmax; 691#endif 692 for (ext = dpy->flushes; ext; ext = ext->next_flush) 693 (*ext->before_flush)(dpy, &ext->codes, dpy->buffer, size); 694 bufindex = dpy->buffer; 695 /* 696 * While write has not written the entire buffer, keep looping 697 * until the entire buffer is written. bufindex will be 698 * incremented and size decremented as buffer is written out. 699 */ 700 while (size) { 701 ESET(0); 702 write_stat = _X11TransWrite(dpy->trans_conn, 703 bufindex, (int) todo); 704 if (write_stat >= 0) { 705 size -= write_stat; 706 todo = size; 707 bufindex += write_stat; 708 } else if (ETEST()) { 709 _XWaitForWritable(dpy 710#ifdef XTHREADS 711 , cv 712#endif 713 ); 714#ifdef SUNSYSV 715 } else if (ECHECK(0)) { 716 _XWaitForWritable(dpy 717#ifdef XTHREADS 718 , cv 719#endif 720 ); 721#endif 722#ifdef ESZTEST 723 } else if (ESZTEST()) { 724 if (todo > 1) 725 todo >>= 1; 726 else { 727 _XWaitForWritable(dpy 728#ifdef XTHREADS 729 , cv 730#endif 731 ); 732 } 733#endif 734 } else if (!ECHECK(EINTR)) { 735 /* Write failed! */ 736 /* errno set by write system call. */ 737 _XIOError(dpy); 738 } 739 } 740 dpy->last_req = (char *)&_dummy_request; 741 _XSetSeqSyncFunction(dpy); 742 dpy->bufptr = dpy->buffer; 743#ifdef XTHREADS 744 dpy->flags &= ~XlibDisplayWriting; 745#endif 746} 747 748int 749_XEventsQueued( 750 register Display *dpy, 751 int mode) 752{ 753 register int len; 754 BytesReadable_t pend; 755 _XAlignedBuffer buf; 756 register xReply *rep; 757 char *read_buf; 758#ifdef XTHREADS 759 int entry_event_serial_num; 760 struct _XCVList *cvl = NULL; 761 xthread_t self; 762 763#ifdef XTHREADS_DEBUG 764 printf("_XEventsQueued called in thread %x\n", XThread_Self()); 765#endif 766#endif /* XTHREADS*/ 767 768 if (mode == QueuedAfterFlush) 769 { 770 _XFlush(dpy); 771 if (dpy->qlen) 772 return(dpy->qlen); 773 } 774 if (dpy->flags & XlibDisplayIOError) return(dpy->qlen); 775 776#ifdef XTHREADS 777 /* create our condition variable and append to list, 778 * unless we were called from within XProcessInternalConnection 779 * or XLockDisplay 780 */ 781 xthread_clear_id(self); 782 if (dpy->lock && (xthread_have_id (dpy->lock->conni_thread) 783 || xthread_have_id (dpy->lock->locking_thread))) 784 /* some thread is in XProcessInternalConnection or XLockDisplay 785 so we have to see if we are it */ 786 self = XThread_Self(); 787 if (!xthread_have_id(self) 788 || (!xthread_equal(self, dpy->lock->conni_thread) 789 && !xthread_equal(self, dpy->lock->locking_thread))) { 790 /* In the multi-threaded case, if there is someone else 791 reading events, then there aren't any available, so 792 we just return. If we waited we would block. 793 */ 794 if (dpy->lock && dpy->lock->event_awaiters) 795 return dpy->qlen; 796 /* nobody here but us, so lock out any newcomers */ 797 cvl = QueueEventReaderLock(dpy); 798 } 799 800 while (dpy->lock && cvl && dpy->lock->reply_first) { 801 /* note which events we have already seen so we'll know 802 if _XReply (in another thread) reads one */ 803 entry_event_serial_num = dpy->next_event_serial_num; 804 ConditionWait(dpy, cvl->cv); 805 /* did _XReply read an event we can return? */ 806 if (_XNewerQueuedEvent(dpy, entry_event_serial_num)) 807 { 808 UnlockNextEventReader(dpy); 809 return 0; 810 } 811 } 812#endif /* XTHREADS*/ 813 814 if (_X11TransBytesReadable(dpy->trans_conn, &pend) < 0) 815 _XIOError(dpy); 816#ifdef XCONN_CHECK_FREQ 817 /* This is a crock, required because FIONREAD or equivalent is 818 * not guaranteed to detect a broken connection. 819 */ 820 if (!pend && !dpy->qlen && ++dpy->conn_checker >= XCONN_CHECK_FREQ) 821 { 822 int result; 823#ifdef USE_POLL 824 struct pollfd filedes; 825#else 826 fd_set r_mask; 827 static struct timeval zero_time; 828#endif 829 830 dpy->conn_checker = 0; 831#ifdef USE_POLL 832 filedes.fd = dpy->fd; 833 filedes.events = POLLIN; 834 if ((result = poll(&filedes, 1, 0))) 835#else 836 FD_ZERO(&r_mask); 837 FD_SET(dpy->fd, &r_mask); 838 if ((result = Select(dpy->fd + 1, &r_mask, NULL, NULL, &zero_time))) 839#endif 840 { 841 if (result > 0) 842 { 843 if (_X11TransBytesReadable(dpy->trans_conn, &pend) < 0) 844 _XIOError(dpy); 845 /* we should not get zero, if we do, force a read */ 846 if (!pend) 847 pend = SIZEOF(xReply); 848 } 849 else if (result < 0 && !(ECHECK(EINTR) || ETEST())) 850 _XIOError(dpy); 851 } 852 } 853#endif /* XCONN_CHECK_FREQ */ 854 if (!(len = pend)) { 855 /* _XFlush can enqueue events */ 856#ifdef XTHREADS 857 if (cvl) 858#endif 859 { 860 UnlockNextEventReader(dpy); 861 } 862 return(dpy->qlen); 863 } 864 /* Force a read if there is not enough data. Otherwise, 865 * a select() loop at a higher-level will spin undesirably, 866 * and we've seen at least one OS that appears to not update 867 * the result from FIONREAD once it has returned nonzero. 868 */ 869#ifdef XTHREADS 870 if (dpy->lock && dpy->lock->reply_awaiters) { 871 read_buf = (char *)dpy->lock->reply_awaiters->buf; 872 len = SIZEOF(xReply); 873 } else 874#endif /* XTHREADS*/ 875 { 876 read_buf = buf.buf; 877 878 if (len < SIZEOF(xReply) 879#ifdef XTHREADS 880 || dpy->async_handlers 881#endif 882 ) 883 len = SIZEOF(xReply); 884 else if (len > BUFSIZE) 885 len = BUFSIZE; 886 len = (len / SIZEOF(xReply)) * SIZEOF(xReply); 887 } 888#ifdef XCONN_CHECK_FREQ 889 dpy->conn_checker = 0; 890#endif 891 892 (void) _XRead (dpy, read_buf, (long) len); 893 894#ifdef XTHREADS 895 /* what did we actually read: reply or event? */ 896 if (dpy->lock && dpy->lock->reply_awaiters) { 897 if (((xReply *)read_buf)->generic.type == X_Reply || 898 ((xReply *)read_buf)->generic.type == X_Error) 899 { 900 dpy->lock->reply_was_read = True; 901 dpy->lock->reply_first = True; 902 if (read_buf != (char *)dpy->lock->reply_awaiters->buf) 903 memcpy(dpy->lock->reply_awaiters->buf, read_buf, 904 len); 905 if (cvl) { 906 UnlockNextEventReader(dpy); 907 } 908 return(dpy->qlen); /* we read, so we can return */ 909 } else if (read_buf != buf.buf) 910 memcpy(buf.buf, read_buf, len); 911 } 912#endif /* XTHREADS*/ 913 914 STARTITERATE(rep,xReply,buf.buf,len > 0) { 915 if (rep->generic.type == X_Reply) { 916 int tmp = len; 917 RESETITERPTR(rep,xReply, 918 _XAsyncReply (dpy, rep, 919 ITERPTR(rep), &tmp, True)); 920 len = tmp; 921 pend = len; 922 } else { 923 if (rep->generic.type == X_Error) 924 _XError (dpy, (xError *)rep); 925 else /* must be an event packet */ 926 _XEnq (dpy, (xEvent *)rep); 927 INCITERPTR(rep,xReply); 928 len -= SIZEOF(xReply); 929 } 930 } ENDITERATE 931 932#ifdef XTHREADS 933 if (cvl) 934#endif 935 { 936 UnlockNextEventReader(dpy); 937 } 938 return(dpy->qlen); 939} 940 941/* _XReadEvents - Flush the output queue, 942 * then read as many events as possible (but at least 1) and enqueue them 943 */ 944void _XReadEvents( 945 register Display *dpy) 946{ 947 _XAlignedBuffer buf; 948 BytesReadable_t pend; 949 int len; 950 register xReply *rep; 951 Bool not_yet_flushed = True; 952 char *read_buf; 953 int i; 954 int entry_event_serial_num = dpy->next_event_serial_num; 955#ifdef XTHREADS 956 struct _XCVList *cvl = NULL; 957 xthread_t self; 958 959#ifdef XTHREADS_DEBUG 960 printf("_XReadEvents called in thread %x\n", 961 XThread_Self()); 962#endif 963 /* create our condition variable and append to list, 964 * unless we were called from within XProcessInternalConnection 965 * or XLockDisplay 966 */ 967 xthread_clear_id(self); 968 if (dpy->lock && (xthread_have_id (dpy->lock->conni_thread) 969 || xthread_have_id (dpy->lock->locking_thread))) 970 /* some thread is in XProcessInternalConnection or XLockDisplay 971 so we have to see if we are it */ 972 self = XThread_Self(); 973 if (!xthread_have_id(self) 974 || (!xthread_equal(self, dpy->lock->conni_thread) 975 && !xthread_equal(self, dpy->lock->locking_thread))) 976 cvl = QueueEventReaderLock(dpy); 977#endif /* XTHREADS */ 978 979 do { 980#ifdef XTHREADS 981 /* if it is not our turn to read an event off the wire, 982 wait til we're at head of list */ 983 if (dpy->lock && cvl && 984 (dpy->lock->event_awaiters != cvl || 985 dpy->lock->reply_first)) { 986 ConditionWait(dpy, cvl->cv); 987 continue; 988 } 989#endif /* XTHREADS */ 990 /* find out how much data can be read */ 991 if (_X11TransBytesReadable(dpy->trans_conn, &pend) < 0) 992 _XIOError(dpy); 993 len = pend; 994 995 /* must read at least one xEvent; if none is pending, then 996 we'll just flush and block waiting for it */ 997 if (len < SIZEOF(xEvent) 998#ifdef XTHREADS 999 || dpy->async_handlers 1000#endif 1001 ) { 1002 len = SIZEOF(xEvent); 1003 /* don't flush until the first time we would block */ 1004 if (not_yet_flushed) { 1005 _XFlush (dpy); 1006 if (_XNewerQueuedEvent(dpy, entry_event_serial_num)) { 1007 /* _XReply has read an event for us */ 1008 goto got_event; 1009 } 1010 not_yet_flushed = False; 1011 } 1012 } 1013 1014#ifdef XTHREADS 1015 /* If someone is waiting for a reply, gamble that 1016 the reply will be the next thing on the wire 1017 and read it into their buffer. */ 1018 if (dpy->lock && dpy->lock->reply_awaiters) { 1019 read_buf = (char *)dpy->lock->reply_awaiters->buf; 1020 len = SIZEOF(xReply); 1021 } else 1022#endif /* XTHREADS*/ 1023 { 1024 read_buf = buf.buf; 1025 1026 /* but we won't read more than the max buffer size */ 1027 if (len > BUFSIZE) 1028 len = BUFSIZE; 1029 1030 /* round down to an integral number of XReps */ 1031 len = (len / SIZEOF(xEvent)) * SIZEOF(xEvent); 1032 } 1033 1034#ifdef XTHREADS 1035 if (xthread_have_id(self)) 1036 /* save value we may have to stick in conni_thread */ 1037 dpy->lock->reading_thread = self; 1038#endif /* XTHREADS */ 1039 dpy->flags |= XlibDisplayReadEvents; 1040 i = _XRead (dpy, read_buf, (long) len); 1041 dpy->flags &= ~XlibDisplayReadEvents; 1042 if (i == -2) { 1043 /* special flag from _XRead to say that internal connection has 1044 done XPutBackEvent. Which we can use so we're done. */ 1045 got_event: 1046#ifdef XTHREADS 1047 if (dpy->lock && dpy->lock->lock_wait) { 1048 if (dpy->lock->event_awaiters != cvl) 1049 /* since it is not us, must be user lock thread */ 1050 ConditionSignal(dpy, 1051 dpy->lock->event_awaiters->cv); 1052 (*dpy->lock->lock_wait)(dpy); 1053 continue; 1054 } 1055#endif 1056 break; 1057 } 1058#ifdef XTHREADS 1059 if (xthread_have_id(self)) 1060 xthread_clear_id(dpy->lock->reading_thread); 1061 1062 /* what did we actually read: reply or event? */ 1063 if (dpy->lock && dpy->lock->reply_awaiters) { 1064 if (((xReply *)read_buf)->generic.type == X_Reply || 1065 ((xReply *)read_buf)->generic.type == X_Error) 1066 { 1067 dpy->lock->reply_was_read = True; 1068 dpy->lock->reply_first = True; 1069 if (read_buf != (char *)dpy->lock->reply_awaiters->buf) 1070 memcpy(dpy->lock->reply_awaiters->buf, 1071 read_buf, len); 1072 ConditionSignal(dpy, dpy->lock->reply_awaiters->cv); 1073 continue; 1074 } else if (read_buf != buf.buf) 1075 memcpy(buf.buf, read_buf, len); 1076 } 1077#endif /* XTHREADS */ 1078 1079 STARTITERATE(rep,xReply,buf.buf,len > 0) { 1080 if (rep->generic.type == X_Reply) { 1081 RESETITERPTR(rep,xReply, 1082 _XAsyncReply (dpy, rep, 1083 ITERPTR(rep), &len, True)); 1084 pend = len; 1085 } else { 1086 if (rep->generic.type == X_Error) 1087 _XError (dpy, (xError *) rep); 1088 else /* must be an event packet */ 1089 { 1090 if (rep->generic.type == GenericEvent) 1091 { 1092 int evlen; 1093 evlen = (rep->generic.length << 2); 1094 if (_XRead(dpy, &read_buf[len], evlen) == -2) 1095 goto got_event; /* XXX: aargh! */ 1096 } 1097 1098 _XEnq (dpy, (xEvent *)rep); 1099 } 1100 INCITERPTR(rep,xReply); 1101 len -= SIZEOF(xReply); 1102 } 1103 } ENDITERATE; 1104 } while (!_XNewerQueuedEvent(dpy, entry_event_serial_num)); 1105 1106 UnlockNextEventReader(dpy); 1107} 1108 1109/* 1110 * _XRead - Read bytes from the socket taking into account incomplete 1111 * reads. This routine may have to be reworked if int < long. 1112 */ 1113int _XRead( 1114 register Display *dpy, 1115 register char *data, 1116 register long size) 1117{ 1118 register long bytes_read; 1119#ifdef XTHREADS 1120 int original_size = size; 1121#endif 1122 1123 if ((dpy->flags & XlibDisplayIOError) || size == 0) 1124 return 0; 1125 ESET(0); 1126 while ((bytes_read = _X11TransRead(dpy->trans_conn, data, (int)size)) 1127 != size) { 1128 1129 if (bytes_read > 0) { 1130 size -= bytes_read; 1131 data += bytes_read; 1132 } 1133 else if (ETEST()) { 1134 if (_XWaitForReadable(dpy) == -2) 1135 return -2; /* internal connection did XPutBackEvent */ 1136 ESET(0); 1137 } 1138#ifdef SUNSYSV 1139 else if (ECHECK(0)) { 1140 if (_XWaitForReadable(dpy) == -2) 1141 return -2; /* internal connection did XPutBackEvent */ 1142 } 1143#endif 1144 else if (bytes_read == 0) { 1145 /* Read failed because of end of file! */ 1146 ESET(EPIPE); 1147 _XIOError(dpy); 1148 } 1149 1150 else /* bytes_read is less than 0; presumably -1 */ { 1151 /* If it's a system call interrupt, it's not an error. */ 1152 if (!ECHECK(EINTR)) 1153 _XIOError(dpy); 1154 } 1155 } 1156#ifdef XTHREADS 1157 if (dpy->lock && dpy->lock->reply_bytes_left > 0) 1158 { 1159 dpy->lock->reply_bytes_left -= original_size; 1160 if (dpy->lock->reply_bytes_left == 0) { 1161 dpy->flags &= ~XlibDisplayReply; 1162 UnlockNextReplyReader(dpy); 1163 } 1164 } 1165#endif /* XTHREADS*/ 1166 return 0; 1167} 1168#endif /* !USE_XCB */ 1169 1170#ifdef LONG64 1171void _XRead32( 1172 Display *dpy, 1173 register long *data, 1174 long len) 1175{ 1176 register int *buf; 1177 register long i; 1178 1179 if (len) { 1180 (void) _XRead(dpy, (char *)data, len); 1181 i = len >> 2; 1182 buf = (int *)data + i; 1183 data += i; 1184 while (--i >= 0) 1185 *--data = *--buf; 1186 } 1187} 1188#endif /* LONG64 */ 1189 1190#ifdef WORD64 1191 1192/* 1193 * XXX This is a *really* stupid way of doing this.... 1194 * PACKBUFFERSIZE must be a multiple of 4. 1195 */ 1196 1197#define PACKBUFFERSIZE 4096 1198 1199 1200/* 1201 * _XRead32 - Read bytes from the socket unpacking each 32 bits 1202 * into a long (64 bits on a CRAY computer). 1203 * 1204 */ 1205static void _doXRead32( 1206 register Display *dpy, 1207 register long *data 1208 register long size, 1209 register char *packbuffer) 1210{ 1211 long *lpack,*lp; 1212 long mask32 = 0x00000000ffffffff; 1213 long maskw, nwords, i, bits; 1214 1215 _XReadPad (dpy, packbuffer, size); 1216 1217 lp = data; 1218 lpack = (long *) packbuffer; 1219 nwords = size >> 2; 1220 bits = 32; 1221 1222 for(i=0;i<nwords;i++){ 1223 maskw = mask32 << bits; 1224 *lp++ = ( *lpack & maskw ) >> bits; 1225 bits = bits ^32; 1226 if(bits){ 1227 lpack++; 1228 } 1229 } 1230} 1231 1232void _XRead32( 1233 Display *dpy, 1234 long *data, 1235 long len) 1236{ 1237 char packbuffer[PACKBUFFERSIZE]; 1238 unsigned nunits = PACKBUFFERSIZE >> 2; 1239 1240 for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) { 1241 _doXRead32 (dpy, data, PACKBUFFERSIZE, packbuffer); 1242 } 1243 if (len) _doXRead32 (dpy, data, len, packbuffer); 1244} 1245 1246 1247 1248/* 1249 * _XRead16 - Read bytes from the socket unpacking each 16 bits 1250 * into a long (64 bits on a CRAY computer). 1251 * 1252 */ 1253static _doXRead16( 1254 register Display *dpy, 1255 register short *data, 1256 register long size, 1257 char *packbuffer) 1258{ 1259 long *lpack,*lp; 1260 long mask16 = 0x000000000000ffff; 1261 long maskw, nwords, i, bits; 1262 1263 (void) _XRead(dpy,packbuffer,size); /* don't do a padded read... */ 1264 1265 lp = (long *) data; 1266 lpack = (long *) packbuffer; 1267 nwords = size >> 1; /* number of 16 bit words to be unpacked */ 1268 bits = 48; 1269 for(i=0;i<nwords;i++){ 1270 maskw = mask16 << bits; 1271 *lp++ = ( *lpack & maskw ) >> bits; 1272 bits -= 16; 1273 if(bits < 0){ 1274 lpack++; 1275 bits = 48; 1276 } 1277 } 1278} 1279 1280void _XRead16( 1281 Display *dpy, 1282 short *data, 1283 long len) 1284{ 1285 char packbuffer[PACKBUFFERSIZE]; 1286 unsigned nunits = PACKBUFFERSIZE >> 1; 1287 1288 for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) { 1289 _doXRead16 (dpy, data, PACKBUFFERSIZE, packbuffer); 1290 } 1291 if (len) _doXRead16 (dpy, data, len, packbuffer); 1292} 1293 1294void _XRead16Pad( 1295 Display *dpy, 1296 short *data, 1297 long size) 1298{ 1299 int slop = (size & 3); 1300 short slopbuf[3]; 1301 1302 _XRead16 (dpy, data, size); 1303 if (slop > 0) { 1304 _XRead16 (dpy, slopbuf, 4 - slop); 1305 } 1306} 1307#endif /* WORD64 */ 1308 1309 1310#if !USE_XCB 1311/* 1312 * _XReadPad - Read bytes from the socket taking into account incomplete 1313 * reads. If the number of bytes is not 0 mod 4, read additional pad 1314 * bytes. This routine may have to be reworked if int < long. 1315 */ 1316void _XReadPad( 1317 register Display *dpy, 1318 register char *data, 1319 register long size) 1320{ 1321 register long bytes_read; 1322 struct iovec iov[2]; 1323 char pad[3]; 1324#ifdef XTHREADS 1325 int original_size; 1326#endif 1327 1328 if ((dpy->flags & XlibDisplayIOError) || size == 0) return; 1329 iov[0].iov_len = (int)size; 1330 iov[0].iov_base = data; 1331 /* 1332 * The following hack is used to provide 32 bit long-word 1333 * aligned padding. The [1] vector is of length 0, 1, 2, or 3, 1334 * whatever is needed. 1335 */ 1336 1337 iov[1].iov_len = -size & 3; 1338 iov[1].iov_base = pad; 1339 size += iov[1].iov_len; 1340#ifdef XTHREADS 1341 original_size = size; 1342#endif 1343 ESET(0); 1344 while ((bytes_read = _X11TransReadv (dpy->trans_conn, iov, 2)) != size) { 1345 1346 if (bytes_read > 0) { 1347 size -= bytes_read; 1348 if (iov[0].iov_len < bytes_read) { 1349 int pad_bytes_read = bytes_read - iov[0].iov_len; 1350 iov[1].iov_len -= pad_bytes_read; 1351 iov[1].iov_base = 1352 (char *)iov[1].iov_base + pad_bytes_read; 1353 iov[0].iov_len = 0; 1354 } 1355 else { 1356 iov[0].iov_len -= bytes_read; 1357 iov[0].iov_base = (char *)iov[0].iov_base + bytes_read; 1358 } 1359 } 1360 else if (ETEST()) { 1361 _XWaitForReadable(dpy); 1362 ESET(0); 1363 } 1364#ifdef SUNSYSV 1365 else if (ECHECK(0)) { 1366 _XWaitForReadable(dpy); 1367 } 1368#endif 1369 else if (bytes_read == 0) { 1370 /* Read failed because of end of file! */ 1371 ESET(EPIPE); 1372 _XIOError(dpy); 1373 } 1374 1375 else /* bytes_read is less than 0; presumably -1 */ { 1376 /* If it's a system call interrupt, it's not an error. */ 1377 if (!ECHECK(EINTR)) 1378 _XIOError(dpy); 1379 } 1380 } 1381#ifdef XTHREADS 1382 if (dpy->lock && dpy->lock->reply_bytes_left > 0) 1383 { 1384 dpy->lock->reply_bytes_left -= original_size; 1385 if (dpy->lock->reply_bytes_left == 0) { 1386 dpy->flags &= ~XlibDisplayReply; 1387 UnlockNextReplyReader(dpy); 1388 } 1389 } 1390#endif /* XTHREADS*/ 1391} 1392 1393/* 1394 * _XSend - Flush the buffer and send the client data. 32 bit word aligned 1395 * transmission is used, if size is not 0 mod 4, extra bytes are transmitted. 1396 * This routine may have to be reworked if int < long; 1397 */ 1398void 1399_XSend ( 1400 register Display *dpy, 1401 _Xconst char *data, 1402 register long size) 1403{ 1404 struct iovec iov[3]; 1405 static char const pad[3] = {0, 0, 0}; 1406 /* XText8 and XText16 require that the padding bytes be zero! */ 1407 1408 long skip, dbufsize, padsize, total, todo; 1409 _XExtension *ext; 1410 1411 if (!size || (dpy->flags & XlibDisplayIOError)) return; 1412 dbufsize = dpy->bufptr - dpy->buffer; 1413#ifdef XTHREADS 1414 dpy->flags |= XlibDisplayWriting; 1415 /* make sure no one else can put in data */ 1416 dpy->bufptr = dpy->bufmax; 1417#endif 1418 padsize = -size & 3; 1419 for (ext = dpy->flushes; ext; ext = ext->next_flush) { 1420 (*ext->before_flush)(dpy, &ext->codes, dpy->buffer, dbufsize); 1421 (*ext->before_flush)(dpy, &ext->codes, (char *)data, size); 1422 if (padsize) 1423 (*ext->before_flush)(dpy, &ext->codes, pad, padsize); 1424 } 1425 skip = 0; 1426 todo = total = dbufsize + size + padsize; 1427 1428 /* 1429 * There are 3 pieces that may need to be written out: 1430 * 1431 * o whatever is in the display buffer 1432 * o the data passed in by the user 1433 * o any padding needed to 32bit align the whole mess 1434 * 1435 * This loop looks at all 3 pieces each time through. It uses skip 1436 * to figure out whether or not a given piece is needed. 1437 */ 1438 while (total) { 1439 long before = skip; /* amount of whole thing written */ 1440 long remain = todo; /* amount to try this time, <= total */ 1441 int i = 0; 1442 long len; 1443 1444 /* You could be very general here and have "in" and "out" iovecs 1445 * and write a loop without using a macro, but what the heck. This 1446 * translates to: 1447 * 1448 * how much of this piece is new? 1449 * if more new then we are trying this time, clamp 1450 * if nothing new 1451 * then bump down amount already written, for next piece 1452 * else put new stuff in iovec, will need all of next piece 1453 * 1454 * Note that todo had better be at least 1 or else we'll end up 1455 * writing 0 iovecs. 1456 */ 1457#define InsertIOV(pointer, length) \ 1458 len = (length) - before; \ 1459 if (len > remain) \ 1460 len = remain; \ 1461 if (len <= 0) { \ 1462 before = (-len); \ 1463 } else { \ 1464 iov[i].iov_len = len; \ 1465 iov[i].iov_base = (pointer) + before; \ 1466 i++; \ 1467 remain -= len; \ 1468 before = 0; \ 1469 } 1470 1471 InsertIOV (dpy->buffer, dbufsize) 1472 InsertIOV ((char *)data, size) 1473 InsertIOV ((char *)pad, padsize) 1474 1475 ESET(0); 1476 if ((len = _X11TransWritev(dpy->trans_conn, iov, i)) >= 0) { 1477 skip += len; 1478 total -= len; 1479 todo = total; 1480 } else if (ETEST()) { 1481 _XWaitForWritable(dpy 1482#ifdef XTHREADS 1483 , NULL 1484#endif 1485 ); 1486#ifdef SUNSYSV 1487 } else if (ECHECK(0)) { 1488 _XWaitForWritable(dpy 1489#ifdef XTHREADS 1490 , NULL 1491#endif 1492 ); 1493#endif 1494#ifdef ESZTEST 1495 } else if (ESZTEST()) { 1496 if (todo > 1) 1497 todo >>= 1; 1498 else { 1499 _XWaitForWritable(dpy 1500#ifdef XTHREADS 1501 , NULL 1502#endif 1503 ); 1504 } 1505#endif 1506 } else if (!ECHECK(EINTR)) { 1507 _XIOError(dpy); 1508 } 1509 } 1510 dpy->last_req = (char *) & _dummy_request; 1511 _XSetSeqSyncFunction(dpy); 1512 dpy->bufptr = dpy->buffer; 1513#ifdef XTHREADS 1514 dpy->flags &= ~XlibDisplayWriting; 1515#endif 1516 return; 1517} 1518 1519static void 1520_XGetMiscCode( 1521 register Display *dpy) 1522{ 1523 xQueryExtensionReply qrep; 1524 register xQueryExtensionReq *qreq; 1525 xXCMiscGetVersionReply vrep; 1526 register xXCMiscGetVersionReq *vreq; 1527 1528 if (dpy->xcmisc_opcode) 1529 return; 1530 GetReq(QueryExtension, qreq); 1531 qreq->nbytes = sizeof(XCMiscExtensionName) - 1; 1532 qreq->length += (qreq->nbytes+(unsigned)3)>>2; 1533 _XSend(dpy, XCMiscExtensionName, (long)qreq->nbytes); 1534 if (!_XReply (dpy, (xReply *)&qrep, 0, xTrue)) 1535 dpy->xcmisc_opcode = -1; 1536 else { 1537 GetReq(XCMiscGetVersion, vreq); 1538 vreq->reqType = qrep.major_opcode; 1539 vreq->miscReqType = X_XCMiscGetVersion; 1540 vreq->majorVersion = XCMiscMajorVersion; 1541 vreq->minorVersion = XCMiscMinorVersion; 1542 if (!_XReply (dpy, (xReply *)&vrep, 0, xTrue)) 1543 dpy->xcmisc_opcode = -1; 1544 else 1545 dpy->xcmisc_opcode = qrep.major_opcode; 1546 } 1547} 1548 1549void 1550_XIDHandler( 1551 register Display *dpy) 1552{ 1553 xXCMiscGetXIDRangeReply grep; 1554 register xXCMiscGetXIDRangeReq *greq; 1555 1556 if (dpy->resource_max == dpy->resource_mask + 1) { 1557 _XGetMiscCode(dpy); 1558 if (dpy->xcmisc_opcode > 0) { 1559 GetReq(XCMiscGetXIDRange, greq); 1560 greq->reqType = dpy->xcmisc_opcode; 1561 greq->miscReqType = X_XCMiscGetXIDRange; 1562 if (_XReply (dpy, (xReply *)&grep, 0, xTrue) && grep.count) { 1563 dpy->resource_id = ((grep.start_id - dpy->resource_base) >> 1564 dpy->resource_shift); 1565 dpy->resource_max = dpy->resource_id; 1566 if (grep.count > 5) 1567 dpy->resource_max += grep.count - 6; 1568 dpy->resource_max <<= dpy->resource_shift; 1569 } 1570 sync_while_locked(dpy); 1571 } 1572 } 1573} 1574 1575/* 1576 * _XAllocID - resource ID allocation routine. 1577 */ 1578XID _XAllocID( 1579 register Display *dpy) 1580{ 1581 XID id; 1582 1583 id = dpy->resource_id << dpy->resource_shift; 1584 if (id >= dpy->resource_max) { 1585 _XSetPrivSyncFunction(dpy); 1586 dpy->resource_max = dpy->resource_mask + 1; 1587 } 1588 if (id <= dpy->resource_mask) { 1589 dpy->resource_id++; 1590 return (dpy->resource_base + id); 1591 } 1592 if (id != 0x10000000) { 1593 (void) fprintf(stderr, 1594 "Xlib: resource ID allocation space exhausted!\n"); 1595 id = 0x10000000; 1596 dpy->resource_id = id >> dpy->resource_shift; 1597 } 1598 return id; 1599} 1600 1601/* 1602 * _XAllocIDs - multiple resource ID allocation routine. 1603 */ 1604void _XAllocIDs( 1605 register Display *dpy, 1606 XID *ids, 1607 int count) 1608{ 1609 XID id; 1610 int i; 1611 xXCMiscGetXIDListReply grep; 1612 register xXCMiscGetXIDListReq *greq; 1613 1614 id = dpy->resource_id << dpy->resource_shift; 1615 if (dpy->resource_max <= dpy->resource_mask && 1616 id <= dpy->resource_mask && 1617 (dpy->resource_max - id) > ((count - 1) << dpy->resource_shift)) { 1618 id += dpy->resource_base; 1619 for (i = 0; i < count; i++) { 1620 ids[i] = id; 1621 id += (1 << dpy->resource_shift); 1622 dpy->resource_id++; 1623 } 1624 return; 1625 } 1626 grep.count = 0; 1627 _XGetMiscCode(dpy); 1628 if (dpy->xcmisc_opcode > 0) { 1629 GetReq(XCMiscGetXIDList, greq); 1630 greq->reqType = dpy->xcmisc_opcode; 1631 greq->miscReqType = X_XCMiscGetXIDList; 1632 greq->count = count; 1633 if (_XReply(dpy, (xReply *)&grep, 0, xFalse) && grep.count) { 1634 _XRead32(dpy, (long *) ids, 4L * (long) (grep.count)); 1635 for (i = 0; i < grep.count; i++) { 1636 id = (ids[i] - dpy->resource_base) >> dpy->resource_shift; 1637 if (id >= dpy->resource_id) 1638 dpy->resource_id = id; 1639 } 1640 if (id >= dpy->resource_max) { 1641 _XSetPrivSyncFunction(dpy); 1642 dpy->resource_max = dpy->resource_mask + 1; 1643 } 1644 } 1645 } 1646 for (i = grep.count; i < count; i++) 1647 ids[i] = XAllocID(dpy); 1648} 1649#endif /* !USE_XCB */ 1650 1651/* 1652 * The hard part about this is that we only get 16 bits from a reply. 1653 * We have three values that will march along, with the following invariant: 1654 * dpy->last_request_read <= rep->sequenceNumber <= dpy->request 1655 * We have to keep 1656 * dpy->request - dpy->last_request_read < 2^16 1657 * or else we won't know for sure what value to use in events. We do this 1658 * by forcing syncs when we get close. 1659 */ 1660 1661unsigned long 1662_XSetLastRequestRead( 1663 register Display *dpy, 1664 register xGenericReply *rep) 1665{ 1666 register unsigned long newseq, lastseq; 1667 1668 lastseq = dpy->last_request_read; 1669 /* 1670 * KeymapNotify has no sequence number, but is always guaranteed 1671 * to immediately follow another event, except when generated via 1672 * SendEvent (hmmm). 1673 */ 1674 if ((rep->type & 0x7f) == KeymapNotify) 1675 return(lastseq); 1676 1677 newseq = (lastseq & ~((unsigned long)0xffff)) | rep->sequenceNumber; 1678 1679 if (newseq < lastseq) { 1680 newseq += 0x10000; 1681 if (newseq > dpy->request) { 1682 (void) fprintf (stderr, 1683 "Xlib: sequence lost (0x%lx > 0x%lx) in reply type 0x%x!\n", 1684 newseq, dpy->request, 1685 (unsigned int) rep->type); 1686 newseq -= 0x10000; 1687 } 1688 } 1689 1690 dpy->last_request_read = newseq; 1691 return(newseq); 1692} 1693 1694#if !USE_XCB 1695/* 1696 * _XReply - Wait for a reply packet and copy its contents into the 1697 * specified rep. Meanwhile we must handle error and event packets that 1698 * we may encounter. 1699 */ 1700Status 1701_XReply ( 1702 register Display *dpy, 1703 register xReply *rep, 1704 int extra, /* number of 32-bit words expected after the reply */ 1705 Bool discard) /* should I discard data following "extra" words? */ 1706{ 1707 /* Pull out the serial number now, so that (currently illegal) requests 1708 * generated by an error handler don't confuse us. 1709 */ 1710 unsigned long cur_request = dpy->request; 1711#ifdef XTHREADS 1712 struct _XCVList *cvl; 1713#endif 1714 1715 if (dpy->flags & XlibDisplayIOError) 1716 return 0; 1717 1718#ifdef XTHREADS 1719 /* create our condition variable and append to list */ 1720 cvl = QueueReplyReaderLock(dpy); 1721 if (cvl) { 1722 cvl->buf = rep; 1723 if (dpy->lock->reply_awaiters == cvl && !dpy->lock->event_awaiters) 1724 dpy->lock->reply_first = True; 1725 } 1726 1727#ifdef XTHREADS_DEBUG 1728 printf("_XReply called in thread %x, adding %x to cvl\n", 1729 XThread_Self(), cvl); 1730#endif 1731 1732 _XFlushInt(dpy, cvl ? cvl->cv : NULL); 1733 /* if it is not our turn to read a reply off the wire, 1734 * wait til we're at head of list. if there is an event waiter, 1735 * and our reply hasn't been read, they'll be in select and will 1736 * hand control back to us next. 1737 */ 1738 if(dpy->lock && 1739 (dpy->lock->reply_awaiters != cvl || !dpy->lock->reply_first)) { 1740 ConditionWait(dpy, cvl->cv); 1741 } 1742 dpy->flags |= XlibDisplayReply; 1743#else /* XTHREADS else */ 1744 _XFlush(dpy); 1745#endif 1746 1747 for (;;) { 1748#ifdef XTHREADS 1749 /* Did another thread's _XReadEvents get our reply by accident? */ 1750 if (!dpy->lock || !dpy->lock->reply_was_read) 1751#endif 1752 (void) _XRead(dpy, (char *)rep, (long)SIZEOF(xReply)); 1753#ifdef XTHREADS 1754 if (dpy->lock) 1755 dpy->lock->reply_was_read = False; 1756#endif 1757 1758 switch ((int)rep->generic.type) { 1759 1760 case X_Reply: 1761 /* Reply received. Fast update for synchronous replies, 1762 * but deal with multiple outstanding replies. 1763 */ 1764 if (rep->generic.sequenceNumber == (cur_request & 0xffff)) 1765 dpy->last_request_read = cur_request; 1766 else { 1767 int pend = SIZEOF(xReply); 1768 if (_XAsyncReply(dpy, rep, (char *)rep, &pend, False) 1769 != (char *)rep) 1770 continue; 1771 } 1772 if (extra <= rep->generic.length) { 1773 if (extra > 0) 1774 /* 1775 * Read the extra data into storage immediately 1776 * following the GenericReply structure. 1777 */ 1778 (void) _XRead (dpy, (char *) (NEXTPTR(rep,xReply)), 1779 ((long)extra) << 2); 1780 if (discard) { 1781 if (extra < rep->generic.length) 1782 _XEatData(dpy, (rep->generic.length - extra) << 2); 1783 } 1784#ifdef XTHREADS 1785 if (dpy->lock) { 1786 if (discard) { 1787 dpy->lock->reply_bytes_left = 0; 1788 } else { 1789 dpy->lock->reply_bytes_left = 1790 (rep->generic.length - extra) << 2; 1791 } 1792 if (dpy->lock->reply_bytes_left == 0) { 1793 dpy->flags &= ~XlibDisplayReply; 1794 UnlockNextReplyReader(dpy); 1795 } 1796 } else 1797 dpy->flags &= ~XlibDisplayReply; 1798#endif 1799 return 1; 1800 } 1801 /* 1802 *if we get here, then extra > rep->generic.length--meaning we 1803 * read a reply that's shorter than we expected. This is an 1804 * error, but we still need to figure out how to handle it... 1805 */ 1806 (void) _XRead (dpy, (char *) (NEXTPTR(rep,xReply)), 1807 ((long) rep->generic.length) << 2); 1808 dpy->flags &= ~XlibDisplayReply; 1809 UnlockNextReplyReader(dpy); 1810 _XIOError (dpy); 1811 return (0); 1812 1813 case X_Error: 1814 { 1815 register _XExtension *ext; 1816 register Bool ret = False; 1817 int ret_code; 1818 xError *err = (xError *) rep; 1819 unsigned long serial; 1820 1821 dpy->flags &= ~XlibDisplayReply; 1822 serial = _XSetLastRequestRead(dpy, (xGenericReply *)rep); 1823 if (serial == cur_request) 1824 /* do not die on "no such font", "can't allocate", 1825 "can't grab" failures */ 1826 switch ((int)err->errorCode) { 1827 case BadName: 1828 switch (err->majorCode) { 1829 case X_LookupColor: 1830 case X_AllocNamedColor: 1831 UnlockNextReplyReader(dpy); 1832 return(0); 1833 } 1834 break; 1835 case BadFont: 1836 if (err->majorCode == X_QueryFont) { 1837 UnlockNextReplyReader(dpy); 1838 return (0); 1839 } 1840 break; 1841 case BadAlloc: 1842 case BadAccess: 1843 UnlockNextReplyReader(dpy); 1844 return (0); 1845 } 1846 /* 1847 * we better see if there is an extension who may 1848 * want to suppress the error. 1849 */ 1850 for (ext = dpy->ext_procs; !ret && ext; ext = ext->next) { 1851 if (ext->error) 1852 ret = (*ext->error)(dpy, err, &ext->codes, &ret_code); 1853 } 1854 if (!ret) { 1855 _XError(dpy, err); 1856 ret_code = 0; 1857 } 1858 if (serial == cur_request) { 1859 UnlockNextReplyReader(dpy); 1860 return(ret_code); 1861 } 1862 1863 } /* case X_Error */ 1864 break; 1865 default: 1866 _XEnq(dpy, (xEvent *) rep); 1867#ifdef XTHREADS 1868 if (dpy->lock && dpy->lock->event_awaiters) 1869 ConditionSignal(dpy, dpy->lock->event_awaiters->cv); 1870#endif 1871 break; 1872 } 1873 } 1874} 1875 1876static char * 1877_XAsyncReply( 1878 Display *dpy, 1879 register xReply *rep, 1880 char *buf, 1881 register int *lenp, 1882 Bool discard) 1883{ 1884 register _XAsyncHandler *async, *next; 1885 register int len; 1886 register Bool consumed = False; 1887 char *nbuf; 1888 1889 (void) _XSetLastRequestRead(dpy, &rep->generic); 1890 len = SIZEOF(xReply) + (rep->generic.length << 2); 1891 if (len < SIZEOF(xReply)) { 1892 _XIOError (dpy); 1893 buf += *lenp; 1894 *lenp = 0; 1895 return buf; 1896 } 1897 1898 for (async = dpy->async_handlers; async; async = next) { 1899 next = async->next; 1900 if ((consumed = (*async->handler)(dpy, rep, buf, *lenp, async->data))) 1901 break; 1902 } 1903 if (!consumed) { 1904 if (!discard) 1905 return buf; 1906 (void) fprintf(stderr, 1907 "Xlib: unexpected async reply (sequence 0x%lx)!\n", 1908 dpy->last_request_read); 1909#ifdef XTHREADS 1910#ifdef XTHREADS_DEBUG 1911 printf("thread %x, unexpected async reply\n", XThread_Self()); 1912#endif 1913#endif 1914 if (len > *lenp) 1915 _XEatData(dpy, len - *lenp); 1916 } 1917 if (len < SIZEOF(xReply)) 1918 { 1919 _XIOError (dpy); 1920 buf += *lenp; 1921 *lenp = 0; 1922 return buf; 1923 } 1924 if (len >= *lenp) { 1925 buf += *lenp; 1926 *lenp = 0; 1927 return buf; 1928 } 1929 *lenp -= len; 1930 buf += len; 1931 len = *lenp; 1932 nbuf = buf; 1933 while (len > SIZEOF(xReply)) { 1934 if (*buf == X_Reply) 1935 return nbuf; 1936 buf += SIZEOF(xReply); 1937 len -= SIZEOF(xReply); 1938 } 1939 if (len > 0 && len < SIZEOF(xReply)) { 1940 buf = nbuf; 1941 len = SIZEOF(xReply) - len; 1942 nbuf -= len; 1943 memmove(nbuf, buf, *lenp); 1944 (void) _XRead(dpy, nbuf + *lenp, (long)len); 1945 *lenp += len; 1946 } 1947 return nbuf; 1948} 1949#endif /* !USE_XCB */ 1950 1951/* 1952 * Support for internal connections, such as an IM might use. 1953 * By Stephen Gildea, X Consortium, September 1993 1954 */ 1955 1956/* _XRegisterInternalConnection 1957 * Each IM (or Xlib extension) that opens a file descriptor that Xlib should 1958 * include in its select/poll mask must call this function to register the 1959 * fd with Xlib. Any XConnectionWatchProc registered by XAddConnectionWatch 1960 * will also be called. 1961 * 1962 * Whenever Xlib detects input available on fd, it will call callback 1963 * with call_data to process it. If non-Xlib code calls select/poll 1964 * and detects input available, it must call XProcessInternalConnection, 1965 * which will call the associated callback. 1966 * 1967 * Non-Xlib code can learn about these additional fds by calling 1968 * XInternalConnectionNumbers or, more typically, by registering 1969 * a XConnectionWatchProc with XAddConnectionWatch 1970 * to be called when fds are registered or unregistered. 1971 * 1972 * Returns True if registration succeeded, False if not, typically 1973 * because could not allocate memory. 1974 * Assumes Display locked when called. 1975 */ 1976Status 1977_XRegisterInternalConnection( 1978 Display* dpy, 1979 int fd, 1980 _XInternalConnectionProc callback, 1981 XPointer call_data 1982) 1983{ 1984 struct _XConnectionInfo *new_conni, **iptr; 1985 struct _XConnWatchInfo *watchers; 1986 XPointer *wd; 1987 1988 new_conni = (struct _XConnectionInfo*)Xmalloc(sizeof(struct _XConnectionInfo)); 1989 if (!new_conni) 1990 return 0; 1991 new_conni->watch_data = (XPointer *)Xmalloc(dpy->watcher_count * sizeof(XPointer)); 1992 if (!new_conni->watch_data) { 1993 Xfree(new_conni); 1994 return 0; 1995 } 1996 new_conni->fd = fd; 1997 new_conni->read_callback = callback; 1998 new_conni->call_data = call_data; 1999 new_conni->next = NULL; 2000 /* link new structure onto end of list */ 2001 for (iptr = &dpy->im_fd_info; *iptr; iptr = &(*iptr)->next) 2002 ; 2003 *iptr = new_conni; 2004 dpy->im_fd_length++; 2005 _XPollfdCacheAdd(dpy, fd); 2006 2007 for (watchers=dpy->conn_watchers, wd=new_conni->watch_data; 2008 watchers; 2009 watchers=watchers->next, wd++) { 2010 *wd = NULL; /* for cleanliness */ 2011 (*watchers->fn) (dpy, watchers->client_data, fd, True, wd); 2012 } 2013 2014 return 1; 2015} 2016 2017/* _XUnregisterInternalConnection 2018 * Each IM (or Xlib extension) that closes a file descriptor previously 2019 * registered with _XRegisterInternalConnection must call this function. 2020 * Any XConnectionWatchProc registered by XAddConnectionWatch 2021 * will also be called. 2022 * 2023 * Assumes Display locked when called. 2024 */ 2025void 2026_XUnregisterInternalConnection( 2027 Display* dpy, 2028 int fd 2029) 2030{ 2031 struct _XConnectionInfo *info_list, **prev; 2032 struct _XConnWatchInfo *watch; 2033 XPointer *wd; 2034 2035 for (prev = &dpy->im_fd_info; (info_list = *prev); 2036 prev = &info_list->next) { 2037 if (info_list->fd == fd) { 2038 *prev = info_list->next; 2039 dpy->im_fd_length--; 2040 for (watch=dpy->conn_watchers, wd=info_list->watch_data; 2041 watch; 2042 watch=watch->next, wd++) { 2043 (*watch->fn) (dpy, watch->client_data, fd, False, wd); 2044 } 2045 if (info_list->watch_data) 2046 Xfree (info_list->watch_data); 2047 Xfree (info_list); 2048 break; 2049 } 2050 } 2051 _XPollfdCacheDel(dpy, fd); 2052} 2053 2054/* XInternalConnectionNumbers 2055 * Returns an array of fds and an array of corresponding call data. 2056 * Typically a XConnectionWatchProc registered with XAddConnectionWatch 2057 * will be used instead of this function to discover 2058 * additional fds to include in the select/poll mask. 2059 * 2060 * The list is allocated with Xmalloc and should be freed by the caller 2061 * with Xfree; 2062 */ 2063Status 2064XInternalConnectionNumbers( 2065 Display *dpy, 2066 int **fd_return, 2067 int *count_return 2068) 2069{ 2070 int count; 2071 struct _XConnectionInfo *info_list; 2072 int *fd_list; 2073 2074 LockDisplay(dpy); 2075 count = 0; 2076 for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) 2077 count++; 2078 fd_list = (int*) Xmalloc (count * sizeof(int)); 2079 if (!fd_list) { 2080 UnlockDisplay(dpy); 2081 return 0; 2082 } 2083 count = 0; 2084 for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) { 2085 fd_list[count] = info_list->fd; 2086 count++; 2087 } 2088 UnlockDisplay(dpy); 2089 2090 *fd_return = fd_list; 2091 *count_return = count; 2092 return 1; 2093} 2094 2095void _XProcessInternalConnection( 2096 Display *dpy, 2097 struct _XConnectionInfo *conn_info) 2098{ 2099 dpy->flags |= XlibDisplayProcConni; 2100#if defined(XTHREADS) && !USE_XCB 2101 if (dpy->lock) { 2102 /* check cache to avoid call to thread_self */ 2103 if (xthread_have_id(dpy->lock->reading_thread)) 2104 dpy->lock->conni_thread = dpy->lock->reading_thread; 2105 else 2106 dpy->lock->conni_thread = XThread_Self(); 2107 } 2108#endif /* XTHREADS && !USE_XCB */ 2109 UnlockDisplay(dpy); 2110 (*conn_info->read_callback) (dpy, conn_info->fd, conn_info->call_data); 2111 LockDisplay(dpy); 2112#if defined(XTHREADS) && !USE_XCB 2113 if (dpy->lock) 2114 xthread_clear_id(dpy->lock->conni_thread); 2115#endif /* XTHREADS && !USE_XCB */ 2116 dpy->flags &= ~XlibDisplayProcConni; 2117} 2118 2119/* XProcessInternalConnection 2120 * Call the _XInternalConnectionProc registered by _XRegisterInternalConnection 2121 * for this fd. 2122 * The Display is NOT locked during the call. 2123 */ 2124void 2125XProcessInternalConnection( 2126 Display* dpy, 2127 int fd 2128) 2129{ 2130 struct _XConnectionInfo *info_list; 2131 2132 LockDisplay(dpy); 2133 for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) { 2134 if (info_list->fd == fd) { 2135 _XProcessInternalConnection(dpy, info_list); 2136 break; 2137 } 2138 } 2139 UnlockDisplay(dpy); 2140} 2141 2142/* XAddConnectionWatch 2143 * Register a callback to be called whenever _XRegisterInternalConnection 2144 * or _XUnregisterInternalConnection is called. 2145 * Callbacks are called with the Display locked. 2146 * If any connections are already registered, the callback is immediately 2147 * called for each of them. 2148 */ 2149Status 2150XAddConnectionWatch( 2151 Display* dpy, 2152 XConnectionWatchProc callback, 2153 XPointer client_data 2154) 2155{ 2156 struct _XConnWatchInfo *new_watcher, **wptr; 2157 struct _XConnectionInfo *info_list; 2158 XPointer *wd_array; 2159 2160 LockDisplay(dpy); 2161 2162 /* allocate new watch data */ 2163 for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) { 2164 wd_array = (XPointer *)Xrealloc((char *)info_list->watch_data, 2165 (dpy->watcher_count + 1) * 2166 sizeof(XPointer)); 2167 if (!wd_array) { 2168 UnlockDisplay(dpy); 2169 return 0; 2170 } 2171 wd_array[dpy->watcher_count] = NULL; /* for cleanliness */ 2172 } 2173 2174 new_watcher = (struct _XConnWatchInfo*)Xmalloc(sizeof(struct _XConnWatchInfo)); 2175 if (!new_watcher) { 2176 UnlockDisplay(dpy); 2177 return 0; 2178 } 2179 new_watcher->fn = callback; 2180 new_watcher->client_data = client_data; 2181 new_watcher->next = NULL; 2182 2183 /* link new structure onto end of list */ 2184 for (wptr = &dpy->conn_watchers; *wptr; wptr = &(*wptr)->next) 2185 ; 2186 *wptr = new_watcher; 2187 dpy->watcher_count++; 2188 2189 /* call new watcher on all currently registered fds */ 2190 for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) { 2191 (*callback) (dpy, client_data, info_list->fd, True, 2192 info_list->watch_data + dpy->watcher_count - 1); 2193 } 2194 2195 UnlockDisplay(dpy); 2196 return 1; 2197} 2198 2199/* XRemoveConnectionWatch 2200 * Unregister a callback registered by XAddConnectionWatch. 2201 * Both callback and client_data must match what was passed to 2202 * XAddConnectionWatch. 2203 */ 2204void 2205XRemoveConnectionWatch( 2206 Display* dpy, 2207 XConnectionWatchProc callback, 2208 XPointer client_data 2209) 2210{ 2211 struct _XConnWatchInfo *watch; 2212 struct _XConnWatchInfo *previous = NULL; 2213 struct _XConnectionInfo *conni; 2214 int counter = 0; 2215 2216 LockDisplay(dpy); 2217 for (watch=dpy->conn_watchers; watch; watch=watch->next) { 2218 if (watch->fn == callback && watch->client_data == client_data) { 2219 if (previous) 2220 previous->next = watch->next; 2221 else 2222 dpy->conn_watchers = watch->next; 2223 Xfree (watch); 2224 dpy->watcher_count--; 2225 /* remove our watch_data for each connection */ 2226 for (conni=dpy->im_fd_info; conni; conni=conni->next) { 2227 /* don't bother realloc'ing; these arrays are small anyway */ 2228 /* overlapping */ 2229 memmove(conni->watch_data+counter, 2230 conni->watch_data+counter+1, 2231 dpy->watcher_count - counter); 2232 } 2233 break; 2234 } 2235 previous = watch; 2236 counter++; 2237 } 2238 UnlockDisplay(dpy); 2239} 2240 2241/* end of internal connections support */ 2242 2243 2244#if !USE_XCB 2245/* Read and discard "n" 8-bit bytes of data */ 2246 2247void _XEatData( 2248 Display *dpy, 2249 register unsigned long n) 2250{ 2251#define SCRATCHSIZE 2048 2252 char buf[SCRATCHSIZE]; 2253 2254 while (n > 0) { 2255 register long bytes_read = (n > SCRATCHSIZE) ? SCRATCHSIZE : n; 2256 (void) _XRead (dpy, buf, bytes_read); 2257 n -= bytes_read; 2258 } 2259#undef SCRATCHSIZE 2260} 2261#endif /* !USE_XCB */ 2262 2263/* Cookie jar implementation 2264 dpy->cookiejar is a linked list. _XEnq receives the events but leaves 2265 them in the normal EQ. _XStoreEvent returns the cookie event (minus 2266 data pointer) and adds it to the cookiejar. _XDeq just removes 2267 the entry like any other event but resets the data pointer for 2268 cookie events (to avoid double-free, the memory is re-used by Xlib). 2269 2270 _XFetchEventCookie (called from XGetEventData) removes a cookie from the 2271 jar. _XFreeEventCookies removes all unclaimed cookies from the jar 2272 (called by XNextEvent). 2273 2274 _XFreeDisplayStructure calls _XFreeEventCookies for each cookie in the 2275 normal EQ. 2276 */ 2277 2278#include "utlist.h" 2279struct stored_event { 2280 XGenericEventCookie ev; 2281 struct stored_event *prev; 2282 struct stored_event *next; 2283}; 2284 2285Bool 2286_XIsEventCookie(Display *dpy, XEvent *ev) 2287{ 2288 return (ev->xcookie.type == GenericEvent && 2289 dpy->generic_event_vec[ev->xcookie.extension & 0x7F] != NULL); 2290} 2291 2292/** 2293 * Free all events in the event list. 2294 */ 2295void 2296_XFreeEventCookies(Display *dpy) 2297{ 2298 struct stored_event **head, *e, *tmp; 2299 2300 if (!dpy->cookiejar) 2301 return; 2302 2303 head = (struct stored_event**)&dpy->cookiejar; 2304 2305 DL_FOREACH_SAFE(*head, e, tmp) { 2306 XFree(e->ev.data); 2307 XFree(e); 2308 if (dpy->cookiejar == e) 2309 dpy->cookiejar = NULL; 2310 } 2311} 2312 2313/** 2314 * Add an event to the display's event list. This event must be freed on the 2315 * next call to XNextEvent(). 2316 */ 2317void 2318_XStoreEventCookie(Display *dpy, XEvent *event) 2319{ 2320 XGenericEventCookie* cookie = &event->xcookie; 2321 struct stored_event **head, *add; 2322 2323 if (!_XIsEventCookie(dpy, event)) 2324 return; 2325 2326 head = (struct stored_event**)(&dpy->cookiejar); 2327 2328 add = Xmalloc(sizeof(struct stored_event)); 2329 if (!add) { 2330 ESET(ENOMEM); 2331 _XIOError(dpy); 2332 } 2333 add->ev = *cookie; 2334 DL_APPEND(*head, add); 2335 cookie->data = NULL; /* don't return data yet, must be claimed */ 2336} 2337 2338/** 2339 * Return the event with the given cookie and remove it from the list. 2340 */ 2341Bool 2342_XFetchEventCookie(Display *dpy, XGenericEventCookie* ev) 2343{ 2344 Bool ret = False; 2345 struct stored_event **head, *event; 2346 head = (struct stored_event**)&dpy->cookiejar; 2347 2348 if (!_XIsEventCookie(dpy, (XEvent*)ev)) 2349 return ret; 2350 2351 DL_FOREACH(*head, event) { 2352 if (event->ev.cookie == ev->cookie && 2353 event->ev.extension == ev->extension && 2354 event->ev.evtype == ev->evtype) { 2355 *ev = event->ev; 2356 DL_DELETE(*head, event); 2357 Xfree(event); 2358 ret = True; 2359 break; 2360 } 2361 } 2362 2363 return ret; 2364} 2365 2366Bool 2367_XCopyEventCookie(Display *dpy, XGenericEventCookie *in, XGenericEventCookie *out) 2368{ 2369 Bool ret = False; 2370 int extension; 2371 2372 if (!_XIsEventCookie(dpy, (XEvent*)in) || !out) 2373 return ret; 2374 2375 extension = in->extension & 0x7F; 2376 2377 if (!dpy->generic_event_copy_vec[extension]) 2378 return ret; 2379 2380 ret = ((*dpy->generic_event_copy_vec[extension])(dpy, in, out)); 2381 out->cookie = ret ? ++dpy->next_cookie : 0; 2382 return ret; 2383} 2384 2385 2386/* 2387 * _XEnq - Place event packets on the display's queue. 2388 * note that no squishing of move events in V11, since there 2389 * is pointer motion hints.... 2390 */ 2391void _XEnq( 2392 register Display *dpy, 2393 register xEvent *event) 2394{ 2395 register _XQEvent *qelt; 2396 int type, extension; 2397 2398 if ((qelt = dpy->qfree)) { 2399 /* If dpy->qfree is non-NULL do this, else malloc a new one. */ 2400 dpy->qfree = qelt->next; 2401 } 2402 else if ((qelt = 2403 (_XQEvent *) Xmalloc((unsigned)sizeof(_XQEvent))) == NULL) { 2404 /* Malloc call failed! */ 2405 ESET(ENOMEM); 2406 _XIOError(dpy); 2407 } 2408 qelt->next = NULL; 2409 2410 type = event->u.u.type & 0177; 2411 extension = ((xGenericEvent*)event)->extension; 2412 /* If an extension has registerd a generic_event_vec handler, then 2413 * it can handle event cookies. Otherwise, proceed with the normal 2414 * event handlers. 2415 * 2416 * If the generic_event_vec is called, qelt->event is a event cookie 2417 * with the data pointer and the "free" pointer set. Data pointer is 2418 * some memory allocated by the extension. 2419 */ 2420 if (type == GenericEvent && dpy->generic_event_vec[extension & 0x7F]) { 2421 XGenericEventCookie *cookie = &qelt->event.xcookie; 2422 (*dpy->generic_event_vec[extension & 0x7F])(dpy, cookie, event); 2423 cookie->cookie = ++dpy->next_cookie; 2424 2425 qelt->qserial_num = dpy->next_event_serial_num++; 2426 if (dpy->tail) dpy->tail->next = qelt; 2427 else dpy->head = qelt; 2428 2429 dpy->tail = qelt; 2430 dpy->qlen++; 2431 } else if ((*dpy->event_vec[type])(dpy, &qelt->event, event)) { 2432 qelt->qserial_num = dpy->next_event_serial_num++; 2433 if (dpy->tail) dpy->tail->next = qelt; 2434 else dpy->head = qelt; 2435 2436 dpy->tail = qelt; 2437 dpy->qlen++; 2438 } else { 2439 /* ignored, or stashed away for many-to-one compression */ 2440 qelt->next = dpy->qfree; 2441 dpy->qfree = qelt; 2442 } 2443} 2444 2445/* 2446 * _XDeq - Remove event packet from the display's queue. 2447 */ 2448void _XDeq( 2449 register Display *dpy, 2450 register _XQEvent *prev, /* element before qelt */ 2451 register _XQEvent *qelt) /* element to be unlinked */ 2452{ 2453 if (prev) { 2454 if ((prev->next = qelt->next) == NULL) 2455 dpy->tail = prev; 2456 } else { 2457 /* no prev, so removing first elt */ 2458 if ((dpy->head = qelt->next) == NULL) 2459 dpy->tail = NULL; 2460 } 2461 qelt->qserial_num = 0; 2462 qelt->next = dpy->qfree; 2463 dpy->qfree = qelt; 2464 dpy->qlen--; 2465 2466 if (_XIsEventCookie(dpy, &qelt->event)) { 2467 XGenericEventCookie* cookie = &qelt->event.xcookie; 2468 /* dpy->qfree is re-used, reset memory to avoid double free on 2469 * _XFreeDisplayStructure */ 2470 cookie->data = NULL; 2471 } 2472} 2473 2474/* 2475 * EventToWire in separate file in that often not needed. 2476 */ 2477 2478/*ARGSUSED*/ 2479Bool 2480_XUnknownWireEvent( 2481 register Display *dpy, /* pointer to display structure */ 2482 register XEvent *re, /* pointer to where event should be reformatted */ 2483 register xEvent *event) /* wire protocol event */ 2484{ 2485#ifdef notdef 2486 (void) fprintf(stderr, 2487 "Xlib: unhandled wire event! event number = %d, display = %x\n.", 2488 event->u.u.type, dpy); 2489#endif 2490 return(False); 2491} 2492 2493Bool 2494_XUnknownWireEventCookie( 2495 Display *dpy, /* pointer to display structure */ 2496 XGenericEventCookie *re, /* pointer to where event should be reformatted */ 2497 xEvent *event) /* wire protocol event */ 2498{ 2499#ifdef notdef 2500 fprintf(stderr, 2501 "Xlib: unhandled wire cookie event! extension number = %d, display = %x\n.", 2502 ((xGenericEvent*)event)->extension, dpy); 2503#endif 2504 return(False); 2505} 2506 2507Bool 2508_XUnknownCopyEventCookie( 2509 Display *dpy, /* pointer to display structure */ 2510 XGenericEventCookie *in, /* source */ 2511 XGenericEventCookie *out) /* destination */ 2512{ 2513#ifdef notdef 2514 fprintf(stderr, 2515 "Xlib: unhandled cookie event copy! extension number = %d, display = %x\n.", 2516 in->extension, dpy); 2517#endif 2518 return(False); 2519} 2520 2521/*ARGSUSED*/ 2522Status 2523_XUnknownNativeEvent( 2524 register Display *dpy, /* pointer to display structure */ 2525 register XEvent *re, /* pointer to where event should be reformatted */ 2526 register xEvent *event) /* wire protocol event */ 2527{ 2528#ifdef notdef 2529 (void) fprintf(stderr, 2530 "Xlib: unhandled native event! event number = %d, display = %x\n.", 2531 re->type, dpy); 2532#endif 2533 return(0); 2534} 2535/* 2536 * reformat a wire event into an XEvent structure of the right type. 2537 */ 2538Bool 2539_XWireToEvent( 2540 register Display *dpy, /* pointer to display structure */ 2541 register XEvent *re, /* pointer to where event should be reformatted */ 2542 register xEvent *event) /* wire protocol event */ 2543{ 2544 2545 re->type = event->u.u.type & 0x7f; 2546 ((XAnyEvent *)re)->serial = _XSetLastRequestRead(dpy, 2547 (xGenericReply *)event); 2548 ((XAnyEvent *)re)->send_event = ((event->u.u.type & 0x80) != 0); 2549 ((XAnyEvent *)re)->display = dpy; 2550 2551 /* Ignore the leading bit of the event type since it is set when a 2552 client sends an event rather than the server. */ 2553 2554 switch (event-> u.u.type & 0177) { 2555 case KeyPress: 2556 case KeyRelease: 2557 { 2558 register XKeyEvent *ev = (XKeyEvent*) re; 2559 ev->root = event->u.keyButtonPointer.root; 2560 ev->window = event->u.keyButtonPointer.event; 2561 ev->subwindow = event->u.keyButtonPointer.child; 2562 ev->time = event->u.keyButtonPointer.time; 2563 ev->x = cvtINT16toInt(event->u.keyButtonPointer.eventX); 2564 ev->y = cvtINT16toInt(event->u.keyButtonPointer.eventY); 2565 ev->x_root = cvtINT16toInt(event->u.keyButtonPointer.rootX); 2566 ev->y_root = cvtINT16toInt(event->u.keyButtonPointer.rootY); 2567 ev->state = event->u.keyButtonPointer.state; 2568 ev->same_screen = event->u.keyButtonPointer.sameScreen; 2569 ev->keycode = event->u.u.detail; 2570 } 2571 break; 2572 case ButtonPress: 2573 case ButtonRelease: 2574 { 2575 register XButtonEvent *ev = (XButtonEvent *) re; 2576 ev->root = event->u.keyButtonPointer.root; 2577 ev->window = event->u.keyButtonPointer.event; 2578 ev->subwindow = event->u.keyButtonPointer.child; 2579 ev->time = event->u.keyButtonPointer.time; 2580 ev->x = cvtINT16toInt(event->u.keyButtonPointer.eventX); 2581 ev->y = cvtINT16toInt(event->u.keyButtonPointer.eventY); 2582 ev->x_root = cvtINT16toInt(event->u.keyButtonPointer.rootX); 2583 ev->y_root = cvtINT16toInt(event->u.keyButtonPointer.rootY); 2584 ev->state = event->u.keyButtonPointer.state; 2585 ev->same_screen = event->u.keyButtonPointer.sameScreen; 2586 ev->button = event->u.u.detail; 2587 } 2588 break; 2589 case MotionNotify: 2590 { 2591 register XMotionEvent *ev = (XMotionEvent *)re; 2592 ev->root = event->u.keyButtonPointer.root; 2593 ev->window = event->u.keyButtonPointer.event; 2594 ev->subwindow = event->u.keyButtonPointer.child; 2595 ev->time = event->u.keyButtonPointer.time; 2596 ev->x = cvtINT16toInt(event->u.keyButtonPointer.eventX); 2597 ev->y = cvtINT16toInt(event->u.keyButtonPointer.eventY); 2598 ev->x_root = cvtINT16toInt(event->u.keyButtonPointer.rootX); 2599 ev->y_root = cvtINT16toInt(event->u.keyButtonPointer.rootY); 2600 ev->state = event->u.keyButtonPointer.state; 2601 ev->same_screen = event->u.keyButtonPointer.sameScreen; 2602 ev->is_hint = event->u.u.detail; 2603 } 2604 break; 2605 case EnterNotify: 2606 case LeaveNotify: 2607 { 2608 register XCrossingEvent *ev = (XCrossingEvent *) re; 2609 ev->root = event->u.enterLeave.root; 2610 ev->window = event->u.enterLeave.event; 2611 ev->subwindow = event->u.enterLeave.child; 2612 ev->time = event->u.enterLeave.time; 2613 ev->x = cvtINT16toInt(event->u.enterLeave.eventX); 2614 ev->y = cvtINT16toInt(event->u.enterLeave.eventY); 2615 ev->x_root = cvtINT16toInt(event->u.enterLeave.rootX); 2616 ev->y_root = cvtINT16toInt(event->u.enterLeave.rootY); 2617 ev->state = event->u.enterLeave.state; 2618 ev->mode = event->u.enterLeave.mode; 2619 ev->same_screen = (event->u.enterLeave.flags & 2620 ELFlagSameScreen) && True; 2621 ev->focus = (event->u.enterLeave.flags & 2622 ELFlagFocus) && True; 2623 ev->detail = event->u.u.detail; 2624 } 2625 break; 2626 case FocusIn: 2627 case FocusOut: 2628 { 2629 register XFocusChangeEvent *ev = (XFocusChangeEvent *) re; 2630 ev->window = event->u.focus.window; 2631 ev->mode = event->u.focus.mode; 2632 ev->detail = event->u.u.detail; 2633 } 2634 break; 2635 case KeymapNotify: 2636 { 2637 register XKeymapEvent *ev = (XKeymapEvent *) re; 2638 ev->window = None; 2639 memcpy(&ev->key_vector[1], 2640 (char *)((xKeymapEvent *) event)->map, 2641 sizeof (((xKeymapEvent *) event)->map)); 2642 } 2643 break; 2644 case Expose: 2645 { 2646 register XExposeEvent *ev = (XExposeEvent *) re; 2647 ev->window = event->u.expose.window; 2648 ev->x = event->u.expose.x; 2649 ev->y = event->u.expose.y; 2650 ev->width = event->u.expose.width; 2651 ev->height = event->u.expose.height; 2652 ev->count = event->u.expose.count; 2653 } 2654 break; 2655 case GraphicsExpose: 2656 { 2657 register XGraphicsExposeEvent *ev = 2658 (XGraphicsExposeEvent *) re; 2659 ev->drawable = event->u.graphicsExposure.drawable; 2660 ev->x = event->u.graphicsExposure.x; 2661 ev->y = event->u.graphicsExposure.y; 2662 ev->width = event->u.graphicsExposure.width; 2663 ev->height = event->u.graphicsExposure.height; 2664 ev->count = event->u.graphicsExposure.count; 2665 ev->major_code = event->u.graphicsExposure.majorEvent; 2666 ev->minor_code = event->u.graphicsExposure.minorEvent; 2667 } 2668 break; 2669 case NoExpose: 2670 { 2671 register XNoExposeEvent *ev = (XNoExposeEvent *) re; 2672 ev->drawable = event->u.noExposure.drawable; 2673 ev->major_code = event->u.noExposure.majorEvent; 2674 ev->minor_code = event->u.noExposure.minorEvent; 2675 } 2676 break; 2677 case VisibilityNotify: 2678 { 2679 register XVisibilityEvent *ev = (XVisibilityEvent *) re; 2680 ev->window = event->u.visibility.window; 2681 ev->state = event->u.visibility.state; 2682 } 2683 break; 2684 case CreateNotify: 2685 { 2686 register XCreateWindowEvent *ev = 2687 (XCreateWindowEvent *) re; 2688 ev->window = event->u.createNotify.window; 2689 ev->parent = event->u.createNotify.parent; 2690 ev->x = cvtINT16toInt(event->u.createNotify.x); 2691 ev->y = cvtINT16toInt(event->u.createNotify.y); 2692 ev->width = event->u.createNotify.width; 2693 ev->height = event->u.createNotify.height; 2694 ev->border_width = event->u.createNotify.borderWidth; 2695 ev->override_redirect = event->u.createNotify.override; 2696 } 2697 break; 2698 case DestroyNotify: 2699 { 2700 register XDestroyWindowEvent *ev = 2701 (XDestroyWindowEvent *) re; 2702 ev->window = event->u.destroyNotify.window; 2703 ev->event = event->u.destroyNotify.event; 2704 } 2705 break; 2706 case UnmapNotify: 2707 { 2708 register XUnmapEvent *ev = (XUnmapEvent *) re; 2709 ev->window = event->u.unmapNotify.window; 2710 ev->event = event->u.unmapNotify.event; 2711 ev->from_configure = event->u.unmapNotify.fromConfigure; 2712 } 2713 break; 2714 case MapNotify: 2715 { 2716 register XMapEvent *ev = (XMapEvent *) re; 2717 ev->window = event->u.mapNotify.window; 2718 ev->event = event->u.mapNotify.event; 2719 ev->override_redirect = event->u.mapNotify.override; 2720 } 2721 break; 2722 case MapRequest: 2723 { 2724 register XMapRequestEvent *ev = (XMapRequestEvent *) re; 2725 ev->window = event->u.mapRequest.window; 2726 ev->parent = event->u.mapRequest.parent; 2727 } 2728 break; 2729 case ReparentNotify: 2730 { 2731 register XReparentEvent *ev = (XReparentEvent *) re; 2732 ev->event = event->u.reparent.event; 2733 ev->window = event->u.reparent.window; 2734 ev->parent = event->u.reparent.parent; 2735 ev->x = cvtINT16toInt(event->u.reparent.x); 2736 ev->y = cvtINT16toInt(event->u.reparent.y); 2737 ev->override_redirect = event->u.reparent.override; 2738 } 2739 break; 2740 case ConfigureNotify: 2741 { 2742 register XConfigureEvent *ev = (XConfigureEvent *) re; 2743 ev->event = event->u.configureNotify.event; 2744 ev->window = event->u.configureNotify.window; 2745 ev->above = event->u.configureNotify.aboveSibling; 2746 ev->x = cvtINT16toInt(event->u.configureNotify.x); 2747 ev->y = cvtINT16toInt(event->u.configureNotify.y); 2748 ev->width = event->u.configureNotify.width; 2749 ev->height = event->u.configureNotify.height; 2750 ev->border_width = event->u.configureNotify.borderWidth; 2751 ev->override_redirect = event->u.configureNotify.override; 2752 } 2753 break; 2754 case ConfigureRequest: 2755 { 2756 register XConfigureRequestEvent *ev = 2757 (XConfigureRequestEvent *) re; 2758 ev->window = event->u.configureRequest.window; 2759 ev->parent = event->u.configureRequest.parent; 2760 ev->above = event->u.configureRequest.sibling; 2761 ev->x = cvtINT16toInt(event->u.configureRequest.x); 2762 ev->y = cvtINT16toInt(event->u.configureRequest.y); 2763 ev->width = event->u.configureRequest.width; 2764 ev->height = event->u.configureRequest.height; 2765 ev->border_width = event->u.configureRequest.borderWidth; 2766 ev->value_mask = event->u.configureRequest.valueMask; 2767 ev->detail = event->u.u.detail; 2768 } 2769 break; 2770 case GravityNotify: 2771 { 2772 register XGravityEvent *ev = (XGravityEvent *) re; 2773 ev->window = event->u.gravity.window; 2774 ev->event = event->u.gravity.event; 2775 ev->x = cvtINT16toInt(event->u.gravity.x); 2776 ev->y = cvtINT16toInt(event->u.gravity.y); 2777 } 2778 break; 2779 case ResizeRequest: 2780 { 2781 register XResizeRequestEvent *ev = 2782 (XResizeRequestEvent *) re; 2783 ev->window = event->u.resizeRequest.window; 2784 ev->width = event->u.resizeRequest.width; 2785 ev->height = event->u.resizeRequest.height; 2786 } 2787 break; 2788 case CirculateNotify: 2789 { 2790 register XCirculateEvent *ev = (XCirculateEvent *) re; 2791 ev->window = event->u.circulate.window; 2792 ev->event = event->u.circulate.event; 2793 ev->place = event->u.circulate.place; 2794 } 2795 break; 2796 case CirculateRequest: 2797 { 2798 register XCirculateRequestEvent *ev = 2799 (XCirculateRequestEvent *) re; 2800 ev->window = event->u.circulate.window; 2801 ev->parent = event->u.circulate.event; 2802 ev->place = event->u.circulate.place; 2803 } 2804 break; 2805 case PropertyNotify: 2806 { 2807 register XPropertyEvent *ev = (XPropertyEvent *) re; 2808 ev->window = event->u.property.window; 2809 ev->atom = event->u.property.atom; 2810 ev->time = event->u.property.time; 2811 ev->state = event->u.property.state; 2812 } 2813 break; 2814 case SelectionClear: 2815 { 2816 register XSelectionClearEvent *ev = 2817 (XSelectionClearEvent *) re; 2818 ev->window = event->u.selectionClear.window; 2819 ev->selection = event->u.selectionClear.atom; 2820 ev->time = event->u.selectionClear.time; 2821 } 2822 break; 2823 case SelectionRequest: 2824 { 2825 register XSelectionRequestEvent *ev = 2826 (XSelectionRequestEvent *) re; 2827 ev->owner = event->u.selectionRequest.owner; 2828 ev->requestor = event->u.selectionRequest.requestor; 2829 ev->selection = event->u.selectionRequest.selection; 2830 ev->target = event->u.selectionRequest.target; 2831 ev->property = event->u.selectionRequest.property; 2832 ev->time = event->u.selectionRequest.time; 2833 } 2834 break; 2835 case SelectionNotify: 2836 { 2837 register XSelectionEvent *ev = (XSelectionEvent *) re; 2838 ev->requestor = event->u.selectionNotify.requestor; 2839 ev->selection = event->u.selectionNotify.selection; 2840 ev->target = event->u.selectionNotify.target; 2841 ev->property = event->u.selectionNotify.property; 2842 ev->time = event->u.selectionNotify.time; 2843 } 2844 break; 2845 case ColormapNotify: 2846 { 2847 register XColormapEvent *ev = (XColormapEvent *) re; 2848 ev->window = event->u.colormap.window; 2849 ev->colormap = event->u.colormap.colormap; 2850 ev->new = event->u.colormap.new; 2851 ev->state = event->u.colormap.state; 2852 } 2853 break; 2854 case ClientMessage: 2855 { 2856 register int i; 2857 register XClientMessageEvent *ev 2858 = (XClientMessageEvent *) re; 2859 ev->window = event->u.clientMessage.window; 2860 ev->format = event->u.u.detail; 2861 switch (ev->format) { 2862 case 8: 2863 ev->message_type = event->u.clientMessage.u.b.type; 2864 for (i = 0; i < 20; i++) 2865 ev->data.b[i] = event->u.clientMessage.u.b.bytes[i]; 2866 break; 2867 case 16: 2868 ev->message_type = event->u.clientMessage.u.s.type; 2869 ev->data.s[0] = cvtINT16toShort(event->u.clientMessage.u.s.shorts0); 2870 ev->data.s[1] = cvtINT16toShort(event->u.clientMessage.u.s.shorts1); 2871 ev->data.s[2] = cvtINT16toShort(event->u.clientMessage.u.s.shorts2); 2872 ev->data.s[3] = cvtINT16toShort(event->u.clientMessage.u.s.shorts3); 2873 ev->data.s[4] = cvtINT16toShort(event->u.clientMessage.u.s.shorts4); 2874 ev->data.s[5] = cvtINT16toShort(event->u.clientMessage.u.s.shorts5); 2875 ev->data.s[6] = cvtINT16toShort(event->u.clientMessage.u.s.shorts6); 2876 ev->data.s[7] = cvtINT16toShort(event->u.clientMessage.u.s.shorts7); 2877 ev->data.s[8] = cvtINT16toShort(event->u.clientMessage.u.s.shorts8); 2878 ev->data.s[9] = cvtINT16toShort(event->u.clientMessage.u.s.shorts9); 2879 break; 2880 case 32: 2881 ev->message_type = event->u.clientMessage.u.l.type; 2882 ev->data.l[0] = cvtINT32toLong(event->u.clientMessage.u.l.longs0); 2883 ev->data.l[1] = cvtINT32toLong(event->u.clientMessage.u.l.longs1); 2884 ev->data.l[2] = cvtINT32toLong(event->u.clientMessage.u.l.longs2); 2885 ev->data.l[3] = cvtINT32toLong(event->u.clientMessage.u.l.longs3); 2886 ev->data.l[4] = cvtINT32toLong(event->u.clientMessage.u.l.longs4); 2887 break; 2888 default: /* XXX should never occur */ 2889 break; 2890 } 2891 } 2892 break; 2893 case MappingNotify: 2894 { 2895 register XMappingEvent *ev = (XMappingEvent *)re; 2896 ev->window = 0; 2897 ev->first_keycode = event->u.mappingNotify.firstKeyCode; 2898 ev->request = event->u.mappingNotify.request; 2899 ev->count = event->u.mappingNotify.count; 2900 } 2901 break; 2902 default: 2903 return(_XUnknownWireEvent(dpy, re, event)); 2904 } 2905 return(True); 2906} 2907 2908 2909/* 2910 * _XDefaultIOError - Default fatal system error reporting routine. Called 2911 * when an X internal system error is encountered. 2912 */ 2913int _XDefaultIOError( 2914 Display *dpy) 2915{ 2916 if (ECHECK(EPIPE)) { 2917 (void) fprintf (stderr, 2918 "X connection to %s broken (explicit kill or server shutdown).\r\n", 2919 DisplayString (dpy)); 2920 } else { 2921 (void) fprintf (stderr, 2922 "XIO: fatal IO error %d (%s) on X server \"%s\"\r\n", 2923#ifdef WIN32 2924 WSAGetLastError(), strerror(WSAGetLastError()), 2925#else 2926 errno, strerror (errno), 2927#endif 2928 DisplayString (dpy)); 2929 (void) fprintf (stderr, 2930 " after %lu requests (%lu known processed) with %d events remaining.\r\n", 2931 NextRequest(dpy) - 1, LastKnownRequestProcessed(dpy), 2932 QLength(dpy)); 2933 2934 } 2935 exit(1); 2936 return(0); /* dummy - function should never return */ 2937} 2938 2939 2940static int _XPrintDefaultError( 2941 Display *dpy, 2942 XErrorEvent *event, 2943 FILE *fp) 2944{ 2945 char buffer[BUFSIZ]; 2946 char mesg[BUFSIZ]; 2947 char number[32]; 2948 const char *mtype = "XlibMessage"; 2949 register _XExtension *ext = (_XExtension *)NULL; 2950 _XExtension *bext = (_XExtension *)NULL; 2951 XGetErrorText(dpy, event->error_code, buffer, BUFSIZ); 2952 XGetErrorDatabaseText(dpy, mtype, "XError", "X Error", mesg, BUFSIZ); 2953 (void) fprintf(fp, "%s: %s\n ", mesg, buffer); 2954 XGetErrorDatabaseText(dpy, mtype, "MajorCode", "Request Major code %d", 2955 mesg, BUFSIZ); 2956 (void) fprintf(fp, mesg, event->request_code); 2957 if (event->request_code < 128) { 2958 sprintf(number, "%d", event->request_code); 2959 XGetErrorDatabaseText(dpy, "XRequest", number, "", buffer, BUFSIZ); 2960 } else { 2961 for (ext = dpy->ext_procs; 2962 ext && (ext->codes.major_opcode != event->request_code); 2963 ext = ext->next) 2964 ; 2965 if (ext) 2966 strcpy(buffer, ext->name); 2967 else 2968 buffer[0] = '\0'; 2969 } 2970 (void) fprintf(fp, " (%s)\n", buffer); 2971 if (event->request_code >= 128) { 2972 XGetErrorDatabaseText(dpy, mtype, "MinorCode", "Request Minor code %d", 2973 mesg, BUFSIZ); 2974 fputs(" ", fp); 2975 (void) fprintf(fp, mesg, event->minor_code); 2976 if (ext) { 2977 sprintf(mesg, "%s.%d", ext->name, event->minor_code); 2978 XGetErrorDatabaseText(dpy, "XRequest", mesg, "", buffer, BUFSIZ); 2979 (void) fprintf(fp, " (%s)", buffer); 2980 } 2981 fputs("\n", fp); 2982 } 2983 if (event->error_code >= 128) { 2984 /* kludge, try to find the extension that caused it */ 2985 buffer[0] = '\0'; 2986 for (ext = dpy->ext_procs; ext; ext = ext->next) { 2987 if (ext->error_string) 2988 (*ext->error_string)(dpy, event->error_code, &ext->codes, 2989 buffer, BUFSIZ); 2990 if (buffer[0]) { 2991 bext = ext; 2992 break; 2993 } 2994 if (ext->codes.first_error && 2995 ext->codes.first_error < (int)event->error_code && 2996 (!bext || ext->codes.first_error > bext->codes.first_error)) 2997 bext = ext; 2998 } 2999 if (bext) 3000 sprintf(buffer, "%s.%d", bext->name, 3001 event->error_code - bext->codes.first_error); 3002 else 3003 strcpy(buffer, "Value"); 3004 XGetErrorDatabaseText(dpy, mtype, buffer, "", mesg, BUFSIZ); 3005 if (mesg[0]) { 3006 fputs(" ", fp); 3007 (void) fprintf(fp, mesg, event->resourceid); 3008 fputs("\n", fp); 3009 } 3010 /* let extensions try to print the values */ 3011 for (ext = dpy->ext_procs; ext; ext = ext->next) { 3012 if (ext->error_values) 3013 (*ext->error_values)(dpy, event, fp); 3014 } 3015 } else if ((event->error_code == BadWindow) || 3016 (event->error_code == BadPixmap) || 3017 (event->error_code == BadCursor) || 3018 (event->error_code == BadFont) || 3019 (event->error_code == BadDrawable) || 3020 (event->error_code == BadColor) || 3021 (event->error_code == BadGC) || 3022 (event->error_code == BadIDChoice) || 3023 (event->error_code == BadValue) || 3024 (event->error_code == BadAtom)) { 3025 if (event->error_code == BadValue) 3026 XGetErrorDatabaseText(dpy, mtype, "Value", "Value 0x%x", 3027 mesg, BUFSIZ); 3028 else if (event->error_code == BadAtom) 3029 XGetErrorDatabaseText(dpy, mtype, "AtomID", "AtomID 0x%x", 3030 mesg, BUFSIZ); 3031 else 3032 XGetErrorDatabaseText(dpy, mtype, "ResourceID", "ResourceID 0x%x", 3033 mesg, BUFSIZ); 3034 fputs(" ", fp); 3035 (void) fprintf(fp, mesg, event->resourceid); 3036 fputs("\n", fp); 3037 } 3038 XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d", 3039 mesg, BUFSIZ); 3040 fputs(" ", fp); 3041 (void) fprintf(fp, mesg, event->serial); 3042 XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%d", 3043 mesg, BUFSIZ); 3044 fputs("\n ", fp); 3045 (void) fprintf(fp, mesg, dpy->request); 3046 fputs("\n", fp); 3047 if (event->error_code == BadImplementation) return 0; 3048 return 1; 3049} 3050 3051int _XDefaultError( 3052 Display *dpy, 3053 XErrorEvent *event) 3054{ 3055 if (_XPrintDefaultError (dpy, event, stderr) == 0) return 0; 3056 exit(1); 3057 /*NOTREACHED*/ 3058} 3059 3060/*ARGSUSED*/ 3061Bool _XDefaultWireError(Display *display, XErrorEvent *he, xError *we) 3062{ 3063 return True; 3064} 3065 3066/* 3067 * _XError - upcall internal or user protocol error handler 3068 */ 3069int _XError ( 3070 Display *dpy, 3071 register xError *rep) 3072{ 3073 /* 3074 * X_Error packet encountered! We need to unpack the error before 3075 * giving it to the user. 3076 */ 3077 XEvent event; /* make it a large event */ 3078 register _XAsyncHandler *async, *next; 3079 3080 event.xerror.serial = _XSetLastRequestRead(dpy, (xGenericReply *)rep); 3081 3082 for (async = dpy->async_handlers; async; async = next) { 3083 next = async->next; 3084 if ((*async->handler)(dpy, (xReply *)rep, 3085 (char *)rep, SIZEOF(xError), async->data)) 3086 return 0; 3087 } 3088 3089 event.xerror.display = dpy; 3090 event.xerror.type = X_Error; 3091 event.xerror.resourceid = rep->resourceID; 3092 event.xerror.error_code = rep->errorCode; 3093 event.xerror.request_code = rep->majorCode; 3094 event.xerror.minor_code = rep->minorCode; 3095 if (dpy->error_vec && 3096 !(*dpy->error_vec[rep->errorCode])(dpy, &event.xerror, rep)) 3097 return 0; 3098 if (_XErrorFunction != NULL) { 3099 int rtn_val; 3100#if defined(XTHREADS) && !USE_XCB 3101 if (dpy->lock) 3102 (*dpy->lock->user_lock_display)(dpy); 3103 UnlockDisplay(dpy); 3104#endif /* XTHREADS && !USE_XCB */ 3105 rtn_val = (*_XErrorFunction)(dpy, (XErrorEvent *)&event); /* upcall */ 3106#if defined(XTHREADS) && !USE_XCB 3107 LockDisplay(dpy); 3108 if (dpy->lock) 3109 (*dpy->lock->user_unlock_display)(dpy); 3110#endif /* XTHREADS && !USE_XCB */ 3111 return rtn_val; 3112 } else { 3113 return _XDefaultError(dpy, (XErrorEvent *)&event); 3114 } 3115} 3116 3117/* 3118 * _XIOError - call user connection error handler and exit 3119 */ 3120int 3121_XIOError ( 3122 Display *dpy) 3123{ 3124 dpy->flags |= XlibDisplayIOError; 3125#ifdef WIN32 3126 errno = WSAGetLastError(); 3127#endif 3128 3129 /* This assumes that the thread calling exit will call any atexit handlers. 3130 * If this does not hold, then an alternate solution would involve 3131 * registering an atexit handler to take over the lock, which would only 3132 * assume that the same thread calls all the atexit handlers. */ 3133#ifdef XTHREADS 3134 if (dpy->lock) 3135 (*dpy->lock->user_lock_display)(dpy); 3136#endif 3137 UnlockDisplay(dpy); 3138 3139 if (_XIOErrorFunction != NULL) 3140 (*_XIOErrorFunction)(dpy); 3141 else 3142 _XDefaultIOError(dpy); 3143 exit (1); 3144 return 0; 3145} 3146 3147 3148/* 3149 * This routine can be used to (cheaply) get some memory within a single 3150 * Xlib routine for scratch space. A single buffer is reused each time 3151 * if possible. To be MT safe, you can only call this between a call to 3152 * GetReq* and a call to Data* or _XSend*, or in a context when the thread 3153 * is guaranteed to not unlock the display. 3154 */ 3155char *_XAllocScratch( 3156 register Display *dpy, 3157 unsigned long nbytes) 3158{ 3159 if (nbytes > dpy->scratch_length) { 3160 if (dpy->scratch_buffer) Xfree (dpy->scratch_buffer); 3161 if ((dpy->scratch_buffer = Xmalloc((unsigned) nbytes))) 3162 dpy->scratch_length = nbytes; 3163 else dpy->scratch_length = 0; 3164 } 3165 return (dpy->scratch_buffer); 3166} 3167 3168/* 3169 * Scratch space allocator you can call any time, multiple times, and be 3170 * MT safe, but you must hand the buffer back with _XFreeTemp. 3171 */ 3172char *_XAllocTemp( 3173 register Display *dpy, 3174 unsigned long nbytes) 3175{ 3176 char *buf; 3177 3178 buf = _XAllocScratch(dpy, nbytes); 3179 dpy->scratch_buffer = NULL; 3180 dpy->scratch_length = 0; 3181 return buf; 3182} 3183 3184void _XFreeTemp( 3185 register Display *dpy, 3186 char *buf, 3187 unsigned long nbytes) 3188{ 3189 if (dpy->scratch_buffer) 3190 Xfree(dpy->scratch_buffer); 3191 dpy->scratch_buffer = buf; 3192 dpy->scratch_length = nbytes; 3193} 3194 3195/* 3196 * Given a visual id, find the visual structure for this id on this display. 3197 */ 3198Visual *_XVIDtoVisual( 3199 Display *dpy, 3200 VisualID id) 3201{ 3202 register int i, j, k; 3203 register Screen *sp; 3204 register Depth *dp; 3205 register Visual *vp; 3206 for (i = 0; i < dpy->nscreens; i++) { 3207 sp = &dpy->screens[i]; 3208 for (j = 0; j < sp->ndepths; j++) { 3209 dp = &sp->depths[j]; 3210 /* if nvisuals == 0 then visuals will be NULL */ 3211 for (k = 0; k < dp->nvisuals; k++) { 3212 vp = &dp->visuals[k]; 3213 if (vp->visualid == id) return (vp); 3214 } 3215 } 3216 } 3217 return (NULL); 3218} 3219 3220int 3221XFree (void *data) 3222{ 3223 Xfree (data); 3224 return 1; 3225} 3226 3227#ifdef _XNEEDBCOPYFUNC 3228void _Xbcopy(b1, b2, length) 3229 register char *b1, *b2; 3230 register length; 3231{ 3232 if (b1 < b2) { 3233 b2 += length; 3234 b1 += length; 3235 while (length--) 3236 *--b2 = *--b1; 3237 } else { 3238 while (length--) 3239 *b2++ = *b1++; 3240 } 3241} 3242#endif 3243 3244#ifdef DataRoutineIsProcedure 3245void Data( 3246 Display *dpy, 3247 char *data, 3248 long len) 3249{ 3250 if (dpy->bufptr + (len) <= dpy->bufmax) { 3251 memcpy(dpy->bufptr, data, (int)len); 3252 dpy->bufptr += ((len) + 3) & ~3; 3253 } else { 3254 _XSend(dpy, data, len); 3255 } 3256} 3257#endif /* DataRoutineIsProcedure */ 3258 3259 3260#ifdef LONG64 3261int 3262_XData32( 3263 Display *dpy, 3264 register long *data, 3265 unsigned len) 3266{ 3267 register int *buf; 3268 register long i; 3269 3270 while (len) { 3271 buf = (int *)dpy->bufptr; 3272 i = dpy->bufmax - (char *)buf; 3273 if (!i) { 3274 _XFlush(dpy); 3275 continue; 3276 } 3277 if (len < i) 3278 i = len; 3279 dpy->bufptr = (char *)buf + i; 3280 len -= i; 3281 i >>= 2; 3282 while (--i >= 0) 3283 *buf++ = *data++; 3284 } 3285 return 0; 3286} 3287#endif /* LONG64 */ 3288 3289#ifdef WORD64 3290 3291/* 3292 * XXX This is a *really* stupid way of doing this. It should just use 3293 * dpy->bufptr directly, taking into account where in the word it is. 3294 */ 3295 3296/* 3297 * Data16 - Place 16 bit data in the buffer. 3298 * 3299 * "dpy" is a pointer to a Display. 3300 * "data" is a pointer to the data. 3301 * "len" is the length in bytes of the data. 3302 */ 3303 3304static doData16( 3305 register Display *dpy, 3306 short *data, 3307 unsigned len, 3308 char *packbuffer) 3309{ 3310 long *lp,*lpack; 3311 long i, nwords,bits; 3312 long mask16 = 0x000000000000ffff; 3313 3314 lp = (long *)data; 3315 lpack = (long *)packbuffer; 3316 3317/* nwords is the number of 16 bit values to be packed, 3318 * the low order 16 bits of each word will be packed 3319 * into 64 bit words 3320 */ 3321 nwords = len >> 1; 3322 bits = 48; 3323 3324 for(i=0;i<nwords;i++){ 3325 if (bits == 48) *lpack = 0; 3326 *lpack ^= (*lp & mask16) << bits; 3327 bits -= 16 ; 3328 lp++; 3329 if(bits < 0){ 3330 lpack++; 3331 bits = 48; 3332 } 3333 } 3334 Data(dpy, packbuffer, len); 3335} 3336 3337_XData16 ( 3338 Display *dpy, 3339 short *data, 3340 unsigned len) 3341{ 3342 char packbuffer[PACKBUFFERSIZE]; 3343 unsigned nunits = PACKBUFFERSIZE >> 1; 3344 3345 for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) { 3346 doData16 (dpy, data, PACKBUFFERSIZE, packbuffer); 3347 } 3348 if (len) doData16 (dpy, data, len, packbuffer); 3349} 3350 3351/* 3352 * Data32 - Place 32 bit data in the buffer. 3353 * 3354 * "dpy" is a pointer to a Display. 3355 * "data" is a pointer to the data. 3356 * "len" is the length in bytes of the data. 3357 */ 3358 3359static doData32( 3360 register Display *dpy 3361 long *data, 3362 unsigned len, 3363 char *packbuffer) 3364{ 3365 long *lp,*lpack; 3366 long i,bits,nwords; 3367 long mask32 = 0x00000000ffffffff; 3368 3369 lpack = (long *) packbuffer; 3370 lp = data; 3371 3372/* nwords is the number of 32 bit values to be packed 3373 * the low order 32 bits of each word will be packed 3374 * into 64 bit words 3375 */ 3376 nwords = len >> 2; 3377 bits = 32; 3378 3379 for(i=0;i<nwords;i++){ 3380 if (bits == 32) *lpack = 0; 3381 *lpack ^= (*lp & mask32) << bits; 3382 bits = bits ^32; 3383 lp++; 3384 if(bits) 3385 lpack++; 3386 } 3387 Data(dpy, packbuffer, len); 3388} 3389 3390void _XData32( 3391 Display *dpy, 3392 long *data, 3393 unsigned len) 3394{ 3395 char packbuffer[PACKBUFFERSIZE]; 3396 unsigned nunits = PACKBUFFERSIZE >> 2; 3397 3398 for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) { 3399 doData32 (dpy, data, PACKBUFFERSIZE, packbuffer); 3400 } 3401 if (len) doData32 (dpy, data, len, packbuffer); 3402} 3403 3404#endif /* WORD64 */ 3405 3406 3407/* Make sure this produces the same string as DefineLocal/DefineSelf in xdm. 3408 * Otherwise, Xau will not be able to find your cookies in the Xauthority file. 3409 * 3410 * Note: POSIX says that the ``nodename'' member of utsname does _not_ have 3411 * to have sufficient information for interfacing to the network, 3412 * and so, you may be better off using gethostname (if it exists). 3413 */ 3414 3415#if (defined(_POSIX_SOURCE) && !defined(AIXV3) && !defined(__QNX__)) || defined(hpux) || defined(SVR4) 3416#define NEED_UTSNAME 3417#include <sys/utsname.h> 3418#else 3419#ifdef HAVE_UNISTD_H 3420#include <unistd.h> 3421#endif 3422#endif 3423 3424/* 3425 * _XGetHostname - similar to gethostname but allows special processing. 3426 */ 3427int _XGetHostname ( 3428 char *buf, 3429 int maxlen) 3430{ 3431 int len; 3432 3433#ifdef NEED_UTSNAME 3434 struct utsname name; 3435 3436 if (maxlen <= 0 || buf == NULL) 3437 return 0; 3438 3439 uname (&name); 3440 len = strlen (name.nodename); 3441 if (len >= maxlen) len = maxlen - 1; 3442 strncpy (buf, name.nodename, len); 3443 buf[len] = '\0'; 3444#else 3445 if (maxlen <= 0 || buf == NULL) 3446 return 0; 3447 3448 buf[0] = '\0'; 3449 (void) gethostname (buf, maxlen); 3450 buf [maxlen - 1] = '\0'; 3451 len = strlen(buf); 3452#endif /* NEED_UTSNAME */ 3453 return len; 3454} 3455 3456 3457/* 3458 * _XScreenOfWindow - get the Screen of a given window 3459 */ 3460 3461Screen *_XScreenOfWindow(Display *dpy, Window w) 3462{ 3463 register int i; 3464 Window root; 3465 int x, y; /* dummy variables */ 3466 unsigned int width, height, bw, depth; /* dummy variables */ 3467 3468 if (XGetGeometry (dpy, w, &root, &x, &y, &width, &height, 3469 &bw, &depth) == False) { 3470 return NULL; 3471 } 3472 for (i = 0; i < ScreenCount (dpy); i++) { /* find root from list */ 3473 if (root == RootWindow (dpy, i)) { 3474 return ScreenOfDisplay (dpy, i); 3475 } 3476 } 3477 return NULL; 3478} 3479 3480 3481#if defined(WIN32) 3482 3483/* 3484 * These functions are intended to be used internally to Xlib only. 3485 * These functions will always prefix the path with a DOS drive in the 3486 * form "<drive-letter>:". As such, these functions are only suitable 3487 * for use by Xlib function that supply a root-based path to some 3488 * particular file, e.g. <ProjectRoot>/lib/X11/locale/locale.dir will 3489 * be converted to "C:/usr/X11R6.3/lib/X11/locale/locale.dir". 3490 */ 3491 3492static int access_file (path, pathbuf, len_pathbuf, pathret) 3493 char* path; 3494 char* pathbuf; 3495 int len_pathbuf; 3496 char** pathret; 3497{ 3498 if (access (path, F_OK) == 0) { 3499 if (strlen (path) < len_pathbuf) 3500 *pathret = pathbuf; 3501 else 3502 *pathret = Xmalloc (strlen (path) + 1); 3503 if (*pathret) { 3504 strcpy (*pathret, path); 3505 return 1; 3506 } 3507 } 3508 return 0; 3509} 3510 3511static int AccessFile (path, pathbuf, len_pathbuf, pathret) 3512 char* path; 3513 char* pathbuf; 3514 int len_pathbuf; 3515 char** pathret; 3516{ 3517 unsigned long drives; 3518 int i, len; 3519 char* drive; 3520 char buf[MAX_PATH]; 3521 char* bufp; 3522 3523 /* just try the "raw" name first and see if it works */ 3524 if (access_file (path, pathbuf, len_pathbuf, pathret)) 3525 return 1; 3526 3527 /* try the places set in the environment */ 3528 drive = getenv ("_XBASEDRIVE"); 3529#ifdef __UNIXOS2__ 3530 if (!drive) 3531 drive = getenv ("X11ROOT"); 3532#endif 3533 if (!drive) 3534 drive = "C:"; 3535 len = strlen (drive) + strlen (path); 3536 if (len < MAX_PATH) bufp = buf; 3537 else bufp = Xmalloc (len + 1); 3538 strcpy (bufp, drive); 3539 strcat (bufp, path); 3540 if (access_file (bufp, pathbuf, len_pathbuf, pathret)) { 3541 if (bufp != buf) Xfree (bufp); 3542 return 1; 3543 } 3544 3545#ifndef __UNIXOS2__ 3546 /* one last place to look */ 3547 drive = getenv ("HOMEDRIVE"); 3548 if (drive) { 3549 len = strlen (drive) + strlen (path); 3550 if (len < MAX_PATH) bufp = buf; 3551 else bufp = Xmalloc (len + 1); 3552 strcpy (bufp, drive); 3553 strcat (bufp, path); 3554 if (access_file (bufp, pathbuf, len_pathbuf, pathret)) { 3555 if (bufp != buf) Xfree (bufp); 3556 return 1; 3557 } 3558 } 3559 3560 /* tried everywhere else, go fishing */ 3561#define C_DRIVE ('C' - 'A') 3562#define Z_DRIVE ('Z' - 'A') 3563 /* does OS/2 (with or with gcc-emx) have getdrives? */ 3564 drives = _getdrives (); 3565 for (i = C_DRIVE; i <= Z_DRIVE; i++) { /* don't check on A: or B: */ 3566 if ((1 << i) & drives) { 3567 len = 2 + strlen (path); 3568 if (len < MAX_PATH) bufp = buf; 3569 else bufp = Xmalloc (len + 1); 3570 *bufp = 'A' + i; 3571 *(bufp + 1) = ':'; 3572 *(bufp + 2) = '\0'; 3573 strcat (bufp, path); 3574 if (access_file (bufp, pathbuf, len_pathbuf, pathret)) { 3575 if (bufp != buf) Xfree (bufp); 3576 return 1; 3577 } 3578 } 3579 } 3580#endif 3581 return 0; 3582} 3583 3584int _XOpenFile(path, flags) 3585 _Xconst char* path; 3586 int flags; 3587{ 3588 char buf[MAX_PATH]; 3589 char* bufp = NULL; 3590 int ret = -1; 3591 UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS); 3592 3593 if (AccessFile (path, buf, MAX_PATH, &bufp)) 3594 ret = open (bufp, flags); 3595 3596 (void) SetErrorMode (olderror); 3597 3598 if (bufp != buf) Xfree (bufp); 3599 3600 return ret; 3601} 3602 3603int _XOpenFileMode(path, flags, mode) 3604 _Xconst char* path; 3605 int flags; 3606 mode_t mode; 3607{ 3608 char buf[MAX_PATH]; 3609 char* bufp = NULL; 3610 int ret = -1; 3611 UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS); 3612 3613 if (AccessFile (path, buf, MAX_PATH, &bufp)) 3614 ret = open (bufp, flags, mode); 3615 3616 (void) SetErrorMode (olderror); 3617 3618 if (bufp != buf) Xfree (bufp); 3619 3620 return ret; 3621} 3622 3623void* _XFopenFile(path, mode) 3624 _Xconst char* path; 3625 _Xconst char* mode; 3626{ 3627 char buf[MAX_PATH]; 3628 char* bufp = NULL; 3629 void* ret = NULL; 3630 UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS); 3631 3632 if (AccessFile (path, buf, MAX_PATH, &bufp)) 3633 ret = fopen (bufp, mode); 3634 3635 (void) SetErrorMode (olderror); 3636 3637 if (bufp != buf) Xfree (bufp); 3638 3639 return ret; 3640} 3641 3642int _XAccessFile(path) 3643 _Xconst char* path; 3644{ 3645 char buf[MAX_PATH]; 3646 char* bufp; 3647 int ret = -1; 3648 UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS); 3649 3650 ret = AccessFile (path, buf, MAX_PATH, &bufp); 3651 3652 (void) SetErrorMode (olderror); 3653 3654 if (bufp != buf) Xfree (bufp); 3655 3656 return ret; 3657} 3658 3659#endif 3660 3661#ifdef WIN32 3662#undef _Xdebug 3663int _Xdebug = 0; 3664int *_Xdebug_p = &_Xdebug; 3665void (**_XCreateMutex_fn_p)(LockInfoPtr) = &_XCreateMutex_fn; 3666void (**_XFreeMutex_fn_p)(LockInfoPtr) = &_XFreeMutex_fn; 3667void (**_XLockMutex_fn_p)(LockInfoPtr 3668#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE) 3669 , char * /* file */ 3670 , int /* line */ 3671#endif 3672 ) = &_XLockMutex_fn; 3673void (**_XUnlockMutex_fn_p)(LockInfoPtr 3674#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE) 3675 , char * /* file */ 3676 , int /* line */ 3677#endif 3678 ) = &_XUnlockMutex_fn; 3679LockInfoPtr *_Xglobal_lock_p = &_Xglobal_lock; 3680#endif 3681