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