Don't call g_set_error() unless the GError pointer is non-NULL. This
authorTor Lillqvist <tml@novell.com>
Wed, 27 Apr 2005 09:50:09 +0000 (09:50 +0000)
committerTor Lillqvist <tml@src.gnome.org>
Wed, 27 Apr 2005 09:50:09 +0000 (09:50 +0000)
2005-04-27  Tor Lillqvist  <tml@novell.com>

* glib/gconvert.c (open_converter, g_convert_with_iconv): Don't
call g_set_error() unless the GError pointer is non-NULL. This
avoids infinite recursion problems in certain rare situations on
Windows, when g_locale_from_utf8() is called from
_glib_get_locale_dir() after the change below. It's the
_glib_gettext() calls to translate error messages that are
parameters to g_set_error() that cause the recursion, not
g_set_error() itself.

* glib/gwin32.c (g_win32_locale_filename_from_utf8): New
function. Converts a filename to the system codepage, and if a
straight conversion isn't possible (because the filename contains
characters not in the system codepage), try looking up the
filename (which should refer to an existing file for this to
succeed) with short (8.3) pathname components.

* glib/gutils.c (_glib_get_locale_dir): No need to cache the
result, this function is normally called only once. Return the
path to the locale directory in system codepage, not UTF-8. The
path is passed to bindtextdomain(), which doesn't use UTF-8 file
names. Use g_win32_locale_filename_from_utf8(). (#301772)

Don't do run-time lookup of message catalog directory on
Cygwin. Cygwin is supposed to look and feel like Unix, and on Unix
we use paths fixed at configure time.

ChangeLog
ChangeLog.pre-2-10
ChangeLog.pre-2-12
ChangeLog.pre-2-8
glib/gconvert.c
glib/gutils.c
glib/gwin32.c
glib/gwin32.h

index cdaedebe59220aa99812fa10c3b67e95a8d47632..d06f120d4a4afe25c251ecaed276a06cdf6c01d3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,31 @@
+2005-04-27  Tor Lillqvist  <tml@novell.com>
+
+       * glib/gconvert.c (open_converter, g_convert_with_iconv): Don't
+       call g_set_error() unless the GError pointer is non-NULL. This
+       avoids infinite recursion problems in certain rare situations on
+       Windows, when g_locale_from_utf8() is called from
+       _glib_get_locale_dir() after the change below. It's the
+       _glib_gettext() calls to translate error messages that are
+       parameters to g_set_error() that cause the recursion, not
+       g_set_error() itself.
+
+       * glib/gwin32.c (g_win32_locale_filename_from_utf8): New
+       function. Converts a filename to the system codepage, and if a
+       straight conversion isn't possible (because the filename contains
+       characters not in the system codepage), try looking up the
+       filename (which should refer to an existing file for this to
+       succeed) with short (8.3) pathname components.
+
+       * glib/gutils.c (_glib_get_locale_dir): No need to cache the
+       result, this function is normally called only once. Return the
+       path to the locale directory in system codepage, not UTF-8. The
+       path is passed to bindtextdomain(), which doesn't use UTF-8 file
+       names. Use g_win32_locale_filename_from_utf8(). (#301772)
+
+       Don't do run-time lookup of message catalog directory on
+       Cygwin. Cygwin is supposed to look and feel like Unix, and on Unix
+       we use paths fixed at configure time.
+
 2005-04-19  Tor Lillqvist  <tml@novell.com>
 
        * glib/gutils.h: Minor comment improvement.
index cdaedebe59220aa99812fa10c3b67e95a8d47632..d06f120d4a4afe25c251ecaed276a06cdf6c01d3 100644 (file)
@@ -1,3 +1,31 @@
+2005-04-27  Tor Lillqvist  <tml@novell.com>
+
+       * glib/gconvert.c (open_converter, g_convert_with_iconv): Don't
+       call g_set_error() unless the GError pointer is non-NULL. This
+       avoids infinite recursion problems in certain rare situations on
+       Windows, when g_locale_from_utf8() is called from
+       _glib_get_locale_dir() after the change below. It's the
+       _glib_gettext() calls to translate error messages that are
+       parameters to g_set_error() that cause the recursion, not
+       g_set_error() itself.
+
+       * glib/gwin32.c (g_win32_locale_filename_from_utf8): New
+       function. Converts a filename to the system codepage, and if a
+       straight conversion isn't possible (because the filename contains
+       characters not in the system codepage), try looking up the
+       filename (which should refer to an existing file for this to
+       succeed) with short (8.3) pathname components.
+
+       * glib/gutils.c (_glib_get_locale_dir): No need to cache the
+       result, this function is normally called only once. Return the
+       path to the locale directory in system codepage, not UTF-8. The
+       path is passed to bindtextdomain(), which doesn't use UTF-8 file
+       names. Use g_win32_locale_filename_from_utf8(). (#301772)
+
+       Don't do run-time lookup of message catalog directory on
+       Cygwin. Cygwin is supposed to look and feel like Unix, and on Unix
+       we use paths fixed at configure time.
+
 2005-04-19  Tor Lillqvist  <tml@novell.com>
 
        * glib/gutils.h: Minor comment improvement.
index cdaedebe59220aa99812fa10c3b67e95a8d47632..d06f120d4a4afe25c251ecaed276a06cdf6c01d3 100644 (file)
@@ -1,3 +1,31 @@
+2005-04-27  Tor Lillqvist  <tml@novell.com>
+
+       * glib/gconvert.c (open_converter, g_convert_with_iconv): Don't
+       call g_set_error() unless the GError pointer is non-NULL. This
+       avoids infinite recursion problems in certain rare situations on
+       Windows, when g_locale_from_utf8() is called from
+       _glib_get_locale_dir() after the change below. It's the
+       _glib_gettext() calls to translate error messages that are
+       parameters to g_set_error() that cause the recursion, not
+       g_set_error() itself.
+
+       * glib/gwin32.c (g_win32_locale_filename_from_utf8): New
+       function. Converts a filename to the system codepage, and if a
+       straight conversion isn't possible (because the filename contains
+       characters not in the system codepage), try looking up the
+       filename (which should refer to an existing file for this to
+       succeed) with short (8.3) pathname components.
+
+       * glib/gutils.c (_glib_get_locale_dir): No need to cache the
+       result, this function is normally called only once. Return the
+       path to the locale directory in system codepage, not UTF-8. The
+       path is passed to bindtextdomain(), which doesn't use UTF-8 file
+       names. Use g_win32_locale_filename_from_utf8(). (#301772)
+
+       Don't do run-time lookup of message catalog directory on
+       Cygwin. Cygwin is supposed to look and feel like Unix, and on Unix
+       we use paths fixed at configure time.
+
 2005-04-19  Tor Lillqvist  <tml@novell.com>
 
        * glib/gutils.h: Minor comment improvement.
index cdaedebe59220aa99812fa10c3b67e95a8d47632..d06f120d4a4afe25c251ecaed276a06cdf6c01d3 100644 (file)
@@ -1,3 +1,31 @@
+2005-04-27  Tor Lillqvist  <tml@novell.com>
+
+       * glib/gconvert.c (open_converter, g_convert_with_iconv): Don't
+       call g_set_error() unless the GError pointer is non-NULL. This
+       avoids infinite recursion problems in certain rare situations on
+       Windows, when g_locale_from_utf8() is called from
+       _glib_get_locale_dir() after the change below. It's the
+       _glib_gettext() calls to translate error messages that are
+       parameters to g_set_error() that cause the recursion, not
+       g_set_error() itself.
+
+       * glib/gwin32.c (g_win32_locale_filename_from_utf8): New
+       function. Converts a filename to the system codepage, and if a
+       straight conversion isn't possible (because the filename contains
+       characters not in the system codepage), try looking up the
+       filename (which should refer to an existing file for this to
+       succeed) with short (8.3) pathname components.
+
+       * glib/gutils.c (_glib_get_locale_dir): No need to cache the
+       result, this function is normally called only once. Return the
+       path to the locale directory in system codepage, not UTF-8. The
+       path is passed to bindtextdomain(), which doesn't use UTF-8 file
+       names. Use g_win32_locale_filename_from_utf8(). (#301772)
+
+       Don't do run-time lookup of message catalog directory on
+       Cygwin. Cygwin is supposed to look and feel like Unix, and on Unix
+       we use paths fixed at configure time.
+
 2005-04-19  Tor Lillqvist  <tml@novell.com>
 
        * glib/gutils.h: Minor comment improvement.
index a2f97ef17ff929b54f4aceac682e54f2be37ef1b..0f5f30b4664d788048cdaa1b0f6ccd220eb6af53 100644 (file)
@@ -399,14 +399,17 @@ open_converter (const gchar *to_codeset,
   G_UNLOCK (iconv_cache_lock);
   
   /* Something went wrong.  */
-  if (errno == EINVAL)
-    g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_NO_CONVERSION,
-                _("Conversion from character set '%s' to '%s' is not supported"),
-                from_codeset, to_codeset);
-  else
-    g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED,
-                _("Could not open converter from '%s' to '%s'"),
-                from_codeset, to_codeset);
+  if (error)
+    {
+      if (errno == EINVAL)
+       g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_NO_CONVERSION,
+                    _("Conversion from character set '%s' to '%s' is not supported"),
+                    from_codeset, to_codeset);
+      else
+       g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED,
+                    _("Could not open converter from '%s' to '%s'"),
+                    from_codeset, to_codeset);
+    }
   
   return cd;
 }
@@ -610,14 +613,16 @@ g_convert_with_iconv (const gchar *str,
            goto again;
          }
        case EILSEQ:
-         g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
-                      _("Invalid byte sequence in conversion input"));
+         if (error)
+           g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
+                        _("Invalid byte sequence in conversion input"));
          have_error = TRUE;
          break;
        default:
-         g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED,
-                      _("Error during conversion: %s"),
-                      g_strerror (errno));
+         if (error)
+           g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED,
+                        _("Error during conversion: %s"),
+                        g_strerror (errno));
          have_error = TRUE;
          break;
        }
@@ -633,8 +638,9 @@ g_convert_with_iconv (const gchar *str,
        {
           if (!have_error)
             {
-              g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_PARTIAL_INPUT,
-                           _("Partial character sequence at end of input"));
+             if (error)
+               g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_PARTIAL_INPUT,
+                            _("Partial character sequence at end of input"));
               have_error = TRUE;
             }
        }
@@ -1122,7 +1128,7 @@ g_get_filename_charsets (G_CONST_RETURN gchar ***filename_charsets)
 gboolean
 g_get_filename_charsets (G_CONST_RETURN gchar ***filename_charsets) 
 {
-  static gchar *charsets[] = {
+  static const gchar *charsets[] = {
     "UTF-8",
     NULL
   };
@@ -1190,8 +1196,9 @@ _g_convert_thread_init (void)
  * @error:         location to store the error occuring, or %NULL to ignore
  *                 errors. Any of the errors in #GConvertError may occur.
  * 
- * Converts a string which is in the encoding used by GLib for filenames
- * into a UTF-8 string.
+ * Converts a string which is in the encoding used by GLib for
+ * filenames into a UTF-8 string. Note that on Windows GLib uses UTF-8
+ * for filenames.
  * 
  * Return value: The converted string, or %NULL on an error.
  **/
@@ -1253,7 +1260,8 @@ g_filename_to_utf8 (const gchar *opsysstring,
  * @error:         location to store the error occuring, or %NULL to ignore
  *                 errors. Any of the errors in #GConvertError may occur.
  * 
- * Converts a string from UTF-8 to the encoding used for filenames.
+ * Converts a string from UTF-8 to the encoding GLib uses for
+ * filenames. Note that on Windows GLib uses UTF-8 for filenames.
  * 
  * Return value: The converted string, or %NULL on an error.
  **/
index 97d427cda53b8656d08dca5ef197952347991bd7..de3304cadb5039460897cf082b3e23362d077c0c 100644 (file)
@@ -2781,23 +2781,46 @@ _g_utils_thread_init (void)
 
 #include <libintl.h>
 
-#ifdef G_PLATFORM_WIN32
+#ifdef G_OS_WIN32
 
+/**
+ * _glib_get_locale_dir:
+ *
+ * Return the path to the lib\locale subfolder of the GLib
+ * installation folder. The path is in the system codepage. We have to
+ * use system codepage as bindtextdomain() doesn't have a UTF-8
+ * interface.
+ */
 static const gchar *
 _glib_get_locale_dir (void)
 {
-  static const gchar *cache = NULL;
-  if (cache == NULL)
-    cache = g_win32_get_package_installation_subdirectory
-      (GETTEXT_PACKAGE, dll_name, "lib\\locale");
+  gchar *dir, *cp_dir;
+  gchar *retval = NULL;
 
-  return cache;
+  dir = g_win32_get_package_installation_directory (GETTEXT_PACKAGE, dll_name);
+  cp_dir = g_win32_locale_filename_from_utf8 (dir);
+  g_free (dir);
+
+  if (cp_dir)
+    {
+      /* Don't use g_build_filename() on pathnames in the system
+       * codepage. In CJK locales cp_dir might end with a double-byte
+       * character whose trailing byte is a backslash.
+       */
+      retval = g_strconcat (cp_dir, "\\lib\\locale", NULL);
+      g_free (cp_dir);
+    }
+
+  if (retval)
+    return retval;
+  else
+    return g_strdup ("");
 }
 
 #undef GLIB_LOCALE_DIR
 #define GLIB_LOCALE_DIR _glib_get_locale_dir ()
 
-#endif /* G_PLATFORM_WIN32 */
+#endif /* G_OS_WIN32 */
 
 G_CONST_RETURN gchar *
 _glib_gettext (const gchar *str)
index 79b90fc274c4aad9a749bafef7aabfc83e14d79b..5cb32b04b64d0e3bcb1f86bdac1b4fc52370b6ed 100644 (file)
@@ -1223,7 +1223,7 @@ get_package_directory_from_module (gchar *module_name)
  * @dll_name was %NULL.
  *
  * If both @package and @dll_name are %NULL, the directory from where
- * the main executable of the process was loaded is uses instead in
+ * the main executable of the process was loaded is used instead in
  * the same way as above.
  *
  * Returns: a string containing the installation directory for
@@ -1467,5 +1467,59 @@ g_win32_get_windows_version (void)
   return windows_version;
 }
 
+/**
+ * g_win32_locale_filename_from_utf8:
+ *
+ * @utf8filename: a UTF-8 encoded filename.
+ *
+ * Convertes a filename from UTF-8 to the system codepage.
+ *
+ * On NT-based Windows, on NTFS file systems, file names are in
+ * Unicode. It is quite possible that Unicode file names contain
+ * characters not representable in the system codepage. (For instance,
+ * Greek or Cyrillic characters on Western European or US Windows
+ * installations, or various less common CJK characters on CJK Windows
+ * installations.)
+ *
+ * In such a case, and if the filename refers to an existing file, and
+ * the file system stores alternate short (8.3) names for directory
+ * entries, the short form of the filename is returned. Note that the
+ * "short" name might in fact be longer than the Unicode name. If no
+ * system codepage name for the file is possible, NULL is returned.
+ *
+ * The return value is dynamically allocated and should be freed when
+ * no longer used.
+ *
+ * Return value: The converted filename, or %NULL on conversion
+ * failure and lack of short names.
+ *
+ * Since: 2.7
+ */
+gchar *
+g_win32_locale_filename_from_utf8 (const gchar *utf8filename)
+{
+  gchar *retval = g_locale_from_utf8 (utf8filename, -1, NULL, NULL, NULL);
+
+  if (retval == NULL && G_WIN32_HAVE_WIDECHAR_API ())
+    {
+      /* 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);
+       }
+    }
+  return retval;
+}
+
 #define __G_WIN32_C__
 #include "galiasdef.c"
index 305025c22a94d6d25ac272eaecdf35865fecfc9a..481138dbb1301949a747c1a473d6c8c0834bee5e 100644 (file)
@@ -91,6 +91,8 @@ gchar*          g_win32_get_package_installation_subdirectory (gchar *package,
 
 guint          g_win32_get_windows_version (void);
 
+gchar*          g_win32_locale_filename_from_utf8 (const gchar *utf8filename);
+
 #define G_WIN32_IS_NT_BASED() (g_win32_get_windows_version () < 0x80000000)
 #define G_WIN32_HAVE_WIDECHAR_API() (G_WIN32_IS_NT_BASED ())