1ecce36beSmrg%{
2ecce36beSmrg
3ecce36beSmrg/* Rely on vasprintf (GNU extension) instead of vsnprintf if
4ecce36beSmrg   possible... */
5ecce36beSmrg#ifdef HAVE_VASPRINTF
6ecce36beSmrg#define _GNU_SOURCE
7ecce36beSmrg#include <stdio.h>
8ecce36beSmrg#endif
9ecce36beSmrg
10ecce36beSmrg#include <xcb/xcb.h>
11ecce36beSmrg#include <stdlib.h>
12ecce36beSmrg#include <stdarg.h>
13ecce36beSmrg#include "xcb_atom.h"
14ecce36beSmrg
15ecce36beSmrgdefine(`COUNT', 0)dnl
16ecce36beSmrgdefine(`DO', `const xcb_atom_t $1 = define(`COUNT', incr(COUNT))COUNT;')dnl
17ecce36beSmrginclude(atomlist.m4)`'dnl
18ecce36beSmrg%}
19ecce36beSmrg
20ecce36beSmrg%readonly-tables
21ecce36beSmrg%pic
22ecce36beSmrg%null-strings
23ecce36beSmrg%enum
24ecce36beSmrg%includes
25ecce36beSmrg%compare-strncmp
26ecce36beSmrg
27ecce36beSmrg%struct-type
28ecce36beSmrgstruct atom_map { int name; xcb_atom_t value; };
29ecce36beSmrg%%
30ecce36beSmrgdefine(`COUNT', 0)dnl
31ecce36beSmrgdefine(`DO', `$1,define(`COUNT', incr(COUNT))COUNT')dnl
32ecce36beSmrginclude(atomlist.m4)`'dnl
33ecce36beSmrg%%
34ecce36beSmrg
35ecce36beSmrgstatic const char atom_names[] =
36ecce36beSmrgdefine(`DO', `	"$1\0"')dnl
37ecce36beSmrginclude(atomlist.m4);
38ecce36beSmrg
39ecce36beSmrgstatic const uint16_t atom_name_offsets[] = {
40ecce36beSmrgdefine(`OFFSET', 0)dnl
41ecce36beSmrgdefine(`DO', `	OFFSET,define(`OFFSET', eval(OFFSET+1+len($1)))')dnl
42ecce36beSmrginclude(atomlist.m4)`'dnl
43ecce36beSmrg};
44ecce36beSmrg
45ecce36beSmrgxcb_atom_t xcb_atom_get(xcb_connection_t *connection, const char *atom_name)
46ecce36beSmrg{
47ecce36beSmrg	if(atom_name == NULL)
48ecce36beSmrg		return XCB_NONE;
49ecce36beSmrg	xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(connection,
50ecce36beSmrg		xcb_intern_atom(connection, 0, strlen(atom_name), atom_name), NULL);
51ecce36beSmrg	if(!reply)
52ecce36beSmrg		return XCB_NONE;
53ecce36beSmrg	xcb_atom_t atom = reply->atom;
54ecce36beSmrg	free(reply);
55ecce36beSmrg	return atom;
56ecce36beSmrg}
57ecce36beSmrg
58ecce36beSmrgxcb_atom_t xcb_atom_get_predefined(uint16_t name_len, const char *name)
59ecce36beSmrg{
60ecce36beSmrg	const struct atom_map *value = in_word_set(name, name_len);
61ecce36beSmrg	xcb_atom_t ret = XCB_NONE;
62ecce36beSmrg	if(value)
63ecce36beSmrg		ret = value->value;
64ecce36beSmrg	return ret;
65ecce36beSmrg}
66ecce36beSmrg
67ecce36beSmrgxcb_atom_fast_cookie_t xcb_atom_get_fast(xcb_connection_t *c, uint8_t only_if_exists, uint16_t name_len, const char *name)
68ecce36beSmrg{
69ecce36beSmrg	xcb_atom_fast_cookie_t cookie;
70ecce36beSmrg
71ecce36beSmrg	if((cookie.u.atom = xcb_atom_get_predefined(name_len, name)) != XCB_NONE)
72ecce36beSmrg	{
73ecce36beSmrg		cookie.tag = TAG_VALUE;
74ecce36beSmrg		return cookie;
75ecce36beSmrg	}
76ecce36beSmrg
77ecce36beSmrg	cookie.tag = TAG_COOKIE;
78ecce36beSmrg	cookie.u.cookie = xcb_intern_atom(c, only_if_exists, name_len, name);
79ecce36beSmrg	return cookie;
80ecce36beSmrg}
81ecce36beSmrg
82ecce36beSmrgxcb_atom_t xcb_atom_get_fast_reply(xcb_connection_t *c, xcb_atom_fast_cookie_t cookie, xcb_generic_error_t **e)
83ecce36beSmrg{
84ecce36beSmrg	switch(cookie.tag)
85ecce36beSmrg	{
86ecce36beSmrg		xcb_intern_atom_reply_t *reply;
87ecce36beSmrg	case TAG_VALUE:
88ecce36beSmrg		if(e)
89ecce36beSmrg			*e = 0;
90ecce36beSmrg		break;
91ecce36beSmrg	case TAG_COOKIE:
92ecce36beSmrg		reply = xcb_intern_atom_reply(c, cookie.u.cookie, e);
93ecce36beSmrg		if(reply)
94ecce36beSmrg		{
95ecce36beSmrg			cookie.u.atom = reply->atom;
96ecce36beSmrg			free(reply);
97ecce36beSmrg		}
98ecce36beSmrg		else
99ecce36beSmrg			cookie.u.atom = XCB_NONE;
100ecce36beSmrg		break;
101ecce36beSmrg	}
102ecce36beSmrg	return cookie.u.atom;
103ecce36beSmrg}
104ecce36beSmrg
105ecce36beSmrgconst char *xcb_atom_get_name_predefined(xcb_atom_t atom)
106ecce36beSmrg{
107ecce36beSmrg	if(atom <= 0 || atom > (sizeof(atom_name_offsets) / sizeof(*atom_name_offsets)))
108ecce36beSmrg		return 0;
109ecce36beSmrg	return atom_names + atom_name_offsets[atom - 1];
110ecce36beSmrg}
111ecce36beSmrg
112ecce36beSmrgint xcb_atom_get_name(xcb_connection_t *c, xcb_atom_t atom, const char **namep, int *lengthp)
113ecce36beSmrg{
114ecce36beSmrg	static char buf[100];
115ecce36beSmrg	const char *name = xcb_atom_get_name_predefined(atom);
116ecce36beSmrg	int namelen;
117ecce36beSmrg	xcb_get_atom_name_cookie_t atomc;
118ecce36beSmrg	xcb_get_atom_name_reply_t *atomr;
119ecce36beSmrg	if(name)
120ecce36beSmrg	{
121ecce36beSmrg		*namep = name;
122ecce36beSmrg		*lengthp = strlen(name);
123ecce36beSmrg		return 1;
124ecce36beSmrg	}
125ecce36beSmrg	atomc = xcb_get_atom_name(c, atom);
126ecce36beSmrg	atomr = xcb_get_atom_name_reply(c, atomc, 0);
127ecce36beSmrg	if(!atomr)
128ecce36beSmrg		return 0;
129ecce36beSmrg	namelen = xcb_get_atom_name_name_length(atomr);
130ecce36beSmrg	if(namelen > sizeof(buf))
131ecce36beSmrg		namelen = sizeof(buf);
132ecce36beSmrg	*lengthp = namelen;
133ecce36beSmrg	memcpy(buf, xcb_get_atom_name_name(atomr), namelen);
134ecce36beSmrg	*namep = buf;
135ecce36beSmrg	free(atomr);
136ecce36beSmrg	return 1;
137ecce36beSmrg}
138ecce36beSmrg
139ecce36beSmrgstatic char *makename(const char *fmt, ...)
140ecce36beSmrg{
141ecce36beSmrg	char *ret;
142ecce36beSmrg	int n;
143ecce36beSmrg	va_list ap;
144ecce36beSmrg
145ecce36beSmrg#ifndef HAVE_VASPRINTF
146ecce36beSmrg	char *np;
147ecce36beSmrg	int size = 64;
148ecce36beSmrg
149ecce36beSmrg	/* First allocate 'size' bytes, should be enough usually */
150ecce36beSmrg	if((ret = malloc(size)) == NULL)
151ecce36beSmrg		return NULL;
152ecce36beSmrg
153ecce36beSmrg	while(1)
154ecce36beSmrg	{
155ecce36beSmrg		va_start(ap, fmt);
156ecce36beSmrg		n = vsnprintf(ret, size, fmt, ap);
157ecce36beSmrg		va_end(ap);
158ecce36beSmrg
159ecce36beSmrg		if(n < 0)
160ecce36beSmrg			return NULL;
161ecce36beSmrg
162ecce36beSmrg		if(n < size)
163ecce36beSmrg			return ret;
164ecce36beSmrg
165ecce36beSmrg		size = n + 1;
166ecce36beSmrg		if((np = realloc(ret, size)) == NULL)
167ecce36beSmrg		{
168ecce36beSmrg			free(ret);
169ecce36beSmrg			return NULL;
170ecce36beSmrg		}
171ecce36beSmrg
172ecce36beSmrg		ret = np;
173ecce36beSmrg	}
174ecce36beSmrg#else
175ecce36beSmrg	va_start(ap, fmt);
176ecce36beSmrg	n = vasprintf(&ret, fmt, ap);
177ecce36beSmrg	va_end(ap);
178ecce36beSmrg
179ecce36beSmrg	if(n < 0)
180ecce36beSmrg		return NULL;
181ecce36beSmrg
182ecce36beSmrg	return ret;
183ecce36beSmrg#endif
184ecce36beSmrg}
185ecce36beSmrg
186ecce36beSmrgchar *xcb_atom_name_by_screen(const char *base, uint8_t screen)
187ecce36beSmrg{
188ecce36beSmrg	return makename("%s_S%u", base, screen);
189ecce36beSmrg}
190ecce36beSmrg
191ecce36beSmrgchar *xcb_atom_name_by_resource(const char *base, uint32_t resource)
192ecce36beSmrg{
193ecce36beSmrg	return makename("%s_R%08X", base, resource);
194ecce36beSmrg}
195ecce36beSmrg
196ecce36beSmrgchar *xcb_atom_name_unique(const char *base, uint32_t id)
197ecce36beSmrg{
198ecce36beSmrg	if(base)
199ecce36beSmrg		return makename("%s_U%lu", base, id);
200ecce36beSmrg	else
201ecce36beSmrg		return makename("U%lu", id);
202ecce36beSmrg}
203