Compare commits

..

1 Commits

Author SHA1 Message Date
Jules Aguillon
6d3dfd0c5a Add 'playpause' key
Sends the KEYCODE_MEDIA_PLAY_PAUSE keyevent.
2024-09-21 21:53:53 +02:00
248 changed files with 1499 additions and 7222 deletions

View File

@@ -13,7 +13,7 @@ jobs:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@v4 uses: actions/checkout@v4
- run: python3 gen_layouts.py - run: python3 gen_layouts.py
- name: "Run 'python3 gen_layouts.py' to update generated files" - name: "Check that the generated 'layouts.xml' is uptodate, otherwise run 'python3 gen_layouts.py'"
run: git diff --exit-code run: git diff --exit-code
check-layouts: check-layouts:
name: check_layout.output name: check_layout.output
@@ -22,5 +22,5 @@ jobs:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@v4 uses: actions/checkout@v4
- run: python3 check_layout.py - run: python3 check_layout.py
- name: "Fix your layout accordingly or run 'python3 check_layout.py' to promote the warnings" - name: "Check that the generated 'check_layout.output' is uptodate, otherwise run 'python3 check_layout.py'"
run: git diff --exit-code run: git diff --exit-code

1
.gitignore vendored
View File

@@ -10,4 +10,3 @@
/build /build
# Directory _build is not used anymore # Directory _build is not used anymore
/_build /_build
/release

View File

@@ -10,13 +10,11 @@
</intent-filter> </intent-filter>
<meta-data android:name="android.view.im" android:resource="@xml/method"/> <meta-data android:name="android.view.im" android:resource="@xml/method"/>
</service> </service>
<activity android:name="juloo.keyboard2.SettingsActivity" android:icon="@mipmap/ic_launcher" android:label="@string/settings_activity_label" android:theme="@style/appTheme" android:exported="true" android:directBootAware="true">
<activity android:name="juloo.keyboard2.SettingsActivity" android:icon="@mipmap/ic_launcher" android:label="@string/settings_activity_label" android:theme="@style/settingsTheme" android:exported="true" android:directBootAware="true">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN"/>
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name="juloo.keyboard2.LauncherActivity" android:icon="@mipmap/ic_launcher" android:theme="@style/appTheme" android:exported="true" android:directBootAware="true"> <activity android:name="juloo.keyboard2.LauncherActivity" android:icon="@mipmap/ic_launcher" android:theme="@style/appTheme" android:exported="true" android:directBootAware="true">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN"/>

View File

@@ -25,7 +25,7 @@ Usage: to apply the symbols located in the corners of each key, slide your finge
| <img src="/fastlane/metadata/android/en-US/images/phoneScreenshots/4.png" alt="Screenshot-4" /> | <img src="/fastlane/metadata/android/en-US/images/phoneScreenshots/5.png" alt="Screenshot-5" /> | <img src="/fastlane/metadata/android/en-US/images/phoneScreenshots/6.png" alt="Screenshot-6" /> | | <img src="/fastlane/metadata/android/en-US/images/phoneScreenshots/4.png" alt="Screenshot-4" /> | <img src="/fastlane/metadata/android/en-US/images/phoneScreenshots/5.png" alt="Screenshot-5" /> | <img src="/fastlane/metadata/android/en-US/images/phoneScreenshots/6.png" alt="Screenshot-6" /> |
## Similar apps ## Similar apps
* [Calculator++](https://git.bubu1.eu/Bubu/android-calculatorpp) - Calculator with a similar UX, swipe to corners for advanced math symbols and operators. * [Calculator++](https://github.com/Bubu/android-calculatorpp) - Calculator with a similar UX, swipe to corners for advanced math symbols and operators. Works up to Android 13 but maybe unmaintained.
## Contributing ## Contributing

Binary file not shown.

View File

@@ -2,33 +2,25 @@ plugins {
id 'com.android.application' version '8.1.1' id 'com.android.application' version '8.1.1'
} }
dependencies {
testImplementation "junit:junit:4.13.2"
}
android { android {
namespace 'juloo.keyboard2' namespace 'juloo.keyboard2'
compileSdk 34 compileSdk 34
defaultConfig { defaultConfig {
applicationId "juloo.keyboard2" applicationId "juloo.keyboard2"
minSdk 21 minSdk 11
targetSdkVersion 35 targetSdkVersion 35
versionCode 46 versionCode 42
versionName "1.30.3" versionName "1.29.1"
} }
sourceSets { sourceSets {
main { main {
manifest.srcFile 'AndroidManifest.xml' manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['srcs/juloo.keyboard2'] java.srcDirs = ['srcs']
res.srcDirs = ['res', 'build/generated-resources'] res.srcDirs = ['res', 'build/generated-resources']
assets.srcDirs = ['assets'] assets.srcDirs = ['assets']
} }
test {
java.srcDirs = ['test']
}
} }
signingConfigs { signingConfigs {
@@ -92,6 +84,9 @@ android {
} }
} }
dependencies {
}
tasks.register('buildKeyboardFont') { tasks.register('buildKeyboardFont') {
println "\nBuilding assets/special_font.ttf" println "\nBuilding assets/special_font.ttf"
mkdir "$buildDir" mkdir "$buildDir"
@@ -134,8 +129,12 @@ tasks.register('genLayoutsList') {
tasks.register('checkKeyboardLayouts') { tasks.register('checkKeyboardLayouts') {
println "\nChecking layouts" println "\nChecking layouts"
exec { exec {
def layouts = new File(projectDir, "srcs/layouts").listFiles().findAll {
it.name.endsWith(".xml")
}
workingDir = projectDir workingDir = projectDir
commandLine("python", "check_layout.py") commandLine("python", "check_layout.py", *layouts)
standardOutput = new FileOutputStream("${projectDir}/check_layout.output")
} }
} }

View File

@@ -1,36 +1,139 @@
arab_alt: Layout includes some ASCII punctuation but not all, missing: !, ", ', +, -, /, :, ;, <, =, >, ?, [, \, ], _, |, ~ # arab_alt
arab_hamvaj_tly: Layout includes some ASCII punctuation but not all, missing: ", %, ', ,, /, ;, <, =, >, ?, [, \, ], _, `, {, |, } Layout includes some ASCII punctuation but not all, missing: !, ", ', +, -, /, :, ;, <, =, >, ?, [, \, ], _, |, ~
arab_pc: Layout includes some ASCII punctuation but not all, missing: !, ', +, ;, ?, \, | 1 warnings
arab_pc_ckb: Layout includes some ASCII punctuation but not all, missing: ", %, ', +, ,, ;, <, =, >, ?, `, |, ~ # arab_hamvaj_tly
arab_pc_ckb_fa: Layout includes some ASCII punctuation but not all, missing: ", #, $, %, &, ', ,, /, ;, ?, @, \, ^, `, |, ~ Layout includes some ASCII punctuation but not all, missing: ", %, ', ,, /, ;, <, =, >, ?, [, \, ], _, `, {, |, }
arab_pc_hindu: Layout includes some ASCII punctuation but not all, missing: !, ', +, ;, ?, \, | Layout doesn't define some important keys, missing: loc esc
arab_pc_ir: Layout includes some ASCII punctuation but not all, missing: ", %, ', ,, /, ;, <, =, >, ?, [, \, ], `, {, |, } 2 warnings
beng_national: Layout includes some ASCII punctuation but not all, missing: $ # arab_pc
beng_provat: Layout includes some ASCII punctuation but not all, missing: $, &, *, ., /, <, >, [, \, ], `, {, |, } Layout includes some ASCII punctuation but not all, missing: !, ', +, ;, ?, \, |
cyrl_yaverti: Layout includes some ASCII punctuation but not all, missing: ~ 1 warnings
cyrl_yqukeng_tj: These keys are now added automatically, unexpected: f11_placeholder, f12_placeholder # arab_pc_ckb
cyrl_yxukeng_os: Layout includes some ASCII punctuation but not all, missing: ", #, $, &, ', @, [, ], ~ Layout includes some ASCII punctuation but not all, missing: ", %, ', +, ,, ., :, ;, <, =, >, ?, `, |, ~
cyrl_yxukeng_os: These keys are now added automatically, unexpected: f11_placeholder, f12_placeholder 1 warnings
deva_alt: Layout includes some ASCII punctuation but not all, missing: #, $, %, &, ', (, ), *, +, ., /, :, <, =, >, [, \, ], ^, _, `, {, |, }, ~ # arab_pc_hindu
deva_alt: Layout doesn't define some important keys, missing: delete Layout includes some ASCII punctuation but not all, missing: !, ', +, ;, ?, \, |
deva_inscript: Duplicate keys: । 1 warnings
deva_inscript: Layout includes some ASCII punctuation but not all, missing: ", $, ', ^, _, `, | # arab_pc_ir
deva_phonetic_in: Duplicate keys: ट Layout includes some ASCII punctuation but not all, missing: ", %, ', ,, /, ;, <, =, >, ?, [, \, ], `, {, |, }
grek_qwerty: Duplicate keys: ; 1 warnings
guj_phonetic_in: Duplicate keys: ટ, ડ # armenian_ph_am
hebr_1_il: Layout includes some ASCII punctuation but not all, missing: (, ), <, >, [, ], {, } 0 warnings
hebr_2_il: Layout includes some ASCII punctuation but not all, missing: (, ), <, >, [, ], {, } # beng_national
kann_kannada: Layout includes some ASCII punctuation but not all, missing: #, $, %, (, ), *, +, /, <, =, >, [, \, ], ^, `, {, |, }, ~ Layout includes some ASCII punctuation but not all, missing: $
latn_bepo_fr: Missing important key, missing: loc capslock 1 warnings
latn_bone: Missing important key, missing: loc capslock # beng_provat
latn_colemak: Some keys contain whitespaces, unexpected: ́ Layout includes some ASCII punctuation but not all, missing: $, &, *, ., /, <, >, [, \, ], `, {, |, }
latn_dvorak: Missing important key, missing: loc capslock 1 warnings
latn_neo2: Layout redefines the bottom row but some important keys are missing, missing: loc switch_clipboard # cyrl_jcuken_ru
latn_qwerty_se: Duplicate keys: !, ', ,, -, ., ? 0 warnings
latn_qwerty_tly: Duplicate keys: a, c, j, q # cyrl_jcuken_uk
latn_qwerty_tly: Missing programming keys, missing: loc esc, loc tab 0 warnings
latn_qwertz_cz_multifunctional: Layout includes some ASCII punctuation but not all, missing: ` # cyrl_lynyertz_sr
latn_qwertz_sk: Layout includes some ASCII punctuation but not all, missing: ` 0 warnings
urdu_phonetic_ur: Duplicate keys: # cyrl_ueishsht
urdu_phonetic_ur: Layout includes some ASCII punctuation but not all, missing: <, >, ?, `, |, ~ 0 warnings
urdu_phonetic_ur: Some keys contain whitespaces, unexpected: # cyrl_yaverti
Layout includes some ASCII punctuation but not all, missing: ~
1 warnings
# deva_alt
Layout includes some ASCII punctuation but not all, missing: #, $, %, &, ', (, ), +, ., /, :, <, =, >, [, \, ], ^, _, `, {, |, }, ~
Layout doesn't define some important keys, missing: loc esc, loc tab
2 warnings
# deva_inscript
Duplicate keys: ।
Layout includes some ASCII punctuation but not all, missing: ", $, ', ^, _, `, |
2 warnings
# grek_qwerty
Duplicate keys: ;
1 warnings
# guj_phonetic_in
Duplicate keys: ટ, ડ
1 warnings
# hang_dubeolsik_kr
Layout doesn't define some important keys, missing: loc esc, loc tab
1 warnings
# hebr_1_il
Layout includes some ASCII punctuation but not all, missing: (, ), <, >, [, ], {, }
1 warnings
# hebr_2_il
Layout includes some ASCII punctuation but not all, missing: (, ), <, >, [, ], {, }
1 warnings
# latn_azerty_fr
0 warnings
# latn_bepo_fr
0 warnings
# latn_bone
Layout doesn't define some important keys, missing: loc esc, loc tab
Layout redefines the bottom row but some important keys are missing, missing: cursor_left, cursor_right, loc compose, loc end, loc home, loc page_down, loc page_up, loc switch_clipboard, loc switch_greekmath, loc voice_typing, switch_backward
2 warnings
# latn_colemak
Some keys contain whitespaces, unexpected: ́
1 warnings
# latn_dvorak
0 warnings
# latn_neo2
Layout redefines the bottom row but some important keys are missing, missing: loc switch_clipboard
1 warnings
# latn_qwerty_br
0 warnings
# latn_qwerty_cz
0 warnings
# latn_qwerty_da
0 warnings
# latn_qwerty_es
0 warnings
# latn_qwerty_gb
0 warnings
# latn_qwerty_hu
0 warnings
# latn_qwerty_jp
0 warnings
# latn_qwerty_lv
0 warnings
# latn_qwerty_no
0 warnings
# latn_qwerty_pl
0 warnings
# latn_qwerty_ro
0 warnings
# latn_qwerty_se
Duplicate keys: !, ', ,, -, ., ?
1 warnings
# latn_qwerty_sk
0 warnings
# latn_qwerty_sr
0 warnings
# latn_qwerty_tly
Duplicate keys: a, c, j, q
Layout doesn't define some important keys, missing: loc esc, loc tab
2 warnings
# latn_qwerty_tr
0 warnings
# latn_qwerty_us
0 warnings
# latn_qwerty_vi
0 warnings
# latn_qwertz
0 warnings
# latn_qwertz_cz
0 warnings
# latn_qwertz_cz_multifunctional
Layout includes some ASCII punctuation but not all, missing: `
1 warnings
# latn_qwertz_de
0 warnings
# latn_qwertz_fr_ch
0 warnings
# latn_qwertz_hu
0 warnings
# latn_qwertz_sk
Layout includes some ASCII punctuation but not all, missing: `
1 warnings
# shaw_imperial_en
0 warnings
# urdu_phonetic_ur
Duplicate keys:
Layout includes some ASCII punctuation but not all, missing: <, >, ?, `, |, ~
Some keys contain whitespaces, unexpected:
3 warnings

View File

@@ -1,8 +1,7 @@
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
import sys, os, glob import sys, os
layout_file_name = 0 warning_count = 0
warnings = []
KNOWN_NOT_LAYOUT = set([ KNOWN_NOT_LAYOUT = set([
"number_row", "numpad", "pin", "number_row", "numpad", "pin",
@@ -11,13 +10,15 @@ KNOWN_NOT_LAYOUT = set([
"clipboard_bottom_row" ]) "clipboard_bottom_row" ])
KEY_ATTRIBUTES = set([ KEY_ATTRIBUTES = set([
"key0", "key1", "key2", "key3", "key4", "key5", "key6", "key7", "key8", "key0",
"c", "nw", "ne", "sw", "se", "w", "e", "n", "s" "key1", "key2", "key3", "key4", "key5", "key6", "key7", "key8",
"nw", "ne", "sw", "se", "w", "e", "n", "s"
]) ])
def warn(msg): def warn(msg):
global warnings global warning_count
warnings.append("%s: %s" % (layout_file_name, msg)) print(msg)
warning_count += 1
def key_list_str(keys): def key_list_str(keys):
return ", ".join(sorted(list(keys))) return ", ".join(sorted(list(keys)))
@@ -73,7 +74,9 @@ def check_layout(layout):
if len(dup) > 0: warn("Duplicate keys: " + key_list_str(dup)) if len(dup) > 0: warn("Duplicate keys: " + key_list_str(dup))
missing_some_of(keys, "~!@#$%^&*(){}`[]=\\-_;:/.,?<>'\"+|", "ASCII punctuation") missing_some_of(keys, "~!@#$%^&*(){}`[]=\\-_;:/.,?<>'\"+|", "ASCII punctuation")
missing_some_of(keys, "0123456789", "digits") missing_some_of(keys, "0123456789", "digits")
missing_required(keys, ["backspace", "delete"], "Layout doesn't define some important keys") missing_required(keys,
["loc esc", "loc tab", "backspace", "delete"],
"Layout doesn't define some important keys")
unexpected_keys(keys, unexpected_keys(keys,
["copy", "paste", "cut", "selectAll", "shareText", ["copy", "paste", "cut", "selectAll", "shareText",
"pasteAsPlainText", "undo", "redo" ], "pasteAsPlainText", "undo", "redo" ],
@@ -87,10 +90,6 @@ def check_layout(layout):
unexpected_keys(keys, filter(lambda k: k.strip()!=k, keys), "Some keys contain whitespaces") unexpected_keys(keys, filter(lambda k: k.strip()!=k, keys), "Some keys contain whitespaces")
unexpected_keys(keys, ["f11_placeholder", "f12_placeholder"], "These keys are now added automatically") unexpected_keys(keys, ["f11_placeholder", "f12_placeholder"], "These keys are now added automatically")
if root.get("script", "latin") == "latin":
missing_required(keys, ["shift", "loc capslock"], "Missing important key")
missing_required(keys, ["loc esc", "loc tab"], "Missing programming keys")
_, bottom_row_keys, _ = parse_row("res/xml/bottom_row.xml") _, bottom_row_keys, _ = parse_row("res/xml/bottom_row.xml")
if root.get("bottom_row") == "false": if root.get("bottom_row") == "false":
@@ -103,17 +102,15 @@ def check_layout(layout):
if root.get("script") == None: if root.get("script") == None:
warn("Layout doesn't specify a script.") warn("Layout doesn't specify a script.")
for fname in sorted(glob.glob("srcs/layouts/*.xml")): for fname in sorted(sys.argv[1:]):
layout_id, _ = os.path.splitext(os.path.basename(fname)) layout_id, _ = os.path.splitext(os.path.basename(fname))
if layout_id in KNOWN_NOT_LAYOUT: if layout_id in KNOWN_NOT_LAYOUT:
continue continue
layout_file_name = layout_id
layout = parse_layout(fname) layout = parse_layout(fname)
if layout == None: if layout == None:
warn("Not a layout file") print("Not a layout file: %s" % layout_id)
else: else:
print("# %s" % layout_id)
warning_count = 0
check_layout(layout) check_layout(layout)
print("%d warnings" % warning_count)
with open("check_layout.output", "w") as out:
for w in warnings:
print(w, file=out)

View File

@@ -20,7 +20,7 @@ A layout XML file comprises tags that start with `<` and end with `>`.
* An optional `<modmap>`...`</modmap>` pair contains instructions if you want to change the behavior of a modifier key such as Shift. * An optional `<modmap>`...`</modmap>` pair contains instructions if you want to change the behavior of a modifier key such as Shift.
* Stand-alone tags include `<key`...`/>`, which defines a single key. * Stand-alone tags include `<key`...`/>`, which defines a single key.
A tag can have properties, defined using an equals sign and a pair of ASCII double quotes. For example, `<key c="a" />` defines the "a" key. The `c` property of the `key` tag says which key you are defining, and the tag's location inside `<row>`...`</row>` specifies where it will go in the row. A tag can have properties, defined using an equals sign and a pair of ASCII double quotes. For example, `<key key0="a" />` defines the "a" key. The `key0` property of the `key` tag says which key you are defining, and the tag's location inside `<row>`...`</row>` specifies where it will go in the row.
### Example ### Example
Here is a complete keyboard file with a single row containing an "a" key on the left and a "b" key on the right: Here is a complete keyboard file with a single row containing an "a" key on the left and a "b" key on the right:
@@ -28,8 +28,8 @@ Here is a complete keyboard file with a single row containing an "a" key on the
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<keyboard name="Simple example" script="latin"> <keyboard name="Simple example" script="latin">
<row> <row>
<key c="a" /> <key key0="a" />
<key c="b" /> <key key0="b" />
</row> </row>
</keyboard> </keyboard>
@@ -47,8 +47,6 @@ The `<keyboard>`...`</keyboard>` pair follows the declaration tag and encloses t
+ We recommend your layout use the built-in bottom row, because it is still evolving and your layout will incorporate innovations in future versions. However, to define your own, the current definition of the bottom row is in [bottom_row.xml](https://github.com/Julow/Unexpected-Keyboard/res/xml/bottom_row.xml). You can copypaste this XML into your custom layout as a starting point. + We recommend your layout use the built-in bottom row, because it is still evolving and your layout will incorporate innovations in future versions. However, to define your own, the current definition of the bottom row is in [bottom_row.xml](https://github.com/Julow/Unexpected-Keyboard/res/xml/bottom_row.xml). You can copypaste this XML into your custom layout as a starting point.
+ Likewise, the current definition of the top (number) row is in [number_row.xml](https://github.com/Julow/Unexpected-Keyboard/res/xml/number_row.xml). + Likewise, the current definition of the top (number) row is in [number_row.xml](https://github.com/Julow/Unexpected-Keyboard/res/xml/number_row.xml).
* `embedded_number_row`: Whether the layout has an embedded number row, and thus the "Show number row" setting shouldn't add another one. It accepts `true` or `false`, and defaults to `false`.
* `locale_extra_keys`: Whether Unexpected should add language-dependent extra keys from [method.xml](../res/xml/method.xml) to this layout. It accepts `true` or `false`, and defaults to `true`. To disable these automatic additions, specify `locale_extra_keys="false"`. * `locale_extra_keys`: Whether Unexpected should add language-dependent extra keys from [method.xml](../res/xml/method.xml) to this layout. It accepts `true` or `false`, and defaults to `true`. To disable these automatic additions, specify `locale_extra_keys="false"`.
## Row ## Row
@@ -61,7 +59,7 @@ A row's default height is 1.0 (one quarter of the keyboard height specified on t
The `<key />` tag defines a key on the keyboard. Its position in the sequence of keys inside `<row>`...`</row>` indicates its position in the row from left to right. What the key does is defined by optional properties. The `<key />` tag defines a key on the keyboard. Its position in the sequence of keys inside `<row>`...`</row>` indicates its position in the row from left to right. What the key does is defined by optional properties.
### Taps ### Taps
What the key does when tapped is defined by the optional `c` property. For example, `<key c="a" />` defines the "a" key. Unexpected Keyboard provides a legend in the middle of the key. What the key does when tapped is defined by the optional `key0` property. For example, `<key key0="a" />` defines the "a" key. Unexpected Keyboard provides a legend in the middle of the key.
When the Shift modifier is tapped, the "a" key becomes the "A" key and the legend temporarily changes. The Fn modifier makes a different change. You can override this behavior with a modmap (see below). When the Shift modifier is tapped, the "a" key becomes the "A" key and the legend temporarily changes. The Fn modifier makes a different change. You can override this behavior with a modmap (see below).
@@ -73,7 +71,7 @@ The following optional properties define the effects of swipes:
<TD STYLE="width: 6em;">nw</TD><TD>n</TD><TD>ne</TD> <TD STYLE="width: 6em;">nw</TD><TD>n</TD><TD>ne</TD>
</TR> </TR>
<TR ALIGN=CENTER> <TR ALIGN=CENTER>
<TD>w</TD><TD>c</TD><TD>e</TD> <TD>w</TD><TD>&nbsp;</TD><TD>e</TD>
</TR> </TR>
<TR> <TR>
<TD>sw</TD><TD>s</TD><TD>se</TD> <TD>sw</TD><TD>s</TD><TD>se</TD>
@@ -86,7 +84,7 @@ The following optional properties define the effects of swipes:
<TD>key1</TD><TD>key7</TD><TD>key2</TD> <TD>key1</TD><TD>key7</TD><TD>key2</TD>
</TR> </TR>
<TR> <TR>
<TD>key5</TD><TD>key0</TD><TD>key6</TD> <TD>key5</TD><TD>&nbsp;</TD><TD>key6</TD>
</TR> </TR>
<TR> <TR>
<TD>key3</TD><TD>key8</TD><TD>key4</TD> <TD>key3</TD><TD>key8</TD><TD>key4</TD>
@@ -95,6 +93,7 @@ The following optional properties define the effects of swipes:
You can define a swipe only once with either compass-point or numeric notation. Unexpected Keyboard automatically puts a small legend in that direction from the center of the key. You can define a swipe only once with either compass-point or numeric notation. Unexpected Keyboard automatically puts a small legend in that direction from the center of the key.
* `slider`: If `slider="true"`, and the key also has `w` and `e` properties, then the key tracks horizontal finger motion precisely and sends the `w` and `e` keystrokes repeatedly. In built-in layouts, this makes the space bar send left and right characters as the user slides on the space bar.
* `anticircle`: The key value to send when doing an anti-clockwise gesture on the key. * `anticircle`: The key value to send when doing an anti-clockwise gesture on the key.
### Layout ### Layout
@@ -105,10 +104,10 @@ A key may have the following properties to control the row's layout:
Normally, a key's width is 1.0 unit. Unexpected Keyboard occupies the full width of the screen, and the row defining the highest number of units (in widths plus shifts) is as wide as the screen. A row whose width is a smaller number of units has empty space on the right. Normally, a key's width is 1.0 unit. Unexpected Keyboard occupies the full width of the screen, and the row defining the highest number of units (in widths plus shifts) is as wide as the screen. A row whose width is a smaller number of units has empty space on the right.
### Extra legend ### Extra legend
* `indication`: An optional extra legend to show under the main label. For example, `<key c="2" indication="ABC" />` displays ABC at the bottom of the 2 key, as on a pinpad or some telephones. If the key also defines a downward swipe with `s` or `key8`, the legends overlap. * `indication`: An optional extra legend to show under the main label. For example, `<key key0="2" indication="ABC" />` displays ABC at the bottom of the 2 key, as on a pinpad or some telephones. If the key also defines a downward swipe with `s` or `key8`, the legends overlap.
### Possible key values ### Possible key values
Built-in strings that assign a special function to a key are described in [this page](Possible-key-values.md). For example, `se="copy"` means a southeasterly swipe produces the Copy key. If a key value does not match any of the built-in strings, it outputs that text _verbatim_. For example, `c="a"` simply outputs the letter a. Built-in strings that assign a special function to a key are described in [this page](Possible-key-values.md). For example, `se="copy"` means a southeasterly swipe produces the Copy key. If a key value does not match any of the built-in strings, it outputs that text _verbatim_. For example, `key0="a"` simply outputs the letter a.
In a layout, a key value can also start with the `loc` prefix. These are place-holders; the tap or swipe does nothing unless enabled through the "Add keys to keyboard" option in the Settings menu, or implicitly enabled by the language the device is set to use. For example, `ne="loc accent_aigu"` says that a northeast swipe produces the acute accent combinatorial key—if enabled. In a layout, a key value can also start with the `loc` prefix. These are place-holders; the tap or swipe does nothing unless enabled through the "Add keys to keyboard" option in the Settings menu, or implicitly enabled by the language the device is set to use. For example, `ne="loc accent_aigu"` says that a northeast swipe produces the acute accent combinatorial key—if enabled.

View File

@@ -1,36 +1,9 @@
# Key values # Key values
A key value defines what a key on the keyboard does when pressed or swiped. This is an exhaustive list of special values accepted for the `key0` through `key8` or `nw` through `se` attributes on a key.
Key values appear in the following places: Any string that does not exactly match these will be printed verbatim.
A key can output multiple characters, but cannot combine multiple built-in key values.
- In custom layouts, they are the value of: the `c` attribute, the compass-point attributes `nw` ... `se`, and the old-style `key0` ... `key8` attributes.
- Internally, they are used in the definition of the "Add keys to the keyboard" setting.
Key values can be any of the following:
- The name of a special key. A complete list of valid special keys follows.
- An arbitrary sequence of characters not containing `:`.
This results in a key that writes the specified characters.
- The syntax `legend:key_def`.
`legend` is the visible legend on the keyboard. It cannot contain `:`.
`key_def` can be:
+ The name of a special key, as listed below.
+ `'string'` An arbitrary string that can contain `:`. `'` can be added to the string as `` \' ``.
+ `keyevent:keycode` An Android keycode. They are listed as `KEYCODE_...` in [KeyEvent](https://developer.android.com/reference/android/view/KeyEvent#summary).
Examples:
+ `⏯:keyevent:85` A play/pause key (which has no effect in most apps).
+ `my@:'my.email@domain.com'` A key that sends an arbitrary string
- A macro, `symbol:key_def1,key_def2,...`.
This results in a key that behaves as if the sequence of `key_def` had been pressed in order.
Examples:
+ `CA:ctrl,a,ctrl,c` A key with legend CA that sends the sequence `ctrl+a`, `ctrl+c`.
+ `Cd:ctrl,backspace` A key with legend Cd that sends the shortcut `ctrl+backspace`.
## Escape codes ## Escape codes
Value | Escape code for Value | Escape code for
@@ -52,24 +25,19 @@ Value | Escape code for
`&quot;` | `"` `&quot;` | `"`
## Modifiers ## Modifiers
System modifiers are sent to the app, which can take app-specific action. System modifiers are sent to the app, which is free to do whatever they want in response.
The other modifiers only exist within the keyboard.
Value | Meaning Value | Meaning
:---------- | :------ :---------- | :------
`shift` | System modifier. `shift` | System modifier.
`ctrl` | System modifier. `ctrl` | System modifier.
`alt` | System modifier. `alt` | System modifier.
`meta` | System modifier. Equivalent to the Windows key. `meta` | System modifier. Equivalent to the Windows key.
`fn` | Activates Fn mode, which assigns letters and symbols to special characters. e.g. `fn` `!` = `¡`
`compose` | Compose key. Enables composing characters using Linux-like shortcuts; e.g. `Compose` `A` `single quote` types `Á` (A with acute accent).
`capslock` | Actives and locks Shift
The other modifiers take effect only within the keyboard. ## Special keys
Value | Meaning
:---------- | :------
`fn` | Activates Fn mode, which assigns letters and symbols to special characters. Example: `fn` `!` = `¡`
`compose` | Compose key. Enables composing characters using Linux-like shortcuts. Example: `Compose` `A` `'` types `Á` (A with acute accent).
`capslock` | Activates and locks Shift.
## App function keys
These keys are sent to apps, which are free to ignore them. The keyboard does not perform editing in response to these keys. These keys are sent to apps, which are free to ignore them. The keyboard does not perform editing in response to these keys.
`esc`, `enter`, `esc`, `enter`,
@@ -78,24 +46,12 @@ These keys are sent to apps, which are free to ignore them. The keyboard does no
`page_up`, `page_down`, `page_up`, `page_down`,
`home`, `end`, `home`, `end`,
`backspace`, `delete`, `backspace`, `delete`,
`insert`, `scroll_lock`, `insert`, `f1`-`f12`,
`f1`-`f12`,
`tab`, `copy`, `tab`, `copy`,
`paste`, `cut`, `paste`, `cut`,
`selectAll`, `pasteAsPlainText`, `selectAll`, `pasteAsPlainText`,
`undo`, `redo` `undo`, `redo`
## Keyboard editing actions
In contrast, these keys perform editing on the text without sending anything to the app.
Value | Meaning
:-------------------- | :------
`cursor_left` | Moves the cursor to the left with the slider gesture.
`cursor_right` | Moves the cursor to the right with the slider gesture.
`cursor_up` | Moves the cursor up with the slider gesture. Warning: this might make the cursor leave the text box.
`cursor_down` | Moves the cursor down with the slider gesture. Warning: this might make the cursor leave the text box.
`delete_word` | Delete the word to the left of the cursor.
`forward_delete_word` | Delete the word to the right of the cursor.
## Whitespace ## Whitespace
Value | Meaning Value | Meaning
:------ | :------ :------ | :------
@@ -105,6 +61,13 @@ Value | Meaning
`zwj` | Zero-width joiner. `zwj` | Zero-width joiner.
`zwnj` | Zero-width non-joiner. `zwnj` | Zero-width non-joiner.
## Keyboard editing actions
These keys perform editing on the text without sending keys that the app can interpret differently or ignore.
Value | Meaning
:----------------- | :------
`cursor_left` | Moves the cursor position to the left directly, without sending a `left` key event.
`cursor_right` | Moves the cursor position to the right directly, without sending a `right` key event.
## Other modifiers and diacritics ## Other modifiers and diacritics
Value | Meaning Value | Meaning
:------------------- | :------ :------------------- | :------
@@ -127,7 +90,6 @@ Value | Meaning
`accent_dot_below` | Dot below. `ạ` `accent_dot_below` | Dot below. `ạ`
`accent_horn` | Horn accent. `ơ` `accent_horn` | Horn accent. `ơ`
`accent_hook_above` | Hook accent. `ả` `accent_hook_above` | Hook accent. `ả`
`accent_double_grave` | Double grave accent. `ȁ`
`superscript` | Superscript. `ᵃ` `superscript` | Superscript. `ᵃ`
`subscript` | Subscript. `ₐ` `subscript` | Subscript. `ₐ`
`ordinal` | Turns `a` and `o` into `ª` and `º`. `ordinal` | Turns `a` and `o` into `ª` and `º`.
@@ -157,7 +119,7 @@ Keys ending in `_placeholder` are normally hidden unless the Fn key is pressed.
`ole`, `ole_placeholder`, `ole`, `ole_placeholder`,
`meteg`, `meteg_placeholder` `meteg`, `meteg_placeholder`
## Keyboard behavior keys ## Unexpected Keyboard specific
Value | Meaning Value | Meaning
:--------------------- | :------ :--------------------- | :------
`config` | Gear icon; opens Unexpected Keyboard settings. `config` | Gear icon; opens Unexpected Keyboard settings.

View File

@@ -1,14 +0,0 @@
New supported languages: Albanian, Belgian, Estonian, Georgian, Hawaiian,
Irish, Kannada, Kazakh, Old Church Slavonic, Serbian, Tajiki, Tamil, Welsh
Added WORKMAN (US) layout.
Improved layouts for modern Hindi and Sanskrit, Greek, Kurdish, Persian, Czech.
New compose sequences and added combining diacritic keys.
New and improved themes.
Many bug fixes and improvements.
Many thanks to the contributors: @anaskaejdar @bokidori @cknight828 @cuhsy
@Danger-Mkh @DocJr90 @IYO-OYI @kalankaboom @Kxeo @marciozomb13 @ms-jagadeeshan
@npnpatidar @ptitgnu @quantenzitrone @Sestowner @solokot @Spike-from-NH
@tenextractor

View File

@@ -1 +0,0 @@
Bug fixes

View File

@@ -1 +0,0 @@
Bug fixes

View File

@@ -1 +0,0 @@
Bug fixes

View File

@@ -52,7 +52,7 @@ def generate_arrays(out, layouts):
values_items, entries_items = zip(*(system_item + layouts + custom_item)) # unzip values_items, entries_items = zip(*(system_item + layouts + custom_item)) # unzip
ids_items = map(lambda s: "@xml/%s" % s if s not in ["system", "custom"] else "-1", values_items) ids_items = map(lambda s: "@xml/%s" % s if s not in ["system", "custom"] else "-1", values_items)
root = XML.Element("resources") root = XML.Element("resources")
root.append(XML.Comment(text=" DO NOT EDIT. This file is generated, run 'gradle genLayoutsList'. ")) root.append(XML.Comment(text="DO NOT EDIT. This file is generated, see gen_layouts.py."))
root.append(mk_array("string-array", "pref_layout_values", values_items)) root.append(mk_array("string-array", "pref_layout_values", values_items))
root.append(mk_array("string-array", "pref_layout_entries", entries_items)) root.append(mk_array("string-array", "pref_layout_entries", entries_items))
root.append(mk_array("integer-array", "layout_ids", ids_items)) root.append(mk_array("integer-array", "layout_ids", ids_items))

View File

@@ -1,38 +0,0 @@
<?xml version="1.0"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt">
<aapt:attr name="android:drawable">
<vector android:name="vector" android:width="35dp" android:height="40dp" android:viewportWidth="35" android:viewportHeight="40">
<path android:name="trace" android:pathData="M 17.5 20 C 20 3 26 7 27.5 10" android:strokeColor="#09b3f1" android:strokeWidth="2" android:strokeLineCap="round"/>
<group android:name="pointer_g">
<path android:name="pointer" android:pathData="m 2,0 a 2,2 0 1,1 -4,0 a 2,2 0 1,1 4,0" android:fillColor="#09b3f1" android:strokeColor="#09b3f1" android:strokeWidth="2" android:fillAlpha="0" android:strokeAlpha="0"/>
</group>
</vector>
</aapt:attr>
<target android:name="trace">
<aapt:attr name="android:animation">
<set>
<objectAnimator android:propertyName="strokeAlpha" android:duration="100" android:valueFrom="0" android:valueTo="1" android:valueType="floatType" android:interpolator="@android:interpolator/fast_out_slow_in"/>
<objectAnimator android:propertyName="trimPathEnd" android:duration="700" android:valueFrom="0" android:valueTo="1" android:interpolator="@android:interpolator/linear_out_slow_in"/>
<objectAnimator android:propertyName="strokeAlpha" android:startOffset="900" android:duration="400" android:valueFrom="1" android:valueTo="0" android:valueType="floatType" android:interpolator="@android:interpolator/linear_out_slow_in"/>
</set>
</aapt:attr>
</target>
<target android:name="pointer">
<aapt:attr name="android:animation">
<set>
<objectAnimator android:propertyName="fillAlpha" android:duration="100" android:valueFrom="0" android:valueTo="1" android:valueType="floatType" android:interpolator="@android:interpolator/fast_out_slow_in"/>
<objectAnimator android:propertyName="strokeAlpha" android:duration="100" android:valueFrom="0" android:valueTo="1" android:valueType="floatType" android:interpolator="@android:interpolator/fast_out_slow_in"/>
<objectAnimator android:propertyName="strokeAlpha" android:duration="100" android:valueFrom="0" android:valueTo="1" android:valueType="floatType" android:interpolator="@android:interpolator/fast_out_slow_in"/>
<objectAnimator android:propertyName="fillAlpha" android:startOffset="900" android:duration="400" android:valueFrom="1" android:valueTo="0" android:valueType="floatType" android:interpolator="@android:interpolator/linear_out_slow_in"/>
<objectAnimator android:propertyName="strokeAlpha" android:startOffset="900" android:duration="400" android:valueFrom="1" android:valueTo="0" android:valueType="floatType" android:interpolator="@android:interpolator/linear_out_slow_in"/>
</set>
</aapt:attr>
</target>
<target android:name="pointer_g">
<aapt:attr name="android:animation">
<set>
<objectAnimator android:propertyXName="translateX" android:propertyYName="translateY" android:duration="700" android:pathData="M 17.5 20 C 20 3 26 7 27 10" android:interpolator="@android:interpolator/linear_out_slow_in"/>
</set>
</aapt:attr>
</target>
</animated-vector>

View File

@@ -1,33 +0,0 @@
<?xml version="1.0"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt">
<aapt:attr name="android:drawable">
<vector android:name="vector" android:width="35dp" android:height="40dp" android:viewportWidth="35" android:viewportHeight="40">
<path android:name="trace" android:pathData="M 0 0" android:fillColor="#09b3f1" android:strokeColor="#09b3f1" android:strokeWidth="2" android:strokeLineCap="round"/>
</vector>
</aapt:attr>
<target android:name="trace">
<aapt:attr name="android:animation">
<set>
<objectAnimator android:propertyName="fillAlpha" android:duration="100" android:valueFrom="0" android:valueTo="1" android:valueType="floatType" android:interpolator="@android:interpolator/fast_out_slow_in"/>
<objectAnimator android:propertyName="strokeAlpha" android:duration="100" android:valueFrom="0" android:valueTo="1" android:valueType="floatType" android:interpolator="@android:interpolator/fast_out_slow_in"/>
<objectAnimator
android:propertyName="pathData"
android:duration="350"
android:valueFrom="M 17.5 20.0 m 2,0 a 2,2 0 1,1 -4,0 a 2,2 0 1,1 4,0 M 17.5 20.0 L 17.5,20.0"
android:valueTo="M 31 4 m 2,0 a 2,2 0 1,1 -4,0 a 2,2 0 1,1 4,0 M 17.5 20.0 L 31,4"
android:valueType="pathType"
android:interpolator="@android:interpolator/linear_out_slow_in"/>
<objectAnimator
android:propertyName="pathData"
android:startOffset="400"
android:duration="800"
android:valueFrom="M 31 4 m 2,0 a 2,2 0 1,1 -4,0 a 2,2 0 1,1 4,0 M 17.5 20.0 L 31,4"
android:valueTo="M 17.5 20.0 m 2,0 a 2,2 0 1,1 -4,0 a 2,2 0 1,1 4,0 M 17.5 20.0 L 31,4"
android:valueType="pathType"
android:interpolator="@android:interpolator/linear_out_slow_in"/>
<objectAnimator android:propertyName="fillAlpha" android:startOffset="900" android:duration="400" android:valueFrom="1" android:valueTo="0" android:valueType="floatType" android:interpolator="@android:interpolator/linear_out_slow_in"/>
<objectAnimator android:propertyName="strokeAlpha" android:startOffset="900" android:duration="400" android:valueFrom="1" android:valueTo="0" android:valueType="floatType" android:interpolator="@android:interpolator/linear_out_slow_in"/>
</set>
</aapt:attr>
</target>
</animated-vector>

View File

@@ -1,25 +0,0 @@
<?xml version="1.0"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt">
<aapt:attr name="android:drawable">
<vector android:name="vector" android:width="35dp" android:height="40dp" android:viewportWidth="35" android:viewportHeight="40">
<path android:name="trace" android:pathData="M 0 0" android:fillColor="#09b3f1" android:strokeColor="#09b3f1" android:strokeWidth="2" android:strokeLineCap="round"/>
</vector>
</aapt:attr>
<target android:name="trace">
<aapt:attr name="android:animation">
<set>
<objectAnimator android:propertyName="fillAlpha" android:duration="100" android:valueFrom="0" android:valueTo="1" android:valueType="floatType" android:interpolator="@android:interpolator/fast_out_slow_in"/>
<objectAnimator android:propertyName="strokeAlpha" android:duration="100" android:valueFrom="0" android:valueTo="1" android:valueType="floatType" android:interpolator="@android:interpolator/fast_out_slow_in"/>
<objectAnimator
android:propertyName="pathData"
android:duration="700"
android:valueFrom="M 17.5 20.0 m 2,0 a 2,2 0 1,1 -4,0 a 2,2 0 1,1 4,0 M 17.5 20.0 L 17.5,20.0"
android:valueTo=" M 31 4 m 2,0 a 2,2 0 1,1 -4,0 a 2,2 0 1,1 4,0 M 17.5 20.0 L 31 ,4"
android:valueType="pathType"
android:interpolator="@android:interpolator/linear_out_slow_in"/>
<objectAnimator android:propertyName="fillAlpha" android:startOffset="900" android:duration="400" android:valueFrom="1" android:valueTo="0" android:valueType="floatType" android:interpolator="@android:interpolator/linear_out_slow_in"/>
<objectAnimator android:propertyName="strokeAlpha" android:startOffset="900" android:duration="400" android:valueFrom="1" android:valueTo="0" android:valueType="floatType" android:interpolator="@android:interpolator/linear_out_slow_in"/>
</set>
</aapt:attr>
</target>
</animated-vector>

View File

@@ -1,25 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="35dp"
android:height="40dp"
android:viewportWidth="35.0"
android:viewportHeight="40.0">
<path
android:pathData="M11.26,10.13L23.74,10.13A1.13,1.13 0,0 1,24.87 11.26L24.87,28.74A1.13,1.13 0,0 1,23.74 29.88L11.26,29.88A1.13,1.13 0,0 1,10.13 28.74L10.13,11.26A1.13,1.13 0,0 1,11.26 10.13z"
android:fillAlpha="1"
android:strokeColor="#404040"
android:fillColor="#333333"
android:strokeWidth="0.251"
android:strokeAlpha="1"/>
<path
android:pathData="m11.18,28.83l0,-0.54l2.9,0l0,0.54z"
android:fillColor="#cccccc"
android:strokeWidth="0.265729"/>
<path
android:pathData="m19.52,17.02 l0.26,0.81q-0.27,0.09 -0.61,0.12 -0.33,0.03 -0.73,0.03 0.41,0.18 0.62,0.47 0.21,0.28 0.21,0.7 0,0.45 -0.22,0.8 -0.22,0.35 -0.62,0.55 -0.41,0.2 -0.97,0.2 -0.2,0 -0.35,-0.02 -0.14,-0.02 -0.28,-0.06 -0.09,0.06 -0.15,0.17 -0.06,0.1 -0.06,0.21 0,0.14 0.11,0.24 0.12,0.1 0.46,0.1l0.8,0q0.49,0 0.87,0.17 0.38,0.17 0.59,0.46 0.22,0.29 0.22,0.65 0,0.69 -0.59,1.07 -0.59,0.38 -1.71,0.38 -0.79,0 -1.24,-0.16 -0.45,-0.16 -0.63,-0.48 -0.18,-0.32 -0.18,-0.78l0.88,0q0,0.24 0.09,0.4 0.1,0.16 0.35,0.24 0.26,0.08 0.74,0.08 0.48,0 0.77,-0.08 0.29,-0.08 0.41,-0.23 0.13,-0.15 0.13,-0.36 0,-0.28 -0.24,-0.43 -0.24,-0.15 -0.65,-0.15l-0.79,0q-0.65,0 -0.96,-0.27 -0.3,-0.27 -0.3,-0.62 0,-0.24 0.13,-0.45 0.14,-0.22 0.38,-0.38 -0.41,-0.22 -0.61,-0.53 -0.19,-0.31 -0.19,-0.76 0,-0.49 0.24,-0.85 0.24,-0.37 0.68,-0.57 0.44,-0.2 1,-0.2 0.55,0 0.92,-0.06 0.37,-0.06 0.64,-0.17 0.28,-0.11 0.55,-0.24zM17.41,18.15q-0.47,0 -0.7,0.27 -0.24,0.26 -0.24,0.68 0,0.44 0.24,0.7 0.24,0.26 0.71,0.26 0.43,0 0.66,-0.25 0.23,-0.25 0.23,-0.72 0,-0.47 -0.23,-0.71 -0.23,-0.24 -0.68,-0.24z"
android:fillColor="#fdfdfd"
android:strokeWidth="0.265729"/>
<path
android:pathData="m21.24,13.59l0,-0.53l2.4,0l0,0.53z"
android:fillColor="#cccccc"
android:strokeWidth="0.265729"/>
</vector>

View File

@@ -1,25 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="35dp"
android:height="40dp"
android:viewportWidth="35.0"
android:viewportHeight="40.0">
<path
android:pathData="M11.26,10.13L23.74,10.13A1.13,1.13 0,0 1,24.87 11.26L24.87,28.74A1.13,1.13 0,0 1,23.74 29.88L11.26,29.88A1.13,1.13 0,0 1,10.13 28.74L10.13,11.26A1.13,1.13 0,0 1,11.26 10.13z"
android:fillAlpha="1"
android:strokeColor="#404040"
android:fillColor="#333333"
android:strokeWidth="0.251"
android:strokeAlpha="1"/>
<path
android:pathData="m16.64,17.64l0,3.21q0,0.41 0.16,0.58 0.17,0.17 0.5,0.17 0.31,0 0.61,-0.19 0.29,-0.19 0.46,-0.46l0,-3.33l0.98,0l0,4.6l-0.84,0l-0.06,-0.59q-0.26,0.34 -0.65,0.53 -0.39,0.18 -0.8,0.18 -0.67,0 -1,-0.37 -0.33,-0.37 -0.33,-1.01l0,-3.33z"
android:fillColor="#fdfdfd"
android:strokeWidth="0.265729"/>
<path
android:pathData="m12.52,24.71q0.3,0 0.54,0.09 0.25,0.09 0.49,0.35l-0.37,0.33q-0.14,-0.16 -0.28,-0.23 -0.14,-0.08 -0.34,-0.08 -0.27,0 -0.41,0.15 -0.14,0.15 -0.14,0.39 0,0.17 0.08,0.31 0.08,0.14 0.23,0.22 0.15,0.08 0.33,0.08l1.58,0l0,0.46l-0.47,0l0,1.56q-0.1,0.12 -0.26,0.24 -0.16,0.12 -0.41,0.21 -0.24,0.08 -0.58,0.08 -0.45,0 -0.75,-0.17 -0.3,-0.17 -0.44,-0.45 -0.15,-0.28 -0.15,-0.6 0,-0.46 0.24,-0.74 0.24,-0.28 0.66,-0.37l0,-0.02q-0.25,-0.06 -0.4,-0.18 -0.15,-0.12 -0.22,-0.3 -0.07,-0.17 -0.07,-0.37 0,-0.26 0.14,-0.48 0.14,-0.22 0.4,-0.35 0.26,-0.13 0.6,-0.13zM13.18,26.79l-0.58,0q-0.28,0 -0.45,0.12 -0.17,0.12 -0.26,0.32 -0.08,0.19 -0.08,0.39 0,0.2 0.08,0.37 0.08,0.17 0.24,0.28 0.16,0.1 0.42,0.1 0.21,0 0.37,-0.07 0.16,-0.07 0.26,-0.19z"
android:fillColor="#cccccc"
android:strokeWidth="0.265729"/>
<path
android:pathData="m22.12,15.25 l-0.61,-0.19 1.54,-3.37l-1.84,0l0,-0.51l2.49,0l0,0.47z"
android:fillColor="#cccccc"
android:strokeWidth="0.265729"/>
</vector>

View File

@@ -1,21 +1,10 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true" android:fitsSystemWindows="true"> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true">
<LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical"> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical">
<TextView style="@style/paragraph" android:text="@string/launcher_description"/> <TextView style="@style/paragraph" android:text="@string/launcher_description"/>
<Button style="@style/paragraph" android:text="@string/launcher_button_imesettings" android:onClick="launch_imesettings" android:layout_width="wrap_content"/> <Button style="@style/paragraph" android:text="@string/launcher_button_imesettings" android:onClick="launch_imesettings" android:layout_width="wrap_content"/>
<Button style="@style/paragraph" android:text="@string/launcher_button_imepicker" android:onClick="launch_imepicker" android:layout_width="wrap_content"/> <Button style="@style/paragraph" android:text="@string/launcher_button_imepicker" android:onClick="launch_imepicker" android:layout_width="wrap_content"/>
<LinearLayout style="@style/anim_box"> <VideoView android:id="@+id/launcher_intro_video" android:layout_width="240dp" android:layout_height="wrap_content" android:layout_gravity="center"/>
<ImageView style="@style/anim" android:id="@+id/launcher_anim_swipe" android:background="@drawable/doc_key_u" android:src="@drawable/doc_anim_swipe"/>
<TextView style="@style/anim_text" android:text="7"/>
</LinearLayout>
<LinearLayout style="@style/anim_box">
<ImageView style="@style/anim" android:id="@+id/launcher_anim_circle" android:background="@drawable/doc_key_g" android:src="@drawable/doc_anim_circle"/>
<TextView style="@style/anim_text" android:text="G"/>
</LinearLayout>
<LinearLayout style="@style/anim_box">
<ImageView style="@style/anim" android:id="@+id/launcher_anim_round_trip" android:background="@drawable/doc_key_g" android:src="@drawable/doc_anim_round_trip"/>
<TextView style="@style/anim_text" android:text=""/>
</LinearLayout>
<TextView android:id="@+id/launcher_tryhere_text" style="@style/paragraph" android:text="@string/launcher_tryhere"/> <TextView android:id="@+id/launcher_tryhere_text" style="@style/paragraph" android:text="@string/launcher_tryhere"/>
<EditText android:id="@+id/launcher_tryhere_area" style="@style/paragraph" android:inputType="text" android:hint="@string/launcher_tryhere_hint" android:importantForAutofill="no"/> <EditText android:id="@+id/launcher_tryhere_area" style="@style/paragraph" android:inputType="text" android:hint="@string/launcher_tryhere_hint" android:importantForAutofill="no"/>
<TextView style="@style/paragraph" android:text="@string/launcher_sourcecode"/> <TextView style="@style/paragraph" android:text="@string/launcher_sourcecode"/>

BIN
res/raw/intro_video.mp4 Normal file

Binary file not shown.

View File

@@ -71,7 +71,6 @@ Tato aplikace neobsahuje žádné reklamy, nevyužívá připojení k síti a je
<string name="pref_theme_e_monet">Monet (dle systému)</string> <string name="pref_theme_e_monet">Monet (dle systému)</string>
<string name="pref_theme_e_monetlight">Monet (Světlý)</string> <string name="pref_theme_e_monetlight">Monet (Světlý)</string>
<string name="pref_theme_e_monetdark">Monet (Tmavý)</string> <string name="pref_theme_e_monetdark">Monet (Tmavý)</string>
<!-- <string name="pref_theme_e_rosepine">Rosé Pine</string> -->
<string name="pref_swipe_dist_e_very_short">Velmi krátká</string> <string name="pref_swipe_dist_e_very_short">Velmi krátká</string>
<string name="pref_swipe_dist_e_short">Krátká</string> <string name="pref_swipe_dist_e_short">Krátká</string>
<string name="pref_swipe_dist_e_default">Běžná</string> <string name="pref_swipe_dist_e_default">Běžná</string>
@@ -121,18 +120,8 @@ Tato aplikace neobsahuje žádné reklamy, nevyužívá připojení k síti a je
<string name="key_descr_home">Home</string> <string name="key_descr_home">Home</string>
<string name="key_descr_end">End</string> <string name="key_descr_end">End</string>
<string name="key_descr_clipboard">Správce schránky</string> <string name="key_descr_clipboard">Správce schránky</string>
<!-- <string name="key_descr_combining">Combining diacritic</string> -->
<!-- <string name="key_descr_dead_key">Dead key</string> -->
<!-- <string name="key_descr_zwj">Zero width joiner</string> -->
<!-- <string name="key_descr_zwnj">Zero width non-joiner</string> -->
<!-- <string name="key_descr_nbsp">Non-breaking space</string> -->
<!-- <string name="key_descr_nnbsp">Narrow non-breaking space</string> -->
<!-- <string name="key_descr_delete_word">Delete a word</string> -->
<!-- <string name="key_descr_forward_delete_word">Delete a word on the right</string> -->
<!-- <string name="key_descr_gesture">Gesture</string> -->
<string name="clipboard_history_heading">Nedávno kopírovaný text</string> <string name="clipboard_history_heading">Nedávno kopírovaný text</string>
<string name="clipboard_pin_heading">Připnout</string> <string name="clipboard_pin_heading">Připnout</string>
<string name="clipboard_remove_confirm">Odebrat ze schránky?</string> <string name="clipboard_remove_confirm">Odebrat ze schránky?</string>
<string name="clipboard_remove_confirmed">Ano</string> <string name="clipboard_remove_confirmed">Ano</string>
<!-- <string name="toast_no_voice_input">No voice typing app installed</string> -->
</resources> </resources>

View File

@@ -71,7 +71,6 @@ Diese App enthält keine Werbung, benötigt keinen Netzwerkzugriff und ist quell
<string name="pref_theme_e_monet">Monet (System)</string> <string name="pref_theme_e_monet">Monet (System)</string>
<string name="pref_theme_e_monetlight">Monet (Hell)</string> <string name="pref_theme_e_monetlight">Monet (Hell)</string>
<string name="pref_theme_e_monetdark">Monet (Dunkel)</string> <string name="pref_theme_e_monetdark">Monet (Dunkel)</string>
<!-- <string name="pref_theme_e_rosepine">Rosé Pine</string> -->
<string name="pref_swipe_dist_e_very_short">Sehr kurz</string> <string name="pref_swipe_dist_e_very_short">Sehr kurz</string>
<string name="pref_swipe_dist_e_short">Kurz</string> <string name="pref_swipe_dist_e_short">Kurz</string>
<string name="pref_swipe_dist_e_default">Normal</string> <string name="pref_swipe_dist_e_default">Normal</string>
@@ -121,18 +120,8 @@ Diese App enthält keine Werbung, benötigt keinen Netzwerkzugriff und ist quell
<string name="key_descr_home">Pos1</string> <string name="key_descr_home">Pos1</string>
<string name="key_descr_end">Ende</string> <string name="key_descr_end">Ende</string>
<string name="key_descr_clipboard">Clipboard-Manager</string> <string name="key_descr_clipboard">Clipboard-Manager</string>
<!-- <string name="key_descr_combining">Combining diacritic</string> -->
<!-- <string name="key_descr_dead_key">Dead key</string> -->
<!-- <string name="key_descr_zwj">Zero width joiner</string> -->
<!-- <string name="key_descr_zwnj">Zero width non-joiner</string> -->
<!-- <string name="key_descr_nbsp">Non-breaking space</string> -->
<!-- <string name="key_descr_nnbsp">Narrow non-breaking space</string> -->
<!-- <string name="key_descr_delete_word">Delete a word</string> -->
<!-- <string name="key_descr_forward_delete_word">Delete a word on the right</string> -->
<!-- <string name="key_descr_gesture">Gesture</string> -->
<string name="clipboard_history_heading">Zuletzt kopierter Text</string> <string name="clipboard_history_heading">Zuletzt kopierter Text</string>
<string name="clipboard_pin_heading">Angeheftet</string> <string name="clipboard_pin_heading">Angeheftet</string>
<string name="clipboard_remove_confirm">Aus der Zwischenablage entfernen?</string> <string name="clipboard_remove_confirm">Aus der Zwischenablage entfernen?</string>
<string name="clipboard_remove_confirmed">Ja</string> <string name="clipboard_remove_confirmed">Ja</string>
<!-- <string name="toast_no_voice_input">No voice typing app installed</string> -->
</resources> </resources>

View File

@@ -71,7 +71,6 @@ La misma no contiene ningún anuncio/publicidad, no realiza peticiones de red y
<string name="pref_theme_e_monet">Monet (de sistema)</string> <string name="pref_theme_e_monet">Monet (de sistema)</string>
<string name="pref_theme_e_monetlight">Monet (claro)</string> <string name="pref_theme_e_monetlight">Monet (claro)</string>
<string name="pref_theme_e_monetdark">Monet (oscuro)</string> <string name="pref_theme_e_monetdark">Monet (oscuro)</string>
<!-- <string name="pref_theme_e_rosepine">Rosé Pine</string> -->
<string name="pref_swipe_dist_e_very_short">Muy corta</string> <string name="pref_swipe_dist_e_very_short">Muy corta</string>
<string name="pref_swipe_dist_e_short">Corta</string> <string name="pref_swipe_dist_e_short">Corta</string>
<string name="pref_swipe_dist_e_default">Normal</string> <string name="pref_swipe_dist_e_default">Normal</string>
@@ -121,18 +120,8 @@ La misma no contiene ningún anuncio/publicidad, no realiza peticiones de red y
<string name="key_descr_home">Inicio</string> <string name="key_descr_home">Inicio</string>
<string name="key_descr_end">Fin</string> <string name="key_descr_end">Fin</string>
<string name="key_descr_clipboard">Arreglar portapapeles</string> <string name="key_descr_clipboard">Arreglar portapapeles</string>
<!-- <string name="key_descr_combining">Combining diacritic</string> -->
<!-- <string name="key_descr_dead_key">Dead key</string> -->
<!-- <string name="key_descr_zwj">Zero width joiner</string> -->
<!-- <string name="key_descr_zwnj">Zero width non-joiner</string> -->
<!-- <string name="key_descr_nbsp">Non-breaking space</string> -->
<!-- <string name="key_descr_nnbsp">Narrow non-breaking space</string> -->
<!-- <string name="key_descr_delete_word">Delete a word</string> -->
<!-- <string name="key_descr_forward_delete_word">Delete a word on the right</string> -->
<!-- <string name="key_descr_gesture">Gesture</string> -->
<string name="clipboard_history_heading">Textos recién copiados</string> <string name="clipboard_history_heading">Textos recién copiados</string>
<string name="clipboard_pin_heading">Pegado</string> <string name="clipboard_pin_heading">Pegado</string>
<string name="clipboard_remove_confirm">¿Sacar este portapapeles?</string> <string name="clipboard_remove_confirm">¿Sacar este portapapeles?</string>
<string name="clipboard_remove_confirmed"></string> <string name="clipboard_remove_confirmed"></string>
<!-- <string name="toast_no_voice_input">No voice typing app installed</string> -->
</resources> </resources>

View File

@@ -71,7 +71,6 @@ This application contains no ads, doesn't make any network requests and is Open
<!-- <string name="pref_theme_e_monet">Monet (System)</string> --> <!-- <string name="pref_theme_e_monet">Monet (System)</string> -->
<!-- <string name="pref_theme_e_monetlight">Monet (Light)</string> --> <!-- <string name="pref_theme_e_monetlight">Monet (Light)</string> -->
<!-- <string name="pref_theme_e_monetdark">Monet (Dark)</string> --> <!-- <string name="pref_theme_e_monetdark">Monet (Dark)</string> -->
<!-- <string name="pref_theme_e_rosepine">Rosé Pine</string> -->
<string name="pref_swipe_dist_e_very_short">بسیار کوتاه</string> <string name="pref_swipe_dist_e_very_short">بسیار کوتاه</string>
<string name="pref_swipe_dist_e_short">کوتاه</string> <string name="pref_swipe_dist_e_short">کوتاه</string>
<string name="pref_swipe_dist_e_default">عادی</string> <string name="pref_swipe_dist_e_default">عادی</string>
@@ -121,18 +120,8 @@ This application contains no ads, doesn't make any network requests and is Open
<!-- <string name="key_descr_home">Home</string> --> <!-- <string name="key_descr_home">Home</string> -->
<!-- <string name="key_descr_end">End</string> --> <!-- <string name="key_descr_end">End</string> -->
<!-- <string name="key_descr_clipboard">Clipboard manager</string> --> <!-- <string name="key_descr_clipboard">Clipboard manager</string> -->
<!-- <string name="key_descr_combining">Combining diacritic</string> -->
<!-- <string name="key_descr_dead_key">Dead key</string> -->
<!-- <string name="key_descr_zwj">Zero width joiner</string> -->
<!-- <string name="key_descr_zwnj">Zero width non-joiner</string> -->
<!-- <string name="key_descr_nbsp">Non-breaking space</string> -->
<!-- <string name="key_descr_nnbsp">Narrow non-breaking space</string> -->
<!-- <string name="key_descr_delete_word">Delete a word</string> -->
<!-- <string name="key_descr_forward_delete_word">Delete a word on the right</string> -->
<!-- <string name="key_descr_gesture">Gesture</string> -->
<!-- <string name="clipboard_history_heading">Recently copied text</string> --> <!-- <string name="clipboard_history_heading">Recently copied text</string> -->
<!-- <string name="clipboard_pin_heading">Pinned</string> --> <!-- <string name="clipboard_pin_heading">Pinned</string> -->
<!-- <string name="clipboard_remove_confirm">Remove this clipboard?</string> --> <!-- <string name="clipboard_remove_confirm">Remove this clipboard?</string> -->
<!-- <string name="clipboard_remove_confirmed">Yes</string> --> <!-- <string name="clipboard_remove_confirmed">Yes</string> -->
<!-- <string name="toast_no_voice_input">No voice typing app installed</string> -->
</resources> </resources>

View File

@@ -71,7 +71,6 @@ Cette application ne contient pas de publicité, n'accède pas au réseau et est
<string name="pref_theme_e_monet">Monet (Système)</string> <string name="pref_theme_e_monet">Monet (Système)</string>
<string name="pref_theme_e_monetlight">Monet (Clair)</string> <string name="pref_theme_e_monetlight">Monet (Clair)</string>
<string name="pref_theme_e_monetdark">Monet (Sombre)</string> <string name="pref_theme_e_monetdark">Monet (Sombre)</string>
<!-- <string name="pref_theme_e_rosepine">Rosé Pine</string> -->
<string name="pref_swipe_dist_e_very_short">Très courte</string> <string name="pref_swipe_dist_e_very_short">Très courte</string>
<string name="pref_swipe_dist_e_short">Courte</string> <string name="pref_swipe_dist_e_short">Courte</string>
<string name="pref_swipe_dist_e_default">Normale</string> <string name="pref_swipe_dist_e_default">Normale</string>
@@ -121,18 +120,8 @@ Cette application ne contient pas de publicité, n'accède pas au réseau et est
<string name="key_descr_home">Début</string> <string name="key_descr_home">Début</string>
<string name="key_descr_end">Fin</string> <string name="key_descr_end">Fin</string>
<string name="key_descr_clipboard">Presse-papiers</string> <string name="key_descr_clipboard">Presse-papiers</string>
<!-- <string name="key_descr_combining">Combining diacritic</string> -->
<!-- <string name="key_descr_dead_key">Dead key</string> -->
<!-- <string name="key_descr_zwj">Zero width joiner</string> -->
<!-- <string name="key_descr_zwnj">Zero width non-joiner</string> -->
<!-- <string name="key_descr_nbsp">Non-breaking space</string> -->
<!-- <string name="key_descr_nnbsp">Narrow non-breaking space</string> -->
<!-- <string name="key_descr_delete_word">Delete a word</string> -->
<!-- <string name="key_descr_forward_delete_word">Delete a word on the right</string> -->
<!-- <string name="key_descr_gesture">Gesture</string> -->
<string name="clipboard_history_heading">Texte récemment copié</string> <string name="clipboard_history_heading">Texte récemment copié</string>
<string name="clipboard_pin_heading">Épinglé</string> <string name="clipboard_pin_heading">Épinglé</string>
<string name="clipboard_remove_confirm">Supprimer ce presse-papiers ?</string> <string name="clipboard_remove_confirm">Supprimer ce presse-papiers ?</string>
<string name="clipboard_remove_confirmed">Oui</string> <string name="clipboard_remove_confirmed">Oui</string>
<!-- <string name="toast_no_voice_input">No voice typing app installed</string> -->
</resources> </resources>

View File

@@ -71,7 +71,6 @@ This application contains no ads, doesn't make any network requests and is Open
<!-- <string name="pref_theme_e_monet">Monet (System)</string> --> <!-- <string name="pref_theme_e_monet">Monet (System)</string> -->
<!-- <string name="pref_theme_e_monetlight">Monet (Light)</string> --> <!-- <string name="pref_theme_e_monetlight">Monet (Light)</string> -->
<!-- <string name="pref_theme_e_monetdark">Monet (Dark)</string> --> <!-- <string name="pref_theme_e_monetdark">Monet (Dark)</string> -->
<!-- <string name="pref_theme_e_rosepine">Rosé Pine</string> -->
<string name="pref_swipe_dist_e_very_short">Veramente breve</string> <string name="pref_swipe_dist_e_very_short">Veramente breve</string>
<string name="pref_swipe_dist_e_short">Breve</string> <string name="pref_swipe_dist_e_short">Breve</string>
<string name="pref_swipe_dist_e_default">Normale</string> <string name="pref_swipe_dist_e_default">Normale</string>
@@ -121,18 +120,8 @@ This application contains no ads, doesn't make any network requests and is Open
<!-- <string name="key_descr_home">Home</string> --> <!-- <string name="key_descr_home">Home</string> -->
<!-- <string name="key_descr_end">End</string> --> <!-- <string name="key_descr_end">End</string> -->
<!-- <string name="key_descr_clipboard">Clipboard manager</string> --> <!-- <string name="key_descr_clipboard">Clipboard manager</string> -->
<!-- <string name="key_descr_combining">Combining diacritic</string> -->
<!-- <string name="key_descr_dead_key">Dead key</string> -->
<!-- <string name="key_descr_zwj">Zero width joiner</string> -->
<!-- <string name="key_descr_zwnj">Zero width non-joiner</string> -->
<!-- <string name="key_descr_nbsp">Non-breaking space</string> -->
<!-- <string name="key_descr_nnbsp">Narrow non-breaking space</string> -->
<!-- <string name="key_descr_delete_word">Delete a word</string> -->
<!-- <string name="key_descr_forward_delete_word">Delete a word on the right</string> -->
<!-- <string name="key_descr_gesture">Gesture</string> -->
<!-- <string name="clipboard_history_heading">Recently copied text</string> --> <!-- <string name="clipboard_history_heading">Recently copied text</string> -->
<!-- <string name="clipboard_pin_heading">Pinned</string> --> <!-- <string name="clipboard_pin_heading">Pinned</string> -->
<!-- <string name="clipboard_remove_confirm">Remove this clipboard?</string> --> <!-- <string name="clipboard_remove_confirm">Remove this clipboard?</string> -->
<!-- <string name="clipboard_remove_confirmed">Yes</string> --> <!-- <string name="clipboard_remove_confirmed">Yes</string> -->
<!-- <string name="toast_no_voice_input">No voice typing app installed</string> -->
</resources> </resources>

View File

@@ -72,7 +72,6 @@ PCキーボードでの半角入力を再現しています。日本語入力、
<string name="pref_theme_e_monet">Monet (システム)</string> <string name="pref_theme_e_monet">Monet (システム)</string>
<string name="pref_theme_e_monetlight">Monet (ライト)</string> <string name="pref_theme_e_monetlight">Monet (ライト)</string>
<string name="pref_theme_e_monetdark">Monet (ダーク)</string> <string name="pref_theme_e_monetdark">Monet (ダーク)</string>
<!-- <string name="pref_theme_e_rosepine">Rosé Pine</string> -->
<string name="pref_swipe_dist_e_very_short">短い</string> <string name="pref_swipe_dist_e_very_short">短い</string>
<string name="pref_swipe_dist_e_short">やや短い</string> <string name="pref_swipe_dist_e_short">やや短い</string>
<string name="pref_swipe_dist_e_default">普通</string> <string name="pref_swipe_dist_e_default">普通</string>
@@ -122,18 +121,8 @@ PCキーボードでの半角入力を再現しています。日本語入力、
<string name="key_descr_home">Home</string> <string name="key_descr_home">Home</string>
<string name="key_descr_end">End</string> <string name="key_descr_end">End</string>
<string name="key_descr_clipboard">クリップボード</string> <string name="key_descr_clipboard">クリップボード</string>
<!-- <string name="key_descr_combining">Combining diacritic</string> -->
<!-- <string name="key_descr_dead_key">Dead key</string> -->
<!-- <string name="key_descr_zwj">Zero width joiner</string> -->
<!-- <string name="key_descr_zwnj">Zero width non-joiner</string> -->
<!-- <string name="key_descr_nbsp">Non-breaking space</string> -->
<!-- <string name="key_descr_nnbsp">Narrow non-breaking space</string> -->
<!-- <string name="key_descr_delete_word">Delete a word</string> -->
<!-- <string name="key_descr_forward_delete_word">Delete a word on the right</string> -->
<!-- <string name="key_descr_gesture">Gesture</string> -->
<string name="clipboard_history_heading">最近コピーしたテキスト</string> <string name="clipboard_history_heading">最近コピーしたテキスト</string>
<string name="clipboard_pin_heading">お気に入り</string> <string name="clipboard_pin_heading">お気に入り</string>
<string name="clipboard_remove_confirm">クリップボードから削除しますか?</string> <string name="clipboard_remove_confirm">クリップボードから削除しますか?</string>
<string name="clipboard_remove_confirmed">はい</string> <string name="clipboard_remove_confirmed">はい</string>
<!-- <string name="toast_no_voice_input">No voice typing app installed</string> -->
</resources> </resources>

View File

@@ -71,7 +71,6 @@
<string name="pref_theme_e_monet">모네트 (시스템)</string> <string name="pref_theme_e_monet">모네트 (시스템)</string>
<string name="pref_theme_e_monetlight">모네트 (라이트)</string> <string name="pref_theme_e_monetlight">모네트 (라이트)</string>
<string name="pref_theme_e_monetdark">모네트 (다크)</string> <string name="pref_theme_e_monetdark">모네트 (다크)</string>
<!-- <string name="pref_theme_e_rosepine">Rosé Pine</string> -->
<string name="pref_swipe_dist_e_very_short">매우 짧음</string> <string name="pref_swipe_dist_e_very_short">매우 짧음</string>
<string name="pref_swipe_dist_e_short">짧음</string> <string name="pref_swipe_dist_e_short">짧음</string>
<string name="pref_swipe_dist_e_default">보통</string> <string name="pref_swipe_dist_e_default">보통</string>
@@ -121,18 +120,8 @@
<string name="key_descr_home"></string> <string name="key_descr_home"></string>
<string name="key_descr_end">종료</string> <string name="key_descr_end">종료</string>
<string name="key_descr_clipboard">클립보드 관리자</string> <string name="key_descr_clipboard">클립보드 관리자</string>
<!-- <string name="key_descr_combining">Combining diacritic</string> -->
<!-- <string name="key_descr_dead_key">Dead key</string> -->
<!-- <string name="key_descr_zwj">Zero width joiner</string> -->
<!-- <string name="key_descr_zwnj">Zero width non-joiner</string> -->
<!-- <string name="key_descr_nbsp">Non-breaking space</string> -->
<!-- <string name="key_descr_nnbsp">Narrow non-breaking space</string> -->
<!-- <string name="key_descr_delete_word">Delete a word</string> -->
<!-- <string name="key_descr_forward_delete_word">Delete a word on the right</string> -->
<!-- <string name="key_descr_gesture">Gesture</string> -->
<string name="clipboard_history_heading">최근에 복사한 텍스트</string> <string name="clipboard_history_heading">최근에 복사한 텍스트</string>
<string name="clipboard_pin_heading">고정</string> <string name="clipboard_pin_heading">고정</string>
<string name="clipboard_remove_confirm">이 클립보드를 제거하시겠습니까?</string> <string name="clipboard_remove_confirm">이 클립보드를 제거하시겠습니까?</string>
<string name="clipboard_remove_confirmed"></string> <string name="clipboard_remove_confirmed"></string>
<!-- <string name="toast_no_voice_input">No voice typing app installed</string> -->
</resources> </resources>

View File

@@ -38,7 +38,7 @@ Tagad lieliski piemērota izmantošanai ikdienā.
<string name="pref_category_typing">Rakstīšana</string> <string name="pref_category_typing">Rakstīšana</string>
<string name="pref_swipe_dist_title">Pavilkšanas attālums</string> <string name="pref_swipe_dist_title">Pavilkšanas attālums</string>
<string name="pref_swipe_dist_summary">Taustiņu stūros esošo rakstzīmju attālums (%s)</string> <string name="pref_swipe_dist_summary">Taustiņu stūros esošo rakstzīmju attālums (%s)</string>
<string name="pref_long_timeout_title">Ilgas piespiešanas noildze</string> <string name="pref_long_timeout_title">Ilgas piepiešanas noildze</string>
<string name="pref_long_interval_title">Taustiņa atkārtošanās aizture</string> <string name="pref_long_interval_title">Taustiņa atkārtošanās aizture</string>
<string name="pref_keyrepeat_enabled">Taustiņa atkārtošanās ar ilgu piespiešanu</string> <string name="pref_keyrepeat_enabled">Taustiņa atkārtošanās ar ilgu piespiešanu</string>
<string name="pref_lock_double_tap_title">Divkāršs piesitiens burtslēgam</string> <string name="pref_lock_double_tap_title">Divkāršs piesitiens burtslēgam</string>
@@ -71,7 +71,6 @@ Tagad lieliski piemērota izmantošanai ikdienā.
<string name="pref_theme_e_monet">Monē (sistēmas)</string> <string name="pref_theme_e_monet">Monē (sistēmas)</string>
<string name="pref_theme_e_monetlight">Monē (gaišs)</string> <string name="pref_theme_e_monetlight">Monē (gaišs)</string>
<string name="pref_theme_e_monetdark">Monē (tumšs)</string> <string name="pref_theme_e_monetdark">Monē (tumšs)</string>
<!-- <string name="pref_theme_e_rosepine">Rosé Pine</string> -->
<string name="pref_swipe_dist_e_very_short">Ļoti tuvs</string> <string name="pref_swipe_dist_e_very_short">Ļoti tuvs</string>
<string name="pref_swipe_dist_e_short">Tuvs</string> <string name="pref_swipe_dist_e_short">Tuvs</string>
<string name="pref_swipe_dist_e_default">Vidējs</string> <string name="pref_swipe_dist_e_default">Vidējs</string>
@@ -123,18 +122,8 @@ Tagad lieliski piemērota izmantošanai ikdienā.
<string name="key_descr_home">Sākums</string> <string name="key_descr_home">Sākums</string>
<string name="key_descr_end">Beigas</string> <string name="key_descr_end">Beigas</string>
<string name="key_descr_clipboard">Starpliktuves pārvaldnieks</string> <string name="key_descr_clipboard">Starpliktuves pārvaldnieks</string>
<!-- <string name="key_descr_combining">Combining diacritic</string> -->
<!-- <string name="key_descr_dead_key">Dead key</string> -->
<!-- <string name="key_descr_zwj">Zero width joiner</string> -->
<!-- <string name="key_descr_zwnj">Zero width non-joiner</string> -->
<!-- <string name="key_descr_nbsp">Non-breaking space</string> -->
<!-- <string name="key_descr_nnbsp">Narrow non-breaking space</string> -->
<!-- <string name="key_descr_delete_word">Delete a word</string> -->
<!-- <string name="key_descr_forward_delete_word">Delete a word on the right</string> -->
<!-- <string name="key_descr_gesture">Gesture</string> -->
<string name="clipboard_history_heading">Nesen starpliktuvē ievietots teksts</string> <string name="clipboard_history_heading">Nesen starpliktuvē ievietots teksts</string>
<string name="clipboard_pin_heading">Piesprausts</string> <string name="clipboard_pin_heading">Piesprausts</string>
<string name="clipboard_remove_confirm">Noņemt šo starpliktuves vienumu?</string> <string name="clipboard_remove_confirm">Noņemt šo starpliktuves vienumu?</string>
<string name="clipboard_remove_confirmed"></string> <string name="clipboard_remove_confirmed"></string>
<!-- <string name="toast_no_voice_input">No voice typing app installed</string> -->
</resources> </resources>

View File

@@ -71,7 +71,6 @@ Aplikacja nie zawiera reklam, nie żąda dostępu do internetu, a jej kod źród
<string name="pref_theme_e_monet">Monet (Systemowy)</string> <string name="pref_theme_e_monet">Monet (Systemowy)</string>
<string name="pref_theme_e_monetlight">Monet (Jasny)</string> <string name="pref_theme_e_monetlight">Monet (Jasny)</string>
<string name="pref_theme_e_monetdark">Monet (Ciemny)</string> <string name="pref_theme_e_monetdark">Monet (Ciemny)</string>
<!-- <string name="pref_theme_e_rosepine">Rosé Pine</string> -->
<string name="pref_swipe_dist_e_very_short">Bardzo mała</string> <string name="pref_swipe_dist_e_very_short">Bardzo mała</string>
<string name="pref_swipe_dist_e_short">Mała</string> <string name="pref_swipe_dist_e_short">Mała</string>
<string name="pref_swipe_dist_e_default">Normalna</string> <string name="pref_swipe_dist_e_default">Normalna</string>
@@ -121,18 +120,8 @@ Aplikacja nie zawiera reklam, nie żąda dostępu do internetu, a jej kod źród
<string name="key_descr_home">Home</string> <string name="key_descr_home">Home</string>
<string name="key_descr_end">End</string> <string name="key_descr_end">End</string>
<string name="key_descr_clipboard">Zarządzanie schowkiem</string> <string name="key_descr_clipboard">Zarządzanie schowkiem</string>
<!-- <string name="key_descr_combining">Combining diacritic</string> -->
<!-- <string name="key_descr_dead_key">Dead key</string> -->
<!-- <string name="key_descr_zwj">Zero width joiner</string> -->
<!-- <string name="key_descr_zwnj">Zero width non-joiner</string> -->
<!-- <string name="key_descr_nbsp">Non-breaking space</string> -->
<!-- <string name="key_descr_nnbsp">Narrow non-breaking space</string> -->
<!-- <string name="key_descr_delete_word">Delete a word</string> -->
<!-- <string name="key_descr_forward_delete_word">Delete a word on the right</string> -->
<!-- <string name="key_descr_gesture">Gesture</string> -->
<string name="clipboard_history_heading">Ostatnio skopiowane elementy</string> <string name="clipboard_history_heading">Ostatnio skopiowane elementy</string>
<string name="clipboard_pin_heading">Przypięte</string> <string name="clipboard_pin_heading">Przypięte</string>
<string name="clipboard_remove_confirm">Usunąć ten element ze schowka?</string> <string name="clipboard_remove_confirm">Usunąć ten element ze schowka?</string>
<string name="clipboard_remove_confirmed">Tak</string> <string name="clipboard_remove_confirmed">Tak</string>
<!-- <string name="toast_no_voice_input">No voice typing app installed</string> -->
</resources> </resources>

View File

@@ -38,9 +38,9 @@ Este aplicativo não contém anúncios, não faz nenhuma solicitação de rede e
<string name="pref_category_typing">Digitação</string> <string name="pref_category_typing">Digitação</string>
<string name="pref_swipe_dist_title">Distância a deslizar</string> <string name="pref_swipe_dist_title">Distância a deslizar</string>
<string name="pref_swipe_dist_summary">Distância até acionar os cantos das teclas (%s)</string> <string name="pref_swipe_dist_summary">Distância até acionar os cantos das teclas (%s)</string>
<string name="pref_long_timeout_title">Tempo de pressionamento</string> <!-- <string name="pref_long_timeout_title">Long press timeout</string> -->
<string name="pref_long_interval_title">Intervalo de repetição de tecla</string> <string name="pref_long_interval_title">Intervalo de repetição de tecla</string>
<string name="pref_keyrepeat_enabled">Repetir tecla ao pressionar</string> <!-- <string name="pref_keyrepeat_enabled">Key repeat on long press</string> -->
<string name="pref_lock_double_tap_title">Tecle duas vezes no shift para travá-lo acionado</string> <string name="pref_lock_double_tap_title">Tecle duas vezes no shift para travá-lo acionado</string>
<string name="pref_lock_double_tap_summary">Ao invés de apertar e segurar por um tempo</string> <string name="pref_lock_double_tap_summary">Ao invés de apertar e segurar por um tempo</string>
<string name="pref_category_behavior">Comportamento</string> <string name="pref_category_behavior">Comportamento</string>
@@ -68,25 +68,24 @@ Este aplicativo não contém anúncios, não faz nenhuma solicitação de rede e
<string name="pref_theme_e_epaper">Papel Eletrônico</string> <string name="pref_theme_e_epaper">Papel Eletrônico</string>
<string name="pref_theme_e_desert">Deserto</string> <string name="pref_theme_e_desert">Deserto</string>
<string name="pref_theme_e_jungle">Selva</string> <string name="pref_theme_e_jungle">Selva</string>
<string name="pref_theme_e_monet">Monet (Sistema)</string> <!-- <string name="pref_theme_e_monet">Monet (System)</string> -->
<string name="pref_theme_e_monetlight">Monet (Claro)</string> <!-- <string name="pref_theme_e_monetlight">Monet (Light)</string> -->
<string name="pref_theme_e_monetdark">Monet (Escuro)</string> <!-- <string name="pref_theme_e_monetdark">Monet (Dark)</string> -->
<string name="pref_theme_e_rosepine">Rosé Pine</string> <string name="pref_swipe_dist_e_very_short">Bem curto</string>
<string name="pref_swipe_dist_e_very_short">Bem curta</string> <string name="pref_swipe_dist_e_short">Curto</string>
<string name="pref_swipe_dist_e_short">Curta</string>
<string name="pref_swipe_dist_e_default">Normal</string> <string name="pref_swipe_dist_e_default">Normal</string>
<string name="pref_swipe_dist_e_far">Longa</string> <string name="pref_swipe_dist_e_far">Longo</string>
<string name="pref_swipe_dist_e_very_far">Bem longa</string> <string name="pref_swipe_dist_e_very_far">Bem longo</string>
<string name="pref_key_horizontal_space">Distância horizontal entre teclas</string> <string name="pref_key_horizontal_space">Distância horizontal entre teclas</string>
<string name="pref_key_vertical_space">Distância vertical entre teclas</string> <string name="pref_key_vertical_space">Distância vertical entre teclas</string>
<string name="pref_border_config_title">Personalizar bordas</string> <string name="pref_border_config_title">Personalizar bordas</string>
<string name="pref_border_width_title">Largura de borda</string> <string name="pref_border_width_title">Largura de borda</string>
<string name="pref_corners_radius_title">Arredondamento de cantos</string> <string name="pref_corners_radius_title">Arredondamento de canto</string>
<string name="pref_circle_sensitivity_title">Sensibilidade do gesto circular</string> <!-- <string name="pref_circle_sensitivity_title">Circle gesture sensitivity</string> -->
<string name="pref_circle_sensitivity_e_high">Alta</string> <!-- <string name="pref_circle_sensitivity_e_high">High</string> -->
<string name="pref_circle_sensitivity_e_medium">Média</string> <!-- <string name="pref_circle_sensitivity_e_medium">Medium</string> -->
<string name="pref_circle_sensitivity_e_low">Baixa</string> <!-- <string name="pref_circle_sensitivity_e_low">Low</string> -->
<string name="pref_circle_sensitivity_e_disabled">Desativada</string> <!-- <string name="pref_circle_sensitivity_e_disabled">Disabled</string> -->
<string name="key_action_next">Próximo</string> <string name="key_action_next">Próximo</string>
<string name="key_action_done">Pronto</string> <string name="key_action_done">Pronto</string>
<string name="key_action_go">Ir</string> <string name="key_action_go">Ir</string>
@@ -120,19 +119,9 @@ Este aplicativo não contém anúncios, não faz nenhuma solicitação de rede e
<string name="key_descr_page_down">Page Down</string> <string name="key_descr_page_down">Page Down</string>
<string name="key_descr_home">Home</string> <string name="key_descr_home">Home</string>
<string name="key_descr_end">End</string> <string name="key_descr_end">End</string>
<string name="key_descr_clipboard">Área de transferência</string> <!-- <string name="key_descr_clipboard">Clipboard manager</string> -->
<string name="key_descr_combining">Combinação de diacríticos</string> <!-- <string name="clipboard_history_heading">Recently copied text</string> -->
<!-- <string name="key_descr_dead_key">Dead key</string> --> <!-- <string name="clipboard_pin_heading">Pinned</string> -->
<!-- <string name="key_descr_zwj">Zero width joiner</string> --> <!-- <string name="clipboard_remove_confirm">Remove this clipboard?</string> -->
<!-- <string name="key_descr_zwnj">Zero width non-joiner</string> --> <!-- <string name="clipboard_remove_confirmed">Yes</string> -->
<!-- <string name="key_descr_nbsp">Non-breaking space</string> -->
<!-- <string name="key_descr_nnbsp">Narrow non-breaking space</string> -->
<!-- <string name="key_descr_delete_word">Delete a word</string> -->
<!-- <string name="key_descr_forward_delete_word">Delete a word on the right</string> -->
<!-- <string name="key_descr_gesture">Gesture</string> -->
<string name="clipboard_history_heading">Textos recém copiados</string>
<string name="clipboard_pin_heading">Fixados</string>
<string name="clipboard_remove_confirm">Remover esta cópia?</string>
<string name="clipboard_remove_confirmed">Sim</string>
<!-- <string name="toast_no_voice_input">No voice typing app installed</string> -->
</resources> </resources>

View File

@@ -71,7 +71,6 @@ Această aplicație nu conține publicitate, nu folosește rețeaua deloc și e
<!-- <string name="pref_theme_e_monet">Monet (System)</string> --> <!-- <string name="pref_theme_e_monet">Monet (System)</string> -->
<!-- <string name="pref_theme_e_monetlight">Monet (Light)</string> --> <!-- <string name="pref_theme_e_monetlight">Monet (Light)</string> -->
<!-- <string name="pref_theme_e_monetdark">Monet (Dark)</string> --> <!-- <string name="pref_theme_e_monetdark">Monet (Dark)</string> -->
<!-- <string name="pref_theme_e_rosepine">Rosé Pine</string> -->
<string name="pref_swipe_dist_e_very_short">Foarte apropiată</string> <string name="pref_swipe_dist_e_very_short">Foarte apropiată</string>
<string name="pref_swipe_dist_e_short">Apropiată</string> <string name="pref_swipe_dist_e_short">Apropiată</string>
<string name="pref_swipe_dist_e_default">Normală</string> <string name="pref_swipe_dist_e_default">Normală</string>
@@ -121,18 +120,8 @@ Această aplicație nu conține publicitate, nu folosește rețeaua deloc și e
<!-- <string name="key_descr_home">Home</string> --> <!-- <string name="key_descr_home">Home</string> -->
<!-- <string name="key_descr_end">End</string> --> <!-- <string name="key_descr_end">End</string> -->
<!-- <string name="key_descr_clipboard">Clipboard manager</string> --> <!-- <string name="key_descr_clipboard">Clipboard manager</string> -->
<!-- <string name="key_descr_combining">Combining diacritic</string> -->
<!-- <string name="key_descr_dead_key">Dead key</string> -->
<!-- <string name="key_descr_zwj">Zero width joiner</string> -->
<!-- <string name="key_descr_zwnj">Zero width non-joiner</string> -->
<!-- <string name="key_descr_nbsp">Non-breaking space</string> -->
<!-- <string name="key_descr_nnbsp">Narrow non-breaking space</string> -->
<!-- <string name="key_descr_delete_word">Delete a word</string> -->
<!-- <string name="key_descr_forward_delete_word">Delete a word on the right</string> -->
<!-- <string name="key_descr_gesture">Gesture</string> -->
<!-- <string name="clipboard_history_heading">Recently copied text</string> --> <!-- <string name="clipboard_history_heading">Recently copied text</string> -->
<!-- <string name="clipboard_pin_heading">Pinned</string> --> <!-- <string name="clipboard_pin_heading">Pinned</string> -->
<!-- <string name="clipboard_remove_confirm">Remove this clipboard?</string> --> <!-- <string name="clipboard_remove_confirm">Remove this clipboard?</string> -->
<!-- <string name="clipboard_remove_confirmed">Yes</string> --> <!-- <string name="clipboard_remove_confirmed">Yes</string> -->
<!-- <string name="toast_no_voice_input">No voice typing app installed</string> -->
</resources> </resources>

View File

@@ -71,7 +71,6 @@
<string name="pref_theme_e_monet">Моне (системная)</string> <string name="pref_theme_e_monet">Моне (системная)</string>
<string name="pref_theme_e_monetlight">Моне (светлая)</string> <string name="pref_theme_e_monetlight">Моне (светлая)</string>
<string name="pref_theme_e_monetdark">Моне (темная)</string> <string name="pref_theme_e_monetdark">Моне (темная)</string>
<string name="pref_theme_e_rosepine">Розовая сосна</string>
<string name="pref_swipe_dist_e_very_short">Очень короткая</string> <string name="pref_swipe_dist_e_very_short">Очень короткая</string>
<string name="pref_swipe_dist_e_short">Короткая</string> <string name="pref_swipe_dist_e_short">Короткая</string>
<string name="pref_swipe_dist_e_default">Обычная</string> <string name="pref_swipe_dist_e_default">Обычная</string>
@@ -121,18 +120,8 @@
<string name="key_descr_home">Home</string> <string name="key_descr_home">Home</string>
<string name="key_descr_end">End</string> <string name="key_descr_end">End</string>
<string name="key_descr_clipboard">Менеджер буфера обмена</string> <string name="key_descr_clipboard">Менеджер буфера обмена</string>
<string name="key_descr_combining">Сочетание диакритических знаков</string>
<!-- <string name="key_descr_dead_key">Dead key</string> -->
<string name="key_descr_zwj">Соединитель нулевой ширины</string>
<string name="key_descr_zwnj">Разделитель нулевой ширины</string>
<string name="key_descr_nbsp">Неразрывный пробел</string>
<string name="key_descr_nnbsp">Узкий неразрывный пробел</string>
<!-- <string name="key_descr_delete_word">Delete a word</string> -->
<!-- <string name="key_descr_forward_delete_word">Delete a word on the right</string> -->
<!-- <string name="key_descr_gesture">Gesture</string> -->
<string name="clipboard_history_heading">Недавно скопированный текст</string> <string name="clipboard_history_heading">Недавно скопированный текст</string>
<string name="clipboard_pin_heading">Закреплено</string> <string name="clipboard_pin_heading">Закреплено</string>
<string name="clipboard_remove_confirm">Удалить этот буфер обмена?</string> <string name="clipboard_remove_confirm">Удалить этот буфер обмена?</string>
<string name="clipboard_remove_confirmed">Да</string> <string name="clipboard_remove_confirmed">Да</string>
<!-- <string name="toast_no_voice_input">No voice typing app installed</string> -->
</resources> </resources>

View File

@@ -71,7 +71,6 @@ Bu uygulama açık kaynaklıdır. Reklam içermez ve internete bağlanmaz."</str
<string name="pref_theme_e_monet">Monet (Sisteme uyarla)</string> <string name="pref_theme_e_monet">Monet (Sisteme uyarla)</string>
<string name="pref_theme_e_monetlight">Monet (Açık)</string> <string name="pref_theme_e_monetlight">Monet (Açık)</string>
<string name="pref_theme_e_monetdark">Monet (Koyu)</string> <string name="pref_theme_e_monetdark">Monet (Koyu)</string>
<!-- <string name="pref_theme_e_rosepine">Rosé Pine</string> -->
<string name="pref_swipe_dist_e_very_short">Çok kısa</string> <string name="pref_swipe_dist_e_very_short">Çok kısa</string>
<string name="pref_swipe_dist_e_short">Kısa</string> <string name="pref_swipe_dist_e_short">Kısa</string>
<string name="pref_swipe_dist_e_default">Normal</string> <string name="pref_swipe_dist_e_default">Normal</string>
@@ -121,18 +120,8 @@ Bu uygulama açık kaynaklıdır. Reklam içermez ve internete bağlanmaz."</str
<string name="key_descr_home">BAŞ(Sol yön tuşu)</string> <string name="key_descr_home">BAŞ(Sol yön tuşu)</string>
<string name="key_descr_end">SON(Sağ yön tuşu)</string> <string name="key_descr_end">SON(Sağ yön tuşu)</string>
<string name="key_descr_clipboard">Pano</string> <string name="key_descr_clipboard">Pano</string>
<!-- <string name="key_descr_combining">Combining diacritic</string> -->
<!-- <string name="key_descr_dead_key">Dead key</string> -->
<!-- <string name="key_descr_zwj">Zero width joiner</string> -->
<!-- <string name="key_descr_zwnj">Zero width non-joiner</string> -->
<!-- <string name="key_descr_nbsp">Non-breaking space</string> -->
<!-- <string name="key_descr_nnbsp">Narrow non-breaking space</string> -->
<!-- <string name="key_descr_delete_word">Delete a word</string> -->
<!-- <string name="key_descr_forward_delete_word">Delete a word on the right</string> -->
<!-- <string name="key_descr_gesture">Gesture</string> -->
<string name="clipboard_history_heading">Son kopyalanan metin</string> <string name="clipboard_history_heading">Son kopyalanan metin</string>
<string name="clipboard_pin_heading">Sabitlendi</string> <string name="clipboard_pin_heading">Sabitlendi</string>
<string name="clipboard_remove_confirm">Bu sabitlemeyi sil</string> <string name="clipboard_remove_confirm">Bu sabitlemeyi sil</string>
<string name="clipboard_remove_confirmed">Evet</string> <string name="clipboard_remove_confirmed">Evet</string>
<!-- <string name="toast_no_voice_input">No voice typing app installed</string> -->
</resources> </resources>

View File

@@ -71,7 +71,6 @@
<string name="pref_theme_e_monet">Моне (Системна)</string> <string name="pref_theme_e_monet">Моне (Системна)</string>
<string name="pref_theme_e_monetlight">Моне (Світла)</string> <string name="pref_theme_e_monetlight">Моне (Світла)</string>
<string name="pref_theme_e_monetdark">Моне (Темна)</string> <string name="pref_theme_e_monetdark">Моне (Темна)</string>
<string name="pref_theme_e_rosepine">Рожева сосна</string>
<string name="pref_swipe_dist_e_very_short">Дуже коротка</string> <string name="pref_swipe_dist_e_very_short">Дуже коротка</string>
<string name="pref_swipe_dist_e_short">Коротка</string> <string name="pref_swipe_dist_e_short">Коротка</string>
<string name="pref_swipe_dist_e_default">Звичайна</string> <string name="pref_swipe_dist_e_default">Звичайна</string>
@@ -121,18 +120,8 @@
<string name="key_descr_home">Home</string> <string name="key_descr_home">Home</string>
<string name="key_descr_end">End</string> <string name="key_descr_end">End</string>
<string name="key_descr_clipboard">Менеджер буфера обміну</string> <string name="key_descr_clipboard">Менеджер буфера обміну</string>
<string name="key_descr_combining">Комбінування діакритики</string>
<string name="key_descr_dead_key">Мертва клавіша</string>
<string name="key_descr_zwj">З\'єднувач нульової ширини</string>
<string name="key_descr_zwnj">Разділювач нульової ширини</string>
<string name="key_descr_nbsp">Нерозривний пробіл</string>
<string name="key_descr_nnbsp">Вузький нерозривний пробіл</string>
<!-- <string name="key_descr_delete_word">Delete a word</string> -->
<!-- <string name="key_descr_forward_delete_word">Delete a word on the right</string> -->
<!-- <string name="key_descr_gesture">Gesture</string> -->
<string name="clipboard_history_heading">Нещодавно скопійований текст</string> <string name="clipboard_history_heading">Нещодавно скопійований текст</string>
<string name="clipboard_pin_heading">Закріплено</string> <string name="clipboard_pin_heading">Закріплено</string>
<string name="clipboard_remove_confirm">Видалити цей буфер обміну?</string> <string name="clipboard_remove_confirm">Видалити цей буфер обміну?</string>
<string name="clipboard_remove_confirmed">Так</string> <string name="clipboard_remove_confirmed">Так</string>
<!-- <string name="toast_no_voice_input">No voice typing app installed</string> -->
</resources> </resources>

View File

@@ -71,7 +71,6 @@ Bây giờ đã hoàn hảo cho việc sử dụng hàng ngày.
<!-- <string name="pref_theme_e_monet">Monet (System)</string> --> <!-- <string name="pref_theme_e_monet">Monet (System)</string> -->
<!-- <string name="pref_theme_e_monetlight">Monet (Light)</string> --> <!-- <string name="pref_theme_e_monetlight">Monet (Light)</string> -->
<!-- <string name="pref_theme_e_monetdark">Monet (Dark)</string> --> <!-- <string name="pref_theme_e_monetdark">Monet (Dark)</string> -->
<!-- <string name="pref_theme_e_rosepine">Rosé Pine</string> -->
<string name="pref_swipe_dist_e_very_short">Rất gần</string> <string name="pref_swipe_dist_e_very_short">Rất gần</string>
<string name="pref_swipe_dist_e_short">Gần</string> <string name="pref_swipe_dist_e_short">Gần</string>
<string name="pref_swipe_dist_e_default">Trungbình</string> <string name="pref_swipe_dist_e_default">Trungbình</string>
@@ -121,18 +120,8 @@ Bây giờ đã hoàn hảo cho việc sử dụng hàng ngày.
<!-- <string name="key_descr_home">Home</string> --> <!-- <string name="key_descr_home">Home</string> -->
<!-- <string name="key_descr_end">End</string> --> <!-- <string name="key_descr_end">End</string> -->
<!-- <string name="key_descr_clipboard">Clipboard manager</string> --> <!-- <string name="key_descr_clipboard">Clipboard manager</string> -->
<!-- <string name="key_descr_combining">Combining diacritic</string> -->
<!-- <string name="key_descr_dead_key">Dead key</string> -->
<!-- <string name="key_descr_zwj">Zero width joiner</string> -->
<!-- <string name="key_descr_zwnj">Zero width non-joiner</string> -->
<!-- <string name="key_descr_nbsp">Non-breaking space</string> -->
<!-- <string name="key_descr_nnbsp">Narrow non-breaking space</string> -->
<!-- <string name="key_descr_delete_word">Delete a word</string> -->
<!-- <string name="key_descr_forward_delete_word">Delete a word on the right</string> -->
<!-- <string name="key_descr_gesture">Gesture</string> -->
<!-- <string name="clipboard_history_heading">Recently copied text</string> --> <!-- <string name="clipboard_history_heading">Recently copied text</string> -->
<!-- <string name="clipboard_pin_heading">Pinned</string> --> <!-- <string name="clipboard_pin_heading">Pinned</string> -->
<!-- <string name="clipboard_remove_confirm">Remove this clipboard?</string> --> <!-- <string name="clipboard_remove_confirm">Remove this clipboard?</string> -->
<!-- <string name="clipboard_remove_confirmed">Yes</string> --> <!-- <string name="clipboard_remove_confirmed">Yes</string> -->
<!-- <string name="toast_no_voice_input">No voice typing app installed</string> -->
</resources> </resources>

View File

@@ -71,7 +71,6 @@
<!-- <string name="pref_theme_e_monet">Monet (System)</string> --> <!-- <string name="pref_theme_e_monet">Monet (System)</string> -->
<!-- <string name="pref_theme_e_monetlight">Monet (Light)</string> --> <!-- <string name="pref_theme_e_monetlight">Monet (Light)</string> -->
<!-- <string name="pref_theme_e_monetdark">Monet (Dark)</string> --> <!-- <string name="pref_theme_e_monetdark">Monet (Dark)</string> -->
<!-- <string name="pref_theme_e_rosepine">Rosé Pine</string> -->
<string name="pref_swipe_dist_e_very_short">非常短</string> <string name="pref_swipe_dist_e_very_short">非常短</string>
<string name="pref_swipe_dist_e_short"></string> <string name="pref_swipe_dist_e_short"></string>
<string name="pref_swipe_dist_e_default">中(默认)</string> <string name="pref_swipe_dist_e_default">中(默认)</string>
@@ -121,18 +120,8 @@
<string name="key_descr_home">Home</string> <string name="key_descr_home">Home</string>
<string name="key_descr_end">End</string> <string name="key_descr_end">End</string>
<!-- <string name="key_descr_clipboard">Clipboard manager</string> --> <!-- <string name="key_descr_clipboard">Clipboard manager</string> -->
<!-- <string name="key_descr_combining">Combining diacritic</string> -->
<!-- <string name="key_descr_dead_key">Dead key</string> -->
<!-- <string name="key_descr_zwj">Zero width joiner</string> -->
<!-- <string name="key_descr_zwnj">Zero width non-joiner</string> -->
<!-- <string name="key_descr_nbsp">Non-breaking space</string> -->
<!-- <string name="key_descr_nnbsp">Narrow non-breaking space</string> -->
<!-- <string name="key_descr_delete_word">Delete a word</string> -->
<!-- <string name="key_descr_forward_delete_word">Delete a word on the right</string> -->
<!-- <string name="key_descr_gesture">Gesture</string> -->
<!-- <string name="clipboard_history_heading">Recently copied text</string> --> <!-- <string name="clipboard_history_heading">Recently copied text</string> -->
<!-- <string name="clipboard_pin_heading">Pinned</string> --> <!-- <string name="clipboard_pin_heading">Pinned</string> -->
<!-- <string name="clipboard_remove_confirm">Remove this clipboard?</string> --> <!-- <string name="clipboard_remove_confirm">Remove this clipboard?</string> -->
<!-- <string name="clipboard_remove_confirmed">Yes</string> --> <!-- <string name="clipboard_remove_confirmed">Yes</string> -->
<!-- <string name="toast_no_voice_input">No voice typing app installed</string> -->
</resources> </resources>

View File

@@ -31,7 +31,6 @@
<item>@string/pref_theme_e_monet</item> <item>@string/pref_theme_e_monet</item>
<item>@string/pref_theme_e_monetlight</item> <item>@string/pref_theme_e_monetlight</item>
<item>@string/pref_theme_e_monetdark</item> <item>@string/pref_theme_e_monetdark</item>
<item>@string/pref_theme_e_rosepine</item>
</string-array> </string-array>
<string-array name="pref_theme_values"> <string-array name="pref_theme_values">
<item>system</item> <item>system</item>
@@ -46,7 +45,6 @@
<item>monet</item> <item>monet</item>
<item>monetlight</item> <item>monetlight</item>
<item>monetdark</item> <item>monetdark</item>
<item>rosepine</item>
</string-array> </string-array>
<string-array name="pref_swipe_dist_entries"> <string-array name="pref_swipe_dist_entries">
<item>@string/pref_swipe_dist_e_very_short</item> <item>@string/pref_swipe_dist_e_very_short</item>

View File

@@ -1,6 +1,6 @@
<?xml version='1.0' encoding='UTF-8'?> <?xml version='1.0' encoding='UTF-8'?>
<resources> <resources>
<!-- DO NOT EDIT. This file is generated, run 'gradle genLayoutsList'. --> <!--DO NOT EDIT. This file is generated, see gen_layouts.py.-->
<string-array name="pref_layout_values"> <string-array name="pref_layout_values">
<item>system</item> <item>system</item>
<item>latn_qwerty_us</item> <item>latn_qwerty_us</item>
@@ -10,55 +10,35 @@
<item>arab_hamvaj_tly</item> <item>arab_hamvaj_tly</item>
<item>arab_pc</item> <item>arab_pc</item>
<item>arab_pc_ckb</item> <item>arab_pc_ckb</item>
<item>arab_pc_ckb_fa</item>
<item>arab_pc_hindu</item> <item>arab_pc_hindu</item>
<item>arab_pc_ir</item> <item>arab_pc_ir</item>
<item>armenian_ph_am</item> <item>armenian_ph_am</item>
<item>beng_national</item> <item>beng_national</item>
<item>beng_provat</item> <item>beng_provat</item>
<item>cyrl_fcuzhen_mn</item>
<item>cyrl_jcuken_kk</item>
<item>cyrl_jcuken_ru</item> <item>cyrl_jcuken_ru</item>
<item>cyrl_jcuken_uk</item> <item>cyrl_jcuken_uk</item>
<item>cyrl_lynyertz_sr</item> <item>cyrl_lynyertz_sr</item>
<item>cyrl_ueishsht</item> <item>cyrl_ueishsht</item>
<item>cyrl_yaverti</item> <item>cyrl_yaverti</item>
<item>cyrl_yqukeng_tj</item>
<item>cyrl_yxukeng_os</item>
<item>deva_alt</item> <item>deva_alt</item>
<item>deva_inscript</item> <item>deva_inscript</item>
<item>deva_phonetic_in</item>
<item>georgian_mes</item>
<item>georgian_qwerty</item>
<item>grek_qwerty</item> <item>grek_qwerty</item>
<item>guj_phonetic_in</item> <item>guj_phonetic_in</item>
<item>hang_dubeolsik_kr</item> <item>hang_dubeolsik_kr</item>
<item>hebr_1_il</item> <item>hebr_1_il</item>
<item>hebr_2_il</item> <item>hebr_2_il</item>
<item>kann_kannada</item>
<item>latn_azerty_be</item>
<item>latn_azerty_fr</item> <item>latn_azerty_fr</item>
<item>latn_bepo_fr</item> <item>latn_bepo_fr</item>
<item>latn_bone</item> <item>latn_bone</item>
<item>latn_neo2</item> <item>latn_neo2</item>
<item>latn_qwerty_apl</item>
<item>latn_qwerty_az</item>
<item>latn_qwerty_bqn</item>
<item>latn_qwerty_br</item> <item>latn_qwerty_br</item>
<item>latn_qwerty_cy</item>
<item>latn_qwerty_cz</item> <item>latn_qwerty_cz</item>
<item>latn_qwerty_da</item> <item>latn_qwerty_da</item>
<item>latn_qwerty_es</item> <item>latn_qwerty_es</item>
<item>latn_qwerty_et</item>
<item>latn_qwerty_ga</item>
<item>latn_qwerty_gb</item> <item>latn_qwerty_gb</item>
<item>latn_qwerty_haw</item>
<item>latn_qwerty_hu</item> <item>latn_qwerty_hu</item>
<item>latn_qwerty_jp</item> <item>latn_qwerty_jp</item>
<item>latn_qwerty_kk</item>
<item>latn_qwerty_lt</item>
<item>latn_qwerty_lv</item> <item>latn_qwerty_lv</item>
<item>latn_qwerty_mt</item>
<item>latn_qwerty_no</item> <item>latn_qwerty_no</item>
<item>latn_qwerty_pl</item> <item>latn_qwerty_pl</item>
<item>latn_qwerty_ro</item> <item>latn_qwerty_ro</item>
@@ -67,20 +47,15 @@
<item>latn_qwerty_sr</item> <item>latn_qwerty_sr</item>
<item>latn_qwerty_tly</item> <item>latn_qwerty_tly</item>
<item>latn_qwerty_tr</item> <item>latn_qwerty_tr</item>
<item>latn_qwerty_uz</item>
<item>latn_qwerty_vi</item> <item>latn_qwerty_vi</item>
<item>latn_qwertz</item> <item>latn_qwertz</item>
<item>latn_qwertz_cz</item> <item>latn_qwertz_cz</item>
<item>latn_qwertz_cz_diacritics</item>
<item>latn_qwertz_cz_multifunctional</item> <item>latn_qwertz_cz_multifunctional</item>
<item>latn_qwertz_de</item> <item>latn_qwertz_de</item>
<item>latn_qwertz_fr_ch</item> <item>latn_qwertz_fr_ch</item>
<item>latn_qwertz_hu</item> <item>latn_qwertz_hu</item>
<item>latn_qwertz_sk</item> <item>latn_qwertz_sk</item>
<item>latn_qwertz_sq</item>
<item>latn_workman_us</item>
<item>shaw_imperial_en</item> <item>shaw_imperial_en</item>
<item>tamil_default</item>
<item>urdu_phonetic_ur</item> <item>urdu_phonetic_ur</item>
<item>custom</item> <item>custom</item>
</string-array> </string-array>
@@ -92,56 +67,36 @@
<item>Arabic Alt</item> <item>Arabic Alt</item>
<item>Talysh (تالشی همواج)</item> <item>Talysh (تالشی همواج)</item>
<item>Arabic PC</item> <item>Arabic PC</item>
<item>Kurdish (کوردی) QWERTY</item> <item>Kurdish (کوردی)</item>
<item>Central Kurdish (سۆرانی) Persian Layout</item>
<item>Arabic PC (Hindu numerals)</item> <item>Arabic PC (Hindu numerals)</item>
<item>Persian PC</item> <item>Persian PC</item>
<item>Armenian</item> <item>Armenian</item>
<item>বাংলা (জাতীয়)</item> <item>বাংলা (জাতীয়)</item>
<item>বাংলা (প্রভাত)</item> <item>বাংলা (প্রভাত)</item>
<item>ФЦУЖЭН (Монгол)</item>
<item>ЙЦУКЕН (Қазақша)</item>
<item>ЙЦУКЕН (Русский)</item> <item>ЙЦУКЕН (Русский)</item>
<item>ЙЦУКЕН (Українська)</item> <item>ЙЦУКЕН (Українська)</item>
<item>ЉЊЕРТЗ (Српски)</item> <item>ЉЊЕРТЗ (Српски)</item>
<item>УЕИШЩ (Български, БДС)</item> <item>УЕИШЩ (Български, БДС)</item>
<item>ЯВЕРТЪ</item> <item>ЯВЕРТЪ</item>
<item>Tajiki Persian (Тоҷикӣ)</item>
<item>Old Church Slavonic (Црькъвьнословѣньскъ ѩзыкъ)</item>
<item>देवनागरी (हिंदी)-2</item> <item>देवनागरी (हिंदी)-2</item>
<item>देवनागरी (हिंदी)-1</item> <item>देवनागरी (हिंदी)-1</item>
<item>हिन्दी फोनेटिक - Hindi Phonetic</item>
<item>ქართული (MES)</item>
<item>ქართული (QWERTY)</item>
<item>QWERTY (Greek)</item> <item>QWERTY (Greek)</item>
<item>ગુજરાતી ફોનેટિક - Gujarati Phonetic</item> <item>ગુજરાતી ફોનેટિક - Gujarati Phonetic</item>
<item>두벌식 (Korean)</item> <item>두벌식 (Korean)</item>
<item>Hebrew 1</item> <item>Hebrew 1</item>
<item>Hebrew 2</item> <item>Hebrew 2</item>
<item>ಕನ್ನಡ - Kannada</item>
<item>AZERTY (Belgian)</item>
<item>AZERTY (Français)</item> <item>AZERTY (Français)</item>
<item>BEPO (Français)</item> <item>BEPO (Français)</item>
<item>Bone</item> <item>Bone</item>
<item>Neo 2</item> <item>Neo 2</item>
<item>QWERTY (APL)</item>
<item>QWERTY (Azərbaycanca)</item>
<item>QWERTY (BQN)</item>
<item>QWERTY (Brasileiro)</item> <item>QWERTY (Brasileiro)</item>
<item>QWERTY (Welsh)</item>
<item>QWERTY (Czech)</item> <item>QWERTY (Czech)</item>
<item>QWERTY (Danish)</item> <item>QWERTY (Danish)</item>
<item>QWERTY (Español)</item> <item>QWERTY (Español)</item>
<item>QWERTY (eesti)</item>
<item>QWERTY (Irish)</item>
<item>QWERTY (UK)</item> <item>QWERTY (UK)</item>
<item>QWERTY (Hawaiian)</item>
<item>QWERTY (Magyar)</item> <item>QWERTY (Magyar)</item>
<item>QWERTY (Japan)</item> <item>QWERTY (Japan)</item>
<item>QWERTY (Qazaqşa)</item>
<item>QWERTY (Lietuviškai)</item>
<item>QWERTY (Latvian)</item> <item>QWERTY (Latvian)</item>
<item>QWERTY (Malti)</item>
<item>QWERTY (Norwegian)</item> <item>QWERTY (Norwegian)</item>
<item>QWERTY (Polski)</item> <item>QWERTY (Polski)</item>
<item>QWERTY (Română)</item> <item>QWERTY (Română)</item>
@@ -150,20 +105,15 @@
<item>QWERTY (Srpski, latinica)</item> <item>QWERTY (Srpski, latinica)</item>
<item>QWERTY (Talysh New Latin)</item> <item>QWERTY (Talysh New Latin)</item>
<item>QWERTY (Türkçe)</item> <item>QWERTY (Türkçe)</item>
<item>QWERTY (Oʻzbekcha)</item>
<item>QWERTY (Vietnamese)</item> <item>QWERTY (Vietnamese)</item>
<item>QWERTZ</item> <item>QWERTZ</item>
<item>QWERTZ (Czech)</item> <item>QWERTZ (Czech)</item>
<item>QWERTZ (Czech with diacritic keys)</item>
<item>QWERTZ Multifunctional (Czech)</item> <item>QWERTZ Multifunctional (Czech)</item>
<item>QWERTZ (Deutsch)</item> <item>QWERTZ (Deutsch)</item>
<item>QWERTZ (Swiss French)</item> <item>QWERTZ (Swiss French)</item>
<item>QWERTZ (Magyar)</item> <item>QWERTZ (Magyar)</item>
<item>QWERTZ (Slovak)</item> <item>QWERTZ (Slovak)</item>
<item>QWERTZ (Albanian)</item>
<item>WORKMAN (US)</item>
<item>Shaw Imperial</item> <item>Shaw Imperial</item>
<item>தமிழ்</item>
<item>Urdu Phonetic</item> <item>Urdu Phonetic</item>
<item>@string/pref_layout_e_custom</item> <item>@string/pref_layout_e_custom</item>
</string-array> </string-array>
@@ -176,55 +126,35 @@
<item>@xml/arab_hamvaj_tly</item> <item>@xml/arab_hamvaj_tly</item>
<item>@xml/arab_pc</item> <item>@xml/arab_pc</item>
<item>@xml/arab_pc_ckb</item> <item>@xml/arab_pc_ckb</item>
<item>@xml/arab_pc_ckb_fa</item>
<item>@xml/arab_pc_hindu</item> <item>@xml/arab_pc_hindu</item>
<item>@xml/arab_pc_ir</item> <item>@xml/arab_pc_ir</item>
<item>@xml/armenian_ph_am</item> <item>@xml/armenian_ph_am</item>
<item>@xml/beng_national</item> <item>@xml/beng_national</item>
<item>@xml/beng_provat</item> <item>@xml/beng_provat</item>
<item>@xml/cyrl_fcuzhen_mn</item>
<item>@xml/cyrl_jcuken_kk</item>
<item>@xml/cyrl_jcuken_ru</item> <item>@xml/cyrl_jcuken_ru</item>
<item>@xml/cyrl_jcuken_uk</item> <item>@xml/cyrl_jcuken_uk</item>
<item>@xml/cyrl_lynyertz_sr</item> <item>@xml/cyrl_lynyertz_sr</item>
<item>@xml/cyrl_ueishsht</item> <item>@xml/cyrl_ueishsht</item>
<item>@xml/cyrl_yaverti</item> <item>@xml/cyrl_yaverti</item>
<item>@xml/cyrl_yqukeng_tj</item>
<item>@xml/cyrl_yxukeng_os</item>
<item>@xml/deva_alt</item> <item>@xml/deva_alt</item>
<item>@xml/deva_inscript</item> <item>@xml/deva_inscript</item>
<item>@xml/deva_phonetic_in</item>
<item>@xml/georgian_mes</item>
<item>@xml/georgian_qwerty</item>
<item>@xml/grek_qwerty</item> <item>@xml/grek_qwerty</item>
<item>@xml/guj_phonetic_in</item> <item>@xml/guj_phonetic_in</item>
<item>@xml/hang_dubeolsik_kr</item> <item>@xml/hang_dubeolsik_kr</item>
<item>@xml/hebr_1_il</item> <item>@xml/hebr_1_il</item>
<item>@xml/hebr_2_il</item> <item>@xml/hebr_2_il</item>
<item>@xml/kann_kannada</item>
<item>@xml/latn_azerty_be</item>
<item>@xml/latn_azerty_fr</item> <item>@xml/latn_azerty_fr</item>
<item>@xml/latn_bepo_fr</item> <item>@xml/latn_bepo_fr</item>
<item>@xml/latn_bone</item> <item>@xml/latn_bone</item>
<item>@xml/latn_neo2</item> <item>@xml/latn_neo2</item>
<item>@xml/latn_qwerty_apl</item>
<item>@xml/latn_qwerty_az</item>
<item>@xml/latn_qwerty_bqn</item>
<item>@xml/latn_qwerty_br</item> <item>@xml/latn_qwerty_br</item>
<item>@xml/latn_qwerty_cy</item>
<item>@xml/latn_qwerty_cz</item> <item>@xml/latn_qwerty_cz</item>
<item>@xml/latn_qwerty_da</item> <item>@xml/latn_qwerty_da</item>
<item>@xml/latn_qwerty_es</item> <item>@xml/latn_qwerty_es</item>
<item>@xml/latn_qwerty_et</item>
<item>@xml/latn_qwerty_ga</item>
<item>@xml/latn_qwerty_gb</item> <item>@xml/latn_qwerty_gb</item>
<item>@xml/latn_qwerty_haw</item>
<item>@xml/latn_qwerty_hu</item> <item>@xml/latn_qwerty_hu</item>
<item>@xml/latn_qwerty_jp</item> <item>@xml/latn_qwerty_jp</item>
<item>@xml/latn_qwerty_kk</item>
<item>@xml/latn_qwerty_lt</item>
<item>@xml/latn_qwerty_lv</item> <item>@xml/latn_qwerty_lv</item>
<item>@xml/latn_qwerty_mt</item>
<item>@xml/latn_qwerty_no</item> <item>@xml/latn_qwerty_no</item>
<item>@xml/latn_qwerty_pl</item> <item>@xml/latn_qwerty_pl</item>
<item>@xml/latn_qwerty_ro</item> <item>@xml/latn_qwerty_ro</item>
@@ -233,20 +163,15 @@
<item>@xml/latn_qwerty_sr</item> <item>@xml/latn_qwerty_sr</item>
<item>@xml/latn_qwerty_tly</item> <item>@xml/latn_qwerty_tly</item>
<item>@xml/latn_qwerty_tr</item> <item>@xml/latn_qwerty_tr</item>
<item>@xml/latn_qwerty_uz</item>
<item>@xml/latn_qwerty_vi</item> <item>@xml/latn_qwerty_vi</item>
<item>@xml/latn_qwertz</item> <item>@xml/latn_qwertz</item>
<item>@xml/latn_qwertz_cz</item> <item>@xml/latn_qwertz_cz</item>
<item>@xml/latn_qwertz_cz_diacritics</item>
<item>@xml/latn_qwertz_cz_multifunctional</item> <item>@xml/latn_qwertz_cz_multifunctional</item>
<item>@xml/latn_qwertz_de</item> <item>@xml/latn_qwertz_de</item>
<item>@xml/latn_qwertz_fr_ch</item> <item>@xml/latn_qwertz_fr_ch</item>
<item>@xml/latn_qwertz_hu</item> <item>@xml/latn_qwertz_hu</item>
<item>@xml/latn_qwertz_sk</item> <item>@xml/latn_qwertz_sk</item>
<item>@xml/latn_qwertz_sq</item>
<item>@xml/latn_workman_us</item>
<item>@xml/shaw_imperial_en</item> <item>@xml/shaw_imperial_en</item>
<item>@xml/tamil_default</item>
<item>@xml/urdu_phonetic_ur</item> <item>@xml/urdu_phonetic_ur</item>
<item>-1</item> <item>-1</item>
</integer-array> </integer-array>

View File

@@ -71,7 +71,6 @@ This application contains no ads, doesn't make any network requests and is Open
<string name="pref_theme_e_monet">Monet (System)</string> <string name="pref_theme_e_monet">Monet (System)</string>
<string name="pref_theme_e_monetlight">Monet (Light)</string> <string name="pref_theme_e_monetlight">Monet (Light)</string>
<string name="pref_theme_e_monetdark">Monet (Dark)</string> <string name="pref_theme_e_monetdark">Monet (Dark)</string>
<string name="pref_theme_e_rosepine">Rosé Pine</string>
<string name="pref_swipe_dist_e_very_short">Very short</string> <string name="pref_swipe_dist_e_very_short">Very short</string>
<string name="pref_swipe_dist_e_short">Short</string> <string name="pref_swipe_dist_e_short">Short</string>
<string name="pref_swipe_dist_e_default">Normal</string> <string name="pref_swipe_dist_e_default">Normal</string>
@@ -121,18 +120,8 @@ This application contains no ads, doesn't make any network requests and is Open
<string name="key_descr_home">Home</string> <string name="key_descr_home">Home</string>
<string name="key_descr_end">End</string> <string name="key_descr_end">End</string>
<string name="key_descr_clipboard">Clipboard manager</string> <string name="key_descr_clipboard">Clipboard manager</string>
<string name="key_descr_combining">Combining diacritic</string>
<string name="key_descr_dead_key">Dead key</string>
<string name="key_descr_zwj">Zero width joiner</string>
<string name="key_descr_zwnj">Zero width non-joiner</string>
<string name="key_descr_nbsp">Non-breaking space</string>
<string name="key_descr_nnbsp">Narrow non-breaking space</string>
<string name="key_descr_delete_word">Delete a word</string>
<string name="key_descr_forward_delete_word">Delete a word on the right</string>
<string name="key_descr_gesture">Gesture</string>
<string name="clipboard_history_heading">Recently copied text</string> <string name="clipboard_history_heading">Recently copied text</string>
<string name="clipboard_pin_heading">Pinned</string> <string name="clipboard_pin_heading">Pinned</string>
<string name="clipboard_remove_confirm">Remove this clipboard?</string> <string name="clipboard_remove_confirm">Remove this clipboard?</string>
<string name="clipboard_remove_confirmed">Yes</string> <string name="clipboard_remove_confirmed">Yes</string>
<string name="toast_no_voice_input">No voice typing app installed</string>
</resources> </resources>

View File

@@ -56,33 +56,5 @@
<item name="android:layout_marginHorizontal">16dp</item> <item name="android:layout_marginHorizontal">16dp</item>
<item name="android:layout_gravity">center</item> <item name="android:layout_gravity">center</item>
</style> </style>
<style name="anim">
<item name="android:adjustViewBounds">true</item>
<item name="android:layout_height">120dp</item>
<item name="android:layout_weight">1</item>
<item name="android:layout_width">wrap_content</item>
</style>
<style name="anim_text">
<item name="android:layout_gravity">center</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_marginHorizontal">20dp</item>
<item name="android:layout_weight">1</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:textAlignment">center</item>
<item name="android:textSize">18dp</item>
<item name="android:textStyle">bold</item>
</style>
<style name="anim_box">
<item name="android:layout_gravity">center</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_marginVertical">16dp</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:orientation">horizontal</item>
</style>
<style name="appTheme" parent="@android:style/Theme.DeviceDefault.DayNight"/> <style name="appTheme" parent="@android:style/Theme.DeviceDefault.DayNight"/>
<style name="settingsTheme" parent="appTheme">
<!-- Setting this in the activity theme so it propagate to nested
preference screens. -->
<item name="android:fitsSystemWindows">true</item>
</style>
</resources> </resources>

View File

@@ -193,33 +193,14 @@
</style> </style>
<style name="MonetDark" parent="@style/BaseTheme"> <style name="MonetDark" parent="@style/BaseTheme">
<item name="android:isLightTheme">false</item> <item name="android:isLightTheme">false</item>
<item name="colorKeyboard">@android:color/system_neutral1_900</item> <item name="colorKeyboard">@android:color/system_accent1_900</item>
<item name="colorKey">@android:color/system_accent2_800</item> <item name="colorKey">@android:color/system_accent1_800</item>
<item name="colorKeyActivated">@android:color/system_accent1_800</item> <item name="colorKeyActivated">@android:color/system_accent1_600</item>
<item name="colorLabel">@android:color/system_neutral1_0</item> <item name="colorLabel">@android:color/system_neutral1_0</item>
<item name="colorLabelActivated">@android:color/system_accent1_400</item> <item name="colorLabelActivated">@android:color/system_accent2_300</item>
<item name="colorLabelLocked">@android:color/system_accent1_100</item> <item name="colorLabelLocked">@android:color/system_accent2_100</item>
<item name="colorSubLabel">@android:color/system_neutral1_300</item> <item name="colorSubLabel">@android:color/system_neutral1_300</item>
<item name="emoji_button_bg">?colorKeyActivated</item> <item name="emoji_button_bg">?colorKeyActivated</item>
<item name="emoji_color">@android:color/system_neutral1_900</item> <item name="emoji_color">@android:color/system_accent1_900</item>
</style>
<style name="RosePine" parent="BaseTheme">
<item name="android:isLightTheme">false</item>
<item name="colorKeyboard">#191724</item>
<item name="colorKey">#26233a</item>
<item name="colorKeyActivated">#403d52</item>
<item name="keyBorderWidth">0dp</item>
<item name="keyBorderWidthActivated">1dp</item>
<item name="keyBorderColorLeft">#6e6a86</item>
<item name="keyBorderColorTop">#6e6a86</item>
<item name="keyBorderColorRight">#6e6a86</item>
<item name="keyBorderColorBottom">#6e6a86</item>
<item name="colorLabel">#e0def4</item>
<item name="colorLabelActivated">#c4a7e7</item>
<item name="colorLabelLocked">#31748f</item>
<item name="colorSubLabel">#6e6a86</item>
<item name="keyBorderRadius">1dp</item>
<item name="emoji_button_bg">#26233a</item>
<item name="emoji_color">#e0def4</item>
</style> </style>
</resources> </resources>

View File

@@ -6,9 +6,5 @@
<dimen name="emoji_text_size">28dp</dimen> <dimen name="emoji_text_size">28dp</dimen>
<dimen name="clipboard_view_height">300dp</dimen> <dimen name="clipboard_view_height">300dp</dimen>
<dimen name="pref_button_size">28dp</dimen> <dimen name="pref_button_size">28dp</dimen>
<!-- Margin needed to accomodate the gesture nav bar on Android 15. Found in <bool name="debug_logs">false</bool> <!-- Will be overwritten automatically by Gradle for the debug build variant -->
[core/res/res/values/dimens.xml]. -->
<dimen name="bottom_inset_min">48dp</dimen>
<!-- Will be overwritten automatically by Gradle for the debug build variant -->
<bool name="debug_logs">false</bool>
</resources> </resources>

View File

@@ -2,7 +2,7 @@
<row height="0.95"> <row height="0.95">
<key width="1.7" key0="ctrl" key1="loc switch_greekmath" key2="loc meta" key3="loc switch_clipboard" key4="switch_numeric"/> <key width="1.7" key0="ctrl" key1="loc switch_greekmath" key2="loc meta" key3="loc switch_clipboard" key4="switch_numeric"/>
<key width="1.1" key0="fn" key1="loc alt" key2="loc change_method" key3="switch_emoji" key4="config"/> <key width="1.1" key0="fn" key1="loc alt" key2="loc change_method" key3="switch_emoji" key4="config"/>
<key width="4.4" key0="space" key7="switch_forward" key8="switch_backward" key5="cursor_left" key6="cursor_right"/> <key width="4.4" key0="space" key7="switch_forward" key8="switch_backward" key5="cursor_left" key6="cursor_right" slider="true"/>
<key width="1.1" key0="loc compose" key7="up" key6="right" key5="left" key8="down" key1="loc home" key2="loc page_up" key3="loc end" key4="loc page_down"/> <key width="1.1" key0="loc compose" key7="up" key6="right" key5="left" key8="down" key1="loc home" key2="loc page_up" key3="loc end" key4="loc page_down"/>
<key width="1.7" key0="enter" key1="loc voice_typing" key2="action"/> <key width="1.7" key0="enter" key1="loc voice_typing" key2="action"/>
</row> </row>

View File

@@ -3,7 +3,7 @@
<keyboard bottom_row="false"> <keyboard bottom_row="false">
<row height="0.95"> <row height="0.95">
<key key0="switch_back_clipboard"/> <key key0="switch_back_clipboard"/>
<key width="3" key0="space" key5="cursor_left" key6="cursor_right"/> <key width="3" key0="space" key5="cursor_left" key6="cursor_right" slider="true"/>
<key key0="backspace" key2="delete"/> <key key0="backspace" key2="delete"/>
<key key0="enter" key2="action"/> <key key0="enter" key2="action"/>
</row> </row>

View File

@@ -3,7 +3,7 @@
<keyboard bottom_row="false"> <keyboard bottom_row="false">
<row height="0.95"> <row height="0.95">
<key key0="switch_back_emoji"/> <key key0="switch_back_emoji"/>
<key width="3" key0="space" key5="cursor_left" key6="cursor_right"/> <key width="3" key0="space" key5="cursor_left" key6="cursor_right" slider="true"/>
<key key0="backspace" key2="delete"/> <key key0="backspace" key2="delete"/>
<key key0="enter" key2="action"/> <key key0="enter" key2="action"/>
</row> </row>

View File

@@ -17,7 +17,7 @@
<key key0="σ" key3="←" key4="∂"/> <key key0="σ" key3="←" key4="∂"/>
<key key0="δ" key3="↓" key4="∫"/> <key key0="δ" key3="↓" key4="∫"/>
<key key0="φ" key3="→" key4="∃"/> <key key0="φ" key3="→" key4="∃"/>
<key key0="γ" key3="∋" key4="∈"/> <key key0="γ" key4="∈"/>
<key key0="η" key1="⊕" key4="4"/> <key key0="η" key1="⊕" key4="4"/>
<key key0="ξ" key1="⊖" key3="" key4="5"/> <key key0="ξ" key1="⊖" key3="" key4="5"/>
<key key0="κ" key1="⊙" key3="" key4="6"/> <key key0="κ" key1="⊙" key3="" key4="6"/>

View File

@@ -1,65 +1,46 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<input-method xmlns:android="http://schemas.android.com/apk/res/android" android:settingsActivity="juloo.keyboard2.SettingsActivity" android:supportsSwitchingToNextInputMethod="true"> <input-method xmlns:android="http://schemas.android.com/apk/res/android" android:settingsActivity="juloo.keyboard2.SettingsActivity" android:supportsSwitchingToNextInputMethod="true">
<!-- The first entry of the list makes latn_qwerty_us the default layout for
unrecognized locales. -->
<subtype android:label="%s" android:languageTag="en" android:imeSubtypeLocale="en" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us"/>
<subtype android:label="%s" android:languageTag="ar" android:imeSubtypeLocale="ar" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=arabic,default_layout=arab_pc_hindu"/> <subtype android:label="%s" android:languageTag="ar" android:imeSubtypeLocale="ar" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=arabic,default_layout=arab_pc_hindu"/>
<subtype android:label="%s" android:languageTag="ar" android:imeSubtypeLocale="ar_TN" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=arabic,default_layout=arab_pc"/> <subtype android:label="%s" android:languageTag="ar" android:imeSubtypeLocale="ar_TN" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=arabic,default_layout=arab_pc"/>
<subtype android:label="%s" android:languageTag="ay" android:imeSubtypeLocale="ay_AM" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=armenian,default_layout=armenian_ph_am"/> <subtype android:label="%s" android:languageTag="ay" android:imeSubtypeLocale="ay_AM" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=armenian,default_layout=armenian_ph_am"/>
<subtype android:label="%s" android:languageTag="az" android:imeSubtypeLocale="az_AZ" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_az,extra_keys=accent_trema:ü:ö@w|accent_cedille:ç:ş@s|ğ@g|ı@k|ə@l"/>
<subtype android:label="%s" android:languageTag="be" android:imeSubtypeLocale="be_BY" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=cyrillic,default_layout=cyrl_jcuken_ru,extra_keys=ґ|є|і|ї|ў"/> <subtype android:label="%s" android:languageTag="be" android:imeSubtypeLocale="be_BY" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=cyrillic,default_layout=cyrl_jcuken_ru,extra_keys=ґ|є|і|ї|ў"/>
<subtype android:label="%s" android:languageTag="bg" android:imeSubtypeLocale="bg_BG" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=cyrillic,default_layout=cyrl_ueishsht,extra_keys=€"/> <subtype android:label="%s" android:languageTag="bg" android:imeSubtypeLocale="bg_BG" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=cyrillic,default_layout=cyrl_ueishsht,extra_keys=€"/>
<subtype android:label="%s" android:languageTag="bn" android:imeSubtypeLocale="bn_BD" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us,extra_keys=৳"/> <subtype android:label="%s" android:languageTag="bn" android:imeSubtypeLocale="bn_BD" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us,extra_keys=৳"/>
<subtype android:label="%s" android:languageTag="cs" android:imeSubtypeLocale="cs_CZ" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwertz_cz,extra_keys=accent_aigu:á:é:í:ó:ú:ý@d|accent_ring:ů@s|accent_caron:č:ě:ň:ř:š:ž:ď:ť@f"/> <subtype android:label="%s" android:languageTag="cs" android:imeSubtypeLocale="cs_CZ" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwertz_cz,extra_keys=accent_aigu:á:é:í:ó:ú:ý@d|accent_ring:ů@s|accent_caron:č:ě:ň:ř:š:ž:ď:ť@f"/>
<subtype android:label="%s" android:languageTag="cy" android:imeSubtypeLocale="cy_GB" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_cy"/>
<subtype android:label="%s" android:languageTag="da" android:imeSubtypeLocale="da_DK" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_da,extra_keys=€|æ|å|ø"/> <subtype android:label="%s" android:languageTag="da" android:imeSubtypeLocale="da_DK" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_da,extra_keys=€|æ|å|ø"/>
<subtype android:label="%s" android:languageTag="de" android:imeSubtypeLocale="de_DE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwertz_de,extra_keys=accent_trema:ä:ö:ü@u|ß|€"/> <subtype android:label="%s" android:languageTag="de" android:imeSubtypeLocale="de_DE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwertz_de,extra_keys=accent_trema:ä:ö:ü@u|ß|€"/>
<subtype android:label="%s" android:languageTag="de-BE" android:imeSubtypeLocale="de_BE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_azerty_be,extra_keys=accent_grave:è@f|accent_aigu:á:é:í:ó:ú:ý:j́@d|accent_circonflexe:ê@f|accent_cedille:ç@c|accent_trema@u|€"/>
<subtype android:label="%s" android:languageTag="el" android:imeSubtypeLocale="el" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=grek_qwerty,extra_keys=£@l|€"/> <subtype android:label="%s" android:languageTag="el" android:imeSubtypeLocale="el" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=grek_qwerty,extra_keys=£@l|€"/>
<subtype android:label="%s" android:languageTag="en-AU" android:imeSubtypeLocale="en_AU" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us"/>
<subtype android:label="%s" android:languageTag="en-CA" android:imeSubtypeLocale="en_CA" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us"/> <subtype android:label="%s" android:languageTag="en-CA" android:imeSubtypeLocale="en_CA" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us"/>
<subtype android:label="%s" android:languageTag="en-GB" android:imeSubtypeLocale="en_GB" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_gb,extra_keys=£@l"/> <subtype android:label="%s" android:languageTag="en-GB" android:imeSubtypeLocale="en_GB" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_gb,extra_keys=£@l"/>
<subtype android:label="%s" android:languageTag="en-IN" android:imeSubtypeLocale="en_IN" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us"/>
<subtype android:label="%s" android:languageTag="en-US" android:imeSubtypeLocale="en_US" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us"/> <subtype android:label="%s" android:languageTag="en-US" android:imeSubtypeLocale="en_US" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us"/>
<subtype android:label="%s" android:languageTag="es" android:imeSubtypeLocale="es_ES" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_es,extra_keys=accent_aigu:á:é:í:ó:ú@d|accent_tilde:ñ@n|accent_grave@f|accent_trema@u|€"/> <subtype android:label="%s" android:languageTag="es" android:imeSubtypeLocale="es_ES" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_es,extra_keys=accent_aigu:á:é:í:ó:ú@d|accent_tilde:ñ@n|accent_grave@f|accent_trema@u|€"/>
<subtype android:label="%s" android:languageTag="et" android:imeSubtypeLocale="et_EE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_et,extra_keys=accent_trema:ä:ö:ü@u|accent_tilde:õ@o|accent_caron:š:ž@s|€"/>
<subtype android:label="%s" android:languageTag="fa" android:imeSubtypeLocale="fa_IR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=arab_pc_ir"/> <subtype android:label="%s" android:languageTag="fa" android:imeSubtypeLocale="fa_IR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=arab_pc_ir"/>
<subtype android:label="%s" android:languageTag="fr-BE" android:imeSubtypeLocale="fr_BE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_azerty_be,extra_keys=accent_grave:è@f|accent_aigu:á:é:í:ó:ú:ý:j́@d|accent_circonflexe:ê@f|accent_cedille:ç@c|accent_trema@u|€"/>
<subtype android:label="%s" android:languageTag="fr-CA" android:imeSubtypeLocale="fr_CA" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_azerty_fr,extra_keys=accent_grave:à:è:ù@f|accent_aigu:é@d|accent_circonflexe:â:ê:ô@f|accent_cedille:ç@c|accent_trema:ë:ï:ü:ÿ@u"/> <subtype android:label="%s" android:languageTag="fr-CA" android:imeSubtypeLocale="fr_CA" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_azerty_fr,extra_keys=accent_grave:à:è:ù@f|accent_aigu:é@d|accent_circonflexe:â:ê:ô@f|accent_cedille:ç@c|accent_trema:ë:ï:ü:ÿ@u"/>
<subtype android:label="%s" android:languageTag="fr-CH" android:imeSubtypeLocale="fr_CH" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwertz_fr_ch,extra_keys=accent_grave:à:è:ù@f|accent_aigu:é@d|accent_circonflexe:â:ê:ô@o|accent_cedille:ç@c|accent_trema:ë:ï:ü:ÿ@u|€"/> <subtype android:label="%s" android:languageTag="fr-CH" android:imeSubtypeLocale="fr_CH" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwertz_fr_ch,extra_keys=accent_grave:à:è:ù@f|accent_aigu:é@d|accent_circonflexe:â:ê:ô@o|accent_cedille:ç@c|accent_trema:ë:ï:ü:ÿ@u|€"/>
<subtype android:label="%s" android:languageTag="fr-FR" android:imeSubtypeLocale="fr_FR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_azerty_fr,extra_keys=accent_grave:à:è@d|accent_aigu:é@d|accent_circonflexe:â:ê:ô@o|accent_cedille:ç@c|accent_trema:ë:ï:ü@l|€"/> <subtype android:label="%s" android:languageTag="fr-FR" android:imeSubtypeLocale="fr_FR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_azerty_fr,extra_keys=accent_grave:à:è@d|accent_aigu:é@d|accent_circonflexe:â:ê:ô@o|accent_cedille:ç@c|accent_trema:ë:ï:ü@l|€"/>
<subtype android:label="%s" android:languageTag="ga" android:imeSubtypeLocale="ga_IE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_ga,extra_keys=accent_aigu:á:é:í:ó:ú@k|accent_dot_above@l"/>
<subtype android:label="%s" android:languageTag="haw" android:imeSubtypeLocale="haw_US" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_haw,extra_keys=ʻ@l|accent_macron:ā:ē:ī:ō:ū@m"/>
<subtype android:label="%s" android:languageTag="he" android:imeSubtypeLocale="he_IL" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=hebrew,default_layout=hebr_1_il,extra_keys=₪@r|€"/> <subtype android:label="%s" android:languageTag="he" android:imeSubtypeLocale="he_IL" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=hebrew,default_layout=hebr_1_il,extra_keys=₪@r|€"/>
<subtype android:label="%s" android:languageTag="hi" android:imeSubtypeLocale="hi_IN" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=devanagari,default_layout=deva_inscript,extra_keys=₹"/> <subtype android:label="%s" android:languageTag="hi" android:imeSubtypeLocale="hi_IN" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=devanagari,default_layout=deva_inscript,extra_keys=₹"/>
<subtype android:label="%s" android:languageTag="hu" android:imeSubtypeLocale="hu_HU" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwertz_hu,extra_keys=accent_aigu:á:é:í:ó:ú@d|accent_trema:ö:ü@u|accent_ogonek@s|accent_double_aigu:ő:ű@k|€"/> <subtype android:label="%s" android:languageTag="hu" android:imeSubtypeLocale="hu_HU" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwertz_hu,extra_keys=accent_aigu:á:é:í:ó:ú@d|accent_trema:ö:ü@u|accent_ogonek@s|accent_double_aigu:ő:ű@k|€"/>
<subtype android:label="%s" android:languageTag="is" android:imeSubtypeLocale="is_IS" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us,extra_keys=ð|þ|æ|accent_trema:ö@o|accent_aigu:á:é:í:ó:ú:ý@d"/> <subtype android:label="%s" android:languageTag="is" android:imeSubtypeLocale="is_IS" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us,extra_keys=ð|þ|æ|accent_trema:ö@o|accent_aigu:á:é:í:ó:ú:ý@d"/>
<subtype android:label="%s" android:languageTag="it" android:imeSubtypeLocale="it_IT" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us,extra_keys=accent_grave:à:è:ì:ò:ù@f|accent_aigu:é:ó@d|accent_circonflexe:î@f|€|ə"/> <subtype android:label="%s" android:languageTag="it" android:imeSubtypeLocale="it_IT" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us,extra_keys=accent_grave:à:è:ì:ò:ù@f|accent_aigu:é:ó@d|accent_circonflexe:î@f|€|ə"/>
<subtype android:label="%s" android:languageTag="ka-GE" android:imeSubtypeLocale="ka_GE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=georgian_mes"/> <subtype android:label="%s" android:languageTag="ja" android:imeSubtypeLocale="ja_JP" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_jp"/>
<subtype android:label="%s" android:languageTag="kk" android:imeSubtypeLocale="kk_KZ" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=cyrl_jcuken_kk"/>
<subtype android:label="%s" android:languageTag="kn" android:imeSubtypeLocale="kn_IN" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=kannada,default_layout=kann_kannada"/>
<subtype android:label="%s" android:languageTag="ko" android:imeSubtypeLocale="ko_KR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=hangul,default_layout=latn_qwerty_us"/> <subtype android:label="%s" android:languageTag="ko" android:imeSubtypeLocale="ko_KR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=hangul,default_layout=latn_qwerty_us"/>
<subtype android:label="%s" android:languageTag="lt" android:imeSubtypeLocale="lt_LT" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_lt,extra_keys=accent_ogonek:ą:ę:į:ų@s|accent_caron:č:š:ž@f|accent_dot_above:ė@s|accent_macron:ū@o|€"/> <subtype android:label="%s" android:languageTag="lt" android:imeSubtypeLocale="lt_LT" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us,extra_keys=accent_ogonek:ą:ę:į:ų@s|accent_caron:č:š:ž@f|accent_dot_above:ė@s|accent_macron:ū@o|€"/>
<subtype android:label="%s" android:languageTag="lv" android:imeSubtypeLocale="lv_LV" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_lv,extra_keys=accent_macron:ā:ē:ī:ū@o|accent_caron:č:š:ž@f|accent_ogonek:ķ:ļ:ņ@s|accent_cedille:ģ@c|€"/> <subtype android:label="%s" android:languageTag="lv" android:imeSubtypeLocale="lv_LV" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_lv,extra_keys=accent_macron:ā:ē:ī:ū@o|accent_caron:č:š:ž@f|accent_ogonek:ķ:ļ:ņ@s|accent_cedille:ģ@c|€"/>
<subtype android:label="%s" android:languageTag="mn" android:imeSubtypeLocale="mn_MN" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=cyrillic,default_layout=cyrl_fcuzhen_mn,extra_keys=ү|ө"/>
<subtype android:label="%s" android:languageTag="mr" android:imeSubtypeLocale="mr_IN" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=devanagari,default_layout=deva_inscript,extra_keys=₹"/> <subtype android:label="%s" android:languageTag="mr" android:imeSubtypeLocale="mr_IN" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=devanagari,default_layout=deva_inscript,extra_keys=₹"/>
<subtype android:label="%s" android:languageTag="mt" android:imeSubtypeLocale="mt_MT" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_mt,extra_keys=accent_grave:à:è:ì:ò:ù|accent_dot_above:ċ:ż:ġ|ħ"/>
<subtype android:label="%s" android:languageTag="ne" android:imeSubtypeLocale="ne_NE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=devanagari,default_layout=deva_inscript,extra_keys=₹"/> <subtype android:label="%s" android:languageTag="ne" android:imeSubtypeLocale="ne_NE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=devanagari,default_layout=deva_inscript,extra_keys=₹"/>
<subtype android:label="%s" android:languageTag="nl-BE" android:imeSubtypeLocale="nl_BE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_azerty_be,extra_keys=accent_grave:è@f|accent_aigu:á:é:í:ó:ú:ý:j́@d|accent_circonflexe:ê@f|accent_cedille:ç@c|accent_trema@u|€"/> <subtype android:label="%s" android:languageTag="nl-BE" android:imeSubtypeLocale="nl_BE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_azerty_fr,extra_keys=accent_grave:è@f|accent_aigu:á:é:í:ó:ú:ý:j́@d|accent_circonflexe:ê@f|accent_cedille:ç@c|accent_trema@u|€"/>
<subtype android:label="%s" android:languageTag="no" android:imeSubtypeLocale="no_NO" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us,extra_keys=€|æ@a|å@a|ø@o|accent_aigu:é:ó@d|accent_grave:è:ò:ù@f|accent_circonflexe:ê:ô@f"/> <subtype android:label="%s" android:languageTag="no" android:imeSubtypeLocale="no_NO" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us,extra_keys=€|æ@a|å@a|ø@o|accent_aigu:é:ó@d|accent_grave:è:ò:ù@f|accent_circonflexe:ê:ô@f"/>
<subtype android:label="%s" android:languageTag="pl" android:imeSubtypeLocale="pl_PL" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_pl"/> <subtype android:label="%s" android:languageTag="pl" android:imeSubtypeLocale="pl_PL" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_pl"/>
<subtype android:label="%s" android:languageTag="pt" android:imeSubtypeLocale="pt_BR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_pt,extra_keys=accent_aigu:á:é:í:ó:ú@d|accent_cedille:ç@c|accent_circonflexe:â:ê:ô@f|accent_grave:à:ò@f|accent_tilde:ã:õ@n|€|ª|º"/> <subtype android:label="%s" android:languageTag="pt" android:imeSubtypeLocale="pt_BR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_pt,extra_keys=accent_aigu:á:é:í:ó:ú@d|accent_cedille:ç@c|accent_circonflexe:â:ê:ô@f|accent_grave:à:ò@f|accent_tilde:ã:õ@n|€|ª|º"/>
<subtype android:label="%s" android:languageTag="ro" android:imeSubtypeLocale="ro_RO" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_ro,extra_keys=ă|â|î|ș|ț|€|$"/> <subtype android:label="%s" android:languageTag="ro" android:imeSubtypeLocale="ro_RO" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_ro,extra_keys=ă|â|î|ș|ț|€|$"/>
<subtype android:label="%s" android:languageTag="ru" android:imeSubtypeLocale="ru_RU" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=cyrl_jcuken_ru"/> <subtype android:label="%s" android:languageTag="ru" android:imeSubtypeLocale="ru_RU" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=cyrl_jcuken_ru"/>
<subtype android:label="%s" android:languageTag="sk" android:imeSubtypeLocale="sk_SK" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwertz_sk,extra_keys=accent_caron:ě:ř:ž:š:č:ň:ď:ľ:ť@f|accent_ring:ů@s|accent_circonflexe:ô@f|accent_trema:ä:ü:ö@u|accent_aigu:á:é:í:ó:ú:ŕ:ś:ĺ:ý@d"/> <subtype android:label="%s" android:languageTag="sk" android:imeSubtypeLocale="sk_SK" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwertz_sk,extra_keys=accent_caron:ě:ř:ž:š:č:ň:ď:ľ:ť@f|accent_ring:ů@s|accent_circonflexe:ô@f|accent_trema:ä:ü:ö@u|accent_aigu:á:é:í:ó:ú:ŕ:ś:ĺ:ý@d"/>
<subtype android:label="%s" android:languageTag="sq" android:imeSubtypeLocale="sq_AL" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwertz_sq"/>
<subtype android:label="%s" android:languageTag="sr" android:imeSubtypeLocale="sr_" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=cyrl_lynyertz_sr"/> <subtype android:label="%s" android:languageTag="sr" android:imeSubtypeLocale="sr_" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=cyrl_lynyertz_sr"/>
<subtype android:label="%s" android:languageTag="sv" android:imeSubtypeLocale="sv_SE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_se,extra_keys=accent_aigu:á@d|accent_trema:ä:ö@o|accent_ring:å@s|€"/> <subtype android:label="%s" android:languageTag="sv" android:imeSubtypeLocale="sv_SE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_se,extra_keys=accent_aigu:á@d|accent_trema:ä:ö@o|accent_ring:å@s|€"/>
<subtype android:label="%s" android:languageTag="ta" android:imeSubtypeLocale="ta_IN" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=tamil,default_layout=tamil_default"/>
<subtype android:label="%s" android:languageTag="tly" android:imeSubtypeLocale="tly_AZ" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_tly,extra_keys=á|ú|â|ê|ı|š|ž"/> <subtype android:label="%s" android:languageTag="tly" android:imeSubtypeLocale="tly_AZ" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_tly,extra_keys=á|ú|â|ê|ı|š|ž"/>
<subtype android:label="%s" android:languageTag="tly" android:imeSubtypeLocale="tly_IR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=arab_hamvaj_tly"/> <subtype android:label="%s" android:languageTag="tly" android:imeSubtypeLocale="tly_IR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=arab_hamvaj_tly"/>
<subtype android:label="%s" android:languageTag="tr" android:imeSubtypeLocale="tr_TR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_tr,extra_keys=accent_cedille:ç:ş@c|accent_trema:ö:ü@u|accent_circonflexe:â:î:û@f|₺|ı|ğ"/> <subtype android:label="%s" android:languageTag="tr" android:imeSubtypeLocale="tr_TR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_tr,extra_keys=accent_cedille:ç:ş@c|accent_trema:ö:ü@u|accent_circonflexe:â:î:û@f|₺|ı|ğ"/>
<subtype android:label="%s" android:languageTag="uk" android:imeSubtypeLocale="uk_UA" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=cyrillic,default_layout=cyrl_jcuken_uk,extra_keys=ґ|є|і|ї|₴"/> <subtype android:label="%s" android:languageTag="uk" android:imeSubtypeLocale="uk_UA" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=cyrillic,default_layout=cyrl_jcuken_uk,extra_keys=ґ|є|і|ї|₴"/>
<subtype android:label="%s" android:languageTag="uz" android:imeSubtypeLocale="uz_UZ" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_uz,extra_keys=ʻ|ʼ"/>
<subtype android:label="%s" android:languageTag="vi" android:imeSubtypeLocale="vi_VN" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_vi"/> <subtype android:label="%s" android:languageTag="vi" android:imeSubtypeLocale="vi_VN" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_vi"/>
</input-method> </input-method>

View File

@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<row height="0.75"> <row height="0.75">
<key key0="1" se="!"/> <key key0="1"/>
<key key0="2" se="@"/> <key key0="2"/>
<key key0="3" se="#"/> <key key0="3"/>
<key key0="4" se="$"/> <key key0="4"/>
<key key0="5" se="%"/> <key key0="5"/>
<key key0="6" sw="^"/> <key key0="6"/>
<key key0="7" sw="&amp;"/> <key key0="7"/>
<key key0="8" sw="*"/> <key key0="8"/>
<key key0="9" sw="("/> <key key0="9"/>
<key key0="0" sw=")"/> <key key0="0"/>
</row> </row>

View File

@@ -10,7 +10,7 @@
<key shift="1.0" key0="4" indication="GHI"/> <key shift="1.0" key0="4" indication="GHI"/>
<key key0="5" indication="JKL"/> <key key0="5" indication="JKL"/>
<key key0="6" indication="MNO"/> <key key0="6" indication="MNO"/>
<key key0="(" key1="paste" key2="=" key3=":" key4="-"/> <key key0="(" key2="=" key3=":" key4="-"/>
</row> </row>
<row> <row>
<key shift="1.0" key0="7" indication="PQRS"/> <key shift="1.0" key0="7" indication="PQRS"/>

View File

@@ -45,7 +45,7 @@
<juloo.keyboard2.prefs.IntSlideBarPreference android:key="horizontal_margin_portrait" android:title="@string/pref_portrait" android:summary="%sdp" android:defaultValue="3" min="0" max="30"/> <juloo.keyboard2.prefs.IntSlideBarPreference android:key="horizontal_margin_portrait" android:title="@string/pref_portrait" android:summary="%sdp" android:defaultValue="3" min="0" max="30"/>
<juloo.keyboard2.prefs.IntSlideBarPreference android:key="horizontal_margin_landscape" android:title="@string/pref_landscape" android:summary="%sdp" android:defaultValue="28" min="0" max="200"/> <juloo.keyboard2.prefs.IntSlideBarPreference android:key="horizontal_margin_landscape" android:title="@string/pref_landscape" android:summary="%sdp" android:defaultValue="28" min="0" max="200"/>
</PreferenceScreen> </PreferenceScreen>
<juloo.keyboard2.prefs.SlideBarPreference android:key="character_size" android:title="@string/pref_character_size_title" android:summary="@string/pref_character_size_summary" android:defaultValue="1.15" min="0.75" max="1.5"/> <juloo.keyboard2.prefs.SlideBarPreference android:key="character_size" android:title="@string/pref_character_size_title" android:summary="@string/pref_character_size_summary" android:defaultValue="1.0" min="0.75" max="1.5"/>
<juloo.keyboard2.prefs.SlideBarPreference android:key="key_vertical_margin" android:title="@string/pref_key_vertical_space" android:summary="%s%%" android:defaultValue="1.5" min="0" max="5"/> <juloo.keyboard2.prefs.SlideBarPreference android:key="key_vertical_margin" android:title="@string/pref_key_vertical_space" android:summary="%s%%" android:defaultValue="1.5" min="0" max="5"/>
<juloo.keyboard2.prefs.SlideBarPreference android:key="key_horizontal_margin" android:title="@string/pref_key_horizontal_space" android:summary="%s%%" android:defaultValue="2" min="0" max="5"/> <juloo.keyboard2.prefs.SlideBarPreference android:key="key_horizontal_margin" android:title="@string/pref_key_horizontal_space" android:summary="%s%%" android:defaultValue="2" min="0" max="5"/>
<CheckBoxPreference android:key="border_config" android:title="@string/pref_border_config_title" android:defaultValue="false"/> <CheckBoxPreference android:key="border_config" android:title="@string/pref_border_config_title" android:defaultValue="false"/>

View File

@@ -11,36 +11,8 @@ let
buildToolsVersions = [ build_tools_version ]; buildToolsVersions = [ build_tools_version ];
platformVersions = [ "34" ]; platformVersions = [ "34" ];
abiVersions = [ "armeabi-v7a" ]; abiVersions = [ "armeabi-v7a" ];
inherit repoJson;
}; };
# Ensure we have the needed system images
repoJson = pkgs.fetchurl {
url =
"https://raw.githubusercontent.com/NixOS/nixpkgs/ebc7402410a3ce2d25622137c190d4ab83945c10/pkgs/development/mobile/androidenv/repo.json";
hash = "sha256-4/0FMyxM+7d66qfhlY3A10RIe6j6VrW8DIilH2eQyzc=";
};
emulators = let
mk_emulator = { platformVersion, device ? "pixel_6", abiVersion ? "x86_64", systemImageType ? "default" }:
pkgs.androidenv.emulateApp rec {
name = "emulator_api${platformVersion}";
inherit platformVersion abiVersion systemImageType;
androidAvdFlags = "--device ${device}";
sdkExtraArgs = { inherit repoJson; };
};
# Allow to install several emulators in the same environment
link_emulator = version_name: args: {
name = "bin/emulate_android_${version_name}";
path = "${mk_emulator args}/bin/run-test-emulator";
};
in pkgs.linkFarm "emulator" [
(link_emulator "5" { platformVersion = "21"; })
# (link_emulator "14" { platformVersion = "34"; })
# There's no 'default' image for Android 15
(link_emulator "15" { platformVersion = "35"; systemImageType = "google_apis"; })
];
ANDROID_SDK_ROOT = "${android.androidsdk}/libexec/android-sdk"; ANDROID_SDK_ROOT = "${android.androidsdk}/libexec/android-sdk";
gradle = pkgs.gradle.override { java = jdk; }; gradle = pkgs.gradle.override { java = jdk; };
@@ -55,14 +27,8 @@ let
''; '';
in pkgs.mkShell { in pkgs.mkShell {
buildInputs = [ buildInputs =
pkgs.findutils [ pkgs.findutils pkgs.fontforge jdk android.androidsdk gradle_wrapped ];
pkgs.fontforge
jdk
android.androidsdk
gradle_wrapped
emulators
];
JAVA_HOME = jdk.home; JAVA_HOME = jdk.home;
inherit ANDROID_SDK_ROOT; inherit ANDROID_SDK_ROOT;
} }

View File

@@ -1,52 +1,17 @@
{ {
// latin
"a": "á", "a": "á",
"c": "ć", "c": "ć",
"e": "é", "e": "é",
"g": "ǵ",
"i": "í", "i": "í",
"k": "ḱ",
"l": "ĺ", "l": "ĺ",
"m": "ḿ", "ń": "ń",
"n": "ń",
"o": "ó", "o": "ó",
"p": "ṕ",
"r": "ŕ", "r": "ŕ",
"s": "ś", "s": "ś",
"u": "ú", "u": "ú",
"w": "ẃ",
"y": "ý", "y": "ý",
"z": "ź", "z": "ź",
// extended latin (multiple diacritics)
"â": "ấ",
"ă": "ắ",
"å": "ǻ",
"æ": "ǽ",
"ç": "ḉ",
"ê": "ế",
"ē": "ḗ",
"ï": "ḯ",
"ô": "ố",
"ơ": "ớ",
"õ": "ṍ",
"ō": "ṓ",
"ø": "ǿ",
"ṡ": "ṥ",
"ü": "ǘ", "ü": "ǘ",
"ư": "ứ",
"ũ": "ṹ",
// greek
"α": "ά",
"ε": "έ",
"η": "ή",
"ι": "ί",
"ο": "ό",
"υ": "ύ",
// cyrillic
"к": "ќ",
"г": "ѓ",
// combining character
"ą": "ą\u0301",
"j": "j\u0301", "j": "j\u0301",
"у": "у\u0301", "у": "у\u0301",
"е": "е\u0301", "е": "е\u0301",

View File

@@ -1,12 +1,8 @@
{ {
// latin
"2": "ƻ",
"b": "ƀ", "b": "ƀ",
"c": "ꞓ", "c": "ꞓ",
"d": "đ", "d": "đ",
"f": "",
"g": "ǥ", "g": "ǥ",
"h": "ħ",
"i": "ɨ", "i": "ɨ",
"j": "ɉ", "j": "ɉ",
"k": "ꝁ", "k": "ꝁ",
@@ -18,13 +14,5 @@
"t": "ŧ", "t": "ŧ",
"u": "ʉ", "u": "ʉ",
"y": "ɏ", "y": "ɏ",
"z": "ƶ", "z": "ƶ"
// extended latin
"ȷ": "ɟ",
// cyrillic
"о": "ө",
"ӧ": "ӫ",
"ү": "ұ",
"ь": "ҍ",
"х": "ӿ"
} }

View File

@@ -1,14 +1,9 @@
{ {
// latin
"a": "ǎ", "a": "ǎ",
"c": "č", "c": "č",
"d": "ď", "d": "ď",
"e": "ě", "e": "ě",
"g": "ǧ",
"h": "ȟ",
"i": "ǐ", "i": "ǐ",
"j": "ǰ", // no uppercase
"k": "ǩ",
"l": "ľ", "l": "ľ",
"n": "ň", "n": "ň",
"o": "ǒ", "o": "ǒ",
@@ -17,17 +12,5 @@
"t": "ť", "t": "ť",
"u": "ǔ", "u": "ǔ",
"z": "ž", "z": "ž",
// extended latin "ü": "ǚ"
"ṡ": "ṧ",
"ü": "ǚ",
"ʒ": "ǯ",
// combining character
"в": "в\u030C",
"г": "г\u030C",
"ғ": "ғ\u030C",
"д": "д\u030C",
"з": "з\u030C",
"р": "р\u030C",
"т": "т\u030C",
"х": "х\u030C"
} }

View File

@@ -1,5 +1,4 @@
{ {
// latin
"c": "ç", "c": "ç",
"d": "ḑ", "d": "ḑ",
"e": "ȩ", "e": "ȩ",
@@ -10,8 +9,5 @@
"n": "ņ", "n": "ņ",
"r": "ŗ", "r": "ŗ",
"s": "ş", "s": "ş",
"t": "ţ", "t": "ţ"
// extended latin
"ć": "ḉ",
"ĕ": "ḝ"
} }

View File

@@ -1,7 +1,4 @@
{ {
"+": "⨣",
"≈": "⩯",
// latin
"a": "â", "a": "â",
"c": "ĉ", "c": "ĉ",
"e": "ê", "e": "ê",
@@ -12,27 +9,7 @@
"o": "ô", "o": "ô",
"ŝ": "ŝ", "ŝ": "ŝ",
"u": "û", "u": "û",
"w": "ŵ",
"x": "x̂",
"y": "ŷ",
"z": "ẑ", "z": "ẑ",
// extended latin
"á": "ấ",
"à": "ầ",
"ã": "ẫ",
"ạ": "ậ",
"ả": "ẩ",
"é": "ế",
"è": "ề",
"ẽ": "ễ",
"ẹ": "ệ",
"ẻ": "ể",
"ó": "ố",
"ò": "ồ",
"ơ": "ổ",
"õ": "ỗ",
"ọ": "ộ",
// combining characters
"а": "а\u0302", "а": "а\u0302",
"е": "е\u0302", "е": "е\u0302",
"и": "и\u0302", "и": "и\u0302",

View File

@@ -17,40 +17,5 @@
"w": "ẇ", "w": "ẇ",
"x": "ẋ", "x": "ẋ",
"y": "ẏ", "y": "ẏ",
"z": "ż", "z": "ż"
// remove dot since i and j already have one
"i": "ı",
"j": "ȷ",
// extended latin
"ā": "ǡ",
"ō": "ȱ",
"ś": "ṥ",
"ṣ": "ṩ",
"š": "ṧ",
"ſ": "ẛ",
// combining character
"k": "k\u0307",
"l": "l\u0307",
"q": "q\u0307",
"u": "u\u0307",
"v": "v\u0307",
"0": "0\u0307",
"1": "1\u0307",
"2": "2\u0307",
"3": "3\u0307",
"4": "4\u0307",
"5": "5\u0307",
"6": "6\u0307",
"7": "7\u0307",
"8": "8\u0307",
"9": "9\u0307",
// math
"∈": "⋵",
"": "⨰",
"∧": "⩑",
"": "⩒",
"≡": "⩧",
"~": "⩪",
"⊆": "⫃",
"⊇": "⫄"
} }

View File

@@ -1,34 +1,14 @@
{ {
// latin
"a": "ạ", "a": "ạ",
"b": "ḅ",
"d": "ḍ",
"e": "ẹ",
"h": "ḥ",
"i": "ị",
"k": "ḳ",
"l": "ḷ",
"m": "ṃ",
"n": "ṇ",
"o": "ọ",
"r": "ṛ",
"s": "ṣ",
"t": "ṭ",
"u": "ụ",
"v": "ṿ",
"w": "ẉ",
"y": "ỵ",
"z": "ẓ",
// extended latin
"ă": "ặ", "ă": "ặ",
"â": "ậ", "â": "ậ",
"e": "ẹ",
"ê": "ệ", "ê": "ệ",
"i": "ị",
"o": "ọ",
"ô": "ộ", "ô": "ộ",
"ơ": "ợ", "ơ": "ợ",
"": "", "u": "",
"ư": "ự", "ư": "ự",
// math "y": "ỵ"
"-": "⨪",
"+": "⨥",
"=": "⩦"
} }

View File

@@ -1,11 +1,7 @@
{ {
" ": "˝",
// latin
"o": "ő", "o": "ő",
"u": "ű", "u": "ű",
// cyrillic " ": "˝",
"у": "ӳ",
// combining character
"a": "a\u030b", "a": "a\u030b",
"e": "e\u030b", "e": "e\u030b",
"i": "i\u030b", "i": "i\u030b",

View File

@@ -1,17 +0,0 @@
{
// latin
"a": "ȁ",
"e": "ȅ",
"i": "ȉ",
"o": "ȍ",
"r": "ȑ",
"u": "ȕ",
//cyrillic
"ѵ": "ѷ",
"а": "а\u030f",
"е": "е\u030f",
"и": "и\u030f",
"о": "о\u030f",
"р": "р\u030f",
"у": "у\u030f"
}

View File

@@ -1,38 +1,8 @@
{ {
// latin
"a": "à", "a": "à",
"e": "è", "e": "è",
"i": "ì", "i": "ì",
"n": "ǹ",
"o": "ò", "o": "ò",
"u": "ù", "u": "ù",
"w": "", "ü": "ǜ"
"y": "ỳ",
// extended latin
"â": "ầ",
"ă": "ằ",
"ê": "ề",
"ē": "ḕ",
"ơ": "ờ",
"ô": "ồ",
"ō": "ṑ",
"ü": "ǜ",
"ư": "ừ",
// greek (technically not a grave, but a varia)
"α": "ὰ",
"ε": "ὲ",
"η": "ὴ",
"ι": "ὶ",
"ο": "ὸ",
"υ": "ὺ",
"ω": "ὼ",
// there is more like ἒ, ᾣ, etc
// cyrillic
"е": "ѐ",
"и": "ѝ",
// combining character
"ɔ": "ɔ\u0300",
"s": "s\u0300",
"ʌ": "ʌ\u0300",
"z": "z\u0300"
} }

View File

@@ -1,35 +1,8 @@
{ {
// latin
"a": "ā", "a": "ā",
"e": "ē", "e": "ē",
"g": "ḡ",
"i": "ī", "i": "ī",
"o": "ō", "o": "ō",
"u": "ū", "u": "ū",
"y": "ȳ", "ü": "ǖ"
// extended latin
"æ": "ǣ",
"ä": "ǟ",
"ȧ": "ǡ",
"è": "ḕ",
"é": "ḗ",
"ḷ": "ḹ",
"ṛ": "ṝ",
"ö": "ȫ",
"ȯ": "ȱ",
"ǫ": "ǭ",
"õ": "ȭ",
"ò": "ṑ",
"ó": "ṓ",
"ü": "ǖ", // there is also ṻ
// cyrillic
"и": "ӣ",
"у": "ӯ",
// greek
"α": "ᾱ",
"ι": "ῑ",
"υ": "ῡ",
// combining characters
"l": "l\u0304",
"r": "r\u0304"
} }

View File

@@ -1,10 +1,10 @@
{ {
// latin
"a": "ą", "a": "ą",
"e": "ę", "e": "ę",
"i": "į", "i": "į",
"k": "ķ",
"l": "ļ",
"n": "ņ",
"o": "ǫ", "o": "ǫ",
"u": "ų", "u": "ų"
// extended latin
"ō": "ǭ"
} }

View File

@@ -1,11 +1,4 @@
{ {
// latin
"a": "å", "a": "å",
"u": "ů", "u": "ů"
"w": "ẘ", // no uppercase
"y": "ẙ", // no uppercase
// extended latin
"á": "ǻ",
// extra
"~": "⸛"
} }

View File

@@ -8,11 +8,7 @@
"l": "ł", "l": "ł",
"n": "ꞥ", "n": "ꞥ",
"o": "ø", "o": "ø",
"ó": "ǿ",
"ɔ": "ꬿ",
"r": "ꞧ", "r": "ꞧ",
"s": "ꞩ", "s": "ꞩ",
"t": "ⱦ", "t": "ⱦ"
"u": "ꞹ",
"v": "ꝟ"
} }

View File

@@ -1,6 +1,4 @@
{ {
// arabic numbers
"0": "₀",
"1": "₁", "1": "₁",
"2": "₂", "2": "₂",
"3": "₃", "3": "₃",
@@ -10,13 +8,12 @@
"7": "₇", "7": "₇",
"8": "₈", "8": "₈",
"9": "₉", "9": "₉",
// math operators "0": "₀",
"+": "₊", "+": "₊",
"-": "₋", "-": "₋",
"=": "₌", "=": "₌",
"(": "₍", "(": "₍",
")": "₎", ")": "₎",
// latin
"a": "ₐ", "a": "ₐ",
"e": "ₑ", "e": "ₑ",
"h": "ₕ", "h": "ₕ",
@@ -33,13 +30,5 @@
"t": "ₜ", "t": "ₜ",
"u": "ᵤ", "u": "ᵤ",
"v": "ᵥ", "v": "ᵥ",
"x": "ₓ", "x": "ₓ"
// extended latin
"ə": "ₔ",
// greek
"β": "ᵦ",
"γ": "ᵧ",
"ρ": "ᵨ",
"φ": "ᵩ",
"χ": "ᵪ"
} }

View File

@@ -1,6 +1,4 @@
{ {
// numbers
"0": "⁰",
"1": "¹", "1": "¹",
"2": "²", "2": "²",
"3": "³", "3": "³",
@@ -10,18 +8,12 @@
"7": "⁷", "7": "⁷",
"8": "⁸", "8": "⁸",
"9": "⁹", "9": "⁹",
// math operators "0": "⁰",
"+": "⁺", "+": "⁺",
"-": "⁻", "-": "⁻",
"=": "⁼", "=": "⁼",
"(": "⁽", "(": "⁽",
")": "⁾", ")": "⁾",
// latin
"n": "ⁿ",
// since there are no more "superscript" characters,
// we substitute with "modifier letter small"s which looks the same
// latin
"a": "ᵃ", "a": "ᵃ",
"b": "ᵇ", "b": "ᵇ",
"c": "ᶜ", "c": "ᶜ",
@@ -34,11 +26,10 @@
"j": "ʲ", "j": "ʲ",
"k": "ᵏ", "k": "ᵏ",
"l": "ˡ", "l": "ˡ",
// see above for n
"m": "ᵐ", "m": "ᵐ",
"n": "ⁿ",
"o": "ᵒ", "o": "ᵒ",
"p": "ᵖ", "p": "ᵖ",
"q": "ꟴ", // there is no proper lowercase superscript q
"r": "ʳ", "r": "ʳ",
"s": "ˢ", "s": "ˢ",
"t": "ᵗ", "t": "ᵗ",
@@ -47,47 +38,5 @@
"w": "ʷ", "w": "ʷ",
"x": "ˣ", "x": "ˣ",
"y": "ʸ", "y": "ʸ",
"z": "ᶻ", "z": "ᶻ"
// extended latin
"ɐ": "ᵄ",
"ᴂ": "ᵆ",
"ɕ": "ᶝ",
"ə": "ᵊ",
"ɛ": "ᵋ",
"ɜ": "ᶟ", // turned open e, ↓ not the same
"ᴈ": "ᵌ", // reversed open e
"ɥ": "ᶣ",
"ɦ": "ʱ",
"ᴉ": "ᵎ",
"ɨ": "ᶤ",
"ɟ": "ᶡ",
"ɱ": "ᶬ",
"ɯ": "ᵚ",
"ɰ": "ᶭ",
"ŋ": "ᵑ",
"ᴝ": "ᵙ",
"ɵ": "ᶱ",
"œ": "ꟹ",
"ɔ": "ᵓ",
"ɹ": "ʴ",
"ɻ": "ʵ",
"ʁ": "ʶ",
"ʂ": "ᶳ",
"ʉ": "ᶶ",
"ʃ": "ᶴ",
"ʒ": "ᶾ",
"ʍ": "ꭩ",
// greek
"ɒ": "ᶛ",
"β": "ᵝ",
"ɣ": "ˠ",
"δ": "ᵟ",
"φ": "ᵠ",
"χ": "ᵡ",
"ι": "ᶥ",
"ʊ": "ᶷ",
"ʌ": "ᶺ",
"θ": "ᶿ",
// cyrillic
"ө": "ᶱ"
} }

View File

@@ -1,21 +1,13 @@
{ {
// latin
"a": "ã", "a": "ã",
"e": "ẽ", "e": "ẽ",
"i": "ĩ", "i": "ĩ",
"n": "ñ", "n": "ñ",
"o": "õ", "o": "õ",
"u": "ũ", "u": "ũ",
"v": "ṽ",
"y": "ỹ",
// extended latin
"ă": "ẵ", "ă": "ẵ",
"â": "ẫ", "â": "ẫ",
"ê": "ễ", "ê": "ễ",
"ơ": "ỡ", "ơ": "ỡ",
"ō": "ȭ", "ư": ""
"ó": "ṍ",
"ö": "ṏ",
"ư": "ữ",
"ú": "ṹ"
} }

View File

@@ -1,54 +1,8 @@
{ {
// fun
"~": "⍨",
"*": "⍣",
"∇": "⍢",
"°": "⍤",
// latin
"a": "ä", "a": "ä",
"e": "ë", "e": "ë",
"h": "ḧ",
"i": "ï", "i": "ï",
"o": "ö", "o": "ö",
"t": "ẗ",
"u": "ü", "u": "ü",
"w": "", "y": "ÿ"
"x": "ẍ",
"y": "ÿ",
// extended latin
"ā": "ǟ",
"ō": "ȫ",
"õ": "ṏ",
"í": "ḯ",
"ū": "ǖ", // there is also ṻ
"ú": "ǘ",
"ù": "ǜ",
"ǔ": "ǚ",
// greek
"ι": "ϊ",
"υ": "ϋ",
"ὺ": "ῢ",
"ύ": "ΰ",
"ῦ": "ῧ",
"ϒ": "ϔ",
// cyrillic
"а": "ӓ",
"ә": "ӛ",
"ж": "ӝ",
"з": "ӟ",
"и": "ӥ",
"о": "ӧ",
"ө": "ӫ",
"э": "ӭ",
"у": "ӱ",
"ч": "ӵ",
"ы": "ӹ",
// combining character
"c": "c\u0308",
"j": "j\u0308",
"k": "k\u0308",
"l": "l\u0308",
"m": "m\u0308",
"n": "n\u0308",
"s": "s\u0308"
} }

View File

@@ -99,18 +99,9 @@ def strip_cstyle_comments(inp):
# Parse from a json file containing a dictionary sequence → result string. # Parse from a json file containing a dictionary sequence → result string.
def parse_sequences_file_json(fname): def parse_sequences_file_json(fname):
def tree_to_seqs(tree, prefix):
for c, r in tree.items():
if isinstance(r, str):
yield prefix + [c], r
else:
yield from tree_to_seqs(r, prefix + [c])
try:
with open(fname, "r") as inp: with open(fname, "r") as inp:
tree = json.loads(strip_cstyle_comments(inp)) seqs = json.loads(strip_cstyle_comments(inp))
return list(tree_to_seqs(tree, [])) return list(seqs.items())
except Exception as e:
print("Failed parsing '%s': %s" % (fname, str(e)), file=sys.stderr)
# Format of the sequences file is determined by its extension # Format of the sequences file is determined by its extension
def parse_sequences_file(fname, xkb_char_extra_names={}): def parse_sequences_file(fname, xkb_char_extra_names={}):
@@ -139,33 +130,26 @@ def parse_sequences_dir(dname):
# Turn a list of sequences into a trie. # Turn a list of sequences into a trie.
def add_sequences_to_trie(seqs, trie): def add_sequences_to_trie(seqs, trie):
global dropped_sequences def add_seq_to_trie(t_, seq, result):
def add_seq_to_trie(seq, result):
t_ = trie t_ = trie
for c in seq[:-1]:
t_ = t_.setdefault(c, {})
if isinstance(t_, str):
return False
c = seq[-1]
if c in t_:
return False
t_[c] = result
return True
def existing_sequence_to_str(seq): # Used in error message
i = 0 i = 0
t_ = trie while i < len(seq) - 1:
while i < len(seq): c = seq[i]
if seq[i] not in t_: break # No collision ? if c not in t_:
t_ = t_[seq[i]] t_[c] = {}
i += 1 if isinstance(t_[c], str):
if isinstance(t_, str): break global dropped_sequences
return "".join(seq[:i]) + " = " + str(t_)
for seq, result in seqs:
if not add_seq_to_trie(seq, result):
dropped_sequences += 1 dropped_sequences += 1
print("Sequence collide: '%s' and '%s = %s'" % ( print("Sequence collide: '%s = %s' '%s = %s'" % (
existing_sequence_to_str(seq), seq[:i+1], t_[c], seq, result),
"".join(seq), result), file=sys.stderr) file=sys.stderr)
return
t_ = t_[c]
i += 1
c = seq[i]
t_[c] = result
for seq, result in seqs:
add_seq_to_trie(trie, seq, result)
# Compile the trie into a state machine. # Compile the trie into a state machine.
def make_automata(tries): def make_automata(tries):
@@ -195,9 +179,6 @@ def make_automata(tries):
# There are two encoding for leafs: character final state for 15-bit # There are two encoding for leafs: character final state for 15-bit
# characters and string final state for the rest. # characters and string final state for the rest.
if len(c) > 1 or ord(c[0]) > 32767: # String final state if len(c) > 1 or ord(c[0]) > 32767: # String final state
# A ':' can be added to the result of a sequence to force a string
# final state. For example, to go through KeyValue lookup.
if c.startswith(":"): c = c[1:]
javachars = array('H', c.encode("UTF-16-LE")) javachars = array('H', c.encode("UTF-16-LE"))
states.append((-1, len(javachars) + 1)) states.append((-1, len(javachars) + 1))
for c in javachars: for c in javachars:

View File

@@ -1,149 +0,0 @@
{
"ا": {
"ا": "combining_alef_above",
"ع": "أ",
"و": "ۉ",
"ي": "ؽ",
"ی": "ؽ",
"۷": "combining_alef_below",
"٧": "combining_alef_below"
},
"ت": {
"د": "ط",
"ر": "ڑ",
"ش": "ث",
"ن": "ٹ"
},
"ج": {
"ش": "چ"
},
"ح": {
"ح": "combining_sukun"
},
"د": {
"ت": "ڈ",
"ز": "ذ",
"ت": "ڑ",
"۷": "ڕ"
},
"س": {
"ش": "ص"
},
"ش": {
"ت": "ث"
},
"ع": {
"ا": "إ",
"ه": "ۀ",
"و": "ؤ",
"ي": "ئ",
"ی": "ئ",
"۷": "combining_hamza_below",
"۸": "combining_hamza_above",
"٧": "combining_hamza_below",
"٨": "combining_hamza_above"
},
"غ": {
"ك": "گ",
"ک": "گ"
},
"ف": {
"و": "ڡ"
},
"ق": {
"و": "ۊ"
},
"ل": {
"ل": "combining_shaddah",
"۷": "ڵ",
"٧": "ڵ"
},
"ن": {
"ت": "ٹ",
"ه": "combining_fathatan",
"و": "combining_dammatan",
"ی": "combining_kasratan",
"ي": "combining_kasratan"
},
"ه": {
" ": "ە",
"ت": "ة",
"ع": "ۀ",
"ن": "combining_fathatan",
"ه": "combining_fatha",
"و": "ۆ",
"ي": "ێ",
"ی": "ێ"
},
"و": {
"ث": "ۋ",
"ع": "ؤ",
"ف": "ڡ",
"ن": "combining_dammatan",
"و": "combining_dammah",
"۷": "ۆ",
"۸": "ۉ",
"۸": "ۉ",
"٧": "ۆ",
"٨": "ۉ",
"٨": "ۉ"
},
"ي": {
" ": "ے",
"ا": "ى",
"ع": "ئ",
"ي": "combining_kasra",
"۷": "ێ",
"۸": "ؽ",
"ن": "combining_kasratan",
"٧": "ێ",
"٨": "ؽ"
},
"ی": {
" ": "ے",
"ا": "ى",
"ع": "ئ",
"ن": "combining_kasratan",
"ی": "combining_kasra",
"۷": "ێ",
"۸": "ؽ",
"٧": "ێ",
"٨": "ؽ"
},
"۷": {
"ا": "combining_alef_below",
"ر": "ڕ",
"ع": "combining_hamza_below",
"ل": "ڵ",
"و": "ۆ",
"ي": "ێ",
"ی": "ێ",
"۷": "combining_arabic_v"
},
"۸": {
"ع": "combining_hamza_above",
"و": "ۉ",
"و": "ۉ",
"ي": "ؽ",
"ی": "ؽ",
"۸": "combining_arabic_inverted_v"
},
"٧": {
"ا": "combining_alef_below",
"ر": "ڕ",
"ع": "combining_hamza_below",
"ل": "ڵ",
"و": "ۆ",
"ي": "ێ",
"٧": "combining_arabic_v",
"ی": "ێ"
},
"٨": {
"ع": "combining_hamza_above",
"و": "ۉ",
"و": "ۉ",
"ي": "ؽ",
"٨": "combining_arabic_inverted_v",
"ی": "ؽ"
}
}

View File

@@ -1,165 +0,0 @@
{
",": {
"г": "ӻ",
"к": "ӄ",
"л": "ԓ",
"н": "ӈ",
"х": "ӽ",
"ѧ": "ӊ"
},
".": {
"г": "ӷ",
"ж": "җ",
"й": "ҋ",
"к": "қ",
"л": "ԯ",
"м": "ӎ",
"н": "ӊ",
"х": "ҳ",
"ч": "ҷ",
"і": "ї"
},
"а": {
"е": "ѣ",
"у": "ѡ",
"ч": "combining_aigu",
"ы": "ѣ",
"ь": "ꙙ",
"ꙋ": "ꙍ",
"ꙑ": "ѣ"
},
"б": {
"ч": "combining_slavonic_psili"
},
"г": {
",": "ӻ",
".": "ӷ",
"й": "ғ",
"к": "ґ",
"х": "ҁ",
"ј": "ғ"
},
"д": {
"е": "ꙉ",
"ж": "џ",
"з": "ꙃ",
"й": "ꙉ",
"ј": "ꙉ",
"ѥ": "ђ"
},
"е": {
"ч": "combining_trema"
},
"ж": {
".": "җ"
},
"з": {
"ф": "ҙ"
},
"и": {
"и": "ӣ",
"у": "ѵ"
},
"й": {
".": "ҋ",
"ч": "combining_breve"
},
"к": {
",": "ӄ",
".": "қ",
"г": "ґ",
"с": "ѯ",
"х": "ҁ",
"ш": "ѯ"
},
"л": {
",": "ԓ",
".": "ԯ",
"ь": "љ"
},
"м": {
".": "ӎ"
},
"н": {
",": "ӈ",
"·": "ԩ",
"ч": "combining_titlo",
"ь": "њ"
},
"о": {
"т": "ѿ",
"у": "ѹ",
"ч": "combining_inverted_breve"
},
"п": {
"с": "ѱ"
},
"т": {
"й": "ћ",
"ф": "ѳ",
"ј": "ћ"
},
"у": {
"и": "ѵ",
"й": "ў",
"у": "ӯ",
"ч": "combining_pokrytie",
"і": "ѵ",
"ј": "ў"
},
"х": {
",": "ӽ",
".": "ҳ",
"ч": "combining_slavonic_dasia"
},
"ч": {
".": "ҷ",
"а": "combining_aigu",
"б": "combining_slavonic_psili",
"е": "combining_trema",
"й": "combining_breve",
"н": "combining_titlo",
"о": "combining_inverted_breve",
"у": "combining_pokrytie",
"х": "combining_slavonic_dasia",
"ч": "combining_payerok",
"ч": "combining_payerok",
"ъ": "combining_vertical_tilde",
"ю": "combining_grave",
"ј": "combining_breve",
"ѧ": "combining_vzmet"
},
"ш": {
"т": "щ"
},
"ъ": {
"ч": "combining_vertical_tilde"
},
"ю": {
"а": "ꙓ",
"е": "ё",
"м": "ѭ",
"н": "ѩ",
"ч": "combining_grave"
},
"я": {
"ь": "ꙝ"
},
"і": {
"\"": "ї",
".": "ї",
"у": "ѵ",
"і": "ӣ"
},
"ј": {
"а": "ꙗ",
"ч": "combining_breve",
"ѣ": "ꙝ"
},
"ѡ": {
"т": "ѿ"
},
"ѧ": {
"ч": "combining_vzmet"
}
}

View File

@@ -4016,7 +4016,7 @@ XCOMM Mathematical Operators
<Multi_key> <U2225> <slash> : "∦" U2226 # NOT PARALLEL TO <Multi_key> <U2225> <slash> : "∦" U2226 # NOT PARALLEL TO
<Multi_key> <U223C> <slash> : "≁" U2241 # NOT TILDE <Multi_key> <U223C> <slash> : "≁" U2241 # NOT TILDE
<Multi_key> <U2243> <slash> : "≄" U2244 # NOT ASYMPTOTICALLY EQUAL TO <Multi_key> <U2243> <slash> : "≄" U2244 # NOT ASYMPTOTICALLY EQUAL TO
XCOMM <Multi_key> <approximate> <slash> : "≇" U2247 # NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO <Multi_key> <approximate> <slash> : "≇" U2247 # NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO
<Multi_key> <U2248> <slash> : "≉" U2249 # NOT ALMOST EQUAL TO <Multi_key> <U2248> <slash> : "≉" U2249 # NOT ALMOST EQUAL TO
<Multi_key> <slash> <equal> : "≠" U2260 # NOT EQUAL TO <Multi_key> <slash> <equal> : "≠" U2260 # NOT EQUAL TO
<Multi_key> <equal> <slash> : "≠" U2260 # NOT EQUAL TO <Multi_key> <equal> <slash> : "≠" U2260 # NOT EQUAL TO

View File

@@ -37,7 +37,6 @@
"†": "‡", "†": "‡",
"×": "∙", "×": "∙",
" ": "nbsp", " ": "nbsp",
// arrows // arrows
"↖": "⇖", "↖": "⇖",
"↑": "⇑", "↑": "⇑",
@@ -78,6 +77,7 @@
"": "", "": "",
"∩": "⋂", "∩": "⋂",
"∃": "∄", "∃": "∄",
"∈": "∉",
"∫": "∮", "∫": "∮",
"Π": "∏", "Π": "∏",
"Σ": "∑", "Σ": "∑",
@@ -87,17 +87,6 @@
"⊂": "⊆", "⊂": "⊆",
"⊃": "⊇", "⊃": "⊇",
"±": "∓", "±": "∓",
// APL
"": "⍶",
"⍵": "⍹",
"⋄": "⌺",
"⍝": "⍧",
"∆": "⍙",
"∇": "⍢",
"": "⍡",
"⎕": "⍞",
// hebrew niqqud // hebrew niqqud
"ק": "qamats", // kamatz "ק": "qamats", // kamatz
"ר": "hataf_qamats", // reduced kamatz "ר": "hataf_qamats", // reduced kamatz
@@ -112,7 +101,6 @@
"ס": "segol", "ס": "segol",
"ב": "hataf_segol", // reduced segol "ב": "hataf_segol", // reduced segol
"צ": "tsere", "צ": "tsere",
// Devanagari symbols // Devanagari symbols
"ए": "ऍ", "ए": "ऍ",
"े": "ॅ", "े": "ॅ",
@@ -169,7 +157,6 @@
"ं": "ॕ", "ं": "ॕ",
"़": "ॎ", "़": "ॎ",
"ऽ": "", "ऽ": "",
// Persian numbers // Persian numbers
"۱": "f1", "۱": "f1",
"۲": "f2", "۲": "f2",
@@ -191,78 +178,5 @@
"٧": "f7", "٧": "f7",
"٨": "f8", "٨": "f8",
"٩": "f9", "٩": "f9",
"٠": "f10", "٠": "f10"
// Cyrillic
"ꙑ": "ы",
"ы": "ꙑ",
"ш": "ѱ",
"з": "ꙁ",
"и": "і",
"і": "и",
"я": "ꙗ",
"е": "ѥ",
"ѡ": "ꙍ",
"о": "ѻ",
"а": "ѣ",
"э": "є",
"ъ": "ь",
"ь": "ъ",
"й": "ј",
"ꙉ": "ђ",
"ч": "ћ",
"ҁ": "қ",
"қ": "ҁ",
"џ": "ҷ",
"ҷ": "џ",
"ј": "й",
"у": "ꙋ",
"м": "ѫ",
"н": "ѧ",
"с": "ѕ",
"л": "ԯ",
"ԓ": "ԯ",
"\ua67d": "\u0483",
"\u0487": "\ua66f",
"ӈ": "ԩ",
// Arabic
":": "zwnj",
"ل": "ڵ",
"\u064F": "ۆ", // combining_dammah
"\u0650": "ێ", // combining_kasra
"ر": "ڕ",
"ب": "ٮ",
"ه": "ھ",
"ث": "پ",
"ز": "ژ",
"غ": "گ",
"ك": "ک",
"ا": "آ",
"ي": "ی",
"ک": "ك",
"ط": "ظ",
"ص": "ض",
"ی": "ي",
"ق": "غ",
"ع": "ء",
"ح": "ہ",
"ێ": "combining_kasra",
"ئ": "combining_hamza_above",
"ؽ": "combining_arabic_inverted_v",
"ۉ": "combining_arabic_inverted_v",
"ڡ": "combining_dammah",
"ة": "combining_fatha",
"إ": "combining_hamza_below",
"ۆ": "combining_arabic_v",
"س": "ـ",
"ف": "ڤ",
"ن": "ں",
// Tamil
"ய": ":௰",
"ஒ": ":ௐ",
"ள": ":௱",
"ச": ":௲",
"வ": ":௳"
} }

View File

@@ -1,12 +0,0 @@
{
"0": "",
"1": "১",
"2": "২",
"3": "৩",
"4": "",
"5": "৫",
"6": "৬",
"7": "",
"8": "৮",
"9": "৯"
}

View File

@@ -1,12 +0,0 @@
{
"0": "",
"1": "१",
"2": "२",
"3": "३",
"4": "४",
"5": "५",
"6": "६",
"7": "७",
"8": "८",
"9": "९"
}

View File

@@ -1,12 +0,0 @@
{
"0": "",
"1": "૧",
"2": "૨",
"3": "૩",
"4": "૪",
"5": "૫",
"6": "૬",
"7": "૭",
"8": "૮",
"9": "૯"
}

View File

@@ -1,14 +0,0 @@
// Used with Arabic despite the name; called "Hindi numerals" in Arabic
// numpad_devanagari is used in Hindi
{
"0": "٠",
"1": "١",
"2": "٢",
"3": "٣",
"4": "٤",
"5": "٥",
"6": "٦",
"7": "٧",
"8": "٨",
"9": "٩"
}

View File

@@ -1,12 +0,0 @@
{
"0": "",
"1": "೧",
"2": "೨",
"3": "೩",
"4": "೪",
"5": "೫",
"6": "೬",
"7": "೭",
"8": "೮",
"9": "೯"
}

View File

@@ -1,12 +0,0 @@
{
"0": "۰",
"1": "۱",
"2": "۲",
"3": "۳",
"4": "۴",
"5": "۵",
"6": "۶",
"7": "۷",
"8": "۸",
"9": "۹"
}

View File

@@ -1,12 +0,0 @@
{
"0": "",
"1": "௧",
"2": "௨",
"3": "௩",
"4": "௪",
"5": "௫",
"6": "௬",
"7": "௭",
"8": "௮",
"9": "௯"
}

View File

@@ -18,53 +18,11 @@
"┐": "╗", "┐": "╗",
"─": "═", "─": "═",
"│": "║", "│": "║",
"∈": "∉",
"∋": "∌",
"⊂": "⊄",
"⊃": "⊅",
"⊆": "⊈",
"⊇": "⊉",
// superscript
"ᵃ": "ᴬ",
"ᵇ": "ᴮ",
"ᶜ": "ꟲ",
"ᵈ": "ᴰ",
"ᵉ": "ᴱ",
"ᶠ": "ꟳ",
"ᵍ": "ᴳ",
"ʰ": "ᴴ",
"ⁱ": "ᴵ",
"ʲ": "ᴶ",
"ᵏ": "ᴷ",
"ˡ": "ᴸ",
"ᵐ": "ᴹ",
"ⁿ": "ᴺ",
"ᵒ": "ᴼ",
"ᵖ": "ᴾ",
"ʳ": "ᴿ",
"ᵗ": "ᵀ",
"ᵘ": "ᵁ",
"ᵛ": "ⱽ",
"ʷ": "ᵂ",
"ᶾ": "ᴣ",
"ᵠ": "ᶲ",
// german eszett has an uppercase, but because it is uncommon, java doesn't know about it
"ß": "ẞ", "ß": "ẞ",
// these characters don't have a preapplied uppercase version, so we use combining characters
"ẗ": "T\u0308",
"ẘ": "W\u030A",
"ẙ": "Y\u030A",
"ǰ": "J\u030C",
"ȷ": "J\u0307",
// In Turkish, upper case of 'iı' is 'İI' but Java's toUpperCase will // In Turkish, upper case of 'iı' is 'İI' but Java's toUpperCase will
// return 'II'. To make 'İ' accessible, make it the shift of 'ı'. This // return 'II'. To make 'İ' accessible, make it the shift of 'ı'. This
// has the inconvenient of swapping i and ı on the keyboard. // has the inconvenient of swapping i and ı on the keyboard.
"ı": "İ", "ı": "İ",
"₹": "₨", "₹": "₨",
// Gujarati alternate characters // Gujarati alternate characters
"અ": "આ", "અ": "આ",
@@ -90,49 +48,5 @@
"મ": "ં", "મ": "ં",
"લ": "ળ", "લ": "ળ",
"સ": "શ", "સ": "શ",
"હ": "", "હ": ""
// Tamil alternate characters
"௹": "₨",
// Modern Hindi and Sanskrit
"अ": "आ",
"इ": "ई",
"ि": "ी",
"उ": "ऊ",
"ु": "ू",
"ए": "ऐ",
"े": "ै",
"ओ": "औ",
"ो": "ौ",
"क": "ख",
"ग": "घ",
"च": "छ",
"ज": "झ",
"ट": "ठ",
"ड": "ढ",
"न": "ण",
"त": "थ",
"द": "ध",
"ब": "भ",
"म": "ं",
"ल": "ळ",
"स": "श",
"ह": "",
"ऋ": "ॠ",
"ृ": "ॄ",
"ऌ": "ॡ",
"ॢ": "ॣ",
"॒": "॑",
"ॅ": "ॲ",
"ॉ": "ऑ",
// Mathematical symbols
"\uD835": {
"\uDD68": "𝕎", // 𝕨𝕎
"\uDD69": "𝕏", // 𝕩𝕏
"\uDD57": "𝔽", // 𝕗𝔽
"\uDD58": "𝔾", // 𝕘𝔾
"\uDD64": "𝕊" // 𝕤𝕊
}
} }

View File

@@ -88,24 +88,6 @@ public final class Autocapitalisation
callback_now(true); callback_now(true);
} }
/** Pause auto capitalisation until [unpause()] is called. */
public boolean pause()
{
boolean was_enabled = _enabled;
stop();
_enabled = false;
return was_enabled;
}
/** Continue auto capitalisation after [pause()] was called. Argument is the
output of [pause()]. */
public void unpause(boolean was_enabled)
{
_enabled = was_enabled;
_should_update_caps_mode = true;
callback_now(true);
}
public static interface Callback public static interface Callback
{ {
public void update_shift_state(boolean should_enable, boolean should_disable); public void update_shift_state(boolean should_enable, boolean should_disable);

View File

@@ -11,7 +11,6 @@ final class ClipboardHistoryCheckBox extends CheckBox
public ClipboardHistoryCheckBox(Context ctx, AttributeSet attrs) public ClipboardHistoryCheckBox(Context ctx, AttributeSet attrs)
{ {
super(ctx, attrs); super(ctx, attrs);
setChecked(Config.globalConfig().clipboard_history_enabled);
setOnCheckedChangeListener(this); setOnCheckedChangeListener(this);
} }

View File

@@ -30,9 +30,11 @@ public final class ClipboardHistoryService
public static void set_history_enabled(boolean e) public static void set_history_enabled(boolean e)
{ {
Config.globalConfig().set_clipboard_history_enabled(e);
if (_service == null) if (_service == null)
return; return;
Config.globalPrefs().edit()
.putBoolean("clipboard_history_enabled", e)
.commit();
if (e) if (e)
_service.add_current_clip(); _service.add_current_clip();
else else

View File

@@ -4,23 +4,30 @@ import java.util.Arrays;
public final class ComposeKey public final class ComposeKey
{ {
/** Apply the pending compose sequence to [kv]. Returns [null] if no sequence /** Apply the pending compose sequence to [kv]. */
matched. */
public static KeyValue apply(int state, KeyValue kv) public static KeyValue apply(int state, KeyValue kv)
{ {
switch (kv.getKind()) switch (kv.getKind())
{ {
case Char: case Char:
return apply(state, kv.getChar()); KeyValue res = apply(state, kv.getChar());
case String: // Grey-out characters not part of any sequence.
return apply(state, kv.getString()); if (res == null)
return kv.withFlags(kv.getFlags() | KeyValue.FLAG_GREYED);
return res;
/* These keys are not greyed. */
case Event:
case Modifier:
case Compose_pending:
return kv;
/* Other keys cannot be part of sequences. */
default:
return kv.withFlags(kv.getFlags() | KeyValue.FLAG_GREYED);
} }
return null;
} }
/** Apply the pending compose sequence to char [c]. Returns [null] if no /** Apply the pending compose sequence to char [c]. */
sequence matched. */ static KeyValue apply(int prev, char c)
public static KeyValue apply(int prev, char c)
{ {
char[] states = ComposeKeyData.states; char[] states = ComposeKeyData.states;
char[] edges = ComposeKeyData.edges; char[] edges = ComposeKeyData.edges;
@@ -42,25 +49,6 @@ public final class ComposeKey
return KeyValue.makeCharKey((char)next_header); return KeyValue.makeCharKey((char)next_header);
} }
/** Apply each char of a string to a sequence. Returns [null] if no sequence
matched. */
public static KeyValue apply(int prev, String s)
{
final int len = s.length();
int i = 0;
if (len == 0) return null;
while (true)
{
KeyValue k = apply(prev, s.charAt(i));
i++;
if (k == null) return null;
if (i >= len) return k;
if (k.getKind() != KeyValue.Kind.Compose_pending)
return null; // Found a final state before the end of [s].
prev = k.getPendingCompose();
}
}
/** The state machine is comprised of two arrays. /** The state machine is comprised of two arrays.
The [states] array represents the different states and the associated The [states] array represents the different states and the associated

View File

@@ -5,272 +5,216 @@ package juloo.keyboard2;
public final class ComposeKeyData public final class ComposeKeyData
{ {
public static final char[] states = public static final char[] states =
("\u0001\u0000acegijklmnoprsuwyz\u00e2\u00e5\u00e6\u00e7\u00ea\u00ef\u00f4\u00f5\u00f8\u00fc\u0103\u0105\u0113\u014d\u0169\u01a1\u01b0\u03b1\u03b5\u03b7\u03b9\u03bf\u03c5\u0430\u0433\u0435\u0438\u043a\u043e\u0443\u044b\u044d\u044e\u044f\u1e61\u00e1\u0107\u00e9\u01f5\u00ed\uFFFF\u006a\u0301\u1e31\u013a\u1e3f\u0144\u00f3\u1e55\u0155\u015b\u00fa" + ("\u0001\u0000aceijlorsuyz\u00fc\u0144\u0430\u0435\u0438\u043e\u0443\u044b\u044d\u044e\u044f\u00e1\u0107\u00e9\u00ed\uFFFF\u006a\u0301\u013a\u00f3\u0155\u015b\u00fa\u00fd\u017a\u01d8\u0144\uFFFF\u0430\u0301\uFFFF\u0435\u0301\uFFFF\u0438\u0301\uFFFF\u043e\u0301\uFFFF\u0443\u0301\uFFFF\u044b\u0301\uFFFF\u044d\u0301\uFFFF\u044e\u0301\uFFFF\u044f\u0301\u0000.01" +
"\u1e83\u00fd\u017a\u1ea5\u01fb\u01fd\u1e09\u1ebf\u1e2f\u1ed1\u1e4d\u01ff\u01d8\u1eaf\uFFFF\u0105\u0301\u1e17\u1e53\u1e79\u1edb\u1ee9\u03ac\u03ad\u03ae\u03af\u03cc\u03cd\uFFFF\u0430\u0301\u0453\uFFFF\u0435\u0301\uFFFF\u0438\u0301\u045c\uFFFF\u043e\u0301\uFFFF\u0443\u0301\uFFFF\u044b\u0301\uFFFF\u044d\u0301\uFFFF\u044e\u0301\uFFFF\u044f\u0301\u1e65\u0000.0123456789\u21b5\u2194" + "23456789\u21b5\u2194\u2199\u2193\u2198\u2190\u2195\u2192\u2196\u2191\u2197\u0000bcdgijklopqrtuyz\u0180\uFFFF\ua793\u0111\u01e5\u0268\u0249\uFFFF\ua741\u019a\u0275\u1d7d\uFFFF\ua757\u024d\u0167\u0289\u024f\u01b6\u0000.0123456789\u2502\u2500\u2514\u2534\u2518" +
"\u2199\u2193\u2198\u2190\u2195\u2192\u2196\u2191\u2197\u00002bcdfghijklopqrtuyz\u0237\u043e\u0445\u044c\u04af\u04e7\u01bb\u0180\uFFFF\ua793\u0111\uFFFF\ua799\u01e5\u0127\u0268\u0249\uFFFF\ua741\u019a\u0275\u1d7d\uFFFF\ua757\u024d\u0167\u0289\u024f\u01b6\u025f\u04e9\u04ff\u048d\u04b1\u04eb\u0000.012345" + "\u251c\u253c\u2524\u250c\u252c\u2510\u0000acdeilnorstuz\u00fc\u01ce\u010d\u010f\u011b\u01d0\u013e\u0148\u01d2\u0159\u0161\u0165\u01d4\u017e\u01da\u0000cdeghklnrst\u00e7\u1e11\u0229\u0123\u1e29\u0137\u013c\u0146\u0157\u015f\u0163\u0000aceghijouz\u015d\u0430\u0435" +
"6789\u2502\u2500\u2514\u2534\u2518\u251c\u253c\u2524\u250c\u252c\u2510\u0000acdeghijklnorstuz\u00fc\u0292\u0432\u0433\u0434\u0437\u0440\u0442\u0445\u0493\u1e61\u01ce\u010d\u010f\u011b\u01e7\u021f\u01d0\u01f0\u01e9\u013e\u0148\u01d2\u0159\u0161\u0165\u01d4\u017e\u01da\u01ef\uFFFF\u0432\u030c\uFFFF\u0433\u030c\uFFFF\u0434\u030c" + "\u0438\u043e\u0443\u00e2\u0109\u00ea\u011d\u0125\u00ee\u0135\u00f4\u00fb\u1e91\u015d\uFFFF\u0430\u0302\uFFFF\u0435\u0302\uFFFF\u0438\u0302\uFFFF\u043e\u0302\uFFFF\u0443\u0302\u0000abcdefghmnoprstwxyz\u0227\u1e03\u010b\u1e0b\u0117\u1e1f\u0121\u1e23\u1e41\u1e45\u022f\u1e57\u1e59\u1e61\u1e6b\u1e87\u1e8b\u1e8f\u017c\u0000aei" +
"\uFFFF\u0437\u030c\uFFFF\u0440\u030c\uFFFF\u0442\u030c\uFFFF\u0445\u030c\uFFFF\u0493\u030c\u1e67\u0000cdeghklnrst\u0107\u0115\u00e7\u1e11\u0229\u0123\u1e29\u0137\u013c\u0146\u0157\u015f\u0163\u1e1d\u0000+aceghijouwxyz\u00e0\u00e1\u00e3\u00e8\u00e9\u00f2\u00f3\u00f5\u015d\u01a1\u0430\u0435\u0438\u043e\u0443" + "ouy\u00e2\u00ea\u00f4\u0103\u01a1\u01b0\u1ea1\u1eb9\u1ecb\u1ecd\u1ee5\u1ef5\u1ead\u1ec7\u1ed9\u1eb7\u1ee3\u1ef1\u0000 aeimouy\u02dd\uFFFF\u0061\u030b\uFFFF\u0065\u030b\uFFFF\u0069\u030b\uFFFF\u006d\u030b\u0151\u0171\uFFFF\u0079\u030b\u0000aeiou\u00fc\u00e0\u00e8\u00ec\u00f2\u00f9\u01dc\u0000aeiouy\u00e2\u00ea\u00f4\u0103" +
"\u1ea1\u1ea3\u1eb9\u1ebb\u1ebd\u1ecd\u2248\u2a23\u00e2\u0109\u00ea\u011d\u0125\u00ee\u0135\u00f4\u00fb\u0175\uFFFF\u0078\u0302\u0177\u1e91\u1ea7\u1eab\u1ec1\u1ed3\u1ed7\u015d\u1ed5\uFFFF\u0430\u0302\uFFFF\u0435\u0302\uFFFF\u0438\u0302\uFFFF\u043e\u0302\uFFFF\u0443\u0302\u1ead\u1ea9\u1ec7\u1ec3\u1ec5\u1ed9\u2a6f\u00000123456789abcdefghi" + "\u01a1\u01b0\u1ea3\u1ebb\u1ec9\u1ecf\u1ee7\u1ef7\u1ea9\u1ec3\u1ed5\u1eb3\u1edf\u1eed\u0000ou\u00f2\u00f3\u00f5\u00f9\u00fa\u0169\u1ecd\u1ecf\u1ee5\u1ee7\u01a1\u01b0\u1edd\u1edb\u1ee1\u1eeb\u1ee9\u1eef\u0000aeiou\u00fc\u0101\u0113\u012b\u014d\u016b\u01d6\u0000aeiklnou\u0105\u0119\u012f\u01eb\u0173\u0000*12345678" +
"jklmnopqrstuvwxyz~\u0101\u014d\u015b\u0161\u017f\u1e63\u2208\u2227\u2228\u2261\u2286\u2287\u2a2f\uFFFF\u0030\u0307\uFFFF\u0031\u0307\uFFFF\u0032\u0307\uFFFF\u0033\u0307\uFFFF\u0034\u0307\uFFFF\u0035\u0307\uFFFF\u0036\u0307\uFFFF\u0037\u0307\uFFFF\u0038\u0307\uFFFF\u0039\u0307\u0227\u1e03\u010b\u1e0b\u0117\u1e1f\u0121\u1e23\u0131\u0237\uFFFF" + "9ao\u00b0\u00aa\u00ba\u207f\u1d48\u1d49\u02b3\u02e2\u1d57\u02b0\u0000au\u00e5\u016f\u0000abcegklnorst\u2c65\u2422\u023c\u0247\uFFFF\ua7a1\uFFFF\ua743\u0142\uFFFF\ua7a5\u00f8\uFFFF\ua7a7\uFFFF\ua7a9\u2c66\u0000()+-0123456789=aehijklm" +
"\u006b\u0307\uFFFF\u006c\u0307\u1e41\u1e45\u022f\u1e57\uFFFF\u0071\u0307\u1e59\u1e61\u1e6b\uFFFF\u0075\u0307\uFFFF\u0076\u0307\u1e87\u1e8b\u1e8f\u017c\u2a6a\u01e1\u0231\u1e9b\u1e69\u22f5\u2a51\u2a52\u2a67\u2ac3\u2ac4\u2a30\u0000+-=abdehiklmnorstuvwyz\u00e2\u00ea\u00f4\u0103\u01a1\u01b0\u1e61\u2a25\u2a2a\u2a66\u1ea1\u1e05" + "noprstuvx\u208d\u208e\u208a\u208b\u2080\u2081\u2082\u2083\u2084\u2085\u2086\u2087\u2088\u2089\u208c\u2090\u2091\u2095\u1d62\u2c7c\u2096\u2097\u2098\u2099\u2092\u209a\u1d63\u209b\u209c\u1d64\u1d65\u2093\u0000()+-0123456789=abcdefghijklmno" +
"\u1e0d\u1eb9\u1e25\u1ecb\u1e33\u1e37\u1e43\u1e47\u1ecd\u1e5b\u1e63\u1e6d\u1ee5\u1e7f\u1e89\u1ef5\u1e93\u1eb7\u1ee3\u1ef1\u0000 aeimouy\u0443\u02dd\uFFFF\u0061\u030b\uFFFF\u0065\u030b\uFFFF\u0069\u030b\uFFFF\u006d\u030b\u0151\u0171\uFFFF\u0079\u030b\u04f3\u0000aeioru\u0430\u0435\u0438\u043e\u0440\u0443\u0475\u0201\u0205\u0209\u020d\u0211\u0215\uFFFF\u0430\u030f" + "prstuvwxyz\u207d\u207e\u207a\u207b\u2070\u00b9\u00b2\u00b3\u2074\u2075\u2076\u2077\u2078\u2079\u207c\u1d43\u1d47\u1d9c\u1da0\u1d4d\u2071\u02b2\u1d4f\u02e1\u1d50\u1d52\u1d56\u1d58\u1d5b\u02b7\u02e3\u02b8\u1dbb\u0000aeinou\u00e2\u00ea\u0103\u01a1\u01b0\u00e3\u1ebd\u0129\u00f1\u00f5\u0169\u1eab\u1ec5\u1eb5\u0000aeiouy\u00e4" +
"\uFFFF\u0435\u030f\uFFFF\u0438\u030f\uFFFF\u043e\u030f\uFFFF\u0440\u030f\uFFFF\u0443\u030f\u0477\u0000aeinosuwyz\u00e2\u00ea\u00f4\u00fc\u0103\u0113\u014d\u01a1\u01b0\u0254\u028c\u03b1\u03b5\u03b7\u03b9\u03bf\u03c5\u03c9\u0435\u0438\u00e0\u00e8\u00ec\u01f9\u00f2\uFFFF\u0073\u0300\u00f9\u1e81\u1ef3\uFFFF\u007a\u0300\u01dc\u1eb1\u1e15\u1e51\u1edd\u1eeb\uFFFF\u0254\u0300\uFFFF\u028c" + "\u00eb\u00ef\u00f6\u00fc\u00ff\u0000 !\"#%'()*+,-./01234578:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdef" +
"\u0300\u1f70\u1f72\u1f74\u1f76\u1f78\u1f7a\u1f7c\u0450\u045d\u0000aeiouy\u00e2\u00ea\u00f4\u0103\u01a1\u01b0\u1ea3\u1ebb\u1ec9\u1ecf\u1ee7\u1ef7\u1eb3\u1edf\u1eed\u0000ou\u00f2\u00f3\u00f5\u00f9\u00fa\u0169\u1ecd\u1ecf\u1ee5\u1ee7\u01a1\u01b0\u1ee1\u1eef\u0000aegiloruy\u00e4\u00e6\u00e8\u00e9\u00f2\u00f3\u00f5\u00f6\u00fc\u01eb\u0227\u022f\u03b1" + "ghijklmnoprstuvwxyz{|~\u00a8\u00af\u00b4\u00b8\u00f7\u02d8\u0391\u0395\u0397\u0399\u039f\u03a5\u03a9\u03b1\u03b5\u03b7\u03b9\u03bf\u03c5\u03c9\u0415\u0417\u041d\u0421\u0437\u043f\u05b4\u05b7\u05b8\u05b9\u05bc\u05bf\u05c1\u05c2\u0653\u0654\u0655\u093c\u09bc\u09c7\u0a3c\u0b3c\u0b47\u0bc6\u0bc7\u0bd7\u0c46\u0cbf\u0cc6\u0cca" +
"\u03b9\u03c5\u0438\u0443\u1e37\u1e5b\u0101\u0113\u1e21\u012b\uFFFF\u006c\u0304\u014d\uFFFF\u0072\u0304\u016b\u0233\u01df\u01e3\u022d\u022b\u01d6\u01ed\u1fb1\u1fd1\u1fe1\u04e3\u04ef\u1e39\u1e5d\u0000aeiou\u014d\u0105\u0119\u012f\u01eb\u0173\u0000*123456789ao\u00b0\u00aa\u00ba\u207f\u1d48\u1d49\u02b3\u02e2\u1d57\u02b0\u0000auwy" + "\u0d46\u0d47\u0dd9\u0ddc\u0f71\u0f90\u0f92\u0f9c\u0fa1\u0fa6\u0fab\u0fb2\u0fb3\u0fb5\u0fb7\u102e\u1100\u1102\u1103\u1105\u1106\u1107\u1108\u1109\u110a\u110b\u110c\u110e\u1111\u1112\u1121\u1132\u113c\u113e\u114e\u1150\u1161\u1163\u1165\u1167\u1169\u116a\u116d\u116e\u116f\u1172\u1173\u1174\u1175\u119e\u11a8\u11aa\u11ab\u11ae\u11af\u11b0\u11b1\u11b2\u11b3\u11b7\u11b8\u11ba\u11bc\u11c1\u11c2\u11ce\u11dd\u11ec\u11f0\u2190\u2191\u2192" +
"~\u00e1\u00e5\u016f\u1e98\u1e99\u2e1b\u0000abcegklnorstuv\u00f3\u0254\u2c65\u2422\u023c\u0247\uFFFF\ua7a1\uFFFF\ua743\u0142\uFFFF\ua7a5\u00f8\uFFFF\ua7a7\uFFFF\ua7a9\u2c66\uFFFF\ua7b9\uFFFF\ua75f\uFFFF\uab3f\u0000()+-0123456789=aehijklmn" + "\u2193\u2203\u2206\u2207\u2208\u220a\u220b\u2218\u2223\u2225\u2227\u2228\u2229\u222a\u223c\u2243\u2248\u224d\u2260\u2261\u2264\u2265\u2272\u2273\u2276\u2277\u227a\u227b\u227c\u227d\u2282\u2283\u2286\u2287\u2291\u2292\u22a3\u22a4\u22a5\u22a8\u22a9\u22ab\u22b2\u22b3\u22b4\u22b5\u22c4\u2373\u2375\u237a\u2395\u25cb\u2add\u0000 (,-.<>_\u00a0\u02d8\u00b8~\u2008\u02c7^\u00af\u0000!" +
"oprstuvx\u0259\u03b2\u03b3\u03c1\u03c6\u03c7\u208d\u208e\u208a\u208b\u2080\u2081\u2082\u2083\u2084\u2085\u2086\u2087\u2088\u2089\u208c\u2090\u2091\u2095\u1d62\u2c7c\u2096\u2097\u2098\u2099\u2092\u209a\u1d63\u209b\u209c\u1d64\u1d65\u2093\u2094\u1d66\u1d67\u1d68\u1d69\u1d6a\u0000()+-0123456789=abcd" + "+?ABDEHIKLMNORSTUVWYZ^abdehiklmnorstuvwyz\u01a0\u01a1\u01af\u01b0\u00a1\u0000OUou\u1ee2\u1ef0\u203d\u1ea0\u1e04\u1e0c\u1eb8\u1e24\u1eca\u1e32\u1e36\u1e42\u1e46\u1ecc\u1e5a\u1e62\u1e6c\u1ee4\u1e7e\u1e88\u1ef4" +
"efghijklmnopqrstuvwxyz\u014b\u0153\u0250\u0252\u0254\u0255\u0259\u025b\u025c\u025f\u0263\u0265\u0266\u0268\u026f\u0270\u0271\u0275\u0279\u027b\u0281\u0282\u0283\u0289\u028a\u028c\u028d\u0292\u03b2\u03b4\u03b8\u03b9\u03c6\u03c7\u04e9\u1d02\u1d08\u1d09\u1d1d\u207d\u207e\u207a\u207b\u2070\u00b9\u00b2\u00b3\u2074\u2075\u2076" + "\u1e92\u00a6\u1e05\u1e0d\u1e25\u1e33\u1e37\u1e43\u1e47\u1e5b\u1e63\u1e6d\u1e7f\u1e89\u1e93\u0000 \"',<>AEHIOUWXY_aehiotuwxy~\u00af\u00b4\u00d5\u00f5\u016a\u016b\u0399\u03a5\u03b9\u03c5\u03d2\u0406\u0410\u0415\u0416\u0417\u0418\u041e\u0423\u0427\u042b\u042d\u0430\u0435\u0436\u0437\u0438\u043e\u0443" +
"\u2077\u2078\u2079\u207c\u1d43\u1d47\u1d9c\u1da0\u1d4d\u2071\u02b2\u1d4f\u02e1\u1d50\u1d52\u1d56\uFFFF\ua7f4\u1d58\u1d5b\u02b7\u02e3\u02b8\u1dbb\u1d51\uFFFF\ua7f9\u1d44\u1d9b\u1d53\u1d9d\u1d4a\u1d4b\u1d9f\u1da1\u02e0\u1da3\u02b1\u1da4\u1d5a\u1dad\u1dac\u1db1\u02b4\u02b5\u02b6\u1db3\u1db4\u1db6\u1db7\u1dba\uFFFF\uab69\u1dbe\u1d5d\u1d5f\u1dbf\u1da5\u1d60\u1d61\u1d46\u1d4c\u1d4e\u1d59\u0000aeinouv" + "\u0447\u044b\u044d\u0456\u04d8\u04d9\u04e8\u04e9\u00a8\u0344\u201e\u201c\u201d\u00c4\u00cb\u1e26\u00cf\u00d6\u00dc\u1e84\u1e8c\u0178\u0000Uu\u1e7a\u1e7b\u1e27\u1e97\u1e85\u1e8d\u0000Oo\u1e4e\u1e4f\u0000Uu\u03aa\u03ab\u03ca\u03cb\u03d4\u0407\u04d2\u0401\u04dc\u04de\u04e4\u04e6\u04f0\u04f4\u04f8\u04ec\u04d3\u0451\u04dd\u04df\u04e5\u04e7\u04f1\u04f5\u04f9\u04ed\u0457\u04da\u04db\u04ea\u04eb\u0000#" +
"y\u00e2\u00ea\u00f3\u00f6\u00fa\u0103\u014d\u01a1\u01b0\u00e3\u1ebd\u0129\u00f1\u00f5\u0169\u1e7d\u1ef9\u1e4f\u1eb5\u0000*acehijklmnostuwxy~\u00b0\u00ed\u00f5\u00f9\u00fa\u0101\u014d\u016b\u01d4\u03b9\u03c5\u03cd\u03d2\u0430\u0436\u0437\u0438\u043e\u0443\u0447\u044b\u044d\u04d9\u04e9\u1f7a\u1fe6\u2207\u2363\u00e4\uFFFF\u0063\u0308" + "ESbefq\u266f\u266b\u266c\u266d\u266a\u266e\u2669\u0000o\u2030\u0000\"'()+,/<>ACEGIJKLMNOPRSUWYZ^_abcegijklmnoprsuwyz~\u00af\u00b8\u00c2\u00c5\u00c6\u00c7" +
"\u00eb\u1e27\u00ef\uFFFF\u006a\u0308\uFFFF\u006b\u0308\uFFFF\u006c\u0308\uFFFF\u006d\u0308\uFFFF\u006e\u0308\u00f6\uFFFF\u0073\u0308\u1e97\u00fc\u1e85\u1e8d\u00ff\u2368\u2364\u03ca\u03cb\u03b0\u03d4\u04d3\u04dd\u04df\u04e5\u04e7\u04f1\u04f5\u04f9\u04ed\u04db\u1fe2\u1fe7\u2362\u0000 !\"#%'()*+,-./01234578:;<" + "\u00ca\u00cf\u00d4\u00d5\u00d8\u00dc\u00e2\u00e5\u00e6\u00e7\u00ea\u00ef\u00f4\u00f5\u00f8\u00fc\u0102\u0103\u0112\u0113\u014c\u014d\u0168\u0169\u01a0\u01a1\u01af\u01b0\u0391\u0395\u0397\u0399\u039f\u03a5\u03a9\u03b1\u03b5\u03b7\u03b9\u03bf\u03c5\u03c9\u0410\u0413\u0415\u0418\u041a\u041e\u0420\u0423\u042b\u042d\u042e\u042f\u0430\u0433\u0435\u0438\u043a\u043e\u0440\u0443\u044b\u044d\u044e\u044f\u2395\u0000 IUi" +
"=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnoprstuvwxyz{|~\u00a8\u00af\u00b4\u00b8\u00f7\u02d8\u0391\u0395\u0397" + "u\u03b9\u03c5\u0385\u1e2e\u01d7\u1e2f\u0390\u03b0\u00b4\u0000\u0391\u0395\u0397\u0399\u039f\u03a5\u03a9\u03b1\u03b5\u03b7\u03b9\u03bf\u03c5\u03c9\u1f0d\u1f1d\u1f2d\u1f3d\u1f4d\u1f5d\u1f6d\u1f05\u1f15\u1f25\u1f35\u1f45\u1f55\u1f65\u0000\u0391\u0395\u0397\u0399\u039f\u03a9\u03b1\u03b5\u03b7\u03b9\u03bf\u03c5\u03c9\u1f0c\u1f1c\u1f2c\u1f3c\u1f4c\u1f6c\u1f04\u1f14\u1f24\u1f34\u1f44\u1f54\u1f64\u0000OUou\u1eda" +
"\u0399\u039f\u03a5\u03a9\u03b1\u03b5\u03b7\u03b9\u03bf\u03c5\u03c9\u0415\u0417\u041d\u0421\u0430\u0431\u0433\u0434\u0435\u0436\u0437\u0438\u0439\u043a\u043b\u043c\u043d\u043e\u043f\u0442\u0443\u0445\u0447\u0448\u044a\u044e\u044f\u0456\u0458\u0461\u0467\u05b4\u05b7\u05b8\u05b9\u05bc\u05bf\u05c1\u05c2\u0627\u062a\u062c\u062d\u062f\u0633\u0634\u0639\u063a\u0641\u0642\u0644\u0646\u0647\u0648\u064a\u0653\u0654\u0655\u0667\u0668\u06cc" + "\u1ee8\u201a\u0000Oo\u01fe\u01ff\u2018\u2019\u00c1\u0106\u00c9\u01f4\u00cd\uFFFF\u004a\u0301\u1e30\u0139\u1e3e\u0143\u00d3\u1e54\u0154\u015a\u00da\u1e82\u00dd\u0179\u0000AEOaeo\u1ea4\u1ebe\u1ed0\u1ea5\u1ebf\u1ed1\u0000EOeo\u1e16\u1e52\u1e17\u1e53\u0000Aa\u1eae\u1eaf\u01f5\u1e31\u1e3f\u1e55\u1e83\u0000OUou\u1e4c\u1e78\u1e4d\u1e79\u0000E" +
"\u06f7\u06f8\u093c\u09bc\u09c7\u0a3c\u0b3c\u0b47\u0bc6\u0bc7\u0bd7\u0c46\u0cbf\u0cc6\u0cca\u0d46\u0d47\u0dd9\u0ddc\u0f71\u0f90\u0f92\u0f9c\u0fa1\u0fa6\u0fab\u0fb2\u0fb3\u0fb5\u0fb7\u102e\u1100\u1102\u1103\u1105\u1106\u1107\u1108\u1109\u110a\u110b\u110c\u110e\u1111\u1112\u1121\u1132\u113c\u113e\u114e\u1150\u1161\u1163\u1165\u1167\u1169\u116a\u116d\u116e\u116f\u1172\u1173\u1174\u1175\u119e\u11a8\u11aa\u11ab\u11ae\u11af\u11b0\u11b1" + "Oeo\u0000Cc\u1e08\u1e09\u01fa\u01fc\u01fb\u01fd\u0386\u0388\u0389\u038a\u038c\u038e\u038f\u03ac\u03ad\u03ae\u03af\u03cc\u03cd\u03ce\uFFFF\u0410\u0301\u0403\uFFFF\u0415\u0301\uFFFF\u0418\u0301\u040c\uFFFF\u041e\u0301\uFFFF\u0420\u0301\uFFFF\u0423\u0301\uFFFF\u042b\u0301\uFFFF\u042d\u0301\uFFFF\u042e\u0301\uFFFF\u042f\u0301\u0453\u045c\uFFFF\u0440\u0301\u235e\u0000 ()-012" +
"\u11b2\u11b3\u11b7\u11b8\u11ba\u11bc\u11c1\u11c2\u11ce\u11dd\u11ec\u11f0\u2190\u2191\u2192\u2193\u2203\u2206\u2207\u2208\u220a\u220b\u2218\u2223\u2225\u2227\u2228\u2229\u222a\u223c\u2243\u2248\u224d\u2260\u2261\u2264\u2265\u2272\u2273\u2276\u2277\u227a\u227b\u227c\u227d\u2282\u2283\u2286\u2287\u2291\u2292\u22a3\u22a4\u22a5\u22a8\u22a9\u22ab\u22b2\u22b3\u22b4\u22b5\u22c4\u2373\u2375\u237a\u2395\u25cb\u2add\u0000 (," + "3456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\u0391\u0395\u0397\u0399\u039f\u03a1\u03a5\u03a9\u03b1\u03b5\u03b7\u03b9\u03bf" +
"-.<>_\u00a0\u02d8\u00b8~\u2008\u02c7^\u00af\u0000!+?ABDEHIKLMNORSTUVWYZ^abdehiklmnorstuvwyz\u01a0\u01a1\u01af\u01b0\u00a1\u0000OUou\u1ee2\u1ef0\u203d\u1ea0\u1e04\u1e0c" + "\u03c1\u03c5\u03c9\u1100\u1102\u1103\u1105\u1106\u1107\u1109\u110b\u110c\u110e\u110f\u1110\u1111\u1112\u30a2\u30a4\u30a6\u30a8\u30aa\u30ab\u30ad\u30af\u30b1\u30b3\u30b5\u30b7\u30b9\u30bb\u30bd\u30bf\u30c1\u30c4\u30c6\u30c8\u30ca\u30cb\u30cc\u30cd\u30ce\u30cf\u30d2\u30d5\u30d8\u30db\u30de\u30df\u30e0\u30e1\u30e2\u30e4\u30e6\u30e8\u30e9\u30ea\u30eb\u30ec\u30ed\u30ef\u30f0\u30f1\u30f2\u4e00\u4e03\u4e09\u4e0a\u4e0b\u4e2d\u4e5d\u4e8c" +
"\u1eb8\u1e24\u1eca\u1e32\u1e36\u1e42\u1e46\u1ecc\u1e5a\u1e62\u1e6c\u1ee4\u1e7e\u1e88\u1ef4\u1e92\u00a6\u0000 \"',<>AEHIOUWXY_aehiotuwxy~\u00af\u00b4\u00d5\u00f5\u016a\u016b\u0399\u03a5\u03b9\u03c5\u03d2\u0406\u0410\u0415\u0416\u0417\u0418\u041e\u0423\u0427\u042b\u042d\u0430\u0435\u0436\u0437\u0438" + "\u4e94\u4f01\u4f11\u512a\u516b\u516d\u5199\u52b4\u533b\u5341\u5354\u5370\u53f3\u540d\u56db\u571f\u591c\u5973\u5b66\u5b97\u5de6\u65e5\u6708\u6709\u6728\u682a\u6b63\u6c34\u6ce8\u706b\u7279\u7537\u76e3\u793e\u795d\u79d8\u8ca1\u8cc7\u9069\u91d1\u9805[\u0000)\uFFFF\ud83c\udd2f{\u0000)\u24ea\u0000)0123456789\u2460\u0000)\u2469\u0000)\u246a\u0000)" +
"\u043e\u0443\u0447\u044b\u044d\u0456\u04d8\u04d9\u04e8\u04e9\u00a8\u0344\u201e\u201c\u201d\u00c4\u00cb\u1e26\u00cf\u00d6\u00dc\u1e84\u1e8c\u0178\u0000Uu\u1e7a\u1e7b\u0000Oo\u1e4e\u0000Uu\u03aa\u03ab\u0407\u04d2\u0401\u04dc\u04de\u04e4\u04e6\u04f0\u04f4\u04f8\u04ec\u0451\u0457\u04da\u04ea\u0000#ESbefq\u266f\u266b\u266c\u266d\u266a\u266e\u2669\u0000o\u2030\u0000" + "\u246b\u0000)\u246c\u0000)\u246d\u0000)\u246e\u0000)\u246f\u0000)\u2470\u0000)\u2471\u0000)\u2472\u0000)0123456789\u2461\u0000)\u2473\u0000)\u3251\u0000)\u3252\u0000)\u3253\u0000)\u3254\u0000)\u3255\u0000)\u3256\u0000)\u3257\u0000)\u3258\u0000)\u3259\u0000)01234" +
"\"'()+,/<>ACEGIJKLMNOPRSUWYZ^_abcegijklmnoprsuwyz~\u00af\u00b8\u00c2\u00c5\u00c6\u00c7\u00ca\u00cf\u00d4\u00d5\u00d8\u00dc\u00e2\u00e5\u00e6\u00e7\u00ea\u00ef\u00f4\u00f5\u00f8\u00fc\u0102" + "56789\u2462\u0000)\u325a\u0000)\u325b\u0000)\u325c\u0000)\u325d\u0000)\u325e\u0000)\u325f\u0000)\u32b1\u0000)\u32b2\u0000)\u32b3\u0000)\u32b4\u0000)0123456789\u2463\u0000)\u32b5\u0000)\u32b6\u0000)\u32b7\u0000)\u32b8\u0000)\u32b9\u0000)\u32ba\u0000)\u32bb\u0000)" +
"\u0103\u0112\u0113\u014c\u014d\u0168\u0169\u01a0\u01a1\u01af\u01b0\u0391\u0395\u0397\u0399\u039f\u03a5\u03a9\u03b1\u03b5\u03b7\u03b9\u03bf\u03c5\u03c9\u0410\u0413\u0415\u0418\u041a\u041e\u0420\u0423\u042b\u042d\u042e\u042f\u0430\u0433\u0435\u0438\u043a\u043e\u0440\u0443\u044b\u044d\u044e\u044f\u2395\u0000 IUiu\u03b9\u03c5\u0385\u1e2e\u01d7\u0390\u00b4\u0000\u0391\u0395\u0397\u0399\u039f\u03a5\u03a9\u03b1" + "\u32bc\u0000)\u32bd\u0000)\u32be\u0000)0\u2464\u0000)\u32bf\u0000)\u2465\u0000)\u2466\u0000)\u2467\u0000)\u2468\u0000)\u24b6\u0000)\u24b7\u0000)\u24b8\u0000)\u24b9\u0000)\u24ba\u0000)\u24bb\u0000)\u24bc\u0000)\u24bd\u0000)\u24be\u0000)\u24bf\u0000)\u24c0\u0000)\u24c1\u0000)\u24c2\u0000)\u24c3\u0000)\u24c4\u0000" +
"\u03b5\u03b7\u03b9\u03bf\u03c5\u03c9\u1f0d\u1f1d\u1f2d\u1f3d\u1f4d\u1f5d\u1f6d\u1f05\u1f15\u1f25\u1f35\u1f45\u1f55\u1f65\u0000\u0391\u0395\u0397\u0399\u039f\u03a9\u03b1\u03b5\u03b7\u03b9\u03bf\u03c5\u03c9\u1f0c\u1f1c\u1f2c\u1f3c\u1f4c\u1f6c\u1f04\u1f14\u1f24\u1f34\u1f44\u1f54\u1f64\u0000OUou\u1eda\u1ee8\u201a\u0000Oo\u01fe\u2018\u2019\u00c1\u0106\u00c9\u01f4\u00cd\uFFFF\u004a\u0301\u1e30\u0139\u1e3e" + ")\u24c5\u0000)\u24c6\u0000)\u24c7\u0000)\u24c8\u0000)\u24c9\u0000)\u24ca\u0000)\u24cb\u0000)\u24cc\u0000)\u24cd\u0000)\u24ce\u0000)\u24cf\u0000)\u24d0\u0000)\u24d1\u0000)\u24d2\u0000)\u24d3\u0000)\u24d4\u0000)\u24d5\u0000)\u24d6\u0000)\u24d7\u0000)\u24d8\u0000)\u24d9\u0000)\u24da\u0000)\u24db\u0000)\u24dc\u0000" +
"\u0143\u00d3\u1e54\u0154\u015a\u00da\u1e82\u00dd\u0179\u0000AEOaeo\u1ea4\u1ebe\u1ed0\u0000EOeo\u1e16\u1e52\u0000Aa\u1eae\u0000OUou\u1e4c\u1e78\u0000EOeo\u0000Cc\u1e08\u01fa\u01fc\u0386\u0388\u0389\u038a\u038c\u038e\u038f\u03ce\uFFFF\u0410\u0301\u0403\uFFFF\u0415\u0301\uFFFF\u0418\u0301\u040c\uFFFF\u041e\u0301\uFFFF\u0420" + ")\u24dd\u0000)\u24de\u0000)\u24df\u0000)\u24e0\u0000)\u24e1\u0000)\u24e2\u0000)\u24e3\u0000)\u24e4\u0000)\u24e5\u0000)\u24e6\u0000)\u24e7\u0000)\u24e8\u0000)\u24e9\u1f09\u1f19\u1f29\u1f39\u1f49\u1fec\u1f59\u1f69\u1f01\u1f11\u1f21\u1f31\u1f41\u1fe5\u1f51\u1f61\u0000)\u1161\u3260\u0000)\u326e\u0000)\u1161\u3261\u0000)\u326f\u0000)\u1161\u3262" +
"\u0301\uFFFF\u0423\u0301\uFFFF\u042b\u0301\uFFFF\u042d\u0301\uFFFF\u042e\u0301\uFFFF\u042f\u0301\uFFFF\u0440\u0301\u235e\u0000 ()-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk" + "\u0000)\u3270\u0000)\u1161\u3263\u0000)\u3271\u0000)\u1161\u3264\u0000)\u3272\u0000)\u1161\u3265\u0000)\u3273\u0000)\u1161\u3266\u0000)\u3274\u0000)\u1161\u3267\u0000)\u3275\u0000)\u1161\u3268\u0000)\u3276\u0000)\u1161\u3269\u0000)\u3277\u0000)\u1161\u326a\u0000)\u3278\u0000)\u1161\u326b\u0000)\u3279\u0000)\u1161\u326c\u0000)" +
"lmnopqrstuvwxyz\u0391\u0395\u0397\u0399\u039f\u03a1\u03a5\u03a9\u03b1\u03b5\u03b7\u03b9\u03bf\u03c1\u03c5\u03c9\u1100\u1102\u1103\u1105\u1106\u1107\u1109\u110b\u110c\u110e\u110f\u1110\u1111\u1112\u30a2\u30a4\u30a6\u30a8\u30aa\u30ab\u30ad\u30af\u30b1\u30b3\u30b5\u30b7\u30b9\u30bb\u30bd\u30bf\u30c1\u30c4\u30c6\u30c8\u30ca\u30cb\u30cc\u30cd\u30ce\u30cf\u30d2" + "\u327a\u0000)\u1161\u326d\u0000)\u327b\u0000)\u32d0\u0000)\u32d1\u0000)\u32d2\u0000)\u32d3\u0000)\u32d4\u0000)\u32d5\u0000)\u32d6\u0000)\u32d7\u0000)\u32d8\u0000)\u32d9\u0000)\u32da\u0000)\u32db\u0000)\u32dc\u0000)\u32dd\u0000)\u32de\u0000)\u32df\u0000)\u32e0\u0000)\u32e1\u0000)\u32e2\u0000)\u32e3\u0000)\u32e4\u0000" +
"\u30d5\u30d8\u30db\u30de\u30df\u30e0\u30e1\u30e2\u30e4\u30e6\u30e8\u30e9\u30ea\u30eb\u30ec\u30ed\u30ef\u30f0\u30f1\u30f2\u4e00\u4e03\u4e09\u4e0a\u4e0b\u4e2d\u4e5d\u4e8c\u4e94\u4f01\u4f11\u512a\u516b\u516d\u5199\u52b4\u533b\u5341\u5354\u5370\u53f3\u540d\u56db\u571f\u591c\u5973\u5b66\u5b97\u5de6\u65e5\u6708\u6709\u6728\u682a\u6b63\u6c34\u6ce8\u706b\u7279\u7537\u76e3\u793e\u795d\u79d8\u8ca1\u8cc7\u9069\u91d1\u9805[\u0000)" + ")\u32e5\u0000)\u32e6\u0000)\u32e7\u0000)\u32e8\u0000)\u32e9\u0000)\u32ea\u0000)\u32eb\u0000)\u32ec\u0000)\u32ed\u0000)\u32ee\u0000)\u32ef\u0000)\u32f0\u0000)\u32f1\u0000)\u32f2\u0000)\u32f3\u0000)\u32f4\u0000)\u32f5\u0000)\u32f6\u0000)\u32f7\u0000)\u32f8\u0000)\u32f9\u0000)\u32fa\u0000)\u32fb\u0000)\u32fc\u0000" +
"\uFFFF\ud83c\udd2f{\u0000)\u24ea\u0000)0123456789\u2460\u0000)\u2469\u0000)\u246a\u0000)\u246b\u0000)\u246c\u0000)\u246d\u0000)\u246e\u0000)\u246f\u0000)\u2470\u0000)\u2471\u0000)\u2472\u0000)0123456789\u2461\u0000)\u2473\u0000)\u3251\u0000)\u3252" + ")\u32fd\u0000)\u32fe\u0000)\u3280\u0000)\u3286\u0000)\u3282\u0000)\u32a4\u0000)\u32a6\u0000)\u32a5\u0000)\u3288\u0000)\u3281\u0000)\u3284\u0000)\u32ad\u0000)\u32a1\u0000)\u329d\u0000)\u3287\u0000)\u3285\u0000)\u32a2\u0000)\u3298\u0000)\u32a9\u0000)\u3289\u0000)\u32af\u0000)\u329e\u0000)\u32a8\u0000)\u3294\u0000" +
"\u0000)\u3253\u0000)\u3254\u0000)\u3255\u0000)\u3256\u0000)\u3257\u0000)\u3258\u0000)\u3259\u0000)0123456789\u2462\u0000)\u325a\u0000)\u325b\u0000)\u325c\u0000)\u325d\u0000)\u325e\u0000)\u325f\u0000)\u32b1\u0000)\u32b2\u0000)\u32b3\u0000)\u32b4\u0000)012345" + ")\u3283\u0000)\u328f\u0000)\u32b0\u0000)\u329b\u0000)\u32ab\u0000)\u32aa\u0000)\u32a7\u0000)\u3290\u0000)\u328a\u0000)\u3292\u0000)\u328d\u0000)\u3291\u0000)\u32a3\u0000)\u328c\u0000)\u329f\u0000)\u328b\u0000)\u3295\u0000)\u329a\u0000)\u32ac\u0000)\u3293\u0000)\u3297\u0000)\u3299\u0000)\u3296\u0000)\u32ae\u0000" +
"6789\u2463\u0000)\u32b5\u0000)\u32b6\u0000)\u32b7\u0000)\u32b8\u0000)\u32b9\u0000)\u32ba\u0000)\u32bb\u0000)\u32bc\u0000)\u32bd\u0000)\u32be\u0000)0\u2464\u0000)\u32bf\u0000)\u2465\u0000)\u2466\u0000)\u2467\u0000)\u2468\u0000)\u24b6\u0000)\u24b7\u0000)\u24b8\u0000)\u24b9\u0000)\u24ba\u0000)\u24bb" + ")\u329c\u0000)\u328e\u0000)\u32a0\u0000)-\u0391\u0395\u0397\u0399\u039f\u03a9\u03b1\u03b5\u03b7\u03b9\u03bf\u03c1\u03c5\u03c9]}\u1f08\u1f18\u1f28\u1f38\u1f48\u1f68\u1f00\u1f10\u1f20\u1f30\u1f40\u1fe4\u1f50\u1f60\u0000'0AUau\u00a8\u25cb\u0000Aa\u00c5\u016e\u2363\u235f\u0000+-OUou#\u00b1\u01a0\u01af\u0000 \"'" +
"\u0000)\u24bc\u0000)\u24bd\u0000)\u24be\u0000)\u24bf\u0000)\u24c0\u0000)\u24c1\u0000)\u24c2\u0000)\u24c3\u0000)\u24c4\u0000)\u24c5\u0000)\u24c6\u0000)\u24c7\u0000)\u24c8\u0000)\u24c9\u0000)\u24ca\u0000)\u24cb\u0000)\u24cc\u0000)\u24cd\u0000)\u24ce\u0000)\u24cf\u0000)\u24d0\u0000)\u24d1\u0000)\u24d2\u0000)\u24d3" + ",-ACDEGHIKLNORSTUacdeghiklnorstu\u00ac\u0104\u00c7\u1e10\u0118\u0122\u1e28\u012e\u0136\u013b\u0145\u01ea\u0156\u015e\u0162\u0172\u0000 ()+,-./:>ADEIKLOU\\^_ad" +
"\u0000)\u24d4\u0000)\u24d5\u0000)\u24d6\u0000)\u24d7\u0000)\u24d8\u0000)\u24d9\u0000)\u24da\u0000)\u24db\u0000)\u24dc\u0000)\u24dd\u0000)\u24de\u0000)\u24df\u0000)\u24e0\u0000)\u24e1\u0000)\u24e2\u0000)\u24e3\u0000)\u24e4\u0000)\u24e5\u0000)\u24e6\u0000)\u24e7\u0000)\u24e8\u0000)\u24e9\u1f09\u1f19\u1f29\u1f39\u1f49\u1fec" + "eilou\u2191\u2193\u25cb\u0000 -.\u00ad\u2014\u2013\u0000Ee\uFFFF\u0116\u0304\uFFFF\u0117\u0304\u233f\u00f7\u0100\u0110\u0112\u012a\u20ad\u00a3\u014c\u016a\u2340\u2212\u234f\u2356\u2296\u0000 !'-.:<=>ABCDEFGHIMNOPRSTWXYZ^ab" +
"\u1f59\u1f69\u1f01\u1f11\u1f21\u1f31\u1f41\u1fe5\u1f51\u1f61\u0000)\u1161\u3260\u0000)\u326e\u0000)\u1161\u3261\u0000)\u326f\u0000)\u1161\u3262\u0000)\u3270\u0000)\u1161\u3263\u0000)\u3271\u0000)\u1161\u3264\u0000)\u3272\u0000)\u1161\u3265\u0000)\u3273\u0000)\u1161\u3266\u0000)\u3274\u0000)\u1161\u3267\u0000)\u3275\u0000)\u1161\u3268\u0000)" + "cdefghimnoprstwxyz\u00b4\u015a\u015b\u0160\u0161\u017f\u1e62\u1e63\u25cb\u02d9\u0000Ss\u1e68\u1e69\u0000Ss\u1e64\u1e65\u00b7\u2026\u2235\u2039\u2022\u203a\u0226\u1e02\u010a\u1e0a\u0116\u1e1e\u0120\u1e22\u0130\u1e40\u1e44\u022e\u1e56\u1e58\u1e60\u1e6a\u1e86\u1e8a\u1e8e\u017b\u0131\u0000Ss\u1e66\u1e67\u1e9b\u2299" +
"\u3276\u0000)\u1161\u3269\u0000)\u3277\u0000)\u1161\u326a\u0000)\u3278\u0000)\u1161\u326b\u0000)\u3279\u0000)\u1161\u326c\u0000)\u327a\u0000)\u1161\u326d\u0000)\u327b\u0000)\u32d0\u0000)\u32d1\u0000)\u32d2\u0000)\u32d3\u0000)\u32d4\u0000)\u32d5\u0000)\u32d6\u0000)\u32d7\u0000)\u32d8\u0000)\u32d9\u0000)\u32da\u0000)\u32db" + "\u0000-/<=BCDGHILOTZ^bcdghilmotuvz\u0294\u0413\u041a\u0433\u043a\u04ae\u04af\u2190\u2192\u2194\u2395\\\u2260\u0243\u20a1\u01e4\u0126\u0197\u0141\u00d8\u0166\u01b5|\u00a2\u0127\u20a5\u00b5\u221a\u02a1\u0492\u049e\u0493\u049f\u04b0\u04b1\u219a\u219b\u21ae\u2341\u0000*3~" +
"\u0000)\u32dc\u0000)\u32dd\u0000)\u32de\u0000)\u32df\u0000)\u32e0\u0000)\u32e1\u0000)\u32e2\u0000)\u32e3\u0000)\u32e4\u0000)\u32e5\u0000)\u32e6\u0000)\u32e7\u0000)\u32e8\u0000)\u32e9\u0000)\u32ea\u0000)\u32eb\u0000)\u32ec\u0000)\u32ed\u0000)\u32ee\u0000)\u32ef\u0000)\u32f0\u0000)\u32f1\u0000)\u32f2\u0000)\u32f3" + "\u2189\u236c\u0000123456789^\u00000\u2152\u00bd\u2153\u00bc\u2155\u2159\u2150\u215b\u2151\u000035^\u2154\u2156\u0000458^\u00be\u2157\u215c\u00005\u2158\u000068\u215a\u215d\u00008\u215e\u00008\u221e\u0000()-.\u2395\u2639\u263a\u2234\u2360\u0000 AEIOSTU_" +
"\u0000)\u32f4\u0000)\u32f5\u0000)\u32f6\u0000)\u32f7\u0000)\u32f8\u0000)\u32f9\u0000)\u32fa\u0000)\u32fb\u0000)\u32fc\u0000)\u32fd\u0000)\u32fe\u0000)\u3280\u0000)\u3286\u0000)\u3282\u0000)\u32a4\u0000)\u32a6\u0000)\u32a5\u0000)\u3288\u0000)\u3281\u0000)\u3284\u0000)\u32ad\u0000)\u32a1\u0000)\u329d\u0000)\u3287" + "aeiostu\u02db\u0218\u021a\u236e\u0219\u021b\u0000 \"'-/3<=>CDELNRSTZ_cdelnrstz\u2395\u226e\u2665\u00ab\u2264\u22c4\u010c\u010e\u011a\u013d\u0147\u0158\u0160\u0164\u017d\u2343\u0000/<>CELNOPRTUW" +
"\u0000)\u3285\u0000)\u32a2\u0000)\u3298\u0000)\u32a9\u0000)\u3289\u0000)\u32af\u0000)\u329e\u0000)\u32a8\u0000)\u3294\u0000)\u3283\u0000)\u328f\u0000)\u32b0\u0000)\u329b\u0000)\u32ab\u0000)\u32aa\u0000)\u32a7\u0000)\u3290\u0000)\u328a\u0000)\u3292\u0000)\u328d\u0000)\u3291\u0000)\u32a3\u0000)\u328c\u0000)\u329f" + "Y^_cdeopruvy\u0415\u0417\u0421\u0423\u0437\u0443\u2395\u21d0\u21d2\u20ac\u20a4\u20a6\u0150\u20bd\u20b9\u20ae\u0170\u20a9\u00a5\u21d1\u2261\u20ab\u21d3\u04f2\u04f3\u2338\u0000 \"'/<=>AEIOU_aeiou\u00a8\u2395\u226f\u2265\u00bb\u00c2\u00ca\u00ce\u00d4\u00db\u2369\u2344\u0000!+" +
"\u0000)\u328b\u0000)\u3295\u0000)\u329a\u0000)\u32ac\u0000)\u3293\u0000)\u3297\u0000)\u3299\u0000)\u3296\u0000)\u32ae\u0000)\u329c\u0000)\u328e\u0000)\u32a0\u0000)-\u0391\u0395\u0397\u0399\u039f\u03a9\u03b1\u03b5\u03b7\u03b9\u03bf\u03c1\u03c5\u03c9]}\u1f08\u1f18\u1f28\u1f38\u1f48\u1f68\u1f00\u1f10\u1f20\u1f30\u1f40\u1fe4\u1f50\u1f60\u0000'0" + "?AEIOUY\\^abeiouy\u00c2\u00ca\u00d4\u00e2\u00ea\u00f4\u0102\u0103\u01a0\u01a1\u01af\u01b0\u2395\u2e18\u0000OUou\u1ede\u1eec\u00bf\u1ea2\u1eba\u1ec8\u1ece\u1ee6\u1ef6\u262d\u0000AEOaeo\u1ea8\u1ec2\u1ed4\u0000Aa\u1eb2\u2370\u0000\"'(*,-;>AET" +
"AUau\u00a8\u25cb\u0000Aa\u00c5\u016e\u235f\u0000+-OUou#\u00b1\u01a0\u01af\u0000 \"',-ACDEGHIKLNORSTUacdeghiklnorstu\u0433\u043a\u043b\u043d\u0445\u0467\u00ac\u0104\u00c7\u1e10\u0118\u0122\u1e28" + "^_`~\u00a8\u00b4\u0102\u00c6@\u00c0\u00c3\u0000.|\u0e3f\u0000',./<=CEOr|\u2102\u20a0\u00a9\u20a2\u20b5\u0000,-.<H\u00d0\u0000\"',-.;<=>E^_`\u00a8\u00b4\u018f\u00c8\u0000.Uilr\uFFFF\ud83d\udd95\uFFFF\ufb03\uFFFF\ufb04\u20a3\u0000" +
"\u012e\u0136\u013b\u0145\u01ea\u0156\u015e\u0162\u0172\u04fb\u04c4\u0513\u04c8\u04fd\u04ca\u0000 ()+,-./:>ADEIKLOU\\^_adeilou\u2191\u2193\u25cb\u0000 -.\u00ad\u2014\u2013\u0000Ee\uFFFF\u0116\u0304\uFFFF\u0117\u0304\u233f\u00f7\u0100\u0110\u0112\u012a\u20ad\u00a3\u014c" + "(,.TU|\u02d8\u011e>\u20b2\u0000,\u0000\"',-.;>J^_`j~\u00a8\u00b4\u0132\u00cc\u0128\u0000'\u00b4\u0000,-\u0000',-/<=LTV\u0000A\u0000P\uFFFF\ud83d\udd96<\u0000.\u0000',<=GNOo~\u014a\u2115\u2116\u00d1\u0000" +
"\u016a\u2340\u2212\u234f\u2356\u2296\u0000 !'-.:<=>ABCDEFGHIMNOPRSTWXYZ^abcdefghimnoprstwxyz\u00b4\u015a\u015b\u0160\u0161\u017f\u0433\u0436\u0439\u043a\u043b\u043c\u043d\u0445\u0447" + "\"',-/;>ACERSXY^_`~\u00a8\u00b4\u0152\u00ae\u00a7\u00a4\u262e\u00d2\u00d5\u0000!.=Pt\u00b6\u20a7\u0000Q\u211a\u0000',<=ORs\u211d\u20a8\u0000!',.;<MOS|\u2120\u1e9e$\u0000,-./;<=HM" +
"\u0456\u1e62\u1e63\u25cb\u02d9\u0000Ss\u1e68\u0000Ss\u1e64\u00b7\u2026\u2235\u2039\u2022\u203a\u0226\u1e02\u010a\u1e0a\u0116\u1e1e\u0120\u1e22\u0130\u1e40\u1e44\u022e\u1e56\u1e58\u1e60\u1e6a\u1e86\u1e8a\u1e8e\u017b\u0000Ss\u1e66\u04f7\u0497\u048b\u049b\u052f\u04ce\u04b3\u04b7\u2299\u0000-/<=BCDGHILOTZ^bcdg" + "\u00de\u2122\u0000 !\"'*,-;>AEGIOU^_`aegiou~\u00a8\u00b4\u00b8\u0391\u0399\u03a5\u03b1\u03b9\u03c5\u0410\u0415\u0416\u0418\u0423\u0430\u0435\u0436\u0438\u0443\u0000,\u0000Ee\u1e1c\u1e1d\u0000Aa\u1eb6\u0114\u012c\u014e\u016c\u00d9\u0103\u0115\u011f\u012d\u014f\u016d\u0168\u0000E" +
"hilmotuvz\u0294\u0413\u041a\u0433\u043a\u04ae\u04af\u2190\u2192\u2194\u2395\\\u2260\u0243\u20a1\u01e4\u0126\u0197\u0141\u00d8\u0166\u01b5|\u00a2\u20a5\u00b5\u221a\u02a1\u0492\u049e\u0493\u049f\u04b0\u219a\u219b\u21ae\u2341\u0000*3~\u2189\u236c\u0000123456789^\u00000\u2152\u00bd\u2153\u00bc\u2155\u2159\u2150" + "e\u1fb8\u1fd8\u1fe8\u1fb0\u1fd0\u1fe0\u04d0\u04d6\u04c1\u0419\u040e\u04d1\u04d7\u04c2\u0439\u045e\u0000Lcsz\u0000=^\u0174\u0000O\u0000\"'=^\u00a8\u00b4\u0176\u0000'.<Z\u2124\u0000]\u2337\u0000-?not\u2395\u25cb\uFFFF\\\u006e\u0000/\uFFFF\ud83d\ude4c\uFFFF\\\u0074\u2342\u2349\u0000[\u0000!()" +
"\u215b\u2151\u000035^\u2154\u2156\u0000458^\u00be\u2157\u215c\u00005\u2158\u000068\u215a\u215d\u00008\u215e\u00008\u221e\u0000()-.\u2395\u2639\u263a\u2234\u2360\u0000 AEIOSTU_aeiostu\u02db\u0218\u021a\u236e\u0219\u021b\u0000 \"'-/3<=" + "+-./0123456789=ACEGHIJOSUWYZ_aceghijosuwyz|\u0410\u0415\u0418\u041e\u0420\u0423\u0430\u0435\u0438\u043e\u0440\u0443\u1eb8\u1eb9\u1ecc\u1ecd\u2212\u4e00\u4e01\u4e09\u4e0a\u4e0b\u4e19\u4e2d\u4e59\u4e8c\u4eba\u56db\u5730" +
">CDELNRSTZ_cdelnrstz\u2395\u226e\u2665\u00ab\u2264\u22c4\u010c\u010e\u011a\u013d\u0147\u0158\u0160\u0164\u017d\u2343\u0000/<>CELNOPRTUWY^_cdeopruvy\u0415\u0417\u0421\u0423\u0437\u0443\u2395\u21d0\u21d2\u20ac" + "\u5929\u7532\u0000AEOaeo\u1eac\u1ec6\u1ed8\u0108\u011c\u0124\u0134\u015c\u1e90\u0000ahijlnorswxy\u0263\u0266\u0279\u027b\u0281\u0295\u02e0\u02b1\u02b4\u02b5\u02b6\u02e4\u0175\u0177\uFFFF\u0410\u0302\uFFFF\u0415\u0302\uFFFF\u0418\u0302\uFFFF\u041e\u0302\uFFFF\u0420\u0302\uFFFF\u0423\u0302\uFFFF\u0440\u0302\u3192\u319c\u3194\u3196\u3198\u319b" +
"\u20a4\u20a6\u0150\u20bd\u20b9\u20ae\u0170\u20a9\u00a5\u21d1\u2261\u20ab\u21d3\u04f2\u2338\u0000 \"'/<=>AEIOU_aeiou\u00a8\u2395\u226f\u2265\u00bb\u00c2\u00ca\u00ce\u00d4\u00db\u2369\u2344\u0000!+?AEIOUY\\^abeiouy\u00c2\u00ca\u00d4\u00e2\u00ea\u00f4\u0102" + "\u3197\u319a\u3193\u319f\u3195\u319e\u319d\u3199\u0000 !\"'()+-.0123456789;<=>AEGIOUY^_aegiouy~\u00c4\u00c6\u00d5\u00d6\u00dc\u00e4\u00e6\u00f5\u00f6\u00fc\u0226\u0227\u0391\u0399\u03a5\u03b1\u03b9\u03c5\u0410\u0415\u0418\u041e\u0420" +
"\u0103\u01a0\u01a1\u01af\u01b0\u2395\u2e18\u0000OUou\u1ede\u1eec\u00bf\u1ea2\u1eba\u1ec8\u1ece\u1ee6\u1ef6\u262d\u0000AEOaeo\u1ea8\u1ec2\u1ed4\u0000Aa\u1eb2\u2370\u0000\"'(*,-;>AET^_`~\u00a8\u00b4\u0102\u00c6@\u00c0\u00c3\u0000.|\u0e3f\u0000',./<=C" + "\u0423\u0430\u0435\u0438\u043e\u0440\u0443\u1e36\u1e37\u1e5a\u1e5b\u2206\u220a\u2212\u2218\u2260\u2282\u2283\u22a5\u22c4\u2373\u2375\u237a\u25cb\u0000LRlr\u1e38\u1e5c\u1e39\u1e5d\u0000AOUaou\u01de\u022a\u01d5\u01df\u022b\u2358\u0000AEOaeo\u01e0\u0230\u01e1\u0231\u0000Oo\u01ec\u01ed\u1e20\u0232\u1e21\u0233\u0000Oo\u022c\u022d\u01e2" +
"EOr|\u2102\u20a0\u00a9\u20a2\u20b5\u0000,-.<H\u00d0\u0000\"',-.;<=>E^_`\u00a8\u00b4\u018f\u00c8\u0000.Uilr\uFFFF\ud83d\udd95\uFFFF\ufb03\uFFFF\ufb04\u20a3\u0000(,.TU|\u02d8\u011e>\u20b2\u0000,\u0000\"',-.;>J^_" + "\u01e3\u1fb9\u1fd9\u1fe9\u1fb1\u1fd1\u1fe1\uFFFF\u0410\u0304\uFFFF\u0415\u0304\u04e2\uFFFF\u041e\u0304\uFFFF\u0420\u0304\u04ee\uFFFF\u0430\u0304\uFFFF\u0435\u0304\u04e3\uFFFF\u043e\u0304\uFFFF\u0440\u0304\u04ef\u2359\u2377\u235b\u2262\u2286\u2287\u234a\u235a\u2378\u2379\u2376\u235c\u0000\"()+AEINOUWY^_`abeinouwy" +
"`j~\u00a8\u00b4\u0132\u00cc\u0128\u0000'\u00b4\u0000,-\u0000',-/<=LTV\u0000A\u0000P\uFFFF\ud83d\udd96<\u0000.\u0000',<=GNOo~\u014a\u2115\u2116\u00d1\u0000\"',-/;>ACERSXY^_`~\u00a8\u00b4\u0152\u00ae\u00a7" + "\u00af\u00c2\u00ca\u00d4\u00dc\u00e2\u00ea\u00f4\u00fc\u0102\u0103\u0112\u0113\u014c\u014d\u01a0\u01a1\u01af\u01b0\u0391\u0395\u0397\u0399\u039f\u03a5\u03a9\u03b1\u03b5\u03b7\u03b9\u03bf\u03c5\u03c9\u0410\u0415\u0418\u041e\u0420\u0423\u0430\u0435\u0438\u043e\u0440\u0443\u0000Uu\u03b9\u03c5\u01db\u1fd2\u1fe2\u0000\u0391\u0395\u0397\u0399\u039f\u03a5\u03a9\u03b1\u03b5\u03b7\u03b9\u03bf\u03c5\u03c9\u1f0b\u1f1b\u1f2b\u1f3b" +
"\u00a4\u262e\u00d2\u00d5\u0000!.=Pt\u00b6\u20a7\u0000Q\u211a\u0000',<=ORs\u211d\u20a8\u0000!',.;<MOS|\u2120\u1e9e$\u0000,-./;<=HM\u00de\u2122\u0000 !\"'*,-;>AEGIOU^_`ae" + "\u1f4b\u1f5b\u1f6b\u1f03\u1f13\u1f23\u1f33\u1f43\u1f53\u1f63\u0000\u0391\u0395\u0397\u0399\u039f\u03a9\u03b1\u03b5\u03b7\u03b9\u03bf\u03c5\u03c9\u1f0a\u1f1a\u1f2a\u1f3a\u1f4a\u1f6a\u1f02\u1f12\u1f22\u1f32\u1f42\u1f52\u1f62\u0000OUou\u1edc\u1eea\u01f8\u1e80\u1ef2\u0000AEOaeo\u1ea6\u1ec0\u1ed2\u1ea7\u1ec1\u1ed3\u0000EOeo\u1e14\u1e50\u1e15\u1e51\u0000\u0410\u0415" +
"giou~\u00a8\u00b4\u00b8\u0391\u0399\u03a5\u03b1\u03b9\u03c5\u0410\u0415\u0416\u0418\u0423\u0430\u0435\u0436\u0438\u0443\u0000,\u0000Ee\u1e1c\u0000Aa\u1eb6\u0114\u012c\u014e\u016c\u00d9\u0103\u0115\u011f\u012d\u014f\u016d\u0168\u0000Ee\u1fb8\u1fd8\u1fe8\u1fb0\u1fd0\u1fe0\u04d0\u04d6\u04c1\u0419\u040e\u04d1\u04d7\u04c2\u0439\u045e\u0000Lcsz\u0000=" + "\u0418\u041e\u0420\u0423\u0430\u0435\u0438\u043e\u0440\u0443\uFFFF\u0410\u030f\uFFFF\u0415\u030f\uFFFF\u0418\u030f\uFFFF\u041e\u030f\uFFFF\u0420\u030f\uFFFF\u0423\u030f\uFFFF\u0430\u030f\uFFFF\u0435\u030f\uFFFF\u0438\u030f\uFFFF\u043e\u030f\uFFFF\u0440\u030f\uFFFF\u0443\u030f\u0000Aa\u1eb0\u1eb1\u01f9\u1e81\u1ef3\u0000EOeo\u1fba\u1fc8\u1fca\u1fda\u1ff8\u1fea\u1ffa\u1f70\u1f72\u1f74\u1f76\u1f78\u1f7a" +
"^\u0174\u0000O\u0000\"'=^\u00a8\u00b4\u0176\u0000'.<Z\u2124\u0000]\u2337\u0000-?not\u2395\u25cb\uFFFF\\\u006e\u0000/\uFFFF\ud83d\ude4c\uFFFF\\\u0074\u2342\u2349\u0000[\u0000!()+-./0123456789=ACEGHIJOS" + "\u1f7c\uFFFF\u0410\u0300\u0400\u040d\uFFFF\u041e\u0300\uFFFF\u0420\u0300\uFFFF\u0423\u0300\uFFFF\u0430\u0300\u0450\u045d\uFFFF\u043e\u0300\uFFFF\u0440\u0300\uFFFF\u0443\u0300\u0000\"'(*,-;>^_`ae~\u00a8\u00b4\u00e6\u0000!,.AEGIOUaegiou\u00b8\u0391\u0399\u03a5\u03b1\u03b9\u03c5\u0410\u0415" +
"UWYZ_aceghijosuwyz|\u0410\u0415\u0418\u041e\u0420\u0423\u0430\u0435\u0438\u043e\u0440\u0443\u1eb8\u1eb9\u1ecc\u1ecd\u2212\u4e00\u4e01\u4e09\u4e0a\u4e0b\u4e19\u4e2d\u4e59\u4e8c\u4eba\u56db\u5730\u5929\u7532\u0000AEOaeo\u1eac\u1ec6\u1ed8\u0108\u011c\u0124\u0134\u015c\u1e90\u0000ahijl" + "\u0416\u0418\u0423\u0430\u0435\u0436\u0438\u0443\u0000Aa\u0000Ee\u0000Ee\u0000\"',./<=ACDEGHIKLNORSTUZacdeghijklnorstuz|\u00dc\u00fc\u0000Uu\u01d9\u01cd\u01e6\u021e\u01cf\u01e8\u01d1\u01d3" +
"norswxy\u0263\u0266\u0279\u027b\u0281\u0295\u02e4\uFFFF\u0410\u0302\uFFFF\u0415\u0302\uFFFF\u0418\u0302\uFFFF\u041e\u0302\uFFFF\u0420\u0302\uFFFF\u0423\u0302\uFFFF\u0440\u0302\u3192\u319c\u3194\u3196\u3198\u319b\u3197\u319a\u3193\u319f\u3195\u319e\u319d\u3199\u0000 !\"'()+-.0123456789;<=" + "\u01e7\u021f\u01f0\u01e9\u0000,-.<=hi\u00f0\u2300\u0000\"',-.;<=>^_`e\u00a8\u00b4\u0259\u0000.Sfils\u017f\uFFFF\ufb00\uFFFF\ufb01\uFFFF\ufb02\u0000(,.Ut\u02d8\u0000,\u0000\"',-.;>^_`j~\u00a8\u00b4\u0133\u0000'" +
">AEGIOUY^_aegiouy~\u00c4\u00c6\u00d5\u00d6\u00dc\u00e4\u00e6\u00f5\u00f6\u00fc\u0226\u0227\u0391\u0399\u03a5\u03b1\u03b9\u03c5\u0410\u0415\u0418\u041e\u0420\u0423\u0430\u0435\u0438\u043e\u0440\u0443\u1e36\u1e37\u1e5a\u1e5b\u2206\u220a\u2212\u2218\u2260\u2282\u2283\u22a5\u22c4\u2373\u2375\u237a\u25cb\u0000LRlr\u1e38\u1e5c" + "\u00b4\u0000,k\u0138\u0000',-/<tv\u0000./u\u0000',<g~\u014b\u0000\"',-/;>AU^_`aceorsuwxy~\u00a8\u00b4\u0153\u1e98\u1e99\u0000!.=o\u0000o\uFFFF\ud83d\udca9\u0000',<=\u0000!'," +
"\u0000AOUaou\u01de\u022a\u01d5\u2358\u0000AEOaeo\u01e0\u0230\u0000Oo\u01ec\u1e20\u0232\u0000Oo\u022c\u01e2\u1fb9\u1fd9\u1fe9\uFFFF\u0410\u0304\uFFFF\u0415\u0304\u04e2\uFFFF\u041e\u0304\uFFFF\u0420\u0304\u04ee\uFFFF\u0430\u0304\uFFFF\u0435\u0304\uFFFF\u043e\u0304\uFFFF\u0440\u0304\u2359\u2377\u235b\u2262\u2286\u2287\u234a\u235a\u2378\u2379\u2376\u235c" + ".;<mos\u00b8\u00df\u0000,-./;<hm\u00fe\u0000\"'*,-/;>AEGIOU^_`aegiou~\u00a8\u00b4\u0000/ACDEGHIKNORSTUZacdeghijkl" +
"\u0000\"()+AEINOUWY^_`abeinouwy\u00af\u00c2\u00ca\u00d4\u00dc\u00e2\u00ea\u00f4\u00fc\u0102\u0103\u0112\u0113\u014c\u014d\u01a0\u01a1\u01af\u01b0\u0391\u0395\u0397\u0399\u039f\u03a5\u03a9\u03b1\u03b5\u03b7\u03b9\u03bf\u03c5\u03c9\u0410\u0415\u0418\u041e\u0420\u0423\u0430\u0435\u0438\u043e\u0440\u0443\u0000U" + "norstuz|\u0000^\u0000ox\u00d7\u0000\"'=^\u00a8\u00b4\u0000'.<\u0000}\u2205\u0000-=BCGS^cv~\u2190\u2192\u2206\u2207\u222a\u2282\u25cb\u2020\u2021\u236d\u2345\u2346\u234b\u2352\u2366\u2367\u233d\u0000\"()+0AEINOUVY^a" +
"u\u03b9\u03c5\u01db\u1fd2\u0000\u0391\u0395\u0397\u0399\u039f\u03a5\u03a9\u03b1\u03b5\u03b7\u03b9\u03bf\u03c5\u03c9\u1f0b\u1f1b\u1f2b\u1f3b\u1f4b\u1f5b\u1f6b\u1f03\u1f13\u1f23\u1f33\u1f43\u1f53\u1f63\u0000\u0391\u0395\u0397\u0399\u039f\u03a9\u03b1\u03b5\u03b7\u03b9\u03bf\u03c5\u03c9\u1f0a\u1f1a\u1f2a\u1f3a\u1f4a\u1f6a\u1f02\u1f12\u1f22\u1f32\u1f42\u1f52\u1f62\u0000OUou\u1edc\u1eea\u01f8\u1e80\u1ef2\u0000" + "beinouvy|~\u00a8\u00c2\u00ca\u00d4\u00e2\u00ea\u00f4\u0102\u0103\u01a0\u01a1\u01af\u01b0\u03b1\u03b7\u03b9\u03c5\u03c9\u2207\u2227\u2228\u0000\u03b9\u03c5\u1fd7\u1fe7\u0000\u0391\u0397\u0399\u03a5\u03a9\u03b1\u03b7\u03b9\u03c5\u03c9\u1f0f\u1f2f\u1f3f\u1f5f\u1f6f\u1f07\u1f27\u1f37\u1f57\u1f67\u0000\u0391\u0397\u0399\u03a9\u03b1\u03b7\u03b9\u03c5\u03c9\u1f0e\u1f2e\u1f3e\u1f6e\u1f06" +
"AEOaeo\u1ea6\u1ec0\u1ed2\u0000EOeo\u1e14\u1e50\u0000\u0410\u0415\u0418\u041e\u0420\u0423\u0430\u0435\u0438\u043e\u0440\u0443\uFFFF\u0410\u030f\uFFFF\u0415\u030f\uFFFF\u0418\u030f\uFFFF\u041e\u030f\uFFFF\u0420\u030f\uFFFF\u0423\u030f\u0000Aa\u1eb0\u0000EOeo\u1fba\u1fc8\u1fca\u1fda\u1ff8\u1fea\u1ffa\uFFFF\u0410\u0300\u0400\u040d\uFFFF\u041e\u0300\uFFFF" + "\u1f26\u1f36\u1f56\u1f66\u0000OUou\u1ee0\u1eee\u1ebc\u1e7c\u1ef8\u0000AEOaeo\u1eaa\u1ec4\u1ed6\u1ed7\u0000Aa\u1eb4\u1e7d\u1ef9\u2248\u2368\u1fb6\u1fc6\u1fd6\u1fe6\u1ff6\u236b\u2372\u2371\u0000'*>AEIOUY`aeiouy~\u00b4\u2207\u2218\u22a4\u25cb\u1fed\u1fc1\u2362\u2364\u2361\u2365\u0000!" +
"\u0420\u0300\uFFFF\u0423\u0300\uFFFF\u0430\u0300\uFFFF\u043e\u0300\uFFFF\u0440\u0300\uFFFF\u0443\u0300\u0000\"'(*,-;>^_`ae~\u00a8\u00b4\u00e6\u0000!,.AEGIOUaegiou\u00b8\u0391\u0399\u03a5\u03b1\u03b9\u03c5\u0410\u0415\u0416\u0418\u0423\u0430\u0435\u0436\u0438\u0443\u0000Aa\u0000" + "\".;AEGIOUYaegiouy~\u00c4\u00c6\u00d5\u00d6\u00dc\u00e4\u00e6\u00f5\u00f6\u00fc\u0226\u0227\u0391\u0399\u03a5\u03b1\u03b9\u03c5\u0410\u0415\u0418\u041e\u0420\u0423\u0430\u0435\u0438\u043e\u0440\u0443\u1e36\u1e37\u1e5a\u1e5b\u22a4\u0000LRlr\u0000AOUaou\u0000AOao\u0000O" +
"Ee\u0000Ee\u0000\"',./<=ACDEGHIKLNORSTUZacdeghijklnorstuz|\u00dc\u00fc\u0000Uu\u01d9\u01cd\u01e6\u021e\u01cf\u01e8\u01d1\u01d3\u0000,-.<=hi\u00f0\u2300\u0000\"" + "o\u0000Oo\u2351\u0000\"()+,/ACEGIJKLMNOPRSUWYZ^_abcegijklmnoprsuwyz~\u00af\u00b8\u00c2\u00c5\u00c6\u00c7\u00ca\u00cf\u00d4\u00d5\u00d8\u00dc\u00e2\u00e5\u00e6\u00e7\u00ea\u00ef\u00f4\u00f5" +
"',-.;<=>^_`e\u00a8\u00b4\u0259\u0000.Sfils\u017f\uFFFF\ufb00\uFFFF\ufb01\uFFFF\ufb02\u0000(,.Ut\u02d8\u0000,\u0000\"',-.;>^_`j~\u00a8\u00b4\u0133\u0000'\u00b4\u0000,k\u0138\u0000',-/<tv\u0000./" + "\u00f8\u00fc\u0102\u0103\u0112\u0113\u014c\u014d\u0168\u0169\u01a0\u01a1\u01af\u01b0\u0391\u0395\u0397\u0399\u039f\u03a5\u03a9\u03b1\u03b5\u03b7\u03b9\u03bf\u03c5\u03c9\u0410\u0413\u0415\u0418\u041a\u041e\u0420\u0423\u042b\u042d\u042e\u042f\u0430\u0433\u0435\u0438\u043a\u043e\u0440\u0443\u044b\u044d\u044e\u044f\u0000IUiu\u03b9\u03c5\u0000\u0391\u0395\u0397\u0399\u039f\u03a5\u03a9\u03b1\u03b5\u03b7\u03b9\u03bf" +
"u\u0000',<g~\u014b\u0000\"',-/;>AU^_`aceorsuwxy~\u00a8\u00b4\u0153\u0000!.=o\u0000o\uFFFF\ud83d\udca9\u0000',<=\u0000!',.;<mos\u00b8\u00df\u0000,-./;<hm\u00fe" + "\u03c5\u03c9\u0000\u0391\u0395\u0397\u0399\u039f\u03a9\u03b1\u03b5\u03b7\u03b9\u03bf\u03c5\u03c9\u0000OUou\u0000Cc\u0000Oo\u0000AEOaeo\u0000EOeo\u0000Aa\u0000OUou\u0000EOeo\u0000Cc\u0000CDEGHKLNRSTcdegh" +
"\u0000\"'*,-/;>AEGIOU^_`aegiou~\u00a8\u00b4\u0000/ACDEGHIKNORSTUZacdeghijklnorstuz|\u0000^\u0000ox\u00d7\u0000\"'=" + "klnrst\u0228\u0000\u2395\u2339\u0000Gg\u0000'\u0000'\u0000'\u0000\"'\u0000'\u0000\"'\u0000'\u0000'\u0000'\u0000'\u0000\"'()`~\u00b4\u0391\u0397\u03a9\u03b1\u03b7\u03c9\u0000()\u03b1\u03b7\u03c9\u0000\u0391\u0397\u03a9\u03b1\u03b7\u03c9\u1f8d\u1f9d\u1fad\u1f85\u1f95\u1fa5\u0000\u0391\u0397\u03a9" +
"^\u00a8\u00b4\u0000'.<\u0000}\u2205\u0000-=BCGS^cv~\u2190\u2192\u2206\u2207\u222a\u2282\u25cb\u2020\u2021\u236d\u2345\u2346\u234b\u2352\u2366\u2367\u233d\u0000\"()+0AEINOUVY^abeinouvy|~\u00a8\u00c2\u00ca\u00d4\u00e2\u00ea\u00f4\u0102" + "\u03b1\u03b7\u03c9\u1f8c\u1f9c\u1fac\u1f84\u1f94\u1fa4\u1fb4\u1fc4\u1ff4\u0000\u0391\u0397\u03a9\u03b1\u03b7\u03c9\u1f89\u1f99\u1fa9\u1f81\u1f91\u1fa1\u0000\u0391\u0397\u03a9\u03b1\u03b7\u03c9\u1f88\u1f98\u1fa8\u1f80\u1f90\u1fa0\u0000()\u03b1\u03b7\u03c9\u0000\u0391\u0397\u03a9\u03b1\u03b7\u03c9\u1f8b\u1f9b\u1fab\u1f83\u1f93\u1fa3\u0000\u0391\u0397\u03a9\u03b1\u03b7\u03c9\u1f8a\u1f9a\u1faa\u1f82\u1f92\u1fa2\u1fb2\u1fc2" +
"\u0103\u01a0\u01a1\u01af\u01b0\u03b1\u03b7\u03b9\u03c5\u03c9\u2207\u2227\u2228\u0000\u03b9\u03c5\u1fd7\u0000\u0391\u0397\u0399\u03a5\u03a9\u03b1\u03b7\u03b9\u03c5\u03c9\u1f0f\u1f2f\u1f3f\u1f5f\u1f6f\u1f07\u1f27\u1f37\u1f57\u1f67\u0000\u0391\u0397\u0399\u03a9\u03b1\u03b7\u03b9\u03c5\u03c9\u1f0e\u1f2e\u1f3e\u1f6e\u1f06\u1f26\u1f36\u1f56\u1f66\u0000OUou\u1ee0\u1eee\u1ebc\u1e7c\u1ef8\u0000AEOa" + "\u1ff2\u0000()\u03b1\u03b7\u03c9\u0000\u0391\u0397\u03a9\u03b1\u03b7\u03c9\u1f8f\u1f9f\u1faf\u1f87\u1f97\u1fa7\u0000\u0391\u0397\u03a9\u03b1\u03b7\u03c9\u1f8e\u1f9e\u1fae\u1f86\u1f96\u1fa6\u1fb7\u1fc7\u1ff7\u0000()\u03b1\u03b7\u03c9\u0000\u0391\u0397\u03a9\u03b1\u03b7\u03c9\u0000\u0391\u0397\u03a9\u03b1\u03b7\u03c9\u1fbc\u1fcc\u1ffc\u1fb3\u1fc3\u1ff3\u0000'\u0000\"'\u0000'\u0000=\u0000" +
"eo\u1eaa\u1ec4\u1ed6\u0000Aa\u1eb4\u2248\u1fb6\u1fc6\u1fd6\u1fe6\u1ff6\u236b\u2372\u2371\u0000'*>AEIOUY`aeiouy~\u00b4\u2207\u2218\u22a4\u25cb\u1fed\u1fc1\u2361\u2365\u0000!\".;AEGIOUYaegiouy~\u00c4\u00c6\u00d5\u00d6\u00dc\u00e4\u00e6" + "=\u0000\u041e\u043e\u0000=\u0000=\u0000\u0430\u0000\u05d9\uFFFF\ufb1d\u0000\u05d0\u05f2\uFFFF\ufb2e\uFFFF\ufb1f\u0000\u05d0\uFFFF\ufb2f\u0000\u05d5\uFFFF\ufb4b\u0000\u05d0\u05d1\u05d2\u05d3\u05d4\u05d5\u05d6\u05d8\u05d9\u05da\u05db\u05dc\u05de\u05e0\u05e1\u05e3\u05e4\u05e6\u05e7\u05e8\u05e9\u05ea\uFFFF\ufb30\uFFFF\ufb31\uFFFF\ufb32\uFFFF\ufb33\uFFFF\ufb34\uFFFF\ufb35\uFFFF\ufb36\uFFFF\ufb38\uFFFF\ufb39\uFFFF\ufb3a" +
"\u00f5\u00f6\u00fc\u0226\u0227\u0391\u0399\u03a5\u03b1\u03b9\u03c5\u0410\u0415\u0418\u041e\u0420\u0423\u0430\u0435\u0438\u043e\u0440\u0443\u1e36\u1e37\u1e5a\u1e5b\u22a4\u0000LRlr\u0000AOUaou\u0000AOao\u0000Oo\u0000Oo\u2351\u0000\"()+,/ACEGIJKLMNOPR" + "\uFFFF\ufb3b\uFFFF\ufb3c\uFFFF\ufb3e\uFFFF\ufb40\uFFFF\ufb41\uFFFF\ufb43\uFFFF\ufb44\uFFFF\ufb46\uFFFF\ufb47\uFFFF\ufb48\uFFFF\ufb49\uFFFF\ufb4a\u0000\u05d1\u05db\u05e4\uFFFF\ufb4c\uFFFF\ufb4d\uFFFF\ufb4e\u0000\u05bc\u05e9\ufb49\u0000\u05e9\uFFFF\ufb2c\uFFFF\ufb2a\u0000\u05bc\u05e9\ufb49\u0000\u05e9\uFFFF\ufb2d\uFFFF\ufb2b\u0000\u0627\u0622\u0000\u0627\u0648\u064a\u06c1\u06d2\u06d5\u0623\u0624\u0626\u06c2\u06d3\u06c0\u0000\u0627" +
"SUWYZ^_abcegijklmnoprsuwyz~\u00af\u00b8\u00c2\u00c5\u00c6\u00c7\u00ca\u00cf\u00d4\u00d5\u00d8\u00dc\u00e2\u00e5\u00e6\u00e7\u00ea\u00ef\u00f4\u00f5\u00f8\u00fc\u0102\u0103\u0112\u0113\u014c\u014d\u0168\u0169\u01a0\u01a1\u01af\u01b0\u0391\u0395\u0397\u0399\u039f\u03a5\u03a9\u03b1\u03b5\u03b7\u03b9" + "\u0625\u0000\u0915\u0916\u0917\u091c\u0921\u0922\u0928\u092b\u092f\u0930\u0933\u0958\u0959\u095a\u095b\u095c\u095d\u0929\u095e\u095f\u0931\u0934\u0000\u09a1\u09a2\u09af\u09dc\u09dd\u09df\u0000\u09be\u09d7\u09cb\u09cc\u0000\u0a16\u0a17\u0a1c\u0a2b\u0a32\u0a38\u0a59\u0a5a\u0a5b\u0a5e\u0a33\u0a36\u0000\u0b21\u0b22\u0b5c\u0b5d\u0000\u0b3e\u0b56\u0b57\u0b4b\u0b48\u0b4c\u0000\u0bbe\u0bd7\u0bca\u0bcc\u0000\u0bbe\u0bcb\u0000\u0b92\u0b94" +
"\u03bf\u03c5\u03c9\u0410\u0413\u0415\u0418\u041a\u041e\u0420\u0423\u042b\u042d\u042e\u042f\u0430\u0433\u0435\u0438\u043a\u043e\u0440\u0443\u044b\u044d\u044e\u044f\u0000IUiu\u03b9\u03c5\u0000\u0391\u0395\u0397\u0399\u039f\u03a5\u03a9\u03b1\u03b5\u03b7\u03b9\u03bf\u03c5\u03c9\u0000\u0391\u0395\u0397\u0399\u039f\u03a9\u03b1\u03b5\u03b7\u03b9\u03bf\u03c5\u03c9\u0000OUou\u0000Cc\u0000" + "\u0000\u0c56\u0c48\u0000\u0cd5\u0cc0\u0000\u0cc2\u0cd5\u0cd6\u0cca\u0cc7\u0cc8\u0000\u0cd5\u0ccb\u0000\u0d3e\u0d57\u0d4a\u0d4c\u0000\u0d3e\u0d4b\u0000\u0dca\u0dcf\u0ddf\u0dda\u0ddc\u0dde\u0000\u0dca\u0ddd\u0000\u0f72\u0f74\u0f80\u0f73\u0f75\u0f81\u0000\u0fb5\u0fb9\u0000\u0fb7\u0f93\u0000\u0fb7\u0f9d\u0000\u0fb7\u0fa2\u0000\u0fb7\u0fa7\u0000\u0fb7\u0fac\u0000\u0f80\u0f76\u0000\u0f80\u0f78\u0000\u0f40\u0f69\u0000\u0f42\u0f4c\u0f51" +
"Oo\u0000AEOaeo\u0000EOeo\u0000Aa\u0000OUou\u0000EOeo\u0000Cc\u0000CDEGHKLNRSTcdeghklnrst\u0228\u0000\u2395\u2339\u0000Gg\u0000'\u0000'\u0000'\u0000\"'\u0000'\u0000" + "\u0f56\u0f5b\u0f43\u0f4d\u0f52\u0f57\u0f5c\u0000\u1025\u1026\u0000\u1100\u1101\u0000\u1100\u1102\u1103\u1107\u1113\u1114\u1115\u1116\u0000\u1100\u1103\u1117\u1104\u0000\u1102\u1105\u110b\u1112\u1118\u1119\u111b\u111a\u0000\u1107\u110b\u111c\u111d\u0000\u1100\u1102\u1103\u1107\u1109\u110a\u110b\u110c\u110e\u1110\u1111\u112b\u112d\u112f\u1132\u1136\u111e\u111f\u1120\u1108\u1121\u1125\u112b\u1127\u1128\u1129\u112a\u112c\u1122\u1123" +
"\"'\u0000'\u0000'\u0000'\u0000'\u0000\"'()`~\u00b4\u0391\u0397\u03a9\u03b1\u03b7\u03c9\u0000()\u03b1\u03b7\u03c9\u0000\u0391\u0397\u03a9\u03b1\u03b7\u03c9\u1f8d\u1f9d\u1fad\u1f85\u1f95\u1fa5\u0000\u0391\u0397\u03a9\u03b1\u03b7\u03c9\u1f8c\u1f9c\u1fac\u1f84\u1f94\u1fa4\u1fb4\u1fc4\u1ff4\u0000\u0391\u0397\u03a9\u03b1\u03b7\u03c9\u1f89\u1f99\u1fa9\u1f81\u1f91\u1fa1" + "\u1124\u1126\u0000\u110b\u0000\u1100\u1102\u1103\u1105\u1106\u1107\u1109\u110a\u110b\u110c\u110e\u110f\u1110\u1111\u1112\u111e\u112d\u112e\u112f\u1130\u1131\u1132\u110a\u1134\u1135\u1136\u1137\u1138\u1139\u113a\u113b\u1133\u0000\u1109\u0000\u1100\u1103\u1106\u1107\u1109\u110b\u110c\u110e\u1110\u1111\u1140\u1141\u1142\u1143\u1144\u1145\u1147\u1148\u1149\u114a\u114b\u1146\u0000\u110b\u110c\u114d\u110d\u0000\u110f\u1112\u1152\u1153" +
"\u0000\u0391\u0397\u03a9\u03b1\u03b7\u03c9\u1f88\u1f98\u1fa8\u1f80\u1f90\u1fa0\u0000()\u03b1\u03b7\u03c9\u0000\u0391\u0397\u03a9\u03b1\u03b7\u03c9\u1f8b\u1f9b\u1fab\u1f83\u1f93\u1fa3\u0000\u0391\u0397\u03a9\u03b1\u03b7\u03c9\u1f8a\u1f9a\u1faa\u1f82\u1f92\u1fa2\u1fb2\u1fc2\u1ff2\u0000()\u03b1\u03b7\u03c9\u0000\u0391\u0397\u03a9\u03b1\u03b7\u03c9\u1f8f\u1f9f\u1faf\u1f87\u1f97\u1fa7\u0000\u0391\u0397\u03a9\u03b1" + "\u0000\u1107\u110b\u1156\u1157\u0000\u1112\u1158\u0000\u1100\u1103\u1107\u1109\u110c\u0000\u1100\u0000\u113c\u113d\u0000\u113e\u113f\u0000\u114e\u114f\u0000\u1150\u1151\u0000\u1169\u116e\u1175\u1176\u1177\u1162\u0000\u1169\u116d\u1175\u1178\u1179\u1164\u0000\u1169\u116e\u1173\u1175\u117a\u117b\u117c\u1166\u0000\u1169\u116e\u1175\u117d\u117e\u1168\u0000\u1161\u1162\u1165\u1166\u1168\u1169\u116e\u1175\u116a\u116b\u117f\u1180\u1181" +
"\u03b7\u03c9\u1f8e\u1f9e\u1fae\u1f86\u1f96\u1fa6\u1fb7\u1fc7\u1ff7\u0000()\u03b1\u03b7\u03c9\u0000\u0391\u0397\u03a9\u03b1\u03b7\u03c9\u0000\u0391\u0397\u03a9\u03b1\u03b7\u03c9\u1fbc\u1fcc\u1ffc\u1fb3\u1fc3\u1ff3\u0000'\u0000\"'\u0000'\u0000=\u0000=\u0000\u041e\u043e\u0000=\u0000\u0435\u0443\u0447\u044b\u044c\ua64b\ua651\u0463\u0461\uFFFF\u0063\u006f\u006d\u0062\u0069\u006e\u0069\u006e" + "\u1182\u1183\u116c\u0000\u1175\u0000\u1163\u1164\u1167\u1169\u1175\u1184\u1185\u1186\u1187\u1188\u0000\u1161\u1162\u1165\u1166\u1168\u116e\u1175\u117c\u1189\u118a\u116f\u1170\u118c\u118d\u1171\u118b\u0000\u1173\u1175\u0000\u1161\u1165\u1166\u1167\u1168\u116e\u1175\u118e\u118f\u1190\u1191\u1192\u1193\u1194\u0000\u116e\u1173\u1175\u1195\u1196\u1174\u0000\u116e\u1197\u0000\u1161\u1163\u1169\u116e\u1173\u119e\u1198\u1199\u119a\u119b" +
"\u0067\u005f\u0061\u0069\u0067\u0075\uFFFF\ua659\uFFFF\ua64d\u0000\u0447\uFFFF\u0063\u006f\u006d\u0062\u0069\u006e\u0069\u006e\u0067\u005f\u0073\u006c\u0061\u0076\u006f\u006e\u0069\u0063\u005f\u0070\u0073\u0069\u006c\u0069\u0000,.\u0439\u043a\u0445\u0458\u0491\u0481\u0000\u0435\u0436\u0437\u0439\u0458\u0465\uFFFF\ua649\u045f\uFFFF\ua643\u0452\u0000\u0447\uFFFF\u0063\u006f\u006d\u0062\u0069\u006e\u0069\u006e\u0067\u005f" + "\u119c\u119d\u0000\u1165\u116e\u1175\u119e\u119f\u11a0\u11a1\u11a2\u0000\u11a8\u11af\u11ba\u11e7\u11a9\u11c3\u11aa\u11c4\u0000\u11a8\u0000\u11a8\u11ae\u11ba\u11bd\u11c0\u11c2\u11eb\u11c5\u11c6\u11c7\u11ac\u11c9\u11ad\u11c8\u0000\u11a8\u11af\u11ca\u11cb\u0000\u11a8\u11aa\u11ab\u11ae\u11af\u11b7\u11b8\u11b9\u11ba\u11bb\u11bf\u11c0\u11c1\u11c2\u11da\u11dd\u11e5\u11e6\u11eb\u11f9\u11b0\u11cc\u11cd\u11ce\u11d0\u11b1\u11b2\u11d3\u11b3" +
"\u0074\u0072\u0065\u006d\u0061\u0000.\u0000=\u0444\u0499\u0000\u0438\u0443\u0475\u0000.\u0447\uFFFF\u0063\u006f\u006d\u0062\u0069\u006e\u0069\u006e\u0067\u005f\u0062\u0072\u0065\u0076\u0065\u0000,.\u0433\u0441\u0445\u0448\u046f\u0000,.\u044c\u0459\u0000.\u0000,\u00b7\u0447\u044c\u0529\uFFFF\u0063\u006f\u006d\u0062\u0069\u006e\u0069\u006e\u0067\u005f\u0074\u0069\u0074\u006c\u006f\u045a" + "\u11d6\u11d8\u11b4\u11b5\u11b6\u11d1\u11d2\u11d4\u11d5\u11d7\u11d9\u0000\u11ba\u0000\u11a8\u11ba\u0000\u11ba\u11bc\u11c2\u0000\u11ba\u0000\u11a8\u11af\u11b8\u11ba\u11bb\u11bc\u11be\u11c2\u11eb\u11da\u11db\u11dc\u11dd\u11de\u11e2\u11e0\u11e1\u11df\u0000\u11af\u11ba\u11bc\u11c1\u11c2\u11e3\u11b9\u11e6\u11e4\u11e5\u0000\u11a8\u11ae\u11af\u11b8\u11ba\u11e7\u11e8\u11e9\u11ea\u11bb\u0000\u11a8\u11a9\u11bc\u11bf\u11ec\u11ed\u11ee\u11ef" +
"\u0000\u0442\u0443\u0447\u047f\u0479\uFFFF\u0063\u006f\u006d\u0062\u0069\u006e\u0069\u006e\u0067\u005f\u0069\u006e\u0076\u0065\u0072\u0074\u0065\u0064\u005f\u0062\u0072\u0065\u0076\u0065\u0000\u0430\u0441\u0471\u0000\u0439\u0444\u0458\u045b\u0473\u0000\u0438\u0439\u0443\u0447\u0456\u0458\uFFFF\u0063\u006f\u006d\u0062\u0069\u006e\u0069\u006e\u0067\u005f\u0070\u006f\u006b\u0072\u0079\u0074\u0069\u0065\u0000,.\u0447\uFFFF" + "\u0000\u11b8\u11bc\u11f3\u11f4\u0000\u11ab\u11af\u11b7\u11b8\u11f5\u11f6\u11f7\u11f8\u0000\u11c2\u11cf\u0000\u11ba\u0000\u11a8\u0000\u11ba\u11eb\u11f1\u11f2\u0000|\u2395\u2347\u0000-\u2395\u2350\u0000|\u2395\u2348\u0000-\u2395\u2357\u0000/\u2204\u0000_|\u2395\u234d\u0000|~\u00a8\u2395\u2354\u0000/\u2209\u0000_\u0000/\u220c\u0000_\u00a8\u2229\u22a4\u22a5\u2395\u25cb" +
"\u0063\u006f\u006d\u0062\u0069\u006e\u0069\u006e\u0067\u005f\u0073\u006c\u0061\u0076\u006f\u006e\u0069\u0063\u005f\u0064\u0061\u0073\u0069\u0061\u0000.\u0430\u0431\u0435\u0439\u043d\u043e\u0443\u0445\u0447\u044a\u044e\u0458\u0467\uFFFF\u0063\u006f\u006d\u0062\u0069\u006e\u0069\u006e\u0067\u005f\u0070\u0061\u0079\u0065\u0072\u006f\u006b\uFFFF\u0063\u006f\u006d\u0062\u0069\u006e\u0069\u006e\u0067\u005f\u0076\u0065\u0072\u0074" + "\u235d\u2355\u234e\u233b\u233e\u0000/\u2224\u0000/\u2226\u0000~\u2228\u2395\u2353\u0000~\u2227\u2395\u234c\u0000\u2218\u0000|\u0000/\u2247\u0000/\u2244\u0000/\u2249\u0000/\u226d\u0000_\u2395\u236f\u0000/\u0000/\u2270\u0000/\u2271\u0000/\u2274\u0000/\u2275\u0000/\u2278\u0000/\u2279\u0000/\u2280\u0000/\u2281\u0000/\u22e0\u0000/" +
"\u0069\u0063\u0061\u006c\u005f\u0074\u0069\u006c\u0064\u0065\uFFFF\u0063\u006f\u006d\u0062\u0069\u006e\u0069\u006e\u0067\u005f\u0067\u0072\u0061\u0076\u0065\uFFFF\u0063\u006f\u006d\u0062\u0069\u006e\u0069\u006e\u0067\u005f\u0076\u007a\u006d\u0065\u0074\u0000\u0442\u0449\u0000\u0447\u0000\u0430\u0435\u043c\u043d\u0447\uFFFF\ua653\u046d\u0469\u0000\u044c\uFFFF\ua65d\u0000\".\u0443\u0456\u0000\u0430\u0447\u0463\uFFFF\ua657" + "\u22e1\u0000/_|\u2284\u0000/_\u2285\u0000/\u2288\u0000/\u2289\u0000/\u22e2\u0000/\u22e3\u0000/\u22ac\u0000\u00a8\u00af\u2218\u22a5\u2336\u0000_\u2218\u22a4\u0000/\u22ad\u0000/\u22ae\u0000/\u22af\u0000/\u22ea\u0000/\u22eb\u0000/\u22ec\u0000/\u22ed\u0000_\u2395\u233a\u0000_\u0000_\u0000_\u0000'/:<=" +
"\u0000\u0442\u0000\u0447\u0000\u05d9\uFFFF\ufb1d\u0000\u05d0\u05f2\uFFFF\ufb2e\uFFFF\ufb1f\u0000\u05d0\uFFFF\ufb2f\u0000\u05d5\uFFFF\ufb4b\u0000\u05d0\u05d1\u05d2\u05d3\u05d4\u05d5\u05d6\u05d8\u05d9\u05da\u05db\u05dc\u05de\u05e0\u05e1\u05e3\u05e4\u05e6\u05e7\u05e8\u05e9\u05ea\uFFFF\ufb30\uFFFF\ufb31\uFFFF\ufb32\uFFFF\ufb33\uFFFF\ufb34\uFFFF\ufb35\uFFFF\ufb36\uFFFF\ufb38\uFFFF\ufb39\uFFFF\ufb3a\uFFFF\ufb3b\uFFFF\ufb3c\uFFFF\ufb3e" + ">?\\\u00f7\u2190\u2191\u2192\u2193\u2206\u2207\u2218\u2227\u2228\u2260\u22c4\u25cb\u233c\u0000*-.\\_|\u00a8\u2218\u2395\u0000/\u2adc\u0000 !\"%'()*,-.0123456789<=>?[]^_abcehlopruyz" +
"\uFFFF\ufb40\uFFFF\ufb41\uFFFF\ufb43\uFFFF\ufb44\uFFFF\ufb46\uFFFF\ufb47\uFFFF\ufb48\uFFFF\ufb49\uFFFF\ufb4a\u0000\u05d1\u05db\u05e4\uFFFF\ufb4c\uFFFF\ufb4d\uFFFF\ufb4e\u0000\u05bc\u05e9\ufb49\u0000\u05e9\uFFFF\ufb2c\uFFFF\ufb2a\u0000\u05bc\u05e9\ufb49\u0000\u05e9\uFFFF\ufb2d\uFFFF\ufb2b\u0000\u0627\u0639\u0648\u064a\u0667\u06cc\u06f7\uFFFF\u0063\u006f\u006d\u0062\u0069\u006e\u0069\u006e\u0067\u005f\u0061\u006c\u0065\u0066\u005f" + "{|}\u00a3\u00a7\u00b1\u00d7\u0398\u03a0\u03a3\u03b2\u03b3\u03b5\u03b8\u03ba\u03c0\u03c1\u03c3\u03c5\u03c6\u05d1\u05d3\u05d5\u05d6\u05d7\u05dd\u05e1\u05e3\u05e4\u05e6\u05e7\u05e8\u05e9\u0660\u0661\u0662\u0663\u0664\u0665\u0666\u0667\u0668\u0669\u06f0\u06f1\u06f2\u06f3\u06f4\u06f5\u06f6\u06f7\u06f8\u06f9\u0901\u0902\u0905\u0906\u0907\u0908\u0909\u090a\u090b\u090c\u090f\u0910\u0913\u0914\u0915\u0916\u0917\u0918\u091a" +
"\u0061\u0062\u006f\u0076\u0065\u0623\u06c9\u063d\uFFFF\u0063\u006f\u006d\u0062\u0069\u006e\u0069\u006e\u0067\u005f\u0061\u006c\u0065\u0066\u005f\u0062\u0065\u006c\u006f\u0077\u0000\u062f\u0631\u0634\u0646\u0637\u0691\u062b\u0679\u0000\u0634\u0686\u0000\u062d\uFFFF\u0063\u006f\u006d\u0062\u0069\u006e\u0069\u006e\u0067\u005f\u0073\u0075\u006b\u0075\u006e\u0000\u062a\u0632\u06f7\u0630\u0695\u0000\u0634\u0635\u0000\u062a\u0000\u0627" + "\u091b\u091c\u091d\u091f\u0921\u0922\u0923\u0925\u0926\u0928\u092a\u092b\u092c\u092f\u0930\u0933\u0935\u0936\u0937\u093c\u093d\u093e\u093f\u0940\u0941\u0943\u0947\u0948\u094b\u094c\u0953\u0956\u0962\u0964\u0970\u2020\u20ac\u20b9\u2190\u2191\u2192\u2193\u2194\u2195\u2196\u2197\u2198\u2199\u2203\u2208\u2227\u2228\u2229\u222a\u222b\u2282\u2283\u22b7\uFFFF\u006e\u0062\u0073\u0070\uFFFF\u0066\u0031\u0030\uFFFF\u0066\u0031\uFFFF\u0066" +
"\u0647\u0648\u064a\u0667\u0668\u06cc\u06f7\u06f8\u0625\u06c0\u0624\u0626\uFFFF\u0063\u006f\u006d\u0062\u0069\u006e\u0069\u006e\u0067\u005f\u0068\u0061\u006d\u007a\u0061\u005f\u0062\u0065\u006c\u006f\u0077\uFFFF\u0063\u006f\u006d\u0062\u0069\u006e\u0069\u006e\u0067\u005f\u0068\u0061\u006d\u007a\u0061\u005f\u0061\u0062\u006f\u0076\u0065\u0000\u0643\u06a9\u06af\u0000\u0648\u06a1\u0000\u0648\u06ca\u0000\u0644\u0667\u06f7\uFFFF\u0063" + "\u0032\uFFFF\u0066\u0033\uFFFF\u0066\u0034\uFFFF\u0066\u0035\uFFFF\u0066\u0036\uFFFF\u0066\u0037\uFFFF\u0066\u0038\uFFFF\u0066\u0039\u20b1\u20b4\u20bf\uFFFF\u0072\u0065\u006d\u006f\u0076\u0065\u0064\u2213\u2219\u03f4\u220f\u2211\u03d0\u0263\u03f5\u03d1\u03f0\u03d6\u03f1\u03c2\u03d2\u03d5\uFFFF\u0068\u0061\u0074\u0061\u0066\u005f\u0073\u0065\u0067\u006f\u006c\uFFFF\u0064\u0061\u0067\u0065\u0073\u0068\uFFFF\u0068\u006f\u006c\u0061" +
"\u006f\u006d\u0062\u0069\u006e\u0069\u006e\u0067\u005f\u0073\u0068\u0061\u0064\u0064\u0061\u0068\u06b5\u0000\u062a\u0647\u0648\u064a\u06cc\uFFFF\u0063\u006f\u006d\u0062\u0069\u006e\u0069\u006e\u0067\u005f\u0066\u0061\u0074\u0068\u0061\u0074\u0061\u006e\uFFFF\u0063\u006f\u006d\u0062\u0069\u006e\u0069\u006e\u0067\u005f\u0064\u0061\u006d\u006d\u0061\u0074\u0061\u006e\uFFFF\u0063\u006f\u006d\u0062\u0069\u006e\u0069\u006e\u0067\u005f" + "\u006d\uFFFF\u0071\u0075\u0062\u0075\u0074\u0073\uFFFF\u0068\u0069\u0072\u0069\u0071\uFFFF\u0072\u0061\u0066\u0065\uFFFF\u0073\u0065\u0067\u006f\u006c\uFFFF\u0068\u0061\u0074\u0061\u0066\u005f\u0070\u0061\u0074\u0061\u0068\uFFFF\u0070\u0061\u0074\u0061\u0068\uFFFF\u0074\u0073\u0065\u0072\u0065\uFFFF\u0071\u0061\u006d\u0061\u0074\u0073\uFFFF\u0068\u0061\u0074\u0061\u0066\u005f\u0071\u0061\u006d\u0061\u0074\u0073\uFFFF\u0073\u0068" +
"\u006b\u0061\u0073\u0072\u0061\u0074\u0061\u006e\u0000 \u062a\u0639\u0646\u0647\u0648\u064a\u06cc\u06d5\u0629\uFFFF\u0063\u006f\u006d\u0062\u0069\u006e\u0069\u006e\u0067\u005f\u0066\u0061\u0074\u0068\u0061\u06c6\u06ce\u0000\u062b\u0639\u0641\u0646\u0648\u0667\u0668\u06f7\u06f8\u06cb\uFFFF\u0063\u006f\u006d\u0062\u0069\u006e\u0069\u006e\u0067\u005f\u0064\u0061\u006d\u006d\u0061\u0068\u0000 \u0627\u0639\u0646\u064a\u0667" + "\u0065\u0076\u0061\u0900\u0955\u0972\u0911\u0973\u0974\u0976\u0977\u0960\u0961\u090d\u090e\u0912\u0975\u097b\u097c\uFFFF\u0936\u094d\u091a\u0979\u0978\u097e\uFFFF\u0924\u094d\u0930\uFFFF\u0926\u094d\u0930\uFFFF\u092a\u094d\u0930\u097f\u097a\uFFFF\u0936\u094d\u0930\uFFFF\u0915\u094d\u0937\u094e\u097d\u0949\u093a\u093b\u0904\u0944\u0945\u0946\u094a\u094f\u0954\u0957\u0963\u0965\u0971\u21d4\u21d5\u21d6\u21d7\u21d8\u21d9\u22c0\u22c1" +
"\u0668\u06f7\u06f8\u06d2\u0649\uFFFF\u0063\u006f\u006d\u0062\u0069\u006e\u0069\u006e\u0067\u005f\u006b\u0061\u0073\u0072\u0061\u0000\u0627\u0622\u0000\u0627\u0648\u064a\u06c1\u06d2\u06d5\u06c2\u06d3\u0000\u0627\u0000\u0627\u0631\u0639\u0644\u0648\u064a\u0667\u06cc\uFFFF\u0063\u006f\u006d\u0062\u0069\u006e\u0069\u006e\u0067\u005f\u0061\u0072\u0061\u0062\u0069\u0063\u005f\u0076\u0000\u0639\u0648\u064a\u0668\u06cc\uFFFF\u0063\u006f" + "\u22c2\u22c3\u222e\u22b6\u0000\u00df\u0131\u0a85\u0a87\u0a89\u0a8f\u0a93\u0a95\u0a97\u0a9a\u0a9c\u0a9f\u0aa1\u0aa4\u0aa6\u0aa8\u0aaa\u0aac\u0aae\u0ab2\u0ab8\u0ab9\u0abf\u0ac1\u0ac7\u0acb\u20b9\u2190\u2191\u2192\u2193\u2196\u2197\u2198\u2199\u2500\u2502\u250c\u2510\u2514\u2518\u251c\u2524\u252c\u2534\u253c\u0a86\u0a88\u0a8a\u0a90\u0a94\u0a96\u0a98\u0a9b\u0a9d\u0aa0\u0aa2\u0aa5\u0aa7\u0aa3\u0aab\u0aad\u0a82\u0ab3\u0ab6\u0a83\u0ac0" +
"\u006d\u0062\u0069\u006e\u0069\u006e\u0067\u005f\u0061\u0072\u0061\u0062\u0069\u0063\u005f\u0069\u006e\u0076\u0065\u0072\u0074\u0065\u0064\u005f\u0076\u0000 \u0627\u0639\u0646\u0667\u0668\u06cc\u06f7\u06f8\u0000\u0627\u0631\u0639\u0644\u0648\u064a\u06cc\u06f7\u0000\u0639\u0648\u064a\u06cc\u06f8\u0000\u0915\u0916\u0917\u091c\u0921\u0922\u0928\u092b\u092f\u0930\u0933\u0958\u0959\u095a\u095b\u095c\u095d\u0929\u095e\u095f\u0931" + "\u0ac2\u0ac8\u0acc\u2550\u2551\u2554\u2557\u255a\u255d\u2560\u2563\u2566\u2569\u256c").toCharArray();
"\u0934\u0000\u09a1\u09a2\u09af\u09dc\u09dd\u09df\u0000\u09be\u09d7\u09cb\u09cc\u0000\u0a16\u0a17\u0a1c\u0a2b\u0a32\u0a38\u0a59\u0a5a\u0a5b\u0a5e\u0a33\u0a36\u0000\u0b21\u0b22\u0b5c\u0b5d\u0000\u0b3e\u0b56\u0b57\u0b4b\u0b48\u0b4c\u0000\u0bbe\u0bd7\u0bca\u0bcc\u0000\u0bbe\u0bcb\u0000\u0b92\u0b94\u0000\u0c56\u0c48\u0000\u0cd5\u0cc0\u0000\u0cc2\u0cd5\u0cd6\u0cca\u0cc7\u0cc8\u0000\u0cd5\u0ccb\u0000\u0d3e\u0d57\u0d4a\u0d4c\u0000\u0d3e" +
"\u0d4b\u0000\u0dca\u0dcf\u0ddf\u0dda\u0ddc\u0dde\u0000\u0dca\u0ddd\u0000\u0f72\u0f74\u0f80\u0f73\u0f75\u0f81\u0000\u0fb5\u0fb9\u0000\u0fb7\u0f93\u0000\u0fb7\u0f9d\u0000\u0fb7\u0fa2\u0000\u0fb7\u0fa7\u0000\u0fb7\u0fac\u0000\u0f80\u0f76\u0000\u0f80\u0f78\u0000\u0f40\u0f69\u0000\u0f42\u0f4c\u0f51\u0f56\u0f5b\u0f43\u0f4d\u0f52\u0f57\u0f5c\u0000\u1025\u1026\u0000\u1100\u1101\u0000\u1100\u1102\u1103\u1107\u1113\u1114\u1115\u1116\u0000" +
"\u1100\u1103\u1117\u1104\u0000\u1102\u1105\u110b\u1112\u1118\u1119\u111b\u111a\u0000\u1107\u110b\u111c\u111d\u0000\u1100\u1102\u1103\u1107\u1109\u110a\u110b\u110c\u110e\u1110\u1111\u112b\u112d\u112f\u1132\u1136\u111e\u111f\u1120\u1108\u1121\u1125\u112b\u1127\u1128\u1129\u112a\u112c\u1122\u1123\u1124\u1126\u0000\u110b\u0000\u1100\u1102\u1103\u1105\u1106\u1107\u1109\u110a\u110b\u110c\u110e\u110f\u1110\u1111\u1112\u111e\u112d\u112e" +
"\u112f\u1130\u1131\u1132\u110a\u1134\u1135\u1136\u1137\u1138\u1139\u113a\u113b\u1133\u0000\u1109\u0000\u1100\u1103\u1106\u1107\u1109\u110b\u110c\u110e\u1110\u1111\u1140\u1141\u1142\u1143\u1144\u1145\u1147\u1148\u1149\u114a\u114b\u1146\u0000\u110b\u110c\u114d\u110d\u0000\u110f\u1112\u1152\u1153\u0000\u1107\u110b\u1156\u1157\u0000\u1112\u1158\u0000\u1100\u1103\u1107\u1109\u110c\u0000\u1100\u0000\u113c\u113d\u0000\u113e\u113f\u0000" +
"\u114e\u114f\u0000\u1150\u1151\u0000\u1169\u116e\u1175\u1176\u1177\u1162\u0000\u1169\u116d\u1175\u1178\u1179\u1164\u0000\u1169\u116e\u1173\u1175\u117a\u117b\u117c\u1166\u0000\u1169\u116e\u1175\u117d\u117e\u1168\u0000\u1161\u1162\u1165\u1166\u1168\u1169\u116e\u1175\u116a\u116b\u117f\u1180\u1181\u1182\u1183\u116c\u0000\u1175\u0000\u1163\u1164\u1167\u1169\u1175\u1184\u1185\u1186\u1187\u1188\u0000\u1161\u1162\u1165\u1166\u1168\u116e" +
"\u1175\u117c\u1189\u118a\u116f\u1170\u118c\u118d\u1171\u118b\u0000\u1173\u1175\u0000\u1161\u1165\u1166\u1167\u1168\u116e\u1175\u118e\u118f\u1190\u1191\u1192\u1193\u1194\u0000\u116e\u1173\u1175\u1195\u1196\u1174\u0000\u116e\u1197\u0000\u1161\u1163\u1169\u116e\u1173\u119e\u1198\u1199\u119a\u119b\u119c\u119d\u0000\u1165\u116e\u1175\u119e\u119f\u11a0\u11a1\u11a2\u0000\u11a8\u11af\u11ba\u11e7\u11a9\u11c3\u11aa\u11c4\u0000\u11a8\u0000" +
"\u11a8\u11ae\u11ba\u11bd\u11c0\u11c2\u11eb\u11c5\u11c6\u11c7\u11ac\u11c9\u11ad\u11c8\u0000\u11a8\u11af\u11ca\u11cb\u0000\u11a8\u11aa\u11ab\u11ae\u11af\u11b7\u11b8\u11b9\u11ba\u11bb\u11bf\u11c0\u11c1\u11c2\u11da\u11dd\u11e5\u11e6\u11eb\u11f9\u11b0\u11cc\u11cd\u11ce\u11d0\u11b1\u11b2\u11d3\u11b3\u11d6\u11d8\u11b4\u11b5\u11b6\u11d1\u11d2\u11d4\u11d5\u11d7\u11d9\u0000\u11ba\u0000\u11a8\u11ba\u0000\u11ba\u11bc\u11c2\u0000\u11ba\u0000" +
"\u11a8\u11af\u11b8\u11ba\u11bb\u11bc\u11be\u11c2\u11eb\u11da\u11db\u11dc\u11dd\u11de\u11e2\u11e0\u11e1\u11df\u0000\u11af\u11ba\u11bc\u11c1\u11c2\u11e3\u11b9\u11e6\u11e4\u11e5\u0000\u11a8\u11ae\u11af\u11b8\u11ba\u11e7\u11e8\u11e9\u11ea\u11bb\u0000\u11a8\u11a9\u11bc\u11bf\u11ec\u11ed\u11ee\u11ef\u0000\u11b8\u11bc\u11f3\u11f4\u0000\u11ab\u11af\u11b7\u11b8\u11f5\u11f6\u11f7\u11f8\u0000\u11c2\u11cf\u0000\u11ba\u0000\u11a8\u0000\u11ba" +
"\u11eb\u11f1\u11f2\u0000|\u2395\u2347\u0000-\u2395\u2350\u0000|\u2395\u2348\u0000-\u2395\u2357\u0000/\u2204\u0000_|\u2395\u234d\u0000|~\u00a8\u2395\u2354\u0000/\u2209\u0000_\u0000/\u220c\u0000_\u00a8\u2229\u22a4\u22a5\u2395\u25cb\u235d\u2355\u234e\u233b\u233e\u0000/\u2224\u0000/\u2226\u0000~\u2228\u2395\u2353\u0000~\u2227\u2395\u234c\u0000\u2218" +
"\u0000|\u0000/\u2241\u0000/\u2244\u0000/\u2249\u0000/\u226d\u0000_\u2395\u236f\u0000/\u0000/\u2270\u0000/\u2271\u0000/\u2274\u0000/\u2275\u0000/\u2278\u0000/\u2279\u0000/\u2280\u0000/\u2281\u0000/\u22e0\u0000/\u22e1\u0000/_|\u2284\u0000/_\u2285\u0000/\u2288\u0000/\u2289\u0000/\u22e2\u0000/\u22e3\u0000" +
"/\u22ac\u0000\u00a8\u00af\u2218\u22a5\u2336\u0000_\u2218\u22a4\u0000/\u22ad\u0000/\u22ae\u0000/\u22af\u0000/\u22ea\u0000/\u22eb\u0000/\u22ec\u0000/\u22ed\u0000_\u2395\u233a\u0000_\u0000_\u0000_\u0000'/:<=>?\\\u00f7\u2190\u2191\u2192\u2193\u2206\u2207\u2218\u2227\u2228\u2260\u22c4\u25cb\u233c\u0000*-.\\_" +
"|\u00a8\u2218\u2395\u0000/\u2adc\u0000 !\"%'()*,-.0123456789:<=>?[]^_abcehlopruyz{|}\u00a3\u00a7\u00b1\u00d7\u0398\u03a0\u03a3\u03b2\u03b3\u03b5\u03b8\u03ba\u03c0\u03c1\u03c3\u03c5\u03c6\u0430\u0435" +
"\u0437\u0438\u0439\u043b\u043c\u043d\u043e\u0441\u0443\u0447\u0448\u044a\u044b\u044c\u044d\u044f\u0456\u0458\u045f\u0461\u0481\u0487\u049b\u04b7\u04c8\u0513\u05d1\u05d3\u05d5\u05d6\u05d7\u05dd\u05e1\u05e3\u05e4\u05e6\u05e7\u05e8\u05e9\u0625\u0626\u0627\u0628\u0629\u062b\u062d\u0631\u0632\u0633\u0635\u0637\u0639\u063a\u063d\u0641\u0642\u0643\u0644\u0646\u0647\u064a\u064f\u0650\u0660\u0661\u0662\u0663\u0664\u0665\u0666\u0667\u0668" +
"\u0669\u06a1\u06a9\u06c6\u06c9\u06cc\u06ce\u06f0\u06f1\u06f2\u06f3\u06f4\u06f5\u06f6\u06f7\u06f8\u06f9\u0901\u0902\u0905\u0906\u0907\u0908\u0909\u090a\u090b\u090c\u090f\u0910\u0913\u0914\u0915\u0916\u0917\u0918\u091a\u091b\u091c\u091d\u091f\u0921\u0922\u0923\u0925\u0926\u0928\u092a\u092b\u092c\u092f\u0930\u0933\u0935\u0936\u0937\u093c\u093d\u093e\u093f\u0940\u0941\u0943\u0947\u0948\u094b\u094c\u0953\u0956\u0962\u0964\u0970\u0b92" +
"\u0b9a\u0baf\u0bb3\u0bb5\u2020\u20ac\u20b9\u2190\u2191\u2192\u2193\u2194\u2195\u2196\u2197\u2198\u2199\u2203\u2206\u2207\u2227\u2228\u2229\u222a\u222b\u2282\u2283\u22a4\u22b7\u22c4\u235d\u2375\u237a\u2395\ua649\ua651\ua67d\uFFFF\u006e\u0062\u0073\u0070\uFFFF\u0066\u0031\u0030\uFFFF\u0066\u0031\uFFFF\u0066\u0032\uFFFF\u0066\u0033\uFFFF\u0066\u0034\uFFFF\u0066\u0035\uFFFF\u0066\u0036\uFFFF\u0066\u0037\uFFFF\u0066\u0038\uFFFF\u0066" +
"\u0039\uFFFF\u007a\u0077\u006e\u006a\u20b1\u20b4\u20bf\uFFFF\u0072\u0065\u006d\u006f\u0076\u0065\u0064\u2213\u2219\u03f4\u220f\u2211\u03d0\u0263\u03f5\u03d1\u03f0\u03d6\u03f1\u03c2\u03d2\u03d5\u0465\uFFFF\ua641\u0456\u0458\u046b\u0467\u047b\u0455\uFFFF\ua64b\u044c\uFFFF\ua651\u044a\u0454\u0438\uFFFF\ua66f\uFFFF\u0068\u0061\u0074\u0061\u0066\u005f\u0073\u0065\u0067\u006f\u006c\uFFFF\u0064\u0061\u0067\u0065\u0073\u0068\uFFFF\u0068" +
"\u006f\u006c\u0061\u006d\uFFFF\u0071\u0075\u0062\u0075\u0074\u0073\uFFFF\u0068\u0069\u0072\u0069\u0071\uFFFF\u0072\u0061\u0066\u0065\uFFFF\u0073\u0065\u0067\u006f\u006c\uFFFF\u0068\u0061\u0074\u0061\u0066\u005f\u0070\u0061\u0074\u0061\u0068\uFFFF\u0070\u0061\u0074\u0061\u0068\uFFFF\u0074\u0073\u0065\u0072\u0065\uFFFF\u0071\u0061\u006d\u0061\u0074\u0073\uFFFF\u0068\u0061\u0074\u0061\u0066\u005f\u0071\u0061\u006d\u0061\u0074\u0073" +
"\uFFFF\u0073\u0068\u0065\u0076\u0061\u066e\u067e\u06c1\u0698\u0640\u0636\u0638\u0621\u06a4\u063a\u06a9\u06ba\u06be\u06cc\u0643\u064a\u0900\u0955\u0972\u0911\u0973\u0974\u0976\u0977\u0960\u0961\u090d\u090e\u0912\u0975\u097b\u097c\uFFFF\u0936\u094d\u091a\u0979\u0978\u097e\uFFFF\u0924\u094d\u0930\uFFFF\u0926\u094d\u0930\uFFFF\u092a\u094d\u0930\u097f\u097a\uFFFF\u0936\u094d\u0930\uFFFF\u0915\u094d\u0937\u094e\u097d\u0949\u093a\u093b" +
"\u0904\u0944\u0945\u0946\u094a\u094f\u0954\u0957\u0963\u0965\u0971\uFFFF\u0bd0\uFFFF\u0bf2\uFFFF\u0bf0\uFFFF\u0bf1\uFFFF\u0bf3\u21d4\u21d5\u21d6\u21d7\u21d8\u21d9\u22c0\u22c1\u22c2\u22c3\u222e\u22b6\u044b\u0483\u00000123456789\u09e6\u09e7\u09e8\u09e9\u09ea\u09eb\u09ec\u09ed\u09ee\u09ef\u00000123456789\u0966\u0967\u0968\u0969\u096a" +
"\u096b\u096c\u096d\u096e\u096f\u00000123456789\u0ae6\u0ae7\u0ae8\u0ae9\u0aea\u0aeb\u0aec\u0aed\u0aee\u0aef\u00000123456789\u0660\u0661\u0662\u0663\u0664\u0665\u0666\u0667\u0668\u0669\u00000123456789\u0ce6\u0ce7\u0ce8\u0ce9\u0cea\u0ceb\u0cec\u0ced\u0cee\u0cef\u0000012" +
"3456789\u06f0\u06f1\u06f2\u06f3\u06f4\u06f5\u06f6\u06f7\u06f8\u06f9\u00000123456789\u0be6\u0be7\u0be8\u0be9\u0bea\u0beb\u0bec\u0bed\u0bee\u0bef\u0000\u00df\u0131\u01f0\u0237\u02b0\u02b2\u02b3\u02b7\u02e1\u0905\u0907\u0909\u090b\u090c\u090f\u0913\u0915\u0917\u091a\u091c\u091f\u0921\u0924\u0926\u0928\u092c\u092e\u0932\u0938\u0939\u093f\u0941\u0943" +
"\u0945\u0947\u0949\u094b\u0952\u0962\u0a85\u0a87\u0a89\u0a8f\u0a93\u0a95\u0a97\u0a9a\u0a9c\u0a9f\u0aa1\u0aa4\u0aa6\u0aa8\u0aaa\u0aac\u0aae\u0ab2\u0ab8\u0ab9\u0abf\u0ac1\u0ac7\u0acb\u0bf9\u1d43\u1d47\u1d48\u1d49\u1d4d\u1d4f\u1d50\u1d52\u1d56\u1d57\u1d58\u1d5b\u1d60\u1d9c\u1da0\u1dbe\u1e97\u1e98\u1e99\u2071\u207f\u20b9\u2190\u2191\u2192\u2193\u2196\u2197\u2198\u2199\u2208\u220b\u2282\u2283\u2286\u2287\u2500\u2502\u250c\u2510\u2514" +
"\u2518\u251c\u2524\u252c\u2534\u253c\ud835\uFFFF\u004a\u030c\uFFFF\u004a\u0307\u1d34\u1d36\u1d3f\u1d42\u1d38\u0906\u0908\u090a\u0910\u0914\u0916\u0918\u091b\u091d\u0920\u0922\u0925\u0927\u0923\u092d\u0902\u0933\u0936\u0903\u0940\u0942\u0948\u094c\u0951\u0a86\u0a88\u0a8a\u0a90\u0a94\u0a96\u0a98\u0a9b\u0a9d\u0aa0\u0aa2\u0aa5\u0aa7\u0aa3\u0aab\u0aad\u0a82\u0ab3\u0ab6\u0a83\u0ac0\u0ac2\u0ac8\u0acc\u1d2c\u1d2e\u1d30\u1d31\u1d33\u1d37" +
"\u1d39\u1d3c\u1d3e\u1d40\u1d41\u2c7d\u1db2\uFFFF\ua7f2\uFFFF\ua7f3\u1d23\uFFFF\u0054\u0308\uFFFF\u0057\u030a\uFFFF\u0059\u030a\u1d35\u1d3a\u2550\u2551\u2554\u2557\u255a\u255d\u2560\u2563\u2566\u2569\u256c\u0000\udd57\udd58\udd64\udd68\udd69\uFFFF\ud835\udd3d\uFFFF\ud835\udd3e\uFFFF\ud835\udd4a\uFFFF\ud835\udd4e\uFFFF\ud835\udd4f").toCharArray();
public static final char[] edges = public static final char[] edges =
("\u0001\u0036\u0037\u0038\u0039\u003a\u003b\u003c\u003f\u0040\u0041\u0042\u0043\u0044\u0045\u0046\u0047\u0048\u0049\u004a\u004b\u004c\u004d\u004e\u004f\u0050\u0051\u0052\u0053\u0054\u0055\u0056\u0059\u005a\u005b\\\u005d\u005e\u005f\u0060\u0061\u0062\u0063\u0064\u0067\u0068\u006b\u006e\u006f\u0072\u0075\u0078\u007b\u007e\u0081\u0001\u0001\u0001\u0001\u0001\u0003\u0000\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001" + ("\u0001\u0018\u0019\u001a\u001b\u001c\u001d\u0020\u0021\"\u0023\u0024\u0025\u0026\u0027\u0028\u0029\u002c\u002f\u0032\u0035\u0038\u003b\u003e\u0041\u0001\u0001\u0001\u0001\u0003\u0000\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u000c\u0050\u0051\u0052" +
"\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u0000\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u0000\u0000\u0001\u0003\u0000\u0000\u0003\u0000\u0000\u0001\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0001\u000c\u008e\u008f\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0001\u0001" + "\u0053\u0054\u0055\u0056\u0057\u0058\u0059\u005a\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0011\u006c\u006d\u006f\u0070\u0071\u0072\u0073\u0075\u0076\u0077\u0078\u007a\u007b\u007c\u007d\u007e\u0001\u0002\u0000\u0001\u0001\u0001\u0001\u0002\u0000\u0001\u0001\u0001\u0002\u0000\u0001\u0001\u0001\u0001\u0001\u000c\u008b\u008c\u008d\u008e\u008f\u0090\u0091\u0092\u0093\u0094\u0095\u0001\u0001\u0001\u0001\u0001" +
"\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u001a\u00b3\u00b4\u00b5\u00b7\u00b8\u00ba\u00bb\u00bc\u00bd\u00be\u00c0\u00c1\u00c2\u00c3\u00c5\u00c6\u00c7\u00c8\u00c9\u00ca\u00cb\u00cc\u00cd\u00ce\u00cf\u0001\u0001\u0002\u0000\u0001\u0002\u0000\u0001\u0001\u0001\u0001\u0002\u0000\u0001\u0001\u0001\u0002\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u000c\u00dc\u00dd\u00de\u00df\u00e0\u00e1\u00e2" + "\u0001\u0001\u0001\u0001\u0001\u0001\u000f\u00a5\u00a6\u00a7\u00a8\u00a9\u00aa\u00ab\u00ac\u00ad\u00ae\u00af\u00b0\u00b1\u00b2\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u000c\u00bf\u00c0\u00c1\u00c2\u00c3\u00c4\u00c5\u00c6\u00c7\u00c8\u00c9\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0011\u00db\u00dc\u00dd\u00de\u00df\u00e0\u00e1\u00e2\u00e3\u00e4\u00e5\u00e6\u00e9" +
"\u00e3\u00e4\u00e5\u00e6\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u001d\u0104\u0105\u0106\u0107\u0108\u0109\u010a\u010b\u010c\u010d\u010e\u010f\u0110\u0111\u0112\u0113\u0114\u0115\u0116\u0117\u011a\u011d\u0120\u0123\u0126\u0129\u012c\u012f\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000" + "\u00ec\u00ef\u00f2\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0014\u0109\u010a\u010b\u010c\u010d\u010e\u010f\u0110\u0111\u0112\u0113\u0114\u0115\u0116\u0117\u0118\u0119\u011a\u011b\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\r\u0129\u012a\u012b" +
"\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0001\u000e\u013e\u013f\u0140\u0141\u0142\u0143\u0144\u0145\u0146\u0147\u0148\u004e\u0149\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0025\u016f\u0170\u0171\u0172\u0173\u0174\u0175\u0176\u0177\u0178\u0179\u017a\u017d\u017e\u017f\u004b\u0180\u0181\u004f\u0182\u0051\u0183\u0184\u0185\u0186\u0189\u018c\u018f\u0192" + "\u012c\u012d\u012e\u012f\u0130\u0131\u0132\u0133\u0134\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0009\u013e\u013f\u0142\u0145\u0148\u014b\u014c\u014d\u0001\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0001\u0001\u0003\u0000\u0000\u0007\u0157\u0158\u0159\u015a\u015b\u015c\u0001\u0001\u0001\u0001\u0001\u0001\r\u016a\u016b\u016c\u016d\u016e\u016f\u0170\u0171\u0172\u0173" +
"\u0195\u0196\u0197\u0198\u0199\u019a\u019b\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u0000\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0033\u01cf\u01d2\u01d5\u01d8\u01db\u01de\u01e1\u01e4\u01e7\u01ea\u01ed\u01ee\u01ef\u01f0\u01f1\u01f2\u01f3\u01f4\u01f5" + "\u0174\u0175\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\r\u0183\u0184\u0185\u0186\u0187\u0188\u0189\u018a\u0133\u0174\u0134\u0175\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0007\u0192\u0193\u0194\u0195\u0196\u0197\u0001\u0001\u0001\u0001\u0001\u0001\u0009\u01a1\u01a2\u01a3\u00c4\u00c5\u00c6\u01a4\u01a5\u0001\u0001\u0001\u0001\u0001\r\u01b3\u01b4\u01b5\u01b6\u01b7\u01b8\u01b9\u01ba\u01bb" +
"\u01f6\u01f7\u01fa\u01fd\u01fe\u01ff\u0200\u0201\u0204\u0205\u0206\u0207\u020a\u020d\u020e\u020f\u0210\u0211\u0212\u0213\u0081\u012f\u0214\u0215\u0216\u0217\u0218\u0219\u021a\u021b\u021c\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003" + "\u01bc\u01b4\u01b5\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u01c0\u01c1\u0001\u0001\r\u01cf\u01d0\u01d1\u01d2\u01d3\u01d5\u01d7\u01d8\u01da\u01db\u01dd\u01df\u0001\u0001\u0001\u0001\u0002\u0000\u0002\u0000\u0001\u0002\u0000\u0001\u0002\u0000\u0002\u0000\u0001\u0021\u0201\u0202\u0203\u0204\u0205\u0206\u0207\u0208\u0209\u020a\u020b\u020c\u020d\u020e\u020f\u0210\u0211\u0212\u0213\u0214\u0215\u0216\u0217" +
"\u0000\u0000\u0003\u0000\u0000\u0001\u0001\u0001\u0001\u0003\u0000\u0000\u0001\u0001\u0001\u0003\u0000\u0000\u0003\u0000\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u001e\u023b\u023c\u023d\u023e\u023f\u0240\u0241\u0242\u0243\u0244\u0245\u0246\u0247\u0248\u0249\u024a\u024b\u024c\u024d\u024e\u024f\u0250\u0195\u0197\u019a\u0251\u0252\u0253\u0215\u0001\u0001\u0001\u0001\u0001" + "\u0218\u0219\u021a\u021b\u021c\u021d\u021e\u021f\u0220\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0029\u024a\u024b\u024c\u024d\u024e\u024f\u0250\u0251\u0252\u0253\u0254\u0255\u0256\u0257\u0258\u0259\u025a\u025b\u01b7\u01b8\u025c\u025d\u01bc\u025e\u025f\u0260\u0261\u0262\u01b6\u0263" +
"\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\n\u025e\u025f\u0262\u0265\u0268\u026b\u026c\u026d\u0270\u0001\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0001\u0001\u0003\u0000\u0000\u0001\u000e\u027f\u0280\u0281\u0282\u0283\u0284\u0285\u0288\u028b\u028e\u0291\u0294\u0297\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u0000\u0000" + "\u0264\u01b9\u01ba\u01bb\u0265\u0266\u0267\u0268\u0269\u026a\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u000c\u0277\u0278\u0279\u027a\u027b\u027c\u027d\u027e\u027f\u0187\u018a\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0007\u0287\u0288\u0289\u028a\u028b\u028c\u0001" +
"\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0001\u001f\u02b7\u02b8\u02b9\u02ba\u02bb\u02bc\u02bf\u02c0\u02c1\u02c2\u017f\u0181\u0182\u02c5\u02c6\u02c7\u02c8\u02c9\u02ca\u02cb\u02ce\u02d1\u02d2\u02d3\u02d4\u02d5\u02d6\u02d7\u02d8\u02d9\u0001\u0001\u0001\u0001\u0001\u0003\u0000\u0000\u0001\u0001\u0001\u0003\u0000\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u0000\u0000\u0003\u0000" + "\u0001\u0001\u0001\u0001\u0001\u0108\u0395\u03a6\u03ff\u047e\u048d\u0490\u05e0\u0998\u09b9\u09c9\u09d4\u0a08\u0a47\u0ab0\u0af4\u0afa\u0b10\u0b16\u0b1e\u0b21\u0b26\u0b29\u0b2c\u0b36\u0b4d\u0b7a\u0bae\u0bcd\u0c0c\u0c23\u0c27\u0c38\u0c3f\u0c51\u0c5f\u0c6a\u0c6c\u0c7f\u0c82\u0c85\u0c97\u0c99\u0ca7\u0cc3\u0ccb\u0cce\u0cd8\u0ce6\u0cf2\u0d49\u0d4e\u0d52\u0d54\u0d5c\u0d62\u0d65\u0d7a\u0d7c\u0e18\u0ecf\u0fdd\u0fef\u1019\u1054\u105e\u106f" +
"\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\r\u02e7\u02e8\u02e9\u02ea\u02eb\u02ec\u0196\u0198\u0185\u02ed\u02ee\u02ef\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\r\u02fd\u02fe\u02c9\\\u02ff\u02ca\u005d\u0300\u0252\u02ee\u0253\u02ef\u0001\u0001\u0001\u0001\u001d\u031e\u031f\u0320\u0321\u0322\u0325\u0326\u0329\u032a\u032b\u032c\u02c7\u0059\u02c8\u005a\u032d\u032e\u032f\u0330\u0212\u0213\u0331" + "\u107d\u1084\u1086\u1096\u1099\u109d\u10a5\u10a9\u10b0\u10cd\u10d7\u10dc\u10e8\u10f2\u110d\u1130\u1132\u1136\u113d\u1141\u1144\u1160\u11e1\u11fe\u124d\u130f\u1327\u132a\u132d\u132f\u1331\u1333\u1336\u1338\u133b\u133d\u133f\u1341\u1343\u13ee\u13f0\u13f3\u13f5\u13f7\u13f9\u13fc\u13fe\u1400\u1402\u1406\u140d\u1411\u1415\u1458\u1462\u146c\u1476\u1479\u1486\u1489\u14a0\u14a7\u14ac\u14b9\u14be\u14c5\u14ca\u14cd\u14d0\u14d3\u14d6\u14dd" +
"\u0332\u0333\u0334\u0335\u0336\u0337\u0001\u0001\u0001\u0001\u0003\u0000\u0000\u0001\u0003\u0000\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0007\u033f\u0340\u0341\u0342\u0343\u0330\u0001\u0001\u0001\u0001\u0001\r\u0351\u0352\u0353\u0354\u0355\u0356\u0357\u0358\u0359\u035a\u0352\u0353\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0007\u0362\u0363\u0364\u0365" + "\u14e0\u14e5\u14e8\u14ef\u14f2\u14f9\u14fc\u14ff\u1502\u1505\u1508\u150b\u150e\u1511\u1514\u151f\u1522\u1525\u152e\u1533\u153c\u1541\u1562\u1564\u1585\u1587\u159e\u15a3\u15a8\u15ad\u15b0\u15b6\u15b8\u15bb\u15be\u15c1\u15c4\u15cb\u15d2\u15db\u15e2\u15f3\u15f5\u1600\u1611\u1614\u1623\u162a\u162d\u163a\u1643\u164c\u164e\u165d\u1662\u168b\u168d\u1690\u1694\u1696\u16a9\u16b4\u16bf\u16c8\u16cd\u16d6\u16d9\u16db\u16dd\u16e2\u16e6\u16ea" +
"\u0366\u004c\u0001\u0001\u0001\u0001\u0001\u0011\u0378\u0379\u037a\u037b\u037c\u037e\u0380\u0381\u0383\u0384\u0386\u0388\u0389\u038b\u0053\u038d\u0001\u0001\u0001\u0001\u0002\u0000\u0002\u0000\u0001\u0002\u0000\u0001\u0002\u0000\u0002\u0000\u0001\u0002\u0000\u0002\u0000\u0002\u0000\u0027\u03b6\u03b7\u03b8\u03b9\u03ba\u03bb\u03bc\u03bd\u03be\u03bf\u03c0\u03c1\u03c2\u03c3\u03c4\u03c5\u03c6\u03c7\u03c8\u03c9\u03ca\u03cb\u03cc\u03cd" + "\u16ee\u16f2\u16f5\u16fa\u1700\u1703\u1705\u1708\u1715\u1718\u171b\u1720\u1725\u1727\u1729\u172c\u172f\u1732\u1735\u1739\u173b\u173e\u1741\u1744\u1747\u174a\u174d\u1750\u1753\u1756\u1759\u175e\u1762\u1765\u1768\u176b\u176e\u1771\u1777\u177b\u177e\u1781\u1784\u1787\u178a\u178d\u1790\u1794\u1796\u1798\u179a\u17b1\u17bb\u0009\u039e\u039f\u03a0\u03a1\u03a2\u03a3\u03a4\u03a5\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u002f\u03d5" +
"\u03ce\u03cf\u03d0\u03d1\u03d2\u03d3\u03d4\u03d5\u03d6\u03d7\u03d8\u03d9\u03da\u03db\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0051\u042d\u042e\u042f\u0430\u0431\u0432\u0433\u0434\u0435\u0436\u0437\u0438\u0439\u043a\u043b\u043c\u043d\u043e\u0355" + "\u03d6\u03dd\u03de\u03df\u03e0\u03e1\u03e2\u03e3\u03e4\u03e5\u03e6\u03e7\u03e8\u03e9\u03ea\u03eb\u03ec\u03ed\u03ee\u03ef\u03f0\u03f1\u0129\u03f2\u03f3\u012a\u03f4\u012b\u03f5\u03f6\u03f7\u03f8\u012c\u03f9\u03fa\u03fb\u012d\u03fc\u03fd\u012e\u03fe\u03db\u0133\u03dc\u0134\u0001\u0005\u03db\u03dc\u0133\u0134\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001" +
"\u0356\u043f\u0440\u035a\u0441\u0442\u0443\u0444\u0445\u0354\u0446\u0447\u0448\u0357\u0358\u0359\u044a\u044b\u044c\u044d\u044e\u044f\u0450\u0451\u0453\u0454\u0455\u0456\u0457\u0458\u0459\u045a\u045b\u045c\u045d\u045e\u045f\u0460\u0461\u0462\u0463\u0464\u0465\u0466\u0467\u0468\u0469\u046a\u046b\u046d\u046e\u046f\u0470\u0471\u0472\u0473\u0462\u0474\u0475\u0476\u0477\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001" + "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0041\u0440\u0440\u0441\u0442\u0443\u0444\u0445\u0446\u0447\u0448\u0449\u044a\u044b\u044c\u044d\u044e\u0287\u0288\u0453\u0289\u028a\u0454\u028b\u0455\u0456\u028c\u0457\u045c\u0441\u045a\u045b\u0451\u0452\u045f\u0460\u0461\u0462\u0463\u0464\u0465\u0466\u0467\u0468\u0469\u046a\u046b\u046c\u046d\u046e\u046f\u0470\u0471\u0472\u0473\u0474\u0475" +
"\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0002\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0002\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0002\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0012\u048a\u048b\u048c\u048d\u048e\u048f\u0490" + "\u0476\u0477\u0478\u0479\u047a\u047b\u047c\u047d\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u0451\u0452\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u045a\u045b\u0001\u0001\u0003\u0451\u0452\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0008\u0486" +
"\u0491\u0180\u0199\u0052\u0492\u005b\u0493\u032d\u02ff\u0300\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u002f\u04c3\u04c4\u04c5\u04c8\u04c9\u04ca\u04cb\u04ce\u04d1\u04d4\u04d7\u04da\u04db\u04de\u04df\u04e0\u04e1\u04e2\u04e3\u04e4\u0050\u0492\u02c5\u0054\u032b\u032e\u032f\u0115\u04e5\u04e6\u04e7\u04e8\u04e9\u04ea\u04eb\u04ec\u04ed\u04ee\u04ef\u04f0\u04f1\u04f2\u00cf\u04f3\u04f4\u04f5\u0001\u0001\u0003\u0000\u0000" + "\u0487\u0488\u0489\u048a\u048b\u048c\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0002\u048f\u0001\u007b\u050b\u0519\u051a\u0537\u0552\u0559\u055a\u055f\u0560\u0561\u0562\u0563\u0564\u0565\u0566\u0569\u056a\u056b\u056c\u056d\u056e\u056f\u0570\u0571\u0572\u0573\u0574\u0575\u0582\u0019\u058b\u001a\u001b\u0590\u001c\u001d\u0591\u0020\u0592\u0028\u0021\u0593\"\u0023\u0024\u0594\u0025\u0026\u0595\u059e\u05a3\u057c\u05a8\u05a9\u05a6" +
"\u0001\u0001\u0001\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0001\u0003\u0000\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0136\u062c\u063d\u0689\u06f5\u0704\u0707\u083c\u0bf4\u0c15\u0c24\u0c2f\u0c6f\u0cae\u0d24\u0d66\u0d6c\u0d82\u0d88\u0d90\u0d93\u0d98\u0d9b\u0d9e\u0da8\u0dbf" + "\u057d\u0514\u057e\u059a\u055d\u0515\u057f\u05aa\u05ab\u05a7\u0580\u0516\u0581\u059c\u055e\u0027\u058e\u058f\u0587\u0589\u0588\u058a\u059b\u059d\u0557\u0186\u0558\u0189\u05ac\u05ad\u05ae\u05af\u05b0\u05b1\u05b2\u05b3\u05b4\u05b5\u05b6\u05b7\u05b8\u05b9\u05ba\u05bd\u05be\u05c1\u05c4\u05c5\u05c8\u05cb\u05ce\u05d1\u05d4\u05d7\u0029\u05da\u002c\u002f\u05db\u0032\u05dc\u0035\u0038\u003b\u003e\u0041\u05df\u0008\u0513\u0514\u0515\u0516" +
"\u0dec\u0e1f\u0e3e\u0e7d\u0e94\u0e98\u0ea9\u0eb0\u0ec2\u0ed0\u0edb\u0edd\u0ef0\u0ef3\u0ef6\u0f08\u0f0a\u0f18\u0f34\u0f3c\u0f3f\u0f49\u0f57\u0f63\u0fb9\u0fbe\u0fc2\u0fc4\u0fcc\u0fd2\u0fd5\u0fea\u0fec\u1081\u1128\u1211\u1223\u124d\u1284\u128e\u129f\u12ad\u12b4\u12b6\u12c6\u12c9\u12cd\u12d5\u12d9\u12e0\u12fb\u1305\u130a\u1316\u1320\u133b\u135e\u1360\u1364\u136b\u136f\u1372\u138e\u140a\u1425\u1474\u1536\u154e\u1551\u1554\u1556\u1558" + "\u0027\u0517\u0518\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u000f\u0529\u052a\u052b\u052c\u052d\u052e\u052f\u0530\u0531\u0532\u0533\u0534\u0535\u0536\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u000e\u0545\u0546\u0547\u0548\u0549\u054a\u054b\u054c\u054d\u054e\u054f\u0550\u0551\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0005\u0557\u0558\u0186\u0189\u0001" +
"\u155a\u155d\u155f\u1562\u1564\u1566\u1568\u156a\u1615\u1617\u161a\u161c\u161e\u1620\u1623\u1625\u1642\u165d\u1666\u1673\u1685\u1687\u168b\u168f\u16a2\u16aa\u16af\u16b1\u16c8\u16e7\u16eb\u16f1\u170b\u1728\u1782\u1785\u1787\u1791\u1795\u179a\u17a0\u17a2\u17a4\u17a8\u17af\u17b3\u17b7\u17fa\u1804\u180e\u1818\u184d\u1856\u1859\u186b\u1871\u1874\u1876\u18b0\u18b4\u18b7\u18ba\u18d1\u1910\u192d\u1949\u1965\u1968\u1971\u1973\u198f\u19b1" + "\u0001\u0001\u0003\u055d\u055e\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u0000\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0007\u057c\u057d\u057e\u057f\u0580\u0581\u0001\u0001\u0001\u0001\u0001\u0001\u0005\u0587\u0588\u0589\u058a\u0001\u0001\u0001\u0001\u0003\u058e\u058f\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0005\u059a\u059b\u059c\u059d\u0001\u0001\u0001\u0001\u0005\u0587" +
"\u19bb\u19c4\u19ca\u19e1\u19e8\u19ed\u19fa\u19ff\u1a06\u1a0b\u1a0e\u1a11\u1a14\u1a17\u1a1e\u1a21\u1a26\u1a29\u1a30\u1a33\u1a3a\u1a3d\u1a40\u1a43\u1a46\u1a49\u1a4c\u1a4f\u1a52\u1a55\u1a60\u1a63\u1a66\u1a6f\u1a74\u1a7d\u1a82\u1aa3\u1aa5\u1ac6\u1ac8\u1adf\u1ae4\u1ae9\u1aee\u1af1\u1af7\u1af9\u1afc\u1aff\u1b02\u1b05\u1b0c\u1b13\u1b1c\u1b23\u1b34\u1b36\u1b41\u1b52\u1b55\u1b64\u1b6b\u1b6e\u1b7b\u1b84\u1b8d\u1b8f\u1b9e\u1ba3\u1bcc\u1bce" + "\u0588\u0589\u058a\u0003\u05a6\u05a7\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u0000\u0000\u0001\u0003\u0000\u0000\u0003\u0000\u0000\u0001\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0001\u0001\u0003\u0000\u0000\u0001\u00c1\u039f\u06a1\u06a2\u06a7\u06a8\u06ab\u06d6" +
"\u1bd1\u1bd5\u1bd7\u1bea\u1bf5\u1c00\u1c09\u1c0e\u1c17\u1c1a\u1c1c\u1c1e\u1c23\u1c27\u1c2b\u1c2f\u1c33\u1c36\u1c3b\u1c41\u1c44\u1c46\u1c49\u1c56\u1c59\u1c5c\u1c61\u1c66\u1c68\u1c6a\u1c6d\u1c70\u1c73\u1c76\u1c7a\u1c7c\u1c7f\u1c82\u1c85\u1c88\u1c8b\u1c8e\u1c91\u1c94\u1c97\u1c9a\u1c9f\u1ca3\u1ca6\u1ca9\u1cac\u1caf\u1cb2\u1cb8\u1cbc\u1cbf\u1cc2\u1cc5\u1cc8\u1ccb\u1cce\u1cd1\u1cd5\u1cd7\u1cd9\u1cdb\u1cf2\u1cfc\u0009\u0635\u0636\u0637" + "\u0701\u072c\u0757\u075e\u0761\u0764\u0767\u076a\u076d\u0770\u0773\u0776\u0779\u077c\u077f\u0782\u0785\u0788\u078b\u078e\u0791\u0794\u0797\u079a\u079d\u07a0\u07a3\u07a6\u07a9\u07ac\u07af\u07b2\u07b5\u07b8\u07bb\u07be\u07c1\u07c4\u07c7\u07ca\u07cd\u07d0\u07d3\u07d6\u07d9\u07dc\u07df\u07e2\u07e5\u07e8\u07eb\u07ee\u07f1\u07f4\u07f7\u07fa\u07fd\u0800\u0803\u0806\u0807\u0808\u0809\u080a\u080b\u080c\u080d\u080e\u080f\u0810\u0811\u0812" +
"\u0638\u0639\u063a\u063b\u063c\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u002f\u066c\u066d\u0674\u0675\u0676\u0677\u0678\u0679\u067a\u067b\u067c\u067d\u067e\u067f\u0680\u0681\u0682\u0683\u0684\u0685\u0686\u0687\u0688\u023e\u023f\u0240\u0241\u0242\u0243\u0244\u0245\u0246\u0247\u0248\u0249\u024a\u024b\u024c\u024d\u024e\u024f\u0250\u0672\u0252\u0673\u0253\u0001\u0005\u0672\u0673\u0252\u0253\u0001\u0001\u0001\u0001\u0001\u0001" + "\u0813\u0814\u0815\u0816\u081d\u0824\u082b\u0832\u0839\u0840\u0847\u084e\u0855\u085c\u0863\u086a\u0871\u0878\u087b\u087e\u0881\u0884\u0887\u088a\u088d\u0890\u0893\u0896\u0899\u089c\u089f\u08a2\u08a5\u08a8\u08ab\u08ae\u08b1\u08b4\u08b7\u08ba\u08bd\u08c0\u08c3\u08c6\u08c9\u08cc\u08cf\u08d2\u08d5\u08d8\u08db\u08de\u08e1\u08e4\u08e7\u08ea\u08ed\u08f0\u08f3\u08f6\u08f9\u08fc\u08ff\u0902\u0905\u0908\u090b\u090e\u0911\u0914\u0917\u091a" +
"\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0041\u06ca\u06ca\u06cb\u06cc\u06cd\u06ce\u06cf\u06d0\u06d1\u06d2\u06d3\u06d4\u06d5\u06d6\u06d7\u06d8\u04c4\u04c8\u04c9\u04ca\u04da\u04de\u04df\u04e0\u04e1\u04e2\u06dd\u06e1\u06cb\u06e0\u0492\u06db\u06dc\u06e4\u06e5\u04e5\u04e6\u04e8\u06e6\u06e7\u06e8\u06e9\u06ea\u06eb\u06ec\u06ed\u06ee\u06ef\u06f0\u04e9\u06f1\u04ea\u04eb\u04ec" + "\u091d\u0920\u0923\u0926\u0929\u092c\u092f\u0932\u0935\u0938\u093b\u093e\u0941\u0944\u0947\u094a\u094d\u0950\u0953\u0956\u0959\u095c\u095f\u0962\u0965\u0968\u096b\u096e\u0971\u0974\u0977\u097a\u097d\u0980\u0983\u0986\u0989\u098c\u098f\u0992\u0995\u0001\u0002\u06a4\u0003\u0000\u0000\u0001\u0002\u06aa\u0001\u000c\u06b7\u06b8\u06bb\u06be\u06c1\u06c4\u06c7\u06ca\u06cd\u06d0\u06d3\u0001\u0002\u06ba\u0001\u0002\u06bd\u0001\u0002\u06c0" +
"\u04ed\u04ee\u04ef\u04f0\u04f1\u06f2\u06f3\u04f2\u06f4\u00cf\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u06db\u06dc\u0001\u0001\u0003\u06e0\u0492\u0001\u0003\u06db\u06dc\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0008\u06fd\u06fe\u06ff\u0700\u0701\u0702\u0703\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0002\u0706\u0001\u007b" + "\u0001\u0002\u06c3\u0001\u0002\u06c6\u0001\u0002\u06c9\u0001\u0002\u06cc\u0001\u0002\u06cf\u0001\u0002\u06d2\u0001\u0002\u06d5\u0001\u000c\u06e2\u06e3\u06e6\u06e9\u06ec\u06ef\u06f2\u06f5\u06f8\u06fb\u06fe\u0001\u0002\u06e5\u0001\u0002\u06e8\u0001\u0002\u06eb\u0001\u0002\u06ee\u0001\u0002\u06f1\u0001\u0002\u06f4\u0001\u0002\u06f7\u0001\u0002\u06fa\u0001\u0002\u06fd\u0001\u0002\u0700\u0001\u000c\u070d\u070e\u0711\u0714\u0717\u071a" +
"\u0782\u078e\u078f\u07ac\u07c7\u07ce\u07cf\u07d3\u07d4\u07d5\u07d6\u07d7\u07d8\u07d9\u07da\u07dd\u07de\u07df\u07e0\u07e1\u07e2\u07e3\u07e4\u07e5\u07e6\u07e7\u07e8\u07e9\u07f3\u0037\u07fa\u0038\u0039\u003a\u003b\u003c\u003f\u0040\u0041\u0042\u0043\u0044\u0045\u0046\u0047\u0048\u0049\u004a\u07fe\u0805\u080a\u07f0\u080e\u080f\u080d\u07f1\u078b\u07f2\u0803\u07d2\u078c\u004b\u004c\u004d\u004e\u004f\u0050\u0051\u0052\u0053\u0054\u07fd" + "\u071d\u0720\u0723\u0726\u0729\u0001\u0002\u0710\u0001\u0002\u0713\u0001\u0002\u0716\u0001\u0002\u0719\u0001\u0002\u071c\u0001\u0002\u071f\u0001\u0002\u0722\u0001\u0002\u0725\u0001\u0002\u0728\u0001\u0002\u072b\u0001\u000c\u0738\u0739\u073c\u073f\u0742\u0745\u0748\u074b\u074e\u0751\u0754\u0001\u0002\u073b\u0001\u0002\u073e\u0001\u0002\u0741\u0001\u0002\u0744\u0001\u0002\u0747\u0001\u0002\u074a\u0001\u0002\u074d\u0001\u0002\u0750" +
"\u0055\u07f8\u0059\u07f9\u005a\u0804\u005b\u07cc\\\u07cd\u005d\u0810\u0811\u0812\u0813\u0814\u0815\u0816\u005e\u005f\u0060\u0061\u0062\u0063\u0817\u0818\u081b\u081c\u081f\u0822\u0823\u0826\u0829\u082c\u082f\u0832\u0835\u0064\u0067\u0068\u006b\u006e\u006f\u0838\u0072\u0075\u0078\u007b\u007e\u083b\u0008\u078a\u078b\u078c\u0050\u0054\u078d\u04e7\u0001\u0001\u0001\u0001\u0001\u000f\u079e\u079f\u07a0\u07a1\u07a2\u07a3\u07a4\u07a5" + "\u0001\u0002\u0753\u0001\u0002\u0756\u0001\u0003\u075a\u075b\u0001\u0002\u075d\u0001\u0002\u0760\u0001\u0002\u0763\u0001\u0002\u0766\u0001\u0002\u0769\u0001\u0002\u076c\u0001\u0002\u076f\u0001\u0002\u0772\u0001\u0002\u0775\u0001\u0002\u0778\u0001\u0002\u077b\u0001\u0002\u077e\u0001\u0002\u0781\u0001\u0002\u0784\u0001\u0002\u0787\u0001\u0002\u078a\u0001\u0002\u078d\u0001\u0002\u0790\u0001\u0002\u0793\u0001\u0002\u0796\u0001\u0002" +
"\u07a6\u07a7\u07a8\u07a9\u07aa\u07ab\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u000e\u07ba\u07bb\u07bc\u07bd\u07be\u07bf\u07c0\u07c1\u07c2\u07c3\u07c4\u07c5\u07c6\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0005\u07cc\u07cd\\\u005d\u0001\u0001\u0001\u0003\u07d2\u0053\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u0000\u0000\u0001\u0001\u0001" + "\u0799\u0001\u0002\u079c\u0001\u0002\u079f\u0001\u0002\u07a2\u0001\u0002\u07a5\u0001\u0002\u07a8\u0001\u0002\u07ab\u0001\u0002\u07ae\u0001\u0002\u07b1\u0001\u0002\u07b4\u0001\u0002\u07b7\u0001\u0002\u07ba\u0001\u0002\u07bd\u0001\u0002\u07c0\u0001\u0002\u07c3\u0001\u0002\u07c6\u0001\u0002\u07c9\u0001\u0002\u07cc\u0001\u0002\u07cf\u0001\u0002\u07d2\u0001\u0002\u07d5\u0001\u0002\u07d8\u0001\u0002\u07db\u0001\u0002\u07de\u0001\u0002" +
"\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0007\u07f0\u07f1\u07f2\u004b\u004f\u0051\u0001\u0001\u0001\u0005\u07f8\u07f9\u0059\u005a\u0001\u0001\u0003\u07fd\u0055\u0001\u0005\u0803\u0804\u0052\u005b\u0001\u0001\u0005\u07f8\u07f9\u0059\u005a\u0003\u080d\u004e\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u0000\u0000\u0001\u0003\u0000\u0000\u0003\u0000\u0000\u0001\u0003\u0000\u0000\u0003\u0000" + "\u07e1\u0001\u0002\u07e4\u0001\u0002\u07e7\u0001\u0002\u07ea\u0001\u0002\u07ed\u0001\u0002\u07f0\u0001\u0002\u07f3\u0001\u0002\u07f6\u0001\u0002\u07f9\u0001\u0002\u07fc\u0001\u0002\u07ff\u0001\u0002\u0802\u0001\u0002\u0805\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u0819\u081a\u0001\u0002\u081c\u0001\u0003\u0820\u0821\u0001\u0002\u0823\u0001\u0003\u0827\u0828\u0001" +
"\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0001\u00c1\u0636\u08fd\u08fe\u0903\u0904\u0907\u0932\u095d\u0988\u09b3\u09ba\u09bd\u09c0\u09c3\u09c6\u09c9\u09cc\u09cf\u09d2\u09d5\u09d8\u09db\u09de\u09e1\u09e4\u09e7\u09ea\u09ed\u09f0\u09f3\u09f6\u09f9\u09fc\u09ff\u0a02\u0a05\u0a08\u0a0b\u0a0e\u0a11\u0a14\u0a17\u0a1a\u0a1d\u0a20\u0a23\u0a26\u0a29\u0a2c\u0a2f\u0a32" + "\u0002\u082a\u0001\u0003\u082e\u082f\u0001\u0002\u0831\u0001\u0003\u0835\u0836\u0001\u0002\u0838\u0001\u0003\u083c\u083d\u0001\u0002\u083f\u0001\u0003\u0843\u0844\u0001\u0002\u0846\u0001\u0003\u084a\u084b\u0001\u0002\u084d\u0001\u0003\u0851\u0852\u0001\u0002\u0854\u0001\u0003\u0858\u0859\u0001\u0002\u085b\u0001\u0003\u085f\u0860\u0001\u0002\u0862\u0001\u0003\u0866\u0867\u0001\u0002\u0869\u0001\u0003\u086d\u086e\u0001\u0002\u0870" +
"\u0a35\u0a38\u0a3b\u0a3e\u0a41\u0a44\u0a47\u0a4a\u0a4d\u0a50\u0a53\u0a56\u0a59\u0a5c\u0a5f\u0a62\u0a63\u0a64\u0a65\u0a66\u0a67\u0a68\u0a69\u0a6a\u0a6b\u0a6c\u0a6d\u0a6e\u0a6f\u0a70\u0a71\u0a72\u0a79\u0a80\u0a87\u0a8e\u0a95\u0a9c\u0aa3\u0aaa\u0ab1\u0ab8\u0abf\u0ac6\u0acd\u0ad4\u0ad7\u0ada\u0add\u0ae0\u0ae3\u0ae6\u0ae9\u0aec\u0aef\u0af2\u0af5\u0af8\u0afb\u0afe\u0b01\u0b04\u0b07\u0b0a\u0b0d\u0b10\u0b13\u0b16\u0b19\u0b1c\u0b1f\u0b22" + "\u0001\u0003\u0874\u0875\u0001\u0002\u0877\u0001\u0002\u087a\u0001\u0002\u087d\u0001\u0002\u0880\u0001\u0002\u0883\u0001\u0002\u0886\u0001\u0002\u0889\u0001\u0002\u088c\u0001\u0002\u088f\u0001\u0002\u0892\u0001\u0002\u0895\u0001\u0002\u0898\u0001\u0002\u089b\u0001\u0002\u089e\u0001\u0002\u08a1\u0001\u0002\u08a4\u0001\u0002\u08a7\u0001\u0002\u08aa\u0001\u0002\u08ad\u0001\u0002\u08b0\u0001\u0002\u08b3\u0001\u0002\u08b6\u0001\u0002" +
"\u0b25\u0b28\u0b2b\u0b2e\u0b31\u0b34\u0b37\u0b3a\u0b3d\u0b40\u0b43\u0b46\u0b49\u0b4c\u0b4f\u0b52\u0b55\u0b58\u0b5b\u0b5e\u0b61\u0b64\u0b67\u0b6a\u0b6d\u0b70\u0b73\u0b76\u0b79\u0b7c\u0b7f\u0b82\u0b85\u0b88\u0b8b\u0b8e\u0b91\u0b94\u0b97\u0b9a\u0b9d\u0ba0\u0ba3\u0ba6\u0ba9\u0bac\u0baf\u0bb2\u0bb5\u0bb8\u0bbb\u0bbe\u0bc1\u0bc4\u0bc7\u0bca\u0bcd\u0bd0\u0bd3\u0bd6\u0bd9\u0bdc\u0bdf\u0be2\u0be5\u0be8\u0beb\u0bee\u0bf1\u0001\u0002\u0900" + "\u08b9\u0001\u0002\u08bc\u0001\u0002\u08bf\u0001\u0002\u08c2\u0001\u0002\u08c5\u0001\u0002\u08c8\u0001\u0002\u08cb\u0001\u0002\u08ce\u0001\u0002\u08d1\u0001\u0002\u08d4\u0001\u0002\u08d7\u0001\u0002\u08da\u0001\u0002\u08dd\u0001\u0002\u08e0\u0001\u0002\u08e3\u0001\u0002\u08e6\u0001\u0002\u08e9\u0001\u0002\u08ec\u0001\u0002\u08ef\u0001\u0002\u08f2\u0001\u0002\u08f5\u0001\u0002\u08f8\u0001\u0002\u08fb\u0001\u0002\u08fe\u0001\u0002" +
"\u0003\u0000\u0000\u0001\u0002\u0906\u0001\u000c\u0913\u0914\u0917\u091a\u091d\u0920\u0923\u0926\u0929\u092c\u092f\u0001\u0002\u0916\u0001\u0002\u0919\u0001\u0002\u091c\u0001\u0002\u091f\u0001\u0002\u0922\u0001\u0002\u0925\u0001\u0002\u0928\u0001\u0002\u092b\u0001\u0002\u092e\u0001\u0002\u0931\u0001\u000c\u093e\u093f\u0942\u0945\u0948\u094b\u094e\u0951\u0954\u0957\u095a\u0001\u0002\u0941\u0001\u0002\u0944\u0001\u0002\u0947\u0001" + "\u0901\u0001\u0002\u0904\u0001\u0002\u0907\u0001\u0002\u090a\u0001\u0002\u090d\u0001\u0002\u0910\u0001\u0002\u0913\u0001\u0002\u0916\u0001\u0002\u0919\u0001\u0002\u091c\u0001\u0002\u091f\u0001\u0002\u0922\u0001\u0002\u0925\u0001\u0002\u0928\u0001\u0002\u092b\u0001\u0002\u092e\u0001\u0002\u0931\u0001\u0002\u0934\u0001\u0002\u0937\u0001\u0002\u093a\u0001\u0002\u093d\u0001\u0002\u0940\u0001\u0002\u0943\u0001\u0002\u0946\u0001\u0002" +
"\u0002\u094a\u0001\u0002\u094d\u0001\u0002\u0950\u0001\u0002\u0953\u0001\u0002\u0956\u0001\u0002\u0959\u0001\u0002\u095c\u0001\u000c\u0969\u096a\u096d\u0970\u0973\u0976\u0979\u097c\u097f\u0982\u0985\u0001\u0002\u096c\u0001\u0002\u096f\u0001\u0002\u0972\u0001\u0002\u0975\u0001\u0002\u0978\u0001\u0002\u097b\u0001\u0002\u097e\u0001\u0002\u0981\u0001\u0002\u0984\u0001\u0002\u0987\u0001\u000c\u0994\u0995\u0998\u099b\u099e\u09a1\u09a4" + "\u0949\u0001\u0002\u094c\u0001\u0002\u094f\u0001\u0002\u0952\u0001\u0002\u0955\u0001\u0002\u0958\u0001\u0002\u095b\u0001\u0002\u095e\u0001\u0002\u0961\u0001\u0002\u0964\u0001\u0002\u0967\u0001\u0002\u096a\u0001\u0002\u096d\u0001\u0002\u0970\u0001\u0002\u0973\u0001\u0002\u0976\u0001\u0002\u0979\u0001\u0002\u097c\u0001\u0002\u097f\u0001\u0002\u0982\u0001\u0002\u0985\u0001\u0002\u0988\u0001\u0002\u098b\u0001\u0002\u098e\u0001\u0002" +
"\u09a7\u09aa\u09ad\u09b0\u0001\u0002\u0997\u0001\u0002\u099a\u0001\u0002\u099d\u0001\u0002\u09a0\u0001\u0002\u09a3\u0001\u0002\u09a6\u0001\u0002\u09a9\u0001\u0002\u09ac\u0001\u0002\u09af\u0001\u0002\u09b2\u0001\u0003\u09b6\u09b7\u0001\u0002\u09b9\u0001\u0002\u09bc\u0001\u0002\u09bf\u0001\u0002\u09c2\u0001\u0002\u09c5\u0001\u0002\u09c8\u0001\u0002\u09cb\u0001\u0002\u09ce\u0001\u0002\u09d1\u0001\u0002\u09d4\u0001\u0002\u09d7\u0001" + "\u0991\u0001\u0002\u0994\u0001\u0002\u0997\u0001\u0011\u09a9\u09aa\u09ab\u09ac\u09ad\u09ae\u09af\u09b0\u09b1\u09b2\u09b3\u09b4\u09b5\u09b6\u09b7\u09b8\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0009\u09c2\u01b3\u09c5\u09c6\u01c0\u01c1\u09c7\u09c8\u0003\u05a8\u05aa\u0001\u0001\u0001\u0001\u0007\u09d0\u09d1\u09d2\u09d3\u0183\u0184\u0001\u0001\u0001\u0001\u0024\u03a0\u0442\u0559" +
"\u0002\u09da\u0001\u0002\u09dd\u0001\u0002\u09e0\u0001\u0002\u09e3\u0001\u0002\u09e6\u0001\u0002\u09e9\u0001\u0002\u09ec\u0001\u0002\u09ef\u0001\u0002\u09f2\u0001\u0002\u09f5\u0001\u0002\u09f8\u0001\u0002\u09fb\u0001\u0002\u09fe\u0001\u0002\u0a01\u0001\u0002\u0a04\u0001\u0002\u0a07\u0001\u0002\u0a0a\u0001\u0002\u0a0d\u0001\u0002\u0a10\u0001\u0002\u0a13\u0001\u0002\u0a16\u0001\u0002\u0a19\u0001\u0002\u0a1c\u0001\u0002\u0a1f\u0001" + "\u03a0\u09f8\u09f9\u09fa\u09fb\u09fc\u09fd\u09fe\u09ff\u0a00\u0a01\u0a02\u0a03\u0a04\u0a05\u0a06\u0a07\u01a1\u00bf\u00c0\u01a2\u00c2\u00c3\u01a3\u00c4\u00c5\u00c6\u01a4\u00c7\u00c8\u00c9\u01a5\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0020\u03a1\u06a7\u09aa\u09d1\u09f8\u0a28\u0a2f\u0a38\u0a39\u0057\u0a3a\u0a3b\u0a3c\u0a3d\u0a3e\u0a3f\u0a40\u0a41\u0a42\u03a5\u0a43\u0192\u006f" +
"\u0002\u0a22\u0001\u0002\u0a25\u0001\u0002\u0a28\u0001\u0002\u0a2b\u0001\u0002\u0a2e\u0001\u0002\u0a31\u0001\u0002\u0a34\u0001\u0002\u0a37\u0001\u0002\u0a3a\u0001\u0002\u0a3d\u0001\u0002\u0a40\u0001\u0002\u0a43\u0001\u0002\u0a46\u0001\u0002\u0a49\u0001\u0002\u0a4c\u0001\u0002\u0a4f\u0001\u0002\u0a52\u0001\u0002\u0a55\u0001\u0002\u0a58\u0001\u0002\u0a5b\u0001\u0002\u0a5e\u0001\u0002\u0a61\u0001\u0001\u0001\u0001\u0001\u0001\u0001" + "\u0193\u0194\u0a3f\u0195\u0196\u0a44\u0a45\u0a46\u0004\u0a2c\u0a2d\u0a2e\u0001\u0001\u0001\u0003\u0a32\u0a35\u0003\u0000\u0000\u0003\u0000\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u003c\u0a83\u0a84\u0a89\u0a8e\u0a8f\u0a90\u0a91\u0a92\u0a93\u0a94\u0a95\u0a96\u0a97\u0a98\u0a99\u0a9a\u0a9b\u0a9c\u0a9d\u0a9e\u0a9f\u0aa0\u0aa1\u0aa2\u0aa3\u0aa4\u0aa5\u0aa6\u0aa7\u0a8e\u0109\u010a" +
"\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u0a75\u0a76\u0001\u0002\u0a78\u0001\u0003\u0a7c\u0a7d\u0001\u0002\u0a7f\u0001\u0003\u0a83\u0a84\u0001\u0002\u0a86\u0001\u0003\u0a8a\u0a8b\u0001\u0002\u0a8d\u0001\u0003\u0a91\u0a92\u0001\u0002\u0a94\u0001\u0003\u0a98\u0a99\u0001\u0002\u0a9b\u0001\u0003\u0a9f\u0aa0\u0001\u0002\u0aa2\u0001\u0003\u0aa6\u0aa7\u0001\u0002\u0aa9\u0001\u0003\u0aad\u0aae\u0001\u0002\u0ab0" + "\u010b\u010c\u010d\u010e\u010f\u0110\u0aa8\u0111\u0112\u0113\u0114\u0115\u0116\u0117\u0118\u0119\u011a\u011b\u0aa9\u0a8c\u0a8d\u0aac\u0aad\u0aae\u0a87\u0a88\u0aaf\u0001\u0003\u0a87\u0a88\u0001\u0001\u0003\u0a8c\u0a8d\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u0a8c\u0a8d\u0001\u0001\u0001\u0001" +
"\u0001\u0003\u0ab4\u0ab5\u0001\u0002\u0ab7\u0001\u0003\u0abb\u0abc\u0001\u0002\u0abe\u0001\u0003\u0ac2\u0ac3\u0001\u0002\u0ac5\u0001\u0003\u0ac9\u0aca\u0001\u0002\u0acc\u0001\u0003\u0ad0\u0ad1\u0001\u0002\u0ad3\u0001\u0002\u0ad6\u0001\u0002\u0ad9\u0001\u0002\u0adc\u0001\u0002\u0adf\u0001\u0002\u0ae2\u0001\u0002\u0ae5\u0001\u0002\u0ae8\u0001\u0002\u0aeb\u0001\u0002\u0aee\u0001\u0002\u0af1\u0001\u0002\u0af4\u0001\u0002\u0af7\u0001" + "\u0028\u0a38\u0ad8\u0ad8\u0ad9\u0ada\u0adb\u0a3b\u0adc\u0add\u0ade\u0adf\u0ae0\u0ae1\u0ae2\u0ae3\u006c\u0ae4\u006f\u0070\u0ae5\u0071\u01d7\u0ae6\u01da\u007b\u0ae7\u0ae8\u007e\u0ae9\u0aea\u0aeb\u0aec\u0aed\u0aee\u0aef\u0af0\u0af1\u0af2\u0af3\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0004\u01b3\u0af8\u0af9" +
"\u0002\u0afa\u0001\u0002\u0afd\u0001\u0002\u0b00\u0001\u0002\u0b03\u0001\u0002\u0b06\u0001\u0002\u0b09\u0001\u0002\u0b0c\u0001\u0002\u0b0f\u0001\u0002\u0b12\u0001\u0002\u0b15\u0001\u0002\u0b18\u0001\u0002\u0b1b\u0001\u0002\u0b1e\u0001\u0002\u0b21\u0001\u0002\u0b24\u0001\u0002\u0b27\u0001\u0002\u0b2a\u0001\u0002\u0b2d\u0001\u0002\u0b30\u0001\u0002\u0b33\u0001\u0002\u0b36\u0001\u0002\u0b39\u0001\u0002\u0b3c\u0001\u0002\u0b3f\u0001" + "\u0001\u0001\u000b\u0b05\u0b08\u0b09\u0b0a\u0b0b\u0b0c\u0b0d\u0b0e\u0b0f\u024f\u0002\u0b07\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0004\u0b14\u0b15\u0250\u0001\u0001\u0005\u0b1b\u0b1c\u0b1d\u0251\u0001\u0001\u0001\u0002\u0b20\u0001\u0003\u0b24\u0b25\u0001\u0001\u0002\u0b28\u0001\u0002\u0b2b\u0001\u0006\u0b32\u0b33\u0a39\u0b34\u0b35\u0001\u0001\u0001\u0001\u0011\u0b47\u09f9\u09fc\u09ff\u0a03\u0b48\u0b49\u0a07\u0b4a" +
"\u0002\u0b42\u0001\u0002\u0b45\u0001\u0002\u0b48\u0001\u0002\u0b4b\u0001\u0002\u0b4e\u0001\u0002\u0b51\u0001\u0002\u0b54\u0001\u0002\u0b57\u0001\u0002\u0b5a\u0001\u0002\u0b5d\u0001\u0002\u0b60\u0001\u0002\u0b63\u0001\u0002\u0b66\u0001\u0002\u0b69\u0001\u0002\u0b6c\u0001\u0002\u0b6f\u0001\u0002\u0b72\u0001\u0002\u0b75\u0001\u0002\u0b78\u0001\u0002\u0b7b\u0001\u0002\u0b7e\u0001\u0002\u0b81\u0001\u0002\u0b84\u0001\u0002\u0b87\u0001" + "\u01a1\u01a2\u01a3\u01a4\u0b4b\u0b4c\u01a5\u0001\u0001\u0001\u0001\u0001\u0001\u001e\u03a3\u0443\u055f\u0055\u0b6b\u0b6c\u0b6d\u0b6e\u0b6f\u0b70\u0b71\u0b72\u0b73\u0b74\u0b75\u0b76\u0b77\u0b78\u0b6e\u00a6\u00a7\u00a8\u00aa\u00ab\u00ad\u00ae\u00af\u00b1\u0b79\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0021\u0ad9\u0b9b\u0b9c\u0b9d\u0b9d\u0b9e\u0b9f\u0ba0\u0ba1\u0ba2\u0ba3\u0ba4\u0ba5" +
"\u0002\u0b8a\u0001\u0002\u0b8d\u0001\u0002\u0b90\u0001\u0002\u0b93\u0001\u0002\u0b96\u0001\u0002\u0b99\u0001\u0002\u0b9c\u0001\u0002\u0b9f\u0001\u0002\u0ba2\u0001\u0002\u0ba5\u0001\u0002\u0ba8\u0001\u0002\u0bab\u0001\u0002\u0bae\u0001\u0002\u0bb1\u0001\u0002\u0bb4\u0001\u0002\u0bb7\u0001\u0002\u0bba\u0001\u0002\u0bbd\u0001\u0002\u0bc0\u0001\u0002\u0bc3\u0001\u0002\u0bc6\u0001\u0002\u0bc9\u0001\u0002\u0bcc\u0001\u0002\u0bcf\u0001" + "\u0ba6\u0ba7\u0ba8\u0b9d\u0ba9\u0b9d\u014b\u0ba1\u0ba2\u014c\u0baa\u0ba6\u0b9d\u0ba1\u0b9d\u0bab\u0ba1\u0bac\u0bad\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0015\u03a4\u0444\u0560\u0bc3\u0b6f\u0bc4\u0bc5\u0bc6\u0bc7\u0bc8\u0bc9\u0bca\u0bc4\u00db\u00dd\u00e0\u00e2\u00e3\u0bcb\u0bcc\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0020\u0bed\u0bee" +
"\u0002\u0bd2\u0001\u0002\u0bd5\u0001\u0002\u0bd8\u0001\u0002\u0bdb\u0001\u0002\u0bde\u0001\u0002\u0be1\u0001\u0002\u0be4\u0001\u0002\u0be7\u0001\u0002\u0bea\u0001\u0002\u0bed\u0001\u0002\u0bf0\u0001\u0002\u0bf3\u0001\u0011\u0c05\u0c06\u0c07\u0c08\u0c09\u0c0a\u0c0b\u0c0c\u0c0d\u0c0e\u0c0f\u0c10\u0c11\u0c12\u0c13\u0c14\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0009\u0c1e\u0351" + "\u0bf5\u0bf6\u0bf7\u0bf8\u0bf9\u0bfa\u0bfb\u0bfc\u0bfd\u016a\u0c07\u016b\u016c\u016d\u016e\u016f\u0c04\u0c05\u0c06\u0170\u0171\u0172\u0c0a\u0173\u0bf3\u0174\u0bf4\u0175\u0c0b\u0001\u0005\u0bf3\u0bf4\u0174\u0175\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0007\u0c04\u0c05\u0c06\u0170\u0171\u0172\u0001\u0001\u0001\u0003\u0c0a\u0173\u0001\u0001\u0012\u0445\u0561\u0c1e\u09c5\u09f9\u0a3a\u09f9\u0bc6\u09c5\u0c1f\u0c20" +
"\u0c21\u0c22\u0362\u0363\u04c3\u0c23\u0003\u080e\u004c\u0001\u0001\u0001\u0007\u0c2b\u0c2c\u0c2d\u0c2e\u02fd\u02fe\u0001\u0001\u0001\u0001\u002a\u0637\u06cc\u07ce\u0637\u0c59\u0c5a\u0c5b\u0c5c\u0c5d\u0c5e\u0c5f\u0c60\u0c61\u0c62\u0c63\u0c64\u0c65\u0c66\u0c67\u0c68\u033f\u013e\u013f\u0340\u0141\u0142\u0341\u0143\u0144\u0145\u0342\u0146\u0147\u0148\u0343\u0c69\u0c6a\u0c6b\u0c6c\u0c6d\u0c6e\u0001\u0001\u0001\u0001\u0001\u0001\u0001" + "\u0bc6\u0a3a\u0c21\u0c22\u0445\u0561\u0001\u0001\u0001\u0001\u0001\u0003\u0a95\u0c26\u0001\u000c\u0562\u09fa\u0a96\u0adb\u0b70\u0b9d\u0c33\u0c34\u0c35\u0c36\u0c37\u0001\u0001\u0001\u0001\u0001\u0006\u09fb\u0a3b\u0a97\u0b71\u0c3e\u0001\u0010\u0446\u0563\u09fc\u0a3c\u0a98\u09fc\u0b72\u0b9d\u0bc7\u0c4f\u0bc7\u0a3c\u0c50\u0446\u0563\u0001\u0001\u0006\u0a99\u0c57\u0c5a\u0c5c\u0c5e\u0003\u0000\u0000\u0002\u0000\u0002\u0000\u0001\u0008" +
"\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0020\u0638\u0903\u0c06\u0c2c\u0c59\u0c8f\u0c96\u0c9f\u0ca0\u0095\u0ca1\u0ca2\u0ca3\u0ca4\u0ca5\u0ca6\u0ca7\u0ca8\u0ca9\u063c\u0caa\u031e\u00b7\u031f\u0321\u0ca6\u0325\u0329\u0cab\u0cac\u0cad\u0004\u0c93\u0c94\u0c95\u0001\u0001\u0001\u0003\u0c99\u0c9c\u0003\u0000\u0000\u0003\u0000\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001" + "\u0c67\u09fd\u0a9a\u0c68\u0c67\u0c69\u0c67\u0001\u0001\u0001\u0002\u09fe\u0010\u0448\u0565\u09ff\u0a3d\u0a9c\u09ff\u0bc8\u0c7c\u0bc8\u0a3d\u0c7d\u0c7c\u0c7e\u0448\u0565\u0001\u0001\u0001\u0003\u0566\u0566\u0003\u0a00\u0a3e\n\u056a\u0a01\u0a3f\u0adf\u0b73\u0b9e\u0c8f\u0c96\u0ae3\u0002\u0c91\u0002\u0c93\u0003\u0000\u0000\u0001\u0002\u0a9d\n\u056c\u0a02\u0b74\u0b9f\u0ca3\u0ca4\u0ca5\u0ca5\u0ca6\u0001\u0001\u0001\u0001\u0015" +
"\u0001\u0001\u0001\u0001\u0001\u0001\u0046\u0cf4\u0cf5\u0cf9\u0cfd\u0cfe\u0cff\u0d00\u0d01\u0d02\u0d03\u0d04\u0d05\u0d06\u0d07\u0d08\u0d09\u0d0a\u0d0b\u0d0c\u0d0d\u0d0e\u0d0f\u0d10\u0d11\u0d12\u0d13\u0d14\u0d15\u0d16\u0cfd\u01ed\u01ee\u01ef\u01f0\u01f1\u01f2\u01f3\u01f4\u01f5\u01fd\u01fe\u01ff\u0200\u0204\u0205\u0206\u020d\u020e\u020f\u0210\u0d17\u0cfc\u0081\u0d1a\u012f\u0214\u0d1b\u0d1c\u0d1d\u0d1e\u0d1f\u0d20\u0c6e\u0d21\u0d22" + "\u0449\u056d\u0a03\u0a40\u0ae0\u0a03\u0bc9\u076c\u0c35\u0cbc\u0cbd\u0cbe\u0cbf\u0cc0\u0bc9\u0a40\u0cc1\u0cc2\u0449\u056d\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0006\u0cc9\u0aa0\u0ba1\u0cc9\u0cca\u0001\u0001\u0002\u0ccd\u0001\u0008\u056f\u0a04\u0b75\u0ba2\u0cbd\u0cd6\u0cd7\u0001\u0001\u000b\u0cbe\u0570\u0a05\u0aa2\u0b48\u0b76\u0ce3\u0cbe\u0ce4\u0ce5\u0001\u0001\u0001\n\u0a06\u0ae1\u0aa3\u0ae1\u0b49\u0b77\u0ba3\u0cf0\u0cf1" +
"\u06f2\u0cf8\u0215\u0d23\u0001\u0003\u0cf8\u0215\u0001\u0003\u0cfc\u0081\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u0cfc\u0081\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0028\u0c9f\u0d4c\u0d4c\u0d4d\u0d4e\u0d4f\u0ca2\u0d50\u0d51\u0d52\u0d53\u0d54\u0d55\u0d56\u0d57\u00b4\u0d58\u00b7\u00ba" + "\u0001\u0001\u002d\u0d1f\u0d26\u044a\u0571\u09c6\u0a07\u0a41\u0a07\u0bca\u0c1e\u0d2a\u0c67\u0d2b\u0d2c\u0d2d\u0bca\u0a41\u0d2e\u0d2f\u0d30\u0d31\u0d32\u0d33\u0d34\u0d35\u044a\u0571\u0d36\u0d39\u0d3a\u0d3b\u0d3c\u0d3d\u0d3e\u0d3f\u0d40\u0d41\u0d42\u0d43\u0d44\u0d45\u0d46\u0d47\u0d48\u0002\u0d21\u0003\u0d24\u0d25\u0001\u0001\u0003\u0d29\u0132\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u0d24" +
"\u00bb\u00bc\u0380\u0d59\u0383\u00c6\u0d5a\u0d5b\u00c9\u0d5c\u0d5d\u0d5e\u0d5f\u0d60\u0d61\u00ce\u0d62\u0d63\u0d64\u0d65\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0004\u0351\u0d6a\u0d6b\u0001\u0001\u000b\u0d77\u0d7a\u0d7b\u0d7c\u0d7d\u0d7e\u0d7f\u0d80\u0d81\u0432\u0002\u0d79\u0001\u0001\u0001\u0001\u0001\u0001\u0001" + "\u0d25\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0005\u0ae3\u0b70\u0b76\u0b78\u0003\u0ba5\u0d51\u0001\u0002\u0cbf\u0007\u044d\u0573\u0ba6\u0d5b\u044d\u0573\u0001\u0005\u0574\u0aa7\u0b78\u0d61\u0001\u0002\u0d64\u0001\u0008\u0a42\u0bfc\u0d6d\u0d70\u0d75\u0d78\u0d79\u0003\u0000\u0000\u0002\u0d72\u0003\u0000\u0000\u0003\u0000\u0000\u0001\u0001\u0002\u0d64\u004e\u0dca\u024a\u024b" +
"\u0001\u0001\u0004\u0d86\u0d87\u0433\u0001\u0001\u0005\u0d8d\u0d8e\u0d8f\u0434\u0001\u0001\u0001\u0002\u0d92\u0001\u0003\u0d96\u0d97\u0001\u0001\u0002\u0d9a\u0001\u0002\u0d9d\u0001\u0006\u0da4\u0da5\u0ca0\u0da6\u0da7\u0001\u0001\u0001\u0001\u0011\u0db9\u0c5a\u0c5d\u0c60\u0c64\u0dba\u0dbb\u0c68\u0dbc\u033f\u0340\u0341\u0342\u0dbd\u0dbe\u0343\u0001\u0001\u0001\u0001\u0001\u0001\u001e\u063a\u06cd\u07d3\u0093\u0ddd\u0dde\u0ddf\u0de0" + "\u024c\u024d\u0a8e\u0ae3\u024e\u024f\u0250\u0251\u0252\u0253\u0254\u0255\u0256\u0257\u0258\u0bc6\u0dd4\u0bc7\u0dd5\u0dd6\u0bc8\u0dd7\u0bc9\u0dd8\u0bca\u0d51\u0d5b\u0dd9\u0dda\u00db\u00dc\u00dd\u00de\u00df\u00e0\u00e1\u00e2\u00e5\u00e3\u0df3\u0df4\u00e4\u0059\u0df5\u0df8\u0dfb\u0dfe\u0e01\u0e04\u00e6\u00e9\u00ec\u00ef\u0e07\u00f2\u0dd2\u0130\u0dd3\u0131\u024d\u0e0a\u0e0b\u0e0c\u0e0d\u0e0e\u0e0f\u0e10\u0e11\u0e12\u0e13\u0e14\u0e15" +
"\u0de1\u0de2\u0de3\u0de4\u0de5\u0de6\u0de7\u0de8\u0de9\u0dea\u0de0\u0105\u0106\u0107\u010d\u010e\u0110\u0111\u0112\u0114\u0deb\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0021\u0d4d\u0e0d\u0e0e\u0e0f\u0e0f\u0e10\u0e11\u0e12\u0e13\u0e14\u0e15\u0e16\u0e17\u0e18\u0e19\u0e1a\u0e0f\u0e1b\u0e0f\u026b\u0e13\u0e14\u026c\u0e1c\u0e18\u0e0f\u0e13\u0e0f\u0e1d\u0e13\u0270\u0e1e\u0001\u0001\u0001" + "\u0e16\u0e17\u0007\u0dd1\u0dd2\u0dd3\u012f\u0130\u0131\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0013\u01b4\u01bc\u025e\u025f\u0261\u01b6\u01b5\u01b9\u01ba\u0267\u0268\u0269\u0ded\u0dee\u0def\u0df0\u0df1\u0df2\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0001\u0001\u0001\u0001\u0001\u0001" +
"\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0015\u063b\u06ce\u07d4\u0e34\u0de1\u0e35\u0e36\u0e37\u0e38\u0e39\u0e3a\u0e3b\u0e35\u0170\u0172\u0175\u0177\u0178\u0e3c\u0e3d\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0020\u0e5e\u0e5f\u0e66\u0e67\u0e68\u0e69\u0e6a\u0e6b\u0e6c\u0e6d\u0e6e\u02e7\u0e78\u02e8\u02e9\u02ea\u02eb\u02ec\u0e75\u0e76\u0e77\u0196\u0198\u0185\u0e7b" + "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0058\u03a5\u0e70\u0e79\u0e85\u0201\u0202\u0203\u0204\u0e86\u0205\u0206\u0207\u0208\u0209\u020a\u020b\u020c\u020d\u020e\u0e91\u0b6e\u020f\u0bc4\u0a3a\u0a3c\u0e96\u0a3d\u0a40\u0a41\u0e97\u03a5\u03a5\u0192\u0193\u0e98\u0194\u0195\u0196\u0e99\u0e9a\u0e80\u0e9f\u0e9d\u0e81\u0e82\u0e83\u0ea0\u0e9e\u0e84\u0197\u0e8d\u0e8f\u0ea1\u0ea2\u0ea3\u0ea4\u0ea5\u0ea6\u0ea7\u0eaa\u0ead\u0eae\u0eb1" +
"\u02ed\u0e64\u02ee\u0e65\u02ef\u0e7c\u0001\u0005\u0e64\u0e65\u02ee\u02ef\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0007\u0e75\u0e76\u0e77\u0196\u0198\u0185\u0001\u0001\u0001\u0003\u0e7b\u02ed\u0001\u0001\u0012\u06cf\u07d5\u0e8f\u0c21\u0c5a\u0ca1\u0c5a\u0e37\u0c21\u0e90\u0e91\u0e37\u0ca1\u0e92\u0e93\u06cf\u07d5\u0001\u0001\u0001\u0001\u0001\u0003\u0d04\u0e97\u0001\u000c\u07d6\u0c5b\u0d05\u0d4f\u0de2\u0e0f\u0ea4" + "\u0eb4\u0eb5\u0eb8\u0ebb\u0ebc\u0ebf\u0ec2\u0e75\u0e77\u0e76\u0e78\u0ec3\u0ec4\u0204\u0ec5\u0ec6\u0ec7\u0ec8\u0ec9\u0eca\u0ecb\u0ecc\u0ecd\u0ece\u0005\u0e75\u0e76\u0e77\u0e78\u0001\u0001\u0001\u0001\u0007\u0e80\u0e81\u0e82\u0e83\u0e84\u0197\u0001\u0001\u0001\u0001\u0001\u0001\u0007\u0e8d\u0a32\u0e8e\u0e8f\u0a35\u0e90\u0001\u0001\u0001\u0001\u0003\u0e94\u0e95\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u0e9d\u0e9e\u0001\u0001\u0001" +
"\u0ea5\u0ea6\u0ea7\u0ea8\u0001\u0001\u0001\u0001\u0001\u0006\u0c5c\u0ca2\u0d06\u0de3\u0eaf\u0001\u0010\u06d0\u07d7\u0c5d\u0ca3\u0d07\u0c5d\u0de4\u0e0f\u0e38\u0ec0\u0e38\u0ca3\u0ec1\u06d0\u07d7\u0001\u0001\u0006\u0d08\u0ec8\u0ecb\u0ecd\u0ecf\u0003\u0000\u0000\u0002\u0000\u0002\u0000\u0001\u0008\u0ed8\u0c5e\u0d09\u0ed9\u0ed8\u0eda\u0ed8\u0001\u0001\u0001\u0002\u0c5f\u0010\u06d2\u07d9\u0c60\u0ca4\u0d0b\u0c60\u0e39\u0eed\u0e39\u0ca4" + "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u0000\u0000\u0003\u0000\u0000\u0001\u0003\u0000\u0000\u0003\u0000\u0000\u0001\u0003\u0000\u0000\u0003\u0000\u0000\u0001\u0003\u0000\u0000\u0003\u0000\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0046\u0f15\u0f1d\u0f3a\u0f55\u0c21\u0c50\u0c7d\u0f5c\u0cc1\u0d2e\u0f5d\u0f5e\u0f5f\u0f6c\u0f75\u0157\u0fa6\u0158\u0159\u0fab\u015a\u015b\u0fac\u0fad" +
"\u0eee\u0eed\u0eef\u06d2\u07d9\u0001\u0001\u0001\u0003\u07da\u07da\u0003\u0c61\u0ca5\n\u07de\u0c62\u0ca6\u0d53\u0de5\u0e10\u0f00\u0f07\u0d57\u0002\u0f02\u0002\u0f04\u0003\u0000\u0000\u0001\u0002\u0d0c\n\u07e0\u0c63\u0de6\u0e11\u0f14\u0f15\u0f16\u0f16\u0f17\u0001\u0001\u0001\u0001\u0015\u06d3\u07e1\u0c64\u0ca7\u0d54\u0c64\u0e3a\u09c8\u0ea6\u0f2d\u0f2e\u0f2f\u0f30\u0f31\u0e3a\u0ca7\u0f32\u0f33\u06d3\u07e1\u0001\u0001\u0001" + "\u0fae\u0f66\u0f67\u0f68\u0f1a\u0f69\u0f6a\u0f6b\u015c\u0fa9\u0faa\u0f71\u0f73\u0f72\u0f74\u0f5a\u0185\u0f5b\u0188\u0fb3\u0fb4\u0fb5\u0fb6\u0fb7\u0fb8\u0fb9\u0fba\u0fbb\u0fbc\u0fbd\u0fbe\u0fbf\u0fc0\u0fc1\u0fc4\u0fc5\u0fc6\u0fc9\u0fcc\u0fcf\u0fd2\u0fd3\u0fd4\u0fd7\u0fda\u0005\u0f1a\u015c\u0f1b\u0f1c\u0001\u0001\u0001\u000f\u0f2c\u0f2d\u0f2e\u0f2f\u0f30\u0f31\u0f32\u0f33\u0f34\u0f35\u0f36\u0f37\u0f38\u0f39\u0001\u0001\u0001\u0001" +
"\u0001\u0001\u0001\u0001\u0006\u0f3a\u0d0f\u0e13\u0f3a\u0f3b\u0001\u0001\u0002\u0f3e\u0001\u0008\u07e3\u0c65\u0de7\u0e14\u0f2e\u0f47\u0f48\u0001\u0001\u000b\u0f2f\u07e4\u0c66\u0d11\u0dba\u0de8\u0f54\u0f2f\u0f55\u0f56\u0001\u0001\u0001\n\u0c67\u0d55\u0d12\u0d55\u0dbb\u0de9\u0e15\u0f61\u0f62\u0001\u0001\u002d\u0f90\u0f96\u06d4\u07e5\u0c22\u0c68\u0ca8\u0c68\u0e3b\u0e8f\u0f9a\u0ed8\u0f9b\u0f9c\u0f9d\u0e3b\u0ca8\u0f9e\u0f9f\u0fa0" + "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u000e\u0f48\u0f49\u0f4a\u0f4b\u0f4c\u0f4d\u0f4e\u0f4f\u0f50\u0f51\u0f52\u0f53\u0f54\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0005\u0f5a\u0f5b\u0185\u0188\u0001\u0001\u0001\u0001\u0001\u0007\u0f66\u0f67\u0f68\u0f69\u0f6a\u0f6b\u0001\u0001\u0001\u0001\u0001\u0001\u0005\u0f71\u0f72\u0f73\u0f74\u0001\u0001\u0001\u0001\r\u0f82\u0f85" +
"\u0fa1\u0fa2\u0fa3\u0fa4\u0fa5\u06d4\u07e5\u0fa6\u0fa9\u0faa\u0fab\u0fac\u0fad\u0fae\u0faf\u0fb0\u0fb1\u0fb2\u0fb3\u0fb4\u0fb5\u0fb6\u0fb7\u0fb8\u0002\u0f92\u0003\u0f95\u0149\u0001\u0003\u0f99\u0251\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u0f95\u0149\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0005\u0d57\u0de2\u0de8\u0dea\u0003\u0e17" + "\u0f88\u0f8b\u0f8e\u0f91\u0f94\u0f97\u0f9a\u0f9d\u0fa0\u0fa3\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0fa9\u0faa\u0001\u0001\u0001\u0001\u0001\u0005\u0f71\u0f72\u0f73\u0f74\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001" +
"\u0fc1\u0001\u0002\u0f30\u0007\u06d7\u07e7\u0e18\u0fcb\u06d7\u07e7\u0001\u0005\u07e8\u0d16\u0dea\u0fd1\u0001\u0002\u0fd4\u0001\u0008\u0ca9\u0e6d\u0fdd\u0fe0\u0fe5\u0fe8\u0fe9\u0003\u0000\u0000\u0002\u0fe2\u0003\u0000\u0000\u0003\u0000\u0000\u0001\u0001\u0002\u0fd4\u004e\u103a\u042d\u042e\u042f\u0430\u0cfd\u0d57\u0431\u0432\u0433\u0434\u0435\u0436\u0437\u0438\u0439\u043a\u043b\u0e37\u1044\u0e38\u1045\u1046\u0e39\u1047\u0e3a\u1048" + "\u0001\u0003\u0000\u0000\u0001\u0001\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0001\u0001\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0011\u0287\u0019\u0d2f\u01c0\u01a1\u0192\u01a1\u00db\u00db\u0192\u0157\u01c0\u0fee\u0277\u0287\u0019\u0001\u0021\u1010\u1013\u010a\u0c1e\u0d2a\u0c67\u0d2b\u0d2c\u0d2d\u0d2f\u0d30\u0d31\u0d32\u0d33\u0d34\u1016\u0d39\u0d3a\u0d3b\u0d3c\u0d3d\u0d3e\u0d3f\u0d40" +
"\u0e3b\u0fc1\u0fcb\u1049\u104a\u0170\u0171\u0172\u0173\u0174\u0175\u0176\u0177\u0184\u0178\u0179\u017d\u017e\u0097\u105e\u1061\u1064\u1067\u106a\u106d\u0186\u0189\u018c\u018f\u1070\u0192\u1042\u0197\u1043\u019a\u0430\u1073\u1074\u1075\u1076\u1077\u1078\u1079\u107a\u107b\u107c\u107d\u107e\u107f\u1080\u0007\u1041\u1042\u1043\u0195\u0197\u019a\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0013\u0352\u035a\u0441\u0442\u0444" + "\u0d41\u0d42\u0d43\u0d44\u0d45\u0d46\u0d47\u0d48\u0003\u0d29\u0132\u0003\u0d24\u0d25\u0003\u0d24\u0d25\u002c\u1045\u001a\u00bf\u010b\u0ae4\u00a6\u0b9d\u1049\u0b70\u0b71\u0b72\u104a\u104b\u104c\u104d\u0b73\u0b74\u104e\u0b75\u0b76\u0b77\u104f\u0b78\u00a5\u00a6\u00a7\u00a8\u1050\u1051\u00a9\u1052\u1053\u00aa\u00ab\u00ac\u00ad\u00ae\u00af\u00b0\u00b1\u0ae4\u1048\u00b2\u0003\u1048\u00b2\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001" +
"\u0354\u0353\u0357\u0358\u044c\u044d\u044e\u045b\u045d\u0463\u0464\u0465\u105d\u0001\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0058\u063c\u10d9\u10e0\u10ea\u03b6\u03b7\u03b8\u03b9\u10eb\u03ba\u03bb\u03bc\u03bd\u03be\u03bf\u03c0\u03c1\u03c2\u03c3\u10f4\u0de0\u03c4" + "\u0001\u0001\u0001\u0001\u0008\u00c0\u006f\u010c\u00a7\u0ba9\u105c\u105d\u0001\u0001\u0010\u0288\u001b\u01a2\u0193\u010d\u01a2\u00a8\u0b9d\u00dd\u00dd\u0193\u0158\u106e\u0288\u001b\u0001\u0007\u010e\u1076\u1077\u1079\u107b\u1076\u0001\u0002\u0000\u0002\u0000\u0002\u0000\u0007\u0d31\u00c2\u010f\u0d31\u0c68\u0d31\u0002\u00c3\u000f\u0289\u001c\u01a3\u0194\u0aa8\u01a3\u00e0\u00e0\u0194\u0159\u1095\u0279\u0289\u001c\u0001\u0003\u001d" +
"\u0e35\u0ca1\u0ca3\u10f8\u0ca4\u0ca7\u0ca8\u10f9\u063c\u063c\u031e\u031f\u0320\u0321\u0325\u0329\u032a\u10fa\u10e7\u10fe\u10fd\u10e8\u10e9\u032b\u032c\u032d\u032e\u032f\u10f2\u0212\u10ff\u1100\u1101\u0331\u0332\u0333\u1102\u1105\u1108\u1109\u110c\u110f\u1110\u1113\u0334\u1116\u1119\u0335\u10de\u0336\u10df\u0337\u111c\u111d\u03b9\u111e\u111f\u1120\u1121\u1122\u1123\u1124\u1125\u1126\u1127\u0005\u10de\u10df\u0336\u0337\u0001\u0001" + "\u001d\u0003\u00c4\u109c\u0001\u0008\u0020\u00c5\u0a3f\u01d7\u00aa\u0c96\u0ae3\u0004\u0111\u0ae6\u0ae7\u0006\u0028\u00c6\u00ab\u10af\u027a\u0001\u001a\u028a\u0021\u01a4\u0195\u01da\u01a4\u00e2\u09c5\u09c6\u00e2\u0195\u015a\u01c0\u0c35\u10ca\u01b3\u0cbd\u0cbe\u01c1\u10cb\u0cbf\u10cc\u027b\u028a\u0021\u0001\u0001\u0001\u0005\u0cc9\u0114\u0ba1\u10d2\u0002\u10d4\u0003\u0000\u0000\u0005\"\u00c7\u00ad\u0ba2\u000b\u0cbe\u0023\u00c8" +
"\u0007\u10e7\u10e8\u10e9\u032b\u032e\u032f\u0001\u0001\u0001\u0001\u0007\u10f2\u0c99\u10f3\u0212\u0c9c\u0213\u0001\u0001\u0003\u10f7\u0330\u0001\u0001\u0001\u0003\u10fd\u032d\u0001\u0001\u0001\u0001\u0001\u0003\u0000\u0000\u0003\u0000\u0000\u0001\u0003\u0000\u0000\u0003\u0000\u0000\u0001\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001" + "\u0116\u0b4b\u00ae\u0ce3\u0cbe\u10e7\u00c8\u0001\u0009\u00c9\u007b\u0117\u007b\u0b4c\u00af\u10f1\u0cf1\u0001\u001b\u028b\u0024\u01c1\u01a5\u0196\u0ae7\u01a5\u00e3\u0c1e\u0d2a\u0c67\u0d2b\u0d2c\u0d2d\u00e3\u0196\u015b\u0d2f\u0d30\u0d31\u0d32\u0d33\u0d34\u027c\u028b\u0024\u0023\u0ae8\u1049\u0b70\u0b71\u0b72\u104a\u104b\u104c\u104d\u0b74\u104e\u0b75\u0b76\u0b77\u104f\u0b78\u00a5\u00a6\u00a7\u00a8\u1050\u1051\u00a9\u1052\u1053\u0ae3" +
"\u0046\u116e\u1175\u1192\u11ad\u0e92\u0ec1\u0eee\u11b4\u0f32\u0f9e\u11b5\u11b6\u11b7\u11c1\u11c8\u02b7\u11e7\u02b8\u02b9\u02ba\u02bb\u02bf\u02c0\u02c1\u11eb\u11be\u11bf\u11c0\u1173\u017f\u0181\u0182\u02c5\u11ea\u02c6\u11c6\u02c7\u11c7\u02c8\u11b2\u02c9\u11b3\u02ca\u11f0\u11f1\u11f2\u11f3\u11f4\u11f5\u11f6\u02d1\u02d2\u02d3\u02d4\u02d5\u02d6\u02d7\u11f7\u11fa\u11fb\u11fc\u11ff\u1202\u1205\u02d8\u02d9\u1208\u120b\u120e\u0005\u1173" + "\u00ab\u00ac\u00ad\u00ae\u00af\u00b0\u00b1\u0053\u0002\u0df3\u0003\u0cbf\u1135\u0001\u0007\u028c\u0025\u0ba6\u0df4\u028c\u0025\u0004\u0026\u011b\u00b1\u0002\u1143\u0001\u0012\u1156\u1157\u0c26\u0c37\u0c69\u0ce5\u0059\u0ae4\u0053\u1158\u1159\u115a\u115b\u115c\u115d\u115e\u115f\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u002f\u118f\u1194\u11a9\u11bc\u0af9\u0c22\u11c3\u0c7e\u0ca6\u0cc2\u0d35\u11c4\u11c5\u11c6\u0277" +
"\u02c5\u1174\u04f3\u0001\u0001\u000f\u1184\u1185\u1186\u1187\u1188\u1189\u118a\u118b\u118c\u118d\u118e\u118f\u1190\u1191\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u000e\u11a0\u11a1\u11a2\u11a3\u11a4\u11a5\u11a6\u11a7\u11a8\u11a9\u11aa\u11ab\u11ac\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0005\u11b2\u11b3\u02c9\u02ca\u0001\u0001\u0001\u0001\u0001\u0007" + "\u11d1\u0278\u0279\u027a\u027b\u027c\u11d5\u11d6\u1158\u11d7\u11d8\u11cd\u11ce\u11cf\u027d\u027e\u11d0\u11d4\u027f\u11c1\u0187\u11c2\u018a\u11d9\u11da\u11db\u11dc\u11dd\u11de\u11df\u11e0\u0003\u1192\u1193\u0001\u0001\u000b\u119f\u11a0\u11a1\u11a2\u11a3\u11a4\u11a5\u11a6\u11a7\u11a8\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\n\u11b3\u11b4\u11b5\u11b6\u11b7\u11b8\u11b9\u11ba\u11bb\u0001\u0001\u0001\u0001\u0001" +
"\u11be\u11bf\u11c0\u017f\u0181\u0182\u0001\u0001\u0001\u0005\u11c6\u11c7\u02c7\u02c8\u0001\u0001\r\u11d5\u11d8\u11db\u11de\u11e1\u11e4\u0285\u0288\u028b\u028e\u0291\u0294\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u11ea\u02c6\u0001\u0005\u11c6\u11c7\u02c7\u02c8\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u0000\u0000\u0001\u0001\u0003\u0000\u0000\u0003" + "\u0001\u0001\u0001\u0001\u0005\u11c1\u11c2\u0187\u018a\u0001\u0001\u0001\u0001\u0001\u0007\u11cd\u11ce\u11cf\u027d\u027e\u11d0\u0001\u0001\u0001\u0001\u0003\u11d4\u027f\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0017\u0513\u09c7\u0bcb\u0445\u0446\u0448\u0449\u044a\u044d\u11f8\u0287\u0288\u0289\u028a\u028b\u028c\u11f9\u0513\u11fa\u11fb\u11fc\u11fd\u0001\u0001\u0001\u0001\u0001\u0001\u0037\u1235" +
"\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0011\u04c4\u0037\u0f9f\u0362\u033f\u031e\u033f\u0170\u0170\u031e\u02b7\u0362\u1222\u048a\u04c4\u0037\u0001\u0021\u1244\u1247\u01ee\u0e8f\u0f9a\u0ed8\u0f9b\u0f9c\u0f9d\u0f9f\u0fa0\u0fa1\u0fa2\u0fa3\u0fa4\u124a\u0fa9\u0faa\u0fab\u0fac\u0fad\u0fae\u0faf\u0fb0\u0fb1\u0fb2\u0fb3\u0fb4\u0fb5\u0fb6\u0fb7\u0fb8\u0003\u0f99\u0251\u0003" + "\u123a\u1241\u1246\u0a3a\u0a3c\u0e96\u0a3d\u0a40\u0a41\u0e97\u0192\u0193\u0e98\u0194\u0195\u0196\u0e99\u1249\u0e80\u0e9f\u0e9d\u0e81\u0e82\u0e83\u0ea0\u0e9e\u0e84\u0197\u0e8d\u0e8f\u0ea1\u0ea2\u0ea3\u0ea4\u0ea5\u0ea6\u0ea7\u0eaa\u0ead\u0eae\u0eb1\u0eb4\u0eb5\u0eb8\u0ebb\u0ebc\u0ebf\u0ec2\u0e75\u0e77\u0e76\u0e78\u124c\u0005\u0e75\u0e76\u0e77\u0e78\u0007\u0e80\u0e81\u0e82\u0e83\u0e84\u0197\u0005\u0e8d\u0e8e\u0e8f\u0e90\u0003\u0e94" +
"\u0f95\u0149\u0003\u0f95\u0149\u002c\u1279\u0038\u013e\u01ef\u0d58\u0105\u0e0f\u127d\u0de2\u0de3\u0de4\u127e\u127f\u1280\u1281\u0de5\u0de6\u1282\u0de7\u0de8\u0de9\u1283\u0dea\u0104\u0105\u0106\u0107\u0108\u0109\u010a\u010b\u010c\u010d\u010e\u010f\u0110\u0111\u0112\u0113\u0114\u0d58\u127c\u0115\u0003\u127c\u0115\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0008\u013f\u00b7\u01f0\u0106\u0e1b\u128c\u128d\u0001\u0001\u0010\u04c8" + "\u0e95\u0003\u0e9d\u0e9e\u0001\u0077\u12c4\u12cb\u12da\u12e8\u12ed\u12f0\u0561\u0562\u0563\u0564\u0565\u0566\u0569\u056a\u056b\u056c\u056d\u056e\u056f\u0570\u0571\u0572\u0573\u0574\u12f3\u12fa\u0019\u12ff\u001a\u001b\u0590\u001c\u001d\u0591\u0020\u0592\u0028\u0021\u0593\"\u0023\u0024\u0594\u0025\u0026\u1302\u1307\u130c\u057c\u05a8\u05a9\u05a6\u057d\u0514\u057e\u059a\u055d\u0515\u057f\u05aa\u05ab\u05a7\u0580\u0516\u0581\u059c" +
"\u0039\u0340\u031f\u01f1\u0340\u0107\u0e0f\u0172\u0172\u031f\u02b8\u129e\u04c8\u0039\u0001\u0007\u01f2\u12a6\u12a7\u12a9\u12ab\u12a6\u0001\u0002\u0000\u0002\u0000\u0002\u0000\u0007\u0fa1\u0141\u01f3\u0fa1\u0ed9\u0fa1\u0002\u0142\u000f\u04ca\u003b\u0341\u0321\u01f5\u0341\u0175\u0175\u0321\u02b9\u12c5\u048c\u04ca\u003b\u0001\u0003\u003c\u003c\u0003\u0143\u12cc\u0001\u0008\u0040\u0144\u0ca6\u0380\u010d\u0f07\u0d57\u0004\u01fd\u0d59" + "\u055e\u0027\u058e\u058f\u0587\u0589\u0588\u058a\u059b\u059d\u0557\u0186\u0558\u0189\u05ac\u05ad\u05ae\u05af\u05b0\u05b1\u05b2\u05b3\u05b4\u05b5\u05b6\u05b7\u05b8\u05b9\u05ba\u05bd\u05be\u05c1\u05c4\u05c5\u05c8\u05cb\u05ce\u05d1\u05d4\u05d7\u0029\u05da\u002c\u002f\u05db\u0032\u05dc\u0035\u0038\u003b\u003e\u0041\u0007\u0514\u0515\u0516\u0027\u0517\u0518\u000f\u0529\u052a\u052b\u052c\u052d\u052e\u052f\u0530\u0531\u0532\u0533\u0534" +
"\u0d5a\u0006\u0042\u0145\u010e\u12df\u048d\u0001\u001a\u04da\u0043\u0342\u0325\u0383\u0342\u0177\u0c21\u0c22\u0177\u0325\u02bb\u0362\u0ea6\u12fa\u0351\u0f2e\u0f2f\u0363\u0364\u0f30\u0365\u048e\u04da\u0043\u0001\u0005\u0f3a\u0200\u0e13\u1300\u0002\u1302\u0003\u0000\u0000\u0005\u0045\u0146\u0110\u0e14\u000b\u0f2f\u0046\u0147\u0205\u0dbd\u0111\u0f54\u0f2f\u1315\u0147\u0001\u0009\u0148\u00c6\u0206\u00c6\u0dbe\u0112\u131f\u0f62\u0001" + "\u0535\u0536\u000e\u0545\u0546\u0547\u0548\u0549\u054a\u054b\u054c\u054d\u054e\u054f\u0550\u0551\u0005\u0557\u0558\u0186\u0189\u0003\u05a6\u05a7\u0003\u055d\u055e\u0007\u057c\u057d\u057e\u057f\u0580\u0581\u0005\u0587\u0588\u0589\u058a\u0003\u058e\u058f\u0005\u059a\u059b\u059c\u059d\u0005\u0587\u0588\u0589\u058a\u0003\u05a6\u05a7\u0017\u09fa\u09fb\u1326\u09fd\u09fe\u0a00\u0a01\u0a02\u0a04\u0a05\u0a06\u00bf\u00c0\u00c1\u00c2\u00c3" +
"\u001b\u04df\u0047\u0363\u0343\u0329\u0d5a\u0343\u0178\u0e8f\u0f9a\u0ed8\u0f9b\u0f9c\u0f9d\u0178\u0329\u02bf\u0f9f\u0fa0\u0fa1\u0fa2\u0fa3\u0fa4\u048f\u04df\u0047\u0023\u0d5b\u127d\u0de2\u0de3\u0de4\u127e\u127f\u1280\u1281\u0de6\u1282\u0de7\u0de8\u0de9\u1283\u0dea\u0104\u0105\u0106\u0107\u0108\u0109\u010a\u010b\u010c\u0d57\u010e\u010f\u0110\u0111\u0112\u0113\u0114\u0091\u0002\u0179\u0003\u0f30\u1363\u0001\u0007\u04e2\u0049\u0e18" + "\u00c4\u00c5\u00c6\u00c7\u00c8\u00c9\u0001\u0002\u1329\u0001\u0003\u0c67\u0d31\u0002\u05ac\u0002\u05ad\u0002\u05ae\u0003\u045f\u05af\u0002\u05b0\u0003\u0460\u05b1\u0002\u05b2\u0002\u05b3\u0002\u05b4\u0002\u05b5\u000e\u0461\u1351\u1374\u1381\u138e\u13b1\u13d4\u13e8\u13e9\u13ea\u13eb\u13ec\u13ed\u0006\u1357\u1364\u1371\u1372\u1373\u0007\u135e\u135f\u1360\u1361\u1362\u1363\u0001\u0001\u0001\u0001\u0001\u0001\u0007\u136b\u136c\u136d" +
"\u017d\u04e2\u0049\u0004\u004a\u0210\u0114\u0002\u1371\u0001\u0012\u1384\u1385\u0e97\u0ea8\u0eda\u0f56\u0097\u0d58\u0091\u1386\u1387\u1388\u1389\u138a\u138b\u138c\u138d\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u002f\u13bd\u13c1\u13d6\u13e9\u0d6b\u0e93\u13f0\u0eef\u0f17\u0f33\u0fa5\u13f1\u13f2\u13f3\u048a\u13fd\u048b\u048c\u048d\u048e\u048f\u0490\u0491\u1386\u1401\u04e3\u13fa\u13fb\u13fc\u0180\u0199\u0183\u1400" + "\u136e\u136f\u1370\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0007\u137b\u137c\u137d\u137e\u137f\u1380\u0001\u0001\u0001\u0001\u0001\u0001\u0007\u1388\u1389\u138a\u138b\u138c\u138d\u0001\u0001\u0001\u0001\u0001\u0001\u0006\u1394\u13a1\u13ae\u13af\u13b0\u0007\u139b\u139c\u139d\u139e\u139f\u13a0\u0001\u0001\u0001\u0001\u0001\u0001\u0007\u13a8\u13a9\u13aa\u13ab\u13ac\u13ad\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001" +
"\u0493\u13ee\u02ff\u13ef\u0300\u1402\u1403\u1404\u1405\u1406\u1407\u1408\u1409\u0003\u13c0\u04f4\u0001\u000b\u13cc\u13cd\u13ce\u13cf\u13d0\u13d1\u13d2\u13d3\u13d4\u13d5\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\n\u13e0\u13e1\u13e2\u13e3\u13e4\u13e5\u13e6\u13e7\u13e8\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0005\u13ee\u13ef\u02ff\u0300\u0001\u0001\u0001\u0001\u0001\u0007\u13fa\u13fb\u13fc\u0180" + "\u0001\u0006\u13b7\u13c4\u13d1\u13d2\u13d3\u0007\u13be\u13bf\u13c0\u13c1\u13c2\u13c3\u0001\u0001\u0001\u0001\u0001\u0001\u0007\u13cb\u13cc\u13cd\u13ce\u13cf\u13d0\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0006\u13da\u13e1\u1371\u1372\u1373\u0007\u135e\u135f\u1360\u1361\u1362\u1363\u0007\u136b\u136c\u136d\u136e\u136f\u1370\u0001\u0001\u0001\u0001\u0001\u0001\u0002\u05b7\u0003\u0462\u05b8\u0002\u05b9\u0002\u0b9d\u0002" +
"\u0199\u0183\u0001\u0001\u0001\u0003\u1400\u0493\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0017\u078a\u04c3\u0e3c\u06cf\u06d0\u06d2\u06d3\u06d4\u06d7\u1421\u04c4\u04c8\u04ca\u04da\u04df\u04e2\u1422\u078a\u04f5\u04e4\u1423\u1424\u0001\u0001\u0001\u0001\u0037\u145c\u1461\u1468\u146d\u0ca1\u0ca3\u10f8\u0ca4\u0ca7\u0ca8\u10f9\u031e\u031f\u0320\u0321\u0325\u0329\u032a\u1470\u10e7\u10fe\u10fd\u10e8\u10e9\u032b\u032c" + "\u0ba1\u0003\u0ca5\u0ca5\u0002\u0b9d\u0002\u0ba1\u0002\u0cbe\u0002\u1404\u0002\u0000\u0003\u1409\u140b\u0002\u0000\u0002\u0000\u0002\u140f\u0002\u0000\u0002\u1413\u0002\u0000\u0017\u142c\u142e\u1430\u1432\u1434\u1436\u1438\u143a\u143c\u143e\u1440\u1442\u1444\u1446\u1448\u144a\u144c\u144e\u1450\u1452\u1454\u1456\u0002\u0000\u0002\u0000\u0002\u0000\u0002\u0000\u0002\u0000\u0002\u0000\u0002\u0000\u0002\u0000\u0002\u0000\u0002\u0000" +
"\u032d\u032e\u032f\u10f2\u0212\u10ff\u1100\u1101\u0331\u0332\u0333\u1102\u1105\u1108\u1109\u110c\u110f\u1110\u1113\u0334\u1116\u1119\u0335\u10de\u0336\u10df\u0337\u1473\u0005\u10de\u10df\u0336\u0337\u0007\u10e7\u10e8\u10e9\u032b\u032e\u032f\u0005\u10f2\u10f3\u0212\u0213\u0003\u10f7\u0330\u0003\u10fd\u032d\u0001\u0077\u14eb\u14f2\u1501\u150f\u1514\u1517\u07d5\u07d6\u07d7\u07d8\u07d9\u07da\u07dd\u07de\u07df\u07e0\u07e1\u07e2\u07e3" + "\u0002\u0000\u0002\u0000\u0002\u0000\u0002\u0000\u0002\u0000\u0002\u0000\u0002\u0000\u0002\u0000\u0002\u0000\u0002\u0000\u0002\u0000\u0002\u0000\u0004\u145c\u145e\u1460\u0002\u0000\u0002\u0000\u0002\u0000\u0004\u1466\u146a\u1468\u0002\u1468\u0002\u0000\u0002\u0000\u0004\u1470\u1474\u1472\u0002\u1472\u0002\u0000\u0002\u0000\u0002\u1478\u0001\u0007\u1480\u1481\u1482\u1483\u1484\u1485\u0001\u0001\u0001\u0001\u0001\u0001\u0002\u1488" +
"\u07e4\u07e5\u07e6\u07e7\u07e8\u151a\u1521\u0037\u1526\u0038\u0039\u003a\u003b\u003c\u003f\u0040\u0041\u0042\u0043\u0044\u0045\u0046\u0047\u0048\u0049\u004a\u1529\u152e\u1533\u07f0\u080e\u080f\u080d\u07f1\u078b\u07f2\u0803\u07d2\u078c\u004b\u004c\u004d\u004e\u004f\u0050\u0051\u0052\u0053\u0054\u07fd\u0055\u07f8\u0059\u07f9\u005a\u0804\u005b\u07cc\\\u07cd\u005d\u0810\u0811\u0812\u0813\u0814\u0815\u0816\u005e\u005f\u0060\u0061" + "\u0001\u000c\u1495\u1496\u1497\u1498\u1499\u149a\u149b\u149c\u149d\u149e\u149f\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0004\u14a4\u14a5\u14a6\u0001\u0001\u0001\u0003\u14aa\u14ab\u0001\u0001\u0007\u14b3\u14b4\u14b5\u14b6\u14b7\u14b8\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u14bc\u14bd\u0001\u0001\u0004\u14c2\u14c3\u14c4\u0001\u0001\u0001\u0003\u14c8\u14c9\u0001\u0001\u0002\u14cc\u0001\u0002\u14cf\u0001" +
"\u0062\u0063\u0817\u0818\u081b\u081c\u081f\u0822\u0823\u0826\u0829\u082c\u082f\u0832\u0835\u0064\u0067\u0068\u006b\u006e\u006f\u0838\u0072\u0075\u0078\u007b\u007e\u0007\u078b\u078c\u0050\u0054\u078d\u04e7\u000f\u079e\u079f\u07a0\u07a1\u07a2\u07a3\u07a4\u07a5\u07a6\u07a7\u07a8\u07a9\u07aa\u07ab\u000e\u07ba\u07bb\u07bc\u07bd\u07be\u07bf\u07c0\u07c1\u07c2\u07c3\u07c4\u07c5\u07c6\u0005\u07cc\u07cd\\\u005d\u0003\u080d\u004e\u0003" + "\u0002\u14d2\u0001\u0002\u14d5\u0001\u0004\u14da\u14db\u14dc\u0001\u0001\u0001\u0002\u14df\u0001\u0003\u14e3\u14e4\u0001\u0001\u0002\u14e7\u0001\u0004\u14ec\u14ed\u14ee\u0001\u0001\u0001\u0002\u14f1\u0001\u0004\u14f6\u14f7\u14f8\u0001\u0001\u0001\u0002\u14fb\u0001\u0002\u14fe\u0001\u0002\u1501\u0001\u0002\u1504\u0001\u0002\u1507\u0001\u0002\u150a\u0001\u0002\u150d\u0001\u0002\u1510\u0001\u0002\u1513\u0001\u0006\u151a\u151b\u151c" +
"\u07d2\u0053\u0007\u07f0\u07f1\u07f2\u004b\u004f\u0051\u0005\u07f8\u07f9\u0059\u005a\u0003\u07fd\u0055\u0005\u0803\u0804\u0052\u005b\u0005\u07f8\u07f9\u0059\u005a\u0003\u080d\u004e\u0017\u0c5b\u0c5c\u154d\u0c5e\u0c5f\u0c61\u0c62\u0c63\u0c65\u0c66\u0c67\u013e\u013f\u0140\u0141\u0142\u0143\u0144\u0145\u0146\u0147\u0148\u0001\u0002\u1550\u0001\u0003\u0ed8\u0fa1\u0002\u0810\u0002\u0811\u0002\u0812\u0003\u06e4\u0813\u0002\u0814\u0003" + "\u151d\u151e\u0001\u0001\u0001\u0001\u0001\u0002\u1521\u0001\u0002\u1524\u0001\u0005\u152a\u152b\u152c\u152d\u0001\u0001\u0001\u0001\u0003\u1531\u1532\u0001\u0001\u0005\u1538\u1539\u153a\u153b\u0001\u0001\u0001\u0001\u0003\u153f\u1540\u0001\u0001\u0011\u1552\u1553\u1554\u1555\u1556\u1557\u1558\u1559\u155a\u155b\u155c\u155d\u155e\u155f\u1560\u1561\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001" +
"\u06e5\u0815\u0002\u0816\u0002\u005e\u0002\u005f\u0002\u0060\u000e\u04e5\u1578\u159b\u15a8\u15b5\u15d8\u15fb\u160f\u1610\u1611\u1612\u1613\u1614\u0006\u157e\u158b\u1598\u1599\u159a\u0007\u1585\u1586\u1587\u1588\u1589\u158a\u0001\u0001\u0001\u0001\u0001\u0001\u0007\u1592\u1593\u1594\u1595\u1596\u1597\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0007\u15a2\u15a3\u15a4\u15a5\u15a6\u15a7\u0001\u0001\u0001\u0001\u0001\u0001" + "\u0001\u0001\u0002\u155d\u0011\u1575\u1576\u1577\u1578\u1579\u157a\u157b\u157c\u157d\u157e\u157f\u1580\u1581\u1582\u1583\u1584\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0002\u157c\u000c\u1593\u1594\u1595\u1596\u1597\u1598\u1599\u159a\u159b\u159c\u159d\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u15a1\u15a2\u0001\u0001\u0003\u15a6\u15a7\u0001\u0001" +
"\u0007\u15af\u15b0\u15b1\u15b2\u15b3\u15b4\u0001\u0001\u0001\u0001\u0001\u0001\u0006\u15bb\u15c8\u15d5\u15d6\u15d7\u0007\u15c2\u15c3\u15c4\u15c5\u15c6\u15c7\u0001\u0001\u0001\u0001\u0001\u0001\u0007\u15cf\u15d0\u15d1\u15d2\u15d3\u15d4\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0006\u15de\u15eb\u15f8\u15f9\u15fa\u0007\u15e5\u15e6\u15e7\u15e8\u15e9\u15ea\u0001\u0001\u0001\u0001\u0001\u0001\u0007\u15f2\u15f3\u15f4\u15f5" + "\u0003\u15ab\u15ac\u0001\u0001\u0002\u15af\u0001\u0006\u155e\u155f\u1560\u1557\u1561\u0002\u1584\u0002\u15ba\u0001\u0002\u15bd\u0001\u0002\u15c0\u0001\u0002\u15c3\u0001\u0004\u15c8\u15c9\u15ca\u0001\u0001\u0001\u0004\u15cf\u15d0\u15d1\u0001\u0001\u0001\u0005\u15d7\u15d8\u15d9\u15da\u0001\u0001\u0001\u0001\u0004\u15df\u15e0\u15e1\u0001\u0001\u0001\u0009\u15eb\u15ec\u15ed\u15ee\u15ef\u15f0\u15f1\u15f2\u0001\u0001\u0001\u0001\u0001" +
"\u15f6\u15f7\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0006\u1601\u1608\u1598\u1599\u159a\u0007\u1585\u1586\u1587\u1588\u1589\u158a\u0007\u1592\u1593\u1594\u1595\u1596\u1597\u0001\u0001\u0001\u0001\u0001\u0001\u0002\u0062\u0003\u04e6\u0063\u0002\u0817\u0002\u0e0f\u0002\u0e13\u0003\u0f16\u0f16\u0002\u0e0f\u0008\u162d\u162e\u162f\u162d\u163e\u1640\u162d\u0001\u0001\u000f\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + "\u0001\u0001\u0001\u0002\u15ec\u0006\u15fb\u15fc\u15fd\u15fe\u15ff\u0001\u0001\u0001\u0001\u0001\u0009\u1609\u160a\u160b\u160c\u160d\u160e\u160f\u1610\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u1610\u160c\u0008\u161c\u161d\u161e\u161f\u1620\u1621\u1622\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0004\u1627\u1628\u1629\u0001\u0001\u0001\u0002\u162c\u0001\u0007\u1634\u1635\u1636\u1637\u1638\u1639\u0001\u0001\u0001\u0001" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0002\u0000\u0002\u0000\u0002\u1644\u0019\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0007\u0c69\u0d1b\u0d5f\u1664\u1665\u0d5f\u0001\u0001\u0007\u166d\u166f\u1670\u166d\u166d\u1672\u0002\u0000\u0001\u0002\u0000\u0001\u0002\u1675\u0010\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + "\u0001\u0001\u0005\u163f\u1640\u1641\u1642\u0001\u0001\u0001\u0001\u0005\u1648\u1649\u164a\u164b\u0001\u0001\u0001\u0001\u0002\u164b\u0008\u1656\u1657\u1658\u1659\u165a\u165b\u165c\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u1660\u1661\u0001\u0001\u0015\u1677\u1678\u1679\u167a\u167b\u167c\u167d\u167e\u167f\u1680\u1681\u1682\u1683\u1684\u1685\u1686\u1687\u1688\u1689\u168a\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001" +
"\u0000\u0000\u0000\u0000\u0000\u0002\u0d1c\u0003\u0e13\u168a\u0001\u0003\u0334\u168e\u0001\u0003\u0d1d\u1692\u0010\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0007\u0c6a\u0d1e\u1664\u16a9\u1665\u16a9\u0001\u0004\u0c6b\u0d1f\u16ae\u0001\u0002\u0d20\u0005\u0c6c\u16b6\u16b7\u16c7\u0001\u0010\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001" + "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0002\u1678\u0003\u1685\u1686\u0004\u167e\u1688\u1687\u0002\u1680\n\u16a0\u16a1\u16a2\u16a3\u16a4\u16a5\u16a6\u16a7\u16a8\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0006\u16af\u16b0\u16b1\u16b2\u16b3\u0001\u0001\u0001\u0001\u0001\u0006\u16ba\u16bb\u16bc\u16bd\u16be\u0001\u0001\u0001\u0001\u0001\u0005\u16c4\u16c5\u16c6\u16c7\u0001\u0001\u0001\u0001" +
"\u0004\u16cc\u16cd\u16ce\u0001\u0001\u0019\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0003\u0f2f\u16ea\u0001\u0004\u16ef\u16f0\u16ef\u0001\u0001\u0007\u168e\u0fb8\u0335\u16f8\u168e\u0fb8\u0013\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0004\u0c6d\u0d21\u170f\u0019" + "\u0003\u16cb\u16cc\u0001\u0001\u0005\u16d2\u16d3\u16d4\u16d5\u0001\u0001\u0001\u0001\u0002\u16d8\u0001\u0002\u16a4\u0002\u16c5\u0003\u16e0\u16e1\u0001\u0001\u0003\u1159\u16e5\u0001\u0003\u0a44\u16e9\u0001\u0003\u115a\u16ed\u0001\u0003\u0a45\u16f1\u0001\u0002\u16f4\u0001\u0004\u0ec3\u115b\u16f9\u0001\u0005\u115c\u11de\u11fa\u16ff\u0001\u0002\u1702\u0001\u0002\u0ec4\u0002\u1707\u0001\u0008\u0ec5\u11fb\u1710\u1711\u1712\u1713\u1714" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u000f\u0d22\u162f\u1644\u1675\u1692\u16b7\u16ce\u16f8\u170f\u1737\u1749\u1762\u1692\u1772\u0012\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0019\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + "\u0001\u0001\u0001\u0001\u0001\u0002\u1717\u0001\u0002\u171a\u0001\u0004\u11df\u0b6f\u171f\u0001\u0004\u11e0\u0b6f\u1724\u0001\u0002\u1710\u0002\u115d\u0002\u172b\u0001\u0002\u172e\u0001\u0002\u1731\u0001\u0002\u1734\u0001\u0003\u0ec6\u1738\u0001\u0002\u0ec6\u0002\u173d\u0001\u0002\u1740\u0001\u0002\u1743\u0001\u0002\u1746\u0001\u0002\u1749\u0001\u0002\u174c\u0001\u0002\u174f\u0001\u0002\u1752\u0001\u0002\u1755\u0001\u0002\u1758" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0010\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0010\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0002\u1784\u0001\u0002\u1749\u0006\u178d\u06f1\u178f\u1790\u1762\u0002\u0000\u0001\u0001\u0002\u1793\u0002\u0000\u0005\u06f2\u06f2\u168e\u0334\u0004\u179e\u1692\u1793\u0002\u0000" + "\u0001\u0004\u175d\u0ec7\u115e\u0001\u0003\u1761\u0ec8\u0001\u0002\u1764\u0001\u0002\u1767\u0001\u0002\u176a\u0001\u0002\u176d\u0001\u0002\u1770\u0001\u0005\u11fc\u124c\u1711\u1776\u0001\u0004\u0ec9\u1712\u1776\u0002\u177d\u0001\u0002\u1780\u0001\u0002\u1783\u0001\u0002\u1786\u0001\u0002\u1789\u0001\u0002\u178c\u0001\u0002\u178f\u0001\u0003\u0eca\u1793\u0001\u0002\u0ecb\u0002\u0ecc\u0002\u0ecd\u0016\u05df\u0af3\u0b35\u0b79\u0bad" +
"\u0002\u16cc\u0002\u1772\u0002\u17a6\u0002\u0000\u0003\u17ab\u17ad\u0002\u0000\u0002\u0000\u0002\u17b1\u0002\u0000\u0002\u17b5\u0002\u0000\u0017\u17ce\u17d0\u17d2\u17d4\u17d6\u17d8\u17da\u17dc\u17de\u17e0\u17e2\u17e4\u17e6\u17e8\u17ea\u17ec\u17ee\u17f0\u17f2\u17f4\u17f6\u17f8\u0002\u0000\u0002\u0000\u0002\u0000\u0002\u0000\u0002\u0000\u0002\u0000\u0002\u0000\u0002\u0000\u0002\u0000\u0002\u0000\u0002\u0000\u0002\u0000\u0002\u0000" + "\u0bcc\u0c0b\u0d78\u1329\u16e5\u16e9\u16ed\u16f1\u16f9\u16ff\u1713\u171f\u1724\u1738\u1793\u17b0\u0001\n\u09c8\u0a46\u0aaf\u0d79\u0ece\u115f\u11fd\u1714\u17b0\u0002\u17bd\u0001\u00ac\u186a\u03d5\u0442\u048f\u0559\u0443\u0444\u01b3\u0a8e\u0a2e\u0a8f\u186f\u1873\u1876\u1879\u187c\u187f\u1882\u1885\u1888\u188b\u0b6d\u11d7\u0bc5\u0bf5\u055f\u0560\u09f8\u0a2d\u0fee\u188e\u0ae4\u0b9d\u188f\u0a3f\u10ca\u0ba1\u0ba2\u0ae7\u0ba6\u1890" +
"\u0002\u0000\u0002\u0000\u0002\u0000\u0002\u0000\u0002\u0000\u0002\u0000\u0002\u0000\u0002\u0000\u0002\u0000\u0004\u17fe\u1800\u1802\u0002\u0000\u0002\u0000\u0002\u0000\u0004\u1808\u180c\u180a\u0002\u180a\u0002\u0000\u0002\u0000\u0004\u1812\u1816\u1814\u0002\u1814\u0002\u0000\u0002\u0000\u0008\u1820\u1835\u1836\u1837\u1838\u1837\u1838\u0015\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + "\u0a91\u03f1\u0a93\u1891\u0cc9\u1899\u189a\u189b\u189c\u189d\u189e\u189f\u18a0\u18a1\u18a2\u18a3\u18a4\u18a5\u18a6\u18a7\u18a8\u18b4\u18bb\u18c1\u18c8\u18ce\u18d3\u18d9\u18e5\u18eb\u18f1\u18f8\u1905\u186f\u1873\u1876\u1879\u187c\u187f\u1882\u1885\u1888\u188b\u186f\u1873\u1876\u1879\u187c\u187f\u1882\u1885\u1888\u188b\u190b\u190c\u190d\u190e\u190f\u1910\u1911\u1912\u1913\u1914\u1915\u1916\u1917\u1918\u1495\u1496\u1497\u1919\u191a" +
"\u0000\u0000\u0000\u0000\u0000\u0001\u0001\u0001\u0015\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0005\u1852\u1853\u1854\u1855\u0001\u0001\u0001\u0001\u0002\u1858\u0001\u0002\u185b\u0010\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0004\u1853\u186f\u1870\u0001\u0001\u0002\u1873\u0001\u0002\u1854\n\u1880" + "\u191b\u1498\u191f\u1920\u1499\u149a\u1921\u1922\u1926\u149b\u192a\u149c\u192e\u149d\u149e\u149f\u192f\u1930\u1934\u1938\u1939\u193a\u193b\u193c\u193d\u193e\u193f\u1940\u1941\u1942\u1943\u1944\u1945\u1946\u1947\u1157\u1891\u0cd7\u0b9b\u0ba7\u0b9c\u0baa\u1948\u1949\u194a\u194b\u194c\u194d\u16f4\u1702\u194e\u194f\u1950\u1951\u1952\u0ec7\u0ec8\u1953\u0005\u0000\u0000\u0000\u0000\u0004\u0000\u0000\u0000\u0003\u0000\u0000\u0003\u0000" +
"\u1881\u1882\u1883\u1884\u189a\u1883\u1884\u189a\u0001\u0001\u0001\u0001\u0016\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0016\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0003\u18b3\u18b3\u0001\u0002\u18b6\u0001\u0002\u18b9\u0001\u0004\u18be\u18d0\u18d0\u0012\u0000" + "\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0001\u0001\u0001\u0008\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u000c\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0007\u0000\u0000\u0000\u0000\u0000\u0000\u0006\u0000\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0006\u1855\u18d7\u18ea\u18fd\u18fd\u0013\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0013\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0013\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + "\u0000\u0007\u0000\u0000\u0000\u0000\u0000\u0000\u0006\u0000\u0000\u0000\u0000\u0000\u0005\u0000\u0000\u0000\u0000\u0006\u0000\u0000\u0000\u0000\u0000\u000c\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0006\u0000\u0000\u0000\u0000\u0000\u0006\u0000\u0000\u0000\u0000\u0000\u0007\u0000\u0000\u0000\u0000\u0000\u0000\r\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0006\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0009\u1919\u191a\u1881\u18d7\u191b\u192b\u192c\u192c\u0001\u0001\u0010\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0001\n\u1937\u1882\u18b6\u18ea\u1938\u192b\u1836\u192b\u1836\u0001\u0011\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\n\u1953\u1954\u1883\u18fd\u1955\u192c" + "\u0000\u0000\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0004\u0000\u0000\u0000\u0001\u0001\u0001\u0004\u0000\u0000\u0000\u0004\u0000\u0000\u0000\u0004\u0000\u0000\u0000\u0001\u0001\u0004\u0000\u0000\u0000\u0004\u0000\u0000\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001" +
"\u1837\u192c\u1837\u0001\u0001\u0010\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0002\u1967\u0001\u0007\u1835\u1882\u1883\u196f\u1970\u1881\u0001\u0001\u0002\u1880\u0009\u1838\u1870\u1884\u18d0\u192b\u192c\u197c\u192c\u0013\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0006\u189a\u1836\u1837\u1995\u1837\u001c\u0000\u0000" + "\u0001\u0001\u0001\u0001\u002f\u0ce4\u0a9c\u1983\u1984\u1985\u1986\u1987\u1988\u1989\u198a\u198b\u198c\u198d\u198e\u198f\u1990\u1991\u1992\u1993\u1994\u1995\u1996\u1997\u1998\u1999\u199a\u0cd7\u0b9b\u0ba7\u0b9c\u0baa\u194a\u194b\u194c\u194d\u199b\u199c\u199d\u199e\u199f\u19a0\u19a1\u19a2\u19a3\u19a4\u19a5\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\n\u1953\u1954\u1883\u18fd\u192c\u1837\u1955\u192c\u1837\u0009\u1838\u1870\u1884\u18d0\u192b\u192c\u192c\u197c\u0006\u189a\u1836\u1837\u1837\u1995\u000c\u19d6\u19d7\u19d8\u19d9\u19da\u19db\u19dc\u19dd\u19de\u19df\u19e0\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001" + "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001").toCharArray();
"\u0001\u0004\u19e5\u19e6\u19e7\u0001\u0001\u0001\u0003\u19eb\u19ec\u0001\u0001\u0007\u19f4\u19f5\u19f6\u19f7\u19f8\u19f9\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u19fd\u19fe\u0001\u0001\u0004\u1a03\u1a04\u1a05\u0001\u0001\u0001\u0003\u1a09\u1a0a\u0001\u0001\u0002\u1a0d\u0001\u0002\u1a10\u0001\u0002\u1a13\u0001\u0002\u1a16\u0001\u0004\u1a1b\u1a1c\u1a1d\u0001\u0001\u0001\u0002\u1a20\u0001\u0003\u1a24\u1a25\u0001\u0001\u0002\u1a28" +
"\u0001\u0004\u1a2d\u1a2e\u1a2f\u0001\u0001\u0001\u0002\u1a32\u0001\u0004\u1a37\u1a38\u1a39\u0001\u0001\u0001\u0002\u1a3c\u0001\u0002\u1a3f\u0001\u0002\u1a42\u0001\u0002\u1a45\u0001\u0002\u1a48\u0001\u0002\u1a4b\u0001\u0002\u1a4e\u0001\u0002\u1a51\u0001\u0002\u1a54\u0001\u0006\u1a5b\u1a5c\u1a5d\u1a5e\u1a5f\u0001\u0001\u0001\u0001\u0001\u0002\u1a62\u0001\u0002\u1a65\u0001\u0005\u1a6b\u1a6c\u1a6d\u1a6e\u0001\u0001\u0001\u0001\u0003" +
"\u1a72\u1a73\u0001\u0001\u0005\u1a79\u1a7a\u1a7b\u1a7c\u0001\u0001\u0001\u0001\u0003\u1a80\u1a81\u0001\u0001\u0011\u1a93\u1a94\u1a95\u1a96\u1a97\u1a98\u1a99\u1a9a\u1a9b\u1a9c\u1a9d\u1a9e\u1a9f\u1aa0\u1aa1\u1aa2\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0002\u1a9e\u0011\u1ab6\u1ab7\u1ab8\u1ab9\u1aba\u1abb\u1abc\u1abd\u1abe\u1abf\u1ac0\u1ac1\u1ac2\u1ac3\u1ac4\u1ac5\u0001\u0001" +
"\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0002\u1abd\u000c\u1ad4\u1ad5\u1ad6\u1ad7\u1ad8\u1ad9\u1ada\u1adb\u1adc\u1add\u1ade\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u1ae2\u1ae3\u0001\u0001\u0003\u1ae7\u1ae8\u0001\u0001\u0003\u1aec\u1aed\u0001\u0001\u0002\u1af0\u0001\u0006\u1a9f\u1aa0\u1aa1\u1a98\u1aa2\u0002\u1ac5\u0002\u1afb\u0001\u0002\u1afe\u0001\u0002" +
"\u1b01\u0001\u0002\u1b04\u0001\u0004\u1b09\u1b0a\u1b0b\u0001\u0001\u0001\u0004\u1b10\u1b11\u1b12\u0001\u0001\u0001\u0005\u1b18\u1b19\u1b1a\u1b1b\u0001\u0001\u0001\u0001\u0004\u1b20\u1b21\u1b22\u0001\u0001\u0001\u0009\u1b2c\u1b2d\u1b2e\u1b2f\u1b30\u1b31\u1b32\u1b33\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0002\u1b2d\u0006\u1b3c\u1b3d\u1b3e\u1b3f\u1b40\u0001\u0001\u0001\u0001\u0001\u0009\u1b4a\u1b4b\u1b4c\u1b4d\u1b4e\u1b4f" +
"\u1b50\u1b51\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u1b51\u1b4d\u0008\u1b5d\u1b5e\u1b5f\u1b60\u1b61\u1b62\u1b63\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0004\u1b68\u1b69\u1b6a\u0001\u0001\u0001\u0002\u1b6d\u0001\u0007\u1b75\u1b76\u1b77\u1b78\u1b79\u1b7a\u0001\u0001\u0001\u0001\u0001\u0001\u0005\u1b80\u1b81\u1b82\u1b83\u0001\u0001\u0001\u0001\u0005\u1b89\u1b8a\u1b8b\u1b8c\u0001\u0001\u0001\u0001\u0002\u1b8c\u0008" +
"\u1b97\u1b98\u1b99\u1b9a\u1b9b\u1b9c\u1b9d\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u1ba1\u1ba2\u0001\u0001\u0015\u1bb8\u1bb9\u1bba\u1bbb\u1bbc\u1bbd\u1bbe\u1bbf\u1bc0\u1bc1\u1bc2\u1bc3\u1bc4\u1bc5\u1bc6\u1bc7\u1bc8\u1bc9\u1bca\u1bcb\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0002\u1bb9\u0003\u1bc6\u1bc7\u0004\u1bbf\u1bc9\u1bc8\u0002\u1bc1\n" +
"\u1be1\u1be2\u1be3\u1be4\u1be5\u1be6\u1be7\u1be8\u1be9\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0006\u1bf0\u1bf1\u1bf2\u1bf3\u1bf4\u0001\u0001\u0001\u0001\u0001\u0006\u1bfb\u1bfc\u1bfd\u1bfe\u1bff\u0001\u0001\u0001\u0001\u0001\u0005\u1c05\u1c06\u1c07\u1c08\u0001\u0001\u0001\u0001\u0003\u1c0c\u1c0d\u0001\u0001\u0005\u1c13\u1c14\u1c15\u1c16\u0001\u0001\u0001\u0001\u0002\u1c19\u0001\u0002\u1be5\u0002\u1c06\u0003\u1c21" +
"\u1c22\u0001\u0001\u0003\u1387\u1c26\u0001\u0003\u0cab\u1c2a\u0001\u0003\u1388\u1c2e\u0001\u0003\u0cac\u1c32\u0001\u0002\u1c35\u0001\u0004\u111c\u1389\u1c3a\u0001\u0005\u138a\u1407\u04f5\u1c40\u0001\u0002\u1c43\u0001\u0002\u111d\u0002\u1c48\u0001\u0008\u111e\u04e4\u1c51\u1c52\u1c53\u1c54\u1c55\u0001\u0001\u0001\u0001\u0001\u0002\u1c58\u0001\u0002\u1c5b\u0001\u0004\u1408\u0de1\u1c60\u0001\u0004\u1409\u0de1\u1c65\u0001\u0002\u1c51" +
"\u0002\u138b\u0002\u1c6c\u0001\u0002\u1c6f\u0001\u0002\u1c72\u0001\u0002\u1c75\u0001\u0003\u111f\u1c79\u0001\u0002\u111f\u0002\u1c7e\u0001\u0002\u1c81\u0001\u0002\u1c84\u0001\u0002\u1c87\u0001\u0002\u1c8a\u0001\u0002\u1c8d\u0001\u0002\u1c90\u0001\u0002\u1c93\u0001\u0002\u1c96\u0001\u0002\u1c99\u0001\u0004\u1c9e\u1120\u138c\u0001\u0003\u1ca2\u1121\u0001\u0002\u1ca5\u0001\u0002\u1ca8\u0001\u0002\u1cab\u0001\u0002\u1cae\u0001\u0002" +
"\u1cb1\u0001\u0005\u1423\u1473\u1c52\u1cb7\u0001\u0004\u1122\u1c53\u1cb7\u0002\u1cbe\u0001\u0002\u1cc1\u0001\u0002\u1cc4\u0001\u0002\u1cc7\u0001\u0002\u1cca\u0001\u0002\u1ccd\u0001\u0002\u1cd0\u0001\u0003\u1123\u1cd4\u0001\u0002\u1124\u0002\u1125\u0002\u1126\u0016\u083b\u0d65\u0da7\u0deb\u0e1e\u0e3d\u0e7c\u0fe8\u1550\u1c26\u1c2a\u1c2e\u1c32\u1c3a\u1c40\u1c54\u1c60\u1c65\u1c79\u1cd4\u1cf1\u0001\n\u0c23\u0cad\u0d23\u0fe9\u1127" +
"\u138d\u1424\u1c55\u1cf1\u0002\u1cfe\u0001\u00f6\u1df5\u066c\u06cc\u0706\u07ce\u06cd\u06ce\u0351\u0cfd\u0c95\u0cfe\u1dfa\u1dfe\u1e01\u1e04\u1e07\u1e0a\u1e0d\u1e10\u1e13\u1e16\u1e19\u0ddf\u1401\u0e36\u0e66\u07d3\u07d4\u0c59\u0c94\u1222\u1e1e\u0d58\u0e0f\u1e1f\u0ca6\u12fa\u0e13\u0e14\u0d5a\u0e18\u1e20\u0d00\u0688\u0d02\u1e21\u0f3a\u1e29\u1e2a\u1e2b\u1e2c\u1e2d\u1e2e\u1e2f\u1e30\u1e31\u1e32\u1e33\u1e34\u1e35\u1e36\u1e37\u162d\u1e38" +
"\u1e39\u1e3b\u1e3c\u0d1f\u1e3d\u1e3e\u1e3f\u1e40\u1e41\u16ef\u16ea\u1e43\u1e44\u1e46\u1e47\u179e\u1e48\u0fb7\u0d22\u1640\u0d1e\u1e49\u1665\u166f\u16b6\u0d1f\u1e4b\u1e57\u1e5e\u1e64\u1e6b\u1e71\u1e76\u1e7c\u1e88\u1e8e\u1e94\u1e9b\u1ea8\u1884\u189a\u1967\u1eae\u191b\u1eaf\u1eb0\u1870\u1eb1\u1eb2\u1eb3\u1eb4\u1eb5\u18b3\u1995\u1eb6\u1eb7\u1eb8\u18d0\u1eb9\u1eba\u1ebb\u192b\u192c\u1dfa\u1dfe\u1e01\u1e04\u1e07\u1e0a\u1e0d\u1e10\u1e13" +
"\u1e16\u1938\u1ebc\u197c\u1995\u1ebd\u1955\u1dfa\u1dfe\u1e01\u1e04\u1e07\u1e0a\u1e0d\u1e10\u1e13\u1e16\u1ebe\u1ebf\u1ec0\u1ec1\u1ec2\u1ec3\u1ec4\u1ec5\u1ec6\u1ec7\u1ec8\u1ec9\u1eca\u1ecb\u19d6\u19d7\u19d8\u1ecc\u1ecd\u1ece\u19d9\u1ed2\u1ed3\u19da\u19db\u1ed4\u1ed5\u1ed9\u19dc\u1edd\u19dd\u1ee1\u19de\u19df\u19e0\u1ee2\u1ee3\u1ee7\u1eeb\u1eec\u1eed\u1eee\u1eef\u1ef0\u1ef1\u1ef2\u1ef3\u1ef4\u1ef5\u1ef6\u1ef7\u1ef8\u1ef9\u1efa\u1efb" +
"\u1efd\u1eff\u1f01\u1f03\u1385\u1e21\u0f48\u0e0d\u0e19\u0e0e\u0e1c\u1f05\u1f06\u1f07\u1f08\u1f09\u1f0a\u1c35\u111c\u04f5\u1f0b\u1f0c\u1f0d\u1f0e\u1f0f\u1120\u1121\u1423\u1f10\u1cd4\u138c\u1125\u1126\u083b\u1672\u1f11\u1f12\u0005\u0000\u0000\u0000\u0000\u0004\u0000\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000" +
"\u0000\u0005\u0000\u0000\u0000\u0000\u0001\u0001\u0001\u0008\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0002\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0002\u0000\u0001\u0002\u0000\u0001\u0001\u0001\u0002\u0000\u000c\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0007\u0000\u0000\u0000\u0000\u0000\u0000\u0006\u0000" +
"\u0000\u0000\u0000\u0000\u0007\u0000\u0000\u0000\u0000\u0000\u0000\u0006\u0000\u0000\u0000\u0000\u0000\u0005\u0000\u0000\u0000\u0000\u0006\u0000\u0000\u0000\u0000\u0000\u000c\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0006\u0000\u0000\u0000\u0000\u0000\u0006\u0000\u0000\u0000\u0000\u0000\u0007\u0000\u0000\u0000\u0000\u0000\u0000\r\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0006\u0000\u0000\u0000\u0000\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0004\u0000\u0000\u0000\u0001\u0001\u0001\u0004\u0000\u0000\u0000\u0004\u0000\u0000\u0000\u0004\u0000\u0000\u0000\u0001\u0001\u0004\u0000\u0000\u0000\u0004\u0000\u0000\u0000\u0001\u0001\u0001\u0001\u0001" +
"\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0002\u0000\u0002\u0000\u0002\u0000\u0002\u0000\u0002\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u000b\u1f1e\u1f1f\u1f20\u1f21\u1f22\u1f23\u1f24\u1f25\u1f26\u1f27\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u000b\u1f33\u1f34\u1f35\u1f36\u1f37\u1f38\u1f39\u1f3a\u1f3b\u1f3c\u0001\u0001\u0001\u0001\u0001" +
"\u0001\u0001\u0001\u0001\u0001\u000b\u1f48\u1f49\u1f4a\u1f4b\u1f4c\u1f4d\u1f4e\u1f4f\u1f50\u1f51\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u000b\u1f5d\u1f5e\u1f5f\u1f60\u1f61\u1f62\u1f63\u1f64\u1f65\u1f66\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u000b\u1f72\u1f73\u1f74\u1f75\u1f76\u1f77\u1f78\u1f79\u1f7a\u1f7b\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u000b\u1f87\u1f88\u1f89" +
"\u1f8a\u1f8b\u1f8c\u1f8d\u1f8e\u1f8f\u1f90\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u000b\u1f9c\u1f9d\u1f9e\u1f9f\u1fa0\u1fa1\u1fa2\u1fa3\u1fa4\u1fa5\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0071\u0f55\u0d0b\u2017\u201a\u201d\u201e\u201f\u2020\u2021\u2022\u2023\u2024\u1ec6\u1ec7\u2025\u2026\u2027\u2028\u2029\u202a\u202b\u202c\u202d\u202e\u202f\u2030\u2031\u2032\u2033\u2034\u2035\u2036\u1ef1" +
"\u1ec0\u2037\u1ec1\u2038\u2039\u1ef8\u203a\u203b\u203c\u203d\u203e\u203f\u2040\u2041\u2042\u2043\u2044\u2045\u2046\u2047\u2048\u2049\u204a\u204b\u204c\u204d\u204e\u204f\u2050\u2051\u0f48\u2052\u2053\u2054\u2055\u2056\u2057\u2058\u2059\u205a\u205b\u205c\u205d\u205e\u205f\u2061\u2063\u2064\u2067\u206a\u206d\u206e\u0f48\u0e0d\u0e19\u0e0e\u0e1c\u1f07\u1f08\u1f09\u1f0a\u1c43\u1c48\u1c9e\u1ca2\u1ca5\u1ca8\u206f\u2070\u2071\u2072\u2073" +
"\u2074\u2075\u2076\u2077\u2078\u2079\u207a\u0003\u0000\u0000\u0003\u0000\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001" +
"\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0002\u0000\u0002\u0000\u0001\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0006\u2080\u2083\u2086\u2089\u208c\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000\u0003\u0000\u0000").toCharArray();
public static final int accent_aigu = 1; public static final int accent_aigu = 1;
public static final int accent_arrows = 130; public static final int accent_arrows = 68;
public static final int accent_bar = 153; public static final int accent_bar = 91;
public static final int accent_box = 208; public static final int accent_box = 127;
public static final int accent_caron = 231; public static final int accent_caron = 150;
public static final int accent_cedille = 304; public static final int accent_cedille = 179;
public static final int accent_circonflexe = 330; public static final int accent_circonflexe = 202;
public static final int accent_dot_above = 412; public static final int accent_dot_above = 245;
public static final int accent_dot_below = 541; public static final int accent_dot_below = 284;
public static final int accent_double_aigu = 596; public static final int accent_double_aigu = 309;
public static final int accent_double_grave = 625; public static final int accent_grave = 336;
public static final int accent_grave = 664; public static final int accent_hook_above = 349;
public static final int accent_hook_above = 730; public static final int accent_horn = 374;
public static final int accent_horn = 752; public static final int accent_macron = 395;
public static final int accent_macron = 769; public static final int accent_ogonek = 408;
public static final int accent_ogonek = 824; public static final int accent_ordinal = 422;
public static final int accent_ordinal = 836; public static final int accent_ring = 445;
public static final int accent_ring = 859; public static final int accent_slash = 450;
public static final int accent_slash = 871; public static final int accent_subscript = 480;
public static final int accent_subscript = 911; public static final int accent_superscript = 545;
public static final int accent_superscript = 988; public static final int accent_tilde = 619;
public static final int accent_tilde = 1144; public static final int accent_trema = 640;
public static final int accent_trema = 1172; public static final int compose = 653;
public static final int compose = 1270; public static final int fn = 6078;
public static final int fn = 7423; public static final int shift = 6484;
public static final int numpad_bengali = 7955;
public static final int numpad_devanagari = 7976;
public static final int numpad_gujarati = 7997;
public static final int numpad_hindu = 8018;
public static final int numpad_kannada = 8039;
public static final int numpad_persian = 8060;
public static final int numpad_tamil = 8081;
public static final int shift = 8102;
} }

View File

@@ -5,9 +5,14 @@ import android.content.res.Configuration;
import android.content.res.Resources; import android.content.res.Resources;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.util.TypedValue; import android.util.TypedValue;
import android.view.KeyEvent;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import juloo.keyboard2.prefs.CustomExtraKeysPreference; import juloo.keyboard2.prefs.CustomExtraKeysPreference;
import juloo.keyboard2.prefs.ExtraKeysPreference; import juloo.keyboard2.prefs.ExtraKeysPreference;
import juloo.keyboard2.prefs.LayoutsPreference; import juloo.keyboard2.prefs.LayoutsPreference;
@@ -23,6 +28,10 @@ public final class Config
public final float labelTextSize; public final float labelTextSize;
public final float sublabelTextSize; public final float sublabelTextSize;
public final KeyboardData.Row bottom_row;
public final KeyboardData.Row number_row;
public final KeyboardData num_pad;
// From preferences // From preferences
/** [null] represent the [system] layout. */ /** [null] represent the [system] layout. */
public List<KeyboardData> layouts; public List<KeyboardData> layouts;
@@ -75,7 +84,6 @@ public final class Config
[get_current_layout()] and [set_current_layout()]. */ [get_current_layout()] and [set_current_layout()]. */
int current_layout_portrait; int current_layout_portrait;
int current_layout_landscape; int current_layout_landscape;
public int bottomInsetMin;
private Config(SharedPreferences prefs, Resources res, IKeyEventHandler h) private Config(SharedPreferences prefs, Resources res, IKeyEventHandler h)
{ {
@@ -85,6 +93,16 @@ public final class Config
keyPadding = res.getDimension(R.dimen.key_padding); keyPadding = res.getDimension(R.dimen.key_padding);
labelTextSize = 0.33f; labelTextSize = 0.33f;
sublabelTextSize = 0.22f; sublabelTextSize = 0.22f;
try
{
number_row = KeyboardData.load_number_row(res);
bottom_row = KeyboardData.load_bottom_row(res);
num_pad = KeyboardData.load_num_pad(res);
}
catch (Exception e)
{
throw new RuntimeException(e.getMessage()); // Not recoverable
}
// from prefs // from prefs
refresh(res); refresh(res);
// initialized later // initialized later
@@ -131,7 +149,7 @@ public final class Config
float swipe_scaling = Math.min(dm.widthPixels, dm.heightPixels) / 10.f * dpi_ratio; float swipe_scaling = Math.min(dm.widthPixels, dm.heightPixels) / 10.f * dpi_ratio;
float swipe_dist_value = Float.valueOf(_prefs.getString("swipe_dist", "15")); float swipe_dist_value = Float.valueOf(_prefs.getString("swipe_dist", "15"));
swipe_dist_px = swipe_dist_value / 25.f * swipe_scaling; swipe_dist_px = swipe_dist_value / 25.f * swipe_scaling;
slide_step_px = 0.4f * swipe_scaling; slide_step_px = 0.2f * swipe_scaling;
vibrate_custom = _prefs.getBoolean("vibrate_custom", false); vibrate_custom = _prefs.getBoolean("vibrate_custom", false);
vibrate_duration = _prefs.getInt("vibrate_duration", 20); vibrate_duration = _prefs.getInt("vibrate_duration", 20);
longPressTimeout = _prefs.getInt("longpress_timeout", 600); longPressTimeout = _prefs.getInt("longpress_timeout", 600);
@@ -157,7 +175,7 @@ public final class Config
get_dip_pref_oriented(dm, "horizontal_margin", 3, 28); get_dip_pref_oriented(dm, "horizontal_margin", 3, 28);
double_tap_lock_shift = _prefs.getBoolean("lock_double_tap", false); double_tap_lock_shift = _prefs.getBoolean("lock_double_tap", false);
characterSize = characterSize =
_prefs.getFloat("character_size", 1.15f) _prefs.getFloat("character_size", 1.f)
* characterSizeScale; * characterSizeScale;
theme = getThemeId(res, _prefs.getString("theme", "")); theme = getThemeId(res, _prefs.getString("theme", ""));
autocapitalisation = _prefs.getBoolean("autocapitalisation", true); autocapitalisation = _prefs.getBoolean("autocapitalisation", true);
@@ -169,8 +187,6 @@ public final class Config
current_layout_landscape = _prefs.getInt("current_layout_landscape", 0); current_layout_landscape = _prefs.getInt("current_layout_landscape", 0);
circle_sensitivity = Integer.valueOf(_prefs.getString("circle_sensitivity", "2")); circle_sensitivity = Integer.valueOf(_prefs.getString("circle_sensitivity", "2"));
clipboard_history_enabled = _prefs.getBoolean("clipboard_history_enabled", false); clipboard_history_enabled = _prefs.getBoolean("clipboard_history_enabled", false);
bottomInsetMin = Utils.is_navigation_bar_gestural(res) ?
(int)res.getDimension(R.dimen.bottom_inset_min) : 0;
} }
public int get_current_layout() public int get_current_layout()
@@ -191,10 +207,182 @@ public final class Config
e.apply(); e.apply();
} }
public void set_clipboard_history_enabled(boolean e) KeyValue action_key()
{ {
clipboard_history_enabled = e; // Update the name to avoid caching in KeyModifier
_prefs.edit().putBoolean("clipboard_history_enabled", e).commit(); return (actionLabel == null) ? null :
KeyValue.getKeyByName("action").withSymbol(actionLabel);
}
/** Update the layout according to the configuration.
* - Remove the switching key if it isn't needed
* - Remove "localized" keys from other locales (not in 'extra_keys')
* - Replace the action key to show the right label
* - Swap the enter and action keys
* - Add the optional numpad and number row
* - Add the extra keys
*/
public KeyboardData modify_layout(KeyboardData kw)
{
final KeyValue action_key = action_key();
// Extra keys are removed from the set as they are encountered during the
// first iteration then automatically added.
final Map<KeyValue, KeyboardData.PreferredPos> extra_keys = new HashMap<KeyValue, KeyboardData.PreferredPos>();
final Set<KeyValue> remove_keys = new HashSet<KeyValue>();
// Make sure the config key is accessible to avoid being locked in a custom
// layout.
extra_keys.put(KeyValue.getKeyByName("config"), KeyboardData.PreferredPos.ANYWHERE);
extra_keys.putAll(extra_keys_param);
extra_keys.putAll(extra_keys_custom);
if (extra_keys_subtype != null && kw.locale_extra_keys)
{
Set<KeyValue> present = new HashSet<KeyValue>();
present.addAll(kw.getKeys().keySet());
present.addAll(extra_keys_param.keySet());
present.addAll(extra_keys_custom.keySet());
extra_keys_subtype.compute(extra_keys,
new ExtraKeys.Query(kw.script, present));
}
KeyboardData.Row added_number_row = null;
if (add_number_row && !show_numpad)
added_number_row = modify_number_row(number_row, kw);
if (added_number_row != null)
remove_keys.addAll(added_number_row.getKeys(0).keySet());
if (kw.bottom_row)
kw = kw.insert_row(bottom_row, kw.rows.size());
kw = kw.mapKeys(new KeyboardData.MapKeyValues() {
public KeyValue apply(KeyValue key, boolean localized)
{
boolean is_extra_key = extra_keys.containsKey(key);
if (is_extra_key)
extra_keys.remove(key);
if (localized && !is_extra_key)
return null;
if (remove_keys.contains(key))
return null;
switch (key.getKind())
{
case Event:
switch (key.getEvent())
{
case CHANGE_METHOD_PICKER:
if (switch_input_immediate)
return KeyValue.getKeyByName("change_method_prev");
return key;
case ACTION:
return (swapEnterActionKey && action_key != null) ?
KeyValue.getKeyByName("enter") : action_key;
case SWITCH_FORWARD:
return (layouts.size() > 1) ? key : null;
case SWITCH_BACKWARD:
return (layouts.size() > 2) ? key : null;
case SWITCH_VOICE_TYPING:
case SWITCH_VOICE_TYPING_CHOOSER:
return shouldOfferVoiceTyping ? key : null;
}
break;
case Keyevent:
switch (key.getKeyevent())
{
case KeyEvent.KEYCODE_ENTER:
return (swapEnterActionKey && action_key != null) ? action_key : key;
}
break;
case Modifier:
switch (key.getModifier())
{
case SHIFT:
if (double_tap_lock_shift)
return key.withFlags(key.getFlags() | KeyValue.FLAG_LOCK);
}
break;
}
return key;
}
});
if (show_numpad)
kw = kw.addNumPad(modify_numpad(num_pad, kw));
if (added_number_row != null)
kw = kw.insert_row(added_number_row, 0);
if (extra_keys.size() > 0)
kw = kw.addExtraKeys(extra_keys.entrySet().iterator());
return kw;
}
/** Handle the numpad layout. The [main_kw] is used to adapt the numpad to
the main layout's script. */
public KeyboardData modify_numpad(KeyboardData kw, KeyboardData main_kw)
{
final KeyValue action_key = action_key();
final KeyModifier.Map_char map_digit = KeyModifier.modify_numpad_script(main_kw.numpad_script);
return kw.mapKeys(new KeyboardData.MapKeyValues() {
public KeyValue apply(KeyValue key, boolean localized)
{
switch (key.getKind())
{
case Event:
switch (key.getEvent())
{
case ACTION:
return (swapEnterActionKey && action_key != null) ?
KeyValue.getKeyByName("enter") : action_key;
}
break;
case Keyevent:
switch (key.getKeyevent())
{
case KeyEvent.KEYCODE_ENTER:
return (swapEnterActionKey && action_key != null) ? action_key : key;
}
break;
case Char:
char prev_c = key.getChar();
char c = prev_c;
if (inverse_numpad)
c = inverse_numpad_char(c);
String modified = map_digit.apply(c);
if (modified != null) // Was modified by script
return KeyValue.makeStringKey(modified);
if (prev_c != c) // Was inverted
return key.withChar(c);
break;
}
return key;
}
});
}
static KeyboardData.MapKeyValues numpad_script_map(String numpad_script)
{
final KeyModifier.Map_char map_digit = KeyModifier.modify_numpad_script(numpad_script);
return new KeyboardData.MapKeyValues() {
public KeyValue apply(KeyValue key, boolean localized)
{
switch (key.getKind())
{
case Char:
String modified = map_digit.apply(key.getChar());
if (modified != null)
return KeyValue.makeStringKey(modified);
break;
}
return key;
}
};
}
/** Modify the pin entry layout. [main_kw] is used to map the digits into the
same script. */
public KeyboardData modify_pinentry(KeyboardData kw, KeyboardData main_kw)
{
return kw.mapKeys(numpad_script_map(main_kw.numpad_script));
}
/** Modify the number row according to [main_kw]'s script. */
public KeyboardData.Row modify_number_row(KeyboardData.Row row,
KeyboardData main_kw)
{
return row.mapKeys(numpad_script_map(main_kw.numpad_script));
} }
private float get_dip_pref(DisplayMetrics dm, String pref_name, float def) private float get_dip_pref(DisplayMetrics dm, String pref_name, float def)
@@ -234,7 +422,6 @@ public final class Config
if ((night_mode & Configuration.UI_MODE_NIGHT_NO) != 0) if ((night_mode & Configuration.UI_MODE_NIGHT_NO) != 0)
return R.style.MonetLight; return R.style.MonetLight;
return R.style.MonetDark; return R.style.MonetDark;
case "rosepine": return R.style.RosePine;
default: default:
case "system": case "system":
if ((night_mode & Configuration.UI_MODE_NIGHT_NO) != 0) if ((night_mode & Configuration.UI_MODE_NIGHT_NO) != 0)
@@ -243,6 +430,20 @@ public final class Config
} }
} }
char inverse_numpad_char(char c)
{
switch (c)
{
case '7': return '1';
case '8': return '2';
case '9': return '3';
case '1': return '7';
case '2': return '8';
case '3': return '9';
default: return c;
}
}
private static Config _globalConfig = null; private static Config _globalConfig = null;
public static void initGlobalConfig(SharedPreferences prefs, Resources res, public static void initGlobalConfig(SharedPreferences prefs, Resources res,
@@ -250,7 +451,6 @@ public final class Config
{ {
migrate(prefs); migrate(prefs);
_globalConfig = new Config(prefs, res, handler); _globalConfig = new Config(prefs, res, handler);
LayoutModifier.init(_globalConfig, res);
} }
public static Config globalConfig() public static Config globalConfig()

View File

@@ -3,7 +3,6 @@ package juloo.keyboard2;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.os.Looper; import android.os.Looper;
import android.text.InputType; import android.text.InputType;
import android.view.KeyCharacterMap;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.ExtractedText; import android.view.inputmethod.ExtractedText;
@@ -61,10 +60,10 @@ public final class KeyEventHandler
{ {
if (key == null) if (key == null)
return; return;
// Stop auto capitalisation when pressing some keys
switch (key.getKind()) switch (key.getKind())
{ {
case Modifier: case Modifier:
// Stop auto capitalisation when activating a system modifier
switch (key.getModifier()) switch (key.getModifier())
{ {
case CTRL: case CTRL:
@@ -74,9 +73,6 @@ public final class KeyEventHandler
break; break;
} }
break; break;
case Compose_pending:
_autocap.stop();
break;
default: break; default: break;
} }
} }
@@ -97,9 +93,10 @@ public final class KeyEventHandler
case Keyevent: send_key_down_up(key.getKeyevent()); break; case Keyevent: send_key_down_up(key.getKeyevent()); break;
case Modifier: break; case Modifier: break;
case Editing: handle_editing_key(key.getEditing()); break; case Editing: handle_editing_key(key.getEditing()); break;
case Compose_pending: _recv.set_compose_pending(true); break; case Compose_pending:
case Slider: handle_slider(key.getSlider(), key.getSliderRepeat()); break; _recv.set_compose_pending(true);
case Macro: evaluate_macro(key.getMacro()); break; break;
case Cursor_move: move_cursor(key.getCursorMove()); break;
} }
update_meta_state(old_mods); update_meta_state(old_mods);
} }
@@ -146,11 +143,11 @@ public final class KeyEventHandler
if (down) if (down)
{ {
_meta_state = _meta_state | meta_flags; _meta_state = _meta_state | meta_flags;
send_keyevent(KeyEvent.ACTION_DOWN, eventCode, _meta_state); send_keyevent(KeyEvent.ACTION_DOWN, eventCode);
} }
else else
{ {
send_keyevent(KeyEvent.ACTION_UP, eventCode, _meta_state); send_keyevent(KeyEvent.ACTION_UP, eventCode);
_meta_state = _meta_state & ~meta_flags; _meta_state = _meta_state & ~meta_flags;
} }
} }
@@ -181,28 +178,23 @@ public final class KeyEventHandler
} }
} }
/*
* Don't set KeyEvent.FLAG_SOFT_KEYBOARD.
*/
void send_key_down_up(int keyCode) void send_key_down_up(int keyCode)
{ {
send_key_down_up(keyCode, _meta_state); send_keyevent(KeyEvent.ACTION_DOWN, keyCode);
send_keyevent(KeyEvent.ACTION_UP, keyCode);
} }
/** Ignores currently pressed system modifiers. */ void send_keyevent(int eventAction, int eventCode)
void send_key_down_up(int keyCode, int metaState)
{
send_keyevent(KeyEvent.ACTION_DOWN, keyCode, metaState);
send_keyevent(KeyEvent.ACTION_UP, keyCode, metaState);
}
void send_keyevent(int eventAction, int eventCode, int metaState)
{ {
InputConnection conn = _recv.getCurrentInputConnection(); InputConnection conn = _recv.getCurrentInputConnection();
if (conn == null) if (conn == null)
return; return;
conn.sendKeyEvent(new KeyEvent(1, 1, eventAction, eventCode, 0, conn.sendKeyEvent(new KeyEvent(1, 1, eventAction, eventCode, 0, _meta_state));
metaState, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE));
if (eventAction == KeyEvent.ACTION_UP) if (eventAction == KeyEvent.ACTION_UP)
_autocap.event_sent(eventCode, metaState); _autocap.event_sent(eventCode, _meta_state);
} }
void send_text(CharSequence text) void send_text(CharSequence text)
@@ -239,8 +231,6 @@ public final class KeyEventHandler
case REPLACE: send_context_menu_action(android.R.id.replaceText); break; case REPLACE: send_context_menu_action(android.R.id.replaceText); break;
case ASSIST: send_context_menu_action(android.R.id.textAssist); break; case ASSIST: send_context_menu_action(android.R.id.textAssist); break;
case AUTOFILL: send_context_menu_action(android.R.id.autofill); break; case AUTOFILL: send_context_menu_action(android.R.id.autofill); break;
case DELETE_WORD: send_key_down_up(KeyEvent.KEYCODE_DEL, KeyEvent.META_CTRL_ON | KeyEvent.META_CTRL_LEFT_ON); break;
case FORWARD_DELETE_WORD: send_key_down_up(KeyEvent.KEYCODE_FORWARD_DEL, KeyEvent.META_CTRL_ON | KeyEvent.META_CTRL_LEFT_ON); break;
} }
} }
@@ -258,18 +248,6 @@ public final class KeyEventHandler
return conn.getExtractedText(_move_cursor_req, 0); return conn.getExtractedText(_move_cursor_req, 0);
} }
/** [repeatition] might be negative, in which case the direction is reversed. */
void handle_slider(KeyValue.Slider s, int repeatition)
{
switch (s)
{
case Cursor_left: move_cursor(-repeatition); break;
case Cursor_right: move_cursor(repeatition); break;
case Cursor_up: move_cursor_vertical(-repeatition); break;
case Cursor_down: move_cursor_vertical(repeatition); break;
}
}
/** Move the cursor right or left, if possible without sending key events. /** Move the cursor right or left, if possible without sending key events.
Unlike arrow keys, the selection is not removed even if shift is not on. Unlike arrow keys, the selection is not removed even if shift is not on.
Falls back to sending arrow keys events if the editor do not support Falls back to sending arrow keys events if the editor do not support
@@ -282,11 +260,13 @@ public final class KeyEventHandler
ExtractedText et = get_cursor_pos(conn); ExtractedText et = get_cursor_pos(conn);
int system_mods = int system_mods =
KeyEvent.META_CTRL_ON | KeyEvent.META_ALT_ON | KeyEvent.META_META_ON; KeyEvent.META_CTRL_ON | KeyEvent.META_ALT_ON | KeyEvent.META_META_ON;
// Fallback to sending key events if system modifiers are activated or // Fallback to sending key events
// ExtractedText is not supported, for example on Termux. if (_move_cursor_force_fallback || et == null
if (!_move_cursor_force_fallback && et != null || (_meta_state & system_mods) != 0)
&& (_meta_state & system_mods) == 0)
{ {
move_cursor_fallback(d);
return;
}
int sel_start = et.selectionStart; int sel_start = et.selectionStart;
int sel_end = et.selectionEnd; int sel_end = et.selectionEnd;
// Continue expanding the selection even if shift is not pressed // Continue expanding the selection even if shift is not pressed
@@ -303,59 +283,24 @@ public final class KeyEventHandler
if ((_meta_state & KeyEvent.META_SHIFT_ON) == 0) if ((_meta_state & KeyEvent.META_SHIFT_ON) == 0)
sel_start = sel_end; sel_start = sel_end;
} }
if (conn.setSelection(sel_start, sel_end)) if (!conn.setSelection(sel_start, sel_end))
return; // [setSelection] succeeded, don't fallback to key events move_cursor_fallback(d);
}
if (d < 0)
send_key_down_up_repeat(KeyEvent.KEYCODE_DPAD_LEFT, -d);
else
send_key_down_up_repeat(KeyEvent.KEYCODE_DPAD_RIGHT, d);
} }
/** Move the cursor up and down. This sends UP and DOWN key events that might /** Send arrow keys as a fallback for editors that do not support
make the focus exit the text box. */ [getExtractedText] like Termux. */
void move_cursor_vertical(int d) void move_cursor_fallback(int d)
{ {
if (d < 0) while (d < 0)
send_key_down_up_repeat(KeyEvent.KEYCODE_DPAD_UP, -d); {
else send_key_down_up(KeyEvent.KEYCODE_DPAD_LEFT);
send_key_down_up_repeat(KeyEvent.KEYCODE_DPAD_DOWN, d); d++;
} }
while (d > 0)
void evaluate_macro(KeyValue[] keys)
{ {
final Pointers.Modifiers empty = Pointers.Modifiers.EMPTY; send_key_down_up(KeyEvent.KEYCODE_DPAD_RIGHT);
// Ignore modifiers that are activated at the time the macro is evaluated d--;
mods_changed(empty);
Pointers.Modifiers mods = empty;
final boolean autocap_paused = _autocap.pause();
for (KeyValue kv : keys)
{
kv = KeyModifier.modify(kv, mods);
if (kv == null)
continue;
if (kv.hasFlagsAny(KeyValue.FLAG_LATCH))
{
// Non-special latchable keys clear latched modifiers
if (!kv.hasFlagsAny(KeyValue.FLAG_SPECIAL))
mods = empty;
mods = mods.with_extra_mod(kv);
} }
else
{
key_down(kv, false);
key_up(kv, mods);
mods = empty;
}
}
_autocap.unpause(autocap_paused);
}
/** Repeat calls to [send_key_down_up]. */
void send_key_down_up_repeat(int event_code, int repeat)
{
while (repeat-- > 0)
send_key_down_up(event_code);
} }
public static interface IReceiver public static interface IReceiver

View File

@@ -36,7 +36,7 @@ public final class KeyModifier
case Modifier: case Modifier:
return modify(k, mod.getModifier()); return modify(k, mod.getModifier());
case Compose_pending: case Compose_pending:
return apply_compose_pending(mod.getPendingCompose(), k); return ComposeKey.apply(mod.getPendingCompose(), k);
case Hangul_initial: case Hangul_initial:
if (k.equals(mod)) // Allow typing the initial in letter form if (k.equals(mod)) // Allow typing the initial in letter form
return KeyValue.makeStringKey(k.getString(), KeyValue.FLAG_GREYED); return KeyValue.makeStringKey(k.getString(), KeyValue.FLAG_GREYED);
@@ -80,8 +80,7 @@ public final class KeyModifier
case DOT_BELOW: return apply_compose(k, ComposeKeyData.accent_dot_below); case DOT_BELOW: return apply_compose(k, ComposeKeyData.accent_dot_below);
case HORN: return apply_compose(k, ComposeKeyData.accent_horn); case HORN: return apply_compose(k, ComposeKeyData.accent_horn);
case HOOK_ABOVE: return apply_compose(k, ComposeKeyData.accent_hook_above); case HOOK_ABOVE: return apply_compose(k, ComposeKeyData.accent_hook_above);
case DOUBLE_GRAVE: return apply_compose(k, ComposeKeyData.accent_double_grave); case ARROW_RIGHT: return apply_map_char(k, map_char_arrow_right);
case ARROW_RIGHT: return apply_combining_char(k, "\u20D7");
default: return k; default: return k;
} }
} }
@@ -104,62 +103,58 @@ public final class KeyModifier
return k; return k;
} }
/** Return the compose state that modifies the numpad script. */ public static Map_char modify_numpad_script(String numpad_script)
public static int modify_numpad_script(String numpad_script)
{ {
if (numpad_script == null) if (numpad_script == null)
return -1; return map_char_none;
switch (numpad_script) switch (numpad_script)
{ {
case "hindu-arabic": return ComposeKeyData.numpad_hindu; case "hindu-arabic": return map_char_numpad_hindu;
case "bengali": return ComposeKeyData.numpad_bengali; case "bengali": return map_char_numpad_bengali;
case "devanagari": return ComposeKeyData.numpad_devanagari; case "devanagari": return map_char_numpad_devanagari;
case "persian": return ComposeKeyData.numpad_persian; case "persian": return map_char_numpad_persian;
case "gujarati": return ComposeKeyData.numpad_gujarati; case "gujarati": return map_char_numpad_gujarati;
case "kannada": return ComposeKeyData.numpad_kannada; default: return map_char_none;
case "tamil": return ComposeKeyData.numpad_tamil;
default: return -1;
} }
} }
/** Keys that do not match any sequence are greyed. */ private static KeyValue apply_map_char(KeyValue k, Map_char map)
private static KeyValue apply_compose_pending(int state, KeyValue kv)
{ {
switch (kv.getKind()) switch (k.getKind())
{ {
case Char: case Char:
case String: char kc = k.getChar();
KeyValue res = ComposeKey.apply(state, kv); String modified = map.apply(kc);
// Grey-out characters not part of any sequence. if (modified != null)
if (res == null) return KeyValue.makeStringKey(modified, k.getFlags());
return kv.withFlags(kv.getFlags() | KeyValue.FLAG_GREYED);
return res;
/* Tapping compose again exits the pending sequence. */
case Compose_pending:
return KeyValue.getKeyByName("compose_cancel");
/* These keys are not greyed. */
case Event:
case Modifier:
return kv;
/* Other keys cannot be part of sequences. */
default:
return kv.withFlags(kv.getFlags() | KeyValue.FLAG_GREYED);
} }
return k;
} }
/** Apply the given compose state or fallback to the dead_char. */ /** Apply the given compose state or fallback to the dead_char. */
private static KeyValue apply_compose_or_dead_char(KeyValue k, int state, char dead_char) private static KeyValue apply_compose_or_dead_char(KeyValue k, int state, char dead_char)
{ {
KeyValue r = ComposeKey.apply(state, k); switch (k.getKind())
{
case Char:
char c = k.getChar();
KeyValue r = ComposeKey.apply(state, c);
if (r != null) if (r != null)
return r; return r;
}
return apply_dead_char(k, dead_char); return apply_dead_char(k, dead_char);
} }
private static KeyValue apply_compose(KeyValue k, int state) private static KeyValue apply_compose(KeyValue k, int state)
{ {
KeyValue r = ComposeKey.apply(state, k); switch (k.getKind())
return (r != null) ? r : k; {
case Char:
KeyValue r = ComposeKey.apply(state, k.getChar());
if (r != null)
return r;
}
return k;
} }
private static KeyValue apply_dead_char(KeyValue k, char dead_char) private static KeyValue apply_dead_char(KeyValue k, char dead_char)
@@ -175,16 +170,6 @@ public final class KeyModifier
return k; return k;
} }
private static KeyValue apply_combining_char(KeyValue k, String combining)
{
switch (k.getKind())
{
case Char:
return KeyValue.makeStringKey(k.getChar() + combining, k.getFlags());
}
return k;
}
private static KeyValue apply_shift(KeyValue k) private static KeyValue apply_shift(KeyValue k)
{ {
if (_modmap != null) if (_modmap != null)
@@ -193,19 +178,18 @@ public final class KeyModifier
if (mapped != null) if (mapped != null)
return mapped; return mapped;
} }
KeyValue r = ComposeKey.apply(ComposeKeyData.shift, k);
if (r != null)
return r;
switch (k.getKind()) switch (k.getKind())
{ {
case Char: case Char:
char kc = k.getChar(); char kc = k.getChar();
KeyValue r = ComposeKey.apply(ComposeKeyData.shift, kc);
if (r != null)
return r;
char c = Character.toUpperCase(kc); char c = Character.toUpperCase(kc);
return (kc == c) ? k : k.withChar(c); return (kc == c) ? k : k.withChar(c);
case String: case String:
String ks = k.getString(); String s = Utils.capitalize_string(k.getString());
String s = Utils.capitalize_string(ks); return KeyValue.makeStringKey(s, k.getFlags());
return s.equals(ks) ? k : KeyValue.makeStringKey(s, k.getFlags());
default: return k; default: return k;
} }
} }
@@ -222,13 +206,12 @@ public final class KeyModifier
switch (k.getKind()) switch (k.getKind())
{ {
case Char: case Char:
case String: KeyValue r = ComposeKey.apply(ComposeKeyData.fn, k.getChar());
KeyValue r = ComposeKey.apply(ComposeKeyData.fn, k);
return (r != null) ? r : k; return (r != null) ? r : k;
case Keyevent: name = apply_fn_keyevent(k.getKeyevent()); break; case Keyevent: name = apply_fn_keyevent(k.getKeyevent()); break;
case Event: name = apply_fn_event(k.getEvent()); break; case Event: name = apply_fn_event(k.getEvent()); break;
case Placeholder: name = apply_fn_placeholder(k.getPlaceholder()); break; case Placeholder: name = apply_fn_placeholder(k.getPlaceholder()); break;
case Editing: name = apply_fn_editing(k.getEditing()); break; case Cursor_move: name = apply_fn_cursormove(k.getCursorMove()); break;
} }
return (name == null) ? k : KeyValue.getKeyByName(name); return (name == null) ? k : KeyValue.getKeyByName(name);
} }
@@ -274,12 +257,12 @@ public final class KeyModifier
} }
} }
private static String apply_fn_editing(KeyValue.Editing p) private static String apply_fn_cursormove(short cur)
{ {
switch (p) switch (cur)
{ {
case UNDO: return "redo"; case -1 : return "home"; // cursor_left
case PASTE: return "pasteAsPlainText"; case 1 : return "end"; // cursor_right
default: return null; default: return null;
} }
} }
@@ -366,31 +349,141 @@ public final class KeyModifier
/** Modify a key affected by a round-trip or a clockwise circle gesture. */ /** Modify a key affected by a round-trip or a clockwise circle gesture. */
private static KeyValue apply_gesture(KeyValue k) private static KeyValue apply_gesture(KeyValue k)
{ {
KeyValue modified = apply_shift(k); KeyValue shifted = apply_shift(k);
if (modified != null && !modified.equals(k)) if (shifted == null || shifted.equals(k))
return modified; return apply_fn(k);
modified = apply_fn(k); return shifted;
if (modified != null && !modified.equals(k)) }
return modified;
String name = null; public static abstract class Map_char
switch (k.getKind())
{ {
case Modifier: /** Modify a char or return [null] if the modifier do not apply. Return a
switch (k.getModifier()) [String] that can contains combining diacritics. */
public abstract String apply(char c);
}
private static final Map_char map_char_none =
new Map_char() {
public String apply(char _c) { return null; }
};
private static final Map_char map_char_arrow_right =
new Map_char() {
public String apply(char c)
{ {
case SHIFT: name = "capslock"; break; switch (c)
}
break;
case Keyevent:
switch (k.getKeyevent())
{ {
case KeyEvent.KEYCODE_DEL: name = "delete_word"; break; default: return c + "\u20D7";
case KeyEvent.KEYCODE_FORWARD_DEL: name = "forward_delete_word"; break;
} }
break;
} }
return (name == null) ? k : KeyValue.getKeyByName(name); };
// Used with Arabic despite the name; called "Hindi numerals" in Arabic
// map_char_numpad_devanagari is used in Hindi
private static final Map_char map_char_numpad_hindu =
new Map_char() {
public String apply(char c)
{
switch (c)
{
case '0': return "٠";
case '1': return "١";
case '2': return "٢";
case '3': return "٣";
case '4': return "٤";
case '5': return "٥";
case '6': return "٦";
case '7': return "٧";
case '8': return "٨";
case '9': return "٩";
default: return null;
} }
}
};
private static final Map_char map_char_numpad_bengali =
new Map_char() {
public String apply(char c)
{
switch (c)
{
case '0': return "";
case '1': return "";
case '2': return "";
case '3': return "";
case '4': return "";
case '5': return "";
case '6': return "";
case '7': return "";
case '8': return "";
case '9': return "";
default: return null;
}
}
};
private static final Map_char map_char_numpad_devanagari =
new Map_char() {
public String apply(char c)
{
switch (c)
{
case '0': return "";
case '1': return "";
case '2': return "";
case '3': return "";
case '4': return "";
case '5': return "";
case '6': return "";
case '7': return "";
case '8': return "";
case '9': return "";
default: return null;
}
}
};
private static final Map_char map_char_numpad_persian =
new Map_char() {
public String apply(char c)
{
switch (c)
{
case '0': return "۰";
case '1': return "۱";
case '2': return "۲";
case '3': return "۳";
case '4': return "۴";
case '5': return "۵";
case '6': return "۶";
case '7': return "۷";
case '8': return "۸";
case '9': return "۹";
default: return null;
}
}
};
private static final Map_char map_char_numpad_gujarati =
new Map_char() {
public String apply(char c)
{
switch (c)
{
case '0': return "";
case '1': return "";
case '2': return "";
case '3': return "";
case '4': return "";
case '5': return "";
case '6': return "";
case '7': return "";
case '8': return "";
case '9': return "";
default: return null;
}
}
};
/** Compose the precomposed initial with the medial [kv]. */ /** Compose the precomposed initial with the medial [kv]. */
private static KeyValue combine_hangul_initial(KeyValue kv, int precomposed) private static KeyValue combine_hangul_initial(KeyValue kv, int precomposed)

View File

@@ -44,7 +44,6 @@ public final class KeyValue implements Comparable<KeyValue>
TREMA, TREMA,
HORN, HORN,
HOOK_ABOVE, HOOK_ABOVE,
DOUBLE_GRAVE,
SUPERSCRIPT, SUPERSCRIPT,
SUBSCRIPT, SUBSCRIPT,
RING, RING,
@@ -75,14 +74,11 @@ public final class KeyValue implements Comparable<KeyValue>
SHARE, SHARE,
ASSIST, ASSIST,
AUTOFILL, AUTOFILL,
DELETE_WORD,
FORWARD_DELETE_WORD,
} }
public static enum Placeholder public static enum Placeholder
{ {
REMOVED, REMOVED,
COMPOSE_CANCEL,
F11, F11,
F12, F12,
SHINDOT, SHINDOT,
@@ -93,54 +89,49 @@ public final class KeyValue implements Comparable<KeyValue>
public static enum Kind public static enum Kind
{ {
Char, Keyevent, Event, Compose_pending, Hangul_initial, Hangul_medial, Char, String, Keyevent, Event, Compose_pending, Hangul_initial,
Modifier, Editing, Placeholder, Hangul_medial, Modifier, Editing, Placeholder,
String, // [_payload] is also the string to output, value is unused. Cursor_move // Value is encoded as a 16-bit integer
Slider, // [_payload] is a [KeyValue.Slider], value is slider repeatition.
Macro, // [_payload] is a [KeyValue.Macro], value is unused.
} }
private static final int FLAGS_OFFSET = 20; private static final int FLAGS_OFFSET = 19;
private static final int KIND_OFFSET = 28; private static final int KIND_OFFSET = 28;
// Key stay activated when pressed once. // Behavior flags.
public static final int FLAG_LATCH = (1 << FLAGS_OFFSET << 0); public static final int FLAG_LATCH = (1 << FLAGS_OFFSET << 0);
// Key can be locked by typing twice when enabled in settings // Key can be locked by typing twice
public static final int FLAG_DOUBLE_TAP_LOCK = (1 << FLAGS_OFFSET << 1); public static final int FLAG_LOCK = (1 << FLAGS_OFFSET << 1);
// Special keys are not repeated. // Special keys are not repeated and don't clear latched modifiers.
// Special latchable keys don't clear latched modifiers.
public static final int FLAG_SPECIAL = (1 << FLAGS_OFFSET << 2); public static final int FLAG_SPECIAL = (1 << FLAGS_OFFSET << 2);
// Whether the symbol should be greyed out. For example, keys that are not // Whether the symbol should be greyed out. For example, keys that are not
// part of the pending compose sequence. // part of the pending compose sequence.
public static final int FLAG_GREYED = (1 << FLAGS_OFFSET << 3); public static final int FLAG_GREYED = (1 << FLAGS_OFFSET << 3);
// The special font is required to render this key. // Rendering flags.
public static final int FLAG_KEY_FONT = (1 << FLAGS_OFFSET << 4); public static final int FLAG_KEY_FONT = (1 << FLAGS_OFFSET << 4); // special font file
// 25% smaller symbols public static final int FLAG_SMALLER_FONT = (1 << FLAGS_OFFSET << 5); // 25% smaller symbols
public static final int FLAG_SMALLER_FONT = (1 << FLAGS_OFFSET << 5); public static final int FLAG_SECONDARY = (1 << FLAGS_OFFSET << 6); // dimmer
// Dimmer symbol // Used by [Pointers].
public static final int FLAG_SECONDARY = (1 << FLAGS_OFFSET << 6);
// Free: (1 << FLAGS_OFFSET << 7) // Free: (1 << FLAGS_OFFSET << 7)
// Free: (1 << FLAGS_OFFSET << 8)
// Ranges for the different components // Ranges for the different components
private static final int FLAGS_BITS = (0b11111111 << FLAGS_OFFSET); // 8 bits wide private static final int FLAGS_BITS =
FLAG_LATCH | FLAG_LOCK | FLAG_SPECIAL | FLAG_GREYED | FLAG_KEY_FONT |
FLAG_SMALLER_FONT | FLAG_SECONDARY;
private static final int KIND_BITS = (0b1111 << KIND_OFFSET); // 4 bits wide private static final int KIND_BITS = (0b1111 << KIND_OFFSET); // 4 bits wide
private static final int VALUE_BITS = 0b11111111111111111111; // 20 bits wide private static final int VALUE_BITS = ~(FLAGS_BITS | KIND_BITS); // 20 bits wide
static static
{ {
check((FLAGS_BITS & KIND_BITS) == 0); // No overlap with kind check((FLAGS_BITS & KIND_BITS) == 0); // No overlap
check(~(FLAGS_BITS | KIND_BITS) == VALUE_BITS); // No overlap with value
check((FLAGS_BITS | KIND_BITS | VALUE_BITS) == ~0); // No holes check((FLAGS_BITS | KIND_BITS | VALUE_BITS) == ~0); // No holes
// No kind is out of range // No kind is out of range
check((((Kind.values().length - 1) << KIND_OFFSET) & ~KIND_BITS) == 0); check((((Kind.values().length - 1) << KIND_OFFSET) & ~KIND_BITS) == 0);
} }
/** [_payload.toString()] is the symbol that is rendered on the keyboard. */ private final String _symbol;
private final Comparable _payload;
/** This field encodes three things: Kind (KIND_BITS), flags (FLAGS_BITS) and /** This field encodes three things: Kind, flags and value. */
value (VALUE_BITS).
The meaning of the value depends on the kind. */
private final int _code; private final int _code;
public Kind getKind() public Kind getKind()
@@ -162,7 +153,7 @@ public final class KeyValue implements Comparable<KeyValue>
When [getKind() == Kind.String], also the string to send. */ When [getKind() == Kind.String], also the string to send. */
public String getString() public String getString()
{ {
return _payload.toString(); return _symbol;
} }
/** Defined only when [getKind() == Kind.Char]. */ /** Defined only when [getKind() == Kind.Char]. */
@@ -214,63 +205,31 @@ public final class KeyValue implements Comparable<KeyValue>
return (_code & VALUE_BITS); return (_code & VALUE_BITS);
} }
/** Defined only when [getKind() == Kind.Slider]. */ /** Defined only when [getKind() == Kind.Cursor_move]. */
public Slider getSlider() public short getCursorMove()
{ {
return (Slider)_payload; return (short)(_code & VALUE_BITS);
}
/** Defined only when [getKind() == Kind.Slider]. */
public int getSliderRepeat()
{
return ((int)(short)(_code & VALUE_BITS));
}
/** Defined only when [getKind() == Kind.Macro]. */
public KeyValue[] getMacro()
{
return ((Macro)_payload).keys;
} }
/* Update the char and the symbol. */ /* Update the char and the symbol. */
public KeyValue withChar(char c) public KeyValue withChar(char c)
{ {
return new KeyValue(String.valueOf(c), Kind.Char, c, return new KeyValue(String.valueOf(c), Kind.Char, c, getFlags());
getFlags() & ~(FLAG_KEY_FONT | FLAG_SMALLER_FONT)); }
public KeyValue withSymbol(String s)
{
return new KeyValue(s, (_code & KIND_BITS), (_code & VALUE_BITS), getFlags());
} }
public KeyValue withKeyevent(int code) public KeyValue withKeyevent(int code)
{ {
return new KeyValue(getString(), Kind.Keyevent, code, getFlags()); return new KeyValue(_symbol, Kind.Keyevent, code, getFlags());
} }
public KeyValue withFlags(int f) public KeyValue withFlags(int f)
{ {
return new KeyValue(_payload, _code, _code, f); return new KeyValue(_symbol, (_code & KIND_BITS), (_code & VALUE_BITS), f);
}
public KeyValue withSymbol(String symbol)
{
int flags = getFlags() & ~(FLAG_KEY_FONT | FLAG_SMALLER_FONT);
switch (getKind())
{
case Char:
case Keyevent:
case Event:
case Compose_pending:
case Hangul_initial:
case Hangul_medial:
case Modifier:
case Editing:
case Placeholder:
if (symbol.length() > 1)
flags |= FLAG_SMALLER_FONT;
return new KeyValue(symbol, _code, _code, flags);
case Macro:
return makeMacro(symbol, getMacro(), flags);
default:
return makeMacro(symbol, new KeyValue[]{ this }, flags);
}
} }
@Override @Override
@@ -279,7 +238,6 @@ public final class KeyValue implements Comparable<KeyValue>
return sameKey((KeyValue)obj); return sameKey((KeyValue)obj);
} }
@Override
public int compareTo(KeyValue snd) public int compareTo(KeyValue snd)
{ {
// Compare the kind and value first, then the flags. // Compare the kind and value first, then the flags.
@@ -289,9 +247,7 @@ public final class KeyValue implements Comparable<KeyValue>
d = _code - snd._code; d = _code - snd._code;
if (d != 0) if (d != 0)
return d; return d;
// Calls [compareTo] assuming that if [_code] matches, then [_payload] are return _symbol.compareTo(snd._symbol);
// of the same class.
return _payload.compareTo(snd._payload);
} }
/** Type-safe alternative to [equals]. */ /** Type-safe alternative to [equals]. */
@@ -299,32 +255,24 @@ public final class KeyValue implements Comparable<KeyValue>
{ {
if (snd == null) if (snd == null)
return false; return false;
return _code == snd._code && _payload.compareTo(snd._payload) == 0; return _symbol.equals(snd._symbol) && _code == snd._code;
} }
@Override @Override
public int hashCode() public int hashCode()
{ {
return _payload.hashCode() + _code; return _symbol.hashCode() + _code;
} }
public String toString() public KeyValue(String s, int kind, int value, int flags)
{ {
int value = _code & VALUE_BITS; _symbol = s;
return "[KeyValue " + getKind().toString() + "+" + getFlags() + "+" + value + " \"" + getString() + "\"]";
}
private KeyValue(Comparable p, int kind, int value, int flags)
{
if (p == null)
throw new NullPointerException("KeyValue payload cannot be null");
_payload = p;
_code = (kind & KIND_BITS) | (flags & FLAGS_BITS) | (value & VALUE_BITS); _code = (kind & KIND_BITS) | (flags & FLAGS_BITS) | (value & VALUE_BITS);
} }
public KeyValue(Comparable p, Kind k, int v, int f) public KeyValue(String s, Kind k, int v, int f)
{ {
this(p, (k.ordinal() << KIND_OFFSET), v, f); this(s, (k.ordinal() << KIND_OFFSET), v, f);
} }
private static KeyValue charKey(String symbol, char c, int flags) private static KeyValue charKey(String symbol, char c, int flags)
@@ -334,7 +282,7 @@ public final class KeyValue implements Comparable<KeyValue>
private static KeyValue charKey(int symbol, char c, int flags) private static KeyValue charKey(int symbol, char c, int flags)
{ {
return charKey(String.valueOf((char)symbol), c, flags | FLAG_KEY_FONT); return charKey(String.valueOf((char)symbol), c, flags);
} }
private static KeyValue modifierKey(String symbol, Modifier m, int flags) private static KeyValue modifierKey(String symbol, Modifier m, int flags)
@@ -366,12 +314,12 @@ public final class KeyValue implements Comparable<KeyValue>
return eventKey(String.valueOf((char)symbol), e, flags | FLAG_KEY_FONT); return eventKey(String.valueOf((char)symbol), e, flags | FLAG_KEY_FONT);
} }
public static KeyValue keyeventKey(String symbol, int code, int flags) private static KeyValue keyeventKey(String symbol, int code, int flags)
{ {
return new KeyValue(symbol, Kind.Keyevent, code, flags | FLAG_SECONDARY); return new KeyValue(symbol, Kind.Keyevent, code, flags | FLAG_SECONDARY);
} }
public static KeyValue keyeventKey(int symbol, int code, int flags) private static KeyValue keyeventKey(int symbol, int code, int flags)
{ {
return keyeventKey(String.valueOf((char)symbol), code, flags | FLAG_KEY_FONT); return keyeventKey(String.valueOf((char)symbol), code, flags | FLAG_KEY_FONT);
} }
@@ -392,12 +340,13 @@ public final class KeyValue implements Comparable<KeyValue>
return editingKey(String.valueOf((char)symbol), action, FLAG_KEY_FONT); return editingKey(String.valueOf((char)symbol), action, FLAG_KEY_FONT);
} }
/** A key that slides the property specified by [s] by the amount specified /** A key that moves the cursor [d] times to the right. If [d] is negative,
with [repeatition]. */ it moves the cursor [abs(d)] times to the left. */
public static KeyValue sliderKey(Slider s, int repeatition) public static KeyValue cursorMoveKey(int d)
{ {
// Casting to a short then back to a int to preserve the sign bit. int symbol = (d < 0) ? 0xE008 : 0xE006;
return new KeyValue(s, Kind.Slider, (short)repeatition & 0xFFFF, return new KeyValue(String.valueOf((char)symbol), Kind.Cursor_move,
((short)d) & 0xFFFF,
FLAG_SPECIAL | FLAG_SECONDARY | FLAG_KEY_FONT); FLAG_SPECIAL | FLAG_SECONDARY | FLAG_KEY_FONT);
} }
@@ -407,12 +356,6 @@ public final class KeyValue implements Comparable<KeyValue>
return new KeyValue("", Kind.Placeholder, id.ordinal(), 0); return new KeyValue("", Kind.Placeholder, id.ordinal(), 0);
} }
private static KeyValue placeholderKey(int symbol, Placeholder id, int flags)
{
return new KeyValue(String.valueOf((char)symbol), Kind.Placeholder,
id.ordinal(), flags | FLAG_KEY_FONT);
}
public static KeyValue makeStringKey(String str) public static KeyValue makeStringKey(String str)
{ {
return makeStringKey(str, 0); return makeStringKey(str, 0);
@@ -420,19 +363,7 @@ public final class KeyValue implements Comparable<KeyValue>
public static KeyValue makeCharKey(char c) public static KeyValue makeCharKey(char c)
{ {
return makeCharKey(c, null, 0); return new KeyValue(String.valueOf(c), Kind.Char, c, 0);
}
public static KeyValue makeCharKey(char c, String symbol, int flags)
{
if (symbol == null)
symbol = String.valueOf(c);
return new KeyValue(symbol, Kind.Char, c, flags);
}
public static KeyValue makeCharKey(int symbol, char c, int flags)
{
return makeCharKey(c, String.valueOf((char)symbol), flags | FLAG_KEY_FONT);
} }
public static KeyValue makeComposePending(String symbol, int state, int flags) public static KeyValue makeComposePending(String symbol, int state, int flags)
@@ -466,11 +397,6 @@ public final class KeyValue implements Comparable<KeyValue>
return KeyValue.makeCharKey((char)precomposed); return KeyValue.makeCharKey((char)precomposed);
} }
public static KeyValue makeActionKey(String symbol)
{
return eventKey(symbol, Event.ACTION, FLAG_SMALLER_FONT);
}
/** Make a key that types a string. A char key is returned for a string of /** Make a key that types a string. A char key is returned for a string of
length 1. */ length 1. */
public static KeyValue makeStringKey(String str, int flags) public static KeyValue makeStringKey(String str, int flags)
@@ -481,37 +407,13 @@ public final class KeyValue implements Comparable<KeyValue>
return new KeyValue(str, Kind.String, 0, flags | FLAG_SMALLER_FONT); return new KeyValue(str, Kind.String, 0, flags | FLAG_SMALLER_FONT);
} }
public static KeyValue makeMacro(String symbol, KeyValue[] keys, int flags)
{
if (symbol.length() > 1)
flags |= FLAG_SMALLER_FONT;
return new KeyValue(new Macro(keys, symbol), Kind.Macro, 0, flags);
}
/** Make a modifier key for passing to [KeyModifier]. */ /** Make a modifier key for passing to [KeyModifier]. */
public static KeyValue makeInternalModifier(Modifier mod) public static KeyValue makeInternalModifier(Modifier mod)
{ {
return new KeyValue("", Kind.Modifier, mod.ordinal(), 0); return new KeyValue("", Kind.Modifier, mod.ordinal(), 0);
} }
/** Return a key by its name. If the given name doesn't correspond to any
special key, it is parsed with [KeyValueParser]. */
public static KeyValue getKeyByName(String name) public static KeyValue getKeyByName(String name)
{
KeyValue k = getSpecialKeyByName(name);
if (k != null)
return k;
try
{
return KeyValueParser.parse(name);
}
catch (KeyValueParser.ParseError _e)
{
return makeStringKey(name);
}
}
public static KeyValue getSpecialKeyByName(String name)
{ {
switch (name) switch (name)
{ {
@@ -524,7 +426,7 @@ public final class KeyValue implements Comparable<KeyValue>
case "\\\\": return makeStringKey("\\"); case "\\\\": return makeStringKey("\\");
/* Modifiers and dead-keys */ /* Modifiers and dead-keys */
case "shift": return modifierKey(0xE00A, Modifier.SHIFT, FLAG_DOUBLE_TAP_LOCK); case "shift": return modifierKey(0xE00A, Modifier.SHIFT, 0);
case "ctrl": return modifierKey("Ctrl", Modifier.CTRL, 0); case "ctrl": return modifierKey("Ctrl", Modifier.CTRL, 0);
case "alt": return modifierKey("Alt", Modifier.ALT, 0); case "alt": return modifierKey("Alt", Modifier.ALT, 0);
case "accent_aigu": return diacritic(0xE050, Modifier.AIGU); case "accent_aigu": return diacritic(0xE050, Modifier.AIGU);
@@ -546,7 +448,6 @@ public final class KeyValue implements Comparable<KeyValue>
case "accent_dot_below": return diacritic(0xE060, Modifier.DOT_BELOW); case "accent_dot_below": return diacritic(0xE060, Modifier.DOT_BELOW);
case "accent_horn": return diacritic(0xE061, Modifier.HORN); case "accent_horn": return diacritic(0xE061, Modifier.HORN);
case "accent_hook_above": return diacritic(0xE062, Modifier.HOOK_ABOVE); case "accent_hook_above": return diacritic(0xE062, Modifier.HOOK_ABOVE);
case "accent_double_grave": return diacritic(0xE063, Modifier.DOUBLE_GRAVE);
case "superscript": return modifierKey("Sup", Modifier.SUPERSCRIPT, 0); case "superscript": return modifierKey("Sup", Modifier.SUPERSCRIPT, 0);
case "subscript": return modifierKey("Sub", Modifier.SUBSCRIPT, 0); case "subscript": return modifierKey("Sub", Modifier.SUBSCRIPT, 0);
case "ordinal": return modifierKey("Ord", Modifier.ORDINAL, 0); case "ordinal": return modifierKey("Ord", Modifier.ORDINAL, 0);
@@ -555,52 +456,6 @@ public final class KeyValue implements Comparable<KeyValue>
case "fn": return modifierKey("Fn", Modifier.FN, 0); case "fn": return modifierKey("Fn", Modifier.FN, 0);
case "meta": return modifierKey("Meta", Modifier.META, 0); case "meta": return modifierKey("Meta", Modifier.META, 0);
/* Combining diacritics */
/* Glyphs is the corresponding dead-key + 0x0100. */
case "combining_dot_above": return makeCharKey(0xE15A, '\u0307', 0);
case "combining_double_aigu": return makeCharKey(0xE15B, '\u030B', 0);
case "combining_slash": return makeCharKey(0xE15C, '\u0337', 0);
case "combining_arrow_right": return makeCharKey(0xE15D, '\u20D7', 0);
case "combining_breve": return makeCharKey(0xE15E, '\u0306', 0);
case "combining_bar": return makeCharKey(0xE15F, '\u0335', 0);
case "combining_aigu": return makeCharKey(0xE150, '\u0301', 0);
case "combining_caron": return makeCharKey(0xE151, '\u030C', 0);
case "combining_cedille": return makeCharKey(0xE152, '\u0327', 0);
case "combining_circonflexe": return makeCharKey(0xE153, '\u0302', 0);
case "combining_grave": return makeCharKey(0xE154, '\u0300', 0);
case "combining_macron": return makeCharKey(0xE155, '\u0304', 0);
case "combining_ring": return makeCharKey(0xE156, '\u030A', 0);
case "combining_tilde": return makeCharKey(0xE157, '\u0303', 0);
case "combining_trema": return makeCharKey(0xE158, '\u0308', 0);
case "combining_ogonek": return makeCharKey(0xE159, '\u0328', 0);
case "combining_dot_below": return makeCharKey(0xE160, '\u0323', 0);
case "combining_horn": return makeCharKey(0xE161, '\u031B', 0);
case "combining_hook_above": return makeCharKey(0xE162, '\u0309', 0);
/* Combining diacritics that do not have a corresponding dead keys start
at 0xE200. */
case "combining_vertical_tilde": return makeCharKey(0xE200, '\u033E', 0);
case "combining_inverted_breve": return makeCharKey(0xE201, '\u0311', 0);
case "combining_pokrytie": return makeCharKey(0xE202, '\u0487', 0);
case "combining_slavonic_psili": return makeCharKey(0xE203, '\u0486', 0);
case "combining_slavonic_dasia": return makeCharKey(0xE204, '\u0485', 0);
case "combining_payerok": return makeCharKey(0xE205, '\uA67D', 0);
case "combining_titlo": return makeCharKey(0xE206, '\u0483', 0);
case "combining_vzmet": return makeCharKey(0xE207, '\uA66F', 0);
case "combining_arabic_v": return makeCharKey(0xE208, '\u065A', 0);
case "combining_arabic_inverted_v": return makeCharKey(0xE209, '\u065B', 0);
case "combining_shaddah": return makeCharKey(0xE210, '\u0651', 0);
case "combining_sukun": return makeCharKey(0xE211, '\u0652', 0);
case "combining_fatha": return makeCharKey(0xE212, '\u064E', 0);
case "combining_dammah": return makeCharKey(0xE213, '\u064F', 0);
case "combining_kasra": return makeCharKey(0xE214, '\u0650', 0);
case "combining_hamza_above": return makeCharKey(0xE215, '\u0654', 0);
case "combining_hamza_below": return makeCharKey(0xE216, '\u0655', 0);
case "combining_alef_above": return makeCharKey(0xE217, '\u0670', 0);
case "combining_fathatan": return makeCharKey(0xE218, '\u064B', 0);
case "combining_kasratan": return makeCharKey(0xE219, '\u064D', 0);
case "combining_dammatan": return makeCharKey(0xE220, '\u064C', 0);
case "combining_alef_below": return makeCharKey(0xE221, '\u0656', 0);
/* Special event keys */ /* Special event keys */
case "config": return eventKey(0xE004, Event.CONFIG, FLAG_SMALLER_FONT); case "config": return eventKey(0xE004, Event.CONFIG, FLAG_SMALLER_FONT);
case "switch_text": return eventKey("ABC", Event.SWITCH_TEXT, FLAG_SMALLER_FONT); case "switch_text": return eventKey("ABC", Event.SWITCH_TEXT, FLAG_SMALLER_FONT);
@@ -623,13 +478,13 @@ public final class KeyValue implements Comparable<KeyValue>
case "esc": return keyeventKey("Esc", KeyEvent.KEYCODE_ESCAPE, FLAG_SMALLER_FONT); case "esc": return keyeventKey("Esc", KeyEvent.KEYCODE_ESCAPE, FLAG_SMALLER_FONT);
case "enter": return keyeventKey(0xE00E, KeyEvent.KEYCODE_ENTER, 0); case "enter": return keyeventKey(0xE00E, KeyEvent.KEYCODE_ENTER, 0);
case "up": return keyeventKey(0xE005, KeyEvent.KEYCODE_DPAD_UP, 0); case "up": return keyeventKey(0xE005, KeyEvent.KEYCODE_DPAD_UP, 0);
case "right": return keyeventKey(0xE006, KeyEvent.KEYCODE_DPAD_RIGHT, FLAG_SMALLER_FONT); case "right": return keyeventKey(0xE006, KeyEvent.KEYCODE_DPAD_RIGHT, 0);
case "down": return keyeventKey(0xE007, KeyEvent.KEYCODE_DPAD_DOWN, 0); case "down": return keyeventKey(0xE007, KeyEvent.KEYCODE_DPAD_DOWN, 0);
case "left": return keyeventKey(0xE008, KeyEvent.KEYCODE_DPAD_LEFT, FLAG_SMALLER_FONT); case "left": return keyeventKey(0xE008, KeyEvent.KEYCODE_DPAD_LEFT, 0);
case "page_up": return keyeventKey(0xE002, KeyEvent.KEYCODE_PAGE_UP, 0); case "page_up": return keyeventKey(0xE002, KeyEvent.KEYCODE_PAGE_UP, 0);
case "page_down": return keyeventKey(0xE003, KeyEvent.KEYCODE_PAGE_DOWN, 0); case "page_down": return keyeventKey(0xE003, KeyEvent.KEYCODE_PAGE_DOWN, 0);
case "home": return keyeventKey(0xE00B, KeyEvent.KEYCODE_MOVE_HOME, FLAG_SMALLER_FONT); case "home": return keyeventKey(0xE00B, KeyEvent.KEYCODE_MOVE_HOME, 0);
case "end": return keyeventKey(0xE00C, KeyEvent.KEYCODE_MOVE_END, FLAG_SMALLER_FONT); case "end": return keyeventKey(0xE00C, KeyEvent.KEYCODE_MOVE_END, 0);
case "backspace": return keyeventKey(0xE011, KeyEvent.KEYCODE_DEL, 0); case "backspace": return keyeventKey(0xE011, KeyEvent.KEYCODE_DEL, 0);
case "delete": return keyeventKey(0xE010, KeyEvent.KEYCODE_FORWARD_DEL, 0); case "delete": return keyeventKey(0xE010, KeyEvent.KEYCODE_FORWARD_DEL, 0);
case "insert": return keyeventKey("Ins", KeyEvent.KEYCODE_INSERT, FLAG_SMALLER_FONT); case "insert": return keyeventKey("Ins", KeyEvent.KEYCODE_INSERT, FLAG_SMALLER_FONT);
@@ -647,12 +502,12 @@ public final class KeyValue implements Comparable<KeyValue>
case "f12": return keyeventKey("F12", KeyEvent.KEYCODE_F12, FLAG_SMALLER_FONT); case "f12": return keyeventKey("F12", KeyEvent.KEYCODE_F12, FLAG_SMALLER_FONT);
case "tab": return keyeventKey(0xE00F, KeyEvent.KEYCODE_TAB, FLAG_SMALLER_FONT); case "tab": return keyeventKey(0xE00F, KeyEvent.KEYCODE_TAB, FLAG_SMALLER_FONT);
case "menu": return keyeventKey("Menu", KeyEvent.KEYCODE_MENU, FLAG_SMALLER_FONT); case "menu": return keyeventKey("Menu", KeyEvent.KEYCODE_MENU, FLAG_SMALLER_FONT);
case "scroll_lock": return keyeventKey("Scrl", KeyEvent.KEYCODE_SCROLL_LOCK, FLAG_SMALLER_FONT); case "playpause": return keyeventKey("Play", KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, FLAG_SMALLER_FONT);
/* Spaces */ /* Spaces */
case "\\t": return charKey("\\t", '\t', 0); // Send the tab character case "\\t": return charKey("\\t", '\t', 0); // Send the tab character
case "\\n": return charKey("\\n", '\n', 0); // Send the newline character case "\\n": return charKey("\\n", '\n', 0); // Send the newline character
case "space": return charKey(0xE00D, ' ', FLAG_SMALLER_FONT | FLAG_GREYED); case "space": return charKey(0xE00D, ' ', FLAG_KEY_FONT | FLAG_SMALLER_FONT | FLAG_GREYED);
case "nbsp": return charKey("\u237d", '\u00a0', FLAG_SMALLER_FONT); case "nbsp": return charKey("\u237d", '\u00a0', FLAG_SMALLER_FONT);
case "nnbsp": return charKey("\u2423", '\u202F', FLAG_SMALLER_FONT); case "nnbsp": return charKey("\u2423", '\u202F', FLAG_SMALLER_FONT);
@@ -696,9 +551,9 @@ public final class KeyValue implements Comparable<KeyValue>
case "meteg": return charKey("\u05DE\u05BD", '\u05BD', 0); // or siluq or sof-pasuq case "meteg": return charKey("\u05DE\u05BD", '\u05BD', 0); // or siluq or sof-pasuq
case "meteg_placeholder": return placeholderKey(Placeholder.METEG); case "meteg_placeholder": return placeholderKey(Placeholder.METEG);
/* intending/preventing ligature - supported by many scripts*/ /* intending/preventing ligature - supported by many scripts*/
case "zwj": return charKey(0xE019, '\u200D', 0); // zero-width joiner (provides ligature) case "zwj": return charKey("zwj", '\u200D', 0); // zero-width joiner (provides ligature)
case "zwnj": case "zwnj":
case "halfspace": return charKey(0xE018, '\u200C', 0); // zero-width non joiner case "halfspace": return charKey("", '\u200C', 0); // zero-width non joiner
/* Editing keys */ /* Editing keys */
case "copy": return editingKey(0xE030, Editing.COPY); case "copy": return editingKey(0xE030, Editing.COPY);
@@ -709,20 +564,15 @@ public final class KeyValue implements Comparable<KeyValue>
case "pasteAsPlainText": return editingKey(0xE035, Editing.PASTE_PLAIN); case "pasteAsPlainText": return editingKey(0xE035, Editing.PASTE_PLAIN);
case "undo": return editingKey(0xE036, Editing.UNDO); case "undo": return editingKey(0xE036, Editing.UNDO);
case "redo": return editingKey(0xE037, Editing.REDO); case "redo": return editingKey(0xE037, Editing.REDO);
case "delete_word": return editingKey(0xE01B, Editing.DELETE_WORD); case "cursor_left": return cursorMoveKey(-1);
case "forward_delete_word": return editingKey(0xE01C, Editing.FORWARD_DELETE_WORD); case "cursor_right": return cursorMoveKey(1);
case "cursor_left": return sliderKey(Slider.Cursor_left, 1);
case "cursor_right": return sliderKey(Slider.Cursor_right, 1);
case "cursor_up": return sliderKey(Slider.Cursor_up, 1);
case "cursor_down": return sliderKey(Slider.Cursor_down, 1);
// These keys are not used // These keys are not used
case "replaceText": return editingKey("repl", Editing.REPLACE); case "replaceText": return editingKey("repl", Editing.REPLACE);
case "textAssist": return editingKey(0xE038, Editing.ASSIST); case "textAssist": return editingKey(0xE038, Editing.ASSIST);
case "autofill": return editingKey("auto", Editing.AUTOFILL); case "autofill": return editingKey("auto", Editing.AUTOFILL);
/* The compose key */ /* The compose key */
case "compose": return makeComposePending(0xE016, ComposeKeyData.compose, FLAG_SECONDARY); case "compose": return makeComposePending(0xE016, ComposeKeyData.compose, FLAG_SECONDARY | FLAG_SMALLER_FONT | FLAG_SPECIAL);
case "compose_cancel": return placeholderKey(0xE01A, Placeholder.COMPOSE_CANCEL, FLAG_SECONDARY);
/* Placeholder keys */ /* Placeholder keys */
case "removed": return placeholderKey(Placeholder.REMOVED); case "removed": return placeholderKey(Placeholder.REMOVED);
@@ -750,21 +600,8 @@ public final class KeyValue implements Comparable<KeyValue>
case "": return makeHangulInitial("", 17); case "": return makeHangulInitial("", 17);
case "": return makeHangulInitial("", 18); case "": return makeHangulInitial("", 18);
/* Tamil letters should be smaller on the keyboard. */ /* Fallback to a string key that types its name */
case "": case "": case "": case "": case "": case "": default: return makeStringKey(name);
case "": case "": case "": case "": case "": case "":
case "": case "": case "": case "": case "": case "":
case "": case "": case "": case "": case "": case "":
case "": case "": case "": case "": case "": case "":
case "": case "": case "": case "": case "": case "":
case "": case "": case "": case "": case "": case "":
case "": case "": case "": case "": case "": case "":
case "": case "": case "": case "": case "": case "ி":
case "": case "": case "": case "": case "": case "":
case "": case "":
return makeStringKey(name, FLAG_SMALLER_FONT);
default: return null;
} }
} }
@@ -774,49 +611,4 @@ public final class KeyValue implements Comparable<KeyValue>
if (!b) if (!b)
throw new RuntimeException("Assertion failure"); throw new RuntimeException("Assertion failure");
} }
public static enum Slider
{
Cursor_left(0xE008),
Cursor_right(0xE006),
Cursor_up(0xE005),
Cursor_down(0xE007);
final String symbol;
Slider(int symbol_)
{
symbol = String.valueOf((char)symbol_);
}
@Override
public String toString() { return symbol; }
};
public static final class Macro implements Comparable<Macro>
{
public final KeyValue[] keys;
private final String _symbol;
public Macro(KeyValue[] keys_, String sym_)
{
keys = keys_;
_symbol = sym_;
}
public String toString() { return _symbol; }
@Override
public int compareTo(Macro snd)
{
int d = keys.length - snd.keys.length;
if (d != 0) return d;
for (int i = 0; i < keys.length; i++)
{
d = keys[i].compareTo(snd.keys[i]);
if (d != 0) return d;
}
return _symbol.compareTo(snd._symbol);
}
};
} }

View File

@@ -1,289 +0,0 @@
package juloo.keyboard2;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
Parse a key definition. The syntax for a key definition is:
- [(symbol):(key_action)]
- [:(kind) (attributes):(payload)].
- If [str] doesn't start with a [:] character, it is interpreted as an
arbitrary string key.
[key_action] is:
- ['Arbitrary string']
- [(key_action),(key_action),...]
- [keyevent:(code)]
- [(key_name)]
For the different kinds and attributes, see doc/Possible-key-values.md.
Examples:
- [:str flags=dim,small symbol='MyKey':'My arbitrary string'].
- [:str:'My arbitrary string'].
*/
public final class KeyValueParser
{
static Pattern KEYDEF_TOKEN;
static Pattern QUOTED_PAT;
static Pattern WORD_PAT;
static public KeyValue parse(String input) throws ParseError
{
int symbol_ends = 0;
final int input_len = input.length();
while (symbol_ends < input_len && input.charAt(symbol_ends) != ':')
symbol_ends++;
if (symbol_ends == 0) // Old syntax
return Starting_with_colon.parse(input);
if (symbol_ends == input_len) // String key
return KeyValue.makeStringKey(input);
String symbol = input.substring(0, symbol_ends);
init();
Matcher m = KEYDEF_TOKEN.matcher(input);
m.region(symbol_ends + 1, input_len);
KeyValue first_key = parse_key_def(m);
if (!parse_comma(m)) // Input is a single key def with a specified symbol
return first_key.withSymbol(symbol);
// Input is a macro
ArrayList<KeyValue> keydefs = new ArrayList<KeyValue>();
keydefs.add(first_key);
do { keydefs.add(parse_key_def(m)); }
while (parse_comma(m));
return KeyValue.makeMacro(symbol, keydefs.toArray(new KeyValue[]{}), 0);
}
static void init()
{
if (KEYDEF_TOKEN != null)
return;
KEYDEF_TOKEN = Pattern.compile("'|,|keyevent:|(?:[^\\\\',]+|\\\\.)+");
QUOTED_PAT = Pattern.compile("((?:[^'\\\\]+|\\\\')*)'");
WORD_PAT = Pattern.compile("[a-zA-Z0-9_]+|.");
}
static KeyValue key_by_name_or_str(String str)
{
KeyValue k = KeyValue.getSpecialKeyByName(str);
if (k != null)
return k;
return KeyValue.makeStringKey(str);
}
static KeyValue parse_key_def(Matcher m) throws ParseError
{
if (!match(m, KEYDEF_TOKEN))
parseError("Expected key definition", m);
String token = m.group(0);
switch (token)
{
case "'": return parse_string_keydef(m);
case ",": parseError("Unexpected comma", m); return null;
case "keyevent:": return parse_keyevent_keydef(m);
default: return key_by_name_or_str(remove_escaping(token));
}
}
static KeyValue parse_string_keydef(Matcher m) throws ParseError
{
if (!match(m, QUOTED_PAT))
parseError("Unterminated quoted string", m);
return KeyValue.makeStringKey(remove_escaping(m.group(1)));
}
static KeyValue parse_keyevent_keydef(Matcher m) throws ParseError
{
if (!match(m, WORD_PAT))
parseError("Expected keyevent code", m);
int eventcode = 0;
try { eventcode = Integer.parseInt(m.group(0)); }
catch (Exception _e)
{ parseError("Expected an integer payload", m); }
return KeyValue.keyeventKey("", eventcode, 0);
}
/** Returns [true] if the next token is a comma, [false] if it is the end of the input. Throws an error otherwise. */
static boolean parse_comma(Matcher m) throws ParseError
{
if (!match(m, KEYDEF_TOKEN))
return false;
String token = m.group(0);
if (!token.equals(","))
parseError("Expected comma instead of '"+ token + "'", m);
return true;
}
static String remove_escaping(String s)
{
if (!s.contains("\\"))
return s;
StringBuilder out = new StringBuilder(s.length());
final int len = s.length();
int prev = 0, i = 0;
for (; i < len; i++)
if (s.charAt(i) == '\\')
{
out.append(s, prev, i);
prev = i + 1;
}
out.append(s, prev, i);
return out.toString();
}
/**
Parse a key definition starting with a [:]. This is the old syntax and is
kept for compatibility.
*/
final static class Starting_with_colon
{
static Pattern START_PAT;
static Pattern ATTR_PAT;
static Pattern QUOTED_PAT;
static Pattern PAYLOAD_START_PAT;
static Pattern WORD_PAT;
static public KeyValue parse(String str) throws ParseError
{
String symbol = null;
int flags = 0;
init();
// Kind
Matcher m = START_PAT.matcher(str);
if (!m.lookingAt())
parseError("Expected kind, for example \":str ...\".", m);
String kind = m.group(1);
// Attributes
while (true)
{
if (!match(m, ATTR_PAT))
break;
String attr_name = m.group(1);
String attr_value = parseSingleQuotedString(m);
switch (attr_name)
{
case "flags":
flags = parseFlags(attr_value, m);
break;
case "symbol":
symbol = attr_value;
break;
default:
parseError("Unknown attribute "+attr_name, m);
}
}
// Payload
if (!match(m, PAYLOAD_START_PAT))
parseError("Unexpected character", m);
String payload;
switch (kind)
{
case "str":
payload = parseSingleQuotedString(m);
if (symbol == null)
return KeyValue.makeStringKey(payload, flags);
return KeyValue.makeStringKey(payload, flags).withSymbol(symbol);
case "char":
payload = parsePayloadWord(m);
if (payload.length() != 1)
parseError("Expected a single character payload", m);
return KeyValue.makeCharKey(payload.charAt(0), symbol, flags);
case "keyevent":
payload = parsePayloadWord(m);
int eventcode = 0;
try { eventcode = Integer.parseInt(payload); }
catch (Exception _e)
{ parseError("Expected an integer payload", m); }
if (symbol == null)
symbol = String.valueOf(eventcode);
return KeyValue.keyeventKey(symbol, eventcode, flags);
default: break;
}
parseError("Unknown kind '"+kind+"'", m, 1);
return null; // Unreachable
}
static String parseSingleQuotedString(Matcher m) throws ParseError
{
if (!match(m, QUOTED_PAT))
parseError("Expected quoted string", m);
return m.group(1).replace("\\'", "'");
}
static String parsePayloadWord(Matcher m) throws ParseError
{
if (!match(m, WORD_PAT))
parseError("Expected a word after ':' made of [a-zA-Z0-9_]", m);
return m.group(0);
}
static int parseFlags(String s, Matcher m) throws ParseError
{
int flags = 0;
for (String f : s.split(","))
{
switch (f)
{
case "dim": flags |= KeyValue.FLAG_SECONDARY; break;
case "small": flags |= KeyValue.FLAG_SMALLER_FONT; break;
default: parseError("Unknown flag "+f, m);
}
}
return flags;
}
static boolean match(Matcher m, Pattern pat)
{
try { m.region(m.end(), m.regionEnd()); } catch (Exception _e) {}
m.usePattern(pat);
return m.lookingAt();
}
static void init()
{
if (START_PAT != null)
return;
START_PAT = Pattern.compile(":(\\w+)");
ATTR_PAT = Pattern.compile("\\s*(\\w+)\\s*=");
QUOTED_PAT = Pattern.compile("'(([^'\\\\]+|\\\\')*)'");
PAYLOAD_START_PAT = Pattern.compile("\\s*:");
WORD_PAT = Pattern.compile("[a-zA-Z0-9_]*");
}
}
static boolean match(Matcher m, Pattern pat)
{
try { m.region(m.end(), m.regionEnd()); } catch (Exception _e) {}
m.usePattern(pat);
return m.lookingAt();
}
static void parseError(String msg, Matcher m) throws ParseError
{
parseError(msg, m, m.regionStart());
}
static void parseError(String msg, Matcher m, int i) throws ParseError
{
StringBuilder msg_ = new StringBuilder("Syntax error");
try
{
msg_.append(" at token '").append(m.group(0)).append("'");
} catch (IllegalStateException _e) {}
msg_.append(" at position ");
msg_.append(i);
msg_.append(": ");
msg_.append(msg);
throw new ParseError(msg_.toString());
}
public static class ParseError extends Exception
{
public ParseError(String msg) { super(msg); }
};
}

View File

@@ -62,7 +62,7 @@ public class Keyboard2 extends InputMethodService
{ {
if (_currentSpecialLayout != null) if (_currentSpecialLayout != null)
return _currentSpecialLayout; return _currentSpecialLayout;
return LayoutModifier.modify_layout(current_layout_unmodified()); return _config.modify_layout(current_layout_unmodified());
} }
void setTextLayout(int l) void setTextLayout(int l)
@@ -92,13 +92,13 @@ public class Keyboard2 extends InputMethodService
/** Load a layout that contains a numpad. */ /** Load a layout that contains a numpad. */
KeyboardData loadNumpad(int layout_id) KeyboardData loadNumpad(int layout_id)
{ {
return LayoutModifier.modify_numpad(KeyboardData.load(getResources(), layout_id), return _config.modify_numpad(KeyboardData.load(getResources(), layout_id),
current_layout_unmodified()); current_layout_unmodified());
} }
KeyboardData loadPinentry(int layout_id) KeyboardData loadPinentry(int layout_id)
{ {
return LayoutModifier.modify_pinentry(KeyboardData.load(getResources(), layout_id), return _config.modify_pinentry(KeyboardData.load(getResources(), layout_id),
current_layout_unmodified()); current_layout_unmodified());
} }
@@ -157,8 +157,6 @@ public class Keyboard2 extends InputMethodService
// Android might return a random subtype, for example, the first in the // Android might return a random subtype, for example, the first in the
// list alphabetically. // list alphabetically.
InputMethodSubtype current_subtype = imm.getCurrentInputMethodSubtype(); InputMethodSubtype current_subtype = imm.getCurrentInputMethodSubtype();
if (current_subtype == null)
return null;
for (InputMethodSubtype s : enabled_subtypes) for (InputMethodSubtype s : enabled_subtypes)
if (s.getLanguageTag().equals(current_subtype.getLanguageTag())) if (s.getLanguageTag().equals(current_subtype.getLanguageTag()))
return s; return s;
@@ -292,16 +290,6 @@ public class Keyboard2 extends InputMethodService
private void updateSoftInputWindowLayoutParams() { private void updateSoftInputWindowLayoutParams() {
final Window window = getWindow().getWindow(); final Window window = getWindow().getWindow();
// On API >= 35, Keyboard2View behaves as edge-to-edge
// APIs 30 to 34 have visual artifact when edge-to-edge is enabled
if (VERSION.SDK_INT >= 35)
{
WindowManager.LayoutParams wattrs = window.getAttributes();
wattrs.layoutInDisplayCutoutMode =
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
// Allow to draw behind system bars
wattrs.setFitInsetsTypes(0);
}
updateLayoutHeightOf(window, ViewGroup.LayoutParams.MATCH_PARENT); updateLayoutHeightOf(window, ViewGroup.LayoutParams.MATCH_PARENT);
final View inputArea = window.findViewById(android.R.id.inputArea); final View inputArea = window.findViewById(android.R.id.inputArea);

View File

@@ -42,12 +42,8 @@ public class Keyboard2View extends View
private Config _config; private Config _config;
private float _keyWidth; private float _keyWidth;
private float _marginRight;
private float _marginLeft;
private float _marginBottom;
private Theme _theme; private Theme _theme;
private Theme.Computed _tc;
private static RectF _tmpRect = new RectF(); private static RectF _tmpRect = new RectF();
@@ -105,6 +101,11 @@ public class Keyboard2View extends View
_keyboard = kw; _keyboard = kw;
_shift_kv = KeyValue.getKeyByName("shift"); _shift_kv = KeyValue.getKeyByName("shift");
_shift_key = _keyboard.findKeyWithValue(_shift_kv); _shift_key = _keyboard.findKeyWithValue(_shift_kv);
if (_shift_key == null)
{
_shift_kv = _shift_kv.withFlags(_shift_kv.getFlags() | KeyValue.FLAG_LOCK);
_shift_key = _keyboard.findKeyWithValue(_shift_kv);
}
_compose_kv = KeyValue.getKeyByName("compose"); _compose_kv = KeyValue.getKeyByName("compose");
_compose_key = _keyboard.findKeyWithValue(_compose_kv); _compose_key = _keyboard.findKeyWithValue(_compose_kv);
KeyModifier.set_modmap(_keyboard.modmap); KeyModifier.set_modmap(_keyboard.modmap);
@@ -230,7 +231,7 @@ public class Keyboard2View extends View
private KeyboardData.Key getKeyAtPosition(float tx, float ty) private KeyboardData.Key getKeyAtPosition(float tx, float ty)
{ {
KeyboardData.Row row = getRowAtPosition(ty); KeyboardData.Row row = getRowAtPosition(ty);
float x = _marginLeft; float x = _config.horizontal_margin;
if (row == null || tx < x) if (row == null || tx < x)
return null; return null;
for (KeyboardData.Key key : row.keys) for (KeyboardData.Key key : row.keys)
@@ -254,57 +255,24 @@ public class Keyboard2View extends View
@Override @Override
public void onMeasure(int wSpec, int hSpec) public void onMeasure(int wSpec, int hSpec)
{ {
int width; DisplayMetrics dm = getContext().getResources().getDisplayMetrics();
int insets_left = 0; int width = dm.widthPixels;
int insets_right = 0; int height =
int insets_bottom = 0; (int)(_config.keyHeight * _keyboard.keysHeight
// LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS is set in [Keyboard2#updateSoftInputWindowLayoutParams]. + _config.marginTop + _config.margin_bottom);
// and keyboard is allowed do draw behind status/navigation bars // Compatibility with display cutouts and navigation on the right
if (VERSION.SDK_INT >= 35) if (VERSION.SDK_INT >= 30)
{ {
WindowMetrics metrics = WindowMetrics metrics =
((WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE)) ((WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE))
.getCurrentWindowMetrics(); .getCurrentWindowMetrics();
width = metrics.getBounds().width(); Insets insets = metrics.getWindowInsets().getInsetsIgnoringVisibility(
WindowInsets wi = metrics.getWindowInsets(); WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars()
int insets_types = | WindowInsets.Type.displayCutout());
WindowInsets.Type.statusBars() width = metrics.getBounds().width() - insets.right - insets.left;
| WindowInsets.Type.displayCutout()
| WindowInsets.Type.mandatorySystemGestures()
| WindowInsets.Type.navigationBars();
Insets insets = wi.getInsets(insets_types);
insets_left = insets.left;
insets_right = insets.right;
// On API 35, the keyboard is allowed to draw under the
// button-navigation bar but on lower APIs, it must be discounted from
// the width.
if (VERSION.SDK_INT < 35)
{
Insets nav_insets = wi.getInsets(WindowInsets.Type.navigationBars());
width -= nav_insets.left + nav_insets.right;
insets_left -= nav_insets.left;
insets_right -= nav_insets.right;
} }
// [insets.bottom] doesn't take into account the buttons that appear in
// the gesture navigation bar when the IME is showing so ensure a minimum
// of margin is added.
if (VERSION.SDK_INT >= 35)
insets_bottom = Math.max(insets.bottom, _config.bottomInsetMin);
}
else
{
DisplayMetrics dm = getContext().getResources().getDisplayMetrics();
width = dm.widthPixels;
}
_marginLeft = Math.max(_config.horizontal_margin, insets_left);
_marginRight = Math.max(_config.horizontal_margin, insets_right);
_marginBottom = _config.margin_bottom + insets_bottom;
_keyWidth = (width - _marginLeft - _marginRight) / _keyboard.keysWidth;
_tc = new Theme.Computed(_theme, _config, _keyWidth);
int height =
(int)(_config.keyHeight * _keyboard.keysHeight
+ _config.marginTop + _marginBottom);
setMeasuredDimension(width, height); setMeasuredDimension(width, height);
_keyWidth = (width - (_config.horizontal_margin * 2)) / _keyboard.keysWidth;
} }
@Override @Override
@@ -316,10 +284,10 @@ public class Keyboard2View extends View
{ {
// Disable the back-gesture on the keyboard area // Disable the back-gesture on the keyboard area
Rect keyboard_area = new Rect( Rect keyboard_area = new Rect(
left + (int)_marginLeft, left + (int)_config.horizontal_margin,
top + (int)_config.marginTop, top + (int)_config.marginTop,
right - (int)_marginRight, right - (int)_config.horizontal_margin,
bottom - (int)_marginBottom); bottom - (int)_config.margin_bottom);
setSystemGestureExclusionRects(Arrays.asList(keyboard_area)); setSystemGestureExclusionRects(Arrays.asList(keyboard_area));
} }
} }
@@ -342,27 +310,34 @@ public class Keyboard2View extends View
{ {
// Set keyboard background opacity // Set keyboard background opacity
getBackground().setAlpha(_config.keyboardOpacity); getBackground().setAlpha(_config.keyboardOpacity);
float y = _tc.margin_top; // Set keys opacity
_theme.keyBgPaint.setAlpha(_config.keyOpacity);
_theme.keyDownBgPaint.setAlpha(_config.keyActivatedOpacity);
_theme.keyBorderPaint.setAlpha(_config.keyOpacity);
float key_vertical_margin = _config.key_vertical_margin * _config.keyHeight;
float key_horizontal_margin = _config.key_horizontal_margin * _keyWidth;
// Add half of the key margin on the left and on the top as it's then added
// on the right and on the bottom of every keys.
float y = _config.marginTop + key_vertical_margin / 2;
for (KeyboardData.Row row : _keyboard.rows) for (KeyboardData.Row row : _keyboard.rows)
{ {
y += row.shift * _config.keyHeight; y += row.shift * _config.keyHeight;
float x = _marginLeft + _tc.margin_left; float x = _config.horizontal_margin + key_horizontal_margin / 2;
float keyH = row.height * _config.keyHeight - _tc.vertical_margin; float keyH = row.height * _config.keyHeight - key_vertical_margin;
for (KeyboardData.Key k : row.keys) for (KeyboardData.Key k : row.keys)
{ {
x += k.shift * _keyWidth; x += k.shift * _keyWidth;
float keyW = _keyWidth * k.width - _tc.horizontal_margin; float keyW = _keyWidth * k.width - key_horizontal_margin;
boolean isKeyDown = _pointers.isKeyDown(k); boolean isKeyDown = _pointers.isKeyDown(k);
Theme.Computed.Key tc_key = isKeyDown ? _tc.key_activated : _tc.key; drawKeyFrame(canvas, x, y, keyW, keyH, isKeyDown);
drawKeyFrame(canvas, x, y, keyW, keyH, tc_key);
if (k.keys[0] != null) if (k.keys[0] != null)
drawLabel(canvas, k.keys[0], keyW / 2f + x, y, keyH, isKeyDown, tc_key); drawLabel(canvas, k.keys[0], keyW / 2f + x, y, keyH, isKeyDown);
for (int i = 1; i < 9; i++) for (int i = 1; i < 9; i++)
{ {
if (k.keys[i] != null) if (k.keys[i] != null)
drawSubLabel(canvas, k.keys[i], x, y, keyW, keyH, i, isKeyDown, tc_key); drawSubLabel(canvas, k.keys[i], x, y, keyW, keyH, i, isKeyDown);
} }
drawIndication(canvas, k, x, y, keyW, keyH, _tc); drawIndication(canvas, k, x, y, keyW, keyH);
x += _keyWidth * k.width; x += _keyWidth * k.width;
} }
y += row.height * _config.keyHeight; y += row.height * _config.keyHeight;
@@ -377,32 +352,42 @@ public class Keyboard2View extends View
/** Draw borders and background of the key. */ /** Draw borders and background of the key. */
void drawKeyFrame(Canvas canvas, float x, float y, float keyW, float keyH, void drawKeyFrame(Canvas canvas, float x, float y, float keyW, float keyH,
Theme.Computed.Key tc) boolean isKeyDown)
{ {
float r = tc.border_radius; float r = _theme.keyBorderRadius;
float w = tc.border_width; if (_config.borderConfig)
r = _config.customBorderRadius * _keyWidth;
float w = (_config.borderConfig) ? _config.customBorderLineWidth : _theme.keyBorderWidth;
float padding = w / 2.f; float padding = w / 2.f;
if (isKeyDown)
w = _theme.keyBorderWidthActivated;
_tmpRect.set(x + padding, y + padding, x + keyW - padding, y + keyH - padding); _tmpRect.set(x + padding, y + padding, x + keyW - padding, y + keyH - padding);
canvas.drawRoundRect(_tmpRect, r, r, tc.bg_paint); canvas.drawRoundRect(_tmpRect, r, r,
isKeyDown ? _theme.keyDownBgPaint : _theme.keyBgPaint);
if (w > 0.f) if (w > 0.f)
{ {
_theme.keyBorderPaint.setStrokeWidth(w);
float overlap = r - r * 0.85f + w; // sin(45°) float overlap = r - r * 0.85f + w; // sin(45°)
drawBorder(canvas, x, y, x + overlap, y + keyH, tc.border_left_paint, tc); drawBorder(canvas, x, y, x + overlap, y + keyH, _theme.keyBorderColorLeft);
drawBorder(canvas, x + keyW - overlap, y, x + keyW, y + keyH, tc.border_right_paint, tc); drawBorder(canvas, x + keyW - overlap, y, x + keyW, y + keyH, _theme.keyBorderColorRight);
drawBorder(canvas, x, y, x + keyW, y + overlap, tc.border_top_paint, tc); drawBorder(canvas, x, y, x + keyW, y + overlap, _theme.keyBorderColorTop);
drawBorder(canvas, x, y + keyH - overlap, x + keyW, y + keyH, tc.border_bottom_paint, tc); drawBorder(canvas, x, y + keyH - overlap, x + keyW, y + keyH, _theme.keyBorderColorBottom);
} }
} }
/** Clip to draw a border at a time. This allows to call [drawRoundRect] /** Clip to draw a border at a time. This allows to call [drawRoundRect]
several time with the same parameters but a different Paint. */ several time with the same parameters but a different Paint. */
void drawBorder(Canvas canvas, float clipl, float clipt, float clipr, void drawBorder(Canvas canvas, float clipl, float clipt, float clipr,
float clipb, Paint paint, Theme.Computed.Key tc) float clipb, int color)
{ {
float r = tc.border_radius; Paint p = _theme.keyBorderPaint;
float r = _theme.keyBorderRadius;
if (_config.borderConfig)
r = _config.customBorderRadius * _keyWidth;
canvas.save(); canvas.save();
canvas.clipRect(clipl, clipt, clipr, clipb); canvas.clipRect(clipl, clipt, clipr, clipb);
canvas.drawRoundRect(_tmpRect, r, r, paint); p.setColor(color);
canvas.drawRoundRect(_tmpRect, r, r, p);
canvas.restore(); canvas.restore();
} }
@@ -427,21 +412,21 @@ public class Keyboard2View extends View
return sublabel ? _theme.subLabelColor : _theme.labelColor; return sublabel ? _theme.subLabelColor : _theme.labelColor;
} }
private void drawLabel(Canvas canvas, KeyValue kv, float x, float y, private void drawLabel(Canvas canvas, KeyValue kv, float x, float y, float keyH, boolean isKeyDown)
float keyH, boolean isKeyDown, Theme.Computed.Key tc)
{ {
kv = modifyKey(kv, _mods); kv = modifyKey(kv, _mods);
if (kv == null) if (kv == null)
return; return;
float textSize = scaleTextSize(kv, _config.labelTextSize, keyH); float textSize = scaleTextSize(kv, _config.labelTextSize, keyH);
Paint p = tc.label_paint(kv.hasFlagsAny(KeyValue.FLAG_KEY_FONT), textSize); Paint p = _theme.labelPaint(kv.hasFlagsAny(KeyValue.FLAG_KEY_FONT));
p.setColor(labelColor(kv, isKeyDown, false)); p.setColor(labelColor(kv, isKeyDown, false));
p.setAlpha(_config.labelBrightness);
p.setTextSize(textSize);
canvas.drawText(kv.getString(), x, (keyH - p.ascent() - p.descent()) / 2f + y, p); canvas.drawText(kv.getString(), x, (keyH - p.ascent() - p.descent()) / 2f + y, p);
} }
private void drawSubLabel(Canvas canvas, KeyValue kv, float x, float y, private void drawSubLabel(Canvas canvas, KeyValue kv, float x, float y,
float keyW, float keyH, int sub_index, boolean isKeyDown, float keyW, float keyH, int sub_index, boolean isKeyDown)
Theme.Computed.Key tc)
{ {
Paint.Align a = LABEL_POSITION_H[sub_index]; Paint.Align a = LABEL_POSITION_H[sub_index];
Vertical v = LABEL_POSITION_V[sub_index]; Vertical v = LABEL_POSITION_V[sub_index];
@@ -449,8 +434,10 @@ public class Keyboard2View extends View
if (kv == null) if (kv == null)
return; return;
float textSize = scaleTextSize(kv, _config.sublabelTextSize, keyH); float textSize = scaleTextSize(kv, _config.sublabelTextSize, keyH);
Paint p = tc.sublabel_paint(kv.hasFlagsAny(KeyValue.FLAG_KEY_FONT), textSize, a); Paint p = _theme.subLabelPaint(kv.hasFlagsAny(KeyValue.FLAG_KEY_FONT), a);
p.setColor(labelColor(kv, isKeyDown, true)); p.setColor(labelColor(kv, isKeyDown, true));
p.setAlpha(_config.labelBrightness);
p.setTextSize(textSize);
float subPadding = _config.keyPadding; float subPadding = _config.keyPadding;
if (v == Vertical.CENTER) if (v == Vertical.CENTER)
y += (keyH - p.ascent() - p.descent()) / 2f; y += (keyH - p.ascent() - p.descent()) / 2f;
@@ -469,13 +456,34 @@ public class Keyboard2View extends View
} }
private void drawIndication(Canvas canvas, KeyboardData.Key k, float x, private void drawIndication(Canvas canvas, KeyboardData.Key k, float x,
float y, float keyW, float keyH, Theme.Computed tc) float y, float keyW, float keyH)
{
boolean special_font = false;
String indic;
int indic_length;
float text_size;
if (k.indication != null)
{
indic = k.indication;
indic_length = indic.length();
text_size = keyH * _config.sublabelTextSize * _config.characterSize;
}
else if (k.anticircle != null)
{
indic = k.anticircle.getString();
// 3 character limit like regular labels
indic_length = Math.min(indic.length(), 3);
special_font = k.anticircle.hasFlagsAny(KeyValue.FLAG_KEY_FONT);
text_size = scaleTextSize(k.anticircle, _config.sublabelTextSize, keyH);
}
else
{ {
if (k.indication == null || k.indication.equals(""))
return; return;
Paint p = tc.indication_paint; }
p.setTextSize(keyH * _config.sublabelTextSize * _config.characterSize); Paint p = _theme.indicationPaint(special_font);
canvas.drawText(k.indication, 0, k.indication.length(), p.setColor(_theme.subLabelColor);
p.setTextSize(text_size);
canvas.drawText(indic, 0, indic_length,
x + keyW / 2f, (keyH - p.ascent() - p.descent()) * 4/5 + y, p); x + keyW / 2f, (keyH - p.ascent() - p.descent()) * 4/5 + y, p);
} }

View File

@@ -31,8 +31,6 @@ public final class KeyboardData
public final String name; public final String name;
/** Whether the bottom row should be added. */ /** Whether the bottom row should be added. */
public final boolean bottom_row; public final boolean bottom_row;
/** Whether the number row is included in the layout and thus another one shouldn't be added. */
public final boolean embedded_number_row;
/** Whether extra keys from [method.xml] should be added to this layout. */ /** Whether extra keys from [method.xml] should be added to this layout. */
public final boolean locale_extra_keys; public final boolean locale_extra_keys;
/** Position of every keys on the layout, see [getKeys()]. */ /** Position of every keys on the layout, see [getKeys()]. */
@@ -195,22 +193,21 @@ public final class KeyboardData
/** Load a layout from a resource ID. Returns [null] on error. */ /** Load a layout from a resource ID. Returns [null] on error. */
public static KeyboardData load(Resources res, int id) public static KeyboardData load(Resources res, int id)
{ {
if (_layoutCache.containsKey(id)) KeyboardData l = _layoutCache.get(id);
return _layoutCache.get(id); if (l == null)
KeyboardData l = null; {
XmlResourceParser parser = null;
try try
{ {
parser = res.getXml(id); XmlResourceParser parser = res.getXml(id);
l = parse_keyboard(parser); l = parse_keyboard(parser);
parser.close();
_layoutCache.put(id, l);
} }
catch (Exception e) catch (Exception e)
{ {
Logs.exn("Failed to load layout id " + id, e); e.printStackTrace();
}
} }
if (parser != null)
parser.close();
_layoutCache.put(id, l);
return l; return l;
} }
@@ -241,7 +238,6 @@ public final class KeyboardData
if (!expect_tag(parser, "keyboard")) if (!expect_tag(parser, "keyboard"))
throw error(parser, "Expected tag <keyboard>"); throw error(parser, "Expected tag <keyboard>");
boolean bottom_row = attribute_bool(parser, "bottom_row", true); boolean bottom_row = attribute_bool(parser, "bottom_row", true);
boolean embedded_number_row = attribute_bool(parser, "embedded_number_row", false);
boolean locale_extra_keys = attribute_bool(parser, "locale_extra_keys", true); boolean locale_extra_keys = attribute_bool(parser, "locale_extra_keys", true);
float specified_kw = attribute_float(parser, "width", 0f); float specified_kw = attribute_float(parser, "width", 0f);
String script = parser.getAttributeValue(null, "script"); String script = parser.getAttributeValue(null, "script");
@@ -272,7 +268,7 @@ public final class KeyboardData
} }
} }
float kw = (specified_kw != 0f) ? specified_kw : compute_max_width(rows); float kw = (specified_kw != 0f) ? specified_kw : compute_max_width(rows);
return new KeyboardData(rows, kw, modmap, script, numpad_script, name, bottom_row, embedded_number_row, locale_extra_keys); return new KeyboardData(rows, kw, modmap, script, numpad_script, name, bottom_row, locale_extra_keys);
} }
private static float compute_max_width(List<Row> rows) private static float compute_max_width(List<Row> rows)
@@ -291,7 +287,7 @@ public final class KeyboardData
} }
protected KeyboardData(List<Row> rows_, float kw, Modmap mm, String sc, protected KeyboardData(List<Row> rows_, float kw, Modmap mm, String sc,
String npsc, String name_, boolean bottom_row_, boolean embedded_number_row_, boolean locale_extra_keys_) String npsc, String name_, boolean bottom_row_, boolean locale_extra_keys_)
{ {
float kh = 0.f; float kh = 0.f;
for (Row r : rows_) for (Row r : rows_)
@@ -304,7 +300,6 @@ public final class KeyboardData
keysWidth = Math.max(kw, 1f); keysWidth = Math.max(kw, 1f);
keysHeight = kh; keysHeight = kh;
bottom_row = bottom_row_; bottom_row = bottom_row_;
embedded_number_row = embedded_number_row_;
locale_extra_keys = locale_extra_keys_; locale_extra_keys = locale_extra_keys_;
} }
@@ -312,7 +307,7 @@ public final class KeyboardData
protected KeyboardData(KeyboardData src, List<Row> rows) protected KeyboardData(KeyboardData src, List<Row> rows)
{ {
this(rows, compute_max_width(rows), src.modmap, src.script, this(rows, compute_max_width(rows), src.modmap, src.script,
src.numpad_script, src.name, src.bottom_row, src.embedded_number_row, src.locale_extra_keys); src.numpad_script, src.name, src.bottom_row, src.locale_extra_keys);
} }
public static class Row public static class Row
@@ -405,6 +400,9 @@ public final class KeyboardData
public final float width; public final float width;
/** Extra empty space on the left of the key. */ /** Extra empty space on the left of the key. */
public final float shift; public final float shift;
/** Keys 2 and 3 are repeated as the finger moves laterally on the key.
Used for the left and right arrow keys on the space bar. */
public final boolean slider;
/** String printed on the keys. It has no other effect. */ /** String printed on the keys. It has no other effect. */
public final String indication; public final String indication;
@@ -412,13 +410,14 @@ public final class KeyboardData
public static final int F_LOC = 1; public static final int F_LOC = 1;
public static final int ALL_FLAGS = F_LOC; public static final int ALL_FLAGS = F_LOC;
protected Key(KeyValue[] ks, KeyValue antic, int f, float w, float s, String i) protected Key(KeyValue[] ks, KeyValue antic, int f, float w, float s, boolean sl, String i)
{ {
keys = ks; keys = ks;
anticircle = antic; anticircle = antic;
keysflags = f; keysflags = f;
width = Math.max(w, 0f); width = Math.max(w, 0f);
shift = Math.max(s, 0f); shift = Math.max(s, 0f);
slider = sl;
indication = i; indication = i;
} }
@@ -473,7 +472,7 @@ public final class KeyboardData
{ {
KeyValue[] ks = new KeyValue[9]; KeyValue[] ks = new KeyValue[9];
int keysflags = 0; int keysflags = 0;
keysflags |= parse_key_attr(parser, get_key_attr(parser, "key0", "c"), ks, 0); keysflags |= parse_key_attr(parser, parser.getAttributeValue(null, "key0"), ks, 0);
/* Swipe gestures (key1-key8 diagram above), with compass-point synonyms. */ /* Swipe gestures (key1-key8 diagram above), with compass-point synonyms. */
keysflags |= parse_key_attr(parser, get_key_attr(parser, "key1", "nw"), ks, 1); keysflags |= parse_key_attr(parser, get_key_attr(parser, "key1", "nw"), ks, 1);
keysflags |= parse_key_attr(parser, get_key_attr(parser, "key2", "ne"), ks, 2); keysflags |= parse_key_attr(parser, get_key_attr(parser, "key2", "ne"), ks, 2);
@@ -487,10 +486,11 @@ public final class KeyboardData
KeyValue anticircle = parse_nonloc_key_attr(parser, "anticircle"); KeyValue anticircle = parse_nonloc_key_attr(parser, "anticircle");
float width = attribute_float(parser, "width", 1f); float width = attribute_float(parser, "width", 1f);
float shift = attribute_float(parser, "shift", 0.f); float shift = attribute_float(parser, "shift", 0.f);
boolean slider = attribute_bool(parser, "slider", false);
String indication = parser.getAttributeValue(null, "indication"); String indication = parser.getAttributeValue(null, "indication");
while (parser.next() != XmlPullParser.END_TAG) while (parser.next() != XmlPullParser.END_TAG)
continue; continue;
return new Key(ks, anticircle, keysflags, width, shift, indication); return new Key(ks, anticircle, keysflags, width, shift, slider, indication);
} }
/** Whether key at [index] as [flag]. */ /** Whether key at [index] as [flag]. */
@@ -502,7 +502,8 @@ public final class KeyboardData
/** New key with the width multiplied by 's'. */ /** New key with the width multiplied by 's'. */
public Key scaleWidth(float s) public Key scaleWidth(float s)
{ {
return new Key(keys, anticircle, keysflags, width * s, shift, indication); return new Key(keys, anticircle, keysflags, width * s, shift, slider,
indication);
} }
public void getKeys(Map<KeyValue, KeyPos> dst, int row, int col) public void getKeys(Map<KeyValue, KeyPos> dst, int row, int col)
@@ -523,12 +524,12 @@ public final class KeyboardData
for (int j = 0; j < keys.length; j++) ks[j] = keys[j]; for (int j = 0; j < keys.length; j++) ks[j] = keys[j];
ks[i] = kv; ks[i] = kv;
int flags = (keysflags & ~(ALL_FLAGS << i)); int flags = (keysflags & ~(ALL_FLAGS << i));
return new Key(ks, anticircle, flags, width, shift, indication); return new Key(ks, anticircle, flags, width, shift, slider, indication);
} }
public Key withShift(float s) public Key withShift(float s)
{ {
return new Key(keys, anticircle, keysflags, width, s, indication); return new Key(keys, anticircle, keysflags, width, s, slider, indication);
} }
public boolean hasValue(KeyValue kv) public boolean hasValue(KeyValue kv)
@@ -554,7 +555,7 @@ public final class KeyboardData
for (int i = 0; i < ks.length; i++) for (int i = 0; i < ks.length; i++)
if (k.keys[i] != null) if (k.keys[i] != null)
ks[i] = apply(k.keys[i], k.keyHasFlag(i, Key.F_LOC)); ks[i] = apply(k.keys[i], k.keyHasFlag(i, Key.F_LOC));
return new Key(ks, k.anticircle, k.keysflags, k.width, k.shift, k.indication); return new Key(ks, k.anticircle, k.keysflags, k.width, k.shift, k.slider, k.indication);
} }
} }

View File

@@ -3,14 +3,11 @@ package juloo.keyboard2;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.app.Activity; import android.app.Activity;
import android.content.Intent; import android.content.Intent;
import android.graphics.drawable.Animatable;
import android.media.AudioManager; import android.media.AudioManager;
import android.media.MediaPlayer; import android.media.MediaPlayer;
import android.net.Uri; import android.net.Uri;
import android.os.Build.VERSION; import android.os.Build.VERSION;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.Settings; import android.provider.Settings;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.Menu; import android.view.Menu;
@@ -18,51 +15,28 @@ import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import java.util.ArrayList; import android.widget.VideoView;
import java.util.List;
public class LauncherActivity extends Activity implements Handler.Callback public class LauncherActivity extends Activity
{ {
/** Text is replaced when receiving key events. */ /** Text is replaced when receiving key events. */
VideoView _intro_video;
TextView _tryhere_text; TextView _tryhere_text;
EditText _tryhere_area; EditText _tryhere_area;
/** Periodically restart the animations. */
List<Animatable> _animations;
Handler _handler;
@Override @Override
public void onCreate(Bundle savedInstanceState) public void onCreate(Bundle savedInstanceState)
{ {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.launcher_activity); setContentView(R.layout.launcher_activity);
_intro_video = (VideoView)findViewById(R.id.launcher_intro_video);
_tryhere_text = (TextView)findViewById(R.id.launcher_tryhere_text); _tryhere_text = (TextView)findViewById(R.id.launcher_tryhere_text);
_tryhere_area = (EditText)findViewById(R.id.launcher_tryhere_area); _tryhere_area = (EditText)findViewById(R.id.launcher_tryhere_area);
if (VERSION.SDK_INT >= 28) if (VERSION.SDK_INT >= 28)
_tryhere_area.addOnUnhandledKeyEventListener( _tryhere_area.addOnUnhandledKeyEventListener(
this.new Tryhere_OnUnhandledKeyEventListener()); this.new Tryhere_OnUnhandledKeyEventListener());
} setup_intro_video(_intro_video);
@Override
public void onStart()
{
super.onStart();
_animations = new ArrayList<Animatable>();
_animations.add(find_anim(R.id.launcher_anim_swipe));
_animations.add(find_anim(R.id.launcher_anim_round_trip));
_animations.add(find_anim(R.id.launcher_anim_circle));
_handler = new Handler(getMainLooper(), this);
_handler.sendEmptyMessageDelayed(0, 500);
}
@Override
public boolean handleMessage(Message _msg)
{
for (Animatable anim : _animations)
anim.start();
_handler.sendEmptyMessageDelayed(0, 3000);
return true;
} }
@Override @Override
@@ -96,10 +70,31 @@ public class LauncherActivity extends Activity implements Handler.Callback
imm.showInputMethodPicker(); imm.showInputMethodPicker();
} }
Animatable find_anim(int id) static void setup_intro_video(final VideoView v)
{ {
ImageView img = (ImageView)findViewById(id); if (VERSION.SDK_INT >= 26)
return (Animatable)img.getDrawable(); v.setAudioFocusRequest(AudioManager.AUDIOFOCUS_NONE);
v.setVideoURI(Uri.parse("android.resource://" +
v.getContext().getPackageName() + "/" + R.raw.intro_video));
v.setOnPreparedListener(new MediaPlayer.OnPreparedListener()
{
@Override
public void onPrepared(MediaPlayer mp)
{
mp.setLooping(true);
}
});
v.setOnErrorListener(new MediaPlayer.OnErrorListener()
{
@Override
public boolean onError(MediaPlayer mp, int what, int extra)
{
v.stopPlayback();
v.setVisibility(View.GONE);
return true;
}
});
v.start();
} }
@TargetApi(28) @TargetApi(28)

View File

@@ -1,216 +0,0 @@
package juloo.keyboard2;
import android.content.res.Resources;
import android.view.KeyEvent;
import java.util.TreeMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public final class LayoutModifier
{
static Config globalConfig;
static KeyboardData.Row bottom_row;
static KeyboardData.Row number_row;
static KeyboardData num_pad;
/** Update the layout according to the configuration.
* - Remove the switching key if it isn't needed
* - Remove "localized" keys from other locales (not in 'extra_keys')
* - Replace the action key to show the right label
* - Swap the enter and action keys
* - Add the optional numpad and number row
* - Add the extra keys
*/
public static KeyboardData modify_layout(KeyboardData kw)
{
// Extra keys are removed from the set as they are encountered during the
// first iteration then automatically added.
final TreeMap<KeyValue, KeyboardData.PreferredPos> extra_keys = new TreeMap<KeyValue, KeyboardData.PreferredPos>();
final Set<KeyValue> remove_keys = new HashSet<KeyValue>();
// Make sure the config key is accessible to avoid being locked in a custom
// layout.
extra_keys.put(KeyValue.getKeyByName("config"), KeyboardData.PreferredPos.ANYWHERE);
extra_keys.putAll(globalConfig.extra_keys_param);
extra_keys.putAll(globalConfig.extra_keys_custom);
// Number row and numpads are added after the modification pass to allow
// removing the number keys from the main layout.
KeyboardData.Row added_number_row = null;
KeyboardData added_numpad = null;
if (globalConfig.show_numpad)
{
added_numpad = modify_numpad(num_pad, kw);
remove_keys.addAll(added_numpad.getKeys().keySet());
}
else if (globalConfig.add_number_row && !kw.embedded_number_row) // The numpad removes the number row
{
added_number_row = modify_number_row(number_row, kw);
remove_keys.addAll(added_number_row.getKeys(0).keySet());
}
// Add the bottom row before computing the extra keys
if (kw.bottom_row)
kw = kw.insert_row(bottom_row, kw.rows.size());
// Compose keys to add to the layout
// 'extra_keys_keyset' reflects changes made to 'extra_keys'
Set<KeyValue> extra_keys_keyset = extra_keys.keySet();
// 'kw_keys' contains the keys present on the layout without any extra keys
Set<KeyValue> kw_keys = kw.getKeys().keySet();
if (globalConfig.extra_keys_subtype != null && kw.locale_extra_keys)
{
Set<KeyValue> present = new HashSet<KeyValue>(kw_keys);
present.addAll(extra_keys_keyset);
globalConfig.extra_keys_subtype.compute(extra_keys,
new ExtraKeys.Query(kw.script, present));
}
kw = kw.mapKeys(new KeyboardData.MapKeyValues() {
public KeyValue apply(KeyValue key, boolean localized)
{
if (localized && !extra_keys.containsKey(key))
return null;
if (remove_keys.contains(key))
return null;
return modify_key(key);
}
});
if (added_numpad != null)
kw = kw.addNumPad(added_numpad);
// Add extra keys that are not on the layout (including 'loc' keys)
extra_keys_keyset.removeAll(kw_keys);
if (extra_keys.size() > 0)
kw = kw.addExtraKeys(extra_keys.entrySet().iterator());
// Avoid adding extra keys to the number row
if (added_number_row != null)
kw = kw.insert_row(added_number_row, 0);
return kw;
}
/** Handle the numpad layout. The [main_kw] is used to adapt the numpad to
the main layout's script. */
public static KeyboardData modify_numpad(KeyboardData kw, KeyboardData main_kw)
{
final int map_digit = KeyModifier.modify_numpad_script(main_kw.numpad_script);
return kw.mapKeys(new KeyboardData.MapKeyValues() {
public KeyValue apply(KeyValue key, boolean localized)
{
switch (key.getKind())
{
case Char:
char prev_c = key.getChar();
char c = prev_c;
if (globalConfig.inverse_numpad)
c = inverse_numpad_char(c);
if (map_digit != -1)
{
KeyValue modified = ComposeKey.apply(map_digit, c);
if (modified != null) // Was modified by script
return modified;
}
if (prev_c != c) // Was inverted
return key.withChar(c);
return key; // Don't fallback into [modify_key]
}
return modify_key(key);
}
});
}
/** Modify the pin entry layout. [main_kw] is used to map the digits into the
same script. */
public static KeyboardData modify_pinentry(KeyboardData kw, KeyboardData main_kw)
{
KeyboardData.MapKeyValues m = numpad_script_map(main_kw.numpad_script);
return m == null ? kw : kw.mapKeys(m);
}
/** Modify the number row according to [main_kw]'s script. */
static KeyboardData.Row modify_number_row(KeyboardData.Row row,
KeyboardData main_kw)
{
KeyboardData.MapKeyValues m = numpad_script_map(main_kw.numpad_script);
return m == null ? row : row.mapKeys(m);
}
static KeyboardData.MapKeyValues numpad_script_map(String numpad_script)
{
final int map_digit = KeyModifier.modify_numpad_script(numpad_script);
if (map_digit == -1)
return null;
return new KeyboardData.MapKeyValues() {
public KeyValue apply(KeyValue key, boolean localized)
{
KeyValue modified = ComposeKey.apply(map_digit, key);
return (modified != null) ? modified : key;
}
};
}
/** Modify keys on the main layout and on the numpad according to the config.
*/
static KeyValue modify_key(KeyValue orig)
{
switch (orig.getKind())
{
case Event:
switch (orig.getEvent())
{
case CHANGE_METHOD_PICKER:
if (globalConfig.switch_input_immediate)
return KeyValue.getKeyByName("change_method_prev");
break;
case ACTION:
if (globalConfig.actionLabel == null)
return null; // Remove the action key
if (globalConfig.swapEnterActionKey)
return KeyValue.getKeyByName("enter");
return KeyValue.makeActionKey(globalConfig.actionLabel);
case SWITCH_FORWARD:
return (globalConfig.layouts.size() > 1) ? orig : null;
case SWITCH_BACKWARD:
return (globalConfig.layouts.size() > 2) ? orig : null;
case SWITCH_VOICE_TYPING:
case SWITCH_VOICE_TYPING_CHOOSER:
return globalConfig.shouldOfferVoiceTyping ? orig : null;
}
break;
case Keyevent:
switch (orig.getKeyevent())
{
case KeyEvent.KEYCODE_ENTER:
if (globalConfig.swapEnterActionKey && globalConfig.actionLabel != null)
return KeyValue.makeActionKey(globalConfig.actionLabel);
break;
}
break;
}
return orig;
}
static char inverse_numpad_char(char c)
{
switch (c)
{
case '7': return '1';
case '8': return '2';
case '9': return '3';
case '1': return '7';
case '2': return '8';
case '3': return '9';
default: return c;
}
}
public static void init(Config globalConfig_, Resources res)
{
globalConfig = globalConfig_;
try
{
number_row = KeyboardData.load_number_row(res);
bottom_row = KeyboardData.load_bottom_row(res);
num_pad = KeyboardData.load_num_pad(res);
}
catch (Exception e)
{
throw new RuntimeException(e.getMessage()); // Not recoverable
}
}
}

Some files were not shown because too many files have changed in this diff Show More