IntAtom.c revision 1ab64890
1/* $Xorg: IntAtom.c,v 1.5 2001/02/09 02:03:34 xorgcvs Exp $ */ 2/* 3 4Copyright 1986, 1990, 1998 The Open Group 5 6Permission to use, copy, modify, distribute, and sell this software and its 7documentation for any purpose is hereby granted without fee, provided that 8the above copyright notice appear in all copies and that both that 9copyright notice and this permission notice appear in supporting 10documentation. 11 12The above copyright notice and this permission notice shall be included 13in all copies or substantial portions of the Software. 14 15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 19OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21OTHER DEALINGS IN THE SOFTWARE. 22 23Except as contained in this notice, the name of The Open Group shall 24not be used in advertising or otherwise to promote the sale, use or 25other dealings in this Software without prior written authorization 26from The Open Group. 27 28*/ 29/* $XFree86: xc/lib/X11/IntAtom.c,v 1.6 2001/12/14 19:54:02 dawes Exp $ */ 30 31#define NEED_REPLIES 32#ifdef HAVE_CONFIG_H 33#include <config.h> 34#endif 35#include "Xlibint.h" 36#include "Xintatom.h" 37 38#define HASH(sig) ((sig) & (TABLESIZE-1)) 39#define REHASHVAL(sig) ((((sig) % (TABLESIZE-3)) + 2) | 1) 40#define REHASH(idx,rehash) ((idx + rehash) & (TABLESIZE-1)) 41 42void 43_XFreeAtomTable(Display *dpy) 44{ 45 register Entry *table; 46 register int i; 47 register Entry e; 48 49 if (dpy->atoms) { 50 table = dpy->atoms->table; 51 for (i = TABLESIZE; --i >= 0; ) { 52 if ((e = *table++) && (e != RESERVED)) 53 Xfree((char *)e); 54 } 55 Xfree((char *)dpy->atoms); 56 } 57} 58 59static 60Atom _XInternAtom( 61 Display *dpy, 62 _Xconst char *name, 63 Bool onlyIfExists, 64 unsigned long *psig, 65 int *pidx, 66 int *pn) 67{ 68 register AtomTable *atoms; 69 register char *s1, c, *s2; 70 register unsigned long sig; 71 register int idx = 0, i; 72 Entry e; 73 int n, firstidx, rehash = 0; 74 xInternAtomReq *req; 75 76 /* look in the cache first */ 77 if (!(atoms = dpy->atoms)) { 78 dpy->atoms = atoms = (AtomTable *)Xcalloc(1, sizeof(AtomTable)); 79 dpy->free_funcs->atoms = _XFreeAtomTable; 80 } 81 sig = 0; 82 for (s1 = (char *)name; (c = *s1++); ) 83 sig += c; 84 n = s1 - (char *)name - 1; 85 if (atoms) { 86 firstidx = idx = HASH(sig); 87 while ((e = atoms->table[idx])) { 88 if (e != RESERVED && e->sig == sig) { 89 for (i = n, s1 = (char *)name, s2 = EntryName(e); --i >= 0; ) { 90 if (*s1++ != *s2++) 91 goto nomatch; 92 } 93 if (!*s2) 94 return e->atom; 95 } 96nomatch: if (idx == firstidx) 97 rehash = REHASHVAL(sig); 98 idx = REHASH(idx, rehash); 99 if (idx == firstidx) 100 break; 101 } 102 } 103 *psig = sig; 104 *pidx = idx; 105 if (atoms && !atoms->table[idx]) 106 atoms->table[idx] = RESERVED; /* reserve slot */ 107 *pn = n; 108 /* not found, go to the server */ 109 GetReq(InternAtom, req); 110 req->nbytes = n; 111 req->onlyIfExists = onlyIfExists; 112 req->length += (n+3)>>2; 113 Data(dpy, name, n); 114 return None; 115} 116 117void 118_XUpdateAtomCache( 119 Display *dpy, 120 const char *name, 121 Atom atom, 122 unsigned long sig, 123 int idx, 124 int n) 125{ 126 Entry e, oe; 127 register char *s1; 128 register char c; 129 int firstidx, rehash; 130 131 if (!dpy->atoms) { 132 if (idx < 0) { 133 dpy->atoms = (AtomTable *)Xcalloc(1, sizeof(AtomTable)); 134 dpy->free_funcs->atoms = _XFreeAtomTable; 135 } 136 if (!dpy->atoms) 137 return; 138 } 139 if (!sig) { 140 for (s1 = (char *)name; (c = *s1++); ) 141 sig += c; 142 n = s1 - (char *)name - 1; 143 if (idx < 0) { 144 firstidx = idx = HASH(sig); 145 if (dpy->atoms->table[idx]) { 146 rehash = REHASHVAL(sig); 147 do 148 idx = REHASH(idx, rehash); 149 while (idx != firstidx && dpy->atoms->table[idx]); 150 } 151 } 152 } 153 e = (Entry)Xmalloc(sizeof(EntryRec) + n + 1); 154 if (e) { 155 e->sig = sig; 156 e->atom = atom; 157 strcpy(EntryName(e), name); 158 if ((oe = dpy->atoms->table[idx]) && (oe != RESERVED)) 159 Xfree((char *)oe); 160 dpy->atoms->table[idx] = e; 161 } 162} 163 164Atom 165XInternAtom ( 166 Display *dpy, 167 const char *name, 168 Bool onlyIfExists) 169{ 170 Atom atom; 171 unsigned long sig; 172 int idx, n; 173 xInternAtomReply rep; 174 175 if (!name) 176 name = ""; 177 LockDisplay(dpy); 178 if ((atom = _XInternAtom(dpy, name, onlyIfExists, &sig, &idx, &n))) { 179 UnlockDisplay(dpy); 180 return atom; 181 } 182 if (dpy->atoms && dpy->atoms->table[idx] == RESERVED) 183 dpy->atoms->table[idx] = NULL; /* unreserve slot */ 184 if (_XReply (dpy, (xReply *)&rep, 0, xTrue)) { 185 if ((atom = rep.atom)) 186 _XUpdateAtomCache(dpy, name, atom, sig, idx, n); 187 } 188 UnlockDisplay(dpy); 189 SyncHandle(); 190 return (rep.atom); 191} 192 193typedef struct { 194 unsigned long start_seq; 195 unsigned long stop_seq; 196 char **names; 197 Atom *atoms; 198 int count; 199 Status status; 200} _XIntAtomState; 201 202static 203Bool _XIntAtomHandler( 204 register Display *dpy, 205 register xReply *rep, 206 char *buf, 207 int len, 208 XPointer data) 209{ 210 register _XIntAtomState *state; 211 register int i, idx = 0; 212 xInternAtomReply replbuf; 213 register xInternAtomReply *repl; 214 215 state = (_XIntAtomState *)data; 216 if (dpy->last_request_read < state->start_seq || 217 dpy->last_request_read > state->stop_seq) 218 return False; 219 for (i = 0; i < state->count; i++) { 220 if (state->atoms[i] & 0x80000000) { 221 idx = ~state->atoms[i]; 222 state->atoms[i] = None; 223 break; 224 } 225 } 226 if (i >= state->count) 227 return False; 228 if (rep->generic.type == X_Error) { 229 state->status = 0; 230 return False; 231 } 232 repl = (xInternAtomReply *) 233 _XGetAsyncReply(dpy, (char *)&replbuf, rep, buf, len, 234 (SIZEOF(xInternAtomReply) - SIZEOF(xReply)) >> 2, 235 True); 236 if ((state->atoms[i] = repl->atom)) 237 _XUpdateAtomCache(dpy, state->names[i], (Atom) repl->atom, 238 (unsigned long)0, idx, 0); 239 return True; 240} 241 242Status 243XInternAtoms ( 244 Display *dpy, 245 char **names, 246 int count, 247 Bool onlyIfExists, 248 Atom *atoms_return) 249{ 250 int i, idx, n, tidx; 251 unsigned long sig; 252 _XAsyncHandler async; 253 _XIntAtomState async_state; 254 int missed = -1; 255 xInternAtomReply rep; 256 257 LockDisplay(dpy); 258 async_state.start_seq = dpy->request + 1; 259 async_state.atoms = atoms_return; 260 async_state.names = names; 261 async_state.count = count - 1; 262 async_state.status = 1; 263 async.next = dpy->async_handlers; 264 async.handler = _XIntAtomHandler; 265 async.data = (XPointer)&async_state; 266 dpy->async_handlers = &async; 267 for (i = 0; i < count; i++) { 268 if (!(atoms_return[i] = _XInternAtom(dpy, names[i], onlyIfExists, 269 &sig, &idx, &n))) { 270 missed = i; 271 atoms_return[i] = ~((Atom)idx); 272 async_state.stop_seq = dpy->request; 273 } 274 } 275 if (missed >= 0) { 276 if (dpy->atoms) { 277 /* unreserve anything we just reserved */ 278 for (i = 0; i < count; i++) { 279 if (atoms_return[i] & 0x80000000) { 280 tidx = ~atoms_return[i]; 281 if (dpy->atoms->table[tidx] == RESERVED) 282 dpy->atoms->table[tidx] = NULL; 283 } 284 } 285 } 286 if (_XReply (dpy, (xReply *)&rep, 0, xTrue)) { 287 if ((atoms_return[missed] = rep.atom)) 288 _XUpdateAtomCache(dpy, names[missed], (Atom) rep.atom, 289 sig, idx, n); 290 } else { 291 atoms_return[missed] = None; 292 async_state.status = 0; 293 } 294 } 295 DeqAsyncHandler(dpy, &async); 296 UnlockDisplay(dpy); 297 if (missed >= 0) 298 SyncHandle(); 299 return async_state.status; 300} 301