screen-4.1.0/0000755000175000017500000000000011732171240011031 5ustar abeabescreen-4.1.0/COPYING0000644000175000017500000010451311642704565012104 0ustar abeabe 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 . screen-4.1.0/configure.in0000644000175000017500000007403211720315605013352 0ustar abeabednl Process this file with autoconf to produce a configure script. dnl dnl $Id$ GNU dnl dnl Many thanks to David MacKenzie for writing autoconf and dnl providing a sample configure.in file for screen. dnl AC_REVISION($Revision$)dnl AC_INIT(screen.c) AC_CONFIG_HEADER(config.h) dnl dnl Define some useful macros dnl AC_DEFUN([AC_PROGRAM_SOURCE], [AC_REQUIRE([AC_PROG_CPP])AC_PROVIDE([$0])cat > conftest.c <&5 | sed -e '1,/_CUT_HERE_/d' -e 's/ //g' > conftest.out" . ./conftest.out rm -f conftest* ])dnl dnl define(AC_NOTE, [echo "$1" 1>&AC_FD_MSG ])dnl dnl dnl Extract version from patchlevel.h dnl rev=`sed < ${srcdir}/patchlevel.h -n -e '/#define REV/s/#define REV *//p'` vers=`sed < ${srcdir}/patchlevel.h -n -e '/#define VERS/s/#define VERS *//p'` pat=`sed < ${srcdir}/patchlevel.h -n -e '/#define PATCHLEVEL/s/#define PATCHLEVEL *//p'` VERSION="$rev.$vers.$pat" AC_NOTE(this is screen version $VERSION) AC_SUBST(VERSION) AC_PREFIX_PROGRAM(screen) AC_PREFIX_PROGRAM(gzip) old_CFLAGS="$CFLAGS" AC_PROG_CC AC_PROG_CPP AC_PROG_GCC_TRADITIONAL AC_ISC_POSIX AC_USE_SYSTEM_EXTENSIONS AC_TRY_RUN(main(){exit(0);},,[ if test $CC != cc ; then AC_NOTE(Your $CC failed - restarting with CC=cc) AC_NOTE() CC=cc export CC exec $0 $configure_args fi ]) AC_TRY_RUN(main(){exit(0);},, exec 5>&2 eval $ac_link AC_NOTE(CC=$CC; CFLAGS=$CFLAGS; LIBS=$LIBS;) AC_NOTE($ac_compile) AC_MSG_ERROR(Can't run the compiler - sorry)) AC_TRY_RUN([ main() { int __something_strange_(); __something_strange_(0); } ],AC_MSG_ERROR(Your compiler does not set the exit status - sorry)) AC_PROG_AWK AC_PROG_INSTALL if test -f etc/toolcheck; then AC_CHECKING(for buggy tools) sh etc/toolcheck 1>&AC_FD_MSG fi dnl SOCKDIR AC_MSG_CHECKING(if a system-wide socket dir should be used) AC_ARG_ENABLE(socket-dir, [ --disable-socket-dir disable system wide socket-dir and use ~/.screen instead], [ AC_MSG_RESULT(no. ~/.screen will be used instead.) ], [ AC_MSG_RESULT(yes) AC_MSG_CHECKING(for the socket dir) SOCKDIR="(eff_uid ? \"/tmp/uscreens\" : \"/tmp/screens\")" AC_ARG_WITH(socket-dir, [ --with-socket-dir=path where to put the per-user sockets], [ case "${withval}" in *\"*) SOCKDIR="${withval}" ;; *) SOCKDIR="\"${withval}\"" ;; esac ]) AC_MSG_RESULT(${SOCKDIR}) AC_DEFINE_UNQUOTED(SOCKDIR, $SOCKDIR) ] ) dnl dnl **** special unix variants **** dnl if test -n "$ISC"; then AC_DEFINE(ISC) LIBS="$LIBS -linet" fi dnl AC_CHECKING(for OSF1) dnl if test -f /bin/uname ; then dnl if test `/bin/uname` = OSF1 || test -f /osf_boot; then dnl AC_DEFINE(OSF1) # this disables MIPS again.... dnl fi dnl fi if test -f /sysV68 ; then AC_DEFINE(sysV68) fi AC_CHECKING(for MIPS) if test -f /lib/libmld.a || test -f /usr/lib/libmld.a || test -f /usr/lib/cmplrs/cc/libmld.a; then oldlibs="$LIBS" test -f /bin/mx || LIBS="$LIBS -lmld" # for nlist. But not on alpha. dnl djm@eng.umd.edu: "... for one thing, it doubles the size of the executable" AC_CHECKING(mld library) AC_TRY_LINK(,,,LIBS="$oldlibs") dnl dnl if test -r /dev/ptc; then AC_DEFINE(MIPS) AC_CHECKING(wait3) AC_TRY_LINK(,[wait3();], , AC_CHECKING(wait2) AC_TRY_LINK(,[wait2();], dnl John Rouillard (rouilj@sni-usa.com): dnl need -I/usr/include/bsd in RISCOS otherwise sockets are broken, no dnl job control etc. dnl Detect RISCOS if wait2 is present, but not wait3. AC_DEFINE(USE_WAIT2) LIBS="$LIBS -lbsd" ; CC="$CC -I/usr/include/bsd" )) fi fi AC_CHECKING(for Ultrix) AC_EGREP_CPP(yes, [#if defined(ultrix) || defined(__ultrix) yes; #endif ], ULTRIX=1) if test -f /usr/lib/libpyr.a ; then oldlibs="$LIBS" LIBS="$LIBS -lpyr" AC_CHECKING(Pyramid OSX) AC_TRY_LINK(,[open_controlling_pty("")], AC_DEFINE(OSX), LIBS="$oldlibs") fi dnl ghazi@caip.rutgers.edu (Kaveh R. Ghazi): dnl BBN butterfly is not POSIX, but a MACH BSD system. dnl Do not define POSIX and TERMIO. AC_CHECKING(for butterfly) AC_EGREP_CPP(yes, [#if defined(butterfly) yes; #endif ], butterfly=1) if test -z "$butterfly"; then if test -n "$ULTRIX"; then test -z "$GCC" && CC="$CC -YBSD" fi AC_CHECKING(for POSIX.1) AC_EGREP_CPP(yes, [#include #include main () { #ifdef _POSIX_VERSION yes; #endif ], AC_NOTE(- you have a POSIX system) AC_DEFINE(POSIX) posix=1) fi AC_CHECKING(for System V) AC_TRY_COMPILE( [#include #include #include ], [int x = SIGCHLD | FNDELAY;], , AC_DEFINE(SYSV)) AC_CHECKING(for sequent/ptx) AC_EGREP_CPP(yes, [#ifdef _SEQUENT_ yes; #endif ], LIBS="$LIBS -lsocket -linet";seqptx=1) oldlibs="$LIBS" LIBS="$LIBS -lelf" AC_CHECKING(SVR4) AC_TRY_LINK([#include ],, [AC_CHECK_HEADER(dwarf.h, AC_DEFINE(SVR4) AC_DEFINE(BUGGYGETLOGIN), [AC_CHECK_HEADER(elf.h, AC_DEFINE(SVR4) AC_DEFINE(BUGGYGETLOGIN))])] ,LIBS="$oldlibs") AC_CHECK_HEADERS([stropts.h string.h strings.h]) AC_CHECKING(for Solaris 2.x) AC_EGREP_CPP(yes, [#if defined(SVR4) && defined(sun) yes #endif ], LIBS="$LIBS -lsocket -lnsl -lkstat") dnl dnl **** typedefs **** dnl dnl (currently not used) dnl dnl AC_CHECKING(for pid_t) dnl AC_EGREP_CPP(pid_t,[#include dnl ],AC_DEFINE(PID_T_DEFINED)) dnl dnl AC_CHECKING(for sig_t) dnl AC_EGREP_CPP(sig_t,[#include dnl #include dnl ],AC_DEFINE(SIG_T_DEFINED)) dnl dnl AC_CHECKING(for uid_t) dnl AC_EGREP_CPP(uid_t,[#include dnl ],AC_DEFINE(UID_T_DEFINED)) dnl dnl dnl **** Job control **** dnl AC_CHECKING(BSD job jontrol) AC_TRY_LINK( [#include #include ], [ #ifdef POSIX tcsetpgrp(0, 0); #else int x = TIOCSPGRP; #ifdef SYSV setpgrp(); #else int y = TIOCNOTTY; #endif #endif ], AC_NOTE(- you have jobcontrol) AC_DEFINE(BSDJOBS), AC_NOTE(- you don't have jobcontrol)) dnl dnl **** setresuid(), setreuid(), seteuid() **** dnl AC_CHECKING(setresuid) AC_TRY_LINK(,[ setresuid(0, 0, 0); ], AC_DEFINE(HAVE_SETRESUID)) AC_CHECKING(setreuid) AC_TRY_LINK(,[ setreuid(0, 0); ], AC_DEFINE(HAVE_SETREUID)) dnl dnl seteuid() check: dnl linux seteuid was broken before V1.1.11 dnl NeXT, AUX, ISC, and ultrix are still broken (no saved uid support) dnl Solaris seteuid doesn't change the saved uid, bad for dnl multiuser screen sessions AC_CHECKING(seteuid) AC_TRY_LINK(,[ #if defined(linux) || defined(NeXT) || defined(_AUX_SOURCE) || defined(AUX) || defined(ultrix) || (defined(sun) && defined(SVR4)) || defined(ISC) || defined(sony_news) seteuid_is_broken(0); #else seteuid(0); #endif ], AC_DEFINE(HAVE_SETEUID)) dnl execvpe AC_CHECKING(execvpe) AC_TRY_LINK(,[ execvpe(0, 0, 0); ], AC_DEFINE(HAVE_EXECVPE) CFLAGS="$CFLAGS -D_GNU_SOURCE") dnl dnl **** select() **** dnl AC_CHECKING(select) AC_TRY_LINK(,[select(0, 0, 0, 0, 0);],, LIBS="$LIBS -lnet -lnsl" AC_CHECKING(select with $LIBS) AC_TRY_LINK(,[select(0, 0, 0, 0, 0);],, AC_MSG_ERROR(!!! no select - no screen)) ) dnl dnl **** FIFO tests **** dnl AC_CHECKING(fifos) AC_TRY_RUN([ /* For select - According to POSIX 1003.1-2001 */ #include /* For select - According to earlier standards */ #include #include #include #include #include #ifndef O_NONBLOCK #define O_NONBLOCK O_NDELAY #endif #ifndef S_IFIFO #define S_IFIFO 0010000 #endif char *fin = "/tmp/conftest$$"; main() { struct stat stb; fd_set f; (void)alarm(5); unlink(fin); #ifdef POSIX if (mkfifo(fin, 0777)) #else if (mknod(fin, S_IFIFO|0777, 0)) #endif exit(1); if (stat(fin, &stb) || (stb.st_mode & S_IFIFO) != S_IFIFO) exit(1); close(0); #ifdef __386BSD__ /* * The next test fails under 386BSD, but screen works using fifos. * Fifos in O_RDWR mode are only used for the BROKEN_PIPE case and for * the select() configuration test. */ exit(0); #endif if (open(fin, O_RDONLY | O_NONBLOCK)) exit(1); if (fork() == 0) { close(0); if (open(fin, O_WRONLY | O_NONBLOCK)) exit(1); close(0); if (open(fin, O_WRONLY | O_NONBLOCK)) exit(1); if (write(0, "TEST", 4) == -1) exit(1); exit(0); } FD_SET(0, &f); if (select(1, &f, 0, 0, 0) == -1) exit(1); exit(0); } ], AC_NOTE(- your fifos are usable) fifo=1, AC_NOTE(- your fifos are not usable)) rm -f /tmp/conftest* if test -n "$fifo"; then AC_CHECKING(for broken fifo implementation) AC_TRY_RUN([ /* For select - According to POSIX 1003.1-2001 */ #include /* For select - According to earlier standards */ #include #include #include #include #include #ifndef O_NONBLOCK #define O_NONBLOCK O_NDELAY #endif #ifndef S_IFIFO #define S_IFIFO 0010000 #endif char *fin = "/tmp/conftest$$"; main() { struct timeval tv; fd_set f; #ifdef POSIX if (mkfifo(fin, 0600)) #else if (mknod(fin, S_IFIFO|0600, 0)) #endif exit(1); close(0); if (open(fin, O_RDONLY|O_NONBLOCK)) exit(1); FD_SET(0, &f); tv.tv_sec = 1; tv.tv_usec = 0; if (select(1, &f, 0, 0, &tv)) exit(1); exit(0); } ], AC_NOTE(- your implementation is ok), AC_NOTE(- you have a broken implementation) AC_DEFINE(BROKEN_PIPE) fifobr=1) rm -f /tmp/conftest* fi dnl dnl **** SOCKET tests **** dnl dnl may need LIBS="$LIBS -lsocket" here dnl AC_CHECKING(sockets) AC_TRY_RUN([ /* For select - According to POSIX 1003.1-2001 */ #include /* For select - According to earlier standards */ #include #include #include #include #include #include #include char *son = "/tmp/conftest$$"; main() { int s1, s2, l; struct sockaddr_un a; fd_set f; (void)alarm(5); if ((s1 = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) exit(1); a.sun_family = AF_UNIX; strcpy(a.sun_path, son); (void) unlink(son); if (bind(s1, (struct sockaddr *) &a, strlen(son)+2) == -1) exit(1); if (listen(s1, 2)) exit(1); if (fork() == 0) { if ((s2 = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) kill(getppid(), 3); (void)connect(s2, (struct sockaddr *)&a, strlen(son) + 2); if (write(s2, "HELLO", 5) == -1) kill(getppid(), 3); exit(0); } l = sizeof(a); close(0); if (accept(s1, &a, &l)) exit(1); FD_SET(0, &f); if (select(1, &f, 0, 0, 0) == -1) exit(1); exit(0); } ], AC_NOTE(- your sockets are usable) sock=1, AC_NOTE(- your sockets are not usable)) rm -f /tmp/conftest* if test -n "$sock"; then AC_CHECKING(socket implementation) AC_TRY_RUN([ /* For select - According to POSIX 1003.1-2001 */ #include /* For select - According to earlier standards */ #include #include #include #include #include #include char *son = "/tmp/conftest$$"; main() { int s; struct stat stb; struct sockaddr_un a; if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) exit(0); a.sun_family = AF_UNIX; strcpy(a.sun_path, son); (void) unlink(son); if (bind(s, (struct sockaddr *) &a, strlen(son)+2) == -1) exit(0); if (stat(son, &stb)) exit(1); close(s); exit(0); } ],AC_NOTE(- you are normal), AC_NOTE(- unix domain sockets are not kept in the filesystem) AC_DEFINE(SOCK_NOT_IN_FS) socknofs=1) rm -f /tmp/conftest* fi dnl dnl **** choose sockets or fifos **** dnl if test -n "$fifo"; then if test -n "$sock"; then if test -n "$nore"; then AC_NOTE(- hmmm... better take the fifos) AC_DEFINE(NAMEDPIPE) elif test -n "$fifobr"; then AC_NOTE(- as your fifos are broken lets use the sockets.) else AC_NOTE(- both sockets and fifos usable. let's take sockets.) fi else AC_NOTE(- using named pipes, of course) AC_DEFINE(NAMEDPIPE) fi elif test -n "$sock"; then AC_NOTE(- using unix-domain sockets, of course) else AC_MSG_ERROR(you have neither usable sockets nor usable pipes -> no screen) fi dnl dnl **** check the select implementation **** dnl AC_CHECKING(select return value) AC_TRY_RUN([ /* For select - According to POSIX 1003.1-2001 */ #include /* For select - According to earlier standards */ #include #include #include #include #include char *nam = "/tmp/conftest$$"; #ifdef NAMEDPIPE #ifndef O_NONBLOCK #define O_NONBLOCK O_NDELAY #endif #ifndef S_IFIFO #define S_IFIFO 0010000 #endif main() { fd_set f; #ifdef __FreeBSD__ /* From Andrew A. Chernov (ache@astral.msk.su): * opening RDWR fifo fails in BSD 4.4, but select return values are * right. */ exit(0); #endif (void)alarm(5); #ifdef POSIX if (mkfifo(nam, 0777)) #else if (mknod(nam, S_IFIFO|0777, 0)) #endif exit(1); close(0); if (open(nam, O_RDWR | O_NONBLOCK)) exit(1); if (write(0, "TEST", 4) == -1) exit(1); #else #include #include #include main() { int s1, s2, l; struct sockaddr_un a; fd_set f; (void)alarm(5); if ((s1 = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) exit(1); a.sun_family = AF_UNIX; strcpy(a.sun_path, nam); (void) unlink(nam); if (bind(s1, (struct sockaddr *) &a, strlen(nam)+2) == -1) exit(1); if (listen(s1, 2)) exit(1); if (fork() == 0) { if ((s2 = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) kill(getppid(), 3); (void)connect(s2, (struct sockaddr *)&a, strlen(nam) + 2); if (write(s2, "HELLO", 5) == -1) kill(getppid(), 3); exit(0); } l = sizeof(a); close(0); if (accept(s1, (struct sockaddr *)&a, &l)) exit(1); #endif FD_SET(0, &f); if (select(1, &f, 0, 0, 0) == -1) exit(1); if (select(1, &f, &f, 0, 0) != 2) exit(1); exit(0); } ],AC_NOTE(- select is ok), AC_NOTE(- select can't count) AC_DEFINE(SELECT_BROKEN)) dnl dnl **** termcap or terminfo **** dnl AC_CHECKING(for tgetent) AC_TRY_LINK(,tgetent((char *)0, (char *)0);,, olibs="$LIBS" LIBS="-lcurses $olibs" AC_CHECKING(libcurses) AC_TRY_LINK(,[ #ifdef __hpux __sorry_hpux_libcurses_is_totally_broken_in_10_10(); #else tgetent((char *)0, (char *)0); #endif ],, LIBS="-ltermcap $olibs" AC_CHECKING(libtermcap) AC_TRY_LINK(,tgetent((char *)0, (char *)0);,, LIBS="-ltermlib $olibs" AC_CHECKING(libtermlib) AC_TRY_LINK(,tgetent((char *)0, (char *)0);,, LIBS="-lncursesw $olibs" AC_CHECKING(libncursesw) AC_TRY_LINK(,tgetent((char *)0, (char *)0);,, LIBS="-lncurses $olibs" AC_CHECKING(libncurses) AC_TRY_LINK(,tgetent((char *)0, (char *)0);,, AC_MSG_ERROR(!!! no tgetent - no screen))))))) AC_TRY_RUN([ main() { exit(strcmp(tgoto("%p1%d", 0, 1), "1") ? 0 : 1); }], AC_NOTE(- you use the termcap database), AC_NOTE(- you use the terminfo database) AC_DEFINE(TERMINFO)) AC_CHECKING(ospeed) AC_TRY_LINK(extern short ospeed;,ospeed=5;,,AC_DEFINE(NEED_OSPEED)) dnl dnl **** PTY specific things **** dnl AC_CHECKING(for /dev/ptc) if test -r /dev/ptc; then AC_DEFINE(HAVE_DEV_PTC) fi AC_CHECKING(for SVR4 ptys) sysvr4ptys= if test -c /dev/ptmx ; then AC_TRY_LINK([],[ptsname(0);grantpt(0);unlockpt(0);],[AC_DEFINE(HAVE_SVR4_PTYS) sysvr4ptys=1]) fi AC_CHECK_FUNCS(getpt) dnl check for openpty() if test -z "$sysvr4ptys"; then AC_CHECK_FUNCS(openpty,, [AC_CHECK_LIB(util,openpty, [AC_DEFINE(HAVE_OPENPTY)] [LIBS="$LIBS -lutil"])]) fi AC_CHECKING(for ptyranges) if test -d /dev/ptym ; then pdir='/dev/ptym' else pdir='/dev' fi dnl SCO uses ptyp%d AC_EGREP_CPP(yes, [#ifdef M_UNIX yes; #endif ], ptys=`echo /dev/ptyp??`, ptys=`echo $pdir/pty??`) dnl if test -c /dev/ptyp19; then dnl ptys=`echo /dev/ptyp??` dnl else dnl ptys=`echo $pdir/pty??` dnl fi if test "$ptys" != "$pdir/pty??" ; then p0=`echo $ptys | tr ' ' '\012' | sed -e 's/^.*\(.\).$/\1/g' | sort -u | tr -d '\012'` p1=`echo $ptys | tr ' ' '\012' | sed -e 's/^.*\(.\)$/\1/g' | sort -u | tr -d '\012'` AC_DEFINE_UNQUOTED(PTYRANGE0,"$p0") AC_DEFINE_UNQUOTED(PTYRANGE1,"$p1") fi dnl **** pty mode/group handling **** dnl dnl support provided by Luke Mewburn , 931222 AC_ARG_WITH(pty-mode, [ --with-pty-mode=mode default mode for ptys], [ ptymode="${withval}" ]) AC_ARG_WITH(pty-group, [ --with-pty-group=group default group for ptys], [ ptygrp="${withval}" ]) test -n "$ptymode" || ptymode=0620 if test -n "$ptygrp" ; then AC_DEFINE_UNQUOTED(PTYMODE, $ptymode) AC_DEFINE_UNQUOTED(PTYGROUP,$ptygrp) else AC_CHECKING(default tty permissions/group) rm -f conftest_grp AC_TRY_RUN([ #include #include #include main() { struct stat sb; char *x,*ttyname(); int om, m; FILE *fp; if (!(x = ttyname(0))) exit(1); if (stat(x, &sb)) exit(1); om = sb.st_mode; if (om & 002) exit(0); m = system("mesg y"); if (m == -1 || m == 127) exit(1); if (stat(x, &sb)) exit(1); m = sb.st_mode; if (chmod(x, om)) exit(1); if (m & 002) exit(0); if (sb.st_gid == getgid()) exit(1); if (!(fp=fopen("conftest_grp", "w"))) exit(1); fprintf(fp, "%d\n", sb.st_gid); fclose(fp); exit(0); } ],[ if test -f conftest_grp; then ptygrp=`cat conftest_grp` AC_NOTE([- pty mode: $ptymode, group: $ptygrp]) AC_DEFINE_UNQUOTED(PTYMODE, $ptymode) AC_DEFINE_UNQUOTED(PTYGROUP,$ptygrp) else AC_NOTE(- ptys are world accessable) fi ],[ WRITEPATH='' XTERMPATH='' AC_PATH_PROG(WRITEPATH, write) AC_PATH_PROG(XTERMPATH, xterm) found= if test -n "$WRITEPATH$XTERMPATH"; then findfollow= lsfollow= found=`find $WRITEPATH $XTERMPATH -follow -print 2>/dev/null` if test -n "$found"; then findfollow=-follow lsfollow=L fi if test -n "$XTERMPATH"; then ptygrpn=`ls -l$lsfollow $XTERMPATH | sed -n -e 1p | $AWK '{print $4}'` if test tty != "$ptygrpn"; then XTERMPATH= fi fi fi if test -n "$WRITEPATH$XTERMPATH"; then found=`find $WRITEPATH $XTERMPATH $findfollow -perm -2000 -print` if test -n "$found"; then ptygrp=`ls -ln$lsfollow $found | sed -n -e 1p | $AWK '{print $4}'` AC_NOTE([- pty mode: $ptymode, group: $ptygrp]) AC_DEFINE_UNQUOTED(PTYMODE, $ptymode) AC_DEFINE_UNQUOTED(PTYGROUP,$ptygrp) else AC_NOTE(- ptys are world accessable) fi else AC_NOTE(- can't determine - assume ptys are world accessable) fi ] ) rm -f conftest_grp fi dnl dnl **** utmp handling **** dnl AC_CHECKING(getutent) AC_TRY_LINK([ #include /* to get time_t on SCO */ #include #if defined(SVR4) && !defined(DGUX) #include #define utmp utmpx #else #include #endif #ifdef __hpux #define pututline _pututline #endif ], [int x = DEAD_PROCESS; pututline((struct utmp *)0); getutent();], AC_DEFINE(GETUTENT), olibs="$LIBS" LIBS="$LIBS -lgen" AC_CHECKING(getutent with -lgen) AC_TRY_LINK([ #include #include #if defined(SVR4) && !defined(DGUX) #include #define utmp utmpx #else #include #endif #ifdef __hpux #define pututline _pututline #endif ], [int x = DEAD_PROCESS; pututline((struct utmp *)0); getutent();], AC_DEFINE(GETUTENT), LIBS="$olibs") ) AC_CHECKING(ut_host) AC_TRY_COMPILE([ #include #include #if defined(SVR4) && !defined(DGUX) #include #define utmp utmpx #else #include #endif ],[struct utmp u; u.ut_host[0] = 0;], AC_DEFINE(UTHOST)) AC_CHECK_HEADER(utempter.h, have_utempter=yes, have_utempter=no) if test "$have_utempter" = yes; then AC_DEFINE(HAVE_UTEMPTER) LIBS="$LIBS -lutempter" fi dnl dnl **** loadav **** dnl AC_CHECKING(for libutil(s)) test -f /usr/lib/libutils.a && LIBS="$LIBS -lutils" test -f /usr/lib/libutil.a && LIBS="$LIBS -lutil" AC_CHECKING(getloadavg) AC_TRY_LINK(,[getloadavg((double *)0, 0);], AC_DEFINE(LOADAV_GETLOADAVG) load=1, if test -f /usr/lib/libkvm.a ; then olibs="$LIBS" LIBS="$LIBS -lkvm" AC_CHECKING(getloadavg with -lkvm) AC_TRY_LINK(,[getloadavg((double *)0, 0);], AC_DEFINE(LOADAV_GETLOADAVG) load=1, LIBS="$olibs") fi ) if test -z "$load" ; then AC_EGREP_CPP(yes, [#if defined(NeXT) || defined(apollo) || defined(linux) yes; #endif ], load=1) fi if test -z "$load" ; then AC_CHECKING(for kernelfile) for core in /unix /vmunix /dynix /hp-ux /xelos /dev/ksyms /kernel/unix /kernel/genunix /unicos /mach /netbsd /386bsd /dgux /bsd /stand/vmunix; do if test -f $core || test -c $core; then break fi done if test ! -f $core && test ! -c $core ; then AC_NOTE(- no kernelfile found) else AC_NOTE(- using kernelfile '$core') if test -r $core ; then AC_DEFINE_UNQUOTED(LOADAV_UNIX,"$core") AC_CHECK_HEADER(nlist.h, [AC_DEFINE(NLIST_STRUCT) AC_CHECKING(n_un in struct nlist) AC_TRY_COMPILE([#include ], [struct nlist n; n.n_un.n_name = 0;], AC_DEFINE(NLIST_NAME_UNION))]) AC_CHECKING(for nlist declaration) AC_EGREP_CPP([nlist(( | )( | )*.*\(|\()],[ #ifdef NLIST_STRUCT # include #else # include #endif ],AC_DEFINE(NLIST_DECLARED)) AC_CHECKING(for avenrun symbol) nlist64= for av in avenrun _avenrun _Loadavg avenrun _avenrun _Loadavg; do AC_TRY_RUN([ #include #ifdef NLIST_STRUCT #include #else #include #endif $nlist64 struct nlist nl[2]; main() { #if !defined(_AUX_SOURCE) && !defined(AUX) # ifdef NLIST_NAME_UNION nl[0].n_un.n_name = "$av"; # else nl[0].n_name = "$av"; # endif #else strncpy(nl[0].n_name, "$av", sizeof(nl[0].n_name)); #endif nlist(LOADAV_UNIX, nl); if (nl[0].n_value == 0) exit(1); exit(0); } ],avensym=$av;break) if test "$av" = _Loadavg; then nlist64='#define nlist nlist64' fi done if test -z "$avensym" ; then AC_NOTE(- no avenrun symbol found) else AC_NOTE(- using avenrun symbol '$avensym') AC_DEFINE_UNQUOTED(LOADAV_AVENRUN,"$avensym") if test -n "$nlist64"; then AC_NOTE(- used nlist64 to find it) AC_DEFINE(LOADAV_USE_NLIST64) fi load=1 fi else AC_NOTE( Can't configure the load average display feature) AC_NOTE( because $core is not readable by you.) AC_NOTE( To configure the load average display feature,) AC_NOTE( re-run configure as root if possible.) AC_NOTE( If you are not the system administrator then disregard) AC_NOTE( this warning. You can still use screen without) AC_NOTE( the load average display feature.) fi fi fi AC_PROGRAM_SOURCE([ #include #include ],[ #if !defined(LOADAV_GETLOADAVG) && ((defined(hp300) && !defined(__hpux)) || defined(sun) || (defined(ultrix) && defined(mips)) || defined(_SEQUENT_) || defined(sgi) || (defined(SVR4) && !defined(__hpux)) || defined(sony_news) || (!defined(__osf__) && defined(__alpha)) || defined(_IBMR2) || defined(_AUX_SOURCE) || defined(AUX) || defined(m88k)) loadtype=long # if defined(apollo) || defined(_IBMR2) || defined(_AUX_SOURCE) || defined(AUX) loadscale=65536 # else # if defined(FSCALE) && !defined(__osf__) # undef FSCALE loadscale=FSCALE # else # ifdef sgi loadtype=int loadscale=1024 # else # if defined(MIPS) || defined(SVR4) || defined(m88k) loadscale=256 # else /* not MIPS */ loadscale=1000 /* our default value */ # endif /* MIPS */ # endif /* sgi */ # endif /* not FSCALE */ # endif /* not apollo */ #else loadtype=double loadscale=1 #endif #ifdef alliant loadnum=4 #else loadnum=3 #endif ]) if test -n "$load" ; then AC_DEFINE(LOADAV) fi if test -n "$loadtype" ; then AC_DEFINE_UNQUOTED(LOADAV_TYPE,$loadtype) fi if test -n "$loadnum" ; then AC_DEFINE_UNQUOTED(LOADAV_NUM,$loadnum) fi if test -n "$loadscale" ; then AC_DEFINE_UNQUOTED(LOADAV_SCALE,$loadscale) fi dnl dnl **** signal handling **** dnl if test -n "$posix" ; then dnl POSIX has reliable signals with void return type. AC_NOTE(assuming posix signal definition) AC_DEFINE(SIGVOID) else AC_CHECKING(return type of signal handlers) AC_TRY_COMPILE( [#include #include #ifdef signal #undef signal #endif extern void (*signal ()) ();], [int i;], AC_DEFINE(SIGVOID)) AC_CHECKING(sigset) AC_TRY_LINK([ #include #include ],[ #ifdef SIGVOID sigset(0, (void (*)())0); #else sigset(0, (int (*)())0); #endif ], AC_DEFINE(USESIGSET)) AC_CHECKING(signal implementation) AC_TRY_RUN([ #include #include #ifndef SIGCLD #define SIGCLD SIGCHLD #endif #ifdef USESIGSET #define signal sigset #endif int got; #ifdef SIGVOID void #endif hand() { got++; } main() { /* on hpux we use sigvec to get bsd signals */ #ifdef __hpux (void)signal(SIGCLD, hand); kill(getpid(), SIGCLD); kill(getpid(), SIGCLD); if (got < 2) exit(1); #endif exit(0); } ],,AC_DEFINE(SYSVSIGS)) fi dnl dnl **** libraries **** dnl AC_CHECKING(for crypt and sec libraries) test -f /lib/libcrypt_d.a || test -f /usr/lib/libcrypt_d.a && LIBS="$LIBS -lcrypt_d" oldlibs="$LIBS" LIBS="$LIBS -lcrypt" AC_CHECKING(crypt) AC_TRY_LINK(,,,LIBS="$oldlibs") test -f /lib/libsec.a || test -f /usr/lib/libsec.a && LIBS="$LIBS -lsec" test -f /lib/libshadow.a || test -f /usr/lib/libshadow.a && LIBS="$LIBS -lshadow" oldlibs="$LIBS" LIBS="$LIBS -lsun" AC_CHECKING(IRIX sun library) AC_TRY_LINK(,,,LIBS="$oldlibs") AC_CHECKING(syslog) AC_TRY_LINK(,[closelog();], , [oldlibs="$LIBS" LIBS="$LIBS -lbsd" AC_CHECKING(syslog in libbsd.a) AC_TRY_LINK(, [closelog();], AC_NOTE(- found.), [LIBS="$oldlibs" AC_NOTE(- bad news: syslog missing.) AC_DEFINE(NOSYSLOG)])]) AC_EGREP_CPP(yes, [#ifdef M_UNIX yes; #endif ], LIBS="$LIBS -lsocket -lcrypt_i") dnl dnl **** misc things **** dnl AC_CHECKING(wait union) AC_TRY_COMPILE([#include #include ],[ union wait x; int y; #ifdef WEXITSTATUS y = WEXITSTATUS(x); #endif ],AC_DEFINE(BSDWAIT)) if test -z "$butterfly"; then AC_CHECKING(for termio or termios) AC_TRY_CPP([#include ], AC_DEFINE(TERMIO), if test -n "$posix"; then AC_TRY_CPP([#include ], AC_DEFINE(TERMIO)) fi ) fi dnl AC_CHECK_HEADER(shadow.h, AC_DEFINE(SHADOWPW)) AC_CHECKING(getspnam) AC_TRY_LINK([#include ], [getspnam("x");],AC_DEFINE(SHADOWPW)) AC_CHECKING(getttyent) AC_TRY_LINK(,[getttyent();], AC_DEFINE(GETTTYENT)) AC_CHECKING(fdwalk) AC_TRY_LINK([#include ], [fdwalk(NULL, NULL);],AC_DEFINE(HAVE_FDWALK)) AC_CHECKING(whether memcpy/memmove/bcopy handles overlapping arguments) AC_TRY_RUN([ main() { char buf[10]; strcpy(buf, "abcdefghi"); bcopy(buf, buf + 2, 3); if (strncmp(buf, "ababcf", 6)) exit(1); strcpy(buf, "abcdefghi"); bcopy(buf + 2, buf, 3); if (strncmp(buf, "cdedef", 6)) exit(1); exit(0); /* libc version works properly. */ }], AC_DEFINE(USEBCOPY)) AC_TRY_RUN([ #define bcopy(s,d,l) memmove(d,s,l) main() { char buf[10]; strcpy(buf, "abcdefghi"); bcopy(buf, buf + 2, 3); if (strncmp(buf, "ababcf", 6)) exit(1); strcpy(buf, "abcdefghi"); bcopy(buf + 2, buf, 3); if (strncmp(buf, "cdedef", 6)) exit(1); exit(0); /* libc version works properly. */ }], AC_DEFINE(USEMEMMOVE)) AC_TRY_RUN([ #define bcopy(s,d,l) memcpy(d,s,l) main() { char buf[10]; strcpy(buf, "abcdefghi"); bcopy(buf, buf + 2, 3); if (strncmp(buf, "ababcf", 6)) exit(1); strcpy(buf, "abcdefghi"); bcopy(buf + 2, buf, 3); if (strncmp(buf, "cdedef", 6)) exit(1); exit(0); /* libc version works properly. */ }], AC_DEFINE(USEMEMCPY)) AC_SYS_LONG_FILE_NAMES AC_MSG_CHECKING(for vsprintf) AC_TRY_LINK(,[vsprintf(0,0,0);], AC_MSG_RESULT(yes);AC_DEFINE(USEVARARGS), AC_MSG_RESULT(no)) AC_HEADER_DIRENT AC_MSG_CHECKING(for setenv) if test -z "$ac_setenv_args"; then AC_TRY_LINK( [#include ], [ setenv((char *) 0, (char *) 0, 0); ], ac_setenv_args=3) fi if test -z "$ac_setenv_args"; then AC_TRY_LINK( [#include ], [ setenv((char *) 0, (char *) 0); ], ac_setenv_args=2) fi if test -n "$ac_setenv_args"; then AC_DEFINE(USESETENV) if test "$ac_setenv_args" = 3; then AC_DEFINE(HAVE_SETENV_3) elif test "$ac_setenv_args" = 2; then AC_DEFINE(HAVE_SETENV_2) fi else AC_MSG_RESULT(no) AC_MSG_CHECKING(for putenv) AC_TRY_LINK(,[putenv((char *)0);unsetenv((char *)0);], AC_MSG_RESULT(yes) , AC_MSG_RESULT(no);AC_DEFINE(NEEDPUTENV)) fi AC_MSG_CHECKING([for nl_langinfo(CODESET)]) AC_TRY_LINK([ #include ],[nl_langinfo(CODESET);], AC_MSG_RESULT(yes);AC_DEFINE(HAVE_NL_LANGINFO), AC_MSG_RESULT(no)) AC_SEARCH_LIBS(gethostname, nsl) AC_CHECK_FUNCS(rename fchmod fchown strerror lstat _exit utimes vsnprintf getcwd setlocale strftime) AC_ARG_ENABLE(pam, [ --enable-pam enable PAM support]) if test "$enable_pam" = "yes"; then AC_MSG_CHECKING(for PAM support) oldlibs="$LIBS" LIBS="$LIBS -lpam" AC_TRY_LINK([#include ], [ pam_start(0, 0, 0, 0); pam_authenticate(0, 0); pam_end(0,0); ], AC_MSG_RESULT(yes);AC_DEFINE(USE_PAM), AC_MSG_RESULT(no);LIBS="$oldlibs") fi AC_ARG_ENABLE(use_locale, [ --enable-locale use localized month/day names]) if test "$enable_use_locale" = "yes"; then AC_DEFINE(USE_LOCALE) fi AC_ARG_ENABLE(telnet, [ --enable-telnet enable builtin telnet]) if test "$enable_telnet" = "yes"; then AC_DEFINE(BUILTIN_TELNET) fi AC_ARG_ENABLE(colors256, [ --enable-colors256 enable support for 256 colors]) if test "$enable_colors256" = "yes"; then AC_DEFINE(COLORS256) fi AC_ARG_ENABLE(rxvt_osc, [ --enable-rxvt_osc enable support for rxvt OSC codes]) if test "$enable_rxvt_osc" = "yes"; then AC_DEFINE(RXVT_OSC) fi dnl dnl **** the end **** dnl if test -z "$old_CFLAGS"; then if test "x$CFLAGS" = "x-g"; then CFLAGS="-O" fi fi dnl Ptx bug workaround -- insert -lc after -ltermcap test -n "$seqptx" && LIBS="-ltermcap -lc -lsocket -linet -lnsl -lsec -lseq" AC_TRY_RUN(main(){exit(0);},,AC_MSG_ERROR(Can't run the compiler - internal error. Sorry.)) ETCSCREENRC= AC_MSG_CHECKING(for the global screenrc file) AC_ARG_WITH(sys-screenrc, [ --with-sys-screenrc=path to the global screenrc file], [ ETCSCREENRC="${withval}" ]) AC_SUBST(ETCSCREENRC) AC_OUTPUT(Makefile doc/Makefile, [[ # a hook for preserving undef directive in config.h mv config.h conftest sed -e 's@^\(.*\)defin.\( .*\) .*/\*\(.*KEEP_UNDEF_HERE\)@\1undef\2 /\*\3@' < conftest > config.h rm -f conftest ]]) echo "" if test -z "$AWK"; then echo "!!! Since you have no awk you must copy the files 'comm.h.dist'" echo "!!! and 'term.h.dist' to 'comm.h' and 'term.h'." echo "!!! Do _not_ change the user configuration section in config.h!" echo "Please check the pathnames in the Makefile." else echo "Now please check the pathnames in the Makefile and in the user" echo "configuration section in config.h." fi echo "Then type 'make' to make screen. Good luck." echo "" screen-4.1.0/TODO0000644000175000017500000000035711642704565011542 0ustar abeabe- display size adaption (Activate) - process.c cleanup via comm splitting - writelocks? - partial? - type into several windows at once (for cluster admins) - configurable digraph table - command line options should overwrite config files. screen-4.1.0/autogen.sh0000755000175000017500000000003211642704565013041 0ustar abeabe#!/bin/sh exec autoreconf screen-4.1.0/logfile.c0000644000175000017500000001635311642704565012642 0ustar abeabe/* Copyright (c) 2008, 2009 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Micah Cowan (micah@cowan.name) * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net) * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Copyright (c) 1987 Oliver Laumann * * 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, 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 (see the file COPYING); if not, see * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA * **************************************************************** */ #include /* dev_t, ino_t, off_t, ... */ #include /* struct stat */ #include /* O_WRONLY for logfile_reopen */ #include "config.h" #include "screen.h" #include "extern.h" #include "logfile.h" static void changed_logfile __P((struct logfile *)); static struct logfile *lookup_logfile __P((char *)); static int stolen_logfile __P((struct logfile *)); static struct logfile *logroot = NULL; static void changed_logfile(l) struct logfile *l; { struct stat o, *s = l->st; if (fstat(fileno(l->fp), &o) < 0) /* get trouble later */ return; if (o.st_size > s->st_size) /* aha, appended text */ { s->st_size = o.st_size; /* this should have changed */ s->st_mtime = o.st_mtime; /* only size and mtime */ } } /* * Requires fd to be open and need_fd to be closed. * If possible, need_fd will be open afterwards and refer to * the object originally reffered by fd. fd will be closed then. * Works just like ``fcntl(fd, DUPFD, need_fd); close(fd);'' * * need_fd is returned on success, else -1 is returned. */ int lf_move_fd(fd, need_fd) int need_fd, fd; { int r = -1; if (fd == need_fd) return fd; if (fd >=0 && fd < need_fd) r = lf_move_fd(dup(fd), need_fd); close(fd); return r; } static int logfile_reopen(name, wantfd, l) char *name; int wantfd; struct logfile *l; { int got_fd; close(wantfd); if (((got_fd = open(name, O_WRONLY | O_CREAT | O_APPEND, 0666)) < 0) || lf_move_fd(got_fd, wantfd) < 0) { logfclose(l); debug1("logfile_reopen: failed for %s\n", name); return -1; } changed_logfile(l); debug2("logfile_reopen: %d = %s\n", wantfd, name); return 0; } static int (* lf_reopen_fn)() = logfile_reopen; /* * Whenever logfwrite discoveres that it is required to close and * reopen the logfile, the function registered here is called. * If you do not register anything here, the above logfile_reopen() * will be used instead. * Your function should perform the same steps as logfile_reopen(): * a) close the original filedescriptor without flushing any output * b) open a new logfile for future output on the same filedescriptor number. * c) zero out st_dev, st_ino to tell the stolen_logfile() indcator to * reinitialise itself. * d) return 0 on success. */ void logreopen_register(fn) int (*fn) __P((char *, int, struct logfile *)); { lf_reopen_fn = fn ? fn : logfile_reopen; } /* * If the logfile has been removed, truncated, unlinked or the like, * return nonzero. * The l->st structure initialised by logfopen is updated * on every call. */ static int stolen_logfile(l) struct logfile *l; { struct stat o, *s = l->st; o = *s; if (fstat(fileno(l->fp), s) < 0) /* remember that stat failed */ s->st_ino = s->st_dev = 0; ASSERT(s == l->st); if (!o.st_dev && !o.st_ino) /* nothing to compare with */ return 0; if ((!s->st_dev && !s->st_ino) || /* stat failed, that's new! */ !s->st_nlink || /* red alert: file unlinked */ (s->st_size < o.st_size) || /* file truncated */ (s->st_mtime != o.st_mtime) || /* file modified */ ((s->st_ctime != o.st_ctime) && /* file changed (moved) */ !(s->st_mtime == s->st_ctime && /* and it was not a change */ o.st_ctime < s->st_ctime))) /* due to delayed nfs write */ { debug1("stolen_logfile: %s stolen!\n", l->name); debug3("st_dev %d, st_ino %d, st_nlink %d\n", (int)s->st_dev, (int)s->st_ino, (int)s->st_nlink); debug2("s->st_size %d, o.st_size %d\n", (int)s->st_size, (int)o.st_size); debug2("s->st_mtime %d, o.st_mtime %d\n", (int)s->st_mtime, (int)o.st_mtime); debug2("s->st_ctime %d, o.st_ctime %d\n", (int)s->st_ctime, (int)o.st_ctime); return -1; } debug1("stolen_logfile: %s o.k.\n", l->name); return 0; } static struct logfile * lookup_logfile(name) char *name; { struct logfile *l; for (l = logroot; l; l = l->next) if (!strcmp(name, l->name)) return l; return NULL; } struct logfile * logfopen(name, fp) char *name; FILE *fp; { struct logfile *l; if (!fp) { if (!(l = lookup_logfile(name))) return NULL; l->opencount++; return l; } if (!(l = (struct logfile *)malloc(sizeof(struct logfile)))) return NULL; if (!(l->st = (struct stat *)malloc(sizeof(struct stat)))) { free((char *)l); return NULL; } if (!(l->name = SaveStr(name))) { free((char *)l->st); free((char *)l); return NULL; } l->fp = fp; l->opencount = 1; l->writecount = 0; l->flushcount = 0; changed_logfile(l); l->next = logroot; logroot = l; return l; } int islogfile(name) char *name; { if (!name) return logroot ? 1 : 0; return lookup_logfile(name) ? 1 : 0; } int logfclose(l) struct logfile *l; { struct logfile **lp; for (lp = &logroot; *lp; lp = &(*lp)->next) if (*lp == l) break; if (!*lp) return -1; if ((--l->opencount) > 0) return 0; if (l->opencount < 0) abort(); *lp = l->next; fclose(l->fp); free(l->name); free((char *)l); return 0; } /* * XXX * write and flush both *should* check the file's stat, if it disappeared * or changed, re-open it. */ int logfwrite(l, buf, n) struct logfile *l; char *buf; int n; { int r; if (stolen_logfile(l) && lf_reopen_fn(l->name, fileno(l->fp), l)) return -1; r = fwrite(buf, n, 1, l->fp); l->writecount += l->flushcount + 1; l->flushcount = 0; changed_logfile(l); return r; } int logfflush(l) struct logfile *l; { int r = 0; if (!l) for (l = logroot; l; l = l->next) { if (stolen_logfile(l) && lf_reopen_fn(l->name, fileno(l->fp), l)) return -1; r |= fflush(l->fp); l->flushcount++; changed_logfile(l); } else { if (stolen_logfile(l) && lf_reopen_fn(l->name, fileno(l->fp), l)) return -1; r = fflush(l->fp); l->flushcount++; changed_logfile(l); } return r; } screen-4.1.0/NEWS.3.90000644000175000017500000001512311642704565012056 0ustar abeabe ------------------------------- What's new in screen-3.9.15 ? ------------------------------- * unicode combining character support * new encoding: chinese GBK * new 'backtick' command and string escape to embed command output into e.g. the hardstatus line ------------------------------- What's new in screen-3.9.13 ? ------------------------------- * altscreen support from Gurusamy Sarathy * new command "maxwin" to set a limit on the number of windows * new keys in copy&paste mode: 'B' and 'E' ------------------------------- What's new in screen-3.9.11 ? ------------------------------- * windowlist, bound to ^A" * support for other encodings, e.g. big5, koi8r, cp1251 new commands 'encoding', 'defencoding' 'register', 'readreg', 'readbuf', 'writebuf' now understand an extra encoding parameter * support for double utf-8 characters * lots of new string escapes and extensions to existsing ones: %LD, %LM, %Lw, %W, %-w, %+w, %H, %f, %F, %l, %=, %<, %> * new commands: 'source', 'eval', 'deflog', 'ignorecase', 'setsid' * command key classes: 'bind', 'command' and 'help' understand a '-c ' parameter. See the man page for examples * new login state: always - don't remove slot even if screen gets detached * 256 color support (experimental) * configurable time format string (for ^At) * config option to use localized month/week names * new option '-h' for hardcopy: also dump the scrollback buffer ------------------------------ What's new in screen-3.9.9 ? ------------------------------ * new '-X' option to send commands to screen sessions. screen -X echo Hi... * added a possibility to change the attributes/color in caption or hardstatus strings: caption always "%3n %{r}%t%{-}%? @%u%?%? %{g}[%h]%{-}%?" * new 'dinfo' command to show what screen thinks about your terminal. * new 'attrcolor' command to map attributes to color codes: attrcolor u "-u b" attrcolor b "r" * support for UTF-8: new commands 'utf8', 'defutf8' to change the encoding of a window, plus a '-U' option to tell screen that your terminal sends/receives UTF-8 codes. * support for 16 colors. ------------------------------ What's new in screen-3.9.8 ? ------------------------------ * new command 'resize' to resize regions (aka split windows), try: bind = resize = bind + resize +1 bind - resize -1 bind _ resize max * new argument for 'focus': up, down, top, bottom * X11 mouse tracking support * Support for the "new color model", aka "background color erase": the bce/defbce commands change the color model of the current window/new windows. * experimental rxvt OSC sequence support (used to set a background picture or to change the default colors), disabled by default. ---------------------------- What's new in screen-3.9 ? ---------------------------- * real multiuser support A window can now be displayed on more than one attached displays. Screen does all the necessary clipping if the window size doesn't fit the display. New command: ^AF - fit the window size into the display size. * split screen support A display may now host multiple windows. New commands: ^AS - split horizontally. This add another region to the display ^A - move the focus to the next region ^AX - kill the current region ^AQ - kill all other regions * hardstatus emulation support The last line of the display may now be used as a hardstatus line if the terminal doesn't have the 'hs' capability. New commands: hardstatus [always]lastline hardstatus [always]message hardstatus [always]ignore * configurable window seperator and hardstatus strings The window (region) seperator and the hardstatus can be set to an arbitrary string containing screen's % escape sequences. The window's hardstatus is just another escape sequence, '%h'. New commands: hardstatus string [string] caption string [string] The default strings are "%h" (hardstatus) and "%3n %t" (caption). * permanent window seperator The window seperator can be set to stay on screen even if the display contains only one region New commands: caption always caption splitonly * many new escapes %c - current time HH:MM (*CHANGE*: this was %w in screen-3.7) %C - current time HH:MM in 24h format %l - the load of the system %h - hardstatus of the window %w - all window names %W - all window names except the current window %u - all other users on this window %? - the part to the next %? is displayed only if an escape expands to an nonempty string. %: - "else" part of %? Some escapes like %c may be qualified with a '0' (like %0c) to make screen use '0' instead of space as a filler. Others understand a length qualifier, like %3n. If escapes like the current time are used as hardstatus/caption string screen will update them so that you can always have the current time onscreen. *CHANGE* ~ is no longer used as bell character, use ^G instead! * logfile timestamps and flush timeout New commands: logfile flush logtstamp [on|off] logtstamp string [string] logtstamp after [secs] * configurable breaktype You can now choose one of TIOCSBRK, TCSBRK, tcsendbreak. New commands: breaktype defbreaktype * other new commands: hstatus - set the window's hardstatus defslowpaste defsilence * optional builtin telnet. This is useful if screen is used as frontend to a terminal multiplexor. Use //telnet to access the builtin telnet program, as in: 'screen //telnet host [port]' * remote detach and reattach change: '-d' is now ignored if the screen is already detached and you want to reattach. You can also use '-RR' to make screen use the first session found if more than one session is available. Thus '-d -RR' or '-x -RR' always gets you a screen. * support for history compaction You can tell screen to suppress trailing blank lines when scolling up text into the history buffer. (Wayne Davison) New command: compacthist * optional Braille support. If you can read Braille and have one of the devices listed in README.DOTSCREEN, please compile with -DHAVE_BRAILLE and let us know if this feature is useful. screen-4.1.0/input.c0000644000175000017500000003341111642704565012352 0ustar abeabe/* Copyright (c) 2008, 2009 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Micah Cowan (micah@cowan.name) * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net) * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Copyright (c) 1987 Oliver Laumann * * 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, 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 (see the file COPYING); if not, see * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA * **************************************************************** */ #include #include "config.h" #include "screen.h" #include "extern.h" #define INPUTLINE (flayer->l_height - 1) static void InpProcess __P((char **, int *)); static void InpAbort __P((void)); static void InpRedisplayLine __P((int, int, int, int)); extern struct layer *flayer; extern struct display *display; extern struct mchar mchar_blank, mchar_so; struct inpline { char buf[101]; /* text buffer */ int len; /* length of the editible string */ int pos; /* cursor position in editable string */ struct inpline *next, *prev; }; /* 'inphist' is used to store the current input when scrolling through history. * inpline->prev == history-prev * inpline->next == history-next */ static struct inpline inphist; struct inpdata { struct inpline inp; int inpmaxlen; /* 100, or less, if caller has shorter buffer */ char *inpstring; /* the prompt */ int inpstringlen; /* length of the prompt */ int inpmode; /* INP_NOECHO, INP_RAW, INP_EVERY */ void (*inpfinfunc) __P((char *buf, int len, char *priv)); char *priv; /* private data for finfunc */ int privdata; /* private data space */ char *search; /* the search string */ }; static struct LayFuncs InpLf = { InpProcess, InpAbort, InpRedisplayLine, DefClearLine, DefRewrite, DefResize, DefRestore, 0 }; /* ** Here is the input routine */ /* called once, after InitOverlayPage in Input() or Isearch() */ void inp_setprompt(p, s) char *p, *s; { struct inpdata *inpdata; inpdata = (struct inpdata *)flayer->l_data; if (p) { inpdata->inpstringlen = strlen(p); inpdata->inpstring = p; } if (s) { if (s != inpdata->inp.buf) strncpy(inpdata->inp.buf, s, sizeof(inpdata->inp.buf) - 1); inpdata->inp.buf[sizeof(inpdata->inp.buf) - 1] = 0; inpdata->inp.pos = inpdata->inp.len = strlen(inpdata->inp.buf); } InpRedisplayLine(INPUTLINE, 0, flayer->l_width - 1, 0); flayer->l_x = inpdata->inpstringlen + (inpdata->inpmode & INP_NOECHO ? 0 : inpdata->inp.pos); flayer->l_y = INPUTLINE; } /* * We dont use HS status line with Input(). * If we would use it, then we should check e_tgetflag("es") if * we are allowed to use esc sequences there. * * mode is an OR of * INP_NOECHO == suppress echoing of characters. * INP_RAW == raw mode. call finfunc after each character typed. * INP_EVERY == digraph mode. */ void Input(istr, len, mode, finfunc, priv, data) char *istr; int len; int mode; void (*finfunc) __P((char *buf, int len, char *priv)); char *priv; int data; { int maxlen; struct inpdata *inpdata; if (!flayer) return; if (len > 100) len = 100; if (!(mode & INP_NOECHO)) { maxlen = flayer->l_width - 1 - strlen(istr); if (len > maxlen) len = maxlen; } if (len < 0) { LMsg(0, "Width %d chars too small", -len); return; } if (InitOverlayPage(sizeof(*inpdata), &InpLf, 1)) return; flayer->l_mode = 1; inpdata = (struct inpdata *)flayer->l_data; inpdata->inpmaxlen = len; inpdata->inpfinfunc = finfunc; inpdata->inp.pos = inpdata->inp.len = 0; inpdata->inp.prev = inphist.prev; inpdata->inpmode = mode; inpdata->privdata = data; if (!priv) priv = (char*)&inpdata->privdata; inpdata->priv = priv; inpdata->inpstringlen = 0; inpdata->inpstring = NULL; inpdata->search = NULL; if (istr) inp_setprompt(istr, (char *)NULL); } static void erase_chars(inpdata, from, to, x, mv) struct inpdata *inpdata; char *from; char *to; int x; int mv; { int chng; ASSERT(from < to); if (inpdata->inp.len > to - inpdata->inp.buf) bcopy(to, from, inpdata->inp.len - (to - inpdata->inp.buf)); chng = to - from; if (mv) { x -= chng; inpdata->inp.pos -= chng; } inpdata->inp.len -= chng; if (!(inpdata->inpmode & INP_NOECHO)) { struct mchar mc; char *s = from < to ? from : to; mc = mchar_so; while (s < inpdata->inp.buf+inpdata->inp.len) { mc.image = *s++; LPutChar(flayer, &mc, x++, INPUTLINE); } while (chng--) LPutChar(flayer, &mchar_blank, x++, INPUTLINE); x = inpdata->inpstringlen + inpdata->inp.pos; LGotoPos(flayer, x, INPUTLINE); } } static void InpProcess(ppbuf, plen) char **ppbuf; int *plen; { int len, x; char *pbuf; char ch; struct inpdata *inpdata; struct display *inpdisplay; int prev, next, search = 0; inpdata = (struct inpdata *)flayer->l_data; inpdisplay = display; #define RESET_SEARCH do { if (inpdata->search) Free(inpdata->search); } while (0) LGotoPos(flayer, inpdata->inpstringlen + (inpdata->inpmode & INP_NOECHO ? 0 : inpdata->inp.pos), INPUTLINE); if (ppbuf == 0) { InpAbort(); return; } x = inpdata->inpstringlen + inpdata->inp.pos; len = *plen; pbuf = *ppbuf; while (len) { char *p = inpdata->inp.buf + inpdata->inp.pos; ch = *pbuf++; len--; if (inpdata->inpmode & INP_EVERY) { inpdata->inp.buf[inpdata->inp.len] = ch; if (ch) { display = inpdisplay; (*inpdata->inpfinfunc)(inpdata->inp.buf, inpdata->inp.len, inpdata->priv); ch = inpdata->inp.buf[inpdata->inp.len]; } } else if (inpdata->inpmode & INP_RAW) { display = inpdisplay; (*inpdata->inpfinfunc)(&ch, 1, inpdata->priv); /* raw */ if (ch) continue; } if (((unsigned char)ch & 0177) >= ' ' && ch != 0177 && inpdata->inp.len < inpdata->inpmaxlen) { if (inpdata->inp.len > inpdata->inp.pos) bcopy(p, p+1, inpdata->inp.len - inpdata->inp.pos); inpdata->inp.buf[inpdata->inp.pos++] = ch; inpdata->inp.len++; if (!(inpdata->inpmode & INP_NOECHO)) { struct mchar mc; mc = mchar_so; mc.image = *p++; LPutChar(flayer, &mc, x, INPUTLINE); x++; if (p < inpdata->inp.buf+inpdata->inp.len) { while (p < inpdata->inp.buf+inpdata->inp.len) { mc.image = *p++; LPutChar(flayer, &mc, x++, INPUTLINE); } x = inpdata->inpstringlen + inpdata->inp.pos; LGotoPos(flayer, x, INPUTLINE); } } RESET_SEARCH; } else if ((ch == '\b' || ch == 0177) && inpdata->inp.pos > 0) { erase_chars(inpdata, p-1, p, x, 1); RESET_SEARCH; } else if (ch == '\025') /* CTRL-U */ { x = inpdata->inpstringlen; if (inpdata->inp.len && !(inpdata->inpmode & INP_NOECHO)) { LClearArea(flayer, x, INPUTLINE, x + inpdata->inp.len - 1, INPUTLINE, 0, 0); LGotoPos(flayer, x, INPUTLINE); } inpdata->inp.len = inpdata->inp.pos = 0; } else if (ch == '\013') /* CTRL-K */ { x = inpdata->inpstringlen + inpdata->inp.pos; if (inpdata->inp.len > inpdata->inp.pos && !(inpdata->inpmode & INP_NOECHO)) { LClearArea(flayer, x, INPUTLINE, x + inpdata->inp.len - inpdata->inp.pos - 1, INPUTLINE, 0, 0); LGotoPos(flayer, x, INPUTLINE); } inpdata->inp.len = inpdata->inp.pos; } else if (ch == '\027' && inpdata->inp.pos > 0) /* CTRL-W */ { char *oldp = p--; while (p > inpdata->inp.buf && *p == ' ') p--; while (p > inpdata->inp.buf && *(p - 1) != ' ') p--; erase_chars(inpdata, p, oldp, x, 1); RESET_SEARCH; } else if (ch == '\004' && inpdata->inp.pos < inpdata->inp.len) /* CTRL-D */ { erase_chars(inpdata, p, p+1, x, 0); RESET_SEARCH; } else if (ch == '\001' || (unsigned char)ch == 0201) /* CTRL-A */ { LGotoPos(flayer, x -= inpdata->inp.pos, INPUTLINE); inpdata->inp.pos = 0; } else if ((ch == '\002' || (unsigned char)ch == 0202) && inpdata->inp.pos > 0) /* CTRL-B */ { LGotoPos(flayer, --x, INPUTLINE); inpdata->inp.pos--; } else if (ch == '\005' || (unsigned char)ch == 0205) /* CTRL-E */ { LGotoPos(flayer, x += inpdata->inp.len - inpdata->inp.pos, INPUTLINE); inpdata->inp.pos = inpdata->inp.len; } else if ((ch == '\006' || (unsigned char)ch == 0206) && inpdata->inp.pos < inpdata->inp.len) /* CTRL-F */ { LGotoPos(flayer, ++x, INPUTLINE); inpdata->inp.pos++; } else if ((prev = ((ch == '\020' || (unsigned char)ch == 0220) && /* CTRL-P */ inpdata->inp.prev)) || (next = ((ch == '\016' || (unsigned char)ch == 0216) && /* CTRL-N */ inpdata->inp.next)) || (search = ((ch == '\022' || (unsigned char)ch == 0222) && inpdata->inp.prev))) { struct mchar mc; struct inpline *sel; int pos = -1; mc = mchar_so; if (prev) sel = inpdata->inp.prev; else if (next) sel = inpdata->inp.next; else { /* search */ inpdata->inp.buf[inpdata->inp.len] = 0; /* Remove the ctrl-r from the end */ if (!inpdata->search) inpdata->search = SaveStr(inpdata->inp.buf); for (sel = inpdata->inp.prev; sel; sel = sel->prev) { char *f; if ((f = strstr(sel->buf, inpdata->search))) { pos = f - sel->buf; break; } } if (!sel) continue; /* Did not find a match. Process the next input. */ } if (inpdata->inp.len && !(inpdata->inpmode & INP_NOECHO)) LClearArea(flayer, inpdata->inpstringlen, INPUTLINE, inpdata->inpstringlen + inpdata->inp.len - 1, INPUTLINE, 0, 0); if ((prev || search) && !inpdata->inp.next) inphist = inpdata->inp; memcpy(&inpdata->inp, sel, sizeof(struct inpline)); if (pos != -1) inpdata->inp.pos = pos; if (inpdata->inp.len > inpdata->inpmaxlen) inpdata->inp.len = inpdata->inpmaxlen; if (inpdata->inp.pos > inpdata->inp.len) inpdata->inp.pos = inpdata->inp.len; x = inpdata->inpstringlen; p = inpdata->inp.buf; if (!(inpdata->inpmode & INP_NOECHO)) { while (p < inpdata->inp.buf+inpdata->inp.len) { mc.image = *p++; LPutChar(flayer, &mc, x++, INPUTLINE); } } x = inpdata->inpstringlen + inpdata->inp.pos; LGotoPos(flayer, x, INPUTLINE); } else if (ch == '\003' || ch == '\007' || ch == '\033' || ch == '\000' || ch == '\n' || ch == '\r') { if (ch != '\n' && ch != '\r') inpdata->inp.len = 0; inpdata->inp.buf[inpdata->inp.len] = 0; if (inpdata->inp.len && !(inpdata->inpmode & (INP_NOECHO | INP_RAW))) { struct inpline *store; /* Look for a duplicate first */ for (store = inphist.prev; store; store = store->prev) { if (strcmp(store->buf, inpdata->inp.buf) == 0) { if (store->next) store->next->prev = store->prev; if (store->prev) store->prev->next = store->next; store->pos = inpdata->inp.pos; break; } } if (!store) { store = malloc(sizeof(struct inpline)); memcpy(store, &inpdata->inp, sizeof(struct inpline)); } store->next = &inphist; store->prev = inphist.prev; if (inphist.prev) inphist.prev->next = store; inphist.prev = store; } flayer->l_data = 0; /* so inpdata does not get freed */ InpAbort(); /* redisplays... */ *ppbuf = pbuf; *plen = len; display = inpdisplay; if ((inpdata->inpmode & INP_RAW) == 0) (*inpdata->inpfinfunc)(inpdata->inp.buf, inpdata->inp.len, inpdata->priv); else (*inpdata->inpfinfunc)(pbuf - 1, 0, inpdata->priv); if (inpdata->search) free(inpdata->search); free(inpdata); return; } else { /* The user was searching, and then pressed some non-control input. So reset * the search string. */ RESET_SEARCH; } } if (!(inpdata->inpmode & INP_RAW)) { flayer->l_x = inpdata->inpstringlen + (inpdata->inpmode & INP_NOECHO ? 0 : inpdata->inp.pos); flayer->l_y = INPUTLINE; } *ppbuf = pbuf; *plen = len; } static void InpAbort() { LAY_CALL_UP(LayRedisplayLine(INPUTLINE, 0, flayer->l_width - 1, 0)); ExitOverlayPage(); } static void InpRedisplayLine(y, xs, xe, isblank) int y, xs, xe, isblank; { int q, r, s, l, v; struct inpdata *inpdata; inpdata = (struct inpdata *)flayer->l_data; if (y != INPUTLINE) { LAY_CALL_UP(LayRedisplayLine(y, xs, xe, isblank)); return; } inpdata->inp.buf[inpdata->inp.len] = 0; q = xs; v = xe - xs + 1; s = 0; r = inpdata->inpstringlen; if (v > 0 && q < r) { l = v; if (l > r - q) l = r - q; LPutStr(flayer, inpdata->inpstring + q - s, l, &mchar_so, q, y); q += l; v -= l; } s = r; r += inpdata->inp.len; if (!(inpdata->inpmode & INP_NOECHO) && v > 0 && q < r) { l = v; if (l > r - q) l = r - q; LPutStr(flayer, inpdata->inp.buf + q - s, l, &mchar_so, q, y); q += l; v -= l; } s = r; r = flayer->l_width; if (!isblank && v > 0 && q < r) { l = v; if (l > r - q) l = r - q; LClearArea(flayer, q, y, q + l - 1, y, 0, 0); q += l; } } screen-4.1.0/NEWS0000644000175000017500000000135211642704565011545 0ustar abeabe ------------------------------ What's new in screen-4.0.3 ? ------------------------------ * zombie command has new option 'onerror' * buffer overflow in resize.c fixed * minor docu update * more robust startup * use setresuid; SendAttachMsg() for fd-passing added; DoCSI enhanced. ------------------------------ What's new in screen-4.0.0 ? ------------------------------ * new screenrc parser, not 100% compatible. * screenblanker support: new 'idle', 'blanker', 'blankerprg' commands. * zmodem support via the 'zmodem' command. * nonblock code rewritten, nonblock now understands a timeout. new command 'defnonblock'. screen-4.1.0/FAQ0000777000175000017500000000000011732171240012457 2doc/FAQustar abeabescreen-4.1.0/ansi.h0000644000175000017500000001067511642704565012161 0ustar abeabe/* Copyright (c) 2008, 2009 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Micah Cowan (micah@cowan.name) * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net) * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Copyright (c) 1987 Oliver Laumann * * 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, 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 (see the file COPYING); if not, see * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA * **************************************************************** * $Id$ GNU */ #define NATTR 6 #define ATTR_DI 0 /* Dim mode */ #define ATTR_US 1 /* Underscore mode */ #define ATTR_BD 2 /* Bold mode */ #define ATTR_RV 3 /* Reverse mode */ #define ATTR_SO 4 /* Standout mode */ #define ATTR_BL 5 /* Blinking */ #define A_DI (1<font[(x) + 1] == 0xff && (unsigned char)(ml)->image[(x) + 1] == 0xff : \ ((unsigned char)(ml)->font[x] & 0x1f) != 0 && ((unsigned char)(ml)->font[x] & 0xe0) == 0 \ ) # define dw_right(ml, x, enc) ((enc == UTF8) ? \ (unsigned char)(ml)->font[x] == 0xff && (unsigned char)(ml)->image[x] == 0xff : \ ((unsigned char)(ml)->font[x] & 0xe0) == 0x80 \ ) # else # define dw_left(ml, x, enc) ( \ ((unsigned char)(ml)->font[x] & 0x1f) != 0 && ((unsigned char)(ml)->font[x] & 0xe0) == 0 \ ) # define dw_right(ml, x, enc) ( \ ((unsigned char)(ml)->font[x] & 0xe0) == 0x80 \ ) # endif /* UTF8 */ #else # define dw_left(ml, x, enc) 0 # define dw_right(ml, x, enc) 0 #endif screen-4.1.0/term.sh0000644000175000017500000000562311642704565012356 0ustar abeabe#! /bin/sh if test -z "$AWK"; then AWK=awk fi if test -z "$srcdir"; then srcdir=. fi LC_ALL=C export LC_ALL rm -f term.h cat << EOF > term.h /* * This file is automagically created from term.c -- DO NOT EDIT */ #define T_FLG 0 #define T_NUM 1 #define T_STR 2 struct term { char *tcname; int type; }; union tcu { int flg; int num; char *str; }; EOF # # SCO-Unix sufferers may need to use the following lines: # perl -p < ${srcdir}/term.c \ # -e 's/"/"C/ if /"[A-Z]."/;' \ # -e 'y/[a-z]/[A-Z]/ if /"/;' \ # sed < ${srcdir}/term.c \ -e '/"[A-Z]."/s/"/"C/' \ -e '/"/y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' \ | $AWK ' /^ [{] ".*KMAPDEF[(].*$/{ if (min == 0) min = s max = s; } /^ [{] ".*KMAPADEF[(].*$/{ if (amin == 0) amin = s amax = s; } /^ [{] ".*KMAPMDEF[(].*$/{ if (mmin == 0) mmin = s mmax = s; } /^ [{] ".*$/{ a=substr($2,2,length($2)-3); b=substr($3,3,3); if (nolist == 0) { printf "#define d_%s d_tcs[%d].%s\n",a,s,b printf "#define D_%s (D_tcs[%d].%s)\n",a,s,b } s++; } /\/* define/{ printf "#define %s %d\n",$3,s } /\/* nolist/{ nolist = 1; } /\/* list/{ nolist = 0; } END { printf "\n#ifdef MAPKEYS\n" printf "# define KMAPDEFSTART %d\n", min printf "# define NKMAPDEF %d\n", max-min+1 printf "# define KMAPADEFSTART %d\n", amin printf "# define NKMAPADEF %d\n", amax-amin+1 printf "# define KMAPMDEFSTART %d\n", mmin printf "# define NKMAPMDEF %d\n", mmax-mmin+1 printf "#endif\n" } ' | sed -e s/NUM/num/ -e s/STR/str/ -e s/FLG/flg/ \ >> term.h rm -f kmapdef.c cat << EOF > kmapdef.c /* * This file is automagically created from term.c -- DO NOT EDIT */ #include "config.h" #ifdef MAPKEYS EOF $AWK < ${srcdir}/term.c ' /^ [{] ".*KMAP.*$/{ for (i = 0; i < 3; i++) { q = $(5+i) if (substr(q, 1, 5) == "KMAPD") { if (min == 0) min = s max = s arr[s] = substr(q, 9, length(q)-9) } if (substr(q, 1, 5) == "KMAPA") { if (amin == 0) amin = s amax = s anarr[s] = substr(q, 10, length(q)-10) } if (substr(q, 1, 5) == "KMAPM") { if (mmin == 0) mmin = s mmax = s mnarr[s] = substr(q, 10, length(q)-10) } } } /^ [{] ".*$/{ s++; } END { printf "char *kmapdef[] = {\n" for (s = min; s <= max; s++) { if (arr[s]) printf "%s", arr[s] else printf "0" if (s < max) printf ",\n" else printf "\n" } printf "};\n\n" printf "char *kmapadef[] = {\n" for (s = amin; s <= amax; s++) { if (anarr[s]) printf "%s", anarr[s] else printf "0" if (s < amax) printf ",\n" else printf "\n" } printf "};\n\n" printf "char *kmapmdef[] = {\n" for (s = mmin; s <= mmax; s++) { if (mnarr[s]) printf "%s", mnarr[s] else printf "0" if (s < mmax) printf ",\n" else printf "\n" } printf "};\n\n#endif\n" } ' >> kmapdef.c chmod a-w kmapdef.c chmod a-w term.h screen-4.1.0/fileio.c0000644000175000017500000004656711642704565012502 0ustar abeabe/* Copyright (c) 2008, 2009 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Micah Cowan (micah@cowan.name) * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net) * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Copyright (c) 1987 Oliver Laumann * * 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, 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 (see the file COPYING); if not, see * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA * **************************************************************** */ #include #include #include #include #ifndef SIGINT # include #endif #include "config.h" #include "screen.h" #include "extern.h" extern struct display *display, *displays; extern struct win *fore; extern struct layer *flayer; extern int real_uid, eff_uid; extern int real_gid, eff_gid; extern char *extra_incap, *extra_outcap; extern char *home, *RcFileName; extern char SockPath[], *SockName; #ifdef COPY_PASTE extern char *BufferFile; #endif extern int hardcopy_append; extern char *hardcopydir; static char *CatExtra __P((char *, char *)); static char *findrcfile __P((char *)); char *rc_name = ""; int rc_recursion = 0; static char * CatExtra(str1, str2) register char *str1, *str2; { register char *cp; register int len1, len2, add_colon; len1 = strlen(str1); if (len1 == 0) return str2; add_colon = (str1[len1 - 1] != ':'); if (str2) { len2 = strlen(str2); if ((cp = realloc(str2, (unsigned) len1 + len2 + add_colon + 1)) == NULL) Panic(0, "%s", strnomem); bcopy(cp, cp + len1 + add_colon, len2 + 1); } else { if (len1 == 0) return 0; if ((cp = malloc((unsigned) len1 + add_colon + 1)) == NULL) Panic(0, "%s", strnomem); cp[len1 + add_colon] = '\0'; } bcopy(str1, cp, len1); if (add_colon) cp[len1] = ':'; return cp; } static char * findrcfile(rcfile) char *rcfile; { char buf[256]; char *p; /* Tilde prefix support courtesy , * taken from a Debian patch. */ if (rcfile && *rcfile == '~') { static char rcfilename_tilde_exp[MAXPATHLEN+1]; char *slash_position = strchr(rcfile, '/'); if (slash_position == rcfile+1) { char *home = getenv("HOME"); if (!home) { Msg(0, "%s: source: tilde expansion failed", rc_name); return NULL; } snprintf(rcfilename_tilde_exp, MAXPATHLEN, "%s/%s", home, rcfile+2); } else if (slash_position) { struct passwd *p; *slash_position = 0; p = getpwnam(rcfile+1); if (!p) { Msg(0, "%s: source: tilde expansion failed for user %s", rc_name, rcfile+1); return NULL; } snprintf(rcfilename_tilde_exp, MAXPATHLEN, "%s/%s", p->pw_dir, slash_position+1); } else { Msg(0, "%s: source: illegal tilde expression.", rc_name); return NULL; } rcfile = rcfilename_tilde_exp; } if (rcfile) { char *rcend = rindex(rc_name, '/'); if (*rcfile != '/' && rcend && (rcend - rc_name) + strlen(rcfile) + 2 < sizeof(buf)) { strncpy(buf, rc_name, rcend - rc_name + 1); strcpy(buf + (rcend - rc_name) + 1, rcfile); if (access(buf, R_OK) == 0) return SaveStr(buf); } debug1("findrcfile: you specified '%s'\n", rcfile); return SaveStr(rcfile); } debug("findrcfile: you specified nothing...\n"); if ((p = getenv("SCREENRC")) != NULL && *p != '\0') { debug1(" $SCREENRC has: '%s'\n", p); return SaveStr(p); } else { debug(" ...nothing in $SCREENRC, defaulting $HOME/.screenrc\n"); if (strlen(home) > sizeof(buf) - 12) Panic(0, "Rc: home too large"); sprintf(buf, "%s/.screenrc", home); return SaveStr(buf); } } /* * this will be called twice: * 1) rcfilename = "/etc/screenrc" * 2) rcfilename = RcFileName */ int StartRc(rcfilename, nopanic) char *rcfilename; int nopanic; { register int argc, len; register char *p, *cp; char buf[2048]; char *args[MAXARGS]; int argl[MAXARGS]; FILE *fp; char *oldrc_name = rc_name; /* always fix termcap/info capabilities */ extra_incap = CatExtra("TF", extra_incap); /* Special settings for vt100 and others */ if (display && (!strncmp(D_termname, "vt", 2) || !strncmp(D_termname, "xterm", 5))) extra_incap = CatExtra("xn:f0=\033Op:f1=\033Oq:f2=\033Or:f3=\033Os:f4=\033Ot:f5=\033Ou:f6=\033Ov:f7=\033Ow:f8=\033Ox:f9=\033Oy:f.=\033On:f,=\033Ol:fe=\033OM:f+=\033Ok:f-=\033Om:f*=\033Oj:f/=\033Oo:fq=\033OX", extra_incap); rc_name = findrcfile(rcfilename); if (rc_name == NULL || (fp = secfopen(rc_name, "r")) == NULL) { const char *rc_nonnull = rc_name ? rc_name : rcfilename; if (!rc_recursion && RcFileName && !strcmp(RcFileName, rc_nonnull)) { /* * User explicitly gave us that name, * this is the only case, where we get angry, if we can't read * the file. */ debug3("StartRc: '%s','%s', '%s'\n", RcFileName, rc_name ? rc_name : "(null)", rcfilename); if (!nopanic) Panic(0, "Unable to open \"%s\".", rc_nonnull); /* possibly NOTREACHED */ } debug1("StartRc: '%s' no good. ignored\n", rc_nonnull); if (rc_name) Free(rc_name); rc_name = oldrc_name; return 1; } while (fgets(buf, sizeof buf, fp) != NULL) { if ((p = rindex(buf, '\n')) != NULL) *p = '\0'; if ((argc = Parse(buf, sizeof buf, args, argl)) == 0) continue; if (strcmp(args[0], "echo") == 0) { if (!display) continue; if (argc < 2 || (argc == 3 && strcmp(args[1], "-n")) || argc > 3) { Msg(0, "%s: 'echo [-n] \"string\"' expected.", rc_name); continue; } AddStr(args[argc - 1]); if (argc != 3) { AddStr("\r\n"); Flush(0); } } else if (strcmp(args[0], "sleep") == 0) { if (!display) continue; debug("sleeeeeeep\n"); if (argc != 2) { Msg(0, "%s: sleep: one numeric argument expected.", rc_name); continue; } DisplaySleep1000(1000 * atoi(args[1]), 1); } #ifdef TERMINFO else if (!strcmp(args[0], "termcapinfo") || !strcmp(args[0], "terminfo")) #else else if (!strcmp(args[0], "termcapinfo") || !strcmp(args[0], "termcap")) #endif { if (!display) continue; if (argc < 3 || argc > 4) { Msg(0, "%s: %s: incorrect number of arguments.", rc_name, args[0]); continue; } for (p = args[1]; p && *p; p = cp) { if ((cp = index(p, '|')) != 0) *cp++ = '\0'; len = strlen(p); if (p[len - 1] == '*') { if (!(len - 1) || !strncmp(p, D_termname, len - 1)) break; } else if (!strcmp(p, D_termname)) break; } if (!(p && *p)) continue; extra_incap = CatExtra(args[2], extra_incap); if (argc == 4) extra_outcap = CatExtra(args[3], extra_outcap); } else if (!strcmp(args[0], "source")) { if (rc_recursion <= 10) { rc_recursion++; (void)StartRc(args[1], 0); rc_recursion--; } } } fclose(fp); Free(rc_name); rc_name = oldrc_name; return 0; } void FinishRc(rcfilename) char *rcfilename; { char buf[2048]; FILE *fp; char *oldrc_name = rc_name; rc_name = findrcfile(rcfilename); if (rc_name == NULL || (fp = secfopen(rc_name, "r")) == NULL) { const char *rc_nonnull = rc_name ? rc_name : rcfilename; if (rc_recursion) Msg(errno, "%s: source %s", oldrc_name, rc_nonnull); else if (RcFileName && !strcmp(RcFileName, rc_nonnull)) { /* * User explicitly gave us that name, * this is the only case, where we get angry, if we can't read * the file. */ debug3("FinishRc:'%s','%s','%s'\n", RcFileName, rc_name ? rc_name : "(null)", rcfilename); Panic(0, "Unable to open \"%s\".", rc_nonnull); /* NOTREACHED */ } debug1("FinishRc: '%s' no good. ignored\n", rc_nonnull); if (rc_name) Free(rc_name); rc_name = oldrc_name; return; } debug("finishrc is going...\n"); while (fgets(buf, sizeof buf, fp) != NULL) RcLine(buf, sizeof buf); (void) fclose(fp); Free(rc_name); rc_name = oldrc_name; } void do_source(rcfilename) char *rcfilename; { if (rc_recursion > 10) { Msg(0, "%s: source: recursion limit reached", rc_name); return; } rc_recursion++; FinishRc(rcfilename); rc_recursion--; } /* * Running a Command Line in the environment determined by the display. * The fore window is taken from the display as well as the user. * This is bad when we run detached. */ void RcLine(ubuf, ubufl) char *ubuf; int ubufl; { char *args[MAXARGS]; int argl[MAXARGS]; #ifdef MULTIUSER extern struct acluser *EffectiveAclUser; /* acl.c */ extern struct acluser *users; /* acl.c */ #endif if (display) { fore = D_fore; flayer = D_forecv->c_layer; } else flayer = fore ? fore->w_savelayer : 0; if (Parse(ubuf, ubufl, args, argl) <= 0) return; #ifdef MULTIUSER if (!display) { /* the session owner does it, when there is no display here */ EffectiveAclUser = users; debug("RcLine: WARNING, no display no user! Session owner executes command\n"); } #endif DoCommand(args, argl); #ifdef MULTIUSER EffectiveAclUser = 0; #endif } /* * needs display for copybuffer access and termcap dumping */ void WriteFile(user, fn, dump) struct acluser *user; char *fn; int dump; { /* dump==0: create .termcap, * dump==1: hardcopy, * #ifdef COPY_PASTE * dump==2: BUFFERFILE * #endif COPY_PASTE * dump==1: scrollback, */ register int i, j, k; register char *p; register FILE *f; char fnbuf[1024]; char *mode = "w"; #ifdef COPY_PASTE int public = 0; # ifdef _MODE_T mode_t old_umask; # else int old_umask; # endif # ifdef HAVE_LSTAT struct stat stb, stb2; int fd, exists = 0; # endif #endif switch (dump) { case DUMP_TERMCAP: if (fn == 0) { i = SockName - SockPath; if (i > (int)sizeof(fnbuf) - 9) i = 0; strncpy(fnbuf, SockPath, i); strcpy(fnbuf + i, ".termcap"); fn = fnbuf; } break; case DUMP_HARDCOPY: case DUMP_SCROLLBACK: if (fn == 0) { if (fore == 0) return; if (hardcopydir && *hardcopydir && strlen(hardcopydir) < sizeof(fnbuf) - 21) sprintf(fnbuf, "%s/hardcopy.%d", hardcopydir, fore->w_number); else sprintf(fnbuf, "hardcopy.%d", fore->w_number); fn = fnbuf; } if (hardcopy_append && !access(fn, W_OK)) mode = "a"; break; #ifdef COPY_PASTE case DUMP_EXCHANGE: if (fn == 0) { strncpy(fnbuf, BufferFile, sizeof(fnbuf) - 1); fnbuf[sizeof(fnbuf) - 1] = 0; fn = fnbuf; } public = !strcmp(fn, DEFAULT_BUFFERFILE); # ifdef HAVE_LSTAT exists = !lstat(fn, &stb); if (public && exists && (S_ISLNK(stb.st_mode) || stb.st_nlink > 1)) { Msg(0, "No write to links, please."); return; } # endif break; #endif } debug2("WriteFile(%d) %s\n", dump, fn); if (UserContext() > 0) { debug("Writefile: usercontext\n"); #ifdef COPY_PASTE if (dump == DUMP_EXCHANGE && public) { old_umask = umask(0); # ifdef HAVE_LSTAT if (exists) { if ((fd = open(fn, O_WRONLY, 0666)) >= 0) { if (fstat(fd, &stb2) == 0 && stb.st_dev == stb2.st_dev && stb.st_ino == stb2.st_ino) ftruncate(fd, 0); else { close(fd); fd = -1; } } } else fd = open(fn, O_WRONLY|O_CREAT|O_EXCL, 0666); f = fd >= 0 ? fdopen(fd, mode) : 0; # else f = fopen(fn, mode); # endif umask(old_umask); } else #endif /* COPY_PASTE */ f = fopen(fn, mode); if (f == NULL) { debug2("WriteFile: fopen(%s,\"%s\") failed\n", fn, mode); UserReturn(0); } else { switch (dump) { case DUMP_HARDCOPY: case DUMP_SCROLLBACK: if (!fore) break; if (*mode == 'a') { putc('>', f); for (j = fore->w_width - 2; j > 0; j--) putc('=', f); fputs("<\n", f); } if (dump == DUMP_SCROLLBACK) { #ifdef COPY_PASTE for (i = 0; i < fore->w_histheight; i++) { p = (char *)(WIN(i)->image); for (k = fore->w_width - 1; k >= 0 && p[k] == ' '; k--) ; for (j = 0; j <= k; j++) putc(p[j], f); putc('\n', f); } #endif } for (i = 0; i < fore->w_height; i++) { p = (char *)fore->w_mlines[i].image; for (k = fore->w_width - 1; k >= 0 && p[k] == ' '; k--) ; for (j = 0; j <= k; j++) putc(p[j], f); putc('\n', f); } break; case DUMP_TERMCAP: if ((p = index(MakeTermcap(fore->w_aflag), '=')) != NULL) { fputs(++p, f); putc('\n', f); } break; #ifdef COPY_PASTE case DUMP_EXCHANGE: p = user->u_plop.buf; for (i = user->u_plop.len; i-- > 0; p++) if (*p == '\r' && (i == 0 || p[1] != '\n')) putc('\n', f); else putc(*p, f); break; #endif } (void) fclose(f); UserReturn(1); } } if (UserStatus() <= 0) Msg(0, "Cannot open \"%s\"", fn); else if (display && !*rc_name) { switch (dump) { case DUMP_TERMCAP: Msg(0, "Termcap entry written to \"%s\".", fn); break; case DUMP_HARDCOPY: case DUMP_SCROLLBACK: Msg(0, "Screen image %s to \"%s\".", (*mode == 'a') ? "appended" : "written", fn); break; #ifdef COPY_PASTE case DUMP_EXCHANGE: Msg(0, "Copybuffer written to \"%s\".", fn); #endif } } } #ifdef COPY_PASTE /* * returns an allocated buffer which holds a copy of the file named fn. * lenp (if nonzero) points to a location, where the buffer size should be * stored. */ char * ReadFile(fn, lenp) char *fn; int *lenp; { int i, l, size; char c, *bp, *buf; struct stat stb; ASSERT(lenp); debug1("ReadFile(%s)\n", fn); if ((i = secopen(fn, O_RDONLY, 0)) < 0) { Msg(errno, "no %s -- no slurp", fn); return NULL; } if (fstat(i, &stb)) { Msg(errno, "no good %s -- no slurp", fn); close(i); return NULL; } size = stb.st_size; if ((buf = malloc(size)) == NULL) { close(i); Msg(0, "%s", strnomem); return NULL; } errno = 0; if ((l = read(i, buf, size)) != size) { if (l < 0) l = 0; Msg(errno, "Got only %d bytes from %s", l, fn); close(i); } else { if (read(i, &c, 1) > 0) Msg(0, "Slurped only %d characters (of %d) into buffer - try again", l, size); else Msg(0, "Slurped %d characters into buffer", l); } close(i); *lenp = l; for (bp = buf; l-- > 0; bp++) if (*bp == '\n' && (bp == buf || bp[-1] != '\r')) *bp = '\r'; return buf; } void KillBuffers() { if (UserContext() > 0) UserReturn(unlink(BufferFile) ? errno : 0); errno = UserStatus(); Msg(errno, "%s %sremoved", BufferFile, errno ? "not " : ""); } #endif /* COPY_PASTE */ /* * (Almost) secure open and fopen... */ FILE * secfopen(name, mode) char *name; char *mode; { FILE *fi; #ifndef USE_SETEUID int flags, fd; #endif debug2("secfopen(%s, %s)\n", name, mode); #ifdef USE_SETEUID xseteuid(real_uid); xsetegid(real_gid); fi = fopen(name, mode); xseteuid(eff_uid); xsetegid(eff_gid); return fi; #else if (eff_uid == real_uid) return fopen(name, mode); if (mode[0] && mode[1] == '+') flags = O_RDWR; else flags = (mode[0] == 'r') ? O_RDONLY : O_WRONLY; if (mode[0] == 'w') flags |= O_CREAT | O_TRUNC; else if (mode[0] == 'a') flags |= O_CREAT | O_APPEND; else if (mode[0] != 'r') { errno = EINVAL; return 0; } if ((fd = secopen(name, flags, 0666)) < 0) return 0; if ((fi = fdopen(fd, mode)) == 0) { close(fd); return 0; } return fi; #endif } int secopen(name, flags, mode) char *name; int flags; int mode; { int fd; #ifndef USE_SETEUID int q; struct stat stb; #endif debug3("secopen(%s, 0x%x, 0%03o)\n", name, flags, mode); #ifdef USE_SETEUID xseteuid(real_uid); xsetegid(real_gid); fd = open(name, flags, mode); xseteuid(eff_uid); xsetegid(eff_gid); return fd; #else if (eff_uid == real_uid) return open(name, flags, mode); /* Truncation/creation is done in UserContext */ if ((flags & O_TRUNC) || ((flags & O_CREAT) && access(name, F_OK))) { if (UserContext() > 0) { if ((fd = open(name, flags, mode)) >= 0) { close(fd); UserReturn(0); } if (errno == 0) errno = EACCES; UserReturn(errno); } if ((q = UserStatus())) { if (q > 0) errno = q; return -1; } } if (access(name, F_OK)) return -1; if ((fd = open(name, flags & ~(O_TRUNC | O_CREAT), 0)) < 0) return -1; debug("open successful\n"); if (fstat(fd, &stb)) { close(fd); return -1; } debug("fstat successful\n"); if (stb.st_uid != real_uid) { switch (flags & (O_RDONLY | O_WRONLY | O_RDWR)) { case O_RDONLY: q = 0004; break; case O_WRONLY: q = 0002; break; default: q = 0006; break; } if ((stb.st_mode & q) != q) { debug1("secopen: permission denied (%03o)\n", stb.st_mode & 07777); close(fd); errno = EACCES; return -1; } } debug1("secopen ok - returning %d\n", fd); return fd; #endif } int printpipe(p, cmd) struct win *p; char *cmd; { int pi[2]; if (pipe(pi)) { WMsg(p, errno, "printing pipe"); return -1; } switch (fork()) { case -1: WMsg(p, errno, "printing fork"); return -1; case 0: display = p->w_pdisplay; displays = 0; #ifdef DEBUG if (dfp && dfp != stderr) fclose(dfp); #endif close(0); dup(pi[0]); closeallfiles(0); if (setgid(real_gid) || setuid(real_uid)) Panic(errno, "printpipe setuid"); #ifdef SIGPIPE signal(SIGPIPE, SIG_DFL); #endif execl("/bin/sh", "sh", "-c", cmd, (char *)0); Panic(errno, "/bin/sh"); default: break; } close(pi[0]); return pi[1]; } int readpipe(cmdv) char **cmdv; { int pi[2]; if (pipe(pi)) { Msg(errno, "pipe"); return -1; } switch (fork()) { case -1: Msg(errno, "fork"); return -1; case 0: displays = 0; #ifdef DEBUG if (dfp && dfp != stderr) fclose(dfp); #endif close(1); if (dup(pi[1]) != 1) { close(pi[1]); Panic(0, "dup"); } closeallfiles(1); if (setgid(real_gid) || setuid(real_uid)) { close(1); Panic(errno, "setuid/setgid"); } #ifdef SIGPIPE signal(SIGPIPE, SIG_DFL); #endif execvp(*cmdv, cmdv); close(1); Panic(errno, "%s", *cmdv); default: break; } close(pi[1]); return pi[0]; } screen-4.1.0/.iscreenrc0000644000175000017500000001516611642704565013034 0ustar abeabe# # A sample .screenrc which I use for everyday work. # # some of the commands commented out here, have been moved to # /local/etc/screenrc # # we want no password, right? #password # This will ask us for a password. password none # Same as not even mentioning it. #password 12Bz/9hNlPLZk # "1234" #password YahtrWblnJw # ypmatch jnweiger passwd. Well, ... :-) scrollback 200 # we have a 200 lines history buffer markkeys "@=\177:@=^C" # our mad facit-twist terminal buffer overflow... markkeys "h=^B:l=^F:\$=^E" # some missing emacs style bindings in copymode echo -n "booting screen" # let it flash, not horn! #vbell on # "vbell" don't work any longer, sorry. #vbell_msg " Wuff, Wuff!! " # this is the default message #bell "Bimmmel No. %" # sounds the bell and shows a message # we want to login all windows we create. #login on # "login", "nologin" don't work any longer, sorry 2. echo -n "." # we have no termcap entry for screen on the target machine? Well then # we tell a lie. term screen # would be the obvious default here. #term vt100 # screen will understand vt100 for 99%. # we want to survive hangups # note that the default setting is off now! autodetach on # when we open a window, where shall its CWD be? chdir # without argument it's my $HOME echo -n "." # I hate nonexisting status lines! Force screen to believe me. #hardstatus off # now some Terminal setup: # Printing in the leftmost column is not save. We express that fact as :LP@: # # Emacs tends to smear it's highlighted status bar across the screen, producing # ugly areas of bright background, if termcap is'nt perfectly sober. # Give a little :ms@: in the termcap, this may help. # # And who invented the initialisation for facit terminals? We tell him that # we non't like smooth scroll, by specifying :ti=\E[?l:. # \E[?3l 80 Zeichen # \E[?3h 132 Zeichen # LP Last column Printable # \E[A cursor up # \E[B cursor down # \E[?4h smooth scroll # \E[?4l jump scroll # \E[%dL insert %d lines # \E[K clear to end of line # cs \E[%i%d;%dr for twist and xterm # ms@ Move in Standout mode is NOT save. # WS our private variable, it declares that the terminal can # be resized by an escape-sequence # The termcap statement takes 2 or three parameters. First parameter lists # which TERMCAPs are affected by this statement. Second we specify changes # in screen's view of that terminals. Third we may specify some capabilities # that user-programs want to see in the $TERMCAP environment variable or in # screen's termcap entry. termcap vt* cl=\E[H\E[J\E[?1h:vi=\E[?35h:ve=\E[35l:ti=\E[?4l[vt100] termcap facit ti=\E[?4l[facit] termcap xterm* is=\E[r\E[m\E[2J\E[H\E[?7h\E[?1;4;6l:Z0=\E[?3h:Z1=\E[?3l echo -n "." # "\E(B", "\E(0", "\E(1", "\E(2", ... to switch between charsets. # screen internally emulates G1: "\E)..", G2: "\E*..", G3: "\E+.." # you can switch between them, with: # # code | switch to # ------+------ # ^O | G0 # ^N | G1 # \En | G2 # \Eo | G3 #termcap facit|vt100|xterm* G0 # how do we resize windows? under sunview, this is standard, but xterm # needs to be a specially hacked xterm, to make this work. termcap xterm* WS=\E[8;%d;%dt # ICL 6402 testing: termcap icl* G0:S0=\E$[start]:E0=\E%[end]:C0=j9kx5 GS=\E(0^O:GE=\E(B^O:G1=k:G2=l:G3=m:G4=j:GV=x:GH=q:GR=u:GL=t:GU=w:GD=v:GC=n # Flowcontrol produces trouble. ^S und ^Q will never reach screen, as our # terminals catch them locally. Who can explain that to me?: #flow on|off|auto [interrupt] # Long Lines get wrapped around (the back of your terminal). This is the # default for vt100. But now programs make different asumptions about your # terminal. You may find two linefeeds where you'd expect one, or you may # be confronted with a truncated line. Currently there is no fix, but pressing # C-A r and doing a redraw. #wrap on # the autoaka allows you to see the currently executing shell command in the # window name field. To use that, your shell prompt must contain ^[k^[\ or # you will see the string "(init)" as a name. # in my .cshrc I may use this for a wonderfull tcsh-prompt: # set prompt="%{^[k^[\\%}%h %c2(%m)%# " # # defining a shellaka that contains a pipe-symbol (|) activites the # autoaka feature. To the left of that | you specify a constant part of # your prompt as a trigger, to the right you may place a default string # as in shellaka '> |tc' # but beware! specifying a window name with the -t option has priority over # the autoaka mechanism. Although specifying -t "> |foo" will work. # shellaka tc # ... now a little bit of key bindings # In case we don't have write permission for /etc/utmp (no s-bit) # we create even local windows via rlogin. -> Et voila: a utmp-slot # utmp-slots are strongly recomended to keep sccs and talk happy. # (thus we have ^A# or. ^Ac for windowcreation with or without utmp-slot.) # but if we run suid-root, we produce all the rlogins with -ln, # as nobody shall refer to these pty's. bind '!' screen -ln -k faui41 rlogin faui41 bind '@' screen -ln -k vme2 rlogin faui4_vme2 #bind '#' screen -k faui43 bind '#' screen -ln -k faui43 rlogin faui43 bind '$' screen -ln -k faui44 rlogin faui44 bind '%' screen -ln -k faui45 rlogin faui45 bind '\^' screen -ln -k sup1 rlogin fausup1 bind '&' screen -ln -k sup2 rlogin fausup2 bind '*' screen -ln -k faui48 rlogin faui48 bind '(' screen -ln -k faui09 rlogin faui09 bind ')' screen -ln -k faui10 rlogin faui10 bind 'J' screen -ln -k 4j rlogin faui4j bind 'P' screen -ln -k 4p rlogin faui4p bind '^C' screen -ln -k 45c rlogin faui45c bind '^D' screen -ln -k 45d rlogin faui45d bind '^E' screen -ln -k 45e rlogin faui45e bind '^I' screen -ln -k 45i rlogin faui45i # these two are logIn and logOut. As a toggle is too stupid. #bind 'I' set login on #bind 'O' set login off bind 'L' # What happens, when you 'think emacs' and want to erase a whole # line? You type ^A^K right? Under screen it should be ^Aa^K. But... # killing the window would be a real punishment for a little mistyping. bind k #wow! I even amange to type ^Ak by accident. #bind ^k #bind K kill echo -n "." #screen 1:faui43 # My good old : syntax #screen -k faui43 # The way Wayne Davison thinks about it. #screen -ln -k faui43 # this one not logged in. #screen -ln 2:faui09 rlogin faui09 -l jnweiger # Finally another bonus feature for people using strange terminal settings like # different baud rate, etc. The next user will get standard settings # as ^[c is a reset sequence. #pow_detach_msg "" # is the default pow_detach_msg "c" echo "done." screen-4.1.0/list_generic.c0000644000175000017500000002462711642704565013673 0ustar abeabe/* Copyright (c) 2010 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net) * * 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, 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 (see the file COPYING); if not, see * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA * **************************************************************** */ #include "config.h" #include "screen.h" #include "list_generic.h" #include "layer.h" #include "extern.h" /* Deals with a generic list display */ extern struct layer *flayer; static void ListProcess __P((char **, int *)); static void ListAbort __P((void)); static void ListRedisplayLine __P((int, int, int, int)); static void ListClearLine __P((int, int, int, int)); static int ListRewrite __P((int, int, int, struct mchar *, int)); static int ListResize __P((int, int)); static void ListRestore __P((void)); static void ListFree __P((void *)); struct LayFuncs ListLf = { ListProcess, ListAbort, ListRedisplayLine, ListClearLine, ListRewrite, ListResize, ListRestore, ListFree }; /** Returns non-zero on success. */ struct ListData * glist_display(struct GenericList *list, const char *name) { struct ListData *ldata; if (InitOverlayPage(sizeof(struct ListData), &ListLf, 0)) return NULL; ldata = flayer->l_data; ldata->name = name; /* We do not SaveStr, since the strings should be all static literals */ ldata->list_fn = list; flayer->l_mode = 1; flayer->l_x = 0; flayer->l_y = flayer->l_height - 1; return ldata; } static void glist_decide_top(struct ListData *ldata) { int count = flayer->l_height - 5; /* 2 for header, 1 for footer */ struct ListRow *top = ldata->selected; for (; count && top != ldata->root; top = top->prev, count--) ; ldata->top = top; } static struct ListRow * glist_search_dir(struct ListData *ldata, struct ListRow *start, int dir) { struct ListRow *row = (dir == 1) ? start->next : start->prev; for (; row; row = (dir == 1) ? row->next : row->prev) if (ldata->list_fn->gl_matchrow(ldata, row, ldata->search)) return row; if (dir == 1) row = ldata->root; else { /* First, go to the end */ if (!start->next) row = start; else for (row = start->next; row->next; row = row->next) ; } for (; row != start; row = (dir == 1) ? row->next : row->prev) if (ldata->list_fn->gl_matchrow(ldata, row, ldata->search)) break; return row; } static void glist_search(char *buf, int len, char *data) { struct ListData *ldata = (struct ListData *)data; struct ListRow *row; if (ldata->search) Free(ldata->search); if (len > 0) ldata->search = SaveStr(buf); else return; for (row = ldata->selected; row; row = row->next) if (ldata->list_fn->gl_matchrow(ldata, row, ldata->search)) break; if (!row) for (row = ldata->root; row != ldata->selected; row = row->next) if (ldata->list_fn->gl_matchrow(ldata, row, ldata->search)) break; if (row == ldata->selected) return; ldata->selected = row; if (ldata->selected->y == -1) glist_decide_top(ldata); glist_display_all(ldata); } static void ListProcess(char **ppbuf, int *plen) { struct ListData *ldata = flayer->l_data; int count = 0; while (*plen > 0) { struct ListRow *old; unsigned char ch; if (!flayer->l_mouseevent.start && ldata->list_fn->gl_pinput && ldata->list_fn->gl_pinput(ldata, ppbuf, plen)) continue; ch = **ppbuf; ++*ppbuf; --*plen; if (flayer->l_mouseevent.start) { int r = LayProcessMouse(flayer, ch); if (r == -1) { LayProcessMouseSwitch(flayer, 0); continue; } else { if (r) ch = 0222; else continue; } } if (!ldata->selected) { *plen = 0; break; } old = ldata->selected; processchar: switch (ch) { case ' ': break; case '\r': case '\n': break; case 0220: /* up */ case 16: /* ^P */ case 'k': if (!ldata->selected->prev) /* There's no where to go */ break; ldata->selected = old->prev; break; case 0216: /* down */ case 14: /* ^N like emacs */ case 'j': if (!ldata->selected->next) /* Nothing to do */ break; ldata->selected = old->next; break; case 033: /* escape */ case 007: /* ^G */ ListAbort(); *plen = 0; return; case 0201: /* home */ case 0001: /* ^A */ ldata->selected = ldata->root; break; case 0205: /* end */ case 0005: /* ^E */ while (ldata->selected->next) ldata->selected = ldata->selected->next; if (ldata->selected->y != -1) { /* Both old and current selections are on the screen. So we can just * redraw these two affected rows. */ } break; case 0004: /* ^D (half-page down) */ case 0006: /* page-down, ^F */ count = (flayer->l_height - 4) >> (ch == 0004); for (; ldata->selected->next && --count; ldata->selected = ldata->selected->next) ; break; case 0025: /* ^U (half-page up) */ case 0002: /* page-up, ^B */ count = (flayer->l_height - 4) >> (ch == 0025); for (; ldata->selected->prev && --count; ldata->selected = ldata->selected->prev) ; break; case '/': /* start searching */ if (ldata->list_fn->gl_matchrow) { char *s; Input("Search: ", 80, INP_COOKED, glist_search, (char *)ldata, 0); if ((s = ldata->search)) { for (; *s; s++) { char *ss = s; int n = 1; LayProcess(&ss, &n); } } } break; /* The following deal with searching. */ case 'n': /* search next */ if (ldata->list_fn->gl_matchrow && ldata->search) ldata->selected = glist_search_dir(ldata, ldata->selected, 1); break; case 'N': /* search prev */ if (ldata->list_fn->gl_matchrow && ldata->search) ldata->selected = glist_search_dir(ldata, ldata->selected, -1); break; /* Now, mouse events. */ case 0222: if (flayer->l_mouseevent.start) { int button = flayer->l_mouseevent.buffer[0]; if (button == 'a') /* Scroll down */ ch = 'j'; else if (button == '`') /* Scroll up */ ch = 'k'; else if (button == ' ') /* Left click */ { int y = flayer->l_mouseevent.buffer[2]; struct ListRow *r = ldata->top; for (r = ldata->top; r && r->y != -1 && r->y != y; r = r->next) ; if (r && r->y == y) ldata->selected = r; ch = 0; } else ch = 0; LayProcessMouseSwitch(flayer, 0); if (ch) goto processchar; } else LayProcessMouseSwitch(flayer, 1); break; } if (old == ldata->selected) /* The selection didn't change */ continue; if (ldata->selected->y == -1) { /* We need to list all the rows, since we are scrolling down. But first, * find the top of the visible list. */ glist_decide_top(ldata); glist_display_all(ldata); } else { /* just redisplay the two lines. */ ldata->list_fn->gl_printrow(ldata, old); ldata->list_fn->gl_printrow(ldata, ldata->selected); flayer->l_y = ldata->selected->y; LaySetCursor(); } } } static void ListAbort(void) { LAY_CALL_UP(LRefreshAll(flayer, 0)); ExitOverlayPage(); } static void ListFree(void *d) { struct ListData *ldata = d; glist_remove_rows(ldata); if (ldata->list_fn->gl_free) ldata->list_fn->gl_free(ldata); if (ldata->search) Free(ldata->search); } static void ListRedisplayLine(int y, int xs, int xe, int isblank) { struct ListData *ldata; ASSERT(flayer); ldata = flayer->l_data; if (y < 0) { glist_display_all(ldata); return; } if (!isblank) LClearArea(flayer, xs, y, xe, y, 0, 0); if (ldata->top && y < ldata->top->y) ldata->list_fn->gl_printheader(ldata); else if (y + 1 == flayer->l_height) ldata->list_fn->gl_printfooter(ldata); else { struct ListRow *row; for (row = ldata->top; row && row->y != -1; row = row->next) if (row->y == y) { ldata->list_fn->gl_printrow(ldata, row); break; } } } static void ListClearLine(int y, int xs, int xe, int bce) { DefClearLine(y, xs, xe, bce); } static int ListRewrite(int y, int xs, int xe, struct mchar *rend, int doit) { return EXPENSIVE; } static int ListResize (int wi, int he) { if (wi < 10 || he < 5) return -1; flayer->l_width = wi; flayer->l_height = he; flayer->l_y = he - 1; return 0; } static void ListRestore (void) { DefRestore(); } struct ListRow * glist_add_row(struct ListData *ldata, void *data, struct ListRow *after) { struct ListRow *r = calloc(1, sizeof(struct ListRow)); r->data = data; if (after) { r->next = after->next; r->prev = after; after->next = r; if (r->next) r->next->prev = r; } else { r->next = ldata->root; if (ldata->root) ldata->root->prev = r; ldata->root = r; } return r; } void glist_remove_rows(struct ListData *ldata) { struct ListRow *row; for (row = ldata->root; row; ) { struct ListRow *r = row; row = row->next; ldata->list_fn->gl_freerow(ldata, r); free(r); } ldata->root = ldata->selected = ldata->top = NULL; } void glist_display_all(struct ListData *list) { int y; struct ListRow *row; LClearAll(flayer, 0); y = list->list_fn->gl_printheader(list); if (!list->top) list->top = list->root; if (!list->selected) list->selected = list->root; for (row = list->root; row != list->top; row = row->next) row->y = -1; for (row = list->top; row; row = row->next) { row->y = y++; if (!list->list_fn->gl_printrow(list, row)) { row->y = -1; y--; } if (y + 1 == flayer->l_height) break; } for (; row; row = row->next) row->y = -1; list->list_fn->gl_printfooter(list); if (list->selected && list->selected->y != -1) flayer->l_y = list->selected->y; else flayer->l_y = flayer->l_height - 1; LaySetCursor(); } void glist_abort(void) { ListAbort(); } screen-4.1.0/comm.c0000644000175000017500000002232411642704565012147 0ustar abeabe/* Copyright (c) 2008, 2009 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Micah Cowan (micah@cowan.name) * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net) * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Copyright (c) 1987 Oliver Laumann * #ifdef HAVE_BRAILLE * Modified by: * Authors: Hadi Bargi Rangin bargi@dots.physics.orst.edu * Bill Barry barryb@dots.physics.orst.edu * * Modifications Copyright (c) 1995 by * Science Access Project, Oregon State University. #endif * * 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, 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 (see the file COPYING); if not, see * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA * **************************************************************** */ #include "config.h" #include "acls.h" #include "comm.h" #define bcopy :-( /* or include screen.h here */ /* Must be in alpha order ! */ struct comm comms[RC_LAST + 1] = { #ifdef MULTIUSER { "acladd", ARGS_1234 }, { "aclchg", ARGS_23 }, { "acldel", ARGS_1 }, { "aclgrp", ARGS_12 }, { "aclumask", ARGS_1|ARGS_ORMORE }, #endif { "activity", ARGS_1 }, #ifdef MULTIUSER { "addacl", ARGS_1234 }, #endif { "allpartial", NEED_DISPLAY|ARGS_1 }, { "altscreen", ARGS_01 }, { "at", ARGS_2|ARGS_ORMORE }, #ifdef COLOR { "attrcolor", ARGS_12 }, #endif { "autodetach", ARGS_1 }, #ifdef AUTO_NUKE { "autonuke", NEED_DISPLAY|ARGS_1 }, #endif { "backtick", ARGS_1|ARGS_ORMORE }, #ifdef COLOR { "bce", NEED_FORE|ARGS_01 }, #endif #ifdef HAVE_BRAILLE /* keywords for braille display (bd) */ { "bd_bc_down", ARGS_0 }, { "bd_bc_left", ARGS_0 }, { "bd_bc_right", ARGS_0 }, { "bd_bc_up", ARGS_0 }, { "bd_bell", ARGS_01 }, { "bd_braille_table", ARGS_01 }, { "bd_eightdot", ARGS_01 }, { "bd_info", ARGS_01 }, { "bd_link", ARGS_01 }, { "bd_lower_left", ARGS_0 }, { "bd_lower_right", ARGS_0 }, { "bd_ncrc", ARGS_01 }, { "bd_port", ARGS_01 }, { "bd_scroll", ARGS_01 }, { "bd_skip", ARGS_01 }, { "bd_start_braille", ARGS_01 }, { "bd_type", ARGS_01 }, { "bd_upper_left", ARGS_0 }, { "bd_upper_right", ARGS_0 }, { "bd_width", ARGS_01 }, #endif { "bell", ARGS_01 }, { "bell_msg", ARGS_01 }, { "bind", ARGS_1|ARGS_ORMORE }, #ifdef MAPKEYS { "bindkey", ARGS_0|ARGS_ORMORE }, #endif { "blanker", NEED_DISPLAY|ARGS_0}, #ifdef BLANKER_PRG { "blankerprg", ARGS_0|ARGS_ORMORE }, #endif { "break", NEED_FORE|ARGS_01 }, { "breaktype", NEED_FORE|ARGS_01 }, #ifdef COPY_PASTE { "bufferfile", ARGS_01 }, #endif { "c1", NEED_FORE|ARGS_01 }, { "caption", ARGS_12 }, #ifdef MULTIUSER { "chacl", ARGS_23 }, #endif { "charset", NEED_FORE|ARGS_1 }, { "chdir", ARGS_01 }, #ifdef DW_CHARS { "cjkwidth", ARGS_01 }, #endif { "clear", NEED_FORE|ARGS_0 }, { "colon", NEED_LAYER|ARGS_01 }, { "command", NEED_DISPLAY|ARGS_02 }, #ifdef COPY_PASTE { "compacthist", ARGS_01 }, #endif { "console", NEED_FORE|ARGS_01 }, #ifdef COPY_PASTE { "copy", NEED_FORE|NEED_DISPLAY|ARGS_0 }, { "crlf", ARGS_01 }, #endif { "debug", ARGS_01 }, #ifdef AUTO_NUKE { "defautonuke", ARGS_1 }, #endif #ifdef COLOR { "defbce", ARGS_1 }, #endif { "defbreaktype", ARGS_01 }, { "defc1", ARGS_1 }, { "defcharset", ARGS_01 }, #ifdef ENCODINGS { "defencoding", ARGS_1 }, #endif { "defescape", ARGS_1 }, { "defflow", ARGS_12 }, { "defgr", ARGS_1 }, { "defhstatus", ARGS_01 }, #ifdef ENCODINGS { "defkanji", ARGS_1 }, #endif { "deflog", ARGS_1 }, #if defined(UTMPOK) && defined(LOGOUTOK) { "deflogin", ARGS_1 }, #endif { "defmode", ARGS_1 }, { "defmonitor", ARGS_1 }, { "defmousetrack", ARGS_1 }, #ifdef MULTI { "defnonblock", ARGS_1 }, #endif { "defobuflimit", ARGS_1 }, #ifdef COPY_PASTE { "defscrollback", ARGS_1 }, #endif { "defshell", ARGS_1 }, { "defsilence", ARGS_1 }, { "defslowpaste", ARGS_1 }, #ifdef UTF8 { "defutf8", ARGS_1 }, #endif { "defwrap", ARGS_1 }, { "defwritelock", ARGS_1 }, #ifdef DETACH { "detach", NEED_DISPLAY|ARGS_01 }, #endif { "digraph", NEED_LAYER|ARGS_012 }, { "dinfo", NEED_DISPLAY|ARGS_0 }, { "displays", NEED_LAYER|ARGS_0 }, { "dumptermcap", NEED_FORE|ARGS_0 }, { "echo", CAN_QUERY|ARGS_12 }, #ifdef ENCODINGS { "encoding", ARGS_12 }, #endif { "escape", ARGS_1 }, { "eval", ARGS_1|ARGS_ORMORE }, #ifdef PSEUDOS { "exec", ARGS_0|ARGS_ORMORE }, #endif { "fit", NEED_DISPLAY|ARGS_0 }, { "flow", NEED_FORE|ARGS_01 }, { "focus", NEED_DISPLAY|ARGS_01 }, { "focusminsize", ARGS_02 }, { "gr", NEED_FORE|ARGS_01 }, { "group", NEED_FORE|ARGS_01 }, { "hardcopy", NEED_FORE|ARGS_012 }, { "hardcopy_append", ARGS_1 }, { "hardcopydir", ARGS_01 }, { "hardstatus", ARGS_012 }, { "height", ARGS_0123 }, { "help", NEED_LAYER|ARGS_02 }, #ifdef COPY_PASTE { "history", NEED_DISPLAY|NEED_FORE|ARGS_0 }, #endif { "hstatus", NEED_FORE|ARGS_1 }, { "idle", ARGS_0|ARGS_ORMORE }, { "ignorecase", ARGS_01 }, { "info", CAN_QUERY|NEED_LAYER|ARGS_0 }, #ifdef ENCODINGS { "kanji", NEED_FORE|ARGS_12 }, #endif { "kill", NEED_FORE|ARGS_0 }, { "lastmsg", CAN_QUERY|NEED_DISPLAY|ARGS_0 }, { "layout", ARGS_1|ARGS_ORMORE}, { "license", NEED_LAYER|ARGS_0 }, #ifdef LOCK { "lockscreen", NEED_DISPLAY|ARGS_0 }, #endif { "log", NEED_FORE|ARGS_01 }, { "logfile", ARGS_012 }, #if defined(UTMPOK) && defined(LOGOUTOK) { "login", NEED_FORE|ARGS_01 }, #endif { "logtstamp", ARGS_012 }, #ifdef MAPKEYS { "mapdefault", NEED_DISPLAY|ARGS_0 }, { "mapnotnext", NEED_DISPLAY|ARGS_0 }, { "maptimeout", ARGS_01 }, #endif #ifdef COPY_PASTE { "markkeys", ARGS_1 }, #endif { "maxwin", ARGS_01 }, { "meta", NEED_LAYER|ARGS_0 }, { "monitor", NEED_FORE|ARGS_01 }, { "mousetrack", NEED_DISPLAY | ARGS_01 }, { "msgminwait", ARGS_1 }, { "msgwait", ARGS_1 }, #ifdef MULTIUSER { "multiuser", ARGS_1 }, #endif #ifdef NETHACK { "nethack", ARGS_1 }, #endif { "next", ARGS_0 }, #ifdef MULTI { "nonblock", NEED_DISPLAY|ARGS_01 }, #endif { "number", CAN_QUERY|NEED_FORE|ARGS_01 }, { "obuflimit", NEED_DISPLAY|ARGS_01 }, { "only", NEED_DISPLAY|ARGS_0 }, { "other", ARGS_0 }, { "partial", NEED_FORE|ARGS_01 }, #ifdef PASSWORD { "password", ARGS_01 }, #endif #ifdef COPY_PASTE { "paste", NEED_LAYER|ARGS_012 }, { "pastefont", ARGS_01 }, #endif { "pow_break", NEED_FORE|ARGS_01 }, #if defined(DETACH) && defined(POW_DETACH) { "pow_detach", NEED_DISPLAY|ARGS_0 }, { "pow_detach_msg", ARGS_01 }, #endif { "prev", ARGS_0 }, { "printcmd", ARGS_01 }, { "process", NEED_DISPLAY|ARGS_01 }, { "quit", ARGS_0 }, #ifdef COPY_PASTE { "readbuf", ARGS_0123 }, #endif { "readreg", ARGS_0|ARGS_ORMORE }, { "redisplay", NEED_DISPLAY|ARGS_0 }, { "register", ARGS_24 }, { "remove", NEED_DISPLAY|ARGS_0 }, #ifdef COPY_PASTE { "removebuf", ARGS_0 }, #endif { "rendition", ARGS_23 }, { "reset", NEED_FORE|ARGS_0 }, { "resize", NEED_DISPLAY|ARGS_0|ARGS_ORMORE }, { "screen", ARGS_0|ARGS_ORMORE }, #ifdef COPY_PASTE { "scrollback", NEED_FORE|ARGS_1 }, #endif { "select", CAN_QUERY|ARGS_01 }, { "sessionname", ARGS_01 }, { "setenv", ARGS_012 }, { "setsid", ARGS_1 }, { "shell", ARGS_1 }, { "shelltitle", ARGS_1 }, { "silence", NEED_FORE|ARGS_01 }, { "silencewait", ARGS_1 }, { "sleep", ARGS_1 }, { "slowpaste", NEED_FORE|ARGS_01 }, { "sorendition", ARGS_012 }, { "source", ARGS_1 }, { "split", NEED_DISPLAY|ARGS_01 }, { "startup_message", ARGS_1 }, { "stuff", NEED_LAYER|ARGS_012 }, #ifdef MULTIUSER { "su", NEED_DISPLAY|ARGS_012 }, #endif #ifdef BSDJOBS { "suspend", NEED_DISPLAY|ARGS_0 }, #endif { "term", ARGS_1 }, { "termcap", ARGS_23 }, { "termcapinfo", ARGS_23 }, { "terminfo", ARGS_23 }, { "time", CAN_QUERY|ARGS_01 }, { "title", CAN_QUERY|NEED_FORE|ARGS_01 }, { "umask", ARGS_1|ARGS_ORMORE }, { "unbindall", ARGS_0 }, { "unsetenv", ARGS_1 }, #ifdef UTF8 { "utf8", NEED_FORE|ARGS_012 }, #endif { "vbell", ARGS_01 }, { "vbell_msg", ARGS_01 }, { "vbellwait", ARGS_1 }, { "verbose", ARGS_01 }, { "version", ARGS_0 }, { "wall", NEED_DISPLAY|ARGS_1}, { "width", ARGS_0123 }, { "windowlist", ARGS_012 }, { "windows", CAN_QUERY|ARGS_0 }, { "wrap", NEED_FORE|ARGS_01 }, #ifdef COPY_PASTE { "writebuf", ARGS_0123 }, #endif { "writelock", NEED_FORE|ARGS_01 }, { "xoff", NEED_LAYER|ARGS_0 }, { "xon", NEED_LAYER|ARGS_0 }, #ifdef ZMODEM { "zmodem", ARGS_012 }, #endif { "zombie", ARGS_012 } }; screen-4.1.0/mark.c0000644000175000017500000010430211720315605012131 0ustar abeabe/* Copyright (c) 2008, 2009 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Micah Cowan (micah@cowan.name) * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net) * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Copyright (c) 1987 Oliver Laumann * * 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, 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 (see the file COPYING); if not, see * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA * **************************************************************** */ #include #include #include "config.h" #include "screen.h" #include "mark.h" #include "extern.h" #ifdef COPY_PASTE /* * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! * * WARNING: these routines use the global variables "fore" and * "flayer" to make things easier. * * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ static int is_letter __P((int)); static void nextword __P((int *, int *, int, int)); static int linestart __P((int)); static int lineend __P((int)); static int rem __P((int, int , int , int , int , char *, int)); static int eq __P((int, int )); static int MarkScrollDownDisplay __P((int)); static int MarkScrollUpDisplay __P((int)); static void MarkProcess __P((char **, int *)); static void MarkAbort __P((void)); static void MarkRedisplayLine __P((int, int, int, int)); static int MarkRewrite __P((int, int, int, struct mchar *, int)); extern struct layer *flayer; extern struct display *display, *displays; extern struct win *fore; extern struct mline mline_blank, mline_null; extern struct mchar mchar_so; #ifdef FONT int pastefont = 1; #endif struct LayFuncs MarkLf = { MarkProcess, MarkAbort, MarkRedisplayLine, DefClearLine, MarkRewrite, DefResize, DefRestore, 0 }; int join_with_cr = 0; int compacthist = 0; unsigned char mark_key_tab[256]; /* this array must be initialised first! */ static struct markdata *markdata; /* * VI like is_letter: 0 - whitespace * 1 - letter * 2 - other */ static int is_letter(c) char c; { if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' || c == '.' || c == '@' || c == ':' || c == '%' || c == '!' || c == '-' || c == '+') /* thus we can catch email-addresses as a word :-) */ return 1; else if (c != ' ') return 2; return 0; } static int linestart(y) int y; { register int x; register unsigned char *i; for (x = markdata->left_mar, i = WIN(y)->image + x; x < fore->w_width - 1; x++) if (*i++ != ' ') break; if (x == fore->w_width - 1) x = markdata->left_mar; return x; } static int lineend(y) int y; { register int x; register unsigned char *i; for (x = markdata->right_mar, i = WIN(y)->image + x; x >= 0; x--) if (*i-- != ' ') break; if (x < 0) x = markdata->left_mar; return x; } /* * nextchar sets *xp to the num-th occurrence of the target in the line. * * Returns -1 if the target doesn't appear num times, 0 otherwise. */ static int nextchar(int *xp, int *yp, int direction, char target, int num) { int width; /* width of the current window. */ int x; /* x coordinate of the current cursor position. */ int step; /* amount to increment x (+1 or -1) */ int adjust; /* Final adjustment of cursor position. */ char *displayed_line; /* Line in which search takes place. */ debug("nextchar\n"); x = *xp; step = 1; adjust = 0; width = fore->w_width; displayed_line = (char *)WIN(*yp) -> image; switch(direction) { case 't': adjust = -1; /* fall through */ case 'f': step = 1; break; case 'T': adjust = 1; /* fall through */ case 'F': step = -1; break; default: ASSERT(0); } x += step; debug1("ml->image = %s\n", displayed_line); debug2("num = %d, width = %d\n",num, width); debug2("x = %d target = %c\n", x, target ); for ( ;x>=0 && x <= width; x += step) { if (displayed_line[x] == target) { if (--num == 0) { *xp = x + adjust; return 0; } } } return -1; } /* * nextword calculates the cursor position of the num'th word. * If the cursor is on a word, it counts as the first. * NW_BACK: search backward * NW_ENDOFWORD: find the end of the word * NW_MUSTMOVE: move at least one char * NW_BIG: match WORDs not words */ #define NW_BACK (1<<0) #define NW_ENDOFWORD (1<<1) #define NW_MUSTMOVE (1<<2) #define NW_BIG (1<<3) static void nextword(xp, yp, flags, num) int *xp, *yp, flags, num; { int xx = fore->w_width, yy = fore->w_histheight + fore->w_height; register int sx, oq, q, x, y; struct mline *ml; x = *xp; y = *yp; sx = (flags & NW_BACK) ? -1 : 1; if ((flags & NW_ENDOFWORD) && (flags & NW_MUSTMOVE)) x += sx; ml = WIN(y); for (oq = -1; ; x += sx, oq = q) { if (x >= xx || x < 0) q = 0; else if (flags & NW_BIG) q = ml->image[x] == ' '; else q = is_letter(ml->image[x]); if (oq >= 0 && oq != q) { if (oq == 0 || !(flags & NW_ENDOFWORD)) *xp = x; else *xp = x-sx; *yp = y; if ((!(flags & NW_ENDOFWORD) && q) || ((flags & NW_ENDOFWORD) && oq)) { if (--num <= 0) return; } } if (x == xx) { x = -1; if (++y >= yy) return; ml = WIN(y); } else if (x < 0) { x = xx; if (--y < 0) return; ml = WIN(y); } } } /* * y1, y2 are WIN coordinates * * redisplay: 0 - just copy * 1 - redisplay + copy * 2 - count + copy, don't redisplay */ static int rem(x1, y1, x2, y2, redisplay, pt, yend) int x1, y1, x2, y2, redisplay, yend; char *pt; { int i, j, from, to, ry, c; int l = 0; unsigned char *im; struct mline *ml; #ifdef FONT int cf, font; unsigned char *fo; #endif markdata->second = 0; if (y2 < y1 || ((y2 == y1) && (x2 < x1))) { i = y2; y2 = y1; y1 = i; i = x2; x2 = x1; x1 = i; } ry = y1 - markdata->hist_offset; i = y1; if (redisplay != 2 && pt == 0 && ry <0) { i -= ry; ry = 0; } for (; i <= y2; i++, ry++) { if (redisplay != 2 && pt == 0 && ry > yend) break; ml = WIN(i); from = (i == y1) ? x1 : 0; if (from < markdata->left_mar) from = markdata->left_mar; for (to = fore->w_width, im = ml->image + to; to >= 0; to--) if (*im-- != ' ') break; if (i == y2 && x2 < to) to = x2; if (to > markdata->right_mar) to = markdata->right_mar; if (redisplay == 1 && from <= to && ry >=0 && ry <= yend) MarkRedisplayLine(ry, from, to, 0); if (redisplay != 2 && pt == 0) /* don't count/copy */ continue; j = from; #ifdef DW_CHARS if (dw_right(ml, j, fore->w_encoding)) j--; #endif im = ml->image + j; #ifdef FONT fo = ml->font + j; font = ASCII; #endif for (; j <= to; j++) { c = (unsigned char)*im++; #ifdef FONT cf = (unsigned char)*fo++; # ifdef UTF8 if (fore->w_encoding == UTF8) { c |= cf << 8; if (c == UCS_HIDDEN) continue; c = ToUtf8_comb(pt, c); l += c; if (pt) pt += c; continue; } # endif # ifdef DW_CHARS if (is_dw_font(cf)) { c = c << 8 | (unsigned char)*im++; fo++; j++; } # endif if (pastefont) { c = EncodeChar(pt, c | cf << 16, fore->w_encoding, &font); l += c; if (pt) pt += c; continue; } #endif /* FONT */ if (pt) *pt++ = c; l++; } #ifdef FONT if (pastefont && font != ASCII) { if (pt) { strcpy(pt, "\033(B"); pt += 3; } l += 3; } #endif if (i != y2 && (to != fore->w_width - 1 || ml->image[to + 1] == ' ')) { /* * this code defines, what glues lines together */ switch (markdata->nonl) { case 0: /* lines separated by newlines */ if (pt) *pt++ = '\r'; l++; if (join_with_cr) { if (pt) *pt++ = '\n'; l++; } break; case 1: /* nothing to separate lines */ break; case 2: /* lines separated by blanks */ if (pt) *pt++ = ' '; l++; break; case 3: /* seperate by comma, for csh junkies */ if (pt) *pt++ = ','; l++; break; } } } return l; } /* Check if two chars are identical. All digits are treated * as same. Used for GetHistory() */ static int eq(a, b) int a, b; { if (a == b) return 1; if (a == 0 || b == 0) return 1; if (a <= '9' && a >= '0' && b <= '9' && b >= '0') return 1; return 0; } /**********************************************************************/ int GetHistory() /* return value 1 if copybuffer changed */ { int i = 0, q = 0, xx, yy, x, y; unsigned char *linep; struct mline *ml; ASSERT(display && fore); x = fore->w_x; if (x >= fore->w_width) x = fore->w_width - 1; y = fore->w_y + fore->w_histheight; debug2("cursor is at x=%d, y=%d\n", x, y); ml = WIN(y); for (xx = x - 1, linep = ml->image + xx; xx >= 0; xx--) if ((q = *linep--) != ' ' ) break; debug3("%c at (%d,%d)\n", q, xx, y); for (yy = y - 1; yy >= 0; yy--) { ml = WIN(yy); linep = ml->image; if (xx < 0 || eq(linep[xx], q)) { /* line is matching... */ for (i = fore->w_width - 1, linep += i; i >= x; i--) if (*linep-- != ' ') break; if (i >= x) break; } } if (yy < 0) return 0; if (D_user->u_plop.buf) UserFreeCopyBuffer(D_user); if ((D_user->u_plop.buf = (char *)malloc((unsigned) (i - x + 2))) == NULL) { LMsg(0, "Not enough memory... Sorry."); return 0; } bcopy((char *)linep - i + x + 1, D_user->u_plop.buf, i - x + 1); D_user->u_plop.len = i - x + 1; #ifdef ENCODINGS D_user->u_plop.enc = fore->w_encoding; #endif return 1; } /**********************************************************************/ void MarkRoutine() { int x, y; ASSERT(fore && display && D_user); debug2("MarkRoutine called: fore nr %d, display %s\n", fore->w_number, D_usertty); if (InitOverlayPage(sizeof(*markdata), &MarkLf, 1)) return; flayer->l_encoding = fore->w_encoding; flayer->l_mode = 1; markdata = (struct markdata *)flayer->l_data; markdata->md_user = D_user; /* XXX: Correct? */ markdata->md_window = fore; markdata->second = 0; markdata->rep_cnt = 0; markdata->append_mode = 0; markdata->write_buffer = 0; markdata->nonl = 0; markdata->left_mar = 0; markdata->right_mar = fore->w_width - 1; markdata->hist_offset = fore->w_histheight; x = fore->w_x; y = D2W(fore->w_y); if (x >= fore->w_width) x = fore->w_width - 1; LGotoPos(flayer, x, W2D(y)); LMsg(0, "Copy mode - Column %d Line %d(+%d) (%d,%d)", x + 1, W2D(y + 1), fore->w_histheight, fore->w_width, fore->w_height); markdata->cx = markdata->x1 = x; markdata->cy = markdata->y1 = y; flayer->l_x = x; flayer->l_y = W2D(y); } static void MarkProcess(inbufp,inlenp) char **inbufp; int *inlenp; { char *inbuf, *pt; int inlen; int cx, cy, x2, y2, j, yend; int newcopylen = 0, od; int in_mark; int rep_cnt; struct acluser *md_user; /* char *extrap = 0, extrabuf[100]; */ markdata = (struct markdata *)flayer->l_data; fore = markdata->md_window; md_user = markdata->md_user; if (inbufp == 0) { MarkAbort(); return; } LGotoPos(flayer, markdata->cx, W2D(markdata->cy)); inbuf= *inbufp; inlen= *inlenp; pt = inbuf; in_mark = 1; while (in_mark && (inlen /* || extrap */)) { unsigned char ch = (unsigned char )*pt++; inlen--; if (flayer->l_mouseevent.start) { int r = LayProcessMouse(flayer, ch); if (r == -1) LayProcessMouseSwitch(flayer, 0); else { if (r) ch = 0222; else continue; } } od = mark_key_tab[(int)ch]; rep_cnt = markdata->rep_cnt; if (od >= '0' && od <= '9' && !markdata->f_cmd.flag) { if (rep_cnt < 1001 && (od != '0' || rep_cnt != 0)) { markdata->rep_cnt = 10 * rep_cnt + od - '0'; continue; /* * Now what is that 1001 here? Well, we have a screen with * 25 * 80 = 2000 characters. Movement is at most across the full * screen. This we do with word by word movement, as character by * character movement never steps over line boundaries. The most words * we can place on the screen are 1000 single letter words. Thus 1001 * is sufficient. Users with bigger screens never write in single letter * words, as they should be more advanced. jw. * Oh, wrong. We still give even the experienced user a factor of ten. */ } } cx = markdata->cx; cy = markdata->cy; if (markdata -> f_cmd.flag) { debug2("searching for %c:%d\n",od,rep_cnt); markdata->f_cmd.flag = 0; markdata->rep_cnt = 0; if (isgraph (od)) { markdata->f_cmd.target = od; rep_cnt = (rep_cnt) ? rep_cnt : 1; nextchar(&cx, &cy, markdata->f_cmd.direction, od, rep_cnt ); revto(cx, cy); continue; } } processchar: switch (od) { case 'f': /* fall through */ case 'F': /* fall through */ case 't': /* fall through */ case 'T': /* fall through */ /* * Set f_cmd to do a search on the next key stroke. * If we break, rep_cnt will be reset, so we * continue instead. It might be cleaner to * store the rep_count in f_cmd and * break here so later followon code will be * hit. */ markdata->f_cmd.flag = 1; markdata->f_cmd.direction = od; debug("entering char search\n"); continue; case ';': case ',': if (!markdata->f_cmd.target) break; if (!rep_cnt) rep_cnt = 1; nextchar(&cx, &cy, od == ';' ? markdata->f_cmd.direction : (markdata->f_cmd.direction ^ 0x20), markdata->f_cmd.target, rep_cnt ); revto(cx, cy); break; case 'o': case 'x': if (!markdata->second) break; markdata->cx = markdata->x1; markdata->cy = markdata->y1; markdata->x1 = cx; markdata->y1 = cy; revto(markdata->cx, markdata->cy); break; case '\014': /* CTRL-L Redisplay */ Redisplay(0); LGotoPos(flayer, cx, W2D(cy)); break; case 0202: /* M-C-b */ case '\010': /* CTRL-H Backspace */ case 'h': if (rep_cnt == 0) rep_cnt = 1; revto(cx - rep_cnt, cy); break; case 0216: /* M-C-p */ case '\016': /* CTRL-N */ case 'j': if (rep_cnt == 0) rep_cnt = 1; revto(cx, cy + rep_cnt); break; case '+': if (rep_cnt == 0) rep_cnt = 1; j = cy + rep_cnt; if (j > fore->w_histheight + fore->w_height - 1) j = fore->w_histheight + fore->w_height - 1; revto(linestart(j), j); break; case '-': if (rep_cnt == 0) rep_cnt = 1; cy -= rep_cnt; if (cy < 0) cy = 0; revto(linestart(cy), cy); break; case '^': revto(linestart(cy), cy); break; case '\n': revto(markdata->left_mar, cy + 1); break; case 0220: /* M-C-p */ case '\020': /* CTRL-P */ case 'k': if (rep_cnt == 0) rep_cnt = 1; revto(cx, cy - rep_cnt); break; case 0206: /* M-C-f */ case 'l': if (rep_cnt == 0) rep_cnt = 1; revto(cx + rep_cnt, cy); break; case '\001': /* CTRL-A from tcsh/emacs */ case '0': revto(markdata->left_mar, cy); break; case '\004': /* CTRL-D down half screen */ if (rep_cnt == 0) rep_cnt = (fore->w_height + 1) >> 1; revto_line(cx, cy + rep_cnt, W2D(cy)); break; case '$': revto(lineend(cy), cy); break; case '\022': /* CTRL-R emacs style backwards search */ ISearch(-1); in_mark = 0; break; case '\023': /* CTRL-S emacs style search */ ISearch(1); in_mark = 0; break; case '\025': /* CTRL-U up half screen */ if (rep_cnt == 0) rep_cnt = (fore->w_height + 1) >> 1; revto_line(cx, cy - rep_cnt, W2D(cy)); break; case '\007': /* CTRL-G show cursorpos */ if (markdata->left_mar == 0 && markdata->right_mar == fore->w_width - 1) LMsg(0, "Column %d Line %d(+%d)", cx+1, W2D(cy)+1, markdata->hist_offset); else LMsg(0, "Column %d(%d..%d) Line %d(+%d)", cx+1, markdata->left_mar+1, markdata->right_mar+1, W2D(cy)+1, markdata->hist_offset); break; case '\002': /* CTRL-B back one page */ if (rep_cnt == 0) rep_cnt = 1; rep_cnt *= fore->w_height; revto(cx, cy - rep_cnt); break; case '\006': /* CTRL-F forward one page */ if (rep_cnt == 0) rep_cnt = 1; rep_cnt *= fore->w_height; revto(cx, cy + rep_cnt); break; case '\005': /* CTRL-E scroll up */ if (rep_cnt == 0) rep_cnt = 1; rep_cnt = MarkScrollUpDisplay(rep_cnt); if (cy < D2W(0)) revto(cx, D2W(0)); else LGotoPos(flayer, cx, W2D(cy)); break; case '\031': /* CTRL-Y scroll down */ if (rep_cnt == 0) rep_cnt = 1; rep_cnt = MarkScrollDownDisplay(rep_cnt); if (cy > D2W(fore->w_height-1)) revto(cx, D2W(fore->w_height-1)); else LGotoPos(flayer, cx, W2D(cy)); break; case '@': /* it may be useful to have a key that does nothing */ break; case '%': rep_cnt--; /* rep_cnt is a percentage for the history buffer */ if (rep_cnt < 0) rep_cnt = 0; if (rep_cnt > 100) rep_cnt = 100; revto_line(markdata->left_mar, (rep_cnt * (fore->w_histheight + fore->w_height)) / 100, (fore->w_height - 1) / 2); break; case 0201: case 'g': rep_cnt = 1; /* FALLTHROUGH */ case 0205: case 'G': /* rep_cnt is here the WIN line number */ if (rep_cnt == 0) rep_cnt = fore->w_histheight + fore->w_height; revto_line(markdata->left_mar, --rep_cnt, (fore->w_height - 1) / 2); break; case 'H': revto(markdata->left_mar, D2W(0)); break; case 'M': revto(markdata->left_mar, D2W((fore->w_height - 1) / 2)); break; case 'L': revto(markdata->left_mar, D2W(fore->w_height - 1)); break; case '|': revto(--rep_cnt, cy); break; case 'w': if (rep_cnt == 0) rep_cnt = 1; nextword(&cx, &cy, NW_MUSTMOVE, rep_cnt); revto(cx, cy); break; case 'e': case 'E': if (rep_cnt == 0) rep_cnt = 1; nextword(&cx, &cy, NW_ENDOFWORD|NW_MUSTMOVE | (od == 'E' ? NW_BIG : 0), rep_cnt); revto(cx, cy); break; case 'b': case 'B': if (rep_cnt == 0) rep_cnt = 1; nextword(&cx, &cy, NW_BACK|NW_ENDOFWORD|NW_MUSTMOVE | (od == 'B' ? NW_BIG : 0), rep_cnt); revto(cx, cy); break; case 'a': markdata->append_mode = 1 - markdata->append_mode; debug1("append mode %d--\n", markdata->append_mode); LMsg(0, (markdata->append_mode) ? ":set append" : ":set noappend"); break; case 'v': case 'V': /* this sets start column to column 9 for VI :set nu users */ if (markdata->left_mar == 8) rep_cnt = 1; else rep_cnt = 9; /* FALLTHROUGH */ case 'c': case 'C': /* set start column (c) and end column (C) */ if (markdata->second) { rem(markdata->x1, markdata->y1, cx, cy, 1, (char *)0, fore->w_height-1); /* Hack */ markdata->second = 1; /* rem turns off second */ } rep_cnt--; if (rep_cnt < 0) rep_cnt = cx; if (od != 'C') { markdata->left_mar = rep_cnt; if (markdata->left_mar > markdata->right_mar) markdata->left_mar = markdata->right_mar; } else { markdata->right_mar = rep_cnt; if (markdata->left_mar > markdata->right_mar) markdata->right_mar = markdata->left_mar; } if (markdata->second) { markdata->cx = markdata->x1; markdata->cy = markdata->y1; revto(cx, cy); } if (od == 'v' || od == 'V') LMsg(0, (markdata->left_mar != 8) ? ":set nonu" : ":set nu"); break; case 'J': /* how do you join lines in VI ? */ markdata->nonl = (markdata->nonl + 1) % 4; switch (markdata->nonl) { case 0: if (join_with_cr) LMsg(0, "Multiple lines (CR/LF)"); else LMsg(0, "Multiple lines (LF)"); break; case 1: LMsg(0, "Lines joined"); break; case 2: LMsg(0, "Lines joined with blanks"); break; case 3: LMsg(0, "Lines joined with comma"); break; } break; case '/': Search(1); in_mark = 0; break; case '?': Search(-1); in_mark = 0; break; case 'n': Search(0); break; case 'N': markdata->isdir = -markdata->isdir; Search(0); markdata->isdir = -markdata->isdir; break; case 'y': case 'Y': if (markdata->second == 0) { revto(linestart(cy), cy); markdata->second++; cx = markdata->x1 = markdata->cx; cy = markdata->y1 = markdata->cy; } if (--rep_cnt > 0) revto(cx, cy + rep_cnt); revto(lineend(markdata->cy), markdata->cy); if (od == 'y') break; /* FALLTHROUGH */ case 'W': if (od == 'W') { if (rep_cnt == 0) rep_cnt = 1; if (!markdata->second) { nextword(&cx, &cy, NW_BACK|NW_ENDOFWORD, 1); revto(cx, cy); markdata->second++; cx = markdata->x1 = markdata->cx; cy = markdata->y1 = markdata->cy; } nextword(&cx, &cy, NW_ENDOFWORD, rep_cnt); revto(cx, cy); } cx = markdata->cx; cy = markdata->cy; /* FALLTHROUGH */ case 'A': if (od == 'A') markdata->append_mode = 1; /* FALLTHROUGH */ case '>': if (od == '>') markdata->write_buffer = 1; /* FALLTHROUGH */ case ' ': case '\r': if (!markdata->second) { markdata->second++; markdata->x1 = cx; markdata->y1 = cy; revto(cx, cy); LMsg(0, "First mark set - Column %d Line %d", cx+1, W2D(cy)+1); break; } else { int append_mode = markdata->append_mode; int write_buffer = markdata->write_buffer; x2 = cx; y2 = cy; newcopylen = rem(markdata->x1, markdata->y1, x2, y2, 2, (char *)0, 0); /* count */ if (md_user->u_plop.buf && !append_mode) UserFreeCopyBuffer(md_user); yend = fore->w_height - 1; if (fore->w_histheight - markdata->hist_offset < fore->w_height) { markdata->second = 0; yend -= MarkScrollUpDisplay(fore->w_histheight - markdata->hist_offset); } if (newcopylen > 0) { /* the +3 below is for : cr + lf + \0 */ if (md_user->u_plop.buf) md_user->u_plop.buf = realloc(md_user->u_plop.buf, (unsigned) (md_user->u_plop.len + newcopylen + 3)); else { md_user->u_plop.len = 0; md_user->u_plop.buf = malloc((unsigned) (newcopylen + 3)); } if (!md_user->u_plop.buf) { MarkAbort(); in_mark = 0; LMsg(0, "Not enough memory... Sorry."); md_user->u_plop.len = 0; md_user->u_plop.buf = 0; break; } if (append_mode) { switch (markdata->nonl) { /* * this code defines, what glues lines together */ case 0: if (join_with_cr) { md_user->u_plop.buf[md_user->u_plop.len] = '\r'; md_user->u_plop.len++; } md_user->u_plop.buf[md_user->u_plop.len] = '\n'; md_user->u_plop.len++; break; case 1: break; case 2: md_user->u_plop.buf[md_user->u_plop.len] = ' '; md_user->u_plop.len++; break; case 3: md_user->u_plop.buf[md_user->u_plop.len] = ','; md_user->u_plop.len++; break; } } md_user->u_plop.len += rem(markdata->x1, markdata->y1, x2, y2, markdata->hist_offset == fore->w_histheight, md_user->u_plop.buf + md_user->u_plop.len, yend); #ifdef ENCODINGS md_user->u_plop.enc = fore->w_encoding; #endif } if (markdata->hist_offset != fore->w_histheight) { LAY_CALL_UP(LRefreshAll(flayer, 0)); } ExitOverlayPage(); WindowChanged(fore, 'P'); if (append_mode) LMsg(0, "Appended %d characters to buffer", newcopylen); else LMsg(0, "Copied %d characters into buffer", md_user->u_plop.len); if (write_buffer) WriteFile(md_user, (char *)0, DUMP_EXCHANGE); in_mark = 0; break; } case 0222: if (flayer->l_mouseevent.start) { int button = flayer->l_mouseevent.buffer[0]; if (button == 'a') { /* Scroll down */ od = 'j'; } else if (button == '`') { /* Scroll up */ od = 'k'; } else if (button == ' ') { /* Left click */ cx = flayer->l_mouseevent.buffer[1]; cy = D2W(flayer->l_mouseevent.buffer[2]); revto(cx, cy); od = ' '; } else od = 0; LayProcessMouseSwitch(flayer, 0); if (od) goto processchar; } else LayProcessMouseSwitch(flayer, 1); break; default: MarkAbort(); LMsg(0, "Copy mode aborted"); in_mark = 0; break; } if (in_mark) /* markdata may be freed */ markdata->rep_cnt = 0; } if (in_mark) { flayer->l_x = markdata->cx; flayer->l_y = W2D(markdata->cy); } *inbufp = pt; *inlenp = inlen; } void revto(tx, ty) int tx, ty; { revto_line(tx, ty, -1); } /* tx, ty: WINDOW, line: DISPLAY */ void revto_line(tx, ty, line) int tx, ty, line; { int fx, fy; int x, y, t, revst, reven, qq, ff, tt, st, en, ce = 0; int ystart = 0, yend = fore->w_height-1; int i, ry; unsigned char *wi; struct mline *ml; struct mchar mc; if (tx < 0) tx = 0; else if (tx > fore->w_width - 1) tx = fore->w_width -1; if (ty < 0) ty = 0; else if (ty > fore->w_histheight + fore->w_height - 1) ty = fore->w_histheight + fore->w_height - 1; fx = markdata->cx; fy = markdata->cy; #ifdef DW_CHARS /* don't just move inside of a kanji, the user wants to see something */ ml = WIN(ty); if (ty == fy && fx + 1 == tx && dw_right(ml, tx, fore->w_encoding) && tx < D_width - 1) tx++; if (ty == fy && fx - 1 == tx && dw_right(ml, fx, fore->w_encoding) && tx) tx--; #endif markdata->cx = tx; markdata->cy = ty; /* * if we go to a position that is currently offscreen * then scroll the screen */ i = 0; if (line >= 0 && line < fore->w_height) i = W2D(ty) - line; else if (ty < markdata->hist_offset) i = ty - markdata->hist_offset; else if (ty > markdata->hist_offset + (fore->w_height - 1)) i = ty - markdata->hist_offset - (fore->w_height - 1); if (i > 0) yend -= MarkScrollUpDisplay(i); else if (i < 0) ystart += MarkScrollDownDisplay(-i); if (markdata->second == 0) { flayer->l_x = tx; flayer->l_y = W2D(ty); LGotoPos(flayer, tx, W2D(ty)); return; } qq = markdata->x1 + markdata->y1 * fore->w_width; ff = fx + fy * fore->w_width; /* "from" offset in WIN coords */ tt = tx + ty * fore->w_width; /* "to" offset in WIN coords*/ if (ff > tt) { st = tt; en = ff; x = tx; y = ty; } else { st = ff; en = tt; x = fx; y = fy; } if (st > qq) { st++; x++; } if (en < qq) en--; if (tt > qq) { revst = qq; reven = tt; } else { revst = tt; reven = qq; } ry = y - markdata->hist_offset; if (ry < ystart) { y += (ystart - ry); x = 0; st = y * fore->w_width; ry = ystart; } ml = WIN(y); for (t = st; t <= en; t++, x++) { if (x >= fore->w_width) { x = 0; y++, ry++; ml = WIN(y); } if (ry > yend) break; if (t == st || x == 0) { wi = ml->image + fore->w_width; for (ce = fore->w_width; ce >= 0; ce--, wi--) if (*wi != ' ') break; } if (x <= ce && x >= markdata->left_mar && x <= markdata->right_mar) { #ifdef DW_CHARS if (dw_right(ml, x, fore->w_encoding)) { if (t == revst) revst--; t--; x--; } #endif if (t >= revst && t <= reven) { mc = mchar_so; #ifdef FONT if (pastefont) mc.font = ml->font[x]; #endif mc.image = ml->image[x]; } else copy_mline2mchar(&mc, ml, x); #ifdef DW_CHARS if (dw_left(ml, x, fore->w_encoding)) { mc.mbcs = ml->image[x + 1]; LPutChar(flayer, &mc, x, W2D(y)); t++; } #endif LPutChar(flayer, &mc, x, W2D(y)); #ifdef DW_CHARS if (dw_left(ml, x, fore->w_encoding)) x++; #endif } } flayer->l_x = tx; flayer->l_y = W2D(ty); LGotoPos(flayer, tx, W2D(ty)); } static void MarkAbort() { int yend, redisp; debug("MarkAbort\n"); markdata = (struct markdata *)flayer->l_data; fore = markdata->md_window; yend = fore->w_height - 1; redisp = markdata->second; if (fore->w_histheight - markdata->hist_offset < fore->w_height) { markdata->second = 0; yend -= MarkScrollUpDisplay(fore->w_histheight - markdata->hist_offset); } if (markdata->hist_offset != fore->w_histheight) { LAY_CALL_UP(LRefreshAll(flayer, 0)); } else { rem(markdata->x1, markdata->y1, markdata->cx, markdata->cy, redisp, (char *)0, yend); } ExitOverlayPage(); WindowChanged(fore, 'P'); } static void MarkRedisplayLine(y, xs, xe, isblank) int y; /* NOTE: y is in DISPLAY coords system! */ int xs, xe; int isblank; { int wy, x, i, rm; int sta, sto, cp; /* NOTE: these 3 are in WINDOW coords system */ unsigned char *wi; struct mline *ml; struct mchar mchar_marked; if (y < 0) /* No special full page handling */ return; markdata = (struct markdata *)flayer->l_data; fore = markdata->md_window; mchar_marked = mchar_so; wy = D2W(y); ml = WIN(wy); if (markdata->second == 0) { if (dw_right(ml, xs, fore->w_encoding) && xs > 0) xs--; if (dw_left(ml, xe, fore->w_encoding) && xe < fore->w_width - 1) xe++; if (xs == 0 && y > 0 && wy > 0 && WIN(wy - 1)->image[flayer->l_width] == 0) LCDisplayLineWrap(flayer, ml, y, xs, xe, isblank); else LCDisplayLine(flayer, ml, y, xs, xe, isblank); return; } sta = markdata->y1 * fore->w_width + markdata->x1; sto = markdata->cy * fore->w_width + markdata->cx; if (sta > sto) { i=sta; sta=sto; sto=i; } cp = wy * fore->w_width + xs; rm = markdata->right_mar; for (x = fore->w_width, wi = ml->image + fore->w_width; x >= 0; x--, wi--) if (*wi != ' ') break; if (x < rm) rm = x; for (x = xs; x <= xe; x++, cp++) if (cp >= sta && x >= markdata->left_mar) break; #ifdef DW_CHARS if (dw_right(ml, x, fore->w_encoding)) x--; #endif if (x > xs) LCDisplayLine(flayer, ml, y, xs, x - 1, isblank); for (; x <= xe; x++, cp++) { if (cp > sto || x > rm) break; #ifdef FONT if (pastefont) mchar_marked.font = ml->font[x]; #endif mchar_marked.image = ml->image[x]; #ifdef DW_CHARS mchar_marked.mbcs = 0; if (dw_left(ml, x, fore->w_encoding)) { mchar_marked.mbcs = ml->image[x + 1]; cp++; } #endif LPutChar(flayer, &mchar_marked, x, y); #ifdef DW_CHARS if (dw_left(ml, x, fore->w_encoding)) x++; #endif } if (x <= xe) LCDisplayLine(flayer, ml, y, x, xe, isblank); } /* * This ugly routine is to speed up GotoPos() */ static int MarkRewrite(ry, xs, xe, rend, doit) int ry, xs, xe, doit; struct mchar *rend; { int dx, x, y, st, en, t, rm; unsigned char *i; struct mline *ml; struct mchar mchar_marked; mchar_marked = mchar_so; debug3("MarkRewrite %d, %d-%d\n", ry, xs, xe); markdata = (struct markdata *)flayer->l_data; fore = markdata->md_window; y = D2W(ry); ml = WIN(y); #ifdef UTF8 if (fore->w_encoding && fore->w_encoding != UTF8 && D_encoding == UTF8 && ContainsSpecialDeffont(ml, xs, xe, fore->w_encoding)) return EXPENSIVE; #endif dx = xe - xs + 1; if (doit) { i = ml->image + xs; while (dx--) PUTCHAR(*i++); return 0; } if (markdata->second == 0) st = en = -1; else { st = markdata->y1 * fore->w_width + markdata->x1; en = markdata->cy * fore->w_width + markdata->cx; if (st > en) { t = st; st = en; en = t; } } t = y * fore->w_width + xs; for (rm = fore->w_width, i = ml->image + fore->w_width; rm >= 0; rm--) if (*i-- != ' ') break; if (rm > markdata->right_mar) rm = markdata->right_mar; x = xs; while (dx--) { if (t >= st && t <= en && x >= markdata->left_mar && x <= rm) { #ifdef FONT if (pastefont) mchar_marked.font = ml->font[x]; #endif rend->image = mchar_marked.image; if (!cmp_mchar(rend, &mchar_marked)) return EXPENSIVE; } else { rend->image = ml->image[x]; if (!cmp_mchar_mline(rend, ml, x)) return EXPENSIVE; } x++; } return xe - xs + 1; } /* * scroll the screen contents up/down. */ static int MarkScrollUpDisplay(n) int n; { int i; debug1("MarkScrollUpDisplay(%d)\n", n); if (n <= 0) return 0; if (n > fore->w_histheight - markdata->hist_offset) n = fore->w_histheight - markdata->hist_offset; markdata->hist_offset += n; i = (n < flayer->l_height) ? n : (flayer->l_height); LScrollV(flayer, i, 0, flayer->l_height - 1, 0); while (i-- > 0) MarkRedisplayLine(flayer->l_height - i - 1, 0, flayer->l_width - 1, 1); return n; } static int MarkScrollDownDisplay(n) int n; { int i; debug1("MarkScrollDownDisplay(%d)\n", n); if (n <= 0) return 0; if (n > markdata->hist_offset) n = markdata->hist_offset; markdata->hist_offset -= n; i = (n < flayer->l_height) ? n : (flayer->l_height); LScrollV(flayer, -i, 0, fore->w_height - 1, 0); while (i-- > 0) MarkRedisplayLine(i, 0, flayer->l_width - 1, 1); return n; } void MakePaster(pa, buf, len, bufiscopy) struct paster *pa; char *buf; int len; int bufiscopy; { FreePaster(pa); pa->pa_pasteptr = buf; pa->pa_pastelen = len; if (bufiscopy) pa->pa_pastebuf = buf; pa->pa_pastelayer = flayer; DoProcess(Layer2Window(flayer), &pa->pa_pasteptr, &pa->pa_pastelen, pa); } void FreePaster(pa) struct paster *pa; { if (pa->pa_pastebuf) free(pa->pa_pastebuf); pa->pa_pastebuf = 0; pa->pa_pasteptr = 0; pa->pa_pastelen = 0; pa->pa_pastelayer = 0; evdeq(&pa->pa_slowev); } #endif /* COPY_PASTE */ screen-4.1.0/resize.c0000644000175000017500000006125111732171225012506 0ustar abeabe/* Copyright (c) 2008, 2009 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Micah Cowan (micah@cowan.name) * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net) * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Copyright (c) 1987 Oliver Laumann * * 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, 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 (see the file COPYING); if not, see * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA * **************************************************************** */ #include #include #ifndef sun #include #endif #ifdef ISC # include # include # include #endif #include "config.h" #include "screen.h" #include "extern.h" static void CheckMaxSize __P((int)); static void FreeMline __P((struct mline *)); static int AllocMline __P((struct mline *ml, int)); static void MakeBlankLine __P((unsigned char *, int)); static void kaablamm __P((void)); static int BcopyMline __P((struct mline *, int, struct mline *, int, int, int)); static void SwapAltScreen __P((struct win *)); extern struct layer *flayer; extern struct display *display, *displays; extern unsigned char *blank, *null; extern struct mline mline_blank, mline_null, mline_old; extern struct win *windows; extern int Z0width, Z1width; extern int captionalways; #if defined(TIOCGWINSZ) || defined(TIOCSWINSZ) struct winsize glwz; #endif static struct mline mline_zero = { (unsigned char *)0, (unsigned char *)0 #ifdef FONT ,(unsigned char *)0 #endif #ifdef COLOR ,(unsigned char *)0 # ifdef COLORS256 ,(unsigned char *)0 # endif #endif }; /* * ChangeFlag: 0: try to modify no window * 1: modify fore (and try to modify no other) + redisplay * 2: modify all windows * * Note: Activate() is only called if change_flag == 1 * i.e. on a WINCH event */ void CheckScreenSize(change_flag) int change_flag; { int wi, he; if (display == 0) { debug("CheckScreenSize: No display -> no check.\n"); return; } #ifdef TIOCGWINSZ if (ioctl(D_userfd, TIOCGWINSZ, (char *)&glwz) != 0) { debug2("CheckScreenSize: ioctl(%d, TIOCGWINSZ) errno %d\n", D_userfd, errno); wi = D_CO; he = D_LI; } else { wi = glwz.ws_col; he = glwz.ws_row; if (wi == 0) wi = D_CO; if (he == 0) he = D_LI; } #else wi = D_CO; he = D_LI; #endif debug2("CheckScreenSize: screen is (%d,%d)\n", wi, he); #if 0 /* XXX: Fixme */ if (change_flag == 2) { debug("Trying to adapt all windows (-A)\n"); for (p = windows; p; p = p->w_next) if (p->w_display == 0 || p->w_display == display) ChangeWindowSize(p, wi, he, p->w_histheight); } #endif if (D_width == wi && D_height == he) { debug("CheckScreenSize: No change -> return.\n"); return; } #ifdef BLANKER_PRG KillBlanker(); #endif ResetIdle(); ChangeScreenSize(wi, he, change_flag); /* XXX Redisplay logic */ #if 0 if (change_flag == 1) Redisplay(D_fore ? D_fore->w_norefresh : 0); #endif } void ChangeScreenSize(wi, he, change_fore) int wi, he; int change_fore; { struct win *p; struct canvas *cv; int wwi; debug2("ChangeScreenSize from (%d,%d) ", D_width, D_height); debug3("to (%d,%d) (change_fore: %d)\n",wi, he, change_fore); cv = &D_canvas; cv->c_xe = wi - 1; cv->c_ye = he - 1 - ((cv->c_slperp && cv->c_slperp->c_slnext) || captionalways) - (D_has_hstatus == HSTATUS_LASTLINE); cv->c_blank.l_height = cv->c_ye - cv->c_ys + 1; if (cv->c_slperp) { ResizeCanvas(cv); RecreateCanvasChain(); RethinkDisplayViewports(); } if (D_forecv == 0) D_forecv = D_cvlist; if (D_forecv) D_fore = Layer2Window(D_forecv->c_layer); D_width = wi; D_height = he; CheckMaxSize(wi); if (D_CWS) { D_defwidth = D_CO; D_defheight = D_LI; } else { if (D_CZ0 && (wi == Z0width || wi == Z1width) && (D_CO == Z0width || D_CO == Z1width)) D_defwidth = D_CO; else D_defwidth = wi; D_defheight = he; } debug2("Default size: (%d,%d)\n", D_defwidth, D_defheight); if (change_fore) ResizeLayersToCanvases(); if (change_fore == 2 && D_CWS == NULL && displays->d_next == 0) { /* adapt all windows - to be removed ? */ for (p = windows; p; p = p->w_next) { debug1("Trying to change window %d.\n", p->w_number); wwi = wi; #if 0 if (D_CZ0 && p->w_width != wi && (wi == Z0width || wi == Z1width)) { if (p->w_width > (Z0width + Z1width) / 2) wwi = Z0width; else wwi = Z1width; } #endif if (p->w_savelayer && p->w_savelayer->l_cvlist == 0) ResizeLayer(p->w_savelayer, wwi, he, 0); #if 0 ChangeWindowSize(p, wwi, he, p->w_histheight); #endif } } } void ResizeLayersToCanvases() { struct canvas *cv; struct layer *l; int lx, ly; debug("ResizeLayersToCanvases\n"); D_kaablamm = 0; for (cv = D_cvlist; cv; cv = cv->c_next) { l = cv->c_layer; if (l == 0) continue; debug("Doing canvas: "); if (l->l_width == cv->c_xe - cv->c_xs + 1 && l->l_height == cv->c_ye - cv->c_ys + 1) { debug("already fitting.\n"); continue; } if (!MayResizeLayer(l)) { debug("may not resize.\n"); } else { debug("doing resize.\n"); ResizeLayer(l, cv->c_xe - cv->c_xs + 1, cv->c_ye - cv->c_ys + 1, display); } /* normalize window, see screen.c */ lx = cv->c_layer->l_x; ly = cv->c_layer->l_y; if (ly + cv->c_yoff < cv->c_ys) { cv->c_yoff = cv->c_ys - ly; RethinkViewportOffsets(cv); } else if (ly + cv->c_yoff > cv->c_ye) { cv->c_yoff = cv->c_ye - ly; RethinkViewportOffsets(cv); } if (lx + cv->c_xoff < cv->c_xs) { int n = cv->c_xs - (lx + cv->c_xoff); if (n < (cv->c_xe - cv->c_xs + 1) / 2) n = (cv->c_xe - cv->c_xs + 1) / 2; if (cv->c_xoff + n > cv->c_xs) n = cv->c_xs - cv->c_xoff; cv->c_xoff += n; RethinkViewportOffsets(cv); } else if (lx + cv->c_xoff > cv->c_xe) { int n = lx + cv->c_xoff - cv->c_xe; if (n < (cv->c_xe - cv->c_xs + 1) / 2) n = (cv->c_xe - cv->c_xs + 1) / 2; if (cv->c_xoff - n + cv->c_layer->l_width - 1 < cv->c_xe) n = cv->c_xoff + cv->c_layer->l_width - 1 - cv->c_xe; cv->c_xoff -= n; RethinkViewportOffsets(cv); } } Redisplay(0); if (D_kaablamm) { kaablamm(); D_kaablamm = 0; } } int MayResizeLayer(l) struct layer *l; { int cvs = 0; debug("MayResizeLayer:\n"); for (; l; l = l->l_next) { if (l->l_cvlist) if (++cvs > 1 || l->l_cvlist->c_lnext) { debug1("may not - cvs %d\n", cvs); return 0; } } debug("may resize\n"); return 1; } /* * Easy implementation: rely on the fact that the only layers * supporting resize are Win and Blank. So just kill all overlays. * * This is a lot harder if done the right way... */ static void kaablamm() { Msg(0, "Aborted because of window size change."); } /* Kills non-resizable layers. */ #define RESIZE_OR_KILL_LAYERS(l, wi, he) do \ { \ struct layer *_last = NULL; \ flayer = (l); \ while (flayer->l_next) \ { \ if (LayResize(wi, he) == 0) \ { \ _last = flayer; \ flayer = flayer->l_next; \ } \ else \ { \ struct canvas *_cv; \ for (_cv = flayer->l_cvlist; _cv; _cv = _cv->c_lnext) \ _cv->c_display->d_kaablamm = 1; \ ExitOverlayPage(); \ if (_last) \ _last->l_next = flayer; \ } \ } \ /* We assume that the bottom-most layer, i.e. when flayer->l_next == 0, \ * is always resizable. Currently, WinLf and BlankLf can be the bottom-most layers. \ */ \ LayResize(wi, he); \ } while (0) void ResizeLayer(l, wi, he, norefdisp) struct layer *l; int wi, he; struct display *norefdisp; { struct win *p; struct canvas *cv; struct layer *oldflayer = flayer; struct display *d, *olddisplay = display; if (l->l_width == wi && l->l_height == he) return; p = Layer2Window(l); /* If 'flayer' and 'l' are for the same window, then we will not * restore 'flayer'. */ if (oldflayer && (l == oldflayer || Layer2Window(oldflayer) == p)) oldflayer = NULL; flayer = l; if (p) { /* It's a window layer. Kill the overlays on it in all displays. */ for (d = displays; d; d = d->d_next) for (cv = d->d_cvlist; cv; cv = cv->c_next) { if (p == Layer2Window(cv->c_layer)) { /* Canvas 'cv' on display 'd' shows this window. Remove any non-resizable * layers over it. */ RESIZE_OR_KILL_LAYERS(cv->c_layer, wi, he); } } } else { /* It's a Blank layer. Just kill the non-resizable overlays over it. */ RESIZE_OR_KILL_LAYERS(flayer, wi, he); } for (display = displays; display; display = display->d_next) { if (display == norefdisp) continue; for (cv = D_cvlist; cv; cv = cv->c_next) if (Layer2Window(cv->c_layer) == p) { CV_CALL(cv, LayRedisplayLine(-1, -1, -1, 0)); RefreshArea(cv->c_xs, cv->c_ys, cv->c_xe, cv->c_ye, 0); } if (D_kaablamm) { kaablamm(); D_kaablamm = 0; } } /* If we started resizing a non-flayer layer, then restore the flayer. * Otherwise, flayer should already be updated to the topmost foreground layer. */ if (oldflayer) flayer = oldflayer; display = olddisplay; } static void FreeMline(ml) struct mline *ml; { if (ml->image) free(ml->image); if (ml->attr && ml->attr != null) free(ml->attr); #ifdef FONT if (ml->font && ml->font != null) free(ml->font); #endif #ifdef COLOR if (ml->color && ml->color != null) free(ml->color); # ifdef COLORS256 if (ml->colorx && ml->colorx != null) free(ml->colorx); # endif #endif *ml = mline_zero; } static int AllocMline(ml, w) struct mline *ml; int w; { ml->image = malloc(w); ml->attr = null; #ifdef FONT ml->font = null; #endif #ifdef COLOR ml->color = null; # ifdef COLORS256 ml->colorx = null; # endif #endif if (ml->image == 0) return -1; return 0; } static int BcopyMline(mlf, xf, mlt, xt, l, w) struct mline *mlf, *mlt; int xf, xt, l, w; { int r = 0; bcopy((char *)mlf->image + xf, (char *)mlt->image + xt, l); if (mlf->attr != null && mlt->attr == null) { if ((mlt->attr = (unsigned char *)calloc(w, 1)) == 0) mlt->attr = null, r = -1; } if (mlt->attr != null) bcopy((char *)mlf->attr + xf, (char *)mlt->attr + xt, l); #ifdef FONT if (mlf->font != null && mlt->font == null) { if ((mlt->font = (unsigned char *)calloc(w, 1)) == 0) mlt->font = null, r = -1; } if (mlt->font != null) bcopy((char *)mlf->font + xf, (char *)mlt->font + xt, l); #endif #ifdef COLOR if (mlf->color != null && mlt->color == null) { if ((mlt->color = (unsigned char *)calloc(w, 1)) == 0) mlt->color = null, r = -1; } if (mlt->color != null) bcopy((char *)mlf->color + xf, (char *)mlt->color + xt, l); # ifdef COLORS256 if (mlf->colorx != null && mlt->colorx == null) { if ((mlt->colorx = (unsigned char *)calloc(w, 1)) == 0) mlt->colorx = null, r = -1; } if (mlt->colorx != null) bcopy((char *)mlf->colorx + xf, (char *)mlt->colorx + xt, l); # endif #endif return r; } static int maxwidth; static void CheckMaxSize(wi) int wi; { unsigned char *oldnull = null; unsigned char *oldblank = blank; struct win *p; int i; struct mline *ml; wi = ((wi + 1) + 255) & ~255; if (wi <= maxwidth) return; maxwidth = wi; debug1("New maxwidth: %d\n", maxwidth); blank = (unsigned char *)xrealloc((char *)blank, maxwidth); null = (unsigned char *)xrealloc((char *)null, maxwidth); mline_old.image = (unsigned char *)xrealloc((char *)mline_old.image, maxwidth); mline_old.attr = (unsigned char *)xrealloc((char *)mline_old.attr, maxwidth); #ifdef FONT mline_old.font = (unsigned char *)xrealloc((char *)mline_old.font, maxwidth); #endif #ifdef COLOR mline_old.color = (unsigned char *)xrealloc((char *)mline_old.color, maxwidth); # ifdef COLORS256 mline_old.colorx = (unsigned char *)xrealloc((char *)mline_old.colorx, maxwidth); # endif #endif if (!(blank && null && mline_old.image && mline_old.attr IFFONT(&& mline_old.font) IFCOLOR(&& mline_old.color) IFCOLORX(&& mline_old.colorx))) Panic(0, "%s", strnomem); MakeBlankLine(blank, maxwidth); bzero((char *)null, maxwidth); mline_blank.image = blank; mline_blank.attr = null; mline_null.image = null; mline_null.attr = null; #ifdef FONT mline_blank.font = null; mline_null.font = null; #endif #ifdef COLOR mline_blank.color = null; mline_null.color = null; # ifdef COLORS256 mline_blank.colorx = null; mline_null.colorx = null; # endif #endif #define RESET_AFC(x, bl) do { if (x == old##bl) x = bl; } while (0) #define RESET_LINES(lines, count) \ do { \ ml = lines; \ for (i = 0; i < count; i++, ml++) \ { \ RESET_AFC(ml->image, blank); \ RESET_AFC(ml->attr, null); \ IFFONT(RESET_AFC(ml->font, null)); \ IFCOLOR(RESET_AFC(ml->color, null)); \ IFCOLORX(RESET_AFC(ml->colorx, null)); \ } \ } while (0) /* We have to run through all windows to substitute * the null and blank references. */ for (p = windows; p; p = p->w_next) { RESET_LINES(p->w_mlines, p->w_height); #ifdef COPY_PASTE RESET_LINES(p->w_hlines, p->w_histheight); RESET_LINES(p->w_alt.hlines, p->w_alt.histheight); #endif RESET_LINES(p->w_alt.mlines, p->w_alt.height); } } char * xrealloc(mem, len) char *mem; int len; { register char *nmem; if (mem == 0) return malloc(len); if ((nmem = realloc(mem, len))) return nmem; free(mem); return (char *)0; } static void MakeBlankLine(p, n) register unsigned char *p; register int n; { while (n--) *p++ = ' '; } #ifdef COPY_PASTE #define OLDWIN(y) ((y < p->w_histheight) \ ? &p->w_hlines[(p->w_histidx + y) % p->w_histheight] \ : &p->w_mlines[y - p->w_histheight]) #define NEWWIN(y) ((y < hi) ? &nhlines[y] : &nmlines[y - hi]) #else #define OLDWIN(y) (&p->w_mlines[y]) #define NEWWIN(y) (&nmlines[y]) #endif int ChangeWindowSize(p, wi, he, hi) struct win *p; int wi, he, hi; { struct mline *mlf = 0, *mlt = 0, *ml, *nmlines, *nhlines; int fy, ty, l, lx, lf, lt, yy, oty, addone; int ncx, ncy, naka, t; int y, shift; if (wi <= 0 || he <= 0) wi = he = hi = 0; if (p->w_type == W_TYPE_GROUP) return 0; if (wi > 1000) { Msg(0, "Window width too large. Truncated to 1000."); wi = 1000; } if (he > 1000) { Msg(0, "Window height too large. Truncated to 1000."); he = 1000; } if (p->w_width == wi && p->w_height == he && p->w_histheight == hi) { debug("ChangeWindowSize: No change.\n"); return 0; } CheckMaxSize(wi); /* XXX */ #if 0 /* just in case ... */ if (wi && (p->w_width != wi || p->w_height != he) && p->w_lay != &p->w_winlay) { debug("ChangeWindowSize: No resize because of overlay?\n"); return -1; } #endif debug("ChangeWindowSize"); debug3(" from (%d,%d)+%d", p->w_width, p->w_height, p->w_histheight); debug3(" to(%d,%d)+%d\n", wi, he, hi); fy = p->w_histheight + p->w_height - 1; ty = hi + he - 1; nmlines = nhlines = 0; ncx = 0; ncy = 0; naka = 0; if (wi) { if (wi != p->w_width || he != p->w_height) { if ((nmlines = (struct mline *)calloc(he, sizeof(struct mline))) == 0) { KillWindow(p); Msg(0, "%s", strnomem); return -1; } } else { debug1("image stays the same: %d lines\n", he); nmlines = p->w_mlines; fy -= he; ty -= he; ncx = p->w_x; ncy = p->w_y; naka = p->w_autoaka; } } #ifdef COPY_PASTE if (hi) { if ((nhlines = (struct mline *)calloc(hi, sizeof(struct mline))) == 0) { Msg(0, "No memory for history buffer - turned off"); hi = 0; ty = he - 1; } } #endif /* special case: cursor is at magic margin position */ addone = 0; if (p->w_width && p->w_x == p->w_width) { debug2("Special addone case: %d %d\n", p->w_x, p->w_y); addone = 1; p->w_x--; } /* handle the cursor and autoaka lines now if the widths are equal */ if (p->w_width == wi) { ncx = p->w_x + addone; ncy = p->w_y + he - p->w_height; /* never lose sight of the line with the cursor on it */ shift = -ncy; for (yy = p->w_y + p->w_histheight - 1; yy >= 0 && ncy + shift < he; yy--) { ml = OLDWIN(yy); if (!ml->image) break; if (ml->image[p->w_width] == ' ') break; shift++; } if (shift < 0) shift = 0; else debug1("resize: cursor out of bounds, shifting %d\n", shift); ncy += shift; if (p->w_autoaka > 0) { naka = p->w_autoaka + he - p->w_height + shift; if (naka < 1 || naka > he) naka = 0; } while (shift-- > 0) { ml = OLDWIN(fy); FreeMline(ml); fy--; } } debug2("fy %d ty %d\n", fy, ty); if (fy >= 0) mlf = OLDWIN(fy); if (ty >= 0) mlt = NEWWIN(ty); while (fy >= 0 && ty >= 0) { if (p->w_width == wi) { /* here is a simple shortcut: just copy over */ *mlt = *mlf; *mlf = mline_zero; if (--fy >= 0) mlf = OLDWIN(fy); if (--ty >= 0) mlt = NEWWIN(ty); continue; } /* calculate lenght */ for (l = p->w_width - 1; l > 0; l--) if (mlf->image[l] != ' ' || mlf->attr[l]) break; if (fy == p->w_y + p->w_histheight && l < p->w_x) l = p->w_x; /* cursor is non blank */ l++; lf = l; /* add wrapped lines to length */ for (yy = fy - 1; yy >= 0; yy--) { ml = OLDWIN(yy); if (ml->image[p->w_width] == ' ') break; l += p->w_width; } /* rewrap lines */ lt = (l - 1) % wi + 1; /* lf is set above */ oty = ty; while (l > 0 && fy >= 0 && ty >= 0) { lx = lt > lf ? lf : lt; if (mlt->image == 0) { if (AllocMline(mlt, wi + 1)) goto nomem; MakeBlankLine(mlt->image + lt, wi - lt); mlt->image[wi] = ((oty == ty) ? ' ' : 0); } if (BcopyMline(mlf, lf - lx, mlt, lt - lx, lx, wi + 1)) goto nomem; /* did we copy the cursor ? */ if (fy == p->w_y + p->w_histheight && lf - lx <= p->w_x && lf > p->w_x) { ncx = p->w_x + lt - lf + addone; ncy = ty - hi; shift = wi ? -ncy + (l - lx) / wi : 0; if (ty + shift > hi + he - 1) shift = hi + he - 1 - ty; if (shift > 0) { debug3("resize: cursor out of bounds, shifting %d [%d/%d]\n", shift, lt - lx, wi); for (y = hi + he - 1; y >= ty; y--) { mlt = NEWWIN(y); FreeMline(mlt); if (y - shift < ty) continue; ml = NEWWIN(y - shift); *mlt = *ml; *ml = mline_zero; } ncy += shift; ty += shift; mlt = NEWWIN(ty); if (naka > 0) naka = naka + shift > he ? 0 : naka + shift; } ASSERT(ncy >= 0); } /* did we copy autoaka line ? */ if (p->w_autoaka > 0 && fy == p->w_autoaka - 1 + p->w_histheight && lf - lx <= 0) naka = ty - hi >= 0 ? 1 + ty - hi : 0; lf -= lx; lt -= lx; l -= lx; if (lf == 0) { FreeMline(mlf); lf = p->w_width; if (--fy >= 0) mlf = OLDWIN(fy); } if (lt == 0) { lt = wi; if (--ty >= 0) mlt = NEWWIN(ty); } } ASSERT(l != 0 || fy == yy); } while (fy >= 0) { FreeMline(mlf); if (--fy >= 0) mlf = OLDWIN(fy); } while (ty >= 0) { if (AllocMline(mlt, wi + 1)) goto nomem; MakeBlankLine(mlt->image, wi + 1); if (--ty >= 0) mlt = NEWWIN(ty); } #ifdef DEBUG if (nmlines != p->w_mlines) for (fy = 0; fy < p->w_height + p->w_histheight; fy++) { ml = OLDWIN(fy); ASSERT(ml->image == 0); } #endif if (p->w_mlines && p->w_mlines != nmlines) free((char *)p->w_mlines); p->w_mlines = nmlines; #ifdef COPY_PASTE if (p->w_hlines && p->w_hlines != nhlines) free((char *)p->w_hlines); p->w_hlines = nhlines; #endif nmlines = nhlines = 0; /* change tabs */ if (p->w_width != wi) { if (wi) { t = p->w_tabs ? p->w_width : 0; p->w_tabs = xrealloc(p->w_tabs, wi + 1); if (p->w_tabs == 0) { nomem: if (nmlines) { for (ty = he + hi - 1; ty >= 0; ty--) { mlt = NEWWIN(ty); FreeMline(mlt); } if (nmlines && p->w_mlines != nmlines) free((char *)nmlines); #ifdef COPY_PASTE if (nhlines && p->w_hlines != nhlines) free((char *)nhlines); #endif } KillWindow(p); Msg(0, "%s", strnomem); return -1; } for (; t < wi; t++) p->w_tabs[t] = t && !(t & 7) ? 1 : 0; p->w_tabs[wi] = 0; } else { if (p->w_tabs) free(p->w_tabs); p->w_tabs = 0; } } /* Change w_saved.y - this is only an estimate... */ p->w_saved.y += ncy - p->w_y; p->w_x = ncx; p->w_y = ncy; if (p->w_autoaka > 0) p->w_autoaka = naka; /* do sanity checks */ if (p->w_x > wi) p->w_x = wi; if (p->w_y >= he) p->w_y = he - 1; if (p->w_saved.x > wi) p->w_saved.x = wi; if (p->w_saved.y < 0) p->w_saved.y = 0; if (p->w_saved.y >= he) p->w_saved.y = he - 1; if (p->w_alt.cursor.x > wi) p->w_alt.cursor.x = wi; if (p->w_alt.cursor.y >= he) p->w_alt.cursor.y = he - 1; /* reset scrolling region */ p->w_top = 0; p->w_bot = he - 1; /* signal new size to window */ #ifdef TIOCSWINSZ if (wi && (p->w_width != wi || p->w_height != he) && p->w_width != 0 && p->w_height != 0 && p->w_ptyfd >= 0 && p->w_pid) { glwz.ws_col = wi; glwz.ws_row = he; debug("Setting pty winsize.\n"); if (ioctl(p->w_ptyfd, TIOCSWINSZ, (char *)&glwz)) debug2("SetPtySize: errno %d (fd:%d)\n", errno, p->w_ptyfd); } #endif /* TIOCSWINSZ */ /* store new size */ p->w_width = wi; p->w_height = he; #ifdef COPY_PASTE p->w_histidx = 0; p->w_histheight = hi; #endif #ifdef BUILTIN_TELNET if (p->w_type == W_TYPE_TELNET) TelWindowSize(p); #endif #ifdef DEBUG /* Test if everything was ok */ for (fy = 0; fy < p->w_height + p->w_histheight; fy++) { ml = OLDWIN(fy); ASSERT(ml->image); # ifdef UTF8 if (p->w_encoding == UTF8) { for (l = 0; l < p->w_width; l++) ASSERT(ml->image[l] >= ' ' || ml->font[l]); } else #endif for (l = 0; l < p->w_width; l++) ASSERT(ml->image[l] >= ' '); } #endif return 0; } void FreeAltScreen(p) struct win *p; { int i; if (p->w_alt.mlines) { for (i = 0; i < p->w_alt.height; i++) FreeMline(p->w_alt.mlines + i); free(p->w_alt.mlines); } p->w_alt.mlines = 0; p->w_alt.width = 0; p->w_alt.height = 0; #ifdef COPY_PASTE if (p->w_alt.hlines) { for (i = 0; i < p->w_alt.histheight; i++) FreeMline(p->w_alt.hlines + i); free(p->w_alt.hlines); } p->w_alt.hlines = 0; p->w_alt.histidx = 0; p->w_alt.histheight = 0; #endif } static void SwapAltScreen(p) struct win *p; { struct mline *ml; int t; #define SWAP(item, t) do { (t) = p->w_alt. item; p->w_alt. item = p->w_##item; p->w_##item = (t); } while (0) SWAP(mlines, ml); SWAP(width, t); SWAP(height, t); #ifdef COPY_PASTE SWAP(histheight, t); SWAP(hlines, ml); SWAP(histidx, t); #endif #undef SWAP } void EnterAltScreen(p) struct win *p; { if (!p->w_alt.on) { /* If not already using the alternate screen buffer, then create a new one and swap it with the 'real' screen buffer. */ FreeAltScreen(p); SwapAltScreen(p); } else { /* Already using the alternate buffer. Just clear the screen. To do so, it is only necessary to reset the height(s) without resetting the width. */ p->w_height = 0; p->w_histheight = 0; } ChangeWindowSize(p, p->w_alt.width, p->w_alt.height, p->w_alt.histheight); p->w_alt.on = 1; } void LeaveAltScreen(p) struct win *p; { if (!p->w_alt.on) return; SwapAltScreen(p); ChangeWindowSize(p, p->w_alt.width, p->w_alt.height, p->w_alt.histheight); FreeAltScreen(p); p->w_alt.on = 0; } screen-4.1.0/display.h0000644000175000017500000002667211642704565012700 0ustar abeabe/* Copyright (c) 2008, 2009 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Micah Cowan (micah@cowan.name) * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net) * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Copyright (c) 1987 Oliver Laumann * * 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, 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 (see the file COPYING); if not, see * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA * **************************************************************** * $Id$ GNU */ #ifndef SCREEN_DISPLAY_H #define SCREEN_DISPLAY_H #include "layout.h" #include "canvas.h" #include "viewport.h" #ifdef MAPKEYS #define KMAP_KEYS (T_OCAPS-T_CAPS) #define KMAP_AKEYS (T_OCAPS-T_CURSOR) #define KMAP_NOTIMEOUT 0x4000 struct kmap_ext { char *str; int fl; struct action um; struct action dm; struct action mm; }; #else #define KMAP_KEYS 0 #endif struct win; /* forward declaration */ struct display { struct display *d_next; /* linked list */ struct acluser *d_user; /* user who owns that display */ struct canvas d_canvas; /* our canvas slice */ struct canvas *d_cvlist; /* the canvases of this display */ struct canvas *d_forecv; /* current input focus */ struct layout *d_layout; /* layout we're using */ void (*d_processinput) __P((char *, int)); char *d_processinputdata; /* data for processinput */ int d_vpxmin, d_vpxmax; /* min/max used position on display */ struct win *d_fore; /* pointer to fore window */ struct win *d_other; /* pointer to other window */ int d_nonblock; /* -1 don't block if obufmax reached */ /* >0: block after nonblock secs */ char d_termname[20 + 1]; /* $TERM */ char *d_tentry; /* buffer for tgetstr */ char d_tcinited; /* termcap inited flag */ int d_width, d_height; /* width/height of the screen */ int d_defwidth, d_defheight; /* default width/height of windows */ int d_top, d_bot; /* scrollregion start/end */ int d_x, d_y; /* cursor position */ struct mchar d_rend; /* current rendition */ int d_col16change; /* the 16col bits changed in attr */ char d_atyp; /* current attribute types */ #ifdef DW_CHARS int d_mbcs; /* saved char for multibytes charset */ #endif #ifdef ENCODINGS int d_encoding; /* what encoding type the display is */ int d_decodestate; /* state of our decoder */ int d_realfont; /* real font of terminal */ #endif int d_insert; /* insert mode flag */ int d_keypad; /* application keypad flag */ int d_cursorkeys; /* application cursorkeys flag */ int d_revvid; /* reverse video */ int d_curvis; /* cursor visibility */ int d_has_hstatus; /* display has hardstatus line */ int d_hstatus; /* hardstatus used */ int d_lp_missing; /* last character on bot line missing */ int d_mouse; /* mouse mode */ int d_mousetrack; /* set when user wants to use mouse even when the window does not */ #ifdef RXVT_OSC int d_xtermosc[4]; /* osc used */ #endif struct mchar d_lpchar; /* missing char */ struct timeval d_status_time; /* time of status display */ int d_status; /* is status displayed? */ char d_status_bell; /* is it only a vbell? */ int d_status_len; /* length of status line */ char *d_status_lastmsg; /* last displayed message */ int d_status_buflen; /* last message buffer len */ int d_status_lastx; /* position of the cursor */ int d_status_lasty; /* before status was displayed */ int d_status_obuflen; /* saved obuflen */ int d_status_obuffree; /* saved obuffree */ int d_status_obufpos; /* end of status position in obuf */ struct event d_statusev; /* timeout event */ struct event d_hstatusev; /* hstatus changed event */ int d_kaablamm; /* display kaablamm msg */ struct action *d_ESCseen; /* Was the last char an ESC (^a) */ int d_userpid; /* pid of attacher */ char d_usertty[MAXPATHLEN]; /* tty we are attached to */ int d_userfd; /* fd of the tty */ struct event d_readev; /* userfd read event */ struct event d_writeev; /* userfd write event */ struct event d_blockedev; /* blocked timeout */ struct mode d_OldMode; /* tty mode when screen was started */ struct mode d_NewMode; /* New tty mode */ int d_flow; /* tty's flow control on/off flag*/ int d_intrc; /* current intr when flow is on */ char *d_obuf; /* output buffer */ int d_obuflen; /* len of buffer */ int d_obufmax; /* len where we are blocking the pty */ int d_obuflenmax; /* len - max */ char *d_obufp; /* pointer in buffer */ int d_obuffree; /* free bytes in buffer */ #ifdef AUTO_NUKE int d_auto_nuke; /* autonuke flag */ #endif #ifdef MAPKEYS int d_nseqs; /* number of valid mappings */ int d_aseqs; /* number of allocated mappings */ unsigned char *d_kmaps; /* keymaps */ unsigned char *d_seqp; /* pointer into keymap array */ int d_seql; /* number of parsed chars */ unsigned char *d_seqh; /* last hit */ struct event d_mapev; /* timeout event */ int d_dontmap; /* do not map next */ int d_mapdefault; /* do map next to default */ #endif union tcu d_tcs[T_N]; /* terminal capabilities */ char *d_attrtab[NATTR]; /* attrib emulation table */ char d_attrtyp[NATTR]; /* attrib group table */ int d_hascolor; /* do we support color */ short d_dospeed; /* baudrate of tty */ #ifdef FONT char d_c0_tab[256]; /* conversion for C0 */ char ***d_xtable; /* char translation table */ #endif int d_UPcost, d_DOcost, d_LEcost, d_NDcost; int d_CRcost, d_IMcost, d_EIcost, d_NLcost; int d_printfd; /* fd for vt100 print sequence */ #ifdef UTMPOK slot_t d_loginslot; /* offset, where utmp_logintty belongs */ struct utmp d_utmp_logintty; /* here the original utmp structure is stored */ int d_loginttymode; # ifdef _SEQUENT_ char d_loginhost[100+1]; # endif /* _SEQUENT_ */ #endif int d_blocked; int d_blocked_fuzz; struct event d_idleev; /* screen blanker */ #ifdef BLANKER_PRG int d_blankerpid; struct event d_blankerev; #endif }; #ifdef MULTI # define DISPLAY(x) display->x #else extern struct display TheDisplay; # define DISPLAY(x) TheDisplay.x #endif #define D_user DISPLAY(d_user) #define D_username (DISPLAY(d_user) ? DISPLAY(d_user)->u_name : 0) #define D_canvas DISPLAY(d_canvas) #define D_cvlist DISPLAY(d_cvlist) #define D_layout DISPLAY(d_layout) #define D_forecv DISPLAY(d_forecv) #define D_processinput DISPLAY(d_processinput) #define D_processinputdata DISPLAY(d_processinputdata) #define D_vpxmin DISPLAY(d_vpxmin) #define D_vpxmax DISPLAY(d_vpxmax) #define D_fore DISPLAY(d_fore) #define D_other DISPLAY(d_other) #define D_nonblock DISPLAY(d_nonblock) #define D_termname DISPLAY(d_termname) #define D_tentry DISPLAY(d_tentry) #define D_tcinited DISPLAY(d_tcinited) #define D_width DISPLAY(d_width) #define D_height DISPLAY(d_height) #define D_defwidth DISPLAY(d_defwidth) #define D_defheight DISPLAY(d_defheight) #define D_top DISPLAY(d_top) #define D_bot DISPLAY(d_bot) #define D_x DISPLAY(d_x) #define D_y DISPLAY(d_y) #define D_rend DISPLAY(d_rend) #define D_col16change DISPLAY(d_col16change) #define D_atyp DISPLAY(d_atyp) #define D_mbcs DISPLAY(d_mbcs) #define D_encoding DISPLAY(d_encoding) #define D_decodestate DISPLAY(d_decodestate) #define D_realfont DISPLAY(d_realfont) #define D_insert DISPLAY(d_insert) #define D_keypad DISPLAY(d_keypad) #define D_cursorkeys DISPLAY(d_cursorkeys) #define D_revvid DISPLAY(d_revvid) #define D_curvis DISPLAY(d_curvis) #define D_has_hstatus DISPLAY(d_has_hstatus) #define D_hstatus DISPLAY(d_hstatus) #define D_lp_missing DISPLAY(d_lp_missing) #define D_mouse DISPLAY(d_mouse) #define D_mousetrack DISPLAY(d_mousetrack) #define D_xtermosc DISPLAY(d_xtermosc) #define D_lpchar DISPLAY(d_lpchar) #define D_status DISPLAY(d_status) #define D_status_time DISPLAY(d_status_time) #define D_status_bell DISPLAY(d_status_bell) #define D_status_len DISPLAY(d_status_len) #define D_status_lastmsg DISPLAY(d_status_lastmsg) #define D_status_buflen DISPLAY(d_status_buflen) #define D_status_lastx DISPLAY(d_status_lastx) #define D_status_lasty DISPLAY(d_status_lasty) #define D_status_obuflen DISPLAY(d_status_obuflen) #define D_status_obuffree DISPLAY(d_status_obuffree) #define D_status_obufpos DISPLAY(d_status_obufpos) #define D_statusev DISPLAY(d_statusev) #define D_hstatusev DISPLAY(d_hstatusev) #define D_kaablamm DISPLAY(d_kaablamm) #define D_ESCseen DISPLAY(d_ESCseen) #define D_userpid DISPLAY(d_userpid) #define D_usertty DISPLAY(d_usertty) #define D_userfd DISPLAY(d_userfd) #define D_OldMode DISPLAY(d_OldMode) #define D_NewMode DISPLAY(d_NewMode) #define D_flow DISPLAY(d_flow) #define D_intr DISPLAY(d_intr) #define D_obuf DISPLAY(d_obuf) #define D_obuflen DISPLAY(d_obuflen) #define D_obufmax DISPLAY(d_obufmax) #define D_obuflenmax DISPLAY(d_obuflenmax) #define D_obufp DISPLAY(d_obufp) #define D_obuffree DISPLAY(d_obuffree) #define D_auto_nuke DISPLAY(d_auto_nuke) #define D_nseqs DISPLAY(d_nseqs) #define D_aseqs DISPLAY(d_aseqs) #define D_seqp DISPLAY(d_seqp) #define D_seql DISPLAY(d_seql) #define D_seqh DISPLAY(d_seqh) #define D_dontmap DISPLAY(d_dontmap) #define D_mapdefault DISPLAY(d_mapdefault) #define D_kmaps DISPLAY(d_kmaps) #define D_tcs DISPLAY(d_tcs) #define D_attrtab DISPLAY(d_attrtab) #define D_attrtyp DISPLAY(d_attrtyp) #define D_hascolor DISPLAY(d_hascolor) #define D_dospeed DISPLAY(d_dospeed) #define D_c0_tab DISPLAY(d_c0_tab) #define D_xtable DISPLAY(d_xtable) #define D_UPcost DISPLAY(d_UPcost) #define D_DOcost DISPLAY(d_DOcost) #define D_LEcost DISPLAY(d_LEcost) #define D_NDcost DISPLAY(d_NDcost) #define D_CRcost DISPLAY(d_CRcost) #define D_IMcost DISPLAY(d_IMcost) #define D_EIcost DISPLAY(d_EIcost) #define D_NLcost DISPLAY(d_NLcost) #define D_printfd DISPLAY(d_printfd) #define D_loginslot DISPLAY(d_loginslot) #define D_utmp_logintty DISPLAY(d_utmp_logintty) #define D_loginttymode DISPLAY(d_loginttymode) #define D_loginhost DISPLAY(d_loginhost) #define D_readev DISPLAY(d_readev) #define D_writeev DISPLAY(d_writeev) #define D_blockedev DISPLAY(d_blockedev) #define D_mapev DISPLAY(d_mapev) #define D_blocked DISPLAY(d_blocked) #define D_blocked_fuzz DISPLAY(d_blocked_fuzz) #define D_idleev DISPLAY(d_idleev) #define D_blankerev DISPLAY(d_blankerev) #define D_blankerpid DISPLAY(d_blankerpid) #define GRAIN 4096 /* Allocation grain size for output buffer */ #define OBUF_MAX 256 /* default for obuflimit */ #define OUTPUT_BLOCK_SIZE 256 /* Block size of output to tty */ #define AddChar(c) \ do \ { \ if (--D_obuffree <= 0) \ Resize_obuf(); \ *D_obufp++ = (c); \ } \ while (0) #define STATUS_OFF 0 #define STATUS_ON_WIN 1 #define STATUS_ON_HS 2 #define HSTATUS_IGNORE 0 #define HSTATUS_LASTLINE 1 #define HSTATUS_MESSAGE 2 #define HSTATUS_HS 3 #define HSTATUS_ALWAYS (1<<2) #endif /* SCREEN_DISPLAY_H */ screen-4.1.0/process.c0000644000175000017500000050371211732171225012666 0ustar abeabe/* Copyright (c) 2010 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net) * Copyright (c) 2008, 2009 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Micah Cowan (micah@cowan.name) * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net) * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Copyright (c) 1987 Oliver Laumann * * 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, 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 (see the file COPYING); if not, see * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA * **************************************************************** */ #include "config.h" #include #include #include #include #if !defined(sun) && !defined(B43) && !defined(ISC) && !defined(pyr) && !defined(_CX_UX) # include #endif #include #ifndef sun #include #endif /* for solaris 2.1, Unixware (SVR4.2) and possibly others: */ #ifdef HAVE_STROPTS_H # include #endif #include "screen.h" #include "extern.h" #include "logfile.h" #include "layout.h" #include "viewport.h" #include "list_generic.h" extern struct comm comms[]; extern char *rc_name; extern char *RcFileName, *home; extern char *BellString, *ActivityString, *ShellProg, *ShellArgs[]; extern char *hstatusstring, *captionstring, *timestring; extern char *wliststr, *wlisttit; extern int captionalways; extern int queryflag; extern char *hardcopydir, *screenlogfile, *logtstamp_string; extern int log_flush, logtstamp_on, logtstamp_after; extern char *VisualBellString; extern int VBellWait, MsgWait, MsgMinWait, SilenceWait; extern char SockPath[], *SockName; extern int TtyMode, auto_detach, use_altscreen; extern int iflag, maxwin; extern int focusminwidth, focusminheight; extern int use_hardstatus, visual_bell; #ifdef COLOR extern int attr2color[][4]; extern int nattr2color; #endif extern int hardstatusemu; extern char *printcmd; extern int default_startup; extern int defobuflimit; extern int defnonblock; extern int defmousetrack; extern int ZombieKey_destroy; extern int ZombieKey_resurrect; extern int ZombieKey_onerror; #ifdef AUTO_NUKE extern int defautonuke; #endif extern int separate_sids; extern struct NewWindow nwin_default, nwin_undef; #ifdef COPY_PASTE extern int join_with_cr; extern int compacthist; extern int search_ic; # ifdef FONT extern int pastefont; # endif extern unsigned char mark_key_tab[]; extern char *BufferFile; #endif #ifdef POW_DETACH extern char *BufferFile, *PowDetachString; #endif #ifdef MULTIUSER extern struct acluser *EffectiveAclUser; /* acl.c */ #endif extern struct term term[]; /* terminal capabilities */ #ifdef MAPKEYS extern char *kmapdef[]; extern char *kmapadef[]; extern char *kmapmdef[]; #endif extern struct mchar mchar_so, mchar_null; extern int renditions[]; extern int VerboseCreate; #ifdef UTF8 extern char *screenencodings; #endif #ifdef DW_CHARS extern int cjkwidth; #endif static int CheckArgNum __P((int, char **)); static void ClearAction __P((struct action *)); static void SaveAction __P((struct action *, int, char **, int *)); static int NextWindow __P((void)); static int PreviousWindow __P((void)); static int MoreWindows __P((void)); static void LogToggle __P((int)); static void ShowInfo __P((void)); static void ShowDInfo __P((void)); static struct win *WindowByName __P((char *)); static int WindowByNumber __P((char *)); static int ParseOnOff __P((struct action *, int *)); static int ParseWinNum __P((struct action *, int *)); static int ParseBase __P((struct action *, char *, int *, int, char *)); static int ParseNum1000 __P((struct action *, int *)); static char **SaveArgs __P((char **)); static int IsNum __P((char *, int)); static void Colonfin __P((char *, int, char *)); static void InputSelect __P((void)); static void InputSetenv __P((char *)); static void InputAKA __P((void)); #ifdef MULTIUSER static int InputSu __P((struct win *, struct acluser **, char *)); static void su_fin __P((char *, int, char *)); #endif static void AKAfin __P((char *, int, char *)); #ifdef COPY_PASTE static void copy_reg_fn __P((char *, int, char *)); static void ins_reg_fn __P((char *, int, char *)); #endif static void process_fn __P((char *, int, char *)); #ifdef PASSWORD static void pass1 __P((char *, int, char *)); static void pass2 __P((char *, int, char *)); #endif #ifdef POW_DETACH static void pow_detach_fn __P((char *, int, char *)); #endif static void digraph_fn __P((char *, int, char *)); static int digraph_find __P((const char *buf)); static void confirm_fn __P((char *, int, char *)); static int IsOnDisplay __P((struct win *)); static void ResizeRegions __P((char *, int)); static void ResizeFin __P((char *, int, char *)); static struct action *FindKtab __P((char *, int)); static void SelectFin __P((char *, int, char *)); static void SelectLayoutFin __P((char *, int, char *)); extern struct layer *flayer; extern struct display *display, *displays; extern struct win *fore, *console_window, *windows; extern struct acluser *users; extern struct layout *layouts, *layout_attach, layout_last_marker; extern struct layout *laytab[]; extern char screenterm[], HostName[], version[]; extern struct NewWindow nwin_undef, nwin_default; extern struct LayFuncs WinLf, MarkLf; extern int Z0width, Z1width; extern int real_uid, real_gid; #ifdef NETHACK extern int nethackflag; #endif extern struct win **wtab; #ifdef MULTIUSER extern char *multi; extern int maxusercount; #endif char NullStr[] = ""; struct plop plop_tab[MAX_PLOP_DEFS]; #ifndef PTYMODE # define PTYMODE 0622 #endif int TtyMode = PTYMODE; int hardcopy_append = 0; int all_norefresh = 0; #ifdef ZMODEM int zmodem_mode = 0; char *zmodem_sendcmd; char *zmodem_recvcmd; static char *zmodes[4] = {"off", "auto", "catch", "pass"}; #endif int idletimo; struct action idleaction; #ifdef BLANKER_PRG char **blankerprg; #endif struct action ktab[256 + KMAP_KEYS]; /* command key translation table */ struct kclass { struct kclass *next; char *name; struct action ktab[256 + KMAP_KEYS]; }; struct kclass *kclasses; #ifdef MAPKEYS struct action umtab[KMAP_KEYS+KMAP_AKEYS]; struct action dmtab[KMAP_KEYS+KMAP_AKEYS]; struct action mmtab[KMAP_KEYS+KMAP_AKEYS]; struct kmap_ext *kmap_exts; int kmap_extn; static int maptimeout = 300; #endif #ifndef MAX_DIGRAPH #define MAX_DIGRAPH 512 #endif struct digraph { unsigned char d[2]; int value; }; /* digraph table taken from old vim and rfc1345 */ static struct digraph digraphs[MAX_DIGRAPH + 1] = { {{' ', ' '}, 160}, /*   */ {{'N', 'S'}, 160}, /*   */ {{'~', '!'}, 161}, /* ¡ */ {{'!', '!'}, 161}, /* ¡ */ {{'!', 'I'}, 161}, /* ¡ */ {{'c', '|'}, 162}, /* ¢ */ {{'c', 't'}, 162}, /* ¢ */ {{'$', '$'}, 163}, /* £ */ {{'P', 'd'}, 163}, /* £ */ {{'o', 'x'}, 164}, /* ¤ */ {{'C', 'u'}, 164}, /* ¤ */ {{'C', 'u'}, 164}, /* ¤ */ {{'E', 'u'}, 164}, /* ¤ */ {{'Y', '-'}, 165}, /* ¥ */ {{'Y', 'e'}, 165}, /* ¥ */ {{'|', '|'}, 166}, /* ¦ */ {{'B', 'B'}, 166}, /* ¦ */ {{'p', 'a'}, 167}, /* § */ {{'S', 'E'}, 167}, /* § */ {{'"', '"'}, 168}, /* ¨ */ {{'\'', ':'}, 168}, /* ¨ */ {{'c', 'O'}, 169}, /* © */ {{'C', 'o'}, 169}, /* © */ {{'a', '-'}, 170}, /* ª */ {{'<', '<'}, 171}, /* « */ {{'-', ','}, 172}, /* ¬ */ {{'N', 'O'}, 172}, /* ¬ */ {{'-', '-'}, 173}, /* ­ */ {{'r', 'O'}, 174}, /* ® */ {{'R', 'g'}, 174}, /* ® */ {{'-', '='}, 175}, /* ¯ */ {{'\'', 'm'}, 175}, /* ¯ */ {{'~', 'o'}, 176}, /* ° */ {{'D', 'G'}, 176}, /* ° */ {{'+', '-'}, 177}, /* ± */ {{'2', '2'}, 178}, /* ² */ {{'2', 'S'}, 178}, /* ² */ {{'3', '3'}, 179}, /* ³ */ {{'3', 'S'}, 179}, /* ³ */ {{'\'', '\''}, 180}, /* ´ */ {{'j', 'u'}, 181}, /* µ */ {{'M', 'y'}, 181}, /* µ */ {{'p', 'p'}, 182}, /* ¶ */ {{'P', 'I'}, 182}, /* ¶ */ {{'~', '.'}, 183}, /* · */ {{'.', 'M'}, 183}, /* · */ {{',', ','}, 184}, /* ¸ */ {{'\'', ','}, 184}, /* ¸ */ {{'1', '1'}, 185}, /* ¹ */ {{'1', 'S'}, 185}, /* ¹ */ {{'o', '-'}, 186}, /* º */ {{'>', '>'}, 187}, /* » */ {{'1', '4'}, 188}, /* ¼ */ {{'1', '2'}, 189}, /* ½ */ {{'3', '4'}, 190}, /* ¾ */ {{'~', '?'}, 191}, /* ¿ */ {{'?', '?'}, 191}, /* ¿ */ {{'?', 'I'}, 191}, /* ¿ */ {{'A', '`'}, 192}, /* À */ {{'A', '!'}, 192}, /* À */ {{'A', '\''}, 193}, /* Á */ {{'A', '^'}, 194}, /*  */ {{'A', '>'}, 194}, /*  */ {{'A', '~'}, 195}, /* à */ {{'A', '?'}, 195}, /* à */ {{'A', '"'}, 196}, /* Ä */ {{'A', ':'}, 196}, /* Ä */ {{'A', '@'}, 197}, /* Å */ {{'A', 'A'}, 197}, /* Å */ {{'A', 'E'}, 198}, /* Æ */ {{'C', ','}, 199}, /* Ç */ {{'E', '`'}, 200}, /* È */ {{'E', '!'}, 200}, /* È */ {{'E', '\''}, 201}, /* É */ {{'E', '^'}, 202}, /* Ê */ {{'E', '>'}, 202}, /* Ê */ {{'E', '"'}, 203}, /* Ë */ {{'E', ':'}, 203}, /* Ë */ {{'I', '`'}, 204}, /* Ì */ {{'I', '!'}, 204}, /* Ì */ {{'I', '\''}, 205}, /* Í */ {{'I', '^'}, 206}, /* Î */ {{'I', '>'}, 206}, /* Î */ {{'I', '"'}, 207}, /* Ï */ {{'I', ':'}, 207}, /* Ï */ {{'D', '-'}, 208}, /* Ð */ {{'N', '~'}, 209}, /* Ñ */ {{'N', '?'}, 209}, /* Ñ */ {{'O', '`'}, 210}, /* Ò */ {{'O', '!'}, 210}, /* Ò */ {{'O', '\''}, 211}, /* Ó */ {{'O', '^'}, 212}, /* Ô */ {{'O', '>'}, 212}, /* Ô */ {{'O', '~'}, 213}, /* Õ */ {{'O', '?'}, 213}, /* Õ */ {{'O', '"'}, 214}, /* Ö */ {{'O', ':'}, 214}, /* Ö */ {{'/', '\\'}, 215}, /* × */ {{'*', 'x'}, 215}, /* × */ {{'O', '/'}, 216}, /* Ø */ {{'U', '`'}, 217}, /* Ù */ {{'U', '!'}, 217}, /* Ù */ {{'U', '\''}, 218}, /* Ú */ {{'U', '^'}, 219}, /* Û */ {{'U', '>'}, 219}, /* Û */ {{'U', '"'}, 220}, /* Ü */ {{'U', ':'}, 220}, /* Ü */ {{'Y', '\''}, 221}, /* Ý */ {{'I', 'p'}, 222}, /* Þ */ {{'T', 'H'}, 222}, /* Þ */ {{'s', 's'}, 223}, /* ß */ {{'s', '"'}, 223}, /* ß */ {{'a', '`'}, 224}, /* à */ {{'a', '!'}, 224}, /* à */ {{'a', '\''}, 225}, /* á */ {{'a', '^'}, 226}, /* â */ {{'a', '>'}, 226}, /* â */ {{'a', '~'}, 227}, /* ã */ {{'a', '?'}, 227}, /* ã */ {{'a', '"'}, 228}, /* ä */ {{'a', ':'}, 228}, /* ä */ {{'a', 'a'}, 229}, /* å */ {{'a', 'e'}, 230}, /* æ */ {{'c', ','}, 231}, /* ç */ {{'e', '`'}, 232}, /* è */ {{'e', '!'}, 232}, /* è */ {{'e', '\''}, 233}, /* é */ {{'e', '^'}, 234}, /* ê */ {{'e', '>'}, 234}, /* ê */ {{'e', '"'}, 235}, /* ë */ {{'e', ':'}, 235}, /* ë */ {{'i', '`'}, 236}, /* ì */ {{'i', '!'}, 236}, /* ì */ {{'i', '\''}, 237}, /* í */ {{'i', '^'}, 238}, /* î */ {{'i', '>'}, 238}, /* î */ {{'i', '"'}, 239}, /* ï */ {{'i', ':'}, 239}, /* ï */ {{'d', '-'}, 240}, /* ð */ {{'n', '~'}, 241}, /* ñ */ {{'n', '?'}, 241}, /* ñ */ {{'o', '`'}, 242}, /* ò */ {{'o', '!'}, 242}, /* ò */ {{'o', '\''}, 243}, /* ó */ {{'o', '^'}, 244}, /* ô */ {{'o', '>'}, 244}, /* ô */ {{'o', '~'}, 245}, /* õ */ {{'o', '?'}, 245}, /* õ */ {{'o', '"'}, 246}, /* ö */ {{'o', ':'}, 246}, /* ö */ {{':', '-'}, 247}, /* ÷ */ {{'o', '/'}, 248}, /* ø */ {{'u', '`'}, 249}, /* ù */ {{'u', '!'}, 249}, /* ù */ {{'u', '\''}, 250}, /* ú */ {{'u', '^'}, 251}, /* û */ {{'u', '>'}, 251}, /* û */ {{'u', '"'}, 252}, /* ü */ {{'u', ':'}, 252}, /* ü */ {{'y', '\''}, 253}, /* ý */ {{'i', 'p'}, 254}, /* þ */ {{'t', 'h'}, 254}, /* þ */ {{'y', '"'}, 255}, /* ÿ */ {{'y', ':'}, 255}, /* ÿ */ {{'"', '['}, 196}, /* Ä */ {{'"', '\\'}, 214}, /* Ö */ {{'"', ']'}, 220}, /* Ü */ {{'"', '{'}, 228}, /* ä */ {{'"', '|'}, 246}, /* ö */ {{'"', '}'}, 252}, /* ü */ {{'"', '~'}, 223} /* ß */ }; #define RESIZE_FLAG_H 1 #define RESIZE_FLAG_V 2 #define RESIZE_FLAG_L 4 static char *resizeprompts[] = { "resize # lines: ", "resize -h # lines: ", "resize -v # lines: ", "resize -b # lines: ", "resize -l # lines: ", "resize -l -h # lines: ", "resize -l -v # lines: ", "resize -l -b # lines: ", }; static int parse_input_int(buf, len, val) const char *buf; int len; int *val; { int x = 0, i; if (len >= 1 && ((*buf == 'U' && buf[1] == '+') || (*buf == '0' && (buf[1] == 'x' || buf[1] == 'X')))) { x = 0; for (i = 2; i < len; i++) { if (buf[i] >= '0' && buf[i] <= '9') x = x * 16 | (buf[i] - '0'); else if (buf[i] >= 'a' && buf[i] <= 'f') x = x * 16 | (buf[i] - ('a' - 10)); else if (buf[i] >= 'A' && buf[i] <= 'F') x = x * 16 | (buf[i] - ('A' - 10)); else return 0; } } else if (buf[0] == '0') { x = 0; for (i = 1; i < len; i++) { if (buf[i] < '0' || buf[i] > '7') return 0; x = x * 8 | (buf[i] - '0'); } } else return 0; *val = x; return 1; } char *noargs[1]; void InitKeytab() { register unsigned int i; #ifdef MAPKEYS char *argarr[2]; #endif for (i = 0; i < sizeof(ktab)/sizeof(*ktab); i++) { ktab[i].nr = RC_ILLEGAL; ktab[i].args = noargs; ktab[i].argl = 0; } #ifdef MAPKEYS for (i = 0; i < KMAP_KEYS+KMAP_AKEYS; i++) { umtab[i].nr = RC_ILLEGAL; umtab[i].args = noargs; umtab[i].argl = 0; dmtab[i].nr = RC_ILLEGAL; dmtab[i].args = noargs; dmtab[i].argl = 0; mmtab[i].nr = RC_ILLEGAL; mmtab[i].args = noargs; mmtab[i].argl = 0; } argarr[1] = 0; for (i = 0; i < NKMAPDEF; i++) { if (i + KMAPDEFSTART < T_CAPS) continue; if (i + KMAPDEFSTART >= T_CAPS + KMAP_KEYS) continue; if (kmapdef[i] == 0) continue; argarr[0] = kmapdef[i]; SaveAction(dmtab + i + (KMAPDEFSTART - T_CAPS), RC_STUFF, argarr, 0); } for (i = 0; i < NKMAPADEF; i++) { if (i + KMAPADEFSTART < T_CURSOR) continue; if (i + KMAPADEFSTART >= T_CURSOR + KMAP_AKEYS) continue; if (kmapadef[i] == 0) continue; argarr[0] = kmapadef[i]; SaveAction(dmtab + i + (KMAPADEFSTART - T_CURSOR + KMAP_KEYS), RC_STUFF, argarr, 0); } for (i = 0; i < NKMAPMDEF; i++) { if (i + KMAPMDEFSTART < T_CAPS) continue; if (i + KMAPMDEFSTART >= T_CAPS + KMAP_KEYS) continue; if (kmapmdef[i] == 0) continue; argarr[0] = kmapmdef[i]; argarr[1] = 0; SaveAction(mmtab + i + (KMAPMDEFSTART - T_CAPS), RC_STUFF, argarr, 0); } #endif ktab['h'].nr = RC_HARDCOPY; #ifdef BSDJOBS ktab['z'].nr = ktab[Ctrl('z')].nr = RC_SUSPEND; #endif ktab['c'].nr = ktab[Ctrl('c')].nr = RC_SCREEN; ktab[' '].nr = ktab[Ctrl(' ')].nr = ktab['n'].nr = ktab[Ctrl('n')].nr = RC_NEXT; ktab['N'].nr = RC_NUMBER; ktab[Ctrl('h')].nr = ktab[0177].nr = ktab['p'].nr = ktab[Ctrl('p')].nr = RC_PREV; ktab['k'].nr = ktab[Ctrl('k')].nr = RC_KILL; ktab['l'].nr = ktab[Ctrl('l')].nr = RC_REDISPLAY; ktab['w'].nr = ktab[Ctrl('w')].nr = RC_WINDOWS; ktab['v'].nr = RC_VERSION; ktab[Ctrl('v')].nr = RC_DIGRAPH; ktab['q'].nr = ktab[Ctrl('q')].nr = RC_XON; ktab['s'].nr = ktab[Ctrl('s')].nr = RC_XOFF; ktab['t'].nr = ktab[Ctrl('t')].nr = RC_TIME; ktab['i'].nr = ktab[Ctrl('i')].nr = RC_INFO; ktab['m'].nr = ktab[Ctrl('m')].nr = RC_LASTMSG; ktab['A'].nr = RC_TITLE; #if defined(UTMPOK) && defined(LOGOUTOK) ktab['L'].nr = RC_LOGIN; #endif ktab[','].nr = RC_LICENSE; ktab['W'].nr = RC_WIDTH; ktab['.'].nr = RC_DUMPTERMCAP; ktab[Ctrl('\\')].nr = RC_QUIT; #ifdef DETACH ktab['d'].nr = ktab[Ctrl('d')].nr = RC_DETACH; # ifdef POW_DETACH ktab['D'].nr = RC_POW_DETACH; # endif #endif ktab['r'].nr = ktab[Ctrl('r')].nr = RC_WRAP; ktab['f'].nr = ktab[Ctrl('f')].nr = RC_FLOW; ktab['C'].nr = RC_CLEAR; ktab['Z'].nr = RC_RESET; ktab['H'].nr = RC_LOG; ktab['M'].nr = RC_MONITOR; ktab['?'].nr = RC_HELP; #ifdef MULTI ktab['*'].nr = RC_DISPLAYS; #endif { char *args[2]; args[0] = "-"; args[1] = NULL; SaveAction(ktab + '-', RC_SELECT, args, 0); } for (i = 0; i < ((maxwin && maxwin < 10) ? maxwin : 10); i++) { char *args[2], arg1[10]; args[0] = arg1; args[1] = 0; sprintf(arg1, "%d", i); SaveAction(ktab + '0' + i, RC_SELECT, args, 0); } ktab['\''].nr = RC_SELECT; /* calling a window by name */ { char *args[2]; args[0] = "-b"; args[1] = 0; SaveAction(ktab + '"', RC_WINDOWLIST, args, 0); } ktab[Ctrl('G')].nr = RC_VBELL; ktab[':'].nr = RC_COLON; #ifdef COPY_PASTE ktab['['].nr = ktab[Ctrl('[')].nr = RC_COPY; { char *args[2]; args[0] = "."; args[1] = 0; SaveAction(ktab + ']', RC_PASTE, args, 0); SaveAction(ktab + Ctrl(']'), RC_PASTE, args, 0); } ktab['{'].nr = RC_HISTORY; ktab['}'].nr = RC_HISTORY; ktab['>'].nr = RC_WRITEBUF; ktab['<'].nr = RC_READBUF; ktab['='].nr = RC_REMOVEBUF; #endif #ifdef POW_DETACH ktab['D'].nr = RC_POW_DETACH; #endif #ifdef LOCK ktab['x'].nr = ktab[Ctrl('x')].nr = RC_LOCKSCREEN; #endif ktab['b'].nr = ktab[Ctrl('b')].nr = RC_BREAK; ktab['B'].nr = RC_POW_BREAK; ktab['_'].nr = RC_SILENCE; ktab['S'].nr = RC_SPLIT; ktab['Q'].nr = RC_ONLY; ktab['X'].nr = RC_REMOVE; ktab['F'].nr = RC_FIT; ktab['\t'].nr = RC_FOCUS; { char *args[2]; args[0] = "prev"; args[1] = 0; SaveAction(ktab + T_BACKTAB - T_CAPS + 256, RC_FOCUS, args, 0); } { char *args[2]; args[0] = "-v"; args[1] = 0; SaveAction(ktab + '|', RC_SPLIT, args, 0); } /* These come last; they may want overwrite others: */ if (DefaultEsc >= 0) { ClearAction(&ktab[DefaultEsc]); ktab[DefaultEsc].nr = RC_OTHER; } if (DefaultMetaEsc >= 0) { ClearAction(&ktab[DefaultMetaEsc]); ktab[DefaultMetaEsc].nr = RC_META; } idleaction.nr = RC_BLANKER; idleaction.args = noargs; idleaction.argl = 0; } static struct action * FindKtab(class, create) char *class; int create; { struct kclass *kp, **kpp; int i; if (class == 0) return ktab; for (kpp = &kclasses; (kp = *kpp) != 0; kpp = &kp->next) if (!strcmp(kp->name, class)) break; if (kp == 0) { if (!create) return 0; if (strlen(class) > 80) { Msg(0, "Command class name too long."); return 0; } kp = malloc(sizeof(*kp)); if (kp == 0) { Msg(0, "%s", strnomem); return 0; } kp->name = SaveStr(class); for (i = 0; i < (int)(sizeof(kp->ktab)/sizeof(*kp->ktab)); i++) { kp->ktab[i].nr = RC_ILLEGAL; kp->ktab[i].args = noargs; kp->ktab[i].argl = 0; kp->ktab[i].quiet = 0; } kp->next = 0; *kpp = kp; } return kp->ktab; } static void ClearAction(act) struct action *act; { char **p; if (act->nr == RC_ILLEGAL) return; act->nr = RC_ILLEGAL; if (act->args == noargs) return; for (p = act->args; *p; p++) free(*p); free((char *)act->args); act->args = noargs; act->argl = 0; } /* * ProcessInput: process input from display and feed it into * the layer on canvas D_forecv. */ #ifdef MAPKEYS /* * This ProcessInput just does the keybindings and passes * everything else on to ProcessInput2. */ void ProcessInput(ibuf, ilen) char *ibuf; int ilen; { int ch, slen; unsigned char *s, *q; int i, l; char *p; debug1("ProcessInput: %d bytes\n", ilen); if (display == 0 || ilen == 0) return; if (D_seql) evdeq(&D_mapev); slen = ilen; s = (unsigned char *)ibuf; while (ilen-- > 0) { ch = *s++; if (D_dontmap || !D_nseqs) { D_dontmap = 0; continue; } for (;;) { debug3("cmp %c %c[%d]\n", ch, *D_seqp, D_seqp - D_kmaps); if (*D_seqp != ch) { l = D_seqp[D_seqp[-D_seql-1] + 1]; if (l) { D_seqp += l * 2 + 4; debug1("miss %d\n", D_seqp - D_kmaps); continue; } debug("complete miss\n"); D_mapdefault = 0; l = D_seql; p = (char *)D_seqp - l; D_seql = 0; D_seqp = D_kmaps + 3; if (l == 0) break; if ((q = D_seqh) != 0) { D_seqh = 0; i = q[0] << 8 | q[1]; i &= ~KMAP_NOTIMEOUT; debug1("Mapping former hit #%d - ", i); debug2("%d(%s) - ", q[2], q + 3); if (StuffKey(i)) ProcessInput2((char *)q + 3, q[2]); if (display == 0) return; l -= q[2]; p += q[2]; } else D_dontmap = 1; debug1("flush old %d\n", l); ProcessInput(p, l); if (display == 0) return; evdeq(&D_mapev); continue; } if (D_seql++ == 0) { /* Finish old stuff */ slen -= ilen + 1; debug1("finish old %d\n", slen); if (slen) ProcessInput2(ibuf, slen); if (display == 0) return; D_seqh = 0; } ibuf = (char *)s; slen = ilen; D_seqp++; l = D_seql; debug2("length am %d, want %d\n", l, D_seqp[-l - 1]); if (l == D_seqp[-l - 1]) { if (D_seqp[l] != l) { q = D_seqp + 1 + l; if (D_kmaps + D_nseqs > q && q[2] > l && !bcmp(D_seqp - l, q + 3, l)) { debug1("have another mapping (%s), delay execution\n", q + 3); D_seqh = D_seqp - 3 - l; D_seqp = q + 3 + l; break; } } i = D_seqp[-l - 3] << 8 | D_seqp[-l - 2]; i &= ~KMAP_NOTIMEOUT; debug1("Mapping #%d - ", i); p = (char *)D_seqp - l; debug2("%d(%s) - ", l, p); D_seql = 0; D_seqp = D_kmaps + 3; D_seqh = 0; if (StuffKey(i)) ProcessInput2(p, l); if (display == 0) return; } break; } } if (D_seql) { debug("am in sequence -> check for timeout\n"); l = D_seql; for (s = D_seqp; ; s += i * 2 + 4) { if (s[-l-3] & KMAP_NOTIMEOUT >> 8) break; if ((i = s[s[-l-1] + 1]) == 0) { SetTimeout(&D_mapev, maptimeout); evenq(&D_mapev); break; } } } ProcessInput2(ibuf, slen); } #else # define ProcessInput2 ProcessInput #endif /* * Here only the screen escape commands are handled. */ void ProcessInput2(ibuf, ilen) char *ibuf; int ilen; { char *s; int ch, slen; struct action *ktabp; debug1("ProcessInput2: %d bytes\n", ilen); while (ilen && display) { debug1(" - ilen now %d bytes\n", ilen); flayer = D_forecv->c_layer; fore = D_fore; slen = ilen; s = ibuf; if (!D_ESCseen) { while (ilen > 0) { if ((unsigned char)*s++ == D_user->u_Esc) break; ilen--; } slen -= ilen; if (slen) DoProcess(fore, &ibuf, &slen, 0); if (--ilen == 0) { D_ESCseen = ktab; WindowChanged(fore, 'E'); } } if (ilen <= 0) return; ktabp = D_ESCseen ? D_ESCseen : ktab; if (D_ESCseen) { D_ESCseen = 0; WindowChanged(fore, 'E'); } ch = (unsigned char)*s; /* * As users have different esc characters, but a common ktab[], * we fold back the users esc and meta-esc key to the Default keys * that can be looked up in the ktab[]. grmbl. jw. * XXX: make ktab[] a per user thing. */ if (ch == D_user->u_Esc) ch = DefaultEsc; else if (ch == D_user->u_MetaEsc) ch = DefaultMetaEsc; if (ch >= 0) DoAction(&ktabp[ch], ch); ibuf = (char *)(s + 1); ilen--; } } void DoProcess(p, bufp, lenp, pa) struct win *p; char **bufp; int *lenp; struct paster *pa; { int oldlen; struct display *d = display; #ifdef COPY_PASTE /* XXX -> PasteStart */ if (pa && *lenp > 1 && p && p->w_slowpaste) { /* schedule slowpaste event */ SetTimeout(&p->w_paster.pa_slowev, p->w_slowpaste); evenq(&p->w_paster.pa_slowev); return; } #endif while (flayer && *lenp) { #ifdef COPY_PASTE if (!pa && p && p->w_paster.pa_pastelen && flayer == p->w_paster.pa_pastelayer) { debug("layer is busy - beep!\n"); WBell(p, visual_bell); *bufp += *lenp; *lenp = 0; display = d; return; } #endif oldlen = *lenp; LayProcess(bufp, lenp); #ifdef COPY_PASTE if (pa && !pa->pa_pastelayer) break; /* flush rest of paste */ #endif if (*lenp == oldlen) { if (pa) { display = d; return; } /* We're full, let's beep */ debug("layer is full - beep!\n"); WBell(p, visual_bell); break; } } *bufp += *lenp; *lenp = 0; display = d; #ifdef COPY_PASTE if (pa && pa->pa_pastelen == 0) FreePaster(pa); #endif } int FindCommnr(str) const char *str; { int x, m, l = 0, r = RC_LAST; while (l <= r) { m = (l + r) / 2; x = strcmp(str, comms[m].name); if (x > 0) l = m + 1; else if (x < 0) r = m - 1; else return m; } return RC_ILLEGAL; } static int CheckArgNum(nr, args) int nr; char **args; { int i, n; static char *argss[] = {"no", "one", "two", "three", "four", "OOPS"}; static char *orformat[] = { "%s: %s: %s argument%s required", "%s: %s: %s or %s argument%s required", "%s: %s: %s, %s or %s argument%s required", "%s: %s: %s, %s, %s or %s argument%s required" }; n = comms[nr].flags & ARGS_MASK; for (i = 0; args[i]; i++) ; if (comms[nr].flags & ARGS_ORMORE) { if (i < n) { Msg(0, "%s: %s: at least %s argument%s required", rc_name, comms[nr].name, argss[n], n != 1 ? "s" : ""); return -1; } } else if ((comms[nr].flags & ARGS_PLUS1) && (comms[nr].flags & ARGS_PLUS2) && (comms[nr].flags & ARGS_PLUS3)) { if (i != n && i != n + 1 && i != n + 2 && i != n + 3) { Msg(0, orformat[3], rc_name, comms[nr].name, argss[n], argss[n + 1], argss[n + 2], argss[n + 3], ""); return -1; } } else if ((comms[nr].flags & ARGS_PLUS1) && (comms[nr].flags & ARGS_PLUS2)) { if (i != n && i != n + 1 && i != n + 2) { Msg(0, orformat[2], rc_name, comms[nr].name, argss[n], argss[n + 1], argss[n + 2], ""); return -1; } } else if ((comms[nr].flags & ARGS_PLUS1) && (comms[nr].flags & ARGS_PLUS3)) { if (i != n && i != n + 1 && i != n + 3) { Msg(0, orformat[2], rc_name, comms[nr].name, argss[n], argss[n + 1], argss[n + 3], ""); return -1; } } else if ((comms[nr].flags & ARGS_PLUS2) && (comms[nr].flags & ARGS_PLUS3)) { if (i != n && i != n + 2 && i != n + 3) { Msg(0, orformat[2], rc_name, comms[nr].name, argss[n], argss[n + 2], argss[n + 3], ""); return -1; } } else if (comms[nr].flags & ARGS_PLUS1) { if (i != n && i != n + 1) { Msg(0, orformat[1], rc_name, comms[nr].name, argss[n], argss[n + 1], n != 0 ? "s" : ""); return -1; } } else if (comms[nr].flags & ARGS_PLUS2) { if (i != n && i != n + 2) { Msg(0, orformat[1], rc_name, comms[nr].name, argss[n], argss[n + 2], "s"); return -1; } } else if (comms[nr].flags & ARGS_PLUS3) { if (i != n && i != n + 3) { Msg(0, orformat[1], rc_name, comms[nr].name, argss[n], argss[n + 3], ""); return -1; } } else if (i != n) { Msg(0, orformat[0], rc_name, comms[nr].name, argss[n], n != 1 ? "s" : ""); return -1; } return i; } static void StuffFin(buf, len, data) char *buf; int len; char *data; { if (!flayer) return; while(len) LayProcess(&buf, &len); } /* If the command is not 'quieted', then use Msg to output the message. If it's a remote * query, then Msg takes care of also outputting the message to the querying client. * * If we want the command to be quiet, and it's a remote query, then use QueryMsg so that * the response does go back to the querying client. * * If the command is quieted, and it's not a remote query, then just don't print the message. */ #define OutputMsg (!act->quiet ? Msg : queryflag >= 0 ? QueryMsg : Dummy) /*ARGSUSED*/ void DoAction(act, key) struct action *act; int key; { int nr = act->nr; char **args = act->args; int *argl = act->argl; struct win *p; int argc, i, n, msgok; char *s; char ch; struct display *odisplay = display; struct acluser *user; user = display ? D_user : users; if (nr == RC_ILLEGAL) { debug1("key '%c': No action\n", key); return; } n = comms[nr].flags; /* Commands will have a CAN_QUERY flag, depending on whether they have * something to return on a query. For example, 'windows' can return a result, * but 'other' cannot. * If some command causes an error, then it should reset queryflag to -1, so that * the process requesting the query can be notified that an error happened. */ if (!(n & CAN_QUERY) && queryflag >= 0) { /* Query flag is set, but this command cannot be queried. */ OutputMsg(0, "%s command cannot be queried.", comms[nr].name); queryflag = -1; return; } if ((n & NEED_DISPLAY) && display == 0) { OutputMsg(0, "%s: %s: display required", rc_name, comms[nr].name); queryflag = -1; return; } if ((n & NEED_FORE) && fore == 0) { OutputMsg(0, "%s: %s: window required", rc_name, comms[nr].name); queryflag = -1; return; } if ((n & NEED_LAYER) && flayer == 0) { OutputMsg(0, "%s: %s: display or window required", rc_name, comms[nr].name); queryflag = -1; return; } if ((argc = CheckArgNum(nr, args)) < 0) return; #ifdef MULTIUSER if (display) { if (AclCheckPermCmd(D_user, ACL_EXEC, &comms[nr])) { OutputMsg(0, "%s: %s: permission denied (user %s)", rc_name, comms[nr].name, (EffectiveAclUser ? EffectiveAclUser : D_user)->u_name); queryflag = -1; return; } } #endif /* MULTIUSER */ msgok = display && !*rc_name; switch(nr) { case RC_SELECT: if (!*args) InputSelect(); else if (args[0][0] == '-' && !args[0][1]) { SetForeWindow((struct win *)0); Activate(0); } else if (args[0][0] == '.' && !args[0][1]) { if (!fore) { OutputMsg(0, "select . needs a window"); queryflag = -1; } else { SetForeWindow(fore); Activate(0); } } else if (ParseWinNum(act, &n) == 0) SwitchWindow(n); else if (queryflag >= 0) queryflag = -1; /* ParseWinNum already prints out an appropriate error message. */ break; #ifdef AUTO_NUKE case RC_DEFAUTONUKE: if (ParseOnOff(act, &defautonuke) == 0 && msgok) OutputMsg(0, "Default autonuke turned %s", defautonuke ? "on" : "off"); if (display && *rc_name) D_auto_nuke = defautonuke; break; case RC_AUTONUKE: if (ParseOnOff(act, &D_auto_nuke) == 0 && msgok) OutputMsg(0, "Autonuke turned %s", D_auto_nuke ? "on" : "off"); break; #endif case RC_DEFOBUFLIMIT: if (ParseNum(act, &defobuflimit) == 0 && msgok) OutputMsg(0, "Default limit set to %d", defobuflimit); if (display && *rc_name) { D_obufmax = defobuflimit; D_obuflenmax = D_obuflen - D_obufmax; } break; case RC_OBUFLIMIT: if (*args == 0) OutputMsg(0, "Limit is %d, current buffer size is %d", D_obufmax, D_obuflen); else if (ParseNum(act, &D_obufmax) == 0 && msgok) OutputMsg(0, "Limit set to %d", D_obufmax); D_obuflenmax = D_obuflen - D_obufmax; break; case RC_DUMPTERMCAP: WriteFile(user, (char *)0, DUMP_TERMCAP); break; case RC_HARDCOPY: { int mode = DUMP_HARDCOPY; char *file = NULL; if (args[0]) { if (!strcmp(*args, "-h")) { mode = DUMP_SCROLLBACK; file = args[1]; } else if (!strcmp(*args, "--") && args[1]) file = args[1]; else file = args[0]; } if (args[0] && file == args[0] && args[1]) { OutputMsg(0, "%s: hardcopy: too many arguments", rc_name); break; } WriteFile(user, file, mode); } break; case RC_DEFLOG: (void)ParseOnOff(act, &nwin_default.Lflag); break; case RC_LOG: n = fore->w_log ? 1 : 0; ParseSwitch(act, &n); LogToggle(n); break; #ifdef BSDJOBS case RC_SUSPEND: Detach(D_STOP); break; #endif case RC_NEXT: if (MoreWindows()) SwitchWindow(NextWindow()); break; case RC_PREV: if (MoreWindows()) SwitchWindow(PreviousWindow()); break; case RC_KILL: { char *name; if (key >= 0) { #ifdef PSEUDOS Input(fore->w_pwin ? "Really kill this filter [y/n]" : "Really kill this window [y/n]", 1, INP_RAW, confirm_fn, NULL, RC_KILL); #else Input("Really kill this window [y/n]", 1, INP_RAW, confirm_fn, NULL, RC_KILL); #endif break; } n = fore->w_number; #ifdef PSEUDOS if (fore->w_pwin) { FreePseudowin(fore); OutputMsg(0, "Filter removed."); break; } #endif name = SaveStr(fore->w_title); KillWindow(fore); OutputMsg(0, "Window %d (%s) killed.", n, name); if (name) free(name); break; } case RC_QUIT: if (key >= 0) { Input("Really quit and kill all your windows [y/n]", 1, INP_RAW, confirm_fn, NULL, RC_QUIT); break; } Finit(0); /* NOTREACHED */ #ifdef DETACH case RC_DETACH: if (*args && !strcmp(*args, "-h")) Hangup(); else Detach(D_DETACH); break; # ifdef POW_DETACH case RC_POW_DETACH: if (key >= 0) { static char buf[2]; buf[0] = key; Input(buf, 1, INP_RAW, pow_detach_fn, NULL, 0); } else Detach(D_POWER); /* detach and kill Attacher's parent */ break; # endif #endif case RC_DEBUG: #ifdef DEBUG if (!*args) { if (dfp) OutputMsg(0, "debugging info is written to %s/", DEBUGDIR); else OutputMsg(0, "debugging is currently off. Use 'debug on' to enable."); break; } if (dfp) { debug("debug: closing debug file.\n"); fflush(dfp); fclose(dfp); dfp = NULL; } if (strcmp("off", *args)) opendebug(0, 1); # ifdef SIG_NODEBUG else if (display) kill(D_userpid, SIG_NODEBUG); /* a one shot item, but hey... */ # endif /* SIG_NODEBUG */ #else if (*args == 0 || strcmp("off", *args)) OutputMsg(0, "Sorry, screen was compiled without -DDEBUG option."); #endif break; #ifdef ZMODEM case RC_ZMODEM: if (*args && !strcmp(*args, "sendcmd")) { if (args[1]) { free(zmodem_sendcmd); zmodem_sendcmd = SaveStr(args[1]); } if (msgok) OutputMsg(0, "zmodem sendcmd: %s", zmodem_sendcmd); break; } if (*args && !strcmp(*args, "recvcmd")) { if (args[1]) { free(zmodem_recvcmd); zmodem_recvcmd = SaveStr(args[1]); } if (msgok) OutputMsg(0, "zmodem recvcmd: %s", zmodem_recvcmd); break; } if (*args) { for (i = 0; i < 4; i++) if (!strcmp(zmodes[i], *args)) break; if (i == 4 && !strcmp(*args, "on")) i = 1; if (i == 4) { OutputMsg(0, "usage: zmodem off|auto|catch|pass"); break; } zmodem_mode = i; } if (msgok) OutputMsg(0, "zmodem mode is %s", zmodes[zmodem_mode]); break; #endif case RC_UNBINDALL: { register unsigned int i; for (i = 0; i < sizeof(ktab)/sizeof(*ktab); i++) ClearAction(&ktab[i]); OutputMsg(0, "Unbound all keys." ); break; } case RC_ZOMBIE: { if (!(s = *args)) { ZombieKey_destroy = 0; break; } if (*argl == 0 || *argl > 2) { OutputMsg(0, "%s:zombie: one or two characters expected.", rc_name); break; } if (args[1]) { if (!strcmp(args[1], "onerror")) { ZombieKey_onerror = 1; } else { OutputMsg(0, "usage: zombie [keys [onerror]]"); break; } } else ZombieKey_onerror = 0; ZombieKey_destroy = args[0][0]; ZombieKey_resurrect = *argl == 2 ? args[0][1] : 0; } break; case RC_WALL: #ifdef MULTIUSER s = D_user->u_name; #else s = D_usertty; #endif { struct display *olddisplay = display; display = 0; /* no display will cause a broadcast */ OutputMsg(0, "%s: %s", s, *args); display = olddisplay; } break; case RC_AT: /* where this AT command comes from: */ if (!user) break; #ifdef MULTIUSER s = SaveStr(user->u_name); /* DO NOT RETURN FROM HERE WITHOUT RESETTING THIS: */ EffectiveAclUser = user; #else s = SaveStr(display ? D_usertty : user->u_name); #endif n = strlen(args[0]); if (n) n--; /* * the windows/displays loops are quite dangerous here, take extra * care not to trigger landmines. Things may appear/disappear while * we are walking along. */ switch (args[0][n]) { case '*': /* user */ { struct display *nd; struct acluser *u; if (!n) u = user; else { for (u = users; u; u = u->u_next) { debug3("strncmp('%s', '%s', %d)\n", *args, u->u_name, n); if (!strncmp(*args, u->u_name, n)) break; } if (!u) { args[0][n] = '\0'; OutputMsg(0, "Did not find any user matching '%s'", args[0]); break; } } debug1("at all displays of user %s\n", u->u_name); for (display = displays; display; display = nd) { nd = display->d_next; if (D_forecv == 0) continue; flayer = D_forecv->c_layer; fore = D_fore; if (D_user != u) continue; debug1("AT display %s\n", D_usertty); DoCommand(args + 1, argl + 1); if (display) OutputMsg(0, "command from %s: %s %s", s, args[1], args[2] ? args[2] : ""); display = NULL; flayer = 0; fore = NULL; } break; } case '%': /* display */ { struct display *nd; debug1("at display matching '%s'\n", args[0]); for (display = displays; display; display = nd) { nd = display->d_next; if (D_forecv == 0) continue; fore = D_fore; flayer = D_forecv->c_layer; if (strncmp(args[0], D_usertty, n) && (strncmp("/dev/", D_usertty, 5) || strncmp(args[0], D_usertty + 5, n)) && (strncmp("/dev/tty", D_usertty, 8) || strncmp(args[0], D_usertty + 8, n))) continue; debug1("AT display %s\n", D_usertty); DoCommand(args + 1, argl + 1); if (display) OutputMsg(0, "command from %s: %s %s", s, args[1], args[2] ? args[2] : ""); display = NULL; fore = NULL; flayer = 0; } break; } case '#': /* window */ n--; /* FALLTHROUGH */ default: { struct win *nw; int ch; n++; ch = args[0][n]; args[0][n] = '\0'; if (!*args[0] || (i = WindowByNumber(args[0])) < 0) { args[0][n] = ch; /* must restore string in case of bind */ /* try looping over titles */ for (fore = windows; fore; fore = nw) { nw = fore->w_next; if (strncmp(args[0], fore->w_title, n)) continue; debug2("AT window %d(%s)\n", fore->w_number, fore->w_title); /* * consider this a bug or a feature: * while looping through windows, we have fore AND * display context. This will confuse users who try to * set up loops inside of loops, but often allows to do * what you mean, even when you adress your context wrong. */ i = 0; /* XXX: other displays? */ if (fore->w_layer.l_cvlist) display = fore->w_layer.l_cvlist->c_display; flayer = fore->w_savelayer ? fore->w_savelayer : &fore->w_layer; DoCommand(args + 1, argl + 1); /* may destroy our display */ if (fore && fore->w_layer.l_cvlist) { display = fore->w_layer.l_cvlist->c_display; OutputMsg(0, "command from %s: %s %s", s, args[1], args[2] ? args[2] : ""); } } display = NULL; fore = NULL; if (i < 0) OutputMsg(0, "%s: at '%s': no such window.\n", rc_name, args[0]); break; } else if (i < maxwin && (fore = wtab[i])) { args[0][n] = ch; /* must restore string in case of bind */ debug2("AT window %d (%s)\n", fore->w_number, fore->w_title); if (fore->w_layer.l_cvlist) display = fore->w_layer.l_cvlist->c_display; flayer = fore->w_savelayer ? fore->w_savelayer : &fore->w_layer; DoCommand(args + 1, argl + 1); if (fore && fore->w_layer.l_cvlist) { display = fore->w_layer.l_cvlist->c_display; OutputMsg(0, "command from %s: %s %s", s, args[1], args[2] ? args[2] : ""); } display = NULL; fore = NULL; } else OutputMsg(0, "%s: at [identifier][%%|*|#] command [args]", rc_name); break; } } free(s); #ifdef MULTIUSER EffectiveAclUser = NULL; #endif break; #ifdef COPY_PASTE case RC_READREG: #ifdef ENCODINGS i = fore ? fore->w_encoding : display ? display->d_encoding : 0; if (args[0] && args[1] && !strcmp(args[0], "-e")) { i = FindEncoding(args[1]); if (i == -1) { OutputMsg(0, "%s: readreg: unknown encoding", rc_name); break; } args += 2; } #endif /* * Without arguments we prompt for a destination register. * It will receive the copybuffer contents. * This is not done by RC_PASTE, as we prompt for source * (not dest) there. */ if ((s = *args) == NULL) { Input("Copy to register:", 1, INP_RAW, copy_reg_fn, NULL, 0); break; } if (*argl != 1) { OutputMsg(0, "%s: copyreg: character, ^x, or (octal) \\032 expected.", rc_name); break; } ch = args[0][0]; /* * With two arguments we *really* read register contents from file */ if (args[1]) { if (args[2]) { OutputMsg(0, "%s: readreg: too many arguments", rc_name); break; } if ((s = ReadFile(args[1], &n))) { struct plop *pp = plop_tab + (int)(unsigned char)ch; if (pp->buf) free(pp->buf); pp->buf = s; pp->len = n; #ifdef ENCODINGS pp->enc = i; #endif } } else /* * with one argument we copy the copybuffer into a specified register * This could be done with RC_PASTE too, but is here to be consistent * with the zero argument call. */ copy_reg_fn(&ch, 0, NULL); break; #endif case RC_REGISTER: #ifdef ENCODINGS i = fore ? fore->w_encoding : display ? display->d_encoding : 0; if (args[0] && args[1] && !strcmp(args[0], "-e")) { i = FindEncoding(args[1]); if (i == -1) { OutputMsg(0, "%s: register: unknown encoding", rc_name); break; } args += 2; argc -= 2; } #endif if (argc != 2) { OutputMsg(0, "%s: register: illegal number of arguments.", rc_name); break; } if (*argl != 1) { OutputMsg(0, "%s: register: character, ^x, or (octal) \\032 expected.", rc_name); break; } ch = args[0][0]; #ifdef COPY_PASTE if (ch == '.') { if (user->u_plop.buf != NULL) UserFreeCopyBuffer(user); if (args[1] && args[1][0]) { user->u_plop.buf = SaveStrn(args[1], argl[1]); user->u_plop.len = argl[1]; #ifdef ENCODINGS user->u_plop.enc = i; #endif } } else #endif { struct plop *plp = plop_tab + (int)(unsigned char)ch; if (plp->buf) free(plp->buf); plp->buf = SaveStrn(args[1], argl[1]); plp->len = argl[1]; #ifdef ENCODINGS plp->enc = i; #endif } break; case RC_PROCESS: if ((s = *args) == NULL) { Input("Process register:", 1, INP_RAW, process_fn, NULL, 0); break; } if (*argl != 1) { OutputMsg(0, "%s: process: character, ^x, or (octal) \\032 expected.", rc_name); break; } ch = args[0][0]; process_fn(&ch, 0, NULL); break; case RC_STUFF: s = *args; if (!args[0]) { Input("Stuff:", 100, INP_COOKED, StuffFin, NULL, 0); break; } n = *argl; if (args[1]) { if (strcmp(s, "-k")) { OutputMsg(0, "%s: stuff: invalid option %s", rc_name, s); break; } s = args[1]; for (i = T_CAPS; i < T_OCAPS; i++) if (strcmp(term[i].tcname, s) == 0) break; if (i == T_OCAPS) { OutputMsg(0, "%s: stuff: unknown key '%s'", rc_name, s); break; } #ifdef MAPKEYS if (StuffKey(i - T_CAPS) == 0) break; #endif s = display ? D_tcs[i].str : 0; if (s == 0) break; n = strlen(s); } while(n) LayProcess(&s, &n); break; case RC_REDISPLAY: Activate(-1); break; case RC_WINDOWS: ShowWindows(-1); break; case RC_VERSION: OutputMsg(0, "screen %s", version); break; case RC_TIME: if (*args) { timestring = SaveStr(*args); break; } OutputMsg(0, "%s", MakeWinMsg(timestring, fore, '%')); break; case RC_INFO: ShowInfo(); break; case RC_DINFO: ShowDInfo(); break; case RC_COMMAND: { struct action *ktabp = ktab; if (argc == 2 && !strcmp(*args, "-c")) { if ((ktabp = FindKtab(args[1], 0)) == 0) { OutputMsg(0, "Unknown command class '%s'", args[1]); break; } } if (D_ESCseen != ktab || ktabp != ktab) { if (D_ESCseen != ktabp) { D_ESCseen = ktabp; WindowChanged(fore, 'E'); } break; } if (D_ESCseen) { D_ESCseen = 0; WindowChanged(fore, 'E'); } } /* FALLTHROUGH */ case RC_OTHER: if (MoreWindows()) SwitchWindow(display && D_other ? D_other->w_number : NextWindow()); break; case RC_META: if (user->u_Esc == -1) break; ch = user->u_Esc; s = &ch; n = 1; LayProcess(&s, &n); break; case RC_XON: ch = Ctrl('q'); s = &ch; n = 1; LayProcess(&s, &n); break; case RC_XOFF: ch = Ctrl('s'); s = &ch; n = 1; LayProcess(&s, &n); break; case RC_DEFBREAKTYPE: case RC_BREAKTYPE: { static char *types[] = { "TIOCSBRK", "TCSBRK", "tcsendbreak", NULL }; extern int breaktype; if (*args) { if (ParseNum(act, &n)) for (n = 0; n < (int)(sizeof(types)/sizeof(*types)); n++) { for (i = 0; i < 4; i++) { ch = args[0][i]; if (ch >= 'a' && ch <= 'z') ch -= 'a' - 'A'; if (ch != types[n][i] && (ch + ('a' - 'A')) != types[n][i]) break; } if (i == 4) break; } if (n < 0 || n >= (int)(sizeof(types)/sizeof(*types))) OutputMsg(0, "%s invalid, chose one of %s, %s or %s", *args, types[0], types[1], types[2]); else { breaktype = n; OutputMsg(0, "breaktype set to (%d) %s", n, types[n]); } } else OutputMsg(0, "breaktype is (%d) %s", breaktype, types[breaktype]); } break; case RC_POW_BREAK: case RC_BREAK: n = 0; if (*args && ParseNum(act, &n)) break; SendBreak(fore, n, nr == RC_POW_BREAK); break; #ifdef LOCK case RC_LOCKSCREEN: Detach(D_LOCK); break; #endif case RC_WIDTH: case RC_HEIGHT: { int w, h; int what = 0; i = 1; if (*args && !strcmp(*args, "-w")) what = 1; else if (*args && !strcmp(*args, "-d")) what = 2; if (what) args++; if (what == 0 && flayer && !display) what = 1; if (what == 1) { if (!flayer) { OutputMsg(0, "%s: %s: window required", rc_name, comms[nr].name); break; } w = flayer->l_width; h = flayer->l_height; } else { if (!display) { OutputMsg(0, "%s: %s: display required", rc_name, comms[nr].name); break; } w = D_width; h = D_height; } if (*args && args[0][0] == '-') { OutputMsg(0, "%s: %s: unknown option %s", rc_name, comms[nr].name, *args); break; } if (nr == RC_HEIGHT) { if (!*args) { #define H0height 42 #define H1height 24 if (h == H0height) h = H1height; else if (h == H1height) h = H0height; else if (h > (H0height + H1height) / 2) h = H0height; else h = H1height; } else { h = atoi(*args); if (args[1]) w = atoi(args[1]); } } else { if (!*args) { if (w == Z0width) w = Z1width; else if (w == Z1width) w = Z0width; else if (w > (Z0width + Z1width) / 2) w = Z0width; else w = Z1width; } else { w = atoi(*args); if (args[1]) h = atoi(args[1]); } } if (*args && args[1] && args[2]) { OutputMsg(0, "%s: %s: too many arguments", rc_name, comms[nr].name); break; } if (w <= 0) { OutputMsg(0, "Illegal width"); break; } if (h <= 0) { OutputMsg(0, "Illegal height"); break; } if (what == 1) { if (flayer->l_width == w && flayer->l_height == h) break; ResizeLayer(flayer, w, h, (struct display *)0); break; } if (D_width == w && D_height == h) break; if (what == 2) { ChangeScreenSize(w, h, 1); } else { if (ResizeDisplay(w, h) == 0) { Activate(D_fore ? D_fore->w_norefresh : 0); /* autofit */ ResizeLayer(D_forecv->c_layer, D_forecv->c_xe - D_forecv->c_xs + 1, D_forecv->c_ye - D_forecv->c_ys + 1, 0); break; } if (h == D_height) OutputMsg(0, "Your termcap does not specify how to change the terminal's width to %d.", w); else if (w == D_width) OutputMsg(0, "Your termcap does not specify how to change the terminal's height to %d.", h); else OutputMsg(0, "Your termcap does not specify how to change the terminal's resolution to %dx%d.", w, h); } } break; case RC_TITLE: if (queryflag >= 0) { if (fore) OutputMsg(0, "%s", fore->w_title); else queryflag = -1; break; } if (*args == 0) InputAKA(); else ChangeAKA(fore, *args, strlen(*args)); break; case RC_COLON: Input(":", 100, INP_EVERY, Colonfin, NULL, 0); if (*args && **args) { s = *args; n = strlen(s); LayProcess(&s, &n); } break; case RC_LASTMSG: if (D_status_lastmsg) OutputMsg(0, "%s", D_status_lastmsg); break; case RC_SCREEN: DoScreen("key", args); break; case RC_WRAP: if (ParseSwitch(act, &fore->w_wrap) == 0 && msgok) OutputMsg(0, "%cwrap", fore->w_wrap ? '+' : '-'); break; case RC_FLOW: if (*args) { if (args[0][0] == 'a') { fore->w_flow = (fore->w_flow & FLOW_AUTO) ? FLOW_AUTOFLAG |FLOW_AUTO|FLOW_NOW : FLOW_AUTOFLAG; } else { if (ParseOnOff(act, &n)) break; fore->w_flow = (fore->w_flow & FLOW_AUTO) | n; } } else { if (fore->w_flow & FLOW_AUTOFLAG) fore->w_flow = (fore->w_flow & FLOW_AUTO) | FLOW_NOW; else if (fore->w_flow & FLOW_NOW) fore->w_flow &= ~FLOW_NOW; else fore->w_flow = fore->w_flow ? FLOW_AUTOFLAG|FLOW_AUTO|FLOW_NOW : FLOW_AUTOFLAG; } SetFlow(fore->w_flow & FLOW_NOW); if (msgok) OutputMsg(0, "%cflow%s", (fore->w_flow & FLOW_NOW) ? '+' : '-', (fore->w_flow & FLOW_AUTOFLAG) ? "(auto)" : ""); break; #ifdef MULTIUSER case RC_DEFWRITELOCK: if (args[0][0] == 'a') nwin_default.wlock = WLOCK_AUTO; else { if (ParseOnOff(act, &n)) break; nwin_default.wlock = n ? WLOCK_ON : WLOCK_OFF; } break; case RC_WRITELOCK: if (*args) { if (args[0][0] == 'a') { fore->w_wlock = WLOCK_AUTO; } else { if (ParseOnOff(act, &n)) break; fore->w_wlock = n ? WLOCK_ON : WLOCK_OFF; } /* * user may have permission to change the writelock setting, * but he may never aquire the lock himself without write permission */ if (!AclCheckPermWin(D_user, ACL_WRITE, fore)) fore->w_wlockuser = D_user; } OutputMsg(0, "writelock %s", (fore->w_wlock == WLOCK_AUTO) ? "auto" : ((fore->w_wlock == WLOCK_OFF) ? "off" : "on")); break; #endif case RC_CLEAR: ResetAnsiState(fore); WriteString(fore, "\033[H\033[J", 6); break; case RC_RESET: ResetAnsiState(fore); #ifdef ZMODEM if (fore->w_zdisplay) zmodem_abort(fore, fore->w_zdisplay); #endif WriteString(fore, "\033c", 2); break; case RC_MONITOR: n = fore->w_monitor != MON_OFF; #ifdef MULTIUSER if (display) n = n && (ACLBYTE(fore->w_mon_notify, D_user->u_id) & ACLBIT(D_user->u_id)); #endif if (ParseSwitch(act, &n)) break; if (n) { #ifdef MULTIUSER if (display) /* we tell only this user */ ACLBYTE(fore->w_mon_notify, D_user->u_id) |= ACLBIT(D_user->u_id); else for (i = 0; i < maxusercount; i++) ACLBYTE(fore->w_mon_notify, i) |= ACLBIT(i); #endif if (fore->w_monitor == MON_OFF) fore->w_monitor = MON_ON; OutputMsg(0, "Window %d (%s) is now being monitored for all activity.", fore->w_number, fore->w_title); } else { #ifdef MULTIUSER if (display) /* we remove only this user */ ACLBYTE(fore->w_mon_notify, D_user->u_id) &= ~ACLBIT(D_user->u_id); else for (i = 0; i < maxusercount; i++) ACLBYTE(fore->w_mon_notify, i) &= ~ACLBIT(i); for (i = maxusercount - 1; i >= 0; i--) if (ACLBYTE(fore->w_mon_notify, i)) break; if (i < 0) #endif fore->w_monitor = MON_OFF; OutputMsg(0, "Window %d (%s) is no longer being monitored for activity.", fore->w_number, fore->w_title); } break; #ifdef MULTI case RC_DISPLAYS: display_displays(); break; #endif case RC_WINDOWLIST: if (!*args) display_windows(0, WLIST_NUM, (struct win *)0); else if (!strcmp(*args, "string")) { if (args[1]) { if (wliststr) free(wliststr); wliststr = SaveStr(args[1]); } if (msgok) OutputMsg(0, "windowlist string is '%s'", wliststr); } else if (!strcmp(*args, "title")) { if (args[1]) { if (wlisttit) free(wlisttit); wlisttit = SaveStr(args[1]); } if (msgok) OutputMsg(0, "windowlist title is '%s'", wlisttit); } else { int flag = 0; int blank = 0; for (i = 0; i < argc; i++) if (!args[i]) continue; else if (!strcmp(args[i], "-m")) flag |= WLIST_MRU; else if (!strcmp(args[i], "-b")) blank = 1; else if (!strcmp(args[i], "-g")) flag |= WLIST_NESTED; else { OutputMsg(0, "usage: windowlist [-b] [-g] [-m] [string [string] | title [title]]"); break; } if (i == argc) display_windows(blank, flag, (struct win *)0); } break; case RC_HELP: if (argc == 2 && !strcmp(*args, "-c")) { struct action *ktabp; if ((ktabp = FindKtab(args[1], 0)) == 0) { OutputMsg(0, "Unknown command class '%s'", args[1]); break; } display_help(args[1], ktabp); } else display_help((char *)0, ktab); break; case RC_LICENSE: display_copyright(); break; #ifdef COPY_PASTE case RC_COPY: if (flayer->l_layfn != &WinLf) { OutputMsg(0, "Must be on a window layer"); break; } MarkRoutine(); WindowChanged(fore, 'P'); break; case RC_HISTORY: { static char *pasteargs[] = {".", 0}; static int pasteargl[] = {1}; if (flayer->l_layfn != &WinLf) { OutputMsg(0, "Must be on a window layer"); break; } if (GetHistory() == 0) break; if (user->u_plop.buf == NULL) break; args = pasteargs; argl = pasteargl; } /*FALLTHROUGH*/ case RC_PASTE: { char *ss, *dbuf, dch; int l = 0; # ifdef ENCODINGS int enc = -1; # endif /* * without args we prompt for one(!) register to be pasted in the window */ if ((s = *args) == NULL) { Input("Paste from register:", 1, INP_RAW, ins_reg_fn, NULL, 0); break; } if (args[1] == 0 && !fore) /* no window? */ break; /* * with two arguments we paste into a destination register * (no window needed here). */ if (args[1] && argl[1] != 1) { OutputMsg(0, "%s: paste destination: character, ^x, or (octal) \\032 expected.", rc_name); break; } # ifdef ENCODINGS else if (fore) enc = fore->w_encoding; # endif /* * measure length of needed buffer */ for (ss = s = *args; (ch = *ss); ss++) { if (ch == '.') { # ifdef ENCODINGS if (enc == -1) enc = user->u_plop.enc; if (enc != user->u_plop.enc) l += RecodeBuf((unsigned char *)user->u_plop.buf, user->u_plop.len, user->u_plop.enc, enc, (unsigned char *)0); else # endif l += user->u_plop.len; } else { # ifdef ENCODINGS if (enc == -1) enc = plop_tab[(int)(unsigned char)ch].enc; if (enc != plop_tab[(int)(unsigned char)ch].enc) l += RecodeBuf((unsigned char *)plop_tab[(int)(unsigned char)ch].buf, plop_tab[(int)(unsigned char)ch].len, plop_tab[(int)(unsigned char)ch].enc, enc, (unsigned char *)0); else # endif l += plop_tab[(int)(unsigned char)ch].len; } } if (l == 0) { OutputMsg(0, "empty buffer"); break; } /* * shortcut: * if there is only one source and the destination is a window, then * pass a pointer rather than duplicating the buffer. */ if (s[1] == 0 && args[1] == 0) # ifdef ENCODINGS if (enc == (*s == '.' ? user->u_plop.enc : plop_tab[(int)(unsigned char)*s].enc)) # endif { MakePaster(&fore->w_paster, *s == '.' ? user->u_plop.buf : plop_tab[(int)(unsigned char)*s].buf, l, 0); break; } /* * if no shortcut, we construct a buffer */ if ((dbuf = (char *)malloc(l)) == 0) { OutputMsg(0, "%s", strnomem); break; } l = 0; /* * concatenate all sources into our own buffer, copy buffer is * special and is skipped if no display exists. */ for (ss = s; (ch = *ss); ss++) { struct plop *pp = (ch == '.' ? &user->u_plop : &plop_tab[(int)(unsigned char)ch]); #ifdef ENCODINGS if (pp->enc != enc) { l += RecodeBuf((unsigned char *)pp->buf, pp->len, pp->enc, enc, (unsigned char *)dbuf + l); continue; } #endif bcopy(pp->buf, dbuf + l, pp->len); l += pp->len; } /* * when called with one argument we paste our buffer into the window */ if (args[1] == 0) { MakePaster(&fore->w_paster, dbuf, l, 1); } else { /* * we have two arguments, the second is already in dch. * use this as destination rather than the window. */ dch = args[1][0]; if (dch == '.') { if (user->u_plop.buf != NULL) UserFreeCopyBuffer(user); user->u_plop.buf = dbuf; user->u_plop.len = l; #ifdef ENCODINGS user->u_plop.enc = enc; #endif } else { struct plop *pp = plop_tab + (int)(unsigned char)dch; if (pp->buf) free(pp->buf); pp->buf = dbuf; pp->len = l; #ifdef ENCODINGS pp->enc = enc; #endif } } break; } case RC_WRITEBUF: if (!user->u_plop.buf) { OutputMsg(0, "empty buffer"); break; } #ifdef ENCODINGS { struct plop oldplop; oldplop = user->u_plop; if (args[0] && args[1] && !strcmp(args[0], "-e")) { int enc, l; char *newbuf; enc = FindEncoding(args[1]); if (enc == -1) { OutputMsg(0, "%s: writebuf: unknown encoding", rc_name); break; } if (enc != oldplop.enc) { l = RecodeBuf((unsigned char *)oldplop.buf, oldplop.len, oldplop.enc, enc, (unsigned char *)0); newbuf = malloc(l + 1); if (!newbuf) { OutputMsg(0, "%s", strnomem); break; } user->u_plop.len = RecodeBuf((unsigned char *)oldplop.buf, oldplop.len, oldplop.enc, enc, (unsigned char *)newbuf); user->u_plop.buf = newbuf; user->u_plop.enc = enc; } args += 2; } #endif if (args[0] && args[1]) OutputMsg(0, "%s: writebuf: too many arguments", rc_name); else WriteFile(user, args[0], DUMP_EXCHANGE); #ifdef ENCODINGS if (user->u_plop.buf != oldplop.buf) free(user->u_plop.buf); user->u_plop = oldplop; } #endif break; case RC_READBUF: #ifdef ENCODINGS i = fore ? fore->w_encoding : display ? display->d_encoding : 0; if (args[0] && args[1] && !strcmp(args[0], "-e")) { i = FindEncoding(args[1]); if (i == -1) { OutputMsg(0, "%s: readbuf: unknown encoding", rc_name); break; } args += 2; } #endif if (args[0] && args[1]) { OutputMsg(0, "%s: readbuf: too many arguments", rc_name); break; } if ((s = ReadFile(args[0] ? args[0] : BufferFile, &n))) { if (user->u_plop.buf) UserFreeCopyBuffer(user); user->u_plop.len = n; user->u_plop.buf = s; #ifdef ENCODINGS user->u_plop.enc = i; #endif } break; case RC_REMOVEBUF: KillBuffers(); break; case RC_IGNORECASE: (void)ParseSwitch(act, &search_ic); if (msgok) OutputMsg(0, "Will %signore case in searches", search_ic ? "" : "not "); break; #endif /* COPY_PASTE */ case RC_ESCAPE: if (*argl == 0) SetEscape(user, -1, -1); else if (*argl == 2) SetEscape(user, (int)(unsigned char)args[0][0], (int)(unsigned char)args[0][1]); else { OutputMsg(0, "%s: two characters required after escape.", rc_name); break; } /* Change defescape if master user. This is because we only * have one ktab. */ if (display && user != users) break; /* FALLTHROUGH */ case RC_DEFESCAPE: if (*argl == 0) SetEscape(NULL, -1, -1); else if (*argl == 2) SetEscape(NULL, (int)(unsigned char)args[0][0], (int)(unsigned char)args[0][1]); else { OutputMsg(0, "%s: two characters required after defescape.", rc_name); break; } #ifdef MAPKEYS CheckEscape(); #endif break; case RC_CHDIR: s = *args ? *args : home; if (chdir(s) == -1) OutputMsg(errno, "%s", s); break; case RC_SHELL: case RC_DEFSHELL: if (ParseSaveStr(act, &ShellProg) == 0) ShellArgs[0] = ShellProg; break; case RC_HARDCOPYDIR: if (*args) (void)ParseSaveStr(act, &hardcopydir); if (msgok) OutputMsg(0, "hardcopydir is %s\n", hardcopydir && *hardcopydir ? hardcopydir : ""); break; case RC_LOGFILE: if (*args) { if (args[1] && !(strcmp(*args, "flush"))) { log_flush = atoi(args[1]); if (msgok) OutputMsg(0, "log flush timeout set to %ds\n", log_flush); break; } if (ParseSaveStr(act, &screenlogfile) || !msgok) break; } OutputMsg(0, "logfile is '%s'", screenlogfile); break; case RC_LOGTSTAMP: if (!*args || !strcmp(*args, "on") || !strcmp(*args, "off")) { if (ParseSwitch(act, &logtstamp_on) == 0 && msgok) OutputMsg(0, "timestamps turned %s", logtstamp_on ? "on" : "off"); } else if (!strcmp(*args, "string")) { if (args[1]) { if (logtstamp_string) free(logtstamp_string); logtstamp_string = SaveStr(args[1]); } if (msgok) OutputMsg(0, "logfile timestamp is '%s'", logtstamp_string); } else if (!strcmp(*args, "after")) { if (args[1]) { logtstamp_after = atoi(args[1]); if (!msgok) break; } OutputMsg(0, "timestamp printed after %ds\n", logtstamp_after); } else OutputMsg(0, "usage: logtstamp [after [n]|string [str]|on|off]"); break; case RC_SHELLTITLE: (void)ParseSaveStr(act, &nwin_default.aka); break; case RC_TERMCAP: case RC_TERMCAPINFO: case RC_TERMINFO: if (!rc_name || !*rc_name) OutputMsg(0, "Sorry, too late now. Place that in your .screenrc file."); break; case RC_SLEEP: break; /* Already handled */ case RC_TERM: s = NULL; if (ParseSaveStr(act, &s)) break; if (strlen(s) >= 20) { OutputMsg(0, "%s: term: argument too long ( < 20)", rc_name); free(s); break; } strcpy(screenterm, s); free(s); debug1("screenterm set to %s\n", screenterm); MakeTermcap((display == 0)); debug("new termcap made\n"); break; case RC_ECHO: if (!msgok && (!rc_name || strcmp(rc_name, "-X"))) break; /* * user typed ^A:echo... well, echo isn't FinishRc's job, * but as he wanted to test us, we show good will */ if (argc > 1 && !strcmp(*args, "-n")) { args++; argc--; } s = *args; if (argc > 1 && !strcmp(*args, "-p")) { args++; argc--; s = *args; if (s) s = MakeWinMsg(s, fore, '%'); } if (s) OutputMsg(0, "%s", s); else { OutputMsg(0, "%s: 'echo [-n] [-p] \"string\"' expected.", rc_name); queryflag = -1; } break; case RC_BELL: case RC_BELL_MSG: if (*args == 0) { char buf[256]; AddXChars(buf, sizeof(buf), BellString); OutputMsg(0, "bell_msg is '%s'", buf); break; } (void)ParseSaveStr(act, &BellString); break; #ifdef COPY_PASTE case RC_BUFFERFILE: if (*args == 0) BufferFile = SaveStr(DEFAULT_BUFFERFILE); else if (ParseSaveStr(act, &BufferFile)) break; if (msgok) OutputMsg(0, "Bufferfile is now '%s'", BufferFile); break; #endif case RC_ACTIVITY: (void)ParseSaveStr(act, &ActivityString); break; #if defined(DETACH) && defined(POW_DETACH) case RC_POW_DETACH_MSG: if (*args == 0) { char buf[256]; AddXChars(buf, sizeof(buf), PowDetachString); OutputMsg(0, "pow_detach_msg is '%s'", buf); break; } (void)ParseSaveStr(act, &PowDetachString); break; #endif #if defined(UTMPOK) && defined(LOGOUTOK) case RC_LOGIN: n = fore->w_slot != (slot_t)-1; if (*args && !strcmp(*args, "always")) { fore->w_lflag = 3; if (!displays && n) SlotToggle(n); break; } if (*args && !strcmp(*args, "attached")) { fore->w_lflag = 1; if (!displays && n) SlotToggle(0); break; } if (ParseSwitch(act, &n) == 0) SlotToggle(n); break; case RC_DEFLOGIN: if (!strcmp(*args, "always")) nwin_default.lflag |= 2; else if (!strcmp(*args, "attached")) nwin_default.lflag &= ~2; else (void)ParseOnOff(act, &nwin_default.lflag); break; #endif case RC_DEFFLOW: if (args[0] && args[1] && args[1][0] == 'i') { iflag = 1; for (display = displays; display; display = display->d_next) { if (!D_flow) continue; #if defined(TERMIO) || defined(POSIX) D_NewMode.tio.c_cc[VINTR] = D_OldMode.tio.c_cc[VINTR]; D_NewMode.tio.c_lflag |= ISIG; #else /* TERMIO || POSIX */ D_NewMode.m_tchars.t_intrc = D_OldMode.m_tchars.t_intrc; #endif /* TERMIO || POSIX */ SetTTY(D_userfd, &D_NewMode); } } if (args[0] && args[0][0] == 'a') nwin_default.flowflag = FLOW_AUTOFLAG; else (void)ParseOnOff(act, &nwin_default.flowflag); break; case RC_DEFWRAP: (void)ParseOnOff(act, &nwin_default.wrap); break; case RC_DEFC1: (void)ParseOnOff(act, &nwin_default.c1); break; #ifdef COLOR case RC_DEFBCE: (void)ParseOnOff(act, &nwin_default.bce); break; #endif case RC_DEFGR: (void)ParseOnOff(act, &nwin_default.gr); break; case RC_DEFMONITOR: if (ParseOnOff(act, &n) == 0) nwin_default.monitor = (n == 0) ? MON_OFF : MON_ON; break; case RC_DEFMOUSETRACK: if (ParseOnOff(act, &n) == 0) defmousetrack = (n == 0) ? 0 : 1000; break; case RC_MOUSETRACK: if (!args[0]) { OutputMsg(0, "Mouse tracking for this display is turned %s", D_mousetrack ? "on" : "off"); } else if (ParseOnOff(act, &n) == 0) { D_mousetrack = n == 0 ? 0 : 1000; if (D_fore) MouseMode(D_fore->w_mouse); } break; case RC_DEFSILENCE: if (ParseOnOff(act, &n) == 0) nwin_default.silence = (n == 0) ? SILENCE_OFF : SILENCE_ON; break; case RC_VERBOSE: if (!*args) OutputMsg(0, "W%s echo command when creating windows.", VerboseCreate ? "ill" : "on't"); else if (ParseOnOff(act, &n) == 0) VerboseCreate = n; break; case RC_HARDSTATUS: if (display) { OutputMsg(0, "%s", ""); /* wait till mintime (keep gcc quiet) */ RemoveStatus(); } if (args[0] && strcmp(args[0], "on") && strcmp(args[0], "off")) { struct display *olddisplay = display; int old_use, new_use = -1; s = args[0]; if (!strncmp(s, "always", 6)) s += 6; if (!strcmp(s, "lastline")) new_use = HSTATUS_LASTLINE; else if (!strcmp(s, "ignore")) new_use = HSTATUS_IGNORE; else if (!strcmp(s, "message")) new_use = HSTATUS_MESSAGE; else if (!strcmp(args[0], "string")) { if (!args[1]) { char buf[256]; AddXChars(buf, sizeof(buf), hstatusstring); OutputMsg(0, "hardstatus string is '%s'", buf); break; } } else { OutputMsg(0, "%s: usage: hardstatus [always]lastline|ignore|message|string [string]", rc_name); break; } if (new_use != -1) { hardstatusemu = new_use | (s == args[0] ? 0 : HSTATUS_ALWAYS); for (display = displays; display; display = display->d_next) { RemoveStatus(); new_use = hardstatusemu & ~HSTATUS_ALWAYS; if (D_HS && s == args[0]) new_use = HSTATUS_HS; ShowHStatus((char *)0); old_use = D_has_hstatus; D_has_hstatus = new_use; if ((new_use == HSTATUS_LASTLINE && old_use != HSTATUS_LASTLINE) || (new_use != HSTATUS_LASTLINE && old_use == HSTATUS_LASTLINE)) ChangeScreenSize(D_width, D_height, 1); RefreshHStatus(); } } if (args[1]) { if (hstatusstring) free(hstatusstring); hstatusstring = SaveStr(args[1]); for (display = displays; display; display = display->d_next) RefreshHStatus(); } display = olddisplay; break; } (void)ParseSwitch(act, &use_hardstatus); if (msgok) OutputMsg(0, "messages displayed on %s", use_hardstatus ? "hardstatus line" : "window"); break; case RC_CAPTION: if (strcmp(args[0], "always") == 0 || strcmp(args[0], "splitonly") == 0) { struct display *olddisplay = display; captionalways = args[0][0] == 'a'; for (display = displays; display; display = display->d_next) ChangeScreenSize(D_width, D_height, 1); display = olddisplay; } else if (strcmp(args[0], "string") == 0) { if (!args[1]) { char buf[256]; AddXChars(buf, sizeof(buf), captionstring); OutputMsg(0, "caption string is '%s'", buf); break; } } else { OutputMsg(0, "%s: usage: caption always|splitonly|string ", rc_name); break; } if (!args[1]) break; if (captionstring) free(captionstring); captionstring = SaveStr(args[1]); RedisplayDisplays(0); break; case RC_CONSOLE: n = (console_window != 0); if (ParseSwitch(act, &n)) break; if (TtyGrabConsole(fore->w_ptyfd, n, rc_name)) break; if (n == 0) OutputMsg(0, "%s: releasing console %s", rc_name, HostName); else if (console_window) OutputMsg(0, "%s: stealing console %s from window %d (%s)", rc_name, HostName, console_window->w_number, console_window->w_title); else OutputMsg(0, "%s: grabbing console %s", rc_name, HostName); console_window = n ? fore : 0; break; case RC_ALLPARTIAL: if (ParseOnOff(act, &all_norefresh)) break; if (!all_norefresh && fore) Activate(-1); if (msgok) OutputMsg(0, all_norefresh ? "No refresh on window change!\n" : "Window specific refresh\n"); break; case RC_PARTIAL: (void)ParseSwitch(act, &n); fore->w_norefresh = n; break; case RC_VBELL: if (ParseSwitch(act, &visual_bell) || !msgok) break; if (visual_bell == 0) OutputMsg(0, "switched to audible bell."); else OutputMsg(0, "switched to visual bell."); break; case RC_VBELLWAIT: if (ParseNum1000(act, &VBellWait) == 0 && msgok) OutputMsg(0, "vbellwait set to %.10g seconds", VBellWait/1000.); break; case RC_MSGWAIT: if (ParseNum1000(act, &MsgWait) == 0 && msgok) OutputMsg(0, "msgwait set to %.10g seconds", MsgWait/1000.); break; case RC_MSGMINWAIT: if (ParseNum1000(act, &MsgMinWait) == 0 && msgok) OutputMsg(0, "msgminwait set to %.10g seconds", MsgMinWait/1000.); break; case RC_SILENCEWAIT: if (ParseNum(act, &SilenceWait)) break; if (SilenceWait < 1) SilenceWait = 1; for (p = windows; p; p = p->w_next) p->w_silencewait = SilenceWait; if (msgok) OutputMsg(0, "silencewait set to %d seconds", SilenceWait); break; case RC_NUMBER: if (*args == 0) OutputMsg(0, queryflag >= 0 ? "%d (%s)" : "This is window %d (%s).", fore->w_number, fore->w_title); else { int old = fore->w_number; int rel = 0, parse; if (args[0][0] == '+') rel = 1; else if (args[0][0] == '-') rel = -1; if (rel) ++act->args[0]; parse = ParseNum(act, &n); if (rel) --act->args[0]; if (parse) break; if (rel > 0) n += old; else if (rel < 0) n = old - n; if (!WindowChangeNumber(fore, n)) { /* Window number could not be changed. */ queryflag = -1; return; } } break; case RC_SILENCE: n = fore->w_silence != 0; i = fore->w_silencewait; if (args[0] && (args[0][0] == '-' || (args[0][0] >= '0' && args[0][0] <= '9'))) { if (ParseNum(act, &i)) break; n = i > 0; } else if (ParseSwitch(act, &n)) break; if (n) { #ifdef MULTIUSER if (display) /* we tell only this user */ ACLBYTE(fore->w_lio_notify, D_user->u_id) |= ACLBIT(D_user->u_id); else for (n = 0; n < maxusercount; n++) ACLBYTE(fore->w_lio_notify, n) |= ACLBIT(n); #endif fore->w_silencewait = i; fore->w_silence = SILENCE_ON; SetTimeout(&fore->w_silenceev, fore->w_silencewait * 1000); evenq(&fore->w_silenceev); if (!msgok) break; OutputMsg(0, "The window is now being monitored for %d sec. silence.", fore->w_silencewait); } else { #ifdef MULTIUSER if (display) /* we remove only this user */ ACLBYTE(fore->w_lio_notify, D_user->u_id) &= ~ACLBIT(D_user->u_id); else for (n = 0; n < maxusercount; n++) ACLBYTE(fore->w_lio_notify, n) &= ~ACLBIT(n); for (i = maxusercount - 1; i >= 0; i--) if (ACLBYTE(fore->w_lio_notify, i)) break; if (i < 0) #endif { fore->w_silence = SILENCE_OFF; evdeq(&fore->w_silenceev); } if (!msgok) break; OutputMsg(0, "The window is no longer being monitored for silence."); } break; #ifdef COPY_PASTE case RC_DEFSCROLLBACK: (void)ParseNum(act, &nwin_default.histheight); break; case RC_SCROLLBACK: if (flayer->l_layfn == &MarkLf) { OutputMsg(0, "Cannot resize scrollback buffer in copy/scrollback mode."); break; } (void)ParseNum(act, &n); ChangeWindowSize(fore, fore->w_width, fore->w_height, n); if (msgok) OutputMsg(0, "scrollback set to %d", fore->w_histheight); break; #endif case RC_SESSIONNAME: if (*args == 0) OutputMsg(0, "This session is named '%s'\n", SockName); else { char buf[MAXPATHLEN]; s = 0; if (ParseSaveStr(act, &s)) break; if (!*s || strlen(s) + (SockName - SockPath) > MAXPATHLEN - 13 || index(s, '/')) { OutputMsg(0, "%s: bad session name '%s'\n", rc_name, s); free(s); break; } strncpy(buf, SockPath, SockName - SockPath); sprintf(buf + (SockName - SockPath), "%d.%s", (int)getpid(), s); free(s); if ((access(buf, F_OK) == 0) || (errno != ENOENT)) { OutputMsg(0, "%s: inappropriate path: '%s'.", rc_name, buf); break; } if (rename(SockPath, buf)) { OutputMsg(errno, "%s: failed to rename(%s, %s)", rc_name, SockPath, buf); break; } debug2("rename(%s, %s) done\n", SockPath, buf); strcpy(SockPath, buf); MakeNewEnv(); WindowChanged((struct win *)0, 'S'); } break; case RC_SETENV: if (!args[0] || !args[1]) { debug1("RC_SETENV arguments missing: %s\n", args[0] ? args[0] : ""); InputSetenv(args[0]); } else { xsetenv(args[0], args[1]); MakeNewEnv(); } break; case RC_UNSETENV: unsetenv(*args); MakeNewEnv(); break; #ifdef COPY_PASTE case RC_DEFSLOWPASTE: (void)ParseNum(act, &nwin_default.slow); break; case RC_SLOWPASTE: if (*args == 0) OutputMsg(0, fore->w_slowpaste ? "Slowpaste in window %d is %d milliseconds." : "Slowpaste in window %d is unset.", fore->w_number, fore->w_slowpaste); else if (ParseNum(act, &fore->w_slowpaste) == 0 && msgok) OutputMsg(0, fore->w_slowpaste ? "Slowpaste in window %d set to %d milliseconds." : "Slowpaste in window %d now unset.", fore->w_number, fore->w_slowpaste); break; case RC_MARKKEYS: if (CompileKeys(*args, *argl, mark_key_tab)) { OutputMsg(0, "%s: markkeys: syntax error.", rc_name); break; } debug1("markkeys %s\n", *args); break; # ifdef FONT case RC_PASTEFONT: if (ParseSwitch(act, &pastefont) == 0 && msgok) OutputMsg(0, "Will %spaste font settings", pastefont ? "" : "not "); break; # endif case RC_CRLF: (void)ParseSwitch(act, &join_with_cr); break; case RC_COMPACTHIST: if (ParseSwitch(act, &compacthist) == 0 && msgok) OutputMsg(0, "%scompacting history lines", compacthist ? "" : "not "); break; #endif #ifdef NETHACK case RC_NETHACK: (void)ParseOnOff(act, &nethackflag); break; #endif case RC_HARDCOPY_APPEND: (void)ParseOnOff(act, &hardcopy_append); break; case RC_VBELL_MSG: if (*args == 0) { char buf[256]; AddXChars(buf, sizeof(buf), VisualBellString); OutputMsg(0, "vbell_msg is '%s'", buf); break; } (void)ParseSaveStr(act, &VisualBellString); debug1(" new vbellstr '%s'\n", VisualBellString); break; case RC_DEFMODE: if (ParseBase(act, *args, &n, 8, "octal")) break; if (n < 0 || n > 0777) { OutputMsg(0, "%s: mode: Invalid tty mode %o", rc_name, n); break; } TtyMode = n; if (msgok) OutputMsg(0, "Ttymode set to %03o", TtyMode); break; case RC_AUTODETACH: (void)ParseOnOff(act, &auto_detach); break; case RC_STARTUP_MESSAGE: (void)ParseOnOff(act, &default_startup); break; #ifdef PASSWORD case RC_PASSWORD: if (*args) { n = (*user->u_password) ? 1 : 0; if (user->u_password != NullStr) free((char *)user->u_password); user->u_password = SaveStr(*args); if (!strcmp(user->u_password, "none")) { if (n) OutputMsg(0, "Password checking disabled"); free(user->u_password); user->u_password = NullStr; } } else { if (!fore) { OutputMsg(0, "%s: password: window required", rc_name); break; } Input("New screen password:", 100, INP_NOECHO, pass1, display ? (char *)D_user : (char *)users, 0); } break; #endif /* PASSWORD */ case RC_BIND: { struct action *ktabp = ktab; int kflag = 0; for (;;) { if (argc > 2 && !strcmp(*args, "-c")) { ktabp = FindKtab(args[1], 1); if (ktabp == 0) break; args += 2; argl += 2; argc -= 2; } else if (argc > 1 && !strcmp(*args, "-k")) { kflag = 1; args++; argl++; argc--; } else break; } #ifdef MAPKEYS if (kflag) { for (n = 0; n < KMAP_KEYS; n++) if (strcmp(term[n + T_CAPS].tcname, *args) == 0) break; if (n == KMAP_KEYS) { OutputMsg(0, "%s: bind: unknown key '%s'", rc_name, *args); break; } n += 256; } else #endif if (*argl != 1) { OutputMsg(0, "%s: bind: character, ^x, or (octal) \\032 expected.", rc_name); break; } else n = (unsigned char)args[0][0]; if (args[1]) { if ((i = FindCommnr(args[1])) == RC_ILLEGAL) { OutputMsg(0, "%s: bind: unknown command '%s'", rc_name, args[1]); break; } if (CheckArgNum(i, args + 2) < 0) break; ClearAction(&ktabp[n]); SaveAction(ktabp + n, i, args + 2, argl + 2); } else ClearAction(&ktabp[n]); } break; #ifdef MAPKEYS case RC_BINDKEY: { struct action *newact; int newnr, fl = 0, kf = 0, af = 0, df = 0, mf = 0; struct display *odisp = display; int used = 0; struct kmap_ext *kme = NULL; for (; *args && **args == '-'; args++, argl++) { if (strcmp(*args, "-t") == 0) fl = KMAP_NOTIMEOUT; else if (strcmp(*args, "-k") == 0) kf = 1; else if (strcmp(*args, "-a") == 0) af = 1; else if (strcmp(*args, "-d") == 0) df = 1; else if (strcmp(*args, "-m") == 0) mf = 1; else if (strcmp(*args, "--") == 0) { args++; argl++; break; } else { OutputMsg(0, "%s: bindkey: invalid option %s", rc_name, *args); return; } } if (df && mf) { OutputMsg(0, "%s: bindkey: -d does not work with -m", rc_name); break; } if (*args == 0) { if (mf) display_bindkey("Edit mode", mmtab); else if (df) display_bindkey("Default", dmtab); else display_bindkey("User", umtab); break; } if (kf == 0) { if (af) { OutputMsg(0, "%s: bindkey: -a only works with -k", rc_name); break; } if (*argl == 0) { OutputMsg(0, "%s: bindkey: empty string makes no sense", rc_name); break; } for (i = 0, kme = kmap_exts; i < kmap_extn; i++, kme++) if (kme->str == 0) { if (args[1]) break; } else if (*argl == (kme->fl & ~KMAP_NOTIMEOUT) && bcmp(kme->str, *args, *argl) == 0) break; if (i == kmap_extn) { if (!args[1]) { OutputMsg(0, "%s: bindkey: keybinding not found", rc_name); break; } kmap_extn += 8; kmap_exts = (struct kmap_ext *)xrealloc((char *)kmap_exts, kmap_extn * sizeof(*kmap_exts)); kme = kmap_exts + i; bzero((char *)kme, 8 * sizeof(*kmap_exts)); for (; i < kmap_extn; i++, kme++) { kme->str = 0; kme->dm.nr = kme->mm.nr = kme->um.nr = RC_ILLEGAL; kme->dm.args = kme->mm.args = kme->um.args = noargs; kme->dm.argl = kme->mm.argl = kme->um.argl = 0; } i -= 8; kme -= 8; } if (df == 0 && kme->dm.nr != RC_ILLEGAL) used = 1; if (mf == 0 && kme->mm.nr != RC_ILLEGAL) used = 1; if ((df || mf) && kme->um.nr != RC_ILLEGAL) used = 1; i += KMAP_KEYS + KMAP_AKEYS; newact = df ? &kme->dm : mf ? &kme->mm : &kme->um; } else { for (i = T_CAPS; i < T_OCAPS; i++) if (strcmp(term[i].tcname, *args) == 0) break; if (i == T_OCAPS) { OutputMsg(0, "%s: bindkey: unknown key '%s'", rc_name, *args); break; } if (af && i >= T_CURSOR && i < T_OCAPS) i -= T_CURSOR - KMAP_KEYS; else i -= T_CAPS; newact = df ? &dmtab[i] : mf ? &mmtab[i] : &umtab[i]; } if (args[1]) { if ((newnr = FindCommnr(args[1])) == RC_ILLEGAL) { OutputMsg(0, "%s: bindkey: unknown command '%s'", rc_name, args[1]); break; } if (CheckArgNum(newnr, args + 2) < 0) break; ClearAction(newact); SaveAction(newact, newnr, args + 2, argl + 2); if (kf == 0 && args[1]) { if (kme->str) free(kme->str); kme->str = SaveStrn(*args, *argl); kme->fl = fl | *argl; } } else ClearAction(newact); for (display = displays; display; display = display->d_next) remap(i, args[1] ? 1 : 0); if (kf == 0 && !args[1]) { if (!used && kme->str) { free(kme->str); kme->str = 0; kme->fl = 0; } } display = odisp; } break; case RC_MAPTIMEOUT: if (*args) { if (ParseNum(act, &n)) break; if (n < 0) { OutputMsg(0, "%s: maptimeout: illegal time %d", rc_name, n); break; } maptimeout = n; } if (*args == 0 || msgok) OutputMsg(0, "maptimeout is %dms", maptimeout); break; case RC_MAPNOTNEXT: D_dontmap = 1; break; case RC_MAPDEFAULT: D_mapdefault = 1; break; #endif #ifdef MULTIUSER case RC_ACLCHG: case RC_ACLADD: case RC_ADDACL: case RC_CHACL: UsersAcl(NULL, argc, args); break; case RC_ACLDEL: if (UserDel(args[0], NULL)) break; if (msgok) OutputMsg(0, "%s removed from acl database", args[0]); break; case RC_ACLGRP: /* * modify a user to gain or lose rights granted to a group. * This group is actually a normal user whose rights were defined * with chacl in the usual way. */ if (args[1]) { if (strcmp(args[1], "none")) /* link a user to another user */ { if (AclLinkUser(args[0], args[1])) break; if (msgok) OutputMsg(0, "User %s joined acl-group %s", args[0], args[1]); } else /* remove all groups from user */ { struct acluser *u; struct aclusergroup *g; if (!(u = *FindUserPtr(args[0]))) break; while ((g = u->u_group)) { u->u_group = g->next; free((char *)g); } } } else /* show all groups of user */ { char buf[256], *p = buf; int ngroups = 0; struct acluser *u; struct aclusergroup *g; if (!(u = *FindUserPtr(args[0]))) { if (msgok) OutputMsg(0, "User %s does not exist.", args[0]); break; } g = u->u_group; while (g) { ngroups++; sprintf(p, "%s ", g->u->u_name); p += strlen(p); if (p > buf+200) break; g = g->next; } if (ngroups) *(--p) = '\0'; OutputMsg(0, "%s's group%s: %s.", args[0], (ngroups == 1) ? "" : "s", (ngroups == 0) ? "none" : buf); } break; case RC_ACLUMASK: case RC_UMASK: while ((s = *args++)) { char *err = 0; if (AclUmask(display ? D_user : users, s, &err)) OutputMsg(0, "umask: %s\n", err); } break; case RC_MULTIUSER: if (ParseOnOff(act, &n)) break; multi = n ? "" : 0; chsock(); if (msgok) OutputMsg(0, "Multiuser mode %s", multi ? "enabled" : "disabled"); break; #endif /* MULTIUSER */ #ifdef PSEUDOS case RC_EXEC: winexec(args); break; #endif #ifdef MULTI case RC_NONBLOCK: i = D_nonblock >= 0; if (*args && ((args[0][0] >= '0' && args[0][0] <= '9') || args[0][0] == '.')) { if (ParseNum1000(act, &i)) break; } else if (!ParseSwitch(act, &i)) i = i == 0 ? -1 : 1000; else break; if (msgok && i == -1) OutputMsg(0, "display set to blocking mode"); else if (msgok && i == 0) OutputMsg(0, "display set to nonblocking mode, no timeout"); else if (msgok) OutputMsg(0, "display set to nonblocking mode, %.10gs timeout", i/1000.); D_nonblock = i; if (D_nonblock <= 0) evdeq(&D_blockedev); break; case RC_DEFNONBLOCK: if (*args && ((args[0][0] >= '0' && args[0][0] <= '9') || args[0][0] == '.')) { if (ParseNum1000(act, &defnonblock)) break; } else if (!ParseOnOff(act, &defnonblock)) defnonblock = defnonblock == 0 ? -1 : 1000; else break; if (display && *rc_name) { D_nonblock = defnonblock; if (D_nonblock <= 0) evdeq(&D_blockedev); } break; #endif case RC_GR: #ifdef ENCODINGS if (fore->w_gr == 2) fore->w_gr = 0; #endif if (ParseSwitch(act, &fore->w_gr) == 0 && msgok) OutputMsg(0, "Will %suse GR", fore->w_gr ? "" : "not "); #ifdef ENCODINGS if (fore->w_gr == 0 && fore->w_FontE) fore->w_gr = 2; #endif break; case RC_C1: if (ParseSwitch(act, &fore->w_c1) == 0 && msgok) OutputMsg(0, "Will %suse C1", fore->w_c1 ? "" : "not "); break; #ifdef COLOR case RC_BCE: if (ParseSwitch(act, &fore->w_bce) == 0 && msgok) OutputMsg(0, "Will %serase with background color", fore->w_bce ? "" : "not "); break; #endif #ifdef ENCODINGS case RC_KANJI: case RC_ENCODING: #ifdef UTF8 if (*args && !strcmp(args[0], "-d")) { if (!args[1]) OutputMsg(0, "encodings directory is %s", screenencodings ? screenencodings : ""); else { free(screenencodings); screenencodings = SaveStr(args[1]); } break; } if (*args && !strcmp(args[0], "-l")) { if (!args[1]) OutputMsg(0, "encoding: -l: argument required"); else if (LoadFontTranslation(-1, args[1])) OutputMsg(0, "encoding: could not load utf8 encoding file"); else if (msgok) OutputMsg(0, "encoding: utf8 encoding file loaded"); break; } #else if (*args && (!strcmp(args[0], "-l") || !strcmp(args[0], "-d"))) { if (msgok) OutputMsg(0, "encoding: screen is not compiled for UTF-8."); break; } #endif for (i = 0; i < 2; i++) { if (args[i] == 0) break; if (!strcmp(args[i], ".")) continue; n = FindEncoding(args[i]); if (n == -1) { OutputMsg(0, "encoding: unknown encoding '%s'", args[i]); break; } if (i == 0 && fore) { WinSwitchEncoding(fore, n); ResetCharsets(fore); } else if (i && display) D_encoding = n; } break; case RC_DEFKANJI: case RC_DEFENCODING: n = FindEncoding(*args); if (n == -1) { OutputMsg(0, "defencoding: unknown encoding '%s'", *args); break; } nwin_default.encoding = n; break; #endif #ifdef UTF8 case RC_DEFUTF8: n = nwin_default.encoding == UTF8; if (ParseSwitch(act, &n) == 0) { nwin_default.encoding = n ? UTF8 : 0; if (msgok) OutputMsg(0, "Will %suse UTF-8 encoding for new windows", n ? "" : "not "); } break; case RC_UTF8: for (i = 0; i < 2; i++) { if (i && args[i] == 0) break; if (args[i] == 0) n = fore->w_encoding != UTF8; else if (strcmp(args[i], "off") == 0) n = 0; else if (strcmp(args[i], "on") == 0) n = 1; else { OutputMsg(0, "utf8: illegal argument (%s)", args[i]); break; } if (i == 0) { WinSwitchEncoding(fore, n ? UTF8 : 0); if (msgok) OutputMsg(0, "Will %suse UTF-8 encoding", n ? "" : "not "); } else if (display) D_encoding = n ? UTF8 : 0; if (args[i] == 0) break; } break; #endif case RC_PRINTCMD: if (*args) { if (printcmd) free(printcmd); printcmd = 0; if (**args) printcmd = SaveStr(*args); } if (*args == 0 || msgok) { if (printcmd) OutputMsg(0, "using '%s' as print command", printcmd); else OutputMsg(0, "using termcap entries for printing"); break; } break; case RC_DIGRAPH: if (argl && argl[0] > 0 && argl[1] > 0) { if (argl[0] != 2) { OutputMsg(0, "Two characters expected to define a digraph"); break; } i = digraph_find(args[0]); digraphs[i].d[0] = args[0][0]; digraphs[i].d[1] = args[0][1]; if (!parse_input_int(args[1], argl[1], &digraphs[i].value)) { if (!(digraphs[i].value = atoi(args[1]))) { if (!args[1][1]) digraphs[i].value = (int)args[1][0]; #ifdef UTF8 else { int t; unsigned char *s = (unsigned char *)args[1]; digraphs[i].value = 0; while (*s) { t = FromUtf8(*s++, &digraphs[i].value); if (t == -1) continue; if (t == -2) digraphs[i].value = 0; else digraphs[i].value = t; break; } } #endif } } break; } Input("Enter digraph: ", 10, INP_EVERY, digraph_fn, NULL, 0); if (*args && **args) { s = *args; n = strlen(s); LayProcess(&s, &n); } break; case RC_DEFHSTATUS: if (*args == 0) { char buf[256]; *buf = 0; if (nwin_default.hstatus) AddXChars(buf, sizeof(buf), nwin_default.hstatus); OutputMsg(0, "default hstatus is '%s'", buf); break; } (void)ParseSaveStr(act, &nwin_default.hstatus); if (*nwin_default.hstatus == 0) { free(nwin_default.hstatus); nwin_default.hstatus = 0; } break; case RC_HSTATUS: (void)ParseSaveStr(act, &fore->w_hstatus); if (*fore->w_hstatus == 0) { free(fore->w_hstatus); fore->w_hstatus = 0; } WindowChanged(fore, 'h'); break; #ifdef FONT case RC_DEFCHARSET: case RC_CHARSET: if (*args == 0) { char buf[256]; *buf = 0; if (nwin_default.charset) AddXChars(buf, sizeof(buf), nwin_default.charset); OutputMsg(0, "default charset is '%s'", buf); break; } n = strlen(*args); if (n == 0 || n > 6) { OutputMsg(0, "%s: %s: string has illegal size.", rc_name, comms[nr].name); break; } if (n > 4 && ( ((args[0][4] < '0' || args[0][4] > '3') && args[0][4] != '.') || ((args[0][5] < '0' || args[0][5] > '3') && args[0][5] && args[0][5] != '.'))) { OutputMsg(0, "%s: %s: illegal mapping number.", rc_name, comms[nr].name); break; } if (nr == RC_CHARSET) { SetCharsets(fore, *args); break; } if (nwin_default.charset) free(nwin_default.charset); nwin_default.charset = SaveStr(*args); break; #endif #ifdef COLOR case RC_ATTRCOLOR: s = args[0]; if (*s >= '0' && *s <= '9') i = *s - '0'; else for (i = 0; i < 8; i++) if (*s == "dubrsBiI"[i]) break; s++; nr = 0; if (*s && s[1] && !s[2]) { if (*s == 'd' && s[1] == 'd') nr = 3; else if (*s == '.' && s[1] == 'd') nr = 2; else if (*s == 'd' && s[1] == '.') nr = 1; else if (*s != '.' || s[1] != '.') s--; s += 2; } if (*s || i < 0 || i >= 8) { OutputMsg(0, "%s: attrcolor: unknown attribute '%s'.", rc_name, args[0]); break; } n = 0; if (args[1]) n = ParseAttrColor(args[1], args[2], 1); if (n == -1) break; attr2color[i][nr] = n; n = 0; for (i = 0; i < 8; i++) if (attr2color[i][0] || attr2color[i][1] || attr2color[i][2] || attr2color[i][3]) n |= 1 << i; nattr2color = n; break; #endif case RC_RENDITION: i = -1; if (strcmp(args[0], "bell") == 0) { i = REND_BELL; } else if (strcmp(args[0], "monitor") == 0) { i = REND_MONITOR; } else if (strcmp(args[0], "silence") == 0) { i = REND_SILENCE; } else if (strcmp(args[0], "so") != 0) { OutputMsg(0, "Invalid option '%s' for rendition", args[0]); break; } ++args; ++argl; if (i != -1) { renditions[i] = ParseAttrColor(args[0], args[1], 1); WindowChanged((struct win *)0, 'w'); WindowChanged((struct win *)0, 'W'); WindowChanged((struct win *)0, 0); break; } /* We are here, means we want to set the sorendition. */ /* FALLTHROUGH*/ case RC_SORENDITION: i = 0; if (*args) { i = ParseAttrColor(*args, args[1], 1); if (i == -1) break; ApplyAttrColor(i, &mchar_so); WindowChanged((struct win *)0, 0); debug2("--> %x %x\n", mchar_so.attr, mchar_so.color); } if (msgok) #ifdef COLOR OutputMsg(0, "Standout attributes 0x%02x color 0x%02x", (unsigned char)mchar_so.attr, 0x99 ^ (unsigned char)mchar_so.color); #else OutputMsg(0, "Standout attributes 0x%02x ", (unsigned char)mchar_so.attr); #endif break; case RC_SOURCE: do_source(*args); break; #ifdef MULTIUSER case RC_SU: s = NULL; if (!*args) { OutputMsg(0, "%s:%s screen login", HostName, SockPath); InputSu(D_fore, &D_user, NULL); } else if (!args[1]) InputSu(D_fore, &D_user, args[0]); else if (!args[2]) s = DoSu(&D_user, args[0], args[1], "\377"); else s = DoSu(&D_user, args[0], args[1], args[2]); if (s) OutputMsg(0, "%s", s); break; #endif /* MULTIUSER */ case RC_SPLIT: s = args[0]; if (s && !strcmp(s, "-v")) AddCanvas(SLICE_HORI); else AddCanvas(SLICE_VERT); Activate(-1); break; case RC_REMOVE: RemCanvas(); Activate(-1); break; case RC_ONLY: OneCanvas(); Activate(-1); break; case RC_FIT: D_forecv->c_xoff = D_forecv->c_xs; D_forecv->c_yoff = D_forecv->c_ys; RethinkViewportOffsets(D_forecv); ResizeLayer(D_forecv->c_layer, D_forecv->c_xe - D_forecv->c_xs + 1, D_forecv->c_ye - D_forecv->c_ys + 1, 0); flayer = D_forecv->c_layer; LaySetCursor(); break; case RC_FOCUS: { struct canvas *cv = 0; if (!*args || !strcmp(*args, "next")) cv = D_forecv->c_next ? D_forecv->c_next : D_cvlist; else if (!strcmp(*args, "prev")) { for (cv = D_cvlist; cv->c_next && cv->c_next != D_forecv; cv = cv->c_next) ; } else if (!strcmp(*args, "top")) cv = D_cvlist; else if (!strcmp(*args, "bottom")) { for (cv = D_cvlist; cv->c_next; cv = cv->c_next) ; } else if (!strcmp(*args, "up")) cv = FindCanvas(D_forecv->c_xs, D_forecv->c_ys - 1); else if (!strcmp(*args, "down")) cv = FindCanvas(D_forecv->c_xs, D_forecv->c_ye + 2); else if (!strcmp(*args, "left")) cv = FindCanvas(D_forecv->c_xs - 1, D_forecv->c_ys); else if (!strcmp(*args, "right")) cv = FindCanvas(D_forecv->c_xe + 1, D_forecv->c_ys); else { OutputMsg(0, "%s: usage: focus [next|prev|up|down|left|right|top|bottom]", rc_name); break; } SetForeCanvas(display, cv); } break; case RC_RESIZE: i = 0; if (D_forecv->c_slorient == SLICE_UNKN) { OutputMsg(0, "resize: need more than one region"); break; } for (; *args; args++) { if (!strcmp(*args, "-h")) i |= RESIZE_FLAG_H; else if (!strcmp(*args, "-v")) i |= RESIZE_FLAG_V; else if (!strcmp(*args, "-b")) i |= RESIZE_FLAG_H | RESIZE_FLAG_V; else if (!strcmp(*args, "-p")) i |= D_forecv->c_slorient == SLICE_VERT ? RESIZE_FLAG_H : RESIZE_FLAG_V; else if (!strcmp(*args, "-l")) i |= RESIZE_FLAG_L; else break; } if (*args && args[1]) { OutputMsg(0, "%s: usage: resize [-h] [-v] [-l] [num]\n", rc_name); break; } if (*args) ResizeRegions(*args, i); else Input(resizeprompts[i], 20, INP_EVERY, ResizeFin, (char*)0, i); break; case RC_SETSID: (void)ParseSwitch(act, &separate_sids); break; case RC_EVAL: args = SaveArgs(args); for (i = 0; args[i]; i++) { if (args[i][0]) Colonfin(args[i], strlen(args[i]), (char *)0); free(args[i]); } free(args); break; case RC_ALTSCREEN: (void)ParseSwitch(act, &use_altscreen); if (msgok) OutputMsg(0, "Will %sdo alternate screen switching", use_altscreen ? "" : "not "); break; case RC_MAXWIN: if (!args[0]) { OutputMsg(0, "maximum windows allowed: %d", maxwin); break; } if (ParseNum(act, &n)) break; if (n < 1) OutputMsg(0, "illegal maxwin number specified"); else if (n > 2048) OutputMsg(0, "maximum 2048 windows allowed"); else if (n > maxwin && windows) OutputMsg(0, "may increase maxwin only when there's no window"); else { if (!windows) wtab = realloc(wtab, n * sizeof(struct win *)); maxwin = n; } break; case RC_BACKTICK: if (ParseBase(act, *args, &n, 10, "decimal")) break; if (!args[1]) setbacktick(n, 0, 0, (char **)0); else { int lifespan, tick; if (argc < 4) { OutputMsg(0, "%s: usage: backtick num [lifespan tick cmd args...]", rc_name); break; } if (ParseBase(act, args[1], &lifespan, 10, "decimal")) break; if (ParseBase(act, args[2], &tick, 10, "decimal")) break; setbacktick(n, lifespan, tick, SaveArgs(args + 3)); } WindowChanged(0, '`'); break; case RC_BLANKER: #ifdef BLANKER_PRG if (blankerprg) { RunBlanker(blankerprg); break; } #endif ClearAll(); CursorVisibility(-1); D_blocked = 4; break; #ifdef BLANKER_PRG case RC_BLANKERPRG: if (!args[0]) { if (blankerprg) { char path[MAXPATHLEN]; char *p = path, **pp; for (pp = blankerprg; *pp; pp++) p += snprintf(p, sizeof(path) - (p - path) - 1, "%s ", *pp); *(p - 1) = '\0'; OutputMsg(0, "blankerprg: %s", path); } else OutputMsg(0, "No blankerprg set."); break; } if (blankerprg) { char **pp; for (pp = blankerprg; *pp; pp++) free(*pp); free(blankerprg); blankerprg = 0; } if (args[0][0]) blankerprg = SaveArgs(args); break; #endif case RC_IDLE: if (*args) { struct display *olddisplay = display; if (!strcmp(*args, "off")) idletimo = 0; else if (args[0][0]) idletimo = atoi(*args) * 1000; if (argc > 1) { if ((i = FindCommnr(args[1])) == RC_ILLEGAL) { OutputMsg(0, "%s: idle: unknown command '%s'", rc_name, args[1]); break; } if (CheckArgNum(i, args + 2) < 0) break; ClearAction(&idleaction); SaveAction(&idleaction, i, args + 2, argl + 2); } for (display = displays; display; display = display->d_next) ResetIdle(); display = olddisplay; } if (msgok) { if (idletimo) OutputMsg(0, "idle timeout %ds, %s", idletimo / 1000, comms[idleaction.nr].name); else OutputMsg(0, "idle off"); } break; case RC_FOCUSMINSIZE: for (i = 0; i < 2 && args[i]; i++) { if (!strcmp(args[i], "max") || !strcmp(args[i], "_")) n = -1; else n = atoi(args[i]); if (i == 0) focusminwidth = n; else focusminheight = n; } if (msgok) { char b[2][20]; for (i = 0; i < 2; i++) { n = i == 0 ? focusminwidth : focusminheight; if (n == -1) strcpy(b[i], "max"); else sprintf(b[i], "%d", n); } OutputMsg(0, "focus min size is %s %s\n", b[0], b[1]); } break; case RC_GROUP: if (*args) { fore->w_group = 0; if (args[0][0]) { fore->w_group = WindowByName(*args); if (fore->w_group == fore || (fore->w_group && fore->w_group->w_type != W_TYPE_GROUP)) fore->w_group = 0; } WindowChanged((struct win *)0, 'w'); WindowChanged((struct win *)0, 'W'); WindowChanged((struct win *)0, 0); } if (msgok) { if (fore->w_group) OutputMsg(0, "window group is %d (%s)\n", fore->w_group->w_number, fore->w_group->w_title); else OutputMsg(0, "window belongs to no group"); } break; case RC_LAYOUT: // A number of the subcommands for "layout" are ignored, or not processed correctly when there // is no attached display. if (!strcmp(args[0], "title")) { if (!display) { if (!args[1]) // There is no display, and there is no new title. Ignore. break; if (!layout_attach || layout_attach == &layout_last_marker) layout_attach = CreateLayout(args[1], 0); else RenameLayout(layout_attach, args[1]); break; } if (!D_layout) { OutputMsg(0, "not on a layout"); break; } if (!args[1]) { OutputMsg(0, "current layout is %d (%s)", D_layout->lay_number, D_layout->lay_title); break; } RenameLayout(D_layout, args[1]); } else if (!strcmp(args[0], "number")) { if (!display) { if (args[1] && layout_attach && layout_attach != &layout_last_marker) RenumberLayout(layout_attach, atoi(args[1])); break; } if (!D_layout) { OutputMsg(0, "not on a layout"); break; } if (!args[1]) { OutputMsg(0, "This is layout %d (%s).\n", D_layout->lay_number, D_layout->lay_title); break; } RenumberLayout(D_layout, atoi(args[1])); break; } else if (!strcmp(args[0], "autosave")) { if (!display) { if (args[1] && layout_attach && layout_attach != &layout_last_marker) { if (!strcmp(args[1], "on")) layout_attach->lay_autosave = 1; else if (!strcmp(args[1], "off")) layout_attach->lay_autosave = 0; } break; } if (!D_layout) { OutputMsg(0, "not on a layout"); break; } if (args[1]) { if (!strcmp(args[1], "on")) D_layout->lay_autosave = 1; else if (!strcmp(args[1], "off")) D_layout->lay_autosave = 0; else { OutputMsg(0, "invalid argument. Give 'on' or 'off"); break; } } if (msgok) OutputMsg(0, "autosave is %s", D_layout->lay_autosave ? "on" : "off"); } else if (!strcmp(args[0], "new")) { char *t = args[1]; n = 0; if (t) { while (*t >= '0' && *t <= '9') t++; if (t != args[1] && (!*t || *t == ':')) { n = atoi(args[1]); if (*t) t++; } else t = args[1]; } if (!t || !*t) t = "layout"; NewLayout(t, n); Activate(-1); } else if (!strcmp(args[0], "save")) { if (!args[1]) { OutputMsg(0, "usage: layout save "); break; } if (display) SaveLayout(args[1], &D_canvas); } else if (!strcmp(args[0], "select")) { if (!display) { if (args[1]) layout_attach = FindLayout(args[1]); break; } if (!args[1]) { Input("Switch to layout: ", 20, INP_COOKED, SelectLayoutFin, NULL, 0); break; } SelectLayoutFin(args[1], strlen(args[1]), (char *)0); } else if (!strcmp(args[0], "next")) { if (!display) { if (layout_attach && layout_attach != &layout_last_marker) layout_attach = layout_attach->lay_next ? layout_attach->lay_next : layouts;; break; } struct layout *lay = D_layout; if (lay) lay = lay->lay_next ? lay->lay_next : layouts; else lay = layouts; if (!lay) { OutputMsg(0, "no layout defined"); break; } if (lay == D_layout) break; LoadLayout(lay, &D_canvas); Activate(-1); } else if (!strcmp(args[0], "prev")) { struct layout *lay = display ? D_layout : layout_attach; struct layout *target = lay; if (lay) { for (lay = layouts; lay->lay_next && lay->lay_next != target; lay = lay->lay_next) ; } else lay = layouts; if (!display) { layout_attach = lay; break; } if (!lay) { OutputMsg(0, "no layout defined"); break; } if (lay == D_layout) break; LoadLayout(lay, &D_canvas); Activate(-1); } else if (!strcmp(args[0], "attach")) { if (!args[1]) { if (!layout_attach) OutputMsg(0, "no attach layout set"); else if (layout_attach == &layout_last_marker) OutputMsg(0, "will attach to last layout"); else OutputMsg(0, "will attach to layout %d (%s)", layout_attach->lay_number, layout_attach->lay_title); break; } if (!strcmp(args[1], ":last")) layout_attach = &layout_last_marker; else if (!args[1][0]) layout_attach = 0; else { struct layout *lay; lay = FindLayout(args[1]); if (!lay) { OutputMsg(0, "unknown layout '%s'", args[1]); break; } layout_attach = lay; } } else if (!strcmp(args[0], "show")) { ShowLayouts(-1); } else if (!strcmp(args[0], "remove")) { struct layout *lay = display ? D_layout : layouts; if (args[1]) { lay = layouts ? FindLayout(args[1]) : (struct layout *)0; if (!lay) { OutputMsg(0, "unknown layout '%s'", args[1]); break; } } if (lay) RemoveLayout(lay); } else if (!strcmp(args[0], "dump")) { if (!display) OutputMsg(0, "Must have a display for 'layout dump'."); else if (!LayoutDumpCanvas(&D_canvas, args[1] ? args[1] : "layout-dump")) OutputMsg(errno, "Error dumping layout."); else OutputMsg(0, "Layout dumped to \"%s\"", args[1] ? args[1] : "layout-dump"); } else OutputMsg(0, "unknown layout subcommand"); break; #ifdef DW_CHARS case RC_CJKWIDTH: if(ParseSwitch(act, &cjkwidth) == 0) { if(msgok) OutputMsg(0, "Treat ambiguous width characters as %s width", cjkwidth ? "full" : "half"); } break; #endif default: #ifdef HAVE_BRAILLE /* key == -2: input from braille keybord, msgok always 0 */ DoBrailleAction(act, key == -2 ? 0 : msgok); #endif break; } if (display != odisplay) { for (display = displays; display; display = display->d_next) if (display == odisplay) break; } } #undef OutputMsg void DoCommand(argv, argl) char **argv; int *argl; { struct action act; const char *cmd = *argv; act.quiet = 0; /* For now, we actually treat both 'supress error' and 'suppress normal message' as the * same, and ignore all messages on either flag. If we wanted to do otherwise, we would * need to change the definition of 'OutputMsg' slightly. */ if (*cmd == '@') /* Suppress error */ { act.quiet |= 0x01; cmd++; } if (*cmd == '-') /* Suppress normal message */ { act.quiet |= 0x02; cmd++; } if ((act.nr = FindCommnr(cmd)) == RC_ILLEGAL) { Msg(0, "%s: unknown command '%s'", rc_name, cmd); return; } act.args = argv + 1; act.argl = argl + 1; DoAction(&act, -1); } static void SaveAction(act, nr, args, argl) struct action *act; int nr; char **args; int *argl; { register int argc = 0; char **pp; int *lp; if (args) while (args[argc]) argc++; if (argc == 0) { act->nr = nr; act->args = noargs; act->argl = 0; return; } if ((pp = (char **)malloc((unsigned)(argc + 1) * sizeof(char **))) == 0) Panic(0, "%s", strnomem); if ((lp = (int *)malloc((unsigned)(argc) * sizeof(int *))) == 0) Panic(0, "%s", strnomem); act->nr = nr; act->args = pp; act->argl = lp; while (argc--) { *lp = argl ? *argl++ : (int)strlen(*args); *pp++ = SaveStrn(*args++, *lp++); } *pp = 0; } static char ** SaveArgs(args) char **args; { register char **ap, **pp; register int argc = 0; while (args[argc]) argc++; if ((pp = ap = (char **)malloc((unsigned)(argc + 1) * sizeof(char **))) == 0) Panic(0, "%s", strnomem); while (argc--) *pp++ = SaveStr(*args++); *pp = 0; return ap; } /* * buf is split into argument vector args. * leading whitespace is removed. * @!| abbreviations are expanded. * the end of buffer is recognized by '\0' or an un-escaped '#'. * " and ' are interpreted. * * argc is returned. */ int Parse(buf, bufl, args, argl) char *buf, **args; int bufl, *argl; { register char *p = buf, **ap = args, *pp; register int delim, argc; int *lp = argl; debug2("Parse %d %s\n", bufl, buf); argc = 0; pp = buf; delim = 0; for (;;) { *lp = 0; while (*p && (*p == ' ' || *p == '\t')) ++p; #ifdef PSEUDOS if (argc == 0 && *p == '!') { *ap++ = "exec"; *lp++ = 4; p++; argc++; continue; } #endif if (*p == '\0' || *p == '#' || *p == '\n') { *p = '\0'; for (delim = 0; delim < argc; delim++) debug1("-- %s\n", args[delim]); args[argc] = 0; return argc; } if (++argc >= MAXARGS) { Msg(0, "%s: too many tokens.", rc_name); return 0; } *ap++ = pp; debug1("- new arg %s\n", p); while (*p) { if (*p == delim) delim = 0; else if (delim != '\'' && *p == '\\' && (p[1] == 'n' || p[1] == 'r' || p[1] == 't' || p[1] == '\'' || p[1] == '"' || p[1] == '\\' || p[1] == '$' || p[1] == '#' || p[1] == '^' || (p[1] >= '0' && p[1] <= '7'))) { p++; if (*p >= '0' && *p <= '7') { *pp = *p - '0'; if (p[1] >= '0' && p[1] <= '7') { p++; *pp = (*pp << 3) | (*p - '0'); if (p[1] >= '0' && p[1] <= '7') { p++; *pp = (*pp << 3) | (*p - '0'); } } pp++; } else { switch (*p) { case 'n': *pp = '\n'; break; case 'r': *pp = '\r'; break; case 't': *pp = '\t'; break; default: *pp = *p; break; } pp++; } } else if (delim != '\'' && *p == '$' && (p[1] == '{' || p[1] == ':' || (p[1] >= 'a' && p[1] <= 'z') || (p[1] >= 'A' && p[1] <= 'Z') || (p[1] >= '0' && p[1] <= '9') || p[1] == '_')) { char *ps, *pe, op, *v, xbuf[11], path[MAXPATHLEN]; int vl; ps = ++p; debug1("- var %s\n", ps); p++; while (*p) { if (*ps == '{' && *p == '}') break; if (*ps == ':' && *p == ':') break; if (*ps != '{' && *ps != ':' && (*p < 'a' || *p > 'z') && (*p < 'A' || *p > 'Z') && (*p < '0' || *p > '9') && *p != '_') break; p++; } pe = p; if (*ps == '{' || *ps == ':') { if (!*p) { Msg(0, "%s: bad variable name.", rc_name); return 0; } p++; } op = *pe; *pe = 0; debug1("- var is '%s'\n", ps); if (*ps == ':') v = gettermcapstring(ps + 1); else { if (*ps == '{') ps++; v = xbuf; if (!strcmp(ps, "TERM")) v = display ? D_termname : "unknown"; else if (!strcmp(ps, "COLUMNS")) sprintf(xbuf, "%d", display ? D_width : -1); else if (!strcmp(ps, "LINES")) sprintf(xbuf, "%d", display ? D_height : -1); else if (!strcmp(ps, "PID")) sprintf(xbuf, "%d", getpid()); else if (!strcmp(ps, "PWD")) { if (getcwd(path, sizeof(path) - 1) == 0) v = "?"; else v = path; } else if (!strcmp(ps, "STY")) { if ((v = strchr(SockName, '.'))) /* Skip the PID */ v++; else v = SockName; } else v = getenv(ps); } *pe = op; vl = v ? strlen(v) : 0; if (vl) { debug1("- sub is '%s'\n", v); if (p - pp < vl) { int right = buf + bufl - (p + strlen(p) + 1); if (right > 0) { bcopy(p, p + right, strlen(p) + 1); p += right; } } if (p - pp < vl) { Msg(0, "%s: no space left for variable expansion.", rc_name); return 0; } bcopy(v, pp, vl); pp += vl; } continue; } else if (delim != '\'' && *p == '^' && p[1]) { p++; *pp++ = *p == '?' ? '\177' : *p & 0x1f; } else if (delim == 0 && (*p == '\'' || *p == '"')) delim = *p; else if (delim == 0 && (*p == ' ' || *p == '\t' || *p == '\n')) break; else *pp++ = *p; p++; } if (delim) { Msg(0, "%s: Missing %c quote.", rc_name, delim); return 0; } if (*p) p++; *pp = 0; debug2("- arg done, '%s' rest %s\n", ap[-1], p); *lp++ = pp - ap[-1]; pp++; } } void SetEscape(u, e, me) struct acluser *u; int e, me; { if (u) { u->u_Esc = e; u->u_MetaEsc = me; } else { if (users) { if (DefaultEsc >= 0) ClearAction(&ktab[DefaultEsc]); if (DefaultMetaEsc >= 0) ClearAction(&ktab[DefaultMetaEsc]); } DefaultEsc = e; DefaultMetaEsc = me; if (users) { if (DefaultEsc >= 0) { ClearAction(&ktab[DefaultEsc]); ktab[DefaultEsc].nr = RC_OTHER; } if (DefaultMetaEsc >= 0) { ClearAction(&ktab[DefaultMetaEsc]); ktab[DefaultMetaEsc].nr = RC_META; } } } } int ParseSwitch(act, var) struct action *act; int *var; { if (*act->args == 0) { *var ^= 1; return 0; } return ParseOnOff(act, var); } static int ParseOnOff(act, var) struct action *act; int *var; { register int num = -1; char **args = act->args; if (args[1] == 0) { if (strcmp(args[0], "on") == 0) num = 1; else if (strcmp(args[0], "off") == 0) num = 0; } if (num < 0) { Msg(0, "%s: %s: invalid argument. Give 'on' or 'off'", rc_name, comms[act->nr].name); return -1; } *var = num; return 0; } int ParseSaveStr(act, var) struct action *act; char **var; { char **args = act->args; if (*args == 0 || args[1]) { Msg(0, "%s: %s: one argument required.", rc_name, comms[act->nr].name); return -1; } if (*var) free(*var); *var = SaveStr(*args); return 0; } int ParseNum(act, var) struct action *act; int *var; { int i; char *p, **args = act->args; p = *args; if (p == 0 || *p == 0 || args[1]) { Msg(0, "%s: %s: invalid argument. Give one argument.", rc_name, comms[act->nr].name); return -1; } i = 0; while (*p) { if (*p >= '0' && *p <= '9') i = 10 * i + (*p - '0'); else { Msg(0, "%s: %s: invalid argument. Give numeric argument.", rc_name, comms[act->nr].name); return -1; } p++; } debug1("ParseNum got %d\n", i); *var = i; return 0; } static int ParseNum1000(act, var) struct action *act; int *var; { int i; char *p, **args = act->args; int dig = 0; p = *args; if (p == 0 || *p == 0 || args[1]) { Msg(0, "%s: %s: invalid argument. Give one argument.", rc_name, comms[act->nr].name); return -1; } i = 0; while (*p) { if (*p >= '0' && *p <= '9') { if (dig < 4) i = 10 * i + (*p - '0'); else if (dig == 4 && *p >= '5') i++; if (dig) dig++; } else if (*p == '.' && !dig) dig++; else { Msg(0, "%s: %s: invalid argument. Give floating point argument.", rc_name, comms[act->nr].name); return -1; } p++; } if (dig == 0) i *= 1000; else while (dig++ < 4) i *= 10; if (i < 0) i = (int)((unsigned int)~0 >> 1); debug1("ParseNum1000 got %d\n", i); *var = i; return 0; } static struct win * WindowByName(s) char *s; { struct win *p; for (p = windows; p; p = p->w_next) if (!strcmp(p->w_title, s)) return p; for (p = windows; p; p = p->w_next) if (!strncmp(p->w_title, s, strlen(s))) return p; return 0; } static int WindowByNumber(str) char *str; { int i; char *s; for (i = 0, s = str; *s; s++) { if (*s < '0' || *s > '9') break; i = i * 10 + (*s - '0'); } return *s ? -1 : i; } /* * Get window number from Name or Number string. * Numbers are tried first, then names, a prefix match suffices. * Be careful when assigning numeric strings as WindowTitles. */ int WindowByNoN(str) char *str; { int i; struct win *p; if ((i = WindowByNumber(str)) < 0 || i >= maxwin) { if ((p = WindowByName(str))) return p->w_number; return -1; } return i; } static int ParseWinNum(act, var) struct action *act; int *var; { char **args = act->args; int i = 0; if (*args == 0 || args[1]) { Msg(0, "%s: %s: one argument required.", rc_name, comms[act->nr].name); return -1; } i = WindowByNoN(*args); if (i < 0) { Msg(0, "%s: %s: invalid argument. Give window number or name.", rc_name, comms[act->nr].name); return -1; } debug1("ParseWinNum got %d\n", i); *var = i; return 0; } static int ParseBase(act, p, var, base, bname) struct action *act; char *p; int *var; int base; char *bname; { int i = 0; int c; if (*p == 0) { Msg(0, "%s: %s: empty argument.", rc_name, comms[act->nr].name); return -1; } while ((c = *p++)) { if (c >= 'a' && c <= 'z') c -= 'a' - 'A'; if (c >= 'A' && c <= 'Z') c -= 'A' - ('0' + 10); c -= '0'; if (c < 0 || c >= base) { Msg(0, "%s: %s: argument is not %s.", rc_name, comms[act->nr].name, bname); return -1; } i = base * i + c; } debug1("ParseBase got %d\n", i); *var = i; return 0; } static int IsNum(s, base) register char *s; register int base; { for (base += '0'; *s; ++s) if (*s < '0' || *s > base) return 0; return 1; } int IsNumColon(s, base, p, psize) int base, psize; char *s, *p; { char *q; if ((q = rindex(s, ':')) != 0) { strncpy(p, q + 1, psize - 1); p[psize - 1] = '\0'; *q = '\0'; } else *p = '\0'; return IsNum(s, base); } void SwitchWindow(n) int n; { struct win *p; debug1("SwitchWindow %d\n", n); if (n < 0 || n >= maxwin) { ShowWindows(-1); return; } if ((p = wtab[n]) == 0) { ShowWindows(n); return; } if (display == 0) { fore = p; return; } if (p == D_fore) { Msg(0, "This IS window %d (%s).", n, p->w_title); return; } #ifdef MULTIUSER if (AclCheckPermWin(D_user, ACL_READ, p)) { Msg(0, "Access to window %d denied.", p->w_number); return; } #endif SetForeWindow(p); Activate(fore->w_norefresh); } /* * SetForeWindow changes the window in the input focus of the display. * Puts window wi in canvas display->d_forecv. */ void SetForeWindow(wi) struct win *wi; { struct win *p; if (display == 0) { fore = wi; return; } p = Layer2Window(D_forecv->c_layer); SetCanvasWindow(D_forecv, wi); if (p) WindowChanged(p, 'u'); if (wi) WindowChanged(wi, 'u'); flayer = D_forecv->c_layer; /* Activate called afterwards, so no RefreshHStatus needed */ } /*****************************************************************/ /* * Activate - make fore window active * norefresh = -1 forces a refresh, disregard all_norefresh then. */ void Activate(norefresh) int norefresh; { debug1("Activate(%d)\n", norefresh); if (display == 0) return; if (D_status) { Msg(0, "%s", ""); /* wait till mintime (keep gcc quiet) */ RemoveStatus(); } if (MayResizeLayer(D_forecv->c_layer)) ResizeLayer(D_forecv->c_layer, D_forecv->c_xe - D_forecv->c_xs + 1, D_forecv->c_ye - D_forecv->c_ys + 1, display); fore = D_fore; if (fore) { /* XXX ? */ if (fore->w_monitor != MON_OFF) fore->w_monitor = MON_ON; fore->w_bell = BELL_ON; WindowChanged(fore, 'f'); #if 0 if (ResizeDisplay(fore->w_width, fore->w_height)) { debug2("Cannot resize from (%d,%d)", D_width, D_height); debug2(" to (%d,%d) -> resize window\n", fore->w_width, fore->w_height); DoResize(D_width, D_height); } #endif } Redisplay(norefresh + all_norefresh); } static int NextWindow() { register struct win **pp; int n = fore ? fore->w_number : maxwin; struct win *group = fore ? fore->w_group : 0; for (pp = fore ? wtab + n + 1 : wtab; pp != wtab + n; pp++) { if (pp == wtab + maxwin) pp = wtab; if (*pp) { if (!fore || group == (*pp)->w_group) break; } } if (pp == wtab + n) return -1; return pp - wtab; } static int PreviousWindow() { register struct win **pp; int n = fore ? fore->w_number : -1; struct win *group = fore ? fore->w_group : 0; for (pp = wtab + n - 1; pp != wtab + n; pp--) { if (pp == wtab - 1) pp = wtab + maxwin - 1; if (*pp) { if (!fore || group == (*pp)->w_group) break; } } if (pp == wtab + n) return -1; return pp - wtab; } static int MoreWindows() { char *m = "No other window."; if (windows && (fore == 0 || windows->w_next)) return 1; if (fore == 0) { Msg(0, "No window available"); return 0; } Msg(0, m, fore->w_number); /* other arg for nethack */ return 0; } void KillWindow(wi) struct win *wi; { struct win **pp, *p; struct canvas *cv; int gotone; struct layout *lay; /* * Remove window from linked list. */ for (pp = &windows; (p = *pp); pp = &p->w_next) if (p == wi) break; ASSERT(p); *pp = p->w_next; wi->w_inlen = 0; wtab[wi->w_number] = 0; if (windows == 0) { FreeWindow(wi); Finit(0); } /* * switch to different window on all canvases */ for (display = displays; display; display = display->d_next) { gotone = 0; for (cv = D_cvlist; cv; cv = cv->c_next) { if (Layer2Window(cv->c_layer) != wi) continue; /* switch to other window */ SetCanvasWindow(cv, FindNiceWindow(D_other, 0)); gotone = 1; } if (gotone) { #ifdef ZMODEM if (wi->w_zdisplay == display) { D_blocked = 0; D_readev.condpos = D_readev.condneg = 0; } #endif Activate(-1); } } /* do the same for the layouts */ for (lay = layouts; lay; lay = lay->lay_next) UpdateLayoutCanvas(&lay->lay_canvas, wi); FreeWindow(wi); WindowChanged((struct win *)0, 'w'); WindowChanged((struct win *)0, 'W'); WindowChanged((struct win *)0, 0); } static void LogToggle(on) int on; { char buf[1024]; if ((fore->w_log != 0) == on) { if (display && !*rc_name) Msg(0, "You are %s logging.", on ? "already" : "not"); return; } if (fore->w_log != 0) { Msg(0, "Logfile \"%s\" closed.", fore->w_log->name); logfclose(fore->w_log); fore->w_log = 0; WindowChanged(fore, 'f'); return; } if (DoStartLog(fore, buf, sizeof(buf))) { Msg(errno, "Error opening logfile \"%s\"", buf); return; } if (ftell(fore->w_log->fp) == 0) Msg(0, "Creating logfile \"%s\".", fore->w_log->name); else Msg(0, "Appending to logfile \"%s\".", fore->w_log->name); WindowChanged(fore, 'f'); } char * AddWindows(buf, len, flags, where) char *buf; int len; int flags; int where; { register char *s, *ss; register struct win **pp, *p; register char *cmd; int l; s = ss = buf; if ((flags & 8) && where < 0) { *s = 0; return ss; } for (pp = ((flags & 4) && where >= 0) ? wtab + where + 1: wtab; pp < wtab + maxwin; pp++) { int rend = -1; if (pp - wtab == where && ss == buf) ss = s; if ((p = *pp) == 0) continue; if ((flags & 1) && display && p == D_fore) continue; if (display && D_fore && D_fore->w_group != p->w_group) continue; cmd = p->w_title; l = strlen(cmd); if (l > 20) l = 20; if (s - buf + l > len - 24) break; if (s > buf || (flags & 4)) { *s++ = ' '; *s++ = ' '; } if (p->w_number == where) { ss = s; if (flags & 8) break; } if (!(flags & 4) || where < 0 || ((flags & 4) && where < p->w_number)) { if (p->w_monitor == MON_DONE && renditions[REND_MONITOR] != -1) rend = renditions[REND_MONITOR]; else if ((p->w_bell == BELL_DONE || p->w_bell == BELL_FOUND) && renditions[REND_BELL] != -1) rend = renditions[REND_BELL]; else if ((p->w_silence == SILENCE_FOUND || p->w_silence == SILENCE_DONE) && renditions[REND_SILENCE] != -1) rend = renditions[REND_SILENCE]; } if (rend != -1) AddWinMsgRend(s, rend); sprintf(s, "%d", p->w_number); s += strlen(s); if (display && p == D_fore) *s++ = '*'; if (!(flags & 2)) { if (display && p == D_other) *s++ = '-'; s = AddWindowFlags(s, len, p); } *s++ = ' '; strncpy(s, cmd, l); s += l; if (rend != -1) AddWinMsgRend(s, -1); } *s = 0; return ss; } char * AddWindowFlags(buf, len, p) char *buf; int len; struct win *p; { char *s = buf; if (p == 0 || len < 12) { *s = 0; return s; } #if 0 if (display && p == D_fore) *s++ = '*'; if (display && p == D_other) *s++ = '-'; #endif if (p->w_layer.l_cvlist && p->w_layer.l_cvlist->c_lnext) *s++ = '&'; if (p->w_monitor == MON_DONE #ifdef MULTIUSER && (ACLBYTE(p->w_mon_notify, D_user->u_id) & ACLBIT(D_user->u_id)) #endif ) *s++ = '@'; if (p->w_bell == BELL_DONE) *s++ = '!'; #ifdef UTMPOK if (p->w_slot != (slot_t) 0 && p->w_slot != (slot_t) -1) *s++ = '$'; #endif if (p->w_log != 0) { strcpy(s, "(L)"); s += 3; } if (p->w_ptyfd < 0 && p->w_type != W_TYPE_GROUP) *s++ = 'Z'; *s = 0; return s; } char * AddOtherUsers(buf, len, p) char *buf; int len; struct win *p; { struct display *d, *olddisplay = display; struct canvas *cv; char *s; int l; s = buf; for (display = displays; display; display = display->d_next) { if (olddisplay && D_user == olddisplay->d_user) continue; for (cv = D_cvlist; cv; cv = cv->c_next) if (Layer2Window(cv->c_layer) == p) break; if (!cv) continue; for (d = displays; d && d != display; d = d->d_next) if (D_user == d->d_user) break; if (d && d != display) continue; if (len > 1 && s != buf) { *s++ = ','; len--; } l = strlen(D_user->u_name); if (l + 1 > len) break; strcpy(s, D_user->u_name); s += l; len -= l; } *s = 0; display = olddisplay; return s; } void ShowWindows(where) int where; { char buf[1024]; char *s, *ss; if (display && where == -1 && D_fore) where = D_fore->w_number; ss = AddWindows(buf, sizeof(buf), 0, where); s = buf + strlen(buf); if (display && ss - buf > D_width / 2) { ss -= D_width / 2; if (s - ss < D_width) { ss = s - D_width; if (ss < buf) ss = buf; } } else ss = buf; Msg(0, "%s", ss); } static void ShowInfo() { char buf[512], *p; register struct win *wp = fore; register int i; if (wp == 0) { Msg(0, "(%d,%d)/(%d,%d) no window", D_x + 1, D_y + 1, D_width, D_height); return; } p = buf; if (buf < (p += GetAnsiStatus(wp, p))) *p++ = ' '; sprintf(p, "(%d,%d)/(%d,%d)", wp->w_x + 1, wp->w_y + 1, wp->w_width, wp->w_height); #ifdef COPY_PASTE sprintf(p += strlen(p), "+%d", wp->w_histheight); #endif sprintf(p += strlen(p), " %c%sflow", (wp->w_flow & FLOW_NOW) ? '+' : '-', (wp->w_flow & FLOW_AUTOFLAG) ? "" : ((wp->w_flow & FLOW_AUTO) ? "(+)" : "(-)")); if (!wp->w_wrap) sprintf(p += strlen(p), " -wrap"); if (wp->w_insert) sprintf(p += strlen(p), " ins"); if (wp->w_origin) sprintf(p += strlen(p), " org"); if (wp->w_keypad) sprintf(p += strlen(p), " app"); if (wp->w_log) sprintf(p += strlen(p), " log"); if (wp->w_monitor != MON_OFF #ifdef MULTIUSER && (ACLBYTE(wp->w_mon_notify, D_user->u_id) & ACLBIT(D_user->u_id)) #endif ) sprintf(p += strlen(p), " mon"); if (wp->w_mouse) sprintf(p += strlen(p), " mouse"); #ifdef COLOR if (wp->w_bce) sprintf(p += strlen(p), " bce"); #endif if (!wp->w_c1) sprintf(p += strlen(p), " -c1"); if (wp->w_norefresh) sprintf(p += strlen(p), " nored"); p += strlen(p); #ifdef FONT # ifdef ENCODINGS if (wp->w_encoding && (display == 0 || D_encoding != wp->w_encoding || EncodingDefFont(wp->w_encoding) <= 0)) { *p++ = ' '; strcpy(p, EncodingName(wp->w_encoding)); p += strlen(p); } # ifdef UTF8 if (wp->w_encoding != UTF8) # endif # endif if (D_CC0 || (D_CS0 && *D_CS0)) { if (wp->w_gr == 2) { sprintf(p, " G%c", wp->w_Charset + '0'); if (wp->w_FontE >= ' ') p[3] = wp->w_FontE; else { p[3] = '^'; p[4] = wp->w_FontE ^ 0x40; p++; } p[4] = '['; p++; } else if (wp->w_gr) sprintf(p++, " G%c%c[", wp->w_Charset + '0', wp->w_CharsetR + '0'); else sprintf(p, " G%c[", wp->w_Charset + '0'); p += 4; for (i = 0; i < 4; i++) { if (wp->w_charsets[i] == ASCII) *p++ = 'B'; else if (wp->w_charsets[i] >= ' ') *p++ = wp->w_charsets[i]; else { *p++ = '^'; *p++ = wp->w_charsets[i] ^ 0x40; } } *p++ = ']'; *p = 0; } #endif if (wp->w_type == W_TYPE_PLAIN) { /* add info about modem control lines */ *p++ = ' '; TtyGetModemStatus(wp->w_ptyfd, p); } #ifdef BUILTIN_TELNET else if (wp->w_type == W_TYPE_TELNET) { *p++ = ' '; TelStatus(wp, p, sizeof(buf) - 1 - (p - buf)); } #endif Msg(0, "%s %d(%s)", buf, wp->w_number, wp->w_title); } static void ShowDInfo() { char buf[512], *p; if (display == 0) return; p = buf; sprintf(p, "(%d,%d)", D_width, D_height), p += strlen(p); #ifdef ENCODINGS if (D_encoding) { *p++ = ' '; strcpy(p, EncodingName(D_encoding)); p += strlen(p); } #endif if (D_CXT) { strcpy(p, " xterm"); p += strlen(p); } #ifdef COLOR if (D_hascolor) { strcpy(p, " color"); p += strlen(p); } #endif #ifdef FONT if (D_CG0) { strcpy(p, " iso2022"); p += strlen(p); } else if (D_CS0 && *D_CS0) { strcpy(p, " altchar"); p += strlen(p); } #endif Msg(0, "%s", buf); } static void AKAfin(buf, len, data) char *buf; int len; char *data; /* dummy */ { ASSERT(display); if (len && fore) ChangeAKA(fore, buf, strlen(buf)); } static void InputAKA() { char *s, *ss; int n; Input("Set window's title to: ", sizeof(fore->w_akabuf) - 1, INP_COOKED, AKAfin, NULL, 0); s = fore->w_title; if (!s) return; for (; *s; s++) { if ((*(unsigned char *)s & 0x7f) < 0x20 || *s == 0x7f) continue; ss = s; n = 1; LayProcess(&ss, &n); } } static void Colonfin(buf, len, data) char *buf; int len; char *data; /* dummy */ { char mbuf[256]; RemoveStatus(); if (buf[len] == '\t') { int m, x; int l = 0, r = RC_LAST; int showmessage = 0; char *s = buf; while (*s && s - buf < len) if (*s++ == ' ') return; /* Showing a message when there's no hardstatus or caption cancels the input */ if (display && (captionalways || D_has_hstatus == HSTATUS_LASTLINE || (D_canvas.c_slperp && D_canvas.c_slperp->c_slnext))) showmessage = 1; while (l <= r) { m = (l + r) / 2; x = strncmp(buf, comms[m].name, len); if (x > 0) l = m + 1; else if (x < 0) r = m - 1; else { s = mbuf; for (l = m - 1; l >= 0 && strncmp(buf, comms[l].name, len) == 0; l--) ; for (m = ++l; m <= r && strncmp(buf, comms[m].name, len) == 0 && s - mbuf < sizeof(mbuf); m++) s += snprintf(s, sizeof(mbuf) - (s - mbuf), " %s", comms[m].name); if (l < m - 1) { if (showmessage) Msg(0, "Possible commands:%s", mbuf); } else { s = mbuf; len = snprintf(mbuf, sizeof(mbuf), "%s \t", comms[l].name + len); if (len > 0 && len < sizeof(mbuf)) LayProcess(&s, &len); } break; } } if (l > r && showmessage) Msg(0, "No commands matching '%*s'", len, buf); return; } if (!len || buf[len]) return; len = strlen(buf) + 1; if (len > (int)sizeof(mbuf)) RcLine(buf, len); else { bcopy(buf, mbuf, len); RcLine(mbuf, sizeof mbuf); } } static void SelectFin(buf, len, data) char *buf; int len; char *data; /* dummy */ { int n; if (!len || !display) return; if (len == 1 && *buf == '-') { SetForeWindow((struct win *)0); Activate(0); return; } if ((n = WindowByNoN(buf)) < 0) return; SwitchWindow(n); } static void SelectLayoutFin(buf, len, data) char *buf; int len; char *data; /* dummy */ { struct layout *lay; if (!len || !display) return; if (len == 1 && *buf == '-') { LoadLayout((struct layout *)0, (struct canvas *)0); Activate(0); return; } lay = FindLayout(buf); if (!lay) Msg(0, "No such layout\n"); else if (lay == D_layout) Msg(0, "This IS layout %d (%s).\n", lay->lay_number, lay->lay_title); else { LoadLayout(lay, &D_canvas); Activate(0); } } static void InputSelect() { Input("Switch to window: ", 20, INP_COOKED, SelectFin, NULL, 0); } static char setenv_var[31]; static void SetenvFin1(buf, len, data) char *buf; int len; char *data; /* dummy */ { if (!len || !display) return; InputSetenv(buf); } static void SetenvFin2(buf, len, data) char *buf; int len; char *data; /* dummy */ { if (!len || !display) return; debug2("SetenvFin2: setenv '%s' '%s'\n", setenv_var, buf); xsetenv(setenv_var, buf); MakeNewEnv(); } static void InputSetenv(arg) char *arg; { static char setenv_buf[50 + sizeof(setenv_var)]; /* need to be static here, cannot be freed */ if (arg) { strncpy(setenv_var, arg, sizeof(setenv_var) - 1); sprintf(setenv_buf, "Enter value for %s: ", setenv_var); Input(setenv_buf, 30, INP_COOKED, SetenvFin2, NULL, 0); } else Input("Setenv: Enter variable name: ", 30, INP_COOKED, SetenvFin1, NULL, 0); } /* * the following options are understood by this parser: * -f, -f0, -f1, -fy, -fa * -t title, -T terminal-type, -h height-of-scrollback, * -ln, -l0, -ly, -l1, -l * -a, -M, -L */ void DoScreen(fn, av) char *fn, **av; { struct NewWindow nwin; register int num; char buf[20]; nwin = nwin_undef; while (av && *av && av[0][0] == '-') { if (av[0][1] == '-') { av++; break; } switch (av[0][1]) { case 'f': switch (av[0][2]) { case 'n': case '0': nwin.flowflag = FLOW_NOW * 0; break; case 'y': case '1': case '\0': nwin.flowflag = FLOW_NOW * 1; break; case 'a': nwin.flowflag = FLOW_AUTOFLAG; break; default: break; } break; case 't': /* no more -k */ if (av[0][2]) nwin.aka = &av[0][2]; else if (*++av) nwin.aka = *av; else --av; break; case 'T': if (av[0][2]) nwin.term = &av[0][2]; else if (*++av) nwin.term = *av; else --av; break; case 'h': if (av[0][2]) nwin.histheight = atoi(av[0] + 2); else if (*++av) nwin.histheight = atoi(*av); else --av; break; #ifdef LOGOUTOK case 'l': switch (av[0][2]) { case 'n': case '0': nwin.lflag = 0; break; case 'y': case '1': case '\0': nwin.lflag = 1; break; case 'a': nwin.lflag = 3; break; default: break; } break; #endif case 'a': nwin.aflag = 1; break; case 'M': nwin.monitor = MON_ON; break; case 'L': nwin.Lflag = 1; break; default: Msg(0, "%s: screen: invalid option -%c.", fn, av[0][1]); break; } ++av; } num = 0; if (av && *av && IsNumColon(*av, 10, buf, sizeof(buf))) { if (*buf != '\0') nwin.aka = buf; num = atoi(*av); if (num < 0 || (maxwin && num > maxwin - 1) || (!maxwin && num > MAXWIN - 1)) { Msg(0, "%s: illegal screen number %d.", fn, num); num = 0; } nwin.StartAt = num; ++av; } if (av && *av) { nwin.args = av; if (!nwin.aka) nwin.aka = Filename(*av); } MakeWindow(&nwin); } #ifdef COPY_PASTE /* * CompileKeys must be called before Markroutine is first used. * to initialise the keys with defaults, call CompileKeys(NULL, mark_key_tab); * * s is an ascii string in a termcap-like syntax. It looks like * "j=u:k=d:l=r:h=l: =.:" and so on... * this example rebinds the cursormovement to the keys u (up), d (down), * l (left), r (right). placing a mark will now be done with ".". */ int CompileKeys(s, sl, array) char *s; int sl; unsigned char *array; { int i; unsigned char key, value; if (sl == 0) { for (i = 0; i < 256; i++) array[i] = i; return 0; } debug1("CompileKeys: '%s'\n", s); while (sl) { key = *(unsigned char *)s++; if (*s != '=' || sl < 3) return -1; sl--; do { s++; sl -= 2; value = *(unsigned char *)s++; array[value] = key; } while (*s == '=' && sl >= 2); if (sl == 0) break; if (*s++ != ':') return -1; sl--; } return 0; } #endif /* COPY_PASTE */ /* * Asynchronous input functions */ #if defined(DETACH) && defined(POW_DETACH) static void pow_detach_fn(buf, len, data) char *buf; int len; char *data; /* dummy */ { debug("pow_detach_fn called\n"); if (len) { *buf = 0; return; } if (ktab[(int)(unsigned char)*buf].nr != RC_POW_DETACH) { if (display) write(D_userfd, "\007", 1); Msg(0, "Detach aborted."); } else Detach(D_POWER); } #endif /* POW_DETACH */ #ifdef COPY_PASTE static void copy_reg_fn(buf, len, data) char *buf; int len; char *data; /* dummy */ { struct plop *pp = plop_tab + (int)(unsigned char)*buf; if (len) { *buf = 0; return; } if (pp->buf) free(pp->buf); pp->buf = 0; pp->len = 0; if (D_user->u_plop.len) { if ((pp->buf = (char *)malloc(D_user->u_plop.len)) == NULL) { Msg(0, "%s", strnomem); return; } bcopy(D_user->u_plop.buf, pp->buf, D_user->u_plop.len); } pp->len = D_user->u_plop.len; #ifdef ENCODINGS pp->enc = D_user->u_plop.enc; #endif Msg(0, "Copied %d characters into register %c", D_user->u_plop.len, *buf); } static void ins_reg_fn(buf, len, data) char *buf; int len; char *data; /* dummy */ { struct plop *pp = plop_tab + (int)(unsigned char)*buf; if (len) { *buf = 0; return; } if (!fore) return; /* Input() should not call us w/o fore, but you never know... */ if (*buf == '.') Msg(0, "ins_reg_fn: Warning: pasting real register '.'!"); if (pp->buf) { MakePaster(&fore->w_paster, pp->buf, pp->len, 0); return; } Msg(0, "Empty register."); } #endif /* COPY_PASTE */ static void process_fn(buf, len, data) char *buf; int len; char *data; /* dummy */ { struct plop *pp = plop_tab + (int)(unsigned char)*buf; if (len) { *buf = 0; return; } if (pp->buf) { ProcessInput(pp->buf, pp->len); return; } Msg(0, "Empty register."); } static void confirm_fn(buf, len, data) char *buf; int len; char *data; { struct action act; if (len || (*buf != 'y' && *buf != 'Y')) { *buf = 0; return; } act.nr = *(int *)data; act.args = noargs; act.argl = 0; act.quiet = 0; DoAction(&act, -1); } #ifdef MULTIUSER struct inputsu { struct acluser **up; char name[24]; char pw1[130]; /* FreeBSD crypts to 128 bytes */ char pw2[130]; }; static void su_fin(buf, len, data) char *buf; int len; char *data; { struct inputsu *i = (struct inputsu *)data; char *p; int l; if (!*i->name) { p = i->name; l = sizeof(i->name) - 1; } else if (!*i->pw1) { strcpy(p = i->pw1, "\377"); l = sizeof(i->pw1) - 1; } else { strcpy(p = i->pw2, "\377"); l = sizeof(i->pw2) - 1; } if (buf && len) strncpy(p, buf, 1 + (l < len) ? l : len); if (!*i->name) Input("Screen User: ", sizeof(i->name) - 1, INP_COOKED, su_fin, (char *)i, 0); else if (!*i->pw1) Input("User's UNIX Password: ", sizeof(i->pw1)-1, INP_COOKED|INP_NOECHO, su_fin, (char *)i, 0); else if (!*i->pw2) Input("User's Screen Password: ", sizeof(i->pw2)-1, INP_COOKED|INP_NOECHO, su_fin, (char *)i, 0); else { if ((p = DoSu(i->up, i->name, i->pw2, i->pw1))) Msg(0, "%s", p); free((char *)i); } } static int InputSu(w, up, name) struct win *w; struct acluser **up; char *name; { struct inputsu *i; if (!(i = (struct inputsu *)calloc(1, sizeof(struct inputsu)))) return -1; i->up = up; if (name && *name) su_fin(name, (int)strlen(name), (char *)i); /* can also initialise stuff */ else su_fin((char *)0, 0, (char *)i); return 0; } #endif /* MULTIUSER */ #ifdef PASSWORD static void pass1(buf, len, data) char *buf; int len; char *data; { struct acluser *u = (struct acluser *)data; if (!*buf) return; ASSERT(u); if (u->u_password != NullStr) free((char *)u->u_password); u->u_password = SaveStr(buf); bzero(buf, strlen(buf)); Input("Retype new password:", 100, INP_NOECHO, pass2, data, 0); } static void pass2(buf, len, data) char *buf; int len; char *data; { int st; char salt[3]; struct acluser *u = (struct acluser *)data; ASSERT(u); if (!buf || strcmp(u->u_password, buf)) { Msg(0, "[ Passwords don't match - checking turned off ]"); if (u->u_password != NullStr) { bzero(u->u_password, strlen(u->u_password)); free((char *)u->u_password); } u->u_password = NullStr; } else if (u->u_password[0] == '\0') { Msg(0, "[ No password - no secure ]"); if (buf) bzero(buf, strlen(buf)); } if (u->u_password != NullStr) { for (st = 0; st < 2; st++) salt[st] = 'A' + (int)((time(0) >> 6 * st) % 26); salt[2] = 0; buf = crypt(u->u_password, salt); bzero(u->u_password, strlen(u->u_password)); free((char *)u->u_password); u->u_password = SaveStr(buf); bzero(buf, strlen(buf)); #ifdef COPY_PASTE if (u->u_plop.buf) UserFreeCopyBuffer(u); u->u_plop.len = strlen(u->u_password); # ifdef ENCODINGS u->u_plop.enc = 0; #endif if (!(u->u_plop.buf = SaveStr(u->u_password))) { Msg(0, "%s", strnomem); D_user->u_plop.len = 0; } else Msg(0, "[ Password moved into copybuffer ]"); #else /* COPY_PASTE */ Msg(0, "[ Crypted password is \"%s\" ]", u->u_password); #endif /* COPY_PASTE */ } } #endif /* PASSWORD */ static int digraph_find(buf) const char *buf; { int i; for (i = 0; i < MAX_DIGRAPH && digraphs[i].d[0]; i++) if ((digraphs[i].d[0] == (unsigned char)buf[0] && digraphs[i].d[1] == (unsigned char)buf[1]) || (digraphs[i].d[0] == (unsigned char)buf[1] && digraphs[i].d[1] == (unsigned char)buf[0])) break; return i; } static void digraph_fn(buf, len, data) char *buf; int len; char *data; /* dummy */ { int ch, i, x; ch = buf[len]; if (ch) { buf[len + 1] = ch; /* so we can restore it later */ if (ch < ' ' || ch == '\177') return; if (len >= 1 && ((*buf == 'U' && buf[1] == '+') || (*buf == '0' && (buf[1] == 'x' || buf[1] == 'X')))) { if (len == 1) return; if ((ch < '0' || ch > '9') && (ch < 'a' || ch > 'f') && (ch < 'A' || ch > 'F')) { buf[len] = '\034'; /* ^] is ignored by Input() */ return; } if (len == (*buf == 'U' ? 5 : 3)) buf[len] = '\n'; return; } if (len && *buf == '0') { if (ch < '0' || ch > '7') { buf[len] = '\034'; /* ^] is ignored by Input() */ return; } if (len == 3) buf[len] = '\n'; return; } if (len == 1) buf[len] = '\n'; return; } if (len < 1) return; if (buf[len + 1]) { buf[len] = buf[len + 1]; /* stored above */ len++; } if (len < 2) return; if (!parse_input_int(buf, len, &x)) { i = digraph_find(buf); if ((x = digraphs[i].value) <= 0) { Msg(0, "Unknown digraph"); return; } } i = 1; *buf = x; #ifdef UTF8 if (flayer->l_encoding == UTF8) i = ToUtf8(buf, x); /* buf is big enough for all UTF-8 codes */ #endif while(i) LayProcess(&buf, &i); } #ifdef MAPKEYS int StuffKey(i) int i; { struct action *act; int discard = 0; debug1("StuffKey #%d", i); #ifdef DEBUG if (i < KMAP_KEYS) debug1(" - %s", term[i + T_CAPS].tcname); #endif if (i < KMAP_KEYS && D_ESCseen) { struct action *act = &D_ESCseen[i + 256]; if (act->nr != RC_ILLEGAL) { D_ESCseen = 0; WindowChanged(fore, 'E'); DoAction(act, i + 256); return 0; } discard = 1; } if (i >= T_CURSOR - T_CAPS && i < T_KEYPAD - T_CAPS && D_cursorkeys) i += T_OCAPS - T_CURSOR; else if (i >= T_KEYPAD - T_CAPS && i < T_OCAPS - T_CAPS && D_keypad) i += T_OCAPS - T_CURSOR; debug1(" - action %d\n", i); flayer = D_forecv->c_layer; fore = D_fore; act = 0; #ifdef COPY_PASTE if (flayer && flayer->l_mode == 1) act = i < KMAP_KEYS+KMAP_AKEYS ? &mmtab[i] : &kmap_exts[i - (KMAP_KEYS+KMAP_AKEYS)].mm; #endif if ((!act || act->nr == RC_ILLEGAL) && !D_mapdefault) act = i < KMAP_KEYS+KMAP_AKEYS ? &umtab[i] : &kmap_exts[i - (KMAP_KEYS+KMAP_AKEYS)].um; if (!act || act->nr == RC_ILLEGAL) act = i < KMAP_KEYS+KMAP_AKEYS ? &dmtab[i] : &kmap_exts[i - (KMAP_KEYS+KMAP_AKEYS)].dm; if (discard && (!act || act->nr != RC_COMMAND)) { if (D_ESCseen) { D_ESCseen = 0; WindowChanged(fore, 'E'); } return 0; } D_mapdefault = 0; if (act == 0 || act->nr == RC_ILLEGAL) return -1; DoAction(act, 0); return 0; } #endif static int IsOnDisplay(wi) struct win *wi; { struct canvas *cv; ASSERT(display); for (cv = D_cvlist; cv; cv = cv->c_next) if (Layer2Window(cv->c_layer) == wi) return 1; return 0; } struct win * FindNiceWindow(wi, presel) struct win *wi; char *presel; { int i; debug2("FindNiceWindow %d %s\n", wi ? wi->w_number : -1 , presel ? presel : "NULL"); if (presel) { i = WindowByNoN(presel); if (i >= 0) wi = wtab[i]; } if (!display) return wi; #ifdef MULTIUSER if (wi && AclCheckPermWin(D_user, ACL_READ, wi)) wi = 0; #endif if (!wi || (IsOnDisplay(wi) && !presel)) { /* try to get another window */ wi = 0; #ifdef MULTIUSER for (wi = windows; wi; wi = wi->w_next) if (!wi->w_layer.l_cvlist && !AclCheckPermWin(D_user, ACL_WRITE, wi)) break; if (!wi) for (wi = windows; wi; wi = wi->w_next) if (wi->w_layer.l_cvlist && !IsOnDisplay(wi) && !AclCheckPermWin(D_user, ACL_WRITE, wi)) break; if (!wi) for (wi = windows; wi; wi = wi->w_next) if (!wi->w_layer.l_cvlist && !AclCheckPermWin(D_user, ACL_READ, wi)) break; if (!wi) for (wi = windows; wi; wi = wi->w_next) if (wi->w_layer.l_cvlist && !IsOnDisplay(wi) && !AclCheckPermWin(D_user, ACL_READ, wi)) break; #endif if (!wi) for (wi = windows; wi; wi = wi->w_next) if (!wi->w_layer.l_cvlist) break; if (!wi) for (wi = windows; wi; wi = wi->w_next) if (wi->w_layer.l_cvlist && !IsOnDisplay(wi)) break; } #ifdef MULTIUSER if (wi && AclCheckPermWin(D_user, ACL_READ, wi)) wi = 0; #endif return wi; } #if 0 /* sorted list of all commands */ static struct comm **commtab; static int ncommtab; void AddComms(cos, hand) struct comm *cos; void (*hand) __P((struct comm *, char **, int)); { int n, i, j, r; for (n = 0; cos[n].name; n++) ; if (n == 0) return; if (commtab) commtab = (struct commt *)realloc(commtab, sizeof(*commtab) * (ncommtab + n)); else commtab = (struct commt *)malloc(sizeof(*commtab) * (ncommtab + n)); if (!commtab) Panic(0, strnomem); for (i = 0; i < n; i++) { for (j = 0; j < ncommtab; j++) { r = strcmp(cos[i].name, commtab[j]->name); if (r == 0) Panic(0, "Duplicate command: %s\n", cos[i].name); if (r < 0) break; } for (r = ncommtab; r > j; r--) commtab[r] = commtab[r - 1]; commtab[j] = cos + i; cos[i].handler = hand; bzero(cos[i].userbits, sizeof(cos[i].userbits)); ncommtab++; } } struct comm * FindComm(str) char *str; { int x, m, l = 0, r = ncommtab - 1; while (l <= r) { m = (l + r) / 2; x = strcmp(str, commtab[m]->name); if (x > 0) l = m + 1; else if (x < 0) r = m - 1; else return commtab[m]; } return 0; } #endif static int CalcSlicePercent(cv, percent) struct canvas *cv; int percent; { int w, wsum, up; if (!cv || !cv->c_slback) return percent; up = CalcSlicePercent(cv->c_slback->c_slback, percent); w = cv->c_slweight; for (cv = cv->c_slback->c_slperp, wsum = 0; cv; cv = cv->c_slnext) wsum += cv->c_slweight; if (wsum == 0) return 0; return (up * w) / wsum; } static int ChangeCanvasSize(fcv, abs, diff, gflag, percent) struct canvas *fcv; /* make this canvas bigger */ int abs; /* mode: 0:rel 1:abs 2:max */ int diff; /* change this much */ int gflag; /* go up if neccessary */ int percent; { struct canvas *cv; int done, have, m, dir; debug3("ChangeCanvasSize abs %d diff %d percent=%d\n", abs, diff, percent); if (abs == 0 && diff == 0) return 0; if (abs == 2) { if (diff == 0) fcv->c_slweight = 0; else { for (cv = fcv->c_slback->c_slperp; cv; cv = cv->c_slnext) cv->c_slweight = 0; fcv->c_slweight = 1; cv = fcv->c_slback->c_slback; if (gflag && cv && cv->c_slback) ChangeCanvasSize(cv, abs, diff, gflag, percent); } return diff; } if (abs) { if (diff < 0) diff = 0; if (percent && diff > percent) diff = percent; } if (percent) { int wsum, up; for (cv = fcv->c_slback->c_slperp, wsum = 0; cv; cv = cv->c_slnext) wsum += cv->c_slweight; if (wsum) { up = gflag ? CalcSlicePercent(fcv->c_slback->c_slback, percent) : percent; debug3("up=%d, wsum=%d percent=%d\n", up, wsum, percent); if (wsum < 1000) { int scale = wsum < 10 ? 1000 : 100; for (cv = fcv->c_slback->c_slperp; cv; cv = cv->c_slnext) cv->c_slweight *= scale; wsum *= scale; debug1("scaled wsum to %d\n", wsum); } for (cv = fcv->c_slback->c_slperp; cv; cv = cv->c_slnext) { if (cv->c_slweight) { cv->c_slweight = (cv->c_slweight * up) / percent; if (cv->c_slweight == 0) cv->c_slweight = 1; } debug1(" - weight %d\n", cv->c_slweight); } diff = (diff * wsum) / percent; percent = wsum; } } else { if (abs && diff == (fcv->c_slorient == SLICE_VERT ? fcv->c_ye - fcv->c_ys + 2 : fcv->c_xe - fcv->c_xs + 2)) return 0; /* fix weights to real size (can't be helped, sorry) */ for (cv = fcv->c_slback->c_slperp; cv; cv = cv->c_slnext) { cv->c_slweight = cv->c_slorient == SLICE_VERT ? cv->c_ye - cv->c_ys + 2 : cv->c_xe - cv->c_xs + 2; debug1(" - weight %d\n", cv->c_slweight); } } if (abs) diff = diff - fcv->c_slweight; debug1("diff = %d\n", diff); if (diff == 0) return 0; if (diff < 0) { cv = fcv->c_slnext ? fcv->c_slnext : fcv->c_slprev; fcv->c_slweight += diff; cv->c_slweight -= diff; return diff; } done = 0; dir = 1; for (cv = fcv->c_slnext; diff > 0; cv = dir > 0 ? cv->c_slnext : cv->c_slprev) { if (!cv) { debug1("reached end, dir is %d\n", dir); if (dir == -1) break; dir = -1; cv = fcv; continue; } if (percent) m = 1; else m = cv->c_slperp ? CountCanvasPerp(cv) * 2 : 2; debug2("min is %d, have %d\n", m, cv->c_slweight); if (cv->c_slweight > m) { have = cv->c_slweight - m; if (have > diff) have = diff; debug1("subtract %d\n", have); cv->c_slweight -= have; done += have; diff -= have; } } if (diff && gflag) { /* need more room! */ cv = fcv->c_slback->c_slback; if (cv && cv->c_slback) done += ChangeCanvasSize(fcv->c_slback->c_slback, 0, diff, gflag, percent); } fcv->c_slweight += done; debug1("ChangeCanvasSize returns %d\n", done); return done; } static void ResizeRegions(arg, flags) char *arg; int flags; { struct canvas *cv; int diff, l; int gflag = 0, abs = 0, percent = 0; int orient = 0; ASSERT(display); if (!*arg) return; if (D_forecv->c_slorient == SLICE_UNKN) { Msg(0, "resize: need more than one region"); return; } gflag = flags & RESIZE_FLAG_L ? 0 : 1; orient |= flags & RESIZE_FLAG_H ? SLICE_HORI : 0; orient |= flags & RESIZE_FLAG_V ? SLICE_VERT : 0; if (orient == 0) orient = D_forecv->c_slorient; l = strlen(arg); if (*arg == '=') { /* make all regions the same height */ struct canvas *cv = gflag ? &D_canvas : D_forecv->c_slback; if (cv->c_slperp->c_slorient & orient) EqualizeCanvas(cv->c_slperp, gflag); /* can't use cv->c_slorient directly as it can be D_canvas */ if ((cv->c_slperp->c_slorient ^ (SLICE_HORI ^ SLICE_VERT)) & orient) { if (cv->c_slback) { cv = cv->c_slback; EqualizeCanvas(cv->c_slperp, gflag); } else EqualizeCanvas(cv, gflag); } ResizeCanvas(cv); RecreateCanvasChain(); RethinkDisplayViewports(); ResizeLayersToCanvases(); return; } if (!strcmp(arg, "min") || !strcmp(arg, "0")) { abs = 2; diff = 0; } else if (!strcmp(arg, "max") || !strcmp(arg, "_")) { abs = 2; diff = 1; } else { if (l > 0 && arg[l - 1] == '%') percent = 1000; if (*arg == '+') diff = atoi(arg + 1); else if (*arg == '-') diff = -atoi(arg + 1); else { diff = atoi(arg); /* +1 because of caption line */ if (diff < 0) diff = 0; abs = diff == 0 ? 2 : 1; } } if (!abs && !diff) return; if (percent) diff = diff * percent / 100; cv = D_forecv; if (cv->c_slorient & orient) ChangeCanvasSize(cv, abs, diff, gflag, percent); if (cv->c_slback->c_slorient & orient) ChangeCanvasSize(cv->c_slback, abs, diff, gflag, percent); ResizeCanvas(&D_canvas); RecreateCanvasChain(); RethinkDisplayViewports(); ResizeLayersToCanvases(); return; #if 0 if (siz + diff < 1) diff = 1 - siz; if (siz + diff > dsize - (nreg - 1) * 2 - 1) diff = dsize - (nreg - 1) * 2 - 1 - siz; if (diff == 0 || siz + diff < 1) return; if (diff < 0) { if (D_forecv->c_next) { D_forecv->c_ye += diff; D_forecv->c_next->c_ys += diff; D_forecv->c_next->c_yoff += diff; } else { for (cv = D_cvlist; cv; cv = cv->c_next) if (cv->c_next == D_forecv) break; ASSERT(cv); cv->c_ye -= diff; D_forecv->c_ys -= diff; D_forecv->c_yoff -= diff; } } else { int s, i = 0, found = 0, di = diff, d2; s = dsize - (nreg - 1) * 2 - 1 - siz; for (cv = D_cvlist; cv; i = cv->c_ye + 2, cv = cv->c_next) { if (cv == D_forecv) { cv->c_ye = i + (cv->c_ye - cv->c_ys) + diff; cv->c_yoff -= cv->c_ys - i; cv->c_ys = i; found = 1; continue; } s -= cv->c_ye - cv->c_ys; if (!found) { if (s >= di) continue; d2 = di - s; } else d2 = di > cv->c_ye - cv->c_ys ? cv->c_ye - cv->c_ys : di; di -= d2; cv->c_ye = i + (cv->c_ye - cv->c_ys) - d2; cv->c_yoff -= cv->c_ys - i; cv->c_ys = i; } } RethinkDisplayViewports(); ResizeLayersToCanvases(); #endif } static void ResizeFin(buf, len, data) char *buf; int len; char *data; { int ch; int flags = *(int *)data; ch = ((unsigned char *)buf)[len]; if (ch == 0) { ResizeRegions(buf, flags); return; } if (ch == 'h') flags ^= RESIZE_FLAG_H; else if (ch == 'v') flags ^= RESIZE_FLAG_V; else if (ch == 'b') flags |= RESIZE_FLAG_H|RESIZE_FLAG_V; else if (ch == 'p') flags ^= D_forecv->c_slorient == SLICE_VERT ? RESIZE_FLAG_H : RESIZE_FLAG_V; else if (ch == 'l') flags ^= RESIZE_FLAG_L; else return; inp_setprompt(resizeprompts[flags], NULL); *(int *)data = flags; buf[len] = '\034'; } void SetForeCanvas(d, cv) struct display *d; struct canvas *cv; { struct display *odisplay = display; if (d->d_forecv == cv) return; display = d; D_forecv = cv; if ((focusminwidth && (focusminwidth < 0 || D_forecv->c_xe - D_forecv->c_xs + 1 < focusminwidth)) || (focusminheight && (focusminheight < 0 || D_forecv->c_ye - D_forecv->c_ys + 1 < focusminheight))) { ResizeCanvas(&D_canvas); RecreateCanvasChain(); RethinkDisplayViewports(); ResizeLayersToCanvases(); /* redisplays */ } fore = D_fore = Layer2Window(D_forecv->c_layer); if (D_other == fore) D_other = 0; flayer = D_forecv->c_layer; #ifdef RXVT_OSC if (D_xtermosc[2] || D_xtermosc[3]) { Activate(-1); } else #endif { RefreshHStatus(); #ifdef RXVT_OSC RefreshXtermOSC(); #endif flayer = D_forecv->c_layer; CV_CALL(D_forecv, LayRestore();LaySetCursor()); WindowChanged(0, 'F'); } display = odisplay; } #ifdef RXVT_OSC void RefreshXtermOSC() { int i; struct win *p; p = Layer2Window(D_forecv->c_layer); for (i = 3; i >=0; i--) SetXtermOSC(i, p ? p->w_xtermosc[i] : 0); } #endif int ParseAttrColor(s1, s2, msgok) char *s1, *s2; int msgok; { int i, n; char *s, *ss; int r = 0; s = s1; while (*s == ' ') s++; ss = s; while (*ss && *ss != ' ') ss++; while (*ss == ' ') ss++; if (*s && (s2 || *ss || !((*s >= 'a' && *s <= 'z') || (*s >= 'A' && *s <= 'Z') || *s == '.'))) { int mode = 0, n = 0; if (*s == '+') { mode = 1; s++; } else if (*s == '-') { mode = -1; s++; } else if (*s == '!') { mode = 2; s++; } else if (*s == '=') s++; if (*s >= '0' && *s <= '9') { n = *s++ - '0'; if (*s >= '0' && *s <= '9') n = n * 16 + (*s++ - '0'); else if (*s >= 'a' && *s <= 'f') n = n * 16 + (*s++ - ('a' - 10)); else if (*s >= 'A' && *s <= 'F') n = n * 16 + (*s++ - ('A' - 10)); else if (*s && *s != ' ') { if (msgok) Msg(0, "Illegal attribute hexchar '%c'", *s); return -1; } } else { while (*s && *s != ' ') { if (*s == 'd') n |= A_DI; else if (*s == 'u') n |= A_US; else if (*s == 'b') n |= A_BD; else if (*s == 'r') n |= A_RV; else if (*s == 's') n |= A_SO; else if (*s == 'B') n |= A_BL; else { if (msgok) Msg(0, "Illegal attribute specifier '%c'", *s); return -1; } s++; } } if (*s && *s != ' ') { if (msgok) Msg(0, "junk after attribute description: '%c'", *s); return -1; } if (mode == -1) r = n << 8 | n; else if (mode == 1) r = n << 8; else if (mode == 2) r = n; else if (mode == 0) r = 0xffff ^ n; } while (*s && *s == ' ') s++; if (s2) { if (*s) { if (msgok) Msg(0, "junk after description: '%c'", *s); return -1; } s = s2; while (*s && *s == ' ') s++; } #ifdef COLOR if (*s) { static char costr[] = "krgybmcw d i.01234567 9 f FKRGYBMCW I "; int numco = 0, j; n = 0; if (*s == '.') { numco++; n = 0x0f; s++; } for (j = 0; j < 2 && *s && *s != ' '; j++) { for (i = 0; costr[i]; i++) if (*s == costr[i]) break; if (!costr[i]) { if (msgok) Msg(0, "illegal color descriptor: '%c'", *s); return -1; } numco++; n = n << 4 | (i & 15); #ifdef COLORS16 if (i >= 48) n = (n & 0x20ff) | 0x200; #endif s++; } if ((n & 0xf00) == 0xf00) n ^= 0xf00; /* clear superflous bits */ #ifdef COLORS16 if (n & 0x2000) n ^= 0x2400; /* shift bit into right position */ #endif if (numco == 1) n |= 0xf0; /* don't change bg color */ if (numco != 2 && n != 0xff) n |= 0x100; /* special invert mode */ if (*s && *s != ' ') { if (msgok) Msg(0, "junk after color description: '%c'", *s); return -1; } n ^= 0xff; r |= n << 16; } #endif while (*s && *s == ' ') s++; if (*s) { if (msgok) Msg(0, "junk after description: '%c'", *s); return -1; } debug1("ParseAttrColor %06x\n", r); return r; } /* * Color coding: * 0-7 normal colors * 9 default color * e just set intensity * f don't change anything * Intensity is encoded into bits 17(fg) and 18(bg). */ void ApplyAttrColor(i, mc) int i; struct mchar *mc; { debug1("ApplyAttrColor %06x\n", i); mc->attr |= i >> 8 & 255; mc->attr ^= i & 255; #ifdef COLOR i = (i >> 16) ^ 0xff; if ((i & 0x100) != 0) { i &= 0xeff; if (mc->attr & (A_SO|A_RV)) # ifdef COLORS16 i = ((i & 0x0f) << 4) | ((i & 0xf0) >> 4) | ((i & 0x200) << 1) | ((i & 0x400) >> 1); # else i = ((i & 0x0f) << 4) | ((i & 0xf0) >> 4); # endif } # ifdef COLORS16 if ((i & 0x0f) != 0x0f) mc->attr = (mc->attr & 0xbf) | ((i >> 3) & 0x40); if ((i & 0xf0) != 0xf0) mc->attr = (mc->attr & 0x7f) | ((i >> 3) & 0x80); # endif mc->color = 0x99 ^ mc->color; if ((i & 0x0e) == 0x0e) i = (i & 0xf0) | (mc->color & 0x0f); if ((i & 0xe0) == 0xe0) i = (i & 0x0f) | (mc->color & 0xf0); mc->color = 0x99 ^ i; debug2("ApplyAttrColor - %02x %02x\n", mc->attr, i); #endif } screen-4.1.0/patchlevel.h0000644000175000017500000010131711642704565013350 0ustar abeabe/* Copyright (c) 2008, 2009 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Micah Cowan (micah@cowan.name) * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net) * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Copyright (c) 1987 Oliver Laumann * * 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, 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 (see the file COPYING); if not, see * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA * **************************************************************** * $Id$ GNU */ /**************************************************************** * * patchlevel.h: Our life story. * * 08.07.91 -- 3.00.01 -wipe and a 'setenv TERM dumb' bugfix. * 17.07.91 -- 3.00.02 another patchlevel by Wayne Davison * 31.07.91 -- 3.00.03 E0, S0, C0 for flexible semi-graphics, nonblocking * window title input and 'C-a :' command input. * 10.08.91 -- 3.00.04 scrollback, markkeys and some bugfixes. * 13.08.91 -- 3.00.05 mark routine improved, ansi prototypes added. * 20.08.91 -- 3.00.06 screen -h, faster GotoPos in overlay, termcap %. * instead of %c * 28.08.91 -- 3.00.07 environment variable support. security. terminfo. * pyramid and ultrix support. * 07.09.91 -- 3.00.99 secopen(), MIPS support, SVR4 support. * 09.09.91 -- 3.01.00 backspace bug fixed. * 03.10.91 -- 3.01.01 ansi.c: null-ptr fixed, CLS now saves to scrollback. * Using setresuid on hpux. Memory leak fixed. * Better GotoPos(). Support for IC. Another resize bug. * Detach() w/o fore crashed. -T and -A(dapt) option. * GNU copyleft. * 19.12.91 -- 3.01.02 flow now really automatic (autoflow killed). * 7 bit restriction removed from WriteString(). * 09.01.92 -- 3.01.03 flow reattach bug fixed. VDISCARD bug fixed. * 13.01.92 -- 3.01.04 new flow concept: ^Af toggles now three states * 21.01.92 -- 3.01.05 '^A:screen 11' bug fixed. aflag in DoScreen(). * Some code cleanup. attach_tty and display_tty[] * added. * 26.01.92 -- 3.01.06 apollo support, "hardcopy_append on", "bufferfile", * SECURITY PROBLEM cleared.. * 28.01.92 -- 3.01.07 screen after su allowed. Pid became part of * SockName. sysvish 14 character restriction considered. * 31.01.92 -- 3.02.00 Ultrix port, Irix 3.3 SGI port, shadow pw support, * data loss on stdin overflow fixed. "refresh off". * 12.02.92 -- 3.02.02 stripdev() moved, -S introduced, bufferfile improved, * ShellProg coredump cleared. SVR4 bugfixes. * I/O code speedup added. * 24.04.92 -- 3.02.03 perfectly stackable overlays. One scrollback per window, * not per display. * 05.05.92 -- 3.02.04 very nasty initialisation bug fixed. * 09.05.92 -- 3.02.05 parsing for $:cl: termcap strings and \012 octal notation * in screenrc file. More structuring. Detached startup * with 'screen -d -m -S...' bugfixed. * 11.05.92 -- 3.02.06 setreuid() bugs cleared, C-a : setenv added. * "xn" capability in TERMCAP needed since "am" is there. * 25.06.92 -- 3.02.07 The multi display test version. Have merci. * 15.07.92 -- 3.02.08 :B8: supports automatic charset switching for 8-bit * 26.09.92 -- 3.02.09 Ported to linux. Ignoring bad files in $SCREENDIR * 22.10.92 -- 3.02.10 screen.c/ansi.c splitted in several pieces. * Better ISearch. Cleanup of loadav.c * 29.10.92 -- 3.02.11 Key mechanism rewritten. New command names. * New iscreenrc syntax. * 02.11.92 -- 3.02.12 'bind g copy_reg' and 'bind x ins_reg' as suggested by * stillson@tsfsrv.mitre.org (Ken Stillson). * 03.11.92 -- 3.02.13 Ported to SunOs 4.1.2. Gulp. Some NULL ptrs fixed and * misc. braindamage fixed. * 03.11.92 -- 3.02.14 Argument number checking, AKA fixed. * 05.11.92 -- 3.02.15 Memory leaks in Detach() and KillWindow() fixed. * Lockprg powerdetaches on SIGHUP. * 12.11.92 -- 3.02.16 Introduced two new termcaps: "CS" and "CE". * (Switch cursorkeys in application mode) * Tim's async output patch. * Fixed an ugly bug in WriteString(). * New command: 'process' * 16.11.92 -- 3.02.17 Nuking unsent tty output is now optional, (toxic * ESC radiation). * 30.11.92 -- 3.02.18 Lots of multi display bugs fixed. New layer * function 'Restore'. MULTIUSER code cleanup. * Rudimental acls added for multiuser. * No more error output, when output gives write errors. * 02.12.92 -- 3.02.19 BROKEN_PIPE and SOCK_NOT_IN_FS defines added for * braindead systems. Bug in recover socket code fixed. * Can create windows again from shell. * 22.12.92 -- 3.02.20 Made a superb configure script. STY and break fixed. * 01.02.93 -- 3.02.21 Coredump bug fixed: 8-bit output in background windows. * Console grabbing somewhat more useable. * 23.02.93 -- 3.02.22 Added ^:exec command, but not tested at all. * 23.02.93 -- 3.02.23 Added 'hardcopydir' and 'logdir' commands. * 11.03.93 -- 3.02.24 Prefixed display and window structure elements. * Screen now handles autowrapped lines correctly * in the redisplay and mark function. * 19.03.93 -- 3.03.00 Patched for BSD386. pseudos work. * 31.03.93 -- 3.03.01 Don't allocate so much empty attr and font lines. * 04.04.93 -- 3.03.02 fixed :exec !..| less and :|less, patched BELL_DONE & * ^B/^F. Fixed auto_nuke attribute resetting. Better linux * configure. ^AW shows '&' when window has other attacher. * MAXWIN > 10 patch. KEEP_UNDEF in config.h.in, shellaka * bug fixed. dec alpha port. Solaris port. * 02.05.93 -- 3.03.03 Configure tweaked for sgi. Update environment with * setenv command. Silence on|off, silencewait , * defautonuke commands added. Manual page updated. * 13.05.93 -- 3.03.04 exit in newsyntax script, finished _CX_UX port. * Texinfo page added by Jason Merrill. Much longish debug * output removed. Select window by title (or number). * 16.06.93 -- 3.04.00 Replaced ^A- by ^A^H to be complementary to ^A SPACE. * Moved into CVS. Yacc. * 28.06.93 -- 3.04.01 Fixed selecting windows with numeric title. Silence * now works without nethackoption set. * 01.07.93 -- 3.04.02 Implementing real acls. * 22.07.93 -- 3.05.00 Fixed SVR4, some multiuser bugs, -- DISTRIBUTED * 05.08.93 -- 3.05.01 ${srcdir} feature added. Shellprog bug fixed. * Motorola reattach bug fixed. Writelock bug fixed. * Copybuffer moved into struct acluser. Configure.in * uglified for Autoconf1.5. Paste may now have an * argument. Interactive setenv. Right margin bug * fixed. IRIX 5 patches. -- DISTRIBUTED * 13.08.93 -- 3.05.02 ultrix support added. expand_vars removed from * register function. Paste bug fixed. * sysmacros.h now included in pty.c on sgis * Strange hpux hack added for TTYCMP. * Zombie feature improved. * 08.09.93 -- 3.05.03 Makefile and OSF1 fine tuning. Eased attach to * multi sessions. Writelock now obeys acl write * permissions. UserDel() now preserves defaults. * acladd/aclchg syntax improved. Updated * documentation. Bug in at command fixed. * MakeWindow() now obeys perm defaults. * 03.10.93 -- 3.05.90 Multiple displays can now share the same window. * Layers now belong to Windows. "Select -" yields a blank * page. Debug output can be switched on/off at runtime. * Number command changes window number and utmp-slot. * 14.10.93 -- 3.05.91 Mechanism to find the "best" window added. Much * debugging done and still needed. Slowpaste setting now * per window. Preserving fore AND other window when * detached. Per user settings for `monitor' and `silence'. * New command `su'. BlankWindow performs now ColonInput. * History command fixed, it depended on paste code that * was previously changed to allow concatenation of buffers. * Fixing umask problem with WriteFile() reported by Jamie * Mason. * 30.11.93 -- 3.05.04 Kanji support added. New keymap feature: * bindkey and various map commands. GR and C1 * flags now define the character processing. * 30.11.93 -- 3.05.92 Kanji support added. New keymap feature: * bindkey and various map commands. GR and C1 * flags now define the character processing. * 17.12.93 -- 3.05.93 Tcon authentification mechanism. AddChar macro broken up * into 2 functions. Acl.c, network.c, misc.c, termcap.c * and tty.c are now display free! * 27.12.93 -- 3.05.94 Telnet login works, can export one window per mux. * Acl-groups added. Export rights is an acl. * connect works, can create shadow window thus import * command channel and switch windows. Can detach sessions * from each other. Can renumber imported and exported * windows. DL_LOOP prevents now SEGV, sessions have names * and can be connected to very flexible. * 03.01.94 -- 3.05.95 Import and export of any number of channels works, * except a small bug with margin handling when exporting. * Window titles are forwarded, break is forwarded and * tcon learned the mux protocoll. A few more bugs in * network.c fixed. Tcon has Mux arrays, Protocoll is '\0' * free. * 08.01.94 -- 3.05.96 More tcon work. Solaris debugging. * * 14.01.94 -- 3.05.05 New FindSocket() code. Nicer socket handling. * 20.01.94 -- 3.05.06 New attribute handling code. NeXT fixes. * 04.02.94 -- 3.05.07 Ugly bug in ScrollH fixed. Keymap defaults. * 10.03.94 -- 3.05.97 'defsilence' by Lloyd Zusman. Zombie resurrekt key. * -b, -p options. Fixed Compilekeys(), gulp. config.h * allows choice of VMIN/VTIME/NDELAY for ttys. * 13.04.94 -- 3.05.08 Kanji bug fixed. POSIX sigaction support. * os.h cleanup. UTNOKEEP splitted into * UT_CLOSE and UT_UNSORTED. linux no longer * implies UT_CLOSE. "struct display" name * convention change: _d_ to d_ and d_ to D_. * 20.04.94 -- 3.05.09 configure.in ptyrange bug fixed. Upgraded * to autoconf-1.8 * 27.04.94 -- 3.05.10 97801 obscure code support. Linux long * password workaround. * 09.05.94 -- 3.05.11 seteuid() support added. Security fixes. * _IBMR2 kludge makes call to sleep obsolete. * Small fixes in uname() code. djm suggests replace of * BSDI by __bsdi__. * 27.07.94 -- 3.05.12 seteuid attacher bug fixed. ks/ke changed * in termcap/info and termcap.c * 01.09.94 -- 3.05.58 (There are a few more patches to come, subtracted 40) * breaktype command to select how we cause breaks. * Testing logfile.c. Manual and texinfo documentation * updated to explain all new commands except keymapping. * Added modem lines to info of plain ttys. Using * cfset{i,o}speed() for POSIX is better, much better. * 07.09.94 -- 3.05.59 Flushing logfiles every 5 seconds. Testing new * resize linewrap code. Resize with care. * Resurrect now displays its command string. * 11.09.94 -- 3.05.60 Lines are now correctly wrapped, when window size * changes; this prevents loss of text. * 15.09.94 -- 3.05.61 umask renamed to aclumask, bell renamed to bell_msg. * *_msg commands show message when called w/o parameter. * Many changes in the manual, thanks to Sven Guckes. * -O removed. * 27.09.94 -- 3.05.13 defwlock stupidity fixed. MakeTermcap ks/ke * ':' removed. Termcap entry improved. * copy_reg and ins_reg obsoleted by better paste command: * paste => paste . * copy_reg r => paste . r * ins_reg r => paste r * ins_reg => paste * 18.10.94 -- 3.05.62 breaktype changed. -L option added to enable logging * from both command line and screenrc. SIGXFSZ ignored. * 28.11.94 -- 3.05.63 ACL's sharpened. No user has any rights, unless * explicitly given. Only two exceptions: 1) "acladd user" * without further parameters. 2) Evry user has a default * umask that gives himself all permissions on the windows * he creates. Bug with colon input on shared windows fixed. * The commad is now executed by the user typing the final * Enter-Key rather by a random user. * 30.11.94 -- 3.05.64 On demand grabbing of pending auto writelocks. * Solaris troubles us with kill(pid, 0) ... not fixed... * defbreaktype added. (breaktype is also global, still...) * SIGARGHACK cleared, to pamper poor little Ultrix4.4 cfe. * defescape added. * w_status changed to w_hstatus, it's a #define in * Domain/OS reported by ejackson@iastate.edu. * 05.12.94 -- 3.05.17 SVR4 pty bug fixed, don't update window status * line if not changed, onyx support. Manual * pages updated. * 14.12.94 -- 3.05.18 w_status changed to w_hstatus, it's a #define in * Domain/OS reported by ejackson@iastate.edu. * Screen manpage patches by larry. * Ugly seteuid bug in ForkWindow() fixed. * 20.12.94 -- 3.06.00 Solaris has broken seteuid(). * osf loadav patches. -- DISTRIBUTED * 08.01.95 -- 3.05.65 Bug with LOGOUTOK and -ln fixed. redundant secfopen() * avoided, when logfflush() looks at delayed nfs updates. * Option parser now allowes condensed options. -A fixed. * New commands 'preselect' and 'defpreselect'. New option * -WdmS starts a detached screen session with watchdog. * 16.01.95 -- 3.06.01 KANJI patch. doc/Makefile.in fixed. * Install now calls doc/Makefile install. * Don't use 'ds' too often, breaks MSkermit. * undef'd LOGOUTOK logs in now. * Ultrix is broken, too (seteuid). * Use \r (not \n) to join lines in pastebuf. * bindkey can now remove sequences. * InitTTY fixed for PLAIN. -- DISTRIBUTED * 06.02.95 -- 3.05.66 DisplayLine() does now clipping to reduce coredump- * frequency. Window size is adapted to the display that * types input, to reduce multi-user confusion. Scrollback * mode still may get the wrong size. * 07.02.95 -- 3.05.67 WinRewrite() also needs to clip. Users without unix * account, but with screen password allowed. Chacl * allows password change, su prompts for user name too. * 01.03.95 -- 3.05.68 Leaving a window may now cause a resize to match a * remaining display. Simple ESC-CR fix in the vt100 * state machine. * 26.03.95 -- 3.05.69 Markroutine() needs to resize the window to avoid * coredumps, just like WinProcess() already does. * More NEED_ flags added in comm.c to avoid coredumps. * 04.04.95 -- 3.06.02 Simple ESC-CR fix in the vt100 state machine. * Now compiles again with all extras disabled. * Zombie resurrect added. defc1, defgr, defkanji * added. Screen now replies to a secondary DA * query. Some missing NEED_XXX added in comm.c. * Better default tty permissions/group test. * More AUX support, now compiles with POSIX. * Function keycodes xtermified (F11, F12). * Paste bug fixed (only worked with KANJI). * Check bcopy before memcpy/memmove. * FindSocket code much fixed & improved. * 10.04.95 -- 3.05.70 Display_displays() now shows the users permissions on * the currently displayed window, this is easier than a * full featured lsacl, but also helps. chacl can now copy * users, but we need to copy windows. * 26.04.95 -- 3.05.71 Multi digit screen numbers in utmp. MakeWindow() now * echoes what it does, just like RemakeWindow() when * 'verbose on' (default off). * `screen -ls myname/' will find own(!) non-multi sessions. * Command line option -q improved and documented. * 'debug off' also shuts attacher debugging off now. * 03.05.95 -- 3.05.72 'connect' command bugfixed. colon prompt improved. * open(O_NONBLOCK) does not work on 4.1.3, using O_NDELAY. * There are writes to exp_wid2chan[-1], XXX I just added * fillers to the mux structure, please debug this ASAP! * WindowByName() prefers exact matches now. Esc forwarding * from Frontend to Backend suppressed unless specified. * 26.06.95 -- 3.05.73 Improving the combination of dflag and rflag: If both * are set, a screen session is reattached, regardless * if it was previously detached or attached elseewhere. * "screen -D -RR" is thus most powerful: Give me my screen * session here and now. No matter, if this means creating * a new session (due to the second R without warning * message), detching the session first (and due to the * capitalised D logging out), or simply attaching to it. * 13.07.95 -- 3.05.74 Markroutine learned new join mode: comma seperated. * Can disable the detach feature from config.h. * Configure.in now calls etc/toolcheck. Password is no * longer a static array. * 30.07.95 -- 3.05.75 Karl Heuer wants to install with a relative symlink. * Command line option -k removed (try -t). * 31.08.95 -- 3.06.03 Color support, digraph command, code * cleanup (struct mchar/mline added). * 03.09.95 -- 3.06.04 SetRendition display check. Solaris unblock * SIGHUP. w_curchar->w_rend, lintified. * Shadow-password code moved and rewritten * (includes sun C2). * 06.09.95 -- 3.05.76 Added support for braille displays (by Hadi Bargi Rangin * and Bill Barry, {bargy,barryb}@dots.physics.orst.edu * Added baud, cs8, istrip, ixon, ixoff options for plain * tty windows. Untested. * 09.09.95 -- 3.07.99 Merged 3.7.76 back into the main distribution but * without network, blankwindow and dlist support. * Global variable Password removed. * Resize code completely rewritten. * New commands: sorendition, (def)charset. * strftime-like message generation. * 26.09.95 -- 3.06.05 resize code completely rewritten. * Very visible cursor added. vbell sequence * \Eb added. _delay for terminfo libs added * to make the padding work for the first time. * New ProcessInput() makes "command command" * work. '[def]escape ""' clears escape chars. * Changed logdir command to logfile. It now uses * MakeWinMsg() to create the filename. * Updated the manuals. * 03.10.95 -- 3.08.00 Merged 3.07.99 back into my 3.06.05. * pause removed. NONROOT now in config.h. * sysV68 configure test. Socket protocol got * revision number. New command termcapinfo. * Screenrcs, docs & configure.in updated * 18.10.95 -- 3.08.01 Info shows parser state. * Very visible cursor added. vbell sequence * \Eb added. _delay for terminfo libs added * to make the padding work for the first time. * Braille code almost completely reworked. * New ProcessInput() makes "command command" * work. '[def]escape ""' clears escape chars. * Command logdir -> logfile and uses MakeWinMsg. * Updated the manuals. New mark command 'x'. * stuff has new "-k" parameter. * 28.10.95 -- 3.06.06 Added new 'XC' capability to provide * a method for character translation. * 17.11.95 -- 3.07.00 Added CheckEscape() function. * acl -> acls because of hpux10 nameclash * /stand/vmunix added to kernel list (hpux10) * stripdev changed to translate * /dev/pts to /dev/pts/ (unixware) * -lgen added to GETUTENT configure test. * 20.11.95 -- 3.07.01 corrected vbell null ptr reference. * -- DISTRIBUTED * 27.11.95 -- 3.08.02 Added CheckEscape() function. * acl -> acls because of hpux10 nameclash * /stand/vmunix added to kernel list (hpux10) * stripdev changed to translate * /dev/pts to /dev/pts/ (unixware) * -lgen added to GETUTENT configure test. * corrected vbell null ptr reference * -- 3.08.03 etc/toolcheck is now shouting louder. * Solaris 2.5 has /kernel/genunix. * Touching socket when detach/attach. * FindWindow corrected. AIX4 patch * from robert@mayday.cix.co.uk. * 1.09.96 -- 3.07.02 added #ifdef MAPKEYS for CheckEscape. * etc/toolcheck is now shouting louder. * Touching socket when detach/attach. * Linux tcflush hack. Linux md5 password suport. * USE_SGR support for dumb (wyse) terminals. * "at" and "reset" commands improved. * Now sensitive to broken AIX4 TIOCPKT. * tek patch unapplied. * linux utmp patch: set slot to DEAD_PROCESS. * include signal.h for killpg if hpux10.10. * linux: elf, but no SVR4, check for utmpx. * hpux10.10 libcurses breaks select()! * -- DISTRIBUTED * 27.09.96 -- 3.07.03 ncurses tgetflag returns -1 if cap not valid. * autonuke fix: reset application mode. An init * string may have cleared it. * Small UTMPOK patch from Douglas B. Jones. * 23.06.97 -- 3.07.04 Some bugfixes. Kanji fixed. * Code update from 3.8.6: Colon line editing added. * Digraph made line-editing resistant. * DEC ALPHA ut_user[0] = 0; * Added error messages to exit_with_usage. * FindSocket code improved (the MULTIUSER part). * Use utimes() if available. Power-detached start. * vsnprintf() support. exit -> _exit in window.c. * AddXChars now tolerates NULL string. * -- DISTRIBUTED * 10.11.98 -- 3.07.05 Wayne's resize.c patch to keep the cursor * onscreen. FindWindow corrected. AIX4 patch * from robert@mayday.cix.co.uk. * Fixed kanji am & markcursor bugs. * SCO support (Gert Doering). * Wayne's statusline extra space. New flag nospc * for MakeWinMsg. New TF capability: add missing * termcap/info caps. screen-exchange security * fix. Use kstat for Solaris' loadavg. * Check for mode 775 if screen runs setgid. * Fixed typo in silence command. * Allow detach with no tty. HPUX10.20 ltchars * hack. Use @1/@7 as replacement for kh/kH. * Use seteuid before calling tgetent. * Check for displays in Msg(). * Linux ncurses hack: redefine _nc_timed_wait. * Configure check for ncurses (sigh). * ITOH Yasufumi: kanji fixes, osf support, * bug fixes. More secure Rewrite(). * Increased line buffer size to 2048 bytes. * SCO-5 Fixes (Brian L. Gentry). * 25.11.98 -- 3.07.06 resize code now handles tabs correctly. * -- DISTRIBUTED * -- 3.09.00 loads'o'bugs fixed, 3.8 merged with 3.7. * new region clip code. * Many new features (see NEWS file). * 3.08.99 -- 3.09.02 -- DISTRIBUTED * 11.08.99 -- 3.09.04 small utmp fix, BSD chflags fix, tty mode fix * -- DISTRIBUTED * 1.09.99 -- 3.09.05 linux SVR4_PTYS fixes, better ShowWindos(), * Panic() displays bug fixed, strerror fixed, * missing $srcdir & bad prefix in Makefiles. * console grabbing with SRIOCSREDIR. * linux utmp workaround added. Some KANJI bugs * fixed. Stupid StuffKey() bug fixed. * -- DISTRIBUTED * 24.07.00 -- 3.09.06 kanji fixes. lock escape char fix. * removed delayed message hack. * resize command & focus subcomands by joze. * fix for solaris' utmp_helper bug. * linux tty handling fix. * mousetracking, rxvt osc sequences. * background color erase support. * don't log user in after hangup. * hstatus escape update bug fixed. * 1.09.00 -- 3.09.08 -- DISTRIBUTED * 25.05.01 -- 3.09.09 use $DESTDIR in Makefiles. * renamed struct user to acluser to fix hpux * problem for good. utf8 support. 16 color * support. New -X option and escape sequence * to send screen commands. * New commands: attrcolor, defutf8, dinfo, utf8. * Extended commands: width, height, readbuf, * writebuf. Better nlist64 detection. * New config.h option SOCKDIR_IS_LOCAL_TO_HOST. * Don't call tputs with an empty string. * New string escape %{ for attr/color changes. * LRefreshAll bug fixed (0 instead of -1 as bce). * New quote handling in Parse(). Workaround for * some bad termcap/info entries added. Set BE * for all xtermish emulators. Added '0x' and * 'U+' prefix in digraph command. LOADAV_TYPE * detection fixed. * -- DISTRIBUTED * 4.09.01 -- 3.09.10 '-R' security fix. Fixed array in MScrollV(). * -- DISTRIBUTED * Reset charset after 'me'. * 14.02.02 -- 3.09.11 Support for other encodings. Double width * utf-8 chars. 'L' modifier for %D, %M, %w * and %W. New %= (hfill), %H (hostname), * %f (flags), %F (focus) escapes. New commands * source, windowlist, deflog. Command key classes. * New login state: always. Time format * changeable. 256 color support. * Updated digraph table. Ignorecase. * Windowlist resizeable on blank window. * Added encoding to paste buffers. * Hpux loadtype detection fixed. * Disabled im/ic warning. Fixed a bug that * could cause window lockups in rare * circumstances. Made hangup signal to the * backend process detach all displays. * New escapes %< %>, + and - flag for %w. * Added eval command, added -h option to detach. * Also set flayer when processing -X commands. * use getpt() on linux systems. doc patches from * Adam Lazur. tty flow/intr cleanup. * -- DISTRIBUTED * 29.08.2002 3.09.12 Port to POSIX 1003.1-2001 hosts (Paul Eggert). * Fixed encoding for reattach password test. * Fixed NUL characters when encodings are active. * Fixed silly encodings bugs. Fixed bogus * oldflayer when a window gets freed. * Altscreen support by Gurusamy Sarathy. * Reuse old password in builtin_screenlock. * -- DISTRIBUTED * 05.09.2002 3.09.13 added missing break statement that broke * the eval command. * -- DISTRIBUTED * 13.03.2003 3.09.15 Console workaround for linux. Scrolling-region * reset fix. GBK encoding added. * support for unicode combining characters added. * openpty() support added (thomas@xs4all.nl). * preselect of blank window ('-') or window * list ('=') added. Added %` string escape * and backtick command. * -- DISTRIBUTED * 08.09.2003 4.00.00 rewrote nonblock command, added defnonblock. * added zmodem support (catch & passthrough). * added screenblanker. * fixed a couple of GBK bugs. * rewrote command parsing. * added -m option to windowlist (Felix Rosencrantz) * -- DISTRIBUTED * 18.09.2003 4.00.01 fixed two small bugs in the new parser. * -- DISTRIBUTED * 05.12.2003 4.00.02 fixed a bug in the ansi parser. fixed execs * on ttys. fixed hardstatus line on blanked screen. * -- DISTRIBUTED * 11.10.2004, 4.00.03jw handle StartRc errors nonfatal if due to a msg. * 12.10.2004, 4.00.03jw1 let docu of 'split' 'focus' 'remove' and 'only' refer to each other. * 01.11.2004, 4.00.03jw2 zombie command has new option 'onerror' * 2005-12-19, 4.00.03jw3 syntax error. */ #define ORIGIN "GNU" #define REV 4 #define VERS 1 #define PATCHLEVEL 0 #define DATE "2-May-06" #define STATE "devel" screen-4.1.0/utmp.c0000644000175000017500000004555111642704565012210 0ustar abeabe/* Copyright (c) 2008, 2009 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Micah Cowan (micah@cowan.name) * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net) * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Copyright (c) 1987 Oliver Laumann * * 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, 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 (see the file COPYING); if not, see * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA * **************************************************************** */ #include #include #include #include "config.h" #include "screen.h" #include "extern.h" #ifdef HAVE_UTEMPTER #include #endif extern struct display *display; #ifdef CAREFULUTMP extern struct win *windows; #endif extern struct win *fore; extern char *LoginName; extern int real_uid, eff_uid; /* * UTNOKEEP: A (ugly) hack for apollo that does two things: * 1) Always close and reopen the utmp file descriptor. (I don't know * for what reason this is done...) * 2) Implement an unsorted utmp file much like GETUTENT. * (split into UT_CLOSE and UT_UNSORTED) */ #ifdef UTNOKEEP # define UT_CLOSE # define UT_UNSORTED #endif #ifdef UT_CLOSE # undef UT_CLOSE # define UT_CLOSE endutent() #else # define UT_CLOSE #endif /* * we have a suid-root helper app that changes the utmp for us * (won't work for login-slots) */ #if (defined(sun) && defined(SVR4) && defined(GETUTENT)) || defined(HAVE_UTEMPTER) # define UTMP_HELPER #endif #ifdef UTMPOK static slot_t TtyNameSlot __P((char *)); static void makeuser __P((struct utmp *, char *, char *, int)); static void makedead __P((struct utmp *)); static int pututslot __P((slot_t, struct utmp *, char *, struct win *)); static struct utmp *getutslot __P((slot_t)); #ifndef GETUTENT static struct utmp *getutent __P((void)); static void endutent __P((void)); static int initutmp __P((void)); static void setutent __P((void)); #endif #if defined(linux) && defined(GETUTENT) static struct utmp *xpututline __P((struct utmp *utmp)); # define pututline xpututline #endif static int utmpok; static char UtmpName[] = UTMPFILE; #ifndef UTMP_HELPER static int utmpfd = -1; #endif # if defined(GETUTENT) && (!defined(SVR4) || defined(__hpux)) && ! defined(__CYGWIN__) # if defined(hpux) /* cruel hpux release 8.0 */ # define pututline _pututline # endif /* hpux */ extern struct utmp *getutline(), *pututline(); # if defined(_SEQUENT_) extern struct utmp *ut_add_user(), *ut_delete_user(); extern char *ut_find_host(); # ifndef UTHOST # define UTHOST /* _SEQUENT_ has ut_find_host() */ # endif # endif /* _SEQUENT_ */ # endif /* GETUTENT && !SVR4 */ # if !defined(GETUTENT) && !defined(UT_UNSORTED) # ifdef GETTTYENT # include # else struct ttyent { char *ty_name; }; static void setttyent __P((void)); static struct ttyent *getttyent __P((void)); # endif # endif /* !GETUTENT && !UT_UNSORTED */ #ifndef _SEQUENT_ # undef D_loginhost # define D_loginhost D_utmp_logintty.ut_host #endif #ifndef UTHOST # undef D_loginhost # define D_loginhost ((char *)0) #endif #endif /* UTMPOK */ /* * SlotToggle - modify the utmp slot of the fore window. * * how > 0 do try to set a utmp slot. * how = 0 try to withdraw a utmp slot. * * w_slot = -1 window not logged in. * w_slot = 0 window not logged in, but should be logged in. * (unable to write utmp, or detached). */ #ifndef UTMPOK void SlotToggle(how) int how; { debug1("SlotToggle (!UTMPOK) %d\n", how); # ifdef UTMPFILE Msg(0, "Unable to modify %s.\n", UTMPFILE); # else Msg(0, "Unable to modify utmp-database.\n"); # endif } #endif #ifdef UTMPOK void SlotToggle(how) int how; { debug1("SlotToggle %d\n", how); if (fore->w_type != W_TYPE_PTY) { Msg(0, "Can only work with normal windows.\n"); return; } if (how) { debug(" try to log in\n"); if ((fore->w_slot == (slot_t) -1) || (fore->w_slot == (slot_t) 0)) { #ifdef USRLIMIT if (CountUsers() >= USRLIMIT) { Msg(0, "User limit reached."); return; } #endif if (SetUtmp(fore) == 0) Msg(0, "This window is now logged in."); else Msg(0, "This window should now be logged in."); WindowChanged(fore, 'f'); } else Msg(0, "This window is already logged in."); } else { debug(" try to log out\n"); if (fore->w_slot == (slot_t) -1) Msg(0, "This window is already logged out\n"); else if (fore->w_slot == (slot_t) 0) { debug("What a relief! In fact, it was not logged in\n"); Msg(0, "This window is not logged in."); fore->w_slot = (slot_t) -1; } else { RemoveUtmp(fore); if (fore->w_slot != (slot_t) -1) Msg(0, "What? Cannot remove Utmp slot?"); else Msg(0, "This window is no longer logged in."); #ifdef CAREFULUTMP CarefulUtmp(); #endif WindowChanged(fore, 'f'); } } } #ifdef CAREFULUTMP /* CAREFULUTMP: goodie for paranoid sysadmins: always leave one * window logged in */ void CarefulUtmp() { struct win *p; if (!windows) /* hopeless */ return; debug("CarefulUtmp counting slots\n"); for (p = windows; p; p = p->w_next) if (p->w_ptyfd >= 0 && p->w_slot != (slot_t)-1) return; /* found one, nothing to do */ debug("CarefulUtmp: no slots, log one in again.\n"); for (p = windows; p; p = p->w_next) if (p->w_ptyfd >= 0) /* no zombies please */ break; if (!p) return; /* really hopeless */ SetUtmp(p); Msg(0, "Window %d is now logged in.\n", p->w_number); } #endif /* CAREFULUTMP */ void InitUtmp() { debug1("InitUtmp testing '%s'...\n", UtmpName); #ifndef UTMP_HELPER if ((utmpfd = open(UtmpName, O_RDWR)) == -1) { if (errno != EACCES) Msg(errno, "%s", UtmpName); debug("InitUtmp failed.\n"); utmpok = 0; return; } # ifdef GETUTENT close(utmpfd); /* it was just a test */ utmpfd = -1; # endif /* GETUTENT */ #endif /* UTMP_HELPER */ utmpok = 1; } #ifdef USRLIMIT int CountUsers() { struct utmp *ut; int UserCount; debug1("CountUsers() - utmpok=%d\n", utmpok); if (!utmpok) return 0; UserCount = 0; setutent(); while (ut = getutent()) if (SLOT_USED(ut)) UserCount++; UT_CLOSE; return UserCount; } #endif /* USRLIMIT */ /* * the utmp entry for tty is located and removed. * it is stored in D_utmp_logintty. */ void RemoveLoginSlot() { struct utmp u, *uu; ASSERT(display); debug("RemoveLoginSlot: removing your logintty\n"); D_loginslot = TtyNameSlot(D_usertty); if (D_loginslot == (slot_t)0 || D_loginslot == (slot_t)-1) return; #ifdef UTMP_HELPER if (eff_uid) /* helpers can't do login slots. sigh. */ #else if (!utmpok) #endif { D_loginslot = 0; debug("RemoveLoginSlot: utmpok == 0\n"); } else { #ifdef _SEQUENT_ { char *p; if ((p = ut_find_host(D_loginslot)) != 0) strncpy(D_loginhost, p, sizeof(D_loginhost) - 1); D_loginhost[sizeof(D_loginhost) - 1] = 0; } #endif /* _SEQUENT_ */ if ((uu = getutslot(D_loginslot)) == 0) { debug("Utmp slot not found -> not removed"); D_loginslot = 0; } else { D_utmp_logintty = *uu; u = *uu; makedead(&u); if (pututslot(D_loginslot, &u, (char *)0, (struct win *)0) == 0) D_loginslot = 0; } UT_CLOSE; } debug1(" slot %d zapped\n", (int)D_loginslot); if (D_loginslot == (slot_t)0) { /* couldn't remove slot, do a 'mesg n' at least. */ struct stat stb; char *tty; debug("couln't zap slot -> do mesg n\n"); D_loginttymode = 0; if ((tty = ttyname(D_userfd)) && stat(tty, &stb) == 0 && (int)stb.st_uid == real_uid && ((int)stb.st_mode & 0777) != 0666) { D_loginttymode = (int)stb.st_mode & 0777; chmod(D_usertty, stb.st_mode & 0600); } } } /* * D_utmp_logintty is reinserted into utmp */ void RestoreLoginSlot() { char *tty; debug("RestoreLoginSlot()\n"); ASSERT(display); if (utmpok && D_loginslot != (slot_t)0 && D_loginslot != (slot_t)-1) { debug1(" logging you in again (slot %#x)\n", (int)D_loginslot); if (pututslot(D_loginslot, &D_utmp_logintty, D_loginhost, (struct win *)0) == 0) Msg(errno,"Could not write %s", UtmpName); } UT_CLOSE; D_loginslot = (slot_t)0; if (D_loginttymode && (tty = ttyname(D_userfd))) chmod(tty, D_loginttymode); } /* * Construct a utmp entry for window wi. * the hostname field reflects what we know about the user (display) * location. If d_loginhost is not set, then he is local and we write * down the name of his terminal line; else he is remote and we keep * the hostname here. The letter S and the window id will be appended. * A saved utmp entry in wi->w_savut serves as a template, usually. */ int SetUtmp(wi) struct win *wi; { register slot_t slot; struct utmp u; int saved_ut; #ifdef UTHOST char *p; char host[sizeof(D_loginhost) + 15]; #else char *host = 0; #endif /* UTHOST */ wi->w_slot = (slot_t)0; if (!utmpok || wi->w_type != W_TYPE_PTY) return -1; if ((slot = TtyNameSlot(wi->w_tty)) == (slot_t)0) { debug1("SetUtmp failed (tty %s).\n",wi->w_tty); return -1; } debug2("SetUtmp %d will get slot %d...\n", wi->w_number, (int)slot); bzero((char *)&u, sizeof(u)); if ((saved_ut = bcmp((char *) &wi->w_savut, (char *)&u, sizeof(u)))) /* restore original, of which we will adopt all fields but ut_host */ bcopy((char *)&wi->w_savut, (char *) &u, sizeof(u)); if (!saved_ut) makeuser(&u, stripdev(wi->w_tty), LoginName, wi->w_pid); #ifdef UTHOST host[sizeof(host) - 15] = '\0'; if (display) { strncpy(host, D_loginhost, sizeof(host) - 15); if (D_loginslot != (slot_t)0 && D_loginslot != (slot_t)-1 && host[0] != '\0') { /* * we want to set our ut_host field to something like * ":ttyhf:s.0" or * "faui45:s.0" or * "132.199.81.4:s.0" (even this may hurt..), but not * "faui45.informati"......:s.0 * HPUX uses host:0.0, so chop at "." and ":" (Eric Backus) */ for (p = host; *p; p++) if ((*p < '0' || *p > '9') && (*p != '.')) break; if (*p) { for (p = host; *p; p++) if (*p == '.' || (*p == ':' && p != host)) { *p = '\0'; break; } } } else { strncpy(host + 1, stripdev(D_usertty), sizeof(host) - 15 - 1); host[0] = ':'; } } else strncpy(host, "local", sizeof(host) - 15); sprintf(host + strlen(host), ":S.%d", wi->w_number); debug1("rlogin hostname: '%s'\n", host); # if !defined(_SEQUENT_) && !defined(sequent) strncpy(u.ut_host, host, sizeof(u.ut_host)); # endif #endif /* UTHOST */ if (pututslot(slot, &u, host, wi) == 0) { Msg(errno,"Could not write %s", UtmpName); UT_CLOSE; return -1; } debug("SetUtmp successful\n"); wi->w_slot = slot; bcopy((char *)&u, (char *)&wi->w_savut, sizeof(u)); UT_CLOSE; return 0; } /* * if slot could be removed or was 0, wi->w_slot = -1; * else not changed. */ int RemoveUtmp(wi) struct win *wi; { struct utmp u, *uu; slot_t slot; slot = wi->w_slot; debug1("RemoveUtmp slot=%#x\n", slot); if (!utmpok) return -1; if (slot == (slot_t)0 || slot == (slot_t)-1) { wi->w_slot = (slot_t)-1; return 0; } bzero((char *) &u, sizeof(u)); #ifdef sgi bcopy((char *)&wi->w_savut, (char *)&u, sizeof(u)); uu = &u; #else if ((uu = getutslot(slot)) == 0) { Msg(0, "Utmp slot not found -> not removed"); return -1; } bcopy((char *)uu, (char *)&wi->w_savut, sizeof(wi->w_savut)); #endif u = *uu; makedead(&u); if (pututslot(slot, &u, (char *)0, wi) == 0) { Msg(errno,"Could not write %s", UtmpName); UT_CLOSE; return -1; } debug("RemoveUtmp successfull\n"); wi->w_slot = (slot_t)-1; UT_CLOSE; return 0; } /********************************************************************* * * routines using the getut* api */ #ifdef GETUTENT #define SLOT_USED(u) (u->ut_type == USER_PROCESS) static struct utmp * getutslot(slot) slot_t slot; { struct utmp u; bzero((char *)&u, sizeof(u)); strncpy(u.ut_line, slot, sizeof(u.ut_line)); setutent(); return getutline(&u); } static int pututslot(slot, u, host, wi) slot_t slot; struct utmp *u; char *host; struct win *wi; { #ifdef _SEQUENT_ if (SLOT_USED(u) && host && *host) return ut_add_user(u.ut_name, slot, u.ut_pid, host) != 0; if (!SLOT_USED(u)) return ut_delete_user(slot, u.ut_pid, 0, 0) != 0; #endif #ifdef HAVE_UTEMPTER if (eff_uid && wi->w_ptyfd != -1) { /* sigh, linux hackers made the helper functions void */ if (SLOT_USED(u)) addToUtmp(wi->w_tty, host, wi->w_ptyfd); else removeLineFromUtmp(wi->w_tty, wi->w_ptyfd); return 1; /* pray for success */ } #endif setutent(); #ifndef __CYGWIN__ return pututline(u) != 0; #else return 1; #endif } static void makedead(u) struct utmp *u; { u->ut_type = DEAD_PROCESS; #if (!defined(linux) || defined(EMPTY)) && !defined(__CYGWIN__) u->ut_exit.e_termination = 0; u->ut_exit.e_exit = 0; #endif #if !defined(sun) || !defined(SVR4) u->ut_user[0] = 0; /* for Digital UNIX, kilbi@rad.rwth-aachen.de */ #endif } static void makeuser(u, line, user, pid) struct utmp *u; char *line, *user; int pid; { time_t now; u->ut_type = USER_PROCESS; strncpy(u->ut_user, user, sizeof(u->ut_user)); /* Now the tricky part... guess ut_id */ #if defined(sgi) || defined(linux) strncpy(u->ut_id, line + 3, sizeof(u->ut_id)); #else /* sgi */ # ifdef _IBMR2 strncpy(u->ut_id, line, sizeof(u->ut_id)); # else strncpy(u->ut_id, line + strlen(line) - 2, sizeof(u->ut_id)); # endif #endif /* sgi */ strncpy(u->ut_line, line, sizeof(u->ut_line)); u->ut_pid = pid; /* must use temp variable because of NetBSD/sparc64, where * ut_xtime is long(64) but time_t is int(32) */ (void)time(&now); u->ut_time = now; } static slot_t TtyNameSlot(nam) char *nam; { return stripdev(nam); } #else /* GETUTENT */ /********************************************************************* * * getut emulation for systems lacking the api */ static struct utmp uent; #define SLOT_USED(u) (u.ut_name[0] != 0) static int initutmp() { if (utmpfd >= 0) return 1; return (utmpfd = open(UtmpName, O_RDWR)) >= 0; } static void setutent() { if (utmpfd >= 0) (void)lseek(utmpfd, (off_t)0, 0); } static void endutent() { if (utmpfd >= 0) close(utmpfd); utmpfd = -1; } static struct utmp * getutent() { if (utmpfd < 0 && !initutmp()) return 0; if (read(utmpfd, &uent, sizeof(uent)) != sizeof(uent)) return 0; return &uent; } static struct utmp * getutslot(slot) slot_t slot; { if (utmpfd < 0 && !initutmp()) return 0; lseek(utmpfd, (off_t)(slot * sizeof(struct utmp)), 0); if (read(utmpfd, &uent, sizeof(uent)) != sizeof(uent)) return 0; return &uent; } static int pututslot(slot, u, host, wi) slot_t slot; struct utmp *u; char *host; struct win *wi; { #ifdef sequent if (SLOT_USED(u)) return add_utmp(slot, u) != -1; #endif if (utmpfd < 0 && !initutmp()) return 0; lseek(utmpfd, (off_t)(slot * sizeof(*u)), 0); if (write(utmpfd, u, sizeof(*u)) != sizeof(*u)) return 0; return 1; } static void makedead(u) struct utmp *u; { #ifdef UT_UNSORTED bzero(u->ut_name, sizeof(u->ut_name)); # ifdef UTHOST bzero(u->ut_host, sizeof(u->ut_host)); # endif #else bzero((char *)u, sizeof(*u)); #endif } static void makeuser(u, line, user, pid) struct utmp *u; char *line, *user; int pid; { time_t now; strncpy(u->ut_line, line, sizeof(u->ut_line)); strncpy(u->ut_name, user, sizeof(u->ut_name)); (void)time(&now); u->ut_time = now; } static slot_t TtyNameSlot(nam) char *nam; { slot_t slot; char *line; #ifndef UT_UNSORTED struct ttyent *tp; #endif line = stripdev(nam); #ifdef UT_UNSORTED setutent(); if (utmpfd < 0) return -1; for (slot = 0; getutent(); slot++) if (strcmp(uent.ut_line, line) == 0) break; UT_CLOSE; #else slot = 1; setttyent(); while ((tp = getttyent()) != 0 && strcmp(line, tp->ty_name) != 0) slot++; #endif return slot; } #endif /* GETUTENT */ /********************************************************************* * * Cheap plastic imitation of ttyent routines. */ #if !defined(GETTTYENT) && !defined(GETUTENT) && !defined(UT_UNSORTED) static char *tt, *ttnext; static char ttys[] = "/etc/ttys"; static void setttyent() { if (ttnext == 0) { struct stat s; register int f; register char *p, *ep; if ((f = open(ttys, O_RDONLY)) == -1 || fstat(f, &s) == -1) Panic(errno, ttys); if ((tt = malloc((unsigned) s.st_size + 1)) == 0) Panic(0, strnomem); if (read(f, tt, s.st_size) != s.st_size) Panic(errno, ttys); close(f); for (p = tt, ep = p + s.st_size; p < ep; p++) if (*p == '\n') *p = '\0'; *p = '\0'; } ttnext = tt; } static struct ttyent * getttyent() { static struct ttyent t; if (*ttnext == '\0') return NULL; t.ty_name = ttnext + 2; ttnext += strlen(ttnext) + 1; return &t; } #endif /* !GETTTYENT && !GETUTENT && !UT_UNSORTED*/ #endif /* UTMPOK */ /********************************************************************* * * getlogin() replacement (for SVR4 machines) */ # if defined(BUGGYGETLOGIN) && defined(UTMP_FILE) char * getlogin() { char *tty = NULL; #ifdef utmp # undef utmp #endif struct utmp u; static char retbuf[sizeof(u.ut_user)+1]; int fd; for (fd = 0; fd <= 2 && (tty = ttyname(fd)) == NULL; fd++) ; if ((tty == NULL) || ((fd = open(UTMP_FILE, O_RDONLY)) < 0)) return NULL; tty = stripdev(tty); retbuf[0] = '\0'; while (read(fd, (char *)&u, sizeof(struct utmp)) == sizeof(struct utmp)) { if (!strncmp(tty, u.ut_line, sizeof(u.ut_line))) { strncpy(retbuf, u.ut_user, sizeof(u.ut_user)); retbuf[sizeof(u.ut_user)] = '\0'; if (u.ut_type == USER_PROCESS) break; } } close(fd); return *retbuf ? retbuf : NULL; } # endif /* BUGGYGETLOGIN */ #if defined(linux) && defined(GETUTENT) # undef pututline /* aargh, linux' pututline returns void! */ struct utmp * xpututline(u) struct utmp *u; { struct utmp *u2; pututline(u); setutent(); u2 = getutline(u); if (u2 == 0) return u->ut_type == DEAD_PROCESS ? u : 0; return u->ut_type == u2->ut_type ? u : 0; } #endif screen-4.1.0/nethack.c0000644000175000017500000001122611642704565012630 0ustar abeabe/* Copyright (c) 2008, 2009 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Micah Cowan (micah@cowan.name) * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net) * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Copyright (c) 1987 Oliver Laumann * * 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, 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 (see the file COPYING); if not, see * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA * **************************************************************** */ #include "config.h" #include "screen.h" #ifdef NETHACK extern int nethackflag; #endif struct nlstrans { char *from; char *to; }; #ifdef NETHACK static struct nlstrans nethacktrans[] = { {"Cannot lock terminal - fork failed", "Cannot fork terminal - lock failed"}, {"Got only %d bytes from %s", "You choke on your food: %d bytes from %s"}, {"Copy mode - Column %d Line %d(+%d) (%d,%d)", "Welcome to hacker's treasure zoo - Column %d Line %d(+%d) (%d,%d)"}, {"First mark set - Column %d Line %d", "You drop a magic marker - Column %d Line %d"}, {"Copy mode aborted", "You escaped the dungeon."}, {"Filter removed.", "You have a sad feeling for a moment..."}, {"Window %d (%s) killed.", "You destroy poor window %d (%s)."}, {"Window %d (%s) is now being monitored for all activity.", "You feel like someone is watching you..."}, {"Window %d (%s) is no longer being monitored for activity.", "You no longer sense the watcher's presence."}, {"empty buffer", "Nothing happens."}, {"switched to audible bell.", "Suddenly you can't see your bell!"}, {"switched to visual bell.", "Your bell is no longer invisible."}, {"The window is now being monitored for %d sec. silence.", "You feel like someone is waiting for %d sec. silence..."}, {"The window is no longer being monitored for silence.", "You no longer sense the watcher's silence."}, {"No other window.", "You cannot escape from window %d!"}, {"Logfile \"%s\" closed.", "You put away your scroll of logging named \"%s\"." }, {"Error opening logfile \"%s\"", "You don't seem to have a scroll of logging named \"%s\"."}, {"Creating logfile \"%s\".", "You start writing on your scroll of logging named \"%s\"."}, {"Appending to logfile \"%s\".", "You add to your scroll of logging named \"%s\"."}, {"Detach aborted.", "The blast of disintegration whizzes by you!"}, {"Empty register.", "Nothing happens."}, {"[ Passwords don't match - checking turned off ]", "[ Passwords don't match - your armor crumbles away ]"}, {"Aborted because of window size change.", "KAABLAMM!!! You triggered a land mine!"}, {"Out of memory.", "Who was that Maude person anyway?"}, {"getpwuid() can't identify your account!", "An alarm sounds through the dungeon...\nThe Keystone Kops are after you!"}, {"Must be connected to a terminal.", "You must play from a terminal."}, {"No Sockets found in %s.\n", "This room is empty (%s).\n"}, {"New screen...", "Be careful! New screen tonight."}, {"Child has been stopped, restarting.", "You regain consciousness."}, {"There are screens on:", "Your inventory:"}, {"There is a screen on:", "Your inventory:"}, {"There are several screens on:", "Prove thyself worthy or perish:"}, {"There is a suitable screen on:", "You see here a good looking screen:"}, {"There are several suitable screens on:", "You may wish for a screen, what do you want?"}, {"%d socket%s wiped out.", "You hear %d distant explosion%s."}, {"Remove dead screens with 'screen -wipe'.", "The dead screen%s touch%s you. Try 'screen -wipe'."}, {"Illegal reattach attempt from terminal %s.", "'%s' tries to touch your session, but fails."}, {"Could not write %s", "%s is too hard to dig in"}, {0, 0} }; #endif const char * DoNLS(from) const char *from; { #ifdef NETHACK struct nlstrans *t; if (nethackflag) { for (t = nethacktrans; t->from; t++) if (strcmp(from, t->from) == 0) return t->to; } #endif return from; } screen-4.1.0/termcap.c0000644000175000017500000007521211642704565012653 0ustar abeabe/* Copyright (c) 2008, 2009 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Micah Cowan (micah@cowan.name) * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net) * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Copyright (c) 1987 Oliver Laumann * * 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, 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 (see the file COPYING); if not, see * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA * **************************************************************** */ #include #include "config.h" #include "screen.h" #include "extern.h" extern struct display *display, *displays; extern int real_uid, real_gid, eff_uid, eff_gid; extern struct term term[]; /* terminal capabilities */ extern struct NewWindow nwin_undef, nwin_default, nwin_options; extern int force_vt; extern int Z0width, Z1width; extern int hardstatusemu; #ifdef MAPKEYS extern struct action umtab[]; extern struct action mmtab[]; extern struct action dmtab[]; extern struct action ktab[]; extern struct kmap_ext *kmap_exts; extern int kmap_extn; extern int DefaultEsc; #endif static void AddCap __P((char *)); static void MakeString __P((char *, char *, int, char *)); static char *findcap __P((char *, char **, int)); static int copyarg __P((char **, char *)); static int e_tgetent __P((char *, char *)); static char *e_tgetstr __P((char *, char **)); static int e_tgetflag __P((char *)); static int e_tgetnum __P((char *)); #ifdef MAPKEYS static int findseq_ge __P((char *, int, unsigned char **)); static void setseqoff __P((unsigned char *, int, int)); static int addmapseq __P((char *, int, int)); static int remmapseq __P((char *, int)); #ifdef DEBUGG static void dumpmap __P((void)); #endif #endif char Termcap[TERMCAP_BUFSIZE + 8]; /* new termcap +8:"TERMCAP=" */ static int Termcaplen; static int tcLineLen; char Term[MAXSTR+5]; /* +5: "TERM=" */ char screenterm[20]; /* new $TERM, usually "screen" */ char *extra_incap, *extra_outcap; static const char TermcapConst[] = "\\\n\ \t:DO=\\E[%dB:LE=\\E[%dD:RI=\\E[%dC:UP=\\E[%dA:bs:bt=\\E[Z:\\\n\ \t:cd=\\E[J:ce=\\E[K:cl=\\E[H\\E[J:cm=\\E[%i%d;%dH:ct=\\E[3g:\\\n\ \t:do=^J:nd=\\E[C:pt:rc=\\E8:rs=\\Ec:sc=\\E7:st=\\EH:up=\\EM:\\\n\ \t:le=^H:bl=^G:cr=^M:it#8:ho=\\E[H:nw=\\EE:ta=^I:is=\\E)0:"; char * gettermcapstring(s) char *s; { int i; if (display == 0 || s == 0) return 0; for (i = 0; i < T_N; i++) { if (term[i].type != T_STR) continue; if (strcmp(term[i].tcname, s) == 0) return D_tcs[i].str; } return 0; } /* * Compile the terminal capabilities for a display. * Input: tgetent(, D_termname) extra_incap, extra_outcap. * Effect: display initialisation. */ int InitTermcap(wi, he) int wi; int he; { register char *s; int i; char tbuf[TERMCAP_BUFSIZE], *tp; int t, xue, xse, xme; ASSERT(display); bzero(tbuf, sizeof(tbuf)); debug1("InitTermcap: looking for tgetent('%s')\n", D_termname); if (*D_termname == 0 || e_tgetent(tbuf, D_termname) != 1) { #ifdef TERMINFO Msg(0, "Cannot find terminfo entry for '%s'.", D_termname); #else Msg(0, "Cannot find termcap entry for '%s'.", D_termname); #endif return -1; } debug1("got it:\n%s\n", tbuf); #ifdef DEBUG if (extra_incap) debug1("Extra incap: %s\n", extra_incap); if (extra_outcap) debug1("Extra outcap: %s\n", extra_outcap); #endif if ((D_tentry = (char *)malloc(TERMCAP_BUFSIZE + (extra_incap ? strlen(extra_incap) + 1 : 0))) == 0) { Msg(0, "%s", strnomem); return -1; } /* * loop through all needed capabilities, record their values in the display */ tp = D_tentry; for (i = 0; i < T_N; i++) { switch(term[i].type) { case T_FLG: D_tcs[i].flg = e_tgetflag(term[i].tcname); break; case T_NUM: D_tcs[i].num = e_tgetnum(term[i].tcname); break; case T_STR: D_tcs[i].str = e_tgetstr(term[i].tcname, &tp); /* no empty strings, please */ if (D_tcs[i].str && *D_tcs[i].str == 0) D_tcs[i].str = 0; break; default: Panic(0, "Illegal tc type in entry #%d", i); /*NOTREACHED*/ } } /* * Now a good deal of sanity checks on the retrieved capabilities. */ if (D_HC) { Msg(0, "You can't run screen on a hardcopy terminal."); return -1; } if (D_OS) { Msg(0, "You can't run screen on a terminal that overstrikes."); return -1; } if (!D_CL) { Msg(0, "Clear screen capability required."); return -1; } if (!D_CM) { Msg(0, "Addressable cursor capability required."); return -1; } if ((s = getenv("COLUMNS")) && (i = atoi(s)) > 0) D_CO = i; if ((s = getenv("LINES")) && (i = atoi(s)) > 0) D_LI = i; if (wi) D_CO = wi; if (he) D_LI = he; if (D_CO <= 0) D_CO = 80; if (D_LI <= 0) D_LI = 24; if (D_CTF) { /* standard fixes for xterms etc */ /* assume color for everything that looks ansi-compatible */ if (!D_CAF && D_ME && (InStr(D_ME, "\033[m") || InStr(D_ME, "\033[0m"))) { #ifdef TERMINFO D_CAF = "\033[3%p1%dm"; D_CAB = "\033[4%p1%dm"; #else D_CAF = "\033[3%dm"; D_CAB = "\033[4%dm"; #endif } if (D_OP && InStr(D_OP, "\033[39;49m")) D_CAX = 1; if (D_OP && (InStr(D_OP, "\033[m") || InStr(D_OP, "\033[0m"))) D_OP = 0; /* ISO2022 */ if ((D_EA && InStr(D_EA, "\033(B")) || (D_AS && InStr(D_AS, "\033(0"))) D_CG0 = 1; if (InStr(D_termname, "xterm") || InStr(D_termname, "rxvt") || (D_CKM && InStr(D_CKM, "\033[M"))) D_CXT = 1; /* "be" seems to be standard for xterms... */ if (D_CXT) D_BE = 1; } if (nwin_options.flowflag == nwin_undef.flowflag) nwin_default.flowflag = D_CNF ? FLOW_NOW * 0 : D_NX ? FLOW_NOW * 1 : FLOW_AUTOFLAG; D_CLP |= (!D_AM || D_XV || D_XN); if (!D_BL) D_BL = "\007"; if (!D_BC) { if (D_BS) D_BC = "\b"; else D_BC = D_LE; } if (!D_CR) D_CR = "\r"; if (!D_NL) D_NL = "\n"; /* * Set up attribute handling. * This is rather complicated because termcap has different * attribute groups. */ if (D_UG > 0) D_US = D_UE = 0; if (D_SG > 0) D_SO = D_SE = 0; /* Unfortunately there is no 'mg' capability. * For now we think that mg > 0 if sg and ug > 0. */ if (D_UG > 0 && D_SG > 0) D_MH = D_MD = D_MR = D_MB = D_ME = 0; xue = ATYP_U; xse = ATYP_S; xme = ATYP_M; if (D_SO && D_SE == 0) { Msg(0, "Warning: 'so' but no 'se' capability."); if (D_ME) xse = xme; else D_SO = 0; } if (D_US && D_UE == 0) { Msg(0, "Warning: 'us' but no 'ue' capability."); if (D_ME) xue = xme; else D_US = 0; } if ((D_MH || D_MD || D_MR || D_MB) && D_ME == 0) { Msg(0, "Warning: 'm?' but no 'me' capability."); D_MH = D_MD = D_MR = D_MB = 0; } /* * Does ME also reverse the effect of SO and/or US? This is not * clearly specified by the termcap manual. Anyway, we should at * least look whether ME and SE/UE are equal: */ if (D_UE && D_SE && strcmp(D_SE, D_UE) == 0) xse = xue; if (D_SE && D_ME && strcmp(D_ME, D_SE) == 0) xse = xme; if (D_UE && D_ME && strcmp(D_ME, D_UE) == 0) xue = xme; for (i = 0; i < NATTR; i++) { D_attrtab[i] = D_tcs[T_ATTR + i].str; D_attrtyp[i] = i == ATTR_SO ? xse : (i == ATTR_US ? xue : xme); } /* Set up missing entries (attributes are priority ordered) */ s = 0; t = 0; for (i = 0; i < NATTR; i++) if ((s = D_attrtab[i])) { t = D_attrtyp[i]; break; } for (i = 0; i < NATTR; i++) { if (D_attrtab[i] == 0) { D_attrtab[i] = s; D_attrtyp[i] = t; } else { s = D_attrtab[i]; t = D_attrtyp[i]; } } if (D_CAF || D_CAB || D_CSF || D_CSB) D_hascolor = 1; if (D_UT) D_BE = 1; /* screen erased with background color */ if (!D_DO) D_DO = D_NL; if (!D_SF) D_SF = D_NL; if (D_IN) D_IC = D_IM = 0; if (D_EI == 0) D_IM = 0; /* some strange termcap entries have IC == IM */ if (D_IC && D_IM && strcmp(D_IC, D_IM) == 0) D_IC = 0; if (D_KE == 0) D_KS = 0; if (D_CVN == 0) D_CVR = 0; if (D_VE == 0) D_VI = D_VS = 0; if (D_CCE == 0) D_CCS = 0; #ifdef FONT if (D_CG0) { if (D_CS0 == 0) #ifdef TERMINFO D_CS0 = "\033(%p1%c"; #else D_CS0 = "\033(%."; #endif if (D_CE0 == 0) D_CE0 = "\033(B"; D_AC = 0; D_EA = 0; } else if (D_AC || (D_AS && D_AE)) /* some kind of graphics */ { D_CS0 = (D_AS && D_AE) ? D_AS : ""; D_CE0 = (D_AS && D_AE) ? D_AE : ""; D_CC0 = D_AC; } else { D_CS0 = D_CE0 = ""; D_CC0 = 0; D_AC = ""; /* enable default string */ } for (i = 0; i < 256; i++) D_c0_tab[i] = i; if (D_AC) { /* init with default string first */ s = "l+m+k+j+u+t+v+w+q-x|n+o~s_p\"r#`+a:f'g#~o.v-^+<,>h#I#0#y"; for (i = strlen(s) & ~1; i >= 0; i -= 2) D_c0_tab[(int)(unsigned char)s[i]] = s[i + 1]; } if (D_CC0) for (i = strlen(D_CC0) & ~1; i >= 0; i -= 2) D_c0_tab[(int)(unsigned char)D_CC0[i]] = D_CC0[i + 1]; debug1("ISO2022 = %d\n", D_CG0); #endif /* FONT */ if (D_PF == 0) D_PO = 0; debug2("terminal size is %d, %d (says TERMCAP)\n", D_CO, D_LI); #ifdef FONT if (D_CXC) if (CreateTransTable(D_CXC)) return -1; #endif /* Termcap fields Z0 & Z1 contain width-changing sequences. */ if (D_CZ1 == 0) D_CZ0 = 0; Z0width = 132; Z1width = 80; CheckScreenSize(0); if (D_TS == 0 || D_FS == 0 || D_DS == 0) D_HS = 0; if (D_HS) { debug("oy! we have a hardware status line, says termcap\n"); if (D_WS < 0) D_WS = 0; } D_has_hstatus = hardstatusemu & ~HSTATUS_ALWAYS; if (D_HS && !(hardstatusemu & HSTATUS_ALWAYS)) D_has_hstatus = HSTATUS_HS; #ifdef ENCODINGS if (D_CKJ) { int enc = FindEncoding(D_CKJ); if (enc != -1) D_encoding = enc; } #endif if (!D_tcs[T_NAVIGATE].str && D_tcs[T_NAVIGATE + 1].str) D_tcs[T_NAVIGATE].str = D_tcs[T_NAVIGATE + 1].str; /* kh = @1 */ if (!D_tcs[T_NAVIGATE + 2].str && D_tcs[T_NAVIGATE + 3].str) D_tcs[T_NAVIGATE + 2].str = D_tcs[T_NAVIGATE + 3].str; /* kH = @7 */ D_UPcost = CalcCost(D_UP); D_DOcost = CalcCost(D_DO); D_NLcost = CalcCost(D_NL); D_LEcost = CalcCost(D_BC); D_NDcost = CalcCost(D_ND); D_CRcost = CalcCost(D_CR); D_IMcost = CalcCost(D_IM); D_EIcost = CalcCost(D_EI); #ifdef AUTO_NUKE if (D_CAN) { debug("termcap has AN, setting autonuke\n"); D_auto_nuke = 1; } #endif if (D_COL > 0) { debug1("termcap has OL (%d), setting limit\n", D_COL); D_obufmax = D_COL; D_obuflenmax = D_obuflen - D_obufmax; } /* Some xterm entries set F0 and F10 to the same string. Nuke F0. */ if (D_tcs[T_CAPS].str && D_tcs[T_CAPS + 10].str && !strcmp(D_tcs[T_CAPS].str, D_tcs[T_CAPS + 10].str)) D_tcs[T_CAPS].str = 0; /* Some xterm entries set kD to ^?. Nuke it. */ if (D_tcs[T_NAVIGATE_DELETE].str && !strcmp(D_tcs[T_NAVIGATE_DELETE].str, "\0177")) D_tcs[T_NAVIGATE_DELETE].str = 0; /* wyse52 entries have kcub1 == kb == ^H. Nuke... */ if (D_tcs[T_CURSOR + 3].str && !strcmp(D_tcs[T_CURSOR + 3].str, "\008")) D_tcs[T_CURSOR + 3].str = 0; #ifdef MAPKEYS D_nseqs = 0; for (i = 0; i < T_OCAPS - T_CAPS; i++) remap(i, 1); for (i = 0; i < kmap_extn; i++) remap(i + (KMAP_KEYS+KMAP_AKEYS), 1); D_seqp = D_kmaps + 3; D_seql = 0; D_seqh = 0; #endif D_tcinited = 1; MakeTermcap(0); #ifdef MAPKEYS CheckEscape(); #endif return 0; } #ifdef MAPKEYS int remap(n, map) int n; int map; { char *s = 0; int fl = 0, domap = 0; struct action *a1, *a2, *tab; int l = 0; struct kmap_ext *kme = 0; a1 = 0; if (n >= KMAP_KEYS+KMAP_AKEYS) { kme = kmap_exts + (n - (KMAP_KEYS+KMAP_AKEYS)); s = kme->str; l = kme->fl & ~KMAP_NOTIMEOUT; fl = kme->fl & KMAP_NOTIMEOUT; a1 = &kme->um; } tab = umtab; for (;;) { a2 = 0; if (n < KMAP_KEYS+KMAP_AKEYS) { a1 = &tab[n]; if (n >= KMAP_KEYS) n -= T_OCAPS-T_CURSOR; s = D_tcs[n + T_CAPS].str; l = s ? strlen(s) : 0; if (n >= T_CURSOR-T_CAPS) a2 = &tab[n + (T_OCAPS-T_CURSOR)]; } if (s == 0 || l == 0) return 0; if (a1 && a1->nr == RC_ILLEGAL) a1 = 0; if (a2 && a2->nr == RC_ILLEGAL) a2 = 0; if (a1 && a1->nr == RC_STUFF && a1->args[0] && strcmp(a1->args[0], s) == 0) a1 = 0; if (a2 && a2->nr == RC_STUFF && a2->args[0] && strcmp(a2->args[0], s) == 0) a2 = 0; domap |= (a1 || a2); if (tab == umtab) { tab = dmtab; a1 = kme ? &kme->dm : 0; } else if (tab == dmtab) { tab = mmtab; a1 = kme ? &kme->mm : 0; } else break; } if (n < KMAP_KEYS) domap = 1; if (map == 0 && domap) return 0; if (map && !domap) return 0; debug3("%smapping %s %#x\n", map? "" :"un",s,n); if (map) return addmapseq(s, l, n | fl); else return remmapseq(s, l); } void CheckEscape() { struct display *odisplay; int i, nr; if (DefaultEsc >= 0) return; odisplay = display; for (display = displays; display; display = display->d_next) { for (i = 0; i < D_nseqs; i += D_kmaps[i + 2] * 2 + 4) { nr = (D_kmaps[i] << 8 | D_kmaps[i + 1]) & ~KMAP_NOTIMEOUT; if (nr < KMAP_KEYS+KMAP_AKEYS) { if (umtab[nr].nr == RC_COMMAND) break; if (umtab[nr].nr == RC_ILLEGAL && dmtab[nr].nr == RC_COMMAND) break; } else { struct kmap_ext *kme = kmap_exts + nr - (KMAP_KEYS+KMAP_AKEYS); if (kme->um.nr == RC_COMMAND) break; if (kme->um.nr == RC_ILLEGAL && kme->dm.nr == RC_COMMAND) break; } } } if (display == 0) { display = odisplay; return; } SetEscape((struct acluser *)0, Ctrl('a'), 'a'); if (odisplay->d_user->u_Esc == -1) odisplay->d_user->u_Esc = DefaultEsc; if (odisplay->d_user->u_MetaEsc == -1) odisplay->d_user->u_MetaEsc = DefaultMetaEsc; display = 0; Msg(0, "Warning: escape char set back to ^A"); display = odisplay; } static int findseq_ge(seq, k, sp) char *seq; int k; unsigned char **sp; { unsigned char *p; int j, l; p = D_kmaps; while (p - D_kmaps < D_nseqs) { l = p[2]; p += 3; for (j = 0; ; j++) { if (j == k || j == l) j = l - k; else if (p[j] != ((unsigned char *)seq)[j]) j = p[j] - ((unsigned char *)seq)[j]; else continue; break; } if (j >= 0) { *sp = p - 3; return j; } p += 2 * l + 1; } *sp = p; return -1; } static void setseqoff(p, i, o) unsigned char *p; int i; int o; { unsigned char *q; int l, k; k = p[2]; if (o < 256) { p[k + 4 + i] = o; return; } /* go for the biggest offset */ for (q = p + k * 2 + 4; ; q += l * 2 + 4) { l = q[2]; if ((q + l * 2 - p) / 2 >= 256) { p[k + 4 + i] = (q - p - 4) / 2; return; } } } static int addmapseq(seq, k, nr) char *seq; int k; int nr; { int i, j, l, mo, m; unsigned char *p, *q; if (k >= 254) return -1; j = findseq_ge(seq, k, &p); if (j == 0) { p[0] = nr >> 8; p[1] = nr; return 0; } i = p - D_kmaps; if (D_nseqs + 2 * k + 4 >= D_aseqs) { D_kmaps = (unsigned char *)xrealloc((char *)D_kmaps, D_aseqs + 256); D_aseqs += 256; p = D_kmaps + i; } D_seqp = D_kmaps + 3; D_seql = 0; D_seqh = 0; evdeq(&D_mapev); if (j > 0) bcopy((char *)p, (char *)p + 2 * k + 4, D_nseqs - i); p[0] = nr >> 8; p[1] = nr; p[2] = k; bcopy(seq, (char *)p + 3, k); bzero(p + k + 3, k + 1); D_nseqs += 2 * k + 4; if (j > 0) { q = p + 2 * k + 4; l = q[2]; for (i = 0; i < k; i++) { if (p[3 + i] != q[3 + i]) { p[k + 4 + i] = k; break; } setseqoff(p, i, q[l + 4 + i] ? q[l + 4 + i] + k + 2: 0); } } for (q = D_kmaps; q < p; q += 2 * l + 4) { l = q[2]; for (m = j = 0; j < l; j++) { mo = m; if (!m && q[3 + j] != seq[j]) m = 1; if (q[l + 4 + j] == 0) { if (!mo && m) setseqoff(q, j, (p - q - 4) / 2); } else if (q + q[l + 4 + j] * 2 + 4 > p || (q + q[l + 4 + j] * 2 + 4 == p && !m)) setseqoff(q, j, q[l + 4 + j] + k + 2); } } #ifdef DEBUGG dumpmap(); #endif return 0; } static int remmapseq(seq, k) char *seq; int k; { int j, l; unsigned char *p, *q; if (k >= 254 || (j = findseq_ge(seq, k, &p)) != 0) return -1; for (q = D_kmaps; q < p; q += 2 * l + 4) { l = q[2]; for (j = 0; j < l; j++) { if (q + q[l + 4 + j] * 2 + 4 == p) setseqoff(q, j, p[k + 4 + j] ? q[l + 4 + j] + p[k + 4 + j] - k : 0); else if (q + q[l + 4 + j] * 2 + 4 > p) q[l + 4 + j] -= k + 2; } } if (D_kmaps + D_nseqs > p + 2 * k + 4) bcopy((char *)p + 2 * k + 4, (char *)p, (D_kmaps + D_nseqs) - (p + 2 * k + 4)); D_nseqs -= 2 * k + 4; D_seqp = D_kmaps + 3; D_seql = 0; D_seqh = 0; evdeq(&D_mapev); #ifdef DEBUGG dumpmap(); #endif return 0; } #ifdef DEBUGG static void dumpmap() { unsigned char *p; int j, n, l, o, oo; debug("Mappings:\n"); p = D_kmaps; if (!p) return; while (p < D_kmaps + D_nseqs) { l = p[2]; debug1("%d: ", p - D_kmaps + 3); for (j = 0; j < l; j++) { o = oo = p[l + 4 + j]; if (o) o = 2 * o + 4 + (p + 3 + j - D_kmaps); if (p[j + 3] > ' ' && p[j + 3] < 0177) { debug3("%c[%d:%d] ", p[j + 3], oo, o); } else debug3("\\%03o[%d:%d] ", p[j + 3], oo, o); } n = p[0] << 8 | p[1]; debug2(" ==> %d%s\n", n & ~KMAP_NOTIMEOUT, (n & KMAP_NOTIMEOUT) ? " (no timeout)" : ""); p += 2 * l + 4; } } #endif /* DEBUGG */ #endif /* MAPKEYS */ /* * Appends to the static variable Termcap */ static void AddCap(s) char *s; { register int n; if (tcLineLen + (n = strlen(s)) > 55 && Termcaplen < TERMCAP_BUFSIZE - 4 - 1) { strcpy(Termcap + Termcaplen, "\\\n\t:"); Termcaplen += 4; tcLineLen = 0; } if (Termcaplen + n < TERMCAP_BUFSIZE - 1) { strcpy(Termcap + Termcaplen, s); Termcaplen += n; tcLineLen += n; } else Panic(0, "TERMCAP overflow - sorry."); } /* * Reads a displays capabilities and reconstructs a termcap entry in the * global buffer "Termcap". A pointer to this buffer is returned. */ char * MakeTermcap(aflag) int aflag; { char buf[TERMCAP_BUFSIZE]; register char *p, *cp, *s, ch, *tname; int i, wi, he; #if 0 int found; #endif if (display) { wi = D_width; he = D_height; tname = D_termname; } else { wi = 80; he = 24; tname = "vt100"; } debug1("MakeTermcap(%d)\n", aflag); if ((s = getenv("SCREENCAP")) && strlen(s) < TERMCAP_BUFSIZE) { sprintf(Termcap, "TERMCAP=%s", s); strcpy(Term, "TERM=screen"); debug("getenvSCREENCAP o.k.\n"); return Termcap; } Termcaplen = 0; debug1("MakeTermcap screenterm='%s'\n", screenterm); debug1("MakeTermcap termname='%s'\n", tname); if (*screenterm == '\0' || strlen(screenterm) > MAXSTR - 3) { debug("MakeTermcap sets screenterm=screen\n"); strcpy(screenterm, "screen"); } #if 0 found = 1; #endif do { strcpy(Term, "TERM="); p = Term + 5; if (!aflag && strlen(screenterm) + strlen(tname) < MAXSTR-1) { sprintf(p, "%s.%s", screenterm, tname); if (e_tgetent(buf, p) == 1) break; } #ifdef COLOR if (nwin_default.bce) { sprintf(p, "%s-bce", screenterm); if (e_tgetent(buf, p) == 1) break; } #endif #ifdef CHECK_SCREEN_W if (wi >= 132) { sprintf(p, "%s-w", screenterm); if (e_tgetent(buf, p) == 1) break; } #endif strcpy(p, screenterm); if (e_tgetent(buf, p) == 1) break; strcpy(p, "vt100"); #if 0 found = 0; #endif } while (0); /* Goto free programming... */ #if 0 #ifndef TERMINFO /* check for compatibility problems, displays == 0 after fork */ if (found) { char xbuf[TERMCAP_BUFSIZE], *xbp = xbuf; if (tgetstr("im", &xbp) && tgetstr("ic", &xbp) && displays) { Msg(0, "Warning: im and ic set in %s termcap entry", p); } } #endif #endif tcLineLen = 100; /* Force NL */ if (strlen(Term) > TERMCAP_BUFSIZE - 40) strcpy(Term, "too_long"); sprintf(Termcap, "TERMCAP=SC|%s|VT 100/ANSI X3.64 virtual terminal:", Term + 5); Termcaplen = strlen(Termcap); debug1("MakeTermcap decided '%s'\n", p); if (extra_outcap && *extra_outcap) { for (cp = extra_outcap; (p = index(cp, ':')); cp = p) { ch = *++p; *p = '\0'; AddCap(cp); *p = ch; } tcLineLen = 100; /* Force NL */ } debug1("MakeTermcap after outcap '%s'\n", (char *)TermcapConst); if (Termcaplen + strlen(TermcapConst) < TERMCAP_BUFSIZE) { strcpy(Termcap + Termcaplen, (char *)TermcapConst); Termcaplen += strlen(TermcapConst); } sprintf(buf, "li#%d:co#%d:", he, wi); AddCap(buf); AddCap("am:"); if (aflag || (force_vt && !D_COP) || D_CLP || !D_AM) { AddCap("xn:"); AddCap("xv:"); AddCap("LP:"); } if (aflag || (D_CS && D_SR) || D_AL || D_CAL) { AddCap("sr=\\EM:"); AddCap("al=\\E[L:"); AddCap("AL=\\E[%dL:"); } else if (D_SR) AddCap("sr=\\EM:"); if (aflag || D_CS) AddCap("cs=\\E[%i%d;%dr:"); if (aflag || D_CS || D_DL || D_CDL) { AddCap("dl=\\E[M:"); AddCap("DL=\\E[%dM:"); } if (aflag || D_DC || D_CDC) { AddCap("dc=\\E[P:"); AddCap("DC=\\E[%dP:"); } if (aflag || D_CIC || D_IC || D_IM) { AddCap("im=\\E[4h:"); AddCap("ei=\\E[4l:"); AddCap("mi:"); AddCap("IC=\\E[%d@:"); } #ifdef MAPKEYS AddCap("ks=\\E[?1h\\E=:"); AddCap("ke=\\E[?1l\\E>:"); #endif AddCap("vi=\\E[?25l:"); AddCap("ve=\\E[34h\\E[?25h:"); AddCap("vs=\\E[34l:"); AddCap("ti=\\E[?1049h:"); AddCap("te=\\E[?1049l:"); if (display) { if (D_US) { AddCap("us=\\E[4m:"); AddCap("ue=\\E[24m:"); } if (D_SO) { AddCap("so=\\E[3m:"); AddCap("se=\\E[23m:"); } if (D_MB) AddCap("mb=\\E[5m:"); if (D_MD) AddCap("md=\\E[1m:"); if (D_MH) AddCap("mh=\\E[2m:"); if (D_MR) AddCap("mr=\\E[7m:"); if (D_MB || D_MD || D_MH || D_MR) AddCap("me=\\E[m:ms:"); if (D_hascolor) AddCap("Co#8:pa#64:AF=\\E[3%dm:AB=\\E[4%dm:op=\\E[39;49m:AX:"); if (D_VB) AddCap("vb=\\Eg:"); #ifndef MAPKEYS if (D_KS) { AddCap("ks=\\E=:"); AddCap("ke=\\E>:"); } if (D_CCS) { AddCap("CS=\\E[?1h:"); AddCap("CE=\\E[?1l:"); } #endif if (D_CG0) AddCap("G0:"); if (D_CC0 || (D_CS0 && *D_CS0)) { AddCap("as=\\E(0:"); AddCap("ae=\\E(B:"); /* avoid `` because some shells dump core... */ AddCap("ac=\\140\\140aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~..--++,,hhII00:"); } if (D_PO) { AddCap("po=\\E[5i:"); AddCap("pf=\\E[4i:"); } if (D_CZ0) { AddCap("Z0=\\E[?3h:"); AddCap("Z1=\\E[?3l:"); } if (D_CWS) AddCap("WS=\\E[8;%d;%dt:"); } for (i = T_CAPS; i < T_ECAPS; i++) { #ifdef MAPKEYS struct action *act; if (i < T_OCAPS) { if (i >= T_KEYPAD) /* don't put keypad codes in TERMCAP */ continue; /* - makes it too big */ if (i >= T_CURSOR && i < T_OCAPS) { act = &umtab[i - (T_CURSOR - T_OCAPS + T_CAPS)]; if (act->nr == RC_ILLEGAL) act = &dmtab[i - (T_CURSOR - T_OCAPS + T_CAPS)]; } else { act = &umtab[i - T_CAPS]; if (act->nr == RC_ILLEGAL) act = &dmtab[i - T_CAPS]; } if (act->nr == RC_ILLEGAL && (i == T_NAVIGATE + 1 || i == T_NAVIGATE + 3)) { /* kh -> @1, kH -> @7 */ act = &umtab[i - T_CAPS - 1]; if (act->nr == RC_ILLEGAL) act = &dmtab[i - T_CAPS - 1]; } if (act->nr != RC_ILLEGAL) { if (act->nr == RC_STUFF) { MakeString(term[i].tcname, buf, sizeof(buf), act->args[0]); AddCap(buf); } continue; } } #endif if (display == 0) continue; switch(term[i].type) { case T_STR: if (D_tcs[i].str == 0) break; MakeString(term[i].tcname, buf, sizeof(buf), D_tcs[i].str); AddCap(buf); break; case T_FLG: if (D_tcs[i].flg == 0) break; sprintf(buf, "%s:", term[i].tcname); AddCap(buf); break; default: break; } } debug("MakeTermcap: end\n"); return Termcap; } static void MakeString(cap, buf, buflen, s) char *cap, *buf; int buflen; char *s; { register char *p, *pmax; register unsigned int c; p = buf; pmax = p + buflen - (3+4+2); *p++ = *cap++; *p++ = *cap; *p++ = '='; while ((c = *s++) && (p < pmax)) { switch (c) { case '\033': *p++ = '\\'; *p++ = 'E'; break; case ':': strcpy(p, "\\072"); p += 4; break; case '^': case '\\': *p++ = '\\'; *p++ = c; break; default: if (c >= 200) { sprintf(p, "\\%03o", c & 0377); p += 4; } else if (c < ' ') { *p++ = '^'; *p++ = c + '@'; } else *p++ = c; } } *p++ = ':'; *p = '\0'; } #undef QUOTES #define QUOTES(p) \ (*p == '\\' && (p[1] == '\\' || p[1] == ',' || p[1] == '%')) #ifdef FONT int CreateTransTable(s) char *s; { int curchar; char *templ, *arg; int templlen; int templnsub; char *p, *sx; char **ctable; int l, c; if ((D_xtable = (char ***)calloc(256, sizeof(char **))) == 0) { Msg(0, "%s", strnomem); return -1; } while (*s) { if (QUOTES(s)) s++; curchar = (unsigned char)*s++; if (curchar == 'B') curchar = 0; /* ASCII */ templ = s; templlen = 0; templnsub = 0; if (D_xtable[curchar] == 0) { if ((D_xtable[curchar] = (char **)calloc(257, sizeof(char *))) == 0) { Msg(0, "%s", strnomem); FreeTransTable(); return -1; } } ctable = D_xtable[curchar]; for(; *s && *s != ','; s++) { if (QUOTES(s)) s++; else if (*s == '%') { templnsub++; continue; } templlen++; } if (*s++ == 0) break; while (*s && *s != ',') { c = (unsigned char)*s++; if (QUOTES((s - 1))) c = (unsigned char)*s++; else if (c == '%') c = 256; if (ctable[c]) free(ctable[c]); arg = s; l = copyarg(&s, (char *)0); if (c != 256) l = l * templnsub + templlen; if ((ctable[c] = (char *)malloc(l + 1)) == 0) { Msg(0, "%s", strnomem); FreeTransTable(); return -1; } sx = ctable[c]; for (p = ((c == 256) ? "%" : templ); *p && *p != ','; p++) { if (QUOTES(p)) p++; else if (*p == '%') { s = arg; sx += copyarg(&s, sx); continue; } *sx++ = *p; } *sx = 0; ASSERT(ctable[c] + l * templnsub + templlen == sx); debug3("XC: %c %c->%s\n", curchar, c, ctable[c]); } if (*s == ',') s++; } return 0; } void FreeTransTable() { char ***p, **q; int i, j; if ((p = D_xtable) == 0) return; for (i = 0; i < 256; i++, p++) { if (*p == 0) continue; q = *p; for (j = 0; j < 257; j++, q++) if (*q) free(*q); free(*p); } free(D_xtable); } #endif /* FONT */ static int copyarg(pp, s) char **pp, *s; { int l; char *p; for (l = 0, p = *pp; *p && *p != ','; p++) { if (QUOTES(p)) p++; if (s) *s++ = *p; l++; } if (*p == ',') p++; *pp = p; return l; } /* ** ** Termcap routines that use our extra_incap ** */ static int e_tgetent(bp, name) char *bp, *name; { int r; #ifdef USE_SETEUID xseteuid(real_uid); xsetegid(real_gid); #endif r = tgetent(bp, name); #ifdef USE_SETEUID xseteuid(eff_uid); xsetegid(eff_gid); #endif return r; } /* findcap: * cap = capability we are looking for * tepp = pointer to bufferpointer * n = size of buffer (0 = infinity) */ static char * findcap(cap, tepp, n) char *cap; char **tepp; int n; { char *tep; char c, *p, *cp; int mode; /* mode: 0=LIT 1=^ 2=\x 3,4,5=\nnn */ int num = 0, capl; if (!extra_incap) return 0; tep = *tepp; capl = strlen(cap); cp = 0; mode = 0; for (p = extra_incap; *p; ) { if (strncmp(p, cap, capl) == 0) { p += capl; c = *p; if (c && c != ':' && c != '@') p++; if (c == 0 || c == '@' || c == '=' || c == ':' || c == '#') cp = tep; } while ((c = *p)) { p++; if (mode == 0) { if (c == ':') break; if (c == '^') mode = 1; if (c == '\\') mode = 2; } else if (mode == 1) { mode = 0; c = c & 0x1f; } else if (mode == 2) { mode = 0; switch(c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': mode = 3; num = 0; break; case 'E': c = 27; break; case 'n': c = '\n'; break; case 'r': c = '\r'; break; case 't': c = '\t'; break; case 'b': c = '\b'; break; case 'f': c = '\f'; break; } } if (mode > 2) { num = num * 8 + (c - '0'); if (mode++ == 5 || (*p < '0' || *p > '9')) { c = num; mode = 0; } } if (mode) continue; if (cp && n != 1) { *cp++ = c; n--; } } if (cp) { *cp++ = 0; *tepp = cp; debug2("'%s' found in extra_incap -> %s\n", cap, tep); return tep; } } return 0; } static char * e_tgetstr(cap, tepp) char *cap; char **tepp; { char *tep; if ((tep = findcap(cap, tepp, 0))) return (*tep == '@') ? 0 : tep; return tgetstr(cap, tepp); } static int e_tgetflag(cap) char *cap; { char buf[2], *bufp; char *tep; bufp = buf; if ((tep = findcap(cap, &bufp, 2))) return (*tep == '@') ? 0 : 1; return tgetflag(cap) > 0; } static int e_tgetnum(cap) char *cap; { char buf[20], *bufp; char *tep, c; int res, base = 10; bufp = buf; if ((tep = findcap(cap, &bufp, 20))) { c = *tep; if (c == '@') return -1; if (c == '0') base = 8; res = 0; while ((c = *tep++) >= '0' && c <= '9') res = res * base + (c - '0'); return res; } return tgetnum(cap); } screen-4.1.0/window.c0000644000175000017500000014637711720315605012530 0ustar abeabe/* Copyright (c) 2010 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net) * Copyright (c) 2008, 2009 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Micah Cowan (micah@cowan.name) * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net) * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Copyright (c) 1987 Oliver Laumann * * 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, 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 (see the file COPYING); if not, see * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA * **************************************************************** */ #include #include #include #include #ifndef sun # include #endif #include "config.h" #include "screen.h" #include "extern.h" #include "logfile.h" /* logfopen() */ extern struct display *displays, *display; extern struct win *windows, *fore, *console_window; extern char *ShellArgs[]; extern char *ShellProg; extern char screenterm[]; extern char *screenlogfile; extern char HostName[]; extern int TtyMode; extern int SilenceWait; extern int real_uid, real_gid, eff_uid, eff_gid; extern char Termcap[]; extern char **NewEnv; extern int visual_bell, maxwin; extern struct event logflushev; extern int log_flush, logtstamp_after; extern int ZombieKey_destroy, ZombieKey_resurrect, ZombieKey_onerror; extern struct layer *flayer; extern int maxusercount; extern int pty_preopen; #ifdef ZMODEM extern int zmodem_mode; extern struct mchar mchar_blank; extern char *zmodem_sendcmd; extern char *zmodem_recvcmd; #endif #if defined(TIOCSWINSZ) || defined(TIOCGWINSZ) extern struct winsize glwz; #endif #ifdef O_NOCTTY extern int separate_sids; #endif static void WinProcess __P((char **, int *)); static void WinRedisplayLine __P((int, int, int, int)); static void WinClearLine __P((int, int, int, int)); static int WinRewrite __P((int, int, int, struct mchar *, int)); static int WinResize __P((int, int)); static void WinRestore __P((void)); static int DoAutolf __P((char *, int *, int)); static void ZombieProcess __P((char **, int *)); static void win_readev_fn __P((struct event *, char *)); static void win_writeev_fn __P((struct event *, char *)); static int muchpending __P((struct win *, struct event *)); #ifdef COPY_PASTE static void paste_slowev_fn __P((struct event *, char *)); #endif #ifdef PSEUDOS static void pseu_readev_fn __P((struct event *, char *)); static void pseu_writeev_fn __P((struct event *, char *)); #endif static void win_silenceev_fn __P((struct event *, char *)); static void win_destroyev_fn __P((struct event *, char *)); static int OpenDevice __P((char **, int, int *, char **)); static int ForkWindow __P((struct win *, char **, char *)); #ifdef ZMODEM static void zmodem_found __P((struct win *, int, char *, int)); static void zmodem_fin __P((char *, int, char *)); static int zmodem_parse __P((struct win *, char *, int)); #endif struct win **wtab; /* window table */ int VerboseCreate = 0; /* XXX move this to user.h */ char DefaultShell[] = "/bin/sh"; #ifndef HAVE_EXECVPE static char DefaultPath[] = ":/usr/ucb:/bin:/usr/bin"; #endif /* keep this in sync with the structure definition in window.h */ struct NewWindow nwin_undef = { -1, /* StartAt */ (char *)0, /* aka */ (char **)0, /* args */ (char *)0, /* dir */ (char *)0, /* term */ -1, /* aflag */ -1, /* flowflag */ -1, /* lflag */ -1, /* histheight */ -1, /* monitor */ -1, /* wlock */ -1, /* silence */ -1, /* wrap */ -1, /* logging */ -1, /* slowpaste */ -1, /* gr */ -1, /* c1 */ -1, /* bce */ -1, /* encoding */ (char *)0, /* hstatus */ (char *)0 /* charset */ }; struct NewWindow nwin_default = { 0, /* StartAt */ 0, /* aka */ ShellArgs, /* args */ 0, /* dir */ screenterm, /* term */ 0, /* aflag */ 1*FLOW_NOW, /* flowflag */ LOGINDEFAULT, /* lflag */ DEFAULTHISTHEIGHT, /* histheight */ MON_OFF, /* monitor */ WLOCK_OFF, /* wlock */ 0, /* silence */ 1, /* wrap */ 0, /* logging */ 0, /* slowpaste */ 0, /* gr */ 1, /* c1 */ 0, /* bce */ 0, /* encoding */ (char *)0, /* hstatus */ (char *)0 /* charset */ }; struct NewWindow nwin_options; static int const_IOSIZE = IOSIZE; static int const_one = 1; void nwin_compose(def, new, res) struct NewWindow *def, *new, *res; { #define COMPOSE(x) res->x = new->x != nwin_undef.x ? new->x : def->x COMPOSE(StartAt); COMPOSE(aka); COMPOSE(args); COMPOSE(dir); COMPOSE(term); COMPOSE(aflag); COMPOSE(flowflag); COMPOSE(lflag); COMPOSE(histheight); COMPOSE(monitor); COMPOSE(wlock); COMPOSE(silence); COMPOSE(wrap); COMPOSE(Lflag); COMPOSE(slow); COMPOSE(gr); COMPOSE(c1); COMPOSE(bce); COMPOSE(encoding); COMPOSE(hstatus); COMPOSE(charset); #undef COMPOSE } /***************************************************************** * * The window layer functions */ struct LayFuncs WinLf = { WinProcess, 0, WinRedisplayLine, WinClearLine, WinRewrite, WinResize, WinRestore, 0 }; static int DoAutolf(buf, lenp, fr) char *buf; int *lenp; int fr; { char *p; int len = *lenp; int trunc = 0; for (p = buf; len > 0; p++, len--) { if (*p != '\r') continue; if (fr-- <= 0) { trunc++; len--; } if (len == 0) break; bcopy(p, p + 1, len++); p[1] = '\n'; } *lenp = p - buf; return trunc; } static void WinProcess(bufpp, lenp) char **bufpp; int *lenp; { int l2 = 0, f, *ilen, l = *lenp, trunc; char *ibuf; debug1("WinProcess: %d bytes\n", *lenp); fore = (struct win *)flayer->l_data; if (fore->w_type == W_TYPE_GROUP) { *bufpp += *lenp; *lenp = 0; return; } if (fore->w_ptyfd < 0) /* zombie? */ { ZombieProcess(bufpp, lenp); return; } #ifdef MULTIUSER /* a pending writelock is this: * fore->w_wlock == WLOCK_AUTO, fore->w_wlockuse = NULL * The user who wants to use this window next, will get the lock, if he can. */ if (display && fore->w_wlock == WLOCK_AUTO && !fore->w_wlockuser && !AclCheckPermWin(D_user, ACL_WRITE, fore)) { fore->w_wlockuser = D_user; debug2("window %d: pending writelock grabbed by user %s\n", fore->w_number, fore->w_wlockuser->u_name); } /* if w_wlock is set, only one user may write, else we check acls */ if (display && ((fore->w_wlock == WLOCK_OFF) ? AclCheckPermWin(D_user, ACL_WRITE, fore) : (D_user != fore->w_wlockuser))) { debug2("window %d, user %s: ", fore->w_number, D_user->u_name); debug2("writelock %d (wlockuser %s)\n", fore->w_wlock, fore->w_wlockuser ? fore->w_wlockuser->u_name : "NULL"); Msg(0, "write: permission denied (user %s)", D_user->u_name); *bufpp += *lenp; *lenp = 0; return; } #endif /* MULTIUSER */ #ifdef BUILTIN_TELNET if (fore->w_type == W_TYPE_TELNET && TelIsline(fore) && *bufpp != fore->w_telbuf) { TelProcessLine(bufpp, lenp); return; } #endif #ifdef PSEUDOS if (W_UWP(fore)) { /* we send the user input to our pseudowin */ ibuf = fore->w_pwin->p_inbuf; ilen = &fore->w_pwin->p_inlen; f = sizeof(fore->w_pwin->p_inbuf) - *ilen; } else #endif /* PSEUDOS */ { /* we send the user input to the window */ ibuf = fore->w_inbuf; ilen = &fore->w_inlen; f = sizeof(fore->w_inbuf) - *ilen; } if (l > f) l = f; #ifdef BUILTIN_TELNET while (l > 0) #else if (l > 0) #endif { l2 = l; bcopy(*bufpp, ibuf + *ilen, l2); if (fore->w_autolf && (trunc = DoAutolf(ibuf + *ilen, &l2, f - l2))) l -= trunc; #ifdef BUILTIN_TELNET if (fore->w_type == W_TYPE_TELNET && (trunc = DoTelnet(ibuf + *ilen, &l2, f - l2))) { l -= trunc; if (fore->w_autolf) continue; /* need exact value */ } #endif *ilen += l2; *bufpp += l; *lenp -= l; return; } } static void ZombieProcess(bufpp, lenp) char **bufpp; int *lenp; { int l = *lenp; char *buf = *bufpp, b1[10], b2[10]; debug1("ZombieProcess: %d bytes\n", *lenp); fore = (struct win *)flayer->l_data; ASSERT(fore->w_ptyfd < 0); *bufpp += *lenp; *lenp = 0; for (; l-- > 0; buf++) { if (*(unsigned char *)buf == ZombieKey_destroy) { debug1("Turning undead: %d\n", fore->w_number); KillWindow(fore); return; } if (*(unsigned char *)buf == ZombieKey_resurrect) { debug1("Resurrecting Zombie: %d\n", fore->w_number); WriteString(fore, "\r\n", 2); RemakeWindow(fore); return; } } b1[AddXChar(b1, ZombieKey_destroy)] = '\0'; b2[AddXChar(b2, ZombieKey_resurrect)] = '\0'; Msg(0, "Press %s to destroy or %s to resurrect window", b1, b2); } static void WinRedisplayLine(y, from, to, isblank) int y, from, to, isblank; { debug3("WinRedisplayLine %d %d %d\n", y, from, to); if (y < 0) return; fore = (struct win *)flayer->l_data; if (from == 0 && y > 0 && fore->w_mlines[y - 1].image[fore->w_width] == 0) LCDisplayLineWrap(&fore->w_layer, &fore->w_mlines[y], y, from, to, isblank); else LCDisplayLine(&fore->w_layer, &fore->w_mlines[y], y, from, to, isblank); } static int WinRewrite(y, x1, x2, rend, doit) int y, x1, x2, doit; struct mchar *rend; { register int cost, dx; register unsigned char *p, *i; #ifdef FONT register unsigned char *f; #endif #ifdef COLOR register unsigned char *c; # ifdef COLORS256 register unsigned char *cx; # endif #endif debug3("WinRewrite %d, %d-%d\n", y, x1, x2); fore = (struct win *)flayer->l_data; dx = x2 - x1 + 1; if (doit) { i = fore->w_mlines[y].image + x1; while (dx-- > 0) PUTCHAR(*i++); return 0; } p = fore->w_mlines[y].attr + x1; #ifdef FONT f = fore->w_mlines[y].font + x1; # ifdef DW_CHARS if (is_dw_font(rend->font)) return EXPENSIVE; # endif # ifdef UTF8 if (fore->w_encoding && fore->w_encoding != UTF8 && D_encoding == UTF8 && ContainsSpecialDeffont(fore->w_mlines + y, x1, x2, fore->w_encoding)) return EXPENSIVE; # endif #endif #ifdef COLOR c = fore->w_mlines[y].color + x1; # ifdef COLORS256 cx = fore->w_mlines[y].colorx + x1; # endif #endif cost = dx = x2 - x1 + 1; while(dx-- > 0) { if (*p++ != rend->attr) return EXPENSIVE; #ifdef FONT if (*f++ != rend->font) return EXPENSIVE; #endif #ifdef COLOR if (*c++ != rend->color) return EXPENSIVE; # ifdef COLORS256 if (*cx++ != rend->colorx) return EXPENSIVE; # endif #endif } return cost; } static void WinClearLine(y, xs, xe, bce) int y, xs, xe, bce; { fore = (struct win *)flayer->l_data; debug3("WinClearLine %d %d-%d\n", y, xs, xe); LClearLine(flayer, y, xs, xe, bce, &fore->w_mlines[y]); } static int WinResize(wi, he) int wi, he; { fore = (struct win *)flayer->l_data; ChangeWindowSize(fore, wi, he, fore->w_histheight); return 0; } static void WinRestore() { struct canvas *cv; fore = (struct win *)flayer->l_data; debug1("WinRestore: win %p\n", fore); for (cv = flayer->l_cvlist; cv; cv = cv->c_next) { display = cv->c_display; if (cv != D_forecv) continue; /* ChangeScrollRegion(fore->w_top, fore->w_bot); */ KeypadMode(fore->w_keypad); CursorkeysMode(fore->w_cursorkeys); SetFlow(fore->w_flow & FLOW_NOW); InsertMode(fore->w_insert); ReverseVideo(fore->w_revvid); CursorVisibility(fore->w_curinv ? -1 : fore->w_curvvis); MouseMode(fore->w_mouse); } } /*****************************************************************/ /* * DoStartLog constructs a path for the "want to be logfile" in buf and * attempts logfopen. * * returns 0 on success. */ int DoStartLog(w, buf, bufsize) struct win *w; char *buf; int bufsize; { int n; if (!w || !buf) return -1; strncpy(buf, MakeWinMsg(screenlogfile, w, '%'), bufsize - 1); buf[bufsize - 1] = 0; debug2("DoStartLog: win %d, file %s\n", w->w_number, buf); if (w->w_log != NULL) logfclose(w->w_log); if ((w->w_log = logfopen(buf, islogfile(buf) ? NULL : secfopen(buf, "a"))) == NULL) return -2; if (!logflushev.queued) { n = log_flush ? log_flush : (logtstamp_after + 4) / 5; if (n) { SetTimeout(&logflushev, n * 1000); evenq(&logflushev); } } return 0; } /* * Umask & wlock are set for the user of the display, * The display d (if specified) switches to that window. */ int MakeWindow(newwin) struct NewWindow *newwin; { register struct win **pp, *p; register int n, i; int f = -1; struct NewWindow nwin; int type, startat; char *TtyName; #ifdef MULTIUSER extern struct acluser *users; #endif if (!wtab) { if (!maxwin) maxwin = MAXWIN; wtab = calloc(maxwin, sizeof(struct win *)); } debug1("NewWindow: StartAt %d\n", newwin->StartAt); debug1("NewWindow: aka %s\n", newwin->aka?newwin->aka:"NULL"); debug1("NewWindow: dir %s\n", newwin->dir?newwin->dir:"NULL"); debug1("NewWindow: term %s\n", newwin->term?newwin->term:"NULL"); nwin_compose(&nwin_default, newwin, &nwin); debug1("NWin: aka %s\n", nwin.aka ? nwin.aka : "NULL"); debug1("NWin: wlock %d\n", nwin.wlock); debug1("NWin: Lflag %d\n", nwin.Lflag); startat = nwin.StartAt < maxwin ? nwin.StartAt : 0; pp = wtab + startat; do { if (*pp == 0) break; if (++pp == wtab + maxwin) pp = wtab; } while (pp != wtab + startat); if (*pp) { Msg(0, "No more windows."); return -1; } #if defined(USRLIMIT) && defined(UTMPOK) /* * Count current number of users, if logging windows in. */ if (nwin.lflag && CountUsers() >= USRLIMIT) { Msg(0, "User limit reached. Window will not be logged in."); nwin.lflag = 0; } #endif n = pp - wtab; debug1("Makewin creating %d\n", n); if ((f = OpenDevice(nwin.args, nwin.lflag, &type, &TtyName)) < 0) return -1; if (type == W_TYPE_GROUP) f = -1; if ((p = (struct win *)calloc(1, sizeof(struct win))) == 0) { close(f); Msg(0, "%s", strnomem); return -1; } #ifdef UTMPOK if (type != W_TYPE_PTY) nwin.lflag = 0; #endif p->w_type = type; /* save the command line so that zombies can be resurrected */ for (i = 0; nwin.args[i] && i < MAXARGS - 1; i++) p->w_cmdargs[i] = SaveStr(nwin.args[i]); p->w_cmdargs[i] = 0; if (nwin.dir) p->w_dir = SaveStr(nwin.dir); if (nwin.term) p->w_term = SaveStr(nwin.term); p->w_number = n; p->w_group = 0; if (fore && fore->w_type == W_TYPE_GROUP) p->w_group = fore; else if (fore && fore->w_group) p->w_group = fore->w_group; #ifdef MULTIUSER /* * This is dangerous: without a display we use creators umask * This is intended to be useful for detached startup. * But is still better than default bits with a NULL user. */ if (NewWindowAcl(p, display ? D_user : users)) { free((char *)p); close(f); Msg(0, "%s", strnomem); return -1; } #endif p->w_layer.l_next = 0; p->w_layer.l_bottom = &p->w_layer; p->w_layer.l_layfn = &WinLf; p->w_layer.l_data = (char *)p; p->w_savelayer = &p->w_layer; p->w_pdisplay = 0; p->w_lastdisp = 0; #ifdef MULTIUSER if (display && !AclCheckPermWin(D_user, ACL_WRITE, p)) p->w_wlockuser = D_user; p->w_wlock = nwin.wlock; #endif p->w_ptyfd = f; p->w_aflag = nwin.aflag; p->w_flow = nwin.flowflag | ((nwin.flowflag & FLOW_AUTOFLAG) ? (FLOW_AUTO|FLOW_NOW) : FLOW_AUTO); if (!nwin.aka) nwin.aka = Filename(nwin.args[0]); strncpy(p->w_akabuf, nwin.aka, sizeof(p->w_akabuf) - 1); if ((nwin.aka = rindex(p->w_akabuf, '|')) != NULL) { p->w_autoaka = 0; *nwin.aka++ = 0; p->w_title = nwin.aka; p->w_akachange = nwin.aka + strlen(nwin.aka); } else p->w_title = p->w_akachange = p->w_akabuf; if (nwin.hstatus) p->w_hstatus = SaveStr(nwin.hstatus); p->w_monitor = nwin.monitor; #ifdef MULTIUSER if (p->w_monitor == MON_ON) { /* always tell all users */ for (i = 0; i < maxusercount; i++) ACLBYTE(p->w_mon_notify, i) |= ACLBIT(i); } #endif /* * defsilence by Lloyd Zusman (zusman_lloyd@jpmorgan.com) */ p->w_silence = nwin.silence; p->w_silencewait = SilenceWait; #ifdef MULTIUSER if (p->w_silence == SILENCE_ON) { /* always tell all users */ for (i = 0; i < maxusercount; i++) ACLBYTE(p->w_lio_notify, i) |= ACLBIT(i); } #endif #ifdef COPY_PASTE p->w_slowpaste = nwin.slow; #else nwin.histheight = 0; #endif p->w_norefresh = 0; strncpy(p->w_tty, TtyName, MAXSTR - 1); #if 0 /* XXX Fixme display resize */ if (ChangeWindowSize(p, display ? D_defwidth : 80, display ? D_defheight : 24, nwin.histheight)) { FreeWindow(p); return -1; } #else if (ChangeWindowSize(p, display ? D_forecv->c_xe - D_forecv->c_xs + 1: 80, display ? D_forecv->c_ye - D_forecv->c_ys + 1 : 24, nwin.histheight)) { FreeWindow(p); return -1; } #endif p->w_encoding = nwin.encoding; ResetWindow(p); /* sets w_wrap, w_c1, w_gr, w_bce */ #ifdef FONT if (nwin.charset) SetCharsets(p, nwin.charset); #endif if (VerboseCreate && type != W_TYPE_GROUP) { struct display *d = display; /* WriteString zaps display */ WriteString(p, ":screen (", 9); WriteString(p, p->w_title, strlen(p->w_title)); WriteString(p, "):", 2); for (f = 0; p->w_cmdargs[f]; f++) { WriteString(p, " ", 1); WriteString(p, p->w_cmdargs[f], strlen(p->w_cmdargs[f])); } WriteString(p, "\r\n", 2); display = d; } p->w_deadpid = 0; p->w_pid = 0; #ifdef PSEUDOS p->w_pwin = 0; #endif #ifdef BUILTIN_TELNET if (type == W_TYPE_TELNET) { if (TelConnect(p)) { FreeWindow(p); return -1; } } else #endif if (type == W_TYPE_PTY) { p->w_pid = ForkWindow(p, nwin.args, TtyName); if (p->w_pid < 0) { FreeWindow(p); return -1; } } /* * Place the new window at the head of the most-recently-used list. */ if (display && D_fore) D_other = D_fore; *pp = p; p->w_next = windows; windows = p; if (type == W_TYPE_GROUP) { SetForeWindow(p); Activate(p->w_norefresh); WindowChanged((struct win*)0, 'w'); WindowChanged((struct win*)0, 'W'); WindowChanged((struct win*)0, 0); return n; } p->w_lflag = nwin.lflag; #ifdef UTMPOK p->w_slot = (slot_t)-1; # ifdef LOGOUTOK debug1("MakeWindow will %slog in.\n", nwin.lflag?"":"not "); if (nwin.lflag & 1) # else /* LOGOUTOK */ debug1("MakeWindow will log in, LOGOUTOK undefined in config.h%s.\n", nwin.lflag?"":" (although lflag=0)"); # endif /* LOGOUTOK */ { p->w_slot = (slot_t)0; if (display || (p->w_lflag & 2)) SetUtmp(p); } # ifdef CAREFULUTMP CarefulUtmp(); /* If all 've been zombies, we've had no slot */ # endif #endif /* UTMPOK */ if (nwin.Lflag) { char buf[1024]; DoStartLog(p, buf, sizeof(buf)); } p->w_readev.fd = p->w_writeev.fd = p->w_ptyfd; p->w_readev.type = EV_READ; p->w_writeev.type = EV_WRITE; p->w_readev.data = p->w_writeev.data = (char *)p; p->w_readev.handler = win_readev_fn; p->w_writeev.handler = win_writeev_fn; p->w_writeev.condpos = &p->w_inlen; evenq(&p->w_readev); evenq(&p->w_writeev); #ifdef COPY_PASTE p->w_paster.pa_slowev.type = EV_TIMEOUT; p->w_paster.pa_slowev.data = (char *)&p->w_paster; p->w_paster.pa_slowev.handler = paste_slowev_fn; #endif p->w_silenceev.type = EV_TIMEOUT; p->w_silenceev.data = (char *)p; p->w_silenceev.handler = win_silenceev_fn; if (p->w_silence > 0) { debug("New window has silence enabled.\n"); SetTimeout(&p->w_silenceev, p->w_silencewait * 1000); evenq(&p->w_silenceev); } p->w_destroyev.type = EV_TIMEOUT; p->w_destroyev.data = 0; p->w_destroyev.handler = win_destroyev_fn; SetForeWindow(p); Activate(p->w_norefresh); WindowChanged((struct win*)0, 'w'); WindowChanged((struct win*)0, 'W'); WindowChanged((struct win*)0, 0); return n; } /* * Resurrect a window from Zombie state. * The command vector is therefore stored in the window structure. * Note: The terminaltype defaults to screenterm again, the current * working directory is lost. */ int RemakeWindow(p) struct win *p; { char *TtyName; int lflag, f; lflag = nwin_default.lflag; if ((f = OpenDevice(p->w_cmdargs, lflag, &p->w_type, &TtyName)) < 0) return -1; evdeq(&p->w_destroyev); /* no re-destroy of resurrected zombie */ strncpy(p->w_tty, *TtyName ? TtyName : p->w_title, MAXSTR - 1); p->w_ptyfd = f; p->w_readev.fd = f; p->w_writeev.fd = f; evenq(&p->w_readev); evenq(&p->w_writeev); if (VerboseCreate) { struct display *d = display; /* WriteString zaps display */ WriteString(p, ":screen (", 9); WriteString(p, p->w_title, strlen(p->w_title)); WriteString(p, "):", 2); for (f = 0; p->w_cmdargs[f]; f++) { WriteString(p, " ", 1); WriteString(p, p->w_cmdargs[f], strlen(p->w_cmdargs[f])); } WriteString(p, "\r\n", 2); display = d; } p->w_deadpid = 0; p->w_pid = 0; #ifdef BUILTIN_TELNET if (p->w_type == W_TYPE_TELNET) { if (TelConnect(p)) return -1; } else #endif if (p->w_type == W_TYPE_PTY) { p->w_pid = ForkWindow(p, p->w_cmdargs, TtyName); if (p->w_pid < 0) return -1; } #ifdef UTMPOK if (p->w_slot == (slot_t)0 && (display || (p->w_lflag & 2))) SetUtmp(p); # ifdef CAREFULUTMP CarefulUtmp(); /* If all 've been zombies, we've had no slot */ # endif #endif WindowChanged(p, 'f'); return p->w_number; } void CloseDevice(wp) struct win *wp; { if (wp->w_ptyfd < 0) return; if (wp->w_type == W_TYPE_PTY) { /* pty 4 SALE */ (void)chmod(wp->w_tty, 0666); (void)chown(wp->w_tty, 0, 0); } close(wp->w_ptyfd); wp->w_ptyfd = -1; wp->w_tty[0] = 0; evdeq(&wp->w_readev); evdeq(&wp->w_writeev); #ifdef BUILTIN_TELNET evdeq(&wp->w_telconnev); #endif wp->w_readev.fd = wp->w_writeev.fd = -1; } void FreeWindow(wp) struct win *wp; { struct display *d; int i; struct canvas *cv, *ncv; struct layer *l; debug1("FreeWindow %d\n", wp ? wp->w_number: -1); #ifdef PSEUDOS if (wp->w_pwin) FreePseudowin(wp); #endif #ifdef UTMPOK RemoveUtmp(wp); #endif CloseDevice(wp); if (wp == console_window) { TtyGrabConsole(-1, -1, "free"); console_window = 0; } if (wp->w_log != NULL) logfclose(wp->w_log); ChangeWindowSize(wp, 0, 0, 0); if (wp->w_type == W_TYPE_GROUP) { struct win *win; for (win = windows; win; win = win->w_next) if (win->w_group == wp) win->w_group = wp->w_group; } if (wp->w_hstatus) free(wp->w_hstatus); for (i = 0; wp->w_cmdargs[i]; i++) free(wp->w_cmdargs[i]); if (wp->w_dir) free(wp->w_dir); if (wp->w_term) free(wp->w_term); for (d = displays; d; d = d->d_next) { if (d->d_other == wp) d->d_other = d->d_fore && d->d_fore->w_next != wp ? d->d_fore->w_next : wp->w_next; if (d->d_fore == wp) d->d_fore = NULL; for (cv = d->d_cvlist; cv; cv = cv->c_next) { for (l = cv->c_layer; l; l = l->l_next) if (l->l_layfn == &WinLf) break; if (!l) continue; if ((struct win *)l->l_data != wp) continue; if (cv->c_layer == wp->w_savelayer) wp->w_savelayer = 0; KillLayerChain(cv->c_layer); } } if (wp->w_savelayer) KillLayerChain(wp->w_savelayer); for (cv = wp->w_layer.l_cvlist; cv; cv = ncv) { ncv = cv->c_lnext; cv->c_layer = &cv->c_blank; cv->c_blank.l_cvlist = cv; cv->c_lnext = 0; cv->c_xoff = cv->c_xs; cv->c_yoff = cv->c_ys; RethinkViewportOffsets(cv); } wp->w_layer.l_cvlist = 0; if (flayer == &wp->w_layer) flayer = 0; LayerCleanupMemory(&wp->w_layer); #ifdef MULTIUSER FreeWindowAcl(wp); #endif /* MULTIUSER */ evdeq(&wp->w_readev); /* just in case */ evdeq(&wp->w_writeev); /* just in case */ evdeq(&wp->w_silenceev); evdeq(&wp->w_destroyev); #ifdef COPY_PASTE FreePaster(&wp->w_paster); #endif free((char *)wp); } static int OpenDevice(args, lflag, typep, namep) char **args; int lflag; int *typep; char **namep; { char *arg = args[0]; struct stat st; int f; if (!arg) return -1; if (strcmp(arg, "//group") == 0) { *typep = W_TYPE_GROUP; *namep = "telnet"; return 0; } #ifdef BUILTIN_TELNET if (strcmp(arg, "//telnet") == 0) { f = TelOpen(args + 1); lflag = 0; *typep = W_TYPE_TELNET; *namep = "telnet"; } else #endif if (strncmp(arg, "//", 2) == 0) { Msg(0, "Invalid argument '%s'", arg); return -1; } else if ((stat(arg, &st)) == 0 && S_ISCHR(st.st_mode)) { if (access(arg, R_OK | W_OK) == -1) { Msg(errno, "Cannot access line '%s' for R/W", arg); return -1; } debug("OpenDevice: OpenTTY\n"); if ((f = OpenTTY(arg, args[1])) < 0) return -1; lflag = 0; *typep = W_TYPE_PLAIN; *namep = arg; } else { *typep = W_TYPE_PTY; f = OpenPTY(namep); if (f == -1) { Msg(0, "No more PTYs."); return -1; } #ifdef TIOCPKT { int flag = 1; if (ioctl(f, TIOCPKT, (char *)&flag)) { Msg(errno, "TIOCPKT ioctl"); close(f); return -1; } } #endif /* TIOCPKT */ } debug1("fcntl(%d, F_SETFL, FNBLOCK)\n", f); (void) fcntl(f, F_SETFL, FNBLOCK); #ifdef linux /* * Tenebreux (zeus@ns.acadiacom.net) has Linux 1.3.70 where select * gets confused in the following condition: * Open a pty-master side, request a flush on it, then set packet * mode and call select(). Select will return a possible read, where * the one byte response to the flush can be found. Select will * thereafter return a possible read, which yields I/O error. * * If we request another flush *after* switching into packet mode, * this I/O error does not occur. We receive a single response byte * although we send two flush requests now. * * Maybe we should not flush at all. * * 10.5.96 jw. */ if (*typep == W_TYPE_PTY || *typep == W_TYPE_PLAIN) tcflush(f, TCIOFLUSH); #endif if (*typep != W_TYPE_PTY) return f; #ifndef PTYROFS #ifdef PTYGROUP if (chown(*namep, real_uid, PTYGROUP) && !eff_uid) #else if (chown(*namep, real_uid, real_gid) && !eff_uid) #endif { Msg(errno, "chown tty"); close(f); return -1; } #ifdef UTMPOK if (chmod(*namep, lflag ? TtyMode : (TtyMode & ~022)) && !eff_uid) #else if (chmod(*namep, TtyMode) && !eff_uid) #endif { Msg(errno, "chmod tty"); close(f); return -1; } #endif return f; } /* * Fields w_width, w_height, aflag, number (and w_tty) * are read from struct win *win. No fields written. * If pwin is nonzero, filedescriptors are distributed * between win->w_tty and open(ttyn) * */ static int ForkWindow(win, args, ttyn) struct win *win; char **args, *ttyn; { int pid; char tebuf[25]; char ebuf[20]; char shellbuf[7 + MAXPATHLEN]; char *proc; #ifndef TIOCSWINSZ char libuf[20], cobuf[20]; #endif int newfd; int w = win->w_width; int h = win->w_height; #ifdef PSEUDOS int i, pat, wfdused; struct pseudowin *pwin = win->w_pwin; #endif int slave = -1; #ifdef O_NOCTTY if (pty_preopen) { debug("pre-opening slave...\n"); if ((slave = open(ttyn, O_RDWR|O_NOCTTY)) == -1) { Msg(errno, "ttyn"); return -1; } } #endif debug("forking...\n"); proc = *args; if (proc == 0) { args = ShellArgs; proc = *args; } fflush(stdout); fflush(stderr); switch (pid = fork()) { case -1: Msg(errno, "fork"); break; case 0: signal(SIGHUP, SIG_DFL); signal(SIGINT, SIG_DFL); signal(SIGQUIT, SIG_DFL); signal(SIGTERM, SIG_DFL); #ifdef BSDJOBS signal(SIGTTIN, SIG_DFL); signal(SIGTTOU, SIG_DFL); #endif #ifdef SIGPIPE signal(SIGPIPE, SIG_DFL); #endif #ifdef SIGXFSZ signal(SIGXFSZ, SIG_DFL); #endif displays = 0; /* beware of Panic() */ if (setgid(real_gid) || setuid(real_uid)) Panic(errno, "Setuid/gid"); eff_uid = real_uid; eff_gid = real_gid; #ifdef PSEUDOS if (!pwin) /* ignore directory if pseudo */ #endif if (win->w_dir && *win->w_dir && chdir(win->w_dir)) Panic(errno, "Cannot chdir to %s", win->w_dir); if (display) { brktty(D_userfd); freetty(); } else brktty(-1); #ifdef DEBUG if (dfp && dfp != stderr) fclose(dfp); #endif if (slave != -1) { close(0); dup(slave); close(slave); closeallfiles(win->w_ptyfd); slave = dup(0); } else closeallfiles(win->w_ptyfd); #ifdef DEBUG if (dfp) /* do not produce child debug, when debug is "off" */ { char buf[256]; sprintf(buf, "%s/screen.child", DEBUGDIR); if ((dfp = fopen(buf, "a")) == 0) dfp = stderr; else (void) chmod(buf, 0666); } debug1("=== ForkWindow: pid %d\n", (int)getpid()); #endif /* Close the three /dev/null descriptors */ close(0); close(1); close(2); newfd = -1; /* * distribute filedescriptors between the ttys */ #ifdef PSEUDOS pat = pwin ? pwin->p_fdpat : ((F_PFRONT<<(F_PSHIFT*2)) | (F_PFRONT<w_ptyfd); wfdused = 1; } } if (wfdused) { /* * the pseudo window process should not be surprised with a * nonblocking filedescriptor. Poor Backend! */ debug1("Clearing NBLOCK on window-fd(%d)\n", win->w_ptyfd); if (fcntl(win->w_ptyfd, F_SETFL, 0)) Msg(errno, "Warning: clear NBLOCK fcntl failed"); } #else /* PSEUDOS */ # ifdef O_NOCTTY if (separate_sids) newfd = open(ttyn, O_RDWR); else newfd = open(ttyn, O_RDWR|O_NOCTTY); # else newfd = open(ttyn, O_RDWR); # endif if (newfd != 0) Panic(errno, "Cannot open %s", ttyn); dup(0); dup(0); #endif /* PSEUDOS */ close(win->w_ptyfd); if (slave != -1) close(slave); if (newfd >= 0) { struct mode fakemode, *modep; InitPTY(newfd); if (fgtty(newfd)) Msg(errno, "fgtty"); if (display) { debug("ForkWindow: using display tty mode for new child.\n"); modep = &D_OldMode; } else { debug("No display - creating tty setting\n"); modep = &fakemode; InitTTY(modep, 0); #ifdef DEBUG DebugTTY(modep); #endif } /* We only want echo if the users input goes to the pseudo * and the pseudo's stdout is not send to the window. */ #ifdef PSEUDOS if (pwin && (!(pat & F_UWP) || (pat & F_PBACK << F_PSHIFT))) { debug1("clearing echo on pseudywin fd (pat %x)\n", pat); # if defined(POSIX) || defined(TERMIO) modep->tio.c_lflag &= ~ECHO; modep->tio.c_iflag &= ~ICRNL; # else modep->m_ttyb.sg_flags &= ~ECHO; # endif } #endif SetTTY(newfd, modep); #ifdef TIOCSWINSZ glwz.ws_col = w; glwz.ws_row = h; (void) ioctl(newfd, TIOCSWINSZ, (char *)&glwz); #endif /* Always turn off nonblocking mode */ (void)fcntl(newfd, F_SETFL, 0); } #ifndef TIOCSWINSZ sprintf(libuf, "LINES=%d", h); sprintf(cobuf, "COLUMNS=%d", w); NewEnv[5] = libuf; NewEnv[6] = cobuf; #endif #ifdef MAPKEYS NewEnv[2] = MakeTermcap(display == 0 || win->w_aflag); #else if (win->w_aflag) NewEnv[2] = MakeTermcap(1); else NewEnv[2] = Termcap; #endif strcpy(shellbuf, "SHELL="); strncpy(shellbuf + 6, ShellProg + (*ShellProg == '-'), sizeof(shellbuf) - 7); shellbuf[sizeof(shellbuf) - 1] = 0; NewEnv[4] = shellbuf; debug1("ForkWindow: NewEnv[4] = '%s'\n", shellbuf); if (win->w_term && *win->w_term && strcmp(screenterm, win->w_term) && (strlen(win->w_term) < 20)) { char *s1, *s2, tl; sprintf(tebuf, "TERM=%s", win->w_term); debug2("Makewindow %d with %s\n", win->w_number, tebuf); tl = strlen(win->w_term); NewEnv[1] = tebuf; if ((s1 = index(NewEnv[2], '|'))) { if ((s2 = index(++s1, '|'))) { if (strlen(NewEnv[2]) - (s2 - s1) + tl < 1024) { bcopy(s2, s1 + tl, strlen(s2) + 1); bcopy(win->w_term, s1, tl); } } } } sprintf(ebuf, "WINDOW=%d", win->w_number); NewEnv[3] = ebuf; if (*proc == '-') proc++; if (!*proc) proc = DefaultShell; debug1("calling execvpe %s\n", proc); execvpe(proc, args, NewEnv); debug1("exec error: %d\n", errno); Panic(errno, "Cannot exec '%s'", proc); default: break; } if (slave != -1) close(slave); return pid; } #ifndef HAVE_EXECVPE void execvpe(prog, args, env) char *prog, **args, **env; { register char *path = NULL, *p; char buf[1024]; char *shargs[MAXARGS + 1]; register int i, eaccess = 0; if (rindex(prog, '/')) path = ""; if (!path && !(path = getenv("PATH"))) path = DefaultPath; do { for (p = buf; *path && *path != ':'; path++) if (p - buf < (int)sizeof(buf) - 2) *p++ = *path; if (p > buf) *p++ = '/'; if (p - buf + strlen(prog) >= sizeof(buf) - 1) continue; strcpy(p, prog); execve(buf, args, env); switch (errno) { case ENOEXEC: shargs[0] = DefaultShell; shargs[1] = buf; for (i = 1; (shargs[i + 1] = args[i]) != NULL; ++i) ; execve(DefaultShell, shargs, env); return; case EACCES: eaccess = 1; break; case ENOMEM: case E2BIG: case ETXTBSY: return; } } while (*path++); if (eaccess) errno = EACCES; } #endif #ifdef PSEUDOS int winexec(av) char **av; { char **pp; char *p, *s, *t; int i, r = 0, l = 0; struct win *w; extern struct display *display; extern struct win *windows; struct pseudowin *pwin; int type; if ((w = display ? fore : windows) == NULL) return -1; if (!*av || w->w_pwin) { Msg(0, "Filter running: %s", w->w_pwin ? w->w_pwin->p_cmd : "(none)"); return -1; } if (w->w_ptyfd < 0) { Msg(0, "You feel dead inside."); return -1; } if (!(pwin = (struct pseudowin *)calloc(1, sizeof(struct pseudowin)))) { Msg(0, "%s", strnomem); return -1; } /* allow ^a:!!./ttytest as a short form for ^a:exec !.. ./ttytest */ for (s = *av; *s == ' '; s++) ; for (p = s; *p == ':' || *p == '.' || *p == '!'; p++) ; if (*p != '|') while (*p && p > s && p[-1] == '.') p--; if (*p == '|') { l = F_UWP; p++; } if (*p) av[0] = p; else av++; t = pwin->p_cmd; for (i = 0; i < 3; i++) { *t = (s < p) ? *s++ : '.'; switch (*t++) { case '.': case '|': l |= F_PFRONT << (i * F_PSHIFT); break; case '!': l |= F_PBACK << (i * F_PSHIFT); break; case ':': l |= F_PBOTH << (i * F_PSHIFT); break; } } if (l & F_UWP) { *t++ = '|'; if ((l & F_PMASK) == F_PFRONT) { *pwin->p_cmd = '!'; l ^= F_PFRONT | F_PBACK; } } if (!(l & F_PBACK)) l |= F_UWP; *t++ = ' '; pwin->p_fdpat = l; debug1("winexec: '%#x'\n", pwin->p_fdpat); l = MAXSTR - 4; for (pp = av; *pp; pp++) { p = *pp; while (*p && l-- > 0) *t++ = *p++; if (l <= 0) break; *t++ = ' '; } *--t = '\0'; debug1("%s\n", pwin->p_cmd); if ((pwin->p_ptyfd = OpenDevice(av, 0, &type, &t)) < 0) { free((char *)pwin); return -1; } strncpy(pwin->p_tty, t, MAXSTR - 1); w->w_pwin = pwin; if (type != W_TYPE_PTY) { FreePseudowin(w); Msg(0, "Cannot only use commands as pseudo win."); return -1; } if (!(pwin->p_fdpat & F_PFRONT)) evdeq(&w->w_readev); #ifdef TIOCPKT { int flag = 0; if (ioctl(pwin->p_ptyfd, TIOCPKT, (char *)&flag)) { Msg(errno, "TIOCPKT pwin ioctl"); FreePseudowin(w); return -1; } if (w->w_type == W_TYPE_PTY && !(pwin->p_fdpat & F_PFRONT)) { if (ioctl(w->w_ptyfd, TIOCPKT, (char *)&flag)) { Msg(errno, "TIOCPKT win ioctl"); FreePseudowin(w); return -1; } } } #endif /* TIOCPKT */ pwin->p_readev.fd = pwin->p_writeev.fd = pwin->p_ptyfd; pwin->p_readev.type = EV_READ; pwin->p_writeev.type = EV_WRITE; pwin->p_readev.data = pwin->p_writeev.data = (char *)w; pwin->p_readev.handler = pseu_readev_fn; pwin->p_writeev.handler = pseu_writeev_fn; pwin->p_writeev.condpos = &pwin->p_inlen; if (pwin->p_fdpat & (F_PFRONT << F_PSHIFT * 2 | F_PFRONT << F_PSHIFT)) evenq(&pwin->p_readev); evenq(&pwin->p_writeev); r = pwin->p_pid = ForkWindow(w, av, t); if (r < 0) FreePseudowin(w); return r; } void FreePseudowin(w) struct win *w; { struct pseudowin *pwin = w->w_pwin; ASSERT(pwin); if (fcntl(w->w_ptyfd, F_SETFL, FNBLOCK)) Msg(errno, "Warning: FreePseudowin: NBLOCK fcntl failed"); #ifdef TIOCPKT if (w->w_type == W_TYPE_PTY && !(pwin->p_fdpat & F_PFRONT)) { int flag = 1; if (ioctl(w->w_ptyfd, TIOCPKT, (char *)&flag)) Msg(errno, "Warning: FreePseudowin: TIOCPKT win ioctl"); } #endif /* should be able to use CloseDevice() here */ (void)chmod(pwin->p_tty, 0666); (void)chown(pwin->p_tty, 0, 0); if (pwin->p_ptyfd >= 0) close(pwin->p_ptyfd); evdeq(&pwin->p_readev); evdeq(&pwin->p_writeev); if (w->w_readev.condneg == &pwin->p_inlen) w->w_readev.condpos = w->w_readev.condneg = 0; evenq(&w->w_readev); free((char *)pwin); w->w_pwin = NULL; } #endif /* PSEUDOS */ #ifdef MULTIUSER /* * returns 0, if the lock really has been released */ int ReleaseAutoWritelock(dis, w) struct display *dis; struct win *w; { debug2("ReleaseAutoWritelock: user %s, window %d\n", dis->d_user->u_name, w->w_number); /* release auto writelock when user has no other display here */ if (w->w_wlock == WLOCK_AUTO && w->w_wlockuser == dis->d_user) { struct display *d; for (d = displays; d; d = d->d_next) if (( d != dis) && (d->d_fore == w) && (d->d_user == dis->d_user)) break; debug3("%s %s autolock on win %d\n", dis->d_user->u_name, d ? "keeps" : "releases", w->w_number); if (!d) { w->w_wlockuser = NULL; return 0; } } return 1; } /* * returns 0, if the lock really could be obtained */ int ObtainAutoWritelock(d, w) struct display *d; struct win *w; { if ((w->w_wlock == WLOCK_AUTO) && !AclCheckPermWin(d->d_user, ACL_WRITE, w) && !w->w_wlockuser) { debug2("%s obtained auto writelock for exported window %d\n", d->d_user->u_name, w->w_number); w->w_wlockuser = d->d_user; return 0; } return 1; } #endif /* MULTIUSER */ /********************************************************************/ #ifdef COPY_PASTE static void paste_slowev_fn(ev, data) struct event *ev; char *data; { struct paster *pa = (struct paster *)data; struct win *p; int l = 1; flayer = pa->pa_pastelayer; if (!flayer) pa->pa_pastelen = 0; if (!pa->pa_pastelen) return; p = Layer2Window(flayer); DoProcess(p, &pa->pa_pasteptr, &l, pa); pa->pa_pastelen -= 1 - l; if (pa->pa_pastelen > 0) { SetTimeout(&pa->pa_slowev, p->w_slowpaste); evenq(&pa->pa_slowev); } } #endif static int muchpending(p, ev) struct win *p; struct event *ev; { struct canvas *cv; for (cv = p->w_layer.l_cvlist; cv; cv = cv->c_lnext) { display = cv->c_display; if (D_status == STATUS_ON_WIN && !D_status_bell) { /* wait 'til status is gone */ debug("BLOCKING because of status\n"); ev->condpos = &const_one; ev->condneg = &D_status; return 1; } debug2("muchpending %s %d: ", D_usertty, D_blocked); debug3("%d %d %d\n", D_obufp - D_obuf, D_obufmax, D_blocked_fuzz); if (D_blocked) continue; if (D_obufp - D_obuf > D_obufmax + D_blocked_fuzz) { if (D_nonblock == 0) { debug1("obuf is full, stopping output to display %s\n", D_usertty); D_blocked = 1; continue; } debug("BLOCKING because of full obuf\n"); ev->condpos = &D_obuffree; ev->condneg = &D_obuflenmax; if (D_nonblock > 0 && !D_blockedev.queued) { debug1("created timeout of %g secs\n", D_nonblock/1000.); SetTimeout(&D_blockedev, D_nonblock); evenq(&D_blockedev); } return 1; } } return 0; } static void win_readev_fn(ev, data) struct event *ev; char *data; { struct win *p = (struct win *)data; char buf[IOSIZE], *bp; int size, len; #ifdef PSEUDOS int wtop; #endif bp = buf; size = IOSIZE; #ifdef PSEUDOS wtop = p->w_pwin && W_WTOP(p); if (wtop) { ASSERT(sizeof(p->w_pwin->p_inbuf) == IOSIZE); size = IOSIZE - p->w_pwin->p_inlen; if (size <= 0) { ev->condpos = &const_IOSIZE; ev->condneg = &p->w_pwin->p_inlen; return; } } #endif if (p->w_layer.l_cvlist && muchpending(p, ev)) return; #ifdef ZMODEM if (!p->w_zdisplay) #endif if (p->w_blocked) { ev->condpos = &const_one; ev->condneg = &p->w_blocked; return; } if (ev->condpos) ev->condpos = ev->condneg = 0; if ((len = p->w_outlen)) { p->w_outlen = 0; WriteString(p, p->w_outbuf, len); return; } debug1("going to read from window fd %d\n", ev->fd); if ((len = read(ev->fd, buf, size)) < 0) { if (errno == EINTR || errno == EAGAIN) return; #if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN) if (errno == EWOULDBLOCK) return; #endif debug2("Window %d: read error (errno %d) - killing window\n", p->w_number, errno); #ifdef BSDWAIT WindowDied(p, (union wait)0, 0); #else WindowDied(p, 0, 0); #endif return; } if (len == 0) { debug1("Window %d: EOF - killing window\n", p->w_number); #ifdef BSDWAIT WindowDied(p, (union wait)0, 0); #else WindowDied(p, 0, 0); #endif return; } debug1(" -> %d bytes\n", len); #ifdef TIOCPKT if (p->w_type == W_TYPE_PTY) { if (buf[0]) { debug1("PAKET %x\n", buf[0]); if (buf[0] & TIOCPKT_NOSTOP) WNewAutoFlow(p, 0); if (buf[0] & TIOCPKT_DOSTOP) WNewAutoFlow(p, 1); } bp++; len--; } #endif #ifdef BUILTIN_TELNET if (p->w_type == W_TYPE_TELNET) len = TelIn(p, bp, len, buf + sizeof(buf) - (bp + len)); #endif if (len == 0) return; #ifdef ZMODEM if (zmodem_mode && zmodem_parse(p, bp, len)) return; #endif #ifdef PSEUDOS if (wtop) { debug("sending input to pwin\n"); bcopy(bp, p->w_pwin->p_inbuf + p->w_pwin->p_inlen, len); p->w_pwin->p_inlen += len; } #endif LayPause(&p->w_layer, 1); WriteString(p, bp, len); LayPause(&p->w_layer, 0); return; } static void win_writeev_fn(ev, data) struct event *ev; char *data; { struct win *p = (struct win *)data; int len; if (p->w_inlen) { debug2("writing %d bytes to win %d\n", p->w_inlen, p->w_number); if ((len = write(ev->fd, p->w_inbuf, p->w_inlen)) <= 0) len = p->w_inlen; /* dead window */ if ((p->w_inlen -= len)) bcopy(p->w_inbuf + len, p->w_inbuf, p->w_inlen); } #ifdef COPY_PASTE if (p->w_paster.pa_pastelen && !p->w_slowpaste) { struct paster *pa = &p->w_paster; flayer = pa->pa_pastelayer; if (flayer) DoProcess(p, &pa->pa_pasteptr, &pa->pa_pastelen, pa); } #endif return; } #ifdef PSEUDOS static void pseu_readev_fn(ev, data) struct event *ev; char *data; { struct win *p = (struct win *)data; char buf[IOSIZE]; int size, ptow, len; size = IOSIZE; ptow = W_PTOW(p); if (ptow) { ASSERT(sizeof(p->w_inbuf) == IOSIZE); size = IOSIZE - p->w_inlen; if (size <= 0) { ev->condpos = &const_IOSIZE; ev->condneg = &p->w_inlen; return; } } if (p->w_layer.l_cvlist && muchpending(p, ev)) return; if (p->w_blocked) { ev->condpos = &const_one; ev->condneg = &p->w_blocked; return; } if (ev->condpos) ev->condpos = ev->condneg = 0; if ((len = p->w_outlen)) { p->w_outlen = 0; WriteString(p, p->w_outbuf, len); return; } if ((len = read(ev->fd, buf, size)) <= 0) { if (errno == EINTR || errno == EAGAIN) return; #if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN) if (errno == EWOULDBLOCK) return; #endif debug2("Window %d: pseudowin read error (errno %d) -- removing pseudowin\n", p->w_number, len ? errno : 0); FreePseudowin(p); return; } /* no packet mode on pseudos! */ if (ptow) { bcopy(buf, p->w_inbuf + p->w_inlen, len); p->w_inlen += len; } WriteString(p, buf, len); return; } static void pseu_writeev_fn(ev, data) struct event *ev; char *data; { struct win *p = (struct win *)data; struct pseudowin *pw = p->w_pwin; int len; ASSERT(pw); if (pw->p_inlen == 0) return; if ((len = write(ev->fd, pw->p_inbuf, pw->p_inlen)) <= 0) len = pw->p_inlen; /* dead pseudo */ if ((p->w_pwin->p_inlen -= len)) bcopy(p->w_pwin->p_inbuf + len, p->w_pwin->p_inbuf, p->w_pwin->p_inlen); } #endif /* PSEUDOS */ static void win_silenceev_fn(ev, data) struct event *ev; char *data; { struct win *p = (struct win *)data; struct canvas *cv; debug1("FOUND silence win %d\n", p->w_number); for (display = displays; display; display = display->d_next) { for (cv = D_cvlist; cv; cv = cv->c_next) if (cv->c_layer->l_bottom == &p->w_layer) break; if (cv) continue; /* user already sees window */ #ifdef MULTIUSER if (!(ACLBYTE(p->w_lio_notify, D_user->u_id) & ACLBIT(D_user->u_id))) continue; #endif Msg(0, "Window %d: silence for %d seconds", p->w_number, p->w_silencewait); p->w_silence = SILENCE_FOUND; WindowChanged(p, 'f'); } } static void win_destroyev_fn(ev, data) struct event *ev; char *data; { struct win *p = (struct win *)ev->data; WindowDied(p, p->w_exitstatus, 1); } #ifdef ZMODEM static int zmodem_parse(p, bp, len) struct win *p; char *bp; int len; { int i; char *b2 = bp; for (i = 0; i < len; i++, b2++) { if (p->w_zauto == 0) { for (; i < len; i++, b2++) if (*b2 == 030) break; if (i == len) break; if (i > 1 && b2[-1] == '*' && b2[-2] == '*') p->w_zauto = 3; continue; } if (p->w_zauto > 5 || *b2 == "**\030B00"[p->w_zauto] || (p->w_zauto == 5 && *b2 == '1') || (p->w_zauto == 5 && p->w_zdisplay && *b2 == '8')) { if (++p->w_zauto < 6) continue; if (p->w_zauto == 6) p->w_zauto = 0; if (!p->w_zdisplay) { if (i > 6) WriteString(p, bp, i + 1 - 6); WriteString(p, "\r\n", 2); zmodem_found(p, *b2 == '1', b2 + 1, len - i - 1); return 1; } else if (p->w_zauto == 7 || *b2 == '8') { int se = p->w_zdisplay->d_blocked == 2 ? 'O' : '\212'; for (; i < len; i++, b2++) if (*b2 == se) break; if (i < len) { zmodem_abort(p, 0); D_blocked = 0; D_readev.condpos = D_readev.condneg = 0; while (len-- > 0) AddChar(*bp++); Flush(0); Activate(D_fore ? D_fore->w_norefresh : 0); return 1; } p->w_zauto = 6; } } else p->w_zauto = *b2 == '*' ? (p->w_zauto == 2 ? 2 : 1) : 0; } if (p->w_zauto == 0 && bp[len - 1] == '*') p->w_zauto = len > 1 && bp[len - 2] == '*' ? 2 : 1; if (p->w_zdisplay) { display = p->w_zdisplay; while (len-- > 0) AddChar(*bp++); return 1; } return 0; } static void zmodem_fin(buf, len, data) char *buf; int len; char *data; { char *s; int n; if (len) RcLine(buf, strlen(buf) + 1); else { s = "\030\030\030\030\030\030\030\030\030\030"; n = strlen(s); LayProcess(&s, &n); } } static void zmodem_found(p, send, bp, len) struct win *p; int send; char *bp; int len; { char *s; int i, n; extern int zmodem_mode; /* check for abort sequence */ n = 0; for (i = 0; i < len ; i++) if (bp[i] != 030) n = 0; else if (++n > 4) return; if (zmodem_mode == 3 || (zmodem_mode == 1 && p->w_type != W_TYPE_PLAIN)) { struct display *d, *olddisplay; olddisplay = display; d = p->w_lastdisp; if (!d || d->d_fore != p) for (d = displays; d; d = d->d_next) if (d->d_fore == p) break; if (!d && p->w_layer.l_cvlist) d = p->w_layer.l_cvlist->c_display; if (!d) d = displays; if (!d) return; display = d; RemoveStatus(); p->w_zdisplay = display; D_blocked = 2 + send; flayer = &p->w_layer; ZmodemPage(); display = d; evdeq(&D_blockedev); D_readev.condpos = &const_IOSIZE; D_readev.condneg = &p->w_inlen; ClearAll(); GotoPos(0, 0); SetRendition(&mchar_blank); AddStr("Zmodem active\r\n\r\n"); AddStr(send ? "**\030B01" : "**\030B00"); while (len-- > 0) AddChar(*bp++); display = olddisplay; return; } flayer = &p->w_layer; Input(":", 100, INP_COOKED, zmodem_fin, NULL, 0); s = send ? zmodem_sendcmd : zmodem_recvcmd; n = strlen(s); LayProcess(&s, &n); } void zmodem_abort(p, d) struct win *p; struct display *d; { struct display *olddisplay = display; struct layer *oldflayer = flayer; if (p) { if (p->w_savelayer && p->w_savelayer->l_next) { if (oldflayer == p->w_savelayer) oldflayer = flayer->l_next; flayer = p->w_savelayer; ExitOverlayPage(); } p->w_zdisplay = 0; p->w_zauto = 0; LRefreshAll(&p->w_layer, 0); } if (d) { display = d; D_blocked = 0; D_readev.condpos = D_readev.condneg = 0; Activate(D_fore ? D_fore->w_norefresh : 0); } display = olddisplay; flayer = oldflayer; } #endif int WindowChangeNumber(struct win *win, int n) { struct win *p; int old = win->w_number; if (n < 0 || n >= maxwin) { Msg(0, "Given window position is invalid."); return 0; } p = wtab[n]; wtab[n] = win; win->w_number = n; wtab[old] = p; if (p) p->w_number = old; #ifdef MULTIUSER /* exchange the acls for these windows. */ AclWinSwap(old, n); #endif #ifdef UTMPOK /* exchange the utmp-slots for these windows */ if ((win->w_slot != (slot_t) -1) && (win->w_slot != (slot_t) 0)) { RemoveUtmp(win); SetUtmp(win); } if (p && (p->w_slot != (slot_t) -1) && (p->w_slot != (slot_t) 0)) { /* XXX: first display wins? */ #if 0 /* Does this make more sense? */ display = p->w_lastdisp ? p->w_lastdisp : p->w_layer.l_cvlist ? p->w_layer.l_cvlist->c_display : 0; #else display = win->w_layer.l_cvlist ? win->w_layer.l_cvlist->c_display : 0; #endif RemoveUtmp(p); SetUtmp(p); } #endif WindowChanged(win, 'n'); WindowChanged((struct win *)0, 'w'); WindowChanged((struct win *)0, 'W'); WindowChanged((struct win *)0, 0); return 1; } screen-4.1.0/screen.c0000644000175000017500000022660411732171225012471 0ustar abeabe/* Copyright (c) 2010 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net) * Copyright (c) 2008, 2009 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Micah Cowan (micah@cowan.name) * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net) * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Copyright (c) 1987 Oliver Laumann #ifdef HAVE_BRAILLE * Modified by: * Authors: Hadi Bargi Rangin bargi@dots.physics.orst.edu * Bill Barry barryb@dots.physics.orst.edu * Randy Lundquist randyl@dots.physics.orst.edu * * Modifications Copyright (c) 1995 by * Science Access Project, Oregon State University. #endif * * 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, 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 (see the file COPYING); if not, see * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA * **************************************************************** */ #include #include #include #ifdef sgi # include #endif #include #ifndef sun # include #endif #ifndef SIGINT # include #endif #include "config.h" #ifdef HAVE_STROPTS_H # include #endif #if defined(SYSV) && !defined(ISC) # include #endif #if defined(sequent) || defined(SVR4) # include #endif /* sequent || SVR4 */ #ifdef ISC # include # include # include #endif /* ISC */ #if (defined(AUX) || defined(_AUX_SOURCE)) && defined(POSIX) # include #endif #if defined(USE_LOCALE) || defined(ENCODINGS) # include #endif #if defined(HAVE_NL_LANGINFO) && defined(ENCODINGS) # include #endif #include "screen.h" #ifdef HAVE_BRAILLE # include "braille.h" #endif #include "patchlevel.h" /* * At the moment we only need the real password if the * builtin lock is used. Therefore disable SHADOWPW if * we do not really need it (kind of security thing). */ #ifndef LOCK # undef SHADOWPW #endif #include #ifdef SHADOWPW # include #endif /* SHADOWPW */ #include "logfile.h" /* islogfile, logfflush */ #ifdef DEBUG FILE *dfp; #endif extern char Term[], screenterm[], **environ, Termcap[]; int force_vt = 1; int VBellWait, MsgWait, MsgMinWait, SilenceWait; extern struct acluser *users; extern struct display *displays, *display; extern struct LayFuncs MarkLf; extern int visual_bell; #ifdef COPY_PASTE extern unsigned char mark_key_tab[]; #endif extern char version[]; extern char DefaultShell[]; #ifdef ZMODEM extern char *zmodem_sendcmd; extern char *zmodem_recvcmd; #endif extern struct layout *layout_last; char *ShellProg; char *ShellArgs[2]; extern struct NewWindow nwin_undef, nwin_default, nwin_options; struct backtick; static struct passwd *getpwbyname __P((char *, struct passwd *)); static void SigChldHandler __P((void)); static sigret_t SigChld __P(SIGPROTOARG); static sigret_t SigInt __P(SIGPROTOARG); static sigret_t CoreDump __P(SIGPROTOARG); static sigret_t FinitHandler __P(SIGPROTOARG); static void DoWait __P((void)); static void serv_read_fn __P((struct event *, char *)); static void serv_select_fn __P((struct event *, char *)); static void logflush_fn __P((struct event *, char *)); static void backtick_filter __P((struct backtick *)); static void backtick_fn __P((struct event *, char *)); static char *runbacktick __P((struct backtick *, int *, time_t)); static int IsSymbol __P((char *, char *)); static char *ParseChar __P((char *, char *)); static int ParseEscape __P((char *)); static char *pad_expand __P((char *, char *, int, int)); #ifdef DEBUG static void fds __P((void)); #endif int nversion; /* numerical version, used for secondary DA */ /* the attacher */ struct passwd *ppp; char *attach_tty; int attach_fd = -1; char *attach_term; char *LoginName; struct mode attach_Mode; char SockPath[MAXPATHLEN + 2 * MAXSTR]; char *SockName; /* SockName is pointer in SockPath */ char *SockMatch = NULL; /* session id command line argument */ int ServerSocket = -1; struct event serv_read; struct event serv_select; struct event logflushev; char **NewEnv = NULL; char *RcFileName = NULL; char *home; char *screenlogfile; /* filename layout */ int log_flush = 10; /* flush interval in seconds */ int logtstamp_on = 0; /* tstamp disabled */ char *logtstamp_string; /* stamp layout */ int logtstamp_after = 120; /* first tstamp after 120s */ char *hardcopydir = NULL; char *BellString; char *VisualBellString; char *ActivityString; #ifdef COPY_PASTE char *BufferFile; #endif #ifdef POW_DETACH char *PowDetachString; #endif char *hstatusstring; char *captionstring; char *timestring; char *wliststr; char *wlisttit; int auto_detach = 1; int iflag, rflag, dflag, lsflag, quietflag, wipeflag, xflag; int cmdflag; int queryflag = -1; int adaptflag; #ifdef MULTIUSER char *multi; char *multi_home; int multi_uid; int own_uid; int multiattach; int tty_mode; int tty_oldmode = -1; #endif char HostName[MAXSTR]; int MasterPid, PanicPid; int real_uid, real_gid, eff_uid, eff_gid; int default_startup; int ZombieKey_destroy, ZombieKey_resurrect, ZombieKey_onerror; char *preselect = NULL; /* only used in Attach() */ #ifdef UTF8 char *screenencodings; #endif #ifdef DW_CHARS int cjkwidth; #endif #ifdef NETHACK int nethackflag = 0; #endif int maxwin; struct layer *flayer; struct win *fore; struct win *windows; struct win *console_window; /* * Do this last */ #include "extern.h" char strnomem[] = "Out of memory."; static int InterruptPlease; static int GotSigChld; static int lf_secreopen(name, wantfd, l) char *name; int wantfd; struct logfile *l; { int got_fd; close(wantfd); if (((got_fd = secopen(name, O_WRONLY | O_CREAT | O_APPEND, 0666)) < 0) || lf_move_fd(got_fd, wantfd) < 0) { logfclose(l); debug1("lf_secreopen: failed for %s\n", name); return -1; } l->st->st_ino = l->st->st_dev = 0; debug2("lf_secreopen: %d = %s\n", wantfd, name); return 0; } /********************************************************************/ /********************************************************************/ /********************************************************************/ static struct passwd * getpwbyname(name, ppp) char *name; struct passwd *ppp; { int n; #ifdef SHADOWPW struct spwd *sss = NULL; static char *spw = NULL; #endif if (!ppp && !(ppp = getpwnam(name))) return NULL; /* Do password sanity check..., allow ##user for SUN_C2 security */ #ifdef SHADOWPW pw_try_again: #endif n = 0; if (ppp->pw_passwd[0] == '#' && ppp->pw_passwd[1] == '#' && strcmp(ppp->pw_passwd + 2, ppp->pw_name) == 0) n = 13; for (; n < 13; n++) { char c = ppp->pw_passwd[n]; if (!(c == '.' || c == '/' || c == '$' || (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))) break; } #ifdef SHADOWPW /* try to determine real password */ if (n < 13 && sss == 0) { sss = getspnam(ppp->pw_name); if (sss) { if (spw) free(spw); ppp->pw_passwd = spw = SaveStr(sss->sp_pwdp); endspent(); /* this should delete all buffers ... */ goto pw_try_again; } endspent(); /* this should delete all buffers ... */ } #endif if (n < 13) ppp->pw_passwd = 0; #ifdef linux if (ppp->pw_passwd && strlen(ppp->pw_passwd) == 13 + 11) ppp->pw_passwd[13] = 0; /* beware of linux's long passwords */ #endif return ppp; } static char * locale_name(void) { static char *s; if (!s) { s = getenv("LC_ALL"); if (s == NULL) s = getenv("LC_CTYPE"); if (s == NULL) s = getenv("LANG"); } return s; } int main(ac, av) int ac; char **av; { register int n; char *ap; char *av0; char socknamebuf[2 * MAXSTR]; int mflag = 0; char *myname = (ac == 0) ? "screen" : av[0]; char *SockDir; struct stat st; #ifdef _MODE_T /* (jw) */ mode_t oumask; #else int oumask; #endif #if defined(SYSV) && !defined(ISC) struct utsname utsnam; #endif struct NewWindow nwin; int detached = 0; /* start up detached */ #ifdef MULTIUSER char *sockp; #endif char *sty = 0; #if (defined(AUX) || defined(_AUX_SOURCE)) && defined(POSIX) setcompat(COMPAT_POSIX|COMPAT_BSDPROT); /* turn on seteuid support */ #endif #if defined(sun) && defined(SVR4) { /* Solaris' login blocks SIGHUP! This is _very bad_ */ sigset_t sset; sigemptyset(&sset); sigprocmask(SIG_SETMASK, &sset, 0); } #endif /* * First, close all unused descriptors * (otherwise, we might have problems with the select() call) */ closeallfiles(0); #ifdef DEBUG opendebug(1, 0); #endif snprintf(version, 59, "%d.%.2d.%.2d%s (%s%s) %s", REV, VERS, PATCHLEVEL, STATE, ORIGIN, GIT_REV, DATE); nversion = REV * 10000 + VERS * 100 + PATCHLEVEL; debug2("-- screen debug started %s (%s)\n", *av, version); #ifdef POSIX debug("POSIX\n"); #endif #ifdef TERMIO debug("TERMIO\n"); #endif #ifdef SYSV debug("SYSV\n"); #endif #ifdef SYSVSIGS debug("SYSVSIGS\n"); #endif #ifdef NAMEDPIPE debug("NAMEDPIPE\n"); #endif #if defined(SIGWINCH) && defined(TIOCGWINSZ) debug("Window size changing enabled\n"); #endif #ifdef HAVE_SETREUID debug("SETREUID\n"); #endif #ifdef HAVE_SETEUID debug("SETEUID\n"); #endif #ifdef hpux debug("hpux\n"); #endif #ifdef USEBCOPY debug("USEBCOPY\n"); #endif #ifdef UTMPOK debug("UTMPOK\n"); #endif #ifdef LOADAV debug("LOADAV\n"); #endif #ifdef NETHACK debug("NETHACK\n"); #endif #ifdef TERMINFO debug("TERMINFO\n"); #endif #ifdef SHADOWPW debug("SHADOWPW\n"); #endif #ifdef NAME_MAX debug1("NAME_MAX = %d\n", NAME_MAX); #endif BellString = SaveStr("Bell in window %n"); VisualBellString = SaveStr(" Wuff, Wuff!! "); ActivityString = SaveStr("Activity in window %n"); screenlogfile = SaveStr("screenlog.%n"); logtstamp_string = SaveStr("-- %n:%t -- time-stamp -- %M/%d/%y %c:%s --\n"); hstatusstring = SaveStr("%h"); captionstring = SaveStr("%4n %t"); timestring = SaveStr("%c:%s %M %d %H%? %l%?"); wlisttit = SaveStr(" Num Name%=Flags"); wliststr = SaveStr("%4n %t%=%f"); #ifdef COPY_PASTE BufferFile = SaveStr(DEFAULT_BUFFERFILE); #endif ShellProg = NULL; #ifdef POW_DETACH PowDetachString = 0; #endif default_startup = (ac > 1) ? 0 : 1; adaptflag = 0; VBellWait = VBELLWAIT * 1000; MsgWait = MSGWAIT * 1000; MsgMinWait = MSGMINWAIT * 1000; SilenceWait = SILENCEWAIT; #ifdef HAVE_BRAILLE InitBraille(); #endif #ifdef ZMODEM zmodem_sendcmd = SaveStr("!!! sz -vv -b "); zmodem_recvcmd = SaveStr("!!! rz -vv -b -E"); #endif #ifdef COPY_PASTE CompileKeys((char *)0, 0, mark_key_tab); #endif #ifdef UTF8 InitBuiltinTabs(); screenencodings = SaveStr(SCREENENCODINGS); #endif #ifdef DW_CHARS cjkwidth = 0; #endif nwin = nwin_undef; nwin_options = nwin_undef; strcpy(screenterm, "screen"); logreopen_register(lf_secreopen); av0 = *av; /* if this is a login screen, assume -RR */ if (*av0 == '-') { rflag = 4; #ifdef MULTI xflag = 1; #else dflag = 1; #endif ShellProg = SaveStr(DefaultShell); /* to prevent nasty circles */ } while (ac > 0) { ap = *++av; if (--ac > 0 && *ap == '-') { if (ap[1] == '-' && ap[2] == 0) { av++; ac--; break; } if (ap[1] == '-' && !strcmp(ap, "--version")) Panic(0, "Screen version %s", version); if (ap[1] == '-' && !strcmp(ap, "--help")) exit_with_usage(myname, NULL, NULL); while (ap && *ap && *++ap) { switch (*ap) { case 'a': nwin_options.aflag = 1; break; case 'A': adaptflag = 1; break; case 'p': /* preselect */ if (*++ap) preselect = ap; else { if (!--ac) exit_with_usage(myname, "Specify a window to preselect with -p", NULL); preselect = *++av; } ap = NULL; break; #ifdef HAVE_BRAILLE case 'B': bd.bd_start_braille = 1; break; #endif case 'c': if (*++ap) RcFileName = ap; else { if (--ac == 0) exit_with_usage(myname, "Specify an alternate rc-filename with -c", NULL); RcFileName = *++av; } ap = NULL; break; case 'e': if (!*++ap) { if (--ac == 0) exit_with_usage(myname, "Specify command characters with -e", NULL); ap = *++av; } if (ParseEscape(ap)) Panic(0, "Two characters are required with -e option, not '%s'.", ap); ap = NULL; break; case 'f': ap++; switch (*ap++) { case 'n': case '0': nwin_options.flowflag = FLOW_NOW * 0; break; case '\0': ap--; /* FALLTHROUGH */ case 'y': case '1': nwin_options.flowflag = FLOW_NOW * 1; break; case 'a': nwin_options.flowflag = FLOW_AUTOFLAG; break; default: exit_with_usage(myname, "Unknown flow option -%s", --ap); } break; case 'h': if (--ac == 0) exit_with_usage(myname, NULL, NULL); nwin_options.histheight = atoi(*++av); if (nwin_options.histheight < 0) exit_with_usage(myname, "-h: %s: negative scrollback size?", *av); break; case 'i': iflag = 1; break; case 't': /* title, the former AkA == -k */ if (--ac == 0) exit_with_usage(myname, "Specify a new window-name with -t", NULL); nwin_options.aka = *++av; break; case 'l': ap++; switch (*ap++) { case 'n': case '0': nwin_options.lflag = 0; break; case '\0': ap--; /* FALLTHROUGH */ case 'y': case '1': nwin_options.lflag = 1; break; case 'a': nwin_options.lflag = 3; break; case 's': /* -ls */ case 'i': /* -list */ lsflag = 1; if (ac > 1 && !SockMatch) { SockMatch = *++av; ac--; } ap = NULL; break; default: exit_with_usage(myname, "%s: Unknown suboption to -l", --ap); } break; case 'w': lsflag = 1; wipeflag = 1; if (ac > 1 && !SockMatch) { SockMatch = *++av; ac--; } break; case 'L': nwin_options.Lflag = 1; break; case 'm': mflag = 1; break; case 'O': /* to be (or not to be?) deleted. jw. */ force_vt = 0; break; case 'T': if (--ac == 0) exit_with_usage(myname, "Specify terminal-type with -T", NULL); if (strlen(*++av) < 20) strcpy(screenterm, *av); else Panic(0, "-T: terminal name too long. (max. 20 char)"); nwin_options.term = screenterm; break; case 'q': quietflag = 1; break; case 'Q': queryflag = 1; cmdflag = 1; break; case 'r': case 'R': #ifdef MULTI case 'x': #endif if (ac > 1 && *av[1] != '-' && !SockMatch) { SockMatch = *++av; ac--; debug2("rflag=%d, SockMatch=%s\n", dflag, SockMatch); } #ifdef MULTI if (*ap == 'x') xflag = 1; #endif if (rflag) rflag = 2; rflag += (*ap == 'R') ? 2 : 1; break; #ifdef REMOTE_DETACH case 'd': dflag = 1; /* FALLTHROUGH */ case 'D': if (!dflag) dflag = 2; if (ac == 2) { if (*av[1] != '-' && !SockMatch) { SockMatch = *++av; ac--; debug2("dflag=%d, SockMatch=%s\n", dflag, SockMatch); } } break; #endif case 's': if (--ac == 0) exit_with_usage(myname, "Specify shell with -s", NULL); if (ShellProg) free(ShellProg); ShellProg = SaveStr(*++av); debug1("ShellProg: '%s'\n", ShellProg); break; case 'S': if (!SockMatch) { if (--ac == 0) exit_with_usage(myname, "Specify session-name with -S", NULL); SockMatch = *++av; } if (!*SockMatch) exit_with_usage(myname, "Empty session-name?", NULL); break; case 'X': cmdflag = 1; break; case 'v': Panic(0, "Screen version %s", version); /* NOTREACHED */ #ifdef UTF8 case 'U': nwin_options.encoding = nwin_options.encoding == -1 ? UTF8 : 0; break; #endif default: exit_with_usage(myname, "Unknown option %s", --ap); } } } else break; } real_uid = getuid(); real_gid = getgid(); eff_uid = geteuid(); eff_gid = getegid(); #ifdef SIGBUS /* OOPS, linux has no bus errors! */ signal(SIGBUS, CoreDump); #endif /* SIGBUS */ signal(SIGSEGV, CoreDump); #ifdef USE_LOCALE setlocale(LC_ALL, ""); #endif #ifdef ENCODINGS if (nwin_options.encoding == -1) { /* ask locale if we should start in UTF-8 mode */ # ifdef HAVE_NL_LANGINFO # ifndef USE_LOCALE setlocale(LC_CTYPE, ""); # endif nwin_options.encoding = FindEncoding(nl_langinfo(CODESET)); debug1("locale says encoding = %d\n", nwin_options.encoding); # else # ifdef UTF8 char *s; if ((s = locale_name()) && InStr(s, "UTF-8")) nwin_options.encoding = UTF8; # endif debug1("environment says encoding=%d\n", nwin_options.encoding); #endif } # ifdef DW_CHARS { char *s; if ((s = locale_name())) { if(!strncmp(s, "zh_", 3) || !strncmp(s, "ja_", 3) || !strncmp(s, "ko_", 3)) { cjkwidth = 1; } } } #endif #endif if (nwin_options.aka) { #ifdef ENCODINGS if (nwin_options.encoding > 0) { size_t len = strlen(nwin_options.aka); size_t newsz; char *newbuf = malloc(3 * len); if (!newbuf) Panic(0, "%s", strnomem); newsz = RecodeBuf((unsigned char *)nwin_options.aka, len, nwin_options.encoding, 0, (unsigned char *)newbuf); newbuf[newsz] = '\0'; nwin_options.aka = newbuf; } else #endif { /* If we just use the original value from av, subsequent shelltitle invocations will attempt to free space we don't own... */ nwin_options.aka = SaveStr(nwin_options.aka); } } if (SockMatch && strlen(SockMatch) >= MAXSTR) Panic(0, "Ridiculously long socketname - try again."); if (cmdflag && !rflag && !dflag && !xflag) xflag = 1; if (!cmdflag && dflag && mflag && !(rflag || xflag)) detached = 1; nwin = nwin_options; #ifdef ENCODINGS nwin.encoding = nwin_undef.encoding; /* let screenrc overwrite it */ #endif if (ac) nwin.args = av; /* make the write() calls return -1 on all errors */ #ifdef SIGXFSZ /* * Ronald F. Guilmette, Oct 29 '94, bug-gnu-utils@prep.ai.mit.edu: * It appears that in System V Release 4, UNIX, if you are writing * an output file and you exceed the currently set file size limit, * you _don't_ just get the call to `write' returning with a * failure code. Rather, you get a signal called `SIGXFSZ' which, * if neither handled nor ignored, will cause your program to crash * with a core dump. */ signal(SIGXFSZ, SIG_IGN); #endif /* SIGXFSZ */ #ifdef SIGPIPE signal(SIGPIPE, SIG_IGN); #endif if (!ShellProg) { register char *sh; sh = getenv("SHELL"); ShellProg = SaveStr(sh ? sh : DefaultShell); } ShellArgs[0] = ShellProg; home = getenv("HOME"); if (!mflag && !SockMatch) { sty = getenv("STY"); if (sty && *sty == 0) sty = 0; } #ifdef NETHACK if (!(nethackflag = (getenv("NETHACKOPTIONS") != NULL))) { char nethackrc[MAXPATHLEN]; if (home && (strlen(home) < (MAXPATHLEN - 20))) { sprintf(nethackrc,"%s/.nethackrc", home); nethackflag = !access(nethackrc, F_OK); } } #endif #ifdef MULTIUSER own_uid = multi_uid = real_uid; if (SockMatch && (sockp = index(SockMatch, '/'))) { *sockp = 0; multi = SockMatch; SockMatch = sockp + 1; if (*multi) { struct passwd *mppp; if ((mppp = getpwnam(multi)) == (struct passwd *)0) Panic(0, "Cannot identify account '%s'.", multi); multi_uid = mppp->pw_uid; multi_home = SaveStr(mppp->pw_dir); if (strlen(multi_home) > MAXPATHLEN - 10) Panic(0, "home directory path too long"); # ifdef MULTI /* always fake multi attach mode */ if (rflag || lsflag) xflag = 1; # endif /* MULTI */ detached = 0; multiattach = 1; } /* Special case: effective user is multiuser. */ if (eff_uid && (multi_uid != eff_uid)) Panic(0, "Must run suid root for multiuser support."); } if (SockMatch && *SockMatch == 0) SockMatch = 0; #endif /* MULTIUSER */ if ((LoginName = getlogin()) && LoginName[0] != '\0') { if ((ppp = getpwnam(LoginName)) != (struct passwd *) 0) if ((int)ppp->pw_uid != real_uid) ppp = (struct passwd *) 0; } if (ppp == 0) { if ((ppp = getpwuid(real_uid)) == 0) { Panic(0, "getpwuid() can't identify your account!"); exit(1); } LoginName = ppp->pw_name; } LoginName = SaveStr(LoginName); ppp = getpwbyname(LoginName, ppp); #if !defined(SOCKDIR) && defined(MULTIUSER) if (multi && !multiattach) { if (home && strcmp(home, ppp->pw_dir)) Panic(0, "$HOME must match passwd entry for multiuser screens."); } #endif #define SET_GUID() do \ { \ setgid(real_gid); \ setuid(real_uid); \ eff_uid = real_uid; \ eff_gid = real_gid; \ } while (0) #define SET_TTYNAME(fatal) do \ { \ if (!(attach_tty = ttyname(0))) \ { \ if (fatal) \ Panic(0, "Must be connected to a terminal."); \ else \ attach_tty = ""; \ } \ else if (stat(attach_tty, &st)) \ Panic(errno, "Cannot access '%s'", attach_tty); \ if (strlen(attach_tty) >= MAXPATHLEN) \ Panic(0, "TtyName too long - sorry."); \ } while (0) if (home == 0 || *home == '\0') home = ppp->pw_dir; if (strlen(LoginName) > 20) Panic(0, "LoginName too long - sorry."); #ifdef MULTIUSER if (multi && strlen(multi) > 20) Panic(0, "Screen owner name too long - sorry."); #endif if (strlen(home) > MAXPATHLEN - 25) Panic(0, "$HOME too long - sorry."); attach_tty = ""; if (!detached && !lsflag && !cmdflag && !(dflag && !mflag && !rflag && !xflag) && !(!mflag && !SockMatch && sty && !xflag)) { #ifndef NAMEDPIPE int fl; #endif /* ttyname implies isatty */ SET_TTYNAME(1); #ifdef MULTIUSER tty_mode = (int)st.st_mode & 0777; #endif #ifndef NAMEDPIPE fl = fcntl(0, F_GETFL, 0); if (fl != -1 && (fl & (O_RDWR|O_RDONLY|O_WRONLY)) == O_RDWR) attach_fd = 0; #endif if (attach_fd == -1) { if ((n = secopen(attach_tty, O_RDWR | O_NONBLOCK, 0)) < 0) Panic(0, "Cannot open your terminal '%s' - please check.", attach_tty); close(n); } debug2("attach_tty is %s, attach_fd is %d\n", attach_tty, attach_fd); if ((attach_term = getenv("TERM")) == 0 || *attach_term == 0) Panic(0, "Please set a terminal type."); if (strlen(attach_term) > sizeof(D_termname) - 1) Panic(0, "$TERM too long - sorry."); GetTTY(0, &attach_Mode); #ifdef DEBUGGGGGGGGGGGGGGG DebugTTY(&attach_Mode); #endif /* DEBUG */ } #ifdef _MODE_T oumask = umask(0); /* well, unsigned never fails? jw. */ #else if ((oumask = (int)umask(0)) == -1) Panic(errno, "Cannot change umask to zero"); #endif SockDir = getenv("SCREENDIR"); if (SockDir) { if (strlen(SockDir) >= MAXPATHLEN - 1) Panic(0, "Ridiculously long $SCREENDIR - try again."); #ifdef MULTIUSER if (multi) Panic(0, "No $SCREENDIR with multi screens, please."); #endif } #ifdef MULTIUSER if (multiattach) { # ifndef SOCKDIR sprintf(SockPath, "%s/.screen", multi_home); SockDir = SockPath; # else SockDir = SOCKDIR; sprintf(SockPath, "%s/S-%s", SockDir, multi); # endif } else #endif { #ifndef SOCKDIR if (SockDir == 0) { sprintf(SockPath, "%s/.screen", home); SockDir = SockPath; } #endif if (SockDir) { if (access(SockDir, F_OK)) { debug1("SockDir '%s' missing ...\n", SockDir); if (UserContext() > 0) { if (mkdir(SockDir, 0700)) UserReturn(0); UserReturn(1); } if (UserStatus() <= 0) Panic(0, "Cannot make directory '%s'.", SockDir); } if (SockDir != SockPath) strcpy(SockPath, SockDir); } #ifdef SOCKDIR else { SockDir = SOCKDIR; if (stat(SockDir, &st)) { n = (eff_uid == 0 && (real_uid || eff_gid == real_gid)) ? 0755 : (eff_gid != real_gid) ? 0775 : #ifdef S_ISVTX 0777|S_ISVTX; #else 0777; #endif if (mkdir(SockDir, n) == -1) Panic(errno, "Cannot make directory '%s'", SockDir); } else { if (!S_ISDIR(st.st_mode)) Panic(0, "'%s' must be a directory.", SockDir); if (eff_uid == 0 && real_uid && (int)st.st_uid != eff_uid) Panic(0, "Directory '%s' must be owned by root.", SockDir); n = (eff_uid == 0 && (real_uid || (st.st_mode & 0775) != 0775)) ? 0755 : (eff_gid == (int)st.st_gid && eff_gid != real_gid) ? 0775 : 0777; if (((int)st.st_mode & 0777) != n) Panic(0, "Directory '%s' must have mode %03o.", SockDir, n); } sprintf(SockPath, "%s/S-%s", SockDir, LoginName); if (access(SockPath, F_OK)) { if (mkdir(SockPath, 0700) == -1) Panic(errno, "Cannot make directory '%s'", SockPath); (void) chown(SockPath, real_uid, real_gid); } } #endif } if (stat(SockPath, &st) == -1) Panic(errno, "Cannot access %s", SockPath); else if (!S_ISDIR(st.st_mode)) Panic(0, "%s is not a directory.", SockPath); #ifdef MULTIUSER if (multi) { if ((int)st.st_uid != multi_uid) Panic(0, "%s is not the owner of %s.", multi, SockPath); } else #endif { if ((int)st.st_uid != real_uid) Panic(0, "You are not the owner of %s.", SockPath); } if ((st.st_mode & 0777) != 0700) Panic(0, "Directory %s must have mode 700.", SockPath); if (SockMatch && index(SockMatch, '/')) Panic(0, "Bad session name '%s'", SockMatch); SockName = SockPath + strlen(SockPath) + 1; *SockName = 0; (void) umask(oumask); debug2("SockPath: %s SockMatch: %s\n", SockPath, SockMatch ? SockMatch : "NULL"); #if defined(SYSV) && !defined(ISC) if (uname(&utsnam) == -1) Panic(errno, "uname"); strncpy(HostName, utsnam.nodename, sizeof(utsnam.nodename) < MAXSTR ? sizeof(utsnam.nodename) : MAXSTR - 1); HostName[sizeof(utsnam.nodename) < MAXSTR ? sizeof(utsnam.nodename) : MAXSTR - 1] = '\0'; #else (void) gethostname(HostName, MAXSTR); HostName[MAXSTR - 1] = '\0'; #endif if ((ap = index(HostName, '.')) != NULL) *ap = '\0'; if (lsflag) { int i, fo, oth; #ifdef MULTIUSER if (multi) real_uid = multi_uid; #endif SET_GUID(); i = FindSocket((int *)NULL, &fo, &oth, SockMatch); if (quietflag) exit(8 + (fo ? ((oth || i) ? 2 : 1) : 0) + i); if (fo == 0) Panic(0, "No Sockets found in %s.\n", SockPath); Panic(0, "%d Socket%s in %s.\n", fo, fo > 1 ? "s" : "", SockPath); /* NOTREACHED */ } signal(SIG_BYE, AttacherFinit); /* prevent races */ if (cmdflag) { /* attach_tty is not mandatory */ SET_TTYNAME(0); if (!*av) Panic(0, "Please specify a command."); SET_GUID(); SendCmdMessage(sty, SockMatch, av, queryflag >= 0); exit(0); } else if (rflag || xflag) { debug("screen -r: - is there anybody out there?\n"); if (Attach(MSG_ATTACH)) { Attacher(); /* NOTREACHED */ } #ifdef MULTIUSER if (multiattach) Panic(0, "Can't create sessions of other users."); #endif debug("screen -r: backend not responding -- still crying\n"); } else if (dflag && !mflag) { SET_TTYNAME(0); Attach(MSG_DETACH); Msg(0, "[%s %sdetached.]\n", SockName, (dflag > 1 ? "power " : "")); eexit(0); /* NOTREACHED */ } if (!SockMatch && !mflag && sty) { /* attach_tty is not mandatory */ SET_TTYNAME(0); SET_GUID(); nwin_options.args = av; SendCreateMsg(sty, &nwin); exit(0); /* NOTREACHED */ } nwin_compose(&nwin_default, &nwin_options, &nwin_default); if (!detached || dflag != 2) MasterPid = fork(); else MasterPid = 0; switch (MasterPid) { case -1: Panic(errno, "fork"); /* NOTREACHED */ case 0: break; default: if (detached) exit(0); if (SockMatch) sprintf(socknamebuf, "%d.%s", MasterPid, SockMatch); else sprintf(socknamebuf, "%d.%s.%s", MasterPid, stripdev(attach_tty), HostName); for (ap = socknamebuf; *ap; ap++) if (*ap == '/') *ap = '-'; #ifdef NAME_MAX if (strlen(socknamebuf) > NAME_MAX) socknamebuf[NAME_MAX] = 0; #endif sprintf(SockPath + strlen(SockPath), "/%s", socknamebuf); SET_GUID(); Attacher(); /* NOTREACHED */ } if (!detached) PanicPid = getppid(); if (DefaultEsc == -1) DefaultEsc = Ctrl('a'); if (DefaultMetaEsc == -1) DefaultMetaEsc = 'a'; ap = av0 + strlen(av0) - 1; while (ap >= av0) { if (!strncmp("screen", ap, 6)) { strncpy(ap, "SCREEN", 6); /* name this process "SCREEN-BACKEND" */ break; } ap--; } if (ap < av0) *av0 = 'S'; #ifdef DEBUG { char buf[256]; if (dfp && dfp != stderr) fclose(dfp); sprintf(buf, "%s/SCREEN.%d", DEBUGDIR, (int)getpid()); if ((dfp = fopen(buf, "w")) == NULL) dfp = stderr; else (void) chmod(buf, 0666); } #endif if (!detached) { if (attach_fd == -1) { if ((n = secopen(attach_tty, O_RDWR, 0)) < 0) Panic(0, "Cannot reopen '%s' - please check.", attach_tty); } else n = dup(attach_fd); } else n = -1; freopen("/dev/null", "r", stdin); freopen("/dev/null", "w", stdout); #ifdef DEBUG if (dfp != stderr) #endif freopen("/dev/null", "w", stderr); debug("-- screen.back debug started\n"); /* * This guarantees that the session owner is listed, even when we * start detached. From now on we should not refer to 'LoginName' * any more, use users->u_name instead. */ if (UserAdd(LoginName, (char *)0, (struct acluser **)0) < 0) Panic(0, "Could not create user info"); if (!detached) { if (MakeDisplay(LoginName, attach_tty, attach_term, n, getppid(), &attach_Mode) == 0) Panic(0, "Could not alloc display"); PanicPid = 0; #ifdef ENCODINGS D_encoding = nwin_options.encoding > 0 ? nwin_options.encoding : 0; debug1("D_encoding = %d\n", D_encoding); #endif } if (SockMatch) { /* user started us with -S option */ sprintf(socknamebuf, "%d.%s", (int)getpid(), SockMatch); } else { sprintf(socknamebuf, "%d.%s.%s", (int)getpid(), stripdev(attach_tty), HostName); } for (ap = socknamebuf; *ap; ap++) if (*ap == '/') *ap = '-'; #ifdef NAME_MAX if (strlen(socknamebuf) > NAME_MAX) { debug2("Socketname %s truncated to %d chars\n", socknamebuf, NAME_MAX); socknamebuf[NAME_MAX] = 0; } #endif sprintf(SockPath + strlen(SockPath), "/%s", socknamebuf); ServerSocket = MakeServerSocket(); InitKeytab(); #ifdef ETCSCREENRC # ifdef ALLOW_SYSSCREENRC if ((ap = getenv("SYSSCREENRC"))) (void)StartRc(ap, 0); else # endif (void)StartRc(ETCSCREENRC, 0); #endif (void)StartRc(RcFileName, 0); # ifdef UTMPOK # ifndef UTNOKEEP InitUtmp(); # endif /* UTNOKEEP */ # endif /* UTMPOK */ if (display) { if (InitTermcap(0, 0)) { debug("Could not init termcap - exiting\n"); fcntl(D_userfd, F_SETFL, 0); /* Flush sets FNBLOCK */ freetty(); if (D_userpid) Kill(D_userpid, SIG_BYE); eexit(1); } MakeDefaultCanvas(); InitTerm(0); #ifdef UTMPOK RemoveLoginSlot(); #endif } else MakeTermcap(1); #ifdef LOADAV InitLoadav(); #endif /* LOADAV */ MakeNewEnv(); signal(SIGHUP, SigHup); signal(SIGINT, FinitHandler); signal(SIGQUIT, FinitHandler); signal(SIGTERM, FinitHandler); #ifdef BSDJOBS signal(SIGTTIN, SIG_IGN); signal(SIGTTOU, SIG_IGN); #endif if (display) { brktty(D_userfd); SetMode(&D_OldMode, &D_NewMode, D_flow, iflag); /* Note: SetMode must be called _before_ FinishRc. */ SetTTY(D_userfd, &D_NewMode); if (fcntl(D_userfd, F_SETFL, FNBLOCK)) Msg(errno, "Warning: NBLOCK fcntl failed"); } else brktty(-1); /* just try */ signal(SIGCHLD, SigChld); #ifdef ETCSCREENRC # ifdef ALLOW_SYSSCREENRC if ((ap = getenv("SYSSCREENRC"))) FinishRc(ap); else # endif FinishRc(ETCSCREENRC); #endif FinishRc(RcFileName); debug2("UID %d EUID %d\n", (int)getuid(), (int)geteuid()); if (windows == NULL) { debug("We open one default window, as screenrc did not specify one.\n"); if (MakeWindow(&nwin) == -1) { fd_set rfd; struct timeval tv = { MsgWait/1000, 1000*(MsgWait%1000) }; FD_SET(0, &rfd); Msg(0, "Sorry, could not find a PTY or TTY."); // allow user to exit early by pressing any key. select(1, &rfd, NULL, NULL, &tv); Finit(0); /* NOTREACHED */ } } else if (ac) /* Screen was invoked with a command */ { MakeWindow(&nwin); } #ifdef HAVE_BRAILLE StartBraille(); #endif if (display && default_startup) display_copyright(); signal(SIGINT, SigInt); if (rflag && (rflag & 1) == 0 && !quietflag) { Msg(0, "New screen..."); rflag = 0; } serv_read.type = EV_READ; serv_read.fd = ServerSocket; serv_read.handler = serv_read_fn; evenq(&serv_read); serv_select.pri = -10; serv_select.type = EV_ALWAYS; serv_select.handler = serv_select_fn; evenq(&serv_select); logflushev.type = EV_TIMEOUT; logflushev.handler = logflush_fn; sched(); /* NOTREACHED */ return 0; } void WindowDied(p, wstat, wstat_valid) struct win *p; #ifdef BSDWAIT union wait wstat; #else int wstat; #endif int wstat_valid; { int killit = 0; if (p->w_destroyev.data == (char *)p) { wstat = p->w_exitstatus; wstat_valid = 1; evdeq(&p->w_destroyev); p->w_destroyev.data = 0; } #if defined(BSDJOBS) && !defined(BSDWAIT) if (!wstat_valid && p->w_pid > 0) { /* EOF on file descriptor. The process is probably also dead. * try a waitpid */ if (waitpid(p->w_pid, &wstat, WNOHANG | WUNTRACED) == p->w_pid) { p->w_pid = 0; wstat_valid = 1; } } #endif if (ZombieKey_destroy && ZombieKey_onerror && wstat_valid && WIFEXITED(wstat) && WEXITSTATUS(wstat) == 0) killit = 1; if (ZombieKey_destroy && !killit) { char buf[100], *s, reason[100]; time_t now; if (wstat_valid) { if (WIFEXITED(wstat)) if (WEXITSTATUS(wstat)) sprintf(reason, "terminated with exit status %d", WEXITSTATUS(wstat)); else sprintf(reason, "terminated normally"); else if (WIFSIGNALED(wstat)) sprintf(reason, "terminated with signal %d%s", WTERMSIG(wstat), #ifdef WCOREDUMP WCOREDUMP(wstat) ? " (core file generated)" : ""); #else ""); #endif } else sprintf(reason, "detached from window"); (void) time(&now); s = ctime(&now); if (s && *s) s[strlen(s) - 1] = '\0'; debug3("window %d (%s) going into zombie state fd %d", p->w_number, p->w_title, p->w_ptyfd); #ifdef UTMPOK if (p->w_slot != (slot_t)0 && p->w_slot != (slot_t)-1) { RemoveUtmp(p); p->w_slot = 0; /* "detached" */ } #endif CloseDevice(p); p->w_deadpid = p->w_pid; p->w_pid = 0; ResetWindow(p); /* p->w_y = p->w_bot; */ p->w_y = MFindUsedLine(p, p->w_bot, 1); sprintf(buf, "\n\r=== Command %s (%s) ===", reason, s ? s : "?"); WriteString(p, buf, strlen(buf)); WindowChanged(p, 'f'); } else KillWindow(p); #ifdef UTMPOK CarefulUtmp(); #endif } static void SigChldHandler() { struct stat st; #ifdef DEBUG fds(); #endif while (GotSigChld) { GotSigChld = 0; DoWait(); #ifdef SYSVSIGS signal(SIGCHLD, SigChld); #endif } if (stat(SockPath, &st) == -1) { debug1("SigChldHandler: Yuck! cannot stat '%s'\n", SockPath); if (!RecoverSocket()) { debug("SCREEN cannot recover from corrupt Socket, bye\n"); Finit(1); } else debug1("'%s' reconstructed\n", SockPath); } else debug2("SigChldHandler: stat '%s' o.k. (%03o)\n", SockPath, (int)st.st_mode); } static sigret_t SigChld SIGDEFARG { debug("SigChld()\n"); GotSigChld = 1; SIGRETURN; } sigret_t SigHup SIGDEFARG { /* Hangup all displays */ while ((display = displays) != 0) Hangup(); SIGRETURN; } /* * the backend's Interrupt handler * we cannot insert the intrc directly, as we never know * if fore is valid. */ static sigret_t SigInt SIGDEFARG { #if HAZARDOUS char ibuf; debug("SigInt()\n"); if (fore && displays) { # if defined(TERMIO) || defined(POSIX) ibuf = displays->d_OldMode.tio.c_cc[VINTR]; # else ibuf = displays->d_OldMode.m_tchars.t_intrc; # endif fore->w_inlen = 0; write(fore->w_ptyfd, &ibuf, 1); } #else signal(SIGINT, SigInt); debug("SigInt() careful\n"); InterruptPlease = 1; #endif SIGRETURN; } static sigret_t CoreDump SIGDEFARG { /* if running with s-bit, we must reset the s-bit, so that we get a * core file anyway. */ struct display *disp; char buf[80]; char *dump_msg = " (core dumped)"; int running_w_s_bit = getuid() != geteuid(); #if defined(SHADOWPW) && !defined(DEBUG) && !defined(DUMPSHADOW) if (running_w_s_bit) dump_msg = ""; #endif #if defined(SYSVSIGS) && defined(SIGHASARG) signal(sigsig, SIG_IGN); #endif setgid(getgid()); setuid(getuid()); unlink("core"); #ifdef SIGHASARG sprintf(buf, "\r\n[screen caught signal %d.%s]\r\n", sigsig, dump_msg); #else sprintf(buf, "\r\n[screen caught a fatal signal.%s]\r\n", dump_msg); #endif for (disp = displays; disp; disp = disp->d_next) { if (disp->d_nonblock < -1 || disp->d_nonblock > 1000000) continue; fcntl(disp->d_userfd, F_SETFL, 0); SetTTY(disp->d_userfd, &D_OldMode); write(disp->d_userfd, buf, strlen(buf)); Kill(disp->d_userpid, SIG_BYE); } if (running_w_s_bit) { #if defined(SHADOWPW) && !defined(DEBUG) && !defined(DUMPSHADOW) Kill(getpid(), SIGKILL); eexit(11); #else /* SHADOWPW && !DEBUG */ abort(); #endif /* SHADOWPW && !DEBUG */ } else abort(); SIGRETURN; } static void DoWait() { register int pid; struct win *p, *next; #ifdef BSDWAIT union wait wstat; #else int wstat; #endif #ifdef BSDJOBS # ifndef BSDWAIT while ((pid = waitpid(-1, &wstat, WNOHANG | WUNTRACED)) > 0) # else # ifdef USE_WAIT2 /* * From: rouilj@sni-usa.com (John Rouillard) * note that WUNTRACED is not documented to work, but it is defined in * /usr/include/sys/wait.h, so it may work */ while ((pid = wait2(&wstat, WNOHANG | WUNTRACED )) > 0) # else /* USE_WAIT2 */ while ((pid = wait3(&wstat, WNOHANG | WUNTRACED, (struct rusage *) 0)) > 0) # endif /* USE_WAIT2 */ # endif #else /* BSDJOBS */ while ((pid = wait(&wstat)) < 0) if (errno != EINTR) break; if (pid > 0) #endif /* BSDJOBS */ { for (p = windows; p; p = next) { next = p->w_next; if ( (p->w_pid && pid == p->w_pid) || (p->w_deadpid && pid == p->w_deadpid) ) { /* child has ceased to exist */ p->w_pid = 0; #ifdef BSDJOBS if (WIFSTOPPED(wstat)) { debug3("Window %d pid %d: WIFSTOPPED (sig %d)\n", p->w_number, pid, WSTOPSIG(wstat)); #ifdef SIGTTIN if (WSTOPSIG(wstat) == SIGTTIN) { Msg(0, "Suspended (tty input)"); continue; } #endif #ifdef SIGTTOU if (WSTOPSIG(wstat) == SIGTTOU) { Msg(0, "Suspended (tty output)"); continue; } #endif /* Try to restart process */ Msg(0, "Child has been stopped, restarting."); if (killpg(pid, SIGCONT)) kill(pid, SIGCONT); } else #endif { /* Screen will detect the window has died when the window's * file descriptor signals EOF (which it will do when the process in * the window terminates). So do this in a timeout of 10 seconds. * (not doing this at all might also work) * See #27061 for more details. */ p->w_destroyev.data = (char *)p; p->w_exitstatus = wstat; SetTimeout(&p->w_destroyev, 10 * 1000); evenq(&p->w_destroyev); } break; } #ifdef PSEUDOS if (p->w_pwin && pid == p->w_pwin->p_pid) { debug2("pseudo of win Nr %d died. pid == %d\n", p->w_number, p->w_pwin->p_pid); FreePseudowin(p); break; } #endif } if (p == 0) { debug1("pid %d not found - hope that's ok\n", pid); } } } static sigret_t FinitHandler SIGDEFARG { #ifdef SIGHASARG debug1("FinitHandler called, sig %d.\n", sigsig); #else debug("FinitHandler called.\n"); #endif Finit(1); SIGRETURN; } void Finit(i) int i; { signal(SIGCHLD, SIG_DFL); signal(SIGHUP, SIG_IGN); debug1("Finit(%d);\n", i); while (windows) { struct win *p = windows; windows = windows->w_next; FreeWindow(p); } if (ServerSocket != -1) { debug1("we unlink(%s)\n", SockPath); #ifdef USE_SETEUID xseteuid(real_uid); xsetegid(real_gid); #endif (void) unlink(SockPath); #ifdef USE_SETEUID xseteuid(eff_uid); xsetegid(eff_gid); #endif } for (display = displays; display; display = display->d_next) { if (D_status) RemoveStatus(); FinitTerm(); #ifdef UTMPOK RestoreLoginSlot(); #endif AddStr("[screen is terminating]\r\n"); Flush(3); SetTTY(D_userfd, &D_OldMode); fcntl(D_userfd, F_SETFL, 0); freetty(); Kill(D_userpid, SIG_BYE); } /* * we _cannot_ call eexit(i) here, * instead of playing with the Socket above. Sigh. */ exit(i); } void eexit(e) int e; { debug("eexit\n"); if (ServerSocket != -1) { debug1("we unlink(%s)\n", SockPath); setgid(real_gid); setuid(real_uid); (void) unlink(SockPath); } exit(e); } void Hangup() { if (display == 0) return; debug1("Hangup %x\n", display); if (D_userfd >= 0) { close(D_userfd); D_userfd = -1; } if (auto_detach || displays->d_next) Detach(D_HANGUP); else Finit(0); } /* * Detach now has the following modes: *D_DETACH SIG_BYE detach backend and exit attacher *D_HANGUP SIG_BYE detach backend and exit attacher *D_STOP SIG_STOP stop attacher (and detach backend) *D_REMOTE SIG_BYE remote detach -- reattach to new attacher *D_POWER SIG_POWER_BYE power detach -- attacher kills his parent *D_REMOTE_POWER SIG_POWER_BYE remote power detach -- both *D_LOCK SIG_LOCK lock the attacher * (jw) * we always remove our utmp slots. (even when "lock" or "stop") * Note: Take extra care here, we may be called by interrupt! */ void Detach(mode) int mode; { int sign = 0, pid; struct canvas *cv; struct win *p; if (display == 0) return; #define AddStrSock(msg) do { \ if (SockName) \ { \ AddStr("[" msg " from "); \ AddStr(SockName); \ AddStr("]\r\n"); \ } \ else \ AddStr("[" msg "]\r\n"); \ } while (0) signal(SIGHUP, SIG_IGN); debug1("Detach(%d)\n", mode); if (D_status) RemoveStatus(); FinitTerm(); if (!display) return; switch (mode) { case D_HANGUP: sign = SIG_BYE; break; case D_DETACH: AddStrSock("detached"); sign = SIG_BYE; break; #ifdef BSDJOBS case D_STOP: sign = SIG_STOP; break; #endif #ifdef REMOTE_DETACH case D_REMOTE: AddStrSock("remote detached"); sign = SIG_BYE; break; #endif #ifdef POW_DETACH case D_POWER: AddStrSock("power detached"); if (PowDetachString) { AddStr(PowDetachString); AddStr("\r\n"); } sign = SIG_POWER_BYE; break; #ifdef REMOTE_DETACH case D_REMOTE_POWER: AddStrSock("remote power detached"); if (PowDetachString) { AddStr(PowDetachString); AddStr("\r\n"); } sign = SIG_POWER_BYE; break; #endif #endif case D_LOCK: ClearAll(); sign = SIG_LOCK; /* tell attacher to lock terminal with a lockprg. */ break; } #ifdef UTMPOK if (displays->d_next == 0) { for (p = windows; p; p = p->w_next) { if (p->w_slot != (slot_t) -1 && !(p->w_lflag & 2)) { RemoveUtmp(p); /* * Set the slot to 0 to get the window * logged in again. */ p->w_slot = (slot_t) 0; } } } if (mode != D_HANGUP) RestoreLoginSlot(); #endif if (displays->d_next == 0 && console_window) { if (TtyGrabConsole(console_window->w_ptyfd, 0, "detach")) { debug("could not release console - killing window\n"); KillWindow(console_window); display = displays; /* restore display */ } } if (D_fore) { #ifdef MULTIUSER ReleaseAutoWritelock(display, D_fore); #endif D_user->u_detachwin = D_fore->w_number; D_user->u_detachotherwin = D_other ? D_other->w_number : -1; } AutosaveLayout(D_layout); layout_last = D_layout; for (cv = D_cvlist; cv; cv = cv->c_next) { p = Layer2Window(cv->c_layer); SetCanvasWindow(cv, 0); if (p) WindowChanged(p, 'u'); } pid = D_userpid; debug2("display: %#x displays: %#x\n", (unsigned int)display, (unsigned int)displays); FreeDisplay(); if (displays == 0) /* Flag detached-ness */ (void) chsock(); /* * tell father what to do. We do that after we * freed the tty, thus getty feels more comfortable on hpux * if it was a power detach. */ Kill(pid, sign); debug2("Detach: Signal %d to Attacher(%d)!\n", sign, pid); debug("Detach returns, we are successfully detached.\n"); signal(SIGHUP, SigHup); #undef AddStrSock } static int IsSymbol(e, s) char *e, *s; { register int l; l = strlen(s); return strncmp(e, s, l) == 0 && e[l] == '='; } void MakeNewEnv() { register char **op, **np; static char stybuf[MAXSTR]; for (op = environ; *op; ++op) ; if (NewEnv) free((char *)NewEnv); NewEnv = np = (char **) malloc((unsigned) (op - environ + 7 + 1) * sizeof(char **)); if (!NewEnv) Panic(0, "%s", strnomem); sprintf(stybuf, "STY=%s", strlen(SockName) <= MAXSTR - 5 ? SockName : "?"); *np++ = stybuf; /* NewEnv[0] */ *np++ = Term; /* NewEnv[1] */ np++; /* room for SHELL */ #ifdef TIOCSWINSZ np += 2; /* room for TERMCAP and WINDOW */ #else np += 4; /* room for TERMCAP WINDOW LINES COLUMNS */ #endif for (op = environ; *op; ++op) { if (!IsSymbol(*op, "TERM") && !IsSymbol(*op, "TERMCAP") && !IsSymbol(*op, "STY") && !IsSymbol(*op, "WINDOW") && !IsSymbol(*op, "SCREENCAP") && !IsSymbol(*op, "SHELL") && !IsSymbol(*op, "LINES") && !IsSymbol(*op, "COLUMNS") ) *np++ = *op; } *np = 0; } #if defined(USEVARARGS) && defined(__STDC__) #define DEFINE_VARARGS_FN(fnname) void fnname (int err, const char *fmt, VA_DOTS) #else #define DEFINE_VARARGS_FN(fnname) void fnname(err, fmt, VA_DOTS) \ int err; \ const char *fmt; \ VA_DECL #endif #define PROCESS_MESSAGE(B) do { \ char *p = B; \ VA_LIST(ap) \ VA_START(ap, fmt); \ fmt = DoNLS(fmt); \ (void)vsnprintf(p, sizeof(B) - 100, fmt, VA_ARGS(ap)); \ VA_END(ap); \ if (err) \ { \ p += strlen(p); \ *p++ = ':'; \ *p++ = ' '; \ strncpy(p, strerror(err), B + sizeof(B) - p - 1); \ B[sizeof(B) - 1] = 0; \ } \ } while (0) DEFINE_VARARGS_FN(Msg) { char buf[MAXPATHLEN*2]; PROCESS_MESSAGE(buf); debug2("Msg('%s') (%#x);\n", buf, (unsigned int)display); if (display && displays) MakeStatus(buf); else if (displays) { for (display = displays; display; display = display->d_next) MakeStatus(buf); } else if (display) { /* no displays but a display - must have forked. * send message to backend! */ char *tty = D_usertty; struct display *olddisplay = display; display = 0; /* only send once */ SendErrorMsg(tty, buf); display = olddisplay; } else printf("%s\r\n", buf); if (queryflag >= 0) write(queryflag, buf, strlen(buf)); } /* * Call FinitTerm for all displays, write a message to each and call eexit(); */ DEFINE_VARARGS_FN(Panic) { char buf[MAXPATHLEN*2]; PROCESS_MESSAGE(buf); debug3("Panic('%s'); display=%x displays=%x\n", buf, display, displays); if (displays == 0 && display == 0) { printf("%s\r\n", buf); if (PanicPid) Kill(PanicPid, SIG_BYE); } else if (displays == 0) { /* no displays but a display - must have forked. * send message to backend! */ char *tty = D_usertty; display = 0; SendErrorMsg(tty, buf); sleep(2); _exit(1); } else for (display = displays; display; display = display->d_next) { if (D_status) RemoveStatus(); FinitTerm(); Flush(3); #ifdef UTMPOK RestoreLoginSlot(); #endif SetTTY(D_userfd, &D_OldMode); fcntl(D_userfd, F_SETFL, 0); write(D_userfd, buf, strlen(buf)); write(D_userfd, "\n", 1); freetty(); if (D_userpid) Kill(D_userpid, SIG_BYE); } #ifdef MULTIUSER if (tty_oldmode >= 0) { # ifdef USE_SETEUID if (setuid(own_uid)) xseteuid(own_uid); /* may be a loop. sigh. */ # else setuid(own_uid); # endif debug1("Panic: changing back modes from %s\n", attach_tty); chmod(attach_tty, tty_oldmode); } #endif eexit(1); } DEFINE_VARARGS_FN(QueryMsg) { char buf[MAXPATHLEN*2]; if (queryflag < 0) return; PROCESS_MESSAGE(buf); write(queryflag, buf, strlen(buf)); } DEFINE_VARARGS_FN(Dummy) {} #undef PROCESS_MESSAGE #undef DEFINE_VARARGS_FN /* * '^' is allowed as an escape mechanism for control characters. jw. * * Added time insertion using ideas/code from /\ndy Jones * (andy@lingua.cltr.uq.OZ.AU) - thanks a lot! * */ #ifndef USE_LOCALE static const char days[] = "SunMonTueWedThuFriSat"; static const char months[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; #endif static char winmsg_buf[MAXSTR]; #define MAX_WINMSG_REND 256 /* rendition changes */ static int winmsg_rend[MAX_WINMSG_REND]; static int winmsg_rendpos[MAX_WINMSG_REND]; static int winmsg_numrend; static char * pad_expand(buf, p, numpad, padlen) char *buf; char *p; int numpad; int padlen; { char *pn, *pn2; int i, r; padlen = padlen - (p - buf); /* space for rent */ if (padlen < 0) padlen = 0; pn2 = pn = p + padlen; r = winmsg_numrend; while (p >= buf) { if (r && *p != 127 && p - buf == winmsg_rendpos[r - 1]) { winmsg_rendpos[--r] = pn - buf; continue; } *pn-- = *p; if (*p-- == 127) { pn[1] = ' '; i = numpad > 0 ? (padlen + numpad - 1) / numpad : 0; padlen -= i; while (i-- > 0) *pn-- = ' '; numpad--; if (r && p - buf == winmsg_rendpos[r - 1]) winmsg_rendpos[--r] = pn - buf; } } return pn2; } struct backtick { struct backtick *next; int num; int tick; int lifespan; time_t bestbefore; char result[MAXSTR]; char **cmdv; struct event ev; char *buf; int bufi; }; struct backtick *backticks; static void backtick_filter(bt) struct backtick *bt; { char *p, *q; int c; for (p = q = bt->result; (c = (unsigned char)*p++) != 0;) { if (c == '\t') c = ' '; if (c >= ' ' || c == '\005') *q++ = c; } *q = 0; } static void backtick_fn(ev, data) struct event *ev; char *data; { struct backtick *bt; int i, j, k, l; bt = (struct backtick *)data; debug1("backtick_fn for #%d\n", bt->num); i = bt->bufi; l = read(ev->fd, bt->buf + i, MAXSTR - i); if (l <= 0) { debug1("EOF on backtick #%d\n", bt->num); evdeq(ev); close(ev->fd); ev->fd = -1; return; } debug1("read %d bytes\n", l); i += l; for (j = 0; j < l; j++) if (bt->buf[i - j - 1] == '\n') break; if (j < l) { for (k = i - j - 2; k >= 0; k--) if (bt->buf[k] == '\n') break; k++; bcopy(bt->buf + k, bt->result, i - j - k); bt->result[i - j - k - 1] = 0; backtick_filter(bt); WindowChanged(0, '`'); } if (j == l && i == MAXSTR) { j = MAXSTR/2; l = j + 1; } if (j < l) { if (j) bcopy(bt->buf + i - j, bt->buf, j); i = j; } bt->bufi = i; } void setbacktick(num, lifespan, tick, cmdv) int num; int lifespan; int tick; char **cmdv; { struct backtick **btp, *bt; char **v; debug1("setbacktick called for backtick #%d\n", num); for (btp = &backticks; (bt = *btp) != 0; btp = &bt->next) if (bt->num == num) break; if (!bt && !cmdv) return; if (bt) { for (v = bt->cmdv; *v; v++) free(*v); free(bt->cmdv); if (bt->buf) free(bt->buf); if (bt->ev.fd >= 0) close(bt->ev.fd); evdeq(&bt->ev); } if (bt && !cmdv) { *btp = bt->next; free(bt); return; } if (!bt) { bt = (struct backtick *)malloc(sizeof *bt); if (!bt) { Msg(0, "%s", strnomem); return; } bzero(bt, sizeof(*bt)); bt->next = 0; *btp = bt; } bt->num = num; bt->tick = tick; bt->lifespan = lifespan; bt->bestbefore = 0; bt->result[0] = 0; bt->buf = 0; bt->bufi = 0; bt->cmdv = cmdv; bt->ev.fd = -1; if (bt->tick == 0 && bt->lifespan == 0) { debug("setbacktick: continuous mode\n"); bt->buf = (char *)malloc(MAXSTR); if (bt->buf == 0) { Msg(0, "%s", strnomem); setbacktick(num, 0, 0, (char **)0); return; } bt->ev.type = EV_READ; bt->ev.fd = readpipe(bt->cmdv); bt->ev.handler = backtick_fn; bt->ev.data = (char *)bt; if (bt->ev.fd >= 0) evenq(&bt->ev); } } static char * runbacktick(bt, tickp, now) struct backtick *bt; int *tickp; time_t now; { int f, i, l, j; time_t now2; debug1("runbacktick called for backtick #%d\n", bt->num); if (bt->tick && (!*tickp || bt->tick < *tickp)) *tickp = bt->tick; if ((bt->lifespan == 0 && bt->tick == 0) || now < bt->bestbefore) { debug1("returning old result (%d)\n", bt->lifespan); return bt->result; } f = readpipe(bt->cmdv); if (f == -1) return bt->result; i = 0; while ((l = read(f, bt->result + i, sizeof(bt->result) - i)) > 0) { debug1("runbacktick: read %d bytes\n", l); i += l; for (j = 1; j < l; j++) if (bt->result[i - j - 1] == '\n') break; if (j == l && i == sizeof(bt->result)) { j = sizeof(bt->result) / 2; l = j + 1; } if (j < l) { bcopy(bt->result + i - j, bt->result, j); i = j; } } close(f); bt->result[sizeof(bt->result) - 1] = '\n'; if (i && bt->result[i - 1] == '\n') i--; debug1("runbacktick: finished, %d bytes\n", i); bt->result[i] = 0; backtick_filter(bt); (void)time(&now2); bt->bestbefore = now2 + bt->lifespan; return bt->result; } int AddWinMsgRend(str, r) const char *str; int r; { if (winmsg_numrend >= MAX_WINMSG_REND || str < winmsg_buf || str >= winmsg_buf + MAXSTR) return -1; winmsg_rend[winmsg_numrend] = r; winmsg_rendpos[winmsg_numrend] = str - winmsg_buf; winmsg_numrend++; return 0; } char * MakeWinMsgEv(str, win, esc, padlen, ev, rec) char *str; struct win *win; int esc; int padlen; struct event *ev; int rec; { static int tick; char *s = str; register char *p = winmsg_buf; register int ctrl; struct timeval now; struct tm *tm; int l, i, r; int num; int zeroflg; int longflg; int minusflg; int plusflg; int qmflag = 0, omflag = 0, qmnumrend = 0; char *qmpos = 0; int numpad = 0; int lastpad = 0; int truncpos = -1; int truncper = 0; int trunclong = 0; struct backtick *bt = NULL; if (winmsg_numrend >= 0) winmsg_numrend = 0; else winmsg_numrend = -winmsg_numrend; tick = 0; tm = 0; ctrl = 0; gettimeofday(&now, NULL); for (; *s && (l = winmsg_buf + MAXSTR - 1 - p) > 0; s++, p++) { *p = *s; if (ctrl) { ctrl = 0; if (*s != '^' && *s >= 64) *p &= 0x1f; continue; } if (*s != esc) { if (esc == '%') { switch (*s) { #if 0 case '~': *p = BELL; break; #endif case '^': ctrl = 1; *p-- = '^'; break; default: break; } } continue; } if (*++s == esc) /* double escape ? */ continue; if ((plusflg = *s == '+') != 0) s++; if ((minusflg = *s == '-') != 0) s++; if ((zeroflg = *s == '0') != 0) s++; num = 0; while(*s >= '0' && *s <= '9') num = num * 10 + (*s++ - '0'); if ((longflg = *s == 'L') != 0) s++; switch (*s) { case '?': p--; if (qmpos) { if ((!qmflag && !omflag) || omflag == 1) { p = qmpos; if (qmnumrend < winmsg_numrend) winmsg_numrend = qmnumrend; } qmpos = 0; break; } qmpos = p; qmnumrend = winmsg_numrend; qmflag = omflag = 0; break; case ':': p--; if (!qmpos) break; if (qmflag && omflag != 1) { omflag = 1; qmpos = p; qmnumrend = winmsg_numrend; } else { p = qmpos; if (qmnumrend < winmsg_numrend) winmsg_numrend = qmnumrend; omflag = -1; } break; case 'd': case 'D': case 'm': case 'M': case 'y': case 'Y': case 'a': case 'A': case 's': case 'c': case 'C': if (l < 4) break; if (tm == 0) { time_t nowsec = now.tv_sec; tm = localtime(&nowsec); } qmflag = 1; if (!tick || tick > 3600) tick = 3600; switch (*s) { case 'd': sprintf(p, "%02d", tm->tm_mday % 100); break; case 'D': #ifdef USE_LOCALE strftime(p, l, (longflg ? "%A" : "%a"), tm); #else sprintf(p, "%3.3s", days + 3 * tm->tm_wday); #endif break; case 'm': sprintf(p, "%02d", tm->tm_mon + 1); break; case 'M': #ifdef USE_LOCALE strftime(p, l, (longflg ? "%B" : "%b"), tm); #else sprintf(p, "%3.3s", months + 3 * tm->tm_mon); #endif break; case 'y': sprintf(p, "%02d", tm->tm_year % 100); break; case 'Y': sprintf(p, "%04d", tm->tm_year + 1900); break; case 'a': sprintf(p, tm->tm_hour >= 12 ? "pm" : "am"); break; case 'A': sprintf(p, tm->tm_hour >= 12 ? "PM" : "AM"); break; case 's': sprintf(p, "%02d", tm->tm_sec); tick = 1; break; case 'c': sprintf(p, zeroflg ? "%02d:%02d" : "%2d:%02d", tm->tm_hour, tm->tm_min); if (!tick || tick > 60) tick = 60; break; case 'C': sprintf(p, zeroflg ? "%02d:%02d" : "%2d:%02d", (tm->tm_hour + 11) % 12 + 1, tm->tm_min); if (!tick || tick > 60) tick = 60; break; default: break; } p += strlen(p) - 1; break; case 'l': #ifdef LOADAV *p = 0; if (l > 20) AddLoadav(p); if (*p) { qmflag = 1; p += strlen(p) - 1; } else *p = '?'; if (!tick || tick > 60) tick = 60; #else *p = '?'; #endif p += strlen(p) - 1; break; case '`': case 'h': if (rec >= 10 || (*s == 'h' && (win == 0 || win->w_hstatus == 0 || *win->w_hstatus == 0))) { p--; break; } if (*s == '`') { for (bt = backticks; bt; bt = bt->next) if (bt->num == num) break; if (bt == 0) { p--; break; } } { char savebuf[sizeof(winmsg_buf)]; int oldtick = tick; int oldnumrend = winmsg_numrend; *p = 0; strcpy(savebuf, winmsg_buf); winmsg_numrend = -winmsg_numrend; MakeWinMsgEv(*s == 'h' ? win->w_hstatus : runbacktick(bt, &oldtick, now.tv_sec), win, '\005', 0, (struct event *)0, rec + 1); debug2("oldtick=%d tick=%d\n", oldtick, tick); if (!tick || oldtick < tick) tick = oldtick; if ((int)strlen(winmsg_buf) < l) strcat(savebuf, winmsg_buf); strcpy(winmsg_buf, savebuf); while (oldnumrend < winmsg_numrend) winmsg_rendpos[oldnumrend++] += p - winmsg_buf; if (*p) qmflag = 1; p += strlen(p) - 1; } break; case 'w': case 'W': { struct win *oldfore = 0; char *ss; if (display) { oldfore = D_fore; D_fore = win; } ss = AddWindows(p, l - 1, (*s == 'w' ? 0 : 1) | (longflg ? 0 : 2) | (plusflg ? 4 : 0) | (minusflg ? 8 : 0), win ? win->w_number : -1); if (display) D_fore = oldfore; } if (*p) qmflag = 1; p += strlen(p) - 1; break; case 'u': *p = 0; if (win) AddOtherUsers(p, l - 1, win); if (*p) qmflag = 1; p += strlen(p) - 1; break; case 'f': *p = 0; if (win) AddWindowFlags(p, l - 1, win); if (*p) qmflag = 1; p += strlen(p) - 1; break; case 't': *p = 0; if (win && (int)strlen(win->w_title) < l) { strcpy(p, win->w_title); if (*p) qmflag = 1; } p += strlen(p) - 1; break; case '{': { char rbuf[128]; s++; for (i = 0; i < 127; i++) if (s[i] && s[i] != '}') rbuf[i] = s[i]; else break; if (s[i] == '}' && winmsg_numrend < MAX_WINMSG_REND) { r = -1; rbuf[i] = 0; debug1("MakeWinMsg attrcolor %s\n", rbuf); if (i != 1 || rbuf[0] != '-') r = ParseAttrColor(rbuf, (char *)0, 0); if (r != -1 || (i == 1 && rbuf[0] == '-')) { winmsg_rend[winmsg_numrend] = r; winmsg_rendpos[winmsg_numrend] = p - winmsg_buf; winmsg_numrend++; } } s += i; p--; } break; case 'H': *p = 0; if ((int)strlen(HostName) < l) { strcpy(p, HostName); if (*p) qmflag = 1; } p += strlen(p) - 1; break; case 'S': { char *session_name; *p = 0; session_name = strchr(SockName, '.') + 1; if ((int)strlen(session_name) < l) { strcpy(p, session_name); if (*p) qmflag = 1; } p += strlen(p) - 1; } break; case 'p': { sprintf(p, "%d", (plusflg && display) ? D_userpid : getpid()); p += strlen(p) - 1; } break; case 'F': p--; /* small hack */ if (display && ((ev && ev == &D_forecv->c_captev) || (!ev && win && win == D_fore))) minusflg = !minusflg; if (minusflg) qmflag = 1; break; case 'P': p--; #ifdef COPY_PASTE if (display && ev && ev != &D_hstatusev) /* Hack */ { /* Is the layer in the current canvas in copy mode? */ struct canvas *cv = (struct canvas *)ev->data; if (ev == &cv->c_captev && cv->c_layer->l_layfn == &MarkLf) qmflag = 1; } #endif break; case 'E': p--; if (display && D_ESCseen) qmflag = 1; break; case '>': truncpos = p - winmsg_buf; truncper = num > 100 ? 100 : num; trunclong = longflg; p--; break; case '=': case '<': *p = ' '; if (num || zeroflg || plusflg || longflg || (*s != '=')) { /* expand all pads */ if (minusflg) { num = (plusflg ? lastpad : padlen) - num; if (!plusflg && padlen == 0) num = p - winmsg_buf; plusflg = 0; } else if (!zeroflg) { if (*s != '=' && num == 0 && !plusflg) num = 100; if (num > 100) num = 100; if (padlen == 0) num = p - winmsg_buf; else num = (padlen - (plusflg ? lastpad : 0)) * num / 100; } if (num < 0) num = 0; if (plusflg) num += lastpad; if (num > MAXSTR - 1) num = MAXSTR - 1; if (numpad) p = pad_expand(winmsg_buf, p, numpad, num); numpad = 0; if (p - winmsg_buf > num && !longflg) { int left, trunc; if (truncpos == -1) { truncpos = lastpad; truncper = 0; } trunc = lastpad + truncper * (num - lastpad) / 100; if (trunc > num) trunc = num; if (trunc < lastpad) trunc = lastpad; left = truncpos - trunc; if (left > p - winmsg_buf - num) left = p - winmsg_buf - num; debug1("lastpad = %d, ", lastpad); debug3("truncpos = %d, trunc = %d, left = %d\n", truncpos, trunc, left); if (left > 0) { if (left + lastpad > p - winmsg_buf) left = p - winmsg_buf - lastpad; if (p - winmsg_buf - lastpad - left > 0) bcopy(winmsg_buf + lastpad + left, winmsg_buf + lastpad, p - winmsg_buf - lastpad - left); p -= left; r = winmsg_numrend; while (r && winmsg_rendpos[r - 1] > lastpad) { r--; winmsg_rendpos[r] -= left; if (winmsg_rendpos[r] < lastpad) winmsg_rendpos[r] = lastpad; } if (trunclong) { if (p - winmsg_buf > lastpad) winmsg_buf[lastpad] = '.'; if (p - winmsg_buf > lastpad + 1) winmsg_buf[lastpad + 1] = '.'; if (p - winmsg_buf > lastpad + 2) winmsg_buf[lastpad + 2] = '.'; } } if (p - winmsg_buf > num) { p = winmsg_buf + num; if (trunclong) { if (num - 1 >= lastpad) p[-1] = '.'; if (num - 2 >= lastpad) p[-2] = '.'; if (num - 3 >= lastpad) p[-3] = '.'; } r = winmsg_numrend; while (r && winmsg_rendpos[r - 1] > num) winmsg_rendpos[--r] = num; } truncpos = -1; trunclong = 0; if (lastpad > p - winmsg_buf) lastpad = p - winmsg_buf; debug1("lastpad now %d\n", lastpad); } if (*s == '=') { while (p - winmsg_buf < num) *p++ = ' '; lastpad = p - winmsg_buf; truncpos = -1; trunclong = 0; debug1("lastpad2 now %d\n", lastpad); } p--; } else if (padlen) { *p = 127; /* internal pad representation */ numpad++; } break; case 'n': s++; /* FALLTHROUGH */ default: s--; if (l > 10 + num) { if (num == 0) num = 1; if (!win) sprintf(p, "%*s", num, num > 1 ? "--" : "-"); else sprintf(p, "%*d", num, win->w_number); qmflag = 1; p += strlen(p) - 1; } break; } } if (qmpos && !qmflag) p = qmpos + 1; *p = '\0'; if (numpad) { if (padlen > MAXSTR - 1) padlen = MAXSTR - 1; p = pad_expand(winmsg_buf, p, numpad, padlen); } if (ev) { evdeq(ev); /* just in case */ ev->timeout.tv_sec = 0; ev->timeout.tv_usec = 0; } if (ev && tick) { now.tv_usec = 100000; if (tick == 1) now.tv_sec++; else now.tv_sec += tick - (now.tv_sec % tick); ev->timeout = now; debug2("NEW timeout %d %d\n", ev->timeout.tv_sec, tick); } return winmsg_buf; } char * MakeWinMsg(s, win, esc) char *s; struct win *win; int esc; { return MakeWinMsgEv(s, win, esc, 0, (struct event *)0, 0); } void PutWinMsg(s, start, max) char *s; int start, max; { int i, p, l, r, n; struct mchar rend; struct mchar rendstack[MAX_WINMSG_REND]; int rendstackn = 0; if (s != winmsg_buf) { /* sorry, no fancy coloring available */ debug1("PutWinMsg %s plain\n", s); l = strlen(s); if (l > max) l = max; l -= start; s += start; while (l-- > 0) PUTCHARLP(*s++); return; } rend = D_rend; p = 0; l = strlen(s); debug2("PutWinMsg %s start attr %x\n", s, rend.attr); for (i = 0; i < winmsg_numrend && max > 0; i++) { if (p > winmsg_rendpos[i] || winmsg_rendpos[i] > l) break; if (p < winmsg_rendpos[i]) { n = winmsg_rendpos[i] - p; if (n > max) n = max; max -= n; p += n; while(n-- > 0) { if (start-- > 0) s++; else PUTCHARLP(*s++); } } r = winmsg_rend[i]; if (r == -1) { if (rendstackn > 0) rend = rendstack[--rendstackn]; } else { rendstack[rendstackn++] = rend; ApplyAttrColor(r, &rend); } SetRendition(&rend); } if (p < l) { n = l - p; if (n > max) n = max; while(n-- > 0) { if (start-- > 0) s++; else PUTCHARLP(*s++); } } } #ifdef DEBUG static void fds1(i, j) int i, j; { while (i < j) { debug1("%d ", i); i++; } if ((j = open("/dev/null", 0)) >= 0) { fds1(i + 1, j); close(j); } else { while (dup(++i) < 0 && errno != EBADF) debug1("%d ", i); debug1(" [%d]\n", i); } } static void fds() { debug("fds: "); fds1(-1, -1); } #endif static void serv_read_fn(ev, data) struct event *ev; char *data; { debug("Knock - knock!\n"); ReceiveMsg(); } static void serv_select_fn(ev, data) struct event *ev; char *data; { struct win *p; debug("serv_select_fn called\n"); /* XXX: messages?? */ if (GotSigChld) { SigChldHandler(); } if (InterruptPlease) { debug("Backend received interrupt\n"); /* This approach is rather questionable in a multi-display * environment */ if (fore && displays) { #if defined(TERMIO) || defined(POSIX) char ibuf = displays->d_OldMode.tio.c_cc[VINTR]; #else char ibuf = displays->d_OldMode.m_tchars.t_intrc; #endif #ifdef PSEUDOS write(W_UWP(fore) ? fore->w_pwin->p_ptyfd : fore->w_ptyfd, &ibuf, 1); debug1("Backend wrote interrupt to %d", fore->w_number); debug1("%s\n", W_UWP(fore) ? " (pseudowin)" : ""); #else write(fore->w_ptyfd, &ibuf, 1); debug1("Backend wrote interrupt to %d\n", fore->w_number); #endif } InterruptPlease = 0; } for (p = windows; p; p = p->w_next) { if (p->w_bell == BELL_FOUND || p->w_bell == BELL_VISUAL) { struct canvas *cv; int visual = p->w_bell == BELL_VISUAL || visual_bell; p->w_bell = BELL_ON; for (display = displays; display; display = display->d_next) { for (cv = D_cvlist; cv; cv = cv->c_next) if (cv->c_layer->l_bottom == &p->w_layer) break; if (cv == 0) { p->w_bell = BELL_DONE; Msg(0, "%s", MakeWinMsg(BellString, p, '%')); } else if (visual && !D_VB && (!D_status || !D_status_bell)) { Msg(0, "%s", VisualBellString); if (D_status) { D_status_bell = 1; debug1("using vbell timeout %d\n", VBellWait); SetTimeout(&D_statusev, VBellWait ); } } } /* don't annoy the user with two messages */ if (p->w_monitor == MON_FOUND) p->w_monitor = MON_DONE; WindowChanged(p, 'f'); } if (p->w_monitor == MON_FOUND) { struct canvas *cv; p->w_monitor = MON_ON; for (display = displays; display; display = display->d_next) { for (cv = D_cvlist; cv; cv = cv->c_next) if (cv->c_layer->l_bottom == &p->w_layer) break; if (cv) continue; /* user already sees window */ #ifdef MULTIUSER if (!(ACLBYTE(p->w_mon_notify, D_user->u_id) & ACLBIT(D_user->u_id))) continue; /* user doesn't care */ #endif Msg(0, "%s", MakeWinMsg(ActivityString, p, '%')); p->w_monitor = MON_DONE; } WindowChanged(p, 'f'); } if (p->w_silence == SILENCE_FOUND) { /* Unset the flag if the user switched to this window. */ if (p->w_layer.l_cvlist) { p->w_silence = SILENCE_ON; WindowChanged(p, 'f'); } } } for (display = displays; display; display = display->d_next) { struct canvas *cv; if (D_status == STATUS_ON_WIN) continue; /* XXX: should use display functions! */ for (cv = D_cvlist; cv; cv = cv->c_next) { int lx, ly; /* normalize window, see resize.c */ lx = cv->c_layer->l_x; ly = cv->c_layer->l_y; if (lx == cv->c_layer->l_width) lx--; if (ly + cv->c_yoff < cv->c_ys) { int i, n = cv->c_ys - (ly + cv->c_yoff); cv->c_yoff = cv->c_ys - ly; RethinkViewportOffsets(cv); if (n > cv->c_layer->l_height) n = cv->c_layer->l_height; CV_CALL(cv, LScrollV(flayer, -n, 0, flayer->l_height - 1, 0); LayRedisplayLine(-1, -1, -1, 1); for (i = 0; i < n; i++) LayRedisplayLine(i, 0, flayer->l_width - 1, 1); if (cv == cv->c_display->d_forecv) LaySetCursor(); ); } else if (ly + cv->c_yoff > cv->c_ye) { int i, n = ly + cv->c_yoff - cv->c_ye; cv->c_yoff = cv->c_ye - ly; RethinkViewportOffsets(cv); if (n > cv->c_layer->l_height) n = cv->c_layer->l_height; CV_CALL(cv, LScrollV(flayer, n, 0, cv->c_layer->l_height - 1, 0); LayRedisplayLine(-1, -1, -1, 1); for (i = 0; i < n; i++) LayRedisplayLine(i + flayer->l_height - n, 0, flayer->l_width - 1, 1); if (cv == cv->c_display->d_forecv) LaySetCursor(); ); } if (lx + cv->c_xoff < cv->c_xs) { int i, n = cv->c_xs - (lx + cv->c_xoff); if (n < (cv->c_xe - cv->c_xs + 1) / 2) n = (cv->c_xe - cv->c_xs + 1) / 2; if (cv->c_xoff + n > cv->c_xs) n = cv->c_xs - cv->c_xoff; cv->c_xoff += n; RethinkViewportOffsets(cv); if (n > cv->c_layer->l_width) n = cv->c_layer->l_width; CV_CALL(cv, LayRedisplayLine(-1, -1, -1, 1); for (i = 0; i < flayer->l_height; i++) { LScrollH(flayer, -n, i, 0, flayer->l_width - 1, 0, 0); LayRedisplayLine(i, 0, n - 1, 1); } if (cv == cv->c_display->d_forecv) LaySetCursor(); ); } else if (lx + cv->c_xoff > cv->c_xe) { int i, n = lx + cv->c_xoff - cv->c_xe; if (n < (cv->c_xe - cv->c_xs + 1) / 2) n = (cv->c_xe - cv->c_xs + 1) / 2; if (cv->c_xoff - n + cv->c_layer->l_width - 1 < cv->c_xe) n = cv->c_xoff + cv->c_layer->l_width - 1 - cv->c_xe; cv->c_xoff -= n; RethinkViewportOffsets(cv); if (n > cv->c_layer->l_width) n = cv->c_layer->l_width; CV_CALL(cv, LayRedisplayLine(-1, -1, -1, 1); for (i = 0; i < flayer->l_height; i++) { LScrollH(flayer, n, i, 0, flayer->l_width - 1, 0, 0); LayRedisplayLine(i, flayer->l_width - n, flayer->l_width - 1, 1); } if (cv == cv->c_display->d_forecv) LaySetCursor(); ); } } } for (display = displays; display; display = display->d_next) { if (D_status == STATUS_ON_WIN || D_cvlist == 0 || D_cvlist->c_next == 0) continue; debug1("serv_select_fn: Restore on cv %#x\n", (int)D_forecv); CV_CALL(D_forecv, LayRestore();LaySetCursor()); } } static void logflush_fn(ev, data) struct event *ev; char *data; { struct win *p; char *buf; int n; if (!islogfile(NULL)) return; /* no more logfiles */ logfflush(NULL); n = log_flush ? log_flush : (logtstamp_after + 4) / 5; if (n) { SetTimeout(ev, n * 1000); evenq(ev); /* re-enqueue ourself */ } if (!logtstamp_on) return; /* write fancy time-stamp */ for (p = windows; p; p = p->w_next) { if (!p->w_log) continue; p->w_logsilence += n; if (p->w_logsilence < logtstamp_after) continue; if (p->w_logsilence - n >= logtstamp_after) continue; buf = MakeWinMsg(logtstamp_string, p, '%'); logfwrite(p->w_log, buf, strlen(buf)); } } /* * Interprets ^?, ^@ and other ^-control-char notation. * Interprets \ddd octal notation * * The result is placed in *cp, p is advanced behind the parsed expression and * returned. */ static char * ParseChar(p, cp) char *p, *cp; { if (*p == 0) return 0; if (*p == '^' && p[1]) { if (*++p == '?') *cp = '\177'; else if (*p >= '@') *cp = Ctrl(*p); else return 0; ++p; } else if (*p == '\\' && *++p <= '7' && *p >= '0') { *cp = 0; do *cp = *cp * 8 + *p - '0'; while (*++p <= '7' && *p >= '0'); } else *cp = *p++; return p; } static int ParseEscape(p) char *p; { unsigned char buf[2]; if (*p == 0) SetEscape((struct acluser *)0, -1, -1); else { if ((p = ParseChar(p, (char *)buf)) == NULL || (p = ParseChar(p, (char *)buf+1)) == NULL || *p) return -1; SetEscape((struct acluser *)0, buf[0], buf[1]); } return 0; } screen-4.1.0/HACKING0000644000175000017500000000343011642704565012034 0ustar abeabeWIP notes on hacking the Screen source. * Screen commands are handled by the DoAction function in process.c. The local variable nr is set to an integer value representing the command to be evaluated; for every command `foo', there is an integer value RC_FOO for use as nr's value to represent it. Find the matching case label to follow procesing of the command. The RC_FOO values are defined in comm.h, which is automatically generated by comm.sh, based on the names of the commands themselves (found in comm.c). * The current display is held in the global variable "display". Variable names like D_foo are shorthands for display->d_foo (where d_foo is a member of "struct display"). * Names like D_IS, D_TI, D_SG usually refer to the values of various termcap features of the current display. These are found in term.h, which is automatically generated from term.c by term.sh. * The main input-reading function for handling user input from a display, is disp_readev_fn in display.c. This also handles automatic transformation of mouse-tracking codes from display coordinates to screen-window coordinates, and decodes characters from the display's encoding, passing it on to the foreground input processor. Input is passed through ProcessInput in process.c to handle keybindings (specified by bindkey and such), and then processed by layer-specific input-processing functions, which you'll find in instances of struct LayFuncs. For instance, keystrokes are processed by: normal windows: WinPrGocess window in copy-mode: MarkProcess window list: WListProcess command input line: InpProcess * Handling string escapes (in hardstatus and the like), such as %w or %{= bw}, is done in screen.c, MakeWinMsgEv(). screen-4.1.0/utf8encodings/0000755000175000017500000000000011642704565013625 5ustar abeabescreen-4.1.0/utf8encodings/030000644000175000017500000010023611642704565013774 0ustar abeabeScreenI2UTF8 KSC 5601-1992!!0!"0!#0!$·!% %!& &!'¨!(0!)­!* !+"%!,ÿ±!?×!@÷!A"`!B"d!C"e!D"!E"4!F°!G 2!H 3!I!!J!+!Kÿà!Lÿá!Mÿå!N&B!O&@!P" !Q"¥!R#!S"!T"!U"a!V"R!W§!X ;!Y&!Z&![%Ë!\%Ï!]%Î!^%Ç!_%Æ!`%¡!a% !b%³!c%²!d%½!e%¼!f!’!g!!h!‘!i!“!j!”!k0!l"j!m"k!n"!o"=!p"!q"5!r"+!s",!t"!u" !v"†!w"‡!x"‚!y"ƒ!z"*!{")!|"'!}"(!~ÿâ"!!Ò""!Ô"#""$""%´"&ÿ^"'Ç"(Ø")Ý"*Ú"+Ù",¸"-Û".¡"/¿"0Ð"1"."2""3""4¤"5! "6 0"7%Á"8%À"9%·":%¶";&d"<&`"=&a">&e"?&g"@&c"A"™"B%È"C%£"D%Ð"E%Ñ"F%’"G%¤"H%¥"I%¨"J%§"K%¦"L%©"M&h"N&"O&"P&"Q&"R¶"S "T !"U!•"V!—"W!™"X!–"Y!˜"Z&m"[&i"\&j"]&l"^2"_2"`!"a3Ç"b!""c3Â"d3Ø"e!!#!ÿ#"ÿ##ÿ#$ÿ#%ÿ#&ÿ#'ÿ#(ÿ#)ÿ #*ÿ #+ÿ #,ÿ #-ÿ #.ÿ#/ÿ#0ÿ#1ÿ#2ÿ#3ÿ#4ÿ#5ÿ#6ÿ#7ÿ#8ÿ#9ÿ#:ÿ#;ÿ#<ÿ#=ÿ#>ÿ#?ÿ#@ÿ #Aÿ!#Bÿ"#Cÿ##Dÿ$#Eÿ%#Fÿ&#Gÿ'#Hÿ(#Iÿ)#Jÿ*#Kÿ+#Lÿ,#Mÿ-#Nÿ.#Oÿ/#Pÿ0#Qÿ1#Rÿ2#Sÿ3#Tÿ4#Uÿ5#Vÿ6#Wÿ7#Xÿ8#Yÿ9#Zÿ:#[ÿ;#\ÿæ#]ÿ=#^ÿ>#_ÿ?#`ÿ@#aÿA#bÿB#cÿC#dÿD#eÿE#fÿF#gÿG#hÿH#iÿI#jÿJ#kÿK#lÿL#mÿM#nÿN#oÿO#pÿP#qÿQ#rÿR#sÿS#tÿT#uÿU#vÿV#wÿW#xÿX#yÿY#zÿZ#{ÿ[#|ÿ\#}ÿ]#~ÿã$!11$"12$#13$$14$%15$&16$'17$(18$)19$*1:$+1;$,1<$-1=$.1>$/1?$01@$11A$21B$31C$41D$51E$61F$71G$81H$91I$:1J$;1K$<1L$=1M$>1N$?1O$@1P$A1Q$B1R$C1S$D1T$E1U$F1V$G1W$H1X$I1Y$J1Z$K1[$L1\$M1]$N1^$O1_$P1`$Q1a$R1b$S1c$T1d$U1e$V1f$W1g$X1h$Y1i$Z1j$[1k$\1l$]1m$^1n$_1o$`1p$a1q$b1r$c1s$d1t$e1u$f1v$g1w$h1x$i1y$j1z$k1{$l1|$m1}$n1~$o1$p1€$q1$r1‚$s1ƒ$t1„$u1…$v1†$w1‡$x1ˆ$y1‰$z1Š${1‹$|1Œ$}1$~1Ž%!!p%"!q%#!r%$!s%%!t%&!u%'!v%(!w%)!x%*!y%0!`%1!a%2!b%3!c%4!d%5!e%6!f%7!g%8!h%9!i%A‘%B’%C“%D”%E•%F–%G—%H˜%I™%Jš%K›%Lœ%M%Nž%OŸ%P %Q¡%R£%S¤%T¥%U¦%V§%W¨%X©%a±%b²%c³%d´%eµ%f¶%g·%h¸%i¹%jº%k»%l¼%m½%n¾%o¿%pÀ%qÁ%rÃ%sÄ%tÅ%uÆ%vÇ%wÈ%xÉ&!%&"%&#% &$%&%%&&%&'%&(%,&)%$&*%4&+%<&,%&-%&.%&/%&0%&1%&2%#&3%3&4%+&5%;&6%K&7% &8%/&9%(&:%7&;%?&<%&=%0&>%%&?%8&@%B&A%&B%&C%&D%&E%&F%&G%&H% &I%&J%&K%!&L%"&M%&&N%'&O%)&P%*&Q%-&R%.&S%1&T%2&U%5&V%6&W%9&X%:&Y%=&Z%>&[%@&\%A&]%C&^%D&_%E&`%F&a%G&b%H&c%I&d%J'!3•'"3–'#3—'$!'%3˜'&3Ä''3£'(3¤')3¥'*3¦'+3™',3š'-3›'.3œ'/3'03ž'13Ÿ'23 '33¡'43¢'53Ê'63'73Ž'83'93Ï':3ˆ';3‰'<3È'=3§'>3¨'?3°'@3±'A3²'B3³'C3´'D3µ'E3¶'F3·'G3¸'H3¹'I3€'J3'K3‚'L3ƒ'M3„'N3º'O3»'P3¼'Q3½'R3¾'S3¿'T3'U3‘'V3’'W3“'X3”'Y!&'Z3À'[3Á'\3Š']3‹'^3Œ'_3Ö'`3Å'a3­'b3®'c3¯'d3Û'e3©'f3ª'g3«'h3¬'i3Ý'j3Ð'k3Ó'l3Ã'm3É'n3Ü'o3Æ(!Æ("Ð(#ª($&(&2((?()A(*Ø(+R(,º(-Þ(.f(/J(12`(22a(32b(42c(52d(62e(72f(82g(92h(:2i(;2j(<2k(=2l(>2m(?2n(@2o(A2p(B2q(C2r(D2s(E2t(F2u(G2v(H2w(I2x(J2y(K2z(L2{(M$Ð(N$Ñ(O$Ò(P$Ó(Q$Ô(R$Õ(S$Ö(T$×(U$Ø(V$Ù(W$Ú(X$Û(Y$Ü(Z$Ý([$Þ(\$ß(]$à(^$á(_$â(`$ã(a$ä(b$å(c$æ(d$ç(e$è(f$é(g$`(h$a(i$b(j$c(k$d(l$e(m$f(n$g(o$h(p$i(q$j(r$k(s$l(t$m(u$n(v½(w!S(x!T(y¼(z¾({![(|!\(}!](~!^)!æ)")#ð)$')%1)&3)'8)(@))B)*ø)+S),ß)-þ).g)/K)0I)12)22)32)42)52)62)72)82)92):2 );2 )<2 )=2 )>2 )?2)@2)A2)B2)C2)D2)E2)F2)G2)H2)I2)J2)K2)L2)M$œ)N$)O$ž)P$Ÿ)Q$ )R$¡)S$¢)T$£)U$¤)V$¥)W$¦)X$§)Y$¨)Z$©)[$ª)\$«)]$¬)^$­)_$®)`$¯)a$°)b$±)c$²)d$³)e$´)f$µ)g$t)h$u)i$v)j$w)k$x)l$y)m$z)n${)o$|)p$})q$~)r$)s$€)t$)u$‚)v¹)w²)x³)y t)z ){ )| ‚)} ƒ)~ „*!0A*"0B*#0C*$0D*%0E*&0F*'0G*(0H*)0I**0J*+0K*,0L*-0M*.0N*/0O*00P*10Q*20R*30S*40T*50U*60V*70W*80X*90Y*:0Z*;0[*<0\*=0]*>0^*?0_*@0`*A0a*B0b*C0c*D0d*E0e*F0f*G0g*H0h*I0i*J0j*K0k*L0l*M0m*N0n*O0o*P0p*Q0q*R0r*S0s*T0t*U0u*V0v*W0w*X0x*Y0y*Z0z*[0{*\0|*]0}*^0~*_0*`0€*a0*b0‚*c0ƒ*d0„*e0…*f0†*g0‡*h0ˆ*i0‰*j0Š*k0‹*l0Œ*m0*n0Ž*o0*p0*q0‘*r0’*s0“+!0¡+"0¢+#0£+$0¤+%0¥+&0¦+'0§+(0¨+)0©+*0ª++0«+,0¬+-0­+.0®+/0¯+00°+10±+20²+30³+40´+50µ+60¶+70·+80¸+90¹+:0º+;0»+<0¼+=0½+>0¾+?0¿+@0À+A0Á+B0Â+C0Ã+D0Ä+E0Å+F0Æ+G0Ç+H0È+I0É+J0Ê+K0Ë+L0Ì+M0Í+N0Î+O0Ï+P0Ð+Q0Ñ+R0Ò+S0Ó+T0Ô+U0Õ+V0Ö+W0×+X0Ø+Y0Ù+Z0Ú+[0Û+\0Ü+]0Ý+^0Þ+_0ß+`0à+a0á+b0â+c0ã+d0ä+e0å+f0æ+g0ç+h0è+i0é+j0ê+k0ë+l0ì+m0í+n0î+o0ï+p0ð+q0ñ+r0ò+s0ó+t0ô+u0õ+v0ö,!,",#,$,%,&,',(,),*,+,,,-,.,/,0,1,2 ,3!,4",5#,6$,7%,8&,9',:(,;),<*,=+,>,,?-,@.,A/,Q0,R1,S2,T3,U4,V5,WQ,X6,Y7,Z8,[9,\:,];,^<,_=,`>,a?,b@,cA,dB,eC,fD,gE,hF,iG,jH,kI,lJ,mK,nL,oM,pN,qO0!¬0"¬0#¬0$¬0%¬0&¬ 0'¬ 0(¬0)¬0*¬0+¬0,¬0-¬0.¬0/¬00¬01¬02¬03¬04¬05¬ 06¬$07¬,08¬-09¬/0:¬00;¬10<¬80=¬90>¬<0?¬@0@¬K0A¬M0B¬T0C¬X0D¬\0E¬p0F¬q0G¬t0H¬w0I¬x0J¬z0K¬€0L¬0M¬ƒ0N¬„0O¬…0P¬†0Q¬‰0R¬Š0S¬‹0T¬Œ0U¬0V¬”0W¬œ0X¬0Y¬Ÿ0Z¬ 0[¬¡0\¬¨0]¬©0^¬ª0_¬¬0`¬¯0a¬°0b¬¸0c¬¹0d¬»0e¬¼0f¬½0g¬Á0h¬Ä0i¬È0j¬Ì0k¬Õ0l¬×0m¬à0n¬á0o¬ä0p¬ç0q¬è0r¬ê0s¬ì0t¬ï0u¬ð0v¬ñ0w¬ó0x¬õ0y¬ö0z¬ü0{¬ý0|­0}­0~­1!­ 1"­ 1#­1$­1%­1&­1'­ 1(­)1)­,1*­-1+­41,­51-­81.­<1/­D10­E11­G12­I13­P14­T15­X16­a17­c18­l19­m1:­p1;­s1<­t1=­u1>­v1?­{1@­|1A­}1B­1C­1D­‚1E­ˆ1F­‰1G­Œ1H­1I­œ1J­1K­¤1L­·1M­À1N­Á1O­Ä1P­È1Q­Ð1R­Ñ1S­Ó1T­Ü1U­à1V­ä1W­ø1X­ù1Y­ü1Z­ÿ1[®1\®1]®1^® 1_® 1`® 1a®1b®01c®11d®41e®71f®81g®:1h®@1i®A1j®C1k®E1l®F1m®J1n®L1o®M1p®N1q®P1r®T1s®V1t®\1u®]1v®_1w®`1x®a1y®e1z®h1{®i1|®l1}®p1~®x2!®y2"®{2#®|2$®}2%®„2&®…2'®Œ2(®¼2)®½2*®¾2+®À2,®Ä2-®Ì2.®Í2/®Ï20®Ð21®Ñ22®Ø23®Ù24®Ü25®è26®ë27®í28®ô29®ø2:®ü2;¯2<¯2=¯ 2>¯2?¯,2@¯-2A¯02B¯22C¯42D¯<2E¯=2F¯?2G¯A2H¯B2I¯C2J¯H2K¯I2L¯P2M¯\2N¯]2O¯d2P¯e2Q¯y2R¯€2S¯„2T¯ˆ2U¯2V¯‘2W¯•2X¯œ2Y¯¸2Z¯¹2[¯¼2\¯À2]¯Ç2^¯È2_¯É2`¯Ë2a¯Í2b¯Î2c¯Ô2d¯Ü2e¯è2f¯é2g¯ð2h¯ñ2i¯ô2j¯ø2k°2l°2m°2n° 2o°2p°2q°2r°2s°(2t°D2u°E2v°H2w°J2x°L2y°N2z°S2{°T2|°U2}°W2~°Y3!°]3"°|3#°}3$°€3%°„3&°Œ3'°3(°3)°‘3*°˜3+°™3,°š3-°œ3.°Ÿ3/° 30°¡31°¢32°¨33°©34°«35°¬36°­37°®38°¯39°±3:°³3;°´3<°µ3=°¸3>°¼3?°Ä3@°Å3A°Ç3B°È3C°É3D°Ð3E°Ñ3F°Ô3G°Ø3H°à3I°å3J±3K± 3L± 3M± 3N±3O±3P±3Q±3R±3S±3T±3U±3V±#3W±$3X±%3Y±(3Z±,3[±43\±53]±73^±83_±93`±@3a±A3b±D3c±H3d±P3e±Q3f±T3g±U3h±X3i±\3j±`3k±x3l±y3m±|3n±€3o±‚3p±ˆ3q±‰3r±‹3s±3t±’3u±“3v±”3w±˜3x±œ3y±¨3z±Ì3{±Ð3|±Ô3}±Ü3~±Ý4!±ß4"±è4#±é4$±ì4%±ð4&±ù4'±û4(±ý4)²4*²4+²4,² 4-² 4.²4/²40²41²42² 43²444²<45²X46²\47²`48²h49²i4:²t4;²u4<²|4=²„4>²…4?²‰4@²4A²‘4B²”4C²˜4D²™4E²š4F² 4G²¡4H²£4I²¥4J²¦4K²ª4L²¬4M²°4N²´4O²È4P²É4Q²Ì4R²Ð4S²Ò4T²Ø4U²Ù4V²Û4W²Ý4X²â4Y²ä4Z²å4[²æ4\²è4]²ë4^²ì4_²í4`²î4a²ï4b²ó4c²ô4d²õ4e²÷4f²ø4g²ù4h²ú4i²û4j²ÿ4k³4l³4m³4n³4o³4p³4q³4r³4s³4t³4u³T4v³U4w³V4x³X4y³[4z³\4{³^4|³_4}³d4~³e5!³g5"³i5#³k5$³n5%³p5&³q5'³t5(³x5)³€5*³5+³ƒ5,³„5-³…5.³Œ5/³50³”51³ 52³¡53³¨54³¬55³Ä56³Å57³È58³Ë59³Ì5:³Î5;³Ð5<³Ô5=³Õ5>³×5?³Ù5@³Û5A³Ý5B³à5C³ä5D³è5E³ü5F´5G´5H´5I´ 5J´(5K´)5L´+5M´45N´P5O´Q5P´T5Q´X5R´`5S´a5T´c5U´e5V´l5W´€5X´ˆ5Y´5Z´¤5[´¨5\´¬5]´µ5^´·5_´¹5`´À5a´Ä5b´È5c´Ð5d´Õ5e´Ü5f´Ý5g´à5h´ã5i´ä5j´æ5k´ì5l´í5m´ï5n´ñ5o´ø5pµ5qµ5rµ5sµ5tµ5uµ$5vµ%5wµ'5xµ(5yµ)5zµ*5{µ05|µ15}µ45~µ86!µ@6"µA6#µC6$µD6%µE6&µK6'µL6(µM6)µP6*µT6+µ\6,µ]6-µ_6.µ`6/µa60µ 61µ¡62µ¤63µ¨64µª65µ«66µ°67µ±68µ³69µ´6:µµ6;µ»6<µ¼6=µ½6>µÀ6?µÄ6@µÌ6AµÍ6BµÏ6CµÐ6DµÑ6EµØ6Fµì6G¶6H¶6I¶6J¶6K¶%6L¶,6M¶46N¶H6O¶d6P¶h6Q¶œ6R¶6S¶ 6T¶¤6U¶«6V¶¬6W¶±6X¶Ô6Y¶ð6Z¶ô6[¶ø6\·6]·6^·6_·(6`·)6a·,6b·/6c·06d·86e·96f·;6g·D6h·H6i·L6j·T6k·U6l·`6m·d6n·h6o·p6p·q6q·s6r·u6s·|6t·}6u·€6v·„6w·Œ6x·6y·6z·6{·‘6|·’6}·–6~·—7!·˜7"·™7#·œ7$· 7%·¨7&·©7'·«7(·¬7)·­7*·´7+·µ7,·¸7-·Ç7.·É7/·ì70·í71·ð72·ô73·ü74·ý75·ÿ76¸77¸78¸79¸7:¸ 7;¸ 7<¸7=¸7>¸7?¸7@¸7A¸$7B¸%7C¸(7D¸,7E¸47F¸57G¸77H¸87I¸97J¸@7K¸D7L¸Q7M¸S7N¸\7O¸]7P¸`7Q¸d7R¸l7S¸m7T¸o7U¸q7V¸x7W¸|7X¸7Y¸¨7Z¸°7[¸´7\¸¸7]¸À7^¸Á7_¸Ã7`¸Å7a¸Ì7b¸Ð7c¸Ô7d¸Ý7e¸ß7f¸á7g¸è7h¸é7i¸ì7j¸ð7k¸ø7l¸ù7m¸û7n¸ý7o¹7p¹7q¹ 7r¹<7s¹=7t¹@7u¹D7v¹L7w¹O7x¹Q7y¹X7z¹Y7{¹\7|¹`7}¹h7~¹i8!¹k8"¹m8#¹t8$¹u8%¹x8&¹|8'¹„8(¹…8)¹‡8*¹‰8+¹Š8,¹8-¹Ž8.¹¬8/¹­80¹°81¹´82¹¼83¹½84¹¿85¹Á86¹È87¹É88¹Ì89¹Î8:¹Ï8;¹Ð8<¹Ñ8=¹Ò8>¹Ø8?¹Ù8@¹Û8A¹Ý8B¹Þ8C¹á8D¹ã8E¹ä8F¹å8G¹è8H¹ì8I¹ô8J¹õ8K¹÷8L¹ø8M¹ù8N¹ú8Oº8Pº8Qº8Rº8Sº88Tº98Uº<8Vº@8WºB8XºH8YºI8ZºK8[ºM8\ºN8]ºS8^ºT8_ºU8`ºX8aº\8bºd8cºe8dºg8eºh8fºi8gºp8hºq8iºt8jºx8kºƒ8lº„8mº…8nº‡8oºŒ8pº¨8qº©8rº«8sº¬8tº°8uº²8vº¸8wº¹8xº»8yº½8zºÄ8{ºÈ8|ºØ8}ºÙ8~ºü9!»9"»9#» 9$»9%»9&»9'»9(» 9)»)9*»+9+»49,»59-»69.»89/»;90»<91»=92»>93»D94»E95»G96»I97»M98»O99»P9:»T9;»X9<»a9=»c9>»l9?»ˆ9@»Œ9A»9B»¤9C»¨9D»¬9E»´9F»·9G»À9H»Ä9I»È9J»Ð9K»Ó9L»ø9M»ù9N»ü9O»ÿ9P¼9Q¼9R¼9S¼ 9T¼ 9U¼ 9V¼ 9W¼9X¼9Y¼9Z¼9[¼9\¼9]¼9^¼9_¼9`¼9a¼9b¼9c¼$9d¼%9e¼'9f¼)9g¼-9h¼09i¼19j¼49k¼89l¼@9m¼A9n¼C9o¼D9p¼E9q¼I9r¼L9s¼M9t¼P9u¼]9v¼„9w¼…9x¼ˆ9y¼‹9z¼Œ9{¼Ž9|¼”9}¼•9~¼—:!¼™:"¼š:#¼ :$¼¡:%¼¤:&¼§:'¼¨:(¼°:)¼±:*¼³:+¼´:,¼µ:-¼¼:.¼½:/¼À:0¼Ä:1¼Í:2¼Ï:3¼Ð:4¼Ñ:5¼Õ:6¼Ø:7¼Ü:8¼ô:9¼õ::¼ö:;¼ø:<¼ü:=½:>½:?½:@½ :A½:B½:C½$:D½,:E½@:F½H:G½I:H½L:I½P:J½X:K½Y:L½d:M½h:N½€:O½:P½„:Q½‡:R½ˆ:S½‰:T½Š:U½:V½‘:W½“:X½•:Y½™:Z½š:[½œ:\½¤:]½°:^½¸:_½Ô:`½Õ:a½Ø:b½Ü:c½é:d½ð:e½ô:f½ø:g¾:h¾:i¾:j¾ :k¾ :l¾:m¾:n¾:o¾:p¾:q¾D:r¾E:s¾H:t¾L:u¾N:v¾T:w¾U:x¾W:y¾Y:z¾Z:{¾[:|¾`:}¾a:~¾d;!¾h;"¾j;#¾p;$¾q;%¾s;&¾t;'¾u;(¾{;)¾|;*¾};+¾€;,¾„;-¾Œ;.¾;/¾;0¾;1¾‘;2¾˜;3¾™;4¾¨;5¾Ð;6¾Ñ;7¾Ô;8¾×;9¾Ø;:¾à;;¾ã;<¾ä;=¾å;>¾ì;?¿;@¿;A¿ ;B¿;C¿;D¿;E¿;F¿;G¿@;H¿A;I¿D;J¿H;K¿P;L¿Q;M¿U;N¿”;O¿°;P¿Å;Q¿Ì;R¿Í;S¿Ð;T¿Ô;U¿Ü;V¿ß;W¿á;XÀ<;YÀQ;ZÀX;[À\;\À`;]Àh;^Ài;_À;`À‘;aÀ”;bÀ˜;cÀ ;dÀ¡;eÀ£;fÀ¥;gÀ¬;hÀ­;iÀ¯;jÀ°;kÀ³;lÀ´;mÀµ;nÀ¶;oÀ¼;pÀ½;qÀ¿;rÀÀ;sÀÁ;tÀÅ;uÀÈ;vÀÉ;wÀÌ;xÀÐ;yÀØ;zÀÙ;{ÀÛ;|ÀÜ;}ÀÝ;~ÀäÁ<­=?´=@µ=A·=B¹=CÂÜ=DÂÝ=EÂà=FÂã=GÂä=HÂë=IÂì=JÂí=KÂï=LÂñ=MÂö=NÂø=OÂù=PÂû=QÂü=RÃ=SÃ=Tà =Uà =Và =WÃ=XÃ=YÃ=ZÃ=[Ã=\Ã$=]Ã%=^Ã(=_Ã)=`ÃE=aÃh=bÃi=cÃl=dÃp=eÃr=fÃx=gÃy=hÃ|=iÃ}=jÄ=kÈ=lÃŒ=mÃÀ=nÃØ=oÃÙ=pÃÜ=qÃß=rÃà=sÃâ=tÃè=uÃé=vÃí=wÃô=xÃõ=yÃø=zÄ={Ä=|Ä$=}Ä,=~Ä0>!Ä4>"Ä<>#Ä=>$ÄH>%Äd>&Äe>'Äh>(Äl>)Ät>*Äu>+Äy>,Ä€>-Ä”>.Äœ>/ĸ>0ļ>1Äé>2Äð>3Äñ>4Äô>5Äø>6Äú>7Äÿ>8Å>9Å>:Å >;Å><Å>=Å>>Å(>?Å)>@Å,>AÅ0>BÅ8>CÅ9>DÅ;>EÅ=>FÅD>GÅE>HÅH>IÅI>JÅJ>KÅL>LÅM>MÅN>NÅS>OÅT>PÅU>QÅW>RÅX>SÅY>TÅ]>UÅ^>VÅ`>WÅa>XÅd>YÅh>ZÅp>[Åq>\Ås>]Åt>^Åu>_Å|>`Å}>aÅ€>bÅ„>cŇ>dÅŒ>eÅ>fÅ>gÅ‘>hÅ•>iÅ—>jŘ>kÅœ>lÅ >mÅ©>nÅ´>oŵ>pŸ>qŹ>rÅ»>sż>tŽ>už>vÅÄ>wÅÅ>xÅÆ>yÅÇ>zÅÈ>{ÅÉ>|ÅÊ>}ÅÌ>~ÅÎ?!ÅÐ?"ÅÑ?#ÅÔ?$ÅØ?%Åà?&Åá?'Åã?(Åå?)Åì?*Åí?+Åî?,Åð?-Åô?.Åö?/Å÷?0Åü?1Åý?2Åþ?3Åÿ?4Æ?5Æ?6Æ?7Æ?8Æ?9Æ?:Æ ?;Æ?<Æ?=Æ?>Æ??Æ?@Æ$?AÆ%?BÆ(?CÆ,?DÆ-?EÆ.?FÆ0?GÆ3?HÆ4?IÆ5?JÆ7?KÆ9?LÆ;?MÆ@?NÆA?OÆD?PÆH?QÆP?RÆQ?SÆS?TÆT?UÆU?VÆ\?WÆ]?XÆ`?YÆl?ZÆo?[Æq?\Æx?]Æy?^Æ|?_Æ€?`ƈ?aƉ?bÆ‹?cÆ?dÆ”?eÆ•?fƘ?gÆœ?hƤ?iÆ¥?jƧ?kÆ©?lư?mƱ?nÆ´?oƸ?pƹ?qƺ?rÆÀ?sÆÁ?tÆÃ?uÆÅ?vÆÌ?wÆÍ?xÆÐ?yÆÔ?zÆÜ?{ÆÝ?|Æà?}Æá?~Æè@!Æé@"Æì@#Æð@$Æø@%Æù@&Æý@'Ç@(Ç@)Ç@*Ç @+Ç@,Ç@-Ç@.Ç@/Ç @0Ç!@1Ç$@2Ç(@3Ç0@4Ç1@5Ç3@6Ç5@7Ç7@8Ç<@9Ç=@:Ç@@;ÇD@<ÇJ@=ÇL@>ÇM@?ÇO@@ÇQ@AÇR@BÇS@CÇT@DÇU@EÇV@FÇW@GÇX@HÇ\@IÇ`@JÇh@KÇk@LÇt@MÇu@NÇx@OÇ|@PÇ}@QÇ~@Rǃ@SÇ„@TÇ…@ULJ@VLj@Wlj@XÇŠ@YÇŽ@ZÇ@[Ç‘@\Ç”@]Ç–@^Ç—@_ǘ@`Çš@aÇ @bÇ¡@cÇ£@dǤ@eÇ¥@fǦ@gǬ@hÇ­@iǰ@jÇ´@kǼ@lǽ@mÇ¿@nÇÀ@oÇÁ@pÇÈ@qÇÉ@rÇÌ@sÇÎ@tÇÐ@uÇØ@vÇÝ@wÇä@xÇè@yÇì@zÈ@{È@|È@}È@~È A!ÈA"ÈA#ÈA$ÈA%ÈA&ÈA'ÈA(È A)È$A*È,A+È-A,È/A-È1A.È8A/ÈÈ…A?ȆA@ȇAAÈ‹ABÈŒACÈADÈ”AEÈAFÈŸAGÈ¡AHȨAIȼAJȽAKÈÄALÈÈAMÈÌANÈÔAOÈÕAPÈ×AQÈÙARÈàASÈáATÈäAUÈõAVÈüAWÈýAXÉAYÉAZÉA[ÉA\É A]É A^ÉA_ÉA`ÉAaÉ,AbÉ4AcÉPAdÉQAeÉTAfÉXAgÉ`AhÉaAiÉcAjÉlAkÉpAlÉtAmÉ|AnɈAoɉApÉŒAqÉArɘAsÉ™AtÉ›AuÉAvÉÀAwÉÁAxÉÄAyÉÇAzÉÈA{ÉÊA|ÉÐA}ÉÑA~ÉÓB!ÉÕB"ÉÖB#ÉÙB$ÉÚB%ÉÜB&ÉÝB'ÉàB(ÉâB)ÉäB*ÉçB+ÉìB,ÉíB-ÉïB.ÉðB/ÉñB0ÉøB1ÉùB2ÉüB3ÊB4ÊB5Ê B6Ê B7Ê B8Ê B9ÊB:ÊB;Ê)B<ÊLB=ÊMB>ÊPB?ÊTB@Ê\BAÊ]BBÊ_BCÊ`BDÊaBEÊhBFÊ}BGÊ„BHʘBIʼBJʽBKÊÀBLÊÄBMÊÌBNÊÍBOÊÏBPÊÑBQÊÓBRÊØBSÊÙBTÊàBUÊìBVÊôBWËBXËBYËBZËB[Ë B\Ë!B]ËAB^ËHB_ËIB`ËLBaËPBbËXBcËYBdË]BeËdBfËxBgËyBhËœBi˸BjËÔBkËäBlËçBmËéBnÌ BoÌ BpÌBqÌBrÌBsÌBtÌ!BuÌ"BvÌ'BwÌ(BxÌ)ByÌ,BzÌ.B{Ì0B|Ì8B}Ì9B~Ì;C!ÌC$ÌDC%ÌEC&ÌHC'ÌLC(ÌTC)ÌUC*ÌWC+ÌXC,ÌYC-Ì`C.ÌdC/ÌfC0ÌhC1ÌpC2ÌuC3̘C4Ì™C5ÌœC6Ì C7̨C8Ì©C9Ì«C:̬C;Ì­C<Ì´C=̵C≯C?̼C@ÌÄCAÌÅCBÌÇCCÌÉCDÌÐCEÌÔCFÌäCGÌìCHÌðCIÍCJÍCKÍ CLÍ CMÍCNÍCOÍCPÍCQÍCRÍ$CSÍ(CTÍ,CUÍ9CVÍ\CWÍ`CXÍdCYÍlCZÍmC[ÍoC\ÍqC]ÍxC^͈C_Í”C`Í•Ca͘CbÍœCcͤCdÍ¥CeͧCfÍ©CgͰChÍÄCiÍÌCjÍÐCkÍèClÍìCmÍðCnÍøCoÍùCpÍûCqÍýCrÎCsÎCtÎ CuÎCvÎCwÎ CxÎ!CyÎ$CzÎ(C{Î0C|Î1C}Î3C~Î5D!ÎXD"ÎYD#Î\D$Î_D%Î`D&ÎaD'ÎhD(ÎiD)ÎkD*ÎmD+ÎtD,ÎuD-ÎxD.Î|D/΄D0Î…D1·D2ΉD3ÎD4ΑD5ΔD6ΘD7ΠD8ΡD9ΣD:ΤD;Î¥D<άD=έD>ÎÁD?ÎäD@ÎåDAÎèDBÎëDCÎìDDÎôDEÎõDFÎ÷DGÎøDHÎùDIÏDJÏDKÏDLÏDMÏDNÏDOÏDPÏDQÏDRÏ DSÏ$DTÏ,DUÏ-DVÏ/DWÏ0DXÏ1DYÏ8DZÏTD[ÏUD\ÏXD]Ï\D^ÏdD_ÏeD`ÏgDaÏiDbÏpDcÏqDdÏtDeÏxDfÏ€DgÏ…DhÏŒDiÏ¡DjϨDkϰDlÏÄDmÏàDnÏáDoÏäDpÏèDqÏðDrÏñDsÏóDtÏõDuÏüDvÐDwÐDxÐDyÐDzÐ-D{Ð4D|Ð5D}Ð8D~ÐÐÑE?ÐÓE@ÐÔEAÐÕEBÐÜECÐÝEDÐàEEÐäEFÐìEGÐíEHÐïEIÐðEJÐñEKÐøELÑ EMÑ0ENÑ1EOÑ4EPÑ8EQÑ:ERÑ@ESÑAETÑCEUÑDEVÑEEWÑLEXÑMEYÑPEZÑTE[Ñ\E\Ñ]E]Ñ_E^ÑaE_ÑhE`ÑlEaÑ|EbÑ„EcшEdÑ EeÑ¡EfѤEgѨEhѰEiѱEjѳEkѵElѺEmѼEnÑÀEoÑØEpÑôEqÑøErÒEsÒ EtÒEuÒ,EvÒ-EwÒ0ExÒ4EyÒÒôF?ÒøF@ÓFAÓFBÓFCÓFDÓ FEÓ FFÓFGÓFHÓFIÓFJÓFKÓFLÓFMÓ FNÓ!FOÓ%FPÓ(FQÓ)FRÓ,FSÓ0FTÓ8FUÓ9FVÓ;FWÓÔøG?ÔûG@ÔýGAÕGBÕGCÕ GDÕGEÕGFÕGGÕÖ¡H?Ö¨H@Ö¬HAÖ°HBÖ¹HCÖ»HDÖÄHEÖÅHFÖÈHGÖÌHHÖÑHIÖÔHJÖ×HKÖÙHLÖàHMÖäHNÖèHOÖðHPÖõHQÖüHRÖýHS×HT×HU×HV×HW×HX×HY× HZ×(H[×)H\×+H]×-H^×4H_×5H`×8Ha×R;J?StJ@TJA`jJBadJCk¼JDsÏJEJF‰ºJG‰ÒJH•£JIOƒJJR JKX¾JLYxJMYæJN^rJO^yJPaÇJQcÀJRgFJSgìJThJUo—JVvNJWw JXxõJYzJZzÿJ[|!J\€J]‚nJ^‚qJ_ŠëJ`•“JaNkJbUJcf÷Jdn4Jex£JfzíJg„[Jh‰Ji‡NJj—¨JkRØJlWNJmX*Jn]LJoaJpa¾Jqb!JrebJsgÑJtjDJunJvuJwu³JxvãJyw°Jz}:J{¯J|”QJ}”RJ~Ÿ•K!S#K"\¬K#u2K$€ÛK%’@K&•˜K'R[K(XK)YÜK*\¡K+]K,^·K-_:K._JK/awK0l_K1uzK2u†K3|àK4}sK5}±K6ŒK7TK8‚!K9…‘K:‰AK;‹K<’üK=–MK>œGK?NËK@N÷KAP KBQñKCXOKDa7KEa>KFahKGe9KHiêKIoKJu¥KKv†KLvÖKM{‡KN‚¥KO„ËKPùKQ“§KR•‹KSU€KT[¢KUWQKVùKW|³KX¹KY‘µKZP(K[S»K\\EK]]èK^bÒK_cnK`dÚKadçKbn Kcp¬Kdy[KeÝKfŽKgùKh}Ki’EKj’øKkN~KlNöKmPeKn]þKo^úKpaKqiWKrqKs†TKtŽGKu“uKvš+KwN^KxP‘KygpKzh@K{Q K|RK}R’K~j¢L!w¼L"’L#žÔL$R«L%`/L&òL'PHL(a©L)cíL*dÊL+hoTL?}PL@:LAŠ#LBQ|LCaJLD{LE‹LF’WLG“ŒLHN¬LIOÓLJPLKP¾LLQLMRÁLNRÍLOSLPWpLQXƒLR^šLS_‘LTavLUa¬LVdÎLWelLXfoLYf»LZfôL[h—L\m‡L]p…L^pñL_tŸL`t¥LatÊLbuÙLcxlLdxìLezßLfzöLg}ELh}“Li€Lj€?LkLlƒ–Lm‹fLnLoLp“áLq˜Lr˜8LsšZLt›èLuOÂLvUSLwX:LxYQLy[cLz\FL{`¸L|bL}hBL~h°M!hèM"nªM#uLM$vxM%xÎM&z=M'|ûM(~kM)~|M*ŠM+Š¡M,Œ?M-–ŽM.ÄM/SäM0SéM1TJM2TqM3VúM4YÑM5[dM6\;M7^«M8b÷M9e7M:eEM;erMiÁM?l½M@uüMAvMBw~MCz?MD”ME€MF€¡MGMH‚æMI‚ýMJƒðMK…ÁMLˆ1MMˆ´MNŠ¥MOùMPœMQ“.MR–ÇMS˜gMTšØMUŸMVTíMWe›MXfòMYhMZz@M[Œ7M\`M]VðM^WdM_]M`fMah±MbhÍMcnþMdt(MeˆžMf›äMglhMhùMiš¨MjO›MkQlMlQqMmRŸMn[TMo]åMp`PMq`mMrbñMsc§Mte;MusÙMvzzMw†£MxŒ¢My—MzN2M{[áM|bM}gœM~tÜN!yÑN"ƒÓN#ЇN$вN%èN&NN'“KN(˜FN)^ÓN*ièN+…ÿN,íN-ùN.Q N/[˜N0[ìN1acN2húN3k>N4pLN5t/N6tØN7{¡N8PN9ƒÅN:‰ÀN;Œ«N<•ÜN=™(N>R.N?`]N@bìNANBOŠNCQINDS!NEXÙNF^ãNGfàNHm8NIpšNJrÂNKsÖNL{PNM€ñNN”[NOSfNPc›NQkNRNVNSP€NTXJNUXÞNV`*NWa'NXbÐNYiÐNZ›AN[[N\}N]€±N^_N_N¤N`PÑNaT¬NbU¬Nc[ Nd] Ne]çNfe*NgeNNhh!NijKNjráNkvŽNlwïNm}^NnùNo Np…NNq†ßNrNsNNtÊNu™NvšUNw›«NxNNyNENzN]N{NÇN|OñN}QwN~RþO!S@O"SãO#SåO$TŽO%VO&WuO'W¢O([ÇO)]‡O*^ÐO+aüO,bØO-eQO.g¸O/géO0iËO1kPO2kÆO3kìO4lBO5nO6pxO7r×O8s–O9tO:w¿O;wéO€ O?üO@‚OA‚ OB‚ßOCˆbOD‹3OEŒüOFŽÀOGOH±OI’dOJ’¶OK™ÒOLšEOMœéON×OOŸœOPW OQ\@ORƒÊOS— OT—«OUž´OVTOWz˜OX¤OYˆÙOZŽÍO[áO\XO]\HO^c˜O_zŸO`[®Oa_ObzyOcz®Od‚ŽOeެOfP&OgR8OhRøOiSwOjWOkbóOlcrOmk OnmÃOow7OpS¥OqsWOr…hOsŽvOt•ÕOug:OvjÃOwopOxŠmOyŽÌOz™KO{ùO|fwO}kxO~Œ´P!›hØP?iuP@–™PAPÅPBR¤PCRäPDaÃPEe¤PFh9PGiÿPHt~PI{KPJ‚¹PKƒëPL‰²PM‹9PNÑPO™IPPù PQNÊPRY—PSdÒPTfPUjŽPVt4PWyPXy½PY‚©PZˆ~P[ˆP\‰_P]ù P^“&P_O P`SÊPa`%PbbqPclrPd}Pe}fPfN˜PgQbPhwÜPi€¯PjOPkOPlQvPmQ€PnUÜPoVhPpW;PqWúPrWüPsYPtYGPuY“Pv[ÄPw\Px]Py]ñPz^~P{_ÌP|b€P}e×P~eãQ!gQ"gQ#g^Q$hËQ%hÄQ&j_Q'k:Q(l#Q)l}Q*l‚Q+mÇQ,s˜Q-t&Q.t*Q/t‚Q0t£Q1uxQ2uQ3xQ4xïQ5yAQ6yGQ7yHQ8yzQ9{•Q:}Q;}ºQ<ˆQ=€Q>€-Q?€ŒQ@ŠQA‹OQBŒHQCwQD“!QE“$QF˜âQG™QQHšQIšQJšeQKž’QL}ÊQMOvQNT QObîQPhTQQ‘ÑQRU«QSQ:QTù QUù QVZQWaæQXù QYbÏQZbÿQ[ùQ\ùQ]ùQ^ùQ_ùQ`ùQa£QbùQcùQdùQeùQfùQgŠþQhùQiùQjùQkùQlf–QmùQnqVQoùQpùQq–ãQrù QscOQtczQuSWQvù!QwgQxi`QynsQzù"Q{u7Q|ù#Q}ù$Q~ù%R!} R"ù&R#ù'R$ˆrR%VÊR&ZR'ù(R(ù)R)ù*R*ù+R+ù,R,NCR-ù-R.QgR/YHR0gðR1€R2ù.R3YsR4^tR5dšR6yÊR7_õR8`lR9bÈR:c{R;[çR<[×R=RªR>ù/R?YtR@_)RA`RBù0RCù1RDù2REtYRFù3RGù4RHù5RIù6RJù7RKù8RL™ÑRMù9RNù:ROù;RPùRSù?RTù@RUùARVùBRWùCRXoÃRYùDRZùER[¿R\²R]`ñR^ùFR_ùGR`fRaùHRbùIRc\?RdùJReùKRfùLRgùMRhùNRiùORjùPRkùQRlZéRmŠ%Rng{Ro}RpùRRqùSRrùTRsùURtùVRuùWRv€ýRwùXRxùYRy\fÇS?máS@n[SAomSBo¹SCuðSD€CSE½SF…ASG‰ƒSHŠÇSI‹ZSJ“SKl“SLuSSM{TSNŽSO]SPUSQXSRXXSS^bSTbSUdžSVhàSWuvSX|ÖSY‡³SZžèS[NãS\WˆS]WnS^Y'S_\ S`\±Sa^6Sb_…Scb4SddáSes³SfúSgˆ‹ShŒ¸Si–ŠSjžÛSk[…Sl_·Sm`³SnPSoRSpR0SqWSrX5SsXWSt\Su\`Sv\öSw]‹Sx^¦Sy_’Sz`¼S{cS|c‰S}dS~hCT!hùT"jÂT#mØT$n!T%nÔT&oäT'qþT(vÜT)wyT*y±T+z;T,„T-‰©T.ŒíT/óT0ŽHT1T2T3ST4ýT5“MT6–vT7—ÜT8kÒT9pT:rXT;r¢Ty¿T?{äT@~›TA‹€TBX©TC`ÇTDefTEeýTFf¾TGlŒTHqTIqÉTJŒZTK˜TLNmTMzTNNÝTOQ¬TPQÍTQRÕTRT TSa§TTgqTUhPTVhßTWmTXo|TYu¼TZw³T[zåT\€ôT]„cT^’…T_Q\T`e—Tag\Tbg“TcuØTdzÇTeƒsTfùZTgŒFThTi˜-Tj\oTkÀTl‚šTmATnoTo’ Tp_—Tq]TrjYTsqÈTtv{Tu{ITv…äTw‹Tx‘'Tyš0TzU‡T{aöT|ù[T}viT~…U!†?U"‡ºU#ˆøU$U%ù\U&mU'pÙU(sÞU)}aU*„=U+ù]U,‘jU-™ñU.ù^U/N‚U0SuU1kU2kU3p>U4rU5†-U6žU7RLU8£U9]PU:dåU;e,U|CU?~œU@…ÍUA‰dUB‰½UCbÉUDØUEˆUF^ÊUGgUHmjUIrüUJtUKtoUL‡‚UMÞUNO†UO] UP_ UQ„ URQ·USc UTueUUN®UVPUWQiUXQÉUYhUZjU[|®U\|±U]|çU^‚oU_ŠÒU`Ua‘ÏUbO¶UcQ7UdRõUeTBUf^ìUganUhb>UieÅUjjÚUkoþUly*Um…ÜUnˆ#Uo•­UpšbUqšjUrž—UsžÎUtR›UufÆUvkwUwpUxy+UybUz—BU{aU|bU}e#U~o#V!qIV"t‰V#}ôV$€oV%„îV&&V'#V(“JV)Q½V*RV+R£V,m V-pÈV.ˆÂV/^ÉV0e‚V1k®V2oÂV3|>V4suV5NäV6O6V7VùV8ù_V9\ºV:]ºV;`VšV?ÎV@€FVAVB’4VC–öVD—HVE˜VFŸaVGO‹VHo§VIy®VJ‘´VK–·VLRÞVMù`VNdˆVOdÄVPjÓVQo^VRpVSrVTvçVU€VV†VW†\VXïVYVZ—2V[›oV\úV]žuV^xŒV_yV`} VaƒÉVb“VcžVdž“VeŠÖVfXßVg_Vhg'Vip'VjtÏVk|`Vl€~VmQ!Vnp(VorbVpxÊVqŒÂVrŒÚVsŒôVt–÷VuN†VvPÚVw[îVx^ÖVye™VzqÎV{vBV|w­V}€JV~„üW!|W"›'W#ŸW$XØW%ZAW&\bW'jW(mÚW)oW*v;W+}/W,~7W-…W.‰8W/“äW0–KW1R‰W2eÒW3góW4i´W5mAW6nœW7pW8t W9t`W:uYW;v$W˜^W?QmW@b.WA–xWBO–WCP+WD]WEmêWF}¸WG*WH_‹WIaDWJhWKùaWL–†WMRÒWN€‹WOQÜWPQÌWQi^WRzWS}¾WTƒñWU–uWVOÚWWR)WXS˜WYTWZUW[\eW\`§W]gNW^h¨W_mlW`rWarøWbtWctƒWdùbWeuâWf|lWgyWh¸Wiƒ‰WjˆÏWkˆáWl‘ÌWm‘ÐWn–âWo›ÉWpTWqo~WrqÐWst˜Wt…úWuŽªWv–£WwœWWxžŸWyg—WzmËW{t3W|èW}—W~x,X!zËX"{ X#|’X$diX%tjX&uòX'x¼X(xèX)™¬X*›TX+ž»X,[ÞX-^UX.o X/œX0ƒ«X1ˆX2NX3SMX4Z)X5]ÒX6_NX7abX8c=X9fiX:füX;nÿXwžX?„,X@…XAˆ;XBXC™EXDœ;XEUXFb¹XGg+XHl«XIƒ XJ‰jXK—zXLN¡XMY„XN_ØXO_ÙXPgXQ}²XRTXS‚’XTƒ+XUƒ½XVXW™XXWËXYY¹XZZ’X[[ÐX\f'X]gšX^h…X_kÏX`qdXauXbŒ·XcŒãXdXe›EXfXgŒŠXh–LXiš@Xjž¥Xk[_XllXmsXnvòXovßXp„ XqQªXr‰“XsQMXtQ•XuRÉXvhÉXwl”XxwXyw Xz}¿X{}ìX|—bX}žµX~nÅY!…Y"Q¥Y#T Y$T}Y%fY&fY'i'Y(nŸY)v¿Y*w‘Y+ƒY,„ÂY-‡ŸY.‘iY/’˜Y0œôY1ˆ‚Y2O®Y3Q’Y4RßY5YÆY6^=Y7aUY8dxY9dyY:f®Y;gÐYkÛY?r_Y@raYAtAYBw8YCwÛYD€YE‚¼YFƒYG‹YH‹(YIŒŒYJg(YKlYLrgYMvîYNwfYOzFYP©YQkYRl’YSY"YTg&YU„™YVSoYWX“YXY™YY^ßYZcÏY[f4Y\gsY]n:Y^s+Y_z×Y`‚×Ya“(YbRÙYc]ëYda®YeaËYfb YgbÇYhd«YieàYjiYYkkfYlkËYmq!Yns÷You]Yp~FYq‚YrƒYs…jYtŠ£YuŒ¿Yv—'YwaYxX¨YyžØYzPY{RY|T;Y}UOY~e‡Z!lvZ"} Z#} Z$€^Z%†ŠZ&•€Z'–ïZ(RÿZ)l•Z*riZ+TsZ,ZšZ-\>Z.]KZ/_LZ0_®Z1g*Z2h¶Z3icZ4n\·Z?`¶Z@a ZAa«ZBeOZCeûZDeüZElZFlïZGsŸZHsÉZI}áZJ•”ZK[ÆZL‡ZM‹ZNR]ZOSZZPbÍZQdZRd²ZSg4ZTj8ZUlÊZVsÀZWtžZX{”ZY|•ZZ~Z[ŠZ\‚6Z]…„Z^ëZ_–ùZ`™ÁZaO4ZbSJZcSÍZdSÛZebÌZfd,ZgeZhe‘ZiiÃZjlîZkoXZlsíZmuTZnv"ZoväZpvüZqxÐZrxûZsy,Zt}FZu‚,Zv‡àZwÔZx˜Zy˜ïZzRÃZ{bÔZ|d¥Z}n$Z~oQ[!v|["Ë[#‘±[$’b[%šî[&›C['P#[(P[)WJ[*Y¨[+\([,^G[-_w[.b?[/e>[0e¹[1eÁ[2f [3g‹[4iœ[5nÂ[6xÅ[7}![8€ª[9€[:‚+[;‚³[<„¡[=†Œ[>Š*[?‹[@¦[A–2[BŸ[CP [DOó[Eùc[FWù[G_˜[HbÜ[Ic’[Jgo[KnC[Lq[MvÃ[N€Ì[O€Ú[Pˆô[Qˆõ[R‰[SŒà[T)[U‘M[V–j[WO/[XOp[Y^gÏ[[h"[\v}[]v~[^›D[_^a[`j [aqi[bqÔ[cuj[dùd[e~A[f…C[g…é[h˜Ü[iO[j{O[kp[l•¥[mQá[n^[ohµ[pl>[qlN[rlÛ[sr¯[t{Ä[uƒ[vlÕ[wt:[xPû[yRˆ[zXÁ[{dØ[|j—[}t§[~vV\!x§\"†\#•â\$—9\%ùe\&S^\'_\(‹Š\)¨\*¯\+Š\,R%\-w¥\.œI\/Ÿ\0N\1P\2Qu\3\[\4^w\5f\6f:\7gÄ\8hÅ\9p³\:u\;uÅ\'\?™ \@š\AOÝ\BX!\CX1\D[ö\Efn\Fke\Gm\Hnz\Io}\Jsä\Ku+\Lƒé\MˆÜ\N‰\O‹\\P\QO\RPÕ\SS\TS\\U[“\V_©\Wg \Xy\Yy\Zƒ/\[…\\‰\]‰†\^9\_;\`™¥\aœ\bg,\cNv\dOø\eYI\f\\g\ï\h\ð\icg\jhÒ\kpý\lq¢\mt+\n~+\o„ì\p‡\q"\r’Ò\sœó\tN \uNØ\vOï\wP…\xRV\yRo\zT&\{T\|Wà\}Y+\~Zf]![Z]"[u]#[Ì]$^œ]%ùf]&bv]'ew](e§])mn]*n¥]+r6],{&]-|?].6]/P]0Q]1š]2‚@]3‚™]4ƒ©]5Š]6Œ ]7Œæ]8Œû]9t]:º];è]<‘Ü]=–]>–D]?™Ù]@œç]AS]BR]CT)]DVt]EX³]FYT]GYn]H_ÿ]Ia¤]Jbn]Kf]Ll~]Mq]NvÆ]O|‰]P|Þ]Q}]R‚¬]SŒÁ]T–ð]Uùg]VO[]W_]X_]YbÂ]Z])][g ]\hÚ]]x|]^~C]_l]`N]aP™]bS]cS*]dSQ]eYƒ]fZb]g^‡]h`²]iaŠ]jbI]kby]le]mg‡]ni§]okÔ]pkÖ]qk×]rkØ]sl¸]tùh]ut5]vuú]wx]xx‘]yyÕ]zyØ]{|ƒ]|}Ë]}á]~€¥^!>^"Â^#ƒò^$‡^%ˆè^&й^'‹l^(Œ»^)‘^*—^^+˜Û^,Ÿ;^-V¬^.[*^/_l^0eŒ^1j³^2k¯^3m\^4oñ^5p^6r]^7s­^8Œ§^9ŒÓ^:˜;^;a‘^š^?NM^@N‹^AN›^BNÕ^CO:^DO<^EO^FOß^GPÿ^HSò^ISø^JU^KUã^LVÛ^MXë^NYb^OZ^P[ë^Q[ú^R\^S]ó^T^+^U_™^V`^Wch^Xeœ^Ye¯^Zgö^[gû^\h­^]k{^^l™^_l×^`n#^ap ^bsE^cx^dy>^ey@^fy`^gyÁ^h{é^i}^j}r^k€†^l‚ ^mƒŽ^n„Ñ^o†Ç^pˆß^qŠP^rŠ^^s‹^tŒÜ^uf^v­^wª^x˜ü^y™ß^zž^{RJ^|ùi^}g^~ùj_!P˜_"R*_#\q_$ec_%lU_&sÊ_'u#_(u_){—_*„œ_+‘x_,—0_-Nw_.d’_/kº_0q^_1…©_2N _3ùk_4gI_5hî_6n_7‚Ÿ_8…_9ˆk_:c÷_;o_<’_=˜¯_>N _?P·_@PÏ_AQ_BUF_CUª_DV_E[@_F\_G\à_H^8_I^Š_J^ _K^Â_L`ó_MhQ_Nja_OnX_Pr=_Qr@_RrÀ_Svø_Tye_U{±_VÔ_Wˆó_X‰ô_YŠs_ZŒa_[ŒÞ_\—_]X^_^t½__Œý_`UÇ_aùl_bza_c}"_d‚r_err_fu_gu%_hùm_i{_jX…_kXû_l]¼_m^_n^¶_o__p`U_qb’_rc_seM_tf‘_ufÙ_vfø_wh_xhò_yr€_zt^_{{n_|}n_}}Ö_~r`!€å`"‚`#…¯`$‰`%Š“`&`'’ä`(žÍ`)Ÿ `*Y`+Ym`,^-`-`Ü`.f`/fs`0g`1lP`2mÅ`3o_`4wó`5x©`6„Æ`7‘Ë`8“+`9NÙ`:PÊ`;QH`[£`?bG`@e~`AeË`Bn2`Cq}`Dt`EtD`Ft‡`Gt¿`Hvl`Iyª`J}Ú`K~U`L¨`Mz`N³`O‚9`P†`Q‡ì`RŠu`Sã`Tx`U’‘`V”%`W™M`X›®`YSh`Z\Q`[iT`\lÄ`]m)`^n+`_‚ ``…›`a‰;`bŠ-`cŠª`d–ê`eŸg`fRa`gf¹`hk²`i~–`j‡þ`k `l•ƒ`m–]`ne`om‰`pqî`qùn`rWÎ`sYÓ`t[¬`u`'`v`ú`wb`xf`yf_`zs)`{sù`|vÛ`}w`~{la!€Va"€ra#ea$Š a%‘’a&Na'Râa(kra)ma*za+{9a,}0a-ùoa.Œ°a/Sìa0V/a1XQa2[µa3\a4\a5]âa6b@a7cƒa8da9f-a:h³a;l¼apa?p¤a@qÒaAu&aBuaCuŽaDvaE{aF{àaG|+aH} aI}9aJ…,aK…maL†aMŠ4aN aOaaPµaQ’·aR—öaSš7aTO×aU\laVg_aWm‘aX|ŸaY~ŒaZ‹a[a\a][ka^]ýa_d a`„Àaa\ab˜áacs‡ad[‹ae`šafg~agmÞahŠaiЦajak˜ alR7amùpanpQaoxŽap“–aqˆpar‘×asOîatS×auUýavVÚawW‚axXýayZÂaz[ˆa{\«a|\Àa}^%a~ab!b b"bKb#cˆb$db%e6b&exb'j9b(kŠb)l4b*mb+o1b,qçb-réb.sxb/tb0t²b1v&b2wab3yÀb4zWb5zêb6|¹b7}b8}¬b9~ab:žb;)b<ƒ1b=„b>„Úb?…êb@ˆ–bAаbB‹bC8bDBbEƒbF‘lbG’–bH’¹bI–‹bJ–§bK–¨bL–ÖbM—bN˜bO™–bPšÓbQ›bRSÔbSX~bTYbU[pbV[¿bWmÑbXoZbYqŸbZt!b[t¹b\€…b]ƒýb^]áb__‡b`_ªba`BbbeìbchbdiobejSbfk‰bgm5bhmóbisãbjvþbkw¬bl{Mbm}bn#bo‚bpƒ@bq„ôbr…cbsŠbbtŠÄbu‘‡bv“bw˜bx™´byb bzˆSb{ðb|’eb}]b~]'c!]ic"t_c#c$‡hc%oÕc&bþc'Òc(‰6c)‰rc*Nc+NXc,Pçc-RÝc.SGc/bc0fc1~ic2ˆc3–^c4Oc5Sc6V6c7YËc8Z¤c9\8c:\Nc;\Mc<^c=_c>`Cc?e½c@f/cAfBcBg¾cCgôcDscEwâcFy:cGÅcH„”cI„ÍcJ‰–cKŠfcLŠicMŠácNŒUcOŒzcPWôcQ[ÔcR_cS`ocTbícUi cVk–cWn\cXq„cY{ÒcZ‡Uc[‹Xc\Žþc]˜ßc^˜þc_O8c`OcaOácbT{ccZ cd[¸ceaX d?\³d@]½dA^DdB`ádCadDcádEjdFn%dG‘dH“TdI˜NdJœdKŸwdL[‰dM\¸dNc dOfOdPhHdQw[Ce?`Ye@cÚeAeeBemeCf˜eDùzeEiJeFj#eGm eHpeIqleJuÒeKv eLy³eMzpeNù{eOŠePù|eQ‰DeRù}eS‹“eT‘ÀeU–}eVù~eW™ eXWeY_¡eZe¼e[oe\ve]y¦e^Šže_™­e`›ZeaŸlebQeca¶edb‘eejefÆegPCehX0ei_fejq ekŠelŠúem[|en†eoOúepQš[f?V¥f@X'fAYøfBZfC[´fDùŽfE^öfFùfGùfHcPfIc;fJù‘fKi=fLl‡fMl¿fNmŽfOm“fPmõfQofRù’fSpßfTq6fUqYfVù“fWqÃfXqÕfYù”fZxOf[xof\ù•f]{uf^}ãf_ù–f`~/faù—fbˆMfcŽßfdù˜feù™ffùšfg’[fhù›fiœöfjùœfkùflùžfm`…fnm…foùŸfpq±fqù frù¡fs•±ftS­fuù¢fvù£fwù¤fxgÓfyù¥fzpŽf{q0f|t0f}‚vf~‚Òg!ù¦g"•»g#šåg$ž}g%fÄg&ù§g'qÁg(„Ig)ù¨g*ù©g+XKg,ùªg-ù«g.]¸g/_qg0ù¬g1f g2fŽg3iyg4i®g5l8g6lóg7n6g8oAg9oÚg:pg;p/gspg?ù­g@t[gAù®gBtÔgCvÈgDzNgE~“gFù¯gGù°gH‚ñgIŠ`gJÎgKù±gL“HgMù²gN—gOù³gPù´gQNBgRP*gSùµgTRgUSágVfógWlmgXoÊgYs gZwg[zbg\‚®g]…Ýg^†g_ù¶g`ˆÔgaŠcgb‹}gcŒkgdù·ge’³gfù¸gg—gh˜giN”gjO gkOÉglP²gmSHgnT>goT3gpUÚgqXbgrXºgsYggtZgu[ägv`Ÿgwù¹gxaÊgyeVgzeÿg{fdg|h§g}lZg~o³h!pÏh"q¬h#sRh${}h%‡h&Фh'œ2h(Ÿh)\Kh*lƒh+sDh,s‰h-’:h.n«h/teh0vh1zih2~h3† h4Q@h5XÅh6dÁh7tîh8uh9vph:Áh;•h<–Íh=™Th>n&h?tæh@z©hAzªhBåhC†ÙhD‡xhEŠhFZIhG[ŒhH[›hIh¡hJihKmchLs©hMthNt,hOx—hP}éhQëhRhSUhTƒžhUŒLhV–.hW˜hXfðhY_€hZeúh[g‰h\ljh]s‹h^P-h_Zh`kjhawîhbYhc]lhd]Íhes%hfuOhgùºhhù»hiPåhjQùhkX/hlY-hmY–hnYÚho[åhpù¼hqù½hr]¢hsb×htdhud“hvdþhwù¾hxfÜhyù¿hzjHh{ùÀh|qÿh}tdh~ùÁi!zˆi"z¯i#~Gi$~^i%€i&pi'ùÂi(‡ïi)‰i*‹ i+Yi,ùÃi-€i.™Ri/a~i0k2i1mti2~i3‰%i4±i5OÑi6P­i7Q—i8RÇi9WÇi:X‰i;[¹i<^¸i=aBi>i•i?mŒi@ngiAn¶iBq”iCtbiDu(iEu,iF€siGƒ8iH„ÉiIŽ iJ“”iK“ÞiLùÄiMNŽiNOQiOPviPQ*iQSÈiRSËiSSóiT[‡iU[ÓiV\$iWaiXa‚iYeôiZr[i[s—i\t@i]vÂi^yPi_y‘i`y¹ia}ib½ic‚‹id…Õie†^ifÂigGihõii‘êij–…ik–èil–éimRÖin_gioeíipf1iqh/irq\isz6itÁiu˜ ivN‘iwùÅixjRiykžizoi{q‰i|€i}‚¸i~…Sj!Kj"–•j#–òj$—ûj%…j&›1j'Nj(qŠj)–Äj*QCj+SŸj,Táj-Wj.Wj/W£j0Z›j1ZÄj2[Ãj3`(j4a?j5côj6l…j7m9j8nrj9nj:r0j;s?jˆj?Ej@`jAùÆjB–bjC˜XjDjEgjFŠjG’^jHOMjIPIjJPÞjKSqjLW jMYÔjNZjO\ jPapjQfjRn-jSr2jTtKjU}ïjV€ÃjW„jX„fjY…?jZ‡_j[ˆ[j\‰j]‹j^Uj_—Ëj`›OjaNsjbO‘jcQjdQjjeùÇjfU/jgU©jh[zji[¥jj^|jk^}jl^¾jm` jn`ßjoajpa jqcÄjre8jsg jtùÈjugÔjvgÚjwùÉjxiajyibjzl¹j{m'j|ùÊj}n8j~ùËk!oák"s6k#s7k$ùÌk%t\k&u1k'ùÍk(vRk)ùÎk*ùÏk+}­k,þk-„8k.ˆÕk/Š˜k0ŠÛk1Šík2Ž0k3ŽBk4Jk5>k6zk7‘Ik8‘Ék9“nk:ùÐk;ùÑkkÓk?€‰k@€²kAùÓkBùÔkCQAkDYkkE\9kFùÕkGùÖkHodkIs§kJ€äkKkLù×kM’kN•kOùØkPùÙkQùÚkRùÛkS€kTbkUpkV}hkW‡kXùÜkYW kZ`ik[aGk\k·k]оk^’€k_–±k`NYkaTkbmëkc…-kd–pke—ókf˜îkgcÖkhlãki‘kjQÝkkaÉklºkmùknOkoPkpQkq[œkraksaÿktdìkuikvkÅkwu‘kxwãky©kz‚dk{…k|‡ûk}ˆck~мl!‹pl"‘«l#NŒl$Nål%O l&ùÝl'ùÞl(Y7l)Yèl*ùßl+]òl,_l-_[l.`!l/ùàl0ùál1ùâl2ùãl3r>l4sål5ùäl6upl7uÍl8ùål9yûl:ùæl;€ l<€3l=€„l>‚ál?ƒQl@ùçlAùèlBŒ½lCŒ³lD‡lEùélFùêlG˜ôlH™ lIùëlJùìlKp7lLvÊlMÊlNÌlOülP‹lQNºlRNÁlSRlTSplUùílVT½lWVàlXYûlY[ÅlZ_l[_Íl\nnl]ùîl^ùïl_}jl`ƒ5laùðlb†“lcŠldùñle—mlf—wlgùòlhùóliNljOZlkO~llXùlmeålnn¢lo8lp“°lq™¹lrNûlsXìltYŠluYÙlv`Alwùôlxùõlyzlzùöl{ƒOl|ŒÃl}Qel~SDm!ù÷m"ùøm#ùùm$NÍm%Rim&[Um'‚¿m(NÔm)R:m*T¨m+YÉm,Yÿm-[Pm.[Wm/[\m0`cm1aHm2nËm3p™m4qnm5s†m6t÷m7uµm8xÁm9}+m:€m;êm<ƒ(m=…m>…Ém?Šîm@ŒÇmA–ÌmBO\mCRúmDV¼mEe«mFf(mGp|mHp¸mIr5mJ}½mK‚mL‘LmM–ÀmNrmO[qmPhçmQk˜mRozmSvÞmT\‘mUf«mVo[mW{´mX|*mYˆ6mZ–Üm[Nm\N×m]S m^X4m_X»m`XïmaYlmb\mc^3md^„me_5mfcŒmgf²mhgVmijmjj£mkk mlo?mmrFmnùúmosPmpt‹mqzàmr|§msxmtßmuçmvƒŠmw„lmx…#my…”mz…Ïm{ˆÝm|m}‘¬m~•wn!–œn"Qn#TÉn$W(n%[°n&bMn'gPn(h=n)h“n*n=n+nÓn,p}n-~!n.ˆÁn/Œ¡n0 n1ŸKn2ŸNn3r-n4{n5ŠÍn6“n7OGn8ONn9Q2n:T€n;YÐn<^•n=bµn>gun?inn@jnAl®nBnnCrÙnDs*nEu½nF{¸nG}5nH‚çnIƒùnJ„WnK…÷nLŠ[nMŒ¯nNއnOnP¸nQ–ÎnRŸ_nSRãnTT nUZánV[ÂnWdXnXeunYnônZrÄn[ùûn\v„n]zMn^{n_|Mn`~>naßnbƒ{nc‹+ndŒÊnednfángŽ_nhêniùnjink“ÑnlOCnmOznnP³noQhnpQxnqRMnrRjnsXantX|nuY`nv\nw\Unx^Ûny`›nzb0n{hn|k¿n}ln~o±o!qNo"t o#u0o$u8o%uQo&vro'{Lo({‹o){­o*{Æo+~o,Šno->o.Io/’?o0’“o1“"o2”+o3–ûo4˜Zo5˜ko6™o7Ro8b*o9b˜o:mYo;vdo}vo?S`o@\¾oA^—oBo8oCp¹oD|˜oE—oF›ŽoGžÞoHc¥oIdzoJ‡voKNoLN•oMN­oNP\oOPuoPTHoQYÃoR[šoS^@oT^­oU^÷oV_oW`ÅoXc:oYe?oZeto[eÌo\fvo]fxo^gþo_iho`j‰oakcobl@ocmÀodmèoenofn^ogpohp¡oisŽojsýoku:olw[omx‡onyŽooz opz}oq|¾or}Žos‚GotŠouŠêovŒžow‘-ox‘Joy‘Øoz’fo{’Ìo|“ o}—o~—Vp!—\p"˜p#Ÿp$R6p%R‘p&U|p'X$p(^p)_p*`Œp+cÐp,h¯p-oßp.ymp/{,p0Íp1…ºp2ˆýp3Šøp4ŽDp5‘p6–dp7–›p8—=p9˜Lp:ŸJp;OÎpR©p?V2p@_pA_kpBcªpCdÍpDeépEfApFfúpGfùpHgpIhpJh×pKiýpLopMonpNqgpOqåpPr*pQtªpRw:pSyVpTyZpUyßpVz pWz•pX|—pY|ßpZ}Dp[~pp\€‡p]…ûp^†¤p_ŠTp`Š¿pa™pbŽpc pdmpe‘ãpf–;pg–ÕphœåpieÏpj|pk³pl“Ãpm[Xpn\ poSRppbÙpqsprP'ps[—pt_žpu`°pvakpwhÕpxmÙpyt.pzz.p{}Bp|}œp}~1p~kq!Ž*q"Ž5q#“~q$”q%OPq&WPq']æq(^§q)c+q*jq+N;q,OOq-Oq.PZq/YÝq0€Äq1Tjq2Thq3Uþq4YOq5[™q6]Þq7^Úq8f]q9g1q:gñq;h*qnJq?oq@p·qAsàqBu‡qC|LqD}qE},qF}¢qG‚qH†ÛqIŠ;qJŠ…qKpqLŽŠqM3qN1qO‘NqP‘RqQ”DqR™ÐqSzùqT|¥qUOÊqVQqWQÆqXWÈqY[ïqZ\ûq[fYq\j=q]mZq^n–q_oìq`q qauoqbzãqcˆ"qd!qeuqf–Ëqg™ÿqhƒqiN-qjNòqkˆFql‘ÍqmS}qnjÛqoikqplAqq„zqrXžqsaŽqtfþqubïqvpÝqwuqxuÇqy~Rqz„¸q{‹Iq|q}NKq~Sêr!T«r"W0r#W@r$_×r%cr&cr'dor(e/r)eèr*fzr+gr,g³r-kbr.l`r/lšr0o,r1wår2x%r3yIr4yWr5}r6€¢r7r8ór9‚r:‚·r;‡r<ŠŒr=ùür>r?¾r@rrAvôrBzrCz7rD~TrE€wrFUrGUÔrHXurIc/rJd"rKfIrLfKrMhmrNi›rOk„rPm%rQn±rRsÍrSthrTt¡rUu[rVu¹rWvárXwrYw‹rZyær[~ r\~r]ûr^…/r_ˆ—r`Š:raŒÑrbŽërc°rd2re“­rf–crg–srh—riO„rjSñrkYêrlZÉrm^rnhNrotÆrpu¾rqyérrz’rs£rt†íruŒêrvÌrwírxeŸrygrzùýr{W÷r|oWr}}Ýr~/s!“ös"–Æs#_µs$aòs%o„s&Ns'O˜s(Ps)SÉs*Ußs+]os,]îs-k!s.kds/xËs0{šs1ùþs2ŽIs3ŽÊs4ns5cIs6d>s7w@s8z„s9“/s:”s;Ÿjsqæs?t¨s@tÚsAzÄsB|sC~‚sD|²sE~˜sF‹šsG sH”}sI™sJ™LsKR9sL[ßsMdæsNg-sO}.sPPísQSÃsRXysSaXsTaYsUaúsVe¬sWzÙsX‹’sY‹–sZP s[P!s\Rus]U1s^Zzt?‚t@…¦tAŒätBŽtCwtD‘çtE•átF–!tG—ÆtHQøtITòtJU†tK_¹tLd¤tMoˆtN}´tOtPMtQ”5tRPÉtS\tTl¾tUmûtVutWw»tX|=tY|dtZŠyt[ŠÂt\Xt]Y¾t^^t_cwt`rRtauŠtbwktcŠÜtdŒ¼tetf^ótgftthmøti€}tjƒÁtkŠËtl—Qtm›ÖtnútoRCtpfÿtqm•trnïts}àttŠætu.tv^twšÔtxRtyRtzTèt{a”t|b„t}bÛt~h¢u!iu"iZu#j5u$p’u%q&u&x]u'yu(yu)yÒu*z u+€–u,‚xu-‚Õu.ƒIu/…Iu0Œ‚u1…u2‘bu3‘‹u4‘®u5OÃu6VÑu7qíu8w×u9‡u:‰øu;[øu<_Öu=gQu>¨u?Sâu@XZuA[õuB`¤uCauDd`uE~=uF€puG…%uH’ƒuId®uJP¬uK]uLguMXœuNb½uOc¨uPiuQixuRjuSnkuTvºuUyËuV‚»uW„)uXŠÏuY¨uZýu[‘u\‘Ku]‘œu^“u_“u`“šua–Ûubš6ucœ udNueu\ufy]ugzúuh{Qui{Éuj~.uk„ÄulŽYumŽtunŽøuoupf%uqi?urtCusQúutg.uužÜuvQEuw_àuxl–uy‡òuzˆ]u{ˆwu|`´u}µu~„v!v"SÖv#T9v$V4v%Z6v&\1v'pŠv(àv)€Zv*v+ív,£v-‘‰v.š_v/òv0Ptv1NÄv2S v3`ûv4n,v5\dv6Oˆv7P$v8Uäv9\Ùv:^_v;`evmÄv?q¾v@uÔvAuôvBvavCzvDzIvE}ÇvF}ûvGnvHôvI†©vJvK–ÉvL™³vMŸRvNRGvORÅvP˜ívQ‰ªvRNvSgÒvTovUOµvV[âvWg•vXlˆvYmxvZtv[x'v\‘Ýv]“|v^‡Äv_yäv`z1va_ëvbNÖvcT¤vdU>veX®vfY¥vg`ðvhbSvibÖvjg6vkiUvl‚5vm–@vn™±vo™ÝvpP,vqSSvrUDvsW|vtúvubXvvúvwdâvxfkvygÝvzoÁv{oïv|t"v}t8v~Šw!”8w"TQw#Vw$Wfw%_Hw&ašw'kNw(pXw)p­w*}»w+Š•w,Yjw-+w.c¢w/ww0€=w1Œªw2XTw3d-w4i»w5[•w6^w7now8úw9…iw:QLw;SðwaKw?k†w@lpwAlðwB{wC€ÎwD‚ÔwEÆwF°wG˜±wHúwIdÇwJo¤wKd‘wLewMQNwNTwOWwPŠwQa_wRhvwSúwTuÛwU{RwV}qwWwXXwYiÌwZw[‰*w\w]˜9w^Pxw_YWw`Y¬wab•wbwc›*wda]werywf•ÖwgWawhZFwi]ôwjbŠwkd­wldúwmgwwnlâwom>wpr,wqt6wrx4wswwt‚­wuÛwv˜wwR$wxWBwygwzrHw{tãw|Œ©w}¦w~’x!–*x"Qkx#Síx$cLx%Oix&Ux'`–x(eWx)l›x*mx+rLx,rýx-zx.‰‡x/Œx0_mx1oŽx2pùx3¨x4ax5O¿x6POx7bAx8rGx9{Çx:}èx;éxšx?Œ¶x@WjxA^sxBg°xC„ xDŠUxET xF[xG^cxH^âxI_ xJeƒxK€ºxL…=xM•‰xN–[xOOHxPSxQS xRSxST†xTTúxUWxV^xW`xXb›xYb±xZcUx[úx\láx]mfx^u±x_x2x`€Þxa/xb‚Þxc„axd„²xeˆxf‰xg xh’êxi˜ýxj›‘xk^Exlf´xmfÝxnpxorxpúxqOõxrR}xs_jxtaSxugSxvjxwoxxtâxyyhxzˆhx{Œyx|˜Çx}˜Äx~šCy!TÁy"zy#iSy$Š÷y%ŒJy&˜¨y'™®y(_|y)b«y*u²y+v®y,ˆ«y-y.–By/S9y0_Yy?^Èy@f0yAl³yBtUyCƒwyD‡fyEŒÀyFPyG—yHœyIXÑyJ[xyK†PyL‹yM´yN[ÒyO`hyP`yQeñyRlWySo"yTo£yUpyVUyWðyX•‘yY•’yZ–Py[—Óy\Rry]Dy^Qýy_T+y`T¸yaUcybUŠycj»ydmµye}Øyf‚fyg’œyh–wyižyyjTykTÈylvÒym†äyn•¤yo•Ôyp–\yqN¢yrO ysYîytZæyu]÷yv`Rywb—yxgmyyhAyzl†y{n/y|8y}€›y~‚*z!úz"ú z#˜z$N¥z%PUz&T³z'W“z(YZz)[iz*[³z+aÈz,iwz-mwz.p#z/‡ùz0‰ãz1Šrz2Šçz3‚z4™íz5š¸z6R¾z7h8z8Pz9^xz:gOz;ƒGz<ˆLz=N«z>Tz?V®z@sæzA‘zB—ÿzC™ zD™WzE™™zFVSzGXŸzH†[zIŠ1zJa²zKjözLs{zMŽÒzNkGzO–ªzPšWzQYUzRrzSkzT—izUOÔzV\ôzW_&zXaøzYf[zZlëz[p«z\s„z]s¹z^sþz_w)z`wMza}Czb}bzc~#zd‚7zeˆRzfú zgŒâzh’Izi˜ozj[Qzkztzlˆ@zm˜znZÌzoOàzpSTzqY>zr\ýzsc>ztmyzurùzvzwzxƒ¢zy’Ïzz˜0z{N¨z|QDz}Rz~W‹{!_b{"lÂ{#nÎ{$p{%pP{&p¯{'q’{(sé{)ti{*ƒJ{+‡¢{,ˆa{-{.¢{/“£{0™¨{1Qn{2_W{3`à{4ag{5f³{6…Y{7ŽJ{8‘¯{9—‹{:NN{;N’{Xú{?Y}{@\µ{A_'{Bb6{CbH{Df {Efg{Fkë{Gmi{HmÏ{InV{Jnø{Ko”{Loà{Moé{Np]{OrÐ{Pt%{QtZ{Rtà{Sv“{Ty\{U|Ê{V~{W€á{X‚¦{Y„k{Z„¿{[†N{\†_{]‡t{^‹w{_Œj{`“¬{a˜{b˜e{c`Ñ{db{e‘w{fZZ{gf{hm÷{in>{jt?{k›B{l_ý{m`Ú{n{{oTÄ{p_{ql^{rlÓ{sm*{tpØ{u}{v†y{wŠ {x;{yS{zTŒ{{[{|j:{}pk{~uu|!y|"y¾|#‚±|$ƒï|%Šq|&‹A|'Œ¨|(—t|)ú |*dô|+e+|,xº|-x»|.zk|/N8|0Uš|1YP|2[¦|3^{|4`£|5cÛ|6ka|7fe|8hS|9n|:qe|;t°|<}|=„|>ši|?œ%|@m;|AnÑ|Bs>|CŒA|D•Ê|EQð|F^L|G_¨|H`M|I`ö|Ja0|KaL|LfC|MfD|Ni¥|OlÁ|Pn_|QnÉ|Rob|SqL|Ttœ|Uv‡|V{Á|W|'|XƒR|Y‡W|ZQ|[–|\žÃ|]S/|^VÞ|_^û|`_Š|a`b|b`”|ca÷|dff|eg|fjœ|gmî|ho®|ipp|jsj|k~j|l¾|mƒ4|n†Ô|oЍ|pŒÄ|qRƒ|rsr|s[–|tjk|u”|vTî|wV†|x[]|yeH|ze…|{fÉ||hŸ|}m|~mÆ}!r;}"€´}#‘u}$šM}%O¯}&P}'Sš}(T})T<}*U‰}+UÅ},^?}-_Œ}.g=}/qf}0sÝ}1}2RÛ}3Ró}4Xd}5XÎ}6q}7q}8qû}9…°}:Š};fˆ}<…¨}=U§}>f„}?qJ}@„1}ASI}BU™}CkÁ}D_Y}E_½}Fcî}Gf‰}HqG}IŠñ}J}Kž¾}LO}Md:}NpË}Ouf}P†g}Q`d}R‹N}Sø}TQG}UQö}VS}Wm6}X€ø}YžÑ}Zf}[k#}\p˜}]uÕ}^T}_\y}`}}aŠ}bk }ck=}dkF}eT8}f`p}gm=}hÕ}i‚}jPÖ}kQÞ}lUœ}mVk}nVÍ}oYì}p[ }q^ }ra™}sa˜}tb1}uf^}vfæ}wq™}xq¹}yqº}zr§}{y§}|z}}²}~Špscreen-4.1.0/utf8encodings/040000644000175000017500000005735611642704565014013 0ustar abeabeScreenI2UTF8³JIS X 0212 (1990)"/Ø"0Ç"1¸"2Ù"3Ý"4¯"5Û"6Ú"7~"8„"9…"B¡"C¦"D¿"kº"lª"m©"n®"o!""p¤"q!&a†&bˆ&c‰&dŠ&eª&gŒ&iŽ&j«&l&q¬&r­&s®&t¯&uÊ&v&wÌ&xÂ&yÍ&zË&{°&|Î'B'C'D'E'F'G'H'I 'J 'K 'L 'M'N'rR'sS'tT'uU'vV'wW'xX'yY'zZ'{['|\'}^'~_)!Æ)")$&)&2)(A))?)+J),Ø)-R)/f)0Þ)Aæ)B)Cð)D')E1)F3)G8)HB)I@)JI)KK)Lø)MS)Nß)Og)Pþ*!Á*"À*#Ä*$Â*%*&Í*'*(*)Å**Ã*+*,*- *.Ç*/ *0*1É*2È*3Ë*4Ê*5*6*7*8*:*;*<"*= *>$*?Í*@Ì*AÏ*BÎ*CÏ*D0*E**F.*G(*H4*I6*J9*K=*L;*MC*NG*OE*PÑ*QÓ*RÒ*SÖ*TÔ*UÑ*VP*WL*XÕ*YT*ZX*[V*\Z*]\*^`*_^*`d*ab*bÚ*cÙ*dÜ*eÛ*fl*gÓ*hp*ij*jr*kn*lh*m×*nÛ*oÙ*pÕ*qt*rÝ*sx*tv*uy*v}*w{+!á+"à+#ä+$â+%+&Î+'+(+)å+*ã+++, +- +.ç+/ +0+1é+2è+3ë+4ê+5+6+7+8+9õ+:+;+=!+>%+?í+@ì+Aï+Bî+CÐ+E++F/+G)+H5+I7+J:+K>+L<+MD+NH+OF+Pñ+Qó+Rò+Sö+Tô+UÒ+VQ+WM+Xõ+YU+ZY+[W+\[+]]+^a+__+`e+ac+bú+cù+dü+eû+fm+gÔ+hq+ik+js+ko+li+mØ+nÜ+oÚ+pÖ+qu+rý+sÿ+tw+uz+v~+w|0!N0"N0#N0$N 0%N0&N0'N#0(N$0)N(0*N+0+N.0,N/0-N00.N50/N@00NA01ND02NG03NQ04NZ05N\06Nc07Nh08Ni09Nt0:Nu0;Ny0N–0?N—0@N0AN¯0BN¹0CNÃ0DNÐ0ENÚ0FNÛ0GNà0HNá0INâ0JNè0KNï0LNñ0MNó0NNõ0ONý0PNþ0QNÿ0RO0SO0TO0UO0VO 0WO 0XO0YO0ZO0[O0\O0]O.0^O10_O`0`O30aO50bO70cO90dO;0eO>0fO@0gOB0hOH0iOI0jOK0kOL0lOR0mOT0nOV0oOX0pO_0qOc0rOj0sOl0tOn0uOq0vOw0wOx0xOy0yOz0zO}0{O~0|O0}O‚0~O„1!O…1"O‰1#OŠ1$OŒ1%OŽ1&O1'O’1(O“1)O”1*O—1+O™1,Oš1-Ož1.OŸ1/O²10O·11O¹12O»13O¼14O½15O¾16OÀ17OÁ18OÅ19OÆ1:OÈ1;OÉ1OÍ1?OÏ1@OÒ1AOÜ1BOà1COâ1DOð1EOò1FOü1GOý1HOÿ1IP1JP1KP1LP1MP 1NP 1OP1PP1QP1RP1SP1TP1UP1VP1WP1XP"1YP'1ZP.1[P01\P21]P31^P51_P@1`PA1aPB1bPE1cPF1dPJ1ePL1fPN1gPQ1hPR1iPS1jPW1kPY1lP_1mP`1nPb1oPc1pPf1qPg1rPj1sPm1tPp1uPq1vP;1wP1xPƒ1yP„1zP†1{PŠ1|PŽ1}P1~P2!P’2"P“2#P”2$P–2%P›2&Pœ2'Pž2(PŸ2)P 2*P¡2+P¢2,Pª2-P¯2.P°2/P¹20Pº21P½22PÀ23PÃ24PÄ25PÇ26PÌ27PÎ28PÐ29PÓ2:PÔ2;PØ2Pß2?Pâ2@Pä2APæ2BPè2CPé2DPï2EPñ2FPö2GPú2HPþ2IQ2JQ2KQ2LQ2MQ 2NQ 2OQ 2PQ2QPò2RQ2SQ2TQ2UQ2VQ2WQ2XQ2YQ#2ZQ'2[Q(2\Q,2]Q-2^Q/2_Q12`Q32aQ42bQ52cQ82dQ92eQB2fQJ2gQO2hQS2iQU2jQW2kQX2lQ_2mQd2nQf2oQ~2pQƒ2qQ„2rQ‹2sQŽ2tQ˜2uQ2vQ¡2wQ£2xQ­2yQ¸2zQº2{Q¼2|Q¾2}Q¿2~QÂ3!QÈ3"QÏ3#QÑ3$QÒ3%QÓ3&QÕ3'QØ3(QÞ3)Qâ3*Qå3+Qî3,Qò3-Qó3.Qô3/Q÷30R31R32R33R34R35R36R37R38R"39R(3:R13;R23RE3?RI3@RU3ARW3BRX3CRZ3DR\3ER_3FR`3GRa3HRf3IRn3JRw3KRx3LRy3MR€3NR‚3OR…3PRŠ3QRŒ3RR“3SR•3TR–3UR—3VR˜3WRš3XRœ3YR¤3ZR¥3[R¦3\R§3]R¯3^R°3_R¶3`R·3aR¸3bRº3cR»3dR½3eRÀ3fRÄ3gRÆ3hRÈ3iRÌ3jRÏ3kRÑ3lRÔ3mRÖ3nRÛ3oRÜ3pRá3qRå3rRè3sRé3tRê3uRì3vRð3wRñ3xRô3yRö3zR÷3{S3|S3}S 3~S 4!S 4"S4#S4$S4%S4&S4'S4(S4)S%4*S'4+S(4,S)4-S+4.S,4/S-40S041S242S543S<44S=45S>46SB47SL48SK49SY4:S[4;Sa4Sl4?Sm4@Sr4ASy4BS~4CSƒ4DS‡4ESˆ4FSŽ4GS“4HS”4IS™4JS4KS¡4LS¤4MSª4NS«4OS¯4PS²4QS´4RSµ4SS·4TS¸4USº4VS½4WSÀ4XSÅ4YSÏ4ZSÒ4[SÓ4\SÕ4]SÚ4^SÝ4_SÞ4`Sà4aSæ4bSç4cSõ4dT4eT4fT4gT!4hT'4iT(4jT*4kT/4lT14mT44nT54oTC4pTD4qTG4rTM4sTO4tT^4uTb4vTd4wTf4xTg4yTi4zTk4{Tm4|Tn4}Tt4~T5!T5"Tƒ5#T…5$Tˆ5%T‰5&T5'T‘5(T•5)T–5*Tœ5+TŸ5,T¡5-T¦5.T§5/T©50Tª51T­52T®53T±54T·55T¹56Tº57T»58T¿59TÆ5:TÊ5;TÍ5Tê5?Tì5@Tï5ATö5BTü5CTþ5DTÿ5EU5FU5GU5HU5IU 5JU 5KU 5LU5MU5NU*5OU+5PU25QU55RU65SU;5TU<5UU=5VUA5WUG5XUI5YUJ5ZUM5[UP5\UQ5]UX5^UZ5_U[5`U^5aU`5bUa5cUd5dUf5eU5fU5gU‚5hU†5iUˆ5jUŽ5kU5lU‘5mU’5nU“5oU”5pU—5qU£5rU¤5sU­5tU²5uU¿5vUÁ5wUÃ5xUÆ5yUÉ5zUË5{UÌ5|UÎ5}UÑ5~UÒ6!UÓ6"U×6#UØ6$UÛ6%UÞ6&Uâ6'Ué6(Uö6)Uÿ6*V6+V6,V 6-V 6.V6/V60V61V62V63V64V,65V066V367V568V769V96:V;6;V<6V@6?VA6@VC6AVD6BVF6CVI6DVK6EVM6FVO6GVT6HV^6IV`6JVa6KVb6LVc6MVf6NVi6OVm6PVo6QVq6RVr6SVu6TV„6UV…6VVˆ6WV‹6XVŒ6YV•6ZV™6[Vš6\V6]Vž6^VŸ6_V¦6`V§6aV¨6bV©6cV«6dV¬6eV­6fV±6gV³6hV·6iV¾6jVÅ6kVÉ6lVÊ6mVË6nVÏ6oVÐ6pVÌ6qVÍ6rVÙ6sVÜ6tVÝ6uVß6vVá6wVä6xVå6yVæ6zVç6{Vè6|Vñ6}Vë6~Ví7!Vö7"V÷7#W7$W7%W7&W 7'W 7(W7)W7*W7+W7,W7-W 7.W"7/W#70W$71W%72W)73W*74W,75W.76W/77W378W479W=7:W>7;W?7WL7?WM7@WR7AWb7BWe7CWg7DWh7EWk7FWm7GWn7HWo7IWp7JWq7KWs7LWt7MWu7NWw7OWy7PWz7QW{7RW|7SW~7TW7UWƒ7VWŒ7WW”7XW—7YW™7ZWš7[Wœ7\W7]Wž7^WŸ7_W¡7`W•7aW§7bW¨7cW©7dW¬7eW¸7fW½7gWÇ7hWÈ7iWÌ7jWÏ7kWÕ7lWÝ7mWÞ7nWä7oWæ7pWç7qWé7rWí7sWð7tWõ7uWö7vWø7wWý7xWþ7yWÿ7zX7{X7|X7}X 7~Wá8!X 8"X 8#X8$X8%X8&X 8'X&8(X'8)X-8*X28+X98,X?8-XI8.XL8/XM80XO81XP82XU83X_84Xa85Xd86Xg87Xh88Xx89X|8:X8;X€8Xˆ8?X‰8@XŠ8AXŒ8BX8CX8DX8EX”8FX–8GX8HX 8IX¡8JX¢8KX¦8LX©8MX±8NX²8OXÄ8PX¼8QXÂ8RXÈ8SXÍ8TXÎ8UXÐ8VXÒ8WXÔ8XXÖ8YXÚ8ZXÝ8[Xá8\Xâ8]Xé8^Xó8_Y8`Y8aY 8bY 8cY8dY8eY8f†A8gY8hY!8iY#8jY$8kY(8lY/8mY08nY38oY58pY68qY?8rYC8sYF8tYR8uYS8vYY8wY[8xY]8yY^8zY_8{Ya8|Yc8}Yk8~Ym9!Yo9"Yr9#Yu9$Yv9%Yy9&Y{9'Y|9(Y‹9)YŒ9*YŽ9+Y’9,Y•9-Y—9.YŸ9/Y¤90Y§91Y­92Y®93Y¯94Y°95Y³96Y·97Yº98Y¼99YÁ9:YÃ9;YÄ9YÍ9?YÒ9@YÝ9AYÞ9BYß9CYã9DYä9EYç9FYî9GYï9HYñ9IYò9JYô9KY÷9LZ9MZ9NZ 9OZ 9PZ9QZ9RZ9SZ9TZ#9UZ$9VZ'9WZ(9XZ*9YZ-9ZZ09[ZD9\ZE9]ZG9^ZH9_ZL9`ZP9aZU9bZ^9cZc9dZe9eZg9fZm9gZw9hZz9iZ{9jZ~9kZ‹9lZ9mZ“9nZ–9oZ™9pZœ9qZž9rZŸ9sZ 9tZ¢9uZ§9vZ¬9wZ±9xZ²9yZ³9zZµ9{Z¸9|Zº9}Z»9~Z¿:!ZÄ:"ZÆ:#ZÈ:$ZÏ:%ZÚ:&ZÜ:'Zà:(Zå:)Zê:*Zî:+Zõ:,Zö:-Zý:.[:/[:0[:1[:2[4:3[:4[:5[:6[!:7[%:8[-:9[8::[A:;[K:<[L:=[R:>[V:?[^:@[h:A[n:B[o:C[|:D[}:E[~:F[:G[:H[„:I[†:J[Š:K[Ž:L[:M[‘:N[“:O[”:P[–:Q[¨:R[©:S[¬:T[­:U[¯:V[±:W[²:X[·:Y[º:Z[¼:[[À:\[Á:][Í:^[Ï:_[Ö:`[×:a[Ø:b[Ù:c[Ú:d[à:e[ï:f[ñ:g[ô:h[ý:i\ :j\:k\:l\:m\#:n\&:o\):p\+:q\,:r\.:s\0:t\2:u\5:v\6:w\Y:x\Z:y\\:z\b:{\c:|\g:}\h:~\i;!\m;"\p;#\t;$\u;%\z;&\{;'\|;(\};)\‡;*\ˆ;+\Š;,\;-\’;.\;/\Ÿ;0\ ;1\¢;2\£;3\¦;4\ª;5\²;6\´;7\µ;8\º;9\É;:\Ë;;\Ò;<\Ý;=\×;>\î;?\ñ;@\ò;A\ô;B];C];D] ;E];F]+;G]#;H]$;I]&;J]';K]1;L]4;M]9;N]=;O]?;P]B;Q]C;R]F;S]H;T]U;U]Q;V]Y;W]J;X]_;Y]`;Z]a;[]b;\]d;]]j;^]m;_]p;`]y;a]z;b]~;c];d];e]ƒ;f]ˆ;g]Š;h]’;i]“;j]”;k]•;l]™;m]›;n]Ÿ;o] ;p]§;q]«;r]°;s]´;t]¸;u]¹;v]Ã;w]Ç;x]Ë;y]Ð;z]Î;{]Ø;|]Ù;}]à;~]ä<2^K<3^P<4^I<5^Q<6^V<7^X<8^[<9^\<:^^<;^h<<^j<=^k<>^l_Ñ=?_Ò=@_Ó=A_Ô=B_Þ=C_á=D_â=E_è=F_é=G_ê=H_ì=I_í=J_î=K_ï=L_ò=M_ó=N_ö=O_ú=P_ü=Q`=R` =S` =T`=U`=V`=W`=X`=Y`=Z`$=[`-=\`3=]`5=^`@=_`G=``H=a`I=b`L=c`Q=d`T=e`V=f`W=g`]=h`a=i`g=j`q=k`~=l`=m`‚=n`†=o`ˆ=p`Š=q`Ž=r`‘=s`“=t`•=u`˜=v`=w`ž=x`¢=y`¤=z`¥={`¨=|`°=}`±=~`·>!`»>"`¾>#`Â>$`Ä>%`È>&`É>'`Ê>(`Ë>)`Î>*`Ï>+`Ô>,`Õ>-`Ù>.`Û>/`Ý>0`Þ>1`â>2`å>3`ò>4`õ>5`ø>6`ü>7`ý>8a>9a>:a >;a >=a>>a>?a>@a>Aa>Ba>Ca>Da>Ea>Fa">Ga*>Ha+>Ia0>Ja1>Ka5>La6>Ma7>Na9>OaA>PaE>QaF>RaI>Sa^>Ta`>Ual>Var>Wax>Xa{>Ya|>Za>[a€>\a>]aƒ>^a„>_a‹>`a>aa’>ba“>ca—>da˜>eaœ>fa>gaŸ>ha >ia¥>ja¨>kaª>la­>ma¸>na¹>oa¼>paÀ>qaÁ>raÂ>saÎ>taÏ>uaÕ>vaÜ>waÝ>xaÞ>yaß>zaá>{aâ>|aç>}aé>~aå?!aì?"aí?#aï?$b?%b?&b?'b?(b?)b?*b?+b ?,b"?-b#?.b'?/b)?0b+?1b9?2b=?3bB?4bC?5bD?6bF?7bL?8bP?9bQ?:bR?;bT?b\??bd?@bm?Abo?Bbs?Cbz?Db}?Eb?FbŽ?Gb?Hb?Ib¦?Jb¨?Kb³?Lb¶?Mb·?Nbº?Ob¾?Pb¿?QbÄ?RbÎ?SbÕ?TbÖ?UbÚ?Vbê?Wbò?Xbô?Ybü?Zbý?[c?\c?]c ?^c ?_c ?`c?ac?bc?cc?dc)?ec*?fc-?gc5?hc6?ic9?jccà@?cå@@cê@Acì@Bcò@Ccó@Dcõ@Ecø@Fcù@Gd @Hd @Id@Jd@Kd@Ld@Md@Nd @Od"@Pd$@Qd%@Rd)@Sd*@Td/@Ud0@Vd5@Wd=@Xd?@YdK@ZdO@[dQ@\dR@]dS@^dT@_dZ@`d[@ad\@bd]@cd_@dd`@eda@fdc@gdm@hds@idt@jd{@kd}@ld…@md‡@nd@od@pd‘@qd˜@rd™@sd›@td@udŸ@vd¡@wd£@xd¦@yd¨@zd¬@{d³@|d½@}d¾@~d¿A!dÄA"dÉA#dÊA$dËA%dÌA&dÎA'dÐA(dÑA)dÕA*d×A+däA,dåA-déA.dêA/díA0dðA1dõA2d÷A3dûA4dÿA5eA6eA7eA8e A9e A:eA;eAeA?eA@eAAeABe"ACe&ADe)AEe.AFe1AGe:AHefaB?fûB@fjBAfkBBflBCf~BDfsBEfuBFfBGfwBHfxBIfyBJf{BKf€BLf|BMf‹BNfŒBOfBPfBQf’BRf™BSfšBTf›BUfœBVfŸBWf BXf¤BYf­BZf±B[f²B\fµB]f»B^f¿B_fÀB`fÂBafÃBbfÈBcfÌBdfÎBefÏBffÔBgfÛBhfßBifèBjfëBkfìBlfîBmfúBngBogBpgBqgBrgBsgBtg Bug"Bvg3Bwg>BxgEBygGBzgHB{gLB|gTB}gUB~g]C!gfC"glC#gnC$gtC%gvC&g{C'gC(g„C)gŽC*gC+g‘C,g“C-g–C.g˜C/g™C0g›C1g°C2g±C3g²C4gµC5g»C6g¼C7g½C8gùC9gÀC:gÂC;gÃCgÉC?gÒC@g×CAgÙCBgÜCCgáCDgæCEgðCFgòCGgöCHg÷CIhRCJhCKhCLhCMhCNh(COh'CPh,CQh-CRh/CSh0CTh1CUh3CVh;CWh?CXhDCYhECZhJC[hLC\hUC]hWC^hXC_h[C`hkCahnCbhoCchpCdhqCehrCfhuCghyChhzCih{Cjh|Ckh‚Clh„Cmh†CnhˆCoh–Cph˜CqhšCrhœCsh¡Cth£Cuh¥Cvh©CwhªCxh®Cyh²Czh»C{hÅC|hÈC}hÌC~hÏD!hÐD"hÑD#hÓD$hÖD%hÙD&hÜD'hÝD(håD)hèD*hêD+hëD,hìD-híD.hðD/hñD0hõD1höD2hûD3hüD4hýD5iD6i D7i D8iD9iD:iD;iDi3D?i5D@i8DAi;DBiBDCiEDDiIDEiNDFiWDGi[DHicDIidDJieDKifDLihDMiiDNilDOipDPiqDQirDRizDSi{DTiDUi€DViDWi’DXi–DYi˜DZi¡D[i¥D\i¦D]i¨D^i«D_i­D`i¯Dai·Dbi¸DciºDdi¼DeiÅDfiÈDgiÑDhiÖDii×DjiâDkiåDliîDmiïDniñDoióDpiõDqiþDrjDsjDtjDujDvjDwjDxjDyjDzj D{j$D|j(D}j0D~j2E!j4E"j7E#j;E$j>E%j?E&jEE'jFE(jIE)jJE*jNE+jPE,jQE-jRE.jUE/jVE0j[E1jdE2jgE3jjE4jqE5jsE6j~E7jE8jƒE9j†E:j‡E;j‰Ej›E?jE@jžEAjŸEBj¥ECj«EDj¯EEj°EFj±EGj´EHj½EIj¾EJj¿EKjÆELjÉEMjÈENjÌEOjÐEPjÔEQjÕERjÖESjÜETjÝEUjäEVjçEWjìEXjðEYjñEZjòE[jüE\jýE]kE^kE_kE`kEak EbkEckEdkEekEfkEgkEhk$Eik(Ejk+Ekk,Elk/Emk5Enk6Eok;Epk?EqkFErkJEskMEtkREukVEvkXEwk]Exk`EykgEzkkE{knE|kpE}kuE~k}F!k~F"k‚F#k…F$k—F%k›F&kŸF'k F(k¢F)k£F*k¨F+k©F,k¬F-k­F.k®F/k°F0k¸F1k¹F2k½F3k¾F4kÃF5kÄF6kÉF7kÌF8kÖF9kÚF:káF;kãFkîF?kñF@k÷FAkùFBkÿFClFDlFElFFl FGl FHlFIlFJlFKlFLlFMl&FNl'FOl(FPl,FQl.FRl3FSl5FTl6FUl:FVl;FWl?FXlJFYlKFZlMF[lOF\lRF]lTF^lYF_l[F`l\FalkFblmFcloFdltFelvFflxFglyFhl{Fil…Fjl†Fkl‡Fll‰Fml”Fnl•Fol—Fpl˜FqlœFrlŸFsl°Ftl²Ful´FvlÂFwlÆFxlÍFylÏFzlÐF{lÑF|lÒF}lÔF~lÖG!lÚG"lÜG#làG$lçG%léG&lëG'lìG(lîG)lòG*lôG+mG,mG-m G.mG/mG0mG1mG2mG3m&G4m'G5m(G6lgG7m.G8m/G9m1G:m9G;mm^G?m_G@maGAmeGBmgGCmoGDmpGEm|GFm‚GGm‡GHm‘GIm’GJm”GKm–GLm—GMm˜GNmªGOm¬GPm´GQm·GRm¹GSm½GTm¿GUmÄGVmÈGWmÊGXmÎGYmÏGZmÖG[mÛG\mÝG]mßG^màG_mâG`måGaméGbmïGcmðGdmôGemöGfmüGgnGhnGinGjn"Gkn'Gln2Gmn6Gnn9Gon;GpnnùH?nûH@nýHAoHBoHCo HDo HEo HFoHGoHHoHIoHJo&HKo)HLo*HMo/HNo0HOo3HPo6HQo;HRopUI?p]I@p^IApNIBpdICpeIDplIEpnIFpuIGpvIHp~IIpIJp…IKp†ILp”IMp•INp–IOp—IPp˜IQp›IRp¤ISp«ITp°IUp±IVp´IWp·IXpÊIYpÑIZpÓI[pÔI\pÕI]pÖI^pØI_pÜI`päIapúIbqIcqIdqIeqIfqIgq Ihq IiqIjqIkq Ilq+Imq-Inq/Ioq0Ipq1Iqq8IrqAIsqEItqFIuqGIvqJIwqKIxqPIyqRIzqWI{qZI|q\I}q^I~q`J!qhJ"qyJ#q€J$q…J%q‡J&qŒJ'q’J(qšJ)q›J*q J+q¢J,q¯J-q°J.q²J/q³J0qºJ1q¿J2qÀJ3qÁJ4qÄJ5qËJ6qÌJ7qÓJ8qÖJ9qÙJ:qÚJ;qÜJrJ?rJ@rJAr JBrJCrJDrJErJFrJGr$JHr+JIr/JJr4JKr8JLr9JMrAJNrBJOrCJPrEJQrNJRrOJSrPJTrSJUrUJVrVJWrZJXr\JYr^JZr`J[rcJ\rhJ]rkJ^rnJ_roJ`rqJarwJbrxJcr{Jdr|JerJfr„Jgr‰JhrJirŽJjr“Jkr›Jlr¨Jmr­Jnr®Jor±Jpr´Jqr¾JrrÁJsrÇJtrÉJurÌJvrÕJwrÖJxrØJyrßJzråJ{róJ|rôJ}rúJ~rûK!rþK"sK#sK$sK%sK&s K's K(sK)sK*sK+sK,sK-s"K.s$K/s'K0s(K1s,K2s1K3s2K4s5K5s:K6s;K7s=K8sCK9sMK:sPK;sRKs]K?s^K@s_KAs`KBsfKCsgKDsiKEskKFslKGsnKHsoKIsqKJswKKsyKLs|KMs€KNsKOsƒKPs…KQs†KRsŽKSsKTs“KUs•KVs—KWs˜KXsœKYsžKZsŸK[s K\s¢K]s¥K^s¦K_sªK`s«Kas­KbsµKcs·Kds¹Kes¼Kfs½Kgs¿KhsÅKisÆKjsÉKksËKlsÌKmsÏKnsÒKosÓKpsÖKqsÙKrsÝKssáKtsãKusæKvsçKwséKxsôKysõKzs÷K{sùK|súK}sûK~sýL!sÿL"tL#tL$tL%tL&t L'tL(tL)tL*t$L+t&L,t(L-t)L.t*L/t+L0t,L1t-L2t.L3t/L4t0L5t1L6t9L7t@L8tCL9tDL:tFL;tGLtQL?tRL@tWLAt]LBtbLCtfLDtgLEthLFtkLGtmLHtnLItqLJtrLKt€LLtLMt…LNt†LOt‡LPt‰LQtLRtLSt‘LTt’LUt˜LVt™LWtšLXtœLYtŸLZt L[t¡L\t£L]t¦L^t¨L_t©L`tªLat«Lbt®Lct¯Ldt±Let²LftµLgt¹Lht»Lit¿LjtÈLktÉLltÌLmtÐLntÓLotØLptÚLqtÛLrtÞLstßLttäLutèLvtêLwtëLxtïLytôLztúL{tûL|tüL}tÿL~uM!uM"uM#uM$u M%u!M&u$M'u'M(u)M)u*M*u/M+u6M,u9M-u=M.u>M/u?M0u@M1uCM2uGM3uHM4uNM5uPM6uRM7uWM8u^M9u_M:uaM;uoMuzM?u{M@u|MAu}MBu~MCuMDu…MEuMFu’MGu“MHu•MIu™MJuœMKu¢MLu¤MMu´MNuºMOu¿MPuÀMQuÁMRuÄMSuÆMTuÌMUuÎMVuÏMWu×MXuÜMYußMZuàM[uáM\uäM]uçM^uìM_uîM`uïMauñMbuùMcvMdvMevMfvMgvMhvMiv Mjv MkvMlvMmvMnvMovMpvMqvMrvMsvMtvMuv#Mvv%Mwv&Mxv)Myv-Mzv2M{v3M|v5M}v8M~v9N!v:N"vv N?v¢N@v£NAv¤NBv¥NCv¦NDv§NEv¨NFvªNGv­NHv½NIvÁNJvÅNKvÉNLvËNMvÌNNvÎNOvÔNPvÙNQvàNRvæNSvèNTvìNUvðNVvñNWvöNXvùNYvüNZwN[wN\w N]wN^wN_wN`wNawNbwNcwNdwNew"Nfw(Ngw-Nhw.Niw/Njw4Nkw5Nlw6Nmw9Nnw=Now>NpwBNqwENrwFNswJNtwMNuwNNvwONwwRNxwVNywWNzw\N{w^N|w_N}w`N~wbO!wdO"wgO#wjO$wlO%wpO&wrO'wsO(wtO)wzO*w}O+w€O,w„O-wŒO.wO/w”O0w•O1w–O2wšO3wŸO4w¢O5w§O6wªO7w®O8w¯O9w±O:wµO;w¾OwÑO?wÒO@wÕOAwÙOBwÞOCwßODwàOEwäOFwæOGwêOHwìOIwðOJwñOKwôOLwøOMwûONxOOxOPx OQx ORxOSxOTxOUx!OVx"OWx#OXx-OYx.OZx0O[x5O\x7O]xCO^xDO_xGO`xHOaxLObxNOcxROdx\Oex^Ofx`OgxaOhxcOixdOjxhOkxjOlxnOmxzOnx~OoxŠOpxOqx”Orx˜Osx¡OtxOuxžOvxŸOwx¤Oxx¨Oyx¬Ozx­O{x°O|x±O}x²O~x³P!x»P"x½P#x¿P$xÇP%xÈP&xÉP'xÌP(xÎP)xÒP*xÓP+xÕP,xÖP-xäP.xÛP/xßP0xàP1xáP2xæP3xêP4xòP5xóP6yP7xöP8x÷P9xúP:xûP;xÿPyP?yP@yPAyPByPCy PDy%PEy'PFy)PGy-PHy1PIy4PJy5PKy;PLy=PMy?PNyDPOyEPPyFPQyJPRyKPSyOPTyQPUyTPVyXPWy[PXy\PYygPZyiP[ykP\yrP]yyP^y{P_y|P`y~Pay‹PbyŒPcy‘Pdy“Pey”Pfy•Pgy–Phy˜Piy›PjyœPky¡Ply¨Pmy©Pny«Poy¯Ppy±Pqy´Pry¸Psy»PtyÂPuyÄPvyÇPwyÈPxyÊPyyÏPzyÔP{yÖP|yÚP}yÝP~yÞQ!yàQ"yâQ#yåQ$yêQ%yëQ&yíQ'yñQ(yøQ)yüQ*zQ+zQ,zQ-z Q.z Q/z Q0zQ1zQ2zQ3zQ4z!Q5z'Q6z+Q7z-Q8z/Q9z0Q:z4Q;z5Qz:Q?zDQ@zEQAzGQBzHQCzLQDzUQEzVQFzYQGz\QHz]QIz_QJz`QKzeQLzgQMzjQNzmQOzuQPzxQQz~QRz€QSz‚QTz…QUz†QVzŠQWz‹QXzQYz‘QZz”Q[zžQ\z Q]z£Q^z¬Q_z³Q`zµQaz¹Qbz»Qcz¼QdzÆQezÉQfzÌQgzÎQhzÑQizÛQjzèQkzéQlzëQmzìQnzñQozôQpzûQqzýQrzþQs{Qt{Qu{Qv{#Qw{'Qx{)Qy{*Qz{+Q{{-Q|{.Q}{/Q~{0R!{1R"{4R#{=R${?R%{@R&{AR'{GR({NR){UR*{`R+{dR,{fR-{iR.{jR/{mR0{oR1{rR2{sR3{wR4{„R5{‰R6{ŽR7{R8{‘R9{–R:{›R;{žR<{ R={¥R>{¬R?{¯R@{°RA{²RB{µRC{¶RD{ºRE{»RF{¼RG{½RH{ÂRI{ÅRJ{ÈRK{ÊRL{ÔRM{ÖRN{×RO{ÙRP{ÚRQ{ÛRR{èRS{êRT{òRU{ôRV{õRW{øRX{ùRY{úRZ{üR[{þR\|R]|R^|R_|R`|Ra| Rb| Rc| Rd|Re|Rf|Rg|Rh| Ri|%Rj|&Rk|(Rl|,Rm|1Rn|3Ro|4Rp|6Rq|9Rr|:Rs|FRt|JRu|URv|QRw|RRx|SRy|YRz|ZR{|[R||\R}|]R~|^S!|aS"|cS#|gS$|iS%|mS&|nS'|pS(|rS)|yS*||S+|}S,|†S-|‡S.|S/|”S0|žS1| S2|¦S3|°S4|¶S5|·S6|ºS7|»S8|¼S9|¿S:|ÄS;|ÇS<|ÈS=|ÉS>|ÍS?|ÏS@|ÓSA|ÔSB|ÕSC|×SD|ÙSE|ÚSF|ÝSG|æSH|éSI|ëSJ|õSK}SL}SM}SN} SO}SP}SQ}SR}SS}ST}SU}SV}#SW}&SX}*SY}-SZ}1S[}S^}@S_}AS`}GSa}HSb}MSc}QSd}SSe}WSf}YSg}ZSh}\Si}]Sj}eSk}gSl}jSm}pSn}xSo}zSp}{Sq}Sr}Ss}‚St}ƒSu}…Sv}†Sw}ˆSx}‹Sy}ŒSz}S{}‘S|}–S}}—S~}T!}žT"}¦T#}§T$}ªT%}³T&}¶T'}·T(}¹T)}ÂT*}ÃT+}ÄT,}ÅT-}ÆT.}ÌT/}ÍT0}ÎT1}×T2}ÙT3~T4}âT5}åT6}æT7}êT8}ëT9}íT:}ñT;}õT<}öT=}ùT>}úT?~T@~TA~TB~TC~TD~TE~TF~ TG~'TH~(TI~,TJ~-TK~/TL~3TM~6TN~?TO~DTP~ETQ~GTR~NTS~PTT~RTU~XTV~_TW~aTX~bTY~eTZ~kT[~nT\~oT]~sT^~xT_~~T`~Ta~†Tb~‡Tc~ŠTd~Te~‘Tf~•Tg~˜Th~šTi~Tj~žTkTo?TpCTqDTrGTsOTtRTuSTv[Tw\Tx]TyaTzcT{dT|eT}fT~mU!qU"}U#~U$U%€U&‹U'U(U)U*‘U+–U,—U-œU.¡U/¢U0¦U1ªU2­U3´U4¼U5¿U6ÀU7ÃU8ÈU9ÎU:ÏU;ÛU<ßU=ãU>åU?èU@ìUAîUBïUCòUDúUEýUFþUGÿUH€UI€UJ€ UK€ UL€UM€UN€UO€UP€UQ€UR€US€UT€UU€ UV€$UW€&UX€,UY€.UZ€0U[€4U\€5U]€7U^€9U_€:U`€Ub€@Uc€DUd€`Ue€dUf€fUg€mUh€qUi€uUj€Uk€ˆUl€ŽUm€œUn€žUo€¦Up€§Uq€«Ur€¸Us€¹Ut€ÈUu€ÍUv€ÏUw€ÒUx€ÔUy€ÕUz€×U{€ØU|€àU}€íU~€îV!€ðV"€òV#€óV$€öV%€ùV&€úV'€þV(V) V*V+V,V-V.V/ V0$V1'V2,V30V45V5:V6aV?gV@hVAiVBmVCoVDwVEVFVG„VH…VI†VJ‹VKŽVL–VM˜VN›VOžVP¢VQ®VR²VS´VT»VUËVVÃVWÅVXÊVYÎVZÏV[ÕV\×V]ÛV^ÝV_ÞV`áVaäVbëVcìVdðVeñVfòVgõVhöViøVjùVkýVlÿVm‚Vn‚Vo‚Vp‚Vq‚Vr‚Vs‚Vt‚Vu‚!Vv‚"Vw‚(Vx‚2Vy‚4Vz‚:V{‚CV|‚DV}‚EV~‚FW!‚KW"‚NW#‚OW$‚QW%‚VW&‚\W'‚`W(‚cW)‚gW*‚mW+‚tW,‚{W-‚}W.‚W/‚€W0‚W1‚ƒW2‚„W3‚‡W4‚‰W5‚ŠW6‚ŽW7‚‘W8‚”W9‚–W:‚˜W;‚šW<‚›W=‚ W>‚¡W?‚£W@‚¤WA‚§WB‚¨WC‚©WD‚ªWE‚®WF‚°WG‚²WH‚´WI‚·WJ‚ºWK‚¼WL‚¾WM‚¿WN‚ÆWO‚ÐWP‚ÕWQ‚ÚWR‚àWS‚âWT‚äWU‚èWV‚êWW‚íWX‚ïWY‚öWZ‚÷W[‚ýW\‚þW]ƒW^ƒW_ƒW`ƒWaƒ Wbƒ WcƒTWdƒWeƒWfƒWgƒWhƒ!Wiƒ"Wjƒ,Wkƒ-Wlƒ.Wmƒ0Wnƒ3Woƒ7Wpƒ:WqƒƒSX?ƒèX@ƒêXAƒöXBƒøXCƒùXDƒüXE„XF„XG„ XH„XI„XJ„XK„XLƒ­XM„/XN„9XO„EXP„GXQ„HXR„JXS„MXT„OXU„QXV„RXW„VXX„XXY„YXZ„ZX[„\X\„`X]„dX^„eX_„gX`„jXa„pXb„sXc„tXd„vXe„xXf„|Xg„}Xh„Xi„…Xj„’Xk„“Xl„•Xm„žXn„¦Xo„¨Xp„©Xq„ªXr„¯Xs„±Xt„´Xu„ºXv„½Xw„¾Xx„ÀXy„ÂXz„ÇX{„ÈX|„ÌX}„ÏX~„ÓY!„ÜY"„çY#„êY$„ïY%„ðY&„ñY'„òY(„÷Y)…2Y*„úY+„ûY,„ýY-…Y.…Y/…Y0… Y1…Y2…Y3…Y4…Y5…"Y6…#Y7…$Y8…%Y9…'Y:…*Y;…+Y<…/Y=…3Y>…4Y?…6Y@…?YA…FYB…OYC…PYD…QYE…RYF…SYG…VYH…YYI…\YJ…]YK…^YL…_YM…`YN…aYO…bYP…dYQ…kYR…oYS…yYT…zYU…{YV…}YW…YX…YY……YZ…†Y[…‰Y\…‹Y]…ŒY^…Y_…“Y`…˜Ya…Yb…ŸYc… Yd…¢Ye…¥Yf…§Yg…´Yh…¶Yi…·Yj…¸Yk…¼Yl…½Ym…¾Yn…¿Yo…ÂYp…ÇYq…ÊYr…ËYs…ÎYt…­Yu…ØYv…ÚYw…ßYx…àYy…æYz…èY{…íY|…óY}…öY~…üZ!…ÿZ"†Z#†Z$†Z%† Z&†Z'†Z(†Z)†Z*†Z+†Z,†Z-†Z.†!Z/†'Z0†)Z1†6Z2†8Z3†:Z4††YZ?†]Z@†`ZA†aZB†bZC†cZD†dZE†iZF†lZG†oZH†uZI†vZJ†wZK†zZL†ZM†‘ZN†–ZO†˜ZP†šZQ†œZR†¡ZS†¦ZT†§ZU†¨ZV†­ZW†±ZX†³ZY†´ZZ†µZ[†·Z\†¸Z]†¹Z^†¿Z_†ÀZ`†ÁZa†ÃZb†ÅZc†ÑZd†ÒZe†ÕZf†×Zg†ÚZh†ÜZi†àZj†ãZk†åZl†çZm†ˆZn†úZo†üZp†ýZq‡Zr‡Zs‡Zt‡ Zu‡Zv‡Zw‡Zx‡Zy‡Zz‡Z{‡Z|‡Z}‡!Z~‡#[!‡(["‡.[#‡/[$‡1[%‡2[&‡9['‡:[(‡<[)‡=[*‡>[+‡@[,‡C[-‡E[.‡M[/‡X[0‡][1‡a[2‡d[3‡e[4‡o[5‡q[6‡r[7‡{[8‡ƒ[9‡„[:‡…[;‡†[<‡‡[=‡ˆ[>‡‰[?‡‹[@‡Œ[A‡[B‡“[C‡•[D‡—[E‡˜[F‡™[G‡ž[H‡ [I‡£[J‡§[K‡¬[L‡­[M‡®[N‡±[O‡µ[P‡¾[Q‡¿[R‡Á[S‡È[T‡É[U‡Ê[V‡Î[W‡Õ[X‡Ö[Y‡Ù[Z‡Ú[[‡Ü[\‡ß[]‡â[^‡ã[_‡ä[`‡ê[a‡ë[b‡í[c‡ñ[d‡ó[e‡ø[f‡ú[g‡ÿ[hˆ[iˆ[jˆ[kˆ [lˆ [mˆ [nˆ[oˆ[pˆ[qˆ[rˆ[sˆ[tˆ[uˆˆ[wˆ[xˆ[yˆ([zˆ-[{ˆ.[|ˆ0[}ˆ2[~ˆ5\!ˆ:\"ˆ<\#ˆA\$ˆC\%ˆE\&ˆH\'ˆI\(ˆJ\)ˆK\*ˆN\+ˆQ\,ˆU\-ˆV\.ˆX\/ˆZ\0ˆ\\1ˆ_\2ˆ`\3ˆd\4ˆi\5ˆq\6ˆy\7ˆ{\8ˆ€\9ˆ˜\:ˆš\;ˆ›\<ˆœ\=ˆŸ\>ˆ \?ˆ¨\@ˆª\Aˆº\Bˆ½\Cˆ¾\DˆÀ\EˆÊ\FˆË\GˆÌ\HˆÍ\IˆÎ\JˆÑ\KˆÒ\LˆÓ\MˆÛ\NˆÞ\Oˆç\Pˆï\Qˆð\Rˆñ\Sˆõ\Tˆ÷\U‰\V‰\W‰ \X‰\Y‰\Z‰\[‰\\‰\]‰\^‰\_‰\`‰ \a‰&\b‰'\c‰(\d‰0\e‰1\f‰2\g‰5\h‰9\i‰:\j‰>\k‰@\l‰B\m‰E\n‰F\o‰I\p‰O\q‰R\r‰W\s‰Z\t‰[\u‰\\v‰a\w‰b\x‰c\y‰k\z‰n\{‰p\|‰s\}‰u\~‰z]!‰{]"‰|]#‰}]$‰‰]%‰]&‰]'‰”](‰•])‰›]*‰œ]+‰Ÿ],‰ ]-‰¥].‰°]/‰´]0‰µ]1‰¶]2‰·]3‰¼]4‰Ô]5‰Õ]6‰Ö]7‰×]8‰Ø]9‰å]:‰é];‰ë]<‰í]=‰ñ]>‰ó]?‰ö]@‰ù]A‰ý]B‰ÿ]CŠ]DŠ]EŠ]FŠ]GŠ]HŠ]IŠ]JŠ]KŠ]LŠ ]MŠ"]NŠ$]OŠ&]PŠ+]QŠ,]RŠ/]SŠ5]TŠ7]UŠ=]VŠ>]WŠ@]XŠC]YŠE]ZŠG][ŠI]\ŠM]]ŠN]^ŠS]_ŠV]`ŠW]aŠX]bŠ\]cŠ]]dŠa]eŠe]fŠg]gŠu]hŠv]iŠw]jŠy]kŠz]lŠ{]mŠ~]nŠ]oŠ€]pŠƒ]qІ]rŠ‹]sŠ]tŠ]uŠ’]vŠ–]wŠ—]xŠ™]yŠŸ]zЧ]{Š©]|Š®]}Н]~г^!ж^"Š·^#Š»^$о^%ŠÃ^&ŠÆ^'ŠÈ^(ŠÉ^)ŠÊ^*ŠÑ^+ŠÓ^,ŠÔ^-ŠÕ^.Š×^/ŠÝ^0Šß^1Šì^2Šð^3Šô^4Šõ^5Šö^6Šü^7Šÿ^8‹^9‹^:‹ ^;‹^<‹^=‹^>‹^?‹ ^@‹-^A‹0^B‹7^C‹<^D‹B^E‹C^F‹D^G‹E^H‹F^I‹H^J‹R^K‹S^L‹T^M‹Y^N‹M^O‹^^P‹c^Q‹m^R‹v^S‹x^T‹y^U‹|^V‹~^W‹^X‹„^Y‹…^Z‹‹^[‹^\‹^]‹”^^‹•^_‹œ^`‹ž^a‹Ÿ^bŒ8^cŒ9^dŒ=^eŒ>^fŒE^gŒG^hŒI^iŒK^jŒO^kŒQ^lŒS^mŒT^nŒW^oŒX^pŒ[^qŒ]^rŒY^sŒc^tŒd^uŒf^vŒh^wŒi^xŒm^yŒs^zŒu^{Œv^|Œ{^}Œ~^~Œ†_!Œ‡_"Œ‹_#Œ_$Œ’_%Œ“_&Œ™_'Œ›_(Œœ_)Œ¤_*Œ¹_+Œº_,ŒÅ_-ŒÆ_.ŒÉ_/ŒË_0ŒÏ_1ŒÖ_2ŒÕ_3ŒÙ_4ŒÝ_5Œá_6Œè_7Œì_8Œï_9Œð_:Œò_;Œõ_<Œ÷_=Œø_>Œþ_?Œÿ_@_A_B _C_D_E_Fe_Gi_Hl_In_J_K‚_L„_Mˆ_N_O_P‘_Q•_Rž_SŸ_T _U¦_V«_W¬_X¯_Y²_Zµ_[·_\¹_]»_^À__Å_`Æ_aÇ_bÈ_cÊ_dÎ_eÑ_fÔ_gÕ_h×_iÙ_jä_kå_lç_mì_nð_o¼_pñ_qò_rô_sý_tŽ_uŽ_vŽ_wŽ_xŽ _yŽ_zŽ_{Ž_|Ž _}Ž!_~Ž"`!Ž#`"Ž&`#Ž'`$Ž1`%Ž3`&Ž6`'Ž7`(Ž8`)Ž9`*Ž=`+Ž@`,ŽA`-ŽK`.ŽM`/ŽN`0ŽO`1ŽT`2Ž[`3Ž\`4Ž]`5Ž^`6Ža`7Žb`8Ži`9Žl`:Žm`;Žo`<Žp`=Žq`>Žy`?Žz`@Ž{`AŽ‚`BŽƒ`Cމ`DŽ`EŽ’`FŽ•`GŽš`HŽ›`IŽ`JŽž`KŽ¢`Lާ`MŽ©`NŽ­`OŽ®`P޳`Q޵`RŽº`SŽ»`TŽÀ`UŽÁ`VŽÃ`WŽÄ`XŽÇ`YŽÏ`ZŽÑ`[ŽÔ`\ŽÜ`]Žè`^Žî`_Žð``Žñ`aŽ÷`bŽù`cŽú`dŽí`e`f`g`h`i`j`k`l`m`n`o `p!`q#`r%`s'`t(`u,`v-`w.`x4`y5`z6`{7`|:`}@`~Aa!Ca"Ga#Oa$Qa%Ra&Sa'Ta(Ua)Xa*]a+^a,ea-a. a/¡a0¤a1¥a2¦a3µa4¶a5¸a6¾a7Àa8Áa9Æa:Êa;Ëa<Ía=Ða>Òa?Óa@ÕaAàaBãaCäaDèaEîaFñaGõaHöaIûaJþaKaLaMaN aOaPaQ(aR)aS/aT*aU,aV-aW3aX4aY7aZ?a[Ca\Da]La^[a_]a`baafabgacladpaetafyag…ahˆai‹ajŒakŽalam•an—ao˜ap™aq›ar as¡at¢au¥av°aw²ax³ay´az¶a{½a|Ìa}¾a~Ãb!Äb"Åb#Çb$Èb%Õb&×b'Øb(Ùb)Üb*Ýb+ßb,åb-Òb.öb/ëb0ïb1ðb2ôb3þb4ÿb5‘b6‘b7‘b8‘b9‘b:‘ b;‘b<‘b=‘b>‘b?‘b@‘bA‘bB‘bC‘ bD‘%bE‘"bF‘#bG‘'bH‘)bI‘.bJ‘/bK‘1bL‘4bM‘6bN‘7bO‘9bP‘:bQ‘’ c?’ c@’ cA’cB’cC’cD’cE’cF’cG’cH’#cI’$cJ’%cK’&cL’(cM’.cN’/cO’0cP’3cQ’5cR’6cS’8cT’9cU’:cV’cX’@cY’BcZ’Cc[’Fc\’Gc]’Jc^’Mc_’Nc`’Oca’Qcb’Xcc’Ycd’\ce’]cf’`cg’ach’eci’gcj’hck’icl’ncm’ocn’pco’ucp’vcq’wcr’xcs’yct’{cu’|cv’}cw’cx’ˆcy’‰cz’Šc{’c|’Žc}’’c~’—d!’™d"’Ÿd#’ d$’¤d%’¥d&’§d'’¨d(’«d)’¯d*’²d+’¶d,’¸d-’ºd.’»d/’¼d0’½d1’¿d2’Àd3’Ád4’Âd5’Ãd6’Åd7’Æd8’Çd9’Èd:’Ëd;’Ìd<’Íd=’Îd>’Ðd?’Ód@’ÕdA’×dB’ØdC’ÙdD’ÜdE’ÝdF’ßdG’àdH’ádI’ãdJ’ådK’çdL’èdM’ìdN’îdO’ðdP’ùdQ’ûdR’ÿdS“dT“dU“dV“ dW“dX“dY“dZ“d[“d\“d]“d^“!d_“$d`“%da“'db“)dc“*dd“3de“4df“6dg“7dh“Gdi“Hdj“Idk“Pdl“Qdm“Rdn“Udo“Wdp“Xdq“Zdr“^ds“ddt“edu“gdv“idw“jdx“mdy“odz“pd{“qd|“sd}“td~“ve!“ze"“}e#“e$“€e%“e&“‚e'“ˆe(“Še)“‹e*“e+“e,“’e-“•e.“˜e/“›e0“že1“¡e2“£e3“¤e4“¦e5“¨e6“«e7“´e8“µe9“¶e:“ºe;“©e<“Áe=“Äe>“Åe?“Æe@“ÇeA“ÉeB“ÊeC“ËeD“ÌeE“ÍeF“ÓeG“ÙeH“ÜeI“ÞeJ“ßeK“âeL“æeM“çeN“ùeO“÷eP“øeQ“úeR“ûeS“ýeT”eU”eV”eW”eX” eY” eZ”e[”e\”e]”e^”e_”e`”.ea”/eb”1ec”2ed”3ee”4ef”;eg”?eh”=ei”Cej”Eek”Hel”Jem”Len”Ueo”Yep”\eq”_er”aes”cet”heu”kev”mew”nex”oey”qez”re{”„e|”ƒe}•xe~•yf!•~f"•„f#•ˆf$•Œf%•f&•Žf'•f(•žf)•Ÿf*•¡f+•¦f,•©f-•«f.•¬f/•´f0•¶f1•ºf2•½f3•¿f4•Æf5•Èf6•Éf7•Ëf8•Ðf9•Ñf:•Òf;•Óf<•Ùf=•Úf>•Ýf?•Þf@•ßfA•àfB•äfC•æfD–fE–fF–"fG–$fH–%fI–&fJ–,fK–1fL–3fM–7fN–8fO–9fP–:fQ–—xg?—{g@—}gA—gB—€gC—‰gD—•gE—–gF——gG—™gH—šgI—žgJ—ŸgK—¢gL—¬gM—®gN—±gO—²gP—µgQ—¶gR—¸gS—¹gT—ºgU—¼gV—¾gW—¿gX—ÁgY—ÄgZ—Åg[—Çg\—Ég]—Êg^—Ìg_—Íg`—Îga—Ðgb—Ñgc—Ôgd—×ge—Øgf—Ùgg—Ýgh—Þgi—àgj—Ûgk—ágl—ägm—ïgn—ñgo—ôgp—÷gq—øgr—úgs˜gt˜ gu˜gv˜ gw˜gx˜gy˜gz˜g{˜g|˜ g}˜#g~˜&h!˜+h"˜.h#˜/h$˜0h%˜2h&˜3h'˜5h(˜%h)˜>h*˜Dh+˜Gh,˜Jh-˜Qh.˜Rh/˜Sh0˜Vh1˜Wh2˜Yh3˜Zh4˜bh5˜ch6˜eh7˜fh8˜jh9˜lh:˜«h;˜­h<˜®h=˜°h>˜´h?˜·h@˜¸hA˜ºhB˜»hC˜¿hD˜ÂhE˜ÅhF˜ÈhG˜ÌhH˜áhI˜ãhJ˜åhK˜æhL˜çhM˜êhN˜óhO˜öhP™hQ™hR™hS™hT™hU™hV™hW™hX™hY™hZ™h[™"h\™&h]™'h^™+h_™1h`™2ha™3hb™4hc™5hd™9he™:hf™;hg™ši?ši@š iAš"iBš#iCš$iDš'iEš-iFš.iGš3iHš5iIš6iJš8iKšGiLšAiMšDiNšJiOšKiPšLiQšNiRšQiSšTiTšViUš]iVšªiWš¬iXš®iYš¯iZš²i[š´i\šµi]š¶i^š¹i_š»i`š¾iaš¿ibšÁicšÃidšÆiešÈifšÎigšÐihšÒiišÕijšÖikš×ilšÛimšÜinšàiošäipšåiqšçiršéisšìitšòiušóivšõiwšùixšúiyšýizšÿi{›i|›i}›i~›j!›j"›j#›j$› j%› j&› j'› j(›j)›j*›j+›j,›j-›j.›j/› j0›&j1›+j2›-j3›3j4›4j5›5j6›7j7›9j8›:j9›=j:›Hj;›Kj<›Lj=›Uj>›Vj?›Wj@›[jA›^jB›ajC›cjD›ejE›fjF›hjG›jjH›kjI›ljJ›mjK›njL›sjM›ujN›wjO›xjP›yjQ›jR›€jS›„jT›…jU›†jV›‡jW›‰jX›ŠjY›‹jZ›j[›j\›j]›”j^›šj_›j`›žja›¦jb›§jc›©jd›¬je›°jf›±jg›²jh›·ji›¸jj›»jk›¼jl›¾jm›¿jn›Ájo›Çjp›Èjq›Îjr›Ðjs›×jt›Øju›Ýjv›ßjw›åjx›çjy›êjz›ëj{›ïj|›ój}›÷j~›øk!›ùk"›úk#›ýk$›ÿk%œk&œk'œ k(œk)œk*œk+œk,œk-œk.œk/œk0œ"k1œ#k2œ&k3œ'k4œ(k5œ)k6œ*k7œ1k8œ5k9œ6k:œ7k;œ=k<œAk=œCk>œDk?œEk@œIkAœJkBœNkCœOkDœPkEœSkFœTkGœVkHœXkIœ[kJœ]kKœ^kLœ_kMœckNœikOœjkPœ\kQœkkRœhkSœnkTœpkUœrkVœukWœwkXœ{kYœækZœòk[œ÷k\œùk] k^k_k`kakbkckdke/kf0kg2kh3ki4kj:kkÖl?×l@ÚlAÞlBßlCàlDålEçlFélGëlHîlIðlJólKôlLþlMž lNžlOžlPžlQžlRžlSžlTžlUžlVžlWžlXžlYžzlZž{l[ž|l\ž€l]ž‚l^žƒl_ž„l`ž…laž‡lbžŽlcžldž–lež˜lfž›lgžžlhž¤liž¨ljž¬lkž®llž¯lmž°lnž³lož´lpžµlqžÆlržÈlsžËltžÕlužßlvžälwžçlxžìlyžílzžîl{žðl|žñl}žòl~žõm!žøm"žÿm#Ÿm$Ÿm%Ÿ m&Ÿm'Ÿm(Ÿm)Ÿm*Ÿm+Ÿm,Ÿm-Ÿm.Ÿm/Ÿm0Ÿm1Ÿ"m2Ÿ&m3Ÿ*m4Ÿ+m5Ÿ/m6Ÿ1m7Ÿ2m8Ÿ4m9Ÿ7m:Ÿ9m;Ÿ:m<ŸŸ?m?ŸAm@ŸCmAŸDmBŸEmCŸFmDŸGmEŸSmFŸUmGŸVmHŸWmIŸXmJŸZmKŸ]mLŸ^mMŸhmNŸimOŸmmPŸnmQŸomRŸpmSŸqmTŸsmUŸumVŸzmWŸ}mXŸmYŸmZŸ‘m[Ÿ’m\Ÿ”m]Ÿ–m^Ÿ—m_Ÿžm`Ÿ¡maŸ¢mbŸ£mcŸ¥screen-4.1.0/utf8encodings/bf0000644000175000017500000000035011642704565014135 0ustar abeabeScreenI2UTF8¿4CP-1251€‚ ƒS„ … &† ‡ !ˆ ¬‰ 0Š ‹ 9Œ  Ž R‘ ’ “ ” • "– — ˜ ™!"šY› :œZ\ž[Ÿ_¡¢^£¥¨©©ª¯²³V´‘¸Q¹!ºT¼X½¾U¿WÀ€ÿOscreen-4.1.0/utf8encodings/d60000644000175000017500000000032411642704565014060 0ustar abeabeScreenI2UTF8Ö.ISO-8859-10¡¢£"¤*¥(¦6¨;©ª`«f¬}®j¯J±²³#´+µ)¶7¸<¹ºa»g¼~½ ¾k¿KÀÇ.È ÊÌÑEÒL×hÙràç/è êìñFòM÷iùsÿ8screen-4.1.0/utf8encodings/190000644000175000017500000027304011642704565014007 0ustar abeabeScreenI2UTF8]ƒGBK@NANBNCNDNENFNGNHN IN!JN#KN&LN)MN.NN/ON1PN3QN5RN7SN<TN@UNAVNBWNDXNFYNJZNQ[NU\NW]NZ^N[_Nb`NcaNdbNecNgdNheNjfNkgNlhNmiNnjNokNrlNtmNunNvoNwpNxqNyrNzsN{tN|uN}vNwN€xNyN‚zNƒ{N„|N…}N‡~NŠ€NN–‚N—ƒN™„Nœ…N†Nž‡N£ˆNª‰N¯ŠN°‹N±ŒN´N¶ŽN·N¸N¹‘N¼’N½“N¾”NÈ•NÌ–NÏ—NИNÒ™NÚšNÛ›NÜœNàNâžNæŸNç Né¡Ní¢Nî£Nï¤Nñ¥Nô¦Nø§Nù¨Nú©NüªNþ«O¬O­O®O¯O°O±O²O³O ´O µO¶O·O¸O¹OºO»O¼O!½O#¾O(¿O)ÀO,ÁO-ÂO.ÃO1ÄO3ÅO5ÆO7ÇO9ÈO;ÉO>ÊO?ËO@ÌOAÍOBÎODÏOEÐOGÑOHÒOIÓOJÔOKÕOLÖOR×OTØOVÙOaÚObÛOfÜOhÝOjÞOkßOmàOnáOqâOrãOuäOwåOxæOyçOzèO}éO€êOëO‚ìO…íO†îO‡ïOŠðOŒñOŽòOóO’ôO“õO•öO–÷O˜øO™ùOšúOœûOžüOŸýO¡þO¢@O¤AO«BO­CO°DO±EO²FO³GO´HO¶IO·JO¸KO¹LOºMO»NO¼OO½PO¾QOÀROÁSOÂTOÆUOÇVOÈWOÉXOËYOÌZOÍ[OÒ\OÓ]OÔ^OÕ_OÖ`OÙaOÛbOàcOâdOäeOåfOçgOëhOìiOðjOòkOôlOõmOönO÷oOùpOûqOürOýsOÿtPuPvPwPxPyPzP{P|P}P ~P €P P‚PƒP„P…P†P‡PˆP‰PŠP‹P ŒP"P#ŽP$P'P+‘P/’P0“P1”P2•P3–P4—P5˜P6™P7šP8›P9œP;P=žP?ŸP@ PA¡PB¢PD£PE¤PF¥PI¦PJ§PK¨PM©PPªPQ«PR¬PS­PT®PV¯PW°PX±PY²P[³P]´P^µP_¶P`·Pa¸Pb¹PcºPd»Pf¼Pg½Ph¾Pi¿PjÀPkÁPmÂPnÃPoÄPpÅPqÆPrÇPsÈPtÉPuÊPxËPyÌPzÍP|ÎP}ÏPÐP‚ÑPƒÒP„ÓP†ÔP‡ÕP‰ÖPŠ×P‹ØPŒÙPŽÚPÛPÜP‘ÝP’ÞP“ßP”àP•áP–âP—ãP˜äP™åPšæP›çPœèPéPžêPŸëP ìP¡íP¢îP¤ïP¦ðPªñP«òP­óP®ôP¯õP°öP±÷P³øP´ùPµúP¶ûP·üP¸ýP¹þP¼@P½AP¾BP¿CPÀDPÁEPÂFPÃGPÄHPÅIPÆJPÇKPÈLPÉMPÊNPËOPÌPPÍQPÎRPÐSPÑTPÒUPÓVPÔWPÕXP×YPØZPÙ[PÛ\PÜ]PÝ^PÞ_Pß`PàaPábPâcPãdPäePåfPègPéhPêiPëjPïkPðlPñmPònPôoPöpP÷qPørPùsPútPüuPývPþwPÿxQyQzQ{Q|Q}Q~Q€Q Q ‚Q ƒQ „Q…Q†Q‡QˆQ‰QŠQ‹QŒQQŽQQQ‘Q’Q“Q”Q•Q –Q"—Q#˜Q$™Q%šQ&›Q'œQ(Q)žQ*ŸQ+ Q,¡Q-¢Q.£Q/¤Q0¥Q1¦Q2§Q3¨Q4©Q5ªQ6«Q7¬Q8­Q9®Q:¯Q;°Q<±Q=²Q>³QB´QGµQJ¶QL·QN¸QO¹QPºQR»QS¼QW½QX¾QY¿Q[ÀQ]ÁQ^ÂQ_ÃQ`ÄQaÅQcÆQdÇQfÈQgÉQiÊQjËQoÌQrÍQzÎQ~ÏQÐQƒÑQ„ÒQ†ÓQ‡ÔQŠÕQ‹ÖQŽ×QØQÙQ‘ÚQ“ÛQ”ÜQ˜ÝQšÞQßQžàQŸáQ¡âQ£ãQ¦äQ§åQ¨æQ©çQªèQ­éQ®êQ´ëQ¸ìQ¹íQºîQ¾ïQ¿ðQÁñQÂòQÃóQÅôQÈõQÊöQÍ÷QÎøQÐùQÒúQÓûQÔüQÕýQÖþQ×@QØAQÙBQÚCQÜDQÞEQßFQâGQãHQåIQæJQçKQèLQéMQêNQìOQîPQñQQòRQôSQ÷TQþURVRWR XR YR ZR[R\R]R^R_R`RaRbR!cR"dR#eR%fR&gR'hR*iR,jR/kR1lR2mR4nR5oR<pR>qRDrREsRFtRGuRHvRIwRKxRNyROzRR{RS|RU}RW~RX€RYRZ‚R[ƒR]„R_…R`†Rb‡RcˆRd‰RfŠRh‹RkŒRlRmŽRnRpRq‘Rs’Rt“Ru”Rv•Rw–Rx—Ry˜Rz™R{šR|›R~œR€RƒžR„ŸR… R†¡R‡¢R‰£RФR‹¥RŒ¦R§RލR©R‘ªR’«R”¬R•­R–®R—¯R˜°R™±Rš²Rœ³R¤´R¥µR¦¶R§·R®¸R¯¹R°ºR´»Rµ¼R¶½R·¾R¸¿R¹ÀRºÁR»ÂR¼ÃR½ÄRÀÅRÁÆRÂÇRÄÈRÅÉRÆÊRÈËRÊÌRÌÍRÍÎRÎÏRÏÐRÑÑRÓÒRÔÓRÕÔR×ÕRÙÖRÚ×RÛØRÜÙRÝÚRÞÛRàÜRáÝRâÞRãßRåàRæáRçâRèãRéäRêåRëæRìçRíèRîéRïêRñëRòìRóíRôîRõïRöðR÷ñRøòRûóRüôRýõSöS÷SøSùSúS ûS üS ýS þS@SASBSCSDSESFSGSHSIS"JS$KS%LS'MS(NS)OS+PS,QS-RS/SS0TS1US2VS3WS4XS5YS6ZS7[S8\S<]S=^S@_SB`SDaSFbSKcSLdSMeSPfSTgSXhSYiS[jS]kSelShmSjnSloSmpSrqSvrSysS{tS|uS}vS~wS€xSySƒzS‡{Sˆ|SŠ}SŽ~S€SS‘‚S’ƒS“„S”…S–†S—‡S™ˆS›‰SœŠSž‹S ŒS¡S¤ŽS§SªS«‘S¬’S­“S¯”S°•S±–S²—S³˜S´™SµšS·›S¸œS¹SºžS¼ŸS½ S¾¡SÀ¢SãSĤSÅ¥SƦSǧSΨSÏ©SЪSÒ«SÓ¬SÕ­SÚ®SܯSݰSÞ±Sá²Sâ³Sç´SôµSú¶Sþ·Sÿ¸T¹TºT»T¼T ½T¾T¿TÀTÁTÂT"ÃT$ÄT%ÅT*ÆT0ÇT3ÈT6ÉT7ÊT:ËT=ÌT?ÍTAÎTBÏTDÐTEÑTGÒTIÓTLÔTMÕTNÖTO×TQØTZÙT]ÚT^ÛT_ÜT`ÝTaÞTcßTeàTgáTiâTjãTkäTlåTmæTnçToèTpéTtêTyëTzìT~íTîTïTƒðT…ñT‡òTˆóT‰ôTŠõTöT‘÷T“øT—ùT˜úTœûTžüTŸýT þT¡@T¢AT¥BT®CT°DT²ETµFT¶GT·HT¹ITºJT¼KT¾LTÃMTÅNTÊOTËPTÖQTØRTÛSTàTTáUTâVTãWTäXTëYTìZTï[Tð\Tñ]Tô^Tõ_Tö`T÷aTøbTùcTûdTþeUfUgUhUiUjUkU lU mU nU oUpUqUrUsUtUuUvUwUxUyUzU{U|U!}U%~U&€U(U)‚U+ƒU-„U2…U4†U5‡U6ˆU8‰U9ŠU:‹U;ŒU=U@ŽUBUEUG‘UH’UK“UL”UM•UN–UO—UQ˜UR™USšUT›UWœUXUYžUZŸU[ U]¡U^¢U_£U`¤Ub¥Uc¦Uh§Ui¨Uk©UoªUp«Uq¬Ur­Us®Ut¯Uy°Uz±U}²U³U…´U†µUŒ¶U·UޏU¹U’ºU“»U•¼U–½U—¾Uš¿U›ÀUžÁU ÂU¡ÃU¢ÄU£ÅU¤ÆU¥ÇU¦ÈU¨ÉU©ÊUªËU«ÌU¬ÍU­ÎU®ÏU¯ÐU°ÑU²ÒU´ÓU¶ÔU¸ÕUºÖU¼×U¿ØUÀÙUÁÚUÂÛUÃÜUÆÝUÇÞUÈßUÊàUËáUÎâUÏãUÐäUÕåU׿UØçUÙèUÚéUÛêUÞëUàìUâíUçîUéïUíðUîñUðòUñóUôôUöõUøöUù÷UúøUûùUüúUÿûVüVýVþV@VAVBV CV DV EVFVGVHVIVJVKVLVMVNVOVPVQV RV!SV"TV%UV&VV(WV)XV*YV+ZV.[V/\V0]V3^V5_V7`V8aV:bV<cV=dV>eV@fVAgVBhVCiVDjVEkVFlVGmVHnVIoVJpVKqVOrVPsVQtVRuVSvVUwVVxVZyV[zV]{V^|V_}V`~Va€VcVe‚VfƒVg„Vm…Vn†Vo‡VpˆVr‰VsŠVt‹VuŒVwVxŽVyVzV}‘V~’V“V€”V•V‚–Vƒ—V„˜V‡™VˆšV‰›VŠœV‹VŒžVŸV V‘¡V’¢V”£V•¤V–¥V—¦V˜§V™¨Vš©V›ªVœ«V¬Vž­VŸ®V ¯V¡°V¢±V¤²V¥³V¦´V§µV¨¶V©·Vª¸V«¹V¬ºV­»V®¼V°½V±¾V²¿V³ÀV´ÁVµÂV¶ÃV¸ÄV¹ÅVºÆV»ÇV½ÈV¾ÉV¿ÊVÀËVÁÌVÂÍVÃÎVÄÏVÅÐVÆÑVÇÒVÈÓVÉÔVËÕVÌÖVÍ×VÎØVÏÙVÐÚVÑÛVÒÜVÓÝVÕÞVÖßVØàVÙáVÜâVããVåäVæåVçæVèçVéèVêéVìêVîëVïìVòíVóîVöïV÷ðVøñVûòVüóWôWõWöW÷WøW ùW úW ûWüWýWþW@WAWBWCWDWEWFWGWHWIWJWKWLW MW!NW"OW$PW%QW&RW'SW+TW1UW2VW4WW5XW6YW7ZW8[W<\W=]W?^WA_WC`WDaWEbWFcWHdWIeWKfWRgWShWTiWUjWVkWXlWYmWbnWcoWepWgqWlrWnsWptWquWrvWtwWuxWxyWyzWz{W}|W~}W~W€€WW‡‚WˆƒW‰„WŠ…W†WއWˆW‰W‘ŠW”‹W•ŒW–W—ŽW˜W™Wš‘Wœ’W“Wž”WŸ•W¥–W¨—Wª˜W¬™W¯šW°›W±œW³WµžW¶ŸW· W¹¡Wº¢W»£W¼¤W½¥W¾¦W¿§WÀ¨WÁ©WĪWÅ«WƬWÇ­WÈ®WɯWʰW̱WͲWгWÑ´WÓµWÖ¶W×·WÛ¸WܹWÞºWá»Wâ¼Wã½Wå¾Wæ¿WçÀWèÁWéÂWêÃWëÄWìÅWîÆWðÇWñÈWòÉWóÊWõËWöÌW÷ÍWûÎWüÏWþÐWÿÑXÒXÓXÔXÕXÖX ×X ØX ÙXÚXÛXÜXÝXÞXßXàXáXâXãXäXåXæXçX"èX#éX%êX&ëX'ìX(íX)îX+ïX,ðX-ñX.òX/óX1ôX2õX3öX4÷X6øX7ùX8úX9ûX:üX;ýX<þX= @X> AX? BX@ CXA DXB EXC FXE GXF HXG IXH JXI KXJ LXK MXN NXO OXP PXR QXS RXU SXV TXW UXY VXZ WX[ XX\ YX] ZX_ [X` \Xa ]Xb ^Xc _Xd `Xf aXg bXh cXi dXj eXm fXn gXo hXp iXq jXr kXs lXt mXu nXv oXw pXx qXy rXz sX{ tX| uX} vX wX‚ xX„ yX† zX‡ {Xˆ |XŠ }X‹ ~XŒ €X XŽ ‚X ƒX „X‘ …X” †X• ‡X– ˆX— ‰X˜ ŠX› ‹Xœ ŒX X  ŽX¡ X¢ X£ ‘X¤ ’X¥ “X¦ ”X§ •Xª –X« —X¬ ˜X­ ™X® šX¯ ›X° œX± X² žX³ ŸX´  Xµ ¡X¶ ¢X· £X¸ ¤X¹ ¥Xº ¦X» §X½ ¨X¾ ©X¿ ªXÀ «X ¬Xà ­XÄ ®XÆ ¯XÇ °XÈ ±XÉ ²XÊ ³XË ´XÌ µXÍ ¶XÎ ·XÏ ¸XÐ ¹XÒ ºXÓ »XÔ ¼XÖ ½X× ¾XØ ¿XÙ ÀXÚ ÁXÛ ÂXÜ ÃXÝ ÄXÞ ÅXß ÆXà ÇXá ÈXâ ÉXã ÊXå ËXæ ÌXç ÍXè ÎXé ÏXê ÐXí ÑXï ÒXñ ÓXò ÔXô ÕXõ ÖX÷ ×Xø ØXú ÙXû ÚXü ÛXý ÜXþ ÝXÿ ÞY ßY àY áY âY ãY äY åY æY çY èY éY êY ëY ìY íY îY ïY ðY ñY òY óY! ôY" õY# öY& ÷Y( øY, ùY0 úY2 ûY3 üY5 ýY6 þY; @Y= AY> BY? CY@ DYC EYE FYF GYJ HYL IYM JYP KYR LYS MYY NY[ OY\ PY] QY^ RY_ SYa TYc UYd VYf WYg XYh YYi ZYj [Yk \Yl ]Ym ^Yn _Yo `Yp aYq bYr cYu dYw eYz fY{ gY| hY~ iY jY€ kY… lY‰ mY‹ nYŒ oYŽ pY qY rY‘ sY” tY• uY˜ vYš wY› xYœ yY zYŸ {Y  |Y¡ }Y¢ ~Y¦ €Y§ Y¬ ‚Y­ ƒY° „Y± …Y³ †Y´ ‡Yµ ˆY¶ ‰Y· ŠY¸ ‹Yº ŒY¼ Y½ ŽY¿ YÀ YÁ ‘Y ’Yà “YÄ ”YÅ •YÇ –YÈ —YÉ ˜YÌ ™YÍ šYÎ ›YÏ œYÕ YÖ žYÙ ŸYÛ  YÞ ¡Yß ¢Yà £Yá ¤Yâ ¥Yä ¦Yæ §Yç ¨Yé ©Yê ªYë «Yí ¬Yî ­Yï ®Yð ¯Yñ °Yò ±Yó ²Yô ³Yõ ´Yö µY÷ ¶Yø ·Yú ¸Yü ¹Yý ºYþ »Z ¼Z ½Z ¾Z ¿Z ÀZ ÁZ ÂZ ÃZ ÄZ ÅZ ÆZ ÇZ ÈZ ÉZ ÊZ ËZ ÌZ ÍZ! ÎZ" ÏZ$ ÐZ& ÑZ' ÒZ( ÓZ* ÔZ+ ÕZ, ÖZ- ×Z. ØZ/ ÙZ0 ÚZ3 ÛZ5 ÜZ7 ÝZ8 ÞZ9 ßZ: àZ; áZ= âZ> ãZ? äZA åZB æZC çZD èZE éZG êZH ëZK ìZL íZM îZN ïZO ðZP ñZQ òZR óZS ôZT õZV öZW ÷ZX øZY ùZ[ úZ\ ûZ] üZ^ ýZ_ þZ` @Za AZc BZd CZe DZf EZh FZi GZk HZl IZm JZn KZo LZp MZq NZr OZs PZx QZy RZ{ SZ| TZ} UZ~ VZ€ WZ XZ‚ YZƒ ZZ„ [Z… \Z† ]Z‡ ^Zˆ _Z‰ `ZŠ aZ‹ bZŒ cZ dZŽ eZ fZ gZ‘ hZ“ iZ” jZ• kZ– lZ— mZ˜ nZ™ oZœ pZ qZž rZŸ sZ  tZ¡ uZ¢ vZ£ wZ¤ xZ¥ yZ¦ zZ§ {Z¨ |Z© }Z« ~Z¬ €Z­ Z® ‚Z¯ ƒZ° „Z± …Z´ †Z¶ ‡Z· ˆZ¹ ‰Zº ŠZ» ‹Z¼ ŒZ½ Z¿ ŽZÀ Zà ZÄ ‘ZÅ ’ZÆ “ZÇ ”ZÈ •ZÊ –ZË —ZÍ ˜ZÎ ™ZÏ šZÐ ›ZÑ œZÓ ZÕ žZ× ŸZÙ  ZÚ ¡ZÛ ¢ZÝ £ZÞ ¤Zß ¥Zâ ¦Zä §Zå ¨Zç ©Zè ªZê «Zì ¬Zí ­Zî ®Zï ¯Zð °Zò ±Zó ²Zô ³Zõ ´Zö µZ÷ ¶Zø ·Zù ¸Zú ¹Zû ºZü »Zý ¼Zþ ½Zÿ ¾[ ¿[ À[ Á[ Â[ Ã[ Ä[ Å[ Æ[ Ç[ È[ É[ Ê[ Ë[ Ì[ Í[ Î[ Ï[ Ð[ Ñ[ Ò[ Ó[ Ô[ Õ[ Ö[ ×[ Ø[ Ù[ Ú[ Û[ Ü[! Ý[" Þ[# ß[$ à[% á[& â[' ã[( ä[) å[* æ[+ ç[, è[- é[. ê[/ ë[0 ì[1 í[3 î[5 ï[6 ð[8 ñ[9 ò[: ó[; ô[< õ[= ö[> ÷[? ø[A ù[B ú[C û[D ü[E ý[F þ[G @[H A[I B[J C[K D[L E[M F[N G[O H[R I[V J[^ K[` L[a M[g N[h O[k P[m Q[n R[o S[r T[t U[v V[w W[x X[y Y[{ Z[| [[~ \[ ][‚ ^[† _[Š `[ a[Ž b[ c[‘ d[’ e[” f[– g[Ÿ h[§ i[¨ j[© k[¬ l[­ m[® n[¯ o[± p[² q[· r[º s[» t[¼ u[À v[Á w[à x[È y[É z[Ê {[Ë |[Í }[Î ~[Ï €[Ñ [Ô ‚[Õ ƒ[Ö „[× …[Ø †[Ù ‡[Ú ˆ[Û ‰[Ü Š[à ‹[â Œ[ã [æ Ž[ç [é [ê ‘[ë ’[ì “[í ”[ï •[ñ –[ò —[ó ˜[ô ™[õ š[ö ›[÷ œ[ý [þ ž\ Ÿ\  \ ¡\ ¢\ £\ ¤\ ¥\ ¦\ §\ ¨\ ©\ ª\ «\ ¬\ ­\ ®\ ¯\ °\ ±\! ²\# ³\& ´\( µ\) ¶\* ·\+ ¸\- ¹\. º\/ »\0 ¼\2 ½\3 ¾\5 ¿\6 À\7 Á\C Â\D Ã\F Ä\G Å\L Æ\M Ç\R È\S É\T Ê\V Ë\W Ì\X Í\Z Î\[ Ï\\ Ð\] Ñ\_ Ò\b Ó\d Ô\g Õ\h Ö\i ×\j Ø\k Ù\l Ú\m Û\p Ü\r Ý\s Þ\t ß\u à\v á\w â\x ã\{ ä\| å\} æ\~ ç\€ è\ƒ é\„ ê\… ë\† ì\‡ í\‰ î\Š ï\‹ ð\Ž ñ\ ò\’ ó\“ ô\• õ\ ö\ž ÷\Ÿ ø\  ù\¡ ú\¤ û\¥ ü\¦ ý\§ þ\¨ @\ª A\® B\¯ C\° D\² E\´ F\¶ G\¹ H\º I\» J\¼ K\¾ L\À M\ N\à O\Å P\Æ Q\Ç R\È S\É T\Ê U\Ì V\Í W\Î X\Ï Y\Ð Z\Ñ [\Ó \\Ô ]\Õ ^\Ö _\× `\Ø a\Ú b\Û c\Ü d\Ý e\Þ f\ß g\à h\â i\ã j\ç k\é l\ë m\ì n\î o\ï p\ñ q\ò r\ó s\ô t\õ u\ö v\÷ w\ø x\ù y\ú z\ü {\ý |\þ }\ÿ ~] €] ] ‚] ƒ] „] …] †] ‡] ˆ] ‰] Š] ‹] Œ] ] Ž] ] ] ‘] ’] “] ”] •] –] —]! ˜]" ™]# š]% ›]( œ]* ]+ ž], Ÿ]/  ]0 ¡]1 ¢]2 £]3 ¤]5 ¥]6 ¦]7 §]8 ¨]9 ©]: ª]; «]< ¬]? ­]@ ®]A ¯]B °]C ±]D ²]E ³]F ´]H µ]I ¶]M ·]N ¸]O ¹]P º]Q »]R ¼]S ½]T ¾]U ¿]V À]W Á]Y Â]Z Ã]\ Ä]^ Å]_ Æ]` Ç]a È]b É]c Ê]d Ë]e Ì]f Í]g Î]h Ï]j Ð]m Ñ]n Ò]p Ó]q Ô]r Õ]s Ö]u ×]v Ø]w Ù]x Ú]y Û]z Ü]{ Ý]| Þ]} ß]~ à] á]€ â] ã]ƒ ä]„ å]… æ]† ç]‡ è]ˆ é]‰ ê]Š ë]‹ ì]Œ í] î]Ž ï] ð] ñ]‘ ò]’ ó]“ ô]” õ]• ö]– ÷]— ø]˜ ù]š ú]› û]œ ü]ž ý]Ÿ þ] @]¡A]¢B]£C]¤D]¥E]¦F]§G]¨H]©I]ªJ]«K]¬L]­M]®N]¯O]°P]±Q]²R]³S]´T]µU]¶V]¸W]¹X]ºY]»Z]¼[]½\]¾]]¿^]À_]Á`]Âa]Ãb]Äc]Æd]Çe]Èf]Ég]Êh]Ëi]Ìj]Îk]Ïl]Ðm]Ñn]Òo]Óp]Ôq]Õr]Ös]×t]Øu]Ùv]Úw]Üx]ßy]àz]ã{]ä|]ê}]ì~]í€]ð]õ‚]öƒ]ø„]ù…]ú†]û‡]üˆ]ÿ‰^Š^‹^Œ^ ^ Ž^ ^ ^‘^’^“^”^•^–^ —^!˜^"™^#š^$›^%œ^(^)ž^*Ÿ^+ ^,¡^/¢^0£^2¤^3¥^4¦^5§^6¨^9©^:ª^>«^?¬^@­^A®^C¯^F°^G±^H²^I³^J´^Kµ^M¶^N·^O¸^P¹^Qº^R»^S¼^V½^W¾^X¿^YÀ^ZÁ^\Â^]Ã^_Ä^`Å^cÆ^dÇ^eÈ^fÉ^gÊ^hË^iÌ^jÍ^kÎ^lÏ^mÐ^nÑ^oÒ^pÓ^qÔ^uÕ^wÖ^y×^~Ø^Ù^‚Ú^ƒÛ^…Ü^ˆÝ^‰Þ^Œß^à^Žá^’â^˜ã^›ä^å^¡æ^¢ç^£è^¤é^¨ê^©ë^ªì^«í^¬î^®ï^¯ð^°ñ^±ò^²ó^´ô^ºõ^»ö^¼÷^½ø^¿ù^Àú^Áû^Âü^Ãý^Äþ^Å@^ÆA^ÇB^ÈC^ËD^ÌE^ÍF^ÎG^ÏH^ÐI^ÔJ^ÕK^×L^ØM^ÙN^ÚO^ÜP^ÝQ^ÞR^ßS^àT^áU^âV^ãW^äX^åY^æZ^ç[^é\^ë]^ì^^í_^î`^ïa^ðb^ñc^òd^óe^õf^øg^ùh^ûi^üj^ýk_l_m_n_ o_ p_ q_r_s_t_u_v_w_x_y_z_{_!|_"}_#~_$€_(_+‚_,ƒ_.„_0…_2†_3‡_4ˆ_5‰_6Š_7‹_8Œ_;_=Ž_>_?_A‘_B’_C“_D”_E•_F–_G—_H˜_I™_Jš_K›_Lœ_M_Nž_OŸ_Q _T¡_Y¢_Z£_[¤_\¥_^¦__§_`¨_c©_eª_g«_h¬_k­_n®_o¯_r°_t±_u²_v³_x´_zµ_}¶_~·_¸_ƒ¹_†º_»_޼_½_‘¾_“¿_”À_–Á_šÂ_›Ã_Ä_žÅ_ŸÆ_ Ç_¢È_£É_¤Ê_¥Ë_¦Ì_§Í_©Î_«Ï_¬Ð_¯Ñ_°Ò_±Ó_²Ô_³Õ_´Ö_¶×_¸Ø_¹Ù_ºÚ_»Û_¾Ü_¿Ý_ÀÞ_Áß_Âà_Çá_Èâ_Êã_Ëä_Îå_Óæ_Ôç_Õè_Úé_Ûê_Üë_Þì_ßí_âî_ãï_åð_æñ_èò_éó_ìô_ïõ_ðö_ò÷_óø_ôù_öú_÷û_ùü_úý_üþ`@`A` B` C` D`E`F`G`H`I`J`K`L`"M`#N`$O`,P`-Q`.R`0S`1T`2U`3V`4W`6X`7Y`8Z`9[`:\`=]`>^`@_`D``Ea`Fb`Gc`Hd`Ie`Jf`Lg`Nh`Oi`Qj`Sk`Tl`Vm`Wn`Xo`[p`\q`^r`_s``t`au`ev`fw`nx`qy`rz`t{`u|`w}`~~`€€``‚‚`…ƒ`†„`‡…`ˆ†`Ї`‹ˆ`މ`Š`‹`‘Œ`“`•Ž`—`˜`™‘`œ’`ž“`¡”`¢•`¤–`¥—`§˜`©™`ªš`®›`°œ`³`µž`¶Ÿ`· `¹¡`º¢`½£`¾¤`¿¥`À¦`Á§`¨`é`Ī`Ç«`Ȭ`É­`Ì®`ͯ`ΰ`ϱ`в`Ò³`Ó´`Ôµ`Ö¶`×·`Ù¸`Û¹`Þº`á»`â¼`ã½`ä¾`å¿`êÀ`ñÁ`òÂ`õÃ`÷Ä`øÅ`ûÆ`üÇ`ýÈ`þÉ`ÿÊaËaÌaÍaÎaÏa Ða Ña ÒaÓaÔaÕaÖa×aØaÙaÚaÛaÜaÝaÞaßa!àa"áa%âa(ãa)äa*åa,æa-ça.èa/éa0êa1ëa2ìa3ía4îa5ïa6ða7ña8òa9óa:ôa;õa<öa=÷a>øa@ùaAúaBûaCüaDýaEþaF@aGAaIBaKCaMDaOEaPFaRGaSHaTIaVJaWKaXLaYMaZNa[Oa\Pa^Qa_Ra`SaaTacUadVaeWafXaiYajZak[al\am]an^ao_aq`araasbatcavdaxeayfazga{ha|ia}ja~kala€mana‚oaƒpa„qa…ra†sa‡taˆua‰vaŠwaŒxayaza{a‘|a’}a“~a•€a–a—‚a˜ƒa™„aš…a›†aœ‡ažˆaŸ‰a Ša¡‹a¢Œa£a¤Ža¥a¦aª‘a«’a­“a®”a¯•a°–a±—a²˜a³™a´šaµ›a¶œa¸a¹žaºŸa» a¼¡a½¢a¿£aÀ¤aÁ¥aæaħaŨaÆ©aǪaÉ«a̬aÍ­aήaϯaаaÓ±aÕ²aÖ³a×´aصaÙ¶aÚ·aÛ¸aܹaݺaÞ»aß¼aà½aá¾aâ¿aãÀaäÁaåÂaçÃaèÄaéÅaêÆaëÇaìÈaíÉaîÊaïËaðÌañÍaòÎaóÏaôÐaöÑa÷ÒaøÓaùÔaúÕaûÖaü×aýØaþÙbÚbÛbÜbÝbÞbßbàb ábâbãbäbåbæbçb èb#éb&êb'ëb(ìb)íb+îb-ïb/ðb0ñb1òb2ób5ôb6õb8öb9÷b:øb;ùb<úbBûbDübEýbFþbJ@bOAbPBbUCbVDbWEbYFbZGb\Hb]Ib^Jb_Kb`LbaMbbNbdObePbhQbqRbrSbtTbuUbwVbxWbzXb{Yb}Zb[b‚\bƒ]b…^b†_b‡`bˆab‹bbŒcbdbŽebfbgb”hb™ibœjbkbžlb£mb¦nb§ob©pbªqb­rb®sb¯tb°ub²vb³wb´xb¶yb·zb¸{bº|b¾}bÀ~bÁ€bÃbË‚bσbÑ„bÕ…b݆bÞ‡bàˆbá‰bäŠbê‹bëŒbðbòŽbõbøbù‘bú’bû“c”c•c–c—c˜c ™c šc ›c œccžcŸc c¡c¢c£c¤c¥c¦c&§c'¨c)©c,ªc-«c.¬c0­c1®c3¯c4°c5±c6²c7³c8´c;µc<¶c>·c?¸c@¹cAºcD»cG¼cH½cJ¾cQ¿cRÀcSÁcTÂcVÃcWÄcXÅcYÆcZÇc[Èc\Éc]Êc`ËcdÌceÍcfÎchÏcjÐckÑclÒcoÓcpÔcrÕcsÖct×cuØcxÙcyÚc|Ûc}Üc~ÝcÞcßcƒàc„ác…âc†ãc‹äcåc‘æc“çc”èc•éc—êc™ëcšìc›ícœîcïcžðcŸñc¡òc¤óc¦ôc«õc¯öc±÷c²øcµùc¶úc¹ûc»üc½ýc¿þcÀ@cÁAcÂBcÃCcÅDcÇEcÈFcÊGcËHcÌIcÑJcÓKcÔLcÕMc×NcØOcÙPcÚQcÛRcÜScÝTcßUcâVcäWcåXcæYcçZcè[cë\cì]cî^cï_cð`cñacóbcõcc÷dcùecúfcûgcühcþidjdkdldmdnd od pd qdrdsdtdudvdwdxdydzd{d|d"}d#~d$€d%d'‚d(ƒd)„d+…d.†d/‡d0ˆd1‰d2Šd3‹d5Œd6d7Žd8d9d;‘d<’d>“d@”dB•dC–dI—dK˜dL™dMšdN›dOœdPdQždSŸdU dV¡dW¢dY£dZ¤d[¥d\¦d]§d_¨d`©daªdb«dc¬dd­de®df¯dh°dj±dk²dl³dn´doµdp¶dq·dr¸ds¹dtºdu»dv¼dw½d{¾d|¿d}Àd~ÁdÂd€ÃdÄdƒÅd†ÆdˆÇd‰ÈdŠÉd‹ÊdŒËdÌdŽÍdÎdÏd“Ðd”Ñd—Òd˜ÓdšÔd›ÕdœÖd×dŸØd Ùd¡Úd¢Ûd£Üd¥Ýd¦Þd§ßd¨àdªád«âd¯ãd±äd²åd³æd´çd¶èd¹éd»êd½ëd¾ìd¿ídÁîdÃïdÄðdÆñdÇòdÈódÉôdÊõdËödÌ÷dÏødÑùdÓúdÔûdÕüdÖýdÙþdÚ@dÛAdÜBdÝCdßDdàEdáFdãGdåHdçIdèJdéKdêLdëMdìNdíOdîPdïQdðRdñSdòTdóUdôVdõWdöXd÷YdøZdù[dú\dû]dü^dý_dþ`dÿaebecedeeefegeheie je ke le meneoepeqereseteuevewexeyeze{e|e}e ~e!€e"e#‚e$ƒe&„e'…e(†e)‡e*ˆe,‰e-Še0‹e1Œe2e3Že7e:e<‘e=’e@“eA”eB•eC–eD—eF˜eG™eJšeK›eMœeNePžeRŸeS eT¡eW¢eX£eZ¤e\¥e_¦e`§ea¨ed©eeªeg«eh¬ei­ej®em¯en°eo±eq²es³eu´evµex¶ey·ez¸e{¹e|ºe}»e~¼e½e€¾e¿e‚ÀeƒÁe„Âe…Ãe†ÄeˆÅe‰ÆeŠÇeÈeŽÉeÊe’Ëe”Ìe•Íe–Îe˜ÏešÐeÑežÒe Óe¢Ôe£Õe¦Öe¨×eªØe¬Ùe®Úe±Ûe²Üe³Ýe´Þeµße¶àe·áe¸âeºãe»äe¾åe¿æeÀçeÂèeÇéeÈêeÉëeÊìeÍíeÐîeÑïeÓðeÔñeÕòeØóeÙôeÚõeÛöeÜ÷eÝøeÞùeßúeáûeãüeäýeêþeë@eòAeóBeôCeõDeøEeùFeûGeüHeýIeþJeÿKfLfMfNfOfPf Qf Rf SfTfUfVfWfXfYfZf[f\f]f!^f"_f#`f$af&bf)cf*df+ef,ff.gf0hf2if3jf7kf8lf9mf:nf;of=pf?qf@rfBsfDtfEufFvfGwfHxfIyfJzfM{fN|fP}fQ~fX€fYf[‚f\ƒf]„f^…f`†fb‡fcˆfe‰fgŠfi‹fjŒfkflŽfmfqfr‘fs’fu“fx”fy•f{–f|—f}˜f™f€šf›fƒœf…f†žfˆŸf‰ fŠ¡f‹¢f£fޤf¥f¦f’§f“¨f”©f•ªf˜«f™¬fš­f›®fœ¯fž°fŸ±f ²f¡³f¢´f£µf¤¶f¥·f¦¸f©¹fªºf«»f¬¼f­½f¯¾f°¿f±Àf²Áf³ÂfµÃf¶Äf·Åf¸ÆfºÇf»Èf¼Éf½Êf¿ËfÀÌfÁÍfÂÎfÃÏfÄÐfÅÑfÆÒfÇÓfÈÔfÉÕfÊÖfË×fÌØfÍÙfÎÚfÏÛfÐÜfÑÝfÒÞfÓßfÔàfÕáfÖâf×ãfØäfÚåfÞæfßçfàèfáéfâêfãëfäìfåífçîfèïfêðfëñfìòfíófîôfïõfñöfõ÷föøføùfúúfûûfýügýgþg@gAgBgCgDg EgFgGgHgIgJgKgLgMgNgOgPg Qg!Rg"Sg#Tg$Ug%Vg'Wg)Xg.Yg0Zg2[g3\g6]g7^g8_g9`g;ag<bg>cg?dgAegDfgEggGhgJigKjgMkgRlgTmgUngWogXpgYqgZrg[sg]tgbugcvgdwgfxggygkzgl{gn|gq}gt~gv€gxgy‚gzƒg{„g}…g€†g‚‡gƒˆg…‰g†Šgˆ‹gŠŒgŒgŽgŽgg‘‘g’’g““g””g–•g™–g›—gŸ˜g ™g¡šg¤›g¦œg©g¬žg®Ÿg± g²¡g´¢g¹£gº¤g»¥g¼¦g½§g¾¨g¿©gÀªg«gŬgÆ­gÇ®gȯgɰgʱg˲g̳gÍ´gεgÕ¶gÖ·g׸gÛ¹gߺgá»gã¼gä½gæ¾gç¿gèÀgêÁgëÂgíÃgîÄgòÅgõÆgöÇg÷ÈgøÉgùÊgúËgûÌgüÍgþÎhÏhÐhÑhÒhÓh ÔhÕhÖh×hØhÙhÚhÛhÜhÝhÞhßh àh"áh#âh$ãh%äh&åh'æh(çh+èh,éh-êh.ëh/ìh0íh1îh4ïh5ðh6ñh:òh;óh?ôhGõhKöhM÷hOøhRùhVúhWûhXühYýhZþh[@h\Ah]Bh^Ch_DhjEhlFhmGhnHhoIhpJhqKhrLhsMhuNhxOhyPhzQh{Rh|Sh}Th~UhVh€Wh‚Xh„Yh‡Zhˆ[h‰\hŠ]h‹^hŒ_h`hŽahbh‘ch’dh”eh•fh–gh˜hh™ihšjh›khœlhmhžnhŸoh ph¡qh£rh¤sh¥th©uhªvh«wh¬xh®yh±zh²{h´|h¶}h·~h¸€h¹hº‚h»ƒh¼„h½…h¾†h¿‡hÁˆhÉhÄŠhÅ‹hÆŒhÇhÈŽhÊhÌhΑhÏ’hГhÑ”hÓ•hÔ–hÖ—hטhÙ™hÛšhÜ›hÝœhÞhßžháŸhâ hä¡hå¢hæ£hç¤hè¥hé¦hê§hë¨hì©híªhï«hò¬hó­hô®hö¯h÷°hø±hû²hý³hþ´hÿµi¶i·i¸i¹iºi»i¼i ½i ¾i ¿iÀiÁiÂiÃiÄiÅiÆiÇiÈiÉiÊiËiÌiÍi!Îi"Ïi#Ði%Ñi&Òi'Ói(Ôi)Õi*Öi+×i,Øi.Ùi/Úi1Ûi2Üi3Ýi5Þi6ßi7ài8ái:âi;ãi<äi>åi@æiAçiCèiDéiEêiFëiGìiHíiIîiJïiKðiLñiMòiNóiOôiPõiQöiR÷iSøiUùiVúiXûiYüi[ýi\þi_@iaAibBidCieDigEihFiiGijHilIimJioKipLirMisNitOiuPivQizRi{Si}Ti~UiViWiƒXi…YiŠZi‹[iŒ\iŽ]i^i_i‘`i’ai“bi–ci—di™eišfigižhiŸii ji¡ki¢li£mi¤ni¥oi¦pi©qiªri¬si®ti¯ui°vi²wi³xiµyi¶zi¸{i¹|iº}i¼~i½€i¾i¿‚iÀƒi„iÃ…iĆiŇiƈiljiÈŠiÉ‹iËŒiÍiÏŽiÑiÒiÓ‘iÕ’iÖ“i×”iØ•iÙ–iÚ—iܘiÝ™iÞšiá›iâœiãiäžiåŸiæ iç¡iè¢ié£iê¤ië¥iì¦iî§iï¨ið©iñªió«iô¬iõ­iö®i÷¯iø°iù±iú²iû³iü´iþµj¶j·j¸j¹jºj»j¼j½j¾j ¿j Àj Áj ÂjÃjÄjÅjÆjÇjÈjÉjÊjËjÌjÍjÎjÏjÐjÑj Òj"Ój#Ôj$Õj%Öj&×j'Øj)Ùj+Új,Ûj-Üj.Ýj0Þj2ßj3àj4áj6âj7ãj8äj9åj:æj;çj<èj?éj@êjAëjBìjCíjEîjFïjHðjIñjJòjKójLôjMõjNöjO÷jQøjRùjSújTûjUüjVýjWþjZ@j\Aj]Bj^Cj_Dj`EjbFjcGjdHjfIjgJjhKjiLjjMjkNjlOjmPjnQjoRjpSjrTjsUjtVjuWjvXjwYjxZjz[j{\j}]j~^j_j`j‚ajƒbj…cj†dj‡ejˆfj‰gjŠhj‹ijŒjjkjlj’mj“nj”oj•pj–qj˜rj™sjštj›ujœvjwjžxjŸyj¡zj¢{j£|j¤}j¥~j¦€j§j¨‚jªƒj­„j®…j¯†j°‡j±ˆj²‰j³Šj´‹jµŒj¶j·Žj¸j¹jº‘j»’j¼“j½”j¾•j¿–jÀ—jÁ˜j™jÚjÄ›jÅœjÆjÇžjÈŸjÉ jÊ¡jË¢jÌ£jͤjÎ¥jϦjЧjѨjÒ©jÓªjÔ«jÕ¬jÖ­j×®jدjÙ°jÚ±jÛ²jܳjÝ´jÞµjß¶jà·já¸jâ¹jãºjä»jå¼jæ½jç¾jè¿jéÀjêÁjëÂjìÃjíÄjîÅjïÆjðÇjñÈjòÉjóÊjôËjõÌjöÍj÷ÎjøÏjùÐjúÑjûÒjüÓjýÔjþÕjÿÖk×kØkÙkÚkÛkÜkÝkÞkßk àk ák âk ãk äkåkækçkèkékêkëkìkíkîkïkðkñkòkókôkõkök%÷k&øk(ùk)úk*ûk+ük,ýk-þk.@k/Ak0Bk1Ck3Dk4Ek5Fk6Gk8Hk;Ik<Jk=Kk?Lk@MkANkBOkDPkEQkHRkJSkKTkMUkNVkOWkPXkQYkRZkS[kT\kU]kV^kW_kX`kZak[bk\ck]dk^ek_fk`gkahkhikijkkkkllkmmknnkookppkqqkrrksskttkuukvvkwwkxxkzyk}zk~{k|k€}k…~kˆ€kŒkŽ‚kƒk„k‘…k”†k•‡k—ˆk˜‰k™Škœ‹kŒkžkŸŽk k¢k£‘k¤’k¥“k¦”k§•k¨–k©—k«˜k¬™k­šk®›k¯œk°k±žk²Ÿk¶ k¸¡k¹¢kº£k»¤k¼¥k½¦k¾§kÀ¨kékĪkÆ«kǬkÈ­kÉ®kʯk̰kαkвkѳkØ´kÚµkܶkÝ·kÞ¸kß¹kàºkâ»kã¼kä½kå¾kæ¿kçÀkèÁkéÂkìÃkíÄkîÅkðÆkñÇkòÈkôÉköÊk÷ËkøÌkúÍkûÎküÏkþÐkÿÑlÒlÓlÔlÕlÖl×l Øl Ùl Úl ÛlÜlÝlÞlßlàlál âl#ãl%äl+ål,æl-çl1èl3él6êl7ël9ìl:íl;îl<ïl>ðl?ñlCòlDólEôlHõlKölL÷lMølNùlOúlQûlRülSýlVþlX@lYAlZBlbClcDleElfFlgGlkHllIlmJlnKloLlqMlsNluOlwPlxQlzRl{Sl|TlUl€Vl„Wl‡XlŠYl‹ZlŽ\l‘]l’^l•_l–`l—al˜blšclœdlelžfl gl¢hl¨il¬jl¯kl°ll´mlµnl¶ol·plºqlÀrlÁslÂtlÃulÆvlÇwlÈxlËylÍzlÎ{lÏ|lÑ}lÒ~lØ€lÙlÚ‚l܃lÝ„lß…lä†læ‡lçˆlé‰lìŠlí‹lòŒlôlùŽlÿmm‘m’m“m”m•m –m —m ˜m™mšm›mœmmžmŸm m¡m¢m£m ¤m!¥m"¦m#§m$¨m&©m(ªm)«m,¬m-­m/®m0¯m4°m6±m7²m8³m:´m?µm@¶mB·mD¸mI¹mLºmP»mU¼mV½mW¾mX¿m[Àm]Ám_ÂmaÃmbÄmdÅmeÆmgÇmhÈmkÉmlÊmmËmpÌmqÍmrÎmsÏmuÐmvÑmyÒmzÓm{Ôm}Õm~Öm×m€ØmÙmƒÚm„Ûm†Üm‡ÝmŠÞm‹ßmàmámâm’ãm–äm—åm˜æm™çmšèmœém¢êm¥ëm¬ìm­ím°îm±ïm³ðm´ñm¶òm·óm¹ômºõm»öm¼÷m½øm¾ùmÁúmÂûmÃümÈýmÉþmÊ@mÍAmÎBmÏCmÐDmÒEmÓFmÔGmÕHm×ImÚJmÛKmÜLmßMmâNmãOmåPmçQmèRméSmêTmíUmïVmðWmòXmôYmõZmö[mø\mú]mý^mþ_mÿ`nanbncndnenfngnhn in jnknlnmnnnonpnqnrnsntn"un&vn'wn(xn*yn,zn.{n0|n1}n3~n5€n6n7‚n9ƒn;„n<…n=†n>‡n?ˆn@‰nAŠnB‹nEŒnFnGŽnHnInJ‘nK’nL“nO”nP•nQ–nR—nU˜nW™nYšnZ›n\œn]n^žn`Ÿna nb¡nc¢nd£ne¤nf¥ng¦nh§ni¨nj©nlªnm«no¬np­nq®nr¯ns°nt±nu²nv³nw´nxµny¶nz·n{¸n|¹n}ºn€»n¼n‚½n„¾n‡¿nˆÀnŠÁn‹ÂnŒÃnÄnŽÅn‘Æn’Çn“Èn”Én•Ên–Ën—Ìn™ÍnšÎn›ÏnÐnžÑn Òn¡Ón£Ôn¤Õn¦Ön¨×n©Øn«Ùn¬Ún­Ûn®Ün°Ýn³Þnµßn¸àn¹án¼ân¾ãn¿änÀånÃænÄçnÅènÆénÈênÉënÊìnÌínÍînÎïnÐðnÒñnÖònØónÙônÛõnÜönÝ÷nãønçùnêúnëûnìüníýnîþnï@nðAnñBnòCnóDnõEnöFn÷GnøHnúInûJnüKnýLnþMnÿNoOoPoQoRoSoToUo Vo Wo Xo YoZo[o\o]o^o_o`oaobocodoeofogo!ho"io#jo%ko&lo'mo(no,oo.po0qo2ro4so5to7uo8vo9wo:xo;yo<zo={o?|o@}oA~oB€oCoD‚oEƒoH„oI…oJ†oL‡oNˆoO‰oPŠoQ‹oRŒoSoTŽoUoVoW‘oY’oZ“o[”o]•o_–o`—oa˜oc™odšoe›ogœohoižojŸok ol¡oo¢op£oq¤os¥ou¦ov§ow¨oy©o{ªo}«o~¬o­o€®o¯o‚°oƒ±o…²o†³o‡´oеo‹¶o·o¸o‘¹o’ºo“»o”¼o•½o–¾o—¿o˜Ào™ÁošÂo›ÃoÄožÅoŸÆo Ço¢Èo£Éo¤Êo¥Ëo¦Ìo¨Ío©ÎoªÏo«Ðo¬Ño­Òo®Óo¯Ôo°Õo±Öo²×o´ØoµÙo·Úo¸ÛoºÜo»Ýo¼Þo½ßo¾ào¿áoÁâoÃãoÄäoÅåoÆæoÇçoÈèoÊéoËêoÌëoÍìoÎíoÏîoÐïoÓðoÔñoÕòoÖóo×ôoØõoÙöoÚ÷oÛøoÜùoÝúoßûoâüoãýoäþoå@oæAoçBoèCoéDoêEoëFoìGoíHoðIoñJoòKoóLoôMoõNoöOo÷PoøQoùRoúSoûToüUoýVoþWoÿXpYpZp[p\p]p^p_p`pap bp cp dp ep fpgphpipjpkplpmpnpopppqprpsptpup vp!wp"xp$yp%zp&{p'|p(}p)~p*€p+p,‚p-ƒp.„p/…p0†p1‡p2ˆp3‰p4Šp6‹p7Œp8p:Žp;p<p=‘p>’p?“p@”pA•pB–pC—pD˜pE™pFšpG›pHœpIpJžpKŸpM pN¡pP¢pQ£pR¤pS¥pT¦pU§pV¨pW©pXªpY«pZ¬p[­p\®p]¯p_°p`±pa²pb³pc´pdµpe¶pf·pg¸ph¹piºpj»pn¼pq½pr¾ps¿ptÀpwÁpyÂpzÃp{Äp}ÅpÆp‚ÇpƒÈp„Ép†Êp‡ËpˆÌp‹ÍpŒÎpÏpÐpÑp‘Òp“Óp—Ôp˜ÕpšÖp›×pžØpŸÙp Úp¡Ûp¢Üp£Ýp¤Þp¥ßp¦àp§áp¨âp©ãpªäp°åp²æp´çpµèp¶épºêp¾ëp¿ìpÄípÅîpÆïpÇðpÉñpËòpÌópÍôpÎõpÏöpÐ÷pÑøpÒùpÓúpÔûpÕüpÖýp×þpÚ@pÜApÝBpÞCpàDpáEpâFpãGpåHpêIpîJpðKpñLpòMpóNpôOpõPpöQpøRpúSpûTpüUpþVpÿWqXqYqZq[q\q]q^q_q`q aq bq cqdqeqfqgqhqiqjqkqlqmqnq oq!pq"qq#rq$sq%tq'uq(vq)wq*xq+yq,zq-{q.|q2}q3~q4€q5q7‚q8ƒq9„q:…q;†q<‡q=ˆq>‰q?Šq@‹qAŒqBqCŽqDqFqG‘qH’qI“qK”qM•qO–qP—qQ˜qR™qSšqT›qUœqVqWžqXŸqY qZ¡q[¢q]£q_¤q`¥qa¦qb§qc¨qe©qiªqj«qk¬ql­qm®qo¯qp°qq±qt²qu³qv´qwµqy¶q{·q|¸q~¹qºq€»q¼q‚½qƒ¾q…¿q†Àq‡ÁqˆÂq‰Ãq‹ÄqŒÅqÆqŽÇqÈq‘Éq’Êq“Ëq•Ìq–Íq—ÎqšÏq›ÐqœÑqÒqžÓq¡Ôq¢Õq£Öq¤×q¥Øq¦Ùq§Úq©ÛqªÜq«Ýq­Þq®ßq¯àq°áq±âq²ãq´äq¶åq·æq¸çqºèq»éq¼êq½ëq¾ìq¿íqÀîqÁïqÂðqÄñqÅòqÆóqÇôqÈõqÉöqÊ÷qËøqÌùqÍúqÏûqÐüqÑýqÒþqÓ @qÖ Aq× BqØ CqÙ DqÚ EqÛ FqÜ GqÝ HqÞ Iqß Jqá Kqâ Lqã Mqä Nqæ Oqè Pqé Qqê Rqë Sqì Tqí Uqï Vqð Wqñ Xqò Yqó Zqô [qõ \qö ]q÷ ^qø _qú `qû aqü bqý cqþ dqÿ er fr gr hr ir jr kr lr mr nr or pr qr rr sr tr ur vr wr xr yr zr {r |r }r ~r €r r ‚r ƒr „r …r! †r" ‡r# ˆr$ ‰r% Šr& ‹r' Œr) r+ Žr- r. r/ ‘r2 ’r3 “r4 ”r: •r< –r> —r@ ˜rA ™rB šrC ›rD œrE rF žrI ŸrJ  rK ¡rN ¢rO £rP ¤rQ ¥rS ¦rT §rU ¨rW ©rX ªrZ «r\ ¬r^ ­r` ®rc ¯rd °re ±rh ²rj ³rk ´rl µrm ¶rp ·rq ¸rs ¹rt ºrv »rw ¼rx ½r{ ¾r| ¿r} Àr‚ Árƒ Âr… Ãr† Är‡ Årˆ Ær‰ ÇrŒ ÈrŽ Ér Êr‘ Ër“ Ìr” Ír• Îr– Ïr— Ðr˜ Ñr™ Òrš Ór› Ôrœ Õr Örž ×r  Ør¡ Ùr¢ Úr£ Ûr¤ Ür¥ Ýr¦ Þr§ ßr¨ àr© árª âr« ãr® är± år² ær³ çrµ èrº ér» êr¼ ër½ ìr¾ ír¿ îrÀ ïrÅ ðrÆ ñrÇ òrÉ órÊ ôrË õrÌ örÏ ÷rÑ ørÓ ùrÔ úrÕ ûrÖ ürØ ýrÚ þrÛ!@äÆ!AäÇ!BäÈ!CäÉ!DäÊ!EäË!FäÌ!GäÍ!HäÎ!IäÏ!JäÐ!KäÑ!LäÒ!MäÓ!NäÔ!OäÕ!PäÖ!Qä×!RäØ!SäÙ!TäÚ!UäÛ!VäÜ!WäÝ!XäÞ!Yäß!Zäà![äá!\äâ!]äã!^ää!_äå!`äæ!aäç!bäè!cäé!däê!eäë!fäì!gäí!häî!iäï!jäð!käñ!läò!mäó!näô!oäõ!päö!qä÷!räø!säù!täú!uäû!väü!wäý!xäþ!yäÿ!zå!{å!|å!}å!~å!€å!å!‚å!ƒå!„å !…å !†å !‡å !ˆå !‰å!Šå!‹å!Œå!å!Žå!å!å!‘å!’å!“å!”å!•å!–å!—å!˜å!™å!šå!›å !œå!!å"!žå#!Ÿå$! å%!¡0!¢0!£0!¤·!¥É!¦Ç!§¨!¨0!©0!ª !«ÿ^!¬ !­ &!® !¯ !° !± !²0!³0!´0!µ0 !¶0 !·0 !¸0 !¹0 !º0!»0!¼0!½0!¾0!¿0!À±!Á×!Â÷!Ã"6!Ä"'!Å"(!Æ"!Ç"!È"*!É")!Ê"!Ë"7!Ì"!Í"¥!Î"%!Ï" !Ð#!Ñ"™!Ò"+!Ó".!Ô"a!Õ"L!Ö"H!×"=!Ø"!Ù"`!Ú"n!Û"o!Ü"d!Ý"e!Þ"!ß"5!à"4!á&B!â&@!ã°!ä 2!å 3!æ!!çÿ!è¤!éÿà!êÿá!ë 0!ì§!í!!î&!ï&!ð%Ë!ñ%Ï!ò%Î!ó%Ç!ô%Æ!õ%¡!ö% !÷%³!ø%²!ù ;!ú!’!û!!ü!‘!ý!“!þ0"@å&"Aå'"Bå("Cå)"Då*"Eå+"Få,"Gå-"Hå."Iå/"Jå0"Kå1"Lå2"Må3"Nå4"Oå5"På6"Qå7"Rå8"Så9"Tå:"Uå;"Vå<"Wå="Xå>"Yå?"Zå@"[åA"\åB"]åC"^åD"_åE"`åF"aåG"båH"cåI"dåJ"eåK"fåL"gåM"håN"iåO"jåP"kåQ"låR"måS"nåT"oåU"påV"qåW"råX"såY"tåZ"uå["vå\"wå]"xå^"yå_"zå`"{åa"|åb"}åc"~åd"€åe"åf"‚åg"ƒåh"„åi"…åj"†åk"‡ål"ˆåm"‰ån"Šåo"‹åp"Œåq"år"Žås"åt"åu"‘åv"’åw"“åx"”åy"•åz"–å{"—å|"˜å}"™å~"šå"›å€"œå"å‚"žåƒ"Ÿå„" å…"¡!p"¢!q"£!r"¤!s"¥!t"¦!u"§!v"¨!w"©!x"ª!y"«å†"¬å‡"­åˆ"®å‰"¯åŠ"°å‹"±$ˆ"²$‰"³$Š"´$‹"µ$Œ"¶$"·$Ž"¸$"¹$"º$‘"»$’"¼$“"½$”"¾$•"¿$–"À$—"Á$˜"Â$™"Ã$š"Ä$›"Å$t"Æ$u"Ç$v"È$w"É$x"Ê$y"Ë$z"Ì${"Í$|"Î$}"Ï$~"Ð$"Ñ$€"Ò$"Ó$‚"Ô$ƒ"Õ$„"Ö$…"×$†"Ø$‡"Ù$`"Ú$a"Û$b"Ü$c"Ý$d"Þ$e"ß$f"à$g"á$h"â$i"ãåŒ"äå"å2 "æ2!"ç2""è2#"é2$"ê2%"ë2&"ì2'"í2("î2)"ïåŽ"ðå"ñ!`"ò!a"ó!b"ô!c"õ!d"ö!e"÷!f"ø!g"ù!h"ú!i"û!j"ü!k"ýå"þå‘#@å’#Aå“#Bå”#Cå•#Då–#Eå—#Få˜#Gå™#Håš#Iå›#Jåœ#Kå#Låž#MåŸ#Nå #Oå¡#På¢#Qå£#Rå¤#Så¥#Tå¦#Uå§#Vå¨#Wå©#Xåª#Yå«#Zå¬#[å­#\å®#]å¯#^å°#_å±#`å²#aå³#bå´#cåµ#då¶#eå·#få¸#gå¹#håº#iå»#jå¼#kå½#lå¾#må¿#nåÀ#oåÁ#påÂ#qåÃ#råÄ#såÅ#tåÆ#uåÇ#våÈ#wåÉ#xåÊ#yåË#zåÌ#{åÍ#|åÎ#}åÏ#~åÐ#€åÑ#åÒ#‚åÓ#ƒåÔ#„åÕ#…åÖ#†å×#‡åØ#ˆåÙ#‰åÚ#ŠåÛ#‹åÜ#ŒåÝ#åÞ#Žåß#åà#åá#‘åâ#’åã#“åä#”åå#•åæ#–åç#—åè#˜åé#™åê#šåë#›åì#œåí#åî#žåï#Ÿåð# åñ#¡ÿ#¢ÿ#£ÿ#¤ÿå#¥ÿ#¦ÿ#§ÿ#¨ÿ#©ÿ #ªÿ #«ÿ #¬ÿ #­ÿ #®ÿ#¯ÿ#°ÿ#±ÿ#²ÿ#³ÿ#´ÿ#µÿ#¶ÿ#·ÿ#¸ÿ#¹ÿ#ºÿ#»ÿ#¼ÿ#½ÿ#¾ÿ#¿ÿ#Àÿ #Áÿ!#Âÿ"#Ãÿ##Äÿ$#Åÿ%#Æÿ&#Çÿ'#Èÿ(#Éÿ)#Êÿ*#Ëÿ+#Ìÿ,#Íÿ-#Îÿ.#Ïÿ/#Ðÿ0#Ñÿ1#Òÿ2#Óÿ3#Ôÿ4#Õÿ5#Öÿ6#×ÿ7#Øÿ8#Ùÿ9#Úÿ:#Ûÿ;#Üÿ<#Ýÿ=#Þÿ>#ßÿ?#àÿ@#áÿA#âÿB#ãÿC#äÿD#åÿE#æÿF#çÿG#èÿH#éÿI#êÿJ#ëÿK#ìÿL#íÿM#îÿN#ïÿO#ðÿP#ñÿQ#òÿR#óÿS#ôÿT#õÿU#öÿV#÷ÿW#øÿX#ùÿY#úÿZ#ûÿ[#üÿ\#ýÿ]#þÿã$@åò$Aåó$Båô$Cåõ$Dåö$Eå÷$Fåø$Gåù$Håú$Iåû$Jåü$Kåý$Låþ$Måÿ$Næ$Oæ$Pæ$Qæ$Ræ$Sæ$Tæ$Uæ$Væ$Wæ $Xæ $Yæ $Zæ $[æ $\æ$]æ$^æ$_æ$`æ$aæ$bæ$cæ$dæ$eæ$fæ$gæ$hæ$iæ$jæ$kæ$læ$mæ$næ $oæ!$pæ"$qæ#$ræ$$sæ%$tæ&$uæ'$væ($wæ)$xæ*$yæ+$zæ,${æ-$|æ.$}æ/$~æ0$€æ1$æ2$‚æ3$ƒæ4$„æ5$…æ6$†æ7$‡æ8$ˆæ9$‰æ:$Šæ;$‹æ<$Œæ=$æ>$Žæ?$æ@$æA$‘æB$’æC$“æD$”æE$•æF$–æG$—æH$˜æI$™æJ$šæK$›æL$œæM$æN$žæO$ŸæP$ æQ$¡0A$¢0B$£0C$¤0D$¥0E$¦0F$§0G$¨0H$©0I$ª0J$«0K$¬0L$­0M$®0N$¯0O$°0P$±0Q$²0R$³0S$´0T$µ0U$¶0V$·0W$¸0X$¹0Y$º0Z$»0[$¼0\$½0]$¾0^$¿0_$À0`$Á0a$Â0b$Ã0c$Ä0d$Å0e$Æ0f$Ç0g$È0h$É0i$Ê0j$Ë0k$Ì0l$Í0m$Î0n$Ï0o$Ð0p$Ñ0q$Ò0r$Ó0s$Ô0t$Õ0u$Ö0v$×0w$Ø0x$Ù0y$Ú0z$Û0{$Ü0|$Ý0}$Þ0~$ß0$à0€$á0$â0‚$ã0ƒ$ä0„$å0…$æ0†$ç0‡$è0ˆ$é0‰$ê0Š$ë0‹$ì0Œ$í0$î0Ž$ï0$ð0$ñ0‘$ò0’$ó0“$ôæR$õæS$öæT$÷æU$øæV$ùæW$úæX$ûæY$üæZ$ýæ[$þæ\%@æ]%Aæ^%Bæ_%Cæ`%Dæa%Eæb%Fæc%Gæd%Hæe%Iæf%Jæg%Kæh%Læi%Mæj%Næk%Oæl%Pæm%Qæn%Ræo%Sæp%Tæq%Uær%Væs%Wæt%Xæu%Yæv%Zæw%[æx%\æy%]æz%^æ{%_æ|%`æ}%aæ~%bæ%cæ€%dæ%eæ‚%fæƒ%gæ„%hæ…%iæ†%jæ‡%kæˆ%læ‰%mæŠ%næ‹%oæŒ%pæ%qæŽ%ræ%sæ%tæ‘%uæ’%væ“%wæ”%xæ•%yæ–%zæ—%{æ˜%|æ™%}æš%~æ›%€æœ%æ%‚æž%ƒæŸ%„æ %…æ¡%†æ¢%‡æ£%ˆæ¤%‰æ¥%Šæ¦%‹æ§%Œæ¨%æ©%Žæª%æ«%æ¬%‘æ­%’æ®%“æ¯%”æ°%•æ±%–æ²%—æ³%˜æ´%™æµ%šæ¶%›æ·%œæ¸%æ¹%žæº%Ÿæ»% æ¼%¡0¡%¢0¢%£0£%¤0¤%¥0¥%¦0¦%§0§%¨0¨%©0©%ª0ª%«0«%¬0¬%­0­%®0®%¯0¯%°0°%±0±%²0²%³0³%´0´%µ0µ%¶0¶%·0·%¸0¸%¹0¹%º0º%»0»%¼0¼%½0½%¾0¾%¿0¿%À0À%Á0Á%Â0Â%Ã0Ã%Ä0Ä%Å0Å%Æ0Æ%Ç0Ç%È0È%É0É%Ê0Ê%Ë0Ë%Ì0Ì%Í0Í%Î0Î%Ï0Ï%Ð0Ð%Ñ0Ñ%Ò0Ò%Ó0Ó%Ô0Ô%Õ0Õ%Ö0Ö%×0×%Ø0Ø%Ù0Ù%Ú0Ú%Û0Û%Ü0Ü%Ý0Ý%Þ0Þ%ß0ß%à0à%á0á%â0â%ã0ã%ä0ä%å0å%æ0æ%ç0ç%è0è%é0é%ê0ê%ë0ë%ì0ì%í0í%î0î%ï0ï%ð0ð%ñ0ñ%ò0ò%ó0ó%ô0ô%õ0õ%ö0ö%÷æ½%øæ¾%ùæ¿%úæÀ%ûæÁ%üæÂ%ýæÃ%þæÄ&@æÅ&AæÆ&BæÇ&CæÈ&DæÉ&EæÊ&FæË&GæÌ&HæÍ&IæÎ&JæÏ&KæÐ&LæÑ&MæÒ&NæÓ&OæÔ&PæÕ&QæÖ&Ræ×&SæØ&TæÙ&UæÚ&VæÛ&WæÜ&XæÝ&YæÞ&Zæß&[æà&\æá&]æâ&^æã&_æä&`æå&aææ&bæç&cæè&dæé&eæê&fæë&gæì&hæí&iæî&jæï&kæð&læñ&mæò&næó&oæô&pæõ&qæö&ræ÷&sæø&tæù&uæú&væû&wæü&xæý&yæþ&zæÿ&{ç&|ç&}ç&~ç&€ç&ç&‚ç&ƒç&„ç&…ç &†ç &‡ç &ˆç &‰ç &Šç&‹ç&Œç&ç&Žç&ç&ç&‘ç&’ç&“ç&”ç&•ç&–ç&—ç&˜ç&™ç&šç&›ç&œç &ç!&žç"&Ÿç#& ç$&¡‘&¢’&£“&¤”&¥•&¦–&§—&¨˜&©™&ªš&«›&¬œ&­&®ž&¯Ÿ&° &±¡&²£&³¤&´¥&µ¦&¶§&·¨&¸©&¹ç%&ºç&&»ç'&¼ç(&½ç)&¾ç*&¿ç+&Àç,&Á±&²&ó&Ä´&ŵ&ƶ&Ç·&ȸ&ɹ&ʺ&Ë»&̼&ͽ&ξ&Ï¿&ÐÀ&ÑÁ&ÒÃ&ÓÄ&ÔÅ&ÕÆ&ÖÇ&×È&ØÉ&Ùç-&Úç.&Ûç/&Üç0&Ýç1&Þç2&ßç3&àþ5&áþ6&âþ9&ãþ:&äþ?&åþ@&æþ=&çþ>&èþA&éþB&êþC&ëþD&ìç4&íç5&îþ;&ïþ<&ðþ7&ñþ8&òþ1&óç6&ôþ3&õþ4&öç7&÷ç8&øç9&ùç:&úç;&ûç<&üç=&ýç>&þç?'@ç@'AçA'BçB'CçC'DçD'EçE'FçF'GçG'HçH'IçI'JçJ'KçK'LçL'MçM'NçN'OçO'PçP'QçQ'RçR'SçS'TçT'UçU'VçV'WçW'XçX'YçY'ZçZ'[ç['\ç\']ç]'^ç^'_ç_'`ç`'aça'bçb'cçc'dçd'eçe'fçf'gçg'hçh'içi'jçj'kçk'lçl'mçm'nçn'oço'pçp'qçq'rçr'sçs'tçt'uçu'vçv'wçw'xçx'yçy'zçz'{ç{'|ç|'}ç}'~ç~'€ç'ç€'‚ç'ƒç‚'„çƒ'…ç„'†ç…'‡ç†'ˆç‡'‰çˆ'Šç‰'‹çŠ'Œç‹'çŒ'Žç'çŽ'ç'‘ç'’ç‘'“ç’'”ç“'•ç”'–ç•'—ç–'˜ç—'™ç˜'šç™'›çš'œç›'çœ'žç'Ÿçž' çŸ'¡'¢'£'¤'¥'¦'§'¨'©'ª'«'¬'­'®'¯'°'±'² '³!'´"'µ#'¶$'·%'¸&'¹''º('»)'¼*'½+'¾,'¿-'À.'Á/'Âç 'Ãç¡'Äç¢'Åç£'Æç¤'Çç¥'Èç¦'Éç§'Êç¨'Ëç©'Ìçª'Íç«'Îç¬'Ïç­'Ðç®'Ñ0'Ò1'Ó2'Ô3'Õ4'Ö5'×Q'Ø6'Ù7'Ú8'Û9'Ü:'Ý;'Þ<'ß='à>'á?'â@'ãA'äB'åC'æD'çE'èF'éG'êH'ëI'ìJ'íK'îL'ïM'ðN'ñO'òç¯'óç°'ôç±'õç²'öç³'÷ç´'øçµ'ùç¶'úç·'ûç¸'üç¹'ýçº'þç»(@Ê(AË(BÙ(C (D (E %(F 5(G!(H! (I!–(J!—(K!˜(L!™(M"(N"(O"#(P"R(Q"f(R"g(S"¿(T%P(U%Q(V%R(W%S(X%T(Y%U(Z%V([%W(\%X(]%Y(^%Z(_%[(`%\(a%](b%^(c%_(d%`(e%a(f%b(g%c(h%d(i%e(j%f(k%g(l%h(m%i(n%j(o%k(p%l(q%m(r%n(s%o(t%p(u%q(v%r(w%s(x%(y%‚(z%ƒ({%„(|%…(}%†(~%‡(€%ˆ(%‰(‚%Š(ƒ%‹(„%Œ(…%(†%Ž(‡%(ˆ%“(‰%”(Š%•(‹%¼(Œ%½(%â(Ž%ã(%ä(%å(‘& (“0(”0(•0(–ç¼(—ç½(˜ç¾(™ç¿(šçÀ(›çÁ(œçÂ(çÃ(žçÄ(ŸçÅ( çÆ(¡(¢á(£Î(¤à(¥(¦é(§(¨è(©+(ªí(«Ð(¬ì(­M(®ó(¯Ò(°ò(±k(²ú(³Ô(´ù(µÖ(¶Ø(·Ú(¸Ü(¹ü(ºê(»Q(¼çÇ(½D(¾H(¿çÈ(Àa(ÁçÉ(ÂçÊ(ÃçË(ÄçÌ(Å1(Æ1(Ç1(È1(É1 (Ê1 (Ë1 (Ì1 (Í1 (Î1(Ï1(Ð1(Ñ1(Ò1(Ó1(Ô1(Õ1(Ö1(×1(Ø1(Ù1(Ú1(Û1(Ü1(Ý1(Þ1(ß1(à1 (á1!(â1"(ã1#(ä1$(å1%(æ1&(ç1'(è1((é1)(êçÍ(ëçÎ(ìçÏ(íçÐ(îçÑ(ïçÒ(ðçÓ(ñçÔ(òçÕ(óçÖ(ôç×(õçØ(öçÙ(÷çÚ(øçÛ(ùçÜ(úçÝ(ûçÞ(üçß(ýçà(þçá)@0!)A0")B0#)C0$)D0%)E0&)F0')G0()H0))I2£)J3Ž)K3)L3œ)M3)N3ž)O3¡)P3Ä)Q3Î)R3Ñ)S3Ò)T3Õ)Uþ0)Vÿâ)Wÿä)Xçâ)Y!!)Z21)[çã)\ )]çä)^çå)_çæ)`0ü)a0›)b0œ)c0ý)d0þ)e0)f0)g0ž)hþI)iþJ)jþK)kþL)lþM)mþN)nþO)oþP)pþQ)qþR)rþT)sþU)tþV)uþW)vþY)wþZ)xþ[)yþ\)zþ]){þ^)|þ_)}þ`)~þa)€þb)þc)‚þd)ƒþe)„þf)…þh)†þi)‡þj)ˆþk)‰çç)Šçè)‹çé)Œçê)çë)Žçì)çí)çî)‘çï)’çð)“çñ)”çò)•çó)–0)—çô)˜çõ)™çö)šç÷)›çø)œçù)çú)žçû)Ÿçü) çý)¡çþ)¢çÿ)£è)¤%)¥%)¦%)§%)¨%)©%)ª%)«%)¬%)­% )®% )¯% )°% )±% )²%)³%)´%)µ%)¶%)·%)¸%)¹%)º%)»%)¼%)½%)¾%)¿%)À%)Á%)Â%)Ã%)Ä% )Å%!)Æ%")Ç%#)È%$)É%%)Ê%&)Ë%')Ì%()Í%))Î%*)Ï%+)Ð%,)Ñ%-)Ò%.)Ó%/)Ô%0)Õ%1)Ö%2)×%3)Ø%4)Ù%5)Ú%6)Û%7)Ü%8)Ý%9)Þ%:)ß%;)à%<)á%=)â%>)ã%?)ä%@)å%A)æ%B)ç%C)è%D)é%E)ê%F)ë%G)ì%H)í%I)î%J)ï%K)ðè)ñè)òè)óè)ôè)õè)öè)÷è)øè )ùè )úè )ûè )üè )ýè)þè*@rÜ*ArÝ*Brß*Crâ*Drã*Erä*Frå*Græ*Hrç*Irê*Jrë*Krõ*Lrö*Mrù*Nrý*Orþ*Prÿ*Qs*Rs*Ss*Ts*Us*Vs*Ws*Xs *Ys *Zs *[s *\s*]s*^s*_s*`s*as*bs*cs*ds*es *fs#*gs$*hs&*is'*js(*ks-*ls/*ms0*ns2*os3*ps5*qs6*rs:*ss;*ts<*us=*vs@*wsA*xsB*ysC*zsD*{sE*|sF*}sG*~sH*€sI*sJ*‚sK*ƒsL*„sN*…sO*†sQ*‡sS*ˆsT*‰sU*ŠsV*‹sX*ŒsY*sZ*Žs[*s\*s]*‘s^*’s_*“sa*”sb*•sc*–sd*—se*˜sf*™sg*šsh*›si*œsj*sk*žsn*Ÿsp* sq*¡à*¢à*£à*¤à*¥à*¦à*§à*¨à*©à*ªà *«à *¬à *­à *®à *¯à*°à*±à*²à*³à*´à*µà*¶à*·à*¸à*¹à*ºà*»à*¼à*½à*¾à*¿à*Àà*Áà *Âà!*Ãà"*Äà#*Åà$*Æà%*Çà&*Èà'*Éà(*Êà)*Ëà**Ìà+*Íà,*Îà-*Ïà.*Ðà/*Ñà0*Òà1*Óà2*Ôà3*Õà4*Öà5*×à6*Øà7*Ùà8*Úà9*Ûà:*Üà;*Ýà<*Þà=*ßà>*àà?*áà@*âàA*ãàB*äàC*åàD*æàE*çàF*èàG*éàH*êàI*ëàJ*ìàK*íàL*îàM*ïàN*ðàO*ñàP*òàQ*óàR*ôàS*õàT*öàU*÷àV*øàW*ùàX*úàY*ûàZ*üà[*ýà\*þà]+@sr+Ass+Bst+Csu+Dsv+Esw+Fsx+Gsy+Hsz+Is{+Js|+Ks}+Ls+Ms€+Ns+Os‚+Psƒ+Qs…+Rs†+Ssˆ+TsŠ+UsŒ+Vs+Ws+Xs+Ys’+Zs“+[s”+\s•+]s—+^s˜+_s™+`sš+asœ+bs+csž+ds +es¡+fs£+gs¤+hs¥+is¦+js§+ks¨+lsª+ms¬+ns­+os±+ps´+qsµ+rs¶+ss¸+ts¹+us¼+vs½+ws¾+xs¿+ysÁ+zsÃ+{sÄ+|sÅ+}sÆ+~sÇ+€sË+sÌ+‚sÎ+ƒsÒ+„sÓ+…sÔ+†sÕ+‡sÖ+ˆs×+‰sØ+ŠsÚ+‹sÛ+ŒsÜ+sÝ+Žsß+sá+sâ+‘sã+’sä+“sæ+”sè+•sê+–së+—sì+˜sî+™sï+šsð+›sñ+œsó+sô+žsõ+Ÿsö+ s÷+¡à^+¢à_+£à`+¤àa+¥àb+¦àc+§àd+¨àe+©àf+ªàg+«àh+¬ài+­àj+®àk+¯àl+°àm+±àn+²ào+³àp+´àq+µàr+¶às+·àt+¸àu+¹àv+ºàw+»àx+¼ày+½àz+¾à{+¿à|+Àà}+Áà~+Âà+Ãà€+Äà+Åà‚+Æàƒ+Çà„+Èà…+Éà†+Êà‡+Ëàˆ+Ìà‰+ÍàŠ+Îà‹+ÏàŒ+Ðà+ÑàŽ+Òà+Óà+Ôà‘+Õà’+Öà“+×à”+Øà•+Ùà–+Úà—+Ûà˜+Üà™+Ýàš+Þà›+ßàœ+àà+áàž+âàŸ+ãà +äà¡+åà¢+æà£+çà¤+èà¥+éà¦+êà§+ëà¨+ìà©+íàª+îà«+ïà¬+ðà­+ñà®+òà¯+óà°+ôà±+õà²+öà³+÷à´+øàµ+ùà¶+úà·+ûà¸+üà¹+ýàº+þà»,@sø,Asù,Bsú,Csû,Dsü,Esý,Fsþ,Gsÿ,Ht,It,Jt,Kt,Lt,Mt,Nt ,Ot ,Pt ,Qt,Rt,St,Tt,Ut,Vt,Wt,Xt,Yt,Zt,[t,\t,]t,^t,_t ,`t!,at#,bt$,ct',dt),et+,ft-,gt/,ht1,it2,jt7,kt8,lt9,mt:,nt;,ot=,pt>,qt?,rt@,stB,ttC,utD,vtE,wtF,xtG,ytH,ztI,{tJ,|tK,}tL,~tM,€tN,tO,‚tP,ƒtQ,„tR,…tS,†tT,‡tV,ˆtX,‰t],Št`,‹ta,Œtb,tc,Žtd,te,tf,‘tg,’th,“ti,”tj,•tk,–tl,—tn,˜to,™tq,štr,›ts,œtt,tu,žtx,Ÿty, tz,¡à¼,¢à½,£à¾,¤à¿,¥àÀ,¦àÁ,§àÂ,¨àÃ,©àÄ,ªàÅ,«àÆ,¬àÇ,­àÈ,®àÉ,¯àÊ,°àË,±àÌ,²àÍ,³àÎ,´àÏ,µàÐ,¶àÑ,·àÒ,¸àÓ,¹àÔ,ºàÕ,»àÖ,¼à×,½àØ,¾àÙ,¿àÚ,ÀàÛ,ÁàÜ,ÂàÝ,ÃàÞ,Äàß,Åàà,Æàá,Çàâ,Èàã,Éàä,Êàå,Ëàæ,Ìàç,Íàè,Îàé,Ïàê,Ðàë,Ñàì,Òàí,Óàî,Ôàï,Õàð,Öàñ,×àò,Øàó,Ùàô,Úàõ,Ûàö,Üà÷,Ýàø,Þàù,ßàú,ààû,áàü,âàý,ãàþ,äàÿ,åá,æá,çá,èá,éá,êá,ëá,ìá,íá,îá ,ïá ,ðá ,ñá ,òá ,óá,ôá,õá,öá,÷á,øá,ùá,úá,ûá,üá,ýá,þá-@t{-At|-Bt}-Ct-Dt‚-Et„-Ft…-Gt†-Htˆ-It‰-JtŠ-KtŒ-Lt-Mt-Nt‘-Ot’-Pt“-Qt”-Rt•-St–-Tt—-Ut˜-Vt™-Wtš-Xt›-Yt-ZtŸ-[t -\t¡-]t¢-^t£-_t¤-`t¥-at¦-btª-ct«-dt¬-et­-ft®-gt¯-ht°-it±-jt²-kt³-lt´-mtµ-nt¶-ot·-pt¸-qt¹-rt»-st¼-tt½-ut¾-vt¿-wtÀ-xtÁ-ytÂ-ztÃ-{tÄ-|tÅ-}tÆ-~tÇ-€tÈ-tÉ-‚tÊ-ƒtË-„tÌ-…tÍ-†tÎ-‡tÏ-ˆtÐ-‰tÑ-ŠtÓ-‹tÔ-ŒtÕ-tÖ-Žt×-tØ-tÙ-‘tÚ-’tÛ-“tÝ-”tß-•tá-–tå-—tç-˜tè-™té-štê-›të-œtì-tí-žtð-Ÿtñ- tò-¡á-¢á-£á-¤á-¥á-¦á-§á -¨á!-©á"-ªá#-«á$-¬á%-­á&-®á'-¯á(-°á)-±á*-²á+-³á,-´á--µá.-¶á/-·á0-¸á1-¹á2-ºá3-»á4-¼á5-½á6-¾á7-¿á8-Àá9-Áá:-Âá;-Ãá<-Äá=-Åá>-Æá?-Çá@-ÈáA-ÉáB-ÊáC-ËáD-ÌáE-ÍáF-ÎáG-ÏáH-ÐáI-ÑáJ-ÒáK-ÓáL-ÔáM-ÕáN-ÖáO-×áP-ØáQ-ÙáR-ÚáS-ÛáT-ÜáU-ÝáV-ÞáW-ßáX-àáY-ááZ-âá[-ãá\-äá]-åá^-æá_-çá`-èáa-éáb-êác-ëád-ìáe-íáf-îág-ïáh-ðái-ñáj-òák-óál-ôám-õán-öáo-÷áp-øáq-ùár-úás-ûát-üáu-ýáv-þáw.@tó.Atõ.Btø.Ctù.Dtú.Etû.Ftü.Gtý.Htþ.Iu.Ju.Ku.Lu.Mu.Nu.Ou.Pu.Qu .Ru .Su .Tu .Uu.Vu.Wu.Xu.Yu.Zu.[u.\u.]u.^u._u .`u!.au".bu#.cu$.du&.eu'.fu*.gu..hu4.iu6.ju9.ku<.lu=.mu?.nuA.ouB.puC.quD.ruF.suG.tuI.uuJ.vuM.wuP.xuQ.yuR.zuS.{uU.|uV.}uW.~uX.€u].u^.‚u_.ƒu`.„ua.…ub.†uc.‡ud.ˆug.‰uh.Šui.‹uk.Œul.um.Žun.uo.up.‘uq.’us.“uu.”uv.•uw.–uz.—u{.˜u|.™u}.šu~.›u€.œu.u‚.žu„.Ÿu…. u‡.¡áx.¢áy.£áz.¤á{.¥á|.¦á}.§á~.¨á.©á€.ªá.«á‚.¬áƒ.­á„.®á….¯á†.°á‡.±áˆ.²á‰.³áŠ.´á‹.µáŒ.¶á.·áŽ.¸á.¹á.ºá‘.»á’.¼á“.½á”.¾á•.¿á–.Àá—.Áá˜.Âá™.Ãáš.Äá›.Åáœ.Æá.Çáž.ÈáŸ.Éá .Êá¡.Ëá¢.Ìá£.Íá¤.Îá¥.Ïá¦.Ðá§.Ñá¨.Òá©.Óáª.Ôá«.Õá¬.Öá­.×á®.Øá¯.Ùá°.Úá±.Ûá².Üá³.Ýá´.Þáµ.ßá¶.àá·.áá¸.âá¹.ãáº.äá».åá¼.æá½.çá¾.èá¿.éáÀ.êáÁ.ëáÂ.ìáÃ.íáÄ.îáÅ.ïáÆ.ðáÇ.ñáÈ.òáÉ.óáÊ.ôáË.õáÌ.öáÍ.÷áÎ.øáÏ.ùáÐ.úáÑ.ûáÒ.üáÓ.ýáÔ.þáÕ/@uˆ/Au‰/BuŠ/CuŒ/Du/EuŽ/Fu/Gu“/Hu•/Iu˜/Ju›/Kuœ/Luž/Mu¢/Nu¦/Ou§/Pu¨/Qu©/Ruª/Su­/Tu¶/Uu·/Vuº/Wu»/Xu¿/YuÀ/ZuÁ/[uÆ/\uË/]uÌ/^uÎ/_uÏ/`uÐ/auÑ/buÓ/cu×/duÙ/euÚ/fuÜ/guÝ/huß/iuà/juá/kuå/lué/muì/nuí/ouî/puï/quò/ruó/suõ/tuö/uu÷/vuø/wuú/xuû/yuý/zuþ/{v/|v/}v/~v/€v/v /‚v /ƒv /„v/…v/†v/‡v/ˆv/‰v/Šv/‹v/Œv/v/Žv/v!/v#/‘v'/’v(/“v,/”v./•v//–v1/—v2/˜v6/™v7/šv9/›v:/œv;/v=/žvA/ŸvB/ vD/¡áÖ/¢á×/£áØ/¤áÙ/¥áÚ/¦áÛ/§áÜ/¨áÝ/©áÞ/ªáß/«áà/¬áá/­áâ/®áã/¯áä/°áå/±áæ/²áç/³áè/´áé/µáê/¶áë/·áì/¸áí/¹áî/ºáï/»áð/¼áñ/½áò/¾áó/¿áô/Àáõ/Ááö/Âá÷/Ãáø/Äáù/Åáú/Æáû/Çáü/Èáý/Éáþ/Êáÿ/Ëâ/Ìâ/Íâ/Îâ/Ïâ/Ðâ/Ñâ/Òâ/Óâ/Ôâ /Õâ /Öâ /×â /Øâ /Ùâ/Úâ/Ûâ/Üâ/Ýâ/Þâ/ßâ/àâ/áâ/ââ/ãâ/äâ/åâ/æâ/çâ/èâ/éâ/êâ/ëâ /ìâ!/íâ"/îâ#/ïâ$/ðâ%/ñâ&/òâ'/óâ(/ôâ)/õâ*/öâ+/÷â,/øâ-/ùâ./úâ//ûâ0/üâ1/ýâ2/þâ30@vE0AvF0BvG0CvH0DvI0EvJ0FvK0GvN0HvO0IvP0JvQ0KvR0LvS0MvU0NvW0OvX0PvY0QvZ0Rv[0Sv]0Tv_0Uv`0Vva0Wvb0Xvd0Yve0Zvf0[vg0\vh0]vi0^vj0_vl0`vm0avn0bvp0cvq0dvr0evs0fvt0gvu0hvv0ivw0jvy0kvz0lv|0mv0nv€0ov0pvƒ0qv…0rv‰0svŠ0tvŒ0uv0vv0wv0xv’0yv”0zv•0{v—0|v˜0}vš0~v›0€vœ0v0‚vž0ƒvŸ0„v 0…v¡0†v¢0‡v£0ˆv¥0‰v¦0Šv§0‹v¨0Œv©0vª0Žv«0v¬0v­0‘v¯0’v°0“v³0”vµ0•v¶0–v·0—v¸0˜v¹0™vº0šv»0›v¼0œv½0v¾0žvÀ0ŸvÁ0 vÃ0¡UJ0¢–?0£WÃ0¤c(0¥TÎ0¦U 0§TÀ0¨v‘0©vL0ª…<0«wî0¬‚~0­x0®r10¯–˜0°—0±l(0²[‰0³Oú0´c 0µf—0¶\¸0·€ú0¸hH0¹€®0ºf0»vÎ0¼Qù0½eV0¾q¬0¿ñ0Àˆ„0ÁP²0ÂYe0ÃaÊ0Äo³0Å‚­0ÆcL0ÇbR0ÈSí0ÉT'0Ê{0ËQk0Ìu¤0Í]ô0ÎbÔ0ÏË0Зv0ÑbŠ0Ò€0ÓW]0Ô—80Õb0Ör80×v}0ØgÏ0Ùv~0ÚdF0ÛOp0Ü%0ÝbÜ0Þz0ße‘0àsí0ád,0âbs0ã‚,0ä˜0åg0ærH0çbn0èbÌ0éO40êtã0ëSJ0ìRž0í~Ê0î¦0ï^.0ðh†0ñiœ0ò€0ó~Ñ0ôhÒ0õxÅ0ö†Œ0÷•Q0øP0ùŒ$0ú‚Þ0û€Þ0üS0ý‰0þRe1@vÄ1AvÇ1BvÉ1CvË1DvÌ1EvÓ1FvÕ1GvÙ1HvÚ1IvÜ1JvÝ1KvÞ1Lvà1Mvá1Nvâ1Ovã1Pvä1Qvæ1Rvç1Svè1Tvé1Uvê1Vvë1Wvì1Xví1Yvð1Zvó1[võ1\vö1]v÷1^vú1_vû1`vý1avÿ1bw1cw1dw1ew1fw1gw 1hw 1iw1jw1kw1lw1mw1nw1ow1pw1qw1rw1sw1tw1uw1vw1ww1xw!1yw#1zw$1{w%1|w'1}w*1~w+1€w,1w.1‚w01ƒw11„w21…w31†w41‡w91ˆw;1‰w=1Šw>1‹w?1ŒwB1wD1ŽwE1wF1wH1‘wI1’wJ1“wK1”wL1•wM1–wN1—wO1˜wR1™wS1šwT1›wU1œwV1wW1žwX1ŸwY1 w\1¡…„1¢–ù1£OÝ1¤X!1¥™q1¦[1§b±1¨b¥1©f´1ªŒy1«œ1¬r1­go1®x‘1¯`²1°SQ1±S1²ˆ1³€Ì1´1µ”¡1¶P 1·rÈ1¸Y1¹`ë1ºq1»ˆ«1¼YT1½‚ï1¾g,1¿{(1À])1Á~÷1Âu-1Ãlõ1ÄŽf1Åø1Æ<1ÇŸ;1ÈkÔ1É‘1Ê{1Ë_|1Ìx§1Í„Ö1Î…=1ÏkÕ1ÐkÙ1ÑkÖ1Ò^1Ó^‡1Ôuù1Õ•í1Öe]1×_ 1Ø_Å1ÙŸ1ÚXÁ1ÛÂ1Ü1Ý–[1Þ—­1ß¹1à1á,1âbA1ãO¿1äSØ1åS^1æ¨1ç©1è«1éM1êh1ë_j1ì˜1íˆh1îœÖ1ïa‹1ðR+1ñv*1ò_l1óeŒ1ôoÒ1õnè1ö[¾1÷dH1øQu1ùQ°1úgÄ1ûN1üyÉ1ý™|1þp³2@w]2Aw^2Bw_2Cw`2Dwd2Ewg2Fwi2Gwj2Hwm2Iwn2Jwo2Kwp2Lwq2Mwr2Nws2Owt2Pwu2Qwv2Rww2Swx2Twz2Uw{2Vw|2Ww2Xw‚2Ywƒ2Zw†2[w‡2\wˆ2]w‰2^wŠ2_w‹2`w2aw2bw“2cw”2dw•2ew–2fw—2gw˜2hw™2iwš2jw›2kwœ2lw2mwž2nw¡2ow£2pw¤2qw¦2rw¨2sw«2tw­2uw®2vw¯2ww±2xw²2yw´2zw¶2{w·2|w¸2}w¹2~wº2€w¼2w¾2‚wÀ2ƒwÁ2„wÂ2…wÃ2†wÄ2‡wÅ2ˆwÆ2‰wÇ2ŠwÈ2‹wÉ2ŒwÊ2wË2ŽwÌ2wÎ2wÏ2‘wÐ2’wÑ2“wÒ2”wÓ2•wÔ2–wÕ2—wÖ2˜wØ2™wÙ2šwÚ2›wÝ2œwÞ2wß2žwà2Ÿwá2 wä2¡uÅ2¢^v2£s»2¤ƒà2¥d­2¦bè2§”µ2¨lâ2©SZ2ªRÃ2«d2¬”Â2­{”2®O/2¯^2°‚62±2²Š2³n$2´lÊ2µšs2¶cU2·S\2¸Tú2¹ˆe2ºWà2»N 2¼^2½ke2¾|?2¿è2À`2Ádæ2Âs2ÈÁ2ÄgP2ÅbM2Æ"2Çwl2ÈŽ)2É‘Ç2Ê_i2˃Ü2Ì…!2Í™2ÎSÂ2φ•2Ðk‹2Ñ`í2Ò`è2Óp2Ô‚Í2Õ‚12ÖNÓ2×l§2Ø…Ï2ÙdÍ2Ú|Ù2Ûiý2Üfù2݃I2ÞS•2ß{V2àO§2áQŒ2âmK2ã\B2äŽm2åcÒ2æSÉ2çƒ,2èƒ62égå2êx´2ëd=2ì[ß2í\”2î]î2ï‹ç2ðbÆ2ñgô2òŒz2ód2ôcº2õ‡I2ö™‹2÷Œ2ø 2ù”ò2úN§2û–2ü˜¤2ýf 2þs3@wæ3Awè3Bwê3Cwï3Dwð3Ewñ3Fwò3Gwô3Hwõ3Iw÷3Jwù3Kwú3Lwû3Mwü3Nx3Ox3Px3Qx3Rx3Sx3Tx 3Ux 3Vx3Wx3Xx3Yx3Zx3[x3\x3]x3^x 3_x!3`x"3ax$3bx(3cx*3dx+3ex.3fx/3gx13hx23ix33jx53kx63lx=3mx?3nxA3oxB3pxC3qxD3rxF3sxH3txI3uxJ3vxK3wxM3xxO3yxQ3zxS3{xT3|xX3}xY3~xZ3€x[3x\3‚x^3ƒx_3„x`3…xa3†xb3‡xc3ˆxd3‰xe3Šxf3‹xg3Œxh3xi3Žxo3xp3xq3‘xr3’xs3“xt3”xu3•xv3–xx3—xy3˜xz3™x{3šx}3›x~3œx3x€3žx3Ÿx‚3 xƒ3¡W:3¢\3£^83¤•3¥P3¦€ 3§S‚3¨e^3©uE3ªU13«P!3¬…3­b„3®”ž3¯g3°V23±on3²]â3³T53´p’3µf3¶bo3·d¤3¸c£3¹_{3ºoˆ3»ô3¼ã3½°3¾\3¿fh3À_ñ3Ál‰3–H3Ã3Ĉl3Åd‘3Æyð3ÇWÎ3ÈjY3Éb3ÊTH3ËNX3Ìz 3Í`é3Îo„3Ï‹Ú3Ðb3Ñ3Òš‹3Óyä3ÔT3Õuô3Öc3×S3Øl`3Ùß3Ú_3Ûšp3Ü€;3ÝŸ3ÞOˆ3ß\:3àd3áÅ3âe¥3ãp½3äQE3åQ²3æ†k3ç]3è[ 3éb½3ê‘l3ëut3ìŽ 3íz 3îa3ï{y3ðNÇ3ñ~ø3òw…3óN3ôí3õR3öQú3÷jq3øS¨3ùއ3ú•3û–Ï3ünÁ3ý–d3þiZ4@x„4Ax…4Bx†4Cxˆ4DxŠ4Ex‹4Fx4Gx4Hx’4Ix”4Jx•4Kx–4Lx™4Mx4Nxž4Ox 4Px¢4Qx¤4Rx¦4Sx¨4Tx©4Uxª4Vx«4Wx¬4Xx­4Yx®4Zx¯4[xµ4\x¶4]x·4^x¸4_xº4`x»4ax¼4bx½4cx¿4dxÀ4exÂ4fxÃ4gxÄ4hxÆ4ixÇ4jxÈ4kxÌ4lxÍ4mxÎ4nxÏ4oxÑ4pxÒ4qxÓ4rxÖ4sx×4txØ4uxÚ4vxÛ4wxÜ4xxÝ4yxÞ4zxß4{xà4|xá4}xâ4~xã4€xä4xå4‚xæ4ƒxç4„xé4…xê4†xë4‡xí4ˆxî4‰xï4Šxð4‹xñ4Œxó4xõ4Žxö4xø4xù4‘xû4’xü4“xý4”xþ4•xÿ4–y4—y4˜y4™y4šy4›y4œy4y 4žy 4Ÿy 4 y 4¡x@4¢P¨4£w×4¤d4¥‰æ4¦Y4§cã4¨]Ý4©z4ªi=4«O 4¬‚94­U˜4®N24¯u®4°z—4±^b4²^Š4³•ï4´R4µT94¶pŠ4·cv4¸•$4¹W‚4ºf%4»i?4¼‘‡4½U4¾mó4¿~¯4Àˆ"4Áb34Â~ð4Ãuµ4ă(4ÅxÁ4Æ–Ì4Çž4ÈaH4Ét÷4Ê‹Í4Ëkd4ÌR:4ÍP4Îk!4Ï€j4Єq4ÑVñ4ÒS4ÓNÎ4ÔN4ÕQÑ4Ö|—4ב‹4Ø|4ÙOÃ4ÚŽ4Û{á4Üzœ4Ýdg4Þ]4ßP¬4à4áv4â|¹4ãmì4äà4ågQ4æ[X4ç[ø4èxË4éd®4êd4ëcª4ìc+4í•4îd-4ï¾4ð{T4ñv)4òbS4óY'4ôTF4õky4öP£4÷b44ø^&4ùk†4úNã4û74üˆ‹4ý_…4þ.5@y 5Ay5By5Cy5Dy5Ey5Fy5Gy5Hy5Iy5Jy5Ky5Ly5My5Ny5Oy5Py5Qy 5Ry!5Sy"5Ty#5Uy%5Vy&5Wy'5Xy(5Yy)5Zy*5[y+5\y,5]y-5^y.5_y/5`y05ay15by25cy35dy55ey65fy75gy85hy95iy=5jy?5kyB5lyC5myD5nyE5oyG5pyJ5qyK5ryL5syM5tyN5uyO5vyP5wyQ5xyR5yyT5zyU5{yX5|yY5}ya5~yc5€yd5yf5‚yi5ƒyj5„yk5…yl5†yn5‡yp5ˆyq5‰yr5Šys5‹yt5Œyu5yv5Žyy5y{5y|5‘y}5’y~5“y5”y‚5•yƒ5–y†5—y‡5˜yˆ5™y‰5šy‹5›yŒ5œy5yŽ5žy5Ÿy‘5 y’5¡` 5¢€=5£bÅ5¤N95¥SU5¦ø5§c¸5¨€Æ5©eæ5ªl.5«OF5¬`î5­má5®‹Þ5¯_95°†Ë5±_S5²c!5³QZ5´ƒa5µhc5¶R5·cc5¸ŽH5¹P5º\›5»yw5¼[ü5½R05¾z;5¿`¼5ÀS5Áv×5Â_·5Ã_—5Äv„5ÅŽl5Æpo5Çv{5È{I5Éwª5ÊQó5Ë“5ÌX$5ÍON5Înô5Ïê5ÐeL5Ñ{5ÒrÄ5Óm¤5Ôß5ÕZá5Öbµ5×^•5ØW05Ù„‚5Ú{,5Û^5Ü_5Ý5Þ5ߘ 5àc‚5ánÇ5âx˜5ãp¹5äQx5å—[5æW«5çu55èOC5éu85ê^—5ë`æ5ìY`5ímÀ5îk¿5ïx‰5ðSü5ñ–Õ5òQË5óR5ôc‰5õT 5ö”“5÷Œ5øÌ5ùr95úxŸ5û‡v5üí5ýŒ 5þSà6@y“6Ay”6By•6Cy–6Dy—6Ey˜6Fy™6Gy›6Hyœ6Iy6Jyž6KyŸ6Ly 6My¡6Ny¢6Oy£6Py¤6Qy¥6Ry¦6Sy¨6Ty©6Uyª6Vy«6Wy¬6Xy­6Yy®6Zy¯6[y°6\y±6]y²6^y´6_yµ6`y¶6ay·6by¸6cy¼6dy¿6eyÂ6fyÄ6gyÅ6hyÇ6iyÈ6jyÊ6kyÌ6lyÎ6myÏ6nyÐ6oyÓ6pyÔ6qyÖ6ry×6syÙ6tyÚ6uyÛ6vyÜ6wyÝ6xyÞ6yyà6zyá6{yâ6|yå6}yè6~yê6€yì6yî6‚yñ6ƒyò6„yó6…yô6†yõ6‡yö6ˆy÷6‰yù6Šyú6‹yü6Œyþ6yÿ6Žz6z6z6‘z6’z6“z 6”z 6•z 6–z6—z6˜z6™z6šz6›z6œz6z6žz6Ÿz6 z6¡N6¢vï6£Sî6¤”‰6¥˜v6¦Ÿ6§•-6¨[š6©‹¢6ªN"6«N6¬Q¬6­„c6®aÂ6¯R¨6°h 6±O—6²`k6³Q»6´m6µQ\6¶b–6·e—6¸–a6¹ŒF6º6»uØ6¼ý6½wc6¾kÒ6¿rŠ6Àrì6Á‹û6ÂX56Ãwy6ÄL6Åg\6Æ•@6Ç€š6È^¦6Én!6ÊY’6Ëzï6Ìwí6Í•;6Îkµ6Ïe­6Ð6ÑX6ÒQQ6Ó–6Ô[ù6ÕX©6ÖT(6׎r6Øef6Ù˜6ÚVä6Û”6Üvþ6ÝA6Þc‡6ßTÆ6àY6áY:6âW›6㎲6äg56åú6æ‚56çRA6è`ð6éX6ê†þ6ë\è6ìžE6íOÄ6î˜66ðZ%6ñ`v6òS„6ób|6ôO6õ‘6ö™6÷`i6ø€ 6ùQ?6ú€36û\6ü™u6ým16þNŒ7@z7Az7Bz!7Cz"7Dz$7Ez%7Fz&7Gz'7Hz(7Iz)7Jz*7Kz+7Lz,7Mz-7Nz.7Oz/7Pz07Qz17Rz27Sz47Tz57Uz67Vz87Wz:7Xz>7Yz@7ZzA7[zB7\zC7]zD7^zE7_zG7`zH7azI7bzJ7czK7dzL7ezM7fzN7gzO7hzP7izR7jzS7kzT7lzU7mzV7nzX7ozY7pzZ7qz[7rz\7sz]7tz^7uz_7vz`7wza7xzb7yzc7zzd7{ze7|zf7}zg7~zh7€zi7zj7‚zk7ƒzl7„zm7…zn7†zo7‡zq7ˆzr7‰zs7Šzu7‹z{7Œz|7z}7Žz~7z‚7z…7‘z‡7’z‰7“zŠ7”z‹7•zŒ7–zŽ7—z7˜z7™z“7šz”7›z™7œzš7z›7žzž7Ÿz¡7 z¢7¡07¢SÑ7£Z7¤{O7¥O7¦NO7§–7¨lÕ7©sÐ7ª…é7«^7¬uj7­û7®j 7¯wþ7°”’7±~A7²Qá7³pæ7´SÍ7µÔ7¶ƒ7·)7¸r¯7¹™m7ºlÛ7»WJ7¼‚³7½e¹7¾€ª7¿b?7À–27ÁY¨7ÂNÿ7Ë¿7Ä~º7Åe>7ƃò7Ç—^7ÈUa7ɘÞ7Ê€¥7ËS*7Ì‹ý7ÍT 7΀º7Ï^Ÿ7Ðl¸7Ñ97Ò‚¬7Ó‘Z7ÔT)7Õl7ÖR7×~·7ØW_7Ùq7Úl~7Û|‰7ÜYK7ÝNý7Þ_ÿ7ßa$7à|ª7áN07â\7ãg«7ä‡7å\ð7æ• 7ç˜Î7èu¯7épý7ê"7ëQ¯7ì7틽7îYI7ïQä7ðO[7ñT&7òY+7óew7ô€¤7õ[u7öbv7÷bÂ7ø7ù^E7úl7û{&7üO7ýOØ7þg 8@z£8Az¤8Bz§8Cz©8Dzª8Ez«8Fz®8Gz¯8Hz°8Iz±8Jz²8Kz´8Lzµ8Mz¶8Nz·8Oz¸8Pz¹8Qzº8Rz»8Sz¼8Tz½8Uz¾8VzÀ8WzÁ8XzÂ8YzÃ8ZzÄ8[zÅ8\zÆ8]zÇ8^zÈ8_zÉ8`zÊ8azÌ8bzÍ8czÎ8dzÏ8ezÐ8fzÑ8gzÒ8hzÓ8izÔ8jzÕ8kz×8lzØ8mzÚ8nzÛ8ozÜ8pzÝ8qzá8rzâ8szä8tzç8uzè8vzé8wzê8xzë8yzì8zzî8{zð8|zñ8}zò8~zó8€zô8zõ8‚zö8ƒz÷8„zø8…zû8†zü8‡zþ8ˆ{8‰{8Š{8‹{8Œ{8{ 8Ž{ 8{ 8{8‘{8’{8“{8”{8•{8–{8—{8˜{8™{8š{8›{!8œ{"8{#8ž{'8Ÿ{)8 {-8¡mn8¢mª8£y8¤ˆ±8¥_8¦u+8§bš8¨…8©Oï8ª‘Ü8«e§8¬/8­Q8®^œ8¯P8°t8±Ro8²‰†8³K8´Y 8µP…8¶NØ8·–8¸r68¹y8º8»[Ì8¼‹£8½–D8¾Y‡8¿8ÀT8ÁVv8ÂV8Ëå8Äe98Åi‚8Æ”™8ÇvÖ8Èn‰8É^r8Êu8ËgF8ÌgÑ8Ízÿ8΀8Ïv8Ða8ÑyÆ8Òeb8Óc8ÔQˆ8ÕR8Ö”¢8×88Ø€›8Ù~²8Ú\—8Ûn/8Üg`8Ý{Ù8Þv‹8ßšØ8à8á”8â|Õ8ãd8ä•P8åz?8æTJ8çTå8èkL8éd8êb8ëž=8ì€ó8íu™8îRr8ï—i8ð„[8ñh<8ò†ä8ó–8ô–”8õ”ì8öN*8÷T8ø~Ù8ùh98úß8û€8üfô8ý^š8þ¹9@{/9A{09B{29C{49D{59E{69F{79G{99H{;9I{=9J{?9K{@9L{A9M{B9N{C9O{D9P{F9Q{H9R{J9S{M9T{N9U{S9V{U9W{W9X{Y9Y{\9Z{^9[{_9\{a9]{c9^{d9_{e9`{f9a{g9b{h9c{i9d{j9e{k9f{l9g{m9h{o9i{p9j{s9k{t9l{v9m{x9n{z9o{|9p{}9q{9r{9s{‚9t{ƒ9u{„9v{†9w{‡9x{ˆ9y{‰9z{Š9{{‹9|{Œ9}{Ž9~{9€{‘9{’9‚{“9ƒ{–9„{˜9…{™9†{š9‡{›9ˆ{ž9‰{Ÿ9Š{ 9‹{£9Œ{¤9{¥9Ž{®9{¯9{°9‘{²9’{³9“{µ9”{¶9•{·9–{¹9—{º9˜{»9™{¼9š{½9›{¾9œ{¿9{À9ž{Â9Ÿ{Ã9 {Ä9¡WÂ9¢€?9£h—9¤]å9¥e;9¦RŸ9§`m9¨Ÿš9©O›9ªŽ¬9«Ql9¬[«9­_9®]é9¯l^9°bñ9±!9²Qq9³”©9´Rþ9µlŸ9¶‚ß9·r×9¸W¢9¹g„9º-9»Y9¼œ9½ƒÇ9¾T•9¿{9ÀO09Ál½9Â[d9ÃYÑ9ÄŸ9ÅSä9ƆÊ9Çš¨9ÈŒ79É€¡9ÊeE9˘~9ÌVú9Í–Ç9ÎR.9ÏtÜ9ÐRP9Ñ[á9Òc9Ó‰9ÔNV9ÕbÐ9Ö`*9×hú9ØQs9Ù[˜9ÚQ 9Û‰Â9Ü{¡9Ý™†9ÞP9ß`ï9àpL9á/9âQI9ã^9ä9åtp9æ‰Ä9çW-9èxE9é_R9꟟9ë•ú9ìh9í›<9î‹á9ïvx9ðhB9ñgÜ9òê9ó59ôR=9õŠ9önÚ9÷hÍ9ø•9ùí9úVý9ûgœ9üˆù9ýÇ9þTÈ:@{Å:A{È:B{É:C{Ê:D{Ë:E{Í:F{Î:G{Ï:H{Ð:I{Ò:J{Ô:K{Õ:L{Ö:M{×:N{Ø:O{Û:P{Ü:Q{Þ:R{ß:S{à:T{â:U{ã:V{ä:W{ç:X{è:Y{é:Z{ë:[{ì:\{í:]{ï:^{ð:_{ò:`{ó:a{ô:b{õ:c{ö:d{ø:e{ù:f{ú:g{û:h{ý:i{ÿ:j|:k|:l|:m|:n|:o|:p|:q|:r| :s| :t| :u|:v|:w|:x|:y|:z|:{|:||:}|:~|:€|:|:‚|:ƒ|:„|:…| :†|!:‡|":ˆ|#:‰|$:Š|%:‹|(:Œ|):|+:Ž|,:|-:|.:‘|/:’|0:“|1:”|2:•|3:–|4:—|5:˜|6:™|7:š|9:›|::œ|;:|<:ž|=:Ÿ|>: |B:¡š¸:¢[i:£mw:¤l&:¥N¥:¦[³:§š‡:¨‘c:©a¨:ª¯:«—é:¬T+:­mµ:®[Ò:¯Qý:°UŠ:±U:²ð:³d¼:´cM:µeñ:¶a¾:·`:¸q :¹lW:ºlI:»Y/:¼gm:½‚*:¾XÕ:¿VŽ:ÀŒj:Ákë:ÂÝ:ÃY}:Ä€:ÅS÷:Æmi:ÇTu:ÈU:Ƀw:ʃÏ:Ëh8:Ìy¾:ÍTŒ:ÎOU:ÏT:ÐvÒ:ÑŒ‰:Ò–:Ól³:Ôm¸:Õk:Ö‰:מd:Ø::ÙV?:ÚžÑ:ÛuÕ:Ü_ˆ:Ýrà:Þ`h:ßTü:àN¨:áj*:âˆa:ã`R:äp:åTÄ:æpØ:ç†y:èž?:ém*:ê[:ë_:ì~¢:íU‰:îO¯:ïs4:ðT<:ñSš:òP:óT:ôT|:õNN:ö_ý:÷tZ:øXö:ù„k:ú€á:û‡t:ürÐ:ý|Ê:þnV;@|C;A|D;B|E;C|F;D|G;E|H;F|I;G|J;H|K;I|L;J|N;K|O;L|P;M|Q;N|R;O|S;P|T;Q|U;R|V;S|W;T|X;U|Y;V|Z;W|[;X|\;Y|];Z|^;[|_;\|`;]|a;^|b;_|c;`|d;a|e;b|f;c|g;d|h;e|i;f|j;g|k;h|l;i|m;j|n;k|o;l|p;m|q;n|r;o|u;p|v;q|w;r|x;s|y;t|z;u|~;v|;w|€;x|;y|‚;z|ƒ;{|„;||…;}|†;~|‡;€|ˆ;|Š;‚|‹;ƒ|Œ;„|;…|Ž;†|;‡|;ˆ|“;‰|”;Š|–;‹|™;Œ|š;|›;Ž| ;|¡;|£;‘|¦;’|§;“|¨;”|©;•|«;–|¬;—|­;˜|¯;™|°;š|´;›|µ;œ|¶;|·;ž|¸;Ÿ|º; |»;¡_';¢†N;£U,;¤b¤;¥N’;¦lª;§b7;¨‚±;©T×;ªSN;«s>;¬nÑ;­u;;®R;¯S;°‹Ý;±iÐ;²_Š;³`;´mî;µWO;¶k";·s¯;¸hS;¹Ø;º;»cb;¼`£;½U$;¾uê;¿Œb;Àq;Ám£;Â[¦;Ã^{;ăR;ÅaL;ÆžÄ;Çxú;ȇW;É|';Êv‡;ËQð;Ì`ö;ÍqL;ÎfC;Ï^L;Ð`M;ÑŒ;Òpp;Óc%;Ô‰;Õ_½;Ö`b;׆Ô;ØVÞ;ÙkÁ;Ú`”;Ûag;ÜSI;Ý`à;Þff;ß?;àyý;áO;âpé;ãlG;䋳;å‹ò;æ~Ø;çƒd;èf;éZZ;ê›B;ëmQ;ìm÷;íŒA;îm;;ïO;ðpk;ñƒ·;òb;ó`Ñ;ô— ;õ';öyx;÷Qû;øW>;ùWú;úg:;ûux;üz=;ýyï;þ{•<@|¿<×u2<Ø”¾<ÙPG<Úz<<ÛN÷<Üg¶<Ýš~<ÞZÁ<ßk|<àvÑ<áWZ<â\<ã{:<ä•ô<åqN<æQ|<瀩<è‚p<éYx<ê<ëƒ'<ìhÀ<ígì<îx±<ïxw<ðbã<ñca<ò{€<óOí<ôRj<õQÏ<öƒP<÷iÛ<ø’t<ùõ<ú1<û‰Á<ü•.<ý{­<þNö=@}7=A}8=B}9=C}:=D};=E}<=F}==G}>=H}?=I}@=J}A=K}B=L}C=M}D=N}E=O}F=P}G=Q}H=R}I=S}J=T}K=U}L=V}M=W}N=X}O=Y}P=Z}Q=[}R=\}S=]}T=^}U=_}V=`}W=a}X=b}Y=c}Z=d}[=e}\=f}]=g}^=h}_=i}`=j}a=k}b=l}c=m}d=n}e=o}f=p}g=q}h=r}i=s}j=t}k=u}l=v}m=w}o=x}p=y}q=z}r={}s=|}t=}}u=~}v=€}x=}y=‚}z=ƒ}{=„}|=…}}=†}~=‡}=ˆ}€=‰}=Š}‚=‹}ƒ=Œ}„=}…=Ž}†=}‡=}ˆ=‘}‰=’}Š=“}‹=”}Œ=•}=–}Ž=—}=˜}=™}‘=š}’=›}“=œ}”=}•=ž}–=Ÿ}—= }˜=¡Pe=¢‚0=£RQ=¤™o=¥n=¦n…=§m§=¨^ú=©Põ=ªYÜ=«\=¬mF=­l_=®u†=¯„‹=°hh=±YV=²‹²=³S =´‘q=µ–M=¶…I=·i=¸y=¹q&=º€ö=»N¤=¼Ê=½mG=¾š„=¿Z=ÀV¼=Ád=”ð=Ãwë=ÄO¥=Å=Ærá=ljÒ=È™z=É4=Ê~Þ=ËR=ÌeY=Í‘u=Î=σ=ÐSë=Ñz–=Òcí=Óc¥=Ôv†=Õyø=ÖˆW=×–6=Øb*=ÙR«=Ú‚‚=ÛhT=Ügp=Ýcw=Þwk=ßzí=àm=á~Ó=â‰ã=ãYÐ=äb=å…É=æ‚¥=çuL=èP=éNË=êu¥=ë‹ë=ì\J=í]þ=î{K=ïe¤=ð‘Ñ=ñNÊ=òm%=ó‰_=ô}'=õ•&=öNÅ=÷Œ(=øÛ=ù—s=úfK=ûy=üÑ=ýpì=þmx>@}™>A}š>B}›>C}œ>D}>E}ž>F}Ÿ>G} >H}¡>I}¢>J}£>K}¤>L}¥>M}§>N}¨>O}©>P}ª>Q}«>R}¬>S}­>T}¯>U}°>V}±>W}²>X}³>Y}´>Z}µ>[}¶>\}·>]}¸>^}¹>_}º>`}»>a}¼>b}½>c}¾>d}¿>e}À>f}Á>g}Â>h}Ã>i}Ä>j}Å>k}Æ>l}Ç>m}È>n}É>o}Ê>p}Ë>q}Ì>r}Í>s}Î>t}Ï>u}Ð>v}Ñ>w}Ò>x}Ó>y}Ô>z}Õ>{}Ö>|}×>}}Ø>~}Ù>€}Ú>}Û>‚}Ü>ƒ}Ý>„}Þ>…}ß>†}à>‡}á>ˆ}â>‰}ã>Š}ä>‹}å>Œ}æ>}ç>Ž}è>}é>}ê>‘}ë>’}ì>“}í>”}î>•}ï>–}ð>—}ñ>˜}ò>™}ó>š}ô>›}õ>œ}ö>}÷>ž}ø>Ÿ}ù> }ú>¡\=>¢R²>£ƒF>¤Qb>¥ƒ>¦w[>§fv>¨œ¸>©N¬>ª`Ê>«|¾>¬|³>­~Ï>®N•>¯‹f>°fo>±˜ˆ>²—Y>³Xƒ>´el>µ•\>¶_„>·uÉ>¸—V>¹zß>ºzÞ>»QÀ>¼p¯>½z˜>¾cê>¿zv>À~ >Ás–>—í>ÃNE>Äpx>ÅN]>Æ‘R>ÇS©>ÈeQ>Éeç>Êü>Ë‚>ÌTŽ>Í\1>Îuš>Ï— >ÐbØ>ÑrÙ>Òu½>Ó\E>Ôšy>ÕƒÊ>Ö\@>×T€>Øwé>ÙN>>Úl®>Û€Z>ÜbÒ>Ýcn>Þ]è>ßQw>àÝ>áŽ>â•/>ãOñ>äSå>å`ç>æp¬>çRg>ècP>éžC>êZ>ëP&>ìw7>íSw>î~â>ïd…>ðe+>ñb‰>òc˜>óP>ôr5>õ‰É>öQ³>÷‹À>ø~Ý>ùWG>úƒÌ>û”§>üQ›>ýT>þ\û?@}û?A}ü?B}ý?C}þ?D}ÿ?E~?F~?G~?H~?I~?J~?K~?L~?M~?N~ ?O~ ?P~ ?Q~ ?R~ ?S~?T~?U~?V~?W~?X~?Y~?Z~?[~?\~?]~?^~?_~?`~?a~?b~?c~?d~?e~ ?f~!?g~"?h~#?i~$?j~%?k~&?l~'?m~(?n~)?o~*?p~+?q~,?r~-?s~.?t~/?u~0?v~1?w~2?x~3?y~4?z~5?{~6?|~7?}~8?~~9?€~:?~?„~??…~@?†~B?‡~C?ˆ~D?‰~E?Š~F?‹~H?Œ~I?~J?Ž~K?~L?~M?‘~N?’~O?“~P?”~Q?•~R?–~S?—~T?˜~U?™~V?š~W?›~X?œ~Y?~Z?ž~[?Ÿ~\? ~]?¡OÊ?¢zã?£mZ?¤á?¥š?¦U€?§T–?¨Sa?©T¯?ª_?«cé?¬iw?­Qï?®ah?¯R ?°X*?±RØ?²WN?³x ?´w ?µ^·?¶aw?·|à?¸b[?¹b—?ºN¢?»p•?¼€?½b÷?¾pä?¿—`?ÀWw?Á‚Û?Âgï?Ãhõ?ÄxÕ?Ř—?ÆyÑ?ÇXó?ÈT³?ÉSï?Ên4?ËQK?ÌR;?Í[¢?΋þ?Ï€¯?ÐUC?ÑW¦?Ò`s?ÓWQ?ÔT-?Õzz?Ö`P?×[T?Øc§?Ùb ?ÚSã?Ûbc?Ü[Ç?Ýg¯?ÞTí?ßzŸ?à‚æ?á‘w?â^“?ãˆä?äY8?åW®?æc?çè?è€ï?éWW?ê{w?ëO©?ì_ë?í[½?îk>?ïS!?ð{P?ñrÂ?òhF?ówÿ?ôw6?õe÷?öQµ?÷N?øvÔ?ù\¿?úz¥?û„u?üYN?ý›A?þP€@@~^@A~_@B~`@C~a@D~b@E~c@F~d@G~e@H~f@I~g@J~h@K~i@L~j@M~k@N~l@O~m@P~n@Q~o@R~p@S~q@T~r@U~s@V~t@W~u@X~v@Y~w@Z~x@[~y@\~z@]~{@^~|@_~}@`~~@a~@b~€@c~@d~ƒ@e~„@f~…@g~†@h~‡@i~ˆ@j~‰@k~Š@l~‹@m~Œ@n~@o~Ž@p~@q~@r~‘@s~’@t~“@u~”@v~•@w~–@x~—@y~˜@z~™@{~š@|~œ@}~@~~ž@€~®@~´@‚~»@ƒ~¼@„~Ö@…~ä@†~ì@‡~ù@ˆ @‰@Š@‹7@Œ9@;@Ž<@=@>@‘?@’@@“A@”C@•F@–G@—H@˜I@™J@šK@›L@œM@N@žO@ŸR@ S@¡™ˆ@¢a'@£nƒ@¤Wd@¥f@¦cF@§Vð@¨bì@©bi@ª^Ó@«–@¬Wƒ@­bÉ@®U‡@¯‡!@°J@±£@²Uf@³ƒ±@´ge@µV@¶„Ý@·Zj@¸h@¹bæ@º{î@»–@¼Qp@½oœ@¾Œ0@¿cý@À‰È@ÁaÒ@Â@ÃpÂ@Änå@Åt@Æi”@Çrü@È^Ê@ÉÎ@Êg@Ëmj@Ìc^@ÍR³@Îrb@Ï€@ÐOl@ÑYå@Ò‘j@ÓpÙ@Ôm@ÕRÒ@ÖNP@×–÷@Ø•m@Ù…~@ÚxÊ@Û}/@ÜQ!@ÝW’@ÞdÂ@߀‹@à|{@álê@âhñ@ãi^@äQ·@åS˜@æh¨@çr@èžÎ@é{ñ@êrø@ëy»@ìo@ít@îgN@ï‘Ì@ðœ¤@ñy<@òƒ‰@óƒT@ôT@õh@öN=@÷S‰@øR±@ùx>@úS†@ûR)@üPˆ@ýO‹@þOÐA@VAAYAB[AC\AD]AE^AF`AGcAHdAIeAJfAKgALkAMlANmAOoAPpAQsARuASvATwAUxAVzAW{AX|AY}AZA[€A\‚A]ƒA^„A_…A`†Aa‡AbˆAc‰Ad‹AeAfAgAh‘Ai’Aj“Ak•Al–Am—An˜Ao™Ap›AqœAr As¢At£Au¥Av¦Aw¨Ax©AyªAz«A{¬A|­A}®A~±A€³A´A‚µAƒ¶A„·A…ºA†»A‡¾AˆÀA‰ÂAŠÃA‹ÄAŒÆAÇAŽÈAÉAËA‘ÍA’ÏA“ÐA”ÑA•ÒA–ÓA—ÖA˜×A™ÙAšÚA›ÛAœÜAÝAžÞAŸâA ãA¡uâA¢zËA£|’A¤l¥A¥–¶A¦R›A§tƒA¨TéA©OéAª€TA«ƒ²A¬ÞA­•pA®^ÉA¯`A°mŸA±^A²e[A³8A´”þAµ`KA¶p¼A·~ÃA¸|®A¹QÉAºhA»|±A¼‚oA½N$A¾†A¿‘ÏAÀf~AÁN®AÂŒAÃd©AÄ€JAÅPÚAÆu—AÇqÎAÈ[åAɽAÊofAËN†AÌd‚AÍ•cAÎ^ÖAÏe™AÐRAшÂAÒpÈAÓR£AÔsAÕt3AÖg—A×x÷AØ—AÙN4AÚ»AÛœÞAÜmËAÝQÛAÞAAßTAàbÎAás²AâƒñAã–öA䟄Aå”ÃAæO6AçšAèQÌAépuAê–uAë\­A옆AíSæAîNäAïnœAðt Añi´AòxkAó™AôuYAõRAöv$A÷mAAøgóAùQmAúŸ™Aû€KAüT™Aý{Bp€@Bq€ABr€DBs€EBt€GBu€HBv€IBw€NBx€OBy€PBz€QB{€SB|€UB}€VB~€WB€€YB€[B‚€\Bƒ€]B„€^B…€_B†€`B‡€aBˆ€bB‰€cBŠ€dB‹€eBŒ€fB€gBŽ€hB€kB€lB‘€mB’€nB“€oB”€pB•€rB–€sB—€tB˜€uB™€vBš€wB›€xBœ€yB€zBž€{BŸ€|B €}B¡–†B¢W„B£bâB¤–GB¥i|B¦ZB§dB¨{ÓB©oBª–KB«‚¦B¬SbB­˜…B®^B¯p‰B°c³B±SdB²†OB³œB´ž“BµxŒB¶—2B·ïB¸BB¹žBºo^B»y„B¼_UB½–FB¾b.B¿štBÀTBÁ”ÝBÂO£BÃeÅBÄ\eBÅ\aBÆBdžQBÈl/BÉ_‹BÊs‡BËnäBÌ~ÿBÍ\æBÎcBÏ[jBÐnæBÑSuBÒNqBÓc BÔueBÕb¡BÖnB×O&BØNÑBÙl¦BÚ~¶BÛ‹ºBÜ„B݇ºBÞWBß;Bà•#Bá{©Bâš¡BãˆøBä„=BåmB暆Bç~ÜBèYˆBéž»Bês›BëxB솂BíšlBîš‚BïVBðTBñWËBòNpBóž¦BôSVBõÈBö B÷w’Bø™’Bù†îBúnáBû…BüfüBýabBþo+C@€~CA€CB€‚CC€…CD€ˆCE€ŠCF€CG€ŽCH€CI€CJ€‘CK€’CL€”CM€•CN€—CO€™CP€žCQ€£CR€¦CS€§CT€¨CU€¬CV€°CW€³CX€µCY€¶CZ€¸C[€¹C\€»C]€ÅC^€ÇC_€ÈC`€ÉCa€ÊCb€ËCc€ÏCd€ÐCe€ÑCf€ÒCg€ÓCh€ÔCi€ÕCj€ØCk€ßCl€àCm€âCn€ãCo€æCp€îCq€õCr€÷Cs€ùCt€ûCu€þCv€ÿCwCxCyCzC{C|C}C~ C€ CC‚CƒC„C…C†C‡Cˆ C‰!CŠ"C‹#CŒ$C%CŽ&C'C(C‘)C’*C“+C”-C•.C–0C—3C˜4C™5Cš7C›9Cœ:C;CžEÊeEËoXEÌvØEÍxÐEÎvüEÏuTEÐR$EÑSÛEÒNSEÓ^žEÔeÁEÕ€*EÖ€ÖE×b›EØT†EÙR(EÚp®EÛˆEÜÑEÝláEÞTxE߀ÚEàWùEáˆôEâTEã–jEä‘MEåOiEæl›EçU·EèvÆEéx0Eêb¨EëpùEìoŽEí_mEî„ìEïhÚEðx|Eñ{÷Eò¨Eóg EôžOEõcgEöx°E÷WoEøxEù—9EúbyEûb«EüRˆEýt5Eþk×F@‚jFA‚kFB‚lFC‚mFD‚qFE‚uFF‚vFG‚wFH‚xFI‚{FJ‚|FK‚€FL‚FM‚ƒFN‚…FO‚†FP‚‡FQ‚‰FR‚ŒFS‚FT‚“FU‚”FV‚•FW‚–FX‚šFY‚›FZ‚žF[‚ F\‚¢F]‚£F^‚§F_‚²F`‚µFa‚¶Fb‚ºFc‚»Fd‚¼Fe‚¿Ff‚ÀFg‚ÂFh‚ÃFi‚ÅFj‚ÆFk‚ÉFl‚ÐFm‚ÖFn‚ÙFo‚ÚFp‚ÝFq‚âFr‚çFs‚èFt‚éFu‚êFv‚ìFw‚íFx‚îFy‚ðFz‚òF{‚óF|‚õF}‚öF~‚øF€‚úF‚üF‚‚ýFƒ‚þF„‚ÿF…ƒF†ƒ F‡ƒ Fˆƒ F‰ƒFŠƒF‹ƒFŒƒFƒFŽƒFƒFƒF‘ƒF’ƒ F“ƒ!F”ƒ"F•ƒ#F–ƒ$F—ƒ%F˜ƒ&F™ƒ)Fšƒ*F›ƒ.Fœƒ0Fƒ2Fžƒ7FŸƒ;F ƒ=F¡UdF¢>F£u²F¤v®F¥S9F¦uÞF§PûF¨\AF©‹lFª{ÇF«POF¬rGF­š—F®˜ØF¯oF°tâF±yhF²d‡F³w¥F´büFµ˜‘F¶+F·TÁF¸€XF¹NRFºWjF»‚ùF¼„ F½^sF¾QíF¿töFÀ‹ÄFÁ\OFÂWaFÃlüFʇFÅZFFÆx4FÇ›DFÈëFÉ|•FÊRVFËbQFÌ”úFÍNÆF΃†FÏ„aFЃéFÑ„²FÒWÔFÓg4FÔWFÕfnFÖmfF׌1FØfÝFÙpFÚgFÛk:FÜhFÝbFÞY»FßNFàQÄFáoFâgÒFãlFäQvFåhËFæYGFçkgFèufFé]FêFëŸPFìe×FíyHFîyAFïš‘FðwFñ\‚FòN^FóOFôT/FõYQFöx F÷VhFølFùÄFú_Fûl}FülãFý‹«FþcG@ƒ>GAƒ?GBƒAGCƒBGDƒDGEƒEGFƒHGGƒJGHƒKGIƒLGJƒMGKƒNGLƒSGMƒUGNƒVGOƒWGPƒXGQƒYGRƒ]GSƒbGTƒpGUƒqGVƒrGWƒsGXƒtGYƒuGZƒvG[ƒyG\ƒzG]ƒ~G^ƒG_ƒ€G`ƒGaƒ‚GbƒƒGcƒ„Gdƒ‡GeƒˆGfƒŠGgƒ‹GhƒŒGiƒGjƒGkƒGlƒ‘Gmƒ”Gnƒ•Goƒ–Gpƒ—Gqƒ™GrƒšGsƒGtƒŸGuƒ¡Gvƒ¢Gwƒ£Gxƒ¤Gyƒ¥Gzƒ¦G{ƒ§G|ƒ¬G}ƒ­G~ƒ®G€ƒ¯GƒµG‚ƒ»Gƒƒ¾G„ƒ¿G…ƒÂG†ƒÃG‡ƒÄGˆƒÆG‰ƒÈGŠƒÉG‹ƒËGŒƒÍGƒÎGŽƒÐGƒÑGƒÒG‘ƒÓG’ƒÕG“ƒ×G”ƒÙG•ƒÚG–ƒÛG—ƒÞG˜ƒâG™ƒãGšƒäG›ƒæGœƒçGƒèGžƒëGŸƒìG ƒíG¡`pG¢m=G£ruG¤bfG¥”ŽG¦”ÅG§SCG¨ÁG©{~GªNßG«Œ&G¬N~G­žÔG®”±G¯”³G°RMG±o\G²cG³mEG´Œ4GµXG¶]LG·k G¸kIG¹gªGºT[G»TG¼ŒG½X™G¾…7G¿_:GÀb¢GÁjGG•9GÃerGÄ`„GÅheGÆw§GÇNTGÈO¨GÉ]çGÊ—˜GËd¬GÌØGÍ\íGÎOÏGÏzGÐRGуGÒNGÓ`/GÔzƒGÕ”¦GÖOµG×N²GØyæGÙt4GÚRäGÛ‚¹GÜdÒGÝy½GÞ[ÝGßlGà—RGá{Gâl"GãP>GäSGånGædÎGçftGèl0Gé`ÅGê˜wGë‹÷Gì^†GítHu„?Hv„@Hw„AHx„BHy„CHz„DH{„EH|„GH}„HH~„IH€„JH„KH‚„LHƒ„MH„„NH…„OH†„PH‡„RHˆ„SH‰„THŠ„UH‹„VHŒ„XH„]HŽ„^H„_H„`H‘„bH’„dH“„eH”„fH•„gH–„hH—„jH˜„nH™„oHš„pH›„rHœ„tH„wHž„yHŸ„{H „|H¡SÖH¢Z6H£Ÿ‹H¤£H¥S»H¦WH§˜§H¨gCH©‘›HªlÉH«QhH¬uÊH­bóH®r¬H¯R8H°RH±:H²p”H³v8H´StHµžJH¶i·H·xnH¸–ÀH¹ˆÙHº¤H»q6H¼qÃH½Q‰H¾gÓH¿täHÀXäHÁeHÂV·HË©HÄ™vHÅbpHÆ~ÕHÇ`ùHÈpíHÉXìHÊNÁHËNºHÌ_ÍHÍ—çHÎNûHÏ‹¤HÐRHÑYŠHÒ~«HÓbTHÔNÍHÕeåHÖbH׃8HØ„ÉHÙƒcHÚ‡HÛq”HÜn¶HÝ[¹HÞ~ÒHßQ—HàcÉHágÔH Hãƒ9HäˆHåQHæ[zHçY‚Hè±HéNsHêl]HëQeHì‰%HíoHî–.Hï…JHðt^Hñ•Hò•ðHóm¦Hô‚åHõ_1Höd’H÷mHø„(HùnHúœÃHûX^Hü[HýN HþSÁI@„}IA„~IB„IC„€ID„IE„ƒIF„„IG„…IH„†II„ŠIJ„IK„IL„IM„‘IN„’IO„“IP„”IQ„•IR„–IS„˜IT„šIU„›IV„IW„žIX„ŸIY„ IZ„¢I[„£I\„¤I]„¥I^„¦I_„§I`„¨Ia„©Ib„ªIc„«Id„¬Ie„­If„®Ig„°Ih„±Ii„³Ij„µIk„¶Il„·Im„»In„¼Io„¾Ip„ÀIq„ÂIr„ÃIs„ÅIt„ÆIu„ÇIv„ÈIw„ËIx„ÌIy„ÎIz„ÏI{„ÒI|„ÔI}„ÕI~„×I€„ØI„ÙI‚„ÚIƒ„ÛI„„ÜI…„ÞI†„áI‡„âIˆ„äI‰„çIŠ„èI‹„éIŒ„êI„ëIŽ„íI„îI„ïI‘„ñI’„òI“„óI”„ôI•„õI–„öI—„÷I˜„øI™„ùIš„úI›„ûIœ„ýI„þIž…IŸ…I …I¡OI¢ecI£hQI¤UÓI¥N'I¦dI§ššI¨bkI©ZÂIªt_I«‚rI¬m©I­hîI®PçI¯ƒŽI°xI±g@I²R9I³l™I´~±IµP»I¶UeI·q^I¸{[I¹fRIºsÊI»‚ëI¼gII½\qI¾R I¿q}IÀˆkIÁ•êI–UIÃdÅIÄaIųIÆU„IÇlUIÈbGIÉ.IÊX’IËO$IÌUFIÍOIÎfLIÏN IÐ\IшóIÒh¢IÓcNIÔz IÕpçIÖ‚I×RúIØ—öIÙ\IÚTèIÛµIÜ~ÍIÝYbIÞJI߆ÇIà‚ Iá‚ IâfIãdDIä\IåaQIæm‰Içy>I苾Iéx7Iêu3IëT{IìO8I펫IîmñIïZ Ið~ÅIñy^IòlˆIó[¡IôZvIõuIö€¾I÷aNIønIùXðIúuIûu%IürrIýSGIþ~óJ@…JA…JB…JC…JD…JE…JF… JG… JH… JI… JJ…JK…JL…JM…JN…JO…JP…JQ…JR…JS…JT…JU…JV…JW… JX…"JY…#JZ…$J[…%J\…&J]…'J^…(J_…)J`…*Ja…-Jb….Jc…/Jd…0Je…1Jf…2Jg…3Jh…4Ji…5Jj…6Jk…>Jl…?Jm…@Jn…AJo…BJp…DJq…EJr…FJs…GJt…KJu…LJv…MJw…NJx…OJy…PJz…QJ{…RJ|…SJ}…TJ~…UJ€…WJ…XJ‚…ZJƒ…[J„…\J……]J†…_J‡…`Jˆ…aJ‰…bJŠ…cJ‹…eJŒ…fJ…gJŽ…iJ…jJ…kJ‘…lJ’…mJ“…nJ”…oJ•…pJ–…qJ—…sJ˜…uJ™…vJš…wJ›…xJœ…|J…}Jž…JŸ…€J …J¡wJ¢vÛJ£RiJ¤€ÜJ¥W#J¦^J§Y1J¨rîJ©e½JªnJ«‹×J¬\8J­†qJ®SAJ¯wóJ°bþJ±eöJ²NÀJ³˜ßJ´†€Jµ[žJ¶‹ÆJ·SòJ¸wâJ¹OJº\NJ»švJ¼YËJ½_J¾y:J¿XëJÀNJÁgÿJÂN‹JÃbíJÄŠ“JÅJÆR¿JÇf/JÈUÜJÉVlJÊJËNÕJÌOJÍ‘ÊJΙpJÏlJÐ^JÑ`CJÒ[¤JÓ‰ÆJÔ‹ÕJÕe6JÖbKJ×™–JØ[ˆJÙ[ÿJÚcˆJÛU.JÜS×JÝv&JÞQ}Jß…,Jàg¢Jáh³JâkŠJãb’Jä“JåSÔJæ‚JçmÑJèuJéNfJêNJë[pJìqŸJí…¯Jîf‘JïfÙJðrJñ‡JòžÍJóŸ Jô\^Jõg/JöðJ÷hJøg_Jùb JúzÖJûX…Jü^¶JýepJþo1K@…‚KA…ƒKB…†KC…ˆKD…‰KE…ŠKF…‹KG…ŒKH…KI…ŽKJ…KK…‘KL…’KM…“KN…”KO…•KP…–KQ…—KR…˜KS…™KT…šKU…KV…žKW…ŸKX… KY…¡KZ…¢K[…£K\…¥K]…¦K^…§K_…©K`…«Ka…¬Kb…­Kc…±Kd…²Ke…³Kf…´Kg…µKh…¶Ki…¸Kj…ºKk…»Kl…¼Km…½Kn…¾Ko…¿Kp…ÀKq…ÂKr…ÃKs…ÄKt…ÅKu…ÆKv…ÇKw…ÈKx…ÊKy…ËKz…ÌK{…ÍK|…ÎK}…ÑK~…ÒK€…ÔK…ÖK‚…×Kƒ…ØK„…ÙK……ÚK†…ÛK‡…ÝKˆ…ÞK‰…ßKŠ…àK‹…áKŒ…âK…ãKŽ…åK…æK…çK‘…èK’…êK“…ëK”…ìK•…íK–…îK—…ïK˜…ðK™…ñKš…òK›…óKœ…ôK…õKž…öKŸ…÷K …øK¡`UK¢R7K£€ K¤dTK¥ˆpK¦u)K§^K¨hK©bôKª—K«SÌK¬r=K­ŒK®l4K¯waK°zK±T.K²w¬K³˜zK´‚Kµ‹ôK¶xUK·gK¸pÁK¹e¯Kºd•K»V6K¼`K½yÁK¾SøK¿NKÀk{KÁ€†KÂ[úKÃUãKÄVÛKÅO:KÆOL}†?L~†@L€†AL†BL‚†CLƒ†DL„†EL…†FL††GL‡†HLˆ†IL‰†JLІKL‹†LLŒ†RL†SLކUL†VL†WL‘†XL’†YL“†[L”†\L•†]L–†_L—†`L˜†aL™†cLš†dL›†eLœ†fL†gLž†hLŸ†iL †jL¡smL¢cL£ŽKL¤ŽL¥€ÎL¦‚ÔL§b¬L¨SðL©lðLª‘^L«Y*L¬`L­lpL®WML¯dJL°*L±v+L²néL³W[L´j€LµuðL¶omL·Œ-L¸ŒL¹WfLºkïL»ˆ’L¼x³L½c¢L¾SùL¿p­LÀldLÁXXLÂd*LÃXLÄhàLÅ›LÆULÇ|ÖLÈPLÉŽºLÊmÌLËŸLÌpëLÍcLÎm›LÏnÔLÐ~æLÑ„LÒhCLÓLÔmØLÕ–vLÖ‹¨L×YWLØryLÙ…äLÚ~LÛu¼LÜŠŠLÝh¯LÞRTLߎ"Là•LácÐL☘LãŽDLäU|LåOSLæfÿLçVLè`ÕLém•LêRCLë\ILìY)LímûLîXkLïu0LðuLñ`lLò‚LóFLôcLõgaLöâL÷w:LøóLù4Lú”ÁLû^LüS…LýT,LþpÃM@†mMA†oMB†pMC†rMD†sME†tMF†uMG†vMH†wMI†xMJ†ƒMK†„ML†…MM††MN†‡MO†ˆMP†‰MQ†ŽMR†MS†MT†‘MU†’MV†”MW†–MX†—MY†˜MZ†™M[†šM\†›M]†žM^†ŸM_† M`†¡Ma†¢Mb†¥Mc†¦Md†«Me†­Mf†®Mg†²Mh†³Mi†·Mj†¸Mk†¹Ml†»Mm†¼Mn†½Mo†¾Mp†¿Mq†ÁMr†ÂMs†ÃMt†ÅMu†ÈMv†ÌMw†ÍMx†ÒMy†ÓMz†ÕM{†ÖM|†×M}†ÚM~†ÜM€†ÝM†àM‚†áMƒ†âM„†ãM…†åM††æM‡†çMˆ†èM‰†êMІëM‹†ìMŒ†ïM†õMކöM†÷M†úM‘†ûM’†üM“†ýM”†ÿM•‡M–‡M—‡M˜‡M™‡ Mš‡ M›‡Mœ‡M‡Mž‡MŸ‡M ‡M¡l@M¢^÷M£P\M¤N­M¥^­M¦c:M§‚GM¨M©hPMª‘nM«w³M¬T M­”ÜM®_dM¯zåM°hvM±cEM²{RM³~ßM´uÛMµPwM¶b•M·Y4M¸M¹QøMºyÃM»zM¼VþM½_’M¾M¿m‚MÀ\`MÁWMÂTMÃQTMÄnMMÅVâMÆc¨Mǘ“MÈMɇMʉ*MËMÌTMÍ\oMÎÀMÏbÖMÐbXMÑ1MÒž5MÓ–@MÔšnMÕš|MÖi-M×Y¥MØbÓMÙU>MÚcMÛTÇM܆ÙMÝmN³~¬N´g*Nµ…N¶TsN·uON¸€ÃN¹U‚Nº›ON»OMN¼n-N½ŒN¾\ N¿apNÀSkNÁvNÂn)NÆŠNÄe‡NÅ•ûNÆ~¹NÇT;NÈz3NÉ} NÊ•îNËUáNÌÁNÍtîNÎcNχNÐm¡NÑzNÒbNÓe¡NÔSgNÕcáNÖlƒN×]ëNØT\NÙ”¨NÚNLNÛlaNÜ‹ìNÝ\KNÞeàNß‚œNàh§NáT>NâT4NãkËNäkfNåN”NæcBNçSHNè‚NéO NêO®NëW^Nìb Ní–þNîfdNïriNðRÿNñR¡Nò`ŸNó‹ïNôfNõq™NögN÷‰NøxRNùwýNúfpNûV;NüT8Ný•!NþrzO@‡¥OA‡¦OB‡§OC‡©OD‡ªOE‡®OF‡°OG‡±OH‡²OI‡´OJ‡¶OK‡·OL‡¸OM‡¹ON‡»OO‡¼OP‡¾OQ‡¿OR‡ÁOS‡ÂOT‡ÃOU‡ÄOV‡ÅOW‡ÇOX‡ÈOY‡ÉOZ‡ÌO[‡ÍO\‡ÎO]‡ÏO^‡ÐO_‡ÔO`‡ÕOa‡ÖOb‡×Oc‡ØOd‡ÙOe‡ÚOf‡ÜOg‡ÝOh‡ÞOi‡ßOj‡áOk‡âOl‡ãOm‡äOn‡æOo‡çOp‡èOq‡éOr‡ëOs‡ìOt‡íOu‡ïOv‡ðOw‡ñOx‡òOy‡óOz‡ôO{‡õO|‡öO}‡÷O~‡øO€‡úO‡ûO‚‡üOƒ‡ýO„‡ÿO…ˆO†ˆO‡ˆOˆˆO‰ˆOŠˆO‹ˆOŒˆOˆ OŽˆ Oˆ Oˆ O‘ˆO’ˆO“ˆO”ˆO•ˆO–ˆO—ˆO˜ˆO™ˆOšˆO›ˆOœˆOˆOžˆOŸˆ O ˆ#O¡zO¢`oO£^ O¤`‰O¥O¦YO§`ÜO¨q„O©pïOªnªO«lPO¬r€O­j„O®ˆ­O¯^-O°N`O±Z³O²UœO³”ãO´mOµ|ûO¶–™O·bO¸~ÆO¹wŽOº†~O»S#O¼—O½–O¾f‡O¿\áOÀO OÁríOÂN OÃS¦OÄYOÅTOÆc€OÇ•(OÈQHOÉNÙOÊœœOË~¤OÌT¸OÍ$OΈTOÏ‚7OЕòOÑmŽOÒ_&OÓZÌOÔf>OÕ–iOÖs°O×s.OØS¿OÙzOÚ™…OÛ¡OÜ[ªOÝ–wOÞ–POß~¿OàvøOáS¢Oâ•vOã™™Oä{±Oå‰DOænXOçNaOèÔOéyeOê‹æOë`óOìTÍOíN«Oî˜yOï]÷OðjaOñPÏOòTOóŒaOô„'Oõx]Oö—O÷RJOøTîOùV£Oú•OûmˆOü[µOýmÆOþfSP@ˆ$PAˆ%PBˆ&PCˆ'PDˆ(PEˆ)PFˆ*PGˆ+PHˆ,PIˆ-PJˆ.PKˆ/PLˆ0PMˆ1PNˆ3POˆ4PPˆ5PQˆ6PRˆ7PSˆ8PTˆ:PUˆ;PVˆ=PWˆ>PXˆ?PYˆAPZˆBP[ˆCP\ˆFP]ˆGP^ˆHP_ˆIP`ˆJPaˆKPbˆNPcˆOPdˆPPeˆQPfˆRPgˆSPhˆUPiˆVPjˆXPkˆZPlˆ[Pmˆ\Pnˆ]Poˆ^Ppˆ_Pqˆ`PrˆfPsˆgPtˆjPuˆmPvˆoPwˆqPxˆsPyˆtPzˆuP{ˆvP|ˆxP}ˆyP~ˆzP€ˆ{Pˆ|P‚ˆ€PƒˆƒP„ˆ†P…ˆ‡P†ˆ‰P‡ˆŠPˆˆŒP‰ˆŽPŠˆP‹ˆPŒˆ‘Pˆ“PŽˆ”Pˆ•Pˆ—P‘ˆ˜P’ˆ™P“ˆšP”ˆ›P•ˆP–ˆžP—ˆŸP˜ˆ P™ˆ¡Pšˆ£P›ˆ¥Pœˆ¦Pˆ§Pžˆ¨PŸˆ©P ˆªP¡\P¢[]P£h!P¤€–P¥UxP¦{P§eHP¨iTP©N›PªkGP«‡NP¬—‹P­SOP®cP¯d:P°ªP±eœP²€ÁP³ŒP´Q™Pµh°P¶SxP·‡ùP¸aÈP¹lÄPºlûP»Œ"P¼\QP½…ªP¾‚¯P¿• PÀk#PÁ›PÂe°PÃ_ûPÄ_ÃPÅOáPƈEPÇfPÈePÉs)PÊ`úPËQtPÌRPÍW‹PÎ_bPÏ¢PЈLPÑ‘’PÒ^xPÓgOPÔ`'PÕYÓPÖQDP×QöPØ€øPÙSPÚlyPÛ–ÄPÜqŠPÝOPÞOîPßžPàg=PáUÅPâ•PãyÀP䈖På~ãPæXŸPçb Pè—Pé†ZPêVPë˜{Pì_P틸Pî„ÄPï‘WPðSÙPñeíPò^Póu\Pô`dPõ}nPöZP÷~êPø~íPùiPúU§Pû[£Pü`¬PýeËPþs„Q@ˆ¬QAˆ®QBˆ¯QCˆ°QDˆ²QEˆ³QFˆ´QGˆµQHˆ¶QIˆ¸QJˆ¹QKˆºQLˆ»QMˆ½QNˆ¾QOˆ¿QPˆÀQQˆÃQRˆÄQSˆÇQTˆÈQUˆÊQVˆËQWˆÌQXˆÍQYˆÏQZˆÐQ[ˆÑQ\ˆÓQ]ˆÖQ^ˆ×Q_ˆÚQ`ˆÛQaˆÜQbˆÝQcˆÞQdˆàQeˆáQfˆæQgˆçQhˆéQiˆêQjˆëQkˆìQlˆíQmˆîQnˆïQoˆòQpˆõQqˆöQrˆ÷QsˆúQtˆûQuˆýQvˆÿQw‰Qx‰Qy‰Qz‰Q{‰Q|‰Q}‰Q~‰Q€‰ Q‰ Q‚‰ Qƒ‰ Q„‰Q…‰Q†‰Q‡‰Qˆ‰Q‰‰QЉQ‹‰QŒ‰Q‰QމQ‰Q‰ Q‘‰"Q’‰#Q“‰$Q”‰&Q•‰'Q–‰(Q—‰)Q˜‰,Q™‰-Qš‰.Q›‰/Qœ‰1Q‰2Qž‰3QŸ‰5Q ‰7Q¡ Q¢vcQ£w)Q¤~ÚQ¥—tQ¦…›Q§[fQ¨ztQ©–êQªˆ@Q«RËQ¬qQ­_ªQ®eìQ¯‹âQ°[ûQ±šoQ²]áQ³k‰Q´l[Qµ‹­Q¶‹¯Q· Q¸ÅQ¹S‹Qºb¼Q»ž&Q¼ž-Q½T@Q¾N+Q¿‚½QÀrYQÁ†œQÂ]QÈYQÄm¯QÅ–ÅQÆTÑQÇNšQÈ‹¶QÉq QÊT½QË– QÌpßQÍmùQÎvÐQÏN%QÐxQчQÒ\©QÓ^öQÔŠQÕ˜œQÖ–Q×pŽQØl¿QÙYDQÚc©QÛwQû€QüpQýY–QþtvR@‰8RA‰9RB‰:RC‰;RD‰RG‰?RH‰@RI‰BRJ‰CRK‰ERL‰FRM‰GRN‰HRO‰IRP‰JRQ‰KRR‰LRS‰MRT‰NRU‰ORV‰PRW‰QRX‰RRY‰SRZ‰TR[‰UR\‰VR]‰WR^‰XR_‰YR`‰ZRa‰[Rb‰\Rc‰]Rd‰`Re‰aRf‰bRg‰cRh‰dRi‰eRj‰gRk‰hRl‰iRm‰jRn‰kRo‰lRp‰mRq‰nRr‰oRs‰pRt‰qRu‰rRv‰sRw‰tRx‰uRy‰vRz‰wR{‰xR|‰yR}‰zR~‰|R€‰}R‰~R‚‰€Rƒ‰‚R„‰„R…‰…R†‰‡R‡‰ˆRˆ‰‰R‰‰ŠRЉ‹R‹‰ŒRŒ‰R‰ŽRމR‰R‰‘R‘‰’R’‰“R“‰”R”‰•R•‰–R–‰—R—‰˜R˜‰™R™‰šRš‰›R›‰œRœ‰R‰žRž‰ŸRŸ‰ R ‰¡R¡dGR¢\'R£eR¤z‘R¥Œ#R¦YÚR§T¬R¨‚R©ƒoRª‰R«€R¬i0R­VNR®€6R¯r7R°‘ÎR±Q¶R²N_R³˜uR´c–RµNR¶SöR·fóR¸KR¹YRºm²R»NR¼XùR½S;R¾cÖR¿”ñRÀORÁO RˆcRØRÄY7RÅWRÆyûRÇNêRÈ€ðRÉu‘RÊl‚RË[œRÌYèRÍ_]RÎiRφRÐPRÑ]òRÒNYRÓwãRÔNåRÕ‚zRÖb‘R×fRØ‘RÙ\yRÚN¿RÛ_yRÜÆRÝ8RÞ€„Rßu«RàN¦RáˆÔRâaRãkÅRä_ÆRåNIRævÊRçn¢Rè‹ãRé‹®RêŒ Rë‹ÑRì_RíüRîÌRï~ÎRðƒ5RñƒkRòVàRók·Rô—óRõ–4RöYûR÷TRø”öRùmëRú[ÅRû™nRü\9Rý_Rþ–S@‰¢SA‰£SB‰¤SC‰¥SD‰¦SE‰§SF‰¨SG‰©SH‰ªSI‰«SJ‰¬SK‰­SL‰®SM‰¯SN‰°SO‰±SP‰²SQ‰³SR‰´SS‰µST‰¶SU‰·SV‰¸SW‰¹SX‰ºSY‰»SZ‰¼S[‰½S\‰¾S]‰¿S^‰ÀS_‰ÃS`‰ÍSa‰ÓSb‰ÔSc‰ÕSd‰×Se‰ØSf‰ÙSg‰ÛSh‰ÝSi‰ßSj‰àSk‰áSl‰âSm‰äSn‰çSo‰èSp‰éSq‰êSr‰ìSs‰íSt‰îSu‰ðSv‰ñSw‰òSx‰ôSy‰õSz‰öS{‰÷S|‰øS}‰ùS~‰úS€‰ûS‰üS‚‰ýSƒ‰þS„‰ÿS…ŠS†ŠS‡ŠSˆŠS‰ŠSŠŠS‹ŠSŒŠ SŠ SŽŠ SŠ SŠ S‘ŠS’ŠS“ŠS”ŠS•ŠS–ŠS—ŠS˜ŠS™ŠSšŠS›ŠSœŠSŠSžŠSŸŠS ŠS¡SpS¢‚ñS£j1S¤ZtS¥žpS¦^”S§(S¨ƒ¹S©„$Sª„%S«ƒgS¬‡GS­ÎS®bS¯vÈS°_qS±˜–S²xlS³f S´TßSµbåS¶OcS·ÃS¸uÈS¹^¸Sº–ÍS»Ž S¼†ùS½TS¾lóS¿mŒSÀl8SÁ`SÂRÇSÃu(SÄ^}SÅOSÆ` SÇ_çSÈ\$SÉu1SÊ®SË”ÀSÌr¹SÍl¹SÎn8SÏ‘ISÐg SÑSËSÒSóSÓOQSÔ‘ÉSÕ‹ñSÖSÈS×^|SØÂSÙmäSÚNŽSÛvÂSÜi†S݆^SÞaSß‚SàOYSáOÞSâ>Sãœ|Säa SånSænSç–…SèNˆSéZ1Sê–èSëNSì\Síy¹Sî[‡Sï‹íSð½Sñs‰SòWßSó‚‹SôÁSõTSöGS÷U»Sø\êSù_¡SúaSûk2SürñSý€²SþЉT@ŠTAŠTBŠ TCŠ!TDŠ"TEŠ#TFŠ$TGŠ%THŠ&TIŠ'TJŠ(TKŠ)TLŠ*TMŠ+TNŠ,TOŠ-TPŠ.TQŠ/TRŠ0TSŠ1TTŠ2TUŠ3TVŠ4TWŠ5TXŠ6TYŠ7TZŠ8T[Š9T\Š:T]Š;T^ŠVš‹?V›‹@Vœ‹AV‹BVž‹CVŸ‹DV ‹EV¡^'V¢uÇV£ÑV¤‹ÁV¥‚V¦gV§e/V¨T1V©‡VªwåV«€¢V¬V­lAV®NKV¯~ÇV°€LV±vôV²i V³k–V´bgVµPXGŒ?XHŒ@XIŒBXJŒCXKŒDXLŒEXMŒHXNŒJXOŒKXPŒMXQŒNXRŒOXSŒPXTŒQXUŒRXVŒSXWŒTXXŒVXYŒWXZŒXX[ŒYX\Œ[X]Œ\X^Œ]X_Œ^X`Œ_XaŒ`XbŒcXcŒdXdŒeXeŒfXfŒgXgŒhXhŒiXiŒlXjŒmXkŒnXlŒoXmŒpXnŒqXoŒrXpŒtXqŒuXrŒvXsŒwXtŒ{XuŒ|XvŒ}XwŒ~XxŒXyŒ€XzŒX{ŒƒX|Œ„X}Œ†X~Œ‡X€ŒˆXŒ‹X‚ŒXƒŒŽX„ŒX…ŒX†Œ‘X‡Œ’XˆŒ“X‰Œ•XŠŒ–X‹Œ—XŒŒ™XŒšXŽŒ›XŒœXŒX‘ŒžX’ŒŸX“Œ X”Œ¡X•Œ¢X–Œ£X—Œ¤X˜Œ¥X™Œ¦XšŒ§X›Œ¨XœŒ©XŒªXžŒ«XŸŒ¬X Œ­X¡NX¢N X£Q@X¤NX¥^ÿX¦SEX§NX¨N˜X©NXª›2X«[lX¬ViX­N(X®yºX¯N?X°SX±NGX²Y-X³r;X´SnXµlX¶VßX·€äX¸™—X¹kÓXºw~X»ŸX¼N6X½NŸX¾ŸX¿N\XÀNiXÁN“X‚ˆXÃ[[XÄUlXÅVXÆNÄXÇSXÈSXÉS£XÊS¥XËS®XÌ—eXÍ]XÎSXÏSõXÐS&XÑS.XÒS>XÓ\XÔSfXÕScXÖRX×RXØRXÙR-XÚR3XÛR?XÜR@XÝRLXÞR^XßRaXàR\XᄯXâR}XãR‚XäRXåRXæR“XçQ‚XèTXéN»XêNÃXëNÉXìNÂXíNèXîNáXïNëXðNÞXñOXòNóXóO"XôOdXõNõXöO%X÷O'XøO XùO+XúO^XûOgXüe8XýOZXþO]Y@Œ®YAŒ¯YBŒ°YCŒ±YDŒ²YEŒ³YFŒ´YGŒµYHŒ¶YIŒ·YJŒ¸YKŒ¹YLŒºYMŒ»YNŒ¼YOŒ½YPŒ¾YQŒ¿YRŒÀYSŒÁYTŒÂYUŒÃYVŒÄYWŒÅYXŒÆYYŒÇYZŒÈY[ŒÉY\ŒÊY]ŒËY^ŒÌY_ŒÍY`ŒÎYaŒÏYbŒÐYcŒÑYdŒÒYeŒÓYfŒÔYgŒÕYhŒÖYiŒ×YjŒØYkŒÙYlŒÚYmŒÛYnŒÜYoŒÝYpŒÞYqŒßYrŒàYsŒáYtŒâYuŒãYvŒäYwŒåYxŒæYyŒçYzŒèY{ŒéY|ŒêY}ŒëY~ŒìY€ŒíYŒîY‚ŒïYƒŒðY„ŒñY…ŒòY†ŒóY‡ŒôYˆŒõY‰ŒöYŠŒ÷Y‹ŒøYŒŒùYŒúYŽŒûYŒüYŒýY‘ŒþY’ŒÿY“Y”Y•Y–Y—Y˜Y™YšY›Yœ Y Yž YŸ Y  Y¡O_Y¢OWY£O2Y¤O=Y¥OvY¦OtY§O‘Y¨O‰Y©OƒYªOY«O~Y¬O{Y­OªY®O|Y¯O¬Y°O”Y±OæY²OèY³OêY´OÅYµOÚY¶OãY·OÜY¸OÑY¹OßYºOøY»P)Y¼PLY½OóY¾P,Y¿PYÀP.YÁP-YÂOþYÃPYÄP YÅP%YÆP(YÇP~YÈPCYÉPUYÊPHYËPNYÌPlYÍP{YÎP¥YÏP§YÐP©YÑPºYÒPÖYÓQYÔPíYÕPìYÖPæY×PîYØQYÙQ YÚNÝYÛl=YÜOXYÝOeYÞOÎYߟ YàlFYá|tYâQnYã]ýYäžÉY噘YæQYçYYèRùYéS YêŠYëSYìQëYíYYîQUYïN YðQVYñN³YòˆnYóˆ¤YôNµYõYöˆÒY÷y€Yø[4YùˆYú¸YûQ«YüQ±YýQ½YþQ¼Z@ZAZBZCZDZEZFZGZHZIZJZKZLZMZNZO ZPQZQRZRWZS_ZTeZUhZViZWjZXlZYnZZoZ[qZ\rZ]xZ^yZ_zZ`{Za|Zb}Zc~ZdZe€Zf‚ZgƒZh†Zi‡ZjˆZk‰ZlŒZmZnŽZoZpZq’Zr“Zs•Zt–Zu—Zv˜Zw™ZxšZy›ZzœZ{Z|žZ} Z~¡Z€¢Z¤Z‚¥Zƒ¦Z„§Z…¨Z†©Z‡ªZˆ«Z‰¬ZŠ­Z‹®ZŒ¯Z°Z޲Z¶Z·Z‘¹Z’»Z“½Z”ÀZ•ÁZ–ÂZ—ÅZ˜ÇZ™ÈZšÉZ›ÊZœÍZÐZžÒZŸÓZ ÔZ¡QÇZ¢Q–Z£Q¢Z¤Q¥Z¥‹ Z¦‹¦Z§‹§Z¨‹ªZ©‹´Zª‹µZ«‹·Z¬‹ÂZ­‹ÃZ®‹ËZ¯‹ÏZ°‹ÎZ±‹ÒZ²‹ÓZ³‹ÔZ´‹ÖZµ‹ØZ¶‹ÙZ·‹ÜZ¸‹ßZ¹‹àZº‹äZ»‹èZ¼‹éZ½‹îZ¾‹ðZ¿‹óZÀ‹öZÁ‹ùZ‹üZËÿZÄŒZÅŒZÆŒZÇŒZÈŒ ZÉŒZÊŒZËŒZÌŒZÍŒZÎŒZÏŒZÐŒZÑŒZÒŒZÓŒZÔŒ ZÕŒ!ZÖŒ%Z׌'ZØŒ*ZÙŒ+ZÚŒ.ZÛŒ/ZÜŒ2ZÝŒ3ZÞŒ5Zߌ6ZàSiZáSzZâ–Zã–"Zä–!Zå–1Zæ–*Zç–=Zè–[€Ž?[ŽC[‚ŽE[ƒŽF[„ŽL[…ŽM[†ŽN[‡ŽO[ˆŽP[‰ŽS[ŠŽT[‹ŽU[ŒŽV[ŽW[ŽŽX[ŽZ[Ž[[‘Ž\[’Ž][“Ž^[”Ž_[•Ž`[–Ža[—Žb[˜Žc[™Žd[šŽe[›Žg[œŽh[Žj[žŽk[ŸŽn[ Žq[¡¸[¢°[£Ï[¤Å[¥¾[¦Ð[§Ä[¨Ç[©Ó[ªæ[«â[¬Ü[­×[®Û[¯ë[°ï[±þ[²‘[³‘"[´‘[µ‘#[¶‘1[·‘/[¸‘9[¹‘C[º‘F[»R [¼YB[½R¢[¾R¬[¿R­[ÀR¾[ÁTÿ[ÂRÐ[ÃRÖ[ÄRð[ÅSß[Æqî[ÇwÍ[È^ô[ÉQõ[ÊQü[Ë›/[ÌS¶[Í_[ÎuZ[Ï]ï[ÐWL[ÑW©[ÒW¡[ÓX~[ÔX¼[ÕXÅ[ÖXÑ[×W)[ØW,[ÙW*[ÚW3[ÛW9[ÜW.[ÝW/[ÞW\[ßW;[àWB[áWi[âW…[ãWk[äW†[åW|[æW{[çWh[èWm[éWv[êWs[ëW­[ìW¤[íWŒ[îW²[ïWÏ[ðW§[ñW´[òW“[óW [ôWÕ[õWØ[öWÚ[÷WÙ[øWÒ[ùW¸[úWô[ûWï[üWø[ýWä[þWÝ\@Žs\AŽu\BŽw\CŽx\DŽy\EŽz\FŽ{\GŽ}\HŽ~\IŽ€\JŽ‚\KŽƒ\LŽ„\Mކ\NŽˆ\Oމ\PŽŠ\QŽ‹\RŽŒ\SŽ\TŽŽ\UŽ‘\VŽ’\WŽ“\XŽ•\YŽ–\ZŽ—\[Ž˜\\Ž™\]Žš\^Ž›\_Ž\`ŽŸ\aŽ \bŽ¡\cŽ¢\dŽ£\eޤ\fŽ¥\gަ\hާ\iލ\jŽ©\kŽª\lŽ­\mŽ®\nް\oޱ\p޳\qŽ´\r޵\s޶\tŽ·\uޏ\v޹\wŽ»\x޼\y޽\z޾\{Ž¿\|ŽÀ\}ŽÁ\~ŽÂ\€ŽÃ\ŽÄ\‚ŽÅ\ƒŽÆ\„ŽÇ\…ŽÈ\†ŽÉ\‡ŽÊ\ˆŽË\‰ŽÌ\ŠŽÍ\‹ŽÏ\ŒŽÐ\ŽÑ\ŽŽÒ\ŽÓ\ŽÔ\‘ŽÕ\’ŽÖ\“Ž×\”ŽØ\•ŽÙ\–ŽÚ\—ŽÛ\˜ŽÜ\™ŽÝ\šŽÞ\›Žß\œŽà\Žá\žŽâ\ŸŽã\ Žä\¡X \¢X \£Wý\¤Wí\¥X\¦X\§X\¨XD\©X \ªXe\«Xl\¬X\­X‰\®Xš\¯X€\°™¨\±Ÿ\²aÿ\³‚y\´‚}\µ‚\¶‚\·‚Š\¸‚¨\¹‚„\º‚Ž\»‚‘\¼‚—\½‚™\¾‚«\¿‚¸\À‚¾\Á‚°\‚È\ÂÊ\Ä‚ã\Å‚˜\Æ‚·\Ç‚®\È‚Ë\É‚Ì\Ê‚Á\Ë‚©\Ì‚´\Í‚¡\΂ª\Ï‚Ÿ\ЂÄ\Ñ‚Î\Ò‚¤\Ó‚á\Ôƒ \Õ‚÷\Ö‚ä\׃\؃\Ù‚Ü\Ú‚ô\Û‚Ò\Ü‚Ø\݃ \Þ‚û\ß‚Ó\àƒ\áƒ\âƒ\ãƒ\äƒ\å‚à\æ‚Õ\çƒ\èƒQ\éƒ[\êƒ\\ëƒ\샒\íƒ<\îƒ4\ïƒ1\ðƒ›\ñƒ^\òƒ/\óƒO\ôƒG\õƒC\öƒ_\÷ƒ@\øƒ\ùƒ`\úƒ-\ûƒ:\üƒ3\ýƒf\þƒe]@Žå]AŽæ]BŽç]CŽè]DŽé]EŽê]FŽë]GŽì]HŽí]IŽî]JŽï]KŽð]LŽñ]MŽò]NŽó]OŽô]PŽõ]QŽö]RŽ÷]SŽø]TŽù]UŽú]VŽû]WŽü]XŽý]YŽþ]ZŽÿ][]\]]]^]_]`]a]b]c]d ]e ]f ]g ]h ]i]j]k]l]m]n]o]p]q]r]s]t]u]v]w]x]y]z]{ ]|!]}"]~#]€$]%]‚&]ƒ']„(]…)]†*]‡+]ˆ,]‰-]Š.]‹/]Œ0]1]Ž2]3]4]‘5]’6]“7]”8]•9]–:]—;]˜<]™=]š>]›?]œ@]A]žB]ŸC] D]¡ƒh]¢ƒ]£ƒi]¤ƒl]¥ƒj]¦ƒm]§ƒn]¨ƒ°]©ƒx]ªƒ³]«ƒ´]¬ƒ ]­ƒª]®ƒ“]¯ƒœ]°ƒ…]±ƒ|]²ƒ¶]³ƒ©]´ƒ}]µƒ¸]¶ƒ{]·ƒ˜]¸ƒž]¹ƒ¨]ºƒº]»ƒ¼]¼ƒÁ]½„]¾ƒå]¿ƒØ]ÀX]Á„]„ ]ÃÝ]ăý]ŃÖ]Æ„]Ç„8]È„]É„]ʃÔ]˃ß]Ì„]Í„]΃ø]σù]Ѓê]уÅ]ÒƒÀ]Ó„&]Ôƒð]Õƒá]Ö„\]ׄQ]Ø„Z]Ù„Y]Ú„s]Û„‡]Ü„ˆ]Ý„z]Þ„‰]ß„x]à„<]á„F]â„i]ã„v]䄌]儎]æ„1]ç„m]è„Á]é„Í]ê„Ð]ë„æ]섽]í„Ó]î„Ê]ï„¿]ð„º]ñ„à]ò„¡]ó„¹]ô„´]õ„—]ö„å]÷„ã]ø… ]ùu ]ú…8]û„ð]ü…9]ý…]þ…:^@E^AF^BG^CH^DI^EJ^FK^GL^HM^IN^JO^KP^LQ^MR^NS^OT^PU^QV^RW^SX^TY^UZ^V[^W\^X]^Y^^Z_^[`^\a^]b^^c^_d^`e^aj^b€^cŒ^d’^e^f ^g¡^h¢^i¤^j¥^k¦^l§^mª^n¬^o­^p®^q¯^r²^s³^t´^uµ^v·^w¸^xº^y»^z¼^{¿^|À^}Ã^~Æ^€É^Ê^‚Ë^ƒÌ^„Í^…Ï^†Ò^‡Ö^ˆ×^‰Ú^Šà^‹á^Œã^ç^Žì^ï^ñ^‘ò^’ô^“õ^”ö^•ú^–û^—ü^˜þ^™ÿ^š^›^œ ^^ž^Ÿ^ ^¡…V^¢…;^£„ÿ^¤„ü^¥…Y^¦…H^§…h^¨…d^©…^^ª…z^«w¢^¬…C^­…r^®…{^¯…¤^°…¨^±…‡^²…^³…y^´…®^µ…œ^¶……^·…¹^¸…·^¹…°^º…Ó^»…Á^¼…Ü^½…ÿ^¾†'^¿†^À†)^Á†^†<^Ã^þ^Ä_^ÅY<^ÆYA^Ç€7^ÈYU^ÉYZ^ÊYX^ËS^Ì\"^Í\%^Î\,^Ï\4^ÐbL^Ñbj^ÒbŸ^Ób»^ÔbÊ^ÕbÚ^Öb×^×bî^Øc"^Ùbö^Úc9^ÛcK^ÜcC^Ýc­^Þcö^ßcq^àcz^ácŽ^âc´^ãcm^äc¬^åcŠ^æci^çc®^èc¼^écò^êcø^ëcà^ìcÿ^ícÄ^îcÞ^ïcÎ^ðdR^ñcÆ^òc¾^ódE^ôdA^õd ^öd^÷d ^ød ^ùd&^úd!^ûd^^üd„^ýdm^þd–_@_A_B#_C$_D%_E'_F(_G)_H*_I+_J,_K0_L1_M2_N3_O4_P7_Q9_R:_S=_T?_U@_VC_WE_XF_YH_ZI_[J_\K_]L_^N__T_`U_aV_bY_cZ_d\_e]_f^_g__h`_ia_jd_kf_lg_mi_nj_ok_pl_qo_rp_sq_tr_us_vv_ww_xx_yy_zz_{{_||_}~_~_€„_…_‚†_ƒ‡_„‰_…Š_†Œ_‡_ˆŽ_‰_Š_‹’_Œ”_–_Ž˜_š_œ_‘ž_’Ÿ_“ _”¤_•¥_–§_—¨_˜©_™«_š­_›²_œ·_¼_ž½_Ÿ¿_ À_¡dz_¢d·_£d¸_¤d™_¥dº_¦dÀ_§dÐ_¨d×_©dä_ªdâ_«e _¬e%_­e._®_ _¯_Ò_°u_±__²S__³Sñ_´Sý_µSé_¶Sè_·Sû_¸T_¹T_ºT_»TK_¼TR_½TS_¾TT_¿TV_ÀTC_ÁT!_ÂTW_ÃTY_ÄT#_ÅT2_ÆT‚_ÇT”_ÈTw_ÉTq_ÊTd_ËTš_ÌT›_ÍT„_ÎTv_ÏTf_ÐT_ÑTÐ_ÒT­_ÓTÂ_ÔT´_ÕTÒ_ÖT§_×T¦_ØTÓ_ÙTÔ_ÚTr_ÛT£_ÜTÕ_ÝT»_ÞT¿_ßTÌ_àTÙ_áTÚ_âTÜ_ãT©_äTª_åT¤_æTÝ_çTÏ_èTÞ_éU_êTç_ëU _ìTý_íU_îTó_ïU"_ðU#_ñU_òU_óU'_ôU*_õUg_öU_÷Uµ_øUI_ùUm_úUA_ûUU_üU?_ýUP_þU<`@Â`AÃ`BÆ`CÈ`DÉ`EË`FÌ`GÍ`HÒ`IÔ`JÕ`KÖ`LØ`MÙ`NÚ`OÞ`Pß`Qà`Rã`Sä`Tå`Ué`Vê`Wì`Xî`Yð`Zñ`[ò`\ó`]õ`^ö`_÷``ù`aú`bû`cü`dÿ`e‘`f‘`g‘`h‘`i‘`j‘`k‘`l‘ `m‘ `n‘ `o‘ `p‘ `q‘`r‘`s‘`t‘`u‘`v‘`w‘`x‘`y‘`z‘`{‘`|‘`}‘`~‘`€‘`‘`‚‘ `ƒ‘!`„‘$`…‘%`†‘&`‡‘'`ˆ‘(`‰‘)`Š‘*`‹‘+`Œ‘,`‘-`Ž‘.`‘0`‘2`‘‘3`’‘4`“‘5`”‘6`•‘7`–‘8`—‘:`˜‘;`™‘<`š‘=`›‘>`œ‘?`‘@`ž‘A`Ÿ‘B` ‘D`¡U7`¢UV`£Uu`¤Uv`¥Uw`¦U3`§U0`¨U\`©U‹`ªUÒ`«Uƒ`¬U±`­U¹`®Uˆ`¯U`°UŸ`±U~`²UÖ`³U‘`´U{`µUß`¶U½`·U¾`¸U”`¹U™`ºUê`»U÷`¼UÉ`½V`¾UÑ`¿Uë`ÀUì`ÁUÔ`ÂUæ`ÃUÝ`ÄUÄ`ÅUï`ÆUå`ÇUò`ÈUó`ÉUÌ`ÊUÍ`ËUè`ÌUõ`ÍUä`Δ`ÏV`ÐV`ÑV `ÒV`ÓV$`ÔV#`ÕUþ`ÖV`×V'`ØV-`ÙVX`ÚV9`ÛVW`ÜV,`ÝVM`ÞVb`ßVY`àV\`áVL`âVT`ãV†`äVd`åVq`æVk`çV{`èV|`éV…`êV“`ëV¯`ìVÔ`íV×`îVÝ`ïVá`ðVõ`ñVë`òVù`óVÿ`ôW`õW `öW `÷W`ø^`ù^`ú^`û^`ü^1`ý^;`þ^aË]4aÌ]=aÍ]laÎ][aÏ]oaÐ]]aÑ]kaÒ]KaÓ]JaÔ]iaÕ]taÖ]‚a×]™aØ]aÙŒsaÚ]·aÛ]ÅaÜ_saÝ_waÞ_‚aß_‡aà_‰aá_Œaâ_•aã_™aä_œaå_¨aæ_­aç_µaè_¼aéˆbaê_aaër­aìr°aír´aîr·aïr¸aðrÃañrÁaòrÎaórÍaôrÒaõrèaörïa÷réaøròaùrôaúr÷aûsaüróaýsaþrúb@‘æbA‘çbB‘èbC‘ébD‘êbE‘ëbF‘ìbG‘íbH‘îbI‘ïbJ‘ðbK‘ñbL‘òbM‘óbN‘ôbO‘õbP‘öbQ‘÷bR‘øbS‘ùbT‘úbU‘ûbV‘übW‘ýbX‘þbY‘ÿbZ’b[’b\’b]’b^’b_’b`’ba’bb’bc’ bd’ be’ bf’ bg’ bh’bi’bj’bk’bl’bm’bn’bo’bp’bq’br’bs’bt’bu’bv’bw’bx’by’bz’ b{’!b|’"b}’#b~’$b€’%b’&b‚’'bƒ’(b„’)b…’*b†’+b‡’,bˆ’-b‰’.bŠ’/b‹’0bŒ’1b’2bŽ’3b’4b’5b‘’6b’’7b“’8b”’9b•’:b–’;b—’bš’?b›’@bœ’Ab’Bbž’CbŸ’Db ’Eb¡rûb¢sb£sb¤s!b¥s b¦sb§sb¨sb©s"bªs9b«s%b¬s,b­s8b®s1b¯sPb°sMb±sWb²s`b³slb´sobµs~b¶‚b·Y%b¸˜çb¹Y$bºYb»™cb¼™gb½™hb¾™ib¿™jbÀ™kbÁ™lb™tbÙwbÄ™}bÅ™€bÆ™„bÇ™‡bÈ™ŠbÉ™bÊ™bË™‘bÌ™“bÍ™”bΙ•bÏ^€bÐ^‘bÑ^‹bÒ^–bÓ^¥bÔ^ bÕ^¹bÖ^µb×^¾bØ^³bÙSbÚ^ÒbÛ^ÑbÜ^ÛbÝ^èbÞ^êbߺbà_Äbá_Ébâ_Öbã_Ïbä`bå_îbæ`bç_ábè_äbé_þbê`bë`bì_êbí_íbî_øbï`bð`5bñ`&bò`bó`bô` bõ`)bö`+b÷` bø`?bù`!bú`xbû`ybü`{bý`zbþ`Bc@’FcA’GcB’HcC’IcD’JcE’KcF’LcG’McH’NcI’OcJ’PcK’QcL’RcM’ScN’TcO’UcP’VcQ’WcR’XcS’YcT’ZcU’[cV’\cW’]cX’^cY’_cZ’`c[’ac\’bc]’cc^’dc_’ec`’fca’gcb’hcc’icd’jce’kcf’lcg’mch’nci’ocj’pck’qcl’rcm’scn’uco’vcp’wcq’xcr’ycs’zct’{cu’|cv’}cw’~cx’cy’€cz’c{’‚c|’ƒc}’„c~’…c€’†c’‡c‚’ˆcƒ’‰c„’Šc…’‹c†’Œc‡’cˆ’c‰’cŠ’‘c‹’’cŒ’“c’”cŽ’•c’–c’—c‘’˜c’’™c“’šc”’›c•’œc–’c—’žc˜’Ÿc™’ cš’¡c›’¢cœ’£c’¤cž’¥cŸ’¦c ’§c¡`jc¢`}c£`–c¤`šc¥`­c¦`c§`ƒc¨`’c©`Œcª`›c«`ìc¬`»c­`±c®`Ýc¯`Øc°`Æc±`Úc²`´c³a c´a&cµac¶a#c·`ôc¸ac¹acºa+c»aJc¼auc½a¬c¾a”c¿a§cÀa·cÁaÔcÂaõcÃ_ÝcÄ–³cÅ•écÆ•ëcÇ•ñcÈ•ócÉ•õcÊ•öcË•ücÌ•þcÍ–cΖcÏ–cЖcÑ– cÒ– cÓ– cÔ– cÕ–cÖ–c×–cØ–cÙ–cÚ–cÛ–cÜN,cÝr?cÞbcßl5càlTcál\câlJcãl£cäl…cålcæl”cçlŒcèlhcélicêltcëlvcìl†cíl©cîlÐcïlÔcðl­cñl÷còløcólñcôl×cõl²cölàc÷lÖcølúcùlëcúlîcûl±cülÓcýlïcþlþd@’¨dA’©dB’ªdC’«dD’¬dE’­dF’¯dG’°dH’±dI’²dJ’³dK’´dL’µdM’¶dN’·dO’¸dP’¹dQ’ºdR’»dS’¼dT’½dU’¾dV’¿dW’ÀdX’ÁdY’ÂdZ’Ãd[’Äd\’Åd]’Æd^’Çd_’Éd`’Êda’Ëdb’Ìdc’Ídd’Îde’Ïdf’Ðdg’Ñdh’Òdi’Ódj’Ôdk’Õdl’Ödm’×dn’Ødo’Ùdp’Údq’Ûdr’Üds’Ýdt’Þdu’ßdv’àdw’ádx’âdy’ãdz’äd{’åd|’æd}’çd~’èd€’éd’êd‚’ëdƒ’ìd„’íd…’îd†’ïd‡’ðdˆ’ñd‰’òdŠ’ód‹’ôdŒ’õd’ödŽ’÷d’ød’ùd‘’úd’’ûd“’üd”’ýd•’þd–’ÿd—“d˜“d™“dš“d›“dœ“d“dž“dŸ“d “ d¡m9d¢m'd£m d¤mCd¥mHd¦md§md¨md©mdªm+d«mMd¬m.d­m5d®md¯mOd°mRd±mTd²m3d³m‘d´modµmžd¶m d·m^d¸m“d¹m”dºm\d»m`d¼m|d½mcd¾nd¿mÇdÀmÅdÁmÞdÂndÃm¿dÄmàdÅndÆmædÇmÝdÈmÙdÉndÊm«dËn dÌm®dÍn+dÎnndÏnNdÐnkdÑn²dÒn_dÓn†dÔnSdÕnTdÖn2d×n%dØnDdÙnßdÚn±dÛn˜dÜnàdÝo-dÞnâdßn¥dàn§dán½dân»dãn·dän×dån´dænÏdçndènÂdénŸdêobdëoFdìoGdío$dîodïnùdðo/dño6dòoKdóotdôo*dõo döo)d÷o‰døodùoŒdúoxdûordüo|dýozdþoÑe@“ eA“ eB“ eC“ eD“eE“eF“eG“eH“eI“eJ“eK“eL“eM“eN“eO“eP“eQ“eR“eS“eT“eU“eV“ eW“!eX“"eY“#eZ“$e[“%e\“&e]“'e^“(e_“)e`“*ea“+eb“,ec“-ed“.ee“/ef“0eg“1eh“2ei“3ej“4ek“5el“6em“7en“8eo“9ep“:eq“;er“gß•gàsŽgás‘gâs®gãs¢gäsŸgåsÏgæsÂgçsÑgès·gés³gêsÀgësÉgìsÈgísågîsÙgï˜|gðt gñségòsçgósÞgôsºgõsògötg÷t*gøt[gùt&gút%gût(güt0gýt.gþt,h@”/hA”0hB”1hC”2hD”3hE”4hF”5hG”6hH”7hI”8hJ”9hK”:hL”;hM”hðhJhñhIhòh)hóhµhôhhõhthöhwh÷h“høhkhùhÂhúinhûhühüihýi hþhùi@•'iA•3iB•=iC•CiD•HiE•KiF•UiG•ZiH•`iI•niJ•tiK•uiL•wiM•xiN•yiO•ziP•{iQ•|iR•}iS•~iT•€iU•iV•‚iW•ƒiX•„iY•…iZ•†i[•‡i\•ˆi]•‰i^•Ši_•‹i`•Œia•ib•Žic•id•ie•‘if•’ig•“ih•”ii••ij•–ik•—il•˜im•™in•šio•›ip•œiq•ir•žis•Ÿit• iu•¡iv•¢iw•£ix•¤iy•¥iz•¦i{•§i|•¨i}•©i~•ªi€•«i•¬i‚•­iƒ•®i„•¯i…•°i†•±i‡•²iˆ•³i‰•´iŠ•µi‹•¶iŒ•·i•¸iŽ•¹i•ºi•»i‘•¼i’•½i“•¾i”•¿i••Ài–•Ái—•Âi˜•Ãi™•Äiš•Åi›•Æiœ•Çi•Èiž•ÉiŸ•Êi •Ëi¡i$i¢hði£i i¤ii¥iWi¦hãi§ii¨iqi©i9iªi`i«iBi¬i]i­i„i®iki¯i€i°i˜i±ixi²i4i³iÌi´i‡iµiˆi¶iÎi·i‰i¸ifi¹iciºiyi»i›i¼i§i½i»i¾i«i¿i­iÀiÔiÁi±iÂiÁiÃiÊiÄißiÅi•iÆiàiÇiiÈiÿiÉj/iÊiíiËjiÌjiÍjeiÎiòiÏjDiÐj>iÑj iÒjPiÓj[iÔj5iÕjŽiÖjyi×j=iØj(iÙjXiÚj|iÛj‘iÜjiÝj©iÞj—ißj«iàs7iásRiâkiãk‚iäk‡iåk„iæk’içk“ièkiékšiêk›iëk¡iìkªiíkiîmiïqiðriñsiòuióviôxiõwiöyi÷ziø|iù~iúiû‚iü„iý‡iþ‹j@•ÌjA•ÍjB•ÎjC•ÏjD•ÐjE•ÑjF•ÒjG•ÓjH•ÔjI•ÕjJ•ÖjK•×jL•ØjM•ÙjN•ÚjO•ÛjP•ÜjQ•ÝjR•ÞjS•ßjT•àjU•ájV•âjW•ãjX•äjY•åjZ•æj[•çj\•ìj]•ÿj^–j_–j`–ja–jb–jc– jd–#je–$jf–%jg–&jh–'ji–(jj–)jk–+jl–,jm–-jn–/jo–0jp–7jq–8jr–9js–:jt–>ju–Ajv–Cjw–Jjx–Njy–Ojz–Qj{–Rj|–Sj}–Vj~–Wj€–Xj–Yj‚–Zjƒ–\j„–]j…–^j†–`j‡–cjˆ–ej‰–fjŠ–kj‹–mjŒ–nj–ojŽ–pj–qj–sj‘–xj’–yj“–zj”–{j•–|j––}j—–~j˜–j™–€jš–j›–‚jœ–ƒj–„jž–‡jŸ–‰j –Šj¡j¢Žj£j¤˜j¥šj¦ŽÎj§b j¨bj©bjªbj«b"j¬b!j­b%j®b$j¯b,j°çj±tïj²tôj³tÿj´ujµuj¶uj·e4j¸eîj¹eïjºeðj»f j¼fj½grj¾fj¿fjÀfjÁp…jÂf÷jÃfjÄf4jÅf1jÆf6jÇf5jÈ€jÉf_jÊfTjËfAjÌfOjÍfVjÎfajÏfWjÐfwjÑf„jÒfŒjÓf§jÔfjÕf¾jÖfÛj×fÜjØfæjÙféjÚ2jÛ3jÜ6jÝ;jÞ=jß@jàEjáFjâHjãIjäGjåMjæUjçYjè‰Çjé‰Êjê‰Ëjë‰Ìjì‰Îjí‰Ïjî‰Ðjï‰ÑjðrnjñrŸjòr]jórfjôrojõr~jörj÷r„jør‹jùrjúrjûr’jücjýc2jþc°k@–ŒkA–ŽkB–‘kC–’kD–“kE–•kF––kG–škH–›kI–kJ–žkK–ŸkL– kM–¡kN–¢kO–£kP–¤kQ–¥kR–¦kS–¨kT–©kU–ªkV–«kW–¬kX–­kY–®kZ–¯k[–±k\–²k]–´k^–µk_–·k`–¸ka–ºkb–»kc–¿kd–Âke–Ãkf–Èkg–Êkh–Ëki–Ðkj–Ñkk–Ókl–Ôkm–Ökn–×ko–Økp–Ùkq–Úkr–Ûks–Ükt–Ýku–Þkv–ßkw–ákx–âky–ãkz–äk{–åk|–æk}–çk~–ëk€–ìk–ík‚–îkƒ–ðk„–ñk…–òk†–ôk‡–õkˆ–øk‰–úkŠ–ûk‹–ükŒ–ýk–ÿkŽ—k—k—k‘— k’— k“— k”—k•—k–—k——k˜—k™—kš—k›—kœ—k—kž—kŸ—k — k¡d?k¢dØk£€k¤kêk¥kók¦kýk§kõk¨kùk©lkªlk«lk¬l k­lk®lk¯lk°lk±l!k²l)k³l$k´l*kµl2k¶e5k·eUk¸ekk¹rMkºrRk»rVk¼r0k½†bk¾Rk¿€ŸkÀ€œkÁ€“k€¼kÃg kÄ€½kÅ€±kÆ€«kÇ€­kÈ€´kÉ€·kÊ€çkË€èkÌ€ékÍ€êk΀ÛkÏ€ÂkЀÄkÑ€ÙkÒ€ÍkÓ€×kÔgkÕ€ÝkÖ€ëk×€ñkØ€ôkÙ€íkÚ kÛkÜ€òkÝ€ükÞgkßkàŒZká6kâkã,käkå2kæHkçLkèSkétkêYkëZkìqkí`kîikï|kð}kñmkògkóXMkôZµkõˆkö‚k÷‘kønÕkù£kúªkûÌküg&kýÊkþ»l@—!lA—"lB—#lC—$lD—%lE—&lF—'lG—(lH—)lI—+lJ—,lK—.lL—/lM—1lN—3lO—4lP—5lQ—6lR—7lS—:lT—;lU—læb=lçbClèbHlébIlêy;lëy@lìyFlíyIlîy[lïy\lðySlñyZlòyblóyWlôy`lõyolöygl÷yzløy…lùyŠlúyšlûy§lüy³lý_Ñlþ_Ðm@—žmA—ŸmB—¡mC—¢mD—¤mE—¥mF—¦mG—§mH—¨mI—©mJ—ªmK—¬mL—®mM—°mN—±mO—³mP—µmQ—¶mR—·mS—¸mT—¹mU—ºmV—»mW—¼mX—½mY—¾mZ—¿m[—Àm\—Ám]—Âm^—Ãm_—Äm`—Åma—Æmb—Çmc—Èmd—Éme—Êmf—Ëmg—Ìmh—Ími—Îmj—Ïmk—Ðml—Ñmm—Òmn—Ómo—Ômp—Õmq—Ömr—×ms—Ømt—Ùmu—Úmv—Ûmw—Ümx—Ýmy—Þmz—ßm{—àm|—ám}—âm~—ãm€—äm—åm‚—èmƒ—îm„—ïm…—ðm†—ñm‡—òmˆ—ôm‰—÷mŠ—øm‹—ùmŒ—úm—ûmŽ—üm—ým—þm‘—ÿm’˜m“˜m”˜m•˜m–˜m—˜m˜˜m™˜mš˜m›˜ mœ˜ m˜ mž˜ mŸ˜ m ˜m¡`np˜?nq˜@nr˜Ans˜Bnt˜Cnu˜Dnv˜Enw˜Fnx˜Gny˜Hnz˜In{˜Jn|˜Kn}˜Ln~˜Mn€˜Nn˜On‚˜Pnƒ˜Qn„˜Rn…˜Sn†˜Tn‡˜Unˆ˜Vn‰˜WnŠ˜Xn‹˜YnŒ˜Zn˜[nŽ˜\n˜]n˜^n‘˜_n’˜`n“˜an”˜bn•˜cn–˜dn—˜en˜˜fn™˜gnš˜hn›˜inœ˜jn˜knž˜lnŸ˜mn ˜nn¡wbn¢wen£wn¤wn¥w}n¦w€n§wŒn¨w‘n©wŸnªw n«w°n¬wµn­w½n®u:n¯u@n°uNn±uKn²uHn³u[n´urnµuyn¶uƒn·Xn¸an¹_nºŠHn»hn¼tn½qn¾yn¿nÀ~nÁvÍnÂvånÈ2nÄ”…nÅ”†nÆ”‡nÇ”‹nÈ”ŠnÉ”ŒnÊ”nË”nÌ”nÍ””nΔ—nÏ”•nДšnÑ”›nÒ”œnÓ”£nÔ”¤nÕ”«nÖ”ªn×”­nØ”¬nÙ”¯nÚ”°nÛ”²nÜ”´nÝ”¶nÞ”·nß”¸nà”¹nᔺn┼n㔽n䔿nå”Änæ”Ènç”Énè”Êné”Ënê”Ìnë”Ínì”Îní”Ðnî”Ñnï”Ònð”Õnñ”Önò”×nó”Ùnô”Ønõ”Ûnö”Þn÷”ßnø”ànù”ânú”änû”ånü”çný”ènþ”êo@˜ooA˜poB˜qoC˜roD˜soE˜toF˜‹oG˜ŽoH˜’oI˜•oJ˜™oK˜£oL˜¨oM˜©oN˜ªoO˜«oP˜¬oQ˜­oR˜®oS˜¯oT˜°oU˜±oV˜²oW˜³oX˜´oY˜µoZ˜¶o[˜·o\˜¸o]˜¹o^˜ºo_˜»o`˜¼oa˜½ob˜¾oc˜¿od˜Àoe˜Áof˜Âog˜Ãoh˜Äoi˜Åoj˜Æok˜Çol˜Èom˜Éon˜Êoo˜Ëop˜Ìoq˜Íor˜Ïos˜Ðot˜Ôou˜Öov˜×ow˜Ûox˜Üoy˜Ýoz˜ào{˜áo|˜âo}˜ão~˜äo€˜åo˜æo‚˜éoƒ˜êo„˜ëo…˜ìo†˜ío‡˜îoˆ˜ïo‰˜ðoŠ˜ño‹˜òoŒ˜óo˜ôoŽ˜õo˜öo˜÷o‘˜øo’˜ùo“˜úo”˜ûo•˜üo–˜ýo—˜þo˜˜ÿo™™oš™o›™oœ™o™ož™oŸ™o ™o¡”éo¢”ëo£”îo¤”ïo¥”óo¦”ôo§”õo¨”÷o©”ùoª”üo«”ýo¬”ÿo­•o®•o¯•o°•o±• o²• o³• o´•oµ•o¶•o·•o¸•o¹•oº•o»•o¼•o½•o¾•o¿•oÀ•"oÁ•*o•+oÕ)oÄ•,oÅ•1oÆ•2oÇ•4oÈ•6oÉ•7oÊ•8oË•oÍ•?oΕBoÏ•5oЕDoÑ•EoÒ•FoÓ•IoÔ•LoÕ•NoÖ•OoוRoØ•SoÙ•ToÚ•VoÛ•WoÜ•XoÝ•YoÞ•[oß•^oà•_oá•]oâ•aoã•boä•doå•eoæ•foç•goè•hoé•ioê•joë•koì•loí•ooî•qoï•roð•soñ•:oòwçoówìoô–ÉoõyÕoöyío÷yãoøyëoùzoú]Goûzoüzoýzoþzp@™pA™ pB™ pC™ pD™ pE™pF™pG™pH™pI™pJ™pK™pL™pM™pN™pO™pP™pQ™pR™pS™pT™pU™pV™ pW™!pX™"pY™#pZ™$p[™%p\™&p]™'p^™(p_™)p`™*pa™+pb™,pc™-pd™/pe™0pf™1pg™2ph™3pi™4pj™5pk™6pl™7pm™8pn™9po™:pp™;pq™pt™?pu™@pv™Apw™Bpx™Cpy™Dpz™Ep{™Fp|™Gp}™Hp~™Ip€™Jp™Kp‚™Lpƒ™Mp„™Np…™Op†™Pp‡™Qpˆ™Rp‰™SpŠ™Vp‹™WpŒ™Xp™YpŽ™Zp™[p™\p‘™]p’™^p“™_p”™`p•™ap–™bp—™dp˜™fp™™spš™xp›™ypœ™{p™~pž™‚pŸ™ƒp ™‰p¡z9p¢z7p£zQp¤žÏp¥™¥p¦zpp§vˆp¨vŽp©v“pªv™p«v¤p¬tÞp­tàp®u,p¯ž p°ž"p±ž(p²ž)p³ž*p´ž+pµž,p¶ž2p·ž1p¸ž6p¹ž8pºž7p»ž9p¼ž:p½ž>p¾žAp¿žBpÀžDpÁžFpžGpÞHpÄžIpÅžKpÆžLpÇžNpÈžQpÉžUpÊžWpËžZpÌž[pÍž\pΞ^pÏžcpОfpÑžgpÒžhpÓžipÔžjpÕžkpÖžlpמqpØžmpÙžspÚu’pÛu”pÜu–pÝu pÞupßu¬pàu£páu³pâu´pãu¸päuÄpåu±pæu°pçuÃpèuÂpéuÖpêuÍpëuãpìuèpíuæpîuäpïuëpðuçpñvpòuñpóuüpôuÿpõvpövp÷vpøv pùvpúv pûv%püvpývpþvq@™ŒqA™ŽqB™šqC™›qD™œqE™qF™žqG™ŸqH™ qI™¡qJ™¢qK™£qL™¤qM™¦qN™§qO™©qP™ªqQ™«qR™¬qS™­qT™®qU™¯qV™°qW™±qX™²qY™³qZ™´q[™µq\™¶q]™·q^™¸q_™¹q`™ºqa™»qb™¼qc™½qd™¾qe™¿qf™Àqg™Áqh™Âqi™Ãqj™Äqk™Åql™Æqm™Çqn™Èqo™Éqp™Êqq™Ëqr™Ìqs™Íqt™Îqu™Ïqv™Ðqw™Ñqx™Òqy™Óqz™Ôq{™Õq|™Öq}™×q~™Øq€™Ùq™Úq‚™Ûqƒ™Üq„™Ýq…™Þq†™ßq‡™àqˆ™áq‰™âqŠ™ãq‹™äqŒ™åq™æqŽ™çq™èq™éq‘™êq’™ëq“™ìq”™íq•™îq–™ïq—™ðq˜™ñq™™òqš™óq›™ôqœ™õq™öqž™÷qŸ™øq ™ùq¡vq¢vq¬v3q­vMq®v^q¯vTq°v\q±vVq²vkq³voq´Êqµzæq¶zxq·zyq¸z€q¹z†qºzˆq»z•q¼z¦q½z q¾z¬q¿z¨qÀz­qÁz³qˆdqÈiqĈrqň}qƈqLj‚qȈ¢qɈÆqʈ·qˈ¼q̈Éq͈âqΈÎqψãqЈåqшñqÒ‰qÓˆüqÔˆèqÕˆþqÖˆðq׉!q؉qÙ‰qÚ‰qÛ‰ q܉4q݉+qÞ‰6q߉Aqà‰fqá‰{qâu‹qã€åqäv²qåv´qæwÜqç€qè€qé€qê€që€ qì€"qí€%qî€&qï€'qð€)qñ€(qò€1qó€ qô€5qõ€Cqö€Fq÷€Mqø€Rqù€iqú€qqû‰ƒqü˜xqý˜€qþ˜ƒr@™úrA™ûrB™ürC™ýrD™þrE™ÿrFšrGšrHšrIšrJšrKšrLšrMšrNšrOš rPš rQš rRš rSš rTšrUšrVšrWšrXšrYšrZšr[šr\šr]šr^šr_šr`šrašrbšrcšrdšrešrfš rgš!rhš"riš#rjš$rkš%rlš&rmš'rnš(roš)rpš*rqš+rrš,rsš-rtš.ruš/rvš0rwš1rxš2ryš3rzš4r{š5r|š6r}š7r~š8r€š9rš:r‚š;rƒšr†š?r‡š@rˆšAr‰šBrŠšCr‹šDrŒšEršFrŽšGršHršIr‘šJr’šKr“šLr”šMr•šNr–šOr—šPr˜šQr™šRrššSr›šTrœšUršVržšWrŸšXr šYr¡˜‰r¢˜Œr£˜r¤˜r¥˜”r¦˜šr§˜›r¨˜žr©˜Ÿrª˜¡r«˜¢r¬˜¥r­˜¦r®†Mr¯†Tr°†lr±†nr²†r³†zr´†|rµ†{r¶†¨r·†r¸†‹r¹†¬rº†r»†§r¼†£r½†ªr¾†“r¿†©rÀ†¶rÁ†Är†µrÆÎrưrņºrƆ±rdž¯rȆÉrɆÏrʆ´rˆér̆ñr͆òrΆírφórІÐrчrÒ†ÞrÓ†ôrÔ†ßrÕ†ØrÖ†Ñrׇr؇rÙ†ørÚ‡rÛ‡ r܇ r݇ rÞ‡#r߇;rà‡rá‡%râ‡.rã‡rä‡>rå‡Hræ‡4rç‡1rè‡)ré‡7rê‡?r뇂rì‡"rí‡}rî‡~rï‡{rð‡`rñ‡prò‡Lró‡nrô‡‹rõ‡Srö‡cr÷‡|rø‡drù‡Yrú‡erû‡“rü‡¯rý‡¨rþ‡Òs@šZsAš[sBš\sCš]sDš^sEš_sFš`sGšasHšbsIšcsJšdsKšesLšfsMšgsNšhsOšisPšjsQšksRšrsSšƒsTš‰sUšsVšŽsWš”sXš•sYš™sZš¦s[š©s\šªs]š«s^š¬s_š­s`š®saš¯sbš²scš³sdš´sešµsfš¹sgš»shš½siš¾sjš¿skšÃslšÄsmšÆsnšÇsošÈspšÉsqšÊsršÍssšÎstšÏsušÐsvšÒswšÔsxšÕsyšÖszš×s{šÙs|šÚs}šÛs~šÜs€šÝsšÞs‚šàsƒšâs„šãs…šäs†šås‡šçsˆšès‰šésŠšês‹šìsŒšîsšðsŽšñsšòsšós‘šôs’šõs“šös”š÷s•šøs–šús—šüs˜šýs™šþsššÿs››sœ›s›sž›sŸ›s ›s¡‡Æs¢‡ˆs£‡…s¤‡­s¥‡—s¦‡ƒs§‡«s¨‡ås©‡¬sª‡µs«‡³s¬‡Ës­‡Ós®‡½s¯‡Ñs°‡Às±‡Ês²‡Ûs³‡ês´‡àsµ‡îs¶ˆs·ˆs¸‡þs¹ˆ sºˆs»ˆ!s¼ˆ9s½ˆs×{sØ{XsÙ{ZsÚ{EsÛ{usÜ{LsÝ{]sÞ{`sß{nsà{{sá{bsâ{rsã{qsä{så{¦sæ{§sç{¸sè{¬sé{sê{¨së{…sì{ªsí{œsî{¢sï{«sð{´sñ{Ñsò{Ásó{Ìsô{Ýsõ{Úsö{ås÷{æsø{êsù| sú{þsû{üsü|sý|sþ| t@›tA› tB› tC› tD› tE› tF›tG›tH›tI›tJ›tK›tL›tM›tN›tO›tP›tQ›tR›tS›tT›tU› tV›!tW›"tX›$tY›%tZ›&t[›'t\›(t]›)t^›*t_›+t`›,ta›-tb›.tc›0td›1te›3tf›4tg›5th›6ti›7tj›8tk›9tl›:tm›=tn›>to›?tp›@tq›Ftr›Jts›Ktt›Ltu›Ntv›Ptw›Rtx›Sty›Utz›Vt{›Wt|›Xt}›Yt~›Zt€›[t›\t‚›]tƒ›^t„›_t…›`t†›at‡›btˆ›ct‰›dtŠ›et‹›ftŒ›gt›htŽ›it›jt›kt‘›lt’›mt“›nt”›ot•›pt–›qt—›rt˜›st™›ttš›ut››vtœ›wt›xtž›ytŸ›zt ›{t¡|t¢|*t£|&t¤|8t¥|At¦|@t§þt¨‚t©‚tª‚t«ìt¬ˆDt­‚!t®‚"t¯‚#t°‚-t±‚/t²‚(t³‚+t´‚8tµ‚;t¶‚3t·‚4t¸‚>t¹‚Dtº‚It»‚Kt¼‚Ot½‚Zt¾‚_t¿‚htÀˆ~tÁˆ…tˆˆtÈØtĈßtʼn^tÆtÇŸtȧtɯtʰt˲tÌ||tÍeItÎ|‘tÏ|tÐ|œtÑ|žtÒ|¢tÓ|²tÔ|¼tÕ|½tÖ|Át×|ÇtØ|ÌtÙ|ÍtÚ|ÈtÛ|ÅtÜ|×tÝ|ètÞ‚ntßf¨tà¿táÎtâÕtãåtäátåætæétçîtèóté|øtê}wtë}¦tì}®tí~Gtî~›ttðž´tñstò„tó”tô‘tõ±tögt÷mtøŒGtùŒItú‘Jtû‘Ptü‘Ntý‘Otþ‘du@›|uA›}uB›~uC›uD›€uE›uF›‚uG›ƒuH›„uI›…uJ›†uK›‡uL›ˆuM›‰uN›ŠuO›‹uP›ŒuQ›uR›ŽuS›uT›uU›‘uV›’uW›“uX›”uY›•uZ›–u[›—u\›˜u]›™u^›šu_››u`›œua›ub›žuc›Ÿud› ue›¡uf›¢ug›£uh›¤ui›¥uj›¦uk›§ul›¨um›©un›ªuo›«up›¬uq›­ur›®us›¯ut›°uu›±uv›²uw›³ux›´uy›µuz›¶u{›·u|›¸u}›¹u~›ºu€›»u›¼u‚›½uƒ›¾u„›¿u…›Àu†›Áu‡›Âuˆ›Ãu‰›ÄuŠ›Åu‹›ÆuŒ›Çu›ÈuŽ›Éu›Êu›Ëu‘›Ìu’›Íu“›Îu”›Ïu•›Ðu–›Ñu—›Òu˜›Óu™›Ôuš›Õu››Öuœ›×u›Øuž›ÙuŸ›Úu ›Ûu¡‘bu¢‘au£‘pu¤‘iu¥‘ou¦‘}u§‘~u¨‘ru©‘tuª‘yu«‘Œu¬‘…u­‘u®‘u¯‘‘u°‘¢u±‘£u²‘ªu³‘­u´‘®uµ‘¯u¶‘µu·‘´u¸‘ºu¹ŒUuºž~u»¸u¼ëu½Žu¾ŽYu¿ŽiuÀµuÁ¿u¼uúuÄÄuÅÖuÆ×uÇÚuÈÞuÉÎuÊÏuËÛuÌÆuÍìuÎ÷uÏøuÐãuÑùuÒûuÓäuÔŽ uÕýuÖŽu׎uØŽuÙŽ,uÚŽ.uÛŽ#uÜŽ/uÝŽ:uÞŽ@uߎ9uàŽ5uáŽ=uâŽ1uãŽIuäŽAuåŽBuæŽQuçŽRuèŽJuéŽpuêŽvuëŽ|uìŽouíŽtuuïŽuðŽ”uñŽuòŽœuóŽžuôŒxuõŒ‚uöŒŠu÷Œ…uøŒ˜uùŒ”uúe›uû‰Öuü‰Þuý‰Úuþ‰Üv@›ÜvA›ÝvB›ÞvC›ßvD›àvE›ávF›âvG›ãvH›ävI›åvJ›ævK›çvL›èvM›évN›êvO›ëvP›ìvQ›ívR›îvS›ïvT›ðvU›ñvV›òvW›óvX›ôvY›õvZ›öv[›÷v\›øv]›ùv^›úv_›ûv`›üva›ývb›þvc›ÿvdœveœvfœvgœvhœviœvjœvkœvlœvmœ vnœ voœ vpœ vqœ vrœvsœvtœvuœvvœvwœvxœvyœvzœv{œv|œv}œv~œv€œvœv‚œvƒœv„œv…œ v†œ!v‡œ"vˆœ#v‰œ$vŠœ%v‹œ&vŒœ'vœ(vŽœ)vœ*vœ+v‘œ,v’œ-v“œ.v”œ/v•œ0v–œ1v—œ2v˜œ3v™œ4všœ5v›œ6vœœ7vœ8vžœ9vŸœ:v œ;v¡‰åv¢‰ëv£‰ïv¤Š>v¥‹&v¦—Sv§–év¨–óv©–ïvª—v«—v¬—v­—v®—v¯—*v°—-v±—0v²—>v³Ÿ€v´ŸƒvµŸ…v¶Ÿ†v·Ÿ‡v¸Ÿˆv¹Ÿ‰vºŸŠv»ŸŒv¼žþv½Ÿ v¾Ÿ v¿–¹vÀ–¼vÁ–½v–ÎvÖÒvÄw¿vÅ–àvÆ’ŽvÇ’®vÈ’ÈvÉ“>vÊ“jvË“ÊvÌ“vÍ”>vΔkvÏœvМ‚vÑœ…vÒœ†vÓœ‡vÔœˆvÕz#vÖœ‹vלŽvØœvÙœ‘vÚœ’vÛœ”vÜœ•vÝœšvÞœ›vßœžvàœŸvᜠv✡v㜢v䜣v圥v朦v眧v蜨v霩vꜫv뜭v윮v휰vvvðœ³vñœ´vòœµvóœ¶vôœ·võœºvöœ»v÷œ¼vøœ½vùœÄvúœÅvûœÆvüœÇvýœÊvþœËw@œwCœ?wDœ@wEœAwFœBwGœCwHœDwIœEwJœFwKœGwLœHwMœIwNœJwOœKwPœLwQœMwRœNwSœOwTœPwUœQwVœRwWœSwXœTwYœUwZœVw[œWw\œXw]œYw^œZw_œ[w`œ\waœ]wbœ^wcœ_wdœ`weœawfœbwgœcwhœdwiœewjœfwkœgwlœhwmœiwnœjwoœkwpœlwqœmwrœnwsœowtœpwuœqwvœrwwœswxœtwyœuwzœvw{œww|œxw}œyw~œzw€œ{wœ}w‚œ~wƒœ€w„œƒw…œ„w†œ‰w‡œŠwˆœŒw‰œwŠœ“w‹œ–wŒœ—wœ˜wŽœ™wœwœªw‘œ¬w’œ¯w“œ¹w”œ¾w•œ¿w–œÀw—œÁw˜œÂw™œÈwšœÉw›œÑwœœÒwœÚwžœÛwŸœàw œáw¡œÌw¢œÍw£œÎw¤œÏw¥œÐw¦œÓw§œÔw¨œÕw©œ×wªœØw«œÙw¬œÜw­œÝw®œßw¯œâw°—|w±—…w²—‘w³—’w´—”wµ—¯w¶—«w·—£w¸—²w¹—´wºš±w»š°w¼š·w½žXw¾š¶w¿šºwÀš¼wÁšÁwšÀwÚÅwÄšÂwÅšËwÆšÌwÇšÑwÈ›EwÉ›CwÊ›GwË›IwÌ›HwÍ›MwΛQwϘèwЙ wÑ™.wÒ™UwÓ™TwÔšßwÕšáwÖšæwךïwØšëwÙšûwÚšíwÛšùwÜ›wÝ›wÞ›wß›wà›#wáž½wâž¾wã~;wäž‚w垇w枈wçž‹wèž’wé“Öwêžw랟wìžÛwížÜwîžÝwïžàwðžßwñžâwòžéwóžçwôžåwõžêwöžïw÷Ÿ"wøŸ,wùŸ/wúŸ9wûŸ7wüŸ=wýŸ>wþŸDx@œãxAœäxBœåxCœæxDœçxEœèxFœéxGœêxHœëxIœìxJœíxKœîxLœïxMœðxNœñxOœòxPœóxQœôxRœõxSœöxTœ÷xUœøxVœùxWœúxXœûxYœüxZœýx[œþx\œÿx]x^x_x`xaxbxcxdxexf xg xh xi xj xkxlxmxnxoxpxqxrxsxtxuxvxwxxxyxzx{x|x} x~!x€"x#x‚$xƒ%x„&x…'x†(x‡)xˆ*x‰+xŠ,x‹-xŒ.x/xŽ0x1x2x‘3x’4x“5x”6x•7x–8x—9x˜:x™;xšx?xž@xŸAx Bx¡â4x¢â5x£â6x¤â7x¥â8x¦â9x§â:x¨â;x©âx¬â?x­â@x®âAx¯âBx°âCx±âDx²âEx³âFx´âGxµâHx¶âIx·âJx¸âKx¹âLxºâMx»âNx¼âOx½âPx¾âQx¿âRxÀâSxÁâTxÂâUxÃâVxÄâWxÅâXxÆâYxÇâZxÈâ[xÉâ\xÊâ]xËâ^xÌâ_xÍâ`xÎâaxÏâbxÐâcxÑâdxÒâexÓâfxÔâgxÕâhxÖâix×âjxØâkxÙâlxÚâmxÛânxÜâoxÝâpxÞâqxßârxàâsxáâtxââuxãâvxäâwxåâxxæâyxçâzxèâ{xéâ|xêâ}xëâ~xìâxíâ€xîâxïâ‚xðâƒxñâ„xòâ…xóâ†xôâ‡xõâˆxöâ‰x÷âŠxøâ‹xùâŒxúâxûâŽxüâxýâxþâ‘y@CyADyBEyCFyDGyEHyFIyGJyHKyILyJMyKNyLOyMPyNQyORyPSyQTyRUySVyTWyUXyVYyWZyX[yY\yZ]y[^y\_y]`y^ay_by`cyadybeycfydgyehyfiygjyhkyilyjmyknyloympynqyorypsyqtyruysvytwyuxyvyywzyx{yy|yz}y{~y|y}€y~y€‚yƒy‚„yƒ…y„†y…‡y†ˆy‡‰yˆŠy‰‹yŠŒy‹yŒŽyyŽy‘y’y‘“y’”y“•y”–y•—y–˜y—™y˜šy™›yšœy›yœžyŸyž yŸ¡y ¢y¡â’y¢â“y£â”y¤â•y¥â–y¦â—y§â˜y¨â™y©âšyªâ›y«âœy¬ây­âžy®âŸy¯â y°â¡y±â¢y²â£y³â¤y´â¥yµâ¦y¶â§y·â¨y¸â©y¹âªyºâ«y»â¬y¼â­y½â®y¾â¯y¿â°yÀâ±yÁâ²yÂâ³yÃâ´yÄâµyÅâ¶yÆâ·yÇâ¸yÈâ¹yÉâºyÊâ»yËâ¼yÌâ½yÍâ¾yÎâ¿yÏâÀyÐâÁyÑâÂyÒâÃyÓâÄyÔâÅyÕâÆyÖâÇy×âÈyØâÉyÙâÊyÚâËyÛâÌyÜâÍyÝâÎyÞâÏyßâÐyàâÑyáâÒyââÓyãâÔyäâÕyåâÖyæâ×yçâØyèâÙyéâÚyêâÛyëâÜyìâÝyíâÞyîâßyïâàyðâáyñââyòâãyóâäyôâåyõâæyöâçy÷âèyøâéyùâêyúâëyûâìyüâíyýâîyþâïz@£zA¤zB¥zC¦zD§zE¨zF©zGªzH«zI¬zJ­zK®zL¯zM°zN±zO²zP³zQ´zRµzS¶zT·zU¸zV¹zWºzX»zY¼zZ½z[¾z\¿z]Àz^Áz_Âz`ÃzaÄzbÅzcÆzdÇzeÈzfÉzgÊzhËziÌzjÍzkÎzlÏzmÐznÑzoÒzpÓzqÔzrÕzsÖzt×zuØzvÙzwÚzxÛzyÜzzÝz{Þz|ßz}àz~áz€âzãz‚äzƒåz„æz…çz†èz‡ézˆêz‰ëzŠìz‹ízŒîzïzŽðzñzòz‘óz’ôz“õz”öz•÷z–øz—ùz˜úz™ûzšüz›ýzœþzÿzžžzŸžz žz¡âðz¢âñz£âòz¤âóz¥âôz¦âõz§âöz¨â÷z©âøzªâùz«âúz¬âûz­âüz®âýz¯âþz°âÿz±ãz²ãz³ãz´ãzµãz¶ãz·ãz¸ãz¹ãzºã z»ã z¼ã z½ã z¾ã z¿ãzÀãzÁãzÂãzÃãzÄãzÅãzÆãzÇãzÈãzÉãzÊãzËãzÌãzÍãzÎãzÏãzÐãzÑã zÒã!zÓã"zÔã#zÕã$zÖã%z×ã&zØã'zÙã(zÚã)zÛã*zÜã+zÝã,zÞã-zßã.zàã/záã0zâã1zãã2zäã3zåã4zæã5zçã6zèã7zéã8zêã9zëã:zìã;zíãzðã?zñã@zòãAzóãBzôãCzõãDzöãEz÷ãFzøãGzùãHzúãIzûãJzüãKzýãLzþãM{@ž{Až{Bž{Cž{Dž{Ež{Fž {Gž {Hž {Iž {Jž {Kž{Lž{Mž{Nž{Ož{Pž{Qž{Rž{Sž{Tž{Už{Vž{Wž{Xž{Yž{Zž{[ž{\ž${]ž'{^ž.{_ž0{`ž4{až;{bž<{cž@{džM{ežP{fžR{gžS{hžT{ižV{jžY{kž]{lž_{mž`{nža{ožb{pže{qžn{ržo{sžr{tžt{užu{vžv{wžw{xžx{yžy{zžz{{ž{{|ž|{}ž}{~ž€{€ž{žƒ{‚ž„{ƒž…{„ž†{…ž‰{†žŠ{‡žŒ{ˆž{‰žŽ{Šž{‹ž{Œž‘{ž”{Žž•{ž–{ž—{‘ž˜{’ž™{“žš{”ž›{•žœ{–žž{—ž {˜ž¡{™ž¢{šž£{›ž¤{œž¥{ž§{žž¨{Ÿž©{ žª{¡ãN{¢ãO{£ãP{¤ãQ{¥ãR{¦ãS{§ãT{¨ãU{©ãV{ªãW{«ãX{¬ãY{­ãZ{®ã[{¯ã\{°ã]{±ã^{²ã_{³ã`{´ãa{µãb{¶ãc{·ãd{¸ãe{¹ãf{ºãg{»ãh{¼ãi{½ãj{¾ãk{¿ãl{Àãm{Áãn{Âão{Ããp{Äãq{Åãr{Æãs{Çãt{Èãu{Éãv{Êãw{Ëãx{Ìãy{Íãz{Îã{{Ïã|{Ðã}{Ñã~{Òã{Óã€{Ôã{Õã‚{Öãƒ{×ã„{Øã…{Ùã†{Úã‡{Ûãˆ{Üã‰{ÝãŠ{Þã‹{ßãŒ{àã{áãŽ{âã{ãã{äã‘{åã’{æã“{çã”{èã•{éã–{êã—{ëã˜{ìã™{íãš{îã›{ïãœ{ðã{ñãž{òãŸ{óã {ôã¡{õã¢{öã£{÷ã¤{øã¥{ùã¦{úã§{ûã¨{üã©{ýãª{þã«|@ž«|Až¬|Bž­|Cž®|Dž¯|Ež°|Fž±|Gž²|Hž³|Ižµ|Jž¶|Kž·|Lž¹|Mžº|Nž¼|Ož¿|PžÀ|QžÁ|RžÂ|SžÃ|TžÅ|UžÆ|VžÇ|WžÈ|XžÊ|YžË|ZžÌ|[žÐ|\žÒ|]žÓ|^žÕ|_žÖ|`ž×|ažÙ|bžÚ|cžÞ|džá|ežã|fžä|gžæ|hžè|ižë|jžì|kží|lžî|mžð|nžñ|ožò|pžó|qžô|ržõ|sžö|tž÷|užø|vžú|wžý|xžÿ|yŸ|zŸ|{Ÿ||Ÿ|}Ÿ|~Ÿ|€Ÿ|Ÿ|‚Ÿ|ƒŸ |„Ÿ |…Ÿ |†Ÿ|‡Ÿ|ˆŸ|‰Ÿ|ŠŸ|‹Ÿ|ŒŸ|Ÿ|ŽŸ|Ÿ|Ÿ|‘Ÿ|’Ÿ|“Ÿ!|”Ÿ#|•Ÿ$|–Ÿ%|—Ÿ&|˜Ÿ'|™Ÿ(|šŸ)|›Ÿ*|œŸ+|Ÿ-|žŸ.|ŸŸ0| Ÿ1|¡ã¬|¢ã­|£ã®|¤ã¯|¥ã°|¦ã±|§ã²|¨ã³|©ã´|ªãµ|«ã¶|¬ã·|­ã¸|®ã¹|¯ãº|°ã»|±ã¼|²ã½|³ã¾|´ã¿|µãÀ|¶ãÁ|·ãÂ|¸ãÃ|¹ãÄ|ºãÅ|»ãÆ|¼ãÇ|½ãÈ|¾ãÉ|¿ãÊ|ÀãË|ÁãÌ|ÂãÍ|ÃãÎ|ÄãÏ|ÅãÐ|ÆãÑ|ÇãÒ|ÈãÓ|ÉãÔ|ÊãÕ|ËãÖ|Ìã×|ÍãØ|ÎãÙ|ÏãÚ|ÐãÛ|ÑãÜ|ÒãÝ|ÓãÞ|Ôãß|Õãà|Öãá|×ãâ|Øãã|Ùãä|Úãå|Ûãæ|Üãç|Ýãè|Þãé|ßãê|àãë|áãì|âãí|ããî|äãï|åãð|æãñ|çãò|èãó|éãô|êãõ|ëãö|ìã÷|íãø|îãù|ïãú|ðãû|ñãü|òãý|óãþ|ôãÿ|õä|öä|÷ä|øä|ùä|úä|ûä|üä|ýä|þä }@Ÿ2}AŸ3}BŸ4}CŸ5}DŸ6}EŸ8}FŸ:}GŸ<}HŸ?}IŸ@}JŸA}KŸB}LŸC}MŸE}NŸF}OŸG}PŸH}QŸI}RŸJ}SŸK}TŸL}UŸM}VŸN}WŸO}XŸR}YŸS}ZŸT}[ŸU}\ŸV}]ŸW}^ŸX}_ŸY}`ŸZ}aŸ[}bŸ\}cŸ]}dŸ^}eŸ_}fŸ`}gŸa}hŸb}iŸc}jŸd}kŸe}lŸf}mŸg}nŸh}oŸi}pŸj}qŸk}rŸl}sŸm}tŸn}uŸo}vŸp}wŸq}xŸr}yŸs}zŸt}{Ÿu}|Ÿv}}Ÿw}~Ÿx}€Ÿy}Ÿz}‚Ÿ{}ƒŸ|}„Ÿ}}…Ÿ~}†Ÿ}‡Ÿ‚}ˆŸ}‰ŸŽ}ŠŸ}‹Ÿ}ŒŸ‘}Ÿ’}ŽŸ“}Ÿ”}Ÿ•}‘Ÿ–}’Ÿ—}“Ÿ˜}”Ÿœ}•Ÿ}–Ÿž}—Ÿ¡}˜Ÿ¢}™Ÿ£}šŸ¤}›Ÿ¥}œù,}ùy}žù•}Ÿùç} ùñ}¡ä }¢ä }£ä }¤ä }¥ä}¦ä}§ä}¨ä}©ä}ªä}«ä}¬ä}­ä}®ä}¯ä}°ä}±ä}²ä}³ä}´ä}µä}¶ä}·ä }¸ä!}¹ä"}ºä#}»ä$}¼ä%}½ä&}¾ä'}¿ä(}Àä)}Áä*}Âä+}Ãä,}Ää-}Åä.}Æä/}Çä0}Èä1}Éä2}Êä3}Ëä4}Ìä5}Íä6}Îä7}Ïä8}Ðä9}Ñä:}Òä;}Óä<}Ôä=}Õä>}Öä?}×ä@}ØäA}ÙäB}ÚäC}ÛäD}ÜäE}ÝäF}ÞäG}ßäH}àäI}áäJ}âäK}ãäL}ääM}åäN}æäO}çäP}èäQ}éäR}êäS}ëäT}ìäU}íäV}îäW}ïäX}ðäY}ñäZ}òä[}óä\}ôä]}õä^}öä_}÷ä`}øäa}ùäb}úäc}ûäd}üäe}ýäf}þäg~@ú ~Aú ~Bú~Cú~Dú~Eú~Fú~Gú~Hú~Iú ~Jú!~Kú#~Lú$~Mú'~Nú(~Oú)~Pè~Qè~Rè~Sè~Tè~Uè~Vè~Wè~Xè~Yè~Zè~[è ~\è!~]è"~^è#~_è$~`è%~aè&~bè'~cè(~dè)~eè*~fè+~gè,~hè-~iè.~jè/~kè0~lè1~mè2~nè3~oè4~pè5~qè6~rè7~sè8~tè9~uè:~vè;~wè<~xè=~yè>~zè?~{è@~|èA~}èB~~èC~€èD~èE~‚èF~ƒèG~„èH~…èI~†èJ~‡èK~ˆèL~‰èM~ŠèN~‹èO~ŒèP~èQ~ŽèR~èS~èT~‘èU~’èV~“èW~”èX~•èY~–èZ~—è[~˜è\~™è]~šè^~›è_~œè`~èa~žèb~Ÿèc~ èd~¡äh~¢äi~£äj~¤äk~¥äl~¦äm~§än~¨äo~©äp~ªäq~«är~¬äs~­ät~®äu~¯äv~°äw~±äx~²äy~³äz~´ä{~µä|~¶ä}~·ä~~¸ä~¹ä€~ºä~»ä‚~¼äƒ~½ä„~¾ä…~¿ä†~Àä‡~Áäˆ~Âä‰~ÃäŠ~Ää‹~ÅäŒ~Æä~ÇäŽ~Èä~Éä~Êä‘~Ëä’~Ìä“~Íä”~Îä•~Ïä–~Ðä—~Ñä˜~Òä™~Óäš~Ôä›~Õäœ~Öä~×äž~ØäŸ~Ùä ~Úä¡~Ûä¢~Üä£~Ýä¤~Þä¥~ßä¦~àä§~áä¨~âä©~ãäª~ää«~åä¬~æä­~çä®~èä¯~éä°~êä±~ëä²~ìä³~íä´~îäµ~ïä¶~ðä·~ñä¸~òä¹~óäº~ôä»~õä¼~öä½~÷ä¾~øä¿~ùäÀ~úäÁ~ûäÂ~üäÃ~ýäÄ~þäÅscreen-4.1.0/utf8encodings/c60000644000175000017500000000010411642704565014053 0ustar abeabeScreenI2UTF8Æ ISO-8859-7¡½¢¼¯ ´„€¶†¸ˆ€ºмŒ¾Ž€ÿÏscreen-4.1.0/utf8encodings/c80000644000175000017500000000005011642704565014055 0ustar abeabeScreenI2UTF8ÈISO-8859-8ß àЀúêscreen-4.1.0/utf8encodings/010000644000175000017500000007216011642704565013776 0ustar abeabeScreenI2UTF8GB 2312-80!!0!"0!#0!$0û!%É!&Ç!'¨!(0!)0!* !+ÿ^!, !- &!. !/ !0 !1 !20!30!40!50 !60 !70 !80 !90 !:0!;0!<0!=0!>0!?0!@±!A×!B÷!C"6!D"'!E"(!F"!G"!H"*!I")!J"!K"7!L"!M"¥!N"%!O" !P#!Q"™!R"+!S".!T"a!U"L!V"H!W"=!X"!Y"`!Z"n!["o!\"d!]"e!^"!_"5!`"4!a&B!b&@!c°!d 2!e 3!f!!gÿ!h¤!iÿà!jÿá!k 0!l§!m!!n&!o&!p%Ë!q%Ï!r%Î!s%Ç!t%Æ!u%¡!v% !w%³!x%²!y ;!z!’!{!!|!‘!}!“!~0"1$ˆ"2$‰"3$Š"4$‹"5$Œ"6$"7$Ž"8$"9$":$‘";$’"<$“"=$”">$•"?$–"@$—"A$˜"B$™"C$š"D$›"E$t"F$u"G$v"H$w"I$x"J$y"K$z"L${"M$|"N$}"O$~"P$"Q$€"R$"S$‚"T$ƒ"U$„"V$…"W$†"X$‡"Y$`"Z$a"[$b"\$c"]$d"^$e"_$f"`$g"a$h"b$i"e2 "f2!"g2""h2#"i2$"j2%"k2&"l2'"m2("n2)"q!`"r!a"s!b"t!c"u!d"v!e"w!f"x!g"y!h"z!i"{!j"|!k#!ÿ#"ÿ##ÿ#$ÿå#%ÿ#&ÿ#'ÿ#(ÿ#)ÿ #*ÿ #+ÿ #,ÿ #-ÿ #.ÿ#/ÿ#0ÿ#1ÿ#2ÿ#3ÿ#4ÿ#5ÿ#6ÿ#7ÿ#8ÿ#9ÿ#:ÿ#;ÿ#<ÿ#=ÿ#>ÿ#?ÿ#@ÿ #Aÿ!#Bÿ"#Cÿ##Dÿ$#Eÿ%#Fÿ&#Gÿ'#Hÿ(#Iÿ)#Jÿ*#Kÿ+#Lÿ,#Mÿ-#Nÿ.#Oÿ/#Pÿ0#Qÿ1#Rÿ2#Sÿ3#Tÿ4#Uÿ5#Vÿ6#Wÿ7#Xÿ8#Yÿ9#Zÿ:#[ÿ;#\ÿ<#]ÿ=#^ÿ>#_ÿ?#`ÿ@#aÿA#bÿB#cÿC#dÿD#eÿE#fÿF#gÿG#hÿH#iÿI#jÿJ#kÿK#lÿL#mÿM#nÿN#oÿO#pÿP#qÿQ#rÿR#sÿS#tÿT#uÿU#vÿV#wÿW#xÿX#yÿY#zÿZ#{ÿ[#|ÿ\#}ÿ]#~ÿã$!0A$"0B$#0C$$0D$%0E$&0F$'0G$(0H$)0I$*0J$+0K$,0L$-0M$.0N$/0O$00P$10Q$20R$30S$40T$50U$60V$70W$80X$90Y$:0Z$;0[$<0\$=0]$>0^$?0_$@0`$A0a$B0b$C0c$D0d$E0e$F0f$G0g$H0h$I0i$J0j$K0k$L0l$M0m$N0n$O0o$P0p$Q0q$R0r$S0s$T0t$U0u$V0v$W0w$X0x$Y0y$Z0z$[0{$\0|$]0}$^0~$_0$`0€$a0$b0‚$c0ƒ$d0„$e0…$f0†$g0‡$h0ˆ$i0‰$j0Š$k0‹$l0Œ$m0$n0Ž$o0$p0$q0‘$r0’$s0“%!0¡%"0¢%#0£%$0¤%%0¥%&0¦%'0§%(0¨%)0©%*0ª%+0«%,0¬%-0­%.0®%/0¯%00°%10±%20²%30³%40´%50µ%60¶%70·%80¸%90¹%:0º%;0»%<0¼%=0½%>0¾%?0¿%@0À%A0Á%B0Â%C0Ã%D0Ä%E0Å%F0Æ%G0Ç%H0È%I0É%J0Ê%K0Ë%L0Ì%M0Í%N0Î%O0Ï%P0Ð%Q0Ñ%R0Ò%S0Ó%T0Ô%U0Õ%V0Ö%W0×%X0Ø%Y0Ù%Z0Ú%[0Û%\0Ü%]0Ý%^0Þ%_0ß%`0à%a0á%b0â%c0ã%d0ä%e0å%f0æ%g0ç%h0è%i0é%j0ê%k0ë%l0ì%m0í%n0î%o0ï%p0ð%q0ñ%r0ò%s0ó%t0ô%u0õ%v0ö&!‘&"’&#“&$”&%•&&–&'—&(˜&)™&*š&+›&,œ&-&.ž&/Ÿ&0 &1¡&2£&3¤&4¥&5¦&6§&7¨&8©&A±&B²&C³&D´&Eµ&F¶&G·&H¸&I¹&Jº&K»&L¼&M½&N¾&O¿&PÀ&QÁ&RÃ&SÄ&TÅ&UÆ&VÇ&WÈ&XÉ'!'"'#'$'%'&'''(')'*'+','-'.'/'0'1'2 '3!'4"'5#'6$'7%'8&'9'':(';)'<*'=+'>,'?-'@.'A/'Q0'R1'S2'T3'U4'V5'WQ'X6'Y7'Z8'[9'\:'];'^<'_='`>'a?'b@'cA'dB'eC'fD'gE'hF'iG'jH'kI'lJ'mK'nL'oM'pN'qO(!("á(#Î($à(%(&é('((è()+(*í(+Ð(,ì(-M(.ó(/Ò(0ò(1k(2ú(3Ô(4ù(5Ö(6Ø(7Ú(8Ü(9ü(:ê(E1(F1(G1(H1(I1 (J1 (K1 (L1 (M1 (N1(O1(P1(Q1(R1(S1(T1(U1(V1(W1(X1(Y1(Z1([1(\1(]1(^1(_1(`1 (a1!(b1"(c1#(d1$(e1%(f1&(g1'(h1((i1))$%)%%)&%)'%)(%))%)*%)+%),%)-% ).% )/% )0% )1% )2%)3%)4%)5%)6%)7%)8%)9%):%);%)<%)=%)>%)?%)@%)A%)B%)C%)D% )E%!)F%")G%#)H%$)I%%)J%&)K%')L%()M%))N%*)O%+)P%,)Q%-)R%.)S%/)T%0)U%1)V%2)W%3)X%4)Y%5)Z%6)[%7)\%8)]%9)^%:)_%;)`%<)a%=)b%>)c%?)d%@)e%A)f%B)g%C)h%D)i%E)j%F)k%G)l%H)m%I)n%J)o%K0!UJ0"–?0#WÃ0$c(0%TÎ0&U 0'TÀ0(v‘0)vL0*…<0+wî0,‚~0-x0.r10/–˜00—01l(02[‰03Oú04c 05f—06\¸07€ú08hH09€®0:f0;vÎ0q¬0?ñ0@ˆ„0AP²0BYe0CaÊ0Do³0E‚­0FcL0GbR0HSí0IT'0J{0KQk0Lu¤0M]ô0NbÔ0OË0P—v0QbŠ0R€0SW]0T—80Ub0Vr80Wv}0XgÏ0Yv~0ZdF0[Op0\%0]bÜ0^z0_e‘0`sí0ad,0bbs0c‚,0d˜0eg0frH0gbn0hbÌ0iO40jtã0kSJ0lRž0m~Ê0n¦0o^.0ph†0qiœ0r€0s~Ñ0thÒ0uxÅ0v†Œ0w•Q0xP0yŒ$0z‚Þ0{€Þ0|S0}‰0~Re1!…„1"–ù1#OÝ1$X!1%™q1&[1'b±1(b¥1)f´1*Œy1+œ1,r1-go1.x‘1/`²10SQ11S12ˆ13€Ì1415”¡16P 17rÈ18Y19`ë1:q1;ˆ«1g,1?{(1@])1A~÷1Bu-1Clõ1DŽf1Eø1F<1GŸ;1HkÔ1I‘1J{1K_|1Lx§1M„Ö1N…=1OkÕ1PkÙ1QkÖ1R^1S^‡1Tuù1U•í1Ve]1W_ 1X_Å1YŸ1ZXÁ1[Â1\1]–[1^—­1_¹1`1a,1bbA1cO¿1dSØ1eS^1f¨1g©1h«1iM1jh1k_j1l˜1mˆh1nœÖ1oa‹1pR+1qv*1r_l1seŒ1toÒ1unè1v[¾1wdH1xQu1yQ°1zgÄ1{N1|yÉ1}™|1~p³2!uÅ2"^v2#s»2$ƒà2%d­2&bè2'”µ2(lâ2)SZ2*RÃ2+d2,”Â2-{”2.O/2/^20‚62122Š23n$24lÊ25šs26cU27S\28Tú29ˆe2:Wà2;N 2<^2=ke2>|?2?è2@`2Adæ2Bs2CˆÁ2DgP2EbM2F"2Gwl2HŽ)2I‘Ç2J_i2KƒÜ2L…!2M™2NSÂ2O†•2Pk‹2Q`í2R`è2Sp2T‚Í2U‚12VNÓ2Wl§2X…Ï2YdÍ2Z|Ù2[iý2\fù2]ƒI2^S•2_{V2`O§2aQŒ2bmK2c\B2dŽm2ecÒ2fSÉ2gƒ,2hƒ62igå2jx´2kd=2l[ß2m\”2n]î2o‹ç2pbÆ2qgô2rŒz2sd2tcº2u‡I2v™‹2wŒ2x 2y”ò2zN§2{–2|˜¤2}f 2~s3!W:3"\3#^83$•3%P3&€ 3'S‚3(e^3)uE3*U13+P!3,…3-b„3.”ž3/g30V231on32]â33T534p’35f36bo37d¤38c£39_{3:oˆ3;ô3<ã3=°3>\3?fh3@_ñ3Al‰3B–H3C3Dˆl3Ed‘3Fyð3GWÎ3HjY3Ib3JTH3KNX3Lz 3M`é3No„3O‹Ú3Pb3Q3Rš‹3Syä3TT3Uuô3Vc3WS3Xl`3Yß3Z_3[šp3\€;3]Ÿ3^Oˆ3_\:3`d3aÅ3be¥3cp½3dQE3eQ²3f†k3g]3h[ 3ib½3j‘l3kut3lŽ 3mz 3na3o{y3pNÇ3q~ø3rw…3sN3tí3uR3vQú3wjq3xS¨3yއ3z•3{–Ï3|nÁ3}–d3~iZ4!x@4"P¨4#w×4$d4%‰æ4&Y4'cã4(]Ý4)z4*i=4+O 4,‚94-U˜4.N24/u®40z—41^b42^Š43•ï44R45T946pŠ47cv48•$49W‚4:f%4;i?4<‘‡4=U4>mó4?~¯4@ˆ"4Ab34B~ð4Cuµ4Dƒ(4ExÁ4F–Ì4Gž4HaH4It÷4J‹Í4Kkd4LR:4MP4Nk!4O€j4P„q4QVñ4RS4SNÎ4TN4UQÑ4V|—4W‘‹4X|4YOÃ4ZŽ4[{á4\zœ4]dg4^]4_P¬4`4av4b|¹4cmì4dà4egQ4f[X4g[ø4hxË4id®4jd4kcª4lc+4m•4nd-4o¾4p{T4qv)4rbS4sY'4tTF4uky4vP£4wb44x^&4yk†4zNã4{74|ˆ‹4}_…4~.5!` 5"€=5#bÅ5$N95%SU5&ø5'c¸5(€Æ5)eæ5*l.5+OF5,`î5-má5.‹Þ5/_950†Ë51_S52c!53QZ54ƒa55hc56R57cc58ŽH59P5:\›5;yw5<[ü5=R05>z;5?`¼5@S5Av×5B_·5C_—5Dv„5EŽl5Fpo5Gv{5H{I5Iwª5JQó5K“5LX$5MON5Nnô5Oê5PeL5Q{5RrÄ5Sm¤5Tß5UZá5Vbµ5W^•5XW05Y„‚5Z{,5[^5\_5]5^5_˜ 5`c‚5anÇ5bx˜5cp¹5dQx5e—[5fW«5gu55hOC5iu85j^—5k`æ5lY`5mmÀ5nk¿5ox‰5pSü5q–Õ5rQË5sR5tc‰5uT 5v”“5wŒ5xÌ5yr95zxŸ5{‡v5|í5}Œ 5~Sà6!N6"vï6#Sî6$”‰6%˜v6&Ÿ6'•-6([š6)‹¢6*N"6+N6,Q¬6-„c6.aÂ6/R¨60h 61O—62`k63Q»64m65Q\66b–67e—68–a69ŒF6:6;uØ6<ý6=wc6>kÒ6?rŠ6@rì6A‹û6BX56Cwy6DL6Eg\6F•@6G€š6H^¦6In!6JY’6Kzï6Lwí6M•;6Nkµ6Oe­6P6QX6RQQ6S–6T[ù6UX©6VT(6WŽr6Xef6Y˜6ZVä6[”6\vþ6]A6^c‡6_TÆ6`Y6aY:6bW›6c޲6dg56eú6f‚56gRA6h`ð6iX6j†þ6k\è6lžE6mOÄ6n˜6o‹¹6pZ%6q`v6rS„6sb|6tO6u‘6v™6w`i6x€ 6yQ?6z€36{\6|™u6}m16~NŒ7!07"SÑ7#Z7${O7%O7&NO7'–7(lÕ7)sÐ7*…é7+^7,uj7-û7.j 7/wþ70”’71~A72Qá73pæ74SÍ75Ô76ƒ77)78r¯79™m7:lÛ7;WJ7<‚³7=e¹7>€ª7?b?7@–27AY¨7BNÿ7C‹¿7D~º7Ee>7Fƒò7G—^7HUa7I˜Þ7J€¥7KS*7L‹ý7MT 7N€º7O^Ÿ7Pl¸7Q97R‚¬7S‘Z7TT)7Ul7VR7W~·7XW_7Yq7Zl~7[|‰7\YK7]Ný7^_ÿ7_a$7`|ª7aN07b\7cg«7d‡7e\ð7f• 7g˜Î7hu¯7ipý7j"7kQ¯7l7m‹½7nYI7oQä7pO[7qT&7rY+7sew7t€¤7u[u7vbv7wbÂ7x7y^E7zl7{{&7|O7}OØ7~g 8!mn8"mª8#y8$ˆ±8%_8&u+8'bš8(…8)Oï8*‘Ü8+e§8,/8-Q8.^œ8/P80t81Ro82‰†83K84Y 85P…86NØ87–88r689y8:8;[Ì8<‹£8=–D8>Y‡8?8@T8AVv8BV8C‹å8De98Ei‚8F”™8GvÖ8Hn‰8I^r8Ju8KgF8LgÑ8Mzÿ8N€8Ov8Pa8QyÆ8Reb8Sc8TQˆ8UR8V”¢8W88X€›8Y~²8Z\—8[n/8\g`8]{Ù8^v‹8_šØ8`8a”8b|Õ8cd8d•P8ez?8fTJ8gTå8hkL8id8jb8kž=8l€ó8mu™8nRr8o—i8p„[8qh<8r†ä8s–8t–”8u”ì8vN*8wT8x~Ù8yh98zß8{€8|fô8}^š8~¹9!WÂ9"€?9#h—9$]å9%e;9&RŸ9'`m9(Ÿš9)O›9*ެ9+Ql9,[«9-_9.]é9/l^90bñ91!92Qq93”©94Rþ95lŸ96‚ß97r×98W¢99g„9:-9;Y9<œ9=ƒÇ9>T•9?{9@O09Al½9B[d9CYÑ9DŸ9ESä9F†Ê9Gš¨9HŒ79I€¡9JeE9K˜~9LVú9M–Ç9NR.9OtÜ9PRP9Q[á9Rc9S‰9TNV9UbÐ9V`*9Whú9XQs9Y[˜9ZQ 9[‰Â9\{¡9]™†9^P9_`ï9`pL9a/9bQI9c^9d9etp9f‰Ä9gW-9hxE9i_R9jŸŸ9k•ú9lh9m›<9n‹á9ovx9phB9qgÜ9rê9s59tR=9uŠ9vnÚ9whÍ9x•9yí9zVý9{gœ9|ˆù9}Ç9~TÈ:!š¸:"[i:#mw:$l&:%N¥:&[³:'š‡:(‘c:)a¨:*¯:+—é:,T+:-mµ:.[Ò:/Qý:0UŠ:1U:2ð:3d¼:4cM:5eñ:6a¾:7`:8q :9lW::lI:;Y/:XÕ:?VŽ:@Œj:Akë:BÝ:CY}:D€:ES÷:Fmi:GTu:HU:Iƒw:JƒÏ:Kh8:Ly¾:MTŒ:NOU:OT:PvÒ:QŒ‰:R–:Sl³:Tm¸:Uk:V‰:Wžd:X::YV?:ZžÑ:[uÕ:\_ˆ:]rà:^`h:_Tü:`N¨:aj*:bˆa:c`R:dp:eTÄ:fpØ:g†y:hž?:im*:j[:k_:l~¢:mU‰:nO¯:os4:pT<:qSš:rP:sT:tT|:uNN:v_ý:wtZ:xXö:y„k:z€á:{‡t:|rÐ:}|Ê:~nV;!_';"†N;#U,;$b¤;%N’;&lª;'b7;(‚±;)T×;*SN;+s>;,nÑ;-u;;.R;/S;0‹Ý;1iÐ;2_Š;3`;4mî;5WO;6k";7s¯;8hS;9Ø;:;;cb;<`£;=U$;>uê;?Œb;@q;Am£;B[¦;C^{;DƒR;EaL;FžÄ;Gxú;H‡W;I|';Jv‡;KQð;L`ö;MqL;NfC;O^L;P`M;QŒ;Rpp;Sc%;T‰;U_½;V`b;W†Ô;XVÞ;YkÁ;Z`”;[ag;\SI;]`à;^ff;_?;`yý;aO;bpé;clG;d‹³;e‹ò;f~Ø;gƒd;hf;iZZ;j›B;kmQ;lm÷;mŒA;nm;;oO;ppk;qƒ·;rb;s`Ñ;t— ;u';vyx;wQû;xW>;yWú;zg:;{ux;|z=;}yï;~{•[cš„=?Z=@V¼=Ad=B”ð=Cwë=DO¥=E=Frá=G‰Ò=H™z=I4=J~Þ=KR=LeY=M‘u=N=Oƒ=PSë=Qz–=Rcí=Sc¥=Tv†=Uyø=VˆW=W–6=Xb*=YR«=Z‚‚=[hT=\gp=]cw=^wk=_zí=`m=a~Ó=b‰ã=cYÐ=db=e…É=f‚¥=guL=hP=iNË=ju¥=k‹ë=l\J=m]þ=n{K=oe¤=p‘Ñ=qNÊ=rm%=s‰_=t}'=u•&=vNÅ=wŒ(=xÛ=y—s=zfK={y=|Ñ=}pì=~mx>!\=>"R²>#ƒF>$Qb>%ƒ>&w[>'fv>(œ¸>)N¬>*`Ê>+|¾>,|³>-~Ï>.N•>/‹f>0fo>1˜ˆ>2—Y>3Xƒ>4el>5•\>6_„>7uÉ>8—V>9zß>:zÞ>;QÀ>=z˜>>cê>?zv>@~ >As–>B—í>CNE>Dpx>EN]>F‘R>GS©>HeQ>Ieç>Jü>K‚>LTŽ>M\1>Nuš>O— >PbØ>QrÙ>Ru½>S\E>Tšy>UƒÊ>V\@>WT€>Xwé>YN>>Zl®>[€Z>\bÒ>]cn>^]è>_Qw>`Ý>aŽ>b•/>cOñ>dSå>e`ç>fp¬>gRg>hcP>ižC>jZ>kP&>lw7>mSw>n~â>od…>pe+>qb‰>rc˜>sP>tr5>u‰É>vQ³>w‹À>x~Ý>yWG>zƒÌ>{”§>|Q›>}T>~\û?!OÊ?"zã?#mZ?$á?%š?&U€?'T–?(Sa?)T¯?*_?+cé?,iw?-Qï?.ah?/R ?0X*?1RØ?2WN?3x ?4w ?5^·?6aw?7|à?8b[?9b—?:N¢?;p•?<€?=b÷?>pä??—`?@Ww?A‚Û?Bgï?Chõ?DxÕ?E˜—?FyÑ?GXó?HT³?ISï?Jn4?KQK?LR;?M[¢?N‹þ?O€¯?PUC?QW¦?R`s?SWQ?TT-?Uzz?V`P?W[T?Xc§?Yb ?ZSã?[bc?\[Ç?]g¯?^Tí?_zŸ?`‚æ?a‘w?b^“?cˆä?dY8?eW®?fc?gè?h€ï?iWW?j{w?kO©?l_ë?m[½?nk>?oS!?p{P?qrÂ?rhF?swÿ?tw6?ue÷?vQµ?wN?xvÔ?y\¿?zz¥?{„u?|YN?}›A?~P€@!™ˆ@"a'@#nƒ@$Wd@%f@&cF@'Vð@(bì@)bi@*^Ó@+–@,Wƒ@-bÉ@.U‡@/‡!@0J@1£@2Uf@3ƒ±@4ge@5V@6„Ý@7Zj@8h@9bæ@:{î@;–@Œ0@?cý@@‰È@AaÒ@B@CpÂ@Dnå@Et@Fi”@Grü@H^Ê@IÎ@Jg@Kmj@Lc^@MR³@Nrb@O€@POl@QYå@R‘j@SpÙ@Tm@URÒ@VNP@W–÷@X•m@Y…~@ZxÊ@[}/@\Q!@]W’@^dÂ@_€‹@`|{@alê@bhñ@ci^@dQ·@eS˜@fh¨@gr@hžÎ@i{ñ@jrø@ky»@lo@mt@ngN@o‘Ì@pœ¤@qy<@rƒ‰@sƒT@tT@uh@vN=@wS‰@xR±@yx>@zS†@{R)@|Pˆ@}O‹@~OÐA!uâA"zËA#|’A$l¥A%–¶A&R›A'tƒA(TéA)OéA*€TA+ƒ²A,ÞA-•pA.^ÉA/`A0mŸA1^A2e[A38A4”þA5`KA6p¼A7~ÃA8|®A9QÉA:hA;|±A<‚oA=N$A>†A?‘ÏA@f~AAN®ABŒACd©AD€JAEPÚAFu—AGqÎAH[åAI½AJofAKN†ALd‚AM•cAN^ÖAOe™APRAQˆÂARpÈASR£ATsAUt3AVg—AWx÷AX—AYN4AZ»A[œÞA\mËA]QÛA^AA_TA`bÎAas²AbƒñAc–öAdŸ„Ae”ÃAfO6AgšAhQÌAipuAj–uAk\­Al˜†AmSæAnNäAonœApt Aqi´ArxkAs™AtuYAuRAvv$AwmAAxgóAyQmAzŸ™A{€KA|T™A}{b.B?štB@TBA”ÝBBO£BCeÅBD\eBE\aBFBG†QBHl/BI_‹BJs‡BKnäBL~ÿBM\æBNcBO[jBPnæBQSuBRNqBSc BTueBUb¡BVnBWO&BXNÑBYl¦BZ~¶B[‹ºB\„B]‡ºB^WB_;B`•#Ba{©Bbš¡BcˆøBd„=BemBfš†Bg~ÜBhYˆBiž»Bjs›BkxBl†‚BmšlBnš‚BoVBpTBqWËBrNpBsž¦BtSVBuÈBv Bww’Bx™’By†îBznáB{…B|füB}abB~o+C!Œ)C"‚’C#ƒ+C$vòC%lC&_ÙC'ƒ½C(s+C)ƒC*•C+kÛC,wÛC-”ÆC.SoC/ƒC0Q’C1^=C2ŒŒC38C4NHC5s«C6gšC7h…C8‘vC9— C:qdC;l¡C•AC?kÏC@ŽCAf'CB[ÐCCY¹CDZšCE•èCF•÷CGNìCH„ CI„™CJj¬CKvßCL•0CMsCNh¦CO[_CPw/CQ‘šCR—aCS|ÜCT÷CUŒCV_%CW|sCXyØCY‰ÅCZlÌC[‡C\[ÆC]^BC^hÉC_w C`~õCaQ•CbQMCcRÉCdZ)CeCf—bCg‚×ChcÏCiw„Cj…ÐCkyÒCln:Cm^™CnY™Co…CppmCqlCrb¿Csv¿CteOCu`¯Cv•ýCwfCx‡ŸCyž#Cz”íC{T C|T}C}Œ,C~dxD!dyD"†D#j!D$œD%xèD&diD'›TD(b¹D)g+D*ƒ«D+X¨D,žØD-l«D.o D/[ÞD0–LD1Œ D2r_D3gÐD4bÇD5raD6N©D7YÆD8kÍD9X“D:f®D;^UDg(D?vîD@wfDArgDBzFDCbÿDDTêDETPDF” DG£DHZDI~³DJlDKNCDLYvDM€DNYHDOSWDPu7DQ–¾DRVÊDSc DTDU`|DV•ùDWmÖDXTbDY™DZQ…D[ZéD\€ýD]Y®D^—D_P*D`låDa\UjE?´E@r,EA^EB`ECt6EDbÍEEc’EFrLEG_˜EHnCEIm>EJeEKoXELvØEMxÐENvüEOuTEPR$EQSÛERNSES^žETeÁEU€*EV€ÖEWb›EXT†EYR(EZp®E[ˆE\ÑE]láE^TxE_€ÚE`WùEaˆôEbTEc–jEd‘MEeOiEfl›EgU·EhvÆEix0Ejb¨EkpùEloŽEm_mEn„ìEohÚEpx|Eq{÷Er¨Esg EtžOEucgEvx°EwWoExxEy—9EzbyE{b«E|RˆE}t5E~k×F!UdF">F#u²F$v®F%S9F&uÞF'PûF(\AF)‹lF*{ÇF+POF,rGF-š—F.˜ØF/oF0tâF1yhF2d‡F3w¥F4büF5˜‘F6+F7TÁF8€XF9NRF:WjF;‚ùF<„ F=^sF>QíF?töF@‹ÄFA\OFBWaFClüFD˜‡FEZFFFx4FG›DFHëFI|•FJRVFKbQFL”úFMNÆFNƒ†FO„aFPƒéFQ„²FRWÔFSg4FTWFUfnFVmfFWŒ1FXfÝFYpFZgF[k:F\hF]bF^Y»F_NF`QÄFaoFbgÒFclFdQvFehËFfYGFgkgFhufFi]FjFkŸPFle×FmyHFnyAFoš‘FpwFq\‚FrN^FsOFtT/FuYQFvx FwVhFxlFyÄFz_F{l}F|lãF}‹«F~cG!`pG"m=G#ruG$bfG%”ŽG&”ÅG'SCG(ÁG){~G*NßG+Œ&G,N~G-žÔG.”±G/”³G0RMG1o\G2cG3mEG4Œ4G5XG6]LG7k G8kIG9gªG:T[G;TG<ŒG=X™G>…7G?_:G@b¢GAjGGB•9GCerGD`„GEheGFw§GGNTGHO¨GI]çGJ—˜GKd¬GLØGM\íGNOÏGOzGPRGQƒGRNGS`/GTzƒGU”¦GVOµGWN²GXyæGYt4GZRäG[‚¹G\dÒG]y½G^[ÝG_lG`—RGa{Gbl"GcP>GdSGenGfdÎGgftGhl0Gi`ÅGj˜wGk‹÷Gl^†GmtgÓH?täH@XäHAeHBV·HC‹©HD™vHEbpHF~ÕHG`ùHHpíHIXìHJNÁHKNºHL_ÍHM—çHNNûHO‹¤HPRHQYŠHR~«HSbTHTNÍHUeåHVbHWƒ8HX„ÉHYƒcHZ‡H[q”H\n¶H][¹H^~ÒH_Q—H`cÉHagÔHb€‰Hcƒ9HdˆHeQHf[zHgY‚Hh±HiNsHjl]HkQeHl‰%HmoHn–.Ho…JHpt^Hq•Hr•ðHsm¦Ht‚åHu_1Hvd’HwmHx„(HynHzœÃH{X^H|[H}N H~SÁI!OI"ecI#hQI$UÓI%N'I&dI'ššI(bkI)ZÂI*t_I+‚rI,m©I-hîI.PçI/ƒŽI0xI1g@I2R9I3l™I4~±I5P»I6UeI7q^I8{[I9fRI:sÊI;‚ëIR I?q}I@ˆkIA•êIB–UICdÅIDaIE³IFU„IGlUIHbGII.IJX’IKO$ILUFIMOINfLION IP\IQˆóIRh¢IScNITz IUpçIV‚IWRúIX—öIY\IZTèI[µI\~ÍI]YbI^JI_†ÇI`‚ Ia‚ IbfIcdDId\IeaQIfm‰Igy>Ih‹¾Iix7Iju3IkT{IlO8ImŽ«InmñIoZ Ip~ÅIqy^IrlˆIs[¡ItZvIuuIv€¾IwaNIxnIyXðIzuI{u%I|rrI}SGI~~óJ!wJ"vÛJ#RiJ$€ÜJ%W#J&^J'Y1J(rîJ)e½J*nJ+‹×J,\8J-†qJ.SAJ/wóJ0bþJ1eöJ2NÀJ3˜ßJ4†€J5[žJ6‹ÆJ7SòJ8wâJ9OJ:\NJ;švJy:J?XëJ@NJAgÿJBN‹JCbíJDŠ“JEJFR¿JGf/JHUÜJIVlJJJKNÕJLOJM‘ÊJN™pJOlJP^JQ`CJR[¤JS‰ÆJT‹ÕJUe6JVbKJW™–JX[ˆJY[ÿJZcˆJ[U.J\S×J]v&J^Q}J_…,J`g¢Jah³JbkŠJcb’Jd“JeSÔJf‚JgmÑJhuJiNfJjNJk[pJlqŸJm…¯Jnf‘JofÙJprJq‡JržÍJsŸ Jt\^Jug/JvðJwhJxg_Jyb JzzÖJ{X…J|^¶J}epJ~o1K!`UK"R7K#€ K$dTK%ˆpK&u)K'^K(hK)bôK*—K+SÌK,r=K-ŒK.l4K/waK0zK1T.K2w¬K3˜zK4‚K5‹ôK6xUK7gK8pÁK9e¯K:d•K;V6K<`K=yÁK>SøK?NK@k{KA€†KB[úKCUãKDVÛKEO:KFOSùL?p­L@ldLAXXLBd*LCXLDhàLE›LFULG|ÖLHPLIŽºLJmÌLKŸLLpëLMcLNm›LOnÔLP~æLQ„LRhCLSLTmØLU–vLV‹¨LWYWLXryLY…äLZ~L[u¼L\ŠŠL]h¯L^RTL_Ž"L`•LacÐLb˜˜LcŽDLdU|LeOSLffÿLgVLh`ÕLim•LjRCLk\ILlY)LmmûLnXkLou0LpuLq`lLr‚LsFLtcLugaLvâLww:LxóLy4Lz”ÁL{^L|S…L}T,L~pÃM!l@M"^÷M#P\M$N­M%^­M&c:M'‚GM(M)hPM*‘nM+w³M,T M-”ÜM._dM/zåM0hvM1cEM2{RM3~ßM4uÛM5PwM6b•M7Y4M8M9QøM:yÃM;zMM?m‚M@\`MAWMBTMCQTMDnMMEVâMFc¨MG˜“MHMI‡MJ‰*MKMLTMM\oMNÀMObÖMPbXMQ1MRž5MS–@MTšnMUš|MVi-MWY¥MXbÓMYU>MZcM[TÇM\†ÙM]mN3~¬N4g*N5…N6TsN7uON8€ÃN9U‚N:›ON;OMN\ N?apN@SkNAvNBn)NC†ŠNDe‡NE•ûNF~¹NGT;NHz3NI} NJ•îNKUáNLÁNMtîNNcNO‡NPm¡NQzNRbNSe¡NTSgNUcáNVlƒNW]ëNXT\NY”¨NZNLN[laN\‹ìN]\KN^eàN_‚œN`h§NaT>NbT4NckËNdkfNeN”NfcBNgSHNh‚NiO NjO®NkW^Nlb Nm–þNnfdNoriNpRÿNqR¡Nr`ŸNs‹ïNtfNuq™NvgNw‰NxxRNywýNzfpN{V;N|T8N}•!N~rzO!zO"`oO#^ O$`‰O%O&YO'`ÜO(q„O)pïO*nªO+lPO,r€O-j„O.ˆ­O/^-O0N`O1Z³O2UœO3”ãO4mO5|ûO6–™O7bO8~ÆO9wŽO:†~O;S#O<—O=–O>f‡O?\áO@O OAríOBN OCS¦ODYOETOFc€OG•(OHQHOINÙOJœœOK~¤OLT¸OM$ONˆTOO‚7OP•òOQmŽOR_&OSZÌOTf>OU–iOVs°OWs.OXS¿OYzOZ™…O[¡O\[ªO]–wO^–PO_~¿O`vøOaS¢Ob•vOc™™Od{±Oe‰DOfnXOgNaOhÔOiyeOj‹æOk`óOlTÍOmN«On˜yOo]÷OpjaOqPÏOrTOsŒaOt„'Oux]Ov—OwRJOxTîOyV£Oz•O{mˆO|[µO}mÆO~fSP!\P"[]P#h!P$€–P%UxP&{P'eHP(iTP)N›P*kGP+‡NP,—‹P-SOP.cP/d:P0ªP1eœP2€ÁP3ŒP4Q™P5h°P6SxP7‡ùP8aÈP9lÄP:lûP;Œ"P<\QP=…ªP>‚¯P?• P@k#PA›PBe°PC_ûPD_ÃPEOáPFˆEPGfPHePIs)PJ`úPKQtPLRPMW‹PN_bPO¢PPˆLPQ‘’PR^xPSgOPT`'PUYÓPVQDPWQöPX€øPYSPZlyP[–ÄP\qŠP]OP^OîP_žP`g=PaUÅPb•PcyÀPdˆ–Pe~ãPfXŸPgb Ph—Pi†ZPjVPk˜{Pl_Pm‹¸Pn„ÄPo‘WPpSÙPqeíPr^Psu\Pt`dPu}nPvZPw~êPx~íPyiPzU§P{[£P|`¬P}eËP~s„Q! Q"vcQ#w)Q$~ÚQ%—tQ&…›Q'[fQ(ztQ)–êQ*ˆ@Q+RËQ,qQ-_ªQ.eìQ/‹âQ0[ûQ1šoQ2]áQ3k‰Q4l[Q5‹­Q6‹¯Q7 Q8ÅQ9S‹Q:b¼Q;ž&Q<ž-Q=T@Q>N+Q?‚½Q@rYQA†œQB]QCˆYQDm¯QE–ÅQFTÑQGNšQH‹¶QIq QJT½QK– QLpßQMmùQNvÐQON%QPxQQ‡QR\©QS^öQTŠQU˜œQV–QWpŽQXl¿QYYDQZc©Q[wQ{€Q|pQ}Y–Q~tvR!dGR"\'R#eR$z‘R%Œ#R&YÚR'T¬R(‚R)ƒoR*‰R+€R,i0R-VNR.€6R/r7R0‘ÎR1Q¶R2N_R3˜uR4c–R5NR6SöR7fóR8KR9YR:m²R;NRcÖR?”ñR@ORAO RBˆcRC˜RDY7REWRFyûRGNêRH€ðRIu‘RJl‚RK[œRLYèRM_]RNiRO†RPPRQ]òRRNYRSwãRTNåRU‚zRVb‘RWfRX‘RY\yRZN¿R[_yR\ÆR]8R^€„R_u«R`N¦RaˆÔRbaRckÅRd_ÆReNIRfvÊRgn¢Rh‹ãRi‹®RjŒ Rk‹ÑRl_RmüRnÌRo~ÎRpƒ5RqƒkRrVàRsk·Rt—óRu–4RvYûRwTRx”öRymëRz[ÅR{™nR|\9R}_R~–S!SpS"‚ñS#j1S$ZtS%žpS&^”S'(S(ƒ¹S)„$S*„%S+ƒgS,‡GS-ÎS.bS/vÈS0_qS1˜–S2xlS3f S4TßS5båS6OcS7ÃS8uÈS9^¸S:–ÍS;Ž S<†ùS=TS>lóS?mŒS@l8SA`SBRÇSCu(SD^}SEOSF` SG_çSH\$SIu1SJ®SK”ÀSLr¹SMl¹SNn8SO‘ISPg SQSËSRSóSSOQST‘ÉSU‹ñSVSÈSW^|SXÂSYmäSZNŽS[vÂS\i†S]†^S^aS_‚S`OYSaOÞSb>Scœ|Sda SenSfnSg–…ShNˆSiZ1Sj–èSkNSl\Smy¹Sn[‡So‹íSp½Sqs‰SrWßSs‚‹StÁSuTSvGSwU»Sx\êSy_¡SzaS{k2S|rñS}€²S~ЉT!mtT"[ÓT#ˆÕT$˜„T%ŒkT&šmT'ž3T(n T)Q¤T*QCT+W£T,ˆT-SŸT.côT/•T0VíT1TXT2WT3s?T4nT5T6ÜT7‚ÑT8a?T9`(T:–bT;fðT<~¦T=ŠT>ÃT?”¥T@\³TA|¤TBgTC`¦TD–TE€TFN‘TGçTHSTI–hTJQATKÐTL…tTM‘]TNfUTO—õTP[UTQSTRx8TSgBTTh=TUTÉTVp~TW[°TX}TYQTZW(T[T±T\eT]f‚T^^T_CT`Ta„lTbmTc|ßTdQÿTe…ûTfg£TgeéTho¡Ti†¤TjŽTkVjTl Tmv‚TnpvToqåTp#TqbéTrRTslýTtzÙU?n[U@~ýUAjUBzàUC_pUDo3UE_ UFcŒUGm¨UHgVUINUJ^UK&ULN×UM€ÀUNv4UO–œUPbÛUQf-URb~USl¼UTuUUqgUViUWQFUX€‡UYSìUZnU[b˜U\TòU]†ðU^™U_€U`•Ua…UbÙUcmYUdsÍUeeŸUfwUguUhx'UiûUjUk”ˆUlO¦Umg•Unu¹Uo‹ÊUp—Uqc/Ur•GUs–5Ut„¸Uuc#UvwAUw_UxrðUyN‰Uz`U{etU|bïU}kcU~e?V!^'V"uÇV#ÑV$‹ÁV%‚V&gV'e/V(T1V)‡V*wåV+€¢V,V-lAV.NKV/~ÇV0€LV1vôV2i V3k–V4bgV5P_×V?cV@c·VAóVBôVCnVD^VE\ÙVFR6VGfzVHyéVIzVJ(VKp™VLuÔVMnÞVNl»VOz’VPN-VQvÅVR_àVS”ŸVTˆwVU~ÈVVyÍVW€¿VX‘ÍVYNòVZOV[‚V\ThV]]ÞV^m2V_‹ÌV`|¥VatVb€˜Vc^VdT’Vev±Vf[™VgfbÙW?SSW@hLWAt"WBƒWC‘LWDUDWEw@WFp|WGmJWHQyWIT¨WJDWKYÿWLnËWMmÄWN[\WO}+WPNÔWQ|}WRnÓWS[PWTêWUn WV[WWW›WXhÕWYŽ*WZ[—W[~üW\`;W]~µW^¹W_pW`YOWacÍWbyßWc³WdSRWeeÏWfyVWg‹ÅWh–;Wi~ÄWj”»Wk~‚WlV4Wm‘‰WngWojWp\ WquWrf(Ws]æWtOPWugÞWvPZWwO\WxWPWy^§X!NX"N X#Q@X$NX%^ÿX&SEX'NX(N˜X)NX*›2X+[lX,ViX-N(X.yºX/N?X0SX1NGX2Y-X3r;X4SnX5lX6VßX7€äX8™—X9kÓX:w~X;ŸXŸX?N\X@NiXAN“XB‚ˆXC[[XDUlXEVXFNÄXGSXHSXIS£XJS¥XKS®XL—eXM]XNSXOSõXPS&XQS.XRS>XS\XTSfXUScXVRXWRXXRXYR-XZR3X[R?X\R@X]RLX^R^X_RaX`R\Xa„¯XbR}XcR‚XdRXeRXfR“XgQ‚XhTXiN»XjNÃXkNÉXlNÂXmNèXnNáXoNëXpNÞXqOXrNóXsO"XtOdXuNõXvO%XwO'XxO XyO+XzO^X{OgX|e8X}OZX~O]Y!O_Y"OWY#O2Y$O=Y%OvY&OtY'O‘Y(O‰Y)OƒY*OY+O~Y,O{Y-OªY.O|Y/O¬Y0O”Y1OæY2OèY3OêY4OÅY5OÚY6OãY7OÜY8OÑY9OßY:OøY;P)YP,Y?PY@P.YAP-YBOþYCPYDP YEP%YFP(YGP~YHPCYIPUYJPHYKPNYLPlYMP{YNP¥YOP§YPP©YQPºYRPÖYSQYTPíYUPìYVPæYWPîYXQYYQ YZNÝY[l=Y\OXY]OeY^OÎY_Ÿ Y`lFYa|tYbQnYc]ýYdžÉYe™˜YfQYgYYhRùYiS YjŠYkSYlQëYmYYnQUYoN YpQVYqN³YrˆnYsˆ¤YtNµYuYvˆÒYwy€Yx[4YyˆYz¸Y{Q«Y|Q±Y}Q½Y~Q¼Z!QÇZ"Q–Z#Q¢Z$Q¥Z%‹ Z&‹¦Z'‹§Z(‹ªZ)‹´Z*‹µZ+‹·Z,‹ÂZ-‹ÃZ.‹ËZ/‹ÏZ0‹ÎZ1‹ÒZ2‹ÓZ3‹ÔZ4‹ÖZ5‹ØZ6‹ÙZ7‹ÜZ8‹ßZ9‹àZ:‹äZ;‹èZ<‹éZ=‹îZ>‹ðZ?‹óZ@‹öZA‹ùZB‹üZC‹ÿZDŒZEŒZFŒZGŒZHŒ ZIŒZJŒZKŒZLŒZMŒZNŒZOŒZPŒZQŒZRŒZSŒZTŒ ZUŒ!ZVŒ%ZWŒ'ZXŒ*ZYŒ+ZZŒ.Z[Œ/Z\Œ2Z]Œ3Z^Œ5Z_Œ6Z`SiZaSzZb–Zc–"Zd–!Ze–1Zf–*Zg–=Zh–R¬[?R­[@R¾[ATÿ[BRÐ[CRÖ[DRð[ESß[Fqî[GwÍ[H^ô[IQõ[JQü[K›/[LS¶[M_[NuZ[O]ï[PWL[QW©[RW¡[SX~[TX¼[UXÅ[VXÑ[WW)[XW,[YW*[ZW3[[W9[\W.[]W/[^W\[_W;[`WB[aWi[bW…[cWk[dW†[eW|[fW{[gWh[hWm[iWv[jWs[kW­[lW¤[mWŒ[nW²[oWÏ[pW§[qW´[rW“[sW [tWÕ[uWØ[vWÚ[wWÙ[xWÒ[yW¸[zWô[{Wï[|Wø[}Wä[~WÝ\!X \"X \#Wý\$Wí\%X\&X\'X\(XD\)X \*Xe\+Xl\,X\-X‰\.Xš\/X€\0™¨\1Ÿ\2aÿ\3‚y\4‚}\5‚\6‚\7‚Š\8‚¨\9‚„\:‚Ž\;‚‘\<‚—\=‚™\>‚«\?‚¸\@‚¾\A‚°\B‚È\C‚Ê\D‚ã\E‚˜\F‚·\G‚®\H‚Ë\I‚Ì\J‚Á\K‚©\L‚´\M‚¡\N‚ª\O‚Ÿ\P‚Ä\Q‚Î\R‚¤\S‚á\Tƒ \U‚÷\V‚ä\Wƒ\Xƒ\Y‚Ü\Z‚ô\[‚Ò\\‚Ø\]ƒ \^‚û\_‚Ó\`ƒ\aƒ\bƒ\cƒ\dƒ\e‚à\f‚Õ\gƒ\hƒQ\iƒ[\jƒ\\kƒ\lƒ’\mƒ<\nƒ4\oƒ1\pƒ›\qƒ^\rƒ/\sƒO\tƒG\uƒC\vƒ_\wƒ@\xƒ\yƒ`\zƒ-\{ƒ:\|ƒ3\}ƒf\~ƒe]!ƒh]"ƒ]#ƒi]$ƒl]%ƒj]&ƒm]'ƒn](ƒ°])ƒx]*ƒ³]+ƒ´],ƒ ]-ƒª].ƒ“]/ƒœ]0ƒ…]1ƒ|]2ƒ¶]3ƒ©]4ƒ}]5ƒ¸]6ƒ{]7ƒ˜]8ƒž]9ƒ¨]:ƒº];ƒ¼]<ƒÁ]=„]>ƒå]?ƒØ]@X]A„]B„ ]CƒÝ]Dƒý]EƒÖ]F„]G„8]H„]I„]JƒÔ]Kƒß]L„]M„]Nƒø]Oƒù]Pƒê]QƒÅ]RƒÀ]S„&]Tƒð]Uƒá]V„\]W„Q]X„Z]Y„Y]Z„s][„‡]\„ˆ]]„z]^„‰]_„x]`„<]a„F]b„i]c„v]d„Œ]e„Ž]f„1]g„m]h„Á]i„Í]j„Ð]k„æ]l„½]m„Ó]n„Ê]o„¿]p„º]q„à]r„¡]s„¹]t„´]u„—]v„å]w„ã]x… ]yu ]z…8]{„ð]|…9]}…]~…:^!…V^"…;^#„ÿ^$„ü^%…Y^&…H^'…h^(…d^)…^^*…z^+w¢^,…C^-…r^.…{^/…¤^0…¨^1…‡^2…^3…y^4…®^5…œ^6……^7…¹^8…·^9…°^:…Ó^;…Á^<…Ü^=…ÿ^>†'^?†^@†)^A†^B†<^C^þ^D_^EY<^FYA^G€7^HYU^IYZ^JYX^KS^L\"^M\%^N\,^O\4^PbL^Qbj^RbŸ^Sb»^TbÊ^UbÚ^Vb×^Wbî^Xc"^Ybö^Zc9^[cK^\cC^]c­^^cö^_cq^`cz^acŽ^bc´^ccm^dc¬^ecŠ^fci^gc®^hc¼^icò^jcø^kcà^lcÿ^mcÄ^ncÞ^ocÎ^pdR^qcÆ^rc¾^sdE^tdA^ud ^vd^wd ^xd ^yd&^zd!^{d^^|d„^}dm^~d–_!dz_"d·_#d¸_$d™_%dº_&dÀ_'dÐ_(d×_)dä_*dâ_+e _,e%_-e._._ _/_Ò_0u_1__2S__3Sñ_4Sý_5Sé_6Sè_7Sû_8T_9T_:T_;TK_TT_?TV_@TC_AT!_BTW_CTY_DT#_ET2_FT‚_GT”_HTw_ITq_JTd_KTš_LT›_MT„_NTv_OTf_PT_QTÐ_RT­_STÂ_TT´_UTÒ_VT§_WT¦_XTÓ_YTÔ_ZTr_[T£_\TÕ_]T»_^T¿__TÌ_`TÙ_aTÚ_bTÜ_cT©_dTª_eT¤_fTÝ_gTÏ_hTÞ_iU_jTç_kU _lTý_mU_nTó_oU"_pU#_qU_rU_sU'_tU*_uUg_vU_wUµ_xUI_yUm_zUA_{UU_|U?_}UP_~U<`!U7`"UV`#Uu`$Uv`%Uw`&U3`'U0`(U\`)U‹`*UÒ`+Uƒ`,U±`-U¹`.Uˆ`/U`0UŸ`1U~`2UÖ`3U‘`4U{`5Uß`6U½`7U¾`8U”`9U™`:Uê`;U÷`UÑ`?Uë`@Uì`AUÔ`BUæ`CUÝ`DUÄ`EUï`FUå`GUò`HUó`IUÌ`JUÍ`KUè`LUõ`MUä`N”`OV`PV`QV `RV`SV$`TV#`UUþ`VV`WV'`XV-`YVX`ZV9`[VW`\V,`]VM`^Vb`_VY``V\`aVL`bVT`cV†`dVd`eVq`fVk`gV{`hV|`iV…`jV“`kV¯`lVÔ`mV×`nVÝ`oVá`pVõ`qVë`rVù`sVÿ`tW`uW `vW `wW`x^`y^`z^`{^`|^1`}^;`~^\Ëa?\åa@]aA]aB]'aC]&aD].aE]$aF]aG]aH]aI]XaJ]>aK]4aL]=aM]laN][aO]oaP]]aQ]kaR]KaS]JaT]iaU]taV]‚aW]™aX]aYŒsaZ]·a[]Åa\_sa]_wa^_‚a__‡a`_‰aa_Œab_•ac_™ad_œae_¨af_­ag_µah_¼aiˆbaj_aakr­alr°amr´anr·aor¸aprÃaqrÁarrÎasrÍatrÒaurèavrïawréaxròayrôazr÷a{sa|róa}sa~rúb!rûb"sb#sb$s!b%s b&sb'sb(sb)s"b*s9b+s%b,s,b-s8b.s1b/sPb0sMb1sWb2s`b3slb4sob5s~b6‚b7Y%b8˜çb9Y$b:Yb;™cb<™gb=™hb>™ib?™jb@™kbA™lbB™tbC™wbD™}bE™€bF™„bG™‡bH™ŠbI™bJ™bK™‘bL™“bM™”bN™•bO^€bP^‘bQ^‹bR^–bS^¥bT^ bU^¹bV^µbW^¾bX^³bYSbZ^Òb[^Ñb\^Ûb]^èb^^êb_ºb`_Äba_Ébb_Öbc_Ïbd`be_îbf`bg_ábh_äbi_þbj`bk`bl_êbm_íbn_øbo`bp`5bq`&br`bs`bt` bu`)bv`+bw` bx`?by`!bz`xb{`yb|`{b}`zb~`Bc!`jc"`}c#`–c$`šc%`­c&`c'`ƒc(`’c)`Œc*`›c+`ìc,`»c-`±c.`Ýc/`Øc0`Æc1`Úc2`´c3a c4a&c5ac6a#c7`ôc8ac9ac:a+c;aJca”c?a§c@a·cAaÔcBaõcC_ÝcD–³cE•écF•ëcG•ñcH•ócI•õcJ•öcK•ücL•þcM–cN–cO–cP–cQ– cR– cS– cT– cU–cV–cW–cX–cY–cZ–c[–c\N,c]r?c^bc_l5c`lTcal\cblJccl£cdl…celcfl”cglŒchlhcilicjltcklvcll†cml©cnlÐcolÔcpl­cql÷crløcslñctl×cul²cvlàcwlÖcxlúcylëczlîc{l±c|lÓc}lïc~lþd!m9d"m'd#m d$mCd%mHd&md'md(md)md*m+d+mMd,m.d-m5d.md/mOd0mRd1mTd2m3d3m‘d4mod5mžd6m d7m^d8m“d9m”d:m\d;m`dnd?mÇd@mÅdAmÞdBndCm¿dDmàdEndFmædGmÝdHmÙdIndJm«dKn dLm®dMn+dNnndOnNdPnkdQn²dRn_dSn†dTnSdUnTdVn2dWn%dXnDdYnßdZn±d[n˜d\nàd]o-d^nâd_n¥d`n§dan½dbn»dcn·ddn×den´dfnÏdgndhnÂdinŸdjobdkoFdloGdmo$dnodonùdpo/dqo6droKdsotdto*duo dvo)dwo‰dxodyoŒdzoxd{ord|o|d}ozd~oÑe!oÉe"o§e#o¹e$o¶e%oÂe&oáe'oîe(oÞe)oàe*oïe+pe,p#e-pe.p9e/p5e0pOe1p^e2[€e3[„e4[•e5[“e6[¥e7[¸e8u/e9šže:d4e;[äe<[îe=‰0e>[ðe?ŽGe@‹eA¶eBÓeCÕeDåeEîeFäeGéeHæeIóeJèeKeLeM eN&eOeP eQeR!eS5eT6eU-eV/eWDeXQeYReZPe[he\Xe]be^[e_f¹e`tea}eb‚ecˆedƒee‹ef_Peg_Weh_Vei_Xej\;ekT«el\Pem\Yen[qeo\cep\feq¼er_*es_)et_-eu‚tev_Zbf?Zuf@€ìfAZªfBZ›fCZwfDZzfEZ¾fFZëfGZ²fHZÒfIZÔfJZ¸fKZàfLZãfMZñfNZÖfOZæfPZØfQZÜfR[ fS[fT[fU[2fV[7fW[@fX\fY\fZ[Zf[[ef\[sf][Qf^[Sf_[bf`šufašwfbšxfcšzfdšfeš}ffš€fgšfhš…fišˆfjšŠfkšflš’fmš“fnš–foš˜fpš›fqšœfršfsšŸftš fuš¢fvš£fwš¥fxš§fy~Ÿfz~¡f{~£f|~¥f}~¨f~~©g!~­g"~°g#~¾g$~Àg%~Ág&~Âg'~Ég(~Ëg)~Ìg*~Ðg+~Ôg,~×g-~Ûg.~àg/~ág0~èg1~ëg2~îg3~ïg4~ñg5~òg6 g7~ög8~úg9~ûg:~þg;g<g=g>g?g@ gA gBgCgDgEgFgGgHgIgJ!gK"gL#gM$gN%gO&gP'gQ*gR+gS,gT-gU/gV0gW1gX2gY3gZ5g[^zg\ug]]Ûg^u>g_•g`sŽgas‘gbs®gcs¢gdsŸgesÏgfsÂggsÑghs·gis³gjsÀgksÉglsÈgmsågnsÙgo˜|gpt gqségrsçgssÞgtsºgusògvtgwt*gxt[gyt&gzt%g{t(g|t0g}t.g~t,h!th"th#tAh$t\h%tWh&tUh'tYh(twh)tmh*t~h+tœh,tŽh-t€h.th/t‡h0t‹h1tžh2t¨h3t©h4th5t§h6tÒh7tºh8—êh9—ëh:—ìh;gLhgHh?gih@g¥hAg‡hBgjhCgshDg˜hEg§hFguhGg¨hHgžhIg­hJg‹hKgwhLg|hMgðhNh hOgØhPh hQgéhRg°hSh hTgÙhUgµhVgÚhWg³hXgÝhYhhZgÃh[g¸h\gâh]hh^gÁh_gýh`h2hah3hbh`hchahdhNhehbhfhDhghdhhhƒhihhjhUhkhfhlhAhmhghnh@hoh>hphJhqhIhrh)hshµhthhuhthvhwhwh“hxhkhyhÂhzinh{hüh|ih}i h~hùi!i$i"hði#i i$ii%iWi&hãi'ii(iqi)i9i*i`i+iBi,i]i-i„i.iki/i€i0i˜i1ixi2i4i3iÌi4i‡i5iˆi6iÎi7i‰i8ifi9ici:iyi;i›ii«i?i­i@iÔiAi±iBiÁiCiÊiDißiEi•iFiàiGiiHiÿiIj/iJiíiKjiLjiMjeiNiòiOjDiPj>iQj iRjPiSj[iTj5iUjŽiVjyiWj=iXj(iYjXiZj|i[j‘i\ji]j©i^j—i_j«i`s7iasRibkick‚idk‡iek„ifk’igk“ihkiikšijk›ikk¡ilkªimkinmioqipriqsiruisvitxiuwivyiwzix|iy~izi{‚i|„i}‡i~‹j!j"Žj#j$˜j%šj&ŽÎj'b j(bj)bj*bj+b"j,b!j-b%j.b$j/b,j0çj1tïj2tôj3tÿj4uj5uj6uj7e4j8eîj9eïj:eðj;f jfj?fj@fjAp…jBf÷jCfjDf4jEf1jFf6jGf5jH€jIf_jJfTjKfAjLfOjMfVjNfajOfWjPfwjQf„jRfŒjSf§jTfjUf¾jVfÛjWfÜjXfæjYféjZ2j[3j\6j];j^=j_@j`EjaFjbHjcIjdGjeMjfUjgYjh‰Çji‰Êjj‰Ëjk‰Ìjl‰Îjm‰Ïjn‰Ðjo‰ÑjprnjqrŸjrr]jsrfjtrojur~jvrjwr„jxr‹jyrjzrj{r’j|cj}c2j~c°k!d?k"dØk#€k$kêk%kók&kýk'kõk(kùk)lk*lk+lk,l k-lk.lk/lk0lk1l!k2l)k3l$k4l*k5l2k6e5k7eUk8ekk9rMk:rRk;rVkRk?€Ÿk@€œkA€“kB€¼kCg kD€½kE€±kF€«kG€­kH€´kI€·kJ€çkK€èkL€ékM€êkN€ÛkO€ÂkP€ÄkQ€ÙkR€ÍkS€×kTgkU€ÝkV€ëkW€ñkX€ôkY€íkZ k[k\€òk]€ük^gk_k`ŒZka6kbkc,kdke2kfHkgLkhSkitkjYkkZklqkm`kniko|kp}kqmkrgksXMktZµkuˆkv‚kw‘kxnÕky£kzªk{Ìk|g&k}Êk~»l!Ál"¦l#k$l$k7l%k9l&kCl'kFl(kYl)˜Ñl*˜Òl+˜Ól,˜Õl-˜Ùl.˜Úl/k³l0_@l1kÂl2‰ól3el4ŸQl5e“l6e¼l7eÆl8eÄl9eÃl:eÌl;eÎlp€l?pœl@p–lAplBp»lCpÀlDp·lEp«lFp±lGpèlHpÊlIqlJqlKqlLq/lMq1lNqslOq\lPqhlQqElRqrlSqJlTqxlUqzlVq˜lWq³lXqµlYq¨lZq l[qàl\qÔl]qçl^qùl_rl`r(lapllbqlcqfldq¹leb>lfb=lgbClhbHlibIljy;lky@llyFlmyIlny[loy\lpySlqyZlryblsyWlty`luyolvyglwyzlxy…lyyŠlzyšl{y§l|y³l}_Ñl~_Ðm!`x-m?xm@xmAx9mBx:mCx;mDxmExyn?n@~nAvÍnBvånCˆ2nD”…nE”†nF”‡nG”‹nH”ŠnI”ŒnJ”nK”nL”nM””nN”—nO”•nP”šnQ”›nR”œnS”£nT”¤nU”«nV”ªnW”­nX”¬nY”¯nZ”°n[”²n\”´n]”¶n^”·n_”¸n`”¹na”ºnb”¼nc”½nd”¿ne”Änf”Èng”Énh”Êni”Ënj”Ìnk”Ínl”Înm”Ðnn”Ñno”Ònp”Õnq”Önr”×ns”Ùnt”Ønu”Ûnv”Þnw”ßnx”àny”ânz”än{”ån|”çn}”èn~”êo!”éo"”ëo#”îo$”ïo%”óo&”ôo'”õo(”÷o)”ùo*”üo+”ýo,”ÿo-•o.•o/•o0•o1• o2• o3• o4•o5•o6•o7•o8•o9•o:•o;•o<•o=•o>•o?•o@•"oA•*oB•+oC•)oD•,oE•1oF•2oG•4oH•6oI•7oJ•8oK•oM•?oN•BoO•5oP•DoQ•EoR•FoS•IoT•LoU•NoV•OoW•RoX•SoY•ToZ•Vo[•Wo\•Xo]•Yo^•[o_•^o`•_oa•]ob•aoc•bod•doe•eof•fog•goh•hoi•ioj•jok•kol•lom•oon•qoo•rop•soq•:orwçoswìot–ÉouyÕovyíowyãoxyëoyzoz]Go{zo|zo}zo~zp!z9p"z7p#zQp$žÏp%™¥p&zpp'vˆp(vŽp)v“p*v™p+v¤p,tÞp-tàp.u,p/ž p0ž"p1ž(p2ž)p3ž*p4ž+p5ž,p6ž2p7ž1p8ž6p9ž8p:ž7p;ž9p<ž:p=ž>p>žAp?žBp@žDpAžFpBžGpCžHpDžIpEžKpFžLpGžNpHžQpIžUpJžWpKžZpLž[pMž\pNž^pOžcpPžfpQžgpRžhpSžipTžjpUžkpVžlpWžqpXžmpYžspZu’p[u”p\u–p]u p^up_u¬p`u£pau³pbu´pcu¸pduÄpeu±pfu°pguÃphuÂpiuÖpjuÍpkuãpluèpmuæpnuäpouëppuçpqvpruñpsuüptuÿpuvpvvpwvpxv pyvpzv p{v%p|vp}vp~vq!vq"vq,v3q-vMq.v^q/vTq0v\q1vVq2vkq3voq4Êq5zæq6zxq7zyq8z€q9z†q:zˆq;z•qz¬q?z¨q@z­qAz³qBˆdqCˆiqDˆrqEˆ}qFˆqGˆ‚qHˆ¢qIˆÆqJˆ·qKˆ¼qLˆÉqMˆâqNˆÎqOˆãqPˆåqQˆñqR‰qSˆüqTˆèqUˆþqVˆðqW‰!qX‰qY‰qZ‰q[‰ q\‰4q]‰+q^‰6q_‰Aq`‰fqa‰{qbu‹qc€åqdv²qev´qfwÜqg€qh€qi€qj€qk€ ql€"qm€%qn€&qo€'qp€)qq€(qr€1qs€ qt€5qu€Cqv€Fqw€Mqx€Rqy€iqz€qq{‰ƒq|˜xq}˜€q~˜ƒr!˜‰r"˜Œr#˜r$˜r%˜”r&˜šr'˜›r(˜žr)˜Ÿr*˜¡r+˜¢r,˜¥r-˜¦r.†Mr/†Tr0†lr1†nr2†r3†zr4†|r5†{r6†¨r7†r8†‹r9†¬r:†r;†§r<†£r=†ªr>†“r?†©r@†¶rA†ÄrB†µrC†ÎrD†°rE†ºrF†±rG†¯rH†ÉrI†ÏrJ†´rK†érL†ñrM†òrN†írO†órP†ÐrQ‡rR†ÞrS†ôrT†ßrU†ØrV†ÑrW‡rX‡rY†ørZ‡r[‡ r\‡ r]‡ r^‡#r_‡;r`‡ra‡%rb‡.rc‡rd‡>re‡Hrf‡4rg‡1rh‡)ri‡7rj‡?rk‡‚rl‡"rm‡}rn‡~ro‡{rp‡`rq‡prr‡Lrs‡nrt‡‹ru‡Srv‡crw‡|rx‡dry‡Yrz‡er{‡“r|‡¯r}‡¨r~‡Òs!‡Æs"‡ˆs#‡…s$‡­s%‡—s&‡ƒs'‡«s(‡ås)‡¬s*‡µs+‡³s,‡Ës-‡Ós.‡½s/‡Ñs0‡Às1‡Ês2‡Ûs3‡ês4‡às5‡îs6ˆs7ˆs8‡þs9ˆ s:ˆs;ˆ!s<ˆ9s=ˆ6s?Bs@DsAEsB‚sCzúsDzýsE{sF{sG{sH{sI{ sJ{+sK{sL{GsM{8sN{*sO{sP{.sQ{1sR{ sS{%sT{$sU{3sV{>sW{sX{XsY{ZsZ{Es[{us\{Ls]{]s^{`s_{ns`{{sa{bsb{rsc{qsd{se{¦sf{§sg{¸sh{¬si{sj{¨sk{…sl{ªsm{œsn{¢so{«sp{´sq{Ñsr{Áss{Ìst{Ýsu{Úsv{åsw{æsx{êsy| sz{þs{{üs||s}|s~| t!|t"|*t#|&t$|8t%|At&|@t'þt(‚t)‚t*‚t+ìt,ˆDt-‚!t.‚"t/‚#t0‚-t1‚/t2‚(t3‚+t4‚8t5‚;t6‚3t7‚4t8‚>t9‚Dt:‚It;‚Kt<‚Ot=‚Zt>‚_t?‚ht@ˆ~tAˆ…tBˆˆtCˆØtDˆßtE‰^tFtGŸtH§tI¯tJ°tK²tL||tMeItN|‘tO|tP|œtQ|žtR|¢tS|²tT|¼tU|½tV|ÁtW|ÇtX|ÌtY|ÍtZ|Èt[|Åt\|×t]|èt^‚nt_f¨t`¿taÎtbÕtcåtdáteætfétgîthóti|øtj}wtk}¦tl}®tm~Gtn~›tož¸tpž´tqstr„ts”tt‘tu±tvgtwmtxŒGtyŒItz‘Jt{‘Pt|‘Nt}‘Ot~‘du!‘bu"‘au#‘pu$‘iu%‘ou&‘}u'‘~u(‘ru)‘tu*‘yu+‘Œu,‘…u-‘u.‘u/‘‘u0‘¢u1‘£u2‘ªu3‘­u4‘®u5‘¯u6‘µu7‘´u8‘ºu9ŒUu:ž~u;¸u<ëu=Žu>ŽYu?Žiu@µuA¿uB¼uCºuDÄuEÖuF×uGÚuHÞuIÎuJÏuKÛuLÆuMìuN÷uOøuPãuQùuRûuSäuTŽ uUýuVŽuWŽuXŽuYŽ,uZŽ.u[Ž#u\Ž/u]Ž:u^Ž@u_Ž9u`Ž5uaŽ=ubŽ1ucŽIudŽAueŽBufŽQugŽRuhŽJuiŽpujŽvukŽ|ulŽoumŽtunŽ…uoŽupŽ”uqŽurŽœusŽžutŒxuuŒ‚uvŒŠuwŒ…uxŒ˜uyŒ”uze›u{‰Öu|‰Þu}‰Úu~‰Üv!‰åv"‰ëv#‰ïv$Š>v%‹&v&—Sv'–év(–óv)–ïv*—v+—v,—v-—v.—v/—*v0—-v1—0v2—>v3Ÿ€v4Ÿƒv5Ÿ…v6Ÿ†v7Ÿ‡v8Ÿˆv9Ÿ‰v:ŸŠv;ŸŒv<žþv=Ÿ v>Ÿ v?–¹v@–¼vA–½vB–ÎvC–ÒvDw¿vE–àvF’ŽvG’®vH’ÈvI“>vJ“jvK“ÊvL“vM”>vN”kvOœvPœ‚vQœ…vRœ†vSœ‡vTœˆvUz#vVœ‹vWœŽvXœvYœ‘vZœ’v[œ”v\œ•v]œšv^œ›v_œžv`œŸvaœ vbœ¡vcœ¢vdœ£veœ¥vfœ¦vgœ§vhœ¨viœ©vjœ«vkœ­vlœ®vmœ°vnœ±voœ²vpœ³vqœ´vrœµvsœ¶vtœ·vuœºvvœ»vwœ¼vxœ½vyœÄvzœÅv{œÆv|œÇv}œÊv~œËw!œÌw"œÍw#œÎw$œÏw%œÐw&œÓw'œÔw(œÕw)œ×w*œØw+œÙw,œÜw-œÝw.œßw/œâw0—|w1—…w2—‘w3—’w4—”w5—¯w6—«w7—£w8—²w9—´w:š±w;š°w<š·w=žXw>š¶w?šºw@š¼wAšÁwBšÀwCšÅwDšÂwEšËwFšÌwGšÑwH›EwI›CwJ›GwK›IwL›HwM›MwN›QwO˜èwP™ wQ™.wR™UwS™TwTšßwUšáwVšæwWšïwXšëwYšûwZšíw[šùw\›w]›w^›w_›w`›#waž½wbž¾wc~;wdž‚wež‡wfžˆwgž‹whž’wi“ÖwjžwkžŸwlžÛwmžÜwnžÝwožàwpžßwqžâwržéwsžçwtžåwužêwvžïwwŸ"wxŸ,wyŸ/wzŸ9w{Ÿ7w|Ÿ=w}Ÿ>w~ŸDscreen-4.1.0/utf8encodings/180000644000175000017500000015311611642704565014007 0ustar abeabeScreenI2UTF85ŽBIG 5!@0!Aÿ !B0!C0!Dÿ!E "!Fÿ!Gÿ!Hÿ!Iÿ!Jþ0!K &!L %!MþP!Nÿd!OþR!P·!QþT!RþU!SþV!TþW!Uÿ\!V !Wþ1!X !Yþ3!Zÿý![þ4!\þO!]ÿ!^ÿ !_þ5!`þ6!aÿ[!bÿ]!cþ7!dþ8!e0!f0!gþ9!hþ:!i0!j0!kþ;!lþ!q0!r0 !sþ?!tþ@!u0 !v0 !wþA!xþB!y0!z0!{þC!|þD!}þY!~þZ!¡þ[!¢þ\!£þ]!¤þ^!¥ !¦ !§ !¨ !©0!ª0!« 5!¬ 2!­ÿ!®ÿ!¯ÿ !° ;!±§!²0!³%Ë!´%Ï!µ%³!¶%²!·%Î!¸&!¹&!º%Ç!»%Æ!¼%¡!½% !¾%½!¿%¼!À2£!Á!! >!Ãÿý!Äÿ?!Åÿý!ÆþI!ÇþJ!ÈþM!ÉþN!ÊþK!ËþL!Ìþ_!Íþ`!Îþa!Ïÿ !Ðÿ !Ñ×!Ò÷!Ó±!Ô"!Õÿ!Öÿ!×ÿ!Ø"f!Ù"g!Ú"`!Û"!Ü"R!Ý"a!Þþb!ßþc!àþd!áþe!âþf!ã"%Çr¯%Ès„%És‰%ÊtÜ%Ëtæ%Ìu%Íu%Îu(%Ïu)%Ðu0%Ñu1%Òu2%Óu3%Ôu‹%Õv}%Öv®%×v¿%Øvî%ÙwÛ%Úwâ%Ûwó%Üy:%Ýy¾%Þzt%ßzË%àN%áN%âNR%ãNS%äNi%åN™%æN¤%çN¦%èN¥%éNÿ%êO %ëO%ìO %íO%îO %ïO%ðO%ñO%òNò%óNö%ôNû%õNð%öNó%÷Ný%øO%ùO %úQI%ûQG%üQF%ýQH%þQh&@Qq&AQ&BQ°&CR&DR&ER&FR&GR&HR£&IS&JS!&KS &LSp&MSq&NT &OT&PT &QT &RT&ST&TT &UT&VT&WT &XT&YT&ZT&[T&\T&]Và&^VÞ&_VÝ&`W3&aW0&bW(&cW-&dW,&eW/&fW)&gY&hY&iY7&jY8&kY„&lYx&mYƒ&nY}&oYy&pY‚&qY&r[W&s[X&t[‡&u[ˆ&v[…&w[‰&x[ú&y\&z\y&{]Þ&|^&}^v&~^t&¡_&¢_&£_Ù&¤_Ö&¥b&¦b &§b &¨b&©bc&ªb[&«bX&¬e6&­eé&®eè&¯eì&°eí&±fò&²fó&³g &´g=&µg4&¶g1&·g5&¸k!&¹kd&ºk{&»l&¼l]&½lW&¾lY&¿l_&Àl`&ÁlP&ÂlU&Ãla&Äl[&ÅlM&ÆlN&Çpp&Èr_&Ér]&Êv~&Ëzù&Ì|s&Í|ø&Î6&ÏŠ&н&Ñ€&Ò€&Ó€ &Ô€&Õ€3&Ö€&×€‰&Ø€‹&Ù€Œ&Úã&Ûê&Üó&Ýü&Þ‚ &ß‚&à‚&á‚n&â‚r&ã‚~&ä†k&åˆ@&æˆL&çˆc&è‰&é–!&êN2&ëN¨&ìOM&íOO&îOG&ïOW&ðO^&ñO4&òO[&óOU&ôO0&õOP&öOQ&÷O=&øO:&ùO8&úOC&ûOT&üO<&ýOF&þOc'@O\'AO`'BO/'CON'DO6'EOY'FO]'GOH'HOZ'IQL'JQK'KQM'LQu'MQ¶'NQ·'OR%'PR$'QR)'RR*'SR('TR«'UR©'VRª'WR¬'XS#'YSs'ZSu'[T'\T-']T'^T>'_T&'`TN'aT''bTF'cTC'dT3'eTH'fTB'gT'hT)'iTJ'jT9'kT;'lT8'mT.'nT5'oT6'pT 'qT<'rT@'sT1'tT+'uT'vT,'wVê'xVð'yVä'zVë'{WJ'|WQ'}W@'~WM'¡WG'¢WN'£W>'¤WP'¥WO'¦W;'§Xï'¨Y>'©Y'ªY’'«Y¨'¬Yž'­Y£'®Y™'¯Y–'°Y'±Y¤'²Y“'³YŠ'´Y¥'µ[]'¶[\'·[Z'¸[['¹[Œ'º[‹'»['¼\,'½\@'¾\A'¿\?'À\>'Á\'Â\‘'Ã\”'Ä\Œ'Å]ë'Æ^ 'Ç^'È^‡'É^Š'Ê^÷'Ë_'Ì_'Í_d'Î_b'Ï_w'Ð_y'Ñ_Ø'Ò_Ì'Ó_×'Ô_Í'Õ_ñ'Ö_ë'×_ø'Ø_ê'Ùb'Úb'Ûb„'Üb—'Ýb–'Þb€'ßbv'àb‰'ábm'âbŠ'ãb|'äb~'åby'æbs'çb’'èbo'éb˜'êbn'ëb•'ìb“'íb‘'îb†'ïe9'ðe;'ñe8'òeñ'ófô'ôg_'õgN'ögO'÷gP'øgQ'ùg\'úgV'ûg^'ügI'ýgF'þg`(@gS(AgW(Bke(CkÏ(DlB(El^(Fl™(Gl(Hlˆ(Il‰(Jl…(Kl›(Llj(Mlz(Nl(Olp(PlŒ(Qlh(Rl–(Sl’(Tl}(Ulƒ(Vlr(Wl~(Xlt(Yl†(Zlv([l(\l”(]l˜(^l‚(_pv(`p|(ap}(bpx(crb(dra(er`(frÄ(grÂ(hs–(iu,(ju+(ku7(lu8(mv‚(nvï(owã(pyÁ(qyÀ(ry¿(szv(t|û(uU(v€–(w€“(x€(y€˜(z€›({€š(|€²(}‚o(~‚’(¡‚‹(¢‚(£‰‹(¤‰Ò(¥Š(¦Œ7(§ŒF(¨ŒU(©Œ(ªd(«p(¬³(­Ž«(®ŽÊ(¯›(°°(±Â(²Æ(³Å(´Ä(µ]á(¶‘(·¢(¸ª(¹¦(º£(»‘I(¼‘Æ(½‘Ì(¾–2(¿–.(À–1(Á–*(–,(ÃN&(ÄNV(ÅNs(ÆN‹(ÇN›(ÈNž(ÉN«(ÊN¬(ËOo(ÌO(ÍO(ÎOs(ÏO(ÐOl(ÑO›(ÒO‹(ÓO†(ÔOƒ(ÕOp(ÖOu(×Oˆ(ØOi(ÙO{(ÚO–(ÛO~(ÜO(ÝO‘(ÞOz(ßQT(àQR(áQU(âQi(ãQw(äQv(åQx(æQ½(çQý(èR;(éR8(êR7(ëR:(ìR0(íR.(îR6(ïRA(ðR¾(ñR»(òSR(óST(ôSS(õSQ(öSf(÷Sw(øSx(ùSy(úSÖ(ûSÔ(üS×(ýTs(þTu)@T–)ATx)BT•)CT€)DT{)ETw)FT„)GT’)HT†)IT|)JT)KTq)LTv)MTŒ)NTš)OTb)PTh)QT‹)RT})STŽ)TVú)UWƒ)VWw)WWj)XWi)YWa)ZWf)[Wd)\W|)]Y)^YI)_YG)`YH)aYD)bYT)cY¾)dY»)eYÔ)fY¹)gY®)hYÑ)iYÆ)jYÐ)kYÍ)lYË)mYÓ)nYÊ)oY¯)pY³)qYÒ)rYÅ)s[_)t[d)u[c)v[—)w[š)x[˜)y[œ)z[™){[›)|\)}\H)~\E)¡\F)¢\·)£\¡)¤\¸)¥\©)¦\«)§\±)¨\³)©^)ª^)«^)¬^)­^)®^)¯^x)°^š)±^—)²^œ)³^•)´^–)µ^ö)¶_&)·_')¸_))¹_€)º_)»_)¼_|)½_Ý)¾_à)¿_ý)À_õ)Á_ÿ)Â`)Ã`)Ä`/)Å`5)Æ`)Ç`*)È`)É`!)Ê`')Ë`))Ì`+)Í`)Îb)Ïb)Ðb?)Ñb>)Òb@)Ób)ÔbÉ)ÕbÌ)ÖbÄ)×b¿)ØbÂ)Ùb¹)ÚbÒ)ÛbÛ)Üb«)ÝbÓ)ÞbÔ)ßbË)àbÈ)áb¨)âb½)ãb¼)äbÐ)åbÙ)æbÇ)çbÍ)èbµ)ébÚ)êb±)ëbØ)ìbÖ)íb×)îbÆ)ïb¬)ðbÎ)ñe>)òe§)óe¼)ôeú)õf)öf)÷f )øf)ùf)úf)ûf)üf)ýf)þf *@f*Ag *Bg *Cgm*Dg‹*Eg•*Fgq*Ggœ*Hgs*Igw*Jg‡*Kg*Lg—*Mgo*Ngp*Og*Pg‰*Qg~*Rg*Sgu*Tgš*Ug“*Vg|*Wgj*Xgr*Yk#*Zkf*[kg*\k*]l*^l*_lã*`lè*aló*bl±*clÌ*dlå*el³*fl½*gl¾*hl¼*ilâ*jl«*klÕ*llÓ*ml¸*nlÄ*ol¹*plÁ*ql®*rl×*slÅ*tlñ*ul¿*vl»*wlá*xlÛ*ylÊ*zl¬*{lï*|lÜ*}lÖ*~là*¡p•*¢pŽ*£p’*¤pŠ*¥p™*¦r,*§r-*¨r8*©rH*ªrg*«ri*¬rÀ*­rÎ*®rÙ*¯r×*°rÐ*±s©*²s¨*³sŸ*´s«*µs¥*¶u=*·u*¸u™*¹uš*ºv„*»vÂ*¼vò*½vô*¾wå*¿wý*Ày>*Áy@*ÂyA*ÃyÉ*ÄyÈ*Åzz*Æzy*Çzú*È|þ*ÉT*ÊŒ*Ë‹*Ì€*Í€º*΀¥*Ï€¢*Ѐ±*Ñ€¡*Ò€«*Ó€©*Ô€´*Õ€ª*Ö€¯*×å*Øþ*Ù‚ *Ú‚³*Û‚*Ü‚™*Ý‚­*Þ‚½*ß‚Ÿ*à‚¹*Ⴑ*€*ã‚¥*䂯*傸*æ‚£*ç‚°*肾*é‚·*ê†N*ë†q*ìR*íˆh*îŽË*ïÎ*ðÔ*ñÑ*òµ*ó¸*ô±*õ¶*ö‘Ç*÷‘Ñ*ø•w*ù•€*ú–*û–@*ü–?*ý–;*þ–D+@–B+A–¹+B–è+C—R+D—^+ENŸ+FN­+GN®+HOá+IOµ+JO¯+KO¿+LOà+MOÑ+NOÏ+OOÝ+POÃ+QO¶+ROØ+SOß+TOÊ+UO×+VO®+WOÐ+XOÄ+YOÂ+ZOÚ+[OÎ+\OÞ+]O·+^QW+_Q’+`Q‘+aQ +bRN+cRC+dRJ+eRM+fRL+gRK+hRG+iRÇ+jRÉ+kRÃ+lRÁ+mS +nSW+oS{+pSš+qSÛ+rT¬+sTÀ+tT¨+uTÎ+vTÉ+wT¸+xT¦+yT³+zTÇ+{TÂ+|T½+}Tª+~TÁ+¡TÄ+¢TÈ+£T¯+¤T«+¥T±+¦T»+§T©+¨T§+©T¿+ªVÿ+«W‚+¬W‹+­W +®W£+¯W¢+°WÎ+±W®+²W“+³YU+´YQ+µYO+¶YN+·YP+¸YÜ+¹YØ+ºYÿ+»Yã+¼Yè+½Z+¾Yå+¿Yê+ÀYÚ+ÁYæ+ÂZ+ÃYû+Ä[i+Å[£+Æ[¦+Ç[¤+È[¢+É[¥+Ê\+Ë\N+Ì\O+Í\M+Î\K+Ï\Ù+Ð\Ò+Ñ]÷+Ò^+Ó^%+Ô^+Õ^}+Ö^ +×^¦+Ø^ú+Ù_+Ú_-+Û_e+Ü_ˆ+Ý_…+Þ_Š+ß_‹+à_‡+á_Œ+â_‰+ã`+ä`+å` +æ`%+ç`+è`(+é`M+ê`p+ë`h+ì`b+í`F+î`C+ï`l+ð`k+ñ`j+ò`d+óbA+ôbÜ+õc+öc +÷bü+øbí+ùc+úbî+ûbý+üc+ýbñ+þb÷,@bï,Abì,Bbþ,Cbô,Dc,Ec,Fe?,GeE,He«,Ie½,Jeâ,Kf%,Lf-,Mf ,Nf',Of/,Pf,Qf(,Rf1,Sf$,Tf÷,Ugÿ,VgÓ,Wgñ,XgÔ,YgÐ,Zgì,[g¶,\g¯,]gõ,^gé,_gï,`gÄ,agÑ,bg´,cgÚ,dgå,eg¸,fgÏ,ggÞ,hgó,ig°,jgÙ,kgâ,lgÝ,mgÒ,nkj,okƒ,pk†,qkµ,rkÒ,sk×,tl,ulÉ,vm ,wm2,xm*,ymA,zm%,{m ,|m1,}m,~m,¡m;,¢m=,£m>,¤m6,¥m,¦lõ,§m9,¨m',©m8,ªm),«m.,¬m5,­m,®m+,¯p«,°pº,±p³,²p¬,³p¯,´p­,µp¸,¶p®,·p¤,¸r0,¹rr,ºro,»rt,¼ré,½rà,¾rá,¿s·,ÀsÊ,Ás»,Âs²,ÃsÍ,ÄsÀ,Ås³,Æu,Çu-,ÈuO,ÉuL,ÊuN,ËuK,Ìu«,Íu¤,Îu¥,Ïu¢,Ðu£,Ñvx,Òv†,Óv‡,Ôvˆ,ÕvÈ,ÖvÆ,×vÃ,ØvÅ,Ùw,Úvù,Ûvø,Üw ,Ýw ,Þvþ,ßvü,àw,áwÜ,âx,ãx,äx ,åx ,æyF,çyI,èyH,éyG,êy¹,ëyº,ìyÑ,íyÒ,îyË,ïz,ðz,ñzÿ,òzý,ó|},ô},õ},ö},÷} ,ø},ù},ú},û8,üŽ,ý¿,þ€-@€-A€ -B€-C€6-D€Ö-E€å-F€Ú-G€Ã-H€Ä-I€Ì-J€á-K€Û-L€Î-M€Þ-N€ä-O€Ý-Pô-Q‚"-R‚ç-Sƒ-Tƒ-U‚ã-V‚Û-W‚æ-Xƒ-Y‚å-Zƒ-[ƒ -\‚Ò-]‚×-^‚ñ-_ƒ-`‚Ü-a‚Ô-b‚Ñ-c‚Þ-d‚Ó-e‚ß-f‚ï-gƒ-h†P-i†y-j†{-k†z-lˆM-mˆk-n‰-o‰Ô-pŠ-qŠ-rŠ-sŒž-tŒ -ut-vs-w´-xŽÍ-yŽÌ-zð-{æ-|â-}ê-~å-¡í-¢ë-£ä-¤è-¥Ê-¦Î-§Á-¨Ã-©‘K-ª‘J-«‘Í-¬•‚-­–P-®–K-¯–L-°–M-±—b-²—i-³—Ë-´—í-µ—ó-¶˜-·˜¨-¸˜Û-¹˜ß-º™–-»™™-¼NX-½N³-¾P -¿P -ÀP#-ÁOï-ÂP&-ÃP%-ÄOø-ÅP)-ÆP-ÇP-ÈP<-ÉP-ÊP-ËP-ÌP-ÍOú-ÎP-ÏP-ÐP(-ÑOñ-ÒP!-ÓP -ÔP-ÕP-ÖOó-×Oî-ØP--ÙP*-ÚOþ-ÛP+-ÜP -ÝQ|-ÞQ¤-ßQ¥-àQ¢-áQÍ-âQÌ-ãQÆ-äQË-åRV-æR\-çRT-èR[-éR]-êS*-ëS-ìSŸ-íS-îSß-ïTè-ðU-ñU-òU7-óTü-ôTå-õTò-öU-÷Tú-øU-ùTé-úTí-ûTá-üU -ýTî-þTê.@Tæ.AU'.BU.CTý.DU.EW.FW.GWÂ.HWÔ.IWË.JWÃ.KX .LY.MYW.NYX.OYZ.PZ.QZ.RZ.SZ.TZ.UZ.VYì.WZ .XZ#.YZ).ZZ%.[Z .\Z .][k.^\X._[°.`[³.a[¶.b[´.c[®.d[µ.e[¹.f[¸.g\.h\Q.i\U.j\P.k\í.l\ý.m\û.n\ê.o\è.p\ð.q\ö.r].s\ô.t]î.u^-.v^+.w^«.x^­.y^§.z_1.{_’.|_‘.}_.~`Y.¡`c.¢`e.£`P.¤`U.¥`m.¦`i.§`o.¨`„.©`Ÿ.ª`š.«`.¬`”.­`Œ.®`….¯`–.°bG.±bó.²c.³bÿ.´cN.µc>.¶c/.·cU.¸cB.¹cF.ºcO.»cI.¼c:.½cP.¾c=.¿c*.Àc+.Ác(.ÂcM.ÃcL.ÄeH.ÅeI.Æe™.ÇeÁ.ÈeÅ.ÉfB.ÊfI.ËfO.ÌfC.ÍfR.ÎfL.ÏfE.ÐfA.Ñfø.Òg.Óg.Ôg.Õh!.Öh8.×hH.ØhF.ÙhS.Úh9.ÛhB.ÜhT.Ýh).Þh³.ßh.àhL.áhQ.âh=.ãgô.ähP.åh@.æh<.çhC.èh*.éhE.êh.ëh.ìhA.íkŠ.îk‰.ïk·.ðl#.ñl'.òl(.ól&.ôl$.õlð.ömj.÷m•.ømˆ.ùm‡.úmf.ûmx.ümw.ýmY.þm“/@ml/Am‰/Bmn/CmZ/Dmt/Emi/FmŒ/GmŠ/Hmy/Im…/Jme/Km”/LpÊ/MpØ/Npä/OpÙ/PpÈ/QpÏ/Rr9/Sry/Trü/Urù/Vrý/Wrø/Xr÷/Ys†/Zsí/[t /\sî/]sà/^sê/_sÞ/`uT/au]/bu\/cuZ/duY/eu¾/fuÅ/guÇ/hu²/iu³/ju½/ku¼/lu¹/muÂ/nu¸/ov‹/pv°/qvÊ/rvÍ/svÎ/tw)/uw/vw /ww(/xwé/yx0/zx'/{x8/|x/}x4/~x7/¡x%/¢x-/£x /¤x/¥x2/¦yU/§yP/¨y`/©y_/ªyV/«y^/¬y]/­yW/®yZ/¯yä/°yã/±yç/²yß/³yæ/´yé/µyØ/¶z„/·zˆ/¸zÙ/¹{/º{/»|‰/¼}!/½}/¾} /¿} /À} /Á}"/Â}/Ã}/Ä}/Å}/Æ}/Ç} /È}/É}/Ê:/Ë_/Ì”/ÍÅ/ÎÁ/Ï€/Ѐ/Ñ€/Ò€/Ó€/Ô€=/Õ€?/Ö€ñ/×/Ø€ð/Ù/Ú€í/Û€ô/Ü/Ý€ø/Þ€ó/ß/à€ý/á /â€ü/ã€ï/äí/åì/æ‚/ç‚/è‚*/é‚+/ê‚(/ë‚,/ì‚»/íƒ+/îƒR/ïƒT/ðƒJ/ñƒ8/òƒP/óƒI/ôƒ5/õƒ4/öƒO/÷ƒ2/øƒ9/ùƒ6/úƒ/ûƒ@/üƒ1/ýƒ(/þƒC0@†T0A†Š0B†ª0C†“0D†¤0E†©0F†Œ0G†£0H†œ0Iˆp0Jˆw0Kˆ0Lˆ‚0Mˆ}0Nˆy0OŠ0PŠ0QŠ0RŠ 0SŠ0TŠ 0UŠ0VŠ0WŠ0XŠ0YŠ0ZŒH0[Œz0\Œy0]Œ¡0^Œ¢0_w0`ެ0aŽÒ0bŽÔ0cŽÏ0d±0e0f0g÷0h0iú0jô0k0lý0m0nø0o•0pá0qÝ0râ0s‘R0t‘M0u‘L0v‘Ø0w‘Ý0x‘×0y‘Ü0z‘Ù0{•ƒ0|–b0}–c0~–a0¡–[0¢–]0£–d0¤–X0¥–^0¦–»0§˜â0¨™¬0©š¨0ªšØ0«›%0¬›20­›<0®N~0¯Pz0°P}0±P\0²PG0³PC0´PL0µPZ0¶PI0·Pe0¸Pv0¹PN0ºPU0»Pu0¼Pt0½Pw0¾PO0¿P0ÀPo0ÁPm0ÂQ\0ÃQ•0ÄQð0ÅRj0ÆRo0ÇRÒ0ÈRÙ0ÉRØ0ÊRÕ0ËS0ÌS0ÍS0ÎS?0ÏS@0ÐS>0ÑSÃ0Òfü0ÓUF0ÔUj0ÕUf0ÖUD0×U^0ØUa0ÙUC0ÚUJ0ÛU10ÜUV0ÝUO0ÞUU0ßU/0àUd0áU80âU.0ãU\0äU,0åUc0æU30çUA0èUW0éW0êW 0ëW 0ìWß0íX0îX 0ïX0ðWà0ñWä0òWú0óX0ôX50õW÷0öWù0÷Y 0øYb0ùZ60úZA0ûZI0üZf0ýZj0þZ@1@Z<1AZb1BZZ1CZF1DZJ1E[p1F[Ç1G[Å1H[Ä1I[Â1J[¿1K[Æ1L\ 1M\1N\1O\`1P\\1Q\]1R]1S]1T]1U]1V]1W]"1X]1Y])1Z]1[]1\]$1]]'1^]1_]â1`^81a^61b^31c^71d^·1e^¸1f^¶1g^µ1h^¾1i_51j_71k_W1l_l1m_i1n_k1o_—1p_™1q_ž1r_˜1s_¡1t_ 1u_œ1v`1w`£1x`‰1y` 1z`¨1{`Ë1|`´1}`æ1~`½1¡`Å1¢`»1£`µ1¤`Ü1¥`¼1¦`Ø1§`Õ1¨`Æ1©`ß1ª`¸1«`Ú1¬`Ç1­b1®b1¯bH1°c 1±c§1²cr1³c–1´c¢1µc¥1¶cw1·cg1¸c˜1¹cª1ºcq1»c©1¼c‰1½cƒ1¾c›1¿ck1Àc¨1Ác„1Âcˆ1Ãc™1Äc¡1Åc¬1Æc’1Çc1Èc€1Éc{1Êci1Ëch1Ìcz1Íe]1ÎeV1ÏeQ1ÐeY1ÑeW1ÒU_1ÓeO1ÔeX1ÕeU1ÖeT1×eœ1Øe›1Ùe¬1ÚeÏ1ÛeË1ÜeÌ1ÝeÎ1Þf]1ßfZ1àfd1áfh1âff1ãf^1äfù1åR×1æg1çh1èh¯1éh¢1êh“1ëhµ1ìh1íhv1îh±1ïh§1ðh—1ñh°1òhƒ1óhÄ1ôh­1õh†1öh…1÷h”1øh1ùh¨1úhŸ1ûh¡1üh‚1ýk21þkº2@kë2Akì2Bl+2CmŽ2Dm¼2Emó2FmÙ2Gm²2Hmá2ImÌ2Jmä2Kmû2Lmú2Mn2NmÇ2OmË2Pm¯2QmÑ2Rm®2SmÞ2Tmù2Um¸2Vm÷2Wmõ2XmÅ2YmÒ2Zn2[mµ2\mÚ2]më2^mØ2_mê2`mñ2amî2bmè2cmÆ2dmÄ2emª2fmì2gm¿2hmæ2ipù2jq 2kq 2lpý2mpï2nr=2or}2pr2qs2rs2ss2ts2us2vs‡2wt2xt 2yt2zt2{sþ2|t 2}tà2~tö2¡t÷2¢u2£u"2¤ue2¥uf2¦ub2§up2¨u2©uÔ2ªuÕ2«uµ2¬uÊ2­uÍ2®vŽ2¯vÔ2°vÒ2±vÛ2²w72³w>2´w<2µw62¶w82·w:2¸xk2¹xC2ºxN2»ye2¼yh2½ym2¾yû2¿z’2Àz•2Á{ 2Â{(2Ã{2Ä{,2Å{&2Æ{2Ç{2È{.2É|’2Ê|—2Ë|•2Ì}F2Í}C2Î}q2Ï}.2Ð}92Ñ}<2Ò}@2Ó}02Ô}32Õ}D2Ö}/2×}B2Ø}22Ù}12Ú=2Ûž2Üš2ÝÌ2ÞÎ2ßÒ2à€2á€J2â€F2ã/2ä2å#2æ+2ç)2è02é$2ê‚2ë‚52ì‚72í‚62î‚922ðƒž2ñƒ˜2òƒx2óƒ¢2ôƒ–2õƒ½2öƒ«2÷ƒ’2øƒŠ2ùƒ“2úƒ‰2ûƒ 2üƒw2ýƒ{2þƒ|3@ƒ†3Aƒ§3B†U3C_j3D†Ç3E†À3F†¶3G†Ä3H†µ3I†Æ3J†Ë3K†±3L†¯3M†É3NˆS3Oˆž3Pˆˆ3Qˆ«3Rˆ’3Sˆ–3Tˆ3Uˆ‹3V‰“3W‰3XŠ*3YŠ3ZŠ#3[Š%3\Š13]Š-3^Š3_Š3`Š"3aŒI3bŒZ3cŒ©3dŒ¬3eŒ«3fŒ¨3gŒª3hŒ§3ig3jf3k¾3lº3mŽÛ3nŽß3o3p 3q3r3s#3t3u3v3w3x3y 3z3{"3|3}3~3¡è3¢í3£ý3¤‘W3¥‘Î3¦‘õ3§‘æ3¨‘ã3©‘ç3ª‘í3«‘é3¬•‰3­–j3®–u3¯–s3°–x3±–p3²–t3³–v3´–w3µ–l3¶–À3·–ê3¸–é3¹zà3ºzß3»˜3¼˜3½›Z3¾œå3¿žu3Àž3Áž¥3ž»3ÃP¢3ÄP3ÅP…3ÆP™3ÇP‘3ÈP€3ÉP–3ÊP˜3ËPš3Ìg3ÍQñ3ÎRr3ÏRt3ÐRu3ÑRi3ÒRÞ3ÓRÝ3ÔRÛ3ÕSZ3ÖS¥3×U{3ØU€3ÙU§3ÚU|3ÛUŠ3ÜU3ÝU˜3ÞU‚3ßUœ3àUª3áU”3âU‡3ãU‹3äUƒ3åU³3æU®3çUŸ3èU>3éU²3êUš3ëU»3ìU¬3íU±3îU~3ïU‰3ðU«3ñU™3òW 3óX/3ôX*3õX43öX$3÷X03øX13ùX!3úX3ûX 3üXù3ýXú3þY`4@Zw4AZš4BZ4CZ’4DZ›4EZ§4F[s4G[q4H[Ò4I[Ì4J[Ó4K[Ð4L\ 4M\ 4N\14O]L4P]P4Q]44R]G4S]ý4T^E4U^=4V^@4W^C4X^~4Y^Ê4Z^Á4[^Â4\^Ä4]_<4^_m4__©4`_ª4a_¨4b`Ñ4c`á4d`²4e`¶4f`à4ga4ha#4i`ú4ja4k`ð4l`û4m`ô4nah4o`ñ4pa4q`ö4ra 4sa4ta4ub4vbI4wc£4xcŒ4ycÏ4zcÀ4{cé4|cÉ4}cÆ4~cÍ4¡cÒ4¢cã4£cÐ4¤cá4¥cÖ4¦cí4§cî4¨cv4©cô4ªcê4«cÛ4¬dR4­cÚ4®cù4¯e^4°ef4±eb4²ec4³e‘4´e4µe¯4¶fn4·fp4¸ft4¹fv4ºfo4»f‘4¼fz4½f~4¾fw4¿fþ4Àfÿ4Ág4Âg4Ãhú4ÄhÕ4Åhà4ÆhØ4Çh×4Èi4Éhß4Êhõ4Ëhî4Ìhç4Íhù4ÎhÒ4Ïhò4Ðhã4ÑhË4ÒhÍ4Ói 4Ôi4Õi4ÖhÉ4×hÚ4Øin4Ùhû4Úk>4Ûk:4Ük=4Ýk˜4Þk–4ßk¼4àkï4ál.4âl/4ãl,4än/4ån84ænT4çn!4èn24éng4ênJ4ën 4ìn%4ín#4în4ïn[4ðnX4ñn$4ònV4ónn4ôn-4õn&4öno4÷n44ønM4ùn:4ún,4ûnC4ün4ýn>4þnË5@n‰5An5BnN5Cnc5DnD5Enr5Fni5Gn_5Hq5Iq5Jq&5Kq05Lq!5Mq65Nqn5Oq5PrL5Qr„5Rr€5Ss65Ts%5Us45Vs)5Wt:5Xt*5Yt35Zt"5[t%5\t55]t65^t45_t/5`t5at&5bt(5cu%5du&5euk5fuj5guâ5huÛ5iuã5juÙ5kuØ5luÞ5muà5nv{5ov|5pv–5qv“5rv´5svÜ5twO5uwí5vx]5wxl5xxo5yz 5zz5{z 5|z5}z5~z˜5¡z—5¢z–5£zå5¤zã5¥{I5¦{V5§{F5¨{P5©{R5ª{T5«{M5¬{K5­{O5®{Q5¯|Ÿ5°|¥5±}^5²}P5³}h5´}U5µ}+5¶}n5·}r5¸}a5¹}f5º}b5»}p5¼}s5½U„5¾Ô5¿Õ5À€ 5Á€R5€…5ÃU5ÄT5ÅK5ÆQ5ÇN5È95ÉF5Ê>5ËL5ÌS5Ít5΂5Ï‚5Ѓé5Ñ„5Òƒø5Ó„ 5Ôƒà5ÕƒÅ5Ö„ 5׃Á5؃ï5Ùƒñ5Úƒô5Û„W5Ü„ 5݃ð5Þ„ 5߃Ì5àƒý5áƒò5âƒÊ5ã„85ä„5å„5æƒÜ5ç„5èƒÔ5éƒß5ê†[5ë†ß5ì†Ù5í†í5î†Ô5ï†Û5ð†ä5ñ†Ð5ò†Þ5óˆW5ôˆÁ5õˆÂ5öˆ±5÷‰ƒ5ø‰–5ùŠ;5úŠ`5ûŠU5üŠ^5ýŠ<5þŠA6@ŠT6AŠ[6BŠP6CŠF6DŠ46EŠ:6FŠ66GŠV6HŒa6IŒ‚6JŒ¯6KŒ¼6LŒ³6MŒ½6NŒÁ6OŒ»6PŒÀ6QŒ´6RŒ·6SŒ¶6TŒ¿6UŒ¸6VŠ6W…6X6YÎ6ZÝ6[Ë6\Ú6]Ñ6^Ì6_Û6`Æ6aŽû6bŽø6cŽü6dœ6e.6f56g16h86i26j66k‘6lõ6m‘ 6nþ6o‘c6p‘e6q‘Ï6r’6s’6t’#6u’ 6v’6w’ 6x’6y’6z’6{•”6|•6}•‹6~•‘6¡•“6¢•’6£•Ž6¤–Š6¥–Ž6¦–‹6§–}6¨–…6©–†6ª–6«–r6¬–„6­–Á6®–Å6¯–Ä6°–Æ6±–Ç6²–ï6³–ò6´—Ì6µ˜6¶˜6·˜6¸˜ç6¹˜ê6º˜ï6»˜é6¼˜ò6½˜í6¾™®6¿™­6ÀžÃ6ÁžÍ6žÑ6ÃN‚6ÄP­6ÅPµ6ÆP²6ÇP³6ÈPÅ6ÉP¾6ÊP¬6ËP·6ÌP»6ÍP¯6ÎPÇ6ÏR6ÐRw6ÑR}6ÒRß6ÓRæ6ÔRä6ÕRâ6ÖRã6×S/6ØUß6ÙUè6ÚUÓ6ÛUæ6ÜUÎ6ÝUÜ6ÞUÇ6ßUÑ6àUã6áUä6âUï6ãUÚ6äUá6åUÅ6æUÆ6çUå6èUÉ6éW6êW6ëX^6ìXQ6íXX6îXW6ïXZ6ðXT6ñXk6òXL6óXm6ôXJ6õXb6öXR6÷XK6øYg6ùZÁ6úZÉ6ûZÌ6üZ¾6ýZ½6þZ¼7@Z³7AZÂ7BZ²7C]i7D]o7E^L7F^y7G^É7H^È7I_7J_Y7K_¬7L_®7Ma7Na7OaH7Pa7Q`ó7Ra7S`ù7Ta7Ua7VaN7WaL7XaD7YaM7Za>7[a47\a'7]a 7^a7_a77`b!7ab"7bd7cd>7dd7ed*7fd-7gd=7hd,7id7jd7kd7ld 7md67nd7od7pd7qel7reŸ7se°7tf—7uf‰7vf‡7wfˆ7xf–7yf„7zf˜7{f7|g7}i”7~im7¡iZ7¢iw7£i`7¤iT7¥iu7¦i07§i‚7¨iJ7©ih7ªik7«i^7¬iS7­iy7®i†7¯i]7°ic7±i[7²kG7³kr7´kÀ7µk¿7¶kÓ7·ký7¸n¢7¹n¯7ºnÓ7»n¶7¼nÂ7½n7¾n7¿nÇ7ÀnÅ7Án¥7Ân˜7Ãn¼7Änº7Ån«7ÆnÑ7Çn–7Ènœ7ÉnÄ7ÊnÔ7Ënª7Ìn§7Ín´7ÎqN7ÏqY7Ðqi7Ñqd7ÒqI7Óqg7Ôq\7Õql7Öqf7×qL7Øqe7Ùq^7ÚqF7Ûqh7ÜqV7Ýr:7ÞrR7ßs77àsE7ás?7âs>7ãto7ätZ7åtU7æt_7çt^7ètA7ét?7êtY7ët[7ìt\7íuv7îux7ïv7ðuð7ñv7òuò7óuñ7ôuú7õuÿ7öuô7÷uó7øvÞ7ùvß7úw[7ûwk7üwf7ýw^7þwc8@wy8Awj8Bwl8Cw\8Dwe8Ewh8Fwb8Gwî8HxŽ8Ix°8Jx—8Kx˜8LxŒ8Mx‰8Nx|8Ox‘8Px“8Qx8Ryz8Sy8Ty8U„,8Vy½8Wz8Xz8Yz 8Zz8[z8\z8]zŸ8^z 8_{w8`{À8a{`8b{n8c{g8d|±8e|³8f|µ8g}“8h}y8i}‘8j}8k}8l}[8mn8ni8oj8pr8q©8r¨8s¤8t€V8u€X8v€†8w€„8xq8yp8zx8{e8|n8}s8~k8¡y8¢z8£f8¤‚8¥‚G8¦„‚8§„w8¨„=8©„18ª„u8«„f8¬„k8­„I8®„l8¯„[8°„<8±„58²„a8³„c8´„i8µ„m8¶„F8·†^8¸†\8¹†_8º†ù8»‡8¼‡8½‡8¾‡8¿†þ8À†û8Á‡8‡8Ç8ć 8ňY8ƈß8LjÔ8ȈÙ8ɈÜ8ʈØ8ˈÝ8̈á8͈Ê8ΈÕ8ψÒ8Љœ8щã8ÒŠk8ÓŠr8ÔŠs8ÕŠf8ÖŠi8׊p8ØŠ‡8ÙŠ|8ÚŠc8ÛŠ 8ÜŠq8ÝŠ…8ÞŠm8ߊb8àŠn8áŠl8âŠy8ãŠ{8äŠ>8åŠh8æŒb8猊8茉8éŒÊ8êŒÇ8ëŒÈ8ìŒÄ8팲8îŒÃ8ïŒÂ8ðŒÅ8ñá8òß8óè8ôï8õó8öú8÷ê8øä8ùæ8ú޲8û8ü 8ýŽþ8þ 9@Ÿ9A²9BK9CJ9DS9EB9FT9G<9HU9IP9JG9KO9LN9MM9NQ9O>9PA9Q‘9R‘9S‘l9T‘j9U‘i9V‘É9W’79X’W9Y’89Z’=9[’@9\’>9]’[9^’K9_’d9`’Q9a’49b’I9c’M9d’E9e’99f’?9g’Z9h•˜9i–˜9j–”9k–•9l–Í9m–Ë9n–É9o–Ê9p–÷9q–û9r–ù9s–ö9t—V9u—t9v—v9w˜9x˜9y˜9z˜ 9{˜9|˜ 9}˜ü9~˜ô9¡˜ý9¢˜þ9£™³9¤™±9¥™´9¦šá9§œé9¨ž‚9©Ÿ9ªŸ9«Ÿ 9¬Pç9­Pî9®På9¯PÖ9°Pí9±PÚ9²PÕ9³PÏ9´PÑ9µPñ9¶PÎ9·Pé9¸Qb9¹Qó9ºRƒ9»R‚9¼S19½S­9¾Uþ9¿V9ÀV9ÁV9ÂUý9ÃV9ÄV9ÅV 9ÆV 9ÇV9ÈU÷9ÉV9ÊV9ËV9ÌV9ÍUö9ÎW9ÏW9ÐXu9ÑX~9ÒXƒ9ÓX“9ÔXŠ9ÕXy9ÖX…9×X}9ØXý9ÙY%9ÚY"9ÛY$9ÜYj9ÝYi9ÞZá9ßZæ9àZé9áZ×9âZÖ9ãZØ9äZã9å[u9æ[Þ9ç[ç9è[á9é[å9ê[æ9ë[è9ì[â9í[ä9î[ß9ï\ 9ð\b9ñ]„9ò]‡9ó^[9ô^c9õ^U9ö^W9÷^T9ø^Ó9ù^Ö9ú_ 9û_F9ü_p9ý_¹9þaG:@a?:AaK:Baw:Cab:Dac:Ea_:FaZ:GaX:Hau:Ib*:Jd‡:KdX:LdT:Md¤:Ndx:Od_:Pdz:QdQ:Rdg:Sd4:Tdm:Ud{:Ver:We¡:Xe×:YeÖ:Zf¢:[f¨:\f:]iœ:^i¨:_i•:`iÁ:ai®:biÓ:ciË:di›:ei·:fi»:gi«:hi´:iiÐ:jiÍ:ki­:liÌ:mi¦:niÃ:oi£:pkI:qkL:rl3:so3:to:unþ:vo:wnô:xo):yo>:zo :{o,:|o:}o:~o":¡nÿ:¢nï:£o:¤o1:¥o8:¦o2:§o#:¨o:©o+:ªo/:«oˆ:¬o*:­nì:®o:¯nò:°nÌ:±n÷:²q”:³q™:´q}:µqŠ:¶q„:·q’:¸r>:¹r’:ºr–:»sD:¼sP:½td:¾tc:¿tj:Àtp:Átm:Âu:Ãu‘:Äv':Åv :Æv :Çv :Èv:Évá:Êvã:Ëw„:Ìw}:Íw:Îwa:ÏxÁ:ÐxŸ:Ñx§:Òx³:Óx©:Ôx£:ÕyŽ:Öy:×y:Øz.:Ùz1:Úzª:Ûz©:Üzí:Ýzï:Þ{¡:ß{•:à{‹:á{u:â{—:ã{:ä{”:å{:æ{¸:ç{‡:è{„:é|¹:ê|½:ë|¾:ì}»:í}°:î}œ:ï}½:ð}¾:ñ} :ò}Ê:ó}´:ô}²:õ}±:ö}º:÷}¢:ø}¿:ù}µ:ú}¸:û}­:ü}Ò:ý}Ç:þ}¬;@p;Aà;Bá;Cß;D€^;E€Z;F€‡;GP;H€;I;Jˆ;KŠ;L;M‚;Nç;Oú;P‚;Q‚;R‚;S‚K;T„É;U„¿;V„Æ;W„Ä;X„™;Y„ž;Z„²;[„œ;\„Ë;]„¸;^„À;_„Ó;`„;a„¼;b„Ñ;c„Ê;d‡?;e‡;f‡;;g‡";h‡%;i‡4;j‡;k‡U;l‡7;m‡);nˆó;o‰;pˆô;qˆù;rˆø;sˆý;tˆè;u‰;vˆï;wЦ;xŠŒ;yŠž;zŠ£;{Š;|Š¡;}Š“;~Ф;¡Šª;¢Š¥;£Š¨;¤Š˜;¥Š‘;¦Šš;§Š§;¨Œj;©Œ;ªŒŒ;«ŒÓ;¬ŒÑ;­ŒÒ;®k;¯™;°•;±ü;²;³;´;µ;¶£;·`;¸X;¹\;ºc;»Y;¼^;½b;¾];¿[;À‘;Á‘;‘;Ñu;Ä‘x;Å‘w;Æ‘t;Ç’x;È’€;É’…;Ê’˜;Ë’–;Ì’{;Í’“;Î’œ;Ï’¨;Ð’|;Ñ’‘;Ò•¡;Ó•¨;Ô•©;Õ•£;Ö•¥;ו¤;Ø–™;Ù–œ;Ú–›;Û–Ì;Ü–Ò;Ý—;Þ—|;ß—…;à—ö;á˜;â˜;㘯;䘱;å™;æ™;ç™ ;è™ ;é™Á;ꚯ;ëš°;ìšæ;í›A;î›B;ïœô;ðœö;ñœó;òž¼;óŸ;;ôŸJ;õQ;öQ;÷Pû;øPõ;ùPù;úQ;ûQ;üQ ;ýQ;þQÜ<@R‡@%>Ai>Bn>Ch>Dm>Ew>F‘0>G‘->H‘'>I‘1>J‘‡>K‘‰>L‘‹>M‘ƒ>N’Å>O’»>P’·>Q’ê>R’¬>S’ä>T’Á>U’³>V’¼>W’Ò>X’Ç>Y’ð>Z’²>[•­>\•±>]—>^—>_—>`— >a—`>b—>c—‹>d—>e˜!>f˜+>g˜>h˜³>i™ >j™>k™>l™>m™Ý>n™Ð>o™ß>p™Û>q™Ñ>r™Õ>s™Ò>t™Ù>uš·>všî>wšï>x›'>y›E>z›D>{›w>|›o>}>~ >¡>¢ž©>£ž¾>¤žÎ>¥X¨>¦ŸR>§Q>¨Q>©Q>ªQ>«Q>¬Q€>­Qª>®QÝ>¯R‘>°R“>±Ró>²VY>³Vk>´Vy>µVi>¶Vd>·Vx>¸Vj>¹Vh>ºVe>»Vq>¼Vo>½Vl>¾Vb>¿Vv>ÀXÁ>ÁX¾>ÂXÇ>ÃXÅ>ÄYn>Å[>Æ[4>Ç[x>È[ð>É\>Ê_J>Ëa²>Ìa‘>Ía©>ÎaŠ>ÏaÍ>Ða¶>Ña¾>ÒaÊ>ÓaÈ>Ôb0>ÕdÅ>ÖdÁ>×dË>Ød»>Ùd¼>ÚdÚ>ÛdÄ>ÜdÇ>ÝdÂ>ÞdÍ>ßd¿>àdÒ>ádÔ>âd¾>ãet>äfÆ>åfÉ>æf¹>çfÄ>èfÇ>éf¸>êj=>ëj8>ìj:>íjY>îjk>ïjX>ðj9>ñjD>òjb>ója>ôjK>õjG>öj5>÷j_>øjH>ùkY>úkw>ûl>üoÂ>ýo±>þo¡?@oÃ?Ao¤?BoÁ?Co§?Do³?EoÀ?Fo¹?Go¶?Ho¦?Io ?Jo´?Kq¾?LqÉ?MqÐ?NqÒ?OqÈ?PqÕ?Qq¹?RqÎ?SqÙ?TqÜ?UqÃ?VqÄ?Wsh?Xtœ?Yt£?Zt˜?[tŸ?\tž?]tâ?^u ?_u ?`v4?av8?bv:?cvç?dvå?ew ?fwž?gwŸ?hw¥?ixè?jxÚ?kxì?lxç?my¦?nzM?ozN?pzF?qzL?rzK?szº?t{Ù?u|?v{É?w{ä?x{Û?y{á?z{é?{{æ?||Õ?}|Ö?~~ ?¡~?¢~?£~?¤~#?¥~?¦~?§~ ?¨~?©y?ª²?«ð?¬ñ?­î?®€(?¯³?°©?±¨?²û?³‚?´‚X?µ‚Y?¶…J?·…Y?¸…H?¹…h?º…i?»…C?¼…I?½…m?¾…j?¿…^?À‡ƒ?Á‡Ÿ?‡ž?Ç¢?ć?ňa?Ɖ*?lj2?ȉ%?ɉ+?ʉ!?ˉª?̉¦?ÍŠæ?Ίú?ÏŠë?Њñ?Ñ‹?ÒŠÜ?ÓŠç?ÔŠî?ÕŠþ?Ö‹?׋?ØŠ÷?ÙŠí?ÚŠó?ÛŠö?ÜŠü?ÝŒk?ÞŒm?ߌ“?àŒô?áŽD?âŽ1?ãŽ4?äŽB?åŽ9?æŽ5?ç;?è/?é8?ê3?ë¨?ì¦?íu?ît?ïx?ðr?ñ|?òz?ó‘4?ô‘’?õ“ ?ö“6?÷’ø?ø“3?ù“/?ú“"?û’ü?ü“+?ý“?þ“@@“@A“&@B“!@C“@D“.@E“@F•»@G–§@H–¨@I–ª@J–Õ@K—@L—@M—@N— @O—@P—@Q—[@R—\@S—f@T—˜@U˜0@V˜8@W˜;@X˜7@Y˜-@Z˜9@[˜$@\™@]™(@^™@_™@`™!@a™@b™í@c™â@d™ñ@eš¸@fš¼@gšû@hší@i›(@j›‘@k@l#@m&@n(@o@p@qžØ@ržÔ@sŸ@tŸœ@uQ*@vQ@wQ!@xQ2@yRõ@zVŽ@{V€@|V@}V…@~V‡@¡V@¢XÕ@£XÓ@¤XÑ@¥XÎ@¦[0@§[*@¨[$@©[z@ª\7@«\h@¬]¼@­]º@®]½@¯]¸@°^k@±_L@²_½@³aÉ@´aÂ@µaÇ@¶aæ@·aË@¸b2@¹b4@ºdÎ@»dÊ@¼dØ@½dà@¾dð@¿dæ@Àdì@Ádñ@Âdâ@Ãdí@Äe‚@Åeƒ@ÆfÙ@ÇfÖ@Èj€@Éj”@Êj„@Ëj¢@Ìjœ@ÍjÛ@Îj£@Ïj~@Ðj—@Ñj@Òj @Ók\@Ôk®@ÕkÚ@Öl@×oØ@Øoñ@Ùoß@Úoà@ÛoÛ@Üoä@Ýoë@Þoï@ßo€@àoì@áoá@âoé@ãoÕ@äoî@åoð@æqç@çqß@èqî@éqæ@êqå@ëqí@ìqì@íqô@îqà@ïr5@ðrF@ñsp@òsr@ót©@ôt°@õt¦@öt¨@÷vF@øvB@ùvL@úvê@ûw³@üwª@ýw°@þw¬A@w§AAw­ABwïACx÷ADxúAExôAFxïAGyAHy§AIyªAJzWAKz¿AL|AM| AN{þAO{÷AP| AQ{àAR|àAS|ÜAT|ÞAU|âAV|ßAW|ÙAX|ÝAY~.AZ~>A[~FA\~7A]~2A^~CA_~+A`~=Aa~1Ab~EAc~AAd~4Ae~9Af~HAg~5Ah~?Ai~/AjDAkóAlüAm€qAn€rAo€pAp€oAq€sArÆAsÃAtºAuÂAvÀAw¿Ax½AyÉAz¾A{èA|‚ A}‚qA~…ªA¡…„A¢…~A£…œA¤…‘A¥…”A¦…¯A§…›A¨…‡A©…¨Aª…ŠA«†gA¬‡ÀA­‡ÑA®‡³A¯‡ÒA°‡ÆA±‡«A²‡»A³‡ºA´‡ÈAµ‡ËA¶‰;A·‰6A¸‰DA¹‰8Aº‰=A»‰¬A¼‹A½‹A¾‹A¿‹AÀ‹ AÁ‹ A‹AËAÄ‹AÅŒAAÆŒ?AÇŒsAÈŒúAÉŒýAÊŒüAËŒøAÌŒûAͨAÎŽIAÏŽKAÐŽHAÑŽJAÒDAÓ>AÔBAÕEAÖ?A×AØ}AÙ„AÚAÛ‚AÜ€AÝ‘9AÞ‘£Aß‘žAà‘œAá“MAâ“‚Aã“(Aä“uAå“JAæ“eAç“KAè“Aé“~Aê“lAë“[Aì“pAí“ZAî“TAï•ÊAð•ËAñ•ÌAò•ÈAó•ÆAô–±Aõ–¸Aö–ÖA÷—Aø—Aù— Aú—ÓAû˜FAü˜¶Aý™5AþšB@™ÿBA›®BB›«BC›ªBD›­BE;BF?BGž‹BHžÏBIžÞBJžÜBKžÝBLžÛBMŸ>BNŸKBOSâBPV•BQV®BRXÙBSXØBT[8BU_]BVaãBWb3BXdôBYdòBZdþB[eB\dúB]dûB^d÷B_e·B`fÜBag&Bbj³Bcj¬BdjÃBej»Bfj¸BgjÂBhj®Bij¯Bjk_BkkxBlk¯Bmp Bnp BooþBppBqoúBrpBspBtqûBuqüBvqþBwqøBxswBysuBzt§B{t¿B|uB}vVB~vXB¡vRB¢w½B£w¿B¤w»B¥w¼B¦yB§y®B¨zaB©zbBªz`B«zÄB¬zÅB­|+B®|'B¯|*B°|B±|#B²|!B³|çB´~TBµ~UB¶~^B·~ZB¸~aB¹~RBº~YB»HB¼ùB½ûB¾€wB¿€vBÀÍBÁÏB‚ BÃ…ÏBÄ…©BÅ…ÍBÆ…ÐBÇ…ÉBÈ…°BÉ…ºBÊ…¹BË…¦ḂïB͇ìB·òBχàBЉ†Bщ²BÒ‰ôBÓ‹(BÔ‹9BÕ‹,BÖ‹+B׌PBØBÙŽYBÚŽcBÛŽfBÜŽdBÝŽ_BÞŽUBߎÀBàIBáMBâ‡BãƒBäˆBå‘«B摬Bç‘ÐBè“”B铊Bê“–Bë“¢B쓳Bí“®BBï“°Bð“˜Bñ“šBò“—Bó•ÔBô•ÖBõ•ÐBö•ÕB÷–âBø–ÜBù–ÙBú–ÛBû–ÞBü—$Bý—£Bþ—¦C@—­CA—ùCB˜MCC˜OCD˜LCE˜NCF˜SCG˜ºCH™>CI™?CJ™=CK™.CL™¥CMšCNšÁCO›CP›CQ›OCR›NCS›MCT›ÊCU›ÉCV›ýCW›ÈCX›ÀCYQCZ]C[`C\žàC]ŸC^Ÿ,C_Q3C`V¥CaXÞCbXßCcXâCd[õCeŸCf^ìCgaòCha÷CiaöCjaõCkeCleCmfàCnfÝCojåCpjÝCqjÚCrjÓCspCtpCup(CvpCwpCxpCypCzrC{r C|rXC}r¢C~sxC¡szC¢t½C£tÊC¤tãC¥u‡C¦u†C§v_C¨vaC©wÇCªyC«y±C¬zkC­ziC®|>C¯|?C°|8C±|=C²|7C³|@C´~kCµ~mC¶~yC·~iC¸~jC¹…Cº~sC»¶C¼¹C½¸C¾ØC¿…éCÀ…ÝCÁ…êCÂ…ÕCÃ…äCÄ…åCÅ…÷CƇûCLjCȈ CɇùCʇþCˉ`C̉_C͉VCΉ^CÏ‹ACЋ\CÑ‹XCÒ‹ICÓ‹ZCÔ‹NCÕ‹OCÖ‹FC׋YCØCÙ CÚŽ|CÛŽrCÜŽ‡CÝŽvCÞŽlCߎzCàŽtCáTCâNCã­CäŠCå‹C摱Cç‘®Cè“áCé“ÑCê“ßCë“ÃCì“ÈCí“ÜCî“ÝCï“ÖCð“âCñ“ÍCò“ØCó“äCô“×Cõ“èCö•ÜC÷–´Cø–ãCù—*Cú—'Cû—aCü—ÜCý—ûCþ˜^D@˜XDA˜[DB˜¼DC™EDD™IDEšDFšDG› DH›èDI›çDJ›ÖDK›ÛDL‰DMaDNrDOjDPlDQž’DRž—DSž“DTž´DURøDVV¨DWV·DXV¶DYV´DZV¼D[XäD\[@D][CD^[}D_[öD`]ÉDaaøDbaúDceDdeDeeDffæDgg'DhjìDip>Djp0Dkp2DlrDms{DntÏDovbDpveDqy&Dry*Dsy,Dty+DuzÇDvzöDw|LDx|CDy|MDz|ïD{|ðD|®D}~}D~~|D¡~‚D¢LD£€D¤ÚD¥‚fD¦…ûD§…ùD¨†D©…úDª†D«† D¬†D­† D®ˆD¯ˆD°‰dD±‰ºD²‰øD³‹pD´‹lDµ‹fD¶‹oD·‹_D¸‹kD¹Dº D»Ž‰D¼ŽD½Ž…D¾Ž‚D¿‘´DÀ‘ËDÁ”D”DÓýDÄ•áDÅ—0DƘÄDÇ™RDÈ™QDÉ™¨DÊš+DËš0DÌš7DÍš5DΜDÏœ DОyDÑžµDÒžèDÓŸ/DÔŸ_DÕŸcDÖŸaD×Q7DØQ8DÙVÁDÚVÀDÛVÂDÜYDÝ\lDÞ]ÍDßaüDàaþDáeDâeDãe•DäféDåjûDækDçjúDèk²DépLDêrDër§DìtÖDítÔDîviDïwÓDð|PDñ~Dò~ŒDó¼Dô†Dõ†-Dö†D÷ˆ#Døˆ"Dùˆ!DúˆDû‰jDü‰lDý‰½Dþ‹tE@‹wEA‹}EBECŽŠEDŽEEŽ‹EF_EG¯EH‘ºEI”.EJ”3EK”5EL”:EM”8EN”2EO”+EP•âEQ—8ER—9ES—2ET—ÿEU˜gEV˜eEW™WEXšEEYšCEZš@E[š>E\šÏE]›TE^›QE_œ-E`œ%Ea¯Eb´EcÂEd¸EežEfžïEgŸEhŸ\EiŸfEjŸgEkQE¶—ÃE·—ÁE¸˜kE¹™UEºšUE»šME¼šÒE½›E¾œIE¿œ1EÀœ>EÁœ;EÂÓEÃ×EÄŸ4EÅŸlEÆŸjEÇŸ”EÈVÌEÉ]ÖEÊbEËe#EÌe+EÍe*EÎfìEÏkEÐtÚEÑzÊEÒ|dEÓ|cEÔ|eEÕ~“EÖ~–E×~”EØâEÙ†8EÚ†?EÛˆ1EÜ‹ŠEÝEÞEß”cEà”`Eá”dEâ—hEã˜oEä™\EåšZEæš[EçšWEèšÓEéšÔEêšÑEëœTEìœWEíœVEîåEEðžôEñVÑEòXéEóe,Eôp^EõvqEövrE÷w×EøPEùˆEúˆ6Eûˆ9EüˆbEý‹“Eþ‹’F@‹–FA‚wFBFC‘ÀFD”jFE—BFF—HFG—DFH—ÆFI˜pFJš_FK›"FL›XFMœ_FNùFOúFPž|FQž}FRŸFSŸwFTŸrFU^óFVkFWpcFX|lFY|nFZˆ;F[‰ÀF\Ž¡F]‘ÁF^”rF_”pF`˜qFa™^FbšÖFc›#FdžÌFepdFfwÚFg‹šFh”wFi—ÉFjšbFkšeFl~œFm‹œFnŽªFo‘ÅFp”}Fq”~Fr”|FsœwFtœxFuž÷FvŒTFw”FxžFyr(FzšjF{›1F|žF}žF~|rF¡0þF¢0F£0žF¤0F¥0AF¦0BF§0CF¨0DF©0EFª0FF«0GF¬0HF­0IF®0JF¯0KF°0LF±0MF²0NF³0OF´0PFµ0QF¶0RF·0SF¸0TF¹0UFº0VF»0WF¼0XF½0YF¾0ZF¿0[FÀ0\FÁ0]FÂ0^FÃ0_FÄ0`FÅ0aFÆ0bFÇ0cFÈ0dFÉ0eFÊ0fFË0gFÌ0hFÍ0iFÎ0jFÏ0kFÐ0lFÑ0mFÒ0nFÓ0oFÔ0pFÕ0qFÖ0rF×0sFØ0tFÙ0uFÚ0vFÛ0wFÜ0xFÝ0yFÞ0zFß0{Fà0|Fá0}Fâ0~Fã0Fä0€Få0Fæ0‚Fç0ƒFè0„Fé0…Fê0†Fë0‡Fì0ˆFí0‰Fî0ŠFï0‹Fð0ŒFñ0Fò0ŽFó0Fô0Fõ0‘Fö0’F÷0“Fø0¡Fù0¢Fú0£Fû0¤Fü0¥Fý0¦Fþ0§G@0¨GA0©GB0ªGC0«GD0¬GE0­GF0®GG0¯GH0°GI0±GJ0²GK0³GL0´GM0µGN0¶GO0·GP0¸GQ0¹GR0ºGS0»GT0¼GU0½GV0¾GW0¿GX0ÀGY0ÁGZ0ÂG[0ÃG\0ÄG]0ÅG^0ÆG_0ÇG`0ÈGa0ÉGb0ÊGc0ËGd0ÌGe0ÍGf0ÎGg0ÏGh0ÐGi0ÑGj0ÒGk0ÓGl0ÔGm0ÕGn0ÖGo0×Gp0ØGq0ÙGr0ÚGs0ÛGt0ÜGu0ÝGv0ÞGw0ßGx0àGy0áGz0âG{0ãG|0äG}0åG~0æG¡0çG¢0èG£0éG¤0êG¥0ëG¦0ìG§0íG¨0îG©0ïGª0ðG«0ñG¬0òG­0óG®0ôG¯0õG°0öG±G²G³G´GµG¶G·G¸G¹GºG»#G¼$G½%G¾&G¿'GÀ(GÁ)GÂ*GÃ+GÄ,GÅ-GÆ.GÇ/GÈ0GÉ1GÊ2GË3GÌ4GÍ5GÎQGÏ6GÐ7GÑ8GÒ9GÓ:GÔ;GÕGØ?GÙ@GÚAGÛBGÜCGÝDGÞEGßFGàGGáHGâIGãJGäKGåLGæMGçNGèOGé$`Gê$aGë$bGì$cGí$dGî$eGï$fGð$gGñ$hGò$iGó$tGô$uGõ$vGö$wG÷$xGø$yGù$zGú${Gû$|Gü$}I@NBIAN\IBQõICSIDS‚IENIFN IGNGIHNIIV×IJú IK\nIL_sIMNINQ‡IONIPN.IQN“IRNÂISNÉITNÈIUQ˜IVRüIWSlIXS¹IYW IZYI[Y,I\\I]]ÿI^eáI_k³I`kÌIalIbr?IcN1IdNIðg9Iñg8Iòg;Ióg:Iôg?IõgJaOgJbORJcO_JdOAJeOXJfO-JgO3JhO?JiOaJjQJkQ¹JlRJmRJnR!JoR­JpR®JqS JrScJsSrJtSŽJuSJvT0JwT7JxT*JyTTJzTEJ{TJ|TJ}T%J~TJ¡T=J¢TOJ£TAJ¤T(J¥T$J¦TGJ§VîJ¨VçJ©VåJªWAJ«WEJ¬WLJ­WIJ®WKJ¯WRJ°YJ±Y@J²Y¦J³Y˜J´Y JµY—J¶YŽJ·Y¢J¸YJ¹YJºY§J»Y¡J¼[ŽJ½[’J¾\(J¿\*JÀ\JÁ\JÂ\ˆJÃ\‹JÄ\‰JÅ\’JÆ\ŠJÇ\†JÈ\“JÉ\•JÊ]àJË^ JÌ^JÍ^‹JÎ^‰JÏ^ŒJÐ^ˆJÑ^JÒ_JÓ_JÔ_xJÕ_vJÖ_ÒJ×_ÑJØ_ÐJÙ_íJÚ_èJÛ_îJÜ_óJÝ_áJÞ_äJß_ãJà_úJá_ïJâ_÷Jã_ûJä`Jå_ôJæb:JçbƒJèbŒJébŽJêbJëb”Jìb‡JíbqJîb{JïbzJðbpJñbJòbˆJóbwJôb}JõbrJöbtJ÷e7JøeðJùeôJúeóJûeòJüeõJýgEJþgGK@gYKAgUKBgLKCgHKDg]KEgMKFgZKGgKKHkÐKIlKJlKKlxKLlgKMlkKNl„KOl‹KPlKQlqKRloKSliKTlšKUlmKVl‡KWl•KXlœKYlfKZlsK[leK\l{K]lŽK^ptK_pzK`rcKar¿Kbr½KcrÃKdrÆKerÁKfrºKgrÅKhs•Kis—Kjs“Kks”Kls’Kmu:Knu9Kou”Kpu•KqvKry=Ks€4Kt€•Ku€™Kv€Kw€’Kx€œKy‚Kz‚K{‚…K|‚ŽK}‚‘K~‚“K¡‚ŠK¢‚ƒK£‚„K¤ŒxK¥ÉK¦¿K§ŸK¨¡K©¥KªžK«§K¬ K­–0K®–(K¯–/K°–-K±N3K²O˜K³O|K´O…KµO}K¶O€K·O‡K¸OvK¹OtKºO‰K»O„K¼OwK½OLK¾O—K¿OjKÀOšKÁOyKÂOKÃOxKÄOKÅOœKÆO”KÇOžKÈO’KÉO‚KÊO•KËOkKÌOnKÍQžKÎQ¼KÏQ¾KÐR5KÑR2KÒR3KÓRFKÔR1KÕR¼KÖS K×S KØSMsuŒMtu˜Muv¯MvvóMwvñMxvðMyvõMzwøM{wüM|wùM}wûM~wúM¡w÷M¢yBM£y?M¤yÅM¥zxM¦z{M§zûM¨|uM©|ýMª€5M«€M¬€®M­€£M®€¸M¯€µM°€­M±‚ M²‚ M³‚ÀM´‚«Mµ‚šM¶‚˜M·‚›M¸‚µM¹‚§Mº‚®M»‚¼M¼‚žM½‚ºM¾‚´M¿‚¨MÀ‚¡MÁ‚©M‚ÂM¤MÄ‚ÃMÅ‚¶MÆ‚¢MdžpMȆoMɆmMʆnMËŒVMÌÒMÍËMÎÓMÏÍMÐÖMÑÕMÒ×MÓ²MÔ´MÕ¯MÖ³M×°MØ–9MÙ–=MÚ–Sh€9Si€úSj€òSk€ùSl€õSmSn€ûSoSp‚Sq‚/Sr‚%Ssƒ3Stƒ-SuƒDSvƒSwƒQSxƒ%SyƒVSzƒ?S{ƒAS|ƒ&S}ƒS~ƒ"S¡ƒBS¢ƒNS£ƒS¤ƒ*S¥ƒS¦ƒTåZMTæZ9TçZLTèZpTéZiTêZGTëZQTìZVTíZBTîZ\Tï[rTð[nTñ[ÁTò[ÀTó\YTô]Tõ] Tö]T÷]Tø] Tù] Tú](Tû] Tü]&Tý]%Tþ]U@]0UA]UB]#UC]UD].UE^>UF^4UG^±UH^´UI^¹UJ^²UK^³UL_6UM_8UN_›UO_–UP_ŸUQ`ŠUR`US`†UT`¾UU`°UV`ºUW`ÓUX`ÔUY`ÏUZ`äU[`ÙU\`ÝU]`ÈU^`±U_`ÛU``·Ua`ÊUb`¿Uc`ÃUd`ÍUe`ÀUfc2UgceUhcŠUic‚Ujc}Ukc½UlcžUmc­UncUoc—Upc«UqcŽUrcoUsc‡UtcUucnUvc¯UwcuUxcœUycmUzc®U{c|U|c¤U}c;U~cŸU¡cxU¢c…U£cU¤c‘U¥cU¦cpU§eSU¨eÍU©feUªfaU«f[U¬fYU­f\U®fbU¯gU°hyU±h‡U²hU³hœU´hmUµhnU¶h®U·h«U¸iVU¹hoUºh£U»h¬U¼h©U½huU¾htU¿h²UÀhUÁhwUÂh’UÃh|UÄhkUÅhrUÆhªUÇh€UÈhqUÉh~UÊh›UËh–UÌh‹UÍh UÎh‰UÏh¤UÐhxUÑh{UÒh‘UÓhŒUÔhŠUÕh}UÖk6U×k3UØk7UÙk8UÚk‘UÛkUÜkUÝkŽUÞkŒUßl*UàmÀUám«Uâm´Uãm³UäntUåm¬UæméUçmâUèm·UémöUêmÔUënUìmÈUímàUîmßUïmÖUðm¾UñmåUòmÜUómÝUômÛUõmôUömÊU÷m½UømíUùmðUúmºUûmÕUümÂUýmÏUþmÉV@mÐVAmòVBmÓVCmýVDm×VEmÍVFmãVGm»VHpúVIq VJp÷VKqVLpôVMq VNpðVOqVPpóVQqVRpüVSpÿVTqVUqVVqVWpøVXpöVYq VZqV[qV\r~V]r{V^r|V_rV`sVasVbsVcsVdsVes VfsVgrÿVhsVisVjsˆVksöVlsøVmsõVntVotVpsýVqtVrtVssúVtsüVusÿVvt Vwt VxsôVytVzudV{ucV|uÎV}uÒV~uÏV¡uËV¢uÌV£uÑV¤uÐV¥vV¦v‰V§vÓV¨w9V©w/Vªw-V«w1V¬w2V­w4V®w3V¯w=V°w%V±w;V²w5V³xHV´xRVµxIV¶xMV·xJV¸xLV¹x&VºxEV»xPV¼ydV½ygV¾yiV¿yjVÀycVÁykVÂyaVÃy»VÄyúVÅyøVÆyöVÇy÷VÈzVÉz”VÊzVË{5VÌ{GVÍ{4VÎ{%VÏ{0VÐ{"VÑ{$VÒ{3VÓ{VÔ{*VÕ{VÖ{1V×{+VØ{-VÙ{/VÚ{2VÛ{8VÜ{VÝ{#VÞ|”Vß|˜Và|–Vá|£Vâ}5Vã}=Vä}8Vå}6Væ}:Vç}EVè},Vé})Vê}AVë}GVì}>Ví}?Vî}JVï};Vð}(VñcVò•VóœVôVõ›VöÊV÷ËVøÍVùÐVúÑVûÇVüÏVýÉVþ€W@€WA€WB€GWC€CWD€HWEWF%WGWHWI-WJWK,WLWM!WNWO'WPWQ"WR‚WS‚8WT‚3WU‚:WV‚4WW‚2WX‚tWYƒWZƒ£W[ƒ¨W\ƒW]ƒzW^ƒsW_ƒ¤W`ƒtWaƒWbƒWcƒ•Wdƒ™WeƒuWfƒ”Wgƒ©Whƒ}WiƒƒWjƒŒWkƒWlƒ›WmƒªWnƒ‹Woƒ~Wpƒ¥Wqƒ¯WrƒˆWsƒ—Wtƒ°WuƒWvƒ¦Wwƒ‡Wxƒ®WyƒvWzƒšW{†YW|†VW}†¿W~†·W¡†ÂW¢†ÁW£†ÅW¤†ºW¥†°W¦†ÈW§†¹W¨†³W©†¸Wª†ÌW«†´W¬†»W­†¼W®†ÃW¯†½W°†¾W±ˆRW²ˆ‰W³ˆ•W´ˆ¨Wµˆ¢W¶ˆªW·ˆšW¸ˆ‘W¹ˆ¡WºˆŸW»ˆ˜W¼ˆ§W½ˆ™W¾ˆ›W¿ˆ—WÀˆ¤WÁˆ¬WˆŒWÈ“WĈŽWʼn‚WƉÖWljÙWȉÕWÉŠ0WÊŠ'WËŠ,WÌŠWÍŒ9WÎŒ;WÏŒ\WÐŒ]WÑŒ}WÒŒ¥WÓ}WÔ{WÕyWÖ¼W×ÂWعWÙ¿WÚÁWÛŽØWÜŽÞWÝŽÝWÞŽÜWߎ×WàŽàWáŽáWâ$Wã WäWåWæ Wç!WèïWéêWêðWëôWìòWíóWîÔWïëWðìWñéWò‘VWó‘XWô‘ZWõ‘SWö‘UW÷‘ìWø‘ôWù‘ñWú‘óWû‘øWü‘äWý‘ùWþ‘êX@‘ëXA‘÷XB‘èXC‘îXD•zXE•†XF•ˆXG–|XH–mXI–kXJ–qXK–oXL–¿XM—jXN˜XO˜åXP™—XQP›XRP•XSP”XTPžXUP‹XVP£XWPƒXXPŒXYPŽXZPX[PhX\PœX]P’X^P‚X_P‡X`Q_XaQÔXbSXcSXdS¤XeS§XfU‘XgU¨XhU¥XiU­XjUwXkVEXlU¢XmU“XnUˆXoUXpUµXqUXrU£XsU’XtU¤XuU}XvUŒXwU¦XxUXyU•XzU¡X{UŽX|W X}X)X~X7X¡XX¢XX£X'X¤X#X¥X(X¦WõX§XHX¨X%X©XXªXX«X3X¬X?X­X6X®X.X¯X9X°X8X±X-X²X,X³X;X´YaXµZ¯X¶Z”X·ZŸX¸ZzX¹Z¢XºZžX»ZxX¼Z¦X½Z|X¾Z¥X¿Z¬XÀZ•XÁZ®XÂZ7XÃZ„XÄZŠXÅZ—XÆZƒXÇZ‹XÈZ©XÉZ{XÊZ}XËZŒXÌZœXÍZXÎZ“XÏZXÐ[êXÑ[ÍXÒ[ËXÓ[ÔXÔ[ÑXÕ[ÊXÖ[ÎX×\ XØ\0XÙ]7XÚ]CXÛ]kXÜ]AXÝ]KXÞ]?Xß]5Xà]QXá]NXâ]UXã]3Xä]:Xå]RXæ]=Xç]1Xè]YXé]BXê]9Xë]IXì]8Xí]Zý?Zþe[@f[A¢[B [C¡[D×[E€Q[F€O[G€P[H€þ[I€Ô[JC[KJ[LR[MO[NG[O=[PM[Q:[Ræ[Sî[T÷[Uø[Vù[W‚[X‚<[Y‚=[Z‚?[[‚u[\ƒ;[]ƒÏ[^ƒù[_„#[`ƒÀ[aƒè[b„[cƒç[dƒä[eƒü[fƒö[g„[hƒÆ[iƒÈ[jƒë[kƒã[lƒ¿[m„[nƒÝ[oƒå[pƒØ[qƒÿ[rƒá[sƒË[tƒÎ[uƒÖ[vƒõ[wƒÉ[x„ [y„[zƒÞ[{„[|„[}ƒÂ[~ƒó[¡ƒÕ[¢ƒú[£ƒÇ[¤ƒÑ[¥ƒê[¦„[§ƒÃ[¨ƒì[©ƒî[ªƒÄ[«ƒû[¬ƒ×[­ƒâ[®„[¯ƒÛ[°ƒþ[±†Ø[²†â[³†æ[´†Ó[µ†ã[¶†Ú[·†ê[¸†Ý[¹†ë[º†Ü[»†ì[¼†é[½†×[¾†è[¿†Ñ[ÀˆH[ÁˆV[ˆU[Ⱥ[Ĉ×[ň¹[ƈ¸[LjÀ[Ȉ¾[Ɉ¶[ʈ¼[ˈ·[̈½[͈²[Ή[ψÉ[Љ•[щ˜[Ò‰—[Ó‰Ý[Ô‰Ú[Õ‰Û[ÖŠN[׊M[ØŠ9[ÙŠY[ÚŠ@[ÛŠW[ÜŠX[ÝŠD[ÞŠE[ߊR[àŠH[áŠQ[âŠJ[ãŠL[äŠO[åŒ_[æŒ[猀[茺[錾[ꌰ[댹[쌵[í„[î€[ï‰[ðØ[ñÓ[òÍ[óÇ[ôÖ[õÜ[öÏ[÷Õ[øÙ[ùÈ[ú×[ûÅ[üŽï[ýŽ÷[þŽú\@Žù\AŽæ\BŽî\CŽå\DŽõ\EŽç\FŽè\GŽö\HŽë\IŽñ\JŽì\KŽô\LŽé\M-\N4\O/\P‘\Q‘,\R‘\Sÿ\Tü\U‘\Vù\Wû\X‘\Y‘\Z‘\[‘\\‘\]‘a\^‘d\_‘_\`‘b\a‘`\b’\c’ \d’%\e’\f’\g’&\h’\i’ \j’\k’\l‘ÿ\m‘ý\n’\o’\p’'\q’\r’\s’$\t’\u’\v’\w’\x•{\y•\z•Œ\{•\|–‡\}–~\~–ˆ\¡–‰\¢–ƒ\£–€\¤–Â\¥–È\¦–Ã\§–ñ\¨–ð\©—l\ª—p\«—n\¬˜\­˜©\®˜ë\¯œæ\°žù\±Nƒ\²N„\³N¶\´P½\µP¿\¶PÆ\·P®\¸PÄ\¹PÊ\ºP´\»PÈ\¼PÂ\½P°\¾PÁ\¿Pº\ÀP±\ÁPË\ÂPÉ\ÃP¶\ÄP¸\ÅQ×\ÆRz\ÇRx\ÈR{\ÉR|\ÊUÃ\ËUÛ\ÌUÌ\ÍUÐ\ÎUË\ÏUÊ\ÐUÝ\ÑUÀ\ÒUÔ\ÓUÄ\ÔUé\ÕU¿\ÖUÒ\×U\ØUÏ\ÙUÕ\ÚUâ\ÛUÖ\ÜUÈ\ÝUò\ÞUÍ\ßUÙ\àUÂ\áW\âXS\ãXh\äXd\åXO\æXM\çXI\èXo\éXU\êXN\ëX]\ìXY\íXe\îX[\ïX=\ðXc\ñXq\òXü\óZÇ\ôZÄ\õZË\öZº\÷Z¸\øZ±\ùZµ\úZ°\ûZ¿\üZÈ\ýZ»\þZÆ]@Z·]AZÀ]BZÊ]CZ´]DZ¶]EZÍ]FZ¹]GZ]H[Ö]I[Ø]J[Ù]K\]L\3]M]q]N]c]O]J]P]e]Q]r]R]l]S]^]T]h]U]g]V]b]W]ð]X^O]Y^N]Z^J][^M]\^K]]^Å]^^Ì]_^Æ]`^Ë]a^Ç]b_@]c_¯]d_­]e`÷]faI]gaJ]ha+]iaE]ja6]ka2]la.]maF]na/]oaO]pa)]qa@]rb ]s‘h]tb#]ub%]vb$]wcÅ]xcñ]ycë]zd]{d]|d ]}d ]~d$]¡d3]¢dC]£d]¤d]¥d]¦d9]§d7]¨d"]©d#]ªd ]«d&]¬d0]­d(]®dA]¯d5]°d/]±d ]²d]³d@]´d%]µd']¶d ]·cç]¸d]¹d.]ºd!]»d]¼eo]½e’]¾eÓ]¿f†]ÀfŒ]Áf•]Âf]Ãf‹]ÄfŠ]Åf™]Æf”]Çfx]Èg ]Éif]Êi_]Ëi8]ÌiN]Íib]Îiq]Ïi?]ÐiE]Ñij]Òi9]ÓiB]ÔiW]ÕiY]Öiz]×iH]ØiI]Ùi5]Úil]Ûi3]Üi=]Ýie]Þhð]ßix]ài4]áii]âi@]ãio]äiD]åiv]æiX]çiA]èit]éiL]êi;]ëiK]ìi7]íi\]îiO]ïiQ]ði2]ñiR]òi/]ói{]ôi<]õkF]ökE]÷kC]økB]ùkH]úkA]ûk›]üú ]ýkû]þkü^@kù^Ak÷^Bkø^Cn›^DnÖ^EnÈ^Fn^GnÀ^HnŸ^In“^Jn”^Kn ^Ln±^Mn¹^NnÆ^OnÒ^Pn½^QnÁ^Rnž^SnÉ^Tn·^Un°^VnÍ^Wn¦^XnÏ^Yn²^Zn¾^[nÃ^\nÜ^]nØ^^n™^_n’^`nŽ^an^bn¤^cn¡^dn¿^en³^fnÐ^gnÊ^hn—^in®^jn£^kqG^lqT^mqR^nqc^oq`^pqA^qq]^rqb^sqr^tqx^uqj^vqa^wqB^xqX^yqC^zqK^{qp^|q_^}qP^~qS^¡qD^¢qM^£qZ^¤rO^¥r^¦rŒ^§r‘^¨r^©rŽ^ªs<^«sB^¬s;^­s:^®s@^¯sJ^°sI^±tD^²tJ^³tK^´tR^µtQ^¶tW^·t@^¸tO^¹tP^ºtN^»tB^¼tF^½tM^¾tT^¿tá^Àtÿ^Átþ^Âtý^Ãu^Äuy^Åuw^Æiƒ^Çuï^Èv^Év^Êu÷^Ëuþ^Ìuü^Íuù^Îuø^Ïv^Ðuû^Ñuö^Òuí^Óuõ^Ôuý^Õv™^Övµ^×vÝ^ØwU^Ùw_^Úw`^ÛwR^ÜwV^ÝwZ^Þwi^ßwg^àwT^áwY^âwm^ãwà^äx‡^åxš^æx”^çx^èx„^éx•^êx…^ëx†^ìx¡^íxƒ^îxy^ïx™^ðx€^ñx–^òx{^óy|^ôy‚^õy}^öyy^÷z^øz^ùz^úz^ûz^üz^ýz"^þz_@z_Az_Bz£_Cz¢_Dzž_Ezë_F{f_G{d_H{m_I{t_J{i_K{r_L{e_M{s_N{q_O{p_P{a_Q{x_R{v_S{c_T|²_U|´_V|¯_W}ˆ_X}†_Y}€_Z}_[}_\}…_]}z_^}Ž__}{_`}ƒ_a}|_b}Œ_c}”_d}„_e}}_f}’_gm_hk_ig_jh_kl_l¦_m¥_n§_oÛ_pÜ_q€!_rd_s`_tw_u\_vi_w[_xb_yr_zg!_{^_|v_}g_~o_¡D_¢a_£‚_¤‚I_¥‚D_¦‚@_§‚B_¨‚E_©„ñ_ª„?_«„V_¬„v_­„y_®„_¯„_°„e_±„Q_²„@_³„†_´„g_µ„0_¶„M_·„}_¸„Z_¹„Y_º„t_»„s_¼„]_½…_¾„^_¿„7_À„:_Á„4_„z_ÄC_Ä„x_Å„2_Æ„E_Ç„)_ȃÙ_É„K_Ê„/_Ë„B_Ì„-_Í„__΄p_Ï„9_ЄN_Ñ„L_Ò„R_Ó„o_Ô„Å_Õ„Ž_Ö„;_ׄG_Ø„6_Ù„3_Ú„h_Û„~_Ü„D_Ý„+_Þ„`_ß„T_à„n_á„P_⇠_ã‡_ä†÷_å‡ _æ†ú_ç†Ö_è†õ_é‡M_ê†ø_ë‡_ì‡ _í‡_î†ö_ï‡ _ð‡_ñˆÖ_òˆË_óˆÍ_ôˆÎ_õˆÞ_öˆÛ_÷ˆÚ_øˆÌ_ùˆÐ_ú‰…_û‰›_ü‰ß_ý‰å_þ‰ä`@‰á`A‰à`B‰â`C‰Ü`D‰æ`EŠv`FІ`GŠ`HŠa`IŠ?`JŠw`KŠ‚`LŠ„`MŠu`NŠƒ`OŠ`PŠt`QŠz`RŒ<`SŒK`TŒJ`UŒe`VŒd`WŒf`XŒ†`YŒ„`ZŒ…`[ŒÌ`\h`]i`^‘`_Œ``Ž`a`b`c“`d”`e`f’`gð`hà`iì`jñ`kî`lÐ`mé`nã`oâ`pç`qò`rë`sô`t`uŽÿ`v`w`x`y`z`{`| `}R`~?`¡D`¢I`£=`¤‘`¥‘ `¦‘`§‘`¨‘`©‘`ª‘ `«‘`¬‘n`­‘o`®’H`¯’R`°’0`±’:`²’f`³’3`´’e`µ’^`¶’ƒ`·’.`¸’J`¹’F`º’m`»’l`¼’O`½’``¾’g`¿’o`À’6`Á’a`Â’p`Ã’1`Ä’T`Å’c`Æ’P`Ç’r`È’N`É’S`Ê’L`Ë’V`Ì’2`Í•Ÿ`Εœ`Ï•ž`Е›`Ñ–’`Ò–“`Ó–‘`Ô–—`Õ–Î`Ö–ú`×–ý`Ø–ø`Ù–õ`Ú—s`Û—w`Ü—x`Ý—r`Þ˜`ߘ `à˜`ᘬ`â˜ö`ã˜ù`䙯`噲`æ™°`癵`èš­`éš«`ê›[`ëœê`ìœí`íœç``ïžý`ðPæ`ñPÔ`òP×`óPè`ôPó`õPÛ`öPê`÷PÝ`øPä`ùPÓ`úPì`ûPð`üPï`ýPã`þPàa@QØaAR€aBRaCRéaDRëaES0aFS¬aGV'aHVaIV aJVaKUüaLVaMVaNVaOVaPVaQUúaRVaSVaTUÿaUUùaVX‰aWX|aXXaYX˜aZX†a[Xa\Xa]Xta^X‹a_Xza`X‡aaX‘abXŽacXvadX‚aeXˆafX{agX”ahXaiXþajYkakZÜalZîamZåanZÕaoZêapZÚaqZíarZëasZóatZâauZàavZÛawZìaxZÞayZÝazZÙa{Zèa|Zßa}[wa~[àa¡[ãa¢\ca£]‚a¤]€a¥]}a¦]†a§]za¨]a©]waª]Ša«]‰a¬]ˆa­]~a®]|a¯]a°]ya±]a²^Xa³^Ya´^Saµ^Øa¶^Ña·^×a¸^Îa¹^Üaº^Õa»^Ùa¼^Òa½^Ôa¾_Da¿_CaÀ_oaÁ_¶aÂa,aÃa(aÄaAaÅa^aÆaqaÇasaÈaRaÉaSaÊaraËalaÌa€aÍataÎaTaÏazaÐa[aÑaeaÒa;aÓajaÔaaaÕaVaÖb)a×b'aØb+aÙd+aÚdMaÛd[aÜd]aÝdtaÞdvaßdraàdsaád}aâduaãdfaäd¦aådNaæd‚açd^aèd\aédKaêdSaëd`aìdPaídaîd?aïdlaðdkañdYaòdeaódwaôesaõe aöf¡a÷f aøfŸaùgaúgaûg"aüi±aýi¶aþiÉb@i bAiÎbBi–bCi°bDi¬bEi¼bFi‘bGi™bHiŽbIi§bJibKi©bLi¾bMi¯bNi¿bOiÄbPi½bQi¤bRiÔbSi¹bTiÊbUišbViÏbWi³bXi“bYiªbZi¡b[ižb\iÙb]i—b^ib_iÂb`iµbai¥bbiÆbckJbdkMbekKbfkžbgkŸbhk bikÃbjkÄbkkþblnÎbmnõbnnñboobpo%bqnøbro7bsnûbto.buo bvoNbwobxobyo'bzob{o;b|ob}níb~o b¡o6b¢osb£nùb¤nîb¥o-b¦o@b§o0b¨ocã‡Fcä‡ cå‡2cæ‡*cç‡-cè‡dÞ›?dß›`dà›adá›_dâœñdãœòdäœõdåž§dæPÿdçQdèQ0déPødêQdëQdìPödíPþdîQ dïQ dðPýdñQ dòR‹dóRŒdôRñdõRïdöVHd÷VBdøVLdùV5dúVAdûVJdüVIdýVFdþVXe@VZeAV@eBV3eCV=eDV,eEV>eFV8eGV*eHV:eIWeJX«eKXeLX±eMX eNX£eOX¯ePX¬eQX¥eRX¡eSXÿeTZÿeUZôeVZýeWZ÷eXZöeY[eZZøe[[e\Zùe][e^[e_[e`[ea\geb]™ec]—ed]Ÿee]’ef]¢eg]“eh]•ei] ej]œek]¡el]šem]žen^ieo^]ep^`eq^\er}óes^Ûet^Þeu^áev_Iew_²exa‹eyaƒezaye{a±e|a°e}a¢e~a‰e¡a›e¢a“e£a¯e¤a­e¥aŸe¦a’e§aªe¨a¡e©aeªafe«a³e¬b-e­dne®dpe¯d–e°d e±d…e²d—e³dœe´deµd‹e¶dŠe·dŒe¸d£e¹dŸeºdhe»d±e¼d˜e½eve¾eze¿eyeÀe{eÁe²eÂe³eÃfµeÄf°eÅf©eÆf²eÇf·eÈfªeÉf¯eÊjeËjeÌjeÍiåeÎiøeÏjeÐiñeÑiäeÒj eÓiÿeÔiìeÕiâeÖje×jeØiþeÙj'eÚiòeÛiîeÜjeÝi÷eÞiçeßj@eàjeáiæeâiûeãj eäiüeåiëeæj eçjeèjeéj%eêjeëiöeìj&eíjeîiôeïjeðkQeñk¥eòk£eók¢eôk¦eõleöle÷kÿeøleùoAeúo&eûo~eüo‡eýoÆeþo’f@ofAo‰fBoŒfCobfDoOfEo…fFoZfGo–fHovfIolfJo‚fKoUfLorfMoRfNoPfOoWfPo”fQo“fRo]fSofToafUokfVo}fWogfXofYoSfZo‹f[oif\of]o•f^ocf_owf`ojfao{fbq²fcq¯fdq›feq°ffq fgqšfhq©fiqµfjqfkq¥flqžfmq¤fnq¡foqªfpqœfqq§frq³fsr˜ftršfusXfvsRfws^fxs_fys`fzs]f{s[f|saf}sZf~sYf¡sbf¢t‡f£t‰f¤tŠf¥t†f¦tf§t}f¨t…f©tˆfªt|f«tyf¬uf­uf®u~f¯v%f°vf±vf²vf³vf´v#fµvf¶v(f·vf¸vœf¹vfºvžf»v›f¼wf½wf¾w‰f¿wˆfÀxÍfÁx»fÂxÏfÃxÌfÄxÑfÅxÎfÆxÔfÇxÈfÈxÃfÉxÄfÊxÉfËyšfÌy¡fÍy fÎyœfÏy¢fÐy›fÑkvfÒz9fÓz²fÔz´fÕz³fÖ{·f×{ËfØ{¾fÙ{¬fÚ{ÎfÛ{¯fÜ{¹fÝ{ÊfÞ{µfß|Åfà|Èfá|Ìfâ|Ëfã}÷fä}Ûfå}êfæ}çfç}×fè}áfé~fê}úfë}æfì}öfí}ñfî}ðfï}îfð}ßfñvfò¬fó°fô­fõíföëf÷êføìfùæfúèfû€dfü€gfý£fþŸg@žgA•gB¢gC™gD—gE‚gF‚OgG‚SgH‚RgI‚PgJ‚NgK‚QgL…$gM…;gN…gO…gP…)gQ…gR… gS… gT…gU… gV…'gW…gX„ûgY…+gZ„úg[…g\… g]„ôg^…*g_„òg`…ga„÷gb„ëgc„ógd„üge…gf„êgg„égh…gi„þgj…(gk…gl….gm…gn„ýgo…gp„ögq…1gr…&gs„çgt„ègu„ðgv„ïgw„ùgx…gy… gz…0g{… g|…g}…/g~†bg¡‡Vg¢‡cg£‡dg¤‡wg¥‡ág¦‡sg§‡Xg¨‡Tg©‡[gª‡Rg«‡ag¬‡Zg­‡Qg®‡^g¯‡mg°‡jg±‡Pg²‡Ng³‡_g´‡]gµ‡og¶‡lg·‡zg¸‡ng¹‡\gº‡eg»‡Og¼‡{g½‡ug¾‡bg¿‡ggÀ‡igÁˆZg‰gÉ gĉgʼn gƉgljgȉgɉgʉgˉg̉g͉ gΉ¢gω¤gЉ£gщígÒ‰ðgÓ‰ìgÔŠÏgÕŠÆgÖŠ¸g׊ÓgØŠÑgÙŠÔgÚŠÕgÛŠ»gÜŠ×gÝŠ¾gÞŠÀgߊÅgàŠØgáŠÃg⊺g㊽gäŠÙgåŒ>gæŒMgçŒgèŒågéŒßgêŒÙgëŒègìŒÚgíŒÝgîŒçgï gðœgñ¡gò›góŽ gôŽ#gõŽ%göŽ$g÷Ž.gøŽgùŽgúŽgûŽgüŽgýŽ&gþŽ'h@ŽhAŽhBŽhCŽhDŽhEŽhFŽhG,hH$hIhJhK hL#hMhNhOshPphQohRghSkhT‘/hU‘+hV‘)hW‘*hX‘2hY‘&hZ‘.h[‘…h\‘†h]‘Šh^‘h_‘‚h`‘„ha‘€hb’Ðhc’Ãhd’Ähe’Àhf’Ùhg’¶hh’Ïhi’ñhj’ßhk’Øhl’éhm’×hn’Ýho’Ìhp’ïhq’Âhr’èhs’Êht’Èhu’Îhv’æhw’Íhx’Õhy’Éhz’àh{’Þh|’çh}’Ñh~’Óh¡’µh¢’áh£’Æh¤’´h¥•|h¦•¬h§•«h¨•®h©•°hª–¤h«–¢h¬–Óh­—h®—h¯—h°—Zh±—Šh²—Žh³—ˆh´—Ðhµ—Ïh¶˜h·˜h¸˜&h¹˜)hº˜(h»˜ h¼˜h½˜'h¾˜²h¿™hÀ˜úhÁ™h™hÙhÄ™hÅ™hÆ™ÜhÇ™ÍhÈ™ÏhÉ™ÓhÊ™ÔhË™ÎhÌ™ÉhÍ™ÖhΙØhÏ™ËhЙ×hÑ™ÌhÒš³hÓšìhÔšëhÕšóhÖšòhךñhØ›FhÙ›ChÚ›ghÛ›thÜ›qhÝ›fhÞ›vhß›uhà›phá›hhâ›dhã›lhäœühåœúhæœýhçœÿhèœ÷héhêhëœùhìœûhíhîhïhðžƒhñžÓhòŸhóŸhôQhõQhöQh÷QhøQhùQÞhúS4hûSáhüVphýV`hþVni@VsiAVfiBVciCVmiDVriEV^iFVwiGWiHWiIXÈiJX½iKXÉiLX¿iMXºiNXÂiOX¼iPXÆiQ[iR[iS[iT[!iU[iV[iW[iX[iY[(iZ[i[[ i\[i][ïi^]¬i_]±i`]©ia]§ib]µic]°id]®ie]ªif]¨ig]²ih]­ii]¯ij]´ik^gil^him^fin^oio^éip^çiq^æir^èis^åit_Kiu_¼ivaiwa¨ixa–iyaÅiza´i{aÆi|aÁi}aÌi~aºi¡a¿i¢a¸i£aŒi¤d×i¥dÖi¦dÐi§dÏi¨dÉi©d½iªd‰i«dÃi¬dÛi­dói®dÙi¯e3i°ei±e|i²e¢i³fÈi´f¾iµfÀi¶fÊi·fËi¸fÏi¹f½iºf»i»fºi¼fÌi½g#i¾j4i¿jfiÀjIiÁjgiÂj2iÃjhiÄj>iÅj]iÆjmiÇjviÈj[iÉjQiÊj(iËjZiÌj;iÍj?iÎjAiÏjjiÐjdiÑjPiÒjOiÓjTiÔjoiÕjiiÖj`i×jkJ…[kK…qkL…NkM…nkN…ukO…UkP…gkQ…`kR…ŒkS…fkT…]kU…TkV…ekW…lkX†ckY†ekZ†dk[‡›k\‡k]‡—k^‡“k_‡’k`‡ˆka‡kb‡–kc‡˜kd‡yke‡‡kf‡£kg‡…kh‡ki‡‘kj‡kk‡„kl‡”km‡œkn‡ško‡‰kp‰kq‰&kr‰0ks‰-kt‰.ku‰'kv‰1kw‰"kx‰)ky‰#kz‰/k{‰,k|‰k}‰ñk~Šàk¡Šâk¢Šòk£Šôk¤Šõk¥ŠÝk¦‹k§Šäk¨Šßk©ŠðkªŠÈk«ŠÞk¬Šák­Šèk®Šÿk¯Šïk°Šûk±Œ‘k²Œ’k³Œk´ŒõkµŒîk¶Œñk·Œðk¸Œók¹lkºnk»¥k¼§k½Ž3k¾Ž>k¿Ž8kÀŽ@kÁŽEkÂŽ6kÃŽnu‰Anv‰Rnw‰7nx‰Bny‰­nz‰¯n{‰®n|‰òn}‰ón~‹n¡‹n¢‹n£‹n¤‹n¥‹ n¦‹"n§‹n¨‹n©‹nª‹n«‹ n¬‹n­‹n®‹n¯‹n°‹n±ŒOn²Œpn³Œrn´ŒqnµŒon¶Œ•n·Œ”n¸Œùn¹onºŽNn»ŽMn¼ŽSn½ŽPn¾ŽLn¿ŽGnÀCnÁ@nÂ…nÃ~nÄ‘8nÅ‘šnÆ‘¢nÇ‘›nÈ‘™nÉ‘ŸnÊ‘¡nË‘nÌ‘ nÍ“¡nΓƒnÏ“¯nГdnÑ“VnÒ“GnÓ“|nÔ“XnÕ“\nÖ“vnדInØ“PnÙ“QnÚ“`nÛ“mnÜ“nÝ“LnÞ“jnß“ynà“Wná“Unâ“Rnã“Onä“qnå“wnæ“{nç“anè“^né“cnê“gnë“€nì“Nní“Ynî•Çnï•Ànð•Énñ•Ãnò•Ånó•·nô–®nõ–°nö–¬n÷— nø—nù—nú—nû—nü—šný—¡nþ—œo@—žoA—oB—ÕoC—ÔoD—ñoE˜AoF˜DoG˜JoH˜IoI˜EoJ˜CoK™%oL™+oM™,oN™*oO™3oP™2oQ™/oR™-oS™1oT™0oU™˜oV™£oW™¡oXšoY™úoZ™ôo[™÷o\™ùo]™øo^™öo_™ûo`™ýoa™þob™üocšodš¾oešþofšýog›ohšüoi›Hoj›šok›¨ol›žom››on›¦oo›¡op›¥oq›¤or›†os›¢ot› ou›¯ov3owAoxgoy6oz.o{/o|1o}8o~0o¡Eo¢Bo£Co¤>o¥7o¦@o§=o¨õo©-oªžŠo«ž‰o¬žo­ž°o®žÈo¯žÚo°žûo±žÿo²Ÿ$o³Ÿ#o´Ÿ"oµŸTo¶Ÿ o·Q1o¸Q-o¹Q.oºV˜o»Vœo¼V—o½Všo¾Vo¿V™oÀYpoÁ[pä‹1på‹%pæ‹7pç‹&pè‹6pé‹.pê‹$pë‹;pì‹=pí‹:pîŒBpïŒupðŒ™pñŒ˜pòŒ—póŒþpôpõpöp÷Ž\pøŽbpùŽ`púŽWpûŽVpüŽ^pýŽepþŽgq@Ž[qAŽZqBŽaqCŽ]qDŽiqEŽTqFFqGGqHHqIKqJ‘(qK‘:qL‘;qM‘>qN‘¨qO‘¥qP‘§qQ‘¯qR‘ªqS“µqT“ŒqU“’qV“·qW“›qX“qY“‰qZ“§q[“Žq\“ªq]“žq^“¦q_“•q`“ˆqa“™qb“Ÿqc“qd“±qe“‘qf“²qg“¤qh“¨qi“´qj“£qk“¥ql•Òqm•Óqn•Ñqo–³qp–×qq–Úqr]Âqs–ßqt–Øqu–Ýqv—#qw—"qx—%qy—¬qz—®q{—¨q|—«q}—¤q~—ªq¡—¢q¢—¥q£—×q¤—Ùq¥—Öq¦—Øq§—úq¨˜Pq©˜Qqª˜Rq«˜¸q¬™Aq­™qü[?qý]Ãqþ^pr@_¿rAaûrBerCerDe rEe rFe rGerHe„rIeÞrJeÝrKfÞrLjçrMjàrNjÌrOjÑrPjÙrQjËrRjßrSjÜrTjÐrUjërVjÏrWjÍrXjÞrYk`rZk°r[l r\pr]p'r^p r_pr`p+rap!rbp"rcp#rdp)reprfp$rgprhp*rir rjr rkrrlrrmrrnr¥ror¦rpr¤rqr£rrr¡rstËrttÅrut·rvtÃrwurxv`rywÉrzwÊr{wÄr|wñr}yr~yr¡y!r¢yr£yr¤yr¥y°r¦zgr§zhr¨|3r©|w÷ˆ0wøˆ2wùˆ.wúˆ3wû‰vwü‰twý‰swþ‰þx@‹ŒxA‹ŽxB‹‹xC‹ˆxDŒExExFŽ˜xGdxHcxI‘¼xJ”bxK”UxL”]xM”WxN”^xO—ÄxP—ÅxQ˜xRšVxSšYxT›xU›xV› xWœRxXœXxYœPxZœJx[œMx\œKx]œUx^œYx_œLx`œNxaûxb÷xcïxdãxeëxføxgäxhöxiáxjîxkæxlòxmðxnâxoìxpôxqóxrèxsíxtžÂxužÐxvžòxwžóxxŸxyŸxzŸ8x{Ÿ7x|Ÿ6x}ŸCx~ŸOx¡Ÿqx¢Ÿpx£Ÿnx¤Ÿox¥VÓx¦VÍx§[Nx¨\mx©e-xªfíx«fîx¬kx­p_x®pax¯p]x°p`x±r#x²tÛx³tåx´wÕxµy8x¶y·x·y¶x¸|jx¹~—xº‰x»‚mx¼†Cx½ˆ8x¾ˆ7x¿ˆ5xÀˆKxÁ‹”x‹•xÃŽžxÄŽŸxÅŽ xÆŽxÇ‘¾xÈ‘½xÉ‘ÂxÊ”kxË”hxÌ”ixÍ–åxΗFxÏ—CxЗGxÑ—ÇxÒ—åxÓš^xÔšÕxÕ›YxÖœcxלgxØœfxÙœbxÚœ^xÛœ`xÜžxÝþxÞžxßžxàžxážxâžxãžxäž xåÿxæýxçžxèž xéŸxêŸFxëŸtxìŸuxíŸvxîVÔxïe.xðe¸xñkxòkxókxôkxõpbxör&x÷rªxøwØxùwÙxúy9xû|ixü|kxý|öxþ~šy@~˜yA~›yB~™yCàyDáyE†FyF†GyG†HyH‰yyI‰zyJ‰|yK‰{yL‰ÿyM‹˜yN‹™yOŽ¥yPޤyQŽ£yR”nyS”myT”oyU”qyV”syW—IyX˜ryY™_yZœhy[œny\œmy]ž y^ž y_žy`žyažybžycž¡ydžõyeŸ yfŸGygŸxyhŸ{yiŸzyjŸyykWylpfym|oynˆy§ˆ=y¨ˆ?y©‹žyªŒœy«Ž©y¬ŽÉy­—Ky®˜sy¯˜ty°˜Ìy±™ay²™«y³šdy´šfyµšgy¶›$y·žy¸žy¹ŸHyºby»ky¼r'y½†Ly¾Ž¨y¿”‚yÀ”€yÁ”yšiyÚhyÄ›.yÅžyÆr)ydžKyÈ‹ŸyÉ”ƒyÊœyyËž·yÌvuyÍškyΜzyÏžyÐpiyÑpjyÒž¤yÓŸ~yÔŸIyÕŸ˜screen-4.1.0/utf8encodings/c40000644000175000017500000000034411642704565014057 0ustar abeabeScreenI2UTF8Ä2ISO-8859-4¡¢8£V¥(¦;©`ª«"¬f®}±²Û³Wµ)¶<·ǹaº»#¼g½J¾~¿KÀÇ.È ÊÌÏ*ÐÑEÒLÓ6ÙrÝhÞjàç/è êìï+ðñFòMó7ùsýiþkÿÙscreen-4.1.0/utf8encodings/cd0000644000175000017500000000006411642704565014136 0ustar abeabeScreenI2UTF8ÍISO-8859-9ÐÝ0Þ^ðý1þ_screen-4.1.0/utf8encodings/a10000644000175000017500000000103011642704565014043 0ustar abeabeScreenI2UTF8¡€KOI8-R€%%‚% ƒ%„%…%†%‡%$ˆ%,‰%4Š%<‹%€Œ%„%ˆŽ%Œ%%‘‘%’’%““# ”% • "–"—"H˜"d™"eš ›#!œ°²ž·Ÿ÷ %P¡%Q¢%R£Q¤%S¥%T¦%U§%V¨%W©%Xª%Y«%Z¬%[­%\®%]¯%^°%_±%`²%a³´%bµ%c¶%d·%e¸%f¹%gº%h»%i¼%j½%k¾%l¿©ÀNÁ0Â1ÃFÄ4Å5ÆDÇ3ÈEÉ8Ê9Ë:Ì;Í<Î=Ï>Ð?ÑOÒ@ÓAÔBÕCÖ6×2ØLÙKÚ7ÛHÜMÝIÞGßJà.áâã&äåæ$çè%éêëìíîïðñ/ò ó!ô"õ#ö÷ø,ù+úû(ü-ý)þ'ÿ*screen-4.1.0/utf8encodings/c70000644000175000017500000000006411642704565014061 0ustar abeabeScreenI2UTF8ÇISO-8859-6¬ »¿€Ú:à@€òRscreen-4.1.0/utf8encodings/cc0000644000175000017500000000010411642704565014130 0ustar abeabeScreenI2UTF8Ì ISO-8859-5¡€¬ ®€ïOð!ñQ€ü\ý§þ^ÿ_screen-4.1.0/utf8encodings/c20000644000175000017500000000040011642704565014046 0ustar abeabeScreenI2UTF8Â9ISO-8859-2¡¢Ø£A¥=¦Z©`ª^«d¬y®}¯{±²Û³Bµ>¶[·ǹaº_»e¼z½ݾ~¿|ÀTÃÅ9ÆÈ ÊÌÏÐÑCÒGÕPØXÙnÛpÞbàUãå:æè êìïðñDòHõQøYùoûqþcÿÙscreen-4.1.0/utf8encodings/c30000644000175000017500000000021411642704565014052 0ustar abeabeScreenI2UTF8ÃISO-8859-3¡&¢ئ$©0ª^«¬4¯{±'¶%¹1º_»¼5¿|Å ÆÕ ØÝlÞ\å æ õ!øýmþ]ÿÙscreen-4.1.0/utf8encodings/020000644000175000017500000006563611642704565014011 0ustar abeabeScreenI2UTF8ßJIS X 0208 (1990)!!0!"0!#0!$ÿ !%ÿ!&0û!'ÿ!(ÿ!)ÿ!*ÿ!+0›!,0œ!-´!.ÿ@!/¨!0ÿ>!1ÿã!2ÿ?!30ý!40þ!50!60ž!70!8NÝ!90!:0!;0!<0ü!= !> !?ÿ!@\!A0!B !Cÿ\!D &!E %!F !G !H !I !Jÿ!Kÿ !L0!M0!Nÿ;!Oÿ=!Pÿ[!Qÿ]!R0!S0 !T0 !U0 !V0 !W0 !X0!Y0!Z0![0!\ÿ !]"!^±!_×!`÷!aÿ!b"`!cÿ!dÿ!e"f!f"g!g"!h"4!i&B!j&@!k°!l 2!m 3!n!!oÿå!pÿ!q¢!r£!sÿ!tÿ!uÿ!vÿ !wÿ !x§!y&!z&!{%Ë!|%Ï!}%Î!~%Ç"!%Æ""%¡"#% "$%³"%%²"&%½"'%¼"( ;")0"*!’"+!",!‘"-!“".0":"";" "<"†"="‡">"‚"?"ƒ"@"*"A")"J"'"K"("L¬"M!Ò"N!Ô"O""P""\" "]"¥"^#"_""`""a"a"b"R"c"j"d"k"e""f"="g""h"5"i"+"j","r!+"s 0"t&o"u&m"v&j"w "x !"y¶"~%ï#0ÿ#1ÿ#2ÿ#3ÿ#4ÿ#5ÿ#6ÿ#7ÿ#8ÿ#9ÿ#Aÿ!#Bÿ"#Cÿ##Dÿ$#Eÿ%#Fÿ&#Gÿ'#Hÿ(#Iÿ)#Jÿ*#Kÿ+#Lÿ,#Mÿ-#Nÿ.#Oÿ/#Pÿ0#Qÿ1#Rÿ2#Sÿ3#Tÿ4#Uÿ5#Vÿ6#Wÿ7#Xÿ8#Yÿ9#Zÿ:#aÿA#bÿB#cÿC#dÿD#eÿE#fÿF#gÿG#hÿH#iÿI#jÿJ#kÿK#lÿL#mÿM#nÿN#oÿO#pÿP#qÿQ#rÿR#sÿS#tÿT#uÿU#vÿV#wÿW#xÿX#yÿY#zÿZ$!0A$"0B$#0C$$0D$%0E$&0F$'0G$(0H$)0I$*0J$+0K$,0L$-0M$.0N$/0O$00P$10Q$20R$30S$40T$50U$60V$70W$80X$90Y$:0Z$;0[$<0\$=0]$>0^$?0_$@0`$A0a$B0b$C0c$D0d$E0e$F0f$G0g$H0h$I0i$J0j$K0k$L0l$M0m$N0n$O0o$P0p$Q0q$R0r$S0s$T0t$U0u$V0v$W0w$X0x$Y0y$Z0z$[0{$\0|$]0}$^0~$_0$`0€$a0$b0‚$c0ƒ$d0„$e0…$f0†$g0‡$h0ˆ$i0‰$j0Š$k0‹$l0Œ$m0$n0Ž$o0$p0$q0‘$r0’$s0“%!0¡%"0¢%#0£%$0¤%%0¥%&0¦%'0§%(0¨%)0©%*0ª%+0«%,0¬%-0­%.0®%/0¯%00°%10±%20²%30³%40´%50µ%60¶%70·%80¸%90¹%:0º%;0»%<0¼%=0½%>0¾%?0¿%@0À%A0Á%B0Â%C0Ã%D0Ä%E0Å%F0Æ%G0Ç%H0È%I0É%J0Ê%K0Ë%L0Ì%M0Í%N0Î%O0Ï%P0Ð%Q0Ñ%R0Ò%S0Ó%T0Ô%U0Õ%V0Ö%W0×%X0Ø%Y0Ù%Z0Ú%[0Û%\0Ü%]0Ý%^0Þ%_0ß%`0à%a0á%b0â%c0ã%d0ä%e0å%f0æ%g0ç%h0è%i0é%j0ê%k0ë%l0ì%m0í%n0î%o0ï%p0ð%q0ñ%r0ò%s0ó%t0ô%u0õ%v0ö&!‘&"’&#“&$”&%•&&–&'—&(˜&)™&*š&+›&,œ&-&.ž&/Ÿ&0 &1¡&2£&3¤&4¥&5¦&6§&7¨&8©&A±&B²&C³&D´&Eµ&F¶&G·&H¸&I¹&Jº&K»&L¼&M½&N¾&O¿&PÀ&QÁ&RÃ&SÄ&TÅ&UÆ&VÇ&WÈ&XÉ'!'"'#'$'%'&'''(')'*'+','-'.'/'0'1'2 '3!'4"'5#'6$'7%'8&'9'':(';)'<*'=+'>,'?-'@.'A/'Q0'R1'S2'T3'U4'V5'WQ'X6'Y7'Z8'[9'\:'];'^<'_='`>'a?'b@'cA'dB'eC'fD'gE'hF'iG'jH'kI'lJ'mK'nL'oM'pN'qO(!%("%(#% ($%(%%(&%('%((%,()%$(*%4(+%<(,%(-%(.%(/%(0%(1%(2%#(3%3(4%+(5%;(6%K(7% (8%/(9%((:%7(;%?(<%(=%0(>%%(?%8(@%B0!Nœ0"U0#Z0$–?0%TÀ0&a0'c(0(Yö0)"0*„u0+ƒ0,zP0-`ª0.cá0/n%00eí01„f02‚¦03›õ04h“05W'06e¡07bq08[›09YÐ0:†{0;˜ô0<}b0=}¾0>›Ž0?b0@|Ÿ0Aˆ·0B[‰0C^µ0Dc 0Ef—0FhH0G•Ç0H—0IgO0JNå0KO 0LOM0MO0NPI0OVò0PY70QYÔ0RZ0S\ 0T`ß0Ua0Vap0Wf0Xi0Ypº0ZuO0[up0\yû0]}­0^}ï0_€Ã0`„0aˆc0b‹0cU0dz0eS;0fN•0gN¥0hWß0i€²0jÁ0kxï0lN0mXñ0nn¢0o80pz20qƒ(0r‚‹0sœ/0tQA0uSp0vT½0wTá0xVà0yYû0z_0{˜ò0|më0}€ä0~…-1!–b1"–p1#– 1$—û1%T 1&Só1'[‡1(pÏ1)½1*Â1+–è1,So1-\1.zº1/N10x“11ü12n&13V14U15k16…17œ;18Yå19S©1:mf1;tÜ1<•1=VB1>N‘1?K1@–ò1AƒO1B™ 1CSá1DU¶1E[01F_q1Gf 1Hfó1Ih1Jl81Kló1Lm)1Mt[1NvÈ1OzN1P˜41Q‚ñ1Rˆ[1SŠ`1T’í1Um²1Vu«1WvÊ1X™Å1Y`¦1Z‹1[Š1\•²1]iŽ1^S­1_Q†1`W1aX01bYD1c[´1d^ö1e`(1fc©1gcô1hl¿1io1jpŽ1kq1lqY1mqÕ1ns?1o~1p‚v1q‚Ñ1r…—1s`1t’[1u1vXi1we¼1xlZ1yu%1zQù1{Y.1|Ye1}_€1~_Ü2!b¼2"eú2#j*2$k'2%k´2&s‹2'Á2(‰V2),2*2+žÄ2,\¡2-l–2.ƒ{2/Q20\K21a¶22Æ23hv24ra25NY26Oú27Sx28`i29n)2:zO2;—ó2Nî2?OU2@O=2AO¡2BOs2CR 2DSï2EV 2FY2GZÁ2H[¶2I[á2JyÑ2Kf‡2Lgœ2Mg¶2NkL2Ol³2Ppk2QsÂ2Ry2Sy¾2Tz<2U{‡2V‚±2W‚Û2Xƒ2Yƒw2Zƒï2[ƒÓ2\‡f2]в2^V)2_Œ¨2`æ2aN2b—2c†Š2dOÄ2e\è2fb2grY2hu;2iå2j‚½2k†þ2lŒÀ2m–Å2n™2o™Õ2pNË2qO2r‰ã2sVÞ2tXJ2uXÊ2v^û2w_ë2x`*2y`”2z`b2{aÐ2|b2}bÐ2~e93!›A3"ff3#h°3$mw3%pp3&uL3'v†3(}u3)‚¥3*‡ù3+•‹3,–Ž3-Œ3.Qñ3/R¾30Y31T³32[³33]34ah35i‚36m¯37x38„Ë39ˆW3:Šr3;“§3<š¸3=ml3>™¨3?†Ù3@W£3Agÿ3B†Î3C’3DRƒ3EV‡3FT3G^Ó3Hbá3Id¹3Jh<3Kh83Lk»3Msr3Nxº3Ozk3P‰š3Q‰Ò3Rk3S3Tí3U•£3V–”3W—i3X[f3Y\³3Zi}3[˜M3\˜N3]c›3^{ 3_j+3`j3ah¶3bœ 3co_3dRr3eU3f`p3gbì3hm;3in3jnÑ3k„[3l‰3mD3nN3oœ93pSö3qi3rj:3s—„3th*3uQ\3vzÃ3w„²3x‘Ü3y“Œ3zV[3{(3|h"3}ƒ3~„14!|¥4"R4#‚Å4$tæ4%N~4&Oƒ4'Q 4([Ò4)R 4*RØ4+Rç4,]û4-Uš4.X*4/Yæ40[Œ41[˜42[Û43^r44^y45`£46a47ac48a¾49cÛ4:eb4;gÑ4k>4?kS4@lW4Ao"4Bo—4CoE4Dt°4Eu4Fvã4Gw 4Hzÿ4I{¡4J|!4K}é4L64Mð4N€4O‚f4Pƒž4Q‰³4RŠÌ4SŒ«4T„4U”Q4V•“4W•‘4X•¢4Y–e4Z—Ó4[™(4\‚4]N84^T+4_\¸4`]Ì4as©4bvL4cw<4d\©4eë4f 4g–Á4h˜4i˜T4j˜X4kO4lO4mSq4nUœ4oVh4pWú4qYG4r[ 4s[Ä4t\4u^ 4v^~4w_Ì4xcî4yg:4ze×4{eâ4|g4}hË4~hÄ5!j_5"^05#kÅ5$l5%l}5&u5'yH5([c5)z5*}5+_½5,‰5-Š5.Œ´5/w50ŽÌ5152˜â53š54›<55N€56P}57Q58Y“59[œ5:b/5;b€5r 5?u‘5@yG5A©5B‡û5Cм5D‹p5Ec¬5FƒÊ5G— 5HT 5IT5JU«5KhT5LjX5MŠp5Nx'5Ogu5PžÍ5QSt5R[¢5S5T†P5U5VN5WNE5XNÇ5YO5ZSÊ5[T85\[®5]_5^`%5_eQ5`g=5alB5blr5clã5dpx5et5fzv5gz®5h{5i}5j|þ5k}f5leç5mr[5nS»5o\E5p]è5qbÒ5rbà5sc5tn 5u†Z5vŠ15wÝ5x’ø5yo5zy¦5{›Z5|N¨5}N«5~N¬6!O›6"O 6#PÑ6$QG6%zö6&Qq6'Qö6(ST6)S!6*S6+Së6,U¬6-Xƒ6.\á6/_760_J61`/62`P63`m64c65eY66jK67lÁ68rÂ69rí6:wï6;€ø6<6=‚6>…N6?÷6@“á6A—ÿ6B™W6CšZ6DNð6EQÝ6F\-6Gf6Him6I\@6Jfò6Kiu6Ls‰6MhP6N|6OPÅ6PRä6QWG6R]þ6S“&6Te¤6Uk#6Vk=6Wt46Xy6Yy½6Z{K6[}Ê6\‚¹6]ƒÌ6^ˆ6_‰_6`‹96aÑ6b‘Ñ6cT6d’€6eN]6fP66gSå6hS:6ir×6js–6kwé6l‚æ6mޝ6n™Æ6o™È6p™Ò6qQw6ra6s†^6tU°6uzz6vPv6w[Ó6xG6y–…6zN26{jÛ6|‘ç6}\Q6~\H7!c˜7"zŸ7#l“7$—t7%a7&zª7'qŠ7(–ˆ7)|‚7*h7+~p7,hQ7-“l7.Rò7/T70…«71Š72¤73ŽÍ74á75Sf76ˆˆ77yA78OÂ79P¾7:R7;QD7sê7?W‹7@YQ7A_b7B_„7C`u7Dav7Eag7Fa©7Gc²7Hd:7Iel7Jfo7KhB7Ln7Muf7Nz=7O|û7P}L7Q}™7R~K7Sk7Tƒ7UƒJ7V†Í7WŠ7XŠc7Y‹f7ZŽý7[˜7\7]‚¸7^Î7_›è7`R‡7ab7bdƒ7coÀ7d–™7ehA7fP‘7gk 7hlz7ioT7jzt7k}P7lˆ@7mŠ#7ng7oNö7pP97qP&7rPe7sQ|7tR87uRc7vU§7wW7xX7yZÌ7z^ú7{a²7|aø7}bó7~cr8!i8"j)8#r}8$r¬8%s.8&x8'xo8(}y8)w 8*€©8+‰‹8,‹8-Œâ8.ŽÒ8/c80“u81–z82˜U83š84žx85QC86SŸ87S³88^{89_&8:n8;n8}C8?‚78@Š8AŠú8B–P8CNN8DP 8ESä8FT|8GVú8HYÑ8I[d8J]ñ8K^«8L_'8Mb88NeE8Og¯8PnV8QrÐ8R|Ê8Sˆ´8T€¡8U€á8Vƒð8W†N8XЇ8Yè8Z’78[–Ç8\˜g8]Ÿ8^N”8_N’8`O 8aSH8bTI8cT>8dZ/8e_Œ8f_¡8g`Ÿ8hh§8ijŽ8jtZ8kx8lŠž8mФ8n‹w8o‘8pN^8q›É8rN¤8sO|8tO¯8uP8vP8wQI8xQl8yRŸ8zR¹8{Rþ8|Sš8}Sã8~T9!T9"U‰9#WQ9$W¢9%Y}9&[T9'[]9([9)]å9*]ç9+]÷9,^x9-^ƒ9.^š9/^·90_91`R92aL93b—94bØ95c§96e;97f98fC99fô9:gm9;h!9l_9?m*9@mi9An/9Bn9Cu29Dv‡9Exl9Fz?9G|à9H}9I}9J}^9K}±9L€9M€9N€¯9O€±9PT9Q9R‚*9SƒR9TˆL9Uˆa9V‹9WŒ¢9XŒü9YÊ9Z‘u9[’q9\x?9]’ü9^•¤9_–M9`˜9a™™9bšØ9c;9dR[9eR«9fS÷9gT9hXÕ9ib÷9joà9kŒj9l_9mž¹9nQK9oR;9pTJ9qVý9rz@9s‘w9t`9užÒ9vsD9wo 9xp9yu9z_ý9{`Ú9|š¨9}rÛ9~¼:!kd:"˜:#NÊ:$Vð:%Wd:&X¾:'ZZ:(`h:)aÇ:*f:+f:,h9:-h±:.m÷:/uÕ:0}::1‚n:2›B:3N›:4OP:5SÉ:6U:7]o:8]æ:9]î::gû:;l™:ŠP:?“–:@ˆß:AWP:B^§:Cc+:DPµ:EP¬:FQ:Gg:HTÉ:IX^:JY»:K[°:L_i:MbM:Nc¡:Oh=:Pks:Qn:Rp}:S‘Ç:Tr€:Ux:Vx&:Wym:XeŽ:Y}0:ZƒÜ:[ˆÁ:\ :]–›:^Rd:_W(:`gP:aj:bŒ¡:cQ´:dWB:e–*:fX::giŠ:h€´:iT²:j]:kWü:lx•:mú:nO\:oRJ:pT‹:qd>:rf(:sg:tgõ:uz„:v{V:w}":x“/:yh\:z›­:{{9:|S:}QŠ:~R7;![ß;"bö;#d®;$dæ;%g-;&kº;'…©;(–Ñ;)v;*›Ö;+cL;,“;-›«;.v¿;/fR;0N ;1P˜;2SÂ;3\q;4`è;5d’;6ec;7h_;8qæ;9sÊ;:u#;;{—;<~‚;=†•;>‹ƒ;?ŒÛ;@‘x;A™;Be¬;Cf«;Dk‹;ENÕ;FNÔ;GO:;HO;IR:;JSø;KSò;LUã;MVÛ;NXë;OYË;PYÉ;QYÿ;R[P;S\M;T^;U^+;V_×;W`;Xc;Ye/;Z[\;[e¯;\e½;]eè;^g;_kb;`k{;al;bsE;cyI;dyÁ;e|ø;f};g}+;h€¢;i;jó;k‰–;lŠ^;mŠi;nŠf;oŠŒ;pŠî;qŒÇ;rŒÜ;s–Ì;t˜ü;uko;vN‹;wO<;xO;yQP;z[W;{[ú;|aH;}c;~fB<%t½<&uÔ<'xÁ<(y:<)€ <*€3<+ê<,„”<-ž<.lPn_“=?b=@gÔ=AlA=Bn =Csc=D~&=E‘Í=F’ƒ=GSÔ=HY=I[¿=JmÑ=Ky]=L~.=M|›=NX~=OqŸ=PQú=QˆS=Rð=SOÊ=T\û=Uf%=Vw¬=Wzã=X‚=Y™ÿ=ZQÆ=[_ª=\eì=]io=^k‰=_mó=`n–=aod=bvþ=c}=d]á=eu=f‘‡=g˜=hQæ=iR=jb@=kf‘=lfÙ=mn=n^¶=o}Ò=pr=qfø=r…¯=s…÷=tŠø=uR©=vSÙ=wYs=x^=y_=z`U={’ä=|–d=}P·=~Q>!RÝ>"S >#SG>$Sì>%Tè>&UF>'U1>(V>)Yh>*Y¾>+Z<>,[µ>-\>.\>/\>0\>1^„>2^Š>3^à>4_p>5b>6b„>7bÛ>8cŒ>9cw>:f>;f >=fv>>g~>?h¢>@j>Aj5>Bl¼>Cmˆ>Dn >EnX>Fq<>Gq&>Hqg>IuÇ>Jw>Kx]>Ly>Mye>Nyð>Ozà>P{>Q|§>R}9>S€–>TƒÖ>U„‹>V…I>Wˆ]>Xˆó>YŠ>ZŠ<>[ŠT>\Šs>]Œa>^ŒÞ>_‘¤>`’f>a“~>b”>c–œ>d—˜>eN >fN>gN>hNW>iQ—>jRp>kWÎ>lX4>mXÌ>n[">o^8>p`Å>qdþ>rga>sgV>tmD>ur¶>vus>wzc>x„¸>y‹r>z‘¸>{“ >|V1>}Wô>~˜þ?!bí?"i ?#k–?$qí?%~T?&€w?'‚r?(‰æ?)˜ß?*‡U?+±?,\;?-O8?.Oá?/Oµ?0U?1Z ?2[Ý?3[é?4_Ã?5aN?6c/?7e°?8fK?9hî?:i›?;mx?u¹??w?@y^?Ayæ?B}3?Cã?D‚¯?E…ª?F‰ª?GŠ:?HŽ«?I›?J2?K‘Ý?L—?MNº?NNÁ?OR?PXu?QXì?R\ ?Su?T\=?UN?VŠ ?WÅ?X–c?Y—m?Z{%?[ŠÏ?\˜?]‘b?^Vó?_S¨?`?aT9?bW‚?c^%?dc¨?el4?fpŠ?gwa?h|‹?ià?jˆp?kB?l‘T?m“?n“?o–?pt^?qšÄ?r]?s]i?tep?ug¢?v¨?w–Û?xcn?ygI?zi?{ƒÅ?|˜?}–À?~ˆþ@!o„@"dz@#[ø@$N@%p,@&u]@'f/@(QÄ@)R6@*Râ@+YÓ@,_@-`'@.b@/e?@0et@1f@2ft@3hò@4h@5kc@6n@7rr@8u@9vÛ@:|¾@;€V@‰@?Š @@Š“@AŠË@B@C‘’@D—R@E—Y@Fe‰@Gz@H@I–»@J^-@K`Ü@Lb@Me¥@Nf@Og@Pwó@QzM@R|M@S~>@T @UŒ¬@Vd@Wá@XŽ_@Yx©@ZR@[bÙ@\c¥@]dB@^b˜@_Š-@`zƒ@a{À@bЬ@c–ê@d}v@e‚ @f‡I@gNÙ@hQH@iSC@jS`@k[£@l\@m\@n]Ý@ob&@pbG@qd°@rh@sh4@tlÉ@umE@vm@wgÓ@xo\@yqN@zq}@{eË@|z@}{­@~}ÚA!~JA"¨A#zA$‚A%‚9A&…¦A'ŠnA(ŒÎA)õA*xA+wA,’­A-’‘A.•ƒA/›®A0RMA1U„A2o8A3q6A4QhA5y…A6~UA7³A8|ÎA9VLA:XQA;\¨AfýA?iZA@rÙAAuABuŽACyADyVAEyßAF|—AG} AH}DAI†AJŠ4AK–;ALaAMŸ ANPçAORuAPSÌAQSâARP ASUªATXîAUYOAVr=AW[‹AX\dAYSAZ`ãA[`óA\c\A]cƒA^c?A_c»A`dÍAaeéAbfùAc]ãAdiÍAeiýAfoAgqåAhN‰AiuéAjvøAkz“Al|ßAm}ÏAn}œAo€aApƒIAqƒXAr„lAs„¼At…ûAuˆÅAvpAwAxmAy“—Az—A{šA|PÏA}X—A~aŽB!ÓB"…5B#B$ B%OÃB&PtB'RGB(SsB)`oB*cIB+g_B,n,B-³B.B/O×B0\^B1ŒÊB2eÏB3}šB4SRB5ˆ–B6QvB7cÃB8[XB9[kB:\ B;d BNÖB?YB@Y*BAlpBBŠQBCU>BDXBEY¥BF`ðBGbSBHgÁBI‚5BJiUBK–@BL™ÄBMš(BNOSBOXBP[þBQ€BR\±BS^/BT_…BU` BVaKBWb4BXfÿBYlðBZnÞB[€ÎB\B]‚ÔB^ˆ‹B_Œ¸B`Ba.Bb–ŠBcžÛBd›ÛBeNãBfSðBgY'Bh{,Bi‘Bj˜LBkùBlnÝBmp'BnSSBoUDBp[…BqbXBrbžBsbÓBtl¢BuoïBvt"BwŠBx”8ByoÁBzŠþB{ƒ8B|QçB}†øB~SêC!SéC"OFC#TC$°C%YjC&1C']ýC(zêC)¿C*hÚC+Œ7C,røC-œHC.j=C/аC0N9C1SXC2VC3WfC4bÅC5c¢C6eæC7kNC8máC9n[C:p­C;wíC}»C?€=C@€ÆCA†ËCBŠ•CC“[CDVãCEXÇCF_>CGe­CHf–CIj€CJkµCKu7CLŠÇCMP$CNwåCOW0CP_CQ`eCRfzCSl`CTuôCUzCVnCWôCX‡CYECZ™³C[{ÉC\u\C]zùC^{QC_„ÄC`CayéCbz’Ccƒ6CdZáCew@CfN-CgNòCh[™Ci_àCjb½CkfvôD?gD@lˆDAsÍDBŒÃDC“®DD–sDEm%DFXœDGiDHiÌDIýDJ“šDKuÛDLDMXZDNhDOc´DPiûDQOCDRo,DSgØDT»DU…&DV}´DW“TDXi?DYopDZWjD[X÷D\[,D]},D^r*D_T D`‘ãDa´DbN­DcONDdP\DePuDfRCDgŒžDhTHDiX$Dj[šDk^Dl^•Dm^­Dn^÷Do_Dp`ŒDqbµDrc:DscÐDth¯Dul@Dvx‡DwyŽDxz Dy}àDz‚GD{ŠD|ŠæD}ŽDD~E!¸E"‘-E#‘ØE$ŸE%låE&dXE'dâE(euE)nôE*v„E+{E,iE-“ÑE.nºE/TòE0_¹E1d¤E2ME3íE4’DE5QxE6XkE7Y)E8\UE9^—E:mûE;~EŽâE?˜[E@p¹EAOEBk¿ECo±EDu0EE–ûEFQNEGTEHX5EIXWEJY¬EK\`EL_’EMe—ENg\EOn!EPv{EQƒßERŒíESETýEU“MEVx%EWx:EXRªEY^¦EZWE[YtE\`E]PE^QZE_Q¬E`QÍEaREbUEcXTEdXXEeYWEf[•Eg\öEh]‹Ei`¼Ejb•Ekd-ElgqEmhCEnh¼EohßEpv×EqmØErnoEsm›EtpoEuqÈEv_SEwuØExywEy{IEz{TE{{RE||ÖE}}qE~R0F!„cF"…iF#…äF$ŠF%‹F&ŒFF'ŽF(F)F*”F+–vF,˜-F-š0F.•ØF/PÍF0RÕF1T F2XF3\F4a§F5džF6mF7w³F8zåF9€ôF:„F;SF<’…F=\àF>F?S?F@_—FA_³FBmœFCryFDwcFEy¿FF{äFGkÒFHrìFIŠ­FJhFKjaFLQøFMzFNi4FO\JFPœöFQ‚ëFR[ÅFS‘IFTpFUVxFV\oFW`ÇFXefFYlŒFZŒZF[AF\˜F]TQF^fÇF_’ F`YHFa£FbQ…FcNMFdQêFe…™Ff‹FgpXFhczFi“KFjibFk™´Fl~FmuwFnSWFoi`FpŽßFq–ãFrl]FsNŒFt\3G?¿G@²GA‰—GB†¤GC]ôGDbŠGEd­GF‰‡GGgwGHlâGIm>GJt6GKx4GLZFGMuGN‚­GO™¬GPOóGQ^ÃGRbÝGSc’GTeWGUgoGVvÃGWrLGX€ÌGY€ºGZ)G[‘MG\P G]WùG^Z’G_h…G`isGaqdGbrýGcŒ·GdXòGeŒàGf–jGgGh‡GiyäGjwçGk„)GlO/GmReGnSZGobÍGpgÏGqlÊGrv}Gs{”Gt|•Gu‚6Gv…„GwëGxfÝGyo GzrG{~G|ƒ«G}™ÁG~ž¦H!QýH"{±H#xrH${¸H%€‡H&{HH'jèH(^aH)€ŒH*uQH+u`H,QkH-’bH.nŒH/vzH0‘—H1šêH2OH3pH4bœH5{OH6•¥H7œéH8VzH9XYH:†äH;–¼HSJH?SÍH@SÛHA^HBd,HCe‘HDgHEl>HFlNHGrHHHr¯HIsíHJuTHK~AHL‚,HM…éHNŒ©HO{ÄHP‘ÆHQqiHR˜HS˜ïHTc=HUfiHVujHWväHXxÐHY…CHZ†îH[S*H\SQH]T&H^YƒH_^‡H`_|Ha`²HbbIHcbyHdb«HeeHfkÔHglÌHhu²Hiv®Hjx‘HkyØHl}ËHmwHn€¥Hoˆ«HpйHqŒ»HrHs—^Ht˜ÛHuj Hv|8HwP™Hx\>Hy_®Hzg‡H{kØH|t5H}w H~ŽI!Ÿ;I"gÊI#zI$S9I%u‹I&šíI'_fI(I)ƒñI*€˜I+_ŠUI?ŒyI@^ßIAcÏIBuÅICyÒID‚×IE“(IF’òIG„œIH†íIIœ-IJTÁIK_lILeŒIMm\INpIOŒ§IPŒÓIQ˜;IReOIStöITN IUNØIVWàIWY+IXZfIY[ÌIZQ¨I[^I\^œI]`I^bvI_ewI`e§IafnIbmnIcr6Id{&IePIfšIg‚™Ih‹\IiŒ IjŒæIktIl–Im–DInO®Iod«IpkfIq‚Ir„aIs…jItèIu\IviSIw˜¨Ix„zIy…WIzOI{RoI|_©I}^EI~g J!yJ"yJ#‰J$‰†J%mõJ&_J'bUJ(l¸J)NÏJ*riJ+›’J,RJ-T;J.VtJ/X³J0a¤J1bnJ2qJ3YnJ4|‰J5|ÞJ6}J7–ðJ8e‡J9€^J:NJ;OuJ^cJ?^sJ@_ JAgÄJBN&JC…=JD•‰JE–[JF|sJG˜JHPûJIXÁJJvVJKx§JLR%JMw¥JN…JO{†JPPOJQY JRrGJS{ÇJT}èJUºJVÔJWMJXO¿JYRÉJZZ)J[_J\—­J]OÝJ^‚J_’êJ`WJacUJbkiJcu+JdˆÜJeJfzBJgRßJhX“JiaUJjb Jkf®JlkÍJm|?JnƒéJoP#JpOøJqSJrTFJsX1JtYIJu[Jv\ðJw\ïJx])Jy^–Jzb±J{cgJ|e>J}e¹J~g K!lÕK"láK#pùK$x2K%~+K&€ÞK'‚³K(„ K)„ìK*‡K+‰K,Š*K-ŒJK.¦K/’ÒK0˜ýK1œóK2lK3NOK4N¡K5PK6RVK7WJK8Y¨K9^=K:_ØK;_ÙKgK?gÐK@hÒKAQ’KB}!KC€ªKD¨KE‹KFŒŒKGŒ¿KH’~KI–2KJT KK˜,KLSKMPÕKNS\KOX¨KPd²KQg4KRrgKSwfKTzFKU‘æKVRÃKWl¡KXk†KYXKZ^LK[YTK\g,K]ûK^QáK_vÆK`diKaxèKb›TKcž»KdWËKeY¹Kff'KggšKhkÎKiTéKjiÙKk^UKlœKmg•Kn›ªKogþKpœRKqh]KrN¦KsOãKtSÈKub¹Kvg+Kwl«KxÄKyO­Kz~mK{ž¿K|NK}abK~n€L!o+L"…L#TsL$g*L%›EL&]óL'{•L(\¬L)[ÆL*‡L+nJL,„ÑL-zL.L/Y™L0|L1lL2w L3RÙL4Y"L5q!L6r_L7wÛL8—'L9aL:i L;ZLT L?T}L@fLAvßLB÷LC’˜LDœôLEYêLFr]LGnÅLHQMLIhÉLJ}¿LK}ìLL—bLMžºLNdxLOj!LPƒLQY„LR[_LSkÛLTsLUvòLV}²LW€LX„™LYQ2LZg(L[žÙL\vîL]gbL^RÿL_™L`\$Lab;Lb|~LcŒ°LdUOLe`¶Lf} Lg•€LhSLiN_LjQ¶LkYLlr:Lm€6Ln‘ÎLo_%LpwâLqS„Lr_yLs}Lt…¬LuŠ3LvŽLw—VLxgóLy…®Lz”SL{a L|aL}l¹L~vRM!ŠíM"8M#U/M$OQM%Q*M&RÇM'SËM([¥M)^}M*` M+a‚M,cÖM-g M.gÚM/ngM0mŒM1s6M2s7M3u1M4yPM5ˆÕM6Š˜M7JM8‘M9õM:–ÄM;‡MOYM?NM@ЉMA?MB˜MCP­MD^|MEY–MF[¹MG^¸MHcÚMIcúMJdÁMKfÜMLiJMMiØMNm MOn¶MPq”MQu(MRz¯MSŠMT€MU„IMV„ÉMW‰MX‹!MYŽ MZeM[–}M\™ M]a~M^b‘M_k2M`lƒMamtMbÌMcüMdmÀMe…Mf‡ºMgˆøMhgeMiƒ±Mj˜N!N?QÌN@[îNAe™NBhNCm¼NDsNEvBNFw­NGzNH|çNI‚oNJŠÒNK|NL‘ÏNM–uNN˜NOR›NP}ÑNQP+NRS˜NSg—NTmËNUqÐNVt3NWèNX*NY–£NZœWN[žŸN\t`N]XAN^m™N_}/N`˜^NaNäNbO6NcO‹NdQ·NeR±Nf]ºNg`Nhs²NiyN}}ôN~€oO!„îO"#O#“,O$TBO%›oO&jÓO'p‰O(ŒÂO)ïO*—2O+R´O,ZAO-^ÊO._O/gO0i|O1i”O2mjO3oO4rbO5rüO6{íO7€O8€~O9‡KO:ÎO;QmO<ž“O=y„O>€‹O?“2O@ŠÖOAP-OBTŒOCŠqODkjOEŒÄOFOG`ÑOHg OIòOJN™OKN˜OLœOMŠkON…ÁOO…hOPiOQn~ORx—OSUP!_ P"NP#NP$N*P%N1P&N6P'NNÂP?N×P@NÞPANíPBNßPCN÷PDO PEOZPFO0PGO[PHO]PIOWPJOGPKOvPLOˆPMOPNO˜POO{PPOiPQOpPRO‘PSOoPTO†PUO–PVQPWOÔPXOßPYOÎPZOØP[OÛP\OÑP]OÚP^OÐP_OäP`OåPaPPbP(PcPPdP*PeP%PfPPgOPhOöPiP!PjP)PkP,PlOþPmOïPnPPoPPpPCPqPGPrgPsPUPtPPPuPHPvPZPwPVPxPlPyPxPzP€P{PšP|P…P}P´P~P²Q!PÉQ"PÊQ#P³Q$PÂQ%PÖQ&PÞQ'PåQ(PíQ)PãQ*PîQ+PùQ,PõQ-Q Q.QQ/QQ0QQ1QQ2QQ3QQ4Q!Q5Q:Q6Q7Q7QQbQ?zøQ@QiQAQjQBQnQCQ€QDQ‚QEVØQFQŒQGQ‰QHQQIQ‘QJQ“QKQ•QLQ–QMQ¤QNQ¦QOQ¢QPQ©QQQªQRQ«QSQ³QTQ±QUQ²QVQ°QWQµQXQ½QYQÅQZQÉQ[QÛQ\QàQ]†UQ^QéQ_QíQ`QðQaQõQbQþQcRQdR QeRQfRQgR'QhR*QiR.QjR3QkR9QlROQmRDQnRKQoRLQpR^QqRTQrRjQsRtQtRiQuRsQvRQwR}QxRQyR”QzR’Q{RqQ|RˆQ}R‘Q~¨R!§R"R¬R#R­R$R¼R%RµR&RÁR'RÍR(R×R)RÞR*RãR+RæR,˜íR-RàR.RóR/RõR0RøR1RùR2SR3SR4u8R5S R6SR7SR8SR9SR:S#R;S/RS8R?S@R@SFRASERBNRCSIRDSMREQÖRFS^RGSiRHSnRIYRJS{RKSwRLS‚RMS–RNS ROS¦RPS¥RQS®RRS°RSS¶RTSÃRU|RV–ÙRWSßRXfüRYqîRZSîR[SèR\SíR]SúR^TR_T=R`T@RaT,RbT-RcTT¯S?UŠS@UŸSAU{SBU~SCU˜SDUžSEU®SFU|SGUƒSHU©SIU‡SJU¨SKUÚSLUÅSMUßSNUÄSOUÜSPUäSQUÔSRVSSU÷STVSUUþSVUýSWVSXUùSYVNSZVPS[qßS\V4S]V6S^V2S_V8S`VkSaVdSbV/ScVlSdVjSeV†SfV€SgVŠShV SiV”SjVSkV¥SlV®SmV¶SnV´SoVÂSpV¼SqVÁSrVÃSsVÀStVÈSuVÎSvVÑSwVÓSxV×SyVîSzVùS{WS|VÿS}WS~W T!WT"W T#W T$WT%WT&WT'UÇT(WT)W&T*W7T+W8T,WNT-W;T.W@T/WOT0WiT1WÀT2WˆT3WaT4WT5W‰T6W“T7W T8W³T9W¤T:WªT;W°TWÔT?WÒT@WÓTAX TBWÖTCWãTDX TEXTFXTGXrTHX!TIXbTJXKTKXpTLkÀTMXRTNX=TOXyTPX…TQX¹TRXŸTSX«TTXºTUXÞTVX»TWX¸TXX®TYXÅTZXÓT[XÑT\X×T]XÙT^XØT_XåT`XÜTaXäTbXßTcXïTdXúTeXùTfXûTgXüThXýTiYTjY TkYTlYTmh¦TnY%ToY,TpY-TqY2TrY8TsY>TtzÒTuYUTvYPTwYNTxYZTyYXTzYbT{Y`T|YgT}YlT~YiU!YxU"YU#YU$O^U%O«U&Y£U'Y²U(YÆU)YèU*YÜU+YU,YÙU-YÚU.Z%U/ZU0ZU1ZU2Z U3ZU4Z@U5ZlU6ZIU7Z5U8Z6U9ZbU:ZjU;ZšUZËU?ZÂU@Z½UAZãUBZ×UCZæUDZéUEZÖUFZúUGZûUH[ UI[ UJ[UK[2ULZÐUM[*UN[6UO[>UP[CUQ[EUR[@US[QUT[UUU[ZUV[[UW[eUX[iUY[pUZ[sU[[uU\[xU]eˆU^[zU_[€U`[ƒUa[¦Ub[¸Uc[ÃUd[ÇUe[ÉUf[ÔUg[ÐUh[äUi[æUj[âUk[ÞUl[åUm[ëUn[ðUo[öUp[óUq\Ur\Us\Ut\ Uu\Uv\ Uw\"Ux\(Uy\8Uz\9U{\AU|\FU}\NU~\SV!\PV"\OV#[qV$\lV%\nV&NbV'\vV(\yV)\ŒV*\‘V+\”V,Y›V-\«V.\»V/\¶V0\¼V1\·V2\ÅV3\¾V4\ÇV5\ÙV6\éV7\ýV8\úV9\íV:]ŒV;\êV<] V=]V>]V?]\V@]VA]VB]VC]VD]"VE]VF]VG]VH]LVI]RVJ]NVK]KVL]lVM]sVN]vVO]‡VP]„VQ]‚VR]¢VS]VT]¬VU]®VV]½VW]VX]·VY]¼VZ]ÉV[]ÍV\]ÓV]]ÒV^]ÖV_]ÛV`]ëVa]òVb]õVc^ Vd^Ve^Vf^Vg^Vh^6Vi^7Vj^DVk^CVl^@Vm^NVn^WVo^TVp^_Vq^bVr^dVs^GVt^uVu^vVv^zVwž¼Vx^Vy^ Vz^ÁV{^ÂV|^ÈV}^ÐV~^ÏW!^ÖW"^ãW#^ÝW$^ÚW%^ÛW&^âW'^áW(^èW)^éW*^ìW+^ñW,^óW-^ðW.^ôW/^øW0^þW1_W2_ W3_]W4_\W5_ W6_W7_W8_)W9_-W:_8W;_AW<_HW=_LW>_NW?_/W@_QWA_VWB_WWC_YWD_aWE_mWF_sWG_wWH_ƒWI_‚WJ_WK_ŠWL_ˆWM_‘WN_‡WO_žWP_™WQ_˜WR_ WS_¨WT_­WU_¼WV_ÖWW_ûWX_äWY_øWZ_ñW[_ÝW\`³W]_ÿW^`!W_``W``Wa`Wb`)Wc`Wd`1We`Wf`Wg`+Wh`&Wi`Wj`:Wk`ZWl`AWm`jWn`wWo`_Wp`JWq`FWr`MWs`cWt`CWu`dWv`BWw`lWx`kWy`YWz`W{`W|`çW}`ƒW~`šX!`„X"`›X#`–X$`—X%`’X&`§X'`‹X(`áX)`¸X*`àX+`ÓX,`´X-_ðX.`½X/`ÆX0`µX1`ØX2aMX3aX4aX5`öX6`÷X7aX8`ôX9`úX:aX;a!X<`ûX=`ñX>a X?aX@aGXAa>XBa(XCa'XDaJXEa?XFabÆY?dÔY@bÈYAbÜYBbÌYCbÊYDbÂYEbÇYFb›YGbÉYHc YIbîYJbñYKc'YLcYMcYNbïYObõYPcPYQc>YRcMYSdYTcOYUc–YVcŽYWc€YXc«YYcvYZc£Y[cY\c‰Y]cŸY^cµY_ckY`ciYac¾YbcéYccÀYdcÆYecãYfcÉYgcÒYhcöYicÄYjdYkd4YldYmdYnd&Yod6YpeYqdYrd(YsdYtdgYudoYvdvYwdNYxe*Yyd•Yzd“Y{d¥Y|d©Y}dˆY~d¼Z!dÚZ"dÒZ#dÅZ$dÇZ%d»Z&dØZ'dÂZ(dñZ)dçZ*‚ Z+dàZ,dáZ-b¬Z.dãZ/dïZ0e,Z1döZ2dôZ3dòZ4dúZ5eZ6dýZ7eZ8eZ9eZ:e$Z;e#Ze5Z?e7Z@e6ZAe8ZBuKZCeHZDeVZEeUZFeMZGeXZHe^ZIe]ZJerZKexZLe‚ZMeƒZN‹ŠZOe›ZPeŸZQe«ZRe·ZSeÃZTeÆZUeÁZVeÄZWeÌZXeÒZYeÛZZeÙZ[eàZ\eáZ]eñZ^grZ_f Z`fZaeûZbgsZcf5Zdf6Zef4ZffZgfOZhfDZifIZjfAZkf^Zlf]ZmfdZnfgZofhZpf_ZqfbZrfpZsfƒZtfˆZufŽZvf‰Zwf„Zxf˜ZyfZzfÁZ{f¹Z|fÉZ}f¾Z~f¼[!fÄ["f¸[#fÖ[$fÚ[%fà[&f?['fæ[(fé[)fð[*fõ[+f÷[,g[-g[.g[/g&[0g'[1—8[2g.[3g?[4g6[5gA[6g8[7g7[8gF[9g^[:g`[;gY[g‰[?gp[@g©[Ag|[Bgj[CgŒ[Dg‹[Eg¦[Fg¡[Gg…[Hg·[Igï[Jg´[Kgì[Lg³[Mgé[Ng¸[Ogä[PgÞ[QgÝ[Rgâ[Sgî[Tg¹[UgÎ[VgÆ[Wgç[Xjœ[Yh[ZhF[[h)[\h@[]hM[^h2[_hN[`h³[ah+[bhY[chc[dhw[eh[fhŸ[gh[hh­[ih”[jh[kh›[lhƒ[mj®[nh¹[oht[phµ[qh [rhº[si[th[uh~[vi[whÊ[xi[yhØ[zi"[{i&[|há[}i [~hÍ\!hÔ\"hç\#hÕ\$i6\%i\&i\'h×\(hã\)i%\*hù\+hà\,hï\-i(\.i*\/i\0i#\1i!\2hÆ\3iy\4iw\5i\\6ix\7ik\8iT\9i~\:in\;i9\iY\?i0\@ia\Ai^\Bi]\Ci\Dij\Ei²\Fi®\GiÐ\Hi¿\IiÁ\JiÓ\Ki¾\LiÎ\M[è\NiÊ\OiÝ\Pi»\QiÃ\Ri§\Sj.\Ti‘\Ui \Viœ\Wi•\Xi´\YiÞ\Ziè\[j\\j\]iÿ\^k \_iù\`iò\aiç\bj\ci±\dj\eií\fj\gië\hj \ij\jjÁ\kj#\lj\mjD\nj \ojr\pj6\qjx\rjG\sjb\tjY\ujf\vjH\wj8\xj"\yj\zj\{j \|j„\}j¢\~j£]!j—]"†]#j»]$jÃ]%jÂ]&j¸]'j³](j¬])jÞ]*jÑ]+jß],jª]-jÚ].jê]/jû]0k]1†]2jú]3k]4k]5›1]6k]7k8]8k7]9vÜ]:k9];˜î]kI]?kP]@kY]AkT]Bk[]Ck_]Dka]Ekx]Fky]Gk]Hk€]Ik„]Jkƒ]Kk]Lk˜]Mk•]Nkž]Ok¤]Pkª]Qk«]Rk¯]Sk²]Tk±]Uk³]Vk·]Wk¼]XkÆ]YkË]ZkÓ][kß]\kì]]kë]^kó]_kï]`ž¾]al]bl]cl]dl]el$]fl#]gl^]hlU]ilb]jlj]kl‚]ll]mlš]nl]ol›]pl~]qlh]rls]sl’]tl]ulÄ]vlñ]wlÓ]xl½]yl×]zlÅ]{lÝ]|l®]}l±]~l¾^!lº^"lÛ^#lï^$lÙ^%lê^&m^'ˆM^(m6^)m+^*m=^+m8^,m^-m5^.m3^/m^0m ^1mc^2m“^3md^4mZ^5my^6mY^7mŽ^8m•^9oä^:m…^;mù^mµ^?mÇ^@mæ^Am¸^BmÆ^Cmì^DmÞ^EmÌ^Fmè^GmÒ^HmÅ^Imú^JmÙ^Kmä^LmÕ^Mmê^Nmî^On-^Pnn^Qn.^Rn^Snr^Tn_^Un>^Vn#^Wnk^Xn+^Ynv^ZnM^[n^\nC^]n:^^nN^_n$^`nÿ^an^bn8^cn‚^dnª^en˜^fnÉ^gn·^hnÓ^in½^jn¯^knÄ^ln²^mnÔ^nnÕ^on^pn¥^qnÂ^rnŸ^soA^to^upL^vnì^wnø^xnþ^yo?^znò^{o1^|nï^}o2^~nÌ_!o>_"o_#n÷_$o†_%oz_&ox_'o_(o€_)oo_*o[_+oó_,om_-o‚_.o|_/oX_0oŽ_1o‘_2oÂ_3of_4o³_5o£_6o¡_7o¤_8o¹_9oÆ_:oª_;oß_oÔ_?oØ_@oñ_Aoî_BoÛ_Cp _Dp _Eoú_Fp_Gp_Hp_Ioþ_Jp_Kp_Lot_Mp_Np_Op_Pp0_Qp>_Rp2_SpQ_Tpc_Up™_Vp’_Wp¯_Xpñ_Yp¬_Zp¸_[p³_\p®_]pß_^pË__pÝ_`pÙ_aq _bpý_cq_dq_eqe_fqU_gqˆ_hqf_iqb_jqL_kqV_lql_mq_nqû_oq„_pq•_qq¨_rq¬_sq×_tq¹_uq¾_vqÒ_wqÉ_xqÔ_yqÎ_zqà_{qì_|qç_}qõ_~qü`!qù`"qÿ`#r `$r`%r`&r(`'r-`(r,`)r0`*r2`+r;`,r<`-r?`.r@`/rF`0rK`1rX`2rt`3r~`4r‚`5r`6r‡`7r’`8r–`9r¢`:r§`;r¹`rÆ`?rÄ`@rÎ`ArÒ`Brâ`Crà`Drá`Erù`Fr÷`GP`Hs`Is `Js`Ks`Ls`Ms4`Ns/`Os)`Ps%`Qs>`RsN`SsO`TžØ`UsW`Vsj`Wsh`Xsp`Ysx`Zsu`[s{`\sz`]sÈ`^s³`_sÎ``s»`asÀ`bså`csî`dsÞ`et¢`ft`gto`ht%`isø`jt2`kt:`ltU`mt?`nt_`otY`ptA`qt\`rti`stp`ttc`utj`vtv`wt~`xt‹`ytž`zt§`{tÊ`|tÏ`}tÔ`~sña!tàa"tãa#tça$téa%tîa&tòa'tða(tña)tøa*t÷a+ua,ua-ua.u a/ua0u a1ua2ua3ua4u&a5u,a6uuia?uda@ugaAukaBumaCuxaDuvaEu†aFu‡aGutaHuŠaIu‰aJu‚aKu”aLušaMuaNu¥aOu£aPuÂaQu³aRuÃaSuµaTu½aUu¸aVu¼aWu±aXuÍaYuÊaZuÒa[uÙa\uãa]uÞa^uþa_uÿa`uüaavabuðacuúaduòaeuóafv agv ahv aivajv'akv alv!amv"anv$aov4apv0aqv;arvGasvHatvFauv\avvXawvaaxvbayvhazvia{vja|vga}vla~vpb!vrb"vvb#vxb$v|b%v€b&vƒb'vˆb(v‹b)vŽb*v–b+v“b,v™b-všb.v°b/v´b0v¸b1v¹b2vºb3vÂb4vÍb5vÖb6vÒb7vÞb8váb9våb:vçb;vêb<†/b=vûb>wb?wb@wbAw)bBw$bCwbDw%bEw&bFwbGw7bHw8bIwGbJwZbKwhbLwkbMw[bNwebOwbPw~bQwybRwŽbSw‹bTw‘bUw bVwžbWw°bXw¶bYw¹bZw¿b[w¼b\w½b]w»b^wÇb_wÍb`w×bawÚbbwÜbcwãbdwîbewübfx bgxbhy&bix bjy*bkxEblxŽbmxtbnx†box|bpxšbqxŒbrx£bsxµbtxªbux¯bvxÑbwxÆbxxËbyxÔbzx¾b{x¼b|xÅb}xÊb~xìc!xçc"xÚc#xýc$xôc%yc&yc'yc(yc)y,c*y+c+y@c,y`c-yWc.y_c/yZc0yUc1ySc2yzc3yc4yŠc5yc6y§c7ŸKc8yªc9y®c:y³c;y¹cyÕc?yçc@yìcAyácByãcCzcDz cEzcFzcGz cHzcIy€cJz1cKz;cLz>cMz7cNzCcOzWcPzIcQzacRzbcSzicTŸcUzpcVzycWz}cXzˆcYz—cZz•c[z˜c\z–c]z©c^zÈc_z°c`z¶cazÅcbzÄccz¿cdƒcezÇcfzÊcgzÍchzÏcizÕcjzÓckzÙclzÚcmzÝcnzácozâcpzæcqzícrzðcs{ct{cu{ cv{cw{3cx{cy{cz{c{{5c|{(c}{6c~{Pd!{zd"{d#{Md${ d%{Ld&{Ed'{ud({ed){td*{gd+{pd,{qd-{ld.{nd/{d0{˜d1{Ÿd2{d3{œd4{šd5{‹d6{’d7{d8{]d9{™d:{Ëd;{Ád<{Ìd={Ïd>{´d?{Æd@{ÝdA{édB|dC|dD{ædE{ådF|`dG|dH|dI|dJ{ódK{÷dL|dM| dN{ödO|#dP|'dQ|*dR|dS|7dT|+dU|=dV|LdW|CdX|TdY|OdZ|@d[|Pd\|Xd]|_d^|dd_|Vd`|eda|ldb|udc|ƒdd|de|¤df|­dg|¢dh|«di|¡dj|¨dk|³dl|²dm|±dn|®do|¹dp|½dq|Àdr|Åds|Âdt|Ødu|Òdv|Üdw|âdx›;dy|ïdz|òd{|ôd||öd}|úd~}e!}e"}e#}e$} e%}Ee&}Ke'}.e(}2e)}?e*}5e+}Fe,}se-}Ve.}Ne/}re0}he1}ne2}Oe3}ce4}“e5}‰e6}[e7}e8}}e9}›e:}ºe;}®e<}£e=}µe>}Çe?}½e@}«eA~=eB}¢eC}¯eD}ÜeE}¸eF}ŸeG}°eH}ØeI}ÝeJ}äeK}ÞeL}ûeM}òeN}áeO~eP~ eQ~#eR~!eS~eT~1eU~eV~ eW~ eX~"eY~FeZ~fe[~;e\~5e]~9e^~Ce_~7e`~2ea~:eb~gec~]ed~Vee~^ef~Yeg~Zeh~yei~jej~iek~|el~{em~ƒen}Õeo~}ep®eq~er~ˆes~‰et~Œeu~’ev~ew~“ex~”ey~–ez~Že{~›e|~œe}8e~:f!Ef"Lf#Mf$Nf%Pf&Qf'Uf(Tf)Xf*_f+`f,hf-if.gf/xf0‚f1†f2ƒf3ˆf4‡f5Œf6”f7žf8f9šf:£f;¯f<²f=¹f>®f?¶f@¸fA‹qfBÅfCÆfDÊfEÕfFÔfGáfHæfIéfJófKùfL˜ÜfM€fN€fO€ fP€fQ€fR€fS€fT€!fU€(fV€?fW€;fX€JfY€FfZ€Rf[€Xf\€Zf]€_f^€bf_€hf`€sfa€rfb€pfc€vfd€yfe€}ff€fg€„fh€†fi€…fj€›fk€“fl€šfm€­fnQfo€¬fp€Ûfq€åfr€Ùfs€Ýft€Äfu€Úfv€Öfw fx€ïfy€ñfzf{)f|#f}/f~Kg!–‹g"Fg#>g$Sg%Qg&€üg'qg(ng)eg*fg+tg,ƒg-ˆg.Šg/€g0‚g1 g2•g3¤g4£g5_g6“g7©g8°g9µg:¾g;¸g<½g=Àg>Âg?ºg@ÉgAÍgBÑgCÙgDØgEÈgFÚgGßgHàgIçgJúgKûgLþgM‚gN‚gO‚gP‚gQ‚ gR‚ gS‚gT‚gU‚)gV‚+gW‚8gX‚3gY‚@gZ‚Yg[‚Xg\‚]g]‚Zg^‚_g_‚dg`‚bga‚hgb‚jgc‚kgd‚.ge‚qgf‚wgg‚xgh‚~gi‚gj‚’gk‚«gl‚Ÿgm‚»gn‚¬go‚ágp‚ãgq‚ßgr‚Ògs‚ôgt‚ógu‚úgvƒ“gwƒgx‚ûgy‚ùgz‚Þg{ƒg|‚Üg}ƒ g~‚Ùh!ƒ5h"ƒ4h#ƒh$ƒ2h%ƒ1h&ƒ@h'ƒ9h(ƒPh)ƒEh*ƒ/h+ƒ+h,ƒh-ƒh.ƒ…h/ƒšh0ƒªh1ƒŸh2ƒ¢h3ƒ–h4ƒ#h5ƒŽh6ƒ‡h7ƒŠh8ƒ|h9ƒµh:ƒsh;ƒuh<ƒ h=ƒ‰h>ƒ¨h?ƒôh@„hAƒëhBƒÎhCƒýhD„hEƒØhF„ hGƒÁhHƒ÷hI„hJƒàhKƒòhL„ hM„"hN„ hOƒ½hP„8hQ…hRƒûhS„mhT„*hU„† i?†i@† iA…þiB…úiC†iD†"iE†iF†0iG†?iH†MiINUiJ†TiK†_iL†giM†qiN†“iO†£iP†©iQ†ªiR†‹iS†ŒiT†¶iU†¯iV†ÄiW†ÆiX†°iY†ÉiZˆ#i[†«i\†Ôi]†Þi^†éi_†ìi`†ßia†Ûib†ïic‡id‡ie‡if‡ig‡ih†ûii‡ij‡ ik‡ il†ùim‡ in‡4io‡?ip‡7iq‡;ir‡%is‡)it‡iu‡`iv‡_iw‡xix‡Liy‡Niz‡ti{‡Wi|‡hi}‡ni~‡Yj!‡Sj"‡cj#‡jj$ˆj%‡¢j&‡Ÿj'‡‚j(‡¯j)‡Ëj*‡½j+‡Àj,‡Ðj-–Öj.‡«j/‡Äj0‡³j1‡Çj2‡Æj3‡»j4‡ïj5‡òj6‡àj7ˆj8ˆ j9‡þj:‡öj;‡÷j<ˆj=‡Òj>ˆj?ˆj@ˆjAˆ"jBˆ!jCˆ1jDˆ6jEˆ9jFˆ'jGˆ;jHˆDjIˆBjJˆRjKˆYjLˆ^jMˆbjNˆkjOˆjPˆ~jQˆžjRˆujSˆ}jTˆµjUˆrjVˆ‚jWˆ—jXˆ’jYˆ®jZˆ™j[ˆ¢j\ˆj]ˆ¤j^ˆ°j_ˆ¿j`ˆ±jaˆÃjbˆÄjcˆÔjdˆØjeˆÙjfˆÝjgˆùjh‰jiˆüjjˆôjkˆèjlˆòjm‰jn‰ jo‰ jp‰jq‰Cjr‰js‰%jt‰*ju‰+jv‰Ajw‰Djx‰;jy‰6jz‰8j{‰Lj|‰j}‰`j~‰^k!‰fk"‰dk#‰mk$‰jk%‰ok&‰tk'‰wk(‰~k)‰ƒk*‰ˆk+‰Šk,‰“k-‰˜k.‰¡k/‰©k0‰¦k1‰¬k2‰¯k3‰²k4‰ºk5‰½k6‰¿k7‰Àk8‰Úk9‰Ük:‰Ýk;‰çk<‰ôk=‰øk>Šk?Šk@ŠkAŠ kBŠkCŠkDŠ%kEŠ6kFŠAkGŠ[kHŠRkIŠFkJŠHkKŠ|kLŠmkMŠlkNŠbkOŠ…kPŠ‚kQŠ„kRЍkSŠ¡kTŠ‘kUŠ¥kVЦkWŠškXŠ£kYŠÄkZŠÍk[ŠÂk\ŠÚk]Šëk^Šók_Šçk`ŠäkaŠñkb‹kcŠàkdŠâkeŠ÷kfŠÞkgŠÛkh‹ ki‹kj‹kkŠákl‹km‹kn‹ko‹ kp‹3kq—«kr‹&ks‹+kt‹>ku‹(kv‹Akw‹Lkx‹Oky‹Nkz‹Ik{‹Vk|‹[k}‹Zk~‹kl!‹_l"‹ll#‹ol$‹tl%‹}l&‹€l'‹Œl(‹Žl)‹’l*‹“l+‹–l,‹™l-‹šl.Œ:l/ŒAl0Œ?l1ŒHl2ŒLl3ŒNl4ŒPl5ŒUl6Œbl7Œll8Œxl9Œzl:Œ‚l;Œ‰l<Œ…l=ŒŠl>Œl?ŒŽl@Œ”lAŒ|lBŒ˜lCblDŒ­lEŒªlFŒ½lGŒ²lHŒ³lIŒ®lJŒ¶lKŒÈlLŒÁlMŒälNŒãlOŒÚlPŒýlQŒúlRŒûlSlTlU lVlWlX lYlZŸNl[l\ŒÍl]l^l_gl`mlaqlbslcld™leÂlf¾lgºlhÏliÚljÖlkÌllÛlmËlnêloëlpßlqãlrülsŽltŽ luÿlvŽlwŽlxŽlyŽlzŽBl{Ž5l|Ž0l}Ž4l~ŽJm!ŽGm"ŽIm#ŽLm$ŽPm%ŽHm&ŽYm'Ždm(Ž`m)Ž*m*Žcm+ŽUm,Žvm-Žrm.Ž|m/Žm0އm1Ž…m2Ž„m3Ž‹m4ŽŠm5Ž“m6Ž‘m7Ž”m8Ž™m9Žªm:Ž¡m;ެm<ްm=ŽÆm>ޱm?޾m@ŽÅmAŽÈmBŽËmCŽÛmDŽãmEŽümFŽûmGŽëmHŽþmI mJmKmLmMmNmOmPmQmR mS&mT3mU;mV9mWEmXBmY>mZLm[Im\Fm]Nm^Wm_\m`bmacmbdmcœmdŸme£mf­mg¯mh·miÚmjåmkâmlêmmïmn‡moômpmqùmrúmsmtmu!mv mwmxmy mz'm{6m|5m}9m~øn!On"Pn#Qn$Rn%n&In'>n(Vn)Xn*^n+hn,on-vn.–¨n/rn0‚n1}n2n3€n4Šn5‰n6n7¨n8¯n9±n:µn;ân<än=bHn>Ûn?‘n@‘nA‘nB‘2nC‘0nD‘JnE‘VnF‘XnG‘cnH‘enI‘inJ‘snK‘rnL‘‹nM‘‰nN‘‚nO‘¢nP‘«nQ‘¯nR‘ªnS‘µnT‘´nU‘ºnV‘ÀnW‘ÁnX‘ÉnY‘ËnZ‘Ðn[‘Ön\‘ßn]‘án^‘Ûn_‘ün`‘õna‘önb’nc‘ÿnd’ne’,nf’ng’nh’^ni’Wnj’Enk’Inl’dnm’Hnn’•no’?np’Knq’Pnr’œns’–nt’“nu’›nv’Znw’Ïnx’¹ny’·nz’én{“n|’ún}“Dn~“.o!“o"“"o#“o$“#o%“:o&“5o'“;o(“\o)“`o*“|o+“no,“Vo-“°o.“¬o/“­o0“”o1“¹o2“Öo3“×o4“èo5“åo6“Øo7“Ão8“Ýo9“Ðo:“Èo;“äo<”o=”o>”o?”o@”oA”oB”6oC”+oD”5oE”!oF”:oG”AoH”RoI”DoJ”[oK”`oL”boM”^oN”joO’)oP”poQ”uoR”woS”}oT”ZoU”|oV”~oW”oX”oY•‚oZ•‡o[•Šo\•”o]•–o^•˜o_•™o`• oa•¨ob•§oc•­od•¼oe•»of•¹og•¾oh•Êoioöoj•Ãok•Íol•Ìom•Õon•Ôoo•Öop•Üoq•áor•åos•âot–!ou–(ov–.ow–/ox–Boy–Loz–Oo{–Ko|–wo}–\o~–^p!–]p"–_p#–fp$–rp%–lp&–p'–˜p(–•p)–—p*–ªp+–§p,–±p-–²p.–°p/–´p0–¶p1–¸p2–¹p3–Îp4–Ëp5–Ép6–Íp7‰Mp8–Üp9— p:–Õp;–ùp<—p=—p>—p?—p@—pA—pB—pC—pD—pE—$pF—*pG—0pH—9pI—=pJ—>pK—DpL—FpM—HpN—BpO—IpP—\pQ—`pR—dpS—fpT—hpURÒpV—kpW—qpX—ypY—…pZ—|p[—p\—zp]—†p^—‹p_—p`—pa—œpb—¨pc—¦pd—£pe—³pf—´pg—Ãph—Æpi—Èpj—Ëpk—Üpl—ípmŸOpn—òpozßpp—öpq—õpr˜ps˜ pt˜8pu˜$pv˜!pw˜7px˜=py˜Fpz˜Op{˜Kp|˜kp}˜op~˜pq!˜qq"˜tq#˜sq$˜ªq%˜¯q&˜±q'˜¶q(˜Äq)˜Ãq*˜Æq+˜éq,˜ëq-™q.™ q/™q0™q1™q2™!q3™q4™q5™$q6™ q7™,q8™.q9™=q:™>q;™Bq<™Iq=™Eq>™Pq?™Kq@™QqA™RqB™LqC™UqD™—qE™˜qF™¥qG™­qH™®qI™¼qJ™ßqK™ÛqL™ÝqM™ØqN™ÑqO™íqP™îqQ™ñqR™òqS™ûqT™øqUšqVšqWšqX™âqYšqZš+q[š7q\šEq]šBq^š@q_šCq`š>qašUqbšMqcš[qdšWqeš_qfšbqgšeqhšdqišiqjškqkšjqlš­qmš°qnš¼qošÀqpšÏqqšÑqršÓqsšÔqtšÞqušßqvšâqwšãqxšæqyšïqzšëq{šîq|šôq}šñq~š÷r!šûr"›r#›r$›r%›r&›"r'›#r(›%r)›'r*›(r+›)r,›*r-›.r.›/r/›2r0›Dr1›Cr2›Or3›Mr4›Nr5›Qr6›Xr7›tr8›“r9›ƒr:›‘r;›–r<›—r=›Ÿr>› r?›¨r@›´rA›ÀrB›ÊrC›¹rD›ÆrE›ÏrF›ÑrG›ÒrH›ãrI›ârJ›ärK›ÔrL›árMœ:rN›òrO›ñrP›ðrQœrRœrSœ rTœrUœ rVœrWœrXœrYœ rZœr[œ.r\œr]œ%r^œ$r_œ!r`œ0raœGrbœ2rcœFrdœ>reœZrfœ`rgœgrhœvriœxrjœçrkœìrlœðrm rnroœërprqrr*rs&rt¯ru#rvrwDrxryrzAr{?r|>r}Fr~Hs!]s"^s#ds$Qs%Ps&Ys'rs(‰s)‡s*«s+os,zs-šs.¤s/©s0²s1Äs2Ás3»s4¸s5ºs6Æs7Ïs8Âs9Ùs:Ós;øs<æs=ís>ïs?ýs@žsAžsBžsCžusDžysEž}sFžsGžˆsHž‹sIžŒsJž’sKž•sLž‘sMžsNž¥sOž©sPž¸sQžªsRž­sS—asTžÌsUžÎsVžÏsWžÐsXžÔsYžÜsZžÞs[žÝs\žàs]žås^žès_žïs`žôsažösbž÷scžùsdžûsežüsfžýsgŸshŸsiv·sjŸskŸ!slŸ,smŸ>snŸJsoŸRspŸTsqŸcsrŸ_ssŸ`stŸasuŸfsvŸgswŸlsxŸjsyŸwszŸrs{Ÿvs|Ÿ•s}Ÿœs~Ÿ t!X/t"iÇt#Yt$tdt%QÜt&q™screen-4.1.0/list_generic.h0000644000175000017500000000510611642704565013667 0ustar abeabe/* Copyright (c) 2010 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net) * * 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, 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 (see the file COPYING); if not, see * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA * **************************************************************** */ struct ListData; struct ListRow { void *data; /* Some data relevant to this row */ struct ListRow *next, *prev; /* doubly linked list */ int y; /* -1 if not on display */ }; struct GenericList { int (*gl_printheader) __P((struct ListData *)); /* Print the header */ int (*gl_printfooter) __P((struct ListData *)); /* Print the footer */ int (*gl_printrow) __P((struct ListData *, struct ListRow *)); /* Print one row */ int (*gl_pinput) __P((struct ListData *, char **inp, int *len)); /* Process input */ int (*gl_freerow) __P((struct ListData *, struct ListRow *)); /* Free data for a row */ int (*gl_free) __P((struct ListData *)); /* Free data for the list */ int (*gl_matchrow) __P((struct ListData *, struct ListRow *, const char *)); }; struct ListData { const char *name; /* An identifier for the list */ struct ListRow *root; /* The first item in the list */ struct ListRow *selected; /* The selected row */ struct ListRow *top; /* The topmost visible row */ struct GenericList *list_fn; /* The functions that deal with the list */ char *search; /* The search term, if any */ void *data; /* List specific data */ }; extern struct LayFuncs ListLf; struct ListRow * glist_add_row __P((struct ListData *ldata, void *data, struct ListRow *after)); void glist_remove_rows __P((struct ListData *ldata)); void glist_display_all __P((struct ListData *list)); struct ListData * glist_display __P((struct GenericList *list, const char *name)); void glist_abort __P((void)); void display_displays __P((void)); void display_windows __P((int onblank, int order, struct win *group)); screen-4.1.0/ChangeLog0000644000175000017500000004113211732171225012607 0ustar abeabeVersion 4.1.0 (??/??/20??): New Commands: * 'unbindall' to unbind all commands * 'up', 'down', 'left', 'right' sub-commands for 'focus' * 'rendition' to specify rendition to use in caption/hardstatus for window-names that have bell/monitor/silence/so turned on. * 'layout', with the following sub-commands - 'title' - 'number' - 'autosave' ('autosave on' or 'autosave off') - 'new' - 'save' ('save ') - 'select' - 'next' - 'prev' - 'attach' - 'show' - 'remove' - 'dump' * 'group' for moving window(s) into a group. * 'defmousetrack' and 'mousetrack', to turn on/off mouse-tracking for displays. It's turned off by default. With mouse-tracking turned on, it's possible to switch to a region ('focus') using mouse clicks. It's also possible to select a text region in copy-mode using a mouse click to place a mark and the scroll wheel to scroll through the buffer. Additional features might be to allow clicking on window-titles in the caption to switch to that window. * All commands prefixed '@' are treated as 'quiet', i.e. '@'-prefixed commands do not trigger any display messages. Changed Commands: * '-v' parameter to 'split' command for vertical splits. * 'sorendition' deprecated in favour of 'rendition so'. * 'digraph' can take a second parameter to specify custom digraphs. For example, 'digraph >= ≥' or 'digraph >= U+2265' Using '0' as the second parameter will remove the digraph. * 'stuff' will prompt for input if there's nothing to stuff. * The argument to ":number" can be prefixed with '+' or '-' to use it as a relative argument. * '-g' parameter to 'windowlist' to show nested list of windows. * '//group' parameter to 'screen' to create a grouped window. * 'blankerprg' shows the currently set command on no argument. * 'maxwin' can now be used to increase the number of maximum windows. .screenrc: * $PID expands to the PID of the screen session. * $PWD expands to the current working directory of the session. * $STY expands to the session name. * Tilde-expansion in pathnames (e.g. for the 'source' command) * C-style escapes can be used (e.g. "\n" to get a newline with 'stuff') * '%p' in caption/hardstatus string expands to the PID of the backend, and '%+p' expands to the PID of the frontend (display). * '%S' in caption/hardstatus string expands to the session name. * '%P' in the caption string evaluates to true if the region is in copy mode. * '%E' in the caption string evaluates to true if the escape character has currently been pressed. Window List: * Nested views when there are window groups (with 'windowlist -g'). * Press 'm' to toggle the most-recent view. * Press 'g' to toggle nestedness. * Press 'a' to view all windows in the list. * Press '/' to search in the list. * Press ',' and '.' to re-order windows in the list. * Press 'K' to kill a window (requires confirmation). Display List: * Press 'd' to detach a display, 'D' to power-detach. Others: * Start using 'ChangeLog' for logging changes again. * Terminfo update for 256-color support. * Multiple input history (partially from Romain Francoise). * vi-like fFtT;, searching in copy mode. * In copy mode, search in reverse direction when 'N' is pressed. * Tab-completion for command input. * Some more readline-like bindings in input mode (e.g. ^W, ^D, ^P, ^N etc.) * Fix displaying unicode characters in the caption/hardstatus on UTF8 locale. * A revamped displays list (for 'displays' command) * Increased default maximum number of windows from 40 to 100. * Increased number color/attribute changes in caption/hardstatus string from 16 to 256. * Some commands can be remotely queried using the -Q command-line flag. In-Progress: * Scripting support (thanks to Google Summer of Code 2009 project by Rui Guo) Developers: * Juergen Weigert * Michael Schroeder * Micah Cowan * Sadrul Habib Chowdhury Contributors: * Clavelito * Dick * Gabriel * Benjamin Andresen * Takeshi Banse * Maarten Billemont * Curtis Brown * Cyril Brulebois * Trent W Buck * Stephane Chazelas * Kees Cook * Thomas Dickey * Christian Ebert * Geraint Edwards * Romain Francoise * Alexander Gattin * Emanuele Giaquinta * Yi-Hsuan Hsin * Kipling Inscore * Chris Jones * Max Kalashnikov * Steve Kemp * Ryan Niebur * Jan Christoph Nordholz * William Pursell * Michael Scherer * Enrico Scholz * Peter Teichman 30.10.94 This is a quick overview of screen's life story. But it is not up to date. You'll find more details about the revision history in patchlevel.h and newer changes are only documented there. 31.7.93 -- 3.5.1 ================ * writelock, number, paste with arg, at, zombie and wall commands added. * Access Control Lists and more multi-user support added. * select and setenv commands enhanced. * socket.c: motorola bugfix. * configure.in: --srcdir support. * configure.in: recognize alpha and SUNOS3 correctly. * doc/screen.texinfo: Documentation by Jason Merrill. 13.05.93 -- 3.3.3 ================= * defautonuke, silence commands added. * exec command added. * hardcopydir, logdir commands added. * Made a superb configure script. * BROKEN_PIPE, SOCK_NOT_IN_FS added for braindamaged systems. * multi display, multi user support. * process command. CS, CE switch cursorkeycap in application mode. * lockprg pow_detaches on SIGHUP * ins_reg copy_reg commands. * new screenrc syntax. * split up screen.c and ansi.c 21.10.92 -- 3.2.9 ================ * ChangeLog: replaces CHANGES and is in GNUish format. * Makefile (CFLAGS, M_CFLAGS, LIBS, OPTIONS): moved user config here, merged all Makefiles, GNUified * socket.c (FindSocket): ignoring bad files in $SCREENDIR * config/config.linux: ported. * utmp.c, exec.c, loadav.c: split apart from screen.c/fileio.c 15.07.92 -- 3.2.8 ================= * ansi.c (WriteString): automatic character set switching for 8bit support 3.2.3-3.2.7 =========== * concept changes: Display structure, Multi attacher ... 3.2.2 ===== * screen.c (main): -m option, "_M_ake always new session", ignore $STY * screen.c (main): -Ssessionname * fileio.c (RcLine): ^A:sessionname give your session a nicer name. * screen.c (main): supporting detached startup via screen -d -m -Ssockname * fileio.c (stripdev): moved, could not compile * overlay.h: "stackable overlay concept" * search.c: vi-like / and ? search AND emacs-like ^S and ^R incremental search in scrollback * mark.c: I meant BSDI not BSD * concept change: struct display and struct newwin introduced. * screen.c (main): -v option prints version. * screen.c (MakeWindow): ^A:screen /dev/ttya opens a character device instead of forking ShellProg with a pty pair. 3.2.0 ===== Ultrix port Irix 3.3 SGI port shadow password suite supported data loss on stdin overflow fixed "refresh off" keyword added. 3.1.1 ------ Screen is now under the GNU copyleft license. See file COPYING. command line option -A. $LINES, $COLUMNS improved. C-A : vbellwait XENIX support (Ronald Khoo) SYSV has uname() instead of gethostname(). hpux has setresuid. ClearScreen now saves image to scrollback buffer. mips has setenv. numerous bugfixes. 3.1 finally released version. ============================= 3.0.99: last minute changes: ---------------------------- MIPS support (J{rvinen Markku) SVR4 support (Marc Boucher) secopen() secfopen() calls replace stat/access/open. C-a : echo improved. 'register int' Changes up to Screen 3.0 Patchlevel 7 ===================================== Better terminfo support: Screen now checks if a termcap/info entry which the name "screen.$TERM" does exist. Look in the "VIRTUAL TERMINAL" section of the manual for more details. Many security improvements. ScrollRegion() bug fixed which caused slow scrolling if AL or DL was used. Pyramid and Ultrix support added. (Tim and Larry) ENVIRONMENT support. /local/etc/screenrc checks for $SYSSCREENRC $HOME/.screenrc checks for $ISCREENRC and $SCREENRC /local/screens checks for $ISCREENDIR and $SCREENDIR .screenrc understands ${VAR} and $VAR . screen 3.0 Patchlevel 6 ======================= .screenrc: screen now only opens the windows you explicitly ask for. if you specify none, you still get one window, of course. screen 3.0. Patchlevel 5 ======================== Ansi prototyping by Christos. copy mode: CTRL-U / CTRL-D exchanged. code cleanup. changes to screen 3.0 patchlevel 4 ================================== markkeys "string" allows to rebind the keys used in copy/history mode. string is made up of pairs "=" which are separated by a colon. Oldchar and newchar are either single ascii characters, or the two character sequence ^x, where x is an ascii character, or a 3 digit octal value prepended with '\'. the string "\040=.:^M=q" rebinds '.' to set marks, and the return rey will abort copy mode. set scrollback 100 resizes the scrollback history buffer to 100 lines. a default of 50 is installed. A Howard Chu like scrollback history is installed. Many vi-like keys are added to the copy mode. The '?' key reports on cursor position. screen 3.0 Patchlevel 3 ======================= WriteString fixed, it did kill the display variable. Yet another LP bugfix. non vt100 semi-graphics character support. waynes patch fixed screen 3.0 Patchlevel 2 ======================= wayne patches cursor motion outside scrollregions. .screenrc monitor on|off changes in Screen 3.0 Patchlevel 1 ================================== screen -wipe ^A : set vbell_msg "Wuff Wuff" Thousand enhancements: help resizible, copy'n'paste in main socket loop, and no more '\0' hackin'. :WS=\E8;%d;%dt: screen can now resize windows under sunview. ^A : set crlf on|off effects markroutine join. screen learned about sized windows under X screen -ls (-d) -q quiet option. We count the number of detached (attached) sessions and set a return value of 10+n. The -q option inhibits all startup warnings/messages. i.e. screen -R -q may return with code 12 or higher or start a new/old session. pow_detach_msg "text string" new command, allows messages, terminal reset, etc. on logout caused by pow_detach. ^A : learned a new keyword "set": commands like "login on" , "vbell off", ... affect the default for windows to be created. But commands like "set login off" affect the actual setting of this window. and not the default. such commands may be bound to keys. example: bind 'O' set login off is valid in your .screenrc as well as typed at the ':' prompt. a bonus is ":set all" which is synonym to ":help". At the Colon prompt also KeyNames can be entered, alothough that makes not always sense. ^A x uses a builtin lockprg, if a) we don't find our lockprg, or b) user supplies us with the environmet variable LOCKPRG set to "builtin" the builtin locks until your login password is typed. on systems using "shadow password files" you are prompted for a password. markroutine can append joined. screen removes the "controlling tty" from utmp while ptys are attached. markroutine performs CR+NL when '\n' is pressed screen may die quietly, when no TERMCAP entry for "screen" is found, and screen is run under X-windows _SEQUENT_ marks sequent386_ptx screen runs now under SunOS4.1.1 (we need setsid()!). bug in SetForeWindow fixed. rare markroutine bug fixed. we dont open every file the attacher tells us. we have now our wonderful "Wuff, Wuff" visual_bell we have now the interprocess-communication-buffer. secure version. '^A =' removes the interprocess-communication-buffer. markroutine as in 2.1 markroutine: 'a' toggles append mode, '>' like ' ', but immediately WriteFile(DUMP_EXCHANGE) then. 'A' like ' ', but first switch to append mode. .screenrc understands "screen 2:faui09 rlogin faui09 -l jnweiger" and "password none" and "vbell [on|off]" '^A :' allows .screenrc commands "online". screen now receives new $TERM from attacher, when it is reattached MakeClientSocket() fifo version does now test for access. .screenrc learns "hardstatus {on|off}" termcap's VB is used for vbell if available. Attach() code rewritten: screen now lists socket directory, if it does not find a suitable socket screen -d [host.tty] detaches a running screen. screen -[ls|list] list all sockets that we find in our sockdir when the socket has been removed, send a SIGCHLD to the poor SCREEN process and it will try to recover. then try a 'screen -r' again. all the socket stuff lives now in an extra file. Major changes in version 2.4: ============================= * Test version that presents the erlangen extensions from 2.0 in a 2.3 screen. * window resize support * screen locking C-a x * support for SYSV * password protection * copy & paste across screens * remote detach and power detach Major changes in version 2.3: * Terminal emulation has been significantly enhanced and bugfixed. * We now fully update the last character on the screen for true auto- margin terminals, though there may be some delay before the character can be safely added to the screen. If your terminal has character insert it will be used to shorten the delay. * Added the "termcap" .screenrc command to tweak your terminal's termcap entry AND to customize the termcap generated for the virtual terminals. See also the -L and -O command-line options, and the SCREENCAP environ- ment variable. * Fixed screen's character handling when detached or suspended to NOT block the child processes in their windows -- output continues to be processed in the background. * Added a.k.a.s (window-name aliases) that allow you to customize the window-information line, including being able to change the name on- the-fly to reflect what's currently running in the window (see the -k option, shellaka command, and ALSO KNOWN AS discussion in the doc). * Added the ability to log the output of a window to a file (see the "C-a H" (log) command). * Flow-control can now be set for each window and switched interactively (see the "flow" command, -f option, and FLOW CONTROL discussion). * Individual windows can be included or excluded from mention in the /etc/utmp file (see the "login" command and -l option). * Added an activity monitor, which allows you to have a window watched for the start of any output and alert you when it occurs (see the "C-a M" (monitor) command). * Enhanced the information in the window-information line to keep track of windows that have: logging turned on '(L)'; beeped in the background '!'; became active while being monitored '@' (see the "C-a w" (windows) command). * Added an on-line help display that lists all the commands and their key bindings (see the "C-a ?" (help) command). * Extended handling of the beep message (and also the new activity message) to allow '~' to specify a literal beep (see the "beep" and "activity" .screenrc commands). * You can now set the default action on receipt of a hangup signal: detach or terminate (see the "autodetach" .screenrc command). * Routing of characters to their virtual terminals has been enhanced to not drop characters nor (in rare circumstances) hang up screen. * The NFS compatibility has been enhanced. Major changes in version 2.0a: * Screen allows you to `detach' the "screen" session from the physical terminal and resume it at a later point in time (possibly on a different terminal or in a different login session). To get an impression of this functionality do the following: - call "screen" and create a couple of windows - type Control-A Control-D (screen terminates; you are back in the shell) - call "screen -r" to resume the detached screen * Screen supports multiple character sets and the ISO 2022 control functions to designate and switch between character sets. This allows you, for instance, to make use of the VT100 graphics character set or national character sets. screen-4.1.0/NEWS.3.70000644000175000017500000000270211642704565012053 0ustar abeabe ---------------------------- What's new in screen-3.7 ? ---------------------------- * Color support. Screen understands the following capabilities: AF (setaf) = Set foreground color (ANSI compatible) AB (setab) = Set background color (ANSI compatible) AX = Does understand ANSI set default fg/bg color (\E[39m / \E[49m) The tweaks for the color xterm would be: termcap xterm 'AF=\E[3%dm:AB=\E[4%dm' terminfo xterm 'AF=\E[3%p1%dm:AB=\E[4%p1%dm' * New 'digraph' command (bound to ^A^V) ^A^Va" or ^A^V0344 input an a-umlaut * activity/bell message strings can now include the window title: %t - title %n - number (a single % still works) * 'defhstatus' command to give everey window a default hardstatus line. ^E is used as a string escape instead of % (see above). Try 'defhstatus "Screen: window ^E (^Et)"' * Input parser changed to understand '^' (see ^E above). Note that the linux color xterm has a stupid bug: the characters get the color of the cursor, therefore if you change color and move the cursor around all the characters will get the new color... Here is a patch: pub/utilities/screen/color_xterm_patch Btw.: rxvt works fine. * Optional Braille support. If you can read Braille and have one of the devices listed in README.DOTSCREEN, please compile with -DHAVE_BRAILLE and let us know if this feature is useful. screen-4.1.0/tty.sh0000644000175000017500000011441311642704565012225 0ustar abeabe#! /bin/sh # sh tty.sh tty.c # This inserts all the needed #ifdefs for IF{} statements # and generates tty.c # # Stupid cpp on A/UX barfs on ``#if defined(FOO) && FOO < 17'' when # FOO is undefined. Reported by Robert C. Tindall (rtindall@uidaho.edu) # rm -f $1 sed -e '1,26d' \ -e 's%^IF{\([^}]*\)}\(.*\)%#if defined(\1)\ \2\ #endif /* \1 */%' \ -e 's%^IFN{\([^}]*\)}\(.*\)%#if !defined(\1)\ \2\ #endif /* \1 */%' \ -e 's%^XIF{\([^}]*\)}\(.*\)%#if defined(\1)\ #if (\1 < MAXCC)\ \2\ #endif \ #endif /* \1 */%' \ < $0 > $1 chmod -w $1 exit 0 /* Copyright (c) 2008, 2009 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Micah Cowan (micah@cowan.name) * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net) * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Copyright (c) 1987 Oliver Laumann * * 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, 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 (see the file COPYING); if not, see * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA * **************************************************************** */ /* * NOTICE: tty.c is automatically generated from tty.sh * Do not change anything here. If you then change tty.sh. */ #include #include #include #ifndef sgi # include #endif #if !defined(sun) || defined(SUNOS3) # include /* collosions with termios.h */ #else # ifndef TIOCEXCL # include /* needed for TIOCEXCL */ # endif #endif #ifdef __hpux # include #endif #ifdef ISC # include # include # include #endif #include "config.h" #ifdef HAVE_STROPTS_H #include /* for I_POP */ #endif #include "screen.h" #include "extern.h" #if !defined(TIOCCONS) && defined(sun) && defined(SVR4) # include #endif extern struct display *display, *displays; extern int iflag; #if (!defined(TIOCCONS) && defined(SRIOCSREDIR)) || defined(linux) extern struct win *console_window; static void consredir_readev_fn __P((struct event *, char *)); #endif int separate_sids = 1; static void DoSendBreak __P((int, int, int)); static sigret_t SigAlrmDummy __P(SIGPROTOARG); /* Frank Schulz (fschulz@pyramid.com): * I have no idea why VSTART is not defined and my fix is probably not * the cleanest, but it works. */ #if !defined(VSTART) && defined(_VSTART) #define VSTART _VSTART #endif #if !defined(VSTOP) && defined(_VSTOP) #define VSTOP _VSTOP #endif #ifndef O_NOCTTY # define O_NOCTTY 0 #endif #ifndef TTYVMIN # define TTYVMIN 1 #endif #ifndef TTYVTIME #define TTYVTIME 0 #endif static sigret_t SigAlrmDummy SIGDEFARG { debug("SigAlrmDummy()\n"); SIGRETURN; } /* * Carefully open a charcter device. Not used to open display ttys. * The second parameter is parsed for a few stty style options. */ int OpenTTY(line, opt) char *line, *opt; { int f; struct mode Mode; sigret_t (*sigalrm)__P(SIGPROTOARG); sigalrm = signal(SIGALRM, SigAlrmDummy); alarm(2); /* this open only succeeds, if real uid is allowed */ if ((f = secopen(line, O_RDWR | O_NONBLOCK | O_NOCTTY, 0)) == -1) { if (errno == EINTR) Msg(0, "Cannot open line '%s' for R/W: open() blocked, aborted.", line); else Msg(errno, "Cannot open line '%s' for R/W", line); alarm(0); signal(SIGALRM, sigalrm); return -1; } if (!isatty(f)) { Msg(0, "'%s' is not a tty", line); alarm(0); signal(SIGALRM, sigalrm); close(f); return -1; } #if defined(I_POP) && defined(POP_TTYMODULES) debug("OpenTTY I_POP\n"); while (ioctl(f, I_POP, (char *)0) >= 0) ; #endif /* * We come here exclusively. This is to stop all kermit and cu type things * accessing the same tty line. * Perhaps we should better create a lock in some /usr/spool/locks directory? */ #ifdef TIOCEXCL errno = 0; if (ioctl(f, TIOCEXCL, (char *) 0) < 0) Msg(errno, "%s: ioctl TIOCEXCL failed", line); debug3("%d %d %d\n", getuid(), geteuid(), getpid()); debug2("%s TIOCEXCL errno %d\n", line, errno); #endif /* TIOCEXCL */ /* * We create a sane tty mode. We do not copy things from the display tty */ #if WE_REALLY_WANT_TO_COPY_THE_TTY_MODE if (display) { debug1("OpenTTY: using mode of display for %s\n", line); Mode = D_NewMode; } else #endif InitTTY(&Mode, W_TYPE_PLAIN); SttyMode(&Mode, opt); #ifdef DEBUG DebugTTY(&Mode); #endif SetTTY(f, &Mode); #if defined(linux) && defined(TIOCMSET) { int mcs = 0; ioctl(f, TIOCMGET, &mcs); mcs |= TIOCM_RTS; ioctl(f, TIOCMSET, &mcs); } #endif brktty(f); alarm(0); signal(SIGALRM, sigalrm); debug2("'%s' CONNECT fd=%d.\n", line, f); return f; } /* * Tty mode handling */ void InitTTY(m, ttyflag) struct mode *m; int ttyflag; { bzero((char *)m, sizeof(*m)); #ifdef POSIX /* struct termios tio * defaults, as seen on SunOS 4.1.3 */ debug1("InitTTY: POSIX: termios defaults based on SunOS 4.1.3, but better (%d)\n", ttyflag); IF{BRKINT} m->tio.c_iflag |= BRKINT; IF{IGNPAR} m->tio.c_iflag |= IGNPAR; /* IF{ISTRIP} m->tio.c_iflag |= ISTRIP; may be needed, let's try. jw. */ IF{IXON} m->tio.c_iflag |= IXON; /* IF{IMAXBEL} m->tio.c_iflag |= IMAXBEL; sorry, this one is ridiculus. jw */ if (!ttyflag) /* may not even be good for ptys.. */ { IF{ICRNL} m->tio.c_iflag |= ICRNL; IF{ONLCR} m->tio.c_oflag |= ONLCR; IF{TAB3} m->tio.c_oflag |= TAB3; IF{OXTABS} m->tio.c_oflag |= OXTABS; /* IF{PARENB} m->tio.c_cflag |= PARENB; nah! jw. */ IF{OPOST} m->tio.c_oflag |= OPOST; } /* * Or-ing the speed into c_cflags is dangerous. * It breaks on bsdi, where c_ispeed and c_ospeed are extra longs. * * IF{B9600} m->tio.c_cflag |= B9600; * IF{IBSHIFT) && defined(B9600} m->tio.c_cflag |= B9600 << IBSHIFT; * * We hope that we have the posix calls to do it right: * If these are not available you might try the above. */ IF{B9600} cfsetospeed(&m->tio, B9600); IF{B9600} cfsetispeed(&m->tio, B9600); IF{CS8} m->tio.c_cflag |= CS8; IF{CREAD} m->tio.c_cflag |= CREAD; IF{CLOCAL} m->tio.c_cflag |= CLOCAL; IF{ECHOCTL} m->tio.c_lflag |= ECHOCTL; IF{ECHOKE} m->tio.c_lflag |= ECHOKE; if (!ttyflag) { IF{ISIG} m->tio.c_lflag |= ISIG; IF{ICANON} m->tio.c_lflag |= ICANON; IF{ECHO} m->tio.c_lflag |= ECHO; } IF{ECHOE} m->tio.c_lflag |= ECHOE; IF{ECHOK} m->tio.c_lflag |= ECHOK; IF{IEXTEN} m->tio.c_lflag |= IEXTEN; XIF{VINTR} m->tio.c_cc[VINTR] = Ctrl('C'); XIF{VQUIT} m->tio.c_cc[VQUIT] = Ctrl('\\'); XIF{VERASE} m->tio.c_cc[VERASE] = 0x7f; /* DEL */ XIF{VKILL} m->tio.c_cc[VKILL] = Ctrl('H'); XIF{VEOF} m->tio.c_cc[VEOF] = Ctrl('D'); XIF{VEOL} m->tio.c_cc[VEOL] = 0000; XIF{VEOL2} m->tio.c_cc[VEOL2] = 0000; XIF{VSWTCH} m->tio.c_cc[VSWTCH] = 0000; XIF{VSTART} m->tio.c_cc[VSTART] = Ctrl('Q'); XIF{VSTOP} m->tio.c_cc[VSTOP] = Ctrl('S'); XIF{VSUSP} m->tio.c_cc[VSUSP] = Ctrl('Z'); XIF{VDSUSP} m->tio.c_cc[VDSUSP] = Ctrl('Y'); XIF{VREPRINT} m->tio.c_cc[VREPRINT] = Ctrl('R'); XIF{VDISCARD} m->tio.c_cc[VDISCARD] = Ctrl('O'); XIF{VWERASE} m->tio.c_cc[VWERASE] = Ctrl('W'); XIF{VLNEXT} m->tio.c_cc[VLNEXT] = Ctrl('V'); XIF{VSTATUS} m->tio.c_cc[VSTATUS] = Ctrl('T'); if (ttyflag) { m->tio.c_cc[VMIN] = TTYVMIN; m->tio.c_cc[VTIME] = TTYVTIME; } # ifdef HPUX_LTCHARS_HACK m->m_ltchars.t_suspc = Ctrl('Z'); m->m_ltchars.t_dsuspc = Ctrl('Y'); m->m_ltchars.t_rprntc = Ctrl('R'); m->m_ltchars.t_flushc = Ctrl('O'); m->m_ltchars.t_werasc = Ctrl('W'); m->m_ltchars.t_lnextc = Ctrl('V'); # endif /* HPUX_LTCHARS_HACK */ #else /* POSIX */ # ifdef TERMIO debug1("InitTTY: nonPOSIX, struct termio a la Motorola SYSV68 (%d)\n", ttyflag); /* struct termio tio * defaults, as seen on Mototola SYSV68: * input: 7bit, CR->NL, ^S/^Q flow control * output: POSTprocessing: NL->NL-CR, Tabs to spaces * control: 9600baud, 8bit CSIZE, enable input * local: enable signals, erase/kill processing, echo on. */ IF{ISTRIP} m->tio.c_iflag |= ISTRIP; IF{IXON} m->tio.c_iflag |= IXON; if (!ttyflag) /* may not even be good for ptys.. */ { IF{OPOST} m->tio.c_oflag |= OPOST; IF{ICRNL} m->tio.c_iflag |= ICRNL; IF{ONLCR} m->tio.c_oflag |= ONLCR; IF{TAB3} m->tio.c_oflag |= TAB3; } #ifdef __bsdi__ )-: cannot handle BSDI without POSIX #else IF{B9600} m->tio.c_cflag = B9600; #endif IF{CS8} m->tio.c_cflag |= CS8; IF{CREAD} m->tio.c_cflag |= CREAD; if (!ttyflag) { IF{ISIG} m->tio.c_lflag |= ISIG; IF{ICANON} m->tio.c_lflag |= ICANON; IF{ECHO} m->tio.c_lflag |= ECHO; } IF{ECHOE} m->tio.c_lflag |= ECHOE; IF{ECHOK} m->tio.c_lflag |= ECHOK; XIF{VINTR} m->tio.c_cc[VINTR] = Ctrl('C'); XIF{VQUIT} m->tio.c_cc[VQUIT] = Ctrl('\\'); XIF{VERASE} m->tio.c_cc[VERASE] = 0177; /* DEL */ XIF{VKILL} m->tio.c_cc[VKILL] = Ctrl('H'); XIF{VEOF} m->tio.c_cc[VEOF] = Ctrl('D'); XIF{VEOL} m->tio.c_cc[VEOL] = 0377; XIF{VEOL2} m->tio.c_cc[VEOL2] = 0377; XIF{VSWTCH} m->tio.c_cc[VSWTCH] = 0000; if (ttyflag) { m->tio.c_cc[VMIN] = TTYVMIN; m->tio.c_cc[VTIME] = TTYVTIME; } # else /* TERMIO */ debug1("InitTTY: BSD: defaults a la SunOS 4.1.3 (%d)\n", ttyflag); m->m_ttyb.sg_ispeed = B9600; m->m_ttyb.sg_ospeed = B9600; m->m_ttyb.sg_erase = 0177; /*DEL */ m->m_ttyb.sg_kill = Ctrl('H'); if (!ttyflag) m->m_ttyb.sg_flags = CRMOD | ECHO IF{ANYP} | ANYP ; else m->m_ttyb.sg_flags = CBREAK IF{ANYP} | ANYP ; m->m_tchars.t_intrc = Ctrl('C'); m->m_tchars.t_quitc = Ctrl('\\'); m->m_tchars.t_startc = Ctrl('Q'); m->m_tchars.t_stopc = Ctrl('S'); m->m_tchars.t_eofc = Ctrl('D'); m->m_tchars.t_brkc = -1; m->m_ltchars.t_suspc = Ctrl('Z'); m->m_ltchars.t_dsuspc = Ctrl('Y'); m->m_ltchars.t_rprntc = Ctrl('R'); m->m_ltchars.t_flushc = Ctrl('O'); m->m_ltchars.t_werasc = Ctrl('W'); m->m_ltchars.t_lnextc = Ctrl('V'); IF{NTTYDISC} m->m_ldisc = NTTYDISC; m->m_lmode = 0 IF{LDECCTQ} | LDECCTQ IF{LCTLECH} | LCTLECH IF{LPASS8} | LPASS8 IF{LCRTKIL} | LCRTKIL IF{LCRTERA} | LCRTERA IF{LCRTBS} | LCRTBS ; # endif /* TERMIO */ #endif /* POSIX */ #if defined(ENCODINGS) && defined(TIOCKSET) m->m_jtchars.t_ascii = 'J'; m->m_jtchars.t_kanji = 'B'; m->m_knjmode = KM_ASCII | KM_SYSSJIS; #endif } void SetTTY(fd, mp) int fd; struct mode *mp; { errno = 0; #ifdef POSIX tcsetattr(fd, TCSADRAIN, &mp->tio); # ifdef HPUX_LTCHARS_HACK ioctl(fd, TIOCSLTC, (char *)&mp->m_ltchars); # endif #else # ifdef TERMIO ioctl(fd, TCSETAW, (char *)&mp->tio); # ifdef CYTERMIO if (mp->tio.c_line == 3) { ioctl(fd, LDSETMAPKEY, (char *)&mp->m_mapkey); ioctl(fd, LDSETMAPSCREEN, (char *)&mp->m_mapscreen); ioctl(fd, LDSETBACKSPACE, (char *)&mp->m_backspace); } # endif # else /* ioctl(fd, TIOCSETP, (char *)&mp->m_ttyb); */ ioctl(fd, TIOCSETC, (char *)&mp->m_tchars); ioctl(fd, TIOCLSET, (char *)&mp->m_lmode); ioctl(fd, TIOCSETD, (char *)&mp->m_ldisc); ioctl(fd, TIOCSETP, (char *)&mp->m_ttyb); ioctl(fd, TIOCSLTC, (char *)&mp->m_ltchars); /* moved here for apollo. jw */ # endif #endif #if defined(ENCODINGS) && defined(TIOCKSET) ioctl(fd, TIOCKSETC, &mp->m_jtchars); ioctl(fd, TIOCKSET, &mp->m_knjmode); #endif if (errno) Msg(errno, "SetTTY (fd %d): ioctl failed", fd); } void GetTTY(fd, mp) int fd; struct mode *mp; { errno = 0; #ifdef POSIX tcgetattr(fd, &mp->tio); # ifdef HPUX_LTCHARS_HACK ioctl(fd, TIOCGLTC, (char *)&mp->m_ltchars); # endif #else # ifdef TERMIO ioctl(fd, TCGETA, (char *)&mp->tio); # ifdef CYTERMIO if (mp->tio.c_line == 3) { ioctl(fd, LDGETMAPKEY, (char *)&mp->m_mapkey); ioctl(fd, LDGETMAPSCREEN, (char *)&mp->m_mapscreen); ioctl(fd, LDGETBACKSPACE, (char *)&mp->m_backspace); } else { mp->m_mapkey = NOMAPKEY; mp->m_mapscreen = NOMAPSCREEN; mp->m_backspace = '\b'; } # endif # else ioctl(fd, TIOCGETP, (char *)&mp->m_ttyb); ioctl(fd, TIOCGETC, (char *)&mp->m_tchars); ioctl(fd, TIOCGLTC, (char *)&mp->m_ltchars); ioctl(fd, TIOCLGET, (char *)&mp->m_lmode); ioctl(fd, TIOCGETD, (char *)&mp->m_ldisc); # endif #endif #if defined(ENCODINGS) && defined(TIOCKSET) ioctl(fd, TIOCKGETC, &mp->m_jtchars); ioctl(fd, TIOCKGET, &mp->m_knjmode); #endif if (errno) Msg(errno, "GetTTY (fd %d): ioctl failed", fd); } /* * needs interrupt = iflag and flow = d->d_flow */ void SetMode(op, np, flow, interrupt) struct mode *op, *np; int flow, interrupt; { *np = *op; ASSERT(display); #if defined(TERMIO) || defined(POSIX) # ifdef CYTERMIO np->m_mapkey = NOMAPKEY; np->m_mapscreen = NOMAPSCREEN; np->tio.c_line = 0; # endif IF{ICRNL} np->tio.c_iflag &= ~ICRNL; IF{ISTRIP} np->tio.c_iflag &= ~ISTRIP; IF{ONLCR} np->tio.c_oflag &= ~ONLCR; np->tio.c_lflag &= ~(ICANON | ECHO); /* * From Andrew Myers (andru@tonic.lcs.mit.edu) * to avoid ^V^V-Problem on OSF1 */ IF{IEXTEN} np->tio.c_lflag &= ~IEXTEN; /* * Unfortunately, the master process never will get SIGINT if the real * terminal is different from the one on which it was originaly started * (process group membership has not been restored or the new tty could not * be made controlling again). In my solution, it is the attacher who * receives SIGINT (because it is always correctly associated with the real * tty) and forwards it to the master [kill(MasterPid, SIGINT)]. * Marc Boucher (marc@CAM.ORG) */ if (interrupt) np->tio.c_lflag |= ISIG; else np->tio.c_lflag &= ~ISIG; /* * careful, careful catche monkey.. * never set VMIN and VTIME to zero, if you want blocking io. * * We may want to do a VMIN > 0, VTIME > 0 read on the ptys too, to * reduce interrupt frequency. But then we would not know how to * handle read returning 0. jw. */ np->tio.c_cc[VMIN] = 1; np->tio.c_cc[VTIME] = 0; if (!interrupt || !flow) np->tio.c_cc[VINTR] = VDISABLE; np->tio.c_cc[VQUIT] = VDISABLE; if (flow == 0) { XIF{VSTART} np->tio.c_cc[VSTART] = VDISABLE; XIF{VSTOP} np->tio.c_cc[VSTOP] = VDISABLE; np->tio.c_iflag &= ~IXON; } XIF{VDISCARD} np->tio.c_cc[VDISCARD] = VDISABLE; XIF{VLNEXT} np->tio.c_cc[VLNEXT] = VDISABLE; XIF{VSTATUS} np->tio.c_cc[VSTATUS] = VDISABLE; XIF{VSUSP} np->tio.c_cc[VSUSP] = VDISABLE; /* Set VERASE to DEL, rather than VDISABLE, to avoid libvte "autodetect" issues. */ XIF{VERASE} np->tio.c_cc[VERASE] = 0x7f; XIF{VKILL} np->tio.c_cc[VKILL] = VDISABLE; # ifdef HPUX_LTCHARS_HACK np->m_ltchars.t_suspc = VDISABLE; np->m_ltchars.t_dsuspc = VDISABLE; np->m_ltchars.t_rprntc = VDISABLE; np->m_ltchars.t_flushc = VDISABLE; np->m_ltchars.t_werasc = VDISABLE; np->m_ltchars.t_lnextc = VDISABLE; # else /* HPUX_LTCHARS_HACK */ XIF{VDSUSP} np->tio.c_cc[VDSUSP] = VDISABLE; XIF{VREPRINT} np->tio.c_cc[VREPRINT] = VDISABLE; XIF{VWERASE} np->tio.c_cc[VWERASE] = VDISABLE; # endif /* HPUX_LTCHARS_HACK */ #else /* TERMIO || POSIX */ if (!interrupt || !flow) np->m_tchars.t_intrc = -1; np->m_ttyb.sg_flags &= ~(CRMOD | ECHO); np->m_ttyb.sg_flags |= CBREAK; # if defined(CYRILL) && defined(CSTYLE) && defined(CS_8BITS) np->m_ttyb.sg_flags &= ~CSTYLE; np->m_ttyb.sg_flags |= CS_8BITS; # endif np->m_tchars.t_quitc = -1; if (flow == 0) { np->m_tchars.t_startc = -1; np->m_tchars.t_stopc = -1; } np->m_ltchars.t_suspc = -1; np->m_ltchars.t_dsuspc = -1; np->m_ltchars.t_flushc = -1; np->m_ltchars.t_lnextc = -1; #endif /* defined(TERMIO) || defined(POSIX) */ } /* operates on display */ void SetFlow(on) int on; { ASSERT(display); if (D_flow == on) return; #if defined(TERMIO) || defined(POSIX) if (on) { D_NewMode.tio.c_cc[VINTR] = iflag ? D_OldMode.tio.c_cc[VINTR] : VDISABLE; XIF{VSTART} D_NewMode.tio.c_cc[VSTART] = D_OldMode.tio.c_cc[VSTART]; XIF{VSTOP} D_NewMode.tio.c_cc[VSTOP] = D_OldMode.tio.c_cc[VSTOP]; D_NewMode.tio.c_iflag |= D_OldMode.tio.c_iflag & IXON; } else { D_NewMode.tio.c_cc[VINTR] = VDISABLE; XIF{VSTART} D_NewMode.tio.c_cc[VSTART] = VDISABLE; XIF{VSTOP} D_NewMode.tio.c_cc[VSTOP] = VDISABLE; D_NewMode.tio.c_iflag &= ~IXON; } # ifdef POSIX # ifdef TCOON if (!on) tcflow(D_userfd, TCOON); # endif if (tcsetattr(D_userfd, TCSANOW, &D_NewMode.tio)) # else if (ioctl(D_userfd, TCSETAW, (char *)&D_NewMode.tio) != 0) # endif debug1("SetFlow: ioctl errno %d\n", errno); #else /* POSIX || TERMIO */ if (on) { D_NewMode.m_tchars.t_intrc = iflag ? D_OldMode.m_tchars.t_intrc : -1; D_NewMode.m_tchars.t_startc = D_OldMode.m_tchars.t_startc; D_NewMode.m_tchars.t_stopc = D_OldMode.m_tchars.t_stopc; } else { D_NewMode.m_tchars.t_intrc = -1; D_NewMode.m_tchars.t_startc = -1; D_NewMode.m_tchars.t_stopc = -1; } if (ioctl(D_userfd, TIOCSETC, (char *)&D_NewMode.m_tchars) != 0) debug1("SetFlow: ioctl errno %d\n", errno); #endif /* POSIX || TERMIO */ D_flow = on; } /* parse commands from opt and modify m */ int SttyMode(m, opt) struct mode *m; char *opt; { static const char sep[] = " \t:;,"; if (!opt) return 0; while (*opt) { while (index(sep, *opt)) opt++; if (*opt >= '0' && *opt <= '9') { if (SetBaud(m, atoi(opt), atoi(opt))) return -1; } else if (!strncmp("cs7", opt, 3)) { #if defined(POSIX) || defined(TERMIO) m->tio.c_cflag &= ~CSIZE; m->tio.c_cflag |= CS7; #else m->m_lmode &= ~LPASS8; #endif } else if (!strncmp("cs8", opt, 3)) { #if defined(POSIX) || defined(TERMIO) m->tio.c_cflag &= ~CSIZE; m->tio.c_cflag |= CS8; #else m->m_lmode |= LPASS8; #endif } else if (!strncmp("istrip", opt, 6)) { #if defined(POSIX) || defined(TERMIO) m->tio.c_iflag |= ISTRIP; #else m->m_lmode &= ~LPASS8; #endif } else if (!strncmp("-istrip", opt, 7)) { #if defined(POSIX) || defined(TERMIO) m->tio.c_iflag &= ~ISTRIP; #else m->m_lmode |= LPASS8; #endif } else if (!strncmp("ixon", opt, 4)) { #if defined(POSIX) || defined(TERMIO) m->tio.c_iflag |= IXON; #else debug("SttyMode: no ixon in old bsd land.\n"); #endif } else if (!strncmp("-ixon", opt, 5)) { #if defined(POSIX) || defined(TERMIO) m->tio.c_iflag &= ~IXON; #else debug("SttyMode: no -ixon in old bsd land.\n"); #endif } else if (!strncmp("ixoff", opt, 5)) { #if defined(POSIX) || defined(TERMIO) m->tio.c_iflag |= IXOFF; #else m->m_ttyb.sg_flags |= TANDEM; #endif } else if (!strncmp("-ixoff", opt, 6)) { #if defined(POSIX) || defined(TERMIO) m->tio.c_iflag &= ~IXOFF; #else m->m_ttyb.sg_flags &= ~TANDEM; #endif } else if (!strncmp("crtscts", opt, 7)) { #if (defined(POSIX) || defined(TERMIO)) && defined(CRTSCTS) m->tio.c_cflag |= CRTSCTS; #endif } else if (!strncmp("-crtscts", opt, 8)) { #if (defined(POSIX) || defined(TERMIO)) && defined(CRTSCTS) m->tio.c_cflag &= ~CRTSCTS; #endif } else return -1; while (*opt && !index(sep, *opt)) opt++; } return 0; } /* * Job control handling * * Somehow the ultrix session handling is broken, so use * the bsdish variant. */ /*ARGSUSED*/ void brktty(fd) int fd; { #if defined(POSIX) && !defined(ultrix) if (separate_sids) setsid(); /* will break terminal affiliation */ /* GNU added for Hurd systems 2001-10-10 */ # if defined(BSD) && defined(TIOCSCTTY) && !defined(__GNU__) ioctl(fd, TIOCSCTTY, (char *)0); # endif /* BSD && TIOCSCTTY */ #else /* POSIX */ # ifdef SYSV if (separate_sids) setpgrp(); /* will break terminal affiliation */ # else /* SYSV */ # ifdef BSDJOBS int devtty; if ((devtty = open("/dev/tty", O_RDWR | O_NONBLOCK)) >= 0) { if (ioctl(devtty, TIOCNOTTY, (char *)0)) debug2("brktty: ioctl(devtty=%d, TIOCNOTTY, 0) = %d\n", devtty, errno); close(devtty); } # endif /* BSDJOBS */ # endif /* SYSV */ #endif /* POSIX */ } int fgtty(fd) int fd; { #ifdef BSDJOBS int mypid; mypid = getpid(); /* The next lines should be obsolete. Can anybody check if they * are really needed on the BSD platforms? * * this is to avoid the message: * fgtty: Not a typewriter (25) */ # if defined(__osf__) || (BSD >= 199103) || defined(ISC) if (separate_sids) setsid(); /* should be already done */ # ifdef TIOCSCTTY ioctl(fd, TIOCSCTTY, (char *)0); # endif # endif # ifdef POSIX if (separate_sids) if (tcsetpgrp(fd, mypid)) { debug1("fgtty: tcsetpgrp: %d\n", errno); return -1; } # else /* POSIX */ if (ioctl(fd, TIOCSPGRP, (char *)&mypid) != 0) debug1("fgtty: TIOSETPGRP: %d\n", errno); # ifndef SYSV /* Already done in brktty():setpgrp() */ if (separate_sids) if (setpgrp(fd, mypid)) debug1("fgtty: setpgrp: %d\n", errno); # endif # endif /* POSIX */ #endif /* BSDJOBS */ return 0; } /* * The alm boards on our sparc center 1000 have a lousy driver. * We cannot generate long breaks unless we use the most ugly form * of ioctls. jw. */ #ifdef POSIX int breaktype = 2; #else /* POSIX */ # ifdef TCSBRK int breaktype = 1; # else int breaktype = 0; # endif #endif /* POSIX */ #if defined(sun) && !defined(SVR4) # define HAVE_SUPER_TCSENDBREAK #endif /* * type: * 0: TIOCSBRK / TIOCCBRK * 1: TCSBRK * 2: tcsendbreak() * n: approximate duration in 1/4 seconds. */ static void DoSendBreak(fd, n, type) int fd, n, type; { switch (type) { case 2: /* tcsendbreak() =============================== */ #ifdef POSIX # ifdef HAVE_SUPER_TCSENDBREAK /* There is one rare case that I have tested, where tcsendbreak works * really great: this was an alm driver that came with SunOS 4.1.3 * If you have this one, define the above symbol. * here we can use the second parameter to specify the duration. */ debug2("tcsendbreak(fd=%d, %d)\n", fd, n); if (tcsendbreak(fd, n) < 0) Msg(errno, "cannot send BREAK (tcsendbreak)"); # else /* * here we hope, that multiple calls to tcsendbreak() can * be concatenated to form a long break, as we do not know * what exact interpretation the second parameter has: * * - sunos 4: duration in quarter seconds * - sunos 5: 0 a short break, nonzero a tcdrain() * - hpux, irix: ignored * - mot88: duration in milliseconds * - aix: duration in milliseconds, but 0 is 25 milliseconds. */ debug2("%d * tcsendbreak(fd=%d, 0)\n", n, fd); { int i; if (!n) n++; for (i = 0; i < n; i++) if (tcsendbreak(fd, 0) < 0) { Msg(errno, "cannot send BREAK (tcsendbreak SVR4)"); return; } } # endif #else /* POSIX */ Msg(0, "tcsendbreak() not available, change breaktype"); #endif /* POSIX */ break; case 1: /* TCSBRK ======================================= */ #ifdef TCSBRK if (!n) n++; /* * Here too, we assume that short breaks can be concatenated to * perform long breaks. But for SOLARIS, this is not true, of course. */ debug2("%d * TCSBRK fd=%d\n", n, fd); { int i; for (i = 0; i < n; i++) if (ioctl(fd, TCSBRK, (char *)0) < 0) { Msg(errno, "Cannot send BREAK (TCSBRK)"); return; } } #else /* TCSBRK */ Msg(0, "TCSBRK not available, change breaktype"); #endif /* TCSBRK */ break; case 0: /* TIOCSBRK / TIOCCBRK ========================== */ #if defined(TIOCSBRK) && defined(TIOCCBRK) /* * This is very rude. Screen actively celebrates the break. * But it may be the only save way to issue long breaks. */ debug("TIOCSBRK TIOCCBRK\n"); if (ioctl(fd, TIOCSBRK, (char *)0) < 0) { Msg(errno, "Can't send BREAK (TIOCSBRK)"); return; } sleep1000(n ? n * 250 : 250); if (ioctl(fd, TIOCCBRK, (char *)0) < 0) { Msg(errno, "BREAK stuck!!! -- HELP! (TIOCCBRK)"); return; } #else /* TIOCSBRK && TIOCCBRK */ Msg(0, "TIOCSBRK/CBRK not available, change breaktype"); #endif /* TIOCSBRK && TIOCCBRK */ break; default: /* unknown ========================== */ Msg(0, "Internal SendBreak error: method %d unknown", type); } } /* * Send a break for n * 0.25 seconds. Tty must be PLAIN. * The longest possible break allowed here is 15 seconds. */ void SendBreak(wp, n, closeopen) struct win *wp; int n, closeopen; { sigret_t (*sigalrm)__P(SIGPROTOARG); #ifdef BUILTIN_TELNET if (wp->w_type == W_TYPE_TELNET) { TelBreak(wp); return; } #endif if (wp->w_type != W_TYPE_PLAIN) return; debug3("break(%d, %d) fd %d\n", n, closeopen, wp->w_ptyfd); #ifdef POSIX (void) tcflush(wp->w_ptyfd, TCIOFLUSH); #else # ifdef TIOCFLUSH (void) ioctl(wp->w_ptyfd, TIOCFLUSH, (char *)0); # endif /* TIOCFLUSH */ #endif /* POSIX */ if (closeopen) { close(wp->w_ptyfd); sleep1000(n ? n * 250 : 250); if ((wp->w_ptyfd = OpenTTY(wp->w_tty, wp->w_cmdargs[1])) < 1) { Msg(0, "Ouch, cannot reopen line %s, please try harder", wp->w_tty); return; } (void) fcntl(wp->w_ptyfd, F_SETFL, FNBLOCK); } else { sigalrm = signal(SIGALRM, SigAlrmDummy); alarm(15); DoSendBreak(wp->w_ptyfd, n, breaktype); alarm(0); signal(SIGALRM, sigalrm); } debug(" broken.\n"); } /* * Console grabbing */ #if (!defined(TIOCCONS) && defined(SRIOCSREDIR)) || defined(linux) static struct event consredir_ev; static int consredirfd[2] = {-1, -1}; static void consredir_readev_fn(ev, data) struct event *ev; char *data; { char *p, *n, buf[256]; int l; if (!console_window || (l = read(consredirfd[0], buf, sizeof(buf))) <= 0) { close(consredirfd[0]); close(consredirfd[1]); consredirfd[0] = consredirfd[1] = -1; evdeq(ev); return; } for (p = n = buf; l > 0; n++, l--) if (*n == '\n') { if (n > p) WriteString(console_window, p, n - p); WriteString(console_window, "\r\n", 2); p = n + 1; } if (n > p) WriteString(console_window, p, n - p); } #endif /*ARGSUSED*/ int TtyGrabConsole(fd, on, rc_name) int fd, on; char *rc_name; { #if defined(TIOCCONS) && !defined(linux) struct display *d; int ret = 0; int sfd = -1; if (on < 0) return 0; /* pty close will ungrab */ if (on) { if (displays == 0) { Msg(0, "I need a display"); return -1; } for (d = displays; d; d = d->d_next) if (strcmp(d->d_usertty, "/dev/console") == 0) break; if (d) { Msg(0, "too dangerous - screen is running on /dev/console"); return -1; } } if (!on) { char *slave; if ((fd = OpenPTY(&slave)) < 0) { Msg(errno, "%s: could not open detach pty master", rc_name); return -1; } if ((sfd = open(slave, O_RDWR | O_NOCTTY)) < 0) { Msg(errno, "%s: could not open detach pty slave", rc_name); close(fd); return -1; } } if (UserContext() == 1) UserReturn(ioctl(fd, TIOCCONS, (char *)&on)); ret = UserStatus(); if (ret) Msg(errno, "%s: ioctl TIOCCONS failed", rc_name); if (!on) { close(sfd); close(fd); } return ret; #else # if defined(SRIOCSREDIR) || defined(linux) struct display *d; # ifdef SRIOCSREDIR int cfd; # else struct mode new1, new2; char *slave; # endif if (on > 0) { if (displays == 0) { Msg(0, "I need a display"); return -1; } for (d = displays; d; d = d->d_next) if (strcmp(d->d_usertty, "/dev/console") == 0) break; if (d) { Msg(0, "too dangerous - screen is running on /dev/console"); return -1; } } if (consredirfd[0] >= 0) { evdeq(&consredir_ev); close(consredirfd[0]); close(consredirfd[1]); consredirfd[0] = consredirfd[1] = -1; } if (on <= 0) return 0; # ifdef SRIOCSREDIR if ((cfd = secopen("/dev/console", O_RDWR|O_NOCTTY, 0)) == -1) { Msg(errno, "/dev/console"); return -1; } if (pipe(consredirfd)) { Msg(errno, "pipe"); close(cfd); consredirfd[0] = consredirfd[1] = -1; return -1; } if (ioctl(cfd, SRIOCSREDIR, consredirfd[1])) { Msg(errno, "SRIOCSREDIR ioctl"); close(cfd); close(consredirfd[0]); close(consredirfd[1]); consredirfd[0] = consredirfd[1] = -1; return -1; } close(cfd); # else /* special linux workaround for a too restrictive kernel */ if ((consredirfd[0] = OpenPTY(&slave)) < 0) { Msg(errno, "%s: could not open detach pty master", rc_name); return -1; } if ((consredirfd[1] = open(slave, O_RDWR | O_NOCTTY)) < 0) { Msg(errno, "%s: could not open detach pty slave", rc_name); close(consredirfd[0]); return -1; } InitTTY(&new1, 0); SetMode(&new1, &new2, 0, 0); SetTTY(consredirfd[1], &new2); if (UserContext() == 1) UserReturn(ioctl(consredirfd[1], TIOCCONS, (char *)&on)); if (UserStatus()) { Msg(errno, "%s: ioctl TIOCCONS failed", rc_name); close(consredirfd[0]); close(consredirfd[1]); return -1; } # endif consredir_ev.fd = consredirfd[0]; consredir_ev.type = EV_READ; consredir_ev.handler = consredir_readev_fn; evenq(&consredir_ev); return 0; # else if (on > 0) Msg(0, "%s: don't know how to grab the console", rc_name); return -1; # endif #endif } /* * Read modem control lines of a physical tty and write them to buf * in a readable format. * Will not write more than 256 characters to buf. * Returns buf; */ char * TtyGetModemStatus(fd, buf) int fd; char *buf; { char *p = buf; #ifdef TIOCGSOFTCAR unsigned int softcar; #endif #if defined(TIOCMGET) || defined(TIOCMODG) unsigned int mflags; #else # ifdef MCGETA /* this is yet another interface, found on hpux. grrr */ mflag mflags; IF{MDTR}# define TIOCM_DTR MDTR IF{MRTS}# define TIOCM_RTS MRTS IF{MDSR}# define TIOCM_DSR MDSR IF{MDCD}# define TIOCM_CAR MDCD IF{MRI}# define TIOCM_RNG MRI IF{MCTS}# define TIOCM_CTS MCTS # endif #endif #if defined(CLOCAL) || defined(CRTSCTS) struct mode mtio; /* screen.h */ #endif #if defined(CRTSCTS) || defined(TIOCM_CTS) int rtscts; #endif int clocal; #if defined(CLOCAL) || defined(CRTSCTS) GetTTY(fd, &mtio); #endif clocal = 0; #ifdef CLOCAL if (mtio.tio.c_cflag & CLOCAL) { clocal = 1; *p++ = '{'; } #endif #ifdef TIOCM_CTS # ifdef CRTSCTS if (!(mtio.tio.c_cflag & CRTSCTS)) rtscts = 0; else # endif /* CRTSCTS */ rtscts = 1; #endif /* TIOCM_CTS */ #ifdef TIOCGSOFTCAR if (ioctl(fd, TIOCGSOFTCAR, (char *)&softcar) < 0) softcar = 0; #endif #if defined(TIOCMGET) || defined(TIOCMODG) || defined(MCGETA) # ifdef TIOCMGET if (ioctl(fd, TIOCMGET, (char *)&mflags) < 0) # else # ifdef TIOCMODG if (ioctl(fd, TIOCMODG, (char *)&mflags) < 0) # else if (ioctl(fd, MCGETA, &mflags) < 0) # endif # endif { #ifdef TIOCGSOFTCAR sprintf(p, "NO-TTY? %s", softcar ? "(CD)" : "CD"); #else sprintf(p, "NO-TTY?"); #endif p += strlen(p); } else { char *s; # ifdef FANCY_MODEM # ifdef TIOCM_LE if (!(mflags & TIOCM_LE)) for (s = "!LE "; *s; *p++ = *s++); # endif # endif /* FANCY_MODEM */ # ifdef TIOCM_RTS s = "!RTS "; if (mflags & TIOCM_RTS) s++; while (*s) *p++ = *s++; # endif # ifdef TIOCM_CTS s = "!CTS "; if (!rtscts) { *p++ = '('; s = "!CTS) "; } if (mflags & TIOCM_CTS) s++; while (*s) *p++ = *s++; # endif # ifdef TIOCM_DTR s = "!DTR "; if (mflags & TIOCM_DTR) s++; while (*s) *p++ = *s++; # endif # ifdef TIOCM_DSR s = "!DSR "; if (mflags & TIOCM_DSR) s++; while (*s) *p++ = *s++; # endif # if defined(TIOCM_CD) || defined(TIOCM_CAR) s = "!CD "; # ifdef TIOCGSOFTCAR if (softcar) { *p++ = '('; s = "!CD) "; } # endif # ifdef TIOCM_CD if (mflags & TIOCM_CD) s++; # else if (mflags & TIOCM_CAR) s++; # endif while (*s) *p++ = *s++; # endif # if defined(TIOCM_RI) || defined(TIOCM_RNG) # ifdef TIOCM_RI if (mflags & TIOCM_RI) # else if (mflags & TIOCM_RNG) # endif for (s = "RI "; *s; *p++ = *s++); # endif # ifdef FANCY_MODEM # ifdef TIOCM_ST s = "!ST "; if (mflags & TIOCM_ST) s++; while (*s) *p++ = *s++; # endif # ifdef TIOCM_SR s = "!SR "; if (mflags & TIOCM_SR) s++; while (*s) *p++ = *s++; # endif # endif /* FANCY_MODEM */ if (p > buf && p[-1] == ' ') p--; *p = '\0'; } #else # ifdef TIOCGSOFTCAR sprintf(p, " %s", softcar ? "(CD)", "CD"); p += strlen(p); # endif #endif if (clocal) *p++ = '}'; *p = '\0'; return buf; } /* * Old bsd-ish machines may not have any of the baudrate B... symbols. * We hope to detect them here, so that the btable[] below always has * many entries. */ #ifndef POSIX # ifndef TERMIO # if !defined(B9600) && !defined(B2400) && !defined(B1200) && !defined(B300) IFN{B0}#define B0 0 IFN{B50}#define B50 1 IFN{B75}#define B75 2 IFN{B110}#define B110 3 IFN{B134}#define B134 4 IFN{B150}#define B150 5 IFN{B200}#define B200 6 IFN{B300}#define B300 7 IFN{B600}#define B600 8 IFN{B1200}#define B1200 9 IFN{B1800}#define B1800 10 IFN{B2400}#define B2400 11 IFN{B4800}#define B4800 12 IFN{B9600}#define B9600 13 IFN{EXTA}#define EXTA 14 IFN{EXTB}#define EXTB 15 # endif # endif #endif /* * On hpux, idx and sym will be different. * Rumor has it that, we need idx in D_dospeed to make tputs * padding correct. * Frequently used entries come first. */ static struct baud_values btable[] = { IF{B9600} { 13, 9600, B9600 }, IF{B19200} { 14, 19200, B19200 }, IF{EXTA} { 14, 19200, EXTA }, IF{B38400} { 15, 38400, B38400 }, IF{EXTB} { 15, 38400, EXTB }, IF{B57600} { 16, 57600, B57600 }, IF{B115200} { 17, 115200, B115200 }, IF{B230400} { 18, 230400, B230400 }, IF{B460800} { 19, 460800, B460800 }, IF{B7200} { 13, 7200, B7200 }, IF{B4800} { 12, 4800, B4800 }, IF{B3600} { 12, 3600, B3600 }, IF{B2400} { 11, 2400, B2400 }, IF{B1800} { 10, 1800, B1800 }, IF{B1200} { 9, 1200, B1200 }, IF{B900} { 9, 900, B900 }, IF{B600} { 8, 600, B600 }, IF{B300} { 7, 300, B300 }, IF{B200} { 6, 200, B200 }, IF{B150} { 5, 150, B150 }, IF{B134} { 4, 134, B134 }, IF{B110} { 3, 110, B110 }, IF{B75} { 2, 75, B75 }, IF{B50} { 1, 50, B50 }, IF{B0} { 0, 0, B0 }, { -1, -1, -1 } }; /* * baud may either be a bits-per-second value or a symbolic * value as returned by cfget?speed() */ struct baud_values * lookup_baud(baud) int baud; { struct baud_values *p; for (p = btable; p->idx >= 0; p++) if (baud == p->bps || baud == p->sym) return p; return NULL; } /* * change the baud rate in a mode structure. * ibaud and obaud are given in bit/second, or at your option as * termio B... symbols as defined in e.g. suns sys/ttydev.h * -1 means don't change. */ int SetBaud(m, ibaud, obaud) struct mode *m; int ibaud, obaud; { struct baud_values *ip, *op; if ((!(ip = lookup_baud(ibaud)) && ibaud != -1) || (!(op = lookup_baud(obaud)) && obaud != -1)) return -1; #ifdef POSIX if (ip) cfsetispeed(&m->tio, ip->sym); if (op) cfsetospeed(&m->tio, op->sym); #else /* POSIX */ # ifdef TERMIO if (ip) { # ifdef IBSHIFT m->tio.c_cflag &= ~(CBAUD << IBSHIFT); m->tio.c_cflag |= (ip->sym & CBAUD) << IBSHIFT; # else /* IBSHIFT */ if (ibaud != obaud) return -1; # endif /* IBSHIFT */ } if (op) { m->tio.c_cflag &= ~CBAUD; m->tio.c_cflag |= op->sym & CBAUD; } # else /* TERMIO */ if (ip) m->m_ttyb.sg_ispeed = ip->idx; if (op) m->m_ttyb.sg_ospeed = op->idx; # endif /* TERMIO */ #endif /* POSIX */ return 0; } /* * Write out the mode struct in a readable form */ #ifdef DEBUG void DebugTTY(m) struct mode *m; { int i; #ifdef POSIX debug("struct termios tio:\n"); debug1("c_iflag = %#x\n", (unsigned int)m->tio.c_iflag); debug1("c_oflag = %#x\n", (unsigned int)m->tio.c_oflag); debug1("c_cflag = %#x\n", (unsigned int)m->tio.c_cflag); debug1("c_lflag = %#x\n", (unsigned int)m->tio.c_lflag); debug1("cfgetospeed() = %d\n", (int)cfgetospeed(&m->tio)); debug1("cfgetispeed() = %d\n", (int)cfgetispeed(&m->tio)); for (i = 0; i < sizeof(m->tio.c_cc)/sizeof(*m->tio.c_cc); i++) { debug2("c_cc[%d] = %#x\n", i, m->tio.c_cc[i]); } # ifdef HPUX_LTCHARS_HACK debug1("suspc = %#02x\n", m->m_ltchars.t_suspc); debug1("dsuspc = %#02x\n", m->m_ltchars.t_dsuspc); debug1("rprntc = %#02x\n", m->m_ltchars.t_rprntc); debug1("flushc = %#02x\n", m->m_ltchars.t_flushc); debug1("werasc = %#02x\n", m->m_ltchars.t_werasc); debug1("lnextc = %#02x\n", m->m_ltchars.t_lnextc); # endif /* HPUX_LTCHARS_HACK */ #else /* POSIX */ # ifdef TERMIO debug("struct termio tio:\n"); debug1("c_iflag = %04o\n", m->tio.c_iflag); debug1("c_oflag = %04o\n", m->tio.c_oflag); debug1("c_cflag = %04o\n", m->tio.c_cflag); debug1("c_lflag = %04o\n", m->tio.c_lflag); for (i = 0; i < sizeof(m->tio.c_cc)/sizeof(*m->tio.c_cc); i++) { debug2("c_cc[%d] = %04o\n", i, m->tio.c_cc[i]); } # else /* TERMIO */ debug1("sg_ispeed = %d\n", m->m_ttyb.sg_ispeed); debug1("sg_ospeed = %d\n", m->m_ttyb.sg_ospeed); debug1("sg_erase = %#02x\n", m->m_ttyb.sg_erase); debug1("sg_kill = %#02x\n", m->m_ttyb.sg_kill); debug1("sg_flags = %#04x\n", (unsigned short)m->m_ttyb.sg_flags); debug1("intrc = %#02x\n", m->m_tchars.t_intrc); debug1("quitc = %#02x\n", m->m_tchars.t_quitc); debug1("startc = %#02x\n", m->m_tchars.t_startc); debug1("stopc = %#02x\n", m->m_tchars.t_stopc); debug1("eofc = %#02x\n", m->m_tchars.t_eofc); debug1("brkc = %#02x\n", m->m_tchars.t_brkc); debug1("suspc = %#02x\n", m->m_ltchars.t_suspc); debug1("dsuspc = %#02x\n", m->m_ltchars.t_dsuspc); debug1("rprntc = %#02x\n", m->m_ltchars.t_rprntc); debug1("flushc = %#02x\n", m->m_ltchars.t_flushc); debug1("werasc = %#02x\n", m->m_ltchars.t_werasc); debug1("lnextc = %#02x\n", m->m_ltchars.t_lnextc); debug1("ldisc = %d\n", m->m_ldisc); debug1("lmode = %#x\n", m->m_lmode); # endif /* TERMIO */ #endif /* POSIX */ } #endif /* DEBUG */ screen-4.1.0/os.h0000644000175000017500000002773711642704565011657 0ustar abeabe/* Copyright (c) 2008, 2009 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Micah Cowan (micah@cowan.name) * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net) * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Copyright (c) 1987 Oliver Laumann * * 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, 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 (see the file COPYING); if not, see * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA * **************************************************************** * $Id$ GNU */ #include #include #include /* In strict ANSI mode, HP-UX machines define __hpux but not hpux */ #if defined(__hpux) && !defined(hpux) # define hpux #endif #if defined(__bsdi__) || defined(__386BSD__) || defined(_CX_UX) || defined(hpux) || defined(_IBMR2) || defined(linux) # include #endif /* __bsdi__ || __386BSD__ || _CX_UX || hpux || _IBMR2 || linux */ #if !defined(HAVE_LONG_FILE_NAMES) && !defined(NAME_MAX) #define NAME_MAX 14 #endif #ifdef ISC # ifdef ENAMETOOLONG # undef ENAMETOOLONG # endif # ifdef ENOTEMPTY # undef ENOTEMPTY # endif # include # include #endif #ifdef sun # define getpgrp __getpgrp # define exit __exit #endif #ifdef POSIX # include # if defined(__STDC__) # include # endif /* __STDC__ */ #endif /* POSIX */ #ifdef sun # undef getpgrp # undef exit #endif /* sun */ #ifndef linux /* all done in */ extern int errno; #endif /* linux */ #ifndef HAVE_STRERROR /* No macros, please */ #undef strerror #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_STRING_H # include #endif #ifdef USEVARARGS # if defined(__STDC__) # include # define VA_LIST(var) va_list var; # define VA_DOTS ... # define VA_DECL # define VA_START(ap, fmt) va_start(ap, fmt) # define VA_ARGS(ap) ap # define VA_END(ap) va_end(ap) # else # include # define VA_LIST(var) va_list var; # define VA_DOTS va_alist # define VA_DECL va_dcl # define VA_START(ap, fmt) va_start(ap) # define VA_ARGS(ap) ap # define VA_END(ap) va_end(ap) # endif #else # define VA_LIST(var) # define VA_DOTS p1, p2, p3, p4, p5, p6 # define VA_DECL unsigned long VA_DOTS; # define VA_START(ap, fmt) # define VA_ARGS(ap) VA_DOTS # define VA_END(ap) # undef vsnprintf # define vsnprintf xsnprintf #endif #if !defined(sun) && !defined(B43) && !defined(ISC) && !defined(pyr) && !defined(_CX_UX) # include #endif #include #ifdef M_UNIX /* SCO */ # include # include # define ftruncate(fd, s) chsize(fd, s) #endif #ifdef SYSV # define index strchr # define rindex strrchr # define bzero(poi,len) memset(poi,0,len) # define bcmp memcmp # define killpg(pgrp,sig) kill( -(pgrp), sig) #endif #ifndef HAVE_GETCWD # define getcwd(b,l) getwd(b) #endif #ifndef USEBCOPY # ifdef USEMEMMOVE # define bcopy(s,d,len) memmove(d,s,len) # else # ifdef USEMEMCPY # define bcopy(s,d,len) memcpy(d,s,len) # else # define NEED_OWN_BCOPY # define bcopy xbcopy # endif # endif #endif #if defined(HAVE_SETRESUID) && !defined(HAVE_SETREUID) # define setreuid(ruid, euid) setresuid(ruid, euid, -1) # define setregid(rgid, egid) setresgid(rgid, egid, -1) #endif #if defined(HAVE_SETEUID) || defined(HAVE_SETREUID) || defined(HAVE_SETRESUID) # define USE_SETEUID #endif #if !defined(HAVE__EXIT) && !defined(_exit) #define _exit(x) exit(x) #endif #ifndef HAVE_UTIMES # define utimes utime #endif #ifndef HAVE_VSNPRINTF # define vsnprintf xvsnprintf #endif #ifdef BUILTIN_TELNET # include # include #endif #if defined(USE_LOCALE) && (!defined(HAVE_SETLOCALE) || !defined(HAVE_STRFTIME)) # undef USE_LOCALE #endif /***************************************************************** * terminal handling */ #ifdef POSIX # include # ifdef hpux # include # endif /* hpux */ # ifdef NCCS # define MAXCC NCCS # else # define MAXCC 256 # endif #else /* POSIX */ # ifdef TERMIO # include # ifdef NCC # define MAXCC NCC # else # define MAXCC 256 # endif # ifdef CYTERMIO # include # endif # else /* TERMIO */ # include # endif /* TERMIO */ #endif /* POSIX */ #ifndef VDISABLE # ifdef _POSIX_VDISABLE # define VDISABLE _POSIX_VDISABLE # else # define VDISABLE 0377 # endif /* _POSIX_VDISABLE */ #endif /* !VDISABLE */ /* on sgi, regardless of the stream head's read mode (RNORM/RMSGN/RMSGD) * TIOCPKT mode causes data loss if our buffer is too small (IOSIZE) * to hold the whole packet at first read(). * (Marc Boucher) * * matthew green: * TIOCPKT is broken on dgux 5.4.1 generic AViiON mc88100 * * Joe Traister: On AIX4, programs like irc won't work if screen * uses TIOCPKT (select fails to return on pty read). */ #if defined(sgi) || defined(DGUX) || defined(_IBMR2) # undef TIOCPKT #endif /* Alexandre Oliva: SVR4 style ptys don't work with osf */ #ifdef __osf__ # undef HAVE_SVR4_PTYS #endif /***************************************************************** * utmp handling */ #ifdef GETUTENT typedef char *slot_t; #else typedef int slot_t; #endif #if defined(UTMPOK) || defined(BUGGYGETLOGIN) # if defined(SVR4) && !defined(DGUX) && !defined(__hpux) && !defined(linux) # include # define UTMPFILE UTMPX_FILE # define utmp utmpx # define getutent getutxent # define getutid getutxid # define getutline getutxline # define pututline pututxline # define setutent setutxent # define endutent endutxent # define ut_time ut_xtime # else /* SVR4 */ # include # endif /* SVR4 */ # ifdef apollo /* * We don't have GETUTENT, so we dig into utmp ourselves. * But we save the permanent filedescriptor and * open utmp just when we need to. * This code supports an unsorted utmp. jw. */ # define UTNOKEEP # endif /* apollo */ # ifndef UTMPFILE # ifdef UTMP_FILE # define UTMPFILE UTMP_FILE # else # ifdef _PATH_UTMP # define UTMPFILE _PATH_UTMP # else # define UTMPFILE "/etc/utmp" # endif /* _PATH_UTMP */ # endif # endif #endif /* UTMPOK || BUGGYGETLOGIN */ #if !defined(UTMPOK) && defined(USRLIMIT) # undef USRLIMIT #endif #ifdef LOGOUTOK # ifndef LOGINDEFAULT # define LOGINDEFAULT 0 # endif #else # ifdef LOGINDEFAULT # undef LOGINDEFAULT # endif # define LOGINDEFAULT 1 #endif /***************************************************************** * file stuff */ #ifndef F_OK #define F_OK 0 #endif #ifndef X_OK #define X_OK 1 #endif #ifndef W_OK #define W_OK 2 #endif #ifndef R_OK #define R_OK 4 #endif #ifndef S_IFIFO #define S_IFIFO 0010000 #endif #ifndef S_IREAD #define S_IREAD 0000400 #endif #ifndef S_IWRITE #define S_IWRITE 0000200 #endif #ifndef S_IEXEC #define S_IEXEC 0000100 #endif #if defined(S_IFIFO) && defined(S_IFMT) && !defined(S_ISFIFO) #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) #endif #if defined(S_IFSOCK) && defined(S_IFMT) && !defined(S_ISSOCK) #define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) #endif #if defined(S_IFCHR) && defined(S_IFMT) && !defined(S_ISCHR) #define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) #endif #if defined(S_IFDIR) && defined(S_IFMT) && !defined(S_ISDIR) #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) #endif #if defined(S_IFLNK) && defined(S_IFMT) && !defined(S_ISLNK) #define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) #endif /* * SunOS 4.1.3: `man 2V open' has only one line that mentions O_NOBLOCK: * * O_NONBLOCK Same as O_NDELAY above. * * on the very same SunOS 4.1.3, I traced the open system call and found * that an open("/dev/ttyy08", O_RDWR|O_NONBLOCK|O_NOCTTY) was blocked, * whereas open("/dev/ttyy08", O_RDWR|O_NDELAY |O_NOCTTY) went through. * * For this simple reason I now favour O_NDELAY. jw. 4.5.95 */ #if defined(sun) && !defined(SVR4) # undef O_NONBLOCK #endif #if !defined(O_NONBLOCK) && defined(O_NDELAY) # define O_NONBLOCK O_NDELAY #endif #if !defined(FNBLOCK) && defined(FNONBLOCK) # define FNBLOCK FNONBLOCK #endif #if !defined(FNBLOCK) && defined(FNDELAY) # define FNBLOCK FNDELAY #endif #if !defined(FNBLOCK) && defined(O_NONBLOCK) # define FNBLOCK O_NONBLOCK #endif #ifndef POSIX #undef mkfifo #define mkfifo(n,m) mknod(n,S_IFIFO|(m),0) #endif #if !defined(HAVE_LSTAT) && !defined(lstat) # define lstat stat #endif /***************************************************************** * signal handling */ #ifdef SIGVOID # define SIGRETURN # define sigret_t void #else # define SIGRETURN return 0; # define sigret_t int #endif /* Geeeee, reverse it? */ #if defined(SVR4) || (defined(SYSV) && defined(ISC)) || defined(_AIX) || defined(linux) || defined(ultrix) || defined(__386BSD__) || defined(__bsdi__) || defined(POSIX) || defined(NeXT) # define SIGHASARG #endif #ifdef SIGHASARG # define SIGPROTOARG (int) # define SIGDEFARG (sigsig) int sigsig; # define SIGARG 0 #else # define SIGPROTOARG (void) # define SIGDEFARG () # define SIGARG #endif #ifndef SIGCHLD #define SIGCHLD SIGCLD #endif #if defined(POSIX) || defined(hpux) # define signal xsignal #else # ifdef USESIGSET # define signal sigset # endif /* USESIGSET */ #endif /* used in screen.c and attacher.c */ #ifndef NSIG /* kbeal needs these w/o SYSV */ # define NSIG 32 #endif /* !NSIG */ /***************************************************************** * Wait stuff */ #if (!defined(sysV68) && !defined(M_XENIX)) || defined(NeXT) || defined(M_UNIX) # include #endif #ifndef WTERMSIG # ifndef BSDWAIT /* if wait is NOT a union: */ # define WTERMSIG(status) (status & 0177) # else # define WTERMSIG(status) status.w_T.w_Termsig # endif #endif #ifndef WSTOPSIG # ifndef BSDWAIT /* if wait is NOT a union: */ # define WSTOPSIG(status) ((status >> 8) & 0377) # else # define WSTOPSIG(status) status.w_S.w_Stopsig # endif #endif /* NET-2 uses WCOREDUMP */ #if defined(WCOREDUMP) && !defined(WIFCORESIG) # define WIFCORESIG(status) WCOREDUMP(status) #endif #ifndef WIFCORESIG # ifndef BSDWAIT /* if wait is NOT a union: */ # define WIFCORESIG(status) (status & 0200) # else # define WIFCORESIG(status) status.w_T.w_Coredump # endif #endif #ifndef WEXITSTATUS # ifndef BSDWAIT /* if wait is NOT a union: */ # define WEXITSTATUS(status) ((status >> 8) & 0377) # else # define WEXITSTATUS(status) status.w_T.w_Retcode # endif #endif /***************************************************************** * select stuff */ #if defined(M_XENIX) || defined(M_UNIX) || defined(_SEQUENT_) #include /* for timeval + FD... */ #endif /* * SunOS 3.5 - Tom Schmidt - Micron Semiconductor, Inc - 27-Jul-93 * tschmidt@vax.micron.com */ #ifndef FD_SET # ifndef SUNOS3 typedef struct fd_set { int fds_bits[1]; } fd_set; # endif # define FD_ZERO(fd) ((fd)->fds_bits[0] = 0) # define FD_SET(b, fd) ((fd)->fds_bits[0] |= 1 << (b)) # define FD_ISSET(b, fd) ((fd)->fds_bits[0] & 1 << (b)) # define FD_SETSIZE 32 #endif /***************************************************************** * user defineable stuff */ #ifndef TERMCAP_BUFSIZE # define TERMCAP_BUFSIZE 2048 #endif #ifndef MAXPATHLEN # define MAXPATHLEN 1024 #endif /* * you may try to vary this value. Use low values if your (VMS) system * tends to choke when pasting. Use high values if you want to test * how many characters your pty's can buffer. */ #define IOSIZE 4096 screen-4.1.0/canvas.h0000644000175000017500000000735711642704565012505 0ustar abeabe/* Copyright (c) 2008, 2009 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Micah Cowan (micah@cowan.name) * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net) * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Copyright (c) 1987 Oliver Laumann * * 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, 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 (see the file COPYING); if not, see * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA * **************************************************************** * $Id$ GNU */ #ifndef SCREEN_CANVAS_H #define SCREEN_CANVAS_H #define SLICE_UNKN 0 #define SLICE_VERT (1 << 0) #define SLICE_HORI (1 << 1) #define SLICE_THIS (1 << 2) /* used in equal test */ #define SLICE_GLOBAL (1 << 3) struct canvas { struct canvas *c_next; /* next canvas on display */ struct display *c_display; /* back pointer to display */ struct canvas *c_slnext; /* next canvas in display slice */ struct canvas *c_slprev; /* prev canvas in display slice */ struct canvas *c_slperp; /* perpendicular slice */ struct canvas *c_slback; /* perpendicular slice back pointer */ int c_slorient; /* our slice orientation */ int c_slweight; /* size ratio */ struct viewport *c_vplist; struct layer *c_layer; /* layer on this canvas */ struct canvas *c_lnext; /* next canvas that displays layer */ struct layer c_blank; /* bottom layer, always blank */ int c_xoff; /* canvas x offset on display */ int c_yoff; /* canvas y offset on display */ int c_xs; int c_xe; int c_ys; int c_ye; struct event c_captev; /* caption changed event */ }; struct win; /* forward declaration */ extern void SetCanvasWindow __P((struct canvas *, struct win *)); extern void SetForeCanvas __P((struct display *, struct canvas *)); extern struct canvas *FindCanvas __P((int, int)); extern int MakeDefaultCanvas __P((void)); extern int AddCanvas __P((int)); extern void RemCanvas __P((void)); extern void OneCanvas __P((void)); extern void FreeCanvas __P((struct canvas *)); extern void ResizeCanvas __P((struct canvas *)); extern void RecreateCanvasChain __P((void)); extern void RethinkViewportOffsets __P((struct canvas *)); extern int CountCanvasPerp __P((struct canvas *)); extern void EqualizeCanvas __P((struct canvas *, int)); extern void DupLayoutCv __P((struct canvas *, struct canvas *, int)); extern void PutWindowCv __P((struct canvas *)); #define CV_CALL(cv, cmd) \ { \ struct display *olddisplay = display; \ struct layer *oldflayer = flayer; \ struct layer *l = cv->c_layer; \ struct canvas *cvlist = l->l_cvlist; \ struct canvas *cvlnext = cv->c_lnext; \ flayer = l; \ l->l_cvlist = cv; \ cv->c_lnext = 0; \ cmd; \ flayer = oldflayer; \ l->l_cvlist = cvlist; \ cv->c_lnext = cvlnext; \ display = olddisplay; \ } #endif /* SCREEN_CANVAS_H */ screen-4.1.0/NEWS.3.60000644000175000017500000000327411642704565012057 0ustar abeabe ---------------------------- What's new in screen-3.6 ? ---------------------------- * Input translation! This makes the vt100 emulation complete. As an addition it is now possible to bind any command to any (function-) key. See the man page for more details (bindkey command). * Status line support. Each window can have a different status line. Use the ANSI APC string to set the status line, i.e.: _\ (For convenience the xterm sequence is also accepted.) You may want to add termcap * '' ':hs:ts=\E_:fs=\E\\:ds=\E_\E\\:' terminfo * '' ':hs:ts=\E_:fs=\E\\:ds=\E_\E\\:' to your ~/.screenrc to make screen advertise the hardstatus support. * Zombie feature added. Windows now may generate a message (with a timestamp) if they die and stay around until the user presses a key. * New paste syntax: Paste can now concatenate registers and paste either on screen or in anouther register. This makes the old "ins_reg", "copy_reg" commands obsolete. * More architecures supported. Screen now runs on AIX3.2.5, Solaris, NeXT and some other exotic platforms. * Kanji support added. Screen understands JIS, EUC and SJIS coding. This is an experimental feature. * GR charset switching (ISO 2022) implemented. Can be enabled with the "gr" command. * C1 sequences implemented (see the "c1" command). * Tek support from Xiaoguang Zhang. Apply tek.patch if you want to make screen pass tek sequences. * List of new commands: bindkey, c1, command, defc1, defgr, defkanji, gr, kanji, mapdefault, mapnotnext, maptimeout, pastefont, printcmd, readreg, stuff, zombie * Lots of other bugs fixed. screen-4.1.0/attacher.c0000644000175000017500000006015011666241426013004 0ustar abeabe/* Copyright (c) 2008, 2009 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Micah Cowan (micah@cowan.name) * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net) * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Copyright (c) 1987 Oliver Laumann * * 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, 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 (see the file COPYING); if not, see * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA * **************************************************************** */ #include "config.h" #include #include #include #include #include #include "screen.h" #include "extern.h" #include static int WriteMessage __P((int, struct msg *)); static sigret_t AttacherSigInt __P(SIGPROTOARG); #if defined(SIGWINCH) && defined(TIOCGWINSZ) static sigret_t AttacherWinch __P(SIGPROTOARG); #endif #ifdef LOCK static sigret_t DoLock __P(SIGPROTOARG); static void LockTerminal __P((void)); static sigret_t LockHup __P(SIGPROTOARG); static void screen_builtin_lck __P((void)); #endif #ifdef DEBUG static sigret_t AttacherChld __P(SIGPROTOARG); #endif static sigret_t AttachSigCont __P(SIGPROTOARG); extern int real_uid, real_gid, eff_uid, eff_gid; extern char *SockName, *SockMatch, SockPath[]; extern char HostName[]; extern struct passwd *ppp; extern char *attach_tty, *attach_term, *LoginName, *preselect; extern int xflag, dflag, rflag, quietflag, adaptflag; extern struct mode attach_Mode; extern struct NewWindow nwin_options; extern int MasterPid, attach_fd; #ifdef MULTIUSER extern char *multi; extern int multiattach, multi_uid, own_uid; extern int tty_mode, tty_oldmode; # ifndef USE_SETEUID static int multipipe[2]; # endif #endif static int ContinuePlease; static sigret_t AttachSigCont SIGDEFARG { debug("SigCont()\n"); ContinuePlease = 1; SIGRETURN; } static int QueryResult; static sigret_t QueryResultSuccess SIGDEFARG { QueryResult = 1; SIGRETURN; } static sigret_t QueryResultFail SIGDEFARG { QueryResult = 2; SIGRETURN; } /* * Send message to a screen backend. * returns 1 if we could attach one, or 0 if none. * Understands MSG_ATTACH, MSG_DETACH, MSG_POW_DETACH * MSG_CONT, MSG_WINCH and nothing else! * * if type == MSG_ATTACH and sockets are used, attaches * tty filedescriptor. */ static int WriteMessage(s, m) int s; struct msg *m; { int r, l = sizeof(*m); #ifndef NAMEDPIPE if (m->type == MSG_ATTACH) return SendAttachMsg(s, m, attach_fd); #endif while(l > 0) { r = write(s, (char *)m + (sizeof(*m) - l), l); if (r == -1 && errno == EINTR) continue; if (r == -1 || r == 0) return -1; l -= r; } return 0; } int Attach(how) int how; { int n, lasts; struct msg m; struct stat st; char *s; debug2("Attach: how=%d, tty=%s\n", how, attach_tty); #ifdef MULTIUSER # ifndef USE_SETEUID while ((how == MSG_ATTACH || how == MSG_CONT) && multiattach) { int ret; if (pipe(multipipe)) Panic(errno, "pipe"); if (chmod(attach_tty, 0666)) Panic(errno, "chmod %s", attach_tty); tty_oldmode = tty_mode; eff_uid = -1; /* make UserContext fork */ real_uid = multi_uid; if ((ret = UserContext()) <= 0) { char dummy; eff_uid = 0; real_uid = own_uid; if (ret < 0) Panic(errno, "UserContext"); close(multipipe[1]); read(multipipe[0], &dummy, 1); if (tty_oldmode >= 0) { chmod(attach_tty, tty_oldmode); tty_oldmode = -1; } ret = UserStatus(); #ifdef LOCK if (ret == SIG_LOCK) LockTerminal(); else #endif #ifdef SIGTSTP if (ret == SIG_STOP) kill(getpid(), SIGTSTP); else #endif if (ret == SIG_POWER_BYE) { int ppid; setgid(real_gid); setuid(real_uid); if ((ppid = getppid()) > 1) Kill(ppid, SIGHUP); exit(0); } else exit(ret); dflag = 0; #ifdef MULTI xflag = 1; #endif how = MSG_ATTACH; continue; } close(multipipe[0]); eff_uid = real_uid; break; } # else /* USE_SETEUID */ if ((how == MSG_ATTACH || how == MSG_CONT) && multiattach) { real_uid = multi_uid; eff_uid = own_uid; #ifdef HAVE_SETRESUID if (setresuid(multi_uid, own_uid, multi_uid)) Panic(errno, "setresuid"); #else xseteuid(multi_uid); xseteuid(own_uid); #endif if (chmod(attach_tty, 0666)) Panic(errno, "chmod %s", attach_tty); tty_oldmode = tty_mode; } # endif /* USE_SETEUID */ #endif /* MULTIUSER */ bzero((char *) &m, sizeof(m)); m.type = how; m.protocol_revision = MSG_REVISION; strncpy(m.m_tty, attach_tty, sizeof(m.m_tty) - 1); m.m_tty[sizeof(m.m_tty) - 1] = 0; if (how == MSG_WINCH) { if ((lasts = MakeClientSocket(0)) >= 0) { WriteMessage(lasts, &m); close(lasts); } return 0; } if (how == MSG_CONT) { if ((lasts = MakeClientSocket(0)) < 0) { Panic(0, "Sorry, cannot contact session \"%s\" again.\r\n", SockName); } } else { n = FindSocket(&lasts, (int *)0, (int *)0, SockMatch); switch (n) { case 0: if (rflag && (rflag & 1) == 0) return 0; if (quietflag) eexit(10); Panic(0, SockMatch && *SockMatch ? "There is no screen to be %sed matching %s." : "There is no screen to be %sed.", xflag ? "attach" : dflag ? "detach" : "resum", SockMatch); /* NOTREACHED */ case 1: break; default: if (rflag < 3) { if (quietflag) eexit(10 + n); Panic(0, "Type \"screen [-d] -r [pid.]tty.host\" to resume one of them."); } /* NOTREACHED */ } } /* * Go in UserContext. Advantage is, you can kill your attacher * when things go wrong. Any disadvantages? jw. * Do this before the attach to prevent races! */ #ifdef MULTIUSER if (!multiattach) #endif setuid(real_uid); #if defined(MULTIUSER) && defined(USE_SETEUID) else { /* This call to xsetuid should also set the saved uid */ xseteuid(real_uid); /* multi_uid, allow backend to send signals */ } #endif setgid(real_gid); eff_uid = real_uid; eff_gid = real_gid; debug2("Attach: uid %d euid %d\n", (int)getuid(), (int)geteuid()); MasterPid = 0; for (s = SockName; *s; s++) { if (*s > '9' || *s < '0') break; MasterPid = 10 * MasterPid + (*s - '0'); } debug1("Attach decided, it is '%s'\n", SockPath); debug1("Attach found MasterPid == %d\n", MasterPid); if (stat(SockPath, &st) == -1) Panic(errno, "stat %s", SockPath); if ((st.st_mode & 0600) != 0600) Panic(0, "Socket is in wrong mode (%03o)", (int)st.st_mode); /* * Change: if -x or -r ignore failing -d */ if ((xflag || rflag) && dflag && (st.st_mode & 0700) == 0600) dflag = 0; /* * Without -x, the mode must match. * With -x the mode is irrelevant unless -d. */ if ((dflag || !xflag) && (st.st_mode & 0700) != (dflag ? 0700 : 0600)) Panic(0, "That screen is %sdetached.", dflag ? "already " : "not "); #ifdef REMOTE_DETACH if (dflag && (how == MSG_DETACH || how == MSG_POW_DETACH)) { m.m.detach.dpid = getpid(); strncpy(m.m.detach.duser, LoginName, sizeof(m.m.detach.duser) - 1); m.m.detach.duser[sizeof(m.m.detach.duser) - 1] = 0; # ifdef POW_DETACH if (dflag == 2) m.type = MSG_POW_DETACH; else # endif m.type = MSG_DETACH; /* If there is no password for the session, or the user enters the correct * password, then we get a SIGCONT. Otherwise we get a SIG_BYE */ signal(SIGCONT, AttachSigCont); if (WriteMessage(lasts, &m)) Panic(errno, "WriteMessage"); close(lasts); while (!ContinuePlease) pause(); /* wait for SIGCONT */ signal(SIGCONT, SIG_DFL); ContinuePlease = 0; if (how != MSG_ATTACH) return 0; /* we detached it. jw. */ sleep(1); /* we dont want to overrun our poor backend. jw. */ if ((lasts = MakeClientSocket(0)) == -1) Panic(0, "Cannot contact screen again. Sigh."); m.type = how; } #endif ASSERT(how == MSG_ATTACH || how == MSG_CONT); strncpy(m.m.attach.envterm, attach_term, sizeof(m.m.attach.envterm) - 1); m.m.attach.envterm[sizeof(m.m.attach.envterm) - 1] = 0; debug1("attach: sending %d bytes... ", (int)sizeof(m)); strncpy(m.m.attach.auser, LoginName, sizeof(m.m.attach.auser) - 1); m.m.attach.auser[sizeof(m.m.attach.auser) - 1] = 0; m.m.attach.esc = DefaultEsc; m.m.attach.meta_esc = DefaultMetaEsc; strncpy(m.m.attach.preselect, preselect ? preselect : "", sizeof(m.m.attach.preselect) - 1); m.m.attach.preselect[sizeof(m.m.attach.preselect) - 1] = 0; m.m.attach.apid = getpid(); m.m.attach.adaptflag = adaptflag; m.m.attach.lines = m.m.attach.columns = 0; if ((s = getenv("LINES"))) m.m.attach.lines = atoi(s); if ((s = getenv("COLUMNS"))) m.m.attach.columns = atoi(s); m.m.attach.encoding = nwin_options.encoding > 0 ? nwin_options.encoding + 1 : 0; #ifdef REMOTE_DETACH #ifdef POW_DETACH if (dflag == 2) m.m.attach.detachfirst = MSG_POW_DETACH; else #endif if (dflag) m.m.attach.detachfirst = MSG_DETACH; else #endif m.m.attach.detachfirst = MSG_ATTACH; #ifdef MULTIUSER /* setup CONT signal handler to repair the terminal mode */ if (multi && (how == MSG_ATTACH || how == MSG_CONT)) signal(SIGCONT, AttachSigCont); #endif if (WriteMessage(lasts, &m)) Panic(errno, "WriteMessage"); close(lasts); debug1("Attach(%d): sent\n", m.type); #ifdef MULTIUSER if (multi && (how == MSG_ATTACH || how == MSG_CONT)) { while (!ContinuePlease) pause(); /* wait for SIGCONT */ signal(SIGCONT, SIG_DFL); ContinuePlease = 0; # ifndef USE_SETEUID close(multipipe[1]); # else xseteuid(own_uid); if (tty_oldmode >= 0) if (chmod(attach_tty, tty_oldmode)) Panic(errno, "chmod %s", attach_tty); tty_oldmode = -1; xseteuid(real_uid); # endif } #endif rflag = 0; return 1; } static int AttacherPanic = 0; #ifdef DEBUG static sigret_t AttacherChld SIGDEFARG { AttacherPanic = 1; SIGRETURN; } #endif static sigret_t AttacherSigAlarm SIGDEFARG { #ifdef DEBUG static int tick_cnt = 0; if ((tick_cnt = (tick_cnt + 1) % 4) == 0) debug("tick\n"); #endif SIGRETURN; } /* * the frontend's Interrupt handler * we forward SIGINT to the poor backend */ static sigret_t AttacherSigInt SIGDEFARG { signal(SIGINT, AttacherSigInt); Kill(MasterPid, SIGINT); SIGRETURN; } /* * Unfortunately this is also the SIGHUP handler, so we have to * check if the backend is already detached. */ sigret_t AttacherFinit SIGDEFARG { struct stat statb; struct msg m; int s; debug("AttacherFinit();\n"); signal(SIGHUP, SIG_IGN); /* Check if signal comes from backend */ if (stat(SockPath, &statb) == 0 && (statb.st_mode & 0777) != 0600) { debug("Detaching backend!\n"); bzero((char *) &m, sizeof(m)); strncpy(m.m_tty, attach_tty, sizeof(m.m_tty) - 1); m.m_tty[sizeof(m.m_tty) - 1] = 0; debug1("attach_tty is %s\n", attach_tty); m.m.detach.dpid = getpid(); m.type = MSG_HANGUP; m.protocol_revision = MSG_REVISION; if ((s = MakeClientSocket(0)) >= 0) { WriteMessage(s, &m); close(s); } } #ifdef MULTIUSER if (tty_oldmode >= 0) { setuid(own_uid); chmod(attach_tty, tty_oldmode); } #endif exit(0); SIGRETURN; } #ifdef POW_DETACH static sigret_t AttacherFinitBye SIGDEFARG { int ppid; debug("AttacherFintBye()\n"); #if defined(MULTIUSER) && !defined(USE_SETEUID) if (multiattach) exit(SIG_POWER_BYE); #endif setgid(real_gid); #ifdef MULTIUSER setuid(own_uid); #else setuid(real_uid); #endif /* we don't want to disturb init (even if we were root), eh? jw */ if ((ppid = getppid()) > 1) Kill(ppid, SIGHUP); /* carefully say good bye. jw. */ exit(0); SIGRETURN; } #endif #if defined(DEBUG) && defined(SIG_NODEBUG) static sigret_t AttacherNoDebug SIGDEFARG { debug("AttacherNoDebug()\n"); signal(SIG_NODEBUG, AttacherNoDebug); if (dfp) { debug("debug: closing debug file.\n"); fflush(dfp); fclose(dfp); dfp = NULL; } SIGRETURN; } #endif /* SIG_NODEBUG */ static int SuspendPlease; static sigret_t SigStop SIGDEFARG { debug("SigStop()\n"); SuspendPlease = 1; SIGRETURN; } #ifdef LOCK static int LockPlease; static sigret_t DoLock SIGDEFARG { # ifdef SYSVSIGS signal(SIG_LOCK, DoLock); # endif debug("DoLock()\n"); LockPlease = 1; SIGRETURN; } #endif #if defined(SIGWINCH) && defined(TIOCGWINSZ) static int SigWinchPlease; static sigret_t AttacherWinch SIGDEFARG { debug("AttacherWinch()\n"); SigWinchPlease = 1; SIGRETURN; } #endif /* * Attacher loop - no return */ void Attacher() { signal(SIGHUP, AttacherFinit); signal(SIG_BYE, AttacherFinit); #ifdef POW_DETACH signal(SIG_POWER_BYE, AttacherFinitBye); #endif #if defined(DEBUG) && defined(SIG_NODEBUG) signal(SIG_NODEBUG, AttacherNoDebug); #endif #ifdef LOCK signal(SIG_LOCK, DoLock); #endif signal(SIGINT, AttacherSigInt); #ifdef BSDJOBS signal(SIG_STOP, SigStop); #endif #if defined(SIGWINCH) && defined(TIOCGWINSZ) signal(SIGWINCH, AttacherWinch); #endif #ifdef DEBUG signal(SIGCHLD, AttacherChld); #endif debug("attacher: going for a nap.\n"); dflag = 0; #ifdef MULTI xflag = 1; #endif for (;;) { signal(SIGALRM, AttacherSigAlarm); alarm(15); pause(); alarm(0); if (kill(MasterPid, 0) < 0 && errno != EPERM) { debug1("attacher: Panic! MasterPid %d does not exist.\n", MasterPid); AttacherPanic++; } if (AttacherPanic) { fcntl(0, F_SETFL, 0); SetTTY(0, &attach_Mode); printf("\nSuddenly the Dungeon collapses!! - You die...\n"); eexit(1); } #ifdef BSDJOBS if (SuspendPlease) { SuspendPlease = 0; #if defined(MULTIUSER) && !defined(USE_SETEUID) if (multiattach) exit(SIG_STOP); #endif signal(SIGTSTP, SIG_DFL); debug("attacher: killing myself SIGTSTP\n"); kill(getpid(), SIGTSTP); debug("attacher: continuing from stop\n"); signal(SIG_STOP, SigStop); (void) Attach(MSG_CONT); } #endif #ifdef LOCK if (LockPlease) { LockPlease = 0; #if defined(MULTIUSER) && !defined(USE_SETEUID) if (multiattach) exit(SIG_LOCK); #endif LockTerminal(); # ifdef SYSVSIGS signal(SIG_LOCK, DoLock); # endif (void) Attach(MSG_CONT); } #endif /* LOCK */ #if defined(SIGWINCH) && defined(TIOCGWINSZ) if (SigWinchPlease) { SigWinchPlease = 0; # ifdef SYSVSIGS signal(SIGWINCH, AttacherWinch); # endif (void) Attach(MSG_WINCH); } #endif /* SIGWINCH */ } } #ifdef LOCK /* ADDED by Rainer Pruy 10/15/87 */ /* POLISHED by mls. 03/10/91 */ static char LockEnd[] = "Welcome back to screen !!\n"; static sigret_t LockHup SIGDEFARG { int ppid = getppid(); setgid(real_gid); #ifdef MULTIUSER setuid(own_uid); #else setuid(real_uid); #endif if (ppid > 1) Kill(ppid, SIGHUP); exit(0); } static void LockTerminal() { char *prg; int sig, pid; sigret_t (*sigs[NSIG])__P(SIGPROTOARG); for (sig = 1; sig < NSIG; sig++) sigs[sig] = signal(sig, sig == SIGCHLD ? SIG_DFL : SIG_IGN); signal(SIGHUP, LockHup); printf("\n"); prg = getenv("LOCKPRG"); if (prg && strcmp(prg, "builtin") && !access(prg, X_OK)) { signal(SIGCHLD, SIG_DFL); debug1("lockterminal: '%s' seems executable, execl it!\n", prg); if ((pid = fork()) == 0) { /* Child */ setgid(real_gid); #ifdef MULTIUSER setuid(own_uid); #else setuid(real_uid); /* this should be done already */ #endif closeallfiles(0); /* important: /etc/shadow may be open */ execl(prg, "SCREEN-LOCK", NULL); exit(errno); } if (pid == -1) Msg(errno, "Cannot lock terminal - fork failed"); else { #ifdef BSDWAIT union wait wstat; #else int wstat; #endif int wret; #ifdef hpux signal(SIGCHLD, SIG_DFL); #endif errno = 0; while (((wret = wait(&wstat)) != pid) || ((wret == -1) && (errno == EINTR)) ) errno = 0; if (errno) { Msg(errno, "Lock"); sleep(2); } else if (WTERMSIG(wstat) != 0) { fprintf(stderr, "Lock: %s: Killed by signal: %d%s\n", prg, WTERMSIG(wstat), WIFCORESIG(wstat) ? " (Core dumped)" : ""); sleep(2); } else if (WEXITSTATUS(wstat)) { debug2("Lock: %s: return code %d\n", prg, WEXITSTATUS(wstat)); } else printf("%s", LockEnd); } } else { if (prg) { debug1("lockterminal: '%s' seems NOT executable, we use our builtin\n", prg); } else { debug("lockterminal: using buitin.\n"); } screen_builtin_lck(); } /* reset signals */ for (sig = 1; sig < NSIG; sig++) { if (sigs[sig] != (sigret_t(*)__P(SIGPROTOARG)) -1) signal(sig, sigs[sig]); } } /* LockTerminal */ #ifdef USE_PAM /* * PAM support by Pablo Averbuj */ #include static int PAM_conv __P((int, const struct pam_message **, struct pam_response **, void *)); static int PAM_conv(num_msg, msg, resp, appdata_ptr) int num_msg; const struct pam_message **msg; struct pam_response **resp; void *appdata_ptr; { int replies = 0; struct pam_response *reply = NULL; reply = malloc(sizeof(struct pam_response)*num_msg); if (!reply) return PAM_CONV_ERR; #define COPY_STRING(s) (s) ? strdup(s) : NULL for (replies = 0; replies < num_msg; replies++) { switch (msg[replies]->msg_style) { case PAM_PROMPT_ECHO_OFF: /* wants password */ reply[replies].resp_retcode = PAM_SUCCESS; reply[replies].resp = appdata_ptr ? strdup((char *)appdata_ptr) : 0; break; case PAM_TEXT_INFO: /* ignore the informational mesage */ /* but first clear out any drek left by malloc */ reply[replies].resp = NULL; break; case PAM_PROMPT_ECHO_ON: /* user name given to PAM already */ /* fall through */ default: /* unknown or PAM_ERROR_MSG */ free(reply); return PAM_CONV_ERR; } } *resp = reply; return PAM_SUCCESS; } static struct pam_conv PAM_conversation = { &PAM_conv, NULL }; #endif /* -- original copyright by Luigi Cannelloni 1985 (luigi@faui70.UUCP) -- */ static void screen_builtin_lck() { char fullname[100], *cp1, message[100 + 100]; #ifdef USE_PAM pam_handle_t *pamh = 0; int pam_error; #else char *pass, mypass[16 + 1], salt[3]; #endif #ifndef USE_PAM pass = ppp->pw_passwd; if (pass == 0 || *pass == 0) { if ((pass = getpass("Key: "))) { strncpy(mypass, pass, sizeof(mypass) - 1); mypass[sizeof(mypass) - 1] = 0; if (*mypass == 0) return; if ((pass = getpass("Again: "))) { if (strcmp(mypass, pass)) { fprintf(stderr, "Passwords don't match.\007\n"); sleep(2); return; } } } if (pass == 0) { fprintf(stderr, "Getpass error.\007\n"); sleep(2); return; } salt[0] = 'A' + (int)(time(0) % 26); salt[1] = 'A' + (int)((time(0) >> 6) % 26); salt[2] = 0; pass = crypt(mypass, salt); pass = ppp->pw_passwd = SaveStr(pass); } #endif debug("screen_builtin_lck looking in gcos field\n"); strncpy(fullname, ppp->pw_gecos, sizeof(fullname) - 9); fullname[sizeof(fullname) - 9] = 0; if ((cp1 = index(fullname, ',')) != NULL) *cp1 = '\0'; if ((cp1 = index(fullname, '&')) != NULL) { strncpy(cp1, ppp->pw_name, 8); cp1[8] = 0; if (*cp1 >= 'a' && *cp1 <= 'z') *cp1 -= 'a' - 'A'; } sprintf(message, "Screen used by %s%s<%s> on %s.\nPassword:\007", fullname, fullname[0] ? " " : "", ppp->pw_name, HostName); /* loop here to wait for correct password */ for (;;) { debug("screen_builtin_lck awaiting password\n"); errno = 0; if ((cp1 = getpass(message)) == NULL) { AttacherFinit(SIGARG); /* NOTREACHED */ } #ifdef USE_PAM PAM_conversation.appdata_ptr = cp1; pam_error = pam_start("screen", ppp->pw_name, &PAM_conversation, &pamh); if (pam_error != PAM_SUCCESS) AttacherFinit(SIGARG); /* goodbye */ pam_error = pam_authenticate(pamh, 0); pam_end(pamh, pam_error); PAM_conversation.appdata_ptr = 0; if (pam_error == PAM_SUCCESS) break; #else if (!strncmp(crypt(cp1, pass), pass, strlen(pass))) break; #endif debug("screen_builtin_lck: NO!!!!!\n"); bzero(cp1, strlen(cp1)); } bzero(cp1, strlen(cp1)); debug("password ok.\n"); } #endif /* LOCK */ void SendCmdMessage(sty, match, av, query) char *sty; char *match; char **av; int query; { int i, s; struct msg m; char *p; int len, n; if (sty == 0) { i = FindSocket(&s, (int *)0, (int *)0, match); if (i == 0) Panic(0, "No screen session found."); if (i != 1) Panic(0, "Use -S to specify a session."); } else { #ifdef NAME_MAX if (strlen(sty) > NAME_MAX) sty[NAME_MAX] = 0; #endif if (strlen(sty) > 2 * MAXSTR - 1) sty[2 * MAXSTR - 1] = 0; sprintf(SockPath + strlen(SockPath), "/%s", sty); if ((s = MakeClientSocket(1)) == -1) exit(1); } bzero((char *)&m, sizeof(m)); m.type = query ? MSG_QUERY : MSG_COMMAND; if (attach_tty) { strncpy(m.m_tty, attach_tty, sizeof(m.m_tty) - 1); m.m_tty[sizeof(m.m_tty) - 1] = 0; } p = m.m.command.cmd; n = 0; for (; *av && n < MAXARGS - 1; ++av, ++n) { len = strlen(*av) + 1; if (p + len >= m.m.command.cmd + sizeof(m.m.command.cmd) - 1) break; strcpy(p, *av); p += len; } *p = 0; m.m.command.nargs = n; strncpy(m.m.attach.auser, LoginName, sizeof(m.m.attach.auser) - 1); m.m.command.auser[sizeof(m.m.command.auser) - 1] = 0; m.protocol_revision = MSG_REVISION; strncpy(m.m.command.preselect, preselect ? preselect : "", sizeof(m.m.command.preselect) - 1); m.m.command.preselect[sizeof(m.m.command.preselect) - 1] = 0; m.m.command.apid = getpid(); debug1("SendCommandMsg writing '%s'\n", m.m.command.cmd); if (query) { /* Create a server socket so we can get back the result */ char *sp = SockPath + strlen(SockPath); char query[] = "-queryX"; char c; int r = -1; for (c = 'A'; c <= 'Z'; c++) { query[6] = c; strcpy(sp, query); /* XXX: strncpy? */ if ((r = MakeServerSocket()) >= 0) break; } if (r < 0) { for (c = '0'; c <= '9'; c++) { query[6] = c; strcpy(sp, query); if ((r = MakeServerSocket()) >= 0) break; } } if (r < 0) Panic(0, "Could not create a listening socket to read the results."); strncpy(m.m.command.writeback, SockPath, sizeof(m.m.command.writeback) - 1); m.m.command.writeback[sizeof(m.m.command.writeback) - 1] = '\0'; /* Send the message, then wait for a response */ signal(SIGCONT, QueryResultSuccess); signal(SIG_BYE, QueryResultFail); if (WriteMessage(s, &m)) Msg(errno, "write"); close(s); while (!QueryResult) pause(); signal(SIGCONT, SIG_DFL); signal(SIG_BYE, SIG_DFL); /* Read the result and spit it out to stdout */ ReceiveRaw(r); unlink(SockPath); if (QueryResult == 2) /* An error happened */ exit(1); } else { if (WriteMessage(s, &m)) Msg(errno, "write"); close(s); } } screen-4.1.0/acls.c0000644000175000017500000006771711642704565012155 0ustar abeabe/* Copyright (c) 2008, 2009 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Micah Cowan (micah@cowan.name) * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net) * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Copyright (c) 1987 Oliver Laumann * * 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, 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 (see the file COPYING); if not, see * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA * **************************************************************** */ #include "config.h" #include /* XXX: WHY IS THIS HERE?? :XXX */ #ifdef CHECKLOGIN # ifdef _SEQUENT_ # include /* needed by */ # endif /* _SEQUENT_ */ # include # ifdef SHADOWPW # include # endif /* SHADOWPW */ #endif /* CHECKLOGIN */ #ifndef NOSYSLOG # include #endif #include "screen.h" /* includes acls.h */ #include "extern.h" /************************************************************************ * user managing code, this does not really belong into the acl stuff * ************************************************************************/ extern struct comm comms[]; extern struct win *windows, **wtab; extern char NullStr[]; extern char SockPath[]; extern struct display *display, *displays; struct acluser *users; #ifdef MULTIUSER int maxusercount = 0; /* used in process.c: RC_MONITOR, RC_SILENCE */ /* record given user ids here */ static AclBits userbits; /* * rights a new unknown user will have on windows and cmds. * These are changed by a "umask ?-..." command: */ static char default_w_bit[ACL_BITS_PER_WIN] = { 1, /* EXEC */ 1, /* WRITE */ 1 /* READ */ }; static char default_c_bit[ACL_BITS_PER_CMD] = { 0 /* EXEC */ }; /* rights of all users per newly created window */ /* * are now stored per user (umask) * static AclBits default_w_userbits[ACL_BITS_PER_WIN]; * static AclBits default_c_userbits[ACL_BITS_PER_CMD]; */ static int GrowBitfield __P((AclBits *, int, int, int)); static struct aclusergroup **FindGroupPtr __P((struct aclusergroup **, struct acluser *, int)); static int AclSetPermCmd __P((struct acluser *, char *, struct comm *)); static int AclSetPermWin __P((struct acluser *, struct acluser *, char *, struct win *)); static int UserAcl __P((struct acluser *, struct acluser **, int, char **)); static int UserAclCopy __P((struct acluser **, struct acluser **)); static int GrowBitfield(bfp, len, delta, defaultbit) AclBits *bfp; int len, delta, defaultbit; { AclBits n, o = *bfp; int i; if (!(n = (AclBits)calloc(1, (unsigned long)(&ACLBYTE((char *)0, len + delta + 1))))) return -1; for (i = 0; i < (len + delta); i++) { if (((i < len) && (ACLBIT(i) & ACLBYTE(o, i))) || ((i >= len) && (defaultbit))) ACLBYTE(n, i) |= ACLBIT(i); } if (len) free((char *)o); *bfp = n; return 0; } #endif /* MULTIUSER */ /* * Returns an nonzero Address. Its contents is either a User-ptr, * or NULL which may be replaced by a User-ptr to create the entry. */ struct acluser ** FindUserPtr(name) char *name; { struct acluser **u; for (u = &users; *u; u = &(*u)->u_next) if (!strcmp((*u)->u_name, name)) break; #ifdef MULTIUSER debug3("FindUserPtr %s %sfound, id %d\n", name, (*u)?"":"not ", (*u)?(*u)->u_id:-1); #else /* MULTIUSER */ debug2("FindUserPtr %s %sfound\n", name, (*u)?"":"not "); #endif /* MULTIUSER */ return u; } int DefaultEsc = -1; /* initialised by screen.c:main() */ int DefaultMetaEsc = -1; /* * Add a new user. His password may be NULL or "" if none. His name must not * be "none", as this represents the NULL-pointer when dealing with groups. * He has default rights, determined by umask. */ int UserAdd(name, pass, up) char *name, *pass; struct acluser **up; { #ifdef MULTIUSER int j; #endif if (!up) up = FindUserPtr(name); if (*up) { if (pass) (*up)->u_password = SaveStr(pass); return 1; /* he is already there */ } if (strcmp("none", name)) /* "none" is a reserved word */ *up = (struct acluser *)calloc(1, sizeof(struct acluser)); if (!*up) return -1; /* he still does not exist */ #ifdef COPY_PASTE (*up)->u_plop.buf = NULL; (*up)->u_plop.len = 0; # ifdef ENCODINGS (*up)->u_plop.enc = 0; # endif #endif (*up)->u_Esc = DefaultEsc; (*up)->u_MetaEsc = DefaultMetaEsc; strncpy((*up)->u_name, name, 20); (*up)->u_password = NULL; if (pass) (*up)->u_password = SaveStr(pass); if (!(*up)->u_password) (*up)->u_password = NullStr; (*up)->u_detachwin = -1; (*up)->u_detachotherwin = -1; #ifdef MULTIUSER (*up)->u_group = NULL; /* now find an unused index */ for ((*up)->u_id = 0; (*up)->u_id < maxusercount; (*up)->u_id++) if (!(ACLBIT((*up)->u_id) & ACLBYTE(userbits, (*up)->u_id))) break; debug2("UserAdd %s id %d\n", name, (*up)->u_id); if ((*up)->u_id == maxusercount) { int j; struct win *w; struct acluser *u; debug2("growing all bitfields %d += %d\n", maxusercount, USER_CHUNK); /* the bitfields are full, grow a chunk */ /* first, the used_uid_indicator: */ if (GrowBitfield(&userbits, maxusercount, USER_CHUNK, 0)) { free((char *)*up); *up = NULL; return -1; } /* second, default command bits */ /* (only if we generate commands dynamically) */ /* for (j = 0; j < ACL_BITS_PER_CMD; j++) if (GrowBitfield(&default_c_userbits[j], maxusercount, USER_CHUNK, default_c_bit[j])) { free((char *)*up); *up = NULL; return -1; } */ /* third, the bits for each commands */ for (j = 0; j <= RC_LAST; j++) { int i; for (i = 0; i < ACL_BITS_PER_CMD; i++) if (GrowBitfield(&comms[j].userbits[i], maxusercount, USER_CHUNK, default_c_bit[i])) { free((char *)*up); *up = NULL; return -1; } } /* fourth, default window creation bits per user */ for (u = users; u != *up; u = u->u_next) { for (j = 0; j < ACL_BITS_PER_WIN; j++) { if (GrowBitfield(&u->u_umask_w_bits[j], maxusercount, USER_CHUNK, default_w_bit[j])) { free((char *)*up); *up = NULL; return -1; } } } /* fifth, the bits for each window */ /* keep these in sync with NewWindowAcl() */ for (w = windows; w; w = w->w_next) { /* five a: the access control list */ for (j = 0; j < ACL_BITS_PER_WIN; j++) if (GrowBitfield(&w->w_userbits[j], maxusercount, USER_CHUNK, default_w_bit[j])) { free((char *)*up); *up = NULL; return -1; } /* five b: the activity notify list */ /* five c: the silence notify list */ if (GrowBitfield(&w->w_mon_notify, maxusercount, USER_CHUNK, 0) || GrowBitfield(&w->w_lio_notify, maxusercount, USER_CHUNK, 0)) { free((char *)*up); *up = NULL; return -1; } } maxusercount += USER_CHUNK; } /* mark the user-entry as "in-use" */ ACLBYTE(userbits, (*up)->u_id) |= ACLBIT((*up)->u_id); /* user id 0 is the session creator, he has all rights */ if ((*up)->u_id == 0) AclSetPerm(NULL, *up, "+a", "#?"); /* user nobody has a fixed set of rights: */ if (!strcmp((*up)->u_name, "nobody")) { AclSetPerm(NULL, *up, "-rwx", "#?"); AclSetPerm(NULL, *up, "+x", "su"); AclSetPerm(NULL, *up, "+x", "detach"); AclSetPerm(NULL, *up, "+x", "displays"); AclSetPerm(NULL, *up, "+x", "version"); } /* * Create his umask: * Give default_w_bit's for all users, * but allow himself everything on "his" windows. */ for (j = 0; j < ACL_BITS_PER_WIN; j++) { if (GrowBitfield(&(*up)->u_umask_w_bits[j], 0, maxusercount, default_w_bit[j])) { free((char *)*up); *up = NULL; return -1; } ACLBYTE((*up)->u_umask_w_bits[j], (*up)->u_id) |= ACLBIT((*up)->u_id); } #else /* MULTIUSER */ debug1("UserAdd %s\n", name); #endif /* MULTIUSER */ return 0; } #if 0 /* change user's password */ int UserSetPass(name, pass, up) char *name, *pass; struct acluser **up; { if (!up) up = FindUserPtr(name); if (!*up) return UserAdd(name, pass, up); if (!strcmp(name, "nobody")) /* he remains without password */ return -1; strncpy((*up)->u_password, pass ? pass : "", 20); (*up)->u_password[20] = '\0'; return 0; } #endif /* * Remove a user from the list. * Destroy all his permissions and completely detach him from the session. */ int UserDel(name, up) char *name; struct acluser **up; { struct acluser *u; #ifdef MULTIUSER int i; #endif struct display *old, *next; if (!up) up = FindUserPtr(name); if (!(u = *up)) return -1; /* he who does not exist cannot be removed */ old = display; for (display = displays; display; display = next) { next = display->d_next; /* read the next ptr now, Detach may zap it. */ if (D_user != u) continue; if (display == old) old = NULL; Detach(D_REMOTE); } display = old; *up = u->u_next; #ifdef MULTIUSER for (up = &users; *up; up = &(*up)->u_next) { /* unlink all group references to this user */ struct aclusergroup **g = &(*up)->u_group; while (*g) { if ((*g)->u == u) { struct aclusergroup *next = (*g)->next; free((char *)(*g)); *g = next; } else g = &(*g)->next; } } ACLBYTE(userbits, u->u_id) &= ~ACLBIT(u->u_id); /* restore the bits in his slot to default: */ AclSetPerm(NULL, u, default_w_bit[ACL_READ] ? "+r" : "-r", "#"); AclSetPerm(NULL, u, default_w_bit[ACL_WRITE]? "+w" : "-w", "#"); AclSetPerm(NULL, u, default_w_bit[ACL_EXEC] ? "+x" : "-x", "#"); AclSetPerm(NULL, u, default_c_bit[ACL_EXEC] ? "+x" : "-x", "?"); for (i = 0; i < ACL_BITS_PER_WIN; i++) free((char *)u->u_umask_w_bits[i]); #endif /* MULTIUSER */ debug1("FREEING user structure for %s\n", u->u_name); #ifdef COPY_PASTE UserFreeCopyBuffer(u); #endif free((char *)u); if (!users) { debug("Last user deleted. Feierabend.\n"); Finit(0); /* Destroying whole session. Noone could ever attach again. */ } return 0; } #ifdef COPY_PASTE /* * returns 0 if the copy buffer was really deleted. * Also removes any references into the users copybuffer */ int UserFreeCopyBuffer(u) struct acluser *u; { struct win *w; struct paster *pa; if (!u->u_plop.buf) return 1; for (w = windows; w; w = w->w_next) { pa = &w->w_paster; if (pa->pa_pasteptr >= u->u_plop.buf && pa->pa_pasteptr - u->u_plop.buf < u->u_plop.len) FreePaster(pa); } free((char *)u->u_plop.buf); u->u_plop.len = 0; u->u_plop.buf = 0; return 0; } #endif /* COPY_PASTE */ #ifdef MULTIUSER /* * Traverses group nodes. It searches for a node that references user u. * If recursive is true, nodes found in the users are also searched using * depth first method. If none of the nodes references u, the address of * the last next pointer is returned. This address will contain NULL. */ static struct aclusergroup ** FindGroupPtr(gp, u, recursive) struct aclusergroup **gp; struct acluser *u; int recursive; { struct aclusergroup **g; ASSERT(recursive < 1000); /* Ouch, cycle detection failed */ while (*gp) { if ((*gp)->u == u) return gp; /* found him here. */ if (recursive && *(g = FindGroupPtr(&(*gp)->u->u_group, u, recursive + 1))) return g; /* found him there. */ gp = &(*gp)->next; } return gp; /* *gp is NULL */ } /* * Returns nonzero if failed or already linked. * Both users are created on demand. * Cyclic links are prevented. */ int AclLinkUser(from, to) char *from, *to; { struct acluser **u1, **u2; struct aclusergroup **g; if (!*(u1 = FindUserPtr(from)) && UserAdd(from, NULL, u1)) return -1; if (!*(u2 = FindUserPtr(to)) && UserAdd(to, NULL, u2)) return -1; /* hmm, could not find both users. */ if (*FindGroupPtr(&(*u2)->u_group, *u1, 1)) return 1; /* cyclic link detected! */ if (*(g = FindGroupPtr(&(*u1)->u_group, *u2, 0))) return 2; /* aha, we are already linked! */ if (!(*g = (struct aclusergroup *)malloc(sizeof(struct aclusergroup)))) return -1; /* Could not alloc link. Poor screen */ (*g)->u = (*u2); (*g)->next = NULL; return 0; } /* * The user pointer stored at *up will be substituted by a pointer * to the named user's structure, if passwords match. * returns NULL if successfull, an static error string otherwise */ char * DoSu(up, name, pw1, pw2) struct acluser **up; char *name, *pw1, *pw2; { struct acluser *u; int sorry = 0; if (!(u = *FindUserPtr(name))) sorry++; else { #ifdef CHECKLOGIN struct passwd *pp; #ifdef SHADOWPW struct spwd *ss; int t, c; #endif char *pass = ""; if (!(pp = getpwnam(name))) { debug1("getpwnam(\"%s\") failed\n", name); if (!(pw1 && *pw1 && *pw1 != '\377')) { debug("no unix account, no screen passwd\n"); sorry++; } } else pass = pp->pw_passwd; #ifdef SHADOWPW for (t = 0; t < 13; t++) { c = pass[t]; if (!(c == '.' || c == '/' || (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))) break; } if (t < 13) { if (!(ss = getspnam(name))) { debug1("getspnam(\"%s\") failed\n", name); sorry++; } else pass = ss->sp_pwdp; } #endif /* SHADOWPW */ if (pw2 && *pw2 && *pw2 != '\377') /* provided a system password */ { if (!*pass || /* but needed none */ strcmp(crypt(pw2, pass), pass)) { debug("System password mismatch\n"); sorry++; } } else /* no pasword provided */ if (*pass) /* but need one */ sorry++; #endif if (pw1 && *pw1 && *pw1 != '\377') /* provided a screen password */ { if (!*u->u_password || /* but needed none */ strcmp(crypt(pw1, u->u_password), u->u_password)) { debug("screen password mismatch\n"); sorry++; } } else /* no pasword provided */ if (*u->u_password) /* but need one */ sorry++; } debug2("syslog(LOG_NOTICE, \"screen %s: \"su %s\" ", SockPath, name); debug2("%s for \"%s\"\n", sorry ? "failed" : "succeded", (*up)->u_name); #ifndef NOSYSLOG # ifdef BSD_42 openlog("screen", LOG_PID); # else openlog("screen", LOG_PID, LOG_AUTH); # endif /* BSD_42 */ syslog(LOG_NOTICE, "%s: \"su %s\" %s for \"%s\"", SockPath, name, sorry ? "failed" : "succeded", (*up)->u_name); closelog(); #else debug("NOT LOGGED.\n"); #endif /* NOSYSLOG */ if (sorry) return "Sorry."; else *up = u; /* substitute user now */ return NULL; } #endif /* MULTIUSER */ /************************************************************************ * end of user managing code * ************************************************************************/ #ifdef MULTIUSER /* This gives the users default rights to the new window w created by u */ int NewWindowAcl(w, u) struct win *w; struct acluser *u; { int i, j; debug2("NewWindowAcl %s's umask_w_bits for window %d\n", u ? u->u_name : "everybody", w->w_number); /* keep these in sync with UserAdd part five. */ if (GrowBitfield(&w->w_mon_notify, 0, maxusercount, 0) || GrowBitfield(&w->w_lio_notify, 0, maxusercount, 0)) return -1; for (j = 0; j < ACL_BITS_PER_WIN; j++) { /* we start with len 0 for the new bitfield size and add maxusercount */ if (GrowBitfield(&w->w_userbits[j], 0, maxusercount, 0)) { while (--j >= 0) free((char *)w->w_userbits[j]); free((char *)w->w_mon_notify); free((char *)w->w_lio_notify); return -1; } for (i = 0; i < maxusercount; i++) if (u ? (ACLBIT(i) & ACLBYTE(u->u_umask_w_bits[j], i)) : default_w_bit[j]) ACLBYTE(w->w_userbits[j], i) |= ACLBIT(i); } return 0; } void FreeWindowAcl(w) struct win *w; { int i; for (i = 0; i < ACL_BITS_PER_WIN; i++) free((char *)w->w_userbits[i]); free((char *)w->w_mon_notify); free((char *)w->w_lio_notify); } /* if mode starts with '-' we remove the users exec bit for cmd */ /* * NOTE: before you make this function look the same as * AclSetPermWin, try to merge both functions. */ static int AclSetPermCmd(u, mode, cmd) struct acluser *u; char *mode; struct comm *cmd; { int neg = 0; char *m = mode; while (*m) { switch (*m++) { case '-': neg = 1; continue; case '+': neg = 0; continue; case 'a': case 'e': case 'x': /* debug3("AclSetPermCmd %s %s %s\n", u->u_name, mode, cmd->name); */ if (neg) ACLBYTE(cmd->userbits[ACL_EXEC], u->u_id) &= ~ACLBIT(u->u_id); else ACLBYTE(cmd->userbits[ACL_EXEC], u->u_id) |= ACLBIT(u->u_id); break; case 'r': case 'w': break; default: return -1; } } return 0; } /* mode strings of the form +rwx -w+rx r -wx are parsed and evaluated */ /* * aclchg nerd -w+w 2 * releases a writelock on window 2 held by user nerd. * Letter n allows network access on a window. * uu should be NULL, except if you want to change his umask. */ static int AclSetPermWin(uu, u, mode, win) struct acluser *u, *uu; char *mode; struct win *win; { int neg = 0; int bit, bits; AclBits *bitarray; char *m = mode; if (uu) { debug3("AclSetPermWin %s UMASK %s %s\n", uu->u_name, u->u_name, mode); bitarray = uu->u_umask_w_bits; } else { ASSERT(win); bitarray = win->w_userbits; debug3("AclSetPermWin %s %s %d\n", u->u_name, mode, win->w_number); } while (*m) { switch (*m++) { case '-': neg = 1; continue; case '+': neg = 0; continue; case 'r': bits = (1 << ACL_READ); break; case 'w': bits = (1 << ACL_WRITE); break; case 'x': bits = (1 << ACL_EXEC); break; case 'a': bits = (1 << ACL_BITS_PER_WIN) - 1; break; default: return -1; } for (bit = 0; bit < ACL_BITS_PER_WIN; bit++) { if (!(bits & (1 << bit))) continue; if (neg) ACLBYTE(bitarray[bit], u->u_id) &= ~ACLBIT(u->u_id); else ACLBYTE(bitarray[bit], u->u_id) |= ACLBIT(u->u_id); if (!uu && (win->w_wlockuser == u) && neg && (bit == ACL_WRITE)) { debug2("%s lost writelock on win %d\n", u->u_name, win->w_number); win->w_wlockuser = NULL; if (win->w_wlock == WLOCK_ON) win->w_wlock = WLOCK_AUTO; } } } if (uu && u->u_name[0] == '?' && u->u_name[1] == '\0') { /* * It is Mr. '?', the unknown user. He deserves special treatment as * he defines the defaults. Sorry, this is global, not per user. */ if (win) { debug1("AclSetPermWin: default_w_bits '%s'.\n", mode); for (bit = 0; bit < ACL_BITS_PER_WIN; bit++) default_w_bit[bit] = (ACLBYTE(bitarray[bit], u->u_id) & ACLBIT(u->u_id)) ? 1 : 0; } else { /* * Hack. I do not want to duplicate all the above code for * AclSetPermCmd. This asumes that there are not more bits * per cmd than per win. */ debug1("AclSetPermWin: default_c_bits '%s'.\n", mode); for (bit = 0; bit < ACL_BITS_PER_CMD; bit++) default_c_bit[bit] = (ACLBYTE(bitarray[bit], u->u_id) & ACLBIT(u->u_id)) ? 1 : 0; } UserDel(u->u_name, NULL); } return 0; } /* * String is broken down into comand and window names, mode applies * A command name matches first, so do not use these as window names. * uu should be NULL, except if you want to change his umask. */ int AclSetPerm(uu, u, mode, s) struct acluser *uu, *u; char *mode, *s; { struct win *w; int i; char *p, ch; debug3("AclSetPerm(uu, user '%s', mode '%s', object '%s')\n", u->u_name, mode, s); while (*s) { switch (*s) { case '*': /* all windows and all commands */ return AclSetPerm(uu, u, mode, "#?"); case '#': if (uu) /* window umask or .. */ AclSetPermWin(uu, u, mode, (struct win *)1); else /* .. or all windows */ for (w = windows; w; w = w->w_next) AclSetPermWin((struct acluser *)0, u, mode, w); s++; break; case '?': if (uu) /* command umask or .. */ AclSetPermWin(uu, u, mode, (struct win *)0); else /* .. or all commands */ for (i = 0; i <= RC_LAST; i++) AclSetPermCmd(u, mode, &comms[i]); s++; break; default: for (p = s; *p && *p != ' ' && *p != '\t' && *p != ','; p++) ; if ((ch = *p)) *p++ = '\0'; if ((i = FindCommnr(s)) != RC_ILLEGAL) AclSetPermCmd(u, mode, &comms[i]); else if (((i = WindowByNoN(s)) >= 0) && wtab[i]) AclSetPermWin((struct acluser *)0, u, mode, wtab[i]); else /* checking group name */ return -1; if (ch) p[-1] = ch; s = p; } } return 0; } /* * Generic ACL Manager: * * This handles acladd and aclchg identical. * With 2 or 4 parameters, the second parameter is a password. * With 3 or 4 parameters the last two parameters specify the permissions * else user is added with full permissions. * With 1 parameter the users permissions are copied from user *argv. * Unlike the other cases, u->u_name should not match *argv here. * uu should be NULL, except if you want to change his umask. */ static int UserAcl(uu, u, argc, argv) struct acluser *uu, **u; int argc; char **argv; { if ((*u && !strcmp((*u)->u_name, "nobody")) || (argc > 1 && !strcmp(argv[0], "nobody"))) return -1; /* do not change nobody! */ switch (argc) { case 1+1+2: debug2("UserAcl: user '%s', password '%s':", argv[0], argv[1]); return (UserAdd(argv[0], argv[1], u) < 0) || AclSetPerm(uu, *u, argv[2], argv[3]); case 1+2: debug1("UserAcl: user '%s', no password:", argv[0]); return (UserAdd(argv[0], NULL, u) < 0) || AclSetPerm(uu, *u, argv[1], argv[2]); case 1+1: debug2("UserAcl: user '%s', password '%s'\n", argv[0], argv[1]); return UserAdd(argv[0], argv[1], u) < 0; case 1: debug1("UserAcl: user '%s', no password:", argv[0]); return (UserAdd(argv[0], NULL, u) < 0) || AclSetPerm(uu, *u, "+a", "#?"); default: return -1; } } static int UserAclCopy(to_up, from_up) struct acluser **to_up, **from_up; { struct win *w; int i, j, to_id, from_id; if (!*to_up || !*from_up) return -1; debug2("UserAclCopy: from user '%s' to user '%s'\n", (*from_up)->u_name, (*to_up)->u_name); if ((to_id = (*to_up)->u_id) == (from_id = (*from_up)->u_id)) return -1; for (w = windows; w; w = w->w_next) { for (i = 0; i < ACL_BITS_PER_WIN; i++) { if (ACLBYTE(w->w_userbits[i], from_id) & ACLBIT(from_id)) ACLBYTE(w->w_userbits[i], to_id) |= ACLBIT(to_id); else { ACLBYTE(w->w_userbits[i], to_id) &= ~ACLBIT(to_id); if ((w->w_wlockuser == *to_up) && (i == ACL_WRITE)) { debug2("%s lost wlock on win %d\n", (*to_up)->u_name, w->w_number); w->w_wlockuser = NULL; if (w->w_wlock == WLOCK_ON) w->w_wlock = WLOCK_AUTO; } } } } for (j = 0; j <= RC_LAST; j++) { for (i = 0; i < ACL_BITS_PER_CMD; i++) { if (ACLBYTE(comms[j].userbits[i], from_id) & ACLBIT(from_id)) ACLBYTE(comms[j].userbits[i], to_id) |= ACLBIT(to_id); else ACLBYTE(comms[j].userbits[i], to_id) &= ~ACLBIT(to_id); } } return 0; } /* * Syntax: * user [password] [+rwx #?] * * [password] [+rwx #?] * user1,user2,user3 [password] [+rwx #?] * user1,user2,user3=user * uu should be NULL, except if you want to change his umask. */ int UsersAcl(uu, argc, argv) struct acluser *uu; int argc; char **argv; { char *s; int r; struct acluser **cf_u = NULL; if (argc == 1) { char *p = NULL; s = argv[0]; while (*s) if (*s++ == '=') p = s; if (p) { p[-1] = '\0'; cf_u = FindUserPtr(p); } } if (argv[0][0] == '*' && argv[0][1] == '\0') { struct acluser **u; debug("all users acls.\n"); for (u = &users; *u; u = &(*u)->u_next) if (strcmp("nobody", (*u)->u_name) && ((cf_u) ? ((r = UserAclCopy(u, cf_u)) < 0) : ((r = UserAcl(uu, u, argc, argv)) < 0))) return -1; return 0; } do { for (s = argv[0]; *s && *s!=' ' && *s!='\t' && *s!=',' && *s!='='; s++) ; *s ? (*s++ = '\0') : (*s = '\0'); debug2("UsersAcl(uu, \"%s\", argc=%d)\n", argv[0], argc); if ((cf_u) ? ((r = UserAclCopy(FindUserPtr(argv[0]), cf_u)) < 0) : ((r = UserAcl(uu, FindUserPtr(argv[0]), argc, argv)) < 0)) return -1; } while (*(argv[0] = s)); return 0; } /* * Preprocess argments, so that umask can be set with UsersAcl * * all current users umask ±rwxn * one specific user umask user1±rwxn * several users umask user1,user2,...±rwxn * default_w_bits umask ?±rwxn * default_c_bits umask ??±rwxn */ int AclUmask(u, str, errp) struct acluser *u; char *str; char **errp; { char mode[16]; char *av[3]; char *p, c = '\0'; /* split str into user and bits section. */ for (p = str; *p; p++) if ((c = *p) == '+' || c == '-') break; if (!*p) { *errp = "Bad argument. Should be ``[user[,user...]{+|-}rwxn''."; return -1; } strncpy(mode, p, 15); mode[15] = '\0'; *p = '\0'; /* construct argument vector */ if (!strcmp("??", str)) { str++; av[2] = "?"; } else av[2] = "#"; av[1] = mode; av[0] = *str ? str : "*"; /* call UsersAcl */ if (UsersAcl(u, 3, av)) { *errp = "UsersAcl failed. Hmmm."; *p = c; return -1; } *p = c; return 0; } void AclWinSwap(a, b) int a, b; { debug2("AclWinSwap(%d, %d) NOP.\n", a, b); } struct acluser *EffectiveAclUser = NULL; /* hook for AT command permission */ int AclCheckPermWin(u, mode, w) struct acluser *u; int mode; struct win *w; { int ok; if (mode < 0 || mode >= ACL_BITS_PER_WIN) return -1; if (EffectiveAclUser) { debug1("AclCheckPermWin: WARNING user %s overridden!\n", u->u_name); u = EffectiveAclUser; } ok = ACLBYTE(w->w_userbits[mode], u->u_id) & ACLBIT(u->u_id); debug3("AclCheckPermWin(%s, %d, %d) = ", u->u_name, mode, w->w_number); if (!ok) { struct aclusergroup **g = &u->u_group; struct acluser *saved_eff = EffectiveAclUser; EffectiveAclUser = NULL; while (*g) { if (!AclCheckPermWin((*g)->u, mode, w)) break; g = &(*g)->next; } EffectiveAclUser = saved_eff; if (*g) ok = 1; } debug1("%d\n", !ok); return !ok; } int AclCheckPermCmd(u, mode, c) struct acluser *u; int mode; struct comm *c; { int ok; if (mode < 0 || mode >= ACL_BITS_PER_CMD) return -1; if (EffectiveAclUser) { debug1("AclCheckPermCmd: WARNING user %s overridden!\n", u->u_name); u = EffectiveAclUser; } ok = ACLBYTE(c->userbits[mode], u->u_id) & ACLBIT(u->u_id); debug3("AclCheckPermCmd(%s %d %s) = ", u->u_name, mode, c->name); if (!ok) { struct aclusergroup **g = &u->u_group; struct acluser *saved_eff = EffectiveAclUser; EffectiveAclUser = NULL; while (*g) { if (!AclCheckPermCmd((*g)->u, mode, c)) break; g = &(*g)->next; } EffectiveAclUser = saved_eff; if (*g) ok = 1; } debug1("%d\n", !ok); return !ok; } #endif /* MULTIUSER */ screen-4.1.0/sched.h0000644000175000017500000000327511642704565012313 0ustar abeabe/* Copyright (c) 2008, 2009 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Micah Cowan (micah@cowan.name) * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net) * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Copyright (c) 1987 Oliver Laumann * * 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, 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 (see the file COPYING); if not, see * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA * **************************************************************** * $Id$ GNU */ struct event { struct event *next; void (*handler) __P((struct event *, char *)); char *data; int fd; int type; int pri; struct timeval timeout; int queued; /* in evs queue */ int active; /* in fdset */ int *condpos; /* only active if condpos - condneg > 0 */ int *condneg; }; #define EV_TIMEOUT 0 #define EV_READ 1 #define EV_WRITE 2 #define EV_ALWAYS 3 screen-4.1.0/doc/0000755000175000017500000000000011732171240011576 5ustar abeabescreen-4.1.0/doc/FAQ0000644000175000017500000003340111642704565012145 0ustar abeabe jw 21.10.93 05.05.94 screen: frequently asked questions -- known problems -- unimplemented bugs =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Q: Why is it impossible to download a file with Kermit/sz/rz when screen is running? Do I need to set some special variables? A: Screen always interprets control-sequences sent by the applications and translates/optimizes them for the current terminal type. Screen always parses the user input for its escape character (CTRL-A). Both are basic screen features and cannot be switched off. Even if it were possible to switch screen into a completely transparent mode, you could never switch between windows, while kermit/sz/rz is downloading a file. You must wait til the end as kermit/sz/rz will not transmit your input during a file transfer and as kermit/sz/rz would be very confused if screen switched away the window containing the other kermit/sz/rz. Simply detach your screen session for each file transfer and start the transfer program only from the shell where you started screen. Q: I am using screen with a YYY terminal, which supports the XXX graphic language. I am very happy with it, except one thing: I cannot render graphics into screen windows. A: You are out of luck there. Screen provides a fixed set of escape sequences in order to make it possible to switch terminal types. Screen has to know exactly what the escape sequences do to the terminal because it must hold an image in memory. Otherwise screen could not restore the image if you switch to another window. Because of this you have to change screens escape sequence parser (ansi.c) to pass the XXX graphics sequences to the terminal. Of course the graphics will be lost if you switch to another window. Screen will only honour graphics sequences that are demanded by an overwhelming majority. Q: For some unknown reason, the fifo in /tmp/screens/S-myname is gone, and i can't resume my screen session. Is there a way to recreate the fifo? A: Screen checks the fifo/socket whenever it receives a SIGCHLD signal. If missing, the fifo/socket is recreated then. If screen is running non set-uid the user can issue a 'kill -CHLD screenpid' directly (it is -CHILD on some systems). Screenpid is the process-id of the screen process found in a 'ps -x' listing. But usually this won't work, as screen should be installed set- uid root. In this case you will not be able to send it a signal, but the kernel will. It does so, whenever a child of screen changes its state. Find the process-id (shellpid below) of the "least important" shell running inside screen. The try 'kill -STOP shellpid'. If the fifo/socket does not reappear, destroy the shell process. You sacrify one shell to save the rest. If nothing works, please do not forget to remove all processes running in the lost screen session. Q: When you start "screen" a page of text comes up to start you off. Is there a way to get rid of this text as a command line argument or by using a switch of some sort. A: Just put the following line in your ~/.screenrc: startup_message off Many peole ask this, although it is in the man page, too :-) Q: Start "screen emacs" and run emacs function suspend-emacs (ctrl-z). The window containing emacs vanishes. A: This is a known bug. Unfortunatly there is no easy fix because this is specified in the POSIX standard. When a new window is created Screen opens up a new session because the window has to get the pty as a controlling terminal (a session can only have one controlling terminal). With the setsid() call the process also creates a new process group. This process group is orphaned, because there is no process in the session which is not in the process group. Now if the process group leader (i.e. your program) gets a TTIN/TTOU/TSTP, POSIX states that the kernel must send a KILL signal to the process group because there is no one left to continue the process. Even if screen would try to restart the program, that would be after it received the KILL signal which cannot be caught or ignored. tromey@klab.caltech.edu (Tom Tromey): I've noticed this exact same problem. I put this in my .emacs file. It seems to work: ;; If running under screen, disable C-z. (if (and (getenv "STY") (not window-system)) (global-unset-key "\C-z")) Q: Screen gets the terminal size wrong and messes up. A: Before you start screen: Check with 'stty -a' what the terminal driver thinks about rows and columns. Check the environment variables LINES and COLUMNS. Then from within screen check with the info command (CTRL-A i) what size screen thinks your terminal is. If correcting tty driver setting and environment variables does not help, look up the terminal capability definition. First the TERMCAP environment variable. If this is not set, look up the terminals name as defined in the environment variable TERM in /etc/termcap or in the terminfo database with untic or infocmp. There may be :li=...: and :co=...: or even :ll=...: entries (cols#... and lines#... when it's terminfo) defined incorrectly. Either construct your own TERMCAP environment variables with correct settings, use screens terminfo/termcap command in your .screenrc file or have the database corrected by the system administrator. Q: Screen messes up the terminal output when I use my favourite ap- plication. Setting the terminal size does not help. A: Probably you got the termcap/terminfo entries wrong. Fixing this is a three stage procedure. First, find out if terminfo or termcap is used. If your system only has /etc/termcap, but not /usr/lib/terminfo/... then you are using termcap. Easy. But if your system has both, then it depends how the appli- cation and how screen were linked. Beware, if your applica- tion runs on another host via rlogin, telnet or the like, you should check the terminfo/termcap databases there. If you cannot tell if terminfo or termcap is used (or you just want to be save), the do all steps in stage 3 in parallel for both systems (on all envolved hosts). Second: Understand the basic rules how screen does its terminal emulation. When screen is started or reattached, it relies on the TERM environment variable to correctly reflect the terminal type you have physically in front of you. And the entry should either exist in the system terminfo/termcap database or be specified via the TERMCAP en- vironment variable (if screen is using the termcap system). On the other end, screen understands one set of control codes. It relies on the application using these codes. This means applica- tions that run under screen must be able to adapt their con- trol codes to screen. The application should use the TERM vari- able and termcap or terminfo library to find out how to drive its terminal. When running under screen, the terminal is virtual and is only defined by the set of control codes that screen understands. The TERM variable is automatically set to "screen" and the "screen"-entries should exist in the data- bases. If your application uses hardcoded control codes rather than a database, you are on your own. Hint: The codes under- stood by screen are a superset of the very common definition named "vt100". Look at the documentation of screen. The codes are listed there. Third: Have the entry "screen" in- stalled on all hosts or make sure you can live with "vt100". Check the codes sent by your application, when the TERM variable is set to "screen". Do not try to set the TERM variable inside screen to anything other than "screen" or "vt100" or compati- ble. Thus your application can drive screen correctly. Also take care that a good entry is installed for your physical terminal that screen has to drive. Even if the entry was good enough for your application to drive the terminal directly, screen may find flaws, as it tries to use other capabilities while op- timizing the screen output. The screenrc commands "termcap" and/or "terminfo" may help to fine-tune capabilities without calling the supervisor to change the database. Q: I cannot configure screen. Sed does not work. A: The regular expressions used in our configure scrip are too complicated for GNU sed version 2.03. In this regard it is bug compatible with Ultrix 3.1 "sed": GNU sed version 2.03 dumps core with our configure script. Try an older release. E.g. from ftp.uni-erlangen.de:/pub/utilities/screen/sed-2.02b.tar.gz Q: When reattaching a session from a different Workstation, the DISPLAY environment variable should be updated. Even ``CTLR-A : setenv DISPLAY newhost:0'' does not work as expected. A: Under unix every process has its own environment. The environ- ment of the SCREEN process can be changed with the `setenv' com- mand. This however cannot affect the environment of the shells or applications already running under screen. Subsequently spawned processes will reflect the changes. One should be aware of this problem when running applications from very old shells. Screen is a means for keeping processes alive. Q: About once every 5 times I ran the program, rather than getting a "screen," I got someone elses IRC output/input. A: What probably happened is that an IRC process was left running on a pseudo tty in such a way that the kernel thought the tty was available for reallocation. You can fix this behaviour by applying the SunOS 4.1.x tty jumbo patch (100513-04). Q: Screen compiled on SunOS 5.3 cannot reattach a detached session. A: You are using /usr/ucb/cc, this compiler is wrong. Actually it links with a C-library that mis-interprets dirent. Try again with /opt/SUNWspro/bin/cc! Q: The "talk" command does not work when Screen is active. A: Talk and several other programs rely on entries in the Utmp- Database (/etc/utmp). On some systems this Database is world writable, on others it is not. If it is not, screen must be installed with the appropriate permissions (user or group s-bit) just like any program that uses PTYs (rlogin, xterm, ...). When screen cannot write to utmp, you will see messages on you display which do not belong to any screen window. When screen can update utmp, it is not guaranteed that it does as you expect. First this depends on the config.h file defining UTMPOK, LOGINDEFAULT, and perhaps CAREFULUTMP. Second it depends on the screenrc files (system wide and per user), if utmp entries are done. Third, you can control whether windows are logged in with screens ``login'' command. Q: Seteuid() does not work as expected in AIX. Attempting a multi- user-attach results in a screen-panic: "seteuid: not owner". A: This is not a screen problem. According to Kay Nettle (pkn@cs.utexas.edu) you need the AIX patch PTF 423674. Q: When I type cd directory (any directory or just blank) from within one of the windows in screen, the whole thing just freezes up. A: You display the current working directory in xterm's title bar, This may be caused by hardcoded ESC-sequences in the shell prompt or in an cd alias. In Xterm the coding is ESC ] n ; string_to_display ^G where n = 1, 2, 3 selects the location of the displayed string. Screen misinterprets this as the ansi operating system comment sequence: ESC ] osc_string and waits (according to ansi) for the string terminator ESC \ Screen versions after 3.5.12 may provide a workaround. Q: Mesg or biff cannot be turned on or off while running screen. A: Screen failed to change the owner of the pty it uses. You need to install screen setuid-root. See the file INSTALL for details. Q: The cursor left key deletes the characters instead of just moving the cursor. A redisplay (^Al) brings everything back. A: Your terminal emulator treats the backspace as "destructive". You can probably change this somewhere in the setup. We can't think of a reason why anybody would want a destructive backspace, but if you really must have it, add the lines termcap 'bc@:bs@' terminfo 'bc@:bs@' to your ~/.screenrc (replace with the terminal type your emulator uses). Q: I have an old SysV OS (like Motorola SysV68) and sometimes screen doesn't reset the attributes correctly. A redisplay (^Al) doesn't make things better. A: The libcurses library has a bug if attributes are cleared with the special ue/se capabilities. As a workaround (other than upgrading your system) modify 'rmul' (and 'rmso'?) in screen's terminfo entry: rmul=\E[m, rmso=\E[m screen-4.1.0/doc/Makefile.in0000644000175000017500000000262011642704565013657 0ustar abeabe# Makefile for Screen documentation srcdir = @srcdir@ VPATH = @srcdir@ DESTDIR = prefix = @prefix@ datarootdir = @datarootdir@ mandir = @mandir@ infodir = @infodir@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ MAKEINFO = makeinfo TEXI2DVI = texi2dvi TEXI2PDF = texi2pdf SHELL = /bin/sh all: screen.info dvi screen.dvi: screen.texinfo mostlyclean $(TEXI2DVI) $(srcdir)/screen.texinfo pdf screen.pdf: screen.texinfo mostlyclean $(TEXI2PDF) $(srcdir)/screen.texinfo info screen.info: screen.texinfo @rm -f screen.info* $(MAKEINFO) $(srcdir)/screen.texinfo -o screen.info install: installdirs $(INSTALL_DATA) $(srcdir)/screen.1 $(DESTDIR)$(mandir)/man1/screen.1 -$(MAKE) screen.info -if test -f screen.info; then d=.; else d=$(srcdir); fi; \ if test -f $$d/screen.info; then \ for f in $$d/screen.info*; do $(INSTALL_DATA) $$f $(DESTDIR)$(infodir);done; \ if $(SHELL) -c 'install-info --version' >/dev/null 2>&1; then \ install-info --info-dir=$(DESTDIR)$(infodir) $$d/screen.info; \ else true; fi; \ fi uninstall: rm -f $(DESTDIR)$(mandir)/man1/screen.1 rm -f $(DESTDIR)$(infodir)/screen.info* installdirs: $(srcdir)/../etc/mkinstalldirs $(DESTDIR)$(mandir)/man1 $(DESTDIR)$(infodir) mostlyclean: -rm -f *.cp *.cps *.fn *.fns *.ky *.kys *.pg *.tp *.vr -rm -f *.log *.aux *.toc *~ clean distclean clobber: mostlyclean -rm -f *.dvi realclean: clean -rm -f *.info* check installcheck: screen-4.1.0/doc/README.DOTSCREEN0000644000175000017500000001445711642704565014032 0ustar abeabeFrom bargi@dots.physics.orst.edu Thu Aug 31 23:42 MET 1995 Received: from faui45.informatik.uni-erlangen.de (root@faui45.informatik.uni-erlangen.de [131.188.34.45]) by immd4.informatik.uni-erlangen.de with ESMTP id XAA14775 (8.6.12/7.4f-FAU);; Thu, 31 Aug 1995 23:42:15 +0200 Received: from dots.physics.orst.edu (bargi@dots.PHYSICS.ORST.EDU [128.193.96.106]) by uni-erlangen.de with ESMTP id XAA03048 (8.6.12/7.4f-FAU); for ; Thu, 31 Aug 1995 23:42:03 +0200 Received: (from bargi@localhost) by dots.physics.orst.edu (8.6.11/8.6.9) id OAA15627; Thu, 31 Aug 1995 14:41:47 -0700 From: Hadi Bargi Rangin Message-Id: <199508312141.OAA15627@dots.physics.orst.edu> Subject: README.DOTSCREEN To: screen@uni-erlangen.de Date: Thu, 31 Aug 1995 14:41:47 -0700 (PDT) Cc: bargi@dots.physics.orst.edu (Hadi Bargi Rangin) X-Mailer: ELM [version 2.4 PL24] MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=US-ASCII Content-Length: 5423 Status: RO Hallo, leider war readme file fuer dotscreen nicht in unserem dotscreen-Packet, deshalb schicke ich es Euch nachtraeglich. Nachdem Ihr unseren packet getestet habt, koennen wir Euch anrufen und vielleicht mehr ueber die Einzelnheiten sprechen, ob wir unsere Weiterentwicklung koordinieren wollen. Danke, Gruss, Hadi =============================================================================== Quick introduction to dotscreen ------------------------------- 1. Introduction 2. Is dotscreen different as screen? 3. Installation instructions 4. Functions description 5. Further development 1. Introduction =============== Dotscreen, is a system which allow a person direct access to unix via a braille display. The emphasis is on direct, because the braille display is connected directly to the serial port on the unix machine. You no longer must use a dos machine running a terminal emulation logged into a unix machine. Dotscreen is built on top of screen, a powerful full-screen window manager for unix tty terminals. Screen keeps track of what is being displayed in each window that it is managing so that it can easily switch back and forth between these windows. Dotscreen makes this stored window information available via a braille display. Dotscreen only allows access to tty terminal sessions, it does not allow access to X-Windows, however, it will run in an xterm window. Currently, it works with the TSI Navigator 40 and the TSI PowerBraille 40 braille displays. We plan to support other displays as demand and information about other displays is made available to us 2. Is dotscreen different than screen? ====================================== All of screens functions still work in dotscreen. A few of the functions are not accessible via braille, but we expect to remedy that in future releases. 3. Installation instructions ============================ Please read the INSTALL file for full installation instructions. In addition to those instructions, note that you must create a .screenrc file and that file must contain the type of braille display that you are using and the serial device that the display is connected to. A minimal .screenrc file should contain something like the following four lines, (these are only examples, please customize them for your configuration) # example of .screenrc when using braille display bd_start_braille on bd_type powerbraille_40 bd_port /dev/ttyS0 bd_braille_table /home/gardner/us-braille.tbl # end of example 4. Functions description ======================== The basic operation of screen is described in README. The braille navigation commands are similar to commands usually found on dos braille screenreaders. Also, because dotscreen is built on top of screen, the user can switch back and forth easily between many running applications. The braille commands can be changed any time after starting screen using the internal screen "C-a :" command line. All braille commands begin with "bd_"; following is the list of braille commands: bd_start_braille on/off # Starts/stops using braille features on screen bd_link on/off # links/unlinks braille cursor to/from screen cursor bd_bell on/off # turn on/off sending bell-signal to terminal bd_scroll on/off # enables/disables scrolling bd_skip on/off # skip/don't skip balnk lines bd_width # number of braille cells that user want to use, # this value is always <= total number of cells bd_ncrc # number of cells displayed on the right side # of physical cursor (default = 1) bd_info # displays braille/screen cursor position # depending on its value, (no info: 0, only # bc-info: 1, only sc-info: 2, bc- and sc-info: 3 bd_port # serial port which braille display is connected to bd_braille_table # braille table to be used. German, US and GS # braille tables are provided bd_type # braille display type being used Note: currently valid value for some parameters: bd_type: 1. navigator_40 2. powerbraille_40. bd_braille_table: 1. gr-braille.tbl German braille code 2. us-braille.tbl US computer braille code 3. gs-braille.tbl GS braille code Since the braille tables are in files, you should give the full pathnames of the files either in .screenrc or using the internal screen "C-a :" command line. 5. Further development ====================== As mentioned above, currently Dotscreen works with Telesensory braille displays the PowerBraille and the Navigator because Telesensory has given us the information needed to program their braille display. We plan to add support for other braille displays when and if we get the requisite information from the braille display manufacturer. Also some things such as cursor navigation from the braille display have not been implemented. If you find a feature missing that you wish to have, please contact us. This software has been developed within the Science Access Project at Oregon State University under the direction of John Gardner. Authors: Hadi Bargi Rangin (bargi@dots.physics.orst.edu) Bill Barry (barryb@dots.physics.orst.edu) screen-4.1.0/doc/screen.10000644000175000017500000047216011732171225013154 0ustar abeabe.\" vi:set wm=5 .TH SCREEN 1 "Aug 2003" .if n .ds Q \&" .if n .ds U \&" .if t .ds Q `` .if t .ds U '' .UC 4 .SH NAME screen \- screen manager with VT100/ANSI terminal emulation .SH SYNOPSIS .B screen [ .B \-\fIoptions\fP ] [ .B \fIcmd\fP [ .B \fIargs\fP ] ] .br .B screen \-r [[\fIpid\fP\fB.\fP]\fItty\fP[\fB.\fP\fIhost\fP]] .br .B screen \-r \fIsessionowner\fP\fB/\fP[[\fIpid\fP\fB.\fP]\fItty\fP[\fB.\fP\fIhost\fP]] .ta .5i 1.8i .SH DESCRIPTION .I Screen is a full-screen window manager that multiplexes a physical terminal between several processes (typically interactive shells). Each virtual terminal provides the functions of a DEC VT100 terminal and, in addition, several control functions from the ISO 6429 (ECMA 48, ANSI X3.64) and ISO 2022 standards (e.\|g. insert/delete line and support for multiple character sets). There is a scrollback history buffer for each virtual terminal and a copy-and-paste mechanism that allows moving text regions between windows. .PP When .I screen is called, it creates a single window with a shell in it (or the specified command) and then gets out of your way so that you can use the program as you normally would. Then, at any time, you can create new (full-screen) windows with other programs in them (including more shells), kill existing windows, view a list of windows, turn output logging on and off, copy-and-paste text between windows, view the scrollback history, switch between windows in whatever manner you wish, etc. All windows run their programs completely independent of each other. Programs continue to run when their window is currently not visible and even when the whole .I screen session is detached from the user's terminal. When a program terminates, .I screen (per default) kills the window that contained it. If this window was in the foreground, the display switches to the previous window; if none are left, .I screen exits. .PP Everything you type is sent to the program running in the current window. The only exception to this is the one keystroke that is used to initiate a command to the window manager. By default, each command begins with a control-a (abbreviated C-a from now on), and is followed by one other keystroke. The command character and all the key bindings can be fully customized to be anything you like, though they are always two characters in length. .PP .I Screen does not understand the prefix \*QC-\*U to mean control. Please use the caret notation (\*Q^A\*U instead of \*QC-a\*U) as arguments to e.g. the .I escape command or the \fI-e\fP option. .I Screen will also print out control characters in caret notation. .PP The standard way to create a new window is to type \*QC-a c\*U. This creates a new window running a shell and switches to that window immediately, regardless of the state of the process running in the current window. Similarly, you can create a new window with a custom command in it by first binding the command to a keystroke (in your .screenrc file or at the \*QC-a :\*U command line) and then using it just like the \*QC-a c\*U command. In addition, new windows can be created by running a command like: .IP screen emacs prog.c .PP from a shell prompt within a previously created window. This will not run another copy of .IR screen , but will instead supply the command name and its arguments to the window manager (specified in the $STY environment variable) who will use it to create the new window. The above example would start the emacs editor (editing prog.c) and switch to its window. - Note that you cannot transport environment variables from the invoking shell to the application (emacs in this case), because it is forked from the parent screen process, not from the invoking shell. .PP If \*Q/etc/utmp\*U is writable by .IR screen , an appropriate record will be written to this file for each window, and removed when the window is terminated. This is useful for working with \*Qtalk\*U, \*Qscript\*U, \*Qshutdown\*U, \*Qrsend\*U, \*Qsccs\*U and other similar programs that use the utmp file to determine who you are. As long as .I screen is active on your terminal, the terminal's own record is removed from the utmp file. See also \*QC-a L\*U. .SH GETTING STARTED Before you begin to use .I screen you'll need to make sure you have correctly selected your terminal type, just as you would for any other termcap/terminfo program. (You can do this by using .IR tset for example.) .PP If you're impatient and want to get started without doing a lot more reading, you should remember this one command: \*QC-a ?\*U. Typing these two characters will display a list of the available .I screen commands and their bindings. Each keystroke is discussed in the section \*QDEFAULT KEY BINDINGS\*U. The manual section \*QCUSTOMIZATION\*U deals with the contents of your .screenrc. .PP If your terminal is a \*Qtrue\*U auto-margin terminal (it doesn't allow the last position on the screen to be updated without scrolling the screen) consider using a version of your terminal's termcap that has automatic margins turned \fIoff\fP. This will ensure an accurate and optimal update of the screen in all circumstances. Most terminals nowadays have \*Qmagic\*U margins (automatic margins plus usable last column). This is the VT100 style type and perfectly suited for .IR screen . If all you've got is a \*Qtrue\*U auto-margin terminal .I screen will be content to use it, but updating a character put into the last position on the screen may not be possible until the screen scrolls or the character is moved into a safe position in some other way. This delay can be shortened by using a terminal with insert-character capability. .SH "COMMAND-LINE OPTIONS" Screen has the following command-line options: .TP 5 .B \-a include \fIall\fP capabilities (with some minor exceptions) in each window's termcap, even if .I screen must redraw parts of the display in order to implement a function. .TP 5 .B \-A Adapt the sizes of all windows to the size of the current terminal. By default, .I screen tries to restore its old window sizes when attaching to resizable terminals (those with \*QWS\*U in its description, e.g. suncmd or some xterm). .TP 5 .BI "\-c " file override the default configuration file from \*Q$HOME/.screenrc\*U to \fIfile\fP. .TP 5 .BR \-d | \-D " [" \fIpid.tty.host ] does not start .IR screen , but detaches the elsewhere running .I screen session. It has the same effect as typing \*QC-a d\*U from .IR screen 's controlling terminal. \fB\-D\fP is the equivalent to the power detach key. If no session can be detached, this option is ignored. In combination with the \fB\-r\fP/\fB\-R\fP option more powerful effects can be achieved: .TP 8 .B \-d \-r Reattach a session and if necessary detach it first. .TP 8 .B \-d \-R Reattach a session and if necessary detach or even create it first. .TP 8 .B \-d \-RR Reattach a session and if necessary detach or create it. Use the first session if more than one session is available. .TP 8 .B \-D \-r Reattach a session. If necessary detach and logout remotely first. .TP 8 .B \-D \-R Attach here and now. In detail this means: If a session is running, then reattach. If necessary detach and logout remotely first. If it was not running create it and notify the user. This is the author's favorite. .TP 8 .B \-D \-RR Attach here and now. Whatever that means, just do it. .IP "" 5 Note: It is always a good idea to check the status of your sessions by means of \*Qscreen \-list\*U. .TP 5 .BI "\-e " xy specifies the command character to be \fIx\fP and the character generating a literal command character to \fIy\fP (when typed after the command character). The default is \*QC-a\*U and `a', which can be specified as \*Q-e^Aa\*U. When creating a .I screen session, this option sets the default command character. In a multiuser session all users added will start off with this command character. But when attaching to an already running session, this option changes only the command character of the attaching user. This option is equivalent to either the commands \*Qdefescape\*U or \*Qescape\*U respectively. .TP 5 .BR \-f\fP ", " \-fn ", and " \-fa turns flow-control on, off, or \*Qautomatic switching mode\*U. This can also be defined through the \*Qdefflow\*U .screenrc command. .TP 5 .BI "\-h " num Specifies the history scrollback buffer to be \fInum\fP lines high. .TP 5 .B \-i will cause the interrupt key (usually C-c) to interrupt the display immediately when flow-control is on. See the \*Qdefflow\*U .screenrc command for details. The use of this option is discouraged. .TP 5 .BR \-l " and " \-ln turns login mode on or off (for /etc/utmp updating). This can also be defined through the \*Qdeflogin\*U .screenrc command. .TP 5 .BR \-ls " [" \fImatch ] .PD 0 .TP 5 .BR \-list " [" \fImatch ] .PD does not start .IR screen , but prints a list of .I pid.tty.host strings identifying your .I screen sessions. Sessions marked `detached' can be resumed with \*Qscreen -r\*U. Those marked `attached' are running and have a controlling terminal. If the session runs in multiuser mode, it is marked `multi'. Sessions marked as `unreachable' either live on a different host or are `dead'. An unreachable session is considered dead, when its name matches either the name of the local host, or the specified parameter, if any. See the \fB-r\fP flag for a description how to construct matches. Sessions marked as `dead' should be thoroughly checked and removed. Ask your system administrator if you are not sure. Remove sessions with the \fB-wipe\fP option. .TP 5 .B \-L tells .I screen to turn on automatic output logging for the windows. .TP 5 .B \-m causes .I screen to ignore the $STY environment variable. With \*Qscreen -m\*U creation of a new session is enforced, regardless whether .I screen is called from within another .I screen session or not. This flag has a special meaning in connection with the `-d' option: .TP 8 .B \-d \-m Start .I screen in \*Qdetached\*U mode. This creates a new session but doesn't attach to it. This is useful for system startup scripts. .TP 8 .B \-D \-m This also starts screen in \*Qdetached\*U mode, but doesn't fork a new process. The command exits if the session terminates. .TP 5 .B \-O selects a more optimal output mode for your terminal rather than true VT100 emulation (only affects auto-margin terminals without `LP'). This can also be set in your .screenrc by specifying `OP' in a \*Qtermcap\*U command. .TP 5 .BI "\-p " number_or_name|-|=|+ Preselect a window. This is useful when you want to reattach to a specific window or you want to send a command via the \*Q-X\*U option to a specific window. As with screen's select command, \*Q-\*U selects the blank window. As a special case for reattach, \*Q=\*U brings up the windowlist on the blank window, while a \*Q+\*U will create a new window. The command will not be executed if the specified window could not be found. .TP 5 .B \-q Suppress printing of error messages. In combination with \*Q-ls\*U the exit value is as follows: 9 indicates a directory without sessions. 10 indicates a directory with running but not attachable sessions. 11 (or more) indicates 1 (or more) usable sessions. In combination with \*Q-r\*U the exit value is as follows: 10 indicates that there is no session to resume. 12 (or more) indicates that there are 2 (or more) sessions to resume and you should specify which one to choose. In all other cases \*Q-q\*U has no effect. .TP 5 .B \-Q Some commands now can be queried from a remote session using this flag, e.g. 'screen -Q windows'. The commands will send the response to the stdout of the querying process. If there was an error in the command, then the querying process will exit with a non-zero status. The commands that can be queried now are: \fBecho\fP \fBinfo\fP \fBlastmsg\fP \fBnumber\fP \fBselect\fP \fBtime\fP \fBtitle\fP \fBwindows\fP .TP 5 .BR \-r " [" \fIpid.tty.host ] .PD 0 .TP 5 .BR \-r " \fIsessionowner/[" \fIpid.tty.host ] .PD resumes a detached .I screen session. No other options (except combinations with \fB\-d\fP/\fB\-D\fP) may be specified, though an optional prefix of [\fIpid.\fP]\fItty.host\fP may be needed to distinguish between multiple detached .I screen sessions. The second form is used to connect to another user's screen session which runs in multiuser mode. This indicates that screen should look for sessions in another user's directory. This requires setuid-root. .TP 5 .B \-R attempts to resume the first detached .I screen session it finds. If successful, all other command-line options are ignored. If no detached session exists, starts a new session using the specified options, just as if .B \-R had not been specified. The option is set by default if .I screen is run as a login-shell (actually screen uses \*Q-xRR\*U in that case). For combinations with the \fB\-d\fP/\fB\-D\fP option see there. .TP 5 .BI "\-s " program sets the default shell to the program specified, instead of the value in the environment variable $SHELL (or \*Q/bin/sh\*U if not defined). This can also be defined through the \*Qshell\*U .screenrc command. .TP 5 .BI "\-S " sessionname When creating a new session, this option can be used to specify a meaningful name for the session. This name identifies the session for \*Qscreen -list\*U and \*Qscreen -r\*U actions. It substitutes the default [\fItty.host\fP] suffix. .TP 5 .BI "\-t " name sets the title (a.\|k.\|a.) for the default shell or specified program. See also the \*Qshelltitle\*U .screenrc command. .TP 5 .BI "\-T " term Set the $TERM enviroment varible using the spcified term as opposed to the defualt setting of \fBscreen\fP. .TP 5 .B \-U Run screen in UTF-8 mode. This option tells screen that your terminal sends and understands UTF-8 encoded characters. It also sets the default encoding for new windows to `utf8'. .TP 5 .B \-v Print version number. .TP 5 .BR \-wipe " [" \fImatch ] does the same as \*Qscreen -ls\*U, but removes destroyed sessions instead of marking them as `dead'. An unreachable session is considered dead, when its name matches either the name of the local host, or the explicitly given parameter, if any. See the \fB-r\fP flag for a description how to construct matches. .TP 5 .B \-x Attach to a not detached .I screen session. (Multi display mode). .I Screen refuses to attach from within itself. But when cascading multiple screens, loops are not detected; take care. .TP 5 .B \-X Send the specified command to a running screen session. You can use the \fB-d\fP or \fB-r\fP option to tell screen to look only for attached or detached screen sessions. Note that this command doesn't work if the session is password protected. .SH "DEFAULT KEY BINDINGS" .ta 12n 26n As mentioned, each .I screen command consists of a \*QC-a\*U followed by one other character. For your convenience, all commands that are bound to lower-case letters are also bound to their control character counterparts (with the exception of \*QC-a a\*U; see below), thus, \*QC-a c\*U as well as \*QC-a C-c\*U can be used to create a window. See section \*QCUSTOMIZATION\*U for a description of the command. .PP .TP 26n The following table shows the default key bindings: .IP "\fBC-a '\fP (select)" Prompt for a window name or number to switch to. .IP "\fBC-a ""\fP (windowlist -b)" Present a list of all windows for selection. .IP "\fBC-a 0\fP (select 0)" .PD 0 .IP "\fB ... \fP ..." .IP "\fBC-a 9\fP (select 9)" .IP "\fBC-a -\fP (select -)" .PD Switch to window number 0 \- 9, or to the blank window. .IP "\fBC-a tab\fP (focus)" .PD Switch the input focus to the next region. See also \fIsplit, remove, only\fP. .IP "\fBC-a C-a\fP (other)" Toggle to the window displayed previously. Note that this binding defaults to the command character typed twice, unless overridden. For instance, if you use the option \*Q\fB\-e]x\fP\*U, this command becomes \*Q]]\*U. .IP "\fBC-a a\fP (meta)" Send the command character (C-a) to window. See \fIescape\fP command. .IP "\fBC-a A\fP (title)" Allow the user to enter a name for the current window. .IP "\fBC-a b\fP" .PD 0 .IP "\fBC-a C-b\fP (break)" .PD Send a break to window. .IP "\fBC-a B\fP (pow_break)" Reopen the terminal line and send a break. .IP "\fBC-a c\fP" .PD 0 .IP "\fBC-a C-c\fP (screen)" .PD Create a new window with a shell and switch to that window. .IP "\fBC-a C\fP (clear)" Clear the screen. .IP "\fBC-a d\fP" .PD 0 .IP "\fBC-a C-d\fP (detach)" .PD Detach .I screen from this terminal. .IP "\fBC-a D D\fP (pow_detach)" Detach and logout. .IP "\fBC-a f\fP" .PD 0 .IP "\fBC-a C-f\fP (flow)" .PD Toggle flow \fIon\fP, \fIoff\fP or \fIauto\fP. .IP "\fBC-a F\fP (fit)" Resize the window to the current region size. .IP "\fBC-a C-g\fP (vbell)" Toggles .I screen's visual bell mode. .IP "\fBC-a h\fP (hardcopy)" .PD Write a hardcopy of the current window to the file \*Qhardcopy.\fIn\fP\*U. .IP "\fBC-a H\fP (log)" Begins/ends logging of the current window to the file \*Qscreenlog.\fIn\fP\*U. .IP "\fBC-a i\fP" .PD 0 .IP "\fBC-a C-i\fP (info)" .PD Show info about this window. .IP "\fBC-a k\fP" .PD 0 .IP "\fBC-a C-k\fP (kill)" .PD Destroy current window. .IP "\fBC-a l\fP" .PD 0 .IP "\fBC-a C-l\fP (redisplay)" .PD Fully refresh current window. .IP "\fBC-a L\fP (login)" Toggle this windows login slot. Available only if .I screen is configured to update the utmp database. .IP "\fBC-a m\fP" .PD 0 .IP "\fBC-a C-m\fP (lastmsg)" .PD Repeat the last message displayed in the message line. .IP "\fBC-a M\fP (monitor)" Toggles monitoring of the current window. .IP "\fBC-a space\fP" .PD 0 .IP "\fBC-a n\fP" .IP "\fBC-a C-n\fP (next)" .PD Switch to the next window. .IP "\fBC-a N\fP (number)" Show the number (and title) of the current window. .IP "\fBC-a backspace\fP" .PD 0 .IP "\fBC-a h\fP" .IP "\fBC-a p\fP" .IP "\fBC-a C-p\fP (prev)" .PD Switch to the previous window (opposite of \fBC-a n\fP). .IP "\fBC-a q\fP" .PD 0 .IP "\fBC-a C-q\fP (xon)" .PD Send a control-q to the current window. .IP "\fBC-a Q\fP (only)" Delete all regions but the current one. See also \fIsplit, remove, focus\fP. .IP "\fBC-a r\fP" .PD 0 .IP "\fBC-a C-r\fP (wrap)" .PD Toggle the current window's line-wrap setting (turn the current window's automatic margins on and off). .IP "\fBC-a s\fP" .PD 0 .IP "\fBC-a C-s\fP (xoff)" .PD Send a control-s to the current window. .IP "\fBC-a S\fP (split)" Split the current region horizontally into two new ones. See also \fIonly, remove, focus\fP. .IP "\fBC-a t\fP" .PD 0 .IP "\fBC-a C-t\fP (time)" .PD Show system information. .IP "\fBC-a v\fP (version)" .PD Display the version and compilation date. .IP "\fBC-a C-v\fP (digraph)" .PD Enter digraph. .IP "\fBC-a w\fP" .PD 0 .IP "\fBC-a C-w\fP (windows)" .PD Show a list of window. .IP "\fBC-a W\fP (width)" Toggle 80/132 columns. .IP "\fBC-a x\fP" .PD 0 .IP "\fBC-a C-x\fP (lockscreen)" .PD Lock this terminal. .IP "\fBC-a X\fP (remove)" Kill the current region. See also \fIsplit, only, focus\fP. .IP "\fBC-a z\fP" .PD 0 .IP "\fBC-a C-z\fP (suspend)" .PD Suspend .IR screen . Your system must support BSD-style job-control. .IP "\fBC-a Z\fP (reset)" Reset the virtual terminal to its \*Qpower-on\*U values. .IP "\fBC-a .\fP (dumptermcap)" Write out a \*Q.termcap\*U file. .IP "\fBC-a ?\fP (help)" Show key bindings. .IP "\fBC-a C-\e\fP (quit)" Kill all windows and terminate .IR screen . .IP "\fBC-a :\fP (colon)" Enter command line mode. .IP "\fBC-a [\fP" .PD 0 .IP "\fBC-a C-[\fP" .IP "\fBC-a esc\fP (copy)" .PD Enter copy/scrollback mode. .IP "\fBC-a C-]\fP" .PD 0 .IP "\fBC-a ]\fP (paste .)" .PD Write the contents of the paste buffer to the stdin queue of the current window. .IP "\fBC-a {\fP .PD 0 .IP "\fBC-a }\fP (history)" .PD Copy and paste a previous (command) line. .IP "\fBC-a >\fP (writebuf)" Write paste buffer to a file. .IP "\fBC-a <\fP (readbuf)" Reads the screen-exchange file into the paste buffer. .IP "\fBC-a =\fP (removebuf)" Removes the file used by \fBC-a <\fP and \fPC-a >\fP. .IP "\fBC-a ,\fP (license)" Shows where .I screen comes from, where it went to and why you can use it. .IP "\fBC-a _\fP (silence)" Start/stop monitoring the current window for inactivity. .IP "\fBC-a |\fP (split -v)" Split the current region vertically into two new ones. .IP "\fBC-a *\fP (displays)" Show a listing of all currently attached displays. .SH CUSTOMIZATION The \*Qsocket directory\*U defaults either to $HOME/.screen or simply to /tmp/screens or preferably to /usr/local/screens chosen at compile-time. If .I screen is installed setuid-root, then the administrator should compile .I screen with an adequate (not NFS mounted) socket directory. If .I screen is not running setuid-root, the user can specify any mode 700 directory in the environment variable $SCREENDIR. .PP When .I screen is invoked, it executes initialization commands from the files \*Q/usr/local/etc/screenrc\*U and \*Q.screenrc\*U in the user's home directory. These are the \*Qprogrammer's defaults\*U that can be overridden in the following ways: for the global screenrc file .I screen searches for the environment variable $SYSSCREENRC (this override feature may be disabled at compile-time). The user specific screenrc file is searched in $SCREENRC, then $HOME/.screenrc. The command line option \fB-c\fP takes precedence over the above user screenrc files. .PP Commands in these files are used to set options, bind functions to keys, and to automatically establish one or more windows at the beginning of your .I screen session. Commands are listed one per line, with empty lines being ignored. A command's arguments are separated by tabs or spaces, and may be surrounded by single or double quotes. A `#' turns the rest of the line into a comment, except in quotes. Unintelligible lines are warned about and ignored. Commands may contain references to environment variables. The syntax is the shell-like "$VAR " or "${VAR}". Note that this causes incompatibility with previous .I screen versions, as now the '$'-character has to be protected with '\e' if no variable substitution shall be performed. A string in single-quotes is also protected from variable substitution. .PP Two configuration files are shipped as examples with your screen distribution: \*Qetc/screenrc\*U and \*Qetc/etcscreenrc\*U. They contain a number of useful examples for various commands. .PP Customization can also be done 'on-line'. To enter the command mode type `C-a :'. Note that commands starting with \*Qdef\*U change default values, while others change current settings. .PP The following commands are available: .sp .ne 3 .BI acladd " usernames" .RI [ crypted-pw ] .br .BI addacl " usernames" .PP Enable users to fully access this screen session. \fIUsernames\fP can be one user or a comma separated list of users. This command enables to attach to the .I screen session and performs the equivalent of `aclchg \fIusernames\fP +rwx \&"#?\&"'. executed. To add a user with restricted access, use the `aclchg' command below. If an optional second parameter is supplied, it should be a crypted password for the named user(s). `Addacl' is a synonym to `acladd'. Multi user mode only. .sp .ne 3 .BI aclchg " usernames permbits list" .br .BI chacl " usernames permbits list" .PP Change permissions for a comma separated list of users. Permission bits are represented as `r', `w' and `x'. Prefixing `+' grants the permission, `-' removes it. The third parameter is a comma separated list of commands and/or windows (specified either by number or title). The special list `#' refers to all windows, `?' to all commands. if \fIusernames\fP consists of a single `*', all known users are affected. A command can be executed when the user has the `x' bit for it. The user can type input to a window when he has its `w' bit set and no other user obtains a writelock for this window. Other bits are currently ignored. To withdraw the writelock from another user in window 2: `aclchg \fIusername\fP -w+w 2'. To allow read-only access to the session: `aclchg \fIusername\fP -w \&"#\&"'. As soon as a user's name is known to .I screen he can attach to the session and (per default) has full permissions for all command and windows. Execution permission for the acl commands, `at' and others should also be removed or the user may be able to regain write permission. Rights of the special username .B nobody cannot be changed (see the \*Qsu\*U command). `Chacl' is a synonym to `aclchg'. Multi user mode only. .sp .ne 3 .BI acldel " username" .PP Remove a user from .IR screen 's access control list. If currently attached, all the user's displays are detached from the session. He cannot attach again. Multi user mode only. .sp .ne 3 .BI aclgrp " username" .RI [ groupname ] .PP Creates groups of users that share common access rights. The name of the group is the username of the group leader. Each member of the group inherits the permissions that are granted to the group leader. That means, if a user fails an access check, another check is made for the group leader. A user is removed from all groups the special value \*Qnone\*U is used for .IR groupname . If the second parameter is omitted all groups the user is in are listed. .sp .ne 3 .B aclumask .RI [[ users ] +bits .RI |[ users ] -bits " .... ]" .br .B umask .RI [[ users ] +bits .RI |[ users ] -bits " .... ]" .PP This specifies the access other users have to windows that will be created by the caller of the command. .I Users may be no, one or a comma separated list of known usernames. If no users are specified, a list of all currently known users is assumed. .I Bits is any combination of access control bits allowed defined with the \*Qaclchg\*U command. The special username \*Q?\*U predefines the access that not yet known users will be granted to any window initially. The special username \*Q??\*U predefines the access that not yet known users are granted to any command. Rights of the special username .B nobody cannot be changed (see the \*Qsu\*U command). `Umask' is a synonym to `aclumask'. .sp .ne 3 .BI activity " message" .PP When any activity occurs in a background window that is being monitored, .I screen displays a notification in the message line. The notification message can be re-defined by means of the \*Qactivity\*U command. Each occurrence of `%' in \fImessage\fP is replaced by the number of the window in which activity has occurred, and each occurrence of `^G' is replaced by the definition for bell in your termcap (usually an audible bell). The default message is .sp 'Activity in window %n' .sp Note that monitoring is off for all windows by default, but can be altered by use of the \*Qmonitor\*U command (C-a M). .sp .ne 3 .BR "allpartial on" | off .PP If set to on, only the current cursor line is refreshed on window change. This affects all windows and is useful for slow terminal lines. The previous setting of full/partial refresh for each window is restored with \*Qallpartial off\*U. This is a global flag that immediately takes effect on all windows overriding the \*Qpartial\*U settings. It does not change the default redraw behavior of newly created windows. .sp .ne 3 .BR "altscreen on" | off .PP If set to on, "alternate screen" support is enabled in virtual terminals, just like in xterm. Initial setting is `off'. .sp .ne 3 .BR "at " "[\fIidentifier\fP][" "#\fP|\fP*\fP|\fP%\fP] " .IR "command " [ args " ... ]" .PP Execute a command at other displays or windows as if it had been entered there. \*QAt\*U changes the context (the `current window' or `current display' setting) of the command. If the first parameter describes a non-unique context, the command will be executed multiple times. If the first parameter is of the form `\fIidentifier\fP*' then identifier is matched against user names. The command is executed once for each display of the selected user(s). If the first parameter is of the form `\fIidentifier\fP%' identifier is matched against displays. Displays are named after the ttys they attach. The prefix `/dev/' or `/dev/tty' may be omitted from the identifier. If \fIidentifier\fP has a `#' or nothing appended it is matched against window numbers and titles. Omitting an identifier in front of the `#', `*' or `%'-character selects all users, displays or windows because a prefix-match is performed. Note that on the affected display(s) a short message will describe what happened. Permission is checked for initiator of the \*Qat\*U command, not for the owners of the affected display(s). Note that the '#' character works as a comment introducer when it is preceded by whitespace. This can be escaped by prefixing a '\e'. Permission is checked for the initiator of the \*Qat\*U command, not for the owners of the affected display(s). .br Caveat: When matching against windows, the command is executed at least once per window. Commands that change the internal arrangement of windows (like \*Qother\*U) may be called again. In shared windows the command will be repeated for each attached display. Beware, when issuing toggle commands like \*Qlogin\*U! Some commands (e.g. \*Qprocess\*U) require that a display is associated with the target windows. These commands may not work correctly under \*Qat\*U looping over windows. .sp .ne 3 .BI "attrcolor " attrib .RI [ "attribute/color-modifier" ] .PP This command can be used to highlight attributes by changing the color of the text. If the attribute .I attrib is in use, the specified attribute/color modifier is also applied. If no modifier is given, the current one is deleted. See the \*QSTRING ESCAPES\*U chapter for the syntax of the modifier. Screen understands two pseudo-attributes, \*Qi\*U stands for high-intensity foreground color and \*QI\*U for high-intensity background color. .sp Examples: .IP attrcolor b "R" .PP Change the color to bright red if bold text is to be printed. .IP attrcolor u "-u b" .PP Use blue text instead of underline. .IP attrcolor b ".I" .PP Use bright colors for bold text. Most terminal emulators do this already. .IP attrcolor i "+b" .PP Make bright colored text also bold. .sp .ne 3 .BR "autodetach on" | off .PP Sets whether .I screen will automatically detach upon hangup, which saves all your running programs until they are resumed with a .B "screen -r" command. When turned off, a hangup signal will terminate .I screen and all the processes it contains. Autodetach is on by default. .sp .ne 3 .BR "autonuke on" | off .PP Sets whether a clear screen sequence should nuke all the output that has not been written to the terminal. See also \*Qobuflimit\*U. .sp .ne 3 .BI "backtick " id .I lifespan .I autorefresh .I cmd .I args... .br .BI "backtick " id .PP Program the backtick command with the numerical id \fIid\fP. The output of such a command is used for substitution of the \*Q%`\*U string escape. The specified \fIlifespan\fP is the number of seconds the output is considered valid. After this time, the command is run again if a corresponding string escape is encountered. The \fIautorefresh\fP parameter triggers an automatic refresh for caption and hardstatus strings after the specified number of seconds. Only the last line of output is used for substitution. .br If both the \fIlifespan\fP and the \fIautorefresh\fP parameters are zero, the backtick program is expected to stay in the background and generate output once in a while. In this case, the command is executed right away and screen stores the last line of output. If a new line gets printed screen will automatically refresh the hardstatus or the captions. .br The second form of the command deletes the backtick command with the numerical id \fIid\fP. .sp .ne 3 .BR "bce " [ on | off ] .PP Change background-color-erase setting. If \*Qbce\*U is set to on, all characters cleared by an erase/insert/scroll/clear operation will be displayed in the current background color. Otherwise the default background color is used. .sp .ne 3 .B bell_msg .RI [ message ] .PP When a bell character is sent to a background window, .I screen displays a notification in the message line. The notification message can be re-defined by this command. Each occurrence of `%' in \fImessage\fP is replaced by the number of the window to which a bell has been sent, and each occurrence of `^G' is replaced by the definition for bell in your termcap (usually an audible bell). The default message is .sp 'Bell in window %n' .sp An empty message can be supplied to the \*Qbell_msg\*U command to suppress output of a message line (bell_msg ""). Without parameter, the current message is shown. .sp .ne 3 .BI "bind " .RB [ -c .IR class ] .I key .RI [ command " [" args ]] .PP Bind a command to a key. By default, most of the commands provided by .I screen are bound to one or more keys as indicated in the \*QDEFAULT KEY BINDINGS\*U section, e.\|g. the command to create a new window is bound to \*QC-c\*U and \*Qc\*U. The \*Qbind\*U command can be used to redefine the key bindings and to define new bindings. The \fIkey\fP argument is either a single character, a two-character sequence of the form \*Q^x\*U (meaning \*QC-x\*U), a backslash followed by an octal number (specifying the ASCII code of the character), or a backslash followed by a second character, such as \*Q\e^\*U or \*Q\e\e\*U. The argument can also be quoted, if you like. If no further argument is given, any previously established binding for this key is removed. The \fIcommand\fP argument can be any command listed in this section. If a command class is specified via the \*Q-c\*U option, the key is bound for the specified class. Use the \*Qcommand\*U command to activate a class. Command classes can be used to create multiple command keys or multi-character bindings. .PP Some examples: .PP .nf bind ' ' windows bind ^k bind k bind K kill bind ^f screen telnet foobar bind \e033 screen -ln -t root -h 1000 9 su .fi .PP would bind the space key to the command that displays a list of windows (so that the command usually invoked by \*QC-a C-w\*U would also be available as \*QC-a space\*U). The next three lines remove the default kill binding from \*QC-a C-k\*U and \*QC-a k\*U. \*QC-a K\*U is then bound to the kill command. Then it binds \*QC-f\*U to the command \*Qcreate a window with a TELNET connection to foobar\*U, and bind \*Qescape\*U to the command that creates an non-login window with a.\|k.\|a. \*Qroot\*U in slot #9, with a superuser shell and a scrollback buffer of 1000 lines. .PP .nf bind -c demo1 0 select 10 bind -c demo1 1 select 11 bind -c demo1 2 select 12 bindkey "^B" command -c demo1 .fi .PP makes \*QC-b 0\*U select window 10, \*QC-b 1\*U window 11, etc. .PP .nf bind -c demo2 0 select 10 bind -c demo2 1 select 11 bind -c demo2 2 select 12 bind - command -c demo2 .fi .PP makes \*QC-a - 0\*U select window 10, \*QC-a - 1\*U window 11, etc. .sp .ne 3 .B bindkey .RB [ -d ] .RB [ -m ] .RB [ -a ] .RB [[ -k | -t ] .I string .RI [ "cmd args" ]] .PP This command manages screen's input translation tables. Every entry in one of the tables tells screen how to react if a certain sequence of characters is encountered. There are three tables: one that should contain actions programmed by the user, one for the default actions used for terminal emulation and one for screen's copy mode to do cursor movement. See section \*QINPUT TRANSLATION\*U for a list of default key bindings. .br If the .B -d option is given, bindkey modifies the default table, .B -m changes the copy mode table and with neither option the user table is selected. The argument .I string is the sequence of characters to which an action is bound. This can either be a fixed string or a termcap keyboard capability name (selectable with the .B -k option). .br Some keys on a VT100 terminal can send a different string if application mode is turned on (e.g the cursor keys). Such keys have two entries in the translation table. You can select the application mode entry by specifying the .B -a option. .br The .B -t option tells screen not to do inter-character timing. One cannot turn off the timing if a termcap capability is used. .br .I Cmd can be any of screen's commands with an arbitrary number of .IR args . If .I cmd is omitted the key-binding is removed from the table. .br Here are some examples of keyboard bindings: .sp .nf bindkey -d .fi Show all of the default key bindings. The application mode entries are marked with [A]. .sp .nf bindkey -k k1 select 1 .fi Make the "F1" key switch to window one. .sp .nf bindkey -t foo stuff barfoo .fi Make "foo" an abbreviation of the word "barfoo". Timeout is disabled so that users can type slowly. .sp .nf bindkey "\e024" mapdefault .fi This key-binding makes \*Q^T\*U an escape character for key-bindings. If you did the above \*Qstuff barfoo\*U binding, you can enter the word \*Qfoo\*U by typing \*Q^Tfoo\*U. If you want to insert a \*Q^T\*U you have to press the key twice (i.e., escape the escape binding). .sp .nf bindkey -k F1 command .fi Make the F11 (not F1!) key an alternative screen escape (besides ^A). .sp .ne 3 .B break .RI [ duration ] .PP Send a break signal for \fIduration\fP*0.25 seconds to this window. For non-Posix systems the time interval may be rounded up to full seconds. Most useful if a character device is attached to the window rather than a shell process (See also chapter \*QWINDOW TYPES\*U). The maximum duration of a break signal is limited to 15 seconds. .sp .ne 3 .B blanker .PP Activate the screen blanker. First the screen is cleared. If no blanker program is defined, the cursor is turned off, otherwise, the program is started and it's output is written to the screen. The screen blanker is killed with the first keypress, the read key is discarded. .br This command is normally used together with the \*Qidle\*U command. .sp .ne 3 .B blankerprg .RI [ "program args" ] .PP Defines a blanker program. Disables the blanker program if an empty argument is given. Shows the currently set blanker program if no arguments are given. .sp .ne 3 .B breaktype .RI [ tcsendbreak | TIOCSBRK .RI | TCSBRK ] .PP Choose one of the available methods of generating a break signal for terminal devices. This command should affect the current window only. But it still behaves identical to \*Qdefbreaktype\*U. This will be changed in the future. Calling \*Qbreaktype\*U with no parameter displays the break method for the current window. .sp .ne 3 .B bufferfile .RI [ exchange-file ] .PP Change the filename used for reading and writing with the paste buffer. If the optional argument to the \*Qbufferfile\*U command is omitted, the default setting (\*Q/tmp/screen-exchange\*U) is reactivated. The following example will paste the system's password file into the .I screen window (using the paste buffer, where a copy remains): .PP .nf C-a : bufferfile /etc/passwd C-a < C-a ] C-a : bufferfile .fi .sp .ne 3 .BR "c1 " [ on | off ] .PP Change c1 code processing. \*QC1 on\*U tells screen to treat the input characters between 128 and 159 as control functions. Such an 8-bit code is normally the same as ESC followed by the corresponding 7-bit code. The default setting is to process c1 codes and can be changed with the \*Qdefc1\*U command. Users with fonts that have usable characters in the c1 positions may want to turn this off. .sp .ne 3 .BR "caption always" | splitonly .RI [ string ] .br .B "caption string" .RI [ string ] .PP This command controls the display of the window captions. Normally a caption is only used if more than one window is shown on the display (split screen mode). But if the type is set to .B always screen shows a caption even if only one window is displayed. The default is .BR splitonly . .P The second form changes the text used for the caption. You can use all escapes from the \*QSTRING ESCAPES\*U chapter. Screen uses a default of `%3n %t'. .P You can mix both forms by providing a string as an additional argument. .sp .ne 3 .BI "charset " set .PP Change the current character set slot designation and charset mapping. The first four character of .I set are treated as charset designators while the fifth and sixth character must be in range '0' to '3' and set the GL/GR charset mapping. On every position a '.' may be used to indicate that the corresponding charset/mapping should not be changed (\fIset\fP is padded to six characters internally by appending '.' chars). New windows have "BBBB02" as default charset, unless a \*Qencoding\*U command is active. .br The current setting can be viewed with the \*Qinfo\*U command. .sp .ne 3 .B chdir .RI [ directory ] .PP Change the \fIcurrent directory\fP of .I screen to the specified directory or, if called without an argument, to your home directory (the value of the environment variable $HOME). All windows that are created by means of the \*Qscreen\*U command from within \*Q.screenrc\*U or by means of \*QC-a : screen ...\*U or \*QC-a c\*U use this as their default directory. Without a chdir command, this would be the directory from which .I screen was invoked. Hardcopy and log files are always written to the \fIwindow's\fP default directory, \fInot\fP the current directory of the process running in the window. You can use this command multiple times in your .screenrc to start various windows in different default directories, but the last chdir value will affect all the windows you create interactively. .sp .ne 3 .B clear .PP Clears the current window and saves its image to the scrollback buffer. .sp .ne 3 .B colon .RI [ prefix ] .PP Allows you to enter \*Q.screenrc\*U command lines. Useful for on-the-fly modification of key bindings, specific window creation and changing settings. Note that the \*Qset\*U keyword no longer exists! Usually commands affect the current window rather than default settings for future windows. Change defaults with commands starting with 'def...'. If you consider this as the `Ex command mode' of .IR screen , you may regard \*QC-a esc\*U (copy mode) as its `Vi command mode'. .sp .ne 3 .B command .RB [ -c .IR class ] .PP This command has the same effect as typing the screen escape character (^A). It is probably only useful for key bindings. If the \*Q-c\*U option is given, select the specified command class. See also \*Qbind\*U and \*Qbindkey\*U. .sp .ne 3 .BR "compacthist " [ on | off ] .PP This tells screen whether to suppress trailing blank lines when scrolling up text into the history buffer. .sp .ne 3 .BR "console " [ on | off ] .PP Grabs or un-grabs the machines console output to a window. .IR Note : Only the owner of /dev/console can grab the console output. This command is only available if the machine supports the ioctl TIOCCONS. .sp .ne 3 .B copy .PP Enter copy/scrollback mode. This allows you to copy text from the current window and its history into the paste buffer. In this mode a vi-like `full screen editor' is active: .br .IR "Movement keys" : .br .in +4n .ti -2n \fBh\fP, \fBC-h\fP, or \fBleft arrow\fP move the cursor left. .br .ti -2n \fBj\fP, \fBC-n\fP, or \fBdown arrow\fP move the cursor down. .br .ti -2n \fBk\fP, \fBC-p\fP, or \fBup arrow\fP move the cursor up. .br .ti -2n \fBl\fP ('el') or \fBright arrow\fP move the cursor right. .br .ti -2n \fB0\fP (zero) or \fBC-a\fP move to the leftmost column. .br .ti -2n \fB+\fP and \fB\-\fP positions one line up and down. .br .ti -2n \fBH\fP, \fBM\fP and \fBL\fP move the cursor to the leftmost column of the top, center or bottom line of the window. .br .ti -2n \fB|\fP moves to the specified absolute column. .br .ti -2n \fBg\fP or \fBhome\fP moves to the beginning of the buffer. .br .ti -2n \fBG\fP or \fBend\fP moves to the specified absolute line (default: end of buffer). .br .ti -2n \fB%\fP jumps to the specified percentage of the buffer. .br .ti -2n \fB^\fP or \fB$\fP move to the leftmost column, to the first or last non-whitespace character on the line. .br .ti -2n \fBw\fP, \fBb\fP, and \fBe\fP move the cursor word by word. .br .ti -2n \fBB\fP, \fBE\fP move the cursor WORD by WORD (as in vi). .br .ti -2n .\"\fBf\fP,\fBt\fP, \fBF\fP, \fBT\fP move the cursor forward/backward to the next occurence of the target. \fBf/F\fP, \fBt/T\fP move the cursor forward/backward to the next occurence of the target. (eg, '3fy' will move the cursor to the 3rd 'y' to the right.) .br .ti -2n \fB;\fP and \fB,\fP Repeat the last f/F/t/T command in the same/opposite direction. .br .ti -2n \fBC-e\fP and \fBC-y\fP scroll the display up/down by one line while preserving the cursor position. .br .ti -2n \fBC-u\fP and \fBC-d\fP scroll the display up/down by the specified amount of lines while preserving the cursor position. (Default: half screen-full). .br .ti -2n \fBC-b\fP and \fBC-f\fP scroll the display up/down a full screen. .br .ti -4n .IR Note : .br Emacs style movement keys can be customized by a .screenrc command. (E.\|g. markkeys "h=^B:l=^F:$=^E") There is no simple method for a full emacs-style keymap, as this involves multi-character codes. .br .ti -4n .IR Marking : .br The copy range is specified by setting two marks. The text between these marks will be highlighted. Press: .br .ti -2n \fBspace\fP or \fBenter\fP to set the first or second mark respectively. If \fBmousetrack\fP is set to `on', marks can also be set using \fPleft mouse click\fP. .br .ti -2n \fBY\fP and \fBy\fP used to mark one whole line or to mark from start of line. .br .ti -2n \fBW\fP marks exactly one word. .br .ti -4n .IR "Repeat count" : .br Any of these commands can be prefixed with a repeat count number by pressing digits .br .ti -2n \fB0\fP..\fB9\fP which is taken as a repeat count. .br Example: \*QC-a C-[ H 10 j 5 Y\*U will copy lines 11 to 15 into the paste buffer. .br .ti -4n .IR Searching : .ti -2n \fB/\fP \fIVi\fP-like search forward. .ti -2n \fB?\fP \fIVi\fP-like search backward. .ti -2n \fBC-a s\fP \fIEmacs\fP style incremental search forward. .ti -2n \fBC-r\fP \fIEmacs\fP style reverse i-search. .ti -2n \fBn\fP Find next search pattern. .ti -2n \fBN\fP Find previous search pattern. .ti -4n .IR Specials : .br There are however some keys that act differently than in .IR vi . .I Vi does not allow one to yank rectangular blocks of text, but .I screen does. Press: .br .ti -2n \fBc\fP or \fBC\fP to set the left or right margin respectively. If no repeat count is given, both default to the current cursor position. .br Example: Try this on a rather full text screen: \*QC-a [ M 20 l SPACE c 10 l 5 j C SPACE\*U. This moves one to the middle line of the screen, moves in 20 columns left, marks the beginning of the paste buffer, sets the left column, moves 5 columns down, sets the right column, and then marks the end of the paste buffer. Now try: .br \*QC-a [ M 20 l SPACE 10 l 5 j SPACE\*U and notice the difference in the amount of text copied. .br .ti -2n \fBJ\fP joins lines. It toggles between 4 modes: lines separated by a newline character (012), lines glued seamless, lines separated by a single whitespace and comma separated lines. Note that you can prepend the newline character with a carriage return character, by issuing a \*Qcrlf on\*U. .br .ti -2n \fBv\fP or \fBV\fP is for all the .I vi users with \*Q:set numbers\*U \- it toggles the left margin between column 9 and 1. Press .br .ti -2n \fBa\fP before the final space key to toggle in append mode. Thus the contents of the paste buffer will not be overwritten, but is appended to. .br .ti -2n \fBA\fP toggles in append mode and sets a (second) mark. .br .ti -2n \fB>\fP sets the (second) mark and writes the contents of the paste buffer to the screen-exchange file (/tmp/screen-exchange per default) once copy-mode is finished. .br This example demonstrates how to dump the whole scrollback buffer to that file: \*QC-A [ g SPACE G $ >\*U. .br .ti -2n \fBC-g\fP gives information about the current line and column. .br .ti -2n \fBx\fP or \fBo\fP exchanges the first mark and the current cursor position. You can use this to adjust an already placed mark. .br .ti -2n \fBC-l\fP ('el') will redraw the screen. .br .ti -2n \fB@\fP does nothing. Does not even exit copy mode. .br .ti -2n All keys not described here exit copy mode. .in -4n .sp .ne 3 .B copy_reg .RI [ key ] .PP No longer exists, use \*Qreadreg\*U instead. .sp .ne 3 .BR "crlf " [ on | off ] .PP This affects the copying of text regions with the `C-a [' command. If it is set to `on', lines will be separated by the two character sequence `CR' - `LF'. Otherwise (default) only `LF' is used. When no parameter is given, the state is toggled. .sp .ne 3 .BR "debug on" | off .PP Turns runtime debugging on or off. If .I screen has been compiled with option -DDEBUG debugging available and is turned on per default. Note that this command only affects debugging output from the main \*QSCREEN\*U process correctly. Debug output from attacher processes can only be turned off once and forever. .sp .ne 3 .BR "defc1 on" | off .PP Same as the \fBc1\fP command except that the default setting for new windows is changed. Initial setting is `on'. .sp .ne 3 .BR "defautonuke on" | off .PP Same as the \fBautonuke\fP command except that the default setting for new displays is changed. Initial setting is `off'. Note that you can use the special `AN' terminal capability if you want to have a dependency on the terminal type. .sp .ne 3 .BR "defbce on" | off .PP Same as the \fBbce\fP command except that the default setting for new windows is changed. Initial setting is `off'. .sp .ne 3 .B defbreaktype .RI [ tcsendbreak | TIOCSBRK .RI | TCSBRK ] .PP Choose one of the available methods of generating a break signal for terminal devices. The preferred methods are .IR tcsendbreak " and " TIOCSBRK . The third, .IR TCSBRK , blocks the complete .I screen session for the duration of the break, but it may be the only way to generate long breaks. .IR Tcsendbreak " and " TIOCSBRK may or may not produce long breaks with spikes (e.g. 4 per second). This is not only system-dependent, this also differs between serial board drivers. Calling \*Qdefbreaktype\*U with no parameter displays the current setting. .sp .ne 3 .BR "defcharset " [ \fIset ] .PP Like the \fBcharset\fP command except that the default setting for new windows is changed. Shows current default if called without argument. .sp .ne 3 .BI "defescape " xy .PP Set the default command characters. This is equivalent to the \*Qescape\*U except that it is useful multiuser sessions only. In a multiuser session \*Qescape\*U changes the command character of the calling user, where \*Qdefescape\*U changes the default command characters for users that will be added later. .sp .ne 3 .BR "defflow on" | off | auto .RB [ interrupt ] .PP Same as the \fBflow\fP command except that the default setting for new windows is changed. Initial setting is `auto'. Specifying \*Qdefflow auto interrupt\*U is the same as the command-line options .B \-fa and .BR \-i . .sp .ne 3 .BR "defgr on" | off .PP Same as the \fBgr\fP command except that the default setting for new windows is changed. Initial setting is `off'. .sp .ne 3 .BR "defhstatus " [ \fIstatus ] .PP The hardstatus line that all new windows will get is set to .I status\fR. This command is useful to make the hardstatus of every window display the window number or title or the like. .I Status may contain the same directives as in the window messages, but the directive escape character is '^E' (octal 005) instead of '%'. This was done to make a misinterpretation of program generated hardstatus lines impossible. If the parameter .I status is omitted, the current default string is displayed. Per default the hardstatus line of new windows is empty. .sp .ne 3 .BI "defencoding " enc .PP Same as the \fBencoding\fP command except that the default setting for new windows is changed. Initial setting is the encoding taken from the terminal. .sp .ne 3 .BR "deflog on" | off .PP Same as the \fBlog\fP command except that the default setting for new windows is changed. Initial setting is `off'. .sp .ne 3 .BR "deflogin on" | off .PP Same as the \fBlogin\fP command except that the default setting for new windows is changed. This is initialized with `on' as distributed (see config.h.in). .sp .ne 3 .BI "defmode " mode .PP The mode of each newly allocated pseudo-tty is set to \fImode\fP. \fIMode\fP is an octal number. When no \*Qdefmode\*U command is given, mode 0622 is used. .sp .ne 3 .BR "defmonitor on" | off .PP Same as the \fBmonitor\fP command except that the default setting for new windows is changed. Initial setting is `off'. .sp .ne 3 .BR "defmousetrack on" | off .PP Same as the \fBmousetrack\fP command except that the default setting for new windows is changed. Initial setting is `off'. .sp .ne 3 .B defnonblock .BR on | off | \fInumsecs .PP Same as the \fBnonblock\fP command except that the default setting for displays is changed. Initial setting is `off'. .sp .ne 3 .BI "defobuflimit " limit .PP Same as the \fBobuflimit\fP command except that the default setting for new displays is changed. Initial setting is 256 bytes. Note that you can use the special 'OL' terminal capability if you want to have a dependency on the terminal type. .sp .ne 3 .BI "defscrollback " num .PP Same as the \fBscrollback\fP command except that the default setting for new windows is changed. Initial setting is 100. .sp .ne 3 .BI "defshell " command .PP Synonym to the \fBshell\fP command. See there. .sp .ne 3 .BR "defsilence on" | off .PP Same as the \fBsilence\fP command except that the default setting for new windows is changed. Initial setting is `off'. .sp .ne 3 .BI "defslowpaste " msec" .PP Same as the \fBslowpaste\fP command except that the default setting for new windows is changed. Initial setting is 0 milliseconds, meaning `off'. .sp .ne 3 .BR "defutf8 on" | off .PP Same as the \fButf8\fP command except that the default setting for new windows is changed. Initial setting is `on' if screen was started with \*Q-U\*U, otherwise `off'. .sp .ne 3 .BR "defwrap on" | off .PP Same as the \fBwrap\fP command except that the default setting for new windows is changed. Initially line-wrap is on and can be toggled with the \*Qwrap\*U command (\*QC-a r\*U) or by means of "C-a : wrap on|off". .sp .ne 3 .BR "defwritelock on" | off | auto .PP Same as the \fBwritelock\fP command except that the default setting for new windows is changed. Initially writelocks will off. .sp .ne 3 .BR "defzombie " [\fIkeys\fP] .PP Synonym to the \fBzombie\fP command. Both currently change the default. See there. .sp .ne 3 .B detach .RB [ -h ] .PP Detach the .I screen session (disconnect it from the terminal and put it into the background). This returns you to the shell where you invoked .IR screen . A detached .I screen can be resumed by invoking .I screen with the .B \-r option (see also section \*QCOMMAND-LINE OPTIONS\*U). The .B \-h option tells screen to immediately close the connection to the terminal (\*Qhangup\*U). .sp .ne 3 .B dinfo .PP Show what screen thinks about your terminal. Useful if you want to know why features like color or the alternate charset don't work. .sp .ne 3 .B displays .PP Shows a tabular listing of all currently connected user front-ends (displays). This is most useful for multiuser sessions. The following keys can be used in displays list: .br .in +4n .ti -2n \fBk\fP, \fBC-p\fP, or \fBup\fP Move up one line. .br .ti -2n \fBj\fP, \fBC-n\fP, or \fBdown\fP Move down one line. .br .ti -2n \fBC-a\fP or \fBhome\fP Move to the first line. .br .ti -2n \fBC-e\fP or \fBend\fP Move to the last line. .br .ti -2n \fBC-u\fP or \fBC-d\fP Move one half page up or down. .br .ti -2n \fBC-b\fP or \fBC-f\fP Move one full page up or down. .br .ti -2n \fBmouseclick\fP Move to the selected line. Available when \*Qmousetrack\*U is set to on. .br .ti -2n \fBspace\fP Refresh the list .br .ti -2n \fBd\fP Detach that display .br .ti -2n \fBD\fP Power detach that display .br .ti -2n \fBC-g\fP, \fBenter\fP, or \fBescape\fP Exit the list .br .ti -4n .PP The following is an example of what \*Qdisplays\*U could look like: .IP xterm 80x42 jnweiger@/dev/ttyp4 0(m11) &rWx .br facit 80x24 mlschroe@/dev/ttyhf nb 11(tcsh) rwx .br xterm 80x42 jnhollma@/dev/ttyp5 0(m11) &R.x .br (A) (B) (C) (D) (E) (F)(G) (H)(I) .PP The legend is as follows: .br (A) The terminal type known by screen for this display. .br (B) Displays geometry as width x height. .br (C) Username who is logged in at the display. .br (D) Device name of the display or the attached device .br (E) Display is in blocking or nonblocking mode. The available modes are "nb", "NB", "Z<", "Z>", and "BL". .br (F) Number of the window .br (G) Name/title of window .br (H) Whether the window is shared .br (I) Window permissions. Made up of three characters: (1st character) ‘-’ : no read ‘r’ : read ‘R’ : read only due to foreign wlock (2nd character) ‘-’ : no write ‘.’ : write suppressed by foreign wlock ‘w’ : write ‘W’ : own wlock (3rd character) ‘-’ : no execute ‘x’ : execute \*QDisplays\*U needs a region size of at least 10 characters wide and 5 characters high in order to display. .sp .ne 3 .BR "digraph " [ \fIpreset [ \fI unicode-value ] ] .PP This command prompts the user for a digraph sequence. The next two characters typed are looked up in a builtin table and the resulting character is inserted in the input stream. For example, if the user enters 'a"', an a-umlaut will be inserted. If the first character entered is a 0 (zero), .I screen will treat the following characters (up to three) as an octal number instead. The optional argument .I preset is treated as user input, thus one can create an \*Qumlaut\*U key. For example the command "bindkey ^K digraph '"'" enables the user to generate an a-umlaut by typing CTRL-K a. When a non-zero .I unicode-value is specified, a new digraph is created with the specified preset. The digraph is unset if a zero value is provided for the .I unicode-value. .sp .ne 3 .B dumptermcap .PP Write the termcap entry for the virtual terminal optimized for the currently active window to the file \*Q.termcap\*U in the user's \*Q$HOME/.screen\*U directory (or wherever .I screen stores its sockets. See the \*QFILES\*U section below). This termcap entry is identical to the value of the environment variable $TERMCAP that is set up by .I screen for each window. For terminfo based systems you will need to run a converter like .IR captoinfo and then compile the entry with .IR tic . .sp .ne 3 .BR "echo " [ -n ] .I message .PP The echo command may be used to annoy .I screen users with a 'message of the day'. Typically installed in a global /local/etc/screenrc. The option \*Q-n\*U may be used to suppress the line feed. See also \*Qsleep\*U. Echo is also useful for online checking of environment variables. .sp .ne 3 .BI "encoding " enc .RI [ enc ] .PP Tell .I screen how to interpret the input/output. The first argument sets the encoding of the current window. Each window can emulate a different encoding. The optional second parameter overwrites the encoding of the connected terminal. It should never be needed as screen uses the locale setting to detect the encoding. There is also a way to select a terminal encoding depending on the terminal type by using the \*QKJ\*U termcap entry. Supported encodings are eucJP, SJIS, eucKR, eucCN, Big5, GBK, KOI8-R, CP1251, UTF-8, ISO8859-2, ISO8859-3, ISO8859-4, ISO8859-5, ISO8859-6, ISO8859-7, ISO8859-8, ISO8859-9, ISO8859-10, ISO8859-15, jis. See also \*Qdefencoding\*U, which changes the default setting of a new window. .sp .ne 3 .BI "escape " xy .PP Set the command character to \fIx\fP and the character generating a literal command character (by triggering the \*Qmeta\*U command) to \fIy\fP (similar to the \-e option). Each argument is either a single character, a two-character sequence of the form \*Q^x\*U (meaning \*QC-x\*U), a backslash followed by an octal number (specifying the ASCII code of the character), or a backslash followed by a second character, such as \*Q\e^\*U or \*Q\e\e\*U. The default is \*Q^Aa\*U. .sp .ne 3 .B eval .I command1 .RI [ command2 .IR ... ] .PP Parses and executes each argument as separate command. .sp .ne 3 .B exec .RI [[ fdpat ] .IR "newcommand " [ "args ..." ]] .PP Run a unix subprocess (specified by an executable path \fInewcommand\fP and its optional arguments) in the current window. The flow of data between newcommands stdin/stdout/stderr, the process originally started in the window (let us call it "application-process") and screen itself (window) is controlled by the file descriptor pattern fdpat. This pattern is basically a three character sequence representing stdin, stdout and stderr of newcommand. A dot (.) connects the file descriptor to .IR screen . An exclamation mark (!) causes the file descriptor to be connected to the application-process. A colon (:) combines both. User input will go to newcommand unless newcommand receives the application-process' output (fdpats first character is `!' or `:') or a pipe symbol (|) is added (as a fourth character) to the end of fdpat. .br Invoking `exec' without arguments shows name and arguments of the currently running subprocess in this window. Only one subprocess a time can be running in each window. .br When a subprocess is running the `kill' command will affect it instead of the windows process. .br Refer to the postscript file `doc/fdpat.ps' for a confusing illustration of all 21 possible combinations. Each drawing shows the digits 2,1,0 representing the three file descriptors of newcommand. The box marked `W' is the usual pty that has the application-process on its slave side. The box marked `P' is the secondary pty that now has .I screen at its master side. .sp Abbreviations: .br Whitespace between the word `exec' and fdpat and the command can be omitted. Trailing dots and a fdpat consisting only of dots can be omitted. A simple `|' is synonymous for the pattern `!..|'; the word exec can be omitted here and can always be replaced by `!'. .sp Examples: .IP exec ... /bin/sh .br exec /bin/sh .br !/bin/sh .PP Creates another shell in the same window, while the original shell is still running. Output of both shells is displayed and user input is sent to the new /bin/sh. .IP exec !.. stty 19200 .br exec ! stty 19200 .br !!stty 19200 .PP Set the speed of the window's tty. If your stty command operates on stdout, then add another `!'. .IP exec !..| less .br |less .PP This adds a pager to the window output. The special character `|' is needed to give the user control over the pager although it gets its input from the window's process. This works, because .I less listens on stderr (a behavior that .I screen would not expect without the `|') when its stdin is not a tty. .I Less versions newer than 177 fail miserably here; good old .I pg still works. .IP !:sed -n s/.*Error.*/\e007/p .PP Sends window output to both, the user and the sed command. The sed inserts an additional bell character (oct. 007) to the window output seen by .IR screen . This will cause "Bell in window x" messages, whenever the string "Error" appears in the window. .sp .ne 3 .B fit .PP Change the window size to the size of the current region. This command is needed because screen doesn't adapt the window size automatically if the window is displayed more than once. .sp .ne 3 .B flow .RB [ on | off | "auto\fR]\fP" .PP Sets the flow-control mode for this window. Without parameters it cycles the current window's flow-control setting from "automatic" to "on" to "off". See the discussion on \*QFLOW-CONTROL\*U later on in this document for full details and note, that this is subject to change in future releases. Default is set by `defflow'. .sp .ne 3 .BR "focus " [ up | down | top | bottom ] .PP Move the input focus to the next region. This is done in a cyclic way so that the top region is selected after the bottom one. If no subcommand is given it defaults to `down'. `up' cycles in the opposite order, `top' and `bottom' go to the top and bottom region respectively. Useful bindings are (j and k as in vi) .nf bind j focus down bind k focus up bind t focus top bind b focus bottom .fi Note that \fBk\fP is traditionally bound to the \fIkill\fP command. .sp .ne 3 .BI "focusminsize [ ( " width "|max|_ ) ( " height "|max|_ ) ]" .PP This forces any currently selected region to be automatically resized at least a certain \fIwidth\fP and \fIheight\fP. All other surrounding regions will be resized in order to accommodate. This constraint follows everytime the \*Qfocus\*U command is used. The \*Qresize\*U command can be used to increase either dimension of a region, but never below what is set with \*Qfocusminsize\*U. The underscore `_' is a synonym for \fBmax\fP. Setting a \fIwidth\fP and \fIheight\fP of `0 0' (zero zero) will undo any constraints and allow for manual resizing. Without any parameters, the minimum width and height is shown. .sp .ne 3 .BR "gr " [ on | off ] .PP Turn GR charset switching on/off. Whenever screen sees an input character with the 8th bit set, it will use the charset stored in the GR slot and print the character with the 8th bit stripped. The default (see also \*Qdefgr\*U) is not to process GR switching because otherwise the ISO88591 charset would not work. .sp .ne 3 .BI group .RI [ grouptitle ] .PP Change or show the group the current window belongs to. Windows can be moved around between different groups by specifying the name of the destination group. Without specifying a group, the title of the current group is displayed. .sp .ne 3 .B hardcopy .RB [ -h ] .RI [ file ] .PP Writes out the currently displayed image to the file \fIfile\fP, or, if no filename is specified, to \fIhardcopy.n\fP in the default directory, where \fIn\fP is the number of the current window. This either appends or overwrites the file if it exists. See below. If the option \fB-h\fP is specified, dump also the contents of the scrollback buffer. .sp .ne 3 .BR "hardcopy_append on" | off .PP If set to "on", .I screen will append to the "hardcopy.n" files created by the command \*QC-a h\*U, otherwise these files are overwritten each time. Default is `off'. .sp .ne 3 .BI "hardcopydir "directory .PP Defines a directory where hardcopy files will be placed. If unset, hardcopys are dumped in .IR screen 's current working directory. .sp .ne 3 .BR "hardstatus " [ on | off ] .br .BR "hardstatus \fR[\fBalways\fR]\fBlastline" | message | ignore .RI [ string ] .br .B "hardstatus string" .RI [ string ] .PP This command configures the use and emulation of the terminal's hardstatus line. The first form toggles whether .I screen will use the hardware status line to display messages. If the flag is set to `off', these messages are overlaid in reverse video mode at the display line. The default setting is `on'. .P The second form tells .I screen what to do if the terminal doesn't have a hardstatus line (i.e. the termcap/terminfo capabilities "hs", "ts", "fs" and "ds" are not set). If the type \*Qlastline\*U is used, .I screen will reserve the last line of the display for the hardstatus. \*Qmessage\*U uses .I screen's message mechanism and \*Qignore\*U tells .I screen never to display the hardstatus. If you prepend the word \*Qalways\*U to the type (e.g., \*Qalwayslastline\*U), .I screen will use the type even if the terminal supports a hardstatus. .P The third form specifies the contents of the hardstatus line. '%h' is used as default string, i.e., the stored hardstatus of the current window (settable via \*QESC]0;^G\*U or \*QESC_ESC\e\*U) is displayed. You can customize this to any string you like including the escapes from the \*QSTRING ESCAPES\*U chapter. If you leave out the argument .IR string , the current string is displayed. .P You can mix the second and third form by providing the string as additional argument. .sp .ne 3 .B height .RB [ -w | -d ] .RI [ lines " [" cols ]] .PP Set the display height to a specified number of lines. When no argument is given it toggles between 24 and 42 lines display. You can also specify a width if you want to change both values. The .B -w option tells screen to leave the display size unchanged and just set the window size, .B -d vice versa. .sp .ne 3 .B help .RB [ -c .IR class ] .PP Not really a online help, but displays a help .I screen showing you all the key bindings. The first pages list all the internal commands followed by their current bindings. Subsequent pages will display the custom commands, one command per key. Press space when you're done reading each page, or return to exit early. All other characters are ignored. If the \*Q-c\*U option is given, display all bound commands for the specified command class. See also \*QDEFAULT KEY BINDINGS\*U section. .sp .ne 3 .B history .PP Usually users work with a shell that allows easy access to previous commands. For example csh has the command \*Q!!\*U to repeat the last command executed. .I Screen allows you to have a primitive way of re-calling \*Qthe command that started ...\*U: You just type the first letter of that command, then hit `C-a {' and .I screen tries to find a previous line that matches with the `prompt character' to the left of the cursor. This line is pasted into this window's input queue. Thus you have a crude command history (made up by the visible window and its scrollback buffer). .sp .ne 3 .BI "hstatus " status .PP Change the window's hardstatus line to the string \fIstatus\fP. .sp .ne 3 .B idle .RI [ timeout .RI [ "cmd args" ]] .PP Sets a command that is run after the specified number of seconds inactivity is reached. This command will normally be the \*Qblanker\*U command to create a screen blanker, but it can be any screen command. If no command is specified, only the timeout is set. A timeout of zero (or the special timeout \fBoff\fP) disables the timer. If no arguments are given, the current settings are displayed. .sp .ne 3 .BR "ignorecase " [ on | off ] .PP Tell screen to ignore the case of characters in searches. Default is `off'. Without any options, the state of ignorecase is toggled. .sp .ne 3 .B info .PP Uses the message line to display some information about the current window: the cursor position in the form \*Q(column,row)\*U starting with \*Q(1,1)\*U, the terminal width and height plus the size of the scrollback buffer in lines, like in \*Q(80,24)+50\*U, the current state of window XON/XOFF flow control is shown like this (See also section FLOW CONTROL): .nf +flow automatic flow control, currently on. -flow automatic flow control, currently off. +(+)flow flow control enabled. Agrees with automatic control. -(+)flow flow control disabled. Disagrees with automatic control. +(-)flow flow control enabled. Disagrees with automatic control. -(-)flow flow control disabled. Agrees with automatic control. .fi The current line wrap setting (`+wrap' indicates enabled, `\-wrap' not) is also shown. The flags `ins', `org', `app', `log', `mon' or `nored' are displayed when the window is in insert mode, origin mode, application-keypad mode, has output logging, activity monitoring or partial redraw enabled. The currently active character set (\fIG0\fP, \fIG1\fP, \fIG2\fP, or \fIG3\fP) and in square brackets the terminal character sets that are currently designated as \fIG0\fP through \fIG3\fP is shown. If the window is in UTF-8 mode, the string \*QUTF-8\*U is shown instead. Additional modes depending on the type of the window are displayed at the end of the status line (See also chapter \*QWINDOW TYPES\*U). .br If the state machine of the terminal emulator is in a non-default state, the info line is started with a string identifying the current state. .br For system information use the \*Qtime\*U command. .sp .ne 3 .BR ins_reg " [" \fIkey ] .PP No longer exists, use \*Qpaste\*U instead. .sp .ne 3 .B kill .PP Kill current window. .br If there is an `exec' command running then it is killed. Otherwise the process (shell) running in the window receives a HANGUP condition, the window structure is removed and .I screen (your display) switches to another window. When the last window is destroyed, .I screen exits. After a kill .I screen switches to the previously displayed window. .br Note: .I Emacs users should keep this command in mind, when killing a line. It is recommended not to use \*QC-a\*U as the .I screen escape key or to rebind kill to \*QC-a K\*U. .sp .ne 3 .B lastmsg .PP Redisplay the last contents of the message/status line. Useful if you're typing when a message appears, because the message goes away when you press a key (unless your terminal has a hardware status line). Refer to the commands \*Qmsgwait\*U and \*Qmsgminwait\*U for fine tuning. .sp .ne 3 .BR "layout new " [\fItitle\fP] .PP Create a new layout. The screen will change to one whole region and be switched to the blank window. From here, you build the regions and the windows they show as you desire. The new layout will be numbered with the smallest available integer, starting with zero. You can optionally give a title to your new layout. Otherwise, it will have a default title of \*Qlayout\*U. You can always change the title later by using the command \fBlayout title\fP. .sp .ne 3 .BR "layout remove " [\fIn|title\fP] .PP Remove, or in other words, delete the specified layout. Either the number or the title can be specified. Without either specification, \fIscreen\fP will remove the current layout. Removing a layout does not affect your set windows or regions. .sp .ne 3 .B layout next .PP Switch to the next layout available .sp .ne 3 .B layout prev .PP Switch to the previous layout available .sp .ne 3 .BR "layout select " [\fIn|title\fP] .PP Select the desired layout. Either the number or the title can be specified. Without either specification, \fIscreen\fP will prompt and ask which screen is desired. To see which layouts are available, use the \fBlayout show\fP command. .sp .ne 3 .B layout show .PP List on the message line the number(s) and title(s) of the available layout(s). The current layout is flagged. .sp .ne 3 .BR "layout title " [\fItitle\fP] .PP Change or display the title of the current layout. A string given will be used to name the layout. Without any options, the current title and number is displayed on the message line. .sp .ne 3 .BR "layout number " [\fIn\fP] .PP Change or display the number of the current layout. An integer given will be used to number the layout. Without any options, the current number and title is displayed on the message line. .sp .ne 3 .BR "layout attach " [\fItitle\fP|\fB:last\fP] .PP Change or display which layout to reattach back to. The default is \fB:last\fP, which tells \fIscreen\fP to reattach back to the last used layout just before detachment. By supplying a title, You can instruct \fIscreen\fP to reattach to a particular layout regardless which one was used at the time of detachment. Without any options, the layout to reattach to will be shown in the message line. .sp .ne 3 .BR "layout save " [\fIn|title\fP] .PP Remember the current arrangement of regions. When used, \fIscreen\fP will remember the arrangement of vertically and horizontally split regions. This arrangement is restored when a \fIscreen\fP session is reattached or switched back from a different layout. If the session ends or the \fIscreen\fP process dies, the layout arrangements are lost. The \fBlayout dump\fP command should help in this siutation. If a number or title is supplied, \fIscreen\fP will remember the arrangement of that particular layout. Without any options, \fIscreen\fP will remember the current layout. Saving your regions can be done automatically by using the \fBlayout autosave\fP command. .sp .ne 3 .BR "layout autosave " [\fBon|off\fP] .PP Change or display the status of automatcally saving layouts. The default is \fBon\fP, meaning when \fIscreen\fP is detached or changed to a different layout, the arrangement of regions and windows will be remembered at the time of change and restored upon return. If autosave is set to \fBoff\fP, that arrangement will only be restored to either to the last manual save, using \fBlayout save\fP, or to when the layout was first created, to a single region with a single window. Without either an \fBon\fP or \fBoff\fP, the current status is displayed on the message line. .sp .ne 3 .BR "layout dump " [\fIfilename\fP] .PP Write to a file the order of splits made in the current layout. This is useful to recreate the order of your regions used in your current layout. Only the current layout is recorded. While the order of the regions are recorded, the sizes of those regions and which windows correspond to which regions are not. If no filename is specified, the default is \fIlayout-dump\fP, saved in the directory that the \fIscreen\fP process was started in. If the file already exists, \fBlayout dump\fP will append to that file. As an example: .PP .nf C-a : layout dump /home/user/.screenrc .fi .PP will save or append the layout to the user's \fI.screenrc\fP file. .sp .ne 3 .B license .PP Display the disclaimer page. This is done whenever .I screen is started without options, which should be often enough. See also the \*Qstartup_message\*U command. .sp .ne 3 .B lockscreen .PP Lock this display. Call a screenlock program (/local/bin/lck or /usr/bin/lock or a builtin if no other is available). Screen does not accept any command keys until this program terminates. Meanwhile processes in the windows may continue, as the windows are in the `detached' state. The screenlock program may be changed through the environment variable $LOCKPRG (which must be set in the shell from which .I screen is started) and is executed with the user's uid and gid. .br Warning: When you leave other shells unlocked and you have no password set on .IR screen , the lock is void: One could easily re-attach from an unlocked shell. This feature should rather be called `lockterminal'. .sp .ne 3 .BR "log " [ on | off ] .PP Start/stop writing output of the current window to a file \*Qscreenlog.\fIn\fP\*U in the window's default directory, where \fIn\fP is the number of the current window. This filename can be changed with the `logfile' command. If no parameter is given, the state of logging is toggled. The session log is appended to the previous contents of the file if it already exists. The current contents and the contents of the scrollback history are not included in the session log. Default is `off'. .sp .ne 3 .BI "logfile " filename .br .BI "logfile flush " secs .PP Defines the name the log files will get. The default is \*Qscreenlog.%n\*U. The second form changes the number of seconds .I screen will wait before flushing the logfile buffer to the file-system. The default value is 10 seconds. .sp .ne 3 .BR "login " [ on | off ] .PP Adds or removes the entry in the utmp database file for the current window. This controls if the window is `logged in'. When no parameter is given, the login state of the window is toggled. Additionally to that toggle, it is convenient having a `log in' and a `log out' key. E.\|g. `bind I login on' and `bind O login off' will map these keys to be C-a I and C-a O. The default setting (in config.h.in) should be \*Qon\*U for a .I screen that runs under suid-root. Use the \*Qdeflogin\*U command to change the default login state for new windows. Both commands are only present when .I screen has been compiled with utmp support. .sp .ne 3 .BR "logtstamp " [ on | off ] .br .B "logtstamp after" .RI [ secs ] .br .B "logtstamp string" .RI [ string ] .PP This command controls logfile time-stamp mechanism of .I screen. If time-stamps are turned \*Qon\*U, .I screen adds a string containing the current time to the logfile after two minutes of inactivity. When output continues and more than another two minutes have passed, a second time-stamp is added to document the restart of the output. You can change this timeout with the second form of the command. The third form is used for customizing the time-stamp string (`-- %n:%t -- time-stamp -- %M/%d/%y %c:%s --\\n' by default). .sp .ne 3 .B mapdefault .PP Tell .I screen that the next input character should only be looked up in the default bindkey table. See also \*Qbindkey\*U. .sp .ne 3 .B mapnotnext .PP Like mapdefault, but don't even look in the default bindkey table. .sp .ne 3 .B maptimeout .RI [ timeout ] .PP Set the inter-character timer for input sequence detection to a timeout of .I timeout ms. The default timeout is 300ms. Maptimeout with no arguments shows the current setting. See also \*Qbindkey\*U. .sp .ne 3 .BI "markkeys " string .PP This is a method of changing the keymap used for copy/history mode. The string is made up of \fIoldchar\fP=\fInewchar\fP pairs which are separated by `:'. Example: The string \*QB=^B:F=^F\*U will change the keys `C-b' and `C-f' to the vi style binding (scroll up/down fill page). This happens to be the default binding for `B' and `F'. The command \*Qmarkkeys h=^B:l=^F:$=^E\*U would set the mode for an emacs-style binding. If your terminal sends characters, that cause you to abort copy mode, then this command may help by binding these characters to do nothing. The no-op character is `@' and is used like this: \*Qmarkkeys @=L=H\*U if you do not want to use the `H' or `L' commands any longer. As shown in this example, multiple keys can be assigned to one function in a single statement. .sp .ne 3 .BI "maxwin " num .PP Set the maximum window number screen will create. Doesn't affect already existing windows. The number can be increased only when there are no existing windows. .sp .ne 3 .B meta .PP Insert the command character (C-a) in the current window's input stream. .sp .ne 3 .BR "monitor " [ on | off ] .PP Toggles activity monitoring of windows. When monitoring is turned on and an affected window is switched into the background, you will receive the activity notification message in the status line at the first sign of output and the window will also be marked with an `@' in the window-status display. Monitoring is initially off for all windows. .sp .ne 3 .BR "mousetrack " [ on | off ] .PP This command determines whether .I screen will watch for mouse clicks. When this command is enabled, regions that have been split in various ways can be selected by pointing to them with a mouse and left-clicking them. Without specifying \fBon\fP or \fBoff\fP, the current state is displayed. The default state is determined by the \*Qdefmousetrack\*U command. .sp .ne 3 .BI "msgminwait " sec .PP Defines the time .I screen delays a new message when one message is currently displayed. The default is 1 second. .sp .ne 3 .BI "msgwait " sec .PP Defines the time a message is displayed if .I screen is not disturbed by other activity. The default is 5 seconds. .sp .ne 3 .BR "multiuser on" | off .PP Switch between singleuser and multiuser mode. Standard .I screen operation is singleuser. In multiuser mode the commands `acladd', `aclchg', `aclgrp' and `acldel' can be used to enable (and disable) other users accessing this .I screen session. .sp .ne 3 .BR "nethack on" | off .PP Changes the kind of error messages used by .IR screen . When you are familiar with the game \*Qnethack\*U, you may enjoy the nethack-style messages which will often blur the facts a little, but are much funnier to read. Anyway, standard messages often tend to be unclear as well. .br This option is only available if .I screen was compiled with the NETHACK flag defined. The default setting is then determined by the presence of the environment variable $NETHACKOPTIONS and the file ~/.nethackrc - if either one is present, the default is \fBon\fP. .sp .ne 3 .B next .PP Switch to the next window. This command can be used repeatedly to cycle through the list of windows. .sp .ne 3 .B nonblock .RB [ on | off | \fInumsecs ] .PP Tell screen how to deal with user interfaces (displays) that cease to accept output. This can happen if a user presses ^S or a TCP/modem connection gets cut but no hangup is received. If nonblock is \fBoff\fP (this is the default) screen waits until the display restarts to accept the output. If nonblock is \fBon\fP, screen waits until the timeout is reached (\fBon\fP is treated as 1s). If the display still doesn't receive characters, screen will consider it \*Qblocked\*U and stop sending characters to it. If at some time it restarts to accept characters, screen will unblock the display and redisplay the updated window contents. .sp .ne 3 .BR "number " [[+|-] \fIn ] .PP Change the current window's number. If the given number \fIn\fP is already used by another window, both windows exchange their numbers. If no argument is specified, the current window number (and title) is shown. Using `+' or `-' will change the window's number by the relative amount specified. .sp .ne 3 .BR "obuflimit " [ \fIlimit ] .PP If the output buffer contains more bytes than the specified limit, no more data will be read from the windows. The default value is 256. If you have a fast display (like xterm), you can set it to some higher value. If no argument is specified, the current setting is displayed. .sp .ne 3 .B only .PP Kill all regions but the current one. .sp .ne 3 .B other .PP Switch to the window displayed previously. If this window does no longer exist, \fIother\fP has the same effect as \fInext\fP. .sp .ne 3 .BR "partial on" | off .PP Defines whether the display should be refreshed (as with \fIredisplay\fP) after switching to the current window. This command only affects the current window. To immediately affect all windows use the \fIallpartial\fP command. Default is `off', of course. This default is fixed, as there is currently no \fIdefpartial\fP command. .sp .ne 3 .BR "password " [ \fIcrypted_pw ] .PP Present a crypted password in your \*Q.screenrc\*U file and .I screen will ask for it, whenever someone attempts to resume a detached. This is useful if you have privileged programs running under .I screen and you want to protect your session from reattach attempts by another user masquerading as your uid (i.e. any superuser.) If no crypted password is specified, .I screen prompts twice for typing a password and places its encryption in the paste buffer. Default is `none', this disables password checking. .sp .ne 3 .BR paste .RI [ registers " [" dest_reg ]] .PP Write the (concatenated) contents of the specified registers to the stdin queue of the current window. The register '.' is treated as the paste buffer. If no parameter is given the user is prompted for a single register to paste. The paste buffer can be filled with the \fIcopy\fP, \fIhistory\fP and \fIreadbuf\fP commands. Other registers can be filled with the \fIregister\fP, \fIreadreg\fP and \fIpaste\fP commands. If \fIpaste\fP is called with a second argument, the contents of the specified registers is pasted into the named destination register rather than the window. If '.' is used as the second argument, the displays paste buffer is the destination. Note, that \*Qpaste\*U uses a wide variety of resources: Whenever a second argument is specified no current window is needed. When the source specification only contains registers (not the paste buffer) then there need not be a current display (terminal attached), as the registers are a global resource. The paste buffer exists once for every user. .sp .ne 3 .BR "pastefont " [ on | off ] .PP Tell .I screen to include font information in the paste buffer. The default is not to do so. This command is especially useful for multi character fonts like kanji. .sp .ne 3 .B pow_break .PP Reopen the window's terminal line and send a break condition. See `break'. .sp .ne 3 .B pow_detach .PP Power detach. Mainly the same as \fIdetach\fP, but also sends a HANGUP signal to the parent process of .IR screen . CAUTION: This will result in a logout, when .I screen was started from your login shell. .sp .ne 3 .B pow_detach_msg .RI [ message ] .PP The \fImessage\fP specified here is output whenever a `Power detach' was performed. It may be used as a replacement for a logout message or to reset baud rate, etc. Without parameter, the current message is shown. .sp .ne 3 .B prev .PP Switch to the window with the next lower number. This command can be used repeatedly to cycle through the list of windows. .sp .ne 3 .B printcmd .RI [ cmd ] .PP If .I cmd is not an empty string, .I screen will not use the terminal capabilities \*Qpo/pf\*U if it detects an ansi print sequence .BR "ESC [ 5 i" , but pipe the output into .IR cmd . This should normally be a command like \*Qlpr\*U or \*Q'cat > /tmp/scrprint'\*U. .B printcmd without a command displays the current setting. The ansi sequence .B "ESC \e" ends printing and closes the pipe. .br Warning: Be careful with this command! If other user have write access to your terminal, they will be able to fire off print commands. .sp .ne 3 .BR process " [" \fIkey ] .PP Stuff the contents of the specified register into .IR screen 's input queue. If no argument is given you are prompted for a register name. The text is parsed as if it had been typed in from the user's keyboard. This command can be used to bind multiple actions to a single key. .sp .ne 3 .B quit .PP Kill all windows and terminate .IR screen . Note that on VT100-style terminals the keys C-4 and C-\e are identical. This makes the default bindings dangerous: Be careful not to type C-a C-4 when selecting window no. 4. Use the empty bind command (as in \*Qbind '^\e'\*U) to remove a key binding. .sp .ne 3 .B readbuf .RB [ -e .IR encoding ] .RI [ filename ] .PP Reads the contents of the specified file into the paste buffer. You can tell screen the encoding of the file via the \fB-e\fP option. If no file is specified, the screen-exchange filename is used. See also \*Qbufferfile\*U command. .sp .ne 3 .B readreg .RB [ -e .IR encoding ] .RI [ register " [" filename ]] .PP Does one of two things, dependent on number of arguments: with zero or one arguments it it duplicates the paste buffer contents into the register specified or entered at the prompt. With two arguments it reads the contents of the named file into the register, just as \fIreadbuf\fP reads the screen-exchange file into the paste buffer. You can tell screen the encoding of the file via the \fB-e\fP option. The following example will paste the system's password file into the .I screen window (using register p, where a copy remains): .PP .nf C-a : readreg p /etc/passwd C-a : paste p .fi .sp .ne 3 .B redisplay .PP Redisplay the current window. Needed to get a full redisplay when in partial redraw mode. .sp .ne 3 .B register .RB [ -e .IR encoding ] .I "key string" .PP Save the specified \fIstring\fP to the register \fIkey\fP. The encoding of the string can be specified via the \fB-e\fP option. See also the \*Qpaste\*U command. .sp .ne 3 .B "remove" .PP Kill the current region. This is a no-op if there is only one region. .sp .ne 3 .B "removebuf" .PP Unlinks the screen-exchange file used by the commands \*Qwritebuf\*U and \*Qreadbuf\*U. .sp .ne 3 .B "rendition bell" | monitor | silence | so .RB "\fIattr\fR " [ \fIcolor ] .PP Change the way .I screen renders the titles of windows that have monitor or bell flags set in caption or hardstatus or windowlist. See the \*QSTRING ESCAPES\*U chapter for the syntax of the modifiers. The default for monitor is currently \*Q=b \*U (bold, active colors), for bell \*Q=ub \*U (underline, bold and active colors), and \*Q=u \*U for silence. .sp .ne 3 .B "reset" .PP Reset the virtual terminal to its \*Qpower-on\*U values. Useful when strange settings (like scroll regions or graphics character set) are left over from an application. .sp .ne 3 .B "resize" .PP Resize the current region. The space will be removed from or added to the region below or if there's not enough space from the region above. .IP resize +N increase current region height by N .IP resize -N decrease current region height by N .IP resize N set current region height to N .IP resize = make all windows equally high .IP resize max maximize current region height .IP resize min minimize current region height .PP .sp .ne 3 .B "screen \fP[\fI-opts\fP] [\fIn\fP] [\fIcmd\fP [\fIargs\fP]|\fB//group\fP]" .PP Establish a new window. The flow-control options (\fB\-f\fP, \fB\-fn\fP and \fB\-fa\fP), title (a.\|k.\|a.) option (\fB\-t\fP), login options (\fB-l\fP and \fB-ln\fP) , terminal type option (\fB-T\fP ), the all-capability-flag (\fB-a\fP) and scrollback option (\fB-h\fP ) may be specified with each command. The option (\fB-M\fP) turns monitoring on for this window. The option (\fB-L\fP) turns output logging on for this window. If an optional number \fIn\fP in the range 0..MAXWIN-1 is given, the window number \fIn\fP is assigned to the newly created window (or, if this number is already in-use, the next available number). If a command is specified after \*Qscreen\*U, this command (with the given arguments) is started in the window; otherwise, a shell is created. If \fB//group\fP is supplied, a container-type window is created in which other windows may be created inside it. Thus, if your \*Q.screenrc\*U contains the lines .sp .nf # example for .screenrc: screen 1 screen -fn -t foobar -L 2 telnet foobar .fi .sp .I screen creates a shell window (in window #1) and a window with a TELNET connection to the machine foobar (with no flow-control using the title \*Qfoobar\*U in window #2) and will write a logfile (\*Qscreenlog.2\*U) of the telnet session. Note, that unlike previous versions of .I screen no additional default window is created when \*Qscreen\*U commands are included in your \*Q.screenrc\*U file. When the initialization is completed, .I screen switches to the last window specified in your .screenrc file or, if none, opens a default window #0. .br Screen has built in some functionality of \*Qcu\*U and \*Qtelnet\*U. See also chapter \*QWINDOW TYPES\*U. .sp .ne 3 .B "scrollback \fP\fInum\fP" .PP Set the size of the scrollback buffer for the current windows to \fInum\fP lines. The default scrollback is 100 lines. See also the \*Qdefscrollback\*U command and use \*Qinfo\*U to view the current setting. To access and use the contents in the scrollback buffer, use the \*Qcopy\*U command. .sp .ne 3 .BR "select " [ \fIWindowID ] .PP Switch to the window identified by \fIWindowID\fP. This can be a prefix of a window title (alphanumeric window name) or a window number. The parameter is optional and if omitted, you get prompted for an identifier. When a new window is established, the first available number is assigned to this window. Thus, the first window can be activated by \*Qselect 0\*U. The number of windows is limited at compile-time by the MAXWIN configuration parameter (which defaults to 40). There are two special WindowIDs, \*Q-\*U selects the internal blank window and \*Q.\*U selects the current window. The latter is useful if used with screen's \*Q-X\*U option. .sp .ne .BR "sessionname " [ \fIname ] .PP Rename the current session. Note, that for \*Qscreen -list\*U the name shows up with the process-id prepended. If the argument \*Qname\*U is omitted, the name of this session is displayed. Caution: The $STY environment variables will still reflect the old name in pre-existing shells. This may result in confusion. Use of this command is generally discouraged. Use the \*Q-S\*U command-line option if you want to name a new session. The default is constructed from the tty and host names. .sp .ne 3 .B "setenv " .RI [ var " [" string ]] .PP Set the environment variable \fIvar\fP to value \fIstring\fP. If only \fIvar\fP is specified, the user will be prompted to enter a value. If no parameters are specified, the user will be prompted for both variable and value. The environment is inherited by all subsequently forked shells. .sp .ne 3 .BR "setsid " [ on | off ] .PP Normally screen uses different sessions and process groups for the windows. If setsid is turned \fIoff\fP, this is not done anymore and all windows will be in the same process group as the screen backend process. This also breaks job-control, so be careful. The default is \fIon\fP, of course. This command is probably useful only in rare circumstances. .sp .ne 3 .B "shell \fIcommand\fP" .PP Set the command to be used to create a new shell. This overrides the value of the environment variable $SHELL. This is useful if you'd like to run a tty-enhancer which is expecting to execute the program specified in $SHELL. If the command begins with a '-' character, the shell will be started as a login-shell. .sp .ne 3 .B "shelltitle \fItitle\fP" .PP Set the title for all shells created during startup or by the C-A C-c command. For details about what a title is, see the discussion entitled \*QTITLES (naming windows)\*U. .sp .ne 3 .BR "silence " [ on | off "|\fIsec\fP]" .PP Toggles silence monitoring of windows. When silence is turned on and an affected window is switched into the background, you will receive the silence notification message in the status line after a specified period of inactivity (silence). The default timeout can be changed with the `silencewait' command or by specifying a number of seconds instead of `on' or `off'. Silence is initially off for all windows. .sp .ne 3 .BI "silencewait " sec .PP Define the time that all windows monitored for silence should wait before displaying a message. Default 30 seconds. .sp .ne .B "sleep \fP\fInum\fP" .PP This command will pause the execution of a .screenrc file for \fInum\fP seconds. Keyboard activity will end the sleep. It may be used to give users a chance to read the messages output by \*Qecho\*U. .sp .ne 3 .B "slowpaste \fImsec\fP" .PP Define the speed at which text is inserted into the current window by the paste ("C-a ]") command. If the slowpaste value is nonzero text is written character by character. .I screen will make a pause of \fImsec\fP milliseconds after each single character write to allow the application to process its input. Only use slowpaste if your underlying system exposes flow control problems while pasting large amounts of text. .sp .ne 3 .BI "source " file .PP Read and execute commands from file \fIfile\fP. Source commands may be nested to a maximum recursion level of ten. If file is not an absolute path and screen is already processing a source command, the parent directory of the running source command file is used to search for the new command file before screen's current directory. Note that termcap/terminfo/termcapinfo commands only work at startup and reattach time, so they must be reached via the default screenrc files to have an effect. .sp .ne 3 .B sorendition .RB [ "\fIattr\fR " [ \fIcolor ]] .PP This command is deprecated. See "rendition so" instead. .sp .ne 3 .B split .RB [ -v ] .PP Split the current region into two new ones. All regions on the display are resized to make room for the new region. The blank window is displayed on the new region. Splits are made horizontally unless -v is used. Use the \*Qremove\*U or the \*Qonly\*U command to delete regions. Use \*Qfocus\*U to toggle between regions. .sp .ne 3 .B "startup_message on\fP|\fBoff" .PP Select whether you want to see the copyright notice during startup. Default is `on', as you probably noticed. .sp .ne 3 .B stuff .RB [ "\fIstring\fR" ] .PP Stuff the string .I string in the input buffer of the current window. This is like the \*Qpaste\*U command but with much less overhead. Without a paramter, screen will prompt for a string to stuff. You cannot paste large buffers with the \*Qstuff\*U command. It is most useful for key bindings. See also \*Qbindkey\*U. .sp .ne 3 .B su .RI [ username " [" password .RI [ password2 ]]] .PP Substitute the user of a display. The command prompts for all parameters that are omitted. If passwords are specified as parameters, they have to be specified un-crypted. The first password is matched against the systems passwd database, the second password is matched against the .I screen password as set with the commands \*Qacladd\*U or \*Qpassword\*U. \*QSu\*U may be useful for the .I screen administrator to test multiuser setups. .\" XXX removed in 3.8.0 XXX .\" but it is mainly used implicitly .\" by the \*Qconnect\*U command to identify users that access a remote session. When the identification fails, the user has access to the commands available for user .BR nobody . These are \*Qdetach\*U, \*Qlicense\*U, \*Qversion\*U, \*Qhelp\*U and \*Qdisplays\*U. .sp .ne 3 .B "suspend" .PP Suspend .IR screen . The windows are in the `detached' state, while .I screen is suspended. This feature relies on the shell being able to do job control. .sp .ne 3 .B "term \fIterm\fP" .PP In each window's environment .I screen opens, the $TERM variable is set to \*Qscreen\*U by default. But when no description for \*Qscreen\*U is installed in the local termcap or terminfo data base, you set $TERM to \- say \- \*Qvt100\*U. This won't do much harm, as .I screen is VT100/ANSI compatible. The use of the \*Qterm\*U command is discouraged for non-default purpose. That is, one may want to specify special $TERM settings (e.g. vt100) for the next \*Qscreen rlogin othermachine\*U command. Use the command \*Qscreen -T vt100 rlogin othermachine\*U rather than setting and resetting the default. .sp .ne 3 .BI termcap " term terminal-tweaks" .RI [ window-tweaks ] .br .BI terminfo " term terminal-tweaks" .RI [ window-tweaks ] .br .BI termcapinfo " term terminal-tweaks" .RI [ window-tweaks ] .PP Use this command to modify your terminal's termcap entry without going through all the hassles involved in creating a custom termcap entry. Plus, you can optionally customize the termcap generated for the windows. You have to place these commands in one of the screenrc startup files, as they are meaningless once the terminal emulator is booted. .br If your system works uses the terminfo database rather than termcap, .I screen will understand the `terminfo' command, which has the same effects as the `termcap' command. Two separate commands are provided, as there are subtle syntactic differences, e.g. when parameter interpolation (using `%') is required. Note that termcap names of the capabilities have to be used with the `terminfo' command. .br In many cases, where the arguments are valid in both terminfo and termcap syntax, you can use the command `termcapinfo', which is just a shorthand for a pair of `termcap' and `terminfo' commands with identical arguments. .PP The first argument specifies which terminal(s) should be affected by this definition. You can specify multiple terminal names by separating them with `|'s. Use `*' to match all terminals and `vt*' to match all terminals that begin with \*Qvt\*U. .PP Each \fItweak\fP argument contains one or more termcap defines (separated by `:'s) to be inserted at the start of the appropriate termcap entry, enhancing it or overriding existing values. The first tweak modifies your terminal's termcap, and contains definitions that your terminal uses to perform certain functions. Specify a null string to leave this unchanged (e.\|g. ''). The second (optional) tweak modifies all the window termcaps, and should contain definitions that .I screen understands (see the \*QVIRTUAL TERMINAL\*U section). .PP Some examples: .IP termcap xterm* LP:hs@ .PP Informs .I screen that all terminals that begin with `xterm' have firm auto-margins that allow the last position on the screen to be updated (LP), but they don't really have a status line (no 'hs' \- append `@' to turn entries off). Note that we assume `LP' for all terminal names that start with \*Qvt\*U, but only if you don't specify a termcap command for that terminal. .IP termcap vt* LP .br termcap vt102|vt220 Z0=\eE[?3h:Z1=\eE[?3l .PP Specifies the firm-margined `LP' capability for all terminals that begin with `vt', and the second line will also add the escape-sequences to switch into (Z0) and back out of (Z1) 132-character-per-line mode if this is a VT102 or VT220. (You must specify Z0 and Z1 in your termcap to use the width-changing commands.) .IP termcap vt100 "" l0=PF1:l1=PF2:l2=PF3:l3=PF4 .PP This leaves your vt100 termcap alone and adds the function key labels to each window's termcap entry. .IP termcap h19|z19 am@:im=\eE@:ei=\eEO dc=\eE[P .PP Takes a h19 or z19 termcap and turns off auto-margins (am@) and enables the insert mode (im) and end-insert (ei) capabilities (the `@' in the `im' string is after the `=', so it is part of the string). Having the `im' and `ei' definitions put into your terminal's termcap will cause .I screen to automatically advertise the character-insert capability in each window's termcap. Each window will also get the delete-character capability (dc) added to its termcap, which .I screen will translate into a line-update for the terminal (we're pretending it doesn't support character deletion). .PP If you would like to fully specify each window's termcap entry, you should instead set the $SCREENCAP variable prior to running .IR screen . See the discussion on the \*QVIRTUAL TERMINAL\*U in this manual, and the termcap(5) man page for more information on termcap definitions. .sp .ne 3 .B time .RI [ string ] .PP Uses the message line to display the time of day, the host name, and the load averages over 1, 5, and 15 minutes (if this is available on your system). For window specific information, use \*Qinfo\*U. If a string is specified, it changes the format of the time report like it is described in the \*QSTRING ESCAPES\*U chapter. Screen uses a default of "%c:%s %M %d %H%? %l%?". .sp .ne 3 .BR "title " [ \fIwindowtitle ] .PP Set the name of the current window to \fIwindowtitle\fP. If no name is specified, .I screen prompts for one. This command was known as `aka' in previous releases. .sp .ne 3 .BI "unbindall " .PP Unbind all the bindings. This can be useful when screen is used solely for its detaching abilities, such as when letting a console application run as a daemon. If, for some reason, it is necessary to bind commands after this, use 'screen -X'. .sp .ne 3 .BI "unsetenv " var .PP Unset an environment variable. .sp .ne 3 .B utf8 .RB [ on | off .RB [ on | off ]] .PP Change the encoding used in the current window. If utf8 is enabled, the strings sent to the window will be UTF-8 encoded and vice versa. Omitting the parameter toggles the setting. If a second parameter is given, the display's encoding is also changed (this should rather be done with screen's \*Q-U\*U option). See also \*Qdefutf8\*U, which changes the default setting of a new window. .sp .ne 3 .B vbell .RB [ on | off ] .PP Sets the visual bell setting for this window. Omitting the parameter toggles the setting. If vbell is switched on, but your terminal does not support a visual bell, a `vbell-message' is displayed in the status line when the bell character (^G) is received. Visual bell support of a terminal is defined by the termcap variable `vb' (terminfo: 'flash'). .br Per default, vbell is off, thus the audible bell is used. See also `bell_msg'. .sp .ne 3 .B vbell_msg .RI [ message ] .PP Sets the visual bell message. \fImessage\fP is printed to the status line if the window receives a bell character (^G), vbell is set to \*Qon\*U, but the terminal does not support a visual bell. The default message is \*QWuff, Wuff!!\*U. Without a parameter, the current message is shown. .sp .ne 3 .BI "vbellwait " sec .PP Define a delay in seconds after each display of .IR screen 's visual bell message. The default is 1 second. .sp .ne 3 .B verbose .RB [ on | off ] .PP If verbose is switched on, the command name is echoed, whenever a window is created (or resurrected from zombie state). Default is off. Without a parameter, the current setting is shown. .sp .ne 3 .B version .PP Print the current version and the compile date in the status line. .sp .ne 3 .BI "wall " "message" .PP Write a message to all displays. The message will appear in the terminal's status line. .sp .ne 3 .B width .RB [ -w | -d ] .RI [ cols " [" lines ]] .PP Toggle the window width between 80 and 132 columns or set it to \fIcols\fP columns if an argument is specified. This requires a capable terminal and the termcap entries \*QZ0\*U and \*QZ1\*U. See the \*Qtermcap\*U command for more information. You can also specify a new height if you want to change both values. The .B -w option tells screen to leave the display size unchanged and just set the window size, .B -d vice versa. .sp .ne 3 .B windowlist .RB [ -b ] .RB [ -m ] .RB [ -g ] .br .B windowlist .B string .RI [ string ] .br .B windowlist .B title .RI [ title ] .PP Display all windows in a table for visual window selection. If screen was in a window group, screen will back out of the group and then display the windows in that group. If the .B -b option is given, screen will switch to the blank window before presenting the list, so that the current window is also selectable. The .B -m option changes the order of the windows, instead of sorting by window numbers screen uses its internal most-recently-used list. The .B -g option will show the windows inside any groups in that level and downwards. The following keys are used to navigate in \*Qwindowlist\*U: .br .in +4n .ti -2n \fBk\fP, \fBC-p\fP, or \fBup\fP Move up one line. .br .ti -2n \fBj\fP, \fBC-n\fP, or \fBdown\fP Move down one line. .br .ti -2n \fBC-g\fP or \fBescape\fP Exit windowlist. .br .ti -2n \fBC-a\fP or \fBhome\fP Move to the first line. .br .ti -2n \fBC-e\fP or \fBend\fP Move to the last line. .br .ti -2n \fBC-u\fP or \fBC-d\fP Move one half page up or down. .br .ti -2n \fBC-b\fP or \fBC-f\fP Move one full page up or down. .br .ti -2n \fB0..9\fP Using the number keys, move to the selected line. .br .ti -2n \fBmouseclick\fP Move to the selected line. Available when \*Qmousetrack\*U is set to \*Qon\*U .br .ti -2n \fB/\fP Search. .br .ti -2n \fBn\fP Repeat search in the forward direction. .br .ti -2n \fBN\fP Repeat search in the backward direction. .br .ti -2n \fBm\fP Toggle MRU. .br .ti -2n \fBg\fP Toggle group nesting. .br .ti -2n \fBa\fP All window view. .br .ti -2n \fBC-h\fP or backspace Back out the group. .br .ti -2n \fB,\fP Switch numbers with the previous window. .br .ti -2n \fB.\fP Switch numbers with the next window. .br .ti -2n \fBK\fP Kill that window. .br .ti -2n \fBspace\fP or \fBenter\fP Select that window. .br .in -4n The table format can be changed with the \fBstring\fP and \fBtitle\fP option, the title is displayed as table heading, while the lines are made by using the string setting. The default setting is \*QNum Name%=Flags\*U for the title and \*Q%3n %t%=%f\*U for the lines. See the \*QSTRING ESCAPES\*U chapter for more codes (e.g. color settings). \*QWindowlist\*U needs a region size of at least 10 characters wide and 6 characters high in order to display. .sp .ne 3 .B windows .PP Uses the message line to display a list of all the windows. Each window is listed by number with the name of process that has been started in the window (or its title); the current window is marked with a `*'; the previous window is marked with a `-'; all the windows that are \*Qlogged in\*U are marked with a `$'; a background window that has received a bell is marked with a `!'; a background window that is being monitored and has had activity occur is marked with an `@'; a window which has output logging turned on is marked with `(L)'; windows occupied by other users are marked with `&'; windows in the zombie state are marked with `Z'. If this list is too long to fit on the terminal's status line only the portion around the current window is displayed. .sp .ne 3 .BR "wrap " [ on | off ] .PP Sets the line-wrap setting for the current window. When line-wrap is on, the second consecutive printable character output at the last column of a line will wrap to the start of the following line. As an added feature, backspace (^H) will also wrap through the left margin to the previous line. Default is `on'. Without any options, the state of wrap is toggled. .sp .ne 3 .B writebuf .RB [ -e .IR encoding ] .RI [ filename ] .PP Writes the contents of the paste buffer to the specified file, or the public accessible screen-exchange file if no filename is given. This is thought of as a primitive means of communication between .I screen users on the same host. If an encoding is specified the paste buffer is recoded on the fly to match the encoding. The filename can be set with the \fIbufferfile\fP command and defaults to \*Q/tmp/screen-exchange\*U. .sp .ne 3 .BR "writelock " [ on | "off\fR|\fBauto\fR]" .PP In addition to access control lists, not all users may be able to write to the same window at once. Per default, writelock is in `auto' mode and grants exclusive input permission to the user who is the first to switch to the particular window. When he leaves the window, other users may obtain the writelock (automatically). The writelock of the current window is disabled by the command \*Qwritelock off\*U. If the user issues the command \*Qwritelock on\*U he keeps the exclusive write permission while switching to other windows. .sp .ne 3 .B xoff .br .B xon .PP Insert a CTRL-s / CTRL-q character to the stdin queue of the current window. .sp .ne 3 .B zmodem .RB [ off\fR|\fPauto\fR|\fPcatch\fR|\fPpass ] .br .B "zmodem sendcmd" .RI [ string ] .br .B "zmodem recvcmd" .RI [ string ] .PP Define zmodem support for screen. Screen understands two different modes when it detects a zmodem request: \*Qpass\*U and \*Qcatch\*U. If the mode is set to \*Qpass\*U, screen will relay all data to the attacher until the end of the transmission is reached. In \*Qcatch\*U mode screen acts as a zmodem endpoint and starts the corresponding rz/sz commands. If the mode is set to \*Qauto\*U, screen will use \*Qcatch\*U if the window is a tty (e.g. a serial line), otherwise it will use \*Qpass\*U. .br You can define the templates screen uses in \*Qcatch\*U mode via the second and the third form. .br Note also that this is an experimental feature. .sp .ne 3 .BR "zombie " [\fIkeys\fP [ onerror ] ] .br .BR "defzombie " [\fIkeys\fP] .PP Per default .I screen windows are removed from the window list as soon as the windows process (e.g. shell) exits. When a string of two keys is specified to the zombie command, `dead' windows will remain in the list. The \fBkill\fP command may be used to remove such a window. Pressing the first key in the dead window has the same effect. When pressing the second key, .I screen will attempt to resurrect the window. The process that was initially running in the window will be launched again. Calling \fBzombie\fP without parameters will clear the zombie setting, thus making windows disappear when their process exits. As the zombie-setting is manipulated globally for all windows, this command should only be called \fBdefzombie\fP. Until we need this as a per window setting, the commands \fBzombie\fP and \fBdefzombie\fP are synonymous. Optionally you can put the word \*Qonerror\*U after the keys. This will cause screen to monitor exit status of the process running in the window. If it exits normally ('0'), the window disappears. Any other exit value causes the window to become a zombie. .SH "THE MESSAGE LINE" .I Screen displays informational messages and other diagnostics in a \fImessage line\fP. While this line is distributed to appear at the bottom of the screen, it can be defined to appear at the top of the screen during compilation. If your terminal has a status line defined in its termcap, .I screen will use this for displaying its messages, otherwise a line of the current screen will be temporarily overwritten and output will be momentarily interrupted. The message line is automatically removed after a few seconds delay, but it can also be removed early (on terminals without a status line) by beginning to type. .PP The message line facility can be used by an application running in the current window by means of the ANSI \fIPrivacy message\fP control sequence. For instance, from within the shell, try something like: .IP echo '^Hello world from window '$WINDOW'\e\e' .PP where '' is an \fIescape\fP, '^' is a literal up-arrow, and '\e\e' turns into a single backslash. .SH "WINDOW TYPES" Screen provides three different window types. New windows are created with .IR screen 's .B screen command (see also the entry in chapter \*QCUSTOMIZATION\*U). The first parameter to the .B screen command defines which type of window is created. The different window types are all special cases of the normal type. They have been added in order to allow .I screen to be used efficiently as a console multiplexer with 100 or more windows. .IP \(bu 3 The normal window contains a shell (default, if no parameter is given) or any other system command that could be executed from a shell (e.g. .BR slogin , etc...) .IP \(bu If a tty (character special device) name (e.g. \*Q/dev/ttya\*U) is specified as the first parameter, then the window is directly connected to this device. This window type is similar to \*Qscreen cu -l /dev/ttya\*U. Read and write access is required on the device node, an exclusive open is attempted on the node to mark the connection line as busy. An optional parameter is allowed consisting of a comma separated list of flags in the notation used by stty(1): .RS .IP Usually 300, 1200, 9600 or 19200. This affects transmission as well as receive speed. .IP "cs8 or cs7" Specify the transmission of eight (or seven) bits per byte. .IP "ixon or -ixon" Enables (or disables) software flow-control (CTRL-S/CTRL-Q) for sending data. .IP "ixoff or -ixoff" Enables (or disables) software flow-control for receiving data. .IP "istrip or -istrip" Clear (or keep) the eight bit in each received byte. .PP You may want to specify as many of these options as applicable. Unspecified options cause the terminal driver to make up the parameter values of the connection. These values are system dependent and may be in defaults or values saved from a previous connection. .PP For tty windows, the .B info command shows some of the modem control lines in the status line. These may include `RTS', `CTS', 'DTR', `DSR', `CD' and more. This depends on the available ioctl()'s and system header files as well as the on the physical capabilities of the serial board. Signals that are logical low (inactive) have their name preceded by an exclamation mark (!), otherwise the signal is logical high (active). Signals not supported by the hardware but available to the ioctl() interface are usually shown low. .PP When the CLOCAL status bit is true, the whole set of modem signals is placed inside curly braces ({ and }). When the CRTSCTS or TIOCSOFTCAR bit is set, the signals `CTS' or `CD' are shown in parenthesis, respectively. .PP For tty windows, the command .B break causes the Data transmission line (TxD) to go low for a specified period of time. This is expected to be interpreted as break signal on the other side. No data is sent and no modem control line is changed when a .B break is issued. .RE .IP \(bu If the first parameter is \*Q//telnet\*U, the second parameter is expected to be a host name, and an optional third parameter may specify a TCP port number (default decimal 23). Screen will connect to a server listening on the remote host and use the telnet protocol to communicate with that server. .br .br For telnet windows, the command .B info shows details about the connection in square brackets ([ and ]) at the end of the status line. .RS .IP b BINARY. The connection is in binary mode. .IP e ECHO. Local echo is disabled. .IP c SGA. The connection is in `character mode' (default: `line mode'). .IP t TTYPE. The terminal type has been requested by the remote host. Screen sends the name \*Qscreen\*U unless instructed otherwise (see also the command `term'). .IP w NAWS. The remote site is notified about window size changes. .IP f LFLOW. The remote host will send flow control information. (Ignored at the moment.) .PP Additional flags for debugging are x, t and n (XDISPLOC, TSPEED and NEWENV). .PP For telnet windows, the command .B break sends the telnet code IAC BREAK (decimal 243) to the remote host. This window type is only available if .I screen was compiled with the BUILTIN_TELNET option defined. .RE .SH "STRING ESCAPES" Screen provides an escape mechanism to insert information like the current time into messages or file names. The escape character is '%' with one exception: inside of a window's hardstatus '^%' ('^E') is used instead. Here is the full list of supported escapes: .IP % the escape character itself .IP a either 'am' or 'pm' .IP A either 'AM' or 'PM' .IP c current time HH:MM in 24h format .IP C current time HH:MM in 12h format .IP d day number .IP D weekday name .IP E sets %? to true if the escape character has been pressed. .IP f flags of the window, see \*Qwindows\*U for meanings of the various flags .IP F sets %? to true if the window has the focus .IP h hardstatus of the window .IP H hostname of the system .IP l current load of the system .IP m month number .IP M month name .IP n window number .IP P sets %? to true if the current region is in copy/paste mode .IP S session name .IP s seconds .IP t window title .IP u all other users on this window .IP w all window numbers and names. With '-' qualifier: up to the current window; with '+' qualifier: starting with the window after the current one. .IP W all window numbers and names except the current one .IP y last two digits of the year number .IP Y full year number .IP ? the part to the next '%?' is displayed only if a '%' escape inside the part expands to a non-empty string .IP : else part of '%?' .IP = pad the string to the display's width (like TeX's hfill). If a number is specified, pad to the percentage of the window's width. A '0' qualifier tells screen to treat the number as absolute position. You can specify to pad relative to the last absolute pad position by adding a '+' qualifier or to pad relative to the right margin by using '-'. The padding truncates the string if the specified position lies before the current position. Add the 'L' qualifier to change this. .IP < same as '%=' but just do truncation, do not fill with spaces .IP > mark the current text position for the next truncation. When screen needs to do truncation, it tries to do it in a way that the marked position gets moved to the specified percentage of the output area. (The area starts from the last absolute pad position and ends with the position specified by the truncation operator.) The 'L' qualifier tells screen to mark the truncated parts with '...'. .IP { attribute/color modifier string terminated by the next \*Q}\*U .IP ` Substitute with the output of a 'backtick' command. The length qualifier is misused to identify one of the commands. .P The 'c' and 'C' escape may be qualified with a '0' to make .I screen use zero instead of space as fill character. The '0' qualifier also makes the '=' escape use absolute positions. The 'n' and '=' escapes understand a length qualifier (e.g. '%3n'), 'D' and 'M' can be prefixed with 'L' to generate long names, 'w' and 'W' also show the window flags if 'L' is given. .PP An attribute/color modifier is is used to change the attributes or the color settings. Its format is \*Q[attribute modifier] [color description]\*U. The attribute modifier must be prefixed by a change type indicator if it can be confused with a color description. The following change types are known: .IP + add the specified set to the current attributes .IP - remove the set from the current attributes .IP ! invert the set in the current attributes .IP = change the current attributes to the specified set .PP The attribute set can either be specified as a hexadecimal number or a combination of the following letters: .IP d dim .PD 0 .IP u underline .IP b bold .IP r reverse .IP s standout .IP B blinking .PD .PP Colors are coded either as a hexadecimal number or two letters specifying the desired background and foreground color (in that order). The following colors are known: .IP k black .PD 0 .IP r red .IP g green .IP y yellow .IP b blue .IP m magenta .IP c cyan .IP w white .IP d default color .IP . leave color unchanged .PD .PP The capitalized versions of the letter specify bright colors. You can also use the pseudo-color 'i' to set just the brightness and leave the color unchanged. .br A one digit/letter color description is treated as foreground or background color dependent on the current attributes: if reverse mode is set, the background color is changed instead of the foreground color. If you don't like this, prefix the color with a \*Q.\*U. If you want the same behavior for two-letter color descriptions, also prefix them with a \*Q.\*U. .br As a special case, \*Q%{-}\*U restores the attributes and colors that were set before the last change was made (i.e., pops one level of the color-change stack). .PP Examples: .IP "\*QG\*U" set color to bright green .IP "\*Q+b r\*U" use bold red .IP "\*Q= yd\*U" clear all attributes, write in default color on yellow background. .IP "%-Lw%{= BW}%50>%n%f* %t%{-}%+Lw%<" The available windows centered at the current window and truncated to the available width. The current window is displayed white on blue. This can be used with \*Qhardstatus alwayslastline\*U. .IP "%?%F%{.R.}%?%3n %t%? [%h]%?" The window number and title and the window's hardstatus, if one is set. Also use a red background if this is the active focus. Useful for \*Qcaption string\*U. .SH "FLOW-CONTROL" Each window has a flow-control setting that determines how .I screen deals with the XON and XOFF characters (and perhaps the interrupt character). When flow-control is turned off, .I screen ignores the XON and XOFF characters, which allows the user to send them to the current program by simply typing them (useful for the \fIemacs\fP editor, for instance). The trade-off is that it will take longer for output from a \*Qnormal\*U program to pause in response to an XOFF. With flow-control turned on, XON and XOFF characters are used to immediately pause the output of the current window. You can still send these characters to the current program, but you must use the appropriate two-character .I screen commands (typically \*QC-a q\*U (xon) and \*QC-a s\*U (xoff)). The xon/xoff commands are also useful for typing C-s and C-q past a terminal that intercepts these characters. .PP Each window has an initial flow-control value set with either the .B \-f option or the \*Qdefflow\*U .screenrc command. Per default the windows are set to automatic flow-switching. It can then be toggled between the three states 'fixed on', 'fixed off' and 'automatic' interactively with the \*Qflow\*U command bound to "C-a f". .PP The automatic flow-switching mode deals with flow control using the TIOCPKT mode (like \*Qrlogin\*U does). If the tty driver does not support TIOCPKT, .I screen tries to find out the right mode based on the current setting of the application keypad \- when it is enabled, flow-control is turned off and visa versa. Of course, you can still manipulate flow-control manually when needed. .PP If you're running with flow-control enabled and find that pressing the interrupt key (usually C-c) does not interrupt the display until another 6-8 lines have scrolled by, try running .I screen with the \*Qinterrupt\*U option (add the \*Qinterrupt\*U flag to the \*Qflow\*U command in your .screenrc, or use the .B \-i command-line option). This causes the output that .I screen has accumulated from the interrupted program to be flushed. One disadvantage is that the virtual terminal's memory contains the non-flushed version of the output, which in rare cases can cause minor inaccuracies in the output. For example, if you switch screens and return, or update the screen with \*QC-a l\*U you would see the version of the output you would have gotten without \*Qinterrupt\*U being on. Also, you might need to turn off flow-control (or use auto-flow mode to turn it off automatically) when running a program that expects you to type the interrupt character as input, as it is possible to interrupt the output of the virtual terminal to your physical terminal when flow-control is enabled. If this happens, a simple refresh of the screen with \*QC-a l\*U will restore it. Give each mode a try, and use whichever mode you find more comfortable. .SH "TITLES (naming windows)" You can customize each window's name in the window display (viewed with the \*Qwindows\*U command (C-a w)) by setting it with one of the title commands. Normally the name displayed is the actual command name of the program created in the window. However, it is sometimes useful to distinguish various programs of the same name or to change the name on-the-fly to reflect the current state of the window. .PP The default name for all shell windows can be set with the \*Qshelltitle\*U command in the .screenrc file, while all other windows are created with a \*Qscreen\*U command and thus can have their name set with the .B \-t option. Interactively, there is the title-string escape-sequence (k\fIname\fP\e) and the \*Qtitle\*U command (C-a A). The former can be output from an application to control the window's name under software control, and the latter will prompt for a name when typed. You can also bind pre-defined names to keys with the \*Qtitle\*U command to set things quickly without prompting. .PP Finally, .I screen has a shell-specific heuristic that is enabled by setting the window's name to \*Q\fIsearch|name\fP\*U and arranging to have a null title escape-sequence output as a part of your prompt. The \fIsearch\fP portion specifies an end-of-prompt search string, while the \fIname\fP portion specifies the default shell name for the window. If the \fIname\fP ends in a `:' .I screen will add what it believes to be the current command running in the window to the end of the window's shell name (e.\|g. \*Q\fIname:cmd\fP\*U). Otherwise the current command name supersedes the shell name while it is running. .PP Here's how it works: you must modify your shell prompt to output a null title-escape-sequence (k\e) as a part of your prompt. The last part of your prompt must be the same as the string you specified for the \fIsearch\fP portion of the title. Once this is set up, .I screen will use the title-escape-sequence to clear the previous command name and get ready for the next command. Then, when a newline is received from the shell, a search is made for the end of the prompt. If found, it will grab the first word after the matched string and use it as the command name. If the command name begins with either '!', '%', or '^' .I screen will use the first word on the following line (if found) in preference to the just-found name. This helps csh users get better command names when using job control or history recall commands. .PP Here's some .screenrc examples: .IP screen -t top 2 nice top .PP Adding this line to your .screenrc would start a nice-d version of the \*Qtop\*U command in window 2 named \*Qtop\*U rather than \*Qnice\*U. .sp .nf shelltitle '> |csh' screen 1 .fi .sp These commands would start a shell with the given shelltitle. The title specified is an auto-title that would expect the prompt and the typed command to look something like the following: .IP /usr/joe/src/dir> trn .PP (it looks after the '> ' for the command name). The window status would show the name \*Qtrn\*U while the command was running, and revert to \*Qcsh\*U upon completion. .IP bind R screen -t '% |root:' su .PP Having this command in your .screenrc would bind the key sequence \*QC-a R\*U to the \*Qsu\*U command and give it an auto-title name of \*Qroot:\*U. For this auto-title to work, the screen could look something like this: .sp .nf % !em emacs file.c .fi .sp Here the user typed the csh history command \*Q!em\*U which ran the previously entered \*Qemacs\*U command. The window status would show \*Qroot:emacs\*U during the execution of the command, and revert to simply \*Qroot:\*U at its completion. .PP .nf bind o title bind E title "" bind u title (unknown) .fi .sp The first binding doesn't have any arguments, so it would prompt you for a title. when you type \*QC-a o\*U. The second binding would clear an auto-title's current setting (C-a E). The third binding would set the current window's title to \*Q(unknown)\*U (C-a u). .PP One thing to keep in mind when adding a null title-escape-sequence to your prompt is that some shells (like the csh) count all the non-control characters as part of the prompt's length. If these invisible characters aren't a multiple of 8 then backspacing over a tab will result in an incorrect display. One way to get around this is to use a prompt like this: .IP set prompt='^[[0000m^[k^[\e% ' .PP The escape-sequence \*Q[0000m\*U not only normalizes the character attributes, but all the zeros round the length of the invisible characters up to 8. Bash users will probably want to echo the escape sequence in the PROMPT_COMMAND: .IP PROMPT_COMMAND='printf "\e033k\e033\e134"' .PP (I used \*Q\134\*U to output a `\e' because of a bug in bash v1.04). .SH "THE VIRTUAL TERMINAL" Each window in a .I screen session emulates a VT100 terminal, with some extra functions added. The VT100 emulator is hard-coded, no other terminal types can be emulated. .br Usually .I screen tries to emulate as much of the VT100/ANSI standard as possible. But if your terminal lacks certain capabilities, the emulation may not be complete. In these cases .I screen has to tell the applications that some of the features are missing. This is no problem on machines using termcap, because .I screen can use the $TERMCAP variable to customize the standard .I screen termcap. .PP But if you do a rlogin on another machine or your machine supports only terminfo this method fails. Because of this, .I screen offers a way to deal with these cases. Here is how it works: .PP When .I screen tries to figure out a terminal name for itself, it first looks for an entry named \*Qscreen.\*U, where is the contents of your $TERM variable. If no such entry exists, .I screen tries \*Qscreen\*U (or \*Qscreen-w\*U if the terminal is wide (132 cols or more)). If even this entry cannot be found, \*Qvt100\*U is used as a substitute. .PP The idea is that if you have a terminal which doesn't support an important feature (e.g. delete char or clear to EOS) you can build a new termcap/terminfo entry for .I screen (named \*Qscreen.\*U) in which this capability has been disabled. If this entry is installed on your machines you are able to do a rlogin and still keep the correct termcap/terminfo entry. The terminal name is put in the $TERM variable of all new windows. .I Screen also sets the $TERMCAP variable reflecting the capabilities of the virtual terminal emulated. Notice that, however, on machines using the terminfo database this variable has no effect. Furthermore, the variable $WINDOW is set to the window number of each window. .PP The actual set of capabilities supported by the virtual terminal depends on the capabilities supported by the physical terminal. If, for instance, the physical terminal does not support underscore mode, .I screen does not put the `us' and `ue' capabilities into the window's $TERMCAP variable, accordingly. However, a minimum number of capabilities must be supported by a terminal in order to run .IR screen ; namely scrolling, clear screen, and direct cursor addressing (in addition, .I screen does not run on hardcopy terminals or on terminals that over-strike). .PP Also, you can customize the $TERMCAP value used by .I screen by using the \*Qtermcap\*U .screenrc command, or by defining the variable $SCREENCAP prior to startup. When the is latter defined, its value will be copied verbatim into each window's $TERMCAP variable. This can either be the full terminal definition, or a filename where the terminal \*Qscreen\*U (and/or \*Qscreen-w\*U) is defined. .PP Note that .I screen honors the \*Qterminfo\*U .screenrc command if the system uses the terminfo database rather than termcap. .PP When the boolean `G0' capability is present in the termcap entry for the terminal on which .I screen has been called, the terminal emulation of .I screen supports multiple character sets. This allows an application to make use of, for instance, the VT100 graphics character set or national character sets. The following control functions from ISO 2022 are supported: \fIlock shift G0\fP (\fISI\fP), \fIlock shift G1\fP (\fISO\fP), \fIlock shift G2\fP, \fIlock shift G3\fP, \fIsingle shift G2\fP, and \fIsingle shift G3\fP. When a virtual terminal is created or reset, the ASCII character set is designated as \fIG0\fP through \fIG3\fP. When the `G0' capability is present, .I screen evaluates the capabilities `S0', `E0', and `C0' if present. `S0' is the sequence the terminal uses to enable and start the graphics character set rather than \fISI\fP. `E0' is the corresponding replacement for \fISO\fP. `C0' gives a character by character translation string that is used during semi-graphics mode. This string is built like the `acsc' terminfo capability. .PP When the `po' and `pf' capabilities are present in the terminal's termcap entry, applications running in a .I screen window can send output to the printer port of the terminal. This allows a user to have an application in one window sending output to a printer connected to the terminal, while all other windows are still active (the printer port is enabled and disabled again for each chunk of output). As a side-effect, programs running in different windows can send output to the printer simultaneously. Data sent to the printer is not displayed in the window. The .I info command displays a line starting `PRIN' while the printer is active. .PP .I Screen maintains a hardstatus line for every window. If a window gets selected, the display's hardstatus will be updated to match the window's hardstatus line. If the display has no hardstatus the line will be displayed as a standard .I screen message. The hardstatus line can be changed with the ANSI Application Program Command (APC): \*QESC_ESC\e\*U. As a convenience for xterm users the sequence \*QESC]0..2;^G\*U is also accepted. .PP Some capabilities are only put into the $TERMCAP variable of the virtual terminal if they can be efficiently implemented by the physical terminal. For instance, `dl' (delete line) is only put into the $TERMCAP variable if the terminal supports either delete line itself or scrolling regions. Note that this may provoke confusion, when the session is reattached on a different terminal, as the value of $TERMCAP cannot be modified by parent processes. .PP The "alternate screen" capability is not enabled by default. Set the \fBaltscreen\fP .screenrc command to enable it. .PP The following is a list of control sequences recognized by .IR screen . \*Q(V)\*U and \*Q(A)\*U indicate VT100-specific and ANSI- or ISO-specific functions, respectively. .PP .ta 22n .TP 27 .B "ESC E" Next Line .TP 27 .B "ESC D" Index .TP 27 .B "ESC M" Reverse Index .TP 27 .B "ESC H" Horizontal Tab Set .TP 27 .B "ESC Z" Send VT100 Identification String .TP 27 .BR "ESC 7" " (V)" Save Cursor and Attributes .TP 27 .BR "ESC 8" " (V)" Restore Cursor and Attributes .TP 27 .BR "ESC [s" " (A)" Save Cursor and Attributes .TP 27 .BR "ESC [u" " (A)" Restore Cursor and Attributes .TP 27 .B "ESC c" Reset to Initial State .TP 27 .B "ESC g" Visual Bell .TP 27 .B "ESC \fPPn\fB p" Cursor Visibility (97801) .TP 27 \h'\w'ESC 'u'Pn = \fB6\fP Invisible .TP 27 \h'\w'ESC Pn = 'u'\fB7\fP Visible .TP 27 .BR "ESC =" " (V)" Application Keypad Mode .TP 27 .BR "ESC >" " (V)" Numeric Keypad Mode .TP 27 .BR "ESC # 8" " (V)" Fill Screen with E's .TP 27 .BR "ESC \e" " (A)" String Terminator .TP 27 .BR "ESC ^" " (A)" Privacy Message String (Message Line) .TP 27 .B "ESC !" Global Message String (Message Line) .TP 27 .B "ESC k" A.\|k.\|a. Definition String .TP 27 .BR "ESC P" " (A)" Device Control String. Outputs a string directly to the host terminal without interpretation. .TP 27 .BR "ESC _" " (A)" Application Program Command (Hardstatus) .TP 27 .BR "ESC ] 0 ; string ^G" " (A)" Operating System Command (Hardstatus, xterm title hack) .TP 27 .BR "ESC ] 83 ; cmd ^G" " (A)" Execute screen command. This only works if multi-user support is compiled into screen. The pseudo-user \*Q:window:\*U is used to check the access control list. Use \*Qaddacl :window: -rwx #?\*U to create a user with no rights and allow only the needed commands. .TP 27 .BR "Control-N" " (A)" Lock Shift G1 (SO) .TP 27 .BR "Control-O" " (A)" Lock Shift G0 (SI) .TP 27 .BR "ESC n" " (A)" Lock Shift G2 .TP 27 .BR "ESC o" " (A)" Lock Shift G3 .TP 27 .BR "ESC N" " (A)" Single Shift G2 .TP 27 .BR "ESC O" " (A)" Single Shift G3 .TP 27 .BR "ESC ( \fPPcs" " (A)" Designate character set as G0 .TP 27 .BR "ESC ) \fPPcs" " (A)" Designate character set as G1 .TP 27 .BR "ESC * \fPPcs" " (A)" Designate character set as G2 .TP 27 .BR "ESC + \fPPcs" " (A)" Designate character set as G3 .TP 27 .B "ESC [ \fPPn\fB ; \fPPn\fB H" Direct Cursor Addressing .TP 27 .B "ESC [ \fPPn\fB ; \fPPn\fB f" same as above .TP 27 .B "ESC [ \fPPn\fB J" Erase in Display .TP 27 \h'\w'ESC [ 'u'Pn = None or \fB0\fP From Cursor to End of Screen .TP 27 \h'\w'ESC [ Pn = 'u'\fB1\fP From Beginning of Screen to Cursor .TP 27 \h'\w'ESC [ Pn = 'u'\fB2\fP Entire Screen .TP 27 .B "ESC [ \fPPn\fB K" Erase in Line .TP 27 \h'\w'ESC [ 'u'Pn = None or \fB0\fP From Cursor to End of Line .TP 27 \h'\w'ESC [ Pn = 'u'\fB1\fP From Beginning of Line to Cursor .TP 27 \h'\w'ESC [ Pn = 'u'\fB2\fP Entire Line .TP 27 .B "ESC [ \fPPn\fB X" Erase character .TP 27 .B "ESC [ \fPPn\fB A" Cursor Up .TP 27 .B "ESC [ \fPPn\fB B" Cursor Down .TP 27 .B "ESC [ \fPPn\fB C" Cursor Right .TP 27 .B "ESC [ \fPPn\fB D" Cursor Left .TP 27 .B "ESC [ \fPPn\fB E" Cursor next line .TP 27 .B "ESC [ \fPPn\fB F" Cursor previous line .TP 27 .B "ESC [ \fPPn\fB G" Cursor horizontal position .TP 27 .B "ESC [ \fPPn\fB `" same as above .TP 27 .B "ESC [ \fPPn\fB d" Cursor vertical position .TP 27 .B "ESC [ \fPPs\fB ;\fP...\fB; \fPPs\fB m" Select Graphic Rendition .TP 27 \h'\w'ESC [ 'u'Ps = None or \fB0\fP Default Rendition .TP 27 \h'\w'ESC [ Ps = 'u'\fB1\fP Bold .TP 27 \h'\w'ESC [ Ps = 'u'\fB2\fP (A) Faint .TP 27 \h'\w'ESC [ Ps = 'u'\fB3\fP (A) \fIStandout\fP Mode (ANSI: Italicized) .TP 27 \h'\w'ESC [ Ps = 'u'\fB4\fP Underlined .TP 27 \h'\w'ESC [ Ps = 'u'\fB5\fP Blinking .TP 27 \h'\w'ESC [ Ps = 'u'\fB7\fP Negative Image .TP 27 \h'\w'ESC [ Ps = 'u'\fB22\fP (A) Normal Intensity .TP 27 \h'\w'ESC [ Ps = 'u'\fB23\fP (A) \fIStandout\fP Mode off (ANSI: Italicized off) .TP 27 \h'\w'ESC [ Ps = 'u'\fB24\fP (A) Not Underlined .TP 27 \h'\w'ESC [ Ps = 'u'\fB25\fP (A) Not Blinking .TP 27 \h'\w'ESC [ Ps = 'u'\fB27\fP (A) Positive Image .TP 27 \h'\w'ESC [ Ps = 'u'\fB30\fP (A) Foreground Black .TP 27 \h'\w'ESC [ Ps = 'u'\fB31\fP (A) Foreground Red .TP 27 \h'\w'ESC [ Ps = 'u'\fB32\fP (A) Foreground Green .TP 27 \h'\w'ESC [ Ps = 'u'\fB33\fP (A) Foreground Yellow .TP 27 \h'\w'ESC [ Ps = 'u'\fB34\fP (A) Foreground Blue .TP 27 \h'\w'ESC [ Ps = 'u'\fB35\fP (A) Foreground Magenta .TP 27 \h'\w'ESC [ Ps = 'u'\fB36\fP (A) Foreground Cyan .TP 27 \h'\w'ESC [ Ps = 'u'\fB37\fP (A) Foreground White .TP 27 \h'\w'ESC [ Ps = 'u'\fB39\fP (A) Foreground Default .TP 27 \h'\w'ESC [ Ps = 'u'\fB40\fP (A) Background Black .TP 27 \h'\w'ESC [ Ps = 'u'\fB...\fP ... .TP 27 \h'\w'ESC [ Ps = 'u'\fB49\fP (A) Background Default .TP 27 .B "ESC [ \fPPn\fB g" Tab Clear .TP 27 \h'\w'ESC [ 'u'Pn = None or \fB0\fP Clear Tab at Current Position .TP 27 \h'\w'ESC [ Ps = 'u'\fB3\fP Clear All Tabs .TP 27 .BR "ESC [ \fPPn\fB ; \fPPn\fB r" " (V)" Set Scrolling Region .TP 27 .BR "ESC [ \fPPn\fB I" " (A)" Horizontal Tab .TP 27 .BR "ESC [ \fPPn\fB Z" " (A)" Backward Tab .TP 27 .BR "ESC [ \fPPn\fB L" " (A)" Insert Line .TP 27 .BR "ESC [ \fPPn\fB M" " (A)" Delete Line .TP 27 .BR "ESC [ \fPPn\fB @" " (A)" Insert Character .TP 27 .BR "ESC [ \fPPn\fB P" " (A)" Delete Character .TP 27 .B "ESC [ \fPPn\fB S" Scroll Scrolling Region Up .TP 27 .B "ESC [ \fPPn\fB T" Scroll Scrolling Region Down .TP 27 .B "ESC [ \fPPn\fB ^" same as above .TP 27 .B "ESC [ \fPPs\fB ;\fP...\fB; \fPPs\fB h" Set Mode .TP 27 .B "ESC [ \fPPs\fB ;\fP...\fB; \fPPs\fB l" Reset Mode .TP 27 \h'\w'ESC [ 'u'Ps = \fB4\fP (A) Insert Mode .TP 27 \h'\w'ESC [ Ps = 'u'\fB20\fP (A) \fIAutomatic Linefeed\fP Mode .TP 27 \h'\w'ESC [ Ps = 'u'\fB34\fP Normal Cursor Visibility .TP 27 \h'\w'ESC [ Ps = 'u'\fB?1\fP (V) Application Cursor Keys .TP 27 \h'\w'ESC [ Ps = 'u'\fB?3\fP (V) Change Terminal Width to 132 columns .TP 27 \h'\w'ESC [ Ps = 'u'\fB?5\fP (V) Reverse Video .TP 27 \h'\w'ESC [ Ps = 'u'\fB?6\fP (V) \fIOrigin\fP Mode .TP 27 \h'\w'ESC [ Ps = 'u'\fB?7\fP (V) \fIWrap\fP Mode .TP 27 \h'\w'ESC [ Ps = 'u'\fB?9\fP X10 mouse tracking .TP 27 \h'\w'ESC [ Ps = 'u'\fB?25\fP (V) Visible Cursor .TP 27 \h'\w'ESC [ Ps = 'u'\fB?47\fP Alternate Screen (old xterm code) .TP 27 \h'\w'ESC [ Ps = 'u'\fB?1000\fP (V) VT200 mouse tracking .TP 27 \h'\w'ESC [ Ps = 'u'\fB?1047\fP Alternate Screen (new xterm code) .TP 27 \h'\w'ESC [ Ps = 'u'\fB?1049\fP Alternate Screen (new xterm code) .TP 27 .BR "ESC [ 5 i" " (A)" Start relay to printer (ANSI Media Copy) .TP 27 .BR "ESC [ 4 i" " (A)" Stop relay to printer (ANSI Media Copy) .TP 27 .B "ESC [ 8 ; \fPPh\fB ; \fPPw\fB t" Resize the window to `Ph' lines and `Pw' columns (SunView special) .TP 27 .B "ESC [ c" Send VT100 Identification String .TP 27 .B "ESC [ x" Send Terminal Parameter Report .TP 27 .B "ESC [ > c" Send VT220 Secondary Device Attributes String .TP 27 .B "ESC [ 6 n" Send Cursor Position Report .SH "INPUT TRANSLATION" In order to do a full VT100 emulation .I screen has to detect that a sequence of characters in the input stream was generated by a keypress on the user's keyboard and insert the VT100 style escape sequence. \fIScreen\fP has a very flexible way of doing this by making it possible to map arbitrary commands on arbitrary sequences of characters. For standard VT100 emulation the command will always insert a string in the input buffer of the window (see also command \fBstuff\fP in the command table). Because the sequences generated by a keypress can change after a reattach from a different terminal type, it is possible to bind commands to the termcap name of the keys. \fIScreen\fP will insert the correct binding after each reattach. See the \fBbindkey\fP command for further details on the syntax and examples. .PP Here is the table of the default key bindings. (A) means that the command is executed if the keyboard is switched into application mode. .PP .ta 18n 34n 50n .nf Key name Termcap name Command \l'54n' .ta 22n 34n 50n Cursor up ku stuff \e033[A stuff \e033OA (A) Cursor down kd stuff \e033[B stuff \e033OB (A) Cursor right kr stuff \e033[C stuff \e033OC (A) Cursor left kl stuff \e033[D stuff \e033OD (A) Function key 0 k0 stuff \e033[10~ Function key 1 k1 stuff \e033OP Function key 2 k2 stuff \e033OQ Function key 3 k3 stuff \e033OR Function key 4 k4 stuff \e033OS Function key 5 k5 stuff \e033[15~ Function key 6 k6 stuff \e033[17~ Function key 7 k7 stuff \e033[18~ Function key 8 k8 stuff \e033[19~ Function key 9 k9 stuff \e033[20~ Function key 10 k; stuff \e033[21~ Function key 11 F1 stuff \e033[23~ Function key 12 F2 stuff \e033[24~ Home kh stuff \e033[1~ End kH stuff \e033[4~ Insert kI stuff \e033[2~ Delete kD stuff \e033[3~ Page up kP stuff \e033[5~ Page down kN stuff \e033[6~ Keypad 0 f0 stuff 0 stuff \e033Op (A) Keypad 1 f1 stuff 1 stuff \e033Oq (A) Keypad 2 f2 stuff 2 stuff \e033Or (A) Keypad 3 f3 stuff 3 stuff \e033Os (A) Keypad 4 f4 stuff 4 stuff \e033Ot (A) Keypad 5 f5 stuff 5 stuff \e033Ou (A) Keypad 6 f6 stuff 6 stuff \e033Ov (A) Keypad 7 f7 stuff 7 stuff \e033Ow (A) Keypad 8 f8 stuff 8 stuff \e033Ox (A) Keypad 9 f9 stuff 9 stuff \e033Oy (A) Keypad + f+ stuff + stuff \e033Ok (A) Keypad - f- stuff - stuff \e033Om (A) Keypad * f* stuff * stuff \e033Oj (A) Keypad / f/ stuff / stuff \e033Oo (A) Keypad = fq stuff = stuff \e033OX (A) Keypad . f. stuff . stuff \e033On (A) Keypad , f, stuff , stuff \e033Ol (A) Keypad enter fe stuff \e015 stuff \e033OM (A) .fi .SH SPECIAL TERMINAL CAPABILITIES The following table describes all terminal capabilities that are recognized by .I screen and are not in the termcap(5) manual. You can place these capabilities in your termcap entries (in `/etc/termcap') or use them with the commands `termcap', `terminfo' and `termcapinfo' in your screenrc files. It is often not possible to place these capabilities in the terminfo database. .PP .ta 5n .TP 13 .BI LP " (bool)" Terminal has VT100 style margins (`magic margins'). Note that this capability is obsolete because .I screen uses the standard 'xn' instead. .TP 13 .BI Z0 " (str)" Change width to 132 columns. .TP 13 .BI Z1 " (str)" Change width to 80 columns. .TP 13 .BI WS " (str)" Resize display. This capability has the desired width and height as arguments. \fISunView(tm)\fP example: '\eE[8;%d;%dt'. .TP 13 .BI NF " (bool)" Terminal doesn't need flow control. Send ^S and ^Q direct to the application. Same as 'flow off'. The opposite of this capability is 'nx'. .TP 13 .BI G0 " (bool)" Terminal can deal with ISO 2022 font selection sequences. .TP 13 .BI S0 " (str)" Switch charset 'G0' to the specified charset. Default is '\eE(%.'. .TP 13 .BI E0 " (str)" Switch charset 'G0' back to standard charset. Default is '\eE(B'. .TP 13 .BI C0 " (str)" Use the string as a conversion table for font '0'. See the 'ac' capability for more details. .TP 13 .BI CS " (str)" Switch cursor-keys to application mode. .TP 13 .BI CE " (str)" Switch cursor-keys back to normal mode. .TP 13 .BI AN " (bool)" Turn on autonuke. See the 'autonuke' command for more details. .TP 13 .BI OL " (num)" Set the output buffer limit. See the 'obuflimit' command for more details. .TP 13 .BI KJ " (str)" Set the encoding of the terminal. See the 'encoding' command for valid encodings. .TP 13 .BI AF " (str)" Change character foreground color in an ANSI conform way. This capability will almost always be set to '\eE[3%dm' ('\eE[3%p1%dm' on terminfo machines). .TP 13 .BI AB " (str)" Same as 'AF', but change background color. .TP 13 .BI AX " (bool)" Does understand ANSI set default fg/bg color (\eE[39m / \eE[49m). .TP 13 .BI XC " (str)" Describe a translation of characters to strings depending on the current font. More details follow in the next section. .TP 13 .BI XT " (bool)" Terminal understands special xterm sequences (OSC, mouse tracking). .TP 13 .BI C8 " (bool)" Terminal needs bold to display high-intensity colors (e.g. Eterm). .TP 13 .BI TF " (bool)" Add missing capabilities to the termcap/info entry. (Set by default). .SH CHARACTER TRANSLATION \fIScreen\fP has a powerful mechanism to translate characters to arbitrary strings depending on the current font and terminal type. Use this feature if you want to work with a common standard character set (say ISO8851-latin1) even on terminals that scatter the more unusual characters over several national language font pages. Syntax: .nf \fBXC=\fP\fI\fP{\fB,,\fP\fI\fP} \fI\fP := \fI