?? qtextcodec.cpp
字號:
/******************************************************************************** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.**** This file is part of the QtCore module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file. Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "qplatformdefs.h"#include "qtextcodec.h"#ifndef QT_NO_TEXTCODEC#include "qlist.h"#include "qfile.h"#ifndef QT_NO_LIBRARY# include "qcoreapplication.h"# include "qtextcodecplugin.h"# include "private/qfactoryloader_p.h"#endif#include "qstringlist.h"#ifdef Q_OS_UNIX# include "qiconvcodec_p.h"#endif#include "qutfcodec_p.h"#include "qsimplecodec_p.h"#include "qlatincodec_p.h"#ifndef QT_NO_CODECS# include "qtsciicodec_p.h"# include "qisciicodec_p.h"# if defined(QT_NO_ICONV) && !defined(QT_BOOTSTRAPPED)// no iconv(3) support, must build all codecs into the library# include "../../plugins/codecs/cn/qgb18030codec.h"# include "../../plugins/codecs/jp/qeucjpcodec.h"# include "../../plugins/codecs/jp/qjiscodec.h"# include "../../plugins/codecs/jp/qsjiscodec.h"# include "../../plugins/codecs/kr/qeuckrcodec.h"# include "../../plugins/codecs/tw/qbig5codec.h"# endif // QT_NO_ICONV# if defined(Q_WS_X11) && !defined(QT_BOOTSTRAPPED)# include "qfontlaocodec_p.h"# include "../../plugins/codecs/jp/qfontjpcodec.h"# endif#endif // QT_NO_CODECS#include "qlocale.h"#include "private/qmutexpool_p.h"#include <stdlib.h>#include <ctype.h>#ifndef Q_OS_TEMP#include <locale.h>#endif#if defined (_XOPEN_UNIX) && !defined(Q_OS_QNX6) && !defined(Q_OS_OSF)#include <langinfo.h>#endif#ifndef QT_NO_TEXTCODECPLUGINQ_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, (QTextCodecFactoryInterface_iid, QCoreApplication::libraryPaths(), QLatin1String("/codecs")))#endifstatic bool nameMatch(const QByteArray &name, const QByteArray &test){ // if they're the same, return a perfect score if (qstricmp(name, test) == 0) return true; const char *n = name.constData(); const char *h = test.constData(); // if the letters and numbers are the same, we have a match while (*n != '\0') { if (isalnum((uchar)*n)) { for (;;) { if (*h == '\0') return false; if (isalnum((uchar)*h)) break; ++h; } if (tolower((uchar)*n) != tolower((uchar)*h)) return false; ++h; } ++n; } while (*h && !isalnum((uchar)*h)) ++h; return (*h == '\0');}static QTextCodec *createForName(const QByteArray &name){#ifndef QT_NO_TEXTCODECPLUGIN QFactoryLoader *l = loader(); QStringList keys = l->keys(); for (int i = 0; i < keys.size(); ++i) { if (nameMatch(name, keys.at(i).toLatin1())) { QString realName = keys.at(i); if (QTextCodecFactoryInterface *factory = qobject_cast<QTextCodecFactoryInterface*>(l->instance(realName))) { return factory->create(realName); } } }#else Q_UNUSED(name);#endif return 0;}static QTextCodec *createForMib(int mib){#ifndef QT_NO_TEXTCODECPLUGIN QString name = QLatin1String("MIB: ") + QString::number(mib); if (QTextCodecFactoryInterface *factory = qobject_cast<QTextCodecFactoryInterface*>(loader()->instance(name))) return factory->create(name);#else Q_UNUSED(mib);#endif return 0;}static QList<QTextCodec*> *all = 0;static bool destroying_is_ok = false;static QTextCodec *localeMapper = 0;QTextCodec *QTextCodec::cftr = 0;class QTextCodecCleanup{public: ~QTextCodecCleanup();};/* Deletes all the created codecs. This destructor is called just before exiting to delete any QTextCodec objects that may be lying around.*/QTextCodecCleanup::~QTextCodecCleanup(){ if (!all) return; destroying_is_ok = true; while (all->size()) delete all->takeFirst(); delete all; all = 0; localeMapper = 0; destroying_is_ok = false;}Q_GLOBAL_STATIC(QTextCodecCleanup, createQTextCodecCleanup)#ifdef Q_OS_WIN32class QWindowsLocalCodec: public QTextCodec{public: QWindowsLocalCodec(); ~QWindowsLocalCodec(); QString convertToUnicode(const char *, int, ConverterState *) const; QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const; QByteArray name() const; int mibEnum() const;};QWindowsLocalCodec::QWindowsLocalCodec(){}QWindowsLocalCodec::~QWindowsLocalCodec(){}QString QWindowsLocalCodec::convertToUnicode(const char *chars, int len, ConverterState * /*state*/) const{ return qt_winMB2QString(chars, len);}QByteArray QWindowsLocalCodec::convertFromUnicode(const QChar *uc, int len, ConverterState *) const{ return qt_winQString2MB(uc, len);}QByteArray QWindowsLocalCodec::name() const{ return "System";}int QWindowsLocalCodec::mibEnum() const{ return 0;}#else/* locale names mostly copied from XFree86 */static const char * const iso8859_2locales[] = { "croatian", "cs", "cs_CS", "cs_CZ","cz", "cz_CZ", "czech", "hr", "hr_HR", "hu", "hu_HU", "hungarian", "pl", "pl_PL", "polish", "ro", "ro_RO", "rumanian", "serbocroatian", "sh", "sh_SP", "sh_YU", "sk", "sk_SK", "sl", "sl_CS", "sl_SI", "slovak", "slovene", "sr_SP", 0 };static const char * const iso8859_3locales[] = { "eo", 0 };static const char * const iso8859_4locales[] = { "ee", "ee_EE", 0 };static const char * const iso8859_5locales[] = { "mk", "mk_MK", "sp", "sp_YU", 0 };static const char * const cp_1251locales[] = { "be", "be_BY", "bg", "bg_BG", "bulgarian", 0 };static const char * const pt_154locales[] = { "ba_RU", "ky", "ky_KG", "kk", "kk_KZ", 0 };static const char * const iso8859_6locales[] = { "ar_AA", "ar_SA", "arabic", 0 };static const char * const iso8859_7locales[] = { "el", "el_GR", "greek", 0 };static const char * const iso8859_8locales[] = { "hebrew", "he", "he_IL", "iw", "iw_IL", 0 };static const char * const iso8859_9locales[] = { "tr", "tr_TR", "turkish", 0 };static const char * const iso8859_13locales[] = { "lt", "lt_LT", "lv", "lv_LV", 0 };static const char * const iso8859_15locales[] = { "et", "et_EE", // Euro countries "br_FR", "ca_ES", "de", "de_AT", "de_BE", "de_DE", "de_LU", "en_IE", "es", "es_ES", "eu_ES", "fi", "fi_FI", "finnish", "fr", "fr_FR", "fr_BE", "fr_LU", "french", "ga_IE", "gl_ES", "it", "it_IT", "oc_FR", "nl", "nl_BE", "nl_NL", "pt", "pt_PT", "sv_FI", "wa_BE", 0 };static const char * const koi8_ulocales[] = { "uk", "uk_UA", "ru_UA", "ukrainian", 0 };static const char * const tis_620locales[] = { "th", "th_TH", "thai", 0 };// static const char * const tcvnlocales[] = {// "vi", "vi_VN", 0 };static bool try_locale_list(const char * const locale[], const char * lang){ int i; for(i=0; locale[i] && *locale[i] && strcmp(locale[i], lang); i++) ; return locale[i] != 0;}// For the probably_koi8_locales we have to look. the standard says// these are 8859-5, but almost all Russian users use KOI8-R and// incorrectly set $LANG to ru_RU. We'll check tolower() to see what// it thinks ru_RU means.// If you read the history, it seems that many Russians blame ISO and// Perestroika for the confusion.//// The real bug is that some programs break if the user specifies// ru_RU.KOI8-R.static const char * const probably_koi8_rlocales[] = { "ru", "ru_SU", "ru_RU", "russian", 0 };static QTextCodec * ru_RU_hack(const char * i) { QTextCodec * ru_RU_codec = 0; QByteArray origlocale(setlocale(LC_CTYPE, i)); // unicode koi8r latin5 name // 0x044E 0xC0 0xEE CYRILLIC SMALL LETTER YU // 0x042E 0xE0 0xCE CYRILLIC CAPITAL LETTER YU int latin5 = tolower(0xCE); int koi8r = tolower(0xE0); if (koi8r == 0xC0 && latin5 != 0xEE) { ru_RU_codec = QTextCodec::codecForName("KOI8-R"); } else if (koi8r != 0xC0 && latin5 == 0xEE) { ru_RU_codec = QTextCodec::codecForName("ISO 8859-5"); } else { // something else again... let's assume... *throws dice* ru_RU_codec = QTextCodec::codecForName("KOI8-R"); qWarning("QTextCodec: Using KOI8-R, probe failed (%02x %02x %s)", koi8r, latin5, i); } setlocale(LC_CTYPE, origlocale); return ru_RU_codec;}#endifstatic QTextCodec *checkForCodec(const char *name) { QTextCodec *c = QTextCodec::codecForName(name); if (!c) { const char *at = strchr(name, '@'); if (at) { QByteArray n(name, at - name); c = QTextCodec::codecForName(n.data()); } } return c;}/* the next two functions are implicitely thread safe, as they are only called by setup() which uses a mutex.*/static void setupLocaleMapper(){#ifdef Q_OS_WIN32 localeMapper = QTextCodec::codecForName("System");#else#ifndef QT_NO_ICONV localeMapper = QTextCodec::codecForName("System");#endif#if defined (_XOPEN_UNIX) && !defined(Q_OS_QNX6) && !defined(Q_OS_OSF) if (!localeMapper) { char *charset = nl_langinfo (CODESET); if (charset) localeMapper = QTextCodec::codecForName(charset); }#endif if (!localeMapper) { // Very poorly defined and followed standards causes lots of // code to try to get all the cases... This logic is // duplicated in QIconvCodec, so if you change it here, change // it there too. // Try to determine locale codeset from locale name assigned to // LC_CTYPE category. // First part is getting that locale name. First try setlocale() which // definitely knows it, but since we cannot fully trust it, get ready // to fall back to environment variables. char * ctype = qstrdup(setlocale(LC_CTYPE, 0)); // Get the first nonempty value from $LC_ALL, $LC_CTYPE, and $LANG // environment variables. char * lang = qstrdup(qgetenv("LC_ALL").constData()); if (!lang || lang[0] == 0 || strcmp(lang, "C") == 0) { if (lang) delete [] lang; lang = qstrdup(qgetenv("LC_CTYPE").constData()); } if (!lang || lang[0] == 0 || strcmp(lang, "C") == 0) { if (lang) delete [] lang; lang = qstrdup(qgetenv("LANG").constData()); } // Now try these in order: // 1. CODESET from ctype if it contains a .CODESET part (e.g. en_US.ISO8859-15) // 2. CODESET from lang if it contains a .CODESET part // 3. ctype (maybe the locale is named "ISO-8859-1" or something) // 4. locale (ditto) // 5. check for "@euro" // 6. guess locale from ctype unless ctype is "C" // 7. guess locale from lang // 1. CODESET from ctype if it contains a .CODESET part (e.g. en_US.ISO8859-15) char * codeset = ctype ? strchr(ctype, '.') : 0; if (codeset && *codeset == '.') localeMapper = checkForCodec(codeset + 1); // 2. CODESET from lang if it contains a .CODESET part codeset = lang ? strchr(lang, '.') : 0; if (!localeMapper && codeset && *codeset == '.') localeMapper = checkForCodec(codeset + 1); // 3. ctype (maybe the locale is named "ISO-8859-1" or something) if (!localeMapper && ctype && *ctype != 0 && strcmp (ctype, "C") != 0) localeMapper = checkForCodec(ctype); // 4. locale (ditto) if (!localeMapper && lang && *lang != 0) localeMapper = checkForCodec(lang); // 5. "@euro" if (!localeMapper && ctype && strstr(ctype, "@euro") || lang && strstr(lang, "@euro")) localeMapper = checkForCodec("ISO 8859-15"); // 6. guess locale from ctype unless ctype is "C" // 7. guess locale from lang char * try_by_name = ctype; if (ctype && *ctype != 0 && strcmp (ctype, "C") != 0) try_by_name = lang; // Now do the guessing. if (lang && *lang && !localeMapper && try_by_name && *try_by_name) { if (try_locale_list(iso8859_15locales, lang)) localeMapper = QTextCodec::codecForName("ISO 8859-15"); else if (try_locale_list(iso8859_2locales, lang)) localeMapper = QTextCodec::codecForName("ISO 8859-2"); else if (try_locale_list(iso8859_3locales, lang)) localeMapper = QTextCodec::codecForName("ISO 8859-3"); else if (try_locale_list(iso8859_4locales, lang)) localeMapper = QTextCodec::codecForName("ISO 8859-4"); else if (try_locale_list(iso8859_5locales, lang)) localeMapper = QTextCodec::codecForName("ISO 8859-5"); else if (try_locale_list(iso8859_6locales, lang)) localeMapper = QTextCodec::codecForName("ISO 8859-6"); else if (try_locale_list(iso8859_7locales, lang)) localeMapper = QTextCodec::codecForName("ISO 8859-7"); else if (try_locale_list(iso8859_8locales, lang)) localeMapper = QTextCodec::codecForName("ISO 8859-8-I"); else if (try_locale_list(iso8859_9locales, lang)) localeMapper = QTextCodec::codecForName("ISO 8859-9"); else if (try_locale_list(iso8859_13locales, lang)) localeMapper = QTextCodec::codecForName("ISO 8859-13"); else if (try_locale_list(tis_620locales, lang)) localeMapper = QTextCodec::codecForName("ISO 8859-11"); else if (try_locale_list(koi8_ulocales, lang)) localeMapper = QTextCodec::codecForName("KOI8-U"); else if (try_locale_list(cp_1251locales, lang)) localeMapper = QTextCodec::codecForName("CP 1251"); else if (try_locale_list(pt_154locales, lang)) localeMapper = QTextCodec::codecForName("PT 154");
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -