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 Farsi extends LayoutBase { 29 private static final String LAYOUT_NAME = "farsi"; 30 Farsi(final Locale locale)31 public Farsi(final Locale locale) { 32 super(new FarsiCustomizer(locale), FarsiSymbols.class, FarsiSymbolsShifted.class); 33 } 34 35 @Override getName()36 public String getName() { return LAYOUT_NAME; } 37 38 private static class FarsiCustomizer extends LayoutCustomizer { FarsiCustomizer(final Locale locale)39 FarsiCustomizer(final Locale locale) { super(locale); } 40 41 @Override getAlphabetKey()42 public ExpectedKey getAlphabetKey() { return FARSI_ALPHABET_KEY; } 43 44 @Override getSymbolsKey()45 public ExpectedKey getSymbolsKey() { return FARSI_SYMBOLS_KEY; } 46 47 @Override getBackToSymbolsKey()48 public ExpectedKey getBackToSymbolsKey() { return FARSI_BACK_TO_SYMBOLS_KEY; } 49 50 @Override getCurrencyKey()51 public ExpectedKey getCurrencyKey() { return CURRENCY_RIAL; } 52 53 @Override getOtherCurrencyKeys()54 public ExpectedKey[] getOtherCurrencyKeys() { 55 return SymbolsShifted.CURRENCIES_OTHER_GENERIC; 56 } 57 58 @Override getLeftShiftKeys(final boolean isPhone)59 public ExpectedKey[] getLeftShiftKeys(final boolean isPhone) { 60 return EMPTY_KEYS; 61 } 62 63 @Override getRightShiftKeys(final boolean isPhone)64 public ExpectedKey[] getRightShiftKeys(final boolean isPhone) { 65 return EMPTY_KEYS; 66 } 67 68 @Override getKeysLeftToSpacebar(final boolean isPhone)69 public ExpectedKey[] getKeysLeftToSpacebar(final boolean isPhone) { 70 if (isPhone) { 71 // U+060C: "،" ARABIC COMMA 72 return joinKeys(key("\u060C", SETTINGS_KEY)); 73 } 74 // U+060C: "،" ARABIC COMMA 75 // U+061F: "؟" ARABIC QUESTION MARK 76 // U+061B: "؛" ARABIC SEMICOLON 77 return joinKeys(key("\u060C", joinMoreKeys( 78 ":", "!", "\u061F", "\u061B", "-", RtlSymbols.DOUBLE_ANGLE_QUOTES_LR_RTL, 79 SETTINGS_KEY))); 80 } 81 82 @Override getKeysRightToSpacebar(final boolean isPhone)83 public ExpectedKey[] getKeysRightToSpacebar(final boolean isPhone) { 84 if (isPhone) { 85 return super.getKeysRightToSpacebar(isPhone); 86 } 87 return joinKeys(key(".", getPunctuationMoreKeys(isPhone))); 88 } 89 90 @Override getSpaceKeys(final boolean isPhone)91 public ExpectedKey[] getSpaceKeys(final boolean isPhone) { 92 return joinKeys(LANGUAGE_SWITCH_KEY, SPACE_KEY, key(ZWNJ_KEY, ZWJ_KEY)); 93 } 94 95 @Override getPunctuationMoreKeys(final boolean isPhone)96 public ExpectedKey[] getPunctuationMoreKeys(final boolean isPhone) { 97 return FARSI_DIACRITICS; 98 } 99 100 // U+0627: "ا" ARABIC LETTER ALEF 101 // U+200C: ZERO WIDTH NON-JOINER 102 // U+0628: "ب" ARABIC LETTER BEH 103 // U+067E: "پ" ARABIC LETTER PEH 104 private static final ExpectedKey FARSI_ALPHABET_KEY = key( 105 "\u0627\u200C\u0628\u200C\u067E", Constants.CODE_SWITCH_ALPHA_SYMBOL); 106 // U+06F3: "۳" EXTENDED ARABIC-INDIC DIGIT THREE 107 // U+06F2: "۲" EXTENDED ARABIC-INDIC DIGIT TWO 108 // U+06F1: "۱" EXTENDED ARABIC-INDIC DIGIT ONE 109 // U+061F: "؟" ARABIC QUESTION MARK 110 private static final ExpectedKey FARSI_SYMBOLS_KEY = key( 111 "\u06F3\u06F2\u06F1\u061F", Constants.CODE_SWITCH_ALPHA_SYMBOL); 112 private static final ExpectedKey FARSI_BACK_TO_SYMBOLS_KEY = key( 113 "\u06F3\u06F2\u06F1\u061F", Constants.CODE_SHIFT); 114 // U+FDFC: "﷼" RIAL SIGN 115 private static final ExpectedKey CURRENCY_RIAL = key("\uFDFC", 116 Symbols.CURRENCY_GENERIC_MORE_KEYS); 117 private static final ExpectedKey[] FARSI_DIACRITICS = { 118 // U+0655: "ٕ" ARABIC HAMZA BELOW 119 // U+0652: "ْ" ARABIC SUKUN 120 // U+0651: "ّ" ARABIC SHADDA 121 // U+064C: "ٌ" ARABIC DAMMATAN 122 // U+064D: "ٍ" ARABIC KASRATAN 123 // U+064B: "ً" ARABIC FATHATAN 124 // U+0654: "ٔ" ARABIC HAMZA ABOVE 125 // U+0656: "ٖ" ARABIC SUBSCRIPT ALEF 126 // U+0670: "ٰ" ARABIC LETTER SUPERSCRIPT ALEF 127 // U+0653: "ٓ" ARABIC MADDAH ABOVE 128 // U+064F: "ُ" ARABIC DAMMA 129 // U+0650: "ِ" ARABIC KASRA 130 // U+064E: "َ" ARABIC FATHA 131 // U+0640: "ـ" ARABIC TATWEEL 132 moreKey(" \u0655", "\u0655"), moreKey(" \u0652", "\u0652"), 133 moreKey(" \u0651", "\u0651"), moreKey(" \u064C", "\u064C"), 134 moreKey(" \u064D", "\u064D"), moreKey(" \u064B", "\u064B"), 135 moreKey(" \u0654", "\u0654"), moreKey(" \u0656", "\u0656"), 136 moreKey(" \u0670", "\u0670"), moreKey(" \u0653", "\u0653"), 137 moreKey(" \u064F", "\u064F"), moreKey(" \u0650", "\u0650"), 138 moreKey(" \u064E", "\u064E"), moreKey("\u0640\u0640\u0640", "\u0640") 139 }; 140 } 141 142 @Override getCommonAlphabetLayout(final boolean isPhone)143 ExpectedKey[][] getCommonAlphabetLayout(final boolean isPhone) { 144 if (isPhone) { 145 return ALPHABET_COMMON; 146 } 147 final ExpectedKeyboardBuilder builder = new ExpectedKeyboardBuilder(ALPHABET_COMMON); 148 // U+0622: "آ" ARABIC LETTER ALEF WITH MADDA ABOVE 149 builder.insertKeysAtRow(3, 10, "\u0622"); 150 return builder.build(); 151 } 152 153 @Override getCommonAlphabetShiftLayout(final boolean isPhone, final int elementId)154 ExpectedKey[][] getCommonAlphabetShiftLayout(final boolean isPhone, final int elementId) { 155 return null; 156 } 157 158 private static final ExpectedKey[][] ALPHABET_COMMON = new ExpectedKeyboardBuilder() 159 .setKeysOfRow(1, 160 // U+0636: "ض" ARABIC LETTER DAD 161 // U+06F1: "۱" EXTENDED ARABIC-INDIC DIGIT ONE 162 key("\u0636", joinMoreKeys("\u06F1", "1")), 163 // U+0635: "ص" ARABIC LETTER SAD 164 // U+06F2: "۲" EXTENDED ARABIC-INDIC DIGIT TWO 165 key("\u0635", joinMoreKeys("\u06F2", "2")), 166 // U+062B: "ث" ARABIC LETTER THEH 167 // U+06F3: "۳" EXTENDED ARABIC-INDIC DIGIT THREE 168 key("\u062B", joinMoreKeys("\u06F3", "3")), 169 // U+0642: "ق" ARABIC LETTER QAF 170 // U+06F4: "۴" EXTENDED ARABIC-INDIC DIGIT FOUR 171 key("\u0642", joinMoreKeys("\u06F4", "4")), 172 // U+0641: "ف" ARABIC LETTER FEH 173 // U+06F5: "۵" EXTENDED ARABIC-INDIC DIGIT FIVE 174 key("\u0641", joinMoreKeys("\u06F5", "5")), 175 // U+063A: "غ" ARABIC LETTER GHAIN 176 // U+06F6: "۶" EXTENDED ARABIC-INDIC DIGIT SIX 177 key("\u063A", joinMoreKeys("\u06F6", "6")), 178 // U+0639: "ع" ARABIC LETTER AIN 179 // U+06F7: "۷" EXTENDED ARABIC-INDIC DIGIT SEVEN 180 key("\u0639", joinMoreKeys("\u06F7", "7")), 181 // U+0647: "ه" ARABIC LETTER HEH 182 // U+FEEB: "ﻫ" ARABIC LETTER HEH INITIAL FORM 183 // U+0647/U+200D: ARABIC LETTER HEH + ZERO WIDTH JOINER 184 // U+0647/U+0654: ARABIC LETTER HEH + ARABIC HAMZA ABOVE 185 // U+0629: "ة" ARABIC LETTER TEH MARBUTA 186 // U+06F8: "۸" EXTENDED ARABIC-INDIC DIGIT EIGHT 187 key("\u0647", joinMoreKeys(moreKey("\uFEEB", "\u0647\u200D"), "\u0647\u0654", 188 "\u0629", "\u06F8", "8")), 189 // U+062E: "خ" ARABIC LETTER KHAH 190 // U+06F9: "۹" EXTENDED ARABIC-INDIC DIGIT NINE 191 key("\u062E", joinMoreKeys("\u06F9", "9")), 192 // U+062D: "ح" ARABIC LETTER HAH 193 // U+06F0: "۰" EXTENDED ARABIC-INDIC DIGIT ZERO 194 key("\u062D", joinMoreKeys("\u06F0", "0")), 195 // U+062C: "ج" ARABIC LETTER JEEM 196 "\u062C") 197 .setKeysOfRow(2, 198 // U+0634: "ش" ARABIC LETTER SHEEN 199 // U+0633: "س" ARABIC LETTER SEEN 200 "\u0634", "\u0633", 201 // U+06CC: "ی" ARABIC LETTER FARSI YEH 202 // U+0626: "ئ" ARABIC LETTER YEH WITH HAMZA ABOVE 203 // U+064A: "ي" ARABIC LETTER YEH 204 // U+FBE8: "ﯨ" ARABIC LETTER UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA INITIAL FORM 205 // U+0649: "ى" ARABIC LETTER ALEF MAKSURA 206 key("\u06CC", joinMoreKeys("\u0626", "\u064A", moreKey("\uFBE8", "\u0649"))), 207 // U+0628: "ب" ARABIC LETTER BEH 208 // U+0644: "ل" ARABIC LETTER LAM 209 "\u0628", "\u0644", 210 // U+0627: "ا" ARABIC LETTER ALEF 211 // U+0671: "ٱ" ARABIC LETTER ALEF WASLA 212 // U+0621: "ء" ARABIC LETTER HAMZA 213 // U+0622: "آ" ARABIC LETTER ALEF WITH MADDA ABOVE 214 // U+0623: "أ" ARABIC LETTER ALEF WITH HAMZA ABOVE 215 // U+0625: "إ" ARABIC LETTER ALEF WITH HAMZA BELOW 216 key("\u0627", joinMoreKeys("\u0671", "\u0621", "\u0622", "\u0623", "\u0625")), 217 // U+062A: "ت" ARABIC LETTER TEH 218 // U+0629: "ة": ARABIC LETTER TEH MARBUTA 219 key("\u062A", moreKey("\u0629")), 220 // U+0646: "ن" ARABIC LETTER NOON 221 // U+0645: "م" ARABIC LETTER MEEM 222 "\u0646", "\u0645", 223 // U+06A9: "ک" ARABIC LETTER KEHEH 224 // U+0643: "ك" ARABIC LETTER KAF 225 key("\u06A9", moreKey("\u0643")), 226 // U+06AF: "گ" ARABIC LETTER GAF 227 "\u06AF") 228 .setKeysOfRow(3, 229 // U+0638: "ظ" ARABIC LETTER ZAH 230 // U+0637: "ط" ARABIC LETTER TAH 231 // U+0698: "ژ" ARABIC LETTER JEH 232 // U+0632: "ز" ARABIC LETTER ZAIN 233 // U+0631: "ر" ARABIC LETTER REH 234 // U+0630: "ذ" ARABIC LETTER THAL 235 // U+062F: "د" ARABIC LETTER DAL 236 // U+067E: "پ" ARABIC LETTER PEH 237 "\u0638", "\u0637", "\u0698", "\u0632", "\u0631", "\u0630", "\u062F", "\u067E", 238 // U+0648: "و" ARABIC LETTER WAW 239 // U+0624: "ؤ" ARABIC LETTER WAW WITH HAMZA ABOVE 240 key("\u0648", moreKey("\u0624")), 241 // U+0686: "چ" ARABIC LETTER TCHEH 242 "\u0686") 243 .build(); 244 245 private static class FarsiSymbols extends RtlSymbols { FarsiSymbols(final LayoutCustomizer customizer)246 public FarsiSymbols(final LayoutCustomizer customizer) { 247 super(customizer); 248 } 249 250 @Override getLayout(final boolean isPhone)251 public ExpectedKey[][] getLayout(final boolean isPhone) { 252 return new ExpectedKeyboardBuilder(super.getLayout(isPhone)) 253 // U+06F1: "۱" EXTENDED ARABIC-INDIC DIGIT ONE 254 // U+00B9: "¹" SUPERSCRIPT ONE 255 // U+00BD: "½" VULGAR FRACTION ONE HALF 256 // U+2153: "⅓" VULGAR FRACTION ONE THIRD 257 // U+00BC: "¼" VULGAR FRACTION ONE QUARTER 258 // U+215B: "⅛" VULGAR FRACTION ONE EIGHTH 259 .replaceKeyOfLabel("1", key("\u06F1", 260 joinMoreKeys("1", "\u00B9", "\u00BD", "\u2153", "\u00BC", "\u215B"))) 261 // U+06F2: "۲" EXTENDED ARABIC-INDIC DIGIT TWO 262 // U+00B2: "²" SUPERSCRIPT TWO 263 // U+2154: "⅔" VULGAR FRACTION TWO THIRDS 264 .replaceKeyOfLabel("2", key("\u06F2", joinMoreKeys("2", "\u00B2", "\u2154"))) 265 // U+06F3: "۳" EXTENDED ARABIC-INDIC DIGIT THREE 266 // U+00B3: "³" SUPERSCRIPT THREE 267 // U+00BE: "¾" VULGAR FRACTION THREE QUARTERS 268 // U+215C: "⅜" VULGAR FRACTION THREE EIGHTHS 269 .replaceKeyOfLabel("3", key("\u06F3", 270 joinMoreKeys("3", "\u00B3", "\u00BE", "\u215C"))) 271 // U+06F4: "۴" EXTENDED ARABIC-INDIC DIGIT FOUR 272 // U+2074: "⁴" SUPERSCRIPT FOUR 273 .replaceKeyOfLabel("4", key("\u06F4", joinMoreKeys("4", "\u2074"))) 274 // U+06F5: "۵" EXTENDED ARABIC-INDIC DIGIT FIVE 275 // U+215D: "⅝" VULGAR FRACTION FIVE EIGHTHS 276 .replaceKeyOfLabel("5", key("\u06F5", joinMoreKeys("5", "\u215D"))) 277 // U+06F6: "۶" EXTENDED ARABIC-INDIC DIGIT SIX 278 .replaceKeyOfLabel("6", key("\u06F6", moreKey("6"))) 279 // U+06F7: "۷" EXTENDED ARABIC-INDIC DIGIT SEVEN 280 // U+215E: "⅞" VULGAR FRACTION SEVEN EIGHTHS 281 .replaceKeyOfLabel("7", key("\u06F7", joinMoreKeys("7", "\u215E"))) 282 // U+06F8: "۸" EXTENDED ARABIC-INDIC DIGIT EIGHT 283 .replaceKeyOfLabel("8", key("\u06F8", moreKey("8"))) 284 // U+06F9: "۹" EXTENDED ARABIC-INDIC DIGIT NINE 285 .replaceKeyOfLabel("9", key("\u06F9", moreKey("9"))) 286 // U+066C: "٬" ARABIC THOUSANDS SEPARATOR 287 .replaceKeyOfLabel("@", key("\u066C", moreKey("@"))) 288 // U+066B: "٫" ARABIC DECIMAL SEPARATOR 289 .replaceKeyOfLabel("#", key("\u066B", moreKey("#"))) 290 // U+06F0: "۰" EXTENDED ARABIC-INDIC DIGIT ZERO 291 // U+066B: "٫" ARABIC DECIMAL SEPARATOR 292 // U+066C: "٬" ARABIC THOUSANDS SEPARATOR 293 // U+207F: "ⁿ" SUPERSCRIPT LATIN SMALL LETTER N 294 // U+2205: "∅" EMPTY SET 295 .replaceKeyOfLabel("0", key("\u06F0", 296 joinMoreKeys("0", "\u066B", "\u066C", "\u207F", "\u2205"))) 297 // U+066A: "٪" ARABIC PERCENT SIGN 298 // U+2030: "‰" PER MILLE SIGN 299 .replaceKeyOfLabel("%", key("\u066A", joinMoreKeys("%", "\u2030"))) 300 // U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK 301 // U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK 302 // U+2264: "≤" LESS-THAN OR EQUAL TO 303 .replaceKeyOfLabel("\"", key("\u00AB", "\u00BB", joinMoreKeys( 304 DOUBLE_QUOTES_9LR, DOUBLE_ANGLE_QUOTES_LR_RTL))) 305 // U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK 306 // U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK 307 // U+2265: "≥" GREATER-THAN EQUAL TO 308 .replaceKeyOfLabel("'", key("\u00BB", "\u00AB", joinMoreKeys( 309 SINGLE_QUOTES_9LR, SINGLE_ANGLE_QUOTES_LR_RTL))) 310 // U+061B: "؛" ARABIC SEMICOLON 311 .replaceKeyOfLabel(";", key("\u061B", moreKey(";"))) 312 // U+061F: "؟" ARABIC QUESTION MARK 313 // U+00BF: "¿" INVERTED QUESTION MARK 314 .replaceKeyOfLabel("?", key("\u061F", joinMoreKeys("?", "\u00BF"))) 315 // U+060C: "،" ARABIC COMMA 316 .replaceKeyOfLabel(",", "\u060C") 317 // U+FD3E: "﴾" ORNATE LEFT PARENTHESIS 318 // U+FD3F: "﴿" ORNATE RIGHT PARENTHESIS 319 .replaceKeyOfLabel("(", key("(", ")", 320 moreKey("\uFD3E", "\uFD3F"), moreKey("<", ">"), moreKey("{", "}"), 321 moreKey("[", "]"))) 322 // U+FD3F: "﴿" ORNATE RIGHT PARENTHESIS 323 // U+FD3E: "﴾" ORNATE LEFT PARENTHESIS 324 .replaceKeyOfLabel(")", key(")", "(", 325 moreKey("\uFD3F", "\uFD3E"), moreKey(">", "<"), moreKey("}", "{"), 326 moreKey("]", "["))) 327 // U+2605: "★" BLACK STAR 328 // U+066D: "٭" ARABIC FIVE POINTED STAR 329 .setMoreKeysOf("*", "\u2605", "\u066D") 330 .build(); 331 } 332 } 333 334 private static class FarsiSymbolsShifted extends RtlSymbolsShifted { FarsiSymbolsShifted(final LayoutCustomizer customizer)335 public FarsiSymbolsShifted(final LayoutCustomizer customizer) { 336 super(customizer); 337 } 338 339 @Override getLayout(final boolean isPhone)340 public ExpectedKey[][] getLayout(final boolean isPhone) { 341 return new ExpectedKeyboardBuilder(super.getLayout(isPhone)) 342 // U+2022: "•" BULLET 343 // U+266A: "♪" EIGHTH NOTE 344 .setMoreKeysOf("\u2022", "\u266A") 345 // U+060C: "،" ARABIC COMMA 346 .replaceKeyOfLabel(",", "\u060C") 347 // U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK 348 // U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK 349 // U+2264: "≤" LESS-THAN OR EQUAL TO 350 .replaceKeyOfLabel("<", key("\u00AB", "\u00BB", 351 moreKey("\u2039", "\u203A"), moreKey("\u2264", "\u2265"), 352 moreKey("<", ">"))) 353 // U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK 354 // U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK 355 // U+2265: "≥" GREATER-THAN EQUAL TO 356 .replaceKeyOfLabel(">", key("\u00BB", "\u00AB", 357 moreKey("\u203A", "\u2039"), moreKey("\u2265", "\u2264"), 358 moreKey(">", "<"))) 359 .build(); 360 } 361 } 362 } 363