1/*
2
3Copyright 1986, 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 in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from The Open Group.
24
25*/
26
27#ifdef HAVE_CONFIG_H
28#include <config.h>
29#endif
30#include "Xlibint.h"
31#include "Xintatom.h"
32
33static
34char *_XGetAtomName(
35    Display *dpy,
36    Atom atom)
37{
38    xResourceReq *req;
39    register Entry *table;
40    register int idx;
41    register Entry e;
42
43    if (dpy->atoms) {
44	table = dpy->atoms->table;
45	for (idx = TABLESIZE; --idx >= 0; ) {
46	    if ((e = *table++) && (e->atom == atom)) {
47		return strdup(EntryName(e));
48	    }
49	}
50    }
51    GetResReq(GetAtomName, atom, req);
52    return (char *)NULL;
53}
54
55char *XGetAtomName(
56    register Display *dpy,
57    Atom atom)
58{
59    xGetAtomNameReply rep;
60    char *name;
61
62    LockDisplay(dpy);
63    if ((name = _XGetAtomName(dpy, atom))) {
64	UnlockDisplay(dpy);
65	return name;
66    }
67    if (_XReply(dpy, (xReply *)&rep, 0, xFalse) == 0) {
68	UnlockDisplay(dpy);
69	SyncHandle();
70	return(NULL);
71    }
72    if ((name = Xmalloc(rep.nameLength + 1))) {
73	_XReadPad(dpy, name, (long)rep.nameLength);
74	name[rep.nameLength] = '\0';
75	_XUpdateAtomCache(dpy, name, atom, 0, -1, 0);
76    } else {
77	_XEatDataWords(dpy, rep.length);
78	name = (char *) NULL;
79    }
80    UnlockDisplay(dpy);
81    SyncHandle();
82    return(name);
83}
84
85typedef struct {
86    uint64_t start_seq;
87    uint64_t stop_seq;
88    Atom *atoms;
89    char **names;
90    int idx;
91    int count;
92    Status status;
93} _XGetAtomNameState;
94
95static
96Bool _XGetAtomNameHandler(
97    register Display *dpy,
98    register xReply *rep,
99    char *buf,
100    int len,
101    XPointer data)
102{
103    register _XGetAtomNameState *state;
104    xGetAtomNameReply replbuf;
105    register xGetAtomNameReply *repl;
106    uint64_t last_request_read = X_DPY_GET_LAST_REQUEST_READ(dpy);
107
108    state = (_XGetAtomNameState *)data;
109    if (last_request_read < state->start_seq ||
110	last_request_read > state->stop_seq)
111	return False;
112    while (state->idx < state->count && state->names[state->idx])
113	state->idx++;
114    if (state->idx >= state->count)
115	return False;
116    if (rep->generic.type == X_Error) {
117	state->status = 0;
118	return False;
119    }
120    repl = (xGetAtomNameReply *)
121	_XGetAsyncReply(dpy, (char *)&replbuf, rep, buf, len,
122			(SIZEOF(xGetAtomNameReply) - SIZEOF(xReply)) >> 2,
123			False);
124    state->names[state->idx] = Xmalloc(repl->nameLength + 1);
125    _XGetAsyncData(dpy, state->names[state->idx], buf, len,
126		   SIZEOF(xGetAtomNameReply), repl->nameLength,
127		   repl->length << 2);
128    if (state->names[state->idx]) {
129	state->names[state->idx][repl->nameLength] = '\0';
130	_XUpdateAtomCache(dpy, state->names[state->idx],
131			  state->atoms[state->idx], 0, -1, 0);
132    } else {
133	state->status = 0;
134    }
135    return True;
136}
137
138Status
139XGetAtomNames (
140    Display *dpy,
141    Atom *atoms,
142    int count,
143    char **names_return)
144{
145    _XAsyncHandler async;
146    _XGetAtomNameState async_state;
147    xGetAtomNameReply rep;
148    int i;
149    int missed = -1;
150
151    LockDisplay(dpy);
152    async_state.start_seq = X_DPY_GET_REQUEST(dpy) + 1;
153    async_state.atoms = atoms;
154    async_state.names = names_return;
155    async_state.idx = 0;
156    async_state.count = count - 1;
157    async_state.status = 1;
158    async.next = dpy->async_handlers;
159    async.handler = _XGetAtomNameHandler;
160    async.data = (XPointer)&async_state;
161    dpy->async_handlers = &async;
162    for (i = 0; i < count; i++) {
163	if (!(names_return[i] = _XGetAtomName(dpy, atoms[i]))) {
164	    missed = i;
165	    async_state.stop_seq = X_DPY_GET_REQUEST(dpy);
166	}
167    }
168    if (missed >= 0) {
169	if (_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
170	    if ((names_return[missed] = Xmalloc(rep.nameLength + 1))) {
171		_XReadPad(dpy, names_return[missed], (long)rep.nameLength);
172		names_return[missed][rep.nameLength] = '\0';
173		_XUpdateAtomCache(dpy, names_return[missed], atoms[missed],
174				  0, -1, 0);
175	    } else {
176		_XEatDataWords(dpy, rep.length);
177		async_state.status = 0;
178	    }
179	}
180    }
181    DeqAsyncHandler(dpy, &async);
182    UnlockDisplay(dpy);
183    if (missed >= 0)
184	SyncHandle();
185    return async_state.status;
186}
187