pax_global_header00006660000000000000000000000064137621665730014532gustar00rootroot0000000000000052 comment=911105ad4fadd2af448483139316a0302ebd2dbb gtkterm-1.1.1/000077500000000000000000000000001376216657300132075ustar00rootroot00000000000000gtkterm-1.1.1/.circleci/000077500000000000000000000000001376216657300150425ustar00rootroot00000000000000gtkterm-1.1.1/.circleci/config.yml000066400000000000000000000010751376216657300170350ustar00rootroot00000000000000version: 2 jobs: build: docker: - image: debian:buster steps: - checkout - run: name: Installdeps command: apt update && apt install -y build-essential meson libgtk-3-dev libvte-2.91-dev gettext libgudev-1.0-dev - run: name: Configure command: meson build - run: name: Build command: ninja -C build - run: name: Install command: ninja -C build install gtkterm-1.1.1/COPYING000066400000000000000000001045131376216657300142460ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . gtkterm-1.1.1/NEWS000066400000000000000000000012551376216657300137110ustar00rootroot000000000000001.1.1 : Fixed many typos (Thanks to Markus Hiereth) 1.1 : Clear scrollbuffer option Added Dutch translation Translation updates 1.0.1 : Change to meson buildsystem Autoreconnect last port Add several translations Bugfix: show HEX output 0.99.6 : Change of maintainership handfull of existing patches applied 0.99.4 : VTxxx compatible display 0.99.2 : internationalization (gettext support) 0.99.0 : macros support 0.98.4 : hexadecimal support (send and receive) 0.98.3 : now gtkterm has a configuration file 0.98 : first GTK+ 2.0 version lots of other changes ! see ChangeLog 0.97 : control signals control 0.9 : initial revision gtkterm-1.1.1/README.md000066400000000000000000000064361376216657300144770ustar00rootroot00000000000000# GTKTerm: A GTK+ Serial Port Terminal [![CircleCI Badge](https://circleci.com/gh/Jeija/gtkterm.svg?style=shield)](https://circleci.com/gh/Jeija/gtkterm) GTKTerm is a simple, graphical serial port terminal emulator for Linux and possibly other POSIX-compliant operating systems. It can be used to communicate with all kinds of devices with a serial interface, such as embedded computers, microcontrollers, modems, GPS receivers, CNC machines and more.

## Usage ### Keyboard Shortcuts As GTKTerm is often used like a terminal emulator, the shortcut keys are assigned to ``, rather than just ``. This allows the user to send keystrokes of the form `X` and not have GTKTerm intercept them. Key Combination | Effect ---:|--- `L` | Clear screen `R` | Send file `Q` | Quit `S` | Configure port `V` | Paste `C` | Copy `B` | Send break F5 | Open Port F6 | Close Port F7 | Toggle DTR F8 | Toggle RTS ### Command Line Options See `man gtkterm` or `gtkterm --help` for more information on available command line interface options. ### Notes on RS485: The RS485 flow control is a software user-space emulation and therefore may not work for all configurations (won't respond quickly enough). If this is the case for your setup, you will need to either use a dedicated RS232 to RS485 converter, or look for a kernel level driver. This is an inherent limitation to user space programs. ### Scriptability with Signals Some microcontrollers and other embedded devices are flashed using the same serial interface that is also used for outputting debug information. To facilitate rapid development on these platforms, GTKTerm supports the following UNIX signals: Signal | Action | Usage Example ---:|:---:|--- `SIGUSR1` | Open Port | `killall -USR1 gtkterm` `SIGUSR2` | Close Port | `killall -USR2 gtkterm` You may find it useful to send these signals in your own firmware flashing scripts. ## Installation GTKTerm has a few dependencies- * Gtk+3.0 (version 3.12 or higher) * vte (version 0.40 or higher) * intltool (version 0.40.0 or higher) * libgudev (version 229 or higher) Once these dependencies are installed, most people should simply run: meson build ninja -C build To install GTKTerm system-wide, run: ninja -C build install gtk-update-icon-cache If you wish to install GTKTerm someplace other than the default directory, e.g. in `/usr`, use: meson build -Dprefix=/usr Then build and install as usual. ## License Original Code by: Julien Schmitt This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . gtkterm-1.1.1/data/000077500000000000000000000000001376216657300141205ustar00rootroot00000000000000gtkterm-1.1.1/data/COPYING000066400000000000000000000156111376216657300151570ustar00rootroot00000000000000Creative Commons Legal Code CC0 1.0 Universal CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER. Statement of Purpose The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work"). Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others. For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights. 1. Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following: i. the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work; ii. moral rights retained by the original author(s) and/or performer(s); iii. publicity and privacy rights pertaining to a person's image or likeness depicted in a Work; iv. rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below; v. rights protecting the extraction, dissemination, use and reuse of data in a Work; vi. database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and vii. other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof. 2. Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose. 3. Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose. 4. Limitations and Disclaimers. a. No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document. b. Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law. c. Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work. d. Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work. gtkterm-1.1.1/data/config_terminal_dialog.ui000066400000000000000000000225771376216657300211530ustar00rootroot00000000000000 100 99999 3000 1 10 290 245 False False True center-on-parent True dialog center False center center vertical 2 False Close True True True bottom True True 0 False False 1 True False center start 5 6 12 True True False Terminal Font 0.01 1 0 0 True True True Sans 12 1 0 True False Scrollback Lines 1 0 1 True True 5 cfg_scrollback_lines 100 1 1 True False Background color 1 0 4 True True True start Background color 1 4 True False Text color 1 0 3 True True True start Text color 1 3 True False Block cursor end 1 0 2 True True start center True True 1 2 False True 0 gtkterm-1.1.1/data/gresource.xml000066400000000000000000000003451376216657300166420ustar00rootroot00000000000000 config_terminal_dialog.ui gtkterm_64x64.png gtkterm-1.1.1/data/gtkterm.1000066400000000000000000000032501376216657300156570ustar00rootroot00000000000000.TH GTKTerm "1" "September 15, 2019" .\" Please adjust this date whenever revising the manpage. .SH NAME GTKTerm \- A simple GTK+ serial port terminal .SH SYNOPSIS .B gtkterm [ options ] .SH DESCRIPTION .B gtkterm is a simple GTK+ terminal used to communicate with the serial port. .SH OPTIONS .B gtkterm accepts the following options: .B \-h, \-\-help Help screen. .TP .B \-c, \-\-config Load configuration (default is "default"). .TP .B \-p, \-\-port Serial port device (default /dev/ttyS0). .TP .B \-s, \-\-speed Serial port speed (default 115200). .TP .B \-b, \-\-bits Number of bits (default 8). .TP .B \-t, \-\-stopbits Number of stopbits (default 1). .TP .B \-a, \-\-parity Partity (default none). .TP .B \-w, \-\-flow Flow control (default none). .TP .B \-d, \-\-delay End of line delay in ms (default none). .TP .B \-r, \-\-char Wait for a special char at end of line (default none). .TP .B \-f, \-\-file Default file to send (default none). .TP .B \-e, \-\-echo Set local echo. .TP .B \-x, \-\-rts_time_before For rs485, time in ms before transmit with rts on .TP .B \-y, \-\-rts_time_after For rs485, time in ms after transmit with rts on .TP .B \-e, \-\-echo Switch on local echo .TP .B \-L, \-\-disable-port-lock Do not lock serial port. Allows to send to serial port from different terminals. .SH AUTHOR .B gtkterm was written by Julien Schmitt. Maintained at https://github.com/Jeija/gtkterm by Willem van den Akker, Florian Euchner .PP This manual page was written by Sebastien Bacher , for the Debian GNU/Linux system (but may be used by others). gtkterm-1.1.1/data/gtkterm.desktop.in000066400000000000000000000003321376216657300175730ustar00rootroot00000000000000[Desktop Entry] Name=GTKTerm GenericName=Serial Port Terminal Comment=Connect to serial consoles Keywords=serial;console;terminal; Icon=gtkterm Exec=gtkterm Terminal=false Type=Application Categories=GNOME;GTK;Utility gtkterm-1.1.1/data/gtkterm.png000066400000000000000000000370121376216657300163060ustar00rootroot00000000000000‰PNG  IHDR,,y}ŽusBIT|dˆ pHYsV‚V‚˜œ×1tEXtSoftwarewww.inkscape.org›î<XtEXtCopyrightCC0 Public Domain Dedication http://creativecommons.org/publicdomain/zero/1.0/Æã½ù=#IDATxÚí ¼U•ÿOUõú¶¼,$!@V²‘ˆ,D2΂2‚l *:âŒâ QÐqDaQÁAâ_AAÀ (!$’B @B²½—·÷RUÿs»«º«ëUuWõ«î·ä÷Íç¦êuW×zϯÎ9uë^"€þŽ„SÐs¦OŸ¾‚'§t;¹’tãúõë—½½)S¦ …ñ쇸Lä2žK-—F.m\Ú¹¼Çe3ïÃMÓV¼öÚkøo=Èý˜6mÚ)¼þNßmذ!ðº5vìØX]]Ýñ²,‹s=]×uq죸Ôp siᲟË.¯sù›¢(}õÕW›ûû5YB8ýƒñãÇ7Äb±KØ .æ?çY´Î(#¸Ìc£þ4ÿ†f̘ñ. ׃,tËØ€·õ³ÂBž\Îå\ø˜Ül!àãò着¦øØŸâùŸOš4éwË—/WQ›ú/2NAß*ödnŽÇãï±ðü¸„X¹ÂF~ÿþ›lÀoñú~ÎF<®¯»ðàX¬þʳ/pù¬«2Væc_Ìeù ¯ïÔ{¨Œgq Õ&!4üç  ¼jᥱodÑúæ)§œÒç¼lÞ¯á|ìáæIAê?—ûyÝÿ`1œÁ r5l´Â›z„²9šJgѺyß¾}ÿèKÞ‹Éɼ_¯ðì¿Up3dz¾ÄÇ}-j ôÌ`×××?ËFû¥jl w>okåÌ™3gõð"ž<]A‘¶åãþ_>ß÷õE/¸„8}+b#zŽg§xX\c±YÏÓ¿ño^çù<íä¿Ãö§J„ÆŸç}ùj" ”ö>Ïsn‘Eö³Á}”…ç l€{ÊÙÆ–-[lð?dÏl6ÿ¹®ˆáNˆD"wU㸧NZÇÛ{¸DÈúPkkël>öÇÊÝÎÆ×ñ±‹vY_å¢9öMgP#!XÀ…Y³fb1ºµÈ"¢Åö|6¸ç‚ØžðÌØ0OàÙßYìßXD?VécWe OŽqõëY¨.Ú¶m[WÛãuÝÆÇ¾˜²-âˆqY »€`Øãù>¹7ˆÜÅv:ÚÛAn“½´vö¢>ɳ®"ÈaÔí•|zÆŽÌd¤bÍ ¾Ë"} ü:û“|N?YÄÓZÈbýiÔLèn´GóäS._w±aö£Ûy %†nq ÷íÛwAÿëäþÐçQéoWjÃB´xòäîÚ} M X ;ÿ^Äh—Tº‰Áưq~ÆÍ‹aÑúZ¥Â`roº§³³SìSE›ˆð'vùúë£zB°€ÁÔ©S#E¼«÷9dûI5öƒÃ.ñžÞ£nN ‡G³ƒÞ¦ªª¢™AØåë›¶lÙÒRcg±þš›0²Xµ‚ E9²ÍCÙ:ªµ/¢¹ät8lüT„Âm[Y¨ï®Öq³X‹†·¿rùúŒ9sæ BM…`¬œêòUSWW×CÕÜ=7³ˆ<ã"f§ìYáÉq.ÛZêµU€Üáòy8•J„š ÁYã<Ñå«ß‹6S½°KË]>?Ntq gy‚[½“eyyµzÆ +y²Ýåk ç}²‹­è•’忸}F'ëòÕ;½Õ± ïÓ Ÿû X‡Ó¦MMÙn}k}o쇅B,Z]Älb€žå7g§/ÉzÁš€Ú Á:äaCâö¦iÛzk·¸ló»¿A; Ù¶^3YÞæ²OCQ[!X Ûçº#‘H¤­·vŠ ´ÅÅ ë+}ì,Ô­½uܼm·fõ¨ª¬CEQ\_À=xð`¯]ö~B.Ÿ«nCsÅ^;nÞ´âòUµ‚uÈÞŒ«7‹Å{q×ýîo€Ç>¸ÛmÛ­¨­¬CžP(ôAd|oì“ñîÜ8—iw€›ú /w‰m€Ú Á:äY»ví>Êøé.Îí}:pà€E&âbÐo(›]¾šÝ‹õÑíœ¿Ú ÁY6¸ôi½äe¸mWô¿%ÀÐ­ÙÆiӦͮöqïtžìçÖ!‡1Ø„§Í™3gX/ì’[W2/lܸ1ÔFZ[[W"è$fÿVuå3ÉeÌGþnj* dÁ­ñH"‘øJ5÷eæÌ™âEì™."òTÛ2zý«Ëן­²X‹~äÝúÅjJ§Ó/¡¦B°eZ–‹¾®Þt‰¯pxtdµê€¦i·¸|Ç_iWÀ»të!a‹õUë̘1ãʃæÄò =KÁÜïòyœEë;ÕØÆKyâ6ˆêS¯½öÚö x—¿%—Ñ{Äè5,$“*}Ü .#_¯È>Þ‹ê Á:;;E×&Í._¦ÒÃNM:õ8c<@r[*ä]¶óºÝ:(Œ°<&ÆS¬d(ØÖÖ&ÉíÉgÖ­[‡p‚¬=kÞVD0nŸ>}úÉ«‘ìEüžgk]¶§XXž¯Ô±óúÌeŸËדTUýÕyç§T(¼žÜ2ˆÑz¾Ú ÁÎ^ÖxâÖ6It#ü8{Zç¹Í™3gNd±zŽgÝòdIþþÚJ÷† š(;…glÚ´éñ€=-‰Åj R±pû£ÛhÁ^V‚=©+Èý½µZþþ7ìiÝ„ÇÁûqMÓV /¦ˆ÷óMÑ i¥…á>žök‰„hüZl$œ$oç1’jdßc¯õ8Dú>å1ìU\^d±iüýYxDÈrO$ù£ñš#âIXkkë©ü›‹ØÅ„¥<´µ©TJŒh£Wë¸_y啽|<¢ñæßÈååk&ÂÇpm2™¼”—½ÃÕÿ[·nÝ*2 ÕxþÍyÂ{åcÇÓ¢ÂÉåR„‚,àÃÛ˜2eÊçØ‹=‘–jñý!QØ€56`1”ý놗"pØ@G²NjkkO£·¿Ž—=sóæÍUï¡€Åzƒ!ZSñ^„gøeÛ¾ÌË‹ØË\¶ri2¾¯ácÇÇ/ÁzmǦñò×°Xý U‚|°|ùrÑïÔElŒ¢—/­ÝEH?Í(ùø±¸7áijì­ËÞÚÁ^ô0WODŸàr„‡Ÿa;Õ(ÖÖÏfÅ+BŸa±ZŽÚ×?@«ï¡±ñþ»Â5WÚ«M'X¬ÎèM±²zZ¼/³ Ѫ4o²§¶7 ±‚`žÂwýßʲ,rV¿¬Ð&Ö±(~xýúõ×öÂX€®ˆœ‹Èbcäå=ØDJˆ4‹Õœ7®CMƒ` eݺ÷YP.faY$¶€Vû¯ïâÉ“'ÏéÃIfûŠ¢ˆæ ¢ÂþÖ)ž.ãéd!Ò,Vm¨aýä°ú‡·õOžMØè.ây.ãc{¹<.¼56V±.×ÙçûÕW_!ñMsæÌùŸd2y6Ï‹'˜§p‰{\…È ®áã~XUÕ‡Y¤v£6A°yØ Ö²85ü|;Èí°Ø•ùOQ¦N:†=qh3‰·/ºø#¼ˆ×l¼/­üÙ»<}“§«9Ä¿ ¼©¯¿‰×ÿLÂÄž<$Êøñã£ñx|ÏO§ì`´#x?x?D“fžoæPZä§^…Bÿ0D¯ß^sP6N3+V¬ÕÕÕMæÙI’$âi ÎJ!ªª–õ;EQpòlèºÞ.ËòN>§›·mÛöÆù矯â¬@°Šò / ‰F£çòìÙ\>ÌÓúCÀP<ë²æ¼uê¹ÂIR·©}¾T9håò<ŸÛßr}üíŒ3š`¬kÖ¬žÔu\>Í%:ÐŽOÓ´Œ°ˆ©9oþí4_ŽX•.«Ð”#Zì}¸Î›‹é¤‹Ëƒ|~ÿgÞ¼y›!X‡¸G‰DnæÙ+¸„‚0Y‹U¤¬û+'áò+Z¥ÄÊ«wå$ZÖ©]¼¬eæó»”=®eë,öª>Ê“û¹Œâ$òIå–ᲇŽ~½+7áòêa•*/‚%òfDÄÞçó} {[Ï@°±º–'·qé7µÖ*H漓H+ö°Ð¯—åö$$ôêa¹‰–›@+¦xÙ§ý+õ¨ßÄ¢µ‚5ðÅêVžügDJRí#•º(%wZªR~ÆÉ„õ‚e~fñ T!.ª5'(‘r±¬®u÷œÔ‚¿­¥ˆ•):š)PÆ÷ZFˆÄÊ*T–×lÂe ’îPát›hå–·ŠYDÍ"ZÙŲߓMÄÈÕë.t™'–¼ŠnÂÆËº^?ûÓ/©½:P\KQ9NÃ##)"’*½uîܹ߀` \±÷{åü6)µÒÊZÚ'o¢Ê[ÔÉb¥™¢¤g§z®ò ÃÎWX]Ï Xáç¦ä$¬ö¯ëyÙ+ü\·lËX&7oÙë2¡ÉïƒË~:mËË~ìƒýœØ–)uNÜö³Ô9±~ît] öÇÿµëÑ50wŽÍnXx$M®™FÓjgÑ‚ú“¨^i(×ÕúOö´~Á`¬]»öt¾¸Oø uÚ¯¼N¢=òz(Õ›¡X Úƒ¡äQ÷.V®BQb{¥Ä*Q-%V®âP!Qõ,V=Õ\;Y Ñìú´xÈ'hfÝ\ßÎ>¯÷ ­§!X„¿ÿýïõ±XlÏŽöú›Ê´)ütPyÞÇ!è9–-ª~®ƒ¨N¬9–.;ü‹4¥fºŸ*¾=;uêÔ¶nËò¡ X,V×{«´ÔIbËhUì{9±"½{Nª0álÉ[YSÖÊK>¼náÑ0»DC¡r¼båº? ÚOˆåU¬ìË—¸Ñ^xÅuË…¶æ!uK«°~ø¬+Ætsûëôµ-Ÿ§Ÿìø>uj^«ø‘]]]_‡‡5p¼«í<;¨Ô²mòZûuJ{û–÷á'ĪZÞªÂ!V=ÇîÛë# -ÄMß÷}祪7±—5f {YÞÃâ‹x®±: l¢•ñïP§¼×ù.[p÷ÕmË”ë}x4”nÞA½Ïa.UÑsôbyJzÛ½$»g¤÷’,¾d]±¯ßî‘Y½wÛþìJ¾O_yó*ZßöŠ—ª>¸££ãl„„ýMÓþ¹ä­IÙLkã?Ê„ƒå†X…•Ô¡a(!„'Qõi(…óÝÃ\Çý´ xQƒöb9ž+o!–oüx€TF’Ýiߊ{ªZ;}ëíëhcûz/Õý,Vy%iV±ï»¤ýôJì'”¯l¹ôÀð>¨Šy«¾á9 ©îQT©Šy+oÞ{—ÖI7½ó Ú—ÚÛ£ºÁêã<òÈ#¢“1îKè´.v%¤–¢†â^1û¯÷áÅPú‹çè)wØM$}Šª—¼ùÍ[‘çbSª‰nݶĥ9rŽ£y2«Ÿ2kÖ,ñB³kçK;BÏs8ø¦è}èÈ[•òK†¹½•·ÒË Ç]n4ëZ_¡gé}PóV}Üs,)ª}-oEe†ãEn4îº4]s«ò©óÎ;O‡`õS-Z”æÉ6§ïD övi÷€÷>Êòý4Ϩ¢çèYT@ÞÊÍsÜѵ^m]ëVå·I’¤A°úwÒ}£Óç{B¯ (ï#мUÑst8'åzŽ¡þ—·rÛŸU-+ݪûëHº÷s¸B8^ÝÜ+7Äûè·y+êî9–ë}¸Šª£7Ô?òVNžã¦¶×ܪûJVÿ¬>]ÃôGç­*í}UªbÞJ.oeߟ݉ݎu]Ó´!XýœH$²š'éîIwµÿxúÀÉ[UÚûè3y+ .oe¿!ªÎϑҵµµk!Xýœ™3g¶ódƒýs…bý'oEUÌ[Ô4 ·¼š·²ž“¨sªêëÑ[ÃÀ¡[l_¯ŽFÞª˜¡ôÐsôä}èÈ[•ã9Ží9W;Ðl¤˜Ë/¿|Ž¢( b]‹¿yÏ=÷ü.¨}“$i%_Ы­Ÿ ÒŽ¡ÝÊ+½â}Ø ehJ§qí*5¤³] IôvBûxTÞjO'ª25ˆ:x¾™ÿÛ,k´ÇË~ñ­¢:\–éØPˆy*Ž£IÓhc*M»UÍYTÉ¿÷q¸&Ñô´DC´ìûø–»NÑi—¤Ï[ùè)bŸ£YJ˜†‰ãàù½ºJ/«iÚ¡ª}ÂsœT;¥»ç!Ë ÖW\q6¯sbëRUõ™eË–®Ò*ö¢‹.ªÇãëxö˜€ÎWšEëø rÍš5b¿¶X?k–·Òó±%EzŒ,â%ùm˜èÒÜŒ6•ÎhRiLRËôCn»eÒ¶ˆLl”éÕ¸\vïš³5™ÎÑ'ÉÙ«-ZÙV]£å”¢Õ¤y4èîçäøh˜.¨«¡ <ÍúìRþK–7»’ô‹–Z™H–Ý3êI,¶—¦Ã4Y—ÏÕë¼ÿ÷()ú«¤–ÝmÏ?ñýûêP”¦F"Da>EtöžßÞ†d’noo§gººŠ{¸=ìįÔC„;½¦Ôk÷°Ž™7oÞÛAØËUW]5“×÷’HdÏÛÒéôŒûµOÖ•W^yO>°÷·®©©iþòåË“‰–x´2"ï,hôçØ(!µV½ á({ŸÙ¯ÒŒ.=k29aFCØà_Ž-,S—P0ʆ}µ¢9²b1<Ûv2^Š.:Ù¥ÕÝ®¥¨« ëæâ9š¯ðºÆ:ZXË;¨X ¼à²ë'öŸoë¤[šZ©SÓ=÷1ãé5J'I!OçêY>†oQ'µûèߪ†ÿûÅéÔ(ß$2%$çI²œ/>–'Û:è«Í-Ô¦iÞëJ@7ĆP#=zÜ™A2,ì™;wîˆ ìdÉ’%¡]»v½Èû;'Hcæ(玥K—^Óë9,«E<ù\%ò僾>À¶ª°’K44=µêy«Ï\{@£âÕ6Bý(Ê–£ØþžM }í ø­7±Š°…}“Â4'¿*ùã¿cJa1¾;žõÆp{‰ç—Ç¿ùL§ä)ou%‡6G ±Š("¢¸ŠÖ„hˆ>ŽzzðåúÚl’²á“!JN륨áµðr“Ùûjc½§Pé¡8M‰EòÂQô\åÏ×´x”nˆÕzºÑܬGiš8빊ç=fDósã8fÖFè–†AUâ9·v^¦îVB°D(È“J &ñy¿û³Ÿýl}¯ V<ÿïóVŽdY¾÷¼ó΋ X/Z’€™‹>¨s".y{jÀ µÇ¤tšCráÜê!8Í[¼¢…ÞMNKEÛ[MfÏíøpØÙÁó1×kÃOfOcš¤}j6M e½žLˆf„M9á’óŠé]…+”]ö´º8ÍŠ„‹z39ü{K¹ýŒû;WgÕÆi~(TôF3WSèÌP¬û¹ÊmÓAØÃ²‘ß’él>Ž…áHEžx:õ/¢‚±ã2uWÔaËCª7¡ Oî 0oåÄØp8|k¯VCÁŠ„†fR1h¨yÁåTœê’GV­aâÇXlº…gñ"aNÜZq9CW¨Ø µÿ g…Á4,GѲ U^¬La9›Å¨ØÝþ“ìÁäø¹"Â%ç=­\âZ6Ä-_>U_SÔû¸¤&nñxÊ;W—ÔÖÚ„½ðFs•-­eÅË\ÞØÙù8%äè}ŒçÏÃaKøåç\Eò¿ ñ:&° 8=ñœL ŸVS¬-ç(35ÖczXb^‘ š8ä*&ÿ=)s®È¹!m‰¼U·ºRÄ{Ÿ™EöúË^VòWU  } VCÁf.Øì¼š¡a7ÁŠuNJº¦âÁeîÂf(¡˜Fbä}¬áGÜ–/1—SòÐ IrìÆyPAC+ÇG¥†ˆÉ^‚Sx7$· *ÈÑ  dÊ#S¨2b¥æÅªË˜Oße„Ëð¼Ô¬x Í40íî} Q,!¤bË‘•:WŠåø¸ ó7š¡’íz˜ó![>Nˆ•d{|l^p-ëU'©â£*ÕIõt”<¶›`qé‘`õ Ô [n.744´¤r‚uõÕW×jì53~.IÒYuwß}÷`.#ÅSq.ÇóNŸ§M>váú+®¸â¸r/ޏ¸"îŸ;‘ÆÆS×ztÅòVæ|:÷­”ŸØ=!ÓCÈy¦ÊÓ2uUáðÓ¬·<¿çÄO,«u;ÛxL{¿°)Ñ]l§×ßyçÝŒ_þò—"?ü¸(¼Þ[xÙel§'xXí8CS<7(•}à"áÆy\üÁ|ÄI¬ìÜ{ï½–.]z%Ï~Ñc¨(î ß,÷®Â{•)Vf‰7å/$òüB­Ç¼•uù’F¢b[ó=öœOgÚ(jÞ3±†^üÛ6^Ç{¤9Šê6þ¼]µüƺ¤%T³†lIµÐ ¹´ryÛ[H³•7Ú–²xMæþ'LÏÊð®:¶¥å¶×ÂÓ·TÍá©™N›Ó*…t‘se]wî8²çê ïçÉ´c^i“®ÒA»7ªž”Ø^Æ[Lç#· µà\5óüFR+Úˇ¤K4YžBözÛÃüÕ7 [ò Uú5lËŸw+gäæææbÁz¨¡¡'ÁòóTPxVMMM—ù}¥†ô§<¹¥ÒO ÅEbb^t1/§biQÑ „Ÿüªf*{ÎG_‡Q¬†h3Æ5©t6¼tU±Õ¢Q¡›X%œDË‹h­L&³&èж(-éô± «P%Š¬ß …¢õ·D‚·¡9t6´}®­Ë"Tj¡à:«.5¿œq,Ï´vÚÎU~>Å3Ï$Ý^êž‹s¸–÷‰DWÆéªä¨JGJGQ­^Göz[nþÊÏSA¶çï°XÝágýÂöyÿ.åÙCÃû¼>5ô$X>ž v±›za¹ïÿ5êaו|j(Ù™ÜzñãMGž·²Êã’Ji{bÚô:l¥ÓfŒ‰ìoÓÓEEõ7ZŠRIÄn€V!1—ãišì×,XÅÞ¿{PÛ°ˆ]Â.ViáÊ/—âò€š(ÚŒdY{'%“é|âÞ\¯Û¹Ê ‹fl#MK[ÚŠ¾þ“$oCµ„w¹s¦å·Õé$ZjÆÓJq¹=ÕYñQ•¦Ð±Ýê«1ï»Á¨Ï§‚ë?üð˱e‘²a½ˆg;ƒ|jXR°|>¼óŽ;îØÞƒG¬"Fðz‚ÊzjÈ'q5_ðt&ß`qñcMc+ÞÜ^Y§ÇÈ>¡S‡é5ØæsáHÖp­&i¤UñýÃjÊÙêr-khÈåþdí2znp sws­¹_J¹¬[µyºP0rg*A;5­h3’÷5•î:Øž?WÏ•±ÍÛšZh{Z-Ú¿ÕÞÆmmm6´ˆø¼F7w¶Ó6]­xï´“õ)d­¯FI³#á»Á¨Ÿ§‚¼Ü †M–Å]wÝõ>{hwÊA…‚†÷òõœÇ}<9ôž~úéí|r6X/¾ Ò:œäd<ÐŽàœîêO†5Z¡§m9+›We7îòO§Sô„¢yÕÇä4=•N,§¢Ñ8Lûžry_æ>ÑX|Ó¡ ƒw•È/÷Þ¯‡¥d÷6JáøÏôHkG¡wUê\ñ²±Ð=ÐÙéÒú¼ðFswW'=ØÖ‘ÍMå¼9ËͤӖ3Îç}]í´TKT,oeŠj^KGÒ˜n‚Ŷ¶~Ñ¢E¾Œúl ÚÌbó§ž3¯ãW>ž– ‹ VMMÍÈ{ѦeË–½ÜÓ4žþ=ïõ)'{LËŒ'~X™ïÆ-]¢hÓ¥0ðÑ\÷Š™ýë¡ѯ•ö|ŒC¨ÓÅÆó€Ä%ª•xPh(wóúïÕ“Ô•°ŠŠÅSÉyWéÌ2w¤»è.)å«wÍÛkTúI8M]n\¾tòö¨'è¶PÒ1oåŽßšè ï³Ôá:[ΕXæ;-­ìù´†ãö›ˆMÄnhk¡%쑵w¥ Cõ®táƒ.íüù7Ú[éútgUzù˜¨MÊôÎ`½¹Š©è”ÒïSAþÝä½èså<‰wð²Ä+q^Ûj• C=l§ò„:ñžeͧ†K¼þÀè¹ájÛgÝ?†Ú‡¿Y"Ñ}ÞÛà§…wûgã­ëôÑvæ&u:L#²¶PÜ÷’Õa‰ž¨Õ©Yöò0 »¡<Òéï"þKJ¢…)™FØå]üÝ ’J¿eÏ­YÒ}Œ “?'¿ëô\X¥óØI9))Ñ(M*h*ð>OŸc¯òá˜Fûåòz)xXMÐÓ)ú´¦(a:B’ ÎÕv/ÿÌèìñdš]É[u÷œ³=ÐÕALtѱ:#Íö¨ai’ñn*E³z Õ^£iJ5FUšd„ƒN*ôT°,jnâ!9—F¯¡!{‚.]ºôi_‚ÅœA>ÞdÅï  ŽP×Û%É×kŠgú,réŽ#v`LÆÓÒ->•—¼•[’Ý1Gc1”ƒl4HôkÞæ 6ŒÆtv{M!Ñ#ªTÒû()ª¢+d‰¢\t•YL+ÝÏ—ö€l1n/a®‹ç¸_Ñé.väïä³#2LËþn/ëÊ… zÔ,–·*æ9 !ú‘ðÐR F¢Ëçlër‘³ÛKyï£'}ãïÕ5ún{hìAÆ¢8B\>–øÜ} ëetÆW~Þ*ÛvV¢ úÄb7]¿6â‡Àì™m¹M×=û2â]CñrôÓ¾BÂÎÎN‘üÞâCdFRpîcYу¯ÞNÏ>ûì­”}­ÀzR3ÍB-Ã\óV~½?ƒH/êö¨¶E$‹Xõ°«ÍP°xmåílBb+×Gñþ=G!P›Ù³Û¶‰éþú*â9 ]"¿.ib¥Spc:îa¥ÚViƒ–ΈUoŒª4Z;’êô:r¸yï9÷Üsßö)¢avÒÇòÙ3_ŸQ>Ý)ÇwËh½z¥0ïˆË.»lH@Š<ÃÇâß-§ïw³RQÌ !¦Ñ}c\óVåxÞ ¥gÞG †€çXÒ ©çžcIQõs£é£c:NP'ÔM˼ïöWb‰1nñ!23‚°åk®¹f¨Ð^áãg‹õý.—H€¯à“s§øY==@½£|ÄÚ¢ÍÖwËÅ•v±ÊÖþ#{6øiQo¨H8÷QÚPÈ[óŒ€<ÇŠŒ'H{LG“ÉÚdrª£T~£ß%oí³®¼òÊ1=µçT*µ˜Ä0 ÞlòN¡9e?%̲ÿá54ä ~uÉ’%=êÅTQ”ë|„‚——û$Cô@jVÚ¼`µ '9/>øi5¼½çÞ‡«A—òÈúˆçØoÇtÔËÏ[™ó5Z ¡INu”m¤¬F…­ðï/ñ eüJOlÙЂk½†‚,n_/µPIqñÎܵk×¥å +útc[ MVs%HÛ+„,)90º÷½ &oå×Pú’çèYTÊ[>ˆDy+óœLÐ&’"+…u“§¢Î2e×{Ÿ¡¡xbwl¹ÛÚ¹s§È›Í "ô,X~CC®H?½üòË/C¬D¶ûQòÖN¤ìPÐD4 å‹¿Á¨Ö Añýcú´÷¡ðgÓ:–è_Ó2Æ÷tZ¥§†b™i:ÍjÓè¬>Õ¢ÓâN‰ŽKKÒËì]ÓATªNóšU:ûƒ4]²K¥sš4š×¡QX+ST<¤-äm\°G¥«v¥é‚ý}¨]çãë›y+sù‰ê$²×MãæºþüóÏïéô^CÃ(ÃcFÊ,t yòã BÁ\ÞÉëˆÐ0”gÇ—X4Æ'÷i ‹x'õxpøÄüžgö ²wÕãFmb´\.³DeÝvdúyçùšæ£h¿hÞ éex>Ðôé}4¤4:wOŠNNJ¯c]¯µ ¼ ÈÔÁ˯èJЯ“ :XŽ¡ð).ü E§upX¶ôo.Ú%ñý­·ó”¢Ò/R]™nnÊñ‡$5ºl{ŠÎbª ™}[ñ4Å÷ϤBm ™þP£ÑRV›ý’ÖÍûð’·ÆÇqõNÁƒz¦Ëå‚® yý­2ý†·q{,Mû$½Ïä­2Bùß$irN°DÝ4çƒáY„†ls—x,u<‡j/²òq¶¹MíùL^·há *´Æ©~¼ ñ®Ï³'jÚÃ\¾Å'h«Ó—\rIc$¹Îˆ•k<îÆ¼¾%A<ÁøÝï~÷i>Y¿L&“"9˜)æüŽ™P²aë(ÁžCA/"ç8¢r¡ÈÍÚ—¢kßíÌ U½(a¢ºp¶›à¨Ñæ8ã •Ú;Òô?ÉNZ+kÝ÷³ˆ7°à Fßx?E5ÖîˆsÃtޮӯ³75·ÒÊÎD‰@óçD|ÿá&•n~7ÅBeö½^Ø»uPŒÖ°Dÿ‘j§ç“©îç¥È58¥U£½ÏBevmïÙü›K Ÿ¾k´ú‹xÿ²BƒŸ:ï§»Gv„6†®Õ¾LápX ž’™šó¡PèÓçœsN¯À {vôm‹‹ÔÐm\~ÈöwÐåÙxÔ›Øcú”G|ªWïÊ·`êù3>±WûÉos1÷_ùwÛù`Ä‹Ç#y:Ÿ?;…üõ%-ÜØùA¼2`Ö1ìUm± •YöŽzšŽZ]ÄKò˜·*gDiÛ¶>´³‹¾¸µ“äA|ªŒR XF7¾âå]ñÚM{Š´Öý·”¤ç£.ûi3”SšÒôõ4’cv±² ÉwG,µ/ÙÕLiíð4ôúi,VßÙÍÛˆ(…#Õ„æ~Ù5._Û×LO¶w:ˆwñ8«M§Èö}Ÿëê8d*ÑRyþšæfú}ggà×γ‡k¹¤O£³”ÅBeÎÇb±c/^üv@‚%^i{‰üµ€O²í®à(g5OÅhêbGðü)|ì³É_csߣAû,ñB4‡†¯z ƒF„‚Ç÷$Ñî"Z»Y FØ«%ºÞŸ¹Ü›—ä¹­O‘ã2¶)Eßy¹…"Bœ¬‚Õ`¬ˆÑBS¼¸ËbEm\Z’”`Ñúê Þ‰HE å˜N=•¢V¡²O#ï'”½+­ÓU[vÓ–®Tîœ8óÄ„N÷rõŽZ½(«pÙ=-˰c]ì=^ðæNÚÜ‘(z ¦ða?Òâ]V …É.ZÝæ%êäÉâ­»éõ®„‹—¤ûÏ[éþÂqs[_bïj|x|N¤,¢µçì³Ïdý/D{ ƒF4á%Ñî;énjÈnßÜ{ƒ^¹9h±Ê$ñB¡U"GÀÓL®À,u]£²½7š·"ßy«‹_oc»–ó£Âˆ‰eTba”æÕ4úg 1Ù­–Lð^Ù¤ST_­QêÄÔD1Í|Î~^cÙ&{ŒýË# ΉÓS³/wÈB;È¥4:|fˆsŒËõ‡—Ì[]¯G)6(ÆëŠæ×™™óÆßÝæ££›'(’·òù€ÄgÞʤ†jiœ2® .ZêæÊ ë¿ß¥¡³wu¥_±*K°wÝu×s>”Áº¦¦¦ŠœT‘Ä´VŒ\åCT{pLéo‘jý>5³ÊøýIšÚ’Îc•‡ž7sXÖ'ÔìðZÓ[Ó4±Uu5”)ìù'<’ZC¤ÌRg/S¸j,93EÊõ ?+¦)–‘œíÞÇtU¢¹bg7±u«úüöæ ©¥u1×¼ÕLI¡ãâ6¡ŠäÅÉM´,¸ðÈF:®1^ÁöV¥=²É4…BJ¨{}Ì&ÞWVÂFu3ÛóÚ*Úón/7WD°Ì§†äã]Æ‚—•Û‹©ÁzѬfå0çë[ŽîÕ†‰ vwYÂ%¥0„²ŠVHÎ{Vªné =ÛúÂ}IWC9A•-beñ²¬âe~'ÄCxr’e¨/£3»“ÃWï㥄8Ù½,ñPÁÜV¦虎õNm¬qmžqzF£ùuä„)ê,Zæ~Ø„ñÌQƒŠßh*4ª’ùåTyªc]…ÃÂ+aK–,½k_F>Þ5ìa(Xö ­e VCÊ„‚ÁZÍ•!m­fÔ>Þè½ÁÍ3ªlÃÄ£[Ô¡䭉êˆ%,$ÊzS0f`v”— Í)WC™(‡òžS®„ˆÆ(ÉšîØ+ç£*9ySjœ[F˜Â…ÂÕ-ôtĶ…÷&DJ¬[ôu•ÉË¥iïk÷†«Ù¿¦ ŠŠ’U„*œEsdÞÞÌšhÉÁO+1ª’ùÙ´ð4rª‹¢Ž†ÃáŠÙA•BòCÁ V•BÊ…‚&¢)W† fŰ&:ãRÅÛGV7oe1ŽF!>a[ÚšœŽy+û(9¶2´MuÝŸÁ±Pw±rò´Œ&ù^8 {ú–Ð]½¡õQËã˜Â%„Cü-– "X + Úï+]îjÔÈ^V5óVÖ꟎ȅÃÌgæ-£‹¼U—m Rë°]Æg)Mw5””ÈGÅáß3Å 5ĺ¨! …—ÓîÞãg²+íê}¤j”¬0Õ‡-Í1ÂÙíd*ÿö`²°´dE*ÿw’’mIgñ±LÁ6Œ0O­8&᱉ó‘Y_¢û¶,ÛH´$«ž·2秇f¸yWI¸W94ìQ(˜`U04¬h(h…ïd+­w5kÚ9©×^¨ÝŸ Y¤ÂGñ™aØ7Sšó 9ËŽî²/,¹Šø.×Z>ׄAɇeB¤º•T^¬ŒÏö&Ò®ÞǵÖâQò^a¦ù—f'IØ„+E´%]ÃñÄÿæÓKÅhD+ÎK«m}ÍIc{‰ì¼ùÙÁìç»ÄwUÎ[™"7+6‹Üꡨ£Õ°… …†=¬ …†­D£QWÁ¢¥Z[µ¼•ÕP66†³¥OåÌaÙ%#Áž°×e/YáZ7,âÚ’ñª¤ü …1 cÖtçщ-åÉ#by±r¸ÃïLó2-tæ°º¬ñšëO[„#Ql”ç4=b%»z;º’ôØŽf:»¾¦P¬RZwÁ²æâ,Ÿ=×X¬¤Â^,×à]ÞÆo¶ OªË ”ê N¦p¥l"Æ?('齈V^ÞÊ·Xž«¹µsÍw»%Ý+Õþ ‚ÕúsÅø¸¨$×Ó"X£´éôjv$°êv'r„CšÁ‘ÿpÓÖô¼!Š}H-‹°ìæ«{ÿ”ZgQµæÝ{Òìx”½-ÙX¿^(nbÅÓšJwŽ jÆܾ«‰¤ø\êr^¬R¶|[Òî]e?ßÁk»m”R²çïï<@'¤äì¨:ݼ*㘺‰Vöï÷ø8¾7$Ýó¼ùUIôÎ0·~n7¡Óö0 ÁÀ‚•ëTÜé¬=<ÊéÁ4XC”w«ÛOZØö¾[§Ó1"Ù‚Ý|†cMºÛ†Ÿ? éô­9õÔ‘KvÆ×ÌëüÆŽ}ôÃÃÓ ÅÄšÌï*®}ü»¯)Ss¨´÷q€—ýâž&Z®¡airö®ÂA1¤ÖU“#™‘„Іãâoã³{öÑC‘:L%Ï¢õ®Ñ…‡ëÙA3*·rK²›ˆÜÕðøðïJÌ›”3$ý@EÆ)ÈÂ"%|ÌÝb–Å"Ù™™ŽÖföÚÛd®S’ôºªfÃSH¬ƒ~Z„d‡’_œ[OÛêCž»q~;™¦+wï§õ-]F¢=]ØœÁštçùWH¥KÆ)´%.{ö>Þb/æ‚®Vz¹­Ë9±Þ\Øì`µ¬Ñ9Ó¢ôfly÷p|Ÿ£ÅÍô‡¹¹D»cÒ=‘)+Ó)úèh6EËhoÕÃQ•LÔ/(¨kV±u²¶¶v-,I÷n¬Y³FŒ\=Ëæye’ï;ÓoÐãÊõoU,9_,÷±PVè£J˜f’Ba!\ÆhÈI’uºJOÔIôÂàóötožÈŽ÷?§š›Ð)œÐr-Û“<¿&¤Ñ£2=ÇÅq?=z§vÛ¬ÓñÓIäCÃDZ¥úõáazzX¨G}ŒÁšuA щ­:E,y¬{ªÏÇ9ܮЃ¥ž÷oå+oUèQ –NZJ3eÛ`9 éõòܹsçÀ::±Ò.X¢ }´<™bê ê¤æŠ`àxW7>AKÓ j:Ó ‘°´>,QË ö°€$%¹ÀPŠå­Š5Ïø;š ¥3êGFuªçðé ÛÑîL I.Ëû°·ö~¦†èièˆìÒ¨å ׯQÑL‰ý$o€<Áë"ÆÞó0¢ÑìP5¦Å µ mçs–©dnžc}ã› ¥3( »æVa–,gwS’VºuNb¯æh}>½¦þ9°¼UÑA$¨ø¨0¢y£^W4ÿÞ•ÈŸ'%ÞyEòï}7ïCˆÓ;"¬Œ—ÑÇ9=Åëml‰yÙÿV7?}ã»å­L ]ä*V™œ ž"‡U$ñ^´rŒW·ò8ø©Ã»f½:øiOŸšy~L·¯Ç¼•¯ÒK¼'Xé1íœ:ìÔ¢uRÓ4Ë™¹sçvÂÞÊhi*Eõzgƒ¶J`ƒŸºÞí+0üysüÔ[ßøäØÞ*°áÇtÛñzU?7—Ñ®M‡Óì†ÙŪäžyóæ½ Ë„` W¹~G Mìbж1õú„÷Az^?-iÐöõ÷’çXü)oeÆt´³xøbR$¥TN@°Ê g(g¤Ë¥Ã‰è} $ÏÑ“¨úüÔkÞ*cx’LŸù‰RÕ‚Á*qBdù…bß’FÒù8GC ÌûÐûRÞŠú`ÞÊ»çØ#Q-u£ÑÝ„±xÞJðáÁ¦Ñ±Ñ¥ê" ‚Uœh4*Zí(mVèã•õ>¨ŠÞ‡Ÿ!¬ú¡çè.ª•D¢TÞÊäÂQ–ªŠ­F],w¦N*^|y®Ø2c”t”4«ß{®y¥Jå­öËnóÖ‹y+ÁICN¢9ƒæ”Ê¥®0ê"€`•äÏ¥89ri& ¼UïyŽA¼«Yͼ•@$Ù¿pÔ¼äRŸ‚B°¼æ±~OÙ>+]"A3”Ó‘·ª‚çØ£w5«‘·Ò½å­ç~>]st©*¨jšöX"˳gÏ~—+qi/+z “Çë}èÈ[Ù÷³G}ŒU#oå´?Œ¯ïÉ»bþ4þüí°D–/ëîRË(¦G¯ãÿãÁyTż•—׊*ì9V£oüªå­ŠÔ•¥†n|+Eåhɺ'IÒݰ@–/ZZZ„Kþ~©å裏ί—¸ÆÊý/oEUÌ[¹œ“jôßòV7N¸‘ÆÆÇz©zÛ¹îý ÁòÅ¢E‹Ò|§»Ñ˲C éÌø—ødÊÈ[¹´¯0· }ŒU+o’B´dÂ’ÌKÎ^à:÷mQ÷`,ßlݺõ>žlð²ìÔÐ)tnüŠIuÈ[9t7oȯ¨úÉ[ù s+˜·j5Ðý1qØ^«Ü:®s¿€åtœ‚â¬^½ú ¾ë=áuùV}?ý©ó§´%õrÕ:‚óåµxìįÛ2½–Òan‘íùUÏy+½ÄñÙÏ´·-Ù¯?æzî¹®ñ6>:oÞ¼§au¬žŠÖR1¤Ÿß¼~™^Hü?z7õZvШ J=œVLTõrBÁ ŠùïÕË9É“DóçÑÅ£/¦ã÷UÇx¿~ÆbõX«Ç¼õÖ[уþƒg}wUÛ¤í¦·R«é½ôë´7ý{`¨SëàŠ®ú ýx-•9Ë~VÌ hLG¿ãú½².Sm¨Ž†E†eÚUÍj˜åéý@—¼Õꆆ†'L˜€µA°aÕªUãEy‰g‡ál€ÙËõjþ¬Y³¶áT”Iw,X°àMÓNãÙý8 (±âr*Ä ‚UæÏŸÿ*»ï"9± gô4ÓÀ¡æ‰sçÎÝ€SÁªsæÌÙÒÕÕµ€+›h¬ãŒŸˆ:sg<Ÿ=oÞ¼Í8þ@«¼ôÒKódY¾™gOù¥„JôÀÀõå¿ø¦‡Q!X½ÇªU«&*Šò)OçJ):ʊ㬦ƒË+\žäºñ°ðÎqJ X}í6*¯]»ö® ‡ñ|gå2(IR¹´ðuß˵ƒç5œ˜ü$^‹X¤Fd¨IEND®B`‚gtkterm-1.1.1/data/gtkterm_128x128.png000066400000000000000000000212331376216657300173210ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aËgAMA± üa cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ pHYsV‚V‚˜œ×1tIMEã ©ÀP>!IDATxÚíy$G}ï?™U}NϹ£=FÚK{ÙìîHhu $ø ¼Þ:lž æXíBr„Â/üâéÅC ü,ž"0ƒ.H qY„‘ŒFbµÚKçJ»«=´ÇÜGOwuUþÞYÕ]ÝÓ3;ÂÚ¨oDMwgeeÖü~¿üeæ7/H A‚ $H A‚ $H A‚ $H A‚ $H A‚ ü.@Íö ¬_¿¾iø®]»ê~¯[·Žr¹L&“A©é_]kˆ°sçκçE­õ´y­[·nRú"2)L)…Öšl6Ëã?~Òÿ©Ù;Í6ÜÙ~Þ l ¿ß ü"º±lÙ2ÚÛÛ1ÆÏç ‚  Ø\,²Àð,ð+`1¦ V †ä[€·Ç€þèf\q¾ïãºîrà"¥Ô¹ÀÂðÖ«ÀÓÀ¯.¼ðÂý?þ8—]vCCCÊüO`ðHø³-è8æ’¬þ,üþSBèííl ²Æ˜MJ©a  ¥I:Ç€ŸÿÐÞÞ¾mxx˜ÞÞÞ¸bÖØ®ŽGh‘‡Kú™®ënÞ¾[£¬|ÙûØcýpçÀÀÀá X¶lû÷ïâ€?c;sÌô>‰× ðÃËTAD‘yÀßb…xVù%à0°8>·øpßððð‡´ÖŽˆ°víÚx^‘*QÀÚµkãÕÃàn¬wXƒUþ0ðJx ‡a¿|¸G)u~:FDÝ¿ßð9§0—<À$ôööFЪ”ú<°[‚‡€ûöb ¡8øoؾ¸Å#­­­_ž6/Çq"C[ܦE˜þ7‡±®_a]úÛ¼Von ‚àÏ[[[w϶Ü^ æ´(¥Øµk½½½›c…ÿ"ð?€*¥¼°jˆ°]D¾§”úp=Ð |fttô¥Ô3Ȳø,5åÿø_À®†xÏk­fŒùpppžRê³á{ͶìfйTL‚1†ÞÞÞÕÀDZÆzøð=ÀŒ18Žƒçy8ŽƒRªO)õ7À-X·»ø¤R*3]ÏÁð^à]aÐOEäÀ®ÈÈÂô1Æàû>XÃø¶Íð‡À{f[n¯sڄج ¿ß~à 7úè¤ø½½½¸®K¥R9|8èþD)õ]ŸmÁÍsÚˆH[¿‚m|Ý7òÁ–ä°!×ü¶Á·xÓt@D–b•ðïZëÇŽ?Þ4þÎ;©TªmÈ_b»y½ÀòÙ–ÝL1§ hο?§”: ”"NOùÀž={ˆµ žÀ¶ØV„€Y´GÏcÊÙl–çŸ~ÊbFX¶…ßç‰È’ÙÜL1§ @)•ráÏA)ŠO>ùä´ÏÅ= Œ…ß;z{{ikRXq`bbâ¤ï3‚cØnhÛÿÿ­À\7Zÿ9'"©†VSœsÎ9Ñ×Lxí*N÷p«@MH0e2N†XŸ¿%|Ö¼Ù–ÝL1§ @DF±}o€³•Rg(¥X·nÝ´ÏÅêæÕØ®ÀbSƱ]Í7ø¾¯J¥R•‰l†‹/¾cŒ"K‰½óœÇœ6€‰‰‰1juëjà °üÀTHëÖ­‹H4° ëF'§ó"ò2ðrøó®ë®TJ1Ý3£££VˆZ¯ŠÞ-Lã¥Ù–ÝL1§ —ËüËÕ§±ÀÙýýýlܸ±···—ÞÞ^”RÑuµ>ù“Àöéòrçð/áÏÕÀ'µÖi°n>î z{{Y¿~}”OˬoÿK¥Ré›mÙÍsÚBjvðÝ0èà Àò®®.<Èúõ룾?"ÂÆ‘ÿ|ëþ‹ÀWDdpºÒ"òM ¢r7cþÈGïÏ+D^D®>þÞ |3•JͶèfŒ9mZk”Reàfì0/X·þ-¥ÔE¤ëâSXE½áø ð5,y$Àí"rÿÉò*—Ëh­÷ „éýoàN,Ѥ•Réðû[Ã{ŸÆ6€¿VJ½4“†ê\Áœf‹Å"‹-bxxx¯ˆ|Ëî½ ë nÃÖµ{±·3°#w‹ÃÇ+À]Àg•R%`ÚúÜuÝèþw±|Àß` ¤?Á2‰ÏÃ8K°.¿3|üpƒˆ|¶eöZ1— @QóH `ïÞ½cH§Ó¤Óéí"ògÀ_×]À«/_VJÝö$ð<˜kŽ(Áª|öÙg£zÝh­ï ‚àீK±Š~SxÅQƲ€ÿÇó­µìÞ½;ÞH”×\Â\2€li޾ðòË/³víZ<ÏÃuÝ—”Rž½ ;n¿Û@ÃÎ ø9ðCÏó^Ìd2ˆ™L†]»vŻǀƒXz¹:N޹ÌNuÛ·ÛõGŽ¡§§çÀŸcçÙ-ÅÎåû ßAM±‹+Ö†Àµ’_ý-ˆÄFÄ>+µ¤¡¢µB)Ö G;h§æ â¡Þ(jïò@°k ÿ|}Æ OG `Ï?ÿüSªŸSjO>ùdTZ2ÀG°³l—Ö2ס! ™'…ˆU`´KGtU*•ºßAÔ]ÆDʯUu‚¨–t«|­5Úqp´Æq\\×±Ÿ)—”ëâº.n*…ÞÓÚAk5#‘*ŽrPJÛÿ§~Éâàf¹C)U.¸à‚S¦£Sf¿øÅ/Èf³(¥Üpõ̧ WÙ(†€qý*úEFÕaÊŒYAHh®äA#TKy` AX²íg-¬Zï‡Ê6¦f0Di¹sUÍÓ %£@Y¥Úû[)]5´F+… ½J#aºö³öÿDá ‡]`qf9kòë83½W¥â†P>cŒù¿J© ŸÏ7îröºá”M - Ñr«?Ànê”·w£úÜŸrÔù5 P±JŠ)&R”¡öiQ‚q@t?Gj†W¶ •`âq?‰å»7ùÒñ§ˆßì½Òspét»¹ õR6Îû#–d–c͆<ðWZë"òã“íp6' \¢SJm¦¶‚†ãîS<Ÿ¾u0†ÑT‹ öS…‚Ї«P<*hôY­ÏãñÅÖËþ¶ù„áa©~KÓð((­ú|UG‰„nT•-V¹ Ac þIx_#b8îå}ßaÇèS|hÑǹ¨íÒHT]Àf¥Ô#étúä;Uü†8eý›°NíηÊSô;{Ø“þ#ê "*¼¤ZB«®3VjÃãñ 1÷»/ÔJ_cxõ¹Xi”ió§yþ‘§‰ÛIÕÛL¯¦YwÏ—ÅË/ñ¿ÀÓ£ÛÑ5µœôœ*RÑ´¢¬FØ›¾Ÿ¢:ˆ®nL ulPbQÈ4F! ÷‰ÚÍÃãé™&áf£4ÍžkÈÇ0YñÑÿ‘Bójù÷½‹AeýJ;Õªó·ÓŠÀˆB1è¼À ~ɺÜ)ØXÚš”*JS•¸šÐMƒ±œT¹Rÿn2Q4¦W÷?ÑÜX§òP Í3c»Ù=¶Ó60íGÅS© )Û×^{­µ“°`©rûí·7»}»cÆ’Q}?Ü:gÆœ¦ôš)J[­jhP|ƒ¡˜&Æb¦y7Óh0©Ä›)Â'½›47 &L‰}/sYçÛö1Å ¦×I?Í=Àµ×^[¥l•RŽRÊâr´Öø¾ÏÕW_]Ÿ°Öxž7ùRÿÇ ÙF8O9\ŸÎr¶ãØ4Exo`øªWâîJ©š¿#ÂU†k yÚ[3±é¾w¼Ì§O ò‹R˜¢ÚŠq ‚t7gçV"Èv z|Û;>•üN¹x÷ÉôƒÝ>pË–-ÜvÛmu7몀HùáîW›±;cœ ïTJ}ôèÑ£cªuS ûDÌaíÈ—{ª4ìt 'ƒP0°1Ð,jËÀü,´WKW–nŠÕFU]ì¥yO6CK{º²0/ ]–´gy>K»RÕjdc.Ã[Ú²8-)èHCg§5Í[;[xo!ëÊ;”âÚ–ð "\~ùåˆH£ë5Lx3ðì–k 3Šïˆy%°y``aóæÍ´µµ‘Ífñ@Ÿ¥Šr`6R €g8ø^õƒX<Ëö³P,óm¹ÃñbŦ5T†ô—­!ŒV8^ô6v@êˆ0æ…éN„ùUìo/à@¹B%Ì¿„#™Ø¸Ceõ è3:ásÐÂ<5çaÄp ˜gº)WÊåryw&“aÁ‚lݺ¥—_~9Ø-é¦ÒÏ­ÀWŒ1 ÃŽÄõ#"›¿õ­o!"|ä#©@{{;®ëòÈ#\L½ëàË"òmÀ¯T*cPJùAÜüc,¸®««ë­5…B¡¡!<Ï£R©<çû~Ÿ”S¤FV]Ù$„ˆ…C~]®À}%86ÇK0PæàX™í¾_â¶Àç•1ÏÆ(CÉÁ°Ç/ÇJì”À8ÂO*JÃå0^w ÄÄP™Š%ÆEP{+>?¯Ïÿ„M÷…Á +U=Ø¿U<žŸð`Ü·ùöÕòÿÑX‘gÛ¨~“.¡ÀR–‘ 2ø¾ßçûþsžçqäÈ|ßÇÓL?ÿèyÞ·•R~¡P X,¢µŽôóejeÊ®»æšk.ŽŽº«€çy„‡25º–AàhâÃ]wÝÅwÜAT—`7IŠïŠUóŠÅ"—^zi44‚—Léá…¸S&‘Q”àóh±Ì؉æxïøÏ —øzÅãpØ·R‡Äpg¥Ä3£%¼2¦¿Äè@‰G‹ü?¯ÌD4Æ&ð3p‡_æÈp‰ ¿„?Pâðp‰¯LyÈTªEs¾2:Î?Ÿeøxs¼HéX‘íÇǸ©oˆ—üŠ%kEØëûÜ88̶þ1Jý%L_‰Á¾ ¾98ÊÍ¥qŠRë^6c à’b©Y‚ x)‚£¾ïó–·¼%’u¤ŸÅ1y÷?Š¶Ï¿å–[¸çž{âúùQ“ªà ;<ñ¤Î’–bwÝŠc‚pÇ®žžÚ˜Äm·ÝÕó£J©Fªò|ìY~ý„Ê}÷»ß=rß}÷íy«;Ú.·àg‡§åÙ¡OÁ=iÃÃZèòa\ÃGRõŒ ÀNeØ/K}ENà¸2ìC(…#…Qü2Â÷ÒÂc:`‰¯0ûá ²ÄM5àUcøüÄ8÷Mh á9ãsB¢4kÅë?<çúX㸴‡ü€gŸñ°¡ØXÍÕ“I†VÓE:Ó6Ù}ÕUW|ÿûß˵™~Š„û*Ýzë­ÕÀžžŽ9B¨»Æ‘Ä áá}u "»”Rwÿ=¹=ÌxïÁƒÙ²eK´;Wt1µ­Ó"Ü-"uÛ`Ý{ï½h­w(MàNw¤›rvpÊA¡ˆ A„²‚½®Â8R­ˆ—©UCýNm|©)?ˆ{„WاMuÒ 1Æ0þü°Cüj8!Óh™¿/pB Gƒr•ÂV*F*ME=ÒC»êEì¸÷Þ{«n:Ä.ìQvqýt…¥úù-[¶TÏO:tèPÔíŒ÷ˆÈÎÈ«W{J© ð÷Àc±Èì¾–¨‹kE¶„÷âTÕcÀ߇i°iÓ¦hÝn­õ¨K†ôÈBÄèI}áÉT0UGÂl?Ý1Bg]¢p"e@5ž (@Ȱ "´™Z5ƒØñy¦)·£",ô„œ ¦š·¥xÁ†;° ,,ð×X> ¨M76®_Cµ}”h–šåäœZëÑPVlÚ´)®¸)õ£”jÚÑ´¡¼§ÒÏãúqÁºô°ox{ ÚÝÔ&q\ƒ=í‹ØCÎÄ6FâƒØÃ“¦Ói¢î ØmX•R¯Ap0•JuäÆzP•4[j2z7Íp¨Õ£W…eíYhOó² øa±ÄsÕù~Ö;¸F¸bÄð%èΦ(¶¥øUFø~¹Ìq?¨æÝžð¾¾€‹K˹ku¹?/ü8¨PSçqÎ- Þ($ë°§àpWÚg»©LRn3æ/β’g¹ZŽ›rqçÇq4R·áYHMõ#"“ô#"ÍôsS¨ã*#ØŒHx¸#æj2À'±ŒÒžÐu¬Ã§ŸSx'¶Qˆçyu”£Öšt:}"‚çÓéÔú|ù RTZ L7<\oªÁ Ÿ8ä±èŒ<´[ÆmqÑgå°Ï-A™gÒ¡Û0°qØðá¢&2~´gXSp9«XâæÃƒ ú´ùÂõCð•†ihK±¬5Mo‹Cëè8÷œ¶Ao¬(þ®œby›yò)Vç]zÓp]ÿ OŒMØ9±ÁºÞŽL6ð3d>‹R=¤Ò)R©Ô ù|¾/^€bt:ý¼‹ÚNçSéçÁFeëx&¡ëðCWóËX<…Ý}û¿†×ʆÄ‘/n»ÚÈ7ŒWÒéôÓ™l†¼ÓNn¼§8Éð0BÊ®<\f‘Ö–í›—¶(8s°±ß'ØÆ\O ¼W¥È.ÌÙ-öêÉCG†ËÛó\œË„JÞ,o›W€•í°²Í~®h#·´?={‹³)|±$ÑŸæó,_Ú«ÚaU¬n‡Um¬XÓŇWv“Ѫ6c¨îÿiÎy°L/§+ÓE&“!N?=66Vi$lb2õ•RÍô³r:ý„:õ•Rõ…³AI  ”:„u烜ƒÀç´Ö‡"ž ›6m¢­­L&³#—Ë•óÙÚKËÀ81ÅO2±ð@ à–—ŲrmiKÓººJÖ¬ì÷hõ >ÂåpFwÎ*½§å-£ç8£Ö 6ÔÖwäpV´ÁŠ6XÑ‹ 6ýÀ°°dXá8ø"t8šu‹#凯²´`Ç ò.½…,®3í¼€ÆªÁ—ßOý-¹r¹\9›Íî( õ¿Õrxbš1&ÒÏ'Ç ð9¥ÔÁ‰‰‰øq:“ àî»ï¦¥¥%RbäjdšÄ¸Óóã¨ñÈf³är¹½¹\îX¾%OKIUÚBaÌ`bEô"9ZRÖýj,;7jY:)ú5a§µå𻳡2Å’?Ç',©3êÕ΋¦Ã#ýcüÔS\é)[¢C(+|£ ö+;E³¾¾¯ŸsZ<Î.IMùEŸ½ÏŸ Wª Åêz8›BØíz çÐÝÖM&—ÁuÝ©Tj¼ÑMOeØéb3ÒÏT§¦ž¶ÕÁ±eb›[Å Uvó 7Sb GÌ[ÌñÅÑb‹Uh6¦Ò¬  ”ya¤Äý-ðL«SW¸(.wS¼ËÓ,­0>Vá?tÀwÚÇRVÑ´³nk&4— ´ŒT8l¾×¥ù×.‡’ª½‹á\qøÐ¸¢wÄ@ÉçiG¸£žÈMî¾ÆI ÆiimN7¯º™ @c°³{îÐZŸ–…¡p·‹õk÷CZ«®ùéetú‹9ì‰5§ VªžË¥ &/ŒäÊ0iêUY ?*—ù™@KV˜ÈÃZتNËB„c_Êø|í !Ý©q4£º GlÇggÚR‚aÀ ¦Wþ4ž ³[ÎfUû*”VÑ  =ÓU¯7NÛ1&±U®û€#‚U­,V½1*¸ÉTíJÈÊU€~„~ÓÙTðÖÅŽ:0äÄÖÆëäðÅ 0è(^M+ÆœØrpê K ”•pÔ…£)EYÕV MKhÅŒu\D»Û… esÊWÏŠ@u²é¡¥ƒb™>Ÿ<]v!g“Ò6Ý¢Œê¸@Ò¨QðñqFEÅgçDí‚I¥yRþ4äß|<£ÙJ!€ît7—u]¯›÷(¥¦;áü·ÞÂ>¬‡=ÕÁЭ—²B_4‰0i6o¿±5=ž½Y¢Ù|¼Fãj¶˜¤q±çts§â¬qÁó®`e~%Fªî~›1Æ›îdôßz§œvû£wQá %§"¥ê”¯:ˆ4 µ·šü)bÊJÓØÍoÊ”©Û?Zir:GÁ- •Ž»}€{•R×‰È c ^xái~=fåÜÀÎÎN†††ÀR͟žü!àL ÷ÉÉ©9Uø sx=1ó2Ò,fd ÖûT•;ÿ‹À ¡³³sFyÌÞ÷:cÛ¶mÑG‚ pÇY‡=‘{ v“fú‘®ß&(l 1<ü Ûè3"‚Rê´’?/6«xâ‰'ì‹„“M~øa®¸â WDfýÝ^O(¥ä¡‡òßþö·× ÌÌ–â«ï5Û‚‰àû>ŽãðÔSO-ù]B|÷Ï ˆÖí'H A‚ $H A‚ $H A‚ $H A‚ $H A‚ $H A‚ $H A‚¯ÿœÏøà2óz®XtEXtCopyrightCC0 Public Domain Dedication http://creativecommons.org/publicdomain/zero/1.0/Æã½ù%tEXtdate:create2019-07-19T21:20:12+00:00ûPæ‡%tEXtdate:modify2019-07-19T21:06:58+00:00ÿEÆ tEXtSoftwarewww.inkscape.org›î<IEND®B`‚gtkterm-1.1.1/data/gtkterm_256x256.png000066400000000000000000000664451376216657300173430ustar00rootroot00000000000000‰PNG  IHDR\r¨f@zTXtRaw profile type exifxÚí›iŽ\7w†ÿsYçC.‡#dùy^VK²lÙÁgA¤e©º«oÝKžáHÚÿø÷ëþ/‹>»\¬Õ^«ç+÷Üãà›æ?_Ÿ×àóû÷ÛWøú÷§÷Ý÷o#¯‰×ôùE=_Ÿ¼_~|Àò×ûóç÷­Ï7±}ÝèÛ“¿n˜ôäÈ7ûk_7Jñó~øúÙõøùfÔßLçëoq~}è}ýág#»p¿]<)$ÿþŸ‹£H= ^ù9ê}ŸR~ï—?ÆÏýUÿ,~~}½Ÿ~„ãs£oÓª¿‹Ó×û¡ü:~/J¿QˆßŸÑ Óÿöë7ñ»w·{Ïgv#WG¸êפ¾Må}Ç…Ü$§÷±Êãoá{{:š~‘µÍT§ó“zˆDü†vá†ó^WX 1Ç)ÝãŠé½×’Å×KJÖŸp£9ò³S#7‹Ì)+ñûXÂ{n×óxXãÉ;pe ÜŒÿüÇýþ¿ûç§Ý«2Á·ï±b\QõÅ0”9ýËU$$ܯ˜–ßà>/þ÷_Jl"ƒå…¹1Ááç糄µ•^ž“/ŽK³ÿôK°ýuuÏb0!‘_C*¡o1Zı‘ŸÁÈcÊq’P\‰›QÆœR%9-êÙ|ÆÂ»6–øyx!%UZ¥©HVÎ%Wú­QBÕTr)¥+­ô2jª¹–Z«UáÔ°dÙŠU3kÖm´Ôr+­6k­õ6zì +®×n½õÞÇà¡#î5¸~ðÆŒ3Í<ˬÓf›}ŽEù¬¼ÊªËV[}wÚ@€ÛuÛn»ïq¡”N>åÔc§~Æ¥Önºù–[¯Ývûß³ö•ÕŸ³öûÌýuÖÂWÖâK”®³Yãm³o·‚“¢œ‘±˜7e€‚ŽÊ™o!ç¨Ì)g¾ÇäR*‘Q%geŒ æb¹á{î~dîOóæˆî¿š·ø«Ì9¥î¿#sN©ûMæþ˜·_dm·é%H]HLAÈDûqÁi#¶!^ú[¯îï~ðÿØæ5§°W>7¬1B·zÎÍÇÒ™·íL÷X©î“/éžFQ¤ÕÓé™雲êÀNÌk·\â—ÌîåÓeRÚ=…8î¹íÜ´jö%q×i¤ 6ïjäd0”÷'-»«Žž/<µA¢P÷ò–nâ¹{î4¨nQ¹E¤Ê¨á8  O»rf­ÔÖØÇfj…}YÇè°˜à$«Ì{•™ “î\cýøÇ¡nûŽë@3Ñ]î­3í7*Êm'õxì%”ící¥¼÷Þ¥¿«2½šç,1Bëžã¹Û†JŇ½NŸq ”çlþÌi#œÝoù];iQæh6i©Ðj)}ùȼ“ËÐÏe›têöü¦Çl?¼¾HmbaŸxž/Ç¿zuö‹Ÿ^PQ5©v× í8Õ®úþ‚{íºÜì¤HÈŒ1l¤èóžÆÞ3;-HTI%Uuãqö{…kÖÔT“Z½Üä·´’—•T9u4:ž`ï·hº7Ààôm—dŒd -M>Þ~'Mwƒüª5ÚD~æÕuŸ±;ú¢ÙáªÉã"eŽ*ÉJºçJÓõ›cšáh椮 ‚J#² <"eȽ‘hEFyë­M~Ü“iæ;).w7uM^Î-–2uÎès¹¯^Ý…\aÓ‡"NtÊ=9ïxà™¨GÂu§ªŒ =lv#JVÕO$Ý׈Uý’ØÈÚA°)j”žÿ¤ÅÕ~‘'Û,9ÔjÑö”dœF-#Ò©ò<Œ¦YšáÖî"¬y‰"Ò}çz"ÍÚ»DÚ%Bq/;vO(å 0:¡DšÊ¦–›‘¿¶Ü¯ÓPäPˆ‡HfÚ%§Më\Å`Óøuln-8 ÉcP!Z Œ;¾«Nv¤aë[MU†£‘ô2wþüše4—{XšeXŠì1.cÄ`öý’ì? ý6Âp59ÒéTŸÛ™ ­‹’h ;|Šâ–µ^qø{j„‹bGDÜýÚ’àShIÝ‹?#S‡´B»©,>J­0uÙvl cÓÉ !íø7˜§¤ãW¥€ø@‘†uyøw´.¡õw¶Q/eÊê6ò–iÐ]¸ðZ<êÙgG9MBH«Í6. Pe „¥+}éŽ ©WÝ-¹PawútÈ+7*/·´ ýQ »}ð"¨¯0B©Z!Ø-?q)¸•(ŸF¼9ã\FÙ‰àÉ–­d~3üµ±Z{{ 6® ï¾ w±-Ô­–è1µxcô Ô!ht°‘‹âyUF(ãDN…YÊ{ó`‚awËÀ‹‹$Q¡û±‘@ÜPG7C«“`‚`´ÃŒsUI#'Uœ°°`ܳî€9FÞø-³Û —× Þ£$.W¯äÙèÞ=œ™Ð€fƒôßٶ€˜“¼òÁ Ü’ï sKÅ óYÃ04FMHöËQÌH i@ÙŒ!ˆL &ìg!/+D` Ø| D‹HEÀA ŸÙ$´H j$"É|-BDü§ÏAÆcŒ‚Ç<ôSÊ¥ Æ9Güe3ƒw%8Zã}ó÷^‘ Ð÷¶ÝF|ä5ú*ädÆ Î%˜Ö–e0 œ­ŸO¦Ž F}”²‰}à a]+—CJ4Ø2©k¡1ÚšøwJ¤ËøZás«Ü -”#¥tMîµ dMÈ y‰Ü¯·ZDßë)F‡Ä\úôäR6ï(ŠÒ# BèÓÁÖ7ÿôõôF¥">[!d¶´XH­5¢Õ´ˆ,°<–ÃÒyR¶›D˜DÀÅPøFʘe”ÌÆ-’•2ÇSg<“Åïzô¨âJ*7 çé£>Ôéá¢{…Ú¼“çÀ …ßf$–1h’;ºx7Ðtˆã¶½§ð&þ`HËé …¡Ȃ⤃À’r­ø× EK#'˜ Ù}!—]ª0ŒÞ_ç ŸÕ×É 1\û9·!´.ÓlE7Û’k ŽÚûó„w5g{Ïþd\¨‘â×2W˜n{?¿lѬ6§|KÈ)¼ð¸8K7J…>½R+.Çʰ˜úþxúÂczÃj#ÔQ§ß~S6^•˜¢Éj†£qT™o $Nú zžÏ³‚m£› ‰‹W÷MÔ¡'@ë_ÁíÃ(”ß>oÞ%Å(¢¨`Öò.Åþ·v9ŸTà§.·R¡4ÿÆ]ÿ~@7ê!qe×z@:{šŸ[Ë Än¸íoÒSÎ{ÊÖ}|ƒBå÷y§¤ãQÖ[ôûÆ¿æƒvq˜ËMÑ Š‘™7 IØ%“²6Þ8ËÑÔFyO¼µÚ$ÉoýT î¿®2ªäƒÄçÃ1ÄŠÖŠwÓ1 =nL)ü¨fæÓ`I|j†'™íüÌéy¢ÞŸ7ŠrŸ¸2%LH(îÍYa}E‚ªí i9”5-&ÜÀÅÐûZ‘F~‰¹ υ䥓Ð;i9Zw·uT^FÇ”/œÕ N†«¥3(!Yòñd!¤ ñMM¢½*úwêÇ=Rï D|´ÕÖÈ\²@J¯C¹ 87côdAÁé°Åùd(twÍ#Å R’¿Ô²AZ”)Ä“€|-Ѓ '.…”*³hÌ[žW”kÅçw?¸¤:íPJ¥2ª´´¼@,¦Ö¯Ú< +| Ù¤Õzð”š=>o¢b~Ìx aÂ&|†rú¥vG­älļ ˨Òé<™hžBôT£·¡#°©v¹¿„€ò½vÍȨüd ´ P¨Œµ¬¡â‚·…¹P€€fyµx<ò5x±q\p!7=DmR#Ô0™§/ÐÝ(‰B‡„·²_¤¹/½Wms„2 û· =áa+† "'qèl\z9%šê ÜÐ TmFo&CŠÛL@ñn8qTµÉp¥š°\;ñÎ,çz Ï‘b´‰¾ ËÄÔ ÆRNÙ „0K§õNÑÄKËtÌOÀ„—IAŸ…]'¢üÑCsM­C£¨©@4PH0Pä:\îr ÞPC±˜À—0fwP±ÓAœsR§ÕÁ€ñ&ivd•³V7®³ ÃÓ¨ÓûhðQ‹(Dá8ìÙFÄŠ†Åî–ËmQXu‹Ñè!˜Ûj¥©³ÝÈ.íÑ}6α„¥ ™‹ò2ØÑ4 [¤fÀºmH{¢:ÁG<œ–±¦Væ.²à•bgn¦„‹cÔ{ËÛ—JÍBô ùI˜bÕcô³Ë¦0^FúS—]\|ƴЪRp `H?SÄ „ SFѹÐÐZZ2øO^Î:=rð³eçÐôç vtRDe|:7þp.ˆ¡ÜÚ%È'u•ˆ¡¤Ñ"Dœ{W¯ƒs¿¥ÁÝÉPÞZƒFÿ£EôÐæµ rûN„¿°Xc?Áø¢UðC¹ êQÆ0wUy”Ý2e¾ ÄAdȯFa¦r ê¾’‚È7Kë‘Îhƒ»•Ð2dVFŽ%‘n 8–?(õ<]ŠÌªx¡Š<¦ñ:ÉÊÙ-µÏ-ÚñÒrN±®m™M&pÈZ5°™À“*¶䊧ñ,(ç×gš^6jù>è5©õdÈC—ÇÐ Œ$tÂ*ÀuR@[y\Ü"ÎÑf¡txàÒR˜…µ-ÔiBŸM:×#-2è×§Óf‚)y- *˜âP2¿ Sj·¤ê4“9AtÁäêN­$ƒmZ宋28Ù$lIÊ®–Us$²ãkq[ Ô1 Î3´å)s³*ØâP!Ô×ÁN#ûœV^Z*=è=MRä6ÅHÊ&Q?]Ÿë*-…@¿KHo—F¯¯*T÷Ú²ˆ¯¤ÑPE戬˜áƒ¨YÏE¾€Ï´×š®†Ý"r¨.ӚDZ¨=ZIDx”*LÔJq÷…X(äR‚TìA¦$ uêÝû¦ü–Þ&a¸+dªMp¹mJhí·:1ÃJYpU¸KR)þõÖïi·´†z´G€$8­MF7Sp|Gàa>ˆk¤7éŠ>x"V«|CaÒÆY—4t ßRɶøŠP†CØMêݧùksŸ§5à‘2CºÓ£ìÕ¶L½Ø$¤B¡ zo… `ßrи|~ª? ”±SIÕ€þtS‹lñ|—šg¸X›ïZ‚‡ÅØïÚ>™‡®Ô2ž¡’Tù1Ì6] MFô+Œ °‡Ûµp6!èumî=&9%+ƒÛƒ;ˆI\HdÆ{hY¥zǰ²Q…W³ÒXY 4±U-éÌ mž¡:4im $ú†î)l&æÎŒ`CpyN%ª¿\ÉöÒVjMZE€ã´ ݦ«%· zÞbT!<£ ÷&'»—6 yL¿oy %×wJ„¨kûâñ^͇&#kdáȬP*I­ ¸Psð9&9òJHÒ`o;Vv#‹e!#0]Û4Ÿ…š!èÕ_¢/jœ˜' šo!‹À $-‚öÊâéÕ’‡']Âä!ÏJ½í­Ýd, ~íuüÄ<8Ž=îfü^†µ¨ˆðÊAZ‚gÈVh Bøíö„4*ñGwÜUA¬“1ÛÄM? †1âÚÛÊ,™ TUƒtÈ–·éyJ ¹áò«ŽÆëÒ¶‹|€'Ú¬>r•Ap`ÚÒµCb‘ô·¬I0/×v35²"’qî«-DÀ‚þ}IY MkAò¥ZäYÕ„œw[›—7uŠ®¨/\!8dêŽU-§†ÿˆd'*VÔR”8NñqÁbw‘´3ãXÇÛ‚ èíhÍ!â û•]B‡PÔM털JSÀ|ÐRørÌÜšBKo¢¶Žá´䟳§Aß‚œö¯ÇS² –t¶ám”cx :ŒsF“3ƒÇ¤b@˜Ž®ÐÑ9ŒvršúþJ R%„r©¤¡|`T.6t„ §á·4 $Èã#¸ÐÞèÜ®Rm<oNO¡**2’_ÐÛ\)w$vÍ™‰†<ÉZµ Ï´’ó| ºLÊE:âŽÌ öÔN«Œñqb¤&%«Vm/P#SZñ›àyVŸCòàݘòbÜ*’®,šQ»‹€› ŸÑA+ ^Æoïj`ž˜Ì:¯VBç˜å-h¢<`V-QÄH‘^YÃáéºqÌ=õ ÏÖ­Ýs.†šÚƒ{¸ß@öû³A.¨kX þØp)€I6<Í‘´à!‰2hIŠM;[^î´ôHsµÑu!uµ— ¥2…¶!ƒ+ªFb‚ßâiÞ‹ÌVnhG©&Ö'.ÃC«&œ¼‹CðTS;P‰ø7‹Ñ@bí_£´`Q%hHÖ–‡ ]–0¸¥=ŒL‰z­½V¸ÝsV¬A +ŪC4æKËoFž©&^ìÎFÜåË  1¼ÀPñkü°iXê¨ )ŸEçójne” ¯ãj<öé¨mj­vvz0è·Žk¡óoÔ‰ª"‚8u!·¦-M¯½¹¢Íu.§Ü¿p~Bǧüµ‘Hd:„J°×ä(HpFyDÑá³^9Þ)›’Âvâ=:P€ÖF’á(IþÏ‘ƒ’šŽQ)aBßß9¼IRåÄ(míd܃1”¬–ŽÇgïxe¨yi¿ ©³]Z~Oêwü6è(¿hö[{ëÌP! ƈRù(€)X |BÆî®¶§QòÌ‚Ú÷õ³ ]ê—ªÿœxh˜¿ôÜßèÇp{Ãñßô†£-à7 _ çk0úÿJ¾‡Ñ|vŽÐg8ŸÁ|ÊŸGç÷Ï£ó ŽûçÑùÇa`ï€ü1:K'+®öºñ: ¡J§Çó¶*ºŽÞè4–ikÌz´È’SÃQBCG Ü·ÓP2ýï'öÿÿÃÀÿú¡û7–Èý'í'ÿŽˆŽn©„iCCPICC profilexœ}‘=HÃ@Å_[¥"•fqˆP,ˆqÔ*¡B¨Zu0¹ô š’GÁµààÇbÕÁÅYWWAüqquRt‘ÿ—ZÄxpÜw÷wï€`£Ê4«kÐtṲ̂’b.¿"†_†€(†‘™eÌJR¾ãë¾ÞÅy–ÿ¹?GŸZ°‰g˜aÚÄëÄS›¶ÁyŸX`eY%>'3é‚Ä\W<~ã\r9È33›™#ˆÅR+ÌʦFœ Ž©šNùÁœÇ*ç-ÎZµÆZ÷ä/Œôå%®ÓB X„ j¨  qZuR,dh?éãtý¹rUÀÈ1 h]?øüîÖ*NNxI‘$Ðýâ8#@xhÖçûØqš'@è¸ÒÛþ0ýIz½­ÅŽ€è6pqÝÖ”=àrx2dSv¥Í`±¼ŸÑ7åþ[ wÕë­µÓ K]¥o€ƒC`´DÙk>ïîéìíß3­þ~¤Ér»ËÈbKGDÿÿÿ ½§“ pHYsV‚V‚˜œ×1tIMEã"tÒ{| IDATxÚìyœeÿßOÝ=“É5 9€Âa®éI çªqa]ÅeWW@ÎL@XT×Õý­ë®çº .Š8“EÀs×[7(! $™ž$r  ¹Èdfº»êùþþ¨ªîêêêc& ­ÏëUÓ=ÕÕUõT?ßóù>Ÿ$H A‚ $H A‚ $H A‚ $H A‚ $H A‚ $H A‚ $H A‚ $H A‚ $H A‚ $H A‚ $H A‚ $H A‚ $H A‚ $H A‚ $H A‚ $H A‚ $H A‚ $H A‚ $H A‚ $H A‚ $Hð§‡ŽŽŽƒzþcŽ9æUoÓ¬Y³^³öÖÂÌ™3êù³ÙlÒ™›€JAlç™LÄße*¥¶›{{{‡}¾3fðÌ3Ï”þŸ8q¢1uêÔÉÀx`4lÀŠÀ>¥Ôn­õ¶¾¾¾Áà{óæÍcÆ #Ul”R ýk0s¹Ü/÷GYöõõ…ŸÛx¥ÔD´–ßÇ À ð ðr.—Û>ω'žÈ£>:’ß),ZB¿J©ßõöö¾ôäDŒTÜüYŃRê›ÀE½½½ºÙód2†††JÿÏ;÷HÃ0þÌï´Yà8àp_à%à÷ÀF¥Ô£ZëûúúÖ‡ÎÃÆ‡+¬oSJý(º?—Ë »„¯ŸÍf[€ÓSyÀLàH`\äk»€ÍÀ¥ÔªT*õÀÚµkæÏŸÏúõë‡û;M~½–Rêï{{{¿œô䯰’G‹þ˜}Ã=I ü³fÍ:̲¬(¥Îf£(å)þvŠˆ\®”z<›Í>,"_êëë[3\á÷ᨇ³qãF&OžlLš4éBà_™Mmðµqþ68_D¶æóù Ùlö®\.wÇúõëG¢ØØQÈ']¸9É#8ð8ꨣÂVê½¶m¯VJ}XØ@øká ÀEJ©_tvvÞtÆgX¯Eœ;wîÜ M³'Mšt/Ð ¼µ áÃà, '›ÍÞ×ÑÑqìÆéììL:P¢^¿˜>}:Ï=÷·wGæ8ýxùàK/½´±³³sF.—cöìÙ¯J»fÍšÅÆÉf³ïÖo2àÔàÍJ©Ç:;;/íííåØceÒ¤IIgJÀë&LàÙgŸ%›ÍŽÏf³ˆÈû|-ï»°/Ûý×] ¥ÔDdÓ¼yóNÙ¼y3pð²êsæÌñ:Ša˜×wGrQ¸~µÓoÓvÿ}¿ÿY-˜"²"›Í~~ÆŒjÛ¶mI&?ɼ¾Üþ;vÍf¾œRçð§ð|«€õÀl¥Ô$­õ¥Ôi~l=¯†¢Îh­ïÍf³ïÊår¿|ì±Ç8âˆ#xá…¨ðoÚ´‰Y³f™†aü›Rêë¾جUJ­žq]w‡aJDÚ•RÇ(¥N‘…~`BóܰuëVwæÌ™ŸÈårÅݦ‰8ðѲX·nsæÌÜ\Gø_¾ |7—Ë­­qÌcÀý@w6›¦”z§ˆ\œsì( gîܹïÞ¸qãÇ~ø–£Ž:ŠM›6`ÛöuÀGkª»Eä®T*õ¿>úè@ …·øÎ¼yóZEä/ü6½oø3âà¨ëmÛÞ2sæÌîÇ{L'=, i8ŽCgg§mšæÕÀy5û%p~&“ù‡@økè®o.—ÛÒÛÛû%ù;ùL­´ƒaŸÉf³SÖ¬YsÀÚ4yòäà^Îö…?n¸p«ˆü-ÐÕ××÷?>úèÀñÇÏÞð†šíÚ°aÃ@ooïÿ¸®{p)Þg)¥ÔçR©Ô‰ozÓ›’–(€C'žx"J©™À¿Ô8äÛÀßår¹UkÖ¬‘c=€ßýîw±çr9¦L™@__ßÓ"ò àýÀ¾˜¯ü¹Rê½V-á.Ö¬YCggçà =î6Eäm}}}wçr¹ÝÁÁO<Áã?^·]›6mÚ›ËåîRJ‹WóÅà«¿ùÍoÔi§–t²Dº(‹Jk}Õ™~~3jÔ¨ r¹ÜÎ@8ŸzꩦλuëVÆÇÆ\.w+ðybƹµÖŸRJM®%|à i²Ù¬!"çsÈï¥}}}^ÌHj:::èíí}D)õ6âk/tvv.yðÁ“N–(€C3fÌÞ.ÎŒ9d‹išç­ZµJg³YF*œ»wï.Áçr¹ÃËÄGç×uÿ>¬ý i”Rc€ëc>ÞüK.—{hÁ‚5½˜fÐ××Ggg'½½½‹•ó–4¨ÈçÎ:묤Ÿ& àÐC{{É3þtC._¿~ýÎÎÎÎ ÷w$ظqciHÎqœ%q±³RêƒóæÍk ×çJ©Sñ²õQü4—ËÝ~Ùe—ñÈ#ì÷uz{{Éf³*—Ëý¸5æñ/¼ðÂ¥'œpBÒépèà‘GaÞ¼ySj¸É?Êår÷¶··3’ DqØ´ilÞ¼yˆ’K»®{þþ\#P2Zë¿ùx@)u=À}÷ÝwÀžc.—ßÚ¯"ªŒºÖ­[—tºDZp]÷1±?Zëÿpä‘GÐëÖÝ0Œ;EäÙa¹ H4ŽDÉ̘1ÃΉ9÷í½½½[fΜÉÓO?}@Û5gΔR/ÕðŽŸ7oÞ‘IoKÀ!¥Ô_Ä9†aü~æÌ™Ìú‡1kÖ,6lØPîŒùøMÐ|¢1£G~c¶Þ000pÀÛ´iÓ&r¹œ ü$γ‘7&½-Q‡"²1‚ò¥ÔÐc=vP.$Þ ÃøYÌÇ©9sæì눈œ³{·ëº›;;;Ù²eËA{˜"² ˆ&1l™tµDR˜={vУʠ™¦Y<¨Z'›EkýLÜg¦iîW1€R*®BiƒRê x4ì¢í²Däè¤Ç% àPÃØ¸g("/®[·î –°ær9 Ãpm1ßO+Wøóü«Ò! cˆêD RJKº[¢)˜¦i_"뼊·áÄXðÔ~*€¸Ù~…W£1""5žŸô¸DR°,ko2L­ûÚGq"¢j\k¿²tJ©}1ûÚ”:ø r†a˜xQ &=.Q‡Ö¯_¿“˜9î"2}öìÙæÁ¼ö /¼€išiª¹÷ÐZoÝÏÓ¿Ó¦ã^gªµnÅc ªØ$HÀk‡PUÚÖ+v‚mÛ©ƒÍj£µ^çE»®»i?Ýð¸²Å_ 7|±hEàñ¤×% àA¨*mMŒ©”jݶmÛA¹vÀ›'"qS_Þ¼yóŽý VÅíO§Óg‚Çà{0àÏa˜L‹Q½I¯KÀ!‰+\9\k½ÊDš½½½ÌŸ?ÿ0àob>þ1Ô_ ¤r¹Ü&<¯¨bø°úð6ÍŸ?×u-à’¸œF:¾?ém‰8äÐÚÚú3<:¬(þcöìÙö)¼†®ë~šn>¥Ô `ijô¦M+߸*ÃÅgÃe$>ùä“Y¿~=¶m/þ6æß¬]»vpñâÅI‡KÀ¡ƒl6ËêÕ«]à1mYÖG}×ö€¤ÏçÎ˺uë˜;wîà}1‡<988øÐþ\#Tå×S#<ø¼ï%0 ï‡~8ð¦¾ÛI ã& Ä¶œ Q‡‚)¾ù|þ_kòOgõõõÉþÎÑŸ9s&7ndÖ¬Yc ÃøF ëÿ‰'žxB?üðýn›Rê¥Ô=qz(›ÍÞ„"û»Öá)§œ(Ó[€¸¤æƒ6lx8à$ `¿qÌ1ÇðøãïÀcê‰"¥”úZ6›½¿sô{ì1æÌ™“±mûëÀœ˜\Äz×u`íéèè`ãÆÀMx|ÿQd€µÖ_ìèè8 ÊC£§žzjÕÁÑH 0;;;O‘¯ŠÈq¥Ë«EäS‚á(A¢ÞC4 î½÷^Dä'"òYâkÙ§ˆÈg•R÷d³Ùììì<.,4‚e²³ÙìØl6û^×uï–Y­8„_º®û©Í›7礥 „.—Ë= ü=1Â>º”Rwe³Ùîl6ûF€‡ªÎCk ttt¼9›Í~UD¾ \\Ãò? |°¯¯ï¥¤w\$ ƒh­™;w.}}}î\ð¹ÞÞÞ‰Àu5_dEäï³Ùì À£À“À`ˆÈ4¥Ô|àx¼Y}£ë\úQ¥Ô…›7oÞqúé§óÀÐvÍž=›Í›7“ËåîÏf³çã­m×gŽ–Íf_Æ+ÚÙìÀ›É×."Y ˜ˆG3^kdd—ˆ\Ù××÷@[[ýýýI'KÀ¡À­¿ë®»¸>›Í¾BíuR~n`*‘Ì·?ᦙaÃ_3æ­<ð@¡–ÕÝ_lÞ¼™Ñ£G³wï^r¹ÜÊl6{"ð@ ¥¤ð–ûš€·šñù¡%|L=ìÎ „?“É$Ÿ„¯?œp är¹OŠÈ[ñæ ÔãP1[=ä•R_Êår‹xàBCÐúàÐìÝ»·”Èår9Û¶~Mý…>Õ0Ûå«Ç™•Ëå ’ŸCCCIgJÀëëÖ­£££ƒ¾¾¾ÿ5M3ëgÒ_Ü_Yþ8§··÷Z€yóæ½jL¹‡ÿ£>ºÍ¶í?Ç[1¨—.ÿaÀÅ[$õŸs¹ÜÉ›7oÞ6wîÜý¦PO„û s•eD[¿~ýËÀÕÙlö.àÀ›EMºùà-¬y¿ˆüܲ¬®_¿~¼Äㆠ†sKû]èÏAàÑGÕÀMÙlöxÃ’g§Ò<Ñ.àAùð½\.÷2Ã=ÉúõëK×ÏårÏ7f³Ù;€ãð—'ú9€)"2ZyI=~(ô°xR)õd.—+Íñ?âˆ#†=A)åŠÈ3þˆ½¯†UøcDggçXŸKÊ}M ŠÈÞ‘º§sçέ°nsçÎ5 ÃÈà%Mÿ·ÑJ©¢ˆäûúúJ4\'t«W¯q›æÎ›2 c\D‰©\.7â9ËÁ(AÙl6ƒW¦l‰ˆá'5µ/ ù\.WØüñ<ñÄ#ý `¼ˆ˜áv)¥öööö& „ $H A‚ $H A‚ $H A‚ $H A‚ $H A‚ $H A‚ $H A‚ $H A‚ $H A‚ $H A‚ $H A‚ $H A‚ $H A‚ $H A‚ $H A‚ $H A‚ $H A‚  ê½o|ã¹ÿþûKÿ?øàƒX–¥ Ãø“ú¡]×Öñ¦iþÉ<A)E¿,^¼¸´ñâÅÜwß}‰x=â¾ûî#üc>òÈ#£±Zë©@§Rê`ôëùˆHÓÿk­‡uî°‚Tªò5úÿõöW€§µÖ½J©­ÀžE‹í X¹r%oyË[ðzÀ¼yóذaCéÿµk×#"§(¥þ8˜üzô@˜ƒ÷"‚Öºâÿ`_ô¸°2ˆ*‰ªá sø5ØÅÞ§”ªÚþÞë[ÿUJýLD^¸páÓÁ'œpëÖ­KÀë?üðÓ4»€w éA©XÖZWlá}Ñãã”Aœà×Rq‚_KD…>xoFÕûð¾èñ”Ñ!€µ"r·a= ,Ø™x‡8Ö¬YâE‹X»v훀ù€y( |T¸µÖ¸®»/Nðã”@œuÿ›õÂa@= žð+¥0M³JÄí3 ãPU.°ND>´hѢ߮^½ZtÒI’(€CWø/nì‘<u‹ˆ”ÜuÝÒ¦µ‹ëÿ^D—ßkA$8.lõ£^@ ða {k´^…ÂPÞ¾²ÐûBüoJÀÀðßÊÀ0½}¦¸óÞÄ4 LËÄ0L,ÓÄ0=QRDPÔü'€Œì¤EùÇE‹ýgÐ×pà–[náꫯâýŸ^§ð¬£Vš!vQ`c Òkª»LœIÅ;…Ö.Ž«Ñ®‹«=Kî:.Z4n`ŵàhÑRp­q+,}`íËBîºeK¯Eÿ3×x|áwwÑ¡;”p«ayS¡v‰/ì‚R(Ã@QþLEsžÖÀ4ýý‚ò|¯À0P†ç1 ¦a`˜ž‚0”ÿüÃï¤òç¿sK©MŠQFc­ñ´Û10AÁ°Gƒ>¶páÂÏÜ|óÍ\{íµ‰x­ðéOšüãð_|êÿ¢ …Æ¥¨4vó¢ùÛŒÕì4îÃñC èKI` ê}÷Yø•ÐñBÌ>©¼Þ>ˆÄÉÁ{_‰wlùÏb‹hïXð÷éò}ùç4HpŒö?“²R‰œ»|ÿUm´ÿF‡> ‚Žè>ÑÞ«ïpý÷:ôꎼúÌïÿÒï!1š¡Ö>ïq²°e oõ9‡±öXZ­VLì’A¨-"W-Z´¨àÆoäºë®KÀk¾¾>:::X»víéÀÝÔÍð{îý€z™—­'xÎú9ÛŒ£¤ƒñ ¶/@e»¨C'5ÿø’P„¾/‘ãK±y…йꜿ$HRîË¡ãËû¤©kÇž;ðbÏó̵ë^/ܶȳ­w?QeTq½¸gònÂ÷£ƒœˆC2Èv_Öß2jïw³ÆÌá°Ôaï¨æHÁ_/\¸ðÁ°š(€×&ö§”Zœ_»‘‚Ë{ÏY¿f§ñà(”¤#V>Ò¡"¤#Pi)#ÔL‡ }^¥l TÞ{ÜýD•AÔ#¡•=…H[›|– «Êí^O"ÞFµ2’ȳ¯©¨«”føüÂ=D?ðW­gñ–ö3ù³ oÆ ]ßøžišKN8á„=IðÚ*€3•R?¬øšÙMoæ{l7M‘A™&¨‘ðF-^ýÛ”²®ÕSN ”EMŠΈu&r|Má¬ÙþÊk눀ŽDø«<‚°$zîÚÊh‡b¬Õv1L¿ˆvs"Ž85“‚J©³,Xð¯gùy]×Ã>òÈ#-†a¼½žðªYÕú_¼d­ÄE0|á¯JÅ)„FÂOµ°…S†Z†6þ–¨õlJø«C`jPe›ÃÉÎ:Ê(¦­UÂOmá[g"ù’ðˆEØK©ÊêG,ô·­L„ÚNð ŒW æ¯ÜÁçû[ Ïbªš£È¶ˆ¼}Íš5™D¼=z4ZëQZ뿨ñªm¬kù:{Í~B,®sÆ»ÚU(F *öQÙAÃCÚ±û"Ê‚ÈýD;lTø£×®øFäøØkǵ5ûÆ·5*@Ú/ՉШ¢«©Œj„ QÅ0<jx ¡¶Ø<œ¿î§¿ÂÖÂP5ÄDDÎÚ&L˜(€W{÷îÈ(¥flj¿Ã O¤ÉNã× f Ë]?ήêt ¬§ÄtΨ@T[ójeD Ë'@õ<hÞs©÷×ð\†çReÍ£Š®¦2ª‘ÜSFU#,Rµ¯RE®RؤùñÀ/øé~ ÞWª©èeJÍ1 #½cÇŽD¼& ¥Ò±š—­v[¬QÒ÷6´žu,wX€*\y‰·ž"ñÖ÷ã…DÏEü³¬÷7R”Q¬¢©è/·nýO†œ¡ZÝMðÚa(䥖°Ó|‚ÝÆ}(ÉT;Õtµ¥ª3Vfûc,P-k«ÆYÏúYóÚ®6Ñ0&FÕ¬ˆÉDǼc¶µ­ï~KMW»JùUy0É[HUü_/I>>š %r?U¿«Àxe³qß³lÚÛ×ÿ\ ˜(€×­­­(¥òJ©'¢ ùEë~ ™›ée8Ö3ÚѤAæ¹fV»vâ¬f¬JkÇK4uUÄX[êx.±qwƒÄYlÎ$Îs¡‘÷£X+®GuáñãýÕ!]p‘Šø¡ÕðýþrÏO㊃ž‘|KKK¢^m "C"²6j½všë–ú‰ªXËÝ ó\ÇzŠÔÏj×k«JLr/2ÄVÃs¡ªÊ°R`šñ\tE(!M(£ø!¶*ekÁëù)¤JÕá¨RàRC±VýþÕ}!£àû¯ü8®®†ðZ@k=<Ý?H/ 3¾sÆež#YóØ$وƨ‰b«÷×£®÷×´æ5<â<—ʈZ‰³Å>µâþ8eDtD‚Ú%Ï•–»Zøãr.±žB0ªBÑEž½¥L(TGû"ò¨ëºƒ¯gz]+€“N:É6U`7÷×KZÕJœÑ¤õ¬pOë¹Ú1C_û÷Ó¤ç¢k%ΤAâ,&ö–8kN¼2ª÷G¯„§3Çd쫟å0â~©¡x%ò,½¹V•Âc›N>ùd÷OR\~ùåì&®¸âŠýùúVàÙðŽ݉àÔÎ<7ˆûãgáÌp4V 6ÈC òJJÂEa§Z“‚ÂVÚ†Dð3žNH ¢Â"5­mdFB^ _ ûDÈ×°žD¿ ¨r+à‘ëíRB?Þ ¿ eÔ¬À†”‘‹°K„g¶–îUb•EX˜ã•d\½Bµ²¨TXB^tÜ`ßïµÖ[_£>ÀdÑÉ—ÞýîwsÛm·qÙe—µÛ¶}&Ái”ˆôk­½|ùòïz×»øþ÷¿?ü“(µMDž¦ã+éñî<^±~†!cêdžë E-P½Xµˆ0 àð¼0cÐÅÖÂ+¦bS«É+&´‰`ÔÌnؤQ%W;nÚ«ø÷úÓä¿Ç{&Žfô(ï<ªÅDµ˜Ðj2z”Í…“Æò•Iã™m™¥PƒÜE„ p³NóF+G·¤bÛzK†ïm¼_Y‘dlÌtkÿõÃbóC{4olmÁh5Q­ªÕ;'­&Çɰbò¾Û>žÑ ÄYóªaG©.“ŽPÙVW40wTG´û=yê©§ê{ï½wX}ö}ï{_à¹.>’Ñl&ðÎ¥K—¾óUÍ,Y²d*ð! ý„0)¥ÔW\qŸ;3·½ímMñŒ3ÎæÀöRXà*&8硬vc‡[0CuÜï ´Š°df&Œ¶a”£lh³¼m”¿¶ÉŒ²9Èà/ò‡Â9˜ü•"“1¡Å‚Œ­´z‚J‹¿eLNmÉðv†QàSU[³<0Ó4ùç‰c™ÞšÛ€´:¯-6dLH)ŽiKó¯‡c–e2X¡üÊï‹cQü»Ñ›[2~{Íøö·™Œj³YÚÒÆefªrˆ-÷ÀUØ\i·2ªÕòÛj{Ï¡ô ,ï^Ó&çŒm£{ü8Ú•bHXóèð^!¿h[Dsêè”» IDATQë¿ x àÌ3Ïlº¿^{íµ|ãß ««k¬ëº_ÄL "òá®®®#º¸ì²Ë¸üòË ¥ÔRàM0y²a8î¸ãF2øx D]PŒÏ/ÀåùH¼'Êûk ±¹ÀYCðÃ,wÊQ!%0ʆ6ÿÕï¸f«ÅÛ]“#tíaª#Dñ+…•ñœL ðVyk ½O›tdlÞm¥(Æt~ ìøÀ˜6ÆÛ&˜¤ Hþ¹ýóøEÚË`BÆæ#ícØò)»*a?Â+ÍüÖŒ'ø-õÚïYíT«ÅE£Û˜¥Œš\ 3Åà"#C*c••T‹é·ÕòÎ(Å´×–Em>Þ:Ší¥°Ej{.BÉQ›¨Õ~â䌖³Pnùvy|¸ýtûöíÁúpò”ŸÓ®¥K—ÃM6­ÞûÞ÷²bÅ LÓ< øØA‘¸®««ë­_üâ‡Õ\´hÑþB±XÄu 5?S.cÆ•äÆeµãbDzÐÀtWÈŠ‘1ËrTHÚBÂXØ‹Qi‹s\Ó‹±#ãñ·›6£lÓÒ”/-¾”¬µ¯Òž ›)“é³ £ øÛn.O§˜n{˜^å+‚ŒÞ” ‚°˜ŠcÒ6×´fØñR„Ó”ÉI-iÌ 2~›hÿ¸V›‹ZGñJ…òóο[àRÒŒKÛ~Û%è+¨À ”•íÝ«eœÖ’á]¦M>n81nª7ÔLV–| p”}4ÊU‹Å@ ¼¼hÑ¢'‡2ó­o}‹¥K—¾UD>räçSo»í6.¾øâ¯¾ùÍooogD”Û a=—\rÉèÛn»mX¡€¯U7»®«ÇÁuŒ¡­…ܘrP©CÖ)U¤žÑ˜zº(¦Ø!A :y¸ó·…\Ö@h[ N±,ŒÈ\PåvŠe{ÂiJÀ)àûo~ó›à>s¥å·´‹½wö=Ë»ž¶wX­yÁ ]Ûá÷„Üô’ÀúçtËÖzÐõ„4PŽw/»íø÷nOŠ/ê²ð¶þEÿ¼Nùž}AË5¿]Z\Q€¼»]·~ûû#íw+Ûß[tH• x¼°b]PoŽ¿´þ¼[yÿÙýó5{\—Ý4žïÑ,QŠƒæXf2‘‰8®^Ò-Þòópß}÷±dÉK)u%pZ-£í¿®‘¿ëééù@ww÷š ñ~Þyçò³ª§§ç:­õß«\úx_fY¾|9çž{îðÀ 'œh¯s ë«”zÚuÝ¿ ÿÒK/àž{îáç?ÿ9@)3ÙÝÝýp °šú´äÿ µ>àïxGSaŠÖú¾Òšâbä[±ÚTýa¡ 2©K ®-{œ«:à T±R üN[Ôë1»‚RÍó,~V,ò»|(œð¿¿¯Fûƒëænßµ—©Á9CÏþhåùÏ[pÄ CJ‰J'¢Üpx¼P Û-Ò ß`ÄD)cÍD&V,êêo¿n¦/ÞqÇÜ~ûíÊ_´¦Þ\™¼RêÚeË–=wÉ%—B^uЊ+8餓¸á†øêW¿ú‚RªQõßXà#K—.=üóŸÿüðÀ’%K,à}~‘A=Ü~ë­·ö]qÅ\{íµ¬^½ºîÁr‘Mþb=Ìš>}úgƒ!ÁÃ;¬îÁgŸ}öjÑ…—‹KzçTÐ-UãÿÃâóx E?Q.Û !Á :ÿ¾"ìs½Ž¿Ïõ6_@V lRºÂÍ wÀ>¥ù¿b†tDXÝj%à[ÖóEnw ¸1YmS„~_RÅÚÖ¿BøË^Àç‹CìÓÚ¯ YÏ ïøÕ}¼°¯P>W­öøÖ{Èåû»úùm¾€Š(^üy¿uŠÜÝ?à‡@n¥‚ ¼«@™úÊï¹Á"ÿ\À21ˆ(e8JŽ*-êêoúœsΩ› úè¶mÛxà>/" úø ×u7|ýë_¯{àêÕ«ù¾Àe—]Fww÷&¥Ô Îýg"ò¾®®.«iJtŸm"ëøõZZ«N=õTzzzö…rõpÃ’%KÞÜ(øÑ~ÜÏÃe?50k`liÑ˸¹ìЀÏ?b­L`³)|ÇtÙ™:}°ùÿaÀ@Ùç°¾àð=Ã%C,\%/ðMUd]¡€Â8±~!e°}С§8Ä:ÑØÄ/fÒ&pgJs‡*RÊ€ëYÿªs;†nsò¬PƆ,uXXÒÀ/"7îí祂/ìµÛ¯~»g€›û÷Ñ[_áÝù+"Ü4°ûûÑ„ïÓ-¿:¼8Xà_òýüF\ÚiŽ(¥h4ãe<“d2®”€ÖzÀ/ùËšý0è£K—.=¸¡‰þý›åË—Ì›7¯iùY±bE¸&§> Ì÷zÕ‡UšaùòåtuuUJ}-q™ê'gãÏæèÈÃÉ_á(}ÚÐb„¿w/À[ßúÖš}Õ—Ÿ‰"òµ&Da‹?ÜG±8¼É°W\q®ën4 CäÒPJݶtéÒ7wwwïn¨|\""¡U-l7 C†#ü›6m ê>¥Ô¾f ð&}¼ ä^àÿ•þ74-Ûf°ë˜•,Z‹¢›áÑJxÎRüë(áä¢ðƺCCÑ„— Xo*z-¡ ¼qú8n‚pÙ~ˆñK³Ài˜" Kb—!ô¢ù™!ŒJÂ_‹Ô3¸÷và{iá>KsNŽw-~ÍÏ ›ÂMO L Mƒ®5gBÇ£x\»,Ì÷óAerŠ2B‰ÂUÂÑüÌu¸GŽCù#1”à¡m4áoû÷ò—Cƒ¼ÝL1Í4½ïºÂN×å×N‘eº@J`J08.5k$î—˜¢°(¹˜-sqÅÅ9ÉZëf§þ}Èï³°ËD³X¾|9K—.:üäú"!À¥ÀMM)­õO Ãøw/zÐ&"êÜsÏå'?ùÉH*—R4·°B^D~Ød"°2FS‚µo<æÀ8Ü–Õ§<Í­†c‰`*x$¥xØö„ÜÈ+Ï*Ù"Œ¥š§O¤¶2€ À¦¦ÏðWŸ:`Iyf,åÕÓ#0`ÀipRB«xqò>†oÇ5KGîÞt*ø¡¸|MF‰7Åíe (ÂT`–RUK§³bqp~8J)V9?-=/¥tQÏ&MB¡üB­xV!â+ýÂ׎©ûТi›Iz¢$*Ik›éƒJ©{DäxŽ" Ý#ZXä]ïzâ­w×ÖèvWD~ÒtpùòåO]MÜG›ˆ´Wøßò–·j0©‰¯|zÙ²e7:èË_þ2Zë¼RêQÿüÞf(ÒÛŽC«b„®©gl‰hmROK¼ØØ´ò,yƯ¬ÅŠÛˆÔÓô…2-¶ZÅטRgaÎ÷AØâ~^`Œ^‘âXñ,¯Š#5…ƬJ~OŸæWºd€#D8Ú×îÑé¶ I=ýÏ[#”â©xÊd ŠÉþ½Ö¬çø*ΨWW÷Q:§`*³Ôü¾ôˆˆäƒ²Þzèîî^ÛLþ ˜,"‡Ayj{³øþ÷¿ašP2—/[¶ìñ¦Àe—]†Rê;J©5£Œ‚¡f±råJ.¼ðB8±‰<ÒÓÓóéfÎ{Í5× ”¥ÔýF)e@˶cЪ¿ÌòÕK`S‡¢;j¹cž”aXÏnºº±*5éÈ©á¹H kßþ|þM·_*”EÍ!6âs ,·"žR ‰Wtõ†übç{„k`ô %ÉPJaÀý€\{íµMõq¿Ï>Òà°QÀ‰]]]Ư~õ«¦å'5­õ_7áüH)õ Ž )°bÅ º»»‡\×ýðRƒ Üðþ÷¿ü½÷ÞK­‹„qÑEÐÚÚz¬_`TC®ë¾;\HÔ Däþà‡3 Ãóú'c Žöܺ­‚+± FÔZ·VŒ_žU'åJÞ*a‘ÚÖ¼Žç"ø…y~\\sÉìBÑztä.BÏ:ót=kNý¥À¼Dä}Â'ªŒj,.ï)Ô_†¬ñ|B¤4)Ó@Qî?ž'ð[Ëjn_ÐW•RçhÃ/f52°dÉî½÷^®ºêªv?×PÛµÖÿÔÝÝ=9h® No¾@ýI]twÜqÑ÷ýèGÕÎ;¿4ò¥~ "-[¶¬¸ ’»ï¾{Šëº¿* sòù<…BB!Ïžö§y©c†;¹ÁR;6 F P¸ ^ø«=o)ãlÛ'¼(Ø»Eso¡Àw\‡#ý‚›zKg”ã;:5ïÝ«9ª¨H›¦mPL› ¤ V[š œÚÀûxxOOOÏC#Éþà?í8έ…BáOø äóyR»x~þ­ˆÙ‚ˆªÁ\‡S¿Št3^€¢kÏ9 $/üÓsƒï(ÚF¥`\ F§¼©³–Qì*òØ@»yoR]ÕÊ<¡sã­ðž.ïÙá2Æ41K<‚e朡´Á˦pÍîWØRphõ3òºŠ6ËkÏ^GíÕÜö\‘ .dL>~¦Ìঠv§ n“!¾TÌ3&¨í‹(—àüCÀGx`«fî>O°Äu`›¥éÒ»S9ÛåMîí>éhÕ:~BÅôäŠ5 ›˜ïQë·Ó¢q>é~’v«tÚSþv§išï?ï¼óöޤ?vuuâÑ£êE®ÀƒÀÿëééYYcì±aŸþ¬üìÞÚÓÓ³úºë®ãÆo¾?ß“OzÌGK—.ý¤ˆüs£ð;(~*"O*¥‘7(¥ÎõÇF {8À'{zz>ÐÒÒÂp×^ûñläóùº®ûŸù|ž|>O±PdWxñøŸ20þ»ÚºJ“ËIÕ‰U£V­y͇ÛGGŸ†qi›‚1)oÞ¼¥¼ò×^)Ð;˜çßRûT¨ü'ꮊð®ïYÊd!™^@©åk "\þüÌ“öÏM(˜µWó-.-¶Y¦æJż÷‘>·s·÷”FtÄ2»€åÀ;`QÞ(s'ØF™š¬Ä™àíØ-rÎîØ®”Ö çRÉáØ„²ˆü®E„™îñ\ª.glj,¶m—”€mÛ×···qñâÅâï÷Ý®®®>Ac6 ð$ðS<¶k«”:WDfâ¢6*üù×îîîOÌ™3§nAÝ@ üþÐÆ'€G›s´€à#J© G)õa`v“cþ«óùüguÖ°…ÿä“Oæmo{›6Mów¦ibš&–eaZ&¶´ÐÒ,¢ã3Ïq™å¸Ìsl¢.~áIK <7HǧLhÙâ÷kñ…Ê2ü¹óBç \¶W0£ëøI0%Y˜? ¼'0Æö<‰`zß–*Qtµ´Ù|qúDÚLGªãäÐV¾²[Ñ26å)ªñiŸö4´gÊïǧ½×±)>:s ‹Ú21« ùBÃgó‹Ri˜† þ9&ø[»¿o)½?ùˆ1tOš€Ln"l‰›Ö'üRk~°€E´˜-å>㿆ñØâÅ‹õ)§œ2¬¾888ÈYgy‘³eY_ ñ4Þ 6f@Ð |DDæú²¥|¿7þf Œšâ|ï{ß €išï¦þ ¾ýÅ.à†Ûo¿}àòË/ç¿øÅ°OððÃ^¹€mÛ[MÓ|Ʋ,‚ÍViZ§‚cRàFcÔñKTÇežgîÓœöÔ€çê§CL¿aBÑ”_íL…Õ·»d R÷û‡ì¸fž1Ú.ocüÿÇøÛhŸ¬3mi0!eòÑ cÙZ‡"8ÿÓÀÇ &ãG‡„²Þx2£m>1g O‹Ä.Íuži‰O‰J`|Æ{ìO••Ãø qüÞÑÖÃç_]›KñVƒ<~2ïž§›ÓÉXÂ}Æ4ͧ-Ëz`ÕªUÃî¿øÅ/èêêâ+_ùJø¿, *¥þv8£fM)€o~ó›,]º”[o½õÉ&²šûƒ›zzzüЇ>Äm·Ý¶_'2MóEÿÇ+ÿ ¶I:ßJzèh/7^wØ-2|WÑbVÕbSæýaQ†QŽËƒ-à¹o1=M™`ÃÕ´å]æ¿\Ĉ¬Ë7ˆpF^8:cù‚úÒk_°=¥cxç6‹Â,ËâDÓòxþü;§kÅÜt+°ú% ì„„Œ] _ŽmMsѸQìòùƒçf ,J§7¡¥lõKJ t¾°gО†q)ÆMjeᣱü(>ÃOê÷_òÿا3£¥Bø}ðL FŠžžÞóž÷ÐÓÓó Rê Q~®ïîî~¬«««éQ³¦Y»»»ùà?ˆã8_þû Üü¯öîÝû™hè1Rœ}öÙ/Z–õŒmÛØ¶í+›Vg<-…hŠÃ[³æÂ“RÓÚ˜³¶<+œ qï§CD—¶IiÜÍ ±9Âìíù â DØ ¼Q¬²Õoó™xÛž€¿ß6<"àrSÔ,0Mò¡áÅ<°Ð436jé3Õ‚;6íyJ•É:ú‹œ3ª…mƒ°/\)óǵ–ÏS:g`ýÓ•^À¸”çù÷=¿½•–ðŒÄpH$ñeÄ5iÀbâþð÷çói·ÛËÞ¢ßolÛ~æì³Ï~qûãÔ©SƒPàóÀ¯‚üü@D¾qå•WÒÓÓÓô—†µ0ȪU«X±bÅ Rêßñf20×Ek½ä[ßú–{饗–¦öî/lÛ~ܶm×¶m?›k“1Ûh< ¥­š°øa'jšÔÏ<#pXAʬÀa¾ÿ AGˆR+LVÔLÙí”(ăk¿¬…#SVyá6»ë—Â?Õ’æãûSj÷it™â* !ëYarÊ¢µÂê‡-tÆS*¦á ý@^)xÛž<ìÎs¬£ªr*–Àá[#ç sb‹÷Y‹Ÿ+hoZrö8ÊõK‰ã¼°FÞZ¤6 ¶P)ôz¸y8cRc°SvøÃ¶mײ¬ÇD_¼é¦›¸âŠ+¸å–[´eY—+¥ú ü<|fÙ²eû†;©hØ À÷ÖÿEc–ߦ "×h­ŸM§Ó±lBÃÅŒ3°Ù²¬=e3zh–Û^µ*o\’/\šR›Bšx¦!@YîÒ«*sß‹„È85äŸ>ÌÛtQÇ–Ëê´Q^z«ÕöVç ò ¦òyŠe‚Ž€¥g_ÙWD;n•@hÛDƦ¼¼B0BÑæ/VÔ°·»ó°+» °»zŸÇí/@0é'T¥ÇØ0>åyãÒÞyGÙÞ}æ]_‰ÊçÞéo»ò8» U£ qåÔTM‡–Ê€hN âÕMQ“o[ýÀØiYÖ¦`DlpfˆÈ¹ú ¿·ôôô¬2?æAQAfÞ®n`åhÀ=J©ï¯X±BçóùòDžyæÒéôæT*µ3Ðè©T ;e3Î9œ´;9R/uV®‘y¦:IÎx9^½£ZŽª°þþøÿŽt:½ù@…¥n½õV ü¸çœî>Ó4»¡‚£i {…’_üâ,]º”[n¹¥éÒ¥Ÿ‘A(Ó± Ê«e‘Ï-[¶l÷’%KX¶lÙ ŠN9å”§zè¡íxå–å¡F[q {S×]F:.18œÓmj-¾IDAT…'`ã›Yý”×(Ãí1ÚVqüùÛ>—Üñ-}¦à:íÀÊb·eÆx^…åäË ¹e.A·üê³þìv¶uÙµ!…bõ@ž=— ñ íº®MÀ“2‚Ðø[o½uOWW×°bÿ+€ !¸téRÕÝÝ}ÍÑzÕÅÕW_]b>PXµj§œr ¶moRJ¦”2‚é.š‰…ilmI¡U¾ñrRÈû£sC»Å9EM«~WJ,¹•D—e†Ý~„u“S¸ªR¨2ÀO‡ |Àq9ªÅòI4•÷êPHðKÔb.î ÃïZ4+-è %ÒLà—C6¿<ÀÑ¢0¢Â_¨ÅrB1D3þ$.ß%Kå,¾¢k^ÜË{ƶ1FSæôw¤,ðÅømWÑe­ÊSTÑQ–Ê,~Å[£ SaO¡MµqDë¤Ò)”¥Â¯÷ÿ¡‡âÔSO=`}óùçŸçâ‹/æÖ[o}xûþž¯««KõôôŒD4,*xÝã‘G¹TD¾âºn¦P(P,)Šô;;øßö§¨vWÌZ \mˆ_NJbêjqЋOÞqY?œU7§Åô²èEíÅè{ü8x—ïoâÇ3ÒÜ2£ÇPU“Žò"œÞ’æ3Óó– ¬j>²ðGX ºlÑn²Ãöø ÂIÎ!³MîœÔÎ4e†r‘uò!*ð¼KqÐeéÑ?o…V©ža¡ølûXþfô¨²ˆ ¼ã{RÈk¾™.ò­b¦'ÇÖeĬûW"ùˆ!Jñ?ZÍ'ú$S3S±RVÉ0Ms¸jáÂ…_ÿc–ë]h­VJMÓÌd2™Ò ¯qj cÝÉl7w•ô`e¼(‘¹ì52Ï ˆ( À]­0Õ…yâ/’¤:òÚ÷Ê̹ 8¬›bóµ£2 KKf£xx0OÏó;yûèÊEDë?¤ËžÅ€Ãž‚Ëÿ;ÊàEFIõGJÁóE‡nÝÅWìQŒu¤ìQÂî¿ï idÀá‹ÇÚü_K¼ð ˆð©]{˜6àr vyù±–Ÿ¼ËƒÍ'ƃÊcBjÈMÐhÑOˆ¥x˜”žÄ´QÓ*¬¿Ï#QÔZ¯þc—?z`íÚµ[ñyÓDÄ[è± YÏÿ°Öþ™Ö\b3Ï”áÑZx*ÉFŠ"|ÄHó¦tÃRÞC®çì-ž4«…´¡J“€¢dÑ1ðoåóüÕ+{øÆÀ/ èßW¤ ÀÞÁ"µË?MR¼y¦ÍN_økYÏàžÂN%Ìi)pC*O®P`ï>ï¼{‹üÁ)Ò=Õ`ÖÂnšà tì=âj+iïL ñgö?r†ØÓ?DÿÞý{ ìÌóCËaÁtÅùG¦Ê•ÑY•¤zÙ¯:oÑ@yña‹±ÓÞÐ_HøöCÈÄø#ð®þ³ªñbp{ñröÈ6V̬²jâÊfâþzžBa»¯+Þ°ÙfcL°ud#‘b%øƒÀsÓ4Lv…µ¦§Þ«cgG^Ù¶­ vâ­†ÚRM¼á<`†–òR\5=¥JÏ„]ø4¸‚Z€7„©¼5Û5!:òKyIÚ³:ÔîQëo·Ø¬^°7fÑ]¹nÑ¢E7ý±Ë†õ§ ”Rÿ·ÆRÐa¾•ο‘’éUq㊳&ž¤ÜaS‡£˜hŸuv®ÿ…¦èÈc¸ #€ÃñˆG´¥XÄ#qtÙÃÖÍiˆ0Y<ÆV×T8¦ÂÁÐRcô#ÚÖ¨÷ä?V` ^ÝE!å%8-ñI>ëБ×*å%:äÍ!fBW—]3嚊…+\cÃø¿?Ù0þ¹`Á‚õ~>®2Aˆf¦ñFŠšêÎÇ\e=›$õ })ºÎž1\ROˆvœÜÀ›„£"Ã^±“–jdÍ£¼†ï™BöÇÑ‘W'â*ò%â%øR~Øä·Aø·‰–úJ-×?FÑ)ßñ=kâY¸âÆu™â‚ 6$ à+W® ¼€Xv¡ŒÃÌ·R”WjŽåÇYO¨M¬Ùxva±ªT[7¤ ŠîF¬¸1‰±hu]µWPßÚ6n¿4Ïá'#'õlÄÚôÿÛ»ŸØ(ª8àß÷¦»Z*[©”Q#%•ºš4ö€Úp˜ b⚀M8xàÌÉ[k‚=’p Šbðà¿Shi5@LŒ‰ÿ ((â2ïça·ewæ÷fwkL óý$XØéÎì{oÞüÞÌï·ðs` {+3ÞWSÐJ¦^·¨ù"ò~‚çñ·\RQÂ8sže'o J”{Ø=Qs=%¸/'aý‹£æÑ™Ió9âûê<3ø²*yf..VÌCÔ‡uÔÛ{£wqÆÒ‹~^êy |Íæ} õ\ýnåµö== jÐm{Ñk‡ʵøu Å<Ô}Œ5z6ZJG) 6ŽwFïìA‰²Ç>(ëÍDÙ²*5ŒÔ³¹2õ¯M”øgõ§ ¯³ë:Ö-\ (måýÔô‹ s¨Ôb‹i7x4؇_ä³_D1¥Á6*C œµœŽ<é†xf.h&Ÿ<À×hÿµ™j«DëøIgóf–ü¢×ýµö®Ú‹»2ÞŠZWƒ ˜ã°„LNN¢\.‡Ôdð@0€>»¡üé-æ!â$X-zY—{/!¾úÈ«°ð®ø:g°P? ¹D)Ñ*Hž”Ýú¥L¼ŽŸV‰Ù»´ øƒ„ISF–`°{YëMOyª\.‡“““–ŠR©kmhŒQ¿8tÚ{±1FÚõȳÖa‘T€"¹–ž/P²{ÏnžÎ‚hL@{Ú±¦3û¢ìP¥ñÏã”ÙC¬ênlý>yÿëoÌJ.æQ·u_ëFz”V—°úÎÕp¢§²‘·œsa©Tâ°”äóyqÎ5½“ƒ` SƒÁS@5µ•(Q瑩UÉSíHÐNËÏßrnñØô(» É({¬£‰÷gÇf&±åÍ F÷X|RO=ö·³s'ž¼ïIh÷„T}oŒ™’´ô‹Ô @%Q¨1æ¸þ¯ƒOÝñ–›u ICý‰%®U£ ~13_’èŸ=Yq¡tNµÃ&Ì•(Eè|ƒ<ƒ‘–Ô3öíéMÏw¿)» £¢Í´%ü/·Öþ˜¦>‘šàðáÃÈårxž‚‡Ó…íí/¢kPÆeo\ï› !p&-œ¹õõzrà üK‰?/v@£AÎÜÉ R¡^÷û#(ƒ‘·1ôë~Sͤ²!³6ÀªÌ*ïÔ•;”Oår¹kããã–š£GV…1ðf qkm?žm÷Û'ð—üPÓP“—üôH7<Ãøu?"ÕmÐJà¬áu?ô‚¥JÔ\‹¢Ç#,>QJd„Š_÷냑V8éº_BÁ–Ž-8¸ñ W â†ÜHj"'ªmÇŽKÍ`".\ÀÀÀΞ=»ÕójX\t?`æú»˜úg:Ð&útUמ“„%<$Âl¢ð¦Z Ô³-mÛÉÛJN”"Ml_}`*²o.²ÑÒ±Tîó€=«÷à™Þgл¬7éÌ—DdG±Xüp¾¤æ²8MÀÕ«WqþüyLLL|3::zŸ1&¡Ö“`™Y¾¶X<ŽKî'|~Á´U&ObԋĨ¶’ã¾Qç¯KK&MdÅŸ¹E¹%9þpP|906oôÀ”–R-aý>)©§ˆ^Ì#öÀÔüß]å×C+¡adͺ²]I×üóŸùµb±øzmá `‰:yòäBöÔÙÙÙiCÞSidÃñyù#|UžÅ/á9üá®,T؉®ø^s±wó5çyÿü™7¬IOæjây-¬ÙVˆJTSÝ–ötQ¼Ç7~­™û/Ût Þ›Ö/[­[±ížmXÛ¾ÖXï~uÀ˜3ù|~Nœ8íÛ·§ª?¤nn& ššº;›Í~ÊS¯M,SmT&•Gînmu÷_4½Š÷s&“ydóæÍ—çÛ¿’”˜Ïô:33ó€µö€‡ÙCSåK#…BáÛ¹¹9äóùT›Öoxx§OŸÆÐÐÐמp‹ËÍN·‡JAŽm…BáÛéééÔvþTϔ˂A5ÆŒYkßÌårðˆ¤l@³k×.9rÅbñzÿg}}}o‹È¤©èA¥j ݾ~«žñ_ðj¡Pø¤§§çúÄĺººpîܹTÎªÆÆÆ°ÿþùø€Éd2A6›µav:çúD¤[D2äÏÓ{ƒïemD ÑDÌ#áͽX6Šíí¯¸MÜ|±^Iœ¾— S‡-Da!Âbcc™Ëüë¹™Dos¬—ùóçsJ˜‰ÉÄ)zoÈ&@¸a¼Ó ~ô Ðû\¾À½_K]æ¶‚˜s§5à¶V–ÒûîÉp=€Üw¡åâ®rFôË]v!=a·ÝÊ=.HŒS u®'©Tô„óð tN¼ž¼=Ž ËÎ8ªót9Ñq÷ü$v%q?a_ŸÄüô¥Xç•dHÍ­s 1¸NLÌÅ;G•Ê?ùÎ4l3 L¯×»#Ñòî¿u:D«ÕJ4¤¶¶VR]]Íá¿yoã1.Ï:Ÿw…¹BÏü<ñî¢ ½ÎÀ Z£N‡d°í‚y_nÉüü´úzfÖµJ.5€•wù¶é:e—tÒKº[ÒN}Ÿô²±_zý$¤}lR\µIm½Úz Åâ2ÑMX‰kÄ j»þ}½pÒïZ!½Ùj³#´AÚÕ|E–Qù©/¾k3µIêuõ??n:½V¢6”1µ¡BfÔ›3ÌúÖ®FƒÚª1T^%¬j޾ÒZÝXf=Q[l=zâˆõÐÑÖýy»­»³3¬ŸØnÍ$vÑï¬Ã»¬9…¬¥yÖcÕEÖrM©µª±ÜIEcÙUµ¶ÎÚÖÔÞe6˜3NÔ—ÊJë³F]㟠+W®t²jÕ*‰ƒœœÖbj—œÓ~ÍH|A£¡™Í¯ |Ôòˆí}Ët¼kš†·Sñ†n ^o˜ŒWëR—ÊÇaii ‹ç‹£1¯0 s "1;?¿<Yyxìp’Gb&ñpnÊÇÂðÀþH[rþ‚Zm-,FKþ·­7Y»¥Ý®ÅU›«fÞÀág/§§§{˜´­¬Q¯QõM7Ò[àÍVåÀÛÍ1Â:óXaMS´ðš!JX¥‹R"„ešpa©:LXT*,¨ ž«æ–©„§J•Â% á±"¹ðp¡T˜–ï/L9óØ66ðÄÁGa2˜¾ÒèÔªö¦Óv-)))Œp—ˆeg¼àA>€ðç~ýúõžÊáUk<Öþá©ñ‡–ñÂ[æñ¶uMãðš!¿¯ƒWÔÑH®Æ’ÚH¼XŽÅå¡x–˜SŒgJ‚0û¨3 ‘ø¹3ɘ#Å„ÜÄeû#aß}¿ÇÁ»G!b×(gúØd;¼„ Š4Eí¼Ƶh§6Q+ãðlx#÷‹‰¢_ô‹fÏz–u^9Ït:möË\¼a‰ìÓgû14ŽEwU ®TÅZ¿š¸lŒGWS<^¦^* EçÙɸôÅ$,(VṂ@\,‹¶óä!)fíóåÑ8[‹$JD¶sT;}lÞ[Yÿ´=@K}žíü’Í{r>ãZÜ´q­víüGEôçˆDß³fÍš°üÏ*™ºÄ²nsm*^oé_gŒ³-×Ež6¸< 螎 õì pe:ГˆOª#±©,8?蜆JCñ—Ò0àê ÀšˆwK‚±>G\¢ç»¦ã}úíµÃ ª>6öÖ¿xïB´V·­SçhØÚ5kÃH‹ÕM[¯¨™9æ."Ž`¢µlûë>V²G›´%ï]¬6… ¯ëcm)Ú1XOÓ§«!Ýõ4j"Z†®ºXtªcñbi–©ÐQŽŽÂ<›¯À\šBêbpžøM¡™FãËÚœ.Bbæ(øRÒO½yÂ;×ÁœoIÊٜø†ÒF¢¶Û&0^L ÿã÷6²Šì&ÅÖÌ¿÷¬Ñ$àU}”Ú0/j¢°¬* ‰ßT„b^Yæ“%*Ì¢9Ÿ”/Ç#y2L#¦Ð|Ÿ¸×ñY~ˆ!¢3}¾ƒ¦LÆ„~ß‹ÇÈ­LmMÛ7õ´–´*Ò>Lc\ÃmÈåÚ]§Pøyþ̽XZž¼‚mN)bY™Ù5o )†š1¶åu‘X ¦¹ÿy:i”» ñH. J\Ê A‡)óOãWpq—jbðx‘I»ýðåNΖð-Ô~Û½ ßîû¶ÚG`êæ)ÈÝ“[Só^KY–ÂâSÈM[/Áë‹Ø±Pz`€{±Ì6nÜ8²*ÛÌ*>¯ß¸áè$kû—©£mÉ4mž© ÇÞ½ À2hˆÇÆm£±¡2Â>ïÑñþ’¯Â‡åaÀ•ÀŇðÎ%Þ¦éÅ׺gàOÅÁ`é4ú^ðM÷²±4Ö¿2s%´Ç´ÛŠÛì}ßFÛ EÌñ ¤|›âž—SSSùÅ󴾃Ò[\X{Éê°ßÖFÚ–T‡c~e(^=N£­Ã¥ýÁX²OŠET×Ñ0÷¨07˳‹•8Ÿ†óFãÑ>x8/g‡âLš?¦mŸzÂ’ðÚ"±±OØ@Vi.˜/,ºÜ|ÙÞ7é¤o£ÎƒŒ œA/sÏ/UãI¦3hãš ¦[kÕIXX­´-®Œ´=OÛålšûöýží£$61Ÿöû\)‰Ú.ãh±&ìòEšå %ÍÿЭÞPmõÂÈí^4u<1*Ý›‹·MȘ“ÑtK«×Æ2²÷½bÅ Wmƒ2÷~T»>Ào‡¥ÕG `¬ÅÐnÚ×° OWúôÍ+W ÏœP sŽ)„ÇKäBÒQ©0³ @˜A'íƒy÷ ù è¤Ûï#Dí)„ÑiB'màNOÁ?ÃCðÝΟt&xla‚$M"°¿±¾}Œ3¦3&FVPQÀûþQmÄO½Rë< zÝL_1,Ø¢ygà…ŠÛÂqøõñq˜W‹¹E1xªp fDã±#Qö{ÎŒÜpLÍæwœP$d…Щ„˜]*Ú…”ÏDðv·É Üª´­.X=Ðll]ÞRy_:ê“÷Mÿ?°»01 zÉɦvÖ}òžÌ{͆ÖF[ÑS£­ìuPí¤¢·ªñ¿TºÒPÑ[áBY}YZ«î¥ës7‰þãS7X»©Ý9xwkÎÿŠ`£KÄl0²ƒ ÛF1^P\3÷ÉzÌßʯY¾“_·Ü”ÿ³ù¦ü«–›ò-·ä_Ÿ¼%ÿñÍ©>ù¿‰o[ûäßµöËo¶õËoµ÷ËûÚä}§û帲޿EZiÚ¨zc=3Œtƒ÷ù¿IÀh4ºÿwæ¡7’çî¾z‡þn×¾xßdC’GrwÜùáa¶a¶a¶;Ù3¨oþ 4IEND®B`‚gtkterm-1.1.1/data/gtkterm_64x64.png000066400000000000000000000070511376216657300171610ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞgAMA± üa cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ pHYsV‚V‚˜œ×1tIMEã$È]Ë IDATxÚíšlÇuÇ?3»{GòÈû!R"e‹úQÇ’ãHòÉ•¥6v“•êD.P´¨¶Të¤hZh‹®íÄè´ùÑ­%«ª´.¤Iš&±Ó$NÀ¶‹‰¦äJ4eJbE‘"y$··;óúÇÎñŽ”eÉÈ}áí¾™÷æ½7ï½%4Ð@ 4Ð@ üŒB]ÍàM›6-¸×Z#"XkQꪦ¯-R©ùyëÑ××wÕsûK±>àÜõóR[ip° ˜~œ®·Ø |˜u4x'°ÁÝŽŠˆq÷à}@ðÚ¬}ÉðQwý‚RJDd›RêQ'€HçOŸb'´Ow:¬>ÜHÝÜÿ<ŒËÏ¿P]¨LLLØ\.·8Œ¿E²‹Ë€€¿vÌd¡ù5üð—Àw}'ð'@ØëÆ.]-± ŸÏû"òQ’þM`È=?q×|°îÞ¿ ì~—dÇ«8 ŒO¸>½KÉ<€^¹DDÚ_¾ …aXï¼"à_€vÛ¯ @“Øõ+À3n¢úyŸ\MÍ<Þ~šHÔy NÓßßµU^*@®Ž äݳ2€ïûõ>$1§Â¯wÉ H¼ý(pkõÜ´iù|¾Úç@¦fËÞtcêØàz32,1–Tííí“À—{EäUU.‹kIÚ’#Ñ«û_$¦ñ1 ª¢ø'úµ:A/–Ê j€ééiü3p+ð¤RêKÀ€•À}î} Ì9F4 •R½"òWÀCÀFàY7ïn`;ð¨Rê‡"²Ö[2!,…8 DZ"9ï$9ï~Å1ü<ð¸ˆô;ó˜^ŒÓ”N=$šð*ðÛÀ×]Ÿ˜Ä|¦—JW%ÉÍ›7£”ÂZÛ µ3ÆÔ‡ÀY‡W‘1¥”xž‡1’¨.ï„×M›&1HcX÷Ì:I`öí Câ¥qB¨?ÆŠ®Í % C|߇$ú›­Ežç…À™*Ý ¸:>fa8Ý@ 4ÐÀÕàŠŽÁ—^z ©zó+‚ˆÌçZ뫪…aˆRŠ;vütpøðá÷ù|žÉÉÉ‹†ÓZkZZZÈçó´··_¶Àâ8f||œÉÉIJ¥R}2uÚÚÚìôt-.n»í¶¥À‹/¾H*•ªžñÀÝ ½U¡[¸XŠ*`ÅbŒ!Žcâ("ŠcLcŒE¤¦Zk|ß'|ßÇ÷}<Ï»”v(+¦d±/“äg•RAÀæÍ›/‹¯ËÖá:æ7+Ôe5¡Šz˜iDq;`%)ŠFqL¥Q‰*„• QÅ1ql0ÖbÅ’L©PJ¡<çùxžøøA€ïxžJ!Âü;@ÑêåX“þ9 ~ÇïöûÀGD¤¿\._¶\¶óÍÀ#‚ÜyÆ?Ä ÿëL©3D6ˆ`¬k"ÄÊb<Á¤qSíY}?c…øè±`¢EcêûXAásM°†.ÿ5õîü{ïÐè‡ßÐZÏ]._o5^©ÐÛÎùGèO=Å„zH*±k“_׬¬¸E‹`qmѵ¹½~l¼{‡{O,–² 9Và†?Ŧ^@+½$ó|ëÐÓÓsÉÎ ]¶Ä³g¼C”)bEÏ3jE°Vˆ%iV2-êgDˆ$Ù}© Ë:šˆ;%z\oAŒ%13Ds>šà¹óßæç³;J¾òË{I~öïß_@]çå$•ÙÀÝGÀÿçR©¦Â˜%~U„õÉ2dEè.[ò‘0À¨JèËÖˆæ¬XŽ‹%!lJX+ü¤\aÚ ˆpƒQ,·š~bN;¡t¡¸1H3l }aeþµ÷ãüƒ¼è`Ìzó§Fðž7â§§§‡ýû÷ãU™­”ú ’Úý½$¹ü½€‘çz{{eóM§Rïš–³wœÕ}X Fjí]Üo=vx>k,ôcI£x°¹™ZØšcN˯ç2ô¬YÆ{Ú3ËáÙÛý€Gsmìɶp£çóBX¡Ù§²Y>ܽŒÙŽÏ† £y1Îéî*¼Ÿ[²[¾XŽËß9pàJ)-"oÈRê9@¶lÙRóJ©Ý$ň2ðm׿€½J©]ÖZÊå2å¹ðGÞäŠXÅM l]¬°1ðÉu·¢Öç¸~E†n¥Y­rM¨® -lmJ‘Ø®=R(RžæÝM)ò v´6Ѿ6‡^ŸçæU96¤nзvdÐÝV,kfg: õæe…f2¬²«ã°\9R.—1Æ`­½(?"²k±¼–¤•ö¸öÉ'®‡€ULOÆMã^©80©Ùéca&‚© Ss1ç¬åœ±LCƒñ2¯—#¦­ex|‹0XääØSÆ2F0S© ã³NWbN‹e,60QAÆæ8Zª8“ø€X,ÒI[9;>5=yt```1?{Dd»®òsm½¼ØFRÎþ2µ*ÌWHÊSÛ€û†††>}ÍÊkN™’7LuvÚæáDý|ßD˜±ˆ. ‡•0¤ ±þir–­sœË·lÄŒODe†f*Xÿ©bf¾:]žˆY«=¾†¼V0"üÙéqÞ76ñRÈÓ¥’s„5¿³ZÖT‚¡r¥|jhhàCuü|]0õà«üŸ© àëœ#ù0yÜÑד”­F€CÅb‘=wï)þëçŸîOM]»Í.ÿ!ƒ›ù¾é'f‰Ð 8DÌ Ž–Ž…v“Êò÷ÁØÄ,„)-Œæçõ QÂä³ñÏÌ”ˆ.p~‚¶>ëÔuh¼þ=wï)>û­gó³ø_Çφz~¼-[¶œ" ‹ï¶|àØü)Ð|B)õc Åb‘ Hu›Š½k¢í‘WvN°º¸D5·ÇôèwZ˜)E ŠÐ ›UÜ—ÍОMÓ7WÁ3–½Eø}Rܶ,À²œ‹bÞj>Yø`¦…©&Í@%rQfýñhÉIÝ©»èhé8xäÇG~088ˆRjøRü|½Z >鎌»€¿­£xRDÐZ“ÍfQJ÷ÙÙ®™ærWëlê<Öªg~&4üê„aíºVhö¸çØ$/g-»¼ۮ˪ ÷ÎFO¡?±¼Ð5²Ün¨1_ªZɧ ãÃX·X#ØeiXÙӟ–bl³×´@hà• ì©YŒV4C“£sÈÉiLl±uþ&9yà¦Ö›èjïÉås'r¹ûöí»l~öïߟh€ÖšÑÑQ:::z•Rˆˆr±(¥èììddd€L&ƒçyçÒAÓ±uÑÍ׳ÿÍœÌ`¬M"¸I¾”UÜs®„ŒÌòïÍù@ñé9V B÷Ù2ß›-Ó—±˜é2ÿöãÿã½g+ ΄|±c)áñþœõ`2䳩ˆ±”©™€$¡qF·²­óv ùÂ1/åsåv´Öœ9s†®®®^Ïó0ÆTÓI$Qó¼äÃÔ|žy¹¡coo/"‚B2”™-zŒaÓµz>I‰&d¬`Œ0 s­%m¡)¶Œ)!0Ö¢Œ«SJ(j§MVÈEÉøQïÂd(¶ÂÍÙ›ùÜŸ£Ío{ÌŠýs¥Χ±wï^Ü&¾)?þbÂ¥PP°½iÕ]§·¯G¯Ô—º]šÁ¨ÚâE`aJãÂׄ#£ÕÅù£ŒJèIŠ]}&(`gÇNÚü¶ÈŠí]Ìl)¼)ÞòÇÑ­[·V/ƒœ¸Á»ƒÕúbc¬™ÏÚâjvheŠuÙ\<ßÏ`­!¶†XܯMhót÷,²káöÂvvwìFDN//ZÛe㊋zJ©a9Тr³3Ý£3´óZÔOhÃd×u-Ý5Hâ#”Ó§V_˜ï[çÝk÷ Ÿ¤¹%w ÷_{?Ë‚eÖb(¥N]LÕjp/Ü'HgA¯üð®æß+”ÒS*&ªÚÈ‚:™ÌÿAÞ€vÁÜ‹hÉo •ò¨`Âbû®”y¸Š£Õ©ˆJ©Í õ…êâ«Qo‰üÆ‚G” rœäÿ "¸2õ‡«3êNE@¯ ½r©àXÒÿî©›ö*4 h h hàgÿET§L›XtEXtCopyrightCC0 Public Domain Dedication http://creativecommons.org/publicdomain/zero/1.0/Æã½ù%tEXtdate:create2019-07-19T21:20:12+00:00ûPæ‡%tEXtdate:modify2019-07-19T21:06:58+00:00ÿEÆ tEXtSoftwarewww.inkscape.org›î<IEND®B`‚gtkterm-1.1.1/data/meson.build000066400000000000000000000025221376216657300162630ustar00rootroot00000000000000gnome = import('gnome') # Glade UI files gresources = gnome.compile_resources('resource', 'gresource.xml', source_dir: '.') # Desktop file desktop_config = configuration_data() desktop_config.set('VERSION', meson.project_version()) desktop_file_configured = configure_file( input: 'gtkterm.desktop.in', output: 'gtkterm.desktop', configuration: desktop_config, install_dir: join_paths( datadir, 'applications', ) ) desktop_file_validate = find_program('desktop-file-validate', required: false) if desktop_file_validate.found() test( 'desktop file test', desktop_file_validate, args: [ desktop_file_configured ] ) endif # Icon install_data('gtkterm_256x256.png', install_dir: join_paths(datadir, 'icons', 'hicolor', '256x256', 'apps'), rename : 'gtkterm.png' ) install_data('gtkterm_128x128.png', install_dir: join_paths(datadir, 'icons', 'hicolor', '128x128', 'apps'), rename : 'gtkterm.png' ) install_data('gtkterm_64x64.png', install_dir: join_paths(datadir, 'icons', 'hicolor', '64x64', 'apps'), rename : 'gtkterm.png' ) install_data('gtkterm_48x48.png', install_dir: join_paths(datadir, 'icons', 'hicolor', '48x48', 'apps'), rename : 'gtkterm.png' ) install_data('gtkterm_48x48.png', install_dir: join_paths(datadir, 'icons', 'hicolor', '48x48', 'apps'), rename : 'gtkterm.png' ) # Manpage install_man('gtkterm.1') gtkterm-1.1.1/meson.build000066400000000000000000000017301376216657300153520ustar00rootroot00000000000000project( 'gtkterm', 'c', version: '1.1.1', meson_version : '>= 0.46.0' ) # Find dependencies gtk_deps = dependency('gtk+-3.0', version : '>= 3.0.0') vte_deps = dependency('vte-2.91', version : '>= 0.28.0') gudev_deps = dependency('gudev-1.0', version: '>= 230') # Find install paths prefix = get_option('prefix') datadir = join_paths(prefix, get_option('datadir')) localedir = join_paths(prefix, get_option('localedir')) # Configure GTKTerm conf = configuration_data() conf.set_quoted('VERSION', meson.project_version()) conf.set_quoted('PACKAGE', meson.project_name()) conf.set_quoted('RELEASE_DATE', 'December 2020') conf.set_quoted('LOCALEDIR', localedir) cc = meson.get_compiler('c') have_serial_h = cc.has_header('linux/serial.h') if have_serial_h conf.set('HAVE_LINUX_SERIAL_H', '1') endif configure_file(output : 'config.h', configuration : conf) config = declare_dependency(include_directories : include_directories('.')) subdir('data') subdir('src') subdir('po') gtkterm-1.1.1/po/000077500000000000000000000000001376216657300136255ustar00rootroot00000000000000gtkterm-1.1.1/po/LINGUAS000066400000000000000000000000311376216657300146440ustar00rootroot00000000000000fr hu ru de zh_CN nl_NL gtkterm-1.1.1/po/POTFILES.in000066400000000000000000000004621376216657300154040ustar00rootroot00000000000000# List of source files containing translatable strings. # Copyright (C) 1995 Free Software Foundation, Inc. # Package source files src/buffer.c src/cmdline.c src/device_monitor.c src/files.c src/gtkterm.c src/i18n.c src/interface.c src/logging.c src/macros.c src/parsecfg.c src/serial.c src/term_config.c gtkterm-1.1.1/po/POTFILES.skip000066400000000000000000000000371376216657300157420ustar00rootroot00000000000000data/config_terminal_dialog.ui gtkterm-1.1.1/po/de.po000066400000000000000000000450561376216657300145670ustar00rootroot00000000000000# Translation of gtkterm to German # Copyright (C) 2002 Sebastien Bacher. # This file is distributed under the same license as the gtkterm package. # Chris Leick , 2010. # Markus Hiereth , 2020. msgid "" msgstr "" "Project-Id-Version: gtkterm 1.1-1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2020-03-09 10:39+0100\n" "PO-Revision-Date: 2020-11-13 19:21+0200\n" "Last-Translator: Markus Hiereth \n" "Language-Team: debian-l10n-german \n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Virtaal 0.7.1\n" #: ../src/buffer.c:164 msgid "ERROR : Buffer is not initialized !\n" msgstr "FEHLER: Puffer ist nicht initialisiert!\n" #: ../src/cmdline.c:37 #, c-format msgid "" "\n" "GTKTerm version %s\n" msgstr "" "\n" "GTKTerm-Version %s\n" #: ../src/cmdline.c:38 msgid "\t (c) Julien Schmitt\n" msgstr "\t (c) Julien Schmitt\n" #: ../src/cmdline.c:39 msgid "" "\n" "This program is released under the terms of the GPL V.2\n" msgstr "" "\n" "Dieses Programm wird unter den Bedingungen der GPL V.2 veröffentlicht\n" #: ../src/cmdline.c:40 msgid "\t ** Use at your own risks ! **\n" msgstr "\t ** Gebrauch auf eigenes Risiko! **\n" #: ../src/cmdline.c:41 msgid "" "\n" "Command line options\n" msgstr "" "\n" "Befehlszeilenoptionen\n" #: ../src/cmdline.c:42 msgid "--help or -h : this help screen\n" msgstr "--help oder -h: Diese Hilfe ausgeben\n" #: ../src/cmdline.c:43 msgid "--config or -c : load configuration\n" msgstr "--config oder -c: Konfiguration laden\n" #: ../src/cmdline.c:44 msgid "--port or -p : serial port device (default /dev/ttyS0)\n" msgstr "--port oder -p: serieller Port (/dev/ttyS0 ist voreingestellt)\n" #: ../src/cmdline.c:45 msgid "--speed or -s : serial port speed (default 9600)\n" msgstr "" "--speed oder -s: Übertragungsrate des seriellen Ports\n" "(9600 ist voreingestellt)\n" #: ../src/cmdline.c:46 msgid "--bits or -b : number of bits (default 8)\n" msgstr "--bits oder -b: Anzahl der Bits (Voreinstellung ist 8)\n" #: ../src/cmdline.c:47 msgid "--stopbits or -t : number of stopbits (default 1)\n" msgstr "" "--stopbits oder -t: Anzahl der Stoppbits (Voreinstellung ist 1)\n" #: ../src/cmdline.c:48 msgid "--parity or -a : parity (default none)\n" msgstr "--parity oder -a: Parität (ohne ist voreingestellt)\n" #: ../src/cmdline.c:49 msgid "--flow or -w : flow control (default none)\n" msgstr "" "--flow oder -w: Fluss-Steuerung (ohne ist voreingestellt)\n" #: ../src/cmdline.c:50 msgid "--delay or -d : end of line delay in ms (default none)\n" msgstr "" "--delay oder -d: Verzögerung am Zeilenende in ms. (keine ist voreingestellt)\n" #: ../src/cmdline.c:51 msgid "" "--char or -r : wait for a special char at end of line (default none)\n" msgstr "" "--char oder -r: erwarte ein spezielles Zeichen als Zeilenende " "(Kein Zeichen ist voreingestellt)\n" #: ../src/cmdline.c:52 msgid "--file or -f : default file to send (default none)\n" msgstr "" "--file oder -f: standardmäßig zu sendende Datei (keine ist " "voreingestellt)\n" #: ../src/cmdline.c:53 msgid "" "--rts_time_before or -x : for RS-485, time in ms before transmit with " "rts on\n" msgstr "" "--rts_time_before oder -x : für RS-485: Zeit in Millisekunden mit »rts " "on«, ehe Daten übertragen werden\n" #: ../src/cmdline.c:54 msgid "" "--rts_time_after or -y : for RS-485, time in ms after transmit with rts " "on\n" msgstr "" "--rts_time_after oder -y : für RS-485: Zeit in Millisekunden mit »rts " "on« nach der Übertragung\n" #: ../src/cmdline.c:55 msgid "--echo or -e : switch on local echo\n" msgstr "--echo oder -e: Lokales Echo anschalten\n" #: ../src/cmdline.c:56 msgid "" "--disable-port-lock or -L: does not lock serial port. Allows to send to " "serial port from different terminals\n" msgstr "" "--disable-port-lock oder -L: den seriellen Port nicht sperren. Dies erlaubt, " "von verschiedenen Terminals aus an einen seriellen Port zu senden\n" #: ../src/cmdline.c:57 msgid "" " Note: incoming data are displayed randomly on only " "one terminal\n" msgstr "" " Beachten Sie: Eingehende Daten werden nur auf einem " "Terminal angezeigt; auf welchem ist nicht vorhersehbar\n" #: ../src/cmdline.c:167 msgid "Undefined command line option\n" msgstr "Befehlszeilenoption wurde nicht verstanden\n" #: ../src/files.c:77 msgid "Send RAW File" msgstr "Sende rohe Datei" #: ../src/files.c:96 #, c-format msgid "Error opening file\n" msgstr "Fehler beim Öffnen der Datei\n" #: ../src/files.c:110 #, c-format msgid "%s : transfer in progress..." msgstr "%s: Übertragung im Gang ..." #: ../src/files.c:128 msgid "Cancel" msgstr "Abbrechen" #: ../src/files.c:143 #, c-format msgid "Cannot read file %s: %s\n" msgstr "Datei %s kann nicht gelesen werden: %s\n" #: ../src/files.c:178 #, c-format msgid "Error sending file\n" msgstr "Fehler beim Senden der Datei\n" #: ../src/files.c:206 #, c-format msgid "Error sending file: %s\n" msgstr "Fehler beim Senden der Datei: %s\n" #: ../src/files.c:292 msgid "Save RAW File" msgstr "Speichere rohe Datei" #: ../src/files.c:311 #, c-format msgid "File error\n" msgstr "Dateifehler\n" #: ../src/files.c:322 ../src/logging.c:68 ../src/logging.c:123 #, c-format msgid "Cannot open file %s: %s\n" msgstr "Datei %s kann nicht geöffnet werden: %s\n" #. Toplevel #: ../src/interface.c:145 msgid "_File" msgstr "/_Datei" #: ../src/interface.c:146 msgid "_Edit" msgstr "/_Bearbeiten" #: ../src/interface.c:147 msgid "_Log" msgstr "/_Logging" #: ../src/interface.c:148 msgid "_Configuration" msgstr "/_Konfiguration" #: ../src/interface.c:149 msgid "Control _signals" msgstr "/_Steuersignale" #: ../src/interface.c:150 msgid "_View" msgstr "/_Ansicht" #: ../src/interface.c:151 msgid "Hexadecimal _chars" msgstr "/Ansicht/Hexadezimale _Zeichen" #: ../src/interface.c:152 msgid "_Help" msgstr "/_Hilfe" #: ../src/interface.c:156 msgid "_Clear screen" msgstr "/Datei/Bildschirm _leeren" #: ../src/interface.c:157 msgid "_Clear scrollback" msgstr "/Datei/_Verlaufsspeicher leeren" #: ../src/interface.c:158 msgid "Send _RAW file" msgstr "/Datei/Rohe Datei sen_den" #: ../src/interface.c:159 msgid "_Save RAW file" msgstr "/Datei/Rohe Datei _speichern" #. Log Menu #: ../src/interface.c:167 msgid "To file..." msgstr "/Logging/_In Datei ..." #. Confuguration Menu #: ../src/interface.c:173 msgid "_Port" msgstr "/Konfiguration/_Port" #: ../src/interface.c:174 msgid "_Main window" msgstr "/Konfiguration/_Hauptfenster" #: ../src/interface.c:175 msgid "_Macros" msgstr "/Konfiguration/_Makros" #: ../src/interface.c:176 msgid "_Load configuration" msgstr "/Konfiguration/Konfiguration _laden" #: ../src/interface.c:177 msgid "_Save configuration" msgstr "/Konfiguration/Konfiguration _speichern" #: ../src/interface.c:178 msgid "_Delete configuration" msgstr "/Konfiguration/Konfiguration lös_chen" #. Signals Menu #: ../src/interface.c:181 msgid "Send break" msgstr "/Steuersignale/Pause _senden" #: ../src/interface.c:182 msgid "_Open Port" msgstr "/Steuersignale/Port _öffnen" #: ../src/interface.c:183 msgid "_Close Port" msgstr "/Steuersignale/Port s_chließen" #: ../src/interface.c:184 msgid "Toggle DTR" msgstr "/Steuersignale/_DTR-Umschaltung" #: ../src/interface.c:185 msgid "Toggle RTS" msgstr "/Steuersignale/_RTS-Umschaltung" #. Configuration Menu #: ../src/interface.c:194 msgid "Local _echo" msgstr "/Konfiguration/Lokales _Echo" #: ../src/interface.c:195 msgid "_CR LF auto" msgstr "/Konfiguration/CR-LF-_Automatik" #: ../src/interface.c:196 msgid "Timestamp" msgstr "/Konfiguration/_Zeitstempel" #. View Menu #: ../src/interface.c:199 msgid "Show _index" msgstr "/Ansicht/Zeige _Index" #: ../src/interface.c:200 msgid "_Send hexadecimal data" msgstr "/Ansicht/Hexadezimale Daten sen_den" #: ../src/interface.c:205 msgid "_ASCII" msgstr "/Ansicht/_ASCII" #: ../src/interface.c:206 msgid "_Hexadecimal" msgstr "/Ansicht/He_xadezimal" #. technischen Hintergrund klären: Fehlen Menütexte in Zeilen 168-170 von interface.c? #: ../src/interface.c:422 msgid "Resume" msgstr "/Logging/_Wieder beginnen" #: ../src/interface.c:567 msgid "Hexadecimal data to send (separator : ';' or space) : " msgstr "Zu sendende hexadezimale Daten (getrennt durch Strichpunkt oder Leerzeichen):" #: ../src/interface.c:736 msgid "" "GTKTerm is a simple GTK+ terminal used to communicate with the serial port." msgstr "" "GTKTerm ist ein einfaches GTK+-Terminal für die Kommunikation über den " "seriellen Port." #: ../src/interface.c:776 msgid "Break signal sent!" msgstr "Pause-Signal gesendet!" #: ../src/interface.c:882 #, c-format msgid "0 byte(s) sent!" msgstr "0 Byte gesendet!" #: ../src/interface.c:896 msgid "Improper formatted hex input, 0 bytes sent!" msgstr "Eingabe war nicht hexadezimal, 0 Byte gesendet!" #: ../src/interface.c:907 #, c-format msgid "%d byte(s) sent!" msgstr "%d Byte gesendet!" #: ../src/logging.c:49 #, c-format msgid "Filename error\n" msgstr "Fehlerhafter Dateiname\n" #: ../src/logging.c:88 msgid "Log file selection" msgstr "Auswahl der Logdatei" #: ../src/logging.c:184 msgid "Failed to log data\n" msgstr "Fehlschlag beim Logging\n" #: ../src/macros.c:144 #, c-format msgid "Macro \"%s\" sent !" msgstr "Makro »%s« gesendet!" #: ../src/macros.c:275 msgid "Shortcut" msgstr "Kürzel" #: ../src/macros.c:432 msgid "" "The \"action\" field of a macro is the data to be sent on the port. Text can " "be entered, but also special chars, like \\n, \\t, \\r, etc. You can also " "enter hexadecimal data preceded by a '\\'. The hexadecimal data should not " "begin with a letter (eg. use \\0FF and not \\FF)\n" "Examples :\n" "\t\"Hello\\n\" sends \"Hello\" followed by a Line Feed\n" "\t\"Hello\\0A\" does the same thing but the LF is entered in hexadecimal" msgstr "" "Das »action«-Feld eines Makros enthält die Daten für den Port. Es kann Text " "eingegeben werden, aber auch Sonderzeichen wie \\n, \\t, " "\\r, etc. Sie können außerdem hexadezimale Daten mit vorangestelltem " "»\\« eingeben. Die hexadezimalen Daten sollten nicht mit einem Buchstaben " "beginnen (benutzen Sie z.B. \\0FF und nicht \\FF)\n" "Beispiele:\n" "\t»Hallo\\n« " "sendet »Hallo« gefolgt von einem Zeilenumbruch\n" "\t»Hallo\\OA« tut das Gleiche, aber der Zeilenumbruch ist hexadezimal " "eingegeben" #: ../src/macros.c:452 msgid "Configure Macros" msgstr "Makros konfigurieren" #: ../src/macros.c:489 msgid "_Add" msgstr "_Hinzufügen" #: ../src/macros.c:493 msgid "_Delete" msgstr "_Löschen" #: ../src/macros.c:497 msgid "_Capture Shortcut" msgstr "Kürzel _erfassen" #: ../src/parsecfg.c:355 #, c-format msgid "Cannot open configuration file `%s'.\n" msgstr "Die Konfigurationsdatei »%s« kann nicht geöffnet werden.\n" #: ../src/parsecfg.c:358 #, c-format msgid "Cannot create configuration file `%s'.\n" msgstr "Konfigurationsdatei »%s« kann nicht erstellt werden.\n" #: ../src/parsecfg.c:361 #, c-format msgid "" "%s(%d): %s\n" "Syntax error\n" msgstr "" "%s(%d): %s\n" "Syntax-Fehler\n" #: ../src/parsecfg.c:364 #, c-format msgid "" "%s(%d): %s\n" "Unrecognized parameter\n" msgstr "" "%s(%d): %s\n" "Parameter nicht erkannt\n" #: ../src/parsecfg.c:367 #, c-format msgid "" "%s(%d): %s\n" "Internal error\n" msgstr "" "%s(%d): %s\n" "Interner Fehler\n" #: ../src/parsecfg.c:370 #, c-format msgid "" "%s(%d): %s\n" "Invalid number\n" msgstr "" "%s(%d): %s\n" "Ungültige Nummer\n" #: ../src/parsecfg.c:373 #, c-format msgid "" "%s(%d): %s\n" "Out of range\n" msgstr "" "%s(%d): %s\n" "Außerhalb des Bereichs\n" #: ../src/parsecfg.c:376 #, c-format msgid "" "%s(%d): %s\n" "Cannot allocate memory.\n" msgstr "" "%s(%d): %s\n" "Speicher kann nicht bereitgestellt werden.\n" #: ../src/parsecfg.c:379 #, c-format msgid "" "%s(%d): %s\n" "It must be specified TRUE or FALSE.\n" msgstr "" "%s(%d): %s\n" "Es muss TRUE oder FALSE angegeben werden.\n" #: ../src/parsecfg.c:382 #, c-format msgid "" "%s(%d): %s\n" "The section name is already used.\n" msgstr "" "%s(%d): %s\n" "Der Abschnittsname wird bereits benutzt.\n" #: ../src/parsecfg.c:385 #, c-format msgid "" "%s(%d)\n" "There is no closing bracket.\n" msgstr "" "%s(%d)\n" "Die schließende Klammer fehlt.\n" #: ../src/parsecfg.c:390 #, c-format msgid "" "%s(%d): %s\n" "Unexplained error\n" msgstr "" "%s(%d): %s\n" "Ungeklärter Fehler\n" #: ../src/serial.c:154 #, c-format msgid "Cannot open %s: %s\n" msgstr "%s kann nicht geöffnet werden: %s\n" #: ../src/serial.c:167 #, c-format msgid "" "Cannot lock port! The serial port may currently be in use by another " "program.\n" msgstr "" "Der serielle Port kann nicht gesperrt werden. Ein anderes Programm könnte " "ihn in Gebrauch haben.\n" #: ../src/serial.c:235 #, c-format msgid "Arbitrary baud rates not supported" msgstr "Die Baudrate ist nicht frei wählbar" #: ../src/serial.c:352 ../src/serial.c:398 msgid "Control signals read" msgstr "Steuersignale gelesen" #: ../src/serial.c:364 msgid "DTR write" msgstr "DTR schreiben" #: ../src/serial.c:374 msgid "RTS write" msgstr "RTS schreiben" #: ../src/serial.c:452 msgid "No open port" msgstr "Kein offener Port" #: ../src/term_config.c:193 msgid "" "No serial devices found!\n" "\n" "Searched the following paths:\n" "\t/dev/ttyS*\n" "\t/dev/tts/*\n" "\t/dev/ttyUSB*\n" "\t/dev/usb/tts/*\n" "\n" "Enter a different device path in the 'Port' box.\n" msgstr "" "Keine Gerätedatei für seriellen Datentransfer gefunden!\n" "\n" "Gesucht wurde mit folgenden Mustern:\n" " /dev/ttyS*\n" " /dev/tts/*\n" " /dev/ttyUSB*\n" " /dev/usb/tts/*\n" "\n" "Geben Sie im Port-Eingabefeld einen anderen Pfad ein.\n" #: ../src/term_config.c:202 msgid "Configuration" msgstr "Konfiguration" #: ../src/term_config.c:206 msgid "Serial port" msgstr "Serieller Port" #: ../src/term_config.c:212 msgid "Port:" msgstr "Port:" #: ../src/term_config.c:214 msgid "Baud Rate:" msgstr "Baudrate:" #: ../src/term_config.c:216 msgid "Parity:" msgstr "Parität:" #: ../src/term_config.c:362 msgid "Bits:" msgstr "Bits:" #: ../src/term_config.c:364 msgid "Stopbits:" msgstr "Stoppbits:" #: ../src/term_config.c:366 msgid "Flow control:" msgstr "Fluss-Steuerung:" #. create an expander widget to hide the 'Advanced features' #: ../src/term_config.c:417 msgid "Advanced Configuration Options" msgstr "Erweiterte Konfigurationsoptionen " #: ../src/term_config.c:422 msgid "ASCII file transfer" msgstr "ASCII-Dateiübertragung" #: ../src/term_config.c:428 msgid "End of line delay (milliseconds):" msgstr "Verzögerung am Zeilenende (Millisekunden):" #: ../src/term_config.c:444 msgid "Wait for this special character before passing to next line:" msgstr "Auf dieses Sonderzeichen warten, bevor es zur nächsten Zeile geht:" #: ../src/term_config.c:457 msgid "RS-485 half-duplex parameters (RTS signal used to send)" msgstr "RS-485 Halb-duplex-Parameter (zum Senden wird RTS-Signal verwendet)" #: ../src/term_config.c:464 msgid "Time with RTS 'on' before transmit (milliseconds):" msgstr "Der Übertragung vorangehende Zeit mit RTS »ein« in Millisekunden" #: ../src/term_config.c:466 msgid "Time with RTS 'on' after transmit (milliseconds):" msgstr "Der Übertragung folgende Zeit mit RTS »ein« in Millisekunden" #: ../src/term_config.c:591 msgid "Load configuration" msgstr "Konfiguration laden" #: ../src/term_config.c:601 msgid "Delete configuration" msgstr "Konfiguration löschen" #: ../src/term_config.c:631 ../src/term_config.c:896 msgid "" "Cannot read configuration file!\n" "Config file may contain invalid parameter.\n" msgstr "" "Die Konfigurationsdatei kann nicht gelesen werden!\n" "Sie enthält womöglich ungültige Parameter.\n" #: ../src/term_config.c:637 msgid "Configurations" msgstr "Konfigurationen" #: ../src/term_config.c:704 msgid "Save configuration" msgstr "Konfiguration speichern" #: ../src/term_config.c:716 msgid "Configuration name: " msgstr "Konfigurationsname:" #: ../src/term_config.c:750 msgid "" "Cannot save configuration file!\n" "Config file may contain invalid parameter.\n" msgstr "" "Die Konfigurationsdatei kann nicht gespeichert werden!\n" "Sie enthält womöglich ungültige Parameter.\n" #: ../src/term_config.c:770 msgid "Cannot overwrite section!" msgstr "Abschnitt kann nicht überschrieben werden!" #: ../src/term_config.c:775 msgid "Cannot read configuration file!" msgstr "Konfigurationsdatei kann nicht gelesen werden." #: ../src/term_config.c:785 #, c-format msgid "Configuration [%s] saved\n" msgstr "Konfiguration [%s] gespeichert\n" #: ../src/term_config.c:804 msgid "" "Cannot write configuration file!\n" "Config file may contain invalid parameter.\n" msgstr "" "Die Konfigurationsdatei kann nicht geschrieben werden!\n" "Sie enthält womöglich ungültige Parameter.\n" #: ../src/term_config.c:819 #, c-format msgid "" "Section [%s] already exists.\n" "\n" "Do you want to overwrite it ?" msgstr "" "Abschnitt [%s] existiert bereits\n" "\n" "Möchten Sie ihn überschreiben?" #: ../src/term_config.c:879 msgid "Cannot delete section!" msgstr "Abschnitt kann nicht gelöscht werden!" #: ../src/term_config.c:1060 #, c-format msgid "No section \"%s\" in configuration file\n" msgstr "Kein Abschnitt [%s] in Konfigurationsdatei\n" #: ../src/term_config.c:1105 #, c-format msgid "Baudrate %d may not be supported by all hardware" msgstr "Nicht jede Hardware kann mit Baudrate %d betrieben werden" #: ../src/term_config.c:1112 #, c-format msgid "" "Invalid number of stop-bits: %d\n" "Falling back to default number of stop-bits number: %d\n" msgstr "" "Ungültige Stoppbit-Anzahl: %d\n" "Es wird die voreingestellte Anzahl Stoppbits verwendet: %d\n" #: ../src/term_config.c:1120 #, c-format msgid "" "Invalid number of bits: %d\n" "Falling back to default number of bits: %d\n" msgstr "" "Ungültige Bit-Anzahl: %d\n" "Es wird die voreingestellte Bit-Anzahl verwendet: %d\n" #: ../src/term_config.c:1128 #, c-format msgid "" "Invalid delay: %d ms\n" "Falling back to default delay: %d ms\n" msgstr "" "Ungültige Verzögerung: %d ms\n" "Es wird die voreingestellte Verzögerung verwendet: %d ms\n" #: ../src/term_config.c:1158 #, c-format msgid "" "Configuration file (%s) with\n" "[default] configuration has been created.\n" msgstr "" "Konfigurationsdatei (%s) erstellt. Der Abschnitt [default] enthält die " "Voreinstellungswerte.\n" #: ../src/term_config.c:1414 #, c-format msgid "Cannot find section %s\n" msgstr "Abschnitt %s kann nicht gefunden werden\n" #: ../src/term_config.c:1454 msgid "Main Window" msgstr "Hauptfenster" gtkterm-1.1.1/po/fr.po000066400000000000000000000520011376216657300145720ustar00rootroot00000000000000# French translations for gtkterm package # Traduction anglaise du package gtkterm. # Copyright (C) 2003 Julien Schmitt # This file is distributed under the same license as the gtkterm package. # Julien Schmitt , 2003, 2011. # msgid "" msgstr "" "Project-Id-Version: gtkterm 0.99.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2020-03-09 10:40+0100\n" "PO-Revision-Date: 2011-07-25 16:06+0200\n" "Last-Translator: Julien Schmitt \n" "Language-Team: French \n" "Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" #: ../src/buffer.c:164 msgid "ERROR : Buffer is not initialized !\n" msgstr "ERREUR : buffer non initialisé !\n" #: ../src/cmdline.c:37 #, c-format msgid "" "\n" "GTKTerm version %s\n" msgstr "" "\n" "GTKTerm version %s\n" #: ../src/cmdline.c:38 msgid "\t (c) Julien Schmitt\n" msgstr "\t (c) Julien Schmitt\n" #: ../src/cmdline.c:39 msgid "" "\n" "This program is released under the terms of the GPL V.2\n" msgstr "" "\n" "Ce programme est distribué selon les termes de la license GPL V.2\n" #: ../src/cmdline.c:40 msgid "\t ** Use at your own risks ! **\n" msgstr "\t ** Livré sans aucune garantie ! **\n" #: ../src/cmdline.c:41 msgid "" "\n" "Command line options\n" msgstr "" "\n" "Options de la ligne de commande\n" #: ../src/cmdline.c:42 msgid "--help or -h : this help screen\n" msgstr "--help or -h : cet écran d'aide\n" #: ../src/cmdline.c:43 msgid "--config or -c : load configuration\n" msgstr "--config ou -c : charger une configuration\n" #: ../src/cmdline.c:44 msgid "--port or -p : serial port device (default /dev/ttyS0)\n" msgstr "--port ou -p : device du port série (/dev/ttyS0 par défaut)\n" #: ../src/cmdline.c:45 msgid "--speed or -s : serial port speed (default 9600)\n" msgstr "--speed ou -s : vitesse du port série (9600 par défaut)\n" #: ../src/cmdline.c:46 msgid "--bits or -b : number of bits (default 8)\n" msgstr "--bits ou -b : nombre de bits (8 par défaut)\n" #: ../src/cmdline.c:47 msgid "--stopbits or -t : number of stopbits (default 1)\n" msgstr "--stopbits ou -t : nombre de bits de stop (1 par défaut)\n" #: ../src/cmdline.c:48 msgid "--parity or -a : parity (default none)\n" msgstr "--parity ou -a : partité (aucune par défaut)\n" #: ../src/cmdline.c:49 msgid "--flow or -w : flow control (default none)\n" msgstr "" "--flow ou -w : contrôle de flux (aucun par défaut)\n" #: ../src/cmdline.c:50 msgid "--delay or -d : end of line delay in ms (default none)\n" msgstr "--delay ou -d : délai de fin de ligne en ms (aucun par défaut)\n" #: ../src/cmdline.c:51 msgid "" "--char or -r : wait for a special char at end of line (default none)\n" msgstr "" "--char ou -r : caractère spécial à attendre en fin de ligne (aucun " "par défaut)\n" #: ../src/cmdline.c:52 msgid "--file or -f : default file to send (default none)\n" msgstr "" "--file ou -f : fichier par défaut à envoyer (aucun par défaut)\n" #: ../src/cmdline.c:53 msgid "" "--rts_time_before or -x : for RS-485, time in ms before transmit with " "rts on\n" msgstr "" "--rts_time_before ou -x : pour RS-485, temps en ms avant transmission " "avec rts activé\n" #: ../src/cmdline.c:54 msgid "" "--rts_time_after or -y : for RS-485, time in ms after transmit with rts " "on\n" msgstr "" "--rts_time_after ou -x : pour RS-485, temps en ms après transmission " "avec rts activé\n" #: ../src/cmdline.c:55 msgid "--echo or -e : switch on local echo\n" msgstr "--echo ou -e : écho local\n" #: ../src/cmdline.c:56 msgid "" "--disable-port-lock or -L: does not lock serial port. Allows to send to " "serial port from different terminals\n" msgstr "" #: ../src/cmdline.c:57 msgid "" " Note: incoming data are displayed randomly on only " "one terminal\n" msgstr "" #: ../src/cmdline.c:167 msgid "Undefined command line option\n" msgstr "Ligne de commande inconnue\n" #: ../src/files.c:77 msgid "Send RAW File" msgstr "" #: ../src/files.c:96 #, c-format msgid "Error opening file\n" msgstr "Erreur d'ouverture du fichier\n" #: ../src/files.c:110 #, c-format msgid "%s : transfer in progress..." msgstr "%s : transfert en cours..." #: ../src/files.c:128 msgid "Cancel" msgstr "Annuler" #: ../src/files.c:143 #, c-format msgid "Cannot read file %s: %s\n" msgstr "Impossible de lire le fichier %s : %s\n" #: ../src/files.c:178 #, fuzzy, c-format msgid "Error sending file\n" msgstr "Erreur d'ouverture du fichier\n" #: ../src/files.c:206 #, fuzzy, c-format msgid "Error sending file: %s\n" msgstr "Erreur d'ouverture du fichier\n" #: ../src/files.c:292 msgid "Save RAW File" msgstr "" #: ../src/files.c:311 #, c-format msgid "File error\n" msgstr "Erreur de fichier\n" #: ../src/files.c:322 ../src/logging.c:68 ../src/logging.c:123 #, c-format msgid "Cannot open file %s: %s\n" msgstr "Impossible d'ouvrir le fichier %s : %s\n" #. Toplevel #: ../src/interface.c:145 #, fuzzy msgid "_File" msgstr "_Fichier" #: ../src/interface.c:146 msgid "_Edit" msgstr "" #: ../src/interface.c:147 #, fuzzy msgid "_Log" msgstr "/_Log" #: ../src/interface.c:148 #, fuzzy msgid "_Configuration" msgstr "/_Configuration" #: ../src/interface.c:149 #, fuzzy msgid "Control _signals" msgstr "/_Signaux de contrôle" #: ../src/interface.c:150 #, fuzzy msgid "_View" msgstr "/_Vue" #: ../src/interface.c:151 #, fuzzy msgid "Hexadecimal _chars" msgstr "/Vue/_Largeur affichage hexadécimal" #: ../src/interface.c:152 #, fuzzy msgid "_Help" msgstr "_Aide" #: ../src/interface.c:156 #, fuzzy msgid "_Clear screen" msgstr "/Fichier/Effacer l'écran" #: ../src/interface.c:157 msgid "_Clear scrollback" msgstr "" #: ../src/interface.c:158 #, fuzzy msgid "Send _RAW file" msgstr "/Fichier/Envoi de _fichier brut" #: ../src/interface.c:159 #, fuzzy msgid "_Save RAW file" msgstr "/Fichier/_Sauvegarde en fichier brut" #. Log Menu #: ../src/interface.c:167 #, fuzzy msgid "To file..." msgstr "/Log/Dans le fichier..." #. Confuguration Menu #: ../src/interface.c:173 #, fuzzy msgid "_Port" msgstr "Port :" #: ../src/interface.c:174 #, fuzzy msgid "_Main window" msgstr "/Configuration/_Fenêtre prncipale" #: ../src/interface.c:175 msgid "_Macros" msgstr "" #: ../src/interface.c:176 #, fuzzy msgid "_Load configuration" msgstr "Charger une configuration" #: ../src/interface.c:177 #, fuzzy msgid "_Save configuration" msgstr "Sauvegarde de la configuration" #: ../src/interface.c:178 #, fuzzy msgid "_Delete configuration" msgstr "Supprimer une configuration" #. Signals Menu #: ../src/interface.c:181 msgid "Send break" msgstr "" #: ../src/interface.c:182 #, fuzzy msgid "_Open Port" msgstr "Aucun port ouvert" #: ../src/interface.c:183 msgid "_Close Port" msgstr "" #: ../src/interface.c:184 msgid "Toggle DTR" msgstr "" #: ../src/interface.c:185 msgid "Toggle RTS" msgstr "" #. Configuration Menu #: ../src/interface.c:194 msgid "Local _echo" msgstr "" #: ../src/interface.c:195 msgid "_CR LF auto" msgstr "" #: ../src/interface.c:196 msgid "Timestamp" msgstr "" #. View Menu #: ../src/interface.c:199 #, fuzzy msgid "Show _index" msgstr "/Vue/Afficher l'index" #: ../src/interface.c:200 #, fuzzy msgid "_Send hexadecimal data" msgstr "/Vue/_Envoi d'hexadécimal" #: ../src/interface.c:205 #, fuzzy msgid "_ASCII" msgstr "/Vue/_ASCII" #: ../src/interface.c:206 #, fuzzy msgid "_Hexadecimal" msgstr "/Vue/_Hexadécimal" #: ../src/interface.c:422 msgid "Resume" msgstr "Reprendre" #: ../src/interface.c:567 msgid "Hexadecimal data to send (separator : ';' or space) : " msgstr "Donnée hexadécimale à envoyer (séparateur : ';' ou espace) : " #: ../src/interface.c:736 msgid "" "GTKTerm is a simple GTK+ terminal used to communicate with the serial port." msgstr "" #: ../src/interface.c:776 msgid "Break signal sent!" msgstr "Signal break envoyé !" #: ../src/interface.c:882 #, c-format msgid "0 byte(s) sent!" msgstr "0 octet(s) envoyé(s) !" #: ../src/interface.c:896 msgid "Improper formatted hex input, 0 bytes sent!" msgstr "" #: ../src/interface.c:907 #, fuzzy, c-format msgid "%d byte(s) sent!" msgstr "0 octet(s) envoyé(s) !" #: ../src/logging.c:49 #, c-format msgid "Filename error\n" msgstr "Erreur du nom du fichier\n" #: ../src/logging.c:88 msgid "Log file selection" msgstr "Sélection du fichier de log" #: ../src/logging.c:184 msgid "Failed to log data\n" msgstr "Échec du log des données\n" #: ../src/macros.c:144 #, c-format msgid "Macro \"%s\" sent !" msgstr "Macro \"%s\" envoyée !" #: ../src/macros.c:275 msgid "Shortcut" msgstr "Raccourci" #: ../src/macros.c:432 msgid "" "The \"action\" field of a macro is the data to be sent on the port. Text can " "be entered, but also special chars, like \\n, \\t, \\r, etc. You can also " "enter hexadecimal data preceded by a '\\'. The hexadecimal data should not " "begin with a letter (eg. use \\0FF and not \\FF)\n" "Examples :\n" "\t\"Hello\\n\" sends \"Hello\" followed by a Line Feed\n" "\t\"Hello\\0A\" does the same thing but the LF is entered in hexadecimal" msgstr "" "Le champ \"action\" de la macro est la donnée à envoyer sur le port. Du " "texte peut être entré, mais aussi des caractères spéciaux, comme \\n, \\t, " "\\r, etc. Vous pouvez aussi entrer un nombre hexadecimal précédé par un " "'\\'. La donnée hexadecimale ne doit pas commencer par une lettre (utiliser " "\\0FF et pas \\FF par exemple)\n" "Exemples :\n" "\t\"Bonjour\\n\" envoie \"Bonjour\" suivi d'un retour à la ligne (LF)\n" "\t\"Bonjour\\0A\" fait la même chose..." #: ../src/macros.c:452 msgid "Configure Macros" msgstr "Configuration des Macros" #: ../src/macros.c:489 msgid "_Add" msgstr "_Ajouter" #: ../src/macros.c:493 msgid "_Delete" msgstr "_Supprimer" #: ../src/macros.c:497 msgid "_Capture Shortcut" msgstr "_Capture le raccourci" #: ../src/parsecfg.c:355 #, c-format msgid "Cannot open configuration file `%s'.\n" msgstr "Ne peut ouvrir le fichier de configuration `%s'.\n" #: ../src/parsecfg.c:358 #, c-format msgid "Cannot create configuration file `%s'.\n" msgstr "Ne peut créer le fichier de configuration `%s'.\n" #: ../src/parsecfg.c:361 #, c-format msgid "" "%s(%d): %s\n" "Syntax error\n" msgstr "" "%s(%d): %s\n" "Erreur de syntaxe\n" #: ../src/parsecfg.c:364 #, c-format msgid "" "%s(%d): %s\n" "Unrecognized parameter\n" msgstr "" "%s(%d): %s\n" "Paramètre inconnu\n" #: ../src/parsecfg.c:367 #, c-format msgid "" "%s(%d): %s\n" "Internal error\n" msgstr "" "%s(%d): %s\n" "Erreur interne\n" #: ../src/parsecfg.c:370 #, c-format msgid "" "%s(%d): %s\n" "Invalid number\n" msgstr "" "%s(%d): %s\n" "Nombre invalide\n" #: ../src/parsecfg.c:373 #, c-format msgid "" "%s(%d): %s\n" "Out of range\n" msgstr "" "%s(%d): %s\n" "En dehors des limites\n" #: ../src/parsecfg.c:376 #, c-format msgid "" "%s(%d): %s\n" "Cannot allocate memory.\n" msgstr "" "%s(%d): %s\n" "Ne peut allouer la mémoire\n" #: ../src/parsecfg.c:379 #, c-format msgid "" "%s(%d): %s\n" "It must be specified TRUE or FALSE.\n" msgstr "" "%s(%d): %s\n" "Il faut spécifier TRUE ou FALSE.\n" #: ../src/parsecfg.c:382 #, c-format msgid "" "%s(%d): %s\n" "The section name is already used.\n" msgstr "" "%s(%d): %s\n" "Le nom de section est déjà utilisé\n" #: ../src/parsecfg.c:385 #, c-format msgid "" "%s(%d)\n" "There is no closing bracket.\n" msgstr "" "%s(%d)\n" "Il n'y a pas de crochet pour fermer l'expression.\n" #: ../src/parsecfg.c:390 #, c-format msgid "" "%s(%d): %s\n" "Unexplained error\n" msgstr "" "%s(%d): %s\n" "Erreur inconnue\n" #: ../src/serial.c:154 #, c-format msgid "Cannot open %s: %s\n" msgstr "Impossible d'ouvrir %s : %s\n" #: ../src/serial.c:167 #, c-format msgid "" "Cannot lock port! The serial port may currently be in use by another " "program.\n" msgstr "" #: ../src/serial.c:235 #, c-format msgid "Arbitrary baud rates not supported" msgstr "" #: ../src/serial.c:352 ../src/serial.c:398 msgid "Control signals read" msgstr "Lecture des signaux de contrôle" #: ../src/serial.c:364 msgid "DTR write" msgstr "Ecriture de DTR" #: ../src/serial.c:374 msgid "RTS write" msgstr "Ecriture de RTS" #: ../src/serial.c:452 msgid "No open port" msgstr "Aucun port ouvert" #: ../src/term_config.c:193 #, fuzzy msgid "" "No serial devices found!\n" "\n" "Searched the following device path patterns:\n" "\t/dev/ttyS*\n" "\t/dev/tts/*\n" "\t/dev/ttyUSB*\n" "\t/dev/usb/tts/*\n" "\n" "Enter a different device path in the 'Port' box.\n" msgstr "" "Aucun périphérique série trouvé !\n" "\n" "Recherche parmi les périphériques suivants :\n" "/dev/ttyS*\n" "/dev/tts/*\n" "/dev/ttyUSB*\n" "/dev/usb/tts/*\n" "\n" "Saisissez un autre périphérique dans la boîte 'Port'.\n" #: ../src/term_config.c:202 msgid "Configuration" msgstr "Configuration" #: ../src/term_config.c:206 msgid "Serial port" msgstr "Port série" #: ../src/term_config.c:212 msgid "Port:" msgstr "Port :" #: ../src/term_config.c:214 msgid "Baud Rate:" msgstr "" #: ../src/term_config.c:216 msgid "Parity:" msgstr "Parité :" #: ../src/term_config.c:362 msgid "Bits:" msgstr "Bits :" #: ../src/term_config.c:364 msgid "Stopbits:" msgstr "Bits de stop :" #: ../src/term_config.c:366 msgid "Flow control:" msgstr "Contrôle de flux :" #. create an expander widget to hide the 'Advanced features' #: ../src/term_config.c:417 msgid "Advanced Configuration Options" msgstr "Options de configurations avancées" #: ../src/term_config.c:422 msgid "ASCII file transfer" msgstr "Transfert de fichier ASCII" #: ../src/term_config.c:428 msgid "End of line delay (milliseconds):" msgstr "Délai de fin de ligne (millisecondes) :" #: ../src/term_config.c:444 msgid "Wait for this special character before passing to next line:" msgstr "Attendre le caractère suivant avant de passer à la ligne suivante :" #: ../src/term_config.c:457 msgid "RS-485 half-duplex parameters (RTS signal used to send)" msgstr "" #: ../src/term_config.c:464 msgid "Time with RTS 'on' before transmit (milliseconds):" msgstr "" #: ../src/term_config.c:466 msgid "Time with RTS 'on' after transmit (milliseconds):" msgstr "" #: ../src/term_config.c:591 msgid "Load configuration" msgstr "Charger une configuration" #: ../src/term_config.c:601 msgid "Delete configuration" msgstr "Supprimer une configuration" #: ../src/term_config.c:631 ../src/term_config.c:896 msgid "" "Cannot read configuration file!\n" "Config file may contain invalid parameter.\n" msgstr "" #: ../src/term_config.c:637 msgid "Configurations" msgstr "Configurations" #: ../src/term_config.c:704 msgid "Save configuration" msgstr "Sauvegarde de la configuration" #: ../src/term_config.c:716 msgid "Configuration name: " msgstr "Nom de la configuration : " #: ../src/term_config.c:750 msgid "" "Cannot save configuration file!\n" "Config file may contain invalid parameter.\n" msgstr "" #: ../src/term_config.c:770 msgid "Cannot overwrite section!" msgstr "Impossible d'écraser la section !" #: ../src/term_config.c:775 msgid "Cannot read configuration file!" msgstr "Impossible de lire le fichier de configuration !" #: ../src/term_config.c:785 #, c-format msgid "Configuration [%s] saved\n" msgstr "Configuration [%s] sauvée\n" #: ../src/term_config.c:804 msgid "" "Cannot write configuration file!\n" "Config file may contain invalid parameter.\n" msgstr "" #: ../src/term_config.c:819 #, fuzzy, c-format msgid "" "Section [%s] already exists.\n" "\n" "Do you want to overwrite it ?" msgstr "" "\n" "La section [%s] existe déjà.\n" "Voulez vous l'écraser ?\n" #: ../src/term_config.c:879 msgid "Cannot delete section!" msgstr "Impossible de supprimer la section !" #: ../src/term_config.c:1060 #, c-format msgid "No section \"%s\" in configuration file\n" msgstr "Pas de section \"%s\" dans le fichier de configuration\n" #: ../src/term_config.c:1105 #, c-format msgid "Baudrate %d may not be supported by all hardware" msgstr "" #: ../src/term_config.c:1112 #, c-format msgid "" "Invalid number of stop-bits: %d\n" "Falling back to default number of stop-bits number: %d\n" msgstr "" "Nombre de bits de stop impossible : %d\n" "Retour au nombre de bits de stop par défaut : %d\n" #: ../src/term_config.c:1120 #, c-format msgid "" "Invalid number of bits: %d\n" "Falling back to default number of bits: %d\n" msgstr "" "Nombre de bits impossible : %d\n" "Retour au nombre de bits par défaut : %d\n" #: ../src/term_config.c:1128 #, c-format msgid "" "Invalid delay: %d ms\n" "Falling back to default delay: %d ms\n" msgstr "" "Délai impossible : %d ms\n" "Retour au délai par défaut : %d ms\n" #: ../src/term_config.c:1158 #, c-format msgid "" "Configuration file (%s) with\n" "[default] configuration has been created.\n" msgstr "" "Le fichier de configuration %s a été créÂé\n" "avec une configuration [default].\n" #: ../src/term_config.c:1414 #, c-format msgid "Cannot find section %s\n" msgstr "Impossible de trouver la section %s\n" #: ../src/term_config.c:1454 msgid "Main Window" msgstr "" #~ msgid "File selection" #~ msgstr "Sélection de fichier" #~ msgid "OK" #~ msgstr "Ok" #~ msgid "Cannot write file %s\n" #~ msgstr "Impossible d'écrire le fichier %s\n" #~ msgid "Help on macros" #~ msgstr "Aide sur les macros" #~ msgid "Lockfile is stale. Overriding it..\n" #~ msgstr "Le fichier de lock est orphelin. Ecrasement...\n" #~ msgid "Device %s is locked.\n" #~ msgstr "Le device %s est vérouillé.\n" #~ msgid "Cannot create lockfile. Sorry.\n" #~ msgstr "Ne peut créer le fichier de lock, désolé\n" #~ msgid "/File/Separator" #~ msgstr "/Fichier/Separateur" #~ msgid "/File/E_xit" #~ msgstr "/Fichier/_Quitter" #~ msgid "/Edit/_Paste" #~ msgstr "/Édition/C_oller" #~ msgid "/Edit/_Copy" #~ msgstr "/Édition/_Copier" #~ msgid "/Edit/Copy _All" #~ msgstr "/Édition/Copier _tout" #~ msgid "/Log/Pause" #~ msgstr "/Log/Pause" #~ msgid "/Log/Stop" #~ msgstr "/Log/Stop" #~ msgid "/Log/Clear" #~ msgstr "/Log/Effacer" #~ msgid "/Configuration/_Port" #~ msgstr "/Configuration/_Port" #~ msgid "/Configuration/Local _echo" #~ msgstr "/Configuration/_Echo local" #~ msgid "/Configuration/_CR LF auto" #~ msgstr "/Configuration/_CR LF auto" #~ msgid "/Configuration/_Macros" #~ msgstr "/Configuration/_Macros" #~ msgid "/Configuration/Separator" #~ msgstr "/Configuration/Separateur" #~ msgid "/Configuration/_Load configuration" #~ msgstr "/Configuration/_Charger une configuration" #~ msgid "/Configuration/_Save configuration" #~ msgstr "/Configuration/_Enregistrer la configuration" #~ msgid "/Configuration/_Delete configuration" #~ msgstr "/Configuration/_Supprimer la configuration" #~ msgid "/Control signals/Send break" #~ msgstr "/Signaux de contrôle/Envoyer un break" #~ msgid "/Control signals/Toggle DTR" #~ msgstr "/Signaux de contrôle/Complémente DTR" #~ msgid "/Control signals/Toggle RTS" #~ msgstr "/Signaux de contrôle/Complémente RTS" #~ msgid "/View/Hexadecimal chars/_8" #~ msgstr "/Vue/Largeur affichage hexadécimal/_8" #~ msgid "/View/Hexadecimal chars/1_0" #~ msgstr "/Vue/Largeur affichage hexadécimal/1_0" #~ msgid "/View/Hexadecimal chars/_16" #~ msgstr "/Vue/Largeur affichage hexadécimal/_16" #~ msgid "/View/Hexadecimal chars/_24" #~ msgstr "/Vue/Largeur affichage hexadécimal/_24" #~ msgid "/View/Hexadecimal chars/_32" #~ msgstr "/Vue/Largeur affichage hexadécimal/_32" #~ msgid "/View/Separator" #~ msgstr "/Vue/Separateur" #~ msgid "/Help/_About..." #~ msgstr "/Aide/À _propos..." #~ msgid "Pause" #~ msgstr "Pause" #~ msgid "About..." #~ msgstr "à propos..." #~ msgid "" #~ "\n" #~ " GTKTerm V. %s \n" #~ "\n" #~ "\t(c) Julien Schmitt\n" #~ "\thttp://www.jls-info.com/julien/linux\n" #~ "\n" #~ "\tLatest Version Available on:\n" #~ "\thttps://fedorahosted.org/gtkterm/" #~ msgstr "" #~ "\n" #~ " GTKTerm V. %s \n" #~ "\n" #~ "\t(c) Julien Schmitt\n" #~ "\thttp://www.jls-info.com/julien/linux/index_fr.html\n" #~ "\n" #~ "\tDernière version disponible sur :\n" #~ "\thttps://fedorahosted.org/gtkterm/" #~ msgid "\"%s\" : %d byte(s) sent!" #~ msgstr "\"%s\" : %d octet(s) envoyé(s) !" #~ msgid "Font selection" #~ msgstr "Sélection de la police" #~ msgid "Cannot read configuration file!\n" #~ msgstr "Impossible de lire le fichier de configuration !\n" #~ msgid "Warning!" #~ msgstr "Attention !" #~ msgid "Terminal configuration" #~ msgstr "Configuration du Terminal" #~ msgid "\t http://www.jls-info.com/julien/linux\n" #~ msgstr "\t http://www.jls-info.com/julien/linux/index_fr.html\n" #~ msgid "Speed :" #~ msgstr "Vitesse :" #~ msgid "" #~ "Unknown speed : %d bauds\n" #~ "Falling back to default speed : %d bauds\n" #~ msgstr "" #~ "Vitesse inconnue : %d bauds\n" #~ "Sélection de la vitesse par défaut : %d bauds\n" #~ msgid "%v / %u Kb (%p %%)" #~ msgstr "%v / %u Ko (%p %%)" #~ msgid "%v / %u bytes (%p %%)" #~ msgstr "%v / %u octets (%p %%)" #~ msgid "/Configuration/Local echo" #~ msgstr "/Configuration/_Echo local" #~ msgid "/View/ASCII" #~ msgstr "/Vue/ASCII" #~ msgid "/View/Hexadecimal" #~ msgstr "/Vue/Hexadecimal" #~ msgid "/View/Hexadecimal chars" #~ msgstr "/Vue/_Largeur affichage hexadecimal" #~ msgid "/View/Show index" #~ msgstr "/Vue/Affichage de l'index" gtkterm-1.1.1/po/gtkterm.pot000066400000000000000000000300421376216657300160250ustar00rootroot00000000000000# 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: 2020-07-20 12:41+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" #: ../src/buffer.c:167 msgid "ERROR : Buffer is not initialized !\n" msgstr "" #: ../src/cmdline.c:37 #, c-format msgid "" "\n" "GTKTerm version %s\n" msgstr "" #: ../src/cmdline.c:38 msgid "\t (c) Julien Schmitt\n" msgstr "" #: ../src/cmdline.c:39 msgid "" "\n" "This program is released under the terms of the GPL V.2\n" msgstr "" #: ../src/cmdline.c:40 msgid "\t ** Use at your own risks ! **\n" msgstr "" #: ../src/cmdline.c:41 msgid "" "\n" "Command line options\n" msgstr "" #: ../src/cmdline.c:42 msgid "--help or -h : this help screen\n" msgstr "" #: ../src/cmdline.c:43 msgid "--config or -c : load configuration\n" msgstr "" #: ../src/cmdline.c:44 msgid "--port or -p : serial port device (default /dev/ttyS0)\n" msgstr "" #: ../src/cmdline.c:45 msgid "--speed or -s : serial port speed (default 9600)\n" msgstr "" #: ../src/cmdline.c:46 msgid "--bits or -b : number of bits (default 8)\n" msgstr "" #: ../src/cmdline.c:47 msgid "--stopbits or -t : number of stopbits (default 1)\n" msgstr "" #: ../src/cmdline.c:48 msgid "--parity or -a : parity (default none)\n" msgstr "" #: ../src/cmdline.c:49 msgid "--flow or -w : flow control (default none)\n" msgstr "" #: ../src/cmdline.c:50 msgid "--delay or -d : end of line delay in ms (default none)\n" msgstr "" #: ../src/cmdline.c:51 msgid "" "--char or -r : wait for a special char at end of line (default none)\n" msgstr "" #: ../src/cmdline.c:52 msgid "--file or -f : default file to send (default none)\n" msgstr "" #: ../src/cmdline.c:53 msgid "" "--rts_time_before or -x : for RS-485, time in ms before transmit with " "rts on\n" msgstr "" #: ../src/cmdline.c:54 msgid "" "--rts_time_after or -y : for RS-485, time in ms after transmit with rts " "on\n" msgstr "" #: ../src/cmdline.c:55 msgid "--echo or -e : switch on local echo\n" msgstr "" #: ../src/cmdline.c:56 msgid "" "--disable-port-lock or -L: does not lock serial port. Allows to send to " "serial port from different terminals\n" msgstr "" #: ../src/cmdline.c:57 msgid "" " Note: incoming data are displayed randomly on only " "one terminal\n" msgstr "" #: ../src/cmdline.c:167 msgid "Undefined command line option\n" msgstr "" #: ../src/files.c:77 msgid "Send RAW File" msgstr "" #: ../src/files.c:96 #, c-format msgid "Error opening file\n" msgstr "" #: ../src/files.c:110 #, c-format msgid "%s : transfer in progress..." msgstr "" #: ../src/files.c:128 msgid "Cancel" msgstr "" #: ../src/files.c:143 #, c-format msgid "Cannot read file %s: %s\n" msgstr "" #: ../src/files.c:178 #, c-format msgid "Error sending file\n" msgstr "" #: ../src/files.c:206 #, c-format msgid "Error sending file: %s\n" msgstr "" #: ../src/files.c:292 msgid "Save RAW File" msgstr "" #: ../src/files.c:311 #, c-format msgid "File error\n" msgstr "" #: ../src/files.c:322 ../src/logging.c:68 ../src/logging.c:123 #, c-format msgid "Cannot open file %s: %s\n" msgstr "" #. Toplevel #: ../src/interface.c:145 msgid "_File" msgstr "" #: ../src/interface.c:146 msgid "_Edit" msgstr "" #: ../src/interface.c:147 msgid "_Log" msgstr "" #: ../src/interface.c:148 msgid "_Configuration" msgstr "" #: ../src/interface.c:149 msgid "Control _signals" msgstr "" #: ../src/interface.c:150 msgid "_View" msgstr "" #: ../src/interface.c:151 msgid "Hexadecimal _chars" msgstr "" #: ../src/interface.c:152 msgid "_Help" msgstr "" #: ../src/interface.c:156 msgid "_Clear screen" msgstr "" #: ../src/interface.c:157 msgid "_Clear scrollback" msgstr "" #: ../src/interface.c:158 msgid "Send _RAW file" msgstr "" #: ../src/interface.c:159 msgid "_Save RAW file" msgstr "" #. Log Menu #: ../src/interface.c:167 msgid "To file..." msgstr "" #. Confuguration Menu #: ../src/interface.c:173 msgid "_Port" msgstr "" #: ../src/interface.c:174 msgid "_Main window" msgstr "" #: ../src/interface.c:175 msgid "_Macros" msgstr "" #: ../src/interface.c:176 msgid "_Load configuration" msgstr "" #: ../src/interface.c:177 msgid "_Save configuration" msgstr "" #: ../src/interface.c:178 msgid "_Delete configuration" msgstr "" #. Signals Menu #: ../src/interface.c:181 msgid "Send break" msgstr "" #: ../src/interface.c:182 msgid "_Open Port" msgstr "" #: ../src/interface.c:183 msgid "_Close Port" msgstr "" #: ../src/interface.c:184 msgid "Toggle DTR" msgstr "" #: ../src/interface.c:185 msgid "Toggle RTS" msgstr "" #. Configuration Menu #: ../src/interface.c:194 msgid "Local _echo" msgstr "" #: ../src/interface.c:195 msgid "_CR LF auto" msgstr "" #: ../src/interface.c:196 msgid "Timestamp" msgstr "" #. View Menu #: ../src/interface.c:199 msgid "Show _index" msgstr "" #: ../src/interface.c:200 msgid "_Send hexadecimal data" msgstr "" #: ../src/interface.c:205 msgid "_ASCII" msgstr "" #: ../src/interface.c:206 msgid "_Hexadecimal" msgstr "" #: ../src/interface.c:422 msgid "Resume" msgstr "" #: ../src/interface.c:567 msgid "Hexadecimal data to send (separator : ';' or space) : " msgstr "" #: ../src/interface.c:727 msgid "" "GTKTerm is a simple GTK+ terminal used to communicate with the serial port." msgstr "" #: ../src/interface.c:779 msgid "Break signal sent!" msgstr "" #: ../src/interface.c:885 #, c-format msgid "0 byte(s) sent!" msgstr "" #: ../src/interface.c:899 msgid "Improper formatted hex input, 0 bytes sent!" msgstr "" #: ../src/interface.c:910 #, c-format msgid "%d byte(s) sent!" msgstr "" #: ../src/logging.c:49 #, c-format msgid "Filename error\n" msgstr "" #: ../src/logging.c:88 msgid "Log file selection" msgstr "" #: ../src/logging.c:184 msgid "Failed to log data\n" msgstr "" #: ../src/macros.c:144 #, c-format msgid "Macro \"%s\" sent !" msgstr "" #: ../src/macros.c:275 msgid "Shortcut" msgstr "" #: ../src/macros.c:432 msgid "" "The \"action\" field of a macro is the data to be sent on the port. Text can " "be entered, but also special chars, like \\n, \\t, \\r, etc. You can also " "enter hexadecimal data preceded by a '\\'. The hexadecimal data should not " "begin with a letter (eg. use \\0FF and not \\FF)\n" "Examples :\n" "\t\"Hello\\n\" sends \"Hello\" followed by a Line Feed\n" "\t\"Hello\\0A\" does the same thing but the LF is entered in hexadecimal" msgstr "" #: ../src/macros.c:452 msgid "Configure Macros" msgstr "" #: ../src/macros.c:489 msgid "_Add" msgstr "" #: ../src/macros.c:493 msgid "_Delete" msgstr "" #: ../src/macros.c:497 msgid "_Capture Shortcut" msgstr "" #: ../src/parsecfg.c:355 #, c-format msgid "Cannot open configuration file `%s'.\n" msgstr "" #: ../src/parsecfg.c:358 #, c-format msgid "Cannot create configuration file `%s'.\n" msgstr "" #: ../src/parsecfg.c:361 #, c-format msgid "" "%s(%d): %s\n" "Syntax error\n" msgstr "" #: ../src/parsecfg.c:364 #, c-format msgid "" "%s(%d): %s\n" "Unrecognized parameter\n" msgstr "" #: ../src/parsecfg.c:367 #, c-format msgid "" "%s(%d): %s\n" "Internal error\n" msgstr "" #: ../src/parsecfg.c:370 #, c-format msgid "" "%s(%d): %s\n" "Invalid number\n" msgstr "" #: ../src/parsecfg.c:373 #, c-format msgid "" "%s(%d): %s\n" "Out of range\n" msgstr "" #: ../src/parsecfg.c:376 #, c-format msgid "" "%s(%d): %s\n" "Cannot allocate memory.\n" msgstr "" #: ../src/parsecfg.c:379 #, c-format msgid "" "%s(%d): %s\n" "It must be specified TRUE or FALSE.\n" msgstr "" #: ../src/parsecfg.c:382 #, c-format msgid "" "%s(%d): %s\n" "The section name is already used.\n" msgstr "" #: ../src/parsecfg.c:385 #, c-format msgid "" "%s(%d)\n" "There is no closing bracket.\n" msgstr "" #: ../src/parsecfg.c:390 #, c-format msgid "" "%s(%d): %s\n" "Unexplained error\n" msgstr "" #: ../src/serial.c:154 #, c-format msgid "Cannot open %s: %s\n" msgstr "" #: ../src/serial.c:167 #, c-format msgid "" "Cannot lock port! The serial port may currently be in use by another " "program.\n" msgstr "" #: ../src/serial.c:235 #, c-format msgid "Arbitrary baud rates not supported" msgstr "" #: ../src/serial.c:352 ../src/serial.c:398 msgid "Control signals read" msgstr "" #: ../src/serial.c:364 msgid "DTR write" msgstr "" #: ../src/serial.c:374 msgid "RTS write" msgstr "" #: ../src/serial.c:452 msgid "No open port" msgstr "" #: ../src/term_config.c:193 msgid "" "No serial devices found!\n" "\n" "Searched the following paths:\n" "\t/dev/ttyS*\n" "\t/dev/tts/*\n" "\t/dev/ttyUSB*\n" "\t/dev/usb/tts/*\n" "\n" "Enter a different device path in the 'Port' box.\n" msgstr "" #: ../src/term_config.c:202 msgid "Configuration" msgstr "" #: ../src/term_config.c:206 msgid "Serial port" msgstr "" #: ../src/term_config.c:212 msgid "Port:" msgstr "" #: ../src/term_config.c:214 msgid "Baud Rate:" msgstr "" #: ../src/term_config.c:216 msgid "Parity:" msgstr "" #: ../src/term_config.c:362 msgid "Bits:" msgstr "" #: ../src/term_config.c:364 msgid "Stopbits:" msgstr "" #: ../src/term_config.c:366 msgid "Flow control:" msgstr "" #. create an expander widget to hide the 'Advanced features' #: ../src/term_config.c:417 msgid "Advanced Configuration Options" msgstr "" #: ../src/term_config.c:422 msgid "ASCII file transfer" msgstr "" #: ../src/term_config.c:428 msgid "End of line delay (milliseconds):" msgstr "" #: ../src/term_config.c:444 msgid "Wait for this special character before passing to next line:" msgstr "" #: ../src/term_config.c:457 msgid "RS-485 half-duplex parameters (RTS signal used to send)" msgstr "" #: ../src/term_config.c:464 msgid "Time with RTS 'on' before transmit (milliseconds):" msgstr "" #: ../src/term_config.c:466 msgid "Time with RTS 'on' after transmit (milliseconds):" msgstr "" #: ../src/term_config.c:591 msgid "Load configuration" msgstr "" #: ../src/term_config.c:601 msgid "Delete configuration" msgstr "" #: ../src/term_config.c:631 ../src/term_config.c:896 msgid "" "Cannot read configuration file!\n" "Config file may contain invalid parameter.\n" msgstr "" #: ../src/term_config.c:637 msgid "Configurations" msgstr "" #: ../src/term_config.c:704 msgid "Save configuration" msgstr "" #: ../src/term_config.c:716 msgid "Configuration name: " msgstr "" #: ../src/term_config.c:750 msgid "" "Cannot save configuration file!\n" "Config file may contain invalid parameter.\n" msgstr "" #: ../src/term_config.c:770 msgid "Cannot overwrite section!" msgstr "" #: ../src/term_config.c:775 msgid "Cannot read configuration file!" msgstr "" #: ../src/term_config.c:785 #, c-format msgid "Configuration [%s] saved\n" msgstr "" #: ../src/term_config.c:804 msgid "" "Cannot write configuration file!\n" "Config file may contain invalid parameter.\n" msgstr "" #: ../src/term_config.c:819 #, c-format msgid "" "Section [%s] already exists.\n" "\n" "Do you want to overwrite it ?" msgstr "" #: ../src/term_config.c:879 msgid "Cannot delete section!" msgstr "" #: ../src/term_config.c:1060 #, c-format msgid "No section \"%s\" in configuration file\n" msgstr "" #: ../src/term_config.c:1105 #, c-format msgid "Baudrate %d may not be supported by all hardware" msgstr "" #: ../src/term_config.c:1112 #, c-format msgid "" "Invalid number of stop-bits: %d\n" "Falling back to default number of stop-bits number: %d\n" msgstr "" #: ../src/term_config.c:1120 #, c-format msgid "" "Invalid number of bits: %d\n" "Falling back to default number of bits: %d\n" msgstr "" #: ../src/term_config.c:1128 #, c-format msgid "" "Invalid delay: %d ms\n" "Falling back to default delay: %d ms\n" msgstr "" #: ../src/term_config.c:1158 #, c-format msgid "" "Configuration file (%s) with\n" "[default] configuration has been created.\n" msgstr "" #: ../src/term_config.c:1414 #, c-format msgid "Cannot find section %s\n" msgstr "" #: ../src/term_config.c:1454 msgid "Main Window" msgstr "" gtkterm-1.1.1/po/hu.po000066400000000000000000000473621376216657300146150ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR Julien Schmitt # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: gtkterm 0.99.4\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2020-03-09 10:41+0100\n" "PO-Revision-Date: 2005-03-09 21:17+0100\n" "Last-Translator: Bus Jozsef \n" "Language-Team: hu \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Language: Hungarian\n" "X-Poedit-Country: HUNGARY\n" "X-Poedit-SourceCharset: iso-8859-2\n" #: ../src/buffer.c:164 msgid "ERROR : Buffer is not initialized !\n" msgstr "HIBA: inicializálatlan buffer !\n" #: ../src/cmdline.c:37 #, c-format msgid "" "\n" "GTKTerm version %s\n" msgstr "" "\n" "GTKTerm verzió %s\n" #: ../src/cmdline.c:38 #, fuzzy msgid "\t (c) Julien Schmitt\n" msgstr "\t (c) Julien Schmitt - julien@jls-info.com\n" #: ../src/cmdline.c:39 msgid "" "\n" "This program is released under the terms of the GPL V.2\n" msgstr "" "\n" "A program GPL V.2 alatt terjeszthetÅ‘\n" #: ../src/cmdline.c:40 msgid "\t ** Use at your own risks ! **\n" msgstr "\t ** Csak saját felelÅ‘sségedre használd! **\n" #: ../src/cmdline.c:41 msgid "" "\n" "Command line options\n" msgstr "" "\n" "Parancssori opciók\n" #: ../src/cmdline.c:42 msgid "--help or -h : this help screen\n" msgstr "--help vagy -h : súgó megjelenítése\n" #: ../src/cmdline.c:43 msgid "--config or -c : load configuration\n" msgstr "--config vagy -c : konfiguráció betöltése\n" #: ../src/cmdline.c:44 msgid "--port or -p : serial port device (default /dev/ttyS0)\n" msgstr "--port vagy -p : soros port (alapértelmezett /dev/ttyS0)\n" #: ../src/cmdline.c:45 msgid "--speed or -s : serial port speed (default 9600)\n" msgstr "" "--speed vagy -s : soros port sebesség (alapértelmezett 9600)\n" #: ../src/cmdline.c:46 msgid "--bits or -b : number of bits (default 8)\n" msgstr "--bits vagy -b : bitek száma (alapértelmezett 8)\n" #: ../src/cmdline.c:47 msgid "--stopbits or -t : number of stopbits (default 1)\n" msgstr "--stopbits vagy -t : stop bitek száma (alapértelmezett 1)\n" #: ../src/cmdline.c:48 msgid "--parity or -a : parity (default none)\n" msgstr "" "--parity vagy -a : paritás (alapértelmezett " "none)\n" #: ../src/cmdline.c:49 #, fuzzy msgid "--flow or -w : flow control (default none)\n" msgstr "--flow vagy -w : folyamatvezérlés(nincs alapértelmezés)\n" #: ../src/cmdline.c:50 msgid "--delay or -d : end of line delay in ms (default none)\n" msgstr "" "--delay vagy -d : sorvége késleltetés (nincs " "alapértelmezés)\n" #: ../src/cmdline.c:51 msgid "" "--char or -r : wait for a special char at end of line (default none)\n" msgstr "" "--char vagy -r : speciális karakterre várakozás a sor végén " "(nincs alapértelmezés)\n" #: ../src/cmdline.c:52 msgid "--file or -f : default file to send (default none)\n" msgstr "" "--file vagy -f : megadott fájlt küld (nincs alapértelmezés)\n" #: ../src/cmdline.c:53 msgid "" "--rts_time_before or -x : for RS-485, time in ms before transmit with " "rts on\n" msgstr "" #: ../src/cmdline.c:54 msgid "" "--rts_time_after or -y : for RS-485, time in ms after transmit with rts " "on\n" msgstr "" #: ../src/cmdline.c:55 msgid "--echo or -e : switch on local echo\n" msgstr "--echo vagy -e : helyi visszhang bekapcsolása\n" #: ../src/cmdline.c:56 msgid "" "--disable-port-lock or -L: does not lock serial port. Allows to send to " "serial port from different terminals\n" msgstr "" #: ../src/cmdline.c:57 msgid "" " Note: incoming data are displayed randomly on only " "one terminal\n" msgstr "" #: ../src/cmdline.c:167 msgid "Undefined command line option\n" msgstr "Félreértett parancssori opció\n" #: ../src/files.c:77 msgid "Send RAW File" msgstr "" #: ../src/files.c:96 #, c-format msgid "Error opening file\n" msgstr "Hiba fájl megnyitásakor\n" #: ../src/files.c:110 #, c-format msgid "%s : transfer in progress..." msgstr "%s : átvitel folyamatban..." #: ../src/files.c:128 msgid "Cancel" msgstr "Mégsem" #: ../src/files.c:143 #, fuzzy, c-format msgid "Cannot read file %s: %s\n" msgstr "Fájl olvasása sikertelen: %s : %s\n" #: ../src/files.c:178 #, fuzzy, c-format msgid "Error sending file\n" msgstr "Hiba fájl megnyitásakor\n" #: ../src/files.c:206 #, fuzzy, c-format msgid "Error sending file: %s\n" msgstr "Hiba fájl megnyitásakor\n" #: ../src/files.c:292 msgid "Save RAW File" msgstr "" #: ../src/files.c:311 #, c-format msgid "File error\n" msgstr "Fájlhiba!\n" #: ../src/files.c:322 ../src/logging.c:68 ../src/logging.c:123 #, fuzzy, c-format msgid "Cannot open file %s: %s\n" msgstr "%s fájl megnyitása nem sikerült: %s\n" #. Toplevel #: ../src/interface.c:145 #, fuzzy msgid "_File" msgstr "/_Fájl" #: ../src/interface.c:146 msgid "_Edit" msgstr "" #: ../src/interface.c:147 msgid "_Log" msgstr "" #: ../src/interface.c:148 #, fuzzy msgid "_Configuration" msgstr "/_Beállítások" #: ../src/interface.c:149 #, fuzzy msgid "Control _signals" msgstr "/_EllenörzÅ‘ jelek" #: ../src/interface.c:150 #, fuzzy msgid "_View" msgstr "/_Nézet" #: ../src/interface.c:151 #, fuzzy msgid "Hexadecimal _chars" msgstr "/Nézet/Hexadecimális _karakter" #: ../src/interface.c:152 #, fuzzy msgid "_Help" msgstr "/_Súgó" #: ../src/interface.c:156 #, fuzzy msgid "_Clear screen" msgstr "/Fájl/KépernyÅ‘ törlése" #: ../src/interface.c:157 msgid "_Clear scrollback" msgstr "" #: ../src/interface.c:158 #, fuzzy msgid "Send _RAW file" msgstr "/Fájl/Raw fájl _küldése" #: ../src/interface.c:159 #, fuzzy msgid "_Save RAW file" msgstr "/Fájl/Raw fájl _mentése" #. Log Menu #: ../src/interface.c:167 msgid "To file..." msgstr "" #. Confuguration Menu #: ../src/interface.c:173 #, fuzzy msgid "_Port" msgstr "Port:" #: ../src/interface.c:174 #, fuzzy msgid "_Main window" msgstr "/Beállítások/_FÅ‘ablak" #: ../src/interface.c:175 msgid "_Macros" msgstr "" #: ../src/interface.c:176 #, fuzzy msgid "_Load configuration" msgstr "Konfiguráció betöltés" #: ../src/interface.c:177 #, fuzzy msgid "_Save configuration" msgstr "Konfiguráció mentése" #: ../src/interface.c:178 #, fuzzy msgid "_Delete configuration" msgstr "Konfiguráció törlése" #. Signals Menu #: ../src/interface.c:181 msgid "Send break" msgstr "" #: ../src/interface.c:182 #, fuzzy msgid "_Open Port" msgstr "Nincs nyitott port" #: ../src/interface.c:183 msgid "_Close Port" msgstr "" #: ../src/interface.c:184 msgid "Toggle DTR" msgstr "" #: ../src/interface.c:185 msgid "Toggle RTS" msgstr "" #. Configuration Menu #: ../src/interface.c:194 msgid "Local _echo" msgstr "" #: ../src/interface.c:195 msgid "_CR LF auto" msgstr "" #: ../src/interface.c:196 msgid "Timestamp" msgstr "" #. View Menu #: ../src/interface.c:199 #, fuzzy msgid "Show _index" msgstr "/Nézet/_Index megjelenítése" #: ../src/interface.c:200 #, fuzzy msgid "_Send hexadecimal data" msgstr "/Nézet/Hexadecimális adat _küldés" #: ../src/interface.c:205 #, fuzzy msgid "_ASCII" msgstr "/Nézet/_ASCII" #: ../src/interface.c:206 #, fuzzy msgid "_Hexadecimal" msgstr "/Nézet/_Hexadecimális" #: ../src/interface.c:422 msgid "Resume" msgstr "" #: ../src/interface.c:567 msgid "Hexadecimal data to send (separator : ';' or space) : " msgstr "Hexadecimális adat küldés (elválasztó : ';' vagy szóköz) :" #: ../src/interface.c:736 msgid "" "GTKTerm is a simple GTK+ terminal used to communicate with the serial port." msgstr "" #: ../src/interface.c:776 #, fuzzy msgid "Break signal sent!" msgstr "Break signál küldve!" #: ../src/interface.c:882 #, fuzzy, c-format msgid "0 byte(s) sent!" msgstr "\"%s\" : %d bájt(ok) küldve!" #: ../src/interface.c:896 msgid "Improper formatted hex input, 0 bytes sent!" msgstr "" #: ../src/interface.c:907 #, fuzzy, c-format msgid "%d byte(s) sent!" msgstr "\"%s\" : %d bájt(ok) küldve!" #: ../src/logging.c:49 #, fuzzy, c-format msgid "Filename error\n" msgstr "Fájlhiba!\n" #: ../src/logging.c:88 #, fuzzy msgid "Log file selection" msgstr "Tallózás" #: ../src/logging.c:184 msgid "Failed to log data\n" msgstr "" #: ../src/macros.c:144 #, c-format msgid "Macro \"%s\" sent !" msgstr "Makró \"%s\" elküldve!" #: ../src/macros.c:275 msgid "Shortcut" msgstr "Gyorsbillentyű" #: ../src/macros.c:432 msgid "" "The \"action\" field of a macro is the data to be sent on the port. Text can " "be entered, but also special chars, like \\n, \\t, \\r, etc. You can also " "enter hexadecimal data preceded by a '\\'. The hexadecimal data should not " "begin with a letter (eg. use \\0FF and not \\FF)\n" "Examples :\n" "\t\"Hello\\n\" sends \"Hello\" followed by a Line Feed\n" "\t\"Hello\\0A\" does the same thing but the LF is entered in hexadecimal" msgstr "" "A makró \"action\" mezÅ‘je az adat, amit a portra küld. Beírható szöveg is, " "vagy speciális karakterek, mint \\n, \\t, \\r, stb. Hexadecimális adat is " "szerepelhet, megelÅ‘zve '\\' karakterrel. A hexadecimális adat nem kezdÅ‘dhet " "betűvel (pl. \\0FF használatos \\FF helyett) \n" "Példák: \n" "\t\"Hello\\n\" \"Hello\" küldése, utána egy soremelés\n" "\t\"Hello\\0A\" ugyanaz, csak a soremelés hexában van megadva." #: ../src/macros.c:452 msgid "Configure Macros" msgstr "A makrók beállítása" #: ../src/macros.c:489 msgid "_Add" msgstr "_Hozzáadás" #: ../src/macros.c:493 msgid "_Delete" msgstr "_Törlés" #: ../src/macros.c:497 msgid "_Capture Shortcut" msgstr "Billentyűparancsok" #: ../src/parsecfg.c:355 #, c-format msgid "Cannot open configuration file `%s'.\n" msgstr "Nem tölthetÅ‘ be a `%s' konfigurációs fájl.\n" #: ../src/parsecfg.c:358 #, c-format msgid "Cannot create configuration file `%s'.\n" msgstr "Nem hozható létre a `%s' konfigurációs fájl.\n" #: ../src/parsecfg.c:361 #, c-format msgid "" "%s(%d): %s\n" "Syntax error\n" msgstr "" "%s(%d): %s\n" "Szintaktikai hiba\n" #: ../src/parsecfg.c:364 #, c-format msgid "" "%s(%d): %s\n" "Unrecognized parameter\n" msgstr "" "%s(%d): %s\n" "Érvénytelen paraméter\n" #: ../src/parsecfg.c:367 #, c-format msgid "" "%s(%d): %s\n" "Internal error\n" msgstr "" "%s(%d): %s\n" "Végzetes hiba\n" #: ../src/parsecfg.c:370 #, c-format msgid "" "%s(%d): %s\n" "Invalid number\n" msgstr "" "%s(%d): %s\n" "Érvénytelen szám\n" #: ../src/parsecfg.c:373 #, c-format msgid "" "%s(%d): %s\n" "Out of range\n" msgstr "" "%s(%d): %s\n" "Hibás értéktartomány\n" #: ../src/parsecfg.c:376 #, c-format msgid "" "%s(%d): %s\n" "Cannot allocate memory.\n" msgstr "" "%s(%d): %s\n" "Nem sikerült memóriát foglalni.\n" #: ../src/parsecfg.c:379 #, c-format msgid "" "%s(%d): %s\n" "It must be specified TRUE or FALSE.\n" msgstr "" "%s(%d): %s\n" "Meg kell adni, hogy TRUE vagy FALSE.\n" #: ../src/parsecfg.c:382 #, c-format msgid "" "%s(%d): %s\n" "The section name is already used.\n" msgstr "" "%s(%d): %s\n" "Ez a név már foglalt.\n" #: ../src/parsecfg.c:385 #, c-format msgid "" "%s(%d)\n" "There is no closing bracket.\n" msgstr "" "%s(%d)\n" "Hiányzik a záró kapocs. .\n" #: ../src/parsecfg.c:390 #, c-format msgid "" "%s(%d): %s\n" "Unexplained error\n" msgstr "" "%s(%d): %s\n" "Rejtélyes hiba\n" #: ../src/serial.c:154 #, fuzzy, c-format msgid "Cannot open %s: %s\n" msgstr "Nem lehet megnyitni a %s-t : %s\n" #: ../src/serial.c:167 #, c-format msgid "" "Cannot lock port! The serial port may currently be in use by another " "program.\n" msgstr "" #: ../src/serial.c:235 #, c-format msgid "Arbitrary baud rates not supported" msgstr "" #: ../src/serial.c:352 ../src/serial.c:398 msgid "Control signals read" msgstr "EllenörzÅ‘ jelek olvasása" #: ../src/serial.c:364 msgid "DTR write" msgstr "DTR írás" #: ../src/serial.c:374 msgid "RTS write" msgstr "RTS írás" #: ../src/serial.c:452 msgid "No open port" msgstr "Nincs nyitott port" #: ../src/term_config.c:193 #, fuzzy msgid "" "No serial devices found!\n" "\n" "Searched the following device path patterns:\n" "\t/dev/ttyS*\n" "\t/dev/tts/*\n" "\t/dev/ttyUSB*\n" "\t/dev/usb/tts/*\n" "\n" "Enter a different device path in the 'Port' box.\n" msgstr "" "Nem találok valódi soros eszközt a /dev könyvtárban!\n" "Legalább egy eszköz kellene ezek közül:\n" "/dev/ttyS*\n" "/dev/tts/*\n" "/dev/ttyUSB*\n" "/dev/usb/tts/*\n" #: ../src/term_config.c:202 msgid "Configuration" msgstr "Konfiguráció" #: ../src/term_config.c:206 msgid "Serial port" msgstr "Soros port" #: ../src/term_config.c:212 #, fuzzy msgid "Port:" msgstr "Port:" #: ../src/term_config.c:214 msgid "Baud Rate:" msgstr "" #: ../src/term_config.c:216 #, fuzzy msgid "Parity:" msgstr "Paritás:" #: ../src/term_config.c:362 #, fuzzy msgid "Bits:" msgstr "Bitek:" #: ../src/term_config.c:364 #, fuzzy msgid "Stopbits:" msgstr "Stoppbitek:" #: ../src/term_config.c:366 #, fuzzy msgid "Flow control:" msgstr "Folyamatvezérlés:" #. create an expander widget to hide the 'Advanced features' #: ../src/term_config.c:417 #, fuzzy msgid "Advanced Configuration Options" msgstr "Konfigurációk" #: ../src/term_config.c:422 msgid "ASCII file transfer" msgstr "ASCII fájl átvitel" #: ../src/term_config.c:428 #, fuzzy msgid "End of line delay (milliseconds):" msgstr "Sorvég késleltetés (tizedmásodperc):" #: ../src/term_config.c:444 #, fuzzy msgid "Wait for this special character before passing to next line:" msgstr "Speciális karakterre várakozás az következÅ‘ sor elött:" #: ../src/term_config.c:457 msgid "RS-485 half-duplex parameters (RTS signal used to send)" msgstr "" #: ../src/term_config.c:464 msgid "Time with RTS 'on' before transmit (milliseconds):" msgstr "" #: ../src/term_config.c:466 msgid "Time with RTS 'on' after transmit (milliseconds):" msgstr "" #: ../src/term_config.c:591 msgid "Load configuration" msgstr "Konfiguráció betöltés" #: ../src/term_config.c:601 msgid "Delete configuration" msgstr "Konfiguráció törlése" #: ../src/term_config.c:631 ../src/term_config.c:896 msgid "" "Cannot read configuration file!\n" "Config file may contain invalid parameter.\n" msgstr "" #: ../src/term_config.c:637 msgid "Configurations" msgstr "Konfigurációk" #: ../src/term_config.c:704 msgid "Save configuration" msgstr "Konfiguráció mentése" #: ../src/term_config.c:716 #, fuzzy msgid "Configuration name: " msgstr "Konfiguráció név:" #: ../src/term_config.c:750 msgid "" "Cannot save configuration file!\n" "Config file may contain invalid parameter.\n" msgstr "" #: ../src/term_config.c:770 #, fuzzy msgid "Cannot overwrite section!" msgstr "Nem sikerült felülírni a szekciót!" #: ../src/term_config.c:775 #, fuzzy msgid "Cannot read configuration file!" msgstr "Konfigurációs fájl beolvasása nem sikerült!" #: ../src/term_config.c:785 #, c-format msgid "Configuration [%s] saved\n" msgstr "Beállítások [%s] elmentve\n" #: ../src/term_config.c:804 msgid "" "Cannot write configuration file!\n" "Config file may contain invalid parameter.\n" msgstr "" #: ../src/term_config.c:819 #, fuzzy, c-format msgid "" "Section [%s] already exists.\n" "\n" "Do you want to overwrite it ?" msgstr "" "\n" "A(z) [%s] szekció már létezik.\n" "Felül kívánja írni?\n" #: ../src/term_config.c:879 #, fuzzy msgid "Cannot delete section!" msgstr "Szekció nem törölhetÅ‘!" #: ../src/term_config.c:1060 #, c-format msgid "No section \"%s\" in configuration file\n" msgstr "A konfigurációs file-ban nincs \"%s\" szekció\n" #: ../src/term_config.c:1105 #, c-format msgid "Baudrate %d may not be supported by all hardware" msgstr "" #: ../src/term_config.c:1112 #, fuzzy, c-format msgid "" "Invalid number of stop-bits: %d\n" "Falling back to default number of stop-bits number: %d\n" msgstr "" "Hibás stop bit: %d\n" "Visszaállítva az alapértelmezett stop bit: %d\n" #: ../src/term_config.c:1120 #, fuzzy, c-format msgid "" "Invalid number of bits: %d\n" "Falling back to default number of bits: %d\n" msgstr "" "Hibás bit szám: %d\n" "Visszaállítva az alapértelmezett bit szám: %d\n" #: ../src/term_config.c:1128 #, fuzzy, c-format msgid "" "Invalid delay: %d ms\n" "Falling back to default delay: %d ms\n" msgstr "" "Hibás késleltetés: %d\n" "Visszaállítva az alapértelmezett késleltetés: %d\n" #: ../src/term_config.c:1158 #, c-format msgid "" "Configuration file (%s) with\n" "[default] configuration has been created.\n" msgstr "" "A (%s) [alapértelmezett] konfigurációs\n" "fájl létrehozva.\n" #: ../src/term_config.c:1414 #, c-format msgid "Cannot find section %s\n" msgstr "%s szekció nem található\n" #: ../src/term_config.c:1454 msgid "Main Window" msgstr "" #~ msgid "\t http://www.jls-info.com/julien/linux\n" #~ msgstr "\t http://www.jls-info.com/julien/linux\n" #~ msgid "Speed :" #~ msgstr "Sebesség:" #~ msgid "Font selection" #~ msgstr "Betűtípus választás" #~ msgid "Cannot read configuration file !\n" #~ msgstr "Konfigurációs fájl beolvasása nem sikerült!\n" #~ msgid "Warning !" #~ msgstr "Figyelmeztetés:" #~ msgid "" #~ "Unknown speed : %d bauds\n" #~ "Falling back to default speed : %d bauds\n" #~ msgstr "" #~ "Ismeretlen sebesség: %d baud\n" #~ "Visszaállítva az alapértelmezett sebesség: %d baud\n" #~ msgid "Terminal configuration" #~ msgstr "A program beállításai" #~ msgid "%v / %u Kb (%p %%)" #~ msgstr "%v / %u Kb (%p %%)" #~ msgid "%v / %u bytes (%p %%)" #~ msgstr "%v / %u bájt (%p %%)" #~ msgid "Cannot write file %s\n" #~ msgstr "Nem sikerült írni a(z) %s célfájlt\n" #~ msgid "Help on macros" #~ msgstr "Súgó a makrókhoz" #~ msgid "Lockfile is stale. Overriding it..\n" #~ msgstr "A zárolási fájl érvénytelen, felülbírálom..\n" #~ msgid "Device %s is locked.\n" #~ msgstr "A %s eszköz zárolva van.\n" #~ msgid "Cannot create lockfile. Sorry.\n" #~ msgstr "Nem tudok létrehozni zárolási fájlt.\n" #~ msgid "/File/Separator" #~ msgstr "/Fájl/_Elválasztó" #~ msgid "/File/E_xit" #~ msgstr "/Fájl/K_ilépés" #~ msgid "/Configuration/_Port" #~ msgstr "/Beállítások/_Port" #~ msgid "/Configuration/Local _echo" #~ msgstr "/Beállítások/Helyi _visszhang" #~ msgid "/Configuration/_CR LF auto" #~ msgstr "/Beállítások/_CR LF auto" #~ msgid "/Configuration/_Macros" #~ msgstr "/Beállítások/Ma_krók" #~ msgid "/Configuration/Separator" #~ msgstr "/Beállítások/_Elválasztó" #~ msgid "/Configuration/_Load configuration" #~ msgstr "/Beállítások/Konfiguráció _betöltése" #~ msgid "/Configuration/_Save configuration" #~ msgstr "/Beállítások/Konfiguráció _mentése" #~ msgid "/Configuration/_Delete configuration" #~ msgstr "/Beállítások/Konfiguráció _törlése" #~ msgid "/Control signals/Send break" #~ msgstr "/EllenörzÅ‘ jelek/Break küldés" #~ msgid "/Control signals/Toggle DTR" #~ msgstr "/EllenörzÅ‘ jelek/DTR " #~ msgid "/Control signals/Toggle RTS" #~ msgstr "/EllenörzÅ‘ jelek/RTS" #~ msgid "/View/Hexadecimal chars/_8" #~ msgstr "/Nézet/Hexadecimális _karakter/_8" #~ msgid "/View/Hexadecimal chars/1_0" #~ msgstr "/Nézet/Hexadecimális _karakter/1_0" #~ msgid "/View/Hexadecimal chars/_16" #~ msgstr "/Nézet/Hexadecimális _karakter/_16" #~ msgid "/View/Hexadecimal chars/_24" #~ msgstr "/Nézet/Hexadecimális _karakter/_24" #~ msgid "/View/Hexadecimal chars/_32" #~ msgstr "/Nézet/Hexadecimális _karakter/_32" #~ msgid "/View/Separator" #~ msgstr "/Nézet/_Elválasztó" #~ msgid "/Help/_About..." #~ msgstr "/Súgó/_Névjegy..." #~ msgid "About..." #~ msgstr "Névjegy..." #~ msgid "" #~ "\n" #~ " GTKTerm V. %s \n" #~ "\n" #~ "\t(c) Julien Schmitt : julien@jls-info.com \n" #~ "\thttp://www.jls-info.com/julien/linux\n" #~ msgstr "" #~ "\n" #~ " GTKTerm V. %s \n" #~ "\n" #~ "\t(c) Julien Schmitt : julien@jls-info.com \n" #~ "\thttp://www.jls-info.com/julien/linux\n" gtkterm-1.1.1/po/meson.build000066400000000000000000000001501376216657300157630ustar00rootroot00000000000000i18n = import('i18n') i18n.gettext(meson.project_name(), args: '--directory=' + meson.source_root() ) gtkterm-1.1.1/po/nl_NL.po000066400000000000000000000427741376216657300152050ustar00rootroot00000000000000# 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. # msgid "" msgstr "" "Project-Id-Version: gtkterm 1.0.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2020-03-09 08:47+0100\n" "PO-Revision-Date: 2020-03-09 10:32+0100\n" "Language-Team: W. van den Akker\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 2.3\n" "Last-Translator: \n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "Language: nl_NL\n" #: ../src/buffer.c:164 msgid "ERROR : Buffer is not initialized !\n" msgstr "Fout: Buffer is niet geinitialiseerd\n" #: ../src/cmdline.c:37 #, c-format msgid "" "\n" "GTKTerm version %s\n" msgstr "" "\n" "GTKTerm versie %s\n" #: ../src/cmdline.c:38 msgid "\t (c) Julien Schmitt\n" msgstr "\t (c) Julien Schmitt\n" #: ../src/cmdline.c:39 msgid "" "\n" "This program is released under the terms of the GPL V.2\n" msgstr "" "\n" "Dit programma is vrijgegeven onder de GPL V.2 licentie\n" #: ../src/cmdline.c:40 msgid "\t ** Use at your own risks ! **\n" msgstr "\t ** Gebruik op eigen risico ! **\n" #: ../src/cmdline.c:41 msgid "" "\n" "Command line options\n" msgstr "" "\n" "Command line opties\n" #: ../src/cmdline.c:42 msgid "--help or -h : this help screen\n" msgstr "--help of -h : dit help scherm\n" #: ../src/cmdline.c:43 msgid "--config or -c : load configuration\n" msgstr "--config of -c : te laden configuratie\n" #: ../src/cmdline.c:44 msgid "--port or -p : serial port device (default /dev/ttyS0)\n" msgstr "" "--port of -p : seriele poort apparaat (standaard /dev/ttyS0)\n" #: ../src/cmdline.c:45 msgid "--speed or -s : serial port speed (default 9600)\n" msgstr "--speed of -s : seriele poort snelheid (standaard 9600)\n" #: ../src/cmdline.c:46 msgid "--bits or -b : number of bits (default 8)\n" msgstr "--bits of -b : aantal bits (standaard 8)\n" #: ../src/cmdline.c:47 msgid "--stopbits or -t : number of stopbits (default 1)\n" msgstr "--stopbits of -t : aantal stopbits (standaard 1)\n" #: ../src/cmdline.c:48 msgid "--parity or -a : parity (default none)\n" msgstr "--parity of -a : partiteit (standaard none)\n" #: ../src/cmdline.c:49 msgid "--flow or -w : flow control (default none)\n" msgstr "--flow of -w : flow controle (standaard none)\n" #: ../src/cmdline.c:50 msgid "--delay or -d : end of line delay in ms (default none)\n" msgstr "--delay of -d : einde regel vertraging in ms (default none)\n" #: ../src/cmdline.c:51 msgid "" "--char or -r : wait for a special char at end of line (default none)\n" msgstr "" "--char of -r : wachten op speciaal teken aan einde van de regel " "(standaard none)\n" #: ../src/cmdline.c:52 msgid "--file or -f : default file to send (default none)\n" msgstr "" "--file of -f : standaard bestand om te versturen (standaard " "none)\n" #: ../src/cmdline.c:53 msgid "" "--rts_time_before or -x : for RS-485, time in ms before transmit with " "rts on\n" msgstr "" "--rts_time_before of -x : voor de RS-485, tijd in ms voordat met RTS " "aan wordt verzonden\n" #: ../src/cmdline.c:54 msgid "" "--rts_time_after or -y : for RS-485, time in ms after transmit with rts " "on\n" msgstr "" "--rts_time_after of -x : voor de RS-485, tijd in ms nadat met RTS aan " "wordt verzonden\n" "\n" #: ../src/cmdline.c:55 msgid "--echo or -e : switch on local echo\n" msgstr "--echo of -e : schakel locale echo aan\n" #: ../src/cmdline.c:56 msgid "" "--disable-port-lock or -L: does not lock serial port. Allows to send to " "serial port from different terminals\n" msgstr "" "--disable-port-lock or -L: poort wordt niet gereserveerd. Geeft mogelijk om " "van andere schermen naar de seriele poort te zenden\n" #: ../src/cmdline.c:57 msgid "" " Note: incoming data are displayed randomly on only " "one terminal\n" msgstr "" " Note: Inkomende data wordt in willekeurige volgorde " "getoond op slechts een scherm\n" #: ../src/cmdline.c:167 msgid "Undefined command line option\n" msgstr "Herken commandlijn optie niet\n" #: ../src/files.c:77 msgid "Send RAW File" msgstr "Versturen ruwe bestand" #: ../src/files.c:96 #, c-format msgid "Error opening file\n" msgstr "Fout bij openen bestand\n" #: ../src/files.c:110 #, c-format msgid "%s : transfer in progress..." msgstr "%s : overdracht vindt plaats..." #: ../src/files.c:128 msgid "Cancel" msgstr "Afbreken" #: ../src/files.c:143 #, c-format msgid "Cannot read file %s: %s\n" msgstr "Kan bestand %s: %s niet lezen\n" #: ../src/files.c:178 #, c-format msgid "Error sending file\n" msgstr "Fout bij versturen bestand\n" #: ../src/files.c:206 #, c-format msgid "Error sending file: %s\n" msgstr "Fout bij versturen bestand: %s\n" #: ../src/files.c:292 msgid "Save RAW File" msgstr "Ruwe bestand opslaan" #: ../src/files.c:311 #, c-format msgid "File error\n" msgstr "Bestand fout\n" #: ../src/files.c:322 ../src/logging.c:68 ../src/logging.c:123 #, c-format msgid "Cannot open file %s: %s\n" msgstr "Kan bestand %s: %s niet openen\n" #. Toplevel #: ../src/interface.c:145 msgid "_File" msgstr "_Bestand" #: ../src/interface.c:146 msgid "_Edit" msgstr "_Wijzigen" #: ../src/interface.c:147 msgid "_Log" msgstr "_Loggen" #: ../src/interface.c:148 msgid "_Configuration" msgstr "_Configuratie" #: ../src/interface.c:149 msgid "Control _signals" msgstr "Controle _signalen" #: ../src/interface.c:150 msgid "_View" msgstr "_Tonen" #: ../src/interface.c:151 msgid "Hexadecimal _chars" msgstr "Hexadecimale _tekens" #: ../src/interface.c:152 msgid "_Help" msgstr "_Help" #: ../src/interface.c:156 msgid "_Clear screen" msgstr "_Opschonen scherm" #: ../src/interface.c:157 msgid "_Clear scrollback" msgstr "_Opschonen scrollback" #: ../src/interface.c:158 msgid "Send _RAW file" msgstr "_Ruwe bestand versturen" #: ../src/interface.c:159 msgid "_Save RAW file" msgstr "_Ruwe bestand opslaan" #. Log Menu #: ../src/interface.c:167 msgid "To file..." msgstr "Naar bestand ..." #. Confuguration Menu #: ../src/interface.c:173 msgid "_Port" msgstr "_Poort" #: ../src/interface.c:174 msgid "_Main window" msgstr "_Hoofd scherm" #: ../src/interface.c:175 msgid "_Macros" msgstr "_Macros" #: ../src/interface.c:176 msgid "_Load configuration" msgstr "_Laden configuration" #: ../src/interface.c:177 msgid "_Save configuration" msgstr "_Opslaan configuratie" #: ../src/interface.c:178 msgid "_Delete configuration" msgstr "_Verwijderen configuratie" #. Signals Menu #: ../src/interface.c:181 msgid "Send break" msgstr "Afbreken versturen" #: ../src/interface.c:182 msgid "_Open Port" msgstr "_Openen Poort" #: ../src/interface.c:183 msgid "_Close Port" msgstr "_Sluiten Poort" #: ../src/interface.c:184 msgid "Toggle DTR" msgstr "Toggel DTR" #: ../src/interface.c:185 msgid "Toggle RTS" msgstr "Toggel RTS" #. Configuration Menu #: ../src/interface.c:194 msgid "Local _echo" msgstr "Lokale _echo" #: ../src/interface.c:195 msgid "_CR LF auto" msgstr "_CR LF automatisch" #: ../src/interface.c:196 msgid "Timestamp" msgstr "Tijdstempel" #. View Menu #: ../src/interface.c:199 msgid "Show _index" msgstr "Toon _index" #: ../src/interface.c:200 msgid "_Send hexadecimal data" msgstr "_Versturen hexadecimale data" #: ../src/interface.c:205 msgid "_ASCII" msgstr "_ASCII" #: ../src/interface.c:206 msgid "_Hexadecimal" msgstr "_Hexadecimaal" #: ../src/interface.c:422 msgid "Resume" msgstr "Hervatten" #: ../src/interface.c:567 msgid "Hexadecimal data to send (separator : ';' or space) : " msgstr "Te verzenden hexadecimale data (scheidingsteken : ';' or spatie) : " #: ../src/interface.c:736 msgid "" "GTKTerm is a simple GTK+ terminal used to communicate with the serial port." msgstr "" "GTKTerm is een eenvoudige GTK+ terminal voor communicatie met de seriele poort." #: ../src/interface.c:776 msgid "Break signal sent!" msgstr "Afbreek signaal verstuurd!" #: ../src/interface.c:882 #, c-format msgid "0 byte(s) sent!" msgstr "0 byte(s) verstuurd!" #: ../src/interface.c:896 msgid "Improper formatted hex input, 0 bytes sent!" msgstr "Onjuist geformteerde hex invoer 0 bytes sent!" #: ../src/interface.c:907 #, c-format msgid "%d byte(s) sent!" msgstr "%d byte(s) verstuurd!" #: ../src/logging.c:49 #, c-format msgid "Filename error\n" msgstr "Fout in bestandsnaam\n" #: ../src/logging.c:88 msgid "Log file selection" msgstr "Selecteren log bestand" #: ../src/logging.c:184 msgid "Failed to log data\n" msgstr "Kan data niet loggen\n" #: ../src/macros.c:144 #, c-format msgid "Macro \"%s\" sent !" msgstr "Macro \"%s\" verstuurd !" #: ../src/macros.c:275 msgid "Shortcut" msgstr "Snelkoppeling" #: ../src/macros.c:432 msgid "" "The \"action\" field of a macro is the data to be sent on the port. Text can " "be entered, but also special chars, like \\n, \\t, \\r, etc. You can also " "enter hexadecimal data preceded by a '\\'. The hexadecimal data should not " "begin with a letter (eg. use \\0FF and not \\FF)\n" "Examples :\n" "\t\"Hello\\n\" sends \"Hello\" followed by a Line Feed\n" "\t\"Hello\\0A\" does the same thing but the LF is entered in hexadecimal" msgstr "" "In het veld \"actie\" van een macro zijn de gegevens die naar de poort " "moeten worden verzonden. Tekst kan worden ingevoerd, maar ook speciale " "tekens, zoals \\ n, \\ t, \\ r, enz. U kunt ook hexadecimale gegevens " "invoeren die worden voorafgegaan door een '\\'. De hexadecimale gegevens " "mogen niet beginnen met een letter (gebruik bijvoorbeeld \\ 0FF en niet \\ " "FF)\n" "Voorbeelden:\n" "\"Hallo \\ n\" stuurt \"Hallo\" gevolgd door een einde regel teken\n" "\"Hallo \\ 0A\" doet hetzelfde, maar de LF wordt hexadecimaal ingevoerd" #: ../src/macros.c:452 msgid "Configure Macros" msgstr "Macros configureren" #: ../src/macros.c:489 msgid "_Add" msgstr "_Toevoegen" #: ../src/macros.c:493 msgid "_Delete" msgstr "_Verwijderen" #: ../src/macros.c:497 msgid "_Capture Shortcut" msgstr "_Snelkoppeling vastleggen" #: ../src/parsecfg.c:355 #, c-format msgid "Cannot open configuration file `%s'.\n" msgstr "Kan configuratie bestand `%s' niet openen.\n" #: ../src/parsecfg.c:358 #, c-format msgid "Cannot create configuration file `%s'.\n" msgstr "Kan create configuratie bestand `%s' niet aanmaken.\n" #: ../src/parsecfg.c:361 #, c-format msgid "" "%s(%d): %s\n" "Syntax error\n" msgstr "" "%s(%d): %s\n" "Syntax fout\n" #: ../src/parsecfg.c:364 #, c-format msgid "" "%s(%d): %s\n" "Unrecognized parameter\n" msgstr "" "%s(%d): %s\n" "Parameter niet herkend\n" #: ../src/parsecfg.c:367 #, c-format msgid "" "%s(%d): %s\n" "Internal error\n" msgstr "" "%s(%d): %s\n" "Internae fout\n" #: ../src/parsecfg.c:370 #, c-format msgid "" "%s(%d): %s\n" "Invalid number\n" msgstr "" "%s(%d): %s\n" "Onjuist nummer\n" #: ../src/parsecfg.c:373 #, c-format msgid "" "%s(%d): %s\n" "Out of range\n" msgstr "" "%s(%d): %s\n" "Buiten bereik\n" #: ../src/parsecfg.c:376 #, c-format msgid "" "%s(%d): %s\n" "Cannot allocate memory.\n" msgstr "" "%s(%d): %s\n" "Kan geheugen niet alloceren.\n" #: ../src/parsecfg.c:379 #, c-format msgid "" "%s(%d): %s\n" "It must be specified TRUE or FALSE.\n" msgstr "" "%s(%d): %s\n" "Moet TRUE of FALSE specifieren.\n" #: ../src/parsecfg.c:382 #, c-format msgid "" "%s(%d): %s\n" "The section name is already used.\n" msgstr "" "%s(%d): %s\n" "Sectie naam is al in gebruik.\n" #: ../src/parsecfg.c:385 #, c-format msgid "" "%s(%d)\n" "There is no closing bracket.\n" msgstr "" "%s(%d)\n" "Er is geen sluit haakje.\n" #: ../src/parsecfg.c:390 #, c-format msgid "" "%s(%d): %s\n" "Unexplained error\n" msgstr "" "%s(%d): %s\n" "onbekende fout\n" #: ../src/serial.c:154 #, c-format msgid "Cannot open %s: %s\n" msgstr "Kan %s: %s niet openen\n" #: ../src/serial.c:167 #, c-format msgid "" "Cannot lock port! The serial port may currently be in use by another " "program.\n" msgstr "" "Kan poort niet reserveren! De seriele poort kan door een ander programma in " "gebruik zijn\n" #: ../src/serial.c:235 #, c-format msgid "Arbitrary baud rates not supported" msgstr "Willekeurige baud-snelheden worden niet ondersteund" #: ../src/serial.c:352 ../src/serial.c:398 msgid "Control signals read" msgstr "Lezen controle signalen" #: ../src/serial.c:364 msgid "DTR write" msgstr "DTR schrijven" #: ../src/serial.c:374 msgid "RTS write" msgstr "RTS schrijven" #: ../src/serial.c:452 msgid "No open port" msgstr "Geen poort open" #: ../src/term_config.c:193 msgid "" "No serial devices found!\n" "\n" "Searched the following device path patterns:\n" "\t/dev/ttyS*\n" "\t/dev/tts/*\n" "\t/dev/ttyUSB*\n" "\t/dev/usb/tts/*\n" "\n" "Enter a different device path in the 'Port' box.\n" msgstr "" "Geen seriele poorten gevonden!\n" "\n" "Naar de volgende paden gezocht:\n" "\t/dev/ttyS*\n" "\t/dev/tts/*\n" "\t/dev/ttyUSB*\n" "\t/dev/usb/tts/*\n" "\n" "Geef pad op in het 'Poort' veld.\n" #: ../src/term_config.c:202 msgid "Configuration" msgstr "Configuratie" #: ../src/term_config.c:206 msgid "Serial port" msgstr "Seriele poort" #: ../src/term_config.c:212 msgid "Port:" msgstr "Poort:" #: ../src/term_config.c:214 msgid "Baud Rate:" msgstr "BaudRate:" #: ../src/term_config.c:216 msgid "Parity:" msgstr "Parity:" #: ../src/term_config.c:362 msgid "Bits:" msgstr "Bits:" #: ../src/term_config.c:364 msgid "Stopbits:" msgstr "Stopbits:" #: ../src/term_config.c:366 msgid "Flow control:" msgstr "Flow controle:" #. create an expander widget to hide the 'Advanced features' #: ../src/term_config.c:417 msgid "Advanced Configuration Options" msgstr "Geavanceerde configuratie opties" #: ../src/term_config.c:422 msgid "ASCII file transfer" msgstr "ASCII bestand overdracht" #: ../src/term_config.c:428 msgid "End of line delay (milliseconds):" msgstr "Vertraging einde-regel (milliseconds):" #: ../src/term_config.c:444 msgid "Wait for this special character before passing to next line:" msgstr "" "Wacht op speciale karakter voordat naar de volgende regel wordt gegaan:" #: ../src/term_config.c:457 msgid "RS-485 half-duplex parameters (RTS signal used to send)" msgstr "" "RS-485 half-duplex parameters (RTS signaal wordt gebruikt om te verzenden)" #: ../src/term_config.c:464 msgid "Time with RTS 'on' before transmit (milliseconds):" msgstr "Tijd voor RTS 'aan' voordat wordt verzonden (milliseconden):" #: ../src/term_config.c:466 msgid "Time with RTS 'on' after transmit (milliseconds):" msgstr "Tijd voor RTS 'aan' nadat is verzonden (milliseconden):" #: ../src/term_config.c:591 msgid "Load configuration" msgstr "Configuratie laden" #: ../src/term_config.c:601 msgid "Delete configuration" msgstr "Configuratie verwijderen" #: ../src/term_config.c:631 ../src/term_config.c:896 msgid "" "Cannot read configuration file!\n" "Config file may contain invalid parameter.\n" msgstr "" "Kan configuratie bestand niet lezen!\n" "Configuratie bestand kan onjuiste parameters bevatten.\n" #: ../src/term_config.c:637 msgid "Configurations" msgstr "Configuraties" #: ../src/term_config.c:704 msgid "Save configuration" msgstr "Configuratie opslaan" #: ../src/term_config.c:716 msgid "Configuration name: " msgstr "Naam configuratie:" #: ../src/term_config.c:750 msgid "" "Cannot save configuration file!\n" "Config file may contain invalid parameter.\n" msgstr "" "Kan configuratie bestand niet opslaan!\n" "Configuratie bestand kan onjuiste parameters bevatten.\n" #: ../src/term_config.c:770 msgid "Cannot overwrite section!" msgstr "Kan sectie niet overschrijven" #: ../src/term_config.c:775 msgid "Cannot read configuration file!" msgstr "Kan configuratiebestand niet overschrijven" #: ../src/term_config.c:785 #, c-format msgid "Configuration [%s] saved\n" msgstr "Configuratie [%s] opgeslagen\n" #: ../src/term_config.c:804 msgid "" "Cannot write configuration file!\n" "Config file may contain invalid parameter.\n" msgstr "" "Kan niet naar configuratie bestand schrijven!\n" "Configuratie bestand kan onjuiste parameters bevatten.\n" #: ../src/term_config.c:819 #, c-format msgid "" "Section [%s] already exists.\n" "\n" "Do you want to overwrite it ?" msgstr "" "Sectie [%s] bestaat.\n" "\n" "Wil je het overschrijven ?" #: ../src/term_config.c:879 msgid "Cannot delete section!" msgstr "Kan sectie niet verwijderen!" #: ../src/term_config.c:1060 #, c-format msgid "No section \"%s\" in configuration file\n" msgstr "Geen sectie \"%s\" in configuratie bestand\n" #: ../src/term_config.c:1105 #, c-format msgid "Baudrate %d may not be supported by all hardware" msgstr "Baudrate %d wellicht niet door alle hardware ondersteund" #: ../src/term_config.c:1112 #, c-format msgid "" "Invalid number of stop-bits: %d\n" "Falling back to default number of stop-bits number: %d\n" msgstr "" "Onjuist aantal stop-bits: %d\n" "Het standaard aantal stopbits wordt gebruikt: %d\n" #: ../src/term_config.c:1120 #, c-format msgid "" "Invalid number of bits: %d\n" "Falling back to default number of bits: %d\n" msgstr "" "Onjuist aantal bits: %d\n" "Het standaard aantal bits wordt gebruikt: %d\n" #: ../src/term_config.c:1128 #, c-format msgid "" "Invalid delay: %d ms\n" "Falling back to default delay: %d ms\n" msgstr "" "Onjuiste vertraging: %d\n" "Het standaard vertraging wordt gebruikt: %d\n" #: ../src/term_config.c:1158 #, c-format msgid "" "Configuration file (%s) with\n" "[default] configuration has been created.\n" msgstr "" "Configuratie bestand (%s) met\n" "[standaard] configuratie is aangemaakt.\n" #: ../src/term_config.c:1414 #, c-format msgid "Cannot find section %s\n" msgstr "Kan sectie %s niet vinden\n" #: ../src/term_config.c:1454 msgid "Main Window" msgstr "Hoofd scherm" gtkterm-1.1.1/po/ru.po000066400000000000000000000565441376216657300146310ustar00rootroot00000000000000# Russian translation for gtkterm package. # # Copyright (C) 2009 Julien Schmitt # This file is distributed under the same license as the gtkterm package. # # Sergey Alyoshin , 2009. # msgid "" msgstr "" "Project-Id-Version: gtkterm 0.99.5\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2020-03-09 10:41+0100\n" "PO-Revision-Date: 2009-08-21 11:34+0400\n" "Last-Translator: Sergey Alyoshin \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; \tplural=n%10==1 && n%100!=11 ? 0 : \tn%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" #: ../src/buffer.c:164 msgid "ERROR : Buffer is not initialized !\n" msgstr "ОШИБКÐ: буфер не инициализирован!\n" #: ../src/cmdline.c:37 #, c-format msgid "" "\n" "GTKTerm version %s\n" msgstr "" "\n" "GTKTerm верÑии %s\n" #: ../src/cmdline.c:38 #, fuzzy msgid "\t (c) Julien Schmitt\n" msgstr "\t (c) Julien Schmitt - julien@jls-info.com\n" #: ../src/cmdline.c:39 msgid "" "\n" "This program is released under the terms of the GPL V.2\n" msgstr "" "\n" "Эта программа выпущена под лицензией GPL v.2\n" #: ../src/cmdline.c:40 msgid "\t ** Use at your own risks ! **\n" msgstr "\t ** ИÑпользуйте на Ñвой риÑк! **\n" #: ../src/cmdline.c:41 msgid "" "\n" "Command line options\n" msgstr "" "\n" "Параметры командной Ñтроки:\n" #: ../src/cmdline.c:42 msgid "--help or -h : this help screen\n" msgstr "--help или -h: Ñто Ñообщение помощи\n" #: ../src/cmdline.c:43 msgid "--config or -c : load configuration\n" msgstr "--config <наÑтройка> или -c: загрузка наÑтройки\n" #: ../src/cmdline.c:44 msgid "--port or -p : serial port device (default /dev/ttyS0)\n" msgstr "" "--port <уÑтройÑтво> или -p: уÑтройÑтво поÑледовательного порта\n" " (по умолчанию /dev/ttyS0)\n" #: ../src/cmdline.c:45 msgid "--speed or -s : serial port speed (default 9600)\n" msgstr "" "--speed <ÑкороÑть> или -s: ÑкороÑть поÑледовательного порта\n" " (по умолчанию 9600)\n" #: ../src/cmdline.c:46 msgid "--bits or -b : number of bits (default 8)\n" msgstr "--bits <биты> или -b: количеÑтво бит (по умолчанию 8)\n" #: ../src/cmdline.c:47 msgid "--stopbits or -t : number of stopbits (default 1)\n" msgstr "--stopbits <Ñтоп-бит> или -t: количеÑтво Ñтоп-битов (по умолчанию 1)\n" #: ../src/cmdline.c:48 msgid "--parity or -a : parity (default none)\n" msgstr "--parity или -a: проверка чётноÑти (по умолчанию none)\n" #: ../src/cmdline.c:49 #, fuzzy msgid "--flow or -w : flow control (default none)\n" msgstr "--flow или -w: управление потоком (по умолчанию none)\n" #: ../src/cmdline.c:50 msgid "--delay or -d : end of line delay in ms (default none)\n" msgstr "--delay <мÑ> или -d: задержка конца Ñтроки, Ð¼Ñ (по умолчанию нет)\n" #: ../src/cmdline.c:51 msgid "" "--char or -r : wait for a special char at end of line (default none)\n" msgstr "" "--char <Ñимвол> или -r: ожидать Ñпециальный Ñимвол в конце Ñтроки\n" " (по умолчанию нет)\n" #: ../src/cmdline.c:52 msgid "--file or -f : default file to send (default none)\n" msgstr "" "--file <имÑ_файла> или -f: задать Ð¸Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð° Ð´Ð»Ñ Ð¾Ñ‚Ð¿Ñ€Ð°Ð²ÐºÐ¸ (по умолчанию нет)\n" #: ../src/cmdline.c:53 msgid "" "--rts_time_before or -x : for RS-485, time in ms before transmit with " "rts on\n" msgstr "" #: ../src/cmdline.c:54 msgid "" "--rts_time_after or -y : for RS-485, time in ms after transmit with rts " "on\n" msgstr "" #: ../src/cmdline.c:55 msgid "--echo or -e : switch on local echo\n" msgstr "--echo или -e: включить локальный вывод\n" #: ../src/cmdline.c:56 msgid "" "--disable-port-lock or -L: does not lock serial port. Allows to send to " "serial port from different terminals\n" msgstr "" #: ../src/cmdline.c:57 msgid "" " Note: incoming data are displayed randomly on only " "one terminal\n" msgstr "" #: ../src/cmdline.c:167 msgid "Undefined command line option\n" msgstr "Ðеверный параметр командной Ñтроки\n" #: ../src/files.c:77 msgid "Send RAW File" msgstr "" #: ../src/files.c:96 #, c-format msgid "Error opening file\n" msgstr "Ошибка Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð°\n" #: ../src/files.c:110 #, c-format msgid "%s : transfer in progress..." msgstr "%s: выполнÑетÑÑ Ð¿ÐµÑ€ÐµÐ´Ð°Ñ‡Ð°..." #: ../src/files.c:128 msgid "Cancel" msgstr "Отмена" #: ../src/files.c:143 #, fuzzy, c-format msgid "Cannot read file %s: %s\n" msgstr "Ðевозможно прочитать файл %s: %s\n" #: ../src/files.c:178 #, fuzzy, c-format msgid "Error sending file\n" msgstr "Ошибка Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð°\n" #: ../src/files.c:206 #, fuzzy, c-format msgid "Error sending file: %s\n" msgstr "Ошибка Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð°\n" #: ../src/files.c:292 msgid "Save RAW File" msgstr "" #: ../src/files.c:311 #, c-format msgid "File error\n" msgstr "Ошибка файла\n" #: ../src/files.c:322 ../src/logging.c:68 ../src/logging.c:123 #, fuzzy, c-format msgid "Cannot open file %s: %s\n" msgstr "Ðевозможно открыть файл %s: %s\n" #. Toplevel #: ../src/interface.c:145 #, fuzzy msgid "_File" msgstr "/_Файл" #: ../src/interface.c:146 msgid "_Edit" msgstr "" #: ../src/interface.c:147 msgid "_Log" msgstr "" #: ../src/interface.c:148 #, fuzzy msgid "_Configuration" msgstr "/_ÐаÑтройка" #: ../src/interface.c:149 #, fuzzy msgid "Control _signals" msgstr "/Сигналы _управлениÑ" #: ../src/interface.c:150 #, fuzzy msgid "_View" msgstr "/_Вид" #: ../src/interface.c:151 #, fuzzy msgid "Hexadecimal _chars" msgstr "/Вид/ШеÑтнадцатеричные _Ñимволы" #: ../src/interface.c:152 #, fuzzy msgid "_Help" msgstr "/_Помощь" #: ../src/interface.c:156 #, fuzzy msgid "_Clear screen" msgstr "/Файл/ОчиÑтить Ñкран" #: ../src/interface.c:157 msgid "_Clear scrollback" msgstr "" #: ../src/interface.c:158 #, fuzzy msgid "Send _RAW file" msgstr "/Файл/_Отправить файл" #: ../src/interface.c:159 #, fuzzy msgid "_Save RAW file" msgstr "/Файл/_Сохранить файл" #. Log Menu #: ../src/interface.c:167 msgid "To file..." msgstr "" #. Confuguration Menu #: ../src/interface.c:173 #, fuzzy msgid "_Port" msgstr "Порт:" #: ../src/interface.c:174 #, fuzzy msgid "_Main window" msgstr "/ÐаÑтройка/_ОÑновное окно" #: ../src/interface.c:175 msgid "_Macros" msgstr "" #: ../src/interface.c:176 #, fuzzy msgid "_Load configuration" msgstr "Загрузить наÑтройку" #: ../src/interface.c:177 #, fuzzy msgid "_Save configuration" msgstr "Сохранить наÑтройку" #: ../src/interface.c:178 #, fuzzy msgid "_Delete configuration" msgstr "Удалить наÑтройку" #. Signals Menu #: ../src/interface.c:181 msgid "Send break" msgstr "" #: ../src/interface.c:182 #, fuzzy msgid "_Open Port" msgstr "Порт не открыт" #: ../src/interface.c:183 msgid "_Close Port" msgstr "" #: ../src/interface.c:184 msgid "Toggle DTR" msgstr "" #: ../src/interface.c:185 msgid "Toggle RTS" msgstr "" #. Configuration Menu #: ../src/interface.c:194 msgid "Local _echo" msgstr "" #: ../src/interface.c:195 msgid "_CR LF auto" msgstr "" #: ../src/interface.c:196 msgid "Timestamp" msgstr "" #. View Menu #: ../src/interface.c:199 #, fuzzy msgid "Show _index" msgstr "/Вид/Показать _индекÑ" #: ../src/interface.c:200 #, fuzzy msgid "_Send hexadecimal data" msgstr "/Вид/Отправить шеÑтнадцатеричные данные" #: ../src/interface.c:205 #, fuzzy msgid "_ASCII" msgstr "/Вид/_ASCII" #: ../src/interface.c:206 #, fuzzy msgid "_Hexadecimal" msgstr "/Вид/_ШеÑтнадцатеричный" #: ../src/interface.c:422 msgid "Resume" msgstr "" #: ../src/interface.c:567 msgid "Hexadecimal data to send (separator : ';' or space) : " msgstr "ШеÑтнадцатеричные данные Ð´Ð»Ñ Ð¾Ñ‚Ð¿Ñ€Ð°Ð²ÐºÐ¸ (разделитель: ';' или пробел): " #: ../src/interface.c:736 msgid "" "GTKTerm is a simple GTK+ terminal used to communicate with the serial port." msgstr "" #: ../src/interface.c:776 #, fuzzy msgid "Break signal sent!" msgstr "Отравлен Ñигнал break!" #: ../src/interface.c:882 #, fuzzy, c-format msgid "0 byte(s) sent!" msgstr "\"%s\": %d байт(а) отправлено!" #: ../src/interface.c:896 msgid "Improper formatted hex input, 0 bytes sent!" msgstr "" #: ../src/interface.c:907 #, fuzzy, c-format msgid "%d byte(s) sent!" msgstr "\"%s\": %d байт(а) отправлено!" #: ../src/logging.c:49 #, fuzzy, c-format msgid "Filename error\n" msgstr "Ошибка файла\n" #: ../src/logging.c:88 #, fuzzy msgid "Log file selection" msgstr "Выбор файла" #: ../src/logging.c:184 msgid "Failed to log data\n" msgstr "" #: ../src/macros.c:144 #, c-format msgid "Macro \"%s\" sent !" msgstr "ÐœÐ°ÐºÑ€Ð¾Ñ \"%s\" отправлен!" #: ../src/macros.c:275 msgid "Shortcut" msgstr "ÐšÐ¾Ð¼Ð±Ð¸Ð½Ð°Ñ†Ð¸Ñ ÐºÐ»Ð°Ð²Ð¸Ñˆ" #: ../src/macros.c:432 msgid "" "The \"action\" field of a macro is the data to be sent on the port. Text can " "be entered, but also special chars, like \\n, \\t, \\r, etc. You can also " "enter hexadecimal data preceded by a '\\'. The hexadecimal data should not " "begin with a letter (eg. use \\0FF and not \\FF)\n" "Examples :\n" "\t\"Hello\\n\" sends \"Hello\" followed by a Line Feed\n" "\t\"Hello\\0A\" does the same thing but the LF is entered in hexadecimal" msgstr "" "Поле \"дейÑтвие\" макроÑа -- Ñто данные отправлÑемые в порт. Может Ñодержать " "текÑÑ‚ и Ñпециальные Ñимволы, такие как \\n, \\t, \\r и пр. Также можно " "вводить шеÑтнадцатеричные данные поÑле '\\'. ШеÑтнадцатеричные данные не " "должны начинатьÑÑ Ñ Ð±ÑƒÐºÐ²Ñ‹ (иÑпользуйте \\0FF вмеÑто \\FF)\n" "Примеры:\n" "\t\"Hello\\n\" отправлÑет \"Hello\" и поÑледующий Ñимвол новой Ñтроки\n" "\t\"Hello\\0A\" делает тоже Ñамое, но Ñимвол новой Ñтроки указан " "шеÑтнадцатеричным кодом" #: ../src/macros.c:452 msgid "Configure Macros" msgstr "ÐаÑтройка макроÑов" #: ../src/macros.c:489 msgid "_Add" msgstr "Доб_авить" #: ../src/macros.c:493 msgid "_Delete" msgstr "У_далить" #: ../src/macros.c:497 msgid "_Capture Shortcut" msgstr "_Захватить комбинацию клавиш" #: ../src/parsecfg.c:355 #, c-format msgid "Cannot open configuration file `%s'.\n" msgstr "Ðевозможно открыть файл наÑтроек \"%s\".\n" #: ../src/parsecfg.c:358 #, c-format msgid "Cannot create configuration file `%s'.\n" msgstr "Ðевозможно Ñоздать файл наÑтроек \"%s\".\n" #: ../src/parsecfg.c:361 #, c-format msgid "" "%s(%d): %s\n" "Syntax error\n" msgstr "" "%s(%d): %s\n" "СинтакÑичеÑÐºÐ°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°\n" #: ../src/parsecfg.c:364 #, c-format msgid "" "%s(%d): %s\n" "Unrecognized parameter\n" msgstr "" "%s(%d): %s\n" "ÐераÑпознанный параметр\n" #: ../src/parsecfg.c:367 #, c-format msgid "" "%s(%d): %s\n" "Internal error\n" msgstr "" "%s(%d): %s\n" "ВнутреннÑÑ Ð¾ÑˆÐ¸Ð±ÐºÐ°\n" #: ../src/parsecfg.c:370 #, c-format msgid "" "%s(%d): %s\n" "Invalid number\n" msgstr "" "%s(%d): %s\n" "Ðеверный номер\n" #: ../src/parsecfg.c:373 #, c-format msgid "" "%s(%d): %s\n" "Out of range\n" msgstr "" "%s(%d): %s\n" "Вне диапазона\n" #: ../src/parsecfg.c:376 #, c-format msgid "" "%s(%d): %s\n" "Cannot allocate memory.\n" msgstr "" "%s(%d): %s\n" "Ðевозможно выделить памÑть.\n" #: ../src/parsecfg.c:379 #, c-format msgid "" "%s(%d): %s\n" "It must be specified TRUE or FALSE.\n" msgstr "" "%s(%d): %s\n" "Должно быть указано TRUE или FALSE.\n" #: ../src/parsecfg.c:382 #, c-format msgid "" "%s(%d): %s\n" "The section name is already used.\n" msgstr "" "%s(%d): %s\n" "Ðазвание раздела уже иÑпользуетÑÑ.\n" #: ../src/parsecfg.c:385 #, c-format msgid "" "%s(%d)\n" "There is no closing bracket.\n" msgstr "" "%s(%d)\n" "Ðет закрывающей Ñкобки.\n" #: ../src/parsecfg.c:390 #, c-format msgid "" "%s(%d): %s\n" "Unexplained error\n" msgstr "" "%s(%d): %s\n" "ÐеобъÑÑÐ½Ð¸Ð¼Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°\n" #: ../src/serial.c:154 #, fuzzy, c-format msgid "Cannot open %s: %s\n" msgstr "Ðевозможно открыть %s: %s\n" #: ../src/serial.c:167 #, c-format msgid "" "Cannot lock port! The serial port may currently be in use by another " "program.\n" msgstr "" #: ../src/serial.c:235 #, c-format msgid "Arbitrary baud rates not supported" msgstr "" #: ../src/serial.c:352 ../src/serial.c:398 msgid "Control signals read" msgstr "Получен управлÑющий Ñигнал" #: ../src/serial.c:364 msgid "DTR write" msgstr "DTR запиÑан" #: ../src/serial.c:374 msgid "RTS write" msgstr "RTS запиÑан" #: ../src/serial.c:452 msgid "No open port" msgstr "Порт не открыт" #: ../src/term_config.c:193 #, fuzzy msgid "" "No serial devices found!\n" "\n" "Searched the following device path patterns:\n" "\t/dev/ttyS*\n" "\t/dev/tts/*\n" "\t/dev/ttyUSB*\n" "\t/dev/usb/tts/*\n" "\n" "Enter a different device path in the 'Port' box.\n" msgstr "" "УÑтройÑтво поÑледовательного порта не найдено в /dev!\n" "Должно быть Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ одно из Ñледующих:\n" "/dev/ttyS*\n" "/dev/tts/*\n" "/dev/ttyUSB*\n" "/dev/usb/tts/*\n" #: ../src/term_config.c:202 msgid "Configuration" msgstr "ÐаÑтройка" #: ../src/term_config.c:206 msgid "Serial port" msgstr "ПоÑледовательный порт" #: ../src/term_config.c:212 #, fuzzy msgid "Port:" msgstr "Порт:" #: ../src/term_config.c:214 msgid "Baud Rate:" msgstr "" #: ../src/term_config.c:216 #, fuzzy msgid "Parity:" msgstr "Проверка чётноÑти:" #: ../src/term_config.c:362 #, fuzzy msgid "Bits:" msgstr "Биты:" #: ../src/term_config.c:364 #, fuzzy msgid "Stopbits:" msgstr "Стоп-бит:" #: ../src/term_config.c:366 #, fuzzy msgid "Flow control:" msgstr "Управление потоком:" #. create an expander widget to hide the 'Advanced features' #: ../src/term_config.c:417 #, fuzzy msgid "Advanced Configuration Options" msgstr "ÐаÑтройки" #: ../src/term_config.c:422 msgid "ASCII file transfer" msgstr "Передача ASCII-файла" #: ../src/term_config.c:428 #, fuzzy msgid "End of line delay (milliseconds):" msgstr "Задержка конца Ñтроки, мÑ:" #: ../src/term_config.c:444 #, fuzzy msgid "Wait for this special character before passing to next line:" msgstr "Ожидать Ñпециальный Ñимвол до передачи Ñледующей Ñтроки:" #: ../src/term_config.c:457 msgid "RS-485 half-duplex parameters (RTS signal used to send)" msgstr "" #: ../src/term_config.c:464 msgid "Time with RTS 'on' before transmit (milliseconds):" msgstr "" #: ../src/term_config.c:466 msgid "Time with RTS 'on' after transmit (milliseconds):" msgstr "" #: ../src/term_config.c:591 msgid "Load configuration" msgstr "Загрузить наÑтройку" #: ../src/term_config.c:601 msgid "Delete configuration" msgstr "Удалить наÑтройку" #: ../src/term_config.c:631 ../src/term_config.c:896 msgid "" "Cannot read configuration file!\n" "Config file may contain invalid parameter.\n" msgstr "" #: ../src/term_config.c:637 msgid "Configurations" msgstr "ÐаÑтройки" #: ../src/term_config.c:704 msgid "Save configuration" msgstr "Сохранить наÑтройку" #: ../src/term_config.c:716 #, fuzzy msgid "Configuration name: " msgstr "Ðазвание наÑтройки: " #: ../src/term_config.c:750 msgid "" "Cannot save configuration file!\n" "Config file may contain invalid parameter.\n" msgstr "" #: ../src/term_config.c:770 #, fuzzy msgid "Cannot overwrite section!" msgstr "Ðевозможно перезапиÑать раздел!" #: ../src/term_config.c:775 #, fuzzy msgid "Cannot read configuration file!" msgstr "Ðевозможно прочитать файл наÑтройки!" #: ../src/term_config.c:785 #, c-format msgid "Configuration [%s] saved\n" msgstr "ÐаÑтройка [%s] Ñохранена\n" #: ../src/term_config.c:804 msgid "" "Cannot write configuration file!\n" "Config file may contain invalid parameter.\n" msgstr "" #: ../src/term_config.c:819 #, fuzzy, c-format msgid "" "Section [%s] already exists.\n" "\n" "Do you want to overwrite it ?" msgstr "" "\n" "Раздел [%s] уже ÑущеÑтвует.\n" "Хотите перезапиÑать его?\n" #: ../src/term_config.c:879 #, fuzzy msgid "Cannot delete section!" msgstr "Ðевозможно удалить раздел!" #: ../src/term_config.c:1060 #, c-format msgid "No section \"%s\" in configuration file\n" msgstr "Раздела \"%s\" нет в файле наÑтроек\n" #: ../src/term_config.c:1105 #, c-format msgid "Baudrate %d may not be supported by all hardware" msgstr "" #: ../src/term_config.c:1112 #, fuzzy, c-format msgid "" "Invalid number of stop-bits: %d\n" "Falling back to default number of stop-bits number: %d\n" msgstr "" "Ðевозможное количеÑтво Ñтоп-бит: %d\n" "ИÑпользуетÑÑ ÐºÐ¾Ð»Ð¸Ñ‡ÐµÑтво Ñтоп-бит по умолчанию: %d\n" #: ../src/term_config.c:1120 #, fuzzy, c-format msgid "" "Invalid number of bits: %d\n" "Falling back to default number of bits: %d\n" msgstr "" "Ðевозможное количеÑтво бит: %d\n" "ИÑпользуетÑÑ ÐºÐ¾Ð»Ð¸Ñ‡ÐµÑтво бит по умолчанию: %d\n" #: ../src/term_config.c:1128 #, fuzzy, c-format msgid "" "Invalid delay: %d ms\n" "Falling back to default delay: %d ms\n" msgstr "" "ÐÐµÐ²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð°Ñ Ð·Ð°Ð´ÐµÑ€Ð¶ÐºÐ°: %d мÑ\n" "ИÑпользуетÑÑ Ð·Ð°Ð´ÐµÑ€Ð¶ÐºÐ° по умолчанию: %d мÑ\n" #: ../src/term_config.c:1158 #, c-format msgid "" "Configuration file (%s) with\n" "[default] configuration has been created.\n" msgstr "" "Создан файл наÑтроек (%s)\n" "Ñ Ð½Ð°Ñтройкой по умолчанию [default].\n" #: ../src/term_config.c:1414 #, c-format msgid "Cannot find section %s\n" msgstr "Ðевозможно найти раздел %s\n" #: ../src/term_config.c:1454 msgid "Main Window" msgstr "" #~ msgid "\t http://www.jls-info.com/julien/linux\n" #~ msgstr "\t http://www.jls-info.com/julien/linux\n" #~ msgid "Speed :" #~ msgstr "СкороÑть:" #~ msgid "Font selection" #~ msgstr "Выбор шрифта" #~ msgid "Cannot read configuration file !\n" #~ msgstr "Ðевозможно прочитать файл наÑтройки!\n" #~ msgid "Warning !" #~ msgstr "Предупреждение!" #~ msgid "" #~ "Unknown speed : %d bauds\n" #~ "Falling back to default speed : %d bauds\n" #~ msgstr "" #~ "ÐеизвеÑÑ‚Ð½Ð°Ñ ÑкороÑть: %d бод\n" #~ "ИÑпользуетÑÑ ÑкороÑть по умолчанию: %d бод\n" #~ msgid "Terminal configuration" #~ msgstr "ÐаÑтройка терминала" #~ msgid "Font selection : " #~ msgstr "Шрифт: " #~ msgid "Show cursor" #~ msgstr "Отображать курÑор" #~ msgid "Text color :" #~ msgstr "Цвет текÑта: " #~ msgid "Background color :" #~ msgstr "Цвет фона: " #~ msgid "Transparency : " #~ msgstr "ПрозрачноÑть: " #~ msgid "Transparency enable" #~ msgstr "Включить прозрачноÑть" #~ msgid "Changing text color" #~ msgstr "Выбор цвета текÑта" #~ msgid "Changing background color" #~ msgstr "Выбор цвета фона" #~ msgid "%v / %u Kb (%p %%)" #~ msgstr "%v / %u Кб (%p %%)" #~ msgid "%v / %u bytes (%p %%)" #~ msgstr "%v / %u байт (%p %%)" #~ msgid "Cannot write file %s\n" #~ msgstr "Ðевозможно запиÑать файл %s\n" #~ msgid "" #~ "\n" #~ "File \"%s\" already exists.\n" #~ "Do you want to overwrite it ?\n" #~ msgstr "" #~ "\n" #~ "Файл \"%s\" уже ÑущеÑтвует.\n" #~ "Хотите перезапиÑать его?\n" #~ msgid "Help on macros" #~ msgstr "Помощь по макроÑам" #~ msgid "Lockfile is stale. Overriding it..\n" #~ msgstr "Файл блокировки уÑтарел. Ðннулирован...\n" #~ msgid "Device %s is locked.\n" #~ msgstr "УÑтройÑтво %s заблокировано.\n" #~ msgid "Cannot create lockfile. Sorry.\n" #~ msgstr "Ðевозможно Ñоздать файл блокировки.\n" #~ msgid "/File/E_xit" #~ msgstr "/Файл/Ð’_ыйти" #~ msgid "/Configuration/_Port" #~ msgstr "/ÐаÑтройка/_Порт" #~ msgid "/Configuration/Local _echo" #~ msgstr "/ÐаÑтройка/Локальный _вывод" #~ msgid "/Configuration/_CR LF auto" #~ msgstr "/Configuration/_Ðвто CR LF" #~ msgid "/Configuration/_Macros" #~ msgstr "/ÐаÑтройка/_МакроÑÑ‹" #~ msgid "/Configuration/_Load configuration" #~ msgstr "/ÐаÑтройка/_Загрузить наÑтройку" #~ msgid "/Configuration/_Save configuration" #~ msgstr "/ÐаÑтройка/_Сохранить наÑтройку" #~ msgid "/Configuration/_Delete configuration" #~ msgstr "/ÐаÑтройка/У_далить наÑтройку" #~ msgid "/Control signals/Send break" #~ msgstr "/Сигналы управлениÑ/Отправить break" #~ msgid "/Control signals/Toggle DTR" #~ msgstr "/Сигналы управлениÑ/Переключить DTR" #~ msgid "/Control signals/Toggle RTS" #~ msgstr "/Сигналы управлениÑ/Переключить RTS" #~ msgid "/View/Hexadecimal chars/_8" #~ msgstr "/Вид/ШеÑтнадцатеричные Ñимволы/_8" #~ msgid "/View/Hexadecimal chars/1_0" #~ msgstr "/Вид/ШеÑтнадцатеричные Ñимволы/1_0" #~ msgid "/View/Hexadecimal chars/_16" #~ msgstr "/Вид/ШеÑтнадцатеричные Ñимволы/_16" #~ msgid "/View/Hexadecimal chars/_24" #~ msgstr "/Вид/ШеÑтнадцатеричные Ñимволы/_24" #~ msgid "/View/Hexadecimal chars/_32" #~ msgstr "/Вид/ШеÑтнадцатеричные Ñимволы/_32" #~ msgid "/Help/_About..." #~ msgstr "/Помощь/_О программе..." #~ msgid "About..." #~ msgstr "О программе..." #~ msgid "" #~ "\n" #~ " GTKTerm V. %s \n" #~ "\n" #~ "\t(c) Julien Schmitt : julien@jls-info.com \n" #~ "\thttp://www.jls-info.com/julien/linux\n" #~ msgstr "" #~ "\n" #~ " GTKTerm верÑии %s \n" #~ "\n" #~ "\t(c) Julien Schmitt: julien@jls-info.com \n" #~ "\thttp://www.jls-info.com/julien/linux\n" gtkterm-1.1.1/po/zh_CN.po000066400000000000000000000412771376216657300152010ustar00rootroot00000000000000# Chinese (China) translation for gtkterm package. # This file is distributed under the same license as the gtkterm package. # # 玉堂白鹤 , 2019. # msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2020-03-09 10:42+0100\n" "PO-Revision-Date: 2020-03-10 14:11+0800\n" "Last-Translator: 玉堂白鹤 \n" "Language-Team: \n" "Language: zh_CN\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 2.3\n" #: ../src/buffer.c:164 msgid "ERROR : Buffer is not initialized !\n" msgstr "错误:缓冲区未åˆå§‹åŒ–ï¼\n" #: ../src/cmdline.c:37 #, c-format msgid "" "\n" "GTKTerm version %s\n" msgstr "" "\n" "GTKTerm 版本 %s\n" #: ../src/cmdline.c:38 msgid "\t (c) Julien Schmitt\n" msgstr "\t (c) Julien Schmitt\n" #: ../src/cmdline.c:39 msgid "" "\n" "This program is released under the terms of the GPL V.2\n" msgstr "" "\n" "è¯¥ç¨‹åºæ ¹æ® GPL V.2 çš„æ¡æ¬¾å‘布\n" #: ../src/cmdline.c:40 msgid "\t ** Use at your own risks ! **\n" msgstr "\t ** ä½¿ç”¨é£Žé™©è‡ªè´Ÿï¼ **\n" #: ../src/cmdline.c:41 msgid "" "\n" "Command line options\n" msgstr "" "\n" "命令行选项\n" #: ../src/cmdline.c:42 msgid "--help or -h : this help screen\n" msgstr "--help 或 -h:此帮助å±å¹•\n" #: ../src/cmdline.c:43 msgid "--config or -c : load configuration\n" msgstr "--config 或 -c:加载é…ç½®\n" #: ../src/cmdline.c:44 msgid "--port or -p : serial port device (default /dev/ttyS0)\n" msgstr "--port 或 -p :串å£è®¾å¤‡ (默认为 /dev/ttyS0)\n" #: ../src/cmdline.c:45 msgid "--speed or -s : serial port speed (default 9600)\n" msgstr "--speed 或 -s :串å£é€Ÿçއ (默认为 9600)\n" #: ../src/cmdline.c:46 msgid "--bits or -b : number of bits (default 8)\n" msgstr "--bits 或 -b :数æ®ä½ (默认为 8)\n" #: ../src/cmdline.c:47 msgid "--stopbits or -t : number of stopbits (default 1)\n" msgstr "--stopbits or -t ï¼šåœæ­¢ä½ (默认为 1)\n" #: ../src/cmdline.c:48 msgid "--parity or -a : parity (default none)\n" msgstr "--parity 或 -a ï¼šå¥‡å¶æ ¡éªŒ (默认为 none)\n" #: ../src/cmdline.c:49 msgid "--flow or -w : flow control (default none)\n" msgstr "--flow 或 -w ï¼šæ•°æ®æµæŽ§åˆ¶ (默认为 none)\n" #: ../src/cmdline.c:50 msgid "--delay or -d : end of line delay in ms (default none)\n" msgstr "--delay or -d :行末延迟(ms) (默认 none)\n" #: ../src/cmdline.c:51 msgid "" "--char or -r : wait for a special char at end of line (default none)\n" msgstr "--char or -r : 在行尾等待特殊字符 (默认为 none)\n" #: ../src/cmdline.c:52 msgid "--file or -f : default file to send (default none)\n" msgstr "--file or -f :è¦å‘é€çš„默认文件 (默认为 none)\n" #: ../src/cmdline.c:53 msgid "" "--rts_time_before or -x : for RS-485, time in ms before transmit with " "rts on\n" msgstr "" #: ../src/cmdline.c:54 msgid "" "--rts_time_after or -y : for RS-485, time in ms after transmit with rts " "on\n" msgstr "" #: ../src/cmdline.c:55 msgid "--echo or -e : switch on local echo\n" msgstr "--echo 或 -e :打开本地回显\n" #: ../src/cmdline.c:56 msgid "" "--disable-port-lock or -L: does not lock serial port. Allows to send to " "serial port from different terminals\n" msgstr "" "--disable-port-lock 或 -L: ä¸é”定串行端å£ã€‚å…许从ä¸åŒçš„终端å‘é€åˆ°ä¸²å£\n" #: ../src/cmdline.c:57 msgid "" " Note: incoming data are displayed randomly on only " "one terminal\n" msgstr " 注æ„: 传入数æ®ä»…åœ¨ä¸€ä¸ªç»ˆç«¯ä¸Šéšæœºæ˜¾ç¤º\n" #: ../src/cmdline.c:167 msgid "Undefined command line option\n" msgstr "错误ç†è§£å‘½ä»¤è¡Œé€‰é¡¹\n" #: ../src/files.c:77 msgid "Send RAW File" msgstr "å‘é€ RAW 文件" #: ../src/files.c:96 #, c-format msgid "Error opening file\n" msgstr "打开文件出错\n" #: ../src/files.c:110 #, c-format msgid "%s : transfer in progress..." msgstr "%s :传输中..." #: ../src/files.c:128 msgid "Cancel" msgstr "å–æ¶ˆ" #: ../src/files.c:143 #, c-format msgid "Cannot read file %s: %s\n" msgstr "æ— æ³•è¯»å–æ–‡ä»¶ %s: %s\n" #: ../src/files.c:178 #, c-format msgid "Error sending file\n" msgstr "å‘逿–‡ä»¶å‡ºé”™\n" #: ../src/files.c:206 #, c-format msgid "Error sending file: %s\n" msgstr "å‘逿–‡ä»¶å‡ºé”™ï¼š%s\n" #: ../src/files.c:292 msgid "Save RAW File" msgstr "ä¿å­˜ RAW 文件" #: ../src/files.c:311 #, c-format msgid "File error\n" msgstr "文件错误\n" #: ../src/files.c:322 ../src/logging.c:68 ../src/logging.c:123 #, c-format msgid "Cannot open file %s: %s\n" msgstr "无法打开文件 %s: %s\n" #. Toplevel #: ../src/interface.c:145 msgid "_File" msgstr "文件(_F)" #: ../src/interface.c:146 msgid "_Edit" msgstr "编辑(_E)" #: ../src/interface.c:147 msgid "_Log" msgstr "日志(_L)" #: ../src/interface.c:148 msgid "_Configuration" msgstr "é…ç½®(_C)" #: ../src/interface.c:149 msgid "Control _signals" msgstr "控制信å·(_S)" #: ../src/interface.c:150 msgid "_View" msgstr "视图(_V)" #: ../src/interface.c:151 msgid "Hexadecimal _chars" msgstr "å六进制字符(_C)" #: ../src/interface.c:152 msgid "_Help" msgstr "帮助(_F)" #: ../src/interface.c:156 msgid "_Clear screen" msgstr "清除å±å¹•(_C)" #: ../src/interface.c:157 msgid "_Clear scrollback" msgstr "清除回滚(_C)" #: ../src/interface.c:158 msgid "Send _RAW file" msgstr "å‘é€ RAW 文件(_R)" #: ../src/interface.c:159 msgid "_Save RAW file" msgstr "ä¿å­˜ RAW 文件(_S)" #. Log Menu #: ../src/interface.c:167 msgid "To file..." msgstr "至文件..." #. Confuguration Menu #: ../src/interface.c:173 msgid "_Port" msgstr "端å£(_P)" #: ../src/interface.c:174 msgid "_Main window" msgstr "主窗å£(_M)" #: ../src/interface.c:175 msgid "_Macros" msgstr "å®(_M)" #: ../src/interface.c:176 msgid "_Load configuration" msgstr "加载é…ç½®(_L)" #: ../src/interface.c:177 msgid "_Save configuration" msgstr "ä¿å­˜é…ç½®(_S)" #: ../src/interface.c:178 msgid "_Delete configuration" msgstr "删除é…ç½®(_D)" #. Signals Menu #: ../src/interface.c:181 msgid "Send break" msgstr "å‘é€ä¸­æ–­" #: ../src/interface.c:182 msgid "_Open Port" msgstr "打开端å£(_O)" #: ../src/interface.c:183 msgid "_Close Port" msgstr "关闭端å£(_C)" #: ../src/interface.c:184 msgid "Toggle DTR" msgstr "åˆ‡æ¢ DTR" #: ../src/interface.c:185 msgid "Toggle RTS" msgstr "åˆ‡æ¢ RTS" #. Configuration Menu #: ../src/interface.c:194 msgid "Local _echo" msgstr "本地回显(_E)" #: ../src/interface.c:195 msgid "_CR LF auto" msgstr "CR LF 自动(_C)" #: ../src/interface.c:196 msgid "Timestamp" msgstr "时间戳" #. View Menu #: ../src/interface.c:199 msgid "Show _index" msgstr "显示索引(_I)" #: ../src/interface.c:200 msgid "_Send hexadecimal data" msgstr "å‘é€å六进制数æ®(_S)" #: ../src/interface.c:205 msgid "_ASCII" msgstr "ASCII(_A)" #: ../src/interface.c:206 msgid "_Hexadecimal" msgstr "å六进制(_H)" #: ../src/interface.c:422 msgid "Resume" msgstr "æ¢å¤" #: ../src/interface.c:567 msgid "Hexadecimal data to send (separator : ';' or space) : " msgstr "è¦å‘é€çš„å六进制数æ®(分隔符 : ';' 或空格) : " #: ../src/interface.c:736 msgid "" "GTKTerm is a simple GTK+ terminal used to communicate with the serial port." msgstr "" "GTKTerm 是一个简å•çš„ GTK+ 终端,用于与串行端å£è¿›è¡Œé€šä¿¡ã€‚" #: ../src/interface.c:776 msgid "Break signal sent!" msgstr "中断信å·å‘é€ï¼" #: ../src/interface.c:882 #, c-format msgid "0 byte(s) sent!" msgstr "å·²å‘é€ 0 个字节ï¼" #: ../src/interface.c:896 msgid "Improper formatted hex input, 0 bytes sent!" msgstr "å六进制输入格å¼ä¸æ­£ç¡®ï¼Œå·²å‘é€ 0 个字节ï¼" #: ../src/interface.c:907 #, c-format msgid "%d byte(s) sent!" msgstr "å·²å‘é€ %d 个字节ï¼" #: ../src/logging.c:49 #, c-format msgid "Filename error\n" msgstr "文件å错误\n" #: ../src/logging.c:88 msgid "Log file selection" msgstr "日志文件选择" #: ../src/logging.c:184 msgid "Failed to log data\n" msgstr "记录数æ®å¤±è´¥\n" #: ../src/macros.c:144 #, c-format msgid "Macro \"%s\" sent !" msgstr "å® \"%s\"å·²å‘é€ï¼" #: ../src/macros.c:275 msgid "Shortcut" msgstr "å¿«æ·é”®" #: ../src/macros.c:432 msgid "" "The \"action\" field of a macro is the data to be sent on the port. Text can " "be entered, but also special chars, like \\n, \\t, \\r, etc. You can also " "enter hexadecimal data preceded by a '\\'. The hexadecimal data should not " "begin with a letter (eg. use \\0FF and not \\FF)\n" "Examples :\n" "\t\"Hello\\n\" sends \"Hello\" followed by a Line Feed\n" "\t\"Hello\\0A\" does the same thing but the LF is entered in hexadecimal" msgstr "" "å®çš„ \"action\" 字段是è¦åœ¨ç«¯å£ä¸Šå‘é€çš„æ•°æ®ã€‚ å¯ä»¥è¾“入文本,但也å¯ä»¥è¾“入特殊字" "符,例如\\n,\\t,\\r,等。您还å¯ä»¥è¾“入以 '\\' 头的å六进制数æ®ã€‚ å六进制数" "æ®ä¸åº”以字æ¯å¼€å¤´(例如,使用 \\0FF è€Œä¸æ˜¯\\FF)\n" "例如 :\n" "\t\"Hello\\n\" å‘é€â€œ Helloâ€ï¼ŒåŽè·Ÿæ¢è¡Œ\n" "\t\"Hello\\0A\" 执行相åŒçš„æ“ä½œï¼Œä½†æ˜¯ LF 以å六进制输入" #: ../src/macros.c:452 msgid "Configure Macros" msgstr "é…ç½®å®" #: ../src/macros.c:489 msgid "_Add" msgstr "添加(_A)" #: ../src/macros.c:493 msgid "_Delete" msgstr "删除(_D)" #: ../src/macros.c:497 msgid "_Capture Shortcut" msgstr "æ•æ‰å¿«æ·é”®" #: ../src/parsecfg.c:355 #, c-format msgid "Cannot open configuration file `%s'.\n" msgstr "无法打开é…置文件 `%s'.\n" #: ../src/parsecfg.c:358 #, c-format msgid "Cannot create configuration file `%s'.\n" msgstr "无法创建é…置文件 `%s'.\n" #: ../src/parsecfg.c:361 #, c-format msgid "" "%s(%d): %s\n" "Syntax error\n" msgstr "" "%s(%d): %s\n" "语法错误\n" #: ../src/parsecfg.c:364 #, c-format msgid "" "%s(%d): %s\n" "Unrecognized parameter\n" msgstr "" "%s(%d): %s\n" "æ— æ³•è¯†åˆ«çš„å‚æ•°\n" #: ../src/parsecfg.c:367 #, c-format msgid "" "%s(%d): %s\n" "Internal error\n" msgstr "" "%s(%d): %s\n" "内部错误\n" #: ../src/parsecfg.c:370 #, c-format msgid "" "%s(%d): %s\n" "Invalid number\n" msgstr "" "%s(%d): %s\n" "无效数值\n" #: ../src/parsecfg.c:373 #, c-format msgid "" "%s(%d): %s\n" "Out of range\n" msgstr "" "%s(%d): %s\n" "超出范围\n" #: ../src/parsecfg.c:376 #, c-format msgid "" "%s(%d): %s\n" "Cannot allocate memory.\n" msgstr "" "%s(%d): %s\n" "无法分é…内存。\n" #: ../src/parsecfg.c:379 #, c-format msgid "" "%s(%d): %s\n" "It must be specified TRUE or FALSE.\n" msgstr "" "%s(%d): %s\n" "必须将其指定为 TRU E或 FALSE。\n" #: ../src/parsecfg.c:382 #, c-format msgid "" "%s(%d): %s\n" "The section name is already used.\n" msgstr "" "%s(%d): %s\n" "这个é…置部分å称已被使用。\n" #: ../src/parsecfg.c:385 #, c-format msgid "" "%s(%d)\n" "There is no closing bracket.\n" msgstr "" "%s(%d)\n" "æ²¡æœ‰å³æ‹¬å·ã€‚\n" #: ../src/parsecfg.c:390 #, c-format msgid "" "%s(%d): %s\n" "Unexplained error\n" msgstr "" "%s(%d): %s\n" "未知错误\n" #: ../src/serial.c:154 #, c-format msgid "Cannot open %s: %s\n" msgstr "无法打开 %s: %s\n" #: ../src/serial.c:167 #, c-format msgid "" "Cannot lock port! The serial port may currently be in use by another " "program.\n" msgstr "无法é”定端å£ï¼ 串行端å£å½“å‰å¯èƒ½æ­£åœ¨è¢«å¦ä¸€ä¸ªç¨‹åºä½¿ç”¨ã€‚\n" #: ../src/serial.c:235 #, c-format msgid "Arbitrary baud rates not supported" msgstr "䏿”¯æŒä»»æ„波特率" #: ../src/serial.c:352 ../src/serial.c:398 msgid "Control signals read" msgstr "è¯»å–æŽ§åˆ¶ä¿¡å·" #: ../src/serial.c:364 msgid "DTR write" msgstr "写入 DTR" #: ../src/serial.c:374 msgid "RTS write" msgstr "写入 RTS" #: ../src/serial.c:452 msgid "No open port" msgstr "无打开的端å£" #: ../src/term_config.c:193 msgid "" "No serial devices found!\n" "\n" "Searched the following device path patterns:\n" "\t/dev/ttyS*\n" "\t/dev/tts/*\n" "\t/dev/ttyUSB*\n" "\t/dev/usb/tts/*\n" "\n" "Enter a different device path in the 'Port' box.\n" msgstr "" "找ä¸åˆ°ä¸²è¡Œè®¾å¤‡ï¼\n" "\n" "æœç´¢ä»¥ä¸‹è·¯å¾„:\n" "\t/dev/ttyS*\n" "\t/dev/tts/*\n" "\t/dev/ttyUSB*\n" "\t/dev/usb/tts/*\n" "\n" "在“端å£â€æ¡†ä¸­è¾“入其他设备路径。\n" #: ../src/term_config.c:202 msgid "Configuration" msgstr "é…ç½®" #: ../src/term_config.c:206 msgid "Serial port" msgstr "串行端å£" #: ../src/term_config.c:212 msgid "Port:" msgstr "端å£ï¼š" #: ../src/term_config.c:214 msgid "Baud Rate:" msgstr "波特率:" #: ../src/term_config.c:216 msgid "Parity:" msgstr "奇嶿 ¡éªŒ:" #: ../src/term_config.c:362 msgid "Bits:" msgstr "æ•°æ®ä½:" #: ../src/term_config.c:364 msgid "Stopbits:" msgstr "åœæ­¢ä½:" #: ../src/term_config.c:366 msgid "Flow control:" msgstr "æ•°æ®æµæŽ§åˆ¶:" #. create an expander widget to hide the 'Advanced features' #: ../src/term_config.c:417 msgid "Advanced Configuration Options" msgstr "高级é…置选项" #: ../src/term_config.c:422 msgid "ASCII file transfer" msgstr "ASCII 文件传输" #: ../src/term_config.c:428 msgid "End of line delay (milliseconds):" msgstr "行末延迟 (毫秒):" #: ../src/term_config.c:444 msgid "Wait for this special character before passing to next line:" msgstr "传递到下一行之å‰ç­‰å¾…这个特殊字符:" #: ../src/term_config.c:457 msgid "RS-485 half-duplex parameters (RTS signal used to send)" msgstr "RS-485 åŠåŒå·¥å‚æ•°(用于å‘é€RTSä¿¡å·)" #: ../src/term_config.c:464 msgid "Time with RTS 'on' before transmit (milliseconds):" msgstr "" #: ../src/term_config.c:466 msgid "Time with RTS 'on' after transmit (milliseconds):" msgstr "" #: ../src/term_config.c:591 msgid "Load configuration" msgstr "加载é…ç½®" #: ../src/term_config.c:601 msgid "Delete configuration" msgstr "删除é…ç½®" #: ../src/term_config.c:631 ../src/term_config.c:896 msgid "" "Cannot read configuration file!\n" "Config file may contain invalid parameter.\n" msgstr "" "无法读å–é…置文件ï¼\n" "é…置文件å¯èƒ½åŒ…嫿— æ•ˆçš„傿•°ã€‚\n" #: ../src/term_config.c:637 msgid "Configurations" msgstr "é…ç½®" #: ../src/term_config.c:704 msgid "Save configuration" msgstr "ä¿å­˜é…ç½®" #: ../src/term_config.c:716 msgid "Configuration name: " msgstr "é…ç½®å称: " #: ../src/term_config.c:750 msgid "" "Cannot save configuration file!\n" "Config file may contain invalid parameter.\n" msgstr "" "无法ä¿å­˜é…置文件ï¼\n" "é…置文件å¯èƒ½åŒ…嫿— æ•ˆçš„傿•°ã€‚\n" #: ../src/term_config.c:770 msgid "Cannot overwrite section!" msgstr "无法覆盖该é…置部分ï¼" #: ../src/term_config.c:775 msgid "Cannot read configuration file!" msgstr "无法读å–é…置文件ï¼" #: ../src/term_config.c:785 #, c-format msgid "Configuration [%s] saved\n" msgstr "é…ç½® [%s] å·²ä¿å­˜\n" #: ../src/term_config.c:804 msgid "" "Cannot write configuration file!\n" "Config file may contain invalid parameter.\n" msgstr "" "无法写入é…置文件ï¼\n" "é…置文件å¯èƒ½åŒ…嫿— æ•ˆçš„傿•°ã€‚\n" #: ../src/term_config.c:819 #, c-format msgid "" "Section [%s] already exists.\n" "\n" "Do you want to overwrite it ?" msgstr "" " [%s] é…置部分已存在。\n" "\n" "您è¦è¦†ç›–它å—?" #: ../src/term_config.c:879 msgid "Cannot delete section!" msgstr "无法删除该é…置部分ï¼" #: ../src/term_config.c:1060 #, c-format msgid "No section \"%s\" in configuration file\n" msgstr "é…置文件中无 \"%s\" 部分\n" #: ../src/term_config.c:1105 #, c-format msgid "Baudrate %d may not be supported by all hardware" msgstr "䏿˜¯æ‰€æœ‰ç¡¬ä»¶éƒ½æ”¯æŒæ³¢ç‰¹çއ %d" #: ../src/term_config.c:1112 #, c-format msgid "" "Invalid number of stop-bits: %d\n" "Falling back to default number of stop-bits number: %d\n" msgstr "" "æ— æ•ˆçš„åœæ­¢ä½ï¼š%d\n" "é€€å›žåˆ°é»˜è®¤çš„åœæ­¢ä½ï¼š%d\n" #: ../src/term_config.c:1120 #, c-format msgid "" "Invalid number of bits: %d\n" "Falling back to default number of bits: %d\n" msgstr "" "无效的数æ®ä½ï¼š%d\n" "退回到默认的数æ®ä½ï¼š%d\n" #: ../src/term_config.c:1128 #, c-format msgid "" "Invalid delay: %d ms\n" "Falling back to default delay: %d ms\n" msgstr "" "无效的延迟: %d ms\n" "退回到默认延迟:%d ms\n" "\n" #: ../src/term_config.c:1158 #, c-format msgid "" "Configuration file (%s) with\n" "[default] configuration has been created.\n" msgstr "" "å·²åˆ›å»ºåŒ…å« [default] çš„\n" "é…置文件 (%s) 。\n" #: ../src/term_config.c:1414 #, c-format msgid "Cannot find section %s\n" msgstr "找ä¸åˆ° %s é…置部分\n" #: ../src/term_config.c:1454 msgid "Main Window" msgstr "主窗å£" #~ msgid "Terminal Font" #~ msgstr "终端字体" #~ msgid "Scrollback Lines" #~ msgstr "回滚行数" #~ msgid "Background color" #~ msgstr "背景颜色" #~ msgid "Text color" #~ msgstr "文本颜色" #~ msgid "Block cursor" #~ msgstr "æ–¹å—光标" #~ msgid "Cannot read configuration file!\n" #~ msgstr "无法读å–é…置文件ï¼\n" gtkterm-1.1.1/screenshot.png000066400000000000000000002415751376216657300161100ustar00rootroot00000000000000‰PNG  IHDRîK¸Ì—sBIT|dˆtEXtSoftwaregnome-screenshotï¿> IDATxœìwxÕÀé„!ztP@ÞÁ‚Q°‚QŸ¢+ŠŠÊ Ï.¬ ¶'*(Ø@)Ò›H¯!4©!$”Íûãìdgûìf7EÎïûöÛÝ™;·Í;çž{î¹8ˆ :tÈÃ>xkÔ†Õcãâ"#ˆ@QEQEQ”ðRP`#//϶s玿'ügÒ»Ó§OŸlN…Ry¥5jtø}þ¯ÓëÖoP=;+“œS§ÈËË¥   Ä2¯(Š¢(Š¢(g ‘‘‘DFFO||yذk·Ã<¸8ÄרQ£ë_ý9» ??.ódFIçYQEQEQÎh"""ˆ/Ÿ‘§ÏiÝfàÁƒEgoܰþçÄJ•jäœ>UÒyTEQEQÅN\¹xNçäh˜Ò¨oÔСCï¹êŠANeg•t¾EQEQE1‘Ÿ—G¹øò²OeŽX¿níî ñõK:SŠ¢(Š¢(Š¢¸ÁÞývG¤îÚžcËÏ‹)é )Š¢(Š¢(Šâ™ˆÈ¨Üh ZÇ(Š¢(Š¢(Jé%2‚èH[~¾:jWEQEQ”RL­ "Rý´+Š¢(Š¢(JéÆf³ *¸+Š¢(Š¢(Ji'ZåvEQEQE)ýD–tEQEQEñO´*ÜåŸÁ²•«øeþïìÞ³—£ÇŽ‘”˜HË͸æŠË©U³<õ 7mñz}®yàžQŒÿë7lâÕç'P¯n-YÆó/¿FÕ*U˜<ái&L~ÅR\¥‚‚n¼ãn" øðí׉ˆp^«ÿý?óöûqç­·Ðï‚>!OïôéÓØl6âããÒ>uê”Ç㾸öæÛˆŠŽfÚ»o:ÿâëo™öù—ükäíœß«;9¹¹ü0÷gæ-\ÈK½:µ¹l@?:w8À©­DFF’X©"M7âÚÁW’RßyÛí;vñÉg_°uûv’“«Ò§{w.¿äb¿ù=uêÓ¿øËV¬"#3“F) ¹å†ë ãÏÏÏgÖ?²`ÉRÒÒöR©bE:w<¡ƒ¯¤\¹r…ñ,Y¾‚7ßû€¶çœÍè»F:¥‘‘‘ÁG3¾`Óæ­[¶nçÛïçp<=ûïɉ“'yçýY°x‰‡²Â¿ÿæ‘qÏrìøqš7kB—”óؾc{÷ï/ g%ÿE)ã”÷?â—ù¿Ó°~}ºv:Ukÿdúç_QPPÀ+/÷y­ÁÊÕkX¾jÚ로ÞÛ¥¿úQ%¼ ºî&Z4oÊ#£ï¡R%éÇOœ<ɤɯ²~Ã&f~úaPñF‡2“Š¢??üô+¿-ZLËæMyàžQT­’Txîxú‰BÁoè5WŸñÕLf|ù5.êËù½º{;'7—‰“_#ûÔ)F¿‘¦Ï :®ÒÈú›hݪÅ?2=W9Ê‚ÅKiP¿./=÷4QQQ€ÜgOà«.HµjUÉËËãÖ»Gs<ýûö¤Aýº€ÜûS§OóÐè{èÒñ<9Ê}=Æws~äÒýIªœè1iûö±|Õj¥4à…gŸ"""‚_~ÍŒ¯fòíì9Üyë-të܆õëÒ®Mk6lÚ£O=Ë¢%Ëø×È[ùmá",^BƒúuÙšæ–ÆôÏÿDZãÇ~ýu\6°áñ|›­ð·•ü[Æ|›‹—T¹2/>÷$QQQlÛ±“?ö$kÿ\oYpŒŒäݦÑ朳‰µ˜¬8ƒóW?Š¢„—zuë°qÓv"ã{ˆˆˆÆ=;‰»S©[»vÐñêâTE)ÃäÛl|òÙ—ÄÆÄpÿ]wR5)ÉI©V¹R%ÏJ6Wź' à÷?fWj*½{t¥ß Ž+##ƒ¦}Æš?ד“—G»Öç0â†ë µƒ†ÞÄ%ý/".6†__HÝ:µyò‘¹êz1MÉÍÍeÅšµÄÇ•c`ÿ‹hÙ¼ L›Áö»¨^-™Ûo¹‘VÍ›ù¯(/¬ß ‚ô9­ZBä÷í>fÍú ÄDGQ­Z5G¹ |—羇gWj*/<3ŽÆgÉçÍwßgî¯óyö‰GiÕ¼™Sz<ù,7‹9ÊÍ#ï¡zr2o¿ò"<åùø}eWêþóÔã4oÒXâïæþ2 ãózÌ>r€Ó99äää_N÷Øèçk]ºÑQÑ$W©JÆÉLjV¯¢9Z¹zÕ’«Òù¼öPÉUªÐ½Kgæüü+K—­ ÿ…xÌGÚÞ4kܘ" ô»_ÍdŪµP5’«Q#¹Za^Z6kJ¥J9q"ƒÓ§r¸¨wjW¯I\¹8ÆŽŸà”ï¬ìl,^Bµäª ì‘SDEDZÎ×.‚.cDÄÅÄ“›Cú‰ ªT®Œ-¿ °Ü~ß½öó_x³çþÄÿ¾™ÅµW]áÆK<¾êGQ”ðóäÃÿfì3ØšÆãÏL$""‚]©{¨žœÌ?ôó¨wE)Ã8xììlš7mBrÕ*!{Þ‚…ü4ï7Ô«ËÃo øú|›qžgÏÞ½ôêÞ•ÌÌ,~[´˜“Y™<>Æa³ûý?MJƒÔ¯[·ðøÜ_æQ·vmê֮ņM[˜úñ4"##iÙ¼)•+'²{O“^~w^~‘ØØØ Êø×ÆMTIª\h'üô¤ÉlݾfM‘X©+V¯µ\ž];³+5•ÕëÖ î«ÖýIÕ¤$Z6kê–^ßÞ=8|ä‡aÐÀ‹©ZUfJ¼ïÖ¹#»R÷°fÝúBÁ}Õºu$UN¤™ý¿?Ö«K¥ 8pàoî=†n;q~î4:«¡Çðs~ù…òåøûÐ!¶íÜÉ ×&.NêúÐ߇hP¯ž“~£‰ëïǽæ#±bÖ®ßPx,=ý11ÑKOÇf³é2pôØ1NœÈ Zµª$$” ý¹m g1Ìüû4¬_Ÿ/¾þ†ù ÿ óäIÚµmí7_OÅ„Kù/J###éÙ½+³çþÄÝÿ~„ÞÝ»²hé2š7iÌ þíã †\5ˆ¥+Vò¿ogÓ»G78YxãÇÅÅz­EQÂOÕ*Uxfì#"¼ï‘Y¯jÉUyzìCTON:Þè‚+J™%mï~@:ãYþpÚ fΞS¦qJ Ï?;ÎåJ‡JÕµ0þýn·­W·±q1náüŵrÍvìÚM¿¾}9ü&ÆŒ}ŠUkÖqêôéB0.6–Ÿ{šZ5«S†*II¼<é"##ùø³/ùß7³èAn»å ¸ïáÇIݓƞ½û8+¥…ÚrfÏÞýO?Aï]) €¿6mfëöí¤4¨Ï„'ÇÁg_ÍdÆW3-•§G—N|òÙ¬ýó/®t){Òörèð.x1D@êÞ}Néß«?Ïÿ]Â\r1•+ù<Þ­sG¦}þkþ\Ï«.'mï>:€ / "Ò!Tz»ŸP@\¹8{ð~¦~<Í[·1{îOÌžûÛ·å¶›o4 þ䪯¾í×·?Ì¡YÓÆ´jÞŒ£ÇP¾|¼Sš*ˆP}<=Ãk›itVCjT«ÆÞýû;~Õ«'³|ÅjòómØl6NfeR±B§k>ùì+\Ø×)Þíïð‘#ö{¶–]{Risv+ÖoÜÄo‹“—ŸË¿ÿu—¥ü¥ŒÃo¸Žõ6²{Oßÿø3½»w£|B¼ÏëŒò”‹‹eÄC™8ù5ÞùðÆŽ]x®ÀÃóë‹÷g]Q”ðMlŒC±CLŒ¯÷©Tã®(e˜J•D¸9|ôhá±ÆR8¿glùÌ_°8è¸o»é&¿þ ÿXÊyíÚÒ«[—€®ß“¶€¹?ÏcîÏóœÎefe î+T(ÚÍDGEj]›5j@T´˜vDDDЬq#R÷¤q2+Óé:›ÍV(lôíݳpá¬Á††ÙŠØ›§ÙóÛ¶õÙ…ÚÕŠ•*Z.OµjUiÚ¤1·låÔ©S¬\û'=ºtò˜^ ÔªYƒ”õÙ²m;YÙÙ¬Z»€.;˜Êîýe`”©iã³øÏScùkÃ&æ-\Ä¢?–±lårró÷ð¿®yûå©V­*§NŸæ‹™ßñ¿of1㋯ÿøÃT¬(usò¤sýgfexµýˆ‰‰á±1÷ñöû³mÇN2NždøÃøpú ²²OQ!!Á)ü‚ÅKøõ÷Ô¯W—y6M1SѮѯY½:“Æ?ABByާŸ`Ä]÷ñDz•äååYÊ¿•0¾ÚÛøI/qðïCÜ9âfN>Íì9?ñÍìعk7O=ö å¶Ú¹Ãy´kÓš•«×²|ÕjÌ;ž[CQ”âåØñtžxv"i{÷Ú´§íÛǸg'ñô؇|ö‘¾PwE)ÃÔ¯#îwìÜÉߦzµdºuêD·NÈÍÍuî8K±ÿ¯U£:ÃoÊï¾Ï”©ѼIcj6ßâ2„¯ zõ;c•+%z·÷ð»pá¤)È(÷c ÷¾øú[§ôZ·jé65ù§aoÞBìÛóòóˆ+çÑÖÛJyztéÄæ-[ùkÃfV®^K­5Ĭ¢À=='¼Ù*»ïÖ¹#;w§²þ¯M¬Zó'‰‰iÙ´)@RåÊì?x¬Ì,Ê—/_xMƉ ª%';ÅÕªEsZµhÎ%ý.bô#³aãf lîî'  \lW À7³~`ÓÖmØòm…‚á®ÔT§ëR÷ì zõdïí¨W§ãÇ>\øÿÐá#O?Aýºu íÞ6mÙÂkSÞ#>>žßs—h¯<µS]U©,æEQQ$”/²Þ£aƒzìØ¹›Œ“™–òo%Œ·öv"#ƒ5ëÖÓ¯o.:¿7õéÅèGŸ`Ý_8xðo’““ý·U{¹n»ézî}è1Þûp:uëÖ.<ç·½ûw@£(J?é¥B¡ýé±ðÄ3IÛ·ñ_ä¥çž*^Õ¸+J¦|ùò\Ы¿ü¶€—^ŸÂƒ÷Ž¢J’-¹yyEŽÿÂ>½X±j5ËV­aòëoóìøõ?mР^=6nÞÊÈá7]<ÝMTd$_OûÀo¸ 7Q³fuª%W NÍš,[µš+/¿„¨ÈH²³³ Ã[)O÷N˜úñt/_ÎÆÍ[¸ê²K¼¦2 q2ÓÉí£·ã];vä“ϾdÉŠ•lؼ™ó{õ(œ•8+¥!ûäëYß3ìš«åúÌLþX¾‚¸¸XÚó¿yë6š6nT(„æåK;IL¬äÓg|fV&ùùùÔ¨VÈÈHÙ' yS6lÚÂÂ?–Ò£kgNœ8Á‚EK—óÚ{¯|p²cÏ·Ùøø³/n ¶íØÉÓ“&Áãcî§^ß>Ë ª%W¥A½ºìÞ“ÆÚõÑæìVdeg“–¶òå˺2õ—ÿŠ+ú ã­½-]¾€£G‹‹‹#Ú~ocbb,·U€š5ªsÕå—ðé—_sÈn ÖÛ»¢(ÅËÎ]»IiPŸÇz °ÏyzìCŒŸø";w§¯úqW”2ÎÍîeÛŽlÞº•QëGQ”ðòõ´÷Mÿä9MJ¬ÄKÏ=åt,PtçTE)ã$$”ç…gŸä›ÙsX¹f-©i{‰‰¥i“FôêÞ•>=ºùÍ=cœ«”X‘»nÎs/¾Ì3¿£Í9­hÞ´‰¥¸ÆÜ{3¾úše+VóÅÌï¨W»­Ïiå5?Þ~‡Vl‡?7lĤÀ¸622’ÇÍ›S?dË–íäååqÿÝ#yõ­w Ó°Rž];³öÏ¿hØ >uëÔ¢ÀKzW_ybÝú >r„>½zPµJ’×ãÝ:u`ç®ÝT¬X‘-šÆW«fMžfö%Û·ïäСÃÔ«W‡Q·ÞB‡vçRT®œÈ•— dõºõìÞ“†ÍV@Ãúõèáùœß³»[=~ÿã/€ÌìÔ®Q!W ¢OOG{jÙ¢O>òo>ýòk6nÙJ­šÕ¹êòôï{Ï{’™}Š&Îbãæ­ìJŸÆƒ¯¸ŒÁƒ.%*Z,8w¥îådV ‰÷ØbÔ«W—rñqü4ï·Âcþ̓SôîÙ®;BD3gýÀʵR-¹ W]~‰}q«õü[Æ„„òŒû0Ÿ~ù5mÜÄÂÅKI®Z•«]Ê—°ÜfÍí;:&†;nº‘§&¾àvΕ£ÇŽû¬EQÊ&Û6ÿ¥²»¢(gÿ}c /eêë/“˜XÑÿ¥(½å«V3áÅW¸ wOîº-p7Š¢(JÙE§*ŠrÆÑ°~}êÖ®Mb¥ŠÅb-Êô–,ÛéNíÛ©¥£¢(ʆڸ+ŠrÆ1h`û¯âéÿB•^Nn.KV¬".6–Ög·(r|Š¢(JÙš{EQ¥ÄY¹fÙÙÙ´m}6±11%EQ¥˜‰Øºi½ªlEQEQ¥”£6(Š¢(ŠRPwEQEQE)¨»¢(Š¢(Š¢”TpWEQEQ”2€îœª(Š¢(Š¢(e€h TtWEQEQ”ÒŽšÊ(Š¢(Š¢(J zoêΒ΃¢(Š¢(Š¢(~ˆÈÊ<©¶2Š¢(Š¢(ŠRÊQSEQEQE)¨à®(Š¢(Š¢(eÜEQEQ¥  ‚»¢(Š¢(Š¢”TpWEQEQ”2€ (Š¢(ŠRPÁ]QEQEQÊ–÷÷?þ„νÎwû\{ÃÍ…anuSÞZøèÍ#øù×y!Ïp yìwÙ^¯ÉÉÉ¡s¯óIÛ»p/ÃéÓ§9“ò|þëþ1!3,[¹’{œAC®£Oÿ ½y|2-dñçÛl¼øÊ«ô»tC®¿‰»vñÑ´é,þcIÈÒO÷ݵm”Â}ŸBù Û'wÝWßõéç_Òï²+È·ÙÜÎ}3k×Ý4(½mÏÀWŸvÈۙùíw–ã*î÷†¢(JY#ÚjÀvmÛðüsÏ8ŒtÈýݺv¦QJÃe+8<å± "Âòõ®exñ•×(_Žûî¾+D9,¼ùö»|ûý÷Ü1b8wŒNdT$›·l!?ß]À–YßÏÊUk˜öÁ{DFFR©bE~[¸ˆììStíÒ9d郧û^Ú·+ÅqŸJÃ3Pë>\Ч¯¼ñ&ëþ\ϹmZ;›ÿû".<¿7ðÏ-¿¢(Š8–÷è¨h¼ž¿ùúa!ÉPQð—G”†2”4«Ö¬å«o¾eƇSINN.<žÒ AHÓIMM£e³f$W­Zxì½7_i¡¤´µâºO¥ÒV÷¡¢zµj´>§¿/\è$¸gfg³bÕ*î½ûNàŸ[~EQ%p, îþø×ýcèÖµ3C®¾ÊãùœœÞ|÷=~÷§sNÓ§W/þuçÄÇLJ* ~ÉÏÏçí÷Þgî/¿•™E×ΜΛËðòoòÝìïøâ3qÓ ¿éưçÑf³ñá´é|?g.ÇŽ§Óæœssß¿¨Y³Fa¦¼÷>?þü ÙÙÙôîÙ“UkV3yÒDêÖ©]äôßûàC†]{“0L>o¹ýNz÷êÁo ±s×.êԮ͘ûî¥Më³ùÏ /ñͬÙüðÓO¤4lÈ'SßqkCþÊÚï²+˜ðô“´kÛ€¿6läžûà×9ßæáš«¯äûæ²aãFž{æiÚµiÍo¿Ã‚Å‹9tè5ªWã–oàâ‹.ðzß]óV”ò‡‚â¸OÞêÂS½v:¯½ß´|±dÙ2¦¼û>;wï&¹jÎïÝ›Q·ß ¸÷-þÚ…¯2åææú¼ÿæ­¨ôí݇O¿ø’{ïUxlñâ%4¨_†õë{,¿¯¾ôÉgž#7/—gŸWXW—^u }zõdÌè{ÈÍÍå¢K1uÊÅ>Ð ô=pËíwrñEòÓ¼yìØ¾ƒ 2æ¾{hѼy±æ[Q¥´`yqj^~ÙÙÙNŸ¼¼<Ë ½ðßWØ»w¾ó¾3…ÔÔTÞ|÷½ 2Hsss Ï¿1åþX¶œçŸ{†ß™B9ƒ†{GÝÉ¥0äê+YôëOÅ"´Lyw*¿/XÄÄgžæƒ·ß"**’»x °®_ŸòK–-çù ÏðÁÛoÁž´½!Kë¶íœÝªe‘ó °tÙrºÿ>þ÷é4ÎnÕ’GÇ=Inn.ÿû~†^3˜ýú±èןødê;ÓEY_zùUúõëË”×_¥ÍÙ­ˆ‰‰¡n:Lzf<Ó?x÷gü„‰ìÞ³°~ß‹RþPP÷ÉW]¸Ö«Õ´<‘‘q’‡{‚K\Ìw_~ΤgÇÓ§gw¯á­´ oeòwÿ‹š·@éÓ»'dÛö…Çæ/XÀ}z{½ÆW_Ú§WO–-_Yh7ÿׯMääæ²h‰cíÈÚ?×SµjRH…vO}ovv66[¾å¼{ã»æpÏ#™ññ‡œÓªwß?†“'O†,(e Ë‚ûª5kéÓ Ógæw³-]{"#ƒY?Ìá¶á7S¹rejT¯Îm·ÜÂï q«y|ÿ£O8“×_Ïä‘1÷Ó¤Q#jÕªÉè{J—íúéÓ§™ñÅ—<2æ~ÎJI¡nÚŒû(éÇO°è%œ>}š¯ÂX†ŒŒ“œÈÈ )±r‘òiÐÿ¢ iÖ´ II•¹ièu9z”´½ÖïP•õöù¤7:‹råÊpÕ Ë9+%…:µksÓ°¡Ô®U“ 7Y޳8Êï‹ÒpŸ\ëÕjZž8tø¹yytíÒ‰Š+pVJŠWªÕvá«LÜÿ@ò ÉU«Ò¶õ9ü¶p! é%K–rAïÞÃûëK;wì@^~>›6m`ÅÊ• »öÒÓOn–.[Nïî=BVðÜ÷öé?í;vZλ7_9ˆÖg·¢Zµdî½kII‰üô˯!Í¿¢(JYÁ²©LÇöíyå¥çƒJ$5u6›}¼ðX^^Ù§NŸ7|åqßþýäÛl4kÒ¤ð˜õe«ÅCÚÞ}P@“Æ %ÄÇÓ²E v§¦R¿^ݰ–¡B…Ê•+ÇÞ½{iÜ謠óé‰ZµjOVV¶¥¼„ê~ÅÅź;~ü8?þü+kׯ'==£Gr:€¶Xå÷Ei¸O®õLZ 4 }Û¶ ½éºuíÂe— ¤C»vÃÓ.\ËÈý$oÁÒ·OfΚ͈›ndÅÊUÔ©[—úõêz ë¯/‹‹£K§,Y¾œV-[°|å*¼ÿ>6mÞ²+¨W·K–¯(4› ÞúÞFÜn9ïVˆŒŒ¤u«³IMK+Z†EQÊ(!³q÷E…Šøàí7ILL,Ž$ÝÈÍÉÁf³a³ÙˆŒ,îësrN“ŸoÃVP@”ÉNll ±±qäåå…µ 4lPŸ?–¯ WOï9ùô?–ó®²fee3âλ9¿WOn½ùFª×¨Áè1Gq”ߥé>5-€¨ÈH^ü«Ö¬eösxø±'hßî\&=;Þ-l°íÂ(S ÷?¼KŸ^=yáåW8pà ó,¤oŸ^^ÃZéK{÷èÉ—3¿fØk8tø0) Ò­s'þ±„>½zrôèQÎnÙ"dù·J¨Þ‘‘‘”‹+ªl)Š¢”)ŠE‚­]S4^¿/^\Éy¤N]Ñ`­Y÷g@×bÇ_TêÕ­KAAkMyÌÏÏgÓæ-4j”Bí:u€ÀË×]3˜ogÍfã&ï¦#þò ¬”5>¾wl¢ž IDAT»ví(ÞM[¶p<=»FÞNJÆ$ÄÇáÁe¨¯û^å÷GqÞ'+Ï@(Òj×¶ ?òï¼ñ*¿/\Ä¡C‡ÝÂõ°zÿƒÉ[°$%U¦}Û¶Ìû}¿/ZÄù^ÌdÀZ_Ú­[¶nÛÁÂÅpž}v kçN¬\½†EK–нk×Q^ûÈ<™éôæͤ4lœ)Š¢”ÂÖ{WN¬ÄÞýû)(( 66–aC®á)ï°|Õ*òm6<ȦÍ[Bš¦·R Óöû÷câ‹/±aãFŽ;^hÿîÕ«±lÅJŽ=ZO(ÈÍË%ýÄ §O^^*T`@¿‹˜ôâd6mÞÂÑcÇxñ•W©^½Úµ ª Ò¯ïœß»#﹦Ê–­[Ù·?¿Îÿ»Rù VÊÚæì³ùföl<ȃ =Õø¢jÕ*dffò¿™ßrüøqæþü Û¶nw ãï¾GùýQ\÷Éê3`%-sŸ`æDFßýð‡æÔ©S¬Z³Žøøx*%VrK§¨Ï€•ûoÎg y+ œß›§M£f>½CYéKâã9·mÞžú>]:u 99™ºujóÑ'ÓéÕ£[Hón+y÷ÔFÞýàC,ZÄñãÇy÷ƒÉÊ΢O¯ÐÚè+Š¢”Âf*3lÈ5<ÿßWرc'O=þÃoºrñåxqò+F~~>;tà¿“&†3—!**š~}/ 22tÖîÏŒ{œÙsæòÃÜ™öégäåçS¿^=˜\æùËg(ðWÖ{FäÙ‰/pÝMé–\•K.îOT”ï&Ý ^=îy;o¿ÿ>o¾ó.;´§cÇóœÂX¹ïÅQ~Ç} äð—–kŸ`‘‘Á¼ßðÆ”wÈÊÌ¢^½zLxzq±îë hÏ€•ûoÎçí#n (oÁÒ§gžŸü2îâ7¬•¾´O¯L|a2ç×¾ðX÷.]øôóÏ9¯Ý¹!Í{ øË»§6Ò±C{^{óm9ÂÙ­Zñæ'SbePE)I"²2O†ÆðV)Ž=Ê%Wfþ?„\˜(mœIeU¬£íâŸË-·ßÉ—_Êe”tVEQJ¥s•¦b™-[·R§N­3B`9“ʪXGÛ…¢(Šr¦P,^e”б+5•ÔÔ=´?·-‡åõ)ïrýµ×–t¶Â™TVÅ:Ú.EQ”3ÜË'3NòþÇÓxbü³T¯–Ì•—_ΠK/)él……3©¬Šu´](Š¢(g*jã®(Š¢(Š¢(eµqWEQEQ”2€ (Š¢(ŠRˆ>pà@IçAQEQEQ?Djã®(Š¢(Š¢(¥5•QEQEQ”2€ (Š¢(ŠRPÁ]QEQEQÊŽ ˜®îõêb »ˆ)*ã|„‰¦M€±ÀBÓ¹¶Àå@K 2°øø Ès‰'˜< ¬-b¾o†ý‹O°ôDÊó]1¥7¸Ó˹·éaJ×j=¿ ´1ýïm!î— ¤M•>jØç€ÅÀÇÀIS¸¯$¤-/1ÿ øð¦éXyà& P8Ì>¥èÏoqÌý-Í÷ó«(Š¢ü£qîKqÕã€5À7öÿ§‹˜JCD »ÕO¸A8„W†!‚ÿ7ÀQäå~'üÇ%l:0Ó~~dP9.=ôPü/þÉÀq—c;Š9žx ˆ7Z¼f?¶Ï&àC iσÖÀ(Ü—Œ_гàîJ,ð_ 2(ØÔBäË?C˜ïpÌý-Í”Ôó«(Š¢ü#qîûìƒýÀo!Je°Øé#Lp3ðp·‡óÿöšþÏâ€~ˆ–þ˜Køï€ë€sÕÁdú g)¢.mµŸà×]iáð‡ý÷ïˆÐØh ·è$‡½Äu-Й53Ï2}‡<'e…`(Š¢œ!DûRDÊ}€·ü„,¶y9¿×ñ-ÀùÈT´«à¾Ø \Bh÷^À@5D¨šŒû@¤=2«Ð8…¿oxÈ›•p?!‚œÁ|ÓïKp6§™èŽÌ6üAø Ü‚˜ŸŒj»I8ßÃÚˆùF *¢ù^Š ¶ŽâŽ•z¶Ê|Óï…x6•±ZAâÍH9Ö#Âö}Èl§ö(!‚{U—ãë üd`ë‰ÈàØÕ4,Ëþ †àvd yŽ^AõÜßà}¤®Ï.â‘ú…»É›7Ê!fB3ó-3ÿAÚ΋q¹æÏ_y­¶—@ž_«õb¥ß\ ¼gÏk%¤]½„ !|õ×Ú”¿H䙸øÅ%œ•rõ|¡éØ9À«Hl0·ZȬî¥@=ä¬FÞM»Äç¯(Š¢”á_œÚyQ¬ó¦ Ðx7À¸›"‚‚7¡i-Ðé°‹B,bv3xy>ó‹¹)òòΞ@l;]Ò·îzD‹º1Q¹ÖôñdöQ ±ƒ¾%èR:“€ Ì×Ö…¼`Ÿ†6à1—05|äÞþÄϳÜJ=‚Q_ý„³R޶À#ö¸Æ"¦'·™/oûnçfñÜ–+#õ¼Áù`©¼Žhù'ã‘Y±ç‘ú2äþ܆ èÇ÷+ÌÛ)àgd en“U€ŽÀìãëåkí%Ðç|׋Õ~{ý€ÑÈÚ‘|{8£ᨿD䞟°ço,ð+Ò>ÌRŽ@ñ×®FÿBÌ@Ç"Âx>Ò^ iŠ¢(%@ø5î­Ç./ç£Ì'ˆÆ¥AñöF†\/a¶×uqh›‚!Ñô,²ÿ߇h´ú" dA쓳¸±& ±Ù=±3$ÜAûw6RÅm¶òž‡c÷àl+‰¼ä øçÈËØlÒ±Êþ1s yiž…³Ý¼•z£Îrü„³RŽë€4äE^,C´vç‘/ƒ(D3˜Ç FìÓ=µÕ9ˆ`ÒÑPš©bÿ6k,£q xòðþŒxc„ýºp˜­lF4¨}¹öcÜ_ƒÃˆPd°%À¼˜]tÂ1Ãt‘=Ï?ŸÕò‚µöÌóë«^¬ö ð«8ÚÑd`²PvžýX¨ë/š?Fê `¥‡p”#P|Õ_Mà*ÄiÁÓñy8 ä´EQ” ü‚{UÄ£‡ÍËùÁˆ¦õËㇼ>õ.ݾ(‚;8 'Ûíq76kŽÌ*˜ò.7[`¸@ÙIh=p<»©ƒ«Vàrìˆý» &™š€,–,o Ÿä!]õ¬”£)bî`^4º’¢ îq|†³—3'ÓœKqÜ Ìy» Y˜ "ôjçß@™mÍ#ƒ—&8˜@ï/„fíÌVD0€Cðìo;#ˆø¬–¬µ—`ðU/ôÈÂgƒ½H¹šàÜC]{ò(ÄÓ×&œÍO‚)G øª¿s‘×Îå›~ÒEQJ€ð î±x×x&!ö±“í9‰Æ±.ÖþÛÕ£M2ÕšŽï®Þ7Ì×uq^.îîô2pL*ྠ. ÑÞT"\I³ÿZÂ<œí’Á™¹U]˜ïLEÝLd:úܧž­Ôs8ðWŽÄÅU  FÀ1³Ñþ•C´ŸC;ioÏï€q·74퉦c_ ¦ O‘¯H¤-^ˆûÀ$H5ýäþxè‚abú`˜ 5Dú’@ ¤¼`­Ýƒ¯z ¤ßÈÁ}½@&Ž™ƒPÕÈàe bBôóIˆ½A8û?_õWÉþíi]A í@Q¥¿à~ïru¤ƒÔù'éæ!¦c±Àsˆ s7þÝU´§û åŸ$Ÿf¡²Î/“8^å‘>D¸ "ZªOLÇj{ k¥žK‚Ä5fE—ã®ÿ%‡éÑJàdaîoxì®Ȧ¸?†<+ÍMÇ /QšÈ€¢™ˆvösçÍÏ] ÷×(øYq‘=Í4‚Û·!ò†_õH¿‡»ÒÃÓþPÕŸÁZû'YHz?ð8b×o`µù¸SÎOú¾êÏ<ûêí}PZÚ¢(ŠÂ/¸§"ZòJ¸kZR»i3M-Ð;8/.ŠžDüTßûKÈuÎ8-ÐL{ =Ž ¡!åÙj:¿ qÙg~av2 4œA&"Ìú£"bÃz‡xi î/Ê®>Âû«g#NOí*lFlpÍ´aü6ÄÃÇDdê×^ÂÍÂacfâ÷¼㢰1J÷@èýµŠ•û›…Ì* Dfef!=«å «Ï¯?í7:"^º@6­+»—¤PÖŸ"ÀÏEïFâ¨S«å8Š äÍ÷¿Iò´Æž‡~¸›£E㘡´XíwCNQ”3‡à^玱âšäìËÌÐà4Gô™ÉÆ}ccz}7ÎÈ}ˆ@0Nš™Î­Ã³ ß±E-ª&Û† 0 ÑiY³›³¯7dì¿“¯#[q^¤e5œÁvdÇØÈ”³ ±'u5JF¦ª·š¿î0í'ð…„Ëp,ê:€”½·—°VêÙàOäe;øÞ~ífšºJ8ì­cÓðp‘Iàf.3½CìÒ[á.È•¥H®CÌb<¹Gœƒ¸Òsõ´ó)âôy{^Ó…ÞI§uŸŠ8/"ƒ…t¤þ:#šÚùöpÜß@ðw ¾Cž E³?¶ZÞ@±úüú#~#Q~”GfnnEî'ðPÕ_7d‡íÈìO d1è œßV˱Ú^Ž‘Ùœ³s²`9`Oï¤/XbÿîØ½››Ú¬ö»¡§(Ê‹Cpï„lÞbÐÎþéƒÝ2}'"LѶð–—ßÞcK ípÐY\< Ø[Ây‚øYöÄÛˆöppRþþ~½ ´1ýïm!îÒÚ^Z£—§€ß·QôVâ †®È&>u‘͵ï(i|å/˜ö †· Þ‘Š“`Ò-®çã[¤M¾àåü\dê×\އ"~dÕÙ1ÄçýTÜw¼ 7¥©¿WÅ ‡à¾‡P=ÙpæûÿÓ†ˆÀs«Ÿpƒ7ež†þß Ûa·A¸dc3éÀLûù‘Aå¸hì§èˆâ›É¸»úÜQqá)d§ÖÈ®V(í¥6²{ädÓ­*ˆÀU Xí7¬Æ(QÈn¶ËíñæQº„ ù ¦½œi×ó±¨îå\"‡ç¶ªü@ædµ«‘³†#R)Š¢`Ü÷Ù?ûñ¼Ev0 AvÁÜé#L²ëãGÀÝÎÿçNsÒ‘öC´ôÇ\‡ør?Ù¯8qH(¡g)²»fiã¨ýûD×”Æö2Ù õe²!ÏfsDÖû «ñJ5 ø Ù!´´á/Á´—3âz>ÒÙ^OT7…q%TùËþ0ýßìLÜÙ EQ…âðã^èƒL‰ûb²sŸ·iAOšŽ-ÈÖ îû€ÍȦOEÜ»!Sݵíù›‰ ÷!Fƒù¦ß ñ>uÚ™}h„˜ ,E¶ãv-ƒ?êÓs¡ ÝÀÿÓ…,d7DóvÞVÓ\ë‘écO¤ õÒÑ,®^A„7W*Ý‘Ù?<œ5Æ”üXdÖ¥6R?“pncµ›œªˆæl)2<Š;½­ä«Í¿¯©/æ›~{k/VË2ˆ½)‡qßî#¸)ïóaÚ\ A» Ú¡Žo(Òö ž5ýv5•±ÚîS€÷íן \Ä#õ= w“¼PåÏ ´ÓÖ8ʉÜûO_<ÄÛi# ðÞ®¬Ìš^ŠìypéÞþ"Ýù¦ßÞžc§Ø÷:¯„ ^Bfw! éëAf~?V!›T‚»9N+ù äùu%ÇþçrÜJ{$]«ý½¢(¥‚ð/Nmì:¹ÎG˜6ˆè»ÆÝyyJÖ"BAD€ñšið:lc<2kò<"Ä»b˜DÜDù<‘€ Ì×Ö…¼ÀžF¦›mˆÙ‚™š@>ÒöþâgáY‹‹˜_MµÇY )oLe°Ò^ÀZ9Ú"ƒÉH;ýgÁ1"‘A¡ësu©«z%ˆ9ε8ìë'á¨Ïå¦pÁòo6å³™[íù f­Â{Úìÿ÷!šïœ@¡~~xŒÝS‘{\Yhlêölµ¿W¥ÔàÜ;á¼uy;ûÜ·.„ˆðÜwÁ=ZÚ¿‡{8÷ ‡¸£7YÓŠ&È¢ 'ÎñiD‹ó îæ=w e33ìßÓ·í¿7!BГ8Ü}½Nx_¬VÓ]…ØÃÞÜ…LOǽÞw!®G í¦"Ä®"8/2Úñو{Æ@xi+/#¦0k"Ïz›ƒÔ×Hdê|oC®@^®#ç'¸‡ÖÔj{±ÊĵÞ͈@÷'â“ü^‚"ö!nG"ƒäžs gµß؋̔݉´ÃSˆ©ÕAä-Jêy íÅj;MCÊu+²îá82PÔÕn0¼´c­áÇ}»¯‹¼ÈóqÊžöˆ©ŽáÇ=¿û†pnœnDß1 õó 2˜`ÿ} ywNÀy¡¨Û³Õþ^Q”RCáõé \†t4WãÝuc¨é‰ø¾†Ð/¶i†¸Ôí*Ðü)ÿ||õ Èf<'‘ÁSM¤*Lv …lµÜþ¿7âÆ6 EQE)8÷}öÁ~‚Û2ÚC]&wú“„ìúøp·‡óÿÅY[9ˆú!Ú¶c.á¿C|¹Ÿ‹ìÞ§XãZä^=†cÙòÄ·'V!»>‚h½g [¬‚{¨ÛU ùSþÙøë7ÉÈŒŸÑÿ$"}Ò‡ˆÀ`¢}_Žö6Ý# ùVEQ” ¿÷òÈ”{Ù IDATó[~ÂB^’Û¼œ÷db°8y» îû€ÍȦO¡Ü{!Û\WC¶ÀžŒû@¤=¢Ík„L¯/E¶âvÍ›•p?![›Ì7ý¾Ñ š©tGfþ°\*wª ®&]} Y1iÉv!ZÍpa5ÆŽŠï!;ˆV±ú—°)Àí@kD»ºÑæï2Üàz¤­¬~·Z¸3€PµSýFGä~›ŸÕß‘6ÑøÙt|>²üKˆyÓ.ƒÒ@i‰<Óž¸¶ñ*Š¢(g4á_œÚÑ^­ó¦ б; „¦ÈT¶7»áµ@ÄéeQˆEÌn¦"f•€çq¬›"f#™ÀÀ›ö´'º¤o5ÜõÈ ~!°ÃþÛødzÈc5Ħÿ– K)lº!;oÆxm$b²p¢ˆyðE ù+ÌÈŒFÖ*ä#õl6}¨¼Žhe'ã-îóA†k<ˆ EywVÄ4¡j§`­ß¨‹c VyÆŒÿõ\Âî@Ún[ÄLÆÛÌP421> ÂlCÖa˜?ë€#„÷ùPEQþÑ„_ãÞ Y<ºËËù(D°úÑ8[Ý]µòr5/2se p Î/ï`ˆ^E¦ÒA´ùï!»Tþ`?6ÈBL8 Ûí,dÑÛy8ìf­†;hÿÎF꯸4touìùƒ˜¥Ìfã¾DŠG CÛY¥$È}3îýd`b'?Ï~l„ýºpT›O‘û;7Àp×iˆ­r?ë#Zf%tXí7*"ݪö°+³qΕùÈzœNˆ ÞÅÂô´|‘ƒ,Ö6¸é³F#Ï»¢(Š¢Aø÷ªˆ …ÍËùÁˆFûËã¬D'o¤›ÂEp±å6Øn»±éXsD£f^p¹Ütny€áe'2)*€Û­cgd01`îÆ]8þÀô;ø ÂE ù+6™þïE„î&8÷öȀ̬=ŒßMpäVÃ5F4µfSže¨ànªvh¿‘ðæûçië¹ùˆ2`Îk3̬Fìã "óo´@Lz¦à{æQQEQü~Á=Ñ>y" ¸ Ñ„FÛ?q¦ëâp÷<’€˜š¤#»¯}_k5ùp%wê $ÿpŸÏBÉ A„+IlÈ@Ŭ D´Ûß»„‡LÿŸDl½‹ê(”ùËÁ} ‘‰ØÉƒ\³›ó]ÂEãИZ ¬·8îÆõ¿R4é7N"}Æqàjû±Ó9W¶#®WøHÿâÉÀ—×™Dd6mð¹pŠ¢(Šbð î'ð.VGÌ,õpî Ä\dˆéX,b‚PÑ®ú›r6¦ÂÓ}†òO ’O³ð^ g'íÇÌ”GjødáJ³?Øõ=œÛLÉ/´ó–¿8Üæ…Ì6DŸ‡g¡*+Àpˆ€èjó\Zdÿé7öànË^ÏtÎÏ5ƒv"¿ò§eƒ¢(Š¢‘ð  S wMs*p˱&À¿€wpÖzEO"öÍwãî©Åu¡+-ÐL{ =Ž]!åÙj:¿ ñDa;™ÎÎ k®+"v·ÇqØâCmÜMê ƒ¦Ò°¨.ÐüuD¼Ž€xú(³’•È‚á4¼›sn+bòd¦…ðg¡h§ôË€»½$vÙõÄ1kNnÎA¶{ZP®(Š¢(âÜk#/?ƒZˆ DÁÇ—°â cçÒæÈKÔL6ð§Ë1cÚy7¢Í5¸ñ 1hfÿ¬Ã³ ßñQTM¶ ÷ÿ‘)uƒ¯€ M^¾B¦óoG¹•A„3ØŽì;ñTbC4…®&B†¯ê-Mp1/Y€ØpWGü²gâì:Ï*¡nWä/æÊ#f3·"³fo!SÏ>/"‹jÓw–íñÍ0Ü {˜AˆK϶ˆ‰"„¢Òo|hߟÞGîÙ`dŸóŒY¨ix22ÖघÎíÁóBoEQEñƒCpï„óÖôíì~kzÅh;¡ÛUp„–öïáÎ=è!îhÄÍâ´"¤iƒ¸‰¸³Û€Øv›_¾›Ð#!á4°Ä~-ˆp? ƒ”[Ï-xöã*>CüÅaV²YŒ÷wñ…º]’¿Sˆš;ʆwó}Û…hDGØóYÎÏ*D¸ 4Ü*Ä,âFDÓ»ÙÑÕS»UÂO&p?2ðio_#šùpÒY1Ìþ1£~ÜEQ” ‰À÷òÎÐp"ð\wס¦'b_z º8ðLÄØ€i`IgDQEQ%4„&éêLDS\\\| 튢(Š¢(Ê?‚âÜó›îâÒ¶'KEQEQEùP<¦2Š¢(Š¢(Š¢‰âѸ+Š¢(Š¢(ŠR$TpWEQEQ”2€ (Š¢(ŠRpøq¿gÛfŠâÇÝ` ²õû8a")Ȇ=cqìT ²‘Íåˆ?÷ÊÀ~ÄÇùW¸of’ˆl„ó0Ž  ‚åÄsÿ"Æ,=‘ò|WŒi¶Gü7²ÿ߃lxd^ì;ñknpÙÑr:°Øt<”íªð”=­+ –ú í꡹O]ÅÔÀ½!ˆO -€QÈŽ¶§€ß·pÞ¥4ög%>EQE)A‚ûRBõ8` ðýÿé"¦Ò¨nõnPÃ˹aˆàÿ ²ãaDpLþã6˜i??2¨—z (>Á½'ð4"|¿‚ ¦š#þÐ=y附l‚”„Ü¿çì×ÿj?Žv…lâ´Üþ¿7"\Ey»@ùÇQÙ¡vðEQE)AÂoã^1eøÅO¸QˆðµÍËyO& [‡–‰Îí6ºMŸz!çŸMtЇ0í7oá7)Èp?ó ‘©ûù¦OqV@f5ºX,7ª «“P+&-À. fóàùˆ‰”wž··z?ื“ñžÿÄ„f62˜™Ô ®g,¡j§ç!ÂôQÓ1ô®C)ˆOQEQÂ@ø÷ÖˆVt0m€®À»ÆÝ1‘ðf‡¼yéF¯+±ˆÙÍTÄ ¤2ã’—Iöü<Œ€‰.é[ w=¢ý^ì°ÿ6>žln)ý[‚.¥°è† â¼61u:QÄ<øc‡=¶ˆ™Œ' ªÕzn<ü< lîð_}àu ÙÇxdðEQE áÜ«"&6/ç#í/Œs°œ¼‘n _ÁÄ–Û`»=îÆ¦cÍ‘Yó‚·å¦sË (;‘LQ9܆h³;#BîhD0¾wáýÓï\à3dnæ#ƒ¶m8Û0X­çƈÆÞl´ wÁ½=2p3Ï&F„þ&¨àn•PµSð¼çsÞûš`âóu\QEQŠ™ð î±@Ž—sIÀMˆ]q´ýgº.wÏ# ˆ D:"¼ûz©×jòáJ.îÚ¸ œí¥+àn"’…ºþÏÞ¹ÇÛ1ÿÿ}ÎÉM‰$.‘ ’·V‚ u§¾´âT‰¢¾´T©KPŠmSTU‘öÛ¢´TUU‰K´U%.E]’¸DA‹H$AÄ9¿?>3¿Y{öì½×ì=³÷>ç<ï×k^{ï™g¯µfÍš™g­õ¬ç©B®‘´£ŽJØYÙ¾ïü9&{ð°ÙÆ×êÈ——Ѻ‰ÇK÷©çp}Ä{1¹øïÖà?»Ÿ‹ëÜ`õãÔFûÆö· Ñó¥¦×si†a4 ù+îK(­®‰^´g%;™‹ììë…Lú Ñßåò^5ø\\Vª2=Q9]å}… Ù–û\ú¢^Z…\3qò…½^±YÔÏŒ'Î…eŽùÔsRÒûÅäâíµ)o¿MÈ«R;4²¥Ù£‹í_™Þ-¨"½…ÈD,)½Zgë Ã0 ##òWÜç!ÅhÅ# ó€“bû6¾\Káhjðôr=‘b÷I G/å´/ò$Æy™…ÎgŽsüEä)Ã%çK+²ŒÒ®]VE>Øß#²Å¯†a›ž G¦¼f‰o=ÏA¦3.›$¤÷Zðº€êM1ŒìÚéh&hѳ`¼s,-'¤šKUk¾f†a)îÃÒ²6rrÓX­²F.ÝÙ»|<Ûzèx 憜Œ^ÌÓ€‚-ä’ùM’ZG²ÛQ£Z¬v4ð ]\Þ|¹¼ )Ç"Åð‰*äB^Fc÷AžOÚÑ`ÜDhudÎ2›Ú¢3‘9Éß ÷šÈ/û2à¾*ÒË«]U·žoFwöGî ·@&1q¦!Ï4?D‹o#·‘Û¢z™‘Ã9tE²j§¿E‹“/Fë*£Ä!Ï@!¾íïwAzß ¾‡˜Ã|¸†aMC¤¸£04øVÁéCÓ»¼Š”çñ+îiØ4ø<:áØé i÷@îÿn¬!ÏÈàñÈÝóȶÛ]¨ù"ðm¤<|òþ3ø_{r!w£NÊ1ÈsK òMŸ—YÍ-ȯù$dÿ½ø7𨳒–¼ÚU%|ëùI´fâËÀÿ¢ŽÒM·³¹È%èdt>}P}<‰”P£¾,¾…îɳ‘9Û\¢(©!¾íïuä1èk¨Ý|ˆL£~š}Ñ Ã0 £ZZ¨‡Ï„ýÂs ¥]7fÍ` r_lhF×b_¤xO~ÝಆaFNä€ ä‰dÙE1õáP4åmJ»at}þ„"‡>Ù Ã0 £ RŸw€Ï àJõÎ38)îæÊÍ0 Ã0 ÃèÔOq7 Ã0 Ã0 £jlRÙ0 Ã0 Ã0:¦¸†a†aF'ÀwÃ0 Ã0 ÃèD~Ü Ðß±Kþ¶OC¡äã~–]ZkPÀ”)D‘JAî÷F @Ho÷"¿ã+bé DuÎ U-G‡¡à,`:Ÿ;ë˜çXä×|Tð{> Vs“#s0òy²E½ ø‡³?ëv5øE‰cGíàr`Œslç”ùTË$¸')ˆSµø\—Ë÷‰ê¢+² L¶)ŠoðŠypQ|…€óQÛ<ø$Ø¿ z}Ht_EÚ­úY„bL^Êñ< Ã0 #‘âþ(‘R}ð/àŽà÷GÔÆúèyL¹ýµJ ¼ƒ‚è,6¾|Æ;‹? Åòøj ÜD숼ñÔKqŸ\€”ï+Pgjc¹5IQ¼)9ƒÐõ»8øÿÁñ¼ÚÕ(L½ËÛÎ÷ó^(˜Ô—kȧѤ½ %¶«{S: ܼ‹:i_C»ïÇdÛPÐ¥™ÁïQý´Åä– ¾µç¡`\oc†a 'RÜ[ÈÀCår0Š6új™AHÿpbÂñ_&ìk¾„F¤ǎ݉|¹o <•ª´Ý›Cе:›ÈßÐ_ì$žÞ ¾ÿ Ít|‰HqÏ«]ͩλÁç’ òj$i¯+®]‘£h§!z{ Y»Eα‡ÑèûLñvj«;ÆÒ\<âü~¸ØÅ¢0 Ã0ŒÓ£²HôESÓ?« wz™¦™–ƒ+ÅGÎ@Êâ,ô) Å}'à8` à`*Å‘±hVaš†…L_T…ÜtÆ=d†ó}_`i,ÍþÀ¨óÕ3xŽb'¡>&-óCkÈ¿Þ ŽD#¶CÐHì£Hù{7&»9ÑukEŠão€ûÒÝ8Í–¼†f&ª1¹Hs=f8ß]³¡x¹~Z"¯Cˆ:a ÑëcÑy·¡ûè Ôùª–¬Úéë ûfŸCy÷^š|žo‡Úè›T&4Áë]m! Ã0 #[òWÜ7G£\Ï”‘ŒGŠN9zÛ¦ÀÑË?®`…ÿ™ç†aF¿â¾Z,6·Äñ6àà4JVIq¿)»÷!¥¢³ƒ€uЂ¾ji®DSî Ñüë]Ñ‚8€‰Hq<›H¹ZŽl­?Kd_ë+÷Vðùª?ŸÂ,ø)RâÎF ŠŸî"ZôçÒ);«!»ãÕ©OtÜÿ 6—ãÐ,Kž 6—Ehdy$Rú@£Ï}_;y™P” ˆF´oõLï,äUfäÁãÀJȆvïC¨Mq‡Båîå í œ}£YwDt¦slfJ¹´¼J6žSÞ¾ŠF'·E‰S¢s"ÅÊâ/ï#/?7dPŽJüލ#RÍ5n¾€±®MáHì çû|¤ôž€FÒ_þS"ÍàYçw8<˜ôŠ{Ú둆MÐù\CñŒØXT¿î(üÛÀäõ©ZÅ=«vê2Í2<:IÌ@JýK®¹py8‡hqêÐÂàoPzàÁ0 Ã0êHþŠ{/JBÓîSƒ’ô ²'í|›¼|>Ž¼ÌœŽFÉžKH?üo­6ªSlSü>…Š]ŠMD–#Ūr¤Â‘è}Ðhïî/Ò;]‡¥hd²VD¾ÌGjjåpdÂ2 )~˙ȅ®xÕÁ$àL4ËÚ®ÇÛÞJ G}C³’jï¶4××h–çaà·±c­¨-î†lÆ]zP8bßhú¡k°µÅR&q/£µqOD.+)ìpýÍðEyó#Ã0 èù+îK(­®‰ ³Ž‹ÌE.“v¨Ä"Yq_5øŒ{œIKOTNWy@¡mýÒ`ŸK_TÃK«k&îB£Žë%›EýÌxò`74zìÎ +!ût°µŸ¾‰Fh)!Ÿ宇-háêGHéÓŽ:0R¬ÔC¡IM#é…ÜöA³•ÊuaÊô?F”Q• Ã0 £>䯸ÏC£b(ižœÛ·!ðuàZ GÇzRl»:6ø|§DÞѲ ]‘Kj:Ÿ9Îñ‘Ç w–`œs,­\È2Ê»þ Yùü~b’4 £Ø”`8R’:£kŰӖÔþ@J_¼c7¾BšíH¿ùøn%ý¢X_ò¸_A¯QÚßûh±ç²=·¬ÚiðT'Rì¹) z úÏ#mÃ0 è‚Hq†”浑 D›Æj_ÞaäÒÇbÇ> pj"ó„×(\hø+ä‰åeäBq#d—ü rß—Ä&ÁñZG²ÛQ£_÷ÑȾÙuxðyÀå6dFs,RB.äe!r4«ÐŽÌDâ&«#ó‰ÙÔ¦‰Lþ†lš×D~Ù—¡ÅÀiÉ«]ùò,:Ÿã‘YI;jW¡ùÊcD‹-ßD×fç„t¶GvåC3Ak¡zyœ|ÏÁ÷z ²Ïï…:$¡Ç›eÈ´ äåé"[ðNó‰læ§!æ?D‹émä;£ÊóɪžŒ:XÓг`#çØ3T§l÷"Šž:µ…µÐ‚dÃ0 Ãh"Å}…¡é· 6¨.4}È«HyO±âž†{ÑKuG¤”¼…´ÞHò½ÀÖÁñZY\ãÜÙ=l^Ý|_D¾¢'£‘ÀÐÜU*v¾r!w#¥ää¹¥…d?îYq êM"ò‡ýoàÿ(½³yµ+_ÞD¤ÉA~-¨#޲_ÚÊåhVçiä©è¢X:áÈsxÂãëò-¾÷õ8uî\n>o~|_Íl.®÷¹hD~2º~}‚üžDJw£Ù4ø<:áØéT÷¬€Ú ¨ƒþjð»Ù<è†aÝ–Z=œû±R$ÙU[L@v¼j2 Ã0 Ã0ŒNJk]rù3š®ß·.¹‰C‘Ë@SÚ Ã0 Ã0Œ.@}÷•hʹ^£í‘ÝûMuÊÏ0 Ã0 Ã0r¦>¦2†a†a†aÔD}FÜ Ã0 Ã0 è SÜ Ã0 Ã0 £`Š»a†a†at"?îPèoÛ% Û§ý‘ÿóR´× €=Sˆ"•‚Ü;îÆôC~ÜïE~®WÄÒˆ|XŸAªZŽ@þ®÷¬1j™€ÎçÎ:åw0òß²E¸½ øGòOs¾—£ÀBSê˜^=9ƒÊíîT’w•·=_Œq~ïœ"Ã0 Ã0r!RÜ%RªÏþÜüþ¨Æ\ÖGŠÂ1äöG‘ “ ¼ƒ‚-6@¡Û7 ¸3°øR@¯¦ÀMÄŽÀ§¨Ÿâr) ö3]—‹ €rÎ7Íù¾ÜŒÖ3½zr;ðˆóû|évgß+9å}>Š$º7ðåœò0 Ã0 #‘â¾0ØBÞÊ(—ƒQ´ÑWËÈ BŠø¯€Žÿ2a_ ÿ>(fÈÈ—û–ÀS©Jk€"d†Q4ÿ†f0¾DþŠ{¾ßäéÕʬ` ™‚®IV÷e9Þ >—Ô!/Ã0 Ã0¼èQY¤Fú»?« wR_J‘v\©-áØB¤ôìK6ŠûN(¬üÀ ÀTŠ;"cѬÂ(2ýQà§hä:­Üt §ó{†ó}_`i,ÍþÀ¨óÙò>0êì‰Ì)† ‘êG‘©Ó»±ÿ~Ï-Ï«¯¡ë¾’tçëû;ɦ-Y§~×mpTÆñ¨ž^C3iÚvZÒ\ðkϾŒŽ6G÷âSÀ¨ó'Ïvj†a]œü÷Í>À3edÆãÑYC9zÛ¦ÀÑË?I1Ù·ïIíÞê{!³›ëÙÐdà24¢•”³§€sÑ ÂqÀ%ÁgGJ¹ÃƒrŸˆ”²³œò$™s¬l¢g“½BÔŠL˜ÜÑסÀ'¨Nþ ¬”ùûH‰Kâ«hæe Z—°³s,Íù|–[/‘uz¾× ¤¼NB¦E+‰ËÙH¡Ï‹4×ç=û²pð:ª‹Oýe¨#ñIL>Ïvj†a]œü÷ÍЈêÜÇÛ€S€ÐÈe%Åýf¤4܇”…RÌÖæû7‘VàJàáà÷Bàz`Wàî`ßD`9RÐÂ5Ë‘­ðg™)åÞ >?@õš­Ô‹>hT|5´˜quàOÎñ'ƒÍeiI²íõÛ^¯ÙÎ÷4ç‹/JvÉ:=ßëj/W`ÿ)û«£:ȃ4×ç=û2Õï©D»YÀo‚ôîI™ža†a%É_q‚L-ÚKŸˆFoõLï,äUf4ªù à%dC»÷!Ô¦¸C¡RôröξѬ‚»w¦slfJ¹´¼J¶ž?~é|ÿyï¹ÁÙ×|-^\™D… "™zØfçEšëÖA¡¢üNð9˜ü÷´×£R{öe,긳1o w¨¸âžu;5 Ã0ŒnDþŠ{/JdBÓéSƒ’ô@f0áÿzSìÑæ…àóq¤ŽF ŸKH?üoï„ciø˜bw˜ïS¨õ§x!ßr4Ù¿ ¹Fsªß¥ÈV9~G¦Ó;ÂeÈlâB’×ü'—’Ö‡4×me°…„Ö<ï¶4×ç=ûЊÎ}7às±c=QÃ0 Ã02#Å} ¥Ò5‘9ÆY ÇÎEæ—I;TâG‘¬¸¯|Æ=Τ¥'*§«ì  Ð¶~i°Ï¥/ªá¥UÈ5šY”7/Ù ¦º£ðÃ*¤YjÖ¥3Ðì×-ÍõðiÏ>´£ƒÈ(Îò”é†a†Q–ü÷yÈ´eÅ#–ó€“bû6¾\‹FÕCzR¼pnlðùÉ GÊÅ‚tENd,Q@¨Qè|æ8Ç_¶£p–`œs,­\È2¤dUbUlè="Ûå<éCq‡h|éúžo½ÓK{ÝêMÚëQ©=‡„i&Ý¿ ÑýÑèóé˜Õ»†aF"R܇!¥9dmä2䦱ÚÑÒ0réÆÀc±cÏÆö…Óú¯QèÃúWÈ£ÇËÈßFÈž÷äö.‰M‚㵎ˆ¶£F¿ ÙÇýŽÌmÈÍá÷‚ïƒ79F¶ô• yø`4«ÐŽìõã^rVGÑigS…è1¢Å‡o¢sÚ9ƒt+ï"ûí^Ha ÝT.C&y¤—öºÕ›4×ç=‡<‹Ì~Žþüw‘·˜iÀÕÀÑâåÅPØÛô IDAT¨þ¶E‹ÇgÄÒ«w;5 Ã0Œ.D¤¸C =C¶ 6€½(¶‰õåU¤<§XqOýhÄsG¤\½…´ÞH¡=qH`ëàx­¬@^BŽGîìžG6àn¾/ßF^6¾ƒFeÿü¯½ ¹»Q'åä᥅d?îõæjTÇ—£Ù§‘ǘ‹jL·Òù‡”p—›ƒÏ›€Ÿç”^ÚëVoÒ\Ÿöò&ê¬LFÏÔ Gâç"×’“Ñó£ê°' ‚SŽýµ<Ò«$·ø s¼GzÍÌŽÀ§€;ëœï¨ƒ4uÜÖ¡0’mZ¹ÎÎù(²êÞÀ—\Ã0º·8¿Ïþìy¥®%ªž ÀÀ?€+лacä.ôò–ÇùCћ痡ÎôQ(ÀÜ òmÀÙÀÌ@~%ðz rYÓ¨÷~W¡‹×_¤¸/ ¶7€‡2Êå`ñÕ22ƒ€¯ Û3»ùrßxÊ¿¨FÀÆÀ<1w Šúr rwƒÏ% -…a]YvLA‹³zÿÖ“Cлþl"u¡pÖ>óˆfÏ$zV·#acùÚe 4?x®Lº¾r†QGzT©‘¾À.ÀÏ*Èü x)#¹…èá°/Ù(î;Ç¡ù`*Å‘±hVað!šÅø)°¨ ¹éèA2Ãù¾/°4–f4µ˜ÂÑŒjMôpÝ€$ùá÷•ËŠaÀ‘¨“0öz¸†èíâsÝFÇ"sŸ6Ô^®@Wè–͉îóV4R÷à~G&M{Þ Z A#”N£pÐÚsפð{4›üóرï£gÜäà÷dà‹ÀõÈ,`R<„F¥]²l/ƒƒ|âN¦?¨"­4|)çî=ów¤¸oM¤¸OBçr‘ó}JðŸ4ràwŸƒ_=§}ï73>ç; ÍŒLAÖÀ׀K)Öñ|žiëoÓ O•É· É_qß=pž)#3Ù‘Ž*°V¹§‘‰N­Þê{!³›ëÙÐd4mv(‘’:]ô§€sÑÌÀqÀ%ÁgGJ¹ÃƒrŸˆóYNy–%”1œœMõŠû@"ó¨=œï3€»ÐKÃGî²*ËQŽ¡À'èZüX ÕÕ÷)|Ђßu[¸ Ýø—iÈü6Œ´ DmòItŸƒ:¶Ccr¾íy 4šøÁÜŒâöÖž»2";ë=P{iö¶~“ïÈž¬@ëÌ.Aí!lY·—ÙÀöÀnH±ªÕÌÖ‡V`8Å#âo¡ò¯ëì»ÝCk!;üKÑ= …g¾r¾÷¹o=§}ï7+iÚURà/@íô4cs”#ãûüKS­Hi¿-È÷ø„|›”ü÷Í]ØÜÇÛЃåtC”RÈ}å\f!»ëø(CZÑ¢—‡ƒß ÑHÆ®h,hªn9ºðáÃj9²þ,²‘K#÷Vðùª¿7k(¿/ƒhd&œÂ¼˜†Ö=,I!—O=@Cy¤Ð6ÒçºMFõ{*Q™g¡“]ÑB'ÃHˤ8ýšhFê‰9ßö|(°ø.êÜ?†’ÏÅþkí¹ks'°0Žh€fwtÍã‹íZÐó/|÷MnDvèû²n/?EJôÙ¨£ð|×]A>y° zÖÇGõ;Pg§¿³oY°µ¿‘ünõ•ó½Ï}ë¹ïýÿÒÔ_² Ÿ¿}Q›uómRòw9)zí%ŽOD#£·VHÇWÎe±S†Zq_®/ioàìÛÍ*¸# 3ciåÒò*°3ɽP_ÚÑ4Ñ*hJéaôà닾/ÿI!—-èÅõ34*2-JÍ^Ä©tÝÆ¢ ÛÑx=$6̦ÈF7d>Å9)Jk–ómÏ£ÑsÂ9LR¬=wmæ ©½}{"ûð÷c²Úv¿ŽÚ…Û²n/o_¾‰Lz ·Ÿÿ0a©YõÿÒÐ<ëüÍm'È6ù¸÷B ;‰AhÚdjP’@o网‚ë+'Ü×;áX>¦¸7ÿ>…/Öþ2/G½¾þUÈ5’Ï ²4c²èfªF.KGSYÓл MË]H4:R麵¢:ßâž{´èÖ0\Ê™¸/•wÐèÍ$4Å» ‘ ¥;¥ïÓž[ M\1‹ÿ¶öÜ=øðuÔ&†"¯mSäVP<ʽŒH1É«½´S8“´ºvþ\ešåø ȳol 2ÓÍÓÄÄç>ïn÷eÚó]Ia;mwdÁÿù—–•®Ç ŸíùkÅ5“—PZ!]5ô³Ž‹¦=N!gÕàsq±4ô òw•À.„Yìsé‹jxirà ç`fľ?Bdgæ#—»¡i¶œ}ÃJÈVºníè¡þ šž‹³¼¦’]‘èEâÞ ñÁƒ§ƒ­ur¿‰ì7qd|ÚsðÑó,$þÛÚs÷à>´vgwÔV v§7ŃZ‰l´ëÕ^î¾:¤yÐŽ†Çö¯‰:¿µ˜ÉúPé>ïn÷eÖçëûüëF䯸ÏCî”P<Ò<8)¶oC4šp-ðxJ¹8ÃQ#ZPMÁcŒ%ZI> Ïçø‹Àv>(Ç9ÇÒÊ…,Ã/Öªhªî="›î´|=Ø„ÿB:{ýU R܇Qh{´6r¥ºñ«­üp$`c´ Àå mŒ š~h±‡¯\œMíT­#Ùí¨ãÐÙrl¸]wO·Ÿ¾|„ìÍçPh‹å+ò2ŠDºšzkG#q»½ÕÑ”ÝlªWÜ_F GÞF×|š-¹›BåÂW®6§x†fÑB¬Çˆ·¼‰êrçiù\·i(²ßÑôb4ý¼-Q¤<—gÑÛñhÚ·µ?óÖÑ=ø3z.^‚ìÑ …SoR¨ lì…î·wŠ/!Ã}–ú¶ç›£Ew#Ó´ø‹ Ò·g£sr'z'´Szé'hp«/z†C±¿ô¬ÛË™èùø7ô~XµûeAzyñ;dëÿ½à{€é1’IJÂ÷>O[ϾïýFQé=u»ò}þ…4{ýÕH¤¸CÓY![¨aVë‡õU¤<§XqÏ“È뤵­z>¹]|E—uí²^¾VS¦ÿ3ø_{r!w#÷RÇ ;¯òõç:ù‘¿Ï"Y÷•KË‘ û߯F×örd ó4R¢.JøŸÏu›‹¦'£öß)÷O¢NPœ7ÑËa2º/ZÐ"‹s7šŸGÓQôÜ“ÑèçãhæÏ]ËŽ4…÷m8v],=ßöü/ävî+H±øj³®­ç\Òµg£sò"RŒ_¢ôº¢‘——テÐ{-Ï¿JÜ‚ÎN"2Ëù7ðäç°´°ðTt.ßFçþ :ÿ<ñ½Ïç’®žëýÞOK¥÷ô\²mW¾Ï¿f¯¿©Õùû¡ x ùçq™€Ü„n&Ã0Œ®Ä$dG»_£ bÔÑ(žÆ9D¦0.a¦}êY(è#ÝøùWŸõ³F¼/p{]rÔôõï0¥Ý0ŒÎO¤Œ=ŽFXG ù¿kd¡Œº³²?Ù’Wki {þPÅ}%2/𠚔єv7½¨†at1:PÀ‘]‘méÈîó–Fʨ;ÑHú\dög î€=ÿ ¨©Œa†a†a5‘äTÃ0 Ã0 Ã0jÆwÃ0 Ã0 Ãè˜ân†a†a€hqêúqw©Å{ÈihQÁyedZkP ¨)D/AÁÎHøÏMÈ-–Ë@´pá ’CA§áà° ÿF0Ï Ê¿ë¡6³j÷"ÿµõrùiõäÀ_”8~ºOÛ9ò5<%á?#?â$þ^â?åÒ«…íÃ_ìjhæçUwÃçùÜ *ú4ò{Ý y€{3ç|·@ñ/6E~¶ß@¾·o£ÐÏ|Öù6Rnto­â~Ü‹ÅÏ·Qåó¥Ùë¹ò÷¾ Äõpðë&)_DŠû£DJõyÈáýÁïjÌe}¤øSAnäîªßCÁBæ%È,þ€ïWĦeGä§Ù^„ýP0¥èš E×·0µå2Œ¼xE‚Lb Лd…÷ 9²w"Wg.o—õI¯Q4ëóª»áû|^ùÁ~JÚŠÚðÍ÷04wð.0½¯G @;yåÛ(¹mQTÙûÐàä(ˆÛ*¨#ÞèòùÒìõÜ\Œ:„·#ïK«£õÍpÒQ´=@§%ì¯vû6\YAfü‘¤ƒt°CìøžÁþþžy ä·¬±ìGÐÁ_2¬‹´ÛÙtðóæ_j›Ôïgß±tp? n‚òÙf[ÖÛÙtðËÇ6D÷ÃÖ)Óüo¿&8¿í‚² ¯±ŽšñyÕÝ6ßçsK°AôîZ‡|“ÚØ¹tð ÒòÊ·QrWÐÁ¯œºvå6AùºJ=Þ×ìõ\aË߯½/š²¸¿‚Ü (ÜKiööYÌBAŸ²`'d–3¸ Ä‹B˜ß‹¦ÕϦ¸§ç+7˜솢äÍp¶þ iöG³ÛyžO­lÌ^uöýh£ºQ›IèœÇ!Ó{ ÔŽÌ4bqPÂÿ¯.ŒíÛ]«»Ð4ìuÀç«(›a€Â›‡#îk¡{ñGÁïpÿ|G~†³ÅÛf5dÞÞDÏ´©h”(Î04Rxs ÷‡à÷à˜œïóÊ7=£6|ŸÏ¡*Pï|“f¦f£Ó9æÛ(¹õg)¬ëǹ1MP>_š½žwžžjÒóȈü÷ÍÑtÁ3edÆã‘bU‰[R÷G4µV.„ÔÓÀÖèaP ½‚¼¦ ò2 §#3¸MaŸ‹ó­KbùûÊŽl ÿ¼|·¤iò5MÿQUŸe:Ö!RRú ²‡¿×­2Í6¤À_‚‹œí_ÌD7g¼,£(ìDS®KP=O Y91 棈~hÎÇè~nAŠûÇÀ[Ž|x¿¾à‘vo¤àº[üéœ&½JŒNG&gi— 7ø=›¿…ü‘›3ø>¯|Ó3j#çsÞùŽFm¥šõ¾ù6J®Ŷì¡íó:MP>_š½žG¡à±ÀŸˆ%F6ÉydDþ‘S7C vn‰ãmÀ)À À"JGW}-.˜^h;¢·ƒ‹Jüg6u+µZ+‰ÂK/D#¼»¢‘\PD»åHÑ ×,Î>‹Î4r¡ðª¿Z åÁªè!;]»Ç‘‚«†Và*¢^ëoƒ4W'²÷½)ákÕÑ.hÝÃ?œ´F %ë×hæà‰*Ëe wPÛÛ¨L@£Èk¢ç‚;¢Þ³+<Òþß`s9ލí¦M¯‡¢ó¹•y&Z\µCLîÉ`sY„f²F"%üŸW¾éµ‘Çó9Ï|7v¦úÅ|¾ù6Jn!ųôŸýš |¾4{=@ϰÿ¢YÉžH‰¿ .|”2½FÕsòW܇ ¥B3OD#Ú·VHçŸÁòPæîÈ´baÂ;e¨Eq‡Â—ÍËA򨂮hVÁ]È;Ó963¥\Z^E¾zó j°Kœ}ÕN½vPøâ~'øL¤¸?Œêng¢pÇŸsö‡ÌG Î ÈSÁ‹Àª,—a@4¸&|)í£‘2_Ë3æwD!µ>³Ê±z†º÷êc+î-ÀYÍÚ¨3’dX‰¬Ó3Ê“åó9¯|‡ ‡O¿©S¾õ–» yÙ >BƒŠ+IÖu¾4k=·¢Ùöãˆô‡w€Ÿ"áž—/#òWÜ{Qz„hp$šÊèl½ÿõ¦¼G›‡â¾ÉŠ{ø_›ør|L±;Ì÷)|Ñô§ðbFÒWRhãé+×ì,E#ïûú9Ǫa%…Ó‰áÍm¥ Qö[Ð(áàÚXZï ¤“ í*ÀkÈLé¹*Ëgto–¡ÑáPq¿Ínì«¥]ÍGž¼êAhGü^lü7h”ê(d&øªƒõÐhV[ygž‘LÏç<ò퇞ɋ‘ò^­’ã›o£äþˆô”¯'£â+S‰Y>_š½ž—¡Ñöwœ}³.±^”/#òWÜ—PZ!])Tg%;M¿\&íдÔh~8E±¸Äq_z¢rºÊûäÆ*di°Ï¥/ªáøö‘kvæSl»µ®s,O@vðCÑhûR4Zçé`k>|8ÙÝF5,@Óú}ÑÌÛ À>hÉ‚2ÿk&:Ð ¦_lÒsz74Juƒ³oX ygž‘L£žÏiòí…Lµú'¢¬¼óm”Ü'h]Ü5ÈôóM`8z7¹³Ì*Ÿ/Í^ϯS¼Ð=\;èv ›½ž+ÿâÔyèWVÃc'Ŷ+‚c×ÙArc¤´¿X"ïáÁñ,^¨cï£ÐùÌqö½ˆÙº£ûãœciåB–¡NC%VE Äö²Yðj˜ë;û& úŽÛ°fÍ?Q½ì‚¦¿¢|ÐŽv¤À߃š/ب–ÈsÓô2~¾¯NþÖ,™ƒf \6IëCñÀÇø2éVz^¥MϨŽF=Ÿ}óm¾ƒÞѧ¢™¬zäÛ(¹%HQ_Žfƒß¥0Hd£ËW‰f¯ç§ÐšF7ÞÆ¦è?· Ê—áí£Q­‚ŒwFàƒßó©~ ë#d×õÅ«ÅW"»cwëÜÞN¡KŸŸ£ÅKk¡ÎQhêmÈåX¢Š«d?_Ž1(ÊÛ§‘yÌ:hªkŠ Žöÿç§Ñð4Š0/({GJ¹5Pĵ·‘ÉΊMm@ÀKQã©Gð“ׂrGÝmQ”Ù»€«Hï3À–F7[ ÙÂÞ…ê-äd¢°+j·×  4.Û#;·ž¨S3&(ß¿ÑJsè†O¡6?­GyÙªöE ëÂQÃÈ”®?rAÚÖ¶ôG#@¡ùà ôŸoEm Î-È]qù^ÞITÛ|Ï·rƒ™æFèy™‹Å¤7ò<|iæz ðž€GAk‡~B±åE³×s"Å=OöCJÔär‰L@ÊÿA$/º2 Ã0 Ã0ŒND}¬}ÿŒLo²ŠbêáÈÅš)í†a†aF >ŠûJ4\¯ÑöÀ£h Ù0 Ã0 Ã0ºõ1•1 Ã0 Ã0 £&Ì1ža†a†atLq7 Ã0 Ã0ŒN€)î†a†a†Ñ ˆâ‘æéÇ䇸?p^™VLgCŠý¸ƒ¢î}EÌŒ‚ˆÜEaÐÐâÔ›3(ŒJV ¡÷=kL§Z& ó©GP¥4ôB~×?|ÓöA¡œó$Éß{½¹w˜RÇôšµt7nAÁ@‹íßDþÏMal…Ð?{'›¶³Zôïú]O‹µ«®Ëzèîú•¾ŽB'y<Ç›9ßFÊ…ŒG±VÖAX\×itù*ÑÌõœ¦]5{=—!RÜ%RªÏCNëï~Tc.ë#Å÷˜ rû½ã´  H›¢¨ªsQЈA ²‹Q𥯡 I™Q0¡f{±®‚üó?‡¢‘nÕØâÔ•7{Óz¦×¬í ;ò"ð(€Ð`"°9 ú_ê'ðxlßÛy0Ö®º&ýPP¯¥¨s7½û à!Y?Ç›=ßFÉ…´g£ÈÁ—!{n§»Ñå«D³×³o»jöz®@¤¸/ ¶7€‡2Êå`ùòÕ22ƒÐhú¯€Žï„.Â)ÀSyÞ‰|¹oé)o¤c òËßku'ÅýûMžž‘/‹P^€¿"~?`cà…˜ì²{ކ/{£­ÓˆÞ»Ñ»øÿ€wƒ}Y?Ç›=ßFÉ…¬”¼éH¹l–óð¥ÙëÙ·]5{=W ÷¾È´åþ r'^*q|¤üû*á Ydôi'ä~:pš 3…ˆ¾…/?›ä¹éÀ d2:ønýÒìf5¶ó<ŸZé [G¢“‘ÙÓQî{QOuÝò›¢0ï÷Ÿ8Çú  _Ç&üïû(Üv5Ìp¶ KÈLB×n2•H*_šôÒ¶£þ„/à!9ç³7Ñ3h*Õ‰3 8™ NG3g"ÓBßv回Ñ\ļp°ì¯hÄ×Uf²~Ž7{¾’›„î­›ƒßÝo;4Aù|iözömWÍ^ÏÈ_qß)RÏ”‘ƒì¾®+#3 ˜”±?½¼F–ùÏÓÀÖÈ̦z!³›iÀÀ4ÍÕÓ‘ \ŠLÎEŠùÖÀ%±ü}åG¶Y^ ¾‡[’YÅȦÿ¨ªÏ²ñôö@³*GŸ zi‹Éµ'·!E| êü„|ܤå¶ðÁ軫Êò…õUÓ†ÔGí±ò¥I/m;0êO¨°¿–p¬7R„Ý­š§îXàtÔI8 µ™ã䆢ûæ:à[DÏÈø¬Žo»òMÏh.ÖAŠèýÛâü.5Òòm”ÜèÞ ×^Jt¿Íl‚òùÒìõÜìç‘ù+î›!;®¹%Ž·!Eí4]Ѝgº%¼MM\‚^ŽIÌþ·NÚBÇh®DÊà߀ïyïêÈL–#íŸÀÝè%7ølro¡ ú{ÓÙºjȬTÏóÑùOE#~brmÀÏÐhöƒÈ¼jº&!w"…jœ³owT—Ó«,_Xÿ+*ȵW¡Þ÷ëÀoÊç›^wlÍN²¥\uº'¢E«ódÿ 4¸Û†Uäy(°­ó™‰fqâ¶óO"¥à>4pñº§FS8ÈáÛ®|Ó3š‹UQlZvzï„Ǻk¾’[†î­p}Ë"¢ûÍ]CبòùÒìõÜìç‘=*‹ÔÈä1£½Äñ‰hDûÖ é´¢‘Õã7‚ÏŸ;#%.Îb§ I/Õ4<é|9HÛ5ØÍ*¸7áLçØÌ”riyÕCg¦-ü yÙ¬mˆtWîÙ˜hD=|0ÎA·½‰ì‘÷DŠÇû™–º˜4жW·|FçeÔá¹Íœ%ñ;àáØ¾jžE ¶ë*ÕQ8Íêü~µûµÑ,VH’Ù^%²NϨ/Ÿ …b‰³¯þfÏ·Qr¾XùºöyÔHþŠ{/J(ŽD#«=‚­·ó¿ÞD î2à¿DJȆ½¹áI"üo©y_>¦Øæû¾¸úSx±@=®•ÚŒúÊuGV zpYF±=íJ ],}|Æ[󟀯«¡)ÿõÉe…w+)<°ÓšÿÝfÔƒ#·µ}ТԃÑÚœ¤™œùÈCW-´ A‹÷bûã¿A&0G!³¾'Ðý³š¥Œ›œùuzF}XŠA¾‡éüu×|%×ìçÑìåë*ç‘ù«K(­®‰¦œÏJ8v.šÎ=8øý:Å \h^ªGNQ,.qÜ—ž¨œ®ò>€Â•ÂKƒ}.}Q Ç/°\w¤7…5ÂR΄ª÷¡µ »#“›Ôî×ß0Þ'šñy¸Í>De3ªjè@/„~±ýIÏÕÝÐìã ξa5äuzF}˜O±míºÎ±îšo£ä|±òuíóȈümÜç¡N\Y Û®Ž]‹”÷§­úšÎ¾MÑÌ-‘÷p4Ú¹ º¢0Öù> Ïgß‹h‘­;º?Î9–V.dê4TbU``{Ùffçû¦¨SSÊÓP%– zùò4ÓYñmF}iGöæ«£v–s)Ë& rt6–@ IDAT}(¨_&ÝJí*mzFsðRÖwöM@íõɤ?t“|%ç‹•¯kŸGF´ß4вUñÎèþað{>ÕÛé|„+=Eqt¿•Àb[od‹|;…®ç¡ãx4â5)úK‘ùC’ ýÁþJöóål"q½:'£‘µ8ùþ秃2Aþèç¡{GJ¹5w”·‘yÈŠMm@”KQã©W0•mQ'f ²ÁLRÚH?J¾ª“ÍÑù­‡êy9…×÷3h²-w-dƒ{ª_—wÑtO¡ÚÀiTàóè:=ün!iõ-Ÿoz!¾íÀÈ—‰¨m»îm_GnX·FÏ­vtm÷Gë+feï;¨/F÷Ù6È„¥ð{¢uŸB/Œ™èÙ»'ð%ô\Nñ3¸R»J›žÑ¼†®ëxÔ^·Ežºî¢p½dûoö|%2Ý?÷“< ØèòU¢3Ô³O»jöz®@ ¡ªx‘«¢8{Q½Â²|ø±‡ì\< 0È‹Á HÁÙŽþ„ä ò9|#ð›ôEþÿBŠ_Œ¢°®üÉO¥x¤kä|zÉýy‰?„|åÂó8¤¯†®Ø¾›Õ„!ÖC—™õàVŠ=¥@ùÅz¥˜Œ|¸ÿ™ A®ï~„:5!“²›³ï3ÈÓÅ èÚ$•ó%ä.³ZN£ôˆêM¨Ó•¦|¾é…ø¶#_nA ÏŒíßùfþZ[Þ?B±²`/àËèž{ør7z‘Ý hŒGÕ§QGþ"äNò±Xš•ÚUÚôŒæ!üpC°_Kqö,Ÿã!ßFÉØnDÏGŽ7º|>4{=û¶«f¯ç2DŠ{žì‡³Éå$™€”ÿƒH^Äe4¡âžµ¹Áh¤Ÿƒ\y†a†atRò·qÙ/#»(¦>Š\±™ÒÞ=Y ™ß|EÑ»ä3 Ã0 ÃèdÔGq_‰ì‹ë5Ú>x™Ý“‰Èl¡p¥ã†a†atêc*c͈ÍûsÔo±¯a†aFLq7 Ã0 Ã0ŒN@}Le Ã0 Ã0 è SÜ Ã0 Ã0 £ÐãÿËÓ;Èou´P°­À5À†ûq¿5IâÇÈg{È@àfdÃ\kˆûÐûž5¦S-Ðù4›õÀÿ è¦«ow·¡Åȵ0ù¢_µÐ$ŸþYÓ¬õl4/ÖNff=ôNwýJ_G²ÿi¹î–¯\/·ãÓÀFÁïC€7›¤|iä|±ú«O=—!ŠœºIšì„¢–þ,øý µY¯œ \@y÷Œ; ¨|PxgòÃ=ÃÙ>FAŒ® Š jÔø †R cP4ÏjL§ZGQ›íE}*05ÎQK:X“Ú”—6$áyà‡(xÍŠ#‰fM³Ö³ÑœX;5š™~èýÝ›‹ ¡€iåº[¾¾rý³Ëá·µQ x`¼F•¯Ù빫Ô_ÖõìAGÑöœ–°¿ÚíÛtpe™AtðG:8fÐÁé^U&ÝaA:[ÖXö#èà/ÖEÚíl:øyó/µ OØw.<\ËjÓ\·í­žmkâÍÚ©mͼMDís„³ïX:¸ŸW!×Ýòõ•k 6ˆt—¡MT¾f¯ç®RY×s…-÷¾À.ÀýäN@#ê/y¦»𒏧Äñ…À,² ú´ò ?ðH‹FáîE#pg“lÞã#7Í*솢Îp¶þ iöGæ<ÛyžO­¼ž°o6òS4°Šô&¡s»9ø}ÑùîàÈ Cá¢oFuô‡à÷à„4[Ð,δ@övà\4+’¦ž}¯ï§Ü'e¼EpíôAAÉŽMøï÷ëö͵SQm;õ­—ÉÀ](šò­Á¹LÖ­R®»± 0xÕÙ÷W4S´UrÝ-__¹P•jÖò5{=w•ú˺ž+¿â¾9z Σ­J¹îÄ:H‘½[œßëV!×Ýòí*åköóhT¾Í^ÏèQY¤F6C‹ç–8Þ†¸7‹€Oy¤Ù ìŽ^bIJlÈlà +µZ‘ÝÒÃÁï…h´iW´ ©s9Ýú(Ø·8ø,ÑKÝWî­àóTI‹5š‰Í€©~1Ʋ` _¶‹H>ç'ƒÍeRvF"¥¤ | ì]ãÈ>Há Ý·ž}¯›ËÛH™í|¿Ø<ìÛ=(Ãôe0µÓÚÚ©o½€^~W=»§7¢ºV!×XµÓ!èÝú8êÈ…ÇÒÊu·|»Jùšý<•o³×sòW܇ …£¥BÎOD#Ú·¦Hs\î½ä;e¨Eq‡Â—ÍËAÚ8û6F³ 9ûf:Çf¦”KË«HqnC· '€ßäœW Zt¼7ZÈÒ×9æšl‰:\Imä“*ò­æº=T&½9HAÚ›H!Ú3øÏû¥þdt¬&ã[/ )ô߯#' R¨ûÊuG>A Åg_’i‚¯\wË·«”¯ÙÏ£Qù6{=— Ž¥=- ŽD#$=‚­·ó¿Þ¾€BöF£4UÈ;üoï²R•ù˜bw˜ïSø¢éOáÅt­¤ÐÕW®³ÐMÍ/FÊ{´€Ã‘9Ð4ÔQX†Ö;\Háå€àóÝŒò­æºý§BšB&«¡‘×õѽ`t~¬&ã[/ ÷Fܵì2Šíá}åºKѳù=àÀ`_?çXZ¹î–oW)_³ŸG£òmöz®@þŠûJ¿0ÖVAî€âœ‹¦‡Žíˆ`þžÒ£ø!áÅâ²R•é‰Êé*ï(|Ù.%z ‡ôE5¿À>r^ÀÅȦëD¤ äÍnhëžsX‚œ;ÛRëõ‡ê®[¥öyZ;±;:‡ÔwÀh¬&ã[/ —øàÍ@4hS\wb>Ŷµë:ÇÒÊu·|»Jùšý<•o³×sò_œ:õ<â/“ðØI±íŠàصD6B.»£—P)o2.ÃÑKiAº"'2Öù> Ïgß‹h‘­;º?Î9–V.dê4TbU``{Ù,hC†#ŸîõzIö¡XÁŸ ÷/tí÷H8–Ô]­TÏi¯›ËQ¼‚}€Ï!F×ÀÚi2¾õ²ó}SÔ Iò<æ+×]x )ë;û& ¶ödrÝ-ß®R¾f?FåÛìõ\PýÒ¨ÇVAÆ;£ćÁïùToñ°? è÷6²MÓº[odCy{ðŸ8ßB#Ý¿ôÈû@TqiìçãŒAQB?ÌcÖNFÓ³? ­ú/:ÏO£‘­1hzr¯Ö‘R.d ôR™ì  x*¤@_ŠO=‚³|-ν)ë;ÛÔvªaZ¬w?É®O¡b&j[{ò½Ñb¹°-E3=Ñ”y ²yý2š9‰§]©žÓ\·A¬[žR¼‹ÌzߣöÅF}°vZ¾õ²Up›£ó[=w—#3ö”rÝ×P;U¶Ewî¢ÐîßW®»å›¦|Û¢Á¼1hÝÛ|dRÖF4 Õ¨ò5{=Cר¿¬ë¹-„òˆ\œÅÙ‹ÚŠihÁÔ=d·ä’‡F/Ÿ«[*¤Óù¾‘ÚL"`] ^œÏ£—ÂܘìÖȯð(ôRú'pţѾráyœŒFÒWCWl_Ч½G¿@ É’ü.gÍõ¨üIœNåõ¥Ž®Ù™D‹á\ú¡™™ñH‰xuT.JÈ·)&_@š¥¨3x5Rp\|êÙ÷º…×·nE£ƒgxÈ͵Óêð­—ÉÈ7û€ã)ÑsÀ(Œ¨í+× ;1nökIÕî#×Ýòõ•»X=¡<· {¸Ñåközî*õ—u=—!RÜód?ô€=\N"‘ Hù?-0Œf$쌞ƒF3Rïv*äûd$g†ÑEÈ߯d¹Œì¢˜úp(ð;Li7š“µÐ4ÿ7Q\€‡Ë‹FC°vj†ÑTÔGq_‰ì"ë5Ú>x¸©NùFZ&¢éý^ÈfwµÅ5šk§†aME}Le Ã0 Ã0 è‰úŒ¸†a†a†Q¦¸†a†aF'ÀwÃ0 Ã0 ÃèDŠûÀŒ›OäÎJœœïQškƒJ·­f'M;¸¸°Îé5Ьîßûür ï Ã0 è#QPíG‘ׂÏw¿?ª1—õQ„¼c*ÈíÜ%±ð]”é(bà1ÈãÁQ±2.FÁ—¾†‚&ufvDÑë Õe*Å®4_©s²  8Ej¼ y8ª%²IÓÞ@îWë™^£¨÷ýq>ò°²7Šnj†au$RÜ[ÈÀCår0Š6új™AÀW€_¡Ýq>¬. r+Ù‚,m‚:.w"_î[¢(„F:Þlt!2` ­q:ЍØø~“§×™y7ø\ÒÐR†aÝ”•Ej¤/° 2q)Ç ("ßK%Ž·!…Ýõ_np!0 }ÊBqß …Ô^xHÇ;"cÑ,À(àC¤üþ”âPã>rÓQHðÎ÷xˆs€þÈd1É!سfšé˜‚f5†¯—R| ÷Gu÷oà¯5æíS“€cß9ß§ ™›4„¯Ò@Z}¾#7 8™i AmôQà"¥/$ 9?u0?ÌÒ^C÷ÃJÒµ÷Øßƒtãdø_ßöâƒïy¤¹àwŸû2µÁÍÑóë)à 4(b†aUÿâÔÍ>À3edÆ ;äëÊÈܤs$²a_8 ½\K¥ý4°5òV_ ½ÙÍ44â?™]¸ŠÃh¤„,ήò¾$–¿¯ÜáÀ!Haz%ønI–5€3r”ýPgÀÝâ­¥ )dG£à,gÇdƧ#%÷,t½Ž«¡\¾õwª«o¿/%ª¿™UæÝØ8ÙDäÛæÈ ö_| )~#)?jýÕ í)ÀIÀãα4í ÜÿB™¼²NÏ÷z€_{ñÅ÷<Ò\ŸûÜ—õ€«€ÕQ]|Í*^Fa{1 Ã0Œä?â¾9œ[âxR„n@#tŸ*!÷,ðmd*§ÿBÊj©h~³ƒ€u(MK+p%Q¸ï…häuW´ap9RDB{ûåÈ&ö³DÊ¢¯Ü[Áç¨þêm¶r}¾“ÐuiEÊI8"ù[¤¼­¼ì;X\ŒL›f"¥¦Ú¢¾õ·,ØB%iµ×a ja[š ܈H>ì{2Ø\¡‘Ö‘$¯x)w!³ïiÚAxlE™¬Óó½à×^|ñ=4×Ãç>÷erP®S‰Ìjf¿ Ò»'ez†a†A=÷!Àû”V®'¢‘®[+¤3½äÿÜFÃŽB Ï)$+‹2Ô¢¸CáËÿå í œ}£‘w‘ìLçØÌ”riyعÊÿ&qŦq¥³#¶ïàs0‘"¶Z+áÆç}Œê÷¼êχàEç÷ëH)ÛHqoA^NöÖF#é!ƒJ¤›ÕZ’Fæzø´—¬I{=*Ý羌E×þmÔ‰ÝSÜ Ã0ŒªÈ_qïEé»AÈôejP’@o罉‚ˆF&C%pr¹É^%ÂÿöN8–†ÑÈžËû¾øûS¼`m9uë_…\£yžÊ#Ô+ƒ-$윅­ª™5ŽÓħ¡‘õ·‚Âóêv~Ž:”Ó€'‚ãë!wŠ¥L$þ“m1ëJšëQ©½äAšëásŸûЊÎ}7às±c=ÐsË0 Ã0ª Å} ¥ª5Ñb¼³Ž‹¦Ã~D#µîÈíËÁï‘%Ò_5ø\\â¸/=ƒrº/õŽH/ ö¹ôE5¼´ ¹®@RÒûÅö×¢`7²þzSØ™uLÜE˜»¡ÑÔœ}I±\JÍFuš½=§¹>÷¹í¨ƒð 2г)n(™›‡ì¦]6¾ŽFÒÝEzï ¯-DÊûÈàw©Üáè%º Ê²»Œ%òD2 Ïçø‹(°«ØsŽ¥• Y†_¬U‘­õ{D6ºÍÀd2á²I 饭¿¬Ùy?Ø)©®W”>wÇg¯o;¨wz¾•Î#íõ¨tŸ‡„i&=×@£û£Ñ³§3wÌ Ã0Œ¦"R܇!¥9dmä ¤¨Tûòy:øÜ˜»|@ábGˆ¦¯_C‹¹Bþ€lÙÏA6îýÑ4ørJÛ‹n‚ljkùkGŒ~ÈÝÝÑȼá~Gæ6äÎï{Á÷AÈÜôO+ò2ð?À>È3K;²×ïˆÉ­Ž¢ÓÎ&Å}Å¢7(\8éÃÍÀQp­éÀh´ZÒÖ_–|‚:•}‘ÙÌ1ȜȵQŒhñá›AYwÎ ïJí`‘ýv/¤° ~/C&y¤×Èë•Ï#Íõð¹ÏCžEf?Çþ; µiÎÕ¨íÿ )úCm‰"ø†aFJ"Å}‘ë¼Û¸öº/"¯7“ï ÑÇÿk¯B.än`#¤$®†f’ü¸gÍ) ûîBîìÒð$røeà‘¢uRŠª!mýeɇÈ?ùqhÁsèÇÝmW£¶w92½x­Ë¸ˆÚ¨ÔŽCÊ«ËÍÁçMÀÏsJ¯‘×*ŸGšëásŸ‡¼‰:+“Ñó±u ‘ø¹Èµädô\íƒ:O’¾ók†a®áI~ì‡^`R@)O& ¿ØQÛbHÀ(S\™5 Ã0 èù`M%/C#aõâPàw˜Òn†a†at ꣸¯DÓÊõmˆÂšßT§ü Ã0 Ã0 #gêc*c†a†aFMÔgÄÝ0 Ã0 Ã0Œš0ÅÝ0 Ã0 Ã0:¦¸†a†aF' òã~…~Ü]jñãr št^™Vàj QÃPÐ¥Oåyù“^“ˆ|NŸAª;p9 Œ3¥Ñ1ÆÔþïÌ ­õÐ3a3t¿Ý \Gý™çÅvh±üaÀëÈÕJÖõì›^–r½€£€O#¿ú½€CHޱ‘e¾[ ÿù›"?þo ßþ·Q쿳µç®ÜN'  |#PÀ³·‚ônAñ’‚»­ƒ4—$*ë¸?:S;mV="Ëzñ}^î«=+¤w; >˜ÄQQH×Ê)î)ÕçÿBA e^-ë£?¦‚ÜþÀZ%Žm|Ý„¿@‘~€.€[ÆÅ¨¢¾†‚©tÞ@n7îËŽ¨c[«âÞ—ZŠ”‚¡è~ëL­1m#"ëzöM/k¹UP¼Žç€ïË»|‡¡¡;€w1è¹?ø~éÉd]#wP°¶%ÀÀW‚ϤÁ½6àl`& ¸’Ò”rzD£îÎÔN›QȺ^|ŸW¾\Š”—íÝ) <êÛ<è(Ú ƒÓöW»}›®¬ 3ˆþHÒÁ :Ø!vü4:¸‡z:ûv d·HHoXplË ÏÃ6Ûš};›~žA:Ñý3ÂÙw,ÜOƒ›à<8vðGàJtMþ€|Ýrd‡g"S£éÌ™Àà„t÷~œÃÐHÇŒ ?ßúõF÷DÓ¿µâs=Ò”¯Òù¦©gß|'¡ë0Í4݃ÌÃ6ˆÉMòÞ Ma›èŸp.•ؘ¼êìû+º“F'²ºn¾÷Gšvº7ªÿéAZCKäí+7ÕëèZÿèºô(ñŸRøÔs šYœFá¨ÎàÔ.Ó¤—‡\øJ©DÖù&ºÎFu6°Šô|܇¢rǹžÂg°µÓävšD,±ÍÙ7)8‡›ƒß=×vHH£’Ѩû£í4Ä÷=8ƒòzÈÄcF‰-ÞÓ¼÷+‘uûó}^…ìDtÏ]έë!“ž{bû}ÛAòWÜ7GÓÏ”‘ƒì×®+#sWΑè×EÓ/”Iûi`kT)Õ²p°:p 2ׄ¦ëÜÌ@4Õ±8Ù‡=@òCµ/jD§ ªO‚´Ûd}8$Ø^¨ ×)œ›¡i¦ï"[¶Ã™¡Ay®¾…^ #)žÆÙ½€^@çú,²?Œã[!k µ GU8—Jø^ßòùž/øÕsšziC/° €£v4mìr8j^!j‡PÝ´ç:èAžO‹ó;©“™Õu¿û÷ŽNGS¢g¡ëw\Bž¾r._ Ê:)Fû{ öWjà¤áSÏÀŨ}„eê”ó _¾×-k9_ê‘ïhÔæÝ—d–ç±™lìÛ¿ꜻƒTÖN“ÛiHï ŸmQgýdBrz†…ëï.%z®ÍŒ¥å£G4Óý‘w;…tz‰ñðåØö 2{ZâÈù¼ßš¡ýùÐ ™³LCïàÁyô,óŸ½ÐZ=ÒOjHÛïNÏfÈmn‰ãmè}°Ùç&ñ,ðmdÿ*ÿBÊB{‰ÿÌF£"îEOËdTþS‰æ,4òº+QcŽ¿Žû¯oýeïõð-Ÿïù‚_=§©—Vô G~‹«oûÞ >?ÒMZ˜†UÑÃdº7ò å‰Ïý‘¶^Œ®ÛLôR‰Öùʹ¼^J!³ƒÏ(=bð!Ñb'ßz~½€¿‡Ö#퉸}§ozYËù’w¾›;S¼h-ëó¸)AkÝ{» kûGÎÚir; ¹™hQß}±r乌HÙ[Dò³ÍWh–û£^í4^â£G¬æ9¿¿ˆÎå`¹³ßçý¶-o>´¢÷ÑÃÁï…hfmW4ƒ‘$¿;D«4hVªT Å}m,¥\OD=š[+¤3]¨ ‡æ¤À_‚MRc[씡ZÅ},º`noòmôðÜHÁš”á´BøEà?%Òìއ¼¤¿!Õ)7Vø0 ÷­âÈ´_@Ó±k£›>Ä]5šc¸ÓMOP¬ÈúÖ_È«¨!׊ïõð-Ÿïù‚_=§©—¢¥Ý?îf}+q*·ƒ 䯸/¡ôâ¸5QC:+áØ¹h òàà÷HTî ¾üY"ýp eq‰ã•hGÚ)nœP85²©5ÜÏßÎAvc.½)|˜€n„EU–3KvC½áœ}Ãb2èŠOÝŧ­¿¬©t=|Ëç{¾¾4º^|˜O±MåºÎ±<ñ¹?Ò´Ó~±ýñ瑯\œR³ˆi¦€ÓÔsOôò}=ó£ðüÓ¤—µœ/yäÛ ™ŽôA£kI÷Oíù4ª7)(K)~Y[;Mn§I„Jü(Ò)•iôˆFÞj§¾z‰/-ÈLì#¤|Æñ}¿5[û+EOÔ¾\å}…k1B" ¿§ô}çÓ*¿â>=hP8½;)¶oCàëhäâqgÿ;è†n!RÞG¿K8 G•· Ê²ƒFIFi”ºqÚÑrZLØšðßmÐêwÐJí¾”ï}Ö‹>wtÆ'ÈÍ>Û76A.mýý?öÞ<^Ž¢ÜÿŸì$!熀„„’@¢ˆ 1M„p¿pA‰ì²ï*‹ ²þ”‹ z½  (›ˆ ˆYE˜Zˆò IDATÂV BBÈ%™ßŸîÛ==Ýgžžé9s–çýzÍëœé®©õ©ª§ªžªZÙ2¿GdSV/m•‡5~ÖôZ©E®,¬ Ü$§Væ_Gw0, žMAqMÚìBñåV­~Xåô`‹Ä³-ëpg!Ïpž|žƒ””CPZAû|ž©Á¿¢ÝY):ÜžÀ9¨­?’ìÉ¢Ó:ƒ|šuß™¤$WŠ\NÓå´7•6½a{úùÈ£G4«~4SNC,z‰…ƒÐà²MP,ý[3å//ˆ.òƒôÙRÜ}iÕY{÷¬rP…Hq†„=d#t¨­U¹o.Ý‚ÊÙˆUhÓiœpùðU¢Í £¬ŽC#Å{Ñ,Ãh´’•I["Ûàz–ö¯®¾6.E3,;¢Í4ów;¡ÄD#ü /¡F#™wkP£Ò™Š6†dÙ"¶Å "»É>¨£wŒ¯ Ûœ#‹ùD›GÞBÇFíœâît#ØéhYj•Š-Øó/d}´´·€ú@kyXãgM¯•¼ùbå%t3Û¿£Y«µhF"¯}äoÑ,Õ9èʡȎôÒgŠ*7°ÕÙ«^‘âÆå4]NüµW rÛ ÉÉÃ9Ó‘GhVýh–œZûA«±5:é+´ÉŽ‹¸˜hàjéßš)`k¯@ùtš€þ þAúç3L¿”‘«T!RÜ'¹:3<s•6>V^A™0‰¶m~ªq¡ï… aRLÎ$}—y/täõu„ ÝvIƒúh”· æ.YŠì¡Ã™Ç´£©>~ˆŽ,¤ãbr]yûŽ”´8á™·?GgöæáJ”w—¡Y‘'Ѿ‚óîž@»·BÑÓ¨BCyåXˆ-ÿŠÆZÖøYÓkÅn^îBA˜ît—AÞÁë ´¤z,Z‚^…®uNÚð6Ký°Êéãh9÷@4cóª‡Ôè®h,ù¼:Që.tvqÈwQp"Ñ Ör+Úè¸Ãõcß þވʫánüM+§“ˆúœFÉó½hÕ»HMârš.§÷ “‚Ï ¶ïm´±ôzjë­4«~4KN­ý UØÍÔÏ¢üxcéM¨‹-¤Øþ­hù[{ ÿøZÆß]zRNÇ"++ÉÆ*Uˆž4Ž=PÎ$ב7u1ÙaíCõÍ;íÉl4øHV’®Àþ¨òîÑ숴Ý-½íAW®Žã8ŽS'¿€ ´Ì±‚bn1µ²pKiïJôC3>ÑRÓt´”uS3#Õ@º[zÇqÇép4~s*hIá²/E(šVd'çJUã(¡]ÝÓÐ~ƒ7ÑÒÚmý¨ÓÝÒë8Žã8N‡£}Leœ|œbpó,ég×;Žã8Žã8]WÜÇqÇq§Ð>6îŽã8Žã8ŽãÔ…+îŽã8Žã8ŽÓ (ßœ:¹9“y:ﳈ#OD›úÎN<ï |?݇òó@óºÛ]@³:·ôMt®ç¯È>¶pº€ê ¢²ò„ :yä t“Þzè¸;ÿI¸kEO!º ÊqÇqÇqÚ šq€.9‚N€¹§|d¡l ì ü4åÝ:èìU´}%­ÕÝ,t«ÖmÀ%Àsè"€ÚøÍžèF±zÂmÎüºøÚ<Úšâv)º öˆ6üsÇqÇqœÑŒûnD×–¿RxûfüfAð»ë û7hæý-`>ððgÊoª}¸ø=0<€fèÇR9¸h Þ-ÞFJþ0`JñtÇqÇqj¦WÅ“5H_{VÏMCÐìïÚ:ü¨'쳑"û‹Ä»½Ñ 17VdŠs8:M†àïÑÀáî”ß,ÅsqÊ{+ákEð Ÿ­sÓìŽö2l„fÕC'ü+}ÉÃæÀýuÄÓqÇqÇ©™Hq_ŽN–ymÂ$ø¾«•>Àê:~_+Ð óR¤¼Çƒ¯¢™ä^Á'œïüÿaÎðVÿ$RÚA6ìkÑ1›i„adÍÈ[)Åþ†ÿ¯¥Ü´åt¬åµh ³"ˆ×¹TšÀ¬¦òèÌTÚÃ;Žã8Žã8íF¤¸/¦Ò–}Dì]­,Cç··'}ÐÑŒýÐI1+ï?†f£OKùíYÈ<äË9Ã|JÅ6´]ÏZ±M–f¼/’éhÖÿºØ³anûR9xi¥“"ÇqÇq§&"Å}>ðutæúÂàÙ4sûx!,B³ßƒ(7¿i=sЉ+G’®l.B'±ÄÙ8¸x´†pÿŠfñ?ü#x¶2¡Y˜ñ›á(_«!¼¼ô£r€0© ÷; Óv@éèOöÉ;Žã8Žã8NÉ÷ߢYæs€Ÿ SHöFç×s†{x3èhpÆŽh†w³àûDd²³x9§»c‘Bz-ºéôã±ß?…ùUÀÓ‰8„æ"¯"—¼ñ»™]€fµ{#Ó”7ÑÆÑ4¶ ~_)’•ùÀ44ëþðyd{ŸÆ4ˆéÌf ~ó@Ãcé8Žã8Žãd)î+€ã‘â{RnoA3Ðõð RN'‘­¸Ÿ€N` 9.ø{#peNw[I ç¤6âЖpß žÏNž=üTÚ‹ƒr~{tÚM{peæehPñ$:ñæ¼· Mµ‡£³Ï¢ã&ÓÒá8Žã8Žã´ -ÔwfŒ=ÐÅ>3)?’±;38Ø)ý…Ùèò¥ovDÇqÇqœ8=ª;)€ß¢ýzn íjìÜDÇRÚÇqÇqœKû(î!ÛoŸm­ÀÃÀÏ›ÇqÇq§³Ð>¦2Žã8Žã8ŽãÔEû̸;Žã8Žã8ŽS®¸;Žã8Žã8N'ÀwÇqÇqÇéDç¸8&ÃÕ t®{=œ ÎNy78Ø$ç)àGÀ~õ®B·ž<˜xß ÜœBtTwà2à}”'N÷d ’ÿ;êô§º@ìè³>À¾è"®ÎΧÑfùYÀ븫—‘¨í‡Ú¿{€k¨}3¿Õ¿"ÝmüºGãßÐÅsw¿¢üþ‡¯ üܵJng¼»¸5åyµ~!o?Ólº²œNöF¡›Õßü»]ú—Æ$à0`c¤¹¤•q5wVùƒæÔ£<îEGÕ#šÑNZåÔÚþÅ©Ö^µA¤¸?L¤TŸ.º-øþ¡ÝÃT6EåДwÛßF‘þ 0(p÷=¤8¤…½'°aá-E ûÀ×jt'äMtì¦Ó}ù RLêUÜ×A÷/< <ƒê©S<ÐåfË‘ò5µý€Kè_Ñîf¡‰™ÛÐMÛãQû; øN é¸ ãì|ìKôÚêjégœˆ¢åt4ðð`º•ü àoÚä^Oàtàà»HJ¤XÝU£Yõ¨è|®…ލG4«´Êi-í_5=¶ "Åý ÊgÞ¤¸+î¿ ü Ý¢šäóhäò-¢‘N @¶Dˆ8ƒQÆý 8²0ï@g¥o üµÆxw6jé 'eèÞ…º8Í÷ưº•ùD¢ö±µ™ÿ:FøW´»K)W~ôvA³JïæLÇŸSžíÏUq×)œãвз‘-Û¬˜›¡A|®N@Ãh*GáÛ è9”Ö§‘]akþ…l€ö&\%-Õ°–‡5~Öô‚-ŸóäKOÔ1} 8X‹–ƒã€dàAàe"™Ø—öYö,ªÜÀV?¬r:8 ;†Êïð”0­îâüg×3bôhð¼’¿¬Ï ˜£$7-±ïá`¥œä#ŒÓÀ ž÷Q®ÌZük„»4Æ"ÙKvj}Ð2òµH¦!¹ï݆_3ÐŒùý)ï,ýBž~¦Ë)ÆÔÄóÑà<>Iårš.§!}ƒpvDƒõ?S>{zjÃÂýwµkÔàlò׬zTO}K#^bÑ#^L|žBæ$Ëbî,ý[gh'CªÉiYí_^=6…¼ãîüŒCvf 3Þ? œŒì…ÂNÿ ¤¬¹ë‰:òëвÃ&†° Y‘x!åe6Šÿ7ˆóy4ó:HF¡Æñ‚÷eøÙ‚fcÃ8]\6B¤uLÕ7 fmê ù ª”‡!;ÑÇ~&ææñàç]4b”BÒk¨B–ÿFŸKüÖšEc-kü¬é[>çÉ—¨ g~‰áõ%Á³·ƒ¿«;ó&RKýÈ+§ç£r{u*ÉY8«»8KP§² ø;™ì+€ˆ6Ç­‹÷!¨m{•mø.ä_¨¾íGÚ)„IûN«E»K2Ø™ôÍc=Pùþ)øþš©ž†f“ô@¶íR9µö Ö~ÆÊ½H Ú¨îMEeûPÌËiºœ†Ü@´ ù÷‰x„¹‚HÙ{—ô¶Íêlò׬zTk}Ë"^bÑ#V‹bß÷Buý8`eì¹¥Û‘ŽßN†T“Ó$Yí_-zl W܇ ÙƬÆq,ʰ‡Pc85¬¢†B´7)ßœ#ìÐþhµ+îP&— Æss"kq×9h'ñßdøY Þ‡¼ø¿9µ)îVŠ6rá³ubnZ€ÝÑrìF¨Ò‡ÄOyÍ1âæQ©ÈZó/ä$ðõb-kü¬é[>çÉ—QšÝ-·/¡cPT¹­~Xåt3´W'^nó©Tt¬îâdízuXY¬Éx¶‚ryHš*= üÍöF¶‘Y«)ÿáÔÞžêÇ/2ÜĕٗP[4ÿ ™øyOÊ;k¿`íg¬ü mhÝ0j Âç!.§mËéiÈ&}K´ªx 2wh4VùkV=ÊSßÚ"^’—-¯¢rÕÊÒ¿uù³æs9m«ý«EM¡ñŠ{ÚnçÍ„¶¸-—߸¯¢QS¯àÓ7æ_ÒOŸõMyg¡Zj™N¥‚Ö‹ò‘ç;h£ÃþȤbàU´d—Ü$³šÊ#‚Vn÷X$¥Øßðÿµ”› €:´k‘à­@3:çÆÜµ #ÞOøŸüž'ÿŠÆRÖøYÓR-ŸóæËG”ËËÚ˜Û®ˆ¥~Xå´•È&1$ùÝê.IV¸œ¶mãÃrÔ!¼‡6|ß%¹+p÷僛¼þíŽØ»‹"t6éàÿRy¼ðûdÿ¸šJž&“§_°ô3yX…VѦ"Å}$šÝ¼:áÎå4]NCB³ŒGQ›}RðÛz6–VÃ"ͪGyó¹yô’<´ßDÊù/ï¬ý[gh'C¬rÚVûW«›Bã»þe´½9n4jã |)ø>:øþ1$p§¥üþ,´Tùå”wá’Gr‡º•µ¨¡½ŸJá„ò¥!Mý“Hp? œ‰ìÆâô¥²ZÉòB#˜ŽFÃ×Åž K¸)!O.)%¿çÍ¿¢©VÖøYÓk¥ÙùÒѱԲ=’l9îÚó¸ò4ˆt›ÑV´áù×Tæwž~ÁÒÏäå>4«7)(Ë©\¸œ¦Ëi¡r4†Æ*îùkV=Ê“ÏV¬z‰•d&ö!RR“Xû·ÎÐN¦‘%§ÕÚ¿Zõد¸/B Í Ê—#BÞAÐBÔ¨Ž¾‡3 ‹Ð¦š8›G£ŽGIg8¢×jŒ;h–dlà‡Õr-ª(w£Í„=R~»ÚU Ú©ÝŸšwJ?*:“RÜ=|*ñlBŠ»¼ù·.²e~ȱ^Ú*kü¬éµR‹\YXA¹IN{Qt¹U«V9}Ø"ñlË:ÜYȳ<ø:ºëbaðl ’‰¤môÔø‚Òz ²Ó~¦ÿŠv×8µ¹GR}bÑ…#cPÿðBŠ»/ ^*m/Lž~ÁÒÏäå/¨¾ME&3P¹Rärš.§½©Üû¶§ïÐxªÉ_³êQž|΋E/±pA¶ Š¥ë í¤UN-í_­zl ‘â>,ð$d#td¨­U¹o.Ý‚ô‹3nE6†g"ÛÃhyq%Qc½ m.Š.3¾J´é"É–È6¸–%¦k+ï£M‡KÑ ËŽh“¼ÀÝNèäƒ?¢‘Ó†è¬ÏG©Ì»5¨°ú#³€CÑÆZÎÍDd7ÙuáŽñd›sd1ŸhóÈ[èØ¨SÜÝ€Î.=-£R±{þ…„g«. >ÐZÖøYÓk%o¾Xy Ýàöïh6`-šA¨Å>rG4óÚ~NDJÎbÊmr[ýÈ#§ßGGwÎE§M¯Ã…÷ÈÞ–ä·h–åtÜçPdyå3€;¡Û­ÏB&·£ÁÍ™(ÞÏé_ÑîŽEäµè¦ÝÇÞ=EyG¶u`ЬÚ!Èœ#íÈàH¦_Jy—§_°ô3yY”¿™È®õŠ7.§érú3t¿ÊKH>ŽL¢^F6ÊÄ"ͪGVwV¬ý UØôÚnÇÑ\L4pµôo¡´Ê©¥ý«UM!RÜ'¥:Ë2<Ïr•6aV^A‰œDºâ~Ñì…2wR8Τ¾“1z¡£ ¯¯ÃÐhì´Kú$Ðÿ@£²1wáÈòPdÎ<¦ùóðCtdÑ”ދɾ·-GJZœð,ÛŸ£3{óp%Ê»ËÐhóIdz^ÂÝh÷öA¨#zU€c(,,Ä–Ec-kü¬éµb 7/w¡F#Lw ºË –Áë H!9.ø{#’“Fa©V9}-çˆfX^BõâÝÍ ´t},ZB]ÜB¹­ôèD”»ÐYÃ!ßEʼnD'"Xük„»­‚¿iùuåmÿjtJÒׂ´ý Ùƒ&Û¿±hV¼YkT?s/²‘—ô‹þ\NÓåôdõÔö½6ì]Omý`,ò׬zdugÅÚZõˆMÑLý,Ê7™Þ„ui!ÅöoÍj'­rš§ý+€øÂaãØàL*—Åd‡µµ/…6‚Ù¨óHV’®Àþ¨òîÑ숴Ý-½íAW®Žã8ŽS'¿€ ´,±‚bn1µ²pKiïJôC3>‘)Åt´ôtS3#Õ@º[zÇqÇép´Ïr¡ñk7­ÈþÈ•ªÆQB»°§!{Ñ7ÑÒÚmý¨ÓÝÒë8Žã8N‡£}Leœ|œbpó,ùÏvÇqÇq:-®¸;Žã8Žã8N' }lÜÇqÇqÇ© WÜÇqÇq§P¾9u2º”bt®åSèüÎ7 éD´©ïìß8ø:§ºå熆lƒ. Ù [ú&:×óWTžkIï-ÀàŒ8]Š.öÈn+ÚØx ÑUµr0>ö}ç:ý«‡O£Mȳ€×›ÇqÇqœ.H¤¸o|Ý÷t“Ö¡À÷Âüa¡l ìøW+ë ó²ŸEW×n—án ܆nÀ.….Ð ±¦÷"4Hˆ³ºŠ;~¨¾5\Ð-b·ï¿ÖV¢ |3ˆßnèRÇqÇq§K)îŸG7Š}‹è’¤ºÄhKtsd­|ÝNöJ~,CçÀ—ÐENYŠû¥”Ïöþ]Û¾ pÑÕÛÖôþ9%Œ}ÐÍ™ñ™yk¸!w ³æ·%ýÆ=+áõ¼ËêðÃqÇqÇéðDŠ{O¤ÀÆo6]Q@ý©ÀÕéõì›4Àç‰J¨@ךޑÀ843_K¸!oÏ£ÁH=Š{& U…1èZù‡ÑÕòñ¸ ¾ŠV † þE9»!S£ Ð*ÈpÇqÇqD´9õNt;äW‘¢9™<‡l¿keëÀßzü¨—±H+×µ¦wš©¿¿Æpã< lål4c‘ÙÏ à,àÊ ì áÖ×'—£©4÷™œ„L—NCùvxã¢ï8Žã8ŽÓ݉fÜŸNF›Gž=6P®­#„qhsæÂ:ü¨‡qhÃæ5”Ï®×’ÞȶýAªÏÎg…g2»ÙX\Å¿zÙX œNd¿¿ÙÈ x$xöxð‰ó.p9Rà_ží¼œVCA«“}ÇqÇqœîN¤¸E3±÷¢Íš£ÙãÐ,s- Þ§>å¿V† Åü1à‰wµ¤wbàç=u„giÌ}£÷-ÐJB|“ñ#±wáÿ-ÀîÈ f#dê?]g3àÊM˜æãŠ»ã8Žã8Nƒˆ÷9À¤¸†ÊØ"àj´ÁòŽCèCíJ= @¦!K‘´‘¯%½»¡Ùçù)ï¬áÆ •è¾m¸)ŠTn`]‰VCÆž€0×¢Ç 4“~.ÚRî[÷þ%¿;Žã8Žã8…)BW4_ ¾®#„e”+†íAdÂÑ8)¨Iò¦·Sþk²W,áÆY7ø»´MWŰ­*Äé$`yìÙtànàºØ³a‰ß•’> ñ¼½ËÙqÇq§mN}6ߨ8:ø^ÏLê"¤à%•ÆFÑ8|ƒÊÓ\Bò¦÷ Hɽ»Îpã Gƒ€× n«*ÿYùüwtRL|vbì]H?*“Rü{™ØÄÙ²z4ÇqÇqœÚÕM1™E|„n=è \Lù¬l>öDGÖ{›æŽHÙl¬£SPz)ÊÇÓÐͤ½ÐåOág:1$OzO@Ç!þ4#ny ™‰÷›³œƒ•(Ÿ#Å{ý ¾áŠÂ?ƒ÷Ÿ@iV¡ÛbCw›SÍû‡èâ¬/!….Q¾ƒÌj–¢rØ™ØôB«ï&ÇqÇqçÿh!n,²°:åd:êïê?æZ´1òÒ:ý¹)¤InDÇü)÷iœD¹}º5½c‘r{eVyÂ)¸·×ÓöÖ<|˜6•¶ÿAùìùöÁû1H)ÿ ðÊWG¡YöÞèÈÊ;€óRÒ1ÝÖº>23z8«Yï ÍqÇqÇ)£\qo{ …q&ÙG#v7¦ [Z÷Á7u:Žã8Žã8UéQÝIüNòÿÚ%´ÎÁ~ÀM¸Òî8Žã8Žã˜hÅý#à|¶=¤xøy³#â8Žã8ŽãtÚÇTÆqÇqÇqœºhŸwÇqÇqÇqêÂwÇqÇqÇé¸âî8Žã8Žã8€^ÿ÷ßc2\Í@çœ×ÉÀ@àì”w“Ñe>›á<…ÎM#ántFøFè|ò{Ðñ%ܵ¢‹NAçw.CÑìˆ8Mc ’ÿ;êôgtÀVÀ¿ow¿¢²¾u6>6ËW»oÀê®^F¢¶wjÿîA÷IÔº™ßê_‘î!/ÖöÞêÎÚÏtººœ†ô®6G}׃5†kug•ƒfÔ£<îEGÕ#:z;R”<·Atsê2$Àó€Ï¢›Nÿ+øþ2õmaÝøð-*?ÜøðwTyžF ñtà7ÀšÀÝŽÀ7Ñž?– †*<¡%·h°{àGwat™Rò²'§ûpºÅ¶^ÅýÀz¨Q¹µû£²!êlŒ@·W»á×ê® v¶pºümºù/ ô¯hwEË‹µ½·º³ö3‰®,§q¾ˆ”é¾À}è6ï¼áZÝYåJŽÚ IDAT Yõ¨‘ùl¥#꽌S„<(U|î£Ä‰)ÏkýœL‰+2ÞH‰»)Ñ;öl%æQb›Ø³Ë)ñ3J´ÄžF‰{)Ñšâï°Àm L‡üÓÑ?§SâGø3<åÙY”¸Ÿƒ;@:ëù|µ ii¬Å]=Ÿ½ƒ0FÅž…íÚz ô¯hwEË‹µ½·º³ö3éÓ•å4ü ¦Ä픘ø?¹Æp­î¬rЬzÔ¨|î쟎ÞN-ÏU>·qïLîÍxß-Ä— V¤¸ÛŽK±g¿Ÿâþ àyйôiZмø]ðÿF)î¶.ÜÝ…–?>Ÿp3;x¿p3š¡ºÍšÔʼØçÜ”÷ÃwG·£‘ÞTàVt–ü˜˜ÛaÀ©ÈÔhnàæT4›–dàA.ö žpgÍ?ÐJÉ®hù·^,å‘'~ÕÒ›'Ÿ­áîÊa"ðàn4S´YÂÝÜ ìéÀXÊeb`JZª‘¶ä¾ Ûšò®¨r³Ö×' Ža4J[œmPôJëÓÀa)aZó/d´7áà*i©†µ<¬ñ³¦lùœ'_z"þ[À!ÀZàô„› <ˆLÛö}jUP’Œ üJSÒŠ*7°Õ«œNNžNCåwxJ˜Vwqþ3ˆëH1z4xÞ É_ÖgPÌQC’›–Ø÷p°RÎGòÆi`Ïû2–Ç¿F¸K#M^¬romï­î¬ýŒ…eÈ4gjâùÆhpŸ¤r9M—SB5 åMEË©UšUê©oiäÑK,zÄ‹À‰ÏSÀ;A!–zÞ•ÚI(Vž«wÜŸq¨a]˜ñþiàd´i5ìôŸ@JÀÚ˜»7Ð.Îǃ¿2ü^€fE♕—Ù(þß ÌçÑÌë4"a…Çÿ Þ<–ág š ãt p=ÚXx q|+ø»ºŠ»ß Jy²_{ ø3𙘛ǃOœwш}4R Aö«¯¡ Y ü|.ñ[kþµ<¬ñ³¦lùœ'_z F0¥ÿ5Âë#›^€·ƒ¿«ߢXÆ;Ó>›¤,õ#¯œžÊíÔ©LNüÖê.ÎÔ)…,þN&{Æ à´:°.Rn‡×!¥ê¬Ø»¡ød»½+R/Iømõ¯hwI²äÅ*÷ÖöÞêÎÚÏX¹)AÕ½©¨lйs9M—Óžh`~ÊM2âP´œZå Yõ¨Öú–E½Ä¢G¬¦Üf{/T×VÆž[êùŽtv²hy®Bã÷!h¶1«q‹"þj ¡ u!ʈPˆîD;q÷ ÜAJùGmø½4‡Z÷ ÀŸ(M.AçæDÍâ ®sÐI þ‘ág)xòzàÿæÔ¦¸[ +Ö ¢YØ•À:17-hSïnhY«ìÝàØÿ¡9F|‰ú1*Ykþ…¼‚:üz±–‡5~Öô‚-ŸóäK‰¨ƒÍn€–Û—Ðx† Žî1Ôð¦QT¹­~Xåt3àÊËm>•ŠŽÕ]œ2ž?ƒ:¬,Ò6B®A²—‡RÂÍÃhâ·€ÞÀ‘d¯¦Xük„;h[^¬romï­î¬ýŒ•?¡Cvn ž}.ö<Äå4]N÷Fæ 7·~Þp-îòÊA³êQžúÖyô’¼lø{•«V–zÞ•ÚÉFÉsWÜûÐv£8‡hF Œø"àj´\žŽq;j´ŽŽE£±+PÁ/%°í[cÜ{ ¥–éT*h½(y¾ƒŽ¼Ü™T¬¼ \„–5㬦rywévERŠý ÿ_Kùõ¨!»u¼+Ќι1w-èÈ·ä Éïyò¯h,åaŸ5½!Õò9o¾|D¹¼¬¹m4Pž-EÊX-G^,õÃ*§­Tžd•ünu—$«\N¶#”çár”Çï3ƒgbï’ܸ{òÁM^ÿŠvGì]–¼ä‘{k{ougíg¬¬B«hS‘â>Ín^pçrZ)§ƒ‘©Ê%¨Ü{õÑ}‚ÿþ»h9µÊA³êQÞ|®F½$­è4§?¡à8ÖzÞUÚÉFÈsßõ/£íÍq£ÑŒA¼^ ¾Ž=[ƒì£®B&o¡Í€=(ŸŒ.=d)öÕX‹Úû©N(_ÙÔ?Äé“ÀñÀ™Èn,N_Ê TÞ­1žE2†¯‹=–pSB‚—\ÚI~Ï›ES­<¬ñ³¦×J³óÅJ´$ßÍZ´W¼,õ#œ&Mé’í‘Õ]’¬•¾Û‹~Tt&¥¸{øTâÙ„wyóo]dËüÍA[åaŸ5½Vj‘+ +(7É©•žè†‡áH «6¨,ºÜªÕ«œ¾l‘x¶eî,äYž|޲0x6ÉDÒ6zê$Ai=Ùç>SƒE»³ÊK^¹·¶÷ÕÜåíg,üÕ·©Èdæ*WŠ\N+åtÚ$gs´jr5ÑæÙ<áZÝYå Yõ(O>çÅ¢—X8 Ž ÛÅRÏ»J;Ùy®BØÜj`»ÀÃQ||_LíKä"ûÿ’}«Û ´|øê¤F£¦‹‰–6B²Ê”ÙÈ®ï»dϸÏDbµ;JãÔLâ7åÓß w;¡Ì½‘3ˆñ :¶+d;àè´e(ÝÇ¢Qè%ä¯HƒÐRÍ@tÄS Ù› DÑêÀÍ—€[P'²;*‹¿¢üG”G› Az•Ý®ÁoûéËp EG²2 Í.õ¥ü"kþ… G£øÔw‰µ<¬ñ³¤7O>[Ãý$°-Ú\²!²™½øg"Ý %ß%hS`Ö€¹Çi¼ ï7}–¡¶!NQåf­V9}™+,EíØÈt¡årjuªo{&‰óº94ëß8ü**¯IHÙÝÉé”ïwÙ 5øç¡ÏÏ£Žñ‹¨#^Ó¿¢ÝYåÅ*÷Öö>O¿`égò°Éá4Ô^…Ê7ŽËi¥œ~„Ìw⟾AÞÜ‚Ú˼áZÝMšUò¤Ã‚µ´è vùd4“þrð›ð³œ¨}¶Ôó®ÒN6Bž«͸OD#“íˆÎ•œlújáTÀ“H¿‰ë6¤`ì…–oV!Û«3)/¸Ð’ägƒX¿Œ–k²f÷z¡£ ¯¯1Þ! ÑÈr6ÊŸ~¨`'ÚÑÈòPdÎ<¦ ôðCT¡† ô^LmWƒü{âÙ Áߟ£3{óp%Ê»ËPeÙž—p÷Ú½}è=Î?†òÎc!¶ü+kyXãgM¯k¸y¹ ª¦»ÝeW1Ù*ø{HÊ»“hì­z–úa•ÓÇÑ€â@Ô ¿„êE2]VwE³)½Ç¢¥ÖU¨±ÛJo€:˻Й¿!ßE¶Ó'L`ñ¯î¬ò²›Ü[Û{«;k?“—{QGü.åtˆËiºœnwV9hV=²º³bí­zĦh¦~åǃLoÂ<\H±ý[Go'‹L‡ø‚QãØàL”\ÈÔ€ïCíK¡`6j4’•¤+°?ª¼{4;"íDwKo{Еë‡ã8ŽãÔIã/`ø-iq‹©•ý€›èXJ{W¢šñ™ˆNu˜ŽLInjf¤HwK¯ã8Žã8Žö8PNKÜ}(}Ñ´¢³<]©j%dÏ< ÙÁ½‰–ÖnlëG˜î–^ÇqÇq:íc*ãäホg©o ã8Žã8ŽÓ©pÅÝqÇqÇq:ícãî8Žã8Žã8N]¸âî8Žã8Žã8€rÅ}$ð}àwèlÉ#ÐÙ³Ep"ðÍ‚üj‹>èLÒ+€{€yèœß4,éÝ8mB¼ø):M¤­m½=йœóÐe IZÑY£ãÛNŠ‰Ë‚pÂO3ùt‡áMއã8Žã8N$RÜ KN† `n@ç)Y@(›¢[¤~Z€_ÕX«½Šò+n“XÓ; )þ·¡›ŸC þ mø½'ºÝ2‹¥À­?õòMt–øÏ ðËqÇqÇé°DóÆ»룙ñW‚g­hvù¿ÕÊ—¿Åüm$ËÐyñ%táÓvî¬é½”ò뢇®³Ý]qýnÂßÁèvÍŸÑö çtÖü¶¤ß¸g%Œg-×Ú;Žã8Žã8†hÆ}`1åÊõ€žd+¿úSÑÕÐíA Û99ÖôÆ•öè<žÖ”ws€?/V ÿ àyÚ÷Rª è î{€ÛÓÑ@#Î0àT´1­ œ ¬—âßnè:ä¹h5"Ë$ÉqÇqÇ©›Hqß)² ["[bßGÔÂÖOÕáG#¨'½cÑM°I¥~<0 ¸Æ‡'탰ÍXà"ﳿ=pa"ü¡À”†B>øN¿ ÀIè<ùÓ Ñዾã8Žã8Nw'2•Y)uC€ë€G‘‚¾«•qèæÔ…uøÑjMï8`g¤ØþoìyOà¸À¯w±Ý»Ø‡òAD£ØX‰fÙ? ž­D6òŸ ž=|â¼ \Žø—ƒgû¯ç£ŽGÐfߴ͸Žã8Žã8NÝTž²)´q›éz®h¼¬­ÃF’'½CÐ 3¿H¼Ûhssް—Æüm´â¾Zõø0öì‘Ø»ðÿ`wd³2u ‰›Õl<@y^ÍÇwÇqÇqœ)îËÑI+ï¡MßÃwµÒX]ÇïEÞô@¦&K‘òWX_Ef%½‚Oßà]Ÿàÿ¸Â>ë›ò®hR¹u%Z {vp0p- ¬@3éç¢UˆìûßKø—üî8Žã8ŽãF¤¸/¦Ò¶{Dì]­,£\1ì(äIodÒ³2ñþcèÊÓRÂ9 xV“$4ÉYšò®h–ƒÏú# ˆT¦£óꯋ=–ø] )éÏ;b9;Žã8Žãt"Å}>ðutæúÂàÙdâ’´yÎÃ"¤à ¢cYhMoOàt©Ð‘TÿJãQ‰g›G£‹˜͈Ãð ¼×rÆ=PùÏÊç¿£ ’â³ÿcïBúQ9˜”âß ÈÄ&ΖÖÈ:Žã8Žã8y ÕRxM> )§;_îî¯#„Ñ…D%ýhÅF°#0ò²šAŠR*ÞÖôLCÇ#öBŠ~øY|€ÌMþ‘øôE—NÝBö9í3‘âžÇ.>‹•(Ÿ#Å{}tÆ{hÒóÏàý'Ð ûx4Yü(æn4€y•Ý®À—‚ôÌ%*ÃwYÍR”¿; ›^À¯Ñ¾ÇqÇq§0Zˆ[kŽE'§¬Bç}_Mùé)µp-ÚyiþX¹)®InDÇ †XÒûc4Hã$4sŸÆ6(½g¦¼ï…ÎH¿žÊ®µòy`6ÚTÚüå³çÛïÇ ¥ü/À(_E€V&½Ñ‘•wçQ™ÞÀ(¯_A·Í¶× ÍqÇq§›P®¸7Š=Â8“ú]…)H©ßßÔé8Žã8ŽãT¥Gu'ð[t:I{ÞÚÑÙ¸ WÚÇqÇqí£¸\€Ï¶‡´?ovDÇqÇqœÎBû˜Ê8Žã8Žã8ŽSí3ãî8Žã8Žã8N]¸âî8Žã8Žã8WÜÇqÇq§ÝœúEà˜ W3Ð9çõp"08;åÝdt™Ï&A8O¡KÞH¸Û¾:ŸütFüG w­è¤SÐ9äÝ…ËÐÅGg4;"NÓ˜‚äÿŽüÙ…ÎöÕ·ÕuúÝl>6ËW»oÀê®^F¢¶7~ŸÄ5Ô¾™ßê_‘î¶A÷Flüð&pð+*ÛçZ©·<ŠÎçFÓÕå4¤pºm<íÞ“¢åÙªoäMo{§£QtT=¢ídt±ä'€ß÷ÞJøemÿnA—d¦q)ºÛÇ@¤¸?L¤TŸ <Ü|ÿÐæY&›¢8My·ðm$ä?2, {GàTà÷¨rl†.ÿY Zœ¥(޾VgÜ;o¢c7îËgP‡T¯â>ÝŽûtCðfÀAÁß´Á·S€‹ÑmÆ žú—4п¢ÝÍB3·¡›Ç£öwðÒQ4Eçsw£‘ù·'°aáZÝYõZÒÛžéh$QhV;¹º‡èYà$?iXÛ¿‹òg'à d_æ™A©âs%NLy^ëçdJ\‘ñîDJÜM‰Þ±gÓ(1ÛÄž]N‰ŸQ¢%öì0JÜK‰Ö‡~l[`:ü㟎þ9?jßG¡:•Vß:ÓçÓA:†䮞ÏÞA£bÏÂvm½úW´»´<:‹÷Sbp;—[{äs{|º²œ†ŸÁ”¸3ÿ'×®ÕUßÈ›ÞöNGwû4«l!Ò9òšâ_=íßÈÖ3>·qïLîÍxß-MÄ—'ÒF{›O£h‡<ü~|Šû7€ç)æÒ§QhTv'ð»àÿRÜm \¸» -»|>áfvð~/àf´Ê}‹p—ÆX${ñNÍ*÷Öò°ÊA=éH² x Ê“aŒ¡|’Êå4]NA Õ$”7Y-§V}#¼4#Vòè%=âEd¢ÿ<…Ì*—ÅÜYêygh'ë!­ýK2í»?Ÿ×yÇÝù‡î…ïŸNFv³a§ÿR֯ܽFpq>üá÷4+/¤¼ÌFñÿ‘`>f^§ Ã(Ô8þOðà± ?[Ðll§K€ëцÀœD%ªmü ª”‡!{ªÇ"ö™˜›ÇƒOœwш}4R ö^C²ø7ø\â·Öü+kyXãgM/Øò9O¾ô@`8;ðKÔ¯, ž½ü]ø›Ü•ŠŽÕ]œ2ž?ƒ:¬,Öd<[A¹<$—h~V^zG’Ýà[ük„;P{{6ª¿H¼³Ê½µ<¬rPK:ÚâOh#ãÎè¤%P[>Ï¿î&§{#s†›Û?o¸wV}Ãê_³Òa%^’—-¯¢Ò¢ÂRÏ;S;™‡¶Ú¿8·÷ä¢ñŠ{ÚÁÍ!š3lp5Z.OǸ5ZGÇ¢ÑØ¨à—’NØ€ö­1î=ÐRËt*´^”<ßAG^îL*Ö^E»ˆŸMüv5•f?+H·{,’RìoøÿZÊ—¨@ ÙµHðV scîZБGï'üO~Ï“Ec)kü¬é ©–Ïyóå#ÊåemÌm£ —MEyz²“LÊt‘Xê‡UN[‰lóC’ß­î’du€Ëɶu…òŽa9½Ì ž ˆ½KrWàîÊ7yý+Ú±w¡6ùlÊÓš§¾YËÃ"µ¤£«Ð*ÚT¤¸D³›W׿î&§ƒ‘©Ê%¨Ü{õÑ}‚ÿþ»h9µêÿš™+yô’<´ßDÊù/ï¬õ¼3´“yi«ýK²Z¥Éyš ´G׿Œ¶7ÇF'ð¥àûèØ³5È>ê*d"ðÚ ØƒòÙÈ8á’G–b_µ¨¡½ŸJá„ò¥!Mý“Aœ> œ‰ìÆâô¥¼Rƒ*»5ƳH¦£Ñðu±gÃnJHà“KJÉïyó¯hª•‡5~ÖôZiv¾ÔJ¨Ä¡±Š»¥~ä‘Ó¤)]²=²ºK’µÒ—g x1•6•#bïâôFïßPÛ8‹òôçñ¯hw eå|d3z$•rœ·¾YÊÃ"a\­é°ršÕŠ”åTvÂ.§•rú1¤@ž–æYÈôèË9õº³êÿš™Ž)áù ûÀ9h¹|s´ùa2š…ÏšqŸ‰ Âj–Æ+h€0!ˆß”O~/ Üí„v2÷FJÌxt"Æ3èØ®íÐ-\[£ÈHdú³-¹å­HƒÐ’Ý@tÄS Ù› DÑêÀ͗Э]K‘Íåë¨L¶B)Â<Ú ð#¨ìv ~Û7HGX†KÐlÂp$+ÓÐìR_4Š ÍH¬ù2âGPß%BÖò°ÆÏ’Þ<ùl ÷“À¶hsQȆh™íNàŸ‰to€–|— Å;kÀ\ëQ7ul»£q ÿ¢RN‹*7ký°Êé;È\a)jÇv@¦ ½(—S«;P}Û3NœÐ%&YŸøÆáWQyMBýŽHNï¤|¿ËN¨£9­|<:Æ/¢ÆuNÿŠvw<ª7y¶iì³,Ȱ˽µ<¬r`MGÖáOCýçU¨|㸜VÊéGÈ|'þéäÍ-¨½Ìnžòµèÿš Ö~ТG€Úå“ÑLúËÁoÂÏr¢öÙRÏ;C;IðnLw›¡z7iÏ¡‚nmÿBN@“Î?¥&¢÷‰hd²Ñy–3M_-¼‚ xé¶<·!c/´|³ -ßIyÁ}€2ë³A¬_FË5Y³{½ÐQ××ï…hd9åO?TA'ÚÑÈòPdÎ<¦õðCT¡† ô^LmWƒü{âÙ Áߟ£3{óp%Ê»ËPeÙž—p÷Ú½}è=Î?†òÎc!¶ü+kyXãgM¯k¸y¹ ¶¦»Ýe×nï´”÷™ no£AÇõw…}–úa•ÓÇÑ€â@Ô ¿„êÅ!5º+š¨Ñ?-¹¯B~ÜVzÔYÞ…Îù.²>‘èD‹p·Uð7-¿N"jûb“{kyXåÀšŽ¼Ü‹€w)WÔòƯ»Éi‘áæqgÕ7Š–—¢ÓaÅÚõlã IDATZõˆMÑLý,Ê7™Þ„y¸bû·fµ“ %{ýØ÷ã‚¿7¢ú öö4ûm ČǨg’}4NÑLAŠý>Tß¼ÓžÌFF²’töG•wfG¤ènémºrýpÇqœ:iüL¿E#œ"n1µ²pKiïJôC3>ÑòÑtdJrS3#Õ@º[zÇqÇép´ÇrZâ¾€ìË Š¦åéJUã(!{æiÈîM´´vc[?êÄt·ô:Žã8ŽÓáhS'§Ü:fÒéžLAòG~ö®B·Ÿ÷QâÄ”çµ~N¦Äï.§ÄÏ(Ñ{v%î¥DkìÙð”ßžE‰û)18åÝ0J̣ͦÃ?þéèŸÓ)ñ£ýL‰Û)1Õ§É õ~>¤%­M©Å]=Ÿ½ƒ0FÅž…íßz ô¯hwiŸ£‚ß¶60Ü¢¾#”Ñ¡)q9‘wS¢wìÙ´Àý6 ,_—Ó¶?ÕÚ—öÓ´üs9íXŸ¢åÏšÏVwÖø}…¿«??oãÞ˜ Ü›ñ~Sàé :!=ѬzHÚàt ekÊ»7€ç)æÒ§Qhu'ð»àÿRÜm \¸» -“|>áfvð~/àf´œr 0¢ŽøÍ‹}ÎMy?$—yük„»4ÂËåz60ܰ+«FO´d_¶®uVqZ!Þ'åÝ)oƒ]NÓå4¤ZûÒ9µä_WÓk?8¶õ©ò¼ŒO2óôûÕ(Zþ¬ùlu—·ü,‘ ^Žò*WÜ·FËOe¼ïE¥z˜IWñ{,ÊÄ,»¾'íQÖÊHàÀúÀ…hÙd0ð]Ê;¤Vd²³ 8 Ù‡ÝGz£Ð ÑqÈæiMàwÏ·ö >ÏUq×)œãÐ2η‘-Û¬˜›¡A|®N@ Ûh*Í‘¶AÐs(­O‡¥„iÍ¿ ÐÞ„ƒ«¤¥Öò°ÆÏš^°åsž|鉸o‡kÓn@2ð ð2‘LìKí ÿx`’…jUn`«V9œ„–¨OCåwxJ˜Vwqþ3ˆëH1z4xÞ É_ÖgPÌQƒ’›–Ø÷p°RÎGòÆi`Ïû2–Ç¿F¸ é¤oG4øú32mlt¸Õ¸3ð竨 F úøÙ}SË€GР<ÎÆhpŸ¤r9M—S°µ/EË‹5ÿº‚œB>½Ä¢G¼ˆL™ãŸ§™Ü²˜;KÿÖLù³æ³Õ]9èƒÌ¸¯E}ú  _zc&ï¸;?ãb¾0ãýTŽ6>üPÅßi{sÂ4+ÏÔ¼ÌFñÿ‘`>f^§ Ã(Ô8þOðà± ?[Ðll§K€ëѯûkˆc¸Á%¹ ,ÉoÀÌâ÷gdòxð‰ó.ŽFJ!À~Àk¨B–ÿFŸKüÖšEc-kü¬é[>çÉ—¨ Gó¿DðúÀ’àÙÛÁßU¿i›žòÐ)ÎסòߤNÿò`©yåô|Tn Nerâ·Vwq– N)dAðw2Ù3VmNZ ¬† ¼~•mø.ä_¨¾íGÚ)„IûI«E» ¹uœ Yé ïn5žNFööáàò 4Ø\[ƒ÷"%hC¢º7•íC1w.§érjm_Š–kþu9Í£—XôˆÕÀ¢Ø÷½.v°2öÜÒ¿íHóäÏšÏVwyä êßþ|­ÔMC+"¯¸A³YBw'Ú‰»'j Ç eû£6~3eäcH²Xs_«â>ep|4¹Uþ͉¬ÅH¨ç “nþü#ÃÏRð>äõÀÿÍ©Mq·V¬D³°+ÑÆ™`w´œ¸ªô!ƒcÿ‡æñå¿Ç¨Td­ùò Õ‹µ<¬ñ³¦lùœ'_JD›øíj*̓Vn÷X$¥Øßðÿµ”› €óZ¤˜®@3çÆÜµ #9ßOøŸüž'ÿŠÆRÖøYÓR-ŸóæËG”ËËÚ˜ÛF0- ^„Ñ‹¨õ þoäé–úa•ÓV"[ëäw«»$YàrÚÞo³–£6í=`fðl@ì]’»w/P>¸Éë_ÑîBÂeöGQ<)ˆó³±ß4"ÜjÌ!šyóp52ËÊ{ Ó*´Š6)î#ÑìæÕ w.§•rš§})R^òä_W‘Ó=€OÇg"»±8}©T~ZÑ’a³™ŽFÃ×Åž K¸)!M.%¿çÍ¿¢©VÖøYÓk¥ÙùR¡þ´”wg!Ó€/70|KýÈ#§I“»d{du—$kE0Ïðb*m GÄÞÅé:ß¿!3‹Y”§?E»K#TâÇ) ín£ÑÌj\x)ø>ºÿ@v³ßBöŸCôü„—ÓJ9ÍÓ¾)/yò¯+É©U/±Ò‚ÌÄ>D€$Öþ­™í¤5Ÿ­îòÆoÊ•÷A”ïªBã÷E¨¢ ¢|ù ɲØûýQ"â—'õÎAJý‘Ø”ÜáHˆ^ËãrCË%¯a·1[‹â~7ÚLØ#å·; Ýô Úý©~rG{ÐÊΤwÏŸJ<›â.oþ­‹l™ß#²«—¶ÊÃ?kz­Ô"WVPn’S ‹Ð&¶8›£U±«‰6·Å)ºÜªÕ«œ¾l‘x¶eî,äYž|®µ0x6ÉDÒ6zRzAi=Ù[>SƒE»ëMå^£°~¼{Vt¸VÞAˆ¢Nxtð½ÚŒuAõm*2™y€Ê•"—ÓJ9ÍÓ¾-/ÖüëJrbÑK,„GmªgéßšÙNZóÙê.¯L ºhl Ò_Hq—A¨k`» àQ||_Lùˆ#"ûõ¿’~úËF(£×C•w6²7û.å3îÇ#ãýÐpcÓØgY×$3QÆYíèÒx $& Fyʧ¿îvB;™{#%f<:ãtäOÈvèö´­ƒxD&B+ÑÒaÞŠ4-± DG<•½Ù@$\«7_nAÈî¨,þŠ”¢qDy´ ¸GPÙíü¶oް — Y‘áHV¦¡Ù¥¾È¾,4#±æ_Èp4ŠA}—YËÃ?Kzóä³5ÜOÛ¢ÍE!"›Ù;&Ò½ZÂ[‚©jæ4>BËëñO_$ ·éIRT¹Yë‡UNßAæ KQ;¶2]èE¹œZÝêÛž‰pâ|€.1ÉúÄ7¿ŠÊkšŒØÉé”ïwÙ u ç¡™ìçQÇøEÔ¯Îé_Ñî®GÐPÔ±íŽ6.þ‹¨ÜŠ—àÝTÇ7Cå7õnñ žHž>BõñhÔ>„§äe ’Ãi¨ÿ¼ •o—ÓJ9ÍÓ¾-/Öüë*rjí-z¨]>ͤ¿ü&ü,'ªç–þ­™í$ØóÙâοñ脺O YÛõo«Ñ^ £þ͸OD#“íˆÎŸœA¥MŽ•WPO¢rTxCѹ–½·gP9k·Uð÷?NJñ»: òúšb±,g£ü釚ljvçC4²<ÙC‡3iG]}üU¨!hùb*gkþÿöÎ;Lª"ëÃï 0D2ˆˆ%)*Ñ„»F0­úéšÖìš1ç€âª¬Š9®sNdD$P2223ß¿{éÛÝ·§ëv÷Ì0pÞç™§§ï­®[éVª:uŽ §$\{Æû| ÙìÂ}¨ìîBs2Òïº>!Ü$tzû4Ñ›ŠìŒŸMüà1·òË5®õáš>×üºâúܨŒEV™ü|ç!_™&•…ËûáÚN'  Åq¨CŸÞ‹Ä~Ä5\®Y%ÎAªk‘ðÔ•nŠ˱È6°Ï­HwúBb \â+po#þ½Q[þMRŸ$¾Þrý\™Å&ïçzŸÏ¢vò¸ý²‚q…ß·ÞÿÙX`z Ø>¡µvÞNsùÜ(á\ËoSi§®ã «±-Z©F¼ycêŸÆ¹äv|Ëuûs-g×pQÚA²÷O/ÍÓÑyÍò_p ü8Uàa¤6ݘkú  Àd¿Å”KNB ñ%ÙŠ^Þƒ+;!Äæ–ߊ`S~? Ã0 #KÊßÀhF’ /¦® üKhß”¨…V,º£m¿~H•ä•™¨rds˯a†aå8´p#çÄ¥Ùò4¡ªü(EúÌû#=¸ÅhkíÙ²~T…ÙÜòk†aÆFGŨÊѸØ!Ì·dwÐ0 Ã0 èR˜àn†a†aU€ŠÑq7 Ã0 Ã0 #+Lp7 Ã0 Ã0Œ*@øáÔ|äLb;dRñ“ÐPѸêžp} á:݉6È]ý„œ„1xÙûgàd¾:l8xx{š}‹6ÈìÏÈfñ³ÄóY9yÒk„œ=¼N¼óÐáÙg¼üLÆ0 Ã0 Ã0Ò.¸AÞsŶHð>¹Œ07ïýt^†án ®õúï¤išH¼üް'j?G*6>íà ðŽïDª6©˜ ìŽ& ÙP ¸MPN®V"u Ÿ@1ªÛ i»‰dê ‡sc½ßÝLüDÅ0 Ã0 èPbbo5$¨=ÔDråå´:ì97ÅýeèðæL4èTk×g.H>Òmÿ äéÒ¹lÿ ¹ÿ 1}õw ¤>Ð ø¸¨„ø›c€u!qÎDj<­€ùiÒW¯ßyÏû &½a&xAþîFüëyhõÞOÓÀ“è ®ËÈ0 Ã0 ÃÈ91Áýpt¨óù?¡1Zý-Iqÿ ïÏçC/làabzé®á‚t÷žÿ¶C‡#÷éa.EVev†g·îç#›SÑaV¼Ï{Ñ„ QUbúñÉNp_ã}®&6AYÔ„É[¢UuŸÄ´¥À÷ï ÑÁÜí0ÁÝ0 Ã0 £’ªLCàxt³:ø|=ò¢é”'R@²ÙÄt|è}¶Ï2Ü`´ªüUŠû aü$D'µÙï€oЪÿH¤›Þ)p5°€˜ÐÒa/Azöaø«ðÙ”/ÄÒ\ø¿„xÕ–c€sÐîÃÅH—ýjï^¢ Lñ&1AùKÔ‡7 Ã0 Ã0* ­¸7CÂú¥!!®D¶ËÌð +ÙÅ(øš÷©Vé]Â{/–O2áX YÐY“"\"ßyŸí€o½ÿ’,Øúºë©&[xŸËSÜÏ%ýЪÿk-S„­éýÕ{ ‰YÚ1 Ã0 Ã0* îóe’ Ûÿ@+Í™2­j×GB|X Wwû"aûû Âùô÷~¦¢Ze¾ Yf9“ÔBi ’uÞ»yŸÁÕõ‰h×¢ð‹wmG4¹˜›"î­¼ô/Hq?—Ô"y‚УŒð{ ëB |Ô!w–† Ã0 Ã0ŒÈHp_‹ìœñÕ'~B*™â{Ýžp••ûiÄl¼ï…,·<ü–A8ŸAÀlï/Œsà:èèýùL!&È?†„òÙÈñSG¤‚ó#ðeà7c€Ãƒ¨'Àÿä‘õƒiØÁ‹ÇÅ~}¶|ì&2K€ýî}ÅhÒV©ÍœìýæÃá Ã0 Ã0Œr'1Å왃„Ó„ îã‘gÓHØ]ܼa8YǶÀ}e¤kGïóÄ{Òú6š$ôF«Ö?£É“Äï,CVyNþí]›ä¥1q§Tò»{ñT÷yϼ •ßddñ&Ì"ÏŸèPí©èàì·ÈÜdX> Ã0 Ã0Œ !Ôعã`tò0ÂM-nŽô.Gæ —¥ [‘œ„ìÔPÙ 1 Ã0 Ã0‚${N-Þ@VI²ñº©q4ð?6.¡Ý0 Ã0 ÃØh©Á}=Òý¶ÕvQˆô㟪섆a†aU…ŠQ•1 Ã0 Ã0 #+*fÅÝ0 Ã0 Ã0Œ¬0ÁÝ0 Ã0 Ã0ª&¸†a†aF fÇýPàì¡!'MÙp!Pžp}gàdW½rX4ÙgO´^ 8yLm„<—¾<Ó´A[F¶ØŸE΄‚Ïsµ9p°™£46Oú ö?&Ëx¢÷'‘§€ÿfwe³:T? X˜ƒpÙÒõÑPü6ð ™úw/—áŽEå4Ð!}½€c€m¼ø¦ 6µ(Ãô%’®ÞòQÈ‹øåÀ'i® 6õvê“®>rÝž]Ú_r´Ø9g,ŽB q‘_^†e¼œA>Ê‹Uލ¬~Ò§p Ð IØÁ¶¥½”ALpÿ’˜P=9zÅû¾.Z¤Il‹:ê“Cî Cý+Àï@Wà4$xß—Ü€ü—€¹@’y[ôB|¬Ú£—¥=É“†åèE8 øgôlUY#óœÆæKo4 e+¸û܈wùÌËQ¼†¨‹œ ­BeÝõ§µ€;Ë1¾\‡seWàZ4à= Ô÷â» |þ˜”ëç4Ï2ŽÍʪ\·S×öWù©ùyvß5Eú\å—[0¤'Пx–åYήlŒrDeõ“>Հˀ¯[Ñâsp’ìÚ^ÒÜ?“\Lî\Ü LG^TA|ÆÞj"©£€?¼ë{£Lž L,ãY„\ËþŽV—'܃lªï’&ÞM‰›Ò1ŒH|Š:7£|Œú ‰õ£…¨o}-z”G|¹çÊ~h‡ôb+[¥hõj´°TÏõiˆ|ÎÌ0ŽÍ‘ʪ\·S×ö·ù§)E&S b®òËç!׎¦/Ÿ•W9Gac”#*«ŸôiŠ„ýqH8Oĵ½¤¡üuÜë ­¡wSÜÛ²›‰„íÂÀµ¾HøÏD¸öU ¹·˜AnœCµA³²×ÑäF`Ëp]€»½pcѶË~ aNòîÿ xmÏÜ lEú>ü]r+ïÞYÀ«ÀHTî/#Õ‡v°-KªÑ8/Ì%h 0‘ÀÓ^î@+'xÏ âZ~ ]šhû7[\ê#JúÒå7J9»>w(ª‡îh…è-´­Û>!Ü8ïÙý€Ä·‰z!y‰BM‡0¹ª7×÷#J;ŒÊœW‹Ïv וk/T×/«—ê)~“Š=€ùÄ/~|„ú4¿óÏC+‚£‰_µë ¼‡Úe”øÊ#œÏÞÄÊðnTVAª!)¸¶ºå¹®õp:ð1ðCaÒQx ^‰\Óçš_p+ç(åR u ×'%hÛ.È1¨ |üH¬MEv۞ϢÁåU¤z–jÀÏU½ÛûáÚN»¡U’KQýòL×pAþÏKëåH0úÆ»^µ¿Tõq´B¨Ýä¾û“•R´ß0¦z^:ß#~ðw‰¯<ÂËÓÐÀy—Ï[0¯{ñÊbkô^|GüXâúÜ(õÖé©>˜â¾++Жyß„ë­Ðx\̲vÞNÁ­>rÝN]ÛŸ+QåŸAhåÿý„ëQÞ7¢È%.rÄÀq SóŠ@8—ñ­*ô“¯ 2ñωÞB¬œ¾&çDOG§Òó™!ü>$+ÿ×G3—_Ñ,¯z nFÂH¢þ3ÄôÇÞñÂ¥b&Z VRTNBù<ŸXÜV^÷'ÖÚ Îñqï>Àøqæ¡ÕX?MwO¢ƒ…‰/² þˆÄCº‰¼†^ÊS^Ýx4ñé3Áû òš±·EB!H iz!K½ø¶öMø­kùå×úpMŸk~Á­œ£”K>êýÕçP'ÜøÍ»ö³÷¹Ö‹7⡘$–¡²›é=¿7ÚFl„VÊ—÷#j;½ÕÛ×hPé•ð[×pA~#¾ÿ™é}ö"õŠèÌ€ˆs 4±j <„ª+÷|~GðèÜÒ@$&êcºÆ—ëp v2©Wv=Bíy¬wm*ðot.ÉŸäMB“¾’ žëZoÕÐDð ÔN¶!;ÞEBPsbï^_T·ŸÂY; o§®õ‘ëvêÚþ\‰*¿€Þ“þh‘%qQ%ÊûæB¹ÄEŽ("þœÓßlw.°&pÝe|Û“¿Ÿ\íýù“?È~l-ƒòÜ£UD—ÆÞ½(ãQÅÉG³«SѬ ïó^$è' v—"]£Ð*äÙh{$ _ï½1™ îÝÐ@œMþ†:Ïíé›õéÈrÎ÷À/)â,õîû,ôâߎÌwWüËoŒþµÚ0yÀAh;vKôÒûÜøêÁí¡ñ$ ²®åç3Õ{¶¸Ö‡kú\ó nå¥\J‰ ð{OÜsÍޟχè]ïTv-€äªÞÀíýpm§íQÚƒõöÉ‚Žk¸ ©Î MCV*ŠS\[M|{HÜzýx­f×@:Á©vS\â+pA!u6ꃃj]Ðù~ë#êf4ø' éžëZo‡£çCÒœ Ÿ"¡l´+ê üë>ÖNÃÛiÔúÈU;ÚþÒU~©=6Fj€©pÍo:¢È%QÙÁ‹wÉ».ã[Uê'+ˆòÜ pkäuÑöÂr$¼'Êj4[]¸6 ­Câó·q¾ñ~sZÍ ;0àw .:ºa䣭–~$ hÕ‰Ÿy.E†"•ŠÚÀO(ï‰i+"Ù$æjÂõsIiàÓÿ¿„x„cPG6 ¦«Q=\—‡L|®Lˆ?ñ{”òË5.õáš>×üú¤+ç¨å²žøöR[‘|ˆ÷ö$ î¹Äåýpm§…ÄÎÂø$~w —HªpeëPûÀU¨\†5á}÷ï%2Ö 7‹øÉMÔør´“šh^x%ñêéÄV€ýr˜<€Ô£|kH.Ïu­·†H5âNôÎT'6&xÿGµ°¶í¢õE‚{k´ºù@B8k§Éí4J}人¶?W¢Ê/ IÜÄ[“ñ‰ZÎéˆ"—D¡¸ çÏ%ÜsߪB?YÁ”ÿ¾‚ô‡Þ Ж^-4ëYf!É«¯“žnæã ñío„þ–G¢ÅWJЋù>É’ó3ÙûËvή@úPAj’që.ñ{ÔòË5éêÃ5}®ùu¥²Ë%Sü“3™l)GÁåýˆÒNë&\Oì·\Ã%’ª¢lÏ'YwuëÀ½ 5Ðà;©Y #>ÿQâËu8?}µ‰Þë©-X‚}ûlï{P/Øå¹®õÖÌK×¥$s%Ru92ä^:ÞC«z-€²ŠdaÌÚir;R¹n§®íÏ•¨òK!:Àÿ"áõ¥œ]q•K\ÉCjbëÐ ×ñ­*ô“Lù îóPRŸømŸjÀUÈÒÆ™¤J'¢Ùw3b+;¢F67®Ɇñ»yŸK g+Ôˆ¤¸ïÂx´½¶w¥½(o¡Ã„ù!¿Ý¦å·ÙY:ȵHžèô 7Ø-áZ·pQËo ¤Ë¼Œ˜®l¶”U®ésͯ+™´+V¯’“)ÕI^õî‹Ò¶‚‘ëzK÷~¸¶ÓYÀö ×vÈ"œ Q¶€¿Î@>1æz×ú rNÔ>õ“'¢¼žôs§e_®Ãùt#攤fî/õ®çlÚz߃+Ç®Ïu©·yèPf퀡•ÖoÈŒ/ÐûÖ©E|H¸sAk§ñí4J}人¶?W\åŸþ¨oMu¶+êû¹Ä…Ðà4R« ¸ŒoU¡Ÿ¬`b‚{KôRøl‰LvÆL…ß#éö„oùœƒ m4ò$Õ1po 1A~ Úª¸ÍŠj ­ÅÅH§Øç1ô’ÌF3±ŽhËéG¤ÓÆÞýl¶>F÷·£C‡ËÑ Ëžèp¬ŸÆžè¤øÇhÅ 9²1ÿ Ée\Œ:©:H-àdtà!ûúõ‰éM Â?1¾šÔê©øŠØá‘%ÈlÔ>!ážA¶ú/CÛRHlÁ½ü||Ûª3ÉNt­×ô¹æ×•¨åâÊlä±ø´ U‚V¢êíÝ::ÿ@ì^^Úž'\¯>WõnïG”vz;2Ý9Yê—E8–‘úX"o ÕÅ«ÐÙHÿw ñ+Õ=‘ì+Qù¿Š&7W òY1¾\‡µµ³Ð‚Οhàü…x++/#]â+¼ëõ:Éâ…×çºÔÛZt(1ˆ¯¦ò±C{Q)B“”ÃÎòÈ0ÖN“Ûi”úÈu;um þ®&±3ÝQ™Í'væÈU~ñ„úèÙ!÷¢äÃ×qÐUŽè‚,}ùgƒæ^相ºŒoU¡ŸŒ‚K{ICLpïNÌ” ÈF¥o§rÉ:‰®ÌñÓƒpÁ}GïóÄ{~³ ½H§£ÓÞ ÙÑ=į^¼„‡Þ¨QýŒ„ˆ'I^å•ÀîÞýl˜‹f–'¡r¬…£ ÄNçClfy2Ò‡öWÃL]ý‰¯œŠ:üo‘ùÀ°|¤ãT$¤ñmŽfâžþ>Tvw¡Nh2ÒL´$2 Þ> DSÑ p6ñ“…¹¸•_®q­×ô¹æ××çFe,šÔúùÎC¾ ¢N^Ç£Npj Ð;ùBisÅåýpm§Ðvîqh…e6z/û%×p¹f5Úº>©¬EƒºÒMQß8Ùö¹ ³ˆà_y„ ²ÿAÞª›¢­êáÄ×Û+hçôoh0]‹ê÷ â­5¸>·²êÍç]ôŽüA¸-ok§áí4—ÏεýÌw6 |?×û|Õ+¸Ë/ è¶ß†å}sÁut•#¶E+õÈ7o R½ñËp.¹ß*«ŸŒ‚K{ICp#¨ü8UÌa$«±T6}Öd¶V^œ„:Ä—dS`(zy®ì„T›[~+‚Mùý0 Ã0Œ”¿&ÐvÃjrã4× üKhß”¨…V|º£­¡~hëé•™¨rds˯a†aFÅŠ[t»²uf‘k ‘Þ» UåG):…½?Ò\Œ¶Öž-ëGU˜Í-¿†a†aT£*c”;„ù–è6g Ã0 Ã0ŒÜ Ã0 Ã0 £ P1:î†a†a†ad… î†a†a†QˆNÝ9dÙÙñ\Œì\¾@²ÑÖÈæf'd×òmdï3¦/D‡ú†gG-dG»/r3¼xx<¦9@èŒìYo_Ôç% aŠçŒ@Ž ZùõBζAå7Ù?]”®l¼˜˜#«L¹ èø¾O–ñeÃ^è°ò0ä Ú0 Ã0 ÃHKLp†æWG¨®È0~äPƧ.rr² _-ÑþZÀY¦f[` _¦ä7 ú%dà¿ ÉÂwmdWû[äùqW¹ õAz"—ÄA‡R®å·+p-ò¤÷0òDv2pšH¬ „]Ž&§!g%Ùpµ—ÁÈ)‡a†a†Q¥ˆ î#ˆ_ý|¹eŒBß@‚Ÿï¶Üws^ˆlU?Jæn`ñ☈7öFÂñ¹„{¨óYìÊ—"ÇP©÷ÏC®x˜°Ø6Ëx}¡ó÷†•ßë(ŸÇ#~k¤fó©ó>Ø•uyÓ©­®DüîÀÍ Ïo£³ +ã ZhpRIºåóÔòK¾a†aƦJjÏ©ÐÆÄC§[ ¡®1ðð ðü{™Ò ✛E ñ^À¯Àu@ $Äߌ„®KýÓ´ä#ÝöO({•R—ßTàßèðí?¼k“ÐÔ’qÍDê9ÁISyq8°­²ûeµéÈï|í]›àýù¸ ð?z׎ s¥Þï[£:2 Ã0 Ã0œ Ü#Ár<ðtŠ_#á5¨3+§ÆÀJR ¯®ä£•ìS‘5¼Ï{‘ ¨â…î(o§ WVùu@ÏZP}$Àߌôò‹Bâ[ˆ·¼÷íÑÊp‚óuàžÿpRƒÙ©:ùÕjÚß6¾ÂwÃ0 Ã0Œˆ$ îu‘ªÄr$|& 㫼0ËСNÿ7þ½L) \hÊj´Ú¾4pmš´Î2îÁhUù«2¤+¿Óß îß›<€²Ž ‰Ó¢kf”êhÔ#ùë´R/pí4á&(«Qù^‡ôø!¦ß¿,!¾Äï†a†aFZâ÷¤ÒP 8 l‰Ì'Y—}ëÀ½LYA¼`˜) I> éëfg³#Pˆì¿Hê]—òk‹ÿ`Zf{ßSéáû*HËSÜÏ%«Ð.@:¨¥'fýÐîÅk-~WŠ„ôº ×sQφa†a›±Ã©Õ€«€­€ó‰™/Lä+$¨o¸Ö ³‰:ÏQ˜‡¼D¡1*‘.x³ÀµQNçfo$¼¦Rµq-¿¥èmð g[ï{ª•è­Pù.ˆ”âp|á?U9lÐW÷»îùÔ"y"Ñ#$¾YHÅ&Èé“i†a†aÄã‹›p°?2ïW æþß àOï?!•ŽH8Ý8YKq±´’ŠuÀ$xgãMsp€—¾•H§ü,´Z|'ñ«å{"!º+ÒÅž¬¥T#Yð¾ÙB$Ås]Ëd™¦5R?Ùø:Dë;¶Jä0/ÝϧxvÖ rnˆï&(_þÀ¯ÞýÎ^Zº¢ÝƒyÈ»«n4aûÕÝ@àïHàG¬—"µšå¨|÷@*6ÕÑîÅÊäÉ0 Ã0 c3 _{ ±a\D¼^wkàd9e-:¬ùñÖS2a4:9"ËxÚ"]òÎÞ÷IÀ=$¯X?×DžEf}: ¡õ>ï^QÊo0ð7´3°™J|ðêÈFú“¤>(•ý€“СÒ<àâWÏw÷î·CBùÀˆŸÌÔE¢hÒ1éç_Or~!o­MZÐgÀ‰È f6“4Ã0 Ã0ŒÍˆ˜à¾1p0#ûIÀ¦BäUõìP§a†aÆfLÙ˜*š7u’Šôº±s4ð?Lh7 Ã0 ÃØÌÙ¸÷õÀØj»O!ð%ðTe'Ä0 Ã0 èl6.UÃ0 Ã0 Ã0BÙ¸VÜ Ã0 Ã0 ÃÅwÃ0 Ã0 è˜àn†a†aU€êþ;8;E¨AÈÞx6\ˆ\ÝO¸¾3²#¾#ÐX Œ^@‡Uƒ @¶¿·DvÇßF¶ßƒá^BÎ…Âl¢û"‡I#;äÙp¬—¶YÆ“)}P~ÆTÐóz×!/±ã+è™©Ø jΕ]ø\Ç·±Ò8ù¨ŽÌŽ~R©)ª:DyßîBŽÆ.¯Àø6v*º¿ âÚî+ãýÈe¹´FczÐßʃdfü¡9Îë tô¾,É⹕Î0ª81ÁýKbBõpä´èïûº,Ÿ²-hO¹7 ô¯ ž]Ó€6ÀMp{—Óã€Úh ó¹u*Azý‰w þ_öž÷ÏhYÚèè¼™VÆ@hT=ª—!Ï··¢Éï¦õ ZÇ£ºlŒV¿D“·ÄNw0p *ãi¤®û6h«» ZA›Ü&¥™Äç‚k>Nþ<„Úp}$ ÜÌÏ œ+CQ™ø\ø?Q  ð°w}`?´òöp:1µtõ»ð$RëçýþE´­½¸˜1®å¥]¹ä7Êû¼÷ áª-¹ŽÜÞ·¡Hõár´ÛØåóà‡ñ–…k9Gí¯\pͯK»ò~t <7eOï&¤Ï¥Êu¹ìÞƒàØóÊß®hç:í&4Bm È ×[7oy×\F»<·2ÃÆ&@ù î]ÐvÕ”¿é€:þ P_dw_w­Uq BÒûe„™ŒTy²µj_€ÔnDêE'¡Žñè@Z; Áq"p%ÒÇ?u’§žïî/Ýg¢ÁóÒ@z¶ӛ"þ™TŒàîš@1*»_Ñy‡cÐêbp í\„º·‘€ujÈs[ÿAmèf/îcQ}ï}Ÿ+®ùMjç¢6z¡—Öcé‹Î…W€÷€æHÅì`‚w/qâèóhÇìrïùûî¹Ö/¨¸Ã ׸•É0àšˆù·r‰R.ùò¾å}&žë ’ëø¢ÔG5$Ø\ƒòyRùGñ§Âµœ£öWépͯk»w Wèåm‚÷\îw‹„ô¹öC¹.—VÄ„ØZh<ò'´[{Ÿ¥À hò{*0-ì\ŠÊÀÚsýÜÊ g›å/¸wB÷Üá÷!ùPÉ"´r¤£÷Y7E\ùH·ýÊîüf"ušVd¶Š|ÞH¤ÆJóCÀþèÀ-Àáh•ñ2bgÖW»!Ê(á~ö>×¢r;,T™¸æc±Òç´2ÕøÑ»v4° 8¥Þï[£]„ '¡ò8mó‚vVžFõáJ®ñ¹âšÐ@=’X›»­L÷!~¢éÎ…ÕÞ_µ@ÚÒµ™ßÐá33ð¿ký¼†v¡NAçMÆ£Écïˆyðq)—(õáSV~£¼oþ½¢2Âä:¾(õ‘„J_ày ¡MPDÁµœsÝ_¹æ×µÝ»†kƒ&Ž£~Âé»öC¹.—-P>O Ýé+÷|~GÑNÅ@4™ÈT/Üõ¹•Î06Ê_poŒ, ”8†Ž:À§¶Ö‡ ­ÈvHØ^_FÜݽ8ßNó\_?¾1Ù î?xÍöân¸¶=Ú}øý:pïëˆá¢2‡øÄòÆ5yÀAHmeK4(ú­µGg/‚+‡_‘,hwC¨k¿!!};b¦k|®¸æï™ß¾/ôÒ»ñ¹k¸ò¢¬³.QÚéïÓŽükµ3L—K¹D©Ÿ\í© ¢ÔG)ñ—¥Þg#¢ î™”s.(¯~2óÑêt¤ö=ðKH8×~¨¼(FïZðù‰»Ê_"ÕµkºÎ™døÙ幕Î0ª0å/¸Pö ‘O]´-¹ ï‰/Û«HÈúpÒe‰V2–Î`´b’hM&¿Ó¯éβø‹d³™+‰¸êß©€„—õÞ½¨á6v\óq Ú¢&n«ÑÊ÷uÄV¿òÐõ²„ø¿ç{q÷Cg%‚TG‡œ£Ä—|ø‘¬þµ N™„+/Ÿ(í´4ðéÿ_Br¹¸âR.Qêç¬ünìD©õÄ—Ÿ¿’ɨI9ç‚Êê'—"Õ¬¡ÈÚ™âb‡Y]û¡ò`S—¡Ã¤Û™Ó—ë…›Eüd¸¼ž[Yá c ü÷¤ï@ ªB-4Û_¦éŽB[¹KС·|·» ‘=îI¿Úïo¥¥š¸RuàAá½>ñ‡³VyׂÔA5‘ع„ÛØqÍG?´úôDàZ˄ߕ¢Ž9Q5*±}• Áá}´ýŸˆß¾\ã‹‚K>|jzÁÕÂàì¨áÊ‹²ÞŸÊl§.å¥>|\v7V*«>2)ç\P™ío²÷—윇Πøg\û¡ò`>ɺÝ[î©&Ó‘ZÓ0âë±<ž[Yá c ü=§ÎC‚QbçêS ¸ áç“^Yõ5hµãwÂ'õG·ËVäV¨“]à6Ýÿ·Cùž¸ö=:µ\Ýï¸5œÏjÜT¶@¶í+×|Ô"yâÔ#$¾Yh <È!áÆ£ƒk P þÕ\ãsÅ5>{þß aV=\ÃU4QÛi®IW.QëÃ×÷­¢ã«¬úˆZÎU=¿AJÐôZT Žª®ýO®Êå+$¸n¸ÖÇKkâY„ÓfH'ü^bŽ–Êó¹•Î06b+î-‘ÎÏ–È´!È c¦«P¾P½=á*+ç ~4:lÚ1po 1A~Ktÿ;/-½Q} á–5!s3s; É@¶+4%ÀYh¢ò'p"Úvš{™™»Ñû¿!:¬7‹øÃM®á|f#´ ­Ú´Ò¨räÛºIìm6t!y…ºˆ˜Å×||Eì°Öï7û„<ïàvtÖaò¼Û/$Ühà>/ìkH¨hy½CÌÜšk|®¸æÔnÿ…„Í"dZn É:Ö®á*ƒ¨í4—¸”K”úˆBº÷­>1=ï$ØúGV#ºòˆ¯²ê#j9»öW騬üöDcÌÇè`isàïèPdp¬tí‡|rU.o æW!§-ÐAÞ1Äï÷D^Ó¯D‰WÑdø ô>Ûéžh‚äŸÙêŽv,çÛõv}ne…3ŒM€˜àÞþôÙ•˜“…A$ën»2½Ô=Üwô>O ¹wQà7¢—qo/Õ?"smaÂg´åwŸCúª»#kÙR„¬4ü™]œŽôõƒz¤ßÿFÖ®BÛü_x¿+É œÏX4é9™bË#s»ÈQ8>äÚh0÷|܇êâ.´u;YöÚQ­žÜ‚¼æžº§Hn?s‘iΓP»®…&Qˆ·âŸ+®ùµé{‘)¶ÆÄì'êm»†« ¢¶Ó\âR.Qê# éÞ·S‘ðäïó)à¿å_eÕGÔrÎUUYù]àÅï§‹L7·~È'W岩Ì;®^„iŠÊn,ñ¾+nEŽ ‰Yf¸-üøœë}>Kl¬uyne†3ŒM€l-—»q0ê¸#ÞÄãÆ@48‚ì%F|B‰ÂX¦á67¬\ Ã0ŒÍò×qmc­F+GÿÄvÃ0 Ã0 c£¦b÷õHqc[m/D6lŸªì„†a†aFÙTŒªŒa†a†aYQ1+î†a†a†ad… î†a†a†Q0ÁÝ0 Ã0 Ã0ª1;î‡oÇ=H6vÜ}.DŽz†'\ß9œØÙ­]Œìʾ@²êÈó–È‘ÅÛÈÞl0ÜKÈ G#€—ß ‘-ä‹ ÷¾…c½´ Ì2žLéƒò3¦‚ž÷*r S‚êâ[dÏwj¿¹ 9ô¸¼ÜSç^w!Ï‹>û8Ä]‘ùpåYät| ðð8ñ6 ý÷ãbdïÚgð"ñ¾ê ;ý{£™÷§É¾?¨(2©ß™Š~Ï Ã0ŒŠ˜àþ%1¡z80 xÅû¾.˧l‹¨“Cî Cý+ÈÃYWä°¢ pS ÜžÀ%ÈÛÜ(ä½í8äú®@¸[gÁ =þ$;€ZŽùÓÓ¤ªLo`*v@Ÿ‚ƦÈkâ]À ¨ŽÂXŒÌ‚nL\ÚË`Ôž\ØórFó(r€Óyì‚\š'A?ˆxÁ=‘4ÑÝ Õñ\4a>øš²'h™ÔïÆLe¼ç†aÆFCLp_äýù,&w.ÕD^Dç„Ü, |¹U€ô?¼ëCyÈ_)òRWÓ‹û$„|ò´as­ IDATŒ# ±(äÞdË}`¢c~ ñ1ϵ¯ IÓ¹Þµ°Ù›B®U6¾;ì~³1æô®øíÿ#$À l|7Ø yAü-E\G!Äg¿5½wU…Lê×0 Ã06Rª§’%u€¾Àý)î/ ¹6Øm û‚û¶ÀÇį~ƒú®Ä»lÒèÜ–âþ"`r• Á}oäž¼)–î$yÂÒ í>´CnÛ¿D®ÛÿÈ Ü8$ ù|ø?ÌUv= šè„Mr2¥©7íŽvGÞO‘¦OH­bÒ…X~óQÛxx7¦%RßèŠÜܯFå2Š˜Ä¥>\ù ðª| þáÝû§—ޟФ懄°€P>¦¡6|Ú… {/¢ò-Ü'\Ÿ‚êk0ðXŠßF“íD²5Þ_&´NAõ\ ½ow£EŸ(õÛx•õ.À~hî'´Ë¨j—ŠZHMèeà¿ ÷nBmç$ǸÓ—.¿®í%Ê{îZ..ý‹ï¡ö!/­õQ»ºM¡üÊÏ¥?p͇_Îý×vF¢2™¸îZ~yÀ´{µ5ªƒ‰h¬û%!¾tíÀ0 Ñò?œÚuìS"ü¦°ƒÂKu’bß¡S«2â/H&2 œyÒFR» \ƒ¹[‰p; Ay5p%Ò)Þ¸9áù®áŽA«£Ÿ?zÿûaêM‘~ó?2Îejf{ŸÛ%\÷Óó©)Dƒü ”ßË÷€ áZÅÀƒÀHoKø*¸K}DÁ% Áy¨÷ÌÑ9€ËÂìŒT¿¾CyŠ÷\â ì?…Ü{ 8€ð6ß•óô{™ÒøZ忸éÚߊÊË'JýúüZ ¸8 Mè£ð'Rï@|ØØx=b|àž_pk/Qßs(»\\û¼8 Ý´cQýÜÈGy”Ÿk%QI×®Nþ…ÔJ/GÂx1j¯>QÚa†å¿âÞ Üs#„ß ÜAO«‹ÐÊEŽÞgÝqå#ÝöO(['y&R§iEl)òÑ Ž¯>²­TíÜ‚ôŽ× Ù?;°éâî†ô‡£„ûÙû\‹ÊyIéÏ_¡0ẟ¦¢2~Û ’£€ñ!á&xAþ@ƒf[$Ôø¸ÔG\òá?÷?ÄVöŸCBEP5åh`ÈKÑù‹­ÑNS¦TC+ƒÕ‘zÌáH?=¬M¿‰“=Ð eFÞgpŲ:± Ïz¢{A>ÉûÝùÄÚÉ ´‚º?ð–w-Jýúü†„"Ÿ™ÓR:èNl'ª¿—æqÄçš_pk/™¼çe•‹kÿ€GkGwO¢ƒ²þ‚H®Ëϵ?ˆ’¨”U~-€¿#ã£×ß'^ Ò Ã0(ÿ÷ÆÈG‰cØá¨ƒ~:áÞëhõ~°Z±<uŠ©âîîÅùvšçúúñ‰*™:f{q·\Ûí>ü~¸5\Tæ ‰Q®Ww³e>ˆOGA³áò€p?Ò«ÜîÝ ³&”®>ʃRâÌ¥Þg£Àµ¨>ƒª_a‚Iö@’1hEïmâ­ÄYTs*#¾`ÚÎðâ‹„¨tC]P×ü74y îÐD­_ÈÍYœYH0¸6Ћ{eñ¹æÜÚK&”U.Qú—RtðÙg!ÊW0¹.?×þ ¼úI(»üvA£gØØRø?J;0 Ãp üWÜ H¿B Z5¿ VÃI¶‚ñ*¸þ…ô€ÿD«@缌Vë­É$âwúÙºû‹äC™+‰8ê‘|Pn š€ÔË ÜÆÄÞgªú(‹¥ÈdèP¤Bâë”Þ‚tj}ŽAj>£‘ »mG_GòÖ³K}”ë‰Wëò'–þÛ–‡ÔQšLœ ÓÐê_-$ü‰ô¤S­xŽABqâ„Õ_iîœü©*\AºòQ›íGòŽButèÜ'Jýúü’âzT^Cý‹¯*´-Z]ŽJ”üBúö’)e•K”þ¥ˆd5ÅÕ$O,rU~àÞ”g?YVùÕ÷>ÃÎÕøDm†a”¿à¾‚ôh2#X 8“ðÃoÅhqÚB^‚LÕå¾}^ˆ,g¼HúÕþlÎ 5Ðëß¹¯"ÖéûÔA5±*ƒpþJöì2C¥f²÷—Ž\ôx}ú¡íå'×Z¦ˆÏ¥>*ƒR`±vç“ø=*+‰™i<€æ~HøäyRœpý¤š\±ô­NEU‘½«‘Ás!÷ƒï{”ú ÆŸ ÞAg"ú{Ï\@fþ¢ä·<)«\¢ô/5½¿àªvÐp€O®ÊÏÇ¥?pÍG1ÉÔJóü²Ê/¸K›jÜØXÚa›å¯*3­¦'v®>Õ€«~>ɃA"+ ¾­ÆüNøàÐuÞ.:„[¡NvCØtt üßå{VàÚ÷ÈbFpu¿{à^Ôp>«‘šŽ-СĞa£‡t>W“½µšT§o¡IZ°•Ö"y ìQF\éêÃÇ3U;Í53nna3¤Yøh‚ê;¯¥¸ÿ&RMër/Æ#õ ¨OþMRF­_W\êw ÚU8­¾‘Åó\ó×÷<Qû—=ÿãD+I¹,¿ eõ®ùøMäƒõŸªÊ$/]Bî—â¶×þ9×á è2ĺ˜–Äwd["Sz 3Œ™®jùBõö„«¬œƒæÑHH Sˆ ò["‹ßyié:èk_M„V~]Vw@“lW²KõºH•çD´Ý4_ö2/v£÷C¤o>‹xg×p>³‘ÚÐVr ÒMT9j‚¶ g;´™)MЀдê„,AW’ê£A´³R‹˜eˆÕÄÔCz¢:û­ö6Goˆo{_;Ôµ•Ñ>)ÒçR>SÑöú?‘ÀQ‚„k¿m¹æÃ•gƒËÞx'’ùlùåáh¤fñMdJ/ÑÒÎÓÈlè­^Z Ç? ÉlÕ}4Ò·¿M–£òÛ­Ô~à…‹R¿QHW¿>cÐ;TBv]ó×÷<Qú—b¤SíÜœŒê&LKÐàjïyH@òWj]óáÊ$4É9 ¦S‘íè³É^×=Èc¨l"Á!‘åH8JÔÁýÓKË È[jC¤wüòΕ¹Hâ$/ÞZh5xkQê7 éê×ç{´ú±C¢™0·üF%Wïy”þåOdýT¤âÛq{rU~®ýk>| 1'¢ÙSÐûvIi¼©„ÔÍ|;îÁÅ¢¹”O;0 c³%èk5Ñ9u\‡‘Ùj]yÒMŽ@ƒƒaTC‘þn6+Fvt@“°+ЄfsÇwÀT–ºU+?Ã0Œr¥üuÜA[Ó«ÑÊÐÆÆÑÈb† íFER ™XìŽõöCV`þW™‰ÚŒiŽvÏC«¨¦V +?Ã0Œ ¡ü­Ê€¶ToD:²…HØ„%£¢)E—öGV—#Õ›g+3Q›1‡£•å¹H*W–j6¬ü Ã0*„ŠQ•1 Ã0 Ã0 #+*FUÆ0 Ã0 Ã0Œ¬0ÁÝ0 Ã0 Ã0ª&¸†a†aF v8õPâí¸ÉÆŽ»Ï…èÞð„ë;#{Ê;"{½‹‘­âH¶<†œ1-GŽ.F'„{ Ùœcðrà{!:x1Ù¹æÞéƒÊgÌ&þÜ#‘eŸÈ«áSÀg”Ã0 Ã0 b‚û—Ä„êáÈAÌ+Þ÷uY>e[äæä{Ã@ÿ rKÝ RmƒŸ=‘³Œw€QÈ„ÞqÈý÷]p· Ï–AzýIvµ ò§!'=FŒÞÈ PE î•õÜ[—Þ†Ààä•÷½ N‡a†aF b‚û"ïÏg1á.­3áHäµrNȽÀÂÀ÷7šhu}¦@Îiæ!Š¥ÈNpM/îGˆy@ü<äG Ï”‹BîA¶ÜwA^ïŒÍ“ È»&ÈqÌ3Èź î†a†al$”¿Ž{ /ðnŠû C®ÍD†* ×¶EÂwÐxå7@5´JŸŠÖ@'à­÷3Ès¨<¤r4‡Ôv®šœ¼Žl?Ô}îD6½ƒ õâ²ðR+Ê„.ÀÝÞóÇ"÷áû%„ç=£ò‚øAà¯^ \K´òŒ÷›—½ïBžÛÆû}/à,/ì[Èâ?ut}®O=´‹³WêìfÌJdºEÂu—|tîCuû*p©Õ·\ؘەk|®é3 Ã0 #%fÇÝ0 Ã0 Ã0ªÕ׬^UÙi0 Ã0 Ã0 # fÒ0 Ã0 Ã0ª&¸†a†aFÀwÃ0 Ã0 è˜àn†a†aUÜ Ã0 Ã0 £ `‚»a†a†aTLp7 Ã0 Ã0Œ*€ î†a†a†Q0ÁÝ0 Ã0 Ã0ª&¸†a†aFÀwÃ0 Ã0 è˜àn†a†aUÜ Ã0 Ã0 £ P=‘œsáÅtÛugŽ=ú¨¤{EEEôé7çŸz‚V[µÌÅãâž·nÝ:ÈË£fAÁ†ûa×ÊâŠk®¥q£Fœsæq×ýõ7:ìÞó2…õëSTTÄSÏý·ÞÇ¢%?S¯n]¶kßžž|"ÛwìÀÃ?Á¨GŸŸOãFè¾ûnœqê)4lØ .þ qÇÝ#™:í[Z¶Ü’aGIÿý÷M›Þ¿þú‹‡yŒ·Þy—?×ýÉîÝvå¢sÏ¡^½z¼ö曼òêëüøã6hÀÁæøaCÉËËÛfìÛã¸íŽ<ùÈhZ´h÷ŒuEE<ðÐÃ|ñõ×,X¸ˆÍšqÜ1C< ¤ôgšG€ÒÒR{êiƼþ¿þ¶”V[µäÄce¿}÷qúýÃ?Áz˜þ3’ÎvŒ»÷Ñ'Ÿrÿƒ£yꑇœâ*«¬ Ã06W‚c@³¦Mi³í¶ =â0ºï±û†ëW\s-ãÞ}?e}zÓ¾m[Š‹‹™úí·Ìžý#+W¯¦F4nÔˆÝvÝ…&—[ú&N™Âø 7„¯[·. éÒiG¶Új«¬ž%n—2HŒ¯V­Z4oÖŒÝwëFƒúõs’ư8'N™Â’ÅK£2!kÁ½¸¤„©S§rʉÇgUFÏ»ýî{¨S»VœÐv-Ü~×=Ìš=›K.¼€V­¶bùŠ•L6……qávݹ+·ßtÅÅÅü8g.7Þz;×Þt3wÜ|ã†0Ë–-ãÔ3ÿÅàý9÷¬³?q×Üx5k°wï^e¦cÔƒ£ùzÂn¾îjn»ënÎ8÷|ùïýäåå1íÛé¼úÚëüã¸ch³Í6ŒŸ<‰›n½ƒÆqÐàA¬ZµŠo»ƒIS¦²zíÚ¤øÿúë/N9ã,¶¨W Î>›-šñÓüqa\ÒŸMž{áE^xé.»è¶ÜrKÞyÿ}®¼îzZ·nÅvíÛ§ý=@Íš5¹éö;yôÁQT˾Á”®¬ Ã06wvݹ+·ÞpÅ%%,\´ˆO?ÿ‚ .½œã†Íÿx—]t!Ÿã'Nbøu7ðÚ Ïmˆ£fÍšIñ•””²ä—Ÿ¹ï¿rÎÿæ™Çq^K•ư8]Óæ*Då›ñø~Ö,vÛuvÛegÈÏgéÒ¥”””лGzíµ‹/æƒ?aè‡oø}µjÕøì˯øý÷ßéÕ£õëoÁŸEEüòË/Ô ”my¤ÏgËÍé¿ß~”””°råJæ-XÀÛï¾G×vb×]vÎ* ®q»–_ii)«V­âë yëíqvè å™isgY î³fý@)¥tìÝlsc}žOqq1oŽÇÈÛo¥ËNhÔ°!m¶i¶zµêÔ®]€.;u攓Näªë®§´´tÊ÷˯½Në­[qÆ?O`ëV-ùiþ|žxúÙ2…ÚÒÒR^xåUn½á::l·7\5œCÆ—_Íž{ìAçN;2jäÝžuà–™8q2Ÿ~þ IJå+hÒ¸£FÞÅaCIzÆ+¯½ÁŠ+}ÿ½[‹æñ«Ì.éÏ4>Ÿ~ö¸aÕæÄãŽå³/¾dòÔo÷{îÁ¢ÅKxîù9úˆÃœ~$]Y†alîT¯VºuëP¿cGvèØ‘ŽÛµçâ+®b¿¾{Ó¶MjÕªµ!|í:µÉ£tÃoÊŠo‹-ê1ü²KpÐfÍú!i÷4“4–gª´E‘¢°xɦϘÁaC¡N:®7 LªW‰jÕkÔJ©Q£F\<%%%ÌþñGõëGóæÍ”—Úµãâ)¯ôùäçåoHWÍš5iÒ¤ M7æ÷? M›miØ AÒo\q‰;JãkÔ¨ûôîÅãO?ÃÒß§YÓ¦Y§1Wq†>'Û&NžB×.]7xÅÅÅÜ÷ßräÑô?ðn¸å¶¸ðEEEÜuï}røQ <äPn¾ck½•Ì˯¾–ënº%.ücO>Å¿/ú¼»î½1¯¿Á³Ï¿HÏ}û1úÑÇB¯ ¿öz®¹á¦¸xŸzö9λøRç|–””PRRÂOóçG*€üéÊÊ0 ÃH¦wÏžì°}GÞxóí¬ãªYP@~~>5Ò.§8³‘Êbâ¤ÉìÔ¹SœPœ ¥¥¥”–”°lÅò¥Ld›¾Ö[oM“Æ™õÃ윦+,îlÊ Zµjäåååte¼<â„La×]ºnø~ï¨øü«¯¹õ†ëxôQÔª/ðÜ6ân.\Ä£ÜÏ£ŒbÞ¼yÜ÷ ôŒûï·/Ÿ|þyÜöËGŸ~Fÿ}cÂ_ðygŸ~0˜#ûŸ¾7Ž?.ôÚ~}÷áÓÏ¿ 8ïÇŸ~Æ~ûìíœÏ5j0xÀn½sw޼‡™³f9ýnÕš5<ùÜszÈAq×þåZmµeܵ­[µ¤[ŸŠ……äçç3sÖq×ëÖ­Ç/¿¤þÝ”iÓè´CG§4/X¸ˆ¦M›pÓmwpàßçÃbô£ÅÕ‹Kú3Í£Ï Ç cƬYüßgñÁGsîEó÷!‡°Û®»8åÃgûŽ8pÐî¸ûžH¿3 Ã02g‡í;2oÁ‚ôËà?–qçÈ{éºSç »ÌÙ’Iœ™ÊéÈÕjlµjÕhß¾=Ÿ}ñ%ŸõKÿ=©ËMúš6iÌò+r’ž²âδ þüóO>ÿêkš7oFãFr’®òˆÓ'+U™ÒÒR&MžÂñÃŽt ñù—^æþ{îb»ví8÷¬3xùÕ1¬X¹’ׯ¾É£Ž¢·eòÿøW]çu&{u߃õë‹™6ý;ºtîÄÒßgÎsèÙcÏÐ繲绳~ýz¦M›N×.Y¾bÓ¿ŸÁ­7\)ž‹Î?‡ÝvÝ…GŸ|ŠgŸ‘:uâøcަWqá¾?ž=÷ŽÀÌÏÏçïC†lø^RRÂòå+’¶âêÕ«G~~~™ ¼zõêôÝ»÷Ü?ŠFÒ¬i^yí &MžL«Vá@>ÿòKæü8‡;o¾)ô~uEE¬ZµŠG?ÊI'ÇñÆòÍĉÜrÇ7nÄ!è”þlòè³}Çœ~êÉÜrÇ]\:üjZ¶lÁƒ¥ý]§œ|Gs<Ÿ}þ=öÚ3£8 Ã0 wš6nÌŒ™3#ÿ.q í¿ÿ¾ÜuÛ-eü¢bât•\)**b]QµjDÙÐk¯=iÙ¢“§MãÛéßѬY3vÞ©3­3<Ô›«ôÕ©S‡ß–.Í*׸]Ë`áâÅ<øÈ£¾·kÛ†Aýúe•–òˆ3Œ¬÷9sçò×_EôÍ-^LqI 3Ø ÂÆ¼yó)))á¢K¯Øpmýúõ¬ýóO@3Ú¾}zóɧŸÑ¥s'>ùì3zöÜkƒn\âó\)(( wÏ|òÙgtíÒ™O?ÿ‚n»îg…ÅWÇ(‹jùùôÛ¯/ýö“ºÇK¯Œá‚K.çâóÏeÈÁ±õ=ºuãî;nÔð?ÿò+®¼özÖ®YÃ"??Ÿºuë²rE¼ºÈš5k)))¡aÆe¦ãßçŸËí#îæ¢K/§q£FxÀ úî݇?–%o-[¶Œo½ƒ³Î8-¶¨[<5 ¨]»6C<œƒ ÀA[âÛï¾ç­qïrÈ:¥?Û<<0ú>ùüsè¿T¯^ƒ‡{œcO<™¯½š{vOûû uk׿‚³ÏâÖwót–‡d Ã0Œôüºt)­[E»í²3wÞ¢…¦Ë®º†ââb 2<”šË8]eW ¨^½:+V¬ ‘Ø˜Ž¼¼<ÚµmC»¶møå—_ønÆLÞ~÷=zíµ'ÛwtÛq/ô­Y³†ÂúÙéÚ»ÆíZ-[´`@¿ýx÷ƒ)))ÉZ¥¥<â #+U™Dýö¿ŠŠ6è…QÏùï}¼ôìS¼ôìSŒyá9ÞyýÕ aúí¿/ú)~ü)ýj2‰Ï‹ÂþûîÃÇžøGŸ|Êþ}÷‰¥«Þ,_ž¼¼zíªW¯NÝÝ®:uâÊK/æ ÁƒxãíÔ:|² 2xàÞû࣠כ5mšd©eñ’%äååÑ´i“2óR‹-¸úŠË÷ú«<óø#sÔ‘,X¸V-ãÕRŠ‹‹¹ìªkØ©s'†t`™qiÖ¤ k,¨lßa»¸Y­Kú]œtÚôܷ߆¿ÇŸ~€ÿÈOòïóΡm›6´ÞºÃ/»„Aúóà#mˆ/ÕïÃØ»OoÚµmËèÇžHº%Ã0 #=ß}?ƒvmÚDþ]µüjPPPÀñÆòþ‡3ç§Ÿ²JK®ãt•ÒÑ °‹güûT4kÖŒ½{÷¢ãvÛ1kvæúå¹H߯¿-uZ¬ËuÜe•¯{^­Z5vî²sšÇ˳;Pq†‘µàÔoßÊÓ_ž4ejhø–-ZP»vm>úì³ÐûÝvÙ…+W1sÖ,¾Ÿ1“î»ÇìÀ&>Ïgýúõi¯uß}w~]º”çÌaÂÄIôéÛÚÚ®m[&NžÂº¢¢¸ßLž2…¶mÚÄèN¤yófÔ¬‘ÞÔRÃÂÔpìÕc/ƽo7öý>b÷]w¥^ÄC ó,dâä) 8`õÒÒR®»éŠŠþâÊKþ)¾ž=öâÝ÷?Œ»öË/¿Ñ*`/Õ%ý.aºï?|úÞ¸ ¾/€¢¢u'¥mÇí;²zÕª ßSý>œs/½ò*?Îw=j<†aFj>ûâK-ZÌÁÎ*žÎvdç.;1úÑÇÒ®„8]e€”ié܉3gòëoéÏ}eBݺu¨^-såŠlÓ7ÁV®ZÅörs>!“¸Ó•A³¦MiѼ9“&OÎYÚÊ#NŸ¬÷n;Ç麵ksÀÀÜ|ûLÿî;þøcV7 väÜ;꾞0â’–üü3ßψéÀUËÏgß¾{s눻é±g÷¸­¬Äç4oÖ”¯¾¿ÁÚJªk5jÔ`ï^=1ò^vêÜ9NMfðÀþäççsÉÃùnÆ ~ùõWÞzç]îõ gœr2k×®åêëoä½>bî¼y,ùùgÞzç]ž~îy8``\šŠKŠ)**¢¨¨ˆÕ«W3aÒd^;–þûÆôëþvÈAÌ›?Ÿ;FÞâŋy÷ýyê™g64½ÀøÖ;ï2ë‡øí·ßøì‹/9û‚‹rдk[Ù¸ûÞû˜ñ”óoÊ*+Ã0ŒÍõÅëY»v-«×®eösxüég¸êºø÷ùç¦4ù…ãÆ»ïÈÜyórÚÌâŒ"D¡}›6´Ùv^û&“§Neé￳råJæÌý©L§K‰üõ×_|øñ'Ì™ûË–/gÕªUü0gS¿ÎvÛ¹™OÎ6}%¥¥üõ×_­_ÏüÁ”iÓøà£éµ×žIæ+£âw6eеËNü8g.Ër¸B^qB:îó,âÏ5k’ôÍÏ?û,FÜs/ç]|)5ª×àÀAiÕ*æ1õÄã¥VíZÜ~çÝüüë¯4nÔã†çulÀ~ûñ¿^âäãKû¼ÃÂÄI“9|è1ì×·/—ýûÂÐkû÷݇ó.¾”+/½8.ŽZµjñÀîfä}£¸èÒ+XûçŸthߎ®¹ŠnàÙh$—IDATž>tII ­[oÍãO?ÃÂ… )^¿žÖÛlÃÅçŸG¿ýâMŽŸ8‰>ýô"×­]›Ö­[sÆ?O‰óøÙ¢ysî»ûNFŒüÇžt ÛnÓš«¯¸Œî»uK[öÓ¦OçžûF±zõ*Ú¶m˱GÉ¡‡¼áþ¬Ù³yú¹çrdüAÞÇG?@ƒú…tØ®qŒÊù—_ QÆl¹e î9‚;Gþ‡cÿq2Íš5ãì3O;Ôé’þlòpóµ×pÿCsýM·²lÙ2š7oÆà8vh´ÃɉyØßûö;¡+ú‰øÞs}ËÊ0 csg¤Éôxùùù´nÕŠŽ¶ã¡ûïcëV¹ñ–Þ}÷Ýè°]{yô ®ºÂÝŒs.ãŒ"Deß½÷fæ?ðó™2í[JJJhPXH{Ïȇ+õ ë3eÚ4V¬XAiI … Ðk¯½âõÊ3}‹—,áÑ'Ÿ"//ÂúõiÜH-ê×ß"«çG‰;Ó2hÕ²%5bÒä)ìÓ§wÖé-¯8òÖ¬^•þTf¯¾þïø1wÞrcúÀ9 Ï[¸hG{o¾òbÜŠ»a†a†alìd¬*SX¿>Gü}Hú€9"ÏûðãOè¶ËÎ&´†a†aUŽŒUe\\Öç’\ #include #include #include "buffer.h" #include "i18n.h" #include "serial.h" #include #include #include #define TIMESTAMP_SIZE 50 extern gboolean timestamp_on; static int need_to_write_timestamp = 0; static char *buffer = NULL; static char *current_buffer; static unsigned int pointer; static int cr_received = 0; char overlapped; extern guint virt_col_pos; void (*write_func)(const char *, unsigned int) = NULL; void (*clear_func)(void) = NULL; void create_buffer(void) { if(buffer == NULL) { buffer = malloc(BUFFER_SIZE); clear_buffer(); } return; } void delete_buffer(void) { if(buffer != NULL) free(buffer); return; } //assumes that buffer always has space for timestamp (TIMESTAMP_SIZE) //buffer points to location where timestamp will be inserted unsigned int insert_timestamp(char *buffer) { unsigned int size = 0; if(timestamp_on) { char buf[TIMESTAMP_SIZE]; struct timespec ts; int d,h,m,s,x; timespec_get(&ts, TIME_UTC); d = (ts.tv_sec / (3600 * 24)); h = (ts.tv_sec / 3600) % 24; m = (ts.tv_sec / 60 ) % 60; s = ts.tv_sec % 60; x = ts.tv_nsec / 1000000; snprintf(buf, TIMESTAMP_SIZE - 1, "[%d.%02uh.%02um.%02us.%03u] " , d, h, m, s, x ); strcpy(buffer, buf); size = strlen(buf); } return size; } void put_chars(const char *chars, unsigned int size, gboolean crlf_auto) { // buffer must still be valid after cr conversion or adding timestamp // only pointer is copied below char out_buffer[(BUFFER_RECEPTION*2) + TIMESTAMP_SIZE]; const char *characters; /* If the auto CR LF mode on, read the buffer to add \r before \n */ if(crlf_auto || timestamp_on) { int i, out_size = 0; for (i=0; i BUFFER_SIZE) { characters = chars + (size - BUFFER_SIZE); size = BUFFER_SIZE; } else characters = chars; if((size + pointer) >= BUFFER_SIZE) { memcpy(current_buffer, characters, BUFFER_SIZE - pointer); chars = characters + BUFFER_SIZE - pointer; pointer = size - (BUFFER_SIZE - pointer); memcpy(buffer, chars, pointer); current_buffer = buffer + pointer; overlapped = 1; } else { memcpy(current_buffer, characters, size); pointer += size; current_buffer += size; } if(write_func != NULL) write_func(characters, size); } void write_buffer(void) { if(write_func == NULL) return; if(overlapped == 0) write_func(buffer, pointer); else { write_func(current_buffer, BUFFER_SIZE - pointer); write_func(buffer, pointer); } } void write_buffer_with_func(void (*func)(const char *, unsigned int)) { void (*write_func_backup)(const char *, unsigned int); write_func_backup = write_func; write_func = func; write_buffer(); write_func = write_func_backup; } void clear_buffer(void) { if(clear_func != NULL) clear_func(); if(buffer == NULL) return; overlapped = 0; memset(buffer, 0, BUFFER_SIZE); current_buffer = buffer; pointer = 0; cr_received = 0; virt_col_pos = 0; } void set_clear_func(void (*func)(void)) { clear_func = func; } void unset_clear_func(void (*func)(void)) { clear_func = NULL; } void set_display_func(void (*func)(const char *, unsigned int)) { write_func = func; } void unset_display_func(void (*func)(const char *, unsigned int)) { write_func = NULL; } gtkterm-1.1.1/src/buffer.h000066400000000000000000000033651376216657300154270ustar00rootroot00000000000000/***********************************************************************/ /* buffer.h */ /* -------- */ /* GTKTerm Software */ /* (c) Julien Schmitt */ /* */ /* ------------------------------------------------------------------- */ /* */ /* Purpose */ /* Management of a local buffer of data received */ /* - Header file - */ /* */ /* ChangeLog */ /* - 0.99.7 : removed auto crlf stuff - (use macros instead) */ /* - 0.98.4 : file creation by Julien */ /* */ /***********************************************************************/ #ifndef BUFFER_H_ #define BUFFER_H_ #define BUFFER_SIZE (128 * 1024) void create_buffer(void); void delete_buffer(void); void put_chars(const char *, unsigned int, gboolean); void clear_buffer(void); void write_buffer(void); void set_display_func(void (*func)(const char *, unsigned int)); void unset_display_func(void (*func)(const char *, unsigned int)); void set_clear_func(void (*func)(void)); void unset_clear_func(void (*func)(void)); void write_buffer_with_func(void (*func)(const char *, unsigned int)); #endif gtkterm-1.1.1/src/cmdline.c000066400000000000000000000122261376216657300155600ustar00rootroot00000000000000/***********************************************************************/ /* cmdline.c */ /* --------- */ /* GTKTerm Software */ /* (c) Julien Schmitt */ /* */ /* ------------------------------------------------------------------- */ /* */ /* Purpose */ /* Reads the command line */ /* */ /* ChangeLog */ /* - 0.99.2 : Internationalization */ /* - 0.98.3 : modified for configuration file */ /* - 0.98.2 : added --echo */ /* - 0.98 : file creation by Julien */ /* */ /***********************************************************************/ #include #include #include #include #include "term_config.h" #include "files.h" #include "auto_config.h" #include "i18n.h" #include #include extern struct configuration_port config; void display_help(void) { i18n_printf(_("\nGTKTerm version %s\n"), VERSION); i18n_printf(_("\t (c) Julien Schmitt\n")); i18n_printf(_("\nThis program is released under the terms of the GPL V.2\n")); i18n_printf(_("\t ** Use at your own risks ! **\n")); i18n_printf(_("\nCommand line options\n")); i18n_printf(_("--help or -h : this help screen\n")); i18n_printf(_("--config or -c : load configuration\n")); i18n_printf(_("--port or -p : serial port device (default /dev/ttyS0)\n")); i18n_printf(_("--speed or -s : serial port speed (default 9600)\n")); i18n_printf(_("--bits or -b : number of bits (default 8)\n")); i18n_printf(_("--stopbits or -t : number of stopbits (default 1)\n")); i18n_printf(_("--parity or -a : parity (default none)\n")); i18n_printf(_("--flow or -w : flow control (default none)\n")); i18n_printf(_("--delay or -d : end of line delay in ms (default none)\n")); i18n_printf(_("--char or -r : wait for a special char at end of line (default none)\n")); i18n_printf(_("--file or -f : default file to send (default none)\n")); i18n_printf(_("--rts_time_before or -x : for RS-485, time in ms before transmit with rts on\n")); i18n_printf(_("--rts_time_after or -y : for RS-485, time in ms after transmit with rts on\n")); i18n_printf(_("--echo or -e : switch on local echo\n")); i18n_printf(_("--disable-port-lock or -L: does not lock serial port. Allows to send to serial port from different terminals\n")); i18n_printf(_(" Note: incoming data are displayed randomly on only one terminal\n")); i18n_printf("\n"); } int read_command_line(int argc, char **argv, gchar *configuration_to_read) { int c; int option_index = 0; static struct option long_options[] = { {"speed", 1, 0, 's'}, {"parity", 1, 0, 'a'}, {"stopbits", 1, 0, 't'}, {"bits", 1, 0, 'b'}, {"file", 1, 0, 'f'}, {"port", 1, 0, 'p'}, {"flow", 1, 0, 'w'}, {"delay", 1, 0, 'd'}, {"char", 1, 0, 'r'}, {"help", 0, 0, 'h'}, {"echo", 0, 0, 'e'}, {"disable-port-lock", 0, 0, 'L'}, {"rts_time_before", 1, 0, 'x'}, {"rts_time_after", 1, 0, 'y'}, {"config", 1, 0, 'c'}, {0, 0, 0, 0} }; /* need a working configuration file ! */ Check_configuration_file(); while(1) { c = getopt_long (argc, argv, "s:a:t:b:f:p:w:d:r:heLc:x:y:", long_options, &option_index); if(c == -1) break; switch(c) { case 'c': Load_configuration_from_file(optarg); break; case 's': config.vitesse = atoi(optarg); break; case 'a': if(!strcmp(optarg, "odd")) config.parite = 1; else if(!strcmp(optarg, "even")) config.parite = 2; break; case 't': config.stops = atoi(optarg); break; case 'b': config.bits = atoi(optarg); break; case 'f': fic_defaut = g_strdup(optarg); break; case 'p': strcpy(config.port, optarg); break; case 'w': if(!strcmp(optarg, "Xon")) config.flux = 1; else if(!strcmp(optarg, "RTS")) config.flux = 2; else if(!strcmp(optarg, "RS485")) config.flux = 3; break; case 'd': config.delai = atoi(optarg); break; case 'r': config.car = *optarg; break; case 'e': config.echo = TRUE; break; case 'L': config.disable_port_lock = TRUE; break; case 'x': config.rs485_rts_time_before_transmit = atoi(optarg); break; case 'y': config.rs485_rts_time_after_transmit = atoi(optarg); break; case 'h': display_help(); return -1; default: i18n_printf(_("Undefined command line option\n")); return -1; } } Verify_configuration(); return 0; } gtkterm-1.1.1/src/cmdline.h000066400000000000000000000023061376216657300155630ustar00rootroot00000000000000/***********************************************************************/ /* cmdline.h */ /* --------- */ /* GTKTerm Software */ /* (c) Julien Schmitt */ /* */ /* ------------------------------------------------------------------- */ /* */ /* Purpose */ /* Reads the command line */ /* - Header file - */ /* */ /* ChangeLog */ /* - 0.98 : file creation by Julien */ /* */ /***********************************************************************/ int read_command_line(int, char **); gtkterm-1.1.1/src/device_monitor.c000066400000000000000000000037741376216657300171630ustar00rootroot00000000000000/***********************************************************************/ /* device_mintor.h */ /* --------- */ /* GTKTerm Software */ /* (c) Julien Schmitt */ /* */ /* ------------------------------------------------------------------- */ /* */ /* Purpose */ /* Monitor device to autoreconnect */ /* Written by Kevin Picot - picotk27@gmail.com */ /* */ /***********************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "interface.h" extern struct configuration_port config; static inline void device_monitor_status(const bool connected) { if (connected) interface_open_port(); else interface_close_port(); } static inline void device_monitor_handle(const char *action) { if (strcmp(action, "remove") == 0) device_monitor_status(false); else if (strcmp(action, "add") == 0) device_monitor_status(true); } void event_udev(GUdevClient *client, const gchar *action, GUdevDevice *device) { if (!device || !action) return; if (!g_udev_device_get_device_file(device)) return; const gchar *name = config.port; if (strcmp(g_udev_device_get_device_file(device), name) == 0) device_monitor_handle(action); } extern void device_monitor_start(void) { const gchar *const subsystems[] = {NULL, NULL}; /* Initial check */ GUdevClient *udev_client = g_udev_client_new(subsystems); if (g_udev_client_query_by_device_file(udev_client, config.port) == NULL) { device_monitor_status(false); } else { device_monitor_status(true); } /* Monitor device */ g_signal_connect(G_OBJECT(udev_client), "uevent", G_CALLBACK(event_udev), NULL); } gtkterm-1.1.1/src/device_monitor.h000066400000000000000000000020321376216657300171520ustar00rootroot00000000000000/***********************************************************************/ /* device_mintor.h */ /* --------- */ /* GTKTerm Software */ /* (c) Julien Schmitt */ /* */ /* ------------------------------------------------------------------- */ /* */ /* Purpose */ /* Monitor device to autoreconnect */ /* Written by Kevin Picot - picotk27@gmail.com */ /* */ /***********************************************************************/ #ifndef DEV_MON_H_ #define DEV_MON_H_ extern void device_monitor_start(void); #endif gtkterm-1.1.1/src/files.c000066400000000000000000000217561376216657300152570ustar00rootroot00000000000000/***********************************************************************/ /* fichier.c */ /* --------- */ /* GTKTerm Software */ /* (c) Julien Schmitt */ /* */ /* ------------------------------------------------------------------- */ /* */ /* Purpose */ /* Raw / text file transfer management */ /* */ /* ChangeLog */ /* (All changes by Julien Schmitt except when explicitly written) */ /* */ /* - 0.99.5 : changed all calls to strerror() by strerror_utf8() */ /* - 0.99.4 : added auto CR LF function by Sebastien */ /* modified ecriture() to use send_serial() */ /* - 0.99.2 : Internationalization */ /* - 0.98.4 : modified to use new buffer */ /* - 0.98 : file transfer completely rewritten / optimized */ /* */ /***********************************************************************/ #include #include #include #include #include #include #include #include #include #include "term_config.h" #include "interface.h" #include "serial.h" #include "buffer.h" #include #include /* Global variables */ gint nb_car; gint car_written; gint current_buffer_position; gint bytes_read; GtkAdjustment *adj; GtkWidget *ProgressBar; gint Fichier; guint callback_handler; gchar *fic_defaut = NULL; GtkWidget *Window; gboolean waiting_for_char = FALSE; gboolean waiting_for_timer = FALSE; gboolean input_running = FALSE; gchar *str = NULL; FILE *Fic; /* Local functions prototype */ gint Envoie_fichier(GtkFileChooser *FS); gint Sauve_fichier(GtkFileChooser *FS); gint close_all(void); void ecriture(gpointer data, gint source); gboolean timer(gpointer pointer); gboolean idle(gpointer pointer); void remove_input(void); void add_input(void); void write_file(char *, unsigned int); extern struct configuration_port config; void send_raw_file(GtkAction *action, gpointer data) { GtkWidget *file_select; file_select = gtk_file_chooser_dialog_new(_("Send RAW File"), GTK_WINDOW(Fenetre), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL); if(fic_defaut != NULL) gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(file_select), fic_defaut); if(gtk_dialog_run(GTK_DIALOG(file_select)) == GTK_RESPONSE_ACCEPT) { gchar *fileName; gchar *msg; fileName = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_select)); if(!g_file_test(fileName, G_FILE_TEST_IS_REGULAR)) { msg = g_strdup_printf(_("Error opening file\n")); show_message(msg, MSG_ERR); g_free(msg); g_free(fileName); gtk_widget_destroy(file_select); return; } Fichier = open(fileName, O_RDONLY); if(Fichier != -1) { GtkWidget *Bouton_annuler, *Box; fic_defaut = g_strdup(fileName); msg = g_strdup_printf(_("%s : transfer in progress..."), fileName); gtk_statusbar_push(GTK_STATUSBAR(StatusBar), id, msg); car_written = 0; current_buffer_position = 0; bytes_read = 0; nb_car = lseek(Fichier, 0L, SEEK_END); lseek(Fichier, 0L, SEEK_SET); Window = gtk_dialog_new(); gtk_window_set_title(GTK_WINDOW(Window), msg); g_free(msg); Box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 10); gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(Window))), Box); ProgressBar = gtk_progress_bar_new(); gtk_box_pack_start(GTK_BOX(Box), ProgressBar, FALSE, FALSE, 5); Bouton_annuler = gtk_button_new_with_label(_("Cancel")); g_signal_connect(GTK_WIDGET(Bouton_annuler), "clicked", G_CALLBACK(close_all), NULL); gtk_container_add(GTK_CONTAINER(gtk_dialog_get_action_area(GTK_DIALOG(Window))), Bouton_annuler); g_signal_connect(GTK_WIDGET(Window), "delete_event", G_CALLBACK(close_all), NULL); gtk_window_set_default_size(GTK_WINDOW(Window), 250, 100); gtk_window_set_modal(GTK_WINDOW(Window), TRUE); gtk_widget_show_all(Window); add_input(); } else { msg = g_strdup_printf(_("Cannot read file %s: %s\n"), fileName, strerror(errno)); show_message(msg, MSG_ERR); g_free(msg); } g_free(fileName); } gtk_widget_destroy(file_select); } void ecriture(gpointer data, gint source) { static gchar buffer[BUFFER_EMISSION]; static gchar *current_buffer; static gint bytes_to_write; gint bytes_written; gchar *car; gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(ProgressBar), (gfloat)car_written/(gfloat)nb_car ); if(car_written < nb_car) { /* Read the file only if buffer totally sent or if buffer empty */ if(current_buffer_position == bytes_read) { bytes_read = read(Fichier, buffer, BUFFER_EMISSION); current_buffer_position = 0; current_buffer = buffer; bytes_to_write = bytes_read; } if(current_buffer == NULL) { /* something went wrong... */ g_free(str); str = g_strdup_printf(_("Error sending file\n")); show_message(str, MSG_ERR); close_all(); return; } car = current_buffer; if(config.delai != 0 || config.car != -1) { /* search for next LF */ bytes_to_write = current_buffer_position; while(*car != LINE_FEED && bytes_to_write < bytes_read) { car++; bytes_to_write++; } if(*car == LINE_FEED) bytes_to_write++; } /* write to serial port */ bytes_written = send_serial(current_buffer, bytes_to_write - current_buffer_position); if(bytes_written == -1) { /* Problem while writing, stop file transfer */ g_free(str); str = g_strdup_printf(_("Error sending file: %s\n"), strerror(errno)); show_message(str, MSG_ERR); close_all(); return; } car_written += bytes_written; current_buffer_position += bytes_written; current_buffer += bytes_written; gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(ProgressBar), (gfloat)car_written/(gfloat)nb_car ); if(config.delai != 0 && *car == LINE_FEED) { remove_input(); g_timeout_add(config.delai, (GSourceFunc)timer, NULL); waiting_for_timer = TRUE; } else if(config.car != -1 && *car == LINE_FEED) { remove_input(); waiting_for_char = TRUE; } } else { close_all(); return; } return; } gboolean timer(gpointer pointer) { if(waiting_for_timer == TRUE) { add_input(); waiting_for_timer = FALSE; } return FALSE; } void add_input(void) { if(input_running == FALSE) { input_running = TRUE; callback_handler = g_io_add_watch_full(g_io_channel_unix_new(serial_port_fd), 10, G_IO_OUT, (GIOFunc)ecriture, NULL, NULL); } } void remove_input(void) { if(input_running == TRUE) { g_source_remove(callback_handler); input_running = FALSE; } } gint close_all(void) { remove_input(); waiting_for_char = FALSE; waiting_for_timer = FALSE; gtk_statusbar_pop(GTK_STATUSBAR(StatusBar), id); close(Fichier); gtk_widget_destroy(Window); return FALSE; } void write_file(char *data, unsigned int size) { fwrite(data, size, 1, Fic); } void save_raw_file(GtkAction *action, gpointer data) { GtkWidget *file_select; file_select = gtk_file_chooser_dialog_new(_("Save RAW File"), GTK_WINDOW(Fenetre), GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL); gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(file_select), TRUE); if(fic_defaut != NULL) gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(file_select), fic_defaut); if(gtk_dialog_run(GTK_DIALOG(file_select)) == GTK_RESPONSE_ACCEPT) { gchar *fileName; gchar *msg; fileName = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_select)); if ((!fileName || (strcmp(fileName, ""))) == 0) { msg = g_strdup_printf(_("File error\n")); show_message(msg, MSG_ERR); g_free(msg); g_free(fileName); gtk_widget_destroy(file_select); return; } Fic = fopen(fileName, "w"); if(Fic == NULL) { msg = g_strdup_printf(_("Cannot open file %s: %s\n"), fileName, strerror(errno)); show_message(msg, MSG_ERR); g_free(msg); } else { fic_defaut = g_strdup(fileName); write_buffer_with_func(write_file); fclose(Fic); } g_free(fileName); } gtk_widget_destroy(file_select); } gtkterm-1.1.1/src/files.h000066400000000000000000000022601376216657300152510ustar00rootroot00000000000000/***********************************************************************/ /* files.h */ /* --------- */ /* GTKTerm Software */ /* (c) Julien Schmitt */ /* */ /* ------------------------------------------------------------------- */ /* */ /* Purpose */ /* Raw / text file transfer management */ /* - Header file - */ /* */ /***********************************************************************/ #ifndef FICHIER_H_ #define FICHIER_H_ void send_raw_file(GtkAction *action, gpointer data); void save_raw_file(GtkAction *action, gpointer data); void add_input(void); extern gboolean waiting_for_char; extern gchar *fic_defaut; #endif gtkterm-1.1.1/src/gtkterm.c000066400000000000000000000043251376216657300156230ustar00rootroot00000000000000/***********************************************************************/ /* gtkterm.c */ /* --------- */ /* GTKTerm Software */ /* (c) Julien Schmitt */ /* */ /* ------------------------------------------------------------------- */ /* */ /* Purpose */ /* Main program file */ /* */ /* ChangeLog */ /* - 0.99.2 : Internationalization */ /* - 0.99.0 : added call to add_shortcuts() */ /* - 0.98 : all GUI functions moved to widgets.c */ /* */ /***********************************************************************/ #include #include #include #include "interface.h" #include "serial.h" #include "term_config.h" #include "cmdline.h" #include "parsecfg.h" #include "buffer.h" #include "macros.h" #include "auto_config.h" #include "device_monitor.h" #include "user_signals.h" #include #include int main(int argc, char *argv[]) { gchar *message; config_file = g_strdup_printf("%s/.gtktermrc", getenv("HOME")); bindtextdomain(PACKAGE, LOCALEDIR); bind_textdomain_codeset(PACKAGE, "UTF-8"); textdomain(PACKAGE); gtk_init(&argc, &argv); create_buffer(); create_main_window(); if(read_command_line(argc, argv) < 0) { delete_buffer(); exit(1); } Config_port(); ConfigFlags(); message = get_port_string(); Set_window_title(message); Set_status_message(message); g_free(message); add_shortcuts(); set_view(ASCII_VIEW); device_monitor_start(); user_signals_catch(); gtk_main(); delete_buffer(); Close_port(); return 0; } gtkterm-1.1.1/src/i18n.c000066400000000000000000000104101376216657300147150ustar00rootroot00000000000000/***********************************************************************/ /* i18n.c */ /* ------ */ /* GTKTerm Software */ /* (c) Julien Schmitt */ /* */ /* ------------------------------------------------------------------- */ /* */ /* Purpose */ /* UTF-8 conversion to print in the console */ /* */ /* ChangeLog */ /* - 0.99.5 : created strerror_utf8() function */ /* - 0.99.2 : file creation by Julien */ /* function iconv_from_utf8_to_locale is based */ /* on hddtemp 0.3 source code */ /* */ /***********************************************************************/ #include #include #include #include #include #include #include #include #include #include "i18n.h" static char *iconv_from_utf8_to_locale(const char *str, const char *fallback_string) { const char *charset; iconv_t cd; size_t nconv; char *buffer, *old_buffer; char *buffer_ptr; char *string_ptr; char *string; const size_t buffer_inc = 80; // Increment buffer size in 80 bytes step size_t buffer_size; size_t buffer_size_left; size_t string_size; // Get the current charset charset = nl_langinfo(CODESET); if(strcmp(charset, "UTF-8") == 0) return g_strdup(str); // Open iconv descriptor cd = iconv_open(charset, "UTF-8"); if (cd == (iconv_t) -1) return g_strdup(fallback_string); // Set up the buffer buffer_size = buffer_size_left = buffer_inc; buffer = (char *) malloc(buffer_size + 1); if (buffer == NULL) return g_strdup(fallback_string); buffer_ptr = buffer; string = g_strdup(str); string_ptr = string; string_size = strlen(string); // Do the conversion while (string_size != 0) { nconv = iconv(cd, &string_ptr, &string_size, &buffer_ptr, &buffer_size_left); if (nconv == (size_t) -1) { if (errno != E2BIG) // if translation error { iconv_close(cd); // close descriptor free(buffer); // free buffer free(string); return g_strdup(fallback_string); // and return fallback string } // increase buffer size buffer_size += buffer_inc; buffer_size_left = buffer_inc; old_buffer = buffer; buffer = (char *) realloc(buffer, buffer_size + 1); if (buffer == NULL) { free(string); return g_strdup(fallback_string); } buffer_ptr = (buffer_ptr - old_buffer) + buffer; } } *buffer_ptr = '\0'; iconv_close(cd); free(string); return buffer; } int i18n_printf(const char *format, ...) { char *new_format; int return_value; va_list args; new_format = iconv_from_utf8_to_locale(format, ""); if(new_format != NULL) { va_start(args, format); return_value = vprintf(new_format, args); va_end(args); free(new_format); } else return_value = 0; return return_value; } int i18n_fprintf(FILE *stream, const char *format, ...) { char *new_format; int return_value; va_list args; new_format = iconv_from_utf8_to_locale(format, ""); if(new_format != NULL) { va_start(args, format); return_value = vfprintf(stream, new_format, args); va_end(args); free(new_format); } else return_value = 0; return return_value; } void i18n_perror(const char *s) { char *conv_string; int errno_backup; errno_backup = errno; conv_string = iconv_from_utf8_to_locale(s, ""); if(conv_string != NULL) { fprintf(stderr, "%s: %s\n", conv_string, strerror_utf8(errno_backup)); free(conv_string); } } char *strerror_utf8(int errornum) { char *utf8error; utf8error = g_locale_to_utf8(strerror(errornum), -1, NULL, NULL, NULL); return utf8error; } gtkterm-1.1.1/src/i18n.h000066400000000000000000000022121376216657300147230ustar00rootroot00000000000000/***********************************************************************/ /* i18n.h */ /* ------ */ /* GTKTerm Software */ /* (c) Julien Schmitt */ /* */ /* ------------------------------------------------------------------- */ /* */ /* Purpose */ /* UTF-8 conversion to print in the console */ /* - Header file - */ /* */ /***********************************************************************/ #ifndef I18N_H_ #define I18N_H #include int i18n_printf(const char *, ...); int i18n_fprintf(FILE *, const char *, ...); void i18n_perror(const char *); char *strerror_utf8(int); #endif gtkterm-1.1.1/src/interface.c000066400000000000000000000774231376216657300161170ustar00rootroot00000000000000/***********************************************************************/ /* widgets.c */ /* --------- */ /* GTKTerm Software */ /* (c) Julien Schmitt */ /* */ /* ------------------------------------------------------------------- */ /* */ /* Purpose */ /* Functions for the management of the GUI for the main window */ /* */ /* ChangeLog */ /* (All changes by Julien Schmitt except when explicitly written) */ /* */ /* - 1.01 : The put_hexadecimal partly function rewritten. */ /* The vte_terminal_get_cursor_position function does */ /* not return always the actual column. */ /* Now it uses an internal column-index (virt_col_pos).*/ /* (Willem van den Akker) */ /* - 0.99.7 : Changed keyboard shortcuts to */ /* (Ken Peek) */ /* - 0.99.6 : Added scrollbar and copy/paste (Zach Davis) */ /* */ /* - 0.99.5 : Make package buildable on pure *BSD by changing the */ /* include to asm/termios.h by sys/ttycom.h */ /* Print message without converting it into the locale */ /* in show_message() */ /* Set backspace key binding to backspace so that the */ /* backspace works. It would even be nicer if the */ /* behaviour of this key could be configured ! */ /* - 0.99.4 : - Sebastien Bacher - */ /* Added functions for CR LF auto mode */ /* Fixed put_text() to have \r\n for the VTE Widget */ /* Rewritten put_hexadecimal() function */ /* - Julien - */ /* Modified send_serial to return the actual number of */ /* bytes written, and also only display exactly what */ /* is written */ /* - 0.99.3 : Modified to use a VTE terminal */ /* - 0.99.2 : Internationalization */ /* - 0.99.0 : \b byte now handled correctly by the ascii widget */ /* SUPPR (0x7F) also prints correctly */ /* adapted for macros */ /* modified "about" dialog */ /* - 0.98.6 : fixed possible buffer overrun in hex send */ /* new "Send break" option */ /* - 0.98.5 : icons in the menu */ /* bug fixed with local echo and hexadecimal */ /* modified hexadecimal send separator, and bug fixed */ /* - 0.98.4 : new hexadecimal display / send */ /* - 0.98.3 : put_text() modified to fit with 0x0D 0x0A */ /* - 0.98.2 : added local echo by Julien */ /* - 0.98 : file creation by Julien */ /* */ /***********************************************************************/ #include #if defined (__linux__) # include /* For control signals */ #endif #if defined (__FreeBSD__) || defined (__FreeBSD_kernel__) \ || defined (__NetBSD__) || defined (__NetBSD_kernel__) \ || defined (__OpenBSD__) || defined (__OpenBSD_kernel__) # include /* For control signals */ #endif #include #include #include #include #include "term_config.h" #include "files.h" #include "serial.h" #include "interface.h" #include "buffer.h" #include "macros.h" #include "auto_config.h" #include "logging.h" #include #include guint id; gboolean echo_on; gboolean crlfauto_on; gboolean timestamp_on = 0; GtkWidget *StatusBar; GtkWidget *signals[6]; static GtkWidget *Hex_Box; static GtkWidget *log_pause_resume_menu = NULL; static GtkWidget *log_start_menu = NULL; static GtkWidget *log_stop_menu = NULL; static GtkWidget *log_clear_menu = NULL; GtkWidget *scrolled_window; GtkWidget *Fenetre; GtkWidget *popup_menu; GtkUIManager *ui_manager; GtkAccelGroup *shortcuts; GtkActionGroup *action_group; GtkWidget *display = NULL; GtkWidget *Text; GtkTextBuffer *buffer; GtkTextIter iter; extern struct configuration_port config; /* Variables for hexadecimal display */ static gint bytes_per_line = 16; static gchar blank_data[128]; static guint total_bytes; static gboolean show_index = FALSE; guint virt_col_pos = 0; /* Local functions prototype */ void signals_send_break_callback(GtkAction *action, gpointer data); void signals_toggle_DTR_callback(GtkAction *action, gpointer data); void signals_toggle_RTS_callback(GtkAction *action, gpointer data); void signals_close_port(GtkAction *action, gpointer data); void signals_open_port(GtkAction *action, gpointer data); void help_about_callback(GtkAction *action, gpointer data); gboolean Envoie_car(GtkWidget *, GdkEventKey *, gpointer); gboolean control_signals_read(void); void echo_toggled_callback(GtkAction *action, gpointer data); void CR_LF_auto_toggled_callback(GtkAction *action, gpointer data); void timestamp_toggled_callback(GtkAction *action, gpointer data); void view_radio_callback(GtkAction *action, gpointer data); void view_hexadecimal_chars_radio_callback(GtkAction* action, gpointer data); void view_index_toggled_callback(GtkAction *action, gpointer data); void view_send_hex_toggled_callback(GtkAction *action, gpointer data); void initialize_hexadecimal_display(void); gboolean Send_Hexadecimal(GtkWidget *, GdkEventKey *, gpointer); gboolean pop_message(void); static gchar *translate_menu(const gchar *, gpointer); static void Got_Input(VteTerminal *, gchar *, guint, gpointer); void edit_copy_callback(GtkAction *action, gpointer data); void update_copy_sensivity(VteTerminal *terminal, gpointer data); void edit_paste_callback(GtkAction *action, gpointer data); void edit_select_all_callback(GtkAction *action, gpointer data); /* Menu */ const GtkActionEntry menu_entries[] = { /* Toplevel */ {"File", NULL, N_("_File")}, {"Edit", NULL, N_("_Edit")}, {"Log", NULL, N_("_Log")}, {"Configuration", NULL, N_("_Configuration")}, {"Signals", NULL, N_("Control _signals")}, {"View", NULL, N_("_View")}, {"ViewHexadecimalChars", NULL, N_("Hexadecimal _chars")}, {"Help", NULL, N_("_Help")}, /* File menu */ {"FileExit", GTK_STOCK_QUIT, NULL, "Q", NULL, gtk_main_quit}, {"ClearScreen", GTK_STOCK_CLEAR, N_("_Clear screen"), "L", NULL, G_CALLBACK(clear_buffer)}, {"ClearScrollback", GTK_STOCK_CLEAR, N_("_Clear scrollback"), "K", NULL, G_CALLBACK(clear_scrollback)}, {"SendFile", GTK_STOCK_JUMP_TO, N_("Send _RAW file"), "R", NULL, G_CALLBACK(send_raw_file)}, {"SaveFile", GTK_STOCK_SAVE_AS, N_("_Save RAW file"), "", NULL, G_CALLBACK(save_raw_file)}, /* Edit menu */ {"EditCopy", GTK_STOCK_COPY, NULL, "C", NULL, G_CALLBACK(edit_copy_callback)}, {"EditPaste", GTK_STOCK_PASTE, NULL, "V", NULL, G_CALLBACK(edit_paste_callback)}, {"EditSelectAll", GTK_STOCK_SELECT_ALL, NULL, "A", NULL, G_CALLBACK(edit_select_all_callback)}, /* Log Menu */ {"LogToFile", GTK_STOCK_MEDIA_RECORD, N_("To file..."), "", NULL, G_CALLBACK(logging_start)}, {"LogPauseResume", GTK_STOCK_MEDIA_PAUSE, NULL, "", NULL, G_CALLBACK(logging_pause_resume)}, {"LogStop", GTK_STOCK_MEDIA_STOP, NULL, "", NULL, G_CALLBACK(logging_stop)}, {"LogClear", GTK_STOCK_CLEAR, NULL, "", NULL, G_CALLBACK(logging_clear)}, /* Confuguration Menu */ {"ConfigPort", GTK_STOCK_PROPERTIES, N_("_Port"), "S", NULL, G_CALLBACK(Config_Port_Fenetre)}, {"ConfigTerminal", GTK_STOCK_PREFERENCES, N_("_Main window"), "", NULL, G_CALLBACK(Config_Terminal)}, {"Macros", NULL, N_("_Macros"), NULL, NULL, G_CALLBACK(Config_macros)}, {"SelectConfig", GTK_STOCK_OPEN, N_("_Load configuration"), "", NULL, G_CALLBACK(select_config_callback)}, {"SaveConfig", GTK_STOCK_SAVE_AS, N_("_Save configuration"), "", NULL, G_CALLBACK(save_config_callback)}, {"DeleteConfig", GTK_STOCK_DELETE, N_("_Delete configuration"), "", NULL, G_CALLBACK(delete_config_callback)}, /* Signals Menu */ {"SignalsSendBreak", NULL, N_("Send break"), "B", NULL, G_CALLBACK(signals_send_break_callback)}, {"SignalsOpenPort", GTK_STOCK_OPEN, N_("_Open Port"), "F5", NULL, G_CALLBACK(signals_open_port)}, {"SignalsClosePort", GTK_STOCK_CLOSE, N_("_Close Port"), "F6", NULL, G_CALLBACK(signals_close_port)}, {"SignalsDTR", NULL, N_("Toggle DTR"), "F7", NULL, G_CALLBACK(signals_toggle_DTR_callback)}, {"SignalsRTS", NULL, N_("Toggle RTS"), "F8", NULL, G_CALLBACK(signals_toggle_RTS_callback)}, /* About menu */ {"HelpAbout", GTK_STOCK_ABOUT, NULL, NULL, NULL, G_CALLBACK(help_about_callback)} }; const GtkToggleActionEntry menu_toggle_entries[] = { /* Configuration Menu */ {"LocalEcho", NULL, N_("Local _echo"), NULL, NULL, G_CALLBACK(echo_toggled_callback), FALSE}, {"CRLFauto", NULL, N_("_CR LF auto"), NULL, NULL, G_CALLBACK(CR_LF_auto_toggled_callback), FALSE}, {"Timestamp", NULL, N_("Timestamp"), NULL, NULL, G_CALLBACK(timestamp_toggled_callback), FALSE}, /* View Menu */ {"ViewIndex", NULL, N_("Show _index"), NULL, NULL, G_CALLBACK(view_index_toggled_callback), FALSE}, {"ViewSendHexData", NULL, N_("_Send hexadecimal data"), NULL, NULL, G_CALLBACK(view_send_hex_toggled_callback), FALSE} }; const GtkRadioActionEntry menu_view_radio_entries[] = { {"ViewASCII", NULL, N_("_ASCII"), NULL, NULL, ASCII_VIEW}, {"ViewHexadecimal", NULL, N_("_Hexadecimal"), NULL, NULL, HEXADECIMAL_VIEW} }; const GtkRadioActionEntry menu_hex_chars_length_radio_entries[] = { {"ViewHex8", NULL, "_8", NULL, NULL, 8}, {"ViewHex10", NULL, "1_0", NULL, NULL, 10}, {"ViewHex16", NULL, "_16", NULL, NULL, 16}, {"ViewHex24", NULL, "_24", NULL, NULL, 24}, {"ViewHex32", NULL, "_32", NULL, NULL, 32} }; static const char *ui_description = "" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " ""; static gchar *translate_menu(const gchar *path, gpointer data) { return _(path); } void view_send_hex_toggled_callback(GtkAction *action, gpointer data) { if(gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action))) gtk_widget_show(GTK_WIDGET(Hex_Box)); else gtk_widget_hide(GTK_WIDGET(Hex_Box)); } void view_index_toggled_callback(GtkAction *action, gpointer data) { show_index = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)); set_view(HEXADECIMAL_VIEW); } void view_hexadecimal_chars_radio_callback(GtkAction* action, gpointer data) { gint current_value; current_value = gtk_radio_action_get_current_value(GTK_RADIO_ACTION(action)); bytes_per_line = current_value; set_view(HEXADECIMAL_VIEW); } void set_view(guint type) { GtkAction *action; GtkAction *show_index_action; GtkAction *hex_chars_action; show_index_action = gtk_action_group_get_action(action_group, "ViewIndex"); hex_chars_action = gtk_action_group_get_action(action_group, "ViewHexadecimalChars"); clear_display(); set_clear_func(clear_display); switch(type) { case ASCII_VIEW: action = gtk_action_group_get_action(action_group, "ViewASCII"); gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), TRUE); gtk_action_set_sensitive(show_index_action, FALSE); gtk_action_set_sensitive(hex_chars_action, FALSE); total_bytes = 0; set_display_func(put_text); break; case HEXADECIMAL_VIEW: action = gtk_action_group_get_action(action_group, "ViewHexadecimal"); gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), TRUE); gtk_action_set_sensitive(show_index_action, TRUE); gtk_action_set_sensitive(hex_chars_action, TRUE); total_bytes = 0; virt_col_pos = 0; set_display_func(put_hexadecimal); break; default: set_display_func(NULL); } write_buffer(); } void view_radio_callback(GtkAction *action, gpointer data) { gint current_value; current_value = gtk_radio_action_get_current_value(GTK_RADIO_ACTION(action)); set_view(current_value); } void Set_local_echo(gboolean echo) { GtkAction *action; echo_on = echo; action = gtk_action_group_get_action(action_group, "LocalEcho"); if(action) gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), echo_on); } void echo_toggled_callback(GtkAction *action, gpointer data) { echo_on = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(action)); configure_echo(echo_on); } void Set_crlfauto(gboolean crlfauto) { GtkAction *action; crlfauto_on = crlfauto; action = gtk_action_group_get_action(action_group, "CRLFauto"); if(action) gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), crlfauto_on); } void CR_LF_auto_toggled_callback(GtkAction *action, gpointer data) { crlfauto_on = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(action)); configure_crlfauto(crlfauto_on); } void Set_timestamp(gboolean timestamp) { GtkAction *action; timestamp_on = timestamp; action = gtk_action_group_get_action(action_group, "Timestamp"); if(action) gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), timestamp_on); } void timestamp_toggled_callback(GtkAction *action, gpointer data) { timestamp_on = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(action)); config.timestamp = timestamp_on ? TRUE : FALSE; } void toggle_logging_pause_resume(gboolean currentlyLogging) { GtkAction *action; action = gtk_action_group_get_action(action_group, "LogPauseResume"); if (currentlyLogging) { gtk_action_set_label(action, NULL); gtk_action_set_stock_id(action, GTK_STOCK_MEDIA_PAUSE); } else { gtk_action_set_label(action, _("Resume")); gtk_action_set_stock_id(action, GTK_STOCK_MEDIA_PLAY); } } void toggle_logging_sensitivity(gboolean currentlyLogging) { GtkAction *action; action = gtk_action_group_get_action(action_group, "LogToFile"); gtk_action_set_sensitive(action, !currentlyLogging); action = gtk_action_group_get_action(action_group, "LogPauseResume"); gtk_action_set_sensitive(action, currentlyLogging); action = gtk_action_group_get_action(action_group, "LogStop"); gtk_action_set_sensitive(action, currentlyLogging); action = gtk_action_group_get_action(action_group, "LogClear"); gtk_action_set_sensitive(action, currentlyLogging); } gboolean terminal_button_press_callback(GtkWidget *widget, GdkEventButton *event, gpointer *data) { if(event->type == GDK_BUTTON_PRESS && event->button == 3 && (event->state & gtk_accelerator_get_default_mod_mask()) == 0) { gtk_menu_popup(GTK_MENU(popup_menu), NULL, NULL, NULL, NULL, event->button, event->time); return TRUE; } return FALSE; } void terminal_popup_menu_callback(GtkWidget *widget, gpointer data) { gtk_menu_popup(GTK_MENU(popup_menu), NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time()); } void create_main_window(void) { GtkWidget *menu, *main_vbox, *label; GtkWidget *hex_send_entry; GtkAccelGroup *accel_group; GError *error; Fenetre = gtk_window_new(GTK_WINDOW_TOPLEVEL); shortcuts = gtk_accel_group_new(); gtk_window_add_accel_group(GTK_WINDOW(Fenetre), GTK_ACCEL_GROUP(shortcuts)); g_signal_connect(GTK_WIDGET(Fenetre), "destroy", (GCallback)gtk_main_quit, NULL); g_signal_connect(GTK_WIDGET(Fenetre), "delete_event", (GCallback)gtk_main_quit, NULL); Set_window_title("GTKTerm"); main_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); gtk_container_add(GTK_CONTAINER(Fenetre), main_vbox); /* Create the UIManager */ ui_manager = gtk_ui_manager_new(); accel_group = gtk_ui_manager_get_accel_group (ui_manager); gtk_window_add_accel_group (GTK_WINDOW (Fenetre), accel_group); /* Create the actions */ action_group = gtk_action_group_new("MenuActions"); gtk_action_group_set_translate_func(action_group, translate_menu, NULL, NULL); gtk_action_group_add_actions(action_group, menu_entries, G_N_ELEMENTS (menu_entries), Fenetre); gtk_action_group_add_toggle_actions(action_group, menu_toggle_entries, G_N_ELEMENTS (menu_toggle_entries), Fenetre); gtk_action_group_add_radio_actions(action_group, menu_view_radio_entries, G_N_ELEMENTS (menu_view_radio_entries), -1, G_CALLBACK(view_radio_callback), Fenetre); gtk_action_group_add_radio_actions(action_group, menu_hex_chars_length_radio_entries, G_N_ELEMENTS (menu_hex_chars_length_radio_entries), 16, G_CALLBACK(view_hexadecimal_chars_radio_callback), Fenetre); gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); /* Load the UI */ error = NULL; if(!gtk_ui_manager_add_ui_from_string(ui_manager, ui_description, -1, &error)) { g_message ("building menus failed: %s", error->message); g_error_free (error); exit (EXIT_FAILURE); } menu = gtk_ui_manager_get_widget (ui_manager, "/MenuBar"); gtk_box_pack_start(GTK_BOX(main_vbox), menu, FALSE, TRUE, 0); /* create vte window */ display = vte_terminal_new(); /* set terminal properties, these could probably be made user configurable */ vte_terminal_set_scroll_on_output(VTE_TERMINAL(display), FALSE); vte_terminal_set_scroll_on_keystroke(VTE_TERMINAL(display), TRUE); vte_terminal_set_mouse_autohide(VTE_TERMINAL(display), TRUE); vte_terminal_set_backspace_binding(VTE_TERMINAL(display), VTE_ERASE_ASCII_BACKSPACE); clear_display(); /* make vte window scrollable - inspired by gnome-terminal package */ scrolled_window = gtk_scrolled_window_new(NULL, gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (display))); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window), GTK_SHADOW_NONE); gtk_container_add(GTK_CONTAINER(scrolled_window), GTK_WIDGET(display)); gtk_box_pack_start(GTK_BOX(main_vbox), scrolled_window, TRUE, TRUE, 0); g_signal_connect(G_OBJECT(display), "button-press-event", G_CALLBACK(terminal_button_press_callback), NULL); g_signal_connect(G_OBJECT(display), "popup-menu", G_CALLBACK(terminal_popup_menu_callback), NULL); g_signal_connect(G_OBJECT(display), "selection-changed", G_CALLBACK(update_copy_sensivity), NULL); update_copy_sensivity(VTE_TERMINAL(display), NULL); popup_menu = gtk_ui_manager_get_widget(ui_manager, "/PopupMenu"); /* set up logging buttons availability */ toggle_logging_pause_resume(FALSE); toggle_logging_sensitivity(FALSE); /* send hex char box (hidden when not in use) */ Hex_Box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); label = gtk_label_new(_("Hexadecimal data to send (separator : ';' or space) : ")); gtk_box_pack_start(GTK_BOX(Hex_Box), label, FALSE, FALSE, 5); hex_send_entry = gtk_entry_new(); g_signal_connect(GTK_WIDGET(hex_send_entry), "activate", (GCallback)Send_Hexadecimal, NULL); gtk_box_pack_start(GTK_BOX(Hex_Box), hex_send_entry, TRUE, TRUE, 5); gtk_box_pack_start(GTK_BOX(main_vbox), Hex_Box, FALSE, TRUE, 2); /* status bar */ StatusBar = gtk_statusbar_new(); gtk_box_pack_start(GTK_BOX(main_vbox), StatusBar, FALSE, FALSE, 0); id = gtk_statusbar_get_context_id(GTK_STATUSBAR(StatusBar), "Messages"); label = gtk_label_new("RI"); gtk_box_pack_end(GTK_BOX(StatusBar), label, FALSE, TRUE, 5); gtk_widget_set_sensitive(GTK_WIDGET(label), FALSE); signals[0] = label; label = gtk_label_new("DSR"); gtk_box_pack_end(GTK_BOX(StatusBar), label, FALSE, TRUE, 5); signals[1] = label; label = gtk_label_new("CD"); gtk_box_pack_end(GTK_BOX(StatusBar), label, FALSE, TRUE, 5); signals[2] = label; label = gtk_label_new("CTS"); gtk_box_pack_end(GTK_BOX(StatusBar), label, FALSE, TRUE, 5); signals[3] = label; label = gtk_label_new("RTS"); gtk_box_pack_end(GTK_BOX(StatusBar), label, FALSE, TRUE, 5); signals[4] = label; label = gtk_label_new("DTR"); gtk_box_pack_end(GTK_BOX(StatusBar), label, FALSE, TRUE, 5); signals[5] = label; g_signal_connect_after(GTK_WIDGET(display), "commit", G_CALLBACK(Got_Input), NULL); g_timeout_add(POLL_DELAY, (GSourceFunc)control_signals_read, NULL); gtk_window_set_default_size(GTK_WINDOW(Fenetre), 750, 550); gtk_widget_show_all(Fenetre); gtk_widget_hide(GTK_WIDGET(Hex_Box)); } void initialize_hexadecimal_display(void) { total_bytes = 0; memset(blank_data, ' ', 128); blank_data[bytes_per_line * 3 + 5] = 0; } void put_hexadecimal(gchar *string, guint size) { static gchar data[128]; static gchar data_byte[6]; static gchar buffer[128]; gint i = 0; if(size == 0) return; while(i < size) { while(gtk_events_pending()) gtk_main_iteration(); /* Print hexadecimal characters */ data[0] = 0; while(virt_col_pos < bytes_per_line && i < size) { gint avance=0; gchar ascii[1]; if(show_index) { /* First byte on line */ if(virt_col_pos == 0) { sprintf(data, "%6d: ", total_bytes); vte_terminal_feed(VTE_TERMINAL(display), data, strlen(data)); } } sprintf(data_byte, "%02X ", (guchar)string[i]); log_chars(data_byte, 3); vte_terminal_feed(VTE_TERMINAL(display), data_byte, 3); avance = (bytes_per_line - virt_col_pos) * 3 + virt_col_pos + 2; /* Move forward */ sprintf(data_byte, "%c[%dC", 27, avance); vte_terminal_feed(VTE_TERMINAL(display), data_byte, strlen(data_byte)); /* Print ascii characters */ ascii[0] = (string[i] > 0x1F) ? string[i] : '.'; vte_terminal_feed(VTE_TERMINAL(display), ascii, 1); /* Move backward */ sprintf(data_byte, "%c[%dD", 27, avance + 1); vte_terminal_feed(VTE_TERMINAL(display), data_byte, strlen(data_byte)); if(virt_col_pos == bytes_per_line / 2 - 1) vte_terminal_feed(VTE_TERMINAL(display), "- ", strlen("- ")); virt_col_pos++; i++; /* End of line ? */ if(virt_col_pos == bytes_per_line) { vte_terminal_feed(VTE_TERMINAL(display), "\r\n", 2); total_bytes += virt_col_pos; virt_col_pos = 0; } } } } void put_text(gchar *string, guint size) { log_chars(string, size); vte_terminal_feed(VTE_TERMINAL(display), string, size); } gint send_serial(gchar *string, gint len) { gint bytes_written; bytes_written = Send_chars(string, len); if(bytes_written > 0) { if(echo_on) put_chars(string, bytes_written, crlfauto_on); } return bytes_written; } static void Got_Input(VteTerminal *widget, gchar *text, guint length, gpointer ptr) { send_serial(text, length); } gboolean Envoie_car(GtkWidget *widget, GdkEventKey *event, gpointer pointer) { if(g_utf8_validate(event->string, 1, NULL)) send_serial(event->string, 1); return FALSE; } void help_about_callback(GtkAction *action, gpointer data) { gchar *authors[] = {"Julien Schimtt", "Zach Davis", "Florian Euchner", "Stephan Enderlein", "Kevin Picot", NULL}; gchar *comments_program = _("GTKTerm is a simple GTK+ terminal used to communicate with the serial port."); gchar *comments[256]; GError *error = NULL; GdkPixbuf *logo = NULL; logo = gdk_pixbuf_new_from_resource ("/org/gtk/gtkterm/gtkterm_64x64.png", &error); g_sprintf(comments, "%s\n\n%s", RELEASE_DATE, comments_program);; gtk_show_about_dialog(GTK_WINDOW(Fenetre), "program-name", "GTKTerm", "logo", logo, "version", VERSION, "comments", comments, "copyright", "Copyright © Julien Schimtt", "authors", authors, "website", "https://github.com/Jeija/gtkterm", "website-label", "https://github.com/Jeija/gtkterm", "license-type", GTK_LICENSE_LGPL_3_0, NULL); } void show_control_signals(int stat) { if(stat & TIOCM_RI) gtk_widget_set_sensitive(GTK_WIDGET(signals[0]), TRUE); else gtk_widget_set_sensitive(GTK_WIDGET(signals[0]), FALSE); if(stat & TIOCM_DSR) gtk_widget_set_sensitive(GTK_WIDGET(signals[1]), TRUE); else gtk_widget_set_sensitive(GTK_WIDGET(signals[1]), FALSE); if(stat & TIOCM_CD) gtk_widget_set_sensitive(GTK_WIDGET(signals[2]), TRUE); else gtk_widget_set_sensitive(GTK_WIDGET(signals[2]), FALSE); if(stat & TIOCM_CTS) gtk_widget_set_sensitive(GTK_WIDGET(signals[3]), TRUE); else gtk_widget_set_sensitive(GTK_WIDGET(signals[3]), FALSE); if(stat & TIOCM_RTS) gtk_widget_set_sensitive(GTK_WIDGET(signals[4]), TRUE); else gtk_widget_set_sensitive(GTK_WIDGET(signals[4]), FALSE); if(stat & TIOCM_DTR) gtk_widget_set_sensitive(GTK_WIDGET(signals[5]), TRUE); else gtk_widget_set_sensitive(GTK_WIDGET(signals[5]), FALSE); } void signals_send_break_callback(GtkAction *action, gpointer data) { sendbreak(); Put_temp_message(_("Break signal sent!"), 800); } void signals_toggle_DTR_callback(GtkAction *action, gpointer data) { Set_signals(0); } void signals_toggle_RTS_callback(GtkAction *action, gpointer data) { Set_signals(1); } void signals_close_port(GtkAction *action, gpointer data) { interface_close_port(); } void signals_open_port(GtkAction *action, gpointer data) { interface_open_port(); } gboolean control_signals_read(void) { int state; state = lis_sig(); if(state >= 0) show_control_signals(state); return TRUE; } void Set_status_message(gchar *msg) { gtk_statusbar_pop(GTK_STATUSBAR(StatusBar), id); gtk_statusbar_push(GTK_STATUSBAR(StatusBar), id, msg); } void Set_window_title(gchar *msg) { gchar* header = g_strdup_printf("GTKTerm - %s", msg); gtk_window_set_title(GTK_WINDOW(Fenetre), header); g_free(header); } void interface_open_port(void) { Config_port(); gchar *message; message = get_port_string(); Set_status_message(message); Set_window_title(message); g_free(message); } void interface_close_port(void) { Close_port(); gchar *message; message = get_port_string(); Set_status_message(message); Set_window_title(message); g_free(message); } void show_message(gchar *message, gint type_msg) { GtkWidget *Fenetre_msg; if(type_msg==MSG_ERR) { Fenetre_msg = gtk_message_dialog_new(GTK_WINDOW(Fenetre), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, message, NULL); } else if(type_msg==MSG_WRN) { Fenetre_msg = gtk_message_dialog_new(GTK_WINDOW(Fenetre), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, message, NULL); } else return; gtk_dialog_run(GTK_DIALOG(Fenetre_msg)); gtk_widget_destroy(Fenetre_msg); } gboolean Send_Hexadecimal(GtkWidget *widget, GdkEventKey *event, gpointer pointer) { guint i; gchar *text, *message, **tokens, *buff; guint scan_val; text = (gchar *)gtk_entry_get_text(GTK_ENTRY(widget)); if(strlen(text) == 0) { message = g_strdup_printf(_("0 byte(s) sent!")); Put_temp_message(message, 1500); gtk_entry_set_text(GTK_ENTRY(widget), ""); g_free(message); return FALSE; } tokens = g_strsplit_set(text, " ;", -1); buff = g_malloc(g_strv_length(tokens)); for(i = 0; tokens[i] != NULL; i++) { if(sscanf(tokens[i], "%02X", &scan_val) != 1) { Put_temp_message(_("Improper formatted hex input, 0 bytes sent!"), 1500); g_free(buff); return FALSE; } buff[i] = scan_val; } send_serial(buff, i); g_free(buff); message = g_strdup_printf(_("%d byte(s) sent!"), i); Put_temp_message(message, 2000); gtk_entry_set_text(GTK_ENTRY(widget), ""); g_strfreev(tokens); return FALSE; } void Put_temp_message(const gchar *text, gint time) { /* time in ms */ gtk_statusbar_push(GTK_STATUSBAR(StatusBar), id, text); g_timeout_add(time, (GSourceFunc)pop_message, NULL); } gboolean pop_message(void) { gtk_statusbar_pop(GTK_STATUSBAR(StatusBar), id); return FALSE; } void clear_display(void) { initialize_hexadecimal_display(); if(display) vte_terminal_reset(VTE_TERMINAL(display), TRUE, TRUE); } void edit_copy_callback(GtkAction *action, gpointer data) { vte_terminal_copy_clipboard(VTE_TERMINAL(display)); } void update_copy_sensivity(VteTerminal *terminal, gpointer data) { GtkAction *action; gboolean can_copy; can_copy = vte_terminal_get_has_selection(VTE_TERMINAL(terminal)); action = gtk_action_group_get_action(action_group, "EditCopy"); gtk_action_set_sensitive(action, can_copy); } void edit_paste_callback(GtkAction *action, gpointer data) { vte_terminal_paste_clipboard(VTE_TERMINAL(display)); } void edit_select_all_callback(GtkAction *action, gpointer data) { vte_terminal_select_all(VTE_TERMINAL(display)); } gtkterm-1.1.1/src/interface.h000066400000000000000000000033571376216657300161170ustar00rootroot00000000000000/***********************************************************************/ /* interface.h */ /* --------- */ /* GTKTerm Software */ /* (c) Julien Schmitt */ /* */ /* ------------------------------------------------------------------- */ /* */ /* Purpose */ /* Functions for the management of the GUI for the main window */ /* - Header file - */ /* */ /***********************************************************************/ #ifndef WIDGETS_H_ #define WIDGETS_H_ #define MSG_WRN 0 #define MSG_ERR 1 #define ASCII_VIEW 0 #define HEXADECIMAL_VIEW 1 void create_main_window(void); void Set_status_message(gchar *); void put_text(gchar *, guint); void put_hexadecimal(gchar *, guint); void Set_local_echo(gboolean); void show_message(gchar *, gint); void clear_display(void); void set_view(guint); gint send_serial(gchar *, gint); void Put_temp_message(const gchar *, gint); void Set_window_title(gchar *msg); void interface_close_port(void); void interface_open_port(void); void toggle_logging_pause_resume(gboolean currentlyLogging); void toggle_logging_sensitivity(gboolean currentlyLogging); extern GtkWidget *Fenetre; extern GtkWidget *StatusBar; extern guint id; extern GtkWidget *Text; extern GtkAccelGroup *shortcuts; #endif gtkterm-1.1.1/src/logging.c000066400000000000000000000105611376216657300155730ustar00rootroot00000000000000/***********************************************************************/ /* logging.h */ /* --------- */ /* GTKTerm Software */ /* (c) */ /* */ /* ------------------------------------------------------------------- */ /* */ /* Purpose */ /* Log all data that GTKTerm sees to a file */ /* */ /* ChangeLog */ /* 0.99.7 - Logging added (Thanks to Brian Beattie) */ /* */ /***********************************************************************/ #include #include #include #include #include #include #include #include #include #include "interface.h" #include "serial.h" #include "buffer.h" #include "logging.h" #include #include #define MAX_WRITE_ATTEMPTS 5 static gboolean Logging; static gchar *LoggingFileName; static FILE *LoggingFile; static gchar *logfile_default = NULL; static gint OpenLogFile(gchar *filename) { gchar *str; // open file and start logging if(!filename || (strcmp(filename, "") == 0)) { str = g_strdup_printf(_("Filename error\n")); show_message(str, MSG_ERR); g_free(str); g_free(filename); return FALSE; } if(LoggingFile != NULL) { fclose(LoggingFile); LoggingFile = NULL; Logging = FALSE; } LoggingFileName = filename; LoggingFile = fopen(LoggingFileName, "a"); if(LoggingFile == NULL) { str = g_strdup_printf(_("Cannot open file %s: %s\n"), LoggingFileName, strerror(errno)); show_message(str, MSG_ERR); g_free(str); g_free(LoggingFileName); } else { logfile_default = g_strdup(LoggingFileName); Logging = TRUE; } return FALSE; } void logging_start(GtkAction *action, gpointer data) { GtkWidget *file_select; gint retval; file_select = gtk_file_chooser_dialog_new(_("Log file selection"), GTK_WINDOW(Fenetre), GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(file_select), TRUE); if(logfile_default != NULL) { gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(file_select), logfile_default); } retval = gtk_dialog_run(GTK_DIALOG(file_select)); if(retval == GTK_RESPONSE_OK) { OpenLogFile(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_select))); } gtk_widget_destroy(file_select); toggle_logging_sensitivity(Logging); toggle_logging_pause_resume(Logging); } void logging_clear(void) { if(LoggingFile == NULL) { return; } //Reopening with "w" will truncate the file LoggingFile = freopen(LoggingFileName, "w", LoggingFile); if (LoggingFile == NULL) { gchar *str = g_strdup_printf(_("Cannot open file %s: %s\n"), LoggingFileName, strerror(errno)); show_message(str, MSG_ERR); g_free(str); g_free(LoggingFileName); } } void logging_pause_resume(void) { if(LoggingFile == NULL) { return; } if(Logging == TRUE) { Logging = FALSE; } else { Logging = TRUE; } toggle_logging_pause_resume(Logging); } void logging_stop(void) { if(LoggingFile == NULL) { return; } fclose(LoggingFile); LoggingFile = NULL; Logging = FALSE; g_free(LoggingFileName); LoggingFileName = NULL; toggle_logging_sensitivity(Logging); toggle_logging_pause_resume(Logging); } void log_chars(gchar *chars, guint size) { guint writeAttempts = 0; guint bytesWritten = 0; /* if we are not logging exit */ if(LoggingFile == NULL || Logging == FALSE) { return; } while (bytesWritten < size) { if (writeAttempts < MAX_WRITE_ATTEMPTS) { bytesWritten += fwrite(&chars[bytesWritten], 1, size-bytesWritten, LoggingFile); } else { show_message(_("Failed to log data\n"), MSG_ERR); return; } } fflush(LoggingFile); } gtkterm-1.1.1/src/logging.h000066400000000000000000000021551376216657300156000ustar00rootroot00000000000000/***********************************************************************/ /* logging.h */ /* --------- */ /* GTKTerm Software */ /* (c) */ /* */ /* ------------------------------------------------------------------- */ /* */ /* Purpose */ /* Log all data that GTKTerm sees to a file */ /* - Header File - */ /***********************************************************************/ #ifndef LOGGING_H_ #define LOGGING_H_ void logging_start(GtkAction *action, gpointer data); void logging_pause_resume(void); void logging_stop(void); void logging_clear(void); void log_chars(gchar *chars, guint size); #endif /* LOGGING_H_ */ gtkterm-1.1.1/src/macros.c000066400000000000000000000326001376216657300154270ustar00rootroot00000000000000/***********************************************************************/ /* macros.c */ /* -------- */ /* GTKTerm Software */ /* (c) Julien Schmitt */ /* */ /* ------------------------------------------------------------------- */ /* */ /* Purpose */ /* Functions for the management of the macros */ /* */ /* ChangeLog */ /* - 0.99.2 : Internationalization */ /* - 0.99.0 : file creation by Julien */ /* */ /***********************************************************************/ #include #include #include #include #include #include #include "interface.h" #include "macros.h" #include #include enum { COLUMN_SHORTCUT, COLUMN_ACTION, NUM_COLUMNS }; macro_t *macros = NULL; static GtkWidget *window = NULL; macro_t *get_shortcuts(gint *size) { gint i = 0; if(macros != NULL) { while(macros[i].shortcut != NULL) i++; } *size = i; return macros; } static void shortcut_callback(gpointer *number) { gchar *string; gchar *str; gint i, length; guchar a; guint val_read; string = macros[(long)number].action; length = strlen(string); for(i = 0; i < length; i++) { if(string[i] == '\\') { if(g_unichar_isdigit((gunichar)string[i + 1])) { if((string[i + 1] == '0') && (string[i + 2] != 0)) { if(g_unichar_isxdigit((gunichar)string[i + 3])) { str = &string[i + 2]; i += 3; } else { str = &string[i + 1]; if(g_unichar_isxdigit((gunichar)string[i + 2])) i += 2; else i++; } } else { str = &string[i + 1]; if(g_unichar_isxdigit((gunichar)string[i + 2])) i += 2; else i++; } if(sscanf(str, "%02X", &val_read) == 1) a = (guchar)val_read; else a = '\\'; } else { switch(string[i + 1]) { case 'a': a = '\a'; break; case 'b': a = '\b'; break; case 't': a = '\t'; break; case 'n': a = '\n'; break; case 'v': a = '\v'; break; case 'f': a = '\f'; break; case 'r': a = '\r'; break; case '\\': a = '\\'; break; default: a = '\\'; i--; break; } i++; } send_serial((gchar*)&a, 1); } else { send_serial(&string[i], 1); } } str = g_strdup_printf(_("Macro \"%s\" sent !"), macros[(long)number].shortcut); Put_temp_message(str, 800); g_free(str); } void create_shortcuts(macro_t *macro, gint size) { macros = g_malloc((size + 1) * sizeof(macro_t)); if(macros != NULL) { memcpy(macros, macro, size * sizeof(macro_t)); macros[size].shortcut = NULL; macros[size].action = NULL; } else perror("malloc"); } void add_shortcuts(void) { long i = 0; guint acc_key; GdkModifierType mod; if(macros == NULL) return; while(macros[i].shortcut != NULL) { macros[i].closure = g_cclosure_new_swap(G_CALLBACK(shortcut_callback), (gpointer)i, NULL); gtk_accelerator_parse(macros[i].shortcut, &acc_key, &mod); if(acc_key != 0) gtk_accel_group_connect(shortcuts, acc_key, mod, GTK_ACCEL_MASK, macros[i].closure); i++; } } static void macros_destroy(void) { gint i = 0; if(macros == NULL) return; while(macros[i].shortcut != NULL) { g_free(macros[i].shortcut); g_free(macros[i].action); /* g_closure_unref(macros[i].closure); */ i++; } g_free(macros); macros = NULL; } void remove_shortcuts(void) { gint i = 0; if(macros == NULL) return; while(macros[i].shortcut != NULL) { gtk_accel_group_disconnect(shortcuts, macros[i].closure); i++; } macros_destroy(); } static GtkTreeModel *create_model(void) { gint i = 0; GtkListStore *store; GtkTreeIter iter; /* create list store */ store = gtk_list_store_new (NUM_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN); /* add data to the list store */ if(macros != NULL) { while(1) { if(macros[i].shortcut == NULL) break; gtk_list_store_append (store, &iter); gtk_list_store_set (store, &iter, COLUMN_SHORTCUT, macros[i].shortcut, COLUMN_ACTION, macros[i].action, -1); i++; } } return GTK_TREE_MODEL(store); } static gboolean shortcut_edited (GtkCellRendererText *cell, const gchar *path_string, const gchar *new_text, gpointer data) { GtkTreeModel *model = (GtkTreeModel *)data; GtkTreePath *path = gtk_tree_path_new_from_string (path_string); GtkTreeIter iter; gtk_tree_model_get_iter(model, &iter, path); gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_ACTION, new_text, -1); gtk_tree_path_free (path); return TRUE; } static void add_columns (GtkTreeView *treeview) { GtkCellRenderer *renderer; GtkTreeViewColumn *column; GtkTreeModel *model = gtk_tree_view_get_model (treeview); renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes (_("Shortcut"), renderer, "text", COLUMN_SHORTCUT, NULL); gtk_tree_view_column_set_sort_column_id (column, COLUMN_SHORTCUT); gtk_tree_view_append_column (treeview, column); renderer = gtk_cell_renderer_text_new (); g_signal_connect (renderer, "edited", G_CALLBACK(shortcut_edited), model); column = gtk_tree_view_column_new_with_attributes ("Action", renderer, "text", COLUMN_ACTION, NULL); g_object_set(G_OBJECT(renderer), "editable", TRUE, NULL); gtk_tree_view_column_set_sort_column_id (column, COLUMN_ACTION); gtk_tree_view_append_column (treeview, column); } static gint Add_shortcut(GtkWidget *button, gpointer pointer) { GtkTreeIter iter; GtkTreeModel *model = (GtkTreeModel *)pointer; gtk_list_store_append(GTK_LIST_STORE(model), &iter); gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_SHORTCUT, "None", -1); return FALSE; } static gboolean Delete_shortcut(GtkWidget *button, gpointer pointer) { GtkTreeIter iter; GtkTreeView *treeview = (GtkTreeView *)pointer; GtkTreeModel *model = gtk_tree_view_get_model (treeview); GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview); if (gtk_tree_selection_get_selected (selection, NULL, &iter)) { gint i; GtkTreePath *path; path = gtk_tree_model_get_path(model, &iter); i = gtk_tree_path_get_indices(path)[0]; gtk_list_store_remove (GTK_LIST_STORE (model), &iter); gtk_tree_path_free (path); } return FALSE; } static gboolean Save_shortcuts(GtkWidget *button, gpointer pointer) { GtkTreeIter iter; GtkTreeView *treeview = (GtkTreeView *)pointer; GtkTreeModel *model = gtk_tree_view_get_model (treeview); gint i = 0; remove_shortcuts(); if(gtk_tree_model_get_iter_first(model, &iter)) { do { i++; } while(gtk_tree_model_iter_next(model, &iter)); gtk_tree_model_get_iter_first(model, &iter); macros = g_malloc((i + 1) * sizeof(macro_t)); i = 0; if(macros != NULL) { do { gtk_tree_model_get(model, &iter, COLUMN_SHORTCUT, &(macros[i].shortcut), \ COLUMN_ACTION, &(macros[i].action), \ -1); i++; } while(gtk_tree_model_iter_next(model, &iter)); macros[i].shortcut = NULL; macros[i].action = NULL; } } add_shortcuts(); return FALSE; } static gboolean key_pressed(GtkWidget *window, GdkEventKey *key, gpointer pointer) { GtkTreeIter iter; GtkTreeView *treeview = (GtkTreeView *)pointer; GtkTreeModel *model = gtk_tree_view_get_model (treeview); GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview); gchar *str = NULL; switch(key->keyval) { case GDK_KEY_Shift_L: case GDK_KEY_Shift_R: case GDK_KEY_Control_L: case GDK_KEY_Control_R: case GDK_KEY_Caps_Lock: case GDK_KEY_Shift_Lock: case GDK_KEY_Meta_L: case GDK_KEY_Meta_R: case GDK_KEY_Alt_L: case GDK_KEY_Alt_R: case GDK_KEY_Super_L: case GDK_KEY_Super_R: case GDK_KEY_Hyper_L: case GDK_KEY_Hyper_R: case GDK_KEY_Mode_switch: return FALSE; default: break; } if(gtk_tree_selection_get_selected(selection, NULL, &iter)) { gint i; GtkTreePath *path; path = gtk_tree_model_get_path(model, &iter); i = gtk_tree_path_get_indices(path)[0]; str = gtk_accelerator_name(key->keyval, key->state & ~GDK_MOD2_MASK); gtk_list_store_set(GTK_LIST_STORE (model), &iter, COLUMN_SHORTCUT, str, -1); gtk_tree_path_free(path); g_free(str); g_signal_handlers_disconnect_by_func(window, G_CALLBACK(key_pressed), pointer); } return FALSE; } static gboolean Capture_shortcut(GtkWidget *button, gpointer pointer) { g_signal_connect_after(window, "key_press_event", G_CALLBACK(key_pressed), pointer); return FALSE; } static gboolean Help_screen(GtkWidget *button, gpointer pointer) { GtkWidget *Dialog; Dialog = gtk_message_dialog_new(pointer, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, _("The \"action\" field of a macro is the data to be sent on the port. Text can be entered, but also special chars, like \\n, \\t, \\r, etc. You can also enter hexadecimal data preceded by a '\\'. The hexadecimal data should not begin with a letter (eg. use \\0FF and not \\FF)\nExamples :\n\t\"Hello\\n\" sends \"Hello\" followed by a Line Feed\n\t\"Hello\\0A\" does the same thing but the LF is entered in hexadecimal")); gtk_dialog_run(GTK_DIALOG (Dialog)); gtk_widget_destroy(Dialog); return FALSE; } void Config_macros(GtkAction *action, gpointer data) { GtkWidget *vbox, *hbox; GtkWidget *sw; GtkTreeModel *model; GtkWidget *treeview; GtkWidget *button; GtkWidget *separator; /* create window, etc */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_set_title (GTK_WINDOW (window), _("Configure Macros")); g_signal_connect (window, "destroy", G_CALLBACK (gtk_widget_destroyed), &window); gtk_container_set_border_width (GTK_CONTAINER (window), 8); vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 8); gtk_container_add (GTK_CONTAINER (window), vbox); sw = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_ETCHED_IN); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0); /* create tree model */ model = create_model (); /* create tree view */ treeview = gtk_tree_view_new_with_model (model); gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (treeview), TRUE); gtk_tree_view_set_search_column (GTK_TREE_VIEW (treeview), COLUMN_SHORTCUT); g_object_unref (model); gtk_container_add (GTK_CONTAINER (sw), treeview); /* add columns to the tree view */ add_columns (GTK_TREE_VIEW (treeview)); hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4); gtk_box_set_homogeneous (GTK_BOX (hbox), TRUE); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); button = gtk_button_new_with_mnemonic (_("_Add")); g_signal_connect(button, "clicked", G_CALLBACK(Add_shortcut), (gpointer)model); gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0); button = gtk_button_new_with_mnemonic (_("_Delete")); g_signal_connect(button, "clicked", G_CALLBACK(Delete_shortcut), (gpointer)treeview); gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0); button = gtk_button_new_with_mnemonic (_("_Capture Shortcut")); g_signal_connect(button, "clicked", G_CALLBACK(Capture_shortcut), (gpointer)treeview); gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0); separator = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL); gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, TRUE, 0); hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4); gtk_box_set_homogeneous (GTK_BOX (hbox), TRUE); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); button = gtk_button_new_from_stock (GTK_STOCK_HELP); g_signal_connect(button, "clicked", G_CALLBACK(Help_screen), (gpointer)window); gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0); button = gtk_button_new_from_stock (GTK_STOCK_OK); g_signal_connect(button, "clicked", G_CALLBACK(Save_shortcuts), (gpointer)treeview); g_signal_connect_swapped(button, "clicked", G_CALLBACK(gtk_widget_destroy), (gpointer)window); gtk_box_pack_end (GTK_BOX (hbox), button, TRUE, TRUE, 0); button = gtk_button_new_from_stock (GTK_STOCK_CANCEL); g_signal_connect_swapped(button, "clicked", G_CALLBACK(gtk_widget_destroy), (gpointer)window); gtk_box_pack_end (GTK_BOX (hbox), button, TRUE, TRUE, 0); gtk_window_set_default_size (GTK_WINDOW(window), 300, 400); gtk_widget_show_all(window); } gtkterm-1.1.1/src/macros.h000066400000000000000000000023701376216657300154350ustar00rootroot00000000000000/***********************************************************************/ /* macros.h */ /* -------- */ /* GTKTerm Software */ /* (c) Julien Schmitt */ /* */ /* ------------------------------------------------------------------- */ /* */ /* Purpose */ /* Functions for the management of the macros */ /* - Header file - */ /* */ /***********************************************************************/ #ifndef MACROS_H_ #define MACROS_H_ typedef struct { gchar *shortcut; gchar *action; GClosure *closure; } macro_t; void Config_macros(GtkAction *action, gpointer data); void remove_shortcuts(void); void add_shortcuts(void); void create_shortcuts(macro_t *, gint); macro_t *get_shortcuts(gint *); #endif gtkterm-1.1.1/src/meson.build000066400000000000000000000010371376216657300161410ustar00rootroot00000000000000sources = [ 'buffer.c', 'buffer.h', 'cmdline.c', 'cmdline.h', 'device_monitor.c', 'device_monitor.h', 'files.c', 'files.h', 'gtkterm.c', 'i18n.c', 'i18n.h', 'interface.c', 'interface.h', 'logging.c', 'logging.h', 'macros.c', 'macros.h', 'parsecfg.c', 'parsecfg.h', 'serial.c', 'serial.h', 'term_config.c', 'term_config.h', 'user_signals.c', 'user_signals.h', gresources ] executable( 'gtkterm', sources, export_dynamic : true, dependencies : [ gtk_deps, vte_deps, config, gudev_deps ], install : true ) gtkterm-1.1.1/src/parsecfg.c000066400000000000000000001230221376216657300157340ustar00rootroot00000000000000/**************************************************************************/ /* */ /* parsecfg - a library for parsing a configuration file */ /* Copyright (C) 1999-2001 Yuuki NINOMIYA */ /* */ /* This program is free software; you can redistribute it and/or modify */ /* it under the terms of the GNU General Public License as published by */ /* the Free Software Foundation; either version 2, or (at your option) */ /* any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the */ /* Free Software Foundation, Inc., 59 Temple Place - Suite 330, */ /* Boston, MA 02111-1307, USA. */ /* */ /**************************************************************************/ /* $Id: parsecfg.c,v 1.15 2001/06/27 15:24:00 gm Exp $ */ /* #ifdef HAVE_CONFIG_H # include "config.h" #endif */ #include #include #include #include #include #include #include "parsecfg.h" #include "i18n.h" #include #include /* proto type declaration of private functions */ static void cfgFatalFunc(cfgErrorCode, const char *, int, const char *); static void (*cfgFatal) (cfgErrorCode, const char *, int, const char *) = cfgFatalFunc; /* default error handler */ static int parse_simple(const char *file, FILE *fp, char *ptr, cfgStruct cfg[], int *line); static int parse_values_between_braces(const char *file, FILE *fp, const char *parameter, cfgStruct cfg[], int *line, cfgFileType type, int section, const char *parameter_buf, int parameter_line); static char *parse_word(char *ptr, char **word, cfgKeywordValue word_type); static int store_value(cfgStruct cfg[], const char *parameter, const char *value, cfgFileType type, int section); static int parse_ini(const char *file, FILE *fp, char *ptr, cfgStruct cfg[], int *line, int *section); static int alloc_for_new_section(cfgStruct cfg[], int *section); static char *get_single_line_without_first_spaces(FILE *fp, char **gotstr, int *line); static char *rm_first_spaces(char *ptr); static char *dynamic_fgets(FILE *fp); static int dump_simple(FILE *fp, cfgStruct cfg[], cfgFileType type); static int dump_ini(FILE *fp, cfgStruct cfg[], cfgFileType type, int max); static void single_or_double_quote(const char *str, char *ret); static int fetch_simple(const char *file, FILE *fp, char *parameter_name, void *result_value, cfgValueType value_type); static int fetch_ini(const char *file, FILE *fp, char *parameter_name, void *result_value, cfgValueType value_type, int section_num, const char *section_name); /* static variables */ static char **parsecfg_section_name = NULL; static int parsecfg_maximum_section; /*************************************************************/ /* PUBLIC FUCNCTIONS */ /*************************************************************/ /* -------------------------------------------------- NAME cfgSetFatalFunc FUNCTION handle new error handler INPUT f ... pointer to new error handler OUTPUT none -------------------------------------------------- */ void cfgSetFatalFunc(void (*f) (cfgErrorCode, const char *, int, const char *)) { cfgFatal = f; } /* -------------------------------------------------- NAME cfgParse FUNCTION parse a configuration file (main function) INPUT file ... name of the configuration file cfg .... array of possible variables type ... type of the configuration file + CFG_SIMPLE .. simple 1:1 + CFG_INI ..... Windows INI-like file OUTPUT the maximum number of sections (if type==CFG_INI then return 0) -1 if an error occured -------------------------------------------------- */ int cfgParse(const char *file, cfgStruct cfg[], cfgFileType type) { char *line_buf; char *ptr; int line = 0; FILE *fp; int error_code; int max_cfg = -1; fp = fopen(file, "r"); if (fp == NULL) { cfgFatal(CFG_OPEN_FAIL, file, 0, NULL); return (-1); } while ((ptr = get_single_line_without_first_spaces(fp, &line_buf, &line)) != NULL) { switch (type) { case CFG_SIMPLE: if ((error_code = parse_simple(file, fp, ptr, cfg, &line)) != CFG_NO_ERROR) { fclose(fp); cfgFatal(error_code, file, line, line_buf); return (-1); } break; case CFG_INI: if ((error_code = parse_ini(file, fp, ptr, cfg, &line, &max_cfg)) != CFG_NO_ERROR) { fclose(fp); cfgFatal(error_code, file, line, line_buf); return (-1); } break; default: fclose(fp); cfgFatal(CFG_INTERNAL_ERROR, file, 0, NULL); return (-1); } free(line_buf); } fclose(fp); parsecfg_maximum_section = max_cfg + 1; return (parsecfg_maximum_section); } /* -------------------------------------------------- NAME cfgDump FUNCTION write configuration data to a file INPUT file ... name of the configuration file cfg .... array of possible variables type ... type of the configuration file + CFG_SIMPLE .. simple 1:1 + CFG_INI ..... Windows INI-like file max_section ... the maximum number of sections (if type is CFG_INI, this arg is ignored) OUTPUT 0 on success and -1 on error -------------------------------------------------- */ int cfgDump(const char *file, cfgStruct cfg[], cfgFileType type, int max_section) { FILE *fp; int retcode; fp = fopen(file, "w"); if (fp == NULL) { cfgFatal(CFG_CREATE_FAIL, file, 0, NULL); return (-1); } switch (type) { case CFG_SIMPLE: retcode = dump_simple(fp, cfg, type); break; case CFG_INI: retcode = dump_ini(fp, cfg, type, max_section); break; default: fclose(fp); cfgFatal(CFG_INTERNAL_ERROR, file, 0, NULL); return (-1); } fclose(fp); return (retcode); } /* -------------------------------------------------- NAME fetchVarFromCfgFile FUNCTION fetch specified variable from configuration file INPUT file ... name of the configuration file parameter_name ... parameter name to fetch result_value ... stored result value_type ... type of variable file_type ... type of the configuration file + CFG_SIMPLE .. simple 1:1 + CFG_INI ..... Windows INI-like file section_num ... section number (for file_type==CFG_INI) section_name ... section name (use this if section_num<1) OUTPUT return 0 if successful, -1 otherwise -------------------------------------------------- */ int fetchVarFromCfgFile(const char *file, char *parameter_name, void *result_value, cfgValueType value_type, cfgFileType file_type, int section_num, const char *section_name) { FILE *fp; fp = fopen(file, "r"); if (fp == NULL) { cfgFatal(CFG_OPEN_FAIL, file, 0, NULL); return (-1); } switch (file_type) { case CFG_SIMPLE: if (fetch_simple(file, fp, parameter_name, result_value, value_type) == 0) { fclose(fp); return (0); } break; case CFG_INI: if (fetch_ini(file, fp, parameter_name, result_value, value_type, section_num, section_name) == 0) { fclose(fp); return (0); } break; default: fclose(fp); cfgFatal(CFG_INTERNAL_ERROR, file, 0, NULL); return (-1); } fclose(fp); return (-1); } /* -------------------------------------------------- NAME cfgSectionNameToNumber FUNCTION convert section name to number INPUT name ... section name OUTPUT section number (0,1,2,...) if no matching, return -1 -------------------------------------------------- */ int cfgSectionNameToNumber(const char *name) { int i; for (i = 0; i < parsecfg_maximum_section; i++) { if (strcasecmp(name, parsecfg_section_name[i]) == 0) { return (i); } } return (-1); } /* -------------------------------------------------- NAME cfgSectionNumberToName FUNCTION convert section number to name INPUT num ... section number (0,1,2,...) OUTPUT pointer to section name if no section, return NULL -------------------------------------------------- */ char *cfgSectionNumberToName(int num) { if (num > parsecfg_maximum_section - 1 || num < 0) { return (NULL); } return (parsecfg_section_name[num]); } /* -------------------------------------------------- NAME cfgAllocForNewSection FUNCTION allocate memory for new section INPUT cfg ... array of possible variables name .. name of new section OUTPUT the maximum number of sections -1 if an error occured -------------------------------------------------- */ int cfgAllocForNewSection(cfgStruct cfg[], const char *name) { int result; int section; section = parsecfg_maximum_section - 1; result = alloc_for_new_section(cfg, §ion); if (result != CFG_NO_ERROR) { cfgFatalFunc(result, "unknown", 0, ""); return (-1); } parsecfg_maximum_section = section + 1; parsecfg_section_name = realloc(parsecfg_section_name, sizeof(char *) * parsecfg_maximum_section); parsecfg_section_name[parsecfg_maximum_section - 1] = strdup(name); return (parsecfg_maximum_section); } /* -------------------------------------------------- NAME cfgStoreValue FUNCTION store the value according to cfg INPUT cfg ......... array of possible variables parameter ... parameter value ....... value type ........ type of the configuration file section ..... section number (0,1,2,...) OUTPUT return 0 if successful, -1 otherwise -------------------------------------------------- */ int cfgStoreValue(cfgStruct cfg[], const char *parameter, const char *value, cfgFileType type, int section) { int result; result = store_value(cfg, parameter, value, type, section); if (result != CFG_NO_ERROR) { cfgFatalFunc(result, "unknown", 0, ""); return (-1); } return (0); } /*************************************************************/ /* PRIVATE FUCNCTIONS */ /*************************************************************/ /* -------------------------------------------------- NAME cfgFatalFunc FUNCTION error handler INPUT error_code ... reason of error file ......... the configuration file line ......... line number causing error str .......... strings at above line OUTPUT none -------------------------------------------------- */ static void cfgFatalFunc(cfgErrorCode error_code, const char *file, int line, const char *str) { switch (error_code) { case CFG_OPEN_FAIL: i18n_fprintf(stderr, _("Cannot open configuration file `%s'.\n"), file); break; case CFG_CREATE_FAIL: i18n_fprintf(stderr, _("Cannot create configuration file `%s'.\n"), file); break; case CFG_SYNTAX_ERROR: i18n_fprintf(stderr, _("%s(%d): %s\nSyntax error\n"), file, line, str); break; case CFG_WRONG_PARAMETER: i18n_fprintf(stderr, _("%s(%d): %s\nUnrecognized parameter\n"), file, line, str); break; case CFG_INTERNAL_ERROR: i18n_fprintf(stderr, _("%s(%d): %s\nInternal error\n"), file, line, str); break; case CFG_INVALID_NUMBER: i18n_fprintf(stderr, _("%s(%d): %s\nInvalid number\n"), file, line, str); break; case CFG_OUT_OF_RANGE: i18n_fprintf(stderr, _("%s(%d): %s\nOut of range\n"), file, line, str); break; case CFG_MEM_ALLOC_FAIL: i18n_fprintf(stderr, _("%s(%d): %s\nCannot allocate memory.\n"), file, line, str); break; case CFG_BOOL_ERROR: i18n_fprintf(stderr, _("%s(%d): %s\nIt must be specified TRUE or FALSE.\n"), file, line, str); break; case CFG_USED_SECTION: i18n_fprintf(stderr, _("%s(%d): %s\nThe section name is already used.\n"), file, line, str); break; case CFG_NO_CLOSING_BRACE: i18n_fprintf(stderr, _("%s(%d)\nThere is no closing bracket.\n"), file, line); break; case CFG_JUST_RETURN_WITHOUT_MSG: break; default: i18n_fprintf(stderr, _("%s(%d): %s\nUnexplained error\n"), file, line, str); } } /* -------------------------------------------------- NAME parse_simple FUNCTION parse as simple 1:1 file INPUT file .. name of the configuration file fp .... file pointer to the configuration file ptr ... pointer of current parsing cfg ... array of possible variables line .. pointer to current working line OUTPUT error code (no error is CFG_NO_ERROR) -------------------------------------------------- */ static int parse_simple(const char *file, FILE *fp, char *ptr, cfgStruct cfg[], int *line) { char *parameter; char *parameter_buf; int parameter_line; char *value; int error_code; parameter_buf = ptr; parameter_line = *line; if ((ptr = parse_word(ptr, ¶meter, CFG_PARAMETER)) == NULL) /* malloc parameter */ { return (CFG_SYNTAX_ERROR); } if (*ptr == '{') { ptr = rm_first_spaces(ptr + 1); if (*ptr != '\0' && *ptr != '#') { free(parameter); return (CFG_SYNTAX_ERROR); } if (parse_values_between_braces(file, fp, parameter, cfg, line, CFG_SIMPLE, 0, parameter_buf, parameter_line) != CFG_NO_ERROR) { return (CFG_JUST_RETURN_WITHOUT_MSG); /* error handling has already done */ } } else { if ((ptr = parse_word(ptr, &value, CFG_VALUE)) == NULL) /* malloc value */ { free(parameter); return (CFG_SYNTAX_ERROR); } if ((error_code = store_value(cfg, parameter, value, CFG_SIMPLE, 0)) != CFG_NO_ERROR) { free(parameter); free(value); return (error_code); } free(parameter); free(value); } return (CFG_NO_ERROR); } /* -------------------------------------------------- NAME parse_word FUNCTION parse a word INPUT ptr ... pointer of current parsing word .. pointer of pointer for parsed word (dynamic allocating) word_type ... what word type parse as + CFG_PARAMETER ... parameter + CFG_VALUE ....... value + CFG_SECTION ..... section OUTPUT new current pointer (on error, return NULL) -------------------------------------------------- */ static char *parse_word(char *ptr, char **word, cfgKeywordValue word_type) { int len = 0; cfgQuote quote_flag; switch (*ptr) { case '\"': quote_flag = CFG_DOUBLE_QUOTE; ptr++; break; case '\'': quote_flag = CFG_SINGLE_QUOTE; ptr++; break; default: quote_flag = CFG_NO_QUOTE; } for (;;) { if (quote_flag == CFG_NO_QUOTE) { if (*(ptr + len) == ' ' || *(ptr + len) == '\t' || *(ptr + len) == '\0' || *(ptr + len) == '#' || (*(ptr + len) == '=' && word_type == CFG_PARAMETER) || (*(ptr + len) == ']' && word_type == CFG_SECTION)) { break; } } else if (quote_flag == CFG_DOUBLE_QUOTE) { if (*(ptr + len) == '\"') { break; } } else if (quote_flag == CFG_SINGLE_QUOTE) { if (*(ptr + len) == '\'') { break; } } if (*(ptr + len) == '\0') { return (NULL); } len++; } if ((*word = malloc(len + 1)) == NULL) { cfgFatalFunc(CFG_MEM_ALLOC_FAIL, "unknown", 0, ""); return (NULL); } strncpy(*word, ptr, len); *(*word + len) = '\0'; ptr += (len + (quote_flag == CFG_NO_QUOTE ? 0 : 1)); ptr = rm_first_spaces(ptr); switch (word_type) { case CFG_PARAMETER: if (*ptr != '=') { free(*word); return (NULL); } ptr++; ptr = rm_first_spaces(ptr); break; case CFG_VALUE: if (*ptr != '\0' && *ptr != '#') { free(*word); return (NULL); } break; case CFG_SECTION: if (*ptr != ']') { free(*word); return (NULL); } break; default: free(*word); return (NULL); } return (ptr); } /* -------------------------------------------------- NAME store_value FUNCTION store the value according to cfg INPUT cfg ......... array of possible variables parameter ... parameter value ....... value type ........ type of the configuration file section ..... section number OUTPUT error code -------------------------------------------------- */ static int store_value(cfgStruct cfg[], const char *parameter, const char *value, cfgFileType type, int section) { int num; long tmp; unsigned long utmp; float ftmp; float dtmp; char *endptr; char *strptr; cfgList *listptr; //first step is to set locale to "C" and ignoring any environment //defined locale. //this is important because when saving float numbers in config file //those are saved either as "1.0" or "1,0". When then starting //gtkterm from console or via window manager menu, different locale //could prevent processing config values correctly. //In such a case configuration not loaded at all. // //Note: locale must be set at different locations to read and write // correct values. setlocale(LC_ALL,"C"); for (num = 0; cfg[num].type != CFG_END; num++) { if (strcasecmp(parameter, cfg[num].parameterName) == 0) { errno = 0; switch (cfg[num].type) { case CFG_BOOL: if (strcasecmp(value, "TRUE") == 0 || strcasecmp(value, "YES") == 0 || strcasecmp(value, "T") == 0 || strcasecmp(value, "Y") == 0 || strcasecmp(value, "1") == 0) { if (type == CFG_INI) { *(*(int **) (cfg[num].value) + section) = 1; } else { *(int *) (cfg[num].value) = 1; } return (CFG_NO_ERROR); } else if (strcasecmp(value, "FALSE") == 0 || strcasecmp(value, "NO") == 0 || strcasecmp(value, "F") == 0 || strcasecmp(value, "N") == 0 || strcasecmp(value, "0") == 0) { if (type == CFG_INI) { *(*(int **) (cfg[num].value) + section) = 0; } else { *(int *) (cfg[num].value) = 0; } return (CFG_NO_ERROR); } return (CFG_BOOL_ERROR); case CFG_STRING: if ((strptr = malloc(strlen(value) + 1)) == NULL) { return (CFG_MEM_ALLOC_FAIL); } strcpy(strptr, value); if (type == CFG_INI) { *(*(char ***) (cfg[num].value) + section) = strptr; } else { *(char **) (cfg[num].value) = strptr; } return (CFG_NO_ERROR); case CFG_INT: tmp = strtol(value, &endptr, 0); if (*endptr) { return (CFG_INVALID_NUMBER); } if (errno == ERANGE || tmp > INT_MAX || tmp < INT_MIN) { return (CFG_OUT_OF_RANGE); } if (type == CFG_INI) { *(*(int **) (cfg[num].value) + section) = tmp; } else { *(int *) (cfg[num].value) = tmp; } return (CFG_NO_ERROR); case CFG_UINT: utmp = strtoul(value, &endptr, 0); if (*endptr) { return (CFG_INVALID_NUMBER); } if (errno == ERANGE || utmp > UINT_MAX) { return (CFG_OUT_OF_RANGE); } if (type == CFG_INI) { *(*(unsigned int **) (cfg[num].value) + section) = utmp; } else { *(unsigned int *) (cfg[num].value) = utmp; } return (CFG_NO_ERROR); case CFG_LONG: tmp = strtol(value, &endptr, 0); if (*endptr) { return (CFG_INVALID_NUMBER); } if (errno == ERANGE) { return (CFG_OUT_OF_RANGE); } if (type == CFG_INI) { *(*(long **) (cfg[num].value) + section) = tmp; } else { *(long *) (cfg[num].value) = tmp; } return (CFG_NO_ERROR); case CFG_ULONG: utmp = strtoul(value, &endptr, 0); if (*endptr) { return (CFG_INVALID_NUMBER); } if (errno == ERANGE) { return (CFG_OUT_OF_RANGE); } if (type == CFG_INI) { *(*(unsigned long **) (cfg[num].value) + section) = utmp; } else { *(unsigned long *) (cfg[num].value) = utmp; } return (CFG_NO_ERROR); case CFG_STRING_LIST: if (type == CFG_INI) { listptr = *(*(cfgList ***) (cfg[num].value) + section); } else { listptr = *(cfgList **) (cfg[num].value); } if (listptr != NULL) { while (listptr->next != NULL) { listptr = listptr->next; } if ((listptr = listptr->next = malloc(sizeof(cfgList))) == NULL) { return (CFG_MEM_ALLOC_FAIL); } } else { if ((listptr = malloc(sizeof(cfgList))) == NULL) { return (CFG_MEM_ALLOC_FAIL); } if (type == CFG_INI) { *(*(cfgList ***) (cfg[num].value) + section) = listptr; } else { *(cfgList **) (cfg[num].value) = listptr; } } if ((strptr = malloc(strlen(value) + 1)) == NULL) { return (CFG_MEM_ALLOC_FAIL); } strcpy(strptr, value); listptr->str = strptr; listptr->next = NULL; return (CFG_NO_ERROR); case CFG_FLOAT: ftmp = strtod(value, &endptr); if (*endptr) { return (CFG_INVALID_NUMBER); } if (errno == ERANGE) { return (CFG_OUT_OF_RANGE); } if (type == CFG_INI) { *(*(float **) (cfg[num].value) + section) = ftmp; } else { *(float *) (cfg[num].value) = ftmp; } return (CFG_NO_ERROR); case CFG_DOUBLE: dtmp = strtod(value, &endptr); if (*endptr) { return (CFG_INVALID_NUMBER); } if (errno == ERANGE) { return (CFG_OUT_OF_RANGE); } if (type == CFG_INI) { *(*(double **) (cfg[num].value) + section) = dtmp; } else { *(double *) (cfg[num].value) = dtmp; } return (CFG_NO_ERROR); default: return (CFG_INTERNAL_ERROR); } } } return (CFG_WRONG_PARAMETER); } /* -------------------------------------------------- NAME parse_values_between_braces FUNCTION parse values between braces INPUT file ....... file name fp ......... file pointer to the configuration file parameter .. parameter cfg ........ array of possible variables line ....... pointer to current working line type ....... file type section .... section number parameter_buf ... for error handling parameter_line .. for error handling OUTPUT CFG_NO_ERROR on success, CFG_JUST_RETURN_WITHOUT_MSG otherwise -------------------------------------------------- */ static int parse_values_between_braces(const char *file, FILE *fp, const char *parameter, cfgStruct cfg[], int *line, cfgFileType type, int section, const char *parameter_buf, int parameter_line) { char *line_buf; char *value; char *ptr; int error_code; while ((ptr = get_single_line_without_first_spaces(fp, &line_buf, line)) != NULL) { if (*ptr == '}') { ptr = rm_first_spaces(ptr + 1); if (*ptr != '\0' && *ptr != '#') { cfgFatal(CFG_SYNTAX_ERROR, file, *line, line_buf); return (CFG_JUST_RETURN_WITHOUT_MSG); } free(line_buf); return (CFG_NO_ERROR); } if (parse_word(ptr, &value, CFG_VALUE) == NULL) { cfgFatal(CFG_SYNTAX_ERROR, file, *line, line_buf); return (CFG_JUST_RETURN_WITHOUT_MSG); } if ((error_code = store_value(cfg, parameter, value, type, section)) != CFG_NO_ERROR) { if (error_code == CFG_WRONG_PARAMETER) { cfgFatal(error_code, file, parameter_line, parameter_buf); return (CFG_JUST_RETURN_WITHOUT_MSG); } cfgFatal(error_code, file, *line, line_buf); return (CFG_JUST_RETURN_WITHOUT_MSG); } free(line_buf); free(value); } cfgFatal(CFG_NO_CLOSING_BRACE, file, *line, NULL); return (CFG_JUST_RETURN_WITHOUT_MSG); } /* -------------------------------------------------- NAME parse_ini FUNCTION parse the configuration file as Windows INI-like file INPUT file .. name of the configuration file fp .... file pointer to the configuration file ptr ... pointer of current parsing strings cfg ... array of possible variables line .. pointer to current working line number section ... pointer to current section number OUTPUT error code (no error is CFG_NO_ERROR) -------------------------------------------------- */ static int parse_ini(const char *file, FILE *fp, char *ptr, cfgStruct cfg[], int *line, int *section) { char *parameter; char *parameter_buf; int parameter_line; char *value; int error_code; int i; if (*ptr == '[') { if ((error_code = alloc_for_new_section(cfg, section)) != CFG_NO_ERROR) { return (error_code); } ptr = rm_first_spaces(ptr + 1); parsecfg_section_name = realloc(parsecfg_section_name, sizeof(char *) * (*section + 1)); if ((ptr = parse_word(ptr, &parsecfg_section_name[*section], CFG_SECTION)) == NULL) { return (CFG_SYNTAX_ERROR); } for (i = 0; i < *section; i++) { if (strcasecmp(parsecfg_section_name[*section], parsecfg_section_name[i]) == 0) { return (CFG_USED_SECTION); } } ptr = rm_first_spaces(ptr + 1); if (*ptr != '\0' && *ptr != '#') { return (CFG_SYNTAX_ERROR); } return (CFG_NO_ERROR); } else if (*section == -1) { return (CFG_SYNTAX_ERROR); } parameter_buf = ptr; parameter_line = *line; if ((ptr = parse_word(ptr, ¶meter, CFG_PARAMETER)) == NULL) { return (CFG_SYNTAX_ERROR); } if (*ptr == '{') { ptr = rm_first_spaces(ptr + 1); if (*ptr != '\0' && *ptr != '#') { return (CFG_SYNTAX_ERROR); } if (parse_values_between_braces(file, fp, parameter, cfg, line, CFG_INI, *section, parameter_buf, parameter_line) != CFG_NO_ERROR) { return (CFG_JUST_RETURN_WITHOUT_MSG); /* error handling has already done */ } free(parameter); } else { if ((ptr = parse_word(ptr, &value, CFG_VALUE)) == NULL) { return (CFG_SYNTAX_ERROR); } if ((error_code = store_value(cfg, parameter, value, CFG_INI, *section)) != CFG_NO_ERROR) { return (error_code); } free(parameter); free(value); } return (CFG_NO_ERROR); } /* -------------------------------------------------- NAME alloc_for_new_section FUNCTION allocate memory for new section INPUT cfg ....... array of possible variables section ... pointer to current section number OUTPUT error code -------------------------------------------------- */ static int alloc_for_new_section(cfgStruct cfg[], int *section) { int num; void *ptr; (*section)++; for (num = 0; cfg[num].type != CFG_END; num++) { switch (cfg[num].type) { case CFG_BOOL: case CFG_INT: case CFG_UINT: if (*section == 0) { *(int **) (cfg[num].value) = NULL; } if ((ptr = realloc(*(int **) (cfg[num].value), sizeof(int) * (*section + 1))) == NULL) { return (CFG_MEM_ALLOC_FAIL); } *(int **) (cfg[num].value) = ptr; if (cfg[num].type == CFG_BOOL) { *(*((int **) (cfg[num].value)) + *section) = -1; } else { *(*((int **) (cfg[num].value)) + *section) = 0; } break; case CFG_LONG: case CFG_ULONG: if (*section == 0) { *(long **) (cfg[num].value) = NULL; } if ((ptr = realloc(*(long **) (cfg[num].value), sizeof(long) * (*section + 1))) == NULL) { return (CFG_MEM_ALLOC_FAIL); } *(long **) (cfg[num].value) = ptr; *(*((long **) (cfg[num].value)) + *section) = 0; break; case CFG_STRING: if (*section == 0) { *(char ***) (cfg[num].value) = NULL; } if ((ptr = realloc(*(char ***) (cfg[num].value), sizeof(char *) * (*section + 1))) == NULL) { return (CFG_MEM_ALLOC_FAIL); } *(char ***) (cfg[num].value) = ptr; *(*(char ***) (cfg[num].value) + *section) = NULL; break; case CFG_STRING_LIST: if (*section == 0) { *(cfgList ***) (cfg[num].value) = NULL; } if ((ptr = realloc(*(cfgList ***) (cfg[num].value), sizeof(cfgList *) * (*section + 1))) == NULL) { return (CFG_MEM_ALLOC_FAIL); } *(cfgList ***) (cfg[num].value) = ptr; *(*(cfgList ***) (cfg[num].value) + *section) = NULL; break; case CFG_FLOAT: if (*section == 0) { *(float **) (cfg[num].value) = NULL; } if ((ptr = realloc(*(float **) (cfg[num].value), sizeof(float) * (*section + 1))) == NULL) { return (CFG_MEM_ALLOC_FAIL); } *(float **) (cfg[num].value) = ptr; *(*((float **) (cfg[num].value)) + *section) = 0; break; case CFG_DOUBLE: if (*section == 0) { *(double **) (cfg[num].value) = NULL; } if ((ptr = realloc(*(double **) (cfg[num].value), sizeof(double) * (*section + 1))) == NULL) { return (CFG_MEM_ALLOC_FAIL); } *(double **) (cfg[num].value) = ptr; *(*((double **) (cfg[num].value)) + *section) = 0; break; default: return (CFG_INTERNAL_ERROR); } } return (CFG_NO_ERROR); } /* -------------------------------------------------- NAME rm_first_spaces FUNCTION remove lead-off spaces and tabs in the string INPUT ptr ... pointer to string OUTPUT new poniter after removing -------------------------------------------------- */ static char *rm_first_spaces(char *ptr) { while (*ptr == ' ' || *ptr == '\t') { ptr++; } return (ptr); } /* -------------------------------------------------- NAME get_single_line_without_first_spaces FUNCTION get a single line without lead-off spaces and tabs from file INPUT fp ....... file pointer gotptr ... pointer stored got string line ..... pointer to line number OUTPUT new pointer after removing -------------------------------------------------- */ static char *get_single_line_without_first_spaces(FILE *fp, char **gotstr, int *line) { char *ptr; for (;;) { if ((*gotstr = dynamic_fgets(fp)) == NULL) { return (NULL); } (*line)++; ptr = rm_first_spaces(*gotstr); if (*ptr != '#' && *ptr != '\0') { return (ptr); } free(*gotstr); } } /* -------------------------------------------------- NAME dynamic_fgets FUNCTION fgets with dynamic allocated memory INPUT fp ... file pointer OUTPUT pointer to got strings NULL on error -------------------------------------------------- */ static char *dynamic_fgets(FILE *fp) { char *ptr; char temp[128]; int i; ptr = malloc(1); if (ptr == NULL) { cfgFatalFunc(CFG_MEM_ALLOC_FAIL, "unknown", 0, ""); return (NULL); } *ptr = '\0'; for (i = 0;; i++) { if (fgets(temp, 128, fp) == NULL) { if (ferror(fp) != 0 || i == 0) { free(ptr); return (NULL); } return (ptr); } ptr = realloc(ptr, 127 * (i + 1) + 1); if (ptr == NULL) { cfgFatalFunc(CFG_MEM_ALLOC_FAIL, "unknown", 0, ""); return (NULL); } strcat(ptr, temp); if (strchr(temp, '\n') != NULL) { *strchr(ptr, '\n') = '\0'; return (ptr); } } } /* -------------------------------------------------- NAME dump_simple FUNCTION INPUT OUTPUT 0 on success, -1 on error -------------------------------------------------- */ static int dump_simple(FILE *fp, cfgStruct cfg[], cfgFileType type) { int i; char c[2]; cfgList *l; for (i = 0; cfg[i].type != CFG_END; i++) { switch (cfg[i].type) { case CFG_BOOL: fprintf(fp, "%s\t= %s\n", cfg[i].parameterName, (*(int *) (cfg[i].value)) ? "True" : "False"); break; case CFG_INT: fprintf(fp, "%s\t= %d\n", cfg[i].parameterName, *(int *) (cfg[i].value)); break; case CFG_UINT: fprintf(fp, "%s\t= %u\n", cfg[i].parameterName, *(unsigned int *) (cfg[i].value)); break; case CFG_LONG: fprintf(fp, "%s\t= %ld\n", cfg[i].parameterName, *(long *) (cfg[i].value)); break; case CFG_ULONG: fprintf(fp, "%s\t= %lu\n", cfg[i].parameterName, *(unsigned long *) (cfg[i].value)); break; case CFG_STRING: if (*(char **) (cfg[i].value) == NULL) { break; } single_or_double_quote(*(char **) (cfg[i].value), c); fprintf(fp, "%s\t= %s%s%s\n", cfg[i].parameterName, c, *(char **) (cfg[i].value), c); break; case CFG_STRING_LIST: for (l = *(cfgList **) (cfg[i].value); l != NULL; l = l->next) { single_or_double_quote(l->str, c); fprintf(fp, "%s\t= %s%s%s\n", cfg[i].parameterName, c, l->str, c); } break; case CFG_FLOAT: fprintf(fp, "%s\t= %f\n", cfg[i].parameterName, *(float *) (cfg[i].value)); break; case CFG_DOUBLE: fprintf(fp, "%s\t= %f\n", cfg[i].parameterName, *(double *) (cfg[i].value)); break; default: cfgFatal(CFG_INTERNAL_ERROR, "?", 0, NULL); return (-1); } } return (0); } /* -------------------------------------------------- NAME dump_ini FUNCTION INPUT OUTPUT 0 on success, -1 on error -------------------------------------------------- */ static int dump_ini(FILE *fp, cfgStruct cfg[], cfgFileType type, int max) { int i, j; char c[2]; cfgList *l; //first step is to set locale to "C" and ignoring any environment //defined locale. //this is important because when saving float numbers in config file //those are saved either as "1.0" or "1,0". When then starting //gtkterm from console or via window manager menu, different locale //could prevent processing config values correctly. //In such a case configuration not loaded at all. // //Note: locale must be set at different locations to read and write // correct values. setlocale(LC_ALL,"C"); for (j = 0; j < max; j++) { single_or_double_quote(cfgSectionNumberToName(j), c); fprintf(fp, "[%s%s%s]\n", c, cfgSectionNumberToName(j), c); for (i = 0; cfg[i].type != CFG_END; i++) { switch (cfg[i].type) { case CFG_BOOL: fprintf(fp, "%s\t= %s\n", cfg[i].parameterName, (*(int **) (cfg[i].value))[j] ? "True" : "False"); break; case CFG_INT: fprintf(fp, "%s\t= %d\n", cfg[i].parameterName, (*(int **) (cfg[i].value))[j]); break; case CFG_UINT: fprintf(fp, "%s\t= %u\n", cfg[i].parameterName, (*(unsigned int **) (cfg[i].value))[j]); break; case CFG_LONG: fprintf(fp, "%s\t= %ld\n", cfg[i].parameterName, (*(long **) (cfg[i].value))[j]); break; case CFG_ULONG: fprintf(fp, "%s\t= %lu\n", cfg[i].parameterName, (*(unsigned long **) (cfg[i].value))[j]); break; case CFG_STRING: if ((*(char ***) (cfg[i].value))[j] == NULL) { break; } single_or_double_quote((*(char ***) (cfg[i].value))[j], c); fprintf(fp, "%s\t= %s%s%s\n", cfg[i].parameterName, c, (*(char ***) (cfg[i].value))[j], c); break; case CFG_STRING_LIST: for (l = (*(cfgList ***) (cfg[i].value))[j]; l != NULL; l = l->next) { single_or_double_quote(l->str, c); fprintf(fp, "%s\t= %s%s%s\n", cfg[i].parameterName, c, l->str, c); } break; case CFG_FLOAT: fprintf(fp, "%s\t= %f\n", cfg[i].parameterName, (*(float **) (cfg[i].value))[j]); break; case CFG_DOUBLE: fprintf(fp, "%s\t= %f\n", cfg[i].parameterName, (*(double **) (cfg[i].value))[j]); break; default: cfgFatal(CFG_INTERNAL_ERROR, "?", 0, NULL); return (-1); } } fprintf(fp, "\n"); } return (0); } /* -------------------------------------------------- NAME single_or_double_quote FUNCTION INPUT OUTPUT none -------------------------------------------------- */ static void single_or_double_quote(const char *str, char *ret) { ret[1] = '\0'; if (strchr(str, '\"') != NULL) { ret[0] = '\''; } else if (strchr(str, '\'') != NULL || strchr(str, '#') != NULL || strchr(str, '\t') != NULL || strchr(str, ' ') != NULL) { ret[0] = '\"'; } else { ret[0] = '\0'; } } /* -------------------------------------------------- NAME fetch_simple FUNCTION INPUT OUTPUT 0 on success, -1 on error -------------------------------------------------- */ static int fetch_simple(const char *file, FILE *fp, char *parameter_name, void *result_value, cfgValueType value_type) { int store_flag = -1; int error_code; int line; char *line_buf; char *ptr; char *read_parameter; char *read_value; cfgStruct fetch_cfg[] = { {parameter_name, value_type, result_value}, {NULL, CFG_END, NULL} }; while ((ptr = get_single_line_without_first_spaces(fp, &line_buf, &line)) != NULL) /* malloc line_buf */ { if ((ptr = parse_word(ptr, &read_parameter, CFG_PARAMETER)) == NULL) /* malloc read_parameter */ { cfgFatal(CFG_SYNTAX_ERROR, file, line, line_buf); free(line_buf); return (-1); } if (strcasecmp(read_parameter, parameter_name) == 0) { if (*ptr == '{') { ptr = rm_first_spaces(ptr + 1); if (*ptr != '\0' && *ptr != '#') { cfgFatal(CFG_SYNTAX_ERROR, file, line, line_buf); free(line_buf); free(read_parameter); return (-1); } if (parse_values_between_braces(file, fp, parameter_name, fetch_cfg, &line, CFG_SIMPLE, 0, line_buf, line) != CFG_NO_ERROR) { free(line_buf); free(read_parameter); return (-1); } } else { if ((ptr = parse_word(ptr, &read_value, CFG_VALUE)) == NULL) /* malloc read_value */ { cfgFatal(CFG_SYNTAX_ERROR, file, line, line_buf); free(line_buf); free(read_parameter); return (-1); } if ((error_code = store_value(fetch_cfg, parameter_name, read_value, CFG_SIMPLE, 0)) != CFG_NO_ERROR) { cfgFatal(error_code, file, line, line_buf); free(read_value); free(line_buf); free(read_parameter); return (-1); } free(read_value); /* free */ } store_flag = 0; free(line_buf); } else { if (*ptr == '{') { ptr = rm_first_spaces(ptr + 1); if (*ptr != '\0' && *ptr != '#') { cfgFatal(CFG_SYNTAX_ERROR, file, line, line_buf); free(line_buf); free(read_parameter); return (-1); } free(line_buf); while ((ptr = get_single_line_without_first_spaces(fp, &line_buf, &line)) != NULL) /* malloc line_buf */ { if (*ptr == '}') { ptr = rm_first_spaces(ptr + 1); if (*ptr != '\0' && *ptr != '#') { cfgFatal(CFG_SYNTAX_ERROR, file, line, line_buf); free(line_buf); free(read_parameter); return (-1); } break; } free(line_buf); } } } free(read_parameter); } return (store_flag); } /* -------------------------------------------------- NAME fetch_ini FUNCTION INPUT OUTPUT 0 on success, -1 on error -------------------------------------------------- */ static int fetch_ini(const char *file, FILE *fp, char *parameter_name, void *result_value, cfgValueType value_type, int section_num, const char *section_name) { int store_flag = -1; int section_flag = -1; int error_code; int line; char *line_buf; char *ptr; char *read_parameter; char *read_value; char *read_section_name; int current_section_number = 0; cfgStruct fetch_cfg[] = { {parameter_name, value_type, result_value}, {NULL, CFG_END, NULL} }; while ((ptr = get_single_line_without_first_spaces(fp, &line_buf, &line)) != NULL) /* malloc line_buf */ { if (*ptr == '[') { if (section_flag == 0) { free(line_buf); return (store_flag); } ptr = rm_first_spaces(ptr + 1); if ((ptr = parse_word(ptr, &read_section_name, CFG_SECTION)) == NULL) /* malloc read_section_name */ { free(line_buf); return (CFG_SYNTAX_ERROR); } ptr = rm_first_spaces(ptr + 1); if (*ptr != '\0' && *ptr != '#') { free(line_buf); free(read_section_name); return (CFG_SYNTAX_ERROR); } current_section_number++; if ((section_num > 0 && current_section_number == section_num) || (section_num <= 0 && strcasecmp(read_section_name, section_name) == 0)) { section_flag = 0; free(line_buf); free(read_section_name); continue; } free(read_section_name); } if (section_flag == -1) { free(line_buf); continue; } if ((ptr = parse_word(ptr, &read_parameter, CFG_PARAMETER)) == NULL) /* malloc read_parameter */ { cfgFatal(CFG_SYNTAX_ERROR, file, line, line_buf); free(line_buf); return (-1); } if (strcasecmp(read_parameter, parameter_name) == 0) { if (*ptr == '{') { ptr = rm_first_spaces(ptr + 1); if (*ptr != '\0' && *ptr != '#') { cfgFatal(CFG_SYNTAX_ERROR, file, line, line_buf); free(line_buf); free(read_parameter); return (-1); } if (parse_values_between_braces(file, fp, parameter_name, fetch_cfg, &line, CFG_SIMPLE, 0, line_buf, line) != CFG_NO_ERROR) { free(line_buf); free(read_parameter); return (-1); } } else { if ((ptr = parse_word(ptr, &read_value, CFG_VALUE)) == NULL) /* malloc read_value */ { cfgFatal(CFG_SYNTAX_ERROR, file, line, line_buf); free(line_buf); free(read_parameter); return (-1); } if ((error_code = store_value(fetch_cfg, parameter_name, read_value, CFG_SIMPLE, 0)) != CFG_NO_ERROR) { cfgFatal(error_code, file, line, line_buf); free(line_buf); free(read_parameter); free(read_value); return (-1); } free(read_value); } store_flag = 0; free(line_buf); } else { if (*ptr == '{') { ptr = rm_first_spaces(ptr + 1); if (*ptr != '\0' && *ptr != '#') { cfgFatal(CFG_SYNTAX_ERROR, file, line, line_buf); free(line_buf); free(read_parameter); return (-1); } free(line_buf); while ((ptr = get_single_line_without_first_spaces(fp, &line_buf, &line)) != NULL) { if (*ptr == '}') { ptr = rm_first_spaces(ptr + 1); if (*ptr != '\0' && *ptr != '#') { cfgFatal(CFG_SYNTAX_ERROR, file, line, line_buf); free(line_buf); free(read_parameter); return (-1); } free(line_buf); break; } free(line_buf); } } } free(read_parameter); } return (store_flag); } gtkterm-1.1.1/src/parsecfg.h000066400000000000000000000067101376216657300157450ustar00rootroot00000000000000/**************************************************************************/ /* */ /* parsecfg - a library for parsing a configuration file */ /* Copyright (C) 1999-2001 Yuuki NINOMIYA */ /* */ /* This program is free software; you can redistribute it and/or modify */ /* it under the terms of the GNU General Public License as published by */ /* the Free Software Foundation; either version 2, or (at your option) */ /* any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the */ /* Free Software Foundation, Inc., 59 Temple Place - Suite 330, */ /* Boston, MA 02111-1307, USA. */ /* */ /**************************************************************************/ /* $Id: parsecfg.h,v 1.15 2001/02/22 12:28:50 gm Exp $ */ #ifndef PARSECFG_H_INCLUDED #define PARSECFG_H_INCLUDED #undef PARSECFG_VERSION #define PARSECFG_VERSION "3.6.7" /* error code */ typedef enum { CFG_NO_ERROR, CFG_OPEN_FAIL, CFG_CREATE_FAIL, CFG_SYNTAX_ERROR, CFG_WRONG_PARAMETER, CFG_INTERNAL_ERROR, CFG_INVALID_NUMBER, CFG_OUT_OF_RANGE, CFG_MEM_ALLOC_FAIL, CFG_BOOL_ERROR, CFG_USED_SECTION, CFG_NO_CLOSING_BRACE, CFG_JUST_RETURN_WITHOUT_MSG } cfgErrorCode; /* type of the configuration file */ typedef enum { CFG_SIMPLE, CFG_INI } cfgFileType; /* constants for recognized value types */ typedef enum { CFG_END, CFG_BOOL, CFG_STRING, CFG_INT, CFG_UINT, CFG_LONG, CFG_ULONG, CFG_STRING_LIST, CFG_FLOAT, CFG_DOUBLE } cfgValueType; typedef enum { CFG_PARAMETER, CFG_VALUE, CFG_SECTION } cfgKeywordValue; typedef enum { CFG_NO_QUOTE, CFG_SINGLE_QUOTE, CFG_DOUBLE_QUOTE } cfgQuote; typedef struct { char *parameterName; cfgValueType type; void *value; } cfgStruct; typedef struct cfgList_tag { char *str; struct cfgList_tag *next; } cfgList; /* proto type declaration of public functions */ #ifdef __cplusplus extern "C" { #endif void cfgSetFatalFunc(void (*f) (cfgErrorCode, const char *, int, const char *)); int cfgParse(const char *file, cfgStruct cfg[], cfgFileType type); int cfgDump(const char *file, cfgStruct cfg[], cfgFileType type, int max_section); int fetchVarFromCfgFile(const char *file, char *parameter_name, void *result_value, cfgValueType value_type, cfgFileType file_type, int section_num, const char *section_name); int cfgSectionNameToNumber(const char *name); char *cfgSectionNumberToName(int num); int cfgAllocForNewSection(cfgStruct cfg[], const char *name); int cfgStoreValue(cfgStruct cfg[], const char *parameter, const char *value, cfgFileType type, int section); #ifdef __cplusplus } #endif #endif /* PARSECFG_H_INCLUDED */ gtkterm-1.1.1/src/serial.c000066400000000000000000000235061376216657300154270ustar00rootroot00000000000000/***********************************************************************/ /* serie.c */ /* ------- */ /* GTKTerm Software */ /* (c) Julien Schmitt */ /* */ /* ------------------------------------------------------------------- */ /* */ /* Purpose */ /* Serial port access functions */ /* */ /* ChangeLog */ /* - 0.99.7 : Removed auto crlf stuff - (use macros instead) */ /* - 0.99.5 : changed all calls to strerror() by strerror_utf8() */ /* - 0.99.2 : Internationalization */ /* - 0.98.6 : new sendbreak() function */ /* - 0.98.1 : lockfile implementation (based on minicom) */ /* - 0.98 : removed IOChannel */ /* */ /***********************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "term_config.h" #include "serial.h" #include "interface.h" #include "files.h" #include "buffer.h" #include "i18n.h" #include #include #ifdef HAVE_LINUX_SERIAL_H #include #endif struct termios termios_save; int serial_port_fd = -1; guint callback_handler_in, callback_handler_err; gboolean callback_activated = FALSE; extern struct configuration_port config; gboolean Lis_port(GIOChannel* src, GIOCondition cond, gpointer data) { gint bytes_read; static gchar c[BUFFER_RECEPTION]; guint i; bytes_read = BUFFER_RECEPTION; while(bytes_read == BUFFER_RECEPTION) { bytes_read = read(serial_port_fd, c, BUFFER_RECEPTION); if(bytes_read > 0) { put_chars(c, bytes_read, config.crlfauto); if(config.car != -1 && waiting_for_char == TRUE) { i = 0; while(i < bytes_read) { if(c[i] == config.car) { waiting_for_char = FALSE; add_input(); i = bytes_read; } i++; } } } else if(bytes_read == -1) { if(errno != EAGAIN) perror(config.port); } } return TRUE; } gboolean io_err(GIOChannel* src, GIOCondition cond, gpointer data) { Close_port(); return TRUE; } int Send_chars(char *string, int length) { int bytes_written = 0; if(serial_port_fd == -1) return 0; /* Normally it never happens, but it is better not to segfault ;) */ if(length == 0) return 0; /* RS485 half-duplex mode ? */ if( config.flux==3 ) { /* set RTS (start to send) */ Set_signals( 1 ); if( config.rs485_rts_time_before_transmit>0 ) usleep(config.rs485_rts_time_before_transmit*1000); } bytes_written = write(serial_port_fd, string, length); /* RS485 half-duplex mode ? */ if( config.flux==3 ) { /* wait all chars are send */ tcdrain( serial_port_fd ); if( config.rs485_rts_time_after_transmit>0 ) usleep(config.rs485_rts_time_after_transmit*1000); /* reset RTS (end of send, now receiving back) */ Set_signals( 1 ); } return bytes_written; } gboolean Config_port(void) { struct termios termios_p; gchar *msg = NULL; Close_port(); serial_port_fd = open(config.port, O_RDWR | O_NOCTTY | O_NDELAY); if(serial_port_fd == -1) { msg = g_strdup_printf(_("Cannot open %s: %s\n"), config.port, strerror_utf8(errno)); show_message(msg, MSG_ERR); g_free(msg); return FALSE; } if(! config.disable_port_lock) { if(flock(serial_port_fd, LOCK_EX | LOCK_NB) == -1) { Close_port(); msg = g_strdup_printf(_("Cannot lock port! The serial port may currently be in use by another program.\n")); show_message(msg, MSG_ERR); g_free(msg); return FALSE; } } tcgetattr(serial_port_fd, &termios_p); memcpy(&termios_save, &termios_p, sizeof(struct termios)); switch(config.vitesse) { case 300: termios_p.c_cflag = B300; break; case 600: termios_p.c_cflag = B600; break; case 1200: termios_p.c_cflag = B1200; break; case 2400: termios_p.c_cflag = B2400; break; case 4800: termios_p.c_cflag = B4800; break; case 9600: termios_p.c_cflag = B9600; break; case 19200: termios_p.c_cflag = B19200; break; case 38400: termios_p.c_cflag = B38400; break; case 57600: termios_p.c_cflag = B57600; break; case 115200: termios_p.c_cflag = B115200; break; case 230400: termios_p.c_cflag = B230400; break; case 460800: termios_p.c_cflag = B460800; break; case 576000: termios_p.c_cflag = B576000; break; case 921600: termios_p.c_cflag = B921600; break; case 1000000: termios_p.c_cflag = B1000000; break; case 2000000: termios_p.c_cflag = B2000000; break; default: #ifdef HAVE_LINUX_SERIAL_H set_custom_speed(config.vitesse, serial_port_fd); termios_p.c_cflag |= B38400; #else Close_port(); msg = g_strdup_printf(_("Arbitrary baud rates not supported")); show_message(msg, MSG_ERR); g_free(msg); return FALSE; #endif } switch(config.bits) { case 5: termios_p.c_cflag |= CS5; break; case 6: termios_p.c_cflag |= CS6; break; case 7: termios_p.c_cflag |= CS7; break; case 8: termios_p.c_cflag |= CS8; break; } switch(config.parite) { case 1: termios_p.c_cflag |= PARODD | PARENB; break; case 2: termios_p.c_cflag |= PARENB; break; default: break; } if(config.stops == 2) termios_p.c_cflag |= CSTOPB; termios_p.c_cflag |= CREAD; termios_p.c_iflag = IGNPAR | IGNBRK; switch(config.flux) { case 1: termios_p.c_iflag |= IXON | IXOFF; break; case 2: termios_p.c_cflag |= CRTSCTS; break; default: termios_p.c_cflag |= CLOCAL; break; } termios_p.c_oflag = 0; termios_p.c_lflag = 0; termios_p.c_cc[VTIME] = 0; termios_p.c_cc[VMIN] = 1; tcsetattr(serial_port_fd, TCSANOW, &termios_p); tcflush(serial_port_fd, TCOFLUSH); tcflush(serial_port_fd, TCIFLUSH); callback_handler_in = g_io_add_watch_full(g_io_channel_unix_new(serial_port_fd), 10, G_IO_IN, (GIOFunc)Lis_port, NULL, NULL); callback_handler_err = g_io_add_watch_full(g_io_channel_unix_new(serial_port_fd), 10, G_IO_ERR, (GIOFunc)io_err, NULL, NULL); callback_activated = TRUE; Set_local_echo(config.echo); return TRUE; } void configure_echo(gboolean echo) { config.echo = echo; } void configure_crlfauto(gboolean crlfauto) { config.crlfauto = crlfauto; } void Close_port(void) { if(serial_port_fd != -1) { if(callback_activated == TRUE) { g_source_remove(callback_handler_in); g_source_remove(callback_handler_err); callback_activated = FALSE; } tcsetattr(serial_port_fd, TCSANOW, &termios_save); tcflush(serial_port_fd, TCOFLUSH); tcflush(serial_port_fd, TCIFLUSH); if(! config.disable_port_lock) { flock(serial_port_fd, LOCK_UN); } close(serial_port_fd); serial_port_fd = -1; } } void Set_signals(guint param) { int stat_; if(serial_port_fd == -1) return; if(ioctl(serial_port_fd, TIOCMGET, &stat_) == -1) { i18n_perror(_("Control signals read")); return; } /* DTR */ if(param == 0) { if(stat_ & TIOCM_DTR) stat_ &= ~TIOCM_DTR; else stat_ |= TIOCM_DTR; if(ioctl(serial_port_fd, TIOCMSET, &stat_) == -1) i18n_perror(_("DTR write")); } /* RTS */ else if(param == 1) { if(stat_ & TIOCM_RTS) stat_ &= ~TIOCM_RTS; else stat_ |= TIOCM_RTS; if(ioctl(serial_port_fd, TIOCMSET, &stat_) == -1) i18n_perror(_("RTS write")); } } int lis_sig(void) { static int stat = 0; int stat_read; if ( config.flux==3 ) { //reset RTS (default = receive) Set_signals( 1 ); } if(serial_port_fd != -1) { if(ioctl(serial_port_fd, TIOCMGET, &stat_read) == -1) { /* Ignore EINVAL, as some serial ports genuinely lack these lines */ /* Thanks to Elie De Brauwer on ubuntu launchpad */ if (errno != EINVAL) { i18n_perror(_("Control signals read")); Close_port(); } return -2; } if(stat_read == stat) return -1; stat = stat_read; return stat; } return -1; } void sendbreak(void) { if(serial_port_fd == -1) return; else tcsendbreak(serial_port_fd, 0); } #ifdef HAVE_LINUX_SERIAL_H gint set_custom_speed(int speed, int port_fd) { struct serial_struct ser; int arby; ioctl(port_fd, TIOCGSERIAL, &ser); ser.custom_divisor = ser.baud_base / speed; if(!(ser.custom_divisor)) ser.custom_divisor = 1; arby = ser.baud_base / ser.custom_divisor; ser.flags &= ~ASYNC_SPD_MASK; ser.flags |= ASYNC_SPD_CUST; ioctl(port_fd, TIOCSSERIAL, &ser); return 0; } #endif gchar* get_port_string(void) { gchar* msg; gchar parity; if(serial_port_fd == -1) { msg = g_strdup(_("No open port")); } else { // 0: none, 1: odd, 2: even switch(config.parite) { case 0: parity = 'N'; break; case 1: parity = 'O'; break; case 2: parity = 'E'; break; default: parity = 'N'; } /* "GtkTerm: device baud-bits-parity-stops" */ msg = g_strdup_printf("%.15s %d-%d-%c-%d", config.port, config.vitesse, config.bits, parity, config.stops ); } return msg; } gtkterm-1.1.1/src/serial.h000066400000000000000000000026671376216657300154410ustar00rootroot00000000000000/***********************************************************************/ /* serie.c */ /* ------- */ /* GTKTerm Software */ /* (c) Julien Schmitt */ /* */ /* ------------------------------------------------------------------- */ /* */ /* Purpose */ /* Serial port access functions */ /* - Header file - */ /* */ /***********************************************************************/ #ifndef SERIE_H_ #define SERIE_H_ extern int serial_port_fd; int Send_chars(char *, int); gboolean Config_port(void); void Set_signals(guint); int lis_sig(void); void Close_port(void); void configure_echo(gboolean); void configure_crlfauto(gboolean); void sendbreak(void); gint set_custom_speed(int, int); gchar* get_port_string(void); #define BUFFER_RECEPTION 8192 #define BUFFER_EMISSION 4096 #define LINE_FEED 0x0A #define POLL_DELAY 100 /* in ms (for control signals) */ #endif gtkterm-1.1.1/src/term_config.c000066400000000000000000001374461376216657300164550ustar00rootroot00000000000000/***********************************************************************/ /* config.c */ /* -------- */ /* GTKTerm Software */ /* (c) Julien Schmitt */ /* */ /* ------------------------------------------------------------------- */ /* */ /* Purpose */ /* Configuration of the serial port */ /* */ /* ChangeLog */ /* - 0.99.7 : Refactor to use newer gtk widgets */ /* Add ability to use arbitrary baud */ /* Add rs458 capability - Marc Le Douarain */ /* Remove auto cr/lf stuff - (use macros instead) */ /* - 0.99.5 : Make the combo list for the device editable */ /* - 0.99.3 : Configuration for VTE terminal */ /* - 0.99.2 : Internationalization */ /* - 0.99.1 : fixed memory management bug */ /* test if there are devices found */ /* - 0.99.0 : fixed enormous memory management bug ;-) */ /* save / read macros */ /* - 0.98.5 : font saved in configuration */ /* bug fixed in memory management */ /* combos set to non editable */ /* - 0.98.3 : configuration file */ /* - 0.98.2 : autodetect existing devices */ /* - 0.98 : added devfs devices */ /* */ /***********************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include "serial.h" #include "term_config.h" #include "interface.h" #include "parsecfg.h" #include "macros.h" #include "i18n.h" #include "config.h" #define DEVICE_NUMBERS_TO_CHECK 12 gchar *devices_to_check[] = { "/dev/ttyS%d", "/dev/tts/%d", "/dev/ttyUSB%d", "/dev/ttyACM%d", "/dev/ttyXRUSB%d", "/dev/usb/tts/%d", NULL }; /* Configuration file variables */ gchar **port; gint *speed; gint *bits; gint *stopbits; gchar **parity; gchar **flow; gint *wait_delay; gint *wait_char; gint *rts_time_before_tx; gint *rts_time_after_tx; gint *echo; gint *crlfauto; gint *timestamp; cfgList **macro_list = NULL; gchar **font; gint *block_cursor; gint *rows; gint *columns; gint *scrollback; gint *visual_bell; gfloat *foreground_red; gfloat *foreground_blue; gfloat *foreground_green; gfloat *foreground_alpha; gfloat *background_red; gfloat *background_blue; gfloat *background_green; gfloat *background_alpha; cfgStruct cfg[] = { {"port", CFG_STRING, &port}, {"speed", CFG_INT, &speed}, {"bits", CFG_INT, &bits}, {"stopbits", CFG_INT, &stopbits}, {"parity", CFG_STRING, &parity}, {"flow", CFG_STRING, &flow}, {"wait_delay", CFG_INT, &wait_delay}, {"wait_char", CFG_INT, &wait_char}, {"rs485_rts_time_before_tx", CFG_INT, &rts_time_before_tx}, {"rs485_rts_time_after_tx", CFG_INT, &rts_time_after_tx}, {"echo", CFG_BOOL, &echo}, {"crlfauto", CFG_BOOL, &crlfauto}, {"timestamp", CFG_BOOL, ×tamp}, {"font", CFG_STRING, &font}, {"macros", CFG_STRING_LIST, ¯o_list}, {"term_block_cursor", CFG_BOOL, &block_cursor}, {"term_rows", CFG_INT, &rows}, {"term_columns", CFG_INT, &columns}, {"term_scrollback", CFG_INT, &scrollback}, {"term_visual_bell", CFG_BOOL, &visual_bell}, {"term_foreground_red", CFG_FLOAT, &foreground_red}, {"term_foreground_blue", CFG_FLOAT, &foreground_blue}, {"term_foreground_green", CFG_FLOAT, &foreground_green}, {"term_foreground_alpha", CFG_FLOAT, &foreground_alpha}, {"term_background_red", CFG_FLOAT, &background_red}, {"term_background_blue", CFG_FLOAT, &background_blue}, {"term_background_green", CFG_FLOAT, &background_green}, {"term_background_alpha", CFG_FLOAT, &background_alpha}, {NULL, CFG_END, NULL} }; gchar *config_file; struct configuration_port config; display_config_t term_conf; GtkWidget *Entry; gint Grise_Degrise(GtkWidget *bouton, gpointer pointeur); void read_font_button(GtkFontButton *fontButton); void Hard_default_configuration(void); void Copy_configuration(int); static void Select_config(gchar *, void *); static void Save_config_file(void); static void load_config(GtkDialog *, gint, GtkTreeSelection *); static void delete_config(GtkDialog *, gint, GtkTreeSelection *); static void save_config(GtkDialog *, gint, GtkWidget *); static void really_save_config(GtkDialog *, gint, gpointer); static gint remove_section(gchar *, gchar *); static gboolean cursor_block(GtkSwitch *, gboolean, gpointer); static void Selec_couleur(GdkRGBA *, gfloat, gfloat, gfloat, gfloat); void config_fg_color(GtkWidget *button, gpointer data); void config_bg_color(GtkWidget *button, gpointer data); static void scrollback_set(GtkAdjustment *, gpointer); extern GtkWidget *display; void ConfigFlags(void) { Set_crlfauto(config.crlfauto); Set_timestamp(config.timestamp); } void Config_Port_Fenetre(GtkAction *action, gpointer data) { GtkWidget *Table, *Label, *Bouton_OK, *Bouton_annule, *Combo, *Dialogue, *Frame, *CheckBouton, *Spin, *Expander, *ExpanderVbox, *content_area, *action_area; static GtkWidget *Combos[10]; GList *liste = NULL; gchar *chaine = NULL; gchar **dev = NULL; GtkAdjustment *adj; struct stat my_stat; gchar *string; int i; for(dev = devices_to_check; *dev != NULL; dev++) { for(i = 0; i < DEVICE_NUMBERS_TO_CHECK; i++) { chaine = g_strdup_printf(*dev, i); if(stat(chaine, &my_stat) == 0) liste = g_list_append(liste, chaine); } } if(liste == NULL) { show_message(_("No serial devices found!\n" "\n" "Searched the following device path patterns:\n" "\t/dev/ttyS*\n\t/dev/tts/*\n\t/dev/ttyUSB*\n\t/dev/usb/tts/*\n\n" "Enter a different device path in the 'Port' box.\n"), MSG_WRN); } Dialogue = gtk_dialog_new(); content_area = gtk_dialog_get_content_area(GTK_DIALOG(Dialogue)); action_area = gtk_dialog_get_action_area(GTK_DIALOG(Dialogue)); gtk_window_set_title(GTK_WINDOW(Dialogue), _("Configuration")); gtk_window_set_resizable(GTK_WINDOW(Dialogue), FALSE); gtk_container_set_border_width(GTK_CONTAINER(content_area), 5); Frame = gtk_frame_new(_("Serial port")); gtk_box_pack_start(GTK_BOX(content_area), Frame, FALSE, TRUE, 5); Table = gtk_table_new(4, 3, FALSE); gtk_container_add(GTK_CONTAINER(Frame), Table); Label = gtk_label_new(_("Port:")); gtk_table_attach(GTK_TABLE(Table), Label, 0, 1, 0, 1, 0, 0, 10, 5); Label = gtk_label_new(_("Baud Rate:")); gtk_table_attach(GTK_TABLE(Table), Label, 1, 2, 0, 1, 0, 0, 10, 5); Label = gtk_label_new(_("Parity:")); gtk_table_attach(GTK_TABLE(Table), Label, 2, 3, 0, 1, 0, 0, 10, 5); // create the devices combo box, and add device strings Combo = gtk_combo_box_text_new_with_entry(); for(i = 0; i < g_list_length(liste); i++) { gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), g_list_nth_data(liste, i)); } // try to restore last selected port, if any if(config.port != NULL && config.port[0] != '\0') { GtkWidget *tmp_entry; tmp_entry = gtk_bin_get_child(GTK_BIN(Combo)); gtk_entry_set_text(GTK_ENTRY(tmp_entry), config.port); } else { gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), 0); } // clean up devices strings //g_list_free(liste, (GDestroyNotify)g_free); // only available in glib >= 2.28 for(i = 0; i < g_list_length(liste); i++) { g_free(g_list_nth_data(liste, i)); } g_list_free(liste); g_free(chaine); gtk_table_attach(GTK_TABLE(Table), Combo, 0, 1, 1, 2, GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 5, 5); Combos[0] = Combo; Combo = gtk_combo_box_text_new_with_entry(); gtk_entry_set_max_length(GTK_ENTRY(gtk_bin_get_child (GTK_BIN (Combo))), 10); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), "300"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), "600"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), "1200"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), "2400"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), "4800"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), "9600"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), "19200"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), "38400"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), "57600"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), "115200"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), "230400"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), "460800"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), "576000"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), "921600"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), "1000000"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), "2000000"); /* set the current choice to the previous setting */ switch(config.vitesse) { case 300: gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), 0); break; case 600: gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), 1); break; case 1200: gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), 2); break; case 2400: gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), 3); break; case 4800: gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), 4); break; case 9600: gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), 5); break; case 19200: gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), 6); break; case 38400: gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), 7); break; case 57600: gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), 8); break; case 115200: gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), 9); break; case 230400: gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), 10); break; case 460800: gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), 11); break; case 576000: gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), 12); break; case 921600: gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), 13); break; case 1000000: gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), 14); break; case 2000000: gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), 15); break; case 0: /* no previous setting, use a default */ gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), 5); default: /* custom baudrate */ string = g_strdup_printf("%d", config.vitesse); gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child (GTK_BIN (Combo))), string); g_free(string); } //validate input text (digits only) g_signal_connect(GTK_ENTRY(gtk_bin_get_child (GTK_BIN (Combo))), "insert-text", G_CALLBACK(check_text_input), isdigit); gtk_table_attach(GTK_TABLE(Table), Combo, 1, 2, 1, 2, GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 5, 5); Combos[1] = Combo; Combo = gtk_combo_box_text_new(); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), "none"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), "odd"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), "even"); switch(config.parite) { case 0: gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), 0); break; case 1: gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), 1); break; case 2: gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), 2); break; } gtk_table_attach(GTK_TABLE(Table), Combo, 2, 3, 1, 2, GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 5, 5); Combos[2] = Combo; Label = gtk_label_new(_("Bits:")); gtk_table_attach(GTK_TABLE(Table), Label, 0, 1, 2, 3, 0, 0, 10, 5); Label = gtk_label_new(_("Stopbits:")); gtk_table_attach(GTK_TABLE(Table), Label, 1, 2, 2, 3, 0, 0, 10, 5); Label = gtk_label_new(_("Flow control:")); gtk_table_attach(GTK_TABLE(Table), Label, 2, 3, 2, 3, 0, 0, 10, 5); Combo = gtk_combo_box_text_new(); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), "5"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), "6"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), "7"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), "8"); gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), 3); if(config.bits >= 5 && config.bits <= 8) gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), config.bits - 5); gtk_table_attach(GTK_TABLE(Table), Combo, 0, 1, 3, 4, GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 5, 5); Combos[3] = Combo; Combo = gtk_combo_box_text_new(); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), "1"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), "2"); gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), 0); if(config.stops == 1 || config.stops == 2) gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), config.stops - 1); gtk_table_attach(GTK_TABLE(Table), Combo, 1, 2, 3, 4, GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 5, 5); Combos[4] = Combo; Combo = gtk_combo_box_text_new(); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), "none"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), "RTS/CTS"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), "Xon/Xoff"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), "RS485-HalfDuplex(RTS)"); gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), 0); switch(config.flux) { case 0: gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), 0); break; case 1: gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), 2); break; case 2: gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), 1); break; case 3: gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), 3); break; } gtk_table_attach(GTK_TABLE(Table), Combo, 2, 3, 3, 4, GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 5, 5); Combos[5] = Combo; /* create an expander widget to hide the 'Advanced features' */ Expander = gtk_expander_new_with_mnemonic(_("Advanced Configuration Options")); ExpanderVbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); gtk_container_add(GTK_CONTAINER(Expander), ExpanderVbox); gtk_container_add(GTK_CONTAINER(content_area), Expander); Frame = gtk_frame_new(_("ASCII file transfer")); gtk_container_add(GTK_CONTAINER(ExpanderVbox), Frame); Table = gtk_table_new(2, 2, FALSE); gtk_container_add(GTK_CONTAINER(Frame), Table); Label = gtk_label_new(_("End of line delay (milliseconds):")); gtk_table_attach_defaults(GTK_TABLE(Table), Label, 0, 1, 0, 1); adj = gtk_adjustment_new(0.0, 0.0, 500.0, 10.0, 20.0, 0.0); Spin = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0, 0); gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(Spin), TRUE); gtk_spin_button_set_value(GTK_SPIN_BUTTON(Spin), (gfloat)config.delai); gtk_table_attach(GTK_TABLE(Table), Spin, 1, 2, 0, 1, GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 5, 5); Combos[6] = Spin; Entry = gtk_entry_new(); gtk_entry_set_max_length(GTK_ENTRY(Entry), 1); gtk_widget_set_sensitive(GTK_WIDGET(Entry), FALSE); gtk_table_attach(GTK_TABLE(Table), Entry, 1, 2, 1, 2, GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 5, 5); CheckBouton = gtk_check_button_new_with_label(_("Wait for this special character before passing to next line:")); g_signal_connect(GTK_WIDGET(CheckBouton), "clicked", G_CALLBACK(Grise_Degrise), (gpointer)Spin); if(config.car != -1) { gtk_entry_set_text(GTK_ENTRY(Entry), &(config.car)); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(CheckBouton), TRUE); } gtk_table_attach_defaults(GTK_TABLE(Table), CheckBouton, 0, 1, 1, 2); Combos[7] = CheckBouton; Frame = gtk_frame_new(_("RS-485 half-duplex parameters (RTS signal used to send)")); gtk_container_add(GTK_CONTAINER(ExpanderVbox), Frame); Table = gtk_table_new(2, 2, FALSE); gtk_container_add(GTK_CONTAINER(Frame), Table); Label = gtk_label_new(_("Time with RTS 'on' before transmit (milliseconds):")); gtk_table_attach_defaults(GTK_TABLE(Table), Label, 0, 1, 0, 1); Label = gtk_label_new(_("Time with RTS 'on' after transmit (milliseconds):")); gtk_table_attach_defaults(GTK_TABLE(Table), Label, 0, 1, 1, 2); adj = gtk_adjustment_new(0.0, 0.0, 500.0, 10.0, 20.0, 0.0); Spin = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0, 0); gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(Spin), TRUE); gtk_spin_button_set_value(GTK_SPIN_BUTTON(Spin), (gfloat)config.rs485_rts_time_before_transmit); gtk_table_attach(GTK_TABLE(Table), Spin, 1, 2, 0, 1, GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 5, 5); Combos[8] = Spin; adj = gtk_adjustment_new(0.0, 0.0, 500.0, 10.0, 20.0, 0.0); Spin = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0, 0); gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(Spin), TRUE); gtk_spin_button_set_value(GTK_SPIN_BUTTON(Spin), (gfloat)config.rs485_rts_time_after_transmit); gtk_table_attach(GTK_TABLE(Table), Spin, 1, 2, 1, 2, GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 5, 5); Combos[9] = Spin; Bouton_OK = gtk_button_new_from_stock(GTK_STOCK_OK); gtk_box_pack_start(GTK_BOX(action_area), Bouton_OK, FALSE, TRUE, 0); g_signal_connect(GTK_WIDGET(Bouton_OK), "clicked", G_CALLBACK(Lis_Config), (gpointer)Combos); g_signal_connect_swapped(GTK_WIDGET(Bouton_OK), "clicked", G_CALLBACK(gtk_widget_destroy), GTK_WIDGET(Dialogue)); Bouton_annule = gtk_button_new_from_stock(GTK_STOCK_CANCEL); g_signal_connect_swapped(GTK_WIDGET(Bouton_annule), "clicked", G_CALLBACK(gtk_widget_destroy), GTK_WIDGET(Dialogue)); gtk_box_pack_start(GTK_BOX(action_area), Bouton_annule, FALSE, TRUE, 0); gtk_widget_show_all(Dialogue); } gint Lis_Config(GtkWidget *bouton, GtkWidget **Combos) { gchar *message; message = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(Combos[0])); strcpy(config.port, message); g_free(message); message = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(Combos[1])); config.vitesse = atoi(message); g_free(message); message = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(Combos[3])); config.bits = atoi(message); g_free(message); config.delai = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(Combos[6])); config.rs485_rts_time_before_transmit = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(Combos[8])); config.rs485_rts_time_after_transmit = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(Combos[9])); message = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(Combos[2])); if(!strcmp(message, "odd")) config.parite = 1; else if(!strcmp(message, "even")) config.parite = 2; else config.parite = 0; g_free(message); message = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(Combos[4])); config.stops = atoi(message); g_free(message); message = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(Combos[5])); if(!strcmp(message, "Xon/Xoff")) config.flux = 1; else if(!strcmp(message, "RTS/CTS")) config.flux = 2; else if(!strncmp(message, "RS485",5)) config.flux = 3; else config.flux = 0; g_free(message); if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(Combos[7]))) { config.car = *gtk_entry_get_text(GTK_ENTRY(Entry)); config.delai = 0; } else config.car = -1; Config_port(); ConfigFlags(); message = get_port_string(); Set_status_message(message); Set_window_title(message); g_free(message); return FALSE; } gint Grise_Degrise(GtkWidget *bouton, gpointer pointeur) { if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(bouton))) { gtk_widget_set_sensitive(GTK_WIDGET(Entry), TRUE); gtk_widget_set_sensitive(GTK_WIDGET(pointeur), FALSE); } else { gtk_widget_set_sensitive(GTK_WIDGET(Entry), FALSE); gtk_widget_set_sensitive(GTK_WIDGET(pointeur), TRUE); } return FALSE; } void clear_scrollback(void){ vte_terminal_set_scrollback_lines (VTE_TERMINAL(display), 0); vte_terminal_set_scrollback_lines (VTE_TERMINAL(display), term_conf.scrollback); } void read_font_button(GtkFontButton *fontButton) { g_free(term_conf.font); term_conf.font = g_strdup(gtk_font_button_get_font_name(fontButton)); if(term_conf.font != NULL) vte_terminal_set_font(VTE_TERMINAL(display), pango_font_description_from_string(term_conf.font)); } void select_config_callback(GtkAction *action, gpointer data) { Select_config(_("Load configuration"), G_CALLBACK(load_config)); } void save_config_callback(GtkAction *action, gpointer data) { Save_config_file(); } void delete_config_callback(GtkAction *action, gpointer data) { Select_config(_("Delete configuration"), G_CALLBACK(delete_config)); } void Select_config(gchar *title, void *callback) { GtkWidget *dialog; GtkWidget *content_area; gint i, max; GtkWidget *Frame, *Scroll, *Liste, *Label; gchar *texte_label; GtkListStore *Modele_Liste; GtkTreeIter iter_Liste; GtkCellRenderer *renderer; GtkTreeViewColumn *Colonne; GtkTreeSelection *Selection_Liste; enum { N_texte, N_COLONNES }; /* Parse the config file */ max = cfgParse(config_file, cfg, CFG_INI); if(max == -1) { show_message(_("Cannot read configuration file!\nConfig file may contain invalid parameter.\n"), MSG_ERR); return; } else { gchar *Titre[]= {_("Configurations")}; dialog = gtk_dialog_new_with_buttons (title, NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CANCEL, GTK_RESPONSE_NONE, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL); content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); Modele_Liste = gtk_list_store_new(N_COLONNES, G_TYPE_STRING); Liste = gtk_tree_view_new_with_model(GTK_TREE_MODEL(Modele_Liste)); gtk_tree_view_set_search_column(GTK_TREE_VIEW(Liste), N_texte); Selection_Liste = gtk_tree_view_get_selection(GTK_TREE_VIEW(Liste)); gtk_tree_selection_set_mode(Selection_Liste, GTK_SELECTION_SINGLE); Frame = gtk_frame_new(NULL); Scroll = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(Scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_container_add(GTK_CONTAINER(Frame), Scroll); gtk_container_add(GTK_CONTAINER(Scroll), Liste); renderer = gtk_cell_renderer_text_new(); g_object_set(G_OBJECT(renderer), "xalign", (gfloat)0.5, NULL); Colonne = gtk_tree_view_column_new_with_attributes(Titre[0], renderer, "text", 0, NULL); gtk_tree_view_column_set_sort_column_id(Colonne, 0); Label=gtk_label_new(""); texte_label = g_strdup_printf("%s", Titre[0]); gtk_label_set_markup(GTK_LABEL(Label), texte_label); g_free(texte_label); gtk_tree_view_column_set_widget(GTK_TREE_VIEW_COLUMN(Colonne), Label); gtk_widget_show(Label); gtk_tree_view_column_set_alignment(GTK_TREE_VIEW_COLUMN(Colonne), 0.5f); gtk_tree_view_column_set_resizable(GTK_TREE_VIEW_COLUMN(Colonne), FALSE); gtk_tree_view_append_column(GTK_TREE_VIEW(Liste), Colonne); for(i = 0; i < max; i++) { gtk_list_store_append(Modele_Liste, &iter_Liste); gtk_list_store_set(Modele_Liste, &iter_Liste, N_texte, cfgSectionNumberToName(i), -1); } gtk_widget_set_size_request(GTK_WIDGET(dialog), 200, 200); g_signal_connect(GTK_WIDGET(dialog), "response", G_CALLBACK (callback), GTK_TREE_SELECTION(Selection_Liste)); g_signal_connect_swapped(GTK_WIDGET(dialog), "response", G_CALLBACK(gtk_widget_destroy), GTK_WIDGET(dialog)); gtk_box_pack_start (GTK_BOX (content_area), Frame, TRUE, TRUE, 0); gtk_widget_show_all (dialog); } } void Save_config_file(void) { GtkWidget *dialog, *content_area, *label, *box, *entry; dialog = gtk_dialog_new_with_buttons (_("Save configuration"), NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CANCEL, GTK_RESPONSE_NONE, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL); content_area = gtk_dialog_get_content_area (GTK_DIALOG(dialog)); gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT); label = gtk_label_new(_("Configuration name: ")); box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); entry = gtk_entry_new(); gtk_entry_set_text(GTK_ENTRY(entry), "default"); gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE); gtk_box_pack_start(GTK_BOX(box), label, FALSE, TRUE, 0); gtk_box_pack_start(GTK_BOX(box), entry, TRUE, TRUE, 0); //validate input text (alpha-numeric only) g_signal_connect(GTK_ENTRY(entry), "insert-text", G_CALLBACK(check_text_input), isalnum); g_signal_connect(GTK_WIDGET(dialog), "response", G_CALLBACK(save_config), GTK_ENTRY(entry)); g_signal_connect_swapped(GTK_WIDGET(dialog), "response", G_CALLBACK(gtk_widget_destroy), GTK_WIDGET(dialog)); gtk_box_pack_start(GTK_BOX(content_area), box, TRUE, FALSE, 5); gtk_widget_show_all (dialog); } void really_save_config(GtkDialog *Fenetre, gint id, gpointer data) { int max, cfg_num, i; gchar *string = NULL; cfg_num = -1; if(id == GTK_RESPONSE_ACCEPT) { max = cfgParse(config_file, cfg, CFG_INI); if(max == -1) { show_message(_("Cannot save configuration file!\nConfig file may contain invalid parameter.\n"), MSG_ERR); return; } for(i = 0; i < max; i++) { if(!strcmp((char *)data, cfgSectionNumberToName(i))) cfg_num = i; } /* not overwriting */ if(cfg_num == -1) { max = cfgAllocForNewSection(cfg, (char *)data); cfg_num = max - 1; } else { if(remove_section(config_file, (char *)data) == -1) { show_message(_("Cannot overwrite section!"), MSG_ERR); return; } if(max == cfgParse(config_file, cfg, CFG_INI)) { show_message(_("Cannot read configuration file!"), MSG_ERR); return; } max = cfgAllocForNewSection(cfg, (char *)data); cfg_num = max - 1; } Copy_configuration(cfg_num); cfgDump(config_file, cfg, CFG_INI, max); string = g_strdup_printf(_("Configuration [%s] saved\n"), (char *)data); show_message(string, MSG_WRN); g_free(string); } else Save_config_file(); } void save_config(GtkDialog *Fenetre, gint id, GtkWidget *edit) { int max, i; const gchar *config_name; if(id == GTK_RESPONSE_ACCEPT) { max = cfgParse(config_file, cfg, CFG_INI); if(max == -1) { show_message(_("Cannot write configuration file!\nConfig file may contain invalid parameter.\n"), MSG_ERR); return; } config_name = gtk_entry_get_text(GTK_ENTRY(edit)); for(i = 0; i < max; i++) { if(!strcmp(config_name, cfgSectionNumberToName(i))) { GtkWidget *message_dialog; message_dialog = gtk_message_dialog_new_with_markup(GTK_WINDOW(Fenetre), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, _("Section [%s] already exists.\n\nDo you want to overwrite it ?"), config_name); gtk_dialog_add_buttons(GTK_DIALOG(message_dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_NONE, GTK_STOCK_YES, GTK_RESPONSE_ACCEPT, NULL); if (gtk_dialog_run(GTK_DIALOG(message_dialog)) == GTK_RESPONSE_ACCEPT) really_save_config(Fenetre, GTK_RESPONSE_ACCEPT, (gpointer)config_name); gtk_widget_destroy(message_dialog); i = max + 1; } } if(i == max) /* Section does not exist */ really_save_config(Fenetre, GTK_RESPONSE_ACCEPT, (gpointer)config_name); } } void load_config(GtkDialog *Fenetre, gint id, GtkTreeSelection *Selection_Liste) { GtkTreeIter iter; GtkTreeModel *Modele; gchar *txt, *message; if(id == GTK_RESPONSE_ACCEPT) { if(gtk_tree_selection_get_selected(Selection_Liste, &Modele, &iter)) { gtk_tree_model_get(GTK_TREE_MODEL(Modele), &iter, 0, (gint *)&txt, -1); Load_configuration_from_file(txt); Verify_configuration(); Config_port(); ConfigFlags(); add_shortcuts(); message = get_port_string(); Set_status_message(message); Set_window_title(message); g_free(message); } } } void delete_config(GtkDialog *Fenetre, gint id, GtkTreeSelection *Selection_Liste) { GtkTreeIter iter; GtkTreeModel *Modele; gchar *txt; if(id == GTK_RESPONSE_ACCEPT) { if(gtk_tree_selection_get_selected(Selection_Liste, &Modele, &iter)) { gtk_tree_model_get(GTK_TREE_MODEL(Modele), &iter, 0, (gint *)&txt, -1); if(remove_section(config_file, txt) == -1) show_message(_("Cannot delete section!"), MSG_ERR); } } } gint Load_configuration_from_file(gchar *config_name) { int max, i, j, k, size; gchar *string = NULL; gchar *str; macro_t *macros = NULL; cfgList *t; max = cfgParse(config_file, cfg, CFG_INI); if(max == -1) { show_message(_("Cannot read configuration file!\nConfig file may contain invalid parameter.\n"), MSG_ERR); return -1; } else { for(i = 0; i < max; i++) { if(!strcmp(config_name, cfgSectionNumberToName(i))) { Hard_default_configuration(); if(port[i] != NULL) strcpy(config.port, port[i]); if(speed[i] != 0) config.vitesse = speed[i]; if(bits[i] != 0) config.bits = bits[i]; if(stopbits[i] != 0) config.stops = stopbits[i]; if(parity[i] != NULL) { if(!g_ascii_strcasecmp(parity[i], "none")) config.parite = 0; else if(!g_ascii_strcasecmp(parity[i], "odd")) config.parite = 1; else if(!g_ascii_strcasecmp(parity[i], "even")) config.parite = 2; } if(flow[i] != NULL) { if(!g_ascii_strcasecmp(flow[i], "none")) config.flux = 0; else if(!g_ascii_strcasecmp(flow[i], "xon")) config.flux = 1; else if(!g_ascii_strcasecmp(flow[i], "rts")) config.flux = 2; else if(!g_ascii_strcasecmp(flow[i], "rs485")) config.flux = 3; } config.delai = wait_delay[i]; if(wait_char[i] != 0) config.car = (signed char)wait_char[i]; else config.car = -1; config.rs485_rts_time_before_transmit = rts_time_before_tx[i]; config.rs485_rts_time_after_transmit = rts_time_after_tx[i]; if(echo[i] != -1) config.echo = (gboolean)echo[i]; else config.echo = FALSE; if(crlfauto[i] != -1) config.crlfauto = (gboolean)crlfauto[i]; else config.crlfauto = FALSE; if(timestamp[i] != -1) config.timestamp = (gboolean)timestamp[i]; else config.timestamp = FALSE; g_free(term_conf.font); term_conf.font = g_strdup(font[i]); t = macro_list[i]; size = 0; if(t != NULL) { size++; while(t->next != NULL) { t = t->next; size++; } } if(size != 0) { t = macro_list[i]; macros = g_malloc(size * sizeof(macro_t)); if(macros == NULL) { perror("malloc"); return -1; } for(j = 0; j < size; j++) { for(k = 0; k < (strlen(t->str) - 1); k++) { if((t->str[k] == ':') && (t->str[k + 1] == ':')) break; } macros[j].shortcut = g_strndup(t->str, k); str = &(t->str[k + 2]); macros[j].action = g_strdup(str); t = t->next; } } remove_shortcuts(); create_shortcuts(macros, size); g_free(macros); if(block_cursor[i] != -1) term_conf.block_cursor = (gboolean)block_cursor[i]; else term_conf.block_cursor = TRUE; if(rows[i] != 0) term_conf.rows = rows[i]; if(columns[i] != 0) term_conf.columns = columns[i]; if(scrollback[i] != 0) term_conf.scrollback = scrollback[i]; if(visual_bell[i] != -1) term_conf.visual_bell = (gboolean)visual_bell[i]; else term_conf.visual_bell = FALSE; term_conf.foreground_color.red = foreground_red[i]; term_conf.foreground_color.green = foreground_green[i]; term_conf.foreground_color.blue = foreground_blue[i]; term_conf.foreground_color.alpha = foreground_alpha[i]; term_conf.background_color.red = background_red[i]; term_conf.background_color.green = background_green[i]; term_conf.background_color.blue = background_blue[i]; term_conf.background_color.alpha = background_alpha[i]; /* rows and columns are empty when the conf is autogenerate in the first save; so set term to default */ if(rows[i] == 0 || columns[i] == 0) { term_conf.block_cursor = TRUE; term_conf.rows = 80; term_conf.columns = 25; term_conf.scrollback = DEFAULT_SCROLLBACK; term_conf.visual_bell = FALSE; term_conf.foreground_color.red = 0.66; term_conf.foreground_color.green = 0.66; term_conf.foreground_color.blue = 0.66; term_conf.foreground_color.alpha = 1; term_conf.background_color.red = 0; term_conf.background_color.green = 0; term_conf.background_color.blue = 0; term_conf.background_color.alpha = 1; } i = max + 1; } } if(i == max) { string = g_strdup_printf(_("No section \"%s\" in configuration file\n"), config_name); show_message(string, MSG_ERR); g_free(string); return -1; } } vte_terminal_set_font(VTE_TERMINAL(display), pango_font_description_from_string(term_conf.font)); vte_terminal_set_size (VTE_TERMINAL(display), term_conf.rows, term_conf.columns); vte_terminal_set_scrollback_lines (VTE_TERMINAL(display), term_conf.scrollback); vte_terminal_set_color_foreground (VTE_TERMINAL(display), &term_conf.foreground_color); vte_terminal_set_color_background (VTE_TERMINAL(display), &term_conf.background_color); vte_terminal_set_color_background (VTE_TERMINAL(display), &term_conf.background_color); vte_terminal_set_cursor_shape(VTE_TERMINAL(display), term_conf.block_cursor ? VTE_CURSOR_SHAPE_BLOCK : VTE_CURSOR_SHAPE_IBEAM); gtk_widget_queue_draw(display); return 0; } void Verify_configuration(void) { gchar *string = NULL; switch(config.vitesse) { case 300: case 600: case 1200: case 2400: case 4800: case 9600: case 19200: case 38400: case 57600: case 115200: case 230400: case 460800: case 576000: case 921600: case 1000000: case 2000000: break; default: string = g_strdup_printf(_("Baudrate %d may not be supported by all hardware"), config.vitesse); show_message(string, MSG_ERR); g_free(string); } if(config.stops != 1 && config.stops != 2) { string = g_strdup_printf(_("Invalid number of stop-bits: %d\nFalling back to default number of stop-bits number: %d\n"), config.stops, DEFAULT_STOP); show_message(string, MSG_ERR); config.stops = DEFAULT_STOP; g_free(string); } if(config.bits < 5 || config.bits > 8) { string = g_strdup_printf(_("Invalid number of bits: %d\nFalling back to default number of bits: %d\n"), config.bits, DEFAULT_BITS); show_message(string, MSG_ERR); config.bits = DEFAULT_BITS; g_free(string); } if(config.delai < 0 || config.delai > 500) { string = g_strdup_printf(_("Invalid delay: %d ms\nFalling back to default delay: %d ms\n"), config.delai, DEFAULT_DELAY); show_message(string, MSG_ERR); config.delai = DEFAULT_DELAY; g_free(string); } if(term_conf.font == NULL) term_conf.font = g_strdup_printf(DEFAULT_FONT); } gint Check_configuration_file(void) { struct stat my_stat; gchar *string = NULL; /* is configuration file present ? */ if(stat(config_file, &my_stat) == 0) { /* If bad configuration file, fallback to _hardcoded_ defaults! */ if(Load_configuration_from_file("default") == -1) { Hard_default_configuration(); return -1; } } /* if not, create it, with the [default] section */ else { string = g_strdup_printf(_("Configuration file (%s) with\n[default] configuration has been created.\n"), config_file); show_message(string, MSG_WRN); cfgAllocForNewSection(cfg, "default"); Hard_default_configuration(); Copy_configuration(0); cfgDump(config_file, cfg, CFG_INI, 1); g_free(string); } return 0; } void Hard_default_configuration(void) { strcpy(config.port, DEFAULT_PORT); config.vitesse = DEFAULT_SPEED; config.parite = DEFAULT_PARITY; config.bits = DEFAULT_BITS; config.stops = DEFAULT_STOP; config.flux = DEFAULT_FLOW; config.delai = DEFAULT_DELAY; config.rs485_rts_time_before_transmit = DEFAULT_DELAY_RS485; config.rs485_rts_time_after_transmit = DEFAULT_DELAY_RS485; config.car = DEFAULT_CHAR; config.echo = DEFAULT_ECHO; config.crlfauto = FALSE; config.timestamp = FALSE; config.disable_port_lock = FALSE; term_conf.font = g_strdup_printf(DEFAULT_FONT); term_conf.block_cursor = TRUE; term_conf.rows = 80; term_conf.columns = 25; term_conf.scrollback = DEFAULT_SCROLLBACK; term_conf.visual_bell = TRUE; Selec_couleur(&term_conf.foreground_color, 0.66, 0.66, 0.66, 1.0); Selec_couleur(&term_conf.background_color, 0, 0, 0, 1.0); } void Copy_configuration(int pos) { gchar *string = NULL; macro_t *macros = NULL; gint size, i; string = g_strdup(config.port); cfgStoreValue(cfg, "port", string, CFG_INI, pos); g_free(string); string = g_strdup_printf("%d", config.vitesse); cfgStoreValue(cfg, "speed", string, CFG_INI, pos); g_free(string); string = g_strdup_printf("%d", config.bits); cfgStoreValue(cfg, "bits", string, CFG_INI, pos); g_free(string); string = g_strdup_printf("%d", config.stops); cfgStoreValue(cfg, "stopbits", string, CFG_INI, pos); g_free(string); switch(config.parite) { case 0: string = g_strdup_printf("none"); break; case 1: string = g_strdup_printf("odd"); break; case 2: string = g_strdup_printf("even"); break; default: string = g_strdup_printf("none"); } cfgStoreValue(cfg, "parity", string, CFG_INI, pos); g_free(string); switch(config.flux) { case 0: string = g_strdup_printf("none"); break; case 1: string = g_strdup_printf("xon"); break; case 2: string = g_strdup_printf("rts"); break; case 3: string = g_strdup_printf("rs485"); break; default: string = g_strdup_printf("none"); } cfgStoreValue(cfg, "flow", string, CFG_INI, pos); g_free(string); string = g_strdup_printf("%d", config.delai); cfgStoreValue(cfg, "wait_delay", string, CFG_INI, pos); g_free(string); string = g_strdup_printf("%d", config.car); cfgStoreValue(cfg, "wait_char", string, CFG_INI, pos); g_free(string); string = g_strdup_printf("%d", config.rs485_rts_time_before_transmit); cfgStoreValue(cfg, "rs485_rts_time_before_tx", string, CFG_INI, pos); g_free(string); string = g_strdup_printf("%d", config.rs485_rts_time_after_transmit); cfgStoreValue(cfg, "rs485_rts_time_after_tx", string, CFG_INI, pos); g_free(string); if(config.echo == FALSE) string = g_strdup_printf("False"); else string = g_strdup_printf("True"); cfgStoreValue(cfg, "echo", string, CFG_INI, pos); g_free(string); if(config.crlfauto == FALSE) string = g_strdup_printf("False"); else string = g_strdup_printf("True"); cfgStoreValue(cfg, "crlfauto", string, CFG_INI, pos); g_free(string); if(config.timestamp == FALSE) string = g_strdup_printf("False"); else string = g_strdup_printf("True"); cfgStoreValue(cfg, "timestamp", string, CFG_INI, pos); g_free(string); string = g_strdup(term_conf.font); cfgStoreValue(cfg, "font", string, CFG_INI, pos); g_free(string); macros = get_shortcuts(&size); for(i = 0; i < size; i++) { string = g_strdup_printf("%s::%s", macros[i].shortcut, macros[i].action); cfgStoreValue(cfg, "macros", string, CFG_INI, pos); g_free(string); } if(term_conf.block_cursor == FALSE) string = g_strdup_printf("False"); else string = g_strdup_printf("True"); cfgStoreValue(cfg, "term_block_cursor", string, CFG_INI, pos); g_free(string); string = g_strdup_printf("%d", term_conf.rows); cfgStoreValue(cfg, "term_rows", string, CFG_INI, pos); g_free(string); string = g_strdup_printf("%d", term_conf.columns); cfgStoreValue(cfg, "term_columns", string, CFG_INI, pos); g_free(string); string = g_strdup_printf("%d", term_conf.scrollback); cfgStoreValue(cfg, "term_scrollback", string, CFG_INI, pos); g_free(string); if(term_conf.visual_bell == FALSE) string = g_strdup_printf("False"); else string = g_strdup_printf("True"); cfgStoreValue(cfg, "term_visual_bell", string, CFG_INI, pos); g_free(string); string = g_strdup_printf("%f", term_conf.foreground_color.red); cfgStoreValue(cfg, "term_foreground_red", string, CFG_INI, pos); g_free(string); string = g_strdup_printf("%f", term_conf.foreground_color.green); cfgStoreValue(cfg, "term_foreground_green", string, CFG_INI, pos); g_free(string); string = g_strdup_printf("%f", term_conf.foreground_color.blue); cfgStoreValue(cfg, "term_foreground_blue", string, CFG_INI, pos); g_free(string); string = g_strdup_printf("%f", term_conf.foreground_color.alpha); cfgStoreValue(cfg, "term_foreground_alpha", string, CFG_INI, pos); g_free(string); string = g_strdup_printf("%f", term_conf.background_color.red); cfgStoreValue(cfg, "term_background_red", string, CFG_INI, pos); g_free(string); string = g_strdup_printf("%f", term_conf.background_color.green); cfgStoreValue(cfg, "term_background_green", string, CFG_INI, pos); g_free(string); string = g_strdup_printf("%f", term_conf.background_color.blue); cfgStoreValue(cfg, "term_background_blue", string, CFG_INI, pos); g_free(string); string = g_strdup_printf("%f", term_conf.background_color.alpha); cfgStoreValue(cfg, "term_background_alpha", string, CFG_INI, pos); g_free(string); } gint remove_section(gchar *cfg_file, gchar *section) { FILE *f = NULL; char *buffer = NULL; char *buf; long size; gchar *to_search; long i, j, length, sect; f = fopen(cfg_file, "r"); if(f == NULL) { perror(cfg_file); return -1; } fseek(f, 0L, SEEK_END); size = ftell(f); rewind(f); buffer = g_malloc(size); if(buffer == NULL) { perror("malloc"); return -1; } if(fread(buffer, 1, size, f) != size) { perror(cfg_file); fclose(f); return -1; } to_search = g_strdup_printf("[%s]", section); length = strlen(to_search); /* Search section */ for(i = 0; i < size - length; i++) { for(j = 0; j < length; j++) { if(to_search[j] != buffer[i + j]) break; } if(j == length) break; } if(i == size - length) { i18n_printf(_("Cannot find section %s\n"), to_search); return -1; } sect = i; /* Search for next section */ for(i = sect + length; i < size; i++) { if(buffer[i] == '[') break; } f = fopen(cfg_file, "w"); if(f == NULL) { perror(cfg_file); return -1; } fwrite(buffer, 1, sect, f); buf = buffer + i; fwrite(buf, 1, size - i, f); fclose(f); g_free(to_search); g_free(buffer); return 0; } void Config_Terminal(GtkAction *action, gpointer data) { GtkBuilder *builder; builder = gtk_builder_new_from_resource("/org/gtk/gtkterm/config_terminal_dialog.ui"); GtkWidget *dialog; dialog = GTK_WIDGET(gtk_builder_get_object(builder, "dialog")); gtk_window_set_transient_for(dialog, Fenetre); gtk_window_set_title(GTK_WINDOW(dialog), _("Main Window")); /** Connect signals **/ // Font Selection Button GtkWidget *cfg_terminal_font; cfg_terminal_font = GTK_WIDGET(gtk_builder_get_object(builder, "cfg_terminal_font")); g_signal_connect(cfg_terminal_font, "font-set", G_CALLBACK(read_font_button), 0); // Scrollback Lines GtkAdjustment *cfg_scrollback_lines; cfg_scrollback_lines = GTK_ADJUSTMENT(gtk_builder_get_object(builder, "cfg_scrollback_lines")); gtk_adjustment_set_value(cfg_scrollback_lines, term_conf.scrollback); g_signal_connect(G_OBJECT(cfg_scrollback_lines), "value_changed", G_CALLBACK(scrollback_set), 0); // Show cursor GtkWidget *cfg_block_cursor; cfg_block_cursor = GTK_WIDGET(gtk_builder_get_object(builder, "cfg_block_cursor")); gtk_switch_set_active(GTK_SWITCH(cfg_block_cursor), term_conf.block_cursor); g_signal_connect(cfg_block_cursor, "state_set", G_CALLBACK(cursor_block), 0); // Text color GtkWidget *cfg_text_color; cfg_text_color = GTK_WIDGET(gtk_builder_get_object(builder, "cfg_text_color")); gtk_color_button_set_rgba(GTK_COLOR_BUTTON(cfg_text_color), &term_conf.foreground_color); g_signal_connect(cfg_text_color, "color-set", G_CALLBACK (config_fg_color), 0); // Background color GtkWidget *cfg_background_color; cfg_background_color = GTK_WIDGET(gtk_builder_get_object(builder, "cfg_background_color")); gtk_color_button_set_rgba(GTK_COLOR_BUTTON(cfg_background_color), &term_conf.background_color); g_signal_connect(cfg_background_color, "color-set", G_CALLBACK (config_bg_color), 0); // Close button GtkWidget *close; close = GTK_WIDGET(gtk_builder_get_object(builder, "close")); g_signal_connect_swapped(close, "clicked", G_CALLBACK(gtk_widget_destroy), GTK_WIDGET(dialog)); gtk_widget_show_all(dialog); } gboolean cursor_block(GtkSwitch *ToggleSwitch, gboolean state, gpointer data) { term_conf.block_cursor = state; vte_terminal_set_cursor_shape(VTE_TERMINAL(display), term_conf.block_cursor ? VTE_CURSOR_SHAPE_BLOCK : VTE_CURSOR_SHAPE_IBEAM); return FALSE; } void Selec_couleur(GdkRGBA *color, gfloat R, gfloat G, gfloat B, gfloat A) { color->red = R; color->green = G; color->blue = B; color->alpha = A; } void config_fg_color(GtkWidget *button, gpointer data) { gchar *string; gtk_color_button_get_rgba (GTK_COLOR_BUTTON (button), &term_conf.foreground_color); vte_terminal_set_color_foreground (VTE_TERMINAL(display), &term_conf.foreground_color); gtk_widget_queue_draw (display); string = g_strdup_printf ("%d", term_conf.foreground_color.red); cfgStoreValue (cfg, "term_foreground_red", string, CFG_INI, 0); g_free (string); string = g_strdup_printf ("%d", term_conf.foreground_color.green); cfgStoreValue (cfg, "term_foreground_green", string, CFG_INI, 0); g_free (string); string = g_strdup_printf ("%d", term_conf.foreground_color.blue); cfgStoreValue (cfg, "term_foreground_blue", string, CFG_INI, 0); g_free (string); string = g_strdup_printf ("%d", term_conf.foreground_color.alpha); cfgStoreValue (cfg, "term_foreground_alpha", string, CFG_INI, 0); g_free (string); } void config_bg_color(GtkWidget *button, gpointer data) { gchar *string; gtk_color_button_get_rgba (GTK_COLOR_BUTTON (button), &term_conf.background_color); vte_terminal_set_color_background (VTE_TERMINAL(display), &term_conf.background_color); gtk_widget_queue_draw (display); string = g_strdup_printf ("%d", term_conf.background_color.red); cfgStoreValue (cfg, "term_background_red", string, CFG_INI, 0); g_free (string); string = g_strdup_printf ("%d", term_conf.background_color.green); cfgStoreValue (cfg, "term_background_green", string, CFG_INI, 0); g_free (string); string = g_strdup_printf ("%d", term_conf.background_color.blue); cfgStoreValue (cfg, "term_background_blue", string, CFG_INI, 0); g_free (string); string = g_strdup_printf ("%d", term_conf.background_color.alpha); cfgStoreValue (cfg, "term_background_alpha", string, CFG_INI, 0); g_free (string); } void scrollback_set(GtkAdjustment *Adjustment, gpointer data) { gint scrollback = gtk_adjustment_get_value(Adjustment); term_conf.scrollback = scrollback; vte_terminal_set_scrollback_lines (VTE_TERMINAL(display), term_conf.scrollback); } /** * Filter user data entry on a GTK entry * * user_data must be a function that takes an int and returns an int * != 0 if the input is valid. For instance, 'isdigit()'. */ void check_text_input(GtkEditable *editable, gchar *new_text, gint new_text_length, gint *position, gpointer user_data) { int i; int (*check_func)(int) = NULL; if(user_data == NULL) { return; } g_signal_handlers_block_by_func(editable, (gpointer)check_text_input, user_data); check_func = (int (*)(int))user_data; for(i = 0; i < new_text_length; i++) { if(!check_func(new_text[i])) goto invalid_input; } gtk_editable_insert_text(editable, new_text, new_text_length, position); invalid_input: g_signal_handlers_unblock_by_func(editable, (gpointer)check_text_input, user_data); g_signal_stop_emission_by_name(editable, "insert-text"); } gtkterm-1.1.1/src/term_config.h000066400000000000000000000057161376216657300164540ustar00rootroot00000000000000/***********************************************************************/ /* config.h */ /* -------- */ /* GTKTerm Software */ /* (c) Julien Schmitt */ /* */ /* ------------------------------------------------------------------- */ /* */ /* Purpose */ /* Configuration of the serial port */ /* - Header file - */ /* */ /***********************************************************************/ #ifndef TERM_CONFIG_H_ #define TERM_CONFIG_H_ void ConfigFlags(void); void Config_Port_Fenetre(GtkAction *action, gpointer data); gint Lis_Config(GtkWidget *bouton, GtkWidget **Combos); void Config_Terminal(GtkAction *action, gpointer data); void select_config_callback(GtkAction *action, gpointer data); void save_config_callback(GtkAction *action, gpointer data); void delete_config_callback(GtkAction *action, gpointer data); void Verify_configuration(void); gint Load_configuration_from_file(gchar *); gint Check_configuration_file(void); void check_text_input(GtkEditable *editable, gchar *new_text, gint new_text_length, gint *position, gpointer user_data); void clear_scrollback(void); struct configuration_port { gchar port[1024]; gint vitesse; // 300 - 600 - 1200 - ... - 2000000 gint bits; // 5 - 6 - 7 - 8 gint stops; // 1 - 2 gint parite; // 0 : None, 1 : Odd, 2 : Even gint flux; // 0 : None, 1 : Xon/Xoff, 2 : RTS/CTS, 3 : RS485halfduplex gint delai; // end of char delay: in ms gint rs485_rts_time_before_transmit; gint rs485_rts_time_after_transmit; gchar car; // caractere à attendre gboolean echo; // echo local gboolean crlfauto; // line feed auto gboolean timestamp; gboolean disable_port_lock; }; typedef struct { gboolean block_cursor; gint rows; gint columns; gint scrollback; gboolean visual_bell; GdkRGBA foreground_color; GdkRGBA background_color; gchar *font; } display_config_t; #define DEFAULT_FONT "Monospace 12" #define DEFAULT_SCROLLBACK 10000 #define DEFAULT_PORT "/dev/ttyS0" #define DEFAULT_SPEED 115200 #define DEFAULT_PARITY 0 #define DEFAULT_BITS 8 #define DEFAULT_STOP 1 #define DEFAULT_FLOW 0 #define DEFAULT_DELAY 0 #define DEFAULT_CHAR -1 #define DEFAULT_DELAY_RS485 30 #define DEFAULT_ECHO FALSE extern gchar *config_file; #endif gtkterm-1.1.1/src/user_signals.c000066400000000000000000000006341376216657300166430ustar00rootroot00000000000000#include #include "interface.h" static gboolean handle_usr1(gpointer user_data) { interface_open_port(); return G_SOURCE_CONTINUE; } static gboolean handle_usr2(gpointer user_data) { interface_close_port(); return G_SOURCE_CONTINUE; } void user_signals_catch(void) { g_unix_signal_add(SIGUSR1, (GSourceFunc) handle_usr1, NULL); g_unix_signal_add(SIGUSR2, (GSourceFunc) handle_usr2, NULL); } gtkterm-1.1.1/src/user_signals.h000066400000000000000000000017151376216657300166510ustar00rootroot00000000000000/***********************************************************************/ /* device_mintor.h */ /* --------- */ /* GTKTerm Software */ /* (c) Julien Schmitt */ /* */ /* ------------------------------------------------------------------- */ /* */ /* Purpose */ /* React to SIGUSR signals (for scriptability) */ /* */ /***********************************************************************/ #ifndef _USER_SIGNALS #define _USER_SIGNALS void user_signals_catch(void); #endif