315 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			315 lines
		
	
	
		
			7.0 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 {
 | |
|     DevPrivateKey      key;
 | |
|     pointer            value;
 | |
|     struct _Private    *next;
 | |
| };
 | |
| 
 | |
| typedef struct _PrivateDesc {
 | |
|     DevPrivateKey key;
 | |
|     unsigned size;
 | |
|     CallbackListPtr initfuncs;
 | |
|     CallbackListPtr deletefuncs;
 | |
|     struct _PrivateDesc *next;
 | |
| } PrivateDescRec;
 | |
| 
 | |
| /* list of all allocated privates */
 | |
| static PrivateDescRec *items = NULL;
 | |
| 
 | |
| static _X_INLINE PrivateDescRec *
 | |
| findItem(const DevPrivateKey key)
 | |
| {
 | |
|     PrivateDescRec *item = items;
 | |
|     while (item) {
 | |
| 	if (item->key == key)
 | |
| 	    return item;
 | |
| 	item = item->next;
 | |
|     }
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Request pre-allocated space.
 | |
|  */
 | |
| _X_EXPORT int
 | |
| dixRequestPrivate(const DevPrivateKey key, unsigned size)
 | |
| {
 | |
|     PrivateDescRec *item = findItem(key);
 | |
|     if (item) {
 | |
| 	if (size > item->size)
 | |
| 	    item->size = size;
 | |
|     } else {
 | |
| 	item = (PrivateDescRec *)xalloc(sizeof(PrivateDescRec));
 | |
| 	if (!item)
 | |
| 	    return FALSE;
 | |
| 	memset(item, 0, sizeof(PrivateDescRec));
 | |
| 
 | |
| 	/* add privates descriptor */
 | |
| 	item->key = key;
 | |
| 	item->size = size;
 | |
| 	item->next = items;
 | |
| 	items = item;
 | |
|     }
 | |
|     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);
 | |
|     PrivateRec *ptr;
 | |
|     unsigned size = sizeof(PrivateRec);
 | |
|     
 | |
|     if (item)
 | |
| 	size += item->size;
 | |
| 
 | |
|     ptr = (PrivateRec *)xcalloc(size, 1);
 | |
|     if (!ptr)
 | |
| 	return NULL;
 | |
|     ptr->key = key;
 | |
|     ptr->value = (size > sizeof(PrivateRec)) ? (ptr + 1) : NULL;
 | |
|     ptr->next = *privates;
 | |
|     *privates = ptr;
 | |
| 
 | |
|     /* call any init funcs and return */
 | |
|     if (item) {
 | |
| 	PrivateCallbackRec calldata = { key, &ptr->value };
 | |
| 	CallCallbacks(&item->initfuncs, &calldata);
 | |
|     }
 | |
|     return &ptr->value;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Look up a private pointer.
 | |
|  */
 | |
| _X_EXPORT pointer
 | |
| dixLookupPrivate(PrivateRec **privates, const DevPrivateKey key)
 | |
| {
 | |
|     PrivateRec *rec = *privates;
 | |
|     pointer *ptr;
 | |
| 
 | |
|     while (rec) {
 | |
| 	if (rec->key == key)
 | |
| 	    return rec->value;
 | |
| 	rec = rec->next;
 | |
|     }
 | |
| 
 | |
|     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)
 | |
| {
 | |
|     PrivateRec *rec = *privates;
 | |
| 
 | |
|     while (rec) {
 | |
| 	if (rec->key == key)
 | |
| 	    return &rec->value;
 | |
| 	rec = rec->next;
 | |
|     }
 | |
| 
 | |
|     return dixAllocatePrivate(privates, key);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Set a private pointer.
 | |
|  */
 | |
| _X_EXPORT int
 | |
| dixSetPrivate(PrivateRec **privates, const DevPrivateKey key, pointer val)
 | |
| {
 | |
|     PrivateRec *rec;
 | |
| 
 | |
|  top:
 | |
|     rec = *privates;
 | |
|     while (rec) {
 | |
| 	if (rec->key == key) {
 | |
| 	    rec->value = val;
 | |
| 	    return TRUE;
 | |
| 	}
 | |
| 	rec = rec->next;
 | |
|     }
 | |
| 
 | |
|     if (!dixAllocatePrivate(privates, key))
 | |
| 	return FALSE;
 | |
|     goto top;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Called to free privates at object deletion time.
 | |
|  */
 | |
| _X_EXPORT void
 | |
| dixFreePrivates(PrivateRec *privates)
 | |
| {
 | |
|     PrivateRec *ptr, *next;
 | |
|     PrivateDescRec *item;
 | |
|     PrivateCallbackRec calldata;
 | |
| 
 | |
|     /* first pass calls the delete callbacks */
 | |
|     for (ptr = privates; ptr; ptr = ptr->next) {
 | |
| 	item = findItem(ptr->key);
 | |
| 	if (item) {
 | |
| 	    calldata.key = ptr->key;
 | |
| 	    calldata.value = &ptr->value;
 | |
| 	    CallCallbacks(&item->deletefuncs, &calldata);
 | |
| 	}
 | |
|     }
 | |
| 	
 | |
|     /* second pass frees the memory */
 | |
|     ptr = privates;
 | |
|     while (ptr) {
 | |
| 	next = ptr->next;
 | |
| 	xfree(ptr);
 | |
| 	ptr = next;
 | |
|     }
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Callback registration
 | |
|  */
 | |
| _X_EXPORT int
 | |
| dixRegisterPrivateInitFunc(const DevPrivateKey key,
 | |
| 			   CallbackProcPtr callback, pointer data)
 | |
| {
 | |
|     PrivateDescRec *item = findItem(key);
 | |
|     if (!item) {
 | |
| 	if (!dixRequestPrivate(key, 0))
 | |
| 	    return FALSE;
 | |
| 	item = findItem(key);
 | |
|     }
 | |
|     return AddCallback(&item->initfuncs, callback, data);
 | |
| }
 | |
| 
 | |
| _X_EXPORT int
 | |
| dixRegisterPrivateDeleteFunc(const DevPrivateKey key,
 | |
| 			     CallbackProcPtr callback, pointer data)
 | |
| {
 | |
|     PrivateDescRec *item = findItem(key);
 | |
|     if (!item) {
 | |
| 	if (!dixRequestPrivate(key, 0))
 | |
| 	    return FALSE;
 | |
| 	item = findItem(key);
 | |
|     }
 | |
|     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)
 | |
| {
 | |
|     PrivateDescRec *next;
 | |
| 
 | |
|     /* reset internal structures */
 | |
|     while (items) {
 | |
| 	next = items->next;
 | |
| 	DeleteCallbackList(&items->initfuncs);
 | |
| 	DeleteCallbackList(&items->deletefuncs);
 | |
| 	xfree(items);
 | |
| 	items = next;
 | |
|     }
 | |
|     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;
 | |
| }
 |