xlsatoms.c revision f5effb2e
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
30fdb3d228Smrg#include <stdio.h>
31fdb3d228Smrg#include <stdlib.h>
32f5effb2eSmrg#include <string.h>
33f5effb2eSmrg#include <xcb/xcb.h>
34f5effb2eSmrg#include <xcb/xproto.h>
35f5effb2eSmrg
36f5effb2eSmrg#define ATOMS_PER_BATCH 100 /* This number can be tuned
37f5effb2eSmrg				higher for fewer round-trips
38f5effb2eSmrg				lower for less bandwidth wasted */
39fdb3d228Smrg
409b41ff1aSmrgstatic char *ProgramName;
41f5effb2eSmrgstatic char *DisplayString;
42fdb3d228Smrg
43f5effb2eSmrgstatic void do_name ( xcb_connection_t *c, char *format, char *name );
44fdb3d228Smrgstatic int parse_range ( char *range, long *lowp, long *highp );
45f5effb2eSmrgstatic void do_range ( xcb_connection_t *c, char *format, char *range );
46f5effb2eSmrgstatic void list_atoms ( xcb_connection_t *c, char *format, int mask,
47fdb3d228Smrg			 long low, long high );
48fdb3d228Smrg
49fdb3d228Smrgstatic void
50fdb3d228Smrgusage(void)
51fdb3d228Smrg{
52fdb3d228Smrg    fprintf (stderr, "usage:  %s [-options...]\n\n", ProgramName);
53fdb3d228Smrg    fprintf (stderr, "where options include:\n");
54fdb3d228Smrg    fprintf (stderr,
55fdb3d228Smrg	     "    -display dpy            X server to which to connect\n");
56fdb3d228Smrg    fprintf (stderr,
57fdb3d228Smrg	     "    -format string          printf-style format to use\n");
58fdb3d228Smrg    fprintf (stderr,
59fdb3d228Smrg	     "    -range [num]-[num]      atom values to list\n");
60fdb3d228Smrg    fprintf (stderr,
61fdb3d228Smrg	     "    -name string            name of single atom to print\n");
62fdb3d228Smrg    putc ('\n', stderr);
63fdb3d228Smrg    exit (1);
64fdb3d228Smrg}
65fdb3d228Smrg
66fdb3d228Smrgint
67fdb3d228Smrgmain(int argc, char *argv[])
68fdb3d228Smrg{
69fdb3d228Smrg    char *displayname = NULL;
70fdb3d228Smrg    char *format = "%lu\t%s";
71fdb3d228Smrg    int i, doit;
72fdb3d228Smrg    int didit = 0;
73f5effb2eSmrg    xcb_connection_t *c = NULL;
74fdb3d228Smrg
75fdb3d228Smrg    ProgramName = argv[0];
76fdb3d228Smrg
77fdb3d228Smrg    for (doit = 0; doit < 2; doit++) {	/* pre-parse to get display */
78fdb3d228Smrg	for (i = 1; i < argc; i++) {
79fdb3d228Smrg	    char *arg = argv[i];
80fdb3d228Smrg
81fdb3d228Smrg	    if (arg[0] == '-') {
82fdb3d228Smrg		switch (arg[1]) {
83fdb3d228Smrg		  case 'd':			/* -display dpy */
84fdb3d228Smrg		    if (++i >= argc) usage ();
85fdb3d228Smrg		    if (!doit) displayname = argv[i];
86fdb3d228Smrg		    continue;
87fdb3d228Smrg		  case 'f':			/* -format string */
88fdb3d228Smrg		    if (++i >= argc) usage ();
89fdb3d228Smrg		    if (doit) format = argv[i];
90fdb3d228Smrg		    continue;
91fdb3d228Smrg		  case 'r':			/* -range num-[num] */
92fdb3d228Smrg		    if (++i >= argc) usage ();
93fdb3d228Smrg		    if (doit) {
94f5effb2eSmrg			do_range (c, format, argv[i]);
95fdb3d228Smrg			didit = 1;
96fdb3d228Smrg		    }
97fdb3d228Smrg		    continue;
98fdb3d228Smrg		  case 'n':			/* -name string */
99fdb3d228Smrg		    if (++i >= argc) usage ();
100fdb3d228Smrg		    if (doit) {
101f5effb2eSmrg			do_name (c, format, argv[i]);
102fdb3d228Smrg			didit = 1;
103fdb3d228Smrg		    }
104fdb3d228Smrg		    continue;
105fdb3d228Smrg		}
106fdb3d228Smrg	    }
107fdb3d228Smrg	    usage ();
108fdb3d228Smrg	}
109fdb3d228Smrg	if (!doit) {
110f5effb2eSmrg	    DisplayString = displayname;
111f5effb2eSmrg	    if (!DisplayString)
112f5effb2eSmrg		DisplayString = getenv("DISPLAY");
113f5effb2eSmrg	    if (!DisplayString)
114f5effb2eSmrg		DisplayString = "";
115f5effb2eSmrg	    c = xcb_connect(displayname, NULL);
116f5effb2eSmrg	    if (!c || xcb_connection_has_error(c)) {
117fdb3d228Smrg		fprintf (stderr, "%s:  unable to open display \"%s\"\n",
118f5effb2eSmrg			 ProgramName, DisplayString);
119fdb3d228Smrg		exit (1);
120fdb3d228Smrg	    }
121fdb3d228Smrg	} else
122fdb3d228Smrg	    if (!didit)		/* no options, default is list all */
123f5effb2eSmrg		list_atoms(c, format, 0, 0, 0);
124fdb3d228Smrg    }
125fdb3d228Smrg
126f5effb2eSmrg    xcb_disconnect(c);
127fdb3d228Smrg    exit (0);
128fdb3d228Smrg}
129fdb3d228Smrg
130fdb3d228Smrgstatic void
131f5effb2eSmrgdo_name(xcb_connection_t *c, char *format, char *name)
132fdb3d228Smrg{
133f5effb2eSmrg    xcb_intern_atom_reply_t *a = xcb_intern_atom_reply(c,
134f5effb2eSmrg	xcb_intern_atom_unchecked(c, 1, strlen(name), name), NULL);
135fdb3d228Smrg
136f5effb2eSmrg    if (a && a->atom != XCB_NONE) {
137f5effb2eSmrg	printf (format, (unsigned long) a->atom, name);
138fdb3d228Smrg	putchar ('\n');
139fdb3d228Smrg    } else {
140fdb3d228Smrg	fprintf (stderr, "%s:  no atom named \"%s\" on server \"%s\"\n",
141f5effb2eSmrg		 ProgramName, name, DisplayString);
142fdb3d228Smrg    }
143f5effb2eSmrg
144f5effb2eSmrg    if (a)
145f5effb2eSmrg	free(a);
146fdb3d228Smrg}
147fdb3d228Smrg
148fdb3d228Smrg
149fdb3d228Smrg#define RangeLow (1 << 0)
150fdb3d228Smrg#define RangeHigh (1 << 1)
151fdb3d228Smrg
152fdb3d228Smrgstatic int
153fdb3d228Smrgparse_range(char *range, long *lowp, long *highp)
154fdb3d228Smrg{
155fdb3d228Smrg    char *dash;
156fdb3d228Smrg    int mask = 0;
157fdb3d228Smrg
158fdb3d228Smrg    if (!range) {			/* NULL means default */
159fdb3d228Smrg	*lowp = 1;
160fdb3d228Smrg	return RangeLow;
161fdb3d228Smrg    }
162fdb3d228Smrg
163fdb3d228Smrg    dash = strchr(range, '-');
164fdb3d228Smrg    if (!dash) dash = strchr(range, ':');
165fdb3d228Smrg    if (dash) {
166fdb3d228Smrg	if (dash == range) {		/* -high */
167fdb3d228Smrg	    *lowp = 1;
168fdb3d228Smrg	} else {			/* low-[high] */
169fdb3d228Smrg	    *dash = '\0';
170fdb3d228Smrg	    *lowp = atoi (range);
171fdb3d228Smrg	    *dash = '-';
172fdb3d228Smrg	}
173fdb3d228Smrg	mask |= RangeLow;
174fdb3d228Smrg	dash++;
175fdb3d228Smrg	if (*dash) {			/* [low]-high */
176fdb3d228Smrg	    *highp = atoi (dash);
177fdb3d228Smrg	    mask |= RangeHigh;
178fdb3d228Smrg	}
179fdb3d228Smrg    } else {				/* number (low == high) */
180fdb3d228Smrg	*lowp = *highp = atoi (range);
181fdb3d228Smrg	mask |= (RangeLow | RangeHigh);
182fdb3d228Smrg    }
183fdb3d228Smrg
184fdb3d228Smrg    return mask;
185fdb3d228Smrg}
186fdb3d228Smrg
187fdb3d228Smrgstatic void
188f5effb2eSmrgdo_range(xcb_connection_t *c, char *format, char *range)
189fdb3d228Smrg{
190fdb3d228Smrg    int mask;
191fdb3d228Smrg    long low, high;
192fdb3d228Smrg
193fdb3d228Smrg    mask = parse_range (range, &low, &high);
194f5effb2eSmrg    list_atoms (c, format, mask, low, high);
195fdb3d228Smrg}
196fdb3d228Smrg
197f5effb2eSmrgstatic int
198f5effb2eSmrgsay_batch(xcb_connection_t *c, char *format, xcb_get_atom_name_cookie_t *cookie, long low, long count)
199fdb3d228Smrg{
200f5effb2eSmrg    xcb_generic_error_t *e;
201f5effb2eSmrg    char atom_name[1024];
202f5effb2eSmrg    long i;
203f5effb2eSmrg    int done = 0;
204f5effb2eSmrg
205f5effb2eSmrg    for (i = 0; i < count; i++)
206f5effb2eSmrg	cookie[i] = xcb_get_atom_name(c, i + low);
207f5effb2eSmrg
208f5effb2eSmrg    for (i = 0; i < count; i++) {
209f5effb2eSmrg	xcb_get_atom_name_reply_t *r;
210f5effb2eSmrg	r = xcb_get_atom_name_reply(c, cookie[i], &e);
211f5effb2eSmrg	if (r) {
212f5effb2eSmrg	    /* We could just use %.*s in 'format', but we want to be compatible
213f5effb2eSmrg	       with legacy command line usage */
214f5effb2eSmrg	    snprintf(atom_name, sizeof(atom_name), "%.*s",
215f5effb2eSmrg		r->name_len, xcb_get_atom_name_name(r));
216f5effb2eSmrg
217f5effb2eSmrg	    printf (format, i + low, atom_name);
218f5effb2eSmrg	    putchar ('\n');
219f5effb2eSmrg	    free(r);
220f5effb2eSmrg	}
221f5effb2eSmrg	if (e) {
222f5effb2eSmrg	    done = 1;
223f5effb2eSmrg	    free(e);
224f5effb2eSmrg	}
225fdb3d228Smrg    }
226f5effb2eSmrg
227f5effb2eSmrg    return done;
228fdb3d228Smrg}
229fdb3d228Smrg
230fdb3d228Smrgstatic void
231f5effb2eSmrglist_atoms(xcb_connection_t *c, char *format, int mask, long low, long high)
232fdb3d228Smrg{
233f5effb2eSmrg    xcb_get_atom_name_cookie_t *cookie_jar;
234f5effb2eSmrg    int done = 0;
235fdb3d228Smrg
236fdb3d228Smrg    switch (mask) {
237fdb3d228Smrg      case RangeHigh:
238fdb3d228Smrg	low = 1;
239fdb3d228Smrg	/* fall through */
240fdb3d228Smrg      case (RangeLow | RangeHigh):
241f5effb2eSmrg	cookie_jar = malloc((high - low + 1) * sizeof(xcb_get_atom_name_cookie_t));
242f5effb2eSmrg        if (!cookie_jar) {
243f5effb2eSmrg	    fprintf(stderr, "Out of memory allocating space for %ld atom requests\n", high - low);
244f5effb2eSmrg	    return;
245fdb3d228Smrg	}
246f5effb2eSmrg
247f5effb2eSmrg	say_batch(c, format, cookie_jar, low, high - low + 1);
248f5effb2eSmrg	free(cookie_jar);
249fdb3d228Smrg	break;
250fdb3d228Smrg
251fdb3d228Smrg      default:
252fdb3d228Smrg	low = 1;
253fdb3d228Smrg	/* fall through */
254fdb3d228Smrg      case RangeLow:
255f5effb2eSmrg	cookie_jar = malloc(ATOMS_PER_BATCH * sizeof(xcb_get_atom_name_cookie_t));
256f5effb2eSmrg        if (!cookie_jar) {
257f5effb2eSmrg	    fprintf(stderr, "Out of memory allocating space for %ld atom requests\n", (long) ATOMS_PER_BATCH);
258f5effb2eSmrg	    return;
259f5effb2eSmrg	}
260f5effb2eSmrg	while (!done) {
261f5effb2eSmrg	    done = say_batch(c, format, cookie_jar, low, ATOMS_PER_BATCH);
262f5effb2eSmrg	    low += ATOMS_PER_BATCH;
263fdb3d228Smrg	}
264f5effb2eSmrg	free(cookie_jar);
265fdb3d228Smrg	break;
266fdb3d228Smrg    }
267fdb3d228Smrg
268fdb3d228Smrg    return;
269fdb3d228Smrg}
270