diff options
Diffstat (limited to 'libX11')
-rw-r--r-- | libX11/src/XlibInt.c | 4288 | ||||
-rw-r--r-- | libX11/src/xkb/XKB.c | 1534 | ||||
-rw-r--r-- | libX11/src/xkb/XKBList.c | 496 | ||||
-rw-r--r-- | libX11/src/xkb/XKBMisc.c | 1956 |
4 files changed, 4138 insertions, 4136 deletions
diff --git a/libX11/src/XlibInt.c b/libX11/src/XlibInt.c index 11e8dfdf8..c385f4cbf 100644 --- a/libX11/src/XlibInt.c +++ b/libX11/src/XlibInt.c @@ -1,2144 +1,2144 @@ -/*
-
-Copyright 1985, 1986, 1987, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall
-not be used in advertising or otherwise to promote the sale, use or
-other dealings in this Software without prior written authorization
-from The Open Group.
-
-*/
-
-/*
- * XlibInt.c - Internal support routines for the C subroutine
- * interface library (Xlib) to the X Window System Protocol V11.0.
- */
-
-#ifdef WIN32
-#define _XLIBINT_
-#endif
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include "Xlibint.h"
-#include "Xprivate.h"
-#include <X11/Xpoll.h>
-#include <assert.h>
-#include <stdio.h>
-#ifdef WIN32
-#include <direct.h>
-#endif
-
-#ifdef XTHREADS
-#include "locking.h"
-
-/* these pointers get initialized by XInitThreads */
-LockInfoPtr _Xglobal_lock = NULL;
-void (*_XCreateMutex_fn)(LockInfoPtr) = NULL;
-/* struct _XCVList *(*_XCreateCVL_fn)() = NULL; */
-void (*_XFreeMutex_fn)(LockInfoPtr) = NULL;
-void (*_XLockMutex_fn)(
- LockInfoPtr /* lock */
-#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
- , char * /* file */
- , int /* line */
-#endif
- ) = NULL;
-void (*_XUnlockMutex_fn)(
- LockInfoPtr /* lock */
-#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
- , char * /* file */
- , int /* line */
-#endif
- ) = NULL;
-xthread_t (*_Xthread_self_fn)(void) = NULL;
-
-#define XThread_Self() ((*_Xthread_self_fn)())
-
-#endif /* XTHREADS */
-
-/* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX
- * systems are broken and return EWOULDBLOCK when they should return EAGAIN
- */
-#ifdef WIN32
-#define ETEST() (WSAGetLastError() == WSAEWOULDBLOCK)
-#else
-#ifdef __CYGWIN__ /* Cygwin uses ENOBUFS to signal socket is full */
-#define ETEST() (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS)
-#else
-#if defined(EAGAIN) && defined(EWOULDBLOCK)
-#define ETEST() (errno == EAGAIN || errno == EWOULDBLOCK)
-#else
-#ifdef EAGAIN
-#define ETEST() (errno == EAGAIN)
-#else
-#define ETEST() (errno == EWOULDBLOCK)
-#endif /* EAGAIN */
-#endif /* EAGAIN && EWOULDBLOCK */
-#endif /* __CYGWIN__ */
-#endif /* WIN32 */
-
-#ifdef WIN32
-#define ECHECK(err) (WSAGetLastError() == err)
-#define ESET(val) WSASetLastError(val)
-#else
-#ifdef __UNIXOS2__
-#define ECHECK(err) (errno == err)
-#define ESET(val)
-#else
-#define ECHECK(err) (errno == err)
-#define ESET(val) errno = val
-#endif
-#endif
-
-#if defined(LOCALCONN) || defined(LACHMAN)
-#ifdef EMSGSIZE
-#define ESZTEST() (ECHECK(EMSGSIZE) || ECHECK(ERANGE))
-#else
-#define ESZTEST() ECHECK(ERANGE)
-#endif
-#else
-#ifdef EMSGSIZE
-#define ESZTEST() ECHECK(EMSGSIZE)
-#endif
-#endif
-
-#ifdef __UNIXOS2__
-#include <limits.h>
-#define MAX_PATH _POSIX_PATH_MAX
-#endif
-
-/*
- * The following routines are internal routines used by Xlib for protocol
- * packet transmission and reception.
- *
- * _XIOError(Display *) will be called if any sort of system call error occurs.
- * This is assumed to be a fatal condition, i.e., XIOError should not return.
- *
- * _XError(Display *, xError *) will be called whenever an X_Error event is
- * received. This is not assumed to be a fatal condition, i.e., it is
- * acceptable for this procedure to return. However, XError should NOT
- * perform any operations (directly or indirectly) on the DISPLAY.
- *
- * Routines declared with a return type of 'Status' return 0 on failure,
- * and non 0 on success. Routines with no declared return type don't
- * return anything. Whenever possible routines that create objects return
- * the object they have created.
- */
-
-#define POLLFD_CACHE_SIZE 5
-
-/* initialize the struct array passed to poll() below */
-Bool _XPollfdCacheInit(
- Display *dpy)
-{
-#ifdef USE_POLL
- struct pollfd *pfp;
-
- pfp = (struct pollfd *)Xmalloc(POLLFD_CACHE_SIZE * sizeof(struct pollfd));
- if (!pfp)
- return False;
- pfp[0].fd = dpy->fd;
- pfp[0].events = POLLIN;
-
- dpy->filedes = (XPointer)pfp;
-#endif
- return True;
-}
-
-void _XPollfdCacheAdd(
- Display *dpy,
- int fd)
-{
-#ifdef USE_POLL
- struct pollfd *pfp = (struct pollfd *)dpy->filedes;
-
- if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) {
- pfp[dpy->im_fd_length].fd = fd;
- pfp[dpy->im_fd_length].events = POLLIN;
- }
-#endif
-}
-
-/* ARGSUSED */
-void _XPollfdCacheDel(
- Display *dpy,
- int fd) /* not used */
-{
-#ifdef USE_POLL
- struct pollfd *pfp = (struct pollfd *)dpy->filedes;
- struct _XConnectionInfo *conni;
-
- /* just recalculate whole list */
- if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) {
- int loc = 1;
- for (conni = dpy->im_fd_info; conni; conni=conni->next) {
- pfp[loc].fd = conni->fd;
- pfp[loc].events = POLLIN;
- loc++;
- }
- }
-#endif
-}
-
-static int sync_hazard(Display *dpy)
-{
- unsigned long span = dpy->request - dpy->last_request_read;
- unsigned long hazard = min((dpy->bufmax - dpy->buffer) / SIZEOF(xReq), 65535 - 10);
- return span >= 65535 - hazard - 10;
-}
-
-static
-void sync_while_locked(Display *dpy)
-{
-#ifdef XTHREADS
- if (dpy->lock)
- (*dpy->lock->user_lock_display)(dpy);
-#endif
- UnlockDisplay(dpy);
- SyncHandle();
- InternalLockDisplay(dpy, /* don't skip user locks */ 0);
-#ifdef XTHREADS
- if (dpy->lock)
- (*dpy->lock->user_unlock_display)(dpy);
-#endif
-}
-
-void _XSeqSyncFunction(
- register Display *dpy)
-{
- xGetInputFocusReply rep;
- register xReq *req;
-
- if ((dpy->request - dpy->last_request_read) >= (65535 - BUFSIZE/SIZEOF(xReq))) {
- GetEmptyReq(GetInputFocus, req);
- (void) _XReply (dpy, (xReply *)&rep, 0, xTrue);
- sync_while_locked(dpy);
- } else if (sync_hazard(dpy))
- _XSetPrivSyncFunction(dpy);
-}
-
-/* NOTE: only called if !XTHREADS, or when XInitThreads wasn't called. */
-static int
-_XPrivSyncFunction (Display *dpy)
-{
-#if XTHREADS
- assert(!dpy->lock_fns);
-#endif
- assert(dpy->synchandler == _XPrivSyncFunction);
- assert((dpy->flags & XlibDisplayPrivSync) != 0);
- dpy->synchandler = dpy->savedsynchandler;
- dpy->savedsynchandler = NULL;
- dpy->flags &= ~XlibDisplayPrivSync;
- if(dpy->synchandler)
- dpy->synchandler(dpy);
- _XIDHandler(dpy);
- _XSeqSyncFunction(dpy);
- return 0;
-}
-
-void _XSetPrivSyncFunction(Display *dpy)
-{
-#ifdef XTHREADS
- if (dpy->lock_fns)
- return;
-#endif
- if (!(dpy->flags & XlibDisplayPrivSync)) {
- dpy->savedsynchandler = dpy->synchandler;
- dpy->synchandler = _XPrivSyncFunction;
- dpy->flags |= XlibDisplayPrivSync;
- }
-}
-
-void _XSetSeqSyncFunction(Display *dpy)
-{
- if (sync_hazard(dpy))
- _XSetPrivSyncFunction (dpy);
-}
-
-#ifdef LONG64
-void _XRead32(
- Display *dpy,
- register long *data,
- long len)
-{
- register int *buf;
- register long i;
-
- if (len) {
- (void) _XRead(dpy, (char *)data, len);
- i = len >> 2;
- buf = (int *)data + i;
- data += i;
- while (--i >= 0)
- *--data = *--buf;
- }
-}
-#endif /* LONG64 */
-
-#ifdef WORD64
-
-/*
- * XXX This is a *really* stupid way of doing this....
- * PACKBUFFERSIZE must be a multiple of 4.
- */
-
-#define PACKBUFFERSIZE 4096
-
-
-/*
- * _XRead32 - Read bytes from the socket unpacking each 32 bits
- * into a long (64 bits on a CRAY computer).
- *
- */
-static void _doXRead32(
- register Display *dpy,
- register long *data
- register long size,
- register char *packbuffer)
-{
- long *lpack,*lp;
- long mask32 = 0x00000000ffffffff;
- long maskw, nwords, i, bits;
-
- _XReadPad (dpy, packbuffer, size);
-
- lp = data;
- lpack = (long *) packbuffer;
- nwords = size >> 2;
- bits = 32;
-
- for(i=0;i<nwords;i++){
- maskw = mask32 << bits;
- *lp++ = ( *lpack & maskw ) >> bits;
- bits = bits ^32;
- if(bits){
- lpack++;
- }
- }
-}
-
-void _XRead32(
- Display *dpy,
- long *data,
- long len)
-{
- char packbuffer[PACKBUFFERSIZE];
- unsigned nunits = PACKBUFFERSIZE >> 2;
-
- for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) {
- _doXRead32 (dpy, data, PACKBUFFERSIZE, packbuffer);
- }
- if (len) _doXRead32 (dpy, data, len, packbuffer);
-}
-
-
-
-/*
- * _XRead16 - Read bytes from the socket unpacking each 16 bits
- * into a long (64 bits on a CRAY computer).
- *
- */
-static _doXRead16(
- register Display *dpy,
- register short *data,
- register long size,
- char *packbuffer)
-{
- long *lpack,*lp;
- long mask16 = 0x000000000000ffff;
- long maskw, nwords, i, bits;
-
- (void) _XRead(dpy,packbuffer,size); /* don't do a padded read... */
-
- lp = (long *) data;
- lpack = (long *) packbuffer;
- nwords = size >> 1; /* number of 16 bit words to be unpacked */
- bits = 48;
- for(i=0;i<nwords;i++){
- maskw = mask16 << bits;
- *lp++ = ( *lpack & maskw ) >> bits;
- bits -= 16;
- if(bits < 0){
- lpack++;
- bits = 48;
- }
- }
-}
-
-void _XRead16(
- Display *dpy,
- short *data,
- long len)
-{
- char packbuffer[PACKBUFFERSIZE];
- unsigned nunits = PACKBUFFERSIZE >> 1;
-
- for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) {
- _doXRead16 (dpy, data, PACKBUFFERSIZE, packbuffer);
- }
- if (len) _doXRead16 (dpy, data, len, packbuffer);
-}
-
-void _XRead16Pad(
- Display *dpy,
- short *data,
- long size)
-{
- int slop = (size & 3);
- short slopbuf[3];
-
- _XRead16 (dpy, data, size);
- if (slop > 0) {
- _XRead16 (dpy, slopbuf, 4 - slop);
- }
-}
-#endif /* WORD64 */
-
-/*
- * The hard part about this is that we only get 16 bits from a reply.
- * We have three values that will march along, with the following invariant:
- * dpy->last_request_read <= rep->sequenceNumber <= dpy->request
- * We have to keep
- * dpy->request - dpy->last_request_read < 2^16
- * or else we won't know for sure what value to use in events. We do this
- * by forcing syncs when we get close.
- */
-
-unsigned long
-_XSetLastRequestRead(
- register Display *dpy,
- register xGenericReply *rep)
-{
- register unsigned long newseq, lastseq;
-
- lastseq = dpy->last_request_read;
- /*
- * KeymapNotify has no sequence number, but is always guaranteed
- * to immediately follow another event, except when generated via
- * SendEvent (hmmm).
- */
- if ((rep->type & 0x7f) == KeymapNotify)
- return(lastseq);
-
- newseq = (lastseq & ~((unsigned long)0xffff)) | rep->sequenceNumber;
-
- if (newseq < lastseq) {
- newseq += 0x10000;
- if (newseq > dpy->request) {
- (void) fprintf (stderr,
- "Xlib: sequence lost (0x%lx > 0x%lx) in reply type 0x%x!\n",
- newseq, dpy->request,
- (unsigned int) rep->type);
- newseq -= 0x10000;
- }
- }
-
- dpy->last_request_read = newseq;
- return(newseq);
-}
-
-/*
- * Support for internal connections, such as an IM might use.
- * By Stephen Gildea, X Consortium, September 1993
- */
-
-/* _XRegisterInternalConnection
- * Each IM (or Xlib extension) that opens a file descriptor that Xlib should
- * include in its select/poll mask must call this function to register the
- * fd with Xlib. Any XConnectionWatchProc registered by XAddConnectionWatch
- * will also be called.
- *
- * Whenever Xlib detects input available on fd, it will call callback
- * with call_data to process it. If non-Xlib code calls select/poll
- * and detects input available, it must call XProcessInternalConnection,
- * which will call the associated callback.
- *
- * Non-Xlib code can learn about these additional fds by calling
- * XInternalConnectionNumbers or, more typically, by registering
- * a XConnectionWatchProc with XAddConnectionWatch
- * to be called when fds are registered or unregistered.
- *
- * Returns True if registration succeeded, False if not, typically
- * because could not allocate memory.
- * Assumes Display locked when called.
- */
-Status
-_XRegisterInternalConnection(
- Display* dpy,
- int fd,
- _XInternalConnectionProc callback,
- XPointer call_data
-)
-{
- struct _XConnectionInfo *new_conni, **iptr;
- struct _XConnWatchInfo *watchers;
- XPointer *wd;
-
- new_conni = (struct _XConnectionInfo*)Xmalloc(sizeof(struct _XConnectionInfo));
- if (!new_conni)
- return 0;
- new_conni->watch_data = (XPointer *)Xmalloc(dpy->watcher_count * sizeof(XPointer));
- if (!new_conni->watch_data) {
- Xfree(new_conni);
- return 0;
- }
- new_conni->fd = fd;
- new_conni->read_callback = callback;
- new_conni->call_data = call_data;
- new_conni->next = NULL;
- /* link new structure onto end of list */
- for (iptr = &dpy->im_fd_info; *iptr; iptr = &(*iptr)->next)
- ;
- *iptr = new_conni;
- dpy->im_fd_length++;
- _XPollfdCacheAdd(dpy, fd);
-
- for (watchers=dpy->conn_watchers, wd=new_conni->watch_data;
- watchers;
- watchers=watchers->next, wd++) {
- *wd = NULL; /* for cleanliness */
- (*watchers->fn) (dpy, watchers->client_data, fd, True, wd);
- }
-
- return 1;
-}
-
-/* _XUnregisterInternalConnection
- * Each IM (or Xlib extension) that closes a file descriptor previously
- * registered with _XRegisterInternalConnection must call this function.
- * Any XConnectionWatchProc registered by XAddConnectionWatch
- * will also be called.
- *
- * Assumes Display locked when called.
- */
-void
-_XUnregisterInternalConnection(
- Display* dpy,
- int fd
-)
-{
- struct _XConnectionInfo *info_list, **prev;
- struct _XConnWatchInfo *watch;
- XPointer *wd;
-
- for (prev = &dpy->im_fd_info; (info_list = *prev);
- prev = &info_list->next) {
- if (info_list->fd == fd) {
- *prev = info_list->next;
- dpy->im_fd_length--;
- for (watch=dpy->conn_watchers, wd=info_list->watch_data;
- watch;
- watch=watch->next, wd++) {
- (*watch->fn) (dpy, watch->client_data, fd, False, wd);
- }
- if (info_list->watch_data)
- Xfree (info_list->watch_data);
- Xfree (info_list);
- break;
- }
- }
- _XPollfdCacheDel(dpy, fd);
-}
-
-/* XInternalConnectionNumbers
- * Returns an array of fds and an array of corresponding call data.
- * Typically a XConnectionWatchProc registered with XAddConnectionWatch
- * will be used instead of this function to discover
- * additional fds to include in the select/poll mask.
- *
- * The list is allocated with Xmalloc and should be freed by the caller
- * with Xfree;
- */
-Status
-XInternalConnectionNumbers(
- Display *dpy,
- int **fd_return,
- int *count_return
-)
-{
- int count;
- struct _XConnectionInfo *info_list;
- int *fd_list;
-
- LockDisplay(dpy);
- count = 0;
- for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next)
- count++;
- fd_list = (int*) Xmalloc (count * sizeof(int));
- if (!fd_list) {
- UnlockDisplay(dpy);
- return 0;
- }
- count = 0;
- for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
- fd_list[count] = info_list->fd;
- count++;
- }
- UnlockDisplay(dpy);
-
- *fd_return = fd_list;
- *count_return = count;
- return 1;
-}
-
-void _XProcessInternalConnection(
- Display *dpy,
- struct _XConnectionInfo *conn_info)
-{
- dpy->flags |= XlibDisplayProcConni;
- UnlockDisplay(dpy);
- (*conn_info->read_callback) (dpy, conn_info->fd, conn_info->call_data);
- LockDisplay(dpy);
- dpy->flags &= ~XlibDisplayProcConni;
-}
-
-/* XProcessInternalConnection
- * Call the _XInternalConnectionProc registered by _XRegisterInternalConnection
- * for this fd.
- * The Display is NOT locked during the call.
- */
-void
-XProcessInternalConnection(
- Display* dpy,
- int fd
-)
-{
- struct _XConnectionInfo *info_list;
-
- LockDisplay(dpy);
- for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
- if (info_list->fd == fd) {
- _XProcessInternalConnection(dpy, info_list);
- break;
- }
- }
- UnlockDisplay(dpy);
-}
-
-/* XAddConnectionWatch
- * Register a callback to be called whenever _XRegisterInternalConnection
- * or _XUnregisterInternalConnection is called.
- * Callbacks are called with the Display locked.
- * If any connections are already registered, the callback is immediately
- * called for each of them.
- */
-Status
-XAddConnectionWatch(
- Display* dpy,
- XConnectionWatchProc callback,
- XPointer client_data
-)
-{
- struct _XConnWatchInfo *new_watcher, **wptr;
- struct _XConnectionInfo *info_list;
- XPointer *wd_array;
-
- LockDisplay(dpy);
-
- /* allocate new watch data */
- for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
- wd_array = (XPointer *)Xrealloc((char *)info_list->watch_data,
- (dpy->watcher_count + 1) *
- sizeof(XPointer));
- if (!wd_array) {
- UnlockDisplay(dpy);
- return 0;
- }
- wd_array[dpy->watcher_count] = NULL; /* for cleanliness */
- }
-
- new_watcher = (struct _XConnWatchInfo*)Xmalloc(sizeof(struct _XConnWatchInfo));
- if (!new_watcher) {
- UnlockDisplay(dpy);
- return 0;
- }
- new_watcher->fn = callback;
- new_watcher->client_data = client_data;
- new_watcher->next = NULL;
-
- /* link new structure onto end of list */
- for (wptr = &dpy->conn_watchers; *wptr; wptr = &(*wptr)->next)
- ;
- *wptr = new_watcher;
- dpy->watcher_count++;
-
- /* call new watcher on all currently registered fds */
- for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
- (*callback) (dpy, client_data, info_list->fd, True,
- info_list->watch_data + dpy->watcher_count - 1);
- }
-
- UnlockDisplay(dpy);
- return 1;
-}
-
-/* XRemoveConnectionWatch
- * Unregister a callback registered by XAddConnectionWatch.
- * Both callback and client_data must match what was passed to
- * XAddConnectionWatch.
- */
-void
-XRemoveConnectionWatch(
- Display* dpy,
- XConnectionWatchProc callback,
- XPointer client_data
-)
-{
- struct _XConnWatchInfo *watch;
- struct _XConnWatchInfo *previous = NULL;
- struct _XConnectionInfo *conni;
- int counter = 0;
-
- LockDisplay(dpy);
- for (watch=dpy->conn_watchers; watch; watch=watch->next) {
- if (watch->fn == callback && watch->client_data == client_data) {
- if (previous)
- previous->next = watch->next;
- else
- dpy->conn_watchers = watch->next;
- Xfree (watch);
- dpy->watcher_count--;
- /* remove our watch_data for each connection */
- for (conni=dpy->im_fd_info; conni; conni=conni->next) {
- /* don't bother realloc'ing; these arrays are small anyway */
- /* overlapping */
- memmove(conni->watch_data+counter,
- conni->watch_data+counter+1,
- dpy->watcher_count - counter);
- }
- break;
- }
- previous = watch;
- counter++;
- }
- UnlockDisplay(dpy);
-}
-
-/* end of internal connections support */
-
-/* Cookie jar implementation
- dpy->cookiejar is a linked list. _XEnq receives the events but leaves
- them in the normal EQ. _XStoreEvent returns the cookie event (minus
- data pointer) and adds it to the cookiejar. _XDeq just removes
- the entry like any other event but resets the data pointer for
- cookie events (to avoid double-free, the memory is re-used by Xlib).
-
- _XFetchEventCookie (called from XGetEventData) removes a cookie from the
- jar. _XFreeEventCookies removes all unclaimed cookies from the jar
- (called by XNextEvent).
-
- _XFreeDisplayStructure calls _XFreeEventCookies for each cookie in the
- normal EQ.
- */
-
-#include "utlist.h"
-struct stored_event {
- XGenericEventCookie ev;
- struct stored_event *prev;
- struct stored_event *next;
-};
-
-Bool
-_XIsEventCookie(Display *dpy, XEvent *ev)
-{
- return (ev->xcookie.type == GenericEvent &&
- dpy->generic_event_vec[ev->xcookie.extension & 0x7F] != NULL);
-}
-
-/**
- * Free all events in the event list.
- */
-void
-_XFreeEventCookies(Display *dpy)
-{
- struct stored_event **head, *e, *tmp;
-
- if (!dpy->cookiejar)
- return;
-
- head = (struct stored_event**)&dpy->cookiejar;
-
- DL_FOREACH_SAFE(*head, e, tmp) {
- XFree(e->ev.data);
- XFree(e);
- if (dpy->cookiejar == e)
- dpy->cookiejar = NULL;
- }
-}
-
-/**
- * Add an event to the display's event list. This event must be freed on the
- * next call to XNextEvent().
- */
-void
-_XStoreEventCookie(Display *dpy, XEvent *event)
-{
- XGenericEventCookie* cookie = &event->xcookie;
- struct stored_event **head, *add;
-
- if (!_XIsEventCookie(dpy, event))
- return;
-
- head = (struct stored_event**)(&dpy->cookiejar);
-
- add = Xmalloc(sizeof(struct stored_event));
- if (!add) {
- ESET(ENOMEM);
- _XIOError(dpy);
- }
- add->ev = *cookie;
- DL_APPEND(*head, add);
- cookie->data = NULL; /* don't return data yet, must be claimed */
-}
-
-/**
- * Return the event with the given cookie and remove it from the list.
- */
-Bool
-_XFetchEventCookie(Display *dpy, XGenericEventCookie* ev)
-{
- Bool ret = False;
- struct stored_event **head, *event;
- head = (struct stored_event**)&dpy->cookiejar;
-
- if (!_XIsEventCookie(dpy, (XEvent*)ev))
- return ret;
-
- DL_FOREACH(*head, event) {
- if (event->ev.cookie == ev->cookie &&
- event->ev.extension == ev->extension &&
- event->ev.evtype == ev->evtype) {
- *ev = event->ev;
- DL_DELETE(*head, event);
- Xfree(event);
- ret = True;
- break;
- }
- }
-
- return ret;
-}
-
-Bool
-_XCopyEventCookie(Display *dpy, XGenericEventCookie *in, XGenericEventCookie *out)
-{
- Bool ret = False;
- int extension;
-
- if (!_XIsEventCookie(dpy, (XEvent*)in) || !out)
- return ret;
-
- extension = in->extension & 0x7F;
-
- if (!dpy->generic_event_copy_vec[extension])
- return ret;
-
- ret = ((*dpy->generic_event_copy_vec[extension])(dpy, in, out));
- out->cookie = ret ? ++dpy->next_cookie : 0;
- return ret;
-}
-
-
-/*
- * _XEnq - Place event packets on the display's queue.
- * note that no squishing of move events in V11, since there
- * is pointer motion hints....
- */
-void _XEnq(
- register Display *dpy,
- register xEvent *event)
-{
- register _XQEvent *qelt;
- int type, extension;
-
- if ((qelt = dpy->qfree)) {
- /* If dpy->qfree is non-NULL do this, else malloc a new one. */
- dpy->qfree = qelt->next;
- }
- else if ((qelt =
- (_XQEvent *) Xmalloc((unsigned)sizeof(_XQEvent))) == NULL) {
- /* Malloc call failed! */
- ESET(ENOMEM);
- _XIOError(dpy);
- }
- qelt->next = NULL;
-
- type = event->u.u.type & 0177;
- extension = ((xGenericEvent*)event)->extension;
-
- qelt->event.type = type;
- /* If an extension has registerd a generic_event_vec handler, then
- * it can handle event cookies. Otherwise, proceed with the normal
- * event handlers.
- *
- * If the generic_event_vec is called, qelt->event is a event cookie
- * with the data pointer and the "free" pointer set. Data pointer is
- * some memory allocated by the extension.
- */
- if (type == GenericEvent && dpy->generic_event_vec[extension & 0x7F]) {
- XGenericEventCookie *cookie = &qelt->event.xcookie;
- (*dpy->generic_event_vec[extension & 0x7F])(dpy, cookie, event);
- cookie->cookie = ++dpy->next_cookie;
-
- qelt->qserial_num = dpy->next_event_serial_num++;
- if (dpy->tail) dpy->tail->next = qelt;
- else dpy->head = qelt;
-
- dpy->tail = qelt;
- dpy->qlen++;
- } else if ((*dpy->event_vec[type])(dpy, &qelt->event, event)) {
- qelt->qserial_num = dpy->next_event_serial_num++;
- if (dpy->tail) dpy->tail->next = qelt;
- else dpy->head = qelt;
-
- dpy->tail = qelt;
- dpy->qlen++;
- } else {
- /* ignored, or stashed away for many-to-one compression */
- qelt->next = dpy->qfree;
- dpy->qfree = qelt;
- }
-}
-
-/*
- * _XDeq - Remove event packet from the display's queue.
- */
-void _XDeq(
- register Display *dpy,
- register _XQEvent *prev, /* element before qelt */
- register _XQEvent *qelt) /* element to be unlinked */
-{
- if (prev) {
- if ((prev->next = qelt->next) == NULL)
- dpy->tail = prev;
- } else {
- /* no prev, so removing first elt */
- if ((dpy->head = qelt->next) == NULL)
- dpy->tail = NULL;
- }
- qelt->qserial_num = 0;
- qelt->next = dpy->qfree;
- dpy->qfree = qelt;
- dpy->qlen--;
-
- if (_XIsEventCookie(dpy, &qelt->event)) {
- XGenericEventCookie* cookie = &qelt->event.xcookie;
- /* dpy->qfree is re-used, reset memory to avoid double free on
- * _XFreeDisplayStructure */
- cookie->data = NULL;
- }
-}
-
-/*
- * EventToWire in separate file in that often not needed.
- */
-
-/*ARGSUSED*/
-Bool
-_XUnknownWireEvent(
- register Display *dpy, /* pointer to display structure */
- register XEvent *re, /* pointer to where event should be reformatted */
- register xEvent *event) /* wire protocol event */
-{
-#ifdef notdef
- (void) fprintf(stderr,
- "Xlib: unhandled wire event! event number = %d, display = %x\n.",
- event->u.u.type, dpy);
-#endif
- return(False);
-}
-
-Bool
-_XUnknownWireEventCookie(
- Display *dpy, /* pointer to display structure */
- XGenericEventCookie *re, /* pointer to where event should be reformatted */
- xEvent *event) /* wire protocol event */
-{
-#ifdef notdef
- fprintf(stderr,
- "Xlib: unhandled wire cookie event! extension number = %d, display = %x\n.",
- ((xGenericEvent*)event)->extension, dpy);
-#endif
- return(False);
-}
-
-Bool
-_XUnknownCopyEventCookie(
- Display *dpy, /* pointer to display structure */
- XGenericEventCookie *in, /* source */
- XGenericEventCookie *out) /* destination */
-{
-#ifdef notdef
- fprintf(stderr,
- "Xlib: unhandled cookie event copy! extension number = %d, display = %x\n.",
- in->extension, dpy);
-#endif
- return(False);
-}
-
-/*ARGSUSED*/
-Status
-_XUnknownNativeEvent(
- register Display *dpy, /* pointer to display structure */
- register XEvent *re, /* pointer to where event should be reformatted */
- register xEvent *event) /* wire protocol event */
-{
-#ifdef notdef
- (void) fprintf(stderr,
- "Xlib: unhandled native event! event number = %d, display = %x\n.",
- re->type, dpy);
-#endif
- return(0);
-}
-/*
- * reformat a wire event into an XEvent structure of the right type.
- */
-Bool
-_XWireToEvent(
- register Display *dpy, /* pointer to display structure */
- register XEvent *re, /* pointer to where event should be reformatted */
- register xEvent *event) /* wire protocol event */
-{
-
- re->type = event->u.u.type & 0x7f;
- ((XAnyEvent *)re)->serial = _XSetLastRequestRead(dpy,
- (xGenericReply *)event);
- ((XAnyEvent *)re)->send_event = ((event->u.u.type & 0x80) != 0);
- ((XAnyEvent *)re)->display = dpy;
-
- /* Ignore the leading bit of the event type since it is set when a
- client sends an event rather than the server. */
-
- switch (event-> u.u.type & 0177) {
- case KeyPress:
- case KeyRelease:
- {
- register XKeyEvent *ev = (XKeyEvent*) re;
- ev->root = event->u.keyButtonPointer.root;
- ev->window = event->u.keyButtonPointer.event;
- ev->subwindow = event->u.keyButtonPointer.child;
- ev->time = event->u.keyButtonPointer.time;
- ev->x = cvtINT16toInt(event->u.keyButtonPointer.eventX);
- ev->y = cvtINT16toInt(event->u.keyButtonPointer.eventY);
- ev->x_root = cvtINT16toInt(event->u.keyButtonPointer.rootX);
- ev->y_root = cvtINT16toInt(event->u.keyButtonPointer.rootY);
- ev->state = event->u.keyButtonPointer.state;
- ev->same_screen = event->u.keyButtonPointer.sameScreen;
- ev->keycode = event->u.u.detail;
- }
- break;
- case ButtonPress:
- case ButtonRelease:
- {
- register XButtonEvent *ev = (XButtonEvent *) re;
- ev->root = event->u.keyButtonPointer.root;
- ev->window = event->u.keyButtonPointer.event;
- ev->subwindow = event->u.keyButtonPointer.child;
- ev->time = event->u.keyButtonPointer.time;
- ev->x = cvtINT16toInt(event->u.keyButtonPointer.eventX);
- ev->y = cvtINT16toInt(event->u.keyButtonPointer.eventY);
- ev->x_root = cvtINT16toInt(event->u.keyButtonPointer.rootX);
- ev->y_root = cvtINT16toInt(event->u.keyButtonPointer.rootY);
- ev->state = event->u.keyButtonPointer.state;
- ev->same_screen = event->u.keyButtonPointer.sameScreen;
- ev->button = event->u.u.detail;
- }
- break;
- case MotionNotify:
- {
- register XMotionEvent *ev = (XMotionEvent *)re;
- ev->root = event->u.keyButtonPointer.root;
- ev->window = event->u.keyButtonPointer.event;
- ev->subwindow = event->u.keyButtonPointer.child;
- ev->time = event->u.keyButtonPointer.time;
- ev->x = cvtINT16toInt(event->u.keyButtonPointer.eventX);
- ev->y = cvtINT16toInt(event->u.keyButtonPointer.eventY);
- ev->x_root = cvtINT16toInt(event->u.keyButtonPointer.rootX);
- ev->y_root = cvtINT16toInt(event->u.keyButtonPointer.rootY);
- ev->state = event->u.keyButtonPointer.state;
- ev->same_screen = event->u.keyButtonPointer.sameScreen;
- ev->is_hint = event->u.u.detail;
- }
- break;
- case EnterNotify:
- case LeaveNotify:
- {
- register XCrossingEvent *ev = (XCrossingEvent *) re;
- ev->root = event->u.enterLeave.root;
- ev->window = event->u.enterLeave.event;
- ev->subwindow = event->u.enterLeave.child;
- ev->time = event->u.enterLeave.time;
- ev->x = cvtINT16toInt(event->u.enterLeave.eventX);
- ev->y = cvtINT16toInt(event->u.enterLeave.eventY);
- ev->x_root = cvtINT16toInt(event->u.enterLeave.rootX);
- ev->y_root = cvtINT16toInt(event->u.enterLeave.rootY);
- ev->state = event->u.enterLeave.state;
- ev->mode = event->u.enterLeave.mode;
- ev->same_screen = (event->u.enterLeave.flags &
- ELFlagSameScreen) && True;
- ev->focus = (event->u.enterLeave.flags &
- ELFlagFocus) && True;
- ev->detail = event->u.u.detail;
- }
- break;
- case FocusIn:
- case FocusOut:
- {
- register XFocusChangeEvent *ev = (XFocusChangeEvent *) re;
- ev->window = event->u.focus.window;
- ev->mode = event->u.focus.mode;
- ev->detail = event->u.u.detail;
- }
- break;
- case KeymapNotify:
- {
- register XKeymapEvent *ev = (XKeymapEvent *) re;
- ev->window = None;
- memcpy(&ev->key_vector[1],
- (char *)((xKeymapEvent *) event)->map,
- sizeof (((xKeymapEvent *) event)->map));
- }
- break;
- case Expose:
- {
- register XExposeEvent *ev = (XExposeEvent *) re;
- ev->window = event->u.expose.window;
- ev->x = event->u.expose.x;
- ev->y = event->u.expose.y;
- ev->width = event->u.expose.width;
- ev->height = event->u.expose.height;
- ev->count = event->u.expose.count;
- }
- break;
- case GraphicsExpose:
- {
- register XGraphicsExposeEvent *ev =
- (XGraphicsExposeEvent *) re;
- ev->drawable = event->u.graphicsExposure.drawable;
- ev->x = event->u.graphicsExposure.x;
- ev->y = event->u.graphicsExposure.y;
- ev->width = event->u.graphicsExposure.width;
- ev->height = event->u.graphicsExposure.height;
- ev->count = event->u.graphicsExposure.count;
- ev->major_code = event->u.graphicsExposure.majorEvent;
- ev->minor_code = event->u.graphicsExposure.minorEvent;
- }
- break;
- case NoExpose:
- {
- register XNoExposeEvent *ev = (XNoExposeEvent *) re;
- ev->drawable = event->u.noExposure.drawable;
- ev->major_code = event->u.noExposure.majorEvent;
- ev->minor_code = event->u.noExposure.minorEvent;
- }
- break;
- case VisibilityNotify:
- {
- register XVisibilityEvent *ev = (XVisibilityEvent *) re;
- ev->window = event->u.visibility.window;
- ev->state = event->u.visibility.state;
- }
- break;
- case CreateNotify:
- {
- register XCreateWindowEvent *ev =
- (XCreateWindowEvent *) re;
- ev->window = event->u.createNotify.window;
- ev->parent = event->u.createNotify.parent;
- ev->x = cvtINT16toInt(event->u.createNotify.x);
- ev->y = cvtINT16toInt(event->u.createNotify.y);
- ev->width = event->u.createNotify.width;
- ev->height = event->u.createNotify.height;
- ev->border_width = event->u.createNotify.borderWidth;
- ev->override_redirect = event->u.createNotify.override;
- }
- break;
- case DestroyNotify:
- {
- register XDestroyWindowEvent *ev =
- (XDestroyWindowEvent *) re;
- ev->window = event->u.destroyNotify.window;
- ev->event = event->u.destroyNotify.event;
- }
- break;
- case UnmapNotify:
- {
- register XUnmapEvent *ev = (XUnmapEvent *) re;
- ev->window = event->u.unmapNotify.window;
- ev->event = event->u.unmapNotify.event;
- ev->from_configure = event->u.unmapNotify.fromConfigure;
- }
- break;
- case MapNotify:
- {
- register XMapEvent *ev = (XMapEvent *) re;
- ev->window = event->u.mapNotify.window;
- ev->event = event->u.mapNotify.event;
- ev->override_redirect = event->u.mapNotify.override;
- }
- break;
- case MapRequest:
- {
- register XMapRequestEvent *ev = (XMapRequestEvent *) re;
- ev->window = event->u.mapRequest.window;
- ev->parent = event->u.mapRequest.parent;
- }
- break;
- case ReparentNotify:
- {
- register XReparentEvent *ev = (XReparentEvent *) re;
- ev->event = event->u.reparent.event;
- ev->window = event->u.reparent.window;
- ev->parent = event->u.reparent.parent;
- ev->x = cvtINT16toInt(event->u.reparent.x);
- ev->y = cvtINT16toInt(event->u.reparent.y);
- ev->override_redirect = event->u.reparent.override;
- }
- break;
- case ConfigureNotify:
- {
- register XConfigureEvent *ev = (XConfigureEvent *) re;
- ev->event = event->u.configureNotify.event;
- ev->window = event->u.configureNotify.window;
- ev->above = event->u.configureNotify.aboveSibling;
- ev->x = cvtINT16toInt(event->u.configureNotify.x);
- ev->y = cvtINT16toInt(event->u.configureNotify.y);
- ev->width = event->u.configureNotify.width;
- ev->height = event->u.configureNotify.height;
- ev->border_width = event->u.configureNotify.borderWidth;
- ev->override_redirect = event->u.configureNotify.override;
- }
- break;
- case ConfigureRequest:
- {
- register XConfigureRequestEvent *ev =
- (XConfigureRequestEvent *) re;
- ev->window = event->u.configureRequest.window;
- ev->parent = event->u.configureRequest.parent;
- ev->above = event->u.configureRequest.sibling;
- ev->x = cvtINT16toInt(event->u.configureRequest.x);
- ev->y = cvtINT16toInt(event->u.configureRequest.y);
- ev->width = event->u.configureRequest.width;
- ev->height = event->u.configureRequest.height;
- ev->border_width = event->u.configureRequest.borderWidth;
- ev->value_mask = event->u.configureRequest.valueMask;
- ev->detail = event->u.u.detail;
- }
- break;
- case GravityNotify:
- {
- register XGravityEvent *ev = (XGravityEvent *) re;
- ev->window = event->u.gravity.window;
- ev->event = event->u.gravity.event;
- ev->x = cvtINT16toInt(event->u.gravity.x);
- ev->y = cvtINT16toInt(event->u.gravity.y);
- }
- break;
- case ResizeRequest:
- {
- register XResizeRequestEvent *ev =
- (XResizeRequestEvent *) re;
- ev->window = event->u.resizeRequest.window;
- ev->width = event->u.resizeRequest.width;
- ev->height = event->u.resizeRequest.height;
- }
- break;
- case CirculateNotify:
- {
- register XCirculateEvent *ev = (XCirculateEvent *) re;
- ev->window = event->u.circulate.window;
- ev->event = event->u.circulate.event;
- ev->place = event->u.circulate.place;
- }
- break;
- case CirculateRequest:
- {
- register XCirculateRequestEvent *ev =
- (XCirculateRequestEvent *) re;
- ev->window = event->u.circulate.window;
- ev->parent = event->u.circulate.event;
- ev->place = event->u.circulate.place;
- }
- break;
- case PropertyNotify:
- {
- register XPropertyEvent *ev = (XPropertyEvent *) re;
- ev->window = event->u.property.window;
- ev->atom = event->u.property.atom;
- ev->time = event->u.property.time;
- ev->state = event->u.property.state;
- }
- break;
- case SelectionClear:
- {
- register XSelectionClearEvent *ev =
- (XSelectionClearEvent *) re;
- ev->window = event->u.selectionClear.window;
- ev->selection = event->u.selectionClear.atom;
- ev->time = event->u.selectionClear.time;
- }
- break;
- case SelectionRequest:
- {
- register XSelectionRequestEvent *ev =
- (XSelectionRequestEvent *) re;
- ev->owner = event->u.selectionRequest.owner;
- ev->requestor = event->u.selectionRequest.requestor;
- ev->selection = event->u.selectionRequest.selection;
- ev->target = event->u.selectionRequest.target;
- ev->property = event->u.selectionRequest.property;
- ev->time = event->u.selectionRequest.time;
- }
- break;
- case SelectionNotify:
- {
- register XSelectionEvent *ev = (XSelectionEvent *) re;
- ev->requestor = event->u.selectionNotify.requestor;
- ev->selection = event->u.selectionNotify.selection;
- ev->target = event->u.selectionNotify.target;
- ev->property = event->u.selectionNotify.property;
- ev->time = event->u.selectionNotify.time;
- }
- break;
- case ColormapNotify:
- {
- register XColormapEvent *ev = (XColormapEvent *) re;
- ev->window = event->u.colormap.window;
- ev->colormap = event->u.colormap.colormap;
- ev->new = event->u.colormap.new;
- ev->state = event->u.colormap.state;
- }
- break;
- case ClientMessage:
- {
- register int i;
- register XClientMessageEvent *ev
- = (XClientMessageEvent *) re;
- ev->window = event->u.clientMessage.window;
- ev->format = event->u.u.detail;
- switch (ev->format) {
- case 8:
- ev->message_type = event->u.clientMessage.u.b.type;
- for (i = 0; i < 20; i++)
- ev->data.b[i] = event->u.clientMessage.u.b.bytes[i];
- break;
- case 16:
- ev->message_type = event->u.clientMessage.u.s.type;
- ev->data.s[0] = cvtINT16toShort(event->u.clientMessage.u.s.shorts0);
- ev->data.s[1] = cvtINT16toShort(event->u.clientMessage.u.s.shorts1);
- ev->data.s[2] = cvtINT16toShort(event->u.clientMessage.u.s.shorts2);
- ev->data.s[3] = cvtINT16toShort(event->u.clientMessage.u.s.shorts3);
- ev->data.s[4] = cvtINT16toShort(event->u.clientMessage.u.s.shorts4);
- ev->data.s[5] = cvtINT16toShort(event->u.clientMessage.u.s.shorts5);
- ev->data.s[6] = cvtINT16toShort(event->u.clientMessage.u.s.shorts6);
- ev->data.s[7] = cvtINT16toShort(event->u.clientMessage.u.s.shorts7);
- ev->data.s[8] = cvtINT16toShort(event->u.clientMessage.u.s.shorts8);
- ev->data.s[9] = cvtINT16toShort(event->u.clientMessage.u.s.shorts9);
- break;
- case 32:
- ev->message_type = event->u.clientMessage.u.l.type;
- ev->data.l[0] = cvtINT32toLong(event->u.clientMessage.u.l.longs0);
- ev->data.l[1] = cvtINT32toLong(event->u.clientMessage.u.l.longs1);
- ev->data.l[2] = cvtINT32toLong(event->u.clientMessage.u.l.longs2);
- ev->data.l[3] = cvtINT32toLong(event->u.clientMessage.u.l.longs3);
- ev->data.l[4] = cvtINT32toLong(event->u.clientMessage.u.l.longs4);
- break;
- default: /* XXX should never occur */
- break;
- }
- }
- break;
- case MappingNotify:
- {
- register XMappingEvent *ev = (XMappingEvent *)re;
- ev->window = 0;
- ev->first_keycode = event->u.mappingNotify.firstKeyCode;
- ev->request = event->u.mappingNotify.request;
- ev->count = event->u.mappingNotify.count;
- }
- break;
- default:
- return(_XUnknownWireEvent(dpy, re, event));
- }
- return(True);
-}
-
-
-/*
- * _XDefaultIOError - Default fatal system error reporting routine. Called
- * when an X internal system error is encountered.
- */
-int _XDefaultIOError(
- Display *dpy)
-{
- if (ECHECK(EPIPE)) {
- (void) fprintf (stderr,
- "X connection to %s broken (explicit kill or server shutdown).\r\n",
- DisplayString (dpy));
- } else {
- (void) fprintf (stderr,
- "XIO: fatal IO error %d (%s) on X server \"%s\"\r\n",
-#ifdef WIN32
- WSAGetLastError(), strerror(WSAGetLastError()),
-#else
- errno, strerror (errno),
-#endif
- DisplayString (dpy));
- (void) fprintf (stderr,
- " after %lu requests (%lu known processed) with %d events remaining.\r\n",
- NextRequest(dpy) - 1, LastKnownRequestProcessed(dpy),
- QLength(dpy));
-
- }
- exit(1);
- return(0); /* dummy - function should never return */
-}
-
-
-static int _XPrintDefaultError(
- Display *dpy,
- XErrorEvent *event,
- FILE *fp)
-{
- char buffer[BUFSIZ];
- char mesg[BUFSIZ];
- char number[32];
- const char *mtype = "XlibMessage";
- register _XExtension *ext = (_XExtension *)NULL;
- _XExtension *bext = (_XExtension *)NULL;
- XGetErrorText(dpy, event->error_code, buffer, BUFSIZ);
- XGetErrorDatabaseText(dpy, mtype, "XError", "X Error", mesg, BUFSIZ);
- (void) fprintf(fp, "%s: %s\n ", mesg, buffer);
- XGetErrorDatabaseText(dpy, mtype, "MajorCode", "Request Major code %d",
- mesg, BUFSIZ);
- (void) fprintf(fp, mesg, event->request_code);
- if (event->request_code < 128) {
- sprintf(number, "%d", event->request_code);
- XGetErrorDatabaseText(dpy, "XRequest", number, "", buffer, BUFSIZ);
- } else {
- for (ext = dpy->ext_procs;
- ext && (ext->codes.major_opcode != event->request_code);
- ext = ext->next)
- ;
- if (ext)
- strcpy(buffer, ext->name);
- else
- buffer[0] = '\0';
- }
- (void) fprintf(fp, " (%s)\n", buffer);
- if (event->request_code >= 128) {
- XGetErrorDatabaseText(dpy, mtype, "MinorCode", "Request Minor code %d",
- mesg, BUFSIZ);
- fputs(" ", fp);
- (void) fprintf(fp, mesg, event->minor_code);
- if (ext) {
- sprintf(mesg, "%s.%d", ext->name, event->minor_code);
- XGetErrorDatabaseText(dpy, "XRequest", mesg, "", buffer, BUFSIZ);
- (void) fprintf(fp, " (%s)", buffer);
- }
- fputs("\n", fp);
- }
- if (event->error_code >= 128) {
- /* kludge, try to find the extension that caused it */
- buffer[0] = '\0';
- for (ext = dpy->ext_procs; ext; ext = ext->next) {
- if (ext->error_string)
- (*ext->error_string)(dpy, event->error_code, &ext->codes,
- buffer, BUFSIZ);
- if (buffer[0]) {
- bext = ext;
- break;
- }
- if (ext->codes.first_error &&
- ext->codes.first_error < (int)event->error_code &&
- (!bext || ext->codes.first_error > bext->codes.first_error))
- bext = ext;
- }
- if (bext)
- sprintf(buffer, "%s.%d", bext->name,
- event->error_code - bext->codes.first_error);
- else
- strcpy(buffer, "Value");
- XGetErrorDatabaseText(dpy, mtype, buffer, "", mesg, BUFSIZ);
- if (mesg[0]) {
- fputs(" ", fp);
- (void) fprintf(fp, mesg, event->resourceid);
- fputs("\n", fp);
- }
- /* let extensions try to print the values */
- for (ext = dpy->ext_procs; ext; ext = ext->next) {
- if (ext->error_values)
- (*ext->error_values)(dpy, event, fp);
- }
- } else if ((event->error_code == BadWindow) ||
- (event->error_code == BadPixmap) ||
- (event->error_code == BadCursor) ||
- (event->error_code == BadFont) ||
- (event->error_code == BadDrawable) ||
- (event->error_code == BadColor) ||
- (event->error_code == BadGC) ||
- (event->error_code == BadIDChoice) ||
- (event->error_code == BadValue) ||
- (event->error_code == BadAtom)) {
- if (event->error_code == BadValue)
- XGetErrorDatabaseText(dpy, mtype, "Value", "Value 0x%x",
- mesg, BUFSIZ);
- else if (event->error_code == BadAtom)
- XGetErrorDatabaseText(dpy, mtype, "AtomID", "AtomID 0x%x",
- mesg, BUFSIZ);
- else
- XGetErrorDatabaseText(dpy, mtype, "ResourceID", "ResourceID 0x%x",
- mesg, BUFSIZ);
- fputs(" ", fp);
- (void) fprintf(fp, mesg, event->resourceid);
- fputs("\n", fp);
- }
- XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d",
- mesg, BUFSIZ);
- fputs(" ", fp);
- (void) fprintf(fp, mesg, event->serial);
- XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%d",
- mesg, BUFSIZ);
- fputs("\n ", fp);
- (void) fprintf(fp, mesg, dpy->request);
- fputs("\n", fp);
- if (event->error_code == BadImplementation) return 0;
- return 1;
-}
-
-int _XDefaultError(
- Display *dpy,
- XErrorEvent *event)
-{
- if (_XPrintDefaultError (dpy, event, stderr) == 0) return 0;
- exit(1);
- /*NOTREACHED*/
-}
-
-/*ARGSUSED*/
-Bool _XDefaultWireError(Display *display, XErrorEvent *he, xError *we)
-{
- return True;
-}
-
-/*
- * _XError - upcall internal or user protocol error handler
- */
-int _XError (
- Display *dpy,
- register xError *rep)
-{
- /*
- * X_Error packet encountered! We need to unpack the error before
- * giving it to the user.
- */
- XEvent event; /* make it a large event */
- register _XAsyncHandler *async, *next;
-
- event.xerror.serial = _XSetLastRequestRead(dpy, (xGenericReply *)rep);
-
- for (async = dpy->async_handlers; async; async = next) {
- next = async->next;
- if ((*async->handler)(dpy, (xReply *)rep,
- (char *)rep, SIZEOF(xError), async->data))
- return 0;
- }
-
- event.xerror.display = dpy;
- event.xerror.type = X_Error;
- event.xerror.resourceid = rep->resourceID;
- event.xerror.error_code = rep->errorCode;
- event.xerror.request_code = rep->majorCode;
- event.xerror.minor_code = rep->minorCode;
- if (dpy->error_vec &&
- !(*dpy->error_vec[rep->errorCode])(dpy, &event.xerror, rep))
- return 0;
- if (_XErrorFunction != NULL) {
- return (*_XErrorFunction)(dpy, (XErrorEvent *)&event); /* upcall */
- } else {
- return _XDefaultError(dpy, (XErrorEvent *)&event);
- }
-}
-
-/*
- * _XIOError - call user connection error handler and exit
- */
-int
-_XIOError (
- Display *dpy)
-{
- dpy->flags |= XlibDisplayIOError;
-#ifdef WIN32
- errno = WSAGetLastError();
-#endif
-
- /* This assumes that the thread calling exit will call any atexit handlers.
- * If this does not hold, then an alternate solution would involve
- * registering an atexit handler to take over the lock, which would only
- * assume that the same thread calls all the atexit handlers. */
-#ifdef XTHREADS
- if (dpy->lock)
- (*dpy->lock->user_lock_display)(dpy);
-#endif
- UnlockDisplay(dpy);
-
- if (_XIOErrorFunction != NULL)
- (*_XIOErrorFunction)(dpy);
- else
- _XDefaultIOError(dpy);
- exit (1);
- return 0;
-}
-
-
-/*
- * This routine can be used to (cheaply) get some memory within a single
- * Xlib routine for scratch space. A single buffer is reused each time
- * if possible. To be MT safe, you can only call this between a call to
- * GetReq* and a call to Data* or _XSend*, or in a context when the thread
- * is guaranteed to not unlock the display.
- */
-char *_XAllocScratch(
- register Display *dpy,
- unsigned long nbytes)
-{
- if (nbytes > dpy->scratch_length) {
- if (dpy->scratch_buffer) Xfree (dpy->scratch_buffer);
- if ((dpy->scratch_buffer = Xmalloc((unsigned) nbytes)))
- dpy->scratch_length = nbytes;
- else dpy->scratch_length = 0;
- }
- return (dpy->scratch_buffer);
-}
-
-/*
- * Scratch space allocator you can call any time, multiple times, and be
- * MT safe, but you must hand the buffer back with _XFreeTemp.
- */
-char *_XAllocTemp(
- register Display *dpy,
- unsigned long nbytes)
-{
- char *buf;
-
- buf = _XAllocScratch(dpy, nbytes);
- dpy->scratch_buffer = NULL;
- dpy->scratch_length = 0;
- return buf;
-}
-
-void _XFreeTemp(
- register Display *dpy,
- char *buf,
- unsigned long nbytes)
-{
- if (dpy->scratch_buffer)
- Xfree(dpy->scratch_buffer);
- dpy->scratch_buffer = buf;
- dpy->scratch_length = nbytes;
-}
-
-/*
- * Given a visual id, find the visual structure for this id on this display.
- */
-Visual *_XVIDtoVisual(
- Display *dpy,
- VisualID id)
-{
- register int i, j, k;
- register Screen *sp;
- register Depth *dp;
- register Visual *vp;
- for (i = 0; i < dpy->nscreens; i++) {
- sp = &dpy->screens[i];
- for (j = 0; j < sp->ndepths; j++) {
- dp = &sp->depths[j];
- /* if nvisuals == 0 then visuals will be NULL */
- for (k = 0; k < dp->nvisuals; k++) {
- vp = &dp->visuals[k];
- if (vp->visualid == id) return (vp);
- }
- }
- }
- return (NULL);
-}
-
-int
-XFree (void *data)
-{
- Xfree (data);
- return 1;
-}
-
-#ifdef _XNEEDBCOPYFUNC
-void _Xbcopy(b1, b2, length)
- register char *b1, *b2;
- register length;
-{
- if (b1 < b2) {
- b2 += length;
- b1 += length;
- while (length--)
- *--b2 = *--b1;
- } else {
- while (length--)
- *b2++ = *b1++;
- }
-}
-#endif
-
-#ifdef DataRoutineIsProcedure
-void Data(
- Display *dpy,
- char *data,
- long len)
-{
- if (dpy->bufptr + (len) <= dpy->bufmax) {
- memcpy(dpy->bufptr, data, (int)len);
- dpy->bufptr += ((len) + 3) & ~3;
- } else {
- _XSend(dpy, data, len);
- }
-}
-#endif /* DataRoutineIsProcedure */
-
-
-#ifdef LONG64
-int
-_XData32(
- Display *dpy,
- register long *data,
- unsigned len)
-{
- register int *buf;
- register long i;
-
- while (len) {
- buf = (int *)dpy->bufptr;
- i = dpy->bufmax - (char *)buf;
- if (!i) {
- _XFlush(dpy);
- continue;
- }
- if (len < i)
- i = len;
- dpy->bufptr = (char *)buf + i;
- len -= i;
- i >>= 2;
- while (--i >= 0)
- *buf++ = *data++;
- }
- return 0;
-}
-#endif /* LONG64 */
-
-#ifdef WORD64
-
-/*
- * XXX This is a *really* stupid way of doing this. It should just use
- * dpy->bufptr directly, taking into account where in the word it is.
- */
-
-/*
- * Data16 - Place 16 bit data in the buffer.
- *
- * "dpy" is a pointer to a Display.
- * "data" is a pointer to the data.
- * "len" is the length in bytes of the data.
- */
-
-static doData16(
- register Display *dpy,
- short *data,
- unsigned len,
- char *packbuffer)
-{
- long *lp,*lpack;
- long i, nwords,bits;
- long mask16 = 0x000000000000ffff;
-
- lp = (long *)data;
- lpack = (long *)packbuffer;
-
-/* nwords is the number of 16 bit values to be packed,
- * the low order 16 bits of each word will be packed
- * into 64 bit words
- */
- nwords = len >> 1;
- bits = 48;
-
- for(i=0;i<nwords;i++){
- if (bits == 48) *lpack = 0;
- *lpack ^= (*lp & mask16) << bits;
- bits -= 16 ;
- lp++;
- if(bits < 0){
- lpack++;
- bits = 48;
- }
- }
- Data(dpy, packbuffer, len);
-}
-
-_XData16 (
- Display *dpy,
- short *data,
- unsigned len)
-{
- char packbuffer[PACKBUFFERSIZE];
- unsigned nunits = PACKBUFFERSIZE >> 1;
-
- for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) {
- doData16 (dpy, data, PACKBUFFERSIZE, packbuffer);
- }
- if (len) doData16 (dpy, data, len, packbuffer);
-}
-
-/*
- * Data32 - Place 32 bit data in the buffer.
- *
- * "dpy" is a pointer to a Display.
- * "data" is a pointer to the data.
- * "len" is the length in bytes of the data.
- */
-
-static doData32(
- register Display *dpy
- long *data,
- unsigned len,
- char *packbuffer)
-{
- long *lp,*lpack;
- long i,bits,nwords;
- long mask32 = 0x00000000ffffffff;
-
- lpack = (long *) packbuffer;
- lp = data;
-
-/* nwords is the number of 32 bit values to be packed
- * the low order 32 bits of each word will be packed
- * into 64 bit words
- */
- nwords = len >> 2;
- bits = 32;
-
- for(i=0;i<nwords;i++){
- if (bits == 32) *lpack = 0;
- *lpack ^= (*lp & mask32) << bits;
- bits = bits ^32;
- lp++;
- if(bits)
- lpack++;
- }
- Data(dpy, packbuffer, len);
-}
-
-void _XData32(
- Display *dpy,
- long *data,
- unsigned len)
-{
- char packbuffer[PACKBUFFERSIZE];
- unsigned nunits = PACKBUFFERSIZE >> 2;
-
- for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) {
- doData32 (dpy, data, PACKBUFFERSIZE, packbuffer);
- }
- if (len) doData32 (dpy, data, len, packbuffer);
-}
-
-#endif /* WORD64 */
-
-
-/* Make sure this produces the same string as DefineLocal/DefineSelf in xdm.
- * Otherwise, Xau will not be able to find your cookies in the Xauthority file.
- *
- * Note: POSIX says that the ``nodename'' member of utsname does _not_ have
- * to have sufficient information for interfacing to the network,
- * and so, you may be better off using gethostname (if it exists).
- */
-
-#if (defined(_POSIX_SOURCE) && !defined(AIXV3) && !defined(__QNX__)) || defined(hpux) || defined(SVR4)
-#define NEED_UTSNAME
-#include <sys/utsname.h>
-#else
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#endif
-
-/*
- * _XGetHostname - similar to gethostname but allows special processing.
- */
-int _XGetHostname (
- char *buf,
- int maxlen)
-{
- int len;
-
-#ifdef NEED_UTSNAME
- struct utsname name;
-
- if (maxlen <= 0 || buf == NULL)
- return 0;
-
- uname (&name);
- len = strlen (name.nodename);
- if (len >= maxlen) len = maxlen - 1;
- strncpy (buf, name.nodename, len);
- buf[len] = '\0';
-#else
- if (maxlen <= 0 || buf == NULL)
- return 0;
-
- buf[0] = '\0';
- (void) gethostname (buf, maxlen);
- buf [maxlen - 1] = '\0';
- len = strlen(buf);
-#endif /* NEED_UTSNAME */
- return len;
-}
-
-
-/*
- * _XScreenOfWindow - get the Screen of a given window
- */
-
-Screen *_XScreenOfWindow(Display *dpy, Window w)
-{
- register int i;
- Window root;
- int x, y; /* dummy variables */
- unsigned int width, height, bw, depth; /* dummy variables */
-
- if (XGetGeometry (dpy, w, &root, &x, &y, &width, &height,
- &bw, &depth) == False) {
- return NULL;
- }
- for (i = 0; i < ScreenCount (dpy); i++) { /* find root from list */
- if (root == RootWindow (dpy, i)) {
- return ScreenOfDisplay (dpy, i);
- }
- }
- return NULL;
-}
-
-
-#if defined(WIN32)
-
-/*
- * These functions are intended to be used internally to Xlib only.
- * These functions will always prefix the path with a DOS drive in the
- * form "<drive-letter>:". As such, these functions are only suitable
- * for use by Xlib function that supply a root-based path to some
- * particular file, e.g. <ProjectRoot>/lib/X11/locale/locale.dir will
- * be converted to "C:/usr/X11R6.3/lib/X11/locale/locale.dir".
- */
-
-static int access_file (path, pathbuf, len_pathbuf, pathret)
- char* path;
- char* pathbuf;
- int len_pathbuf;
- char** pathret;
-{
- if (access (path, F_OK) == 0) {
- if (strlen (path) < len_pathbuf)
- *pathret = pathbuf;
- else
- *pathret = Xmalloc (strlen (path) + 1);
- if (*pathret) {
- strcpy (*pathret, path);
- return 1;
- }
- }
- return 0;
-}
-
-static int AccessFile (path, pathbuf, len_pathbuf, pathret)
- char* path;
- char* pathbuf;
- int len_pathbuf;
- char** pathret;
-{
- unsigned long drives;
- int i, len;
- char* drive;
- char buf[MAX_PATH];
- char* bufp;
-
- /* just try the "raw" name first and see if it works */
- if (access_file (path, pathbuf, len_pathbuf, pathret))
- return 1;
-
- /* try the places set in the environment */
- drive = getenv ("_XBASEDRIVE");
-#ifdef __UNIXOS2__
- if (!drive)
- drive = getenv ("X11ROOT");
-#endif
- if (!drive)
- drive = "C:";
- len = strlen (drive) + strlen (path);
- if (len < MAX_PATH) bufp = buf;
- else bufp = Xmalloc (len + 1);
- strcpy (bufp, drive);
- strcat (bufp, path);
- if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
- if (bufp != buf) Xfree (bufp);
- return 1;
- }
-
-#ifndef __UNIXOS2__
- /* one last place to look */
- drive = getenv ("HOMEDRIVE");
- if (drive) {
- len = strlen (drive) + strlen (path);
- if (len < MAX_PATH) bufp = buf;
- else bufp = Xmalloc (len + 1);
- strcpy (bufp, drive);
- strcat (bufp, path);
- if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
- if (bufp != buf) Xfree (bufp);
- return 1;
- }
- }
-
- /* tried everywhere else, go fishing */
-#define C_DRIVE ('C' - 'A')
-#define Z_DRIVE ('Z' - 'A')
- /* does OS/2 (with or with gcc-emx) have getdrives? */
- drives = _getdrives ();
- for (i = C_DRIVE; i <= Z_DRIVE; i++) { /* don't check on A: or B: */
- if ((1 << i) & drives) {
- len = 2 + strlen (path);
- if (len < MAX_PATH) bufp = buf;
- else bufp = Xmalloc (len + 1);
- *bufp = 'A' + i;
- *(bufp + 1) = ':';
- *(bufp + 2) = '\0';
- strcat (bufp, path);
- if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
- if (bufp != buf) Xfree (bufp);
- return 1;
- }
- }
- }
-#endif
- return 0;
-}
-
-int _XOpenFile(path, flags)
- _Xconst char* path;
- int flags;
-{
- char buf[MAX_PATH];
- char* bufp = NULL;
- int ret = -1;
- UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
-
- if (AccessFile (path, buf, MAX_PATH, &bufp))
- ret = open (bufp, flags);
-
- (void) SetErrorMode (olderror);
-
- if (bufp != buf) Xfree (bufp);
-
- return ret;
-}
-
-int _XOpenFileMode(path, flags, mode)
- _Xconst char* path;
- int flags;
- mode_t mode;
-{
- char buf[MAX_PATH];
- char* bufp = NULL;
- int ret = -1;
- UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
-
- if (AccessFile (path, buf, MAX_PATH, &bufp))
- ret = open (bufp, flags, mode);
-
- (void) SetErrorMode (olderror);
-
- if (bufp != buf) Xfree (bufp);
-
- return ret;
-}
-
-void* _XFopenFile(path, mode)
- _Xconst char* path;
- _Xconst char* mode;
-{
- char buf[MAX_PATH];
- char* bufp = NULL;
- void* ret = NULL;
- UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
-
- if (AccessFile (path, buf, MAX_PATH, &bufp))
- ret = fopen (bufp, mode);
-
- (void) SetErrorMode (olderror);
-
- if (bufp != buf) Xfree (bufp);
-
- return ret;
-}
-
-int _XAccessFile(path)
- _Xconst char* path;
-{
- char buf[MAX_PATH];
- char* bufp;
- int ret = -1;
- UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
-
- ret = AccessFile (path, buf, MAX_PATH, &bufp);
-
- (void) SetErrorMode (olderror);
-
- if (bufp != buf) Xfree (bufp);
-
- return ret;
-}
-
-#endif
-
-#ifdef WIN32
-#undef _Xdebug
-int _Xdebug = 0;
-int *_Xdebug_p = &_Xdebug;
-void (**_XCreateMutex_fn_p)(LockInfoPtr) = &_XCreateMutex_fn;
-void (**_XFreeMutex_fn_p)(LockInfoPtr) = &_XFreeMutex_fn;
-void (**_XLockMutex_fn_p)(LockInfoPtr
-#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
- , char * /* file */
- , int /* line */
-#endif
- ) = &_XLockMutex_fn;
-void (**_XUnlockMutex_fn_p)(LockInfoPtr
-#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
- , char * /* file */
- , int /* line */
-#endif
- ) = &_XUnlockMutex_fn;
-LockInfoPtr *_Xglobal_lock_p = &_Xglobal_lock;
-#endif
+/* + +Copyright 1985, 1986, 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +/* + * XlibInt.c - Internal support routines for the C subroutine + * interface library (Xlib) to the X Window System Protocol V11.0. + */ + +#ifdef WIN32 +#define _XLIBINT_ +#endif +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include "Xlibint.h" +#include "Xprivate.h" +#include <X11/Xpoll.h> +#include <assert.h> +#include <stdio.h> +#ifdef WIN32 +#include <direct.h> +#endif + +#ifdef XTHREADS +#include "locking.h" + +/* these pointers get initialized by XInitThreads */ +LockInfoPtr _Xglobal_lock = NULL; +void (*_XCreateMutex_fn)(LockInfoPtr) = NULL; +/* struct _XCVList *(*_XCreateCVL_fn)() = NULL; */ +void (*_XFreeMutex_fn)(LockInfoPtr) = NULL; +void (*_XLockMutex_fn)( + LockInfoPtr /* lock */ +#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE) + , char * /* file */ + , int /* line */ +#endif + ) = NULL; +void (*_XUnlockMutex_fn)( + LockInfoPtr /* lock */ +#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE) + , char * /* file */ + , int /* line */ +#endif + ) = NULL; +xthread_t (*_Xthread_self_fn)(void) = NULL; + +#define XThread_Self() ((*_Xthread_self_fn)()) + +#endif /* XTHREADS */ + +/* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX + * systems are broken and return EWOULDBLOCK when they should return EAGAIN + */ +#ifdef WIN32 +#define ETEST() (WSAGetLastError() == WSAEWOULDBLOCK) +#else +#ifdef __CYGWIN__ /* Cygwin uses ENOBUFS to signal socket is full */ +#define ETEST() (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS) +#else +#if defined(EAGAIN) && defined(EWOULDBLOCK) +#define ETEST() (errno == EAGAIN || errno == EWOULDBLOCK) +#else +#ifdef EAGAIN +#define ETEST() (errno == EAGAIN) +#else +#define ETEST() (errno == EWOULDBLOCK) +#endif /* EAGAIN */ +#endif /* EAGAIN && EWOULDBLOCK */ +#endif /* __CYGWIN__ */ +#endif /* WIN32 */ + +#ifdef WIN32 +#define ECHECK(err) (WSAGetLastError() == err) +#define ESET(val) WSASetLastError(val) +#else +#ifdef __UNIXOS2__ +#define ECHECK(err) (errno == err) +#define ESET(val) +#else +#define ECHECK(err) (errno == err) +#define ESET(val) errno = val +#endif +#endif + +#if defined(LOCALCONN) || defined(LACHMAN) +#ifdef EMSGSIZE +#define ESZTEST() (ECHECK(EMSGSIZE) || ECHECK(ERANGE)) +#else +#define ESZTEST() ECHECK(ERANGE) +#endif +#else +#ifdef EMSGSIZE +#define ESZTEST() ECHECK(EMSGSIZE) +#endif +#endif + +#ifdef __UNIXOS2__ +#include <limits.h> +#define MAX_PATH _POSIX_PATH_MAX +#endif + +/* + * The following routines are internal routines used by Xlib for protocol + * packet transmission and reception. + * + * _XIOError(Display *) will be called if any sort of system call error occurs. + * This is assumed to be a fatal condition, i.e., XIOError should not return. + * + * _XError(Display *, xError *) will be called whenever an X_Error event is + * received. This is not assumed to be a fatal condition, i.e., it is + * acceptable for this procedure to return. However, XError should NOT + * perform any operations (directly or indirectly) on the DISPLAY. + * + * Routines declared with a return type of 'Status' return 0 on failure, + * and non 0 on success. Routines with no declared return type don't + * return anything. Whenever possible routines that create objects return + * the object they have created. + */ + +#define POLLFD_CACHE_SIZE 5 + +/* initialize the struct array passed to poll() below */ +Bool _XPollfdCacheInit( + Display *dpy) +{ +#ifdef USE_POLL + struct pollfd *pfp; + + pfp = (struct pollfd *)Xmalloc(POLLFD_CACHE_SIZE * sizeof(struct pollfd)); + if (!pfp) + return False; + pfp[0].fd = dpy->fd; + pfp[0].events = POLLIN; + + dpy->filedes = (XPointer)pfp; +#endif + return True; +} + +void _XPollfdCacheAdd( + Display *dpy, + int fd) +{ +#ifdef USE_POLL + struct pollfd *pfp = (struct pollfd *)dpy->filedes; + + if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) { + pfp[dpy->im_fd_length].fd = fd; + pfp[dpy->im_fd_length].events = POLLIN; + } +#endif +} + +/* ARGSUSED */ +void _XPollfdCacheDel( + Display *dpy, + int fd) /* not used */ +{ +#ifdef USE_POLL + struct pollfd *pfp = (struct pollfd *)dpy->filedes; + struct _XConnectionInfo *conni; + + /* just recalculate whole list */ + if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) { + int loc = 1; + for (conni = dpy->im_fd_info; conni; conni=conni->next) { + pfp[loc].fd = conni->fd; + pfp[loc].events = POLLIN; + loc++; + } + } +#endif +} + +static int sync_hazard(Display *dpy) +{ + unsigned long span = dpy->request - dpy->last_request_read; + unsigned long hazard = min((dpy->bufmax - dpy->buffer) / SIZEOF(xReq), 65535 - 10); + return span >= 65535 - hazard - 10; +} + +static +void sync_while_locked(Display *dpy) +{ +#ifdef XTHREADS + if (dpy->lock) + (*dpy->lock->user_lock_display)(dpy); +#endif + UnlockDisplay(dpy); + SyncHandle(); + InternalLockDisplay(dpy, /* don't skip user locks */ 0); +#ifdef XTHREADS + if (dpy->lock) + (*dpy->lock->user_unlock_display)(dpy); +#endif +} + +void _XSeqSyncFunction( + register Display *dpy) +{ + xGetInputFocusReply rep; + register xReq *req; + + if ((dpy->request - dpy->last_request_read) >= (65535 - BUFSIZE/SIZEOF(xReq))) { + GetEmptyReq(GetInputFocus, req); + (void) _XReply (dpy, (xReply *)&rep, 0, xTrue); + sync_while_locked(dpy); + } else if (sync_hazard(dpy)) + _XSetPrivSyncFunction(dpy); +} + +/* NOTE: only called if !XTHREADS, or when XInitThreads wasn't called. */ +static int +_XPrivSyncFunction (Display *dpy) +{ +#if XTHREADS + assert(!dpy->lock_fns); +#endif + assert(dpy->synchandler == _XPrivSyncFunction); + assert((dpy->flags & XlibDisplayPrivSync) != 0); + dpy->synchandler = dpy->savedsynchandler; + dpy->savedsynchandler = NULL; + dpy->flags &= ~XlibDisplayPrivSync; + if(dpy->synchandler) + dpy->synchandler(dpy); + _XIDHandler(dpy); + _XSeqSyncFunction(dpy); + return 0; +} + +void _XSetPrivSyncFunction(Display *dpy) +{ +#ifdef XTHREADS + if (dpy->lock_fns) + return; +#endif + if (!(dpy->flags & XlibDisplayPrivSync)) { + dpy->savedsynchandler = dpy->synchandler; + dpy->synchandler = _XPrivSyncFunction; + dpy->flags |= XlibDisplayPrivSync; + } +} + +void _XSetSeqSyncFunction(Display *dpy) +{ + if (sync_hazard(dpy)) + _XSetPrivSyncFunction (dpy); +} + +#ifdef LONG64 +void _XRead32( + Display *dpy, + register long *data, + long len) +{ + register int *buf; + register long i; + + if (len) { + (void) _XRead(dpy, (char *)data, len); + i = len >> 2; + buf = (int *)data + i; + data += i; + while (--i >= 0) + *--data = *--buf; + } +} +#endif /* LONG64 */ + +#ifdef WORD64 + +/* + * XXX This is a *really* stupid way of doing this.... + * PACKBUFFERSIZE must be a multiple of 4. + */ + +#define PACKBUFFERSIZE 4096 + + +/* + * _XRead32 - Read bytes from the socket unpacking each 32 bits + * into a long (64 bits on a CRAY computer). + * + */ +static void _doXRead32( + register Display *dpy, + register long *data + register long size, + register char *packbuffer) +{ + long *lpack,*lp; + long mask32 = 0x00000000ffffffff; + long maskw, nwords, i, bits; + + _XReadPad (dpy, packbuffer, size); + + lp = data; + lpack = (long *) packbuffer; + nwords = size >> 2; + bits = 32; + + for(i=0;i<nwords;i++){ + maskw = mask32 << bits; + *lp++ = ( *lpack & maskw ) >> bits; + bits = bits ^32; + if(bits){ + lpack++; + } + } +} + +void _XRead32( + Display *dpy, + long *data, + long len) +{ + char packbuffer[PACKBUFFERSIZE]; + unsigned nunits = PACKBUFFERSIZE >> 2; + + for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) { + _doXRead32 (dpy, data, PACKBUFFERSIZE, packbuffer); + } + if (len) _doXRead32 (dpy, data, len, packbuffer); +} + + + +/* + * _XRead16 - Read bytes from the socket unpacking each 16 bits + * into a long (64 bits on a CRAY computer). + * + */ +static _doXRead16( + register Display *dpy, + register short *data, + register long size, + char *packbuffer) +{ + long *lpack,*lp; + long mask16 = 0x000000000000ffff; + long maskw, nwords, i, bits; + + (void) _XRead(dpy,packbuffer,size); /* don't do a padded read... */ + + lp = (long *) data; + lpack = (long *) packbuffer; + nwords = size >> 1; /* number of 16 bit words to be unpacked */ + bits = 48; + for(i=0;i<nwords;i++){ + maskw = mask16 << bits; + *lp++ = ( *lpack & maskw ) >> bits; + bits -= 16; + if(bits < 0){ + lpack++; + bits = 48; + } + } +} + +void _XRead16( + Display *dpy, + short *data, + long len) +{ + char packbuffer[PACKBUFFERSIZE]; + unsigned nunits = PACKBUFFERSIZE >> 1; + + for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) { + _doXRead16 (dpy, data, PACKBUFFERSIZE, packbuffer); + } + if (len) _doXRead16 (dpy, data, len, packbuffer); +} + +void _XRead16Pad( + Display *dpy, + short *data, + long size) +{ + int slop = (size & 3); + short slopbuf[3]; + + _XRead16 (dpy, data, size); + if (slop > 0) { + _XRead16 (dpy, slopbuf, 4 - slop); + } +} +#endif /* WORD64 */ + +/* + * The hard part about this is that we only get 16 bits from a reply. + * We have three values that will march along, with the following invariant: + * dpy->last_request_read <= rep->sequenceNumber <= dpy->request + * We have to keep + * dpy->request - dpy->last_request_read < 2^16 + * or else we won't know for sure what value to use in events. We do this + * by forcing syncs when we get close. + */ + +unsigned long +_XSetLastRequestRead( + register Display *dpy, + register xGenericReply *rep) +{ + register unsigned long newseq, lastseq; + + lastseq = dpy->last_request_read; + /* + * KeymapNotify has no sequence number, but is always guaranteed + * to immediately follow another event, except when generated via + * SendEvent (hmmm). + */ + if ((rep->type & 0x7f) == KeymapNotify) + return(lastseq); + + newseq = (lastseq & ~((unsigned long)0xffff)) | rep->sequenceNumber; + + if (newseq < lastseq) { + newseq += 0x10000; + if (newseq > dpy->request) { + (void) fprintf (stderr, + "Xlib: sequence lost (0x%lx > 0x%lx) in reply type 0x%x!\n", + newseq, dpy->request, + (unsigned int) rep->type); + newseq -= 0x10000; + } + } + + dpy->last_request_read = newseq; + return(newseq); +} + +/* + * Support for internal connections, such as an IM might use. + * By Stephen Gildea, X Consortium, September 1993 + */ + +/* _XRegisterInternalConnection + * Each IM (or Xlib extension) that opens a file descriptor that Xlib should + * include in its select/poll mask must call this function to register the + * fd with Xlib. Any XConnectionWatchProc registered by XAddConnectionWatch + * will also be called. + * + * Whenever Xlib detects input available on fd, it will call callback + * with call_data to process it. If non-Xlib code calls select/poll + * and detects input available, it must call XProcessInternalConnection, + * which will call the associated callback. + * + * Non-Xlib code can learn about these additional fds by calling + * XInternalConnectionNumbers or, more typically, by registering + * a XConnectionWatchProc with XAddConnectionWatch + * to be called when fds are registered or unregistered. + * + * Returns True if registration succeeded, False if not, typically + * because could not allocate memory. + * Assumes Display locked when called. + */ +Status +_XRegisterInternalConnection( + Display* dpy, + int fd, + _XInternalConnectionProc callback, + XPointer call_data +) +{ + struct _XConnectionInfo *new_conni, **iptr; + struct _XConnWatchInfo *watchers; + XPointer *wd; + + new_conni = (struct _XConnectionInfo*)Xmalloc(sizeof(struct _XConnectionInfo)); + if (!new_conni) + return 0; + new_conni->watch_data = (XPointer *)Xmalloc(dpy->watcher_count * sizeof(XPointer)); + if (!new_conni->watch_data) { + Xfree(new_conni); + return 0; + } + new_conni->fd = fd; + new_conni->read_callback = callback; + new_conni->call_data = call_data; + new_conni->next = NULL; + /* link new structure onto end of list */ + for (iptr = &dpy->im_fd_info; *iptr; iptr = &(*iptr)->next) + ; + *iptr = new_conni; + dpy->im_fd_length++; + _XPollfdCacheAdd(dpy, fd); + + for (watchers=dpy->conn_watchers, wd=new_conni->watch_data; + watchers; + watchers=watchers->next, wd++) { + *wd = NULL; /* for cleanliness */ + (*watchers->fn) (dpy, watchers->client_data, fd, True, wd); + } + + return 1; +} + +/* _XUnregisterInternalConnection + * Each IM (or Xlib extension) that closes a file descriptor previously + * registered with _XRegisterInternalConnection must call this function. + * Any XConnectionWatchProc registered by XAddConnectionWatch + * will also be called. + * + * Assumes Display locked when called. + */ +void +_XUnregisterInternalConnection( + Display* dpy, + int fd +) +{ + struct _XConnectionInfo *info_list, **prev; + struct _XConnWatchInfo *watch; + XPointer *wd; + + for (prev = &dpy->im_fd_info; (info_list = *prev); + prev = &info_list->next) { + if (info_list->fd == fd) { + *prev = info_list->next; + dpy->im_fd_length--; + for (watch=dpy->conn_watchers, wd=info_list->watch_data; + watch; + watch=watch->next, wd++) { + (*watch->fn) (dpy, watch->client_data, fd, False, wd); + } + if (info_list->watch_data) + Xfree (info_list->watch_data); + Xfree (info_list); + break; + } + } + _XPollfdCacheDel(dpy, fd); +} + +/* XInternalConnectionNumbers + * Returns an array of fds and an array of corresponding call data. + * Typically a XConnectionWatchProc registered with XAddConnectionWatch + * will be used instead of this function to discover + * additional fds to include in the select/poll mask. + * + * The list is allocated with Xmalloc and should be freed by the caller + * with Xfree; + */ +Status +XInternalConnectionNumbers( + Display *dpy, + int **fd_return, + int *count_return +) +{ + int count; + struct _XConnectionInfo *info_list; + int *fd_list; + + LockDisplay(dpy); + count = 0; + for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) + count++; + fd_list = (int*) Xmalloc (count * sizeof(int)); + if (!fd_list) { + UnlockDisplay(dpy); + return 0; + } + count = 0; + for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) { + fd_list[count] = info_list->fd; + count++; + } + UnlockDisplay(dpy); + + *fd_return = fd_list; + *count_return = count; + return 1; +} + +void _XProcessInternalConnection( + Display *dpy, + struct _XConnectionInfo *conn_info) +{ + dpy->flags |= XlibDisplayProcConni; + UnlockDisplay(dpy); + (*conn_info->read_callback) (dpy, conn_info->fd, conn_info->call_data); + LockDisplay(dpy); + dpy->flags &= ~XlibDisplayProcConni; +} + +/* XProcessInternalConnection + * Call the _XInternalConnectionProc registered by _XRegisterInternalConnection + * for this fd. + * The Display is NOT locked during the call. + */ +void +XProcessInternalConnection( + Display* dpy, + int fd +) +{ + struct _XConnectionInfo *info_list; + + LockDisplay(dpy); + for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) { + if (info_list->fd == fd) { + _XProcessInternalConnection(dpy, info_list); + break; + } + } + UnlockDisplay(dpy); +} + +/* XAddConnectionWatch + * Register a callback to be called whenever _XRegisterInternalConnection + * or _XUnregisterInternalConnection is called. + * Callbacks are called with the Display locked. + * If any connections are already registered, the callback is immediately + * called for each of them. + */ +Status +XAddConnectionWatch( + Display* dpy, + XConnectionWatchProc callback, + XPointer client_data +) +{ + struct _XConnWatchInfo *new_watcher, **wptr; + struct _XConnectionInfo *info_list; + XPointer *wd_array; + + LockDisplay(dpy); + + /* allocate new watch data */ + for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) { + wd_array = (XPointer *)Xrealloc((char *)info_list->watch_data, + (dpy->watcher_count + 1) * + sizeof(XPointer)); + if (!wd_array) { + UnlockDisplay(dpy); + return 0; + } + wd_array[dpy->watcher_count] = NULL; /* for cleanliness */ + } + + new_watcher = (struct _XConnWatchInfo*)Xmalloc(sizeof(struct _XConnWatchInfo)); + if (!new_watcher) { + UnlockDisplay(dpy); + return 0; + } + new_watcher->fn = callback; + new_watcher->client_data = client_data; + new_watcher->next = NULL; + + /* link new structure onto end of list */ + for (wptr = &dpy->conn_watchers; *wptr; wptr = &(*wptr)->next) + ; + *wptr = new_watcher; + dpy->watcher_count++; + + /* call new watcher on all currently registered fds */ + for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) { + (*callback) (dpy, client_data, info_list->fd, True, + info_list->watch_data + dpy->watcher_count - 1); + } + + UnlockDisplay(dpy); + return 1; +} + +/* XRemoveConnectionWatch + * Unregister a callback registered by XAddConnectionWatch. + * Both callback and client_data must match what was passed to + * XAddConnectionWatch. + */ +void +XRemoveConnectionWatch( + Display* dpy, + XConnectionWatchProc callback, + XPointer client_data +) +{ + struct _XConnWatchInfo *watch; + struct _XConnWatchInfo *previous = NULL; + struct _XConnectionInfo *conni; + int counter = 0; + + LockDisplay(dpy); + for (watch=dpy->conn_watchers; watch; watch=watch->next) { + if (watch->fn == callback && watch->client_data == client_data) { + if (previous) + previous->next = watch->next; + else + dpy->conn_watchers = watch->next; + Xfree (watch); + dpy->watcher_count--; + /* remove our watch_data for each connection */ + for (conni=dpy->im_fd_info; conni; conni=conni->next) { + /* don't bother realloc'ing; these arrays are small anyway */ + /* overlapping */ + memmove(conni->watch_data+counter, + conni->watch_data+counter+1, + dpy->watcher_count - counter); + } + break; + } + previous = watch; + counter++; + } + UnlockDisplay(dpy); +} + +/* end of internal connections support */ + +/* Cookie jar implementation + dpy->cookiejar is a linked list. _XEnq receives the events but leaves + them in the normal EQ. _XStoreEvent returns the cookie event (minus + data pointer) and adds it to the cookiejar. _XDeq just removes + the entry like any other event but resets the data pointer for + cookie events (to avoid double-free, the memory is re-used by Xlib). + + _XFetchEventCookie (called from XGetEventData) removes a cookie from the + jar. _XFreeEventCookies removes all unclaimed cookies from the jar + (called by XNextEvent). + + _XFreeDisplayStructure calls _XFreeEventCookies for each cookie in the + normal EQ. + */ + +#include "utlist.h" +struct stored_event { + XGenericEventCookie ev; + struct stored_event *prev; + struct stored_event *next; +}; + +Bool +_XIsEventCookie(Display *dpy, XEvent *ev) +{ + return (ev->xcookie.type == GenericEvent && + dpy->generic_event_vec[ev->xcookie.extension & 0x7F] != NULL); +} + +/** + * Free all events in the event list. + */ +void +_XFreeEventCookies(Display *dpy) +{ + struct stored_event **head, *e, *tmp; + + if (!dpy->cookiejar) + return; + + head = (struct stored_event**)&dpy->cookiejar; + + DL_FOREACH_SAFE(*head, e, tmp) { + if (dpy->cookiejar == e) + dpy->cookiejar = NULL; + XFree(e->ev.data); + XFree(e); + } +} + +/** + * Add an event to the display's event list. This event must be freed on the + * next call to XNextEvent(). + */ +void +_XStoreEventCookie(Display *dpy, XEvent *event) +{ + XGenericEventCookie* cookie = &event->xcookie; + struct stored_event **head, *add; + + if (!_XIsEventCookie(dpy, event)) + return; + + head = (struct stored_event**)(&dpy->cookiejar); + + add = Xmalloc(sizeof(struct stored_event)); + if (!add) { + ESET(ENOMEM); + _XIOError(dpy); + } + add->ev = *cookie; + DL_APPEND(*head, add); + cookie->data = NULL; /* don't return data yet, must be claimed */ +} + +/** + * Return the event with the given cookie and remove it from the list. + */ +Bool +_XFetchEventCookie(Display *dpy, XGenericEventCookie* ev) +{ + Bool ret = False; + struct stored_event **head, *event; + head = (struct stored_event**)&dpy->cookiejar; + + if (!_XIsEventCookie(dpy, (XEvent*)ev)) + return ret; + + DL_FOREACH(*head, event) { + if (event->ev.cookie == ev->cookie && + event->ev.extension == ev->extension && + event->ev.evtype == ev->evtype) { + *ev = event->ev; + DL_DELETE(*head, event); + Xfree(event); + ret = True; + break; + } + } + + return ret; +} + +Bool +_XCopyEventCookie(Display *dpy, XGenericEventCookie *in, XGenericEventCookie *out) +{ + Bool ret = False; + int extension; + + if (!_XIsEventCookie(dpy, (XEvent*)in) || !out) + return ret; + + extension = in->extension & 0x7F; + + if (!dpy->generic_event_copy_vec[extension]) + return ret; + + ret = ((*dpy->generic_event_copy_vec[extension])(dpy, in, out)); + out->cookie = ret ? ++dpy->next_cookie : 0; + return ret; +} + + +/* + * _XEnq - Place event packets on the display's queue. + * note that no squishing of move events in V11, since there + * is pointer motion hints.... + */ +void _XEnq( + register Display *dpy, + register xEvent *event) +{ + register _XQEvent *qelt; + int type, extension; + + if ((qelt = dpy->qfree)) { + /* If dpy->qfree is non-NULL do this, else malloc a new one. */ + dpy->qfree = qelt->next; + } + else if ((qelt = + (_XQEvent *) Xmalloc((unsigned)sizeof(_XQEvent))) == NULL) { + /* Malloc call failed! */ + ESET(ENOMEM); + _XIOError(dpy); + } + qelt->next = NULL; + + type = event->u.u.type & 0177; + extension = ((xGenericEvent*)event)->extension; + + qelt->event.type = type; + /* If an extension has registerd a generic_event_vec handler, then + * it can handle event cookies. Otherwise, proceed with the normal + * event handlers. + * + * If the generic_event_vec is called, qelt->event is a event cookie + * with the data pointer and the "free" pointer set. Data pointer is + * some memory allocated by the extension. + */ + if (type == GenericEvent && dpy->generic_event_vec[extension & 0x7F]) { + XGenericEventCookie *cookie = &qelt->event.xcookie; + (*dpy->generic_event_vec[extension & 0x7F])(dpy, cookie, event); + cookie->cookie = ++dpy->next_cookie; + + qelt->qserial_num = dpy->next_event_serial_num++; + if (dpy->tail) dpy->tail->next = qelt; + else dpy->head = qelt; + + dpy->tail = qelt; + dpy->qlen++; + } else if ((*dpy->event_vec[type])(dpy, &qelt->event, event)) { + qelt->qserial_num = dpy->next_event_serial_num++; + if (dpy->tail) dpy->tail->next = qelt; + else dpy->head = qelt; + + dpy->tail = qelt; + dpy->qlen++; + } else { + /* ignored, or stashed away for many-to-one compression */ + qelt->next = dpy->qfree; + dpy->qfree = qelt; + } +} + +/* + * _XDeq - Remove event packet from the display's queue. + */ +void _XDeq( + register Display *dpy, + register _XQEvent *prev, /* element before qelt */ + register _XQEvent *qelt) /* element to be unlinked */ +{ + if (prev) { + if ((prev->next = qelt->next) == NULL) + dpy->tail = prev; + } else { + /* no prev, so removing first elt */ + if ((dpy->head = qelt->next) == NULL) + dpy->tail = NULL; + } + qelt->qserial_num = 0; + qelt->next = dpy->qfree; + dpy->qfree = qelt; + dpy->qlen--; + + if (_XIsEventCookie(dpy, &qelt->event)) { + XGenericEventCookie* cookie = &qelt->event.xcookie; + /* dpy->qfree is re-used, reset memory to avoid double free on + * _XFreeDisplayStructure */ + cookie->data = NULL; + } +} + +/* + * EventToWire in separate file in that often not needed. + */ + +/*ARGSUSED*/ +Bool +_XUnknownWireEvent( + register Display *dpy, /* pointer to display structure */ + register XEvent *re, /* pointer to where event should be reformatted */ + register xEvent *event) /* wire protocol event */ +{ +#ifdef notdef + (void) fprintf(stderr, + "Xlib: unhandled wire event! event number = %d, display = %x\n.", + event->u.u.type, dpy); +#endif + return(False); +} + +Bool +_XUnknownWireEventCookie( + Display *dpy, /* pointer to display structure */ + XGenericEventCookie *re, /* pointer to where event should be reformatted */ + xEvent *event) /* wire protocol event */ +{ +#ifdef notdef + fprintf(stderr, + "Xlib: unhandled wire cookie event! extension number = %d, display = %x\n.", + ((xGenericEvent*)event)->extension, dpy); +#endif + return(False); +} + +Bool +_XUnknownCopyEventCookie( + Display *dpy, /* pointer to display structure */ + XGenericEventCookie *in, /* source */ + XGenericEventCookie *out) /* destination */ +{ +#ifdef notdef + fprintf(stderr, + "Xlib: unhandled cookie event copy! extension number = %d, display = %x\n.", + in->extension, dpy); +#endif + return(False); +} + +/*ARGSUSED*/ +Status +_XUnknownNativeEvent( + register Display *dpy, /* pointer to display structure */ + register XEvent *re, /* pointer to where event should be reformatted */ + register xEvent *event) /* wire protocol event */ +{ +#ifdef notdef + (void) fprintf(stderr, + "Xlib: unhandled native event! event number = %d, display = %x\n.", + re->type, dpy); +#endif + return(0); +} +/* + * reformat a wire event into an XEvent structure of the right type. + */ +Bool +_XWireToEvent( + register Display *dpy, /* pointer to display structure */ + register XEvent *re, /* pointer to where event should be reformatted */ + register xEvent *event) /* wire protocol event */ +{ + + re->type = event->u.u.type & 0x7f; + ((XAnyEvent *)re)->serial = _XSetLastRequestRead(dpy, + (xGenericReply *)event); + ((XAnyEvent *)re)->send_event = ((event->u.u.type & 0x80) != 0); + ((XAnyEvent *)re)->display = dpy; + + /* Ignore the leading bit of the event type since it is set when a + client sends an event rather than the server. */ + + switch (event-> u.u.type & 0177) { + case KeyPress: + case KeyRelease: + { + register XKeyEvent *ev = (XKeyEvent*) re; + ev->root = event->u.keyButtonPointer.root; + ev->window = event->u.keyButtonPointer.event; + ev->subwindow = event->u.keyButtonPointer.child; + ev->time = event->u.keyButtonPointer.time; + ev->x = cvtINT16toInt(event->u.keyButtonPointer.eventX); + ev->y = cvtINT16toInt(event->u.keyButtonPointer.eventY); + ev->x_root = cvtINT16toInt(event->u.keyButtonPointer.rootX); + ev->y_root = cvtINT16toInt(event->u.keyButtonPointer.rootY); + ev->state = event->u.keyButtonPointer.state; + ev->same_screen = event->u.keyButtonPointer.sameScreen; + ev->keycode = event->u.u.detail; + } + break; + case ButtonPress: + case ButtonRelease: + { + register XButtonEvent *ev = (XButtonEvent *) re; + ev->root = event->u.keyButtonPointer.root; + ev->window = event->u.keyButtonPointer.event; + ev->subwindow = event->u.keyButtonPointer.child; + ev->time = event->u.keyButtonPointer.time; + ev->x = cvtINT16toInt(event->u.keyButtonPointer.eventX); + ev->y = cvtINT16toInt(event->u.keyButtonPointer.eventY); + ev->x_root = cvtINT16toInt(event->u.keyButtonPointer.rootX); + ev->y_root = cvtINT16toInt(event->u.keyButtonPointer.rootY); + ev->state = event->u.keyButtonPointer.state; + ev->same_screen = event->u.keyButtonPointer.sameScreen; + ev->button = event->u.u.detail; + } + break; + case MotionNotify: + { + register XMotionEvent *ev = (XMotionEvent *)re; + ev->root = event->u.keyButtonPointer.root; + ev->window = event->u.keyButtonPointer.event; + ev->subwindow = event->u.keyButtonPointer.child; + ev->time = event->u.keyButtonPointer.time; + ev->x = cvtINT16toInt(event->u.keyButtonPointer.eventX); + ev->y = cvtINT16toInt(event->u.keyButtonPointer.eventY); + ev->x_root = cvtINT16toInt(event->u.keyButtonPointer.rootX); + ev->y_root = cvtINT16toInt(event->u.keyButtonPointer.rootY); + ev->state = event->u.keyButtonPointer.state; + ev->same_screen = event->u.keyButtonPointer.sameScreen; + ev->is_hint = event->u.u.detail; + } + break; + case EnterNotify: + case LeaveNotify: + { + register XCrossingEvent *ev = (XCrossingEvent *) re; + ev->root = event->u.enterLeave.root; + ev->window = event->u.enterLeave.event; + ev->subwindow = event->u.enterLeave.child; + ev->time = event->u.enterLeave.time; + ev->x = cvtINT16toInt(event->u.enterLeave.eventX); + ev->y = cvtINT16toInt(event->u.enterLeave.eventY); + ev->x_root = cvtINT16toInt(event->u.enterLeave.rootX); + ev->y_root = cvtINT16toInt(event->u.enterLeave.rootY); + ev->state = event->u.enterLeave.state; + ev->mode = event->u.enterLeave.mode; + ev->same_screen = (event->u.enterLeave.flags & + ELFlagSameScreen) && True; + ev->focus = (event->u.enterLeave.flags & + ELFlagFocus) && True; + ev->detail = event->u.u.detail; + } + break; + case FocusIn: + case FocusOut: + { + register XFocusChangeEvent *ev = (XFocusChangeEvent *) re; + ev->window = event->u.focus.window; + ev->mode = event->u.focus.mode; + ev->detail = event->u.u.detail; + } + break; + case KeymapNotify: + { + register XKeymapEvent *ev = (XKeymapEvent *) re; + ev->window = None; + memcpy(&ev->key_vector[1], + (char *)((xKeymapEvent *) event)->map, + sizeof (((xKeymapEvent *) event)->map)); + } + break; + case Expose: + { + register XExposeEvent *ev = (XExposeEvent *) re; + ev->window = event->u.expose.window; + ev->x = event->u.expose.x; + ev->y = event->u.expose.y; + ev->width = event->u.expose.width; + ev->height = event->u.expose.height; + ev->count = event->u.expose.count; + } + break; + case GraphicsExpose: + { + register XGraphicsExposeEvent *ev = + (XGraphicsExposeEvent *) re; + ev->drawable = event->u.graphicsExposure.drawable; + ev->x = event->u.graphicsExposure.x; + ev->y = event->u.graphicsExposure.y; + ev->width = event->u.graphicsExposure.width; + ev->height = event->u.graphicsExposure.height; + ev->count = event->u.graphicsExposure.count; + ev->major_code = event->u.graphicsExposure.majorEvent; + ev->minor_code = event->u.graphicsExposure.minorEvent; + } + break; + case NoExpose: + { + register XNoExposeEvent *ev = (XNoExposeEvent *) re; + ev->drawable = event->u.noExposure.drawable; + ev->major_code = event->u.noExposure.majorEvent; + ev->minor_code = event->u.noExposure.minorEvent; + } + break; + case VisibilityNotify: + { + register XVisibilityEvent *ev = (XVisibilityEvent *) re; + ev->window = event->u.visibility.window; + ev->state = event->u.visibility.state; + } + break; + case CreateNotify: + { + register XCreateWindowEvent *ev = + (XCreateWindowEvent *) re; + ev->window = event->u.createNotify.window; + ev->parent = event->u.createNotify.parent; + ev->x = cvtINT16toInt(event->u.createNotify.x); + ev->y = cvtINT16toInt(event->u.createNotify.y); + ev->width = event->u.createNotify.width; + ev->height = event->u.createNotify.height; + ev->border_width = event->u.createNotify.borderWidth; + ev->override_redirect = event->u.createNotify.override; + } + break; + case DestroyNotify: + { + register XDestroyWindowEvent *ev = + (XDestroyWindowEvent *) re; + ev->window = event->u.destroyNotify.window; + ev->event = event->u.destroyNotify.event; + } + break; + case UnmapNotify: + { + register XUnmapEvent *ev = (XUnmapEvent *) re; + ev->window = event->u.unmapNotify.window; + ev->event = event->u.unmapNotify.event; + ev->from_configure = event->u.unmapNotify.fromConfigure; + } + break; + case MapNotify: + { + register XMapEvent *ev = (XMapEvent *) re; + ev->window = event->u.mapNotify.window; + ev->event = event->u.mapNotify.event; + ev->override_redirect = event->u.mapNotify.override; + } + break; + case MapRequest: + { + register XMapRequestEvent *ev = (XMapRequestEvent *) re; + ev->window = event->u.mapRequest.window; + ev->parent = event->u.mapRequest.parent; + } + break; + case ReparentNotify: + { + register XReparentEvent *ev = (XReparentEvent *) re; + ev->event = event->u.reparent.event; + ev->window = event->u.reparent.window; + ev->parent = event->u.reparent.parent; + ev->x = cvtINT16toInt(event->u.reparent.x); + ev->y = cvtINT16toInt(event->u.reparent.y); + ev->override_redirect = event->u.reparent.override; + } + break; + case ConfigureNotify: + { + register XConfigureEvent *ev = (XConfigureEvent *) re; + ev->event = event->u.configureNotify.event; + ev->window = event->u.configureNotify.window; + ev->above = event->u.configureNotify.aboveSibling; + ev->x = cvtINT16toInt(event->u.configureNotify.x); + ev->y = cvtINT16toInt(event->u.configureNotify.y); + ev->width = event->u.configureNotify.width; + ev->height = event->u.configureNotify.height; + ev->border_width = event->u.configureNotify.borderWidth; + ev->override_redirect = event->u.configureNotify.override; + } + break; + case ConfigureRequest: + { + register XConfigureRequestEvent *ev = + (XConfigureRequestEvent *) re; + ev->window = event->u.configureRequest.window; + ev->parent = event->u.configureRequest.parent; + ev->above = event->u.configureRequest.sibling; + ev->x = cvtINT16toInt(event->u.configureRequest.x); + ev->y = cvtINT16toInt(event->u.configureRequest.y); + ev->width = event->u.configureRequest.width; + ev->height = event->u.configureRequest.height; + ev->border_width = event->u.configureRequest.borderWidth; + ev->value_mask = event->u.configureRequest.valueMask; + ev->detail = event->u.u.detail; + } + break; + case GravityNotify: + { + register XGravityEvent *ev = (XGravityEvent *) re; + ev->window = event->u.gravity.window; + ev->event = event->u.gravity.event; + ev->x = cvtINT16toInt(event->u.gravity.x); + ev->y = cvtINT16toInt(event->u.gravity.y); + } + break; + case ResizeRequest: + { + register XResizeRequestEvent *ev = + (XResizeRequestEvent *) re; + ev->window = event->u.resizeRequest.window; + ev->width = event->u.resizeRequest.width; + ev->height = event->u.resizeRequest.height; + } + break; + case CirculateNotify: + { + register XCirculateEvent *ev = (XCirculateEvent *) re; + ev->window = event->u.circulate.window; + ev->event = event->u.circulate.event; + ev->place = event->u.circulate.place; + } + break; + case CirculateRequest: + { + register XCirculateRequestEvent *ev = + (XCirculateRequestEvent *) re; + ev->window = event->u.circulate.window; + ev->parent = event->u.circulate.event; + ev->place = event->u.circulate.place; + } + break; + case PropertyNotify: + { + register XPropertyEvent *ev = (XPropertyEvent *) re; + ev->window = event->u.property.window; + ev->atom = event->u.property.atom; + ev->time = event->u.property.time; + ev->state = event->u.property.state; + } + break; + case SelectionClear: + { + register XSelectionClearEvent *ev = + (XSelectionClearEvent *) re; + ev->window = event->u.selectionClear.window; + ev->selection = event->u.selectionClear.atom; + ev->time = event->u.selectionClear.time; + } + break; + case SelectionRequest: + { + register XSelectionRequestEvent *ev = + (XSelectionRequestEvent *) re; + ev->owner = event->u.selectionRequest.owner; + ev->requestor = event->u.selectionRequest.requestor; + ev->selection = event->u.selectionRequest.selection; + ev->target = event->u.selectionRequest.target; + ev->property = event->u.selectionRequest.property; + ev->time = event->u.selectionRequest.time; + } + break; + case SelectionNotify: + { + register XSelectionEvent *ev = (XSelectionEvent *) re; + ev->requestor = event->u.selectionNotify.requestor; + ev->selection = event->u.selectionNotify.selection; + ev->target = event->u.selectionNotify.target; + ev->property = event->u.selectionNotify.property; + ev->time = event->u.selectionNotify.time; + } + break; + case ColormapNotify: + { + register XColormapEvent *ev = (XColormapEvent *) re; + ev->window = event->u.colormap.window; + ev->colormap = event->u.colormap.colormap; + ev->new = event->u.colormap.new; + ev->state = event->u.colormap.state; + } + break; + case ClientMessage: + { + register int i; + register XClientMessageEvent *ev + = (XClientMessageEvent *) re; + ev->window = event->u.clientMessage.window; + ev->format = event->u.u.detail; + switch (ev->format) { + case 8: + ev->message_type = event->u.clientMessage.u.b.type; + for (i = 0; i < 20; i++) + ev->data.b[i] = event->u.clientMessage.u.b.bytes[i]; + break; + case 16: + ev->message_type = event->u.clientMessage.u.s.type; + ev->data.s[0] = cvtINT16toShort(event->u.clientMessage.u.s.shorts0); + ev->data.s[1] = cvtINT16toShort(event->u.clientMessage.u.s.shorts1); + ev->data.s[2] = cvtINT16toShort(event->u.clientMessage.u.s.shorts2); + ev->data.s[3] = cvtINT16toShort(event->u.clientMessage.u.s.shorts3); + ev->data.s[4] = cvtINT16toShort(event->u.clientMessage.u.s.shorts4); + ev->data.s[5] = cvtINT16toShort(event->u.clientMessage.u.s.shorts5); + ev->data.s[6] = cvtINT16toShort(event->u.clientMessage.u.s.shorts6); + ev->data.s[7] = cvtINT16toShort(event->u.clientMessage.u.s.shorts7); + ev->data.s[8] = cvtINT16toShort(event->u.clientMessage.u.s.shorts8); + ev->data.s[9] = cvtINT16toShort(event->u.clientMessage.u.s.shorts9); + break; + case 32: + ev->message_type = event->u.clientMessage.u.l.type; + ev->data.l[0] = cvtINT32toLong(event->u.clientMessage.u.l.longs0); + ev->data.l[1] = cvtINT32toLong(event->u.clientMessage.u.l.longs1); + ev->data.l[2] = cvtINT32toLong(event->u.clientMessage.u.l.longs2); + ev->data.l[3] = cvtINT32toLong(event->u.clientMessage.u.l.longs3); + ev->data.l[4] = cvtINT32toLong(event->u.clientMessage.u.l.longs4); + break; + default: /* XXX should never occur */ + break; + } + } + break; + case MappingNotify: + { + register XMappingEvent *ev = (XMappingEvent *)re; + ev->window = 0; + ev->first_keycode = event->u.mappingNotify.firstKeyCode; + ev->request = event->u.mappingNotify.request; + ev->count = event->u.mappingNotify.count; + } + break; + default: + return(_XUnknownWireEvent(dpy, re, event)); + } + return(True); +} + + +/* + * _XDefaultIOError - Default fatal system error reporting routine. Called + * when an X internal system error is encountered. + */ +int _XDefaultIOError( + Display *dpy) +{ + if (ECHECK(EPIPE)) { + (void) fprintf (stderr, + "X connection to %s broken (explicit kill or server shutdown).\r\n", + DisplayString (dpy)); + } else { + (void) fprintf (stderr, + "XIO: fatal IO error %d (%s) on X server \"%s\"\r\n", +#ifdef WIN32 + WSAGetLastError(), strerror(WSAGetLastError()), +#else + errno, strerror (errno), +#endif + DisplayString (dpy)); + (void) fprintf (stderr, + " after %lu requests (%lu known processed) with %d events remaining.\r\n", + NextRequest(dpy) - 1, LastKnownRequestProcessed(dpy), + QLength(dpy)); + + } + exit(1); + return(0); /* dummy - function should never return */ +} + + +static int _XPrintDefaultError( + Display *dpy, + XErrorEvent *event, + FILE *fp) +{ + char buffer[BUFSIZ]; + char mesg[BUFSIZ]; + char number[32]; + const char *mtype = "XlibMessage"; + register _XExtension *ext = (_XExtension *)NULL; + _XExtension *bext = (_XExtension *)NULL; + XGetErrorText(dpy, event->error_code, buffer, BUFSIZ); + XGetErrorDatabaseText(dpy, mtype, "XError", "X Error", mesg, BUFSIZ); + (void) fprintf(fp, "%s: %s\n ", mesg, buffer); + XGetErrorDatabaseText(dpy, mtype, "MajorCode", "Request Major code %d", + mesg, BUFSIZ); + (void) fprintf(fp, mesg, event->request_code); + if (event->request_code < 128) { + sprintf(number, "%d", event->request_code); + XGetErrorDatabaseText(dpy, "XRequest", number, "", buffer, BUFSIZ); + } else { + for (ext = dpy->ext_procs; + ext && (ext->codes.major_opcode != event->request_code); + ext = ext->next) + ; + if (ext) + strcpy(buffer, ext->name); + else + buffer[0] = '\0'; + } + (void) fprintf(fp, " (%s)\n", buffer); + if (event->request_code >= 128) { + XGetErrorDatabaseText(dpy, mtype, "MinorCode", "Request Minor code %d", + mesg, BUFSIZ); + fputs(" ", fp); + (void) fprintf(fp, mesg, event->minor_code); + if (ext) { + sprintf(mesg, "%s.%d", ext->name, event->minor_code); + XGetErrorDatabaseText(dpy, "XRequest", mesg, "", buffer, BUFSIZ); + (void) fprintf(fp, " (%s)", buffer); + } + fputs("\n", fp); + } + if (event->error_code >= 128) { + /* kludge, try to find the extension that caused it */ + buffer[0] = '\0'; + for (ext = dpy->ext_procs; ext; ext = ext->next) { + if (ext->error_string) + (*ext->error_string)(dpy, event->error_code, &ext->codes, + buffer, BUFSIZ); + if (buffer[0]) { + bext = ext; + break; + } + if (ext->codes.first_error && + ext->codes.first_error < (int)event->error_code && + (!bext || ext->codes.first_error > bext->codes.first_error)) + bext = ext; + } + if (bext) + sprintf(buffer, "%s.%d", bext->name, + event->error_code - bext->codes.first_error); + else + strcpy(buffer, "Value"); + XGetErrorDatabaseText(dpy, mtype, buffer, "", mesg, BUFSIZ); + if (mesg[0]) { + fputs(" ", fp); + (void) fprintf(fp, mesg, event->resourceid); + fputs("\n", fp); + } + /* let extensions try to print the values */ + for (ext = dpy->ext_procs; ext; ext = ext->next) { + if (ext->error_values) + (*ext->error_values)(dpy, event, fp); + } + } else if ((event->error_code == BadWindow) || + (event->error_code == BadPixmap) || + (event->error_code == BadCursor) || + (event->error_code == BadFont) || + (event->error_code == BadDrawable) || + (event->error_code == BadColor) || + (event->error_code == BadGC) || + (event->error_code == BadIDChoice) || + (event->error_code == BadValue) || + (event->error_code == BadAtom)) { + if (event->error_code == BadValue) + XGetErrorDatabaseText(dpy, mtype, "Value", "Value 0x%x", + mesg, BUFSIZ); + else if (event->error_code == BadAtom) + XGetErrorDatabaseText(dpy, mtype, "AtomID", "AtomID 0x%x", + mesg, BUFSIZ); + else + XGetErrorDatabaseText(dpy, mtype, "ResourceID", "ResourceID 0x%x", + mesg, BUFSIZ); + fputs(" ", fp); + (void) fprintf(fp, mesg, event->resourceid); + fputs("\n", fp); + } + XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d", + mesg, BUFSIZ); + fputs(" ", fp); + (void) fprintf(fp, mesg, event->serial); + XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%d", + mesg, BUFSIZ); + fputs("\n ", fp); + (void) fprintf(fp, mesg, dpy->request); + fputs("\n", fp); + if (event->error_code == BadImplementation) return 0; + return 1; +} + +int _XDefaultError( + Display *dpy, + XErrorEvent *event) +{ + if (_XPrintDefaultError (dpy, event, stderr) == 0) return 0; + exit(1); + /*NOTREACHED*/ +} + +/*ARGSUSED*/ +Bool _XDefaultWireError(Display *display, XErrorEvent *he, xError *we) +{ + return True; +} + +/* + * _XError - upcall internal or user protocol error handler + */ +int _XError ( + Display *dpy, + register xError *rep) +{ + /* + * X_Error packet encountered! We need to unpack the error before + * giving it to the user. + */ + XEvent event; /* make it a large event */ + register _XAsyncHandler *async, *next; + + event.xerror.serial = _XSetLastRequestRead(dpy, (xGenericReply *)rep); + + for (async = dpy->async_handlers; async; async = next) { + next = async->next; + if ((*async->handler)(dpy, (xReply *)rep, + (char *)rep, SIZEOF(xError), async->data)) + return 0; + } + + event.xerror.display = dpy; + event.xerror.type = X_Error; + event.xerror.resourceid = rep->resourceID; + event.xerror.error_code = rep->errorCode; + event.xerror.request_code = rep->majorCode; + event.xerror.minor_code = rep->minorCode; + if (dpy->error_vec && + !(*dpy->error_vec[rep->errorCode])(dpy, &event.xerror, rep)) + return 0; + if (_XErrorFunction != NULL) { + return (*_XErrorFunction)(dpy, (XErrorEvent *)&event); /* upcall */ + } else { + return _XDefaultError(dpy, (XErrorEvent *)&event); + } +} + +/* + * _XIOError - call user connection error handler and exit + */ +int +_XIOError ( + Display *dpy) +{ + dpy->flags |= XlibDisplayIOError; +#ifdef WIN32 + errno = WSAGetLastError(); +#endif + + /* This assumes that the thread calling exit will call any atexit handlers. + * If this does not hold, then an alternate solution would involve + * registering an atexit handler to take over the lock, which would only + * assume that the same thread calls all the atexit handlers. */ +#ifdef XTHREADS + if (dpy->lock) + (*dpy->lock->user_lock_display)(dpy); +#endif + UnlockDisplay(dpy); + + if (_XIOErrorFunction != NULL) + (*_XIOErrorFunction)(dpy); + else + _XDefaultIOError(dpy); + exit (1); + return 0; +} + + +/* + * This routine can be used to (cheaply) get some memory within a single + * Xlib routine for scratch space. A single buffer is reused each time + * if possible. To be MT safe, you can only call this between a call to + * GetReq* and a call to Data* or _XSend*, or in a context when the thread + * is guaranteed to not unlock the display. + */ +char *_XAllocScratch( + register Display *dpy, + unsigned long nbytes) +{ + if (nbytes > dpy->scratch_length) { + if (dpy->scratch_buffer) Xfree (dpy->scratch_buffer); + if ((dpy->scratch_buffer = Xmalloc((unsigned) nbytes))) + dpy->scratch_length = nbytes; + else dpy->scratch_length = 0; + } + return (dpy->scratch_buffer); +} + +/* + * Scratch space allocator you can call any time, multiple times, and be + * MT safe, but you must hand the buffer back with _XFreeTemp. + */ +char *_XAllocTemp( + register Display *dpy, + unsigned long nbytes) +{ + char *buf; + + buf = _XAllocScratch(dpy, nbytes); + dpy->scratch_buffer = NULL; + dpy->scratch_length = 0; + return buf; +} + +void _XFreeTemp( + register Display *dpy, + char *buf, + unsigned long nbytes) +{ + if (dpy->scratch_buffer) + Xfree(dpy->scratch_buffer); + dpy->scratch_buffer = buf; + dpy->scratch_length = nbytes; +} + +/* + * Given a visual id, find the visual structure for this id on this display. + */ +Visual *_XVIDtoVisual( + Display *dpy, + VisualID id) +{ + register int i, j, k; + register Screen *sp; + register Depth *dp; + register Visual *vp; + for (i = 0; i < dpy->nscreens; i++) { + sp = &dpy->screens[i]; + for (j = 0; j < sp->ndepths; j++) { + dp = &sp->depths[j]; + /* if nvisuals == 0 then visuals will be NULL */ + for (k = 0; k < dp->nvisuals; k++) { + vp = &dp->visuals[k]; + if (vp->visualid == id) return (vp); + } + } + } + return (NULL); +} + +int +XFree (void *data) +{ + Xfree (data); + return 1; +} + +#ifdef _XNEEDBCOPYFUNC +void _Xbcopy(b1, b2, length) + register char *b1, *b2; + register length; +{ + if (b1 < b2) { + b2 += length; + b1 += length; + while (length--) + *--b2 = *--b1; + } else { + while (length--) + *b2++ = *b1++; + } +} +#endif + +#ifdef DataRoutineIsProcedure +void Data( + Display *dpy, + char *data, + long len) +{ + if (dpy->bufptr + (len) <= dpy->bufmax) { + memcpy(dpy->bufptr, data, (int)len); + dpy->bufptr += ((len) + 3) & ~3; + } else { + _XSend(dpy, data, len); + } +} +#endif /* DataRoutineIsProcedure */ + + +#ifdef LONG64 +int +_XData32( + Display *dpy, + register long *data, + unsigned len) +{ + register int *buf; + register long i; + + while (len) { + buf = (int *)dpy->bufptr; + i = dpy->bufmax - (char *)buf; + if (!i) { + _XFlush(dpy); + continue; + } + if (len < i) + i = len; + dpy->bufptr = (char *)buf + i; + len -= i; + i >>= 2; + while (--i >= 0) + *buf++ = *data++; + } + return 0; +} +#endif /* LONG64 */ + +#ifdef WORD64 + +/* + * XXX This is a *really* stupid way of doing this. It should just use + * dpy->bufptr directly, taking into account where in the word it is. + */ + +/* + * Data16 - Place 16 bit data in the buffer. + * + * "dpy" is a pointer to a Display. + * "data" is a pointer to the data. + * "len" is the length in bytes of the data. + */ + +static doData16( + register Display *dpy, + short *data, + unsigned len, + char *packbuffer) +{ + long *lp,*lpack; + long i, nwords,bits; + long mask16 = 0x000000000000ffff; + + lp = (long *)data; + lpack = (long *)packbuffer; + +/* nwords is the number of 16 bit values to be packed, + * the low order 16 bits of each word will be packed + * into 64 bit words + */ + nwords = len >> 1; + bits = 48; + + for(i=0;i<nwords;i++){ + if (bits == 48) *lpack = 0; + *lpack ^= (*lp & mask16) << bits; + bits -= 16 ; + lp++; + if(bits < 0){ + lpack++; + bits = 48; + } + } + Data(dpy, packbuffer, len); +} + +_XData16 ( + Display *dpy, + short *data, + unsigned len) +{ + char packbuffer[PACKBUFFERSIZE]; + unsigned nunits = PACKBUFFERSIZE >> 1; + + for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) { + doData16 (dpy, data, PACKBUFFERSIZE, packbuffer); + } + if (len) doData16 (dpy, data, len, packbuffer); +} + +/* + * Data32 - Place 32 bit data in the buffer. + * + * "dpy" is a pointer to a Display. + * "data" is a pointer to the data. + * "len" is the length in bytes of the data. + */ + +static doData32( + register Display *dpy + long *data, + unsigned len, + char *packbuffer) +{ + long *lp,*lpack; + long i,bits,nwords; + long mask32 = 0x00000000ffffffff; + + lpack = (long *) packbuffer; + lp = data; + +/* nwords is the number of 32 bit values to be packed + * the low order 32 bits of each word will be packed + * into 64 bit words + */ + nwords = len >> 2; + bits = 32; + + for(i=0;i<nwords;i++){ + if (bits == 32) *lpack = 0; + *lpack ^= (*lp & mask32) << bits; + bits = bits ^32; + lp++; + if(bits) + lpack++; + } + Data(dpy, packbuffer, len); +} + +void _XData32( + Display *dpy, + long *data, + unsigned len) +{ + char packbuffer[PACKBUFFERSIZE]; + unsigned nunits = PACKBUFFERSIZE >> 2; + + for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) { + doData32 (dpy, data, PACKBUFFERSIZE, packbuffer); + } + if (len) doData32 (dpy, data, len, packbuffer); +} + +#endif /* WORD64 */ + + +/* Make sure this produces the same string as DefineLocal/DefineSelf in xdm. + * Otherwise, Xau will not be able to find your cookies in the Xauthority file. + * + * Note: POSIX says that the ``nodename'' member of utsname does _not_ have + * to have sufficient information for interfacing to the network, + * and so, you may be better off using gethostname (if it exists). + */ + +#if (defined(_POSIX_SOURCE) && !defined(AIXV3) && !defined(__QNX__)) || defined(hpux) || defined(SVR4) +#define NEED_UTSNAME +#include <sys/utsname.h> +#else +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#endif + +/* + * _XGetHostname - similar to gethostname but allows special processing. + */ +int _XGetHostname ( + char *buf, + int maxlen) +{ + int len; + +#ifdef NEED_UTSNAME + struct utsname name; + + if (maxlen <= 0 || buf == NULL) + return 0; + + uname (&name); + len = strlen (name.nodename); + if (len >= maxlen) len = maxlen - 1; + strncpy (buf, name.nodename, len); + buf[len] = '\0'; +#else + if (maxlen <= 0 || buf == NULL) + return 0; + + buf[0] = '\0'; + (void) gethostname (buf, maxlen); + buf [maxlen - 1] = '\0'; + len = strlen(buf); +#endif /* NEED_UTSNAME */ + return len; +} + + +/* + * _XScreenOfWindow - get the Screen of a given window + */ + +Screen *_XScreenOfWindow(Display *dpy, Window w) +{ + register int i; + Window root; + int x, y; /* dummy variables */ + unsigned int width, height, bw, depth; /* dummy variables */ + + if (XGetGeometry (dpy, w, &root, &x, &y, &width, &height, + &bw, &depth) == False) { + return NULL; + } + for (i = 0; i < ScreenCount (dpy); i++) { /* find root from list */ + if (root == RootWindow (dpy, i)) { + return ScreenOfDisplay (dpy, i); + } + } + return NULL; +} + + +#if defined(WIN32) + +/* + * These functions are intended to be used internally to Xlib only. + * These functions will always prefix the path with a DOS drive in the + * form "<drive-letter>:". As such, these functions are only suitable + * for use by Xlib function that supply a root-based path to some + * particular file, e.g. <ProjectRoot>/lib/X11/locale/locale.dir will + * be converted to "C:/usr/X11R6.3/lib/X11/locale/locale.dir". + */ + +static int access_file (path, pathbuf, len_pathbuf, pathret) + char* path; + char* pathbuf; + int len_pathbuf; + char** pathret; +{ + if (access (path, F_OK) == 0) { + if (strlen (path) < len_pathbuf) + *pathret = pathbuf; + else + *pathret = Xmalloc (strlen (path) + 1); + if (*pathret) { + strcpy (*pathret, path); + return 1; + } + } + return 0; +} + +static int AccessFile (path, pathbuf, len_pathbuf, pathret) + char* path; + char* pathbuf; + int len_pathbuf; + char** pathret; +{ + unsigned long drives; + int i, len; + char* drive; + char buf[MAX_PATH]; + char* bufp; + + /* just try the "raw" name first and see if it works */ + if (access_file (path, pathbuf, len_pathbuf, pathret)) + return 1; + + /* try the places set in the environment */ + drive = getenv ("_XBASEDRIVE"); +#ifdef __UNIXOS2__ + if (!drive) + drive = getenv ("X11ROOT"); +#endif + if (!drive) + drive = "C:"; + len = strlen (drive) + strlen (path); + if (len < MAX_PATH) bufp = buf; + else bufp = Xmalloc (len + 1); + strcpy (bufp, drive); + strcat (bufp, path); + if (access_file (bufp, pathbuf, len_pathbuf, pathret)) { + if (bufp != buf) Xfree (bufp); + return 1; + } + +#ifndef __UNIXOS2__ + /* one last place to look */ + drive = getenv ("HOMEDRIVE"); + if (drive) { + len = strlen (drive) + strlen (path); + if (len < MAX_PATH) bufp = buf; + else bufp = Xmalloc (len + 1); + strcpy (bufp, drive); + strcat (bufp, path); + if (access_file (bufp, pathbuf, len_pathbuf, pathret)) { + if (bufp != buf) Xfree (bufp); + return 1; + } + } + + /* tried everywhere else, go fishing */ +#define C_DRIVE ('C' - 'A') +#define Z_DRIVE ('Z' - 'A') + /* does OS/2 (with or with gcc-emx) have getdrives? */ + drives = _getdrives (); + for (i = C_DRIVE; i <= Z_DRIVE; i++) { /* don't check on A: or B: */ + if ((1 << i) & drives) { + len = 2 + strlen (path); + if (len < MAX_PATH) bufp = buf; + else bufp = Xmalloc (len + 1); + *bufp = 'A' + i; + *(bufp + 1) = ':'; + *(bufp + 2) = '\0'; + strcat (bufp, path); + if (access_file (bufp, pathbuf, len_pathbuf, pathret)) { + if (bufp != buf) Xfree (bufp); + return 1; + } + } + } +#endif + return 0; +} + +int _XOpenFile(path, flags) + _Xconst char* path; + int flags; +{ + char buf[MAX_PATH]; + char* bufp = NULL; + int ret = -1; + UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS); + + if (AccessFile (path, buf, MAX_PATH, &bufp)) + ret = open (bufp, flags); + + (void) SetErrorMode (olderror); + + if (bufp != buf) Xfree (bufp); + + return ret; +} + +int _XOpenFileMode(path, flags, mode) + _Xconst char* path; + int flags; + mode_t mode; +{ + char buf[MAX_PATH]; + char* bufp = NULL; + int ret = -1; + UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS); + + if (AccessFile (path, buf, MAX_PATH, &bufp)) + ret = open (bufp, flags, mode); + + (void) SetErrorMode (olderror); + + if (bufp != buf) Xfree (bufp); + + return ret; +} + +void* _XFopenFile(path, mode) + _Xconst char* path; + _Xconst char* mode; +{ + char buf[MAX_PATH]; + char* bufp = NULL; + void* ret = NULL; + UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS); + + if (AccessFile (path, buf, MAX_PATH, &bufp)) + ret = fopen (bufp, mode); + + (void) SetErrorMode (olderror); + + if (bufp != buf) Xfree (bufp); + + return ret; +} + +int _XAccessFile(path) + _Xconst char* path; +{ + char buf[MAX_PATH]; + char* bufp; + int ret = -1; + UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS); + + ret = AccessFile (path, buf, MAX_PATH, &bufp); + + (void) SetErrorMode (olderror); + + if (bufp != buf) Xfree (bufp); + + return ret; +} + +#endif + +#ifdef WIN32 +#undef _Xdebug +int _Xdebug = 0; +int *_Xdebug_p = &_Xdebug; +void (**_XCreateMutex_fn_p)(LockInfoPtr) = &_XCreateMutex_fn; +void (**_XFreeMutex_fn_p)(LockInfoPtr) = &_XFreeMutex_fn; +void (**_XLockMutex_fn_p)(LockInfoPtr +#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE) + , char * /* file */ + , int /* line */ +#endif + ) = &_XLockMutex_fn; +void (**_XUnlockMutex_fn_p)(LockInfoPtr +#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE) + , char * /* file */ + , int /* line */ +#endif + ) = &_XUnlockMutex_fn; +LockInfoPtr *_Xglobal_lock_p = &_Xglobal_lock; +#endif diff --git a/libX11/src/xkb/XKB.c b/libX11/src/xkb/XKB.c index 43b3ef95a..f926cb997 100644 --- a/libX11/src/xkb/XKB.c +++ b/libX11/src/xkb/XKB.c @@ -1,767 +1,767 @@ -/************************************************************
-Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
-
-Permission to use, copy, modify, and distribute this
-software and its documentation for any purpose and without
-fee is hereby granted, provided that the above copyright
-notice appear in all copies and that both that copyright
-notice and this permission notice appear in supporting
-documentation, and that the name of Silicon Graphics not be
-used in advertising or publicity pertaining to distribution
-of the software without specific prior written permission.
-Silicon Graphics makes no representation about the suitability
-of this software for any purpose. It is provided "as is"
-without any express or implied warranty.
-
-SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
-SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
-GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
-DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
-DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
-THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-********************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include "Xlibint.h"
-#include <X11/extensions/XKBproto.h>
-#include "XKBlibint.h"
-
-XkbInternAtomFunc _XkbInternAtomFunc= XInternAtom;
-XkbGetAtomNameFunc _XkbGetAtomNameFunc= XGetAtomName;
-
-Bool
-XkbQueryExtension( Display *dpy,
- int * opcodeReturn,
- int * eventBaseReturn,
- int * errorBaseReturn,
- int * majorReturn,
- int * minorReturn)
-{
- if (!XkbUseExtension(dpy,majorReturn,minorReturn))
- return False;
- if (opcodeReturn)
- *opcodeReturn = dpy->xkb_info->codes->major_opcode;
- if (eventBaseReturn)
- *eventBaseReturn = dpy->xkb_info->codes->first_event;
- if (errorBaseReturn)
- *errorBaseReturn = dpy->xkb_info->codes->first_error;
- if (majorReturn)
- *majorReturn = dpy->xkb_info->srv_major;
- if (minorReturn)
- *minorReturn = dpy->xkb_info->srv_minor;
- return True;
-}
-
-Bool
-XkbLibraryVersion(int *libMajorRtrn,int *libMinorRtrn)
-{
-int supported;
-
- if (*libMajorRtrn != XkbMajorVersion) {
- /* version 0.65 is (almost) compatible with 1.00 */
- if ((XkbMajorVersion==1)&&(((*libMajorRtrn)==0)&&((*libMinorRtrn)==65)))
- supported= True;
- else supported= False;
- }
- else {
- supported = True;
- }
-
- *libMajorRtrn = XkbMajorVersion;
- *libMinorRtrn = XkbMinorVersion;
- return supported;
-}
-
-Bool
-XkbSelectEvents( Display * dpy,
- unsigned int deviceSpec,
- unsigned int affect,
- unsigned int selectAll)
-{
- register xkbSelectEventsReq *req;
- XkbInfoPtr xkbi;
-
- if ((dpy->flags & XlibDisplayNoXkb) ||
- (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
- return False;
- LockDisplay(dpy);
- xkbi = dpy->xkb_info;
- xkbi->selected_events&= ~affect;
- xkbi->selected_events|= (affect&selectAll);
- GetReq(kbSelectEvents, req);
- req->reqType = xkbi->codes->major_opcode;
- req->xkbReqType = X_kbSelectEvents;
- req->deviceSpec = deviceSpec;
- req->affectWhich = (CARD16)affect;
- req->clear = affect&(~selectAll);
- req->selectAll = affect&selectAll;
- if (affect&XkbMapNotifyMask) {
- req->affectMap= XkbAllMapComponentsMask;
- /* the implicit support needs the client info */
- /* even if the client itself doesn't want it */
- if (selectAll&XkbMapNotifyMask)
- req->map= XkbAllMapEventsMask;
- else req->map= XkbAllClientInfoMask;
- if (selectAll&XkbMapNotifyMask)
- xkbi->selected_map_details= XkbAllMapEventsMask;
- else xkbi->selected_map_details= 0;
- }
- if (affect&XkbNewKeyboardNotifyMask) {
- if (selectAll&XkbNewKeyboardNotifyMask)
- xkbi->selected_nkn_details= XkbAllNewKeyboardEventsMask;
- else xkbi->selected_nkn_details= 0;
- if (!(xkbi->xlib_ctrls&XkbLC_IgnoreNewKeyboards)) {
- /* we want it, even if the client doesn't. Don't mess */
- /* around with details -- ask for all of them and throw */
- /* away the ones we don't need */
- req->selectAll|= XkbNewKeyboardNotifyMask;
- }
- }
- UnlockDisplay(dpy);
- SyncHandle();
- return True;
-}
-
-Bool
-XkbSelectEventDetails( Display * dpy,
- unsigned deviceSpec,
- unsigned eventType,
- unsigned long int affect,
- unsigned long int details)
-{
- register xkbSelectEventsReq *req;
- XkbInfoPtr xkbi;
- int size = 0;
- char *out;
- union {
- CARD8 *c8;
- CARD16 *c16;
- CARD32 *c32;
- } u;
-
- if ((dpy->flags & XlibDisplayNoXkb) ||
- (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
- return False;
- LockDisplay(dpy);
- xkbi = dpy->xkb_info;
- if (affect&details) xkbi->selected_events|= (1<<eventType);
- else xkbi->selected_events&= ~(1<<eventType);
- GetReq(kbSelectEvents, req);
- req->reqType = xkbi->codes->major_opcode;
- req->xkbReqType = X_kbSelectEvents;
- req->deviceSpec = deviceSpec;
- req->clear= req->selectAll= 0;
- if (eventType==XkbMapNotify) {
- /* we need all of the client info, even if the application */
- /* doesn't. Make sure that we always request the stuff */
- /* that the implicit support needs, and just filter out anything */
- /* the client doesn't want later */
- req->affectWhich = 0;
- req->selectAll = 0;
- req->clear = 0;
- req->affectMap = (CARD16)affect;
- req->map = (CARD16)details|(XkbAllClientInfoMask&affect);
- req->affectWhich = XkbMapNotifyMask;
- xkbi->selected_map_details&= ~affect;
- xkbi->selected_map_details|= (details&affect);
- }
- else {
- req->affectMap = req->map = 0;
- req->affectWhich= (1<<eventType);
- switch (eventType) {
- case XkbNewKeyboardNotify:
- xkbi->selected_nkn_details&= ~affect;
- xkbi->selected_nkn_details|= (details&affect);
- if (!(xkbi->xlib_ctrls&XkbLC_IgnoreNewKeyboards))
- details= (affect&XkbAllNewKeyboardEventsMask);
- case XkbStateNotify:
- case XkbNamesNotify:
- case XkbAccessXNotify:
- case XkbExtensionDeviceNotify:
- size= 2;
- req->length+= 1;
- break;
- case XkbControlsNotify:
- case XkbIndicatorStateNotify:
- case XkbIndicatorMapNotify:
- size= 4;
- req->length+= 2;
- break;
- case XkbBellNotify:
- case XkbActionMessage:
- case XkbCompatMapNotify:
- size= 1;
- req->length+= 1;
- break;
- }
- BufAlloc(char *,out,(((size*2)+(unsigned)3)/4)*4);
- u.c8= (CARD8 *)out;
- if (size==2) {
- u.c16[0]= (CARD16)affect;
- u.c16[1]= (CARD16)details;
- }
- else if (size==4) {
- u.c32[0]= (CARD32)affect;
- u.c32[1]= (CARD32)details;
- }
- else {
- u.c8[0]= (CARD8)affect;
- u.c8[1]= (CARD8)details;
- }
- }
- UnlockDisplay(dpy);
- SyncHandle();
- return True;
-}
-
-Bool
-XkbLockModifiers( Display * dpy,
- unsigned int deviceSpec,
- unsigned int affect,
- unsigned int values)
-{
- register xkbLatchLockStateReq *req;
- XkbInfoPtr xkbi;
-
- if ((dpy->flags & XlibDisplayNoXkb) ||
- (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
- return False;
- LockDisplay(dpy);
- xkbi = dpy->xkb_info;
- GetReq(kbLatchLockState, req);
- req->reqType = xkbi->codes->major_opcode;
- req->xkbReqType = X_kbLatchLockState;
- req->deviceSpec = deviceSpec;
- req->affectModLocks= affect;
- req->modLocks = values;
- req->lockGroup = False;
- req->groupLock = 0;
-
- req->affectModLatches = req->modLatches = 0;
- req->latchGroup = False;
- req->groupLatch = 0;
- UnlockDisplay(dpy);
- SyncHandle();
- return True;
-}
-
-Bool
-XkbLatchModifiers( Display * dpy,
- unsigned int deviceSpec,
- unsigned int affect,
- unsigned int values)
-{
- register xkbLatchLockStateReq *req;
- XkbInfoPtr xkbi;
-
- if ((dpy->flags & XlibDisplayNoXkb) ||
- (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
- return False;
- LockDisplay(dpy);
- xkbi = dpy->xkb_info;
- GetReq(kbLatchLockState, req);
- req->reqType = xkbi->codes->major_opcode;
- req->xkbReqType = X_kbLatchLockState;
- req->deviceSpec = deviceSpec;
-
- req->affectModLatches= affect;
- req->modLatches = values;
- req->latchGroup = False;
- req->groupLatch = 0;
-
- req->affectModLocks = req->modLocks = 0;
- req->lockGroup = False;
- req->groupLock = 0;
-
- UnlockDisplay(dpy);
- SyncHandle();
- return True;
-}
-
-Bool
-XkbLockGroup(Display *dpy,unsigned int deviceSpec,unsigned int group)
-{
- register xkbLatchLockStateReq *req;
- XkbInfoPtr xkbi;
-
- if ((dpy->flags & XlibDisplayNoXkb) ||
- (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
- return False;
- LockDisplay(dpy);
- xkbi = dpy->xkb_info;
- GetReq(kbLatchLockState, req);
- req->reqType = xkbi->codes->major_opcode;
- req->xkbReqType = X_kbLatchLockState;
- req->deviceSpec = deviceSpec;
- req->affectModLocks= 0;
- req->modLocks = 0;
- req->lockGroup = True;
- req->groupLock = group;
-
- req->affectModLatches = req->modLatches = 0;
- req->latchGroup = False;
- req->groupLatch = 0;
- UnlockDisplay(dpy);
- SyncHandle();
- return True;
-}
-
-Bool
-XkbLatchGroup(Display *dpy,unsigned int deviceSpec,unsigned int group)
-{
- register xkbLatchLockStateReq *req;
- XkbInfoPtr xkbi;
-
- if ((dpy->flags & XlibDisplayNoXkb) ||
- (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
- return False;
- LockDisplay(dpy);
- xkbi = dpy->xkb_info;
- GetReq(kbLatchLockState, req);
- req->reqType = xkbi->codes->major_opcode;
- req->xkbReqType = X_kbLatchLockState;
- req->deviceSpec = deviceSpec;
-
- req->affectModLatches= 0;
- req->modLatches = 0;
- req->latchGroup = True;
- req->groupLatch = group;
-
- req->affectModLocks = req->modLocks = 0;
- req->lockGroup = False;
- req->groupLock = 0;
-
- UnlockDisplay(dpy);
- SyncHandle();
- return True;
-}
-
-unsigned
-XkbSetXlibControls(Display *dpy,unsigned affect,unsigned values)
-{
- if (!dpy->xkb_info)
- XkbUseExtension(dpy,NULL,NULL);
- if (!dpy->xkb_info)
- return 0;
- affect&= XkbLC_AllControls;
- dpy->xkb_info->xlib_ctrls&= ~affect;
- dpy->xkb_info->xlib_ctrls|= (affect&values);
- return dpy->xkb_info->xlib_ctrls;
-}
-
-unsigned
-XkbGetXlibControls(Display *dpy)
-{
- if (!dpy->xkb_info)
- XkbUseExtension(dpy,NULL,NULL);
- if (!dpy->xkb_info)
- return 0;
- return dpy->xkb_info->xlib_ctrls;
-}
-
-unsigned int
-XkbXlibControlsImplemented(void)
-{
-#ifdef __sgi
- return XkbLC_AllControls;
-#else
- return XkbLC_AllControls&~XkbLC_AllComposeControls;
-#endif
-}
-
-Bool
-XkbSetDebuggingFlags( Display * dpy,
- unsigned int mask,
- unsigned int flags,
- char * msg,
- unsigned int ctrls_mask,
- unsigned int ctrls,
- unsigned int * rtrn_flags,
- unsigned int * rtrn_ctrls)
-{
- register xkbSetDebuggingFlagsReq *req;
- xkbSetDebuggingFlagsReply rep;
- XkbInfoPtr xkbi;
-
- if ((dpy->flags & XlibDisplayNoXkb) ||
- (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
- return False;
- LockDisplay(dpy);
- xkbi = dpy->xkb_info;
- GetReq(kbSetDebuggingFlags, req);
- req->reqType= xkbi->codes->major_opcode;
- req->xkbReqType= X_kbSetDebuggingFlags;
- req->affectFlags= mask;
- req->flags= flags;
- req->affectCtrls= ctrls_mask;
- req->ctrls= ctrls;
-
- if (msg) {
- char *out;
- req->msgLength= (unsigned short)strlen(msg)+1;
- req->length+= (req->msgLength+(unsigned)3)>>2;
- BufAlloc(char *,out,((req->msgLength+(unsigned)3)/4)*4);
- memcpy(out,msg,req->msgLength);
- }
- else req->msgLength= 0;
- if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
- UnlockDisplay(dpy);
- SyncHandle();
- return False;
- }
- if (rtrn_flags)
- *rtrn_flags= rep.currentFlags;
- if (rtrn_ctrls)
- *rtrn_ctrls= rep.currentCtrls;
- UnlockDisplay(dpy);
- SyncHandle();
- return True;
-}
-
-Bool
-XkbComputeEffectiveMap( XkbDescPtr xkb,
- XkbKeyTypePtr type,
- unsigned char * map_rtrn)
-{
-register int i;
-unsigned tmp;
-XkbKTMapEntryPtr entry = NULL;
-
- if ((!xkb)||(!type)||(!xkb->server))
- return False;
-
- if (type->mods.vmods!=0) {
- if (!XkbVirtualModsToReal(xkb,type->mods.vmods,&tmp))
- return False;
-
- type->mods.mask= tmp|type->mods.real_mods;
- entry= type->map;
- for (i=0;i<type->map_count;i++,entry++) {
- tmp= 0;
- if (entry->mods.vmods!=0) {
- if (!XkbVirtualModsToReal(xkb,entry->mods.vmods,&tmp))
- return False;
- if (tmp==0) {
- entry->active= False;
- continue;
- }
- }
- entry->active= True;
- entry->mods.mask= (entry->mods.real_mods|tmp)&type->mods.mask;
- }
- }
- else {
- type->mods.mask= type->mods.real_mods;
- }
- if (map_rtrn!=NULL) {
- bzero(map_rtrn,type->mods.mask+1);
- for (i=0;i<type->map_count;i++) {
- if (entry->active) {
- map_rtrn[type->map[i].mods.mask]= type->map[i].level;
- }
- }
- }
- return True;
-}
-
-Status
-XkbGetState(Display *dpy,unsigned deviceSpec,XkbStatePtr rtrn)
-{
- register xkbGetStateReq *req;
- xkbGetStateReply rep;
- XkbInfoPtr xkbi;
-
- if ((dpy->flags & XlibDisplayNoXkb) ||
- (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
- return BadAccess;
- LockDisplay(dpy);
- xkbi = dpy->xkb_info;
- GetReq(kbGetState, req);
- req->reqType = xkbi->codes->major_opcode;
- req->xkbReqType = X_kbGetState;
- req->deviceSpec = deviceSpec;
- if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
- UnlockDisplay(dpy);
- SyncHandle();
- return BadImplementation;
- }
- rtrn->mods= rep.mods;
- rtrn->base_mods= rep.baseMods;
- rtrn->latched_mods= rep.latchedMods;
- rtrn->locked_mods= rep.lockedMods;
- rtrn->group= rep.group;
- rtrn->base_group= rep.baseGroup;
- rtrn->latched_group= rep.latchedGroup;
- rtrn->locked_group= rep.lockedGroup;
- rtrn->compat_state= rep.compatState;
- rtrn->grab_mods= rep.grabMods;
- rtrn->compat_grab_mods= rep.compatGrabMods;
- rtrn->lookup_mods= rep.lookupMods;
- rtrn->compat_lookup_mods= rep.compatLookupMods;
- rtrn->ptr_buttons= rep.ptrBtnState;
- UnlockDisplay(dpy);
- SyncHandle();
- return Success;
-}
-
-Bool
-XkbSetDetectableAutoRepeat(Display *dpy,Bool detectable,Bool *supported)
-{
-register xkbPerClientFlagsReq * req;
-xkbPerClientFlagsReply rep;
-XkbInfoPtr xkbi;
-
- if ((dpy->flags & XlibDisplayNoXkb) ||
- (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
- return False;
- LockDisplay(dpy);
- xkbi = dpy->xkb_info;
- GetReq(kbPerClientFlags, req);
- req->reqType = xkbi->codes->major_opcode;
- req->xkbReqType = X_kbPerClientFlags;
- req->deviceSpec = XkbUseCoreKbd;
- req->change = XkbPCF_DetectableAutoRepeatMask;
- if (detectable)
- req->value = XkbPCF_DetectableAutoRepeatMask;
- else req->value = 0;
- req->ctrlsToChange = req->autoCtrls= req->autoCtrlValues= 0;
- if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
- UnlockDisplay(dpy);
- SyncHandle();
- return False;
- }
- UnlockDisplay(dpy);
- SyncHandle();
- if (supported!=NULL)
- *supported= ((rep.supported&XkbPCF_DetectableAutoRepeatMask)!=0);
- return ((rep.value&XkbPCF_DetectableAutoRepeatMask)!=0);
-}
-
-Bool
-XkbGetDetectableAutoRepeat(Display *dpy,Bool *supported)
-{
-register xkbPerClientFlagsReq * req;
-xkbPerClientFlagsReply rep;
-XkbInfoPtr xkbi;
-
- if ((dpy->flags & XlibDisplayNoXkb) ||
- (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
- return False;
- LockDisplay(dpy);
- xkbi = dpy->xkb_info;
- GetReq(kbPerClientFlags, req);
- req->reqType = xkbi->codes->major_opcode;
- req->xkbReqType = X_kbPerClientFlags;
- req->deviceSpec = XkbUseCoreKbd;
- req->change = 0;
- req->value = 0;
- req->ctrlsToChange = req->autoCtrls= req->autoCtrlValues= 0;
- if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
- UnlockDisplay(dpy);
- SyncHandle();
- return False;
- }
- UnlockDisplay(dpy);
- SyncHandle();
- if (supported!=NULL)
- *supported= ((rep.supported&XkbPCF_DetectableAutoRepeatMask)!=0);
- return ((rep.value&XkbPCF_DetectableAutoRepeatMask)!=0);
-}
-
-Bool
-XkbSetAutoResetControls( Display * dpy,
- unsigned changes,
- unsigned * auto_ctrls,
- unsigned * auto_values)
-{
-register xkbPerClientFlagsReq * req;
-xkbPerClientFlagsReply rep;
-XkbInfoPtr xkbi;
-
- if ((dpy->flags & XlibDisplayNoXkb) ||
- (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
- return False;
- LockDisplay(dpy);
- xkbi = dpy->xkb_info;
- GetReq(kbPerClientFlags, req);
- req->reqType = xkbi->codes->major_opcode;
- req->xkbReqType = X_kbPerClientFlags;
- req->change = XkbPCF_AutoResetControlsMask;
- req->deviceSpec = XkbUseCoreKbd;
- req->value = XkbPCF_AutoResetControlsMask;
- req->ctrlsToChange= changes;
- req->autoCtrls= *auto_ctrls;
- req->autoCtrlValues= *auto_values;
- if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
- UnlockDisplay(dpy);
- SyncHandle();
- return False;
- }
- UnlockDisplay(dpy);
- SyncHandle();
- *auto_ctrls= rep.autoCtrls;
- *auto_values= rep.autoCtrlValues;
- return ((rep.value&XkbPCF_AutoResetControlsMask)!=0);
-}
-
-Bool
-XkbGetAutoResetControls( Display * dpy,
- unsigned * auto_ctrls,
- unsigned * auto_ctrl_values)
-{
-register xkbPerClientFlagsReq * req;
-xkbPerClientFlagsReply rep;
-XkbInfoPtr xkbi;
-
- if ((dpy->flags & XlibDisplayNoXkb) ||
- (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
- return False;
- LockDisplay(dpy);
- xkbi = dpy->xkb_info;
- GetReq(kbPerClientFlags, req);
- req->reqType = xkbi->codes->major_opcode;
- req->xkbReqType = X_kbPerClientFlags;
- req->deviceSpec = XkbUseCoreKbd;
- req->change = 0;
- req->value = 0;
- req->ctrlsToChange = req->autoCtrls= req->autoCtrlValues= 0;
- if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
- UnlockDisplay(dpy);
- SyncHandle();
- return False;
- }
- UnlockDisplay(dpy);
- SyncHandle();
- if (auto_ctrls)
- *auto_ctrls= rep.autoCtrls;
- if (auto_ctrl_values)
- *auto_ctrl_values= rep.autoCtrlValues;
- return ((rep.value&XkbPCF_AutoResetControlsMask)!=0);
-}
-
-Bool
-XkbSetPerClientControls( Display * dpy,
- unsigned change,
- unsigned * values)
-{
-register xkbPerClientFlagsReq * req;
-xkbPerClientFlagsReply rep;
-XkbInfoPtr xkbi;
-unsigned value_hold = *values;
-
- if ((dpy->flags & XlibDisplayNoXkb) ||
- (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)) ||
- (change & ~(XkbPCF_GrabsUseXKBStateMask|XkbPCF_LookupStateWhenGrabbed|XkbPCF_SendEventUsesXKBState)))
- return False;
- LockDisplay(dpy);
- xkbi = dpy->xkb_info;
- GetReq(kbPerClientFlags, req);
- req->reqType = xkbi->codes->major_opcode;
- req->xkbReqType = X_kbPerClientFlags;
- req->change = change;
- req->deviceSpec = XkbUseCoreKbd;
- req->value = *values;
- req->ctrlsToChange = req->autoCtrls = req->autoCtrlValues= 0;
- if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
- UnlockDisplay(dpy);
- SyncHandle();
- return False;
- }
- UnlockDisplay(dpy);
- SyncHandle();
- *values = rep.value;
- return ((rep.value&value_hold)!=0);
-}
-
-Bool
-XkbGetPerClientControls( Display * dpy,
- unsigned * ctrls)
-{
-register xkbPerClientFlagsReq * req;
-xkbPerClientFlagsReply rep;
-XkbInfoPtr xkbi;
-
- if ((dpy->flags & XlibDisplayNoXkb) ||
- (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)) ||
- (*ctrls & ~(XkbPCF_GrabsUseXKBStateMask|XkbPCF_LookupStateWhenGrabbed|XkbPCF_SendEventUsesXKBState)))
- return False;
- LockDisplay(dpy);
- xkbi = dpy->xkb_info;
- GetReq(kbPerClientFlags, req);
- req->reqType = xkbi->codes->major_opcode;
- req->xkbReqType = X_kbPerClientFlags;
- req->deviceSpec = XkbUseCoreKbd;
- req->change = 0;
- req->value = 0;
- req->ctrlsToChange = req->autoCtrls= req->autoCtrlValues= 0;
- if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
- UnlockDisplay(dpy);
- SyncHandle();
- return False;
- }
- UnlockDisplay(dpy);
- SyncHandle();
- if (ctrls)
- *ctrls= (rep.value & (XkbPCF_GrabsUseXKBStateMask |
- XkbPCF_LookupStateWhenGrabbed |
- XkbPCF_SendEventUsesXKBState));
- return (True);
-}
-
-Display *
-XkbOpenDisplay( char * name,
- int * ev_rtrn,
- int * err_rtrn,
- int * major_rtrn,
- int * minor_rtrn,
- int * reason)
-{
- Display* dpy;
- int major_num,minor_num;
-
- if ((major_rtrn!=NULL) && (minor_rtrn!=NULL)) {
- if (!XkbLibraryVersion(major_rtrn,minor_rtrn)) {
- if (reason!=NULL)
- *reason= XkbOD_BadLibraryVersion;
- return NULL;
- }
- }
- else {
- major_num= XkbMajorVersion;
- minor_num= XkbMinorVersion;
- major_rtrn= &major_num;
- minor_rtrn= &minor_num;
- }
- dpy= XOpenDisplay(name);
- if (dpy==NULL) {
- if (reason!=NULL)
- *reason= XkbOD_ConnectionRefused;
- return NULL;
- }
- if (!XkbQueryExtension(dpy,NULL,ev_rtrn,err_rtrn,major_rtrn,minor_rtrn)) {
- if (reason!=NULL) {
- if ((*major_rtrn!=0)||(*minor_rtrn!=0))
- *reason= XkbOD_BadServerVersion;
- else *reason= XkbOD_NonXkbServer;
- }
- XCloseDisplay(dpy);
- return NULL;
- }
- if (reason!=NULL)
- *reason= XkbOD_Success;
- return dpy;
-}
-
-void
-XkbSetAtomFuncs(XkbInternAtomFunc getAtom,XkbGetAtomNameFunc getName)
-{
- _XkbInternAtomFunc= (getAtom?getAtom:XInternAtom);
- _XkbGetAtomNameFunc= (getName?getName:XGetAtomName);
- return;
-}
+/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +Permission to use, copy, modify, and distribute this +software and its documentation for any purpose and without +fee is hereby granted, provided that the above copyright +notice appear in all copies and that both that copyright +notice and this permission notice appear in supporting +documentation, and that the name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL +DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH +THE USE OR PERFORMANCE OF THIS SOFTWARE. + +********************************************************/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include "Xlibint.h" +#include <X11/extensions/XKBproto.h> +#include "XKBlibint.h" + +XkbInternAtomFunc _XkbInternAtomFunc= XInternAtom; +XkbGetAtomNameFunc _XkbGetAtomNameFunc= XGetAtomName; + +Bool +XkbQueryExtension( Display *dpy, + int * opcodeReturn, + int * eventBaseReturn, + int * errorBaseReturn, + int * majorReturn, + int * minorReturn) +{ + if (!XkbUseExtension(dpy,majorReturn,minorReturn)) + return False; + if (opcodeReturn) + *opcodeReturn = dpy->xkb_info->codes->major_opcode; + if (eventBaseReturn) + *eventBaseReturn = dpy->xkb_info->codes->first_event; + if (errorBaseReturn) + *errorBaseReturn = dpy->xkb_info->codes->first_error; + if (majorReturn) + *majorReturn = dpy->xkb_info->srv_major; + if (minorReturn) + *minorReturn = dpy->xkb_info->srv_minor; + return True; +} + +Bool +XkbLibraryVersion(int *libMajorRtrn,int *libMinorRtrn) +{ +int supported; + + if (*libMajorRtrn != XkbMajorVersion) { + /* version 0.65 is (almost) compatible with 1.00 */ + if ((XkbMajorVersion==1)&&(((*libMajorRtrn)==0)&&((*libMinorRtrn)==65))) + supported= True; + else supported= False; + } + else { + supported = True; + } + + *libMajorRtrn = XkbMajorVersion; + *libMinorRtrn = XkbMinorVersion; + return supported; +} + +Bool +XkbSelectEvents( Display * dpy, + unsigned int deviceSpec, + unsigned int affect, + unsigned int selectAll) +{ + register xkbSelectEventsReq *req; + XkbInfoPtr xkbi; + + if ((dpy->flags & XlibDisplayNoXkb) || + (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL))) + return False; + LockDisplay(dpy); + xkbi = dpy->xkb_info; + xkbi->selected_events&= ~affect; + xkbi->selected_events|= (affect&selectAll); + GetReq(kbSelectEvents, req); + req->reqType = xkbi->codes->major_opcode; + req->xkbReqType = X_kbSelectEvents; + req->deviceSpec = deviceSpec; + req->affectWhich = (CARD16)affect; + req->clear = affect&(~selectAll); + req->selectAll = affect&selectAll; + if (affect&XkbMapNotifyMask) { + req->affectMap= XkbAllMapComponentsMask; + /* the implicit support needs the client info */ + /* even if the client itself doesn't want it */ + if (selectAll&XkbMapNotifyMask) + req->map= XkbAllMapEventsMask; + else req->map= XkbAllClientInfoMask; + if (selectAll&XkbMapNotifyMask) + xkbi->selected_map_details= XkbAllMapEventsMask; + else xkbi->selected_map_details= 0; + } + if (affect&XkbNewKeyboardNotifyMask) { + if (selectAll&XkbNewKeyboardNotifyMask) + xkbi->selected_nkn_details= XkbAllNewKeyboardEventsMask; + else xkbi->selected_nkn_details= 0; + if (!(xkbi->xlib_ctrls&XkbLC_IgnoreNewKeyboards)) { + /* we want it, even if the client doesn't. Don't mess */ + /* around with details -- ask for all of them and throw */ + /* away the ones we don't need */ + req->selectAll|= XkbNewKeyboardNotifyMask; + } + } + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool +XkbSelectEventDetails( Display * dpy, + unsigned deviceSpec, + unsigned eventType, + unsigned long int affect, + unsigned long int details) +{ + register xkbSelectEventsReq *req; + XkbInfoPtr xkbi; + int size = 0; + char *out; + union { + CARD8 *c8; + CARD16 *c16; + CARD32 *c32; + } u; + + if ((dpy->flags & XlibDisplayNoXkb) || + (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL))) + return False; + LockDisplay(dpy); + xkbi = dpy->xkb_info; + if (affect&details) xkbi->selected_events|= (1<<eventType); + else xkbi->selected_events&= ~(1<<eventType); + GetReq(kbSelectEvents, req); + req->reqType = xkbi->codes->major_opcode; + req->xkbReqType = X_kbSelectEvents; + req->deviceSpec = deviceSpec; + req->clear= req->selectAll= 0; + if (eventType==XkbMapNotify) { + /* we need all of the client info, even if the application */ + /* doesn't. Make sure that we always request the stuff */ + /* that the implicit support needs, and just filter out anything */ + /* the client doesn't want later */ + req->affectWhich = 0; + req->selectAll = 0; + req->clear = 0; + req->affectMap = (CARD16)affect; + req->map = (CARD16)details|(XkbAllClientInfoMask&affect); + req->affectWhich = XkbMapNotifyMask; + xkbi->selected_map_details&= ~affect; + xkbi->selected_map_details|= (details&affect); + } + else { + req->affectMap = req->map = 0; + req->affectWhich= (1<<eventType); + switch (eventType) { + case XkbNewKeyboardNotify: + xkbi->selected_nkn_details&= ~affect; + xkbi->selected_nkn_details|= (details&affect); + if (!(xkbi->xlib_ctrls&XkbLC_IgnoreNewKeyboards)) + details= (affect&XkbAllNewKeyboardEventsMask); + case XkbStateNotify: + case XkbNamesNotify: + case XkbAccessXNotify: + case XkbExtensionDeviceNotify: + size= 2; + req->length+= 1; + break; + case XkbControlsNotify: + case XkbIndicatorStateNotify: + case XkbIndicatorMapNotify: + size= 4; + req->length+= 2; + break; + case XkbBellNotify: + case XkbActionMessage: + case XkbCompatMapNotify: + size= 1; + req->length+= 1; + break; + } + BufAlloc(char *,out,(((size*2)+(unsigned)3)/4)*4); + u.c8= (CARD8 *)out; + if (size==2) { + u.c16[0]= (CARD16)affect; + u.c16[1]= (CARD16)details; + } + else if (size==4) { + u.c32[0]= (CARD32)affect; + u.c32[1]= (CARD32)details; + } + else { + u.c8[0]= (CARD8)affect; + u.c8[1]= (CARD8)details; + } + } + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool +XkbLockModifiers( Display * dpy, + unsigned int deviceSpec, + unsigned int affect, + unsigned int values) +{ + register xkbLatchLockStateReq *req; + XkbInfoPtr xkbi; + + if ((dpy->flags & XlibDisplayNoXkb) || + (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL))) + return False; + LockDisplay(dpy); + xkbi = dpy->xkb_info; + GetReq(kbLatchLockState, req); + req->reqType = xkbi->codes->major_opcode; + req->xkbReqType = X_kbLatchLockState; + req->deviceSpec = deviceSpec; + req->affectModLocks= affect; + req->modLocks = values; + req->lockGroup = False; + req->groupLock = 0; + + req->affectModLatches = req->modLatches = 0; + req->latchGroup = False; + req->groupLatch = 0; + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool +XkbLatchModifiers( Display * dpy, + unsigned int deviceSpec, + unsigned int affect, + unsigned int values) +{ + register xkbLatchLockStateReq *req; + XkbInfoPtr xkbi; + + if ((dpy->flags & XlibDisplayNoXkb) || + (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL))) + return False; + LockDisplay(dpy); + xkbi = dpy->xkb_info; + GetReq(kbLatchLockState, req); + req->reqType = xkbi->codes->major_opcode; + req->xkbReqType = X_kbLatchLockState; + req->deviceSpec = deviceSpec; + + req->affectModLatches= affect; + req->modLatches = values; + req->latchGroup = False; + req->groupLatch = 0; + + req->affectModLocks = req->modLocks = 0; + req->lockGroup = False; + req->groupLock = 0; + + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool +XkbLockGroup(Display *dpy,unsigned int deviceSpec,unsigned int group) +{ + register xkbLatchLockStateReq *req; + XkbInfoPtr xkbi; + + if ((dpy->flags & XlibDisplayNoXkb) || + (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL))) + return False; + LockDisplay(dpy); + xkbi = dpy->xkb_info; + GetReq(kbLatchLockState, req); + req->reqType = xkbi->codes->major_opcode; + req->xkbReqType = X_kbLatchLockState; + req->deviceSpec = deviceSpec; + req->affectModLocks= 0; + req->modLocks = 0; + req->lockGroup = True; + req->groupLock = group; + + req->affectModLatches = req->modLatches = 0; + req->latchGroup = False; + req->groupLatch = 0; + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool +XkbLatchGroup(Display *dpy,unsigned int deviceSpec,unsigned int group) +{ + register xkbLatchLockStateReq *req; + XkbInfoPtr xkbi; + + if ((dpy->flags & XlibDisplayNoXkb) || + (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL))) + return False; + LockDisplay(dpy); + xkbi = dpy->xkb_info; + GetReq(kbLatchLockState, req); + req->reqType = xkbi->codes->major_opcode; + req->xkbReqType = X_kbLatchLockState; + req->deviceSpec = deviceSpec; + + req->affectModLatches= 0; + req->modLatches = 0; + req->latchGroup = True; + req->groupLatch = group; + + req->affectModLocks = req->modLocks = 0; + req->lockGroup = False; + req->groupLock = 0; + + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +unsigned +XkbSetXlibControls(Display *dpy,unsigned affect,unsigned values) +{ + if (!dpy->xkb_info) + XkbUseExtension(dpy,NULL,NULL); + if (!dpy->xkb_info) + return 0; + affect&= XkbLC_AllControls; + dpy->xkb_info->xlib_ctrls&= ~affect; + dpy->xkb_info->xlib_ctrls|= (affect&values); + return dpy->xkb_info->xlib_ctrls; +} + +unsigned +XkbGetXlibControls(Display *dpy) +{ + if (!dpy->xkb_info) + XkbUseExtension(dpy,NULL,NULL); + if (!dpy->xkb_info) + return 0; + return dpy->xkb_info->xlib_ctrls; +} + +unsigned int +XkbXlibControlsImplemented(void) +{ +#ifdef __sgi + return XkbLC_AllControls; +#else + return XkbLC_AllControls&~XkbLC_AllComposeControls; +#endif +} + +Bool +XkbSetDebuggingFlags( Display * dpy, + unsigned int mask, + unsigned int flags, + char * msg, + unsigned int ctrls_mask, + unsigned int ctrls, + unsigned int * rtrn_flags, + unsigned int * rtrn_ctrls) +{ + register xkbSetDebuggingFlagsReq *req; + xkbSetDebuggingFlagsReply rep; + XkbInfoPtr xkbi; + + if ((dpy->flags & XlibDisplayNoXkb) || + (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL))) + return False; + LockDisplay(dpy); + xkbi = dpy->xkb_info; + GetReq(kbSetDebuggingFlags, req); + req->reqType= xkbi->codes->major_opcode; + req->xkbReqType= X_kbSetDebuggingFlags; + req->affectFlags= mask; + req->flags= flags; + req->affectCtrls= ctrls_mask; + req->ctrls= ctrls; + + if (msg) { + char *out; + req->msgLength= (unsigned short)strlen(msg)+1; + req->length+= (req->msgLength+(unsigned)3)>>2; + BufAlloc(char *,out,((req->msgLength+(unsigned)3)/4)*4); + memcpy(out,msg,req->msgLength); + } + else req->msgLength= 0; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + if (rtrn_flags) + *rtrn_flags= rep.currentFlags; + if (rtrn_ctrls) + *rtrn_ctrls= rep.currentCtrls; + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool +XkbComputeEffectiveMap( XkbDescPtr xkb, + XkbKeyTypePtr type, + unsigned char * map_rtrn) +{ +register int i; +unsigned tmp; +XkbKTMapEntryPtr entry = NULL; + + if ((!xkb)||(!type)||(!xkb->server)) + return False; + + if (type->mods.vmods!=0) { + if (!XkbVirtualModsToReal(xkb,type->mods.vmods,&tmp)) + return False; + + type->mods.mask= tmp|type->mods.real_mods; + entry= type->map; + for (i=0;i<type->map_count;i++,entry++) { + tmp= 0; + if (entry->mods.vmods!=0) { + if (!XkbVirtualModsToReal(xkb,entry->mods.vmods,&tmp)) + return False; + if (tmp==0) { + entry->active= False; + continue; + } + } + entry->active= True; + entry->mods.mask= (entry->mods.real_mods|tmp)&type->mods.mask; + } + } + else { + type->mods.mask= type->mods.real_mods; + } + if (map_rtrn!=NULL) { + bzero(map_rtrn,type->mods.mask+1); + for (i=0;i<type->map_count;i++) { + if (entry && entry->active) { + map_rtrn[type->map[i].mods.mask]= type->map[i].level; + } + } + } + return True; +} + +Status +XkbGetState(Display *dpy,unsigned deviceSpec,XkbStatePtr rtrn) +{ + register xkbGetStateReq *req; + xkbGetStateReply rep; + XkbInfoPtr xkbi; + + if ((dpy->flags & XlibDisplayNoXkb) || + (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL))) + return BadAccess; + LockDisplay(dpy); + xkbi = dpy->xkb_info; + GetReq(kbGetState, req); + req->reqType = xkbi->codes->major_opcode; + req->xkbReqType = X_kbGetState; + req->deviceSpec = deviceSpec; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return BadImplementation; + } + rtrn->mods= rep.mods; + rtrn->base_mods= rep.baseMods; + rtrn->latched_mods= rep.latchedMods; + rtrn->locked_mods= rep.lockedMods; + rtrn->group= rep.group; + rtrn->base_group= rep.baseGroup; + rtrn->latched_group= rep.latchedGroup; + rtrn->locked_group= rep.lockedGroup; + rtrn->compat_state= rep.compatState; + rtrn->grab_mods= rep.grabMods; + rtrn->compat_grab_mods= rep.compatGrabMods; + rtrn->lookup_mods= rep.lookupMods; + rtrn->compat_lookup_mods= rep.compatLookupMods; + rtrn->ptr_buttons= rep.ptrBtnState; + UnlockDisplay(dpy); + SyncHandle(); + return Success; +} + +Bool +XkbSetDetectableAutoRepeat(Display *dpy,Bool detectable,Bool *supported) +{ +register xkbPerClientFlagsReq * req; +xkbPerClientFlagsReply rep; +XkbInfoPtr xkbi; + + if ((dpy->flags & XlibDisplayNoXkb) || + (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL))) + return False; + LockDisplay(dpy); + xkbi = dpy->xkb_info; + GetReq(kbPerClientFlags, req); + req->reqType = xkbi->codes->major_opcode; + req->xkbReqType = X_kbPerClientFlags; + req->deviceSpec = XkbUseCoreKbd; + req->change = XkbPCF_DetectableAutoRepeatMask; + if (detectable) + req->value = XkbPCF_DetectableAutoRepeatMask; + else req->value = 0; + req->ctrlsToChange = req->autoCtrls= req->autoCtrlValues= 0; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + UnlockDisplay(dpy); + SyncHandle(); + if (supported!=NULL) + *supported= ((rep.supported&XkbPCF_DetectableAutoRepeatMask)!=0); + return ((rep.value&XkbPCF_DetectableAutoRepeatMask)!=0); +} + +Bool +XkbGetDetectableAutoRepeat(Display *dpy,Bool *supported) +{ +register xkbPerClientFlagsReq * req; +xkbPerClientFlagsReply rep; +XkbInfoPtr xkbi; + + if ((dpy->flags & XlibDisplayNoXkb) || + (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL))) + return False; + LockDisplay(dpy); + xkbi = dpy->xkb_info; + GetReq(kbPerClientFlags, req); + req->reqType = xkbi->codes->major_opcode; + req->xkbReqType = X_kbPerClientFlags; + req->deviceSpec = XkbUseCoreKbd; + req->change = 0; + req->value = 0; + req->ctrlsToChange = req->autoCtrls= req->autoCtrlValues= 0; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + UnlockDisplay(dpy); + SyncHandle(); + if (supported!=NULL) + *supported= ((rep.supported&XkbPCF_DetectableAutoRepeatMask)!=0); + return ((rep.value&XkbPCF_DetectableAutoRepeatMask)!=0); +} + +Bool +XkbSetAutoResetControls( Display * dpy, + unsigned changes, + unsigned * auto_ctrls, + unsigned * auto_values) +{ +register xkbPerClientFlagsReq * req; +xkbPerClientFlagsReply rep; +XkbInfoPtr xkbi; + + if ((dpy->flags & XlibDisplayNoXkb) || + (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL))) + return False; + LockDisplay(dpy); + xkbi = dpy->xkb_info; + GetReq(kbPerClientFlags, req); + req->reqType = xkbi->codes->major_opcode; + req->xkbReqType = X_kbPerClientFlags; + req->change = XkbPCF_AutoResetControlsMask; + req->deviceSpec = XkbUseCoreKbd; + req->value = XkbPCF_AutoResetControlsMask; + req->ctrlsToChange= changes; + req->autoCtrls= *auto_ctrls; + req->autoCtrlValues= *auto_values; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + UnlockDisplay(dpy); + SyncHandle(); + *auto_ctrls= rep.autoCtrls; + *auto_values= rep.autoCtrlValues; + return ((rep.value&XkbPCF_AutoResetControlsMask)!=0); +} + +Bool +XkbGetAutoResetControls( Display * dpy, + unsigned * auto_ctrls, + unsigned * auto_ctrl_values) +{ +register xkbPerClientFlagsReq * req; +xkbPerClientFlagsReply rep; +XkbInfoPtr xkbi; + + if ((dpy->flags & XlibDisplayNoXkb) || + (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL))) + return False; + LockDisplay(dpy); + xkbi = dpy->xkb_info; + GetReq(kbPerClientFlags, req); + req->reqType = xkbi->codes->major_opcode; + req->xkbReqType = X_kbPerClientFlags; + req->deviceSpec = XkbUseCoreKbd; + req->change = 0; + req->value = 0; + req->ctrlsToChange = req->autoCtrls= req->autoCtrlValues= 0; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + UnlockDisplay(dpy); + SyncHandle(); + if (auto_ctrls) + *auto_ctrls= rep.autoCtrls; + if (auto_ctrl_values) + *auto_ctrl_values= rep.autoCtrlValues; + return ((rep.value&XkbPCF_AutoResetControlsMask)!=0); +} + +Bool +XkbSetPerClientControls( Display * dpy, + unsigned change, + unsigned * values) +{ +register xkbPerClientFlagsReq * req; +xkbPerClientFlagsReply rep; +XkbInfoPtr xkbi; +unsigned value_hold = *values; + + if ((dpy->flags & XlibDisplayNoXkb) || + (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)) || + (change & ~(XkbPCF_GrabsUseXKBStateMask|XkbPCF_LookupStateWhenGrabbed|XkbPCF_SendEventUsesXKBState))) + return False; + LockDisplay(dpy); + xkbi = dpy->xkb_info; + GetReq(kbPerClientFlags, req); + req->reqType = xkbi->codes->major_opcode; + req->xkbReqType = X_kbPerClientFlags; + req->change = change; + req->deviceSpec = XkbUseCoreKbd; + req->value = *values; + req->ctrlsToChange = req->autoCtrls = req->autoCtrlValues= 0; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + UnlockDisplay(dpy); + SyncHandle(); + *values = rep.value; + return ((rep.value&value_hold)!=0); +} + +Bool +XkbGetPerClientControls( Display * dpy, + unsigned * ctrls) +{ +register xkbPerClientFlagsReq * req; +xkbPerClientFlagsReply rep; +XkbInfoPtr xkbi; + + if ((dpy->flags & XlibDisplayNoXkb) || + (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)) || + (*ctrls & ~(XkbPCF_GrabsUseXKBStateMask|XkbPCF_LookupStateWhenGrabbed|XkbPCF_SendEventUsesXKBState))) + return False; + LockDisplay(dpy); + xkbi = dpy->xkb_info; + GetReq(kbPerClientFlags, req); + req->reqType = xkbi->codes->major_opcode; + req->xkbReqType = X_kbPerClientFlags; + req->deviceSpec = XkbUseCoreKbd; + req->change = 0; + req->value = 0; + req->ctrlsToChange = req->autoCtrls= req->autoCtrlValues= 0; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + UnlockDisplay(dpy); + SyncHandle(); + if (ctrls) + *ctrls= (rep.value & (XkbPCF_GrabsUseXKBStateMask | + XkbPCF_LookupStateWhenGrabbed | + XkbPCF_SendEventUsesXKBState)); + return (True); +} + +Display * +XkbOpenDisplay( char * name, + int * ev_rtrn, + int * err_rtrn, + int * major_rtrn, + int * minor_rtrn, + int * reason) +{ + Display* dpy; + int major_num,minor_num; + + if ((major_rtrn!=NULL) && (minor_rtrn!=NULL)) { + if (!XkbLibraryVersion(major_rtrn,minor_rtrn)) { + if (reason!=NULL) + *reason= XkbOD_BadLibraryVersion; + return NULL; + } + } + else { + major_num= XkbMajorVersion; + minor_num= XkbMinorVersion; + major_rtrn= &major_num; + minor_rtrn= &minor_num; + } + dpy= XOpenDisplay(name); + if (dpy==NULL) { + if (reason!=NULL) + *reason= XkbOD_ConnectionRefused; + return NULL; + } + if (!XkbQueryExtension(dpy,NULL,ev_rtrn,err_rtrn,major_rtrn,minor_rtrn)) { + if (reason!=NULL) { + if ((*major_rtrn!=0)||(*minor_rtrn!=0)) + *reason= XkbOD_BadServerVersion; + else *reason= XkbOD_NonXkbServer; + } + XCloseDisplay(dpy); + return NULL; + } + if (reason!=NULL) + *reason= XkbOD_Success; + return dpy; +} + +void +XkbSetAtomFuncs(XkbInternAtomFunc getAtom,XkbGetAtomNameFunc getName) +{ + _XkbInternAtomFunc= (getAtom?getAtom:XInternAtom); + _XkbGetAtomNameFunc= (getName?getName:XGetAtomName); + return; +} diff --git a/libX11/src/xkb/XKBList.c b/libX11/src/xkb/XKBList.c index 1afe3685f..8f245f245 100644 --- a/libX11/src/xkb/XKBList.c +++ b/libX11/src/xkb/XKBList.c @@ -1,247 +1,249 @@ -/************************************************************
-Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc.
-
-Permission to use, copy, modify, and distribute this
-software and its documentation for any purpose and without
-fee is hereby granted, provided that the above copyright
-notice appear in all copies and that both that copyright
-notice and this permission notice appear in supporting
-documentation, and that the name of Silicon Graphics not be
-used in advertising or publicity pertaining to distribution
-of the software without specific prior written permission.
-Silicon Graphics makes no representation about the suitability
-of this software for any purpose. It is provided "as is"
-without any express or implied warranty.
-
-SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
-SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
-GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
-DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
-DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
-THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-********************************************************/
-
-#define NEED_MAP_READERS
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include "Xlibint.h"
-#include <X11/extensions/XKBproto.h>
-#include "XKBlibint.h"
-
-/***====================================================================***/
-
-static void
-_FreeComponentNames(int num,XkbComponentNamePtr names)
-{
-int i;
-XkbComponentNamePtr tmp;
-
- if ((num<1)||(names==NULL))
- return;
- for (i=0,tmp=names;i<num;i++,tmp++) {
- if (tmp->name) {
- _XkbFree(tmp->name);
- tmp->name= NULL;
- }
- }
- _XkbFree(names);
- return;
-}
-
-/***====================================================================***/
-
-static XkbComponentNamePtr
-_ReadListing(XkbReadBufferPtr buf,int count,Status *status_rtrn)
-{
-XkbComponentNamePtr first,this;
-register int i;
-CARD16 * flags;
-int slen,wlen;
-char * str;
-
- if (count<1)
- return NULL;
- first= _XkbTypedCalloc(count,XkbComponentNameRec);
- if (!first)
- return NULL;
- for (this=first,i=0;i<count;i++,this++) {
- flags= (CARD16 *)_XkbGetReadBufferPtr(buf,2*sizeof(CARD16));
- if (!flags)
- goto BAILOUT;
- this->flags= flags[0];
- slen= flags[1];
- wlen= ((slen+1)/2)*2; /* pad to 2 byte boundary */
- this->name= _XkbTypedCalloc(slen+1,char);
- if (!this->name)
- goto BAILOUT;
- str= (char *)_XkbGetReadBufferPtr(buf,wlen);
- memcpy(this->name,str,slen);
- }
- return first;
-BAILOUT:
- *status_rtrn= BadAlloc;
- _FreeComponentNames(i,first);
- return NULL;
-}
-
-/***====================================================================***/
-
-XkbComponentListPtr
-XkbListComponents( Display * dpy,
- unsigned deviceSpec,
- XkbComponentNamesPtr ptrns,
- int * max_inout)
-{
-register xkbListComponentsReq* req;
-xkbListComponentsReply rep;
-XkbInfoPtr xkbi;
-XkbComponentListPtr list;
-XkbReadBufferRec buf;
-int left;
-char * str;
-int extraLen,len,mapLen,codesLen,typesLen,compatLen,symsLen,geomLen;
-
- if ( (dpy==NULL) || (dpy->flags & XlibDisplayNoXkb) ||
- (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)) ||
- (ptrns==NULL) || (max_inout==NULL))
- return NULL;
-
- xkbi= dpy->xkb_info;
- LockDisplay(dpy);
- GetReq(kbListComponents, req);
- req->reqType = xkbi->codes->major_opcode;
- req->xkbReqType = X_kbListComponents;
- req->deviceSpec = deviceSpec;
- req->maxNames = *max_inout;
-
- mapLen= codesLen= typesLen= compatLen= symsLen= geomLen= 0;
- if (ptrns->keymap)
- mapLen= (int)strlen(ptrns->keymap);
- if (ptrns->keycodes)
- codesLen= (int)strlen(ptrns->keycodes);
- if (ptrns->types)
- typesLen= (int)strlen(ptrns->types);
- if (ptrns->compat)
- compatLen= (int)strlen(ptrns->compat);
- if (ptrns->symbols)
- symsLen= (int)strlen(ptrns->symbols);
- if (ptrns->geometry)
- geomLen= (int)strlen(ptrns->geometry);
- if (mapLen>255) mapLen= 255;
- if (codesLen>255) codesLen= 255;
- if (typesLen>255) typesLen= 255;
- if (compatLen>255) compatLen= 255;
- if (symsLen>255) symsLen= 255;
- if (geomLen>255) geomLen= 255;
-
- len= mapLen+codesLen+typesLen+compatLen+symsLen+geomLen+6;
- len= XkbPaddedSize(len);
- req->length+= len/4;
- BufAlloc(char *,str,len);
- *str++= mapLen;
- if (mapLen>0) {
- memcpy(str,ptrns->keymap,mapLen);
- str+= mapLen;
- }
- *str++= codesLen;
- if (codesLen>0) {
- memcpy(str,ptrns->keycodes,codesLen);
- str+= codesLen;
- }
- *str++= typesLen;
- if (typesLen>0) {
- memcpy(str,ptrns->types,typesLen);
- str+= typesLen;
- }
- *str++= compatLen;
- if (compatLen>0) {
- memcpy(str,ptrns->compat,compatLen);
- str+= compatLen;
- }
- *str++= symsLen;
- if (symsLen>0) {
- memcpy(str,ptrns->symbols,symsLen);
- str+= symsLen;
- }
- *str++= geomLen;
- if (geomLen>0) {
- memcpy(str,ptrns->geometry,geomLen);
- str+= geomLen;
- }
- if (!_XReply(dpy, (xReply *)&rep, 0, xFalse))
- goto BAILOUT;
- extraLen= (int)rep.length*4;
- *max_inout= rep.extra;
- if (extraLen==0) { /* no matches, but we don't want to report a failure */
- list= _XkbTypedCalloc(1,XkbComponentListRec);
- UnlockDisplay(dpy);
- SyncHandle();
- return list;
- }
- if (_XkbInitReadBuffer(dpy,&buf,extraLen)) {
- Status status;
-
- status= Success;
- list= _XkbTypedCalloc(1,XkbComponentListRec);
- if (!list) {
- _XkbFreeReadBuffer(&buf);
- goto BAILOUT;
- }
- list->num_keymaps= rep.nKeymaps;
- list->num_keycodes= rep.nKeycodes;
- list->num_types= rep.nTypes;
- list->num_compat= rep.nCompatMaps;
- list->num_symbols= rep.nSymbols;
- list->num_geometry= rep.nGeometries;
- if ((status==Success)&&(list->num_keymaps>0))
- list->keymaps= _ReadListing(&buf,list->num_keymaps,&status);
- if ((status==Success)&&(list->num_keycodes>0))
- list->keycodes= _ReadListing(&buf,list->num_keycodes,&status);
- if ((status==Success)&&(list->num_types>0))
- list->types= _ReadListing(&buf,list->num_types,&status);
- if ((status==Success)&&(list->num_compat>0))
- list->compat= _ReadListing(&buf,list->num_compat,&status);
- if ((status==Success)&&(list->num_symbols>0))
- list->symbols= _ReadListing(&buf,list->num_symbols,&status);
- if ((status==Success)&&(list->num_geometry>0))
- list->geometry= _ReadListing(&buf,list->num_geometry,&status);
- left= _XkbFreeReadBuffer(&buf);
- if ((status!=Success)||(buf.error)||(left>2)) {
- XkbFreeComponentList(list);
- goto BAILOUT;
- }
- UnlockDisplay(dpy);
- SyncHandle();
- return list;
- }
-BAILOUT:
- UnlockDisplay(dpy);
- SyncHandle();
- return NULL;
-}
-
-void
-XkbFreeComponentList(XkbComponentListPtr list)
-{
- if (list) {
- if (list->keymaps)
- _FreeComponentNames(list->num_keymaps,list->keymaps);
- if (list->keycodes)
- _FreeComponentNames(list->num_keycodes,list->keycodes);
- if (list->types)
- _FreeComponentNames(list->num_types,list->types);
- if (list->compat)
- _FreeComponentNames(list->num_compat,list->compat);
- if (list->symbols)
- _FreeComponentNames(list->num_symbols,list->symbols);
- if (list->geometry)
- _FreeComponentNames(list->num_geometry,list->geometry);
- bzero((char *)list,sizeof(XkbComponentListRec));
- _XkbFree(list);
- }
- return;
-}
+/************************************************************ +Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc. + +Permission to use, copy, modify, and distribute this +software and its documentation for any purpose and without +fee is hereby granted, provided that the above copyright +notice appear in all copies and that both that copyright +notice and this permission notice appear in supporting +documentation, and that the name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL +DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH +THE USE OR PERFORMANCE OF THIS SOFTWARE. + +********************************************************/ + +#define NEED_MAP_READERS +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include "Xlibint.h" +#include <X11/extensions/XKBproto.h> +#include "XKBlibint.h" + +/***====================================================================***/ + +static void +_FreeComponentNames(int num,XkbComponentNamePtr names) +{ +int i; +XkbComponentNamePtr tmp; + + if ((num<1)||(names==NULL)) + return; + for (i=0,tmp=names;i<num;i++,tmp++) { + if (tmp->name) { + _XkbFree(tmp->name); + tmp->name= NULL; + } + } + _XkbFree(names); + return; +} + +/***====================================================================***/ + +static XkbComponentNamePtr +_ReadListing(XkbReadBufferPtr buf,int count,Status *status_rtrn) +{ +XkbComponentNamePtr first,this; +register int i; +CARD16 * flags; +int slen,wlen; +char * str; + + if (count<1) + return NULL; + first= _XkbTypedCalloc(count,XkbComponentNameRec); + if (!first) + return NULL; + for (this=first,i=0;i<count;i++,this++) { + flags= (CARD16 *)_XkbGetReadBufferPtr(buf,2*sizeof(CARD16)); + if (!flags) + goto BAILOUT; + this->flags= flags[0]; + slen= flags[1]; + wlen= ((slen+1)/2)*2; /* pad to 2 byte boundary */ + this->name= _XkbTypedCalloc(slen+1,char); + if (!this->name) + goto BAILOUT; + str= (char *)_XkbGetReadBufferPtr(buf,wlen); + if (!str) + goto BAILOUT; + memcpy(this->name,str,slen); + } + return first; +BAILOUT: + *status_rtrn= BadAlloc; + _FreeComponentNames(i,first); + return NULL; +} + +/***====================================================================***/ + +XkbComponentListPtr +XkbListComponents( Display * dpy, + unsigned deviceSpec, + XkbComponentNamesPtr ptrns, + int * max_inout) +{ +register xkbListComponentsReq* req; +xkbListComponentsReply rep; +XkbInfoPtr xkbi; +XkbComponentListPtr list; +XkbReadBufferRec buf; +int left; +char * str; +int extraLen,len,mapLen,codesLen,typesLen,compatLen,symsLen,geomLen; + + if ( (dpy==NULL) || (dpy->flags & XlibDisplayNoXkb) || + (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)) || + (ptrns==NULL) || (max_inout==NULL)) + return NULL; + + xkbi= dpy->xkb_info; + LockDisplay(dpy); + GetReq(kbListComponents, req); + req->reqType = xkbi->codes->major_opcode; + req->xkbReqType = X_kbListComponents; + req->deviceSpec = deviceSpec; + req->maxNames = *max_inout; + + mapLen= codesLen= typesLen= compatLen= symsLen= geomLen= 0; + if (ptrns->keymap) + mapLen= (int)strlen(ptrns->keymap); + if (ptrns->keycodes) + codesLen= (int)strlen(ptrns->keycodes); + if (ptrns->types) + typesLen= (int)strlen(ptrns->types); + if (ptrns->compat) + compatLen= (int)strlen(ptrns->compat); + if (ptrns->symbols) + symsLen= (int)strlen(ptrns->symbols); + if (ptrns->geometry) + geomLen= (int)strlen(ptrns->geometry); + if (mapLen>255) mapLen= 255; + if (codesLen>255) codesLen= 255; + if (typesLen>255) typesLen= 255; + if (compatLen>255) compatLen= 255; + if (symsLen>255) symsLen= 255; + if (geomLen>255) geomLen= 255; + + len= mapLen+codesLen+typesLen+compatLen+symsLen+geomLen+6; + len= XkbPaddedSize(len); + req->length+= len/4; + BufAlloc(char *,str,len); + *str++= mapLen; + if (mapLen>0) { + memcpy(str,ptrns->keymap,mapLen); + str+= mapLen; + } + *str++= codesLen; + if (codesLen>0) { + memcpy(str,ptrns->keycodes,codesLen); + str+= codesLen; + } + *str++= typesLen; + if (typesLen>0) { + memcpy(str,ptrns->types,typesLen); + str+= typesLen; + } + *str++= compatLen; + if (compatLen>0) { + memcpy(str,ptrns->compat,compatLen); + str+= compatLen; + } + *str++= symsLen; + if (symsLen>0) { + memcpy(str,ptrns->symbols,symsLen); + str+= symsLen; + } + *str++= geomLen; + if (geomLen>0) { + memcpy(str,ptrns->geometry,geomLen); + str+= geomLen; + } + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) + goto BAILOUT; + extraLen= (int)rep.length*4; + *max_inout= rep.extra; + if (extraLen==0) { /* no matches, but we don't want to report a failure */ + list= _XkbTypedCalloc(1,XkbComponentListRec); + UnlockDisplay(dpy); + SyncHandle(); + return list; + } + if (_XkbInitReadBuffer(dpy,&buf,extraLen)) { + Status status; + + status= Success; + list= _XkbTypedCalloc(1,XkbComponentListRec); + if (!list) { + _XkbFreeReadBuffer(&buf); + goto BAILOUT; + } + list->num_keymaps= rep.nKeymaps; + list->num_keycodes= rep.nKeycodes; + list->num_types= rep.nTypes; + list->num_compat= rep.nCompatMaps; + list->num_symbols= rep.nSymbols; + list->num_geometry= rep.nGeometries; + if ((status==Success)&&(list->num_keymaps>0)) + list->keymaps= _ReadListing(&buf,list->num_keymaps,&status); + if ((status==Success)&&(list->num_keycodes>0)) + list->keycodes= _ReadListing(&buf,list->num_keycodes,&status); + if ((status==Success)&&(list->num_types>0)) + list->types= _ReadListing(&buf,list->num_types,&status); + if ((status==Success)&&(list->num_compat>0)) + list->compat= _ReadListing(&buf,list->num_compat,&status); + if ((status==Success)&&(list->num_symbols>0)) + list->symbols= _ReadListing(&buf,list->num_symbols,&status); + if ((status==Success)&&(list->num_geometry>0)) + list->geometry= _ReadListing(&buf,list->num_geometry,&status); + left= _XkbFreeReadBuffer(&buf); + if ((status!=Success)||(buf.error)||(left>2)) { + XkbFreeComponentList(list); + goto BAILOUT; + } + UnlockDisplay(dpy); + SyncHandle(); + return list; + } +BAILOUT: + UnlockDisplay(dpy); + SyncHandle(); + return NULL; +} + +void +XkbFreeComponentList(XkbComponentListPtr list) +{ + if (list) { + if (list->keymaps) + _FreeComponentNames(list->num_keymaps,list->keymaps); + if (list->keycodes) + _FreeComponentNames(list->num_keycodes,list->keycodes); + if (list->types) + _FreeComponentNames(list->num_types,list->types); + if (list->compat) + _FreeComponentNames(list->num_compat,list->compat); + if (list->symbols) + _FreeComponentNames(list->num_symbols,list->symbols); + if (list->geometry) + _FreeComponentNames(list->num_geometry,list->geometry); + bzero((char *)list,sizeof(XkbComponentListRec)); + _XkbFree(list); + } + return; +} diff --git a/libX11/src/xkb/XKBMisc.c b/libX11/src/xkb/XKBMisc.c index f3d1d1f1b..4aa1f733a 100644 --- a/libX11/src/xkb/XKBMisc.c +++ b/libX11/src/xkb/XKBMisc.c @@ -1,978 +1,978 @@ -/************************************************************
-Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
-
-Permission to use, copy, modify, and distribute this
-software and its documentation for any purpose and without
-fee is hereby granted, provided that the above copyright
-notice appear in all copies and that both that copyright
-notice and this permission notice appear in supporting
-documentation, and that the name of Silicon Graphics not be
-used in advertising or publicity pertaining to distribution
-of the software without specific prior written permission.
-Silicon Graphics makes no representation about the suitability
-of this software for any purpose. It is provided "as is"
-without any express or implied warranty.
-
-SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
-SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
-GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
-DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
-DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
-THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-********************************************************/
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#elif defined(HAVE_CONFIG_H)
-#include <config.h>
-#endif
-
-#ifndef XKB_IN_SERVER
-
-#include <stdio.h>
-#include "Xlibint.h"
-#include <X11/extensions/XKBproto.h>
-#include <X11/keysym.h>
-#include "XKBlibint.h"
-
-#else
-
-#include <stdio.h>
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include "misc.h"
-#include "inputstr.h"
-#include <X11/keysym.h>
-#define XKBSRV_NEED_FILE_FUNCS
-#include <X11/extensions/XKBsrv.h>
-
-#endif /* XKB_IN_SERVER */
-
-/***====================================================================***/
-
-#define mapSize(m) (sizeof(m)/sizeof(XkbKTMapEntryRec))
-static XkbKTMapEntryRec map2Level[]= {
- { True, ShiftMask, {1, ShiftMask, 0} }
-};
-
-static XkbKTMapEntryRec mapAlpha[]= {
- { True, ShiftMask, { 1, ShiftMask, 0 } },
- { True, LockMask, { 0, LockMask, 0 } }
-};
-
-static XkbModsRec preAlpha[]= {
- { 0, 0, 0 },
- { LockMask, LockMask, 0 }
-};
-
-#define NL_VMOD_MASK 0
-static XkbKTMapEntryRec mapKeypad[]= {
- { True, ShiftMask, { 1, ShiftMask, 0 } },
- { False, 0, { 1, 0, NL_VMOD_MASK } }
-};
-
-static XkbKeyTypeRec canonicalTypes[XkbNumRequiredTypes] = {
- { { 0, 0, 0 },
- 1, /* num_levels */
- 0, /* map_count */
- NULL, NULL,
- None, NULL
- },
- { { ShiftMask, ShiftMask, 0 },
- 2, /* num_levels */
- mapSize(map2Level), /* map_count */
- map2Level, NULL,
- None, NULL
- },
- { { ShiftMask|LockMask, ShiftMask|LockMask, 0 },
- 2, /* num_levels */
- mapSize(mapAlpha), /* map_count */
- mapAlpha, preAlpha,
- None, NULL
- },
- { { ShiftMask, ShiftMask, NL_VMOD_MASK },
- 2, /* num_levels */
- mapSize(mapKeypad), /* map_count */
- mapKeypad, NULL,
- None, NULL
- }
-};
-
-Status
-XkbInitCanonicalKeyTypes(XkbDescPtr xkb,unsigned which,int keypadVMod)
-{
-XkbClientMapPtr map;
-XkbKeyTypePtr from,to;
-Status rtrn;
-
- if (!xkb)
- return BadMatch;
- rtrn= XkbAllocClientMap(xkb,XkbKeyTypesMask,XkbNumRequiredTypes);
- if (rtrn!=Success)
- return rtrn;
- map= xkb->map;
- if ((which&XkbAllRequiredTypes)==0)
- return Success;
- rtrn= Success;
- from= canonicalTypes;
- to= map->types;
- if (which&XkbOneLevelMask)
- rtrn= XkbCopyKeyType(&from[XkbOneLevelIndex],&to[XkbOneLevelIndex]);
- if ((which&XkbTwoLevelMask)&&(rtrn==Success))
- rtrn= XkbCopyKeyType(&from[XkbTwoLevelIndex],&to[XkbTwoLevelIndex]);
- if ((which&XkbAlphabeticMask)&&(rtrn==Success))
- rtrn= XkbCopyKeyType(&from[XkbAlphabeticIndex],&to[XkbAlphabeticIndex]);
- if ((which&XkbKeypadMask)&&(rtrn==Success)) {
- XkbKeyTypePtr type;
- rtrn= XkbCopyKeyType(&from[XkbKeypadIndex],&to[XkbKeypadIndex]);
- type= &to[XkbKeypadIndex];
- if ((keypadVMod>=0)&&(keypadVMod<XkbNumVirtualMods)&&(rtrn==Success)) {
- type->mods.vmods= (1<<keypadVMod);
- type->map[0].active= True;
- type->map[0].mods.mask= ShiftMask;
- type->map[0].mods.real_mods= ShiftMask;
- type->map[0].mods.vmods= 0;
- type->map[0].level= 1;
- type->map[1].active= False;
- type->map[1].mods.mask= 0;
- type->map[1].mods.real_mods= 0;
- type->map[1].mods.vmods= (1<<keypadVMod);
- type->map[1].level= 1;
- }
- }
- return Success;
-}
-
-/***====================================================================***/
-
-#define CORE_SYM(i) (i<map_width?core_syms[i]:NoSymbol)
-#define XKB_OFFSET(g,l) (((g)*groupsWidth)+(l))
-
-int
-XkbKeyTypesForCoreSymbols( XkbDescPtr xkb,
- int map_width,
- KeySym * core_syms,
- unsigned int protected,
- int * types_inout,
- KeySym * xkb_syms_rtrn)
-{
-register int i;
-unsigned int empty;
-int nSyms[XkbNumKbdGroups];
-int nGroups,tmp,groupsWidth;
-
- /* Section 12.2 of the protocol describes this process in more detail */
- /* Step 1: find the # of symbols in the core mapping per group */
- groupsWidth= 2;
- for (i=0;i<XkbNumKbdGroups;i++) {
- if ((protected&(1<<i))&&(types_inout[i]<xkb->map->num_types)) {
- nSyms[i]= xkb->map->types[types_inout[i]].num_levels;
- if (nSyms[i]>groupsWidth)
- groupsWidth= nSyms[i];
- }
- else {
- types_inout[i]= XkbTwoLevelIndex; /* don't really know, yet */
- nSyms[i]= 2;
- }
- }
- if (nSyms[XkbGroup1Index]<2)
- nSyms[XkbGroup1Index]= 2;
- if (nSyms[XkbGroup2Index]<2)
- nSyms[XkbGroup2Index]= 2;
- /* Step 2: Copy the symbols from the core ordering to XKB ordering */
- /* symbols in the core are in the order: */
- /* G1L1 G1L2 G2L1 G2L2 [G1L[3-n]] [G2L[3-n]] [G3L*] [G3L*] */
- xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,0)]= CORE_SYM(0);
- xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,1)]= CORE_SYM(1);
- for (i=2;i<nSyms[XkbGroup1Index];i++) {
- xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,i)]= CORE_SYM(2+i);
- }
- xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,0)]= CORE_SYM(2);
- xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,1)]= CORE_SYM(3);
- tmp= 2+(nSyms[XkbGroup1Index]-2); /* offset to extra group2 syms */
- for (i=2;i<nSyms[XkbGroup2Index];i++) {
- xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,i)]= CORE_SYM(tmp+i);
- }
- tmp= nSyms[XkbGroup1Index]+nSyms[XkbGroup2Index];
- if ((tmp>=map_width)&&
- ((protected&(XkbExplicitKeyType3Mask|XkbExplicitKeyType4Mask))==0)) {
- nSyms[XkbGroup3Index]= 0;
- nSyms[XkbGroup4Index]= 0;
- nGroups= 2;
- }
- else {
- nGroups= 3;
- for (i=0;i<nSyms[XkbGroup3Index];i++,tmp++) {
- xkb_syms_rtrn[XKB_OFFSET(XkbGroup3Index,i)]= CORE_SYM(tmp);
- }
- if ((tmp<map_width)||(protected&XkbExplicitKeyType4Mask)) {
- nGroups= 4;
- for (i=0;i<nSyms[XkbGroup4Index];i++,tmp++) {
- xkb_syms_rtrn[XKB_OFFSET(XkbGroup4Index,i)]= CORE_SYM(tmp);
- }
- }
- else {
- nSyms[XkbGroup4Index]= 0;
- }
- }
- /* steps 3&4: alphanumeric expansion, assign canonical types */
- empty= 0;
- for (i=0;i<nGroups;i++) {
- KeySym *syms;
- syms= &xkb_syms_rtrn[XKB_OFFSET(i,0)];
- if ((nSyms[i]>1)&&(syms[1]==NoSymbol)&&(syms[0]!=NoSymbol)) {
- KeySym upper,lower;
- XConvertCase(syms[0],&lower,&upper);
- if (upper!=lower) {
- xkb_syms_rtrn[XKB_OFFSET(i,0)]= lower;
- xkb_syms_rtrn[XKB_OFFSET(i,1)]= upper;
- if ((protected&(1<<i))==0)
- types_inout[i]= XkbAlphabeticIndex;
- }
- else if ((protected&(1<<i))==0) {
- types_inout[i]= XkbOneLevelIndex;
- /* nSyms[i]= 1;*/
- }
- }
- if (((protected&(1<<i))==0)&&(types_inout[i]==XkbTwoLevelIndex)) {
- if (IsKeypadKey(syms[0])||IsKeypadKey(syms[1]))
- types_inout[i]= XkbKeypadIndex;
- else {
- KeySym upper,lower;
- XConvertCase(syms[0],&lower,&upper);
- if ((syms[0]==lower)&&(syms[1]==upper))
- types_inout[i]= XkbAlphabeticIndex;
- }
- }
- if (syms[0]==NoSymbol) {
- register int n;
- Bool found;
- for (n=1,found=False;(!found)&&(n<nSyms[i]);n++) {
- found= (syms[n]!=NoSymbol);
- }
- if (!found)
- empty|= (1<<i);
- }
- }
- /* step 5: squoosh out empty groups */
- if (empty) {
- for (i=nGroups-1;i>=0;i--) {
- if (((empty&(1<<i))==0)||(protected&(1<<i)))
- break;
- nGroups--;
- }
- }
- if (nGroups<1)
- return 0;
-
- /* step 6: replicate group 1 into group two, if necessary */
- if ((nGroups>1)&&((empty&(XkbGroup1Mask|XkbGroup2Mask))==XkbGroup2Mask)) {
- if ((protected&(XkbExplicitKeyType1Mask|XkbExplicitKeyType2Mask))==0) {
- nSyms[XkbGroup2Index]= nSyms[XkbGroup1Index];
- types_inout[XkbGroup2Index]= types_inout[XkbGroup1Index];
- memcpy((char *)&xkb_syms_rtrn[2],(char *)xkb_syms_rtrn,
- 2*sizeof(KeySym));
- }
- else if (types_inout[XkbGroup1Index]==types_inout[XkbGroup2Index]) {
- memcpy((char *)&xkb_syms_rtrn[nSyms[XkbGroup1Index]],
- (char *)xkb_syms_rtrn,
- nSyms[XkbGroup1Index]*sizeof(KeySym));
- }
- }
-
- /* step 7: check for all groups identical or all width 1 */
- if (nGroups>1) {
- Bool sameType,allOneLevel;
- allOneLevel= (xkb->map->types[types_inout[0]].num_levels==1);
- for (i=1,sameType=True;(allOneLevel||sameType)&&(i<nGroups);i++) {
- sameType=(sameType&&(types_inout[i]==types_inout[XkbGroup1Index]));
- if (allOneLevel)
- allOneLevel= (xkb->map->types[types_inout[i]].num_levels==1);
- }
- if ((sameType)&&
- (!(protected&(XkbExplicitKeyTypesMask&~XkbExplicitKeyType1Mask)))){
- register int s;
- Bool identical;
- for (i=1,identical=True;identical&&(i<nGroups);i++) {
- KeySym *syms;
- syms= &xkb_syms_rtrn[XKB_OFFSET(i,0)];
- for (s=0;identical&&(s<nSyms[i]);s++) {
- if (syms[s]!=xkb_syms_rtrn[s])
- identical= False;
- }
- }
- if (identical)
- nGroups= 1;
- }
- if (allOneLevel && (nGroups>1)) {
- KeySym *syms;
- syms= &xkb_syms_rtrn[nSyms[XkbGroup1Index]];
- nSyms[XkbGroup1Index]= 1;
- for (i=1;i<nGroups;i++) {
- xkb_syms_rtrn[i]= syms[0];
- syms+= nSyms[i];
- nSyms[i]= 1;
- }
- }
- }
- return nGroups;
-}
-
-static XkbSymInterpretPtr
-_XkbFindMatchingInterp( XkbDescPtr xkb,
- KeySym sym,
- unsigned int real_mods,
- unsigned int level)
-{
-register unsigned i;
-XkbSymInterpretPtr interp,rtrn;
-CARD8 mods;
-
- rtrn= NULL;
- interp= xkb->compat->sym_interpret;
- for (i=0;i<xkb->compat->num_si;i++,interp++) {
- if ((interp->sym==NoSymbol)||(sym==interp->sym)) {
- int match;
- if ((level==0)||((interp->match&XkbSI_LevelOneOnly)==0))
- mods= real_mods;
- else mods= 0;
- switch (interp->match&XkbSI_OpMask) {
- case XkbSI_NoneOf:
- match= ((interp->mods&mods)==0);
- break;
- case XkbSI_AnyOfOrNone:
- match= ((mods==0)||((interp->mods&mods)!=0));
- break;
- case XkbSI_AnyOf:
- match= ((interp->mods&mods)!=0);
- break;
- case XkbSI_AllOf:
- match= ((interp->mods&mods)==interp->mods);
- break;
- case XkbSI_Exactly:
- match= (interp->mods==mods);
- break;
- default:
- match= 0;
- break;
- }
- if (match) {
- if (interp->sym!=NoSymbol) {
- return interp;
- }
- else if (rtrn==NULL) {
- rtrn= interp;
- }
- }
- }
- }
- return rtrn;
-}
-
-static void
-_XkbAddKeyChange(KeyCode *pFirst,unsigned char *pNum,KeyCode newKey)
-{
-KeyCode last;
-
- last= (*pFirst)+(*pNum);
- if (newKey<*pFirst) {
- *pFirst= newKey;
- *pNum= (last-newKey)+1;
- }
- else if (newKey>last) {
- *pNum= (last-*pFirst)+1;
- }
- return;
-}
-
-static void
-_XkbSetActionKeyMods(XkbDescPtr xkb,XkbAction *act,unsigned mods)
-{
-unsigned tmp;
-
- switch (act->type) {
- case XkbSA_SetMods: case XkbSA_LatchMods: case XkbSA_LockMods:
- if (act->mods.flags&XkbSA_UseModMapMods)
- act->mods.real_mods= act->mods.mask= mods;
- if ((tmp= XkbModActionVMods(&act->mods))!=0) {
- XkbVirtualModsToReal(xkb,tmp,&tmp);
- act->mods.mask|= tmp;
- }
- break;
- case XkbSA_ISOLock:
- if (act->iso.flags&XkbSA_UseModMapMods)
- act->iso.real_mods= act->iso.mask= mods;
- if ((tmp= XkbModActionVMods(&act->iso))!=0) {
- XkbVirtualModsToReal(xkb,tmp,&tmp);
- act->iso.mask|= tmp;
- }
- break;
- }
- return;
-}
-
-#define IBUF_SIZE 8
-
-Bool
-XkbApplyCompatMapToKey(XkbDescPtr xkb,KeyCode key,XkbChangesPtr changes)
-{
-KeySym * syms;
-unsigned char explicit,mods;
-XkbSymInterpretPtr *interps,ibuf[IBUF_SIZE];
-int n,nSyms,found;
-unsigned changed,tmp;
-
- if ((!xkb)||(!xkb->map)||(!xkb->map->key_sym_map)||
- (!xkb->compat)||(!xkb->compat->sym_interpret)||
- (key<xkb->min_key_code)||(key>xkb->max_key_code)) {
- return False;
- }
- if (((!xkb->server)||(!xkb->server->key_acts))&&
- (XkbAllocServerMap(xkb,XkbAllServerInfoMask,0)!=Success)) {
- return False;
- }
- changed= 0; /* keeps track of what has changed in _this_ call */
- explicit= xkb->server->explicit[key];
- if (explicit&XkbExplicitInterpretMask) /* nothing to do */
- return True;
- mods= (xkb->map->modmap?xkb->map->modmap[key]:0);
- nSyms= XkbKeyNumSyms(xkb,key);
- syms= XkbKeySymsPtr(xkb,key);
- if (nSyms>IBUF_SIZE) {
- interps= _XkbTypedCalloc(nSyms,XkbSymInterpretPtr);
- if (interps==NULL) {
- interps= ibuf;
- nSyms= IBUF_SIZE;
- }
- }
- else {
- interps= ibuf;
- }
- found= 0;
- for (n=0;n<nSyms;n++) {
- unsigned level= (n%XkbKeyGroupsWidth(xkb,key));
- interps[n]= NULL;
- if (syms[n]!=NoSymbol) {
- interps[n]= _XkbFindMatchingInterp(xkb,syms[n],mods,level);
- if (interps[n]&&interps[n]->act.type!=XkbSA_NoAction)
- found++;
- else interps[n]= NULL;
- }
- }
- /* 1/28/96 (ef) -- XXX! WORKING HERE */
- if (!found) {
- if (xkb->server->key_acts[key]!=0) {
- xkb->server->key_acts[key]= 0;
- changed|= XkbKeyActionsMask;
- }
- }
- else {
- XkbAction *pActs;
- unsigned int new_vmodmask;
- changed|= XkbKeyActionsMask;
- pActs= XkbResizeKeyActions(xkb,key,nSyms);
- if (!pActs) {
- if (nSyms > IBUF_SIZE)
- Xfree(interps);
- return False;
- }
- new_vmodmask= 0;
- for (n=0;n<nSyms;n++) {
- if (interps[n]) {
- unsigned effMods;
-
- pActs[n]= *((XkbAction *)&interps[n]->act);
- if ((n==0)||((interps[n]->match&XkbSI_LevelOneOnly)==0)) {
- effMods= mods;
- if (interps[n]->virtual_mod!=XkbNoModifier)
- new_vmodmask|= (1<<interps[n]->virtual_mod);
- }
- else effMods= 0;
- _XkbSetActionKeyMods(xkb,&pActs[n],effMods);
- }
- else pActs[n].type= XkbSA_NoAction;
- }
- if (((explicit&XkbExplicitVModMapMask)==0)&&
- (xkb->server->vmodmap[key]!=new_vmodmask)) {
- changed|= XkbVirtualModMapMask;
- xkb->server->vmodmap[key]= new_vmodmask;
- }
- if (interps[0]) {
- if ((interps[0]->flags&XkbSI_LockingKey)&&
- ((explicit&XkbExplicitBehaviorMask)==0)) {
- xkb->server->behaviors[key].type= XkbKB_Lock;
- changed|= XkbKeyBehaviorsMask;
- }
- if (((explicit&XkbExplicitAutoRepeatMask)==0)&&(xkb->ctrls)) {
- CARD8 old;
- old= xkb->ctrls->per_key_repeat[key/8];
- if (interps[0]->flags&XkbSI_AutoRepeat)
- xkb->ctrls->per_key_repeat[key/8]|= (1<<(key%8));
- else xkb->ctrls->per_key_repeat[key/8]&= ~(1<<(key%8));
- if (changes && (old!=xkb->ctrls->per_key_repeat[key/8]))
- changes->ctrls.changed_ctrls|= XkbPerKeyRepeatMask;
- }
- }
- }
- if ((!found)||(interps[0]==NULL)) {
- if (((explicit&XkbExplicitAutoRepeatMask)==0)&&(xkb->ctrls)) {
- CARD8 old;
- old= xkb->ctrls->per_key_repeat[key/8];
-#ifdef RETURN_SHOULD_REPEAT
- if (*XkbKeySymsPtr(xkb,key) != XK_Return)
-#endif
- xkb->ctrls->per_key_repeat[key/8]|= (1<<(key%8));
- if (changes && (old!=xkb->ctrls->per_key_repeat[key/8]))
- changes->ctrls.changed_ctrls|= XkbPerKeyRepeatMask;
- }
- if (((explicit&XkbExplicitBehaviorMask)==0)&&
- (xkb->server->behaviors[key].type==XkbKB_Lock)) {
- xkb->server->behaviors[key].type= XkbKB_Default;
- changed|= XkbKeyBehaviorsMask;
- }
- }
- if (changes) {
- XkbMapChangesPtr mc;
- mc= &changes->map;
- tmp= (changed&mc->changed);
- if (tmp&XkbKeyActionsMask)
- _XkbAddKeyChange(&mc->first_key_act,&mc->num_key_acts,key);
- else if (changed&XkbKeyActionsMask) {
- mc->changed|= XkbKeyActionsMask;
- mc->first_key_act= key;
- mc->num_key_acts= 1;
- }
- if (tmp&XkbKeyBehaviorsMask) {
- _XkbAddKeyChange(&mc->first_key_behavior,&mc->num_key_behaviors,
- key);
- }
- else if (changed&XkbKeyBehaviorsMask) {
- mc->changed|= XkbKeyBehaviorsMask;
- mc->first_key_behavior= key;
- mc->num_key_behaviors= 1;
- }
- if (tmp&XkbVirtualModMapMask)
- _XkbAddKeyChange(&mc->first_vmodmap_key,&mc->num_vmodmap_keys,key);
- else if (changed&XkbVirtualModMapMask) {
- mc->changed|= XkbVirtualModMapMask;
- mc->first_vmodmap_key= key;
- mc->num_vmodmap_keys= 1;
- }
- mc->changed|= changed;
- }
- if (interps!=ibuf)
- _XkbFree(interps);
- return True;
-}
-
-Bool
-XkbUpdateMapFromCore( XkbDescPtr xkb,
- KeyCode first_key,
- int num_keys,
- int map_width,
- KeySym * core_keysyms,
- XkbChangesPtr changes)
-{
-register int key,last_key;
-KeySym * syms;
-
- syms= &core_keysyms[(first_key-xkb->min_key_code)*map_width];
- if (changes) {
- if (changes->map.changed&XkbKeySymsMask) {
- _XkbAddKeyChange(&changes->map.first_key_sym,
- &changes->map.num_key_syms,first_key);
- if (num_keys>1) {
- _XkbAddKeyChange(&changes->map.first_key_sym,
- &changes->map.num_key_syms,
- first_key+num_keys-1);
- }
- }
- else {
- changes->map.changed|= XkbKeySymsMask;
- changes->map.first_key_sym= first_key;
- changes->map.num_key_syms= num_keys;
- }
- }
- last_key= first_key+num_keys-1;
- for (key=first_key;key<=last_key;key++,syms+= map_width) {
- XkbMapChangesPtr mc;
- unsigned explicit;
- KeySym tsyms[XkbMaxSymsPerKey];
- int types[XkbNumKbdGroups];
- int nG;
-
- explicit= xkb->server->explicit[key]&XkbExplicitKeyTypesMask;
- types[XkbGroup1Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup1Index);
- types[XkbGroup2Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup2Index);
- types[XkbGroup3Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup3Index);
- types[XkbGroup4Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup4Index);
- nG= XkbKeyTypesForCoreSymbols(xkb,map_width,syms,explicit,types,tsyms);
- if (changes)
- mc= &changes->map;
- else mc= NULL;
- XkbChangeTypesOfKey(xkb,key,nG,XkbAllGroupsMask,types,mc);
- memcpy((char *)XkbKeySymsPtr(xkb,key),(char *)tsyms,
- XkbKeyNumSyms(xkb,key)*sizeof(KeySym));
- XkbApplyCompatMapToKey(xkb,key,changes);
- }
-
- if ((xkb->server->vmods!=NULL)&&(xkb->map->modmap!=NULL)&&(changes)&&
- (changes->map.changed&(XkbVirtualModMapMask|XkbModifierMapMask))) {
- unsigned char newVMods[XkbNumVirtualMods];
- register unsigned bit,i;
- unsigned present;
-
- bzero(newVMods,XkbNumVirtualMods);
- present= 0;
- for (key=xkb->min_key_code;key<=xkb->max_key_code;key++) {
- if (xkb->server->vmodmap[key]==0)
- continue;
- for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
- if (bit&xkb->server->vmodmap[key]) {
- present|= bit;
- newVMods[i]|= xkb->map->modmap[key];
- }
- }
- }
- for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
- if ((bit&present)&&(newVMods[i]!=xkb->server->vmods[i])) {
- changes->map.changed|= XkbVirtualModsMask;
- changes->map.vmods|= bit;
- xkb->server->vmods[i]= newVMods[i];
- }
- }
- }
- if (changes && (changes->map.changed&XkbVirtualModsMask))
- XkbApplyVirtualModChanges(xkb,changes->map.vmods,changes);
- return True;
-}
-
-Status
-XkbChangeTypesOfKey( XkbDescPtr xkb,
- int key,
- int nGroups,
- unsigned groups,
- int * newTypesIn,
- XkbMapChangesPtr changes)
-{
-XkbKeyTypePtr pOldType,pNewType;
-register int i;
-int width,nOldGroups,oldWidth,newTypes[XkbNumKbdGroups];
-
- if ((!xkb) || (!XkbKeycodeInRange(xkb,key)) || (!xkb->map) ||
- (!xkb->map->types)||((groups&XkbAllGroupsMask)==0)||
- (nGroups>XkbNumKbdGroups)) {
- return BadMatch;
- }
- if (nGroups==0) {
- for (i=0;i<XkbNumKbdGroups;i++) {
- xkb->map->key_sym_map[key].kt_index[i]= XkbOneLevelIndex;
- }
- i= xkb->map->key_sym_map[key].group_info;
- i= XkbSetNumGroups(i,0);
- xkb->map->key_sym_map[key].group_info= i;
- XkbResizeKeySyms(xkb,key,0);
- return Success;
- }
-
- nOldGroups= XkbKeyNumGroups(xkb,key);
- oldWidth= XkbKeyGroupsWidth(xkb,key);
- for (width=i=0;i<nGroups;i++) {
- if (groups&(1<<i))
- newTypes[i]= newTypesIn[i];
- else if (i<nOldGroups)
- newTypes[i]= XkbKeyKeyTypeIndex(xkb,key,i);
- else if (nOldGroups>0)
- newTypes[i]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup1Index);
- else newTypes[i]= XkbTwoLevelIndex;
- if (newTypes[i]>xkb->map->num_types)
- return BadMatch;
- pNewType= &xkb->map->types[newTypes[i]];
- if (pNewType->num_levels>width)
- width= pNewType->num_levels;
- }
- if ((xkb->ctrls)&&(nGroups>xkb->ctrls->num_groups))
- xkb->ctrls->num_groups= nGroups;
- if ((width!=oldWidth)||(nGroups!=nOldGroups)) {
- KeySym oldSyms[XkbMaxSymsPerKey],*pSyms;
- int nCopy;
-
- if (nOldGroups==0) {
- pSyms= XkbResizeKeySyms(xkb,key,width*nGroups);
- if (pSyms!=NULL) {
- i= xkb->map->key_sym_map[key].group_info;
- i= XkbSetNumGroups(i,nGroups);
- xkb->map->key_sym_map[key].group_info= i;
- xkb->map->key_sym_map[key].width= width;
- for (i=0;i<nGroups;i++) {
- xkb->map->key_sym_map[key].kt_index[i]= newTypes[i];
- }
- return Success;
- }
- return BadAlloc;
- }
- pSyms= XkbKeySymsPtr(xkb,key);
- memcpy(oldSyms,pSyms,XkbKeyNumSyms(xkb,key)*sizeof(KeySym));
- pSyms= XkbResizeKeySyms(xkb,key,width*nGroups);
- if (pSyms==NULL)
- return BadAlloc;
- bzero(pSyms,width*nGroups*sizeof(KeySym));
- for (i=0;(i<nGroups)&&(i<nOldGroups);i++) {
- pOldType= XkbKeyKeyType(xkb,key,i);
- pNewType= &xkb->map->types[newTypes[i]];
- if (pNewType->num_levels>pOldType->num_levels)
- nCopy= pOldType->num_levels;
- else nCopy= pNewType->num_levels;
- memcpy(&pSyms[i*width],&oldSyms[i*oldWidth],nCopy*sizeof(KeySym));
- }
- if (XkbKeyHasActions(xkb,key)) {
- XkbAction oldActs[XkbMaxSymsPerKey],*pActs;
- pActs= XkbKeyActionsPtr(xkb,key);
- memcpy(oldActs,pActs,XkbKeyNumSyms(xkb,key)*sizeof(XkbAction));
- pActs= XkbResizeKeyActions(xkb,key,width*nGroups);
- if (pActs==NULL)
- return BadAlloc;
- bzero(pActs,width*nGroups*sizeof(XkbAction));
- for (i=0;(i<nGroups)&&(i<nOldGroups);i++) {
- pOldType= XkbKeyKeyType(xkb,key,i);
- pNewType= &xkb->map->types[newTypes[i]];
- if (pNewType->num_levels>pOldType->num_levels)
- nCopy= pOldType->num_levels;
- else nCopy= pNewType->num_levels;
- memcpy(&pActs[i*width],&oldActs[i*oldWidth],
- nCopy*sizeof(XkbAction));
- }
- }
- i= xkb->map->key_sym_map[key].group_info;
- i= XkbSetNumGroups(i,nGroups);
- xkb->map->key_sym_map[key].group_info= i;
- xkb->map->key_sym_map[key].width= width;
- }
- width= 0;
- for (i=0;i<nGroups;i++) {
- xkb->map->key_sym_map[key].kt_index[i]= newTypes[i];
- if (xkb->map->types[newTypes[i]].num_levels>width)
- width= xkb->map->types[newTypes[i]].num_levels;
- }
- xkb->map->key_sym_map[key].width= width;
- if (changes!=NULL) {
- if (changes->changed&XkbKeySymsMask) {
- _XkbAddKeyChange(&changes->first_key_sym,&changes->num_key_syms,
- key);
- }
- else {
- changes->changed|= XkbKeySymsMask;
- changes->first_key_sym= key;
- changes->num_key_syms= 1;
- }
- }
- return Success;
-}
-
-/***====================================================================***/
-
-Bool
-XkbVirtualModsToReal(XkbDescPtr xkb,unsigned virtual_mask,unsigned *mask_rtrn)
-{
-register int i,bit;
-register unsigned mask;
-
- if (xkb==NULL)
- return False;
- if (virtual_mask==0) {
- *mask_rtrn= 0;
- return True;
- }
- if (xkb->server==NULL)
- return False;
- for (i=mask=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
- if (virtual_mask&bit)
- mask|= xkb->server->vmods[i];
- }
- *mask_rtrn= mask;
- return True;
-}
-
-/***====================================================================***/
-
-Bool
-XkbUpdateActionVirtualMods(XkbDescPtr xkb,XkbAction *act,unsigned changed)
-{
-unsigned int tmp;
-
- switch (act->type) {
- case XkbSA_SetMods: case XkbSA_LatchMods: case XkbSA_LockMods:
- if (((tmp= XkbModActionVMods(&act->mods))&changed)!=0) {
- XkbVirtualModsToReal(xkb,tmp,&tmp);
- act->mods.mask= act->mods.real_mods;
- act->mods.mask|= tmp;
- return True;
- }
- break;
- case XkbSA_ISOLock:
- if ((((tmp= XkbModActionVMods(&act->iso))!=0)&changed)!=0) {
- XkbVirtualModsToReal(xkb,tmp,&tmp);
- act->iso.mask= act->iso.real_mods;
- act->iso.mask|= tmp;
- return True;
- }
- break;
- }
- return False;
-}
-
-void
-XkbUpdateKeyTypeVirtualMods( XkbDescPtr xkb,
- XkbKeyTypePtr type,
- unsigned int changed,
- XkbChangesPtr changes)
-{
-register unsigned int i;
-unsigned int mask;
-
- XkbVirtualModsToReal(xkb,type->mods.vmods,&mask);
- type->mods.mask= type->mods.real_mods|mask;
- if ((type->map_count>0)&&(type->mods.vmods!=0)) {
- XkbKTMapEntryPtr entry;
- for (i=0,entry=type->map;i<type->map_count;i++,entry++) {
- if (entry->mods.vmods!=0) {
- XkbVirtualModsToReal(xkb,entry->mods.vmods,&mask);
- entry->mods.mask=entry->mods.real_mods|mask;
- /* entry is active if vmods are bound*/
- entry->active= (mask!=0);
- }
- else entry->active= 1;
- }
- }
- if (changes) {
- int type_ndx;
- type_ndx= type-xkb->map->types;
- if ((type_ndx<0)||(type_ndx>xkb->map->num_types))
- return;
- if (changes->map.changed&XkbKeyTypesMask) {
- int last;
- last= changes->map.first_type+changes->map.num_types-1;
- if (type_ndx<changes->map.first_type) {
- changes->map.first_type= type_ndx;
- changes->map.num_types= (last-type_ndx)+1;
- }
- else if (type_ndx>last) {
- changes->map.num_types= (type_ndx-changes->map.first_type)+1;
- }
- }
- else {
- changes->map.changed|= XkbKeyTypesMask;
- changes->map.first_type= type_ndx;
- changes->map.num_types= 1;
- }
- }
- return;
-}
-
-Bool
-XkbApplyVirtualModChanges(XkbDescPtr xkb,unsigned changed,XkbChangesPtr changes)
-{
-register int i;
-unsigned int checkState = 0;
-
- if ((!xkb) || (!xkb->map) || (changed==0))
- return False;
- for (i=0;i<xkb->map->num_types;i++) {
- if (xkb->map->types[i].mods.vmods & changed)
- XkbUpdateKeyTypeVirtualMods(xkb,&xkb->map->types[i],changed,changes);
- }
- if (changed&xkb->ctrls->internal.vmods) {
- unsigned int newMask;
- XkbVirtualModsToReal(xkb,xkb->ctrls->internal.vmods,&newMask);
- newMask|= xkb->ctrls->internal.real_mods;
- if (xkb->ctrls->internal.mask!=newMask) {
- xkb->ctrls->internal.mask= newMask;
- if (changes) {
- changes->ctrls.changed_ctrls|= XkbInternalModsMask;
- checkState= True;
- }
- }
- }
- if (changed&xkb->ctrls->ignore_lock.vmods) {
- unsigned int newMask;
- XkbVirtualModsToReal(xkb,xkb->ctrls->ignore_lock.vmods,&newMask);
- newMask|= xkb->ctrls->ignore_lock.real_mods;
- if (xkb->ctrls->ignore_lock.mask!=newMask) {
- xkb->ctrls->ignore_lock.mask= newMask;
- if (changes) {
- changes->ctrls.changed_ctrls|= XkbIgnoreLockModsMask;
- checkState= True;
- }
- }
- }
- if (xkb->indicators!=NULL) {
- XkbIndicatorMapPtr map;
- map= &xkb->indicators->maps[0];
- for (i=0;i<XkbNumIndicators;i++,map++) {
- if (map->mods.vmods&changed) {
- unsigned int newMask;
- XkbVirtualModsToReal(xkb,map->mods.vmods,&newMask);
- newMask|= map->mods.real_mods;
- if (newMask!=map->mods.mask) {
- map->mods.mask= newMask;
- if (changes) {
- changes->indicators.map_changes|= (1<<i);
- checkState= True;
- }
- }
- }
- }
- }
- if (xkb->compat!=NULL) {
- XkbCompatMapPtr compat;
- compat= xkb->compat;
- for (i=0;i<XkbNumKbdGroups;i++) {
- unsigned int newMask;
- XkbVirtualModsToReal(xkb,compat->groups[i].vmods,&newMask);
- newMask|= compat->groups[i].real_mods;
- if (compat->groups[i].mask!=newMask) {
- compat->groups[i].mask= newMask;
- if (changes) {
- changes->compat.changed_groups|= (1<<i);
- checkState= True;
- }
- }
- }
- }
- if (xkb->map && xkb->server) {
- int highChange = 0, lowChange = -1;
- for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
- if (XkbKeyHasActions(xkb,i)) {
- register XkbAction *pAct;
- register int n;
-
- pAct= XkbKeyActionsPtr(xkb,i);
- for (n=XkbKeyNumActions(xkb,i);n>0;n--,pAct++) {
- if ((pAct->type!=XkbSA_NoAction)&&
- XkbUpdateActionVirtualMods(xkb,pAct,changed)) {
- if (lowChange<0)
- lowChange= i;
- highChange= i;
- }
- }
- }
- }
- if (changes && (lowChange>0)) { /* something changed */
- if (changes->map.changed&XkbKeyActionsMask) {
- int last;
- if (changes->map.first_key_act<lowChange)
- lowChange= changes->map.first_key_act;
- last= changes->map.first_key_act+changes->map.num_key_acts-1;
- if (last>highChange)
- highChange= last;
- }
- changes->map.changed|= XkbKeyActionsMask;
- changes->map.first_key_act= lowChange;
- changes->map.num_key_acts= (highChange-lowChange)+1;
- }
- }
- return checkState;
-}
+/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +Permission to use, copy, modify, and distribute this +software and its documentation for any purpose and without +fee is hereby granted, provided that the above copyright +notice appear in all copies and that both that copyright +notice and this permission notice appear in supporting +documentation, and that the name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL +DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH +THE USE OR PERFORMANCE OF THIS SOFTWARE. + +********************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#elif defined(HAVE_CONFIG_H) +#include <config.h> +#endif + +#ifndef XKB_IN_SERVER + +#include <stdio.h> +#include "Xlibint.h" +#include <X11/extensions/XKBproto.h> +#include <X11/keysym.h> +#include "XKBlibint.h" + +#else + +#include <stdio.h> +#include <X11/X.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "inputstr.h" +#include <X11/keysym.h> +#define XKBSRV_NEED_FILE_FUNCS +#include <X11/extensions/XKBsrv.h> + +#endif /* XKB_IN_SERVER */ + +/***====================================================================***/ + +#define mapSize(m) (sizeof(m)/sizeof(XkbKTMapEntryRec)) +static XkbKTMapEntryRec map2Level[]= { + { True, ShiftMask, {1, ShiftMask, 0} } +}; + +static XkbKTMapEntryRec mapAlpha[]= { + { True, ShiftMask, { 1, ShiftMask, 0 } }, + { True, LockMask, { 0, LockMask, 0 } } +}; + +static XkbModsRec preAlpha[]= { + { 0, 0, 0 }, + { LockMask, LockMask, 0 } +}; + +#define NL_VMOD_MASK 0 +static XkbKTMapEntryRec mapKeypad[]= { + { True, ShiftMask, { 1, ShiftMask, 0 } }, + { False, 0, { 1, 0, NL_VMOD_MASK } } +}; + +static XkbKeyTypeRec canonicalTypes[XkbNumRequiredTypes] = { + { { 0, 0, 0 }, + 1, /* num_levels */ + 0, /* map_count */ + NULL, NULL, + None, NULL + }, + { { ShiftMask, ShiftMask, 0 }, + 2, /* num_levels */ + mapSize(map2Level), /* map_count */ + map2Level, NULL, + None, NULL + }, + { { ShiftMask|LockMask, ShiftMask|LockMask, 0 }, + 2, /* num_levels */ + mapSize(mapAlpha), /* map_count */ + mapAlpha, preAlpha, + None, NULL + }, + { { ShiftMask, ShiftMask, NL_VMOD_MASK }, + 2, /* num_levels */ + mapSize(mapKeypad), /* map_count */ + mapKeypad, NULL, + None, NULL + } +}; + +Status +XkbInitCanonicalKeyTypes(XkbDescPtr xkb,unsigned which,int keypadVMod) +{ +XkbClientMapPtr map; +XkbKeyTypePtr from,to; +Status rtrn; + + if (!xkb) + return BadMatch; + rtrn= XkbAllocClientMap(xkb,XkbKeyTypesMask,XkbNumRequiredTypes); + if (rtrn!=Success) + return rtrn; + map= xkb->map; + if ((which&XkbAllRequiredTypes)==0) + return Success; + rtrn= Success; + from= canonicalTypes; + to= map->types; + if (which&XkbOneLevelMask) + rtrn= XkbCopyKeyType(&from[XkbOneLevelIndex],&to[XkbOneLevelIndex]); + if ((which&XkbTwoLevelMask)&&(rtrn==Success)) + rtrn= XkbCopyKeyType(&from[XkbTwoLevelIndex],&to[XkbTwoLevelIndex]); + if ((which&XkbAlphabeticMask)&&(rtrn==Success)) + rtrn= XkbCopyKeyType(&from[XkbAlphabeticIndex],&to[XkbAlphabeticIndex]); + if ((which&XkbKeypadMask)&&(rtrn==Success)) { + XkbKeyTypePtr type; + rtrn= XkbCopyKeyType(&from[XkbKeypadIndex],&to[XkbKeypadIndex]); + type= &to[XkbKeypadIndex]; + if ((keypadVMod>=0)&&(keypadVMod<XkbNumVirtualMods)&&(rtrn==Success)) { + type->mods.vmods= (1<<keypadVMod); + type->map[0].active= True; + type->map[0].mods.mask= ShiftMask; + type->map[0].mods.real_mods= ShiftMask; + type->map[0].mods.vmods= 0; + type->map[0].level= 1; + type->map[1].active= False; + type->map[1].mods.mask= 0; + type->map[1].mods.real_mods= 0; + type->map[1].mods.vmods= (1<<keypadVMod); + type->map[1].level= 1; + } + } + return Success; +} + +/***====================================================================***/ + +#define CORE_SYM(i) (i<map_width?core_syms[i]:NoSymbol) +#define XKB_OFFSET(g,l) (((g)*groupsWidth)+(l)) + +int +XkbKeyTypesForCoreSymbols( XkbDescPtr xkb, + int map_width, + KeySym * core_syms, + unsigned int protected, + int * types_inout, + KeySym * xkb_syms_rtrn) +{ +register int i; +unsigned int empty; +int nSyms[XkbNumKbdGroups]; +int nGroups,tmp,groupsWidth; + + /* Section 12.2 of the protocol describes this process in more detail */ + /* Step 1: find the # of symbols in the core mapping per group */ + groupsWidth= 2; + for (i=0;i<XkbNumKbdGroups;i++) { + if ((protected&(1<<i))&&(types_inout[i]<xkb->map->num_types)) { + nSyms[i]= xkb->map->types[types_inout[i]].num_levels; + if (nSyms[i]>groupsWidth) + groupsWidth= nSyms[i]; + } + else { + types_inout[i]= XkbTwoLevelIndex; /* don't really know, yet */ + nSyms[i]= 2; + } + } + if (nSyms[XkbGroup1Index]<2) + nSyms[XkbGroup1Index]= 2; + if (nSyms[XkbGroup2Index]<2) + nSyms[XkbGroup2Index]= 2; + /* Step 2: Copy the symbols from the core ordering to XKB ordering */ + /* symbols in the core are in the order: */ + /* G1L1 G1L2 G2L1 G2L2 [G1L[3-n]] [G2L[3-n]] [G3L*] [G3L*] */ + xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,0)]= CORE_SYM(0); + xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,1)]= CORE_SYM(1); + for (i=2;i<nSyms[XkbGroup1Index];i++) { + xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,i)]= CORE_SYM(2+i); + } + xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,0)]= CORE_SYM(2); + xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,1)]= CORE_SYM(3); + tmp= 2+(nSyms[XkbGroup1Index]-2); /* offset to extra group2 syms */ + for (i=2;i<nSyms[XkbGroup2Index];i++) { + xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,i)]= CORE_SYM(tmp+i); + } + tmp= nSyms[XkbGroup1Index]+nSyms[XkbGroup2Index]; + if ((tmp>=map_width)&& + ((protected&(XkbExplicitKeyType3Mask|XkbExplicitKeyType4Mask))==0)) { + nSyms[XkbGroup3Index]= 0; + nSyms[XkbGroup4Index]= 0; + nGroups= 2; + } + else { + nGroups= 3; + for (i=0;i<nSyms[XkbGroup3Index];i++,tmp++) { + xkb_syms_rtrn[XKB_OFFSET(XkbGroup3Index,i)]= CORE_SYM(tmp); + } + if ((tmp<map_width)||(protected&XkbExplicitKeyType4Mask)) { + nGroups= 4; + for (i=0;i<nSyms[XkbGroup4Index];i++,tmp++) { + xkb_syms_rtrn[XKB_OFFSET(XkbGroup4Index,i)]= CORE_SYM(tmp); + } + } + else { + nSyms[XkbGroup4Index]= 0; + } + } + /* steps 3&4: alphanumeric expansion, assign canonical types */ + empty= 0; + for (i=0;i<nGroups;i++) { + KeySym *syms; + syms= &xkb_syms_rtrn[XKB_OFFSET(i,0)]; + if ((nSyms[i]>1)&&(syms[1]==NoSymbol)&&(syms[0]!=NoSymbol)) { + KeySym upper,lower; + XConvertCase(syms[0],&lower,&upper); + if (upper!=lower) { + xkb_syms_rtrn[XKB_OFFSET(i,0)]= lower; + xkb_syms_rtrn[XKB_OFFSET(i,1)]= upper; + if ((protected&(1<<i))==0) + types_inout[i]= XkbAlphabeticIndex; + } + else if ((protected&(1<<i))==0) { + types_inout[i]= XkbOneLevelIndex; + /* nSyms[i]= 1;*/ + } + } + if (((protected&(1<<i))==0)&&(types_inout[i]==XkbTwoLevelIndex)) { + if (IsKeypadKey(syms[0])||IsKeypadKey(syms[1])) + types_inout[i]= XkbKeypadIndex; + else { + KeySym upper,lower; + XConvertCase(syms[0],&lower,&upper); + if ((syms[0]==lower)&&(syms[1]==upper)) + types_inout[i]= XkbAlphabeticIndex; + } + } + if (syms[0]==NoSymbol) { + register int n; + Bool found; + for (n=1,found=False;(!found)&&(n<nSyms[i]);n++) { + found= (syms[n]!=NoSymbol); + } + if (!found) + empty|= (1<<i); + } + } + /* step 5: squoosh out empty groups */ + if (empty) { + for (i=nGroups-1;i>=0;i--) { + if (((empty&(1<<i))==0)||(protected&(1<<i))) + break; + nGroups--; + } + } + if (nGroups<1) + return 0; + + /* step 6: replicate group 1 into group two, if necessary */ + if ((nGroups>1)&&((empty&(XkbGroup1Mask|XkbGroup2Mask))==XkbGroup2Mask)) { + if ((protected&(XkbExplicitKeyType1Mask|XkbExplicitKeyType2Mask))==0) { + nSyms[XkbGroup2Index]= nSyms[XkbGroup1Index]; + types_inout[XkbGroup2Index]= types_inout[XkbGroup1Index]; + memcpy((char *)&xkb_syms_rtrn[2],(char *)xkb_syms_rtrn, + 2*sizeof(KeySym)); + } + else if (types_inout[XkbGroup1Index]==types_inout[XkbGroup2Index]) { + memcpy((char *)&xkb_syms_rtrn[nSyms[XkbGroup1Index]], + (char *)xkb_syms_rtrn, + nSyms[XkbGroup1Index]*sizeof(KeySym)); + } + } + + /* step 7: check for all groups identical or all width 1 */ + if (nGroups>1) { + Bool sameType,allOneLevel; + allOneLevel= (xkb->map->types[types_inout[0]].num_levels==1); + for (i=1,sameType=True;(allOneLevel||sameType)&&(i<nGroups);i++) { + sameType=(sameType&&(types_inout[i]==types_inout[XkbGroup1Index])); + if (allOneLevel) + allOneLevel= (xkb->map->types[types_inout[i]].num_levels==1); + } + if ((sameType)&& + (!(protected&(XkbExplicitKeyTypesMask&~XkbExplicitKeyType1Mask)))){ + register int s; + Bool identical; + for (i=1,identical=True;identical&&(i<nGroups);i++) { + KeySym *syms; + syms= &xkb_syms_rtrn[XKB_OFFSET(i,0)]; + for (s=0;identical&&(s<nSyms[i]);s++) { + if (syms[s]!=xkb_syms_rtrn[s]) + identical= False; + } + } + if (identical) + nGroups= 1; + } + if (allOneLevel && (nGroups>1)) { + KeySym *syms; + syms= &xkb_syms_rtrn[nSyms[XkbGroup1Index]]; + nSyms[XkbGroup1Index]= 1; + for (i=1;i<nGroups;i++) { + xkb_syms_rtrn[i]= syms[0]; + syms+= nSyms[i]; + nSyms[i]= 1; + } + } + } + return nGroups; +} + +static XkbSymInterpretPtr +_XkbFindMatchingInterp( XkbDescPtr xkb, + KeySym sym, + unsigned int real_mods, + unsigned int level) +{ +register unsigned i; +XkbSymInterpretPtr interp,rtrn; +CARD8 mods; + + rtrn= NULL; + interp= xkb->compat->sym_interpret; + for (i=0;i<xkb->compat->num_si;i++,interp++) { + if ((interp->sym==NoSymbol)||(sym==interp->sym)) { + int match; + if ((level==0)||((interp->match&XkbSI_LevelOneOnly)==0)) + mods= real_mods; + else mods= 0; + switch (interp->match&XkbSI_OpMask) { + case XkbSI_NoneOf: + match= ((interp->mods&mods)==0); + break; + case XkbSI_AnyOfOrNone: + match= ((mods==0)||((interp->mods&mods)!=0)); + break; + case XkbSI_AnyOf: + match= ((interp->mods&mods)!=0); + break; + case XkbSI_AllOf: + match= ((interp->mods&mods)==interp->mods); + break; + case XkbSI_Exactly: + match= (interp->mods==mods); + break; + default: + match= 0; + break; + } + if (match) { + if (interp->sym!=NoSymbol) { + return interp; + } + else if (rtrn==NULL) { + rtrn= interp; + } + } + } + } + return rtrn; +} + +static void +_XkbAddKeyChange(KeyCode *pFirst,unsigned char *pNum,KeyCode newKey) +{ +KeyCode last; + + last= (*pFirst)+(*pNum); + if (newKey<*pFirst) { + *pFirst= newKey; + *pNum= (last-newKey)+1; + } + else if (newKey>last) { + *pNum= (last-*pFirst)+1; + } + return; +} + +static void +_XkbSetActionKeyMods(XkbDescPtr xkb,XkbAction *act,unsigned mods) +{ +unsigned tmp; + + switch (act->type) { + case XkbSA_SetMods: case XkbSA_LatchMods: case XkbSA_LockMods: + if (act->mods.flags&XkbSA_UseModMapMods) + act->mods.real_mods= act->mods.mask= mods; + if ((tmp= XkbModActionVMods(&act->mods))!=0) { + XkbVirtualModsToReal(xkb,tmp,&tmp); + act->mods.mask|= tmp; + } + break; + case XkbSA_ISOLock: + if (act->iso.flags&XkbSA_UseModMapMods) + act->iso.real_mods= act->iso.mask= mods; + if ((tmp= XkbModActionVMods(&act->iso))!=0) { + XkbVirtualModsToReal(xkb,tmp,&tmp); + act->iso.mask|= tmp; + } + break; + } + return; +} + +#define IBUF_SIZE 8 + +Bool +XkbApplyCompatMapToKey(XkbDescPtr xkb,KeyCode key,XkbChangesPtr changes) +{ +KeySym * syms; +unsigned char explicit,mods; +XkbSymInterpretPtr *interps,ibuf[IBUF_SIZE]; +int n,nSyms,found; +unsigned changed,tmp; + + if ((!xkb)||(!xkb->map)||(!xkb->map->key_sym_map)|| + (!xkb->compat)||(!xkb->compat->sym_interpret)|| + (key<xkb->min_key_code)||(key>xkb->max_key_code)) { + return False; + } + if (((!xkb->server)||(!xkb->server->key_acts))&& + (XkbAllocServerMap(xkb,XkbAllServerInfoMask,0)!=Success)) { + return False; + } + changed= 0; /* keeps track of what has changed in _this_ call */ + explicit= xkb->server->explicit[key]; + if (explicit&XkbExplicitInterpretMask) /* nothing to do */ + return True; + mods= (xkb->map->modmap?xkb->map->modmap[key]:0); + nSyms= XkbKeyNumSyms(xkb,key); + syms= XkbKeySymsPtr(xkb,key); + if (nSyms>IBUF_SIZE) { + interps= _XkbTypedCalloc(nSyms,XkbSymInterpretPtr); + if (interps==NULL) { + interps= ibuf; + nSyms= IBUF_SIZE; + } + } + else { + interps= ibuf; + } + found= 0; + for (n=0;n<nSyms;n++) { + unsigned level= (n%XkbKeyGroupsWidth(xkb,key)); + interps[n]= NULL; + if (syms[n]!=NoSymbol) { + interps[n]= _XkbFindMatchingInterp(xkb,syms[n],mods,level); + if (interps[n]&&interps[n]->act.type!=XkbSA_NoAction) + found++; + else interps[n]= NULL; + } + } + /* 1/28/96 (ef) -- XXX! WORKING HERE */ + if (!found) { + if (xkb->server->key_acts[key]!=0) { + xkb->server->key_acts[key]= 0; + changed|= XkbKeyActionsMask; + } + } + else { + XkbAction *pActs; + unsigned int new_vmodmask; + changed|= XkbKeyActionsMask; + pActs= XkbResizeKeyActions(xkb,key,nSyms); + if (!pActs) { + if (nSyms > IBUF_SIZE) + Xfree(interps); + return False; + } + new_vmodmask= 0; + for (n=0;n<nSyms;n++) { + if (interps[n]) { + unsigned effMods; + + pActs[n]= *((XkbAction *)&interps[n]->act); + if ((n==0)||((interps[n]->match&XkbSI_LevelOneOnly)==0)) { + effMods= mods; + if (interps[n]->virtual_mod!=XkbNoModifier) + new_vmodmask|= (1<<interps[n]->virtual_mod); + } + else effMods= 0; + _XkbSetActionKeyMods(xkb,&pActs[n],effMods); + } + else pActs[n].type= XkbSA_NoAction; + } + if (((explicit&XkbExplicitVModMapMask)==0)&& + (xkb->server->vmodmap[key]!=new_vmodmask)) { + changed|= XkbVirtualModMapMask; + xkb->server->vmodmap[key]= new_vmodmask; + } + if (interps[0]) { + if ((interps[0]->flags&XkbSI_LockingKey)&& + ((explicit&XkbExplicitBehaviorMask)==0)) { + xkb->server->behaviors[key].type= XkbKB_Lock; + changed|= XkbKeyBehaviorsMask; + } + if (((explicit&XkbExplicitAutoRepeatMask)==0)&&(xkb->ctrls)) { + CARD8 old; + old= xkb->ctrls->per_key_repeat[key/8]; + if (interps[0]->flags&XkbSI_AutoRepeat) + xkb->ctrls->per_key_repeat[key/8]|= (1<<(key%8)); + else xkb->ctrls->per_key_repeat[key/8]&= ~(1<<(key%8)); + if (changes && (old!=xkb->ctrls->per_key_repeat[key/8])) + changes->ctrls.changed_ctrls|= XkbPerKeyRepeatMask; + } + } + } + if ((!found)||(interps[0]==NULL)) { + if (((explicit&XkbExplicitAutoRepeatMask)==0)&&(xkb->ctrls)) { + CARD8 old; + old= xkb->ctrls->per_key_repeat[key/8]; +#ifdef RETURN_SHOULD_REPEAT + if (*XkbKeySymsPtr(xkb,key) != XK_Return) +#endif + xkb->ctrls->per_key_repeat[key/8]|= (1<<(key%8)); + if (changes && (old!=xkb->ctrls->per_key_repeat[key/8])) + changes->ctrls.changed_ctrls|= XkbPerKeyRepeatMask; + } + if (((explicit&XkbExplicitBehaviorMask)==0)&& + (xkb->server->behaviors[key].type==XkbKB_Lock)) { + xkb->server->behaviors[key].type= XkbKB_Default; + changed|= XkbKeyBehaviorsMask; + } + } + if (changes) { + XkbMapChangesPtr mc; + mc= &changes->map; + tmp= (changed&mc->changed); + if (tmp&XkbKeyActionsMask) + _XkbAddKeyChange(&mc->first_key_act,&mc->num_key_acts,key); + else if (changed&XkbKeyActionsMask) { + mc->changed|= XkbKeyActionsMask; + mc->first_key_act= key; + mc->num_key_acts= 1; + } + if (tmp&XkbKeyBehaviorsMask) { + _XkbAddKeyChange(&mc->first_key_behavior,&mc->num_key_behaviors, + key); + } + else if (changed&XkbKeyBehaviorsMask) { + mc->changed|= XkbKeyBehaviorsMask; + mc->first_key_behavior= key; + mc->num_key_behaviors= 1; + } + if (tmp&XkbVirtualModMapMask) + _XkbAddKeyChange(&mc->first_vmodmap_key,&mc->num_vmodmap_keys,key); + else if (changed&XkbVirtualModMapMask) { + mc->changed|= XkbVirtualModMapMask; + mc->first_vmodmap_key= key; + mc->num_vmodmap_keys= 1; + } + mc->changed|= changed; + } + if (interps!=ibuf) + _XkbFree(interps); + return True; +} + +Bool +XkbUpdateMapFromCore( XkbDescPtr xkb, + KeyCode first_key, + int num_keys, + int map_width, + KeySym * core_keysyms, + XkbChangesPtr changes) +{ +register int key,last_key; +KeySym * syms; + + syms= &core_keysyms[(first_key-xkb->min_key_code)*map_width]; + if (changes) { + if (changes->map.changed&XkbKeySymsMask) { + _XkbAddKeyChange(&changes->map.first_key_sym, + &changes->map.num_key_syms,first_key); + if (num_keys>1) { + _XkbAddKeyChange(&changes->map.first_key_sym, + &changes->map.num_key_syms, + first_key+num_keys-1); + } + } + else { + changes->map.changed|= XkbKeySymsMask; + changes->map.first_key_sym= first_key; + changes->map.num_key_syms= num_keys; + } + } + last_key= first_key+num_keys-1; + for (key=first_key;key<=last_key;key++,syms+= map_width) { + XkbMapChangesPtr mc; + unsigned explicit; + KeySym tsyms[XkbMaxSymsPerKey]; + int types[XkbNumKbdGroups]; + int nG; + + explicit= xkb->server->explicit[key]&XkbExplicitKeyTypesMask; + types[XkbGroup1Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup1Index); + types[XkbGroup2Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup2Index); + types[XkbGroup3Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup3Index); + types[XkbGroup4Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup4Index); + nG= XkbKeyTypesForCoreSymbols(xkb,map_width,syms,explicit,types,tsyms); + if (changes) + mc= &changes->map; + else mc= NULL; + XkbChangeTypesOfKey(xkb,key,nG,XkbAllGroupsMask,types,mc); + memcpy((char *)XkbKeySymsPtr(xkb,key),(char *)tsyms, + XkbKeyNumSyms(xkb,key)*sizeof(KeySym)); + XkbApplyCompatMapToKey(xkb,key,changes); + } + + if ((xkb->map->modmap!=NULL)&&(changes)&& + (changes->map.changed&(XkbVirtualModMapMask|XkbModifierMapMask))) { + unsigned char newVMods[XkbNumVirtualMods]; + register unsigned bit,i; + unsigned present; + + bzero(newVMods,XkbNumVirtualMods); + present= 0; + for (key=xkb->min_key_code;key<=xkb->max_key_code;key++) { + if (xkb->server->vmodmap[key]==0) + continue; + for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { + if (bit&xkb->server->vmodmap[key]) { + present|= bit; + newVMods[i]|= xkb->map->modmap[key]; + } + } + } + for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { + if ((bit&present)&&(newVMods[i]!=xkb->server->vmods[i])) { + changes->map.changed|= XkbVirtualModsMask; + changes->map.vmods|= bit; + xkb->server->vmods[i]= newVMods[i]; + } + } + } + if (changes && (changes->map.changed&XkbVirtualModsMask)) + XkbApplyVirtualModChanges(xkb,changes->map.vmods,changes); + return True; +} + +Status +XkbChangeTypesOfKey( XkbDescPtr xkb, + int key, + int nGroups, + unsigned groups, + int * newTypesIn, + XkbMapChangesPtr changes) +{ +XkbKeyTypePtr pOldType,pNewType; +register int i; +int width,nOldGroups,oldWidth,newTypes[XkbNumKbdGroups]; + + if ((!xkb) || (!XkbKeycodeInRange(xkb,key)) || (!xkb->map) || + (!xkb->map->types)||((groups&XkbAllGroupsMask)==0)|| + (nGroups>XkbNumKbdGroups)) { + return BadMatch; + } + if (nGroups==0) { + for (i=0;i<XkbNumKbdGroups;i++) { + xkb->map->key_sym_map[key].kt_index[i]= XkbOneLevelIndex; + } + i= xkb->map->key_sym_map[key].group_info; + i= XkbSetNumGroups(i,0); + xkb->map->key_sym_map[key].group_info= i; + XkbResizeKeySyms(xkb,key,0); + return Success; + } + + nOldGroups= XkbKeyNumGroups(xkb,key); + oldWidth= XkbKeyGroupsWidth(xkb,key); + for (width=i=0;i<nGroups;i++) { + if (groups&(1<<i)) + newTypes[i]= newTypesIn[i]; + else if (i<nOldGroups) + newTypes[i]= XkbKeyKeyTypeIndex(xkb,key,i); + else if (nOldGroups>0) + newTypes[i]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup1Index); + else newTypes[i]= XkbTwoLevelIndex; + if (newTypes[i]>xkb->map->num_types) + return BadMatch; + pNewType= &xkb->map->types[newTypes[i]]; + if (pNewType->num_levels>width) + width= pNewType->num_levels; + } + if ((xkb->ctrls)&&(nGroups>xkb->ctrls->num_groups)) + xkb->ctrls->num_groups= nGroups; + if ((width!=oldWidth)||(nGroups!=nOldGroups)) { + KeySym oldSyms[XkbMaxSymsPerKey],*pSyms; + int nCopy; + + if (nOldGroups==0) { + pSyms= XkbResizeKeySyms(xkb,key,width*nGroups); + if (pSyms!=NULL) { + i= xkb->map->key_sym_map[key].group_info; + i= XkbSetNumGroups(i,nGroups); + xkb->map->key_sym_map[key].group_info= i; + xkb->map->key_sym_map[key].width= width; + for (i=0;i<nGroups;i++) { + xkb->map->key_sym_map[key].kt_index[i]= newTypes[i]; + } + return Success; + } + return BadAlloc; + } + pSyms= XkbKeySymsPtr(xkb,key); + memcpy(oldSyms,pSyms,XkbKeyNumSyms(xkb,key)*sizeof(KeySym)); + pSyms= XkbResizeKeySyms(xkb,key,width*nGroups); + if (pSyms==NULL) + return BadAlloc; + bzero(pSyms,width*nGroups*sizeof(KeySym)); + for (i=0;(i<nGroups)&&(i<nOldGroups);i++) { + pOldType= XkbKeyKeyType(xkb,key,i); + pNewType= &xkb->map->types[newTypes[i]]; + if (pNewType->num_levels>pOldType->num_levels) + nCopy= pOldType->num_levels; + else nCopy= pNewType->num_levels; + memcpy(&pSyms[i*width],&oldSyms[i*oldWidth],nCopy*sizeof(KeySym)); + } + if (XkbKeyHasActions(xkb,key)) { + XkbAction oldActs[XkbMaxSymsPerKey],*pActs; + pActs= XkbKeyActionsPtr(xkb,key); + memcpy(oldActs,pActs,XkbKeyNumSyms(xkb,key)*sizeof(XkbAction)); + pActs= XkbResizeKeyActions(xkb,key,width*nGroups); + if (pActs==NULL) + return BadAlloc; + bzero(pActs,width*nGroups*sizeof(XkbAction)); + for (i=0;(i<nGroups)&&(i<nOldGroups);i++) { + pOldType= XkbKeyKeyType(xkb,key,i); + pNewType= &xkb->map->types[newTypes[i]]; + if (pNewType->num_levels>pOldType->num_levels) + nCopy= pOldType->num_levels; + else nCopy= pNewType->num_levels; + memcpy(&pActs[i*width],&oldActs[i*oldWidth], + nCopy*sizeof(XkbAction)); + } + } + i= xkb->map->key_sym_map[key].group_info; + i= XkbSetNumGroups(i,nGroups); + xkb->map->key_sym_map[key].group_info= i; + xkb->map->key_sym_map[key].width= width; + } + width= 0; + for (i=0;i<nGroups;i++) { + xkb->map->key_sym_map[key].kt_index[i]= newTypes[i]; + if (xkb->map->types[newTypes[i]].num_levels>width) + width= xkb->map->types[newTypes[i]].num_levels; + } + xkb->map->key_sym_map[key].width= width; + if (changes!=NULL) { + if (changes->changed&XkbKeySymsMask) { + _XkbAddKeyChange(&changes->first_key_sym,&changes->num_key_syms, + key); + } + else { + changes->changed|= XkbKeySymsMask; + changes->first_key_sym= key; + changes->num_key_syms= 1; + } + } + return Success; +} + +/***====================================================================***/ + +Bool +XkbVirtualModsToReal(XkbDescPtr xkb,unsigned virtual_mask,unsigned *mask_rtrn) +{ +register int i,bit; +register unsigned mask; + + if (xkb==NULL) + return False; + if (virtual_mask==0) { + *mask_rtrn= 0; + return True; + } + if (xkb->server==NULL) + return False; + for (i=mask=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { + if (virtual_mask&bit) + mask|= xkb->server->vmods[i]; + } + *mask_rtrn= mask; + return True; +} + +/***====================================================================***/ + +Bool +XkbUpdateActionVirtualMods(XkbDescPtr xkb,XkbAction *act,unsigned changed) +{ +unsigned int tmp; + + switch (act->type) { + case XkbSA_SetMods: case XkbSA_LatchMods: case XkbSA_LockMods: + if (((tmp= XkbModActionVMods(&act->mods))&changed)!=0) { + XkbVirtualModsToReal(xkb,tmp,&tmp); + act->mods.mask= act->mods.real_mods; + act->mods.mask|= tmp; + return True; + } + break; + case XkbSA_ISOLock: + if ((((tmp= XkbModActionVMods(&act->iso))!=0)&changed)!=0) { + XkbVirtualModsToReal(xkb,tmp,&tmp); + act->iso.mask= act->iso.real_mods; + act->iso.mask|= tmp; + return True; + } + break; + } + return False; +} + +void +XkbUpdateKeyTypeVirtualMods( XkbDescPtr xkb, + XkbKeyTypePtr type, + unsigned int changed, + XkbChangesPtr changes) +{ +register unsigned int i; +unsigned int mask; + + XkbVirtualModsToReal(xkb,type->mods.vmods,&mask); + type->mods.mask= type->mods.real_mods|mask; + if ((type->map_count>0)&&(type->mods.vmods!=0)) { + XkbKTMapEntryPtr entry; + for (i=0,entry=type->map;i<type->map_count;i++,entry++) { + if (entry->mods.vmods!=0) { + XkbVirtualModsToReal(xkb,entry->mods.vmods,&mask); + entry->mods.mask=entry->mods.real_mods|mask; + /* entry is active if vmods are bound*/ + entry->active= (mask!=0); + } + else entry->active= 1; + } + } + if (changes) { + int type_ndx; + type_ndx= type-xkb->map->types; + if ((type_ndx<0)||(type_ndx>xkb->map->num_types)) + return; + if (changes->map.changed&XkbKeyTypesMask) { + int last; + last= changes->map.first_type+changes->map.num_types-1; + if (type_ndx<changes->map.first_type) { + changes->map.first_type= type_ndx; + changes->map.num_types= (last-type_ndx)+1; + } + else if (type_ndx>last) { + changes->map.num_types= (type_ndx-changes->map.first_type)+1; + } + } + else { + changes->map.changed|= XkbKeyTypesMask; + changes->map.first_type= type_ndx; + changes->map.num_types= 1; + } + } + return; +} + +Bool +XkbApplyVirtualModChanges(XkbDescPtr xkb,unsigned changed,XkbChangesPtr changes) +{ +register int i; +unsigned int checkState = 0; + + if ((!xkb) || (!xkb->map) || (changed==0)) + return False; + for (i=0;i<xkb->map->num_types;i++) { + if (xkb->map->types[i].mods.vmods & changed) + XkbUpdateKeyTypeVirtualMods(xkb,&xkb->map->types[i],changed,changes); + } + if (changed&xkb->ctrls->internal.vmods) { + unsigned int newMask; + XkbVirtualModsToReal(xkb,xkb->ctrls->internal.vmods,&newMask); + newMask|= xkb->ctrls->internal.real_mods; + if (xkb->ctrls->internal.mask!=newMask) { + xkb->ctrls->internal.mask= newMask; + if (changes) { + changes->ctrls.changed_ctrls|= XkbInternalModsMask; + checkState= True; + } + } + } + if (changed&xkb->ctrls->ignore_lock.vmods) { + unsigned int newMask; + XkbVirtualModsToReal(xkb,xkb->ctrls->ignore_lock.vmods,&newMask); + newMask|= xkb->ctrls->ignore_lock.real_mods; + if (xkb->ctrls->ignore_lock.mask!=newMask) { + xkb->ctrls->ignore_lock.mask= newMask; + if (changes) { + changes->ctrls.changed_ctrls|= XkbIgnoreLockModsMask; + checkState= True; + } + } + } + if (xkb->indicators!=NULL) { + XkbIndicatorMapPtr map; + map= &xkb->indicators->maps[0]; + for (i=0;i<XkbNumIndicators;i++,map++) { + if (map->mods.vmods&changed) { + unsigned int newMask; + XkbVirtualModsToReal(xkb,map->mods.vmods,&newMask); + newMask|= map->mods.real_mods; + if (newMask!=map->mods.mask) { + map->mods.mask= newMask; + if (changes) { + changes->indicators.map_changes|= (1<<i); + checkState= True; + } + } + } + } + } + if (xkb->compat!=NULL) { + XkbCompatMapPtr compat; + compat= xkb->compat; + for (i=0;i<XkbNumKbdGroups;i++) { + unsigned int newMask; + XkbVirtualModsToReal(xkb,compat->groups[i].vmods,&newMask); + newMask|= compat->groups[i].real_mods; + if (compat->groups[i].mask!=newMask) { + compat->groups[i].mask= newMask; + if (changes) { + changes->compat.changed_groups|= (1<<i); + checkState= True; + } + } + } + } + if (xkb->map && xkb->server) { + int highChange = 0, lowChange = -1; + for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { + if (XkbKeyHasActions(xkb,i)) { + register XkbAction *pAct; + register int n; + + pAct= XkbKeyActionsPtr(xkb,i); + for (n=XkbKeyNumActions(xkb,i);n>0;n--,pAct++) { + if ((pAct->type!=XkbSA_NoAction)&& + XkbUpdateActionVirtualMods(xkb,pAct,changed)) { + if (lowChange<0) + lowChange= i; + highChange= i; + } + } + } + } + if (changes && (lowChange>0)) { /* something changed */ + if (changes->map.changed&XkbKeyActionsMask) { + int last; + if (changes->map.first_key_act<lowChange) + lowChange= changes->map.first_key_act; + last= changes->map.first_key_act+changes->map.num_key_acts-1; + if (last>highChange) + highChange= last; + } + changes->map.changed|= XkbKeyActionsMask; + changes->map.first_key_act= lowChange; + changes->map.num_key_acts= (highChange-lowChange)+1; + } + } + return checkState; +} |