IntAtom.c revision 2d67cb4f
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(e); 51 } 52 Xfree(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(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 uint64_t start_seq; 192 uint64_t 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 uint64_t last_request_read = X_DPY_GET_LAST_REQUEST_READ(dpy); 212 213 state = (_XIntAtomState *)data; 214 215 if (last_request_read < state->start_seq || 216 last_request_read > state->stop_seq) 217 return False; 218 for (i = 0; i < state->count; i++) { 219 if (state->atoms[i] & 0x80000000) { 220 idx = ~state->atoms[i]; 221 state->atoms[i] = None; 222 break; 223 } 224 } 225 if (i >= state->count) 226 return False; 227 if (rep->generic.type == X_Error) { 228 state->status = 0; 229 return False; 230 } 231 repl = (xInternAtomReply *) 232 _XGetAsyncReply(dpy, (char *)&replbuf, rep, buf, len, 233 (SIZEOF(xInternAtomReply) - SIZEOF(xReply)) >> 2, 234 True); 235 if ((state->atoms[i] = repl->atom)) 236 _XUpdateAtomCache(dpy, state->names[i], (Atom) repl->atom, 237 (unsigned long)0, idx, 0); 238 return True; 239} 240 241Status 242XInternAtoms ( 243 Display *dpy, 244 char **names, 245 int count, 246 Bool onlyIfExists, 247 Atom *atoms_return) 248{ 249 int i, idx, n, tidx; 250 unsigned long sig; 251 _XAsyncHandler async; 252 _XIntAtomState async_state; 253 int missed = -1; 254 xInternAtomReply rep; 255 256 LockDisplay(dpy); 257 async_state.start_seq = X_DPY_GET_REQUEST(dpy) + 1; 258 async_state.atoms = atoms_return; 259 async_state.names = names; 260 async_state.count = count - 1; 261 async_state.status = 1; 262 async.next = dpy->async_handlers; 263 async.handler = _XIntAtomHandler; 264 async.data = (XPointer)&async_state; 265 dpy->async_handlers = &async; 266 for (i = 0; i < count; i++) { 267 if (!(atoms_return[i] = _XInternAtom(dpy, names[i], onlyIfExists, 268 &sig, &idx, &n))) { 269 missed = i; 270 atoms_return[i] = ~((Atom)idx); 271 async_state.stop_seq = X_DPY_GET_REQUEST(dpy); 272 } 273 } 274 if (missed >= 0) { 275 if (dpy->atoms) { 276 /* unreserve anything we just reserved */ 277 for (i = 0; i < count; i++) { 278 if (atoms_return[i] & 0x80000000) { 279 tidx = ~atoms_return[i]; 280 if (dpy->atoms->table[tidx] == RESERVED) 281 dpy->atoms->table[tidx] = NULL; 282 } 283 } 284 } 285 if (_XReply (dpy, (xReply *)&rep, 0, xTrue)) { 286 if ((atoms_return[missed] = rep.atom)) 287 _XUpdateAtomCache(dpy, names[missed], (Atom) rep.atom, 288 sig, idx, n); 289 } else { 290 atoms_return[missed] = None; 291 async_state.status = 0; 292 } 293 } 294 DeqAsyncHandler(dpy, &async); 295 UnlockDisplay(dpy); 296 if (missed >= 0) 297 SyncHandle(); 298 return async_state.status; 299} 300