Take zerowidth and double-width chars into consideration when computing
authorBehdad Esfahbod <behdad@gnome.org>
Wed, 3 Jan 2007 23:05:36 +0000 (23:05 +0000)
committerBehdad Esfahbod <behdad@src.gnome.org>
Wed, 3 Jan 2007 23:05:36 +0000 (23:05 +0000)
2007-01-03  Behdad Esfahbod  <behdad@gnome.org>

        * glib/goption.c (_g_unichar_get_width), (_g_utf8_strwidth),
        (calculate_max_length), (print_entry), (print_help): Take zerowidth
        and double-width chars into consideration when computing width of a
        string.  Also fix another bug in width computation.

        * glib/guniprop.c (g_unichar_iszerowidth): Fix typo.  It was not
        working correctly.

svn path=/trunk/; revision=5204

ChangeLog
glib/goption.c
glib/guniprop.c

index 24e9384..2696785 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,15 @@
 2007-01-03  Behdad Esfahbod  <behdad@gnome.org>
 
+       * glib/goption.c (_g_unichar_get_width), (_g_utf8_strwidth),
+       (calculate_max_length), (print_entry), (print_help): Take zerowidth
+       and double-width chars into consideration when computing width of a
+       string.  Also fix another bug in width computation.
+
+       * glib/guniprop.c (g_unichar_iszerowidth): Fix typo.  It was not
+       working correctly.
+
+2007-01-03  Behdad Esfahbod  <behdad@gnome.org>
+
        * glib/glib.symbols:
        * glib/gunicode.h:
        * glib/guniprop.c: Add g_unichar_iszerowidth(). (#347645)
index 8b5139a..e75e576 100644 (file)
@@ -122,6 +122,59 @@ static void free_changes_list (GOptionContext *context,
 static void free_pending_nulls (GOptionContext *context,
                                gboolean        perform_nulls);
 
+
+static int
+_g_unichar_get_width (gunichar c)
+{
+  if (G_UNLIKELY (g_unichar_iszerowidth (c)))
+    return 0;
+
+  /* we ignore the fact that we should call g_unichar_iswide_cjk() under
+   * some locales (legacy East Asian ones) */
+  if (g_unichar_iswide (c))
+    return 2;
+
+  return 1;
+}
+
+static glong
+_g_utf8_strwidth (const gchar *p,
+                  gssize       max)
+{
+  glong len = 0;
+  const gchar *start = p;
+  g_return_val_if_fail (p != NULL || max == 0, 0);
+  max = strlen (p);
+
+  if (max < 0)
+    {
+      while (*p)
+        {
+          len += _g_unichar_get_width (g_utf8_get_char (p));
+          p = g_utf8_next_char (p);
+        }
+    }
+  else
+    {
+      if (max == 0 || !*p)
+        return 0;
+
+      /* this case may not be quite correct */
+      
+      len += _g_unichar_get_width (g_utf8_get_char (p));
+      p = g_utf8_next_char (p);          
+
+      while (p - start < max && *p)
+        {
+          len += _g_unichar_get_width (g_utf8_get_char (p));
+          p = g_utf8_next_char (p);          
+        }
+    }
+
+  return len;
+}
+
+
 GQuark
 g_option_error_quark (void)
 {
@@ -421,13 +474,13 @@ calculate_max_length (GOptionGroup *group)
       if (entry->flags & G_OPTION_FLAG_HIDDEN)
        continue;
 
-      len = g_utf8_strlen (entry->long_name, -1);
+      len = _g_utf8_strwidth (entry->long_name, -1);
       
       if (entry->short_name)
        len += 4;
       
       if (!NO_ARG (entry) && entry->arg_description)
-       len += 1 + g_utf8_strlen (TRANSLATE (group, entry->arg_description), -1);
+       len += 1 + _g_utf8_strwidth (TRANSLATE (group, entry->arg_description), -1);
       
       max_length = MAX (max_length, len);
     }
@@ -458,7 +511,8 @@ print_entry (GOptionGroup       *group,
   if (entry->arg_description)
     g_string_append_printf (str, "=%s", TRANSLATE (group, entry->arg_description));
   
-  g_print ("%-*s %s\n", max_length + 4, str->str,
+  g_print ("%s%*s %s\n", str->str,
+          (int) (max_length + 4 - _g_utf8_strwidth (str->str, -1)), "",
           entry->description ? TRANSLATE (group, entry->description) : "");
   g_string_free (str, TRUE);  
 }
@@ -546,11 +600,11 @@ print_help (GOptionContext *context,
 
   list = context->groups;
 
-  max_length = g_utf8_strlen ("-?, --help", -1);
+  max_length = _g_utf8_strwidth ("-?, --help", -1);
 
   if (list)
     {
-      len = g_utf8_strlen ("--help-all", -1);
+      len = _g_utf8_strwidth ("--help-all", -1);
       max_length = MAX (max_length, len);
     }
 
@@ -565,7 +619,7 @@ print_help (GOptionContext *context,
       GOptionGroup *group = list->data;
       
       /* First, we check the --help-<groupname> options */
-      len = g_utf8_strlen ("--help-", -1) + g_utf8_strlen (group->name, -1);
+      len = _g_utf8_strwidth ("--help-", -1) + _g_utf8_strwidth (group->name, -1);
       max_length = MAX (max_length, len);
 
       /* Then we go through the entries */
index 2292e76..908d3fe 100644 (file)
@@ -380,7 +380,7 @@ g_unichar_iszerowidth (gunichar c)
   if (G_UNLIKELY (c == 0x00AD))
     return FALSE;
 
-  if (G_UNLIKELY (ISZEROWIDTHTYPE (c)))
+  if (G_UNLIKELY (ISZEROWIDTHTYPE (TYPE (c))))
     return TRUE;
 
   if (G_UNLIKELY ((c >= 0x1160 && c < 0x1200) ||