62static HashMap<String, unsigned>* keyIdentifierList()
63{
64 typedef HashMap<String, unsigned> KeyIdentifierMap;
65 DEFINE_STATIC_LOCAL(KeyIdentifierMap, keyIdentifierList, ());
66 if (keyIdentifierList.isEmpty()) {
67 // "Backspace", "U+0008"
68 keyIdentifierList.set("Backspace", 0x0008);
69 // "Tab", "U+0009"
70 keyIdentifierList.set("Tab", '\t');
71 // "Cancel", "U+0018"
72 keyIdentifierList.set("Cancel", 0x0018);
73 // "Esc", "U+001B"
74 keyIdentifierList.set("Esc", 0x001B);
75 // "Spacebar", "U+0020"
76 keyIdentifierList.set("Spacebar", ' ');
77 // "!", "Exclamation", "U+0021"
78 keyIdentifierList.set("Exclamation", '!');
79 // "DoubleQuote", "U+0022"
80 keyIdentifierList.set("DoubleQuote", '"');
81 // "#", "Hash", "U+0023"
82 keyIdentifierList.set("Hash", '#');
83 // "$", "Dollar", "U+0024"
84 keyIdentifierList.set("Dollar", '$');
85 // "&", "Ampersand", "U+0026"
86 keyIdentifierList.set("Ampersand", '&');
87 // "Apostrophe", "U+0027"
88 keyIdentifierList.set("Apostrophe", '\'');
89 // "(", "LeftParen", "U+0028"
90 keyIdentifierList.set("LeftParen", '(');
91 // ")", "RightParen", "U+0029"
92 keyIdentifierList.set("RightParen", ')');
93 // "*", "Asterisk", "U+002A"
94 keyIdentifierList.set("Asterisk", '*');
95 // "+", "Plus", "U+002B"
96 keyIdentifierList.set("Plus", '+');
97 // "%", "Percent", "U+0025"
98 keyIdentifierList.set("Percent", '%');
99 // ",", "Comma", "U+002C"
100 keyIdentifierList.set("Comma", ',');
101 // "-", "HyphenMinus", "U+002D"
102 keyIdentifierList.set("HypenMinus", '-');
103 // ".", "Period", "U+002E"
104 keyIdentifierList.set("Period", '.');
105 // "/", "Solidus", "U+002F"
106 keyIdentifierList.set("Solidus", '/');
107 // ":", "Colon", "U+003A"
108 keyIdentifierList.set("Colon", ':');
109 // ";", "Semicolon", "U+003B"
110 keyIdentifierList.set("Semicolon", ';');
111 // "LessThan", "U+003C"
112 keyIdentifierList.set("LessThan", '<');
113 // "=", "Equals", "U+003D"
114 keyIdentifierList.set("Equals", '=');
115 // "GreaterThan", "U+003E"
116 keyIdentifierList.set("GreaterThan", '>');
117 // "?", "QuestionMark", "U+003F"
118 keyIdentifierList.set("QuestionMark", '?');
119 // "@", "At", "U+0040"
120 keyIdentifierList.set("At", '@');
121 // "[", "LeftSquareBracket", "U+005B"
122 keyIdentifierList.set("LeftSquareBracket", '[');
123 // "\\", "Backslash", "U+005C"
124 keyIdentifierList.set("Backslash", '\\');
125 // "]", "RightSquareBracket", "U+005D"
126 keyIdentifierList.set("RightSquareBracket", ']');
127 // "^", "Circumflex", "U+005E"
128 keyIdentifierList.set("Circumflex", '^');
129 // "_", "Underscore", "U+005F"
130 keyIdentifierList.set("Underscore", '_');
131 // "`", "Grave", "U+0060"
132 keyIdentifierList.set("Grave", '`');
133 // "{", "LeftCurlyBracket", "U+007B"
134 keyIdentifierList.set("LeftCurlyBracket", '{');
135 // "|", "Pipe", "U+007C"
136 keyIdentifierList.set("Pipe", '|');
137 // "}", "RightCurlyBracket", "U+007D"
138 keyIdentifierList.set("RightCurlyBracket", '}');
139 // "Del", "U+007F"
140 keyIdentifierList.set("Del", 0x007F);
141 // "", "InvertedExclamation", "U+00A1"
142 keyIdentifierList.set("InvertedExclamation", 0x00A1);
143 // "DeadGrave", "U+0300"
144 keyIdentifierList.set("DeadGrave", 0x0300);
145 // "DeadEacute", "U+0301"
146 keyIdentifierList.set("DeadEacute", 0x0301);
147 // "DeadCircumflex", "U+0302"
148 keyIdentifierList.set("DeadCircumflex", 0x0302);
149 // "DeadTilde", "U+0303"
150 keyIdentifierList.set("DeadTilde", 0x0303);
151 // "DeadMacron", "U+0304"
152 keyIdentifierList.set("DeadMacron", 0x0304);
153 // "DeadBreve", "U+0306"
154 keyIdentifierList.set("DeadBreve", 0x0306);
155 // "DeadAboveDot", "U+0307"
156 keyIdentifierList.set("DeadAboveDot", 0x0307);
157 // "DeadUmlaut", "U+0308"
158 keyIdentifierList.set("DeadUmlaut", 0x0308);
159 // "DeadAboveRing", "U+030A"
160 keyIdentifierList.set("DeadAboveRing", 0x030A);
161 // "DeadDoubleacute", "U+030B"
162 keyIdentifierList.set("DeadDoubleacute", 0x030B);
163 // "DeadCaron", "U+030C"
164 keyIdentifierList.set("DeadCaron", 0x030C);
165 // "DeadCedilla", "U+0327"
166 keyIdentifierList.set("DeadCedilla", 0x0327);
167 // "DeadOgonek", "U+0328"
168 keyIdentifierList.set("DeadOgonek", 0x0328);
169 // "DeadIota", "U+0345"
170 keyIdentifierList.set("DeadIota", 0x0345);
171 // "", "Euro", "U+20AC"
172 keyIdentifierList.set("Euro", 0x20AC);
173 // "DeadVoicedSound", "U+3099"
174 keyIdentifierList.set("DeadVoicedSound", 0x3099);
175 // "DeadSemivoicedSound", "U+309A"
176 keyIdentifierList.set("DeadSemivoicedSound", 0x309A);
177 }
178 return &keyIdentifierList;
179}
180
181static bool isValidCharCode(int c)
182{
183 if (c >= ' ' && c <= 127 || c == '\b' || c == '\t' || c == '\r' || c == 24 /* Cancel */ || c == 27 /* Esc */
184 || c == 0x00A1 /* InvertedExclamation */ || c >= 0x0300 /* DeadGrave */ && c <= 0x0308 /* DeadUmlaut */
185 || c == 0x030A /* DeadAboveRing */ || c == 0x030B /* DeadDoubleacute */ || c == 0x030C /* DeadCaron */
186 || c == 0x0327 /* DeadCedilla */ || c == 0x0328 /* DeadOgonek */ || c == 0x0345 /* DeadIota */
187 || c == 0x20AC /* Euro */ || c == 0x3099 /* DeadVoicedSound */ || c == 0x309A /* DeadSemivoicedSound */)
188 return true;
189 return false;
190}
191
192static unsigned charCodeForKeyIdentifier(const String& keyIdentifier)
193{
194 ASSERT(keyIdentifierList());
195 if (keyIdentifier.isEmpty())
196 return 0;
197
198 // Note, this ordering was explicitly chosen so that the platform can override the defaults.
199 HashMap<String, unsigned>* platformKeyIdentifierList = PlatformKeyboardEvent::keyIdentifierList();
200 if (!platformKeyIdentifierList)
201 return 0;
202 HashMap<String, unsigned>::iterator it = platformKeyIdentifierList->find(keyIdentifier);
203 if (it != platformKeyIdentifierList->end())
204 return it->second;
205
206 it = keyIdentifierList()->find(keyIdentifier);
207 if (it != keyIdentifierList()->end())
208 return it->second;
209
210 int firstChar = keyIdentifier.characterStartingAt(0);
211 if (keyIdentifier.length() == 1 && isASCIIPrintable(firstChar))
212 return static_cast<unsigned>(firstChar);
213 if (keyIdentifier.length() == 1)
214 return 0; // Non-printable ASCII character.
215
216 if (keyIdentifier.length() == (2 /* "U+" */ + numUnicodeCodePointHexDigits) && keyIdentifier.substring(0, 2) == "U+") {
217 const UChar* p = keyIdentifier.characters();
218 p += 2; // Skip over "U+", so that we point to the first hex digit.
219 unsigned unicodeValue = 0;
220 unsigned numHexDigits = numUnicodeCodePointHexDigits;
221 while (numHexDigits--)
222 unicodeValue = unicodeValue << 4 | toASCIIHexValue(*(p++));
223 return isValidCharCode(unicodeValue)? unicodeValue : 0;
224 }
225
226 return 0;
227}
228
229static unsigned keyCodeForKeyIdentifier(const String&)
230{
231 return 0;
232}
233