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