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:
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