privates.c revision 4642e01f
1/* 2 3Copyright 1993, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included 12in all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 18OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20OTHER DEALINGS IN THE SOFTWARE. 21 22Except as contained in this notice, the name of The Open Group shall 23not be used in advertising or otherwise to promote the sale, use or 24other dealings in this Software without prior written authorization 25from The Open Group. 26 27*/ 28 29#ifdef HAVE_DIX_CONFIG_H 30#include <dix-config.h> 31#endif 32 33#include <stddef.h> 34#include "windowstr.h" 35#include "resource.h" 36#include "privates.h" 37#include "gcstruct.h" 38#include "cursorstr.h" 39#include "colormapst.h" 40#include "inputstr.h" 41 42struct _Private { 43 int state; 44 pointer value; 45}; 46 47typedef struct _PrivateDesc { 48 DevPrivateKey key; 49 unsigned size; 50 CallbackListPtr initfuncs; 51 CallbackListPtr deletefuncs; 52} PrivateDescRec; 53 54#define PRIV_MAX 256 55#define PRIV_STEP 16 56 57/* list of all allocated privates */ 58static PrivateDescRec items[PRIV_MAX]; 59static int nextPriv; 60 61static PrivateDescRec * 62findItem(const DevPrivateKey key) 63{ 64 if (!*key) { 65 if (nextPriv >= PRIV_MAX) 66 return NULL; 67 68 items[nextPriv].key = key; 69 *key = nextPriv; 70 nextPriv++; 71 } 72 73 return items + *key; 74} 75 76static _X_INLINE int 77privateExists(PrivateRec **privates, const DevPrivateKey key) 78{ 79 return *key && *privates && 80 (*privates)[0].state > *key && 81 (*privates)[*key].state; 82} 83 84/* 85 * Request pre-allocated space. 86 */ 87_X_EXPORT int 88dixRequestPrivate(const DevPrivateKey key, unsigned size) 89{ 90 PrivateDescRec *item = findItem(key); 91 if (!item) 92 return FALSE; 93 if (size > item->size) 94 item->size = size; 95 return TRUE; 96} 97 98/* 99 * Allocate a private and attach it to an existing object. 100 */ 101_X_EXPORT pointer * 102dixAllocatePrivate(PrivateRec **privates, const DevPrivateKey key) 103{ 104 PrivateDescRec *item = findItem(key); 105 PrivateCallbackRec calldata; 106 PrivateRec *ptr; 107 pointer value; 108 int oldsize, newsize; 109 110 newsize = (*key / PRIV_STEP + 1) * PRIV_STEP; 111 112 /* resize or init privates array */ 113 if (!item) 114 return NULL; 115 116 /* initialize privates array if necessary */ 117 if (!*privates) { 118 ptr = xcalloc(newsize, sizeof(*ptr)); 119 if (!ptr) 120 return NULL; 121 *privates = ptr; 122 (*privates)[0].state = newsize; 123 } 124 125 oldsize = (*privates)[0].state; 126 127 /* resize privates array if necessary */ 128 if (*key >= oldsize) { 129 ptr = xrealloc(*privates, newsize * sizeof(*ptr)); 130 if (!ptr) 131 return NULL; 132 memset(ptr + oldsize, 0, (newsize - oldsize) * sizeof(*ptr)); 133 *privates = ptr; 134 (*privates)[0].state = newsize; 135 } 136 137 /* initialize slot */ 138 ptr = *privates + *key; 139 ptr->state = 1; 140 if (item->size) { 141 value = xcalloc(item->size, 1); 142 if (!value) 143 return NULL; 144 ptr->value = value; 145 } 146 147 calldata.key = key; 148 calldata.value = &ptr->value; 149 CallCallbacks(&item->initfuncs, &calldata); 150 151 return &ptr->value; 152} 153 154/* 155 * Look up a private pointer. 156 */ 157_X_EXPORT pointer 158dixLookupPrivate(PrivateRec **privates, const DevPrivateKey key) 159{ 160 pointer *ptr; 161 162 if (privateExists(privates, key)) 163 return (*privates)[*key].value; 164 165 ptr = dixAllocatePrivate(privates, key); 166 return ptr ? *ptr : NULL; 167} 168 169/* 170 * Look up the address of a private pointer. 171 */ 172_X_EXPORT pointer * 173dixLookupPrivateAddr(PrivateRec **privates, const DevPrivateKey key) 174{ 175 if (privateExists(privates, key)) 176 return &(*privates)[*key].value; 177 178 return dixAllocatePrivate(privates, key); 179} 180 181/* 182 * Set a private pointer. 183 */ 184_X_EXPORT int 185dixSetPrivate(PrivateRec **privates, const DevPrivateKey key, pointer val) 186{ 187 top: 188 if (privateExists(privates, key)) { 189 (*privates)[*key].value = val; 190 return TRUE; 191 } 192 193 if (!dixAllocatePrivate(privates, key)) 194 return FALSE; 195 goto top; 196} 197 198/* 199 * Called to free privates at object deletion time. 200 */ 201_X_EXPORT void 202dixFreePrivates(PrivateRec *privates) 203{ 204 int i; 205 PrivateCallbackRec calldata; 206 207 if (privates) 208 for (i = 1; i < privates->state; i++) 209 if (privates[i].state) { 210 /* call the delete callbacks */ 211 calldata.key = items[i].key; 212 calldata.value = &privates[i].value; 213 CallCallbacks(&items[i].deletefuncs, &calldata); 214 215 /* free pre-allocated memory */ 216 if (items[i].size) 217 xfree(privates[i].value); 218 } 219 220 xfree(privates); 221} 222 223/* 224 * Callback registration 225 */ 226_X_EXPORT int 227dixRegisterPrivateInitFunc(const DevPrivateKey key, 228 CallbackProcPtr callback, pointer data) 229{ 230 PrivateDescRec *item = findItem(key); 231 if (!item) 232 return FALSE; 233 234 return AddCallback(&item->initfuncs, callback, data); 235} 236 237_X_EXPORT int 238dixRegisterPrivateDeleteFunc(const DevPrivateKey key, 239 CallbackProcPtr callback, pointer data) 240{ 241 PrivateDescRec *item = findItem(key); 242 if (!item) 243 return FALSE; 244 245 return AddCallback(&item->deletefuncs, callback, data); 246} 247 248/* Table of devPrivates offsets */ 249static const int offsetDefaults[] = { 250 -1, /* RT_NONE */ 251 offsetof(WindowRec, devPrivates), /* RT_WINDOW */ 252 offsetof(PixmapRec, devPrivates), /* RT_PIXMAP */ 253 offsetof(GC, devPrivates), /* RT_GC */ 254 -1, /* RT_FONT */ 255 offsetof(CursorRec, devPrivates), /* RT_CURSOR */ 256 offsetof(ColormapRec, devPrivates), /* RT_COLORMAP */ 257 -1, /* RT_CMAPENTRY */ 258 -1, /* RT_OTHERCLIENT */ 259 -1 /* RT_PASSIVEGRAB */ 260}; 261 262static int *offsets = NULL; 263static int offsetsSize = 0; 264 265/* 266 * Specify where the devPrivates field is located in a structure type 267 */ 268_X_EXPORT int 269dixRegisterPrivateOffset(RESTYPE type, int offset) 270{ 271 type = type & TypeMask; 272 273 /* resize offsets table if necessary */ 274 while (type >= offsetsSize) { 275 unsigned i = offsetsSize * 2 * sizeof(int); 276 offsets = (int *)xrealloc(offsets, i); 277 if (!offsets) { 278 offsetsSize = 0; 279 return FALSE; 280 } 281 for (i=offsetsSize; i < 2*offsetsSize; i++) 282 offsets[i] = -1; 283 offsetsSize *= 2; 284 } 285 286 offsets[type] = offset; 287 return TRUE; 288} 289 290_X_EXPORT int 291dixLookupPrivateOffset(RESTYPE type) 292{ 293 type = type & TypeMask; 294 assert(type < offsetsSize); 295 return offsets[type]; 296} 297 298int 299dixResetPrivates(void) 300{ 301 int i; 302 303 /* reset private descriptors */ 304 for (i = 1; i < nextPriv; i++) { 305 *items[i].key = 0; 306 DeleteCallbackList(&items[i].initfuncs); 307 DeleteCallbackList(&items[i].deletefuncs); 308 } 309 nextPriv = 1; 310 311 /* reset offsets */ 312 if (offsets) 313 xfree(offsets); 314 offsetsSize = sizeof(offsetDefaults); 315 offsets = (int *)xalloc(offsetsSize); 316 offsetsSize /= sizeof(int); 317 if (!offsets) 318 return FALSE; 319 memcpy(offsets, offsetDefaults, sizeof(offsetDefaults)); 320 return TRUE; 321} 322