bug-gnu-utils
[Top][All Lists]
Advanced

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

Suggested patch for libintl (gettext 0.10.40) on Win32


From: Tor Lillqvist
Subject: Suggested patch for libintl (gettext 0.10.40) on Win32
Date: Thu, 20 Sep 2001 03:15:39 +0300 (EEST)

Hi,

Here are some suggested patches to make libintl behave better on
Windows. My main concern is that I don't like hard-coded paths in
DLLs. The user should be able to install a package in any
location. These patches takes care of that by not using hard-coded
LOCALEDIR and LOCALE_ALIAS_PATH macros, but instead looks up at
runtime the location from which the libintl DLL was loaded, and
assumes that the directory structure there mimics that on Unix. That
is, the DLL being located in a "lib" or "bin" directory, that has a
sibling "share" directory (that has a "locale" subdirectory).

--tml

diff -ru2 /g/tmp/gettext-0.10.40/configure.in ./configure.in
--- /g/tmp/gettext-0.10.40/configure.in Sat Sep 15 03:44:12 2001
+++ ./configure.in      Thu Sep 20 00:09:26 2001
@@ -26,4 +26,5 @@
 
 dnl Check for build configuration.
+AC_LIBTOOL_WIN32_DLL
 AM_PROG_LIBTOOL
 
diff -ru2 /g/tmp/gettext-0.10.40/intl/Makefile.in ./intl/Makefile.in
--- /g/tmp/gettext-0.10.40/intl/Makefile.in     Sat Sep 15 04:15:50 2001
+++ ./intl/Makefile.in  Thu Sep 20 01:06:34 2001
@@ -53,5 +53,5 @@
 
 DEFS = -DLOCALEDIR=\"$(localedir)\" -DLOCALE_ALIAS_PATH=\"$(aliaspath)\" \
--DLIBDIR=\"$(libdir)\" @DEFS@
+-DLIBDIR=\"$(libdir)\" -DLTV_CURRENT=$(LTV_CURRENT) -DLTV_AGE=$(LTV_AGE) @DEFS@
 CPPFLAGS = @CPPFLAGS@
 CFLAGS = @CFLAGS@
diff -ru2 /g/tmp/gettext-0.10.40/intl/bindtextdom.c ./intl/bindtextdom.c
--- /g/tmp/gettext-0.10.40/intl/bindtextdom.c   Mon Sep  3 17:00:50 2001
+++ ./intl/bindtextdom.c        Thu Sep 20 03:07:52 2001
@@ -60,4 +60,8 @@
 extern const char _nl_default_dirname[];
 
+#ifdef _WIN32
+extern void _set_nl_default_dirname (void);
+#endif
+
 /* List with bindings of specific domains.  */
 extern struct binding *_nl_domain_bindings;
@@ -101,4 +105,9 @@
   struct binding *binding;
   int modified;
+
+#ifdef _WIN32
+  if (_nl_default_dirname[0] == 0)
+    _set_nl_default_dirname ();
+#endif
 
   /* Some sanity checks.  */
diff -ru2 /g/tmp/gettext-0.10.40/intl/dcigettext.c ./intl/dcigettext.c
--- /g/tmp/gettext-0.10.40/intl/dcigettext.c    Mon Sep  3 17:00:50 2001
+++ ./intl/dcigettext.c Thu Sep 20 03:18:20 2001
@@ -65,4 +65,12 @@
 #endif
 
+#ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
+#define STRICT
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+#undef STRICT
+#endif
+
 #if defined HAVE_UNISTD_H || defined _LIBC
 # include <unistd.h>
@@ -281,5 +289,11 @@
 
 /* Contains the default location of the message catalogs.  */
+#ifdef _WIN32
+/* On Windows we don't want any hardcoded paths */
+#undef LOCALEDIR
+char _nl_default_dirname[MAX_PATH] = "";
+#else
 const char _nl_default_dirname[] = LOCALEDIR;
+#endif
 
 /* List with bindings of specific domains created by bindtextdomain()
@@ -396,4 +410,177 @@
 #endif
 
+#ifdef _WIN32
+
+/* These routines lifted from GLib and simplified */
+
+typedef char gchar;
+#define G_DIR_SEPARATOR '\\'
+#define G_DIR_SEPARATOR_S "\\"
+
+static gchar *
+get_package_directory_from_module (gchar *module_name)
+{
+  HMODULE hmodule = NULL;
+  gchar fn[MAX_PATH];
+  gchar *p;
+  gchar *result;
+
+  if (module_name)
+    {
+      hmodule = GetModuleHandle (module_name);
+      if (!hmodule)
+       return NULL;
+    }
+
+  if (!GetModuleFileName (hmodule, fn, MAX_PATH))
+    return NULL;
+
+  if ((p = strrchr (fn, G_DIR_SEPARATOR)) != NULL)
+    *p = '\0';
+
+  p = strrchr (fn, G_DIR_SEPARATOR);
+  if (p && (strcasecmp (p + 1, "bin") == 0 ||
+           strcasecmp (p + 1, "lib") == 0))
+    *p = '\0';
+
+  return strdup (fn);
+}
+
+/**
+ * g_win32_get_package_installation_directory:
+ * @package: An identifier for a software package, or NULL
+ * @dll_name: The name of a DLL that a package provides, or NULL
+ *
+ * Try to determine the installation directory for a software package.
+ * Typically used by GNU software packages.
+ *
+ * @package should be a short identifier for the package. Typically it
+ * is the same identifier as used for GETTEXT_PACKAGE in software
+ * configured accoring to GNU standards. The function first looks in
+ * the Windows Registry for the value #InstallationDirectory in the
+ * key address@hidden, and if that value exists and is a
+ * string, returns that.
+ *
+ * If @package is NULL, or the above value isn't found in the
+ * Registry, but @dll_name is non-NULL, it should name a DLL loaded
+ * into the current process. Typically that would be the name of the
+ * DLL calling this function, looking for its installation
+ * directory. The function then asks Windows what directory that DLL
+ * was loaded from. If that directory's last component is "bin" or
+ * "lib", the parent directory is returned, otherwise the directory
+ * itself. If that DLL isn't loaded, the function proceeds as if
+ * @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 same way as above.
+ *
+ * The return value should be freed with g_free() when not needed any longer.  
*/
+
+static gchar *
+g_win32_get_package_installation_directory (gchar *package,
+                                           gchar *dll_name)
+{
+  gchar *result = NULL;
+  gchar key[1000];
+  HKEY reg_key = NULL;
+  DWORD type;
+  DWORD nbytes;
+
+  if (package != NULL)
+    {
+      strcpy (key, "Software\\");
+      strcat (key, package);
+      
+      nbytes = 0;
+      if ((RegOpenKeyEx (HKEY_CURRENT_USER, key, 0,
+                        KEY_QUERY_VALUE, &reg_key) == ERROR_SUCCESS
+          && RegQueryValueEx (reg_key, "InstallationDirectory", 0,
+                              &type, NULL, &nbytes) == ERROR_SUCCESS)
+         ||
+         ((RegOpenKeyEx (HKEY_LOCAL_MACHINE, key, 0,
+                        KEY_QUERY_VALUE, &reg_key) == ERROR_SUCCESS
+          && RegQueryValueEx (reg_key, "InstallationDirectory", 0,
+                              &type, NULL, &nbytes) == ERROR_SUCCESS)
+          && type == REG_SZ))
+       {
+         result = malloc (nbytes + 1);
+         RegQueryValueEx (reg_key, "InstallationDirectory", 0,
+                          &type, result, &nbytes);
+         result[nbytes] = '\0';
+       }
+
+      if (reg_key != NULL)
+       RegCloseKey (reg_key);
+      
+      free (key);
+      
+    }
+  if (result)
+    {
+      return strdup (result);
+    }
+
+  if (dll_name != NULL)
+    result = get_package_directory_from_module (dll_name);
+
+  if (result == NULL)
+    result = get_package_directory_from_module (NULL);
+
+  return result;
+}
+
+/**
+ * g_win32_get_package_installation_subdirectory:
+ * @package: An identifier for a software package, or NULL
+ * @dll_name: The name of a DLL that a package provides, or NULL
+ * @subdir: A subdirectory of the package installation directory.
+ *
+ * Returns a string containg the path of the subdirectory @subdir in
+ * the return value from calling
+ * g_win32_get_package_installation_directory() with the @package and
+ * @dll_name parameters. The return value should be freed with
+ * g_free() when no longer needed.
+ */
+
+static gchar *
+g_win32_get_package_installation_subdirectory (gchar *package,
+                                              gchar *dll_name,
+                                              gchar *subdir)
+{
+  gchar *prefix;
+  gchar *sep;
+  gchar tmp[MAX_PATH];
+
+  prefix = g_win32_get_package_installation_directory (package, dll_name);
+
+  sep = (prefix[strlen (prefix) - 1] == G_DIR_SEPARATOR ?
+        "" : G_DIR_SEPARATOR_S);
+
+  strcpy (tmp, prefix);
+  free (prefix);
+  strcat (tmp, sep);
+  strcat (tmp, subdir);
+  return strdup (tmp);
+}
+
+void
+_set_nl_default_dirname (void)
+{
+  char *dir;
+  char my_dll_name[MAX_PATH];
+
+  if (_nl_default_dirname[0])
+    return;
+
+  /* This is the kind of DLL name that libtool generates */
+  sprintf (my_dll_name, "libintl-%d.dll", LTV_CURRENT - LTV_AGE);
+  dir = g_win32_get_package_installation_subdirectory
+    ("GNU libintl", my_dll_name, "share\\locale");
+  strcpy (_nl_default_dirname, dir);
+  free (dir);
+}
+#endif
+
 /* Look up MSGID in the DOMAINNAME message catalog for the current
    CATEGORY locale and, if PLURAL is nonzero, search over string
@@ -487,5 +674,10 @@
 
   if (binding == NULL)
-    dirname = (char *) _nl_default_dirname;
+    {
+#ifdef _WIN32
+      _set_nl_default_dirname();
+#endif
+      dirname = (char *) _nl_default_dirname;
+    }
   else if (IS_ABSOLUTE_PATH (binding->dirname))
     dirname = binding->dirname;
@@ -1187,5 +1379,4 @@
     }
 #endif
-
   return language != NULL && strcmp (retval, "C") != 0 ? language : retval;
 }
diff -ru2 /g/tmp/gettext-0.10.40/intl/localealias.c ./intl/localealias.c
--- /g/tmp/gettext-0.10.40/intl/localealias.c   Mon Sep  3 17:00:50 2001
+++ ./intl/localealias.c        Thu Sep 20 01:16:46 2001
@@ -116,4 +116,15 @@
 static size_t maxmap;
 
+#ifdef _WIN32
+/* On Windows we don't want any hardcoded paths */
+#undef LOCALE_ALIAS_PATH
+
+#define WIN32_LEAN_AND_MEAN
+#define STRICT
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+#undef STRICT
+#endif
+
 
 /* Prototypes for local functions.  */
@@ -129,8 +140,24 @@
     const char *name;
 {
+#ifdef _WIN32
+  static char locale_alias_path_buf[MAX_PATH] = "";
+  static const char *locale_alias_path = locale_alias_path_buf;
+  extern const char _nl_default_dirname__[];
+  extern void _set_nl_default_dirname (void);
+#else
   static const char *locale_alias_path = LOCALE_ALIAS_PATH;
+#endif
   struct alias_map *retval;
   const char *result = NULL;
   size_t added;
+
+#ifdef _WIN32
+  if (!locale_alias_path[0])
+    {
+      _set_nl_default_dirname ();
+      strcpy (locale_alias_path_buf, _nl_default_dirname__);
+      strcat (locale_alias_path_buf, ";.");
+    }
+#endif
 
 #ifdef _LIBC




reply via email to

[Prev in Thread] Current Thread [Next in Thread]