2 * Copyright (C) 2006 George Staikos <staikos@kde.org>
3 * Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com>
4 * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
23 #ifndef WTF_UNICODE_QT4_H
24 #define WTF_UNICODE_QT4_H
26 #include "ScriptCodesFromICU.h"
27 #include "UnicodeMacrosFromICU.h"
36 #include <unicode/ubrk.h>
40 namespace QUnicodeTables {
43 ushort line_break_class : 8;
45 ushort combiningClass :8;
47 signed short digitValue : 6; /* 5 needed */
48 ushort unicodeVersion : 4;
49 ushort lowerCaseSpecial : 1;
50 ushort upperCaseSpecial : 1;
51 ushort titleCaseSpecial : 1;
52 ushort caseFoldSpecial : 1; /* currently unused */
53 signed short mirrorDiff : 16;
54 signed short lowerCaseDiff : 16;
55 signed short upperCaseDiff : 16;
56 signed short titleCaseDiff : 16;
57 signed short caseFoldDiff : 16;
59 Q_CORE_EXPORT const Properties * QT_FASTCALL properties(uint ucs4);
60 Q_CORE_EXPORT const Properties * QT_FASTCALL properties(ushort ucs2);
64 // ugly hack to make UChar compatible with JSChar in API/JSStringRef.h
65 #if defined(Q_OS_WIN) || (COMPILER(RVCT) && !OS(LINUX))
66 typedef wchar_t UChar;
68 typedef uint16_t UChar;
72 typedef uint32_t UChar32;
79 LeftToRight = QChar::DirL,
80 RightToLeft = QChar::DirR,
81 EuropeanNumber = QChar::DirEN,
82 EuropeanNumberSeparator = QChar::DirES,
83 EuropeanNumberTerminator = QChar::DirET,
84 ArabicNumber = QChar::DirAN,
85 CommonNumberSeparator = QChar::DirCS,
86 BlockSeparator = QChar::DirB,
87 SegmentSeparator = QChar::DirS,
88 WhiteSpaceNeutral = QChar::DirWS,
89 OtherNeutral = QChar::DirON,
90 LeftToRightEmbedding = QChar::DirLRE,
91 LeftToRightOverride = QChar::DirLRO,
92 RightToLeftArabic = QChar::DirAL,
93 RightToLeftEmbedding = QChar::DirRLE,
94 RightToLeftOverride = QChar::DirRLO,
95 PopDirectionalFormat = QChar::DirPDF,
96 NonSpacingMark = QChar::DirNSM,
97 BoundaryNeutral = QChar::DirBN
100 enum DecompositionType {
101 DecompositionNone = QChar::NoDecomposition,
102 DecompositionCanonical = QChar::Canonical,
103 DecompositionCompat = QChar::Compat,
104 DecompositionCircle = QChar::Circle,
105 DecompositionFinal = QChar::Final,
106 DecompositionFont = QChar::Font,
107 DecompositionFraction = QChar::Fraction,
108 DecompositionInitial = QChar::Initial,
109 DecompositionIsolated = QChar::Isolated,
110 DecompositionMedial = QChar::Medial,
111 DecompositionNarrow = QChar::Narrow,
112 DecompositionNoBreak = QChar::NoBreak,
113 DecompositionSmall = QChar::Small,
114 DecompositionSquare = QChar::Square,
115 DecompositionSub = QChar::Sub,
116 DecompositionSuper = QChar::Super,
117 DecompositionVertical = QChar::Vertical,
118 DecompositionWide = QChar::Wide
123 Mark_NonSpacing = U_MASK(QChar::Mark_NonSpacing),
124 Mark_SpacingCombining = U_MASK(QChar::Mark_SpacingCombining),
125 Mark_Enclosing = U_MASK(QChar::Mark_Enclosing),
126 Number_DecimalDigit = U_MASK(QChar::Number_DecimalDigit),
127 Number_Letter = U_MASK(QChar::Number_Letter),
128 Number_Other = U_MASK(QChar::Number_Other),
129 Separator_Space = U_MASK(QChar::Separator_Space),
130 Separator_Line = U_MASK(QChar::Separator_Line),
131 Separator_Paragraph = U_MASK(QChar::Separator_Paragraph),
132 Other_Control = U_MASK(QChar::Other_Control),
133 Other_Format = U_MASK(QChar::Other_Format),
134 Other_Surrogate = U_MASK(QChar::Other_Surrogate),
135 Other_PrivateUse = U_MASK(QChar::Other_PrivateUse),
136 Other_NotAssigned = U_MASK(QChar::Other_NotAssigned),
137 Letter_Uppercase = U_MASK(QChar::Letter_Uppercase),
138 Letter_Lowercase = U_MASK(QChar::Letter_Lowercase),
139 Letter_Titlecase = U_MASK(QChar::Letter_Titlecase),
140 Letter_Modifier = U_MASK(QChar::Letter_Modifier),
141 Letter_Other = U_MASK(QChar::Letter_Other),
142 Punctuation_Connector = U_MASK(QChar::Punctuation_Connector),
143 Punctuation_Dash = U_MASK(QChar::Punctuation_Dash),
144 Punctuation_Open = U_MASK(QChar::Punctuation_Open),
145 Punctuation_Close = U_MASK(QChar::Punctuation_Close),
146 Punctuation_InitialQuote = U_MASK(QChar::Punctuation_InitialQuote),
147 Punctuation_FinalQuote = U_MASK(QChar::Punctuation_FinalQuote),
148 Punctuation_Other = U_MASK(QChar::Punctuation_Other),
149 Symbol_Math = U_MASK(QChar::Symbol_Math),
150 Symbol_Currency = U_MASK(QChar::Symbol_Currency),
151 Symbol_Modifier = U_MASK(QChar::Symbol_Modifier),
152 Symbol_Other = U_MASK(QChar::Symbol_Other)
156 // FIXME: handle surrogates correctly in all methods
158 inline UChar32 toLower(UChar32 ch)
160 return QChar::toLower(uint32_t(ch));
163 inline int toLower(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
165 const UChar *e = src + srcLength;
166 const UChar *s = src;
170 // this avoids one out of bounds check in the loop
171 if (s < e && QChar(*s).isLowSurrogate()) {
178 while (s < e && (rindex < uint(resultLength) || !r)) {
180 if (QChar(c).isLowSurrogate() && QChar(*(s - 1)).isHighSurrogate())
181 c = QChar::surrogateToUcs4(*(s - 1), c);
182 const QUnicodeTables::Properties *prop = QUnicodeTables::properties(c);
183 if (prop->lowerCaseSpecial) {
188 qstring += QChar(*(s-1));
189 qstring += QChar(*s);
191 qstring = qstring.toLower();
192 for (int i = 0; i < qstring.length(); ++i) {
193 if (rindex >= uint(resultLength)) {
194 needed += qstring.length() - i;
198 r[rindex] = qstring.at(i).unicode();
203 r[rindex] = *s + prop->lowerCaseDiff;
210 *error = (needed != 0);
211 if (rindex < uint(resultLength))
213 return rindex + needed;
216 inline UChar32 toUpper(UChar32 c)
218 return QChar::toUpper(uint32_t(c));
221 inline int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
223 const UChar *e = src + srcLength;
224 const UChar *s = src;
228 // this avoids one out of bounds check in the loop
229 if (s < e && QChar(*s).isLowSurrogate()) {
236 while (s < e && (rindex < resultLength || !r)) {
238 if (QChar(c).isLowSurrogate() && QChar(*(s - 1)).isHighSurrogate())
239 c = QChar::surrogateToUcs4(*(s - 1), c);
240 const QUnicodeTables::Properties *prop = QUnicodeTables::properties(c);
241 if (prop->upperCaseSpecial) {
246 qstring += QChar(*(s-1));
247 qstring += QChar(*s);
249 qstring = qstring.toUpper();
250 for (int i = 0; i < qstring.length(); ++i) {
251 if (rindex >= resultLength) {
252 needed += qstring.length() - i;
256 r[rindex] = qstring.at(i).unicode();
261 r[rindex] = *s + prop->upperCaseDiff;
268 *error = (needed != 0);
269 if (rindex < resultLength)
271 return rindex + needed;
274 inline int toTitleCase(UChar32 c)
276 return QChar::toTitleCase(uint32_t(c));
279 inline UChar32 foldCase(UChar32 c)
281 return QChar::toCaseFolded(uint32_t(c));
284 inline int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
286 // FIXME: handle special casing. Easiest with some low level API in Qt
288 if (resultLength < srcLength) {
292 for (int i = 0; i < srcLength; ++i)
293 result[i] = QChar::toCaseFolded(ushort(src[i]));
297 inline bool isArabicChar(UChar32 c)
299 return c >= 0x0600 && c <= 0x06FF;
302 inline bool isPrintableChar(UChar32 c)
304 const uint test = U_MASK(QChar::Other_Control) |
305 U_MASK(QChar::Other_NotAssigned);
306 return !(U_MASK(QChar::category(uint32_t(c))) & test);
309 inline bool isSeparatorSpace(UChar32 c)
311 return QChar::category(uint32_t(c)) == QChar::Separator_Space;
314 inline bool isPunct(UChar32 c)
316 const uint test = U_MASK(QChar::Punctuation_Connector) |
317 U_MASK(QChar::Punctuation_Dash) |
318 U_MASK(QChar::Punctuation_Open) |
319 U_MASK(QChar::Punctuation_Close) |
320 U_MASK(QChar::Punctuation_InitialQuote) |
321 U_MASK(QChar::Punctuation_FinalQuote) |
322 U_MASK(QChar::Punctuation_Other);
323 return U_MASK(QChar::category(uint32_t(c))) & test;
326 inline bool isLower(UChar32 c)
328 return QChar::category(uint32_t(c)) == QChar::Letter_Lowercase;
331 inline bool hasLineBreakingPropertyComplexContext(UChar32)
333 // FIXME: Implement this to return whether the character has line breaking property SA (Complex Context).
337 inline UChar32 mirroredChar(UChar32 c)
339 return QChar::mirroredChar(uint32_t(c));
342 inline uint8_t combiningClass(UChar32 c)
344 return QChar::combiningClass(uint32_t(c));
347 inline DecompositionType decompositionType(UChar32 c)
349 return (DecompositionType)QChar::decompositionTag(c);
352 inline int umemcasecmp(const UChar* a, const UChar* b, int len)
354 // handle surrogates correctly
355 for (int i = 0; i < len; ++i) {
356 uint c1 = QChar::toCaseFolded(ushort(a[i]));
357 uint c2 = QChar::toCaseFolded(ushort(b[i]));
364 inline Direction direction(UChar32 c)
366 return (Direction)QChar::direction(uint32_t(c));
369 inline CharCategory category(UChar32 c)
371 return (CharCategory) U_MASK(QChar::category(uint32_t(c)));
374 } // namespace Unicode
377 #endif // WTF_UNICODE_QT4_H