diff --git a/src/corelib/tools/qchar.cpp b/src/corelib/tools/qchar.cpp index 3034e430ef..74df59ab5b 100644 --- a/src/corelib/tools/qchar.cpp +++ b/src/corelib/tools/qchar.cpp @@ -1053,33 +1053,48 @@ template static inline T toLowerCase_helper(T uc) { const QUnicodeTables::Properties *p = qGetProp(uc); - if (!p->lowerCaseSpecial) - return uc + p->lowerCaseDiff; - return uc; + if (p->lowerCaseSpecial) { + const ushort *specialCase = specialCaseMap + p->lowerCaseDiff; + if (*specialCase == 1) + return specialCase[1]; + } + return uc + p->lowerCaseDiff; } template static inline T toUpperCase_helper(T uc) { const QUnicodeTables::Properties *p = qGetProp(uc); - if (!p->upperCaseSpecial) - return uc + p->upperCaseDiff; - return uc; + if (p->upperCaseSpecial) { + const ushort *specialCase = specialCaseMap + p->upperCaseDiff; + if (*specialCase == 1) + return specialCase[1]; + } + return uc + p->upperCaseDiff; } template static inline T toTitleCase_helper(T uc) { const QUnicodeTables::Properties *p = qGetProp(uc); - if (!p->titleCaseSpecial) - return uc + p->titleCaseDiff; - return uc; + if (p->titleCaseSpecial) { + const ushort *specialCase = specialCaseMap + p->titleCaseDiff; + if (*specialCase == 1) + return specialCase[1]; + } + return uc + p->titleCaseDiff; } template static inline T toCaseFolded_helper(T uc) { - return uc + qGetProp(uc)->caseFoldDiff; + const QUnicodeTables::Properties *p = qGetProp(uc); + if (p->caseFoldSpecial) { + const ushort *specialCase = specialCaseMap + p->caseFoldDiff; + if (*specialCase == 1) + return specialCase[1]; + } + return uc + p->caseFoldDiff; } /*! diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 65b52f3229..39747aa3e9 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -5263,7 +5263,20 @@ QString QString::toCaseFolded() const prop = qGetProp(*p); } if (prop->caseFoldSpecial) { + const ushort *specialCase = specialCaseMap + prop->caseFoldDiff; + ushort length = *specialCase++; +#if 0 + int pos = pp - s.d->data; + s.resize(s.d->size + length - 1); + pp = s.d->data + pos; + while (length--) + *pp++ = *specialCase++; +#else //### we currently don't support full case foldings + Q_ASSERT(length == 1); + Q_UNUSED(length) + *pp++ = *specialCase; +#endif } else { *pp++ = *p + prop->caseFoldDiff; } diff --git a/src/corelib/tools/qunicodetables_p.h b/src/corelib/tools/qunicodetables_p.h index 0b8115035c..d8f8340673 100644 --- a/src/corelib/tools/qunicodetables_p.h +++ b/src/corelib/tools/qunicodetables_p.h @@ -76,7 +76,7 @@ namespace QUnicodeTables { ushort lowerCaseSpecial : 1; ushort upperCaseSpecial : 1; ushort titleCaseSpecial : 1; - ushort caseFoldSpecial : 1; /* currently unused */ + ushort caseFoldSpecial : 1; signed short mirrorDiff : 16; signed short lowerCaseDiff : 16; signed short upperCaseDiff : 16; diff --git a/util/unicode/main.cpp b/util/unicode/main.cpp index d769176c6f..488026d0d5 100644 --- a/util/unicode/main.cpp +++ b/util/unicode/main.cpp @@ -383,7 +383,7 @@ static const char *property_string = " ushort lowerCaseSpecial : 1;\n" " ushort upperCaseSpecial : 1;\n" " ushort titleCaseSpecial : 1;\n" - " ushort caseFoldSpecial : 1; /* currently unused */\n" + " ushort caseFoldSpecial : 1;\n" " signed short mirrorDiff : 16;\n" " signed short lowerCaseDiff : 16;\n" " signed short upperCaseDiff : 16;\n" @@ -785,10 +785,16 @@ static void readUnicodeData() int upperCase = properties[UD_UpperCase].toInt(&ok, 16); Q_ASSERT(ok); int diff = upperCase - codepoint; - if (qAbs(diff) >= (1<<14)) - qWarning() << "upperCaseDiff exceeded (" << hex << codepoint << "->" << upperCase << ")"; - data.p.upperCaseDiff = diff; - maxUpperCaseDiff = qMax(maxUpperCaseDiff, qAbs(diff)); + if (qAbs(diff) >= (1<<14)) { + qWarning() << "upperCaseDiff exceeded (" << hex << codepoint << "->" << upperCase << "); map it for special case"; + // if the condition below doesn't hold anymore we need to modify our special upper casing code in qchar.cpp + Q_ASSERT(!QChar::requiresSurrogates(codepoint) && !QChar::requiresSurrogates(upperCase)); + data.p.upperCaseSpecial = true; + data.p.upperCaseDiff = appendToSpecialCaseMap(QList() << upperCase); + } else { + data.p.upperCaseDiff = diff; + maxUpperCaseDiff = qMax(maxUpperCaseDiff, qAbs(diff)); + } if (QChar::requiresSurrogates(codepoint) || QChar::requiresSurrogates(upperCase)) { // if the conditions below doesn't hold anymore we need to modify our upper casing code Q_ASSERT(QChar::highSurrogate(codepoint) == QChar::highSurrogate(upperCase)); @@ -799,10 +805,16 @@ static void readUnicodeData() int lowerCase = properties[UD_LowerCase].toInt(&ok, 16); Q_ASSERT(ok); int diff = lowerCase - codepoint; - if (qAbs(diff) >= (1<<14)) - qWarning() << "lowerCaseDiff exceeded (" << hex << codepoint << "->" << lowerCase << ")"; - data.p.lowerCaseDiff = diff; - maxLowerCaseDiff = qMax(maxLowerCaseDiff, qAbs(diff)); + if (qAbs(diff) >= (1<<14)) { + qWarning() << "lowerCaseDiff exceeded (" << hex << codepoint << "->" << lowerCase << "); map it for special case"; + // if the condition below doesn't hold anymore we need to modify our special lower casing code in qchar.cpp + Q_ASSERT(!QChar::requiresSurrogates(codepoint) && !QChar::requiresSurrogates(lowerCase)); + data.p.lowerCaseSpecial = true; + data.p.lowerCaseDiff = appendToSpecialCaseMap(QList() << lowerCase); + } else { + data.p.lowerCaseDiff = diff; + maxLowerCaseDiff = qMax(maxLowerCaseDiff, qAbs(diff)); + } if (QChar::requiresSurrogates(codepoint) || QChar::requiresSurrogates(lowerCase)) { // if the conditions below doesn't hold anymore we need to modify our lower casing code Q_ASSERT(QChar::highSurrogate(codepoint) == QChar::highSurrogate(lowerCase)); @@ -816,10 +828,16 @@ static void readUnicodeData() int titleCase = properties[UD_TitleCase].toInt(&ok, 16); Q_ASSERT(ok); int diff = titleCase - codepoint; - if (qAbs(diff) >= (1<<14)) - qWarning() << "titleCaseDiff exceeded (" << hex << codepoint << "->" << titleCase << ")"; - data.p.titleCaseDiff = diff; - maxTitleCaseDiff = qMax(maxTitleCaseDiff, qAbs(diff)); + if (qAbs(diff) >= (1<<14)) { + qWarning() << "titleCaseDiff exceeded (" << hex << codepoint << "->" << titleCase << "); map it for special case"; + // if the condition below doesn't hold anymore we need to modify our special title casing code in qchar.cpp + Q_ASSERT(!QChar::requiresSurrogates(codepoint) && !QChar::requiresSurrogates(titleCase)); + data.p.titleCaseSpecial = true; + data.p.titleCaseDiff = appendToSpecialCaseMap(QList() << titleCase); + } else { + data.p.titleCaseDiff = diff; + maxTitleCaseDiff = qMax(maxTitleCaseDiff, qAbs(diff)); + } if (QChar::requiresSurrogates(codepoint) || QChar::requiresSurrogates(titleCase)) { // if the conditions below doesn't hold anymore we need to modify our title casing code Q_ASSERT(QChar::highSurrogate(codepoint) == QChar::highSurrogate(titleCase)); @@ -1355,10 +1373,16 @@ static void readCaseFolding() if (foldMap.size() == 1) { int caseFolded = foldMap.at(0); int diff = caseFolded - codepoint; - if (qAbs(diff) >= (1<<14)) - qWarning() << "caseFoldDiff exceeded (" << hex << codepoint << "->" << caseFolded << ")"; - ud.p.caseFoldDiff = diff; - maxCaseFoldDiff = qMax(maxCaseFoldDiff, qAbs(diff)); + if (qAbs(diff) >= (1<<14)) { + qWarning() << "caseFoldDiff exceeded (" << hex << codepoint << "->" << caseFolded << "); map it for special case"; + // if the condition below doesn't hold anymore we need to modify our special case folding code in qchar.cpp + Q_ASSERT(!QChar::requiresSurrogates(codepoint) && !QChar::requiresSurrogates(caseFolded)); + ud.p.caseFoldSpecial = true; + ud.p.caseFoldDiff = appendToSpecialCaseMap(foldMap); + } else { + ud.p.caseFoldDiff = diff; + maxCaseFoldDiff = qMax(maxCaseFoldDiff, qAbs(diff)); + } if (QChar::requiresSurrogates(codepoint) || QChar::requiresSurrogates(caseFolded)) { // if the conditions below doesn't hold anymore we need to modify our case folding code Q_ASSERT(QChar::highSurrogate(codepoint) == QChar::highSurrogate(caseFolded));