322 lines
7.1 KiB
C
322 lines
7.1 KiB
C
/*
|
|
|
|
Copyright 1993, 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.
|
|
|
|
*/
|
|
|
|
#ifdef HAVE_DIX_CONFIG_H
|
|
#include <dix-config.h>
|
|
#endif
|
|
|
|
#include <stddef.h>
|
|
#include "windowstr.h"
|
|
#include "resource.h"
|
|
#include "privates.h"
|
|
#include "gcstruct.h"
|
|
#include "cursorstr.h"
|
|
#include "colormapst.h"
|
|
#include "inputstr.h"
|
|
|
|
struct _Private {
|
|
int state;
|
|
pointer value;
|
|
};
|
|
|
|
typedef struct _PrivateDesc {
|
|
DevPrivateKey key;
|
|
unsigned size;
|
|
CallbackListPtr initfuncs;
|
|
CallbackListPtr deletefuncs;
|
|
} PrivateDescRec;
|
|
|
|
#define PRIV_MAX 256
|
|
#define PRIV_STEP 16
|
|
|
|
/* list of all allocated privates */
|
|
static PrivateDescRec items[PRIV_MAX];
|
|
static int nextPriv;
|
|
|
|
static PrivateDescRec *
|
|
findItem(const DevPrivateKey key)
|
|
{
|
|
if (!*key) {
|
|
if (nextPriv >= PRIV_MAX)
|
|
return NULL;
|
|
|
|
items[nextPriv].key = key;
|
|
*key = nextPriv;
|
|
nextPriv++;
|
|
}
|
|
|
|
return items + *key;
|
|
}
|
|
|
|
static _X_INLINE int
|
|
privateExists(PrivateRec **privates, const DevPrivateKey key)
|
|
{
|
|
return *key && *privates &&
|
|
(*privates)[0].state > *key &&
|
|
(*privates)[*key].state;
|
|
}
|
|
|
|
/*
|
|
* Request pre-allocated space.
|
|
*/
|
|
_X_EXPORT int
|
|
dixRequestPrivate(const DevPrivateKey key, unsigned size)
|
|
{
|
|
PrivateDescRec *item = findItem(key);
|
|
if (!item)
|
|
return FALSE;
|
|
if (size > item->size)
|
|
item->size = size;
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* Allocate a private and attach it to an existing object.
|
|
*/
|
|
_X_EXPORT pointer *
|
|
dixAllocatePrivate(PrivateRec **privates, const DevPrivateKey key)
|
|
{
|
|
PrivateDescRec *item = findItem(key);
|
|
PrivateCallbackRec calldata;
|
|
PrivateRec *ptr;
|
|
pointer value;
|
|
int oldsize, newsize;
|
|
|
|
newsize = (*key / PRIV_STEP + 1) * PRIV_STEP;
|
|
|
|
/* resize or init privates array */
|
|
if (!item)
|
|
return NULL;
|
|
|
|
/* initialize privates array if necessary */
|
|
if (!*privates) {
|
|
ptr = xcalloc(newsize, sizeof(*ptr));
|
|
if (!ptr)
|
|
return NULL;
|
|
*privates = ptr;
|
|
(*privates)[0].state = newsize;
|
|
}
|
|
|
|
oldsize = (*privates)[0].state;
|
|
|
|
/* resize privates array if necessary */
|
|
if (*key >= oldsize) {
|
|
ptr = xrealloc(*privates, newsize * sizeof(*ptr));
|
|
if (!ptr)
|
|
return NULL;
|
|
memset(ptr + oldsize, 0, (newsize - oldsize) * sizeof(*ptr));
|
|
*privates = ptr;
|
|
(*privates)[0].state = newsize;
|
|
}
|
|
|
|
/* initialize slot */
|
|
ptr = *privates + *key;
|
|
ptr->state = 1;
|
|
if (item->size) {
|
|
value = xcalloc(item->size, 1);
|
|
if (!value)
|
|
return NULL;
|
|
ptr->value = value;
|
|
}
|
|
|
|
calldata.key = key;
|
|
calldata.value = &ptr->value;
|
|
CallCallbacks(&item->initfuncs, &calldata);
|
|
|
|
return &ptr->value;
|
|
}
|
|
|
|
/*
|
|
* Look up a private pointer.
|
|
*/
|
|
_X_EXPORT pointer
|
|
dixLookupPrivate(PrivateRec **privates, const DevPrivateKey key)
|
|
{
|
|
pointer *ptr;
|
|
|
|
if (privateExists(privates, key))
|
|
return (*privates)[*key].value;
|
|
|
|
ptr = dixAllocatePrivate(privates, key);
|
|
return ptr ? *ptr : NULL;
|
|
}
|
|
|
|
/*
|
|
* Look up the address of a private pointer.
|
|
*/
|
|
_X_EXPORT pointer *
|
|
dixLookupPrivateAddr(PrivateRec **privates, const DevPrivateKey key)
|
|
{
|
|
if (privateExists(privates, key))
|
|
return &(*privates)[*key].value;
|
|
|
|
return dixAllocatePrivate(privates, key);
|
|
}
|
|
|
|
/*
|
|
* Set a private pointer.
|
|
*/
|
|
_X_EXPORT int
|
|
dixSetPrivate(PrivateRec **privates, const DevPrivateKey key, pointer val)
|
|
{
|
|
top:
|
|
if (privateExists(privates, key)) {
|
|
(*privates)[*key].value = val;
|
|
return TRUE;
|
|
}
|
|
|
|
if (!dixAllocatePrivate(privates, key))
|
|
return FALSE;
|
|
goto top;
|
|
}
|
|
|
|
/*
|
|
* Called to free privates at object deletion time.
|
|
*/
|
|
_X_EXPORT void
|
|
dixFreePrivates(PrivateRec *privates)
|
|
{
|
|
int i;
|
|
PrivateCallbackRec calldata;
|
|
|
|
if (privates)
|
|
for (i = 1; i < privates->state; i++)
|
|
if (privates[i].state) {
|
|
/* call the delete callbacks */
|
|
calldata.key = items[i].key;
|
|
calldata.value = &privates[i].value;
|
|
CallCallbacks(&items[i].deletefuncs, &calldata);
|
|
|
|
/* free pre-allocated memory */
|
|
if (items[i].size)
|
|
xfree(privates[i].value);
|
|
}
|
|
|
|
xfree(privates);
|
|
}
|
|
|
|
/*
|
|
* Callback registration
|
|
*/
|
|
_X_EXPORT int
|
|
dixRegisterPrivateInitFunc(const DevPrivateKey key,
|
|
CallbackProcPtr callback, pointer data)
|
|
{
|
|
PrivateDescRec *item = findItem(key);
|
|
if (!item)
|
|
return FALSE;
|
|
|
|
return AddCallback(&item->initfuncs, callback, data);
|
|
}
|
|
|
|
_X_EXPORT int
|
|
dixRegisterPrivateDeleteFunc(const DevPrivateKey key,
|
|
CallbackProcPtr callback, pointer data)
|
|
{
|
|
PrivateDescRec *item = findItem(key);
|
|
if (!item)
|
|
return FALSE;
|
|
|
|
return AddCallback(&item->deletefuncs, callback, data);
|
|
}
|
|
|
|
/* Table of devPrivates offsets */
|
|
static const int offsetDefaults[] = {
|
|
-1, /* RT_NONE */
|
|
offsetof(WindowRec, devPrivates), /* RT_WINDOW */
|
|
offsetof(PixmapRec, devPrivates), /* RT_PIXMAP */
|
|
offsetof(GC, devPrivates), /* RT_GC */
|
|
-1, /* RT_FONT */
|
|
offsetof(CursorRec, devPrivates), /* RT_CURSOR */
|
|
offsetof(ColormapRec, devPrivates), /* RT_COLORMAP */
|
|
-1, /* RT_CMAPENTRY */
|
|
-1, /* RT_OTHERCLIENT */
|
|
-1 /* RT_PASSIVEGRAB */
|
|
};
|
|
|
|
static int *offsets = NULL;
|
|
static int offsetsSize = 0;
|
|
|
|
/*
|
|
* Specify where the devPrivates field is located in a structure type
|
|
*/
|
|
_X_EXPORT int
|
|
dixRegisterPrivateOffset(RESTYPE type, int offset)
|
|
{
|
|
type = type & TypeMask;
|
|
|
|
/* resize offsets table if necessary */
|
|
while (type >= offsetsSize) {
|
|
unsigned i = offsetsSize * 2 * sizeof(int);
|
|
offsets = (int *)xrealloc(offsets, i);
|
|
if (!offsets) {
|
|
offsetsSize = 0;
|
|
return FALSE;
|
|
}
|
|
for (i=offsetsSize; i < 2*offsetsSize; i++)
|
|
offsets[i] = -1;
|
|
offsetsSize *= 2;
|
|
}
|
|
|
|
offsets[type] = offset;
|
|
return TRUE;
|
|
}
|
|
|
|
_X_EXPORT int
|
|
dixLookupPrivateOffset(RESTYPE type)
|
|
{
|
|
type = type & TypeMask;
|
|
assert(type < offsetsSize);
|
|
return offsets[type];
|
|
}
|
|
|
|
int
|
|
dixResetPrivates(void)
|
|
{
|
|
int i;
|
|
|
|
/* reset private descriptors */
|
|
for (i = 1; i < nextPriv; i++) {
|
|
*items[i].key = 0;
|
|
DeleteCallbackList(&items[i].initfuncs);
|
|
DeleteCallbackList(&items[i].deletefuncs);
|
|
}
|
|
nextPriv = 1;
|
|
|
|
/* reset offsets */
|
|
if (offsets)
|
|
xfree(offsets);
|
|
offsetsSize = sizeof(offsetDefaults);
|
|
offsets = (int *)xalloc(offsetsSize);
|
|
offsetsSize /= sizeof(int);
|
|
if (!offsets)
|
|
return FALSE;
|
|
memcpy(offsets, offsetDefaults, sizeof(offsetDefaults));
|
|
return TRUE;
|
|
}
|