]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/intl.cpp
added wxEncodingToCodepage() and implemented it properly (using in32 API instead...
[wxWidgets.git] / src / common / intl.cpp
index c3e563c245f0b5c582b6adce2c197f7787d4c1ba..f41c6ba9c54cbd089e22227cd19c9cebba57547a 100644 (file)
@@ -1,5 +1,5 @@
 /////////////////////////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////////////////////////
-// Name:        intl.cpp
+// Name:        src/common/intl.cpp
 // Purpose:     Internationalization and localisation for wxWindows
 // Author:      Vadim Zeitlin
 // Modified by:
 // Purpose:     Internationalization and localisation for wxWindows
 // Author:      Vadim Zeitlin
 // Modified by:
 #if wxUSE_INTL
 
 // standard headers
 #if wxUSE_INTL
 
 // standard headers
-#include  <locale.h>
-#include  <ctype.h>
+#include <locale.h>
+#include <ctype.h>
+#include <stdlib.h>
+#ifdef HAVE_LANGINFO_H
+  #include <langinfo.h>
+#endif
 
 // wxWindows
 
 // wxWindows
-#include "wx/defs.h"
-#include "wx/string.h"
-#include "wx/tokenzr.h"
-#include "wx/intl.h"
+#ifndef WX_PRECOMP
+    #include "wx/string.h"
+    #include "wx/intl.h"
+    #include "wx/log.h"
+    #include "wx/debug.h"
+    #include "wx/utils.h"
+    #include "wx/dynarray.h"
+#endif // WX_PRECOMP
+
 #include "wx/file.h"
 #include "wx/file.h"
-#include "wx/log.h"
-#include "wx/debug.h"
-#include "wx/utils.h"
-#include "wx/dynarray.h"
+#include "wx/tokenzr.h"
 #include "wx/module.h"
 #include "wx/module.h"
+#include "wx/fontmap.h"
+#include "wx/encconv.h"
+
 #ifdef __WIN32__
 #ifdef __WIN32__
-#include "wx/msw/private.h"
+    #include "wx/msw/private.h"
+#elif defined(__UNIX_LIKE__)
+    #include "wx/fontmap.h"         // for CharsetToEncoding()
 #endif
 
 #endif
 
-
-#include <stdlib.h>
-
 // ----------------------------------------------------------------------------
 // simple types
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // simple types
 // ----------------------------------------------------------------------------
@@ -86,9 +94,7 @@ typedef unsigned char size_t8;
             {
                 // Asserting a sizeof directly causes some compilers to
                 // issue a "using constant in a conditional expression" warning
             {
                 // Asserting a sizeof directly causes some compilers to
                 // issue a "using constant in a conditional expression" warning
-                size_t intsize = sizeof(int);
-
-                wxASSERT_MSG( intsize == 4,
+                wxASSERT_MSG( wxAssertIsEqual(sizeof(int), 4),
                               "size_t32 is incorrectly defined!" );
             }
         } intsizechecker;
                               "size_t32 is incorrectly defined!" );
             }
         } intsizechecker;
@@ -335,6 +341,12 @@ static wxString GetFullSearchPath(const wxChar *lang)
 
     // then take the current directory
     // FIXME it should be the directory of the executable
 
     // then take the current directory
     // FIXME it should be the directory of the executable
+#ifdef __WXMAC__
+    wxChar cwd[512] ;
+    wxGetWorkingDirectory( cwd , sizeof( cwd ) ) ;
+    searchPath << GetAllMsgCatalogSubdirs(cwd, lang);
+    // generic search paths could be somewhere in the system folder preferences
+#else
     searchPath << GetAllMsgCatalogSubdirs(wxT("."), lang);
 
     // and finally add some standard ones
     searchPath << GetAllMsgCatalogSubdirs(wxT("."), lang);
 
     // and finally add some standard ones
@@ -342,7 +354,7 @@ static wxString GetFullSearchPath(const wxChar *lang)
         << GetAllMsgCatalogSubdirs(wxT("/usr/share/locale"), lang)
         << GetAllMsgCatalogSubdirs(wxT("/usr/lib/locale"), lang)
         << GetAllMsgCatalogSubdirs(wxT("/usr/local/share/locale"), lang);
         << GetAllMsgCatalogSubdirs(wxT("/usr/share/locale"), lang)
         << GetAllMsgCatalogSubdirs(wxT("/usr/lib/locale"), lang)
         << GetAllMsgCatalogSubdirs(wxT("/usr/local/share/locale"), lang);
-
+#endif
     return searchPath;
 }
 
     return searchPath;
 }
 
@@ -500,17 +512,8 @@ const char *wxMsgCatalog::GetString(const char *szOrig) const
   return NULL;
 }
 
   return NULL;
 }
 
-
-#if wxUSE_GUI
-#include "wx/fontmap.h"
-#include "wx/encconv.h"
-#endif
-
 void wxMsgCatalog::ConvertEncoding()
 {
 void wxMsgCatalog::ConvertEncoding()
 {
-#if wxUSE_GUI
-    wxFontEncoding enc;
-
     // first, find encoding header:
     const char *hdr = StringAtOfs(m_pOrigTable, 0);
     if ( hdr == NULL || hdr[0] != 0 ) {
     // first, find encoding header:
     const char *hdr = StringAtOfs(m_pOrigTable, 0);
     if ( hdr == NULL || hdr[0] != 0 ) {
@@ -527,23 +530,12 @@ void wxMsgCatalog::ConvertEncoding()
     while (header[n] != wxT('\n'))
         charset << header[n++];
 
     while (header[n] != wxT('\n'))
         charset << header[n++];
 
-    enc = wxTheFontMapper->CharsetToEncoding(charset, FALSE);
+#if wxUSE_FONTMAP
+    wxFontEncoding enc = wxTheFontMapper->CharsetToEncoding(charset, FALSE);
     if ( enc == wxFONTENCODING_SYSTEM )
         return; // unknown encoding
 
     if ( enc == wxFONTENCODING_SYSTEM )
         return; // unknown encoding
 
-    wxFontEncoding targetEnc = wxFONTENCODING_SYSTEM;
-#ifdef __UNIX__
-    wxString langFull;
-    if (wxGetEnv(wxT("LC_ALL"), &langFull) ||
-        wxGetEnv(wxT("LC_CTYPE"), &langFull) ||
-        wxGetEnv(wxT("LANG"), &langFull))
-    {
-        wxString lcharset = langFull.AfterFirst(wxT('.')).BeforeFirst(wxT('@'));
-        if (!lcharset.IsEmpty())
-            targetEnc = wxTheFontMapper->CharsetToEncoding(lcharset, FALSE);
-    }
-#endif
-
+    wxFontEncoding targetEnc = wxLocale::GetSystemEncoding();
     if (targetEnc == wxFONTENCODING_SYSTEM)
     {
         wxFontEncodingArray a = wxEncodingConverter::GetPlatformEquivalents(enc);
     if (targetEnc == wxFONTENCODING_SYSTEM)
     {
         wxFontEncodingArray a = wxEncodingConverter::GetPlatformEquivalents(enc);
@@ -559,7 +551,7 @@ void wxMsgCatalog::ConvertEncoding()
 
     for (size_t i = 0; i < m_numStrings; i++)
         converter.Convert((char*)StringAtOfs(m_pTransTable, i));
 
     for (size_t i = 0; i < m_numStrings; i++)
         converter.Convert((char*)StringAtOfs(m_pTransTable, i));
-#endif // wxUSE_GUI
+#endif // wxUSE_FONTMAP
 }
 
 
 }
 
 
@@ -623,7 +615,12 @@ bool wxLocale::Init(const wxChar *szName,
   if ( m_strShort.IsEmpty() ) {
     // FIXME I don't know how these 2 letter abbreviations are formed,
     //       this wild guess is surely wrong
   if ( m_strShort.IsEmpty() ) {
     // FIXME I don't know how these 2 letter abbreviations are formed,
     //       this wild guess is surely wrong
-    m_strShort = tolower(szLocale[0]) + tolower(szLocale[1]);
+    if ( szLocale[0] )
+    {
+        m_strShort += (wxChar)wxTolower(szLocale[0]);
+        if ( szLocale[1] )
+            m_strShort += (wxChar)wxTolower(szLocale[1]);
+    }
   }
 
   // save the old locale to be able to restore it later
   }
 
   // save the old locale to be able to restore it later
@@ -679,7 +676,7 @@ bool wxLocale::Init(int language, int flags)
     wxString name = info->Description;
     wxString canonical = info->CanonicalName;
     wxString locale;
     wxString name = info->Description;
     wxString canonical = info->CanonicalName;
     wxString locale;
-    wxChar *retloc;
+    const wxChar *retloc;
 
     // Set the locale:
 #ifdef __UNIX__
 
     // Set the locale:
 #ifdef __UNIX__
@@ -763,7 +760,8 @@ bool wxLocale::Init(int language, int flags)
         wxLogError(wxT("Cannot set locale to language %s."), name.c_str());
         return FALSE;
     }
         wxLogError(wxT("Cannot set locale to language %s."), name.c_str());
         return FALSE;
     }
-
+#elif defined(__WXMAC__)
+    retloc = wxSetlocale(LC_ALL , wxEmptyString);
 #else
     return FALSE;
 #endif
 #else
     return FALSE;
 #endif
@@ -803,7 +801,7 @@ void wxLocale::AddCatalogLookupPathPrefix(const wxString& prefix)
         return wxLANGUAGE_ENGLISH;
     }
 
         return wxLANGUAGE_ENGLISH;
     }
 
-    if ( langFull == _T("C") )
+    if ( langFull == _T("C") || langFull == _T("POSIX") )
     {
         // default C locale
         return wxLANGUAGE_ENGLISH;
     {
         // default C locale
         return wxLANGUAGE_ENGLISH;
@@ -811,18 +809,31 @@ void wxLocale::AddCatalogLookupPathPrefix(const wxString& prefix)
 
     // the language string has the following form
     //
 
     // the language string has the following form
     //
-    //      lang[_LANG[.encoding]]
+    //      lang[_LANG][.encoding][@modifier]
+    //
+    // (see environ(5) in the Open Unix specification)
     //
     //
-    // where lang is the primary language, LANG is a sublang
+    // where lang is the primary language, LANG is a sublang/territory,
+    // encoding is the charset to use and modifier "allows the user to select
+    // a specific instance of localization data within a single category"
     //
     // for example, the following strings are valid:
     //      fr
     //      fr_FR
     //      de_DE.iso88591
     //
     // for example, the following strings are valid:
     //      fr
     //      fr_FR
     //      de_DE.iso88591
+    //      de_DE@euro
+    //      de_DE.iso88591@euro
 
     // for now we don't use the encoding, although we probably should (doing
     // translations of the msg catalogs on the fly as required) (TODO)
 
     // for now we don't use the encoding, although we probably should (doing
     // translations of the msg catalogs on the fly as required) (TODO)
-    langFull = langFull.BeforeFirst(_T('.'));
+    //
+    // we don't use the modifiers neither but we probably should translate
+    // "euro" into iso885915
+    size_t posEndLang = langFull.find_first_of(_T("@."));
+    if ( posEndLang != wxString::npos )
+    {
+        langFull.Truncate(posEndLang);
+    }
 
     // in addition to the format above, we also can have full language names
     // in LANG env var - for example, SuSE is known to use LANG="german" - so
 
     // in addition to the format above, we also can have full language names
     // in LANG env var - for example, SuSE is known to use LANG="german" - so
@@ -901,6 +912,292 @@ void wxLocale::AddCatalogLookupPathPrefix(const wxString& prefix)
             }
         }
     }
             }
         }
     }
+#elif defined(__WXMAC__)
+    char* lc = NULL ;
+    long lang = GetScriptVariable( smSystemScript, smScriptLang) ;
+    switch( GetScriptManagerVariable( smRegionCode ) ) {
+      case verUS :
+        lc = "en_US" ;
+        break ;
+      case verFrance :
+        lc = "fr_FR" ;
+        break ;
+      case verBritain :
+        lc = "en_GB" ;
+        break ;
+      case verGermany :
+        lc = "de_DE" ;
+        break ;
+      case verItaly :
+        lc = "it_IT" ;
+        break ;
+      case verNetherlands :
+        lc = "nl_NL" ;
+        break ;
+      case verFlemish :
+        lc = "nl_BE" ;
+        break ;
+      case verSweden :
+        lc = "sv_SE" ;
+        break ;
+      case verSpain :
+        lc = "es_ES" ;
+        break ;
+      case verDenmark :
+        lc = "da_DK" ;
+        break ;
+      case verPortugal :
+        lc = "pt_PT" ;
+        break ;
+      case verFrCanada:
+        lc = "fr_CA" ;
+        break ;
+      case verNorway:
+        lc = "no_NO" ;
+        break ;
+      case verIsrael:
+        lc = "iw_IL" ;
+        break ;
+      case verJapan:
+        lc = "ja_JP" ;
+        break ;
+      case verAustralia:
+        lc = "en_AU" ;
+        break ;
+      case verArabic:
+        lc = "ar" ;
+        break ;
+      case verFinland:
+        lc = "fi_FI" ;
+        break ;
+      case verFrSwiss:
+        lc = "fr_CH" ;
+        break ;
+      case verGrSwiss:
+        lc = "de_CH" ;
+        break ;
+      case verGreece:
+        lc = "el_GR" ;
+        break ;
+      case verIceland:
+        lc = "is_IS" ;
+        break ;
+      case verMalta:
+        lc = "mt_MT" ;
+        break ;
+      case verCyprus:
+      // _CY is not part of wx, so we have to translate according to the system language
+        if ( lang == langGreek ) {
+          lc = "el_GR" ;
+        }
+        else if ( lang == langTurkish ) {
+          lc = "tr_TR" ;
+        }
+        break ;
+      case verTurkey:
+        lc = "tr_TR" ;
+        break ;
+      case verYugoCroatian:
+        lc = "hr_HR" ;
+        break ;
+      case verIndiaHindi:
+        lc = "hi_IN" ;
+        break ;
+      case verPakistanUrdu:
+        lc = "ur_PK" ;
+        break ;
+      case verTurkishModified:
+        lc = "tr_TR" ;
+        break ;
+      case verItalianSwiss:
+        lc = "it_CH" ;
+        break ;
+      case verInternational:
+        lc = "en" ;
+        break ;
+      case verRomania:
+        lc = "ro_RO" ;
+        break ;
+      case verGreecePoly:
+        lc = "el_GR" ;
+        break ;
+      case verLithuania:
+        lc = "lt_LT" ;
+        break ;
+      case verPoland:
+        lc = "pl_PL" ;
+        break ;
+      case verMagyar :
+      case verHungary:
+        lc = "hu_HU" ;
+        break ;
+      case verEstonia:
+        lc = "et_EE" ;
+        break ;
+      case verLatvia:
+        lc = "lv_LV" ;
+        break ;
+      case verSami:
+        // not known
+        break ;
+      case verFaroeIsl:
+        lc = "fo_FO" ;
+        break ;
+      case verIran:
+        lc = "fa_IR" ;
+        break ;
+      case verRussia:
+        lc = "ru_RU" ;
+        break ;
+       case verIreland:
+        lc = "ga_IE" ;
+        break ;
+      case verKorea:
+        lc = "ko_KR" ;
+        break ;
+      case verChina:
+        lc = "zh_CN" ;
+        break ;
+      case verTaiwan:
+        lc = "zh_TW" ;
+        break ;
+      case verThailand:
+        lc = "th_TH" ;
+        break ;
+      case verCzech:
+        lc = "cs_CZ" ;
+        break ;
+      case verSlovak:
+        lc = "sk_SK" ;
+        break ;
+      case verBengali:
+        lc = "bn" ;
+        break ;
+      case verByeloRussian:
+        lc = "be_BY" ;
+        break ;
+      case verUkraine:
+        lc = "uk_UA" ;
+        break ;
+      case verGreeceAlt:
+        lc = "el_GR" ;
+        break ;
+      case verSerbian:
+        lc = "sr_YU" ;
+        break ;
+      case verSlovenian:
+        lc = "sl_SI" ;
+        break ;
+      case verMacedonian:
+        lc = "mk_MK" ;
+        break ;
+      case verCroatia:
+        lc = "hr_HR" ;
+        break ;
+      case verBrazil:
+        lc = "pt_BR " ;
+        break ;
+      case verBulgaria:
+        lc = "bg_BG" ;
+        break ;
+      case verCatalonia:
+        lc = "ca_ES" ;
+        break ;
+      case verScottishGaelic:
+        lc = "gd" ;
+        break ;
+      case verManxGaelic:
+        lc = "gv" ;
+        break ;
+      case verBreton:
+        lc = "br" ;
+        break ;
+      case verNunavut:
+        lc = "iu_CA" ;
+        break ;
+      case verWelsh:
+        lc = "cy" ;
+        break ;
+      case verIrishGaelicScript:
+        lc = "ga_IE" ;
+        break ;
+      case verEngCanada:
+        lc = "en_CA" ;
+        break ;
+      case verBhutan:
+        lc = "dz_BT" ;
+        break ;
+      case verArmenian:
+        lc = "hy_AM" ;
+        break ;
+      case verGeorgian:
+        lc = "ka_GE" ;
+        break ;
+      case verSpLatinAmerica:
+        lc = "es_AR" ;
+        break ;
+      case verTonga:
+        lc = "to_TO" ;
+        break ;
+      case verFrenchUniversal:
+        lc = "fr_FR" ;
+        break ;
+      case verAustria:
+        lc = "de_AT" ;
+        break ;
+      case verGujarati:
+        lc = "gu_IN" ;
+        break ;
+      case verPunjabi:
+        lc = "pa" ;
+        break ;
+      case verIndiaUrdu:
+        lc = "ur_IN" ;
+        break ;
+      case verVietnam:
+        lc = "vi_VN" ;
+        break ;
+      case verFrBelgium:
+        lc = "fr_BE" ;
+        break ;
+      case verUzbek:
+        lc = "uz_UZ" ;
+        break ;
+      case verSingapore:
+        lc = "zh_SG" ;
+        break ;
+      case verNynorsk:
+        lc = "nn_NO" ;
+        break ;
+      case verAfrikaans:
+        lc = "af_ZA" ;
+        break ;
+      case verEsperanto:
+        lc = "eo" ;
+        break ;
+      case verMarathi:
+        lc = "mr_IN" ;
+        break ;
+      case verTibetan:
+        lc = "bo" ;
+        break ;
+      case verNepal:
+        lc = "ne_NP" ;
+        break ;
+      case verGreenland:
+        lc = "kl_GL" ;
+        break ;
+      default :
+        break ;
+   }
+  for ( i = 0; i < count; i++ )
+  {
+      if ( ms_languagesDB->Item(i).CanonicalName == lc )
+      {
+          break;
+      }
+  }
+    
 #elif defined(__WIN32__)
     LCID lcid = GetUserDefaultLCID();
     if ( lcid != 0 )
 #elif defined(__WIN32__)
     LCID lcid = GetUserDefaultLCID();
     if ( lcid != 0 )
@@ -930,6 +1227,111 @@ void wxLocale::AddCatalogLookupPathPrefix(const wxString& prefix)
     return wxLANGUAGE_UNKNOWN;
 }
 
     return wxLANGUAGE_UNKNOWN;
 }
 
+// ----------------------------------------------------------------------------
+// encoding stuff
+// ----------------------------------------------------------------------------
+
+// this is a bit strange as under Windows we get the encoding name using its
+// numeric value and under Unix we do it the other way round, but this just
+// reflects the way different systems provide he encoding info
+
+/* static */
+wxString wxLocale::GetSystemEncodingName()
+{
+    wxString encname;
+
+#if defined(__WIN32__) && !defined(__WXMICROWIN__)
+    // FIXME: what is the error return value for GetACP()?
+    UINT codepage = ::GetACP();
+    encname.Printf(_T("windows-%u"), codepage);
+#elif defined(__UNIX_LIKE__)
+
+#if defined(HAVE_LANGINFO_H) && defined(CODESET)
+    // GNU libc provides current character set this way (this conforms
+    // to Unix98)
+    char *oldLocale = strdup(setlocale(LC_CTYPE, NULL));
+    setlocale(LC_CTYPE, "");
+    char *alang = nl_langinfo(CODESET);
+    setlocale(LC_CTYPE, oldLocale);
+    free(oldLocale);
+    if (alang)
+    {
+        encname = wxConvLibc.cMB2WX(alang);
+    }
+    else
+#endif // HAVE_LANGINFO_H
+    {
+        // if we can't get at the character set directly, try to see if it's in
+        // the environment variables (in most cases this won't work, but I was
+        // out of ideas)
+        wxChar *lang = wxGetenv(wxT("LC_ALL"));
+        wxChar *dot = lang ? wxStrchr(lang, wxT('.')) : (wxChar *)NULL;
+        if (!dot)
+        {
+            lang = wxGetenv(wxT("LC_CTYPE"));
+            if ( lang )
+                dot = wxStrchr(lang, wxT('.'));
+        }
+        if (!dot)
+        {
+            lang = wxGetenv(wxT("LANG"));
+            if ( lang )
+                dot = wxStrchr(lang, wxT('.'));
+        }
+
+        if ( dot )
+        {
+            encname = dot+1;
+        }
+    }
+#endif // Win32/Unix
+
+    return encname;
+}
+
+/* static */
+wxFontEncoding wxLocale::GetSystemEncoding()
+{
+#if defined(__WIN32__) && !defined(__WXMICROWIN__)
+    UINT codepage = ::GetACP();
+
+    // wxWindows only knows about CP1250-1257, 932, 936, 949, 950
+    if ( codepage >= 1250 && codepage <= 1257 )
+    {
+        return (wxFontEncoding)(wxFONTENCODING_CP1250 + codepage - 1250);
+    }
+
+    if ( codepage == 932 )
+    {
+        return wxFONTENCODING_CP932;
+    }
+
+    if ( codepage == 936 )
+    {
+        return wxFONTENCODING_CP936;
+    }
+
+    if ( codepage == 949 )
+    {
+        return wxFONTENCODING_CP949;
+    }
+
+    if ( codepage == 950 )
+    {
+        return wxFONTENCODING_CP950;
+    }
+#elif defined(__UNIX_LIKE__) && wxUSE_FONTMAP
+    wxString encname = GetSystemEncodingName();
+    if ( !encname.empty() )
+    {
+        return wxTheFontMapper->
+            CharsetToEncoding(encname, FALSE /* not interactive */);
+    }
+#endif // Win32/Unix
+
+    return wxFONTENCODING_SYSTEM;
+}
+
 /*static*/ void wxLocale::AddLanguage(const wxLanguageInfo& info)
 {
     CreateLanguagesDB();
 /*static*/ void wxLocale::AddLanguage(const wxLanguageInfo& info)
 {
     CreateLanguagesDB();
@@ -1008,12 +1410,13 @@ const wxMB2WXbuf wxLocale::GetString(const wxChar *szOrigString,
 
     return (wxMB2WXbuf)(szOrigString);
   }
 
     return (wxMB2WXbuf)(szOrigString);
   }
-  else
-  {
-    return wxConvertMB2WX(pszTrans); // or preferably wxCSConv(charset).cMB2WX(pszTrans) or something,
-                                     // a macro similar to wxConvertMB2WX could be written for that
-  }
 
 
+  // or preferably wxCSConv(charset).cMB2WX(pszTrans) or something, a macro
+  // similar to wxConvertMB2WX could be written for that
+
+  return wxConvertMB2WX(pszTrans);
+
+  // undo the hack from the beginning of this function
   #undef szOrgString
 }
 
   #undef szOrgString
 }
 
@@ -1109,7 +1512,7 @@ IMPLEMENT_DYNAMIC_CLASS(wxLocaleModule, wxModule)
 // This table is generated by misc/languages/genlang.py
 // When making changes, please put them into misc/languages/langtabl.txt
 
 // This table is generated by misc/languages/genlang.py
 // When making changes, please put them into misc/languages/langtabl.txt
 
-#ifndef __WIN32__
+#if !defined(__WIN32__) || defined(__WXMICROWIN__)
 
 #define SETWINLANG(info,lang,sublang)
 
 
 #define SETWINLANG(info,lang,sublang)
 
@@ -1845,7 +2248,5 @@ void wxLocale::InitLanguagesDB()
 
 // --- --- --- generated code ends here --- --- ---
 
 
 // --- --- --- generated code ends here --- --- ---
 
-
-
 #endif // wxUSE_INTL
 
 #endif // wxUSE_INTL