[glib] W32 - don't use gettext & gcov during gettext init



commit 75fa8c2afbab4f414d2eb03684d9f807bd690aef
Author: Руслан Ижбулатов <lrn1986 gmail com>
Date:   Thu Jul 13 01:42:13 2017 +0000

    W32 - don't use gettext & gcov during gettext init
    
    Non-representable characters during UTF16->locale conversion
    will cause gcov code to return an error, for which it will try
    to use gettext, so that the error message is localized.
    
    If such call is made while gettext is being initialized
    (there's a g_once_init_enter up the stack), the thread will hang forever.
    
    To solve this, use W32 API to do the UTF16->locale conversion
    and don't use gettext when it returns an error.
    
    Also optimize g_win32_locale_filename_from_utf8() a bit,
    as we need more UTF16 and less UTF8 now.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=784579

 glib/gwin32.c |   76 +++++++++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 60 insertions(+), 16 deletions(-)
---
diff --git a/glib/gwin32.c b/glib/gwin32.c
index f54d65f..cc6da5f 100644
--- a/glib/gwin32.c
+++ b/glib/gwin32.c
@@ -616,6 +616,49 @@ g_win32_get_windows_version (void)
   return windows_version;
 }
 
+/*
+ * Doesn't use gettext (and gconv), preventing recursive calls when
+ * g_win32_locale_filename_from_utf8() is called during
+ * gettext initialization.
+ */
+static gchar *
+special_wchar_to_locale_enoding (wchar_t *wstring)
+{
+  int sizeof_output;
+  int wctmb_result;
+  char *result;
+  BOOL not_representable = FALSE;
+
+  sizeof_output = WideCharToMultiByte (CP_ACP,
+                                       WC_NO_BEST_FIT_CHARS,
+                                       wstring, -1,
+                                       NULL, 0,
+                                       NULL,
+                                       &not_representable);
+
+  if (not_representable ||
+      sizeof_output == 0 ||
+      sizeof_output > MAX_PATH)
+    return NULL;
+
+  result = g_malloc0 (sizeof_output + 1);
+
+  wctmb_result = WideCharToMultiByte (CP_ACP,
+                                      WC_NO_BEST_FIT_CHARS,
+                                      wstring, -1,
+                                      result, sizeof_output + 1,
+                                      NULL,
+                                      &not_representable);
+
+  if (wctmb_result == sizeof_output &&
+      not_representable == FALSE)
+    return result;
+
+  g_free (result);
+
+  return NULL;
+}
+
 /**
  * g_win32_locale_filename_from_utf8:
  * @utf8filename: a UTF-8 encoded filename.
@@ -648,26 +691,27 @@ g_win32_get_windows_version (void)
 gchar *
 g_win32_locale_filename_from_utf8 (const gchar *utf8filename)
 {
-  gchar *retval = g_locale_from_utf8 (utf8filename, -1, NULL, NULL, NULL);
+  gchar *retval;
+  wchar_t *wname;
+
+  wname = g_utf8_to_utf16 (utf8filename, -1, NULL, NULL, NULL);
+
+  if (wname == NULL)
+    return NULL;
+
+  retval = special_wchar_to_locale_enoding (wname);
 
   if (retval == NULL)
     {
-      /* Conversion failed, so convert to wide chars, check if there
-       * is a 8.3 version, and use that.
-       */
-      wchar_t *wname = g_utf8_to_utf16 (utf8filename, -1, NULL, NULL, NULL);
-      if (wname != NULL)
-       {
-         wchar_t wshortname[MAX_PATH + 1];
-         if (GetShortPathNameW (wname, wshortname, G_N_ELEMENTS (wshortname)))
-           {
-             gchar *tem = g_utf16_to_utf8 (wshortname, -1, NULL, NULL, NULL);
-             retval = g_locale_from_utf8 (tem, -1, NULL, NULL, NULL);
-             g_free (tem);
-           }
-         g_free (wname);
-       }
+      /* Conversion failed, so check if there is a 8.3 version, and use that. */
+      wchar_t wshortname[MAX_PATH + 1];
+
+      if (GetShortPathNameW (wname, wshortname, G_N_ELEMENTS (wshortname)))
+        retval = special_wchar_to_locale_enoding (wshortname);
     }
+
+  g_free (wname);
+
   return retval;
 }
 


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