diff options
Diffstat (limited to 'config.profiles/harmattan/patches/icu.diff')
-rw-r--r-- | config.profiles/harmattan/patches/icu.diff | 732 |
1 files changed, 732 insertions, 0 deletions
diff --git a/config.profiles/harmattan/patches/icu.diff b/config.profiles/harmattan/patches/icu.diff new file mode 100644 index 0000000000..16a17fd14e --- /dev/null +++ b/config.profiles/harmattan/patches/icu.diff @@ -0,0 +1,732 @@ +diff --git a/configure b/configure +index 3a748e2..77232dc 100755 +--- a/configure ++++ b/configure +@@ -779,6 +779,7 @@ CFG_PULSEAUDIO=auto + CFG_COREWLAN=auto + CFG_ICD=auto + CFG_NOPROCESS=no ++CFG_ICU=no + + # initalize variables used for installation + QT_INSTALL_PREFIX= +@@ -940,7 +941,7 @@ while [ "$#" -gt 0 ]; do + VAL=no + ;; + #Qt style yes options +- -incremental|-qvfb|-profile|-shared|-static|-sm|-xinerama|-xshape|-xsync|-xinput|-xinput2|-egl|-reduce-exports|-pch|-separate-debug-info|-stl|-freetype|-xcursor|-xfixes|-xrandr|-xrender|-mitshm|-fontconfig|-xkb|-nis|-qdbus|-dbus|-dbus-linked|-glib|-gstreamer|-gtkstyle|-cups|-iconv|-largefile|-h|-help|-v|-verbose|-debug|-release|-fast|-accessibility|-confirm-license|-gnumake|-framework|-qt3support|-debug-and-release|-exceptions|-cocoa|-carbon|-universal|-prefix-install|-silent|-armfpa|-optimized-qmake|-dwarf2|-reduce-relocations|-sse|-openssl|-openssl-linked|-ptmalloc|-xmlpatterns|-phonon|-phonon-backend|-multimedia|-audio-backend|-svg|-declarative|-javascript-jit|-script|-scripttools|-rpath|-force-pkg-config|-s60|-usedeffiles) ++ -incremental|-qvfb|-profile|-shared|-static|-sm|-xinerama|-xshape|-xsync|-xinput|-xinput2|-egl|-reduce-exports|-pch|-separate-debug-info|-stl|-freetype|-xcursor|-xfixes|-xrandr|-xrender|-mitshm|-fontconfig|-xkb|-nis|-qdbus|-dbus|-dbus-linked|-glib|-gstreamer|-gtkstyle|-cups|-iconv|-largefile|-h|-help|-v|-verbose|-debug|-release|-fast|-accessibility|-confirm-license|-gnumake|-framework|-qt3support|-debug-and-release|-exceptions|-cocoa|-carbon|-universal|-prefix-install|-silent|-armfpa|-optimized-qmake|-dwarf2|-reduce-relocations|-sse|-openssl|-openssl-linked|-ptmalloc|-xmlpatterns|-phonon|-phonon-backend|-multimedia|-audio-backend|-svg|-declarative|-javascript-jit|-script|-scripttools|-rpath|-force-pkg-config|-s60|-usedeffiles|-icu) + VAR=`echo $1 | sed "s,^-\(.*\),\1,"` + VAL=yes + ;; +@@ -2242,6 +2243,13 @@ while [ "$#" -gt 0 ]; do + QT_CFLAGS_FPU=$VAL + fi + ;; ++ icu) ++ if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then ++ CFG_ICU="$VAL" ++ else ++ UNKNOWN_OPT=yes ++ fi ++ ;; + *) + UNKNOWN_OPT=yes + ;; +@@ -7040,6 +7048,10 @@ if [ "$CFG_ICD" = "yes" ]; then + QT_CONFIG="$QT_CONFIG icd" + fi + ++if [ "$CFG_ICU" = "yes" ]; then ++ QT_CONFIG="$QT_CONFIG icu" ++fi ++ + # + # Some Qt modules are too advanced in C++ for some old compilers + # Detect here the platforms where they are known to work. +diff --git a/src/corelib/tools/qchar.cpp b/src/corelib/tools/qchar.cpp +index 7cdc256..11a85d5 100644 +--- a/src/corelib/tools/qchar.cpp ++++ b/src/corelib/tools/qchar.cpp +@@ -57,6 +57,12 @@ + + QT_BEGIN_NAMESPACE + ++#ifdef QT_USE_ICU ++// from qlocale_icu.cpp ++extern uint qt_u_toUpper(uint c); ++extern uint qt_u_toLower(uint c); ++#endif ++ + #ifndef QT_NO_CODEC_FOR_C_STRINGS + # ifdef QT_NO_TEXTCODEC + # define QT_NO_CODEC_FOR_C_STRINGS +@@ -1076,6 +1082,12 @@ QChar::UnicodeVersion QChar::unicodeVersion(ushort ucs2) + */ + QChar QChar::toLower() const + { ++#ifdef QT_USE_ICU ++ uint res = qt_u_toLower(ucs); ++ if (res) ++ return QChar(res); ++ // else fall through ++#endif + const QUnicodeTables::Properties *p = qGetProp(ucs); + if (!p->lowerCaseSpecial) + return ucs + p->lowerCaseDiff; +@@ -1090,6 +1102,12 @@ QChar QChar::toLower() const + */ + uint QChar::toLower(uint ucs4) + { ++#ifdef QT_USE_ICU ++ uint res = qt_u_toLower(ucs4); ++ if (res) ++ return res; ++ // else fall through ++#endif + if (ucs4 > UNICODE_LAST_CODEPOINT) + return ucs4; + const QUnicodeTables::Properties *p = qGetProp(ucs4); +@@ -1106,6 +1124,12 @@ uint QChar::toLower(uint ucs4) + */ + ushort QChar::toLower(ushort ucs2) + { ++#ifdef QT_USE_ICU ++ uint res = qt_u_toLower(ucs2); ++ if (res) ++ return res & 0xffff; ++ // else fall through ++#endif + const QUnicodeTables::Properties *p = qGetProp(ucs2); + if (!p->lowerCaseSpecial) + return ucs2 + p->lowerCaseDiff; +@@ -1118,6 +1142,12 @@ ushort QChar::toLower(ushort ucs2) + */ + QChar QChar::toUpper() const + { ++#ifdef QT_USE_ICU ++ uint res = qt_u_toUpper(ucs); ++ if (res) ++ return QChar(res); ++ // else fall through ++#endif + const QUnicodeTables::Properties *p = qGetProp(ucs); + if (!p->upperCaseSpecial) + return ucs + p->upperCaseDiff; +@@ -1132,6 +1162,12 @@ QChar QChar::toUpper() const + */ + uint QChar::toUpper(uint ucs4) + { ++#ifdef QT_USE_ICU ++ uint res = qt_u_toUpper(ucs4); ++ if (res) ++ return res; ++ // else fall through ++#endif + if (ucs4 > UNICODE_LAST_CODEPOINT) + return ucs4; + const QUnicodeTables::Properties *p = qGetProp(ucs4); +@@ -1148,6 +1184,12 @@ uint QChar::toUpper(uint ucs4) + */ + ushort QChar::toUpper(ushort ucs2) + { ++#ifdef QT_USE_ICU ++ uint res = qt_u_toUpper(ucs2); ++ if (res) ++ return res & 0xffff; ++ // else fall through ++#endif + const QUnicodeTables::Properties *p = qGetProp(ucs2); + if (!p->upperCaseSpecial) + return ucs2 + p->upperCaseDiff; +diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp +index 6515edb..5470048 100644 +--- a/src/corelib/tools/qlocale.cpp ++++ b/src/corelib/tools/qlocale.cpp +@@ -134,6 +134,10 @@ void qt_symbianUpdateSystemPrivate(); + void qt_symbianInitSystemLocale(); + #endif + ++#ifdef QT_USE_ICU ++extern bool qt_initIcu(const QString &localeName); ++#endif ++ + /****************************************************************************** + ** Helpers for accessing Qt locale database + */ +@@ -2346,6 +2350,10 @@ void QLocale::setDefault(const QLocale &locale) + { + default_lp = locale.d(); + default_number_options = locale.numberOptions(); ++ ++#ifdef QT_USE_ICU ++ qt_initIcu(locale.name()); ++#endif + } + + /*! +diff --git a/src/corelib/tools/qlocale_icu.cpp b/src/corelib/tools/qlocale_icu.cpp +new file mode 100644 +index 0000000..7fe3801 +--- /dev/null ++++ b/src/corelib/tools/qlocale_icu.cpp +@@ -0,0 +1,247 @@ ++/**************************************************************************** ++** ++** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). ++** All rights reserved. ++** Contact: Nokia Corporation (qt-info@nokia.com) ++** ++** This file is part of the QtCore module of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:LGPL$ ++** No Commercial Usage ++** This file contains pre-release code and may not be distributed. ++** You may use this file in accordance with the terms and conditions ++** contained in the Technology Preview License Agreement accompanying ++** this package. ++** ++** GNU Lesser General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU Lesser ++** General Public License version 2.1 as published by the Free Software ++** Foundation and appearing in the file LICENSE.LGPL included in the ++** packaging of this file. Please review the following information to ++** ensure the GNU Lesser General Public License version 2.1 requirements ++** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** ++** In addition, as a special exception, Nokia gives you certain additional ++** rights. These rights are described in the Nokia Qt LGPL Exception ++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ++** ++** If you have questions regarding the use of this file, please contact ++** Nokia at qt-info@nokia.com. ++** ++** ++** ++** ++** ++** ++** ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++#include "qglobal.h" ++#include "qlibrary.h" ++#include "qdebug.h" ++ ++#include "unicode/uversion.h" ++#include "unicode/ucol.h" ++ ++QT_BEGIN_NAMESPACE ++ ++typedef UCollator *(*Ptr_ucol_open)(const char *loc, UErrorCode *status); ++typedef void (*Ptr_ucol_close)(UCollator *coll); ++typedef UCollationResult (*Ptr_ucol_strcoll)(const UCollator *coll, const UChar *source, int32_t sourceLength, const UChar *target, int32_t targetLength); ++typedef int32_t (*Ptr_u_strToCase)(UChar *dest, int32_t destCapacity, const UChar *src, int32_t srcLength, const char *locale, UErrorCode *pErrorCode); ++ ++static Ptr_ucol_open ptr_ucol_open = 0; ++static Ptr_ucol_strcoll ptr_ucol_strcoll = 0; ++static Ptr_ucol_close ptr_ucol_close = 0; ++static Ptr_u_strToCase ptr_u_strToUpper = 0; ++static Ptr_u_strToCase ptr_u_strToLower = 0; ++ ++enum LibLoadStatus ++{ ++ ErrorLoading = -1, ++ NotLoaded = 0, ++ Loaded = 1 ++}; ++ ++static LibLoadStatus status = NotLoaded; ++ ++static UCollator *icuCollator = 0; ++ ++#define STRINGIFY2(x) #x ++#define STRINGIFY(x) STRINGIFY2(x) ++ ++bool qt_initIcu(const QString &localeString) ++{ ++ if (status == ErrorLoading) ++ return false; ++ ++ if (status == NotLoaded) { ++ ++ // resolve libicui18n ++ QLibrary lib(QLatin1String("icui18n"), QLatin1String(U_ICU_VERSION_SHORT)); ++ if (!lib.load()) { ++ qWarning() << "Unable to load library icui18n" << lib.errorString(); ++ status = ErrorLoading; ++ return false; ++ } ++ ++ ptr_ucol_open = (Ptr_ucol_open)lib.resolve("ucol_open"); ++ ptr_ucol_close = (Ptr_ucol_close)lib.resolve("ucol_close"); ++ ptr_ucol_strcoll = (Ptr_ucol_strcoll)lib.resolve("ucol_strcoll"); ++ ++ if (!ptr_ucol_open || !ptr_ucol_close || !ptr_ucol_strcoll) { ++ // try again with decorated symbol names ++ ptr_ucol_open = (Ptr_ucol_open)lib.resolve("ucol_open" STRINGIFY(U_ICU_VERSION_SUFFIX)); ++ ptr_ucol_close = (Ptr_ucol_close)lib.resolve("ucol_close" STRINGIFY(U_ICU_VERSION_SUFFIX)); ++ ptr_ucol_strcoll = (Ptr_ucol_strcoll)lib.resolve("ucol_strcoll" STRINGIFY(U_ICU_VERSION_SUFFIX)); ++ } ++ ++ if (!ptr_ucol_open || !ptr_ucol_close || !ptr_ucol_strcoll) { ++ ptr_ucol_open = 0; ++ ptr_ucol_close = 0; ++ ptr_ucol_strcoll = 0; ++ ++ qWarning("Unable to find symbols in icui18n"); ++ status = ErrorLoading; ++ return false; ++ } ++ ++ // resolve libicuuc ++ QLibrary ucLib(QLatin1String("icuuc"), QLatin1String(U_ICU_VERSION_SHORT)); ++ if (!ucLib.load()) { ++ qWarning() << "Unable to load library icuuc" << ucLib.errorString(); ++ status = ErrorLoading; ++ return false; ++ } ++ ++ ptr_u_strToUpper = (Ptr_u_strToCase)ucLib.resolve("u_strToUpper"); ++ ptr_u_strToLower = (Ptr_u_strToCase)ucLib.resolve("u_strToLower"); ++ ++ if (!ptr_u_strToUpper || !ptr_u_strToLower) { ++ ptr_u_strToUpper = (Ptr_u_strToCase)ucLib.resolve("u_strToUpper" STRINGIFY(U_ICU_VERSION_SUFFIX)); ++ ptr_u_strToLower = (Ptr_u_strToCase)ucLib.resolve("u_strToLower" STRINGIFY(U_ICU_VERSION_SUFFIX)); ++ } ++ ++ if (!ptr_u_strToUpper || !ptr_u_strToLower) { ++ ptr_u_strToUpper = 0; ++ ptr_u_strToLower = 0; ++ ++ qWarning("Unable to find symbols in icuuc"); ++ status = ErrorLoading; ++ return false; ++ } ++ ++ // success :) ++ status = Loaded; ++ } ++ ++ if (icuCollator) { ++ ptr_ucol_close(icuCollator); ++ icuCollator = 0; ++ } ++ ++ UErrorCode icuStatus = U_ZERO_ERROR; ++ icuCollator = ptr_ucol_open(localeString.toLatin1().constData(), &icuStatus); ++ ++ if (!icuCollator) { ++ qWarning("Unable to open locale %s in ICU, error code %d", qPrintable(localeString), icuStatus); ++ return false; ++ } ++ ++ return true; ++} ++ ++bool qt_ucol_strcoll(const QChar *source, int sourceLength, const QChar *target, int targetLength, int *result) ++{ ++ Q_ASSERT(result); ++ Q_ASSERT(source); ++ Q_ASSERT(target); ++ ++ if (!icuCollator) ++ return false; ++ ++ *result = ptr_ucol_strcoll(icuCollator, reinterpret_cast<const UChar *>(source), int32_t(sourceLength), ++ reinterpret_cast<const UChar *>(target), int32_t(targetLength)); ++ ++ return true; ++} ++ ++// caseFunc can either be u_strToUpper or u_strToLower ++static bool qt_u_strToCase(const QString &str, QString *out, const QLocale &locale, Ptr_u_strToCase caseFunc) ++{ ++ Q_ASSERT(out); ++ ++ if (!icuCollator) ++ return false; ++ ++ QString result(str.size(), Qt::Uninitialized); ++ ++ UErrorCode status = U_ZERO_ERROR; ++ ++ int32_t size = caseFunc(reinterpret_cast<UChar *>(result.data()), result.size(), ++ reinterpret_cast<const UChar *>(str.constData()), str.size(), ++ locale.name().toLatin1().constData(), &status); ++ ++ if (U_FAILURE(status)) ++ return false; ++ ++ if (size < result.size()) { ++ result.resize(size); ++ } else if (size > result.size()) { ++ qDebug() << "RESULT SIZE MISMATCH"; ++ // the resulting string is larger than our source string ++ result.resize(size); ++ ++ status = U_ZERO_ERROR; ++ size = caseFunc(reinterpret_cast<UChar *>(result.data()), result.size(), ++ reinterpret_cast<const UChar *>(str.constData()), str.size(), ++ locale.name().toLatin1().constData(), &status); ++ ++ if (U_FAILURE(status)) ++ return false; ++ ++ // if the sizes don't match now, we give up. ++ if (size != result.size()) ++ return false; ++ } ++ ++ *out = result; ++ return true; ++} ++ ++bool qt_u_strToUpper(const QString &str, QString *out, const QLocale &locale) ++{ ++ return qt_u_strToCase(str, out, locale, ptr_u_strToUpper); ++} ++ ++bool qt_u_strToLower(const QString &str, QString *out, const QLocale &locale) ++{ ++ return qt_u_strToCase(str, out, locale, ptr_u_strToLower); ++} ++ ++uint qt_u_toUpper(uint c) ++{ ++ if (c > 0xffff) ++ return 0; ++ ++ QString out; ++ if (qt_u_strToUpper(QChar(c), &out, QLocale()) && !out.isEmpty()) ++ return out.at(0).unicode(); ++ return 0; ++} ++ ++uint qt_u_toLower(uint c) ++{ ++ if (c > 0xffff) ++ return 0; ++ ++ QString out; ++ if (qt_u_strToLower(QChar(c), &out, QLocale()) && !out.isEmpty()) ++ return out.at(0).unicode(); ++ return 0; ++} ++ ++QT_END_NAMESPACE +diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp +index d641d74..0f5cee1 100644 +--- a/src/corelib/tools/qstring.cpp ++++ b/src/corelib/tools/qstring.cpp +@@ -112,6 +112,13 @@ int qFindString(const QChar *haystack, int haystackLen, int from, + int qFindStringBoyerMoore(const QChar *haystack, int haystackLen, int from, + const QChar *needle, int needleLen, Qt::CaseSensitivity cs); + ++#ifdef QT_USE_ICU ++// qlocale_icu.cpp ++extern bool qt_ucol_strcoll(const QChar *source, int sourceLength, const QChar *target, int targetLength, int *result); ++extern bool qt_u_strToUpper(const QString &str, QString *out, const QLocale &locale); ++extern bool qt_u_strToLower(const QString &str, QString *out, const QLocale &locale); ++#endif ++ + + // Unicode case-insensitive comparison + static int ucstricmp(const ushort *a, const ushort *ae, const ushort *b, const ushort *be) +@@ -4808,6 +4815,14 @@ int QString::localeAwareCompare_helper(const QChar *data1, int length1, + TPtrC p2 = TPtrC16(reinterpret_cast<const TUint16 *>(data2), length2); + return p1.CompareC(p2); + #elif defined(Q_OS_UNIX) ++# if defined(QT_USE_ICU) ++ int res; ++ if (qt_ucol_strcoll(data1, length1, data2, length2, &res)) { ++ if (res == 0) ++ res = ucstrcmp(data1, length1, data2, length2); ++ return res; ++ } // else fall through ++# endif + // declared in <string.h> + int delta = strcoll(toLocal8Bit_helper(data1, length1), toLocal8Bit_helper(data2, length2)); + if (delta == 0) +@@ -4943,6 +4958,15 @@ QString QString::toLower() const + if (!d->size) + return *this; + ++#ifdef QT_USE_ICU ++ { ++ QString result; ++ if (qt_u_strToLower(*this, &result, QLocale())) ++ return result; ++ // else fall through and use Qt's toUpper ++ } ++#endif ++ + const ushort *e = d->data + d->size; + + // this avoids one out of bounds check in the loop +@@ -5034,6 +5058,15 @@ QString QString::toUpper() const + if (!d->size) + return *this; + ++#ifdef QT_USE_ICU ++ { ++ QString result; ++ if (qt_u_strToUpper(*this, &result, QLocale())) ++ return result; ++ // else fall through and use Qt's toUpper ++ } ++#endif ++ + const ushort *e = d->data + d->size; + + // this avoids one out of bounds check in the loop +diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri +index d81ab04..46c39f3 100644 +--- a/src/corelib/tools/tools.pri ++++ b/src/corelib/tools/tools.pri +@@ -92,6 +92,11 @@ else:SOURCES += tools/qelapsedtimer_generic.cpp + contains(QT_CONFIG, zlib):include($$PWD/../../3rdparty/zlib.pri) + else:include($$PWD/../../3rdparty/zlib_dependency.pri) + ++contains(QT_CONFIG,icu) { ++ SOURCES += tools/qlocale_icu.cpp ++ DEFINES += QT_USE_ICU ++} ++ + DEFINES += HB_EXPORT=Q_CORE_EXPORT + INCLUDEPATH += ../3rdparty/harfbuzz/src + HEADERS += ../3rdparty/harfbuzz/src/harfbuzz.h +diff --git a/tests/auto/qchar/qchar.pro b/tests/auto/qchar/qchar.pro +index 3813e4e..d991365 100644 +--- a/tests/auto/qchar/qchar.pro ++++ b/tests/auto/qchar/qchar.pro +@@ -13,3 +13,5 @@ symbian: { + } else { + DEFINES += SRCDIR=\\\"$$PWD/\\\" + } ++ ++contains(QT_CONFIG,icu):DEFINES += QT_USE_ICU +diff --git a/tests/auto/qchar/tst_qchar.cpp b/tests/auto/qchar/tst_qchar.cpp +index 45dd7eb..514a836 100644 +--- a/tests/auto/qchar/tst_qchar.cpp ++++ b/tests/auto/qchar/tst_qchar.cpp +@@ -103,7 +103,8 @@ tst_QChar::~tst_QChar() + { } + + void tst_QChar::initTestCase() +-{ } ++{ ++} + + void tst_QChar::cleanupTestCase() + { } +@@ -114,6 +115,7 @@ void tst_QChar::init() + int argc = 0; + app = new QCoreApplication(argc, NULL); + #endif ++ QLocale::setDefault(QLocale::C); + } + + void tst_QChar::cleanup() +@@ -143,9 +145,36 @@ void tst_QChar::toUpper() + QVERIFY(QChar::toUpper((uint)0x1c8) == 0x1c7); + QVERIFY(QChar::toUpper((uint)0x1c9) == 0x1c7); + +- QVERIFY(QChar::toUpper((uint)0x10400) == 0x10400); +- QVERIFY(QChar::toUpper((uint)0x10428) == 0x10400); ++ QCOMPARE(QChar::toUpper((uint)0x10400), 0x10400u); ++ QCOMPARE(QChar::toUpper((uint)0x10428), 0x10400u); ++ ++#ifdef QT_USE_ICU ++ QCOMPARE(QChar('i').toUpper(), QChar('I')); ++ QCOMPARE(QChar::toUpper(ushort('i')), ushort('I')); ++ QCOMPARE(QChar::toUpper(uint('i')), uint('I')); ++ ++ QLocale::setDefault(QLocale(QLocale::Turkish, QLocale::Turkey)); ++ ++ // in Turkish locale, upper-caseing a 'i' will result in a capital I plus dot (0x0130) ++ QCOMPARE(QChar('i').toUpper(), QChar(0x0130u)); ++ QCOMPARE(QChar::toUpper(ushort('i')), ushort(0x0130u)); ++ QCOMPARE(QChar::toUpper(uint('i')), 0x0130u); ++ ++ // upper-casing a lower-case i without dot (0x0131) will result in 'I' ++ QCOMPARE(QChar(0x0131u).toUpper(), QChar('I')); ++ QCOMPARE(QChar::toUpper(ushort(0x0131u)), ushort('I')); ++ QCOMPARE(QChar::toUpper(uint(0x0131u)), uint('I')); ++ ++ // upper-casing an upper-case 0x0130 should do nothing ++ QCOMPARE(QChar(0x0130u).toUpper(), QChar(0x0130u)); ++ QCOMPARE(QChar::toUpper(ushort(0x0130u)), ushort(0x0130u)); ++ QCOMPARE(QChar::toUpper(uint(0x0130u)), uint(0x0130u)); + ++ // upper-casing an upper-case I should do nothing ++ QCOMPARE(QChar('I').toUpper(), QChar('I')); ++ QCOMPARE(QChar::toUpper(ushort('I')), ushort('I')); ++ QCOMPARE(QChar::toUpper(uint('I')), uint('I')); ++#endif + } + + void tst_QChar::toLower() +@@ -170,6 +199,34 @@ void tst_QChar::toLower() + + QVERIFY(QChar::toLower((uint)0x10400) == 0x10428); + QVERIFY(QChar::toLower((uint)0x10428) == 0x10428); ++ ++#ifdef QT_USE_ICU ++ QCOMPARE(QChar('I').toLower(), QChar('i')); ++ QCOMPARE(QChar::toLower(ushort('I')), ushort('i')); ++ QCOMPARE(QChar::toLower(uint('I')), uint('i')); ++ ++ QLocale::setDefault(QLocale(QLocale::Turkish, QLocale::Turkey)); ++ ++ // in turkish locale, lower-casing an 'I' will result with a lower-case i without dot (0x0131) ++ QCOMPARE(QChar('I').toLower(), QChar(0x0131u)); ++ QCOMPARE(QChar::toLower(ushort('I')), ushort(0x0131u)); ++ QCOMPARE(QChar::toLower(uint('I')), uint(0x0131u)); ++ ++ // lower-casing a captial I with dot (0x0130) will result in 'i' ++ QCOMPARE(QChar(0x0130u).toLower(), QChar('i')); ++ QCOMPARE(QChar::toLower(ushort(0x0130u)), ushort('i')); ++ QCOMPARE(QChar::toLower(uint(0x0130u)), uint('i')); ++ ++ // lower-casing a lower-case i should do nothing ++ QCOMPARE(QChar('i').toLower(), QChar('i')); ++ QCOMPARE(QChar::toLower(ushort('i')), ushort('i')); ++ QCOMPARE(QChar::toLower(uint('i')), uint('i')); ++ ++ // lower-casing a lower-case i without dot (0x0131) should do nothing ++ QCOMPARE(QChar(0x0131u).toLower(), QChar(0x0131u)); ++ QCOMPARE(QChar::toLower(ushort(0x0131u)), ushort(0x0131u)); ++ QCOMPARE(QChar::toLower(uint(0x0131u)), uint(0x0131u)); ++#endif + } + + void tst_QChar::toTitle() +diff --git a/tests/auto/qstring/qstring.pro b/tests/auto/qstring/qstring.pro +index ed758c6..92dd755 100644 +--- a/tests/auto/qstring/qstring.pro ++++ b/tests/auto/qstring/qstring.pro +@@ -6,3 +6,5 @@ symbian:LIBS += -llibm + QT = core + + DEFINES += QT_NO_CAST_TO_ASCII ++ ++contains(QT_CONFIG,icu):DEFINES += QT_USE_ICU +diff --git a/tests/auto/qstring/tst_qstring.cpp b/tests/auto/qstring/tst_qstring.cpp +index ecae3d8..6baf9fc 100644 +--- a/tests/auto/qstring/tst_qstring.cpp ++++ b/tests/auto/qstring/tst_qstring.cpp +@@ -210,6 +210,8 @@ private slots: + void task262677remove(); + void QTBUG10404_compareRef(); + void QTBUG9281_arg_locale(); ++ ++ void toUpperLower_icu(); + }; + + typedef QList<int> IntList; +@@ -1544,6 +1546,11 @@ void tst_QString::toUpper() + QCOMPARE( lower.toUpper(), upper); + + ++#ifdef QT_USE_ICU ++ // test doesn't work with ICU support, since QChar is unaware of any locale ++ QEXPECT_FAIL("", "test doesn't work with ICU support, since QChar is unaware of any locale", Continue); ++ QVERIFY(false); ++#else + for (int i = 0; i < 65536; ++i) { + QString str(1, QChar(i)); + QString upper = str.toUpper(); +@@ -1551,6 +1558,7 @@ void tst_QString::toUpper() + if (upper.length() == 1) + QVERIFY(upper == QString(1, QChar(i).toUpper())); + } ++#endif + } + + void tst_QString::toLower() +@@ -1582,6 +1590,11 @@ void tst_QString::toLower() + upper += QChar(QChar::lowSurrogate(0x10400)); + QCOMPARE( upper.toLower(), lower); + ++#ifdef QT_USE_ICU ++ // test doesn't work with ICU support, since QChar is unaware of any locale ++ QEXPECT_FAIL("", "test doesn't work with ICU support, since QChar is unaware of any locale", Continue); ++ QVERIFY(false); ++#else + for (int i = 0; i < 65536; ++i) { + QString str(1, QChar(i)); + QString lower = str.toLower(); +@@ -1589,6 +1602,7 @@ void tst_QString::toLower() + if (lower.length() == 1) + QVERIFY(str.toLower() == QString(1, QChar(i).toLower())); + } ++#endif + } + + void tst_QString::trimmed() +@@ -4200,6 +4214,8 @@ void tst_QString::localeAwareCompare() + + #elif defined (Q_WS_MAC) + QSKIP("Setting the locale is not supported on OS X (you can set the C locale, but that won't affect CFStringCompare which is used to compare strings)", SkipAll); ++#elif defined(QT_USE_ICU) ++ QLocale::setDefault(QLocale(locale)); + #else + if (!locale.isEmpty()) { + const char *newLocale = setlocale(LC_ALL, locale.toLatin1()); +@@ -4211,6 +4227,11 @@ void tst_QString::localeAwareCompare() + } + #endif + ++#ifdef QT_USE_ICU ++ // ### for c1, ICU disagrees with libc on how to compare ++ QEXPECT_FAIL("c1", "ICU disagrees with test", Abort); ++#endif ++ + int testres = QString::localeAwareCompare(s1, s2); + if (result < 0) { + QVERIFY(testres < 0); +@@ -4912,6 +4933,40 @@ void tst_QString::QTBUG9281_arg_locale() + QLocale::setDefault(QLocale::C); + } + ++void tst_QString::toUpperLower_icu() ++{ ++#ifndef QT_USE_ICU ++ QSKIP("Qt was built without ICU support", QTest::SkipAll); ++#endif ++ ++ QString s = QString::fromLatin1("i"); ++ ++ QCOMPARE(s.toUpper(), QString::fromLatin1("I")); ++ QCOMPARE(s.toLower(), QString::fromLatin1("i")); ++ ++ QLocale::setDefault(QLocale(QLocale::Turkish, QLocale::Turkey)); ++ ++ // turkish locale has a capital I with a dot (U+0130, utf8 c4b0) ++ ++ QCOMPARE(s.toUpper(), QString::fromUtf8("\xc4\xb0")); ++ QCOMPARE(QString::fromUtf8("\xc4\xb0").toLower(), s); ++ ++ // nothing should happen here ++ QCOMPARE(s.toLower(), s); ++ QCOMPARE(QString::fromLatin1("I").toUpper(), QString::fromLatin1("I")); ++ ++ // U+0131, utf8 c4b1 is the lower-case i without a dot ++ QString sup = QString::fromUtf8("\xc4\xb1"); ++ ++ QCOMPARE(sup.toUpper(), QString::fromLatin1("I")); ++ QCOMPARE(QString::fromLatin1("I").toLower(), sup); ++ ++ // nothing should happen here ++ QCOMPARE(sup.toLower(), sup); ++ QCOMPARE(QString::fromLatin1("i").toLower(), QString::fromLatin1("i")); ++ ++ // the cleanup function will restore the default locale ++} + + + QTEST_APPLESS_MAIN(tst_QString) |