#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
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;
}
_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;
}
_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;
if (!item)
return NULL;
if (!*privates) {
ptr = xcalloc(newsize, sizeof(*ptr));
if (!ptr)
return NULL;
*privates = ptr;
(*privates)[0].state = newsize;
}
oldsize = (*privates)[0].state;
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;
}
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;
}
_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;
}
_X_EXPORT pointer *
dixLookupPrivateAddr(PrivateRec **privates, const DevPrivateKey key)
{
if (privateExists(privates, key))
return &(*privates)[*key].value;
return dixAllocatePrivate(privates, key);
}
_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;
}
_X_EXPORT void
dixFreePrivates(PrivateRec *privates)
{
int i;
PrivateCallbackRec calldata;
if (privates)
for (i = 1; i < privates->state; i++)
if (privates[i].state) {
calldata.key = items[i].key;
calldata.value = &privates[i].value;
CallCallbacks(&items[i].deletefuncs, &calldata);
if (items[i].size)
xfree(privates[i].value);
}
xfree(privates);
}
_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);
}
static const int offsetDefaults[] = {
-1,
offsetof(WindowRec, devPrivates),
offsetof(PixmapRec, devPrivates),
offsetof(GC, devPrivates),
-1,
offsetof(CursorRec, devPrivates),
offsetof(ColormapRec, devPrivates),
-1,
-1,
-1
};
static int *offsets = NULL;
static int offsetsSize = 0;
_X_EXPORT int
dixRegisterPrivateOffset(RESTYPE type, int offset)
{
type = type & TypeMask;
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;
for (i = 1; i < nextPriv; i++) {
*items[i].key = 0;
DeleteCallbackList(&items[i].initfuncs);
DeleteCallbackList(&items[i].deletefuncs);
}
nextPriv = 1;
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;
}