Obsolete option --no-sig-create-check.
[gnupg.git] / util / simple-gettext.c
index 8ec6aba..9225737 100644 (file)
@@ -1,11 +1,12 @@
 /* simple-gettext.c  - a simplified version of gettext.
- * Copyright (C) 1995, 1996, 1997, 1999 Free Software Foundation, Inc.
+ * Copyright (C) 1995, 1996, 1997, 1999,
+ *               2005 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
  * GnuPG is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
  * GnuPG is distributed in the hope that it will be useful,
@@ -14,8 +15,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /* This is a simplified version of gettext written by Ulrich Drepper.
@@ -41,6 +41,7 @@
 #include "types.h"
 #include "util.h"
 
+#include "windows.h" /* For GetModuleFileName.  */
 
 /* The magic number of the GNU message catalog format. */
 #define MAGIC        0x950412de
@@ -230,68 +231,154 @@ load_domain( const char *filename )
 }
 
 
-/****************
- * Set the file used for translations. Pass a NULL to disable
- * translation.  A new filename may be set at anytime.
- * WARNING: After changing the filename you should not access any data
- *         retrieved by gettext().
+/* Set the file used for translations.  Pass a NULL to disable
+   translation.  A new filename may be set at anytime.  WARNING: After
+   changing the filename you should not access any data retrieved by
+   gettext().
+
+   If REGKEY is not NULL, the function tries to selected the language
+   the registry key "Lang" below that key.  If in addition the
+   environment variable LANGUAGE has been set, that value will
+   override a value set by the registry key.
  */
 int
-set_gettext_file( const char *filename )
+set_gettext_file ( const char *filename, const char *regkey )
 {
-    struct loaded_domain *domain = NULL;
+  struct loaded_domain *domain = NULL;
 
-    if( filename && *filename ) {
-       if( filename[0] == '/'
+  if ( filename && *filename )
+    {
+      if ( filename[0] == '/'
 #ifdef HAVE_DRIVE_LETTERS
-           || ( isalpha(filename[0])
-                && filename[1] == ':'
-                && (filename[2] == '/' || filename[2] == '\\') )
+           || ( isalpha(filename[0])
+                && filename[1] == ':'
+                && (filename[2] == '/' || filename[2] == '\\') )
 #endif
-          ) {
-           /* absolute path - use it as is */
-           domain = load_domain( filename );
+          )
+        {
+          /* absolute path - use it as is */
+          domain = load_domain( filename );
        }
-       else { /* relative path - append ".mo" and get dir from the environment */
-           char *buf = NULL;
-           char *dir;
-            char *p;
-
-           dir = read_w32_registry_string( NULL,
-                                           "Control Panel\\Mingw32\\NLS",
-                                           "MODir" );
-           if( dir && (buf=malloc(strlen(dir)+strlen(filename)+1+3+1)) ) {
-               strcpy(stpcpy(stpcpy(stpcpy( buf, dir),"\\"), filename),".mo");
-                /* Better make sure that we don't mix forward and
-                   backward slashes.  It seems that some Windoze
-                   versions don't accept this. */
-                for (p=buf; *p; p++)
-                  {
-                    if (*p == '/')
-                      *p = '\\';
-                  }
-               domain = load_domain( buf );
-               free(buf);
-           }
-           free(dir);
+      else if (regkey)  /* Standard.  */
+        {
+          char *instdir, *langid, *fname;
+          char *p;
+          int envvar_mode = 0;
+          
+        again:
+          if (!envvar_mode && (p = getenv ("LANGUAGE")) && *p)
+            {
+              envvar_mode = 1;
+              langid = malloc (strlen (p)+1);
+              if (!langid)
+                return -1;
+              strcpy (langid, p);
+              /* We only make use of the first language given.  Strip
+                 the rest.  */
+              p = strchr (langid, ':');
+              if (p)
+                *p = 0;
+              
+              /* In the $LANGUAGE case we do not use the registered
+                 installation directory but the one where the gpg
+                 binary has been found.  */
+              instdir = malloc (MAX_PATH+5);
+              if ( !instdir || !GetModuleFileName (NULL, instdir, MAX_PATH) )
+                {
+                  free (langid);
+                  free (instdir);
+                  return -1; /* Error getting the process' file name.  */
+                }
+              p = strrchr (instdir, DIRSEP_C);
+              if (!p)
+                {
+                  free (langid);
+                  free (instdir);
+                  return -1; /* Invalid file name returned.  */
+                }
+              *p = 0;
+            }
+          else
+            {
+              instdir = read_w32_registry_string ("HKEY_LOCAL_MACHINE",
+                                                  regkey,
+                                                  "Install Directory");
+              if (!instdir)
+                return -1;
+              langid = read_w32_registry_string (NULL, /* HKCU then HKLM */
+                                                 regkey,
+                                                 "Lang");
+              if (!langid)
+                {
+                  free (instdir);
+                  return -1;
+                }
+            }
+          
+          /* Strip stuff after a dot in case the user tried to enter
+             the entire locale syntacs as usual for POSIX.  */
+          p = strchr (langid, '.');
+          if (p)
+            *p = 0;
+          
+          /* Build the key: "<instdir>/<domain>.nls/<langid>.mo" We
+             use a directory below the installation directory with the
+             domain included in case the software has been insalled
+             with other software altogether at the same place.  */
+          fname = malloc (strlen (instdir) + 1 + strlen (filename) + 5
+                          + strlen (langid) + 3 + 1);
+          if (!fname)
+            {
+              free (instdir);
+              free (langid);
+              return -1;
+            }
+          strcpy (stpcpy (stpcpy (stpcpy (stpcpy ( stpcpy (fname,
+                  instdir),"\\"), filename), ".nls\\"), langid), ".mo");
+          free (instdir);
+          free (langid);
+
+          /* Better make sure that we don't mix forward and backward
+             slashes.  It seems that some Windoze versions don't
+             accept this. */
+          for (p=fname; *p; p++) 
+            {
+              if (*p == '/')
+                *p = '\\';
+            }
+          domain = load_domain (fname);
+          free(fname);
+
+          if (!domain && envvar_mode == 1)
+            {
+              /* In case it failed, we try again using the registry
+                 method. */
+              envvar_mode++;
+              goto again;
+            }
        }
-       if( !domain )
-           return -1;
+      
+
+      if (!domain)
+        return -1;
     }
 
-    if( the_domain ) {
-        struct overflow_space_s *os, *os2;
-       free( the_domain->data );
-       free( the_domain->mapped );
-        for (os=the_domain->overflow_space; os; os = os2) {
-            os2 = os->next;
-            free (os);
+  if ( the_domain )
+    {
+      struct overflow_space_s *os, *os2;
+
+      free ( the_domain->data );
+      free ( the_domain->mapped );
+      for (os=the_domain->overflow_space; os; os = os2)
+        {
+          os2 = os->next;
+          free (os);
         }
-       free( the_domain );
-       the_domain = NULL;
+      free ( the_domain );
+      the_domain = NULL;
     }
-    the_domain = domain;
-    return 0;
+  the_domain = domain;
+  return 0;
 }
 
 
@@ -332,7 +419,7 @@ get_string( struct loaded_domain *domain, u32 idx )
           else
             p = "ERROR in GETTEXT MALLOC";
         }
-      m_free (buf);
+      xfree (buf);
     }
   else if (domain->mapped[idx] == 2) 
     { /* We need to get the string from the overflow_space. */
@@ -427,7 +514,7 @@ gettext( const char *msgid )
        log_info("InputCP=%u  OutputCP=%u\n", cp1, cp2 );
 
        if( !SetConsoleOutputCP( 1252 ) )
-          log_info("SetConsoleOutputCP failed: %d\n", (int)GetLastError() );
+            log_info("SetConsoleOutputCP failed: %s\n", w32_strerror (0));
 
        cp1 = GetConsoleCP();
        cp2 = GetConsoleOutputCP();