xlsatoms.c revision 585aa3f7
1fdb3d228Smrg/*
2fdb3d228Smrg *
3fdb3d228SmrgCopyright 1989, 1998  The Open Group
4f5effb2eSmrgCopyright 2009 Open Text Corporation
5fdb3d228Smrg
6fdb3d228SmrgPermission to use, copy, modify, distribute, and sell this software and its
7fdb3d228Smrgdocumentation for any purpose is hereby granted without fee, provided that
8fdb3d228Smrgthe above copyright notice appear in all copies and that both that
9fdb3d228Smrgcopyright notice and this permission notice appear in supporting
10fdb3d228Smrgdocumentation.
11fdb3d228Smrg
12fdb3d228SmrgThe above copyright notice and this permission notice shall be included in
13fdb3d228Smrgall copies or substantial portions of the Software.
14fdb3d228Smrg
15fdb3d228SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16fdb3d228SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17fdb3d228SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18fdb3d228SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19fdb3d228SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20fdb3d228SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21fdb3d228Smrg
22fdb3d228SmrgExcept as contained in this notice, the name of The Open Group shall not be
23fdb3d228Smrgused in advertising or otherwise to promote the sale, use or other dealings
24fdb3d228Smrgin this Software without prior written authorization from The Open Group.
25fdb3d228Smrg *
26fdb3d228Smrg * Author:  Jim Fulton, MIT X Consortium
27f5effb2eSmrg * Author:  Peter Harris, Open Text Corporation
28fdb3d228Smrg */
29fdb3d228Smrg
30585aa3f7Smrg#ifdef HAVE_CONFIG_H
31585aa3f7Smrg# include "config.h"
32585aa3f7Smrg#endif
33585aa3f7Smrg
34fdb3d228Smrg#include <stdio.h>
35fdb3d228Smrg#include <stdlib.h>
36f5effb2eSmrg#include <string.h>
37f5effb2eSmrg#include <xcb/xcb.h>
38f5effb2eSmrg#include <xcb/xproto.h>
39f5effb2eSmrg
40f5effb2eSmrg#define ATOMS_PER_BATCH 100 /* This number can be tuned
41f5effb2eSmrg				higher for fewer round-trips
42f5effb2eSmrg				lower for less bandwidth wasted */
43fdb3d228Smrg
447d575c90Smrgstatic const char *ProgramName;
457d575c90Smrgstatic const char *DisplayString;
46fdb3d228Smrg
477d575c90Smrgstatic void do_name ( xcb_connection_t *c, const char *format, char *name );
48fdb3d228Smrgstatic int parse_range ( char *range, long *lowp, long *highp );
497d575c90Smrgstatic void do_range ( xcb_connection_t *c, const char *format, char *range );
507d575c90Smrgstatic void list_atoms ( xcb_connection_t *c, const char *format, int mask,
51fdb3d228Smrg			 long low, long high );
52fdb3d228Smrg
53fdb3d228Smrgstatic void
54585aa3f7Smrgusage(const char *errmsg)
55fdb3d228Smrg{
56585aa3f7Smrg    if (errmsg != NULL)
57585aa3f7Smrg	fprintf (stderr, "%s: %s\n\n", ProgramName, errmsg);
58585aa3f7Smrg
59585aa3f7Smrg    fprintf (stderr, "usage:  %s [-options...]\n\n%s\n", ProgramName,
60585aa3f7Smrg	     "where options include:\n"
61585aa3f7Smrg	     "    -display dpy            X server to which to connect\n"
62585aa3f7Smrg	     "    -format string          printf-style format to use\n"
63585aa3f7Smrg	     "    -range [num]-[num]      atom values to list\n"
64585aa3f7Smrg	     "    -name string            name of single atom to print\n"
65585aa3f7Smrg	     "    -version                print program version\n"
66585aa3f7Smrg	);
67fdb3d228Smrg    exit (1);
68fdb3d228Smrg}
69fdb3d228Smrg
70fdb3d228Smrgint
71fdb3d228Smrgmain(int argc, char *argv[])
72fdb3d228Smrg{
73fdb3d228Smrg    char *displayname = NULL;
747d575c90Smrg    const char *format = "%lu\t%s";
75fdb3d228Smrg    int i, doit;
76fdb3d228Smrg    int didit = 0;
77f5effb2eSmrg    xcb_connection_t *c = NULL;
78fdb3d228Smrg
79fdb3d228Smrg    ProgramName = argv[0];
80fdb3d228Smrg
81fdb3d228Smrg    for (doit = 0; doit < 2; doit++) {	/* pre-parse to get display */
82fdb3d228Smrg	for (i = 1; i < argc; i++) {
83fdb3d228Smrg	    char *arg = argv[i];
84fdb3d228Smrg
85fdb3d228Smrg	    if (arg[0] == '-') {
86fdb3d228Smrg		switch (arg[1]) {
87fdb3d228Smrg		  case 'd':			/* -display dpy */
88585aa3f7Smrg		    if (++i >= argc) usage ("-display requires an argument");
89fdb3d228Smrg		    if (!doit) displayname = argv[i];
90fdb3d228Smrg		    continue;
91fdb3d228Smrg		  case 'f':			/* -format string */
92585aa3f7Smrg		    if (++i >= argc) usage ("-format requires an argument");
93fdb3d228Smrg		    if (doit) format = argv[i];
94fdb3d228Smrg		    continue;
95fdb3d228Smrg		  case 'r':			/* -range num-[num] */
96585aa3f7Smrg		    if (++i >= argc) usage ("-range requires an argument");
97fdb3d228Smrg		    if (doit) {
98f5effb2eSmrg			do_range (c, format, argv[i]);
99fdb3d228Smrg			didit = 1;
100fdb3d228Smrg		    }
101fdb3d228Smrg		    continue;
102fdb3d228Smrg		  case 'n':			/* -name string */
103585aa3f7Smrg		    if (++i >= argc) usage ("-name requires an argument");
104fdb3d228Smrg		    if (doit) {
105f5effb2eSmrg			do_name (c, format, argv[i]);
106fdb3d228Smrg			didit = 1;
107fdb3d228Smrg		    }
108fdb3d228Smrg		    continue;
109585aa3f7Smrg		  case 'v':
110585aa3f7Smrg		    if (strcmp(arg, "-version") == 0) {
111585aa3f7Smrg			puts(PACKAGE_STRING);
112585aa3f7Smrg			exit(0);
113585aa3f7Smrg		    }
114585aa3f7Smrg		    /* else FALLTHROUGH to unrecognized arg case below */
115fdb3d228Smrg		}
116fdb3d228Smrg	    }
117585aa3f7Smrg	    fprintf (stderr, "%s: unrecognized argument %s\n\n",
118585aa3f7Smrg		     ProgramName, arg);
119585aa3f7Smrg	    usage (NULL);
120fdb3d228Smrg	}
121fdb3d228Smrg	if (!doit) {
122f5effb2eSmrg	    DisplayString = displayname;
123f5effb2eSmrg	    if (!DisplayString)
124f5effb2eSmrg		DisplayString = getenv("DISPLAY");
125f5effb2eSmrg	    if (!DisplayString)
126f5effb2eSmrg		DisplayString = "";
127f5effb2eSmrg	    c = xcb_connect(displayname, NULL);
128f5effb2eSmrg	    if (!c || xcb_connection_has_error(c)) {
129fdb3d228Smrg		fprintf (stderr, "%s:  unable to open display \"%s\"\n",
130f5effb2eSmrg			 ProgramName, DisplayString);
131fdb3d228Smrg		exit (1);
132fdb3d228Smrg	    }
133fdb3d228Smrg	} else
134fdb3d228Smrg	    if (!didit)		/* no options, default is list all */
135f5effb2eSmrg		list_atoms(c, format, 0, 0, 0);
136fdb3d228Smrg    }
137fdb3d228Smrg
138f5effb2eSmrg    xcb_disconnect(c);
139fdb3d228Smrg    exit (0);
140fdb3d228Smrg}
141fdb3d228Smrg
142fdb3d228Smrgstatic void
1437d575c90Smrgdo_name(xcb_connection_t *c, const char *format, char *name)
144fdb3d228Smrg{
145f5effb2eSmrg    xcb_intern_atom_reply_t *a = xcb_intern_atom_reply(c,
146f5effb2eSmrg	xcb_intern_atom_unchecked(c, 1, strlen(name), name), NULL);
147fdb3d228Smrg
148f5effb2eSmrg    if (a && a->atom != XCB_NONE) {
149f5effb2eSmrg	printf (format, (unsigned long) a->atom, name);
150fdb3d228Smrg	putchar ('\n');
151fdb3d228Smrg    } else {
152fdb3d228Smrg	fprintf (stderr, "%s:  no atom named \"%s\" on server \"%s\"\n",
153f5effb2eSmrg		 ProgramName, name, DisplayString);
154fdb3d228Smrg    }
155f5effb2eSmrg
156f5effb2eSmrg    if (a)
157f5effb2eSmrg	free(a);
158fdb3d228Smrg}
159fdb3d228Smrg
160fdb3d228Smrg
161fdb3d228Smrg#define RangeLow (1 << 0)
162fdb3d228Smrg#define RangeHigh (1 << 1)
163fdb3d228Smrg
164fdb3d228Smrgstatic int
165fdb3d228Smrgparse_range(char *range, long *lowp, long *highp)
166fdb3d228Smrg{
167fdb3d228Smrg    char *dash;
168fdb3d228Smrg    int mask = 0;
169fdb3d228Smrg
170fdb3d228Smrg    if (!range) {			/* NULL means default */
171fdb3d228Smrg	*lowp = 1;
172fdb3d228Smrg	return RangeLow;
173fdb3d228Smrg    }
174fdb3d228Smrg
175fdb3d228Smrg    dash = strchr(range, '-');
176fdb3d228Smrg    if (!dash) dash = strchr(range, ':');
177fdb3d228Smrg    if (dash) {
178fdb3d228Smrg	if (dash == range) {		/* -high */
179fdb3d228Smrg	    *lowp = 1;
180fdb3d228Smrg	} else {			/* low-[high] */
181fdb3d228Smrg	    *dash = '\0';
182fdb3d228Smrg	    *lowp = atoi (range);
183fdb3d228Smrg	    *dash = '-';
184fdb3d228Smrg	}
185fdb3d228Smrg	mask |= RangeLow;
186fdb3d228Smrg	dash++;
187fdb3d228Smrg	if (*dash) {			/* [low]-high */
188fdb3d228Smrg	    *highp = atoi (dash);
189fdb3d228Smrg	    mask |= RangeHigh;
190fdb3d228Smrg	}
191fdb3d228Smrg    } else {				/* number (low == high) */
192fdb3d228Smrg	*lowp = *highp = atoi (range);
193fdb3d228Smrg	mask |= (RangeLow | RangeHigh);
194fdb3d228Smrg    }
195fdb3d228Smrg
196fdb3d228Smrg    return mask;
197fdb3d228Smrg}
198fdb3d228Smrg
199fdb3d228Smrgstatic void
2007d575c90Smrgdo_range(xcb_connection_t *c, const char *format, char *range)
201fdb3d228Smrg{
202fdb3d228Smrg    int mask;
203fdb3d228Smrg    long low, high;
204fdb3d228Smrg
205fdb3d228Smrg    mask = parse_range (range, &low, &high);
206f5effb2eSmrg    list_atoms (c, format, mask, low, high);
207fdb3d228Smrg}
208fdb3d228Smrg
209f5effb2eSmrgstatic int
2107d575c90Smrgsay_batch(xcb_connection_t *c, const char *format, xcb_get_atom_name_cookie_t *cookie, long low, long count)
211fdb3d228Smrg{
212f5effb2eSmrg    xcb_generic_error_t *e;
213f5effb2eSmrg    char atom_name[1024];
214f5effb2eSmrg    long i;
215f5effb2eSmrg    int done = 0;
216f5effb2eSmrg
217f5effb2eSmrg    for (i = 0; i < count; i++)
218f5effb2eSmrg	cookie[i] = xcb_get_atom_name(c, i + low);
219f5effb2eSmrg
220f5effb2eSmrg    for (i = 0; i < count; i++) {
221f5effb2eSmrg	xcb_get_atom_name_reply_t *r;
222f5effb2eSmrg	r = xcb_get_atom_name_reply(c, cookie[i], &e);
223f5effb2eSmrg	if (r) {
224f5effb2eSmrg	    /* We could just use %.*s in 'format', but we want to be compatible
225f5effb2eSmrg	       with legacy command line usage */
226f5effb2eSmrg	    snprintf(atom_name, sizeof(atom_name), "%.*s",
227f5effb2eSmrg		r->name_len, xcb_get_atom_name_name(r));
228f5effb2eSmrg
229f5effb2eSmrg	    printf (format, i + low, atom_name);
230f5effb2eSmrg	    putchar ('\n');
231f5effb2eSmrg	    free(r);
232f5effb2eSmrg	}
233f5effb2eSmrg	if (e) {
234f5effb2eSmrg	    done = 1;
235f5effb2eSmrg	    free(e);
236f5effb2eSmrg	}
237fdb3d228Smrg    }
238f5effb2eSmrg
239f5effb2eSmrg    return done;
240fdb3d228Smrg}
241fdb3d228Smrg
242fdb3d228Smrgstatic void
2437d575c90Smrglist_atoms(xcb_connection_t *c, const char *format, int mask, long low, long high)
244fdb3d228Smrg{
245f5effb2eSmrg    xcb_get_atom_name_cookie_t *cookie_jar;
246f5effb2eSmrg    int done = 0;
247fdb3d228Smrg
248fdb3d228Smrg    switch (mask) {
249fdb3d228Smrg      case RangeHigh:
250fdb3d228Smrg	low = 1;
251fdb3d228Smrg	/* fall through */
252fdb3d228Smrg      case (RangeLow | RangeHigh):
253f5effb2eSmrg	cookie_jar = malloc((high - low + 1) * sizeof(xcb_get_atom_name_cookie_t));
254f5effb2eSmrg        if (!cookie_jar) {
255f5effb2eSmrg	    fprintf(stderr, "Out of memory allocating space for %ld atom requests\n", high - low);
256f5effb2eSmrg	    return;
257fdb3d228Smrg	}
258f5effb2eSmrg
259f5effb2eSmrg	say_batch(c, format, cookie_jar, low, high - low + 1);
260f5effb2eSmrg	free(cookie_jar);
261fdb3d228Smrg	break;
262fdb3d228Smrg
263fdb3d228Smrg      default:
264fdb3d228Smrg	low = 1;
265fdb3d228Smrg	/* fall through */
266fdb3d228Smrg      case RangeLow:
267f5effb2eSmrg	cookie_jar = malloc(ATOMS_PER_BATCH * sizeof(xcb_get_atom_name_cookie_t));
268f5effb2eSmrg        if (!cookie_jar) {
269f5effb2eSmrg	    fprintf(stderr, "Out of memory allocating space for %ld atom requests\n", (long) ATOMS_PER_BATCH);
270f5effb2eSmrg	    return;
271f5effb2eSmrg	}
272f5effb2eSmrg	while (!done) {
273f5effb2eSmrg	    done = say_batch(c, format, cookie_jar, low, ATOMS_PER_BATCH);
274f5effb2eSmrg	    low += ATOMS_PER_BATCH;
275fdb3d228Smrg	}
276f5effb2eSmrg	free(cookie_jar);
277fdb3d228Smrg	break;
278fdb3d228Smrg    }
279fdb3d228Smrg
280fdb3d228Smrg    return;
281fdb3d228Smrg}
282