Re: Solution for UTF-8 chars in the title bar?



Janek Kozicki <janek_listy wp pl> writes:
> thanks, but I was unable to test your patch. I tried it against
> 1.3, 1.3.1 and svn-HEAD - I was unable to resolve conflicts by hand.

Yes, it was a patch against a previous patch.  Things get complicated
without version control.  Attached is a diff against 1.3.2.  The patch
series is available at http://www.iki.fi/tkorvola/sawfish.git, branch
utf-8-names-fix.  I may post it to the wiki if I find the time.

To illustrate the difference, run Sawfish in a non-UTF-8 locale but
with a title font capable of displaying Unicode (I use Freemono),
start a uxterm and gucharmap, then try xterm -T 'funny characters' and
konsole -T 'funny characters', where the funny characters are not
representable in the locale of Sawfish.  With the Net_wm_names patch,
only konsole gets its title rendered correctly but xterm does not.
With the attached patch, both windows get correct titles.

The issues raised here remain unaddressed though:
<URL:http://mail.gnome.org/archives/sawfish-list/2007-October/msg00018.html>.

-- 
	Timo Korvola		<URL:http://www.iki.fi/tkorvola>

diff --git a/src/events.c b/src/events.c
index 4b58c7c..364be1c 100644
--- a/src/events.c
+++ b/src/events.c
@@ -479,106 +479,110 @@ motion_notify (XEvent *ev)
 
 static bool
 update_window_name(Lisp_Window * w, XPropertyEvent xproperty) {
-  u_char *prop;
-  Atom actual;
-  int format;
-  long nitems, bytes_after;
-  char **text_list;
-  XTextProperty tprop;
-  int count;
-  repv str = Qnil;
-  int convert_status;
-
-  if (xproperty.state != PropertyNewValue
-      || XGetWindowProperty (dpy, w->id, xproperty.atom,
-			     0, 200, False, AnyPropertyType, &actual,
-			     &format, &nitems,
-			     &bytes_after, &prop) != Success
-      || actual == None)
-    return FALSE;
-
-  if (format != 8 || WINDOW_IS_GONE_P (w))
-    return FALSE;
-
-  tprop.value = prop;
-  tprop.encoding = actual;
-  tprop.format = format;
-  tprop.nitems = strlen (prop);
-
-  if (actual == xa_compound_text || actual == XA_STRING) 
+    u_char *prop;
+    Atom actual;
+    int format;
+    long nitems, bytes_after;
+    char **text_list;
+    XTextProperty tprop;
+    int count;
+    repv str = Qnil;
+    int convert_status;
+
+    if (xproperty.state != PropertyNewValue
+        || XGetWindowProperty (dpy, w->id, xproperty.atom,
+                               0, 200, False, AnyPropertyType, &actual,
+                               &format, &nitems,
+                               &bytes_after, &prop) != Success
+        || actual == None)
+        return FALSE;
+
+    if (format != 8 || WINDOW_IS_GONE_P (w))
     {
-      convert_status = XmbTextPropertyToTextList (dpy, &tprop, &text_list, &count);
-      if (convert_status >= Success && count > 0) 
-	{
-	  char * utf8str = g_locale_to_utf8(text_list[0], -1, NULL, NULL, NULL);
-	  if (utf8str)
-	    str = rep_string_dup (utf8str);
-	}
-      XFreeStringList(text_list);
+        XFree (prop);
+        return FALSE;
     }
 
+    tprop.value = prop;
+    tprop.encoding = actual;
+    tprop.format = format;
+    tprop.nitems = strlen (prop);
+
 #ifdef X_HAVE_UTF8_STRING
-  if (actual == xa_utf8_string) 
+    if (actual == xa_compound_text || actual == XA_STRING
+        || actual == xa_utf8_string) 
+    {
+        convert_status = Xutf8TextPropertyToTextList (dpy, &tprop, &text_list,
+                                                      &count);
+        if (convert_status >= Success && count > 0)
+            str = rep_string_dup (text_list[0]);
+        XFreeStringList(text_list);
+    }
+#else
+    if (actual == xa_compound_text || actual == XA_STRING)
     {
-      convert_status = Xutf8TextPropertyToTextList (dpy, &tprop, &text_list, &count);
-      if (convert_status >= Success && count > 0)
-	str = rep_string_dup (text_list[0]);
-      XFreeStringList(text_list);
+        convert_status = XmbTextPropertyToTextList (dpy, &tprop, &text_list,
+                                                    &count);
+        if (convert_status >= Success) 
+        {
+            if (count > 0)
+            {
+                char * utf8str = g_locale_to_utf8(text_list[0], -1,
+                                                  NULL, NULL, NULL);
+                if (utf8str)
+                {
+                    str = rep_string_dup (utf8str);
+                    g_free (utf8str);
+                }
+            }
+            XFreeStringList(text_list);
+        }
     }
 #endif
 
-  XFree (prop);
+    XFree (prop);
   
-  if (str == Qnil)
-    return FALSE;
+    if (str == Qnil)
+        return FALSE;
 
-  if (xproperty.atom == xa_wm_net_name)
+    if (xproperty.atom == xa_wm_net_name
+        && str != Qnil && Fequal (w->net_name, str) == Qnil)
     {
-      if ( str != Qnil && Fequal (w->net_name, str) == Qnil)
-	{
-	  w->net_name = str;
-	  return TRUE;
-	}
+        w->net_name = str;
+        return TRUE;
     }
   
-  if (xproperty.atom == xa_wm_net_icon_name) 
+    if (xproperty.atom == xa_wm_net_icon_name
+        && str != Qnil && Fequal (w->net_icon_name, str) == Qnil)
     {
-      if ( str != Qnil && Fequal (w->net_icon_name, str) == Qnil)
-	{
-	  w->net_icon_name = str;
-	  return TRUE;
-	}
+        w->net_icon_name = str;
+        return TRUE;
     }
   
-  /* No point in updating the rest if we have the _NET ones. They won't
-     be used anyways. */
-  if (w->net_name != Qnil)
-    return FALSE;
-  
-  if (xproperty.atom == XA_WM_NAME)
+    if (w->net_name == Qnil && xproperty.atom == XA_WM_NAME)
     {
-      if (str == Qnil)
-	str = rep_null_string ();
-      if (Fequal (w->name, str) == Qnil
-	  || Fequal (w->full_name, str) == Qnil)
-	{
-	  w->full_name = w->name = str;
-	  return TRUE;
-	}
+        if (str == Qnil)
+            str = rep_null_string ();
+        if (Fequal (w->name, str) == Qnil
+            || Fequal (w->full_name, str) == Qnil)
+        {
+            w->full_name = w->name = str;
+            return TRUE;
+        }
     }
   
-  if (xproperty.atom == XA_WM_ICON_NAME)
+    if (w->net_icon_name == Qnil && xproperty.atom == XA_WM_ICON_NAME)
     {
-      if (str == Qnil)
-	str = rep_null_string ();
-      if (Fequal (w->icon_name, str) == Qnil)
-	{
-	  w->icon_name = str;
-	  return TRUE;
-	}
-    }	  
+        if (str == Qnil)
+            str = rep_null_string ();
+        if (Fequal (w->icon_name, str) == Qnil)
+        {
+            w->icon_name = str;
+            return TRUE;
+        }
+    }    
 
-  return FALSE;
+    return FALSE;
 }
 
 static void
@@ -614,16 +618,15 @@ property_notify (XEvent *ev)
 	    break;
 
 	default:
-
-	    if (ev->xproperty.atom == XA_WM_NAME ||
-		ev->xproperty.atom == XA_WM_ICON_NAME ||
-		ev->xproperty.atom == xa_wm_net_name ||
-		ev->xproperty.atom == xa_wm_net_icon_name ) 
-	    {
-	      need_refresh = changed = 
-		update_window_name(w, ev->xproperty);
-	    }
-	    else if (ev->xproperty.atom == xa_wm_colormap_windows)
+            if (ev->xproperty.atom == XA_WM_NAME ||
+                ev->xproperty.atom == XA_WM_ICON_NAME ||
+                ev->xproperty.atom == xa_wm_net_name ||
+                ev->xproperty.atom == xa_wm_net_icon_name ) 
+            {
+                need_refresh = changed = 
+                    update_window_name(w, ev->xproperty);
+            }
+            else if (ev->xproperty.atom == xa_wm_colormap_windows)
 	    {
 		if (w->n_cmap_windows > 0)
 		    XFree (w->cmap_windows);
diff --git a/src/windows.c b/src/windows.c
index 734032c..b7e2da6 100644
--- a/src/windows.c
+++ b/src/windows.c
@@ -356,85 +356,73 @@ remove_window_frame (Lisp_Window *w)
     }
 }
 
+
+static repv
+text_prop_to_utf8 (XTextProperty *prop)
+{
+    repv rval = Qnil;
+    if (prop->value && prop->nitems > 0)
+    {
+        char **list;
+        int count;
+        prop->nitems = strlen(prop->value);
+#ifdef X_HAVE_UTF8_STRING
+        if (Xutf8TextPropertyToTextList (dpy, prop, &list, &count) >= Success)
+        {
+            if (count > 0)
+                rval = rep_string_dup (list[0]);
+            XFreeStringList (list);
+        }
+#else
+        if (XmbTextPropertyToTextList (dpy, prop, &list, &count) >= Success)
+        {
+            if (count > 0) {
+                gchar *ustr = g_locale_to_utf8(list[0], -1, NULL, NULL, NULL);
+                if (ustr)
+                {
+                    rval = rep_string_dup (ustr);
+                    g_free (ustr);
+                }
+            }
+            XFreeStringList (list);
+        }
+#endif
+    }
+    return rval;
+}
+
+
 /* Queries X properties to get the window {icon,}name */
 static void
-get_window_name(Lisp_Window * w)
+get_window_name(Lisp_Window *w)
 {
-  char *tem;
-  XTextProperty prop;
+    XTextProperty prop;
 
-  /* We only try to use the utf8 properties if our xlib supports them */
+    /* We only try to use the utf8 properties if our xlib supports them.
+       Otherwise conversion would have to go via the current locale, which
+       might lose some characters. */
 #ifdef X_HAVE_UTF8_STRING
-  if (XGetTextProperty (dpy, w->id, &prop, xa_wm_net_name) && prop.value) {
-    if (prop.nitems > 0)
-      {
-        char **list;
-	int count;
-	prop.nitems = strlen(prop.value);
-	if (Xutf8TextPropertyToTextList (dpy, &prop, &list, &count)
-	    >= Success)
-	  {
-	    if (count > 0)
-	      w->net_name = rep_string_dup (list[0]);
-	    XFreeStringList (list);
-	  }
-      }
-  }
-
-  if (XGetTextProperty (dpy, w->id, &prop, xa_wm_net_icon_name) && prop.value) {
-    if (prop.nitems > 0)
-      {
-        char **list;
-	int count;
-	prop.nitems = strlen(prop.value);
-	if (Xutf8TextPropertyToTextList (dpy, &prop, &list, &count)
-	    >= Success)
-	  {
-	    if (count > 0)
-	      w->net_icon_name = rep_string_dup (list[0]);
-	    XFreeStringList (list);
-	  }
-      }
-  }
-
-  /* If we got the _NET names, there's no point in querying the others, 
-     as they won't be used anyways. */
-  if (w->net_name != Qnil)
-    return;
-
+    if (XGetTextProperty (dpy, w->id, &prop, xa_wm_net_name))
+        w->net_name = text_prop_to_utf8 (&prop);
+    if (XGetTextProperty (dpy, w->id, &prop, xa_wm_net_icon_name))
+        w->net_icon_name = text_prop_to_utf8 (&prop);
 #endif
 
-  if (XGetWMName (dpy, w->id, &prop) && prop.value)
+    if (w->net_name == Qnil && XGetWMName (dpy, w->id, &prop))
     {
-      if (prop.nitems > 0)
-	{
-	  char **list;
-	  int count;
-	  prop.nitems = strlen(prop.value);
-	  if (XmbTextPropertyToTextList (dpy, &prop, &list, &count)
-	      >= Success)
-	    {
-	      if (count > 0)
-		w->name = rep_string_dup (g_locale_to_utf8(list[0],
-							   -1, NULL, NULL, NULL));
-	      XFreeStringList (list);
-	    }
-	}
-      XFree (prop.value);
+        repv name = text_prop_to_utf8 (&prop);
+        if (name != Qnil)
+            w->name = name;
     }
-  w->full_name = w->name;
+    w->full_name = w->name;
   
-  if (XGetIconName (dpy, w->id, &tem))
-    {
-      w->icon_name = rep_string_dup (g_locale_to_utf8(tem,
-						      -1, NULL, NULL, NULL));
-      XFree (tem);
-    }
-  else
-    w->icon_name = w->name;
-
+    if (w->net_icon_name == Qnil && XGetWMIconName (dpy, w->id, &prop))
+        w->icon_name = text_prop_to_utf8 (&prop);
+    if (w->icon_name == Qnil)
+        w->icon_name = w->name;
 }
 
+
 /* Add the top-level window ID to the manager's data structures */
 Lisp_Window *
 add_window (Window id)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]