]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/intl.cpp
Removed 'interface' pragma for gcc 2.96
[wxWidgets.git] / src / common / intl.cpp
index 71535962623f1a67fd3443b329abbfcd1cfc6031..272d7f3f633b1f6af3700cc96af4abe8c980712e 100644 (file)
@@ -40,6 +40,7 @@
 #include "wx/intl.h"
 #include "wx/file.h"
 #include "wx/log.h"
+#include "wx/debug.h"
 #include "wx/utils.h"
 
 #include <stdlib.h>
@@ -76,7 +77,11 @@ typedef unsigned char size_t8;
         public:
             IntSizeChecker()
             {
-                wxASSERT_MSG( sizeof(int) == 4,
+                // 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,
                               "size_t32 is incorrectly defined!" );
             }
         } intsizechecker;
@@ -92,23 +97,39 @@ const size_t32 MSGCATALOG_MAGIC    = 0x950412de;
 const size_t32 MSGCATALOG_MAGIC_SW = 0xde120495;
 
 // extension of ".mo" files
-#define MSGCATALOG_EXTENSION  ".mo"
+#define MSGCATALOG_EXTENSION  _T(".mo")
 
 // ----------------------------------------------------------------------------
 // global functions
 // ----------------------------------------------------------------------------
 
-// suppress further error messages about missing translations
-// (if you don't have one catalog file, you wouldn't like to see the
-//  error message for each string in it, so normally it's given only
-//  once)
-void wxSuppressTransErrors();
+#ifdef __WXDEBUG__
+
+// small class to suppress the translation erros until exit from current scope
+class NoTransErr
+{
+public:
+    NoTransErr() { ms_suppressCount++; }
+   ~NoTransErr() { ms_suppressCount--;  }
+
+   static bool Suppress() { return ms_suppressCount > 0; }
+
+private:
+   static size_t ms_suppressCount;
+};
 
-// restore the logging
-void wxRestoreTransErrors();
+size_t NoTransErr::ms_suppressCount = 0;
 
-// get the current state
-bool wxIsLoggingTransErrors();
+#else // !Debug
+
+class NoTransErr
+{
+public:
+    NoTransErr() { }
+   ~NoTransErr() { }
+};
+
+#endif // Debug/!Debug
 
 static wxLocale *wxSetLocale(wxLocale *pLocale);
 
@@ -127,7 +148,7 @@ public:
  ~wxMsgCatalog();
 
   // load the catalog from disk (szDirPrefix corresponds to language)
-  bool Load(const wxChar *szDirPrefix, const wxChar *szName);
+  bool Load(const wxChar *szDirPrefix, const wxChar *szName, bool bConvertEncoding = FALSE);
   bool IsLoaded() const { return m_pData != NULL; }
 
   // get name of the catalog
@@ -174,6 +195,9 @@ private:
   const char *StringAtOfs(wxMsgTableEntry *pTable, size_t32 index) const
     { return (const char *)(m_pData + Swap(pTable[index].ofsString)); }
 
+  // convert encoding to platform native one, if neccessary
+  void ConvertEncoding();
+
   // utility functions
     // calculate the hash value of given string
   static inline size_t32 GetHash(const char *sz);
@@ -245,14 +269,6 @@ wxMsgCatalog::~wxMsgCatalog()
   wxDELETEA(m_pszName);
 }
 
-// small class to suppress the translation erros until exit from current scope
-class NoTransErr
-{
-public:
-    NoTransErr() { wxSuppressTransErrors(); }
-   ~NoTransErr() { wxRestoreTransErrors();  }
-};
-
 // return all directories to search for given prefix
 static wxString GetAllMsgCatalogSubdirs(const wxChar *prefix,
                                         const wxChar *lang)
@@ -262,7 +278,7 @@ static wxString GetAllMsgCatalogSubdirs(const wxChar *prefix,
     // search first in prefix/fr/LC_MESSAGES, then in prefix/fr and finally in
     // prefix (assuming the language is 'fr')
     searchPath << prefix << wxFILE_SEP_PATH << lang << wxFILE_SEP_PATH
-                         << _T("LC_MESSAGES") << wxPATH_SEP
+                         << wxT("LC_MESSAGES") << wxPATH_SEP
                << prefix << wxFILE_SEP_PATH << lang << wxPATH_SEP
                << prefix << wxPATH_SEP;
 
@@ -282,31 +298,38 @@ static wxString GetFullSearchPath(const wxChar *lang)
                    << wxPATH_SEP;
     }
 
+    // LC_PATH is a standard env var containing the search path for the .mo
+    // files
+    const wxChar *pszLcPath = wxGetenv(wxT("LC_PATH"));
+    if ( pszLcPath != NULL )
+        searchPath << GetAllMsgCatalogSubdirs(pszLcPath, lang);
+
     // then take the current directory
     // FIXME it should be the directory of the executable
-    searchPath << GetAllMsgCatalogSubdirs(_T("."), lang) << wxPATH_SEP;
+    searchPath << GetAllMsgCatalogSubdirs(wxT("."), lang);
 
     // and finally add some standard ones
     searchPath
-        << GetAllMsgCatalogSubdirs(_T("/usr/share/locale"), lang) << wxPATH_SEP
-        << GetAllMsgCatalogSubdirs(_T("/usr/lib/locale"), lang) << wxPATH_SEP
-        << GetAllMsgCatalogSubdirs(_T("/usr/local/share/locale"), lang);
+        << GetAllMsgCatalogSubdirs(wxT("/usr/share/locale"), lang)
+        << GetAllMsgCatalogSubdirs(wxT("/usr/lib/locale"), lang)
+        << GetAllMsgCatalogSubdirs(wxT("/usr/local/share/locale"), lang);
 
     return searchPath;
 }
 
 // open disk file and read in it's contents
-bool wxMsgCatalog::Load(const wxChar *szDirPrefix, const wxChar *szName)
+bool wxMsgCatalog::Load(const wxChar *szDirPrefix, const wxChar *szName0, bool bConvertEncoding)
 {
-  // FIXME VZ: I forgot the exact meaning of LC_PATH - anyone to remind me?
-#if 0
-  const wxChar *pszLcPath = wxGetenv("LC_PATH");
-  if ( pszLcPath != NULL )
-      strPath += pszLcPath + wxString(szDirPrefix) + MSG_PATH;
-#endif // 0
+   /* 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('.')));
 
   wxString searchPath = GetFullSearchPath(szDirPrefix);
-  const wxChar *sublocale = wxStrchr(szDirPrefix, _T('_'));
+  const wxChar *sublocale = wxStrchr(szDirPrefix, wxT('_'));
   if ( sublocale )
   {
       // also add just base locale name: for things like "fr_BE" (belgium
@@ -324,20 +347,20 @@ bool wxMsgCatalog::Load(const wxChar *szDirPrefix, const wxChar *szName)
   // not yet be loaded (and it's normal)
   //
   // (we're using an object because we have several return paths)
-  NoTransErr noTransErr;
 
+  NoTransErr noTransErr;
   wxLogVerbose(_("looking for catalog '%s' in path '%s'."),
-               szName, searchPath.c_str());
+               szName.c_str(), searchPath.c_str());
 
   wxString strFullName;
   if ( !wxFindFileInPath(&strFullName, searchPath, strFile) ) {
-    wxLogWarning(_("catalog file for domain '%s' not found."), szName);
+    wxLogWarning(_("catalog file for domain '%s' not found."), szName.c_str());
     return FALSE;
   }
 
   // open file
   wxLogVerbose(_("using catalog '%s' from '%s'."),
-             szName, strFullName.c_str());
+             szName.c_str(), strFullName.c_str());
 
   wxFile fileMsg(strFullName);
   if ( !fileMsg.IsOpened() )
@@ -388,6 +411,9 @@ bool wxMsgCatalog::Load(const wxChar *szDirPrefix, const wxChar *szName)
   m_pszName = new wxChar[wxStrlen(szName) + 1];
   wxStrcpy(m_pszName, szName);
 
+  if (bConvertEncoding)
+      ConvertEncoding();
+
   // everything is fine
   return TRUE;
 }
@@ -404,7 +430,13 @@ const char *wxMsgCatalog::GetString(const char *szOrig) const
 
     size_t32 nIncr = 1 + (nHashVal % (m_nHashSize - 2));
 
-    while ( TRUE ) {
+#if defined(__VISAGECPP__)
+// VA just can't stand while(1) or while(TRUE)
+    bool bOs2var = TRUE;
+    while(bOs2var) {
+#else
+    while (1) {
+#endif
       size_t32 nStr = Swap(m_pHashTable[nIndex]);
       if ( nStr == 0 )
         return NULL;
@@ -438,6 +470,53 @@ const char *wxMsgCatalog::GetString(const char *szOrig) const
   return NULL;
 }
 
+
+#if wxUSE_GUI
+#include "wx/fontmap.h"
+#include "wx/encconv.h"
+#endif
+
+void wxMsgCatalog::ConvertEncoding()
+{
+#if wxUSE_GUI
+    wxFontEncoding enc;
+
+    // first, find encoding header:
+    const char *hdr = StringAtOfs(m_pOrigTable, 0);
+    if (hdr == NULL) return; // not supported by this catalog, does not have non-fuzzy header
+    if (hdr[0] != 0) return; // ditto
+
+    /* we support catalogs with header (msgid "") that is _not_ marked as "#, fuzzy" (otherwise
+       the string would not be included into compiled catalog) */
+    wxString header(StringAtOfs(m_pTransTable, 0));
+    wxString charset;
+    int pos = header.Find(wxT("Content-Type: text/plain; charset="));
+    if (pos == wxNOT_FOUND)
+        return; // incorrectly filled Content-Type header
+    size_t n = pos + 34; /*strlen("Content-Type: text/plain; charset=")*/
+    while (header[n] != wxT('\n'))
+        charset << header[n++];
+
+    enc = wxTheFontMapper->CharsetToEncoding(charset, FALSE);
+    if ( enc == wxFONTENCODING_SYSTEM )
+        return; // unknown encoding
+
+    wxFontEncodingArray a = wxEncodingConverter::GetPlatformEquivalents(enc);
+    if (a[0] == enc)
+        return; // no conversion needed, locale uses native encoding
+
+    if (a.GetCount() == 0)
+        return; // we don't know common equiv. under this platform
+
+    wxEncodingConverter converter;
+
+    converter.Init(enc, a[0]);
+    for (size_t i = 0; i < m_numStrings; i++)
+        converter.Convert((char*)StringAtOfs(m_pTransTable, i));
+#endif
+}
+
+
 // ----------------------------------------------------------------------------
 // wxLocale
 // ----------------------------------------------------------------------------
@@ -452,14 +531,19 @@ wxLocale::wxLocale()
 bool wxLocale::Init(const wxChar *szName,
                     const wxChar *szShort,
                     const wxChar *szLocale,
-                    bool        bLoadDefault)
+                    bool        bLoadDefault,
+                    bool        bConvertEncoding)
 {
   m_strLocale = szName;
   m_strShort = szShort;
+  m_bConvertEncoding = bConvertEncoding;
 
   // change current locale (default: same as long name)
   if ( szLocale == NULL )
-    szLocale = szName;
+  {
+    // the argument to setlocale()
+    szLocale = szShort;
+  }
   m_pszOldLocale = wxSetlocale(LC_ALL, szLocale);
   if ( m_pszOldLocale == NULL )
     wxLogError(_("locale '%s' can not be set."), szLocale);
@@ -479,7 +563,7 @@ bool wxLocale::Init(const wxChar *szName,
   m_pMsgCat = NULL;
   bool bOk = TRUE;
   if ( bLoadDefault )
-    bOk = AddCatalog(_T("wxstd"));
+    bOk = AddCatalog(wxT("wxstd"));
 
   return bOk;
 }
@@ -511,13 +595,17 @@ wxLocale::~wxLocale()
 
 // get the translation of given string in current locale
 const wxMB2WXbuf wxLocale::GetString(const wxChar *szOrigString,
-                                    const wxChar *szDomain) const
+                                     const wxChar *szDomain) const
 {
   if ( wxIsEmpty(szOrigString) )
       return szDomain;
 
   const char *pszTrans = NULL;
-  const wxWX2MBbuf szOrgString = wxConv_libc.cWX2MB(szOrigString);
+#if wxUSE_UNICODE
+  const wxWX2MBbuf szOrgString = wxConvCurrent->cWX2MB(szOrigString);
+#else // ANSI
+  #define szOrgString szOrigString
+#endif // Unicode/ANSI
 
   wxMsgCatalog *pMsgCat;
   if ( szDomain != NULL ) {
@@ -537,34 +625,32 @@ const wxMB2WXbuf wxLocale::GetString(const wxChar *szOrigString,
   }
 
   if ( pszTrans == NULL ) {
-    if ( wxIsLoggingTransErrors() ) {
-      // suppress further error messages if we're not debugging: this avoids
-      // flooding the user with messages about each and every missing string if,
-      // for example, a whole catalog file is missing.
-
-      // do it before calling LogWarning to prevent infinite recursion!
 #ifdef __WXDEBUG__
+    if ( !NoTransErr::Suppress() ) {
       NoTransErr noTransErr;
-#else // !debug
-      wxSuppressTransErrors();
-#endif // debug/!debug
 
       if ( szDomain != NULL )
       {
-        wxLogWarning(_("string '%s' not found in domain '%s' for locale '%s'."),
+        wxLogDebug(_T("string '%s' not found in domain '%s' for locale '%s'."),
                      szOrigString, szDomain, m_strLocale.c_str());
       }
       else
       {
-        wxLogWarning(_("string '%s' not found in locale '%s'."),
-                     szOrigString, m_strLocale.c_str());
+        wxLogDebug(_T("string '%s' not found in locale '%s'."),
+                   szOrigString, m_strLocale.c_str());
       }
     }
+#endif // __WXDEBUG__
 
     return (wxMB2WXbuf)(szOrigString);
   }
   else
-    return (wxMB2WXbuf)(wxConv_libc.cMB2WX(pszTrans));
+  {
+    return wxConvertMB2WX(pszTrans); // or preferably wxCSConv(charset).cMB2WX(pszTrans) or something,
+                                     // a macro similar to wxConvertMB2WX could be written for that
+  }
+
+  #undef szOrgString
 }
 
 // find catalog by name in a linked list, return NULL if !found
@@ -591,7 +677,7 @@ bool wxLocale::AddCatalog(const wxChar *szDomain)
 {
   wxMsgCatalog *pMsgCat = new wxMsgCatalog;
 
-  if ( pMsgCat->Load(m_strShort, szDomain) ) {
+  if ( pMsgCat->Load(m_strShort, szDomain, m_bConvertEncoding) ) {
     // add it to the head of the list so that in GetString it will
     // be searched before the catalogs added earlier
     pMsgCat->m_pNext = m_pMsgCat;
@@ -611,26 +697,6 @@ bool wxLocale::AddCatalog(const wxChar *szDomain)
 // global functions and variables
 // ----------------------------------------------------------------------------
 
-// translation errors logging
-// --------------------------
-
-static bool gs_bGiveTransErrors = TRUE;
-
-void wxSuppressTransErrors()
-{
-  gs_bGiveTransErrors = FALSE;
-}
-
-void wxRestoreTransErrors()
-{
-  gs_bGiveTransErrors = TRUE;
-}
-
-bool wxIsLoggingTransErrors()
-{
-  return gs_bGiveTransErrors;
-}
-
 // retrieve/change current locale
 // ------------------------------