[PATCH] Display _NET_WM_ICONs as ASCII art instead of as a big list of integers

Soeren Sandmann sandmann at daimi.au.dk
Tue Apr 28 15:55:53 PDT 2009


New version that hopefully works correctly on 64 bit.

---
 configure.ac |    2 +-
 dsimple.c    |   12 +++++-
 dsimple.h    |    1 +
 xprop.c      |  132 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 144 insertions(+), 3 deletions(-)

diff --git a/configure.ac b/configure.ac
index bba437b..6087c3b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -36,7 +36,7 @@ AC_PROG_INSTALL
 
 XORG_CWARNFLAGS
 
-AC_CHECK_HEADERS([wchar.h wctype.h])
+AC_CHECK_HEADERS([wchar.h wctype.h langinfo.h])
 
 # Checks for pkg-config packages
 PKG_CHECK_MODULES(XPROP, x11)
diff --git a/dsimple.c b/dsimple.c
index 4bd4837..cd08d7c 100644
--- a/dsimple.c
+++ b/dsimple.c
@@ -72,7 +72,17 @@ char *Malloc(unsigned size)
 
 	return(data);
 }
-	
+
+/*
+ * Realloc: like realloc but handles out of memory using Fatal_Error:
+ */
+char *Realloc(char *mem, unsigned size)
+{
+    if (!(mem = realloc (mem, size)))
+	Fatal_Error("Out of memory!");
+
+    return mem;
+}
 
 /*
  * Get_Display_Name (argc, argv) Look for -display, -d, or host:dpy (obselete)
diff --git a/dsimple.h b/dsimple.h
index 7557571..1c09c9d 100644
--- a/dsimple.h
+++ b/dsimple.h
@@ -59,6 +59,7 @@ extern int screen;                           /* The current screen */
     /* Declarations for functions in just_display.c */
 
 char *Malloc(unsigned);
+char *Realloc(char *,unsigned);
 char *Get_Display_Name(int *, char **);
 Display *Open_Display(const char *);
 void Setup_Display_And_Screen(int *, char **);
diff --git a/xprop.c b/xprop.c
index 73a9db8..8261b15 100644
--- a/xprop.c
+++ b/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)
@@ -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++;
-- 
1.6.2.2



More information about the xorg-devel mailing list