diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-02-24 02:13:59 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-02-24 02:13:59 +0000 |
commit | a6d58bb6052ac8cb01805a48c4ad2f129126116f (patch) | |
tree | dd867a099fcbb263a8009a9fb22695b87855dad6 /src/kvilib/system/kvi_locale.cpp | |
download | kvirc-a6d58bb6052ac8cb01805a48c4ad2f129126116f.tar.gz kvirc-a6d58bb6052ac8cb01805a48c4ad2f129126116f.zip |
Added KDE3 version of kvirc
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/kvirc@1095341 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src/kvilib/system/kvi_locale.cpp')
-rw-r--r-- | src/kvilib/system/kvi_locale.cpp | 1191 |
1 files changed, 1191 insertions, 0 deletions
diff --git a/src/kvilib/system/kvi_locale.cpp b/src/kvilib/system/kvi_locale.cpp new file mode 100644 index 00000000..f49eabe4 --- /dev/null +++ b/src/kvilib/system/kvi_locale.cpp @@ -0,0 +1,1191 @@ +//============================================================================= +// +// File : kvi_locale.cpp +// Creation date : Fri Mar 19 1999 19:08:41 by Szymon Stefanek +// +// This file is part of the KVirc irc client distribution +// Copyright (C) 1999-2002 Szymon Stefanek (pragma at kvirc dot net) +// +// This program 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 (at your opinion) any later version. +// +// This program is distributed in the HOPE that it will be USEFUL, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the 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. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +//============================================================================= + +#define __KVILIB__ + + +//#define _KVI_DEBUG_CHECK_RANGE_ +#include "kvi_debug.h" +#include "kvi_malloc.h" +#include "kvi_bswap.h" + +#define _KVI_LOCALE_CPP_ +#include "kvi_locale.h" + +#include <qglobal.h> //for debug() +#include <qtextcodec.h> +#include <qdir.h> + +#ifdef COMPILE_USE_QT4 + #include <qlocale.h> +#endif + +#include "kvi_string.h" +#include "kvi_qcstring.h" +#include "kvi_env.h" +#include "kvi_fileutils.h" +#include "kvi_file.h" + + +KVILIB_API KviMessageCatalogue * g_pMainCatalogue = 0; + +static KviStr g_szLang; +static KviTranslator * g_pTranslator = 0; +static KviPointerHashTable<const char *,KviMessageCatalogue> * g_pCatalogueDict = 0; +static QTextCodec * g_pUtf8TextCodec = 0; + + +///////////////////////////////////////////////////////////////////////////////////////////////////// +// +// The following code was extracted and adapted from gutf8.c +// from the GNU GLIB2 package. +// +// gutf8.c - Operations on UTF-8 strings. +// +// Copyright (C) 1999 Tom Tromey +// Copyright (C) 2000 Red Hat, Inc. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the +// Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301, USA. +// +///////////////////////////////////////////////////////////////////////////////////////////////////// + +typedef char gchar; +typedef unsigned char guchar; +typedef signed int gssize; +typedef unsigned int gunichar; + + + +#define UNICODE_VALID(Char) \ + ((Char) < 0x110000 && \ + (((Char) & 0xFFFFF800) != 0xD800) && \ + ((Char) < 0xFDD0 || (Char) > 0xFDEF) && \ + ((Char) & 0xFFFE) != 0xFFFE) + +#define CONTINUATION_CHAR \ + if ((*(guchar *)p & 0xc0) != 0x80) /* 10xxxxxx */ \ + goto error; \ + val <<= 6; \ + val |= (*(guchar *)p) & 0x3f; + + +static const char * +fast_validate (const char *str) + +{ + gunichar val = 0; + gunichar min = 0; + const gchar *p; + + for (p = str; *p; p++) + { + if (*(guchar *)p < 128) + /* done */; + else + { + const gchar *last; + + last = p; + if ((*(guchar *)p & 0xe0) == 0xc0) /* 110xxxxx */ + { + if ((*(guchar *)p & 0x1e) == 0) + goto error; + p++; + if ((*(guchar *)p & 0xc0) != 0x80) /* 10xxxxxx */ + goto error; + } + else + { + if ((*(guchar *)p & 0xf0) == 0xe0) /* 1110xxxx */ + { + min = (1 << 11); + val = *(guchar *)p & 0x0f; + goto TWO_REMAINING; + } + else if ((*(guchar *)p & 0xf8) == 0xf0) /* 11110xxx */ + { + min = (1 << 16); + val = *(guchar *)p & 0x07; + } + else + goto error; + + p++; + CONTINUATION_CHAR; + TWO_REMAINING: + p++; + CONTINUATION_CHAR; + p++; + CONTINUATION_CHAR; + + if (val < min) + goto error; + + if (!UNICODE_VALID(val)) + goto error; + } + + continue; + + error: + return last; + } + } + + return p; +} + +static const gchar * +fast_validate_len (const char *str, + gssize max_len) + +{ + gunichar val = 0; + gunichar min = 0; + const gchar *p; + + for (p = str; (max_len < 0 || (p - str) < max_len) && *p; p++) + { + if (*(guchar *)p < 128) + /* done */; + else + { + const gchar *last; + + last = p; + if ((*(guchar *)p & 0xe0) == 0xc0) /* 110xxxxx */ + { + if (max_len >= 0 && max_len - (p - str) < 2) + goto error; + + if ((*(guchar *)p & 0x1e) == 0) + goto error; + p++; + if ((*(guchar *)p & 0xc0) != 0x80) /* 10xxxxxx */ + goto error; + } + else + { + if ((*(guchar *)p & 0xf0) == 0xe0) /* 1110xxxx */ + { + if (max_len >= 0 && max_len - (p - str) < 3) + goto error; + + min = (1 << 11); + val = *(guchar *)p & 0x0f; + goto TWO_REMAINING; + } + else if ((*(guchar *)p & 0xf8) == 0xf0) /* 11110xxx */ + { + if (max_len >= 0 && max_len - (p - str) < 4) + goto error; + + min = (1 << 16); + val = *(guchar *)p & 0x07; + } + else + goto error; + + p++; + CONTINUATION_CHAR; + TWO_REMAINING: + p++; + CONTINUATION_CHAR; + p++; + CONTINUATION_CHAR; + + if (val < min) + goto error; + if (!UNICODE_VALID(val)) + goto error; + } + + continue; + + error: + return last; + } + } + + return p; +} + +static bool g_utf8_validate (const char *str, + gssize max_len, + const gchar **end) + +{ + const gchar *p; + + if (max_len < 0) + p = fast_validate (str); + else + p = fast_validate_len (str, max_len); + + if (end) + *end = p; + + if ((max_len >= 0 && p != str + max_len) || + (max_len < 0 && *p != '\0')) + return false; + else + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////// +// End of gutf8.c +/////////////////////////////////////////////////////////////////////////////////////////////// + + +class KviSmartTextCodec : public QTextCodec +{ +protected: + KviQCString m_szName; + QTextCodec * m_pRecvCodec; + QTextCodec * m_pSendCodec; +public: + KviSmartTextCodec(const char * szName,const char * szChildCodecName,bool bSendInUtf8) + : QTextCodec() + { + m_szName = szName; + if(!g_pUtf8TextCodec) + { + g_pUtf8TextCodec = QTextCodec::codecForName("UTF-8"); + if(!g_pUtf8TextCodec) + { + debug("Can't find the global utf8 text codec!"); + g_pUtf8TextCodec = QTextCodec::codecForLocale(); // try anything else... + } + } + m_pRecvCodec = QTextCodec::codecForName(szChildCodecName); + if(!m_pRecvCodec) + { + debug("Can't find the codec for name %s (composite codec creation)",szName); + m_pRecvCodec = g_pUtf8TextCodec; + } + if(bSendInUtf8) + m_pSendCodec = g_pUtf8TextCodec; + else + m_pSendCodec = m_pRecvCodec; + } +public: + bool ok(){ return m_pRecvCodec && g_pUtf8TextCodec; }; + + virtual int mibEnum () const { return 0; }; + +#ifdef COMPILE_USE_QT4 + virtual QByteArray name() const { return m_szName; }; +protected: + virtual QByteArray convertFromUnicode(const QChar * input,int number,ConverterState * state) const + { + return m_pSendCodec->fromUnicode(input,number,state); + } + virtual QString convertToUnicode(const char * chars,int len,ConverterState * state) const + { + if(g_utf8_validate(chars,len,NULL))return g_pUtf8TextCodec->toUnicode(chars,len,state); + return m_pRecvCodec->toUnicode(chars,len,state); + } +#else +public: + virtual const char * mimeName () const { return m_pRecvCodec->mimeName(); }; + virtual const char * name () const { return m_szName.data(); }; + virtual QTextDecoder * makeDecoder () const { return m_pRecvCodec->makeDecoder(); }; + virtual QTextEncoder * makeEncoder () const { return m_pSendCodec->makeEncoder(); }; + QCString fromUnicode (const QString & uc) const { return m_pSendCodec->fromUnicode(uc); }; + virtual QCString fromUnicode (const QString & uc,int & lenInOut) const { return m_pSendCodec->fromUnicode(uc,lenInOut); }; + QString toUnicode(const char * chars) const + { + if(g_utf8_validate(chars,-1,NULL))return g_pUtf8TextCodec->toUnicode(chars); + return m_pRecvCodec->toUnicode(chars); + }; + virtual QString toUnicode(const char * chars,int len) const + { + if(g_utf8_validate(chars,len,NULL))return g_pUtf8TextCodec->toUnicode(chars,len); + return m_pRecvCodec->toUnicode(chars,len); + }; + QString toUnicode(const QByteArray & a,int len) const + { + if(g_utf8_validate(a.data(),len,NULL))return g_pUtf8TextCodec->toUnicode(a,len); + return m_pRecvCodec->toUnicode(a,len); + }; + QString toUnicode(const QByteArray & a) const + { + if(g_utf8_validate(a.data(),a.size(),NULL))return g_pUtf8TextCodec->toUnicode(a); + return m_pRecvCodec->toUnicode(a); + }; + QString toUnicode(const QCString & a,int len) const + { + if(g_utf8_validate(a.data(),len,NULL))return g_pUtf8TextCodec->toUnicode(a,len); + return m_pRecvCodec->toUnicode(a,len); + }; + QString toUnicode(const QCString & a) const + { + if(g_utf8_validate(a.data(),-1,NULL))return g_pUtf8TextCodec->toUnicode(a); + return m_pRecvCodec->toUnicode(a); + }; + + virtual bool canEncode(QChar ch) const { return m_pSendCodec->canEncode(ch); }; + virtual bool canEncode(const QString &s) const { return m_pSendCodec->canEncode(s); }; + virtual int heuristicContentMatch(const char * chars,int len) const + { + int iii = g_pUtf8TextCodec->heuristicContentMatch(chars,len); + if(iii < 0)return m_pRecvCodec->heuristicContentMatch(chars,len); + return iii; + } + virtual int heuristicNameMatch(const char * hint) const { return 0; }; +#endif +}; + +static KviPointerHashTable<const char *,KviSmartTextCodec> * g_pSmartCodecDict = 0; + + + +///////////////////////////////////////////////////////////////////////////////////////////////////// +// +// The following code was extracted and adapted from gettext.h and gettextP.h +// from the GNU gettext package. +// +// Internal header for GNU gettext internationalization functions. +// Copyright (C) 1995, 1997 Free Software Foundation, Inc. +// +// This program 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, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with the GNU C Library; see the file COPYING.LIB. If not, +// write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301, USA. +// +///////////////////////////////////////////////////////////////////////////////////////////////////// + +#include <stdio.h> + +#if HAVE_LIMITS_H || _LIBC + #include <limits.h> +#endif + +// The magic number of the GNU message catalog format. +#define KVI_LOCALE_MAGIC 0x950412de +#define KVI_LOCALE_MAGIC_SWAPPED 0xde120495 + +// Revision number of the currently used .mo (binary) file format. +#define MO_REVISION_NUMBER 0 + + +// Header for binary .mo file format. +struct GnuMoFileHeader +{ + // The magic number. + kvi_u32_t magic; + // The revision number of the file format. + kvi_u32_t revision; + // The number of strings pairs. + kvi_u32_t nstrings; + // Offset of table with start offsets of original strings. + kvi_u32_t orig_tab_offset; + // Offset of table with start offsets of translation strings. + kvi_u32_t trans_tab_offset; + // Size of hashing table. + kvi_u32_t hash_tab_size; + // Offset of first hashing entry. + kvi_u32_t hash_tab_offset; +}; + +struct GnuMoStringDescriptor +{ + // Length of addressed string. + kvi_u32_t length; + // Offset of string in file. + kvi_u32_t offset; +}; + +#define KVI_SWAP_IF_NEEDED(flag,value) (flag ? kvi_swap32(value) : (value)) + +/////////////////////////////////////////////////////////////////////////////////////////////// +// End of gettext.h & gettextP.h +/////////////////////////////////////////////////////////////////////////////////////////////// + + +// HELPERS + +static int somePrimeNumbers[90]= +{ + 257 , 521 , 769 , 1031, 1087, 1091, 1103, 1117, 1123, 1151, // Incomplete *.mo files + 1163, 1171, 1181, 1193, 1201, 1213, 1217, 1223, 1229, 1231, // Complete *.mo files + 1237, 1249, 1259, 1277, 1283, 1289, 1291, 1297, 1307, 1319, + 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1433, + 1447, 1459, 1471, 1481, 1493, 1511, 1523, 1531, 1543, 1553, + 1567, 1571, 1583, 1597, 1609, 1619, 1627, 1637, 1657, 1667, // Too big for KVIrc *.mo files + 1693, 1709, 1721, 1733, 1741, 1753, 1777, 1789, 1811, 1831, + 1907, 2069, 2111, 2221, 2309, 2441, 2531, 2617, 2731, 2837, + 2903, 3121, 3329, 3331, 3767, 4127, 5051, 6089, 7039, 9973 +}; + +int kvi_getFirstBiggerPrime(int number) +{ + for(int i=0;i<90;i++){ + if(somePrimeNumbers[i] >= number)return somePrimeNumbers[i]; + } + return 9973; //error! +} + + +KviMessageCatalogue::KviMessageCatalogue() +{ + //m_uEncoding = 0; + m_pTextCodec = QTextCodec::codecForLocale(); + + //m_pMessages = new KviPointerHashTable<const char *,KviTranslationEntry>(1123,true,false); // dictSize, case sensitive , don't copy keys + m_pMessages = new KviPointerHashTable<const char *,KviTranslationEntry>(32,true,false); // dictSize, case sensitive , don't copy keys + m_pMessages->setAutoDelete(true); +} + +KviMessageCatalogue::~KviMessageCatalogue() +{ + if(m_pMessages) + delete m_pMessages; +} + +bool KviMessageCatalogue::load(const QString& name) +{ + QString szCatalogueFile(name); + + // Try to load the header + KviFile f(szCatalogueFile); + if(!f.openForReading()) + { + debug("[KviLocale]: Failed to open the messages file %s: probably doesn't exist",KviQString::toUtf8(szCatalogueFile).data()); + return false; + } + + GnuMoFileHeader hdr; + + if(f.readBlock((char *)&hdr,sizeof(GnuMoFileHeader)) < (int)sizeof(GnuMoFileHeader)) + { + debug("KviLocale: Failed to read header of %s",KviQString::toUtf8(szCatalogueFile).data()); + f.close(); + return false; + } + + bool bMustSwap = false; + + if(hdr.magic != KVI_LOCALE_MAGIC) + { + if(hdr.magic == KVI_LOCALE_MAGIC_SWAPPED) + { + debug("KviLocale: Swapped magic for file %s: swapping data too",KviQString::toUtf8(szCatalogueFile).data()); + bMustSwap = true; + } else { + debug("KviLocale: Bad locale magic for file %s: not a *.mo file ?",KviQString::toUtf8(szCatalogueFile).data()); + f.close(); + return false; + } + } + + if(KVI_SWAP_IF_NEEDED(bMustSwap,hdr.revision) != MO_REVISION_NUMBER) + { + debug("KviLocale: Invalid *.mo file revision number for file %s",KviQString::toUtf8(szCatalogueFile).data()); + f.close(); + return false; + } + + int numberOfStrings = KVI_SWAP_IF_NEEDED(bMustSwap,hdr.nstrings); + + if(numberOfStrings <= 0) + { + debug("KviLocale: No translated messages found in file %s",KviQString::toUtf8(szCatalogueFile).data()); + f.close(); + return false; + } + + if(numberOfStrings >= 9972) + { + debug("Number of strings too big...sure that it is a KVIrc catalog file ?"); + numberOfStrings = 9972; + } + + // return back + f.seek(0); + + unsigned int fSize = f.size(); + char * buffer = (char *)kvi_malloc(fSize); + + // FIXME: maybe read it in blocks eh ? + if(f.readBlock(buffer,fSize) < (int)fSize) + { + debug("KviLocale: Error while reading the translation file %s",KviQString::toUtf8(szCatalogueFile).data()); + kvi_free(buffer); + f.close(); + return false; + } + + // Check for broken *.mo files + if(fSize < (24 + (sizeof(GnuMoStringDescriptor) * numberOfStrings))) + { + debug("KviLocale: Broken translation file %s (too small for all descriptors)",KviQString::toUtf8(szCatalogueFile).data()); + kvi_free(buffer); + f.close(); + return false; + } + + GnuMoStringDescriptor * origDescriptor = (GnuMoStringDescriptor *)(buffer + KVI_SWAP_IF_NEEDED(bMustSwap,hdr.orig_tab_offset)); + GnuMoStringDescriptor * transDescriptor = (GnuMoStringDescriptor *)(buffer + KVI_SWAP_IF_NEEDED(bMustSwap,hdr.trans_tab_offset)); + + // Check again for broken *.mo files + int expectedFileSize = KVI_SWAP_IF_NEEDED(bMustSwap,transDescriptor[numberOfStrings - 1].offset) + + KVI_SWAP_IF_NEEDED(bMustSwap,transDescriptor[numberOfStrings - 1].length); + + if(fSize < (unsigned int)expectedFileSize) + { + debug("KviLocale: Broken translation file %s (too small for all the message strings)",KviQString::toUtf8(szCatalogueFile).data()); + kvi_free(buffer); + f.close(); + return false; + } + + // Ok...we can run now + + int dictSize = kvi_getFirstBiggerPrime(numberOfStrings); + if(m_pMessages) + delete m_pMessages; + m_pMessages = new KviPointerHashTable<const char *,KviTranslationEntry>(dictSize,true,false); // dictSize, case sensitive , don't copy keys + m_pMessages->setAutoDelete(true); + + KviStr szHeader; + + for(int i=0;i < numberOfStrings;i++) + { + // FIXME: "Check for NULL inside strings here ?" + //debug("original seems to be at %u and %u byttes long",KVI_SWAP_IF_NEEDED(bMustSwap,origDescriptor[i].offset), + // KVI_SWAP_IF_NEEDED(bMustSwap,origDescriptor[i].length)); + //debug("translated seems to be at %u and %u byttes long",KVI_SWAP_IF_NEEDED(bMustSwap,transDescriptor[i].offset), + // KVI_SWAP_IF_NEEDED(bMustSwap,transDescriptor[i].length)); + + KviTranslationEntry * e = new KviTranslationEntry( + (char *)(buffer + KVI_SWAP_IF_NEEDED(bMustSwap,origDescriptor[i].offset)), + KVI_SWAP_IF_NEEDED(bMustSwap,origDescriptor[i].length), + (char *)(buffer + KVI_SWAP_IF_NEEDED(bMustSwap,transDescriptor[i].offset)), + KVI_SWAP_IF_NEEDED(bMustSwap,transDescriptor[i].length)); + + // In some (or all?) *.mo files the first string + // is zero bytes long and the translated one contains + // informations about the translation + if(e->m_szKey.len() == 0) + { + szHeader = e->m_szEncodedTranslation; + delete e; + continue; + } + + m_pMessages->insert(e->m_szKey.ptr(),e); + } + + kvi_free(buffer); + f.close(); + + m_pTextCodec = 0; + + // find out the text encoding , if possible + if(szHeader.hasData()) + { + // find "charset=*\n" + int idx = szHeader.findFirstIdx("charset="); + if(idx != -1) + { + szHeader.cutLeft(idx + 8); + szHeader.cutFromFirst('\n'); + szHeader.stripWhiteSpace(); + m_pTextCodec = KviLocale::codecForName(szHeader.ptr()); + if(!m_pTextCodec) + { + debug("Can't find the codec for charset=%s",szHeader.ptr()); + debug("Falling back to codecForLocale()"); + m_pTextCodec = QTextCodec::codecForLocale(); + } + } + } + + if(!m_pTextCodec) + { + debug("The message catalogue does not have a \"charset\" header"); + debug("Assuming utf8"); // FIXME: or codecForLocale() ? + m_pTextCodec = QTextCodec::codecForName("UTF-8"); + } + + return true; +} + +const char * KviMessageCatalogue::translate(const char *text) +{ + KviTranslationEntry * aux = m_pMessages->find(text); + if(aux)return aux->m_szEncodedTranslation.ptr(); + return text; +} + +const QString & KviMessageCatalogue::translateToQString(const char *text) +{ + KviTranslationEntry * aux = m_pMessages->find(text); + if(aux) + { + if(aux->m_pQTranslation)return *(aux->m_pQTranslation); + aux->m_pQTranslation = new QString(m_pTextCodec->toUnicode(aux->m_szEncodedTranslation.ptr())); + return *(aux->m_pQTranslation); + } + // no translation is available: let's avoid continous string decoding + aux = new KviTranslationEntry(text); + m_pMessages->insert(aux->m_szKey.ptr(),aux); + aux->m_pQTranslation = new QString(m_pTextCodec->toUnicode(aux->m_szEncodedTranslation.ptr())); + return *(aux->m_pQTranslation); +} + + + + +namespace KviLocale +{ +#ifndef QT_NO_BIG_CODECS + #define NUM_ENCODINGS 109 +#else + #define NUM_ENCODINGS 85 +#endif + + + + static EncodingDescription supported_encodings[]= + { + { "UTF-8" , 0 , 0 , "8-bit Unicode" }, + { "ISO-8859-1" , 0 , 0 , "Western, Latin-1" }, + { "ISO-8859-2" , 0 , 0 , "Central European 1" }, + { "ISO-8859-3" , 0 , 0 , "Central European 2" }, + { "ISO-8859-4" , 0 , 0 , "Baltic, Standard" }, + { "ISO-8859-5" , 0 , 0 , "Cyrillic, ISO" }, + { "ISO-8859-6" , 0 , 0 , "Arabic, Standard" }, + { "ISO-8859-7" , 0 , 0 , "Greek" }, + { "ISO-8859-8" , 0 , 0 , "Hebrew, visually ordered" }, + { "ISO-8859-8-i" , 0 , 0 , "Hebrew, logically ordered" }, + { "ISO-8859-9" , 0 , 0 , "Turkish, Latin-5" }, + { "ISO-8859-15" , 0 , 0 , "Western, Latin-1 + Euro" }, + { "KOI8-R" , 0 , 0 , "Cyrillic, KOI" }, + { "KOI8-U" , 0 , 0 , "Ukrainian" }, + { "CP-1250" , 0 , 0 , "Central European 3" }, + { "CP-1251" , 0 , 0 , "Cyrillic, Windows" }, + { "CP-1252" , 0 , 0 , "Western, CP" }, + { "CP-1253" , 0 , 0 , "Greek, CP" }, + { "CP-1256" , 0 , 0 , "Arabic, CP" }, + { "CP-1257" , 0 , 0 , "Baltic, CP" }, + { "CP-1255" , 0 , 0 , "Hebrew, CP" }, + { "CP-1254" , 0 , 0 , "Turkish, CP" }, + { "TIS-620" , 0 , 0 , "Thai" }, +#ifndef QT_NO_BIG_CODECS + { "Big5" , 0 , 0 , "Chinese Traditional" }, + { "Big5-HKSCS" , 0 , 0 , "Chinese Traditional, Hong Kong" }, + { "GB18030" , 0 , 0 , "Chinese Simplified" }, + { "JIS7" , 0 , 0 , "Japanese (JIS7)" }, + { "Shift-JIS" , 0 , 0 , "Japanese (Shift-JIS)" }, + { "EUC-JP" , 0 , 0 , "Japanese (EUC-JP)" }, + { "EUC-KR" , 0 , 0 , "Korean" }, + { "TSCII" , 0 , 0 , "Tamil" }, +#endif + { "ISO-8859-10" , 0 , 0 , "ISO-8859-10" }, + { "ISO-8859-13" , 0 , 0 , "ISO-8859-13" }, + { "ISO-8859-14" , 0 , 0 , "ISO-8859-14" }, + { "IBM-850" , 0 , 0 , "IBM-850" }, + { "IBM-866" , 0 , 0 , "IBM-866" }, + { "CP874" , 0 , 0 , "CP874" }, + + // smart codecs that send in the local charset + { "ISO-8859-1 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Western Latin-1, O: Western Latin-1" }, + { "ISO-8859-2 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Central European 1, O: Central European 1" }, + { "ISO-8859-3 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Central European 2, O: Central European 2" }, + { "ISO-8859-4 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Baltic, Standard, O: Baltic, Standard" }, + { "ISO-8859-5 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Cyrillic, ISO, O: Cyrillic, ISO" }, + { "ISO-8859-6 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Arabic, Standard, O: Arabic, Standard" }, + { "ISO-8859-7 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Greek, O: Greek" }, + { "ISO-8859-8 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Hebrew, visually ordered, O: Hebrew, visually ordered" }, + { "ISO-8859-8-i [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Hebrew, logically ordered, O: Hebrew, logically ordered" }, + { "ISO-8859-9 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Turkish, Latin-5, O: Turkish, Latin-5" }, + { "ISO-8859-15 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Western, Latin-1 + Euro, O: Western, Latin-1 + Euro" }, + { "KOI8-R [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Cyrillic, KOI, O: Cyrillic, KOI" }, + { "KOI8-U [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Ukrainian, O: Ukrainian" }, + { "CP-1250 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Central European 3, O: Central European 3" }, + { "CP-1251 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Cyrillic, Windows, O: Cyrillic, Windows" }, + { "CP-1252 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Western, CP, O: Western, CP" }, + { "CP-1253 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Greek, CP, O: Greek, CP" }, + { "CP-1256 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Arabic, CP, O: Arabic, CP" }, + { "CP-1257 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Baltic, CP, O: Baltic, CP" }, + { "CP-1255 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Hebrew, CP, O: Hebrew, CP" }, + { "CP-1254 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Turkish, CP, O: Turkish, CP" }, + { "TIS-620 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Thai, O: Thai" }, +#ifndef QT_NO_BIG_CODECS + { "Big5 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Chinese Traditional, O: Chinese Traditional" }, + { "Big5-HKSCS [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Chinese Traditional, Hong Kong, O: Chinese Traditional, Hong Kong" }, + { "GB18030 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Chinese Simplified, O: Chinese Simplified" }, + { "JIS7 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Japanese (JIS7), O: Japanese " }, + { "Shift-JIS [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Japanese (Shift-JIS), O: Japanese (Shift-JIS)" }, + { "EUC-JP [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Japanese (EUC-JP), O: Japanese (EUC-JP)" }, + { "EUC-KR [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Korean, O: Korean" }, + { "TSCII [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Tamil, O: Tamil" }, +#endif + { "ISO-8859-10 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / ISO-8859-10, O: ISO-8859-10" }, + { "ISO-8859-13 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / ISO-8859-13, O: ISO-8859-13" }, + { "ISO-8859-14 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / ISO-8859-14, O: ISO-8859-14" }, + { "IBM-850 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / IBM-850, O: IBM-850" }, + { "IBM-866 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / IBM-866, O: IBM-866" }, + { "CP874 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / CP874, O: CP874" }, + + // smart codecs that send in utf8 + { "UTF-8 [ISO-8859-1]" , 1 , 1 , "I: 8-bit Unicode / Western Latin-1, O: 8-bit Unicode" }, + { "UTF-8 [ISO-8859-2]" , 1 , 1 , "I: 8-bit Unicode / Central European 1, O: 8-bit Unicode" }, + { "UTF-8 [ISO-8859-3]" , 1 , 1 , "I: 8-bit Unicode / Central European 2, O: 8-bit Unicode" }, + { "UTF-8 [ISO-8859-4]" , 1 , 1 , "I: 8-bit Unicode / Baltic, Standard, O: 8-bit Unicode" }, + + { "UTF-8 [ISO-8859-5]" , 1 , 1 , "I: 8-bit Unicode / Cyrillic, ISO, O: 8-bit Unicode" }, + { "UTF-8 [ISO-8859-6]" , 1 , 1 , "I: 8-bit Unicode / Arabic, Standard, O: 8-bit Unicode" }, + { "UTF-8 [ISO-8859-7]" , 1 , 1 , "I: 8-bit Unicode / Greek, O: 8-bit Unicode" }, + { "UTF-8 [ISO-8859-8]" , 1 , 1 , "I: 8-bit Unicode / Hebrew, visually ordered, O: 8-bit Unicode" }, + + { "UTF-8 [ISO-8859-8-i]" , 1 , 1 , "I: 8-bit Unicode / Hebrew, logically ordered, O: 8-bit Unicode" }, + { "UTF-8 [ISO-8859-9]" , 1 , 1 , "I: 8-bit Unicode / Turkish, Latin-5, O: 8-bit Unicode" }, + { "UTF-8 [ISO-8859-15]" , 1 , 1 , "I: 8-bit Unicode / Western, Latin-1 + Euro, O: 8-bit Unicode" }, + { "UTF-8 [KOI8-R]" , 1 , 1 , "I: 8-bit Unicode / Cyrillic, KOI, O: 8-bit Unicode" }, + + { "UTF-8 [KOI8-U]" , 1 , 1 , "I: 8-bit Unicode / Ukrainian, O: 8-bit Unicode" }, + { "UTF-8 [CP-1250]" , 1 , 1 , "I: 8-bit Unicode / Central European 3, O: 8-bit Unicode" }, + { "UTF-8 [CP-1251]" , 1 , 1 , "I: 8-bit Unicode / Cyrillic, Windows, O: 8-bit Unicode" }, + { "UTF-8 [CP-1252]" , 1 , 1 , "I: 8-bit Unicode / Western, CP, O: 8-bit Unicode" }, + + { "UTF-8 [CP-1253]" , 1 , 1 , "I: 8-bit Unicode / Greek, CP, O: 8-bit Unicode" }, + { "UTF-8 [CP-1256]" , 1 , 1 , "I: 8-bit Unicode / Arabic, CP, O: 8-bit Unicode" }, + { "UTF-8 [CP-1257]" , 1 , 1 , "I: 8-bit Unicode / Baltic, CP, O: 8-bit Unicode" }, + { "UTF-8 [CP-1255]" , 1 , 1 , "I: 8-bit Unicode / Hebrew, CP, O: 8-bit Unicode" }, + + { "UTF-8 [CP-1254]" , 1 , 1 , "I: 8-bit Unicode / Turkish, CP, O: 8-bit Unicode" }, + { "UTF-8 [TIS-620]" , 1 , 1 , "I: 8-bit Unicode / Thai, O: 8-bit Unicode" }, +#ifndef QT_NO_BIG_CODECS + { "UTF-8 [Big5]" , 1 , 1 , "I: 8-bit Unicode / Chinese Traditional, O: 8-bit Unicode" }, + { "UTF-8 [Big5-HKSCS]" , 1 , 1 , "I: 8-bit Unicode / Chinese Traditional, Hong Kong, O: 8-bit Unicode" }, + + { "UTF-8 [GB18030]" , 1 , 1 , "I: 8-bit Unicode / Chinese Simplified, O: 8-bit Unicode" }, + { "UTF-8 [JIS7]" , 1 , 1 , "I: 8-bit Unicode / Japanese (JIS7), O: 8-bit Unicode" }, + { "UTF-8 [Shift-JIS]" , 1 , 1 , "I: 8-bit Unicode / Japanese (Shift-JIS), O: Japanese (Shift-JIS)" }, + { "UTF-8 [EUC-JP]" , 1 , 1 , "I: 8-bit Unicode / Japanese (EUC-JP), O: Japanese (EUC-JP)" }, + + { "UTF-8 [EUC-KR]" , 1 , 1 , "I: 8-bit Unicode / Korean, O: 8-bit Unicode" }, + { "UTF-8 [TSCII]" , 1 , 1 , "I: 8-bit Unicode / Tamil, O: 8-bit Unicode" }, +#endif + { "UTF-8 [ISO-8859-10]" , 1 , 1 , "I: 8-bit Unicode / ISO-8859-10, O: 8-bit Unicode" }, + { "UTF-8 [ISO-8859-13]" , 1 , 1 , "I: 8-bit Unicode / ISO-8859-13, O: 8-bit Unicode" }, + + { "UTF-8 [ISO-8859-14]" , 1 , 1 , "I: 8-bit Unicode / ISO-8859-14, O: 8-bit Unicode" }, + { "UTF-8 [IBM-850]" , 1 , 1 , "I: 8-bit Unicode / IBM-850, O: 8-bit Unicode" }, + { "UTF-8 [IBM-866]" , 1 , 1 , "I: 8-bit Unicode / IBM-866, O: 8-bit Unicode" }, + { "UTF-8 [CP874]" , 1 , 1 , "I: 8-bit Unicode / CP874, O: 8-bit Unicode" }, + + { 0 , 0 , 0 , 0 } + }; + + EncodingDescription * encodingDescription(int iIdx) + { + if(iIdx > NUM_ENCODINGS)return &(supported_encodings[NUM_ENCODINGS]); + return &(supported_encodings[iIdx]); + } + + QTextCodec * codecForName(const char * szName) + { + KviStr szTmp = szName; + int idx = szTmp.findFirstIdx('['); + if(idx != -1) + { + // composite codec: either UTF-8 [child codec] or child codec [UTF-8] + KviSmartTextCodec * c = g_pSmartCodecDict->find(szName); + if(c)return c; + + + if(kvi_strEqualCIN("UTF-8 [",szName,7)) + { + szTmp.replaceAll("UTF-8 [",""); + szTmp.replaceAll("]",""); + // smart codec that sends UTF-8 + c = new KviSmartTextCodec(szName,szTmp.ptr(),true); + } else { + szTmp.cutFromFirst(' '); + // smart codec that sends child encoding + c = new KviSmartTextCodec(szName,szTmp.ptr(),false); + } + if(c->ok()) + { + g_pSmartCodecDict->replace(szName,c); + return c; + } else { + delete c; + } + } + return QTextCodec::codecForName(szName); + } + + const KviStr & localeName() + { + return g_szLang; + } + + bool loadCatalogue(const QString &name,const QString &szLocaleDir) + { + //debug("Looking up catalogue %s",name); + if(g_pCatalogueDict->find(KviQString::toUtf8(name).data()))return true; // already loaded + + QString szBuffer; + + if(findCatalogue(szBuffer,name,szLocaleDir)) + { + KviMessageCatalogue * c = new KviMessageCatalogue(); + if(c->load(szBuffer)) + { + //debug("KviLocale: loaded catalogue %s",name); + g_pCatalogueDict->insert(KviQString::toUtf8(name).data(),c); + return true; + } + } + return false; + } + + bool unloadCatalogue(const QString &name) + { + //debug("Unloading catalogue : %s",name); + return g_pCatalogueDict->remove(KviQString::toUtf8(name).data()); + } + + bool findCatalogue(QString &szBuffer,const QString& name,const QString& szLocaleDir) + { + KviStr szLocale = g_szLang; + + QString szLocDir = szLocaleDir; + KviQString::ensureLastCharIs(szLocDir,KVI_PATH_SEPARATOR_CHAR); + + KviQString::sprintf(szBuffer,"%Q%Q_%s.mo",&szLocDir,&name,szLocale.ptr()); + + if(KviFileUtils::fileExists(szBuffer))return true; + + if(szLocale.findFirstIdx('.') != -1) + { + // things like en_GB.utf8 + // kill them + szLocale.cutFromFirst('.'); + + KviQString::sprintf(szBuffer,"%Q%Q_%s.mo",&szLocDir,&name,szLocale.ptr()); + if(KviFileUtils::fileExists(szBuffer))return true; + } + + if(szLocale.findFirstIdx('@') != -1) + { + // things like @euro ? + // kill them + szLocale.cutFromFirst('@'); + KviQString::sprintf(szBuffer,"%Q%Q_%s.mo",&szLocDir,&name,szLocale.ptr()); + if(KviFileUtils::fileExists(szBuffer))return true; + } + + if(szLocale.findFirstIdx('_') != -1) + { + // things like en_GB + // kill them + szLocale.cutFromFirst('_'); + KviQString::sprintf(szBuffer,"%Q%Q_%s.mo",&szLocDir,&name,szLocale.ptr()); + if(KviFileUtils::fileExists(szBuffer))return true; + } + + // try the lower case version too + szLocale.toLower(); + KviQString::sprintf(szBuffer,"%Q%Q_%s.mo",&szLocDir,&name,szLocale.ptr()); + if(KviFileUtils::fileExists(szBuffer))return true; + + return false; + } + + // + // This function attempts to determine the current locale + // and then load the corresponding translation file + // from the KVIrc locale directory + // Returns true if the locale was correctly set + // i.e. the locale is C or POSIX (no translation needed) + // or the locale is correctly defined and the + // translation map was sucesfully loaded + // + + void init(QApplication * app,const QString &localeDir) + { + // first of all try to find out the current locale + g_szLang=""; +#ifdef COMPILE_USE_QT4 + QString szLangFile=QString("%1/.kvirc_force_locale").arg(QDir::homePath()); +#else + QString szLangFile=QString("%1/.kvirc_force_locale").arg(QDir::homeDirPath()); +#endif + if(KviFileUtils::fileExists(szLangFile)) + { + QString szTmp; + KviFileUtils::readFile(szLangFile,szTmp); + g_szLang=szTmp; + } + if(g_szLang.isEmpty())g_szLang = kvi_getenv("KVIRC_LANG"); +#ifdef COMPILE_USE_QT4 + if(g_szLang.isEmpty())g_szLang = QLocale::system().name(); +#else + if(g_szLang.isEmpty())g_szLang = QTextCodec::locale(); +#endif + if(g_szLang.isEmpty())g_szLang = kvi_getenv("LC_MESSAGES"); + if(g_szLang.isEmpty())g_szLang = kvi_getenv("LANG"); + if(g_szLang.isEmpty())g_szLang = "en"; + g_szLang.stripWhiteSpace(); + + // the main catalogue is supposed to be kvirc_<language>.mo + g_pMainCatalogue = new KviMessageCatalogue(); + // the catalogue dict + g_pCatalogueDict = new KviPointerHashTable<const char *,KviMessageCatalogue>; + g_pCatalogueDict->setAutoDelete(true); + + // the smart codec dict + g_pSmartCodecDict = new KviPointerHashTable<const char *,KviSmartTextCodec>; + // the Qt docs explicitly state that we shouldn't delete + // the codecs by ourselves... + g_pSmartCodecDict->setAutoDelete(false); + + if(g_szLang.hasData()) + { + QString szBuffer; + if(findCatalogue(szBuffer,"kvirc",localeDir)) + { + g_pMainCatalogue->load(szBuffer); + g_pTranslator = new KviTranslator(app,"kvirc_translator"); + app->installTranslator(g_pTranslator); + } else { + KviStr szTmp = g_szLang; + szTmp.cutFromFirst('.'); + szTmp.cutFromFirst('_'); + szTmp.cutFromFirst('@'); + szTmp.toLower(); + if(!(kvi_strEqualCI(szTmp.ptr(),"en") || + kvi_strEqualCI(szTmp.ptr(),"c") || + kvi_strEqualCI(szTmp.ptr(),"us") || + kvi_strEqualCI(szTmp.ptr(),"gb") || + kvi_strEqualCI(szTmp.ptr(),"posix"))) + { + // FIXME: THIS IS NO LONGER VALID!!! + debug("Can't find the catalogue for locale \"%s\" (%s)",g_szLang.ptr(),szTmp.ptr()); + debug("There is no such translation or the $LANG variable was incorrectly set"); + debug("You can use $KVIRC_LANG to override the catalogue name"); + debug("For example you can set KVIRC_LANG to it_IT to force usage of the it.mo catalogue"); + } + } + } + + //g_pTextCodec = QTextCodec::codecForLocale(); + //if(!g_pTextCodec)g_pTextCodec = QTextCodec::codecForLocale(); + } + + void done(QApplication * app) + { + delete g_pMainCatalogue; + delete g_pCatalogueDict; + delete g_pSmartCodecDict; + g_pMainCatalogue = 0; + g_pCatalogueDict = 0; + g_pSmartCodecDict = 0; + if(g_pTranslator) + { + app->removeTranslator(g_pTranslator); + delete g_pTranslator; + g_pTranslator = 0; + } + } + + KviMessageCatalogue * getLoadedCatalogue(const QString& name) + { + return g_pCatalogueDict->find(KviQString::toUtf8(name).data()); + } + + + const char * translate(const char * text,const char * context) + { + if(context) + { + KviMessageCatalogue * c = g_pCatalogueDict->find(context); + if(!c) + { + // FIXME: Should really try to load the catalogue here! + c = new KviMessageCatalogue(); + g_pCatalogueDict->insert(context,c); + } + return c->translate(text); + } + return g_pMainCatalogue->translate(text); + } + + const QString & translateToQString(const char * text,const char * context) + { + if(context) + { + KviMessageCatalogue * c = g_pCatalogueDict->find(context); + if(!c) + { + // FIXME: Should really try to load the catalogue here! + c = new KviMessageCatalogue(); + g_pCatalogueDict->insert(context,c); + } + return c->translateToQString(text); + } + return g_pMainCatalogue->translateToQString(text); + } +}; + +KviTranslator::KviTranslator(QObject * par,const char * nam) +#ifdef COMPILE_USE_QT4 +: QTranslator(par) +#else +: QTranslator(par,nam) +#endif +{ +} + +KviTranslator::~KviTranslator() +{ +} + +#ifdef COMPILE_USE_QT4 +QString KviTranslator::translate(const char *context,const char * message,const char * comment) const +{ + // we ignore contexts and comments for qt translations + return g_pMainCatalogue->translateToQString(message); +} +#endif + +QString KviTranslator::find(const char *context,const char * message) const +{ + // we ignore contexts for qt translations + return g_pMainCatalogue->translateToQString(message); +} + +#ifndef COMPILE_USE_QT4 +QTranslatorMessage KviTranslator::findMessage(const char * context,const char * sourceText,const char * comment) const +{ + // we ignore contexts for qt translations + return QTranslatorMessage(context,sourceText,comment,g_pMainCatalogue->translateToQString(sourceText)); +} +#endif + +#if 0 + +// a fake table that will force these translations +// to be included in the *.pot file + +static QString fake_translations_table[]= +{ + // global + __tr2qs("OK"), + __tr2qs("Cancel"), + // color dialog + __tr2qs("Select color"), + __tr2qs("&Basic colors"), + __tr2qs("&Custom colors"), + __tr2qs("&Red"), + __tr2qs("&Green"), + __tr2qs("Bl&ue"), + __tr2qs("&Define Custom Colors >>"), + __tr2qs("&Add to Custom Colors"), + // font dialog + __tr2qs("Select Font"), + __tr2qs("&Font"), + __tr2qs("Font st&yle"), + __tr2qs("&Size"), + __tr2qs("Sample"), + __tr2qs("Effects"), + __tr2qs("Stri&keout"), + __tr2qs("&Underline"), + __tr2qs("Scr&ipt"), + //File selector + __tr2qs("Parent Directory"), + __tr2qs("Back"), + __tr2qs("Forward"), + __tr2qs("Reload"), + __tr2qs("New Directory"), + __tr2qs("Bookmarks"), + __tr2qs("Add Bookmark"), + __tr2qs("&Edit Bookmarks"), + __tr2qs("New Bookmark Folder..."), + __tr2qs("Configure"), + __tr2qs("Sorting"), + __tr2qs("By Name"), + __tr2qs("By Date"), + __tr2qs("By Size"), + __tr2qs("Reverse"), + __tr2qs("Directories First"), + __tr2qs("Case Insensitive"), + __tr2qs("Short View"), + __tr2qs("Detailed View"), + __tr2qs("Show Hidden Files"), + __tr2qs("Show Quick Access Navigation Panel"), + __tr2qs("Show Preview"), + __tr2qs("Separate Directories"), + __tr2qs("Often used directories"), + __tr2qs("Desktop"), + __tr2qs("Home Directory"), + __tr2qs("Floppy"), + __tr2qs("Temporary Files"), + __tr2qs("Network"), + __tr2qs("New Directory..."), + __tr2qs("Delete"), + __tr2qs("Thumbnail Previews"), + __tr2qs("Large Icons"), + __tr2qs("Small Icons"), + __tr2qs("Properties..."), + __tr2qs("&Automatic Preview"), + __tr2qs("&Preview"), + __tr2qs("&Location:"), + __tr2qs("&Filter:"), + __tr2qs("All Files"), + __tr2qs("&OK"), + __tr2qs("&Cancel") + +} + +#endif |