IntAtom.c revision eb411b4b
1/* 2 3Copyright 1986, 1990, 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_CONFIG_H 30#include <config.h> 31#endif 32#include "Xlibint.h" 33#include "Xintatom.h" 34 35#define HASH(sig) ((sig) & (TABLESIZE-1)) 36#define REHASHVAL(sig) ((((sig) % (TABLESIZE-3)) + 2) | 1) 37#define REHASH(idx,rehash) ((idx + rehash) & (TABLESIZE-1)) 38 39void 40_XFreeAtomTable(Display *dpy) 41{ 42 register Entry *table; 43 register int i; 44 register Entry e; 45 46 if (dpy->atoms) { 47 table = dpy->atoms->table; 48 for (i = TABLESIZE; --i >= 0; ) { 49 if ((e = *table++) && (e != RESERVED)) 50 Xfree((char *)e); 51 } 52 Xfree((char *)dpy->atoms); 53 } 54} 55 56static 57Atom _XInternAtom( 58 Display *dpy, 59 _Xconst char *name, 60 Bool onlyIfExists, 61 unsigned long *psig, 62 int *pidx, 63 int *pn) 64{ 65 register AtomTable *atoms; 66 register char *s1, c, *s2; 67 register unsigned long sig; 68 register int idx = 0, i; 69 Entry e; 70 int n, firstidx, rehash = 0; 71 xInternAtomReq *req; 72 73 /* look in the cache first */ 74 if (!(atoms = dpy->atoms)) { 75 dpy->atoms = atoms = Xcalloc(1, sizeof(AtomTable)); 76 dpy->free_funcs->atoms = _XFreeAtomTable; 77 } 78 sig = 0; 79 for (s1 = (char *)name; (c = *s1++); ) 80 sig += c; 81 n = s1 - (char *)name - 1; 82 if (atoms) { 83 firstidx = idx = HASH(sig); 84 while ((e = atoms->table[idx])) { 85 if (e != RESERVED && e->sig == sig) { 86 for (i = n, s1 = (char *)name, s2 = EntryName(e); --i >= 0; ) { 87 if (*s1++ != *s2++) 88 goto nomatch; 89 } 90 if (!*s2) 91 return e->atom; 92 } 93nomatch: if (idx == firstidx) 94 rehash = REHASHVAL(sig); 95 idx = REHASH(idx, rehash); 96 if (idx == firstidx) 97 break; 98 } 99 } 100 *psig = sig; 101 *pidx = idx; 102 if (atoms && !atoms->table[idx]) 103 atoms->table[idx] = RESERVED; /* reserve slot */ 104 *pn = n; 105 /* not found, go to the server */ 106 GetReq(InternAtom, req); 107 req->nbytes = n; 108 req->onlyIfExists = onlyIfExists; 109 req->length += (n+3)>>2; 110 Data(dpy, name, n); 111 return None; 112} 113 114void 115_XUpdateAtomCache( 116 Display *dpy, 117 const char *name, 118 Atom atom, 119 unsigned long sig, 120 int idx, 121 int n) 122{ 123 Entry e, oe; 124 register char *s1; 125 register char c; 126 int firstidx, rehash; 127 128 if (!dpy->atoms) { 129 if (idx < 0) { 130 dpy->atoms = Xcalloc(1, sizeof(AtomTable)); 131 dpy->free_funcs->atoms = _XFreeAtomTable; 132 } 133 if (!dpy->atoms) 134 return; 135 } 136 if (!sig) { 137 for (s1 = (char *)name; (c = *s1++); ) 138 sig += c; 139 n = s1 - (char *)name - 1; 140 if (idx < 0) { 141 firstidx = idx = HASH(sig); 142 if (dpy->atoms->table[idx]) { 143 rehash = REHASHVAL(sig); 144 do 145 idx = REHASH(idx, rehash); 146 while (idx != firstidx && dpy->atoms->table[idx]); 147 } 148 } 149 } 150 e = Xmalloc(sizeof(EntryRec) + n + 1); 151 if (e) { 152 e->sig = sig; 153 e->atom = atom; 154 strcpy(EntryName(e), name); 155 if ((oe = dpy->atoms->table[idx]) && (oe != RESERVED)) 156 Xfree((char *)oe); 157 dpy->atoms->table[idx] = e; 158 } 159} 160 161Atom 162XInternAtom ( 163 Display *dpy, 164 const char *name, 165 Bool onlyIfExists) 166{ 167 Atom atom; 168 unsigned long sig; 169 int idx, n; 170 xInternAtomReply rep; 171 172 if (!name) 173 name = ""; 174 LockDisplay(dpy); 175 if ((atom = _XInternAtom(dpy, name, onlyIfExists, &sig, &idx, &n))) { 176 UnlockDisplay(dpy); 177 return atom; 178 } 179 if (dpy->atoms && dpy->atoms->table[idx] == RESERVED) 180 dpy->atoms->table[idx] = NULL; /* unreserve slot */ 181 if (_XReply (dpy, (xReply *)&rep, 0, xTrue)) { 182 if ((atom = rep.atom)) 183 _XUpdateAtomCache(dpy, name, atom, sig, idx, n); 184 } 185 UnlockDisplay(dpy); 186 SyncHandle(); 187 return (rep.atom); 188} 189 190typedef struct { 191 unsigned long start_seq; 192 unsigned long stop_seq; 193 char **names; 194 Atom *atoms; 195 int count; 196 Status status; 197} _XIntAtomState; 198 199static 200Bool _XIntAtomHandler( 201 register Display *dpy, 202 register xReply *rep, 203 char *buf, 204 int len, 205 XPointer data) 206{ 207 register _XIntAtomState *state; 208 register int i, idx = 0; 209 xInternAtomReply replbuf; 210 register xInternAtomReply *repl; 211 212 state = (_XIntAtomState *)data; 213 if (dpy->last_request_read < state->start_seq || 214 dpy->last_request_read > state->stop_seq) 215 return False; 216 for (i = 0; i < state->count; i++) { 217 if (state->atoms[i] & 0x80000000) { 218 idx = ~state->atoms[i]; 219 state->atoms[i] = None; 220 break; 221 } 222 } 223 if (i >= state->count) 224 return False; 225 if (rep->generic.type == X_Error) { 226 state->status = 0; 227 return False; 228 } 229 repl = (xInternAtomReply *) 230 _XGetAsyncReply(dpy, (char *)&replbuf, rep, buf, len, 231 (SIZEOF(xInternAtomReply) - SIZEOF(xReply)) >> 2, 232 True); 233 if ((state->atoms[i] = repl->atom)) 234 _XUpdateAtomCache(dpy, state->names[i], (Atom) repl->atom, 235 (unsigned long)0, idx, 0); 236 return True; 237} 238 239Status 240XInternAtoms ( 241 Display *dpy, 242 char **names, 243 int count, 244 Bool onlyIfExists, 245 Atom *atoms_return) 246{ 247 int i, idx, n, tidx; 248 unsigned long sig; 249 _XAsyncHandler async; 250 _XIntAtomState async_state; 251 int missed = -1; 252 xInternAtomReply rep; 253 254 LockDisplay(dpy); 255 async_state.start_seq = dpy->request + 1; 256 async_state.atoms = atoms_return; 257 async_state.names = names; 258 async_state.count = count - 1; 259 async_state.status = 1; 260 async.next = dpy->async_handlers; 261 async.handler = _XIntAtomHandler; 262 async.data = (XPointer)&async_state; 263 dpy->async_handlers = &async; 264 for (i = 0; i < count; i++) { 265 if (!(atoms_return[i] = _XInternAtom(dpy, names[i], onlyIfExists, 266 &sig, &idx, &n))) { 267 missed = i; 268 atoms_return[i] = ~((Atom)idx); 269 async_state.stop_seq = dpy->request; 270 } 271 } 272 if (missed >= 0) { 273 if (dpy->atoms) { 274 /* unreserve anything we just reserved */ 275 for (i = 0; i < count; i++) { 276 if (atoms_return[i] & 0x80000000) { 277 tidx = ~atoms_return[i]; 278 if (dpy->atoms->table[tidx] == RESERVED) 279 dpy->atoms->table[tidx] = NULL; 280 } 281 } 282 } 283 if (_XReply (dpy, (xReply *)&rep, 0, xTrue)) { 284 if ((atoms_return[missed] = rep.atom)) 285 _XUpdateAtomCache(dpy, names[missed], (Atom) rep.atom, 286 sig, idx, n); 287 } else { 288 atoms_return[missed] = None; 289 async_state.status = 0; 290 } 291 } 292 DeqAsyncHandler(dpy, &async); 293 UnlockDisplay(dpy); 294 if (missed >= 0) 295 SyncHandle(); 296 return async_state.status; 297} 298