summaryrefslogtreecommitdiff
path: root/app/xprop/xprop.c
diff options
context:
space:
mode:
authorMatthieu Herrb <matthieu@cvs.openbsd.org>2009-10-24 15:10:43 +0000
committerMatthieu Herrb <matthieu@cvs.openbsd.org>2009-10-24 15:10:43 +0000
commit30d8d367bb6977fc985e93c1b2d9e6fc29d2bb5c (patch)
treeee6faed8e27503a5f17a9a4b47dc5ee0c99636fb /app/xprop/xprop.c
parentec8c4ef3c6151d54c632f64bd5f960b4c6e7d9d8 (diff)
Update to xprop 1.1.0
Diffstat (limited to 'app/xprop/xprop.c')
-rw-r--r--app/xprop/xprop.c158
1 files changed, 155 insertions, 3 deletions
diff --git a/app/xprop/xprop.c b/app/xprop/xprop.c
index f1bf02a41..8261b1530 100644
--- a/app/xprop/xprop.c
+++ b/app/xprop/xprop.c
@@ -45,6 +45,9 @@ from The Open Group.
#include <wctype.h>
#endif
#include <locale.h>
+#ifdef HAVE_LANGINFO_H
+#include <langinfo.h>
+#endif
#ifndef HAVE_WCTYPE_H
#define iswprint(x) isprint(x)
@@ -355,7 +358,7 @@ typedef struct _propertyRec {
"?m3(\t\twindow id # to use for icon: $4\n)"\
"?m4(\t\tstarting position for icon: $5, $6\n)"\
"?m6(\t\twindow id # of group leader: $8\n)"\
-"?m8(\t\tThe visible hint bit is set\n)"
+"?m8(\t\tThe urgency hint bit is set\n)"
#define WM_ICON_SIZE_DFORMAT ":\n"\
"\t\tminimum icon size: $0 by $1\n"\
@@ -416,6 +419,7 @@ static propertyRec windowPropTable[] = {
{"WM_NAME", XA_WM_NAME, "8t", 0 },
{"WM_PROTOCOLS", 0, "32a", ": protocols $0+\n"},
{"WM_SIZE_HINTS", XA_WM_SIZE_HINTS,"32mii", WM_SIZE_HINTS_DFORMAT },
+ {"_NET_WM_ICON", 0, "32o", 0 },
{"WM_STATE", 0, "32cx", WM_STATE_DFORMAT}
};
#undef ARC_DFORMAT
@@ -740,6 +744,113 @@ Format_Len_String (const char *string, int len)
return result;
}
+static int
+is_utf8_locale (void)
+{
+#ifdef HAVE_LANGINFO_H
+ char *charmap = nl_langinfo (CODESET);
+
+ return charmap && strcmp (charmap, "UTF-8") == 0;
+#else
+ return 0;
+#endif
+}
+
+static const char *
+Format_Icons (const unsigned long *icon, int len)
+{
+ char *result = NULL, *tail = NULL;
+ int alloced;
+ const unsigned long *end = icon + len / sizeof (unsigned long);
+
+ alloced = 0;
+
+ while (icon < end)
+ {
+ unsigned long width, height;
+ int w, h;
+ int offset;
+
+ width = *icon++;
+ height = *icon++;
+
+ offset = (tail - result);
+
+ alloced += 80; /* For the header */
+ alloced += (width*4 + 8) * height; /* For the rows (plus padding) */
+
+ result = Realloc (result, alloced);
+ tail = &result[offset];
+
+ if (end - icon < width * height)
+ break;
+
+ tail += sprintf (tail, "\tIcon (%lu x %lu):\n", width, height);
+
+ if (width > 144 || height > 144)
+ {
+ tail += sprintf (tail, "\t(not shown)");
+ icon += width * height;
+ continue;
+ }
+
+ for (h = 0; h < height; ++h)
+ {
+ tail += sprintf (tail, "\t");
+
+ for (w = 0; w < width; ++w)
+ {
+ unsigned char a, r, g, b;
+ unsigned long pixel = *icon++;
+ unsigned long brightness;
+
+ a = (pixel & 0xff000000) >> 24;
+ r = (pixel & 0x00ff0000) >> 16;
+ g = (pixel & 0x0000ff00) >> 8;
+ b = (pixel & 0x000000ff);
+
+ brightness =
+ (a / 255.0) * (1000 - ((299 * (r / 255.0)) +
+ (587 * (g / 255.0)) +
+ (114 * (b / 255.0))));
+
+ if (is_utf8_locale())
+ {
+ static const char palette[][4] =
+ {
+ " ",
+ "\342\226\221", /* 25% */
+ "\342\226\222", /* 50% */
+ "\342\226\223", /* 75% */
+ "\342\226\210", /* 100% */
+ };
+ int idx;
+
+ idx = (brightness * ((sizeof (palette)/sizeof(palette[0])) - 1)) / 1000;
+
+ tail += sprintf (tail, "%s", palette[idx]);
+ }
+ else
+ {
+ static const char palette[] =
+ " .'`,^:\";~-_+<>i!lI?/\\|()1{}[]rcvunxzjftLCJUYXZO0Qoahkbdpqwm*WMB8&%$#@";
+ int idx;
+
+ idx = (brightness * (sizeof(palette) - 2)) / 1000;
+
+ *tail++ = palette[idx];
+ }
+ }
+
+ tail += sprintf (tail, "\n");
+ }
+
+ tail += sprintf (tail, "\n");
+ }
+
+ return result;
+}
+
static const char *
Format_Len_Text (const char *string, int len, Atom encoding)
{
@@ -859,6 +970,8 @@ Format_Thunk (thunk t, char format_char)
return Format_Mask_Word(value);
case 'a':
return Format_Atom(value);
+ case 'o':
+ return Format_Icons((const unsigned long *)t.extra_value, (int)t.value);
default:
Fatal_Error("bad format character: %c", format_char);
}
@@ -1112,6 +1225,20 @@ Extract_Len_String (const char **pointer, int *length, int size, const char **st
return len;
}
+static long
+Extract_Icon (const char **pointer, int *length, int size, const char **icon)
+{
+ int len = 0;
+
+ if (size != 32)
+ Fatal_Error("can't use format character 'o' with any size except 32.");
+
+ len = *length;
+ *icon = *pointer;
+ *length = 0;
+ return len;
+}
+
static thunk *
Break_Down_Property (const char *pointer, int length, Atom type, const char *format, int size)
{
@@ -1130,7 +1257,10 @@ Break_Down_Property (const char *pointer, int length, Atom type, const char *for
else if (format_char == 't') {
t.extra_encoding = type;
t.value = Extract_Len_String(&pointer,&length,size,&t.extra_value);
- } else
+ }
+ else if (format_char == 'o')
+ t.value = Extract_Icon (&pointer,&length,size,&t.extra_value);
+ else
t.value = Extract_Value(&pointer,&length,size,format_char=='i');
thunks = Add_Thunk(thunks, t);
i++;
@@ -1596,6 +1726,22 @@ Parse_Format_Mapping (int *argc, char ***argv)
static int spy = 0;
+static int (*old_error_handler)(Display *dpy, XErrorEvent *ev);
+
+static int spy_error_handler(Display *dpy, XErrorEvent *ev)
+{
+ if (ev->error_code == BadWindow || ev->error_code == BadMatch) {
+ /* Window was destroyed */
+ puts("");
+ exit(0);
+ }
+
+ if (old_error_handler)
+ return old_error_handler(dpy, ev);
+
+ return 0;
+}
+
int
main (int argc, char **argv)
{
@@ -1738,9 +1884,15 @@ main (int argc, char **argv)
XEvent event;
const char *format, *dformat;
- XSelectInput(dpy, target_win, PropertyChangeMask);
+ XSelectInput(dpy, target_win, PropertyChangeMask | StructureNotifyMask);
+ old_error_handler = XSetErrorHandler(spy_error_handler);
for (;;) {
+ fflush(stdout);
XNextEvent(dpy, &event);
+ if (event.type == DestroyNotify)
+ break;
+ if (event.type != PropertyNotify)
+ continue;
format = dformat = NULL;
if (props) {
int i;