]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/intl.cpp
ensure that GetItemRect() returns the real rect and not 0 even if it's called before...
[wxWidgets.git] / src / common / intl.cpp
index e78a33c9d0195b46f91ab3133a5cf141248cc6f0..9efed8b554eeeb09065f389104c0f77a7e27d8cf 100644 (file)
@@ -17,7 +17,7 @@
 // headers
 // ----------------------------------------------------------------------------
 
-#ifdef __GNUG__
+#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
     #pragma implementation "intl.h"
 #endif
 
 #if wxUSE_INTL
 
 // standard headers
+
+#ifndef __WXWINCE__
 #include <locale.h>
+#endif
+
 #include <ctype.h>
 #include <stdlib.h>
 #ifdef HAVE_LANGINFO_H
     #include "wx/dynarray.h"
 #endif // WX_PRECOMP
 
+#ifdef __WIN32__
+    #include "wx/msw/private.h"
+#elif defined(__UNIX_LIKE__)
+    #include "wx/fontmap.h"         // for CharsetToEncoding()
+#endif
+
 #include "wx/file.h"
 #include "wx/tokenzr.h"
 #include "wx/module.h"
 #include "wx/encconv.h"
 #include "wx/hashmap.h"
 
-#ifdef __WIN32__
-    #include "wx/msw/private.h"
-#elif defined(__UNIX_LIKE__)
-    #include "wx/fontmap.h"         // for CharsetToEncoding()
-#endif
-
 #if defined(__WXMAC__)
   #include  "wx/mac/private.h"  // includes mac headers
 #endif
@@ -141,6 +145,7 @@ static inline wxString ExtractNotLang(const wxString& langFull)
 #endif // __UNIX__
 
 
+
 // ----------------------------------------------------------------------------
 // wxMsgCatalogFile corresponds to one disk-file message catalog.
 //
@@ -187,21 +192,37 @@ private:
     // all data is stored here, NULL if no data loaded
     size_t8 *m_pData;
 
+    // amount of memory pointed to by m_pData.
+    size_t32 m_nSize;
+
     // data description
     size_t32          m_numStrings;   // number of strings in this domain
     wxMsgTableEntry  *m_pOrigTable,   // pointer to original   strings
                      *m_pTransTable;  //            translated
 
-    const char *StringAtOfs(wxMsgTableEntry *pTable, size_t32 index) const
-      { return (const char *)(m_pData + Swap(pTable[index].ofsString)); }
+    // swap the 2 halves of 32 bit integer if needed
+    size_t32 Swap(size_t32 ui) const
+    {
+          return m_bSwapped ? (ui << 24) | ((ui & 0xff00) << 8) |
+                              ((ui >> 8) & 0xff00) | (ui >> 24)
+                            : ui;
+    }
 
-    wxString GetCharset() const;
+    const char *StringAtOfs(wxMsgTableEntry *pTable, size_t32 n) const
+    {
+        const wxMsgTableEntry * const ent = pTable + n;
 
-    // utility functions
-      // big<->little endian
-    inline size_t32 Swap(size_t32 ui) const;
+        // this check could fail for a corrupt message catalog
+        size_t32 ofsString = Swap(ent->ofsString);
+        if ( ofsString + Swap(ent->nLen) > m_nSize)
+            return NULL;
 
-    bool          m_bSwapped;   // wrong endianness?
+        return (const char *)(m_pData + ofsString);
+    }
+
+    wxString GetCharset() const;
+
+    bool m_bSwapped;   // wrong endianness?
 
     DECLARE_NO_COPY_CLASS(wxMsgCatalogFile)
 };
@@ -249,22 +270,15 @@ static wxArrayString s_searchPrefixes;
 // wxMsgCatalogFile class
 // ----------------------------------------------------------------------------
 
-// swap the 2 halves of 32 bit integer if needed
-size_t32 wxMsgCatalogFile::Swap(size_t32 ui) const
-{
-  return m_bSwapped ? (ui << 24) | ((ui & 0xff00) << 8) |
-                      ((ui >> 8) & 0xff00) | (ui >> 24)
-                    : ui;
-}
-
 wxMsgCatalogFile::wxMsgCatalogFile()
 {
-  m_pData = NULL;
+    m_pData = NULL;
+    m_nSize = 0;
 }
 
 wxMsgCatalogFile::~wxMsgCatalogFile()
 {
-  wxDELETEA(m_pData);
+    wxDELETEA(m_pData);
 }
 
 // return all directories to search for given prefix
@@ -298,9 +312,11 @@ static wxString GetFullSearchPath(const wxChar *lang)
 
     // LC_PATH is a standard env var containing the search path for the .mo
     // files
+#ifndef __WXWINCE__
     const wxChar *pszLcPath = wxGetenv(wxT("LC_PATH"));
     if ( pszLcPath != NULL )
         searchPath << GetAllMsgCatalogSubdirs(pszLcPath, lang);
+#endif
 
 #ifdef __UNIX__
     // add some standard ones and the one in the tree where wxWin was installed:
@@ -413,6 +429,7 @@ bool wxMsgCatalogFile::Load(const wxChar *szDirPrefix, const wxChar *szName0)
                    Swap(pHeader->ofsOrigTable));
   m_pTransTable = (wxMsgTableEntry *)(m_pData +
                    Swap(pHeader->ofsTransTable));
+  m_nSize = nSize;
 
   // everything is fine
   return TRUE;
@@ -614,7 +631,27 @@ bool wxLocale::Init(const wxChar *szName,
 
     wxCHECK_MSG( szLocale, FALSE, _T("no locale to set in wxLocale::Init()") );
   }
+
+#ifdef __WXWINCE__
+  // FIXME: I'm guessing here
+  wxChar localeName[256];
+  int ret = GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SLANGUAGE, localeName,
+      256);
+  if (ret != 0)
+  {
+    m_pszOldLocale = wxStrdup(localeName);      
+  }
+  else
+    m_pszOldLocale = NULL;
+
+  // TODO: how to find languageId
+  // SetLocaleInfo(languageId, SORT_DEFAULT, localeName);
+#else
   m_pszOldLocale = wxSetlocale(LC_ALL, szLocale);
+  if ( m_pszOldLocale )
+      m_pszOldLocale = wxStrdup(m_pszOldLocale);
+#endif
+
   if ( m_pszOldLocale == NULL )
     wxLogError(_("locale '%s' can not be set."), szLocale);
 
@@ -643,6 +680,39 @@ bool wxLocale::Init(const wxChar *szName,
   return bOk;
 }
 
+
+#if defined(__UNIX__) && wxUSE_UNICODE
+static wxWCharBuffer wxSetlocaleTryUTF(int c, const wxChar *lc)
+{
+    wxMB2WXbuf l = wxSetlocale(c, lc);
+    if ( !l && lc && lc[0] != 0 )
+    {
+       wxString buf(lc);
+        wxString buf2;
+       buf2 = buf + wxT(".UTF-8");
+       l = wxSetlocale(c, buf2.c_str());
+        if ( !l )
+        {
+            buf2 = buf + wxT(".utf-8");
+           l = wxSetlocale(c, buf2.c_str());
+        }
+        if ( !l )
+        {
+            buf2 = buf + wxT(".UTF8");
+           l = wxSetlocale(c, buf2.c_str());
+        }
+        if ( !l )
+        {
+            buf2 = buf + wxT(".utf8");
+           l = wxSetlocale(c, buf2.c_str());
+        }
+    }
+    return l;
+}
+#else
+#define wxSetlocaleTryUTF(c, lc)  wxSetlocale(c, lc)
+#endif
+
 bool wxLocale::Init(int language, int flags)
 {
     int lang = language;
@@ -678,12 +748,12 @@ bool wxLocale::Init(int language, int flags)
     else
         locale = info->CanonicalName;
 
-    wxMB2WXbuf retloc = wxSetlocale(LC_ALL, locale);
+    wxMB2WXbuf retloc = wxSetlocaleTryUTF(LC_ALL, locale);
 
     if ( !retloc )
     {
         // Some C libraries don't like xx_YY form and require xx only
-        retloc = wxSetlocale(LC_ALL, locale.Mid(0,2));
+        retloc = wxSetlocaleTryUTF(LC_ALL, locale.Mid(0,2));
     }
     if ( !retloc )
     {
@@ -696,14 +766,18 @@ bool wxLocale::Init(int language, int flags)
             locale = wxT("in") + locale.Mid(3);
         else if (mid == wxT("yi"))
             locale = wxT("ji") + locale.Mid(3);
+        else if (mid == wxT("nb"))
+            locale = wxT("no_NO");
+        else if (mid == wxT("nn"))
+            locale = wxT("no_NY");
 
-        retloc = wxSetlocale(LC_ALL, locale);
+        retloc = wxSetlocaleTryUTF(LC_ALL, locale);
     }
     if ( !retloc )
     {
         // (This time, we changed locale in previous if-branch, so try again.)
         // Some C libraries don't like xx_YY form and require xx only
-        retloc = wxSetlocale(LC_ALL, locale.Mid(0,2));
+        retloc = wxSetlocaleTryUTF(LC_ALL, locale.Mid(0,2));
     }
     if ( !retloc )
     {
@@ -711,6 +785,17 @@ bool wxLocale::Init(int language, int flags)
         return FALSE;
     }
 #elif defined(__WIN32__)
+
+    #if wxUSE_UNICODE && (defined(__VISUALC__) || defined(__MINGW32__))
+        // NB: setlocale() from msvcrt.dll (used by VC++ and Mingw)
+        //     can't set locale to language that can only be written using
+        //     Unicode.  Therefore wxSetlocale call failed, but we don't want
+        //     to report it as an error -- so that at least message catalogs
+        //     can be used. Watch for code marked with
+        //     #ifdef SETLOCALE_FAILS_ON_UNICODE_LANGS bellow.
+        #define SETLOCALE_FAILS_ON_UNICODE_LANGS
+    #endif
+    
     wxMB2WXbuf retloc = wxT("C");
     if (language != wxLANGUAGE_DEFAULT)
     {
@@ -721,42 +806,69 @@ bool wxLocale::Init(int language, int flags)
         }
         else
         {
+            int codepage = -1;
             wxUint32 lcid = MAKELCID(MAKELANGID(info->WinLang, info->WinSublang),
                                      SORT_DEFAULT);
-            if (SetThreadLocale(lcid))
+            // FIXME
+#ifndef __WXWINCE__
+            SetThreadLocale(lcid);
+#endif
+            // NB: we must translate LCID to CRT's setlocale string ourselves,
+            //     because SetThreadLocale does not modify change the
+            //     interpretation of setlocale(LC_ALL, "") call:
+            wxChar buffer[256];
+            buffer[0] = wxT('\0');
+            GetLocaleInfo(lcid, LOCALE_SENGLANGUAGE, buffer, 256);
+            locale << buffer;
+            if (GetLocaleInfo(lcid, LOCALE_SENGCOUNTRY, buffer, 256) > 0)
+                locale << wxT("_") << buffer;
+            if (GetLocaleInfo(lcid, LOCALE_IDEFAULTANSICODEPAGE, buffer, 256) > 0)
             {
-                retloc = wxSetlocale(LC_ALL, wxEmptyString);
+                codepage = wxAtoi(buffer);
+                if (codepage != 0)
+                    locale << wxT(".") << buffer;
+            }
+            if (locale.IsEmpty())
+            {
+                wxLogLastError(wxT("SetThreadLocale"));
+                wxLogError(wxT("Cannot set locale to language %s."), name.c_str());
+                return FALSE;
             }
             else
             {
-                // Windows9X doesn't support SetThreadLocale, so we must
-                // translate LCID to CRT's setlocale string ourselves
-                locale.Empty();
-                if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
-                {
-                    wxChar buffer[256];
-                    buffer[0] = wxT('\0');
-                    GetLocaleInfo(lcid, LOCALE_SENGLANGUAGE, buffer, 256);
-                    locale << buffer;
-                    if (GetLocaleInfo(lcid, LOCALE_SENGCOUNTRY, buffer, 256) > 0)
-                        locale << wxT("_") << buffer;
-                }
-                if (locale.IsEmpty())
-                {
-                    wxLogLastError(wxT("SetThreadLocale"));
-                    wxLogError(wxT("Cannot set locale to language %s."), name.c_str());
-                    return FALSE;
-                }
-                else
+            // FIXME
+#ifndef __WXWINCE__
+                retloc = wxSetlocale(LC_ALL, locale);
+#endif
+#ifdef SETLOCALE_FAILS_ON_UNICODE_LANGS
+                if (codepage == 0 && (const wxChar*)retloc == NULL)
                 {
-                    retloc = wxSetlocale(LC_ALL, locale);
+                    retloc = wxT("C");
                 }
+#endif
             }
         }
     }
     else
     {
+            // FIXME
+#ifndef __WXWINCE__
         retloc = wxSetlocale(LC_ALL, wxEmptyString);
+#else
+        retloc = NULL;
+#endif
+#ifdef SETLOCALE_FAILS_ON_UNICODE_LANGS
+        if ((const wxChar*)retloc == NULL)
+        {
+            wxChar buffer[16];
+            if (GetLocaleInfo(LOCALE_USER_DEFAULT,
+                              LOCALE_IDEFAULTANSICODEPAGE, buffer, 16) > 0 &&
+                 wxStrcmp(buffer, wxT("0")) == 0)
+            {
+                retloc = wxT("C");
+            }
+        }
+#endif
     }
 
     if ( !retloc )
@@ -772,12 +884,15 @@ bool wxLocale::Init(int language, int flags)
 #endif
 
 #ifndef WX_NO_LOCALE_SUPPORT
-     wxChar *szLocale = retloc ? wxStrdup(retloc) : NULL;
+    wxChar *szLocale = retloc ? wxStrdup(retloc) : NULL;
     bool ret = Init(name, canonical, retloc,
                     (flags & wxLOCALE_LOAD_DEFAULT) != 0,
                     (flags & wxLOCALE_CONV_ENCODING) != 0);
-    if (szLocale)
-        free(szLocale);
+    free(szLocale);
+
+    if ( ret )
+        m_language = lang;
+
     return ret;
 #endif
 }
@@ -865,10 +980,16 @@ void wxLocale::AddCatalogLookupPathPrefix(const wxString& prefix)
         wxString lang;
         if ( langOrig == wxT("iw"))
             lang = _T("he");
-        else if ( langOrig == wxT("in") )
+        else if (langOrig == wxT("in"))
             lang = wxT("id");
-        else if ( langOrig == wxT("ji") )
+        else if (langOrig == wxT("ji"))
             lang = wxT("yi");
+        else if (langOrig == wxT("no_NO"))
+            lang = wxT("nb_NO");
+        else if (langOrig == wxT("no_NY"))
+            lang = wxT("nn_NO");
+        else if (langOrig == wxT("no"))
+            lang = wxT("nb_NO");
         else
             lang = langOrig;
 
@@ -964,7 +1085,7 @@ void wxLocale::AddCatalogLookupPathPrefix(const wxString& prefix)
         lc = wxT("fr_CA") ;
         break ;
       case verNorway:
-        lc = wxT("no_NO") ;
+        lc = wxT("nb_NO") ;
         break ;
       case verIsrael:
         lc = wxT("iw_IL") ;
@@ -1407,6 +1528,16 @@ const wxLanguageInfo *wxLocale::GetLanguageInfo(int lang)
     return NULL;
 }
 
+/* static */
+wxString wxLocale::GetLanguageName(int lang)
+{
+    const wxLanguageInfo *info = GetLanguageInfo(lang);
+    if ( !info )
+        return wxEmptyString;
+    else
+        return info->Description;
+}
+
 /* static */
 const wxLanguageInfo *wxLocale::FindLanguageInfo(const wxString& locale)
 {
@@ -1445,7 +1576,12 @@ const wxLanguageInfo *wxLocale::FindLanguageInfo(const wxString& locale)
 
 wxString wxLocale::GetSysName() const
 {
+            // FIXME
+#ifndef __WXWINCE__
     return wxSetlocale(LC_ALL, NULL);
+#else
+    return wxEmptyString;
+#endif
 }
 
 // clean up
@@ -1461,7 +1597,11 @@ wxLocale::~wxLocale()
 
     // restore old locale
     wxSetLocale(m_pOldLocale);
+    // FIXME
+#ifndef __WXWINCE__
     wxSetlocale(LC_ALL, m_pszOldLocale);
+#endif
+    free((wxChar *)m_pszOldLocale);     // const_cast
 }
 
 // get the translation of given string in current locale
@@ -2313,7 +2453,7 @@ void wxLocale::InitLanguagesDB()
    LNG(wxLANGUAGE_NAURU,                      "na"   , 0              , 0                                 , "Nauru")
    LNG(wxLANGUAGE_NEPALI,                     "ne"   , LANG_NEPALI    , SUBLANG_DEFAULT                   , "Nepali")
    LNG(wxLANGUAGE_NEPALI_INDIA,               "ne_IN", LANG_NEPALI    , SUBLANG_NEPALI_INDIA              , "Nepali (India)")
-   LNG(wxLANGUAGE_NORWEGIAN_BOKMAL,           "no_NO", LANG_NORWEGIAN , SUBLANG_NORWEGIAN_BOKMAL          , "Norwegian (Bokmal)")
+   LNG(wxLANGUAGE_NORWEGIAN_BOKMAL,           "nb_NO", LANG_NORWEGIAN , SUBLANG_NORWEGIAN_BOKMAL          , "Norwegian (Bokmal)")
    LNG(wxLANGUAGE_NORWEGIAN_NYNORSK,          "nn_NO", LANG_NORWEGIAN , SUBLANG_NORWEGIAN_NYNORSK         , "Norwegian (Nynorsk)")
    LNG(wxLANGUAGE_OCCITAN,                    "oc"   , 0              , 0                                 , "Occitan")
    LNG(wxLANGUAGE_ORIYA,                      "or"   , LANG_ORIYA     , SUBLANG_DEFAULT                   , "Oriya")