pax_global_header00006660000000000000000000000064133750701160014515gustar00rootroot0000000000000052 comment=8e51b70449b724e5120eb404ec77a1014b658b97 ibus-sunpinyin-2.0.3+git20181120/000077500000000000000000000000001337507011600161115ustar00rootroot00000000000000ibus-sunpinyin-2.0.3+git20181120/CMakeLists.txt000066400000000000000000000014121337507011600206470ustar00rootroot00000000000000# CMakeLists.txt: cmake config file for ibus-sunpinyin set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/modules/") if(COMMAND cmake_policy) cmake_policy(SET CMP0005 NEW) endif(COMMAND cmake_policy) cmake_minimum_required(VERSION 2.6) project(SUNPINYIN) set(PACKAGE ibus-sunpinyin) set(GETTEXT_PACKAGE ${PACKAGE}) set(PACKAGE_NAME ${PACKAGE}) set(PACKAGE_BUGREPORT "sunpinyin-developers@googlegroups.com") set(PACKAGE_TARNAME ${PACKAGE}) set(VERSION "2.0.2") set(PACKAGE_VERSION ${VERSION}) set(PACKAGE_STRING "${PACKAGE} ${VERSION}") include(Paths) install(DIRECTORY icons DESTINATION "${DATA_DIR}") add_subdirectory (src) add_subdirectory (setup) add_subdirectory (data) add_subdirectory (po) ibus-sunpinyin-2.0.3+git20181120/COPYING000066400000000000000000000000571337507011600171460ustar00rootroot00000000000000Refer to LGPL.LICENSE and OPENSOLARIS.LICENSE. ibus-sunpinyin-2.0.3+git20181120/LGPL.LICENSE000066400000000000000000000647041337507011600176660ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, 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 this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), 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 distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser 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 Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! -------------------------------------------------------------------- NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) For Covered Software in this distribution, this License shall be governed by the laws of the State of California (excluding conflict-of-law provisions). Any litigation relating to this License shall be subject to the jurisdiction of the Federal Courts of the Northern District of California and the state courts of the State of California, with venue lying in Santa Clara County, California. ibus-sunpinyin-2.0.3+git20181120/OPENSOLARIS.LICENSE000066400000000000000000000443521337507011600207230ustar00rootroot00000000000000COMMON DEVELOPMENT AND DISTRIBUTION LICENSE Version 1.0 1. Definitions. 1.1. "Contributor" means each individual or entity that creates or contributes to the creation of Modifications. 1.2. "Contributor Version" means the combination of the Original Software, prior Modifications used by a Contributor (if any), and the Modifications made by that particular Contributor. 1.3. "Covered Software" means (a) the Original Software, or (b) Modifications, or (c) the combination of files containing Original Software with files containing Modifications, in each case including portions thereof. 1.4. "Executable" means the Covered Software in any form other than Source Code. 1.5. "Initial Developer" means the individual or entity that first makes Original Software available under this License. 1.6. "Larger Work" means a work which combines Covered Software or portions thereof with code not governed by the terms of this License. 1.7. "License" means this document. 1.8. "Licensable" means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently acquired, any and all of the rights conveyed herein. 1.9. "Modifications" means the Source Code and Executable form of any of the following: A. Any file that results from an addition to, deletion from or modification of the contents of a file containing Original Software or previous Modifications; B. Any new file that contains any part of the Original Software or previous Modifications; or C. Any new file that is contributed or otherwise made available under the terms of this License. 1.10. "Original Software" means the Source Code and Executable form of computer software code that is originally released under this License. 1.11. "Patent Claims" means any patent claim(s), now owned or hereafter acquired, including without limitation, method, process, and apparatus claims, in any patent Licensable by grantor. 1.12. "Source Code" means (a) the common form of computer software code in which modifications are made and (b) associated documentation included in or with such code. 1.13. "You" (or "Your") means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License. For legal entities, "You" includes any entity which controls, is controlled by, or is under common control with You. For purposes of this definition, "control" means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. 2. License Grants. 2.1. The Initial Developer Grant. Conditioned upon Your compliance with Section 3.1 below and subject to third party intellectual property claims, the Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive license: (a) under intellectual property rights (other than patent or trademark) Licensable by Initial Developer, to use, reproduce, modify, display, perform, sublicense and distribute the Original Software (or portions thereof), with or without Modifications, and/or as part of a Larger Work; and (b) under Patent Claims infringed by the making, using or selling of Original Software, to make, have made, use, practice, sell, and offer for sale, and/or otherwise dispose of the Original Software (or portions thereof). (c) The licenses granted in Sections 2.1(a) and (b) are effective on the date Initial Developer first distributes or otherwise makes the Original Software available to a third party under the terms of this License. (d) Notwithstanding Section 2.1(b) above, no patent license is granted: (1) for code that You delete from the Original Software, or (2) for infringements caused by: (i) the modification of the Original Software, or (ii) the combination of the Original Software with other software or devices. 2.2. Contributor Grant. Conditioned upon Your compliance with Section 3.1 below and subject to third party intellectual property claims, each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license: (a) under intellectual property rights (other than patent or trademark) Licensable by Contributor to use, reproduce, modify, display, perform, sublicense and distribute the Modifications created by such Contributor (or portions thereof), either on an unmodified basis, with other Modifications, as Covered Software and/or as part of a Larger Work; and (b) under Patent Claims infringed by the making, using, or selling of Modifications made by that Contributor either alone and/or in combination with its Contributor Version (or portions of such combination), to make, use, sell, offer for sale, have made, and/or otherwise dispose of: (1) Modifications made by that Contributor (or portions thereof); and (2) the combination of Modifications made by that Contributor with its Contributor Version (or portions of such combination). (c) The licenses granted in Sections 2.2(a) and 2.2(b) are effective on the date Contributor first distributes or otherwise makes the Modifications available to a third party. (d) Notwithstanding Section 2.2(b) above, no patent license is granted: (1) for any code that Contributor has deleted from the Contributor Version; (2) for infringements caused by: (i) third party modifications of Contributor Version, or (ii) the combination of Modifications made by that Contributor with other software (except as part of the Contributor Version) or other devices; or (3) under Patent Claims infringed by Covered Software in the absence of Modifications made by that Contributor. 3. Distribution Obligations. 3.1. Availability of Source Code. Any Covered Software that You distribute or otherwise make available in Executable form must also be made available in Source Code form and that Source Code form must be distributed only under the terms of this License. You must include a copy of this License with every copy of the Source Code form of the Covered Software You distribute or otherwise make available. You must inform recipients of any such Covered Software in Executable form as to how they can obtain such Covered Software in Source Code form in a reasonable manner on or through a medium customarily used for software exchange. 3.2. Modifications. The Modifications that You create or to which You contribute are governed by the terms of this License. You represent that You believe Your Modifications are Your original creation(s) and/or You have sufficient rights to grant the rights conveyed by this License. 3.3. Required Notices. You must include a notice in each of Your Modifications that identifies You as the Contributor of the Modification. You may not remove or alter any copyright, patent or trademark notices contained within the Covered Software, or any notices of licensing or any descriptive text giving attribution to any Contributor or the Initial Developer. 3.4. Application of Additional Terms. You may not offer or impose any terms on any Covered Software in Source Code form that alters or restricts the applicable version of this License or the recipients' rights hereunder. You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Software. However, you may do so only on Your own behalf, and not on behalf of the Initial Developer or any Contributor. You must make it absolutely clear that any such warranty, support, indemnity or liability obligation is offered by You alone, and You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of warranty, support, indemnity or liability terms You offer. 3.5. Distribution of Executable Versions. You may distribute the Executable form of the Covered Software under the terms of this License or under the terms of a license of Your choice, which may contain terms different from this License, provided that You are in compliance with the terms of this License and that the license for the Executable form does not attempt to limit or alter the recipient's rights in the Source Code form from the rights set forth in this License. If You distribute the Covered Software in Executable form under a different license, You must make it absolutely clear that any terms which differ from this License are offered by You alone, not by the Initial Developer or Contributor. You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of any such terms You offer. 3.6. Larger Works. You may create a Larger Work by combining Covered Software with other code not governed by the terms of this License and distribute the Larger Work as a single product. In such a case, You must make sure the requirements of this License are fulfilled for the Covered Software. 4. Versions of the License. 4.1. New Versions. Sun Microsystems, Inc. is the initial license steward and may publish revised and/or new versions of this License from time to time. Each version will be given a distinguishing version number. Except as provided in Section 4.3, no one other than the license steward has the right to modify this License. 4.2. Effect of New Versions. You may always continue to use, distribute or otherwise make the Covered Software available under the terms of the version of the License under which You originally received the Covered Software. If the Initial Developer includes a notice in the Original Software prohibiting it from being distributed or otherwise made available under any subsequent version of the License, You must distribute and make the Covered Software available under the terms of the version of the License under which You originally received the Covered Software. Otherwise, You may also choose to use, distribute or otherwise make the Covered Software available under the terms of any subsequent version of the License published by the license steward. 4.3. Modified Versions. When You are an Initial Developer and You want to create a new license for Your Original Software, You may create and use a modified version of this License if You: (a) rename the license and remove any references to the name of the license steward (except to note that the license differs from this License); and (b) otherwise make it clear that the license contains terms which differ from this License. 5. DISCLAIMER OF WARRANTY. COVERED SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED SOFTWARE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED SOFTWARE IS WITH YOU. SHOULD ANY COVERED SOFTWARE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. 6. TERMINATION. 6.1. This License and the rights granted hereunder will terminate automatically if You fail to comply with terms herein and fail to cure such breach within 30 days of becoming aware of the breach. Provisions which, by their nature, must remain in effect beyond the termination of this License shall survive. 6.2. If You assert a patent infringement claim (excluding declaratory judgment actions) against Initial Developer or a Contributor (the Initial Developer or Contributor against whom You assert such claim is referred to as "Participant") alleging that the Participant Software (meaning the Contributor Version where the Participant is a Contributor or the Original Software where the Participant is the Initial Developer) directly or indirectly infringes any patent, then any and all rights granted directly or indirectly to You by such Participant, the Initial Developer (if the Initial Developer is not the Participant) and all Contributors under Sections 2.1 and/or 2.2 of this License shall, upon 60 days notice from Participant terminate prospectively and automatically at the expiration of such 60 day notice period, unless if within such 60 day period You withdraw Your claim with respect to the Participant Software against such Participant either unilaterally or pursuant to a written agreement with Participant. 6.3. In the event of termination under Sections 6.1 or 6.2 above, all end user licenses that have been validly granted by You or any distributor hereunder prior to termination (excluding licenses granted to You by any distributor) shall survive termination. 7. LIMITATION OF LIABILITY. UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED SOFTWARE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOST PROFITS, LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. 8. U.S. GOVERNMENT END USERS. The Covered Software is a "commercial item," as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer software" (as that term is defined at 48 C.F.R. 252.227-7014(a)(1)) and "commercial computer software documentation" as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government End Users acquire Covered Software with only those rights set forth herein. This U.S. Government Rights clause is in lieu of, and supersedes, any other FAR, DFAR, or other clause or provision that addresses Government rights in computer software under this License. 9. MISCELLANEOUS. This License represents the complete agreement concerning subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. This License shall be governed by the law of the jurisdiction specified in a notice contained within the Original Software (except to the extent applicable law, if any, provides otherwise), excluding such jurisdiction's conflict-of-law provisions. Any litigation relating to this License shall be subject to the jurisdiction of the courts located in the jurisdiction and venue specified in a notice contained within the Original Software, with the losing party responsible for costs, including, without limitation, court costs and reasonable attorneys' fees and expenses. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not apply to this License. You agree that You alone are responsible for compliance with the United States export administration regulations (and the export control laws and regulation of any other countries) when You use, distribute or otherwise make available any Covered Software. 10. RESPONSIBILITY FOR CLAIMS. As between Initial Developer and the Contributors, each party is responsible for claims and damages arising, directly or indirectly, out of its utilization of rights under this License and You agree to work with Initial Developer and Contributors to distribute such responsibility on an equitable basis. Nothing herein is intended or shall be deemed to constitute any admission of liability. -------------------------------------------------------------------- NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) For Covered Software in this distribution, this License shall be governed by the laws of the State of California (excluding conflict-of-law provisions). Any litigation relating to this License shall be subject to the jurisdiction of the Federal Courts of the Northern District of California and the state courts of the State of California, with venue lying in Santa Clara County, California. ibus-sunpinyin-2.0.3+git20181120/README000066400000000000000000000001741337507011600167730ustar00rootroot00000000000000ibus-sunpinyin === ibus-sunpinyin is a wrapper around SunPinyin which enables user to use SunPinyin with IBus framework. ibus-sunpinyin-2.0.3+git20181120/SConstruct000066400000000000000000000135331337507011600201500ustar00rootroot00000000000000import os sources = ['src/debug.cpp', 'src/engine.cpp', 'src/ibus_portable.cpp', 'src/imi_ibus_win.cpp', 'src/main.cpp', 'src/sunpinyin_config.cpp', 'src/sunpinyin_engine.cpp', 'src/sunpinyin_engine_proxy.cpp', 'src/sunpinyin_lookup_table.cpp', 'src/sunpinyin_property.cpp'] locales = ['zh_CN'] cflags = '-O2 -g -pipe ' version = '2.0.3' AddOption('--prefix', dest='prefix', metavar='DIR', help='installation prefix') AddOption('--libdir', dest='libdir', metavar='DIR', help='installation libdir') AddOption('--libexecdir', dest='libexecdir', metavar='DIR', help='installation libexecdir') AddOption('--datadir', dest='datadir', metavar='DIR', help='installation datadir') AddOption('--rpath', dest='rpath', metavar='DIR', help='encode rpath in the executables') opts = Variables('configure.conf') opts.Add('PREFIX', default='/usr/local') opts.Add('LIBDIR', default='/usr/local/lib') opts.Add('LIBEXECDIR', default='/usr/local/lib') opts.Add('DATADIR', default='/usr/local/share') def PassVariables(envvar, env): for (x, y) in envvar: if x in os.environ: print 'Warning: you\'ve set %s in the environmental variable!' % x env[y] = os.environ[x] env = Environment(ENV=os.environ, CFLAGS=cflags, CXXFLAGS=cflags, CPPPATH=['.'], tools=['default', 'textfile']) opts.Update(env) if GetOption('prefix') is not None: env['PREFIX'] = GetOption('prefix') env['LIBDIR'] = env['PREFIX'] + '/lib' env['LIBEXECDIR'] = env['PREFIX'] + '/lib/' env['DATADIR'] = env['PREFIX'] + '/share/' if GetOption('libdir') is not None: env['LIBDIR'] = GetOption('libdir') if GetOption('libexecdir') is not None: env['LIBEXECDIR'] = GetOption('libexecdir') if GetOption('datadir') is not None: env['DATADIR'] = GetOption('datadir') opts.Save('configure.conf', env) envvar = [('CC', 'CC'), ('CXX', 'CXX'), ('CFLAGS', 'CFLAGS'), ('CXXFLAGS', 'CXXFLAGS'), ('LDFLAGS', 'LINKFLAGS')] PassVariables(envvar, env) data_dir = env['DATADIR'] + '/ibus-sunpinyin' icons_dir = env['DATADIR'] + '/ibus-sunpinyin/icons' bin_dir = env['LIBEXECDIR'] + '/ibus-sunpinyin' gettext_package = 'ibus-sunpinyin' extra_cflags = ' -DIBUS_SUNPINYIN_LOCALEDIR=\'"%s"\'' % (env['DATADIR'] + '/locale') extra_cflags += ' -DIBUS_SUNPINYIN_ICON_DIR=\'"%s"\'' % icons_dir extra_cflags += ' -DLIBEXECDIR=\'"%s"\'' % bin_dir extra_cflags += ' -DGETTEXT_PACKAGE=\'"%s"\'' % gettext_package env.Append(CFLAGS=extra_cflags) env.Append(CXXFLAGS=extra_cflags) if GetOption('rpath') is not None: env.Append(LINKFLAGS=' -Wl,-R -Wl,%s' % GetOption('rpath')) # #==============================configure================================ # def CheckPKGConfig(context, version='0.12.0'): context.Message( 'Checking for pkg-config... ' ) ret = context.TryAction('pkg-config --atleast-pkgconfig-version=%s' % version)[0] context.Result(ret) return ret def CheckPKG(context, name): context.Message( 'Checking for %s... ' % name ) ret = context.TryAction('pkg-config --exists \'%s\'' % name)[0] context.Result(ret) return ret conf = Configure(env, custom_tests={'CheckPKGConfig' : CheckPKGConfig, 'CheckPKG' : CheckPKG }) def DoConfigure(): if GetOption('clean'): return if not conf.CheckPKGConfig(): Exit(1) if not conf.CheckPKG('ibus-1.0'): Exit(1) if not conf.CheckPKG('sunpinyin-2.0'): Exit(1) env = conf.Finish() env.ParseConfig('pkg-config ibus-1.0 sunpinyin-2.0 --libs --cflags') DoConfigure() env.Program('ibus-engine-sunpinyin', source=sources) for locale in locales: mo = 'po/%s.mo' % (locale,) env.Command(mo, [], 'msgfmt po/%s.po -o %s' % (locale, mo)) sub = {'@LIBEXEC_DIR@': bin_dir, '@DATA_DIR@' : data_dir, '@ICON_DIR@': icons_dir, '@VERSION@' : version, '@INSTALL_PREFIX@': env['PREFIX']} env.Substfile('data/sunpinyin.xml.in', SUBST_DICT=sub) env.Substfile('setup/config.py.in', SUBST_DICT=sub) env.Substfile('setup/ibus-setup-sunpinyin.in', SUBST_DICT=sub) # #==============================install================================ # def DoInstall(): libexec_target = env.Install(bin_dir, ['ibus-engine-sunpinyin', 'setup/ibus-setup-sunpinyin']) for exec_bin in libexec_target: env.AddPostAction(exec_bin, Chmod(str(exec_bin), 0755)) setup_target = env.Install(data_dir + '/setup', ['setup/setup.xml', 'setup/main.py', 'setup/config.py']) icons_target = env.Install(icons_dir, ['icons/cnpunc.svg', 'icons/eng.svg', 'icons/enpunc.svg', 'icons/fullwidth.svg', 'icons/halfwidth.svg', 'icons/han.svg', 'icons/setup.svg', 'icons/sunpinyin-logo.png']) component_target = env.Install(env['DATADIR'] + '/ibus/component', 'data/sunpinyin.xml') locale_targets = [] for locale in locales: path = env['DATADIR'] + '/locale/%s/LC_MESSAGES/%s.mo' % \ (locale, gettext_package) locale_targets.append(env.InstallAs(path, 'po/%s.mo' % (locale,))) env.Alias('install-libexec', [libexec_target, setup_target]) env.Alias('install-data', [icons_target, component_target]) env.Alias('install-locale', locale_targets) DoInstall() env.Alias('install', ['install-libexec', 'install-data', 'install-locale']) # -*- indent-tabs-mode: nil -*- vim:et:ts=4 ibus-sunpinyin-2.0.3+git20181120/cmake/000077500000000000000000000000001337507011600171715ustar00rootroot00000000000000ibus-sunpinyin-2.0.3+git20181120/cmake/modules/000077500000000000000000000000001337507011600206415ustar00rootroot00000000000000ibus-sunpinyin-2.0.3+git20181120/cmake/modules/FindSunPinyin.cmake000066400000000000000000000016441337507011600244050ustar00rootroot00000000000000# - Try to find SunPinyin # Once done, this will define # # SunPinyin_FOUND - system has iBus # SunPinyin_INCLUDE_DIRS - the iBus include directories # SunPinyin_LIBRARIES - link these to use iBus include(LibFindMacros) # Dependencies # Use pkg-config to get hints about paths libfind_pkg_check_modules(SunPinyin_PKGCONF sunpinyin-2.0) # Include dir find_path(SunPinyin_INCLUDE_DIR NAMES sunpinyin.h PATHS ${SunPinyin_PKGCONF_INCLUDE_DIRS} ) # Finally the library itself find_library(SunPinyin_LIBRARY NAMES sunpinyin PATHS ${SunPinyin_PKGCONF_LIBRARY_DIRS} ) # Set the include dir variables and the libraries and let libfind_process do the # rest. # NOTE: Singular variables for this library, plural for libraries this this lib # depends on. set(SunPinyin_PROCESS_INCLUDES SunPinyin_INCLUDE_DIR) set(SunPinyin_PROCESS_LIBS SunPinyin_LIBRARY) libfind_process(SunPinyin) # -*- indent-tabs-mode: nil -*- vim:et:ts=4 ibus-sunpinyin-2.0.3+git20181120/cmake/modules/FindiBus.cmake000066400000000000000000000015171337507011600233520ustar00rootroot00000000000000# - Try to find iBus # Once done, this will define # # iBus_FOUND - system has iBus # iBus_INCLUDE_DIRS - the iBus include directories # iBus_LIBRARIES - link these to use iBus include(LibFindMacros) # Dependencies # Use pkg-config to get hints about paths libfind_pkg_check_modules(iBus_PKGCONF ibus-1.0) # Include dir find_path(iBus_INCLUDE_DIR NAMES ibus.h PATHS ${iBus_PKGCONF_INCLUDE_DIRS} ) # Finally the library itself find_library(iBus_LIBRARY NAMES ibus PATHS ${iBus_PKGCONF_LIBRARY_DIRS} ) # Set the include dir variables and the libraries and let libfind_process do the # rest. # NOTE: Singular variables for this library, plural for libraries this this lib # depends on. set(iBus_PROCESS_INCLUDES iBus_INCLUDE_DIR) set(iBus_PROCESS_LIBS iBus_LIBRARY) libfind_process(iBus) # -*- indent-tabs-mode: nil -*- vim:et:ts=4 ibus-sunpinyin-2.0.3+git20181120/cmake/modules/Gettext.cmake000066400000000000000000000141061337507011600232710ustar00rootroot00000000000000# Gettext support: Create/Update pot file and # # To use: INCLUDE(Gettext) # # Most of the gettext support code is from FindGettext.cmake of cmake, # but it is included here because: # # 1. Some system like RHEL5 does not have FindGettext.cmake # 2. Bug of GETTEXT_CREATE_TRANSLATIONS make it unable to be include in 'All' # 3. It does not support xgettext # #=================================================================== # Variables: # XGETTEXT_OPTIONS: Options pass to xgettext # Default: --language=C --keyword=_ --keyword=N_ --keyword=C_:1c,2 --keyword=NC_:1c,2 # GETTEXT_MSGMERGE_EXECUTABLE: the full path to the msgmerge tool. # GETTEXT_MSGFMT_EXECUTABLE: the full path to the msgfmt tool. # GETTEXT_FOUND: True if gettext has been found. # XGETTEXT_EXECUTABLE: the full path to the xgettext. # XGETTEXT_FOUND: True if xgettext has been found. # #=================================================================== # Macros: # GETTEXT_CREATE_POT(potFile # [OPTION xgettext_options] # SRC list_of_source_file_that_contains_msgid # ) # # Generate .pot file. # OPTION xgettext_options: Override XGETTEXT_OPTIONS # # * Produced targets: pot_file # #------------------------------------------------------------------- # GETTEXT_CREATE_TRANSLATIONS ( outputFile [ALL] locale1 ... localeN # [COMMENT comment] ) # # This will create a target "translations" which will convert the # given input po files into the binary output mo file. If the # ALL option is used, the translations will also be created when # building the default target. # # * Produced targets: translations #------------------------------------------------------------------- FIND_PROGRAM(GETTEXT_MSGMERGE_EXECUTABLE msgmerge) FIND_PROGRAM(GETTEXT_MSGFMT_EXECUTABLE msgfmt) FIND_PROGRAM(XGETTEXT_EXECUTABLE xgettext) IF (GETTEXT_MSGMERGE_EXECUTABLE AND GETTEXT_MSGFMT_EXECUTABLE ) SET(GETTEXT_FOUND TRUE) ELSE (GETTEXT_MSGMERGE_EXECUTABLE AND GETTEXT_MSGFMT_EXECUTABLE) SET(GETTEXT_FOUND FALSE) IF (GetText_REQUIRED) MESSAGE(FATAL_ERROR "GetText not found") ENDIF (GetText_REQUIRED) ENDIF (GETTEXT_MSGMERGE_EXECUTABLE AND GETTEXT_MSGFMT_EXECUTABLE ) IF(XGETTEXT_EXECUTABLE) SET(XGETTEXT_FOUND TRUE) ELSE(XGETTEXT_EXECUTABLE) MESSAGE(STATUS "xgettext not found.") SET(XGETTTEXT_FOUND FALSE) ENDIF(XGETTEXT_EXECUTABLE) IF(NOT DEFINED XGETTEXT_OPTIONS) SET(XGETTEXT_OPTIONS --keyword=_ --keyword=N_ --keyword=C_:1c,2 --keyword=NC_:1c,2 -s) ENDIF(NOT DEFINED XGETTEXT_OPTIONS) IF(XGETTEXT_FOUND) MACRO(GETTEXT_CREATE_POT _potFile _pot_options ) SET(_xgettext_options_list) SET(_src_list) SET(_src_list_abs) SET(_stage "SRC") FOREACH(_pot_option ${_pot_options} ${ARGN}) IF(_pot_option STREQUAL "OPTION") SET(_stage "OPTION") ELSEIF(_pot_option STREQUAL "SRC") SET(_stage "SRC") ELSE(_pot_option STREQUAL "OPTION") IF(_stage STREQUAL "OPTION") SET(_xgettext_options_list ${_xgettext_options_list} ${_pot_option}) ELSE(_stage STREQUAL "OPTION") FILE(RELATIVE_PATH _relFile ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${_pot_option}) GET_FILENAME_COMPONENT(_absFile ${_pot_option} ABSOLUTE) SET(_src_list ${_src_list} ${_relFile}) SET(_src_list_abs ${_src_list_abs} ${_absFile}) ENDIF(_stage STREQUAL "OPTION") ENDIF(_pot_option STREQUAL "OPTION") ENDFOREACH(_pot_option ${_pot_options} ${ARGN}) IF (_xgettext_options_list) SET(_xgettext_options ${_xgettext_options_list}) ELSE(_xgettext_options_list) SET(_xgettext_options ${XGETTEXT_OPTIONS}) ENDIF(_xgettext_options_list) #MESSAGE("${XGETTEXT_EXECUTABLE} ${_xgettext_options_list} -o ${_potFile} ${_src_list}") ADD_CUSTOM_COMMAND(OUTPUT ${_potFile} COMMAND ${XGETTEXT_EXECUTABLE} ${_xgettext_options} -o ${_potFile} ${_src_list} DEPENDS ${_src_list_abs} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) ADD_CUSTOM_TARGET(pot_file COMMAND ${XGETTEXT_EXECUTABLE} ${_xgettext_options_list} -o ${_potFile} ${_src_list} DEPENDS ${_src_list_abs} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Extract translatable messages to ${_potFile}" ) ENDMACRO(GETTEXT_CREATE_POT _potFile _pot_options) MACRO(GETTEXT_CREATE_TRANSLATIONS _potFile _firstLang) SET(_gmoFiles) GET_FILENAME_COMPONENT(_potBasename ${_potFile} NAME_WE) GET_FILENAME_COMPONENT(_absPotFile ${_potFile} ABSOLUTE) SET(_addToAll) SET(_is_comment FALSE) FOREACH (_currentLang ${_firstLang} ${ARGN}) IF(_currentLang STREQUAL "ALL") SET(_addToAll "ALL") ELSEIF(_currentLang STREQUAL "COMMENT") SET(_is_comment TRUE) ELSEIF(_is_comment) SET(_is_comment FALSE) SET(_comment ${_currentLang}) ELSE() SET(_lang ${_currentLang}) GET_FILENAME_COMPONENT(_absFile ${_currentLang}.po ABSOLUTE) GET_FILENAME_COMPONENT(_abs_PATH ${_absFile} PATH) SET(_gmoFile ${CMAKE_CURRENT_BINARY_DIR}/${_lang}.gmo) #MESSAGE("_absFile=${_absFile} _abs_PATH=${_abs_PATH} _lang=${_lang} curr_bin=${CMAKE_CURRENT_BINARY_DIR}") ADD_CUSTOM_COMMAND( OUTPUT ${_gmoFile} COMMAND ${GETTEXT_MSGMERGE_EXECUTABLE} --quiet --update --backup=none -s ${_absFile} ${_absPotFile} COMMAND ${GETTEXT_MSGFMT_EXECUTABLE} -o ${_gmoFile} ${_absFile} DEPENDS ${_absPotFile} ${_absFile} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) INSTALL(FILES ${_gmoFile} DESTINATION share/locale/${_lang}/LC_MESSAGES RENAME ${_potBasename}.mo) SET(_gmoFiles ${_gmoFiles} ${_gmoFile}) ENDIF() ENDFOREACH (_currentLang ) IF(DEFINED _comment) ADD_CUSTOM_TARGET(translations ${_addToAll} DEPENDS ${_gmoFiles} COMMENT ${_comment}) ELSE(DEFINED _comment) ADD_CUSTOM_TARGET(translations ${_addToAll} DEPENDS ${_gmoFiles}) ENDIF(DEFINED _comment) ENDMACRO(GETTEXT_CREATE_TRANSLATIONS ) ENDIF(XGETTEXT_FOUND) # -*- indent-tabs-mode: nil -*- vim:et:ts=4 ibus-sunpinyin-2.0.3+git20181120/cmake/modules/LibFindMacros.cmake000066400000000000000000000101161337507011600243160ustar00rootroot00000000000000# Works the same as find_package, but forwards the "REQUIRED" and "QUIET" arguments # used for the current package. For this to work, the first parameter must be the # prefix of the current package, then the prefix of the new package etc, which are # passed to find_package. macro (libfind_package PREFIX) set (LIBFIND_PACKAGE_ARGS ${ARGN}) if (${PREFIX}_FIND_QUIETLY) set (LIBFIND_PACKAGE_ARGS ${LIBFIND_PACKAGE_ARGS} QUIET) endif (${PREFIX}_FIND_QUIETLY) if (${PREFIX}_FIND_REQUIRED) set (LIBFIND_PACKAGE_ARGS ${LIBFIND_PACKAGE_ARGS} REQUIRED) endif (${PREFIX}_FIND_REQUIRED) find_package(${LIBFIND_PACKAGE_ARGS}) endmacro (libfind_package) # CMake developers made the UsePkgConfig system deprecated in the same release (2.6) # where they added pkg_check_modules. Consequently I need to support both in my scripts # to avoid those deprecated warnings. Here's a helper that does just that. # Works identically to pkg_check_modules, except that no checks are needed prior to use. macro (libfind_pkg_check_modules PREFIX PKGNAME) if (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4) include(UsePkgConfig) pkgconfig(${PKGNAME} ${PREFIX}_INCLUDE_DIRS ${PREFIX}_LIBRARY_DIRS ${PREFIX}_LDFLAGS ${PREFIX}_CFLAGS) else (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4) find_package(PkgConfig) if (PKG_CONFIG_FOUND) pkg_check_modules(${PREFIX} ${PKGNAME}) endif (PKG_CONFIG_FOUND) endif (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4) endmacro (libfind_pkg_check_modules) # Do the final processing once the paths have been detected. # If include dirs are needed, ${PREFIX}_PROCESS_INCLUDES should be set to contain # all the variables, each of which contain one include directory. # Ditto for ${PREFIX}_PROCESS_LIBS and library files. # Will set ${PREFIX}_FOUND, ${PREFIX}_INCLUDE_DIRS and ${PREFIX}_LIBRARIES. # Also handles errors in case library detection was required, etc. macro (libfind_process PREFIX) # Skip processing if already processed during this run if (NOT ${PREFIX}_FOUND) # Start with the assumption that the library was found set (${PREFIX}_FOUND TRUE) # Process all includes and set _FOUND to false if any are missing foreach (i ${${PREFIX}_PROCESS_INCLUDES}) if (${i}) set (${PREFIX}_INCLUDE_DIRS ${${PREFIX}_INCLUDE_DIRS} ${${i}}) mark_as_advanced(${i}) else (${i}) set (${PREFIX}_FOUND FALSE) endif (${i}) endforeach (i) # Process all libraries and set _FOUND to false if any are missing foreach (i ${${PREFIX}_PROCESS_LIBS}) if (${i}) set (${PREFIX}_LIBRARIES ${${PREFIX}_LIBRARIES} ${${i}}) mark_as_advanced(${i}) else (${i}) set (${PREFIX}_FOUND FALSE) endif (${i}) endforeach (i) # Print message and/or exit on fatal error if (${PREFIX}_FOUND) if (NOT ${PREFIX}_FIND_QUIETLY) message (STATUS "Found ${PREFIX} ${${PREFIX}_VERSION}") endif (NOT ${PREFIX}_FIND_QUIETLY) else (${PREFIX}_FOUND) if (${PREFIX}_FIND_REQUIRED) foreach (i ${${PREFIX}_PROCESS_INCLUDES} ${${PREFIX}_PROCESS_LIBS}) message("${i}=${${i}}") endforeach (i) message (FATAL_ERROR "Required library ${PREFIX} NOT FOUND.\nInstall the library (dev version) and try again. If the library is already installed, use ccmake to set the missing variables manually.") endif (${PREFIX}_FIND_REQUIRED) endif (${PREFIX}_FOUND) endif (NOT ${PREFIX}_FOUND) endmacro (libfind_process) macro(libfind_library PREFIX basename) set(TMP "") if(MSVC80) set(TMP -vc80) endif(MSVC80) if(MSVC90) set(TMP -vc90) endif(MSVC90) set(${PREFIX}_LIBNAMES ${basename}${TMP}) if(${ARGC} GREATER 2) set(${PREFIX}_LIBNAMES ${basename}${TMP}-${ARGV2}) string(REGEX REPLACE "\\." "_" TMP ${${PREFIX}_LIBNAMES}) set(${PREFIX}_LIBNAMES ${${PREFIX}_LIBNAMES} ${TMP}) endif(${ARGC} GREATER 2) find_library(${PREFIX}_LIBRARY NAMES ${${PREFIX}_LIBNAMES} PATHS ${${PREFIX}_PKGCONF_LIBRARY_DIRS} ) endmacro(libfind_library) # -*- indent-tabs-mode: nil -*- vim:et:ts=4 ibus-sunpinyin-2.0.3+git20181120/cmake/modules/Paths.cmake000066400000000000000000000010041337507011600227150ustar00rootroot00000000000000if(NOT DEFINED LIBEXEC_DIR) set(LIBEXEC_DIR "${CMAKE_INSTALL_PREFIX}/libexec") endif() add_definitions(-DLIBEXECDIR="${LIBEXEC_DIR}") set(INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") set(DATA_DIR "${CMAKE_INSTALL_PREFIX}/share/${PACKAGE}") set(ICON_DIR "${DATA_DIR}/icons") add_definitions(-DIBUS_SUNPINYIN_ICON_DIR="${ICON_DIR}" -DGETTEXT_PACKAGE="${GETTEXT_PACKAGE}" -DIBUS_SUNPINYIN_LOCALEDIR="${CMAKE_INSTALL_PREFIX}/share/locale") # -*- indent-tabs-mode: nil -*- vim:et:ts=4 ibus-sunpinyin-2.0.3+git20181120/data/000077500000000000000000000000001337507011600170225ustar00rootroot00000000000000ibus-sunpinyin-2.0.3+git20181120/data/CMakeLists.txt000066400000000000000000000004331337507011600215620ustar00rootroot00000000000000configure_file(${CMAKE_CURRENT_SOURCE_DIR}/sunpinyin.xml.in ${CMAKE_CURRENT_BINARY_DIR}/sunpinyin.xml) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/sunpinyin.xml DESTINATION "${CMAKE_INSTALL_PREFIX}/share/ibus/component") # -*- indent-tabs-mode: nil -*- vim:et:ts=4 ibus-sunpinyin-2.0.3+git20181120/data/sunpinyin.xml.in000066400000000000000000000017011337507011600222040ustar00rootroot00000000000000 org.freedesktop.IBus.SunPinyin SunPinyin Component @LIBEXEC_DIR@/ibus-engine-sunpinyin --ibus @VERSION@ Kov Chai <tchaikov@gmail.com> LGPL http://opensolaris.org/os/project/input-method/ ibus-sunpinyin sunpinyin zh_CN LGPL Kov Chai <tchaikov@gmail.com> @ICON_DIR@/sunpinyin-logo.png us SunPinyin SunPinyin Input Method 99 @LIBEXEC_DIR@/ibus-setup-sunpinyin ibus-sunpinyin-2.0.3+git20181120/icons/000077500000000000000000000000001337507011600172245ustar00rootroot00000000000000ibus-sunpinyin-2.0.3+git20181120/icons/cnpunc.svg000066400000000000000000000035061337507011600212370ustar00rootroot00000000000000 ibus-sunpinyin-2.0.3+git20181120/icons/eng.svg000066400000000000000000000030651337507011600205220ustar00rootroot00000000000000 ibus-sunpinyin-2.0.3+git20181120/icons/enpunc.svg000066400000000000000000000026151337507011600212410ustar00rootroot00000000000000 , . ibus-sunpinyin-2.0.3+git20181120/icons/fullwidth.svg000066400000000000000000000051561337507011600217560ustar00rootroot00000000000000 image/svg+xml ibus-sunpinyin-2.0.3+git20181120/icons/halfwidth.svg000066400000000000000000000106351337507011600217240ustar00rootroot00000000000000 image/svg+xml ibus-sunpinyin-2.0.3+git20181120/icons/han.svg000066400000000000000000000030551337507011600205160ustar00rootroot00000000000000 ibus-sunpinyin-2.0.3+git20181120/icons/setup.svg000066400000000000000000000246521337507011600211160ustar00rootroot00000000000000 image/svg+xml Jakub Steiner http://jimmac.musichall.cz Emblem System emblem system library crucial base ibus-sunpinyin-2.0.3+git20181120/icons/sunpinyin-logo.png000066400000000000000000004644171337507011600227440ustar00rootroot00000000000000PNG  IHDRl pHYs   IDATx`\6|YEL)&{KxIBBKIHBB(i@BH $P^б4S [VudY]<3w]J+Y2ivΜ)̙sx,˒/~/i.gg)OC\j}dg"46O;m,,W{1ǢrʫH"&@ĮXEbŀ8-D6O~F<6î>zwa@!;@\τ> cSU~; r*<&-T8"bEq? Xd#7yȳs:$ Pڍ<,KkWl"Ļ\%6l[\*i+?YSm"^" D9B^}4#ٌEEyMI4%D[5'7M+$Ej 2렝Ks#Yq*=zA-xJ9r /<-ߌHlk#h!*S&*Σ^vbؘ҇_UyJ.7 ]jTr0n 8Kȓkb[1*>1ևL R %r0Ιgu3Ptll!mՃʻE@R0c'* RqM)1L;8Wm]wGOxsse(t~ ٸڷ XR5Rʏ1v')%u48BN)ΎF2-n4ٲlxM9E;ʄs{%@ۖఴT°֕0Ľ3n DN"&;,zl{^:|q%#ԉgwrP,MTE&7tNrD@zK|#J3=9mj V˨YoR`Zh%tvj Ap}m?vnC<Z&_MZ<N6D)rU2fRJ'}JzӀp$#l}&|!0g{c8,Gπ8C2/o9DG͌EH?͏'c4&dlߞЃUY sTU"R q ꦢ_zd4,QHZ >xֹTJ9oMx&Y~)/c[s* qUT"O$ 1_q @d~V4R@CJ8@#\AUKm)G2޴. [rt 1eJTlpwG IGG9B)l4T!Ǖ38!nr5s#GJsE%Y/(Z@U1 Gi)${A&Bd#?Y_Hy@i5i[* e#_ xƏrNxӬ1wsM1;k oj%t.I뎷:DPM%HWxrg Ұ/e3(;8 `8HĒ+eOixJʀ?ٽ5D:-1g9_>hu%FX99i{9IrS1Ε2 vg%՟*V(k£ۄэz rLr6UL%M?8Qm@0Huȟ2Z1`&9ϿmKս@mRt60 :~%[/-L~_(]N P 8w=xIfu u?:+ؒ`V4k(=p*$aȻF qY;-DA6U@exXwZ__&ɸ_/\0 Ut[2I{Ԧ1JK A>ݧ q|$AHhB w3t4"O^[55Ptڤ% ttw߼=j{"{7?mi;u 9D,D} 7^}  zb$)Aȸuuu[GʦYt~<~ihJ?rMr( Yow]zg A[rS(ǾUD4zkkSLF 0p[nm[_[V$1a⍫x!]M T+*c͓{ݟȗ>xR<r&tZ=Br'㻏Zp$g!TJ\z#LPE8#>cGU[=Ev9x)?@h٦CTݞS^?2yJJbJϠkGI޳W$f#]`0zY__ hjj>LR)&1%pZA/y8pXp!Z)Z!#8^-%G>}{ꇨ#vޮ|F˪ϗy[*t=Z<(Zm+,++ '[4/K6841xq9كIUWat[\1"6!k i_$')7n] !=y3` Ǝ M_\>F^k2&/'7z3gʞ0*Euj\)o~v)*-En W!WӾzפ`mH[a鞳n ^Y./ѝ]Z \}zguk`#r ʨ)^)lO6g%Z'HxB;JOk@=sBcL9#ڤ2r7y#@6CSFT$Uxwܳ1$ xriVdYV漙3wÿwJxK_9uQZߋQ+v@o8 lZ88&_x5+Nt쏜+2#T3Jirڞnt]⎽s_boxo:vLQ =mbub cQByӻO7_x[3fd'F,ky -EyVcNLv+<c6z |-D1$|QJX7ca 6T4%0^@VA}C9S;yw?_,σY_]ϙ0a(,)ƽ%orЂjQLH:o\w*p[K >wCm}'>Bp,6>^!~f'2wqujk_E~b4S)S[O_ƴc Da9ByzoP'zO1i([~0J}Џ< `Gpt?,5u K9#?}72,3!+n?yC1efCgFSg" `*tt򒼷O޼&0g&\tņ1>.9G0B$ld󵳬傯x薹sS;;'[aOBkHXpa?R]S.ϸea)AƱxb(3N?Oo'iC^xp,ζo#7` ޒc) r?z2suQ\ǾC%iK rGv % 6>Np|TK Pig9d,D6 wxFn禽oF)" #C'u>>yv+) w|$J:.Y`q~@xxBSHa]"1SڀeXQƕ"F%zT:rl^&jR+H(TlwogQv&np +D7"7Ha6o6^̈8B=$L*: է3Y3~W`a41|XP|*h%hJZ9nk$$ozt}#n0zX׾M;9BAeT5"$MLXC!{q0`ıУKv8tbmzY4J:MAs\!n9 Gdka%4:y&5ыQ%ގ[{Aluʢ|ںĚi o\#Kۨ}q;oBSӲX%Μ#+jU`A%%BY)a6NJɳ'}WNKM 3d?%ʈ6G#tom–[)lĈx:6IR2`,/ ~'ϝ^t#A= Ԙ~m']6I!VjBظ,`"9nWg`W5Vm5rs*e;EPR'3|ΜˁQr@rgD`7?,$bǪ, l::m(;gYXQu}φEҗ^cm4Ji/ݍ Qq@N eϟ* )eqTCW#ϑokǏIegy+HgM mWU9vIW>Hh~]!mrf^ --D:gZ>; Ka*66 ׃PBeU_8HΜw?N"ŠqC]! Im]h1`ֹ?\'w ?X L_.пQ6f˭/RbU}ݒti2J\A[Hofγ]jl<]x-zj EIc2{s_%ڭ >>]Yyf'Ÿ;?ՌػD ~/J%vh9jL6Es=3g^=u1ZyfP-Js%dhTonx[Ľ IDATnO` j~񊍊h%f{W},p~+QscaBmXFOW䗜I%?.`o,JȕM0Ȱ997˩S:7kZVLs7ўvEM SIvVAҙ7ɴM> A9LU`'LUPyC4S Y'E.^ N:wSao*3G9xdM5 KgшTZ,].BnTחU,HJN"28Zޤ@r}sDIS夠@'&s*ٶ",3@6qNM2` 11gB>ܬ;yN]`?6 D_I[i݂bq:B_!S3- @K%<ž7Ff׬!9HCz\zfP=mc`"D_4)=dM|{BEGnƤ >db. [? V}W,M֍Ń1W9{R큛Y'Κ3nYsʚނbB8N|`XY ܛ_(ksH~ɿ|xt%Z,NpZ(+QFysp;ͧ3!+nmOdW 0o>3UrwHϔ;^(숫{gxix7|ږ=uXR?~LّE~`ݧ?Qq4U+ݐF랔Ǐmjd`KNx?R{R3gm_ia,([|%Z6ϒZyO&F ؂`;a2e/ KkpxHh<~Fv*P-E`8ofxByWYW.=0׿^poO+f[}-{m:;p>Lv I3\{k(kj`(Pm9e@F}Ľ5MKg](cmĪ`-Ql~x"_ɞ\w Ԫި|MR3EaAb.:GU. |K`Md!=\4)J0lBFjcj=|xRǓg] g&_֓p/Co 9v>f+=Ҩe\ZAx'$9L~>q[U{K|Y'y-.m+zNӧ3C&xrUkɥv\V3a~sZm S~zttr_9>)0㪈LGXOj2IV>źeEpSa&媌U?Ejœ㗦뗮Ё ~'6d&Jawoқ4 g锁a8b+S[M8ZS&2wk4w]s*,Wm0? wZ'慝r_7!ss a !gH1w87iTZw|/~f|iXK)f~j )~W^ 3< #>/+ T3 <&]&lx*CDUa8@ 6Ccê^65L>oNf: q[_T옎@8p |s s } ty$VW bbb b3r;7'z |(`֤Հ]qX3B?8F*2@nS5oVIN3$Sh nP`-GґDqU$\}F#?30"eeV=;Yɢc7QSXTC"R%l@6l*b8H`vmSi]b_oMjuL[ $u[‰Vj>JC+%LKqY8lbcM[k[8B6w,m[vnK Eanv&gxD:\D<<$HV`8tQ,apՅ&O_H~~l);KS۔ ?uoV7q*@r)ЬBBX,B.#pp~`JH35^$*(_[Lx<9ER0b wH{2(߰R*Qf,K͜Avy8Cƣ7ogƚBopD[w(>?V+nKUƂ;vƪQ?Rvx.?b ? X?:~IѮ3TRghPZ |ϽEQ@]F]=PZeyf 3^YUDM<>2 or}pqU+=68dWD,( IgC'ѷcS*RnbЅ暵RpkM=цp 'a%r!qϿ=&%e`#+sꔩ_ɻKԉ]]j5&Wǵ"tipQ.i5ݾ‹ݙm̓3sey 5s߄+FeqoU ""cRT)! 6`%+'ln "q aI i0B] @NS=bUϜ}9mR66'Dl&7?W:v7/1E{ LkO~~f\\˫C1|mc4Ue\ W VS^FA <#!u&ջ-C;W&pk 90khRɘt@J]Yׅs@>d%>7\| K-h'Ϛq!Z(z$̰W P$"ų0hKcp:OGzc SN$ T(3,) 7F8Q `Do5I?,cDZ~$o|J}<ᗗA$<ղD_hJJڭ 74,y^c}4 @1Y8ZYgValEh 2Zcg{Z3aaox S,˒p_gF-ez w~'5򀃐or6[OHWt<#?.:]m$'( ׾ҞOk,'_Pg˳Zp} ?g6&(0]aNA.#Ӱ=xfc^8H9A% nvj%-{=p2ڥN3w!V30ɇ(AIiaLjT`|? ڞ,MrEjwvפ{qz{fQUcPI ,w d .?=n874A8xi>ݞkSdwӇo!ᕓe-]yMvaLIDXJĚRcJkp|b]\,,Y$-(rΓϮ}_z깕ݧBA *8Ҧ#|6&.kQ>VaT</a},BPz*o .´&_`f* CcqSlTYm8Ox QrejDTڞ 1B'|!ݻGVJ#Vh N2}qy:LdQ ˒OwJo̓C@$YH&YT&n&!!/Bܲ˧GgG!zMRJX x %m<ɑoIbMMwǟ|0>0rtDo?B[CxUvyɺVM91V-V{X5FKUuբvlȣf os*G-0J߱-%ă~=>_LÉiޱGlV0~f9~s5ɇ;qZ Y>f`Ee/Ϝd~.7 h&c⨴=?0usGt>{{r9Oeju3㌂gZ<S?)'\0I&TYj@ 2Ep33eawnrqH zwيSdթ?$Z҉ohF$eU1.}i[ Aֵ$(f%Y:ޭ3L+F'v겋4e{pY uGל(բKDlW?AEP.L@ґgG0.{ynJ͕?PjR &!&.S l7y */u>w'7XpX w]q_@5D[PO %U_mj>ۤơbݫ*+}Pa=;}Izőz&!S,抋$3FZZt!qi[ZVmWS;J[ԉ|]fH\~\`ƑN1ouI]V&atHOo+ {g_#o .r``64l pϦ+֬Tw]{gfo:#€y!,䱗ȑ,Cda׋qF؆` F凖pw-O>F w)P7y̛$pb>2R Qǽ /yx5Uuu+Q?&$/'Yt/3yOej3 p )Vx'GQ]:w~k.?€)Iˌ'^g?~3z(.(%@Қ Mjf\.WdqV̻%5~=';>&#T_ʋv5ӈȜi'MD 3yѫyi죓Z$[,->f LKC-7xwa(&.//5zEǪdT"to&31BoIƖ|uފOUZWg{dTw زU5}FTLWb3hRrk{Ij>P/ʀ$?I. GxRѷK V,T.2f䇾6VwKۛ[0Lp'Zrǧݠıcn SځqfL`j9?=Nbh߈m1-Z c qҫx>wB330a//+xOsQj̇lٺ߀1(`g%p'kվ -^>zb<ʩP gNlY#R4.{_]N4=N6;/mKw D-Brk)OɳϾ k 7sTX)60sJ ArO Lywڪ9[ڐJ\BvO*,/S1b H-Nv u Srz iQ9 m !k"ZlA0P0³FqWS&J^!OsQD^>mC)2#<9hnk~Ci ɑ#>eXƾ(& qHog a`uxd8cWISuH+q)7%7ߋ"p8@By0hWȶ1ND͑a/Ե/t4YK 'zPg m@A(a.&lo*T:*O7siz]1Z?ac~hd A1<2e˧J@K֏6lhzjx{IH߄kxW@He @/A~Bye#2U`.m'sU|?}To %{vKD$1f4bGGKM <7kRgSf-Å}P< z|۞ʥK7[kxp<-w,CG|DlUsv;Rzi`e|]=ie_EWL ZvJhNjd Jz}BAώ1hD׵H 4Hj!yNȆ6k!`2/P|9amf|폁?ԄmYA;F:"mmZ{O_gDl,Bfc-Vk ~Uَ-A֓g<6\`C IDAT" +Ǝ.Gxb 9 P<|zNZ͍υK!0+Z1 FmY]քw~7Fz;P >0bo~:p&6,z,Ɓ q'%SG1`;O!q>" &9vنZ s:I!LS }&Ltuu9ĩOՍ{QsrrP(er͊'O T<wLiQ*d Fy?Z8L|vg( Bjx$!>;LpmB)|B0nRVHD~}sI*DlaDϷd?}n--aPۉ]R;f/Pb!M6/`[^^^TS8S:/zqt > xxkmW׾!XyaGҁ=4;w=z'/o::=q+_ߺ.W=Ç˙Ooö֏0"\Ӯ5eܝR 0>W]𸃏=o\ۤh nWCs`+-owI]Jazp{T} mS AArswǒ h}8O-;:#bw-Xvg0Ɗ{c4^U䱳_05jTqq^^>Lx=NRs Gx[W |tP`8ȷ =99%lܺuO@}1/|1XdGjSvۥvݝ~ 7-?_uOG?>_X W#'^췛x\){/4yy} {Ttb'$~3~s Y|՗eTB` Z|˟[fY//[6 7gA:>zyWizj(h<g ;_Q`RuVw3pX%oT,zs /?s?Pӻ/;GudO&*C׌]}F v8Pc#H#)<n\!8 {+F9xg[EEf`^DZiwt6k5֒:>٭koh ^'SaԏEx4d ^:b\ ~NgU0<' 4#M 6y~B3_&KqMU;0&B cO*]aWY8B/%Xt^Pbg8K&p NFCX!?@7#PFk&t&&tԍ#@ʋ4H?;8!m n&yse71sH)sS?& iq.)`5ϊ q`CyrøY~ 7ҩAy*rXThiҽ!:` Byȳ32(W|Ԍ3@C<@kDT B6Zb.w<-tI8rn{UzFs\?Uj ?!ϋbJA4ƻFZ4 9WiMa)HBh\Z0Yݻ7ֶ(Kc:R8lH&8EC|#n10. SifΟp1j$|$qwS6tdO~fY*D )Ɗo#Gԫy6J|\iX{D AA4C"R0V3ޅlslaPD1Bl";8CP^ς6 k2鷟񚱀%yӇgx&*wrԚL`YB 6$]ia> nXT˟ dy0>OhmxBbøV~i20!,ISͧ[*u>I\7= bHpZtFc;LMSiW6e'bNbeN6#xGrHx{,@qz 1>S<̻v$OJ:@FT] 4n:$ZIh-5Bj #<' 88~nYďsycꙃ1yω(dEY8E`pCvٺ|:Ki4~Ğr8 1WPu0zbs 8pϐh-)bv-Hذ)̯yK^i!-9+?^8߇|Ա{3D(e@攙b8oxxR_>?O姖ieD -3ȴ s<,~Ω+g~/ΆH  M} Dz  畗W]Eeo q`@C"zQIlcIh''GȹP L@Œ:?/]ʛD(V_/yV8O·4ӧş/GgN(פf>a:)7 W(#| E8y!T 2٩k]B6 .5rқx2?zP>cW~/&j2C+gxW.nEݭ8*ƻf|̜ NNAk~m`~wW#(W륨|ke d#9FA2SR(̚~PFMX>W|yXP+Z~8:quǂh ʪAB"P6\fak,v}Qg' tIO"NFbҶiD!SO%\> 9 NY6i ,QMN2oS@b*O~9]0D[h(01`jF4plyIrX !wWb0'[2\*C;f%, I~K%Ȩ+,o_#$."QeNyiHpdQNU5,"_ݑ3D~/ܻG&U{Kͻ[diL{kL"}^*a]az A=J ~z&C ߕ6`u5[t< 06ڀPV,By4DުE b;o(BgWDC*?qzu!PCF=*[/ zoВajɖXd>o샕 EW# qO?IUZ3L!-T] A4aԗޟp/ŦԆ80`,j1C"۔#q4nd:ft5uc o3[3ZĄukܭ <ôD)]Hy9["-1BwԌ\l9T!&C߀R(qIt>,##nh^֧@F>03Zpyݥ0ULOz% #Ҷ9_WS$ےy $ -`6BeEXKB{$)fh60sW?e܀ ]CA լ/xI;&loEWԣmUQ#"2Nj ?V걋`$֥xGǑxTט!ap]j==+WRxUKb¨SÂPAڱǝ$[xG1җe3%R|C@"9ڴQ|㯲il~>૊ aux67 ןAu'^{?(@0-`'jZe˭Ϸ0F^Do.)ݦ,M7A_y|;ʙcڰBr+^&Ou+g^垮 >r i`s^ٍ-)~^'gHyH'2aj!ds^ nR G|Kn>BqA200Bf$IG2ջ1;O8W@cmX4 ӄ^F# u+V2]Q齊 C}xmnny_]:ni5~wu"|,HxBj8Cۄw\$q)i\0I^fNI#L +u߮dȘ *6#gF-@iw%g(9f@@H_]3zb|2}b>)j}*VOCX>5~̨Z-)[@_YL9e Z<*%n`)|xV帄a>1bݸ @3zmTI_/_;?~k5[5~G9z}vwI5MDvb҆ٝRԆ!Oq'\ns=ߎ'1?@Q^uM3dDnfY`ű=R&'^S虉|v;s[F̿lU^|Y{PPBzQzYIL VLZ (s*S}1-iY)V:k TUOKN V7Nk(3ƪOTH oQMrų̜cߜTޞGi{(Bs\a>lX2m$ta{SȳO kKw'_ucϠt]{0[IgH1Z`^6{V;à mQ4y'O :y [jXDt{=8{[OdS!{f5`[>&wY=7t}\F~ӵ $&8]T:9 BT٦,l|x %VUg\c" cxr>34`DwpR l>Ǡ]j)ifj)iIHayQBkT7I-Iı}yC?V58Xp"(5ՠ~xGX"rw&U$KNCw<`x mM nDQe[_aZ><[,ñO/f$ٗ|ns*\s=nX;kvz _+b6[pTs[MC\v"+X{c-ž~d0=`].UTZ8t1`YlT|lN1lӊBJ8~ mģep\3Drsg?J5eJD^zi.[Yj'cQ 3dTr\5 AH'0гV!lp qQ|bRgi7b^ ʖyxs%8[_wêc<)(xmٗQϓι|S,Fbx=:yArND (,*׈fvWubVV$&3S}z:N0}s9{n6 WGY06m6HUȇ"cs@/Cqnwd ean=9 L]#vk?XWE9D_𙶶& ZF"O^ys/[m^ WUYd7P ǜ+wV9+C3GW0 y8(cBSS %#2w+3HxoX@6kmahİY/ōQSqWp|_] V) FI\v?[HJ m]iن'R[9 mh|rUZy1`*20iP~+b 4#PIEX84=Kw6AV;Q(6RZ[["9p4ݗIljn~[bᐛ42H$IG+u(ɭB 4fh[6M5:N84!/`bEO}.TafB?.<]:.W+ң~?nj &܃ם@JGۅȥ7P&Acn>9nUu3 K(kG7!ן qMiM@஡UY!OsŸFߺqZZ>d .*, X8ɽǕvmyn?8"KM:I= f5LQSBlOU OS} xdOO#XH;7Ý\v<  _ʷ{ >񭬑[6ֶȵ3Q(lJFFojjXև9W<_R8.*ԯln>I;\ O3,N[3u:FJS!JYp+ՄmJT󀊱k wWkg{A};XZBe3@؍)ZK&j ޣ*M?Po,%S-b4^ʉI.gP0claRLIM*k"jLC+^]")Rnr4nƃ3&/0HtϚK%TEOw?>xk..o8Ԥ>4Hņҏ]׆hN9W=(iCa`zpg0߆"!=[6C3 9C[MRepcr5|{3`˕ݳuׄ1Q`r}4ډvS~_UyGX8Bi%^ʋn'SGS-T+igI`UO8 |vGxO_[2@o!8{zu~Ƙ/#Ɛ|M{t׳x!Js%F>) ` va NSĖ؛߽,/:/55&(%#ܐx8 ,!9mO>[;R<0myob bFwwT9=iM'{ŕ6 =u#ވQԮqپ=/N$hii9OǷ`=3Z7$i3pel=[ .@akce槥mg 8W~jTyBXioΎtwAH:o|ϛZڞ@ ݙhR|gNF$՝lgF,\P:*PlQzT]46eVBȚjU\-j%l@sfG6F ~کQFeejC) C!bCC8\G~n8a>qG{%sCL8ZNy1%XB ױYѶIriV-{^PMł%@?AF$cT`Hy2ϟ6SBʥ27A +uK\ k(Ce70Ξy*a*k>)]JVX9QjaE4dz{] (.9fIԭKw*$A ŋnI&^ {qGBǗ $x/apJ^/bDq3g V^05˱M/PY U _\8rѫ.b%SV`&Se!e'84?E%۱4#1 UY)d>S3ݩ(YclW5~4bQ%f'`fg cHX^Dž04ʡ %ҙX^,pIʳ_S}Sm: B(: <|9}R~h|?61L#BO9vpJNPa!0tBkKX X8 ^El?D24~Tc/b5>J4>uŘn3s iP=u!4dpQ\1\Uh2n 6y#}b1VC7F]L~`sH |jbϻ&]$q`lxr#s*^NݓX0Z(Lprp̀")\`XX`j寑~B T:}2uf<TT e`ȓi4doX\'{Urr$,%q:QL|*j˩eooZV"9v>Y{ %3fZQӛG a5J`O7$73]ڎ R89”@ @rD?fZ@evff> &`V4hn[$!I<5 ktCÉ6dzre(tik6=o)[Lρ? E#n.f,qUaޠWNvhy9W+qazBԠ10$-+~.qX(H3n4tQfΠ _qy񔝗̤jpל8fFQޟ%G%ݏC憰tGl!2Qw)(/O_+e˫R@f&q|*y1 IUqC(HE+] JOJ>,uQ雀M.RUK'QPU̙sASW'`LܷK% j.[_KSaLqq6&t>pI)t#"6ulZ,Н>Bq6̬\֕p-2hª+]ɫū{qrƇ^8$Rp5b6m8N}8^;8cW|K=P&iC3m!L?c'D/aMu"3:1WEy[Q`Fbv丷θ  p7hx=L$3(4ӻԐ(G ?Т vą;ИYA9ovFc<$Bfec OxׅgˆNNa46?1;B J rH!Cˌ=WkT\d aV# pVft"Zv5(I1Xp… }eee~t`g3،}dY?Wǚ a !p ~יx39G٠M+r ]O<}p` &+$ò \nY sph2dNUBfςQ.]"jѢ7ڥJvO2 Zr:  NK/wY \7{,AuAT\.I!@mb (4!̼FT,ΗyӮ\M߹d7&fH(ĿU?_?]謷577ϩ"̫m~T3jk`͠^-; S\ZMB(,"mO6ކț~./cf lyk45blN2?|&) `oo6g<θg{`!p4Joʕ q ͭG8PaH#oٟēAwڜ@6( ༄6>ycǼuՓG!oN5g~5HO8=CߝBy/+O"Y睲|w]\qa,LD&r|v? Dzƞ|?B(<㪗aXuBWU_`X'qVm#ذ9D84{73Gh$XtIN~SV.?{W]{Wumzc8i9(Ğ#u`"咕'z=ui84 ]Eg3Po)KUOյѕqoddd>+Ls"K :t'Y]u~X>bu:$ÿm~п>#J+G4H`2(`i9sWye Fd qW-{Ҷnn\܁;ӄQFGPPk#4tio *Xeo;y ؎Fva"f;>+}./ 0fɒ8~ 8uF Uus| .yc%p!fcYhɱ]Tw%p/%lX܍ ܞ?D:`Z×Jr$S U;K3z,dK&[aGZpשޙټk Fg5p̳~u)XU*[~sE8(3ڞ{2&3N_`*jb}_ (T\ۜ-?m~oǧ>;x&Pr e%Wc*K싋OH\JUo5ޚ0'ȩOg:Ǚݷd7kh5pk|Goj\ -@g!W7'@-(6+%#;;_ޔy#^rE:&ujyxO~Vvit4ԝ gχi#1$~#m֣:Q0_[@u 5痯xݗֻa*n:A k\ܥQ/DzGWHrG2_r+) 4ür:Us]gw?-zӺF6(A z릌MJmpĻȯ8g{G#nY#:i~[Vg^,] N[f"xU_f*5"'e2Rf>5_#q9Z+r of:o586(@Wܴ2.y=,Vh{5vw,"ѫj&9D\q݅vˏ* U%͹ `5In,W=~ܻ"xUMG/h'xfdB̛2&#D)}1k֣Ӈf(# Q(Tg+~^$ڻtX mA/pj-Ge~k~s-|mvk(.)5.9 K߽Ի ^wp֥&|'iwrq<^ kazgÛ3m;ݭo H.zIu?EaG~}K{7<_Y/epŹ[ Q8#p'NǴ5k;/?:.np:LJG}w&Kq?/ 84!#xF9x\C$]G_fX@Y J" uTºiZ,z8BPF#z_f..Uqyf g%zIrRI-ζ[* ski-`y zWH<1 Bxˊ OEYk0;3Ñ4iĠOzd{_3{6~^ y i202% LamՃ5mָapS'ytk4pϏrG70|)o]VeP堿Ʒvf\c+=n2lA퐊nLƐ=tK{ˮp K`˰7xw[TQxP%S" IDAT]ʘBp]ێx9أ̤4aQsa;my5<<ԍ:*( 3)J 0^3GN4f~J g9ߪ[#]ﰭ>nͯa@öu` ״ pr:񝍗Hp+7 KmU䲚;B'2x4왰u+/ܦ$QIX}vv[uoϴOg}k8xzl7Ѝ!P`<#K.A:l*~n83_=3]^M'?.OJ4Hd! PVxxr-e,JLpu|P-eIJw]I1fg1Y `vb!ȼpU툧ߊNcW!hN[/Jp*?鎹q@fxJȚU0[sӷK;+[UmzUpۑf6-ßVG2 d2 ֪sog -p3I H:< )dJ*j2`0`nyX@lE 2zNvƟ23: mGM+mT[Ia`{ 3d JLj%D|i&2ˏI4(`:=#?tHґ]g 80my:u\]SD$v&vkR7#N'4\g7o?0Y;9v3БNGS+vn&p` _'Y#V֋N̨7R!IpuYTXA3*NQ'- f m}7-UN!8)JXI[j8fy J{Pb‚̚-DťP|Ypt|Iw3g`if B&3Eнs|䥣kpH7+3}H\NS+@fC%Ic9 XnUm;Y7FJWu| Ptu0(b4zGnҀgFV.OI࿐xgpE0޳@_NEPc:~x4鲭tuqom3<q0BPn)afxa]Uauej[#i[BpWny2"|Q@FOZ.|rmqC:$? ΌCxd_HXǃ3Z!(8x#ZS}V`n&~NIqrcwac-r0lqILhrvϳu8#vVpL;/^_iޡ_}r?WV狼4Dx@)"BXu>L['pʙ>CaY"/ߕ"f"Ά jxu? /ߊV߰!O]OI R˯-j^A W!01Z1D> T!?P7W)(G%D"R̀4HR"RfdKYbor˄8HV1=A)!#Xb.W<+T^_P#! dfE3zJP!ب הmo?K˯pBī++To"ӣФADf lLڎݸo:~cG)' 9DŽq|D6hv L $2 ) 頲aW_UnAtsO+瘙 gFMvoa_x?~A~cR{qR`xt vEffZ-F`fM[uM|yf%ӶE3눓M1O;l, JatPFC5Ѯz d/cL]r/K1rmÂ9D's̫s*7`ViL ,ž<ǥzu\/ I!R #]+-dn])fEo|_0?E`Ȃ=xa!U%cUl\, ^:=ox"\?c;h?ܝ8gvC @$zq,#~DR|>_.S%7P)~P>2=95VxVO[1G6J^q6= ўxdyPI$uM:$rhߋxS1C6 H#{ÀI:oU\tO*Pqeh04>mc`5F©STV Y@<_h AQCiDhm;$? wO0]X 2䟆k󰽎W ͞W;x(vguL~b!U) xI6c7} \Y~S{";;@.mP eŻI ۏp܊3^R>,_DAE6x!u=7L)OU{jEF< ^ALl~BڅpV\9LG}8fAL ѫ<7E~8xaP5H+匳N ?jb L9yettg7 {^c AF_x)Jc7& [0l{OS`"MKw7qx|.h4pznI8,zURv?!@2 QcH; QcNDWE pL/IIdPt3O*(a?^NjZ7OItntM朽=)^ 禑 W;%Ů ~l+ 6H c̹g,Ǽg~]." Wb=BV0L wy %1' ? 1 =ᝰ AS{I/ *b"/4Th8XبW6@{{yeۭZ?d~O?]A=f{P "<~$?-(Gǟ%,?_j^Aj۱ߋee8[λv iT ]*I0 ~p#%)3`{߾LLES+q=ZdoxaJKZH$J} ϩ<,NAA_vd뿥t!aat9P~⧒:*>4>rչ[d1|ar9 ?{d>ڤ?O;M{Ke?|N#:;7˘~od d13tp} d 18@RP ^e^B$~%wފ*hqiTq'wIuCTT{,%T9< @7 I#۞-s.h.v4^-3-8=5L 8D%qdHbd1D,nD Ng L-F'f2 8oCsqDUSjypHyy2eaʑB @:oSqv &)丙d~LeX4ڎC|$ KO4d#j3[e,\'qi-M4G8l b7~|ӵePUVp]8Eu IxNէL+RsHl d1xMON j8Ab^ 8b~6XfXNpǻZ45U_òM*0 A(ocxIӘ>uA+gz8Yg4w㮥wI?t6j=q6&֑I6z׏9_ʴ#'$2\wFp 8{(-$9<*&̅sXt=U[$bP*;v3 3#ܾ]-67Z.֏d6焒lYcwW;|Hǃ7 }1Wĺ"z3b d.L[/)9}"pދI(eǹX Dd"_$^-X-Cy: ]4Gan#b ԣ@N&Yq. (&a. 0 gLӌF4[2̻i=ΰ L7̉yRg[\Ei K04 yMV< F*P9lAW*M?,ÃHGU嵠LYɂc٥T㘎ƓT77lԄ/xmo[[Cό1Mop˿"KsFX̦(EM$pt8m"nS)|swCH[Еo)'@O}FT:;#X_Dy9[y3̤~e oRFQ }aIm*(l@KIUȶnSP 1 {YKʜFtF χƌ~AG;'~Yӏr= .uO#v` _ ¯ޑ`M1b(&J+nRNVx v1U ˰Al_EASWO74>\UsX6m_Ư-ˁ9( |]bIlM#X FIxNB+t1cr -&$=:J"nic\sW9wck4* AFp!pt8m[5\Okt!De.BV8H8:cpug)PY(Y^xS_0ipK6`?,1U+̢~VX]|gX ^xA:e3q @X 'eM[!}YB2Ԛic{|U4:LNnFx±o)2fIwFs QSmvPF1 q{![5 Yrsυ0V]q#pW5]a4uU3o:I1?/\'y!+BV8ݘE)4B+au8 h?&cBbFs#_,#ry5x;2 D0Hy1~<GMv CbXQydxDՏ˒,k8j$F8dh)Yq{Ip_%rgZV8à w#paQʿ\¦'abXw±i2l'$Mo7&zsLp % SVpɲDS~\Tĉ°T\?4#E^X>h -_Ko)'~s2'%9 w6;w)l 8"зP1^7FdH`,bVESp MJՋ4dn%BvߞGw ,W)D%1ϙ[r߶uZ}"bqмtx t CƳ-:F;gtzCdg`wSYy^c u";ۥ#_PCu <udj1u@6^ -HpyF!;LL_ 45̏"|~?zИ |f;j0;f6(?vSf㳥g\7ԇ2絠H IDAT4^,o3PU;p>~pbk"1X~ f[)jqVC kLא:'bI8;NTҙE+ 4 {4}r0X%^;jw{7)6KDo{4TfIy/G j:m5aUo_Ꙓ1cκzaA]M}t3_qTDIyu3 `,Be۴LeDnw] eGJ ΃7yÛ ?na(qC"xo;͈s@Y?(4 3s8r"7vu릜4(2r(}?l 2 |߆'Džo0Vt#uܕ Y~cGp, *Edg̘`@'j#;% "R9#8h->hȌf*mL %,36JNMWp@ rLon 4UZ,Yr/NXuW GKTaIvxט{x ^DŽ'q\Paux&I.;JiqXWJV5oB{ ^6Gt|#6N 8qUoAX־n#CdK* $mL۬Į(J1)kp~]8|(>k[Uhf$ŠPW"*0(MhyXQUqOW}=+~ r2+@c`">?{pfxsl/.ЌCZ2a\#>snX%#5g--_y ETccڷ8\K^|щŻi\<ڄVs|nZOj'Sr~5{/u*iL˨+e Va>ݲi|dgo_[KLs>9kC l+w?6г)0*, %Ί dW__n[]~E2?}+M4f[\F(+ܸuՖQhiՙ0099oJHC!\~Ï=дޖXU`!$[lY W3a7k:gt߭8Gߨ{/0 oŦ&Hg0&h~vplg|6ƛc*^R ,8 akwȺiY_[6ݕ}7rb(i >]u{VЙd b:[oax bK/L'!ߔ+k d\ސ3 MfM7m.5NFI 4.F1UF]>R8g'8?||_ӣ9HRq+M,(hҥK/"6_hn]*V{ʤAMhjqӶpT[`{֎Ř7b4̀:U a3~*?naMKp JdJ8+Չ|hY*N?ydݫq9'άP-f8FC q/caQI|*dC9gu^O*Jf᪷FrMY7kOC vwڹkOvӮ+Ӌi[{Q=SfXڅ p mjnmܲVV~% <<ۉ(P&(7%uCfI[:˚qэH#EH!CW/-xܷb\@V8=£gʮmgK"=!ݳ+OBB1>T;vmMM[[u5a!謺qKhoؤqiZNrjˇ1װۗ:7tݧ߽^⸷{9ov! ޿FLc[)ؾ4tpV| !az5K`LYSm 4J}gYJQ|յ>, ~6j)'5-AS^JߖsKU?^UXWx1JAiX 4(3Jk0OVk/li3r=d`WWWI%ghZN5 `.kD~(%6tmq{Yq̫/X]]5CK`R#HāQ鯱NGgۏ;SϦz" fWepVFk09/|t^D,/:BL Y6_hT=GQz\6$wl>0سm7ڨ 5vԏ;~SkybU8# Y@#`+VwR$M-m-Z[鉥kT~A!H pch4cSQBX?`k]<|/TeE`Бqr];N9|\2ӽgͭ;QX~ۗI{ܒŞi#|Yc:AT8[1LJV$pUVSrQ)ͭ [e5 {R־&aфr2< 0s+ ȯc\cV\xNNPCQi#'!wp6x~ a)ڞ</McO(dQy0L>BiU75&z>ΡN0D'?t>~鈙3śusoS qx:AZzwhhxUik:y?/nb5bSN6b3={tjӍzD.p 䦗n0h[w\ژgsSYS&%4@Ѓ?c^xG*~lK/8q 1 !"f<'T$e q 3N0ZiaQ===v o]}[[Airm~f ܋Σ}aghR:t:YNǬ9ԿC"k=t#@\S`LvozJB#`J ֐mE,pOCI?a7NG\8FI -wʊ7\%g|qu(#g~lX([Ȧ>6()vQ3H7vBlh.MwC:2, 8SQoZYc$zl±M{{":=V7D/@.BN0L vzf9tQIϹ\ɓcB&k^]8puY{MLߵI'7>ԏu ۏ'>$k\@LK/;vc ϬEAL|;zP.͗'%6vzsə~Ɛ;N?aR[?"CA rwja*FgFi$.k֖Zq& Ap{A~#;J qm 5?ֱ-j2&FBɱύn7 و3+9>/Z1JK/ñ5yL  Kt-fr. {Qj"}xGG7 i$iL;O'" 0}%"T.XHAy=.eK-R1ڮ= zst1XW3Q,氙 @7͒e!@I:ӹO>,ŽpxFgՖ%Q"!79ɥ6EH7qc0bl΍8 5AW'H*Q*p$8c237 y*Ӹok/:ߗ3Ti:_?Y'Yheʱ@qN~Ͽ+.TB帊C9 9Aguf%Rs!Jxl+Y'W["sc> fsp(=›{cR̠Q`k^Yq VyOe.)r)D`}u[ʽo,x9HX@0T磻8aȖPWk30 V䤻Z>" ˞===%=ms)xp3OYMNfǜXWQn lNrRNUe ,.(vvdw'ZAKm1Vǐźs*(v_ (,ѓ'FFsh9'wK)WPGOu >wë標 W:+\@3dJS & ߃xH?q;@-=dI 筒?q ^R f@[gkY#is3W3Z<4V RZ7g%9hLۦ<.-`˜ӝǤOKϟ92Y_Ugjm~1[0Zh/&vu`1Mdd߰̀0Nu gYy[FKsS`Mt>% COĔTGɎ4~"?B^ lۙ xcB >kF2җpB`~7ywp")Tv>\8fɋdKR˴a) P70@rhN96 w\^.Ol Hg0zTa/1Z}%!~v}[ ĚzR C@aG/I JIx@RbÐ ˜vKj_fnɘc$n!o=Dr,ZnZ<5;b_8 1<(BW& fE29MW %ꏼS!2hq+`ze5gQ\lGJ^*+`̀GbĠa'' &!#@!{C2 3N\>8h*/y~leI"1d1܌w7ZDVObGx=G7N1>PwFˈ%W%XU'm#GmhzS>%L%A+0C6P*Uc_<- (QCHwL"}QC2@  :MvJ191q0Vű65@PeS(` Wbc$6a< 6_VtHGzG22 EuklO ٍ`<Lt W3+/A,9d砤By؃aB6%8tv+{XqP>kQǛA㡻0%ʮ6 փP*qCO}Px+8/7U wIxNk~#ʸЙz}I6͜ʇO}' NPK-4 ̭AѓrM؆]sFepjٓwS㫷~!L$g]H3|f e^9&N?34VOf:C=Άbq+ `=?-s$ 5ъ<-;X^:{Ee0TY B`)Bh`vUyгfaUqKcBK*`-#S122 8֪IS>ȞL?mѶn`iL}EWO `0}Gv7_^k&22Yz0~` , SX]sYPŸ~S!euwaxup&g2T&c0)Pd#pp8R0Hce(x܅u$#f؁ ua1'{Ava5ͣ,'u*6Ker[w] wpa f!fDz `h}W.;6P֟ yIAXa㶨cPu\\ՖXˎ fB ^ԂWapcV$al8AF P"]S.ݱ4v}3/$V˃TN+^k*a)5@zX" ߱6V?! z|.5QEhUd XթB`/`l q%0)s0A!pˎ%|hÑ<$0˞oxWxM|I{9IH:$Idd@Fdc  6F6`09 $B@C(g۽pwg'^MOOlYij^*W;ջwN<`1X '-x{S2k*:1j^!xUشmS6džnξgdllp|"Ϟ PgET 4e\ɥdfhxllۗ/vw{{QRm0Rjys1S8~_E83(q/RGTE|t5+E]1cxwk%)D |~+DQK"~ӈG,ioi~ʕ'^z ^gЁ zP޳kmQu<tE˛Y^ڠP?zJ*ň.VqG0$3]Ɔt UbttʼxHϼ8.j)C?8?}M.T]V)0ݰaC|rr2ܜHd2l2O zx>/B! 0E/ wi*1HN x>-D|4Ͽb pL.HdK<k&V_v-՗X2UGdڷF67J Z|ڥ믿bճB,HE >>]m_{zh]"HAHD_Xc__ >7`ںo`1,m/ݲc/x3c!݄ 4"c[.&=<GFB~X1k]CCe"`%Bt%ވcD7Ei[t‹<#2)kbcO [Z{~9vGx>=Lpy3LѣG>\rxh(z*@`%v<ƎUvvq`3v;s'65!>s/:ێܵk,>Ļ CW &===_Z;WŋXa%8eٌ}kܴq[{+3 X'(}ZHo%c~ =3. `1]}Wz5Vb5@UtX3J'$ pqݫwl\e[>xq,rPA1ٿ@ = رǹ~^G''[hC} SX.wo7ګ؆'PI(ĖTb ,Ebq!ڶbڿ}֚nN' X0,Lb@_|wQ؛;ǻ~ʤ0t0m-~u2|4h(SsN uժ|s 8\]lڴq?pq*kΪq};GyaxUNČQpn>=ؘy7 p܊~~CD:;;[[[WӪe8[q!!8F̵Z'=Fq `{xHgOO psz䣡t 7,1Ehn$d#\mB_gU64q}{ Z `aʹAQuY P`Q Sea. z,DNjJܕ[+]49eoY47u T|TaM ק_wk~ide_!rgPc˙2Xi-t_urTŗ쇛~:iZb_r{Fzա)=+ݷȳ`J 4@yF𴷮W?^̧Ubk;yw cM|hA(edWCE>vߛw1uQ@uQ s7lYW\WZ᧠C)Zu~xe{Ѷ*[WZyQI\W D,horLE;T| V )^H<@ B|GC}CuϢ+XtUu}i×V9M+jif+nq18 iw7^K6@P bO[ۢk~OEp^ѧT 6壀6Z$n6-4b1oؕRϯHơ~Yaw{]Ӂݿ}|]q 4@WTJoݰ+RP񭯇ˇ? f32Hl@C LUsx P?u1-N(\z]ܱr~ &,{|Ƿ43=_ЅzZ{Fgvs!`i{ 4F^C֗-9hb>[^k | 5>( ͅap1z jVD?RU ?p[O?+/Hz s.FT@B:ZY|͊=) WB!ǫ* (|28\unYPW5 _3(=S߼YW] a~k<=t~7:z5 %,$eRnCaYiK~Q5m^ Xu~/y|/]" ?Q;?~8;o(_U9p=k7QGvwrFo ոbju/xdC,xNxG/%`i >).HSvы [z hj댅o KG ~%~n'!po 4-@˳/芛Ř^\'"Nbq|H%mV'cwxh)0/X"N{xqoݴ ~rZ[0TK7v~ga`c@0 0\3_Í?, b|/زiۮ֞^l8 #5Lp^JXg{_M_kj᩾빸g훛Pe> _݂+.VO6,+,P9%PǡЃHrH|g6oɭu0y=?WO +U_1]@{B/[x8xxhӱ(~WL5= Eó%P Z$MH3XOW7+'*GJYh]~B۹:ڕW剧%XRE-^܊?Ldve׮QՍ)~LJi]ttps'^>)dqUGv{* !Kɣf¢ٲּefBA^#Gd0*ªFH,r?0v,7! hw8ZXt#56<X[aN LL`J'Ns K|~פ `kխ i P\0BЛiLJ?mR)n;9>hhzOt鹪âhj—(u)wmKa.5c䁊b>Ǣ͙3:XI:x5EʣOEeL%xo+]Tsp//5 JK|h[˨`lC] K#yN0*=# ^$/x-peBQBȧ  ~ S4]ct͡K“?/'j$%P@&ǰ; 1*PZu33RU$0byJ K-$\\_k$.,_Y߈\9#FV(,`Da"B n/t|x]>oLP8^}+ji`SET˩+T=qF/X|O\_ȻpAL*x@Y'8$iH/ IDAT Tt.4B}pqKs.KJ|EE[5rъ@+($H.8'`݇wDiFu|96|/ϧF1*&]ٯ^ZN S_QEJoR9 #@)?UxH/&~Ip\!wGNGۛϰsP-zjD4%Ш-?>/L` 6".p>GD`PLe*u6/h]y?7؅4OSՠ,+NNl6V:-` 6iHx`m% mMg  2 B[xմ3\`=mRbE: }oүȠMcpQy>Zk*)ᖖ|Jtl|^&ᴆ͆MO矆 |:\.#>$ aQ2۷_e{NO/1x,׋FնRm7 v#ʐ 5FOF'~W U3b+9w9kx؀B֮\!| ]".p>XR=Z<|+=Hx$y [#Qne)fAvm8c\spQ)n@cܻ!oSĻ)/[! B9ak ' y[S-나lF"@%a|pWc_GALkS.mu/~:oP싪uil6e:R,,s )4 X׸|Ҩ\'⃓!tϴP{%{4 p$!|I''ƻ 7p%Z,|%ߺ{rNϵs4{ =>h~qI@ zՕ%G*O~K͋ߗ / K|%~_Z#[;bpE EN ˳uL A<~>S̗߉j,^]I#Ż*R)_BI/JMhaQh_Wx]S5ƮkMs]~L9|)7'$.Uvwkq~W'xa^24v$|d-tČq.b eDJى_*ʺw4%}>G;, BWxL|=&fx8,s0n]nE- 䍋e-*}俐TAݰFq+9 PHMw G¥/*^%}>GWu ]G!@T ;p$A'vn^__d |r10چ0@L`!.[息|OՌ[4|^%f)6 A7 K /\9W҇st3xǟЕ~~a$!o QEt.yvoŻwe KO:LC.A 4{/33^>/ ;YfьxmыMfvŕ~H$\ _NCCst}+L3~=~P~Hk08xoQoV;6_.?6oipSw$$_t^Ts>w(\ԄN U+ @jFा|pQKs.+|͑;m'« t`#Tt/e^3M0 >MK'ŭ"zta|{2 p8|Qxh]DX6"Zil |po}r:`xD9oJm{ً sM+M;C\V TQ^C.`q2Kx,_ڻ>}vЏCMmju:*:5sXTsCOK󅋥HKRh>_'\ҡ[pWpX[ae3Y#D@ 4^EUpN }{ޮ}:r=7=j/YV.6ߪ/EXlb( Uu+pA#~ '<4nHmg qhB_X*d3Ö[Ci_ *T,=:/ Ec`8~y}SzɁ1?Ox1,ai^,|FٯpUsgze6uéVL0+ڬ;oc>!u::^$X,Ϲ |9Œn O;McTՔNᮚJjLSJ*ܞGOl.w<Q!ռd9@/`båMyɟ|X=~6?ȫd_jX Yat LZMoq/g;̫We-8j^)F 8GR=ܥ5Ak Iq$2 $ ʌ ? 'ւA~2CN,bĂh_;ӂ~#.~*4[xJB>T:7" 5Ǟ?3>&,˻൒RT +7T%kF3'Qn17* -}%VHTJk4OhTA>o9i/X|%{_uYUf2FIt83y~ُ?ͽ֙6٧Ƈz=ŰBF+FVE*p4p7nTuh`13QP9?1WzZ.R9Q x]x)jUh%I3$4|F{ա[`؟T7 ?zs-M*=2WгWm^ B ԛ&{:Vk !\!%,>8u`hQF!T>@=w?(S>/@Q*D"{[&f`Pkã [+txL^\>QL h k ̑놣*kZ#5^Pc fAiFlQ)8Ear'ʀ5 Әtx-~6"-[4|_kB:x!f!e|[s y)>u+^/AϚ1Y[+ 1._j> }9H eGy(D{qMA .*`ME 4 w^ϯ(u+/U | =zxnG'0.*} Xc*WX$shc)-ePR Oޔ&!:E(,ia#:WDG{_e ͚%oze=1_fw(THfy,J~+B?CCyƃ@_!? { br[rX{|%|U)y@c+N(qu&*+߻[KN㟯o7=MXB%TO > ~XM{oT~sj|Jips}jެZbؘz쭯S3OUk~yn_0)ӈǠg<6(بjY Q$z:w۾S/ t1ȡbN;9%1cdjr,Jdʲ\zC|ϾOv(fڍ ,ȦBGAhm؂K܇Z0N8uYDbqՁ^˟S]}j] yFIR>(8 (?rQ5\\~o\Kjn5Bly鄕U2 a) Gp|(uQdM7d h+h@JM=u`Y >21Ҋ4|\!B`s= sq\Cج?嫧VrK(#ht.-#A@T (h߆τW0܏S8Uixq=/\dC79`.Y* !^^*{,7xLE{%0wr{gνIf VZ^ko9pc1b,_lt?J ֗Y4 {oDWK͐56}[H5h.ursql5Eݎ׽P/]2Cإc(ifkal[iK~g XLlA7|zw@6{Uzo/v"7hPj{y ;C3A\QMYqD,4 kQ,( \||r bکAA#nd~Q)X3nO`=IEbIp9}B;eSӬq_vqJ4 ^=`F&cWMGEkBCnvW$v0fA5m!np:;ߨ1F$uaJdM|}+HTe%797+F>rW`nC>oXXκxc*E_3jN yZFb ̢R,yqGcm[b>8d<|څᑻ8@RT[w^c\)%8ls>u>$\7N ݳ4h4A1ugUMb}cySl~p$@ű_N%a/k;Lu=Tɉ-xSx:>_}v/Ȭ a3(7pkfEœ'Ry5<dS[c ~a; gϞ<]ʞ4PJyrY短{Fj<=R,ztV!&*kEL.z͖g],:X|Z<Ƈo^Zv p ^|$|K@aa*>^#)_OQÞ$FXү>-NcT,"O[ڟWuxqYE9qyhf;4\#([ԁ$x2աYT  cӀ#zeso-U_kC}3j`na"q0HxTl{")Vdܠ`6}7NXe4 Kaygƿr$KS-XADBw,W9O)yd."7 p7?f KSk3t ډg~rkU qNF޾Jueh.~/W gooS :X.SvlQ *+pg @m.RX sOI@8_1 'g7s@/U|2P> #TEu׵W-PrNؤ\b|*w;2,hC'9ɫgڅo+ /fXU9Q93PR]B, a|Fy5ϻ}Of.1ϞOI7Th>Xli345 `#t~!$kՌW@Y𶷩 (An5&oetŔˑm \D\{PvYkRdԽo|J٧'\ˠ<0. m8AG=߂jj0㌺dB)TmmLv??H )+jum9/uפWKPaZQ6#Y>r5T\؂auO=ۋ܆/qGԜvè w#֕Ꙕ f IDATM]N9w%ʛ|kSCWs>i`Äg/\_,M(ϓ.x6⠹'\x#G0kb% -dMyPmuz a?[b_2\${m?Ai(J 8>Ȍ2%O<әLt&MKd˞*g+ :p-`;_}+?]enh9Z, '99|^oi:,)Мaݢ,q:x/^c}#xSκZ oCwpȿtV,S&kL"V% diSn!tr'ᦙ$ېB :! CA=Lctfб)<|]N%P8+O(pO cR+-l߼2aI;p#8xxdX I|PO"5Hʂʀ/.·!/&9 ?o9 "͗]y}{Ĝ8 Zq{ZUnؕhB/~)Z2ZlfTE+5( fb(tZآP$ G.5OkDGQ&.9) X|S' hcHGBq{UkR0<ɧH:GHJ**N#ٙ֏`z= O\r a2刵&^xU+o:8eo5Ż~3#s*"\-ιU3ddY);#{9.Q6, }!#$~qб)Ko<-{2/op~?{750A:,X:3Siy0sF7T֯kv[_%*Lxw>h3?y kY x.u_};׫I7㸩[Jf-je+ @A4$.q>-nq|0qFhU¯32 YS?56VG79PCx2ڊ/ͻ:U t[4-@{O=;TTHM3^V%zZEЄ@h!?OEϖ͋>U( Q)DϏK;.XeG%ް9Vb*5F/NF|o\yKP~/B=s9TׄžsطdV,PT51/$:Bڿ7q`Zs֜QQ/Y7bb:m= iJ;+3\|2c?`N jY#*Mq5 .Sz'+rnz7c$tM;|Iݻ` 㑳:Ւ3^kO[Eڞ*׷U\!r $^'ppI+q~{pr@ Ob{yG<e{9&3#TN9#Tu 2?& 4e6[Njrqr$Pr3._߱"ILc 8 ;0Εx]dO"iy|i9Ù[Ty{93Q" nH8`$ʤDr<89ɂטgS5jTYTV#,T⯀ⷋ0`8CM29 P6nn}g=J} ]PQ, b?=?|mja$ΓF5L#~ _QT bXp8'K .܂4<'&)`Ae:xJ.3+xm@ .^d%!=vۆsm yX<K_նWp]+5dsY|RJ¿ sJL|wB]p . 6lܨJ)xĕ]W)4_̀;S$- !|$'.8 p,w&7 QIbɑ@ –)OZs~ Ӑh^eO 3_qPyp ç3TtqHHH{fؠTzi0?~\ʒ( ;a:o^q #wX~핯Vy7S=%ԄZ WA8ts?W]u2a؝W^zڅ8DcՖ׿S?9Sߺ~ǹ$T*`ʕ-m|;7OS +A@cWE0q2N@ ㋗t ڄU'7>RJ9+((A,rNdvhɽ>FPsYKPq6?CF']gL33L!8\ne&~A^7sU~޵ic`I XEFqa8V*8qR!FbOnVH?^ 8qכ^=ȄY5(ӊ7N+ KlApiD]DXL,ْGDmąc/njcc( 7kBN A~h\%sV&pᬑ 3( ˰?6^i>խOuz;8E\tt?5 6p 3c%k ygIPHݣ" l^pҭYNǒLhCfB3Gp{_΍JgH-l̹`6{~KheH+xge#~qܻCk(H^Q"W¨ez+hs34 h+䥶YU węhU$[-xRwN'/$4k85@z'8 aƆ;8 o~^_=\s&Ս\ P@o"Oѻ *]tRoW}>l_&dz̆ 4qsA.QIF/J0ӥUj~o|."nQ=|WZCH3zۇkH0 Y;| )O5[_%߁bk&E[˶Nl{[ADTD76RNS~B[\c $+PK4J8O3'xѕZWpo+%Id|ڛNo ʖMؽp篹 cQ !)0M|n)/䤂OnAD|VSZr \;]0y?>ԩ4ts2-U46˦mzJ @\s–^(kmW}+,1R]W- tnGcl/5C $^,9c{y 7_ulLTJ5_hzf:̃¶n/#07S^Ә 2\UlVgs *EL|ylS!(s$Sp/~8o5oئՑoPE1,cj0)/= 9,}+l%А@A~g +f^D@^8ؐ'tG~of*`{ScMDUp=3/9" L+.{j*j,,Ac{>hYs$Na ᇓ5< T.'G `GւW"hysV/Ua* 8WPkW<čg0RN$8E(嵑x,Z lqR28: h 2Hg=X6\Pjx݃!m 7OP0 8Fpyj|42<5FC ! AO?Ҙ3aoDeTЬW!]#'6Z1E]/BÔ+^)̏"6lmݏ#E.q:~!Kf\Z/m.APp؀n)OU'&D?6zoU~רx,W>Sg' ?^HUki'# " ,6}ĝ_HƠ (:99O&\I׾-7~Z_DBi9 #Z YWu)9O`1M, ~,d&Pr l@GPH8_XMVcGUӘ Hh =x" ZHFGFx͸{@"mM&\S#]È.hąGN~Wܣ(Q#OS[qF !eOcz&QhLY-T Nb/ z ^ IDAT0=8, '.v9HDk0| k:??iUW;h4Np 惖))J !5mxV4R5`Y m-xO_gb$l3P#b___fU|ss.V(޹W}G_Z3aER9!D?a4PxIr4M ~z͘?np7479WS!{ =7Ppxl y-%=POOb*AǙ6Ӂ|1Ha1 7yg+0$vTA8)Š43AUS,H[qoA{k o>#!9I9FfނF>]lʿ,*ьF]ʼnSAN*J;}U};Ceq#M; %>z={ ?6V'5jsQ^*7بLU\魂`a)46crVl][S02`> <#Xnī$'ejb.Z J}x@O丳+E澛}[á[kR,b&&͹h0\D>߿wۮ;-/' kpWPx/}$ ?V,:>ϡiGp9$|(ύg*s3vd!=ozـ9 S>֣}#%(w(Y r@pCV#qGu#rq͗6oPx$!F@E ?p C,x5J"+8rNv" $%~Q ?xW| L`|^דi_"24XXdϏ;B Ӷibi2ƊH=FS{]ؔ)F>ixd7 N"|ei't4NpaCW1>4A9}FMk~rXBVy=?Ä`jb+:U #4{KY8(s.(ᛌJ\SI΅ayj>d daϟTe-jW:wpNsV$2E87={^uȼ B!7[5kI}p|.? +K&$} 2~p )ۺq3;D9| O@ri55W.׻\E 6_&zPNoIP{p&/d:M'?T+N{Rf$Lc1X`JЋ?ڷ ET^yUuu559t$t:traēxҭGrw( ~/+"3aPAvE5W~J/RqaԪ.{ Xx]xU`iKeR "<6Y->-_?*@| l|"A7k#*2V;'2OepA/ ><<_@][Fw? ʲ)⾄h*:qqw.PÌyk0]LGU6eLpݏ?ϥ۱؃Tܢ=E6F-$ FXj@Seɫ44[Y.!C:~0Y@4^>_ zEJن$OXc۾3%Njz | ?UPTӌ(z֡6^6MOprOGꊴL|caM+cnHdpTWȩY)bF%=: DW1>gw,Ʒ X"Xq R'+hmK|0}z&pectC mkl$/7W}4Dk-f>kxeW -ֲ8UwGj,.+%4OBGzFו_\ FH Mj,]б_ܹ#H o(h~9N!R p XA'" h;Rv÷ZTTv$0,k^t!2cM"r/7wq,>8 Fh ^ +qް=SFЁCΆ4?LT}ӤTN+5)1%n9'OX-mRm?xCM/cXaANYS9Qb/rcO~՛~Qһ6fP!xR8%: +xME8#Wq>ƣ D"cu?.uCF%1 +|[zޡa*ȫ}q!$7#ҭZ e Ss->8N?eFq/4q`]?pB{AY ?55/@=GaqUQT/  1z 0?PJ LIC^*Xք'V\$3\3={?v]{s\ʬ>z0gC.ՅU9Y* C2Lv aB(JJ@pk13%awqw Ɖ!A+Ahu)\CtX!_A+|ydD9A6֮~}k)2h`}Y};g@qXzTE;ƒޛI⑙utWLι7{\ \D}(x *["_^(rŲΞs}]U]GfȌꮮꞌȸOMYL! ǘ–t&*Pr\Cj ~ SNǚ8ZssF:l]ڻg-yHqsBNzZw+ڟC~iJ!Z TduT6qoUR,_7WG%"-"hYX)kuY+V%&Rl?|TOOwzdlXYs-f:߿! ֝PG}'&fl˂΁%@憞xǯM37e!p]ˆO)._ _#9Ι;'Ժ^Y%[&kJ++U\ɸkK5"I1*対9^ +/Pq]IyX8,:%N!+ Qy͚Lňi(pݿa0n`PBT(N!@K$pzh=ϞޟbrH5Y|9`1Jhh!}p2SΔBY&agR5_oڃJ^jٳzL^lԢk=? [jW 4+Ss0֪Uy~ީ -3}b;8_4s;3` ޓv,6o%[B+0NL/)aZG=KyঈI&ܟoǮyIk.{4/8gFG{N=}oa|ombZD{%WôZLznx#p 9MU+cx樿W U.89ò5g20~'lW0}A]HG7;+[Xy2y(oFܰhi`NChu{N_3@?j N!9ַ tOAˏlݶ ֒HlСC*L8%Z ӴO ˩_VÄ7~71nXT*85Tꑑ6R\9zS!ko<s4aM& '߉A4\`VW%k2\ƞm57GӣbWL/{TT1 $ @N'->4wo=72{ɴ0Ifard~68 p9@7v:gھ!Ebjlg8{{Oջ\,Wz o,H|91}^d9ACIW"3$y/_/qs[yY1h|V0͊s4r>/Y)Jo]ۑK~z)oŸ3Nќc׭^pm;`rȑ#EvX` w%@Swǿi]%Aq. caXo7v_%F+н7%ωH:,1Nq^ȕ3`H,+7qD[<ۇbdTg "WHfiςf)G'<50t9a0,R, N[8]4S~զA,.LBYe# !䙔\.#?۔^JxB7J /*uxWE w 8Tsoވ~Ga+®_~[DIAL]/spe&m%p еʰ`xg\`uκvbqAIEAwl?MZGԕ/U /$P;а$4icfM3cgoفjsČsMaMEmVy+$] 8|C?#?$Y1(iy<{K.rIqF)t}/z=XϽMvs+%}BP@3$eSE˚O:H%\bCE(cLs:: 6JiIjY\msS=.OyPc3T#% ^*wrOۄ I&XtBeCwe.F7!~܀\nS5c7ۚ-;548Y3 ,P*ʉ2Is{[TGM9,LB-eʱM=J-vy[cbJ͌Co}OIG@|&h7rd߀u҈[U9,+ V`V}G-_'~wJ 7gyl`:UV?PPr )ٮO7`Ep|60,әX9)s텸^YㄪO*[w;~ׄC"KgԶ%U剌"P[Tj+ SC"R~R{ӭ2l3])JD,8녫 ɶ*҄朤J=8cv?={&N>14<8<9e-ln?=ApZ֙|&6sg#%@ D!w_p"VܳK? {SwgVev L2,f QQ A.Ry򒣢bՒ;Y A.;ſ_Jiï ɏ|\2o_"52/ RH:"D͟}{ɰƒqnAN䣏{SSO (ӏ˿LfvhzfL,}<Ì>ǴeQǴ3yu Tm‰ ZW" z[R-iN3|tL~ɂ1a"PՆlC^-qՏ?ÚBD9 e"{d8@-~&OywZA;)3Mz{[iMߕ&o7S acu_(iU6l=939h]l/.1f K۟JFOWn-].|雥,aaII 6bD[ 𾀽yoڍs@V#C_21w)\š{q0ё8y2/ >%5o{,]ȸR<Ȇ?/ nf^Xg b%'ۄ_zXH,z\s/mǗDTlqYn%'~17i$v3MsR}͠.;2ֆT'0'w8Yo:<%g>Mq%l,.ۭdTdU?FЯ|}.o]/=.scK^|AVn,qtB' PFUwқ~\dM\S^z938| !yk "pDB o`HOeMtc_?̢(~l/V`I\b^X0-,=!H²)>&'u$ lsО IDATonlnxm;Ұ22H.Nr_Y`{>_ Y:~*znE<\vjD(o!R>}$?S\^,3V@ʧ?Q7=+!/M80A-* gg{MizId0/3ɏc9v9 _v_0mFl®_ ھ{iTN纎HH fahjh 2'"x\~q{݁| IUD`[Ojw}fKQ.=6!_;.)޷IO^;{ֱ$ˏ dAqsmq%~x|SO 98b}̸"y⍝׃\718~ CtN=)g_K}Xp ΣpmBmK6Eĺ[Dq0/5^(ur!'?@J$[R=ao PW a1)&o~쿕k};R خrscj)UG[{ةom~zUX}"oBpG;W圪| qhߗ9[:a]CsR]c=QJl Rƃ 7 h? #p?RAֱQ{ᒡQ~ V߭`AXm6ǩ\D ^ͣ aw'w=*Q0 *UM ߊh~ɶˑ#l7khJ-= @<`AÆ-aļLqOH}}biro I%+O2ڭSrrt WܝhEMye:VrGҥeӰ!Rk:MW,AC# DJU{sC%tX1[,oD6-R)_~~h9삶[)z&(S1)XpkH?"hh ,?Ƹ'P⢔ =c15k%tR N- ?Ip ?,khœWI=HAL(H ATU*45z=/" ryKo|Ę6ց|bP%@@p+Fw A)Ug/PɟlX "O,/NE3ЌS=཈^[{zO+ӿBAH g%{8TXKi-4ʆG[$6-]d3)ZaciY=kQL{A~2цvܤV[C׳'wѯ?%,,(&%Y~4JG2"8jta c߄ɟ@IX͆HB";*AN Y-</?drgHOW_":֝ہ5>J MX4a7wİ*Cˍ!Z'`B?uDflԃ^Aҳ7$yk̙_ H-@"Uswp[=^(nN HaR3&b@ &v'0iP$IHeE . V+wa~9S'/o'X6>MJ.) Lږ^n> a)$(>h{b-$h>"^aq[QE. ;؞ 6oih%+Kzt\ 7,^ 澑;Y$(?'~3X{N  C@:n Rq,9Xݰ&ɛnѴ7*AG[WN o*f9;O]?yzV(?41)AoO| m2?I/ ` BP'I L@SBӍ7,w$}57߱r`ZPJh$U+g%rP#"?@sS7 ɍaD"rT 0l*!S !$I~ha ŭőV}-?_vȜϊ8)2q7#?jyH}؃@C[:5{g4 Ws`~  ZKPup[0`qTrPX;,PY^222EK *XpvJd5?me7Yo"HYԲds?Gk~Ia/L\GC.@;D8P*a\HdF#"2TQ0 D\ğף DVs ۩?#d<.fR¼gpRp+VOR|*}CϰmPsgp0<$wU(-aA}8FqF,v h+I}pL|N-"ՄM~M.AP!kZOzHq^Rxω8ۺRZF7k|34},^|珜A(U-X^wpӂ؅,>}"$\M70B &-JnQ p4՗{N|I1ޛ~ҠN I٩xЉ;1 a' 桽:@K9a2 ӂErX (gd ,7_IHtNmy<OIGVRV{U 4I]cJ>N|r !pY@$#Z~@OƯ!GC8"iO^U#t!OxZ @, ("n*@ ؼ/)ovCir+Is]`Ln) r}sRʏ4ʲώc%fdA"PKq\ /\HkB͘PV6D>K.B P8ʯ89IqQN .Vk4*VJ`apI`c fDNe(bYIM~KmZa!CYq'Ba$RerwF V(/|~ncQlx`6"H-lƒ˷aE KP}'ˏr[Zl[sx1K8MlgŠ5-SUA9“ IVf2bd fi L>[}['EWq;V[OœR sItbOZظ%Džv. HF'?Oz[żTWʥ54@iiɸ*7.5A}Z &??[@ftZ{DyA9N7@ $4x˜/ imهrb! jKefQ ^fs8+6P\vCV8#9W ڒ$ qzk!ԓNnh ia8i\@Ȼx0h87mNJ?p@ĺqjTN8Oo" O,!͎u RX=H•h6[7Q\D=41%\Ŏ_\ٛ4?'qhŴc}I;;;Ck7<@ťLGminﮔu eNO&BҰ\[?E`CD-DF;l~\jxcSS2"@"M؇6w*҄-;A vkխaDtAܠ|W8XsPx a"  DJ5<JS\}'W'pVڱAMHODwyK%p>ܲdYK%Bf7d]X`"-G4lL 7+D{onVXcRX"f @yڂj|}3>|K}s3muvL&MC^@#@"ܹD𑂇 O=*緜إ/#'ᬚgET&x`mnjv pq^Q9 T9Sx]$D852g < q)<݆dv$\8nh|avhjjV^ch,cuA1 850;єe%a) 7]~E_"f$zڠĶ/ PO" f.SrgݛEʁtsq}f4y8{7'c.Mp1`yK>7 `}Z( `g p?X$B 2p#Ј[T턠3 dbj:w5C P,ay֟1QIKhf>^l9thV̌c:+zB :} -dBfmDt \{j˵\Ez(8qzvB|xMG"({D7* z7uw4ݾ뺃f[Ỏ9BXFI a^ F" =QǑ3{w|3`S"X6ci4wՑ ?=8:ݮ@9Ӳ]]4aa1ݜ'yml3|b'@q/L:0Q%,Gt-g. D nbHi? : jf8(#@ap(d5mǝ>v&]G# L~,>Tl <94>8;1{he'՜KWݝM7wwv^KZvrhM~Ȁ@_ 2oEQqH$%&႙9Laf`vy8d杆nADf9w吂 4 L|c4:)=YCB.tgV$uяS--3ڏ@@( 8, Nxj^ 53"1oox- ~u_b_] <k$pZ9)-{jhdS]QYNC0~(gSs`Yp90wv_xޡps);Wq3TYgdD L#qFL퀍2Y,Kdr\vyy ߇/dX*]Ȇ[Ns,0Ł``& 9,׌i7@Ô9.,pˑlZѨdw뽃 ,yOx!''1\9F{@@1lP$_*_F)2?/^PGD/>zjph㢯6?cq0B9!"b^#럙!GA8@|q (@wÕ DXp,>O030>JvϦ @l^È <-9d,D۰"8s ݔH G"8` O|`*EZÔˁ!/7 %2@v Atx+t&ͧS"%l0GTxǗgYn̠ YDCl`[!s9&үBoUz2R`'*_cbNV nBV[&c[ZHM@e S> ~o 0 -g)eSqhp8Ki'xСb4R&<[q4Ǔfd]|TǁV/`LَiXDZ|X3^,wL[ag\9\LaCP& qoP5X@B 7Fhpb1;#. g*}]F's1[\6Z[S9()ďwPsBA2a%>IJĤi Sm|<21;$ߠM IDAT>RC<NJ.v};W` 7HaMa+8fI>xԳ Q,EѶBON/4p XC8 4'iZqؿO.~#&7?{վטPK0HgR٩sxgC3bnqxfffq=HG rIT,%ހlXT;&\1T"LWrT *~,)}t|M0ORohHɡF[OK6KPgp`]zP6ŝ[h~fj]_tWt}1N~jAs5󵑅 vy7gbp;MIIX#)7P@OO"tR.yPzk2l ړ_yau9 *;n? zSPyǷ-,N9\hw;s挛5G&G(_Us#l< 뚃f$d a Fvs<}#; #0i?߅}!p*E;ɉhu- ˈ~ȑ#8 fc=p9pnmB@GT{&5u 4oqznu? Rh~ã9E_f4H'l`0`AH@=[.SE(G)'Y,:wN ޡL6 v%}PhrY#oΈ1mx/h>)'.`zFhT֍݇ѫGw`!16LI?xIc8z>5=zzx.']ߏjMAj9e鼙vyn>r 4pjCCC˽8 g* 98J+N 'oz<;@I?͇]H şW2%IN~l]tNڟ5:"=.ۃK8Ta<g%7)bd ӿ|K54eK$ef <΋ߖCC< =(8@GXAy&)4Z^V`Ѱo>XRM$0C"+ӵOb9}v}_ow I,Y(QbtP䧤&`{S.sGLJ0yNz\4sySf166Q#{; J3w0[ a߰M7 _Dm%:?i7"r/wZ箑Mgak&4a'krIFDV55*ƒH8]cy`G~܌!XpC Y~i[ۅ;wrppfPiz?4И1}{sSDKj/{cv{8XcB&/_|#f{NH;Ӳ4# {7JO/ҙ~w T=S?篩'r4N_T'ZgV/ e"Nz !c?|+_ypY6!9C鬜w%5RzfdvzqH!G@g!X-H L^FF"^8]s8. di_M5]ɮ>Z2m rrT!$Kt{b O]83<:;f֟s00 8cݹ!G`] ȋ9\J&}ZwIvaUpj;uo7˒Ag4ŅK佸'y!3DZϝRsTY/xr^Տf"\kNZzڎюA tKH[YnB6pH|?:̹ť,4&(H;xՇA"{Ӷ=hBͯhHpk0v|o>ocG~b7_c]_w6]8ԍ&Go#"?j%8%r{+=>~|{gsI}<%Sf,uavv~z~q{3{ֈҸ^˄yܵ6=<o6)؃ ˣ3܆~y\ + ;wd! q.(O"řÝ8s=8<ʚqe[L~)LQ\oՎKS)|NqDhu'pLvG,k&ւ.'irq[_H&[c#|Im9Df2$k~jn#(J*L FapT^YI0nM9Zl)9(n NJp.ֶl6[bO"MYFN- -&XxP$-WzF b豭eQvwE7E 58kk"DhhDj =Q"l/Ƹ0,9nHW:Y툨H @ ~0xۏ=]Ժvqҙx>pfcX^t{"D߇Q " LDߴH~}z8n"m_pfdط?>}}9 '5% Aa 1 QE"l->f\&Z"xQַu+ Lg@I TGD6@fT8KZ q݉'36 {7@M5@O6bҗ|\c@<>o XG;Ώ =p^Yү@$ 1FXa[%o~ij-4sl |zVD@Eq8H̊B>.~*8!G.@ƅ@4nD5 P>i\me_xe.q.L@"N _I-:ADfp™obF ̰xLtp\ƃ@4^D5 npT}xλz_|իRjr[Jl_c$ڊP* G#5ibZ:8u?;'FNph{R7@#@ b:DXB0pB_DBGn %]`jz2,xu2#™ lJ)09*ꏶy"l+"`[Av}_Hu=>Z o=whɐL8)0=黱= f瞾340 >$|"0s_ݾ+}*+WteA* 1pzO 7{!'0%3q:(k@ bNA`!@1%kxn>>fKv0 z @s>dxzO>#f7.#Pѧ[FYFA+}7ݱ8+J/Na.a6+_T3^a^_V,@yJ*TQ($`O.p{'݇'Kɣ +8"6K?vW_%^OJ}+E%>GA,F#!)@2~(Z|Y?kU˧D3s7]1v5,bVE#" ^}e~b}"^RDZkmk^2EX>?@!1ufU ']uK}, a|- @O/FC}Twj@#@F@ID@A`B0JA &z8Ƈ?cDO݇;o@_^0 J?|):8{>4P!p#lEI"AۺZ$/~_b$kp``Tltj`MEX8j@R?7_3/Fn l$!B &*_3@C>Ql5xp=_E󟻗૆hUAKs%pV0_fw }=#DC b0DXB_*=~)tY'!PFN *eV I6i~0zB ' h]<#}'F> (A0z C btD@wpkC=1 'HEc* Eg,]2/(N}ꃑ A@A b$gu@ hUp3Gqv;**^~9x5C ?Kpvw <,2Fg~#owO>U^A@\}|ظWĮgw}'DBHU{ೝZW!DKٔ>7; R?oz3Fw \|D_?,nV~Wqdo˄rGAH,6$%(KW>K}a...[ma~u'"뀀絼zEۍ" aNH20W(vCbi60O EqݓC.D EQk'-G>X0B&^ T$>FB+|Gk_.r#.= Sb/wgXؑ`%E:"`pԾuC x|/#s痫~fI§ ʇO߅FUh9ID p!0O/R핾-+2 ̈g3P cbo7I~3^)Lqw< otӐ@7ٻO<؋-zkmO7^eXjEK$݊(3^SqslXI\W;xrHLS! ߌ+Ώc^y_h¯7]ו',+՛3V\<[4E17\as!3c,Ewb}^3uW\&D%ڧ)2 Um>Ǟ10UDH#u'Z^#_1{-V,L ?&fG&nX8+[yD M16~s׽Vd K=EU7==x*.D<*!C=ݯYͯjȔ߂`[;".!~rF@ Kq~q>K!;>p=8 nv &C$Y;:YzCH[W׾+oTzUP}pU=SOZ*QYW<:PaXY|\?[QHA0uo@ bՙXۢd H{"Pr#CP@\Ȭ<>=?-kO VD2Nyf!|s`+̔$1o[$^%ߗpFS~/JJ ?T ta 2И5էZrãTH 춹#Ɍgcc*պ%oń=Cnmv[T~Q%Ô,M"tDitBDғ55SϠ3ny!{YqA, 8 Ȫ* FBCo_tWbʯ"o0*X̂O-|C*?.0|u .O_ UPZzS SO(V~(\壞/9N2}C'i_KR?Uv7$;\r4;:&N@mź̰\74/ X?2"f?Ί!(7FLSSd5 Al#oc`g *&+O@?4*+1ѱ) C@͕ cR?N{8ӾUK `_ 4=z *@+O}VO¶UW m"?L"AV`w?~?%+[چ*{O0/~1V}K"S bqw:%qǛ'}ޫ [5]NJ$Sw7Ldp(egs's,I?chO{ֆ6>#_w ?6O2kU m6\G>*(5S_ _p<_ZRQ ƩWbx `A^ S OVJO[Kd.G8|-Azw?j*`Zv%WQO9WLE&Dq( r[D .Y[eU4C,D9fPzO1$g@ԷĠ%2 pKIn7;ok^* EK|]_Ŗ([ P B OMrb 0!WH#TCmc8zZ2@õ`Y%>֏ypI1VG/mLըzd*""<:)_AwF-ŕ CwZJ//>U4:ehPdd;8."C<},3=?>UJO_ eXx=]}@2~ x9%a4AfgI,P'D<Dϫ/>rOϔW."uDž9!:OIڤWSA!˰ #T WRO=\?%Oib[>`r u%%o)*=e>ΡZp=BL^uj _FZxh/Һ65VO&:DNVVPzt-~|6TS-XO_!:^s˵`#qN}ц<# h# 6QN"0C?\dAlxu4uhV/hjY=j3Q2`cQŽMsaYT!CIP/{#%G4'Pi 4^ӣ੕/ë/ܞ病6ob (O8JM,O[ /J{\H>Vb)^L(H?ӰVmq,8SK1[şx9]"qN CNC>5L(5N<}{, I,.V><2懳%W~RJ> XYTYhS+g:ehPZۤJz1C_ i@JקBogpEAu+)]h}_ztKԿN X> D\rW?l$5BˑEJyjҕ //z^J !xz5/^=zz[ t.VfD8Wd &S@~u$JuT]a"`*ZYB*TS-Uz?&@^^-_f@I~Ydp 6]C1[=00N7uÕ;!l!P]j_cz 9 !jOU׷_/?X7z~jg ҁ6; HV'MI|gnj^EfQr0RD<~\k|U)o=Z}R} LVf @8+s8Klx'<P[ûގ ܪ,:ɰf|=?_R3T|oH0*޸/DabNn l4 >)I 4_Ŕ Rnd"`D1jsj^=Keq]5dU҇?Xzy*q&eNEG҇ګW-՚fC0\j یƈo*mkHF` ] cVU`&s Go_ ._KT?_CUM$&+~8cnQwT>ZLcU`_-}H0뤧H؝8DipO6Xv_F p?s!'P]e@&^_%}U=SR~80*iuPuSO=\+/f-j" U[_~&6z C4h/@q8"#@ NRoq=y߅F\&ޡ`y/+UiZɛǁ,3//?e>9 _NY ʒZ}~]˶x+M%k#E Fߕ)i9U>{uE6x7*_ͭK+#.` eBt0CXIDMՑ?L=\O/?DӇ^@j*sC0۫Oo?2]ߊ֖b– pST/Vx >RИ? >'Q41I$/.icX= Ym |:H6X#`}p)/vWO1~!p3`UC`i+)J=\+/^-j?`[Gotʟc@@ʂMV($1ua!W½{=O_o;ѯRPaNY@xjzzfv30>tQ+^uD :a!\5*xf QZABfz|N=p-?YVz_/_K=pP{Py;jgQA0.߫uj3ВMCYp O J-vJdC}EU/J|1\#|Mu*AcՒGqO@I[)-b``'*%E.Yt {AWC2## R9UꕵazykpzWQz5)#))~uhG+#n|6DiZ_C=K齾qb@k3XE=WY81LD l`: MPB@\)CK !jzzp-PS=}W9g-["z?@Z|HWIw+/Jb8;2g?lhƆKȕ) CNJxYz ~UW)?T+:ܓBV_~|@}E̬V5O',Z/ް؂0UZRk7@WM'e5d/^pbԄ93!XYE>4$F)FY-]Z}{GnJ}GȀ)!&Xo\hkc??_|+ŢDw8n/A b|$pvkzx;h|6r\?IqP+a6!z\[E%}ո'0V=i WAp)!B~2]&*[P-3ObZ&EflJd&|X<3^'&OA5px*.zGH=iaއ`ȧ'Ǫ=]Ѷ/~dT7=bycTPn/6I}aPf >/^_C)#E- ܓ'@%VK6kC/ID[ iʟI]L^ [ЫV D[Pz!o?{o;*oyK40J6qqH+ @D%Vk v*RJNHA (֢b 7ȟO]X](3wq wS.w/De/;jD" d$ *P@+f  a\-ʣZptꩇk)\~y~\o腓x݋UoA=q= Zi[QIԙus5j>W`8緓έ]Zބuhe `z7&XSW0#?> 'y*/}뎈~Mz\, nq U)SYothaDD_ՖyFX;yЭΟ lq[Tlz۶x+mVJT{y+%WxdRI(P=W0b` b aǘE*xŸ_9|{ nSxƛ!ϓ\>qաs~A`îY#D\g;$;3YJZBH"pq%$6d6Hc,DD $jWaggv'vN}z^~=agW]3+W+Z;}j!5wuU1OAX,k0gtg_*>{RO!$4K:ŤtD]?R`4m#\ϭFbDY-3ٮfU!MZ,L;2~7+⁒E yrQO?BDd션?-V]KtPj^eQ[5K} =풲)6JQh~{jnt+߂֛G0Nr~p<}]jk_G::Jcncm|A g@gDi7{73Kl(&U405 {yj_7JTTMz7g(YR\FR<nX@m+|KKuQ`ν^w|L LWwg},U婩K3=a.8u,0٭`at@&&mݦPQR0Ws֬2$.엄TbR.xLY''kvq3:KN0vn%-uCD50HӦaƠgqQ~gR6ʬ}J%[L!ZTvHH $N[u͙ ހYp痘ӯO~ U[;.'T.=P8ʎP PމJ(6ʯ=t׌Ն?b3ۼӗg]k\!ּ ,xOFD${E̒Hٽ. `8iSl g<nTvco[wƦ%^ZVCVM7NZ6]N%Ϯ fT m9;^}z^;pE$8Xm(2n\dXTiUAjƥ~uEiFƅ7W'so K#?2I<5tԃ.#0NٞL.; dJ/4.G;h qf:TK;i9kpٟ bxn8{Y~=ɺaP`k\[tv^3835e6m'NC{RUb\GuCZ5 =Oʅ"'V$?z68Y7*mD_l1rK\J7^ɫtꞷR$g0`(6c_ձPF] Ya&M#FHxvt: [SczؿF.V{~/ySb$d:N!X>VP&EeR;8Aj}yqxNaMp". =}Z(YOԖT4e!8g`ozګqͶJISukMKk}TCI19iy5'RЍCP>>$A"eCGƂ7~Rw:uzdU "ȩ9|80ԹAZ0MR;A6zP}9=.d&x PRg:S\ÎOM-tˬDWU. X="3虤Dbb_]M %d|hU0xZb'VI6$Ly#f %,]!F3eP 7h<.X*RzVQc`gH M&c`}B4 IO{*b?>ƺTiAE;TYhP8SV9 d=tc_t B+bxldŽfn,F?rf ژ:^CHM1Bi2\5 90XkkG:K\.Qƍ=N ҂2]NفX2VҸr Tyx`vXݨP 1ncn!`}zk= IDATS|qzetL>1VB*'%aMc~ss#ļ(eυ*n|< kv?vjBR[Tw[N -M2=+y)+&ڋTn2gq{qTӊ! !w\zvAybL݀XkrcQڗ}\VٛTvʏ:/2Aя݄Z57F0Hgc:oEW>SxɫfȘ멕ls Ӆ[DAp z G]|Qsc`R2{|!egɀ~e~v'$ڎ;E Q45-Io|ȳ\#j|fTAtӮ& lf SwqځAI]PwMw+VJG%.MB&gJG"yT` QB"}|7/[dRjAdsP%11o17*?843ܠE;׬Rgn;6S٘ <Ņ'.T};>j{0{@ucn$>g׺joF%ݪ @sFkx#nuOt< "]HbU6$pzߥ~ @W;L:A`o5k'* `~K7QBj5A iAXt ՓHOYbZ=f{*$$W\{ß %5R }D_( +y[-KYWs0g 1d䃻 V;p0$ ܃cE1ss#Nb-*ưLh?F:Ϫ Dq N$ĐaQ5tmȷNUײU*"IIA28P~n]AG׿"7]~o\#UsλLeP#WGU|Z, M% JejhGIW9mz!&~2չv>.R. d?527ePfy`*b9j:XFQ^=`;Fr.l\KǷޅEq/+ EhH8 fe@GU(qtuG#$Df:Μ8Ł +X-;dgDv{NU aN"AM]׾oGju^ gYP>>c-U*9аX'.h[ݨoGaeT_QCYywOPa=G&ԾM`./RO^#* 9Z'֜Z$eXѢ@GF9]]RK5I&pLժyc@Z%-0;GV)vy4/rÎr i0y+gOb[!TfmI&>yz#'~Uc65"E!UP[M3蹯{? G Ț?Fy ׽9C NG4:?SK\Hyǀ!E`A08Q(pC`8C]+_+`>C`s[̙Xx5Ds L@{T|JǎȐ7ef† 0H Њr׍ \L65wX**3 nAe: )T!~G?Q]Α%pU'5P&Jh8Дba1Ý|Eo3ugUeX ŨN&&@C&ڳ+KJPt$*r,i(bHeڧ\vE~fTz"-hVtx^UV+, fxD{~B2ssV?B3h.yk3zbIR9IĿ| 4T ̓_F2{|bCA|j#?VmU1+(??0lP1K I|] <-PwP=V'UNt0,C ^$F1YWO4x* *~{oK?IQZ"?ap߼D]u/Tzv$xHH}t&&I=z}Ӆ:unC[feV3Y1>'8HBJ"iLݑLSr# QQOnhťc] hU lbRZtDapK̞=\z(QI+yF˸ħ)xN=' F >%E\̌D:ʑ a)2A8ϑ3DǏ Z Ђk}XCUoϩ_탪 DVwǍpE6- M 7uwKCn5b/t873{=\<Ǥ4wO@CML^z :qӵ:L៝L[<@AQ럞A8ٟWn'|ȫ+@oN\209>~v0tS !XgS& xrZ7 JaGg#E|rڀLe̖M1{%ίm$Mw_zu?Pg"_ S>,c`S@pq6?L \>T977!Ty9*qxIl dC810wwoWGSu?IdVQ<}\8%X\ke#C~ltUjlu Ko^ZoMIT+-&(]:꣌[qVA.QNlk+/@}0G_i/n$qE.~hLOxvԣ*fmk!&^9$'mѻJ_֩0'a.ks/3{nl|>g@0?>2kX:9/:g=C\!qWl5 y> ӷϒ G Vlu Gx4Lȧ4Q`t[ r*ƿZ?i@Ҁh(]F_ 93b.L:u_Q=+mZcp0R=^QnyP=ת'U;8y<!ed_»)yLf8R;LRf+<)606w;xy96R3sSICq׿;R&o8&J#hZ șs{Utb@.`q)ճ }8^0Pz 7[Ya@1X3WPE-;lrT95qq<6+_M$fp * D:&AIPC3|1nN:hk=9/V>}zmo&% S L#6Q&`ʀwps\df9wRMޣ6ê41 G3 cv, nm~Ct19އ*VfL٬_yp˝gb0t;}y'ču` 5F.lc 3CN/MC'"0`%"'^Mx0Sټ0cZ>W-~ #/NaV^pT@1pvo=vVx'<g \է\(?TxD -8Gp܋JT+= i=N0K=s an?Urh+a 0Axyq U8l/|LMܫ7V &́16}Bh\3L2藓2EZAٵUr`PM+c,%TfS GgF #qJ`8Y1AOμC{~rMj<1tvITծW-ki?Jp?} N賧yzo95RVxn'o _9"8'@zpTGi*b]7y!dPv@i]ƚ#R<$J0a<^z8IMԚި2W=ЇdO@xW>%;*Gk9'IpˮR~%A<0OqH1枔]fպkLWS[uE xu Ad/@#ol?g\?Imc9h~;4fZ н@jٓ5JH2tqLވk.HѺȉn{@D.R(wŏ"L)XDMnaq8}'Y};:2S )@ RH(O2;==Nϱ3Mj 2p.`z[>AR>&4Ty’@n*6_]e "VE!Ÿ{Hh$rʏS[V5rn0QW fU["?fO?>ꗾV\˕n>~gpI]ceDY,XIpe0t\a{ʢ_=3~5-WqU6~mRƃc )R@~$_߀yłŸLeNk~7`G|&L7"${ {T}vOj .&th!RP Бdd NMbSGրԤG`0xp1CoRɘdJQi _q0čI*>{ёaV:j໷o*YJh>}_mD?pxI5:q_qe\zd?AjE<[XP 뼦P }H!\L]oaٮzi- LE, ,ԫ[44k# ~LMl މSd}: @Jr%hj֪oZ|y/B밴O>{ە5p ObZGXJ\RBn=j޳^(]+&Zܯ-8ۈG& M8p9+ԕIU4WgE"ϙsFyǖO1~/D.NNÝolIp|g9Yú>,{ wU}/ao*]`\{gv#.V >!VŬu '?a9$e%&c.<̻eIaN`E\%Ϭkb\>|7 X:`!^Za/0>&Yut5zi^ yGDG3wy_t0":-WCoe`7zswSugT] zsW?ڬg9` /f@wY6??#cfZjQ?aZnM|E~Vu-Xd=vmfPclޢAf"l?F0ԨF2jeyYs#{_z[ClXޯε5ab%+p*-)_z*qu2D&{* {{LCŏ6gWi_:8LXk/~~QHr|)_Bd o0ٍwnhs~^+8pyR; Hxfݰe>reUy!xdt󣴃yU:#;JMeS/qigOuE"Bu.R\'8I:? GO]6č)Ñ lT.iNqVqBA,tmfDD'TAYIK)J%[5ץ2=[E vv"=S{J3\_.z9s F" n &;1?d7qk2 ޶{ј=<ƠW IDATBԻq@k{܈UX:-qh'%d ɣλv0kj¦<(%s)BQ di!()Ҕ xܸwGUeH#hߏ2LDPS(YWQe PqL!7a}dV8{ߌgegϓ1а|L*q0"lUBHTOW|K?jHO}oG*0Wm9عo__ޅJyBEk <xhr(3O𙰗軈tYᴘ]<#5X/}LhT4V›mո̄>u ɗ,D7zCy5;YSAAeYjX$UWq1NtfFMď>huۜ%~&D7 -0Rhn+^*x>2vﵙѺ 1}U\q&hHɋ@InCr[~AbdzvBg^Gsgg6\!$EM`$jƦvk'Nc,}e%Mv[ ˘1 ~%l@ ׸ Սj#S{BG~ZUMe ت3?=Nu`*}[?o'qZEt D2޻ܾx k0*2xXݿ&8l13 NϭhS8,tR !1lQf-w*;0Q]Vc BjM%'87!Qq<F`N9~d3e C4RdC(ٸ6~a_'6Y|CMQ9[ j 뷝"6J>eA&6VO?EqUxJ}% 5.ྒྷ >@%ý ̋_[W=.ݻuC__#U剧 S=Utly ĖJ7!XU ȫ(Fw~Kh7T9gU07vqTp(y.rd BM[#&^y6k!Bc@(Xݲʴd[.AJ|/Updꍰ$zt*(U`b!ĜSy<5y\ G}!$DHi ?,sT2aIʂe@3 JV~"3΀y TfmG*2ݡ#T0x2~sƏ^4KLsV]ǪfapXh5- Mf|yt?8 Ԛ? kh)%MxO ~1QD ;πQDaa811Soejn܍+Xh =v;3h~3-C4N:RR)//5 ^Y>$Q[s,uIZV0`@OG _c{_$\W t @-/_"Г1'}2!5'-i!ai5wWk^|Ixg&`h%l@Jxw~1=_[.cM@~ F4n<,U~BhPmPpxF& Dp*R{*n/PJ@FhV&Zw__|gQ4ϨgCxvm \x ,=Y¸y#9 ۿC;!`6cHwGU/Ti'u*ÁV~£}C`6 v:3jcMŋBs UO(စxT:Tz)X/R@Bqw(O? Yhk?Ez*LW%jʑY`N},q`S1=vi|1e7Gn>r;38pI 'GX汉ni2#` 0<@Wgܚ4?pQ/.;i6 ZO`s_ ~b#6B3 Zwi!h4~Ҹ>5 \có5m|M: yaxi3[ꠌZ !ʁףP5eϡH(0xtmܬj%& g/s_jf^~HF$.QvT‚Z+,p<ۃZ}7S̏A*xJ%c . F{Y0`,8O :\^0ҍ/c=(6u |= -Ʒӯg7|lxןf ctab_#Mwƨx\|]h}L?.ݏ~Q6CñcQ|nZ M5 5Bb1`\eUf\c YGecKWrEZ٬}p0wzywEuHSQV"§qm1 &.x? Ӷפa&lo>O;Ndh';E*!o ~8q*v2s֏8 sӮ5sMSrwJժa) ujAyC5gn8qAP8/6SW?A)M`vƕMl+aҀp N}o+B=6=jV0Ey>W|w>^>|sJ#\=9U$G uiy#oT͖'bdB\Dz{XG:bR]kA؄tN˱;E kڗEx=, NR;CMDq7fc®oEZЪ>AE>yF }Yj8Hp5LG_&AyY<Vdr 粪<kcnb"6C']z_y'rL}}&4X,{x0 @V'xb`݅sW͆3k ϏޒYvG QPÝL,YSVxvKYyYIHN/H&"yvq(hɻP[=̃m$dIIc0Ky>-j2=:xܰ]U*jl\T;G ;X:.`sLXsκ@|X6'A B1!uj,'j˗l]ar0f/|?b~afsGf?8ߟ 0I1Moca~0Gyb^/|h{rWcPفfVοĿz}/HЋs makoo{Êҷ ^fWؔ9"1擐|!M@7D`"nS2/g5L0!?Jy/[;Bz@֜}5A+_~fCc(&M[J/ͤet7pM\݇ ;_n-*+(IcPHnJj%/eL b,0 9ϟDuuS9ZP ZeghO |+};9a,lo;͖L@fAjJtTM|t};5T!4cҰHcx ꁨ#{p?oI};~}lk=,`<(=Q, $q/XcKpt!_>yo/c}ep<],`x Ʀ[$2Az\oki[vzD.iǿJ,;M*7!a0!,|S9, ,u\MQ-_qvX\|TbױL6,o-uh|ԑ3ơurсNR ԑv)So)Ζ;>_^K$OY>&)Q ]6^-W9_BF`n0q𡽲Ex՞SoÍJ Îb/->;q S^o=,n3YI˸Ilł`e x ~$N\^oW w{`$TP qH? !ލ˂S߭~ h0 ʇB_笗(TA~=5drJO~k:>~ &lS̓JhJ%XT˜d+o];=~"ZL@o⵽$؋V:- NM~O6]ޏuw_Zb)=3ť^`mv5e(>>fʎG7W8&Lx|ҫdj@|CPB#xPgS+|:3d> )٣GMvFʂgwvxoo{M|BqAʄ4{b::zF۵dǿ.f8~>WA9 чͬغGK#o:(ܔ,3u\%0;`iQn$XV?2t-B>U&^' GєY.*SW'bg`bCZ.zʴY/*0tex.av,|Х pZ Iw6M}˲/X,h{Jjպein՝CbOE<~Q>[_S>8@Cہ :F_߲֔c+V5mICow]Sʹ*T) IDATú2%θDSzPq eI`HH 4dή25 ixַ~`@4-|7Rэ*?6#=*S a=05s% KhKrR G}n_r{A}yG^SypOMwϞe?Dt+«Ɵ7s3B66|teDS` vx=-|MzakA]eo~%W9ҙ`"/>xK6$$Skf`A^Qջl23[ߠ>i>ڳ;`g?IV\,Uq!, c8%QXfRӶO8^@c8]UPI6ڎ:!% cO `<  z*j?puW'`e{8.8e ʡ1WطFGzÆ?n[{cM^t2>9¨N%u52 Ȉ:go}í>r=h08gQ'~VH9y?!$'7PvL|ƭ5'zT~BaƯe dS|Osa3h2UYi% 7!2atQq+L BOgPCY5}DJ1qH]@'A&^/`aȘ[-n6ߝp͵.'$gѣrgNvٮd)p[k5{KM ?S;*k{˺5w.[(#S&&ruK%?z|pK׮=_:ͳ\x_šQig F)X `\{ Gn3a-e6m"|k/pU/l$fh(Fq58ZSh5&isZ˵S̄$C#]hd'9瑾1 {g ej ^{jF:`"v,؂/됦Kwvϴ̧M@<:j%*Ē eÂiƇ {C` V<ʶR2Ӳb˖-KɁJٽdcjw4T>{kVӞ1R_O7!pěTFVt>n}Q5D rihe8 u衽 |u/2%u8ycс⟇%NٚsZՒˮRfuReFC0zT9V4d8M|cg먓ny3>rӥ|Dߟa˰f[ ͙*˘z2p0|W_b]1x2?)@p޴eϮ-I8@'0zGcxkN* -qӉp0!0 Ac QKWA0xa+C P»a+uh3^$@d^[ E0R/~ggYP&Qmk)3: o"N Gx%zް ?Uʔ<؍RIf 2~ҦUe!<*JqNdɶ>6)`jG~d;~u]>p˼?m"L?4V` 4Wy הIHx7c 2x&YWGyP?؏u~\,"1tܩû ñF7~yEGQq zboX8mDgn+ /SUj A/Bk)]Q\ "]OP68XsS! FUg)'P3<_J0 u? q7ܤ3dx+T肱Hya>t^t~DeULeÖmtlU}/ O SO趯mg')سH@nlk^M)d& & G&ҭm=R*UF+Çb+W=mecƻ QMF \*&(Xv: ;8-j‘'~#ᅑGxfQ Zc-Q\{{"0$ՒKWptn槫n+c'>ow TN,(e'fKGxDfn|~k͕Gn2ؔ(¦8Pwp2`+䣗 U?̗A^x*SPSl'bQ4Ha0ApOq?f^ Jd'{p{;w? |gh`$ԀXvZW)*͈rDr2XHaU)7|+6_4י ?ʑ3~nyH ~#k,8t&ܤuS0 3_P}Kb& ~/^#JnѭO~с'ՉgikG_nu$I8H4P苌h5/C9NLb8N!Fѵa 6L&aixvi|iÆ8uҞpr&noDb߿m;}<ޓJ}^pk 3Wpk``+\9 IԦ BXWAP*D,elӁ1+UbܛRNo0HƏaa{3WlxSݼ;B[,PL, >֓ݰnl[%%-A/(~4 r"زî m|4^7[O ^)qğ˳sWB ;Q=ݥ(>ucÞ({UؽPQs!_<>g\+yKg͡g``94rR  H )5 n.YcN!2p9,pgF%_͆p`zб3WXOe:ko}]K8'nUI18`k:ݱ[xu FipA2[%MԚdlGn…pM5D  WČqn*%!<@*1z=\% ˋ~SOO* o&Ձ V;;DMX,oxU =W' P€y=Sy6)ߒJC:0<|y4Ff@hq8Wɂg mb賦T1M x~<\<ϏM3?ƙCgÑr&c)#ilHc9qQ{IJ4;a A yubE\"pDd;H9F }ta_$+^̕k_3=Be'"<1I0.3n)s˿YṪ4̝wC#GZxcOzɍ uCAu11|0cuwq8aT=2foS Kh'&Nkb:ɟh?p0Gǣz͟WYT^fX,m7s{va0wԃ|sTk^ r ^{ w($ҟ}t⾱Lv|P~С( (X-)x'SDS*MwU2R)34kG1K 7E"dWE&ʕ+r.Fh`V9  C"UgZꗏ #@&=1zqttHkIL5heQs/7(spԌ^Ǎq$m7Ipv. |+8Wqg "x^412{]0I&-w]{\uq <6c؅~;^ ƚfH{۫?QґYR!ֱ,9^Y3mWo+؟Ɍ; ᗋ|)<}Ň?vχOlݿƊ10$CHMe04dJL7F `+$i+Y, fg*Wvcul<`@:䂱Lf}{&/Xw,ʾ\vW /Vp̦r {  Lk:o!_:8b`՛:BY˃1@|'7ج4;$' ).5ԖwߢqÛ(3Ζ+}?qIR0?rLm&X(;tt_E!x؟Be+]t4I .ᬿ#~͔b  `Y 3'-$x1 CMch%}dxf }k 5>#D`uLABMA۟_*s恜p-;uGfG>9an]D֘>%*"ı=8g8RKדWeE2;~ToU7rŻ6)'q]c;sW؟caM=7?]f4nXxoIδiGfD݊즽#jd*ߎ۩_.ᯙ;@asRz၃b~q=Aќ39i\+)>rXjQ.iTda^ 41bh%/HA0GvpW>U|KWo Ga"G(-{MXHU#%  |9.kUURzvzM_W6i&̅[}@*~ c0y=J +ӗ.͂%!3S?7<5xF!gGfXs/6i_f{TX?/F^ϗ[)ZWB]؞~yFB-⪀+V/\I5NmG }@{ ԛB- a+0C<x(Q;wR(_h`7ux{ycc'Հp0k}? z [m^|ok: Y߁W3 .Hm^tw '6b\EO3&>rr/^4~ʷ$lK@ Kjz0 U݃ 尾TXYn qWpA+Y-\:hnNjA\뇞:fٗ:LT4Ǹtp|n#Vs[nrH4j ۳h{\Ƀ  /TW rxgUXxwPw.ST 7.Xje*~eYEXoߐ'vnNv }#W5ũK򃑹$TS0ܛN_*tg5rXVJJr^!{qK <֚[yPHz"Ƃ* h-ezpOװ@/3_Y9S"@J0+&1ENbȢ :z ESz0N_B4trӷb{ׁ* D?>?w3oϑ^7֦R=/q~B#y! %z{ߣ&nYx7K 7HToy ey ! 8IQԟS_Rpzlf ,H$%r$"יE)Ǫ4,NU*Ӱv3 A&O < 3A\TZ*r0(HBƂ 0x/zLi|zv~+x{S̀Rr.<{*h6  n>:op/#~*bEtp X*15u,!L}ƃy.eDzVXq?俾/-V?^{zk B.XlKtێ{DN3t^}a^6ёV'`9K"a _|ׅo›T;[z2EgQFB@%8@-Ɓ +Ƃ a'(tyblB=w|!?K9yJPpS(Haˁڧ@8UG9Cu4aEDHi"ޛӪZjT؇>jT i)女*;2CpX3>߫'T=z3Vz  :a%8۠c Օ^>! _r}鑖z:~?6 &lسz/# tpqUG+T `|*H,%,pBKzّ\6ǜ_?.9 ~5,l@J +{TkĀ]KVM𑀰!CVOsS=?\FjR M!ƠDy(D7 O%R|2I b /c^wϓ6o7"glbѿRQU7oyLkm0_ v$ܾqڃ5.}_l|z,,U ٭Tt.WQWn * ==>&L; U`,X [ bC%vPb&Ds@=zjFiAm ߚ' n.'K ?zk  z t. &V „2r7W~@ "'b30 "C34yF?7;Z|of,z^ B)UDՑ3]?̊|AVFXǬ@F|B >u9RW>~b"Ah|Ÿ˦s4/`upSOWZ0OQ 價R(A w=a+Oasl`P>~0-2tհ(Po=z;23gɝ2_A/2 .u{qmJ@E+!~SPUS NNi7063zuE\/fJyP~䍯 bE LLxKZ 0~=1O:ծ;9r \mfϝz=~yw_ûY|?~ͽY'C;O鿦;2!$:fc+ħk.0SNT,(|L\Ƨ !M{RWҕ+'O8wĐ|$| p(~% Ux@ Ѐ4‰Wz S{/-@!2]ذ^XT^PÐ^A|u\'mķ s98{C:zyHg2/(ϪGTtG!vXW'YԼˬp m,Y_#)7'Ys2&^ hh5sEq(H?3!6 nz]K-?ӉW&}Éjtyr[*,r>?&7j`,Ⱦ>3Ë:V` ZJ|4#Jٌx@b0H>P.NgU$5j@/!$AwA3`4 IA\ZT}`Ь&ߎ ]e59ͦjL!;p0@roTtx΂IۤhYGNzAdܐHc%w?7~ %ZVvnt| GzC|@QÉ\x% zH@J1ktޣJiwo w5``|HAqv!ŲA.DZl:X$T /}{yٺo?2ȟm >n7+Z7 5K2cx@pD ݷ_# ޤR'p uMe<-!J:r_V3/>&X$1A?ok'_S(iȸ%ǼE\OXQSK/ye2geɀ"l H?HKx`~zY/_UqirzzV1aԁ^kۇz_,uJ,僎K vV?oo>% $ߖ$u;}B*iB Hjpug=2ׁuۚ_3{~OBdTpy@UEw A4ʺ*Ƨȟ9"}l8T)^/YYz!dxt=3:VCmB CDW4襌4lwqݝ笝RR-{]ޝ@z_T}8pS7!X)~TPt  7IZtqka?H]]-L&*ݤĭbD_X^߃>=%jffjX\>/>7Ts{b~L5/! KDm. <4n5L6X;)H($w]OC*=lRz=;\WAVn>S<ڣi$0I5u,N[_'l_ʕ?}:>ا) 1K'YxWwg0ub{?|ϛk~W_U͹ItmO6m@;ؔET$^ ҐGN@$4!gj0]l~ZO۷OoP7+AŸnVO[{ܫLk>%]LVP.y c)5a".y&|}+@a _ ҇<\#e{ ^T.# C>4zSEkܜ'M׮Μ'/Z`'ߨJq@yC^6 {5_hЗ&UwK/kcOR|IazbJ-!*#r ܻթ$u-- o5BȒ%Q:ᇧ>*Ax fm]>-ԍ2D?ewJ.h@8f/4 ~Q7$}=@&O0fA=(hp\WfK 6S/!!),urE)gON\8Kqrrāȧ*c,q ?+>֜>u-@@/J8^r7;J/e AgѵЫtF0 ɽ;s`/|uOoLDP2m٬S,kF*=INSTw,2 8}هk^t]}"zE}`_A ȲjE6ͭE-k;IT {wจE:'| Ja4pPWK:7R`B7BAU!Ec;oHKfcc[S;1},Dr[%Gtq}]#돪T!ԁ׼VyR5Tq&FXM{rFN^TGKall=sR}?pmwCV !CjI!D"1@Wh$̍]{Y$mpK*%֌cv8Kg/O?3Or@\*^𩂠>\~#>֟QDH=Xw >>@J=<{~bfbOoə4DB?cp=ā}~rܘX==Һj6<<ҟole6Aܪ#?I/Tjk>* `|+.}T݀2a+WMzOM A|'S^v).U Ajrf/=&"VTV<o_#RYԡ'xJ2__ o8   jo`+?.③R/AsHhL94yyoIJE }>|r9|NoӽN2M 8kh7P^^7?xfb+Cbejfn :Qď>Qυ.oUZ ŶxlHp` ~v^u}0R¤mzP#1܆H.9GPz~nxb ,?6.wЃmXQ0~|ƛwAHL<Ÿ]}N{T_[JPcǿCUsFm@?SFS/u>saP_>nm߈q:+K&~Xg)ޗzD@F$:_§ Si  ɏpoz3e2{i@D}zG˗hз#-X`EЬBNet;zH8srښӉ B &%@L{9y.bllb0⣟ IDATUGH8M {Uyv8lMmvKvpXLJN+}buu였*!3"B#e&κjq W,/ .\>#M?֣/kf]s=/c~i'\~'TG$ʐ"ʡE*Px/"q`-/RwǵHMzW ó6a׾m!8/n|1|7~<.pg&HatCA(iH!@H`}l[#dYs.@Iк+<dL&^K kX7 _K>QOgG<:|eaS}.|)Z7EBKG .^Z]ז5np#@bT1/_;  ~_%6  :(H:r?~"~"<=ݬgTȃr :;p _[17I wkq9n^i;aW53&,k> ӸH(Q*-A/HN:" L PtD#K=Nf*nُg]eJѸ׀o/] _Mt1?9,\C`jzq4nK$1\Y8Ps6x %,1f `pj zB >kYp)lq4`΀4%8o]< LKʁ{zw,rR'pf:_J:³ў%9ul\#&] ,#u"AzZi[)= SKZA ~5L/Q'&Kh( $ŀ̗!sm(Mj _H~ $P/-M۽ Q&rcߨ[1zeȟ ane؇o ͡YCx!5{qc ufu}󒷥:.y. v'aCvkC q#>oT6}˾.?#’Wtj .ѐT _6҇9 JWv8OA"H;:'?1(ձ?Zfwk0>,l7P 4FO*Р <0LS K-ߞGvG=Rc_y^,4,|}nVnàO'>"U}/QD_ܳ×JO_rp^>F)ܗv5վ?S/? ~\|䢧%Cqǵ NVwR&XVίb uTw)Uz],:ؔ܂q" N恪lq_{B }izNU:ߋ_SޯJ *E=O_|Z?( s,60䡟dMzv!)>D!~Bu#_1쁜|ȟ[hC_shȟyTZ@?[AF$AV`@$ 6t Kt :}#49:c(o֛p{*/N"^ t:y Z(x9a?*8i_1\PI_vwm].*iOWY"K P}/~Whum#~K難_nbr? /V.[TC Ģ@d56t Kt :gMc7\LН(ڒB1B+a|KbנW,@knIԳ'sjUG?}K%xJ ; auf{]uenm$$ooAkYl--z}@X>j]G5p O%߁;9-aSvp97R^3YlbMBیXpaGB0zjrz$rSETؐjyߧzQ/W] H1)zF>W2D M75&y,, ʖ@X^Qoo["~(ȟb~1KiUrˉ翴zZz9Ȭ;2E.`.tJrc۱cɳYDl$tJ̯>dB@ @B PbQ8ttc˨]/Q^gyȽ?Fuw,]:(0[A lY†!`:Ik6X-W %GT6 ߼BD4K/>IH#DEmtS {ݦ>nTfDN^> r}M ۘ xcIpiHv+A\X-o?& M߄j\9g>? ('FoDQKH(Pѷ呿i7089(q$p7";8w bҀ`D 9`kN(6!q>V>KQ%4 jrA~ۿA HOr3ryG:ڀA]A"tw?H';aassZ?9{? Zׯ^9!h]KlꇜG^Zͬ ^6E~L1 's@nGPT3a6[aC X%C*C=*uV)P/B*s/;o'܅ڀb`ntNo%+u=kղTڨ:OnT'7wiϡ? b}?Kzȟ5ΞbcKl7q+fH1BXA0H=@6"vU3@-=Bul.xeռH _/fTsjV^ !zNu[O3vSoH5NXmHx\]{U9=M;z j6jD Zw"~#, (d-І%ڠ% 笃^5@?vdTHt΁>Vj@ A:N[ X9*.d#O|1s~?ywדRqz&usJ{:L1KhlvL$? p]|ZM*gE|.94/uc ]!'O#}kpk>5o|APB?Z܇f?'-,-v}bf$)>Ab@ sv鬫 FMM8bD\y& 1N;FMTۣNzDtATiP{MeyXP509NO/EM}_.1xyA첺jDW_H?z EOij"} W Y,.5@kuĚ%rtzݢ"J[@Li[@|0ib(|C VB`~=1w"A( }l‹'V~SjUu0HM'q*esG ܖ fTܘj/|vrcfs14ǎi*@|׎}tA$ x<В (g:/ ` kii;/nuBr>0uwZY y ܾ@$'\ hR׹ѨVT\Nb B]B"'rtFm1ʷmqШD"&1J-h":T0OI kaDA#a@B_a@) 5 VT.MUn1P ?1hنrPu@j7x9h!?H7 ;4:㻪^*Z@]XxgyPoϡwr͖C#]fإ J(ڇIL 1@$OE5Ө%(+I8K~Y an;K²KJߎkH H6!Z,_ *Ï 򘯯GH"~K2 Шg>m3>R h{#E6h}U+[X[ȵJu=wIP hl S i b)Z2 $\Hp0 TBrLT cA\B Mďb%И'MLRaۃ]H\,j0C>7lش|OY>+EOxȼqk4=}qPX Svq lʀz T{4D%Hp o,Q &haC K'cRO̞ʷֿ+*tAX (qy*Q7Unu8 D5\YX uV^% uz؋߷DsnB5ceRl% 4lX _t0Vm^p[z_dW+ YK6G^ =RmRk_e?T^~~GXb%_Cz`Fn@8=J ô4+" fK lԻ^XYi'Fk'=!հ6t Kt 8ƕzzӏ?C@<29:Pp|8[a, `ꀼ%()鍙\,(%TvM1P1@| .+B u cUk .Ӗp6fS؟uOk  dn|L"qƽD`cV{kRUA,22xwp:Db@ (uHHXij׉8ja|ɿ/@O&lgƶ^35ۻ`]n |@$v_k5f [*mQ# h3CT% ᐸ#ƖmCBK܌/5e@#ϤLy%nD %6<5ٙLxJĽoiLnt` VLT1aO"IIXI W 0℅w:Hj Hv@%CP@Q'r> %6=KɿJ= {? uҬAB$-ň$]~uhmqPgAmυO޼ `u l*C "('B! DeY)ݼN}@ݍ]d7{!` yXt lJ}C1zc@ Zӕ-U??޹N*P^(>e&i  fO vw-W۟-bO>A@M A\'a͊$@P:P7B[ J b{(+Fh% ;7`1od|mJLTV|&~6I~ľMw]K?奼t2 BM]Kp@$rW|.MD );4Hi]61O k L3X_mv `rz>:;)z칳cs3].I]?ift=Oy\OV9GVvmVCnQb?cgϳ.it!3/d)91t Tb1mG衆C)Ug1WN2Fq#|]:hi7&NC1 >з'-# rJ r# G7X A'D˭L'ff'J]gN|z`?TC;'*BNlqt'@qhHyf'B<bHA@>}?_ZeT|f6 &5{1Fzp/X"@Bt|W G|>)bD8I\c' +cv}Dq˭|NhQL?!Ƿe9G/p^a:+'GC8 %ʼn L?t^{6u!Q ؋Z؄gv:S맸O]KOSZGFfFd$>[߲rD_C3&Id' A( t=a9eXיdBaI° U, x6LP>ăZB "0 RM* g]&fL\ϠEy=EH2ş{Mz3o =Ձ~/WR,8jmpY}a!7Wg%Ob}.IJ3^CW52cj4=vM,0w# gElKRbxɣs̑g9@a 4.wį vprJ?`ZHO^ݫr  y6 SnZu 98bKGPH$\NI(D0!|J`*いH $:d h}(K,|-ydYF?^B5'Z!ơ?f0 xDqy()5_: &*]DxPVaf`!7_r혭 og}o9 ((=e3l@\܉;iA#spzމ˘3~>d0(Ӵ5s.BO*@B(80z8`D@)? ܰG#z!@@Řl\@hmxf DԠgl iyބ:m=:̓M!Z==B,{uq XL$$4 M(("Iui.Hܤ@f;563 o׉xNmdq͜G%$סXag&>ݻwo6=+5 zP`|.CS{b ~ĮXx`9dJ OM?S@ngK)@ bRf".ER }$1m.QrBPC%G,hX m@#Qԓm.(A<Ο' J !S}Dg`<^s|.*gr1#$@N]!IXZdlӃ8}_ [N_Vd9M=q ~8 "T*eA3'}@ !GoTu<7j:iWa "3Mc$u:AgJ`=P;%mjm@b{CUwT>ѽȭ"WBDQ&n?j׳&AH[&'΁".XQ(P%)@.Ab@-0C {nR֝DkU*OO?OIPR.LNbXR*3DcZ2 *˼e:N.i 8d0O>,D QD?ZI-jN}r)tsi.]S_6*ӍkvF?2Vr7]ZS;mZ!` BʖۑH81Ҁ<~^7p .B, )\{HOm" !#І ڑ9"OsMݟV?x|Fl̜z8YpSdkjIW.cm>AWϜG9_>e B[W !pT{4Z: *C! -@3foOp-}?CTk6>`cqO %}/= ~ +z 6%§D+{͈]4򛚚3umI Kle&@*fU]T @9ғ`m|~CCp7c1uD@@n9[N/B_%}\ Z@㏦`,?iDu"W\TEkՋ/Roȭ }{eBf_4^EXheZE?3Q-@ B``ppoqnf3y9QePvô<)R{.[`GQFxz晹ZRjJ\qzY3tV8"xo*x ny۔%lOB @;9`&qFp;W\( |V =׻y>r0!b,%DD'~ub_jeO_:ne2/N8G{u$`_M5R::^H ` , vYzlq>mƉcՀZk~= ЄhP$!_0b~:ּܡ{RO~מhܙ#4Kfp tWRxCj),U網m-b!` ,DA-+`ɠ n۾s& `i^pw?2#D"SU֋|_}sc=i^4[j a+*"5v`[B`, B`5$jq^ bxD|8ۻH>EiZwD?tM$KT/ŚyzbbR߁جN|pQ?Mլl[u !` acX\$:},P 8X6t$">pE{zp~6Nm0= h< =G1l6[mԚQX(YN;p >ܕω}o f ` j!@rE)>;ac!X2h 'Ql-0|=GnvlE}4僲pDȄ53OM?AV0wڵqDz?mޚȿUk^g!` `!@"@xe`,N>^>A 6Z-޻D ;|b*d j@T-7>?9y8J6/͔&f',@j:b\VY`!fBֵ!`}`a,D͆!KB±Cݻp]e/)䀍@v3lTBm|B~އwODt85(p7j5 v-MA6fCHP aoBR6~n  =P_c=4xax%b'AJC7 ?"B}8!krLts NL㾚 v%Z~Gun8إ\? p{ѭaxl1oy=ڶ@ !RG[V63!T 0cU@ؒ308\,Eٝ!/^>gIDAT:jpS,kOhnZoM/щVԪϥ|&=W/}v<ϫxR4}K-}ܶ@ !d᰷7ѡ > I}x> "hP ~~|σ{{2'zB0 ;Em=竹F*_s̬+nC?/9ֺd)l NVζZ5tJ]K.`p3!D*@ ^Yx,"s\A[p{z] WA6L )_6t"}zKR>u׮*۫__~_c,S!tjHMXʧjA/}@_L K@ڪ-V#,5* i@4N6PÞXFog[p< F b @ Ā!Kk⢗|>]7DsG>"z3}AFԝ)@TC_kc? PϴH `T\5 <!p@H$`/mxt$ 2t}Cez | 3!P1@" _@8쉡RIFg ֏rud n_\q_"Głnܒxn ,,>} p; 9< I M #RQNԃ%=؄H| ۿ Toǻ'n M-͏ =uiru3X{~dV:-!Vz ?xXS_E?kf7lJV]v= !0<-Qg>9}\c\z*Y1?`V%W!Qu4Pyp5H$/d`e!B/޹e[٠jCLf ~Dþ2< ĚHgX>`V%ꗱe!@ !|?v9 e>ĐÉz3`C"@e@pJ<`P_S#ywW!G5 |kbey^~?[nZ mKle_uwC !<2pC5A6F" 8))즗ؙnmq~"V>11Auڳm6%dz;!4Ka@Nn3>p \7Ft %X7A,+ 8keqR!X ؞;@ !D*~Gi8 ۟nn n0 / aLauL> npaܰ ll!s im@…om@"L&Nr.t^&h_7a3je6~?`%vǵM$>6 ` x֊v ]K좏m{!@ E|kؖbX`|t    Y{o[n!`!`!`!`!;!` m-,,,v9us>9IENDB`ibus-sunpinyin-2.0.3+git20181120/po/000077500000000000000000000000001337507011600165275ustar00rootroot00000000000000ibus-sunpinyin-2.0.3+git20181120/po/.gitignore000066400000000000000000000000421337507011600205130ustar00rootroot00000000000000POTFILES stamp-it Makefile.in.in ibus-sunpinyin-2.0.3+git20181120/po/CMakeLists.txt000066400000000000000000000007241337507011600212720ustar00rootroot00000000000000include(Gettext) set(POT_SRCS ../src/main.cpp ../src/sunpinyin_property.cpp ../setup/setup.glade) set(LANGS zh_CN) set(POT_FILE ${CMAKE_CURRENT_BINARY_DIR}/${GETTEXT_PACKAGE}.pot) if (GETTEXT_FOUND) GETTEXT_CREATE_POT(${POT_FILE} OPTION ${XGETTEXT_OPTIONS} SRC ${POT_SRCS}) GETTEXT_CREATE_TRANSLATIONS(${POT_FILE} ALL ${LANGS} COMMENT "Creating translations.") endif() # -*- indent-tabs-mode: nil -*- vim:et:ts=4 ibus-sunpinyin-2.0.3+git20181120/po/ibus-sunpinyin.po000066400000000000000000000070211337507011600220630ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-05-09 21:02+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" #: ../src/main.cpp:107 msgid "Simplified Chinese Input Method developed by SUN" msgstr "" #: ../src/sunpinyin_property.cpp:62 msgid "Switch to Chinese input mode" msgstr "" #: ../src/sunpinyin_property.cpp:65 msgid "Switch to English input mode" msgstr "" #: ../src/sunpinyin_property.cpp:77 msgid "Switch to full-width letter input mode" msgstr "" #: ../src/sunpinyin_property.cpp:80 msgid "Switch to half-width letter input mode" msgstr "" #: ../src/sunpinyin_property.cpp:91 msgid "Switch to Chinese punctuation" msgstr "" #: ../src/sunpinyin_property.cpp:94 msgid "Switch to English punctuation" msgstr "" #: ../src/sunpinyin_property.cpp:167 msgid "Preference" msgstr "" #: ../setup/setup.glade:7 msgid "SunPinyin Setup" msgstr "" #: ../setup/setup.glade:44 msgid "Quan Pin" msgstr "" #: ../setup/setup.glade:57 msgid "Shuang Pin" msgstr "" #: ../setup/setup.glade:78 msgid "" "MS2003\n" "ZiRanMa\n" "ZiGuang\n" "ABC\n" "PinYinJiaJia" msgstr "" #: ../setup/setup.glade:102 msgid "Pinyin Mode" msgstr "" #: ../setup/setup.glade:143 msgid "Chinese" msgstr "" #: ../setup/setup.glade:156 msgid "English" msgstr "" #: ../setup/setup.glade:174 msgid "Chinese punctuation" msgstr "" #: ../setup/setup.glade:189 msgid "English punctuation" msgstr "" #: ../setup/setup.glade:206 msgid "Full-width Letter" msgstr "" #: ../setup/setup.glade:221 msgid "Half-width Letter" msgstr "" #: ../setup/setup.glade:243 msgid "Initial Status" msgstr "" #: ../setup/setup.glade:283 msgid "Fuzzy Pinyin" msgstr "" #: ../setup/setup.glade:297 msgid "Auto Correct" msgstr "" #: ../setup/setup.glade:312 ../setup/setup.glade:958 msgid "Fuzzy Pinyin Setup" msgstr "" #: ../setup/setup.glade:327 ../setup/setup.glade:1256 msgid "Auto Correct Setup" msgstr "" #: ../setup/setup.glade:348 msgid "QuanPin Setup" msgstr "" #: ../setup/setup.glade:365 msgid "Pinyin Mode" msgstr "" #: ../setup/setup.glade:424 msgid "Ch/En Switch key" msgstr "" #: ../setup/setup.glade:488 ../setup/setup.glade:1202 #: ../setup/setup.glade:1382 ../setup/setup.glade:2254 msgid "None" msgstr "" #: ../setup/setup.glade:508 msgid "Full/Half-width Punct Switch" msgstr "" #: ../setup/setup.glade:588 msgid "Page Flip" msgstr "" #: ../setup/setup.glade:608 msgid "Keyboard" msgstr "" #: ../setup/setup.glade:681 msgid "Character Set" msgstr "" #: ../setup/setup.glade:723 msgid "Candidate Num" msgstr "" #: ../setup/setup.glade:734 msgid "Memory Strength" msgstr "" #: ../setup/setup.glade:809 msgid "Punct mapping" msgstr "" #: ../setup/setup.glade:822 msgid "Mapping Setup" msgstr "" #: ../setup/setup.glade:841 msgid "Symbol Mapping" msgstr "" #: ../setup/setup.glade:861 msgid "General" msgstr "" #: ../setup/setup.glade:872 msgid "copyright (c) 2009" msgstr "" #: ../setup/setup.glade:881 msgid "About" msgstr "" #: ../setup/setup.glade:1187 ../setup/setup.glade:1368 #: ../setup/setup.glade:2240 msgid "All" msgstr "" #: ../setup/setup.glade:1436 msgid "Punct Mapping" msgstr "" ibus-sunpinyin-2.0.3+git20181120/po/zh_CN.po000066400000000000000000000107171337507011600200760ustar00rootroot00000000000000# SunPinyin # Copyright (C) 2007,2009,2010 Kov Chai # This file is distributed under the same license as the sunpinyin package. # Kov Chai , 2007. # msgid "" msgstr "" "Project-Id-Version: sunpinyin 2.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-07-23 00:07+0800\n" "PO-Revision-Date: 2010-02-18 20:18+0800\n" "Last-Translator: Kov Chai \n" "Language-Team: Kov Chai \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: setup/setup.glade:461 msgid "Ch/En Switch key" msgstr "汉/英切换热键" #: setup/setup.glade:764 msgid "Character Set" msgstr "字符集" #: setup/setup.glade:545 msgid "Full/Half-width Punct Switch" msgstr "中/英文标点切换" #: setup/setup.glade:243 msgid "Initial Status" msgstr "初始状态" #: setup/setup.glade:671 msgid "Miscellaneous" msgstr "其它" #: setup/setup.glade:625 msgid "Page Flip" msgstr "翻页" #: setup/setup.glade:102 msgid "Pinyin Mode" msgstr "拼音模式" #: setup/setup.glade:385 msgid "QuanPin Setup" msgstr "全拼设置" #: setup/setup.glade:924 msgid "Symbol Mapping" msgstr "标点映射" #: setup/setup.glade:964 msgid "About" msgstr "关于" #: setup/setup.glade:1270 setup/setup.glade:1438 #: setup/setup.glade:2310 msgid "All" msgstr "全选" #: setup/setup.glade:297 msgid "Auto Correct" msgstr "自动纠错" #: setup/setup.glade:327 setup/setup.glade:1339 msgid "Auto Correct Setup" msgstr "自动纠错设置" #: setup/setup.glade:658 msgid "Cancel with Backspace" msgstr "用 backspace 取消选好的候选词" #: setup/setup.glade:806 msgid "Candidate Num" msgstr "候选词的个数" #: setup/setup.glade:143 msgid "Chinese" msgstr "中文" #: setup/setup.glade:174 msgid "Chinese punctuation" msgstr "中文标点" #: setup/setup.glade:156 msgid "English" msgstr "英文" #: setup/setup.glade:189 msgid "English punctuation" msgstr "英文标点" #: setup/setup.glade:206 msgid "Full-width Letter" msgstr "全角字母" #: setup/setup.glade:283 msgid "Fuzzy Pinyin" msgstr "模糊拼音" #: setup/setup.glade:312 setup/setup.glade:1041 msgid "Fuzzy Pinyin Setup" msgstr "模糊拼音设置" #: setup/setup.glade:944 msgid "General" msgstr "通用" #: setup/setup.glade:221 msgid "Half-width Letter" msgstr "半角字母" #: setup/setup.glade:364 msgid "Inner Fuzzy" msgstr "支持内模糊音节 (xian->xi'an)" #: setup/setup.glade:691 msgid "Keyboard" msgstr "快捷键" #: setup/setup.glade:78 msgid "" "MS2003\n" "ZiRanMa\n" "ZiGuang\n" "ABC\n" "PinYinJiaJia\n" "XiaoHe" msgstr "" "微软2003\n" "自然码\n" "紫光\n" "智能ABC\n" "拼音加加\n" "小鹤" #: setup/setup.glade:905 msgid "Mapping Setup" msgstr "自定义标点映射配置" #: setup/setup.glade:817 msgid "Memory Strength" msgstr "记忆强度" #: setup/setup.glade:525 setup/setup.glade:1285 #: setup/setup.glade:1452 setup/setup.glade:2324 msgid "None" msgstr "全不选" #: setup/setup.glade:402 msgid "Pinyin Mode" msgstr "拼音模式" #: src/sunpinyin_property.cpp:167 msgid "Preference" msgstr "设置" #: setup/setup.glade:1506 msgid "Punct Mapping" msgstr "自定义标点映射" #: setup/setup.glade:892 msgid "Punct mapping" msgstr "自定义标点映射" #: setup/setup.glade:44 msgid "Quan Pin" msgstr "全拼" #: setup/setup.glade:57 msgid "Shuang Pin" msgstr "双拼" #: src/main.cpp:104 msgid "Simplified Chinese Input Method developed by SUN" msgstr "Sun 公司开发的简体中文输入法" #: setup/setup.glade:343 msgid "Smart Segmentation" msgstr "智能切分" #: setup/setup.glade:7 msgid "SunPinyin Setup" msgstr "SunPinyin 配置" #: src/sunpinyin_property.cpp:62 msgid "Switch to Chinese input mode" msgstr "切换到中文输入模式" #: src/sunpinyin_property.cpp:91 msgid "Switch to Chinese punctuation" msgstr "使用中文标点" #: src/sunpinyin_property.cpp:65 msgid "Switch to English input mode" msgstr "切换到英文输入模式" #: src/sunpinyin_property.cpp:94 msgid "Switch to English punctuation" msgstr "使用英文标点" #: src/sunpinyin_property.cpp:77 msgid "Switch to full-width letter input mode" msgstr "切换到全角输入模式" #: src/sunpinyin_property.cpp:80 msgid "Switch to half-width letter input mode" msgstr "切换到半角输入模式" #: setup/setup.glade:955 msgid "copyright (c) 2009" msgstr "版权所有 (c) 2009" ibus-sunpinyin-2.0.3+git20181120/setup/000077500000000000000000000000001337507011600172515ustar00rootroot00000000000000ibus-sunpinyin-2.0.3+git20181120/setup/CMakeLists.txt000066400000000000000000000010211337507011600220030ustar00rootroot00000000000000configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.py.in ${CMAKE_CURRENT_BINARY_DIR}/config.py) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ibus-setup-sunpinyin.in ${CMAKE_CURRENT_BINARY_DIR}/ibus-setup-sunpinyin @ONLY) install(FILES setup.glade main.py ${CMAKE_CURRENT_BINARY_DIR}/config.py DESTINATION "${DATA_DIR}/setup") install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/ibus-setup-sunpinyin DESTINATION ${LIBEXEC_DIR}) # -*- indent-tabs-mode: nil -*- vim:et:ts=4 ibus-sunpinyin-2.0.3+git20181120/setup/config.py.in000066400000000000000000000001531337507011600214740ustar00rootroot00000000000000prefix = "@INSTALL_PREFIX@" datadir = "@INSTALL_PREFIX@/share" localedir = "@INSTALL_PREFIX@/share/locale" ibus-sunpinyin-2.0.3+git20181120/setup/ibus-setup-sunpinyin.in000066400000000000000000000002531337507011600237330ustar00rootroot00000000000000#!/bin/sh prefix=@INSTALL_PREFIX@ exec_prefix=${prefix} export IBUS_PREFIX=${prefix} export IBUS_LOCALEDIR=${prefix}/share/locale exec python @DATA_DIR@/setup/main.py $@ ibus-sunpinyin-2.0.3+git20181120/setup/main.py000066400000000000000000000573311337507011600205600ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # Copyright (c) 2009 Leo Zheng , Kov Chai # * # The contents of this file are subject to the terms of either the GNU Lesser # General Public License Version 2.1 only ("LGPL") or the Common Development and # Distribution License ("CDDL")(collectively, the "License"). You may not use this # file except in compliance with the License. You can obtain a copy of the CDDL at # http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at # http://www.opensource.org/licenses/lgpl-license.php. See the License for the # specific language governing permissions and limitations under the License. When # distributing the software, include this License Header Notice in each file and # include the full text of the License in the License file as well as the # following notice: # # NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE # (CDDL) # For Covered Software in this distribution, this License shall be governed by the # laws of the State of California (excluding conflict-of-law provisions). # Any litigation relating to this License shall be subject to the jurisdiction of # the Federal Courts of the Northern District of California and the state courts # of the State of California, with venue lying in Santa Clara County, California. # # Contributor(s): # # If you wish your version of this file to be governed by only the CDDL or only # the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to # include this software in this distribution under the [CDDL or LGPL Version 2.1] # license." If you don't indicate a single choice of license, a recipient has the # option to distribute your version of this file under either the CDDL or the LGPL # Version 2.1, or to extend the choice of license to its licensees as provided # above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL # Version 2 license, then the option applies only if the new code is made subject # to such option by the copyright holder. # import sys import os from os import path try: import gtk except ImportError: from gi import require_version as gi_require_version gi_require_version('Gtk', '3.0') from gi.repository import Gtk as gtk try: import ibus except ImportError: from gi import require_version as gi_require_version gi_require_version('IBus', '1.0') from gi.repository import IBus as ibus import gettext import locale GETTEXT_PACKAGE="ibus-sunpinyin" _ = lambda msg: gettext.gettext(msg) XML_FILE = path.join(path.dirname(__file__), "setup.xml") SEPARATOR = "/" class Logger: @staticmethod def pr(message): print >> sys.stderr, message class Option(object): """Option serves as an interface of ibus.config it is used to synchronize the configuration with setting on user interface """ config = ibus.Bus().get_config() def __init__(self, name, default): self.name = name self.default = default def read(self): section, key = self.__get_config_name() return self.config.get_value(section, key, self.default) def write(self, v): section, key = self.__get_config_name() return self.config.set_value(section, key, type(self.default)(v)) def __get_config_name(self): keys = self.name.rsplit(SEPARATOR ,1) if len(keys) == 2: return SEPARATOR.join(("engine/SunPinyin", keys[0])), keys[1] else: assert len(keys) == 1 return "engine/SunPinyin", keys[0] class TrivalOption(Option): """option represented using a simple gtk widget """ def __init__(self, name, default, owner): super(TrivalOption, self).__init__(name, default) self.xml = owner self.widget = owner.get_object(name) assert self.widget is not None, "%s not found in gtkbuilder" % name def init_ui(self): self.init() self.read_config() def init(self): pass def read_config(self): """update user inferface with ibus.config """ self.v = self.read() self.__set_value(self.v) def write_config(self): v = self.save_ui_setting() self.write(v) def save_ui_setting(self): """save user interface settings into self.v """ self.v = self.__get_value() return self.v def is_changed(self): return self.v != self.__get_value() def __get_value(self): try: return self.widget.get_value() except: return self.widget.get_active() def __set_value(self, v): try: self.widget.set_value(v) except: self.widget.set_active(v) class CheckBoxOption(TrivalOption): def __init__(self, name, default, owner): super(CheckBoxOption, self).__init__(name, default, owner) class ComboBoxOption(TrivalOption): def __init__(self, name, default, options, owner): try: default = int(default) except ValueError: default = options.index(default) super(ComboBoxOption, self).__init__(name, default, owner) self.options = options def init(self): model = gtk.ListStore(str) for v in self.options: model.append([str(v)]) self.widget.set_model(model) def __get_value(self): active = self.widget.get_active() try: # if the options are numbers, save the liternal of active option as # a number return int(self.options[active]) except ValueError: # otherwise save its index return active def __set_value(self, v): try: # if the options are just numbers, we treat 'self.v' as the literal # of option dummy = int(self.options[0]) active = self.options.index(v) except ValueError: active = v self.widget.set_active(active) class RadioOption(Option): """option represented using multiple Raidio buttons """ def __init__(self, name, default, options, owner): super(RadioOption, self).__init__(name, default) self.options = options self.xml = owner def init_ui(self): self.read_config() def read_config(self): self.v = self.read() name = SEPARATOR.join([self.name, self.v]) button = self.xml.get_object(name) assert button is not None, "button: %r not found" % name button.set_active(True) def write_config(self): active_opt = None for opt in self.options: radio_name = SEPARATOR.join([self.name, opt]) radio = self.xml.get_object(radio_name) if radio.get_active(): active_opt = opt break assert active_opt is not None self.write(active_opt) class MappingInfo: def __init__(self, name, mapping): self.name = name self.mapping = mapping class MappingOption(object): """an option which presents some sort of mapping, e.g. fuzzy pinyin mapping it is not directly related to a config option like TrivalOption does, but we always have a checkbox in UI for each of it so user can change it easily. """ def __init__(self, name, mappings, owner): self.name = name self.widget = owner.get_object(name) self.mappings = mappings def get_mappings(self): if self.widget.get_active(): return [':'.join(self.mappings)] else: return [] def set_active(self, enabled): self.widget.set_active(enabled) def get_active(self): return self.widget.get_active() is_enabled = property(get_active, set_active) def key(self): return self.mappings[0] class MultiMappingOption(Option): def __init__(self, name, options, default=[]): Option.__init__(self, name, default) self.options = options self.saved_pairs = default def read_config(self): if not self.saved_pairs: self.saved_pairs = self.read() keys = set([pair.split(':')[0] for pair in self.saved_pairs]) for opt in self.options: opt.is_enabled = (opt.key() in keys) # throw away unknown pair def write_config(self): # ignore empty settings if self.saved_pairs: self.write(self.saved_pairs) def save_ui_setting(self): self.saved_pairs = sum([opt.get_mappings() for opt in self.options if opt.is_enabled], []) return self.saved_pairs def set_active_all(self, enabled): for opt in self.options: opt.is_enabled = enabled class MultiCheckDialog (object): """ a modal dialog box with 'choose all' and 'choose none' button TODO: another option is to use radio button """ def __init__ (self, ui_name, config_name, mappings, option_klass=MappingOption): self.ui_name = ui_name self.config_name = config_name self.mappings = mappings self.option_klass = option_klass self.saved_settings = [] self.mapping_options = None def get_setup_name(self): """assuming the name of dialog looks like 'dlg_fuzzy_setup' """ return '_'.join(['dlg', self.ui_name, 'setup']) def __init_ui(self): dlg_name = self.get_setup_name() self.__xml = gtk.Builder() self.__xml.add_objects_from_file(XML_FILE, [dlg_name]) self.__dlg = self.__xml.get_object(dlg_name) assert self.__dlg is not None, "dialog %s not found in %s" % (dlg_name, XML_FILE) handlers = {'_'.join(["on", self.ui_name, "select_all_clicked"]) : self.on_button_check_all_clicked, '_'.join(["on", self.ui_name, "unselect_all_clicked"]) : self.on_button_uncheck_all_clicked, '_'.join(["on", self.ui_name, "ok_clicked"]) : self.on_button_ok_clicked, '_'.join(["on", self.ui_name, "cancel_clicked"]) : self.on_button_cancel_clicked} self.__xml.connect_signals(handlers) options = [self.option_klass(m.name, m.mapping, self.__xml) for m in self.mappings] self.mapping_options = MultiMappingOption(self.config_name, options, self.saved_settings) def dummy(self): """a dummy func, i don't initialize myself upon other's request. instead, i will do it by myself. """ pass init_ui = read_config = dummy def run(self): self.__init_ui() self.__read_config() self.__dlg.run() def __read_config(self): self.mapping_options.read_config() def __save_ui_settings(self): """save to in-memory storage, will flush to config if not canceled in main_window """ self.saved_settings = self.mapping_options.save_ui_setting() def write_config(self): if self.mapping_options is not None: self.mapping_options.write_config() def on_button_check_all_clicked(self, button): self.mapping_options.set_active_all(True) def on_button_uncheck_all_clicked(self, button): self.mapping_options.set_active_all(False) def on_button_ok_clicked(self, button): """update given options with settings in UI, these settings will be written to config if user push 'OK' or 'Apply' in the main window """ self.__save_ui_settings() self.__dlg.destroy() def on_button_cancel_clicked(self, button): self.__dlg.destroy() class FuzzySetupDialog (MultiCheckDialog): def __init__(self): mappings = [MappingInfo('QuanPin/Fuzzy/ShiSi', ('sh','s')), MappingInfo('QuanPin/Fuzzy/ZhiZi', ('zh','z')), MappingInfo('QuanPin/Fuzzy/ChiCi', ('ch','c')), MappingInfo('QuanPin/Fuzzy/ShiSi', ('sh','s')), MappingInfo('QuanPin/Fuzzy/AnAng', ('an','ang')), MappingInfo('QuanPin/Fuzzy/OnOng', ('on','ong')), MappingInfo('QuanPin/Fuzzy/EnEng', ('en','eng')), MappingInfo('QuanPin/Fuzzy/InIng', ('in','ing')), MappingInfo('QuanPin/Fuzzy/EngOng', ('eng','ong')), MappingInfo('QuanPin/Fuzzy/IanIang', ('ian','iang')), MappingInfo('QuanPin/Fuzzy/UanUang', ('uan','uang')), MappingInfo('QuanPin/Fuzzy/NeLe', ('n','l')), MappingInfo('QuanPin/Fuzzy/FoHe', ('f','h')), MappingInfo('QuanPin/Fuzzy/LeRi', ('l','r')), MappingInfo('QuanPin/Fuzzy/KeGe', ('k','g'))] MultiCheckDialog.__init__(self, ui_name = 'fuzzy', config_name = 'QuanPin/Fuzzy/Pinyins', mappings = mappings) class CorrectionSetupDialog (MultiCheckDialog): def __init__(self): mappings = [MappingInfo('QuanPin/AutoCorrection/GnNg', ('gn','ng')), MappingInfo('QuanPin/AutoCorrection/UenUn', ('uen','un')), MappingInfo('QuanPin/AutoCorrection/ImgIng', ('img','ing')), MappingInfo('QuanPin/AutoCorrection/IouIu', ('iou','iu')), MappingInfo('QuanPin/AutoCorrection/UeiUi', ('uei','ui'))] MultiCheckDialog.__init__(self, ui_name = 'correction', config_name = 'QuanPin/AutoCorrection/Pinyins', mappings = mappings) class PunctMapping(MappingOption): def __init__(self, name, mappings, owner): MappingOption.__init__(self, name, mappings, owner) if mappings: self.widget.set_sensitive(True) self.init_keys_values(mappings) else: self.widget.set_sensitive(False) def init_keys_values(self, mappings): self.keys = [m[0] for m in mappings] values_with_closing = [v or k for k, v in mappings] self.values = [] for v in values_with_closing: try: self.values.append(v[0]) except: self.values.append(v) self.keys.reverse() self.values.reverse() def get_mappings(self): if self.widget.get_active(): pairs = [] for k,vs in self.mappings: try: for v in vs: pairs.append(':'.join([k,v])) except: v = vs if v is None: continue pairs.append(':'.join([k,v])) return pairs else: return [] def set_active(self, enabled): if not self.mappings: return if enabled: self.widget.set_label('\n'.join(self.values)) else: self.widget.set_label('\n'.join(self.keys)) self.widget.set_active(enabled) is_enabled = property(MappingOption.get_active, set_active) def key(self): for k, v in self.mappings: if v is not None: return k else: return None class PunctMappingSetupDialog (MultiCheckDialog): # TODO: the UI should looks like a virtual keyboard, # user are allowed to choose the mappings to all punctuation keys. def __init__(self): mappings = [MappingInfo('togglebutton1', [('`',None), ('~',u'~')]), MappingInfo('togglebutton2', []), MappingInfo('togglebutton3', [('2',None), ('@',u'@')]), MappingInfo('togglebutton4', [('3',None), ('#',u'#')]), MappingInfo('togglebutton5', [('4',None), ('$',u'¥' )]), MappingInfo('togglebutton6', [('5',None), ('%',u'%')]), MappingInfo('togglebutton7', [('6',None), ('^',u'…')]), MappingInfo('togglebutton8', [('7',None), ('&',u'&')]), MappingInfo('togglebutton9', [('8',None), ('*',u'*')]), MappingInfo('togglebutton10', [('9',None), ('*',u'(')]), MappingInfo('togglebutton11', [('0',None), ('*',u')')]), MappingInfo('togglebutton12', [('-',u'-'), ('_',u'——')]), MappingInfo('togglebutton13', [('=',u'='), ('+',u'+')]), MappingInfo('togglebutton14', [('\\',None), ('|',u'‖')]), MappingInfo('togglebutton27', [('[',u'〔'), ('{',u'{')]), MappingInfo('togglebutton28', [(']',u'〕'), ('}',u'}')]), MappingInfo('togglebutton39', []), MappingInfo('togglebutton40', []), MappingInfo('togglebutton50', [(',',None), ('<',u'〈')]), MappingInfo('togglebutton51', [('.',u'·'), ('>',u'〉')]), MappingInfo('togglebutton52', [('/',u'/'), ('?',None)])] #'\'',(u'‘',u'’'), MultiCheckDialog.__init__(self, ui_name="punctmapping", config_name="General/PunctMapping/Mappings", mappings=mappings, option_klass=PunctMapping) class MainWindow(): SPECIAL_OBJECTS = [ 'pymodel', 'memory_adjustment', 'candidate_adjustment', 'max_best_adjustment', 'max_tail_candidate_adjustment', ] def __init__ (self): self.__bus = ibus.Bus() self.__config = self.__bus.get_config() def run(self): self.__init_ui("main_window") self.__read_config() gtk.main() def __init_ui(self, name): self.__init_gettext() xml_file = path.join(path.dirname(__file__), XML_FILE) self.__xml = gtk.Builder() self.__xml.add_objects_from_file(xml_file, self.SPECIAL_OBJECTS) self.__xml.add_objects_from_file(xml_file, [name]) self.__xml.connect_signals(self) self.__init_options() self.window = self.__xml.get_object(name) self.window.show_all() def __init_gettext(self): locale.setlocale(locale.LC_ALL, "") localedir = os.getenv("IBUS_LOCALEDIR") gettext.bindtextdomain(GETTEXT_PACKAGE, localedir) gettext.bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8") def __init_options(self): self.__fuzzy_setup = FuzzySetupDialog() self.__correction_setup = CorrectionSetupDialog() self.__punctmapping_setup = PunctMappingSetupDialog() self.__options = [ TrivalOption("General/MemoryPower", 3, self.__xml), TrivalOption("General/PageSize", 10, self.__xml), TrivalOption("General/MaxBest", 1, self.__xml), TrivalOption("General/MaxTailCandidate", 0, self.__xml), RadioOption("General/InitialStatus/Mode", 'Chinese', ['Chinese', 'English'], self.__xml), RadioOption("General/InitialStatus/Punct", 'Full', ['Full', 'Half'], self.__xml), RadioOption("General/InitialStatus/Letter", 'Half', ['Full', 'Half'], self.__xml), RadioOption("General/Charset", 'GBK', ['GB2312', 'GBK', 'GB18030'], self.__xml), CheckBoxOption("General/PunctMapping/Enabled", False, self.__xml), RadioOption("Keyboard/ModeSwitch", 'Shift', ['Shift', 'Control'], self.__xml), RadioOption("Keyboard/PunctSwitch", 'None', ['ControlComma', 'ControlPeriod', 'None'], self.__xml), CheckBoxOption("Keyboard/Page/MinusEquals", False, self.__xml), CheckBoxOption("Keyboard/Page/Brackets", False, self.__xml), CheckBoxOption("Keyboard/Page/CommaPeriod", False, self.__xml), CheckBoxOption("Keyboard/CancelBackspace", True, self.__xml), CheckBoxOption("Keyboard/SmartPunct", True, self.__xml), RadioOption("Pinyin/Scheme", 'QuanPin', ['QuanPin', 'ShuangPin'], self.__xml), ComboBoxOption("Pinyin/ShuangPinType", 'MS2003', ['MS2003', 'ABC', 'ZiRanMa', 'Pinyin++', 'ZiGuang', 'XiaoHe'], self.__xml), CheckBoxOption("QuanPin/Fuzzy/Enabled", False, self.__xml), CheckBoxOption("QuanPin/AutoCorrection/Enabled", False, self.__xml), CheckBoxOption("QuanPin/FuzzySegs/Enabled", False, self.__xml), CheckBoxOption("QuanPin/InnerFuzzy/Enabled", False, self.__xml), self.__fuzzy_setup, self.__correction_setup, self.__punctmapping_setup, ] def __get_option(self, name): for opt in self.__options: if opt.name == name: return opt else: return None def __read_config(self): for opt in self.__options: opt.init_ui() opt.read_config() self.on_chk_fuzzy_enabled_toggled(None) self.on_chk_correction_enabled_toggled(None) self.on_chk_punctmapping_enabled_toggled(None) self.on_radio_shuangpin_toggled(None) def __write_config(self): for opt in self.__options: opt.write_config() def __update_enabling_button(self, checkbox_name, button_name): """enable a setup button when checked, disable it otherwise """ checkbox = self.__xml.get_object(checkbox_name) assert checkbox is not None, "checkbox: %s not found" % checkbox_name button = self.__xml.get_object(button_name) assert button is not None, "button: %s not found" % button_name button_enabled = checkbox.get_active() button.set_sensitive(button_enabled) def on_radio_shuangpin_toggled(self, button): radio = self.__xml.get_object("Pinyin/Scheme/ShuangPin") enabled = radio.get_active() combo = self.__xml.get_object("Pinyin/ShuangPinType") combo.set_sensitive(enabled) def on_chk_fuzzy_enabled_toggled(self, button): self.__update_enabling_button("QuanPin/Fuzzy/Enabled", "button_fuzzy_setup") def on_button_fuzzy_setup_clicked(self, button): self.__fuzzy_setup.run() def on_chk_correction_enabled_toggled(self, button): self.__update_enabling_button("QuanPin/AutoCorrection/Enabled", "button_correction_setup") def on_chk_smartseg_enabled_toggled(self, button): self.__update_enabling_button("QuanPin/FuzzySegs/Enabled", "QuanPin/InnerFuzzy/Enabled") def on_button_correction_setup_clicked(self, button): self.__correction_setup.run() def on_chk_punctmapping_enabled_toggled(self, button): self.__update_enabling_button("General/PunctMapping/Enabled", "button_punctmapping_setup") def on_button_punctmapping_setup_clicked(self, button): self.__punctmapping_setup.run() def on_main_ok_clicked(self, button): self.__write_config() self.__quit() def on_main_apply_clicked(self, button): self.__write_config() def on_main_cancel_clicked(self, button): self.__quit() def __quit(self): gtk.main_quit() if __name__ == "__main__": MainWindow().run() # -*- indent-tabs-mode: nil -*- vim:et:ts=4 ibus-sunpinyin-2.0.3+git20181120/setup/setup.xml000066400000000000000000004523051337507011600211440ustar00rootroot00000000000000 1 11 9 1 1 1 False 5 Auto Correct Setup False True center normal True False vertical 2 True False end All True True True False False False 0 None True True True False False False 1 gtk-ok True True True False True False False 2 gtk-cancel True True True False True False False 3 False True end 0 True False 3 2 True gn -> ng True True False False True True img -> ing True True False False True True 1 2 uei -> ui True True False False True True 2 3 uen -> un True True False False True True 1 2 iou -> iu True True False False True True 1 2 1 2 False True 1 correction_select_all correction_unselect_all correction_ok correction_cancel False 5 Fuzzy Pinyin Setup False True center normal True False vertical 2 True False end All True True True False False False 0 None True True True False False False 1 gtk-ok True True True False True False False 2 gtk-cancel True True True False True False False 3 False True end 0 True False 7 2 True z -> zh True True False False True True c -> ch True True False False True True 1 2 s -> sh True True False False True True 2 3 an -> ang True True False False True True 3 4 on -> ong True True False False True True 4 5 en -> eng True True False False True True 5 6 in -> ing True True False False True True 6 7 eng -> ong True True False False True 1 2 ian -> iang True True False False True True 1 2 1 2 uan -> uang True True False False True 1 2 2 3 l -> n True True False False True True 1 2 3 4 f -> h True True False False True True 1 2 4 5 r -> l True True False False True True 1 2 5 6 k -> g True True False False True 1 2 6 7 False True 1 fuzzy_select_all fuzzy_unselect_all fuzzy_ok fuzzy_cancel False 5 Punct Mapping False True center normal True False vertical 2 True False end All True True True False False False 0 None True True True False False False 1 gtk-ok True True True False True False False 2 gtk-cancel True True True False True False False 3 False True end 0 True False True False ~ ` True True True False True True 0 ! 1 1 True True True False True True 1 @ 2 True True True False True True 2 # 3 True True True False True True 3 $ 4 True True True False True True 4 % 5 True True True False True True 5 ^ 6 True True True False True True 6 & 7 True True True False True True 7 * 8 True True True False True True 8 ( 9 True True True False True True 9 ) 0 True True True False True True 10 _ - True True True False True True 11 + = True True True False True True 12 | \ True True True False True True 13 <- True False True True False True True 14 True True 0 True False tab 27 True False True True False True True 0 Q True False True True False True True 1 W True False True True False True True 2 E True False True True False True True 3 R True False True True False True True 4 T True False True True False True True 5 Y True False True True False True True 6 U True False True True False True True 7 I True False True True False True True 8 O True False True True False True True 9 P True False True True False True True 10 { [ True True True False True True 11 } ] True True True False True True 12 True True 1 True False caps True False True True False True True 0 A True False True True False True True 1 S True False True True False True True 2 D True False True True False True True 3 F True False True True False True True 4 G True False True True False True True 5 H True False True True False True True 6 J True False True True False True True 7 K True False True True False True True 8 L True False True True False True True 9 : ; True True True False True True 10 " ' True True True False True True 11 Enter 42 True False True True False True True 12 True True 2 True False shift True False True True False True True 0 Z True False True True False True True 1 X True False True True False True True 2 C True False True True False True True 3 V True False True True False True True 4 B True False True True False True True 5 N True False True True False True True 6 M True False True True False True True 7 < , True True True False True True 8 > . True True True False True True 9 ? / True True True False True True 10 shift True False True True False True True 11 True True 3 True False Ctrl True False True True False True True 0 Win True False True True False True True 1 Alt True False True True False True True 2 True False True True False True True 3 Alt True False True True False True True 4 Win True False True True False True True 5 []] True False True True False True True 6 Ctrl True False True True False True True 7 True True 4 False True 1 punctmapping_select_all punctmapping_unselect_all punctmapping_ok punctmapping_cancel True False SunPinyin Setup False center True False True True 5 True False True False 5 0 none True False 12 True False 10 2 2 True Quan Pin True True False False 0 True True GTK_EXPAND Shuang Pin True True False False none 0 0.47999998927116394 True Pinyin/Scheme/QuanPin 1 2 GTK_EXPAND True False pymodel 0 on 0 1 2 1 2 GTK_EXPAND True False <b>Pinyin Mode</b> True False True 0 True False False True 5 1 True False 5 0 none True False 12 True False 10 3 2 True Chinese True True False False 0 True True GTK_EXPAND English True True False False half 0 0.47999998927116394 True General/InitialStatus/Mode/Chinese 1 2 GTK_EXPAND Chinese punctuation True True False False 0 True True 1 2 GTK_EXPAND English punctuation True True False False 0 True General/InitialStatus/Punct/Full 1 2 1 2 GTK_EXPAND Full-width Letter True True False False 0 True True 2 3 GTK_EXPAND Half-width Letter True True False False 0 True General/InitialStatus/Letter/Full 1 2 2 3 GTK_EXPAND True False <b>Initial Status</b> True False True 2 True False False True 5 3 True False 5 0 none True False 12 True False 10 4 2 Fuzzy Pinyin True True False False 0 True True GTK_EXPAND Auto Correct True True False False 0 True 1 2 GTK_EXPAND Fuzzy Pinyin Setup True True True False 0.51999998092651367 1 2 GTK_EXPAND Auto Correct Setup True True True False 1 2 1 2 GTK_EXPAND Smart Segmentation True True False False 0 True True 2 3 GTK_EXPAND Inner Fuzzy True True False False 0 True True 3 4 GTK_FILL GTK_EXPAND 23 True False <b>QuanPin Setup</b> True False True 4 True False Pinyin Mode False True False True False 5 0 none True False 12 True False 10 2 True Shift True True False False 0 True True GTK_EXPAND Control True True False False 0 True True Keyboard/ModeSwitch/Shift 1 2 GTK_EXPAND True False <b>Ch/En Switch key</b> True False True 0 True False False True 1 True False 5 0 none True False 12 True False 10 3 True Ctrl + , True True False False 0 True True GTK_EXPAND Ctrl + . True True False False 0 True True Keyboard/PunctSwitch/ControlComma 1 2 GTK_EXPAND None True True False False 0 True True Keyboard/PunctSwitch/ControlComma 2 3 GTK_EXPAND True False <b>Full/Half-width Punct Switch</b> True False True 2 True False False True 3 True False 9 0 none True False 12 True False 10 3 True - / = True True False False 0 True True GTK_EXPAND [ / ] True True False False 0 True 1 2 GTK_EXPAND , / . True True False False 0 True 2 3 True False <b>Page Flip</b> True False True 4 True False False True 5 True False 9 0 none True False 12 True False Cancel with Backspace True True False False 0 True True False True 0 Smart Punctuation True True False False 0 True False True 1 True False <b>Miscellaneous</b> True False True 6 1 True False Keyboard 1 False True False True False 5 0 none True False 12 True False 10 3 True GB2312 True True False False 0 True True GBK True True False False 0 True General/Charset/GB2312 1 2 GB18030 True True False False 0 True General/Charset/GB2312 2 3 True False <b>Character Set</b> True False True 0 True False False True 1 True False 5 0 none True False 12 True False 10 4 2 True True False 0 Candidate Num end True False 0 Memory Strength end 1 2 True True candidate_adjustment 0 right 1 2 True True memory_adjustment 0 right 1 2 1 2 True False 0 Number of Best Sentence 2 3 True False 0 Number of Best Tail Candidate 3 4 True True max_best_adjustment 0 0 right 1 2 2 3 True True max_tail_candidate_adjustment 0 0 right 1 2 3 4 False True 2 True False False True 3 True False 5 0 none True False 12 True False 10 2 True Punct mapping True True False False 0 True Mapping Setup True True True False 1 2 True False <b>Symbol Mapping</b> True False True 4 2 True False General 2 False True True 0 True False 10 10 True end gtk-ok True True True False True False False 0 gtk-cancel True True True False True False False 1 gtk-apply True True True False True False False 2 False False 1 10 1 1 10 10 1 10 11 3 1 1 1 MS2003 ZiRanMa ZiGuang ABC PinYinJiaJia XiaoHe ibus-sunpinyin-2.0.3+git20181120/src/000077500000000000000000000000001337507011600167005ustar00rootroot00000000000000ibus-sunpinyin-2.0.3+git20181120/src/CMakeLists.txt000066400000000000000000000017311337507011600214420ustar00rootroot00000000000000# CMakeLists.txt: cmake config file for ibus-sunpinyin find_package(GTK2 REQUIRED gtk) find_package(iBus 1.2 REQUIRED) find_package(SunPinyin 2.0 REQUIRED) include_directories(${GTK2_INCLUDE_DIRS} ${iBus_INCLUDE_DIRS} ${SunPinyin_INCLUDE_DIRS}) set(LIBS ${LIBS} ${GTK2_LIBRARIES} ${iBus_LIBRARIES} ${SunPinyin_LIBRARIES}) set(ENGINE_SRCS main.cpp engine.cpp pointer.h ibus_common.h imi_ibus_win.cpp imi_ibus_win.h sunpinyin_config_keys.h sunpinyin_config.cpp sunpinyin_config.h sunpinyin_engine.cpp sunpinyin_engine.h sunpinyin_engine_proxy.cpp sunpinyin_engine_proxy.h sunpinyin_lookup_table.cpp sunpinyin_lookup_table.h sunpinyin_property.cpp sunpinyin_property.h) set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) add_executable(ibus-engine-sunpinyin ${ENGINE_SRCS}) target_link_libraries(ibus-engine-sunpinyin ${LIBS}) install(TARGETS ibus-engine-sunpinyin RUNTIME DESTINATION ${LIBEXEC_DIR}) # -*- indent-tabs-mode: nil -*- vim:et:ts=4 ibus-sunpinyin-2.0.3+git20181120/src/debug.cpp000066400000000000000000000003611337507011600204720ustar00rootroot00000000000000#include "debug.h" #include #include #include namespace ibus { using namespace std; std::fstream log("/tmp/ibus.log", fstream::app|fstream::out); } // -*- indent-tabs-mode: nil -*- vim:et:ts=4 ibus-sunpinyin-2.0.3+git20181120/src/debug.h000066400000000000000000000007471337507011600201470ustar00rootroot00000000000000#ifndef IBUS_SUNPINYIN_DEBUG_H #define IBUS_SUNPINYIN_DEBUG_H #include #include #include #include namespace ibus { extern std::fstream log; } using std::cout; using std::hex; using std::endl; #define PRINT_VAL(val) \ do { \ cout << " "#val" = " << val << endl; \ } while (0) #endif // IBUS_SUNPINYIN_DEBUG_H // -*- indent-tabs-mode: nil -*- vim:et:ts=4 ibus-sunpinyin-2.0.3+git20181120/src/engine.cpp000066400000000000000000000112051337507011600206500ustar00rootroot00000000000000/* * Copyright (c) 2009 Kov Chai * * The contents of this file are subject to the terms of either the GNU Lesser * General Public License Version 2.1 only ("LGPL") or the Common Development and * Distribution License ("CDDL")(collectively, the "License"). You may not use this * file except in compliance with the License. You can obtain a copy of the CDDL at * http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at * http://www.opensource.org/licenses/lgpl-license.php. See the License for the * specific language governing permissions and limitations under the License. When * distributing the software, include this License Header Notice in each file and * include the full text of the License in the License file as well as the * following notice: * * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE * (CDDL) * For Covered Software in this distribution, this License shall be governed by the * laws of the State of California (excluding conflict-of-law provisions). * Any litigation relating to this License shall be subject to the jurisdiction of * the Federal Courts of the Northern District of California and the state courts * of the State of California, with venue lying in Santa Clara County, California. * * Contributor(s): * * If you wish your version of this file to be governed by only the CDDL or only * the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to * include this software in this distribution under the [CDDL or LGPL Version 2.1] * license." If you don't indicate a single choice of license, a recipient has the * option to distribute your version of this file under either the CDDL or the LGPL * Version 2.1, or to extend the choice of license to its licensees as provided * above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL * Version 2 license, then the option applies only if the new code is made subject * to such option by the copyright holder. */ #include "sunpinyin_engine_proxy.h" #include "sunpinyin_engine.h" #include "sunpinyin_config.h" #include "engine.h" #define IBUS_SUNPINYIN_ENGINE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_SUNPINYIN_ENGINE, IBusSunPinyinEngineClass)) #define IBUS_SUNPINYIN_ENGINE_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_SUNPINYIN_ENGINE, IBusSunPinyinEngineClass)) struct IBusSunPinyinEngineClass { IBusEngineClass parent; }; typedef SunPinyinEngine IBusSunPinyinEngine; /* functions prototype */ static void ibus_sunpinyin_engine_class_init (IBusSunPinyinEngineClass *); IBusEngineClass *parent_class = NULL; GType ibus_sunpinyin_engine_get_type (void) { static GType type = 0; static const GTypeInfo type_info = { sizeof (IBusSunPinyinEngineClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) ibus_sunpinyin_engine_class_init, NULL, NULL, sizeof (IBusSunPinyinEngine), 0, (GInstanceInitFunc) ibus_sunpinyin_engine_init, }; if (type == 0) { type = g_type_register_static (IBUS_TYPE_ENGINE, "IBusSunPinyinEngine", &type_info, (GTypeFlags) 0); } return type; } // initialize the meta class object void ibus_sunpinyin_engine_class_init (IBusSunPinyinEngineClass *klass) { IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass); IBusEngineClass *engine_class = IBUS_ENGINE_CLASS (klass); parent_class = (IBusEngineClass *) g_type_class_peek_parent (klass); ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_sunpinyin_engine_destroy; engine_class->process_key_event = ibus_sunpinyin_engine_process_key_event; engine_class->focus_in = ibus_sunpinyin_engine_focus_in; engine_class->focus_out = ibus_sunpinyin_engine_focus_out; engine_class->reset = ibus_sunpinyin_engine_reset; engine_class->enable = ibus_sunpinyin_engine_enable; engine_class->disable = ibus_sunpinyin_engine_disable; engine_class->page_up = ibus_sunpinyin_engine_page_up; engine_class->page_down = ibus_sunpinyin_engine_page_down; engine_class->cursor_up = ibus_sunpinyin_engine_cursor_up; engine_class->cursor_down = ibus_sunpinyin_engine_cursor_down; engine_class->property_activate = ibus_sunpinyin_engine_property_activate; engine_class->candidate_clicked = ibus_sunpinyin_engine_candidate_clicked; } // -*- indent-tabs-mode: nil -*- vim:et:ts=4 ibus-sunpinyin-2.0.3+git20181120/src/engine.h000066400000000000000000000045161337507011600203240ustar00rootroot00000000000000/* * Copyright (c) 2009 Kov Chai * * The contents of this file are subject to the terms of either the GNU Lesser * General Public License Version 2.1 only ("LGPL") or the Common Development and * Distribution License ("CDDL")(collectively, the "License"). You may not use this * file except in compliance with the License. You can obtain a copy of the CDDL at * http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at * http://www.opensource.org/licenses/lgpl-license.php. See the License for the * specific language governing permissions and limitations under the License. When * distributing the software, include this License Header Notice in each file and * include the full text of the License in the License file as well as the * following notice: * * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE * (CDDL) * For Covered Software in this distribution, this License shall be governed by the * laws of the State of California (excluding conflict-of-law provisions). * Any litigation relating to this License shall be subject to the jurisdiction of * the Federal Courts of the Northern District of California and the state courts * of the State of California, with venue lying in Santa Clara County, California. * * Contributor(s): * * If you wish your version of this file to be governed by only the CDDL or only * the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to * include this software in this distribution under the [CDDL or LGPL Version 2.1] * license." If you don't indicate a single choice of license, a recipient has the * option to distribute your version of this file under either the CDDL or the LGPL * Version 2.1, or to extend the choice of license to its licensees as provided * above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL * Version 2 license, then the option applies only if the new code is made subject * to such option by the copyright holder. */ #ifndef __ENGINE_H__ #define __ENGINE_H__ #include #define IBUS_TYPE_SUNPINYIN_ENGINE \ (ibus_sunpinyin_engine_get_type ()) GType ibus_sunpinyin_engine_get_type (void); void ibus_sunpinyin_init(IBusBus *bus); void ibus_sunpinyin_exit(); #endif /* __ENGINE_H__ */ // -*- indent-tabs-mode: nil -*- vim:et:ts=4 ibus-sunpinyin-2.0.3+git20181120/src/ibus_common.h000066400000000000000000000047431337507011600213730ustar00rootroot00000000000000/* * Copyright (c) 2010 Kov Chai * * The contents of this file are subject to the terms of either the GNU Lesser * General Public License Version 2.1 only ("LGPL") or the Common Development and * Distribution License ("CDDL")(collectively, the "License"). You may not use this * file except in compliance with the License. You can obtain a copy of the CDDL at * http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at * http://www.opensource.org/licenses/lgpl-license.php. See the License for the * specific language governing permissions and limitations under the License. When * distributing the software, include this License Header Notice in each file and * include the full text of the License in the License file as well as the * following notice: * * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE * (CDDL) * For Covered Software in this distribution, this License shall be governed by the * laws of the State of California (excluding conflict-of-law provisions). * Any litigation relating to this License shall be subject to the jurisdiction of * the Federal Courts of the Northern District of California and the state courts * of the State of California, with venue lying in Santa Clara County, California. * * Contributor(s): * * If you wish your version of this file to be governed by only the CDDL or only * the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to * include this software in this distribution under the [CDDL or LGPL Version 2.1] * license." If you don't indicate a single choice of license, a recipient has the * option to distribute your version of this file under either the CDDL or the LGPL * Version 2.1, or to extend the choice of license to its licensees as provided * above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL * Version 2 license, then the option applies only if the new code is made subject * to such option by the copyright holder. */ #include #include "pointer.h" namespace ibus { typedef Pointer Text; typedef Pointer Property; typedef Pointer PropList; typedef Pointer Engine; typedef Pointer LookupTable; typedef Pointer Bus; typedef Pointer Config; typedef Pointer Component; typedef Pointer Factory; } // -*- indent-tabs-mode: nil -*- vim:et:ts=4 ibus-sunpinyin-2.0.3+git20181120/src/ibus_portable.cpp000066400000000000000000000061411337507011600222400ustar00rootroot00000000000000/* * Copyright (c) 2009 Kov Chai * * The contents of this file are subject to the terms of either the GNU Lesser * General Public License Version 2.1 only ("LGPL") or the Common Development and * Distribution License ("CDDL")(collectively, the "License"). You may not use this * file except in compliance with the License. You can obtain a copy of the CDDL at * http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at * http://www.opensource.org/licenses/lgpl-license.php. See the License for the * specific language governing permissions and limitations under the License. When * distributing the software, include this License Header Notice in each file and * include the full text of the License in the License file as well as the * following notice: * * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE * (CDDL) * For Covered Software in this distribution, this License shall be governed by the * laws of the State of California (excluding conflict-of-law provisions). * Any litigation relating to this License shall be subject to the jurisdiction of * the Federal Courts of the Northern District of California and the state courts * of the State of California, with venue lying in Santa Clara County, California. * * Contributor(s): * * If you wish your version of this file to be governed by only the CDDL or only * the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to * include this software in this distribution under the [CDDL or LGPL Version 2.1] * license." If you don't indicate a single choice of license, a recipient has the * option to distribute your version of this file under either the CDDL or the LGPL * Version 2.1, or to extend the choice of license to its licensees as provided * above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL * Version 2 license, then the option applies only if the new code is made subject * to such option by the copyright holder. */ #include "ibus_portable.h" #if defined(WITH_IBUS_1_1_0) void ibus_property_set_icon (IBusProperty *prop, const gchar *icon) { g_assert (IBUS_IS_PROPERTY (prop)); g_free (prop->icon); prop->icon = NULL; prop->icon = g_strdup (icon != NULL ? icon : ""); } void ibus_property_set_state (IBusProperty *prop, IBusPropState state) { g_assert (IBUS_IS_PROPERTY (prop)); g_return_if_fail (state == PROP_STATE_UNCHECKED || state == PROP_STATE_CHECKED || state == PROP_STATE_INCONSISTENT); prop->state = state; } void ibus_property_set_tooltip (IBusProperty *prop, IBusText *tooltip) { g_assert (IBUS_IS_PROPERTY (prop)); g_return_if_fail (tooltip == NULL || IBUS_IS_TEXT (tooltip)); UNREF (prop->tooltip); if (tooltip == NULL) { prop->tooltip = ibus_text_new_from_static_string (""); } else { prop->tooltip = (IBusText *)g_object_ref (tooltip); } } #endif // WITH_IBUS_1_1_0 // -*- indent-tabs-mode: nil -*- vim:et:ts=4 ibus-sunpinyin-2.0.3+git20181120/src/ibus_portable.h000066400000000000000000000050051337507011600217030ustar00rootroot00000000000000/* * Copyright (c) 2009 Kov Chai * * The contents of this file are subject to the terms of either the GNU Lesser * General Public License Version 2.1 only ("LGPL") or the Common Development and * Distribution License ("CDDL")(collectively, the "License"). You may not use this * file except in compliance with the License. You can obtain a copy of the CDDL at * http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at * http://www.opensource.org/licenses/lgpl-license.php. See the License for the * specific language governing permissions and limitations under the License. When * distributing the software, include this License Header Notice in each file and * include the full text of the License in the License file as well as the * following notice: * * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE * (CDDL) * For Covered Software in this distribution, this License shall be governed by the * laws of the State of California (excluding conflict-of-law provisions). * Any litigation relating to this License shall be subject to the jurisdiction of * the Federal Courts of the Northern District of California and the state courts * of the State of California, with venue lying in Santa Clara County, California. * * Contributor(s): * * If you wish your version of this file to be governed by only the CDDL or only * the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to * include this software in this distribution under the [CDDL or LGPL Version 2.1] * license." If you don't indicate a single choice of license, a recipient has the * option to distribute your version of this file under either the CDDL or the LGPL * Version 2.1, or to extend the choice of license to its licensees as provided * above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL * Version 2 license, then the option applies only if the new code is made subject * to such option by the copyright holder. */ #ifndef IBUS_COMPABILITY_H #define IBUS_COMPABILITY_H #if defined(WITH_IBUS_1_1_0) #include void ibus_property_set_icon (IBusProperty *prop, const gchar *icon); void ibus_property_set_state (IBusProperty *prop, IBusPropState state); void ibus_property_set_tooltip (IBusProperty *prop, IBusText *tooltip); #endif // WITH_IBUS_1_1_0 #endif // IBUS_COMPABILITY_H // -*- indent-tabs-mode: nil -*- vim:et:ts=4 ibus-sunpinyin-2.0.3+git20181120/src/imi_ibus_win.cpp000066400000000000000000000066421337507011600220710ustar00rootroot00000000000000/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 2007, 2009 Kov Chai * * The contents of this file are subject to the terms of either the GNU Lesser * General Public License Version 2.1 only ("LGPL") or the Common Development and * Distribution License ("CDDL")(collectively, the "License"). You may not use this * file except in compliance with the License. You can obtain a copy of the CDDL at * http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at * http://www.opensource.org/licenses/lgpl-license.php. See the License for the * specific language governing permissions and limitations under the License. When * distributing the software, include this License Header Notice in each file and * include the full text of the License in the License file as well as the * following notice: * * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE * (CDDL) * For Covered Software in this distribution, this License shall be governed by the * laws of the State of California (excluding conflict-of-law provisions). * Any litigation relating to this License shall be subject to the jurisdiction of * the Federal Courts of the Northern District of California and the state courts * of the State of California, with venue lying in Santa Clara County, California. * * Contributor(s): * * If you wish your version of this file to be governed by only the CDDL or only * the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to * include this software in this distribution under the [CDDL or LGPL Version 2.1] * license." If you don't indicate a single choice of license, a recipient has the * option to distribute your version of this file under either the CDDL or the LGPL * Version 2.1, or to extend the choice of license to its licensees as provided * above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL * Version 2 license, then the option applies only if the new code is made subject * to such option by the copyright holder. */ #include #include #include #include "sunpinyin_engine.h" #include "imi_ibus_win.h" CIBusWinHandler::CIBusWinHandler(SunPinyinEngine* engine) : m_engine(engine) { // } CIBusWinHandler::~CIBusWinHandler() { } void CIBusWinHandler::commit(const TWCHAR* wstr) { if (wstr) { std::wstring str; copy(wstr, wstr+WCSLEN(wstr)+1, back_inserter(str)); m_engine->commit_string(str); } } void CIBusWinHandler::updatePreedit(const IPreeditString* ppd) { if (ppd) m_engine->update_preedit_string(*ppd); } void CIBusWinHandler::updateCandidates(const ICandidateList* pcl) { if (pcl) m_engine->update_candidates(*pcl); } void CIBusWinHandler::throwBackKey(unsigned keycode, unsigned keyvalue, unsigned modifier) { if (keyvalue > 0x0 && keyvalue < 0x7f) { printf("%c", keyvalue); fflush(stdout); } } void CIBusWinHandler::updateStatus(int key, int value) { switch (key) { case STATUS_ID_CN: m_engine->update_status_property(value != 0); break; case STATUS_ID_FULLPUNC: m_engine->update_punct_property(value != 0); break; case STATUS_ID_FULLSYMBOL: m_engine->update_letter_property(value != 0); break; default: break; } } // -*- indent-tabs-mode: nil -*- vim:et:ts=4 ibus-sunpinyin-2.0.3+git20181120/src/imi_ibus_win.h000066400000000000000000000060031337507011600215250ustar00rootroot00000000000000/* * Copyright (c) 2007,2009 Kov Chai * * The contents of this file are subject to the terms of either the GNU Lesser * General Public License Version 2.1 only ("LGPL") or the Common Development and * Distribution License ("CDDL")(collectively, the "License"). You may not use this * file except in compliance with the License. You can obtain a copy of the CDDL at * http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at * http://www.opensource.org/licenses/lgpl-license.php. See the License for the * specific language governing permissions and limitations under the License. When * distributing the software, include this License Header Notice in each file and * include the full text of the License in the License file as well as the * following notice: * * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE * (CDDL) * For Covered Software in this distribution, this License shall be governed by the * laws of the State of California (excluding conflict-of-law provisions). * Any litigation relating to this License shall be subject to the jurisdiction of * the Federal Courts of the Northern District of California and the state courts * of the State of California, with venue lying in Santa Clara County, California. * * Contributor(s): * * If you wish your version of this file to be governed by only the CDDL or only * the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to * include this software in this distribution under the [CDDL or LGPL Version 2.1] * license." If you don't indicate a single choice of license, a recipient has the * option to distribute your version of this file under either the CDDL or the LGPL * Version 2.1, or to extend the choice of license to its licensees as provided * above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL * Version 2 license, then the option applies only if the new code is made subject * to such option by the copyright holder. */ #ifndef IMI_IBUS_WIN_H #define IMI_IBUS_WIN_H #include class SunPinyinEngine; class CIBusWinHandler : public CIMIGlibHandler { public: CIBusWinHandler(SunPinyinEngine *); /* inherited methods implementation */ /*@{*/ virtual ~CIBusWinHandler(); /** commit a string, normally the converted result */ virtual void commit(const TWCHAR* wstr); /** when a key is not processed */ virtual void throwBackKey(unsigned keycode, unsigned keyvalue, unsigned modifier); /** Update window's preedit area using a GTK widget. */ virtual void updatePreedit(const IPreeditString* ppd); /** Update window's candidates area using a GTK widget. */ virtual void updateCandidates(const ICandidateList* pcl); /** Update status of current session using a GTK buttons. */ virtual void updateStatus(int key, int value); /*@}*/ private: SunPinyinEngine *m_engine; }; #endif // IMI_IBUS_WIN_H // -*- indent-tabs-mode: nil -*- vim:et:ts=4 ibus-sunpinyin-2.0.3+git20181120/src/main.cpp000066400000000000000000000124541337507011600203360ustar00rootroot00000000000000/* * Copyright (c) 2009 Kov Chai * * The contents of this file are subject to the terms of either the GNU Lesser * General Public License Version 2.1 only ("LGPL") or the Common Development and * Distribution License ("CDDL")(collectively, the "License"). You may not use this * file except in compliance with the License. You can obtain a copy of the CDDL at * http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at * http://www.opensource.org/licenses/lgpl-license.php. See the License for the * specific language governing permissions and limitations under the License. When * distributing the software, include this License Header Notice in each file and * include the full text of the License in the License file as well as the * following notice: * * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE * (CDDL) * For Covered Software in this distribution, this License shall be governed by the * laws of the State of California (excluding conflict-of-law provisions). * Any litigation relating to this License shall be subject to the jurisdiction of * the Federal Courts of the Northern District of California and the state courts * of the State of California, with venue lying in Santa Clara County, California. * * Contributor(s): * * If you wish your version of this file to be governed by only the CDDL or only * the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to * include this software in this distribution under the [CDDL or LGPL Version 2.1] * license." If you don't indicate a single choice of license, a recipient has the * option to distribute your version of this file under either the CDDL or the LGPL * Version 2.1, or to extend the choice of license to its licensees as provided * above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL * Version 2 license, then the option applies only if the new code is made subject * to such option by the copyright holder. */ #include #include #include #include #include #include #include "engine.h" #include "ibus_common.h" #include "sunpinyin_config.h" #define N_(String) (String) #define _(String) gettext(String) static ibus::Factory factory; // options static gboolean by_ibus = FALSE; static gboolean verbose = FALSE; static const GOptionEntry entries[] = { { "ibus", 'i', 0, G_OPTION_ARG_NONE, &by_ibus, "component is executed by ibus", NULL }, { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "verbose", NULL }, { NULL }, }; static void ibus_disconnected_cb (IBusBus *bus, gpointer user_data) { ibus_quit (); } IBusBus *bus = NULL; ibus::Component component; static void init () { ibus_init (); bus = ibus_bus_new (); g_object_ref_sink(bus); if (!ibus_bus_is_connected (bus)) { g_warning("Can not connect to ibus"); exit (0); } g_signal_connect (bus, "disconnected", G_CALLBACK (ibus_disconnected_cb), NULL); IBusConfig* config = ibus_bus_get_config(bus); g_object_ref_sink(config); SunPinyinConfig::set_config(config); component = ibus_component_new ("org.freedesktop.IBus.SunPinyin", "SunPinyin2", "0.1.0", "LGPL/CDDL", "Kov Chai ", "http://code.google.com/p/sunpinyin/", "", "ibus-sunpinyin"); ibus_component_add_engine (component, ibus_engine_desc_new ("sunpinyin", "SunPinyin", _("Simplified Chinese Input Method developed by SUN"), "zh_CN", "LGPL/CDDL", "Kov Chai ", IBUS_SUNPINYIN_ICON_DIR"/sunpinyin-logo.png", "en")); factory = ibus_factory_new (ibus_bus_get_connection (bus)); ibus_factory_add_engine (factory, "sunpinyin", IBUS_TYPE_SUNPINYIN_ENGINE); if (by_ibus) { ibus_bus_request_name (bus, "org.freedesktop.IBus.SunPinyin", 0); } else { ibus_bus_register_component (bus, component); } ibus_main (); } int main(int argc, char *argv[]) { setlocale (LC_ALL, ""); bindtextdomain (GETTEXT_PACKAGE, IBUS_SUNPINYIN_LOCALEDIR); textdomain (GETTEXT_PACKAGE); GOptionContext* context; context = g_option_context_new ("- ibus sunpinyin engine component"); g_option_context_add_main_entries (context, entries, "ibus-sunpinyin"); GError *error = NULL; if (!g_option_context_parse (context, &argc, &argv, &error)) { g_print ("Option parsing failed: %s\n", error->message); return -1; } // mask SIGTERM so that the destroy() method has the chance to be called // in case user quits X session. sighold(SIGTERM); init (); } // -*- indent-tabs-mode: nil -*- vim:et:ts=4 ibus-sunpinyin-2.0.3+git20181120/src/pointer.h000066400000000000000000000057441337507011600205430ustar00rootroot00000000000000/* * Copyright (c) 2010 Kov Chai * * The contents of this file are subject to the terms of either the GNU Lesser * General Public License Version 2.1 only ("LGPL") or the Common Development and * Distribution License ("CDDL")(collectively, the "License"). You may not use this * file except in compliance with the License. You can obtain a copy of the CDDL at * http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at * http://www.opensource.org/licenses/lgpl-license.php. See the License for the * specific language governing permissions and limitations under the License. When * distributing the software, include this License Header Notice in each file and * include the full text of the License in the License file as well as the * following notice: * * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE * (CDDL) * For Covered Software in this distribution, this License shall be governed by the * laws of the State of California (excluding conflict-of-law provisions). * Any litigation relating to this License shall be subject to the jurisdiction of * the Federal Courts of the Northern District of California and the state courts * of the State of California, with venue lying in Santa Clara County, California. * * Contributor(s): * * If you wish your version of this file to be governed by only the CDDL or only * the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to * include this software in this distribution under the [CDDL or LGPL Version 2.1] * license." If you don't indicate a single choice of license, a recipient has the * option to distribute your version of this file under either the CDDL or the LGPL * Version 2.1, or to extend the choice of license to its licensees as provided * above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL * Version 2 license, then the option applies only if the new code is made subject * to such option by the copyright holder. */ #ifndef POINTER_H #define POINTER_H template class Pointer { public: Pointer(T *p = 0) : m_p(0) { set(p); } ~Pointer() { set(0); } Pointer(const Pointer& p) : m_p(0) { set(p.m_p); } Pointer& operator=(T *object) { set(object); return *this; } Pointer& operator=(const Pointer& src) { set(src.m_p); return *this; } const T* operator->() const { return m_p; } T* operator->() { return m_p; } operator T* () const { return m_p; } operator bool () const { return m_p != 0; } private: T *m_p; void set(T *p) { if (m_p) { g_object_unref(m_p); } m_p = p; if (p) { g_object_ref_sink(p); } } }; #endif// POINTER_H // -*- indent-tabs-mode: nil -*- vim:et:ts=4 ibus-sunpinyin-2.0.3+git20181120/src/sunpinyin_config.cpp000066400000000000000000000323531337507011600227730ustar00rootroot00000000000000/* * Copyright (c) 2009 Kov Chai * * The contents of this file are subject to the terms of either the GNU Lesser * General Public License Version 2.1 only ("LGPL") or the Common Development and * Distribution License ("CDDL")(collectively, the "License"). You may not use this * file except in compliance with the License. You can obtain a copy of the CDDL at * http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at * http://www.opensource.org/licenses/lgpl-license.php. See the License for the * specific language governing permissions and limitations under the License. When * distributing the software, include this License Header Notice in each file and * include the full text of the License in the License file as well as the * following notice: * * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE * (CDDL) * For Covered Software in this distribution, this License shall be governed by the * laws of the State of California (excluding conflict-of-law provisions). * Any litigation relating to this License shall be subject to the jurisdiction of * the Federal Courts of the Northern District of California and the state courts * of the State of California, with venue lying in Santa Clara County, California. * * Contributor(s): * * If you wish your version of this file to be governed by only the CDDL or only * the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to * include this software in this distribution under the [CDDL or LGPL Version 2.1] * license." If you don't indicate a single choice of license, a recipient has the * option to distribute your version of this file under either the CDDL or the LGPL * Version 2.1, or to extend the choice of license to its licensees as provided * above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL * Version 2 license, then the option applies only if the new code is made subject * to such option by the copyright holder. */ #include #include #include "sunpinyin_config_keys.h" #include "sunpinyin_config.h" using namespace std; struct ConfigItem { string section; string name; ConfigItem(const string& key) { section = "engine/SunPinyin/"; size_t pos = key.rfind('/'); if (pos != key.npos) { section += key.substr(0, pos); pos += 1; } else { pos = 0; } name = key.substr(pos); } }; IBusConfig* SunPinyinConfig::m_config; SunPinyinConfig::SunPinyinConfig() { m_scheme_names["QuanPin"] = CSunpinyinSessionFactory::QUANPIN; m_scheme_names["ShuangPin"] = CSunpinyinSessionFactory::SHUANGPIN; } SunPinyinConfig::~SunPinyinConfig() {} void SunPinyinConfig::set_config(IBusConfig* config) { assert(config); m_config = config; listen_on_changed(); } CSunpinyinSessionFactory::EPyScheme SunPinyinConfig::get_py_scheme(CSunpinyinSessionFactory::EPyScheme scheme) { string default_name = get_scheme_name(scheme); string name = get(PINYIN_SCHEME, default_name); return get_scheme(name); } bool SunPinyinConfig::is_initial_mode_cn() { string init_mode("Chinese"); init_mode = get(CONFIG_GENERAL_INITIAL_MODE, init_mode); return (init_mode == "Chinese"); } bool SunPinyinConfig::is_initial_punct_full() { string init_punct("Full"); init_punct = get(CONFIG_GENERAL_INITIAL_PUNCT, init_punct); return (init_punct == "Full"); } bool SunPinyinConfig::is_initial_letter_full() { string init_letter("Half"); init_letter = get(CONFIG_GENERAL_INITIAL_LETTER, init_letter); return (init_letter == "Full"); } void SunPinyinConfig::listen_on_changed() { assert(m_config != NULL); g_signal_connect(m_config, "value-changed", G_CALLBACK(on_config_value_changed), 0); } std::string SunPinyinConfig::get_scheme_name(CSunpinyinSessionFactory::EPyScheme scheme) { string val = "ShuangPin"; for (SchemeNames::iterator it = m_scheme_names.begin(); it != m_scheme_names.end(); ++it) { if (it->second == scheme) val = it->first; } return val; } CSunpinyinSessionFactory::EPyScheme SunPinyinConfig::get_scheme(const std::string& name) { CSunpinyinSessionFactory::EPyScheme val = CSunpinyinSessionFactory::SHUANGPIN; SchemeNames::iterator it = m_scheme_names.find(name); if (it != m_scheme_names.end()) { val = it->second; } return val; } #if IBUS_CHECK_VERSION (1, 3, 99) static vector get_strings_from_gvariant(GVariant *value); bool SunPinyinConfig::get(const char* key, bool val) { assert(m_config != NULL); ConfigItem item(key); GVariant* value = ibus_config_get_value(m_config, item.section.c_str(), item.name.c_str()); bool result = val; if (g_variant_classify(value) == G_VARIANT_CLASS_BOOLEAN) { result = (g_variant_get_boolean(value) == TRUE); } return result; } void SunPinyinConfig::set(const char* key, bool val) { assert(m_config != NULL); GVariant * value = g_variant_new_boolean(val); ConfigItem item(key); ibus_config_set_value(m_config, item.section.c_str(), item.name.c_str(), value); } std::string SunPinyinConfig::get(const char* key, const std::string& val) { assert(m_config != NULL); ConfigItem item(key); GVariant* value = ibus_config_get_value(m_config, item.section.c_str(), item.name.c_str()); string result = val; if (g_variant_classify(value) == G_VARIANT_CLASS_STRING) { result = string(g_variant_get_string(value, NULL)); } return result; } void SunPinyinConfig::set(const char* key, const std::string& val) { assert(m_config != NULL); GVariant* value = g_variant_new_string(val.c_str()); ConfigItem item(key); ibus_config_set_value(m_config, item.section.c_str(), item.name.c_str(), value); } int SunPinyinConfig::get(const char* key, int val) { assert(m_config != NULL); ConfigItem item(key); GVariant* value = ibus_config_get_value(m_config, item.section.c_str(), item.name.c_str()); int result = val; if (g_variant_classify(value) == G_VARIANT_CLASS_INT32) { result = g_variant_get_int32(value); } return result; } void SunPinyinConfig::set(const char* key, int val) { assert(m_config != NULL); GVariant* value = g_variant_new_int32(val); ConfigItem item(key); ibus_config_set_value(m_config, item.section.c_str(), item.name.c_str(), value); } std::vector SunPinyinConfig::get(const char* key, const std::vector& val) { assert(m_config != NULL); ConfigItem item(key); GVariant* value = ibus_config_get_value(m_config, item.section.c_str(), item.name.c_str()); vector result(val); if (g_variant_classify(value) == G_VARIANT_CLASS_ARRAY) { result = get_strings_from_gvariant(value); } return result; } vector get_strings_from_gvariant(GVariant *value) { const gchar **array = g_variant_get_strv(value, NULL); assert(array != NULL); vector strings; for (unsigned i = 0; array[i]; ++i) { strings.push_back(array[i]); } return strings; } static COptionEvent g_value_to_event(const gchar *section, const gchar *name, GVariant *value) { string event_name; if (strlen(section) == 0) { event_name = name; } else { event_name = string(section) + "/" + string(name); } switch (g_variant_classify(value)) { case G_VARIANT_CLASS_INT32: return COptionEvent(event_name, g_variant_get_int32(value)); case G_VARIANT_CLASS_STRING: return COptionEvent(event_name, g_variant_get_string(value, NULL)); case G_VARIANT_CLASS_BOOLEAN: return COptionEvent(event_name, g_variant_get_boolean(value)?true:false); default: // G_TYPE_VALUE_ARRAY() not a constant if (G_VARIANT_CLASS_ARRAY == g_variant_classify(value)) return COptionEvent(event_name, get_strings_from_gvariant(value)); assert(false && "unknown gvalue"); return COptionEvent(event_name, 0); } } void SunPinyinConfig::on_config_value_changed(IBusConfig *config, const gchar *section, const gchar *name, GVariant *value, SunPinyinConfig* thiz) { static const char* prefix = "engine/SunPinyin/"; if (!strstr(section, prefix)) return; const char *sub_section = section + strlen(prefix); COptionEvent event = g_value_to_event(sub_section, name, value); AOptionEventBus::instance().publishEvent(event); } #else /* for versions lower than 1.3.99 (or 1.4) */ static vector get_strings_from_gvalue(GValue* value); bool SunPinyinConfig::get(const char* key, bool val) { assert(m_config != NULL); GValue v = {0}; gboolean got; ConfigItem item(key); got = ibus_config_get_value(m_config, item.section.c_str(), item.name.c_str(), &v); bool result = val; if (got && G_VALUE_TYPE(&v) == G_TYPE_BOOLEAN) { result = (g_value_get_boolean(&v) == TRUE); } return result; } void SunPinyinConfig::set(const char* key, bool value) { assert(m_config != NULL); GValue v = {0}; g_value_init(&v, G_TYPE_BOOLEAN); g_value_set_boolean(&v, value?TRUE:FALSE); ConfigItem item(key); ibus_config_set_value(m_config, item.section.c_str(), item.name.c_str(), &v); } std::string SunPinyinConfig::get(const char* key, const std::string& val) { assert(m_config != NULL); GValue v = {0}; gboolean got; ConfigItem item(key); got = ibus_config_get_value(m_config, item.section.c_str(), item.name.c_str(), &v); string result = val; if (got && G_VALUE_TYPE(&v) == G_TYPE_STRING) { result = string(g_value_get_string(&v)); } return result; } void SunPinyinConfig::set(const char* key, const std::string& val) { assert(m_config != NULL); GValue v = {0}; g_value_init(&v, G_TYPE_STRING); g_value_set_string(&v, val.c_str()); ConfigItem item(key); ibus_config_set_value(m_config, item.section.c_str(), item.name.c_str(), &v); } int SunPinyinConfig::get(const char* key, int val) { assert(m_config != NULL); GValue v = {0}; gboolean got; ConfigItem item(key); got = ibus_config_get_value(m_config, item.section.c_str(), item.name.c_str(), &v); int result = val; if (got && G_VALUE_TYPE(&v) == G_TYPE_INT) { result = g_value_get_int(&v); } return result; } void SunPinyinConfig::set(const char* key, int value) { assert(m_config != NULL); GValue v = {0}; g_value_init(&v, G_TYPE_INT); g_value_set_int(&v, value); ConfigItem item(key); ibus_config_set_value(m_config, item.section.c_str(), item.name.c_str(), &v); } std::vector SunPinyinConfig::get(const char *key, const std::vector& val) { assert(m_config != NULL); GValue v = {0}; gboolean got; ConfigItem item(key); got = ibus_config_get_value(m_config, item.section.c_str(), item.name.c_str(), &v); vector result(val); if (got && G_VALUE_TYPE(&v) == G_TYPE_VALUE_ARRAY) { result = get_strings_from_gvalue(&v); } return result; } vector get_strings_from_gvalue(GValue *value) { GValueArray *array = (GValueArray *)g_value_get_boxed(value); assert(array != NULL); vector strings; for (unsigned i = 0; i < array->n_values; ++i) { GValue *element = &(array->values[i]); assert (G_VALUE_TYPE(element) == G_TYPE_STRING && "only array of string is supported"); strings.push_back(g_value_get_string(element)); } return strings; } static COptionEvent g_value_to_event(const gchar *section, const gchar *name, GValue *value) { string event_name; if (strlen(section) == 0) { event_name = name; } else { event_name = string(section) + "/" + string(name); } switch (G_VALUE_TYPE(value)) { case G_TYPE_INT: return COptionEvent(event_name, g_value_get_int(value)); case G_TYPE_STRING: return COptionEvent(event_name, g_value_get_string(value)); case G_TYPE_BOOLEAN: return COptionEvent(event_name, g_value_get_boolean(value)?true:false); default: // G_TYPE_VALUE_ARRAY() not a constant if (G_TYPE_VALUE_ARRAY == G_VALUE_TYPE(value)) return COptionEvent(event_name, get_strings_from_gvalue(value)); assert(false && "unknown gvalue"); return COptionEvent(event_name, 0); } } void SunPinyinConfig::on_config_value_changed(IBusConfig *config, const gchar *section, const gchar *name, GValue *value, SunPinyinConfig* thiz) { static const char* prefix = "engine/SunPinyin/"; if (!strstr(section, prefix)) return; const char *sub_section = section + strlen(prefix); COptionEvent event = g_value_to_event(sub_section, name, value); AOptionEventBus::instance().publishEvent(event); } #endif // -*- indent-tabs-mode: nil -*- vim:et:ts=4 ibus-sunpinyin-2.0.3+git20181120/src/sunpinyin_config.h000066400000000000000000000105041337507011600224320ustar00rootroot00000000000000/* * Copyright (c) 2009 Kov Chai * * The contents of this file are subject to the terms of either the GNU Lesser * General Public License Version 2.1 only ("LGPL") or the Common Development and * Distribution License ("CDDL")(collectively, the "License"). You may not use this * file except in compliance with the License. You can obtain a copy of the CDDL at * http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at * http://www.opensource.org/licenses/lgpl-license.php. See the License for the * specific language governing permissions and limitations under the License. When * distributing the software, include this License Header Notice in each file and * include the full text of the License in the License file as well as the * following notice: * * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE * (CDDL) * For Covered Software in this distribution, this License shall be governed by the * laws of the State of California (excluding conflict-of-law provisions). * Any litigation relating to this License shall be subject to the jurisdiction of * the Federal Courts of the Northern District of California and the state courts * of the State of California, with venue lying in Santa Clara County, California. * * Contributor(s): * * If you wish your version of this file to be governed by only the CDDL or only * the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to * include this software in this distribution under the [CDDL or LGPL Version 2.1] * license." If you don't indicate a single choice of license, a recipient has the * option to distribute your version of this file under either the CDDL or the LGPL * Version 2.1, or to extend the choice of license to its licensees as provided * above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL * Version 2 license, then the option applies only if the new code is made subject * to such option by the copyright holder. */ #ifndef SUNPINYIN_CONFIG_H #define SUNPINYIN_CONFIG_H #include #include #include #include #include class EngineImpl; enum CharsetLevel { GB2312, GBK, GB18030 }; class SunPinyinConfig { typedef std::map SchemeNames; typedef std::map TypeNames; SchemeNames m_scheme_names; TypeNames m_type_names; static IBusConfig* m_config; public: SunPinyinConfig(); virtual ~SunPinyinConfig(); static void set_config(IBusConfig *config); bool get(const char* key, bool val); void set(const char* key, bool val); int get(const char* key, int val); void set(const char* key, int val); std::string get(const char *key, const std::string& default_val); void set(const char* key, const std::string& val); std::vector get(const char *key, const std::vector& val); CSunpinyinSessionFactory::EPyScheme get_py_scheme(CSunpinyinSessionFactory::EPyScheme); void set_py_scheme(CSunpinyinSessionFactory::EPyScheme); bool is_initial_mode_cn(); bool is_initial_punct_full(); bool is_initial_letter_full(); /** * register on_config_value_changed() as the signal handler of value-changed, */ static void listen_on_changed(); private: /** * called by ibus when a value changed in config */ #if IBUS_CHECK_VERSION(1, 3, 99) static void on_config_value_changed(IBusConfig *config, const gchar *section, const gchar *name, GVariant *value, SunPinyinConfig *user_data); #else static void on_config_value_changed(IBusConfig *config, const gchar *section, const gchar *name, GValue *value, SunPinyinConfig *user_data); #endif std::string get_scheme_name(CSunpinyinSessionFactory::EPyScheme scheme); CSunpinyinSessionFactory::EPyScheme get_scheme(const std::string& name); }; #endif // SUNPINYIN_CONFIG_H // -*- indent-tabs-mode: nil -*- vim:et:ts=4 ibus-sunpinyin-2.0.3+git20181120/src/sunpinyin_config_keys.h000066400000000000000000000111621337507011600234660ustar00rootroot00000000000000/* * Copyright (c) 2009 Kov Chai * * The contents of this file are subject to the terms of either the GNU Lesser * General Public License Version 2.1 only ("LGPL") or the Common Development and * Distribution License ("CDDL")(collectively, the "License"). You may not use this * file except in compliance with the License. You can obtain a copy of the CDDL at * http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at * http://www.opensource.org/licenses/lgpl-license.php. See the License for the * specific language governing permissions and limitations under the License. When * distributing the software, include this License Header Notice in each file and * include the full text of the License in the License file as well as the * following notice: * * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE * (CDDL) * For Covered Software in this distribution, this License shall be governed by the * laws of the State of California (excluding conflict-of-law provisions). * Any litigation relating to this License shall be subject to the jurisdiction of * the Federal Courts of the Northern District of California and the state courts * of the State of California, with venue lying in Santa Clara County, California. * * Contributor(s): * * If you wish your version of this file to be governed by only the CDDL or only * the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to * include this software in this distribution under the [CDDL or LGPL Version 2.1] * license." If you don't indicate a single choice of license, a recipient has the * option to distribute your version of this file under either the CDDL or the LGPL * Version 2.1, or to extend the choice of license to its licensees as provided * above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL * Version 2 license, then the option applies only if the new code is made subject * to such option by the copyright holder. */ #ifndef SUNPINYIN_CONFIG_KEYS_H #define SUNPINYIN_CONFIG_KEYS_H #define CONFIG_GENERAL_PAGE_SIZE "General/PageSize" #define CONFIG_GENERAL_MEMORY_POWER "General/MemoryPower" #define CONFIG_GENERAL_CHARSET_LEVEL "General/Charset" #define CONFIG_GENERAL_MAX_BEST "General/MaxBest" #define CONFIG_GENERAL_MAX_TAIL_CANDIDATE "General/MaxTailCandidate" #define CONFIG_GENERAL_INITIAL_MODE "General/InitialStatus/Mode" #define CONFIG_GENERAL_INITIAL_PUNCT "General/InitialStatus/Punct" #define CONFIG_GENERAL_INITIAL_LETTER "General/InitialStatus/Letter" #define CONFIG_QUANPIN_FUZZY_ANY "QuanPin/Fuzzy/Any" #define CONFIG_QUANPIN_FUZZY_ZhiZi "QuanPin/Fuzzy/ZhiZi" #define CONFIG_QUANPIN_FUZZY_ChiCi "QuanPin/Fuzzy/ChiCi" #define CONFIG_QUANPIN_FUZZY_ShiSi "QuanPin/Fuzzy/ShiSi" #define CONFIG_QUANPIN_FUZZY_AnAng "QuanPin/Fuzzy/AnAng" #define CONFIG_QUANPIN_FUZZY_OnOng "QuanPin/Fuzzy/OnOng" #define CONFIG_QUANPIN_FUZZY_EnEng "QuanPin/Fuzzy/EnEng" #define CONFIG_QUANPIN_FUZZY_InIng "QuanPin/Fuzzy/InIng" #define CONFIG_QUANPIN_FUZZY_EngOng "QuanPin/Fuzzy/EngOng" #define CONFIG_QUANPIN_FUZZY_IanIang "QuanPin/Fuzzy/IanIang" #define CONFIG_QUANPIN_FUZZY_UanUang "QuanPin/Fuzzy/UanUang" #define CONFIG_QUANPIN_FUZZY_NeLe "QuanPin/Fuzzy/NeLe" #define CONFIG_QUANPIN_FUZZY_FoHe "QuanPin/Fuzzy/FoHe" #define CONFIG_QUANPIN_FUZZY_LeRi "QuanPin/Fuzzy/LeRi" #define CONFIG_QUANPIN_FUZZY_KeGe "QuanPin/Fuzzy/KeGe" #define CONFIG_QUANPIN_FUZZYSEGS_ENABLED "QuanPin/FuzzySegs/Enabled" #define CONFIG_QUANPIN_INNERFUZZY_ENABLED "QuanPin/InnerFuzzy/Enabled" #define CONFIG_QUANPIN_CORRECTION_IgnIng "QuanPin/AutoCorrecting/IgnIng" #define CONFIG_QUANPIN_CORRECTION_OgnOng "QuanPin/AutoCorrecting/OgnOng" #define CONFIG_QUANPIN_CORRECTION_UenUn "QuanPin/AutoCorrecting/UenUn" #define CONFIG_QUANPIN_CORRECTION_ImgIng "QuanPin/AutoCorrecting/ImgIng" #define CONFIG_QUANPIN_CORRECTION_IouIu "QuanPin/AutoCorrecting/IouIu" #define CONFIG_QUANPIN_CORRECTION_UeiUi "QuanPin/AutoCorrecting/UeiUi" #define CONFIG_KEYBOARD_MODE_SWITCH "Keyboard/ModeSwitch" #define CONFIG_KEYBOARD_PUNCT_SWITCH "Keyboard/PunctSwitch" #define CONFIG_KEYBOARD_PAGE_COMMA "Keyboard/Page/CommaPeriod" #define CONFIG_KEYBOARD_PAGE_MINUS "Keyboard/Page/MinusEquals" #define CONFIG_KEYBOARD_PAGE_BRACKET "Keyboard/Page/Brackets" #define CONFIG_KEYBOARD_CANCEL_BACKSPACE "Keyboard/CancelBackspace" #define CONFIG_KEYBOARD_SMARK_PUNCT "Keyboard/SmartPunct" #endif // SUNPINYIN_CONFIG_KEYS_H // -*- indent-tabs-mode: nil -*- vim:et:ts=4 ibus-sunpinyin-2.0.3+git20181120/src/sunpinyin_engine.cpp000066400000000000000000000504331337507011600227720ustar00rootroot00000000000000/* * Copyright (c) 2009 Kov Chai * * The contents of this file are subject to the terms of either the GNU Lesser * General Public License Version 2.1 only ("LGPL") or the Common Development and * Distribution License ("CDDL")(collectively, the "License"). You may not use this * file except in compliance with the License. You can obtain a copy of the CDDL at * http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at * http://www.opensource.org/licenses/lgpl-license.php. See the License for the * specific language governing permissions and limitations under the License. When * distributing the software, include this License Header Notice in each file and * include the full text of the License in the License file as well as the * following notice: * * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE * (CDDL) * For Covered Software in this distribution, this License shall be governed by the * laws of the State of California (excluding conflict-of-law provisions). * Any litigation relating to this License shall be subject to the jurisdiction of * the Federal Courts of the Northern District of California and the state courts * of the State of California, with venue lying in Santa Clara County, California. * * Contributor(s): * * If you wish your version of this file to be governed by only the CDDL or only * the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to * include this software in this distribution under the [CDDL or LGPL Version 2.1] * license." If you don't indicate a single choice of license, a recipient has the * option to distribute your version of this file under either the CDDL or the LGPL * Version 2.1, or to extend the choice of license to its licensees as provided * above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL * Version 2 license, then the option applies only if the new code is made subject * to such option by the copyright holder. */ #include #include #include #include #include "sunpinyin_property.h" #include "sunpinyin_lookup_table.h" #include "sunpinyin_config.h" #include "sunpinyin_config_keys.h" #include "imi_ibus_win.h" #include "ibus_portable.h" #include "sunpinyin_engine.h" extern ibus::Config config; SunPinyinEngine::SunPinyinEngine(IBusEngine *engine) : m_engine(engine), m_status_prop(SunPinyinProperty::create_status_prop(engine)), m_letter_prop(SunPinyinProperty::create_letter_prop(engine)), m_punct_prop(SunPinyinProperty::create_punct_prop(engine)), m_wh(NULL), m_pv(NULL), m_hotkey_profile(NULL), m_hard_forward(false) { CSunpinyinSessionFactory& factory = CSunpinyinSessionFactory::getFactory(); CSunpinyinSessionFactory::EPyScheme pinyin_scheme = m_config.get_py_scheme(CSunpinyinSessionFactory::QUANPIN); factory.setPinyinScheme(pinyin_scheme); if (pinyin_scheme == CSunpinyinSessionFactory::QUANPIN) { update_fuzzy_pinyins(); update_correction_pinyins(); update_fuzzy_segs(); } else { update_shuangpin_type(); } update_user_data_dir(); update_punct_mappings(); factory.setCandiWindowSize(m_config.get(CONFIG_GENERAL_PAGE_SIZE, 10)); m_pv = factory.createSession(); if (!m_pv) return; m_hotkey_profile = new CHotkeyProfile(); m_pv->setHotkeyProfile(m_hotkey_profile); m_wh = new CIBusWinHandler(this); m_pv->attachWinHandler(m_wh); m_prop_list = ibus_prop_list_new(); ibus_prop_list_append(m_prop_list, m_status_prop); ibus_prop_list_append(m_prop_list, m_letter_prop); ibus_prop_list_append(m_prop_list, m_punct_prop); ibus_prop_list_append(m_prop_list, m_setup_prop); update_config(); } SunPinyinEngine::~SunPinyinEngine() { if (m_pv) { CSunpinyinSessionFactory& factory = CSunpinyinSessionFactory::getFactory(); factory.destroySession(m_pv); } delete m_wh; delete m_hotkey_profile; } static CKeyEvent translate_key(guint key_val, guint /*key_code*/, guint modifiers) { // XXX: may need to move this logic into CKeyEvent if (key_val > 0x20 && key_val < 0x7f // isprint(key_val) && !isspace(key_val) && !(modifiers & IM_CTRL_MASK)) { // we only care about key_val here return CKeyEvent(key_val, key_val, modifiers); } else { // what matters is key_code, but ibus sents me key_code as key_val return CKeyEvent(key_val, 0, modifiers); } } gboolean SunPinyinEngine::process_key_event (guint key_val, guint key_code, guint modifiers) { CKeyEvent key = translate_key(key_val, key_code, modifiers); if (getenv("DISABLE_HARD_FORWARD") == NULL) { // Ctrl+ is pressed. let's just hard code these. // it looks ridiculous, but on what else do you need to do this hack? if (key.code == 0x20 && key.modifiers == IM_CTRL_MASK) { m_hard_forward = !m_hard_forward; return TRUE; } else if (m_hard_forward) { return FALSE; } } if (!m_pv->getStatusAttrValue(CIBusWinHandler::STATUS_ID_CN)) { // we are in English input mode if (!m_hotkey_profile->isModeSwitchKey(key)) { m_hotkey_profile->rememberLastKey(key); return FALSE; } } else if (m_hotkey_profile->isModeSwitchKey(key)) { m_pv->onKeyEvent(CKeyEvent(IM_VK_ENTER, 0, 0)); m_pv->setStatusAttrValue(CIMIWinHandler::STATUS_ID_CN, false); return TRUE; } return m_pv->onKeyEvent(key); } void SunPinyinEngine::focus_in () { ibus_engine_register_properties(m_engine, m_prop_list); m_pv->updateWindows(CIMIView::PREEDIT_MASK | CIMIView::CANDIDATE_MASK); } void SunPinyinEngine::focus_out () { reset(); } void SunPinyinEngine::reset () { m_pv->updateWindows(m_pv->clearIC()); } void SunPinyinEngine::enable () { bool is_cn = m_config.is_initial_mode_cn(); m_status_prop.update(is_cn); m_pv->setStatusAttrValue(CIMIWinHandler::STATUS_ID_CN, is_cn); bool is_letter_full = m_config.is_initial_letter_full(); m_letter_prop.update(is_letter_full); m_pv->setStatusAttrValue(CIMIWinHandler::STATUS_ID_FULLSYMBOL, is_letter_full); bool is_punct_full = m_config.is_initial_punct_full(); m_punct_prop.update(is_punct_full); m_pv->setStatusAttrValue(CIMIWinHandler::STATUS_ID_FULLPUNC, is_punct_full); } void SunPinyinEngine::disable () { } void SunPinyinEngine::page_up () { m_pv->onCandidatePageRequest(-1, true /* relative */); } void SunPinyinEngine::page_down () { m_pv->onCandidatePageRequest(1, true /* relative */); } void SunPinyinEngine::property_activate (const std::string& property, unsigned /*state*/) { if (m_status_prop.toggle(property)) { m_pv->setStatusAttrValue(CIMIWinHandler::STATUS_ID_CN, m_status_prop.state()); } else if (m_letter_prop.toggle(property)) { m_pv->setStatusAttrValue(CIMIWinHandler::STATUS_ID_FULLSYMBOL, m_letter_prop.state()); } else if (m_punct_prop.toggle(property)) { m_pv->setStatusAttrValue(CIMIWinHandler::STATUS_ID_FULLPUNC, m_punct_prop.state()); } else { // try to launch the setup UI m_setup_prop.launch(property); } } void SunPinyinEngine::candidate_clicked (guint index) { m_pv->onCandidateSelectRequest(index); } void SunPinyinEngine::cursor_up () { if (m_lookup_table.cursor_up()) { update_lookup_table(); } } void SunPinyinEngine::cursor_down () { if (m_lookup_table.cursor_down()) { update_lookup_table(); } } bool SunPinyinEngine::onConfigChanged(const COptionEvent& event) { if (event.name == CONFIG_GENERAL_MEMORY_POWER) { update_history_power(); } else if (event.name == CONFIG_GENERAL_PAGE_SIZE) { update_cand_window_size(); } else if (event.name == CONFIG_GENERAL_CHARSET_LEVEL) { update_charset_level(); } else if (event.name == CONFIG_GENERAL_MAX_BEST) { update_max_best(); } else if (event.name == CONFIG_GENERAL_MAX_TAIL_CANDIDATE) { update_max_tail_candidate(); } else if (event.name == CONFIG_KEYBOARD_MODE_SWITCH) { update_mode_key(); } else if (event.name == CONFIG_KEYBOARD_PUNCT_SWITCH) { update_punct_key(); } else if (event.name == CONFIG_KEYBOARD_PAGE_COMMA) { update_page_key_comma(); } else if (event.name == CONFIG_KEYBOARD_PAGE_MINUS) { update_page_key_minus(); } else if (event.name == CONFIG_KEYBOARD_PAGE_BRACKET) { update_page_key_bracket(); } else if (event.name == CONFIG_QUANPIN_FUZZYSEGS_ENABLED) { update_fuzzy_segs(); } else if (event.name == CONFIG_KEYBOARD_CANCEL_BACKSPACE) { update_cancel_with_backspace(); } else if (event.name == CONFIG_KEYBOARD_SMARK_PUNCT) { update_smart_punc(); } return false; } void SunPinyinEngine::update_config() { update_history_power(); update_cand_window_size(); update_max_best(); update_max_tail_candidate(); update_charset_level(); update_page_key_minus(); update_page_key_comma(); update_page_key_bracket(); update_mode_key(); update_punct_key(); update_cancel_with_backspace(); update_smart_punc(); update_punct_mappings(); update_candi_delete_key(); // update_quanpin_config(); // update_shuangpin_config(); } void SunPinyinEngine::commit_string (const std::wstring& str) { IBusText *text; text = ibus_text_new_from_ucs4((const gunichar*) str.c_str()); ibus_engine_commit_text(m_engine, text); } void SunPinyinEngine::update_candidates(const ICandidateList& cl) { if (m_lookup_table.update_candidates(cl) > 0) update_lookup_table(); else ibus_engine_hide_lookup_table (m_engine); } void SunPinyinEngine::update_lookup_table() { ibus_engine_update_lookup_table(m_engine, m_lookup_table, TRUE); } bool SunPinyinEngine::is_valid() const { return m_pv != NULL; } static int find_embed_preedit_pos(const IPreeditString& preedit) { int mask = IPreeditString::USER_CHOICE & IPreeditString::HANZI_CHAR; for (size_t i = 0; i < preedit.charTypeSize(); i++) { if ((preedit.charTypeAt(i) & mask) == 0) { return i; } } return preedit.charTypeSize(); } enum {ORANGE = 0xE76F00, GRAY_BLUE = 0x35556B, WHITE = 0xFFFFFF, BLACK = 0x000000}; void SunPinyinEngine::update_preedit_string(const IPreeditString& preedit) { if (preedit.size() > 0) { wstring wstr(preedit.string()); int embed_pos = find_embed_preedit_pos(preedit); wstring embed_wstr = wstr.substr(0, embed_pos); wstring preedit_wstr = wstr.substr(embed_pos); const gunichar* embed_cstr = (const gunichar*) embed_wstr.c_str(); const gunichar* preedit_cstr = (const gunichar*) preedit_wstr.c_str(); IBusText* preedit_text = ibus_text_new_from_ucs4(preedit_cstr); int caret = preedit.caret() - embed_pos; if (preedit.caret() < preedit.size()) { ibus_text_append_attribute(preedit_text, IBUS_ATTR_TYPE_FOREGROUND, WHITE, caret, preedit_wstr.size()); ibus_text_append_attribute(preedit_text, IBUS_ATTR_TYPE_BACKGROUND, GRAY_BLUE, caret, preedit_wstr.size()); } ibus_engine_update_auxiliary_text(m_engine, preedit_text, TRUE); ibus_engine_update_preedit_text(m_engine, ibus_text_new_from_ucs4(embed_cstr), preedit.caret(), TRUE); } else { ibus_engine_hide_auxiliary_text(m_engine); ibus_engine_hide_preedit_text(m_engine); } } void SunPinyinEngine::update_status_property(bool cn) { m_status_prop.update(cn); } void SunPinyinEngine::update_punct_property(bool full) { m_punct_prop.update(full); } void SunPinyinEngine::update_letter_property(bool full) { m_letter_prop.update(full); } void SunPinyinEngine::update_history_power() { unsigned power = m_config.get(CONFIG_GENERAL_MEMORY_POWER, 3); CIMIContext* ic = m_pv->getIC(); assert(ic); ic->setHistoryPower(power); } void SunPinyinEngine::update_charset_level() { std::string charset("GBK"); charset = m_config.get(CONFIG_GENERAL_CHARSET_LEVEL, charset); //printf("charset is %s.\n", charset.c_str()); CIMIContext* ic = m_pv->getIC(); assert(ic); if (charset == "GB2312") { ic->setCharsetLevel(0); } else if (charset == "GBK") { ic->setCharsetLevel(1); } else { ic->setCharsetLevel(2); } } void SunPinyinEngine::update_cand_window_size() { unsigned size = m_config.get(CONFIG_GENERAL_PAGE_SIZE, 10); m_pv->setCandiWindowSize(size); } void SunPinyinEngine::update_mode_key() { std::string mode_switch("Shift"); mode_switch = m_config.get(CONFIG_KEYBOARD_MODE_SWITCH, mode_switch); CKeyEvent shift_l (IM_VK_SHIFT_L, 0, IM_SHIFT_MASK|IM_RELEASE_MASK); CKeyEvent shift_r (IM_VK_SHIFT_R, 0, IM_SHIFT_MASK|IM_RELEASE_MASK); CKeyEvent control_l(IM_VK_CONTROL_L, 0, IM_CTRL_MASK|IM_RELEASE_MASK); CKeyEvent control_r(IM_VK_CONTROL_R, 0, IM_CTRL_MASK|IM_RELEASE_MASK); if (mode_switch == "Shift") { m_hotkey_profile->removeModeSwitchKey(control_l); m_hotkey_profile->removeModeSwitchKey(control_r); m_hotkey_profile->addModeSwitchKey(shift_l); m_hotkey_profile->addModeSwitchKey(shift_r); } else if (mode_switch == "Control") { m_hotkey_profile->removeModeSwitchKey(shift_l); m_hotkey_profile->removeModeSwitchKey(shift_r); m_hotkey_profile->addModeSwitchKey(control_l); m_hotkey_profile->addModeSwitchKey(control_r); } } void SunPinyinEngine::update_punct_key() { std::string punct_switch("ControlComma"); punct_switch = m_config.get(CONFIG_KEYBOARD_PUNCT_SWITCH, punct_switch); if (punct_switch == "ControlComma") { m_hotkey_profile->setPunctSwitchKey(CKeyEvent(IM_VK_COMMA, 0, IM_CTRL_MASK)); } else if (punct_switch == "ControlPeriod") { m_hotkey_profile->setPunctSwitchKey(CKeyEvent(IM_VK_PERIOD, 0, IM_CTRL_MASK)); } } void SunPinyinEngine::update_page_key_minus() { update_page_key(CONFIG_KEYBOARD_PAGE_MINUS, false, IM_VK_MINUS, IM_VK_EQUALS); } void SunPinyinEngine::update_page_key_comma() { update_page_key(CONFIG_KEYBOARD_PAGE_COMMA, false, IM_VK_COMMA, IM_VK_PERIOD); } void SunPinyinEngine::update_page_key_bracket() { update_page_key(CONFIG_KEYBOARD_PAGE_BRACKET, false, IM_VK_OPEN_BRACKET, IM_VK_CLOSE_BRACKET); } void SunPinyinEngine::update_page_key(const char* conf_key, bool default_val, unsigned page_up, unsigned page_down) { bool enabled = m_config.get(conf_key, default_val); if (enabled) { m_hotkey_profile->addPageUpKey(CKeyEvent(page_up, 0)); m_hotkey_profile->addPageDownKey(CKeyEvent(page_down, 0)); } else { m_hotkey_profile->removePageUpKey(CKeyEvent(page_up, 0)); m_hotkey_profile->removePageDownKey(CKeyEvent(page_down, 0)); } } void SunPinyinEngine::update_cancel_with_backspace() { bool enabled = m_config.get(CONFIG_KEYBOARD_CANCEL_BACKSPACE, true); m_pv->setCancelOnBackspace(enabled); } void SunPinyinEngine::update_smart_punc() { m_pv->setSmartPunct(m_config.get(CONFIG_KEYBOARD_SMARK_PUNCT, true)); } void SunPinyinEngine::update_max_best() { if (m_pv->getIC() == NULL) { return; } int oldval = (int) m_pv->getIC()->getMaxBest(); m_pv->getIC()->setMaxBest(m_config.get(CONFIG_GENERAL_MAX_BEST, oldval)); } void SunPinyinEngine::update_max_tail_candidate() { if (m_pv->getIC() == NULL) { return; } int oldval = (int) m_pv->getIC()->getMaxTailCandidateNum(); m_pv->getIC()->setMaxTailCandidateNum( m_config.get(CONFIG_GENERAL_MAX_TAIL_CANDIDATE, oldval)); } string_pairs parse_pairs(const std::vector& strings) { string_pairs pairs; for (std::vector::const_iterator pair = strings.begin(); pair != strings.end(); ++pair) { std::string::size_type found = pair->find(':'); if (found == pair->npos || pair->length() < 3) continue; if (found == 0 && (*pair)[0] == ':') found = 1; pairs.push_back(make_pair(pair->substr(0, found), pair->substr(found+1))); } return pairs; } // the mappings in default_pairs will override the ones in user_pairs string_pairs merge_pairs(const string_pairs& default_pairs, const string_pairs& user_pairs) { typedef std::map Indexes; Indexes indexes; int index = 0; for (string_pairs::const_iterator it = default_pairs.begin(); it != default_pairs.end(); ++it, ++index) { Indexes::iterator found = indexes.find(it->first); if (found == indexes.end()) { indexes[it->first] = index; } else { // it is a paired punct. indexes[it->first] = -found->second; } } string_pairs result(default_pairs); for (string_pairs::const_iterator it = user_pairs.begin(); it != user_pairs.end(); ++it) { Indexes::iterator found = indexes.find(it->first); if (found == indexes.end()) { result.push_back(*it); } else if (found->second >= 0) { result[found->second] = *it; } else { // it is a paired punct, // but we don't support this kind of mapping yet, // so quietly ignore it. } } return result; } void SunPinyinEngine::update_punct_mappings() { CSimplifiedChinesePolicy& policy = ASimplifiedChinesePolicy::instance(); if (m_config.get(PINYIN_PUNCTMAPPING_ENABLED, false)) { std::vector mappings; mappings = m_config.get(PINYIN_PUNCTMAPPING_MAPPINGS, mappings); string_pairs pairs(merge_pairs(policy.getDefaultPunctMapping(), parse_pairs(mappings))); policy.setPunctMapping(pairs); } } void SunPinyinEngine::update_user_data_dir() { std::stringstream user_data_dir; user_data_dir << g_get_home_dir() << G_DIR_SEPARATOR_S << ".sunpinyin"; ASimplifiedChinesePolicy::instance().setUserDataDir(user_data_dir.str()); } void SunPinyinEngine::update_fuzzy_pinyins() { bool enabled = m_config.get(QUANPIN_FUZZY_ENABLED, false); AQuanpinSchemePolicy::instance().setFuzzyForwarding(enabled); AShuangpinSchemePolicy::instance().setFuzzyForwarding(enabled); if (!enabled) return; std::vector fuzzy_pinyins; fuzzy_pinyins = m_config.get(QUANPIN_FUZZY_PINYINS, fuzzy_pinyins); AQuanpinSchemePolicy::instance().setFuzzyPinyinPairs(parse_pairs(fuzzy_pinyins)); AShuangpinSchemePolicy::instance().setFuzzyPinyinPairs(parse_pairs(fuzzy_pinyins)); } void SunPinyinEngine::update_correction_pinyins() { bool enabled = m_config.get(QUANPIN_AUTOCORRECTION_ENABLED, false); AQuanpinSchemePolicy::instance().setAutoCorrecting(enabled); if (!enabled) return; std::vector correction_pinyins; correction_pinyins = m_config.get(QUANPIN_AUTOCORRECTION_PINYINS, correction_pinyins); AQuanpinSchemePolicy::instance().setAutoCorrectionPairs(parse_pairs(correction_pinyins)); } void SunPinyinEngine::update_fuzzy_segs() { bool enable_fuzzy_segs = m_config.get(CONFIG_QUANPIN_FUZZYSEGS_ENABLED, false); AQuanpinSchemePolicy::instance().setFuzzySegmentation(enable_fuzzy_segs); bool enable_inner_fuzzy = m_config.get(CONFIG_QUANPIN_INNERFUZZY_ENABLED, false); AQuanpinSchemePolicy::instance().setInnerFuzzySegmentation(CONFIG_QUANPIN_INNERFUZZY_ENABLED); } void SunPinyinEngine::update_shuangpin_type() { EShuangpinType shuangpin_type = MS2003; shuangpin_type = (EShuangpinType) m_config.get(SHUANGPIN_TYPE, (int) shuangpin_type); AShuangpinSchemePolicy::instance().setShuangpinType(shuangpin_type); } void SunPinyinEngine::update_candi_delete_key() { /* FIXME: need to get candi_delete_key from user's configuration */ m_hotkey_profile->setCandiDeleteKey(CKeyEvent(0, 0, IM_ALT_MASK)); } // -*- indent-tabs-mode: nil -*- vim:et:ts=4 ibus-sunpinyin-2.0.3+git20181120/src/sunpinyin_engine.h000066400000000000000000000125201337507011600224320ustar00rootroot00000000000000/* * Copyright (c) 2009 Kov Chai * * The contents of this file are subject to the terms of either the GNU Lesser * General Public License Version 2.1 only ("LGPL") or the Common Development and * Distribution License ("CDDL")(collectively, the "License"). You may not use this * file except in compliance with the License. You can obtain a copy of the CDDL at * http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at * http://www.opensource.org/licenses/lgpl-license.php. See the License for the * specific language governing permissions and limitations under the License. When * distributing the software, include this License Header Notice in each file and * include the full text of the License in the License file as well as the * following notice: * * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE * (CDDL) * For Covered Software in this distribution, this License shall be governed by the * laws of the State of California (excluding conflict-of-law provisions). * Any litigation relating to this License shall be subject to the jurisdiction of * the Federal Courts of the Northern District of California and the state courts * of the State of California, with venue lying in Santa Clara County, California. * * Contributor(s): * * If you wish your version of this file to be governed by only the CDDL or only * the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to * include this software in this distribution under the [CDDL or LGPL Version 2.1] * license." If you don't indicate a single choice of license, a recipient has the * option to distribute your version of this file under either the CDDL or the LGPL * Version 2.1, or to extend the choice of license to its licensees as provided * above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL * Version 2 license, then the option applies only if the new code is made subject * to such option by the copyright holder. */ #ifndef SUNPINYIN_ENGINE_H #define SUNPINYIN_ENGINE_H #include #include #include #include "sunpinyin_config.h" #include "sunpinyin_property.h" #include "sunpinyin_lookup_table.h" class ICandidateList; class IPreeditString; class CIBusWinHandler; class CIMIView; class CHotkeyProfile; class SunPinyinEngine : public IConfigurable { public: SunPinyinEngine(IBusEngine *); virtual ~SunPinyinEngine(); void init (); void destroy (); /* @{ */ gboolean process_key_event (guint key_val, guint key_code, guint modifiers); void focus_in (); void focus_out (); void reset (); void enable (); void disable (); void page_up (); void page_down (); void cursor_up (); void cursor_down (); void commit_string (const std::wstring&); void property_activate (const std::string& name, unsigned state = PROP_STATE_UNCHECKED); void candidate_clicked (guint index); /* @} */ /* helpers for @ref CIBusWinHandler */ /* @{ */ void update_candidates(const ICandidateList&); void update_preedit_string(const IPreeditString&); void update_status_property(bool); void update_punct_property(bool); void update_letter_property(bool); /* @} */ /* for implemented class */ bool is_valid() const; virtual bool onConfigChanged(const COptionEvent& event); private: void update_config(); void update_history_power(); void update_cand_window_size(); void update_mode_key(); void update_punct_key(); void update_page_key_minus(); void update_page_key_comma(); void update_page_key_bracket(); void update_page_key(const char* conf_key, bool default_val, unsigned page_up, unsigned page_down); void update_candi_delete_key(); void update_cancel_with_backspace(); void update_smart_punc(); void update_max_best(); void update_max_tail_candidate(); void update_charset_level(); void update_user_data_dir(); void update_punct_mappings(); void update_fuzzy_pinyins(); void update_correction_pinyins(); void update_fuzzy_segs(); void update_shuangpin_type(); void update_lookup_table(); private: ibus::Engine m_engine; ibus::PropList m_prop_list; SunPinyinProperty m_status_prop; SunPinyinProperty m_letter_prop; SunPinyinProperty m_punct_prop; SetupLauncher m_setup_prop; SunPinyinLookupTable m_lookup_table; CIBusWinHandler *m_wh; CIMIView *m_pv; CHotkeyProfile *m_hotkey_profile; SunPinyinConfig m_config; /// Hacks for GNOME 3.6 above, where there is no notion of trigger an /// engine. In GNOME 3.6 triggering only means switch the language/engine /// it is engine's task to simulate this trigger behavior if they need. /// /// This is necessary to do rather than switch back and forth the actual /// language mapping is because some applications (Emacs) explicitly tell /// ibus "there is no context", please don't trigger. While GNOME's /// language switch behavior does not listen to that. It's more of a global /// keybinding switch rather than per-application input context style /// switch. /// /// - Mike Qin bool m_hard_forward; }; #endif // SUNPINYIN_ENGINE_H // -*- indent-tabs-mode: nil -*- vim:et:ts=4 ibus-sunpinyin-2.0.3+git20181120/src/sunpinyin_engine_proxy.cpp000066400000000000000000000117111337507011600242270ustar00rootroot00000000000000/* * Copyright (c) 2009 Kov Chai * * The contents of this file are subject to the terms of either the GNU Lesser * General Public License Version 2.1 only ("LGPL") or the Common Development and * Distribution License ("CDDL")(collectively, the "License"). You may not use this * file except in compliance with the License. You can obtain a copy of the CDDL at * http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at * http://www.opensource.org/licenses/lgpl-license.php. See the License for the * specific language governing permissions and limitations under the License. When * distributing the software, include this License Header Notice in each file and * include the full text of the License in the License file as well as the * following notice: * * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE * (CDDL) * For Covered Software in this distribution, this License shall be governed by the * laws of the State of California (excluding conflict-of-law provisions). * Any litigation relating to this License shall be subject to the jurisdiction of * the Federal Courts of the Northern District of California and the state courts * of the State of California, with venue lying in Santa Clara County, California. * * Contributor(s): * * If you wish your version of this file to be governed by only the CDDL or only * the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to * include this software in this distribution under the [CDDL or LGPL Version 2.1] * license." If you don't indicate a single choice of license, a recipient has the * option to distribute your version of this file under either the CDDL or the LGPL * Version 2.1, or to extend the choice of license to its licensees as provided * above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL * Version 2 license, then the option applies only if the new code is made subject * to such option by the copyright holder. */ #include "sunpinyin_engine_proxy.h" #include "sunpinyin_engine.h" #define IBUS_SUNPINYIN_ENGINE(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_SUNPINYIN_ENGINE, IBusSunPinyinEngine)) #define IBUS_IS_SUNPINYIN_ENGINE(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_SUNPINYIN_ENGINE)) #define IBUS_SUNPINYIN_ENGINE_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_SUNPINYIN_ENGINE, IBusSunPinyinEngineClass)) extern IBusEngineClass *parent_class; struct IBusSunPinyinEngine { IBusEngine parent; /* members */ SunPinyinEngine *engine; }; #define GET_PY_ENGINE(__engine__) \ (((IBusSunPinyinEngine *)(__engine__))->engine) void ibus_sunpinyin_engine_init(IBusEngine *py_engine) { if (g_object_is_floating (py_engine)) g_object_ref_sink (py_engine); GET_PY_ENGINE(py_engine) = new SunPinyinEngine(IBUS_ENGINE(py_engine)); } void ibus_sunpinyin_engine_destroy(IBusEngine *py_engine) { delete GET_PY_ENGINE(py_engine); GET_PY_ENGINE(py_engine) = NULL; IBUS_OBJECT_CLASS (parent_class)->destroy( IBUS_OBJECT(py_engine)); } gboolean ibus_sunpinyin_engine_process_key_event(IBusEngine *engine, guint keyval, guint keycode, guint modifiers) { if (GET_PY_ENGINE(engine)->is_valid()) { return GET_PY_ENGINE(engine)->process_key_event(keyval, keycode, modifiers) ? TRUE : FALSE; } else { return FALSE; } } void ibus_sunpinyin_engine_property_activate (IBusEngine *engine, const gchar *prop_name, guint prop_state) { if (GET_PY_ENGINE(engine)->is_valid()) { GET_PY_ENGINE(engine)->property_activate(prop_name, prop_state); } } void ibus_sunpinyin_engine_candidate_clicked (IBusEngine *engine, guint index, guint button, guint state) { GET_PY_ENGINE(engine)->candidate_clicked(index); } #define IMPL_WITH(name) \ void \ ibus_sunpinyin_engine_##name (IBusEngine *engine) \ { \ IBusSunPinyinEngine *py_engine = \ (IBusSunPinyinEngine *) engine; \ if (py_engine->engine->is_valid()) { \ py_engine->engine->name(); \ } \ parent_class->name (engine); \ } IMPL_WITH(focus_in) IMPL_WITH(focus_out) IMPL_WITH(reset) IMPL_WITH(enable) IMPL_WITH(disable) IMPL_WITH(page_up) IMPL_WITH(page_down) IMPL_WITH(cursor_up) IMPL_WITH(cursor_down) // -*- indent-tabs-mode: nil -*- vim:et:ts=4 ibus-sunpinyin-2.0.3+git20181120/src/sunpinyin_engine_proxy.h000066400000000000000000000071331337507011600236770ustar00rootroot00000000000000/* * Copyright (c) 2009 Kov Chai * * The contents of this file are subject to the terms of either the GNU Lesser * General Public License Version 2.1 only ("LGPL") or the Common Development and * Distribution License ("CDDL")(collectively, the "License"). You may not use this * file except in compliance with the License. You can obtain a copy of the CDDL at * http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at * http://www.opensource.org/licenses/lgpl-license.php. See the License for the * specific language governing permissions and limitations under the License. When * distributing the software, include this License Header Notice in each file and * include the full text of the License in the License file as well as the * following notice: * * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE * (CDDL) * For Covered Software in this distribution, this License shall be governed by the * laws of the State of California (excluding conflict-of-law provisions). * Any litigation relating to this License shall be subject to the jurisdiction of * the Federal Courts of the Northern District of California and the state courts * of the State of California, with venue lying in Santa Clara County, California. * * Contributor(s): * * If you wish your version of this file to be governed by only the CDDL or only * the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to * include this software in this distribution under the [CDDL or LGPL Version 2.1] * license." If you don't indicate a single choice of license, a recipient has the * option to distribute your version of this file under either the CDDL or the LGPL * Version 2.1, or to extend the choice of license to its licensees as provided * above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL * Version 2 license, then the option applies only if the new code is made subject * to such option by the copyright holder. */ #ifndef SUNPINYIN_ENGINE_PROXY_H #define SUNPINYIN_ENGINE_PROXY_H #include extern "C" { void ibus_sunpinyin_engine_init(IBusEngine *engine); void ibus_sunpinyin_engine_destroy(IBusEngine *engine); gboolean ibus_sunpinyin_engine_process_key_event(IBusEngine *engine, guint keyval, guint keycode, guint modifiers); void ibus_sunpinyin_engine_focus_in(IBusEngine *engine); void ibus_sunpinyin_engine_focus_out(IBusEngine *engine); void ibus_sunpinyin_engine_reset(IBusEngine *engine); void ibus_sunpinyin_engine_enable(IBusEngine *engine); void ibus_sunpinyin_engine_disable(IBusEngine *engine); void ibus_sunpinyin_engine_focus_in(IBusEngine *engine); void ibus_sunpinyin_engine_focus_out(IBusEngine *engine); void ibus_sunpinyin_engine_page_up(IBusEngine *engine); void ibus_sunpinyin_engine_page_down(IBusEngine *engine); void ibus_sunpinyin_engine_cursor_up(IBusEngine *engine); void ibus_sunpinyin_engine_cursor_down(IBusEngine *engine); void ibus_sunpinyin_engine_property_activate (IBusEngine *engine, const gchar *prop_name, guint prop_state); void ibus_sunpinyin_engine_candidate_clicked(IBusEngine *engine, guint index, guint button, guint state); }; #endif // SUNPINYIN_ENGINE_PROXY_H // -*- indent-tabs-mode: nil -*- vim:et:ts=4 ibus-sunpinyin-2.0.3+git20181120/src/sunpinyin_lookup_table.cpp000066400000000000000000000114301337507011600241770ustar00rootroot00000000000000/* * Copyright (c) 2009 Kov Chai * * The contents of this file are subject to the terms of either the GNU Lesser * General Public License Version 2.1 only ("LGPL") or the Common Development and * Distribution License ("CDDL")(collectively, the "License"). You may not use this * file except in compliance with the License. You can obtain a copy of the CDDL at * http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at * http://www.opensource.org/licenses/lgpl-license.php. See the License for the * specific language governing permissions and limitations under the License. When * distributing the software, include this License Header Notice in each file and * include the full text of the License in the License file as well as the * following notice: * * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE * (CDDL) * For Covered Software in this distribution, this License shall be governed by the * laws of the State of California (excluding conflict-of-law provisions). * Any litigation relating to this License shall be subject to the jurisdiction of * the Federal Courts of the Northern District of California and the state courts * of the State of California, with venue lying in Santa Clara County, California. * * Contributor(s): * * If you wish your version of this file to be governed by only the CDDL or only * the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to * include this software in this distribution under the [CDDL or LGPL Version 2.1] * license." If you don't indicate a single choice of license, a recipient has the * option to distribute your version of this file under either the CDDL or the LGPL * Version 2.1, or to extend the choice of license to its licensees as provided * above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL * Version 2 license, then the option applies only if the new code is made subject * to such option by the copyright holder. */ #include #include "ibus_portable.h" #include "sunpinyin_lookup_table.h" SunPinyinLookupTable::SunPinyinLookupTable() : Pointer(ibus_lookup_table_new (9, 0, TRUE, TRUE)) {} SunPinyinLookupTable::~SunPinyinLookupTable() { } int SunPinyinLookupTable::update_candidates(const ICandidateList& cl) { const int size = cl.size(); if (size <= 0) return size; const int total = cl.total(); // total is the number of items in all pages, while size is the number of items in the current // page (only these items are included in the candidate list). ibus_lookup_table_set_page_size(*this, size); // We are updating the current page only, thus some ugly hacks are needed... ibus_lookup_table_clear(*this); int page_start = get_current_page_start(), cur_total = 0; // Dummy candidates are inserted when they are not in the current page. // Maybe we can share these candidates (but what if someone else changes the attributes?) for (; cur_total < page_start; ++cur_total) ibus_lookup_table_append_candidate(*this, ibus_text_new_from_static_string("")); for (int i = 0; i < size; ++i) { const TWCHAR* cand = cl.candiString(i); if (cand && cl.candiSize(i)) { ibus::Text text(ibus_text_new_from_ucs4(cand)); decorate_candidate(text, cl.candiType(i)); ibus_lookup_table_append_candidate(*this, text); ++cur_total; } else break; // I think this shouldn't happen... } for (; cur_total < total; ++cur_total) ibus_lookup_table_append_candidate(*this, ibus_text_new_from_static_string("")); return size; //ibus_lookup_table_set_cursor_pos (m_lookup_table, index); } bool SunPinyinLookupTable::cursor_up() { ibus_lookup_table_cursor_up(*this); return true; } bool SunPinyinLookupTable::cursor_down() { ibus_lookup_table_cursor_down(*this); return true; } size_t SunPinyinLookupTable::get_cursor_pos() const { return ibus_lookup_table_get_cursor_pos(*this); } void SunPinyinLookupTable::decorate_candidate(ibus::Text text, int type) { switch (type) { case ICandidateList::BEST_WORD: ibus_text_append_attribute (text, IBUS_ATTR_TYPE_FOREGROUND, 0x003E6B8A, 0, -1); ibus_text_append_attribute (text, IBUS_ATTR_TYPE_UNDERLINE, IBUS_ATTR_UNDERLINE_SINGLE, 0, -1); break; case ICandidateList::USER_SELECTED_WORD: break; case ICandidateList::NORMAL_WORD: break; } } int SunPinyinLookupTable::get_current_page_start() const { guint cursor = ibus_lookup_table_get_cursor_pos(*this); guint cursor_in_page = ibus_lookup_table_get_cursor_in_page(*this); return cursor - cursor_in_page; } // -*- indent-tabs-mode: nil -*- vim:et:ts=4 ibus-sunpinyin-2.0.3+git20181120/src/sunpinyin_lookup_table.h000066400000000000000000000065671337507011600236630ustar00rootroot00000000000000/* * Copyright (c) 2009 Kov Chai * * The contents of this file are subject to the terms of either the GNU Lesser * General Public License Version 2.1 only ("LGPL") or the Common Development and * Distribution License ("CDDL")(collectively, the "License"). You may not use this * file except in compliance with the License. You can obtain a copy of the CDDL at * http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at * http://www.opensource.org/licenses/lgpl-license.php. See the License for the * specific language governing permissions and limitations under the License. When * distributing the software, include this License Header Notice in each file and * include the full text of the License in the License file as well as the * following notice: * * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE * (CDDL) * For Covered Software in this distribution, this License shall be governed by the * laws of the State of California (excluding conflict-of-law provisions). * Any litigation relating to this License shall be subject to the jurisdiction of * the Federal Courts of the Northern District of California and the state courts * of the State of California, with venue lying in Santa Clara County, California. * * Contributor(s): * * If you wish your version of this file to be governed by only the CDDL or only * the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to * include this software in this distribution under the [CDDL or LGPL Version 2.1] * license." If you don't indicate a single choice of license, a recipient has the * option to distribute your version of this file under either the CDDL or the LGPL * Version 2.1, or to extend the choice of license to its licensees as provided * above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL * Version 2 license, then the option applies only if the new code is made subject * to such option by the copyright holder. */ #ifndef SUNPINYIN_LOOKUP_TABLE_H #define SUNPINYIN_LOOKUP_TABLE_H #include #include "ibus_common.h" class ICandidateList; /** * a helper class to maintain the IBusLookupTable */ class SunPinyinLookupTable : public ibus::LookupTable { public: SunPinyinLookupTable(); virtual ~SunPinyinLookupTable(); /** * update lookup table with given candidate list * @param cl candidate list * @return the number of candidates updated */ int update_candidates(const ICandidateList& cl); bool cursor_up(); bool cursor_down(); size_t get_cursor_pos() const; private: /** * set the candidate in lookup table * @param cl the candidate list including all available candidates in current page * @param index the candidate's index in page * @param begin the begin position in candidates * @return the length of candidate string */ int append_candidate(const ICandidateList& cl, int index, int begin); /** * get the index of current page's start point * @return the index where current page starts */ int get_current_page_start() const; /** * update text's attributes according to the type of candidate * @param text * @param type */ void decorate_candidate(ibus::Text text, int type); }; #endif // SUNPINYIN_LOOKUP_TABLE_H // -*- indent-tabs-mode: nil -*- vim:et:ts=4 ibus-sunpinyin-2.0.3+git20181120/src/sunpinyin_property.cpp000066400000000000000000000163631337507011600234150ustar00rootroot00000000000000/* * Copyright (c) 2009 Kov Chai * * The contents of this file are subject to the terms of either the GNU Lesser * General Public License Version 2.1 only ("LGPL") or the Common Development and * Distribution License ("CDDL")(collectively, the "License"). You may not use this * file except in compliance with the License. You can obtain a copy of the CDDL at * http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at * http://www.opensource.org/licenses/lgpl-license.php. See the License for the * specific language governing permissions and limitations under the License. When * distributing the software, include this License Header Notice in each file and * include the full text of the License in the License file as well as the * following notice: * * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE * (CDDL) * For Covered Software in this distribution, this License shall be governed by the * laws of the State of California (excluding conflict-of-law provisions). * Any litigation relating to this License shall be subject to the jurisdiction of * the Federal Courts of the Northern District of California and the state courts * of the State of California, with venue lying in Santa Clara County, California. * * Contributor(s): * * If you wish your version of this file to be governed by only the CDDL or only * the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to * include this software in this distribution under the [CDDL or LGPL Version 2.1] * license." If you don't indicate a single choice of license, a recipient has the * option to distribute your version of this file under either the CDDL or the LGPL * Version 2.1, or to extend the choice of license to its licensees as provided * above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL * Version 2 license, then the option applies only if the new code is made subject * to such option by the copyright holder. */ #include #include #include "ibus_portable.h" #include "sunpinyin_property.h" #define N_(String) (String) #define _(String) gettext(String) static const char *PROP_STATUS = "status"; static const char *PROP_LETTER = "full_letter"; static const char *PROP_PUNCT = "full_punct"; PropertyInfo::PropertyInfo() : label(NULL), tooltip(NULL) {} PropertyInfo::~PropertyInfo() {} SunPinyinProperty SunPinyinProperty::create_status_prop(ibus::Engine engine, bool state) { SunPinyinProperty prop(engine, PROP_STATUS); prop.m_info[0].label = ibus_text_new_from_static_string("EN"); prop.m_info[0].icon = IBUS_SUNPINYIN_ICON_DIR"/eng.svg"; prop.m_info[0].tooltip = ibus_text_new_from_static_string(_("Switch to Chinese input mode")); prop.m_info[1].label = ibus_text_new_from_static_string("CN"); prop.m_info[1].icon = IBUS_SUNPINYIN_ICON_DIR"/han.svg"; prop.m_info[1].tooltip = ibus_text_new_from_static_string(_("Switch to English input mode")); prop.init(state); return prop; } SunPinyinProperty SunPinyinProperty::create_letter_prop(ibus::Engine engine, bool state) { SunPinyinProperty prop(engine, PROP_LETTER); prop.m_info[0].label = ibus_text_new_from_static_string("Aa"); prop.m_info[0].icon = IBUS_SUNPINYIN_ICON_DIR"/halfwidth.svg"; prop.m_info[0].tooltip = ibus_text_new_from_static_string(_("Switch to full-width letter input mode")); prop.m_info[1].label = ibus_text_new_from_static_string("Aa"); prop.m_info[1].icon = IBUS_SUNPINYIN_ICON_DIR"/fullwidth.svg"; prop.m_info[1].tooltip = ibus_text_new_from_static_string(_("Switch to half-width letter input mode")); prop.init(state); return prop; } SunPinyinProperty SunPinyinProperty::create_punct_prop(ibus::Engine engine, bool state) { SunPinyinProperty prop(engine, PROP_PUNCT); prop.m_info[0].label = ibus_text_new_from_static_string(",."); prop.m_info[0].icon = IBUS_SUNPINYIN_ICON_DIR"/enpunc.svg"; prop.m_info[0].tooltip = ibus_text_new_from_static_string(_("Switch to Chinese punctuation")); prop.m_info[1].label = ibus_text_new_from_static_string(",。"); prop.m_info[1].icon = IBUS_SUNPINYIN_ICON_DIR"/cnpunc.svg"; prop.m_info[1].tooltip = ibus_text_new_from_static_string(_("Switch to English punctuation")); prop.init(state); return prop; } SunPinyinProperty::SunPinyinProperty(ibus::Engine engine, const std::string& name) : ibus::Property( ibus_property_new(name.c_str(), PROP_TYPE_NORMAL, NULL, /* label */ NULL, /* icon */ NULL, /* tooltip */ TRUE, /* sensitive */ TRUE, /* visible */ PROP_STATE_UNCHECKED, /* state */ NULL)), m_engine(engine), m_name(name), m_state(false) {} SunPinyinProperty::~SunPinyinProperty() { } bool SunPinyinProperty::toggle(const std::string& name) { if (name == m_name) { // called by ibus, simple toggle current state update(!m_state); return true; } return false; } void SunPinyinProperty::update(bool state) { if (state == m_state) return; init(state); ibus_engine_update_property(m_engine, *this); } void SunPinyinProperty::init(bool state) { m_state = state; int which = m_state ? 1 : 0; PropertyInfo& info = m_info[which]; ibus_property_set_label(*this, info.label); ibus_property_set_icon(*this, info.icon.c_str()); ibus_property_set_tooltip(*this, info.tooltip); ibus_property_set_visible(*this, TRUE); ibus_property_set_state(*this, state ? PROP_STATE_CHECKED : PROP_STATE_UNCHECKED); } bool SunPinyinProperty::state() const { return m_state; } SetupLauncher::SetupLauncher() : ibus::Property( ibus_property_new("setup", PROP_TYPE_NORMAL, NULL, /* label */ NULL, /* icon */ NULL, /* tooltip */ TRUE, /* sensitive */ TRUE, /* visible */ PROP_STATE_UNCHECKED, /* state */ NULL)), m_name("setup") { m_info.label = ibus_text_new_from_static_string(_("Preference")); m_info.tooltip = ibus_text_new_from_static_string(_("Preference")); m_info.icon = IBUS_SUNPINYIN_ICON_DIR"/setup.svg"; init(); } void SetupLauncher::launch(const std::string& name) { if (m_name != name) return; GError *error = NULL; gchar *argv[2] = { NULL, }; gchar *path; const char* libexecdir; libexecdir = g_getenv("LIBEXECDIR"); if (libexecdir == NULL) libexecdir = LIBEXECDIR; path = g_build_filename(libexecdir, "ibus-setup-sunpinyin", NULL); argv[0] = path; argv[1] = NULL; gboolean success; success = g_spawn_async (NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &error); if (!success) { g_message("Unabled to launch \"%s\"", path); } g_free(path); } void SetupLauncher::init() { ibus_property_set_label (*this, m_info.label); ibus_property_set_icon (*this, m_info.icon.c_str()); ibus_property_set_tooltip (*this, m_info.tooltip); ibus_property_set_visible (*this, TRUE); } // -*- indent-tabs-mode: nil -*- vim:et:ts=4 ibus-sunpinyin-2.0.3+git20181120/src/sunpinyin_property.h000066400000000000000000000065061337507011600230600ustar00rootroot00000000000000/* * Copyright (c) 2009 Kov Chai * * The contents of this file are subject to the terms of either the GNU Lesser * General Public License Version 2.1 only ("LGPL") or the Common Development and * Distribution License ("CDDL")(collectively, the "License"). You may not use this * file except in compliance with the License. You can obtain a copy of the CDDL at * http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at * http://www.opensource.org/licenses/lgpl-license.php. See the License for the * specific language governing permissions and limitations under the License. When * distributing the software, include this License Header Notice in each file and * include the full text of the License in the License file as well as the * following notice: * * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE * (CDDL) * For Covered Software in this distribution, this License shall be governed by the * laws of the State of California (excluding conflict-of-law provisions). * Any litigation relating to this License shall be subject to the jurisdiction of * the Federal Courts of the Northern District of California and the state courts * of the State of California, with venue lying in Santa Clara County, California. * * Contributor(s): * * If you wish your version of this file to be governed by only the CDDL or only * the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to * include this software in this distribution under the [CDDL or LGPL Version 2.1] * license." If you don't indicate a single choice of license, a recipient has the * option to distribute your version of this file under either the CDDL or the LGPL * Version 2.1, or to extend the choice of license to its licensees as provided * above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL * Version 2 license, then the option applies only if the new code is made subject * to such option by the copyright holder. */ #ifndef SUNPINYIN_PROPERTY_H #define SUNPINYIN_PROPERTY_H #include #include "ibus_common.h" struct PropertyInfo { PropertyInfo(); ~PropertyInfo(); std::string icon; ibus::Text label; ibus::Text tooltip; }; class SunPinyinProperty : public ibus::Property { ibus::Engine m_engine; const std::string m_name; PropertyInfo m_info[2]; bool m_state; public: static SunPinyinProperty create_status_prop(ibus::Engine engine, bool state = true); static SunPinyinProperty create_letter_prop(ibus::Engine engine, bool state = false); static SunPinyinProperty create_punct_prop(ibus::Engine engine, bool state = false); virtual ~SunPinyinProperty(); bool toggle(const std::string& name); void update(bool state); bool state() const; private: void init(bool state); SunPinyinProperty(ibus::Engine engine, const std::string& name); }; class SetupLauncher : public ibus::Property { const std::string m_name; PropertyInfo m_info; public: SetupLauncher(); void launch(const std::string& name); void init(); }; #endif // SUNPINYIN_PROPERTY_H // -*- indent-tabs-mode: nil -*- vim:et:ts=4