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 cdaedeb..d06f120 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 cdaedeb..d06f120 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 cdaedeb..d06f120 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 cdaedeb..d06f120 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 a2f97ef..0f5f30b 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 97d427c..de3304c 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 79b90fc..5cb32b0 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 305025c..481138d 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 ())