summaryrefslogtreecommitdiff
path: root/src/x11/async-getprop.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/x11/async-getprop.c')
-rw-r--r--src/x11/async-getprop.c680
1 files changed, 0 insertions, 680 deletions
diff --git a/src/x11/async-getprop.c b/src/x11/async-getprop.c
deleted file mode 100644
index 72fe0d3b7..000000000
--- a/src/x11/async-getprop.c
+++ /dev/null
@@ -1,680 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/* Asynchronous X property getting hack */
-
-/*
- * Copyright (C) 2002 Havoc Pennington
- * Copyright (C) 1986, 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.
- */
-
-#include <assert.h>
-
-#undef DEBUG_SPEW
-#ifdef DEBUG_SPEW
-#include <stdio.h>
-#endif
-
-#include "async-getprop.h"
-
-#define NEED_REPLIES
-#include <X11/Xlibint.h>
-
-#ifndef NULL
-#define NULL ((void*)0)
-#endif
-
-typedef struct _ListNode ListNode;
-typedef struct _AgPerDisplayData AgPerDisplayData;
-
-struct _ListNode
-{
- ListNode *next;
-};
-
-struct _AgGetPropertyTask
-{
- ListNode node;
-
- AgPerDisplayData *dd;
- Window window;
- Atom property;
-
- unsigned long request_seq;
- int error;
-
- Atom actual_type;
- int actual_format;
-
- unsigned long n_items;
- unsigned long bytes_after;
- char *data;
-
- Bool have_reply;
-};
-
-struct _AgPerDisplayData
-{
- ListNode node;
- _XAsyncHandler async;
-
- Display *display;
- ListNode *pending_tasks;
- ListNode *pending_tasks_tail;
- ListNode *completed_tasks;
- ListNode *completed_tasks_tail;
- int n_tasks_pending;
- int n_tasks_completed;
-};
-
-static ListNode *display_datas = NULL;
-static ListNode *display_datas_tail = NULL;
-
-static void
-append_to_list (ListNode **head,
- ListNode **tail,
- ListNode *task)
-{
- task->next = NULL;
-
- if (*tail == NULL)
- {
- assert (*head == NULL);
- *head = task;
- *tail = task;
- }
- else
- {
- (*tail)->next = task;
- *tail = task;
- }
-}
-
-static void
-remove_from_list (ListNode **head,
- ListNode **tail,
- ListNode *task)
-{
- ListNode *prev;
- ListNode *node;
-
- prev = NULL;
- node = *head;
- while (node != NULL)
- {
- if (node == task)
- {
- if (prev)
- prev->next = node->next;
- else
- *head = node->next;
-
- if (node == *tail)
- *tail = prev;
-
- break;
- }
-
- prev = node;
- node = node->next;
- }
-
- /* can't remove what's not there */
- assert (node != NULL);
-
- node->next = NULL;
-}
-
-static void
-move_to_completed (AgPerDisplayData *dd,
- AgGetPropertyTask *task)
-{
- remove_from_list (&dd->pending_tasks,
- &dd->pending_tasks_tail,
- &task->node);
-
- append_to_list (&dd->completed_tasks,
- &dd->completed_tasks_tail,
- &task->node);
-
- dd->n_tasks_pending -= 1;
- dd->n_tasks_completed += 1;
-}
-
-static AgGetPropertyTask*
-find_pending_by_request_sequence (AgPerDisplayData *dd,
- unsigned long request_seq)
-{
- ListNode *node;
-
- /* if the sequence is after our last pending task, we
- * aren't going to find a match
- */
- {
- AgGetPropertyTask *task = (AgGetPropertyTask*) dd->pending_tasks_tail;
- if (task != NULL)
- {
- if (task->request_seq < request_seq)
- return NULL;
- else if (task->request_seq == request_seq)
- return task; /* why not check this */
- }
- }
-
- /* Generally we should get replies in the order we sent
- * requests, so we should usually be using the task
- * at the head of the list, if we use any task at all.
- * I'm not sure this is 100% guaranteed, if it is,
- * it would be a big speedup.
- */
-
- node = dd->pending_tasks;
- while (node != NULL)
- {
- AgGetPropertyTask *task = (AgGetPropertyTask*) node;
-
- if (task->request_seq == request_seq)
- return task;
-
- node = node->next;
- }
-
- return NULL;
-}
-
-static Bool
-async_get_property_handler (Display *dpy,
- xReply *rep,
- char *buf,
- int len,
- XPointer data)
-{
- xGetPropertyReply replbuf;
- xGetPropertyReply *reply;
- AgGetPropertyTask *task;
- AgPerDisplayData *dd;
- int bytes_read;
-
- dd = (AgPerDisplayData*) data;
-
-#if 0
- printf ("%s: seeing request seq %ld buflen %d\n", __FUNCTION__,
- dpy->last_request_read, len);
-#endif
-
- task = find_pending_by_request_sequence (dd, dpy->last_request_read);
-
- if (task == NULL)
- return False;
-
- assert (dpy->last_request_read == task->request_seq);
-
- task->have_reply = True;
- move_to_completed (dd, task);
-
- /* read bytes so far */
- bytes_read = SIZEOF (xReply);
-
- if (rep->generic.type == X_Error)
- {
- xError errbuf;
-
- task->error = rep->error.errorCode;
-
-#ifdef DEBUG_SPEW
- printf ("%s: error code = %d (ignoring error, eating %d bytes, generic.length = %ld)\n",
- __FUNCTION__, task->error, (SIZEOF (xError) - bytes_read),
- rep->generic.length);
-#endif
-
- /* We return True (meaning we consumed the reply)
- * because otherwise it would invoke the X error handler,
- * and an async API is useless if you have to synchronously
- * trap X errors. Also GetProperty can always fail, pretty
- * much, so trapping errors is always what you want.
- *
- * We have to eat all the error reply data here.
- * (kind of a charade as we know sizeof(xError) == sizeof(xReply))
- *
- * Passing discard = True seems to break things; I don't understand
- * why, because there should be no extra data in an error reply,
- * right?
- */
- _XGetAsyncReply (dpy, (char *)&errbuf, rep, buf, len,
- (SIZEOF (xError) - bytes_read) >> 2, /* in 32-bit words */
- False); /* really seems like it should be True */
-
- return True;
- }
-
-#ifdef DEBUG_SPEW
- printf ("%s: already read %d bytes reading %d more for total of %d; generic.length = %ld\n",
- __FUNCTION__, bytes_read, (SIZEOF (xGetPropertyReply) - bytes_read) >> 2,
- SIZEOF (xGetPropertyReply), rep->generic.length);
-#endif
-
- /* (kind of a silly as we know sizeof(xGetPropertyReply) == sizeof(xReply)) */
- reply = (xGetPropertyReply *)
- _XGetAsyncReply (dpy, (char *)&replbuf, rep, buf, len,
- (SIZEOF (xGetPropertyReply) - bytes_read) >> 2, /* in 32-bit words */
- False); /* False means expecting more data to follow,
- * don't eat the rest of the reply
- */
-
- bytes_read = SIZEOF (xGetPropertyReply);
-
-#ifdef DEBUG_SPEW
- printf ("%s: have reply propertyType = %ld format = %d n_items = %ld\n",
- __FUNCTION__, reply->propertyType, reply->format, reply->nItems);
-#endif
-
- assert (task->data == NULL);
-
- /* This is all copied from XGetWindowProperty(). Not sure we should
- * LockDisplay(). Not sure I'm passing the right args to
- * XGetAsyncData(). Not sure about a lot of things.
- */
-
- /* LockDisplay (dpy); */
-
- if (reply->propertyType != None)
- {
- long nbytes, netbytes;
-
- /* this alignment macro from orbit2 */
-#define ALIGN_VALUE(this, boundary) \
- (( ((unsigned long)(this)) + (((unsigned long)(boundary)) -1)) & (~(((unsigned long)(boundary))-1)))
-
- switch (reply->format)
- {
- /*
- * One extra byte is malloced than is needed to contain the property
- * data, but this last byte is null terminated and convenient for
- * returning string properties, so the client doesn't then have to
- * recopy the string to make it null terminated.
- */
- case 8:
- nbytes = reply->nItems;
- /* there's padding to word boundary */
- netbytes = ALIGN_VALUE (nbytes, 4);
- if (nbytes + 1 > 0 &&
- (task->data = (char *) Xmalloc ((unsigned)nbytes + 1)))
- {
-#ifdef DEBUG_SPEW
- printf ("%s: already read %d bytes using %ld, more eating %ld more\n",
- __FUNCTION__, bytes_read, nbytes, netbytes);
-#endif
- /* _XReadPad (dpy, (char *) task->data, netbytes); */
- _XGetAsyncData (dpy, task->data, buf, len,
- bytes_read, nbytes,
- netbytes);
- }
- break;
-
- case 16:
- nbytes = reply->nItems * sizeof (short);
- netbytes = reply->nItems << 1;
- netbytes = ALIGN_VALUE (netbytes, 4); /* align to word boundary */
- if (nbytes + 1 > 0 &&
- (task->data = (char *) Xmalloc ((unsigned)nbytes + 1)))
- {
-#ifdef DEBUG_SPEW
- printf ("%s: already read %d bytes using %ld more, eating %ld more\n",
- __FUNCTION__, bytes_read, nbytes, netbytes);
-#endif
- /* _XRead16Pad (dpy, (short *) task->data, netbytes); */
- _XGetAsyncData (dpy, task->data, buf, len,
- bytes_read, nbytes, netbytes);
- }
- break;
-
- case 32:
- /* NOTE buffer is in longs to match XGetWindowProperty() */
- nbytes = reply->nItems * sizeof (long);
- netbytes = reply->nItems << 2; /* wire size is always 32 bits though */
- if (nbytes + 1 > 0 &&
- (task->data = (char *) Xmalloc ((unsigned)nbytes + 1)))
- {
-#ifdef DEBUG_SPEW
- printf ("%s: already read %d bytes using %ld more, eating %ld more\n",
- __FUNCTION__, bytes_read, nbytes, netbytes);
-#endif
-
- /* We have to copy the XGetWindowProperty() crackrock
- * and get format 32 as long even on 64-bit platforms.
- */
- if (sizeof (long) == 8)
- {
- char *netdata;
- char *lptr;
- char *end_lptr;
-
- /* Store the 32-bit values in the end of the array */
- netdata = task->data + nbytes / 2;
-
- _XGetAsyncData (dpy, netdata, buf, len,
- bytes_read, netbytes,
- netbytes);
-
- /* Now move the 32-bit values to the front */
-
- lptr = task->data;
- end_lptr = task->data + nbytes;
- while (lptr != end_lptr)
- {
- *(long*) lptr = *(CARD32*) netdata;
- lptr += sizeof (long);
- netdata += sizeof (CARD32);
- }
- }
- else
- {
- /* Here the wire format matches our actual format */
- _XGetAsyncData (dpy, task->data, buf, len,
- bytes_read, netbytes,
- netbytes);
- }
- }
- break;
-
- default:
- /*
- * This part of the code should never be reached. If it is,
- * the server sent back a property with an invalid format.
- * This is a BadImplementation error.
- *
- * However this async GetProperty API doesn't report errors
- * via the standard X mechanism, so don't do anything about
- * it, other than store it in task->error.
- */
- {
-#if 0
- xError error;
-#endif
-
- task->error = BadImplementation;
-
-#if 0
- error.sequenceNumber = task->request_seq;
- error.type = X_Error;
- error.majorCode = X_GetProperty;
- error.minorCode = 0;
- error.errorCode = BadImplementation;
-
- _XError (dpy, &error);
-#endif
- }
-
- nbytes = netbytes = 0L;
- break;
- }
-
- if (task->data == NULL)
- {
- task->error = BadAlloc;
-
-#ifdef DEBUG_SPEW
- printf ("%s: already read %d bytes eating %ld\n",
- __FUNCTION__, bytes_read, netbytes);
-#endif
- /* _XEatData (dpy, (unsigned long) netbytes); */
- _XGetAsyncData (dpy, NULL, buf, len,
- bytes_read, 0, netbytes);
-
- /* UnlockDisplay (dpy); */
- return BadAlloc; /* not Success */
- }
-
- (task->data)[nbytes] = '\0';
- }
-
-#ifdef DEBUG_SPEW
- printf ("%s: have data\n", __FUNCTION__);
-#endif
-
- task->actual_type = reply->propertyType;
- task->actual_format = reply->format;
- task->n_items = reply->nItems;
- task->bytes_after = reply->bytesAfter;
-
- /* UnlockDisplay (dpy); */
-
- return True;
-}
-
-static AgPerDisplayData*
-get_display_data (Display *display,
- Bool create)
-{
- ListNode *node;
- AgPerDisplayData *dd;
-
- node = display_datas;
- while (node != NULL)
- {
- dd = (AgPerDisplayData*) node;
-
- if (dd->display == display)
- return dd;
-
- node = node->next;
- }
-
- if (!create)
- return NULL;
-
- dd = Xcalloc (1, sizeof (AgPerDisplayData));
- if (dd == NULL)
- return NULL;
-
- dd->display = display;
- dd->async.next = display->async_handlers;
- dd->async.handler = async_get_property_handler;
- dd->async.data = (XPointer) dd;
- dd->display->async_handlers = &dd->async;
-
- append_to_list (&display_datas,
- &display_datas_tail,
- &dd->node);
-
- return dd;
-}
-
-static void
-maybe_free_display_data (AgPerDisplayData *dd)
-{
- if (dd->pending_tasks == NULL &&
- dd->completed_tasks == NULL)
- {
- DeqAsyncHandler (dd->display, &dd->async);
- remove_from_list (&display_datas, &display_datas_tail,
- &dd->node);
- XFree (dd);
- }
-}
-
-AgGetPropertyTask*
-ag_task_create (Display *dpy,
- Window window,
- Atom property,
- long offset,
- long length,
- Bool delete,
- Atom req_type)
-{
- AgGetPropertyTask *task;
- xGetPropertyReq *req;
- AgPerDisplayData *dd;
-
- /* Fire up our request */
- LockDisplay (dpy);
-
- dd = get_display_data (dpy, True);
- if (dd == NULL)
- {
- UnlockDisplay (dpy);
- return NULL;
- }
-
- GetReq (GetProperty, req);
- req->window = window;
- req->property = property;
- req->type = req_type;
- req->delete = delete;
- req->longOffset = offset;
- req->longLength = length;
-
- /* Queue up our async task */
- task = Xcalloc (1, sizeof (AgGetPropertyTask));
- if (task == NULL)
- {
- UnlockDisplay (dpy);
- return NULL;
- }
-
- task->dd = dd;
- task->window = window;
- task->property = property;
- task->request_seq = dpy->request;
-
- append_to_list (&dd->pending_tasks,
- &dd->pending_tasks_tail,
- &task->node);
- dd->n_tasks_pending += 1;
-
- UnlockDisplay (dpy);
-
- SyncHandle ();
-
- return task;
-}
-
-static void
-free_task (AgGetPropertyTask *task)
-{
- remove_from_list (&task->dd->completed_tasks,
- &task->dd->completed_tasks_tail,
- &task->node);
- task->dd->n_tasks_completed -= 1;
- maybe_free_display_data (task->dd);
- XFree (task);
-}
-
-Status
-ag_task_get_reply_and_free (AgGetPropertyTask *task,
- Atom *actual_type,
- int *actual_format,
- unsigned long *nitems,
- unsigned long *bytesafter,
- unsigned char **prop)
-{
- Display *dpy;
-
- *prop = NULL;
-
- dpy = task->dd->display; /* Xlib macros require a variable named "dpy" */
-
- if (task->error != Success)
- {
- Status s = task->error;
-
- free_task (task);
-
- return s;
- }
-
- if (!task->have_reply)
- {
- free_task (task);
-
- return BadAlloc; /* not Success */
- }
-
- *actual_type = task->actual_type;
- *actual_format = task->actual_format;
- *nitems = task->n_items;
- *bytesafter = task->bytes_after;
-
- *prop = (unsigned char*) task->data; /* pass out ownership of task->data */
-
- SyncHandle ();
-
- free_task (task);
-
- return Success;
-}
-
-Bool
-ag_task_have_reply (AgGetPropertyTask *task)
-{
- return task->have_reply;
-}
-
-Atom
-ag_task_get_property (AgGetPropertyTask *task)
-{
- return task->property;
-}
-
-Window
-ag_task_get_window (AgGetPropertyTask *task)
-{
- return task->window;
-}
-
-Display*
-ag_task_get_display (AgGetPropertyTask *task)
-{
- return task->dd->display;
-}
-
-AgGetPropertyTask*
-ag_get_next_completed_task (Display *display)
-{
- AgPerDisplayData *dd;
-
- dd = get_display_data (display, False);
-
- if (dd == NULL)
- return NULL;
-
-#ifdef DEBUG_SPEW
- printf ("%d pending %d completed\n",
- dd->n_tasks_pending,
- dd->n_tasks_completed);
-#endif
-
- return (AgGetPropertyTask*) dd->completed_tasks;
-}
-
-void*
-ag_Xmalloc (unsigned long bytes)
-{
- return (void*) Xmalloc (bytes);
-}
-
-void*
-ag_Xmalloc0 (unsigned long bytes)
-{
- return (void*) Xcalloc (bytes, 1);
-}