1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.inputmethod.keyboard.layout; 18 19 import com.android.inputmethod.keyboard.layout.Symbols.RtlSymbols; 20 import com.android.inputmethod.keyboard.layout.SymbolsShifted.RtlSymbolsShifted; 21 import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer; 22 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey; 23 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder; 24 import com.android.inputmethod.latin.common.Constants; 25 26 import java.util.Locale; 27 28 public final class Arabic extends LayoutBase { 29 private static final String LAYOUT_NAME = "arabic"; 30 Arabic(final Locale locale)31 public Arabic(final Locale locale) { 32 super(new ArabicCustomizer(locale), ArabicSymbols.class, ArabicSymbolsShifted.class); 33 } 34 35 @Override getName()36 public String getName() { return LAYOUT_NAME; } 37 38 private static class ArabicCustomizer extends LayoutCustomizer { ArabicCustomizer(final Locale locale)39 ArabicCustomizer(final Locale locale) { super(locale); } 40 41 @Override getAlphabetKey()42 public ExpectedKey getAlphabetKey() { return ARABIC_ALPHABET_KEY; } 43 44 @Override getSymbolsKey()45 public ExpectedKey getSymbolsKey() { return ARABIC_SYMBOLS_KEY; } 46 47 @Override getBackToSymbolsKey()48 public ExpectedKey getBackToSymbolsKey() { return ARABIC_BACK_TO_SYMBOLS_KEY; } 49 50 @Override getDoubleAngleQuoteKeys()51 public ExpectedKey[] getDoubleAngleQuoteKeys() { 52 return RtlSymbols.DOUBLE_ANGLE_QUOTES_LR_RTL; 53 } 54 55 @Override getSingleAngleQuoteKeys()56 public ExpectedKey[] getSingleAngleQuoteKeys() { 57 return RtlSymbols.SINGLE_ANGLE_QUOTES_LR_RTL; 58 } 59 60 @Override getLeftShiftKeys(final boolean isPhone)61 public ExpectedKey[] getLeftShiftKeys(final boolean isPhone) { 62 return EMPTY_KEYS; 63 } 64 65 @Override getRightShiftKeys(final boolean isPhone)66 public ExpectedKey[] getRightShiftKeys(final boolean isPhone) { 67 return EMPTY_KEYS; 68 } 69 70 @Override getKeysLeftToSpacebar(final boolean isPhone)71 public ExpectedKey[] getKeysLeftToSpacebar(final boolean isPhone) { 72 if (isPhone) { 73 // U+060C: "،" ARABIC COMMA 74 return joinKeys(key("\u060C", SETTINGS_KEY)); 75 } 76 // U+060C: "،" ARABIC COMMA 77 // U+061F: "؟" ARABIC QUESTION MARK 78 // U+061B: "؛" ARABIC SEMICOLON 79 return joinKeys(key("\u060C", joinMoreKeys( 80 ":", "!", "\u061F", "\u061B", "-", "\"", "'", SETTINGS_KEY))); 81 } 82 83 @Override getKeysRightToSpacebar(final boolean isPhone)84 public ExpectedKey[] getKeysRightToSpacebar(final boolean isPhone) { 85 if (isPhone) { 86 return super.getKeysRightToSpacebar(isPhone); 87 } 88 // U+060C: "،" ARABIC COMMA 89 // U+061F: "؟" ARABIC QUESTION MARK 90 // U+061B: "؛" ARABIC SEMICOLON 91 return joinKeys(key(".", getPunctuationMoreKeys(isPhone))); 92 } 93 94 @Override getPunctuationMoreKeys(final boolean isPhone)95 public ExpectedKey[] getPunctuationMoreKeys(final boolean isPhone) { 96 return ARABIC_DIACRITICS; 97 } 98 99 // U+0623: "أ" ARABIC LETTER ALEF WITH HAMZA ABOVE 100 // U+200C: ZERO WIDTH NON-JOINER 101 // U+0628: "ب" ARABIC LETTER BEH 102 // U+062C: "ج" ARABIC LETTER JEEM 103 private static final ExpectedKey ARABIC_ALPHABET_KEY = key( 104 "\u0623\u200C\u0628\u200C\u062C", Constants.CODE_SWITCH_ALPHA_SYMBOL); 105 // U+0663: "٣" ARABIC-INDIC DIGIT THREE 106 // U+0662: "٢" ARABIC-INDIC DIGIT TWO 107 // U+0661: "١" ARABIC-INDIC DIGIT ONE 108 // U+061F: "؟" ARABIC QUESTION MARK 109 private static final ExpectedKey ARABIC_SYMBOLS_KEY = key( 110 "\u0663\u0662\u0661\u061F", Constants.CODE_SWITCH_ALPHA_SYMBOL); 111 private static final ExpectedKey ARABIC_BACK_TO_SYMBOLS_KEY = key( 112 "\u0663\u0662\u0661\u061F", Constants.CODE_SHIFT); 113 114 private static final ExpectedKey[] ARABIC_DIACRITICS = { 115 // U+0655: "ٕ" ARABIC HAMZA BELOW 116 // U+0654: "ٔ" ARABIC HAMZA ABOVE 117 // U+0652: "ْ" ARABIC SUKUN 118 // U+064D: "ٍ" ARABIC KASRATAN 119 // U+064C: "ٌ" ARABIC DAMMATAN 120 // U+064B: "ً" ARABIC FATHATAN 121 // U+0651: "ّ" ARABIC SHADDA 122 // U+0656: "ٖ" ARABIC SUBSCRIPT ALEF 123 // U+0670: "ٰ" ARABIC LETTER SUPERSCRIPT ALEF 124 // U+0653: "ٓ" ARABIC MADDAH ABOVE 125 // U+0650: "ِ" ARABIC KASRA 126 // U+064F: "ُ" ARABIC DAMMA 127 // U+064E: "َ" ARABIC FATHA 128 // U+0640: "ـ" ARABIC TATWEEL 129 moreKey(" \u0655", "\u0655"), moreKey(" \u0654", "\u0654"), 130 moreKey(" \u0652", "\u0652"), moreKey(" \u064D", "\u064D"), 131 moreKey(" \u064C", "\u064C"), moreKey(" \u064B", "\u064B"), 132 moreKey(" \u0651", "\u0651"), moreKey(" \u0656", "\u0656"), 133 moreKey(" \u0670", "\u0670"), moreKey(" \u0653", "\u0653"), 134 moreKey(" \u0650", "\u0650"), moreKey(" \u064F", "\u064F"), 135 moreKey(" \u064E", "\u064E"), moreKey("\u0640\u0640\u0640", "\u0640") 136 }; 137 } 138 139 @Override getCommonAlphabetLayout(final boolean isPhone)140 ExpectedKey[][] getCommonAlphabetLayout(final boolean isPhone) { 141 if (isPhone) { 142 return ALPHABET_COMMON; 143 } 144 final ExpectedKeyboardBuilder builder = new ExpectedKeyboardBuilder(ALPHABET_COMMON); 145 // U+0626: "ئ" ARABIC LETTER YEH WITH HAMZA ABOVE 146 builder.insertKeysAtRow(3, 2, "\u0626"); 147 return builder.build(); 148 } 149 150 @Override getCommonAlphabetShiftLayout(final boolean isPhone, final int elementId)151 ExpectedKey[][] getCommonAlphabetShiftLayout(final boolean isPhone, final int elementId) { 152 return null; 153 } 154 155 private static final ExpectedKey[][] ALPHABET_COMMON = new ExpectedKeyboardBuilder() 156 .setKeysOfRow(1, 157 // U+0636: "ض" ARABIC LETTER DAD 158 // U+0661: "١" ARABIC-INDIC DIGIT ONE 159 key("\u0636", joinMoreKeys("1", "\u0661")), 160 // U+0635: "ص" ARABIC LETTER SAD 161 // U+0662: "٢" ARABIC-INDIC DIGIT TWO 162 key("\u0635", joinMoreKeys("2", "\u0662")), 163 // U+062B: "ث" ARABIC LETTER THEH 164 // U+0663: "٣" ARABIC-INDIC DIGIT THREE 165 key("\u062B", joinMoreKeys("3", "\u0663")), 166 // U+0642: "ق" ARABIC LETTER QAF 167 // U+0664: "٤" ARABIC-INDIC DIGIT FOUR 168 // U+06A8: "ڨ" ARABIC LETTER QAF WITH THREE DOTS ABOVE 169 key("\u0642", joinMoreKeys("4", "\u0664", "\u06A8")), 170 // U+0641: "ف" ARABIC LETTER FEH 171 // U+0665: "٥" ARABIC-INDIC DIGIT FIVE 172 // U+06A4: "ڤ" ARABIC LETTER VEH 173 // U+06A2: "ڢ" ARABIC LETTER FEH WITH DOT MOVED BELOW 174 // U+06A5: "ڥ" ARABIC LETTER FEH WITH THREE DOTS BELOW 175 key("\u0641", joinMoreKeys("5", "\u0665", "\u06A4", "\u06A2", "\u06A5")), 176 // U+063A: "غ" ARABIC LETTER GHAIN 177 // U+0666: "٦" ARABIC-INDIC DIGIT SIX 178 key("\u063A", joinMoreKeys("6", "\u0666")), 179 // U+0639: "ع" ARABIC LETTER AIN 180 // U+0667: "٧" ARABIC-INDIC DIGIT SEVEN 181 key("\u0639", joinMoreKeys("7", "\u0667")), 182 // U+0647: "ه" ARABIC LETTER HEH 183 // U+0668: "٨" ARABIC-INDIC DIGIT EIGHT 184 // U+FEEB: "ﻫ" ARABIC LETTER HEH INITIAL FORM 185 // U+0647 U+200D: ARABIC LETTER HEH + ZERO WIDTH JOINER 186 key("\u0647", joinMoreKeys("8", "\u0668", moreKey("\uFEEB", "\u0647\u200D"))), 187 // U+062E: "خ" ARABIC LETTER KHAH 188 // U+0669: "٩" ARABIC-INDIC DIGIT NINE 189 key("\u062E", joinMoreKeys("9", "\u0669")), 190 // U+062D: "ح" ARABIC LETTER HAH 191 // U+0660: "٠" ARABIC-INDIC DIGIT ZERO 192 key("\u062D", joinMoreKeys("0", "\u0660")), 193 // U+062C: "ج" ARABIC LETTER JEEM 194 // U+0686: "چ" ARABIC LETTER TCHEH 195 key("\u062C", moreKey("\u0686"))) 196 .setKeysOfRow(2, 197 // U+0634: "ش" ARABIC LETTER SHEEN 198 // U+069C: "ڜ" ARABIC LETTER SEEN WITH THREE DOTS BELOW AND THREE DOTS ABOVE 199 key("\u0634", moreKey("\u069C")), 200 // U+0633: "س" ARABIC LETTER SEEN 201 "\u0633", 202 // U+064A: "ي" ARABIC LETTER YEH 203 // U+0626: "ئ" ARABIC LETTER YEH WITH HAMZA ABOVE 204 // U+0649: "ى" ARABIC LETTER ALEF MAKSURA 205 key("\u064A", joinMoreKeys("\u0626", "\u0649")), 206 // U+0628: "ب" ARABIC LETTER BEH 207 // U+067E: "پ" ARABIC LETTER PEH 208 key("\u0628", moreKey("\u067E")), 209 // U+0644: "ل" ARABIC LETTER LAM 210 // U+FEFB: "ﻻ" ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM 211 // U+0627: "ا" ARABIC LETTER ALEF 212 // U+FEF7: "ﻷ" ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM 213 // U+0623: "أ" ARABIC LETTER ALEF WITH HAMZA ABOVE 214 // U+FEF9: "ﻹ" ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM 215 // U+0625: "إ" ARABIC LETTER ALEF WITH HAMZA BELOW 216 // U+FEF5: "ﻵ" ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM 217 // U+0622: "آ" ARABIC LETTER ALEF WITH MADDA ABOVE 218 key("\u0644", 219 moreKey("\uFEFB", "\u0644\u0627"), moreKey("\uFEF7", "\u0644\u0623"), 220 moreKey("\uFEF9", "\u0644\u0625"), moreKey("\uFEF5", "\u0644\u0622")), 221 // U+0627: "ا" ARABIC LETTER ALEF 222 // U+0622: "آ" ARABIC LETTER ALEF WITH MADDA ABOVE 223 // U+0621: "ء" ARABIC LETTER HAMZA 224 // U+0623: "أ" ARABIC LETTER ALEF WITH HAMZA ABOVE 225 // U+0625: "إ" ARABIC LETTER ALEF WITH HAMZA BELOW 226 // U+0671: "ٱ" ARABIC LETTER ALEF WASLA 227 key("\u0627", joinMoreKeys("\u0622", "\u0621", "\u0623", "\u0625", "\u0671")), 228 // U+062A: "ت" ARABIC LETTER TEH 229 // U+0646: "ن" ARABIC LETTER NOON 230 // U+0645: "م" ARABIC LETTER MEEM 231 "\u062A", "\u0646", "\u0645", 232 // U+0643: "ك" ARABIC LETTER KAF 233 // U+06AF: "گ" ARABIC LETTER GAF 234 // U+06A9: "ک" ARABIC LETTER KEHEH 235 key("\u0643", joinMoreKeys("\u06AF", "\u06A9")), 236 // U+0637: "ط" ARABIC LETTER TAH 237 "\u0637") 238 .setKeysOfRow(3, 239 // U+0630: "ذ" ARABIC LETTER THAL 240 // U+0621: "ء" ARABIC LETTER HAMZA 241 // U+0624: "ؤ" ARABIC LETTER WAW WITH HAMZA ABOVE 242 // U+0631: "ر" ARABIC LETTER REH 243 "\u0630", "\u0621", "\u0624", "\u0631", 244 // U+0649: "ى" ARABIC LETTER ALEF MAKSURA 245 // U+0626: "ئ" ARABIC LETTER YEH WITH HAMZA ABOVE 246 key("\u0649", moreKey("\u0626")), 247 // U+0629: "ة" ARABIC LETTER TEH MARBUTA 248 // U+0648: "و" ARABIC LETTER WAW 249 "\u0629", "\u0648", 250 // U+0632: "ز" ARABIC LETTER ZAIN 251 // U+0698: "ژ" ARABIC LETTER JEH 252 key("\u0632", moreKey("\u0698")), 253 // U+0638: "ظ" ARABIC LETTER ZAH 254 // U+062F: "د" ARABIC LETTER DAL 255 "\u0638", "\u062F") 256 .build(); 257 258 private static class ArabicSymbols extends RtlSymbols { ArabicSymbols(final LayoutCustomizer customizer)259 public ArabicSymbols(final LayoutCustomizer customizer) { 260 super(customizer); 261 } 262 263 @Override getLayout(final boolean isPhone)264 public ExpectedKey[][] getLayout(final boolean isPhone) { 265 return new ExpectedKeyboardBuilder(super.getLayout(isPhone)) 266 // U+0661: "١" ARABIC-INDIC DIGIT ONE 267 // U+00B9: "¹" SUPERSCRIPT ONE 268 // U+00BD: "½" VULGAR FRACTION ONE HALF 269 // U+2153: "⅓" VULGAR FRACTION ONE THIRD 270 // U+00BC: "¼" VULGAR FRACTION ONE QUARTER 271 // U+215B: "⅛" VULGAR FRACTION ONE EIGHTH 272 .replaceKeyOfLabel("1", key("\u0661", 273 joinMoreKeys("1", "\u00B9", "\u00BD", "\u2153", "\u00BC", "\u215B"))) 274 // U+0662: "٢" ARABIC-INDIC DIGIT TWO 275 // U+00B2: "²" SUPERSCRIPT TWO 276 // U+2154: "⅔" VULGAR FRACTION TWO THIRDS 277 .replaceKeyOfLabel("2", key("\u0662", joinMoreKeys("2", "\u00B2", "\u2154"))) 278 // U+0663: "٣" ARABIC-INDIC DIGIT THREE 279 // U+00B3: "³" SUPERSCRIPT THREE 280 // U+00BE: "¾" VULGAR FRACTION THREE QUARTERS 281 // U+215C: "⅜" VULGAR FRACTION THREE EIGHTHS 282 .replaceKeyOfLabel("3", key("\u0663", 283 joinMoreKeys("3", "\u00B3", "\u00BE", "\u215C"))) 284 // U+0664: "٤" ARABIC-INDIC DIGIT FOUR 285 // U+2074: "⁴" SUPERSCRIPT FOUR 286 .replaceKeyOfLabel("4", key("\u0664", joinMoreKeys("4", "\u2074"))) 287 // U+0665: "٥" ARABIC-INDIC DIGIT FIVE 288 // U+215D: "⅝" VULGAR FRACTION FIVE EIGHTHS 289 .replaceKeyOfLabel("5", key("\u0665", joinMoreKeys("5", "\u215D"))) 290 // U+0666: "٦" ARABIC-INDIC DIGIT SIX 291 .replaceKeyOfLabel("6", key("\u0666", moreKey("6"))) 292 // U+0667: "٧" ARABIC-INDIC DIGIT SEVEN 293 // U+215E: "⅞" VULGAR FRACTION SEVEN EIGHTHS 294 .replaceKeyOfLabel("7", key("\u0667", joinMoreKeys("7", "\u215E"))) 295 // U+0668: "٨" ARABIC-INDIC DIGIT EIGHT 296 .replaceKeyOfLabel("8", key("\u0668", moreKey("8"))) 297 // U+0669: "٩" ARABIC-INDIC DIGIT NINE 298 .replaceKeyOfLabel("9", key("\u0669", moreKey("9"))) 299 // U+0660: "٠" ARABIC-INDIC DIGIT ZERO 300 // U+066B: "٫" ARABIC DECIMAL SEPARATOR 301 // U+066C: "٬" ARABIC THOUSANDS SEPARATOR 302 // U+207F: "ⁿ" SUPERSCRIPT LATIN SMALL LETTER N 303 // U+2205: "∅" EMPTY SET 304 .replaceKeyOfLabel("0", key("\u0660", 305 joinMoreKeys("0", "\u066B", "\u066C", "\u207F", "\u2205"))) 306 // U+066A: "٪" ARABIC PERCENT SIGN 307 // U+2030: "‰" PER MILLE SIGN 308 .replaceKeyOfLabel("%", key("\u066A", joinMoreKeys("%", "\u2030"))) 309 // U+061B: "؛" ARABIC SEMICOLON 310 .replaceKeyOfLabel(";", key("\u061B", moreKey(";"))) 311 // U+061F: "؟" ARABIC QUESTION MARK 312 // U+00BF: "¿" INVERTED QUESTION MARK 313 .replaceKeyOfLabel("?", key("\u061F", joinMoreKeys("?", "\u00BF"))) 314 // U+060C: "،" ARABIC COMMA 315 .replaceKeyOfLabel(",", "\u060C") 316 // U+FD3E: "﴾" ORNATE LEFT PARENTHESIS 317 // U+FD3F: "﴿" ORNATE RIGHT PARENTHESIS 318 .replaceKeyOfLabel("(", key("(", ")", 319 moreKey("\uFD3E", "\uFD3F"), moreKey("<", ">"), moreKey("{", "}"), 320 moreKey("[", "]"))) 321 // U+FD3F: "﴿" ORNATE RIGHT PARENTHESIS 322 // U+FD3E: "﴾" ORNATE LEFT PARENTHESIS 323 .replaceKeyOfLabel(")", key(")", "(", 324 moreKey("\uFD3F", "\uFD3E"), moreKey(">", "<"), moreKey("}", "{"), 325 moreKey("]", "["))) 326 // U+2605: "★" BLACK STAR 327 // U+066D: "٭" ARABIC FIVE POINTED STAR 328 .setMoreKeysOf("*", "\u2605", "\u066D") 329 .build(); 330 } 331 } 332 333 private static class ArabicSymbolsShifted extends RtlSymbolsShifted { ArabicSymbolsShifted(final LayoutCustomizer customizer)334 public ArabicSymbolsShifted(final LayoutCustomizer customizer) { 335 super(customizer); 336 } 337 338 @Override getLayout(final boolean isPhone)339 public ExpectedKey[][] getLayout(final boolean isPhone) { 340 return new ExpectedKeyboardBuilder(super.getLayout(isPhone)) 341 // U+2022: "•" BULLET 342 // U+266A: "♪" EIGHTH NOTE 343 .setMoreKeysOf("\u2022", "\u266A") 344 // U+060C: "،" ARABIC COMMA 345 .replaceKeyOfLabel(",", "\u060C") 346 .build(); 347 } 348 } 349 } 350