keyboardlayouteditor

[Fork] Archive of the keyboard layout editor.
git clone https://git.jojolepro.com/keyboardlayouteditor.git
Log | Files | Refs | README | LICENSE

commit cbf82ad0f1f973a9a1c3c3845be3c65b70e8fa6b
parent 70f8b14d888872225ecf4259e9aa42202bd8a40a
Author: simos.lists <simos.lists@70737e48-4f4a-0410-8df8-290828ad50c4>
Date:   Sun,  7 Sep 2008 14:05:09 +0000

Initial import of source code.

git-svn-id: http://keyboardlayouteditor.googlecode.com/svn/trunk@58 70737e48-4f4a-0410-8df8-290828ad50c4

Diffstat:
AKeyboardLayoutEditor/.project | 23+++++++++++++++++++++++
AKeyboardLayoutEditor/.pydevproject | 9+++++++++
AKeyboardLayoutEditor/.settings/org.eclipse.ltk.core.refactoring.prefs | 3+++
AKeyboardLayoutEditor/README.txt | 31+++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/COPYING | 674+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/Common.py | 97+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/DeadKeysDict.py | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/Disconnect. | 1+
AKeyboardLayoutEditor/src/DumbKey.py | 298+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/Enum.py | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/GenericLayout.py | 188+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/Key.py | 184+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/KeyDict.py | 127+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/KeyValue.py | 147+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/Keyboard.py | 173+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/KeyboardLayoutEditor.py | 937+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/Keycodes.g | 110+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/KeycodesReader.py | 126+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/KeycodesWalker.g | 34++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/Keysyms.py | 2007+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/KeysymsUni.py | 1390+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/KeysymsUniByValue.py | 1323+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/ParseXKB.py | 511+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/ParseXML.py | 181+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/README.txt | 41+++++++++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/SelectVariant.py | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/XKBGrammar.g | 203+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/XKBGrammarWalker.g | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/aliases | 99+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/evdev | 302++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/kle-icon.svg | 2924+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/kle-icon2.svg | 2947+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/kle-icon3.svg | 2932+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/kle-icon4.svg | 8347+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/parse_xkb_to_xml.py | 284+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/parse_xml_to_xkb.py | 106+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/print_tree.py | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/utils/Keysyms.g | 46++++++++++++++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/utils/KeysymsWalker.g | 20++++++++++++++++++++
AKeyboardLayoutEditor/src/utils/extract_keysymdefh.py | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/utils/extract_keysymstxt.py | 134+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/utils/keysymdef.h | 2374+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/utils/keysyms.txt | 1801+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AKeyboardLayoutEditor/src/xfree86 | 417+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
44 files changed, 31965 insertions(+), 0 deletions(-)

diff --git a/KeyboardLayoutEditor/.project b/KeyboardLayoutEditor/.project @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>KeyboardLayoutEditor</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.dltk.core.scriptbuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.python.pydev.PyDevBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.python.pydev.pythonNature</nature> + <nature>org.deved.antlride.core.nature</nature> + </natures> +</projectDescription> diff --git a/KeyboardLayoutEditor/.pydevproject b/KeyboardLayoutEditor/.pydevproject @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<?eclipse-pydev version="1.0"?> + +<pydev_project> +<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH"> +<path>/KeyboardLayoutEditor/src</path> +</pydev_pathproperty> +<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.5</pydev_property> +</pydev_project> diff --git a/KeyboardLayoutEditor/.settings/org.eclipse.ltk.core.refactoring.prefs b/KeyboardLayoutEditor/.settings/org.eclipse.ltk.core.refactoring.prefs @@ -0,0 +1,3 @@ +#Wed Aug 06 11:11:43 BST 2008 +eclipse.preferences.version=1 +org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false diff --git a/KeyboardLayoutEditor/README.txt b/KeyboardLayoutEditor/README.txt @@ -0,0 +1,31 @@ +This is the Keyboard Layout Editor, a pygtk program that helps create or edit XKB keyboard layouts. + +This is the version that has been submitted to the GSoC xorg project; you can find the latest version +at +http://code.google.com/p/keyboardlayouteditor/ + +You are strongly encouraged to use the version that is found at the above URL, +as it includes several bug fixes. + +The project was developed using Eclipse (Ganymede), with the Python (PyDev) and Antlr (AntlrIDE) add-ons. +If you also have SVN support in Eclipse, you can grab the latest source from within Eclipse. +There is also integration with Mylene so that you can get the list of issues/bugs/todo items +automatically. + +To run the application, you need the python binding packages for +* Cairo +* Pango +* GObject +* lxml + +and the Antlr 3.1 Runtime environment for Python. You grab that at +http://antlr.org/download/Python/ +Choose the appropriate *.egg file for the 3.1 version, then type + +sudo easy_install antlr_python_runtime-3.1-py2.5.egg + +This should to the installation for you. + +You run this program with + +./KeyboardLayoutEditor.py diff --git a/KeyboardLayoutEditor/src/COPYING b/KeyboardLayoutEditor/src/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + <program> Copyright (C) <year> <name of author> + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<http://www.gnu.org/licenses/>. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +<http://www.gnu.org/philosophy/why-not-lgpl.html>. diff --git a/KeyboardLayoutEditor/src/Common.py b/KeyboardLayoutEditor/src/Common.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python +# -*- encoding: UTF-8 -*- +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/> + +import cairo +import Enum + +keytypes = Enum.Enum("SIMPLE SPECIAL").vals(illegal=255) +alignments = Enum.Enum("LEFT CENTRE RIGHT").vals(illegal=255) +keysegments = Enum.Enum("ALL ONE TWO THREE FOUR NONE").vals(illegal=255) +keyvaluetype = Enum.Enum("UNICHAR CODEPOINT KEYSYM CONSTANT DEADKEY ANY VOIDSYMBOL NOSYMBOL NOACTION VERBATIM").vals(illegal=255) + +keysegmentslist = [keysegments.ONE, keysegments.TWO, + keysegments.THREE, keysegments.FOUR] +keysegmentslistreverse = list(keysegmentslist) +keysegmentslistreverse.reverse() + +fontname = "Sans" +fontstyle = cairo.FONT_SLANT_NORMAL +fontweight = cairo.FONT_WEIGHT_NORMAL +fontsize = 12 + +gucharmappath = "/usr/bin/gucharmap" + +# The Xkeyboard-Config path +xkcpath = "/etc/X11/xkb" +xkcsymbols = xkcpath + "/symbols" + +# The program icon +KLEiconfile = "kleiconfile.ico" + +# Max levels, currently 4. May go 8 in future. +LEVELMAX = 4 + +# The application's official full name. +applicationname="Keyboard Layout Editor" + +# Holds the current filename. +currentlayoutfile='' + +# The directory to the xkeyboard-config base directory. +basedir = '/etc/X11/xkb/' + +# The directory to the xkeyboard-config symbols directory. +symbolsdir = basedir + 'symbols/' + +# A gtk.Statusbar object, shared, so that all can write to. +statusbar = None + +# Default dead key. +deadkey = "dead_acute" + +# Text that appears when saving a keyboard layout (appears in text file, at start +layout_preamble = """///////////////////////////////////////////////////////////////////////////////// +// +// Generated keyboard layout file with the Keyboard Layout Editor. +// For more about the software, see http://code.google.com/p/keyboardlayouteditor +// + +""" + +# Sorts a dictionary by value, produces a sorted list of values. +def sortDict(adict, cmp_function = None): + keys = adict.keys() + keys.sort(cmp_function) + return map(adict.get, keys) + +def addtostatusbar(message): + statusbar.push(statusbar.console_context, message) + +def parseIncludeString(include): + """ + Parses strings of the form 'us(intl)', 'us', and produces + { 'filename': 'us', 'variant': 'intl' }, { 'filename': 'us', 'variant': 'basic' } + """ + if include.partition('(')[1] == '(': + return { 'filename': include.partition('(')[0], 'variant': include.partition('(')[2].partition(')')[0] } + else: + return { 'filename': include.partition('(')[0], 'variant': '' } + +if __name__ == '__main__': + print parseIncludeString('us') + print parseIncludeString('us(level1)') + + diff --git a/KeyboardLayoutEditor/src/DeadKeysDict.py b/KeyboardLayoutEditor/src/DeadKeysDict.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python +# -*- encoding: UTF-8 -*- +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/> + +class DeadKeysClass: + def __init__(self): + self.dict = { + 'dead_grave' : ('Grave', '`'), + 'dead_acute' : ('Acute', '´'), + 'dead_circumflex' : ('Circumflex', '^'), + 'dead_tilde' : ('Tilde', '~'), + 'dead_perispomeni' : ('Perispomeni', '῀'), + 'dead_macron' : ('Macron', 'ˉ'), + 'dead_breve' : ('Breve', '˘'), + 'dead_abovedot' : ('Abovedot', '˙'), + 'dead_diaeresis' : ('Diaeresis', '¨'), + 'dead_abovering' : ('Abovering', '˚'), + 'dead_doubleacute' : ('Double Acute', '˝'), + 'dead_caron' : ('Caron', 'ˇ'), + 'dead_cedilla' : ('Cedilla', '¸'), + 'dead_ogonek' : ('Ogonek', '˛'), + 'dead_iota' : ('Iota', 'ͺ'), + 'dead_voiced_sound' : ('Voiced Sound', '゙'), # TODO (maybe) + 'dead_semivoiced_sound' : ('Semivoiced Sound', '゚'), # TODO (maybe) + 'dead_belowdot' : ('Below Dot', '?'), # TODO + 'dead_hook' : ('Hook', '?'), # TODO + 'dead_horn' : ('Horn', '?'), # TODO + 'dead_stroke' : ('Stroke', '?'), # TODO + 'dead_abovecomma' : ('Above Comma', '?'), # TODO + 'dead_psili' : ('Psili', '?'), # TODO + 'dead_abovereversedcomma' : ('Above Reversed Comma', 'ʽ'), + 'dead_dasia' : ('Dasia', '῾'), + 'dead_belowring' : ('Below Ring', '˳'), + 'dead_belowmacron' : ('Below Macron', 'ˍ'), + 'dead_belowcircumflex' : ('Below Circumflex', 'ˬ'), + 'dead_belowtilde' : ('Below Tilde', '˷'), + 'dead_belowbreve' : ('Below Breve', '?'), # TODO + 'dead_belowdiaeresis' : ('Below Diaeresis', '?') } # TODO + +DeadKeys = DeadKeysClass() + +if __name__ == "__main__": + for k in DeadKeys.dict.keys(): + print k, DeadKeys.dict[k]+ \ No newline at end of file diff --git a/KeyboardLayoutEditor/src/Disconnect. b/KeyboardLayoutEditor/src/Disconnect. @@ -0,0 +1 @@ +/home/user/EclipseWorkspace/KeyboardLayoutEditor/src diff --git a/KeyboardLayoutEditor/src/DumbKey.py b/KeyboardLayoutEditor/src/DumbKey.py @@ -0,0 +1,297 @@ +#!/usr/bin/env python +# -*- encoding: UTF-8 -*- +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/> + +import gtk +import gobject +import cairo +import copy + +import Common +import KeyValue +from KeyDict import KeyDict, included_files, activated_variants + +class DumbKey(gtk.DrawingArea): + def __init__(self, size = 1, keycode = None, vertical = False, + keytype = Common.keytypes.SIMPLE, + level1 = '', level2 = '', + level3 = '', level4 = ''): + gtk.DrawingArea.__init__(self) + self.connect("expose_event", self.expose) + + self.__key_width = 50 + self.keyvalues = {} + self.dvalues = {} + self.dvalues_inherited = {} + + self.setvalues(size, keycode, vertical, keytype, + level1, level2, level3, level4) + + self.modifier = 1 + self.highlight_x = -1 + self.highlight_y = -1 + self.highlight = False + self.pending = { "ispending": False, + "keysegment": Common.keysegments.NONE, + "value": '', + "coordinates": (-1, -1) } + self.popup_highlight = 0 + + self.infowin = gtk.Window() + self.infowin.set_decorated(False) + + def setvalues(self, size = 1, keycode = None, vertical = False, + keytype = Common.keytypes.SIMPLE, + level1 = '', level2 = '', + level3 = '', level4 = ''): + self.keycode = keycode + self.size = size + self.vertical = vertical + self.keytype = keytype + if self.keycode in KeyDict.IgnoreKeys: + self.verbatim = True + else: + self.verbatim = False + self.keyvalues = { + Common.keysegments.ONE: KeyValue.KeyValue(level1.decode('utf-8'), self.verbatim), + Common.keysegments.TWO: KeyValue.KeyValue(level2.decode('utf-8'), self.verbatim), + Common.keysegments.THREE: KeyValue.KeyValue(level3.decode('utf-8'), self.verbatim), + Common.keysegments.FOUR: KeyValue.KeyValue(level4.decode('utf-8'), self.verbatim) + } + # Fills up the dvalues list with the values to display + self.extract_display_keyvalues() + + def expose(self, widget, event): + self.context = widget.window.cairo_create() + + # set a clip region for the expose event + self.context.rectangle(event.area.x, event.area.y, + event.area.width, event.area.height) + self.context.clip() + + self.a = self.parent.get_parent() + self.b = self.a.parent.get_parent() + self.set_size_request(int(self.__key_width*self.size), -1) + self.draw(self.context) + + return False + + def draw(self, context): + """ Draws the actual key in the widget using Cairo""" + rect = self.get_allocation() + + """ Draw the rectangle, filling in with color """ + self.context.set_source_rgb(0.0, 0.0, 0.0) + self.roundedrec(context, 0, 0, rect.width, rect.height, 15, 3) + + if self.keytype == Common.keytypes.SIMPLE: + context.set_source_rgb(1.0 * self.modifier, + 1.0 * self.modifier, + 0.9 * self.modifier) + elif self.keytype == Common.keytypes.SPECIAL: + context.set_source_rgb(.7 * self.modifier, + .7 * self.modifier, + .5 * self.modifier) + self.context.fill_preserve() + self.context.stroke() + + """ Highlight the segment """ + if self.highlight or self.popup_highlight: + self.context.set_source_rgb(1.0, 1.0, 0.6) + self.roundedrec_segment(context, self.pending["keysegment"], + 0, 0, rect.width, rect.height, 15, 3) + self.context.fill_preserve() + self.context.stroke() + + """ Draw the cross """ + context.set_source_rgb(.1,.1,.1) + context.set_line_width(0.3) + if self.dvalues[Common.keysegments.THREE].getPValue() != '' \ + or self.dvalues[Common.keysegments.FOUR].getPValue() != '': + self.context.move_to(rect.width / 2, 0) + self.context.line_to(rect.width / 2, rect.height) + if self.dvalues[Common.keysegments.TWO].getPValue() != '': + self.context.move_to(0, rect.height / 2) + self.context.line_to(rect.width, rect.height / 2) + self.context.stroke() + + """ Draw the four characters on the key """ + self.context.set_source_rgb(0,1,0) + if self.dvalues[Common.keysegments.ONE].getPValue() == '': + pass + if self.dvalues[Common.keysegments.TWO].getPValue() == '' and \ + self.dvalues[Common.keysegments.THREE].getPValue() == '' and \ + self.dvalues[Common.keysegments.FOUR].getPValue() == '' \ + or self.dvalues[Common.keysegments.THREE].getPValue() == '' and \ + self.dvalues[Common.keysegments.FOUR].getPValue() == '': + self.draw_character(context, self.dvalues[Common.keysegments.ONE].getPValue(), + Common.alignments.LEFT, + 0, rect.height / 2, rect.width, rect.height / 2) + else: + self.draw_character(context, self.dvalues[Common.keysegments.ONE].getPValue(), + Common.alignments.CENTRE, + 0, rect.height / 2, rect.width / 2, rect.height / 2) + + if self.dvalues[Common.keysegments.THREE].getPValue() == '' and \ + self.dvalues[Common.keysegments.FOUR].getPValue() == '': + self.draw_character(context, self.dvalues[Common.keysegments.TWO].getPValue(), + Common.alignments.LEFT, + 0, 0, rect.width, rect.height / 2) + else: + self.draw_character(context, self.dvalues[Common.keysegments.TWO].getPValue(), + Common.alignments.CENTRE, + 0, 0, rect.width / 2, rect.height / 2) + self.draw_character(context, self.dvalues[Common.keysegments.THREE].getPValue(), + Common.alignments.CENTRE, + rect.width / 2, rect.height / 2, + rect.width / 2, rect.height / 2 ) + self.draw_character(context, self.dvalues[Common.keysegments.FOUR].getPValue(), + Common.alignments.CENTRE, + rect.width / 2, 0, rect.width / 2, rect.height / 2) + + def draw_segment(self, segment): + pass + + def draw_line(self, context, x1, y1, x2, y2): + self.context.move_to(x1, y1) + self.context.line_to(x2, y2) + self.context.stroke() + + def draw_linewh(self, context, x, y, w, h): + self.context.move_to(x, y) + self.context.line_to(x+w, y+h) + self.context.stroke() + + def draw_character(self, context, char, align, cx, cy, cwidth, cheight): + if char == '': + return + self.context.select_font_face(Common.fontname, Common.fontstyle, + Common.fontweight) + self.context.set_font_size(Common.fontsize * 1.0) + fascent, fdescent, fheight, fxadvance, fyadvance = self.context.font_extents() + xbearing, ybearing, width, height, xadvance, yadvance = \ + self.context.text_extents(char) + + if align == Common.alignments.CENTRE: + self.context.move_to(cx + cwidth/2 - width/2 - xbearing, + cy + cheight/2 - height/2 - ybearing) + elif align == Common.alignments.LEFT: + self.context.move_to(cx + cwidth/16 - xbearing, + cy + cheight - cheight/16 + ybearing) + elif align == Common.alignments.RIGHT: + self.context.move_to(cx + cwidth/2 - width/2 - xbearing, + cy + cheight/2 - height/2 - ybearing) + else: + print "Error; unknown alignment" + sys.exit(-1) + + self.context.set_source_rgb(.30, .30, .30) + self.context.show_text(char) + + def redraw(self): + (x,y,width,height) = self.get_allocation() + self.queue_draw_area(x, y, width, height) + + def roundedrec(self, context, x, y, w, h, r = 10, line_width=1): + "Draw a rounded rectangle (source: anonymous/pygtk website)" + # A****BQ + # H C + # * * + # G D + # F****E + + context.set_line_width(line_width) + context.move_to(x+r,y) # Move to A + context.line_to(x+w-r,y) # Straight line to B + context.curve_to(x+w,y,x+w,y,x+w,y+r) # Curve to C, Control points are both at Q + context.line_to(x+w,y+h-r) # Move to D + context.curve_to(x+w,y+h,x+w,y+h,x+w-r,y+h) # Curve to E + context.line_to(x+r,y+h) # Line to F + context.curve_to(x,y+h,x,y+h,x,y+h-r) # Curve to G + context.line_to(x,y+r) # Line to H + context.curve_to(x,y,x,y,x+r,y) # Curve to A + + def roundedrec_segment(self,context, which_segment, x, y, w, h, r = 10, + line_width=1): + "Draw a rounded rectangle (source: anonymous/pygtk website)" + # A****BQ + # H C + # * * + # G D + # F****E + + context.set_line_width(line_width) + if which_segment == Common.keysegments.ALL: + self.roundedrec(context, x, y, w, h, r, line_width) + elif which_segment == Common.keysegments.ONE: + context.move_to(x, y + h / 2) # Move to GH-middle + context.line_to(x, y + h - r) # Line to G + context.curve_to(x, y + h, x, y + h, x + r, y+h)# Curve to F + context.line_to(x + w / 2, y + h) # Line to FE-middle + context.line_to(x + w / 2, y + h / 2) # Line to middle + context.line_to(x, y + h / 2) # Line to GH-middle + elif which_segment == Common.keysegments.TWO: + context.move_to(x, y + h / 2) # Move to GH-middle + context.line_to(x, y + r) # Line to H + context.curve_to(x, y, x, y, x + r, y) # Curve to A + context.line_to(x + w / 2, y) # Line to AB-middle + context.line_to(x + w / 2, y + h / 2) # Line to middle + context.line_to(x, y + h / 2) # Line to GH-middle + elif which_segment == Common.keysegments.THREE: + context.move_to(x + w / 2, y + h) # Move to FE-middle + context.line_to(x + w - r, y + h) # Line to E + context.curve_to(x + w, y + h, x + w, y + h, + x + w, y + h - r) # Curve to D + context.line_to(x + w, y + h / 2) # Line to CD-middle + context.line_to(x + w / 2, y + h / 2) # Line to middle + context.line_to(x + w / 2, y + h) # Line to FE-middle + elif which_segment == Common.keysegments.FOUR: + context.move_to(x + w, y + h / 2) # Move to CD-middle + context.line_to(x + w, y + r) # Line to C + context.curve_to(x + w, y, x + w, y, + x + w - r, y) # Curve to B + context.line_to(x + w / 2, y) # Line to AB-middle + context.line_to(x + w / 2, y + h / 2) # Line to middle + context.line_to(x + w, y + h / 2) # Line to CD-middle + + def do_highlight(self, do_highlight = Common.keysegments.NONE, x = -1, y = -1): + self.highlight_x = x + self.highlight_y = y + + #print "do_highlight():", x, y + if do_highlight: + self.modifier = .8 + else: + self.modifier = 1 + + self.queue_draw() + + def extract_display_keyvalues(self): + """ Updates the display values, based on current include files, layout """ + for counter in Common.keysegmentslist: + self.dvalues[counter] = copy.copy(self.keyvalues[counter]) + if self.keycode in KeyDict.IgnoreKeys: + continue + if self.keyvalues[counter].getType() == Common.keyvaluetype.NOSYMBOL: + for layout in activated_variants.keys(): + for variant in activated_variants[layout].keys(): + if activated_variants[layout][variant].has_key(self.keycode): + if activated_variants[layout][variant][self.keycode].has_key(counter): + self.dvalues_inherited[counter] = True + self.dvalues[counter] = copy.copy(activated_variants[layout][variant][self.keycode][counter]) + if self.dvalues[counter].getType() == Common.keyvaluetype.NOSYMBOL: + self.dvalues_inherited[counter] = False + self.dvalues[counter] = copy.copy(self.keyvalues[counter]) + + \ No newline at end of file diff --git a/KeyboardLayoutEditor/src/Enum.py b/KeyboardLayoutEditor/src/Enum.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python +# -*- encoding: UTF-8 -*- +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/> + +class Enum: + + """Create an enumerated type, then add var/value pairs to it. + The constructor and the method .ints(names) take a list of variable names, + and assign them consecutive integers as values. The method .strs(names) + assigns each variable name to itself (that is variable 'v' has value 'v'). + The method .vals(a=99, b=200) allows you to assign any value to variables. + A 'list of variable names' can also be a string, which will be .split(). + The method .end() returns one more than the maximum int value. + Example: opcodes = Enum("add sub load store").vals(illegal=255).""" + + def __init__(self, names=[]): self.ints(names) + + def set(self, var, val): + """Set var to the value val in the enum.""" + if var in vars(self).keys(): raise AttributeError("duplicate var in enum") + if val in vars(self).values(): raise ValueError("duplicate value in enum") + vars(self)[var] = val + return self + + def strs(self, names): + """Set each of the names to itself (as a string) in the enum.""" + for var in self._parse(names): self.set(var, var) + return self + + def ints(self, names): + """Set each of the names to the next highest int in the enum.""" + for var in self._parse(names): self.set(var, self.end()) + return self + + def vals(self, **entries): + """Set each of var=val pairs in the enum.""" + for (var, val) in entries.items(): self.set(var, val) + return self + + def end(self): + """One more than the largest int value in the enum, or 0 if none.""" + try: return max([x for x in vars(self).values() if type(x)==type(0)]) + 1 + except ValueError: return 0 + + def _parse(self, names): + ### If names is a string, parse it as a list of names. + if type(names) == type(""): return names.split() + else: return names diff --git a/KeyboardLayoutEditor/src/GenericLayout.py b/KeyboardLayoutEditor/src/GenericLayout.py @@ -0,0 +1,188 @@ +#!/usr/bin/env python +# -*- encoding: UTF-8 -*- +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/> + +import Common +from lxml import etree +from KeyDict import KeyDict, included_files, activated_variants + +# <layout layoutname="CHANGEME"> +# <symbols> +# <mapoption/> +# <mapname/> +# <mapmaterial> +# <tokenname name="CHANGEME"/> +# <tokeninclude/> +# <tokenkey override="CHANGEME"> +# <keycodename/> +# <keysymgroup/> +# <symbolsgroup> +# <symbol/> +# <symbol/> +# <symbol/> +# <symbol/> +# </symbolsgroup> +# </tokenkey> +# </mapmaterial> +# </symbols> +#</layout> + + +class GenericLayout: + def __init__(self): + self.generic_layout = etree.Element("layout", layoutname = "CHANGEME") + + self.symbols = etree.SubElement(self.generic_layout, "symbols") + + self.mapoption = etree.SubElement(self.symbols, "mapoption") + self.mapname = etree.SubElement(self.symbols, "mapname") + self.mapmaterial = etree.SubElement(self.symbols, "mapmaterial") + + self.tokenname = etree.SubElement(self.mapmaterial, "tokenname") + self.tokenname.attrib["name"] = "CHANGEME" + self.tokinclude = etree.SubElement(self.mapmaterial, "tokeninclude") + + """for keycodename in KeyDict.Keys.keys(): + self.tokenkey = etree.SubElement(self.mapmaterial, "tokenkey") + self.tokenkey.attrib["override"] = "False" + + self.keycodename = etree.SubElement(self.tokenkey, "keycodename") + self.keycodename.text = keycodename + self.keysymgroup = etree.SubElement(self.tokenkey, "keysymgroup") + + self.symbolsgroup = etree.SubElement(self.tokenkey, "symbolsgroup") + + for counter in range(Common.LEVELS): + etree.SubElement(self.symbolsgroup, "symbol") + """ + + def create_layout(self, layoutcode, layoutvariant, layoutname, layoutkeys): + """ + Creates an lxml construct with the layout. + Makes use of KeyDict.included_files, KeyDict.activated_variants + """ + self.new_layout = etree.Element("layout", layoutname = layoutcode) + + self.symbols = etree.SubElement(self.new_layout, "symbols") + + self.mapoption = etree.SubElement(self.symbols, "mapoption") + self.mapoption.text = "xkb_symbols" + self.mapname = etree.SubElement(self.symbols, "mapname") + self.mapname.text = layoutvariant + self.mapmaterial = etree.SubElement(self.symbols, "mapmaterial") + + self.tokenname = etree.SubElement(self.mapmaterial, "tokenname") + self.tokenname.attrib["name"] = layoutname + for includefile in activated_variants.keys(): + for variant in activated_variants[includefile].keys(): + self.tokinclude = etree.SubElement(self.mapmaterial, "tokeninclude") + self.tokinclude.text = includefile + '(' + variant + ')' + + for keycodename in layoutkeys.keys(): + if keycodename in KeyDict.IgnoreKeys: + #print "keycodename", keycodename, "is in ignorekeys" + continue + votes_empty = 0 + for counter in Common.keysegmentslist: + if layoutkeys[keycodename].key.keyvalues[counter].getType() == Common.keyvaluetype.NOSYMBOL: + votes_empty += 1 + if votes_empty == len(Common.keysegmentslist): + # print "Keycode", keycodename, "is empty, skipping" + continue + else: + print keycodename, "we only had", votes_empty, "votes," + for counter in Common.keysegmentslist: + print layoutkeys[keycodename].key.keyvalues[counter].getValue(), + print + #print layoutkeys[keycodename].key.keyvalues[Common.keysegments.ONE].getValue() + self.tokenkey = etree.SubElement(self.mapmaterial, "tokenkey") + self.tokenkey.attrib["override"] = "False" + + self.keycodename = etree.SubElement(self.tokenkey, "keycodename") + self.keycodename.text = keycodename + self.keysymgroup = etree.SubElement(self.tokenkey, "keysymgroup") + + self.symbolsgroup = etree.SubElement(self.keysymgroup, "symbolsgroup") + + print "Counting elems in key:", + for counter in Common.keysegmentslistreverse: + max_index = counter + if layoutkeys[keycodename].key.keyvalues[counter].getType() == Common.keyvaluetype.NOSYMBOL: + print "O", + continue + else: + break + print + print "Doing look between", Common.keysegments.ONE, "and", max_index + for counter in range(Common.keysegments.ONE, max_index + 1): + sym = etree.SubElement(self.symbolsgroup, "symbol") + sym.text = layoutkeys[keycodename].key.keyvalues[counter].getValue() + if sym.text == "": + sym.text = "NoSymbol" + + print "sym.text", sym.text + return self.new_layout + + def create_tokenkey(self, keycodenametext): + if not self.exists_tokenkey(keycodenametext): + tokenkey = etree.SubElement(self.mapmaterial, "tokenkey") + tokenkey.attrib["override"] = "False" + + keycodename = etree.SubElement(tokenkey, "keycodename") + keycodename.text = keycodenametext + keysymgroup = etree.SubElement(tokenkey, "keysymgroup") + + symbolsgroup = etree.SubElement(tokenkey, "symbolsgroup") + + for counter in Common.keysegmentslist: + etree.SubElement(symbolsgroup, "symbol") + return tokenkey + else: + return None + + def return_tokenkey(self, keycode): + all_tokenkeys = self.generic_layout.findall(".//tokenkey") + if all_tokenkeys == []: + return None + for tk in all_tokenkeys: + keycodenames = tk.findall(".//keycodename") + if keycodenames == []: + SystemError("Internal error, expecting a keycodename") + if len(keycodenames) > 1: + SystemError("Internal error, expecting only one keycodename") + if keycodenames[0].text == keycode: + return tk + + def exists_tokenkey(self, keycode): + all_tokenkeys = self.generic_layout.findall(".//tokenkey") + if all_tokenkeys == []: + return False + for tk in all_tokenkeys: + keycodenames = tk.findall(".//keycodename") + if keycodenames == []: + SystemError("Internal error, expecting a keycodename") + if len(keycodenames) > 1: + SystemError("Internal error, expecting only one keycodename") + if keycodenames[0].text == keycode: + return True + else: + return False + + def tostring(self): + return etree.tostring(self.generic_layout, pretty_print = True) + +if __name__ == "__main__": + gl = GenericLayout() + print gl.tostring() diff --git a/KeyboardLayoutEditor/src/Key.py b/KeyboardLayoutEditor/src/Key.py @@ -0,0 +1,184 @@ +#!/usr/bin/env python +# -*- encoding: UTF-8 -*- +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/> + +import gtk +import gobject + +import Common +import DumbKey +import KeyValue +from KeyDict import KeyDict + +class Key(gtk.EventBox): + TARGET_TYPE_TEXT = 80 + __toKey__ = [ ( "text/plain", 0, TARGET_TYPE_TEXT ) ] + + def __init__(self, size = 1, keycode = None, vertical = False, + keytype = Common.keytypes.SIMPLE, + level1 = '', level2 = '', level3 = '', level4 = ''): + gtk.EventBox.__init__(self) + + self.keycode = keycode + #print "Key: Invoked __init__(), level1:", level1 + + self.key = DumbKey.DumbKey(size, keycode, vertical, keytype, + level1, level2, level3, level4) + self.add(self.key) + self.set_events(gtk.gdk.BUTTON_PRESS_MASK) + self.connect("button_press_event", self.button_press_event_callback) + self.connect("button_release_event", self.button_release_event_callback) + + # Initialise the context menu + self.context_menu = gtk.Menu() + self.context_menu_item = gtk.MenuItem("Remove") + self.context_menu.add(self.context_menu_item) + self.context_menu_item.connect("activate", self.menu_item_activate_callback, + "remove") + self.context_menu.connect("selection-done", self.menu_selection_done_callback) + self.context_menu.show_all() + + # Adding DnD support + if self.keycode not in KeyDict.IgnoreKeys: + self.connect("drag_data_received", self.drag_data_get_callback) + self.drag_dest_set(gtk.DEST_DEFAULT_MOTION | + gtk.DEST_DEFAULT_HIGHLIGHT | + gtk.DEST_DEFAULT_DROP, + self.__toKey__, gtk.gdk.ACTION_COPY) + + self.add_events(self.get_events() | gtk.gdk.EXPOSURE_MASK + | gtk.gdk.BUTTON1_MOTION_MASK | gtk.gdk.BUTTON_PRESS_MASK + | gtk.gdk.POINTER_MOTION_MASK | gtk.gdk.DRAG_MOTION + | gtk.gdk.DROP_FINISHED | gtk.gdk.DRAG_STATUS | gtk.gdk.ENTER_NOTIFY + | gtk.gdk.DRAG_ENTER) + # self.connect("motion-notify-event", self.mouse_move_signal) + self.connect("enter_notify_event", self.enter_notify_callback) + self.connect("leave_notify_event", self.leave_notify_callback) + self.connect("drag_drop", self.drag_drop_callback) + self.connect("drag_motion", self.drag_motion_callback) + self.connect("drag_leave", self.drag_leave_callback) + self.tooltips = gtk.Tooltips() + self.tooltips.set_tip(self, "Keycode: " + self.keycode) + + def drag_data_get_callback(self, widget, context, x, y, selection, targetType, time): + #print "Callback drag_data_get: Received a callback for '%(str)s', segment: %(s)d at %(x)d, %(y)d" % \ + # { "s": self.key.pending["keysegment"], "str": selection.data.decode('utf-8'), "x": x, "y": y } + if selection.data[0] == '\\' and \ + (selection.data[1] == 'u' or selection.data[1] == 'U'): + newval = selection.data.decode('unicode-escape') + else: + newval = selection.data + self.key.pending["ispending"] = True + self.key.pending["value"] = newval + #print "drag_data_get" + #print "self.key.pending[\"keysegment\"]:", self.key.pending["keysegment"] + self.key.keyvalues[self.key.pending["keysegment"]].add(newval) + self.key.extract_display_keyvalues() + self.key.redraw() + self.set_tooltip() + Common.addtostatusbar('Added ' + newval + ' to key ' + self.keycode + \ + ', at level ' + str(self.key.pending["keysegment"])) + + def mouse_move_callback(self, widget, event): + pass + + def enter_notify_callback(self, widget, event): + #print "enter_notify" + self.key.do_highlight(True) + self.set_tooltip() + + def leave_notify_callback(self, widget, event): + #self.key.infowin.hide() + #print "leave_notify" + self.key.do_highlight(False, event.x, event.y) + + def drag_drop_callback(self, widget, drag_context, x, y, timestamp): + # print "drag_drop" + pass + + def drag_motion_callback(self, widget, drag_context, x, y, timestamp): + #print "drag_motion" + self.key.highlight = True + self.key.do_highlight(True, x, y) + self.key.pending["keysegment"] = self.find_highlighted_segment(x, y) + + def drag_leave_callback(self, widget, drag_context, timestamp): + #print "drag_leave" + self.key.highlight = False + self.key.do_highlight(False) + + def button_press_event_callback(self, widget, event): + if self.keycode not in KeyDict.IgnoreKeys: + if (event.button == 3): + self.key.popup_highlight = True + self.context_menu.popup(None, None, None, event.button, event.time) + self.key.pending["keysegment"] = self.find_highlighted_segment(event.x, event.y) + # Tell calling code that we have handled this event. + return True + + # Tell calling code we have not handled this code; pass it on + return False + + def button_release_event_callback(self, widget, event): + self.key.popup_highlight = False + + def menu_selection_done_callback(self, menushell): + """ Dehighlight highlighted segment """ + self.key.popup_highlight = False + self.key.redraw() + + def menu_item_activate_callback(self, menuitem, action): + if action == "remove": + self.key.keyvalues[self.key.pending["keysegment"]].add('') + self.key.extract_display_keyvalues() + self.set_tooltip() + self.key.redraw() + + def myname(self): + return "[%(k1)s, %(k2)s, %(k3)s, %(k4)s]" % \ + { "k1": self.key.keyvalues[Common.keysegments.ONE].getValue(), + "k2": self.key.keyvalues[Common.keysegments.TWO].getValue(), + "k3": self.key.keyvalues[Common.keysegments.THREE].getValue(), + "k4": self.key.keyvalues[Common.keysegments.FOUR].getValue() + } + + def find_highlighted_segment(self, x, y): + dummy, dummy, width, height = self.get_allocation() + #print "find:", width, height, x, y + if x != -1 and y != -1: + if x <= width/2: + if y <= height/2: + return Common.keysegments.TWO + else: + return Common.keysegments.ONE + elif y <= height/2: + return Common.keysegments.FOUR + else: + return Common.keysegments.THREE + else: + return Common.keysegments.NONE + + def set_tooltip(self): + tooltip_string = "Keycode: " + self.keycode + counter_empty = 0 + for counter in Common.keysegmentslist: + if self.key.dvalues[counter].getType() == Common.keyvaluetype.NOSYMBOL: + counter_empty +=1 + if counter_empty < len(Common.keysegmentslist): + for counter in Common.keysegmentslist: + tooltip_string += "\n" + str(counter) + ". " +\ + self.key.dvalues[counter].getValue() + " " +\ + self.key.dvalues[counter].getPValue() + self.tooltips.set_tip(self, tooltip_string) diff --git a/KeyboardLayoutEditor/src/KeyDict.py b/KeyboardLayoutEditor/src/KeyDict.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python +# -*- encoding: UTF-8 -*- +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/> + +import Key +import Common + +class KeyDictClass: + def __init__(self): + self.Keys = {} + + self.IgnoreKeys = [ "ESC", "FK01", "FK02", "FK03", "FK04", "FK05", "FK06", + "FK07", "FK08", "FK09", "FK10", "FK11", "FK12", + "BKSP", "TAB", "CAPS", "RTRN", "LFSH", "RTSH", "LCTL", + "LWIN", "LALT", "SPCE", "RALT", "RWIN", "MENU", "RCTL" ] + + def set(self): + self.Keys = { + "ESC" : Key.Key(1, "ESC", False, Common.keytypes.SPECIAL,'Esc'), + "FK01": Key.Key(1, "FK01", False, Common.keytypes.SIMPLE, 'F1'), + "FK02": Key.Key(1, "FK02", False, Common.keytypes.SIMPLE, 'F2'), + "FK03": Key.Key(1, "FK03", False, Common.keytypes.SIMPLE, 'F3'), + "FK04": Key.Key(1, "FK04", False, Common.keytypes.SIMPLE, 'F4'), + "FK05": Key.Key(1, "FK05", False, Common.keytypes.SIMPLE, 'F5'), + "FK06": Key.Key(1, "FK06", False, Common.keytypes.SIMPLE, 'F6'), + "FK07": Key.Key(1, "FK07", False, Common.keytypes.SIMPLE, 'F7'), + "FK08": Key.Key(1, "FK08", False, Common.keytypes.SIMPLE, 'F8'), + "FK09": Key.Key(1, "FK09", False, Common.keytypes.SIMPLE, 'F9'), + "FK10": Key.Key(1, "FK10", False, Common.keytypes.SIMPLE, 'F10'), + "FK11": Key.Key(1, "FK11", False, Common.keytypes.SIMPLE, 'F11'), + "FK12": Key.Key(1, "FK12", False, Common.keytypes.SIMPLE, 'F12'), + + "TLDE": Key.Key(1, "TLDE", False, Common.keytypes.SIMPLE), + "AE01": Key.Key(1, "AE01", False, Common.keytypes.SIMPLE), + "AE02": Key.Key(1, "AE02", False, Common.keytypes.SIMPLE), + "AE03": Key.Key(1, "AE03", False, Common.keytypes.SIMPLE), + "AE04": Key.Key(1, "AE04", False, Common.keytypes.SIMPLE), + "AE05": Key.Key(1, "AE05", False, Common.keytypes.SIMPLE), + "AE06": Key.Key(1, "AE06", False, Common.keytypes.SIMPLE), + "AE07": Key.Key(1, "AE07", False, Common.keytypes.SIMPLE), + "AE08": Key.Key(1, "AE08", False, Common.keytypes.SIMPLE), + "AE09": Key.Key(1, "AE09", False, Common.keytypes.SIMPLE), + "AE10": Key.Key(1, "AE10", False, Common.keytypes.SIMPLE), + "AE11": Key.Key(1, "AE11", False, Common.keytypes.SIMPLE), + "AE12": Key.Key(1, "AE12", False, Common.keytypes.SIMPLE), + "BKSP": Key.Key(2, "BKSP", False, Common.keytypes.SPECIAL,'Backspace'), + + "TAB" : Key.Key(1.8, "TAB", False, Common.keytypes.SPECIAL, 'Tab', 'ISO_Left'), + "AD01": Key.Key(1, "AD01", False, Common.keytypes.SIMPLE), + "AD02": Key.Key(1, "AD02", False, Common.keytypes.SIMPLE), + "AD03": Key.Key(1, "AD03", False, Common.keytypes.SIMPLE), + "AD04": Key.Key(1, "AD04", False, Common.keytypes.SIMPLE), + "AD05": Key.Key(1, "AD05", False, Common.keytypes.SIMPLE), + "AD06": Key.Key(1, "AD06", False, Common.keytypes.SIMPLE), + "AD07": Key.Key(1, "AD07", False, Common.keytypes.SIMPLE), + "AD08": Key.Key(1, "AD08", False, Common.keytypes.SIMPLE), + "AD09": Key.Key(1, "AD09", False, Common.keytypes.SIMPLE), + "AD10": Key.Key(1, "AD10", False, Common.keytypes.SIMPLE), + "AD11": Key.Key(1, "AD11", False, Common.keytypes.SIMPLE), + "AD12": Key.Key(1, "AD12", False, Common.keytypes.SIMPLE), + "BKSL": Key.Key(1, "BKSL", False, Common.keytypes.SIMPLE), + + "CAPS": Key.Key(2, "CAPS", False, Common.keytypes.SPECIAL, 'Caps Lock'), + "AC01": Key.Key(1, "AC01", False, Common.keytypes.SIMPLE), + "AC02": Key.Key(1, "AC02", False, Common.keytypes.SIMPLE), + "AC03": Key.Key(1, "AC03", False, Common.keytypes.SIMPLE), + "AC04": Key.Key(1, "AC04", False, Common.keytypes.SIMPLE), + "AC05": Key.Key(1, "AC05", False, Common.keytypes.SIMPLE), + "AC06": Key.Key(1, "AC06", False, Common.keytypes.SIMPLE), + "AC07": Key.Key(1, "AC07", False, Common.keytypes.SIMPLE), + "AC08": Key.Key(1, "AC08", False, Common.keytypes.SIMPLE), + "AC09": Key.Key(1, "AC09", False, Common.keytypes.SIMPLE), + "AC10": Key.Key(1, "AC10", False, Common.keytypes.SIMPLE), + "AC11": Key.Key(1, "AC11", False,Common.keytypes.SIMPLE), + "RTRN": Key.Key(2, "RTRN", False, Common.keytypes.SPECIAL, 'Return'), + + "LFSH": Key.Key(1, "LFSH", False, Common.keytypes.SPECIAL,'Shift L', 'ISO Prev'), + "LSGT": Key.Key(1, "LSGT", False, Common.keytypes.SIMPLE), + "AB01": Key.Key(1, "AB01", False, Common.keytypes.SIMPLE), + "AB02": Key.Key(1, "AB02", False, Common.keytypes.SIMPLE), + "AB03": Key.Key(1, "AB03", False, Common.keytypes.SIMPLE), + "AB04": Key.Key(1, "AB04", False, Common.keytypes.SIMPLE), + "AB05": Key.Key(1, "AB05", False, Common.keytypes.SIMPLE), + "AB06": Key.Key(1, "AB06", False, Common.keytypes.SIMPLE), + "AB07": Key.Key(1, "AB07", False, Common.keytypes.SIMPLE), + "AB08": Key.Key(1, "AB08", False, Common.keytypes.SIMPLE), + "AB09": Key.Key(1, "AB09", False, Common.keytypes.SIMPLE), + "AB10": Key.Key(1, "AB10", False, Common.keytypes.SIMPLE), + "RTSH": Key.Key(2.5, "RTSH", False, Common.keytypes.SPECIAL, 'Shift R', 'ISO Next'), + + "LCTL": Key.Key(1.8, "LCTL", False, Common.keytypes.SPECIAL, 'Control L'), + "LWIN": Key.Key(1.5, "LWIN", False, Common.keytypes.SPECIAL, 'Super L'), + "LALT": Key.Key(1.5, "LALT", False, Common.keytypes.SPECIAL, 'Alt L'), + "SPCE": Key.Key(9.0, "SPCE", False, Common.keytypes.SIMPLE, 'Spacebar'), + "RALT": Key.Key(1.3, "RALT", False, Common.keytypes.SPECIAL, 'AltGr'), + "RWIN": Key.Key(1.3, "RWIN", False, Common.keytypes.SPECIAL, 'Super R'), + "MENU": Key.Key(1.3, "MENU", False, Common.keytypes.SPECIAL, 'Compose'), + "RCTL": Key.Key(1.5, "RCTL", False, Common.keytypes.SPECIAL, 'Control R') + } + +# The dict keeps the current variants that are selected. +# For example, { "latin": {"basic": parsed1, "east": parsed2}, +# "kpdl": {"one": parsed3, "two":parsed4} } +activated_variants = {} + +# This dict keeps track of included files +# For example, included_files["latin"] = { "file": "/tmp/latin", +# "variants": variants_list, "xml": xml_layout } +included_files = {} + +KeyDict = KeyDictClass() + +if __name__ == "__main__": + for k in KeyDict.Keys.keys(): + print k, KeyDict.Keys[k] diff --git a/KeyboardLayoutEditor/src/KeyValue.py b/KeyboardLayoutEditor/src/KeyValue.py @@ -0,0 +1,146 @@ +#!/usr/bin/env python +# -*- encoding: UTF-8 -*- +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/> + +import Common +import Keysyms +from DeadKeysDict import DeadKeys +from KeysymsUniByValue import KeysymsUniByValue +from KeysymsUni import KeysymsUni + +class KeyValue: + def __init__(self, value = None, verbatim = False): + # Any of Common.keyvaluetype. + self.__type__ = "" + # String that goes to the XKB file + self.__value__ = "" + # String shown in the editor + self.__presentation_value__ = "" + + if value != None: + self.add(value, verbatim) + + def getType(self): + return self.__type__ + + def getValue(self): + return self.__value__ + + def getPValue(self): + """ Accessor to retrieve the PresenationValue """ + return self.__presentation_value__ + + def tostring(self): + return "type: %(type)s, value: %(value)s, pvalue: %(pvalue)s" % \ + { "type": self.getType(), "value": self.getValue(), + "pvalue": self.getPValue() } + + def copy(self, existing): + self.__type__ = existing.getType() + self.__value__ = existing.getValue() + self.__presentation_value__ = existing.getPValue() + + def reset(self): + self.add('') + + def add(self, value, verbatim = False): + if verbatim: + if value != '': + self.__type__ = Common.keyvaluetype.VERBATIM + self.__value__ = value + self.__presentation_value__ = value + return + try: + intval = ord(value.decode('utf8')) + except TypeError, e: + intval = 0 + if value == '': + """ If value is empty, we put NoSymbol and inherit from above. """ + self.__type__ = Common.keyvaluetype.NOSYMBOL + self.__value__ = '' + self.__presentation_value__ = '' + elif intval > 0: + """ If value is a verbatim character, """ + if KeysymsUniByValue.has_key(intval): + self.__type__ = Common.keyvaluetype.KEYSYM + self.__value__ = KeysymsUniByValue[intval] + self.__presentation_value__ = value + else: + self.__type__ = Common.keyvaluetype.CODEPOINT + self.__value__ = 'U' + "%04X" % intval + self.__presentation_value__ = value + elif value[0] == 'U': + """ if value is of the form Uxxxx, where xxxx a hex number, """ + try: + val = int(value[1:], 16) + except ValueError, e: + val = 0 + if val > 0: + self.__type__ = Common.keyvaluetype.CODEPOINT + self.__value__ = value + self.__presentation_value__ = unichr(val) + elif value[0] == '0': + """ if value is of the form 0x1000..., a hex number, """ + try: + val = int(value, 16) + except ValueError: + val = 0 + if val > 0: + if val < 0x1000000: + SystemError("Encountered constant that was supposed to be over\ + 0x1000 000. This should not have happened because we\ + changed this in the code, all over the place.\ + Sorry, I cannot continue. Error with %(e)s, value %(v)d" + % { "e": value, "v": val} ) + self.__type__ = Common.keyvaluetype.CONSTANT + self.__value__ = value.lower() + self.__presentation_value__ = unichr(val - 0x1000000) # TODO: 0x200E (special) + elif value[:5] == "dead_": + self.__type__ = Common.keyvaluetype.DEADKEY + self.__value__ = value + self.__presentation_value__ = "D" + DeadKeys.dict[value][1] + else: + self.__type__ = Common.keyvaluetype.KEYSYM + self.__value__ = value + if KeysymsUni.has_key(value): + self.__presentation_value__ = unichr(KeysymsUni[value]) + elif value in ["VoidSymbol", "voidsymbol"]: + """ If value is empty, we put VoidSymbol and inherit from above. """ + self.__type__ = Common.keyvaluetype.VOIDSYMBOL + self.__value__ = '' + self.__presentation_value__ = '' + elif value in ["NoSymbol", "noSymbol", "Nosymbol"]: + """ If value is empty, we put NoSymbol and inherit from above. """ + self.__type__ = Common.keyvaluetype.NOSYMBOL + self.__value__ = '' + self.__presentation_value__ = '' + elif value == "NoAction": + """ If value is empty, we put NoAction and inherit from above. """ + self.__type__ = Common.keyvaluetype.NOACTION + self.__value__ = '' + self.__presentation_value__ = '' + else: + self.__presentation_value__ = value + +if __name__ == "__main__": + print KeyValue("U0392").tostring() + print KeyValue("U4FE8").tostring() + print KeyValue("0x1000389").tostring() + print KeyValue("dead_acute").tostring() + print KeyValue("0x1000392").tostring() + print KeyValue("A").tostring() + print KeyValue("'").tostring() + print KeyValue("α").tostring() + + \ No newline at end of file diff --git a/KeyboardLayoutEditor/src/Keyboard.py b/KeyboardLayoutEditor/src/Keyboard.py @@ -0,0 +1,173 @@ +#!/usr/bin/env python +# -*- encoding: UTF-8 -*- +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/> + +import sys +import gtk +import gobject +import cairo +from lxml import etree + +import Common +import Key +import GenericLayout +from ParseXML import ParseXML +from KeyDict import KeyDict, included_files, activated_variants + +class Keyboard(gtk.Frame): + __gtype_name__ = 'Keyboard' + + SPACING = 5 + + def __init__(self, layout): + gtk.Frame.__init__(self) + self.connect("expose_event", self.expose) + + # This is a GenericLayout object, created in KeyboardLayoutEditor. + self.xmllayout = layout + + self.layoutcode = "" + self.layoutvariant = "" + self.layoutname = "" + + KeyDict.set() + + # Fill in the KeyDict structure with xml branches + for key in KeyDict.Keys.keys(): + if self.xmllayout.exists_tokenkey(key): + print "Key", key, "already exists in xmllayout." + if KeyDict.Keys[key].xmlbranch == None: + print "Key", key, "was not set, setting now" + elif KeyDict.Keys[key].xmlbranch != xmllayout.return_tokenkey(key): + print "Key", key, "already set to something..." + else: + KeyDict.Keys[key].xmlbranch = xmllayout.create_tokenkey(key) + elif self.xmllayout.create_tokenkey(key) != None: + pass + #print "Added", key + else: + SystemError("Unable to add " + key) + + #print self.xmllayout.tostring() + + self.set_label("") + self.set_shadow_type(gtk.SHADOW_NONE) + + __row1 = ("ESC" , "FK01", "FK02", "FK03", "FK04", "FK05", "FK06", "FK07", "FK08", "FK09", "FK10", "FK11", "FK12") + __row1_esc = ("ESC",) + __row1_f14 = ("FK01", "FK02", "FK03", "FK04") + __row1_f58 = ("FK05", "FK06", "FK07", "FK08") + __row1_f92 = ("FK09", "FK10", "FK11", "FK12") + + __row2 = ("TLDE", "AE01", "AE02", "AE03", "AE04", "AE05", "AE06", "AE07", "AE08", "AE09", "AE10", "AE11", "AE12", "BKSP") + __row3 = ("TAB" , "AD01", "AD02", "AD03", "AD04", "AD05", "AD06", "AD07", "AD08", "AD09", "AD10", "AD11", "AD12", "BKSL") + __row4 = ("CAPS", "AC01", "AC02", "AC03", "AC04", "AC05", "AC06", "AC07", "AC08", "AC09", "AC10", "AC11", "RTRN") + __row5 = ("LFSH", "LSGT", "AB01", "AB02", "AB03", "AB04", "AB05", "AB06", "AB07", "AB08", "AB09", "AB10", "RTSH") + __row6 = ("LCTL", "LWIN", "LALT", "SPCE", "RALT", "RWIN", "MENU", "RCTL") + + vbox = gtk.VBox(False, Keyboard.SPACING) + + hbox1 = gtk.HBox(False, Keyboard.SPACING) + hbox2 = gtk.HBox(False, Keyboard.SPACING) + hbox3 = gtk.HBox(False, Keyboard.SPACING) + hbox4 = gtk.HBox(False, Keyboard.SPACING) + hbox5 = gtk.HBox(False, Keyboard.SPACING) + hbox6 = gtk.HBox(False, Keyboard.SPACING) + + hboxtop_esc = gtk.HBox(False, Keyboard.SPACING) + hboxtop_f14 = gtk.HBox(False, Keyboard.SPACING) + hboxtop_f58 = gtk.HBox(False, Keyboard.SPACING) + hboxtop_f92 = gtk.HBox(False, Keyboard.SPACING) + aligntop_esc = gtk.Alignment( 0, 0, .1, 1) + aligntop_f14 = gtk.Alignment(.1, 0, .5, 1) + aligntop_f58 = gtk.Alignment(.8, 0, .5, 1) + aligntop_f92 = gtk.Alignment( 1, 0, .4, 1) + aligntop_esc.add(hboxtop_esc) + aligntop_f14.add(hboxtop_f14) + aligntop_f58.add(hboxtop_f58) + aligntop_f92.add(hboxtop_f92) + hbox1.pack_start(aligntop_esc, expand=True, fill=True) + hbox1.pack_start(aligntop_f14, expand=True, fill=True) + hbox1.pack_start(aligntop_f58, expand=True, fill=True) + hbox1.pack_start(aligntop_f92, expand=True, fill=True) + + vbox.pack_start(hbox1, expand=True, fill=True) + vbox.pack_start(hbox2, expand=True, fill=True) + vbox.pack_start(hbox3, expand=True, fill=True) + vbox.pack_start(hbox4, expand=True, fill=True) + vbox.pack_start(hbox5, expand=True, fill=True) + vbox.pack_start(hbox6, expand=True, fill=True) + + for item in __row1_esc: + hboxtop_esc.pack_start(KeyDict.Keys[item], expand=True, fill=True) + for item in __row1_f14: + hboxtop_f14.pack_start(KeyDict.Keys[item], expand=True, fill=True) + for item in __row1_f58: + hboxtop_f58.pack_start(KeyDict.Keys[item], expand=True, fill=True) + for item in __row1_f92: + hboxtop_f92.pack_start(KeyDict.Keys[item], expand=True, fill=True) + + for item in __row2: + hbox2.pack_start(KeyDict.Keys[item], expand=True, fill=True) + for item in __row3: + hbox3.pack_start(KeyDict.Keys[item], expand=True, fill=True) + for item in __row4: + hbox4.pack_start(KeyDict.Keys[item], expand=True, fill=True) + for item in __row5: + hbox5.pack_start(KeyDict.Keys[item], expand=True, fill=True) + for item in __row6: + hbox6.pack_start(KeyDict.Keys[item], expand=True, fill=True) + + self.add(vbox) + + def draw(self, context): + pass + + def expose(self, widget, event): + self.context = widget.window.cairo_create() + + # set a clip region for the expose event + self.context.rectangle(event.area.x, event.area.y, + event.area.width, event.area.height) + self.context.clip() + self.draw(self.context) + + return False + + def receiveCallback(widget, context, x, y, selection, targetType, time): + print "Keyboard: Received a callback for", selection, "at", x, y, "at", time + + def redraw(self): + for keycode in KeyDict.Keys.keys(): + KeyDict.Keys[keycode].key.extract_display_keyvalues() + KeyDict.Keys[keycode].key.redraw() + + def save(self, layout_file): + try: + fout = open(layout_file, "w") + except IOError, e: + return False + + self.gl_layout = GenericLayout.GenericLayout() + newxml = self.gl_layout.create_layout(self.layoutcode, + self.layoutvariant, + self.layoutname, + KeyDict.Keys) + fout.write(Common.layout_preamble) + ParseXML(newxml, fout) + fout.close() + + return True + diff --git a/KeyboardLayoutEditor/src/KeyboardLayoutEditor.py b/KeyboardLayoutEditor/src/KeyboardLayoutEditor.py @@ -0,0 +1,937 @@ +#!/usr/bin/env python +# -*- encoding: UTF-8 -*- +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/> + +__author__ = "Simos Xenitellis <simos.lists@googlemail.com>" +__version__ = "1.0" +__date__ = "Date: 2008/08/18" +__copyright__ = "Copyright (c) 2008 Simos Xenitellis" +__license__ = "GPLv3" + +# Hidden: *Lexer.py, *Parser.py, *Walker.py, evdev, aliases, *.tokens, *.g, KeysymsUni.py, print_tree.py, parse_*.py + +try: + import os + import copy + import string + import gtk + import gobject + import pango +except ImportError, e: + raise SystemExit("Import error, Keyboard Layout Editor: " + str(e)) + +if gtk.pygtk_version < (2, 12): + print "PyGtk 2.12 or later required for this application" + print "You have pyGTK", gtk.pygtk_version + raise SystemExit + +try: + import cairo +except ImportError, e: + raise SystemExit("The Python bindings for Cairo are required \ + for this application: " + str(e)) + +try: + from lxml import etree +except ImportError, e: + raise SystemExit("The Python bindings for libxml2 were not found: " + str(e)) + +try: + import Enum + import Key + import Keyboard + import ParseXKB + import GenericLayout + import Common + import SelectVariant + from KeyDict import KeyDict, included_files, activated_variants + from ParseXML import ExtractVariantsKeycodes + from DeadKeysDict import DeadKeys +except ImportError, e: + raise SystemExit("Import error, Keyboard Layout Editor: " + str(e)) + +class Controller_KeyboardLayoutEditor: + """ The keyboard layout editor controller """ + + def __init__(self): + # This is the parser for XKB files, creates an lxml.etree object. + self.parse_xkb = ParseXKB.ParseXKB() + + # Here we create an lxml.etree object that holds the current layout. + self.xmllayout = GenericLayout.GenericLayout() + + # Include files: the selected model and paths, as dict ("model", "paths") + self.include_layout_selected = {} + + # This is the window object. + self.window = gtk.Window() + + # This variable holds the state of the layout; where modifications took place. + #self.layout_not_empty = False + + # Capture keyboard events (key presses), and highlight the relevant keys. + self.root_window = gtk.gdk.get_default_root_window() + self.root_window.set_events(gtk.gdk.KEY_PRESS_MASK) + gtk.gdk.event_handler_set(self.keypress_filter_callback, None) + + # Set initial size + (width, height) = self.window.get_size() + self.window.resize(800, 550) + + self.window.connect("check_resize", self.check_resize) + + self.icon_pixbuf = gtk.gdk.pixbuf_new_from_file('kle-icon4.svg') + self.window.set_icon(self.icon_pixbuf) + + self.TARGET_TYPE_TEXT = 80 + + self.select_variant = SelectVariant.SelectVariant(self.window) + + # Set window title + self.window.set_title("Keyboard Layout Editor") + + # Fill in the dead key section + deadkey_frame = gtk.Frame("Dead keys") + deadkey_vbox = gtk.VBox() + deadkey_info_label = gtk.Label("Drag the dead key (coloured text)" + " and drop to the keyboard below. Click on button for more options.") + deadkey_info_label.set_line_wrap(True) + deadkey_combobox = gtk.ComboBox() + deadkey_liststore = gtk.ListStore(str) + deadkey_cell = gtk.CellRendererText() + deadkey_combobox.pack_start(deadkey_cell) + deadkey_combobox.add_attribute(deadkey_cell, 'text', 0) + self.deadkey_label = gtk.Label("No dead key") + + PLIST = pango.AttrList() + BOLD = pango.AttrWeight(pango.WEIGHT_HEAVY, 0, -1) + GRAYBG = pango.AttrBackground(45000, 40000, 55000, 0, -1) + PLIST.insert(BOLD) + PLIST.insert(GRAYBG) + self.deadkey_label.set_property("attributes", PLIST) + + deadkey_eventboxlabel = gtk.EventBox() + deadkey_eventboxlabel.add(self.deadkey_label) + deadkey_eventboxlabel.connect("drag_data_get", + self.deadkey_drag_data_get_callback) + deadkey_eventboxlabel.drag_source_set(gtk.gdk.BUTTON1_MASK, + [ ( "text/plain", 0, self.TARGET_TYPE_TEXT )], + gtk.gdk.ACTION_COPY) + + deadkey_vbox.pack_start(deadkey_info_label, expand=False, fill=False) + deadkey_vbox.pack_start(deadkey_eventboxlabel, expand=False, fill=False) + deadkey_vbox.pack_start(deadkey_combobox, expand=False, fill=False) + deadkey_frame.add(deadkey_vbox) + + self.deadkey_tooltips = gtk.Tooltips() + self.set_deadkey_tooltip() + + deadkey_combobox.set_wrap_width(4) + deadkey_allnames = [] + for deadkey in DeadKeys.dict.keys(): + deadkey_allnames.append([DeadKeys.dict[deadkey][0]]) + deadkey_allnames.sort() + for deadkeyname in deadkey_allnames: + deadkey_liststore.append(deadkeyname) + deadkey_combobox.set_model(deadkey_liststore) + deadkey_combobox.connect('changed', self.changed_deadkey_combobox_callback) + deadkey_combobox.set_active(4) + + deadkey_unicodechars_vbox = gtk.VBox() + unicodechars_frame = gtk.Frame("Unicode characters") + unicodechars_vbox = gtk.VBox() + unicodechars_label = gtk.Label("Start Character Map, and then drag \ +and drop characters from there to the keyboard below") + unicodechars_label.set_line_wrap(True) + unicodechars_button = gtk.Button("Start Character map") + unicodechars_button.connect("clicked", self.unicodechars_clicked_callback) + unicodechars_vbox.pack_start(unicodechars_label, expand = False, fill = False) + unicodechars_vbox.pack_start(unicodechars_button, expand = False, fill = False) + unicodechars_frame.add(unicodechars_vbox) + deadkey_unicodechars_vbox.pack_start(unicodechars_frame, + expand = False, + fill = False) + deadkey_unicodechars_vbox.pack_start(deadkey_frame, + expand = False, + fill = False) + + includefile_frame = gtk.Frame("Include files") + includefile_hbox = gtk.HBox() + includefile_button_load = gtk.Button("Load file...") + includefile_button_remove = gtk.Button("Remove layout") + includefile_button_load.connect("clicked", self.clicked_loadincludefile_callback) + includefile_button_remove.connect("clicked", self.clicked_removeentry_callback) + includefile_button_remove.set_sensitive(False) + includefile_frame.add(includefile_hbox) + includefile_vbox = gtk.VBox() + includefile_hbox.add(self.doincludes(includefile_button_remove)) + includefile_hbox.add(includefile_vbox) + includefile_vbox.pack_end(includefile_button_load, expand = False) + includefile_vbox.pack_end(includefile_button_remove, expand = False) + + addtolayout_frame = gtk.Frame("Add to layout") + addtolayout_hbox = gtk.HBox() + addtolayout_frame.add(addtolayout_hbox) + addtolayout_hbox.pack_start(includefile_frame, expand=True, fill=True) + addtolayout_hbox.pack_start(deadkey_unicodechars_vbox, expand=False, fill=False) + + layoutdetails_frame = gtk.Frame("Layout details") + layoutdetails_vbox = gtk.VBox() + layoutdetails_hbox_code = gtk.HBox() + layoutdetails_label_code = gtk.Label("Layout code") + self.layoutdetails_entry_code = gtk.Entry() + self.layoutdetails_entry_code.set_max_length(10) + self.layoutdetails_entry_code.connect("key_release_event", self.entry_callback, self.layoutdetails_entry_code) + layoutdetails_code_tooltip = gtk.Tooltips() + layoutdetails_code_tooltip_text = "Enter the layout code.\nTypically \ +this is the relevant ISO 3166\ncountry code, \ +or in special cases,\nthe ISO 639 language code. \ +This is two \nor three letters long, lowercase." + layoutdetails_code_tooltip.set_tip(self.layoutdetails_entry_code, layoutdetails_code_tooltip_text) + layoutdetails_hbox_code.pack_start(layoutdetails_label_code, expand=False, fill=False) + layoutdetails_hbox_code.pack_start(self.layoutdetails_entry_code, expand=True, fill=True) + layoutdetails_vbox.pack_start(layoutdetails_hbox_code, expand=False, fill=False) + layoutdetails_hbox_variant = gtk.HBox() + layoutdetails_label_variant = gtk.Label("Variant") + self.layoutdetails_entry_variant = gtk.Entry() + self.layoutdetails_entry_variant.set_max_length(24) + self.layoutdetails_entry_variant.connect("key_release_event", self.entry_callback, self.layoutdetails_entry_variant) + layoutdetails_variant_tooltip = gtk.Tooltips() + layoutdetails_variant_tooltip_text = "Enter the variant name.\nThis is one \ +or more alphanumeric characters,\nall lowercase." + layoutdetails_variant_tooltip.set_tip(self.layoutdetails_entry_variant, layoutdetails_variant_tooltip_text) + layoutdetails_hbox_variant.pack_start(layoutdetails_label_variant, expand=False, fill=False) + layoutdetails_hbox_variant.pack_start(self.layoutdetails_entry_variant, expand=True, fill=True) + layoutdetails_vbox.pack_start(layoutdetails_hbox_variant, expand=False, fill=False) + layoutdetails_hbox_name = gtk.HBox() + layoutdetails_label_name = gtk.Label("Layout name") + self.layoutdetails_entry_name = gtk.Entry() + self.layoutdetails_entry_name.set_max_length(48) + self.layoutdetails_entry_name.connect("key_release_event", self.entry_callback, self.layoutdetails_entry_name) + layoutdetails_name_tooltip = gtk.Tooltips() + layoutdetails_name_tooltip_text = "Enter the layout name.\nIt is \ +the name to describe this variant.\n\ +This is a free-form description.\n\ +Please do not put punctuation marks." + layoutdetails_name_tooltip.set_tip(self.layoutdetails_entry_name, layoutdetails_name_tooltip_text) + layoutdetails_hbox_name.pack_start(layoutdetails_label_name, expand=False, fill=False) + layoutdetails_hbox_name.pack_start(self.layoutdetails_entry_name, expand=True, fill=True) + layoutdetails_vbox.pack_start(layoutdetails_hbox_name, expand=False, fill=False) + + preferences_frame = gtk.Frame("Preferences") + preferences_vbox = gtk.VBox() + preferences_frame.add(preferences_vbox) + + basedir_vbox = gtk.VBox() + basedir_label = gtk.Label('Select a new basedir') + basedir_vbox.pack_start(basedir_label, expand=False, fill=False) + basedirbutton = gtk.Button(Common.basedir) + basedirbutton.connect('clicked', self.basedir_set_callback) + basedir_vbox.pack_start(basedirbutton, expand=False, fill=False) + + fontbutton_vbox = gtk.VBox() + fontbutton_label = gtk.Label("Select a font") + fontbutton_vbox.pack_start(fontbutton_label, expand=False, fill=False) + fontbutton = gtk.FontButton(fontname=Common.fontname + " " + str(Common.fontsize)) + fontbutton.set_title('Select a font') + fontbutton.connect('font-set', self.font_set_callback) + fontbutton_vbox.pack_start(fontbutton, expand=False, fill=False) + + preferences_vbox.pack_start(fontbutton_vbox, expand=True, fill=True) + preferences_vbox.pack_start(basedir_vbox, expand=True, fill=True) + + #layoutdetails_vbox.pack_start(preferences_frame, expand=False, fill=False) + + layoutdetails_frame.add(layoutdetails_vbox) + + layoutdetails_and_preferences_vbox = gtk.VBox() + layoutdetails_and_preferences_vbox.pack_start(layoutdetails_frame, expand=True, fill=True) + layoutdetails_and_preferences_vbox.pack_start(preferences_frame, expand=True, fill=True) + + layoutdetails_and_addtoframe = gtk.HBox() + layoutdetails_and_addtoframe.pack_start(layoutdetails_and_preferences_vbox, expand=False, fill=False) + layoutdetails_and_addtoframe.pack_start(addtolayout_frame, expand=True, fill=True) + + # Create an accelerator group + accelgroup = gtk.AccelGroup() + # Add the accelerator group to the toplevel window + self.window.add_accel_group(accelgroup) + + # Create an action for starting with a new layout using a stock item + action_new = gtk.Action('New', '_New...', 'New layout', gtk.STOCK_NEW) + action_new.set_property('short-label', '_New') + # Connect a callback to the action + action_new.connect('activate', self.new_layout) + + # Create an action for opening an existing layout using a stock item + action_open = gtk.Action('Open', '_Open', + 'Open an existing layout', gtk.STOCK_OPEN) + action_open.set_property('short-label', '_Open') + # Connect a callback to the action + action_open.connect('activate', self.open_layout) + + # Create an action for saving the layout using a stock item + action_save = gtk.Action('Save', '_Save', 'Save the Layout', + gtk.STOCK_SAVE) + action_save.set_property('short-label', '_Save') + # Connect a callback to the action + action_save.connect('activate', self.save_layout) + + # Create an action for saving the layout with a new name, using a stock item + action_save_as = gtk.Action('SaveAs', 'Save _As', + 'Save the layout with a different filename', + gtk.STOCK_SAVE_AS) + action_save_as.set_property('short-label', '_Save As') + # Connect a callback to the action + action_save_as.connect('activate', self.save_as_layout) + + # Create an action for quitting the program using a stock item + action_quit = gtk.Action('Quit', '_Quit', 'Quit the Program', + gtk.STOCK_QUIT) + action_quit.set_property('short-label', '_Quit') + # Connect a callback to the action + action_quit.connect('activate', self.quit_application) + + # Create an ActionGroup named BasicAction + actiongroup = gtk.ActionGroup('BasicAction') + # Add the action to the actiongroup with an accelerator + # None means use the stock item accelerator + actiongroup.add_action_with_accel(action_new, None) + actiongroup.add_action_with_accel(action_open, None) + actiongroup.add_action_with_accel(action_save, None) + actiongroup.add_action_with_accel(action_save_as, None) + actiongroup.add_action_with_accel(action_quit, None) + + # Have the action use accelgroup + action_new.set_accel_group(accelgroup) + action_open.set_accel_group(accelgroup) + action_save.set_accel_group(accelgroup) + action_save_as.set_accel_group(accelgroup) + action_quit.set_accel_group(accelgroup) + + # Create a MenuBar + menubar = gtk.MenuBar() + + # Create the File Action and MenuItem + file_action = gtk.Action('File', '_File', None, None) + actiongroup.add_action(file_action) + file_menuitem = file_action.create_menu_item() + menubar.append(file_menuitem) + + # Create the File Menu + file_menu = gtk.Menu() + file_menuitem.set_submenu(file_menu) + + # Create a proxy MenuItem + menuitem_new = action_new.create_menu_item() + menuitem_open = action_open.create_menu_item() + menuitem_save = action_save.create_menu_item() + menuitem_save_as = action_save_as.create_menu_item() + menuitem_quit = action_quit.create_menu_item() + file_menu.append(menuitem_new) + file_menu.append(menuitem_open) + file_menu.append(menuitem_save) + file_menu.append(menuitem_save_as) + file_menu.append(menuitem_quit) + + self.mainvbox = gtk.VBox(False) + + # Here we create the Keyboard object. + self.mykeyboard = Keyboard.Keyboard(self.xmllayout) + + # Status bar object + Common.statusbar = gtk.Statusbar() + Common.statusbar.console_context = Common.statusbar.get_context_id('statusbar') + + self.window.add(self.mainvbox) + + self.mykeyboard.add_events(gtk.gdk.KEY_PRESS_MASK | + gtk.gdk.POINTER_MOTION_MASK | + gtk.gdk.BUTTON_PRESS_MASK | + gtk.gdk.SCROLL_MASK) + + self.mainvbox.pack_start(menubar, expand=False, fill=True) + self.mainvbox.pack_start(layoutdetails_and_addtoframe, expand=False, + fill=False) + self.mainvbox.pack_start(self.mykeyboard, expand=True, fill=True) + self.mainvbox.pack_start(Common.statusbar, expand=False, fill=True) + + self.window.connect("destroy", gtk.main_quit) + self.window.show_all() + + def doincludes(self, button_remove): + # create a TreeStore with one string column to use as the model + self.treestore_includes = gtk.TreeStore(str, 'gboolean', 'gboolean') + + self.treestore_includes_iters = {} + + # create the TreeView using treestore + self.treeview_includes = gtk.TreeView(self.treestore_includes) + + # get a TreeViewSelection object + self.treeview_includes_selection = self.treeview_includes.get_selection() + self.treeview_includes_selection.connect('changed', + self.on_selection_changed_callback, button_remove) + + # create the TreeViewColumn to display the data + self.cells0 = gtk.CellRendererText() + self.treeview_includes.insert_column_with_attributes(-1, "Layout", self.cells0, text=0) + + # create the TreeViewColumn to display the data + self.cells1 = gtk.CellRendererToggle() + self.cells1.connect( 'toggled', + self.col1_toggled_callback, + self.treestore_includes ) + self.treeview_includes.insert_column_with_attributes(-1, "Included", + self.cells1, + active=1, + visible=2) + + # make it searchable + self.treeview_includes.set_search_column(0) + + # Allow drag and drop reordering of rows + self.treeview_includes.set_reorderable(False) + self.treeview_includes.set_enable_tree_lines(True) + self.treeview_includes.set_show_expanders(True) + + self.scrolled_window = gtk.ScrolledWindow() + self.scrolled_window.add_with_viewport(self.treeview_includes) + self.scrolled_window.set_size_request(300, 200) + + return self.scrolled_window + + def clicked_loadincludefile_callback(self, param): + chooser = gtk.FileChooserDialog("Load layout file", + action=gtk.FILE_CHOOSER_ACTION_OPEN, + buttons=(gtk.STOCK_CANCEL, + gtk.RESPONSE_CANCEL, + gtk.STOCK_OPEN, + gtk.RESPONSE_OK)) + chooser.set_current_folder(Common.symbolsdir) + chooser.set_default_response(gtk.RESPONSE_OK) + + filter = gtk.FileFilter() + filter.set_name("All files") + filter.add_pattern("*") + chooser.add_filter(filter) + + response = chooser.run() + if response == gtk.RESPONSE_OK: + layout_file = chooser.get_filename() + layout_name = layout_file.rpartition('/')[2] + for layout_id in included_files.keys(): + if included_files[layout_id]["file"] == layout_file: + chooser.destroy() + self.error_dialog("The file " + layout_file + + " has already been loaded. Remove first before reloading.") + return + #print layout_file, layout_name + parse_result = self.parse_xkb.parse_layout(layout_file) + #print parse_result + if parse_result["success"] == True: + # For example, included_files["latin"] = { "file": "/tmp/latin", + # "variants": variants_dict, xml_layout } + self.add_includefile(layout_file) + + chooser.destroy() + Common.addtostatusbar('Successfully added include file ' + layout_file + '.') + else: + chooser.destroy() + self.error_dialog("An error was encountered while trying to parse " \ + + layout_file + ". The file is not loaded.") + elif response == gtk.RESPONSE_CANCEL: + chooser.destroy() + + def add_includefile(self, layout_file, highlight_variant = None): + """ Adds an include file in the Include file tree. """ + try: + layout_file.index('/') + fullfilename = True + except ValueError: + fullfilename = False + + if fullfilename: + include_parse_result = self.parse_xkb.parse_layout(layout_file) + layout_name = layout_file.rpartition('/')[2] + else: + include_parse_result = self.parse_xkb.parse_layout(Common.symbolsdir + layout_file) + layout_name = layout_file + + print "ADD++Include_parse_result (after parse_xkb.parse_layout):", include_parse_result + if include_parse_result["success"] == True: + include_parsed_variants = copy.deepcopy(include_parse_result["variants"]) + include_parsed_layout = include_parse_result["layout"] + + # For example, included_files["latin"] = { "file": "/tmp/latin", + # "variants": variants_dict, xml_layout } + included_files[layout_name] = { 'file': layout_name, + 'variants' : include_parsed_variants, + 'xml' : include_parsed_layout} + print "+++included files for", layout_name, included_files[layout_name] + + self.treestore_includes_iters[layout_name] = \ + self.treestore_includes.append(None, [layout_name, False, False]) + for variant in include_parsed_variants: + print "ADD_INCLUDE, doing variant", variant + if highlight_variant != None and variant == highlight_variant: + print "HIGHLIGHT", variant + self.treestore_includes.append(self.treestore_includes_iters[layout_name], + [variant, True, True]) + else: + self.treestore_includes.append(self.treestore_includes_iters[layout_name], + [variant, False, True]) + + def basedir_set_callback(self, button): + """ Signal, emitted when the user presses the basedir button. """ + chooser = gtk.FileChooserDialog("Select new basedir", + action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, + buttons=(gtk.STOCK_CANCEL, + gtk.RESPONSE_CANCEL, + gtk.STOCK_OPEN, + gtk.RESPONSE_OK)) + chooser.set_current_folder(Common.basedir) + chooser.set_default_response(gtk.RESPONSE_OK) + + filter = gtk.FileFilter() + filter.set_name("All files") + filter.add_pattern("*") + chooser.add_filter(filter) + + response = chooser.run() + if response == gtk.RESPONSE_OK: + symbols_temp = chooser.get_filename() + '/symbols/' + if os.path.isdir(symbols_temp): + Common.basedir = chooser.get_filename() + Common.symbolsdir = Common.basedir + '/symbols/' + button.set_label(Common.basedir) + else: + chooser.destroy() + self.error_dialog('Invalid basedir ' + symbols_temp + '.\n' \ + 'symbols/ subdirectory not found.') + return + elif response == gtk.RESPONSE_CANCEL: + pass + chooser.destroy() + + def new_layout(self, something): + """ Invoked when the user clicks File/New... """ + if self.layout_not_empty(): + if self.ask_to_save_first() == False: + Common.addtostatusbar('Canceled the new layout.') + return + self.reset_layout() + Common.addtostatusbar('Created new layout.') + + def reset_layout(self): + activated_variants.clear() + included_files.clear() + Common.currentlayoutfile = '' + self.mykeyboard.layoutcode = '' + self.mykeyboard.layoutvariant = '' + self.mykeyboard.layoutname = '' + self.layoutdetails_entry_code.set_text(self.mykeyboard.layoutcode) + self.layoutdetails_entry_variant.set_text(self.mykeyboard.layoutvariant) + self.layoutdetails_entry_name.set_text(self.mykeyboard.layoutname) + for keycode in KeyDict.Keys.keys(): + if keycode not in KeyDict.IgnoreKeys: + for segment in Common.keysegmentslist: + KeyDict.Keys[keycode].key.keyvalues[segment].reset() + + self.treestore_includes.clear() + self.mykeyboard.redraw() + + def ask_to_save_first(self): + """ Asks the user if to save. On cancel, we return False. """ + shallsave_message = "Would you like to save the existing layout?" + shallsave_box = gtk.MessageDialog(parent=self.window, + flags=gtk.DIALOG_MODAL, + type=gtk.MESSAGE_QUESTION, + buttons=gtk.BUTTONS_YES_NO, + message_format = shallsave_message) + shallsave_box.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL) + shallsave_box.set_default_response(gtk.RESPONSE_CANCEL) + response = shallsave_box.run() + shallsave_box.destroy() + if response == gtk.RESPONSE_CANCEL: + return False + elif response == gtk.RESPONSE_YES: + if self.save_layout(None): + return True + else: + return False + elif response == gtk.RESPONSE_NO: + return True + return False + + def open_layout(self, something): + """ Invoked when the user clicks File/Open... """ + if self.layout_not_empty(): + if self.ask_to_save_first() == False: + Common.addtostatusbar('Canceled opening a layout.') + return + + chooser = gtk.FileChooserDialog("Open layout file", + action=gtk.FILE_CHOOSER_ACTION_OPEN, + buttons=(gtk.STOCK_CANCEL, + gtk.RESPONSE_CANCEL, + gtk.STOCK_OPEN, + gtk.RESPONSE_OK)) + chooser.set_current_folder(Common.symbolsdir) + chooser.set_default_response(gtk.RESPONSE_OK) + + filter = gtk.FileFilter() + filter.set_name("All files") + filter.add_pattern("*") + chooser.add_filter(filter) + + response = chooser.run() + if response == gtk.RESPONSE_OK: + layout_file = chooser.get_filename() + chooser.destroy() + layout_name = layout_file.rpartition('/')[2] + print "We are about to open a file" + print "+We have layout file", layout_file + parse_result = self.parse_xkb.parse_layout(layout_file) + if parse_result["success"] == True: + # For example, included_files["latin"] = { "file": "/tmp/latin", + # "variants": variants_dict, xml_layout } + + # Clear the layout constructs + print "+Parse was success", parse_result + + self.select_variant.set_list(parse_result['variants']) + self.select_variant.show() + # If the user did not select a variant, we cancel the opening of the file. + if self.select_variant.get_selection() == '': + Common.addtostatusbar('Canceled opening layout file.') + return + self.reset_layout() + variant_verbose_name = '' + self.mykeyboard.layoutvariant = self.select_variant.get_selection() + Common.currentlayoutfile = layout_file + print "Selected:", self.mykeyboard.layoutvariant + result_extract = ExtractVariantsKeycodes(parse_result['layout'], + self.mykeyboard.layoutvariant) + print "+Extracting variants from layout", parse_result['layout'], "variant", self.mykeyboard.layoutvariant + newkeydict = result_extract['keydict'] + newvariants = result_extract['variants'] + print "+Keycodes (newkeydict):", newkeydict + print "+Variants (newvariants):", newvariants + + for keycode in KeyDict.Keys.keys(): + if keycode not in KeyDict.IgnoreKeys: + if newkeydict.has_key(keycode): + for segment in Common.keysegmentslist: + if newkeydict[keycode].has_key(segment): + KeyDict.Keys[keycode].key.keyvalues[segment].copy(newkeydict[keycode][segment]) + + self.mykeyboard.layoutcode = layout_name + self.mykeyboard.layoutname = result_extract['variant_name'] + self.layoutdetails_entry_code.set_text(self.mykeyboard.layoutcode) + self.layoutdetails_entry_variant.set_text(self.mykeyboard.layoutvariant) + self.layoutdetails_entry_name.set_text(self.mykeyboard.layoutname) + + for variant in result_extract['variants']: + print "++Parsed include strings:", Common.parseIncludeString(variant) + parsed_variant = Common.parseIncludeString(variant) + + include_parse_result = self.parse_xkb.parse_layout(Common.symbolsdir + + parsed_variant['filename']) + print "++Include_parse_result (after parse_xkb.parse_layout):", include_parse_result + if include_parse_result["success"] == True: + include_parsed_layout = include_parse_result["layout"] + if parsed_variant['variant'] == '': + """ If not variant is supplied, we select the first one. """ + parsed_variant['variant'] = include_parse_result["variants"][0] + print "+++fixed", include_parse_result["variants"][0] + + # For example, included_files["latin"] = { "file": "/tmp/latin", + # "variants": variants_dict, xml_layout } + included_files[parsed_variant['variant']] = { + "file": parsed_variant['filename'], + "variants" : copy.deepcopy(include_parse_result["variants"]), + "xml" : include_parsed_layout} + print "+++included files for", layout_name, included_files[parsed_variant['variant']] + self.add_includefile(parsed_variant['filename'], + parsed_variant['variant']) + self.select_include_variant(parsed_variant['filename'], + parsed_variant['variant'], + included_files[parsed_variant['filename']]["xml"]) + + if result_extract['variants'] == []: + parsed_variant = [] + + self.mykeyboard.redraw() + Common.addtostatusbar('Successfully opened layout file ' + layout_file + ', ' + + 'selected variant ' + self.mykeyboard.layoutname + '.') + else: + chooser.destroy() + self.error_dialog('An error was encountered while trying to parse ' \ + + layout_file + '. The file is not opened.') + Common.addtostatusbar('Failed at parsing layout file ' + layout_file + '.') + elif response == gtk.RESPONSE_CANCEL: + chooser.destroy() + Common.addtostatusbar('Canceled opening layout file.') + else: + # Should not be reached + chooser.destroy() + + def save_layout(self, something): + """ Invoked when the user clicks File/Save """ + if self.save_perform_checks_notifications() == False: + return False + + if Common.currentlayoutfile == '': + return self.save_as_layout(None) + else: + if os.access(Common.currentlayoutfile, os.W_OK): + result = self.mykeyboard.save(Common.currentlayoutfile) + if result == True: + Common.addtostatusbar('Layout saved to ' + Common.currentlayoutfile + '.') + return True + else: + return False + else: + self.error_dialog('Cannot write to file ' + Common.currentlayoutfile + '. Please select to Save As.') + Common.addtostatusbar('File save cancelled because file is not writable; please select Save As.') + return False + + def save_as_layout(self, arg): + """ Invoked when the user clicks File/Save As...""" + if self.save_perform_checks_notifications() == False: + return False + chooser = gtk.FileChooserDialog("Save layout file as...", + action=gtk.FILE_CHOOSER_ACTION_SAVE, + buttons=(gtk.STOCK_CANCEL, + gtk.RESPONSE_CANCEL, + gtk.STOCK_SAVE_AS, + gtk.RESPONSE_OK)) + chooser.set_current_folder(".") + chooser.set_default_response(gtk.RESPONSE_OK) + chooser.set_filename(self.mykeyboard.layoutcode) + + filter = gtk.FileFilter() + filter.set_name("All files") + filter.add_pattern("*") + chooser.add_filter(filter) + + response = chooser.run() + if response == gtk.RESPONSE_OK: + temp_filename = chooser.get_filename() + chooser.destroy() + if os.access(os.path.dirname(temp_filename), os.W_OK): + Common.currentlayoutfile = temp_filename + self.mykeyboard.save(Common.currentlayoutfile) + Common.addtostatusbar('Layout saved to ' + Common.currentlayoutfile + '.') + return True + else: + print "temp_filename:", temp_filename + self.error_dialog('File save cancelled; cannot save to ' + temp_filename + '.') + Common.addtostatusbar('File save cancelled; cannot save to ' + temp_filename + '.') + return False + else: + chooser.destroy() + return False + + def save_perform_checks_notifications(self): + if self.layout_not_empty() == False: + self.error_dialog("The layout is empty. Not saving.") + return False + if self.mykeyboard.layoutcode == '': + self.error_dialog("Cannot save layout; please add a layout code.") + return False + if self.mykeyboard.layoutvariant == '': + self.error_dialog("Cannot save layout; please add a layout variant.") + return False + if self.mykeyboard.layoutname == '': + self.error_dialog("Cannot save layout; please add a layout name.") + return False + return True + + def clicked_removeentry_callback(self, button): + model = self.include_layout_selected["model"] + path = str(self.include_layout_selected["paths"][0][0]) + iter_layout = model.get_iter_from_string(path.partition(':')[0]) + selected_layout = model.get_value(iter_layout, 0) + + if activated_variants.has_key(selected_layout): + del activated_variants[selected_layout] + print "clicked_removeentry_callback:", included_files + del included_files[selected_layout] + del self.include_layout_selected["model"][self.include_layout_selected["paths"][0]] + self.mykeyboard.redraw() + Common.addtostatusbar('Removed layout ' + selected_layout) + button.set_sensitive(False) + + def col1_toggled_callback( self, cell, path, model ): + """ Sets the toggled state on the toggle button to true or false. """ + model[path][1] = not model[path][1] + + iter_variant = model.get_iter_from_string(path) + iter_layout = model.get_iter_from_string(path.partition(':')[0]) + toggle_layout = model.get_value(iter_layout, 0) + toggle_variant = model.get_value(iter_variant, 0) + + # If the variant is toggled **ON**, + #print "toggling", + if model[path][1]: + #print "on" + if not activated_variants.has_key(toggle_layout): + activated_variants[toggle_layout] = {} + + self.select_include_variant(toggle_layout, toggle_variant, + included_files[toggle_layout]["xml"]) + else: # If the variant is toggled **OFF** + #print "off" + del activated_variants[toggle_layout][toggle_variant] + if len(activated_variants[toggle_layout]) == 0: + del activated_variants[toggle_layout] + for keycode in KeyDict.Keys.keys(): + KeyDict.Keys[keycode].key.extract_display_keyvalues() + KeyDict.Keys[keycode].key.redraw() + + def select_include_variant(self, layout, variant, xml_layout): + if not activated_variants.has_key(layout): + activated_variants[layout] = {} + if not activated_variants[layout].has_key(variant): + activated_variants[layout][variant] = {} + if activated_variants[layout].has_key(variant): + activated_variants[layout][variant].clear() + activated_variants[layout][variant] = {} + store_keydict = {} + self.parse_xkb.parse_layout_controller(store_keydict, + Common.symbolsdir + layout, + variant) + activated_variants[layout][variant] = copy.deepcopy(store_keydict) + for keycode in activated_variants[layout][variant].keys(): + if KeyDict.Keys.has_key(keycode): + KeyDict.Keys[keycode].key.extract_display_keyvalues() + KeyDict.Keys[keycode].key.redraw() + + def changed_deadkey_combobox_callback(self, combobox): + model = combobox.get_model() + index = combobox.get_active() + if index > -1: + self.deadkey_label.set_text(model[index][0]) + for dk in DeadKeys.dict.keys(): + if DeadKeys.dict[dk][0] == model[index][0]: + Common.deadkey = dk + break + self.set_deadkey_tooltip() + + def deadkey_drag_data_get_callback(self, widget, context, selection, + targetType, eventTime): + if targetType == self.TARGET_TYPE_TEXT: + label = widget.get_children()[0] + deadkey_value = '' + for deadkey in DeadKeys.dict.keys(): + if DeadKeys.dict[deadkey][0] == label.get_text(): + deadkey_value = deadkey + selection.set(selection.target, 8, deadkey_value) + + def on_selection_changed_callback(self, selection, button): + model, paths = selection.get_selected_rows() + self.include_layout_selected = { "model": model, "paths": paths } + if self.include_layout_selected["paths"]: + if len(paths[0]) == 1: + button.set_sensitive(True) + else: + button.set_sensitive(False) + + def entry_callback(self, widget, event, entry): + if entry == self.layoutdetails_entry_code: + self.mykeyboard.layoutcode = entry.get_text() + elif entry == self.layoutdetails_entry_variant: + self.mykeyboard.layoutvariant = entry.get_text() + elif entry == self.layoutdetails_entry_name: + self.mykeyboard.layoutname = entry.get_text() + else: + SystemError("Internal error at entry boxes") + + def font_set_callback(self, fontbutton): + newfont = fontbutton.get_font_name() + context = self.window.create_pango_context() + for family in context.list_families(): + if newfont.find(family.get_name()) == 0: + face = family.list_faces()[0] + Common.fontname = family.get_name() + Common.fontsize = string.atoi(newfont.rpartition(' ')[-1], 10) + Common.fontstyle = cairo.FONT_SLANT_NORMAL + Common.fontweight = cairo.FONT_WEIGHT_NORMAL + if face.get_face_name() == "Regular": + Common.fontstyle = cairo.FONT_SLANT_NORMAL + if face.get_face_name() == "Bold": + Common.fontweight = cairo.FONT_SLANT_BOLD + if face.get_face_name() == "Italic": + Common.fontstyle = cairo.FONT_SLANT_ITALIC + if face.get_face_name() == "Oblique": + Common.fontstyle = cairo.FONT_SLANT_OBLIQUE + break + for keycode in KeyDict.Keys.keys(): + KeyDict.Keys[keycode].key.redraw() + Common.addtostatusbar('Font set to ' + newfont + '.') + + def set_deadkey_tooltip(self): + tooltip_string = "Dead key: " + DeadKeys.dict[Common.deadkey][0] + "\n" + tooltip_string += "Keysym: " + Common.deadkey + "\n" + tooltip_string += "Representation: " + DeadKeys.dict[Common.deadkey][1] + self.deadkey_tooltips.set_tip(self.deadkey_label, tooltip_string) + + def quit_application(self, arg): + if self.layout_not_empty(): + if self.ask_to_save_first() == True: + gtk.main_quit() + + def layout_not_empty(self): + if activated_variants != {}: + return True + if self.mykeyboard.layoutcode != "" or \ + self.mykeyboard.layoutvariant != "" or \ + self.mykeyboard.layoutname != "": + return True + for keycode in KeyDict.Keys.keys(): + if keycode not in KeyDict.IgnoreKeys: + for segment in Common.keysegmentslist: + if KeyDict.Keys[keycode].key.keyvalues[segment].getType() !=\ + Common.keyvaluetype.NOSYMBOL: + return True + return False + + def unicodechars_clicked_callback(self, button): + os.spawnl(os.P_NOWAIT, Common.gucharmappath) + + def check_resize(self, container): + pass # TODO: Make sure the keyboard does not get too small. + + def error_dialog(self, message): + notification_box = gtk.MessageDialog(parent=self.window, + flags=gtk.DIALOG_MODAL, + type=gtk.MESSAGE_INFO, + buttons=gtk.BUTTONS_OK, + message_format = message) + notification_box.run() + notification_box.destroy() + + def keypress_filter_callback(self, event, data = None): + if event.type == gtk.gdk.KEY_PRESS: + #print event.keyval, event.string + pass + gtk.main_do_event(event) + +if __name__ == "__main__": + myeditor = Controller_KeyboardLayoutEditor() + + gtk.main() diff --git a/KeyboardLayoutEditor/src/Keycodes.g b/KeyboardLayoutEditor/src/Keycodes.g @@ -0,0 +1,110 @@ +// Keycodes Grammar (X.org) +// Written by Simos Xenitellis <simos.lists@googlemail.com>, 2008. +// Version 0.8 + +grammar Keycodes; + +options +{ + language = Python; + output = AST; +} + +tokens +{ + KEYCODEDOC; + KEYCODELIST; + KEYCODELISTTYPE; + KEYCODELISTOPTIONS; + KEYCODELISTOPTS; + KEYCODELISTNAME; + KEYCODEMATERIAL; + INCLUDE; + MINIMUM; + MAXIMUM; + ALIAS; + INDICATOR; + KEYCODE; +} + +keycodedoc + : keycodelist+ EOF + -> ^(KEYCODEDOC keycodelist+) + ; + +keycodelist + : keycodelisttype '{' keycodeMaterial+ '}' ';' + -> ^(KEYCODELIST keycodelisttype ^(KEYCODEMATERIAL keycodeMaterial+)) + ; + +keycodelisttype + : KEYCODELISTOPTS+ DQSTRING + -> ^(KEYCODELISTTYPE ^(KEYCODELISTOPTIONS KEYCODELISTOPTS+) ^(KEYCODELISTNAME DQSTRING)) + ; + +keycodeMaterial + : line_include + | line_minmax ';'! + | line_alias ';'! + | line_keycode ';'! + | line_indicator ';'! + ; + +line_include + : 'include' DQSTRING + -> ^(INCLUDE DQSTRING) + ; + +line_minmax + : 'minimum' '=' NAME -> ^(MINIMUM NAME) + | 'maximum' '=' NAME -> ^(MAXIMUM NAME) + ; + +line_alias + : 'alias' '<' val+=NAME '>' '=' '<' val+=NAME '>' + -> ^(ALIAS $val+) + ; + +line_keycode + : '<' val+=NAME '>' '=' val+=NAME + -> ^(KEYCODE NAME+) + ; + +line_indicator + : 'indicator' NAME '=' DQSTRING + -> ^(INDICATOR NAME DQSTRING) + ; + +KEYCODELISTOPTS + : 'default' + | 'xkb_keycodes' + ; + +NAME + : ( 'a'..'z' | 'A'..'Z' | '_' | '0'..'9' | '+' | '-' )* + ; + +WS + : + ( ' ' | '\r' | '\t' | '\u000C' | '\n') + { $channel=HIDDEN; } + ; + +COMMENT + : + '/*' .* '*/' {$channel=HIDDEN;} + ; + +LINE_COMMENT + : + ('//' | '#') ~('\n' | '\r')* '\r'? '\n' + { $channel=HIDDEN; } + ; + +/** Match various string types. Note that greedy=false implies ''' + * should make us exit loop not continue. + */ +DQSTRING + : '"' ((options {greedy=false;}:~('"'))*) '"' + ; + diff --git a/KeyboardLayoutEditor/src/KeycodesReader.py b/KeyboardLayoutEditor/src/KeycodesReader.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python +# -*- encoding: UTF-8 -*- +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/> + +import sys +import re +import antlr3 + +from KeycodesLexer import KeycodesLexer, KEYCODELISTTYPE, KEYCODEMATERIAL, \ + KEYCODELISTOPTIONS, KEYCODELISTNAME, \ + INCLUDE, MINIMUM, MAXIMUM, KEYCODE, \ + ALIAS, INDICATOR +from KeycodesParser import KeycodesParser +from KeycodesWalker import KeycodesWalker + +# Global variable, we use global so that the compare function does not have to create the dictionary on every invocation. +KEYCODEDB = {} + +# Helper function to iterate through all children of a given type +def getChildrenListByType(tree, type_value): + list = [] + for i in range(tree.getChildCount()): + child = tree.getChild(i) + if child.getType() == type_value: + list.append(child) + return list + + +def parseFile(fileandvariant = "xfree86|xfree86", *morefilesandvariants): + keycodedb = {} + for eachfileandvariant in (fileandvariant,) + morefilesandvariants: + filename, pipe, variant = eachfileandvariant.partition('|') + + try: + file = open(filename, 'r') + except OSError: + print "Could not open file ", filename, " Aborting..." + sys.exit(-1) + file.close + + char_stream = antlr3.ANTLRFileStream(filename) + lexer = KeycodesLexer(char_stream) + tokens = antlr3.CommonTokenStream(lexer) + parser = KeycodesParser(tokens) + + result = parser.keycodedoc() + + nodes = antlr3.tree.CommonTreeNodeStream(result.tree) + nodes.setTokenStream(tokens) + walker = KeycodesWalker(nodes) + # walker.keycodedoc() + + keycodeidinclude = [variant] + + for itemKeycodeDoc in result.tree.getChildren(): + copying = False + listType = getChildrenListByType(itemKeycodeDoc, KEYCODELISTTYPE) + material = getChildrenListByType(itemKeycodeDoc, KEYCODEMATERIAL) + if len(listType) != 1: + print "Requires single node for KEYCODELISTTYPE. Found", len(listType) + sys.exit(-1) + if len(material) != 1: + print "Requires single node for KEYCODEMATERIAL. Found", len(material) + sys.exit(-1) + + for listNameGroup in getChildrenListByType(listType[0], KEYCODELISTNAME): + for listName in listNameGroup.getChildren(): + if listName.getText()[1:-1] == variant or listName.getText()[1:-1] in keycodeidinclude: + copying = True + + if not copying: + break + + for materialIncludeGroup in getChildrenListByType(material[0], INCLUDE): + for includeName in materialIncludeGroup.getChildren(): + includeKeycodelist = re.findall('(\w+)\((\w+)\)', includeName.getText()[1:-1]) + if includeKeycodelist[0][1] not in keycodeidinclude: + keycodeidinclude.append(includeKeycodelist[0][1]) + + for keycode in getChildrenListByType(material[0], KEYCODE): + keycodedb[keycode.getChild(0).getText()] = keycode.getChild(1).getText() + + for alias in getChildrenListByType(material[0], ALIAS): + keycodedb[alias.getChild(0).getText()] = keycodedb[alias.getChild(1).getText()] + + for indicator in getChildrenListByType(material[0], INDICATOR): + pass + + return keycodedb + +def compare_keycode(a, b): + global KEYCODEDB + if not KEYCODEDB.has_key(a): + if not KEYCODEDB.has_key(b): + return 0 + else: + return 1 + else: + return -1 + if KEYCODEDB[a] > KEYCODEDB[b]: + return 1 + elif KEYCODEDB[a] < KEYCODEDB[b]: + return -1 + else: + return 0 + +def initialise(): + global KEYCODEDB + + KEYCODEDB = parseFile("xfree86|xfree86", "aliases|qwerty", "evdev|evdev") + #KEYCODEDB = parseFile("evdev|evdev", "aliases|qwerty") + +if __name__ == "__main__": + KEYCODEDB = parseFile("xfree86|xfree86", "aliases|qwerty") diff --git a/KeyboardLayoutEditor/src/KeycodesWalker.g b/KeyboardLayoutEditor/src/KeycodesWalker.g @@ -0,0 +1,34 @@ +// Keycodes Grammar (X.org) +// Written by Simos Xenitellis <simos.lists@googlemail.com>, 2008. +// Version 0.8 + +tree grammar KeycodesWalker; + +options +{ + language = Python; + tokenVocab = Keycodes; + ASTLabelType = CommonTree; +} + + +keycodedoc + : ^(KEYCODEDOC keycodelist+) + ; + +keycodelist + : ^(KEYCODELIST keycodelisttype ^(KEYCODEMATERIAL keycodeMaterial+)) + ; + +keycodelisttype + : ^(KEYCODELISTTYPE ^(KEYCODELISTOPTIONS KEYCODELISTOPTS+) ^(KEYCODELISTNAME DQSTRING)) + ; + +keycodeMaterial + : ^(INCLUDE DQSTRING) + | ^(MINIMUM NAME) + | ^(MAXIMUM NAME) + | ^(ALIAS NAME+) + | ^(KEYCODE NAME+) + | ^(INDICATOR NAME DQSTRING) + ; diff --git a/KeyboardLayoutEditor/src/Keysyms.py b/KeyboardLayoutEditor/src/Keysyms.py @@ -0,0 +1,2007 @@ +#!/usr/bin/env python +# -*- encoding: UTF-8 -*- +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/> + +KeysymDB = { + "0" : 0x0030, + "1" : 0x0031, + "2" : 0x0032, + "3" : 0x0033, + "3270_AltCursor" : 0xfd10, + "3270_Attn" : 0xfd0e, + "3270_BackTab" : 0xfd05, + "3270_ChangeScreen" : 0xfd19, + "3270_Copy" : 0xfd15, + "3270_CursorBlink" : 0xfd0f, + "3270_CursorSelect" : 0xfd1c, + "3270_DeleteWord" : 0xfd1a, + "3270_Duplicate" : 0xfd01, + "3270_Enter" : 0xfd1e, + "3270_EraseEOF" : 0xfd06, + "3270_EraseInput" : 0xfd07, + "3270_ExSelect" : 0xfd1b, + "3270_FieldMark" : 0xfd02, + "3270_Ident" : 0xfd13, + "3270_Jump" : 0xfd12, + "3270_KeyClick" : 0xfd11, + "3270_Left2" : 0xfd04, + "3270_PA1" : 0xfd0a, + "3270_PA2" : 0xfd0b, + "3270_PA3" : 0xfd0c, + "3270_Play" : 0xfd16, + "3270_PrintScreen" : 0xfd1d, + "3270_Quit" : 0xfd09, + "3270_Record" : 0xfd18, + "3270_Reset" : 0xfd08, + "3270_Right2" : 0xfd03, + "3270_Rule" : 0xfd14, + "3270_Setup" : 0xfd17, + "3270_Test" : 0xfd0d, + "4" : 0x0034, + "5" : 0x0035, + "6" : 0x0036, + "7" : 0x0037, + "8" : 0x0038, + "9" : 0x0039, + "A" : 0x0041, + "AE" : 0x00c6, + "Aacute" : 0x00c1, + "Abelowdot" : 0x1001ea0, + "Abreve" : 0x01c3, + "Abreveacute" : 0x1001eae, + "Abrevebelowdot" : 0x1001eb6, + "Abrevegrave" : 0x1001eb0, + "Abrevehook" : 0x1001eb2, + "Abrevetilde" : 0x1001eb4, + "AccessX_Enable" : 0xfe70, + "AccessX_Feedback_Enable" : 0xfe71, + "Acircumflex" : 0x00c2, + "Acircumflexacute" : 0x1001ea4, + "Acircumflexbelowdot" : 0x1001eac, + "Acircumflexgrave" : 0x1001ea6, + "Acircumflexhook" : 0x1001ea8, + "Acircumflextilde" : 0x1001eaa, + "Adiaeresis" : 0x00c4, + "Agrave" : 0x00c0, + "Ahook" : 0x1001ea2, + "Alt_L" : 0xffe9, + "Alt_R" : 0xffea, + "Amacron" : 0x03c0, + "Aogonek" : 0x01a1, + "Arabic_0" : 0x1000660, + "Arabic_1" : 0x1000661, + "Arabic_2" : 0x1000662, + "Arabic_3" : 0x1000663, + "Arabic_4" : 0x1000664, + "Arabic_5" : 0x1000665, + "Arabic_6" : 0x1000666, + "Arabic_7" : 0x1000667, + "Arabic_8" : 0x1000668, + "Arabic_9" : 0x1000669, + "Arabic_ain" : 0x05d9, + "Arabic_alef" : 0x05c7, + "Arabic_alefmaksura" : 0x05e9, + "Arabic_beh" : 0x05c8, + "Arabic_comma" : 0x05ac, + "Arabic_dad" : 0x05d6, + "Arabic_dal" : 0x05cf, + "Arabic_damma" : 0x05ef, + "Arabic_dammatan" : 0x05ec, + "Arabic_ddal" : 0x1000688, + "Arabic_farsi_yeh" : 0x10006cc, + "Arabic_fatha" : 0x05ee, + "Arabic_fathatan" : 0x05eb, + "Arabic_feh" : 0x05e1, + "Arabic_fullstop" : 0x10006d4, + "Arabic_gaf" : 0x10006af, + "Arabic_ghain" : 0x05da, + "Arabic_ha" : 0x05e7, + "Arabic_hah" : 0x05cd, + "Arabic_hamza" : 0x05c1, + "Arabic_hamza_above" : 0x1000654, + "Arabic_hamza_below" : 0x1000655, + "Arabic_hamzaonalef" : 0x05c3, + "Arabic_hamzaonwaw" : 0x05c4, + "Arabic_hamzaonyeh" : 0x05c6, + "Arabic_hamzaunderalef" : 0x05c5, + "Arabic_heh" : 0x05e7, + "Arabic_heh_doachashmee" : 0x10006be, + "Arabic_heh_goal" : 0x10006c1, + "Arabic_jeem" : 0x05cc, + "Arabic_jeh" : 0x1000698, + "Arabic_kaf" : 0x05e3, + "Arabic_kasra" : 0x05f0, + "Arabic_kasratan" : 0x05ed, + "Arabic_keheh" : 0x10006a9, + "Arabic_khah" : 0x05ce, + "Arabic_lam" : 0x05e4, + "Arabic_madda_above" : 0x1000653, + "Arabic_maddaonalef" : 0x05c2, + "Arabic_meem" : 0x05e5, + "Arabic_noon" : 0x05e6, + "Arabic_noon_ghunna" : 0x10006ba, + "Arabic_peh" : 0x100067e, + "Arabic_percent" : 0x100066a, + "Arabic_qaf" : 0x05e2, + "Arabic_question_mark" : 0x05bf, + "Arabic_ra" : 0x05d1, + "Arabic_rreh" : 0x1000691, + "Arabic_sad" : 0x05d5, + "Arabic_seen" : 0x05d3, + "Arabic_semicolon" : 0x05bb, + "Arabic_shadda" : 0x05f1, + "Arabic_sheen" : 0x05d4, + "Arabic_sukun" : 0x05f2, + "Arabic_superscript_alef" : 0x1000670, + "Arabic_switch" : 0xff7e, + "Arabic_tah" : 0x05d7, + "Arabic_tatweel" : 0x05e0, + "Arabic_tcheh" : 0x1000686, + "Arabic_teh" : 0x05ca, + "Arabic_tehmarbuta" : 0x05c9, + "Arabic_thal" : 0x05d0, + "Arabic_theh" : 0x05cb, + "Arabic_tteh" : 0x1000679, + "Arabic_veh" : 0x10006a4, + "Arabic_waw" : 0x05e8, + "Arabic_yeh" : 0x05ea, + "Arabic_yeh_baree" : 0x10006d2, + "Arabic_zah" : 0x05d8, + "Arabic_zain" : 0x05d2, + "Aring" : 0x00c5, + "Armenian_AT" : 0x1000538, + "Armenian_AYB" : 0x1000531, + "Armenian_BEN" : 0x1000532, + "Armenian_CHA" : 0x1000549, + "Armenian_DA" : 0x1000534, + "Armenian_DZA" : 0x1000541, + "Armenian_E" : 0x1000537, + "Armenian_FE" : 0x1000556, + "Armenian_GHAT" : 0x1000542, + "Armenian_GIM" : 0x1000533, + "Armenian_HI" : 0x1000545, + "Armenian_HO" : 0x1000540, + "Armenian_INI" : 0x100053b, + "Armenian_JE" : 0x100054b, + "Armenian_KE" : 0x1000554, + "Armenian_KEN" : 0x100053f, + "Armenian_KHE" : 0x100053d, + "Armenian_LYUN" : 0x100053c, + "Armenian_MEN" : 0x1000544, + "Armenian_NU" : 0x1000546, + "Armenian_O" : 0x1000555, + "Armenian_PE" : 0x100054a, + "Armenian_PYUR" : 0x1000553, + "Armenian_RA" : 0x100054c, + "Armenian_RE" : 0x1000550, + "Armenian_SE" : 0x100054d, + "Armenian_SHA" : 0x1000547, + "Armenian_TCHE" : 0x1000543, + "Armenian_TO" : 0x1000539, + "Armenian_TSA" : 0x100053e, + "Armenian_TSO" : 0x1000551, + "Armenian_TYUN" : 0x100054f, + "Armenian_VEV" : 0x100054e, + "Armenian_VO" : 0x1000548, + "Armenian_VYUN" : 0x1000552, + "Armenian_YECH" : 0x1000535, + "Armenian_ZA" : 0x1000536, + "Armenian_ZHE" : 0x100053a, + "Armenian_accent" : 0x100055b, + "Armenian_amanak" : 0x100055c, + "Armenian_apostrophe" : 0x100055a, + "Armenian_at" : 0x1000568, + "Armenian_ayb" : 0x1000561, + "Armenian_ben" : 0x1000562, + "Armenian_but" : 0x100055d, + "Armenian_cha" : 0x1000579, + "Armenian_da" : 0x1000564, + "Armenian_dza" : 0x1000571, + "Armenian_e" : 0x1000567, + "Armenian_exclam" : 0x100055c, + "Armenian_fe" : 0x1000586, + "Armenian_full_stop" : 0x1000589, + "Armenian_ghat" : 0x1000572, + "Armenian_gim" : 0x1000563, + "Armenian_hi" : 0x1000575, + "Armenian_ho" : 0x1000570, + "Armenian_hyphen" : 0x100058a, + "Armenian_ini" : 0x100056b, + "Armenian_je" : 0x100057b, + "Armenian_ke" : 0x1000584, + "Armenian_ken" : 0x100056f, + "Armenian_khe" : 0x100056d, + "Armenian_ligature_ew" : 0x1000587, + "Armenian_lyun" : 0x100056c, + "Armenian_men" : 0x1000574, + "Armenian_nu" : 0x1000576, + "Armenian_o" : 0x1000585, + "Armenian_paruyk" : 0x100055e, + "Armenian_pe" : 0x100057a, + "Armenian_pyur" : 0x1000583, + "Armenian_question" : 0x100055e, + "Armenian_ra" : 0x100057c, + "Armenian_re" : 0x1000580, + "Armenian_se" : 0x100057d, + "Armenian_separation_mark" : 0x100055d, + "Armenian_sha" : 0x1000577, + "Armenian_shesht" : 0x100055b, + "Armenian_tche" : 0x1000573, + "Armenian_to" : 0x1000569, + "Armenian_tsa" : 0x100056e, + "Armenian_tso" : 0x1000581, + "Armenian_tyun" : 0x100057f, + "Armenian_verjaket" : 0x1000589, + "Armenian_vev" : 0x100057e, + "Armenian_vo" : 0x1000578, + "Armenian_vyun" : 0x1000582, + "Armenian_yech" : 0x1000565, + "Armenian_yentamna" : 0x100058a, + "Armenian_za" : 0x1000566, + "Armenian_zhe" : 0x100056a, + "Atilde" : 0x00c3, + "AudibleBell_Enable" : 0xfe7a, + "B" : 0x0042, + "Babovedot" : 0x1001e02, + "BackSpace" : 0xff08, + "Begin" : 0xff58, + "BounceKeys_Enable" : 0xfe74, + "Break" : 0xff6b, + "Byelorussian_SHORTU" : 0x06be, + "Byelorussian_shortu" : 0x06ae, + "C" : 0x0043, + "Cabovedot" : 0x02c5, + "Cacute" : 0x01c6, + "Cancel" : 0xff69, + "Caps_Lock" : 0xffe5, + "Ccaron" : 0x01c8, + "Ccedilla" : 0x00c7, + "Ccircumflex" : 0x02c6, + "Clear" : 0xff0b, + "Codeinput" : 0xff37, + "ColonSign" : 0x10020a1, + "Control_L" : 0xffe3, + "Control_R" : 0xffe4, + "CruzeiroSign" : 0x10020a2, + "Cyrillic_A" : 0x06e1, + "Cyrillic_BE" : 0x06e2, + "Cyrillic_CHE" : 0x06fe, + "Cyrillic_CHE_descender" : 0x10004b6, + "Cyrillic_CHE_vertstroke" : 0x10004b8, + "Cyrillic_DE" : 0x06e4, + "Cyrillic_DZHE" : 0x06bf, + "Cyrillic_E" : 0x06fc, + "Cyrillic_EF" : 0x06e6, + "Cyrillic_EL" : 0x06ec, + "Cyrillic_EM" : 0x06ed, + "Cyrillic_EN" : 0x06ee, + "Cyrillic_EN_descender" : 0x10004a2, + "Cyrillic_ER" : 0x06f2, + "Cyrillic_ES" : 0x06f3, + "Cyrillic_GHE" : 0x06e7, + "Cyrillic_GHE_bar" : 0x1000492, + "Cyrillic_HA" : 0x06e8, + "Cyrillic_HARDSIGN" : 0x06ff, + "Cyrillic_HA_descender" : 0x10004b2, + "Cyrillic_I" : 0x06e9, + "Cyrillic_IE" : 0x06e5, + "Cyrillic_IO" : 0x06b3, + "Cyrillic_I_macron" : 0x10004e2, + "Cyrillic_JE" : 0x06b8, + "Cyrillic_KA" : 0x06eb, + "Cyrillic_KA_descender" : 0x100049a, + "Cyrillic_KA_vertstroke" : 0x100049c, + "Cyrillic_LJE" : 0x06b9, + "Cyrillic_NJE" : 0x06ba, + "Cyrillic_O" : 0x06ef, + "Cyrillic_O_bar" : 0x10004e8, + "Cyrillic_PE" : 0x06f0, + "Cyrillic_SCHWA" : 0x10004d8, + "Cyrillic_SHA" : 0x06fb, + "Cyrillic_SHCHA" : 0x06fd, + "Cyrillic_SHHA" : 0x10004ba, + "Cyrillic_SHORTI" : 0x06ea, + "Cyrillic_SOFTSIGN" : 0x06f8, + "Cyrillic_TE" : 0x06f4, + "Cyrillic_TSE" : 0x06e3, + "Cyrillic_U" : 0x06f5, + "Cyrillic_U_macron" : 0x10004ee, + "Cyrillic_U_straight" : 0x10004ae, + "Cyrillic_U_straight_bar" : 0x10004b0, + "Cyrillic_VE" : 0x06f7, + "Cyrillic_YA" : 0x06f1, + "Cyrillic_YERU" : 0x06f9, + "Cyrillic_YU" : 0x06e0, + "Cyrillic_ZE" : 0x06fa, + "Cyrillic_ZHE" : 0x06f6, + "Cyrillic_ZHE_descender" : 0x1000496, + "Cyrillic_a" : 0x06c1, + "Cyrillic_be" : 0x06c2, + "Cyrillic_che" : 0x06de, + "Cyrillic_che_descender" : 0x10004b7, + "Cyrillic_che_vertstroke" : 0x10004b9, + "Cyrillic_de" : 0x06c4, + "Cyrillic_dzhe" : 0x06af, + "Cyrillic_e" : 0x06dc, + "Cyrillic_ef" : 0x06c6, + "Cyrillic_el" : 0x06cc, + "Cyrillic_em" : 0x06cd, + "Cyrillic_en" : 0x06ce, + "Cyrillic_en_descender" : 0x10004a3, + "Cyrillic_er" : 0x06d2, + "Cyrillic_es" : 0x06d3, + "Cyrillic_ghe" : 0x06c7, + "Cyrillic_ghe_bar" : 0x1000493, + "Cyrillic_ha" : 0x06c8, + "Cyrillic_ha_descender" : 0x10004b3, + "Cyrillic_hardsign" : 0x06df, + "Cyrillic_i" : 0x06c9, + "Cyrillic_i_macron" : 0x10004e3, + "Cyrillic_ie" : 0x06c5, + "Cyrillic_io" : 0x06a3, + "Cyrillic_je" : 0x06a8, + "Cyrillic_ka" : 0x06cb, + "Cyrillic_ka_descender" : 0x100049b, + "Cyrillic_ka_vertstroke" : 0x100049d, + "Cyrillic_lje" : 0x06a9, + "Cyrillic_nje" : 0x06aa, + "Cyrillic_o" : 0x06cf, + "Cyrillic_o_bar" : 0x10004e9, + "Cyrillic_pe" : 0x06d0, + "Cyrillic_schwa" : 0x10004d9, + "Cyrillic_sha" : 0x06db, + "Cyrillic_shcha" : 0x06dd, + "Cyrillic_shha" : 0x10004bb, + "Cyrillic_shorti" : 0x06ca, + "Cyrillic_softsign" : 0x06d8, + "Cyrillic_te" : 0x06d4, + "Cyrillic_tse" : 0x06c3, + "Cyrillic_u" : 0x06d5, + "Cyrillic_u_macron" : 0x10004ef, + "Cyrillic_u_straight" : 0x10004af, + "Cyrillic_u_straight_bar" : 0x10004b1, + "Cyrillic_ve" : 0x06d7, + "Cyrillic_ya" : 0x06d1, + "Cyrillic_yeru" : 0x06d9, + "Cyrillic_yu" : 0x06c0, + "Cyrillic_ze" : 0x06da, + "Cyrillic_zhe" : 0x06d6, + "Cyrillic_zhe_descender" : 0x1000497, + "D" : 0x0044, + "Dabovedot" : 0x1001e0a, + "Dcaron" : 0x01cf, + "Delete" : 0xffff, + "DongSign" : 0x10020ab, + "Down" : 0xff54, + "Dstroke" : 0x01d0, + "E" : 0x0045, + "ENG" : 0x03bd, + "ETH" : 0x00d0, + "Eabovedot" : 0x03cc, + "Eacute" : 0x00c9, + "Ebelowdot" : 0x1001eb8, + "Ecaron" : 0x01cc, + "Ecircumflex" : 0x00ca, + "Ecircumflexacute" : 0x1001ebe, + "Ecircumflexbelowdot" : 0x1001ec6, + "Ecircumflexgrave" : 0x1001ec0, + "Ecircumflexhook" : 0x1001ec2, + "Ecircumflextilde" : 0x1001ec4, + "EcuSign" : 0x10020a0, + "Ediaeresis" : 0x00cb, + "Egrave" : 0x00c8, + "Ehook" : 0x1001eba, + "Eisu_Shift" : 0xff2f, + "Eisu_toggle" : 0xff30, + "Emacron" : 0x03aa, + "End" : 0xff57, + "Eogonek" : 0x01ca, + "Escape" : 0xff1b, + "Eth" : 0x00d0, + "Etilde" : 0x1001ebc, + "EuroSign" : 0x20ac, + "Execute" : 0xff62, + "F" : 0x0046, + "F1" : 0xffbe, + "F10" : 0xffc7, + "F11" : 0xffc8, + "F12" : 0xffc9, + "F13" : 0xffca, + "F14" : 0xffcb, + "F15" : 0xffcc, + "F16" : 0xffcd, + "F17" : 0xffce, + "F18" : 0xffcf, + "F19" : 0xffd0, + "F2" : 0xffbf, + "F20" : 0xffd1, + "F21" : 0xffd2, + "F22" : 0xffd3, + "F23" : 0xffd4, + "F24" : 0xffd5, + "F25" : 0xffd6, + "F26" : 0xffd7, + "F27" : 0xffd8, + "F28" : 0xffd9, + "F29" : 0xffda, + "F3" : 0xffc0, + "F30" : 0xffdb, + "F31" : 0xffdc, + "F32" : 0xffdd, + "F33" : 0xffde, + "F34" : 0xffdf, + "F35" : 0xffe0, + "F4" : 0xffc1, + "F5" : 0xffc2, + "F6" : 0xffc3, + "F7" : 0xffc4, + "F8" : 0xffc5, + "F9" : 0xffc6, + "FFrancSign" : 0x10020a3, + "Fabovedot" : 0x1001e1e, + "Farsi_0" : 0x10006f0, + "Farsi_1" : 0x10006f1, + "Farsi_2" : 0x10006f2, + "Farsi_3" : 0x10006f3, + "Farsi_4" : 0x10006f4, + "Farsi_5" : 0x10006f5, + "Farsi_6" : 0x10006f6, + "Farsi_7" : 0x10006f7, + "Farsi_8" : 0x10006f8, + "Farsi_9" : 0x10006f9, + "Farsi_yeh" : 0x10006cc, + "Find" : 0xff68, + "First_Virtual_Screen" : 0xfed0, + "G" : 0x0047, + "Gabovedot" : 0x02d5, + "Gbreve" : 0x02ab, + "Gcaron" : 0x10001e6, + "Gcedilla" : 0x03ab, + "Gcircumflex" : 0x02d8, + "Georgian_an" : 0x10010d0, + "Georgian_ban" : 0x10010d1, + "Georgian_can" : 0x10010ea, + "Georgian_char" : 0x10010ed, + "Georgian_chin" : 0x10010e9, + "Georgian_cil" : 0x10010ec, + "Georgian_don" : 0x10010d3, + "Georgian_en" : 0x10010d4, + "Georgian_fi" : 0x10010f6, + "Georgian_gan" : 0x10010d2, + "Georgian_ghan" : 0x10010e6, + "Georgian_hae" : 0x10010f0, + "Georgian_har" : 0x10010f4, + "Georgian_he" : 0x10010f1, + "Georgian_hie" : 0x10010f2, + "Georgian_hoe" : 0x10010f5, + "Georgian_in" : 0x10010d8, + "Georgian_jhan" : 0x10010ef, + "Georgian_jil" : 0x10010eb, + "Georgian_kan" : 0x10010d9, + "Georgian_khar" : 0x10010e5, + "Georgian_las" : 0x10010da, + "Georgian_man" : 0x10010db, + "Georgian_nar" : 0x10010dc, + "Georgian_on" : 0x10010dd, + "Georgian_par" : 0x10010de, + "Georgian_phar" : 0x10010e4, + "Georgian_qar" : 0x10010e7, + "Georgian_rae" : 0x10010e0, + "Georgian_san" : 0x10010e1, + "Georgian_shin" : 0x10010e8, + "Georgian_tan" : 0x10010d7, + "Georgian_tar" : 0x10010e2, + "Georgian_un" : 0x10010e3, + "Georgian_vin" : 0x10010d5, + "Georgian_we" : 0x10010f3, + "Georgian_xan" : 0x10010ee, + "Georgian_zen" : 0x10010d6, + "Georgian_zhar" : 0x10010df, + "Greek_ALPHA" : 0x07c1, + "Greek_ALPHAaccent" : 0x07a1, + "Greek_BETA" : 0x07c2, + "Greek_CHI" : 0x07d7, + "Greek_DELTA" : 0x07c4, + "Greek_EPSILON" : 0x07c5, + "Greek_EPSILONaccent" : 0x07a2, + "Greek_ETA" : 0x07c7, + "Greek_ETAaccent" : 0x07a3, + "Greek_GAMMA" : 0x07c3, + "Greek_IOTA" : 0x07c9, + "Greek_IOTAaccent" : 0x07a4, + "Greek_IOTAdiaeresis" : 0x07a5, + "Greek_IOTAdieresis" : 0x07a5, + "Greek_KAPPA" : 0x07ca, + "Greek_LAMBDA" : 0x07cb, + "Greek_LAMDA" : 0x07cb, + "Greek_MU" : 0x07cc, + "Greek_NU" : 0x07cd, + "Greek_OMEGA" : 0x07d9, + "Greek_OMEGAaccent" : 0x07ab, + "Greek_OMICRON" : 0x07cf, + "Greek_OMICRONaccent" : 0x07a7, + "Greek_PHI" : 0x07d6, + "Greek_PI" : 0x07d0, + "Greek_PSI" : 0x07d8, + "Greek_RHO" : 0x07d1, + "Greek_SIGMA" : 0x07d2, + "Greek_TAU" : 0x07d4, + "Greek_THETA" : 0x07c8, + "Greek_UPSILON" : 0x07d5, + "Greek_UPSILONaccent" : 0x07a8, + "Greek_UPSILONdieresis" : 0x07a9, + "Greek_XI" : 0x07ce, + "Greek_ZETA" : 0x07c6, + "Greek_accentdieresis" : 0x07ae, + "Greek_alpha" : 0x07e1, + "Greek_alphaaccent" : 0x07b1, + "Greek_beta" : 0x07e2, + "Greek_chi" : 0x07f7, + "Greek_delta" : 0x07e4, + "Greek_epsilon" : 0x07e5, + "Greek_epsilonaccent" : 0x07b2, + "Greek_eta" : 0x07e7, + "Greek_etaaccent" : 0x07b3, + "Greek_finalsmallsigma" : 0x07f3, + "Greek_gamma" : 0x07e3, + "Greek_horizbar" : 0x07af, + "Greek_iota" : 0x07e9, + "Greek_iotaaccent" : 0x07b4, + "Greek_iotaaccentdieresis" : 0x07b6, + "Greek_iotadieresis" : 0x07b5, + "Greek_kappa" : 0x07ea, + "Greek_lambda" : 0x07eb, + "Greek_lamda" : 0x07eb, + "Greek_mu" : 0x07ec, + "Greek_nu" : 0x07ed, + "Greek_omega" : 0x07f9, + "Greek_omegaaccent" : 0x07bb, + "Greek_omicron" : 0x07ef, + "Greek_omicronaccent" : 0x07b7, + "Greek_phi" : 0x07f6, + "Greek_pi" : 0x07f0, + "Greek_psi" : 0x07f8, + "Greek_rho" : 0x07f1, + "Greek_sigma" : 0x07f2, + "Greek_switch" : 0xff7e, + "Greek_tau" : 0x07f4, + "Greek_theta" : 0x07e8, + "Greek_upsilon" : 0x07f5, + "Greek_upsilonaccent" : 0x07b8, + "Greek_upsilonaccentdieresis" : 0x07ba, + "Greek_upsilondieresis" : 0x07b9, + "Greek_xi" : 0x07ee, + "Greek_zeta" : 0x07e6, + "H" : 0x0048, + "Hangul" : 0xff31, + "Hangul_A" : 0x0ebf, + "Hangul_AE" : 0x0ec0, + "Hangul_AraeA" : 0x0ef6, + "Hangul_AraeAE" : 0x0ef7, + "Hangul_Banja" : 0xff39, + "Hangul_Cieuc" : 0x0eba, + "Hangul_Codeinput" : 0xff37, + "Hangul_Dikeud" : 0x0ea7, + "Hangul_E" : 0x0ec4, + "Hangul_EO" : 0x0ec3, + "Hangul_EU" : 0x0ed1, + "Hangul_End" : 0xff33, + "Hangul_Hanja" : 0xff34, + "Hangul_Hieuh" : 0x0ebe, + "Hangul_I" : 0x0ed3, + "Hangul_Ieung" : 0x0eb7, + "Hangul_J_Cieuc" : 0x0eea, + "Hangul_J_Dikeud" : 0x0eda, + "Hangul_J_Hieuh" : 0x0eee, + "Hangul_J_Ieung" : 0x0ee8, + "Hangul_J_Jieuj" : 0x0ee9, + "Hangul_J_Khieuq" : 0x0eeb, + "Hangul_J_Kiyeog" : 0x0ed4, + "Hangul_J_KiyeogSios" : 0x0ed6, + "Hangul_J_KkogjiDalrinIeung" : 0x0ef9, + "Hangul_J_Mieum" : 0x0ee3, + "Hangul_J_Nieun" : 0x0ed7, + "Hangul_J_NieunHieuh" : 0x0ed9, + "Hangul_J_NieunJieuj" : 0x0ed8, + "Hangul_J_PanSios" : 0x0ef8, + "Hangul_J_Phieuf" : 0x0eed, + "Hangul_J_Pieub" : 0x0ee4, + "Hangul_J_PieubSios" : 0x0ee5, + "Hangul_J_Rieul" : 0x0edb, + "Hangul_J_RieulHieuh" : 0x0ee2, + "Hangul_J_RieulKiyeog" : 0x0edc, + "Hangul_J_RieulMieum" : 0x0edd, + "Hangul_J_RieulPhieuf" : 0x0ee1, + "Hangul_J_RieulPieub" : 0x0ede, + "Hangul_J_RieulSios" : 0x0edf, + "Hangul_J_RieulTieut" : 0x0ee0, + "Hangul_J_Sios" : 0x0ee6, + "Hangul_J_SsangKiyeog" : 0x0ed5, + "Hangul_J_SsangSios" : 0x0ee7, + "Hangul_J_Tieut" : 0x0eec, + "Hangul_J_YeorinHieuh" : 0x0efa, + "Hangul_Jamo" : 0xff35, + "Hangul_Jeonja" : 0xff38, + "Hangul_Jieuj" : 0x0eb8, + "Hangul_Khieuq" : 0x0ebb, + "Hangul_Kiyeog" : 0x0ea1, + "Hangul_KiyeogSios" : 0x0ea3, + "Hangul_KkogjiDalrinIeung" : 0x0ef3, + "Hangul_Mieum" : 0x0eb1, + "Hangul_MultipleCandidate" : 0xff3d, + "Hangul_Nieun" : 0x0ea4, + "Hangul_NieunHieuh" : 0x0ea6, + "Hangul_NieunJieuj" : 0x0ea5, + "Hangul_O" : 0x0ec7, + "Hangul_OE" : 0x0eca, + "Hangul_PanSios" : 0x0ef2, + "Hangul_Phieuf" : 0x0ebd, + "Hangul_Pieub" : 0x0eb2, + "Hangul_PieubSios" : 0x0eb4, + "Hangul_PostHanja" : 0xff3b, + "Hangul_PreHanja" : 0xff3a, + "Hangul_PreviousCandidate" : 0xff3e, + "Hangul_Rieul" : 0x0ea9, + "Hangul_RieulHieuh" : 0x0eb0, + "Hangul_RieulKiyeog" : 0x0eaa, + "Hangul_RieulMieum" : 0x0eab, + "Hangul_RieulPhieuf" : 0x0eaf, + "Hangul_RieulPieub" : 0x0eac, + "Hangul_RieulSios" : 0x0ead, + "Hangul_RieulTieut" : 0x0eae, + "Hangul_RieulYeorinHieuh" : 0x0eef, + "Hangul_Romaja" : 0xff36, + "Hangul_SingleCandidate" : 0xff3c, + "Hangul_Sios" : 0x0eb5, + "Hangul_Special" : 0xff3f, + "Hangul_SsangDikeud" : 0x0ea8, + "Hangul_SsangJieuj" : 0x0eb9, + "Hangul_SsangKiyeog" : 0x0ea2, + "Hangul_SsangPieub" : 0x0eb3, + "Hangul_SsangSios" : 0x0eb6, + "Hangul_Start" : 0xff32, + "Hangul_SunkyeongeumMieum" : 0x0ef0, + "Hangul_SunkyeongeumPhieuf" : 0x0ef4, + "Hangul_SunkyeongeumPieub" : 0x0ef1, + "Hangul_Tieut" : 0x0ebc, + "Hangul_U" : 0x0ecc, + "Hangul_WA" : 0x0ec8, + "Hangul_WAE" : 0x0ec9, + "Hangul_WE" : 0x0ece, + "Hangul_WEO" : 0x0ecd, + "Hangul_WI" : 0x0ecf, + "Hangul_YA" : 0x0ec1, + "Hangul_YAE" : 0x0ec2, + "Hangul_YE" : 0x0ec6, + "Hangul_YEO" : 0x0ec5, + "Hangul_YI" : 0x0ed2, + "Hangul_YO" : 0x0ecb, + "Hangul_YU" : 0x0ed0, + "Hangul_YeorinHieuh" : 0x0ef5, + "Hangul_switch" : 0xff7e, + "Hankaku" : 0xff29, + "Hcircumflex" : 0x02a6, + "Hebrew_switch" : 0xff7e, + "Help" : 0xff6a, + "Henkan" : 0xff23, + "Henkan_Mode" : 0xff23, + "Hiragana" : 0xff25, + "Hiragana_Katakana" : 0xff27, + "Home" : 0xff50, + "Hstroke" : 0x02a1, + "Hyper_L" : 0xffed, + "Hyper_R" : 0xffee, + "I" : 0x0049, + "ISO_Center_Object" : 0xfe33, + "ISO_Continuous_Underline" : 0xfe30, + "ISO_Discontinuous_Underline" : 0xfe31, + "ISO_Emphasize" : 0xfe32, + "ISO_Enter" : 0xfe34, + "ISO_Fast_Cursor_Down" : 0xfe2f, + "ISO_Fast_Cursor_Left" : 0xfe2c, + "ISO_Fast_Cursor_Right" : 0xfe2d, + "ISO_Fast_Cursor_Up" : 0xfe2e, + "ISO_First_Group" : 0xfe0c, + "ISO_First_Group_Lock" : 0xfe0d, + "ISO_Group_Latch" : 0xfe06, + "ISO_Group_Lock" : 0xfe07, + "ISO_Group_Shift" : 0xff7e, + "ISO_Last_Group" : 0xfe0e, + "ISO_Last_Group_Lock" : 0xfe0f, + "ISO_Left_Tab" : 0xfe20, + "ISO_Level2_Latch" : 0xfe02, + "ISO_Level3_Latch" : 0xfe04, + "ISO_Level3_Lock" : 0xfe05, + "ISO_Level3_Shift" : 0xfe03, + "ISO_Level5_Latch" : 0xfe12, + "ISO_Level5_Lock" : 0xfe13, + "ISO_Level5_Shift" : 0xfe11, + "ISO_Lock" : 0xfe01, + "ISO_Move_Line_Down" : 0xfe22, + "ISO_Move_Line_Up" : 0xfe21, + "ISO_Next_Group" : 0xfe08, + "ISO_Next_Group_Lock" : 0xfe09, + "ISO_Partial_Line_Down" : 0xfe24, + "ISO_Partial_Line_Up" : 0xfe23, + "ISO_Partial_Space_Left" : 0xfe25, + "ISO_Partial_Space_Right" : 0xfe26, + "ISO_Prev_Group" : 0xfe0a, + "ISO_Prev_Group_Lock" : 0xfe0b, + "ISO_Release_Both_Margins" : 0xfe2b, + "ISO_Release_Margin_Left" : 0xfe29, + "ISO_Release_Margin_Right" : 0xfe2a, + "ISO_Set_Margin_Left" : 0xfe27, + "ISO_Set_Margin_Right" : 0xfe28, + "Iabovedot" : 0x02a9, + "Iacute" : 0x00cd, + "Ibelowdot" : 0x1001eca, + "Ibreve" : 0x100012c, + "Icircumflex" : 0x00ce, + "Idiaeresis" : 0x00cf, + "Igrave" : 0x00cc, + "Ihook" : 0x1001ec8, + "Imacron" : 0x03cf, + "Insert" : 0xff63, + "Iogonek" : 0x03c7, + "Itilde" : 0x03a5, + "J" : 0x004a, + "Jcircumflex" : 0x02ac, + "K" : 0x004b, + "KP_0" : 0xffb0, + "KP_1" : 0xffb1, + "KP_2" : 0xffb2, + "KP_3" : 0xffb3, + "KP_4" : 0xffb4, + "KP_5" : 0xffb5, + "KP_6" : 0xffb6, + "KP_7" : 0xffb7, + "KP_8" : 0xffb8, + "KP_9" : 0xffb9, + "KP_Add" : 0xffab, + "KP_Begin" : 0xff9d, + "KP_Decimal" : 0xffae, + "KP_Delete" : 0xff9f, + "KP_Divide" : 0xffaf, + "KP_Down" : 0xff99, + "KP_End" : 0xff9c, + "KP_Enter" : 0xff8d, + "KP_Equal" : 0xffbd, + "KP_F1" : 0xff91, + "KP_F2" : 0xff92, + "KP_F3" : 0xff93, + "KP_F4" : 0xff94, + "KP_Home" : 0xff95, + "KP_Insert" : 0xff9e, + "KP_Left" : 0xff96, + "KP_Multiply" : 0xffaa, + "KP_Next" : 0xff9b, + "KP_Page_Down" : 0xff9b, + "KP_Page_Up" : 0xff9a, + "KP_Prior" : 0xff9a, + "KP_Right" : 0xff98, + "KP_Separator" : 0xffac, + "KP_Space" : 0xff80, + "KP_Subtract" : 0xffad, + "KP_Tab" : 0xff89, + "KP_Up" : 0xff97, + "Kana_Lock" : 0xff2d, + "Kana_Shift" : 0xff2e, + "Kanji" : 0xff21, + "Kanji_Bangou" : 0xff37, + "Katakana" : 0xff26, + "Kcedilla" : 0x03d3, + "Korean_Won" : 0x0eff, + "L" : 0x004c, + "L1" : 0xffc8, + "L10" : 0xffd1, + "L2" : 0xffc9, + "L3" : 0xffca, + "L4" : 0xffcb, + "L5" : 0xffcc, + "L6" : 0xffcd, + "L7" : 0xffce, + "L8" : 0xffcf, + "L9" : 0xffd0, + "Lacute" : 0x01c5, + "Last_Virtual_Screen" : 0xfed4, + "Lbelowdot" : 0x1001e36, + "Lcaron" : 0x01a5, + "Lcedilla" : 0x03a6, + "Left" : 0xff51, + "Linefeed" : 0xff0a, + "LiraSign" : 0x10020a4, + "Lstroke" : 0x01a3, + "M" : 0x004d, + "Mabovedot" : 0x1001e40, + "Macedonia_DSE" : 0x06b5, + "Macedonia_GJE" : 0x06b2, + "Macedonia_KJE" : 0x06bc, + "Macedonia_dse" : 0x06a5, + "Macedonia_gje" : 0x06a2, + "Macedonia_kje" : 0x06ac, + "Mae_Koho" : 0xff3e, + "Massyo" : 0xff2c, + "Menu" : 0xff67, + "Meta_L" : 0xffe7, + "Meta_R" : 0xffe8, + "MillSign" : 0x10020a5, + "Mode_switch" : 0xff7e, + "MouseKeys_Accel_Enable" : 0xfe77, + "MouseKeys_Enable" : 0xfe76, + "Muhenkan" : 0xff22, + "Multi_key" : 0xff20, + "MultipleCandidate" : 0xff3d, + "N" : 0x004e, + "Nacute" : 0x01d1, + "NairaSign" : 0x10020a6, + "Ncaron" : 0x01d2, + "Ncedilla" : 0x03d1, + "NewSheqelSign" : 0x10020aa, + "Next" : 0xff56, + "Next_Virtual_Screen" : 0xfed2, + "Ntilde" : 0x00d1, + "Num_Lock" : 0xff7f, + "O" : 0x004f, + "OE" : 0x13bc, + "Oacute" : 0x00d3, + "Obarred" : 0x100019f, + "Obelowdot" : 0x1001ecc, + "Ocaron" : 0x10001d1, + "Ocircumflex" : 0x00d4, + "Ocircumflexacute" : 0x1001ed0, + "Ocircumflexbelowdot" : 0x1001ed8, + "Ocircumflexgrave" : 0x1001ed2, + "Ocircumflexhook" : 0x1001ed4, + "Ocircumflextilde" : 0x1001ed6, + "Odiaeresis" : 0x00d6, + "Odoubleacute" : 0x01d5, + "Ograve" : 0x00d2, + "Ohook" : 0x1001ece, + "Ohorn" : 0x10001a0, + "Ohornacute" : 0x1001eda, + "Ohornbelowdot" : 0x1001ee2, + "Ohorngrave" : 0x1001edc, + "Ohornhook" : 0x1001ede, + "Ohorntilde" : 0x1001ee0, + "Omacron" : 0x03d2, + "Ooblique" : 0x00d8, + "Oslash" : 0x00d8, + "Otilde" : 0x00d5, + "Overlay1_Enable" : 0xfe78, + "Overlay2_Enable" : 0xfe79, + "P" : 0x0050, + "Pabovedot" : 0x1001e56, + "Page_Down" : 0xff56, + "Page_Up" : 0xff55, + "Pause" : 0xff13, + "PesetaSign" : 0x10020a7, + "Pointer_Accelerate" : 0xfefa, + "Pointer_Button1" : 0xfee9, + "Pointer_Button2" : 0xfeea, + "Pointer_Button3" : 0xfeeb, + "Pointer_Button4" : 0xfeec, + "Pointer_Button5" : 0xfeed, + "Pointer_Button_Dflt" : 0xfee8, + "Pointer_DblClick1" : 0xfeef, + "Pointer_DblClick2" : 0xfef0, + "Pointer_DblClick3" : 0xfef1, + "Pointer_DblClick4" : 0xfef2, + "Pointer_DblClick5" : 0xfef3, + "Pointer_DblClick_Dflt" : 0xfeee, + "Pointer_DfltBtnNext" : 0xfefb, + "Pointer_DfltBtnPrev" : 0xfefc, + "Pointer_Down" : 0xfee3, + "Pointer_DownLeft" : 0xfee6, + "Pointer_DownRight" : 0xfee7, + "Pointer_Drag1" : 0xfef5, + "Pointer_Drag2" : 0xfef6, + "Pointer_Drag3" : 0xfef7, + "Pointer_Drag4" : 0xfef8, + "Pointer_Drag5" : 0xfefd, + "Pointer_Drag_Dflt" : 0xfef4, + "Pointer_EnableKeys" : 0xfef9, + "Pointer_Left" : 0xfee0, + "Pointer_Right" : 0xfee1, + "Pointer_Up" : 0xfee2, + "Pointer_UpLeft" : 0xfee4, + "Pointer_UpRight" : 0xfee5, + "Prev_Virtual_Screen" : 0xfed1, + "PreviousCandidate" : 0xff3e, + "Print" : 0xff61, + "Prior" : 0xff55, + "Q" : 0x0051, + "R" : 0x0052, + "R1" : 0xffd2, + "R10" : 0xffdb, + "R11" : 0xffdc, + "R12" : 0xffdd, + "R13" : 0xffde, + "R14" : 0xffdf, + "R15" : 0xffe0, + "R2" : 0xffd3, + "R3" : 0xffd4, + "R4" : 0xffd5, + "R5" : 0xffd6, + "R6" : 0xffd7, + "R7" : 0xffd8, + "R8" : 0xffd9, + "R9" : 0xffda, + "Racute" : 0x01c0, + "Rcaron" : 0x01d8, + "Rcedilla" : 0x03a3, + "Redo" : 0xff66, + "RepeatKeys_Enable" : 0xfe72, + "Return" : 0xff0d, + "Right" : 0xff53, + "Romaji" : 0xff24, + "RupeeSign" : 0x10020a8, + "S" : 0x0053, + "SCHWA" : 0x100018f, + "Sabovedot" : 0x1001e60, + "Sacute" : 0x01a6, + "Scaron" : 0x01a9, + "Scedilla" : 0x01aa, + "Scircumflex" : 0x02de, + "Scroll_Lock" : 0xff14, + "Select" : 0xff60, + "Serbian_DJE" : 0x06b1, + "Serbian_DZE" : 0x06bf, + "Serbian_JE" : 0x06b8, + "Serbian_LJE" : 0x06b9, + "Serbian_NJE" : 0x06ba, + "Serbian_TSHE" : 0x06bb, + "Serbian_dje" : 0x06a1, + "Serbian_dze" : 0x06af, + "Serbian_je" : 0x06a8, + "Serbian_lje" : 0x06a9, + "Serbian_nje" : 0x06aa, + "Serbian_tshe" : 0x06ab, + "Shift_L" : 0xffe1, + "Shift_Lock" : 0xffe6, + "Shift_R" : 0xffe2, + "SingleCandidate" : 0xff3c, + "SlowKeys_Enable" : 0xfe73, + "StickyKeys_Enable" : 0xfe75, + "Super_L" : 0xffeb, + "Super_R" : 0xffec, + "Sys_Req" : 0xff15, + "T" : 0x0054, + "THORN" : 0x00de, + "Tab" : 0xff09, + "Tabovedot" : 0x1001e6a, + "Tcaron" : 0x01ab, + "Tcedilla" : 0x01de, + "Terminate_Server" : 0xfed5, + "Thai_baht" : 0x0ddf, + "Thai_bobaimai" : 0x0dba, + "Thai_chochan" : 0x0da8, + "Thai_chochang" : 0x0daa, + "Thai_choching" : 0x0da9, + "Thai_chochoe" : 0x0dac, + "Thai_dochada" : 0x0dae, + "Thai_dodek" : 0x0db4, + "Thai_fofa" : 0x0dbd, + "Thai_fofan" : 0x0dbf, + "Thai_hohip" : 0x0dcb, + "Thai_honokhuk" : 0x0dce, + "Thai_khokhai" : 0x0da2, + "Thai_khokhon" : 0x0da5, + "Thai_khokhuat" : 0x0da3, + "Thai_khokhwai" : 0x0da4, + "Thai_khorakhang" : 0x0da6, + "Thai_kokai" : 0x0da1, + "Thai_lakkhangyao" : 0x0de5, + "Thai_lekchet" : 0x0df7, + "Thai_lekha" : 0x0df5, + "Thai_lekhok" : 0x0df6, + "Thai_lekkao" : 0x0df9, + "Thai_leknung" : 0x0df1, + "Thai_lekpaet" : 0x0df8, + "Thai_leksam" : 0x0df3, + "Thai_leksi" : 0x0df4, + "Thai_leksong" : 0x0df2, + "Thai_leksun" : 0x0df0, + "Thai_lochula" : 0x0dcc, + "Thai_loling" : 0x0dc5, + "Thai_lu" : 0x0dc6, + "Thai_maichattawa" : 0x0deb, + "Thai_maiek" : 0x0de8, + "Thai_maihanakat" : 0x0dd1, + "Thai_maihanakat_maitho" : 0x0dde, + "Thai_maitaikhu" : 0x0de7, + "Thai_maitho" : 0x0de9, + "Thai_maitri" : 0x0dea, + "Thai_maiyamok" : 0x0de6, + "Thai_moma" : 0x0dc1, + "Thai_ngongu" : 0x0da7, + "Thai_nikhahit" : 0x0ded, + "Thai_nonen" : 0x0db3, + "Thai_nonu" : 0x0db9, + "Thai_oang" : 0x0dcd, + "Thai_paiyannoi" : 0x0dcf, + "Thai_phinthu" : 0x0dda, + "Thai_phophan" : 0x0dbe, + "Thai_phophung" : 0x0dbc, + "Thai_phosamphao" : 0x0dc0, + "Thai_popla" : 0x0dbb, + "Thai_rorua" : 0x0dc3, + "Thai_ru" : 0x0dc4, + "Thai_saraa" : 0x0dd0, + "Thai_saraaa" : 0x0dd2, + "Thai_saraae" : 0x0de1, + "Thai_saraaimaimalai" : 0x0de4, + "Thai_saraaimaimuan" : 0x0de3, + "Thai_saraam" : 0x0dd3, + "Thai_sarae" : 0x0de0, + "Thai_sarai" : 0x0dd4, + "Thai_saraii" : 0x0dd5, + "Thai_sarao" : 0x0de2, + "Thai_sarau" : 0x0dd8, + "Thai_saraue" : 0x0dd6, + "Thai_sarauee" : 0x0dd7, + "Thai_sarauu" : 0x0dd9, + "Thai_sorusi" : 0x0dc9, + "Thai_sosala" : 0x0dc8, + "Thai_soso" : 0x0dab, + "Thai_sosua" : 0x0dca, + "Thai_thanthakhat" : 0x0dec, + "Thai_thonangmontho" : 0x0db1, + "Thai_thophuthao" : 0x0db2, + "Thai_thothahan" : 0x0db7, + "Thai_thothan" : 0x0db0, + "Thai_thothong" : 0x0db8, + "Thai_thothung" : 0x0db6, + "Thai_topatak" : 0x0daf, + "Thai_totao" : 0x0db5, + "Thai_wowaen" : 0x0dc7, + "Thai_yoyak" : 0x0dc2, + "Thai_yoying" : 0x0dad, + "Thorn" : 0x00de, + "Touroku" : 0xff2b, + "Tslash" : 0x03ac, + "U" : 0x0055, + "Uacute" : 0x00da, + "Ubelowdot" : 0x1001ee4, + "Ubreve" : 0x02dd, + "Ucircumflex" : 0x00db, + "Udiaeresis" : 0x00dc, + "Udoubleacute" : 0x01db, + "Ugrave" : 0x00d9, + "Uhook" : 0x1001ee6, + "Uhorn" : 0x10001af, + "Uhornacute" : 0x1001ee8, + "Uhornbelowdot" : 0x1001ef0, + "Uhorngrave" : 0x1001eea, + "Uhornhook" : 0x1001eec, + "Uhorntilde" : 0x1001eee, + "Ukrainian_GHE_WITH_UPTURN" : 0x06bd, + "Ukrainian_I" : 0x06b6, + "Ukrainian_IE" : 0x06b4, + "Ukrainian_YI" : 0x06b7, + "Ukrainian_ghe_with_upturn" : 0x06ad, + "Ukrainian_i" : 0x06a6, + "Ukrainian_ie" : 0x06a4, + "Ukrainian_yi" : 0x06a7, + "Ukranian_I" : 0x06b6, + "Ukranian_JE" : 0x06b4, + "Ukranian_YI" : 0x06b7, + "Ukranian_i" : 0x06a6, + "Ukranian_je" : 0x06a4, + "Ukranian_yi" : 0x06a7, + "Umacron" : 0x03de, + "Undo" : 0xff65, + "Uogonek" : 0x03d9, + "Up" : 0xff52, + "Uring" : 0x01d9, + "Utilde" : 0x03dd, + "V" : 0x0056, + "VoidSymbol" : 0xffffff, + "W" : 0x0057, + "Wacute" : 0x1001e82, + "Wcircumflex" : 0x1000174, + "Wdiaeresis" : 0x1001e84, + "Wgrave" : 0x1001e80, + "WonSign" : 0x10020a9, + "X" : 0x0058, + "Xabovedot" : 0x1001e8a, + "Y" : 0x0059, + "Yacute" : 0x00dd, + "Ybelowdot" : 0x1001ef4, + "Ycircumflex" : 0x1000176, + "Ydiaeresis" : 0x13be, + "Ygrave" : 0x1001ef2, + "Yhook" : 0x1001ef6, + "Ytilde" : 0x1001ef8, + "Z" : 0x005a, + "Zabovedot" : 0x01af, + "Zacute" : 0x01ac, + "Zcaron" : 0x01ae, + "Zen_Koho" : 0xff3d, + "Zenkaku" : 0xff28, + "Zenkaku_Hankaku" : 0xff2a, + "Zstroke" : 0x10001b5, + "a" : 0x0061, + "aacute" : 0x00e1, + "abelowdot" : 0x1001ea1, + "abovedot" : 0x01ff, + "abreve" : 0x01e3, + "abreveacute" : 0x1001eaf, + "abrevebelowdot" : 0x1001eb7, + "abrevegrave" : 0x1001eb1, + "abrevehook" : 0x1001eb3, + "abrevetilde" : 0x1001eb5, + "acircumflex" : 0x00e2, + "acircumflexacute" : 0x1001ea5, + "acircumflexbelowdot" : 0x1001ead, + "acircumflexgrave" : 0x1001ea7, + "acircumflexhook" : 0x1001ea9, + "acircumflextilde" : 0x1001eab, + "acute" : 0x00b4, + "adiaeresis" : 0x00e4, + "ae" : 0x00e6, + "agrave" : 0x00e0, + "ahook" : 0x1001ea3, + "amacron" : 0x03e0, + "ampersand" : 0x0026, + "aogonek" : 0x01b1, + "apostrophe" : 0x0027, + "approxeq" : 0x1002248, + "approximate" : 0x08c8, + "aring" : 0x00e5, + "asciicircum" : 0x005e, + "asciitilde" : 0x007e, + "asterisk" : 0x002a, + "at" : 0x0040, + "atilde" : 0x00e3, + "b" : 0x0062, + "babovedot" : 0x1001e03, + "backslash" : 0x005c, + "ballotcross" : 0x0af4, + "bar" : 0x007c, + "because" : 0x1002235, + "blank" : 0x09df, + "botintegral" : 0x08a5, + "botleftparens" : 0x08ac, + "botleftsqbracket" : 0x08a8, + "botleftsummation" : 0x08b2, + "botrightparens" : 0x08ae, + "botrightsqbracket" : 0x08aa, + "botrightsummation" : 0x08b6, + "bott" : 0x09f6, + "botvertsummationconnector" : 0x08b4, + "braceleft" : 0x007b, + "braceright" : 0x007d, + "bracketleft" : 0x005b, + "bracketright" : 0x005d, + "braille_blank" : 0x1002800, + "braille_dot_1" : 0xfff1, + "braille_dot_10" : 0xfffa, + "braille_dot_2" : 0xfff2, + "braille_dot_3" : 0xfff3, + "braille_dot_4" : 0xfff4, + "braille_dot_5" : 0xfff5, + "braille_dot_6" : 0xfff6, + "braille_dot_7" : 0xfff7, + "braille_dot_8" : 0xfff8, + "braille_dot_9" : 0xfff9, + "braille_dots_1" : 0x1002801, + "braille_dots_12" : 0x1002803, + "braille_dots_123" : 0x1002807, + "braille_dots_1234" : 0x100280f, + "braille_dots_12345" : 0x100281f, + "braille_dots_123456" : 0x100283f, + "braille_dots_1234567" : 0x100287f, + "braille_dots_12345678" : 0x10028ff, + "braille_dots_1234568" : 0x10028bf, + "braille_dots_123457" : 0x100285f, + "braille_dots_1234578" : 0x10028df, + "braille_dots_123458" : 0x100289f, + "braille_dots_12346" : 0x100282f, + "braille_dots_123467" : 0x100286f, + "braille_dots_1234678" : 0x10028ef, + "braille_dots_123468" : 0x10028af, + "braille_dots_12347" : 0x100284f, + "braille_dots_123478" : 0x10028cf, + "braille_dots_12348" : 0x100288f, + "braille_dots_1235" : 0x1002817, + "braille_dots_12356" : 0x1002837, + "braille_dots_123567" : 0x1002877, + "braille_dots_1235678" : 0x10028f7, + "braille_dots_123568" : 0x10028b7, + "braille_dots_12357" : 0x1002857, + "braille_dots_123578" : 0x10028d7, + "braille_dots_12358" : 0x1002897, + "braille_dots_1236" : 0x1002827, + "braille_dots_12367" : 0x1002867, + "braille_dots_123678" : 0x10028e7, + "braille_dots_12368" : 0x10028a7, + "braille_dots_1237" : 0x1002847, + "braille_dots_12378" : 0x10028c7, + "braille_dots_1238" : 0x1002887, + "braille_dots_124" : 0x100280b, + "braille_dots_1245" : 0x100281b, + "braille_dots_12456" : 0x100283b, + "braille_dots_124567" : 0x100287b, + "braille_dots_1245678" : 0x10028fb, + "braille_dots_124568" : 0x10028bb, + "braille_dots_12457" : 0x100285b, + "braille_dots_124578" : 0x10028db, + "braille_dots_12458" : 0x100289b, + "braille_dots_1246" : 0x100282b, + "braille_dots_12467" : 0x100286b, + "braille_dots_124678" : 0x10028eb, + "braille_dots_12468" : 0x10028ab, + "braille_dots_1247" : 0x100284b, + "braille_dots_12478" : 0x10028cb, + "braille_dots_1248" : 0x100288b, + "braille_dots_125" : 0x1002813, + "braille_dots_1256" : 0x1002833, + "braille_dots_12567" : 0x1002873, + "braille_dots_125678" : 0x10028f3, + "braille_dots_12568" : 0x10028b3, + "braille_dots_1257" : 0x1002853, + "braille_dots_12578" : 0x10028d3, + "braille_dots_1258" : 0x1002893, + "braille_dots_126" : 0x1002823, + "braille_dots_1267" : 0x1002863, + "braille_dots_12678" : 0x10028e3, + "braille_dots_1268" : 0x10028a3, + "braille_dots_127" : 0x1002843, + "braille_dots_1278" : 0x10028c3, + "braille_dots_128" : 0x1002883, + "braille_dots_13" : 0x1002805, + "braille_dots_134" : 0x100280d, + "braille_dots_1345" : 0x100281d, + "braille_dots_13456" : 0x100283d, + "braille_dots_134567" : 0x100287d, + "braille_dots_1345678" : 0x10028fd, + "braille_dots_134568" : 0x10028bd, + "braille_dots_13457" : 0x100285d, + "braille_dots_134578" : 0x10028dd, + "braille_dots_13458" : 0x100289d, + "braille_dots_1346" : 0x100282d, + "braille_dots_13467" : 0x100286d, + "braille_dots_134678" : 0x10028ed, + "braille_dots_13468" : 0x10028ad, + "braille_dots_1347" : 0x100284d, + "braille_dots_13478" : 0x10028cd, + "braille_dots_1348" : 0x100288d, + "braille_dots_135" : 0x1002815, + "braille_dots_1356" : 0x1002835, + "braille_dots_13567" : 0x1002875, + "braille_dots_135678" : 0x10028f5, + "braille_dots_13568" : 0x10028b5, + "braille_dots_1357" : 0x1002855, + "braille_dots_13578" : 0x10028d5, + "braille_dots_1358" : 0x1002895, + "braille_dots_136" : 0x1002825, + "braille_dots_1367" : 0x1002865, + "braille_dots_13678" : 0x10028e5, + "braille_dots_1368" : 0x10028a5, + "braille_dots_137" : 0x1002845, + "braille_dots_1378" : 0x10028c5, + "braille_dots_138" : 0x1002885, + "braille_dots_14" : 0x1002809, + "braille_dots_145" : 0x1002819, + "braille_dots_1456" : 0x1002839, + "braille_dots_14567" : 0x1002879, + "braille_dots_145678" : 0x10028f9, + "braille_dots_14568" : 0x10028b9, + "braille_dots_1457" : 0x1002859, + "braille_dots_14578" : 0x10028d9, + "braille_dots_1458" : 0x1002899, + "braille_dots_146" : 0x1002829, + "braille_dots_1467" : 0x1002869, + "braille_dots_14678" : 0x10028e9, + "braille_dots_1468" : 0x10028a9, + "braille_dots_147" : 0x1002849, + "braille_dots_1478" : 0x10028c9, + "braille_dots_148" : 0x1002889, + "braille_dots_15" : 0x1002811, + "braille_dots_156" : 0x1002831, + "braille_dots_1567" : 0x1002871, + "braille_dots_15678" : 0x10028f1, + "braille_dots_1568" : 0x10028b1, + "braille_dots_157" : 0x1002851, + "braille_dots_1578" : 0x10028d1, + "braille_dots_158" : 0x1002891, + "braille_dots_16" : 0x1002821, + "braille_dots_167" : 0x1002861, + "braille_dots_1678" : 0x10028e1, + "braille_dots_168" : 0x10028a1, + "braille_dots_17" : 0x1002841, + "braille_dots_178" : 0x10028c1, + "braille_dots_18" : 0x1002881, + "braille_dots_2" : 0x1002802, + "braille_dots_23" : 0x1002806, + "braille_dots_234" : 0x100280e, + "braille_dots_2345" : 0x100281e, + "braille_dots_23456" : 0x100283e, + "braille_dots_234567" : 0x100287e, + "braille_dots_2345678" : 0x10028fe, + "braille_dots_234568" : 0x10028be, + "braille_dots_23457" : 0x100285e, + "braille_dots_234578" : 0x10028de, + "braille_dots_23458" : 0x100289e, + "braille_dots_2346" : 0x100282e, + "braille_dots_23467" : 0x100286e, + "braille_dots_234678" : 0x10028ee, + "braille_dots_23468" : 0x10028ae, + "braille_dots_2347" : 0x100284e, + "braille_dots_23478" : 0x10028ce, + "braille_dots_2348" : 0x100288e, + "braille_dots_235" : 0x1002816, + "braille_dots_2356" : 0x1002836, + "braille_dots_23567" : 0x1002876, + "braille_dots_235678" : 0x10028f6, + "braille_dots_23568" : 0x10028b6, + "braille_dots_2357" : 0x1002856, + "braille_dots_23578" : 0x10028d6, + "braille_dots_2358" : 0x1002896, + "braille_dots_236" : 0x1002826, + "braille_dots_2367" : 0x1002866, + "braille_dots_23678" : 0x10028e6, + "braille_dots_2368" : 0x10028a6, + "braille_dots_237" : 0x1002846, + "braille_dots_2378" : 0x10028c6, + "braille_dots_238" : 0x1002886, + "braille_dots_24" : 0x100280a, + "braille_dots_245" : 0x100281a, + "braille_dots_2456" : 0x100283a, + "braille_dots_24567" : 0x100287a, + "braille_dots_245678" : 0x10028fa, + "braille_dots_24568" : 0x10028ba, + "braille_dots_2457" : 0x100285a, + "braille_dots_24578" : 0x10028da, + "braille_dots_2458" : 0x100289a, + "braille_dots_246" : 0x100282a, + "braille_dots_2467" : 0x100286a, + "braille_dots_24678" : 0x10028ea, + "braille_dots_2468" : 0x10028aa, + "braille_dots_247" : 0x100284a, + "braille_dots_2478" : 0x10028ca, + "braille_dots_248" : 0x100288a, + "braille_dots_25" : 0x1002812, + "braille_dots_256" : 0x1002832, + "braille_dots_2567" : 0x1002872, + "braille_dots_25678" : 0x10028f2, + "braille_dots_2568" : 0x10028b2, + "braille_dots_257" : 0x1002852, + "braille_dots_2578" : 0x10028d2, + "braille_dots_258" : 0x1002892, + "braille_dots_26" : 0x1002822, + "braille_dots_267" : 0x1002862, + "braille_dots_2678" : 0x10028e2, + "braille_dots_268" : 0x10028a2, + "braille_dots_27" : 0x1002842, + "braille_dots_278" : 0x10028c2, + "braille_dots_28" : 0x1002882, + "braille_dots_3" : 0x1002804, + "braille_dots_34" : 0x100280c, + "braille_dots_345" : 0x100281c, + "braille_dots_3456" : 0x100283c, + "braille_dots_34567" : 0x100287c, + "braille_dots_345678" : 0x10028fc, + "braille_dots_34568" : 0x10028bc, + "braille_dots_3457" : 0x100285c, + "braille_dots_34578" : 0x10028dc, + "braille_dots_3458" : 0x100289c, + "braille_dots_346" : 0x100282c, + "braille_dots_3467" : 0x100286c, + "braille_dots_34678" : 0x10028ec, + "braille_dots_3468" : 0x10028ac, + "braille_dots_347" : 0x100284c, + "braille_dots_3478" : 0x10028cc, + "braille_dots_348" : 0x100288c, + "braille_dots_35" : 0x1002814, + "braille_dots_356" : 0x1002834, + "braille_dots_3567" : 0x1002874, + "braille_dots_35678" : 0x10028f4, + "braille_dots_3568" : 0x10028b4, + "braille_dots_357" : 0x1002854, + "braille_dots_3578" : 0x10028d4, + "braille_dots_358" : 0x1002894, + "braille_dots_36" : 0x1002824, + "braille_dots_367" : 0x1002864, + "braille_dots_3678" : 0x10028e4, + "braille_dots_368" : 0x10028a4, + "braille_dots_37" : 0x1002844, + "braille_dots_378" : 0x10028c4, + "braille_dots_38" : 0x1002884, + "braille_dots_4" : 0x1002808, + "braille_dots_45" : 0x1002818, + "braille_dots_456" : 0x1002838, + "braille_dots_4567" : 0x1002878, + "braille_dots_45678" : 0x10028f8, + "braille_dots_4568" : 0x10028b8, + "braille_dots_457" : 0x1002858, + "braille_dots_4578" : 0x10028d8, + "braille_dots_458" : 0x1002898, + "braille_dots_46" : 0x1002828, + "braille_dots_467" : 0x1002868, + "braille_dots_4678" : 0x10028e8, + "braille_dots_468" : 0x10028a8, + "braille_dots_47" : 0x1002848, + "braille_dots_478" : 0x10028c8, + "braille_dots_48" : 0x1002888, + "braille_dots_5" : 0x1002810, + "braille_dots_56" : 0x1002830, + "braille_dots_567" : 0x1002870, + "braille_dots_5678" : 0x10028f0, + "braille_dots_568" : 0x10028b0, + "braille_dots_57" : 0x1002850, + "braille_dots_578" : 0x10028d0, + "braille_dots_58" : 0x1002890, + "braille_dots_6" : 0x1002820, + "braille_dots_67" : 0x1002860, + "braille_dots_678" : 0x10028e0, + "braille_dots_68" : 0x10028a0, + "braille_dots_7" : 0x1002840, + "braille_dots_78" : 0x10028c0, + "braille_dots_8" : 0x1002880, + "breve" : 0x01a2, + "brokenbar" : 0x00a6, + "c" : 0x0063, + "cabovedot" : 0x02e5, + "cacute" : 0x01e6, + "careof" : 0x0ab8, + "caret" : 0x0afc, + "caron" : 0x01b7, + "ccaron" : 0x01e8, + "ccedilla" : 0x00e7, + "ccircumflex" : 0x02e6, + "cedilla" : 0x00b8, + "cent" : 0x00a2, + "checkerboard" : 0x09e1, + "checkmark" : 0x0af3, + "circle" : 0x0bcf, + "club" : 0x0aec, + "colon" : 0x003a, + "comma" : 0x002c, + "containsas" : 0x100220B, + "copyright" : 0x00a9, + "cr" : 0x09e4, + "crossinglines" : 0x09ee, + "cuberoot" : 0x100221B, + "currency" : 0x00a4, + "cursor" : 0x0aff, + "d" : 0x0064, + "dabovedot" : 0x1001e0b, + "dagger" : 0x0af1, + "dcaron" : 0x01ef, + "dead_abovecomma" : 0xfe64, + "dead_abovedot" : 0xfe56, + "dead_abovereversedcomma" : 0xfe65, + "dead_abovering" : 0xfe58, + "dead_acute" : 0xfe51, + "dead_belowbreve" : 0xfe6b, + "dead_belowcircumflex" : 0xfe69, + "dead_belowdiaeresis" : 0xfe6c, + "dead_belowdot" : 0xfe60, + "dead_belowmacron" : 0xfe68, + "dead_belowring" : 0xfe67, + "dead_belowtilde" : 0xfe6a, + "dead_breve" : 0xfe55, + "dead_caron" : 0xfe5a, + "dead_cedilla" : 0xfe5b, + "dead_circumflex" : 0xfe52, + "dead_dasia" : 0xfe65, + "dead_diaeresis" : 0xfe57, + "dead_doubleacute" : 0xfe59, + "dead_grave" : 0xfe50, + "dead_hook" : 0xfe61, + "dead_horn" : 0xfe62, + "dead_iota" : 0xfe5d, + "dead_macron" : 0xfe54, + "dead_ogonek" : 0xfe5c, + "dead_perispomeni" : 0xfe53, + "dead_psili" : 0xfe64, + "dead_semivoiced_sound" : 0xfe5f, + "dead_stroke" : 0xfe63, + "dead_tilde" : 0xfe53, + "dead_voiced_sound" : 0xfe5e, + "decimalpoint" : 0x0abd, + "degree" : 0x00b0, + "diaeresis" : 0x00a8, + "diamond" : 0x0aed, + "digitspace" : 0x0aa5, + "dintegral" : 0x100222C, + "division" : 0x00f7, + "dollar" : 0x0024, + "doubbaselinedot" : 0x0aaf, + "doubleacute" : 0x01bd, + "doubledagger" : 0x0af2, + "doublelowquotemark" : 0x0afe, + "downarrow" : 0x08fe, + "downcaret" : 0x0ba8, + "downshoe" : 0x0bd6, + "downstile" : 0x0bc4, + "downtack" : 0x0bc2, + "dstroke" : 0x01f0, + "e" : 0x0065, + "eabovedot" : 0x03ec, + "eacute" : 0x00e9, + "ebelowdot" : 0x1001eb9, + "ecaron" : 0x01ec, + "ecircumflex" : 0x00ea, + "ecircumflexacute" : 0x1001ebf, + "ecircumflexbelowdot" : 0x1001ec7, + "ecircumflexgrave" : 0x1001ec1, + "ecircumflexhook" : 0x1001ec3, + "ecircumflextilde" : 0x1001ec5, + "ediaeresis" : 0x00eb, + "egrave" : 0x00e8, + "ehook" : 0x1001ebb, + "eightsubscript" : 0x1002088, + "eightsuperior" : 0x1002078, + "elementof" : 0x1002208, + "ellipsis" : 0x0aae, + "em3space" : 0x0aa3, + "em4space" : 0x0aa4, + "emacron" : 0x03ba, + "emdash" : 0x0aa9, + "emfilledcircle" : 0x0ade, + "emfilledrect" : 0x0adf, + "emopencircle" : 0x0ace, + "emopenrectangle" : 0x0acf, + "emptyset" : 0x1002205, + "emspace" : 0x0aa1, + "endash" : 0x0aaa, + "enfilledcircbullet" : 0x0ae6, + "enfilledsqbullet" : 0x0ae7, + "eng" : 0x03bf, + "enopencircbullet" : 0x0ae0, + "enopensquarebullet" : 0x0ae1, + "enspace" : 0x0aa2, + "eogonek" : 0x01ea, + "equal" : 0x003d, + "eth" : 0x00f0, + "etilde" : 0x1001ebd, + "exclam" : 0x0021, + "exclamdown" : 0x00a1, + "f" : 0x0066, + "fabovedot" : 0x1001e1f, + "femalesymbol" : 0x0af8, + "ff" : 0x09e3, + "figdash" : 0x0abb, + "filledlefttribullet" : 0x0adc, + "filledrectbullet" : 0x0adb, + "filledrighttribullet" : 0x0add, + "filledtribulletdown" : 0x0ae9, + "filledtribulletup" : 0x0ae8, + "fiveeighths" : 0x0ac5, + "fivesixths" : 0x0ab7, + "fivesubscript" : 0x1002085, + "fivesuperior" : 0x1002075, + "fourfifths" : 0x0ab5, + "foursubscript" : 0x1002084, + "foursuperior" : 0x1002074, + "fourthroot" : 0x100221C, + "function" : 0x08f6, + "g" : 0x0067, + "gabovedot" : 0x02f5, + "gbreve" : 0x02bb, + "gcaron" : 0x10001e7, + "gcedilla" : 0x03bb, + "gcircumflex" : 0x02f8, + "grave" : 0x0060, + "greater" : 0x003e, + "greaterthanequal" : 0x08be, + "guillemotleft" : 0x00ab, + "guillemotright" : 0x00bb, + "h" : 0x0068, + "hairspace" : 0x0aa8, + "hcircumflex" : 0x02b6, + "heart" : 0x0aee, + "hebrew_aleph" : 0x0ce0, + "hebrew_ayin" : 0x0cf2, + "hebrew_bet" : 0x0ce1, + "hebrew_beth" : 0x0ce1, + "hebrew_chet" : 0x0ce7, + "hebrew_dalet" : 0x0ce3, + "hebrew_daleth" : 0x0ce3, + "hebrew_doublelowline" : 0x0cdf, + "hebrew_finalkaph" : 0x0cea, + "hebrew_finalmem" : 0x0ced, + "hebrew_finalnun" : 0x0cef, + "hebrew_finalpe" : 0x0cf3, + "hebrew_finalzade" : 0x0cf5, + "hebrew_finalzadi" : 0x0cf5, + "hebrew_gimel" : 0x0ce2, + "hebrew_gimmel" : 0x0ce2, + "hebrew_he" : 0x0ce4, + "hebrew_het" : 0x0ce7, + "hebrew_kaph" : 0x0ceb, + "hebrew_kuf" : 0x0cf7, + "hebrew_lamed" : 0x0cec, + "hebrew_mem" : 0x0cee, + "hebrew_nun" : 0x0cf0, + "hebrew_pe" : 0x0cf4, + "hebrew_qoph" : 0x0cf7, + "hebrew_resh" : 0x0cf8, + "hebrew_samech" : 0x0cf1, + "hebrew_samekh" : 0x0cf1, + "hebrew_shin" : 0x0cf9, + "hebrew_taf" : 0x0cfa, + "hebrew_taw" : 0x0cfa, + "hebrew_tet" : 0x0ce8, + "hebrew_teth" : 0x0ce8, + "hebrew_waw" : 0x0ce5, + "hebrew_yod" : 0x0ce9, + "hebrew_zade" : 0x0cf6, + "hebrew_zadi" : 0x0cf6, + "hebrew_zain" : 0x0ce6, + "hebrew_zayin" : 0x0ce6, + "hexagram" : 0x0ada, + "horizconnector" : 0x08a3, + "horizlinescan1" : 0x09ef, + "horizlinescan3" : 0x09f0, + "horizlinescan5" : 0x09f1, + "horizlinescan7" : 0x09f2, + "horizlinescan9" : 0x09f3, + "hstroke" : 0x02b1, + "ht" : 0x09e2, + "hyphen" : 0x00ad, + "i" : 0x0069, + "iacute" : 0x00ed, + "ibelowdot" : 0x1001ecb, + "ibreve" : 0x100012d, + "icircumflex" : 0x00ee, + "identical" : 0x08cf, + "idiaeresis" : 0x00ef, + "idotless" : 0x02b9, + "ifonlyif" : 0x08cd, + "igrave" : 0x00ec, + "ihook" : 0x1001ec9, + "imacron" : 0x03ef, + "implies" : 0x08ce, + "includedin" : 0x08da, + "includes" : 0x08db, + "infinity" : 0x08c2, + "integral" : 0x08bf, + "intersection" : 0x08dc, + "iogonek" : 0x03e7, + "itilde" : 0x03b5, + "j" : 0x006a, + "jcircumflex" : 0x02bc, + "jot" : 0x0bca, + "k" : 0x006b, + "kana_A" : 0x04b1, + "kana_CHI" : 0x04c1, + "kana_E" : 0x04b4, + "kana_FU" : 0x04cc, + "kana_HA" : 0x04ca, + "kana_HE" : 0x04cd, + "kana_HI" : 0x04cb, + "kana_HO" : 0x04ce, + "kana_HU" : 0x04cc, + "kana_I" : 0x04b2, + "kana_KA" : 0x04b6, + "kana_KE" : 0x04b9, + "kana_KI" : 0x04b7, + "kana_KO" : 0x04ba, + "kana_KU" : 0x04b8, + "kana_MA" : 0x04cf, + "kana_ME" : 0x04d2, + "kana_MI" : 0x04d0, + "kana_MO" : 0x04d3, + "kana_MU" : 0x04d1, + "kana_N" : 0x04dd, + "kana_NA" : 0x04c5, + "kana_NE" : 0x04c8, + "kana_NI" : 0x04c6, + "kana_NO" : 0x04c9, + "kana_NU" : 0x04c7, + "kana_O" : 0x04b5, + "kana_RA" : 0x04d7, + "kana_RE" : 0x04da, + "kana_RI" : 0x04d8, + "kana_RO" : 0x04db, + "kana_RU" : 0x04d9, + "kana_SA" : 0x04bb, + "kana_SE" : 0x04be, + "kana_SHI" : 0x04bc, + "kana_SO" : 0x04bf, + "kana_SU" : 0x04bd, + "kana_TA" : 0x04c0, + "kana_TE" : 0x04c3, + "kana_TI" : 0x04c1, + "kana_TO" : 0x04c4, + "kana_TSU" : 0x04c2, + "kana_TU" : 0x04c2, + "kana_U" : 0x04b3, + "kana_WA" : 0x04dc, + "kana_WO" : 0x04a6, + "kana_YA" : 0x04d4, + "kana_YO" : 0x04d6, + "kana_YU" : 0x04d5, + "kana_a" : 0x04a7, + "kana_closingbracket" : 0x04a3, + "kana_comma" : 0x04a4, + "kana_conjunctive" : 0x04a5, + "kana_e" : 0x04aa, + "kana_fullstop" : 0x04a1, + "kana_i" : 0x04a8, + "kana_middledot" : 0x04a5, + "kana_o" : 0x04ab, + "kana_openingbracket" : 0x04a2, + "kana_switch" : 0xff7e, + "kana_tsu" : 0x04af, + "kana_tu" : 0x04af, + "kana_u" : 0x04a9, + "kana_ya" : 0x04ac, + "kana_yo" : 0x04ae, + "kana_yu" : 0x04ad, + "kappa" : 0x03a2, + "kcedilla" : 0x03f3, + "kra" : 0x03a2, + "l" : 0x006c, + "lacute" : 0x01e5, + "latincross" : 0x0ad9, + "lbelowdot" : 0x1001e37, + "lcaron" : 0x01b5, + "lcedilla" : 0x03b6, + "leftanglebracket" : 0x0abc, + "leftarrow" : 0x08fb, + "leftcaret" : 0x0ba3, + "leftdoublequotemark" : 0x0ad2, + "leftmiddlecurlybrace" : 0x08af, + "leftopentriangle" : 0x0acc, + "leftpointer" : 0x0aea, + "leftradical" : 0x08a1, + "leftshoe" : 0x0bda, + "leftsinglequotemark" : 0x0ad0, + "leftt" : 0x09f4, + "lefttack" : 0x0bdc, + "less" : 0x003c, + "lessthanequal" : 0x08bc, + "lf" : 0x09e5, + "logicaland" : 0x08de, + "logicalor" : 0x08df, + "lowleftcorner" : 0x09ed, + "lowrightcorner" : 0x09ea, + "lstroke" : 0x01b3, + "m" : 0x006d, + "mabovedot" : 0x1001e41, + "macron" : 0x00af, + "malesymbol" : 0x0af7, + "maltesecross" : 0x0af0, + "marker" : 0x0abf, + "masculine" : 0x00ba, + "minus" : 0x002d, + "minutes" : 0x0ad6, + "mu" : 0x00b5, + "multiply" : 0x00d7, + "musicalflat" : 0x0af6, + "musicalsharp" : 0x0af5, + "n" : 0x006e, + "nabla" : 0x08c5, + "nacute" : 0x01f1, + "ncaron" : 0x01f2, + "ncedilla" : 0x03f1, + "ninesubscript" : 0x1002089, + "ninesuperior" : 0x1002079, + "nl" : 0x09e8, + "nobreakspace" : 0x00a0, + "notapproxeq" : 0x1002247, + "notelementof" : 0x1002209, + "notequal" : 0x08bd, + "notidentical" : 0x1002262, + "notsign" : 0x00ac, + "ntilde" : 0x00f1, + "numbersign" : 0x0023, + "numerosign" : 0x06b0, + "o" : 0x006f, + "oacute" : 0x00f3, + "obarred" : 0x1000275, + "obelowdot" : 0x1001ecd, + "ocaron" : 0x10001d2, + "ocircumflex" : 0x00f4, + "ocircumflexacute" : 0x1001ed1, + "ocircumflexbelowdot" : 0x1001ed9, + "ocircumflexgrave" : 0x1001ed3, + "ocircumflexhook" : 0x1001ed5, + "ocircumflextilde" : 0x1001ed7, + "odiaeresis" : 0x00f6, + "odoubleacute" : 0x01f5, + "oe" : 0x13bd, + "ogonek" : 0x01b2, + "ograve" : 0x00f2, + "ohook" : 0x1001ecf, + "ohorn" : 0x10001a1, + "ohornacute" : 0x1001edb, + "ohornbelowdot" : 0x1001ee3, + "ohorngrave" : 0x1001edd, + "ohornhook" : 0x1001edf, + "ohorntilde" : 0x1001ee1, + "omacron" : 0x03f2, + "oneeighth" : 0x0ac3, + "onefifth" : 0x0ab2, + "onehalf" : 0x00bd, + "onequarter" : 0x00bc, + "onesixth" : 0x0ab6, + "onesubscript" : 0x1002081, + "onesuperior" : 0x00b9, + "onethird" : 0x0ab0, + "ooblique" : 0x00f8, + "openrectbullet" : 0x0ae2, + "openstar" : 0x0ae5, + "opentribulletdown" : 0x0ae4, + "opentribulletup" : 0x0ae3, + "ordfeminine" : 0x00aa, + "oslash" : 0x00f8, + "otilde" : 0x00f5, + "overbar" : 0x0bc0, + "overline" : 0x047e, + "p" : 0x0070, + "pabovedot" : 0x1001e57, + "paragraph" : 0x00b6, + "parenleft" : 0x0028, + "parenright" : 0x0029, + "partdifferential" : 0x1002202, + "partialderivative" : 0x08ef, + "percent" : 0x0025, + "period" : 0x002e, + "periodcentered" : 0x00b7, + "phonographcopyright" : 0x0afb, + "plus" : 0x002b, + "plusminus" : 0x00b1, + "prescription" : 0x0ad4, + "prolongedsound" : 0x04b0, + "punctspace" : 0x0aa6, + "q" : 0x0071, + "quad" : 0x0bcc, + "question" : 0x003f, + "questiondown" : 0x00bf, + "quotedbl" : 0x0022, + "quoteleft" : 0x0060, + "quoteright" : 0x0027, + "r" : 0x0072, + "racute" : 0x01e0, + "radical" : 0x08d6, + "rcaron" : 0x01f8, + "rcedilla" : 0x03b3, + "registered" : 0x00ae, + "rightanglebracket" : 0x0abe, + "rightarrow" : 0x08fd, + "rightcaret" : 0x0ba6, + "rightdoublequotemark" : 0x0ad3, + "rightmiddlecurlybrace" : 0x08b0, + "rightmiddlesummation" : 0x08b7, + "rightopentriangle" : 0x0acd, + "rightpointer" : 0x0aeb, + "rightshoe" : 0x0bd8, + "rightsinglequotemark" : 0x0ad1, + "rightt" : 0x09f5, + "righttack" : 0x0bfc, + "s" : 0x0073, + "sabovedot" : 0x1001e61, + "sacute" : 0x01b6, + "scaron" : 0x01b9, + "scedilla" : 0x01ba, + "schwa" : 0x1000259, + "scircumflex" : 0x02fe, + "script_switch" : 0xff7e, + "seconds" : 0x0ad7, + "section" : 0x00a7, + "semicolon" : 0x003b, + "semivoicedsound" : 0x04df, + "seveneighths" : 0x0ac6, + "sevensubscript" : 0x1002087, + "sevensuperior" : 0x1002077, + "signaturemark" : 0x0aca, + "signifblank" : 0x0aac, + "similarequal" : 0x08c9, + "singlelowquotemark" : 0x0afd, + "sixsubscript" : 0x1002086, + "sixsuperior" : 0x1002076, + "slash" : 0x002f, + "soliddiamond" : 0x09e0, + "space" : 0x0020, + "squareroot" : 0x100221A, + "ssharp" : 0x00df, + "sterling" : 0x00a3, + "stricteq" : 0x1002263, + "t" : 0x0074, + "tabovedot" : 0x1001e6b, + "tcaron" : 0x01bb, + "tcedilla" : 0x01fe, + "telephone" : 0x0af9, + "telephonerecorder" : 0x0afa, + "therefore" : 0x08c0, + "thinspace" : 0x0aa7, + "thorn" : 0x00fe, + "threeeighths" : 0x0ac4, + "threefifths" : 0x0ab4, + "threequarters" : 0x00be, + "threesubscript" : 0x1002083, + "threesuperior" : 0x00b3, + "tintegral" : 0x100222D, + "topintegral" : 0x08a4, + "topleftparens" : 0x08ab, + "topleftradical" : 0x08a2, + "topleftsqbracket" : 0x08a7, + "topleftsummation" : 0x08b1, + "toprightparens" : 0x08ad, + "toprightsqbracket" : 0x08a9, + "toprightsummation" : 0x08b5, + "topt" : 0x09f7, + "topvertsummationconnector" : 0x08b3, + "trademark" : 0x0ac9, + "trademarkincircle" : 0x0acb, + "tslash" : 0x03bc, + "twofifths" : 0x0ab3, + "twosubscript" : 0x1002082, + "twosuperior" : 0x00b2, + "twothirds" : 0x0ab1, + "u" : 0x0075, + "uacute" : 0x00fa, + "ubelowdot" : 0x1001ee5, + "ubreve" : 0x02fd, + "ucircumflex" : 0x00fb, + "udiaeresis" : 0x00fc, + "udoubleacute" : 0x01fb, + "ugrave" : 0x00f9, + "uhook" : 0x1001ee7, + "uhorn" : 0x10001b0, + "uhornacute" : 0x1001ee9, + "uhornbelowdot" : 0x1001ef1, + "uhorngrave" : 0x1001eeb, + "uhornhook" : 0x1001eed, + "uhorntilde" : 0x1001eef, + "umacron" : 0x03fe, + "underbar" : 0x0bc6, + "underscore" : 0x005f, + "union" : 0x08dd, + "uogonek" : 0x03f9, + "uparrow" : 0x08fc, + "upcaret" : 0x0ba9, + "upleftcorner" : 0x09ec, + "uprightcorner" : 0x09eb, + "upshoe" : 0x0bc3, + "upstile" : 0x0bd3, + "uptack" : 0x0bce, + "uring" : 0x01f9, + "utilde" : 0x03fd, + "v" : 0x0076, + "variation" : 0x08c1, + "vertbar" : 0x09f8, + "vertconnector" : 0x08a6, + "voicedsound" : 0x04de, + "vt" : 0x09e9, + "w" : 0x0077, + "wacute" : 0x1001e83, + "wcircumflex" : 0x1000175, + "wdiaeresis" : 0x1001e85, + "wgrave" : 0x1001e81, + "x" : 0x0078, + "xabovedot" : 0x1001e8b, + "y" : 0x0079, + "yacute" : 0x00fd, + "ybelowdot" : 0x1001ef5, + "ycircumflex" : 0x1000177, + "ydiaeresis" : 0x00ff, + "yen" : 0x00a5, + "ygrave" : 0x1001ef3, + "yhook" : 0x1001ef7, + "ytilde" : 0x1001ef9, + "z" : 0x007a, + "zabovedot" : 0x01bf, + "zacute" : 0x01bc, + "zcaron" : 0x01be, + "zerosubscript" : 0x1002080, + "zerosuperior" : 0x1002070, + "zstroke" : 0x10001b6, +} diff --git a/KeyboardLayoutEditor/src/KeysymsUni.py b/KeyboardLayoutEditor/src/KeysymsUni.py @@ -0,0 +1,1390 @@ +#!/usr/bin/env python +# -*- encoding: UTF-8 -*- +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/> + +KeysymsUni = { + "0" : 0x30, + "1" : 0x31, + "2" : 0x32, + "3" : 0x33, + "4" : 0x34, + "5" : 0x35, + "6" : 0x36, + "7" : 0x37, + "8" : 0x38, + "9" : 0x39, + "A" : 0x41, + "AE" : 0xC6, + "Aacute" : 0xC1, + "Abelowdot" : 0x1EA0, + "Abreve" : 0x102, + "Abreveacute" : 0x1EAE, + "Abrevebelowdot" : 0x1EB6, + "Abrevegrave" : 0x1EB0, + "Abrevehook" : 0x1EB2, + "Abrevetilde" : 0x1EB4, + "Acircumflex" : 0xC2, + "Acircumflexacute" : 0x1EA4, + "Acircumflexbelowdot" : 0x1EAC, + "Acircumflexgrave" : 0x1EA6, + "Acircumflexhook" : 0x1EA8, + "Acircumflextilde" : 0x1EAA, + "Adiaeresis" : 0xC4, + "Agrave" : 0xC0, + "Ahook" : 0x1EA2, + "Amacron" : 0x100, + "Aogonek" : 0x104, + "Arabic_0" : 0x660, + "Arabic_1" : 0x661, + "Arabic_2" : 0x662, + "Arabic_3" : 0x663, + "Arabic_4" : 0x664, + "Arabic_5" : 0x665, + "Arabic_6" : 0x666, + "Arabic_7" : 0x667, + "Arabic_8" : 0x668, + "Arabic_9" : 0x669, + "Arabic_ain" : 0x639, + "Arabic_alef" : 0x627, + "Arabic_alefmaksura" : 0x649, + "Arabic_beh" : 0x628, + "Arabic_comma" : 0x60C, + "Arabic_dad" : 0x636, + "Arabic_dal" : 0x62F, + "Arabic_damma" : 0x64F, + "Arabic_dammatan" : 0x64C, + "Arabic_ddal" : 0x688, + "Arabic_fatha" : 0x64E, + "Arabic_fathatan" : 0x64B, + "Arabic_feh" : 0x641, + "Arabic_fullstop" : 0x6D4, + "Arabic_gaf" : 0x6AF, + "Arabic_ghain" : 0x63A, + "Arabic_ha" : 0x647, + "Arabic_hah" : 0x62D, + "Arabic_hamza" : 0x621, + "Arabic_hamza_above" : 0x654, + "Arabic_hamza_below" : 0x655, + "Arabic_hamzaonalef" : 0x623, + "Arabic_hamzaonwaw" : 0x624, + "Arabic_hamzaonyeh" : 0x626, + "Arabic_hamzaunderalef" : 0x625, + "Arabic_heh_doachashmee" : 0x6BE, + "Arabic_heh_goal" : 0x6C1, + "Arabic_jeem" : 0x62C, + "Arabic_jeh" : 0x698, + "Arabic_kaf" : 0x643, + "Arabic_kasra" : 0x650, + "Arabic_kasratan" : 0x64D, + "Arabic_keheh" : 0x6A9, + "Arabic_khah" : 0x62E, + "Arabic_lam" : 0x644, + "Arabic_madda_above" : 0x653, + "Arabic_maddaonalef" : 0x622, + "Arabic_meem" : 0x645, + "Arabic_noon" : 0x646, + "Arabic_noon_ghunna" : 0x6BA, + "Arabic_peh" : 0x67E, + "Arabic_percent" : 0x66A, + "Arabic_qaf" : 0x642, + "Arabic_question_mark" : 0x61F, + "Arabic_ra" : 0x631, + "Arabic_rreh" : 0x691, + "Arabic_sad" : 0x635, + "Arabic_seen" : 0x633, + "Arabic_semicolon" : 0x61B, + "Arabic_shadda" : 0x651, + "Arabic_sheen" : 0x634, + "Arabic_sukun" : 0x652, + "Arabic_superscript_alef" : 0x670, + "Arabic_tah" : 0x637, + "Arabic_tatweel" : 0x640, + "Arabic_tcheh" : 0x686, + "Arabic_teh" : 0x62A, + "Arabic_tehmarbuta" : 0x629, + "Arabic_thal" : 0x630, + "Arabic_theh" : 0x62B, + "Arabic_tteh" : 0x679, + "Arabic_veh" : 0x6A4, + "Arabic_waw" : 0x648, + "Arabic_yeh" : 0x64A, + "Arabic_yeh_baree" : 0x6D2, + "Arabic_zah" : 0x638, + "Arabic_zain" : 0x632, + "Aring" : 0xC5, + "Armenian_AT" : 0x538, + "Armenian_AYB" : 0x531, + "Armenian_BEN" : 0x532, + "Armenian_CHA" : 0x549, + "Armenian_DA" : 0x534, + "Armenian_DZA" : 0x541, + "Armenian_E" : 0x537, + "Armenian_FE" : 0x556, + "Armenian_GHAT" : 0x542, + "Armenian_GIM" : 0x533, + "Armenian_HI" : 0x545, + "Armenian_HO" : 0x540, + "Armenian_INI" : 0x53B, + "Armenian_JE" : 0x54B, + "Armenian_KE" : 0x554, + "Armenian_KEN" : 0x53F, + "Armenian_KHE" : 0x53D, + "Armenian_LYUN" : 0x53C, + "Armenian_MEN" : 0x544, + "Armenian_NU" : 0x546, + "Armenian_O" : 0x555, + "Armenian_PE" : 0x54A, + "Armenian_PYUR" : 0x553, + "Armenian_RA" : 0x54C, + "Armenian_RE" : 0x550, + "Armenian_SE" : 0x54D, + "Armenian_SHA" : 0x547, + "Armenian_TCHE" : 0x543, + "Armenian_TO" : 0x539, + "Armenian_TSA" : 0x53E, + "Armenian_TSO" : 0x551, + "Armenian_TYUN" : 0x54F, + "Armenian_VEV" : 0x54E, + "Armenian_VO" : 0x548, + "Armenian_VYUN" : 0x552, + "Armenian_YECH" : 0x535, + "Armenian_ZA" : 0x536, + "Armenian_ZHE" : 0x53A, + "Armenian_amanak" : 0x55C, + "Armenian_apostrophe" : 0x55A, + "Armenian_at" : 0x568, + "Armenian_ayb" : 0x561, + "Armenian_ben" : 0x562, + "Armenian_but" : 0x55D, + "Armenian_cha" : 0x579, + "Armenian_comma" : 0x2C, + "Armenian_da" : 0x564, + "Armenian_dza" : 0x571, + "Armenian_e" : 0x567, + "Armenian_ellipsis" : 0x2026, + "Armenian_em_dash" : 0x2014, + "Armenian_en_dash" : 0x2013, + "Armenian_fe" : 0x586, + "Armenian_ghat" : 0x572, + "Armenian_gim" : 0x563, + "Armenian_guillemotleft" : 0xAB, + "Armenian_guillemotright" : 0xBB, + "Armenian_hi" : 0x575, + "Armenian_ho" : 0x570, + "Armenian_ini" : 0x56B, + "Armenian_je" : 0x57B, + "Armenian_ke" : 0x584, + "Armenian_ken" : 0x56F, + "Armenian_khe" : 0x56D, + "Armenian_ligature_ew" : 0x587, + "Armenian_lyun" : 0x56C, + "Armenian_men" : 0x574, + "Armenian_mijaket" : 0x2E, + "Armenian_nu" : 0x576, + "Armenian_o" : 0x585, + "Armenian_parenleft" : 0x28, + "Armenian_parenright" : 0x29, + "Armenian_paruyk" : 0x55E, + "Armenian_pe" : 0x57A, + "Armenian_pyur" : 0x583, + "Armenian_ra" : 0x57C, + "Armenian_re" : 0x580, + "Armenian_se" : 0x57D, + "Armenian_section_sign" : 0xA7, + "Armenian_sha" : 0x577, + "Armenian_shesht" : 0x55B, + "Armenian_tche" : 0x573, + "Armenian_to" : 0x569, + "Armenian_tsa" : 0x56E, + "Armenian_tso" : 0x581, + "Armenian_tyun" : 0x57F, + "Armenian_verjaket" : 0x589, + "Armenian_vev" : 0x57E, + "Armenian_vo" : 0x578, + "Armenian_vyun" : 0x582, + "Armenian_yech" : 0x565, + "Armenian_yentamna" : 0x58A, + "Armenian_za" : 0x566, + "Armenian_zhe" : 0x56A, + "Atilde" : 0xC3, + "B" : 0x42, + "Babovedot" : 0x1E02, + "BackSpace" : 0x8, + "Byelorussian_SHORTU" : 0x40E, + "Byelorussian_shortu" : 0x45E, + "C" : 0x43, + "Cabovedot" : 0x10A, + "Cacute" : 0x106, + "Ccaron" : 0x10C, + "Ccedilla" : 0xC7, + "Ccircumflex" : 0x108, + "Clear" : 0xB, + "ColonSign" : 0x20A1, + "CruzeiroSign" : 0x20A2, + "Cyrillic_A" : 0x410, + "Cyrillic_BE" : 0x411, + "Cyrillic_CHE" : 0x427, + "Cyrillic_CHE_descender" : 0x4B6, + "Cyrillic_CHE_vertstroke" : 0x4B8, + "Cyrillic_DE" : 0x414, + "Cyrillic_DZHE" : 0x40F, + "Cyrillic_E" : 0x42D, + "Cyrillic_EF" : 0x424, + "Cyrillic_EL" : 0x41B, + "Cyrillic_EM" : 0x41C, + "Cyrillic_EN" : 0x41D, + "Cyrillic_EN_descender" : 0x4A2, + "Cyrillic_ER" : 0x420, + "Cyrillic_ES" : 0x421, + "Cyrillic_GHE" : 0x413, + "Cyrillic_GHE_bar" : 0x492, + "Cyrillic_HA" : 0x425, + "Cyrillic_HARDSIGN" : 0x42A, + "Cyrillic_HA_descender" : 0x4B2, + "Cyrillic_I" : 0x418, + "Cyrillic_IE" : 0x415, + "Cyrillic_IO" : 0x401, + "Cyrillic_I_macron" : 0x4E2, + "Cyrillic_JE" : 0x408, + "Cyrillic_KA" : 0x41A, + "Cyrillic_KA_descender" : 0x49A, + "Cyrillic_KA_vertstroke" : 0x49C, + "Cyrillic_LJE" : 0x409, + "Cyrillic_NJE" : 0x40A, + "Cyrillic_O" : 0x41E, + "Cyrillic_O_bar" : 0x4E8, + "Cyrillic_PE" : 0x41F, + "Cyrillic_SCHWA" : 0x4D8, + "Cyrillic_SHA" : 0x428, + "Cyrillic_SHCHA" : 0x429, + "Cyrillic_SHHA" : 0x4BA, + "Cyrillic_SHORTI" : 0x419, + "Cyrillic_SOFTSIGN" : 0x42C, + "Cyrillic_TE" : 0x422, + "Cyrillic_TSE" : 0x426, + "Cyrillic_U" : 0x423, + "Cyrillic_U_macron" : 0x4EE, + "Cyrillic_U_straight" : 0x4AE, + "Cyrillic_U_straight_bar" : 0x4B0, + "Cyrillic_VE" : 0x412, + "Cyrillic_YA" : 0x42F, + "Cyrillic_YERU" : 0x42B, + "Cyrillic_YU" : 0x42E, + "Cyrillic_ZE" : 0x417, + "Cyrillic_ZHE" : 0x416, + "Cyrillic_ZHE_descender" : 0x496, + "Cyrillic_a" : 0x430, + "Cyrillic_be" : 0x431, + "Cyrillic_che" : 0x447, + "Cyrillic_che_descender" : 0x4B7, + "Cyrillic_che_vertstroke" : 0x4B9, + "Cyrillic_de" : 0x434, + "Cyrillic_dzhe" : 0x45F, + "Cyrillic_e" : 0x44D, + "Cyrillic_ef" : 0x444, + "Cyrillic_el" : 0x43B, + "Cyrillic_em" : 0x43C, + "Cyrillic_en" : 0x43D, + "Cyrillic_en_descender" : 0x4A3, + "Cyrillic_er" : 0x440, + "Cyrillic_es" : 0x441, + "Cyrillic_ghe" : 0x433, + "Cyrillic_ghe_bar" : 0x493, + "Cyrillic_ha" : 0x445, + "Cyrillic_ha_descender" : 0x4B3, + "Cyrillic_hardsign" : 0x44A, + "Cyrillic_i" : 0x438, + "Cyrillic_i_macron" : 0x4E3, + "Cyrillic_ie" : 0x435, + "Cyrillic_io" : 0x451, + "Cyrillic_je" : 0x458, + "Cyrillic_ka" : 0x43A, + "Cyrillic_ka_descender" : 0x49B, + "Cyrillic_ka_vertstroke" : 0x49D, + "Cyrillic_lje" : 0x459, + "Cyrillic_nje" : 0x45A, + "Cyrillic_o" : 0x43E, + "Cyrillic_o_bar" : 0x4E9, + "Cyrillic_pe" : 0x43F, + "Cyrillic_schwa" : 0x4D9, + "Cyrillic_sha" : 0x448, + "Cyrillic_shcha" : 0x449, + "Cyrillic_shha" : 0x4BB, + "Cyrillic_shorti" : 0x439, + "Cyrillic_softsign" : 0x44C, + "Cyrillic_te" : 0x442, + "Cyrillic_tse" : 0x446, + "Cyrillic_u" : 0x443, + "Cyrillic_u_macron" : 0x4EF, + "Cyrillic_u_straight" : 0x4AF, + "Cyrillic_u_straight_bar" : 0x4B1, + "Cyrillic_ve" : 0x432, + "Cyrillic_ya" : 0x44F, + "Cyrillic_yeru" : 0x44B, + "Cyrillic_yu" : 0x44E, + "Cyrillic_ze" : 0x437, + "Cyrillic_zhe" : 0x436, + "Cyrillic_zhe_descender" : 0x497, + "D" : 0x44, + "Dabovedot" : 0x1E0A, + "Dcaron" : 0x10E, + "DongSign" : 0x20AB, + "Dstroke" : 0x110, + "E" : 0x45, + "ENG" : 0x14A, + "ETH" : 0xD0, + "Eabovedot" : 0x116, + "Eacute" : 0xC9, + "Ebelowdot" : 0x1EB8, + "Ecaron" : 0x11A, + "Ecircumflex" : 0xCA, + "Ecircumflexacute" : 0x1EBE, + "Ecircumflexbelowdot" : 0x1EC6, + "Ecircumflexgrave" : 0x1EC0, + "Ecircumflexhook" : 0x1EC2, + "Ecircumflextilde" : 0x1EC4, + "EcuSign" : 0x20A0, + "Ediaeresis" : 0xCB, + "Egrave" : 0xC8, + "Ehook" : 0x1EBA, + "Emacron" : 0x112, + "Eogonek" : 0x118, + "Escape" : 0x1B, + "Eth" : 0xD0, + "Etilde" : 0x1EBC, + "EuroSign" : 0x20AC, + "F" : 0x46, + "FFrancSign" : 0x20A3, + "Fabovedot" : 0x1E1E, + "Farsi_0" : 0x6F0, + "Farsi_1" : 0x6F1, + "Farsi_2" : 0x6F2, + "Farsi_3" : 0x6F3, + "Farsi_4" : 0x6F4, + "Farsi_5" : 0x6F5, + "Farsi_6" : 0x6F6, + "Farsi_7" : 0x6F7, + "Farsi_8" : 0x6F8, + "Farsi_9" : 0x6F9, + "Farsi_yeh" : 0x6CC, + "G" : 0x47, + "Gabovedot" : 0x120, + "Gbreve" : 0x11E, + "Gcaron" : 0x1E6, + "Gcedilla" : 0x122, + "Gcircumflex" : 0x11C, + "Georgian_an" : 0x10D0, + "Georgian_ban" : 0x10D1, + "Georgian_can" : 0x10EA, + "Georgian_char" : 0x10ED, + "Georgian_chin" : 0x10E9, + "Georgian_cil" : 0x10EC, + "Georgian_don" : 0x10D3, + "Georgian_en" : 0x10D4, + "Georgian_fi" : 0x10F6, + "Georgian_gan" : 0x10D2, + "Georgian_ghan" : 0x10E6, + "Georgian_hae" : 0x10F0, + "Georgian_har" : 0x10F4, + "Georgian_he" : 0x10F1, + "Georgian_hie" : 0x10F2, + "Georgian_hoe" : 0x10F5, + "Georgian_in" : 0x10D8, + "Georgian_jhan" : 0x10EF, + "Georgian_jil" : 0x10EB, + "Georgian_kan" : 0x10D9, + "Georgian_khar" : 0x10E5, + "Georgian_las" : 0x10DA, + "Georgian_man" : 0x10DB, + "Georgian_nar" : 0x10DC, + "Georgian_on" : 0x10DD, + "Georgian_par" : 0x10DE, + "Georgian_phar" : 0x10E4, + "Georgian_qar" : 0x10E7, + "Georgian_rae" : 0x10E0, + "Georgian_san" : 0x10E1, + "Georgian_shin" : 0x10E8, + "Georgian_tan" : 0x10D7, + "Georgian_tar" : 0x10E2, + "Georgian_un" : 0x10E3, + "Georgian_vin" : 0x10D5, + "Georgian_we" : 0x10F3, + "Georgian_xan" : 0x10EE, + "Georgian_zen" : 0x10D6, + "Georgian_zhar" : 0x10DF, + "Greek_ALPHA" : 0x391, + "Greek_ALPHAaccent" : 0x386, + "Greek_BETA" : 0x392, + "Greek_CHI" : 0x3A7, + "Greek_DELTA" : 0x394, + "Greek_EPSILON" : 0x395, + "Greek_EPSILONaccent" : 0x388, + "Greek_ETA" : 0x397, + "Greek_ETAaccent" : 0x389, + "Greek_GAMMA" : 0x393, + "Greek_IOTA" : 0x399, + "Greek_IOTAaccent" : 0x38A, + "Greek_IOTAdiaeresis" : 0x3AA, + "Greek_KAPPA" : 0x39A, + "Greek_LAMBDA" : 0x39B, + "Greek_LAMDA" : 0x39B, + "Greek_MU" : 0x39C, + "Greek_NU" : 0x39D, + "Greek_OMEGA" : 0x3A9, + "Greek_OMEGAaccent" : 0x38F, + "Greek_OMICRON" : 0x39F, + "Greek_OMICRONaccent" : 0x38C, + "Greek_PHI" : 0x3A6, + "Greek_PI" : 0x3A0, + "Greek_PSI" : 0x3A8, + "Greek_RHO" : 0x3A1, + "Greek_SIGMA" : 0x3A3, + "Greek_TAU" : 0x3A4, + "Greek_THETA" : 0x398, + "Greek_UPSILON" : 0x3A5, + "Greek_UPSILONaccent" : 0x38E, + "Greek_UPSILONdieresis" : 0x3AB, + "Greek_XI" : 0x39E, + "Greek_ZETA" : 0x396, + "Greek_accentdieresis" : 0x385, + "Greek_alpha" : 0x3B1, + "Greek_alphaaccent" : 0x3AC, + "Greek_beta" : 0x3B2, + "Greek_chi" : 0x3C7, + "Greek_delta" : 0x3B4, + "Greek_epsilon" : 0x3B5, + "Greek_epsilonaccent" : 0x3AD, + "Greek_eta" : 0x3B7, + "Greek_etaaccent" : 0x3AE, + "Greek_finalsmallsigma" : 0x3C2, + "Greek_gamma" : 0x3B3, + "Greek_horizbar" : 0x2015, + "Greek_iota" : 0x3B9, + "Greek_iotaaccent" : 0x3AF, + "Greek_iotaaccentdieresis" : 0x390, + "Greek_iotadieresis" : 0x3CA, + "Greek_kappa" : 0x3BA, + "Greek_lambda" : 0x3BB, + "Greek_mu" : 0x3BC, + "Greek_nu" : 0x3BD, + "Greek_omega" : 0x3C9, + "Greek_omegaaccent" : 0x3CE, + "Greek_omicron" : 0x3BF, + "Greek_omicronaccent" : 0x3CC, + "Greek_phi" : 0x3C6, + "Greek_pi" : 0x3C0, + "Greek_psi" : 0x3C8, + "Greek_rho" : 0x3C1, + "Greek_sigma" : 0x3C3, + "Greek_tau" : 0x3C4, + "Greek_theta" : 0x3B8, + "Greek_upsilon" : 0x3C5, + "Greek_upsilonaccent" : 0x3CD, + "Greek_upsilonaccentdieresis" : 0x3B0, + "Greek_upsilondieresis" : 0x3CB, + "Greek_xi" : 0x3BE, + "Greek_zeta" : 0x3B6, + "H" : 0x48, + "Hangul_A" : 0x314F, + "Hangul_AE" : 0x3150, + "Hangul_AraeA" : 0x318D, + "Hangul_AraeAE" : 0x318E, + "Hangul_Cieuc" : 0x314A, + "Hangul_Dikeud" : 0x3137, + "Hangul_E" : 0x3154, + "Hangul_EO" : 0x3153, + "Hangul_EU" : 0x3161, + "Hangul_Hieuh" : 0x314E, + "Hangul_I" : 0x3163, + "Hangul_Ieung" : 0x3147, + "Hangul_J_Cieuc" : 0x11BE, + "Hangul_J_Dikeud" : 0x11AE, + "Hangul_J_Hieuh" : 0x11C2, + "Hangul_J_Ieung" : 0x11BC, + "Hangul_J_Jieuj" : 0x11BD, + "Hangul_J_Khieuq" : 0x11BF, + "Hangul_J_Kiyeog" : 0x11A8, + "Hangul_J_KiyeogSios" : 0x11AA, + "Hangul_J_KkogjiDalrinIeung" : 0x11F0, + "Hangul_J_Mieum" : 0x11B7, + "Hangul_J_Nieun" : 0x11AB, + "Hangul_J_NieunHieuh" : 0x11AD, + "Hangul_J_NieunJieuj" : 0x11AC, + "Hangul_J_PanSios" : 0x11EB, + "Hangul_J_Phieuf" : 0x11C1, + "Hangul_J_Pieub" : 0x11B8, + "Hangul_J_PieubSios" : 0x11B9, + "Hangul_J_Rieul" : 0x11AF, + "Hangul_J_RieulHieuh" : 0x11B6, + "Hangul_J_RieulKiyeog" : 0x11B0, + "Hangul_J_RieulMieum" : 0x11B1, + "Hangul_J_RieulPhieuf" : 0x11B5, + "Hangul_J_RieulPieub" : 0x11B2, + "Hangul_J_RieulSios" : 0x11B3, + "Hangul_J_RieulTieut" : 0x11B4, + "Hangul_J_Sios" : 0x11BA, + "Hangul_J_SsangKiyeog" : 0x11A9, + "Hangul_J_SsangSios" : 0x11BB, + "Hangul_J_Tieut" : 0x11C0, + "Hangul_J_YeorinHieuh" : 0x11F9, + "Hangul_Jieuj" : 0x3148, + "Hangul_Khieuq" : 0x314B, + "Hangul_Kiyeog" : 0x3131, + "Hangul_KiyeogSios" : 0x3133, + "Hangul_KkogjiDalrinIeung" : 0x3181, + "Hangul_Mieum" : 0x3141, + "Hangul_Nieun" : 0x3134, + "Hangul_NieunHieuh" : 0x3136, + "Hangul_NieunJieuj" : 0x3135, + "Hangul_O" : 0x3157, + "Hangul_OE" : 0x315A, + "Hangul_PanSios" : 0x317F, + "Hangul_Phieuf" : 0x314D, + "Hangul_Pieub" : 0x3142, + "Hangul_PieubSios" : 0x3144, + "Hangul_Rieul" : 0x3139, + "Hangul_RieulHieuh" : 0x3140, + "Hangul_RieulKiyeog" : 0x313A, + "Hangul_RieulMieum" : 0x313B, + "Hangul_RieulPhieuf" : 0x313F, + "Hangul_RieulPieub" : 0x313C, + "Hangul_RieulSios" : 0x313D, + "Hangul_RieulTieut" : 0x313E, + "Hangul_RieulYeorinHieuh" : 0x316D, + "Hangul_Sios" : 0x3145, + "Hangul_SsangDikeud" : 0x3138, + "Hangul_SsangJieuj" : 0x3149, + "Hangul_SsangKiyeog" : 0x3132, + "Hangul_SsangPieub" : 0x3143, + "Hangul_SsangSios" : 0x3146, + "Hangul_SunkyeongeumMieum" : 0x3171, + "Hangul_SunkyeongeumPhieuf" : 0x3184, + "Hangul_SunkyeongeumPieub" : 0x3178, + "Hangul_Tieut" : 0x314C, + "Hangul_U" : 0x315C, + "Hangul_WA" : 0x3158, + "Hangul_WAE" : 0x3159, + "Hangul_WE" : 0x315E, + "Hangul_WEO" : 0x315D, + "Hangul_WI" : 0x315F, + "Hangul_YA" : 0x3151, + "Hangul_YAE" : 0x3152, + "Hangul_YE" : 0x3156, + "Hangul_YEO" : 0x3155, + "Hangul_YI" : 0x3162, + "Hangul_YO" : 0x315B, + "Hangul_YU" : 0x3160, + "Hangul_YeorinHieuh" : 0x3186, + "Hcircumflex" : 0x124, + "Hstroke" : 0x126, + "I" : 0x49, + "Iabovedot" : 0x130, + "Iacute" : 0xCD, + "Ibelowdot" : 0x1ECA, + "Ibreve" : 0x12C, + "Icircumflex" : 0xCE, + "Idiaeresis" : 0xCF, + "Igrave" : 0xCC, + "Ihook" : 0x1EC8, + "Imacron" : 0x12A, + "Iogonek" : 0x12E, + "Itilde" : 0x128, + "J" : 0x4A, + "Jcircumflex" : 0x134, + "K" : 0x4B, + "KP_0" : 0x30, + "KP_1" : 0x31, + "KP_2" : 0x32, + "KP_3" : 0x33, + "KP_4" : 0x34, + "KP_5" : 0x35, + "KP_6" : 0x36, + "KP_7" : 0x37, + "KP_8" : 0x38, + "KP_9" : 0x39, + "KP_Add" : 0x2B, + "KP_Decimal" : 0x2E, + "KP_Divide" : 0x2F, + "KP_Enter" : 0xD, + "KP_Equal" : 0x3D, + "KP_Multiply" : 0x2A, + "KP_Separator" : 0x2C, + "KP_Space" : 0x20, + "KP_Subtract" : 0x2D, + "KP_Tab" : 0x9, + "Kcedilla" : 0x136, + "Korean_Won" : 0x20A9, + "L" : 0x4C, + "Lacute" : 0x139, + "Lbelowdot" : 0x1E36, + "Lcaron" : 0x13D, + "Lcedilla" : 0x13B, + "Linefeed" : 0xA, + "LiraSign" : 0x20A4, + "Lstroke" : 0x141, + "M" : 0x4D, + "Mabovedot" : 0x1E40, + "Macedonia_DSE" : 0x405, + "Macedonia_GJE" : 0x403, + "Macedonia_KJE" : 0x40C, + "Macedonia_dse" : 0x455, + "Macedonia_gje" : 0x453, + "Macedonia_kje" : 0x45C, + "MillSign" : 0x20A5, + "N" : 0x4E, + "Nacute" : 0x143, + "NairaSign" : 0x20A6, + "Ncaron" : 0x147, + "Ncedilla" : 0x145, + "NewSheqelSign" : 0x20AA, + "Ntilde" : 0xD1, + "O" : 0x4F, + "OE" : 0x152, + "Oacute" : 0xD3, + "Obarred" : 0x19F, + "Obelowdot" : 0x1ECC, + "Ocircumflex" : 0xD4, + "Ocircumflexacute" : 0x1ED0, + "Ocircumflexbelowdot" : 0x1ED8, + "Ocircumflexgrave" : 0x1ED2, + "Ocircumflexhook" : 0x1ED4, + "Ocircumflextilde" : 0x1ED6, + "Odiaeresis" : 0xD6, + "Odoubleacute" : 0x150, + "Ograve" : 0xD2, + "Ohook" : 0x1ECE, + "Ohorn" : 0x1A0, + "Ohornacute" : 0x1EDA, + "Ohornbelowdot" : 0x1EE2, + "Ohorngrave" : 0x1EDC, + "Ohornhook" : 0x1EDE, + "Ohorntilde" : 0x1EE0, + "Omacron" : 0x14C, + "Ooblique" : 0xD8, + "Otilde" : 0xD5, + "P" : 0x50, + "Pabovedot" : 0x1E56, + "Pause" : 0x13, + "PesetaSign" : 0x20A7, + "Q" : 0x51, + "R" : 0x52, + "Racute" : 0x154, + "Rcaron" : 0x158, + "Rcedilla" : 0x156, + "Return" : 0xD, + "RupeeSign" : 0x20A8, + "S" : 0x53, + "SCHWA" : 0x18F, + "Sabovedot" : 0x1E60, + "Sacute" : 0x15A, + "Scaron" : 0x160, + "Scedilla" : 0x15E, + "Scircumflex" : 0x15C, + "Scroll_Lock" : 0x14, + "Serbian_DJE" : 0x402, + "Serbian_TSHE" : 0x40B, + "Serbian_dje" : 0x452, + "Serbian_tshe" : 0x45B, + "Sys_Req" : 0x15, + "T" : 0x54, + "THORN" : 0xDE, + "Tab" : 0x9, + "Tabovedot" : 0x1E6A, + "Tcaron" : 0x164, + "Tcedilla" : 0x162, + "Thai_baht" : 0xE3F, + "Thai_bobaimai" : 0xE1A, + "Thai_chochan" : 0xE08, + "Thai_chochang" : 0xE0A, + "Thai_choching" : 0xE09, + "Thai_chochoe" : 0xE0C, + "Thai_dochada" : 0xE0E, + "Thai_dodek" : 0xE14, + "Thai_fofa" : 0xE1D, + "Thai_fofan" : 0xE1F, + "Thai_hohip" : 0xE2B, + "Thai_honokhuk" : 0xE2E, + "Thai_khokhai" : 0xE02, + "Thai_khokhon" : 0xE05, + "Thai_khokhuat" : 0xE03, + "Thai_khokhwai" : 0xE04, + "Thai_khorakhang" : 0xE06, + "Thai_kokai" : 0xE01, + "Thai_lakkhangyao" : 0xE45, + "Thai_lekchet" : 0xE57, + "Thai_lekha" : 0xE55, + "Thai_lekhok" : 0xE56, + "Thai_lekkao" : 0xE59, + "Thai_leknung" : 0xE51, + "Thai_lekpaet" : 0xE58, + "Thai_leksam" : 0xE53, + "Thai_leksi" : 0xE54, + "Thai_leksong" : 0xE52, + "Thai_leksun" : 0xE50, + "Thai_lochula" : 0xE2C, + "Thai_loling" : 0xE25, + "Thai_lu" : 0xE26, + "Thai_maichattawa" : 0xE4B, + "Thai_maiek" : 0xE48, + "Thai_maihanakat" : 0xE31, + "Thai_maitaikhu" : 0xE47, + "Thai_maitho" : 0xE49, + "Thai_maitri" : 0xE4A, + "Thai_maiyamok" : 0xE46, + "Thai_moma" : 0xE21, + "Thai_ngongu" : 0xE07, + "Thai_nikhahit" : 0xE4D, + "Thai_nonen" : 0xE13, + "Thai_nonu" : 0xE19, + "Thai_oang" : 0xE2D, + "Thai_paiyannoi" : 0xE2F, + "Thai_phinthu" : 0xE3A, + "Thai_phophan" : 0xE1E, + "Thai_phophung" : 0xE1C, + "Thai_phosamphao" : 0xE20, + "Thai_popla" : 0xE1B, + "Thai_rorua" : 0xE23, + "Thai_ru" : 0xE24, + "Thai_saraa" : 0xE30, + "Thai_saraaa" : 0xE32, + "Thai_saraae" : 0xE41, + "Thai_saraaimaimalai" : 0xE44, + "Thai_saraaimaimuan" : 0xE43, + "Thai_saraam" : 0xE33, + "Thai_sarae" : 0xE40, + "Thai_sarai" : 0xE34, + "Thai_saraii" : 0xE35, + "Thai_sarao" : 0xE42, + "Thai_sarau" : 0xE38, + "Thai_saraue" : 0xE36, + "Thai_sarauee" : 0xE37, + "Thai_sarauu" : 0xE39, + "Thai_sorusi" : 0xE29, + "Thai_sosala" : 0xE28, + "Thai_soso" : 0xE0B, + "Thai_sosua" : 0xE2A, + "Thai_thanthakhat" : 0xE4C, + "Thai_thonangmontho" : 0xE11, + "Thai_thophuthao" : 0xE12, + "Thai_thothahan" : 0xE17, + "Thai_thothan" : 0xE10, + "Thai_thothong" : 0xE18, + "Thai_thothung" : 0xE16, + "Thai_topatak" : 0xE0F, + "Thai_totao" : 0xE15, + "Thai_wowaen" : 0xE27, + "Thai_yoyak" : 0xE22, + "Thai_yoying" : 0xE0D, + "Thorn" : 0xDE, + "Tslash" : 0x166, + "U" : 0x55, + "Uacute" : 0xDA, + "Ubelowdot" : 0x1EE4, + "Ubreve" : 0x16C, + "Ucircumflex" : 0xDB, + "Udiaeresis" : 0xDC, + "Udoubleacute" : 0x170, + "Ugrave" : 0xD9, + "Uhook" : 0x1EE6, + "Uhorn" : 0x1AF, + "Uhornacute" : 0x1EE8, + "Uhornbelowdot" : 0x1EF0, + "Uhorngrave" : 0x1EEA, + "Uhornhook" : 0x1EEC, + "Uhorntilde" : 0x1EEE, + "Ukrainian_GHE_WITH_UPTURN" : 0x490, + "Ukrainian_I" : 0x406, + "Ukrainian_IE" : 0x404, + "Ukrainian_YI" : 0x407, + "Ukrainian_ghe_with_upturn" : 0x491, + "Ukrainian_i" : 0x456, + "Ukrainian_ie" : 0x454, + "Ukrainian_yi" : 0x457, + "Umacron" : 0x16A, + "Uogonek" : 0x172, + "Uring" : 0x16E, + "Utilde" : 0x168, + "V" : 0x56, + "W" : 0x57, + "Wacute" : 0x1E82, + "Wcircumflex" : 0x174, + "Wdiaeresis" : 0x1E84, + "Wgrave" : 0x1E80, + "WonSign" : 0x20A9, + "X" : 0x58, + "Xabovedot" : 0x1E8A, + "Y" : 0x59, + "Yacute" : 0xDD, + "Ybelowdot" : 0x1EF4, + "Ycircumflex" : 0x176, + "Ydiaeresis" : 0x178, + "Ygrave" : 0x1EF2, + "Yhook" : 0x1EF6, + "Ytilde" : 0x1EF8, + "Z" : 0x5A, + "Zabovedot" : 0x17B, + "Zacute" : 0x179, + "Zcaron" : 0x17D, + "Zstroke" : 0x1B5, + "a" : 0x61, + "aacute" : 0xE1, + "abelowdot" : 0x1EA1, + "abovedot" : 0x2D9, + "abreve" : 0x103, + "abreveacute" : 0x1EAF, + "abrevebelowdot" : 0x1EB7, + "abrevegrave" : 0x1EB1, + "abrevehook" : 0x1EB3, + "abrevetilde" : 0x1EB5, + "acircumflex" : 0xE2, + "acircumflexacute" : 0x1EA5, + "acircumflexbelowdot" : 0x1EAD, + "acircumflexgrave" : 0x1EA7, + "acircumflexhook" : 0x1EA9, + "acircumflextilde" : 0x1EAB, + "acute" : 0xB4, + "adiaeresis" : 0xE4, + "ae" : 0xE6, + "agrave" : 0xE0, + "ahook" : 0x1EA3, + "amacron" : 0x101, + "ampersand" : 0x26, + "aogonek" : 0x105, + "apostrophe" : 0x27, + "approximate" : 0x223C, + "aring" : 0xE5, + "asciicircum" : 0x5E, + "asciitilde" : 0x7E, + "asterisk" : 0x2A, + "at" : 0x40, + "atilde" : 0xE3, + "b" : 0x62, + "babovedot" : 0x1E03, + "backslash" : 0x5C, + "ballotcross" : 0x2717, + "bar" : 0x7C, + "botintegral" : 0x2321, + "botleftparens" : 0x239D, + "botleftsqbracket" : 0x23A3, + "botrightparens" : 0x23A0, + "botrightsqbracket" : 0x23A6, + "bott" : 0x2534, + "braceleft" : 0x7B, + "braceright" : 0x7D, + "bracketleft" : 0x5B, + "bracketright" : 0x5D, + "breve" : 0x2D8, + "brokenbar" : 0xA6, + "c" : 0x63, + "cabovedot" : 0x10B, + "cacute" : 0x107, + "careof" : 0x2105, + "caret" : 0x2038, + "caron" : 0x2C7, + "ccaron" : 0x10D, + "ccedilla" : 0xE7, + "ccircumflex" : 0x109, + "cedilla" : 0xB8, + "cent" : 0xA2, + "checkerboard" : 0x2592, + "checkmark" : 0x2713, + "circle" : 0x25CB, + "club" : 0x2663, + "colon" : 0x3A, + "combining_acute" : 0x301, + "combining_belowdot" : 0x323, + "combining_grave" : 0x300, + "combining_hook" : 0x309, + "combining_tilde" : 0x303, + "comma" : 0x2C, + "copyright" : 0xA9, + "cr" : 0x240D, + "crossinglines" : 0x253C, + "currency" : 0xA4, + "d" : 0x64, + "dabovedot" : 0x1E0B, + "dagger" : 0x2020, + "dcaron" : 0x10F, + "dead_abovedot" : 0x307, + "dead_abovering" : 0x30A, + "dead_acute" : 0x301, + "dead_belowdot" : 0x323, + "dead_breve" : 0x306, + "dead_caron" : 0x30C, + "dead_cedilla" : 0x327, + "dead_circumflex" : 0x302, + "dead_diaeresis" : 0x308, + "dead_doubleacute" : 0x30B, + "dead_grave" : 0x300, + "dead_hook" : 0x309, + "dead_horn" : 0x31B, + "dead_iota" : 0x345, + "dead_macron" : 0x304, + "dead_ogonek" : 0x328, + "dead_semivoiced_sound" : 0x309A, + "dead_tilde" : 0x303, + "dead_voiced_sound" : 0x3099, + "decimalpoint" : 0x2E, + "degree" : 0xB0, + "diaeresis" : 0xA8, + "diamond" : 0x2666, + "digitspace" : 0x2007, + "division" : 0xF7, + "dollar" : 0x24, + "doubbaselinedot" : 0x2025, + "doubleacute" : 0x2DD, + "doubledagger" : 0x2021, + "doublelowquotemark" : 0x201E, + "downarrow" : 0x2193, + "downcaret" : 0x2228, + "downshoe" : 0x222A, + "downstile" : 0x230A, + "downtack" : 0x22A5, + "dstroke" : 0x111, + "e" : 0x65, + "eabovedot" : 0x117, + "eacute" : 0xE9, + "ebelowdot" : 0x1EB9, + "ecaron" : 0x11B, + "ecircumflex" : 0xEA, + "ecircumflexacute" : 0x1EBF, + "ecircumflexbelowdot" : 0x1EC7, + "ecircumflexgrave" : 0x1EC1, + "ecircumflexhook" : 0x1EC3, + "ecircumflextilde" : 0x1EC5, + "ediaeresis" : 0xEB, + "egrave" : 0xE8, + "ehook" : 0x1EBB, + "ellipsis" : 0x2026, + "em3space" : 0x2004, + "em4space" : 0x2005, + "emacron" : 0x113, + "emdash" : 0x2014, + "emfilledcircle" : 0x25CF, + "emfilledrect" : 0x25AE, + "emopencircle" : 0x25CB, + "emopenrectangle" : 0x25AF, + "emspace" : 0x2003, + "endash" : 0x2013, + "enfilledcircbullet" : 0x2022, + "enfilledsqbullet" : 0x25AA, + "eng" : 0x14B, + "enopencircbullet" : 0x25E6, + "enopensquarebullet" : 0x25AB, + "enspace" : 0x2002, + "eogonek" : 0x119, + "equal" : 0x3D, + "eth" : 0xF0, + "etilde" : 0x1EBD, + "exclam" : 0x21, + "exclamdown" : 0xA1, + "f" : 0x66, + "fabovedot" : 0x1E1F, + "femalesymbol" : 0x2640, + "ff" : 0x240C, + "figdash" : 0x2012, + "filledlefttribullet" : 0x25C0, + "filledrectbullet" : 0x25AC, + "filledrighttribullet" : 0x25B6, + "filledtribulletdown" : 0x25BC, + "filledtribulletup" : 0x25B2, + "fiveeighths" : 0x215D, + "fivesixths" : 0x215A, + "fourfifths" : 0x2158, + "function" : 0x192, + "g" : 0x67, + "gabovedot" : 0x121, + "gbreve" : 0x11F, + "gcaron" : 0x1E7, + "gcedilla" : 0x123, + "gcircumflex" : 0x11D, + "grave" : 0x60, + "greater" : 0x3E, + "greaterthanequal" : 0x2265, + "guillemotleft" : 0xAB, + "guillemotright" : 0xBB, + "h" : 0x68, + "hairspace" : 0x200A, + "hcircumflex" : 0x125, + "heart" : 0x2665, + "hebrew_aleph" : 0x5D0, + "hebrew_ayin" : 0x5E2, + "hebrew_bet" : 0x5D1, + "hebrew_beth" : 0x5D1, + "hebrew_chet" : 0x5D7, + "hebrew_dalet" : 0x5D3, + "hebrew_daleth" : 0x5D3, + "hebrew_doublelowline" : 0x2017, + "hebrew_finalkaph" : 0x5DA, + "hebrew_finalmem" : 0x5DD, + "hebrew_finalnun" : 0x5DF, + "hebrew_finalpe" : 0x5E3, + "hebrew_finalzade" : 0x5E5, + "hebrew_finalzadi" : 0x5E5, + "hebrew_gimel" : 0x5D2, + "hebrew_gimmel" : 0x5D2, + "hebrew_he" : 0x5D4, + "hebrew_het" : 0x5D7, + "hebrew_kaph" : 0x5DB, + "hebrew_kuf" : 0x5E7, + "hebrew_lamed" : 0x5DC, + "hebrew_mem" : 0x5DE, + "hebrew_nun" : 0x5E0, + "hebrew_pe" : 0x5E4, + "hebrew_qoph" : 0x5E7, + "hebrew_resh" : 0x5E8, + "hebrew_samech" : 0x5E1, + "hebrew_samekh" : 0x5E1, + "hebrew_shin" : 0x5E9, + "hebrew_taf" : 0x5EA, + "hebrew_taw" : 0x5EA, + "hebrew_tet" : 0x5D8, + "hebrew_teth" : 0x5D8, + "hebrew_waw" : 0x5D5, + "hebrew_yod" : 0x5D9, + "hebrew_zade" : 0x5E6, + "hebrew_zadi" : 0x5E6, + "hebrew_zain" : 0x5D6, + "hebrew_zayin" : 0x5D6, + "horizconnector" : 0x2500, + "horizlinescan1" : 0x23BA, + "horizlinescan3" : 0x23BB, + "horizlinescan5" : 0x2500, + "horizlinescan7" : 0x23BC, + "horizlinescan9" : 0x23BD, + "hstroke" : 0x127, + "ht" : 0x2409, + "hyphen" : 0xAD, + "i" : 0x69, + "iacute" : 0xED, + "ibelowdot" : 0x1ECB, + "ibreve" : 0x12D, + "icircumflex" : 0xEE, + "identical" : 0x2261, + "idiaeresis" : 0xEF, + "idotless" : 0x131, + "ifonlyif" : 0x21D4, + "igrave" : 0xEC, + "ihook" : 0x1EC9, + "imacron" : 0x12B, + "implies" : 0x21D2, + "includedin" : 0x2282, + "includes" : 0x2283, + "infinity" : 0x221E, + "integral" : 0x222B, + "intersection" : 0x2229, + "iogonek" : 0x12F, + "itilde" : 0x129, + "j" : 0x6A, + "jcircumflex" : 0x135, + "jot" : 0x2218, + "k" : 0x6B, + "kana_A" : 0x30A2, + "kana_CHI" : 0x30C1, + "kana_E" : 0x30A8, + "kana_FU" : 0x30D5, + "kana_HA" : 0x30CF, + "kana_HE" : 0x30D8, + "kana_HI" : 0x30D2, + "kana_HO" : 0x30DB, + "kana_I" : 0x30A4, + "kana_KA" : 0x30AB, + "kana_KE" : 0x30B1, + "kana_KI" : 0x30AD, + "kana_KO" : 0x30B3, + "kana_KU" : 0x30AF, + "kana_MA" : 0x30DE, + "kana_ME" : 0x30E1, + "kana_MI" : 0x30DF, + "kana_MO" : 0x30E2, + "kana_MU" : 0x30E0, + "kana_N" : 0x30F3, + "kana_NA" : 0x30CA, + "kana_NE" : 0x30CD, + "kana_NI" : 0x30CB, + "kana_NO" : 0x30CE, + "kana_NU" : 0x30CC, + "kana_O" : 0x30AA, + "kana_RA" : 0x30E9, + "kana_RE" : 0x30EC, + "kana_RI" : 0x30EA, + "kana_RO" : 0x30ED, + "kana_RU" : 0x30EB, + "kana_SA" : 0x30B5, + "kana_SE" : 0x30BB, + "kana_SHI" : 0x30B7, + "kana_SO" : 0x30BD, + "kana_SU" : 0x30B9, + "kana_TA" : 0x30BF, + "kana_TE" : 0x30C6, + "kana_TO" : 0x30C8, + "kana_TSU" : 0x30C4, + "kana_U" : 0x30A6, + "kana_WA" : 0x30EF, + "kana_WO" : 0x30F2, + "kana_YA" : 0x30E4, + "kana_YO" : 0x30E8, + "kana_YU" : 0x30E6, + "kana_a" : 0x30A1, + "kana_closingbracket" : 0x300D, + "kana_comma" : 0x3001, + "kana_conjunctive" : 0x30FB, + "kana_e" : 0x30A7, + "kana_fullstop" : 0x3002, + "kana_i" : 0x30A3, + "kana_o" : 0x30A9, + "kana_openingbracket" : 0x300C, + "kana_tsu" : 0x30C3, + "kana_u" : 0x30A5, + "kana_ya" : 0x30E3, + "kana_yo" : 0x30E7, + "kana_yu" : 0x30E5, + "kcedilla" : 0x137, + "kra" : 0x138, + "l" : 0x6C, + "lacute" : 0x13A, + "latincross" : 0x271D, + "lbelowdot" : 0x1E37, + "lcaron" : 0x13E, + "lcedilla" : 0x13C, + "leftanglebracket" : 0x27E8, + "leftarrow" : 0x2190, + "leftcaret" : 0x3C, + "leftdoublequotemark" : 0x201C, + "leftmiddlecurlybrace" : 0x23A8, + "leftopentriangle" : 0x25C1, + "leftpointer" : 0x261C, + "leftradical" : 0x23B7, + "leftshoe" : 0x2282, + "leftsinglequotemark" : 0x2018, + "leftt" : 0x251C, + "lefttack" : 0x22A2, + "less" : 0x3C, + "lessthanequal" : 0x2264, + "lf" : 0x240A, + "logicaland" : 0x2227, + "logicalor" : 0x2228, + "lowleftcorner" : 0x2514, + "lowrightcorner" : 0x2518, + "lstroke" : 0x142, + "m" : 0x6D, + "mabovedot" : 0x1E41, + "macron" : 0xAF, + "malesymbol" : 0x2642, + "maltesecross" : 0x2720, + "masculine" : 0xBA, + "minus" : 0x2D, + "minutes" : 0x2032, + "mu" : 0xB5, + "multiply" : 0xD7, + "musicalflat" : 0x266D, + "musicalsharp" : 0x266F, + "n" : 0x6E, + "nabla" : 0x2207, + "nacute" : 0x144, + "ncaron" : 0x148, + "ncedilla" : 0x146, + "nl" : 0x2424, + "nobreakspace" : 0xA0, + "notequal" : 0x2260, + "notsign" : 0xAC, + "ntilde" : 0xF1, + "numbersign" : 0x23, + "numerosign" : 0x2116, + "o" : 0x6F, + "oacute" : 0xF3, + "obarred" : 0x275, + "obelowdot" : 0x1ECD, + "ocaron" : 0x1D2, + "ocircumflex" : 0xF4, + "ocircumflexacute" : 0x1ED1, + "ocircumflexbelowdot" : 0x1ED9, + "ocircumflexgrave" : 0x1ED3, + "ocircumflexhook" : 0x1ED5, + "ocircumflextilde" : 0x1ED7, + "odiaeresis" : 0xF6, + "odoubleacute" : 0x151, + "oe" : 0x153, + "ogonek" : 0x2DB, + "ograve" : 0xF2, + "ohook" : 0x1ECF, + "ohorn" : 0x1A1, + "ohornacute" : 0x1EDB, + "ohornbelowdot" : 0x1EE3, + "ohorngrave" : 0x1EDD, + "ohornhook" : 0x1EDF, + "ohorntilde" : 0x1EE1, + "omacron" : 0x14D, + "oneeighth" : 0x215B, + "onefifth" : 0x2155, + "onehalf" : 0xBD, + "onequarter" : 0xBC, + "onesixth" : 0x2159, + "onesuperior" : 0xB9, + "onethird" : 0x2153, + "openrectbullet" : 0x25AD, + "openstar" : 0x2606, + "opentribulletdown" : 0x25BD, + "opentribulletup" : 0x25B3, + "ordfeminine" : 0xAA, + "oslash" : 0xF8, + "otilde" : 0xF5, + "overbar" : 0xAF, + "overline" : 0x203E, + "p" : 0x70, + "pabovedot" : 0x1E57, + "paragraph" : 0xB6, + "parenleft" : 0x28, + "parenright" : 0x29, + "partialderivative" : 0x2202, + "percent" : 0x25, + "period" : 0x2E, + "periodcentered" : 0xB7, + "phonographcopyright" : 0x2117, + "plus" : 0x2B, + "plusminus" : 0xB1, + "prescription" : 0x211E, + "prolongedsound" : 0x30FC, + "punctspace" : 0x2008, + "q" : 0x71, + "quad" : 0x2395, + "question" : 0x3F, + "questiondown" : 0xBF, + "quotedbl" : 0x22, + "quoteleft" : 0x60, + "quoteright" : 0x27, + "r" : 0x72, + "racute" : 0x155, + "radical" : 0x221A, + "rcaron" : 0x159, + "rcedilla" : 0x157, + "registered" : 0xAE, + "rightanglebracket" : 0x27E9, + "rightarrow" : 0x2192, + "rightcaret" : 0x3E, + "rightdoublequotemark" : 0x201D, + "rightmiddlecurlybrace" : 0x23AC, + "rightopentriangle" : 0x25B7, + "rightpointer" : 0x261E, + "rightshoe" : 0x2283, + "rightsinglequotemark" : 0x2019, + "rightt" : 0x2524, + "righttack" : 0x22A3, + "s" : 0x73, + "sabovedot" : 0x1E61, + "sacute" : 0x15B, + "scaron" : 0x161, + "scedilla" : 0x15F, + "schwa" : 0x259, + "scircumflex" : 0x15D, + "seconds" : 0x2033, + "section" : 0xA7, + "semicolon" : 0x3B, + "semivoicedsound" : 0x309C, + "seveneighths" : 0x215E, + "signaturemark" : 0x2613, + "signifblank" : 0x2423, + "similarequal" : 0x2243, + "singlelowquotemark" : 0x201A, + "slash" : 0x2F, + "soliddiamond" : 0x25C6, + "space" : 0x20, + "ssharp" : 0xDF, + "sterling" : 0xA3, + "t" : 0x74, + "tabovedot" : 0x1E6B, + "tcaron" : 0x165, + "tcedilla" : 0x163, + "telephone" : 0x260E, + "telephonerecorder" : 0x2315, + "therefore" : 0x2234, + "thinspace" : 0x2009, + "thorn" : 0xFE, + "threeeighths" : 0x215C, + "threefifths" : 0x2157, + "threequarters" : 0xBE, + "threesuperior" : 0xB3, + "topintegral" : 0x2320, + "topleftparens" : 0x239B, + "topleftradical" : 0x250C, + "topleftsqbracket" : 0x23A1, + "toprightparens" : 0x239E, + "toprightsqbracket" : 0x23A4, + "topt" : 0x252C, + "trademark" : 0x2122, + "tslash" : 0x167, + "twofifths" : 0x2156, + "twosuperior" : 0xB2, + "twothirds" : 0x2154, + "u" : 0x75, + "uacute" : 0xFA, + "ubelowdot" : 0x1EE5, + "ubreve" : 0x16D, + "ucircumflex" : 0xFB, + "udiaeresis" : 0xFC, + "udoubleacute" : 0x171, + "ugrave" : 0xF9, + "uhook" : 0x1EE7, + "uhorn" : 0x1B0, + "uhornacute" : 0x1EE9, + "uhornbelowdot" : 0x1EF1, + "uhorngrave" : 0x1EEB, + "uhornhook" : 0x1EED, + "uhorntilde" : 0x1EEF, + "umacron" : 0x16B, + "underbar" : 0x5F, + "underscore" : 0x5F, + "union" : 0x222A, + "uogonek" : 0x173, + "uparrow" : 0x2191, + "upcaret" : 0x2227, + "upleftcorner" : 0x250C, + "uprightcorner" : 0x2510, + "upshoe" : 0x2229, + "upstile" : 0x2308, + "uptack" : 0x22A4, + "uring" : 0x16F, + "utilde" : 0x169, + "v" : 0x76, + "variation" : 0x221D, + "vertbar" : 0x2502, + "vertconnector" : 0x2502, + "voicedsound" : 0x309B, + "vt" : 0x240B, + "w" : 0x77, + "wacute" : 0x1E83, + "wcircumflex" : 0x175, + "wdiaeresis" : 0x1E85, + "wgrave" : 0x1E81, + "x" : 0x78, + "xabovedot" : 0x1E8B, + "y" : 0x79, + "yacute" : 0xFD, + "ybelowdot" : 0x1EF5, + "ycircumflex" : 0x177, + "ydiaeresis" : 0xFF, + "yen" : 0xA5, + "ygrave" : 0x1EF3, + "yhook" : 0x1EF7, + "ytilde" : 0x1EF9, + "z" : 0x7A, + "zabovedot" : 0x17C, + "zacute" : 0x17A, + "zcaron" : 0x17E, + "zstroke" : 0x1B6, +} + +if __name__ == "__main__": + pass diff --git a/KeyboardLayoutEditor/src/KeysymsUniByValue.py b/KeyboardLayoutEditor/src/KeysymsUniByValue.py @@ -0,0 +1,1323 @@ +#!/usr/bin/env python +# -*- encoding: UTF-8 -*- +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/> + +KeysymsUniByValue = { + 0x8 : "BackSpace", + 0x9 : "KP_Tab", + 0xA : "Linefeed", + 0xB : "Clear", + 0xD : "KP_Enter", + 0x13 : "Pause", + 0x14 : "Scroll_Lock", + 0x15 : "Sys_Req", + 0x1B : "Escape", + 0x20 : "KP_Space", + 0x21 : "exclam", + 0x22 : "quotedbl", + 0x23 : "numbersign", + 0x24 : "dollar", + 0x25 : "percent", + 0x26 : "ampersand", + 0x27 : "quoteright", + 0x28 : "Armenian_parenleft", + 0x29 : "Armenian_parenright", + 0x2A : "KP_Multiply", + 0x2B : "KP_Add", + 0x2C : "Armenian_comma", + 0x2D : "KP_Subtract", + 0x2E : "Armenian_mijaket", + 0x2F : "KP_Divide", + 0x30 : "KP_0", + 0x31 : "KP_1", + 0x32 : "KP_2", + 0x33 : "KP_3", + 0x34 : "KP_4", + 0x35 : "KP_5", + 0x36 : "KP_6", + 0x37 : "KP_7", + 0x38 : "KP_8", + 0x39 : "KP_9", + 0x3A : "colon", + 0x3B : "semicolon", + 0x3C : "leftcaret", + 0x3D : "KP_Equal", + 0x3E : "rightcaret", + 0x3F : "question", + 0x40 : "at", + 0x41 : "A", + 0x42 : "B", + 0x43 : "C", + 0x44 : "D", + 0x45 : "E", + 0x46 : "F", + 0x47 : "G", + 0x48 : "H", + 0x49 : "I", + 0x4A : "J", + 0x4B : "K", + 0x4C : "L", + 0x4D : "M", + 0x4E : "N", + 0x4F : "O", + 0x50 : "P", + 0x51 : "Q", + 0x52 : "R", + 0x53 : "S", + 0x54 : "T", + 0x55 : "U", + 0x56 : "V", + 0x57 : "W", + 0x58 : "X", + 0x59 : "Y", + 0x5A : "Z", + 0x5B : "bracketleft", + 0x5C : "backslash", + 0x5D : "bracketright", + 0x5E : "asciicircum", + 0x5F : "underbar", + 0x60 : "quoteleft", + 0x61 : "a", + 0x62 : "b", + 0x63 : "c", + 0x64 : "d", + 0x65 : "e", + 0x66 : "f", + 0x67 : "g", + 0x68 : "h", + 0x69 : "i", + 0x6A : "j", + 0x6B : "k", + 0x6C : "l", + 0x6D : "m", + 0x6E : "n", + 0x6F : "o", + 0x70 : "p", + 0x71 : "q", + 0x72 : "r", + 0x73 : "s", + 0x74 : "t", + 0x75 : "u", + 0x76 : "v", + 0x77 : "w", + 0x78 : "x", + 0x79 : "y", + 0x7A : "z", + 0x7B : "braceleft", + 0x7C : "bar", + 0x7D : "braceright", + 0x7E : "asciitilde", + 0xA0 : "nobreakspace", + 0xA1 : "exclamdown", + 0xA2 : "cent", + 0xA3 : "sterling", + 0xA4 : "currency", + 0xA5 : "yen", + 0xA6 : "brokenbar", + 0xA7 : "Armenian_section_sign", + 0xA8 : "diaeresis", + 0xA9 : "copyright", + 0xAA : "ordfeminine", + 0xAB : "Armenian_guillemotleft", + 0xAC : "notsign", + 0xAD : "hyphen", + 0xAE : "registered", + 0xAF : "overbar", + 0xB0 : "degree", + 0xB1 : "plusminus", + 0xB2 : "twosuperior", + 0xB3 : "threesuperior", + 0xB4 : "acute", + 0xB5 : "mu", + 0xB6 : "paragraph", + 0xB7 : "periodcentered", + 0xB8 : "cedilla", + 0xB9 : "onesuperior", + 0xBA : "masculine", + 0xBB : "Armenian_guillemotright", + 0xBC : "onequarter", + 0xBD : "onehalf", + 0xBE : "threequarters", + 0xBF : "questiondown", + 0xC0 : "Agrave", + 0xC1 : "Aacute", + 0xC2 : "Acircumflex", + 0xC3 : "Atilde", + 0xC4 : "Adiaeresis", + 0xC5 : "Aring", + 0xC6 : "AE", + 0xC7 : "Ccedilla", + 0xC8 : "Egrave", + 0xC9 : "Eacute", + 0xCA : "Ecircumflex", + 0xCB : "Ediaeresis", + 0xCC : "Igrave", + 0xCD : "Iacute", + 0xCE : "Icircumflex", + 0xCF : "Idiaeresis", + 0xD0 : "Eth", + 0xD1 : "Ntilde", + 0xD2 : "Ograve", + 0xD3 : "Oacute", + 0xD4 : "Ocircumflex", + 0xD5 : "Otilde", + 0xD6 : "Odiaeresis", + 0xD7 : "multiply", + 0xD8 : "Ooblique", + 0xD9 : "Ugrave", + 0xDA : "Uacute", + 0xDB : "Ucircumflex", + 0xDC : "Udiaeresis", + 0xDD : "Yacute", + 0xDE : "Thorn", + 0xDF : "ssharp", + 0xE0 : "agrave", + 0xE1 : "aacute", + 0xE2 : "acircumflex", + 0xE3 : "atilde", + 0xE4 : "adiaeresis", + 0xE5 : "aring", + 0xE6 : "ae", + 0xE7 : "ccedilla", + 0xE8 : "egrave", + 0xE9 : "eacute", + 0xEA : "ecircumflex", + 0xEB : "ediaeresis", + 0xEC : "igrave", + 0xED : "iacute", + 0xEE : "icircumflex", + 0xEF : "idiaeresis", + 0xF0 : "eth", + 0xF1 : "ntilde", + 0xF2 : "ograve", + 0xF3 : "oacute", + 0xF4 : "ocircumflex", + 0xF5 : "otilde", + 0xF6 : "odiaeresis", + 0xF7 : "division", + 0xF8 : "oslash", + 0xF9 : "ugrave", + 0xFA : "uacute", + 0xFB : "ucircumflex", + 0xFC : "udiaeresis", + 0xFD : "yacute", + 0xFE : "thorn", + 0xFF : "ydiaeresis", + 0x100 : "Amacron", + 0x101 : "amacron", + 0x102 : "Abreve", + 0x103 : "abreve", + 0x104 : "Aogonek", + 0x105 : "aogonek", + 0x106 : "Cacute", + 0x107 : "cacute", + 0x108 : "Ccircumflex", + 0x109 : "ccircumflex", + 0x10A : "Cabovedot", + 0x10B : "cabovedot", + 0x10C : "Ccaron", + 0x10D : "ccaron", + 0x10E : "Dcaron", + 0x10F : "dcaron", + 0x110 : "Dstroke", + 0x111 : "dstroke", + 0x112 : "Emacron", + 0x113 : "emacron", + 0x116 : "Eabovedot", + 0x117 : "eabovedot", + 0x118 : "Eogonek", + 0x119 : "eogonek", + 0x11A : "Ecaron", + 0x11B : "ecaron", + 0x11C : "Gcircumflex", + 0x11D : "gcircumflex", + 0x11E : "Gbreve", + 0x11F : "gbreve", + 0x120 : "Gabovedot", + 0x121 : "gabovedot", + 0x122 : "Gcedilla", + 0x123 : "gcedilla", + 0x124 : "Hcircumflex", + 0x125 : "hcircumflex", + 0x126 : "Hstroke", + 0x127 : "hstroke", + 0x128 : "Itilde", + 0x129 : "itilde", + 0x12A : "Imacron", + 0x12B : "imacron", + 0x12C : "Ibreve", + 0x12D : "ibreve", + 0x12E : "Iogonek", + 0x12F : "iogonek", + 0x130 : "Iabovedot", + 0x131 : "idotless", + 0x134 : "Jcircumflex", + 0x135 : "jcircumflex", + 0x136 : "Kcedilla", + 0x137 : "kcedilla", + 0x138 : "kra", + 0x139 : "Lacute", + 0x13A : "lacute", + 0x13B : "Lcedilla", + 0x13C : "lcedilla", + 0x13D : "Lcaron", + 0x13E : "lcaron", + 0x141 : "Lstroke", + 0x142 : "lstroke", + 0x143 : "Nacute", + 0x144 : "nacute", + 0x145 : "Ncedilla", + 0x146 : "ncedilla", + 0x147 : "Ncaron", + 0x148 : "ncaron", + 0x14A : "ENG", + 0x14B : "eng", + 0x14C : "Omacron", + 0x14D : "omacron", + 0x150 : "Odoubleacute", + 0x151 : "odoubleacute", + 0x152 : "OE", + 0x153 : "oe", + 0x154 : "Racute", + 0x155 : "racute", + 0x156 : "Rcedilla", + 0x157 : "rcedilla", + 0x158 : "Rcaron", + 0x159 : "rcaron", + 0x15A : "Sacute", + 0x15B : "sacute", + 0x15C : "Scircumflex", + 0x15D : "scircumflex", + 0x15E : "Scedilla", + 0x15F : "scedilla", + 0x160 : "Scaron", + 0x161 : "scaron", + 0x162 : "Tcedilla", + 0x163 : "tcedilla", + 0x164 : "Tcaron", + 0x165 : "tcaron", + 0x166 : "Tslash", + 0x167 : "tslash", + 0x168 : "Utilde", + 0x169 : "utilde", + 0x16A : "Umacron", + 0x16B : "umacron", + 0x16C : "Ubreve", + 0x16D : "ubreve", + 0x16E : "Uring", + 0x16F : "uring", + 0x170 : "Udoubleacute", + 0x171 : "udoubleacute", + 0x172 : "Uogonek", + 0x173 : "uogonek", + 0x174 : "Wcircumflex", + 0x175 : "wcircumflex", + 0x176 : "Ycircumflex", + 0x177 : "ycircumflex", + 0x178 : "Ydiaeresis", + 0x179 : "Zacute", + 0x17A : "zacute", + 0x17B : "Zabovedot", + 0x17C : "zabovedot", + 0x17D : "Zcaron", + 0x17E : "zcaron", + 0x18F : "SCHWA", + 0x192 : "function", + 0x19F : "Obarred", + 0x1A0 : "Ohorn", + 0x1A1 : "ohorn", + 0x1AF : "Uhorn", + 0x1B0 : "uhorn", + 0x1B5 : "Zstroke", + 0x1B6 : "zstroke", + 0x1D2 : "ocaron", + 0x1E6 : "Gcaron", + 0x1E7 : "gcaron", + 0x259 : "schwa", + 0x275 : "obarred", + 0x2C7 : "caron", + 0x2D8 : "breve", + 0x2D9 : "abovedot", + 0x2DB : "ogonek", + 0x2DD : "doubleacute", + 0x300 : "combining_grave", + 0x301 : "combining_acute", + 0x302 : "dead_circumflex", + 0x303 : "combining_tilde", + 0x304 : "dead_macron", + 0x306 : "dead_breve", + 0x307 : "dead_abovedot", + 0x308 : "dead_diaeresis", + 0x309 : "dead_hook", + 0x30A : "dead_abovering", + 0x30B : "dead_doubleacute", + 0x30C : "dead_caron", + 0x31B : "dead_horn", + 0x323 : "dead_belowdot", + 0x327 : "dead_cedilla", + 0x328 : "dead_ogonek", + 0x345 : "dead_iota", + 0x385 : "Greek_accentdieresis", + 0x386 : "Greek_ALPHAaccent", + 0x388 : "Greek_EPSILONaccent", + 0x389 : "Greek_ETAaccent", + 0x38A : "Greek_IOTAaccent", + 0x38C : "Greek_OMICRONaccent", + 0x38E : "Greek_UPSILONaccent", + 0x38F : "Greek_OMEGAaccent", + 0x390 : "Greek_iotaaccentdieresis", + 0x391 : "Greek_ALPHA", + 0x392 : "Greek_BETA", + 0x393 : "Greek_GAMMA", + 0x394 : "Greek_DELTA", + 0x395 : "Greek_EPSILON", + 0x396 : "Greek_ZETA", + 0x397 : "Greek_ETA", + 0x398 : "Greek_THETA", + 0x399 : "Greek_IOTA", + 0x39A : "Greek_KAPPA", + 0x39B : "Greek_LAMDA", + 0x39C : "Greek_MU", + 0x39D : "Greek_NU", + 0x39E : "Greek_XI", + 0x39F : "Greek_OMICRON", + 0x3A0 : "Greek_PI", + 0x3A1 : "Greek_RHO", + 0x3A3 : "Greek_SIGMA", + 0x3A4 : "Greek_TAU", + 0x3A5 : "Greek_UPSILON", + 0x3A6 : "Greek_PHI", + 0x3A7 : "Greek_CHI", + 0x3A8 : "Greek_PSI", + 0x3A9 : "Greek_OMEGA", + 0x3AA : "Greek_IOTAdiaeresis", + 0x3AB : "Greek_UPSILONdieresis", + 0x3AC : "Greek_alphaaccent", + 0x3AD : "Greek_epsilonaccent", + 0x3AE : "Greek_etaaccent", + 0x3AF : "Greek_iotaaccent", + 0x3B0 : "Greek_upsilonaccentdieresis", + 0x3B1 : "Greek_alpha", + 0x3B2 : "Greek_beta", + 0x3B3 : "Greek_gamma", + 0x3B4 : "Greek_delta", + 0x3B5 : "Greek_epsilon", + 0x3B6 : "Greek_zeta", + 0x3B7 : "Greek_eta", + 0x3B8 : "Greek_theta", + 0x3B9 : "Greek_iota", + 0x3BA : "Greek_kappa", + 0x3BB : "Greek_lambda", + 0x3BC : "Greek_mu", + 0x3BD : "Greek_nu", + 0x3BE : "Greek_xi", + 0x3BF : "Greek_omicron", + 0x3C0 : "Greek_pi", + 0x3C1 : "Greek_rho", + 0x3C2 : "Greek_finalsmallsigma", + 0x3C3 : "Greek_sigma", + 0x3C4 : "Greek_tau", + 0x3C5 : "Greek_upsilon", + 0x3C6 : "Greek_phi", + 0x3C7 : "Greek_chi", + 0x3C8 : "Greek_psi", + 0x3C9 : "Greek_omega", + 0x3CA : "Greek_iotadieresis", + 0x3CB : "Greek_upsilondieresis", + 0x3CC : "Greek_omicronaccent", + 0x3CD : "Greek_upsilonaccent", + 0x3CE : "Greek_omegaaccent", + 0x401 : "Cyrillic_IO", + 0x402 : "Serbian_DJE", + 0x403 : "Macedonia_GJE", + 0x404 : "Ukrainian_IE", + 0x405 : "Macedonia_DSE", + 0x406 : "Ukrainian_I", + 0x407 : "Ukrainian_YI", + 0x408 : "Cyrillic_JE", + 0x409 : "Cyrillic_LJE", + 0x40A : "Cyrillic_NJE", + 0x40B : "Serbian_TSHE", + 0x40C : "Macedonia_KJE", + 0x40E : "Byelorussian_SHORTU", + 0x40F : "Cyrillic_DZHE", + 0x410 : "Cyrillic_A", + 0x411 : "Cyrillic_BE", + 0x412 : "Cyrillic_VE", + 0x413 : "Cyrillic_GHE", + 0x414 : "Cyrillic_DE", + 0x415 : "Cyrillic_IE", + 0x416 : "Cyrillic_ZHE", + 0x417 : "Cyrillic_ZE", + 0x418 : "Cyrillic_I", + 0x419 : "Cyrillic_SHORTI", + 0x41A : "Cyrillic_KA", + 0x41B : "Cyrillic_EL", + 0x41C : "Cyrillic_EM", + 0x41D : "Cyrillic_EN", + 0x41E : "Cyrillic_O", + 0x41F : "Cyrillic_PE", + 0x420 : "Cyrillic_ER", + 0x421 : "Cyrillic_ES", + 0x422 : "Cyrillic_TE", + 0x423 : "Cyrillic_U", + 0x424 : "Cyrillic_EF", + 0x425 : "Cyrillic_HA", + 0x426 : "Cyrillic_TSE", + 0x427 : "Cyrillic_CHE", + 0x428 : "Cyrillic_SHA", + 0x429 : "Cyrillic_SHCHA", + 0x42A : "Cyrillic_HARDSIGN", + 0x42B : "Cyrillic_YERU", + 0x42C : "Cyrillic_SOFTSIGN", + 0x42D : "Cyrillic_E", + 0x42E : "Cyrillic_YU", + 0x42F : "Cyrillic_YA", + 0x430 : "Cyrillic_a", + 0x431 : "Cyrillic_be", + 0x432 : "Cyrillic_ve", + 0x433 : "Cyrillic_ghe", + 0x434 : "Cyrillic_de", + 0x435 : "Cyrillic_ie", + 0x436 : "Cyrillic_zhe", + 0x437 : "Cyrillic_ze", + 0x438 : "Cyrillic_i", + 0x439 : "Cyrillic_shorti", + 0x43A : "Cyrillic_ka", + 0x43B : "Cyrillic_el", + 0x43C : "Cyrillic_em", + 0x43D : "Cyrillic_en", + 0x43E : "Cyrillic_o", + 0x43F : "Cyrillic_pe", + 0x440 : "Cyrillic_er", + 0x441 : "Cyrillic_es", + 0x442 : "Cyrillic_te", + 0x443 : "Cyrillic_u", + 0x444 : "Cyrillic_ef", + 0x445 : "Cyrillic_ha", + 0x446 : "Cyrillic_tse", + 0x447 : "Cyrillic_che", + 0x448 : "Cyrillic_sha", + 0x449 : "Cyrillic_shcha", + 0x44A : "Cyrillic_hardsign", + 0x44B : "Cyrillic_yeru", + 0x44C : "Cyrillic_softsign", + 0x44D : "Cyrillic_e", + 0x44E : "Cyrillic_yu", + 0x44F : "Cyrillic_ya", + 0x451 : "Cyrillic_io", + 0x452 : "Serbian_dje", + 0x453 : "Macedonia_gje", + 0x454 : "Ukrainian_ie", + 0x455 : "Macedonia_dse", + 0x456 : "Ukrainian_i", + 0x457 : "Ukrainian_yi", + 0x458 : "Cyrillic_je", + 0x459 : "Cyrillic_lje", + 0x45A : "Cyrillic_nje", + 0x45B : "Serbian_tshe", + 0x45C : "Macedonia_kje", + 0x45E : "Byelorussian_shortu", + 0x45F : "Cyrillic_dzhe", + 0x490 : "Ukrainian_GHE_WITH_UPTURN", + 0x491 : "Ukrainian_ghe_with_upturn", + 0x492 : "Cyrillic_GHE_bar", + 0x493 : "Cyrillic_ghe_bar", + 0x496 : "Cyrillic_ZHE_descender", + 0x497 : "Cyrillic_zhe_descender", + 0x49A : "Cyrillic_KA_descender", + 0x49B : "Cyrillic_ka_descender", + 0x49C : "Cyrillic_KA_vertstroke", + 0x49D : "Cyrillic_ka_vertstroke", + 0x4A2 : "Cyrillic_EN_descender", + 0x4A3 : "Cyrillic_en_descender", + 0x4AE : "Cyrillic_U_straight", + 0x4AF : "Cyrillic_u_straight", + 0x4B0 : "Cyrillic_U_straight_bar", + 0x4B1 : "Cyrillic_u_straight_bar", + 0x4B2 : "Cyrillic_HA_descender", + 0x4B3 : "Cyrillic_ha_descender", + 0x4B6 : "Cyrillic_CHE_descender", + 0x4B7 : "Cyrillic_che_descender", + 0x4B8 : "Cyrillic_CHE_vertstroke", + 0x4B9 : "Cyrillic_che_vertstroke", + 0x4BA : "Cyrillic_SHHA", + 0x4BB : "Cyrillic_shha", + 0x4D8 : "Cyrillic_SCHWA", + 0x4D9 : "Cyrillic_schwa", + 0x4E2 : "Cyrillic_I_macron", + 0x4E3 : "Cyrillic_i_macron", + 0x4E8 : "Cyrillic_O_bar", + 0x4E9 : "Cyrillic_o_bar", + 0x4EE : "Cyrillic_U_macron", + 0x4EF : "Cyrillic_u_macron", + 0x531 : "Armenian_AYB", + 0x532 : "Armenian_BEN", + 0x533 : "Armenian_GIM", + 0x534 : "Armenian_DA", + 0x535 : "Armenian_YECH", + 0x536 : "Armenian_ZA", + 0x537 : "Armenian_E", + 0x538 : "Armenian_AT", + 0x539 : "Armenian_TO", + 0x53A : "Armenian_ZHE", + 0x53B : "Armenian_INI", + 0x53C : "Armenian_LYUN", + 0x53D : "Armenian_KHE", + 0x53E : "Armenian_TSA", + 0x53F : "Armenian_KEN", + 0x540 : "Armenian_HO", + 0x541 : "Armenian_DZA", + 0x542 : "Armenian_GHAT", + 0x543 : "Armenian_TCHE", + 0x544 : "Armenian_MEN", + 0x545 : "Armenian_HI", + 0x546 : "Armenian_NU", + 0x547 : "Armenian_SHA", + 0x548 : "Armenian_VO", + 0x549 : "Armenian_CHA", + 0x54A : "Armenian_PE", + 0x54B : "Armenian_JE", + 0x54C : "Armenian_RA", + 0x54D : "Armenian_SE", + 0x54E : "Armenian_VEV", + 0x54F : "Armenian_TYUN", + 0x550 : "Armenian_RE", + 0x551 : "Armenian_TSO", + 0x552 : "Armenian_VYUN", + 0x553 : "Armenian_PYUR", + 0x554 : "Armenian_KE", + 0x555 : "Armenian_O", + 0x556 : "Armenian_FE", + 0x55A : "Armenian_apostrophe", + 0x55B : "Armenian_shesht", + 0x55C : "Armenian_amanak", + 0x55D : "Armenian_but", + 0x55E : "Armenian_paruyk", + 0x561 : "Armenian_ayb", + 0x562 : "Armenian_ben", + 0x563 : "Armenian_gim", + 0x564 : "Armenian_da", + 0x565 : "Armenian_yech", + 0x566 : "Armenian_za", + 0x567 : "Armenian_e", + 0x568 : "Armenian_at", + 0x569 : "Armenian_to", + 0x56A : "Armenian_zhe", + 0x56B : "Armenian_ini", + 0x56C : "Armenian_lyun", + 0x56D : "Armenian_khe", + 0x56E : "Armenian_tsa", + 0x56F : "Armenian_ken", + 0x570 : "Armenian_ho", + 0x571 : "Armenian_dza", + 0x572 : "Armenian_ghat", + 0x573 : "Armenian_tche", + 0x574 : "Armenian_men", + 0x575 : "Armenian_hi", + 0x576 : "Armenian_nu", + 0x577 : "Armenian_sha", + 0x578 : "Armenian_vo", + 0x579 : "Armenian_cha", + 0x57A : "Armenian_pe", + 0x57B : "Armenian_je", + 0x57C : "Armenian_ra", + 0x57D : "Armenian_se", + 0x57E : "Armenian_vev", + 0x57F : "Armenian_tyun", + 0x580 : "Armenian_re", + 0x581 : "Armenian_tso", + 0x582 : "Armenian_vyun", + 0x583 : "Armenian_pyur", + 0x584 : "Armenian_ke", + 0x585 : "Armenian_o", + 0x586 : "Armenian_fe", + 0x587 : "Armenian_ligature_ew", + 0x589 : "Armenian_verjaket", + 0x58A : "Armenian_yentamna", + 0x5D0 : "hebrew_aleph", + 0x5D1 : "hebrew_beth", + 0x5D2 : "hebrew_gimmel", + 0x5D3 : "hebrew_daleth", + 0x5D4 : "hebrew_he", + 0x5D5 : "hebrew_waw", + 0x5D6 : "hebrew_zayin", + 0x5D7 : "hebrew_het", + 0x5D8 : "hebrew_teth", + 0x5D9 : "hebrew_yod", + 0x5DA : "hebrew_finalkaph", + 0x5DB : "hebrew_kaph", + 0x5DC : "hebrew_lamed", + 0x5DD : "hebrew_finalmem", + 0x5DE : "hebrew_mem", + 0x5DF : "hebrew_finalnun", + 0x5E0 : "hebrew_nun", + 0x5E1 : "hebrew_samekh", + 0x5E2 : "hebrew_ayin", + 0x5E3 : "hebrew_finalpe", + 0x5E4 : "hebrew_pe", + 0x5E5 : "hebrew_finalzadi", + 0x5E6 : "hebrew_zadi", + 0x5E7 : "hebrew_qoph", + 0x5E8 : "hebrew_resh", + 0x5E9 : "hebrew_shin", + 0x5EA : "hebrew_taw", + 0x60C : "Arabic_comma", + 0x61B : "Arabic_semicolon", + 0x61F : "Arabic_question_mark", + 0x621 : "Arabic_hamza", + 0x622 : "Arabic_maddaonalef", + 0x623 : "Arabic_hamzaonalef", + 0x624 : "Arabic_hamzaonwaw", + 0x625 : "Arabic_hamzaunderalef", + 0x626 : "Arabic_hamzaonyeh", + 0x627 : "Arabic_alef", + 0x628 : "Arabic_beh", + 0x629 : "Arabic_tehmarbuta", + 0x62A : "Arabic_teh", + 0x62B : "Arabic_theh", + 0x62C : "Arabic_jeem", + 0x62D : "Arabic_hah", + 0x62E : "Arabic_khah", + 0x62F : "Arabic_dal", + 0x630 : "Arabic_thal", + 0x631 : "Arabic_ra", + 0x632 : "Arabic_zain", + 0x633 : "Arabic_seen", + 0x634 : "Arabic_sheen", + 0x635 : "Arabic_sad", + 0x636 : "Arabic_dad", + 0x637 : "Arabic_tah", + 0x638 : "Arabic_zah", + 0x639 : "Arabic_ain", + 0x63A : "Arabic_ghain", + 0x640 : "Arabic_tatweel", + 0x641 : "Arabic_feh", + 0x642 : "Arabic_qaf", + 0x643 : "Arabic_kaf", + 0x644 : "Arabic_lam", + 0x645 : "Arabic_meem", + 0x646 : "Arabic_noon", + 0x647 : "Arabic_ha", + 0x648 : "Arabic_waw", + 0x649 : "Arabic_alefmaksura", + 0x64A : "Arabic_yeh", + 0x64B : "Arabic_fathatan", + 0x64C : "Arabic_dammatan", + 0x64D : "Arabic_kasratan", + 0x64E : "Arabic_fatha", + 0x64F : "Arabic_damma", + 0x650 : "Arabic_kasra", + 0x651 : "Arabic_shadda", + 0x652 : "Arabic_sukun", + 0x653 : "Arabic_madda_above", + 0x654 : "Arabic_hamza_above", + 0x655 : "Arabic_hamza_below", + 0x660 : "Arabic_0", + 0x661 : "Arabic_1", + 0x662 : "Arabic_2", + 0x663 : "Arabic_3", + 0x664 : "Arabic_4", + 0x665 : "Arabic_5", + 0x666 : "Arabic_6", + 0x667 : "Arabic_7", + 0x668 : "Arabic_8", + 0x669 : "Arabic_9", + 0x66A : "Arabic_percent", + 0x670 : "Arabic_superscript_alef", + 0x679 : "Arabic_tteh", + 0x67E : "Arabic_peh", + 0x686 : "Arabic_tcheh", + 0x688 : "Arabic_ddal", + 0x691 : "Arabic_rreh", + 0x698 : "Arabic_jeh", + 0x6A4 : "Arabic_veh", + 0x6A9 : "Arabic_keheh", + 0x6AF : "Arabic_gaf", + 0x6BA : "Arabic_noon_ghunna", + 0x6BE : "Arabic_heh_doachashmee", + 0x6C1 : "Arabic_heh_goal", + 0x6CC : "Farsi_yeh", + 0x6D2 : "Arabic_yeh_baree", + 0x6D4 : "Arabic_fullstop", + 0x6F0 : "Farsi_0", + 0x6F1 : "Farsi_1", + 0x6F2 : "Farsi_2", + 0x6F3 : "Farsi_3", + 0x6F4 : "Farsi_4", + 0x6F5 : "Farsi_5", + 0x6F6 : "Farsi_6", + 0x6F7 : "Farsi_7", + 0x6F8 : "Farsi_8", + 0x6F9 : "Farsi_9", + 0xE01 : "Thai_kokai", + 0xE02 : "Thai_khokhai", + 0xE03 : "Thai_khokhuat", + 0xE04 : "Thai_khokhwai", + 0xE05 : "Thai_khokhon", + 0xE06 : "Thai_khorakhang", + 0xE07 : "Thai_ngongu", + 0xE08 : "Thai_chochan", + 0xE09 : "Thai_choching", + 0xE0A : "Thai_chochang", + 0xE0B : "Thai_soso", + 0xE0C : "Thai_chochoe", + 0xE0D : "Thai_yoying", + 0xE0E : "Thai_dochada", + 0xE0F : "Thai_topatak", + 0xE10 : "Thai_thothan", + 0xE11 : "Thai_thonangmontho", + 0xE12 : "Thai_thophuthao", + 0xE13 : "Thai_nonen", + 0xE14 : "Thai_dodek", + 0xE15 : "Thai_totao", + 0xE16 : "Thai_thothung", + 0xE17 : "Thai_thothahan", + 0xE18 : "Thai_thothong", + 0xE19 : "Thai_nonu", + 0xE1A : "Thai_bobaimai", + 0xE1B : "Thai_popla", + 0xE1C : "Thai_phophung", + 0xE1D : "Thai_fofa", + 0xE1E : "Thai_phophan", + 0xE1F : "Thai_fofan", + 0xE20 : "Thai_phosamphao", + 0xE21 : "Thai_moma", + 0xE22 : "Thai_yoyak", + 0xE23 : "Thai_rorua", + 0xE24 : "Thai_ru", + 0xE25 : "Thai_loling", + 0xE26 : "Thai_lu", + 0xE27 : "Thai_wowaen", + 0xE28 : "Thai_sosala", + 0xE29 : "Thai_sorusi", + 0xE2A : "Thai_sosua", + 0xE2B : "Thai_hohip", + 0xE2C : "Thai_lochula", + 0xE2D : "Thai_oang", + 0xE2E : "Thai_honokhuk", + 0xE2F : "Thai_paiyannoi", + 0xE30 : "Thai_saraa", + 0xE31 : "Thai_maihanakat", + 0xE32 : "Thai_saraaa", + 0xE33 : "Thai_saraam", + 0xE34 : "Thai_sarai", + 0xE35 : "Thai_saraii", + 0xE36 : "Thai_saraue", + 0xE37 : "Thai_sarauee", + 0xE38 : "Thai_sarau", + 0xE39 : "Thai_sarauu", + 0xE3A : "Thai_phinthu", + 0xE3F : "Thai_baht", + 0xE40 : "Thai_sarae", + 0xE41 : "Thai_saraae", + 0xE42 : "Thai_sarao", + 0xE43 : "Thai_saraaimaimuan", + 0xE44 : "Thai_saraaimaimalai", + 0xE45 : "Thai_lakkhangyao", + 0xE46 : "Thai_maiyamok", + 0xE47 : "Thai_maitaikhu", + 0xE48 : "Thai_maiek", + 0xE49 : "Thai_maitho", + 0xE4A : "Thai_maitri", + 0xE4B : "Thai_maichattawa", + 0xE4C : "Thai_thanthakhat", + 0xE4D : "Thai_nikhahit", + 0xE50 : "Thai_leksun", + 0xE51 : "Thai_leknung", + 0xE52 : "Thai_leksong", + 0xE53 : "Thai_leksam", + 0xE54 : "Thai_leksi", + 0xE55 : "Thai_lekha", + 0xE56 : "Thai_lekhok", + 0xE57 : "Thai_lekchet", + 0xE58 : "Thai_lekpaet", + 0xE59 : "Thai_lekkao", + 0x10D0 : "Georgian_an", + 0x10D1 : "Georgian_ban", + 0x10D2 : "Georgian_gan", + 0x10D3 : "Georgian_don", + 0x10D4 : "Georgian_en", + 0x10D5 : "Georgian_vin", + 0x10D6 : "Georgian_zen", + 0x10D7 : "Georgian_tan", + 0x10D8 : "Georgian_in", + 0x10D9 : "Georgian_kan", + 0x10DA : "Georgian_las", + 0x10DB : "Georgian_man", + 0x10DC : "Georgian_nar", + 0x10DD : "Georgian_on", + 0x10DE : "Georgian_par", + 0x10DF : "Georgian_zhar", + 0x10E0 : "Georgian_rae", + 0x10E1 : "Georgian_san", + 0x10E2 : "Georgian_tar", + 0x10E3 : "Georgian_un", + 0x10E4 : "Georgian_phar", + 0x10E5 : "Georgian_khar", + 0x10E6 : "Georgian_ghan", + 0x10E7 : "Georgian_qar", + 0x10E8 : "Georgian_shin", + 0x10E9 : "Georgian_chin", + 0x10EA : "Georgian_can", + 0x10EB : "Georgian_jil", + 0x10EC : "Georgian_cil", + 0x10ED : "Georgian_char", + 0x10EE : "Georgian_xan", + 0x10EF : "Georgian_jhan", + 0x10F0 : "Georgian_hae", + 0x10F1 : "Georgian_he", + 0x10F2 : "Georgian_hie", + 0x10F3 : "Georgian_we", + 0x10F4 : "Georgian_har", + 0x10F5 : "Georgian_hoe", + 0x10F6 : "Georgian_fi", + 0x11A8 : "Hangul_J_Kiyeog", + 0x11A9 : "Hangul_J_SsangKiyeog", + 0x11AA : "Hangul_J_KiyeogSios", + 0x11AB : "Hangul_J_Nieun", + 0x11AC : "Hangul_J_NieunJieuj", + 0x11AD : "Hangul_J_NieunHieuh", + 0x11AE : "Hangul_J_Dikeud", + 0x11AF : "Hangul_J_Rieul", + 0x11B0 : "Hangul_J_RieulKiyeog", + 0x11B1 : "Hangul_J_RieulMieum", + 0x11B2 : "Hangul_J_RieulPieub", + 0x11B3 : "Hangul_J_RieulSios", + 0x11B4 : "Hangul_J_RieulTieut", + 0x11B5 : "Hangul_J_RieulPhieuf", + 0x11B6 : "Hangul_J_RieulHieuh", + 0x11B7 : "Hangul_J_Mieum", + 0x11B8 : "Hangul_J_Pieub", + 0x11B9 : "Hangul_J_PieubSios", + 0x11BA : "Hangul_J_Sios", + 0x11BB : "Hangul_J_SsangSios", + 0x11BC : "Hangul_J_Ieung", + 0x11BD : "Hangul_J_Jieuj", + 0x11BE : "Hangul_J_Cieuc", + 0x11BF : "Hangul_J_Khieuq", + 0x11C0 : "Hangul_J_Tieut", + 0x11C1 : "Hangul_J_Phieuf", + 0x11C2 : "Hangul_J_Hieuh", + 0x11EB : "Hangul_J_PanSios", + 0x11F0 : "Hangul_J_KkogjiDalrinIeung", + 0x11F9 : "Hangul_J_YeorinHieuh", + 0x1E02 : "Babovedot", + 0x1E03 : "babovedot", + 0x1E0A : "Dabovedot", + 0x1E0B : "dabovedot", + 0x1E1E : "Fabovedot", + 0x1E1F : "fabovedot", + 0x1E36 : "Lbelowdot", + 0x1E37 : "lbelowdot", + 0x1E40 : "Mabovedot", + 0x1E41 : "mabovedot", + 0x1E56 : "Pabovedot", + 0x1E57 : "pabovedot", + 0x1E60 : "Sabovedot", + 0x1E61 : "sabovedot", + 0x1E6A : "Tabovedot", + 0x1E6B : "tabovedot", + 0x1E80 : "Wgrave", + 0x1E81 : "wgrave", + 0x1E82 : "Wacute", + 0x1E83 : "wacute", + 0x1E84 : "Wdiaeresis", + 0x1E85 : "wdiaeresis", + 0x1E8A : "Xabovedot", + 0x1E8B : "xabovedot", + 0x1EA0 : "Abelowdot", + 0x1EA1 : "abelowdot", + 0x1EA2 : "Ahook", + 0x1EA3 : "ahook", + 0x1EA4 : "Acircumflexacute", + 0x1EA5 : "acircumflexacute", + 0x1EA6 : "Acircumflexgrave", + 0x1EA7 : "acircumflexgrave", + 0x1EA8 : "Acircumflexhook", + 0x1EA9 : "acircumflexhook", + 0x1EAA : "Acircumflextilde", + 0x1EAB : "acircumflextilde", + 0x1EAC : "Acircumflexbelowdot", + 0x1EAD : "acircumflexbelowdot", + 0x1EAE : "Abreveacute", + 0x1EAF : "abreveacute", + 0x1EB0 : "Abrevegrave", + 0x1EB1 : "abrevegrave", + 0x1EB2 : "Abrevehook", + 0x1EB3 : "abrevehook", + 0x1EB4 : "Abrevetilde", + 0x1EB5 : "abrevetilde", + 0x1EB6 : "Abrevebelowdot", + 0x1EB7 : "abrevebelowdot", + 0x1EB8 : "Ebelowdot", + 0x1EB9 : "ebelowdot", + 0x1EBA : "Ehook", + 0x1EBB : "ehook", + 0x1EBC : "Etilde", + 0x1EBD : "etilde", + 0x1EBE : "Ecircumflexacute", + 0x1EBF : "ecircumflexacute", + 0x1EC0 : "Ecircumflexgrave", + 0x1EC1 : "ecircumflexgrave", + 0x1EC2 : "Ecircumflexhook", + 0x1EC3 : "ecircumflexhook", + 0x1EC4 : "Ecircumflextilde", + 0x1EC5 : "ecircumflextilde", + 0x1EC6 : "Ecircumflexbelowdot", + 0x1EC7 : "ecircumflexbelowdot", + 0x1EC8 : "Ihook", + 0x1EC9 : "ihook", + 0x1ECA : "Ibelowdot", + 0x1ECB : "ibelowdot", + 0x1ECC : "Obelowdot", + 0x1ECD : "obelowdot", + 0x1ECE : "Ohook", + 0x1ECF : "ohook", + 0x1ED0 : "Ocircumflexacute", + 0x1ED1 : "ocircumflexacute", + 0x1ED2 : "Ocircumflexgrave", + 0x1ED3 : "ocircumflexgrave", + 0x1ED4 : "Ocircumflexhook", + 0x1ED5 : "ocircumflexhook", + 0x1ED6 : "Ocircumflextilde", + 0x1ED7 : "ocircumflextilde", + 0x1ED8 : "Ocircumflexbelowdot", + 0x1ED9 : "ocircumflexbelowdot", + 0x1EDA : "Ohornacute", + 0x1EDB : "ohornacute", + 0x1EDC : "Ohorngrave", + 0x1EDD : "ohorngrave", + 0x1EDE : "Ohornhook", + 0x1EDF : "ohornhook", + 0x1EE0 : "Ohorntilde", + 0x1EE1 : "ohorntilde", + 0x1EE2 : "Ohornbelowdot", + 0x1EE3 : "ohornbelowdot", + 0x1EE4 : "Ubelowdot", + 0x1EE5 : "ubelowdot", + 0x1EE6 : "Uhook", + 0x1EE7 : "uhook", + 0x1EE8 : "Uhornacute", + 0x1EE9 : "uhornacute", + 0x1EEA : "Uhorngrave", + 0x1EEB : "uhorngrave", + 0x1EEC : "Uhornhook", + 0x1EED : "uhornhook", + 0x1EEE : "Uhorntilde", + 0x1EEF : "uhorntilde", + 0x1EF0 : "Uhornbelowdot", + 0x1EF1 : "uhornbelowdot", + 0x1EF2 : "Ygrave", + 0x1EF3 : "ygrave", + 0x1EF4 : "Ybelowdot", + 0x1EF5 : "ybelowdot", + 0x1EF6 : "Yhook", + 0x1EF7 : "yhook", + 0x1EF8 : "Ytilde", + 0x1EF9 : "ytilde", + 0x2002 : "enspace", + 0x2003 : "emspace", + 0x2004 : "em3space", + 0x2005 : "em4space", + 0x2007 : "digitspace", + 0x2008 : "punctspace", + 0x2009 : "thinspace", + 0x200A : "hairspace", + 0x2012 : "figdash", + 0x2013 : "Armenian_en_dash", + 0x2014 : "Armenian_em_dash", + 0x2015 : "Greek_horizbar", + 0x2017 : "hebrew_doublelowline", + 0x2018 : "leftsinglequotemark", + 0x2019 : "rightsinglequotemark", + 0x201A : "singlelowquotemark", + 0x201C : "leftdoublequotemark", + 0x201D : "rightdoublequotemark", + 0x201E : "doublelowquotemark", + 0x2020 : "dagger", + 0x2021 : "doubledagger", + 0x2022 : "enfilledcircbullet", + 0x2025 : "doubbaselinedot", + 0x2026 : "Armenian_ellipsis", + 0x2032 : "minutes", + 0x2033 : "seconds", + 0x2038 : "caret", + 0x203E : "overline", + 0x20A0 : "EcuSign", + 0x20A1 : "ColonSign", + 0x20A2 : "CruzeiroSign", + 0x20A3 : "FFrancSign", + 0x20A4 : "LiraSign", + 0x20A5 : "MillSign", + 0x20A6 : "NairaSign", + 0x20A7 : "PesetaSign", + 0x20A8 : "RupeeSign", + 0x20A9 : "WonSign", + 0x20AA : "NewSheqelSign", + 0x20AB : "DongSign", + 0x20AC : "EuroSign", + 0x2105 : "careof", + 0x2116 : "numerosign", + 0x2117 : "phonographcopyright", + 0x211E : "prescription", + 0x2122 : "trademark", + 0x2153 : "onethird", + 0x2154 : "twothirds", + 0x2155 : "onefifth", + 0x2156 : "twofifths", + 0x2157 : "threefifths", + 0x2158 : "fourfifths", + 0x2159 : "onesixth", + 0x215A : "fivesixths", + 0x215B : "oneeighth", + 0x215C : "threeeighths", + 0x215D : "fiveeighths", + 0x215E : "seveneighths", + 0x2190 : "leftarrow", + 0x2191 : "uparrow", + 0x2192 : "rightarrow", + 0x2193 : "downarrow", + 0x21D2 : "implies", + 0x21D4 : "ifonlyif", + 0x2202 : "partialderivative", + 0x2207 : "nabla", + 0x2218 : "jot", + 0x221A : "radical", + 0x221D : "variation", + 0x221E : "infinity", + 0x2227 : "upcaret", + 0x2228 : "downcaret", + 0x2229 : "upshoe", + 0x222A : "downshoe", + 0x222B : "integral", + 0x2234 : "therefore", + 0x223C : "approximate", + 0x2243 : "similarequal", + 0x2260 : "notequal", + 0x2261 : "identical", + 0x2264 : "lessthanequal", + 0x2265 : "greaterthanequal", + 0x2282 : "leftshoe", + 0x2283 : "rightshoe", + 0x22A2 : "lefttack", + 0x22A3 : "righttack", + 0x22A4 : "uptack", + 0x22A5 : "downtack", + 0x2308 : "upstile", + 0x230A : "downstile", + 0x2315 : "telephonerecorder", + 0x2320 : "topintegral", + 0x2321 : "botintegral", + 0x2395 : "quad", + 0x239B : "topleftparens", + 0x239D : "botleftparens", + 0x239E : "toprightparens", + 0x23A0 : "botrightparens", + 0x23A1 : "topleftsqbracket", + 0x23A3 : "botleftsqbracket", + 0x23A4 : "toprightsqbracket", + 0x23A6 : "botrightsqbracket", + 0x23A8 : "leftmiddlecurlybrace", + 0x23AC : "rightmiddlecurlybrace", + 0x23B7 : "leftradical", + 0x23BA : "horizlinescan1", + 0x23BB : "horizlinescan3", + 0x23BC : "horizlinescan7", + 0x23BD : "horizlinescan9", + 0x2409 : "ht", + 0x240A : "lf", + 0x240B : "vt", + 0x240C : "ff", + 0x240D : "cr", + 0x2423 : "signifblank", + 0x2424 : "nl", + 0x2500 : "horizlinescan5", + 0x2502 : "vertbar", + 0x250C : "upleftcorner", + 0x2510 : "uprightcorner", + 0x2514 : "lowleftcorner", + 0x2518 : "lowrightcorner", + 0x251C : "leftt", + 0x2524 : "rightt", + 0x252C : "topt", + 0x2534 : "bott", + 0x253C : "crossinglines", + 0x2592 : "checkerboard", + 0x25AA : "enfilledsqbullet", + 0x25AB : "enopensquarebullet", + 0x25AC : "filledrectbullet", + 0x25AD : "openrectbullet", + 0x25AE : "emfilledrect", + 0x25AF : "emopenrectangle", + 0x25B2 : "filledtribulletup", + 0x25B3 : "opentribulletup", + 0x25B6 : "filledrighttribullet", + 0x25B7 : "rightopentriangle", + 0x25BC : "filledtribulletdown", + 0x25BD : "opentribulletdown", + 0x25C0 : "filledlefttribullet", + 0x25C1 : "leftopentriangle", + 0x25C6 : "soliddiamond", + 0x25CB : "circle", + 0x25CF : "emfilledcircle", + 0x25E6 : "enopencircbullet", + 0x2606 : "openstar", + 0x260E : "telephone", + 0x2613 : "signaturemark", + 0x261C : "leftpointer", + 0x261E : "rightpointer", + 0x2640 : "femalesymbol", + 0x2642 : "malesymbol", + 0x2663 : "club", + 0x2665 : "heart", + 0x2666 : "diamond", + 0x266D : "musicalflat", + 0x266F : "musicalsharp", + 0x2713 : "checkmark", + 0x2717 : "ballotcross", + 0x271D : "latincross", + 0x2720 : "maltesecross", + 0x27E8 : "leftanglebracket", + 0x27E9 : "rightanglebracket", + 0x3001 : "kana_comma", + 0x3002 : "kana_fullstop", + 0x300C : "kana_openingbracket", + 0x300D : "kana_closingbracket", + 0x3099 : "dead_voiced_sound", + 0x309A : "dead_semivoiced_sound", + 0x309B : "voicedsound", + 0x309C : "semivoicedsound", + 0x30A1 : "kana_a", + 0x30A2 : "kana_A", + 0x30A3 : "kana_i", + 0x30A4 : "kana_I", + 0x30A5 : "kana_u", + 0x30A6 : "kana_U", + 0x30A7 : "kana_e", + 0x30A8 : "kana_E", + 0x30A9 : "kana_o", + 0x30AA : "kana_O", + 0x30AB : "kana_KA", + 0x30AD : "kana_KI", + 0x30AF : "kana_KU", + 0x30B1 : "kana_KE", + 0x30B3 : "kana_KO", + 0x30B5 : "kana_SA", + 0x30B7 : "kana_SHI", + 0x30B9 : "kana_SU", + 0x30BB : "kana_SE", + 0x30BD : "kana_SO", + 0x30BF : "kana_TA", + 0x30C1 : "kana_CHI", + 0x30C3 : "kana_tsu", + 0x30C4 : "kana_TSU", + 0x30C6 : "kana_TE", + 0x30C8 : "kana_TO", + 0x30CA : "kana_NA", + 0x30CB : "kana_NI", + 0x30CC : "kana_NU", + 0x30CD : "kana_NE", + 0x30CE : "kana_NO", + 0x30CF : "kana_HA", + 0x30D2 : "kana_HI", + 0x30D5 : "kana_FU", + 0x30D8 : "kana_HE", + 0x30DB : "kana_HO", + 0x30DE : "kana_MA", + 0x30DF : "kana_MI", + 0x30E0 : "kana_MU", + 0x30E1 : "kana_ME", + 0x30E2 : "kana_MO", + 0x30E3 : "kana_ya", + 0x30E4 : "kana_YA", + 0x30E5 : "kana_yu", + 0x30E6 : "kana_YU", + 0x30E7 : "kana_yo", + 0x30E8 : "kana_YO", + 0x30E9 : "kana_RA", + 0x30EA : "kana_RI", + 0x30EB : "kana_RU", + 0x30EC : "kana_RE", + 0x30ED : "kana_RO", + 0x30EF : "kana_WA", + 0x30F2 : "kana_WO", + 0x30F3 : "kana_N", + 0x30FB : "kana_conjunctive", + 0x30FC : "prolongedsound", + 0x3131 : "Hangul_Kiyeog", + 0x3132 : "Hangul_SsangKiyeog", + 0x3133 : "Hangul_KiyeogSios", + 0x3134 : "Hangul_Nieun", + 0x3135 : "Hangul_NieunJieuj", + 0x3136 : "Hangul_NieunHieuh", + 0x3137 : "Hangul_Dikeud", + 0x3138 : "Hangul_SsangDikeud", + 0x3139 : "Hangul_Rieul", + 0x313A : "Hangul_RieulKiyeog", + 0x313B : "Hangul_RieulMieum", + 0x313C : "Hangul_RieulPieub", + 0x313D : "Hangul_RieulSios", + 0x313E : "Hangul_RieulTieut", + 0x313F : "Hangul_RieulPhieuf", + 0x3140 : "Hangul_RieulHieuh", + 0x3141 : "Hangul_Mieum", + 0x3142 : "Hangul_Pieub", + 0x3143 : "Hangul_SsangPieub", + 0x3144 : "Hangul_PieubSios", + 0x3145 : "Hangul_Sios", + 0x3146 : "Hangul_SsangSios", + 0x3147 : "Hangul_Ieung", + 0x3148 : "Hangul_Jieuj", + 0x3149 : "Hangul_SsangJieuj", + 0x314A : "Hangul_Cieuc", + 0x314B : "Hangul_Khieuq", + 0x314C : "Hangul_Tieut", + 0x314D : "Hangul_Phieuf", + 0x314E : "Hangul_Hieuh", + 0x314F : "Hangul_A", + 0x3150 : "Hangul_AE", + 0x3151 : "Hangul_YA", + 0x3152 : "Hangul_YAE", + 0x3153 : "Hangul_EO", + 0x3154 : "Hangul_E", + 0x3155 : "Hangul_YEO", + 0x3156 : "Hangul_YE", + 0x3157 : "Hangul_O", + 0x3158 : "Hangul_WA", + 0x3159 : "Hangul_WAE", + 0x315A : "Hangul_OE", + 0x315B : "Hangul_YO", + 0x315C : "Hangul_U", + 0x315D : "Hangul_WEO", + 0x315E : "Hangul_WE", + 0x315F : "Hangul_WI", + 0x3160 : "Hangul_YU", + 0x3161 : "Hangul_EU", + 0x3162 : "Hangul_YI", + 0x3163 : "Hangul_I", + 0x316D : "Hangul_RieulYeorinHieuh", + 0x3171 : "Hangul_SunkyeongeumMieum", + 0x3178 : "Hangul_SunkyeongeumPieub", + 0x317F : "Hangul_PanSios", + 0x3181 : "Hangul_KkogjiDalrinIeung", + 0x3184 : "Hangul_SunkyeongeumPhieuf", + 0x3186 : "Hangul_YeorinHieuh", + 0x318D : "Hangul_AraeA", + 0x318E : "Hangul_AraeAE", +} + +if __name__ == "__main__": + pass diff --git a/KeyboardLayoutEditor/src/ParseXKB.py b/KeyboardLayoutEditor/src/ParseXKB.py @@ -0,0 +1,510 @@ +#!/usr/bin/env python +# -*- encoding: UTF-8 -*- +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/> + +import sys +import os.path +import string +import antlr3 +import re +import copy +from lxml import etree +from XKBGrammarLexer import XKBGrammarLexer +from XKBGrammarParser import XKBGrammarParser +from XKBGrammarWalker import XKBGrammarWalker, LAYOUT, SYMBOLS, MAPMATERIAL, MAPTYPE, MAPOPTIONS, MAPOPTS, MAPNAME, TOKEN_INCLUDE, TOKEN_NAME, TOKEN_KEY_TYPE, TOKEN_KEY, TOKEN_TYPE, TOKEN_MODIFIER_MAP, TOKEN_VIRTUAL_MODIFIERS, KEYCODE, KEYCODEX, ELEM_KEYSYMS, ELEM_KEYSYMGROUP, ELEM_VIRTUALMODS, OVERLAY, VALUE, STATE, NAME, DQSTRING, OVERRIDE +import KeycodesReader +import KeysymsUni + +import Common +from ParseXML import ExtractVariantsKeycodes + +class ParseXKB: + def __init__(self): + KeycodesReader.initialise() + + # Sorts a dictionary by value, produces a sorted list of values. + def sortDict(self, adict, cmp_function = None): + keys = adict.keys() + keys.sort(cmp_function) + return map(adict.get, keys) + + # Helper function to iterate through all children of a given type + def getChildrenByType(self, tree, type_value): + for i in range(tree.getChildCount()): + child = tree.getChild(i) + if child.getType() == type_value: + yield child + + # Helper function to iterate through all children of a given type + def getChildrenByTypes(self, tree, type_value1, type_value2): + for i in range(tree.getChildCount()): + child = tree.getChild(i) + if child.getType() == type_value1 or child.getType() == type_value2: + yield child + + # Helper function to iterate through all children of a given type + def getChildrenListByType(self, tree, type_value): + list = [] + for i in range(tree.getChildCount()): + child = tree.getChild(i) + if child.getType() == type_value: + list.append(child) + return list + + # Helper function to iterate through all children of a given type + def getChildrenListByTypes(self, tree, type_value1, type_value2): + list = [] + for i in range(tree.getChildCount()): + child = tree.getChild(i) + if child.getType() == type_value1 or child.getType() == type_value2: + list.append(child) + return list + + def hasChildByType(self, tree, type_value): + has = False + for i in range(tree.getChildCount()): + child = tree.getChild(i) + if child.getType() == type_value: + has = True + break + return has + + def parse(self, xkbfilename): + char_stream = antlr3.ANTLRFileStream(xkbfilename, encoding='utf-8') + lexer = XKBGrammarLexer(char_stream) + tokens = antlr3.CommonTokenStream(lexer) + parser = XKBGrammarParser(tokens) + + result = parser.layout() + + # print "tree =", result.tree.toStringTree() + + nodes = antlr3.tree.CommonTreeNodeStream(result.tree) + nodes.setTokenStream(tokens) + walker = XKBGrammarWalker(nodes) + # walker.layout() + + layout = etree.Element('layout') + + doc = etree.ElementTree(layout) + + layout.attrib['layoutname'] = os.path.basename(xkbfilename) + + #print "Processing", os.path.basename(xkbfilename), "...", + for symbols in result.tree.getChildren(): + eSymbol = etree.SubElement(layout, 'symbols') + for mapobject in symbols.getChildren(): + if mapobject.getType() == MAPTYPE: + for maptypesect in mapobject.getChildren(): + if maptypesect.getType() == MAPOPTIONS: + for mapoption in maptypesect.getChildren(): + if mapoption.getText() == 'xkb_symbols' or mapoption.getText() == 'hidden': + eMapOption = etree.SubElement(eSymbol, 'mapoption') + eMapOption.text = mapoption.getText() + elif maptypesect.getType() == MAPNAME: + if maptypesect.getChildCount() == 1: + eMapName = etree.SubElement(eSymbol, 'mapname') + eMapName.text = maptypesect.getChildren()[0].getText()[1:-1] + else: + print "\t\t\tInternal error in mapoption" + else: + print "\t\tInternal error in maptypesect" + sys.exit(-2) + elif mapobject.getType() == MAPMATERIAL: + eMapMaterial = etree.SubElement(eSymbol, 'mapmaterial') + for name in self.getChildrenByType(mapobject, TOKEN_NAME): + nameText = name.getChild(0).getText()[1:-1] + eTokenName = etree.SubElement(eMapMaterial, 'tokenname', name=nameText ) + for include in self.getChildrenByType(mapobject, TOKEN_INCLUDE): + eInclude = etree.SubElement(eMapMaterial, 'tokeninclude') + eInclude.text = include.getChild(0).getText()[1:-1] + for keytype in self.getChildrenByType(mapobject, TOKEN_KEY_TYPE): + keytypeText = keytype.getChild(0).getText() + eKeyType = etree.SubElement(eMapMaterial, 'tokentype') + eKeyType.text = keytypeText[1:-1] + for modmap in self.getChildrenByType(mapobject, TOKEN_MODIFIER_MAP): + eModMap = etree.SubElement(eMapMaterial, 'tokenmodifiermap', state=modmap.getChild(0).getText()) + for modstate in self.getChildrenByTypes(modmap, KEYCODE, KEYCODEX): + if modstate.getType() == KEYCODE: + eModState = etree.SubElement(eModMap, "keycode", value=modstate.getChild(0).getText()) + elif modstate.getType() == KEYCODEX: + eModState = etree.SubElement(eModMap, "keycodex", value=modstate.getChild(0).getText()) + else: + print "Unexpected token encountered. Aborting...", modstate.getText() + sys.exit(-1) + allkeysymgroups = {} + for keyset in self.getChildrenByType(mapobject, TOKEN_KEY): + allkeysymgroups[keyset.getChild(0).getChild(0).getText()] = keyset + sortedkeysymgroups = self.sortDict(allkeysymgroups, KeycodesReader.compare_keycode) + for keyset in sortedkeysymgroups: + elem_keysymgroup = self.getChildrenByType(keyset, ELEM_KEYSYMGROUP) + elem_virtualmods = self.getChildrenByType(keyset, ELEM_VIRTUALMODS) + elem_overlay = self.getChildrenByType(keyset, OVERLAY) + override = self.getChildrenListByType(keyset, OVERRIDE) + eTokenKey = etree.SubElement(eMapMaterial, 'tokenkey') + eKeyCodeName = etree.SubElement(eTokenKey, 'keycodename') + keycodex = self.getChildrenListByType(keyset, KEYCODEX) + if len(keycodex) == 1: + eKeyCodeName.text = keycodex[0].getChild(0).getText() + else: + print "Could not retrieve keycode name" + exit(-1) + if len(override) == 1: + eTokenKey.attrib['override'] = "True" + else: + eTokenKey.attrib['override'] = "False" + if len(self.getChildrenListByType(keyset, ELEM_KEYSYMGROUP)): + elem_keysyms = self.getChildrenListByType(keyset, ELEM_KEYSYMS) + eKeySymGroup = etree.SubElement(eTokenKey, 'keysymgroup') + keysymgroup_counter = len(self.getChildrenListByType(keyset, ELEM_KEYSYMGROUP)) + for elem in elem_keysymgroup: + eSymbolsGroup = etree.SubElement(eKeySymGroup, 'symbolsgroup') + for elem2 in elem.getChildren(): + for elem3 in elem2.getChildren(): + eSymbol = etree.SubElement(eSymbolsGroup, 'symbol') + eSymbol.text = elem3.getText() + if len(elem_keysyms) > 0: + if len(elem_keysyms) == 1: + ksname = elem_keysyms[0].getChild(0).getText() + eKeySyms = etree.SubElement(eKeySymGroup, 'typegroup', value=ksname[1:-1]) + else: + """ We are probably processing level3; we keep first item """ + ksname = elem_keysyms[0].getChild(0).getText() + eKeySyms = etree.SubElement(eKeySymGroup, 'typegroup', value=ksname[1:-1]) + #print "Possibly processing level3" + if len(self.getChildrenListByType(keyset, ELEM_VIRTUALMODS)): + for vmods in elem_virtualmods: + etree.SubElement(eKeySymGroup, 'tokenvirtualmodifiers', value=vmods.getChild(0).getText()) + if len(self.getChildrenListByType(keyset, OVERLAY)): + for elem in elem_overlay: + for elem2 in self.getChildrenByType(elem, KEYCODEX): + pass + else: + print "\tInternal error at map level,", mapobject.getText() + # sys.exit(-2) + + return layout + + + def parse_layout(self, xkbfilename, variant = None): + char_stream = antlr3.ANTLRFileStream(xkbfilename, encoding='utf-8') + lexer = XKBGrammarLexer(char_stream) + tokens = antlr3.CommonTokenStream(lexer) + parser = XKBGrammarParser(tokens) + + result = parser.layout() + variants = [] + + layout = etree.Element('layout') + layout.attrib['layoutname'] = os.path.basename(xkbfilename) + + #print "Processing", os.path.basename(xkbfilename), "...", + for symbols in result.tree.getChildren(): + eSymbol = etree.SubElement(layout, 'symbols') + for mapobject in symbols.getChildren(): + if mapobject.getType() == MAPTYPE: + for maptypesect in mapobject.getChildren(): + if maptypesect.getType() == MAPOPTIONS: + for mapoption in maptypesect.getChildren(): + if mapoption.getText() == 'xkb_symbols' or mapoption.getText() == 'hidden': + eMapOption = etree.SubElement(eSymbol, 'mapoption') + eMapOption.text = mapoption.getText() + elif maptypesect.getType() == MAPNAME: + if maptypesect.getChildCount() == 1: + eMapName = etree.SubElement(eSymbol, 'mapname') + eMapName.text = maptypesect.getChildren()[0].getText()[1:-1] + variants.append(maptypesect.getChildren()[0].getText()[1:-1]) + else: + return { "success": False } + #print "\t\t\tInternal error in mapoption" + else: + return { "success": False } + #print "\t\tInternal error in maptypesect" + #sys.exit(-2) + elif mapobject.getType() == MAPMATERIAL: + eMapMaterial = etree.SubElement(eSymbol, 'mapmaterial') + for name in self.getChildrenByType(mapobject, TOKEN_NAME): + nameText = name.getChild(0).getText()[1:-1] + eTokenName = etree.SubElement(eMapMaterial, 'tokenname', name=nameText ) + for include in self.getChildrenByType(mapobject, TOKEN_INCLUDE): + eInclude = etree.SubElement(eMapMaterial, 'tokeninclude') + eInclude.text = include.getChild(0).getText()[1:-1] + for keytype in self.getChildrenByType(mapobject, TOKEN_KEY_TYPE): + keytypeText = keytype.getChild(0).getText() + eKeyType = etree.SubElement(eMapMaterial, 'tokentype') + eKeyType.text = keytypeText[1:-1] + for modmap in self.getChildrenByType(mapobject, TOKEN_MODIFIER_MAP): + eModMap = etree.SubElement(eMapMaterial, 'tokenmodifiermap', state=modmap.getChild(0).getText()) + for modstate in self.getChildrenByTypes(modmap, KEYCODE, KEYCODEX): + if modstate.getType() == KEYCODE: + eModState = etree.SubElement(eModMap, "keycode", value=modstate.getChild(0).getText()) + elif modstate.getType() == KEYCODEX: + eModState = etree.SubElement(eModMap, "keycodex", value=modstate.getChild(0).getText()) + else: + return { "success": False } + # print "Unexpected token encountered. Aborting...", modstate.getText() + # sys.exit(-1) + allkeysymgroups = {} + for keyset in self.getChildrenByType(mapobject, TOKEN_KEY): + allkeysymgroups[keyset.getChild(0).getChild(0).getText()] = keyset + sortedkeysymgroups = self.sortDict(allkeysymgroups, KeycodesReader.compare_keycode) + for keyset in sortedkeysymgroups: + elem_keysymgroup = self.getChildrenByType(keyset, ELEM_KEYSYMGROUP) + elem_virtualmods = self.getChildrenByType(keyset, ELEM_VIRTUALMODS) + elem_overlay = self.getChildrenByType(keyset, OVERLAY) + override = self.getChildrenListByType(keyset, OVERRIDE) + eTokenKey = etree.SubElement(eMapMaterial, 'tokenkey') + eKeyCodeName = etree.SubElement(eTokenKey, 'keycodename') + keycodex = self.getChildrenListByType(keyset, KEYCODEX) + if len(keycodex) == 1: + eKeyCodeName.text = keycodex[0].getChild(0).getText() + else: + return { "success": False } + #print "Could not retrieve keycode name" + #exit(-1) + if len(override) == 1: + eTokenKey.attrib['override'] = "True" + else: + eTokenKey.attrib['override'] = "False" + if len(self.getChildrenListByType(keyset, ELEM_KEYSYMGROUP)): + elem_keysyms = self.getChildrenListByType(keyset, ELEM_KEYSYMS) + eKeySymGroup = etree.SubElement(eTokenKey, 'keysymgroup') + keysymgroup_counter = len(self.getChildrenListByType(keyset, ELEM_KEYSYMGROUP)) + for elem in elem_keysymgroup: + eSymbolsGroup = etree.SubElement(eKeySymGroup, 'symbolsgroup') + for elem2 in elem.getChildren(): + for elem3 in elem2.getChildren(): + eSymbol = etree.SubElement(eSymbolsGroup, 'symbol') + eSymbol.text = elem3.getText() + if len(elem_keysyms) > 0: + if len(elem_keysyms) == 1: + ksname = elem_keysyms[0].getChild(0).getText() + eKeySyms = etree.SubElement(eKeySymGroup, 'typegroup', value=ksname[1:-1]) + else: + """ We are probably processing level3; we keep first item """ + ksname = elem_keysyms[0].getChild(0).getText() + eKeySyms = etree.SubElement(eKeySymGroup, 'typegroup', value=ksname[1:-1]) + #print "Possibly processing level3" + if len(self.getChildrenListByType(keyset, ELEM_VIRTUALMODS)): + for vmods in elem_virtualmods: + etree.SubElement(eKeySymGroup, 'tokenvirtualmodifiers', value=vmods.getChild(0).getText()) + if len(self.getChildrenListByType(keyset, OVERLAY)): + for elem in elem_overlay: + for elem2 in self.getChildrenByType(elem, KEYCODEX): + pass + else: + return { "success": False } + #print "\tInternal error at map level,", mapobject.getText() + # sys.exit(-2) + + return { "success": True, "variants": variants, "layout": layout } + + + +################################################################################ +# xkb_symbols "basic" { +# name[Group1]= "USA"; +# include "latin" +# include "kpdl(comma) +# include "level3(ralt_switch)" +# +# // Alphanumeric section +# key <TLDE> { [ grave, asciitilde ] }; +# key <AE01> { [ 1, exclam ] }; +# key <AE02> { [ 2, at ] }; +# }; + +# Algorigth +# 1. Collect include statements +# 2. Parse include files +# + def parse_layout_controller(self, store_keydict, xkbfilename, variantname = None): + self.parse_layout_recursive(store_keydict, xkbfilename, variantname, start = True) + return store_keydict + + def parse_layout_recursive(self, store_keydict, xkbfilename, variantname = None, start = True): + #print "Processing", os.path.basename(xkbfilename), "..." + parsed_layout = self.parse_layout_slave(xkbfilename, variantname) + + #print "############# ", xkbfilename, variantname, "Looping for", parsed_layout['variants'] + for includefile in parsed_layout['variants']: + #print " Doing includefile:", includefile + include_components = Common.parseIncludeString(includefile) + if include_components['variant'] == '': + #print " variant was empty", + include_parse_result = self.parse_layout(xkbfilename) + include_components['variant'] = include_parse_result["variants"][0] + #print " we fix to", include_components + + #print " Calling ourselves", Common.symbolsdir + include_components['filename'], include_components['variant'] + new_parsed_layout = self.parse_layout_recursive(store_keydict, + Common.symbolsdir + include_components['filename'], + include_components['variant'], + True) + #print " new_parsed_result for variantname", include_components['variant'], " is ", new_parsed_layout + if new_parsed_layout.has_key('keydict'): + #print " LINES:", len(new_parsed_layout['keydict'].keys()) + for k in new_parsed_layout['keydict'].keys(): + for i in parsed_layout['keydict'][k].keys(): + #print parsed_layout['keydict'][k][i].getPValue(), + if store_keydict.has_key(k) == False: + store_keydict[k] = {} + store_keydict[k][i] = copy.copy(new_parsed_layout['keydict'][k][i]) + #print + + #extraction_result = ExtractVariantsKeycodes(parsed_layout['layout'], variantname) + if start == True: + #print "parsed_result for variantname", variantname, " is ", parsed_layout + if parsed_layout.has_key('keydict'): + #print " LINES:", len(parsed_layout['keydict'].keys()) + for k in parsed_layout['keydict'].keys(): + #print k, + for i in parsed_layout['keydict'][k].keys(): + #print parsed_layout['keydict'][k][i].getPValue(), + if store_keydict.has_key(k) == False: + store_keydict[k] = {} + store_keydict[k][i] = copy.copy(parsed_layout['keydict'][k][i]) + #print + + return { 'success': True, 'layout': parsed_layout['layout'], 'variants': parsed_layout['variants'] } + + def parse_layout_slave(self, xkbfilename, variantname = None): + #print "+++++We are recursive, called with", xkbfilename, variantname + char_stream = antlr3.ANTLRFileStream(xkbfilename, encoding='utf-8') + lexer = XKBGrammarLexer(char_stream) + tokens = antlr3.CommonTokenStream(lexer) + parser = XKBGrammarParser(tokens) + + parser_layout = parser.layout() + variants = [] + + xml_layout = etree.Element('layout') + xml_layout.attrib['layoutname'] = os.path.basename(xkbfilename) + + includes = [] + + for symbols in parser_layout.tree.getChildren(): + eSymbol = etree.SubElement(xml_layout, 'symbols') + for mapobject in symbols.getChildren(): + if mapobject.getType() == MAPTYPE: + for maptypesect in mapobject.getChildren(): + if maptypesect.getType() == MAPOPTIONS: + for mapoption in maptypesect.getChildren(): + if mapoption.getText() == 'xkb_symbols' or mapoption.getText() == 'hidden': + eMapOption = etree.SubElement(eSymbol, 'mapoption') + eMapOption.text = mapoption.getText() + elif maptypesect.getType() == MAPNAME: + if maptypesect.getChildCount() == 1: + eMapName = etree.SubElement(eSymbol, 'mapname') + eMapName.text = maptypesect.getChildren()[0].getText()[1:-1] + variants.append(maptypesect.getChildren()[0].getText()[1:-1]) + else: + return { "success": False } + else: + return { "success": False } + elif mapobject.getType() == MAPMATERIAL: + eMapMaterial = etree.SubElement(eSymbol, 'mapmaterial') + for name in self.getChildrenByType(mapobject, TOKEN_NAME): + nameText = name.getChild(0).getText()[1:-1] + eTokenName = etree.SubElement(eMapMaterial, 'tokenname', name=nameText ) + for include in self.getChildrenByType(mapobject, TOKEN_INCLUDE): + eInclude = etree.SubElement(eMapMaterial, 'tokeninclude') + eInclude.text = include.getChild(0).getText()[1:-1] + includes.append(eInclude.text) + for keytype in self.getChildrenByType(mapobject, TOKEN_KEY_TYPE): + keytypeText = keytype.getChild(0).getText() + eKeyType = etree.SubElement(eMapMaterial, 'tokentype') + eKeyType.text = keytypeText[1:-1] + for modmap in self.getChildrenByType(mapobject, TOKEN_MODIFIER_MAP): + eModMap = etree.SubElement(eMapMaterial, 'tokenmodifiermap', state=modmap.getChild(0).getText()) + for modstate in self.getChildrenByTypes(modmap, KEYCODE, KEYCODEX): + if modstate.getType() == KEYCODE: + eModState = etree.SubElement(eModMap, "keycode", value=modstate.getChild(0).getText()) + elif modstate.getType() == KEYCODEX: + eModState = etree.SubElement(eModMap, "keycodex", value=modstate.getChild(0).getText()) + else: + return { "success": False } + # print "Unexpected token encountered. Aborting...", modstate.getText() + # sys.exit(-1) + allkeysymgroups = {} + for keyset in self.getChildrenByType(mapobject, TOKEN_KEY): + allkeysymgroups[keyset.getChild(0).getChild(0).getText()] = keyset + sortedkeysymgroups = self.sortDict(allkeysymgroups, KeycodesReader.compare_keycode) + for keyset in sortedkeysymgroups: + elem_keysymgroup = self.getChildrenByType(keyset, ELEM_KEYSYMGROUP) + elem_virtualmods = self.getChildrenByType(keyset, ELEM_VIRTUALMODS) + elem_overlay = self.getChildrenByType(keyset, OVERLAY) + override = self.getChildrenListByType(keyset, OVERRIDE) + eTokenKey = etree.SubElement(eMapMaterial, 'tokenkey') + eKeyCodeName = etree.SubElement(eTokenKey, 'keycodename') + keycodex = self.getChildrenListByType(keyset, KEYCODEX) + if len(keycodex) == 1: + eKeyCodeName.text = keycodex[0].getChild(0).getText() + else: + return { "success": False } + #print "Could not retrieve keycode name" + #exit(-1) + if len(override) == 1: + eTokenKey.attrib['override'] = "True" + else: + eTokenKey.attrib['override'] = "False" + if len(self.getChildrenListByType(keyset, ELEM_KEYSYMGROUP)): + elem_keysyms = self.getChildrenListByType(keyset, ELEM_KEYSYMS) + eKeySymGroup = etree.SubElement(eTokenKey, 'keysymgroup') + keysymgroup_counter = len(self.getChildrenListByType(keyset, ELEM_KEYSYMGROUP)) + for elem in elem_keysymgroup: + eSymbolsGroup = etree.SubElement(eKeySymGroup, 'symbolsgroup') + for elem2 in elem.getChildren(): + for elem3 in elem2.getChildren(): + eSymbol = etree.SubElement(eSymbolsGroup, 'symbol') + eSymbol.text = elem3.getText() + if len(elem_keysyms) > 0: + if len(elem_keysyms) == 1: + ksname = elem_keysyms[0].getChild(0).getText() + eKeySyms = etree.SubElement(eKeySymGroup, 'typegroup', value=ksname[1:-1]) + else: + """ We are probably processing level3; we keep first item """ + ksname = elem_keysyms[0].getChild(0).getText() + eKeySyms = etree.SubElement(eKeySymGroup, 'typegroup', value=ksname[1:-1]) + #print "Possibly processing level3" + if len(self.getChildrenListByType(keyset, ELEM_VIRTUALMODS)): + for vmods in elem_virtualmods: + etree.SubElement(eKeySymGroup, 'tokenvirtualmodifiers', value=vmods.getChild(0).getText()) + if len(self.getChildrenListByType(keyset, OVERLAY)): + for elem in elem_overlay: + for elem2 in self.getChildrenByType(elem, KEYCODEX): + pass + else: + return { "success": False } + + extraction_result = ExtractVariantsKeycodes(xml_layout, variantname) + return { 'success': True, + 'all_variants': variants, + 'variants': extraction_result['variants'], + 'layout': xml_layout, + 'keydict': extraction_result['keydict'] + } + +if __name__ == '__main__': + px = ParseXKB() + + store_keydict = {} + px.parse_layout_controller(store_keydict, '/etc/X11/xkb/symbols/gr', 'polytonic') + print "About to print" + for k in store_keydict.keys(): + print k, + for i in store_keydict[k].keys(): + print store_keydict[k][i].getValue(), + print+ \ No newline at end of file diff --git a/KeyboardLayoutEditor/src/ParseXML.py b/KeyboardLayoutEditor/src/ParseXML.py @@ -0,0 +1,180 @@ +#!/usr/bin/env python +# -*- encoding: UTF-8 -*- +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/> + +import sys +import antlr3 +from lxml import etree + +import Common +import KeyValue + +def __recurse_tree__(node, fout): + if node.tag == "layout": + #print "Parsing", node.attrib["layoutname"] + for n in node: + __recurse_tree__(n, fout) + elif node.tag == "symbols": + for k in node: + if k.tag == "mapoption": + fout.write(k.text) + fout.write(" ") + elif k.tag == "mapname": + fout.write("\"%(s)s\"\n{\n" % { "s": k.text }) + elif k.tag == "mapmaterial": + keycodedict_lines = {} + for t in k: + if t.tag == "tokenname": + fout.write("\tname[Group1] = \"%(s)s\";\n" % { "s": t.attrib["name"] }) + elif t.tag == "tokeninclude": + fout.write("\tinclude \"%(s)s\"\n" % { "s": t.text }) + elif t.tag == "tokentype": + fout.write("\tkey.type = \"%(s)s\";\n" % { "s": t.text }) + elif t.tag == "tokenmodifiermap": + fout.write("\tmodifier_map %(s)s { " % { "s": t.attrib['state'] }) + count_mm = len(t) + for mm in t: + if mm.tag == "keycodex": + fout.write("<%(s)s>" % { "s": mm.attrib["value"] }) + elif mm.tag == "keycode": + fout.write("%(s)s" % { "s": mm.attrib["value"] }) + if count_mm > 1: + fout.write(", ") + count_mm -= 1 + fout.write(' };\n') + elif t.tag == "tokenkey": + # We attempt to sort the keycode lines by keycode value. + keycodelinelist = [] + keycodelinelist.append("\t") + if t.attrib["override"] == "True": + keycodelinelist.append("override ") + for tk in t: + if tk.tag == "keycodename": + keycodelinelist.append("key <%(s)s> { " % { "s": tk.text }) + keycodelinekeycode = tk.text + elif tk.tag == "keysymgroup": + gotitem = False + for ks in tk: + if ks.tag == "typegroup": + if gotitem: + keycodelinelist.append(", ") + keycodelinelist.append("type = \"%(s)s\" " % { "s": ks.attrib["value"] }) + gotitem = True + elif ks.tag == "tokenvirtualmodifiers": + if gotitem: + keycodelinelist.append(", ") + keycodelinelist.append("virtualMods = %(s)s " % { "s": ks.attrib["value"] }) + elif ks.tag == "symbolsgroup": + if gotitem: + keycodelinelist.append(", ") + gotitem = True + keycodelinelist.append("[ ") + count_sg = len(ks) + for sg in ks: + if sg.tag == "symbol": + if count_sg > 1: + keycodelinelist.append("%(s)14s, " % { "s": sg.text }) + else: + keycodelinelist.append("%(s)14s " % { "s": sg.text }) + count_sg -= 1 + else: + print "ERROR" + sys.exit(-1) + for spaces_count in range(Common.LEVELMAX - len(ks)): + keycodelinelist.append('%(s)15s ' % { 's': ' ' }) + keycodelinelist.append("]") + keycodelinelist.append(" };\n") + keycodedict_lines[keycodelinekeycode] = "".join(keycodelinelist) + keycodeslist = keycodedict_lines.keys() + keycodeslist.sort() + for kc in keycodeslist: + fout.write(keycodedict_lines[kc]) + fout.write("};\n\n") + +def __extract_keycodes__(node, variants, keydict, variant): + we_are_shooting = False + variant_verbose_name = '' + if node.tag == "layout": + #print "Parsing", node.attrib["layoutname"] + for n in node: + result = __extract_keycodes__(n, variants, keydict, variant) + if result != None: + if result['done'] == True: + return result + + if node.tag == "symbols": + for k in node: + if k.tag == "mapoption": + pass + elif k.tag == "mapname": + # If we are not processing the correct variant, + if k.text != variant: + break + else: + we_are_shooting = True + elif k.tag == "mapmaterial": + for t in k: + if t.tag == "tokenname": + variant_verbose_name = t.attrib["name"] + elif t.tag == "tokeninclude": + variants.append(t.text) + elif t.tag == "tokentype": + # t.text + pass + elif t.tag == "tokenmodifiermap": + pass + elif t.tag == "tokenkey": + if t.attrib["override"] == "True": + pass + for tk in t: + if tk.tag == "keycodename": + keycodename = tk.text + keydict[keycodename] = {} + elif tk.tag == "keysymgroup": + for ks in tk: + if ks.tag == "typegroup": + # ks.attrib["value"] + pass + elif ks.tag == "tokenvirtualmodifiers": + # ks.attrib["value"] + pass + elif ks.tag == "symbolsgroup": + key_index = Common.keysegments.ONE + keyvalues = {} + for sg in ks: + if sg.tag == "symbol": + newkeyvalue = KeyValue.KeyValue(sg.text) + keyvalues[key_index] = newkeyvalue + key_index += 1 + keydict[keycodename] = keyvalues + if we_are_shooting: + return { 'done' : True, 'variants': variants, 'keydict': keydict, 'variant_name': variant_verbose_name } + +def ParseXML(xmllayoutroot, fout): + return __recurse_tree__(xmllayoutroot, fout) + +def ExtractVariantsKeycodes(xmllayoutroot, variant): + VariantsNew = [] + KeyDictNew = {} + return __extract_keycodes__(xmllayoutroot, VariantsNew, KeyDictNew, variant) + +if __name__ == "__main__": + sourcefile = "/home/user/WORK/KEYBOARDLAYOUTEDITOR/keyboardlayouteditor/XKBGrammar/demo.xml" + sourcefile = "/home/user/WORK/KEYBOARDLAYOUTEDITOR/keyboardlayouteditor/XKBGrammar/us.xml" + doc = etree.parse(sourcefile) + #print doc + #print etree.tounicode(doc, pretty_print=True) + #ParseXML(doc.getroot(), sys.stdout) + print ExtractVariantsKeycodes(doc.getroot(), "euro")+ \ No newline at end of file diff --git a/KeyboardLayoutEditor/src/README.txt b/KeyboardLayoutEditor/src/README.txt @@ -0,0 +1,41 @@ +This is the Keyboard Layout Editor (KLE), a pygtk program that helps create +or edit XKB keyboard layouts. This allows you to type characters from different +languages or other special Unicode characters on your Linux desktop. + +The project page of the Keyboard Layout Editor is +http://code.google.com/p/keyboardlayouteditor/ + +You are strongly encouraged to use the version that is found at the above URL, +as it includes several bug fixes. + +The project was developed using Eclipse (Ganymede), with the Python (PyDev) +and Antlr (AntlrIDE) add-ons. + +PyDev is found at +http://pydev.sourceforge.net/ + +AntlrIDE is found at +http://antlrv3ide.sourceforge.net/ + +If you also have SVN support in Eclipse (hint: Subclipse), +you can grab the latest source from within Eclipse. +There is also integration with Mylene so that you can get the list of +issues/bugs/todo items automatically. + +To run the application, you need the python binding packages for +* Cairo +* Pango +* GObject +* lxml + +and the Antlr 3.1 Runtime environment for Python. You grab that at +http://antlr.org/download/Python/ +Choose the appropriate *.egg file for the 3.1 version, then type + +sudo easy_install antlr_python_runtime-3.1-py2.5.egg + +This should do the installation for you. + +You run the Keyboard Layout Editor with + +./KeyboardLayoutEditor.py diff --git a/KeyboardLayoutEditor/src/SelectVariant.py b/KeyboardLayoutEditor/src/SelectVariant.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python +# -*- encoding: UTF-8 -*- +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/> + +import gtk +import gobject +import copy + +class SelectVariant: + def __init__(self, window): + self.dialog = gtk.Dialog("Select Variant", + window, + gtk.DIALOG_MODAL, + (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, + gtk.STOCK_OK, gtk.RESPONSE_ACCEPT) ) + vbox = gtk.VBox() + self.dialog.vbox.pack_start(vbox, expand = True, fill = True) + vbox.show() + + # The selection + self.selection = '' + + # Creation of the actual model + self.store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_BOOLEAN) + for i in ([1,2,3,4,5]): + self.store.append((i, True)) + + # Creation of the filter, from the model + self.filter = self.store.filter_new() + self.filter.set_visible_column(1) + + # The TreeView gets the filter as model + self.view = gtk.TreeView(self.filter) + + # Some other gtk stuff + renderer = gtk.CellRendererText() + self.view.insert_column_with_attributes(-1,"Variants",renderer,text=0) + vbox.pack_start(self.view) + self.view.show() + self.dialog.connect("response", self.select_row) + self.dialog.connect("close", self.close) + + def show(self): + self.dialog.show() + self.dialog.run() + + def set_list(self, list_items): + self.store.clear() + for variant in list_items: + self.store.append((variant, True)) + self.selection = list_items[0] + + def get_selection(self): + return self.selection + + def select_row(self, widget, response_id): + if response_id == gtk.RESPONSE_ACCEPT: + # Get the selected row + filter_iter = self.view.get_selection().get_selected()[1] + # Translate it into a useful iterator + store_iter = self.filter.convert_iter_to_child_iter(filter_iter) + # Use it to show the selected row + self.selection = self.store[store_iter][0] + print self.selection + else: + self.selection = '' + print "Cancelled" + self.dialog.hide() + + def close(self): + self.dialog.hide() + +if __name__ == '__main__': + # That's it + # Prepare the window and other Gtk stuff + window = gtk.Window(gtk.WINDOW_TOPLEVEL) + window.set_modal(True) + window.set_default_size(100, 200) + window.connect("destroy", gtk.main_quit) + a = SelectVariant(window) + a.set_list(["one", "two", "three"]) + a.show() + gtk.main() diff --git a/KeyboardLayoutEditor/src/XKBGrammar.g b/KeyboardLayoutEditor/src/XKBGrammar.g @@ -0,0 +1,203 @@ +// XKB Grammar (X.org) +// Written by Simos Xenitellis <simos.lists@googlemail.com>, 2008. +// Version 0.8 + +grammar XKBGrammar; + +options +{ + language = Python; + output = AST; +} + +tokens +{ + // Keywords + TOKEN_INCLUDE; + TOKEN_KEY_TYPE; + TOKEN_NAME; + TOKEN_KEY; + TOKEN_TYPE; + TOKEN_MODIFIER_MAP; + TOKEN_SYMBOL; + TOKEN_VIRTUAL_MODIFIERS; + + // Tokens for tree. + LAYOUT; + SYMBOLS; + MAPTYPE; + MAPNAME; + MAPOPTIONS; + MAPMATERIAL; + KEYCODE; + KEYCODEX; + VALUE; + STATE; + ELEM_KEYSYMGROUP; + ELEM_KEYSYMS; + ELEM_VIRTUALMODS; + KEYELEMENTS; + OVERRIDE; + OVERLAY; +} + +// We cover XKB symbol files that look like +// +// // comments can appear here. +// one of more modifiers "mysymbolsname" +// { +// // comments can appear here. +// include "somename" // comments can also appear here. +// name[somestring] = "sometext"; +// key.type[someotherstring] = "someothertext"; +// key <someotherstring> { [ somesymbol, someothersymbol, ... uptoEightSymbols ] }; +// modifier_map someothertext { somesymbol, someothersymbol, ... uptoEightSymbols }; +// // can also have multiples of the above. +// }; +// +// // can have several symbol sections as above. + +layout + : symbols+ EOF + -> ^(LAYOUT symbols+) + ; + +symbols + : mapType '{' mapMaterial+ '}' ';' + -> ^(SYMBOLS mapType ^(MAPMATERIAL mapMaterial+)) + ; + +mapType + : MAPOPTS+ DQSTRING + -> ^(MAPTYPE ^(MAPOPTIONS MAPOPTS+) ^(MAPNAME DQSTRING)) + ; + +mapMaterial + : line_include + | line_name ';'! + | line_keytype ';'! + | line_key ';'! + | line_modifier_map ';'! + | line_virtual_modifiers ';'! + ; + +line_include + : 'include' DQSTRING + -> ^(TOKEN_INCLUDE DQSTRING) + ; + +line_name + : 'name' ('[' NAME ']')? '=' DQSTRING + -> ^(TOKEN_NAME DQSTRING) + ; + +line_keytype + : 'key.type' ('[' NAME ']')? '=' DQSTRING + -> ^(TOKEN_KEY_TYPE DQSTRING) + ; + +line_key + : OVERRIDE? 'key' '<' NAME '>' '{' keyelements (',' keyelements)* '}' + -> ^(TOKEN_KEY OVERRIDE? ^(KEYCODEX NAME) keyelements+) + ; + +line_modifier_map + : 'modifier_map' STATE '{' keycode (',' keycode)* '}' + -> ^(TOKEN_MODIFIER_MAP STATE keycode+) + ; + +line_virtual_modifiers + : 'virtual_modifiers' NAME (',' NAME)* + -> ^(TOKEN_VIRTUAL_MODIFIERS NAME+) + ; + +keycode + : '<' NAME '>' -> ^(KEYCODEX NAME) + | NAME -> ^(KEYCODE NAME) + ; + +override + : 'override' + ; + +keyelements + : elem_keysyms + | elem_keysymgroup + | elem_virtualmods + | elem_overlay + ; + +elem_keysyms + : 'type' ('[' NAME ']')? '=' DQSTRING + -> ^(ELEM_KEYSYMS DQSTRING) + ; + +elem_keysymgroup + : ('symbols' '[' NAME ']' '=')? '[' keysym+=NAME (',' keysym+=NAME)* ']' + -> ^(ELEM_KEYSYMGROUP ^(VALUE $keysym+ )) + ; + +elem_virtualmods + : ('virtualMods' '=' NAME) + -> ^(ELEM_VIRTUALMODS NAME) + ; + +elem_overlay + : NAME '=' keycode + -> ^(OVERLAY NAME keycode) + ; + +MAPOPTS + : 'default' + | 'hidden' + | 'partial' + | 'alphanumeric_keys' + | 'keypad_keys' + | 'function_keys' + | 'modifier_keys' + | 'alternate_group' + | 'xkb_symbols' + ; + +STATE + : 'Shift' + | 'Control' + | 'Lock' + | 'Mod1' + | 'Mod2' + | 'Mod3' + | 'Mod4' + | 'Mod5' + ; + +OVERRIDE + : 'override' + ; + +NAME + : ( 'a'..'z' | 'A'..'Z' | '_' | '0'..'9' | '+' | '-' )* + ; + +WS + : + ( ' ' | '\r' | '\t' | '\u000C' | '\n') + { $channel=HIDDEN; } + ; + +COMMENT + : + '/*' .* '*/' {$channel=HIDDEN;} + ; + +LINE_COMMENT + : + ('//' | '#') ~('\n' | '\r')* '\r'? '\n' + { $channel=HIDDEN; } + ; + +/** Match various string types. Note that greedy=false implies ''' + * should make us exit loop not continue. + */ +DQSTRING + : '"' (options {greedy=false;}:~('"'))* '"' + ; diff --git a/KeyboardLayoutEditor/src/XKBGrammarWalker.g b/KeyboardLayoutEditor/src/XKBGrammarWalker.g @@ -0,0 +1,57 @@ +// XKB Grammar (X.org) +// Written by Simos Xenitellis <simos.lists@googlemail.com>, 2008. +// Version 0.8 + +tree grammar XKBGrammarWalker; + +options +{ + language = Python; + tokenVocab = XKBGrammar; + ASTLabelType = CommonTree; +} + +layout + : ^(LAYOUT symbols+) + ; + +symbols + : ^(SYMBOLS mapType ^(MAPMATERIAL mapMaterial+)) + ; + +mapType + : ^(MAPTYPE ^(MAPOPTIONS MAPOPTS+) ^(MAPNAME DQSTRING)) + ; + +mapMaterial + : ^(TOKEN_INCLUDE DQSTRING) + | ^(TOKEN_NAME DQSTRING) + | ^(TOKEN_KEY_TYPE NAME? ^(VALUE DQSTRING)) + | ^(TOKEN_KEY OVERRIDE? ^(KEYCODEX NAME) keyelements+) + | ^(TOKEN_MODIFIER_MAP STATE keycode+) + | ^(TOKEN_VIRTUAL_MODIFIERS NAME+) + ; + +keycode + : ^(KEYCODE NAME) + | ^(KEYCODEX NAME) + ; + +keyelements + : ^(ELEM_KEYSYMS DQSTRING) + | ^(ELEM_KEYSYMGROUP ^(VALUE NAME+)) + | ^(ELEM_VIRTUALMODS NAME) + | ^(ELEM_OVERLAY NAME keycode) + ; + +mapopts + : 'default' + | 'hidden' + | 'partial' + | 'alphanumeric_keys' + | 'keypad_keys' + | 'function_keys' + | 'modifier_keys' + | 'alternate_group' + | 'xkb_symbols' + ; diff --git a/KeyboardLayoutEditor/src/aliases b/KeyboardLayoutEditor/src/aliases @@ -0,0 +1,99 @@ + +// keycode aliases for phonetic keyboard maps + +default +xkb_keycodes "qwerty" { + + alias <LatQ> = <AD01>; + alias <LatW> = <AD02>; + alias <LatE> = <AD03>; + alias <LatR> = <AD04>; + alias <LatT> = <AD05>; + alias <LatY> = <AD06>; + alias <LatU> = <AD07>; + alias <LatI> = <AD08>; + alias <LatO> = <AD09>; + alias <LatP> = <AD10>; + + alias <LatA> = <AC01>; + alias <LatS> = <AC02>; + alias <LatD> = <AC03>; + alias <LatF> = <AC04>; + alias <LatG> = <AC05>; + alias <LatH> = <AC06>; + alias <LatJ> = <AC07>; + alias <LatK> = <AC08>; + alias <LatL> = <AC09>; + + alias <LatZ> = <AB01>; + alias <LatX> = <AB02>; + alias <LatC> = <AB03>; + alias <LatV> = <AB04>; + alias <LatB> = <AB05>; + alias <LatN> = <AB06>; + alias <LatM> = <AB07>; +}; + +xkb_keycodes "azerty" { + + alias <LatA> = <AD01>; + alias <LatZ> = <AD02>; + alias <LatE> = <AD03>; + alias <LatR> = <AD04>; + alias <LatT> = <AD05>; + alias <LatY> = <AD06>; + alias <LatU> = <AD07>; + alias <LatI> = <AD08>; + alias <LatO> = <AD09>; + alias <LatP> = <AD10>; + + alias <LatQ> = <AC01>; + alias <LatS> = <AC02>; + alias <LatD> = <AC03>; + alias <LatF> = <AC04>; + alias <LatG> = <AC05>; + alias <LatH> = <AC06>; + alias <LatJ> = <AC07>; + alias <LatK> = <AC08>; + alias <LatL> = <AC09>; + alias <LatM> = <AC10>; + + alias <LatW> = <AB01>; + alias <LatX> = <AB02>; + alias <LatC> = <AB03>; + alias <LatV> = <AB04>; + alias <LatB> = <AB05>; + alias <LatN> = <AB06>; +}; + +xkb_keycodes "qwertz" { + + alias <LatQ> = <AD01>; + alias <LatW> = <AD02>; + alias <LatE> = <AD03>; + alias <LatR> = <AD04>; + alias <LatT> = <AD05>; + alias <LatZ> = <AD06>; + alias <LatU> = <AD07>; + alias <LatI> = <AD08>; + alias <LatO> = <AD09>; + alias <LatP> = <AD10>; + + alias <LatA> = <AC01>; + alias <LatS> = <AC02>; + alias <LatD> = <AC03>; + alias <LatF> = <AC04>; + alias <LatG> = <AC05>; + alias <LatH> = <AC06>; + alias <LatJ> = <AC07>; + alias <LatK> = <AC08>; + alias <LatL> = <AC09>; + + alias <LatY> = <AB01>; + alias <LatX> = <AB02>; + alias <LatC> = <AB03>; + alias <LatV> = <AB04>; + alias <LatB> = <AB05>; + alias <LatN> = <AB06>; + alias <LatM> = <AB07>; +}; diff --git a/KeyboardLayoutEditor/src/evdev b/KeyboardLayoutEditor/src/evdev @@ -0,0 +1,302 @@ +// translation from evdev scancodes to something resembling xfree86 keycodes. + +default xkb_keycodes "evdev" { + minimum = 8; + maximum = 255; + + # Added for pc105 compatibility + <LSGT> = 94; + + <TLDE> = 49; + <AE01> = 10; + <AE02> = 11; + <AE03> = 12; + <AE04> = 13; + <AE05> = 14; + <AE06> = 15; + <AE07> = 16; + <AE08> = 17; + <AE09> = 18; + <AE10> = 19; + <AE11> = 20; + <AE12> = 21; + <BKSP> = 22; + + <TAB> = 23; + <AD01> = 24; + <AD02> = 25; + <AD03> = 26; + <AD04> = 27; + <AD05> = 28; + <AD06> = 29; + <AD07> = 30; + <AD08> = 31; + <AD09> = 32; + <AD10> = 33; + <AD11> = 34; + <AD12> = 35; + <BKSL> = 51; + <RTRN> = 36; + + <CAPS> = 66; + <AC01> = 38; + <AC02> = 39; + <AC03> = 40; + <AC04> = 41; + <AC05> = 42; + <AC06> = 43; + <AC07> = 44; + <AC08> = 45; + <AC09> = 46; + <AC10> = 47; + <AC11> = 48; + + <LFSH> = 50; + <AB01> = 52; + <AB02> = 53; + <AB03> = 54; + <AB04> = 55; + <AB05> = 56; + <AB06> = 57; + <AB07> = 58; + <AB08> = 59; + <AB09> = 60; + <AB10> = 61; + <RTSH> = 62; + + <LALT> = 64; + <LCTL> = 37; + <SPCE> = 65; + <RCTL> = 105; + <RALT> = 108; + // Microsoft keyboard extra keys + <LWIN> = 133; + <RWIN> = 134; + <COMP> = 135; + alias <MENU> = <COMP>; + + <ESC> = 9; + <FK01> = 67; + <FK02> = 68; + <FK03> = 69; + <FK04> = 70; + <FK05> = 71; + <FK06> = 72; + <FK07> = 73; + <FK08> = 74; + <FK09> = 75; + <FK10> = 76; + <FK11> = 95; + <FK12> = 96; + + <PRSC> = 107; + // <SYRQ> = 107; + <SCLK> = 78; + <PAUS> = 127; + // <BRK> = 419; + + <INS> = 118; + <HOME> = 110; + <PGUP> = 112; + <DELE> = 119; + <END> = 115; + <PGDN> = 117; + + <UP> = 111; + <LEFT> = 113; + <DOWN> = 116; + <RGHT> = 114; + + <NMLK> = 77; + <KPDV> = 106; + <KPMU> = 63; + <KPSU> = 82; + + <KP7> = 79; + <KP8> = 80; + <KP9> = 81; + <KPAD> = 86; + + <KP4> = 83; + <KP5> = 84; + <KP6> = 85; + + <KP1> = 87; + <KP2> = 88; + <KP3> = 89; + <KPEN> = 104; + + <KP0> = 90; + <KPDL> = 91; + <KPEQ> = 125; + + <FK13> = 191; + <FK14> = 192; + <FK15> = 193; + <FK16> = 194; + <FK17> = 195; + <FK18> = 196; + <FK19> = 197; + <FK20> = 198; + <FK21> = 199; + <FK22> = 200; + <FK23> = 201; + <FK24> = 202; + + // Keys that are generated on Japanese keyboards + + <HZTG> = 93; // Hankaku/Zenkakau toggle + <HKTG> = 101; // Hiragana/Katakana toggle + <AB11> = 211; // backslash/underscore + <HENK> = 100; // Henkan + <MUHE> = 102; // Muhenkan + <AE13> = 132; // Yen + <KATA> = 98; // Katakana + <HIRA> = 99; // Hiragana + <JPCM> = 103; // KPJPComma + <RO> = 97; // Romaji + + // Keys that are generated on Korean keyboards + + <HNGL> = 130; // Hangul Latin toggle + <HJCV> = 131; // Hangul to Hanja conversion + + // Solaris compatibility + + alias <LMTA> = <LWIN>; + alias <RMTA> = <RWIN>; + <MUTE> = 121; + <VOL-> = 122; + <VOL+> = 123; + <POWR> = 124; + <STOP> = 136; + <AGAI> = 137; + <PROP> = 138; + <UNDO> = 139; + <FRNT> = 140; + <COPY> = 141; + <OPEN> = 142; + <PAST> = 143; + <FIND> = 144; + <CUT> = 145; + <HELP> = 146; + + // Extended keys that may be generated on "Internet" keyboards. + // evdev has standardize names for these. + + <LNFD> = 109; // #define KEY_LINEFEED 101 + <I120> = 120; // #define KEY_MACRO 112 + <I126> = 126; // #define KEY_KPPLUSMINUS 118 + <I129> = 129; // #define KEY_KPCOMMA 121 + <I147> = 147; // #define KEY_MENU 139 + <I148> = 148; // #define KEY_CALC 140 + <I149> = 149; // #define KEY_SETUP 141 + <I150> = 150; // #define KEY_SLEEP 142 + <I151> = 151; // #define KEY_WAKEUP 143 + <I152> = 152; // #define KEY_FILE 144 + <I153> = 153; // #define KEY_SENDFILE 145 + <I154> = 154; // #define KEY_DELETEFILE 146 + <I155> = 155; // #define KEY_XFER 147 + <I156> = 156; // #define KEY_PROG1 148 + <I157> = 157; // #define KEY_PROG2 149 + <I158> = 158; // #define KEY_WWW 150 + <I159> = 159; // #define KEY_MSDOS 151 + <I160> = 160; // #define KEY_COFFEE 152 + <I161> = 161; // #define KEY_DIRECTION 153 + <I162> = 162; // #define KEY_CYCLEWINDOWS 154 + <I163> = 163; // #define KEY_MAIL 155 + <I164> = 164; // #define KEY_BOOKMARKS 156 + <I165> = 165; // #define KEY_COMPUTER 157 + <I166> = 166; // #define KEY_BACK 158 + <I167> = 167; // #define KEY_FORWARD 159 + <I168> = 168; // #define KEY_CLOSECD 160 + <I169> = 169; // #define KEY_EJECTCD 161 + <I170> = 170; // #define KEY_EJECTCLOSECD 162 + <I171> = 171; // #define KEY_NEXTSONG 163 + <I172> = 172; // #define KEY_PLAYPAUSE 164 + <I173> = 173; // #define KEY_PREVIOUSSONG 165 + <I174> = 174; // #define KEY_STOPCD 166 + <I175> = 175; // #define KEY_RECORD 167 + <I176> = 176; // #define KEY_REWIND 168 + <I177> = 177; // #define KEY_PHONE 169 + <I178> = 178; // #define KEY_ISO 170 + <I179> = 179; // #define KEY_CONFIG 171 + <I180> = 180; // #define KEY_HOMEPAGE 172 + <I181> = 181; // #define KEY_REFRESH 173 + <I182> = 182; // #define KEY_EXIT 174 + <I183> = 183; // #define KEY_MOVE 175 + <I184> = 184; // #define KEY_EDIT 176 + <I185> = 185; // #define KEY_SCROLLUP 177 + <I186> = 186; // #define KEY_SCROLLDOWN 178 + <I187> = 187; // #define KEY_KPLEFTPAREN 179 + <I188> = 188; // #define KEY_KPRIGHTPAREN 180 + <I189> = 189; // #define KEY_NEW 181 + <I190> = 190; // #define KEY_REDO 182 + <I208> = 208; // #define KEY_PLAYCD 200 + <I209> = 209; // #define KEY_PAUSECD 201 + <I210> = 210; // #define KEY_PROG3 202 + //<I211> = 211; // #define KEY_PROG4 203 conflicts with AB11 + <I213> = 213; // #define KEY_SUSPEND 205 + <I214> = 214; // #define KEY_CLOSE 206 + <I215> = 215; // #define KEY_PLAY 207 + <I216> = 216; // #define KEY_FASTFORWARD 208 + <I217> = 217; // #define KEY_BASSBOOST 209 + <I218> = 218; // #define KEY_PRINT 210 + <I219> = 219; // #define KEY_HP 211 + <I220> = 220; // #define KEY_CAMERA 212 + <I221> = 221; // #define KEY_SOUND 213 + <I222> = 222; // #define KEY_QUESTION 214 + <I223> = 223; // #define KEY_EMAIL 215 + <I224> = 224; // #define KEY_CHAT 216 + <I225> = 225; // #define KEY_SEARCH 217 + <I226> = 226; // #define KEY_CONNECT 218 + <I227> = 227; // #define KEY_FINANCE 219 + <I228> = 228; // #define KEY_SPORT 220 + <I229> = 229; // #define KEY_SHOP 221 + <I230> = 230; // #define KEY_ALTERASE 222 + <I231> = 231; // #define KEY_CANCEL 223 + <I232> = 232; // #define KEY_BRIGHTNESSDOWN 224 + <I233> = 233; // #define KEY_BRIGHTNESSUP 225 + <I234> = 234; // #define KEY_MEDIA 226 + <I235> = 235; // #define KEY_SWITCHVIDEOMODE 227 + <I236> = 236; // #define KEY_KBDILLUMTOGGLE 228 + <I237> = 237; // #define KEY_KBDILLUMDOWN 229 + <I238> = 238; // #define KEY_KBDILLUMUP 230 + <I239> = 239; // #define KEY_SEND 231 + <I240> = 240; // #define KEY_REPLY 232 + <I241> = 241; // #define KEY_FORWARDMAIL 233 + <I242> = 242; // #define KEY_SAVE 234 + <I243> = 243; // #define KEY_DOCUMENTS 235 + <I244> = 244; // #define KEY_BATTERY 236 + <I245> = 245; // #define KEY_BLUETOOTH 237 + <I246> = 246; // #define KEY_WLAN 238 + <I247> = 247; // (not defined in input.h) 239 + <I248> = 248; // #define KEY_UNKNOWN 240 + <I249> = 249; // #define KEY_VIDEO_NEXT 241 + <I250> = 250; // #define KEY_VIDEO_PREV 242 + <I251> = 251; // #define KEY_BRIGHTNESS_CYCLE 243 + <I252> = 252; // #define KEY_BRIGHTNESS_ZERO 244 + <I253> = 253; // #define KEY_DISPLAY_OFF 245 + + // Fake keycodes for virtual keys + <LVL3> = 92; + <MDSW> = 203; + <ALT> = 204; + <META> = 205; + <SUPR> = 206; + <HYPR> = 207; + + indicator 1 = "Caps Lock"; + indicator 2 = "Num Lock"; + indicator 3 = "Scroll Lock"; + indicator 4 = "Compose"; + indicator 5 = "Kana"; + indicator 6 = "Sleep"; + indicator 7 = "Suspend"; + indicator 8 = "Mute"; + indicator 9 = "Misc"; + indicator 10 = "Mail"; + indicator 11 = "Charging"; + + alias <ALGR> = <RALT>; +}; diff --git a/KeyboardLayoutEditor/src/kle-icon.svg b/KeyboardLayoutEditor/src/kle-icon.svg @@ -0,0 +1,2924 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="55.75" + height="55.75" + id="svg2" + sodipodi:version="0.32" + inkscape:version="0.46" + sodipodi:docname="kle-icon.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape" + version="1.0"> + <defs + id="defs4"> + <linearGradient + id="linearGradient3134"> + <stop + id="stop3136" + offset="0" + style="stop-color: rgb(246, 246, 246); stop-opacity: 1;" /> + <stop + id="stop3138" + offset="1" + style="stop-color: rgb(183, 183, 183); stop-opacity: 1;" /> + </linearGradient> + <linearGradient + id="linearGradient5756"> + <stop + style="stop-color: rgb(218, 218, 218); stop-opacity: 1;" + offset="0" + id="stop5758" /> + <stop + style="stop-color: rgb(183, 183, 183); stop-opacity: 1;" + offset="1" + id="stop5760" /> + </linearGradient> + <pattern + patternUnits="userSpaceOnUse" + width="295.15189" + height="83.359736" + patternTransform="translate(71.517996,14.39953)" + id="pattern7209"> + <g + id="g5203" + inkscape:label="Livello 1" + transform="matrix(0.2821302,0,0,0.2821302,-0.6005839,-122.53814)"> + <rect + style="fill:url(#linearGradient7514);fill-opacity:1;fill-rule:nonzero;stroke:#9a9a9a;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect5205" + width="1044.1549" + height="293.46548" + x="3.1287472" + y="435.33188" + rx="5" + ry="5.0000005" + inkscape:label="#rect2160" /> + <g + transform="matrix(0.582337,0,0,0.581113,112.003,382.489)" + inkscape:label="#g4203" + id="g5207"> + <rect + style="opacity:1;fill:url(#linearGradient7516);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:3.43805003;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect5209" + width="67.956474" + height="70.532257" + x="10.849505" + y="261.68634" + rx="8.5860949" + ry="8.6041832" + inkscape:label="#rect2160" /> + <text + xml:space="preserve" + style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Zekton" + x="19.733999" + y="318.48401" + id="text5211" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan5213" + x="19.733999" + y="318.48401" + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;font-family:Arial">Q</tspan></text> + </g> + <g + inkscape:label="#g4208" + transform="matrix(0.582337,0,0,0.581113,112.006,382.489)" + id="g5215"> + <rect + inkscape:label="#rect2160" + ry="8.6041832" + rx="8.5860949" + y="261.68634" + x="89.641403" + height="70.532257" + width="67.956474" + id="rect5217" + style="opacity:1;fill:url(#linearGradient7518);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:3.43805003;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> + <text + sodipodi:linespacing="100%" + id="text5219" + y="319.85901" + x="93.3853" + style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Zekton" + xml:space="preserve"><tspan + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;font-family:Arial" + y="319.85901" + x="93.3853" + id="tspan5221" + sodipodi:role="line">W</tspan></text> + </g> + <g + inkscape:label="#g4213" + transform="matrix(0.582337,0,0,0.581113,112.01,382.489)" + id="g5223"> + <rect + inkscape:label="#rect2160" + ry="8.6041832" + rx="8.5860949" + y="261.68634" + x="168.4333" + height="70.532257" + width="67.956474" + id="rect5225" + style="opacity:1;fill:url(#linearGradient7520);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:3.43805003;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> + <text + sodipodi:linespacing="100%" + id="text5227" + y="319.85901" + x="180.255" + style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Zekton" + xml:space="preserve"><tspan + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;font-family:Arial" + y="319.85901" + x="180.255" + id="tspan5229" + sodipodi:role="line">E</tspan></text> + </g> + <g + inkscape:label="#g4218" + transform="matrix(0.582337,0,0,0.581113,111.426,382.489)" + id="g5231"> + <rect + inkscape:label="#rect2160" + ry="8.6041832" + rx="8.5860949" + y="261.68634" + x="248.23535" + height="70.532257" + width="67.956474" + id="rect5233" + style="opacity:1;fill:url(#linearGradient7522);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:3.43805003;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> + <text + sodipodi:linespacing="100%" + id="text5235" + y="319.85901" + x="261.39032" + style="font-size:60.93024826px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans;-inkscape-font-specification:Sans" + xml:space="preserve"><tspan + y="319.85901" + x="261.39032" + id="tspan6449" + sodipodi:role="line">Ř</tspan></text> + </g> + <g + inkscape:label="#g4223" + transform="matrix(0.582337,0,0,0.581113,113.194,382.489)" + id="g5239"> + <rect + style="opacity:1;fill:url(#linearGradient7524);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:3.43805003;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect5241" + width="67.956474" + height="70.532257" + x="323.9968" + y="261.68634" + rx="8.5860949" + ry="8.6041832" + inkscape:label="#rect2160" /> + <text + xml:space="preserve" + style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Zekton" + x="338.319" + y="319.85901" + id="text5243" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan5245" + x="338.319" + y="319.85901" + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;font-family:Arial">T</tspan></text> + </g> + <g + inkscape:label="#g4228" + transform="matrix(0.582337,0,0,0.581113,111.433,382.489)" + id="g5247"> + <rect + inkscape:label="#rect2160" + ry="8.6041832" + rx="8.5860949" + y="261.68634" + x="405.81915" + height="70.532257" + width="67.956474" + id="rect5249" + style="opacity:1;fill:url(#linearGradient7526);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:3.43805003;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> + <text + sodipodi:linespacing="100%" + id="text5251" + y="319.85901" + x="418.60999" + style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Zekton" + xml:space="preserve"><tspan + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;font-family:Arial" + y="319.85901" + x="418.60999" + id="tspan5253" + sodipodi:role="line">Y</tspan></text> + </g> + <g + inkscape:label="#g4233" + transform="matrix(0.582337,0,0,0.581113,110.849,382.489)" + id="g5255"> + <rect + style="opacity:1;fill:url(#linearGradient7528);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:3.43805003;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect5257" + width="67.956474" + height="70.532257" + x="485.62122" + y="261.68634" + rx="8.5860949" + ry="8.6041832" + inkscape:label="#rect2160" /> + <text + xml:space="preserve" + style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Zekton" + x="496.55301" + y="319.46799" + id="text5259" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan5261" + x="496.55301" + y="319.46799" + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;font-family:Arial">U</tspan></text> + </g> + <g + inkscape:label="#g4238" + transform="matrix(0.582337,0,0,0.581113,110.852,382.489)" + id="g5263"> + <rect + inkscape:label="#rect2160" + ry="8.6041832" + rx="8.5860949" + y="261.68634" + x="564.41309" + height="70.532257" + width="67.956474" + id="rect5265" + style="opacity:1;fill:url(#linearGradient7530);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:3.43805003;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> + <text + sodipodi:linespacing="100%" + id="text5267" + y="319.85901" + x="589.39099" + style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Zekton" + xml:space="preserve"><tspan + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;font-family:Arial" + y="319.85901" + x="589.39099" + id="tspan5269" + sodipodi:role="line">I</tspan></text> + </g> + <g + inkscape:label="#g4243" + transform="matrix(0.582337,0,0,0.581113,110.856,382.489)" + id="g5271"> + <rect + style="opacity:1;fill:url(#linearGradient7532);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:3.43805003;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect5273" + width="67.956474" + height="70.532257" + x="643.20496" + y="261.68634" + rx="8.5860949" + ry="8.6041832" + inkscape:label="#rect2160" /> + <text + xml:space="preserve" + style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Zekton" + x="652.18298" + y="319.87399" + id="text5275" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan5277" + x="652.18298" + y="319.87399" + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;font-family:Arial">O</tspan></text> + </g> + <g + inkscape:label="#g4248" + transform="matrix(0.582337,0,0,0.581113,112.624,382.489)" + id="g5279"> + <rect + inkscape:label="#rect2160" + ry="8.6041832" + rx="8.5860949" + y="261.68634" + x="718.96637" + height="70.532257" + width="67.956474" + id="rect5281" + style="opacity:1;fill:url(#linearGradient7534);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:3.43805003;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> + <text + sodipodi:linespacing="100%" + id="text5283" + y="319.85901" + x="730.52301" + style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Zekton" + xml:space="preserve"><tspan + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;font-family:Arial" + y="319.85901" + x="730.52301" + id="tspan5285" + sodipodi:role="line">P</tspan></text> + </g> + <g + transform="matrix(0.582337,0,0,0.581113,129.837,382.489)" + inkscape:label="#g4358" + id="g5287"> + <rect + inkscape:label="#rect2160" + ry="8.6041832" + rx="8.5860949" + y="347.54932" + x="10.849505" + height="70.532257" + width="67.956474" + id="rect5289" + style="fill:url(#linearGradient7536);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:3.43805003;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> + <text + sodipodi:linespacing="100%" + id="text5291" + y="405.72198" + x="23.483999" + style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Zekton" + xml:space="preserve"><tspan + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;font-family:Arial" + y="405.72198" + x="23.483999" + id="tspan5293" + sodipodi:role="line">A</tspan></text> + </g> + <g + inkscape:label="#g4363" + transform="matrix(0.582337,0,0,0.581113,130.022,382.489)" + id="g5295"> + <rect + style="fill:url(#linearGradient7538);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:3.43805003;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect5297" + width="67.956474" + height="70.532257" + x="89.641403" + y="347.54932" + rx="8.5860949" + ry="8.6041832" + inkscape:label="#rect2160" /> + <text + xml:space="preserve" + style="font-size:67.02326965px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans;-inkscape-font-specification:Sans" + x="96.929756" + y="410.12659" + id="text5299" + sodipodi:linespacing="100%"><tspan + y="410.12659" + x="96.929756" + id="tspan6437" + sodipodi:role="line">Σ</tspan></text> + </g> + <g + inkscape:label="#g4368" + transform="matrix(0.582337,0,0,0.581113,130.206,382.489)" + id="g5303"> + <rect + inkscape:label="#rect2160" + ry="8.6041832" + rx="8.5860949" + y="347.54932" + x="168.4333" + height="70.532257" + width="67.956474" + id="rect5305" + style="fill:url(#linearGradient7540);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:3.43805003;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> + <text + sodipodi:linespacing="100%" + id="text5307" + y="401.31738" + x="178.537" + style="font-size:60.93024826px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans;-inkscape-font-specification:Sans" + xml:space="preserve"><tspan + y="401.31738" + x="178.537" + id="tspan6439" + sodipodi:role="line">Д</tspan></text> + </g> + <g + inkscape:label="#g4373" + transform="matrix(0.582337,0,0,0.581113,128.626,382.489)" + id="g5311"> + <rect + style="fill:url(#linearGradient7542);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:3.43805003;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect5313" + width="67.956474" + height="70.532257" + x="250.25566" + y="347.54932" + rx="8.5860949" + ry="8.6041832" + inkscape:label="#rect2160" /> + <text + xml:space="preserve" + style="font-size:73.11629486px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans;-inkscape-font-specification:Sans" + x="256.93802" + y="405.72198" + id="text5315" + sodipodi:linespacing="100%"><tspan + y="405.72198" + x="256.93802" + id="tspan6445" + sodipodi:role="line">अ</tspan></text> + </g> + <g + inkscape:label="#g4378" + transform="matrix(0.582337,0,0,0.581113,129.4,382.489)" + id="g5319"> + <rect + inkscape:label="#rect2160" + ry="8.6041832" + rx="8.5860949" + y="347.54932" + x="328.03741" + height="70.532257" + width="67.956474" + id="rect5321" + style="fill:url(#linearGradient7544);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:3.43805003;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> + <text + sodipodi:linespacing="100%" + id="text5323" + y="405.72198" + x="337.422" + style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Zekton" + xml:space="preserve"><tspan + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;font-family:Arial" + y="405.72198" + x="337.422" + id="tspan5325" + sodipodi:role="line">G</tspan></text> + </g> + <g + inkscape:label="#g4383" + transform="matrix(0.582337,0,0,0.581113,130.761,382.489)" + id="g5327"> + <rect + style="fill:url(#linearGradient7546);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:3.43805003;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect5329" + width="67.956474" + height="70.532257" + x="404.80902" + y="347.54932" + rx="8.5860949" + ry="8.6041832" + inkscape:label="#rect2160" /> + <text + xml:space="preserve" + style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Zekton" + x="415.694" + y="405.72198" + id="text5331" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan5333" + x="415.694" + y="405.72198" + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;font-family:Arial">H</tspan></text> + </g> + <g + inkscape:label="#g4388" + transform="matrix(0.582337,0,0,0.581113,128.593,382.489)" + id="g5335"> + <rect + inkscape:label="#rect2160" + ry="8.6041832" + rx="8.5860949" + y="347.54932" + x="487.64154" + height="70.532257" + width="67.956474" + id="rect5337" + style="fill:url(#linearGradient7548);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:3.43805003;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> + <text + sodipodi:linespacing="100%" + id="text5339" + y="405.33099" + x="507.245" + style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Zekton" + xml:space="preserve"><tspan + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;font-family:Arial" + y="405.33099" + x="507.245" + id="tspan5341" + sodipodi:role="line">J</tspan></text> + </g> + <g + inkscape:label="#g4393" + transform="matrix(0.582337,0,0,0.581113,129.366,382.489)" + id="g5343"> + <rect + style="fill:url(#linearGradient7550);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:3.43805003;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect5345" + width="67.956474" + height="70.532257" + x="565.42328" + y="347.54932" + rx="8.5860949" + ry="8.6041832" + inkscape:label="#rect2160" /> + <text + xml:space="preserve" + style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Zekton" + x="575.776" + y="405.72198" + id="text5347" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan5349" + x="575.776" + y="405.72198" + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;font-family:Arial">K</tspan></text> + </g> + <g + inkscape:label="#g4398" + transform="matrix(0.582337,0,0,0.581113,127.197,382.489)" + id="g5351"> + <rect + inkscape:label="#rect2160" + ry="8.6041832" + rx="8.5860949" + y="347.54932" + x="648.2558" + height="70.532257" + width="67.956474" + id="rect5353" + style="fill:url(#linearGradient7552);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:3.43805003;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> + <text + sodipodi:linespacing="100%" + id="text5355" + y="405.72198" + x="663.23401" + style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Zekton" + xml:space="preserve"><tspan + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;font-family:Arial" + y="405.72198" + x="663.23401" + id="tspan5357" + sodipodi:role="line">L</tspan></text> + </g> + <g + transform="matrix(0.582337,0,0,0.581113,166.774,382.489)" + inkscape:label="#g4482" + id="g5359"> + <rect + style="fill:url(#linearGradient7554);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:3.43805003;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect5361" + width="67.956474" + height="70.532257" + x="10.849505" + y="433.41229" + rx="8.5860949" + ry="8.6041832" + inkscape:label="#rect2160" /> + <text + xml:space="preserve" + style="font-size:67.02326965px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans;-inkscape-font-specification:Sans" + x="23.239437" + y="484.97809" + id="text5363" + sodipodi:linespacing="100%"><tspan + y="484.97809" + x="23.239437" + id="tspan6443" + sodipodi:role="line">ɀ</tspan></text> + </g> + <g + inkscape:label="#g4515" + transform="matrix(0.582337,0,0,0.581113,167.61,382.489)" + id="g5367"> + <rect + inkscape:label="#rect2160" + ry="8.6041832" + rx="8.5860949" + y="433.41229" + x="89.641403" + height="70.532257" + width="67.956474" + id="rect5369" + style="fill:url(#linearGradient7556);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:3.43805003;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> + <text + sodipodi:linespacing="100%" + id="text5371" + y="491.58499" + x="102.338" + style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Zekton" + xml:space="preserve"><tspan + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;font-family:Arial" + y="491.58499" + x="102.338" + id="tspan5373" + sodipodi:role="line">X</tspan></text> + </g> + <g + inkscape:label="#g4510" + transform="matrix(0.582337,0,0,0.581113,169.033,382.489)" + id="g5375"> + <rect + style="fill:url(#linearGradient7558);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:3.43805003;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect5377" + width="67.956474" + height="70.532257" + x="167.42316" + y="433.41229" + rx="8.5860949" + ry="8.6041832" + inkscape:label="#rect2160" /> + <text + xml:space="preserve" + style="font-size:60.93024826px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans;-inkscape-font-specification:Sans" + x="175.76634" + y="484.97809" + id="text5379" + sodipodi:linespacing="100%"><tspan + y="484.97809" + x="175.76634" + id="tspan6441" + sodipodi:role="line">ټ</tspan></text> + </g> + <g + inkscape:label="#g4505" + transform="matrix(0.582337,0,0,0.581113,169.868,382.489)" + id="g5383"> + <rect + inkscape:label="#rect2160" + ry="8.6041832" + rx="8.5860949" + y="433.41229" + x="246.21506" + height="70.532257" + width="67.956474" + id="rect5385" + style="fill:url(#linearGradient7560);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:3.43805003;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> + <text + sodipodi:linespacing="100%" + id="text5387" + y="491.58499" + x="258.95901" + style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Zekton" + xml:space="preserve"><tspan + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;font-family:Arial" + y="491.58499" + x="258.95901" + id="tspan5389" + sodipodi:role="line">V</tspan></text> + </g> + <g + inkscape:label="#g4492" + transform="matrix(0.582337,0,0,0.581113,166.585,382.489)" + id="g5391"> + <rect + style="fill:url(#linearGradient7562);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:3.43805003;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect5393" + width="67.956474" + height="70.532257" + x="332.07803" + y="433.41229" + rx="8.5860949" + ry="8.6041832" + inkscape:label="#rect2160" /> + <text + xml:space="preserve" + style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Zekton" + x="344.07199" + y="491.58499" + id="text5395" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan5397" + x="344.07199" + y="491.58499" + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;font-family:Arial">B</tspan></text> + </g> + <g + inkscape:label="#g4487" + transform="matrix(0.582337,0,0,0.581113,165.656,382.489)" + id="g5399"> + <rect + inkscape:label="#rect2160" + ry="8.6041832" + rx="8.5860949" + y="433.41229" + x="413.90039" + height="70.532257" + width="67.956474" + id="rect5401" + style="fill:url(#linearGradient7564);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:3.43805003;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> + <text + sodipodi:linespacing="100%" + id="text5403" + y="491.58499" + x="424.957" + style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Zekton" + xml:space="preserve"><tspan + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;font-family:Arial" + y="491.58499" + x="424.957" + id="tspan5405" + sodipodi:role="line">N</tspan></text> + </g> + <g + transform="matrix(0.582337,0,0,0.581113,171.785,382.489)" + inkscape:label="#g5775" + id="g5407"> + <rect + style="fill:url(#linearGradient7566);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:3.43805003;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect5409" + width="67.956474" + height="70.532257" + x="483.60089" + y="433.41229" + rx="8.5860949" + ry="8.6041832" + inkscape:label="#rect2160" /> + <text + xml:space="preserve" + style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Zekton" + x="490.97" + y="491.58499" + id="text5411" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan5413" + x="490.97" + y="491.58499" + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;font-family:Arial">M</tspan></text> + </g> + <rect + inkscape:label="#rect2160" + ry="5" + rx="5.0000005" + y="683.6593" + x="245.98868" + height="40.98719" + width="187.17503" + id="rect5415" + style="fill:url(#linearGradient7568);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> + <g + transform="matrix(0.686513,0,0,0.68539,76.5151,229.287)" + inkscape:label="#g2451" + id="g5417"> + <rect + inkscape:label="#rect2160" + ry="7.2951193" + rx="7.2831788" + y="373.93552" + x="92.651985" + height="59.801289" + width="57.644268" + id="rect5419" + style="fill:url(#linearGradient7570);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:2.9156599;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> + <text + sodipodi:linespacing="100%" + id="text5421" + y="423.436" + x="108.38" + style="font-size:20.35330009px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Zekton" + xml:space="preserve" + transform="scale(1.00023,0.999767)"><tspan + style="font-size:54.27550125px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;font-family:Arial" + y="423.436" + x="108.38" + id="tspan5423" + sodipodi:role="line">1</tspan></text> + </g> + <g + inkscape:label="#g4712" + transform="matrix(0.582337,0,0,0.581113,134.816,382.489)" + id="g5425"> + <rect + style="fill:url(#linearGradient7572);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:3.43805003;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect5427" + width="67.956474" + height="70.532257" + x="87.992363" + y="177.40062" + rx="8.5860949" + ry="8.6041832" + inkscape:label="#rect2160" /> + <text + xml:space="preserve" + style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Zekton" + x="104.924" + y="235.66701" + id="text5429" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan5431" + x="104.924" + y="235.66701" + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;font-family:Arial">2</tspan></text> + </g> + <g + inkscape:label="#g4717" + transform="matrix(0.582337,0,0,0.581113,133.333,382.489)" + id="g5433"> + <rect + style="fill:url(#linearGradient7574);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:3.43805003;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect5435" + width="67.956474" + height="70.532257" + x="169.42093" + y="177.40062" + rx="8.5860949" + ry="8.6041832" + inkscape:label="#rect2160" /> + <text + xml:space="preserve" + style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Zekton" + x="185.71201" + y="235.25999" + id="text5437" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan5439" + x="185.71201" + y="235.25999" + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;font-family:Arial">3</tspan></text> + </g> + <g + inkscape:label="#g4722" + transform="matrix(0.582337,0,0,0.581113,135.177,382.489)" + id="g5441"> + <rect + inkscape:label="#rect2160" + ry="8.6041832" + rx="8.5860949" + y="177.40062" + x="245.13521" + height="70.532257" + width="67.956474" + id="rect5443" + style="fill:url(#linearGradient7576);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:3.43805003;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> + <text + sodipodi:linespacing="100%" + id="text5445" + y="217.95471" + x="262.457" + style="font-size:54.83722305px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans;-inkscape-font-specification:Sans" + xml:space="preserve"><tspan + y="217.95471" + x="262.457" + id="tspan6447" + sodipodi:role="line">၄</tspan></text> + </g> + <g + inkscape:label="#g4727" + transform="matrix(0.582337,0,0,0.581113,136.189,382.489)" + id="g5449"> + <rect + style="fill:url(#linearGradient7578);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:3.43805003;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect5451" + width="67.956474" + height="70.532257" + x="322.27808" + y="177.40062" + rx="8.5860949" + ry="8.6041832" + inkscape:label="#rect2160" /> + <text + xml:space="preserve" + style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Zekton" + x="338.41299" + y="234.87" + id="text5453" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan5455" + x="338.41299" + y="234.87" + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;font-family:Arial">5</tspan></text> + </g> + <g + inkscape:label="#g4776" + transform="matrix(0.582337,0,0,0.581113,136.752,382.489)" + id="g5457"> + <rect + inkscape:label="#rect2160" + ry="8.6041832" + rx="8.5860949" + y="177.40062" + x="400.19199" + height="70.532257" + width="67.956474" + id="rect5459" + style="fill:url(#linearGradient7580);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:3.43805003;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> + <text + sodipodi:linespacing="100%" + id="text5461" + y="235.276" + x="416.63901" + style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Zekton" + xml:space="preserve"><tspan + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;font-family:Arial" + y="235.276" + x="416.63901" + id="tspan5463" + sodipodi:role="line">6</tspan></text> + </g> + <g + inkscape:label="#g4732" + transform="matrix(0.582337,0,0,0.581113,134.886,382.489)" + id="g5465"> + <rect + style="fill:url(#linearGradient7582);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:3.43805003;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect5467" + width="67.956474" + height="70.532257" + x="482.27808" + y="177.40062" + rx="8.5860949" + ry="8.6041832" + inkscape:label="#rect2160" /> + <text + xml:space="preserve" + style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Zekton" + x="498.397" + y="235.276" + id="text5469" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan5471" + x="498.397" + y="235.276" + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;font-family:Arial">7</tspan></text> + </g> + <g + inkscape:label="#g4737" + transform="matrix(0.582337,0,0,0.581113,134.234,382.489)" + id="g5473"> + <rect + inkscape:label="#rect2160" + ry="8.6041832" + rx="8.5860949" + y="177.40062" + x="562.27808" + height="70.532257" + width="67.956474" + id="rect5475" + style="fill:url(#linearGradient7584);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:3.43805003;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> + <text + sodipodi:linespacing="100%" + id="text5477" + y="235.276" + x="578.56897" + style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Zekton" + xml:space="preserve"><tspan + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;font-family:Arial" + y="235.276" + x="578.56897" + id="tspan5479" + sodipodi:role="line">8</tspan></text> + </g> + <g + inkscape:label="#g4750" + transform="matrix(0.582337,0,0,0.581113,132.751,382.489)" + id="g5481"> + <rect + style="fill:url(#linearGradient7586);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:3.43805003;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect5483" + width="67.956474" + height="70.532257" + x="643.70667" + y="177.40062" + rx="8.5860949" + ry="8.6041832" + inkscape:label="#rect2160" /> + <text + xml:space="preserve" + style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Zekton" + x="659.966" + y="235.276" + id="text5485" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan5487" + x="659.966" + y="235.276" + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;font-family:Arial">9</tspan></text> + </g> + <g + inkscape:label="#g4755" + transform="matrix(0.582337,0,0,0.581113,130.436,382.489)" + id="g5489"> + <rect + inkscape:label="#rect2160" + ry="8.6041832" + rx="8.5860949" + y="177.40062" + x="726.56378" + height="70.532257" + width="67.956474" + id="rect5491" + style="fill:url(#linearGradient7588);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:3.43805003;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> + <text + sodipodi:linespacing="100%" + id="text5493" + y="235.276" + x="742.948" + style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Zekton" + xml:space="preserve"><tspan + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;font-family:Arial" + y="235.276" + x="742.948" + id="tspan5495" + sodipodi:role="line">0</tspan></text> + </g> + <g + transform="matrix(0.686513,0,0,0.68539,0.98082,229.287)" + inkscape:label="#g2713" + id="g5497"> + <path + style="fill:url(#linearGradient7590);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:2.9156599;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + d="M 977.96875,445.15625 C 975.19875,445.15625 972.96875,447.38625 972.96875,450.15625 L 972.96875,499.96875 C 972.96875,502.73875 975.19875,504.96874 977.96875,504.96875 L 1002.9688,504.96875 L 1002.9688,572.8125 C 1002.9688,575.5825 1005.1988,577.8125 1007.9688,577.8125 L 1157.8125,577.8125 C 1160.5825,577.8125 1162.8125,575.5825 1162.8125,572.8125 L 1162.8125,494.21875 C 1162.8125,493.75708 1162.7098,493.33009 1162.5938,492.90625 L 1162.5938,450.15625 C 1162.5938,447.38625 1160.3637,445.15625 1157.5938,445.15625 L 977.96875,445.15625 z" + id="path5499" /> + <text + sodipodi:linespacing="100%" + id="text5501" + y="494.595" + x="973.68597" + style="font-size:20.35330009px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Zekton" + xml:space="preserve" + transform="scale(1.00023,0.999767)"><tspan + style="font-size:54.27550125px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;font-family:Arial" + y="494.595" + x="973.68597" + id="tspan5503" + sodipodi:role="line">ENTER</tspan></text> + </g> + <g + transform="matrix(0.686513,0,0,0.68539,0.98082,229.287)" + inkscape:label="#g2456" + id="g5505"> + <rect + style="fill:url(#linearGradient7592);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:2.9156599;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect5507" + width="119.07284" + height="59.801289" + x="7.4271193" + y="373.93552" + rx="7.2831783" + ry="7.2951193" + inkscape:label="#rect2160" /> + <text + transform="scale(1.00023,0.999767)" + xml:space="preserve" + style="font-size:20.35330009px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Zekton" + x="10.0222" + y="423.35599" + id="text5509" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan5511" + x="10.0222" + y="423.35599" + style="font-size:54.27550125px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;font-family:Arial">ESC</tspan></text> + </g> + <g + transform="matrix(0.686513,0,0,0.68539,0.98082,229.287)" + inkscape:label="#g2662" + id="g5513"> + <rect + style="fill:url(#linearGradient7594);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:2.9156599;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect5515" + width="57.644268" + height="59.801289" + x="135.76682" + y="373.93552" + rx="7.2831788" + ry="7.2951193" + inkscape:label="#rect2160" /> + <text + transform="scale(1.00023,0.999767)" + xml:space="preserve" + style="font-size:20.35330009px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Zekton" + x="157.21001" + y="439.284" + id="text5517" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan5519" + x="157.21001" + y="439.284" + style="font-size:54.27550125px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;font-family:Arial">`</tspan></text> + </g> + <g + transform="matrix(0.686513,0,0,0.68539,3.02743,229.287)" + inkscape:label="#g2516" + id="g5521"> + <rect + style="fill:url(#linearGradient7596);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:2.9156599;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect5523" + width="57.644268" + height="59.801289" + x="868.80811" + y="373.93552" + rx="7.2831788" + ry="7.2951193" + inkscape:label="#rect2160" /> + <text + xml:space="preserve" + style="font-size:20.35330009px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Zekton" + x="888.37097" + y="417.98999" + id="text5525" + sodipodi:linespacing="100%" + transform="scale(1.00023,0.999767)"><tspan + sodipodi:role="line" + id="tspan5527" + x="888.37097" + y="417.98999" + style="font-size:54.27550125px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;font-family:Arial">-</tspan></text> + </g> + <g + inkscape:label="#g4755" + transform="matrix(0.582337,0,0,0.581113,222.306,382.489)" + id="g5529"> + <rect + inkscape:label="#rect2160" + ry="8.6041832" + rx="8.5860949" + y="177.40062" + x="726.56378" + height="70.532257" + width="67.956474" + id="rect5531" + style="fill:url(#linearGradient7598);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:3.43805003;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> + <text + sodipodi:linespacing="100%" + id="text5533" + y="235.276" + x="742.948" + style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Zekton" + xml:space="preserve"><tspan + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;font-family:Arial" + y="235.276" + x="742.948" + id="tspan5535" + sodipodi:role="line">+</tspan></text> + </g> + <g + transform="matrix(0.686513,0,0,0.68539,0.980707,229.287)" + inkscape:label="#g2526" + id="g5537"> + <rect + style="fill:url(#linearGradient7600);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:2.9156599;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect5539" + width="153.35855" + height="59.801289" + x="1005.6117" + y="373.93552" + rx="7.2831788" + ry="7.2951193" + inkscape:label="#rect2160" /> + <text + xml:space="preserve" + style="font-size:20.35330009px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Zekton" + x="1008.75" + y="423.35599" + id="text5541" + sodipodi:linespacing="100%" + transform="scale(1.00023,0.999767)"><tspan + sodipodi:role="line" + id="tspan5543" + x="1008.75" + y="423.35599" + style="font-size:54.27550125px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;font-family:Arial">BKSP</tspan></text> + </g> + <g + transform="matrix(0.686513,0,0,0.68539,0.98082,229.287)" + inkscape:label="#g2558" + id="g5545"> + <rect + inkscape:label="#rect2160" + ry="7.2951193" + rx="7.2831788" + y="445.3978" + x="8.366272" + height="59.801289" + width="153.35855" + id="rect5547" + style="fill:url(#linearGradient7602);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:2.9156599;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> + <text + sodipodi:linespacing="100%" + id="text5549" + y="494.83499" + x="35.030201" + style="font-size:20.35330009px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Zekton" + xml:space="preserve" + transform="scale(1.00023,0.999767)"><tspan + style="font-size:54.27550125px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;text-anchor:start;font-family:Arial" + y="494.83499" + x="35.030201" + id="tspan5551" + sodipodi:role="line">TAB</tspan></text> + </g> + <g + transform="matrix(0.686513,0,0,0.68539,-19.4073,229.287)" + inkscape:label="#g2598" + id="g5553"> + <rect + style="fill:url(#linearGradient7604);fill-opacity:1;fill-rule:nonzero;stroke:#d6d6d6;stroke-width:2.9156599;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect5555" + width="57.644268" + height="59.801289" + x="869.02838" + y="445.3978" + rx="7.2831788" + ry="7.2951193" + inkscape:label="#rect2160" /> + <text + xml:space="preserve" + style="font-size:20.35330009px;font-style:normal;font-variant:nor