pax_global_header00006660000000000000000000000064136224261550014520gustar00rootroot0000000000000052 comment=d6cc9d0af0e73b1e17172f9b5af8dcedc0475242 termit-3.1/000077500000000000000000000000001362242615500126675ustar00rootroot00000000000000termit-3.1/.gitignore000066400000000000000000000002751362242615500146630ustar00rootroot00000000000000config.h CMakeFiles CMakeCache.txt install_manifest.txt tags cscope.out Makefile termit.spec termit.SlackBuild termit-*.ebuild *~ *.gmo cmake_install.cmake cmake_uninstall.cmake src/termit termit-3.1/CMakeLists.txt000066400000000000000000000050171362242615500154320ustar00rootroot00000000000000# Copyright © 2007-2016 Evgeny Ratnikov # # 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 . PROJECT(TERMIT C) cmake_minimum_required(VERSION 2.6.1 FATAL_ERROR) SET(CMAKE_VERSION "${CMAKE_CACHE_MAJOR_VERSION}.${CMAKE_CACHE_MINOR_VERSION}.${CMAKE_CACHE_RELEASE_VERSION}") INCLUDE(UsePkgConfig) ADD_DEFINITIONS(-Wall) SET(DEFAULT_XDG_DIR "/etc/xdg") string(REPLACE ":" ";" XDG_DIRS "$ENV{XDG_CONFIG_DIRS}") FOREACH(xdgDir ${XDG_DIRS}) SET(XDG_DIR ${xdgDir}) BREAK() ENDFOREACH() IF(NOT XDG_DIR) SET(XDG_DIR "/etc/xdg") ENDIF(NOT XDG_DIR) SET(DEBUG FALSE CACHE BOOL "debug info") SET(ENABLE_NLS TRUE CACHE BOOL "enable translation") SET(XDG_DIR ${XDG_DIR} CACHE STRING "default xdg dir") SET(TERMIT_PACKAGE "termit") SET(TERMIT_PACKAGE_VERSION "3.1.0") SET(TERMIT_LOCALE_DIR "${CMAKE_INSTALL_PREFIX}/share/locale") SET(TERMIT_XDG_DIR "${XDG_DIR}/termit") SET(TERMIT_PACKAGE_NAME "termit - terminal emulator") SET(TERMIT_PACKAGE_STRING "${TERMIT_PACKAGE} ${TERMIT_PACKAGE_VERSION}") SET(TERMIT_PACKAGE_BUGREPORT "ratnikov.ev@gmail.com") CONFIGURE_FILE(${TERMIT_SOURCE_DIR}/config.h.in ${TERMIT_SOURCE_DIR}/config.h) CONFIGURE_FILE( "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake/cmake_uninstall.cmake" IMMEDIATE @ONLY) ADD_CUSTOM_TARGET(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake/cmake_uninstall.cmake") ADD_SUBDIRECTORY(doc) ADD_SUBDIRECTORY(src) IF(ENABLE_NLS) ADD_SUBDIRECTORY(po) ENDIF(ENABLE_NLS) ADD_SUBDIRECTORY(utils) ADD_SUBDIRECTORY(etc) MESSAGE("\n termit ${TERMIT_PACKAGE_VERSION}\n") MESSAGE("Prefix dir:.......... ${CMAKE_INSTALL_PREFIX}") IF(ENABLE_NLS) MESSAGE("Locales dir:......... ${TERMIT_LOCALE_DIR}") ENDIF(ENABLE_NLS) MESSAGE("Xdg dir:............. ${TERMIT_XDG_DIR}") message("Gtk:................. ${GTK_VERSION}") message("Vte:................. ${VTE_VERSION}") message("Lua:................. ${LUA_VERSION}") MESSAGE("Debug:............... ${DEBUG}") MESSAGE("") termit-3.1/COPYING000066400000000000000000001043741362242615500137330ustar00rootroot00000000000000 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 . termit-3.1/ChangeLog000066400000000000000000000164631362242615500144530ustar00rootroot00000000000000 require Lua 5.3 disable menubar on F10 new options: scrollOnKeystroke, scrollOnOutput fixed tab style reset after cancel preferences dialog refactored several deprecated functions fixed recursive termit_close_tab call appdata -> metainfo default icon name for terminal window irc colormap (by clort81) get rid of deprecated match_check version 3.0 added AppData file license changed to GPLv3.0+ added 'apply to all tabs' in preferences dialog new options: cursorBlinkMode, cursorShape startMaximized, hideTitlebarWhenMaximized wordChars replaced with wordCharExceptions removed options: imageFile, transparency, visibleBell Require libvte>0.29 and Gtk-3. version 2.10.1 Fixed error with conflicting libvte/Gtk versions Fixed ebuild (by Ilya Mochalov). Suppress "invalid option" for -e. Fixed missing link to math library (by Thomas Koch) Miminum required version for Gtk-2 changed to 2.24. Miminum required version for libvte changed to 0.28. Rebuild po-files due to source changes. version 2.10.0 fixed compilation for OpenBSD prevent building termit with incompatible Gtk and Vte versions "exec" commandline option now works nearly like in xterm new options: showBorder - show notebook's borders version 2.9.6 fixed handling geometry setting added support to choose libraries while configuring termit build scrollable tabs in tabbar new options: tabPos - set tabbar position version 2.9.5 fixed bug with hideTabbar and hideSingleTab tabs indexes start with 1 (Lua-indexing) fixed desktop file added Swedish translation (by Tomas Fasth) version 2.9.4 fix hyphen-used-as-minus-sign in manpage (by Thomas Koch) new options: hideTabbar (by Anurag Priyam) new Lua functions: toggleTabbar added Polish translation (by Miś Uszatek) added Danish translation added support for Lua 5.2 fixed docs version 2.9.3 fixed installing as non-root added Spanish translation (by Martintxo) added German translation (by Dennis Ploeger) updated Hungarian translation (by Peter Polonkai) apply foreground color for bold fonts added several WM-specific commandline options: --name, --class, --role version 2.9.2 fix build with --as-needed linker flags enabled (patch by Artur Frysiak) Meta, Super and Hyper in keybindings (patch by Artur Frysiak) project language set to C new Lua functions: feed feedChild fixed some compilation issues when using Gtk+3 added Japanese translation (by Nobuhiro Iwamatsu) version 2.9.1 fixed setEncoding in termit.utils module fixed possible zombie process version 2.9.0 new Lua functions: setColormap added support for system-wide rc.lua added support for using modules in rc.lua added several predefined colormaps version 2.8.1 fixed bug in currentTabIndex version 2.8.0 search in vte buffer (only for vte >= 0.26) new Lua functions forEachRow forEachVisibleRow findDlg findNext findPrev new options backspaceBinding deleteBinding setStatusbar extra warnings when compiling in DEBUG mode fixed docs version 2.7.1 display proper encoding when switching pages version 2.7.0 refactored reading table from Lua fixed working with sessions new options: imageFile - path to image to be set on the background colormap - instead of setColormap matches - instead of setMatches tabs - opened by default tabs changed default binding for 'closeTab' from 'Ctrl-w' to 'CtrlShift-w' cleanup fixed docs version 2.6.0 fixed -e option: read configs first only then execute accelerators for user menus new Lua functions setTabTitleDlg loadSessionDlg saveSessionDlg preferencesDlg quit cleanup fixed docs removed support for deprecated: use rc.lua instead of init.lua in openTab use title instead of name and workingDir instead of working_dir action in menuitem must be lua-function version 2.5.0 GPLv2 license agreement in every source file new Lua functions selection currentTab global array 'tabs' with tab settings fixed bug: hidden menu appears after reconfigure deprecated: use rc.lua instead of init.lua in openTab use title instead of name and workingDir instead of working_dir fixed docs version 2.4.0 new Lua functions setColormap version 2.3.0 read rc.lua instead of init.lua (init.lua is deprecated) new Lua functions new options audibleBell, visibleBell, setMatches, spawn, urgencyOnBell version 2.2.0 mixed modifiers (e.g. AltCtrl, AltShift, etc.) new Lua functions setTabForegroundColor, setTabBackgroundColor, bindMouse, toggleMenubar, setWindowTitle, currentTabIndex, getTabTitle, getWindowTitle new options per-tab foreground/background colors, fillTabbar, hideMenubar, changeTitle version 2.1.1 fixed typo in docs, init foreground color with "gray", proper Lua-includes when building from source version 2.1.0 added support for changing foreground color added man page cmake_minimum_required changed to 2.6.1, 2.6.0 have problems with FindLua51.cmake module fixed reconfigure when running with --init option version 2.0.0 embedded Lua - configs and sessions replaced with lua-scripts xterm-like dynamic window title version 1.3.5 added Korean translation (by SeonKon Choi) added termit.spec.in for Fedora 8 (by SeonKon Choi) fixed bug with show/hide scrollbar version 1.3.4 fixes Hungarian translation (by Peter Polonkai) version 1.3.3 added termit.SlackBuild and termit.ebuild added support for kb_policy (for shortcuts) versoin 1.3.2 fixed loading default options when no config file was found added session.example to installed docs version 1.3.1 added show_scrollbar option in popup menu and termit.cfg shell_cmd variable splitted into shell (eg bash, zsh, python, etc) and shell_cmd (eg -c 'su - root', etc) updated documentation bugfix with uninitialized GError fixed --usage output fixed statusbar encoding when loading session fixed compilation warnings version 1.3 when both -s and -e options are presented at command line load session and add tab with command added --execute/-e command-line option added hide_single_tab options in termit.cfg (hide tab tray when only one tab is opened) added configurable keybindings (example here: doc/termit.example) added support for shell_cmd in session file added transparent background options in termit.cfg (patch by Tetralet) added doc/session.example code cleanup version 1.2 tabs are reordable for Gtk versions > 2.10.0 added geometry option in termit.cfg (setting COLSxROWS) --help support added initial Translation Chinese translation (author Ming Lu) version 1.1.3 default Sans font replaced with Monospace fixed linking with option "--as-needed" (patch by Andrew Borodin) version 1.1.2 bugfix with GError when parsing config files added hungarian translation (author Peter Polonkai) added french translation (author Mallory Mollo) version 1.1.1 important for 64bit platforms: fixes a cast of a pointer to "int" use pkg-config for detecting vte library version 1.1 build system changed to CMake (http://www.cmake.org/) --version (-v) support added session support added desktop file according to "Desktop Entry Specification" v1.0 config file placement changed according to "XDG Base Directory Specification" v0.6 version 1.0.3 double-click on empty space in tabbar opens new tab in debug mode prints pid of child shell process version 1.0.2 only fixing bootstrap.sh version 1.0.1 removed unneccessary free - potential "double-free" error version 1.0 initial release termit-3.1/INSTALL000066400000000000000000000006331362242615500137220ustar00rootroot00000000000000Installation Instructions ************************* Termit requires CMake (version 2.4 or later). You can obtain CMake sources here http://cmake.org/. Run CMake generator: cmake . Then configure termit: ccmake . Then make: make And finally install: make install Package makers can specify DESTDIR: make install DESTDIR="destdir" To remove termit: make uninstall termit-3.1/TODO000066400000000000000000000004561362242615500133640ustar00rootroot00000000000000-- names for sessions -- encode displayed buffer (hmmm it seems vte doesn't support that) -- store in TermitTab only flags: SET_NAME, SET_FG_FONT, SET_BG_FONT, etc values are already stored in VteTerminal, so we can simply read VteTerminal properties on demand thus we can achieve smaller memory usage termit-3.1/cmake/000077500000000000000000000000001362242615500137475ustar00rootroot00000000000000termit-3.1/cmake/cmake_uninstall.cmake.in000066400000000000000000000030761362242615500205350ustar00rootroot00000000000000# Copyright (C) 2007-2010, Evgeny Ratnikov # # This file is part of termit. # termit is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 # as published by the Free Software Foundation. # termit 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 termit. If not, see . IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) STRING(REGEX REPLACE "\n" ";" files "${files}") FOREACH(file ${files}) MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") IF(EXISTS "$ENV{DESTDIR}${file}") EXEC_PROGRAM( "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" OUTPUT_VARIABLE rm_out RETURN_VALUE rm_retval ) IF(NOT "${rm_retval}" STREQUAL 0) MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") ENDIF(NOT "${rm_retval}" STREQUAL 0) ELSE(EXISTS "$ENV{DESTDIR}${file}") MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") ENDIF(EXISTS "$ENV{DESTDIR}${file}") ENDFOREACH(file) termit-3.1/config.h.in000066400000000000000000000023541362242615500147160ustar00rootroot00000000000000/* Copyright © 2007-2016 Evgeny Ratnikov * * 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 . */ /* Gettext locale dir */ #define LOCALEDIR "${TERMIT_LOCALE_DIR}" /* Name of package */ #define PACKAGE "${TERMIT_PACKAGE}" /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "${TERMIT_PACKAGE_BUGREPORT}" /* Define to the full name of this package. */ #define PACKAGE_NAME "${TERMIT_PACKAGE_NAME}" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "${TERMIT_PACKAGE_STRING}" /* Define to the version of this package. */ #define PACKAGE_VERSION "${TERMIT_PACKAGE_VERSION}" termit-3.1/doc/000077500000000000000000000000001362242615500134345ustar00rootroot00000000000000termit-3.1/doc/CMakeLists.txt000066400000000000000000000020721362242615500161750ustar00rootroot00000000000000# Copyright © 2007-2016 Evgeny Ratnikov # # 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 . SET(TERMIT_DOCS ../COPYING README lua_api.txt rc.lua.example) INSTALL(FILES ${TERMIT_DOCS} DESTINATION ${CMAKE_INSTALL_PREFIX}/share/doc/${TERMIT_PACKAGE}) INSTALL(FILES termit.1 DESTINATION ${CMAKE_INSTALL_PREFIX}/share/man/man1) INSTALL(FILES termit.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications) INSTALL(FILES termit.metainfo.xml DESTINATION ${CMAKE_INSTALL_PREFIX}/share/metainfo) termit-3.1/doc/README000066400000000000000000000015521362242615500143170ustar00rootroot00000000000000 Termit Simple terminal emulator based on vte library, extensible via lua. Features: * multiple tabs * switching encodings * sessions * configurable keybindings * embedded Lua Configuration can be changed via $HOME/.config/termit/rc.lua file (example is provided). Command-line arguments: * --version (-v) - prints version info * --init=init_file - use init_file instead of standard rc.lua * --execute=cmd - execute command (also -e) Keybindings can be configured via rc.lua. Defaults are: Alt-Left - previous tab Alt-Right - next tab Ctrl-t - open tab Ctlr-w - close tab Ctrl-Insert - copy Shift-Insert - paste Lua API is described in lua_api.txt termit-3.1/doc/lua_api.txt000066400000000000000000000162171362242615500156160ustar00rootroot00000000000000h4. Functions *activateTab(_tab_index_)* - Activates tab by index. _tab_index_ - index of tab to activate. Index of the first tab is 1. *addMenu(_menu_)* - Adds menu in menubar. _menu_ - table of TermitMenuItem type. *addPopupMenu(_menu_)* - Adds menu in popup menu, similar to addMenu. _menu_ - table of TermitMenuItem type. *bindKey(_keys_, _luaFunction_)* - Sets new keybinding. If luaFunction is nil removes keybinding. _keys_ - string with keybinding. Available modifiers are Alt Ctrl Shift Meta Super Hyper. _luaFunction_ - callback function pre. Example: don't close tab with Ctrl-w, use CtrlShift-w bindKey('Ctrl-w', nil) bindKey('CtrlShift-w', closeTab) *bindMouse(_event_, _luaFunction_)* - Sets new mouse-binding. If luaFunction is nil removes mouse-binding. _event_ - string with one of those values: DoubleClick _luaFunction_ - callback function *closeTab()* - Closes active tab. *copy()* - Copies selection into tab's buffer. *currentTab()* - Returns current tab of TermitTabInfo. *currentTabIndex()* - Returns current tab index. *feed(data)* - Interprets data as if it were data received from a terminal process. *feedChild(data)* - Sends a data to the terminal as if it were data entered by the user at the keyboard. *findDlg()* - Opens find entry. (Enabled when build with vte version >= 0.26) *findNext()* - Searches the next string matching search regex. *findPrev()* - Searches the previous string matching search regex. *forEachRow(_func_)* - For each terminal row in entire scrollback buffer executes function passing row as argument. _func_ - function to be called. *forEachVisibleRow(_func_)* - For each visible terminal row executes function passing row as argument. _func_ - function to be called. *loadSessionDlg()* - Displays "Load session" dialog. *nextTab()* - Activates next tab. *openTab(_tabInfo_)* - Opens new tab. _tabinfo_ - table of TermitTabInfo with tab settings. pre. Example: tabInfo = {} tabInfo.title = 'Zsh tab' tabInfo.command = 'zsh' tabInfo.encoding = 'UTF-8' tabInfo.workingDir = '/tmp' openTab(tabInfo) *paste()* - Pastes tab's buffer. *preferencesDlg()* - Displays "Preferences" dialog. *prevTab()* - Activates previous tab. *quit()* - Quit. *reconfigure()* - Sets all configurable variables to defaults and forces rereading rc.lua. *saveSessionDlg()* - Displays "Save session" dialog. *selection()* - Returns selected text from current tab. *setColormap(_colormap_)* - Changes colormap for active tab. _colormap_ - array with 8 or 16 or 24 colors. *setEncoding(_encoding_)* - Changes encoding for active tab. _encoding_ - string with encoding name. pre. Example: setEncoding('UTF-8') *setKbPolicy(_kb_policy_)* - Sets keyuboard policy for shortcuts. _kb_policy_ - string with one of those values: * keycode - use hardware keyboard codes (XkbLayout-independent) * keysym - use keysym values (XkbLayout-dependent) pre. Example: treat keys via current XkbLayout setKbPolicy('keysym') *setOptions(_opts_)* - Changes default options. _opts_ - table of TermitOptions type with new options: *setTabBackgroundColor(_color_)* - Changes background color for active tab. _color_ - string with new color. *setTabFont(_font_)* - Changes font for active tab. _font_ - string with new font. *setTabForegroundColor(_color_)* - Changes foreground (e.g. font) color for active tab. _color_ - string with new color. *setTabTitle(_tabTitle_)* - Changes title for active tab. _tabTitle_ - string with new tab title. *setTabTitleDlg()* - Displays "Set tab title" dialog. *setWindowTitle(_title_)* - Changes termit window title. _title_ - string with new title. *spawn(_command_) - Spawns command (works via shell). _command_ - string with command and arguments. *toggleMenubar()* - Displays or hides menubar. *toggleTabbar()* - Displays or hides tabbar. h4. Types *TermitCursorBlinkMode* - one of those string values: * System - Follow GTK+ settings for cursor blinking * BlinkOn - Cursor blinks * BlinkOff - Cursor does not blink *TermitCursorShape* - one of those string values: * Block - Draw a block cursor * Ibeam - Draw a vertical bar on the left side of character * Underline - Draw a horizontal bar below the character *TermitEraseBinding* - one of those string values: * Auto - VTE_ERASE_AUTO * AsciiBksp - VTE_ERASE_ASCII_BACKSPACE * AsciiDel - VTE_ERASE_ASCII_DELETE * EraseDel - VTE_ERASE_DELETE_SEQUENCE * EraseTty - VTE_ERASE_TTY For detailed description look into Vte docs. *TermitKeybindings* - table with predefined keybindings. * closeTab - 'Ctrl-w' * copy - 'Ctrl-Insert' * nextTab - 'Alt-Right' * openTab - 'Ctrl-t' * paste - 'Shift-Insert' * prevTab - 'Alt-Left' pre. Example: enable Gnome-like tab switching keys = {} keys.nextTab = 'Ctrl-Page_Down' keys.prevTab = 'Ctrl-Page_Up' setKeys(keys) *TermitMenuItem* - table for menuitems. * accel - accelerator for menuitem. String with keybinding * action - lua-function to execute when item activated * name - name for menuitem *TermitOptions* - table with termit options. * allowChangingTitle - auto change title (similar to xterm) * audibleBell - enables audible bell * backgroundColor - background color * backspaceBinding - reaction on backspace key (one of TermitEraseBinding) * colormap - array with 8 or 16 or 24 colors * cursorBlinkMode - cursor blink mode (one of TermitCursorBlinkMode) * cursorShape - cursor shape (one of TermitCursorShape) * deleteBinding - reaction on delete key (one of TermitEraseBinding) * encoding - default encoding * fillTabbar - expand tabs' titles to fill whole tabbar * font - font name * foregroundColor - foreground color * geometry - cols x rows to start with * getTabTitle - lua function to generate new tab title * getWindowTitle - lua function to generate new window title * hideMenubar - hide menubar * hideTabbar - hide tabbar * hideSingleTab - hide tabbar when only 1 tab present * hideTitlebarWhenMaximized - hide window titlebar when mazimized * matches - table with items of TermitMatch type * scrollbackLines - the length of scrollback buffer * scrollOnKeystroke - enables scroll to the bottom when the user presses a key * scrollOnOutput - enables scroll to the bottom when new data is received * setStatusbar - lua function to generate new statusbar message * showBorder - show notebook border * showScrollbar - display scrollbar * startMaximized - maximize window on start * tabName - default tab name * tabPos - tabbar position (Top, Bottom, Left, Right) * tabs - table with items of TermitTabInfo type * urgencyOnBell - set WM-hint 'urgent' on termit window when bell * wordCharExceptions - additional word characters (double click selects word) *TermitTabInfo* - table with tab settings: * command * encoding * font - font string * fontSize - font size * pid - process id * title * workingDir h4. Globals *tabs* - Readonly table with tab settings, access specific tabs by index. h4. Bugs After start sometimes there is black screen. Resizing termit window helps. In options table 'tabs' field should be the last one. When loading all settings are applied in the same order as they are set in options table. So if you set tabs and only then colormap, these tabs would have default colormap. termit-3.1/doc/rc.lua.example000066400000000000000000000106341362242615500162010ustar00rootroot00000000000000-- Example file with lots of options. -- You can test with with this command: -- cd ./etc && ../src/termit --init ../doc/rc.lua.example colormaps = require("termit.colormaps") utils = require("termit.utils") defaults = {} defaults.windowTitle = 'Termit' defaults.startMaximized = true defaults.hideTitlebarWhenMaximized = true defaults.tabName = 'Terminal' defaults.encoding = 'UTF-8' defaults.wordCharExceptions = '- .,_/' defaults.font = 'Terminus 12' --defaults.foregroundColor = 'gray' --defaults.backgroundColor = 'black' defaults.showScrollbar = true defaults.hideSingleTab = false defaults.hideTabbar = false defaults.showBorder = true defaults.hideMenubar = false defaults.fillTabbar = true defaults.scrollbackLines = 4096 defaults.geometry = '80x24' defaults.allowChangingTitle = false --defaults.backspaceBinding = 'AsciiBksp' --defaults.deleteBinding = 'AsciiDel' defaults.cursorBlinkMode = 'BlinkOff' defaults.cursorShape = 'Ibeam' defaults.tabPos = 'Right' defaults.setStatusbar = function (tabInd) tab = tabs[tabInd] if tab then return tab.encoding..' Bksp: '..tab.backspaceBinding..' Del: '..tab.deleteBinding end return '' end defaults.colormap = colormaps.delicate defaults.matches = {['http[^ ]+'] = function (url) print('Matching url: '..url) end} defaults.tabs = {{title = 'Test new tab 1'; workingDir = '/tmp'}; {title = 'Test new tab 2'; workingDir = '/tmp'}} setOptions(defaults) bindKey('Ctrl-Page_Up', prevTab) bindKey('Ctrl-Page_Down', nextTab) bindKey('Ctrl-F', findDlg) bindKey('Ctrl-2', function () print('Hello2!') end) bindKey('Ctrl-3', function () print('Hello3!') end) bindKey('Ctrl-3', nil) -- remove previous binding -- don't close tab with Ctrl-w, use CtrlShift-w bindKey('Ctrl-w', nil) bindKey('CtrlShift-w', closeTab) setKbPolicy('keycode') bindMouse('DoubleClick', openTab) -- userMenu = {} table.insert(userMenu, {name='Close tab', action=closeTab}) table.insert(userMenu, {name='New tab name', action=function () setTabTitle('New tab name') end}) mi = {} mi.name = 'Zsh tab' mi.action = function () tabInfo = {} tabInfo.title = 'Zsh tab' tabInfo.command = 'zsh' tabInfo.encoding = 'UTF-8' tabInfo.workingDir = '/tmp' tabInfo.backspaceBinding = 'AsciiBksp' tabInfo.deleteBinding = 'EraseDel' openTab(tabInfo) end table.insert(userMenu, mi) table.insert(userMenu, {name='set red color', action=function () setTabForegroundColor('red') end}) table.insert(userMenu, {name='Reconfigure', action=reconfigure, accel='Ctrl-r'}) table.insert(userMenu, {name='Selection', action=function () print(selection()) end}) table.insert(userMenu, {name='dumpAllRows', action=function () forEachRow(print) end}) table.insert(userMenu, {name='dumpVisibleRowsToFile', action=function () utils.dumpToFile(forEachVisibleRow, '/tmp/termit.dump') end}) table.insert(userMenu, {name='findNext', action=findNext, accel='Alt-n'}) table.insert(userMenu, {name='findPrev', action=findPrev, accel='Alt-p'}) table.insert(userMenu, {name='new colormap', action=function () setColormap(colormaps.mikado) end}) table.insert(userMenu, {name='toggle menubar', action=function () toggleMenubar() end}) table.insert(userMenu, {name='toggle tabbar', action=function () toggleTabbar() end}) mi = {} mi.name = 'Get tab info' mi.action = function () tab = tabs[currentTabIndex()] if tab then utils.printTable(tab, ' ') end end table.insert(userMenu, mi) function round(float) return math.floor(float + .5) end function changeTabFontSize(delta) tab = tabs[currentTabIndex()] fontSize = round(tab.fontSize) setTabFont(string.sub(tab.font, 1, string.find(tab.font, '%d+$') - 1)..(fontSize + delta)) end table.insert(userMenu, {name='Increase font size', action=function () changeTabFontSize(1) end}) table.insert(userMenu, {name='Decrease font size', action=function () changeTabFontSize(-1) end}) table.insert(userMenu, {name='feed example', action=function () feed('example') end}) table.insert(userMenu, {name='feedChild example', action=function () feedChild('date\n') end}) table.insert(userMenu, {name='move tab left', action=function () setTabPos(currentTabIndex() - 1) end}) table.insert(userMenu, {name='move tab right', action=function () setTabPos(currentTabIndex() + 1) end}) table.insert(userMenu, {name='User quit', action=quit}) addMenu(userMenu, "User menu") addPopupMenu(userMenu, "User menu") addMenu(utils.encMenu(), "Encodings") addPopupMenu(utils.encMenu(), "Encodings") termit-3.1/doc/termit.1000066400000000000000000000225471362242615500150340ustar00rootroot00000000000000.\" Process this file with .\" groff -man -Tascii foo.1 .\" .TH TERMIT 1 "NOV 2008" Linux "User Manuals" .SH NAME termit \(hy lightweight terminal emulator .SH SYNOPSIS .B termit [\-option ...] .SH DESCRIPTION .B termit is a vte\(hybased lightweight terminal emulator. All configuration is done via Lua\(hyscripts. The only other dependencies are Gtk+ and Vte. .SH OPTIONS .BR \-h, .BR \-\-help .RS Print help .RE .BR \-v, .BR \-\-version .RS Print version number .RE .BR \-e, .BR \-\-execute = .I cmd .RS Use .I cmd as shell .RE .BR \-i, .BR \-\-init = .I file .RS Use .I file instead of default rc.lua .RE .BR \-n, .BR \-\-name = .I name .RS Use .I name in window name hint .RE .BR \-c, .BR \-\-class = .I class .RS Use .I class in window class hint .RE .BR \-r, .BR \-\-role = .I role .RS Use .I role in window role Gtk\(hyhint .RE .BR \-T, .BR \-\-title = .I title .RS Use .I title in window title (Turns off .I allowChangingTitle option.) .RE .P termit \-\-init=session.lua \-\-name=TermitName \-\-class=TermitClass \-\-role=TermitRole \-\-title=TermitTitle \-\-execute=zsh .P .RE .SH FILES .I $HOME/.config/termit/rc.lua .RS Per user configuration file. See section .BR "TERMIT LUA API" for further details. .RE .I /usr/share/doc/termit/rc.lua.example .RS Example rc.lua file. Demonstrates usage of almost all available settings. .SH "TERMIT LUA API" .B "Functions:" .B activateTab ( .I tab_index ) Activates tab by index. tab_index \(hy index of tab to activate. Index of the first tab is 1. .P .B addMenu ( .I menu ) Adds menu in menubar. menu \(hy table of TermitMenuItem type. .P .B addPopupMenu ( .I menu ) Adds menu in popup menu, similar to addMenu. menu \(hy table of TermitMenuItem type. .P .B bindKey ( .I keys , .I luaFunction ) Sets new keybinding. If luaFunction is .I nil removes keybinding. keys \(hy string with keybinding. Available modifiers are Alt Ctrl Shift Meta Super Hyper. luaFunction \(hy callback function .P .B bindMouse ( .I event , .I luaFunction ) Sets new mouse\(hybinding. If luaFunction is .I nil removes mouse\(hybinding. event \(hy string with one of those values: DoubleClick luaFunction \(hy callback function .P .B closeTab () Closes active tab. .P .B copy () Copies selection into tab's buffer. .P .B currentTab () Returns current tab of TermitTabInfo. .P .B currentTabIndex () Returns current tab index. .P .B feed ( .I data ) Interprets data as if it were data received from a terminal process. .P .B feedChild ( .I data ) Sends a data to the terminal as if it were data entered by the user at the keyboard. .P .B findDlg () Opens search entry. .P .B findNext () Searches the next string matching search regex. .P .B findPrev () Searches the previous string matching search regex. .P .B forEachRow ( .I func ) For each terminal row in entire scrollback buffer executes function passing row as argument. func \(hy function to be called. .P .B forEachVisibleRow ( .I func ) For each visible terminal row executes function passing row as argument. func \(hy function to be called. .P .B loadSessionDlg () Displays "Load session" dialog. .P .B nextTab () Activates next tab. .P .B openTab ( .I tabInfo ) Opens new tab. tabinfo \(hy table of TermitTabInfo with tab settings. .P .B paste () Pastes tab's buffer. .P .B preferencesDlg () Displays "Preferences" dialog. .P .B prevTab () Activates previous tab. .P .B quit () Quit. .P .B reconfigure () Sets all configurable variables to defaults and forces rereading rc.lua. .P .B saveSessionDlg () Displays "Save session" dialog. .P .B selection () Returns selected text from current tab. .P .B setColormap ( .I colormap ) Changes colormap for active tab. colormap \(hy array with 8 or 16 or 24 colors. .P .B setEncoding ( .I encoding ) Changes encoding for active tab. encoding \(hy string with encoding name. .P .B setKbPolicy ( .I kb_policy ) Sets keyuboard policy for shortcuts. kb_policy \(hy string with one of those values: keycode \(hy use hardware keyboard codes (XkbLayout\(hyindependent) keysym \(hy use keysym values (XkbLayout\(hydependent) .P .B setOptions ( .I opts ) Changes default options. opts \(hy TermitOptions table with new options. .P .B setTabBackgroundColor ( .I color ) Changes background color for active tab. color \(hy string with new color. .P .B setTabFont ( .I font ) Changes font for active tab. font \(hy string with new font. .P .B setTabForegroundColor ( .I color ) Changes foreground (e.g. font) color for active tab. color \(hy string with new color. .P .B setTabPos ( .I newPos ) Changes position for active tab. newPos \(hy number with new tab position. .P .B setTabTitle ( .I tabTitle ) Changes title for active tab. tabTitle \(hy string with new tab title. .P .B setTabTitleDlg () Displays "Set tab title" dialog. .P .B setWindowTitle ( .I title ) Changes termit window title. title \(hy string with new title. .P .B spawn ( .I command ) Spawns command (works via shell). command \(hy string with command and arguments. .P .B toggleMenubar () Displays or hides menubar. .P .P .B toggleTabbar () Displays or hides tabbar. .P .B "Types:" .B TermitCursorBlinkMode \(hy one of those string values: System Follow GTK+ settings for cursor blinking BlinkOn Cursor blinks BlinkOff Cursor does not blink .P .B TermitCursorShape \(hy one of those string values: Block Draw a block cursor Ibeam Draw a vertical bar on the left side of character Underline Draw a horizontal bar below the character .P .B TermitEraseBinding \(hy one of those string values: Auto VTE_ERASE_AUTO AsciiBksp VTE_ERASE_ASCII_BACKSPACE AsciiDel VTE_ERASE_ASCII_DELETE EraseDel VTE_ERASE_DELETE_SEQUENCE EraseTty VTE_ERASE_TTY .P For detailed description look into Vte docs. .P .B TermitKeybindings \(hy table with predefined keybindings. closeTab 'Ctrl\(hyw' copy 'Ctrl\(hyInsert' nextTab 'Alt\(hyRight' openTab 'Ctrl\(hyt' paste 'Shift\(hyInsert' prevTab 'Alt\(hyLeft' .P .B TermitMatch \(hy table for matches. field name match regular expression field value lua callback for action on Left\(hyclick. .P .B TermitMenuItem \(hy table for menuitems. accel accelerator for menuitem. String with keybinding action lua function to execute when item activated name name for menuitem .P .B TermitOptions \(hy table with termit options. allowChangingTitle auto change title (similar to xterm) audibleBell enables audible bell backgroundColor background color backspaceBinding reaction on backspace key (one of TermitEraseBinding) colormap array with 8 or 16 or 24 colors cursorBlinkMode cursor blink mode (one of TermitCursorBlinkMode) cursorShape cursor shape (one of TermitCursorShape) deleteBinding reaction on delete key (one of TermitEraseBinding) encoding default encoding fillTabbar expand tabs' titles to fill whole tabbar font font name foregroundColor foreground color geometry cols x rows to start with getTabTitle lua function to generate new tab title getWindowTitle lua function to generate new window title hideMenubar hide menubar hideSingleTab hide tabbar when only 1 tab present hideTabbar hide tabbar hideTitlebarWhenMaximized hide window titlebar when mazimized matches table with items of TermitMatch type scrollbackLines the length of scrollback buffer scrollOnKeystroke enables scroll to the bottom when the user presses a key scrollOnOutput enables scroll to the bottom when new data is received setStatusbar lua function to generate new statusbar message showScrollbar display scrollbar showBorder show notebook borders startMaximized maximize window on start tabName default tab name tabPos tabbar position (Top, Bottom, Left, Right) tabs table with items of TermitTabInfo type urgencyOnBell set WM\(hyhint 'urgent' on termit window when bell wordCharExceptions additional word characters (double click selects word) .P .B TermitTabInfo \(hy table with tab settings: command tab start command encoding current tab encoding font font string fontSize font size pid process id title tab title workingDir tab working dir .P .B "Globals:" .B tabs is the array with settings for all tabs. Access specific tab by index. .RS .SH EXAMPLES Look inside provided rc.lua.example. .SH BUGS After start sometimes there is black screen. Resizing termit window helps. .P In options table 'tabs' field should be the last one. When loading all settings are applied in the same order as they are set in options table. So if you set tabs and only then colormap, these tabs would have default colormap. .SH AUTHOR Evgeny Ratnikov .SH "SEE ALSO" .BR lua (1) termit-3.1/doc/termit.desktop000066400000000000000000000005331362242615500163340ustar00rootroot00000000000000[Desktop Entry] Name=Termit GenericName=Terminal emulator GenericName[ru]=Эмулятор терминала Comment=Lightweight terminal emulator Comment[ru]=Легкий эмулятор терминала TryExec=termit Exec=termit Icon=utilities-terminal Type=Application Categories=GTK;System;TerminalEmulator; Terminal=false Keywords=Run; termit-3.1/doc/termit.metainfo.xml000066400000000000000000000022251362242615500172640ustar00rootroot00000000000000 org.gnome.ratnikov.ev.apps.termit FSFAP GPL-3.0+ Termit Terminal emulator

Small terminal emulator configurable via Lua. Other dependencies are Vte and Gtk3 libs. Termit supports multiple tabs, encoding switching and sessions.

termit.desktop Terminal main window with shell session https://raw.githubusercontent.com/nonstop/termit/master/doc/termit.png https://github.com/nonstop/termit/wiki GNOME termit Evgeny Ratnikov https://github.com/nonstop/termit/issues
termit-3.1/doc/termit.png000066400000000000000000002200211362242615500154430ustar00rootroot00000000000000PNG  IHDRH& =gAMA a cHRMz&u0`:pQ<bKGD oFFsstIME T" vpAgV{IDATxw$Gy8y{w:锅$@ KFX`` ccc_lD6#F0`,Xs@(NoӤyG鮮~ _' q#$y@" hEY55,,,EYADDYXH$ AEMA@D ܍] afF@k" dfqH^XXDsE"B` !YkY8,d !!EkADk-"wb"C`@&$(HbkqAD g"k) $HA(2 AkZbHW@}j{v Q\ʜ;2X8*WʀVY(T=h1 !AL >%Hl*Ŧլ@bK,u^]`-!$h JQf"Y}"±M !ϲ\DgfH"X[jd$sADѐ%2q\ɝ7mD,!8kXY56 _t[nnZwq޽{m|>92y<2"D8J():4qX kؚE,UIy||J>l6sr9 rAfI n[ƖoZ.'>@.GŶZ&qAι#cJ/2ώIeæz?T7hL,e;\.C>s bEF@v!9ngX.$4ƖeP.ld992E[1Cf``@lnmߡd@F5DH"a:B` &ƔKq9$,A(J4@A$IVe ;G&"BkLUkZoɉ-[6nܴ)JaRNT+ͷݙeT.m<Bچ@01q>r"$yMr9wy,5"" >04gJჇvT1;(T/38+jj6HHBrN 0 '@@`@A y;wi$ϐ.@ DjΚ4JA9 }fq>i b 2qεZ4M4ҴH{(ՠAADB|3u&",O4MR9d`hX'$`ni8TdqOLL5 ڡ!!1avA$k `q$Cx~qpqIσ 8"!ԔkYE(N9cigiVͦ,7 ,DB`>Xkl7U@g̀.&Ii޻rHqsv+ovinI\(.cf&(2}}}}}5\eiy}}}r\.GQ{(I@3;C "YvV,ϦuaxZ-CqIFr7l,0zǖ0!HQT(! ",C&4ιά 2Q1MW!x%HE "EPVƈHE B`DQ {$*@ $ffe EPŘ`A0E ! @10U% ,BjBQ', "c5LD23Na/h -Tf%'3†Zǖ$IRf( $YYgDF\,l-zPC [CcY"VT.ȀYULhKAc=C~ ,Ȉ#6 U'&'sref"i;!TUigw8F`I4l-ȓ],$cc27h P!9(eJ };)jnٸ}VT>YߺusZm6.8!d7("DyhЀsv4kYYqZ-xԠB@%}i:A 0}BTJ#[6m9v,ŝHJs*J*FwlܻKhg6!8#2ho@xp+ !H,q)"2/n^6oPNMbvL ԥ,JSSzژLgc(MIY|pccS CȌ$ xFחYlY;T*QdD5$`$0DAHE2B s[4ͳ$c4FDv;c\Hf!ȈG"|Ɛ \?nm,̜9'QPv+Il$L@ Hn !8d0mf㆐993RVQj[ITj˧ ~j$3}WTCE ޣ&)L@<Jvrg)3`%2Yn6(GDj rY+ K`!a,bMB0& ,Tl bWAv;,2fhF{_w133#N'IJSE}``@ x ,A9ypoϭ`ժGQiӐܾ6fDO73Flʥ$2qiNMի@!˲$DI,LA!n}}}dC.~TiP<&$|,kSg⃭8""!a.6i;"t.0[CYZ`_?$pH n{AN=ZO"B|`f)n6שr/Ey3MED"̞VSD,X#$eB mŗ_ EqӢhLW=Eىh> 8iV$3ĈhaDHI6u~ӵJEYEE P0 2Qq#@.{FJfj"JB$` \T!B>]U!0 G`24j{W)čz"93Xʥ<#qd+EB!K192v፛7z^[7NL6T{K<_+T>OH!`LQPJ"X"$l6TKJ sBs{cGf;Tsp/Iܻ~rYeއ%}L(RduYhZ,x|`1.5|j5vl6Ș C,rRj 8-!a_س;sYER;mȀJI5rv<קFTkTiеSSJ-"hރY0"eyBH, cfv7 .31eYqf2Vb$o g%CZexh(.8je<4$"h@D "1c R"  bwG&v;XIjǑX.Wss]NW쯥yQ[GEkK0PT_E 5,n<-1xʥ\)BjYTʈP88/[{A]1| 0Ɖ0 rp3]L_5wyC6wiq`gZ#bC@[DRyQmFQ 6qṪv}(qNqcL+iJd"_kR(,`B^K ZZJJy["f>mZ!km屍6o4JY4"Qq> t@k*$ _:EbtG'jgYJ)ҌMLL |9J]@kmQX*`rrrrrQD}lM-lrpyڭ,6&IG].#c(Bx240QTTZb0ۦXD9CQ ;ӽ z$P* ?X976""pFDt @qY 0təanVFlc,˃@ȈG(3Qd QϳvnFKػrfl@P Q'I`xJQ 1{ bLhZ)!8)%6jɉ82g=D"6Ewq22 wI@08{|;ڇbK̜>7CV]>vd"I* (d!k,kFLS*0Y ymJ4rQ.'o()FpQ(,=TuxlT*Ʋ4=̳I)*B DZۿ`j-MÇWk -`ww4[-olwsnㆡ$5qii9GdDl>wޓve1Ey!Ѭ, Tʥɉ @.IdYDZso,8}z+?(:tS/t/X A`Bv,o22F,XoY A%j@08jVR3IsFKF9t dCL4׷}VƘ4keY3IKh L_>@ճ^o56m B?ȇ BD.zLdƍF)FCrVZohDQ{EQ` !61yi ˲6yn3p0# t?v.Ev ڹ%>a3s(E'R$"r;pPR@CcSS6(,!@ѓ]  "KōB5u\tTmg_)jyG!=xӣ_49#k˕Z)ͰV6TJ):ep!p<xM<88PV!"tY pzYCjSǜ;חzoh|}޺V.'6ls9眽kpp(I,'&&nnu`6Tkif f?8[o6sj6D>RRjs2 qD^r1e)PG0="o1a]_tCyqvيwPL7YLlZ5_iVtn(@##V+bb6 kmټnK:}MnJBR B L'{옓ELeqMg9l~2uٻHYT+> q`i4SJ)uaG<1y; +6ycd\!0H6`Yߌ\SIrN咵09!"z㍿pN=9=|ƾ/mIL+SƣH!?k; {F{22RP~=jYz\}+XW{or}2Ň5 I[qx˹Rolf^%bΉ%>3o "WJ)5ٺqxh6A-;  svV[k;M)SuwfŖ Y÷TSO+Rg$I1yh7!R|Ǝcnx_Qzd熽ʂO wA* "K<159Ѯ }.C04˲ `m,,y?WWF'v阓o9 mK#D6Wr%zW_+ߝ҆3/ĽF?#߻?:wSǵoNSҞ|€N0F7 4X%?f綘Tx]c h#uB\iv8Ke}iZ^EkK[ͩ9}RJKDgɳ{/"d} =lC94h:sxҿk1pA{؆+gm۶5Rf,۶ۿۆW^&߹a}㋞{?̾h$;x/AS5?+>7 V?u _6X"tZC|Pčۿ/'?;> 0u+j>8o~G%ɦ%ۘl]W\&W7o]mlڻ^7]}+>| ԟWÞ|髮m&Gy*'wCI_7>I<0?"S]#ԗn_s^o*Is?/v̩{ʗ^^Eҫg,Xvc5c 9RJO"RNb$ȳl3D p(ڭ UtC/z+[ s +*{DJ9`"Ww*tnІ!񉻛)wm?8g=OzfPhTw>/;3yk?=)x#sTz~'v=xٿ$3ܜȅM4}] w#NYȂ _5{˵2{ZIi3?I|^'n ]No=C퇿A"xVOSe"H9Js?wl"o|p`

nG7,7]1\g Uk}=ܯ|wD߼X}[cm+r4mĩ^E:g#ܫ/cN)$" K&,2pXE󮇈S>ޏN.;C9s{WU'sO4""Zi z:859Yl6fjp%2H=IyUݲ7F4T;(nF[ꋭu7|g]GNt_SG;:-qtmR}_NLf;$p{X/]9h&zA3œ6cESE)ZsD$s.wQdyBmd;}@d޶8_me㬱kn@rRHMS닊.ql'6$InV{||2~ȃ;p9w>xs~wl#|E9_?@c*ޯwg/gC65~HmdZ? Ͼ4zsA9̡_ٿm<|տRi&' ?mt_s|C1|c}(?wxoჿ.@?x#=E ߱w[밽oS7=g|/c>vagjxνgs?7ԿM_Ƽ#PJ)!ˆ ]>"e_^~3wN bИ 'o= fRC?aG3W†L}^vON?;&k߼` nzq1T*EzȦ7:ymmh+n_ߺu2!w}j;fҹ >}qWں ̓I14ݶ2*cpZqG̟&.P%2ၛtޏp(Rk OJP*}R)_D{ 2}]6Wl~~9,>#ɨq熁3v$I{,Ȳ|Ϟ=d`7&Sfs_Ma[YҶg"()U=Tc~Jm1K&wY@_uWfp\!I[y ps#B?Nqd9GY y c(7QhijhVL,! ""JdN)Rj="Zk)M3D`[3 dRJ)Y@j%M8N,,"BIa޹bRJ)Ԫ%͛ʕʑÇ&sc2=>1L\Y5Fi1,nry2qf8kIJW v Ns;5$BDBLJZV병NHRJ5 ox]RQ\h4vGvzF(daA k6lMtG5yvޯvW-Xk7o^ӵ_V)Z}sR)cBJmd$A,e)fȲW<3{ZaZ__eܱtRJE#Dc !!H , "P<<́"#"iwR81{kZ.oԧj}}j+EPNvؘӱC|V.ӴO_PJ)Ndq:WEQDhAD$p H&L|~ϧKTDn5i[kDR!Ie {G !t:$ ̈^~7^M_`[:M8}:J/LJ-cX'=pR-,8] .F%"A@Ddbg^F7/0Ybi;6ow9$W=}{}L*g>艏ޱ_Pgٕ xş|jן%'oW^uƭខ+V>9≻ধ^TvKn=_z;[w]O]P?՟x_5WnG}a{K~Ҿ'ok_W=h^/O~xU ænMg'>O>x7q[lBwzKпm.nӜ#'^o}F>Rj5{l,E`!.-soؿs}jm] `C1L{#5p30A~۟g{Rr +:Z}W 6_|撺qp*_z{SC8g[v`;'J W\ҧ=ϯ~ {̳`1=f'=='\ϯk<{W=R>Y]'IW?0VGgN?| ~.ǧvJ)Jrܻ}D$@8K/~51Z`3Y0;DkEܙHs[}/O~#+^RtI$g?~o;>hC<_ w.9]wv~%gU)q2cymߴ7]2tu}8t"EkН?ߏ~կ7SΜ)VC;RK#I*dV;Ch@X !S'ﰟs0r1u+Z{a/|s&Иu+0mÏn+mЈצq+}_5ϯO<_u{,Lw->]{/rE' L6?ȧoiϽSuc &ߞɖK?}[ ,d*ѦvFq}y셍Q> knE|sgCq?/ 8kS'v vƟG?u+/=v{=w=?9O\w3^zgGr&>-8g{~v{?0vӗ#?/%>#{ w<{?_w5~﹭&o7RwkO^`Yk\`nwWOY>;G}>/w_-GtՅ^{>9Gg^R_o8&C/~ĭg6`uyY .zwEvAm8>G%xȋ^nؑv |%n5~''s~C;K{{rݭ9k?Ϯ7X얫VGpN>~WNyx{?叞ḴSJ)Dy#k#8x6Ƣ>Y/ T D‹/9 ]tKV;#mٺms ƎްqsRj=y_uJl6!"Zcw><=9hPJ)NmVg.(5DhH01ZrS+uriSRJq>rR֐,LAHY!ݛR4ot;RK%"hmd y`fBS഍n4SJ)T1[ >0fDDff$<=<$%Ѭi߰oJ) D6NJe>xEXyjgX)Rw΅w!fȝq0!-f$RJ)ur#{8""c<8"i6"cHjg@)R]]E9'€hL$";,q\ޙDJcdˏ#K(+R(a@ha9gpf`XB5׍v #AȲ./Z#Gp_,GFFN)R'tah0d3碈D 0.+ft3FLz^RJӉ~"s1RC cbGg12k|CYGn>oR#y3\g#n0V:әn]qpϩӶZRjYc k1B,(b !̌'6ڳ h ftE.~B.rN#]8[:smt;3VFrJ)J@@@$DD2"cAiYc jv.ᆑ.+dHr)/x\ZM)RK} !(c+E;τ(fc7:_b#K5udv#=[TGݒ?iF==9OThRJ)\BV e(y̤#˴eLg.vjޅaIFWmv0-J)r !!3aH !xfa>zt#/fĥBSJ):dX`GGD@"p#K|htg 3q΅nYٻ<Z=;sn֙Q訓GbRJ9'$ a@_x8!I;_2st-K:jIFؕRJUw΅]Ux7Z(NJ}}8NDZ5H(,Q'gRJ)Vs{ABcƀ023/]W^tqY (Rb ;( 23],3U׍,Sn+RJSH "DD 2=z4ĪRJ)B k-0gAOhWJ)Rj%͌k"b"Y;$ptygXfOncNŋ٫YҙHzt{$xt嘆^QG;^ZzگcY:q?w+S05`A\NDH(|aYR5V%:\jn|h /hGUZ(%vb_!(zڱ, a $DA.OtT`=f RE&6uRQݼMsobI+٤3+);:[SR/kEk$,ޟWVw"I7k|Pꔇ8SGH&c ̂"4E V/fyZm3\kE9=Fu6BnM_&YE?{_y˺8nɥ'hӧR',E6mBf` h;5n1ux.Zb-^nx~ӠVC+NmDD  K(,t}얱LĥVc1stf+*KU4HA4h'8Z}`bMY$'Y#X!kO4|DZ clR-DFQD,b\,:mnZ&ŬcbȒ%_'s˻.h>t[\Gy~8Οnì,Yk1Vb1tkA#gx,-1E)V޽{;>tUhT"Kc,3x 쇫RJ)F`D6 3D$vfjaʵ*^RJZD́EBN}JKC/J)^$q=3ƈ@sJ)R ),! ,, @aaFvJ)Rk5QXќgD@,M aX2\Ԗw[99:cyRX;кOsbq|XS!3F8x @B,D0Des1>a *F-)v^:؄J-@1c,QɠE8O#iAVs\Gz/2pUu119d2D:& XpyןcY49DgA9]f_o$y_0?Йfus챼[/X N!$ ^L.?'x]wiB3(4}QFѩ ßۿK/x蕿'>AO?}3gBG~;=th/y;E͹[Cwna޹Ztz'ş'k<K]r[jWYדz,x^_v  ԩj|ſ_}o?/y e;/}o~13#"0 0 <|W׈xw71̫z)5Zw138, 0@H8z7stłk?YZge҂MokpXkt"϶ޯ?=+h՝}̾+i%1a)@s`&Ahw4''ds.['sS颹ZzZМyw%֋9cK(| @d OŞptًNRN6hNکm]Ď)5-5k$ۋ4ޯ?=EM;fNY6  `*NXp韆ڔ8XHjìZgb\R>+nv%}^Kz2uwt~sgN[r}$VJ@lC"ߒ9*F*B?caj @9Stw΅]U6Zc Yk (DXrz=RJ)V]1O01TrޔR$,@P<4I(D=$yەqV:-Nϒ9-{7ϥ~_fwYNzkRNd:2DD@H3Xb{4K۪6"ɡ0ЯNѓASPTV "<;9H}a1M6KmY)jw~ϮYwy=\[bbnGԭ5V'j9_dmjNJך5d G.|b\Rk""0s`f`E9 <`SŜ8:_jRۭrmQ݂|o[ޚ-ղqs\j~֠:nHl{7*N%(H(DLa^=3# >ݭ|;WJ)N={\XUŋg]wc##k "bc} LDXEV)V)RJ816ĂH3('WJ)Z QR" qx 1!C` "uJ)RkDƐ$}}%kI$X`` 0;iSJ)T7}*@Bqdck-@!f^6PJ)T" !84`l%0sYs#Q9MFVrygfF)E/?/W6O,::RJӑxa`g" "cXB!pjgv>BhG3 kRJ Z9,躯uԫRJ\L{1!drmV;MNodF:^t3U0RJuq)Ql=1,l#{ ,\FHϦLg [wyP#+,z wm=!1(tcUn.5RQoqy; y9r !|Y}._eIG-q6*R'n޽ Kx^rх5mݖ/2ZoRJ08WH&;8 ;'XB>xu3RJ)uڻwo҇*^k?!kmQad\JH@J)R DF  @DPO)RJQh- h$XRJ!p7. ,X<9!@tSJ)R+$c!D@E:"cRJ)v`aAEi͵` c@EAr#`ʋ|tƂwRJ)ҲvCJI,0 MOԒӡRJ)uU5.gc C wO+@Ln:RJ)Jswd0o8= iͩ:]>glIzй|N6΂%/ƎJ)Z)n5UiZ_  G,by#3wZMg &m9yw&EG)R8˥3w'I\;HH@f&ƕaף8=%#SRJ)BsJpa1J' v Ni4jK):SfCL$DP_.2_X0֝9tN0+9_+t+%:zXp}RH ̈b9 80sʼn VB畷(‚/ѫ ?93:qJ( (*Msߞ2 #tfJM־%I^{OZ*Zw,S]{x?yg? 4 ⲏv2'.gcƋnHt{wbs;yϞc-xTLgI/r|e,>5}WJ[seqv\xO_T(E+ ^ Sي^ WlMۭS.y~ʜQQ(֯F R*Wj4<Ɵ|]{vkӦ #@@@VAO1VZvR= Ɲ2)v>9֝8;/oǭy" bQq {dt{Gqd޷vdL|Vw-.?"qͻ[9K|rIϽa<|A.Y"/8ar^jw[Wp\ץ/z_W^)ԑÛ7nlMM~vv8xC!W;O/^J)Z/۹}Ͽsyz2Xag(RJV+;okCX@ Q'NOD)Rjꏣ8l4H- t':MڣRJ)N=FKgmypz[X@D,:DX)Rj->LLL Hhhxf89\,jvJ)RSjx'Ƅ(JH"RJ)*[EjOq;WqVvJ)RkX@$%ÀÓV2J)Ԋ!fy4os(@EAD"Sj}Y(R+|Hmei޲4=I,wU4FQJ)H@884TJ6YK`Eg%$pJ=:vّS)^,Ny3I.fgv[\jm,7R7 Cpγk "h&tݖv[>o{y3{̒gI˻g{w.頺eO):uqp"@BrAKH"Ա5b%Պ@q4X^ZcRJb:JnEt]0pSv'o[S˒;*R "αB&Vv:c՝2u :M|{9q3"nRz>`,&ŔJQnJ)18(6V70f=sfOW;ju{4RJ)V޽{;>tU%Uk%>SJ)Z۬zٚ$ [l 0 tRJ5,`扱}{J!LO>ڹU'EVmU3_pyڹP(J寬v.:y1DI\8)8̱J)[l\\S8tds)E bR)j KI2=@  K+fsYPOD)U`f "\DR,H1 h`RJ)Hsf$jd;N'UJ)ZD>5)'IZ.#G," 3"J)Rk&P$JRƬն" 2=ѧbjV)RJuՒ$Ƅs"E; "N)R0|c_y[~g Rj[)t0Mwg ? ;钷<}VJ5DZ2]E S)(]shy-=olKy#}?2[7VRke2W1)E6 "Ci@ R+E7}M OzC|cJmw.}pw~C}S|#񻏱K?VRCCRAW6ZAD@ F*VNOo:__3gOş:W~˿ū}J)$e"Q\>|# P;)RJw=rx<Ck[nFxaOp,ݓ[E{ߑt\' 杫)WDjmJlb12`f}j%I Os(V,r呑wO Ƕ*ڊwJ[6o>v:00db HDI'dTߖI?E?/VκNuw޹@i[Yͯ<9g9futхŋןwq3H:Y|q;s{y9?tw { s읜g"ZQKWLE&%CW< E\",\*8]>=ҁ?{I,~[tKge>sz~vʹ[+}VR{Uj"H1 sc :*tzj?mɤ_uz>i5dQ􎣆GR}4d;[Z;U/KRk2~ZG,.{3?߽n]N4Sk%fv R+iefK~"Y3swv_6Vڽ}-|)i{:o:?ɫ]5?Y(>ݻsaCW/"ŗ^8nqYABB3uu3O(V.W/_?xۍ?_MSv_y+5SJ,ɾ ^l`QFXo6DTVlZL ¼+I2 0yPiuAlǭ%OyԦ?W_wnϿ=>Ǿ.\ &ܵ.7_N)`tY{?&5 7c\uF;V#ou39Wؼ04g88yәw,fE$ 'nsT_p&)߰=Mn]@O^w◺OZf`&/~-]=]Gn=O6.kjCRjl佋l$AFV ,d 0;CtwSh&N]х"uF ;y|T89w ¾ ֶֽVRVֶUZ?QRAKX}r=1!$3I&LOs;̓pqےo_p=wm燋x ?ʃ=^uex{(&|ss:@z˾jKO3[TaȦ/f_~-RS'O(̙6`C]cuu|&RJJ(iI, s’D\焻-iufe bEqܯ-,Ϳ|_3k o7#yf^ckhZvPBsMvn<̱$"J!-(رZ91i؈=Kb"\.Y=c{.h]zc1_U) ]Ov C:"J$'%ٶ%%ݱq~,D:%!&Kt]c g&-qj$PACS:q,e F=7"!t;@[zys]6cR22@pm BӀ"RrZ펍qn؈/+O[_M~ױQĉɒ=uD|{[k0SG#/U1ʼnlpudc1֩$wBBʪ4sTJJRJ#^G$~dI^5:url˲]^^YfͺDA+ p뚨5tkB# &A$^c1XX~V\& E[x:h " BBA:u#[cQxa]vl c0j뼍M;3+--%II5I"B+c{p?,c~Q.A'??˥k :P@@@ @AbclbeFX$tLp7fRDJRJ:1M0D1$C)rR)E()T$R A]O*2O69%cAFFFCC@:.:"v$^p)k3cu!"+h.f6!4 )pK1c7sCHgYNI ~j-\Y+ e6Dn2>t71c}n&c)?5a肄T*)T-]+?#KƔ.~pȗusvc}#)3tZBE.쉞6`.VS7c1/=FjvdUeu0]nJGD" B @Dױ)Q /n]1P8n>rкچ] }0ĮeB1u3c5l+r @@hn#70yԱg9:Vf' pHi\b2Nka[GIDATY9)]r]^}͜Qkw4_jCNKqˊ7Ru܋veo1MvuϿ!['蜚&1sO⊺|X@T|fތ;";^ZZJԘ9E]%vGۼ(]U)l)s|e=yC/O6`ݖ䣇|ZV(!&=pѡR*aiN>/_U}2"0w#cŊ@JRR}C]yYU_9fH Xǎ6}]KwzwĴC:+8ru}<3/ً~<;(5J=бyYIfȻr82׍{'TSyd% UQ% H֠Rk,O 45NcbV `'5=_m;J~T(xY߈m#ˈsw4l{+W/ 2~p7ߟq=?<^ N\l9M,(>wuWbxٗi?0gdr$@>%m-*GY4ܭ1X(ɞdDo3}8ى͋usD\P#,qϴU?돜 kvÔTak<.@8׏amp:D/r W^Jx$vtY9qzT~X]aðcuHziiiY2Lؓ)$DޖrzݾRYpʥ'n߰6q?=ޚKo=/i9Ot7'rƬ…苵{O{髊Up UKtθ+2Fq9YV`İ"o*rgתcU6hC jkkM)%I)D"uLx2>DnG:ʌ<|ȷp޹͹D PqeUʦ/f_~-RS'OFv//]2{G ;%6WtPMe?xE59%aFZWtcc[6=rTѦrs$MxRJ*QR*(%IJG:$O"'dg݉ӵ )GBLǻpxWL eimjb2uAٖC&X8WVY.ao(--mߢr)8g |z#x=bCudW"%䋟fc!nC4v(i [14}:_.D}K|o}]+y9ң]1XI3zmۚ ARs"Pn1'-yJ`WcScu&kJMK24Q #~ q1cۓUT10m|jGWj.ܢhv}FZ(fFSDn81C{[Wuk0cm90@^uH)%JJRRJWOtcdzbYXb?cHBO0d Z|~c146xeFrr2555y>@ PPJ$1c1zٶk@\NDH) @\c1xMH(';HG( PDHc1XUV[@%O(59)`G@jX/XlDsuIyF1yԱg9:WOtc,N!'By"la׵B)?1cfdd 59ill֛ۿũY 3{wTWagpĆHq़+Y[e9n9=w_xl}ହy jU֦w^z:`ߐ~`qոeś~ZD)ÎpWWm2cc +Yҝ))M>8 B9;vf{4~j;8wy]:tgv4ILp̼E?>8r`.\vc &O=kǂ n{Y`g'nK?_qC>{cM5_6R:&{>(B2X/v{bΜի &⫗Ziu1WqFy{ L"'RFθӿi͞Tc2`$鋮}9L3Թ:6/+ AUQc}(ʒYSS _U1),]xݜم䞾oG{jȐ!ګ/{캭,g\~//dWF7cIgAv=:X/U۩~~9ObEEUccHvBPͿ4D~WfXϩߔVzÚݠ䥪3f`3ʢ]g{Nc %=DOt+̉rSi\Cɢٲs׎m;꺷c['FTJ4w;^Ǯ#c2Nk근 Q6iyyQֲ8's]^m]]-Q't͂S.=9u-%dа,֙^\Xte~rS۷w wyW/bex^:;.is)3n$G~g: *V)'~Tg;/0f%[QA@xw"9H)i;R:R:D KS'ʶL Ew?=' 4Qo"-})9~4 d|>jHx4mh>{+J2k/=!S7=Ao%/՜ J5TSeoJ=9>td__ T$rh]WVY.ao(--쳏Q\l-(+EH))R:J_}<ѷK&vlljc1wUu@)E &tD$ )F@X1cGmmmKH)"RJNJ)RDbC1cBHIR H)%!v61c%ah*#3ͪjϯ("4 Qu:/m9VcWB]ד=C%'%隦kA.&,#nk1zXM a.ѫwa1!5Ze뺆:(BШ:"PⒸts#w-4чs.c1h @ jBU!*b{ToKb<1Xi;";9%EGD!BhDZv:Jk9ؾ#51D!HhnEyN ]1닚|MnWJrrJj.D?n)> weK.]o0BBpG-D}1m[1c}s3@eU`@ojv#xӀ9ND 7ͥxc1M3giZii륔mH!&OĔ.D3M%6at1!^6 QMMZPaX[z[^ cɅuذ4 [ӃdcW_or' 4] @Ah~>q{됱.”iW)I_UqO[.,,g\>J*cMS<$dzF%yXDD"38f~SbY3-9}T?='7zSzϯ35{3O Y|2'"muygņ@1E5mT$4<;Q"EJIQY4.0k[ پ7uAٖe'θWowiGE rƝ}y3 I7?7wZZYs?qZ~2 қkj{w=9dG`gQ/՜L6.ߋWV7'"y s|Јt_|Y:!GهH`-zvX~k֬KtAJKK#:yrAZjzJzަƌ Q :Hɱ1 ~K2G8)~3 cVu 7`-yJU; Zo J+OS$2ƞpW\Qs7zzzG=ҲĶF&I\|VV`m퐌1s[ffeIaX +o:v 뻸˒Ci>g~̆tvZ1:+uYzKK@Qs5Ghjܵ$3iUlZvcpEK]X^KIΚW[ Le[2pmMʼnhX6rDlV$euNR@B NX?4d}OiaF?6g٣t̼g/wPM=}j*/$bӿ`qOpTO/rSսc,$ m|weRp:(%@@M9?ܷ5VP[UAE?TWe?S9P v<>8[WO8섙3/i˟uJd81C o@H @HDDU۷WwU[KqzgŁmj6o3eCi`EW W,u|[kʌi9StM&[ZB iڼ]!Ρ"ۨwP+uGD'3\ÍA06NowշuO֗{U3z˧Uμ7Š+#=×?t&cSDH7< m^V0`n]856]&=-6.Bp.,ǢѺ9a/>_n8\}޸x*>9[?9ǟ5 ?|riHvi'\aP~yM71zcu5u.-ЦO;MtI@Ds&G}( e]Ό9KwPeى.H`zye5]H^EGtò$0ցW%&"lcl21X B0e:HB$T:v1Fŧꫪ(mLKKtQc,^<)_wi)ifYu `f(rQhgOo3\ZI[+H6nY;rxb1XwaP155}С H(B D&c1il󶵾ԼcG$=wyͻI;ooNW{\y~q/=&,nMMLRJ  "Exȸ~zZ<[0-;ƻ/,+[)"+nh8;rl}$wYw3_?叅7<~Ukw<Cڿm齗jsm :#ϝ{c+[/N&j@umCfzKs5z5u[A(GE b1BȻ_'2H`r0lvo4Ro+ENEYEQs2({LgY[]&ԌA3tU[]ffN7GёS^^UT+0`,Ѝpݹ h]fSeSChA9RuXS]Xmp1`& rg {~v;ߘPyx@>꒟RomȮ)G@էOn,v]rn;<ؙ]xr'X>mvU;v.7B'$Ԅ8?Ιo$Qr{WT~k~yV\oͿy0C;ޣUyL*zivxߺSl ϸs3S4UZ50)MCPUwn|uDHzI;oEbo!r)i@*]ծmSn935Kﶗn嶿 x}Ln`ۑ][@X`oTTm >dRR*qv\=m$(*Ҟ9wy#aq?,] k 'gStRZб:" ' ;?#@pc e~#\DN=oI{"sÆ}f_oS~ipn.xƀ_sB($(؞0"gu @or%D"R`-TKjZT A 5D;RZEgŶJ+&|{$vkI7߸sН{agn!_#tLk8 3plه6P}[q1vXcPܞpeǨwJ ?'7=Wv)ڱރLpG3iʋ.Z Pj)Q /}es}p}.%J|؅"6cT֍)4@^^ɟf\V .HX^9s2g~\഑P?'\9YSr|}`aPPs(*X_RWo*BiIH)K}5k ~ 9w>lSR=OW @?$k voݸZԡnk.oh}zZ8)?]NX/56Uz${lei&ΐP+]( p+O̚m7k $ ly3՞P՜t)R (Mئ;kPVJ .ّ1m̸2[*t{Ƭ'ѣ?#*E*X^YGFRM|$@ᙤvo-EY`qk;1p?{[?x3/ 4zY݊+ מvsuYQ9'e[,^T⬾oue9A&K'P $PHn/xһpNLT`yA7`P령4|=-]HDd}mڴn;|M:G/vMV~ںS;jU"\!8F$PlМ 5uysƦD_=lyYWtJ>tι'|An@eѲ=Y9Xsz ]W^4U|VLH)$# G# EAS[qZ 7±NOBǮu<&.rՁG hDqӟijWۏEUG{CU\Q0Ug-/펷pE>eKã=yrmOt6jں>d\5%|k|-ѷXA AGcI% Ͼ6RlHRJ:&f%Ξ|Db}O*{XLRZS[N^V;(۲D0tz͚u.KN?a@%*"I:(B@D5c>N-8lFi9a"@8%HHB;! g5%z5WMt1c,bN}Mu9hc*?(t< IRI'QABib{:wev|~ʌ1Xde+R\MM~H V;AD!P ݿ+ZnDVc1L8`X$iIJy?=g5%6!hߑX[Q$Ώ }Ds?t^k}=tYk+gLy1TA,%m)r,倮9HZr'oEi3Lŏ5`z~wn!Bt_[D;kcJeA! Mi# D3PzU9 kV~4=|MݏL4 ݖJZRWHI)II"RQ$vluSQR$+6\NlD?̺9O-%OR^U }c;c'z}a[|{V+)soQ}"1pIrs<-Xߕ+syĘ&~o)Ӯ7SBYo-^П%e`P:(q=-v@J"*"8*{[K؛JǗil}XI?kFrasoh{cU:O/+\+fΘÎ;;on0借v,x53/7WN<)PW֡'mN9;GϻU K  `ҶHR.PIj1RiknYBאG =[;,'Ϛ{!P^\S+E/9oƘ!&N+GOWs L3kGKw6/z3/,j8^o6.ߋWV;`}7MϷϔ:Wu@GLDniSG; {^= >|௯CY?[7s-m >dRR*qv\Jq़+Y[ߣɟ0:#N<2^7l#Z쯎8q-Ⱥ]p/ĔslaI UU!1yy0( Ma" "5/ GJvl5.7qopcbi&YП8G&F_Nig{,DKL5bꤳ)~V+5k:0k"kw᪵En ¦8|UrʈwJ#Fشz @1運zrO=YHsC]\ɷkCLK_U> _<$yT6TU'=gA>*_U>Kt ,R t"B(!xXXB^U}x闛j,#{tE?C}|dW5T*`M"2J]n _}'|z_\aۚ1ӏ-[Ź FWL.'yذ>1/&r^:6_z{G`Nt4D"(#1+k- :D3]IcKVGn]=fμ䦙g,V~dž9髲`@m'ʑ(E"KѣFm߱s ӓ;ҲLYXmaR.mP{}a.;Fs?VJX?o>v'iT,zoAc-<%P @M!D@D""R'ֱmJWXTw&8xW"m!F`EW W,u|[k>Z*/k>+ޫ[;Z],}UM>twd~}e:rj}6^y7]O?cϚ5javsYSŋ='2 u[;wyCYSyc-jްq0 XkjCUm!%T  hB5D(9Tc1zBpGoq72ww;}f1Q/6 ӎ"JvDi`oZ@ VzU >Y_ss쵟~W7Ȳze9z<:Cwŵ }˖Y|E 疛.s~-/*q̒}ssYp}i_8W5C}RR+O{/ wB@ DZhh~0zSs=r*WO; vk_n8\}޸xu!S?Nsg^r۽ nkv`lxTEWl׻r)G~ىnfw~o˂ퟖ?g_8u+_}o"ɪ/^z}/h^ 5]h kxiB:RHIq϶dQ.i"G4~406..E% W.`\D9~Y|M:9wPeqz8E5k% ,JKK#:f(fh!2S-eRBPDH)Vxgw7$[F_?-mT>y`1N)(ԔQBH(P`$G3clCHi uq !@qq2!BZ Ecmي2>Dݵ;'u#oյzEyK/ecoQ JL@Yr4I@ )-O3q  Õ..C"nfㄻn8]PZws}c% o @vt PH)3oJb۞Ko+c1;"()ANd"$ScmyU6ޖ$Dx0c)jG P :@  04"Z%mp]Ɍ1Xr,BB$t@0ܦ#mۡ- c?p c1 DRDlr$H=I)#UFeBÍomSG#C]Q6Z?z.Yo~e2M#E`"R(P4A?9Rtt,{߉.0k7O`U' COtXcNy"zNw8hR7t]qRNN@ HZc% uf)H@)V9!Pf7K1c @,iK%@вu"BDD$""R*Hqb[p2c9pg9yTi,ҷ^jwfzJ*.\{ 姖 :7]2n}0yY44W/]rt̏o.c4%"*EI(DBD"t@^1t8릛ִi٢yw yqS@zSzϯ35{3O Y|2G$O?sO:%T3.<:}-8mɿ-Tdj\?;*P0ciaBw M뚦B)ilW,c1+g_zưŏ?MMq_͛6W+(n}}Ed̸C<9<`O,mwmdz~4GOl. 𤻡qgŀ0V)E4 PH@!H$x"Fx{ϭKKZ顢vs%Y*X1:?DR UԛUz){8$422P3Z+e$ɠ"R#@np_2Y{LQEy~5EHPnjcn81'џ-GcW`ۧ>QS\jh[=._}du-'/zM4'Ydf:U$))};.'myMT;H?޿N'8bhp[xX~cKiJ4 @B҄:(CTc= cos;OJ[O`Kv{ҬOPagM>Iv֐3/+Տl㼎16V9GJRR(4""J쵥cQǬ<<~qÙª.Ze˅ؓ/eƝ_,w?el漎1BhH%)PB2 M" .-c @C~ lZp3;@GZ9%'_fcar;pD1YM$Ipmt0TuMm[.C4 qD!BZQ!\e6NQt}Fs]$y(w!9CK/˪kJBg,0H)Bh5wah& C'%<<\_UqHת.Dx^ 2Ƣf}j?654}96o\9\tQ-p2)rV8;^{C.6Ay{ԙמ`GXs sC$zmu24$˶QJT䉻 M3cE1:ͷ[ tnW-qK1e*[XL:>⚿ [wg~̖O{} sGü?*s=>Z_֤}%W֨a ;`(T )ܺ±޼Du6E\N7 osB)uc=S=@_{p>pϫt3z[̹9?7l]^'@wlzǫJR&铏cf k}M~R=fdAfj `]Ee];v&19L-Hmkmj2>i;>je{:Æ]&N捵˷@΄OkPWRo9ޯF,ɝMMz$vc;`Q 2#Lveb` ='~w>b1o/? -zKOFvymAi7ɪ_]Vh9dI7K-i3;S\zw_˲㉾{Vp) :ǒ") !Ivr1^ʸL?޿N|DhS2GImZBjg=i(/\KoR{x~5C+׬Y肰D*--ă':_)%@ $"bdqu1P[V5M2 ^|uն/']saXY!-M%˟}lnȪu 7`-yJU;[Vc*-tt(B"PQ+/d.7ۻGƏq_WuҦ`Q>n~t]Q*{QfEX$IDZm[I 5 u H"@(It". ں\}.sםϗuWǫ9O{ڡcMw78?KTcu4cE>{яRuXXTHhR*MB"&Q$BE4xe{b7hu1=:X/U۩~~9҅ܺza'̜yM3X筮(*S/Z5Vxb/dBH񶴬3D@隦 @)@ t$wŴSB~CIU!,N-Y]L}ĴSE2z({~Yھz? ]C+o/YSpy7u@[qb@m]tPi{vV$/{w_7^z4щW=Dx Ը⾫VtR`]b[OU7:Tgֿ{d}B$$ԕA!HDDQcUם.^+1c$4BS#i  @( A;m1cP(JBJІb-C-kgqZ 7]-ۜj=T]73K- cRDDB.qH* 5@@@ ./c,W,ۿ$^&#iK B B+Hc1֋@l^q"R!J m;cL A9iB C{SF c1K]hJ)$IM@$" Bc1XoF*PJHD"'DԲcƳ(XLHt))3 D:It!4  ~6ˑtAP8^7ByMyp tnKHl9{!4 COt)XcNX?HQ Eh"NB @hwK\ҔD-օ%\3}k3 \r/{f@hB cI!4$҄kJ)"Z.~>2c} ) " Dh R7W.?T \OM)QƇآ<98"}uZ?sۿ}bŏC3O03]c=G(R)t mphJ{.! @t:kin']t<]cҬfT]{|F9ou3[PHEi TDfJ?mxF1zehRH@耂 -z[S_+ܗb^4]1Xq{\Id]76hBBA(yR_P̍(1g4JI]ǔOR[7tH47hZnRtaqp,0.\Cmf_ƫx_q.b} z yKTc[cI4 ǑBC6x$RJ!(DJ*]`].ԩsey;5`gm]I%\,JWVY.ao(--ꨩRIv{_5o (@(vH014stڬ#ATmYG|")++:` ='~9cБRe @Q( T P) @Wc+=2cqIξ ʠ3μ1ٳnz@ c}5LNK[J)!PG] hD g1O<2Y?H-(<#N1X/E :~Pe8Js$D@) $$E`"%/ ?lJ*aT[bgח*3;c,tC4MT@@Jb3C{"lIn +-ߜ1];5eQMyXZZio:7%cEv$ !֫C@($RkKՅ.,Ms4ۅ%%_/Lywcr +ZAOlݨ@)M)\1 "Rп-CB@M$O  nvb,Zmn45sV;t#"o;Յc#5]D(G"ղ%WitZQwF_3cf\b/o|%=?͕A3ga'zOO |]vs//.ɣ3t0Ω\b| nSȢ/ ~5 H#H )T d BR `Obn'p P_+X߅&p]݉95!U*= =}l_—t:عWhoJ͝NG|:ΝyuPnƯ*Di/.ٗ_T_<ѥ`ou4!P4LSB(zFvvc]BPHW].[D1XtM4@&4Q^S .BP#"m)c1zn4B,4yflmrc1XE$ nGēO! }A 5v놉Jqc1X/ D$DJǟxB ~h XӒS"ED1cEDJ*"HRqczv~pQEuMFf((U!_kN bQ?p{3c! "H)IJu}ذagsN^^+/e6%j\VlﰞA9c1R@@d+)D:"@jjӦԾƛ|Xc1(J(IHHDYYYXhQSo׮5D)}Ycja2>tgb".;Ft׍'1Xb) GI! t9JꄡDN4+^}%r!NLϽ<ck$) 8R4i=cR8Ѷm: ۚR!!L`%DcC `󕕕-__Ota6ڂ1cC@Q؎Tt ,+Æ DYO,:n|}mc%h=TL˲(Gy5c# B۲~MMMՕU+Wnbێkm%WO;}qc1⫴4«ǜs(R|_~')iƌ8ѷc1:ah΄p#Η_., 2:ꨣ:6zkc1= J j8Q`jjE$0V#b *vxG#3cR*(%jBӂc8(b'ɖ?.wRW_jkj`в䞗a[u=%%eذѣF&X"Q0zD - @Ĕ sc^KuP@)RruM`FFF0,K T q/mf'))#33-: w" } m+.,PPPc1"ڲe;xp㓒B%M"$RO2|~ؘ2j{.2c1֛ tatPzfҖQn͛7$''zKS\PV8eYMMM۷o߱cСC]l_#ں; -ZQ}{ }1=====`ɒ%d@E܎1X/'P)RlA)NE\ hRSS[uiZwxPJKB}a8{6hhl,*|I'r>h5͖͘9.Zhذay4Dv5MZ>K=1͔R@T0taNDFo @4Mӱ,0h& :B lZ(XuѣG&%%%ZXwI5M -2z;vmB"Cmۡ<"3c)" [:t ] El,[%'(P@ivy]k;uee'Mkc.kРA6n" uRȾ;L[wDdc7 Tj[3t WnlaFcSmD*J`>K}]]m1' q:05߶eBD)%gu"\:D$NrKKzϹ%m‘P@4rÆ/J޸ϼ!m{OdcCI <ԄY˲Æ'$C0hN4akci ovV䂎{W[GR]?j[W= ~ǥoWpTkvQkC>\Kc8SOTc@@*P"I}ݮb˲Iu`I˝!F6ōjv?+wmvl^3u? {Rrٯ拧x7wb;q`"GL M[T6:Hv#ÝQ^&#ݮR؜1+LP #isK"ZfMN>3(ɝaz|Am:v_/T3/Wm󞿝p̛/?}iI+P>moW_LN)d-vu.,9G3t/˖r1Ya"yCwZVȃ~ 2a1ƺu!@: wxk~bMrrӦ+v;-E?`줉c&N0dsϮ}o㹯&OĨw^x6oIQhwKIG_nD`trx\uל߯r˼*T _?)GK[Hu_w}ֵyAq["m#xKv96Ua?M=6|^6pӦ]+eACg?)d:+QpvsM]nͽ=xу׋o~qG?M~Ou4;~XWw-{-ʂOgMcQG(mێ.4]s >/bT]zO9O?n|" O?Cxܟ50drδnM~oQ}5Q[Yʧ_X{ Ӓ1'?iVykR{[Vq]׶Œ]h w }_^YѝYΊbE=2<|1 =e2?$2!> +>~{(0 s/?$sO=YCͽ ]̟^=WyP{\}`NcTdOfF"֗E]7FnݺUV&T\~|=d*IQRgФuLtm*hE"6λMg_,w`Ճ??Ĺ:Zi\ @{~>cē~q5 s}z?f= pWmșWxɌ#я_ړ}:7xg4hۇ➌NV6 t9w:!'{\#<'D]9qhi#&N a+$7>;\μh!C aw_30\'跂AǑ*5QRI@EAĠAf̘qiuBA˶4ea(a vZl>,7gehm_S&rs^~au "S`z+QϘ4|i?tVn(<|SŇU34~{ʦ\1ůqǛDpd^kX'-4RVbUqgezrs_yYy2 k6r!%ږB(V +)Cxc M>$($)#8$T@i:{IOn6A @IRJm+ҶK[d&s%j8*JxHkYÆt4fjm.O,X[R7x!Da;^/^q=}/hj.Ϡ//vx>?1NLrajd]ӕ I04 y+K즎gfmJkn~F.TCv!y_Uzf;k/x+m8} ͭ() ݟ nBr 4>nZ?AʉYÚ[n NzK9]hξ5iĄ+[0YgTm8NBum44hnYW)iĄMwfpadD@߯7?{ëvWهrƵ[Uˋ9{ld1mi:K3Pw^G @!}A7sڂkl5ӧ7>}0|m4g+RJ~8񝖦}W>, _6\*PWGCרqzꟻJJF_))B%y_Pl;cͼk~ ?_Ox77=-S0tѦB͆]3N"KS1| ۞:vvmӅRG;~N4V.ݽf}Z'weY]:ɸ(d&Gn5N:w,Г^{Z6k_nCx(c1 ]@"˱ -B&\[ue9vHʖ6CR\w^uڍ&SR߫nH9eGF\4qi֗d">秤nh:t4S v~F34z䘉cie9'9EO7?4@7Y9(rq.#hϪ$1ckRRQ35_, w~pg|~7cM%몇ǜmhhCί6y+\ R Muw27f„&0~XjӶ~sPAtoc PN&I2@B$)Jfjjjm۾m6;8UڧeO,SԇɐffxR϶wՕ7uU}s뎇 [yb)]qɫz˶鱓SxZ\ɡh=/C.8$@3S\+pMʅ{y}z7<ݿLdevA׽K9dhS5crC_m:ݹ'$6vB1@ $uڑ*~#:۟iM_.YvY̊wkiODi$ޛ뜑sOV\=gYo,¢Of* ݊c]i6j0T8k[lɲJwgeɱ '_pշw߹ ͙u42SO׿ѢwD4:lӲr˳7>~/0i؃ffKh;ڃ=Mmuѽ7<4[?H}S P$"Ypg>1S>6kO>Ŀz6@R9Pv}?UuS/v"H"i600STR@NF3;h laG,C?95\#Grm=U3hz0u_|f֨C/gg_1ATAOP s7_~veum[Gs 5''ւ'LUG*|bwݙ;PG˿Z [[[aÆΜi{p'FQi_㎳mHENj-]0?gq|WQxzE\|q@wemec1;͹IDZA:RB 𨚊ԤC^{b!38'qӍWn?%ZX ")cg$jZƌO8 mg8D>㸩o,-bdc2\&"0,+@O\)n;Jv=bX0`hZh̉7w?hu4lj),s1ZORȳ'1NKIlK:]htΠߗ;('{ 4 !x !4MT+,T(CD)xJQsc^.hKR1t4kllЂii R"~&s\HIUUU999b_QUUUrrzdGVJi\dc7M^5@Dt=33#45t]CSiqLU fH TRh\..% WJdg lٲiB~HtuZR ydg۶ ۖ2]tb{>zv =1͔P H 44BT+i%]J:i):xp uy<;w93q@0PYQsNJ Zo loJJʀ#]n a9tbOBHGcjDQ#@ttuS IRj(ʪohPJu?#@ J{iۖC:tTJ[lj9QU]2 I"Xf; b(Dr̞cf3%r4@0{)58o;tOHWK{[K\0;f rKt'80/t Qi5'^(rÆ=1T)C) 4Du" ]QԄDZ WUUUUU]^^n۶߅QP;_ZjjAL]Nt4mqC7n*`)[Ϥ 5gfd ;#5MȌ1XRi1H(4Mzlh."d (r ;nhI'"mq[+맥|8>WȌ1Xoּt@P LCׅz44\R@ .CDZ-; I)Ec;##G)8PJIIJ*%*R ؛6m޼ipB P@!!9VyT醞$4@@H?!wp[x`C}M,[y4MKh@߯iFFFB uJu"rDlۮ"˶kjk5M6bxzf*ƌ6MnDzlg]BzSBhH:N @UIDAT>|豣32mDtݦi"ﯪڶnڳ>b̈BQD! 6nloTjk묠&PCBDjBD zaq8a7P2OCdU7Jk6R'Llrm27@c=8,gy(E*%ٚӲ%2F"-qPJ:o)i–d/K*rD]~tA5 1ҽTEwտԢ|\~u?z<ӑ6]Cc2D%T] `Wyeq^oٛLNLef"icV[;32Ҝ4Z3F122;Χ)t=>{ {ᆲK:HH9u9,{w7P k#:#H-s,ͭv)IXi3eBѨp&`>Z޼uws31"DBF0Xh#\e6w]$gݝ2nononz^OƌXV~~/r7cx/秧LJ=ُw1"Oa>{7oON{w?N/ex}7C[Jf~Lw6iTH,) U&0FAtt ̈h֪ %erDF9G W&w PZ_N]4f,!JAD%2ʪ@D7 J(5 T4M)a_~g}6M=Ui<<<OO?/ysszBrq^j in枑kU`VѯꛮNĩs{uLo>3^4psx]Zo76o2e*-%\h@2 F%A4biC]o)e[s5 2(|Wuv(E)uDdB s,$ͼ5oEJܞfF+M%1K2 ,)NyyHv=ef0SFS ^qF+ 4J@>OfZ_SN,r/ԷK jE4gl}ZG%#c,k wNTJ!m*/=̵`mmւ*&2#xp'oCkd!@TKö":h!&q/47S+R G&,iތ"mS׽=s[eQXFhCny\jꮑ\첚EbdpBv1"" naBc4 ICrL7DXu~'y:է6fUS}Y*ϲ,Jsqq{{{wG0.BӚu΢*T/JVsD F7 psH3/1VԚ8N;SC"Uފ:(nFP? a@rYnoC:yR)|:E$ԣYﶛLJO?Ix|z^q1r=_Ƽ5[ 4Q3ad %#Iswߞ[6[FÊ\iUx1Ո( {YA5p0b@zrHֳ.m,7faЬlAβzbh$Eظc 15f$ds$+֭3+&h M jJK :Nz^,N& ftǩQPg;w ~.j{AyvY^_gחbFȼ.W%UW>f?{F7OS|D~śaPSƐ4b(M/ Ld77h;̙O/ Xf\ՌRD4zݠ2S^f +[Zff2"bHFKp;I/Sp~f)$z̩ իWw"twާwp8>ry7C3W#$7[cc7S\Ic5QFl!-32+6(@9ƈ0dR"G5/ `6 .+:EJT UMnPfM =իxI"7IB] YvƴA*՝1bIrh:btoTZ]DҠr#E-^3_uM3hny9h݌ d2$Ќ2\fL!e*~=u)42Gf!rXAe2, xHe$f'y͙Q8ύu 2Hh\$3/ͷ$E2m+UûYXr y"֌rC^,͌E(ݬRE2):HbuDVC@lI&wSf$h{O3ZhwG5z0V(fIwSn-mPs$(nBaܜaޛ4RIGlEi$84g%甦iwY ?T{2FZl*.6>`ennu*03'f),Ƃmwss|LRAgܽXk-# 2!# J:R!3s13 X$yjaƻۛáOM2F@m_޼=߿[777M ?>>.˲$`y Oken7s)3?Lmϻ^~ wOvާyeY%"1Ox鴮ͭOMI. *ER4'j~*Z eFU\2QXfyU  Ĩ huʈ,u nJem^HeYOS/rOyvnG۷ߏ1_yfޯ?f>.!UZi[[W3/fX s눵kR3~p, yva* Tm|:rywJWlk%LYļ!C1}UXHUmnp # {fR9$d m1`*|3mM`4` FlIF|h1eFes &%O{5'ZW%_p6MBidcX:2N'g N6=^Na &wIS82bztѽ:Y\QOƠӦQX3"XU`k{&œe13%SP"Egכ&+003PL) mS~;bc8ˊJ(D 6 ^EV^D[aFPlͧ+23)m oi!lIvXjA(3\R9Ƙ\];FXWQ^l{*`{k"rYWM77kLq^NyΧxaay$HxeM۲2*߼A.$d&1[Vn0hD)E5phQL58O}"2&FZot+|>/2_11E1^߷R|x8~wwz]n77wOH}~ͽcL2݁vFXy򼞛|>???uH||vO>]v4yg}#޾^}/>5-}Vep[U6$7.E 5#`ShMոܷ#̫W\7nRhEc/Y07?urU?*]e,L̻q<߾}??`f_~{z4MӤ Gí֚gk[ZrWԴ?zkO$)ན~?}vz-Au,gVS+7* U5Ns2֦6Vl4Z_^V( tnd)p~~xLJ~ߧ2#ֱ <2Fnnƈp?w7_~EQ3iqf,Ar ֚w4Oy> k>Mhlm"|:3pw//'f|߷־[u{3mf=Boymr`4*x_̼ud.e9Hni򸩺涡r"@]&jVnT"OY3|^hTj*ddHYϳc%ux|leTN:k|>o#5mT(3"RTn?>ƨ[ltj6zV]8m58lS⸸!7 *߇3>>Fuux=Nf3nP5)UóIt1Ѐ$rzVo뺮z:so767$So^\J5)+j#40 P-k3rbHIwmn܆}iLԈLe2 Gd_ʖ-R`A]II#cjf"+f)fZ%֬FƩfŐ %j $3eJ;^Σ127sĊ6ڿw5O[,Yɢ€$4Mu hx:~Yb,S<%3؎mnDu c5c 'h]Ԉ]n ܱ!wOlY=31f 2.0 TermIt terminal emulator termit-3.1/etc/000077500000000000000000000000001362242615500134425ustar00rootroot00000000000000termit-3.1/etc/CMakeLists.txt000066400000000000000000000014471362242615500162100ustar00rootroot00000000000000# Copyright © 2007-2016 Evgeny Ratnikov # # 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 . SET(TERMIT_ETC termit/rc.lua termit/colormaps.lua termit/utils.lua) INSTALL(FILES ${TERMIT_ETC} DESTINATION ${TERMIT_XDG_DIR}) termit-3.1/etc/termit/000077500000000000000000000000001362242615500147465ustar00rootroot00000000000000termit-3.1/etc/termit/colormaps.lua000066400000000000000000000031411362242615500174470ustar00rootroot00000000000000local M = {} M.tango = {'#2e2e34343636', '#cccc00000000', '#4e4e9a9a0606', '#c4c4a0a00000', '#34346565a4a4', '#757550507b7b', '#060698209a9a', '#d3d3d7d7cfcf', '#555557575353', '#efef29292929', '#8a8ae2e23434', '#fcfce9e94f4f', '#72729f9fcfcf', '#adad7f7fa8a8', '#3434e2e2e2e2', '#eeeeeeeeecec'} M.zenburn = {'#1e2320', '#705050', '#60b48a', '#dfaf8f', '#b8c2cb', '#dc8cc3', '#486858', '#dcdccc', '#709080' ,'#dca3a3', '#c3bf9f', '#f0dfaf', '#94bff3', '#ec93d3', '#93e0e3', '#ffffff'} M.delicate = {'#2B2B2B', '#870000', '#5F875F', '#875F00', '#005FAF', '#5F5F87', '#008787', '#818181', '#414141', '#D70000', '#AFD7AF', '#D7AF00', '#00AFFF', '#AFAFD7', '#00D7D7', '#CECECE'} M.mikado = {'#322a2c', '#a04363', '#9b9329', '#bf7a29', '#6a8c8c', '#856774', '#757978', '#bcbcaf', '#46423b', '#ae837a', '#b4aa30', '#c7a551', '#74999e', '#9c818e', '#9fa590', '#c1c4bc'} M.parkerBrothers = {'#322a2c', '#79220E', '#344B1B', '#B45B00', '#434045', '#5C1E25', '#394745', '#AE8842', '#46423b', '#AA261F', '#76550F', '#B57F02', '#908862', '#624A35', '#393E38', '#A59058'} M.fishbone = {'#293b3b', '#bf5357', '#41a551', '#aea64f', '#416ea5', '#bf6053', '#714da5', '#876868', '#344040', '#bf6367', '#51a55f', '#aea75d', '#5177a5', '#bf6e63', '#7859a5', '#876f6f'} M.bright = {'#000000', '#CD0000', '#00CD00', '#CDCD00', '#0000CD', '#CD00CD', '#00CDCD', '#E5E5E5', '#4D4D4D', '#ff0000', '#00ff00', '#00ffff', '#0000ff', '#ff00ff', '#00ffff', '#ffffff'} M.irc = {'#000000', '#800000', '#008000', '#FF8000', '#000080', '#800080', '#408080', '#C0C0C0', '#808080', '#FF0000', '#00FF00', '#FFFF00', '#0000FF', '#FF00FF', '#00FFFF', '#FFFFFF'} return M termit-3.1/etc/termit/rc.lua000066400000000000000000000010161362242615500160530ustar00rootroot00000000000000colormaps = require('termit.colormaps') utils = require('termit.utils') defaults = {} defaults.windowTitle = 'Termit' defaults.tabName = 'Terminal' defaults.encoding = 'UTF-8' defaults.scrollbackLines = 4096 defaults.font = 'Monospace 10' defaults.geometry = '80x24' defaults.hideSingleTab = false defaults.showScrollbar = true defaults.fillTabbar = false defaults.hideMenubar = false defaults.allowChangingTitle = false defaults.audibleBell = false defaults.urgencyOnBell = false setOptions(defaults) setKbPolicy('keysym') termit-3.1/etc/termit/utils.lua000066400000000000000000000024131362242615500166110ustar00rootroot00000000000000local M = {} local io = io local pairs, print = pairs, print local table, tostring, type = table, tostring, type local setEncoding = setEncoding function encMenu () encodings = {'UTF-8', 'KOI8-R', 'CP1251', 'CP866'} menu = {} for k, v in pairs(encodings) do table.insert(menu, {name = v; action = function () setEncoding(v) end}) end return menu end function pairsByKeys(t, f) local a = {} for n in pairs(t) do table.insert(a, n) end table.sort(a, f) local i = 0 -- iterator variable local iter = function () -- iterator function i = i + 1 if a[i] == nil then return nil else return a[i], t[a[i]] end end return iter end function printTable(tbl, indent) for k, v in pairsByKeys(tbl) do if type(v) == 'table' then print(indent..k..':') local_indent = indent..' ' printTable(v, local_indent) else print(indent..tostring(k)..'='..tostring(v)) end end end function dumpToFile(func, file) io.output(io.open(file, 'w+')) callback = function (str) io.write(str..'\n') end func(callback) io.close() end M.encMenu = encMenu M.pairsByKeys = pairsByKeys M.printTable = printTable M.dumpToFile = dumpToFile return M termit-3.1/po/000077500000000000000000000000001362242615500133055ustar00rootroot00000000000000termit-3.1/po/CMakeLists.txt000066400000000000000000000043421362242615500160500ustar00rootroot00000000000000SET(PO_FILES de.po es.po fr.po hu.po ja.po ko.po pl.po ru.po sv.po zh_TW.po) SET(COPYRIGHT_HOLDER "Evgeny Ratnikov") SET(POT_FILE termit.pot) INCLUDE(${TERMIT_SOURCE_DIR}/src/Sources.cmake) FIND_PROGRAM(XGETTEXT_EXECUTABLE xgettext) FIND_PROGRAM(MSGFMT_EXECUTABLE msgfmt) FIND_PROGRAM(MSGMERGE_EXECUTABLE msgmerge) SET(ENABLE_NLS FALSE) IF(XGETTEXT_EXECUTABLE AND MSGFMT_EXECUTABLE AND MSGMERGE_EXECUTABLE) SET(ENABLE_NLS TRUE) ENDIF(XGETTEXT_EXECUTABLE AND MSGFMT_EXECUTABLE AND MSGMERGE_EXECUTABLE) IF(NOT ENABLE_NLS) MESSAGE(SEND_ERROR "gettext utils not found, disabling gettext") ELSE(NOT ENABLE_NLS) # Create PO Template file 'termit.pot' SET(PO_SOURCE_FILES) SET(PO_SOURCE_FILES_FULL_PATH) FOREACH(SRC_FILE ${TERMIT_SRCS}) SET(PO_SOURCE_FILES ${PO_SOURCE_FILES} src/${SRC_FILE}) SET(PO_SOURCE_FILES_FULL_PATH ${PO_SOURCE_FILES_FULL_PATH} ${TERMIT_SOURCE_DIR}/src/${SRC_FILE}) ENDFOREACH(SRC_FILE ${TERMIT_SRCS}) ADD_CUSTOM_COMMAND( OUTPUT ${POT_FILE} COMMAND ${XGETTEXT_EXECUTABLE} ARGS -o ${POT_FILE} -s --directory=${TERMIT_SOURCE_DIR} --omit-header --msgid-bugs-address=${TERMIT_PACKAGE_BUGREPORT} -c --keyword=_ --copyright-holder=${COPYRIGHT_HOLDER} ${PO_SOURCE_FILES} DEPENDS ${PO_SOURCE_FILES_FULL_PATH}) ADD_CUSTOM_TARGET(pot DEPENDS ${PO_SOURCE_FILES_FULL_PATH} ${POT_FILE}) # Update .po files and compile them into .gmo files SET(GMO_FILES) FOREACH(PO_FILE ${PO_FILES}) GET_FILENAME_COMPONENT(LANG ${PO_FILE} NAME_WE) SET(_gmofile ${CMAKE_CURRENT_BINARY_DIR}/${LANG}.gmo) ADD_CUSTOM_COMMAND( OUTPUT ${_gmofile} COMMAND ${MSGMERGE_EXECUTABLE} ARGS --quiet --update -s ${CMAKE_CURRENT_SOURCE_DIR}/${PO_FILE} ${POT_FILE} COMMAND ${MSGFMT_EXECUTABLE} ARGS -o ${_gmofile} ${CMAKE_CURRENT_SOURCE_DIR}/${PO_FILE} DEPENDS ${POT_FILE} ${CMAKE_CURRENT_SOURCE_DIR}/${PO_FILE} COMMENT "Language: ${LANG}") INSTALL(FILES ${_gmofile} DESTINATION ${TERMIT_LOCALE_DIR}/${LANG}/LC_MESSAGES RENAME termit.mo) SET(GMO_FILES ${GMO_FILES} ${_gmofile}) ENDFOREACH(PO_FILE ${PO_FILES}) ADD_CUSTOM_TARGET(gmo ALL DEPENDS ${GMO_FILES}) ADD_DEPENDENCIES(gmo pot) SET(TERMIT_DISTR_FILES "${POT_FILE} ${PO_FILES} CMakeLists.txt") ENDIF(NOT ENABLE_NLS) termit-3.1/po/da.po000066400000000000000000000035631362242615500142400ustar00rootroot00000000000000#: src/termit_preferences.c:299 msgid "Audible bell" msgstr "Hørbar klokke" #: src/termit_preferences.c:260 msgid "Background" msgstr "Baggrund" #: src/termit_preferences.c:276 msgid "Background image" msgstr "Baggrunds billede" #: src/termit_core_api.c:433 msgid "Cannot create a new tab" msgstr "Kan ikke oprette ny fane" #: src/termit_core_api.c:361 msgid "Cannot parse command. Creating tab with shell" msgstr "Kan ikke tolke kommando. Opretter fane med skal" #: src/termit.c:194 msgid "Edit" msgstr "Redigér" #: src/termit.c:177 msgid "File" msgstr "Fil" #: src/termit_preferences.c:242 msgid "Font" msgstr "Skrifttype" #: src/termit_preferences.c:251 msgid "Foreground" msgstr "Forgrund" #. g_signal_connect(btn_switch_image_file, "toggled", G_CALLBACK(dlg_switch_image_file), btn_image_file); #. TERMIT_PREFERENCE_ROW2(btn_switch_image_file, btn_image_file); #: src/termit_preferences.c:283 msgid "Image" msgstr "Billede" #: src/callbacks.c:383 msgid "Open session" msgstr "Åben session" #: src/callbacks.c:353 msgid "Save session" msgstr "Gem session" #: src/termit.c:234 msgid "Scrollbar" msgstr "Rullebjælke" #: src/termit.c:209 msgid "Sessions" msgstr "Sessioner" #. Edit menu #: src/termit.c:189 src/termit.c:229 msgid "Set tab name..." msgstr "Angiv fanenavn..." #: src/callbacks.c:37 msgid "" "Several tabs are opened.\n" "Close anyway?" msgstr "" "Adskillige faner åbne.\n" "Luk alligevel?" #: src/callbacks.c:262 src/callbacks.c:271 msgid "Tab name" msgstr "Fanenavn" #: src/termit_preferences.c:235 msgid "Title" msgstr "Titel" #: src/termit_preferences.c:291 msgid "Transparency" msgstr "Gennemsigtighed" #: src/sessions.c:90 #, c-format msgid "Unable to create directory '%s': %s" msgstr "Kan ikke oprette sti '%s': %s" #: src/termit_preferences.c:307 msgid "Visible bell" msgstr "Synlige klokke" #: src/termit_preferences.c:267 msgid "images" msgstr "billeder" termit-3.1/po/de.po000066400000000000000000000052531362242615500142420ustar00rootroot00000000000000# Termit translation file. # Copyright (C) 2007 # This file is distributed under the same license as the termit package. # Evgeny Ratnikov ratnikov.ev@gmail.com 2007. # msgid "" msgstr "" "Project-Id-Version: 1.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: \n" "PO-Revision-Date: 2011-12-19 21:23+0100\n" "Last-Translator: Dennis Ploeger \n" "Language-Team: de\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: src/termit_preferences.c:218 msgid "Apply to all tabs" msgstr "" #: src/termit_preferences.c:206 msgid "Background" msgstr "Hintergrund" #: src/termit_core_api.c:440 msgid "Cannot create a new tab" msgstr "Konnte keinen neuen Tab erzeugen" #: src/termit_core_api.c:392 msgid "Cannot parse command. Creating tab with shell" msgstr "" "Konnte Befehl nicht untersuchen. Erstelle einen Tab mit der Kommandozeile" #: src/termit.c:187 src/termit.c:226 msgid "Copy" msgstr "" #: src/termit.c:170 src/termit.c:223 msgid "Delete" msgstr "" #: src/termit.c:190 msgid "Edit" msgstr "Bearbeiten" #: src/termit.c:173 msgid "File" msgstr "Datei" #: src/termit_preferences.c:192 msgid "Font" msgstr "Schriftart" #: src/termit_preferences.c:199 msgid "Foreground" msgstr "Vordergrund" #. File menu #: src/termit.c:169 src/termit.c:222 msgid "Open" msgstr "" #. Sessions menu #: src/termit.c:202 src/callbacks.c:395 msgid "Open session" msgstr "Sitzung öffnen" #: src/termit.c:188 src/termit.c:227 msgid "Paste" msgstr "" #: src/termit.c:186 src/termit.c:225 src/termit_preferences.c:166 msgid "Preferences" msgstr "" #: src/termit.c:171 src/termit.c:228 msgid "Quit" msgstr "" #: src/termit.c:203 src/callbacks.c:365 msgid "Save session" msgstr "Sitzung speichern" #: src/termit.c:229 msgid "Scrollbar" msgstr "Bildlaufleiste" #: src/termit.c:205 msgid "Sessions" msgstr "Sitzungen" #. Edit menu #: src/termit.c:185 src/termit.c:224 msgid "Set tab name..." msgstr "Tab-Namen setzen..." #: src/callbacks.c:41 msgid "" "Several tabs are opened.\n" "Close anyway?" msgstr "" "Mehrere Tabs sind geöffnet.\n" "Trotzdem schließen?" #: src/callbacks.c:274 src/callbacks.c:285 msgid "Tab name" msgstr "Tab-Name" #: src/termit_preferences.c:186 msgid "Title" msgstr "Titel" #: src/sessions.c:90 #, c-format msgid "Unable to create directory '%s': %s" msgstr "Konnte Verzeichnis '%s' nicht erstellen: %s" #: src/termit_preferences.c:212 #, fuzzy msgid "audible bell" msgstr "Glocke" #~ msgid "Background image" #~ msgstr "Hintergrundbild" #~ msgid "Image" #~ msgstr "Bild" #~ msgid "Transparency" #~ msgstr "Transparenz" #~ msgid "Visible bell" #~ msgstr "Sichtbare Glocke" #~ msgid "images" #~ msgstr "Bilder" termit-3.1/po/es.po000066400000000000000000000052131362242615500142550ustar00rootroot00000000000000# Termit translation file. # Copyright (C) 2007 # This file is distributed under the same license as the termit package. # Evgeny Ratnikov ratnikov.ev@gmail.com 2007. # msgid "" msgstr "" "Project-Id-Version: \n" "POT-Creation-Date: \n" "PO-Revision-Date: \n" "Last-Translator: Martintxo \n" "Language-Team: \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" #: src/termit_preferences.c:218 msgid "Apply to all tabs" msgstr "" #: src/termit_preferences.c:206 msgid "Background" msgstr "Fondo" #: src/termit_core_api.c:440 msgid "Cannot create a new tab" msgstr "No se puede crear una nueva pestaña" #: src/termit_core_api.c:392 msgid "Cannot parse command. Creating tab with shell" msgstr "El comando no se entiende. Creando una nueva pestaña con shell" #: src/termit.c:187 src/termit.c:226 msgid "Copy" msgstr "" #: src/termit.c:170 src/termit.c:223 msgid "Delete" msgstr "" #: src/termit.c:190 msgid "Edit" msgstr "Editar" #: src/termit.c:173 msgid "File" msgstr "Archivo" #: src/termit_preferences.c:192 msgid "Font" msgstr "Tipografía" #: src/termit_preferences.c:199 msgid "Foreground" msgstr "Frente" #. File menu #: src/termit.c:169 src/termit.c:222 msgid "Open" msgstr "" #. Sessions menu #: src/termit.c:202 src/callbacks.c:395 msgid "Open session" msgstr "Abrir sesión" #: src/termit.c:188 src/termit.c:227 msgid "Paste" msgstr "" #: src/termit.c:186 src/termit.c:225 src/termit_preferences.c:166 msgid "Preferences" msgstr "" #: src/termit.c:171 src/termit.c:228 msgid "Quit" msgstr "" #: src/termit.c:203 src/callbacks.c:365 msgid "Save session" msgstr "Guardar sesión" #: src/termit.c:229 msgid "Scrollbar" msgstr "Barra de desplazamiento" #: src/termit.c:205 msgid "Sessions" msgstr "Sesiones" #. Edit menu #: src/termit.c:185 src/termit.c:224 msgid "Set tab name..." msgstr "Establece el nombre de la pestaña" #: src/callbacks.c:41 msgid "" "Several tabs are opened.\n" "Close anyway?" msgstr "" "Hay varias pestañas abiertas.\n" "¿Cerrarlas todas?" #: src/callbacks.c:274 src/callbacks.c:285 msgid "Tab name" msgstr "Nombre de la pestaña" #: src/termit_preferences.c:186 msgid "Title" msgstr "Título" #: src/sessions.c:90 #, c-format msgid "Unable to create directory '%s': %s" msgstr "No se puede crear el directorio '%s': %s." #: src/termit_preferences.c:212 #, fuzzy msgid "audible bell" msgstr "Timbre audible" #~ msgid "Background image" #~ msgstr "Imagen de fondo" #~ msgid "Image" #~ msgstr "Imagen" #~ msgid "Transparency" #~ msgstr "Transparencia" #~ msgid "Visible bell" #~ msgstr "Timbre visible" #~ msgid "images" #~ msgstr "imágenes" termit-3.1/po/fr.po000066400000000000000000000046671362242615500142710ustar00rootroot00000000000000msgid "" msgstr "" "Project-Id-Version: Termit 1.1.1\n" "POT-Creation-Date: \n" "PO-Revision-Date: 2008-01-22 11:12+0100\n" "Last-Translator: Mallory Mollo \n" "Language-Team: Mallory Mollo \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Language: French\n" "X-Poedit-Country: FRANCE\n" #: src/termit_preferences.c:218 msgid "Apply to all tabs" msgstr "" #: src/termit_preferences.c:206 msgid "Background" msgstr "" #: src/termit_core_api.c:440 msgid "Cannot create a new tab" msgstr "Impossible de créer un nouvel onglet" #: src/termit_core_api.c:392 msgid "Cannot parse command. Creating tab with shell" msgstr "" #: src/termit.c:187 src/termit.c:226 msgid "Copy" msgstr "" #: src/termit.c:170 src/termit.c:223 msgid "Delete" msgstr "" #: src/termit.c:190 msgid "Edit" msgstr "Éditer" #: src/termit.c:173 msgid "File" msgstr "Fichier" #: src/termit_preferences.c:192 msgid "Font" msgstr "" #: src/termit_preferences.c:199 msgid "Foreground" msgstr "" #. File menu #: src/termit.c:169 src/termit.c:222 msgid "Open" msgstr "" #. Sessions menu #: src/termit.c:202 src/callbacks.c:395 msgid "Open session" msgstr "Ouvrir une session" #: src/termit.c:188 src/termit.c:227 msgid "Paste" msgstr "" #: src/termit.c:186 src/termit.c:225 src/termit_preferences.c:166 msgid "Preferences" msgstr "" #: src/termit.c:171 src/termit.c:228 msgid "Quit" msgstr "" #: src/termit.c:203 src/callbacks.c:365 msgid "Save session" msgstr "Enregistrer la session" #: src/termit.c:229 msgid "Scrollbar" msgstr "" #: src/termit.c:205 msgid "Sessions" msgstr "Sessions" #. Edit menu #: src/termit.c:185 src/termit.c:224 msgid "Set tab name..." msgstr "Définir le nom de l'onglet..." #: src/callbacks.c:41 msgid "" "Several tabs are opened.\n" "Close anyway?" msgstr "" "Vous êtes sur le point de fermer plusieurs onglets.\n" "Voulez-vous vraiment continuer ?" #: src/callbacks.c:274 src/callbacks.c:285 msgid "Tab name" msgstr "Nom de l'onglet" #: src/termit_preferences.c:186 #, fuzzy msgid "Title" msgstr "Fichier" #: src/sessions.c:90 #, c-format msgid "Unable to create directory '%s': %s" msgstr "Impossible de créer le dossier '%s': %s" #: src/termit_preferences.c:212 msgid "audible bell" msgstr "" #~ msgid "Bookmarks" #~ msgstr "Marques-page" #~ msgid "Encoding" #~ msgstr "Encodage" #~ msgid "Select font" #~ msgstr "Définir la police" termit-3.1/po/hu.po000066400000000000000000000052721362242615500142670ustar00rootroot00000000000000# Termit translation file. # Copyright (C) 2007 # This file is distributed under the same license as the termit package. # Evgeny Ratnikov ratnikov.ev@gmail.com 2007. # msgid "" msgstr "" "Project-Id-Version: 1.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: \n" "PO-Revision-Date: 2011-12-19 21:23+0100\n" "Last-Translator: Peter Polonkai \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" #: src/termit_preferences.c:218 msgid "Apply to all tabs" msgstr "" #: src/termit_preferences.c:206 msgid "Background" msgstr "Háttér" #: src/termit_core_api.c:440 msgid "Cannot create a new tab" msgstr "Nem sikerült új fület létrehozni" #: src/termit_core_api.c:392 msgid "Cannot parse command. Creating tab with shell" msgstr "" "Nem lehetséges a parancs értelmezése. Fül létrehozása shell segítségével" #: src/termit.c:187 src/termit.c:226 msgid "Copy" msgstr "" #: src/termit.c:170 src/termit.c:223 msgid "Delete" msgstr "" #: src/termit.c:190 msgid "Edit" msgstr "Szerkesztés" #: src/termit.c:173 msgid "File" msgstr "Fájl" #: src/termit_preferences.c:192 msgid "Font" msgstr "Betűtípus" #: src/termit_preferences.c:199 msgid "Foreground" msgstr "Előtér" #. File menu #: src/termit.c:169 src/termit.c:222 msgid "Open" msgstr "" #. Sessions menu #: src/termit.c:202 src/callbacks.c:395 msgid "Open session" msgstr "Megnyitás" #: src/termit.c:188 src/termit.c:227 msgid "Paste" msgstr "" #: src/termit.c:186 src/termit.c:225 src/termit_preferences.c:166 msgid "Preferences" msgstr "" #: src/termit.c:171 src/termit.c:228 msgid "Quit" msgstr "" #: src/termit.c:203 src/callbacks.c:365 msgid "Save session" msgstr "Mentés" #: src/termit.c:229 msgid "Scrollbar" msgstr "Gördítősáv" #: src/termit.c:205 msgid "Sessions" msgstr "Munkamenetek" #. Edit menu #: src/termit.c:185 src/termit.c:224 msgid "Set tab name..." msgstr "Fül átnevezése..." #: src/callbacks.c:41 msgid "" "Several tabs are opened.\n" "Close anyway?" msgstr "" "Több fül is nyitva van.\n" "Bezárja mind?" #: src/callbacks.c:274 src/callbacks.c:285 msgid "Tab name" msgstr "Fül neve" #: src/termit_preferences.c:186 msgid "Title" msgstr "Cím" #: src/sessions.c:90 #, c-format msgid "Unable to create directory '%s': %s" msgstr "A könyvtár létrehozása sikertelen '%s': %s" #: src/termit_preferences.c:212 #, fuzzy msgid "audible bell" msgstr "Hallható figyelmeztetés" #~ msgid "Background image" #~ msgstr "Háttérkép" #~ msgid "Image" #~ msgstr "Kép" #~ msgid "Transparency" #~ msgstr "Átlátszóság" #~ msgid "Visible bell" #~ msgstr "Látható figyelmeztetés" #~ msgid "images" #~ msgstr "képek" termit-3.1/po/ja.po000066400000000000000000000052151362242615500142420ustar00rootroot00000000000000# Copyright (c) 2011 Nobuhiro Iwamatsu msgid "" msgstr "" "Project-Id-Version: termit japanese translate\n" "POT-Creation-Date: \n" "PO-Revision-Date: 2011-09-01 02:28+0900\n" "Last-Translator: Nobuhiro Iwamatsu \n" "Language-Team: \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Language: Japanese\n" "X-Poedit-Country: JAPAN\n" #: src/termit_preferences.c:218 msgid "Apply to all tabs" msgstr "" #: src/termit_preferences.c:206 msgid "Background" msgstr "背景" #: src/termit_core_api.c:440 msgid "Cannot create a new tab" msgstr "新しいタブを作成できません" #: src/termit_core_api.c:392 msgid "Cannot parse command. Creating tab with shell" msgstr "コマンドを解析できません。シェル経由でタブを作成します" #: src/termit.c:187 src/termit.c:226 msgid "Copy" msgstr "" #: src/termit.c:170 src/termit.c:223 msgid "Delete" msgstr "" #: src/termit.c:190 msgid "Edit" msgstr "編集" #: src/termit.c:173 msgid "File" msgstr "ファイル" #: src/termit_preferences.c:192 msgid "Font" msgstr "フォント" #: src/termit_preferences.c:199 msgid "Foreground" msgstr "前景" #. File menu #: src/termit.c:169 src/termit.c:222 msgid "Open" msgstr "" #. Sessions menu #: src/termit.c:202 src/callbacks.c:395 msgid "Open session" msgstr "セッションを開く" #: src/termit.c:188 src/termit.c:227 msgid "Paste" msgstr "" #: src/termit.c:186 src/termit.c:225 src/termit_preferences.c:166 msgid "Preferences" msgstr "" #: src/termit.c:171 src/termit.c:228 msgid "Quit" msgstr "" #: src/termit.c:203 src/callbacks.c:365 msgid "Save session" msgstr "セッションを保存する" #: src/termit.c:229 msgid "Scrollbar" msgstr "スクロールバー" #: src/termit.c:205 msgid "Sessions" msgstr "セッション" #. Edit menu #: src/termit.c:185 src/termit.c:224 msgid "Set tab name..." msgstr "タブ名を設定する" #: src/callbacks.c:41 msgid "" "Several tabs are opened.\n" "Close anyway?" msgstr "終了しますか?" #: src/callbacks.c:274 src/callbacks.c:285 msgid "Tab name" msgstr "タブ名" #: src/termit_preferences.c:186 msgid "Title" msgstr "タイトル" #: src/sessions.c:90 #, c-format msgid "Unable to create directory '%s': %s" msgstr "ディレクトリ '%s' が生成できません: %s" #: src/termit_preferences.c:212 #, fuzzy msgid "audible bell" msgstr "可聴ベル" #~ msgid "Background image" #~ msgstr "背景画像" #~ msgid "Image" #~ msgstr "画像" #~ msgid "Transparency" #~ msgstr "透過" #~ msgid "Visible bell" #~ msgstr "可視ベル" #~ msgid "images" #~ msgstr "画像" termit-3.1/po/ko.po000066400000000000000000000047301362242615500142620ustar00rootroot00000000000000msgid "" msgstr "" "Project-Id-Version: termit korean translate\n" "POT-Creation-Date: \n" "PO-Revision-Date: 2008-09-02 05:26+0900\n" "Last-Translator: SeonKon Choi \n" "Language-Team: \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Language: Korean\n" "X-Poedit-Country: KOREA, REPUBLIC OF\n" #: src/termit_preferences.c:218 msgid "Apply to all tabs" msgstr "" #: src/termit_preferences.c:206 msgid "Background" msgstr "" #: src/termit_core_api.c:440 msgid "Cannot create a new tab" msgstr "새 탭을 만들 수 없습니다" #: src/termit_core_api.c:392 msgid "Cannot parse command. Creating tab with shell" msgstr "명령을 해석할 수 없습니다. 쉘을 이용한 새 탭을 만듭니다" #: src/termit.c:187 src/termit.c:226 msgid "Copy" msgstr "" #: src/termit.c:170 src/termit.c:223 msgid "Delete" msgstr "" #: src/termit.c:190 msgid "Edit" msgstr "편집" #: src/termit.c:173 msgid "File" msgstr "파일" #: src/termit_preferences.c:192 msgid "Font" msgstr "" #: src/termit_preferences.c:199 msgid "Foreground" msgstr "" #. File menu #: src/termit.c:169 src/termit.c:222 msgid "Open" msgstr "" #. Sessions menu #: src/termit.c:202 src/callbacks.c:395 msgid "Open session" msgstr "세션 열기" #: src/termit.c:188 src/termit.c:227 msgid "Paste" msgstr "" #: src/termit.c:186 src/termit.c:225 src/termit_preferences.c:166 msgid "Preferences" msgstr "" #: src/termit.c:171 src/termit.c:228 msgid "Quit" msgstr "" #: src/termit.c:203 src/callbacks.c:365 msgid "Save session" msgstr "세션 저장" #: src/termit.c:229 msgid "Scrollbar" msgstr "스크롤 바" #: src/termit.c:205 msgid "Sessions" msgstr "세션" #. Edit menu #: src/termit.c:185 src/termit.c:224 msgid "Set tab name..." msgstr "탭 이름 바꾸기" #: src/callbacks.c:41 msgid "" "Several tabs are opened.\n" "Close anyway?" msgstr "" "다른 탭들이 아직 열려 있습니다.\n" "전부 닫고 종료할까요 ?" #: src/callbacks.c:274 src/callbacks.c:285 msgid "Tab name" msgstr "탭 이름" #: src/termit_preferences.c:186 #, fuzzy msgid "Title" msgstr "파일" #: src/sessions.c:90 #, c-format msgid "Unable to create directory '%s': %s" msgstr "디렉토리를 만들 수 없습니다 '%s': %s" #: src/termit_preferences.c:212 msgid "audible bell" msgstr "" #~ msgid "Bookmarks" #~ msgstr "책갈피" #~ msgid "Encoding" #~ msgstr "문자집합" #~ msgid "Select font" #~ msgstr "글꼴 바꾸기" termit-3.1/po/pl.po000066400000000000000000000053641362242615500142700ustar00rootroot00000000000000# Polish translation of termit. # Copyright (C) 2007 # This file is distributed under the same license as the termit package. # Miś Uszatek , 2012 # msgid "" msgstr "" "Project-Id-Version: termit-2.9.3\n" "POT-Creation-Date: \n" "PO-Revision-Date: 2012-05-02 20:02+0100\n" "Last-Translator: Miś Uszatek \n" "Language-Team: Polish\n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " "|| n%100>=20) ? 1 : 2);\n" #: src/termit_preferences.c:218 msgid "Apply to all tabs" msgstr "" #: src/termit_preferences.c:206 msgid "Background" msgstr "Tło" #: src/termit_core_api.c:440 msgid "Cannot create a new tab" msgstr "Nie można utworzyć nowej karty" #: src/termit_core_api.c:392 msgid "Cannot parse command. Creating tab with shell" msgstr "Nie można przetworzyć polecenia. Tworzenia karty z powłoki" #: src/termit.c:187 src/termit.c:226 msgid "Copy" msgstr "" #: src/termit.c:170 src/termit.c:223 msgid "Delete" msgstr "" #: src/termit.c:190 msgid "Edit" msgstr "Edycja" #: src/termit.c:173 msgid "File" msgstr "Plik" #: src/termit_preferences.c:192 msgid "Font" msgstr "Czcionka" #: src/termit_preferences.c:199 msgid "Foreground" msgstr "Pierwszy plan" #. File menu #: src/termit.c:169 src/termit.c:222 msgid "Open" msgstr "" #. Sessions menu #: src/termit.c:202 src/callbacks.c:395 msgid "Open session" msgstr "Otwórz sesje" #: src/termit.c:188 src/termit.c:227 msgid "Paste" msgstr "" #: src/termit.c:186 src/termit.c:225 src/termit_preferences.c:166 msgid "Preferences" msgstr "" #: src/termit.c:171 src/termit.c:228 msgid "Quit" msgstr "" #: src/termit.c:203 src/callbacks.c:365 msgid "Save session" msgstr "Zapisz sesje " #: src/termit.c:229 msgid "Scrollbar" msgstr "Pasek przewijania" #: src/termit.c:205 msgid "Sessions" msgstr "Sesja" #. Edit menu #: src/termit.c:185 src/termit.c:224 msgid "Set tab name..." msgstr "Ustaw nazwe karty..." #: src/callbacks.c:41 msgid "" "Several tabs are opened.\n" "Close anyway?" msgstr "" "Kilka kart jest otwartych.\n" "Zamknąć pomimo to?" #: src/callbacks.c:274 src/callbacks.c:285 msgid "Tab name" msgstr "Nazwa Karty" #: src/termit_preferences.c:186 msgid "Title" msgstr "Tytuł" #: src/sessions.c:90 #, c-format msgid "Unable to create directory '%s': %s" msgstr "Nie można utworzyć katalogu '%s': %s" #: src/termit_preferences.c:212 #, fuzzy msgid "audible bell" msgstr "Głośny dzwonek" #~ msgid "Background image" #~ msgstr "Obraz tła" #~ msgid "Image" #~ msgstr "Obraz" #~ msgid "Transparency" #~ msgstr "Przezroczystość" #~ msgid "Visible bell" #~ msgstr "Widoczny dzwonek" #~ msgid "images" #~ msgstr "obrazy" termit-3.1/po/ru.po000066400000000000000000000052461362242615500143020ustar00rootroot00000000000000# Termit translation file. # Copyright (C) 2007 # This file is distributed under the same license as the termit package. # Evgeny Ratnikov ratnikov.ev@gmail.com 2007. # msgid "" msgstr "" "Project-Id-Version: 1.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2007-09-25 09:19+0400\n" "PO-Revision-Date: 2007-12-15 18:05+0400\n" "Last-Translator: Evgeny V. Ratnikov ratnikov.ev@gmail.com\n" "Language-Team: ru_RU\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: src/termit_preferences.c:218 msgid "Apply to all tabs" msgstr "" #: src/termit_preferences.c:206 msgid "Background" msgstr "" #: src/termit_core_api.c:440 msgid "Cannot create a new tab" msgstr "Ошибка открытия новой вкладки" #: src/termit_core_api.c:392 msgid "Cannot parse command. Creating tab with shell" msgstr "" #: src/termit.c:187 src/termit.c:226 msgid "Copy" msgstr "" #: src/termit.c:170 src/termit.c:223 msgid "Delete" msgstr "" #: src/termit.c:190 msgid "Edit" msgstr "Правка" #: src/termit.c:173 msgid "File" msgstr "Файл" #: src/termit_preferences.c:192 msgid "Font" msgstr "" #: src/termit_preferences.c:199 msgid "Foreground" msgstr "" #. File menu #: src/termit.c:169 src/termit.c:222 msgid "Open" msgstr "" #. Sessions menu #: src/termit.c:202 src/callbacks.c:395 msgid "Open session" msgstr "Открыть сессию" #: src/termit.c:188 src/termit.c:227 msgid "Paste" msgstr "" #: src/termit.c:186 src/termit.c:225 src/termit_preferences.c:166 msgid "Preferences" msgstr "" #: src/termit.c:171 src/termit.c:228 msgid "Quit" msgstr "" #: src/termit.c:203 src/callbacks.c:365 msgid "Save session" msgstr "Сохранить сессию" #: src/termit.c:229 msgid "Scrollbar" msgstr "Полоса прокрутки" #: src/termit.c:205 msgid "Sessions" msgstr "Сессии" #. Edit menu #: src/termit.c:185 src/termit.c:224 msgid "Set tab name..." msgstr "Заголовок вкладки" #: src/callbacks.c:41 msgid "" "Several tabs are opened.\n" "Close anyway?" msgstr "" "Открыто несколько вкладок.\n" "Закрыть?" #: src/callbacks.c:274 src/callbacks.c:285 msgid "Tab name" msgstr "Заголовок вкладки" #: src/termit_preferences.c:186 #, fuzzy msgid "Title" msgstr "Файл" #: src/sessions.c:90 #, c-format msgid "Unable to create directory '%s': %s" msgstr "Невозможно создать директорию '%s': %s" #: src/termit_preferences.c:212 msgid "audible bell" msgstr "" #~ msgid "Bookmarks" #~ msgstr "Закладки" #~ msgid "Encoding" #~ msgstr "Кодировка" #~ msgid "Select font" #~ msgstr "Выбор шрифта" termit-3.1/po/sv.po000066400000000000000000000040711362242615500142770ustar00rootroot00000000000000#: src/termit_preferences.c:218 msgid "Apply to all tabs" msgstr "" #: src/termit_preferences.c:206 msgid "Background" msgstr "Bakgrund" #: src/termit_core_api.c:440 msgid "Cannot create a new tab" msgstr "Kan inte skapa ny flik" #: src/termit_core_api.c:392 msgid "Cannot parse command. Creating tab with shell" msgstr "Kan inte tolka kommando. Skapar interaktiv flik." #: src/termit.c:187 src/termit.c:226 msgid "Copy" msgstr "" #: src/termit.c:170 src/termit.c:223 msgid "Delete" msgstr "" #: src/termit.c:190 msgid "Edit" msgstr "Redigera" #: src/termit.c:173 msgid "File" msgstr "Arkiv" #: src/termit_preferences.c:192 msgid "Font" msgstr "Teckensnitt" #: src/termit_preferences.c:199 msgid "Foreground" msgstr "Frgrund" #. File menu #: src/termit.c:169 src/termit.c:222 msgid "Open" msgstr "" #. Sessions menu #: src/termit.c:202 src/callbacks.c:395 msgid "Open session" msgstr "ppna arbetspass" #: src/termit.c:188 src/termit.c:227 msgid "Paste" msgstr "" #: src/termit.c:186 src/termit.c:225 src/termit_preferences.c:166 msgid "Preferences" msgstr "" #: src/termit.c:171 src/termit.c:228 msgid "Quit" msgstr "" #: src/termit.c:203 src/callbacks.c:365 msgid "Save session" msgstr "Spara arbetspass" #: src/termit.c:229 msgid "Scrollbar" msgstr "Rullningslist" #: src/termit.c:205 msgid "Sessions" msgstr "Arbetspass" #. Edit menu #: src/termit.c:185 src/termit.c:224 msgid "Set tab name..." msgstr "Namnge fliken..." #: src/callbacks.c:41 msgid "" "Several tabs are opened.\n" "Close anyway?" msgstr "" #: src/callbacks.c:274 src/callbacks.c:285 msgid "Tab name" msgstr "Fliknamn" #: src/termit_preferences.c:186 msgid "Title" msgstr "Rubrik" #: src/sessions.c:90 #, c-format msgid "Unable to create directory '%s': %s" msgstr "Kan inte skapa mappen '%s': %s" #: src/termit_preferences.c:212 #, fuzzy msgid "audible bell" msgstr "Ljudsignal" #~ msgid "Background image" #~ msgstr "Bakgrundsbild" #~ msgid "Image" #~ msgstr "Avbild" #~ msgid "Transparency" #~ msgstr "Genomskinlighet" #~ msgid "Visible bell" #~ msgstr "Ljudsignal" #~ msgid "images" #~ msgstr "avbilder" termit-3.1/po/termit.pot000066400000000000000000000031361362242615500153400ustar00rootroot00000000000000#: src/termit_preferences.c:218 msgid "Apply to all tabs" msgstr "" #: src/termit_preferences.c:206 msgid "Background" msgstr "" #: src/termit_core_api.c:440 msgid "Cannot create a new tab" msgstr "" #: src/termit_core_api.c:392 msgid "Cannot parse command. Creating tab with shell" msgstr "" #: src/termit.c:187 src/termit.c:226 msgid "Copy" msgstr "" #: src/termit.c:170 src/termit.c:223 msgid "Delete" msgstr "" #: src/termit.c:190 msgid "Edit" msgstr "" #: src/termit.c:173 msgid "File" msgstr "" #: src/termit_preferences.c:192 msgid "Font" msgstr "" #: src/termit_preferences.c:199 msgid "Foreground" msgstr "" #. File menu #: src/termit.c:169 src/termit.c:222 msgid "Open" msgstr "" #. Sessions menu #: src/termit.c:202 src/callbacks.c:395 msgid "Open session" msgstr "" #: src/termit.c:188 src/termit.c:227 msgid "Paste" msgstr "" #: src/termit.c:186 src/termit.c:225 src/termit_preferences.c:166 msgid "Preferences" msgstr "" #: src/termit.c:171 src/termit.c:228 msgid "Quit" msgstr "" #: src/termit.c:203 src/callbacks.c:365 msgid "Save session" msgstr "" #: src/termit.c:229 msgid "Scrollbar" msgstr "" #: src/termit.c:205 msgid "Sessions" msgstr "" #. Edit menu #: src/termit.c:185 src/termit.c:224 msgid "Set tab name..." msgstr "" #: src/callbacks.c:41 msgid "" "Several tabs are opened.\n" "Close anyway?" msgstr "" #: src/callbacks.c:274 src/callbacks.c:285 msgid "Tab name" msgstr "" #: src/termit_preferences.c:186 msgid "Title" msgstr "" #: src/sessions.c:90 #, c-format msgid "Unable to create directory '%s': %s" msgstr "" #: src/termit_preferences.c:212 msgid "audible bell" msgstr "" termit-3.1/po/zh_TW.po000066400000000000000000000046011362242615500147010ustar00rootroot00000000000000# Traditional Chinese messages for termit. # Copyright (C) 2008 Tetralet . # This file is distributed under the same license as termit. # msgid "" msgstr "" "Project-Id-Version: termit\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2008-02-05 22:50+0000\n" "PO-Revision-Date: 2008-02-20 11:18+0800\n" "Last-Translator: Tetralet \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: src/termit_preferences.c:218 msgid "Apply to all tabs" msgstr "" #: src/termit_preferences.c:206 msgid "Background" msgstr "" #: src/termit_core_api.c:440 msgid "Cannot create a new tab" msgstr "無法建立新分頁" #: src/termit_core_api.c:392 msgid "Cannot parse command. Creating tab with shell" msgstr "" #: src/termit.c:187 src/termit.c:226 msgid "Copy" msgstr "" #: src/termit.c:170 src/termit.c:223 msgid "Delete" msgstr "" #: src/termit.c:190 msgid "Edit" msgstr "編輯" #: src/termit.c:173 msgid "File" msgstr "檔案" #: src/termit_preferences.c:192 msgid "Font" msgstr "" #: src/termit_preferences.c:199 msgid "Foreground" msgstr "" #. File menu #: src/termit.c:169 src/termit.c:222 msgid "Open" msgstr "" #. Sessions menu #: src/termit.c:202 src/callbacks.c:395 msgid "Open session" msgstr "開啟作業階段" #: src/termit.c:188 src/termit.c:227 msgid "Paste" msgstr "" #: src/termit.c:186 src/termit.c:225 src/termit_preferences.c:166 msgid "Preferences" msgstr "" #: src/termit.c:171 src/termit.c:228 msgid "Quit" msgstr "" #: src/termit.c:203 src/callbacks.c:365 msgid "Save session" msgstr "儲存作業階段" #: src/termit.c:229 msgid "Scrollbar" msgstr "" #: src/termit.c:205 msgid "Sessions" msgstr "作業階段" #. Edit menu #: src/termit.c:185 src/termit.c:224 msgid "Set tab name..." msgstr "設定分頁名稱..." #: src/callbacks.c:41 msgid "" "Several tabs are opened.\n" "Close anyway?" msgstr "已開啟數個分頁。是否關閉?" #: src/callbacks.c:274 src/callbacks.c:285 msgid "Tab name" msgstr "分頁名稱" #: src/termit_preferences.c:186 #, fuzzy msgid "Title" msgstr "檔案" #: src/sessions.c:90 #, c-format msgid "Unable to create directory '%s': %s" msgstr "無法建立目錄 '%s': %s" #: src/termit_preferences.c:212 msgid "audible bell" msgstr "" #~ msgid "Bookmarks" #~ msgstr "書籤" #~ msgid "Encoding" #~ msgstr "編碼" #~ msgid "Select font" #~ msgstr "選擇字型" termit-3.1/src/000077500000000000000000000000001362242615500134565ustar00rootroot00000000000000termit-3.1/src/CMakeLists.txt000066400000000000000000000053521362242615500162230ustar00rootroot00000000000000# Copyright © 2007-2016 Evgeny Ratnikov # # 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 . SET(TARGET "termit") INCLUDE_DIRECTORIES(${TERMIT_SOURCE_DIR}) INCLUDE (FindPkgConfig) pkg_search_module(GTK REQUIRED gtk+-3.0>=3.22) pkg_search_module(VTE REQUIRED libvte>=0.46 vte>=0.46 vte-2.91>=0.46) IF(NOT VTE_FOUND) message(FATAL_ERROR "Vte library was not found.") ENDIF(NOT VTE_FOUND) SET(LUA_VERSION "" CACHE STRING "Lua version") IF(LUA_VERSION STREQUAL "") IF(${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD") pkg_search_module(LUA REQUIRED lua53) ELSE(${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD") pkg_search_module(LUA REQUIRED lua>=5.3 lua5.3) ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD") ELSE(LUA_VERSION STREQUAL "") pkg_search_module(LUA REQUIRED lua=${LUA_VERSION} lua5.3=${LUA_VERSION}) ENDIF(LUA_VERSION STREQUAL "") IF(NOT LUA_FOUND) message(FATAL_ERROR "Lua library was not found.") ENDIF(NOT LUA_FOUND) INCLUDE(Sources.cmake) SET(TERMIT_CFLAGS "-I${LUA_INCLUDE_DIR}") IF(${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD") SET(TERMIT_CFLAGS "${TERMIT_CFLAGS} -I/usr/local/include") ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD") FOREACH(cflag ${VTE_CFLAGS} ${GTK_CFLAGS} ${LUA_CFLAGS}) SET(TERMIT_CFLAGS "${TERMIT_CFLAGS} ${cflag}") ENDFOREACH(cflag) IF(DEBUG) SET(EXTRA_CFLAGS "-std=c99 -Wall -Wextra -Wno-missing-field-initializers -Wno-unused-parameter") SET(TERMIT_CFLAGS "${TERMIT_CFLAGS} ${EXTRA_CFLAGS} -g -DDEBUG -DGTK_DISABLE_DEPRECATED") ELSE(DEBUG) SET(TERMIT_CFLAGS "${TERMIT_CFLAGS} -O2") ENDIF(DEBUG) set(TERMIT_LDFLAGS ${VTE_LDFLAGS} ${GTK_LDFLAGS}) SET_SOURCE_FILES_PROPERTIES(${TERMIT_SRCS} PROPERTIES COMPILE_FLAGS "${TERMIT_CFLAGS}") ADD_EXECUTABLE(${TARGET} ${TERMIT_SRCS}) IF(${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD") SET(TERMIT_LDFLAGS"-llua5.3") ELSE(${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD") SET(TERMIT_LDFLAGS "-ldl -lm") ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD") FOREACH(ldflag ${VTE_LDFLAGS} ${LUA_LDFLAGS}) LIST(APPEND TERMIT_LDFLAGS "${ldflag}") ENDFOREACH(ldflag) LIST(APPEND TERMIT_LDFLAGS "-lX11") target_link_libraries(${TARGET} ${TERMIT_LDFLAGS}) INSTALL(TARGETS ${TARGET} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) termit-3.1/src/Sources.cmake000066400000000000000000000017031362242615500161040ustar00rootroot00000000000000# Copyright © 2007-2016 Evgeny Ratnikov # # 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 . SET( TERMIT_SRCS termit.c termit_core_api.c callbacks.c sessions.c keybindings.c lua_conf.c lua_api.c configs.c termit_style.c termit_preferences.c ) SET( TERMIT_HDRS termit_core_api.h callbacks.h configs.h sessions.h keybindings.h lua_api.h termit.h termit_style.h ) termit-3.1/src/callbacks.c000066400000000000000000000325471362242615500155540ustar00rootroot00000000000000/* Copyright © 2007-2016 Evgeny Ratnikov * * 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 . */ #include #include #include #include #include "termit.h" #include "configs.h" #include "sessions.h" #include "termit_core_api.h" #include "termit_style.h" #include "lua_api.h" #include "keybindings.h" #include "callbacks.h" static gboolean confirm_exit() { if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(termit.notebook)) <= 1) { return FALSE; } GtkWidget *dlg = gtk_message_dialog_new( GTK_WINDOW(termit.main_window), GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, _("Several tabs are opened.\nClose anyway?")); gint response = gtk_dialog_run(GTK_DIALOG(dlg)); gtk_widget_destroy(dlg); return (response == GTK_RESPONSE_YES) ? FALSE : TRUE; } gboolean termit_on_delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) { return confirm_exit(); } void termit_on_destroy(GtkWidget *widget, gpointer data) { termit_quit(); } void termit_on_tab_title_changed(VteTerminal *vte, gpointer user_data) { if (!configs.allow_changing_title) { return; } gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(termit.notebook)); TERMIT_GET_TAB_BY_INDEX(pTab, page, return); if (pTab->custom_tab_name) { return; } termit_tab_set_title(pTab, vte_terminal_get_window_title(VTE_TERMINAL(pTab->vte))); } gboolean termit_on_search_keypress(GtkWidget *widget, GdkEventKey *event, gpointer user_data) { switch (event->keyval) { case GDK_KEY_Return: { if (event->state == GDK_CONTROL_MASK) { termit_on_find_prev(NULL, NULL); } else { termit_on_find_next(NULL, NULL); } return TRUE; } case GDK_KEY_Escape: { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(termit.b_toggle_search), FALSE); return TRUE; } default: return FALSE; } return FALSE; } static void termit_search_prepare_regex(const gchar* searchRegex) { gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(termit.notebook)); TERMIT_GET_TAB_BY_INDEX(pTab, page, return); if (strlen(searchRegex) == 0) { VteRegex* regex = vte_terminal_search_get_regex(VTE_TERMINAL(pTab->vte)); if (regex) { vte_regex_unref(regex); } vte_terminal_search_set_regex(VTE_TERMINAL(pTab->vte), NULL, 0); } else { VteRegex* currSearchRegex = vte_terminal_search_get_regex(VTE_TERMINAL(pTab->vte)); if (currSearchRegex && strcmp(pTab->search_regex, searchRegex) == 0) { return; } if (currSearchRegex) { vte_regex_unref(currSearchRegex); } if (pTab->search_regex) { g_free(pTab->search_regex); } GError* err = NULL; VteRegex* regex = vte_regex_new_for_search(searchRegex, -1, VTE_REGEX_FLAGS_DEFAULT, &err); if (err) { TRACE("failed to compile regex [%s]: skipping", searchRegex); return; } vte_terminal_search_set_regex(VTE_TERMINAL(pTab->vte), regex, 0); pTab->search_regex = g_strdup(searchRegex); } } void termit_on_find_next(GtkButton* btn, gpointer user_data) { termit_search_prepare_regex(gtk_entry_get_text(GTK_ENTRY(termit.search_entry))); termit_search_find_next(); } void termit_on_find_prev(GtkButton* btn, gpointer user_data) { termit_search_prepare_regex(gtk_entry_get_text(GTK_ENTRY(termit.search_entry))); termit_search_find_prev(); } void termit_on_toggle_search(GtkToggleButton* tb, gpointer user_data) { termit_toggle_search(); } void termit_on_toggle_scrollbar() { TRACE_MSG(__FUNCTION__); gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(termit.notebook)); TERMIT_GET_TAB_BY_INDEX(pTab, page, return); if (pTab->scrollbar_is_shown) { gtk_widget_hide(GTK_WIDGET(pTab->scrollbar)); } else { gtk_widget_show(GTK_WIDGET(pTab->scrollbar)); } pTab->scrollbar_is_shown = !pTab->scrollbar_is_shown; } void termit_on_child_exited(VteTerminal* vte, gint status, gpointer user_data) { gint page = -1; struct TermitTab* pTab = termit_get_tab_by_vte(vte, &page); if (!pTab) { return; } TRACE("child process exited with status %d", status); termit_del_tab_n(page); if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(termit.notebook)) == 0) { TRACE("no pages left, exiting"); termit_quit(); } } static int termit_cursor_under_match(GdkEvent* ev, char** matchedText) { gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(termit.notebook)); TERMIT_GET_TAB_BY_INDEX(pTab, page, return -1); int tag = -1; *matchedText = vte_terminal_match_check_event(VTE_TERMINAL(pTab->vte), ev, &tag); return tag; } static struct Match* get_match_by_tag(GArray* matches, int tag) { guint i = 0; for (; ilen; ++i) { struct Match* match = &g_array_index(matches, struct Match, i); if (match->tag == tag) { return match; } } return NULL; } gboolean termit_on_popup(GtkWidget *widget, GdkEvent *event) { if (event->type != GDK_BUTTON_PRESS) { return FALSE; } GdkEventButton *event_button = (GdkEventButton *) event; if (event_button->button == 3) { GtkMenu *menu = GTK_MENU(termit.menu); gtk_menu_popup_at_pointer(menu, NULL); return TRUE; } else if (event_button->button == 1) { gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(termit.notebook)); TERMIT_GET_TAB_BY_INDEX(pTab, page, return FALSE); char* matchedText = NULL; int matchTag = termit_cursor_under_match(event, &matchedText); if (!matchedText) { return FALSE; } struct Match* match = get_match_by_tag(pTab->matches, matchTag); if (!match) { g_free(matchedText); return FALSE; } TRACE("tag=%d match=[%s]", matchTag, match->pattern); termit_lua_domatch(match->lua_callback, matchedText); g_free(matchedText); } return FALSE; } static gboolean dlg_key_press(GtkWidget *widget, GdkEventKey *event, gpointer user_data) { switch (event->keyval) { case GDK_KEY_Return: g_signal_emit_by_name(widget, "response", GTK_RESPONSE_ACCEPT, NULL); break; case GDK_KEY_Escape: g_signal_emit_by_name(widget, "response", GTK_RESPONSE_REJECT, NULL); break; default: return FALSE; } return TRUE; } void termit_on_beep(VteTerminal *vte, gpointer user_data) { struct TermitTab* pTab = (struct TermitTab*)user_data; if (!pTab) { ERROR("pTab is NULL"); return; } if (!gtk_window_has_toplevel_focus(GTK_WINDOW(termit.main_window))) { if (configs.urgency_on_bell) { gtk_window_set_urgency_hint(GTK_WINDOW(termit.main_window), TRUE); gchar* marked_title = g_strdup_printf("%s", gtk_label_get_text(GTK_LABEL(pTab->tab_name))); gtk_label_set_markup(GTK_LABEL(pTab->tab_name), marked_title); g_free(marked_title); } } } gboolean termit_on_focus(GtkWidget *widget, GtkDirectionType arg1, gpointer user_data) { struct TermitTab* pTab = (struct TermitTab*)user_data; if (!pTab) { ERROR("pTab is NULL"); return FALSE; } if (gtk_window_get_urgency_hint(GTK_WINDOW(termit.main_window))) { gtk_window_set_urgency_hint(GTK_WINDOW(termit.main_window), FALSE); gtk_label_set_markup(GTK_LABEL(pTab->tab_name), gtk_label_get_text(GTK_LABEL(pTab->tab_name))); gtk_label_set_use_markup(GTK_LABEL(pTab->tab_name), FALSE); } return FALSE; } void termit_on_set_tab_name() { GtkWidget *dlg = gtk_dialog_new_with_buttons( _("Tab name"), GTK_WINDOW(termit.main_window), GTK_DIALOG_MODAL, "_Cancel", GTK_RESPONSE_REJECT, "_OK", GTK_RESPONSE_ACCEPT, NULL); gtk_dialog_set_default_response(GTK_DIALOG(dlg), GTK_RESPONSE_ACCEPT); gtk_window_set_modal(GTK_WINDOW(dlg), TRUE); gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(termit.notebook)); TERMIT_GET_TAB_BY_INDEX(pTab, page, return); GtkWidget *label = gtk_label_new(_("Tab name")); GtkWidget *entry = gtk_entry_new(); gtk_entry_set_text( GTK_ENTRY(entry), gtk_notebook_get_tab_label_text(GTK_NOTEBOOK(termit.notebook), pTab->hbox)); GtkWidget *hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0); g_signal_connect(G_OBJECT(dlg), "key-press-event", G_CALLBACK(dlg_key_press), dlg); gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dlg))), hbox, FALSE, FALSE, 10); gtk_widget_show_all(dlg); if (GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dlg))) { termit_tab_set_title(pTab, gtk_entry_get_text(GTK_ENTRY(entry))); pTab->custom_tab_name = TRUE; } gtk_widget_destroy(dlg); } void termit_preferences_dialog(struct TermitTab *style); void termit_on_edit_preferences() { gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(termit.notebook)); TERMIT_GET_TAB_BY_INDEX(pTab, page, return); termit_preferences_dialog(pTab); } void termit_on_exit() { if (confirm_exit() == FALSE) { termit_quit(); } } void termit_on_switch_page(GtkNotebook *notebook, gpointer arg, guint page, gpointer user_data) { TERMIT_GET_TAB_BY_INDEX(pTab, page, return); TRACE("%s page=%d vte=%p", __FUNCTION__, page, pTab->vte); // it seems that set_active eventually calls toggle callback /*((GtkCheckMenuItem*)termit.mi_show_scrollbar)->active = pTab->scrollbar_is_shown;*/ gpointer pHandlerId = g_object_get_data(G_OBJECT(termit.mi_show_scrollbar), "handlerId"); if (pHandlerId) { g_signal_handler_disconnect(G_OBJECT(termit.mi_show_scrollbar), *((gulong*)pHandlerId)); } gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(termit.mi_show_scrollbar), pTab->scrollbar_is_shown); termit_set_show_scrollbar_signal(termit.mi_show_scrollbar, pHandlerId); termit_set_statusbar_message(page); if (configs.allow_changing_title) { termit_set_window_title(pTab->title); } } gint termit_on_double_click(GtkWidget *widget, GdkEventButton *event, gpointer func_data) { termit_mouse_event(event); return FALSE; } static gchar* termit_get_xdg_data_path() { gchar* fullPath = NULL; const gchar *dataHome = g_getenv("XDG_DATA_HOME"); if (dataHome) { fullPath = g_strdup_printf("%s/termit", dataHome); } else { fullPath = g_strdup_printf("%s/.local/share/termit", g_getenv("HOME")); } TRACE("XDG_DATA_PATH=%s", fullPath); return fullPath; } void termit_on_save_session() { gchar* fullPath = termit_get_xdg_data_path(); GtkWidget* dlg = gtk_file_chooser_dialog_new( _("Save session"), GTK_WINDOW(termit.main_window), GTK_FILE_CHOOSER_ACTION_SAVE, "_Cancel", GTK_RESPONSE_REJECT, "_Save", GTK_RESPONSE_ACCEPT, NULL); gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dlg), TRUE); gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dlg), fullPath); gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dlg), "New session"); if (gtk_dialog_run(GTK_DIALOG(dlg)) != GTK_RESPONSE_ACCEPT) { gtk_widget_destroy(dlg); g_free(fullPath); return; } gchar* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dlg)); termit_save_session(filename); g_free(filename); gtk_widget_destroy(dlg); g_free(fullPath); } void termit_on_load_session() { gchar* fullPath = termit_get_xdg_data_path(); GtkWidget* dlg = gtk_file_chooser_dialog_new( _("Open session"), GTK_WINDOW(termit.main_window), GTK_FILE_CHOOSER_ACTION_OPEN, "_Cancel", GTK_RESPONSE_REJECT, "_OK", GTK_RESPONSE_ACCEPT, NULL); gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dlg), TRUE); gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dlg), fullPath); if (gtk_dialog_run(GTK_DIALOG(dlg)) != GTK_RESPONSE_ACCEPT) { goto free_dlg; } gchar* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dlg)); termit_load_session(filename); g_free(filename); free_dlg: gtk_widget_destroy(dlg); g_free(fullPath); } void termit_on_menu_item_selected(GtkWidget *widget, void *data) { struct UserMenuItem* pMi = (struct UserMenuItem*)g_object_get_data(G_OBJECT(widget), TERMIT_USER_MENU_ITEM_DATA); if (pMi && pMi->lua_callback) { termit_lua_dofunction(pMi->lua_callback); } } gboolean termit_on_key_press(GtkWidget *widget, GdkEventKey *event, gpointer user_data) { return termit_key_event(event); } termit-3.1/src/callbacks.h000066400000000000000000000037611362242615500155550ustar00rootroot00000000000000/* Copyright © 2007-2016 Evgeny Ratnikov * * 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 . */ #ifndef TERMIT_CALLBACKS_H #define TERMIT_CALLBACKS_H gboolean termit_on_delete_event(GtkWidget *widget, GdkEvent *event, gpointer data); void termit_on_destroy(GtkWidget *widget, gpointer data); gboolean termit_on_popup(GtkWidget *, GdkEvent *); gboolean termit_on_key_press(GtkWidget *widget, GdkEventKey *event, gpointer user_data); gboolean termit_on_focus(GtkWidget *widget, GtkDirectionType arg1, gpointer user_data); void termit_on_beep(VteTerminal *vte, gpointer user_data); void termit_on_edit_preferences(); void termit_on_set_tab_name(); void termit_on_toggle_scrollbar(); void termit_on_child_exited(VteTerminal*, gint, gpointer); void termit_on_exit(); void termit_on_switch_page(GtkNotebook *notebook, gpointer arg, guint page, gpointer user_data); void termit_on_menu_item_selected(GtkWidget *widget, void *data); gint termit_on_double_click(GtkWidget *widget, GdkEventButton *event, gpointer func_data); void termit_on_save_session(); void termit_on_load_session(); void termit_on_tab_title_changed(VteTerminal *vte, gpointer user_data); void termit_on_toggle_search(GtkToggleButton*, gpointer); void termit_on_find_next(GtkButton*, gpointer); void termit_on_find_prev(GtkButton*, gpointer); gboolean termit_on_search_keypress(GtkWidget *widget, GdkEventKey *event, gpointer user_data); #endif /* TERMIT_CALLBACKS_H */ termit-3.1/src/configs.c000066400000000000000000000226511362242615500152600ustar00rootroot00000000000000/* Copyright © 2007-2016 Evgeny Ratnikov * * 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 . */ #include #include #include "termit.h" #include "keybindings.h" #include "configs.h" #include "lua_api.h" struct Configs configs = {}; static struct { const char* name; VteEraseBinding val; } erase_bindings[] = { {"Auto", VTE_ERASE_AUTO}, {"AsciiBksp", VTE_ERASE_ASCII_BACKSPACE}, {"AsciiDel", VTE_ERASE_ASCII_DELETE}, {"EraseDel", VTE_ERASE_DELETE_SEQUENCE}, {"EraseTty", VTE_ERASE_TTY} }; static guint EraseBindingsSz = sizeof(erase_bindings)/sizeof(erase_bindings[0]); const char* termit_erase_binding_to_string(VteEraseBinding val) { return erase_bindings[val].name; } VteEraseBinding termit_erase_binding_from_string(const char* str) { guint i = 0; for (; i < EraseBindingsSz; ++i) { if (strcmp(str, erase_bindings[i].name) == 0) { return erase_bindings[i].val; } } ERROR("unknown erase binding [%s], using Auto", str); return VTE_ERASE_AUTO; } static struct { const char* name; VteCursorBlinkMode val; } cursor_blink_modes[] = { {"System", VTE_CURSOR_BLINK_SYSTEM}, {"BlinkOn", VTE_CURSOR_BLINK_ON}, {"BlinkOff", VTE_CURSOR_BLINK_OFF} }; static guint BlinkModesSz = sizeof(cursor_blink_modes)/sizeof(cursor_blink_modes[0]); const char* termit_cursor_blink_mode_to_string(VteCursorBlinkMode val) { return cursor_blink_modes[val].name; } VteCursorBlinkMode termit_cursor_blink_mode_from_string(const char* str) { guint i = 0; for (; i < BlinkModesSz; ++i) { if (strcmp(str, cursor_blink_modes[i].name) == 0) { return cursor_blink_modes[i].val; } } ERROR("unknown blink mode [%s], using System", str); return VTE_CURSOR_BLINK_SYSTEM; } static struct { const char* name; VteCursorShape val; } cursor_shapes[] = { {"Block", VTE_CURSOR_SHAPE_BLOCK}, {"Ibeam", VTE_CURSOR_SHAPE_IBEAM}, {"Underline", VTE_CURSOR_SHAPE_UNDERLINE} }; static guint ShapesSz = sizeof(cursor_shapes)/sizeof(cursor_shapes[0]); const char* termit_cursor_shape_to_string(VteCursorShape val) { return cursor_shapes[val].name; } VteCursorShape termit_cursor_shape_from_string(const char* str) { guint i = 0; for (; i < ShapesSz; ++i) { if (strcmp(str, cursor_shapes[i].name) == 0) { return cursor_shapes[i].val; } } ERROR("unknown cursor shape [%s], using Block", str); return VTE_CURSOR_SHAPE_BLOCK; } void termit_config_trace() { #ifdef DEBUG TRACE(" default_window_title = %s", configs.default_window_title); TRACE(" default_tab_name = %s", configs.default_tab_name); TRACE(" default_encoding = %s", configs.default_encoding); TRACE(" default_word_char_exceptions = %s", configs.default_word_char_exceptions); TRACE(" show_scrollbar = %d", configs.show_scrollbar); TRACE(" hide_menubar = %d", configs.hide_menubar); TRACE(" hide_tabbar = %d", configs.hide_tabbar); TRACE(" fill_tabbar = %d", configs.fill_tabbar); TRACE(" show_border = %d", configs.show_border); TRACE(" hide_single_tab = %d", configs.hide_single_tab); TRACE(" start_maximized = %d", configs.start_maximized); TRACE(" hide_titlebar_when_maximized = %d", configs.hide_titlebar_when_maximized); TRACE(" scrollback_lines = %d", configs.scrollback_lines); TRACE(" cols x rows = %d x %d", configs.cols, configs.rows); TRACE(" backspace = %s", termit_erase_binding_to_string(configs.default_bksp)); TRACE(" delete = %s", termit_erase_binding_to_string(configs.default_delete)); TRACE(" blink = %s", termit_cursor_blink_mode_to_string(configs.default_blink)); TRACE(" shape = %s", termit_cursor_shape_to_string(configs.default_shape)); TRACE(" allow_changing_title = %d", configs.allow_changing_title); TRACE(" audible_bell = %d", configs.audible_bell); TRACE(" scroll_on_output = %d", configs.scroll_on_output); TRACE(" scroll_on_keystroke = %d", configs.scroll_on_keystroke); TRACE(" get_window_title_callback = %d", configs.get_window_title_callback); TRACE(" get_tab_title_callback = %d", configs.get_tab_title_callback); TRACE(" get_statusbar_callback = %d", configs.get_statusbar_callback); TRACE(" kb_policy = %d", configs.kb_policy); TRACE(" tab_pos = %d", configs.tab_pos); TRACE(" style:"); TRACE(" font_name = %s", configs.style.font_name); if (configs.style.foreground_color) { gchar* tmpStr = gdk_rgba_to_string(configs.style.foreground_color); TRACE(" foreground_color = %s", tmpStr); g_free(tmpStr); } if (configs.style.background_color) { gchar* tmpStr = gdk_rgba_to_string(configs.style.background_color); TRACE(" background_color = %s", tmpStr); g_free(tmpStr); } #endif } void termit_configs_set_defaults() { configs.default_window_title = g_strdup("Termit"); configs.default_tab_name = g_strdup("Terminal"); termit_style_init(&configs.style); configs.default_command = g_strdup(g_getenv("SHELL")); configs.default_encoding = g_strdup("UTF-8"); configs.default_word_char_exceptions = g_strdup("-A-Za-z0-9,./?%&#_~"); configs.scrollback_lines = 4096; configs.cols = 80; configs.rows = 24; configs.default_bksp = VTE_ERASE_AUTO; configs.default_delete = VTE_ERASE_AUTO; configs.default_blink = VTE_CURSOR_BLINK_SYSTEM; configs.default_shape = VTE_CURSOR_SHAPE_BLOCK; configs.user_menus = g_array_new(FALSE, TRUE, sizeof(struct UserMenu)); configs.user_popup_menus = g_array_new(FALSE, TRUE, sizeof(struct UserMenu)); configs.key_bindings = g_array_new(FALSE, TRUE, sizeof(struct KeyBinding)); configs.mouse_bindings = g_array_new(FALSE, TRUE, sizeof(struct MouseBinding)); configs.matches = g_array_new(FALSE, TRUE, sizeof(struct Match)); configs.start_maximized = FALSE; configs.hide_titlebar_when_maximized = FALSE; configs.hide_single_tab = FALSE; configs.show_scrollbar = TRUE; configs.fill_tabbar = FALSE; configs.hide_menubar = FALSE; configs.hide_tabbar = FALSE; configs.show_border = TRUE; configs.allow_changing_title = FALSE; configs.audible_bell = FALSE; configs.urgency_on_bell = FALSE; configs.get_window_title_callback = 0; configs.get_tab_title_callback = 0; configs.get_statusbar_callback = 0; configs.kb_policy = TermitKbUseKeysym; configs.tab_pos = GTK_POS_TOP; configs.scroll_on_output = FALSE; configs.scroll_on_keystroke = TRUE; } static void free_menu(GArray* menus) { guint i = 0; for (; ilen; ++i) { struct UserMenu* um = &g_array_index(menus, struct UserMenu, i); guint j = 0; for (; jitems->len; ++j) { struct UserMenuItem* umi = &g_array_index(um->items, struct UserMenuItem, j); g_free(umi->name); g_free(umi->accel); termit_lua_unref(&umi->lua_callback); } g_free(um->name); g_array_free(um->items, TRUE); } } void termit_config_deinit() { g_free(configs.default_window_title); g_free(configs.default_tab_name); termit_style_free(&configs.style); g_free(configs.default_command); g_free(configs.default_encoding); g_free(configs.default_word_char_exceptions); free_menu(configs.user_menus); g_array_free(configs.user_menus, TRUE); free_menu(configs.user_popup_menus); g_array_free(configs.user_popup_menus, TRUE); // name and default_binding are static (e.g. can be in readonly mempage) guint i = 0; for (; ilen; ++i) { struct KeyBinding* kb = &g_array_index(configs.key_bindings, struct KeyBinding, i); termit_lua_unref(&kb->lua_callback); } g_array_free(configs.key_bindings, TRUE); i = 0; for (; ilen; ++i) { struct MouseBinding* mb = &g_array_index(configs.mouse_bindings, struct MouseBinding, i); termit_lua_unref(&mb->lua_callback); } g_array_free(configs.mouse_bindings, TRUE); i = 0; for (; ilen; ++i) { struct Match* match = &g_array_index(configs.matches, struct Match, i); vte_regex_unref(match->regex); g_free(match->pattern); } g_array_free(configs.matches, TRUE); termit_lua_unref(&configs.get_window_title_callback); termit_lua_unref(&configs.get_tab_title_callback); termit_lua_unref(&configs.get_statusbar_callback); } termit-3.1/src/configs.h000066400000000000000000000060431362242615500152620ustar00rootroot00000000000000/* Copyright © 2007-2016 Evgeny Ratnikov * * 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 . */ #ifndef TERMIT_CONFIGS_H #define TERMIT_CONFIGS_H #include #include #include "termit_style.h" enum TermitKbPolicy {TermitKbUseKeycode = 1, TermitKbUseKeysym = 2}; struct Configs { gchar* default_window_title; gchar* default_tab_name; gchar* default_command; gchar* default_encoding; gchar* default_word_char_exceptions; guint scrollback_lines; guint cols; guint rows; VteEraseBinding default_bksp; VteEraseBinding default_delete; VteCursorBlinkMode default_blink; VteCursorShape default_shape; GArray* user_menus; // UserMenu GArray* user_popup_menus; // UserMenu GArray* key_bindings; // KeyBinding GArray* mouse_bindings; // MouseBinding GArray* matches; // Match gboolean start_maximized; gboolean hide_titlebar_when_maximized; gboolean hide_single_tab; gboolean show_scrollbar; gboolean hide_menubar; gboolean hide_tabbar; gboolean fill_tabbar; gboolean show_border; gboolean urgency_on_bell; gboolean allow_changing_title; gboolean audible_bell; gboolean scroll_on_output; gboolean scroll_on_keystroke; int get_window_title_callback; int get_tab_title_callback; int get_statusbar_callback; enum TermitKbPolicy kb_policy; GtkPositionType tab_pos; struct TermitStyle style; GArray* default_tabs; // TabInfo }; struct Match { gchar* pattern; VteRegex* regex; guint32 flags; int tag; int lua_callback; }; struct UserMenuItem { gchar* name; gchar* accel; int lua_callback; }; struct UserMenu { gchar* name; GArray* items; // UserMenuItem }; extern struct Configs configs; void termit_config_deinit(); void termit_configs_set_defaults(); void termit_config_load(); void termit_config_trace(); void termit_keys_trace(); const char* termit_erase_binding_to_string(VteEraseBinding val); VteEraseBinding termit_erase_binding_from_string(const char* str); const char* termit_cursor_blink_mode_to_string(VteCursorBlinkMode val); VteCursorBlinkMode termit_cursor_blink_mode_from_string(const char* str); const char* termit_cursor_shape_to_string(VteCursorShape val); VteCursorShape termit_cursor_shape_from_string(const char* str); #define TERMIT_USER_MENU_ITEM_DATA "termit.umi_data" #define TERMIT_TAB_DATA "termit.tab_data" #endif /* TERMIT_CONFIGS_H */ termit-3.1/src/keybindings.c000066400000000000000000000222741362242615500161370ustar00rootroot00000000000000/* Copyright © 2007-2016 Evgeny Ratnikov * * 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 . */ #include #include #include #include #include #include #include "termit.h" #include "configs.h" #include "termit_core_api.h" #include "lua_api.h" #include "keybindings.h" extern lua_State* L; static Display* disp; void termit_keys_trace() { #ifdef DEBUG guint i = 0; for (; ilen; ++i) { struct KeyBinding* kb = &g_array_index(configs.key_bindings, struct KeyBinding, i); TRACE("%s: %d, %d(%ld)", kb->name, kb->kws.state, kb->kws.keyval, kb->keycode); } #endif } #define ADD_DEFAULT_KEYBINDING(keybinding_, lua_callback_) \ { \ lua_getglobal(ls, lua_callback_); \ int func = luaL_ref(ls, LUA_REGISTRYINDEX); \ termit_keys_bind(keybinding_, func); \ } void termit_keys_set_defaults() { lua_State* ls = L; disp = XOpenDisplay(NULL); ADD_DEFAULT_KEYBINDING("Alt-Left", "prevTab"); ADD_DEFAULT_KEYBINDING("Alt-Right", "nextTab"); ADD_DEFAULT_KEYBINDING("Ctrl-t", "openTab"); ADD_DEFAULT_KEYBINDING("CtrlShift-w", "closeTab"); ADD_DEFAULT_KEYBINDING("Ctrl-Insert", "copy"); ADD_DEFAULT_KEYBINDING("Shift-Insert", "paste"); // push func to stack, get ref termit_keys_trace(); } struct TermitModifier { const gchar* name; guint state; }; struct TermitModifier termit_modifiers[] = { {"Alt", GDK_MOD1_MASK}, {"Ctrl", GDK_CONTROL_MASK}, {"Shift", GDK_SHIFT_MASK}, {"Meta", GDK_META_MASK}, {"Super", GDK_SUPER_MASK}, {"Hyper", GDK_HYPER_MASK} }; static guint TermitModsSz = sizeof(termit_modifiers)/sizeof(struct TermitModifier); static gint get_modifier_state(const gchar* token) { size_t modifier_len; size_t step; if (!token) { return GDK_NOTHING; } guint i = 0; gint state = 0; while (strlen(token) > 0) { step = 0; for (; ilen; ++i) { struct KeyBinding* kb = &g_array_index(configs.key_bindings, struct KeyBinding, i); if (!strcmp(kb->name, name)) { return i; } } return -1; } struct TermitMouseEvent { const gchar* name; GdkEventType type; }; struct TermitMouseEvent termit_mouse_events[] = { {"DoubleClick", GDK_2BUTTON_PRESS} }; static guint TermitMouseEventsSz = sizeof(termit_mouse_events)/sizeof(struct TermitMouseEvent); gint get_mouse_event_type(const gchar* event_name) { if (!event_name) { return GDK_NOTHING; } guint i = 0; for (; ilen; ++i) { struct MouseBinding* mb = &g_array_index(configs.mouse_bindings, struct MouseBinding, i); if (type == mb->type) { return i; } } return -1; } void termit_keys_unbind(const gchar* keybinding) { gint kb_index = get_kb_index(keybinding); if (kb_index < 0) { TRACE("keybinding [%s] not found - skipping", keybinding); return; } struct KeyBinding* kb = &g_array_index(configs.key_bindings, struct KeyBinding, kb_index); termit_lua_unref(&kb->lua_callback); g_free(kb->name); g_array_remove_index(configs.key_bindings, kb_index); } int termit_parse_keys_str(const gchar* keybinding, struct KeyWithState* kws) { gchar *modifier = NULL, *key = NULL; // token[0] - modifier. Only Alt, Ctrl or Shift allowed. gchar** tokens = g_strsplit(keybinding, "-", 2); if (!tokens[0]) { ERROR("failed to parse: [%s]", keybinding); return -1; } if (!tokens[1]) { key = tokens[0]; } else { modifier = tokens[0]; key = tokens[1]; } gint tmp_state = 0; if (modifier) { tmp_state = get_modifier_state(modifier); if (tmp_state == GDK_NOTHING) { TRACE("Bad modifier: %s", keybinding); return -1; } } guint tmp_keyval = gdk_keyval_from_name(key); if (tmp_keyval == GDK_KEY_VoidSymbol) { TRACE("Bad keyval: %s", keybinding); return -1; } g_strfreev(tokens); kws->state = tmp_state; kws->keyval = gdk_keyval_to_lower(tmp_keyval); return 0; } void termit_keys_bind(const gchar* keybinding, int lua_callback) { struct KeyWithState kws = {}; if (termit_parse_keys_str(keybinding, &kws) < 0) { ERROR("failed to parse keybinding: %s", keybinding); return; } gint kb_index = get_kb_index(keybinding); if (kb_index < 0) { struct KeyBinding kb = {}; kb.name = g_strdup(keybinding); kb.kws = kws; kb.keycode = XKeysymToKeycode(disp, kb.kws.keyval); kb.lua_callback = lua_callback; g_array_append_val(configs.key_bindings, kb); } else { struct KeyBinding* kb = &g_array_index(configs.key_bindings, struct KeyBinding, kb_index); kb->kws = kws; kb->keycode = XKeysymToKeycode(disp, kb->kws.keyval); termit_lua_unref(&kb->lua_callback); kb->lua_callback = lua_callback; } } void termit_mouse_bind(const gchar* mouse_event, int lua_callback) { GdkEventType type = get_mouse_event_type(mouse_event); if (type == GDK_NOTHING) { TRACE("unknown event: %s", mouse_event); return; } gint mb_index = get_mb_index(type); if (mb_index < 0) { struct MouseBinding mb = {}; mb.type = type; mb.lua_callback = lua_callback; g_array_append_val(configs.mouse_bindings, mb); } else { struct MouseBinding* mb = &g_array_index(configs.mouse_bindings, struct MouseBinding, mb_index); mb->type = type; termit_lua_unref(&mb->lua_callback); mb->lua_callback = lua_callback; } } void termit_mouse_unbind(const gchar* mouse_event) { GdkEventType type = get_mouse_event_type(mouse_event); if (type == GDK_NOTHING) { TRACE("unknown event: %s", mouse_event); return; } gint mb_index = get_mb_index(type); if (mb_index < 0) { TRACE("mouse event [%d] not found - skipping", type); return; } struct MouseBinding* mb = &g_array_index(configs.mouse_bindings, struct MouseBinding, mb_index); termit_lua_unref(&mb->lua_callback); g_array_remove_index(configs.mouse_bindings, mb_index); } static gboolean termit_key_press_use_keycode(GdkEventKey *event) { guint i = 0; for (; ilen; ++i) { struct KeyBinding* kb = &g_array_index(configs.key_bindings, struct KeyBinding, i); if (kb && (event->state & kb->kws.state) == kb->kws.state) { if (event->hardware_keycode == kb->keycode) { termit_lua_dofunction(kb->lua_callback); return TRUE; } } } return FALSE; } static gboolean termit_key_press_use_keysym(GdkEventKey *event) { guint i = 0; for (; ilen; ++i) { struct KeyBinding* kb = &g_array_index(configs.key_bindings, struct KeyBinding, i); if (kb && (event->state & kb->kws.state) == kb->kws.state) { if (gdk_keyval_to_lower(event->keyval) == kb->kws.keyval) { termit_lua_dofunction(kb->lua_callback); return TRUE; } } } return FALSE; } gboolean termit_key_event(GdkEventKey* event) { switch(configs.kb_policy) { case TermitKbUseKeycode: return termit_key_press_use_keycode(event); break; case TermitKbUseKeysym: return termit_key_press_use_keysym(event); break; default: ERROR("unknown kb_policy: %d", configs.kb_policy); } return FALSE; } gboolean termit_mouse_event(GdkEventButton* event) { guint i = 0; for (; ilen; ++i) { struct MouseBinding* kb = &g_array_index(configs.mouse_bindings, struct MouseBinding, i); if (kb && (event->type & kb->type)) { termit_lua_dofunction(kb->lua_callback); } } return FALSE; } termit-3.1/src/keybindings.h000066400000000000000000000030441362242615500161360ustar00rootroot00000000000000/* Copyright © 2007-2016 Evgeny Ratnikov * * 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 . */ #ifndef TERMIT_KEYBINDINGS_H #define TERMIT_KEYBINDINGS_H #include #include struct KeyWithState { guint state; guint keyval; }; typedef void(*BindingCallback)(); struct KeyBinding { gchar* name; struct KeyWithState kws; KeySym keycode; int lua_callback; }; struct MouseBinding { GdkEventType type; int lua_callback; }; //void termit_load_keys(); int termit_parse_keys_str(const gchar* keybinding, struct KeyWithState* kws); void termit_keys_bind(const gchar* keys, int lua_callback); void termit_keys_unbind(const gchar* keys); void termit_mouse_bind(const gchar* mouse_event, int lua_callback); void termit_mouse_unbind(const gchar* mouse_event); void termit_keys_set_defaults(); gboolean termit_key_event(GdkEventKey* event); gboolean termit_mouse_event(GdkEventButton* event); #endif /* TERMIT_KEYBINDINGS_H */ termit-3.1/src/lua_api.c000066400000000000000000000521551362242615500152440ustar00rootroot00000000000000/* Copyright © 2007-2016 Evgeny Ratnikov * * 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 . */ #include #include #include #include #include "termit.h" #include "termit_core_api.h" #include "keybindings.h" #include "configs.h" #include "callbacks.h" #include "lua_api.h" extern lua_State* L; TermitLuaTableLoaderResult termit_lua_load_table(lua_State* ls, TermitLuaTableLoaderFunc func, const int tableIndex, void* data) { if (!lua_istable(ls, tableIndex)) { ERROR("not a table"); return TERMIT_LUA_TABLE_LOADER_FAILED; } lua_pushnil(ls); while (lua_next(ls, tableIndex) != 0) { if (lua_isnumber(ls, tableIndex + 1)) { func("0", ls, tableIndex + 2, data); } else if (lua_isstring(ls, tableIndex + 1)) { const char* name = lua_tostring(ls, tableIndex + 1); func(name, ls, tableIndex + 2, data); } else { ERROR("neither number nor string value found - skipping"); lua_pop(ls, 1); } lua_pop(ls, 1); } return TERMIT_LUA_TABLE_LOADER_OK; } void termit_lua_execute(const gchar* cmd) { TRACE("executing script: %s", cmd); int s = luaL_dostring(L, cmd); termit_lua_report_error(__FILE__, __LINE__, s); } void termit_lua_report_error(const char* file, int line, int status) { if (status == 0) { return; } g_fprintf(stderr, "%s:%d %s\n", file, line, lua_tostring(L, -1)); lua_pop(L, 1); } static int termit_lua_setOptions(lua_State* ls) { termit_lua_load_table(ls, termit_lua_options_loader, 1, &configs); if (configs.default_tabs) { guint i = 0; for (; i < configs.default_tabs->len; ++i) { struct TabInfo* ti = &g_array_index(configs.default_tabs, struct TabInfo, i); termit_append_tab_with_details(ti); g_free(ti->name); g_strfreev(ti->argv); g_free(ti->encoding); g_free(ti->working_dir); } g_array_free(configs.default_tabs, TRUE); configs.default_tabs = NULL; } return 0; } int termit_lua_dofunction(int f) { lua_State* ls = L; if(f != LUA_REFNIL) { lua_rawgeti(ls, LUA_REGISTRYINDEX, f); if (lua_pcall(ls, 0, 0, 0)) { TRACE("error running function (%d): %s", f, lua_tostring(ls, -1)); lua_pop(ls, 1); return 0; } return 1; } return 0; } int termit_lua_dofunction2(int f, const char* arg1) { lua_State* ls = L; if(f != LUA_REFNIL) { lua_rawgeti(ls, LUA_REGISTRYINDEX, f); lua_pushstring(ls, arg1); if (lua_pcall(ls, 1, 0, 0)) { TRACE("error running function (%d): %s", f, lua_tostring(ls, -1)); lua_pop(ls, 1); return 0; } return 1; } return 0; } int termit_lua_domatch(int f, const gchar* matchedText) { lua_State* ls = L; if(f != LUA_REFNIL) { lua_rawgeti(ls, LUA_REGISTRYINDEX, f); lua_pushstring(ls, matchedText); if (lua_pcall(ls, 1, 0, 0)) { TRACE("error running function (%d: %s): %s", f, matchedText, lua_tostring(ls, -1)); lua_pop(ls, 1); return 0; } return 1; } return 0; } void termit_lua_unref(int* lua_callback) { if (*lua_callback) { luaL_unref(L, LUA_REGISTRYINDEX, *lua_callback); *lua_callback = 0; } } gchar* termit_lua_getStatusbarCallback(int f, guint page) { lua_State* ls = L; if(f != LUA_REFNIL) { lua_rawgeti(ls, LUA_REGISTRYINDEX, f); lua_pushnumber(ls, page); if (lua_pcall(ls, 1, 1, 0)) { TRACE("error running function: %s", lua_tostring(ls, -1)); lua_pop(ls, 1); return NULL; } if (lua_isstring(ls, -1)) { return g_strdup(lua_tostring(ls, -1)); } } return NULL; } gchar* termit_lua_getTitleCallback(int f, const gchar* title) { lua_State* ls = L; if(f != LUA_REFNIL) { lua_rawgeti(ls, LUA_REGISTRYINDEX, f); lua_pushstring(ls, title); if (lua_pcall(ls, 1, 1, 0)) { TRACE("error running function: %s", lua_tostring(ls, -1)); lua_pop(ls, 1); return NULL; } if (lua_isstring(ls, -1)) { return g_strdup(lua_tostring(ls, -1)); } } return NULL; } static int termit_lua_bindKey(lua_State* ls) { TRACE_MSG(__FUNCTION__); if (lua_isnil(ls, 1)) { TRACE_MSG("nil args: skipping"); } else if (!lua_isstring(ls, 1)) { TRACE_MSG("bad args: skipping"); } else if (lua_isnil(ls, 2)) { const char* keybinding = lua_tostring(ls, 1); termit_keys_unbind(keybinding); TRACE("unbindKey: %s", keybinding); } else if (lua_isfunction(ls, 2)) { const char* keybinding = lua_tostring(ls, 1); int func = luaL_ref(ls, LUA_REGISTRYINDEX); termit_keys_bind(keybinding, func); TRACE("bindKey: %s - %d", keybinding, func); } return 0; } static int termit_lua_bindMouse(lua_State* ls) { if (lua_isnil(ls, 1)) { TRACE_MSG("nil args: skipping"); } else if (!lua_isstring(ls, 1)) { TRACE_MSG("bad args: skipping"); } else if (lua_isnil(ls, 2)) { const char* mousebinding = lua_tostring(ls, 1); termit_mouse_unbind(mousebinding); TRACE("unbindMouse: %s", mousebinding); } else if (lua_isfunction(ls, 2)) { const char* mousebinding = lua_tostring(ls, 1); int func = luaL_ref(ls, LUA_REGISTRYINDEX); termit_mouse_bind(mousebinding, func); TRACE("bindMouse: %s - %d", mousebinding, func); } return 0; } static int termit_lua_toggleMenubar(lua_State* ls) { termit_toggle_menubar(); return 0; } static int termit_lua_toggleTabbar(lua_State* ls) { termit_toggle_tabbar(); return 0; } void termit_lua_tab_loader(const gchar* name, lua_State* ls, int index, void* data) { struct TabInfo* ti = (struct TabInfo*)data; if (strcmp(name, "title") == 0) { termit_config_get_string(&ti->name, ls, index); } else if (strcmp(name, "command") == 0) { if (ti->argv == NULL) { ti->argv = (gchar**)g_new0(gchar*, 2); } termit_config_get_string(&ti->argv[0], ls, index); } else if (strcmp(name, "encoding") == 0) { termit_config_get_string(&ti->encoding, ls, index); } else if (strcmp(name, "backspaceBinding") == 0) { termit_config_get_erase_binding(&ti->bksp_binding, ls, index); } else if (strcmp(name, "deleteBinding") == 0) { termit_config_get_erase_binding(&ti->delete_binding, ls, index); } else if (strcmp(name, "cursorBlinkMode") == 0) { termit_config_get_cursor_blink_mode(&ti->cursor_blink_mode, ls, index); } else if (strcmp(name, "cursorShape") == 0) { termit_config_get_cursor_shape(&ti->cursor_shape, ls, index); } else if (strcmp(name, "workingDir") == 0) { termit_config_get_string(&ti->working_dir, ls, index); } } static int termit_lua_nextTab(lua_State* ls) { TRACE_MSG(__FUNCTION__); termit_next_tab(); return 0; } static int termit_lua_prevTab(lua_State* ls) { TRACE_MSG(__FUNCTION__); termit_prev_tab(); return 0; } static int termit_lua_copy(lua_State* ls) { TRACE_MSG(__FUNCTION__); termit_copy(); return 0; } static int termit_lua_paste(lua_State* ls) { TRACE_MSG(__FUNCTION__); termit_paste(); return 0; } static int termit_lua_openTab(lua_State* ls) { TRACE_MSG(__FUNCTION__); if (lua_istable(ls, 1)) { struct TabInfo ti = {}; if (termit_lua_load_table(ls, termit_lua_tab_loader, 1, &ti) != TERMIT_LUA_TABLE_LOADER_OK) { ERROR("openTab failed"); return 0; } termit_append_tab_with_details(&ti); g_free(ti.name); g_strfreev(ti.argv); g_free(ti.encoding); g_free(ti.working_dir); } else { termit_append_tab(); } return 0; } static int termit_lua_closeTab(lua_State* ls) { TRACE_FUNC; termit_close_tab(); return 0; } static int termit_lua_setKbPolicy(lua_State* ls) { if (lua_isnil(ls, 1)) { TRACE_MSG("no kbPolicy defined: skipping"); return 0; } else if (!lua_isstring(ls, 1)) { TRACE_MSG("kbPolicy is not string: skipping"); return 0; } const gchar* val = lua_tostring(ls, 1); TRACE("setKbPolicy: %s", val); if (!strcmp(val, "keycode")) { termit_set_kb_policy(TermitKbUseKeycode); } else if (!strcmp(val, "keysym")) { termit_set_kb_policy(TermitKbUseKeysym); } else { ERROR("unknown kbPolicy: %s", val); } return 0; } static void menuItemLoader(const gchar* name, lua_State* ls, int index, void* data) { struct UserMenuItem* umi = (struct UserMenuItem*)data; if (!strcmp(name, "name") && lua_isstring(ls, index)) { const gchar* value = lua_tostring(ls, index); umi->name = g_strdup(value); } else if (!strcmp(name, "action") && lua_isfunction(ls, index)) { umi->lua_callback = luaL_ref(ls, LUA_REGISTRYINDEX); lua_pushnil(ls); // luaL_ref pops value so we restore stack size } else if (!strcmp(name, "accel") && lua_isstring(ls, index)) { const gchar* value = lua_tostring(ls, index); umi->accel = g_strdup(value); } } static void menuLoader(const gchar* name, lua_State* ls, int index, void* data) { struct UserMenu* um = (struct UserMenu*)data; if (lua_istable(ls, index)) { struct UserMenuItem umi = {}; if (termit_lua_load_table(ls, menuItemLoader, index, &umi) == TERMIT_LUA_TABLE_LOADER_OK) { g_array_append_val(um->items, umi); } else { ERROR("failed to load item: %s.%s", name, lua_tostring(ls, 3)); } } else { ERROR("unknown type instead if menu table: skipping"); lua_pop(ls, 1); } } static int loadMenu(lua_State* ls, GArray* menus) { if (lua_isnil(ls, 1) || lua_isnil(ls, 2)) { TRACE_MSG("menu not defined: skipping"); return -1; } else if (!lua_istable(ls, 1) || !lua_isstring(ls, 2)) { TRACE_MSG("menu is not table: skipping"); return -1; } struct UserMenu um = {}; um.name = g_strdup(lua_tostring(ls, 2)); lua_pop(ls, 1); um.items = g_array_new(FALSE, TRUE, sizeof(struct UserMenuItem)); if (termit_lua_load_table(ls, menuLoader, 1, &um) != TERMIT_LUA_TABLE_LOADER_OK) { ERROR("addMenu failed"); } if (um.items->len > 0) { g_array_append_val(menus, um); } else { g_free(um.name); g_array_free(um.items, TRUE); } return 0; } static int termit_lua_addMenu(lua_State* ls) { if (loadMenu(ls, configs.user_menus) < 0) { ERROR("addMenu failed"); } return 0; } static int termit_lua_addPopupMenu(lua_State* ls) { if (loadMenu(ls, configs.user_popup_menus) < 0) { ERROR("addMenu failed"); } return 0; } static int termit_lua_setColormap(lua_State* ls) { const gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(termit.notebook)); TERMIT_GET_TAB_BY_INDEX(pTab, page, return 0); termit_lua_load_colormap(ls, 1, &pTab->style.colors, &pTab->style.colors_size); termit_tab_apply_colors(pTab); return 0; } static int termit_lua_setEncoding(lua_State* ls) { if (lua_isnil(ls, 1)) { TRACE_MSG("no encoding defined: skipping"); return 0; } else if (!lua_isstring(ls, 1)) { TRACE_MSG("encoding is not string: skipping"); return 0; } const gchar* val = lua_tostring(ls, 1); termit_set_encoding(val); return 0; } static int termit_lua_activateTab(lua_State* ls) { if (lua_isnil(ls, 1)) { TRACE_MSG("no tabNum defined: skipping"); return 0; } else if (!lua_isnumber(ls, 1)) { TRACE_MSG("tabNum is not number: skipping"); return 0; } int tab_index = lua_tointeger(ls, 1); termit_activate_tab(tab_index - 1); return 0; } static int termit_lua_currentTab(lua_State* ls) { return termit_lua_fill_tab(termit_get_current_tab_index(), ls); } static int termit_lua_currentTabIndex(lua_State* ls) { lua_pushinteger(ls, termit_get_current_tab_index() + 1); return 1; } static int termit_lua_loadSessionDialog(lua_State* ls) { termit_on_load_session(); return 0; } static int termit_lua_saveSessionDialog(lua_State* ls) { termit_on_save_session(); return 0; } static int termit_lua_preferencesDialog(lua_State* ls) { termit_on_edit_preferences(); return 0; } static int termit_lua_setTabTitleDialog(lua_State* ls) { termit_on_set_tab_name(); return 0; } static int termit_lua_setTabPos(lua_State* ls) { if (lua_isnil(ls, 1)) { TRACE_MSG("no tabNum defined: skipping"); return 0; } else if (!lua_isnumber(ls, 1)) { TRACE_MSG("tabNum is not number: skipping"); return 0; } int tab_index = lua_tointeger(ls, 1); gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(termit.notebook)); TERMIT_GET_TAB_BY_INDEX(pTab, page, return 0); termit_tab_set_pos(pTab, tab_index - 1); return 0; } static int termit_lua_setTabTitle(lua_State* ls) { if (lua_isnil(ls, 1)) { TRACE_MSG("no tabName defined: skipping"); return 0; } else if (!lua_isstring(ls, 1)) { TRACE_MSG("tabName is not string: skipping"); return 0; } const gchar* val = lua_tostring(ls, 1); gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(termit.notebook)); TERMIT_GET_TAB_BY_INDEX(pTab, page, return 0); termit_tab_set_title(pTab, val); pTab->custom_tab_name = TRUE; return 0; } static int termit_lua_setWindowTitle(lua_State* ls) { if (lua_isnil(ls, 1)) { TRACE_MSG("no title defined: skipping"); return 0; } else if (!lua_isstring(ls, 1)) { TRACE_MSG("title is not string: skipping"); return 0; } const gchar* val = lua_tostring(ls, 1); termit_set_window_title(val); return 0; } static int termit_lua_setTabColor__(lua_State* ls, void (*callback)(gint, const GdkRGBA*)) { if (lua_isnil(ls, 1)) { TRACE_MSG("no color defined: skipping"); return 0; } else if (!lua_isstring(ls, 1)) { TRACE_MSG("color is not string: skipping"); return 0; } const gchar* val = lua_tostring(ls, 1); GdkRGBA color; if (gdk_rgba_parse(&color, val) == TRUE) { callback(-1, &color); } return 0; } static int termit_lua_setTabForegroundColor(lua_State* ls) { return termit_lua_setTabColor__(ls, &termit_tab_set_color_foreground_by_index); } static int termit_lua_setTabBackgroundColor(lua_State* ls) { return termit_lua_setTabColor__(ls, &termit_tab_set_color_background_by_index); } static int termit_lua_setTabFont(lua_State* ls) { if (lua_isnil(ls, 1)) { TRACE_MSG("no font defined: skipping"); return 0; } else if (!lua_isstring(ls, 1)) { TRACE_MSG("font is not string: skipping"); return 0; } const gchar* val = lua_tostring(ls, 1); termit_tab_set_font_by_index(-1, val); return 0; } static int termit_lua_spawn(lua_State* ls) { if (lua_isnil(ls, 1)) { TRACE_MSG("no command defined: skipping"); return 0; } else if (!lua_isstring(ls, 1)) { TRACE_MSG("command is not string: skipping"); return 0; } GError *err = NULL; const gchar* val = lua_tostring(ls, 1); g_spawn_command_line_async(val, &err); return 0; } static int termit_lua_forEachRow(lua_State* ls) { if (lua_isnil(ls, 1)) { TRACE_MSG("no function defined: skipping"); return 0; } else if (!lua_isfunction(ls, 1)) { TRACE_MSG("1 arg is not function: skipping"); return 0; } int func = luaL_ref(ls, LUA_REGISTRYINDEX); termit_for_each_row(func); termit_lua_unref(&func); return 0; } static int termit_lua_forEachVisibleRow(lua_State* ls) { if (lua_isnil(ls, 1)) { TRACE_MSG("no function defined: skipping"); return 0; } else if (!lua_isfunction(ls, 1)) { TRACE_MSG("1 arg is not function: skipping"); return 0; } int func = luaL_ref(ls, LUA_REGISTRYINDEX); termit_for_each_visible_row(func); termit_lua_unref(&func); return 0; } static int termit_lua_feed(lua_State* ls) { if (lua_isnil(ls, 1)) { TRACE_MSG("no data defined: skipping"); return 0; } else if (!lua_isstring(ls, 1)) { TRACE_MSG("data is not string: skipping"); return 0; } const gchar* val = lua_tostring(ls, 1); gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(termit.notebook)); TERMIT_GET_TAB_BY_INDEX(pTab, page, return 0); termit_tab_feed(pTab, val); return 0; } static int termit_lua_feedChild(lua_State* ls) { if (lua_isnil(ls, 1)) { TRACE_MSG("no data defined: skipping"); return 0; } else if (!lua_isstring(ls, 1)) { TRACE_MSG("data is not string: skipping"); return 0; } const gchar* val = lua_tostring(ls, 1); gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(termit.notebook)); TERMIT_GET_TAB_BY_INDEX(pTab, page, return 0); termit_tab_feed_child(pTab, val); return 0; } static int termit_lua_findNext(lua_State* ls) { termit_search_find_next(); return 0; } static int termit_lua_findPrev(lua_State* ls) { termit_search_find_prev(); return 0; } static int termit_lua_findDlg(lua_State* ls) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(termit.b_toggle_search), TRUE); return 0; } static int termit_lua_selection(lua_State* ls) { gchar* buff = termit_get_selection(); if (!buff) { return 0; } lua_pushstring(ls, buff); g_free(buff); return 1; } static int termit_lua_reconfigure(lua_State* ls) { termit_reconfigure(); termit_config_trace(); return 0; } static int termit_lua_quit(lua_State* ls) { termit_on_exit(); return 0; } struct TermitLuaFunction { const char* lua_func_name; lua_CFunction c_func; int lua_func; } functions[] = { {"activateTab", termit_lua_activateTab, 0}, {"addMenu", termit_lua_addMenu, 0}, {"addPopupMenu", termit_lua_addPopupMenu, 0}, {"bindKey", termit_lua_bindKey, 0}, {"bindMouse", termit_lua_bindMouse, 0}, {"closeTab", termit_lua_closeTab, 0}, {"copy", termit_lua_copy, 0}, {"currentTab", termit_lua_currentTab, 0}, {"currentTabIndex", termit_lua_currentTabIndex, 0}, {"feed", termit_lua_feed, 0}, {"feedChild", termit_lua_feedChild, 0}, {"findDlg", termit_lua_findDlg, 0}, {"findNext", termit_lua_findNext, 0}, {"findPrev", termit_lua_findPrev, 0}, {"forEachRow", termit_lua_forEachRow, 0}, {"forEachVisibleRow", termit_lua_forEachVisibleRow, 0}, {"loadSessionDlg", termit_lua_loadSessionDialog, 0}, {"nextTab", termit_lua_nextTab, 0}, {"openTab", termit_lua_openTab, 0}, {"paste", termit_lua_paste, 0}, {"preferencesDlg", termit_lua_preferencesDialog, 0}, {"prevTab", termit_lua_prevTab, 0}, {"quit", termit_lua_quit, 0}, {"reconfigure", termit_lua_reconfigure, 0}, {"saveSessionDlg", termit_lua_saveSessionDialog, 0}, {"selection", termit_lua_selection, 0}, {"setColormap", termit_lua_setColormap, 0}, {"setEncoding", termit_lua_setEncoding, 0}, {"setKbPolicy", termit_lua_setKbPolicy, 0}, {"setOptions", termit_lua_setOptions, 0}, {"setTabBackgroundColor", termit_lua_setTabBackgroundColor, 0}, {"setTabFont", termit_lua_setTabFont, 0}, {"setTabForegroundColor", termit_lua_setTabForegroundColor, 0}, {"setTabPos", termit_lua_setTabPos, 0}, {"setTabTitle", termit_lua_setTabTitle, 0}, {"setTabTitleDlg", termit_lua_setTabTitleDialog, 0}, {"setWindowTitle", termit_lua_setWindowTitle, 0}, {"spawn", termit_lua_spawn, 0}, {"toggleMenubar", termit_lua_toggleMenubar, 0}, {"toggleTabbar", termit_lua_toggleTabbar, 0} }; int termit_get_lua_func(const char* name) { unsigned short i = 0; for (; i < sizeof(functions)/sizeof(functions[0]); ++i) { if (strcmp(name, functions[i].lua_func_name) == 0) { return functions[i].lua_func; } } ERROR("not found lua function by name [%s]", name); return 0; } void termit_lua_init_api() { unsigned short i = 0; for (; i < sizeof(functions)/sizeof(functions[0]); ++i) { lua_pushcfunction(L, functions[i].c_func); functions[i].lua_func = luaL_ref(L, LUA_REGISTRYINDEX); lua_rawgeti(L, LUA_REGISTRYINDEX, functions[i].lua_func); lua_setglobal(L, functions[i].lua_func_name); TRACE("%s [%d]", functions[i].lua_func_name, functions[i].lua_func); } } termit-3.1/src/lua_api.h000066400000000000000000000070771362242615500152540ustar00rootroot00000000000000/* Copyright © 2007-2016 Evgeny Ratnikov * * 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 . */ #ifndef TERMIT_LUA_API_H #define TERMIT_LUA_API_H struct lua_State; void termit_lua_init_api(); void termit_lua_close(); void termit_lua_report_error(const char* file, int line, int status); void termit_lua_init(const gchar* initFile); void termit_lua_load_config(); void termit_lua_execute(const gchar* cmd); int termit_lua_dofunction(int f); int termit_lua_dofunction2(int f, const char* arg1); int termit_lua_domatch(int f, const gchar* matchedText); void termit_lua_unref(int* lua_callback); gchar* termit_lua_getTitleCallback(int f, const gchar* title); gchar* termit_lua_getStatusbarCallback(int f, guint page); int termit_get_lua_func(const char* name); typedef enum {TERMIT_LUA_TABLE_LOADER_OK, TERMIT_LUA_TABLE_LOADER_FAILED} TermitLuaTableLoaderResult; typedef void (*TermitLuaTableLoaderFunc)(const gchar*, struct lua_State*, int, void*); TermitLuaTableLoaderResult termit_lua_load_table(struct lua_State* ls, TermitLuaTableLoaderFunc func, const int tableIndex, void* data); int termit_lua_fill_tab(int tab_index, struct lua_State* ls); /** * Loaders * */ void termit_lua_options_loader(const gchar* name, struct lua_State* ls, int index, void* data); void termit_lua_keys_loader(const gchar* name, struct lua_State* ls, int index, void* data); void termit_lua_tab_loader(const gchar* name, struct lua_State* ls, int index, void* data); void termit_lua_load_colormap(struct lua_State* ls, int index, GdkRGBA** colors, glong* sz); void termit_config_get_string(gchar** opt, struct lua_State* ls, int index); void termit_config_get_double(double* opt, struct lua_State* ls, int index); void termit_config_getuint(guint* opt, struct lua_State* ls, int index); void termit_config_get_boolean(gboolean* opt, struct lua_State* ls, int index); void termit_config_get_function(int* opt, struct lua_State* ls, int index); void termit_config_get_color(GdkRGBA** opt, struct lua_State* ls, int index); void termit_config_get_erase_binding(VteEraseBinding* opt, struct lua_State* ls, int index); void termit_config_get_cursor_blink_mode(VteCursorBlinkMode* opt, struct lua_State* ls, int index); void termit_config_get_cursor_shape(VteCursorShape* opt, struct lua_State* ls, int index); #define TERMIT_TAB_ADD_NUMBER(name, value) {\ lua_pushstring(ls, name); \ lua_pushnumber(ls, value); \ lua_rawset(ls, -3); \ } #define TERMIT_TAB_ADD_STRING(name, value) {\ lua_pushstring(ls, name); \ lua_pushstring(ls, value); \ lua_rawset(ls, -3); \ } #define TERMIT_TAB_ADD_VOID(name, value) {\ lua_pushstring(ls, name); \ lua_pushlightuserdata(ls, value); \ lua_rawset(ls, -3); \ } #define TERMIT_TAB_ADD_BOOLEAN(name, value) {\ lua_pushstring(ls, name); \ lua_pushboolean(ls, value); \ lua_rawset(ls, -3); \ } #define TERMIT_TAB_ADD_CALLBACK(name, value) {\ lua_pushstring(ls, name); \ lua_rawgeti(ls, LUA_REGISTRYINDEX, value); \ lua_rawset(ls, -3); \ } #endif /* TERMIT_LUA_API_H */ termit-3.1/src/lua_conf.c000066400000000000000000000415041362242615500154140ustar00rootroot00000000000000/* Copyright © 2007-2016 Evgeny Ratnikov * * 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 . */ #include #include // XParseGeometry #include #include #include #include #include "termit.h" #include "termit_core_api.h" #include "configs.h" #include "keybindings.h" #include "lua_api.h" extern struct TermitData termit; extern struct Configs configs; lua_State* L = NULL; void termit_lua_close() { lua_close(L); } static void trace_menus(GArray* menus) { #ifdef DEBUG guint i = 0; for (; ilen; ++i) { struct UserMenu* um = &g_array_index(menus, struct UserMenu, i); TRACE("%s items %d", um->name, um->items->len); guint j = 0; for (; jitems->len; ++j) { struct UserMenuItem* umi = &g_array_index(um->items, struct UserMenuItem, j); TRACE(" %s: (%d) [%s]", umi->name, umi->lua_callback, umi->accel); } } #endif } void termit_config_get_string(gchar** opt, lua_State* ls, int index) { if (!lua_isnil(ls, index) && lua_isstring(ls, index)) { if (*opt) { g_free(*opt); } *opt = g_strdup(lua_tostring(ls, index)); } } void termit_config_get_double(double* opt, lua_State* ls, int index) { if (!lua_isnil(ls, index) && lua_isnumber(ls, index)) { *opt = lua_tonumber(ls, index); } } void termit_config_getuint(guint* opt, lua_State* ls, int index) { if (!lua_isnil(ls, index) && lua_isnumber(ls, index)) { *opt = lua_tointeger(ls, index); } } void termit_config_get_boolean(gboolean* opt, lua_State* ls, int index) { if (!lua_isnil(ls, index) && lua_isboolean(ls, index)) { *opt = lua_toboolean(ls, index); } } void termit_config_get_function(int* opt, lua_State* ls, int index) { if (!lua_isnil(ls, index) && lua_isfunction(ls, index)) { *opt = luaL_ref(ls, LUA_REGISTRYINDEX); // luaL_ref pops value so we restore stack size lua_pushnil(ls); } } void termit_config_get_color(GdkRGBA** opt, lua_State* ls, int index) { gchar* color_str = NULL; termit_config_get_string(&color_str, ls, index); if (color_str) { GdkRGBA color = {}; if (gdk_rgba_parse(&color, color_str) == TRUE) { *opt = gdk_rgba_copy(&color); TRACE("color_str=%s", color_str); } } g_free(color_str); } void termit_config_get_erase_binding(VteEraseBinding* opt, lua_State* ls, int index) { gchar* str = NULL; termit_config_get_string(&str, ls, index); *opt = termit_erase_binding_from_string(str); g_free(str); } void termit_config_get_cursor_blink_mode(VteCursorBlinkMode* opt, lua_State* ls, int index) { gchar* str = NULL; termit_config_get_string(&str, ls, index); *opt = termit_cursor_blink_mode_from_string(str); g_free(str); } void termit_config_get_cursor_shape(VteCursorShape* opt, lua_State* ls, int index) { gchar* str = NULL; termit_config_get_string(&str, ls, index); *opt = termit_cursor_shape_from_string(str); g_free(str); } static void matchesLoader(const gchar* pattern, struct lua_State* ls, int index, void* data) { TRACE("pattern=%s index=%d data=%p", pattern, index, data); if (!lua_isfunction(ls, index)) { ERROR("match [%s] without function: skipping", pattern); return; } GArray* matches = (GArray*)data; struct Match match = {}; GError* err = NULL; match.regex = vte_regex_new_for_match(pattern, -1, VTE_REGEX_FLAGS_DEFAULT, &err); if (err) { TRACE("failed to compile regex [%s]: skipping", pattern); return; } match.flags = 0; match.pattern = g_strdup(pattern); termit_config_get_function(&match.lua_callback, ls, index); g_array_append_val(matches, match); } struct ColormapHelper { GdkRGBA* colors; int idx; }; static void colormapLoader(const gchar* name, lua_State* ls, int index, void* data) { struct ColormapHelper* ch = (struct ColormapHelper*)data; if (!lua_isnil(ls, index) && lua_isstring(ls, index)) { const gchar* colorStr = lua_tostring(ls, index); if (!gdk_rgba_parse(&(ch->colors[ch->idx]), colorStr)) { ERROR("failed to parse color: %s %d - %s", name, ch->idx, colorStr); } } else { ERROR("invalid type in colormap: skipping"); } ++ch->idx; } static void tabsLoader(const gchar* name, lua_State* ls, int index, void* data) { if (lua_istable(ls, index)) { GArray* tabs = (GArray*)data; struct TabInfo ti = {}; if (termit_lua_load_table(ls, termit_lua_tab_loader, index, &ti) != TERMIT_LUA_TABLE_LOADER_OK) { ERROR("failed to load tab: %s %s", name, lua_tostring(ls, 3)); } else { g_array_append_val(tabs, ti); } } else { ERROR("unknown type instead if tab table: skipping"); lua_pop(ls, 1); } } void termit_lua_load_colormap(lua_State* ls, int index, GdkRGBA** colors, glong* sz) { if (lua_isnil(ls, index) || !lua_istable(ls, index)) { ERROR("invalid colormap type"); return; } const int size = lua_rawlen(ls, index); if ((size != 8) && (size != 16) && (size != 24)) { ERROR("bad colormap length: %d", size); return; } struct ColormapHelper ch = {}; ch.colors = g_malloc0(size * sizeof(GdkRGBA)); if (termit_lua_load_table(ls, colormapLoader, index, &ch) == TERMIT_LUA_TABLE_LOADER_OK) { if (*colors) { g_free(*colors); } *colors = ch.colors; *sz = size; } else { ERROR("failed to load colormap"); return; } TRACE("colormap loaded: size=%ld", *sz); } static void termit_config_get_position(GtkPositionType* pos, lua_State* ls, int index) { if (!lua_isnil(ls, index) && lua_isstring(ls, index)) { const char* str = lua_tostring(ls, index); if (strcmp(str, "Top") == 0) { *pos = GTK_POS_TOP; } else if (strcmp(str, "Bottom") == 0) { *pos = GTK_POS_BOTTOM; } else if (strcmp(str, "Left") == 0) { *pos = GTK_POS_LEFT; } else if (strcmp(str, "Right") == 0) { *pos = GTK_POS_RIGHT; } else { ERROR("unknown pos: [%s]", str); } } } void termit_lua_options_loader(const gchar* name, lua_State* ls, int index, void* data) { struct Configs* p_cfg = (struct Configs*)data; if (!strcmp(name, "tabName")) { termit_config_get_string(&(p_cfg->default_tab_name), ls, index); } else if (!strcmp(name, "windowTitle")) { termit_config_get_string(&(p_cfg->default_window_title), ls, index); } else if (!strcmp(name, "encoding")) { termit_config_get_string(&(p_cfg->default_encoding), ls, index); } else if (!strcmp(name, "wordCharExceptions")) { termit_config_get_string(&(p_cfg->default_word_char_exceptions), ls, index); } else if (!strcmp(name, "font")) { termit_config_get_string(&(p_cfg->style.font_name), ls, index); } else if (!strcmp(name, "foregroundColor")) { termit_config_get_color(&p_cfg->style.foreground_color, ls, index); } else if (!strcmp(name, "backgroundColor")) { termit_config_get_color(&p_cfg->style.background_color, ls, index); } else if (!strcmp(name, "showScrollbar")) { termit_config_get_boolean(&(p_cfg->show_scrollbar), ls, index); } else if (!strcmp(name, "fillTabbar")) { termit_config_get_boolean(&(p_cfg->fill_tabbar), ls, index); } else if (!strcmp(name, "hideSingleTab")) { termit_config_get_boolean(&(p_cfg->hide_single_tab), ls, index); } else if (!strcmp(name, "hideMenubar")) { termit_config_get_boolean(&(p_cfg->hide_menubar), ls, index); } else if (!strcmp(name, "hideTabbar")) { termit_config_get_boolean(&(p_cfg->hide_tabbar), ls, index); } else if (!strcmp(name, "showBorder")) { termit_config_get_boolean(&(p_cfg->show_border), ls, index); } else if (!strcmp(name, "startMaximized")) { termit_config_get_boolean(&(p_cfg->start_maximized), ls, index); } else if (!strcmp(name, "hideTitlebarWhenMaximized")) { termit_config_get_boolean(&(p_cfg->hide_titlebar_when_maximized), ls, index); } else if (!strcmp(name, "scrollbackLines")) { termit_config_getuint(&(p_cfg->scrollback_lines), ls, index); } else if (!strcmp(name, "allowChangingTitle")) { termit_config_get_boolean(&(p_cfg->allow_changing_title), ls, index); } else if (!strcmp(name, "audibleBell")) { termit_config_get_boolean(&(p_cfg->audible_bell), ls, index); } else if (!strcmp(name, "scrollOnOutput")) { termit_config_get_boolean(&(p_cfg->scroll_on_output), ls, index); } else if (!strcmp(name, "scrollOnKeystroke")) { termit_config_get_boolean(&(p_cfg->scroll_on_keystroke), ls, index); } else if (!strcmp(name, "urgencyOnBell")) { termit_config_get_boolean(&(p_cfg->urgency_on_bell), ls, index); } else if (!strcmp(name, "getWindowTitle")) { termit_config_get_function(&(p_cfg->get_window_title_callback), ls, index); } else if (!strcmp(name, "tabPos")) { termit_config_get_position(&(p_cfg->tab_pos), ls, index); } else if (!strcmp(name, "getTabTitle")) { termit_config_get_function(&(p_cfg->get_tab_title_callback), ls, index); } else if (!strcmp(name, "setStatusbar")) { termit_config_get_function(&(p_cfg->get_statusbar_callback), ls, index); } else if (!strcmp(name, "backspaceBinding")) { termit_config_get_erase_binding(&(p_cfg->default_bksp), ls, index); } else if (!strcmp(name, "deleteBinding")) { termit_config_get_erase_binding(&(p_cfg->default_delete), ls, index); } else if (!strcmp(name, "cursorBlinkMode")) { termit_config_get_cursor_blink_mode(&(p_cfg->default_blink), ls, index); } else if (!strcmp(name, "cursorShape")) { termit_config_get_cursor_shape(&(p_cfg->default_shape), ls, index); } else if (!strcmp(name, "colormap")) { termit_lua_load_colormap(ls, index, &configs.style.colors, &configs.style.colors_size); } else if (!strcmp(name, "matches")) { if (termit_lua_load_table(ls, matchesLoader, index, configs.matches) != TERMIT_LUA_TABLE_LOADER_OK) { ERROR("failed to load matches"); } } else if (!strcmp(name, "geometry")) { gchar* geometry_str = NULL; termit_config_get_string(&geometry_str, ls, index); if (geometry_str) { unsigned int cols = 0, rows = 0; int tmp1 = 0, tmp2 = 0; XParseGeometry(geometry_str, &tmp1, &tmp2, &cols, &rows); if ((cols != 0) && (rows != 0)) { p_cfg->cols = cols; p_cfg->rows = rows; } } g_free(geometry_str); } else if (!strcmp(name, "tabs")) { if (lua_istable(ls, index)) { if (!configs.default_tabs) { configs.default_tabs = g_array_new(FALSE, TRUE, sizeof(struct TabInfo)); } TRACE("tabs at index: %d tabs.size=%d", index, configs.default_tabs->len); if (termit_lua_load_table(ls, tabsLoader, index, configs.default_tabs) != TERMIT_LUA_TABLE_LOADER_OK) { ERROR("openTab failed"); } } else { ERROR("expecting table"); } } } static void termit_lua_add_package_path(const gchar* path) { gchar* luaCmd = g_strdup_printf("package.path = package.path .. \";%s/?.lua\"", path); int s = luaL_dostring(L, luaCmd); termit_lua_report_error(__FILE__, __LINE__, s); g_free(luaCmd); } static gchar** termit_system_path() { const gchar *configSystem = g_getenv("XDG_CONFIG_DIRS"); gchar* xdgConfigDirs = NULL; if (configSystem) { xdgConfigDirs = g_strdup_printf("%s:/etc/xdg", configSystem); } else { xdgConfigDirs = g_strdup("/etc/xdg"); } gchar** systemPaths = g_strsplit(xdgConfigDirs, ":", 0); g_free(xdgConfigDirs); return systemPaths; } static gchar* termit_user_path() { const gchar *configHome = g_getenv("XDG_CONFIG_HOME"); if (configHome) { return g_strdup(configHome); } else { return g_strdup_printf("%s/.config", g_getenv("HOME")); } } static void load_init(const gchar* initFile) { const gchar *configFile = "rc.lua"; gchar** systemPaths = termit_system_path(); guint i = 0; gchar* systemPath = systemPaths[i]; while (systemPath) { if (g_file_test(systemPath, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR) == TRUE) { termit_lua_add_package_path(systemPath); } systemPath = systemPaths[++i]; } gchar* userPath = termit_user_path(); termit_lua_add_package_path(userPath); gchar* fullPath = NULL; if (initFile) { fullPath = g_strdup(initFile); } else { fullPath = g_strdup_printf("%s/termit/%s", userPath, configFile); if (g_file_test(fullPath, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR) == FALSE) { TRACE("%s not found", fullPath); g_free(fullPath); i = 0; gchar* systemPath = systemPaths[i]; while (systemPath) { fullPath = g_strdup_printf("%s/termit/%s", systemPath, configFile); if (g_file_test(fullPath, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR) == FALSE) { TRACE("%s not found", fullPath); g_free(fullPath); fullPath = NULL; } else { break; } systemPath = systemPaths[++i]; } } } g_strfreev(systemPaths); g_free(userPath); if (fullPath) { TRACE("using config: %s", fullPath); int s = luaL_loadfile(L, fullPath); termit_lua_report_error(__FILE__, __LINE__, s); g_free(fullPath); s = lua_pcall(L, 0, LUA_MULTRET, 0); termit_lua_report_error(__FILE__, __LINE__, s); } else { ERROR("config file %s not found", configFile); } } int termit_lua_fill_tab(int tab_index, lua_State* ls) { TERMIT_GET_TAB_BY_INDEX(pTab, tab_index, return 0); lua_newtable(ls); TERMIT_TAB_ADD_STRING("title", pTab->title); TERMIT_TAB_ADD_STRING("command", pTab->argv[0]); TERMIT_TAB_ADD_STRING("argv", ""); // FIXME: add argv TERMIT_TAB_ADD_STRING("encoding", pTab->encoding); gchar* working_dir = termit_get_pid_dir(pTab->pid); TERMIT_TAB_ADD_STRING("workingDir", working_dir); g_free(working_dir); TERMIT_TAB_ADD_NUMBER("pid", pTab->pid); TERMIT_TAB_ADD_STRING("font", pTab->style.font_name); TERMIT_TAB_ADD_NUMBER("fontSize", pango_font_description_get_size(pTab->style.font)/PANGO_SCALE); TERMIT_TAB_ADD_STRING("backspaceBinding", termit_erase_binding_to_string(pTab->bksp_binding)); TERMIT_TAB_ADD_STRING("deleteBinding", termit_erase_binding_to_string(pTab->delete_binding)); TERMIT_TAB_ADD_STRING("cursorBlinkMode", termit_cursor_blink_mode_to_string(pTab->cursor_blink_mode)); TERMIT_TAB_ADD_STRING("cursorShape", termit_cursor_shape_to_string(pTab->cursor_shape)); return 1; } static int termit_lua_tabs_index(lua_State* ls) { if (lua_isnumber(ls, 1)) { TRACE_MSG("index is not number: skipping"); return 0; } int tab_index = lua_tointeger(ls, -1); TRACE("tab_index:%d", tab_index); return termit_lua_fill_tab(tab_index - 1, ls); } static int termit_lua_tabs_newindex(lua_State* ls) { ERROR("'tabs' is read-only variable"); return 0; } static void termit_lua_init_tabs() { lua_newtable(L); luaL_newmetatable(L, "tabs_meta"); lua_pushcfunction(L, termit_lua_tabs_index); lua_setfield(L, -2, "__index"); lua_pushcfunction(L, termit_lua_tabs_newindex); lua_setfield(L, -2, "__newindex"); lua_setmetatable(L, -2); lua_setglobal(L, "tabs"); } static const gchar* termit_init_file = NULL; void termit_lua_load_config() { load_init(termit_init_file); termit_config_trace(); trace_menus(configs.user_menus); trace_menus(configs.user_popup_menus); } void termit_lua_init(const gchar* initFile) { L = luaL_newstate(); luaL_openlibs(L); if (!termit_init_file) { termit_init_file = g_strdup(initFile); } termit_lua_init_tabs(); termit_lua_init_api(); termit_keys_set_defaults(); termit_lua_load_config(); } termit-3.1/src/sessions.c000066400000000000000000000120131362242615500154650ustar00rootroot00000000000000/* Copyright © 2007-2016 Evgeny Ratnikov * * 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 . */ #include #include #include #include #include #include #include #include #include #include #include #include "termit.h" #include "termit_core_api.h" #include "configs.h" #include "callbacks.h" #include "lua_api.h" #include "sessions.h" extern lua_State* L; // from Openbox static gboolean parse_mkdir(const gchar *path, gint mode) { gboolean ret = TRUE; g_return_val_if_fail(path != NULL, FALSE); g_return_val_if_fail(path[0] != '\0', FALSE); if (!g_file_test(path, G_FILE_TEST_IS_DIR)) { if (mkdir(path, mode) == -1) { ret = FALSE; } } return ret; } // from Openbox static gboolean parse_mkdir_path(const gchar *path, gint mode) { gboolean ret = TRUE; g_return_val_if_fail(path != NULL, FALSE); g_return_val_if_fail(path[0] == '/', FALSE); if (!g_file_test(path, G_FILE_TEST_IS_DIR)) { gchar *c, *e; c = g_strdup(path); e = c; while ((e = strchr(e + 1, '/'))) { *e = '\0'; if (!(ret = parse_mkdir(c, mode))) { goto parse_mkdir_path_end; } *e = '/'; } ret = parse_mkdir(c, mode); parse_mkdir_path_end: g_free(c); } return ret; } void termit_init_sessions() { gchar *fullPath; const gchar *dataHome = g_getenv("XDG_DATA_HOME"); if (dataHome) { fullPath = g_strdup_printf("%s/termit", dataHome); } else { fullPath = g_strdup_printf("%s/.local/share/termit", g_getenv("HOME")); } TRACE("%s %s", __FUNCTION__, fullPath); if (!parse_mkdir_path(fullPath, 0700)) { g_message(_("Unable to create directory '%s': %s"), fullPath, g_strerror(errno)); } g_free(fullPath); } void termit_load_session(const gchar* sessionFile) { TRACE("loading sesions from %s", sessionFile); int s = luaL_dofile(L, sessionFile); termit_lua_report_error(__FILE__, __LINE__, s); } /** * saves session as lua-script * */ void termit_save_session(const gchar* sessionFile) { TRACE("saving session to file %s", sessionFile); FILE* fd = g_fopen(sessionFile, "w"); if ((intptr_t)fd == -1) { TRACE("failed savimg to %s", sessionFile); return; } guint pages = gtk_notebook_get_n_pages(GTK_NOTEBOOK(termit.notebook)); guint i = 0; for (; i < pages; ++i) { TERMIT_GET_TAB_BY_INDEX(pTab, i, continue); gchar* working_dir = termit_get_pid_dir(pTab->pid); gchar* groupName = g_strdup_printf("tab%d", i); g_fprintf(fd, "%s = {}\n", groupName); g_fprintf(fd, "%s.title = \"%s\"\n", groupName, gtk_label_get_text(GTK_LABEL(pTab->tab_name))); g_fprintf(fd, "%s.workingDir = \"%s\"\n", groupName, working_dir); g_fprintf(fd, "%s.command = \"%s\"\n", groupName, pTab->argv[0]); // FIXME compund commands would not be saved g_fprintf(fd, "%s.argv = {}\n", groupName); g_fprintf(fd, "%s.encoding = \"%s\"\n", groupName, pTab->encoding); GValue val = {}; g_value_init(&val, g_type_from_name("VteEraseBinding")); g_object_get_property(G_OBJECT(pTab->vte), "backspace-binding", &val); VteEraseBinding eb = g_value_get_enum(&val); if (eb != VTE_ERASE_AUTO) { g_fprintf(fd, "%s.backspaceBinding = \"%s\"\n", groupName, termit_erase_binding_to_string(eb)); } g_value_unset(&val); g_value_init(&val, g_type_from_name("VteEraseBinding")); g_object_get_property(G_OBJECT(pTab->vte), "delete-binding", &val); eb = g_value_get_enum(&val); if (eb != VTE_ERASE_AUTO) { g_fprintf(fd, "%s.deleteBinding = \"%s\"\n", groupName, termit_erase_binding_to_string(eb)); } g_value_unset(&val); if (pTab->cursor_blink_mode != VTE_CURSOR_BLINK_SYSTEM) { g_fprintf(fd, "%s.cursorBlinkMode = \"%s\"\n", groupName, termit_cursor_blink_mode_to_string(pTab->cursor_blink_mode)); } if (pTab->cursor_shape != VTE_CURSOR_SHAPE_BLOCK) { g_fprintf(fd, "%s.cursorShape = \"%s\"\n", groupName, termit_cursor_shape_to_string(pTab->cursor_shape)); } g_fprintf(fd, "openTab(%s)\n\n", groupName); g_free(groupName); g_free(working_dir); } // g_fprintf(fd, data); fclose(fd); } termit-3.1/src/sessions.h000066400000000000000000000016221362242615500154760ustar00rootroot00000000000000/* Copyright © 2007-2016 Evgeny Ratnikov * * 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 . */ #ifndef TERMIT_SESSIONS_H #define TERMIT_SESSIONS_H void termit_init_sessions(); void termit_load_session(const gchar* sessionFile); void termit_save_session(const gchar* sessionFile); #endif /* TERMIT_SESSIONS_H */ termit-3.1/src/termit.c000066400000000000000000000474361362242615500151440ustar00rootroot00000000000000/* Copyright © 2007-2016 Evgeny Ratnikov * * 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 . */ #include #include #include #include #include #include #include "config.h" #include "termit_core_api.h" #include "lua_api.h" #include "callbacks.h" #include "sessions.h" #include "keybindings.h" #include "configs.h" #include "termit.h" struct TermitData termit = {}; struct TermitTab* termit_get_tab_by_index(guint index) { GtkWidget* tabWidget = gtk_notebook_get_nth_page(GTK_NOTEBOOK(termit.notebook), index); if (!tabWidget) { ERROR("tabWidget not found by index=%u", index); return NULL; } struct TermitTab* pTab = (struct TermitTab*)g_object_get_data(G_OBJECT(tabWidget), TERMIT_TAB_DATA); return pTab; } struct TermitTab* termit_get_tab_by_vte(VteTerminal* vte, gint* page) { gint sz = gtk_notebook_get_n_pages(GTK_NOTEBOOK(termit.notebook)); for (gint p = 0; p < sz; ++p) { struct TermitTab* pTab = termit_get_tab_by_index(p); if (pTab && VTE_TERMINAL(pTab->vte) == vte) { *page = p; return pTab; } } ERROR("tabWidget not found by vte=%p", vte); return NULL; } static GtkWidget* create_statusbar() { GtkWidget* statusbar = gtk_statusbar_new(); return statusbar; } static void create_search(struct TermitData* termit) { termit->b_toggle_search = gtk_toggle_button_new(); gtk_button_set_image(GTK_BUTTON(termit->b_toggle_search), gtk_image_new_from_icon_name("edit-find", GTK_ICON_SIZE_BUTTON)); g_signal_connect(G_OBJECT(termit->b_toggle_search), "toggled", G_CALLBACK(termit_on_toggle_search), NULL); termit->b_find_next = gtk_button_new_from_icon_name("go-next", GTK_ICON_SIZE_BUTTON); g_signal_connect(G_OBJECT(termit->b_find_next), "clicked", G_CALLBACK(termit_on_find_next), NULL); termit->b_find_prev = gtk_button_new_from_icon_name("go-previous", GTK_ICON_SIZE_BUTTON); g_signal_connect(G_OBJECT(termit->b_find_prev), "clicked", G_CALLBACK(termit_on_find_prev), NULL); termit->search_entry = gtk_entry_new(); g_signal_connect(G_OBJECT(termit->search_entry), "key-press-event", G_CALLBACK(termit_on_search_keypress), NULL); } static void pack_widgets() { termit.hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); gtk_box_pack_start(GTK_BOX(termit.hbox), termit.menu_bar, FALSE, 0, 0); gtk_box_pack_start(GTK_BOX(termit.hbox), termit.b_toggle_search, FALSE, 0, 0); gtk_box_pack_start(GTK_BOX(termit.hbox), termit.search_entry, FALSE, 0, 0); gtk_box_pack_start(GTK_BOX(termit.hbox), termit.b_find_prev, FALSE, 0, 0); gtk_box_pack_start(GTK_BOX(termit.hbox), termit.b_find_next, FALSE, 0, 0); gtk_box_pack_start(GTK_BOX(termit.hbox), termit.statusbar, TRUE, 1, 0); GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); gtk_box_pack_start(GTK_BOX(vbox), termit.notebook, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(vbox), termit.hbox, FALSE, FALSE, 0); gtk_container_add(GTK_CONTAINER(termit.main_window), vbox); if (!gtk_notebook_get_n_pages(GTK_NOTEBOOK(termit.notebook))) { termit_append_tab(); } g_signal_connect(G_OBJECT(termit.notebook), "switch-page", G_CALLBACK(termit_on_switch_page), NULL); g_signal_connect(G_OBJECT(termit.main_window), "button-press-event", G_CALLBACK(termit_on_double_click), NULL); } static void menu_item_set_accel(GtkMenuItem* mi, const gchar* parentName, const gchar* itemName, const gchar* accel) { struct KeyWithState kws = {}; if (termit_parse_keys_str(accel, &kws) < 0) { ERROR("failed to parse keybinding: %s", accel); return; } gchar* path = NULL; path = g_strdup_printf("/%s/%s", parentName, itemName); gtk_menu_item_set_accel_path(GTK_MENU_ITEM(mi), path); gtk_accel_map_add_entry(path, kws.keyval, kws.state); g_free(path); } static void termit_create_menus(GtkWidget* menu_bar, GtkAccelGroup* accel, GArray* menus) { TRACE("menus->len=%d", menus->len); guint j = 0; for (; jlen; ++j) { struct UserMenu* um = &g_array_index(menus, struct UserMenu, j); GtkWidget *mi_menu = gtk_menu_item_new_with_label(um->name); GtkWidget *menu = gtk_menu_new(); gtk_menu_item_set_submenu(GTK_MENU_ITEM(mi_menu), menu); gtk_menu_set_accel_group(GTK_MENU(menu), accel); TRACE("%s items->len=%d", um->name, um->items->len); guint i = 0; gtk_menu_set_accel_group(GTK_MENU(menu), accel); for (; iitems->len; ++i) { struct UserMenuItem* umi = &g_array_index(um->items, struct UserMenuItem, i); GtkWidget *mi_tmp = gtk_menu_item_new_with_label(umi->name); g_object_set_data(G_OBJECT(mi_tmp), TERMIT_USER_MENU_ITEM_DATA, umi); g_signal_connect(G_OBJECT(mi_tmp), "activate", G_CALLBACK(termit_on_menu_item_selected), NULL); if (umi->accel) { menu_item_set_accel(GTK_MENU_ITEM(mi_tmp), um->name, umi->name, umi->accel); } gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi_tmp); } gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), mi_menu); } } static GtkWidget* termit_lua_menu_item_from_string(const gchar* label, const char* luaFunc) { GtkWidget *mi = gtk_menu_item_new_with_label(label); g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(termit_on_menu_item_selected), NULL); struct UserMenuItem* umi = (struct UserMenuItem*)malloc(sizeof(struct UserMenuItem)); umi->name = g_strdup(gtk_menu_item_get_label(GTK_MENU_ITEM(mi))); umi->accel = NULL; umi->lua_callback = termit_get_lua_func(luaFunc); g_object_set_data(G_OBJECT(mi), TERMIT_USER_MENU_ITEM_DATA, umi); return mi; } void termit_create_menubar() { GtkAccelGroup *accel = gtk_accel_group_new(); gtk_window_add_accel_group(GTK_WINDOW(termit.main_window), accel); GtkWidget* menu_bar = gtk_menu_bar_new(); // File menu GtkWidget *mi_new_tab = termit_lua_menu_item_from_string(_("Open"), "openTab"); GtkWidget *mi_close_tab = termit_lua_menu_item_from_string(_("Delete"), "closeTab"); GtkWidget *mi_exit = termit_lua_menu_item_from_string(_("Quit"), "quit"); GtkWidget *mi_file = gtk_menu_item_new_with_label(_("File")); GtkWidget *file_menu = gtk_menu_new(); gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), mi_new_tab); gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), mi_close_tab); gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), gtk_separator_menu_item_new()); gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), mi_exit); gtk_menu_item_set_submenu(GTK_MENU_ITEM(mi_file), file_menu); gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), mi_file); // Edit menu GtkWidget *mi_set_tab_name = termit_lua_menu_item_from_string(_("Set tab name..."), "setTabTitleDlg"); GtkWidget *mi_edit_preferences = termit_lua_menu_item_from_string(_("Preferences"), "preferencesDlg"); GtkWidget *mi_copy = termit_lua_menu_item_from_string(_("Copy"), "copy"); GtkWidget *mi_paste = termit_lua_menu_item_from_string(_("Paste"), "paste"); GtkWidget *mi_edit = gtk_menu_item_new_with_label(_("Edit")); GtkWidget *edit_menu = gtk_menu_new(); gtk_menu_shell_append(GTK_MENU_SHELL(edit_menu), mi_copy); gtk_menu_shell_append(GTK_MENU_SHELL(edit_menu), mi_paste); gtk_menu_shell_append(GTK_MENU_SHELL(edit_menu), gtk_separator_menu_item_new()); gtk_menu_shell_append(GTK_MENU_SHELL(edit_menu), mi_set_tab_name); gtk_menu_shell_append(GTK_MENU_SHELL(edit_menu), mi_edit_preferences); gtk_menu_item_set_submenu(GTK_MENU_ITEM(mi_edit), edit_menu); gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), mi_edit); // Sessions menu GtkWidget *mi_load_session = termit_lua_menu_item_from_string(_("Open session"), "loadSessionDlg"); GtkWidget *mi_save_session = termit_lua_menu_item_from_string(_("Save session"), "saveSessionDlg"); GtkWidget *mi_sessions = gtk_menu_item_new_with_label(_("Sessions")); GtkWidget *sessions_menu = gtk_menu_new(); gtk_menu_shell_append(GTK_MENU_SHELL(sessions_menu), mi_load_session); gtk_menu_shell_append(GTK_MENU_SHELL(sessions_menu), mi_save_session); gtk_menu_item_set_submenu(GTK_MENU_ITEM(mi_sessions), sessions_menu); gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), mi_sessions); // User menus termit_create_menus(menu_bar, accel, configs.user_menus); termit.menu_bar = menu_bar; } void termit_create_popup_menu() { termit.menu = gtk_menu_new(); GtkWidget *mi_new_tab = termit_lua_menu_item_from_string(_("Open"), "openTab"); GtkWidget *mi_close_tab = termit_lua_menu_item_from_string(_("Delete"), "closeTab"); GtkWidget *mi_set_tab_name = termit_lua_menu_item_from_string(_("Set tab name..."), "setTabTitleDlg"); GtkWidget *mi_edit_preferences = termit_lua_menu_item_from_string(_("Preferences"), "preferencesDlg"); GtkWidget *mi_copy = termit_lua_menu_item_from_string(_("Copy"), "copy"); GtkWidget *mi_paste = termit_lua_menu_item_from_string(_("Paste"), "paste"); GtkWidget *mi_exit = termit_lua_menu_item_from_string(_("Quit"), "quit"); termit.mi_show_scrollbar = gtk_check_menu_item_new_with_label(_("Scrollbar")); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(termit.mi_show_scrollbar), configs.show_scrollbar); termit_set_show_scrollbar_signal(termit.mi_show_scrollbar, NULL); gtk_menu_shell_append(GTK_MENU_SHELL(termit.menu), mi_new_tab); gtk_menu_shell_append(GTK_MENU_SHELL(termit.menu), mi_close_tab); gtk_menu_shell_append(GTK_MENU_SHELL(termit.menu), gtk_separator_menu_item_new()); gtk_menu_shell_append(GTK_MENU_SHELL(termit.menu), mi_set_tab_name); gtk_menu_shell_append(GTK_MENU_SHELL(termit.menu), termit.mi_show_scrollbar); gtk_menu_shell_append(GTK_MENU_SHELL(termit.menu), mi_edit_preferences); gtk_menu_shell_append(GTK_MENU_SHELL(termit.menu), gtk_separator_menu_item_new()); gtk_menu_shell_append(GTK_MENU_SHELL(termit.menu), mi_copy); gtk_menu_shell_append(GTK_MENU_SHELL(termit.menu), mi_paste); gtk_menu_shell_append(GTK_MENU_SHELL(termit.menu), gtk_separator_menu_item_new()); gtk_menu_shell_append(GTK_MENU_SHELL(termit.menu), mi_exit); // User popup menus TRACE("user_popup_menus->len=%d", configs.user_popup_menus->len); guint j = 0; for (; jlen; ++j) { struct UserMenu* um = &g_array_index(configs.user_popup_menus, struct UserMenu, j); GtkWidget *mi_util = gtk_menu_item_new_with_label(um->name); GtkWidget *utils_menu = gtk_menu_new(); gtk_menu_item_set_submenu(GTK_MENU_ITEM(mi_util), utils_menu); TRACE("%s items->len=%d", um->name, um->items->len); guint i = 0; for (; iitems->len; i++) { struct UserMenuItem* umi = &g_array_index(um->items, struct UserMenuItem, i); GtkWidget *mi_tmp = gtk_menu_item_new_with_label(umi->name); g_object_set_data(G_OBJECT(mi_tmp), TERMIT_USER_MENU_ITEM_DATA, umi); gtk_menu_shell_append(GTK_MENU_SHELL(utils_menu), mi_tmp); g_signal_connect(G_OBJECT(mi_tmp), "activate", G_CALLBACK(termit_on_menu_item_selected), NULL); } gtk_menu_shell_insert(GTK_MENU_SHELL(termit.menu), mi_util, 6); } gtk_widget_show_all(termit.menu); } static void termit_init(const gchar* initFile, gchar** argv) { termit_init_sessions(); termit_configs_set_defaults(); termit.tab_max_number = 1; termit.main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_default_icon_name("utilities-terminal"); termit.statusbar = create_statusbar(); create_search(&termit); termit.notebook = gtk_notebook_new(); gtk_notebook_set_scrollable(GTK_NOTEBOOK(termit.notebook), TRUE); gtk_notebook_set_show_tabs(GTK_NOTEBOOK(termit.notebook), TRUE); termit_lua_init(initFile); gtk_notebook_set_tab_pos(GTK_NOTEBOOK(termit.notebook), configs.tab_pos); if (argv) { termit_append_tab_with_command(argv); } termit_create_menubar(); pack_widgets(); termit_create_popup_menu(); if (!configs.allow_changing_title) { termit_set_window_title(configs.default_window_title); } if (configs.hide_titlebar_when_maximized) { gtk_window_set_hide_titlebar_when_maximized(GTK_WINDOW(termit.main_window), TRUE); } if (configs.start_maximized) { gtk_window_maximize(GTK_WINDOW(termit.main_window)); } gtk_notebook_set_show_border(GTK_NOTEBOOK(termit.notebook), configs.show_border); } enum { TERMIT_GETOPT_HELP = 'h', TERMIT_GETOPT_VERSION = 'v', TERMIT_GETOPT_INIT = 'i', TERMIT_GETOPT_NAME = 'n', TERMIT_GETOPT_CLASS = 'c', TERMIT_GETOPT_ROLE = 'r', TERMIT_GETOPT_TITLE = 'T' }; static void termit_print_usage() { g_print( "termit %s - terminal emulator\n" "\n" "This program comes with NO WARRANTY, to the extent permitted by law.\n" "You may redistribute copies of this program\n" "under the terms of the GNU General Public License.\n" "For more information about these matters, see the file named COPYING.\n" "\n" "Options:\n" " -h, --help - print this help message\n" " -v, --version - print version number\n" " -e, --execute - execute command\n" " -i, --init=init_file - use init_file instead of standard rc.lua\n" " -n, --name=name - set window name hint\n" " -c, --class=class - set window class hint\n" " -r, --role=role - set window role (Gtk hint)\n" " -T, --title=title - set window title\n" "", PACKAGE_VERSION); } /* Support the command-line option "-e ", which creates a new terminal window and runs the specified command. may be multiple arguments, which form the argument list to the executed program. In other words, the behavior is as though the arguments were passed directly to execvp, bypassing the shell. (xterm's behavior of falling back on using the shell if -e had a single argument and exec failed is permissible but not required.) exec($T, "-e", "bc") --> runs bc exec($T, "-e", "bc --quiet") --> fails OR runs bc --quiet [1] exec($T, "-e", "bc", "--quiet") --> runs bc --quiet exec($T, "-e", "bc *") --> fails OR runs bc * (wildcard) [1] exec($T, "-e", "bc", "*") --> runs bc * (literal) [1] Programs are allowed to pass the entire argument to -e to the shell if and only if there is only one argument and exec fails. */ static GArray* parse_execute_args(int argc, char **argv) { GArray* arr = NULL; int i = 0; int foundE = 0; for (; i < argc; ++i) { if (foundE) { gchar* arg = g_strdup(argv[i]); g_array_append_val(arr, arg); } else { TRACE("[%s] %d", argv[i], strncmp(argv[i], "--execute=", 10)); if ((strcmp(argv[i], "-e") == 0) || (strcmp(argv[i], "--execute") == 0)) { foundE = 1; arr = g_array_new(FALSE, TRUE, sizeof(gchar*)); } else if (strncmp(argv[i], "--execute=", 10) == 0) { foundE = 1; TRACE("arg=[%s]", argv[i] + 10); arr = g_array_new(FALSE, TRUE, sizeof(gchar*)); gchar* arg = g_strdup(argv[i] + 10); g_array_append_val(arr, arg); } } } if (arr == NULL) { return NULL; } if (arr->len > 0) { return arr; } g_array_free(arr, TRUE); return NULL; } int main(int argc, char **argv) { opterr = 0; // suppress "invalid option" error message from getopt gchar* initFile = NULL; GArray* arrArgv = parse_execute_args(argc, argv);; gchar *windowName = NULL, *windowClass = NULL, *windowRole = NULL, *windowTitle = NULL; while (1) { static struct option long_options[] = { {"help", no_argument, 0, TERMIT_GETOPT_HELP}, {"version", no_argument, 0, TERMIT_GETOPT_VERSION}, {"init", required_argument, 0, TERMIT_GETOPT_INIT}, {"name", required_argument, 0, TERMIT_GETOPT_NAME}, {"class", required_argument, 0, TERMIT_GETOPT_CLASS}, {"role", required_argument, 0, TERMIT_GETOPT_ROLE}, {"title", required_argument, 0, TERMIT_GETOPT_TITLE}, {0, 0, 0, 0} }; /* getopt_long stores the option index here. */ int option_index = 0; int flag = getopt_long(argc, argv, "-hvi:n:c:r:T:", long_options, &option_index); /* Detect the end of the options. */ if (flag == -1) { break; } switch (flag) { case TERMIT_GETOPT_HELP: termit_print_usage(); return 0; case TERMIT_GETOPT_VERSION: g_printf(PACKAGE_VERSION); g_printf("\n"); return 0; case TERMIT_GETOPT_INIT: initFile = g_strdup(optarg); break; case TERMIT_GETOPT_NAME: windowName = g_strdup(optarg); break; case TERMIT_GETOPT_CLASS: windowClass = g_strdup(optarg); break; case TERMIT_GETOPT_ROLE: windowRole = g_strdup(optarg); break; case TERMIT_GETOPT_TITLE: windowTitle = g_strdup(optarg); break; case '?': break; /* getopt_long already printed an error message. */ default: break; } } bind_textdomain_codeset(PACKAGE, "UTF-8"); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); gtk_init(&argc, &argv); #ifdef __linux__ signal(SIGCHLD, SIG_IGN); #endif /* LINUX */ gchar** cmdArgv = NULL; if (arrArgv != NULL) { cmdArgv = (gchar**)g_new0(gchar*, arrArgv->len + 1); guint i = 0; for (; i < arrArgv->len; ++i) { cmdArgv[i] = g_array_index(arrArgv, gchar*, i); TRACE(" %d=[%s]", i, cmdArgv[i]); } g_array_free(arrArgv, TRUE); } termit_init(initFile, cmdArgv); g_strfreev(cmdArgv); g_free(initFile); g_signal_connect(G_OBJECT (termit.main_window), "delete_event", G_CALLBACK (termit_on_delete_event), NULL); g_signal_connect(G_OBJECT (termit.main_window), "destroy", G_CALLBACK (termit_on_destroy), NULL); g_signal_connect(G_OBJECT (termit.main_window), "key-press-event", G_CALLBACK(termit_on_key_press), NULL); TRACE("window: name=[%s] class=[%s] role=[%s] title=[%s]", windowName, windowClass, windowRole, windowTitle); if (windowName || windowClass) { gtk_window_set_wmclass(GTK_WINDOW(termit.main_window), windowName, windowClass); g_free(windowName); g_free(windowClass); } if (windowRole) { gtk_window_set_role(GTK_WINDOW(termit.main_window), windowRole); g_free(windowRole); } if (windowTitle) { configs.allow_changing_title = FALSE; gtk_window_set_title(GTK_WINDOW(termit.main_window), windowTitle); g_free(windowTitle); } // Disable menubar on F10 g_object_set(G_OBJECT(gtk_widget_get_settings(termit.main_window)), "gtk-menu-bar-accel", "", NULL); /* Show the application window */ gtk_widget_show_all(termit.main_window); // actions after display termit_after_show_all(); gtk_main(); termit_config_deinit(); termit_lua_close(); return 0; } termit-3.1/src/termit.h000066400000000000000000000060071362242615500151360ustar00rootroot00000000000000/* Copyright © 2007-2016 Evgeny Ratnikov * * 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 . */ #ifndef TERMIT_H #define TERMIT_H #include #include #include #include #include #define _(String) gettext(String) #include "termit_style.h" struct TermitData { GtkWidget *main_window; GtkWidget *notebook; GtkWidget *statusbar; GtkWidget *b_toggle_search; GtkWidget *b_find_next; GtkWidget *b_find_prev; GtkWidget *search_entry; GtkWidget *cb_bookmarks; GtkWidget *menu; GtkWidget *mi_show_scrollbar; GtkWidget *hbox; GtkWidget *menu_bar; gint tab_max_number; }; extern struct TermitData termit; struct TermitTab { GtkWidget *tab_name; GtkWidget *hbox; GtkWidget *vte; GtkWidget *scrollbar; gboolean scrollbar_is_shown; gboolean custom_tab_name; gboolean audible_bell; VteEraseBinding bksp_binding; VteEraseBinding delete_binding; VteCursorBlinkMode cursor_blink_mode; VteCursorShape cursor_shape; gchar *encoding; gchar **argv; gchar *title; GArray* matches; gchar* search_regex; struct TermitStyle style; GPid pid; gulong onChildExitedHandlerId; }; struct TabInfo { gchar* name; gchar** argv; gchar* working_dir; gchar* encoding; VteEraseBinding bksp_binding; VteEraseBinding delete_binding; VteCursorBlinkMode cursor_blink_mode; VteCursorShape cursor_shape; }; struct TermitTab* termit_get_tab_by_index(guint); #define TERMIT_GET_TAB_BY_INDEX(pTab, ind, action) \ struct TermitTab* pTab = termit_get_tab_by_index(ind); \ if (!pTab) \ { g_fprintf(stderr, "%s:%d error: %s is null\n", __FILE__, __LINE__, #pTab); action; } struct TermitTab* termit_get_tab_by_vte(VteTerminal*, gint*); #ifdef DEBUG #define ERROR(format, ...) g_fprintf(stderr, "ERROR: %s:%d " format "\n", __FILE__, __LINE__, ## __VA_ARGS__) #define STDFMT "%s:%d " #define STD __FILE__, __LINE__ #define TRACE(format, ...) g_fprintf(stderr, STDFMT format, STD, ## __VA_ARGS__); g_fprintf(stderr, "\n") #define TRACE_MSG(x) g_fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, x) #define TRACE_FUNC g_fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__) #else #define ERROR(format, ...) g_fprintf(stderr, "%s:%d " format "\n", __FILE__, __LINE__, ## __VA_ARGS__) #define TRACE(format, ...) #define TRACE_MSG(x) #define TRACE_FUNC #endif #endif /* TERMIT_H */ termit-3.1/src/termit_core_api.c000066400000000000000000000606221362242615500167750ustar00rootroot00000000000000/* Copyright © 2007-2016 Evgeny Ratnikov * * 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 . */ #include #include #include #include "termit.h" #include "configs.h" #include "callbacks.h" #include "lua_api.h" #include "keybindings.h" #include "termit_core_api.h" #include "termit_style.h" void termit_create_popup_menu(); void termit_create_menubar(); static void termit_hide_scrollbars() { gint page_num = gtk_notebook_get_n_pages(GTK_NOTEBOOK(termit.notebook)); gint i=0; for (; iscrollbar_is_shown) { gtk_widget_hide(pTab->scrollbar); } } } void termit_tab_set_color_foreground(struct TermitTab* pTab, const GdkRGBA* p_color) { if (p_color) { pTab->style.foreground_color = gdk_rgba_copy(p_color); vte_terminal_set_color_foreground(VTE_TERMINAL(pTab->vte), pTab->style.foreground_color); if (pTab->style.foreground_color) { vte_terminal_set_color_bold(VTE_TERMINAL(pTab->vte), pTab->style.foreground_color); } } } void termit_tab_set_color_background(struct TermitTab* pTab, const GdkRGBA* p_color) { if (p_color) { pTab->style.background_color = gdk_rgba_copy(p_color); vte_terminal_set_color_background(VTE_TERMINAL(pTab->vte), pTab->style.background_color); } } void termit_tab_apply_colors(struct TermitTab* pTab) { if (pTab->style.colors) { vte_terminal_set_colors(VTE_TERMINAL(pTab->vte), NULL, NULL, pTab->style.colors, pTab->style.colors_size); if (pTab->style.foreground_color) { vte_terminal_set_color_bold(VTE_TERMINAL(pTab->vte), pTab->style.foreground_color); } } if (pTab->style.foreground_color) { vte_terminal_set_color_foreground(VTE_TERMINAL(pTab->vte), pTab->style.foreground_color); } if (pTab->style.background_color) { vte_terminal_set_color_background(VTE_TERMINAL(pTab->vte), pTab->style.background_color); } } void termit_tab_feed(struct TermitTab* pTab, const gchar* data) { vte_terminal_feed(VTE_TERMINAL(pTab->vte), data, strlen(data)); } void termit_tab_feed_child(struct TermitTab* pTab, const gchar* data) { vte_terminal_feed_child(VTE_TERMINAL(pTab->vte), data, strlen(data)); } static void termit_set_colors() { gint page_num = gtk_notebook_get_n_pages(GTK_NOTEBOOK(termit.notebook)); gint i=0; for (; ivte), pTab->style.font); const gint cw = vte_terminal_get_char_width(VTE_TERMINAL(pTab->vte)); const gint ch = vte_terminal_get_char_height(VTE_TERMINAL(pTab->vte)); charWidth = charWidth > cw ? charWidth : cw; charHeight = charHeight > ch ? charHeight : ch; } const gint newWidth = charWidth * configs.cols + padding.left + padding.right; const gint newHeight = charHeight * configs.rows + padding.top + padding.bottom; gint oldWidth, oldHeight; gtk_window_get_size(GTK_WINDOW(termit.main_window), &oldWidth, &oldHeight); const gint width = (newWidth > oldWidth) ? newWidth : oldWidth; const gint height = (newHeight > oldHeight) ? newHeight : oldHeight; gtk_window_resize(GTK_WINDOW(termit.main_window), width, height); GdkGeometry geom; geom.min_width = width; geom.min_height = height; gtk_window_set_geometry_hints(GTK_WINDOW(termit.main_window), termit.main_window, &geom, GDK_HINT_MIN_SIZE); } gchar* termit_get_pid_dir(pid_t pid) { gchar* file = g_strdup_printf("/proc/%d/cwd", pid); gchar* link = g_file_read_link(file, NULL); g_free(file); return link; } void termit_toggle_menubar() { if (configs.hide_menubar) { gtk_widget_hide(GTK_WIDGET(termit.hbox)); } else { gtk_widget_show(GTK_WIDGET(termit.hbox)); } configs.hide_menubar = !configs.hide_menubar; } static void termit_check_tabbar() { if (!configs.hide_tabbar) { if (configs.hide_single_tab && gtk_notebook_get_n_pages(GTK_NOTEBOOK(termit.notebook)) == 1) { gtk_notebook_set_show_tabs(GTK_NOTEBOOK(termit.notebook), FALSE); } else { gtk_notebook_set_show_tabs(GTK_NOTEBOOK(termit.notebook), TRUE); } } else { gtk_notebook_set_show_tabs(GTK_NOTEBOOK(termit.notebook), FALSE); } } void termit_toggle_tabbar() { gtk_notebook_set_show_tabs(GTK_NOTEBOOK(termit.notebook), configs.hide_tabbar); configs.hide_tabbar = !configs.hide_tabbar; } void termit_toggle_search() { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(termit.b_toggle_search))) { gtk_widget_show(termit.search_entry); gtk_widget_show(termit.b_find_prev); gtk_widget_show(termit.b_find_next); gtk_window_set_focus(GTK_WINDOW(termit.main_window), termit.search_entry); } else { gtk_widget_hide(termit.search_entry); gtk_widget_hide(termit.b_find_prev); gtk_widget_hide(termit.b_find_next); gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(termit.notebook)); TERMIT_GET_TAB_BY_INDEX(pTab, page, return); gtk_window_set_focus(GTK_WINDOW(termit.main_window), pTab->vte); } } void termit_after_show_all() { termit_set_fonts(); termit_hide_scrollbars(); termit_set_colors(); termit_toggle_menubar(); termit_check_tabbar(); termit_toggle_search(); } void termit_reconfigure() { gtk_widget_destroy(termit.menu); gtk_container_remove(GTK_CONTAINER(termit.hbox), termit.menu_bar); termit_config_deinit(); termit_configs_set_defaults(); termit_keys_set_defaults(); termit_lua_load_config(); termit_create_popup_menu(); termit_create_menubar(); gtk_box_pack_start(GTK_BOX(termit.hbox), termit.menu_bar, FALSE, 0, 0); gtk_box_reorder_child(GTK_BOX(termit.hbox), termit.menu_bar, 0); gtk_widget_show_all(termit.main_window); termit_after_show_all(); } void termit_set_statusbar_message(guint page) { TERMIT_GET_TAB_BY_INDEX(pTab, page, return); TRACE("%s page=%d get_statusbar_callback=%d", __FUNCTION__, page, configs.get_statusbar_callback); if (configs.get_statusbar_callback) { gchar* statusbarMessage = termit_lua_getStatusbarCallback(configs.get_statusbar_callback, page); TRACE("statusbarMessage=[%s]", statusbarMessage); gtk_statusbar_push(GTK_STATUSBAR(termit.statusbar), 0, statusbarMessage); g_free(statusbarMessage); } else { gtk_statusbar_push(GTK_STATUSBAR(termit.statusbar), 0, vte_terminal_get_encoding(VTE_TERMINAL(pTab->vte))); } } void termit_del_tab_n(gint page) { TERMIT_GET_TAB_BY_INDEX(pTab, page, return); TRACE("%s page=%d pid=%d", __FUNCTION__, page, pTab->pid); g_signal_handler_disconnect(G_OBJECT(pTab->vte), pTab->onChildExitedHandlerId); g_array_free(pTab->matches, TRUE); g_free(pTab->encoding); g_strfreev(pTab->argv); g_free(pTab->title); termit_style_free(&pTab->style); g_free(pTab->search_regex); g_free(pTab); gtk_notebook_remove_page(GTK_NOTEBOOK(termit.notebook), page); termit_check_tabbar(); } static void termit_del_tab() { gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(termit.notebook)); termit_del_tab_n(page); } static void termit_tab_add_matches(struct TermitTab* pTab, GArray* matches) { guint i = 0; for (; ilen; ++i) { struct Match* match = &g_array_index(matches, struct Match, i); struct Match tabMatch = {}; tabMatch.lua_callback = match->lua_callback; tabMatch.pattern = match->pattern; tabMatch.tag = vte_terminal_match_add_regex(VTE_TERMINAL(pTab->vte), match->regex, match->flags); vte_terminal_match_set_cursor_type(VTE_TERMINAL(pTab->vte), tabMatch.tag, GDK_HAND2); g_array_append_val(pTab->matches, tabMatch); } } void termit_search_find_next() { gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(termit.notebook)); TERMIT_GET_TAB_BY_INDEX(pTab, page, return); TRACE("%s tab=%p page=%d", __FUNCTION__, pTab, page); vte_terminal_search_find_next(VTE_TERMINAL(pTab->vte)); } void termit_search_find_prev() { gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(termit.notebook)); TERMIT_GET_TAB_BY_INDEX(pTab, page, return); TRACE("%s tab=%p page=%d", __FUNCTION__, pTab, page); vte_terminal_search_find_previous(VTE_TERMINAL(pTab->vte)); } static void termit_for_each_row_execute(struct TermitTab* pTab, glong row_start, glong row_end, int lua_callback) { glong i = row_start; for (; i < row_end; ++i) { char* str = vte_terminal_get_text_range(VTE_TERMINAL(pTab->vte), i, 0, i, 500, NULL, &lua_callback, NULL); str[strlen(str) - 1] = '\0'; termit_lua_dofunction2(lua_callback, str); free(str); } } void termit_for_each_row(int lua_callback) { TRACE("%s lua_callback=%d", __FUNCTION__, lua_callback); gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(termit.notebook)); TERMIT_GET_TAB_BY_INDEX(pTab, page, return); GtkAdjustment* adj = gtk_range_get_adjustment(GTK_RANGE(pTab->scrollbar)); const glong rows_total = gtk_adjustment_get_upper(adj); termit_for_each_row_execute(pTab, 0, rows_total, lua_callback); } void termit_for_each_visible_row(int lua_callback) { TRACE("%s lua_callback=%d", __FUNCTION__, lua_callback); gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(termit.notebook)); TERMIT_GET_TAB_BY_INDEX(pTab, page, return); GtkAdjustment* adj = gtk_range_get_adjustment(GTK_RANGE(pTab->scrollbar)); const glong row_start = ceil(gtk_adjustment_get_value(adj)); const glong page_size = vte_terminal_get_row_count(VTE_TERMINAL(pTab->vte)); termit_for_each_row_execute(pTab, row_start, row_start + page_size, lua_callback); } void termit_tab_set_audible_bell(struct TermitTab* pTab, gboolean audible_bell) { pTab->audible_bell = audible_bell; vte_terminal_set_audible_bell(VTE_TERMINAL(pTab->vte), audible_bell); } void termit_tab_set_pos(struct TermitTab* pTab, int newPos) { gint index = gtk_notebook_get_current_page(GTK_NOTEBOOK(termit.notebook)); gint pagesCnt = gtk_notebook_get_n_pages(GTK_NOTEBOOK(termit.notebook)); if (newPos < 0) { newPos = pagesCnt - 1; } else if (newPos >= pagesCnt) { newPos = 0; } gtk_notebook_reorder_child(GTK_NOTEBOOK(termit.notebook), gtk_notebook_get_nth_page(GTK_NOTEBOOK(termit.notebook), index), newPos); } void termit_append_tab_with_details(const struct TabInfo* ti) { struct TermitTab* pTab = g_malloc0(sizeof(struct TermitTab)); termit_style_copy(&pTab->style, &configs.style); if (ti->name) { pTab->tab_name = gtk_label_new(ti->name); pTab->custom_tab_name = TRUE; } else { gchar* label_text = g_strdup_printf("%s %d", configs.default_tab_name, termit.tab_max_number++); pTab->tab_name = gtk_label_new(label_text); g_free(label_text); pTab->custom_tab_name = FALSE; } if (configs.tab_pos == GTK_POS_RIGHT) { gtk_label_set_angle(GTK_LABEL(pTab->tab_name), 270); } else if (configs.tab_pos == GTK_POS_LEFT) { gtk_label_set_angle(GTK_LABEL(pTab->tab_name), 90); } pTab->encoding = (ti->encoding) ? g_strdup(ti->encoding) : g_strdup(configs.default_encoding); pTab->bksp_binding = ti->bksp_binding; pTab->delete_binding = ti->delete_binding; pTab->cursor_blink_mode = ti->cursor_blink_mode; pTab->cursor_shape = ti->cursor_shape; pTab->hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); pTab->vte = vte_terminal_new(); VteTerminal* vte = VTE_TERMINAL(pTab->vte); vte_terminal_set_size(vte, configs.cols, configs.rows); vte_terminal_set_scrollback_lines(vte, configs.scrollback_lines); vte_terminal_set_scroll_on_output(vte, configs.scroll_on_output); vte_terminal_set_scroll_on_keystroke(vte, configs.scroll_on_keystroke); if (configs.default_word_char_exceptions) { vte_terminal_set_word_char_exceptions(vte, configs.default_word_char_exceptions); } vte_terminal_set_mouse_autohide(vte, TRUE); vte_terminal_set_backspace_binding(vte, pTab->bksp_binding); vte_terminal_set_delete_binding(vte, pTab->delete_binding); vte_terminal_set_cursor_blink_mode(vte, pTab->cursor_blink_mode); vte_terminal_set_cursor_shape(vte, pTab->cursor_shape); vte_terminal_search_set_wrap_around(vte, TRUE); guint l = 0; if (ti->argv == NULL) { l = 1; pTab->argv = (gchar**)g_new0(gchar*, 2); pTab->argv[0] = g_strdup(configs.default_command); } else { while (ti->argv[l] != NULL) { ++l; } pTab->argv = (gchar**)g_new0(gchar*, l + 1); guint i = 0; for (; i < l; ++i) { pTab->argv[i] = g_strdup(ti->argv[i]); } } g_assert(l >= 1); /* parse command */ GError *cmd_err = NULL; if (l == 1) { // arguments may be in one compound string gchar **cmd_argv; if (!g_shell_parse_argv(pTab->argv[0], NULL, &cmd_argv, &cmd_err)) { ERROR("%s", _("Cannot parse command. Creating tab with shell")); g_error_free(cmd_err); return; } g_strfreev(pTab->argv); pTab->argv = cmd_argv; } gchar *cmd_path = NULL; cmd_path = g_find_program_in_path(pTab->argv[0]); if (cmd_path != NULL) { g_free(pTab->argv[0]); pTab->argv[0] = g_strdup(cmd_path); g_free(cmd_path); } if (vte_terminal_spawn_sync(vte, VTE_PTY_DEFAULT, ti->working_dir, pTab->argv, NULL, 0, NULL, NULL, &pTab->pid, NULL, // g_cancellable_new &cmd_err) != TRUE) { ERROR("failed to open tab: %s", cmd_err->message); g_error_free(cmd_err); return; } TRACE("command=%s pid=%d", pTab->argv[0], pTab->pid); g_signal_connect(G_OBJECT(pTab->vte), "bell", G_CALLBACK(termit_on_beep), pTab); g_signal_connect(G_OBJECT(pTab->vte), "focus-in-event", G_CALLBACK(termit_on_focus), pTab); g_signal_connect(G_OBJECT(pTab->vte), "window-title-changed", G_CALLBACK(termit_on_tab_title_changed), NULL); pTab->onChildExitedHandlerId = g_signal_connect(G_OBJECT(pTab->vte), "child-exited", G_CALLBACK(termit_on_child_exited), &termit_close_tab); g_signal_connect_swapped(G_OBJECT(pTab->vte), "button-press-event", G_CALLBACK(termit_on_popup), NULL); if (vte_terminal_set_encoding(vte, pTab->encoding, &cmd_err) != TRUE) { ERROR("cannot set encoding (%s): %s", pTab->encoding, cmd_err->message); g_error_free(cmd_err); return; } pTab->matches = g_array_new(FALSE, TRUE, sizeof(struct Match)); termit_tab_add_matches(pTab, configs.matches); vte_terminal_set_font(vte, pTab->style.font); gint index = gtk_notebook_append_page(GTK_NOTEBOOK(termit.notebook), pTab->hbox, pTab->tab_name); if (index == -1) { ERROR("%s", _("Cannot create a new tab")); return; } if (configs.fill_tabbar) { GValue val = {}; g_value_init(&val, G_TYPE_BOOLEAN); g_value_set_boolean(&val, TRUE); gtk_container_child_set_property(GTK_CONTAINER(termit.notebook), pTab->hbox, "tab-expand", &val); gtk_container_child_set_property(GTK_CONTAINER(termit.notebook), pTab->hbox, "tab-fill", &val); } termit_tab_set_audible_bell(pTab, configs.audible_bell); pTab->scrollbar = gtk_scrollbar_new(GTK_ORIENTATION_VERTICAL, gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(pTab->vte))); gtk_box_pack_start(GTK_BOX(pTab->hbox), pTab->vte, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(pTab->hbox), pTab->scrollbar, FALSE, FALSE, 0); GtkWidget* tabWidget = gtk_notebook_get_nth_page(GTK_NOTEBOOK(termit.notebook), index); if (!tabWidget) { ERROR("tabWidget is NULL"); return; } g_object_set_data(G_OBJECT(tabWidget), TERMIT_TAB_DATA, pTab); if (index == 0) { // there is no "switch-page" signal on the first page termit_set_statusbar_message(index); } pTab->scrollbar_is_shown = configs.show_scrollbar; gtk_widget_show_all(termit.notebook); termit_tab_apply_colors(pTab); gtk_notebook_set_current_page(GTK_NOTEBOOK(termit.notebook), index); gtk_notebook_set_tab_reorderable(GTK_NOTEBOOK(termit.notebook), pTab->hbox, TRUE); gtk_window_set_focus(GTK_WINDOW(termit.main_window), pTab->vte); termit_check_tabbar(); termit_hide_scrollbars(); } void termit_append_tab_with_command(gchar** argv) { struct TabInfo ti = {}; ti.bksp_binding = configs.default_bksp; ti.delete_binding = configs.default_delete; ti.cursor_blink_mode = configs.default_blink; ti.cursor_shape = configs.default_shape; ti.argv = argv; termit_append_tab_with_details(&ti); } void termit_append_tab() { termit_append_tab_with_command(NULL); } void termit_set_encoding(const gchar* encoding) { gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(termit.notebook)); TERMIT_GET_TAB_BY_INDEX(pTab, page, return); TRACE("%s tab=%p page=%d encoding=%s", __FUNCTION__, pTab, page, encoding); if (vte_terminal_set_encoding(VTE_TERMINAL(pTab->vte), encoding, NULL) != TRUE) { ERROR("Cannot set encoding %s", encoding); } else { g_free(pTab->encoding); pTab->encoding = g_strdup(encoding); termit_set_statusbar_message(page); } } void termit_tab_set_title(struct TermitTab* pTab, const gchar* title) { gchar* tmp_title = g_strdup(title); if (configs.get_tab_title_callback) { gchar* lua_title = termit_lua_getTitleCallback(configs.get_tab_title_callback, title); if (!lua_title) { ERROR("termit_lua_getTitleCallback(%s) failed", title); g_free(tmp_title); return; } g_free(tmp_title); tmp_title = lua_title; } if (pTab->title) { g_free(pTab->title); } pTab->title = tmp_title; gtk_label_set_text(GTK_LABEL(pTab->tab_name), pTab->title); termit_set_window_title(title); } void termit_set_default_colors() { gint page_num = gtk_notebook_get_n_pages(GTK_NOTEBOOK(termit.notebook)); gint i=0; for (; ivte)); } } void termit_tab_set_font(struct TermitTab* pTab, const gchar* font_name) { if (pTab->style.font_name) { g_free(pTab->style.font_name); } pTab->style.font_name = g_strdup(font_name); if (pTab->style.font) { pango_font_description_free(pTab->style.font); } pTab->style.font = pango_font_description_from_string(font_name); vte_terminal_set_font(VTE_TERMINAL(pTab->vte), pTab->style.font); } void termit_tab_set_font_by_index(gint tab_index, const gchar* font_name) { TRACE("%s: tab_index=%d font=%s", __FUNCTION__, tab_index, font_name); if (tab_index < 0) { tab_index = gtk_notebook_get_current_page(GTK_NOTEBOOK(termit.notebook)); } TERMIT_GET_TAB_BY_INDEX(pTab, tab_index, return); termit_tab_set_font(pTab, font_name); } static void termit_set_color__(gint tab_index, const GdkRGBA* p_color, void (*callback)(struct TermitTab*, const GdkRGBA*)) { TRACE("%s: tab_index=%d color=%p", __FUNCTION__, tab_index, p_color); if (!p_color) { TRACE_MSG("p_color is NULL"); return; } if (tab_index < 0) { tab_index = gtk_notebook_get_current_page(GTK_NOTEBOOK(termit.notebook)); } TERMIT_GET_TAB_BY_INDEX(pTab, tab_index, return); callback(pTab, p_color); } void termit_tab_set_color_foreground_by_index(gint tab_index, const GdkRGBA* p_color) { termit_set_color__(tab_index, p_color, termit_tab_set_color_foreground); } void termit_tab_set_color_background_by_index(gint tab_index, const GdkRGBA* p_color) { termit_set_color__(tab_index, p_color, termit_tab_set_color_background); } void termit_paste() { gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(termit.notebook)); TERMIT_GET_TAB_BY_INDEX(pTab, page, return); vte_terminal_paste_clipboard(VTE_TERMINAL(pTab->vte)); } void termit_copy() { gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(termit.notebook)); TERMIT_GET_TAB_BY_INDEX(pTab, page, return); vte_terminal_copy_clipboard_format(VTE_TERMINAL(pTab->vte), VTE_FORMAT_TEXT); } static void clipboard_received_text(GtkClipboard *clipboard, const gchar *text, gpointer data) { if (text) { gchar** d = (gchar**)data; *d = g_strdup(text); } } gchar* termit_get_selection() { gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(termit.notebook)); TERMIT_GET_TAB_BY_INDEX(pTab, page, return NULL); if (vte_terminal_get_has_selection(VTE_TERMINAL(pTab->vte)) == FALSE) { return NULL; } GtkClipboard* clip = gtk_clipboard_get(GDK_SELECTION_PRIMARY); gchar* text = NULL; gtk_clipboard_request_text(clip, clipboard_received_text, &text); if (!text) { return NULL; } return text; } void termit_close_tab() { termit_del_tab(); if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(termit.notebook)) == 0) { TRACE("no pages left, exiting"); termit_quit(); } } void termit_activate_tab(gint tab_index) { if (tab_index < 0) { TRACE("tab_index(%d) < 0: skipping", tab_index); return; } if (tab_index >= gtk_notebook_get_n_pages(GTK_NOTEBOOK(termit.notebook))) { TRACE("tab_index(%d) > n_pages: skipping", tab_index); return; } gtk_notebook_set_current_page(GTK_NOTEBOOK(termit.notebook), tab_index); } void termit_prev_tab() { gint index = gtk_notebook_get_current_page(GTK_NOTEBOOK(termit.notebook)); index = (index) ? index - 1 : gtk_notebook_get_n_pages(GTK_NOTEBOOK(termit.notebook)) - 1; termit_activate_tab(index); } void termit_next_tab() { gint index = gtk_notebook_get_current_page(GTK_NOTEBOOK(termit.notebook)); index = (index == gtk_notebook_get_n_pages(GTK_NOTEBOOK(termit.notebook)) - 1) ? 0 : index + 1; termit_activate_tab(index); } void termit_quit() { while (gtk_notebook_get_n_pages(GTK_NOTEBOOK(termit.notebook)) > 0) { termit_del_tab(); } gtk_main_quit(); } int termit_get_current_tab_index() { return gtk_notebook_get_current_page(GTK_NOTEBOOK(termit.notebook)); } void termit_set_kb_policy(enum TermitKbPolicy kbp) { configs.kb_policy = kbp; } void termit_set_window_title(const gchar* title) { if (!title) { return; } if (!configs.get_window_title_callback) { gchar* window_title = g_strdup_printf("%s: %s", configs.default_window_title, title); gtk_window_set_title(GTK_WINDOW(termit.main_window), window_title); g_free(window_title); } else { gchar* window_title = termit_lua_getTitleCallback(configs.get_window_title_callback, title); if (!window_title) { ERROR("termit_lua_getTitleCallback(%s) failed", title); return; } gtk_window_set_title(GTK_WINDOW(termit.main_window), window_title); g_free(window_title); } } void termit_set_show_scrollbar_signal(GtkWidget* menuItem, gpointer pHandlerId) { gulong handlerId = g_signal_connect(G_OBJECT(menuItem), "toggled", G_CALLBACK(termit_on_toggle_scrollbar), NULL); if (pHandlerId == NULL) { pHandlerId = g_malloc(sizeof(handlerId)); } memcpy(pHandlerId, &handlerId, sizeof(handlerId)); g_object_set_data(G_OBJECT(menuItem), "handlerId", pHandlerId); } termit-3.1/src/termit_core_api.h000066400000000000000000000054641362242615500170050ustar00rootroot00000000000000/* Copyright © 2007-2016 Evgeny Ratnikov * * 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 . */ #ifndef TERMIT_CORE_API_H #define TERMIT_CORE_API_H #include "termit.h" #include "configs.h" void termit_reconfigure(); void termit_after_show_all(); void termit_append_tab(); void termit_append_tab_with_command(gchar** argv); void termit_append_tab_with_details(const struct TabInfo*); void termit_activate_tab(gint tab_index); void termit_prev_tab(); void termit_next_tab(); void termit_paste(); void termit_copy(); gchar* termit_get_selection(); void termit_search_find_next(); void termit_search_find_prev(); void termit_for_each_row(int lua_callback); void termit_for_each_visible_row(int lua_callback); void termit_del_tab_n(gint page); void termit_close_tab(); void termit_toggle_menubar(); void termit_toggle_tabbar(); void termit_toggle_search(); void termit_set_window_title(const gchar* title); void termit_set_statusbar_message(guint page); void termit_set_encoding(const gchar* encoding); void termit_quit(); void termit_tab_feed(struct TermitTab* pTab, const gchar* data); void termit_tab_feed_child(struct TermitTab* pTab, const gchar* data); void termit_tab_set_font(struct TermitTab* pTab, const gchar* font_name); void termit_tab_set_font_by_index(gint tab_index, const gchar* font_name); void termit_tab_apply_colors(struct TermitTab* pTab); void termit_tab_set_color_foreground(struct TermitTab* pTab, const GdkRGBA* p_color); void termit_tab_set_color_background(struct TermitTab* pTab, const GdkRGBA* p_color); void termit_tab_set_color_foreground_by_index(gint tab_index, const GdkRGBA*); void termit_tab_set_color_background_by_index(gint tab_index, const GdkRGBA*); void termit_tab_set_title(struct TermitTab* pTab, const gchar* title); void termit_tab_set_audible_bell(struct TermitTab* pTab, gboolean audible_bell); void termit_tab_set_pos(struct TermitTab* pTab, int newPos); int termit_get_current_tab_index(); gchar* termit_get_pid_dir(pid_t pid); /** * function to switch key processing policy * keycodes - kb layout independent * keysyms - kb layout dependent * */ void termit_set_kb_policy(enum TermitKbPolicy kbp); void termit_set_show_scrollbar_signal(GtkWidget* menuItem, gpointer pHanderId); #endif /* TERMIT_CORE_API_H */ termit-3.1/src/termit_preferences.c000066400000000000000000000222051362242615500175100ustar00rootroot00000000000000/* Copyright © 2007-2016 Evgeny Ratnikov * * 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 . */ #include #include #include #include #include "termit.h" #include "termit_style.h" #include "termit_core_api.h" static gboolean dlg_key_press(GtkWidget *widget, GdkEventKey *event, gpointer user_data) { switch (event->keyval) { case GDK_KEY_Return: g_signal_emit_by_name(widget, "response", GTK_RESPONSE_ACCEPT, NULL); break; case GDK_KEY_Escape: g_signal_emit_by_name(widget, "response", GTK_RESPONSE_REJECT, NULL); break; default: return FALSE; } return TRUE; } static void dlg_set_tab_color__(GtkColorButton *widget, gpointer user_data, void (*callback)(struct TermitTab*, const GdkRGBA*)) { if (!user_data) { ERROR("user_data is NULL"); return; } struct TermitTab* pTab = (struct TermitTab*)user_data; GdkRGBA color = {}; gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(widget), &color); callback(pTab, &color); } static void dlg_set_foreground(GtkColorButton *widget, gpointer user_data) { return dlg_set_tab_color__(widget, user_data, termit_tab_set_color_foreground); } static void dlg_set_background(GtkColorButton *widget, gpointer user_data) { return dlg_set_tab_color__(widget, user_data, termit_tab_set_color_background); } static void dlg_set_font(GtkFontChooser *widget, gpointer user_data) { if (!user_data) { ERROR("user_data is NULL"); return; } struct TermitTab* pTab = (struct TermitTab*)user_data; termit_tab_set_font(pTab, gtk_font_chooser_get_font(widget)); } static gboolean dlg_set_audible_bell(GtkToggleButton *btn, gpointer user_data) { if (!user_data) { ERROR("user_data is NULL"); return FALSE; } struct TermitTab* pTab = (struct TermitTab*)user_data; gboolean value = gtk_toggle_button_get_active(btn); termit_tab_set_audible_bell(pTab, value); return FALSE; } static gboolean dlg_set_apply_to_all_tabs(GtkToggleButton *btn, gpointer user_data) { if (!user_data) { ERROR("user_data is NULL"); return FALSE; } gboolean* flag = (gboolean*)user_data; *flag = gtk_toggle_button_get_active(btn); return FALSE; } struct TermitDlgHelper { struct TermitTab* pTab; gchar* tab_title; gboolean handmade_tab_title; struct TermitStyle style; gboolean au_bell; // widgets with values GtkWidget* dialog; GtkWidget* entry_title; GtkWidget* btn_font; GtkWidget* btn_foreground; GtkWidget* btn_background; GtkWidget* btn_audible_bell; GtkWidget* btn_apply_to_all_tabs; }; static struct TermitDlgHelper* termit_dlg_helper_new(struct TermitTab* pTab) { struct TermitDlgHelper* hlp = g_malloc0(sizeof(struct TermitDlgHelper)); hlp->pTab = pTab; if (pTab->title) { hlp->handmade_tab_title = TRUE; hlp->tab_title = g_strdup(pTab->title); } else { hlp->tab_title = g_strdup(gtk_label_get_text(GTK_LABEL(pTab->tab_name))); } termit_style_copy(&hlp->style, &pTab->style); hlp->au_bell = pTab->audible_bell; return hlp; } static void termit_dlg_helper_free(struct TermitDlgHelper* hlp) { g_free(hlp->tab_title); termit_style_free(&hlp->style); g_free(hlp); } static void dlg_set_tab_default_values(struct TermitTab* pTab, struct TermitDlgHelper* hlp) { if (hlp->tab_title) { termit_tab_set_title(pTab, hlp->tab_title); } termit_style_free(&pTab->style); termit_style_copy(&pTab->style, &hlp->style); termit_tab_apply_colors(pTab); termit_tab_set_font(pTab, hlp->style.font_name); termit_tab_set_audible_bell(pTab, hlp->au_bell); } static void dlg_set_default_values(struct TermitDlgHelper* hlp) { gtk_entry_set_text(GTK_ENTRY(hlp->entry_title), hlp->tab_title); gtk_font_chooser_set_font(GTK_FONT_CHOOSER(hlp->btn_font), hlp->style.font_name); if (hlp->style.foreground_color) { gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(hlp->btn_foreground), hlp->style.foreground_color); } if (hlp->style.background_color) { gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(hlp->btn_background), hlp->style.background_color); } gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(hlp->btn_audible_bell), hlp->au_bell); } static void dlg_restore_defaults(GtkButton *button, gpointer user_data) { struct TermitDlgHelper* hlp = (struct TermitDlgHelper*)user_data; dlg_set_default_values(hlp); dlg_set_tab_default_values(hlp->pTab, hlp); } void termit_preferences_dialog(struct TermitTab *pTab) { // store font_name, foreground, background struct TermitDlgHelper* hlp = termit_dlg_helper_new(pTab); GtkWidget* dialog = gtk_dialog_new_with_buttons(_("Preferences"), GTK_WINDOW(termit.main_window), GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL, "_Cancel", GTK_RESPONSE_REJECT, "_Apply", GTK_RESPONSE_ACCEPT, NULL); g_signal_connect(G_OBJECT(dialog), "key-press-event", G_CALLBACK(dlg_key_press), dialog); GtkWidget* grid = gtk_grid_new(); #define TERMIT_PREFERENCE_ROW(pref_name, widget) \ gtk_grid_attach(GTK_GRID(grid), gtk_label_new(pref_name), 0, row, 1, 1); \ gtk_grid_attach(GTK_GRID(grid), widget, 1, row, 1, 1); \ hlp->widget = widget; \ row++; gboolean apply_to_all_tabs_flag = FALSE; GtkWidget* entry_title = gtk_entry_new(); guint row = 0; { // tab title gtk_entry_set_text(GTK_ENTRY(entry_title), hlp->tab_title); TERMIT_PREFERENCE_ROW(_("Title"), entry_title); } // font selection GtkWidget* btn_font = gtk_font_button_new_with_font(pTab->style.font_name); g_signal_connect(btn_font, "font-set", G_CALLBACK(dlg_set_font), pTab); TERMIT_PREFERENCE_ROW(_("Font"), btn_font); // foreground GtkWidget* btn_foreground = (pTab->style.foreground_color) ? gtk_color_button_new_with_rgba(pTab->style.foreground_color) : gtk_color_button_new(); g_signal_connect(btn_foreground, "color-set", G_CALLBACK(dlg_set_foreground), pTab); TERMIT_PREFERENCE_ROW(_("Foreground"), btn_foreground); // background GtkWidget* btn_background = (pTab->style.background_color) ? gtk_color_button_new_with_rgba(pTab->style.background_color) : gtk_color_button_new(); g_signal_connect(btn_background, "color-set", G_CALLBACK(dlg_set_background), pTab); TERMIT_PREFERENCE_ROW(_("Background"), btn_background); // audible_bell GtkWidget* btn_audible_bell = gtk_check_button_new(); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(btn_audible_bell), pTab->audible_bell); g_signal_connect(btn_audible_bell, "toggled", G_CALLBACK(dlg_set_audible_bell), pTab); TERMIT_PREFERENCE_ROW(_("audible bell"), btn_audible_bell); // apply to al tabs GtkWidget* btn_apply_to_all_tabs = gtk_check_button_new(); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(btn_apply_to_all_tabs), FALSE); g_signal_connect(btn_apply_to_all_tabs, "toggled", G_CALLBACK(dlg_set_apply_to_all_tabs), &apply_to_all_tabs_flag); TERMIT_PREFERENCE_ROW(_("Apply to all tabs"), btn_apply_to_all_tabs); GtkWidget* btn_restore = gtk_button_new_from_icon_name("document-revert", GTK_ICON_SIZE_BUTTON); g_signal_connect(G_OBJECT(btn_restore), "clicked", G_CALLBACK(dlg_restore_defaults), hlp); gtk_grid_attach(GTK_GRID(grid), btn_restore, 0, row, 2, 1); gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), grid); gtk_widget_show_all(dialog); if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) { dlg_set_tab_default_values(pTab, hlp); } else { if (apply_to_all_tabs_flag) { gint page_num = gtk_notebook_get_n_pages(GTK_NOTEBOOK(termit.notebook)); gint i=0; for (; ititle || (!pTab->title && strcmp(gtk_label_get_text(GTK_LABEL(pTab->tab_name)), gtk_entry_get_text(GTK_ENTRY(entry_title))) != 0)) { termit_tab_set_title(pTab, gtk_entry_get_text(GTK_ENTRY(entry_title))); } } termit_dlg_helper_free(hlp); gtk_widget_destroy(dialog); } termit-3.1/src/termit_style.c000066400000000000000000000043361362242615500163540ustar00rootroot00000000000000/* Copyright © 2007-2016 Evgeny Ratnikov * * 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 . */ #include #include #include #include "termit_style.h" void termit_style_init(struct TermitStyle* style) { style->font_name = g_strdup("Monospace 10"); style->font = pango_font_description_from_string(style->font_name); style->foreground_color = NULL; style->background_color = NULL; style->colors = NULL; style->colors_size = 0; } void termit_style_free(struct TermitStyle* style) { g_free(style->font_name); pango_font_description_free(style->font); if (style->colors) { g_free(style->colors); } if (style->background_color) { gdk_rgba_free(style->background_color); } if (style->foreground_color) { gdk_rgba_free(style->foreground_color); } struct TermitStyle tmp = {}; *style = tmp; } void termit_style_copy(struct TermitStyle* dest, const struct TermitStyle* src) { dest->font_name = g_strdup(src->font_name); dest->font = pango_font_description_from_string(src->font_name); if (src->background_color) { dest->background_color = gdk_rgba_copy(src->background_color); } else { dest->background_color = NULL; } if (src->foreground_color) { dest->foreground_color = gdk_rgba_copy(src->foreground_color); } else { dest->foreground_color = NULL; } if (src->colors_size) { dest->colors = g_memdup(src->colors, src->colors_size * sizeof(GdkRGBA)); dest->colors_size = src->colors_size; } else { dest->colors = NULL; dest->colors_size = 0; } } termit-3.1/src/termit_style.h000066400000000000000000000022641362242615500163570ustar00rootroot00000000000000/* Copyright © 2007-2016 Evgeny Ratnikov * * 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 . */ #ifndef TERMIT_STYLE_H #define TERMIT_STYLE_H #include #include #include struct TermitStyle { gchar* font_name; PangoFontDescription* font; GdkRGBA* foreground_color; GdkRGBA* background_color; GdkRGBA* colors; glong colors_size; }; void termit_style_init(struct TermitStyle* style); void termit_style_copy(struct TermitStyle* dest, const struct TermitStyle* src); void termit_style_free(struct TermitStyle* style); #endif /* TERMIT_STYLE_H */ termit-3.1/utils/000077500000000000000000000000001362242615500140275ustar00rootroot00000000000000termit-3.1/utils/CMakeLists.txt000066400000000000000000000015601362242615500165710ustar00rootroot00000000000000# Copyright © 2007-2016 Evgeny Ratnikov # # 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 . # Slackware SlackBuild CONFIGURE_FILE(termit.SlackBuild.in ${TERMIT_SOURCE_DIR}/utils/termit.SlackBuild @ONLY) # Fedora spec CONFIGURE_FILE(termit.spec.in ${TERMIT_SOURCE_DIR}/utils/termit.spec @ONLY) termit-3.1/utils/slack-desc000066400000000000000000000005531362242615500157660ustar00rootroot00000000000000 |-----handy-ruler------------------------------------------------------| termit: termit (terminal emulator) termit: termit: Small terminal emulator configurable via Lua. termit: Other dependencies are Vte and Gtk2 libs. termit: Termit supports multiple tabs, encoding switching and sessions. termit: termit: http://wiki.github.com/nonstop/termit/ termit: termit-3.1/utils/termit.SlackBuild.in000066400000000000000000000032041362242615500176760ustar00rootroot00000000000000#!/bin/sh # Slackware build script for termit # Written by Evgeny Ratnikov (ratnikov dot ev at gmail dot com) PRGNAM=termit VERSION=${VERSION:-"@TERMIT_PACKAGE_VERSION@"} ARCH=${ARCH:-i686} BUILD=${BUILD:-1} TAG=${TAG:-_SBo} CWD=$(pwd) TMP=${TMP:-/tmp/$TAG} PKG=$TMP/package-$PRGNAM OUTPUT=${OUTPUT:-/tmp} if [ "$ARCH" = "i486" ]; then SLKCFLAGS="-O2 -march=i486 -mtune=i686" elif [ "$ARCH" = "i686" ]; then SLKCFLAGS="-O2 -march=i686 -mtune=i686" elif [ "$ARCH" = "x86_64" ]; then SLKCFLAGS="-O2 -fPIC" fi set -e rm -rf $PKG mkdir -p $TMP $PKG $OUTPUT cd $TMP rm -rf $PRGNAM-$VERSION tar xvf $CWD/$PRGNAM-$VERSION.tar.bz2 cd $PRGNAM-$VERSION find . \ \( -perm 777 -o -perm 775 -o -perm 711 -o -perm 555 -o -perm 511 \) \ -exec chmod 755 {} \; -o \ \( -perm 666 -o -perm 664 -o -perm 600 -o -perm 444 -o -perm 440 -o -perm 400 \) \ -exec chmod 644 {} \; CFLAGS="$SLKCFLAGS" CXXFLAGS="$SLKCFLAGS" cmake -DCMAKE_INSTALL_PREFIX=/usr . make make install DESTDIR=$PKG ( cd $PKG find . | xargs file | grep "executable" | grep ELF | cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null || true find . | xargs file | grep "shared object" | grep ELF | cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null || true ) mkdir -p $PKG/usr/doc/$PRGNAM-$VERSION cp -a ChangeLog INSTALL COPYING TODO $PKG/usr/doc/$PRGNAM-$VERSION cat $CWD/$PRGNAM.SlackBuild > $PKG/usr/doc/$PRGNAM-$VERSION/$PRGNAM.SlackBuild cat $CWD/slack-desc > $PKG/usr/doc/$PRGNAM-$VERSION/$PRGNAM.slack-desc mkdir -p $PKG/install cat $CWD/slack-desc > $PKG/install/slack-desc cd $PKG chown -R root:root . /sbin/makepkg -l y -c n $OUTPUT/$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.tgz termit-3.1/utils/termit.ebuild000066400000000000000000000015611362242615500165240ustar00rootroot00000000000000# Copyright 1999-2008 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # $Header: $ EAPI=2 CMAKE_MIN_VERSION="2.6.1" inherit cmake-utils SRC_URI="https://github.com/nonstop/${PN}/archive/${PV}.tar.gz -> ${P}.tar.gz" HOMEPAGE="http://wiki.github.com/nonstop/termit/" DESCRIPTION="Simple terminal emulator based on vte library with Lua scripting." RDEPEND=">=x11-libs/vte-0.42.5 >=x11-libs/gtk+-3.18 >=dev-lang/lua-5.2" DEPEND="${RDEPEND}" SLOT="0" LICENSE="GPL-3" KEYWORDS="~x86 ~amd64" IUSE="" DOCS="INSTALL ChangeLog doc/README doc/rc.lua.example doc/lua_api.txt" CMAKE_IN_SOURCE_BUILD="yes" pkg_postinst() { einfo einfo "There is a example of configfile in " einfo " /usr/share/doc/termit/rc.lua.example " einfo "Copy this file to " einfo " \$HOME/.config/termit/rc.lua" einfo "and modify to fit your needs." einfo } termit-3.1/utils/termit.spec.in000066400000000000000000000027611362242615500166220ustar00rootroot00000000000000Summary: termit (terminal emulator) Name: termit Version: @TERMIT_PACKAGE_VERSION@ Release: 1%{?dist} License: GPLv3 URL: http://wiki.github.com/nonstop/termit/ Group: System Environment/Base Source: %{name}-%{version}.tar.bz2 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: gtk3-devel >= 3.18 BuildRequires: vte-devel >= 0.42.5 BuildRequires: lua-devel >= 5.2 BuildRequires: cmake desktop-file-utils gettext %description Small terminal emulator. The only dependencies are Vte and Gtk3 libs. Termit supports tabs, bookmarks, encoding switching and sessions. %prep %setup -q %build find . -type f -name CMakeCache.txt -exec rm -rf {} \; %cmake DCMAKE_INSTALL_DOCDIR=%{_docdir} . make VERBOSE=1 %{?_smp_mflags} %install rm -rf $RPM_BUILD_ROOT make install DESTDIR=$RPM_BUILD_ROOT desktop-file-install \ --delete-original \ --remove-category=Utility \ --add-category=System \ --dir=${RPM_BUILD_ROOT}%{_datadir}/applications \ ${RPM_BUILD_ROOT}%{_datadir}/applications/%{name}.desktop %find_lang %{name} rm -rf ${RPM_BUILD_ROOT}%{_datadir}/doc/termit/ %clean rm -rf $RPM_BUILD_ROOT %files -f %{name}.lang %defattr(-,root,root,-) %doc ChangeLog COPYING TODO %doc doc/README doc/rc.lua.example doc/lua_api.txt doc/termit.svg %{_bindir}/%{name} %{_datadir}/applications/%{name}.desktop %{_mandir}/man1/%{name}.1.*