Wikia

Sawfish

Utf 8 names fix

773pages on
this wiki
Talk0
Browse all patches

Author Edit

Timo Korvola

Synopsis Edit

Patch against 1.3.2. 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.

See this post and this post

Patch Edit

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)

Community's reasons for inclusion or rejection Edit

Patch submitters, please vote also! Yes, obviosuly your vote will be positive, but it's the place to give your explanation why this patch is good for all Sawfish users, and why it is correct - good reasons for inclusion.

When voting anonymously please write your name, so that it can be associated with your posts on the mailing list. If you are logged in you can sign yourself by typing four tilda characters: ~~~~.

Yes vote: yes. I'm using this patch and it fixed my UTF-8 problem - Gabor Z.Papp

Yes vote: yes. This also fixes crashed related to wrong reencodings of the properties [1] RodrigoGallardo 19:21, 5 February 2008 (UTC)

Yes vote: yes. I've been using this patch since about a week and it seems to work nicely without causing any other apparent problems. -- Peter

Yes vote: yes. Wow, this one is pretty long. I hope that with this one we finally will have utf-8 working nicely ;-) Thanks, applied. Janek Kozicki 19:30, 18 February 2008 (UTC)

Around Wikia's network

Random Wiki