More work on bidi and contextual forms.
[WebKit-https.git] / WebCore / kwq / KWQChar.mm
1 /*
2  * Copyright (C) 2001, 2002 Apple Computer, Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #import "KWQString.h"
27 #import "KWQLogging.h"
28 #import <Foundation/Foundation.h>
29
30 #import <CoreFoundation/CFBidi.h>
31
32
33 static UniChar scratchUniChar;
34
35 static CFMutableStringRef GetScratchUniCharString()
36 {
37     static CFMutableStringRef s = NULL;
38     if (!s)
39         s = CFStringCreateMutableWithExternalCharactersNoCopy(kCFAllocatorDefault, &scratchUniChar, 1, 1, kCFAllocatorNull);
40     return s;
41 }
42
43 const QChar QChar::null;
44
45 bool QChar::isSpace() const
46 {
47     // Without this first quick case, this function was showing up in profiles.
48     if (c <= 0x7F) {
49         return isspace(c);
50     }
51     static CFCharacterSetRef set = CFCharacterSetGetPredefined(kCFCharacterSetWhitespaceAndNewline);
52     return CFCharacterSetIsCharacterMember(set, c);
53 }
54
55 bool QChar::isDigit() const
56 {
57     static CFCharacterSetRef set = CFCharacterSetGetPredefined(kCFCharacterSetDecimalDigit);
58     return CFCharacterSetIsCharacterMember(set, c);
59 }
60
61 bool QChar::isLetter() const
62 {
63     static CFCharacterSetRef set = CFCharacterSetGetPredefined(kCFCharacterSetLetter);
64     return CFCharacterSetIsCharacterMember(set, c);
65 }
66
67 bool QChar::isNumber() const
68 {
69     return isLetterOrNumber() && !isLetter();
70 }
71
72 bool QChar::isLetterOrNumber() const
73 {
74     static CFCharacterSetRef set = CFCharacterSetGetPredefined(kCFCharacterSetAlphaNumeric);
75     return CFCharacterSetIsCharacterMember(set, c);
76 }
77
78 bool QChar::isPunct() const
79 {
80     static CFCharacterSetRef set = CFCharacterSetGetPredefined(kCFCharacterSetPunctuation);
81     return CFCharacterSetIsCharacterMember(set, c);
82 }
83
84 QChar QChar::lower() const
85 {
86     // Without this first quick case, this function was showing up in profiles.
87     if (c <= 0x7F) {
88         return (char)tolower(c);
89     }
90     scratchUniChar = c;
91     CFStringLowercase(GetScratchUniCharString(), NULL);
92     return scratchUniChar;
93 }
94
95 QChar QChar::upper() const
96 {
97     // Without this first quick case, this function was showing up in profiles.
98     if (c <= 0x7F) {
99         return (char)toupper(c);
100     }
101     scratchUniChar = c;
102     CFStringUppercase(GetScratchUniCharString(), NULL);
103     return scratchUniChar;
104 }
105
106 QChar::Direction QChar::direction() const
107 {
108     uint8_t type;
109     QChar::Direction dir = DirL;
110
111      if (c == ' ')
112          return DirWS;
113
114     // Early out for latin1.
115     if (c < 0x7f)
116         return dir;
117         
118     CFUniCharGetBidiCategory (&c, 1, &type);
119     switch (type){
120         case kCFUniCharBiDiPropertyON:
121             dir = DirON;
122             break;
123         case kCFUniCharBiDiPropertyL:
124             dir = DirL;
125             break;
126         case kCFUniCharBiDiPropertyR:
127             dir = DirR;
128             break;
129         case kCFUniCharBiDiPropertyAN:
130             dir = DirAN;
131             break;
132         case kCFUniCharBiDiPropertyEN:
133             dir = DirEN;
134             break;
135         case kCFUniCharBiDiPropertyAL:
136             dir = DirAL;
137             break;
138         case kCFUniCharBiDiPropertyNSM:
139             dir = DirNSM;
140             break;
141         case kCFUniCharBiDiPropertyCS:
142             dir = DirCS;
143             break;
144         case kCFUniCharBiDiPropertyES:
145             dir = DirES;
146             break;
147         case kCFUniCharBiDiPropertyET:
148             dir = DirET;
149             break;
150         case kCFUniCharBiDiPropertyBN:
151             dir = DirBN;
152             break;
153         case kCFUniCharBiDiPropertyS:
154             dir = DirS;
155             break;
156         case kCFUniCharBiDiPropertyWS:
157             dir = DirWS;
158             break;
159         case kCFUniCharBiDiPropertyB:
160             dir = DirB;
161             break;
162         case kCFUniCharBiDiPropertyRLO:
163             dir = DirRLO;
164             break;
165         case kCFUniCharBiDiPropertyRLE:
166             dir = DirRLE;
167             break;
168         case kCFUniCharBiDiPropertyLRO:
169             dir = DirLRO;
170             break;
171         case kCFUniCharBiDiPropertyLRE:
172             dir = DirLRE;
173             break;
174         case kCFUniCharBiDiPropertyPDF:
175             dir = DirPDF;
176             break;
177     }
178     return dir;
179 }
180
181 bool QChar::mirrored() const
182 {
183     // FIXME: unimplemented because we don't do BIDI yet
184     ERROR("not yet implemented");
185     // return whether character should be reversed if text direction is reversed
186     return false;
187 }
188
189 QChar QChar::mirroredChar() const
190 {
191     // FIXME: unimplemented because we don't do BIDI yet
192     ERROR("not yet implemented");
193     // return mirrored character if it is mirrored else return itself
194     return *this;
195 }
196
197 int QChar::digitValue() const
198 {
199     if (c < '0' || c > '9')
200         return -1;
201     else
202         return c - '0';
203 }