]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/intl.cpp
limit recursion depth in DumpUDT() to prevent crashes when dumping linked lists
[wxWidgets.git] / src / common / intl.cpp
index ac1b779ea411572368b772a16507a3b8623ba5b0..e068eeb93f7dc8e82cd143fb397d6daebd8619a8 100644 (file)
@@ -72,6 +72,7 @@
 #endif
 
 #include "wx/file.h"
+#include "wx/filename.h"
 #include "wx/tokenzr.h"
 #include "wx/module.h"
 #include "wx/fontmap.h"
@@ -99,9 +100,6 @@ typedef wxUint32 size_t32;
 const size_t32 MSGCATALOG_MAGIC    = 0x950412de;
 const size_t32 MSGCATALOG_MAGIC_SW = 0xde120495;
 
-// extension of ".mo" files
-#define MSGCATALOG_EXTENSION  _T(".mo")
-
 // the constants describing the format of lang_LANG locale string
 static const size_t LEN_LANG = 2;
 static const size_t LEN_SUBLANG = 2;
@@ -1037,6 +1035,8 @@ static wxString GetFullSearchPath(const wxChar *lang)
                    << wxPATH_SEP;
     }
 
+    // TODO: use wxStandardPaths instead of all this mess!!
+
     // LC_PATH is a standard env var containing the search path for the .mo
     // files
 #ifndef __WXWINCE__
@@ -1056,30 +1056,30 @@ static wxString GetFullSearchPath(const wxChar *lang)
 
     // 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);
+#if defined(__WXMAC__)
+    searchPath << GetAllMsgCatalogSubdirs(wxGetCwd(), lang);
     // generic search paths could be somewhere in the system folder preferences
-#else // !Mac
+#elif defined(__WXMSW__)
+    // look in the directory of the executable
+    wxString path;
+    wxSplitPath(wxGetFullModuleName(), &path, NULL, NULL);
+    searchPath << GetAllMsgCatalogSubdirs(path, lang);
+#else // !Mac, !MSW
     searchPath << GetAllMsgCatalogSubdirs(wxT("."), lang);
-
 #endif // platform
 
     return searchPath;
 }
 
 // open disk file and read in it's contents
-bool wxMsgCatalogFile::Load(const wxChar *szDirPrefix, const wxChar *szName0,
+bool wxMsgCatalogFile::Load(const wxChar *szDirPrefix, const wxChar *szName,
                             wxPluralFormsCalculatorPtr& rPluralFormsCalculator)
 {
-   /* We need to handle locales like  de_AT.iso-8859-1
-      For this we first chop off the .CHARSET specifier and ignore it.
-      FIXME: UNICODE SUPPORT: must use CHARSET specifier!
-   */
-   wxString szName = szName0;
-   if(szName.Find(wxT('.')) != -1) // contains a dot
-      szName = szName.Left(szName.Find(wxT('.')));
+  /*
+     We need to handle locales like  de_AT.iso-8859-1
+     For this we first chop off the .CHARSET specifier and ignore it.
+     FIXME: UNICODE SUPPORT: must use CHARSET specifier!
+  */
 
   wxString searchPath = GetFullSearchPath(szDirPrefix);
   const wxChar *sublocale = wxStrchr(szDirPrefix, wxT('_'));
@@ -1093,9 +1093,6 @@ bool wxMsgCatalogFile::Load(const wxChar *szDirPrefix, const wxChar *szName0,
                  << wxPATH_SEP;
   }
 
-  wxString strFile = szName;
-  strFile += MSGCATALOG_EXTENSION;
-
   // don't give translation errors here because the wxstd catalog might
   // not yet be loaded (and it's normal)
   //
@@ -1103,36 +1100,37 @@ bool wxMsgCatalogFile::Load(const wxChar *szDirPrefix, const wxChar *szName0,
 
   NoTransErr noTransErr;
   wxLogVerbose(_("looking for catalog '%s' in path '%s'."),
-               szName.c_str(), searchPath.c_str());
+               szName, searchPath.c_str());
 
+  wxFileName fn(szName);
+  fn.SetExt(_T("mo"));
   wxString strFullName;
-  if ( !wxFindFileInPath(&strFullName, searchPath, strFile) ) {
-    wxLogVerbose(_("catalog file for domain '%s' not found."), szName.c_str());
-    return FALSE;
+  if ( !wxFindFileInPath(&strFullName, searchPath, fn.GetFullPath()) ) {
+    wxLogVerbose(_("catalog file for domain '%s' not found."), szName);
+    return false;
   }
 
   // open file
-  wxLogVerbose(_("using catalog '%s' from '%s'."),
-             szName.c_str(), strFullName.c_str());
+  wxLogVerbose(_("using catalog '%s' from '%s'."), szName, strFullName.c_str());
 
   wxFile fileMsg(strFullName);
   if ( !fileMsg.IsOpened() )
-    return FALSE;
+    return false;
 
-  // get the file size
-  off_t nSize = fileMsg.Length();
+  // get the file size (assume it is less than 4Gb...)
+  wxFileOffset nSize = fileMsg.Length();
   if ( nSize == wxInvalidOffset )
-    return FALSE;
+    return false;
 
   // read the whole file in memory
   m_pData = new size_t8[nSize];
-  if ( fileMsg.Read(m_pData, nSize) != nSize ) {
+  if ( fileMsg.Read(m_pData, (size_t)nSize) != nSize ) {
     wxDELETEA(m_pData);
-    return FALSE;
+    return false;
   }
 
   // examine header
-  bool bValid = (size_t)nSize > sizeof(wxMsgCatalogHeader);
+  bool bValid = nSize + (size_t)0 > sizeof(wxMsgCatalogHeader);
 
   wxMsgCatalogHeader *pHeader = (wxMsgCatalogHeader *)m_pData;
   if ( bValid ) {
@@ -1148,7 +1146,7 @@ bool wxMsgCatalogFile::Load(const wxChar *szDirPrefix, const wxChar *szName0,
     wxLogWarning(_("'%s' is not a valid message catalog."), strFullName.c_str());
 
     wxDELETEA(m_pData);
-    return FALSE;
+    return false;
   }
 
   // initialize
@@ -1157,7 +1155,7 @@ bool wxMsgCatalogFile::Load(const wxChar *szDirPrefix, const wxChar *szName0,
                    Swap(pHeader->ofsOrigTable));
   m_pTransTable = (wxMsgTableEntry *)(m_pData +
                    Swap(pHeader->ofsTransTable));
-  m_nSize = nSize;
+  m_nSize = (size_t32)nSize;
 
   // now parse catalog's header and try to extract catalog charset and
   // plural forms formula from it:
@@ -1222,7 +1220,7 @@ void wxMsgCatalogFile::FillHash(wxMessagesHash& hash,
 {
 #if wxUSE_WCHAR_T
     wxCSConv *csConv = NULL;
-    if ( !!m_charset )
+    if ( !m_charset.empty() )
         csConv = new wxCSConv(m_charset);
 
     wxMBConv& inputConv = csConv ? *((wxMBConv*)csConv) : *wxConvCurrent;
@@ -1234,15 +1232,15 @@ void wxMsgCatalogFile::FillHash(wxMessagesHash& hash,
 #elif wxUSE_FONTMAP
     wxASSERT_MSG( msgIdCharset == NULL,
                   _T("non-ASCII msgid languages only supported if wxUSE_WCHAR_T=1") );
-    
+
     wxEncodingConverter converter;
     if ( convertEncoding )
     {
         wxFontEncoding targetEnc = wxFONTENCODING_SYSTEM;
-        wxFontEncoding enc = wxFontMapper::Get()->CharsetToEncoding(m_charset, FALSE);
+        wxFontEncoding enc = wxFontMapperBase::Get()->CharsetToEncoding(m_charset, false);
         if ( enc == wxFONTENCODING_SYSTEM )
         {
-            convertEncoding = FALSE; // unknown encoding
+            convertEncoding = false; // unknown encoding
         }
         else
         {
@@ -1252,10 +1250,10 @@ void wxMsgCatalogFile::FillHash(wxMessagesHash& hash,
                 wxFontEncodingArray a = wxEncodingConverter::GetPlatformEquivalents(enc);
                 if (a[0] == enc)
                     // no conversion needed, locale uses native encoding
-                    convertEncoding = FALSE;
+                    convertEncoding = false;
                 if (a.GetCount() == 0)
                     // we don't know common equiv. under this platform
-                    convertEncoding = FALSE;
+                    convertEncoding = false;
                 targetEnc = a[0];
             }
         }
@@ -1338,10 +1336,10 @@ bool wxMsgCatalog::Load(const wxChar *szDirPrefix, const wxChar *szName,
     if ( file.Load(szDirPrefix, szName, m_pluralFormsCalculator) )
     {
         file.FillHash(m_messages, msgIdCharset, bConvertEncoding);
-        return TRUE;
+        return true;
     }
 
-    return FALSE;
+    return false;
 }
 
 const wxChar *wxMsgCatalog::GetString(const wxChar *sz, size_t n) const
@@ -1398,6 +1396,9 @@ wxLanguageInfoArray *wxLocale::ms_languagesDB = NULL;
 void wxLocale::DoCommonInit()
 {
   m_pszOldLocale = NULL;
+
+  m_pOldLocale = wxSetLocale(this);
+
   m_pMsgCat = NULL;
   m_language = wxLANGUAGE_UNKNOWN;
   m_initialized = false;
@@ -1425,7 +1426,7 @@ bool wxLocale::Init(const wxChar *szName,
     // the argument to setlocale()
     szLocale = szShort;
 
-    wxCHECK_MSG( szLocale, FALSE, _T("no locale to set in wxLocale::Init()") );
+    wxCHECK_MSG( szLocale, false, _T("no locale to set in wxLocale::Init()") );
   }
 
 #ifdef __WXWINCE__
@@ -1455,7 +1456,7 @@ bool wxLocale::Init(const wxChar *szName,
 
   // the short name will be used to look for catalog files as well,
   // so we need something here
-  if ( m_strShort.IsEmpty() ) {
+  if ( m_strShort.empty() ) {
     // FIXME I don't know how these 2 letter abbreviations are formed,
     //       this wild guess is surely wrong
     if ( szLocale && szLocale[0] )
@@ -1466,12 +1467,9 @@ bool wxLocale::Init(const wxChar *szName,
     }
   }
 
-  // save the old locale to be able to restore it later
-  m_pOldLocale = wxSetLocale(this);
-
   // load the default catalog with wxWidgets standard messages
   m_pMsgCat = NULL;
-  bool bOk = TRUE;
+  bool bOk = true;
   if ( bLoadDefault )
     bOk = AddCatalog(wxT("wxstd"));
 
@@ -1479,30 +1477,30 @@ bool wxLocale::Init(const wxChar *szName,
 }
 
 
-#if defined(__UNIX__) && wxUSE_UNICODE
+#if defined(__UNIX__) && wxUSE_UNICODE && !defined(__WXMAC__)
 static wxWCharBuffer wxSetlocaleTryUTF(int c, const wxChar *lc)
 {
     wxMB2WXbuf l = wxSetlocale(c, lc);
     if ( !l && lc && lc[0] != 0 )
     {
-       wxString buf(lc);
+        wxString buf(lc);
         wxString buf2;
-       buf2 = buf + wxT(".UTF-8");
-       l = wxSetlocale(c, buf2.c_str());
+        buf2 = buf + wxT(".UTF-8");
+        l = wxSetlocale(c, buf2.c_str());
         if ( !l )
         {
             buf2 = buf + wxT(".utf-8");
-           l = wxSetlocale(c, buf2.c_str());
+            l = wxSetlocale(c, buf2.c_str());
         }
         if ( !l )
         {
             buf2 = buf + wxT(".UTF8");
-           l = wxSetlocale(c, buf2.c_str());
+            l = wxSetlocale(c, buf2.c_str());
         }
         if ( !l )
         {
             buf2 = buf + wxT(".utf8");
-           l = wxSetlocale(c, buf2.c_str());
+            l = wxSetlocale(c, buf2.c_str());
         }
     }
     return l;
@@ -1523,7 +1521,7 @@ bool wxLocale::Init(int language, int flags)
     // We failed to detect system language, so we will use English:
     if (lang == wxLANGUAGE_UNKNOWN)
     {
-       return FALSE;
+       return false;
     }
 
     const wxLanguageInfo *info = GetLanguageInfo(lang);
@@ -1532,7 +1530,7 @@ bool wxLocale::Init(int language, int flags)
     if (info == NULL)
     {
         wxLogError(wxT("Unknown language %i."), lang);
-        return FALSE;
+        return false;
     }
 
     wxString name = info->Description;
@@ -1580,7 +1578,7 @@ bool wxLocale::Init(int language, int flags)
     if ( !retloc )
     {
         wxLogError(wxT("Cannot set locale to '%s'."), locale.c_str());
-        return FALSE;
+        return false;
     }
 #elif defined(__WIN32__)
 
@@ -1633,11 +1631,11 @@ bool wxLocale::Init(int language, int flags)
                 if (codepage != 0)
                     locale << wxT(".") << buffer;
             }
-            if (locale.IsEmpty())
+            if (locale.empty())
             {
                 wxLogLastError(wxT("SetThreadLocale"));
                 wxLogError(wxT("Cannot set locale to language %s."), name.c_str());
-                return FALSE;
+                return false;
             }
             else
             {
@@ -1679,12 +1677,30 @@ bool wxLocale::Init(int language, int flags)
     if ( !retloc )
     {
         wxLogError(wxT("Cannot set locale to language %s."), name.c_str());
-        return FALSE;
+        return false;
     }
-#elif defined(__WXMAC__) || defined(__WXPM__)
+#elif defined(__WXMAC__)
+    if (lang == wxLANGUAGE_DEFAULT)
+        locale = wxEmptyString;
+    else
+        locale = info->CanonicalName;
+
+    wxMB2WXbuf retloc = wxSetlocale(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));
+    }
+    if ( !retloc )
+    {
+        wxLogError(wxT("Cannot set locale to '%s'."), locale.c_str());
+        return false;
+    }
+#elif defined(__WXPM__)
     wxMB2WXbuf retloc = wxSetlocale(LC_ALL , wxEmptyString);
 #else
-    return FALSE;
+    return false;
     #define WX_NO_LOCALE_SUPPORT
 #endif
 
@@ -2181,6 +2197,9 @@ wxString wxLocale::GetSystemEncodingName()
     // FIXME: what is the error return value for GetACP()?
     UINT codepage = ::GetACP();
     encname.Printf(_T("windows-%u"), codepage);
+#elif defined(__WXMAC__)
+    // default is just empty string, this resolves to the default system
+    // encoding later
 #elif defined(__UNIX_LIKE__)
 
 #if defined(HAVE_LANGINFO_H) && defined(CODESET)
@@ -2285,19 +2304,19 @@ wxFontEncoding wxLocale::GetSystemEncoding()
         return wxFONTENCODING_CP950;
     }
 #elif defined(__WXMAC__)
-       TextEncoding encoding = 0 ;
+    TextEncoding encoding = 0 ;
 #if TARGET_CARBON
-       encoding = CFStringGetSystemEncoding() ;
+    encoding = CFStringGetSystemEncoding() ;
 #else
-        UpgradeScriptInfoToTextEncoding ( smSystemScript , kTextLanguageDontCare , kTextRegionDontCare , NULL , &encoding ) ;
+    UpgradeScriptInfoToTextEncoding ( smSystemScript , kTextLanguageDontCare , kTextRegionDontCare , NULL , &encoding ) ;
 #endif
     return wxMacGetFontEncFromSystemEnc( encoding ) ;
 #elif defined(__UNIX_LIKE__) && wxUSE_FONTMAP
     wxString encname = GetSystemEncodingName();
     if ( !encname.empty() )
     {
-        wxFontEncoding enc = wxFontMapper::Get()->
-            CharsetToEncoding(encname, FALSE /* not interactive */);
+        wxFontEncoding enc = (wxFontMapperBase::Get())->
+            CharsetToEncoding(encname, false /* not interactive */);
 
         // on some modern Linux systems (RedHat 8) the default system locale
         // is UTF8 -- but it isn't supported by wxGTK in ANSI build at all so
@@ -2423,8 +2442,9 @@ wxLocale::~wxLocale()
         delete pTmpCat;
     }
 
-    // restore old locale
+    // restore old locale pointer
     wxSetLocale(m_pOldLocale);
+
     // FIXME
 #ifndef __WXWINCE__
     wxSetlocale(LC_ALL, m_pszOldLocale);
@@ -2519,14 +2539,14 @@ wxString wxLocale::GetHeaderValue( const wxChar* szHeader,
         if ( pMsgCat == NULL )
             return wxEmptyString;
 
-        pszTrans = pMsgCat->GetString(wxT(""), (size_t)-1);
+        pszTrans = pMsgCat->GetString(wxEmptyString, (size_t)-1);
     }
     else
     {
         // search in all domains
         for ( pMsgCat = m_pMsgCat; pMsgCat != NULL; pMsgCat = pMsgCat->m_pNext )
         {
-            pszTrans = pMsgCat->GetString(wxT(""), (size_t)-1);
+            pszTrans = pMsgCat->GetString(wxEmptyString, (size_t)-1);
             if ( pszTrans != NULL )   // take the first found
                 break;
         }
@@ -2538,11 +2558,11 @@ wxString wxLocale::GetHeaderValue( const wxChar* szHeader,
     wxChar const * pszFound = wxStrstr(pszTrans, szHeader);
     if ( pszFound == NULL )
       return wxEmptyString;
-    
+
     pszFound += wxStrlen(szHeader) + 2 /* ': ' */;
 
     // Every header is separated by \n
-    
+
     wxChar const * pszEndLine = wxStrchr(pszFound, wxT('\n'));
     if ( pszEndLine == NULL ) pszEndLine = pszFound + wxStrlen(pszFound);
 
@@ -2736,7 +2756,7 @@ class wxLocaleModule: public wxModule
     DECLARE_DYNAMIC_CLASS(wxLocaleModule)
     public:
         wxLocaleModule() {}
-        bool OnInit() { return TRUE; }
+        bool OnInit() { return true; }
         void OnExit() { wxLocale::DestroyLanguagesDB(); }
 };